PyHOPE 0.9.0__tar.gz → 0.10.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyhope-0.9.0 → pyhope-0.10.0}/AUTHORS.md +1 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/PKG-INFO +12 -5
- {pyhope-0.9.0 → pyhope-0.10.0}/README.md +9 -1
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/__init__.py +59 -16
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/basis/basis_basis.py +114 -58
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/basis/basis_connect.py +6 -4
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/basis/basis_jacobian.py +19 -10
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/basis/basis_watertight.py +30 -15
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/check/check.py +22 -3
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/check/check_health.py +128 -44
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/check/check_install.py +9 -2
- pyhope-0.10.0/pyhope/check/check_unittest.py +329 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/common/common.py +11 -4
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/common/common_numba.py +1 -1
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/common/common_parallel.py +4 -2
- pyhope-0.10.0/pyhope/common/common_template.py +91 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/common/common_tools.py +19 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/common/common_unique.py +0 -1
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/common/common_vars.py +24 -10
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/config/config.py +7 -1
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/gmsh/gmsh_install.py +17 -8
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/io/formats/meshio.py +21 -14
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/io/formats/vtk.py +9 -2
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/io/io.py +36 -60
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/io/io_debug.py +7 -9
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/io/io_gmsh.py +0 -2
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/io/io_xdmf.py +1 -1
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/connect/connect.py +65 -45
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/connect/connect_mortar.py +168 -43
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/connect/connect_rbtree.py +47 -48
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/elements/elements_shapefunctions.py +8 -1
- pyhope-0.10.0/pyhope/mesh/extrude/mesh_extrude.py +490 -0
- pyhope-0.10.0/pyhope/mesh/extrude/templates/linear.py +65 -0
- pyhope-0.10.0/pyhope/mesh/fem/fem.py +508 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/mesh.py +34 -16
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/mesh_builtin.py +27 -24
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/mesh_common.py +185 -140
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/mesh_duplicates.py +23 -16
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/mesh_external.py +16 -10
- pyhope-0.10.0/pyhope/mesh/mesh_mortar.py +218 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/mesh_orient.py +12 -4
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/mesh_sort.py +7 -4
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/mesh_vars.py +21 -12
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/reader/reader_gambit.py +1 -21
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/reader/reader_gmsh.py +150 -35
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/reader/reader_hopr.py +4 -23
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/sort/sort_hilbert.py +4 -4
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/topology/mesh_serendipity.py +4 -0
- pyhope-0.10.0/pyhope/mesh/topology/mesh_splittohex.py +654 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/topology/mesh_topology.py +113 -57
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/transform/mesh_transform.py +47 -68
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/transform/templates/convtest.py +8 -1
- pyhope-0.10.0/pyhope/mesh/transform/templates/cylinder.py +151 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/transform/templates/default.py +8 -2
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/transform/templates/phill.py +17 -10
- pyhope-0.10.0/pyhope/mesh/transform/templates/sine.py +105 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/transform/templates/sphere.py +62 -22
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/transform/templates/sphere_box.py +24 -16
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/meshio/meshio_convert.py +13 -6
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/meshio/meshio_ordering.py +15 -5
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/output/output.py +4 -2
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/readintools/commandline.py +7 -4
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/readintools/readintools.py +26 -6
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/script/pyhope_cli.py +12 -10
- {pyhope-0.9.0 → pyhope-0.10.0}/pyproject.toml +32 -13
- pyhope-0.9.0/pyhope/basis/__init__.py +0 -0
- pyhope-0.9.0/pyhope/check/__init__.py +0 -0
- pyhope-0.9.0/pyhope/common/__init__.py +0 -0
- pyhope-0.9.0/pyhope/config/__init__.py +0 -0
- pyhope-0.9.0/pyhope/io/__init__.py +0 -0
- pyhope-0.9.0/pyhope/mesh/__init__.py +0 -0
- pyhope-0.9.0/pyhope/mesh/fem/fem.py +0 -450
- pyhope-0.9.0/pyhope/mesh/topology/mesh_splittohex.py +0 -412
- pyhope-0.9.0/pyhope/mesh/transform/templates/cylinder.py +0 -115
- pyhope-0.9.0/pyhope/output/__init__.py +0 -0
- pyhope-0.9.0/pyhope/readintools/__init__.py +0 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/LICENSE.md +0 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/__main__.py +0 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/common/common_progress.py +0 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/gmsh/gmsh_override.py +0 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/io/formats/cgns.py +0 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/io/formats/gmsh.py +1 -1
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/io/io_vars.py +0 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/elements/elements_ordering.py +0 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/mesh/mesh_sides.py +0 -0
- {pyhope-0.9.0 → pyhope-0.10.0}/pyhope/meshio/meshio_nodes.py +0 -0
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyHOPE
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: Python High-Order Preprocessing Environment
|
|
5
|
-
License: GPL-3.0-only
|
|
5
|
+
License-Expression: GPL-3.0-only
|
|
6
6
|
License-File: AUTHORS.md
|
|
7
7
|
License-File: LICENSE.md
|
|
8
8
|
Keywords: PyHOPE,mesh generator
|
|
9
9
|
Author: Numerics Research Group (NRG)
|
|
10
10
|
Author-email: numerics@iag.uni-stuttgart.de
|
|
11
11
|
Requires-Python: >=3.10
|
|
12
|
-
Classifier: Development Status ::
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
13
|
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
15
14
|
Classifier: Programming Language :: Python :: 3
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -35,6 +34,12 @@ Project-URL: Homepage, https://numericsresearchgroup.org
|
|
|
35
34
|
Project-URL: Repository, https://github.com/hopr-framework/pyhope
|
|
36
35
|
Description-Content-Type: text/markdown
|
|
37
36
|
|
|
37
|
+
[](https://github.com/hopr-framework/PyHOPE/actions/workflows/ci.yml)
|
|
38
|
+
[](https://github.com/hopr-framework/PyHOPE/actions/workflows/github-pages.yml)
|
|
39
|
+
[](https://joss.theoj.org/papers/39eb3be78f37c78588fe6dc443785024)
|
|
40
|
+
[](https://www.bestpractices.dev/projects/12060)
|
|
41
|
+
[](https://www.bestpractices.dev/projects/12060)
|
|
42
|
+
|
|
38
43
|
PyHOPE (Python High-Order Preprocessing Environment) is an open-source Python framework for the generation of three-dimensional unstructured high-order meshes. These meshes are needed by high-order numerical methods like Discontinuous Galerkin, Spectral Element Methods, or pFEM, in order to retain their accuracy if the computational domain includes curved boundaries.
|
|
39
44
|
|
|
40
45
|
PyHOPE has been developed by the Numerics Research Group (NRG) lead by Prof. Andrea Beck at the Institute of Aerodynamics and Gas Dynamics at the University of Stuttgart, Germany.
|
|
@@ -73,6 +78,7 @@ PyHOPE features internal health checks to verify that everything works as expect
|
|
|
73
78
|
pyhope --verify [tutorials] # Run all health checks
|
|
74
79
|
pyhope --verify-health # Run Python health checks
|
|
75
80
|
pyhope --verify-install [tutorials] # Run PyHOPE mesh generation checks
|
|
81
|
+
pyhope --verify-unittest # Run PyHOPE unit tests
|
|
76
82
|
```
|
|
77
83
|
|
|
78
84
|
> [!NOTE]
|
|
@@ -169,6 +175,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
169
175
|
├────
|
|
170
176
|
│ doPeriodicCorrect │ False │ DEFAULT │
|
|
171
177
|
│ doMortars │ True │ DEFAULT │
|
|
178
|
+
│ Processing Sides |█████████████████████████████████| 3072/3072 [100%] in 0.0s (24000.00/s)
|
|
172
179
|
├────
|
|
173
180
|
│ Number of sides : 3072
|
|
174
181
|
│ Number of inner sides : 2688
|
|
@@ -219,7 +226,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
219
226
|
```
|
|
220
227
|
|
|
221
228
|
## Python Library Usage
|
|
222
|
-
PyHOPE can be included in other Python libraries. PyHOPE exposes its functionally via runtime contexts defined by [Context Managers](https://docs.python.org/3/library/stdtypes.html#typecontextmanager). The following Python code loads a HOPR HDF5 mesh and derived quantities. For a complete list of currently implemented functions, see the [
|
|
229
|
+
PyHOPE can be included in other Python libraries. PyHOPE exposes its functionally via runtime contexts defined by [Context Managers](https://docs.python.org/3/library/stdtypes.html#typecontextmanager). The following Python code loads a HOPR HDF5 mesh and derived quantities. For a complete list of currently implemented functions, see the [PyHOPE documentation](https://hopr-framework.github.io/PyHOPE/user-guide/library_usage).
|
|
223
230
|
```python
|
|
224
231
|
from pyhope import Basis, Mesh
|
|
225
232
|
with Mesh('1-01-cartbox_mesh.h5') as m:
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
[](https://github.com/hopr-framework/PyHOPE/actions/workflows/ci.yml)
|
|
2
|
+
[](https://github.com/hopr-framework/PyHOPE/actions/workflows/github-pages.yml)
|
|
3
|
+
[](https://joss.theoj.org/papers/39eb3be78f37c78588fe6dc443785024)
|
|
4
|
+
[](https://www.bestpractices.dev/projects/12060)
|
|
5
|
+
[](https://www.bestpractices.dev/projects/12060)
|
|
6
|
+
|
|
1
7
|
PyHOPE (Python High-Order Preprocessing Environment) is an open-source Python framework for the generation of three-dimensional unstructured high-order meshes. These meshes are needed by high-order numerical methods like Discontinuous Galerkin, Spectral Element Methods, or pFEM, in order to retain their accuracy if the computational domain includes curved boundaries.
|
|
2
8
|
|
|
3
9
|
PyHOPE has been developed by the Numerics Research Group (NRG) lead by Prof. Andrea Beck at the Institute of Aerodynamics and Gas Dynamics at the University of Stuttgart, Germany.
|
|
@@ -36,6 +42,7 @@ PyHOPE features internal health checks to verify that everything works as expect
|
|
|
36
42
|
pyhope --verify [tutorials] # Run all health checks
|
|
37
43
|
pyhope --verify-health # Run Python health checks
|
|
38
44
|
pyhope --verify-install [tutorials] # Run PyHOPE mesh generation checks
|
|
45
|
+
pyhope --verify-unittest # Run PyHOPE unit tests
|
|
39
46
|
```
|
|
40
47
|
|
|
41
48
|
> [!NOTE]
|
|
@@ -132,6 +139,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
132
139
|
├────
|
|
133
140
|
│ doPeriodicCorrect │ False │ DEFAULT │
|
|
134
141
|
│ doMortars │ True │ DEFAULT │
|
|
142
|
+
│ Processing Sides |█████████████████████████████████| 3072/3072 [100%] in 0.0s (24000.00/s)
|
|
135
143
|
├────
|
|
136
144
|
│ Number of sides : 3072
|
|
137
145
|
│ Number of inner sides : 2688
|
|
@@ -182,7 +190,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
182
190
|
```
|
|
183
191
|
|
|
184
192
|
## Python Library Usage
|
|
185
|
-
PyHOPE can be included in other Python libraries. PyHOPE exposes its functionally via runtime contexts defined by [Context Managers](https://docs.python.org/3/library/stdtypes.html#typecontextmanager). The following Python code loads a HOPR HDF5 mesh and derived quantities. For a complete list of currently implemented functions, see the [
|
|
193
|
+
PyHOPE can be included in other Python libraries. PyHOPE exposes its functionally via runtime contexts defined by [Context Managers](https://docs.python.org/3/library/stdtypes.html#typecontextmanager). The following Python code loads a HOPR HDF5 mesh and derived quantities. For a complete list of currently implemented functions, see the [PyHOPE documentation](https://hopr-framework.github.io/PyHOPE/user-guide/library_usage).
|
|
186
194
|
```python
|
|
187
195
|
from pyhope import Basis, Mesh
|
|
188
196
|
with Mesh('1-01-cartbox_mesh.h5') as m:
|
|
@@ -28,32 +28,72 @@
|
|
|
28
28
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
29
29
|
from collections import namedtuple
|
|
30
30
|
from contextlib import contextmanager
|
|
31
|
+
from functools import update_wrapper
|
|
32
|
+
from typing import final
|
|
31
33
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
32
34
|
# Third-party libraries
|
|
33
35
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
34
36
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
35
37
|
# Local imports
|
|
36
38
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
37
|
-
from pyhope.basis.basis_basis import legendre_gauss_nodes, legendre_gauss_lobatto_nodes
|
|
38
|
-
from pyhope.basis.basis_basis import barycentric_weights, polynomial_derivative_matrix
|
|
39
|
-
from pyhope.basis.basis_basis import lagrange_interpolation_polys, calc_vandermonde
|
|
40
|
-
from pyhope.basis.basis_basis import change_basis_3D, change_basis_2D
|
|
41
|
-
from pyhope.basis.basis_basis import evaluate_jacobian
|
|
42
39
|
# ==================================================================================================================================
|
|
43
40
|
|
|
44
41
|
|
|
42
|
+
def _staticwrapper(func):
|
|
43
|
+
""" Custom helper to lift the (annotations, doc, etc.) to the staticmethod
|
|
44
|
+
"""
|
|
45
|
+
# Create a wrapper that carries the metadata
|
|
46
|
+
def wrapper(*args, **kwargs):
|
|
47
|
+
return func(*args, **kwargs)
|
|
48
|
+
|
|
49
|
+
# Lift metadata (annotations, doc, etc.) to the wrapper
|
|
50
|
+
update_wrapper(wrapper, func)
|
|
51
|
+
|
|
52
|
+
# Convert the metadata-rich wrapper into a staticmethod
|
|
53
|
+
return staticmethod(wrapper)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@final
|
|
45
57
|
class Basis:
|
|
46
58
|
""" Basis class to hold all basis related functions and variables
|
|
47
59
|
"""
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
change_basis_3D
|
|
55
|
-
|
|
56
|
-
evaluate_jacobian
|
|
60
|
+
# Local imports ----------------------------------------
|
|
61
|
+
from pyhope.basis.basis_basis import legendre_gauss_nodes, legendre_gauss_lobatto_nodes
|
|
62
|
+
from pyhope.basis.basis_basis import barycentric_weights
|
|
63
|
+
from pyhope.basis.basis_basis import polynomial_derivative_matrix, polynomial_derivative_matrix_prism
|
|
64
|
+
from pyhope.basis.basis_basis import polynomial_derivative_matrix_pyram, polynomial_derivative_matrix_tetra
|
|
65
|
+
from pyhope.basis.basis_basis import lagrange_interpolation_polys, calc_vandermonde
|
|
66
|
+
from pyhope.basis.basis_basis import change_basis_3D, change_basis_2D, change_basis_1D
|
|
67
|
+
from pyhope.basis.basis_basis import equi_nodes_prism, equi_nodes_pyram, equi_nodes_tetra
|
|
68
|
+
from pyhope.basis.basis_basis import evaluate_jacobian, evaluate_jacobian_simplex
|
|
69
|
+
# ------------------------------------------------------
|
|
70
|
+
legendre_gauss_nodes = _staticwrapper(legendre_gauss_nodes)
|
|
71
|
+
legendre_gauss_lobatto_nodes = _staticwrapper(legendre_gauss_lobatto_nodes)
|
|
72
|
+
barycentric_weights = _staticwrapper(barycentric_weights)
|
|
73
|
+
polynomial_derivative_matrix = _staticwrapper(polynomial_derivative_matrix)
|
|
74
|
+
polynomial_derivative_matrix_prism = _staticwrapper(polynomial_derivative_matrix_prism)
|
|
75
|
+
polynomial_derivative_matrix_pyram = _staticwrapper(polynomial_derivative_matrix_pyram)
|
|
76
|
+
polynomial_derivative_matrix_tetra = _staticwrapper(polynomial_derivative_matrix_tetra)
|
|
77
|
+
lagrange_interpolation_polys = _staticwrapper(lagrange_interpolation_polys)
|
|
78
|
+
calc_vandermonde = _staticwrapper(calc_vandermonde)
|
|
79
|
+
change_basis_3D = _staticwrapper(change_basis_3D)
|
|
80
|
+
change_basis_2D = _staticwrapper(change_basis_2D)
|
|
81
|
+
change_basis_1D = _staticwrapper(change_basis_1D)
|
|
82
|
+
equi_nodes_prism = _staticwrapper(equi_nodes_prism)
|
|
83
|
+
equi_nodes_pyram = _staticwrapper(equi_nodes_pyram)
|
|
84
|
+
equi_nodes_tetra = _staticwrapper(equi_nodes_tetra)
|
|
85
|
+
evaluate_jacobian = _staticwrapper(evaluate_jacobian)
|
|
86
|
+
evaluate_jacobian_simplex = _staticwrapper(evaluate_jacobian_simplex)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@final
|
|
90
|
+
class Mapping:
|
|
91
|
+
""" Mapping class to hold all mapping related functions and variables
|
|
92
|
+
"""
|
|
93
|
+
# Local imports ----------------------------------------
|
|
94
|
+
from pyhope.mesh.mesh_common import LINMAP
|
|
95
|
+
# ------------------------------------------------------
|
|
96
|
+
mesh_format_to_tensor_product = _staticwrapper(LINMAP)
|
|
57
97
|
|
|
58
98
|
|
|
59
99
|
# Define a named tuple to hold the mesh data
|
|
@@ -61,12 +101,13 @@ MeshContainer = namedtuple('Mesh',
|
|
|
61
101
|
['mesh', # The generated mesh object
|
|
62
102
|
'nGeo', # Polynomial order
|
|
63
103
|
'bcs', # Boundary conditions
|
|
104
|
+
'vvs', # Periodic vectors
|
|
64
105
|
'elems', # Elements
|
|
65
106
|
'sides' # Sides
|
|
66
107
|
])
|
|
67
108
|
|
|
68
109
|
|
|
69
|
-
@contextmanager
|
|
110
|
+
@contextmanager
|
|
70
111
|
def Mesh(*args: str, stdout: bool = False, stderr: bool = True):
|
|
71
112
|
""" Mesh context manager to generate a mesh from a given file
|
|
72
113
|
|
|
@@ -139,10 +180,11 @@ def Mesh(*args: str, stdout: bool = False, stderr: bool = True):
|
|
|
139
180
|
ConnectMesh()
|
|
140
181
|
|
|
141
182
|
# Export mesh variables
|
|
142
|
-
mesh
|
|
183
|
+
mesh = mesh_vars.mesh
|
|
143
184
|
|
|
144
185
|
nGeo = mesh_vars.nGeo
|
|
145
186
|
bcs = mesh_vars.bcs
|
|
187
|
+
vvs = mesh_vars.vvs
|
|
146
188
|
|
|
147
189
|
elems = mesh_vars.elems
|
|
148
190
|
sides = mesh_vars.sides
|
|
@@ -150,6 +192,7 @@ def Mesh(*args: str, stdout: bool = False, stderr: bool = True):
|
|
|
150
192
|
yield MeshContainer(mesh = mesh, # noqa: E251
|
|
151
193
|
nGeo = nGeo, # noqa: E251
|
|
152
194
|
bcs = bcs, # noqa: E251
|
|
195
|
+
vvs = vvs, # noqa: E251
|
|
153
196
|
elems = elems, # noqa: E251
|
|
154
197
|
sides = sides # noqa: E251
|
|
155
198
|
)
|
|
@@ -25,8 +25,9 @@
|
|
|
25
25
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
26
26
|
# Standard libraries
|
|
27
27
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
28
|
+
from __future__ import annotations
|
|
28
29
|
from functools import cache
|
|
29
|
-
from typing import
|
|
30
|
+
from typing import Any, Final
|
|
30
31
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
31
32
|
# Third-party libraries
|
|
32
33
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
@@ -34,31 +35,38 @@ import numpy as np
|
|
|
34
35
|
import scipy as sp
|
|
35
36
|
# from threadpoolctl import ThreadpoolController
|
|
36
37
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
37
|
-
#
|
|
38
|
+
# Typing libraries
|
|
38
39
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
40
|
+
import typing
|
|
39
41
|
from pyhope.common.common_numba import NUMBA_AVAILABLE
|
|
42
|
+
if typing.TYPE_CHECKING or NUMBA_AVAILABLE:
|
|
43
|
+
import numpy.typing as npt
|
|
44
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
45
|
+
# Local imports
|
|
46
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
40
47
|
from pyhope.common.common_numba import jit, types
|
|
41
48
|
from pyhope.mesh.mesh_common import NDOFS_ELEM
|
|
42
49
|
# ==================================================================================================================================
|
|
43
50
|
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
@jit(types.Tuple((types.float64[:], types.float64[:]))(types.int64), nopython=True, cache=True, nogil=True)
|
|
53
|
+
def legendre_gauss_lobatto_nodes(order: int) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
|
|
46
54
|
""" Return Legendre-Gauss-Lobatto nodes and weights for a given order in 1D
|
|
47
55
|
"""
|
|
48
56
|
order -= 1
|
|
49
57
|
# Special cases for small N
|
|
50
58
|
if order == 1:
|
|
51
|
-
return np.array((-1, 1)), np.array((1, 1))
|
|
59
|
+
return np.array((-1, 1), dtype=np.float64), np.array((1, 1), dtype=np.float64)
|
|
52
60
|
|
|
53
61
|
# Compute the initial guess for the LGL nodes (roots of P'_N)
|
|
54
62
|
nodes = np.cos(np.pi * np.arange(order+1) / order)
|
|
55
63
|
|
|
56
64
|
# Initialize the Legendre polynomial and its derivative
|
|
57
|
-
p = np.zeros((order+1, order+1))
|
|
65
|
+
p = np.zeros((order+1, order+1), dtype=np.float64)
|
|
58
66
|
|
|
59
67
|
# Iteratively solve for the LGL nodes using Newton's method
|
|
60
68
|
xOld = 2 * np.ones_like(nodes)
|
|
61
|
-
tol
|
|
69
|
+
tol = 1e-14
|
|
62
70
|
while np.max(np.abs(nodes - xOld)) > tol:
|
|
63
71
|
xOld = nodes.copy()
|
|
64
72
|
p[:, 0] = 1
|
|
@@ -76,7 +84,8 @@ def legendre_gauss_lobatto_nodes(order: int) -> tuple[np.ndarray, np.ndarray]:
|
|
|
76
84
|
return nodes, weights
|
|
77
85
|
|
|
78
86
|
|
|
79
|
-
|
|
87
|
+
@cache
|
|
88
|
+
def legendre_gauss_nodes(order: int) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
|
|
80
89
|
""" Return Legendre-Gauss nodes and weights for a given order in 1D
|
|
81
90
|
"""
|
|
82
91
|
nodes, weights = np.polynomial.legendre.leggauss(order)
|
|
@@ -84,7 +93,7 @@ def legendre_gauss_nodes(order: int) -> tuple[np.ndarray, np.ndarray]:
|
|
|
84
93
|
|
|
85
94
|
|
|
86
95
|
@cache
|
|
87
|
-
def equi_nodes_prism(order: int) -> np.
|
|
96
|
+
def equi_nodes_prism(order: int) -> npt.NDArray[np.float64]:
|
|
88
97
|
""" Return equidistant nodes on a wedge/prism
|
|
89
98
|
"""
|
|
90
99
|
xEq = np.linspace(-1, 1, num=order, dtype=np.float64)
|
|
@@ -94,7 +103,7 @@ def equi_nodes_prism(order: int) -> np.ndarray:
|
|
|
94
103
|
|
|
95
104
|
|
|
96
105
|
@cache
|
|
97
|
-
def equi_nodes_pyram(order: int) -> np.
|
|
106
|
+
def equi_nodes_pyram(order: int) -> npt.NDArray[np.float64]:
|
|
98
107
|
""" Return equidistant nodes on a pyramid
|
|
99
108
|
"""
|
|
100
109
|
xEq = np.linspace(-1, 1, num=order, dtype=np.float64)
|
|
@@ -104,7 +113,7 @@ def equi_nodes_pyram(order: int) -> np.ndarray:
|
|
|
104
113
|
|
|
105
114
|
|
|
106
115
|
@cache
|
|
107
|
-
def equi_nodes_tetra(order: int) -> np.
|
|
116
|
+
def equi_nodes_tetra(order: int) -> npt.NDArray[np.float64]:
|
|
108
117
|
""" Return equidistant nodes on a tetrahedron
|
|
109
118
|
"""
|
|
110
119
|
xEq = np.linspace(-1, 1, num=order, dtype=np.float64)
|
|
@@ -113,26 +122,49 @@ def equi_nodes_tetra(order: int) -> np.ndarray:
|
|
|
113
122
|
return np.vstack((xEq[iXI[mask]], xEq[iETA[mask]], xEq[iZETA[mask]]))
|
|
114
123
|
|
|
115
124
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
if not NUMBA_AVAILABLE:
|
|
126
|
+
def barycentric_weights(_: int, xGP: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
127
|
+
""" Compute the barycentric weights for a given node set
|
|
128
|
+
> Algorithm 30, Kopriva
|
|
129
|
+
"""
|
|
130
|
+
# Create a difference matrix (x_i - x_j) for all i, j
|
|
131
|
+
diff_matrix = xGP[:, np.newaxis] - xGP[np.newaxis, :]
|
|
122
132
|
|
|
123
|
-
|
|
124
|
-
|
|
133
|
+
# Set the diagonal to 1 to avoid division by zero (diagonal elements will not be used)
|
|
134
|
+
np.fill_diagonal(diff_matrix, 1.0)
|
|
125
135
|
|
|
126
|
-
|
|
127
|
-
|
|
136
|
+
# Compute the product of all differences for each row (excluding the diagonal)
|
|
137
|
+
wBary = np.prod(diff_matrix, axis=1)
|
|
128
138
|
|
|
129
|
-
|
|
130
|
-
|
|
139
|
+
# Take the reciprocal to get the final barycentric weights
|
|
140
|
+
# wBary = 1.0 / wBary
|
|
131
141
|
|
|
132
|
-
|
|
142
|
+
return 1.0 / wBary
|
|
143
|
+
else:
|
|
144
|
+
@jit(types.float64[:](types.int64, types.float64[:]), nopython=True, cache=True, nogil=True)
|
|
145
|
+
def barycentric_weights(_, xGP):
|
|
146
|
+
""" Compute the barycentric weights for a given node set
|
|
147
|
+
> Algorithm 30, Kopriva
|
|
148
|
+
"""
|
|
149
|
+
n = xGP.shape[0]
|
|
150
|
+
w_bary = np.ones(n, dtype=np.float64)
|
|
151
|
+
|
|
152
|
+
# Create a difference matrix (x_i - x_j) for all i, j
|
|
153
|
+
for i in range(n):
|
|
154
|
+
# Set the diagonal to 1 to avoid division by zero (diagonal elements will not be used)
|
|
155
|
+
p = 1.0
|
|
156
|
+
|
|
157
|
+
# Compute the product of all differences for each row (excluding the diagonal)
|
|
158
|
+
for j in range(n):
|
|
159
|
+
if i != j:
|
|
160
|
+
p *= (xGP[i] - xGP[j])
|
|
161
|
+
w_bary[i] = p
|
|
133
162
|
|
|
163
|
+
# Take the reciprocal to get the final barycentric weights
|
|
164
|
+
return 1.0 / w_bary
|
|
134
165
|
|
|
135
|
-
|
|
166
|
+
|
|
167
|
+
def polynomial_derivative_matrix(order: int, xGP: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
136
168
|
""" Compute the polynomial derivative matrix for a given node set
|
|
137
169
|
> Algorithm 37, Kopriva
|
|
138
170
|
"""
|
|
@@ -148,12 +180,17 @@ def polynomial_derivative_matrix(order: int, xGP: np.ndarray) -> np.ndarray:
|
|
|
148
180
|
return D
|
|
149
181
|
|
|
150
182
|
|
|
151
|
-
|
|
183
|
+
@jit(types.float64[:](types.float64, types.int64, types.float64[:], types.float64[:]),
|
|
184
|
+
nopython=True, cache=True, nogil=True)
|
|
185
|
+
def lagrange_interpolation_polys(x: float,
|
|
186
|
+
order: int,
|
|
187
|
+
xGP: npt.NDArray[np.float64],
|
|
188
|
+
wBary: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
152
189
|
""" Computes all Lagrange functions evaluated at position x in [-1;1]
|
|
153
190
|
> Algorithm 34, Kopriva
|
|
154
191
|
"""
|
|
155
192
|
# Equal points need special treatment
|
|
156
|
-
lagrange = np.zeros(order)
|
|
193
|
+
lagrange = np.zeros(order, dtype=np.float64)
|
|
157
194
|
for iGP in range(order):
|
|
158
195
|
if abs(x - xGP[iGP]) < 1.E-14:
|
|
159
196
|
lagrange[iGP] = 1
|
|
@@ -170,11 +207,17 @@ def lagrange_interpolation_polys(x: Union[float, np.ndarray], order: int, xGP: n
|
|
|
170
207
|
return lagrange/tmp
|
|
171
208
|
|
|
172
209
|
|
|
173
|
-
|
|
210
|
+
@jit(types.float64[:, :](types.int64, types.int64, types.float64[:], types.float64[:], types.float64[:]),
|
|
211
|
+
nopython=True, cache=True, nogil=True)
|
|
212
|
+
def calc_vandermonde(n_In: int,
|
|
213
|
+
n_Out: int,
|
|
214
|
+
wBary_In: npt.NDArray[np.float64],
|
|
215
|
+
xi_In: npt.NDArray[np.float64],
|
|
216
|
+
xi_Out: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
174
217
|
""" Build a 1D Vandermonde matrix using the Lagrange basis functions of degree N_In,
|
|
175
218
|
evaluated at the interpolation points xi_Out
|
|
176
219
|
"""
|
|
177
|
-
Vdm = np.zeros((n_Out, n_In))
|
|
220
|
+
Vdm = np.zeros((n_Out, n_In), dtype=np.float64)
|
|
178
221
|
for iXI in range(n_Out):
|
|
179
222
|
Vdm[iXI, :] = lagrange_interpolation_polys(xi_Out[iXI], n_In, xi_In, wBary_In)
|
|
180
223
|
return Vdm
|
|
@@ -254,7 +297,7 @@ def calc_vandermonde(n_In: int, n_Out: int, wBary_In: np.ndarray, xi_In: np.ndar
|
|
|
254
297
|
# return Vdm
|
|
255
298
|
|
|
256
299
|
|
|
257
|
-
def polynomial_derivative_matrix_prism(order: int, xGP: np.
|
|
300
|
+
def polynomial_derivative_matrix_prism(order: int, xGP: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
258
301
|
""" Compute the polynomial derivative matrix for a prism
|
|
259
302
|
"""
|
|
260
303
|
a: Final[np.ndarray] = xGP[0, :]
|
|
@@ -262,19 +305,19 @@ def polynomial_derivative_matrix_prism(order: int, xGP: np.ndarray) -> np.ndarra
|
|
|
262
305
|
c: Final[np.ndarray] = xGP[2, :]
|
|
263
306
|
|
|
264
307
|
nDOFs = NDOFS_ELEM(106, order-1)
|
|
265
|
-
Vdm = np.zeros(( nDOFs, nDOFs))
|
|
266
|
-
Vr = np.zeros(( nDOFs, nDOFs))
|
|
267
|
-
Vs = np.zeros(( nDOFs, nDOFs))
|
|
268
|
-
Vt = np.zeros(( nDOFs, nDOFs))
|
|
269
|
-
D = np.zeros((3, nDOFs, nDOFs))
|
|
308
|
+
Vdm = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
309
|
+
Vr = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
310
|
+
Vs = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
311
|
+
Vt = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
312
|
+
D = np.zeros((3, nDOFs, nDOFs), dtype=np.float64)
|
|
270
313
|
|
|
271
314
|
# Precompute required Jacobi polynomials and derivatives
|
|
272
315
|
# fZETA(i) = P_i^(0,0)(c), dfZETA(i) = 0.5*(i+1)*P_{i-1}^{(1,1)}(c)
|
|
273
|
-
fZETA_all = np.array(
|
|
274
|
-
dfZETA_all = np.array(
|
|
275
|
-
# fETA(j) = P_j^(0,0)(
|
|
276
|
-
fETA_all = np.array(
|
|
277
|
-
dfETA_all = np.array(
|
|
316
|
+
fZETA_all = np.array(tuple( sp.special.eval_jacobi(i , 0, 0, c) for i in range(order)))
|
|
317
|
+
dfZETA_all = np.array(tuple(0.5*(i+1)*sp.special.eval_jacobi(i-1, 1, 1, c) for i in range(order)))
|
|
318
|
+
# fETA(j) = P_j^(0,0)(tuple(), dfETA(j) = 0.5*(j+1)*P_{j-1}^{(1,1)}(b)
|
|
319
|
+
fETA_all = np.array(tuple( sp.special.eval_jacobi(j , 0, 0, b) for j in range(order)))
|
|
320
|
+
dfETA_all = np.array(tuple(0.5*(j+1)*sp.special.eval_jacobi(j-1, 1, 1, b) for j in range(order)))
|
|
278
321
|
|
|
279
322
|
jacobi_xi_polys = [[sp.special.jacobi(i, 2*j + 1, 0) for i in range(order - j)] for j in range(order)]
|
|
280
323
|
jacobi_xi_derivs = [[p.deriv() for p in row] for row in jacobi_xi_polys]
|
|
@@ -347,7 +390,7 @@ def polynomial_derivative_matrix_prism(order: int, xGP: np.ndarray) -> np.ndarra
|
|
|
347
390
|
return D
|
|
348
391
|
|
|
349
392
|
|
|
350
|
-
def polynomial_derivative_matrix_pyram(order: int, xGP: np.
|
|
393
|
+
def polynomial_derivative_matrix_pyram(order: int, xGP: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
351
394
|
""" Compute the polynomial derivative matrix for a pyramid
|
|
352
395
|
"""
|
|
353
396
|
a = np.where((1 - xGP[2, :]) <= 1.e-12, -1.0, 2 * (1 + xGP[0, :]) / (1. - xGP[2, :] + 1.e-20) - 1.)
|
|
@@ -355,11 +398,11 @@ def polynomial_derivative_matrix_pyram(order: int, xGP: np.ndarray) -> np.ndarra
|
|
|
355
398
|
c = xGP[2, :]
|
|
356
399
|
|
|
357
400
|
nDOFs = NDOFS_ELEM(105, order-1)
|
|
358
|
-
Vdm = np.zeros(( nDOFs, nDOFs))
|
|
359
|
-
Vr = np.zeros(( nDOFs, nDOFs))
|
|
360
|
-
Vs = np.zeros(( nDOFs, nDOFs))
|
|
361
|
-
Vt = np.zeros(( nDOFs, nDOFs))
|
|
362
|
-
D = np.zeros((3, nDOFs, nDOFs))
|
|
401
|
+
Vdm = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
402
|
+
Vr = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
403
|
+
Vs = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
404
|
+
Vt = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
405
|
+
D = np.zeros((3, nDOFs, nDOFs), dtype=np.float64)
|
|
363
406
|
|
|
364
407
|
iX = 0
|
|
365
408
|
for iZETA in range(order):
|
|
@@ -421,7 +464,7 @@ def polynomial_derivative_matrix_pyram(order: int, xGP: np.ndarray) -> np.ndarra
|
|
|
421
464
|
return D
|
|
422
465
|
|
|
423
466
|
|
|
424
|
-
def polynomial_derivative_matrix_tetra(order: int, xGP: np.
|
|
467
|
+
def polynomial_derivative_matrix_tetra(order: int, xGP: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
425
468
|
""" Compute the polynomial derivative matrix for a tetra
|
|
426
469
|
"""
|
|
427
470
|
a = np.where(np.abs(xGP[1, :] + xGP[2, :]) <= 1.e-12, -1.0, 2 * (1 + xGP[0, :]) / (- xGP[1, :] - xGP[2, :] + 1.e-20) - 1.)
|
|
@@ -429,11 +472,11 @@ def polynomial_derivative_matrix_tetra(order: int, xGP: np.ndarray) -> np.ndarra
|
|
|
429
472
|
c = xGP[2, :]
|
|
430
473
|
|
|
431
474
|
nDOFs = NDOFS_ELEM(104, order-1)
|
|
432
|
-
Vdm = np.zeros(( nDOFs, nDOFs))
|
|
433
|
-
Vr = np.zeros(( nDOFs, nDOFs))
|
|
434
|
-
Vs = np.zeros(( nDOFs, nDOFs))
|
|
435
|
-
Vt = np.zeros(( nDOFs, nDOFs))
|
|
436
|
-
D = np.zeros((3, nDOFs, nDOFs))
|
|
475
|
+
Vdm = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
476
|
+
Vr = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
477
|
+
Vs = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
478
|
+
Vt = np.zeros(( nDOFs, nDOFs), dtype=np.float64)
|
|
479
|
+
D = np.zeros((3, nDOFs, nDOFs), dtype=np.float64)
|
|
437
480
|
|
|
438
481
|
# Precompute constants
|
|
439
482
|
sqrt2 = np.sqrt(2.)
|
|
@@ -504,7 +547,7 @@ def polynomial_derivative_matrix_tetra(order: int, xGP: np.ndarray) -> np.ndarra
|
|
|
504
547
|
|
|
505
548
|
|
|
506
549
|
if not NUMBA_AVAILABLE:
|
|
507
|
-
def change_basis_3D(Vdm: np.
|
|
550
|
+
def change_basis_3D(Vdm: npt.NDArray[np.float64], x3D_In: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
508
551
|
""" Interpolate a 3D tensor product Lagrange basis defined by (N_in+1) 1D interpolation point positions xi_In(0:N_In)
|
|
509
552
|
to another 3D tensor product node positions (number of nodes N_out+1)
|
|
510
553
|
defined by (N_out+1) interpolation point positions xi_Out(0:N_Out)
|
|
@@ -533,7 +576,7 @@ if not NUMBA_AVAILABLE:
|
|
|
533
576
|
|
|
534
577
|
else:
|
|
535
578
|
@jit((types.float64[:, :, :, ::1])(types.float64[:, ::1], types.float64[:, :, :, :]), nopython=True, cache=True, nogil=True)
|
|
536
|
-
def change_basis_3D(Vdm: np.
|
|
579
|
+
def change_basis_3D(Vdm: npt.NDArray[np.float64], x3D_In: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
537
580
|
""" Interpolate a 3D tensor product Lagrange basis defined by (N_in+1) 1D interpolation point positions xi_In(0:N_In)
|
|
538
581
|
to another 3D tensor product node positions (number of nodes N_out+1)
|
|
539
582
|
defined by (N_out+1) interpolation point positions xi_Out(0:N_Out)
|
|
@@ -561,7 +604,7 @@ else:
|
|
|
561
604
|
|
|
562
605
|
|
|
563
606
|
if not NUMBA_AVAILABLE:
|
|
564
|
-
def change_basis_2D(Vdm: np.
|
|
607
|
+
def change_basis_2D(Vdm: npt.NDArray[np.float64], x2D_In: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
565
608
|
""" Interpolate a 2D tensor product Lagrange basis defined by (N_in+1) 1D interpolation point positions xi_In(0:N_In)
|
|
566
609
|
to another 2D tensor product node positions (number of nodes N_out+1)
|
|
567
610
|
defined by (N_out+1) interpolation point positions xi_Out(0:N_Out)
|
|
@@ -584,7 +627,7 @@ if not NUMBA_AVAILABLE:
|
|
|
584
627
|
|
|
585
628
|
else:
|
|
586
629
|
@jit((types.float64[:, :, ::1])(types.float64[:, ::1], types.float64[:, :, :]), nopython=True, cache=True, nogil=True)
|
|
587
|
-
def change_basis_2D(Vdm: np.
|
|
630
|
+
def change_basis_2D(Vdm: npt.NDArray[np.float64], x2D_In: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
588
631
|
""" Interpolate a 2D tensor product Lagrange basis defined by (N_in+1) 1D interpolation point positions xi_In(0:N_In)
|
|
589
632
|
to another 2D tensor product node positions (number of nodes N_out+1)
|
|
590
633
|
defined by (N_out+1) interpolation point positions xi_Out(0:N_Out)
|
|
@@ -607,7 +650,18 @@ else:
|
|
|
607
650
|
return x2D_Out.reshape(dim1, n_Out, n_Out)
|
|
608
651
|
|
|
609
652
|
|
|
610
|
-
def
|
|
653
|
+
def change_basis_1D(Vdm: npt.NDArray[np.float64], x1D_In: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
654
|
+
""" Interpolate a 1D tensor product Lagrange basis defined by (N_in+1) 1D interpolation point positions xi_In(0:N_In)
|
|
655
|
+
to another 1D tensor product node positions (number of nodes N_out+1)
|
|
656
|
+
defined by (N_out+1) interpolation point positions xi_Out(0:N_Out)
|
|
657
|
+
xi is defined in the 1D reference element xi=[-1,1]
|
|
658
|
+
"""
|
|
659
|
+
return Vdm @ x1D_In
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
def evaluate_jacobian(xGeo_In: npt.NDArray[np.float64],
|
|
663
|
+
VdmGLtoAP: npt.NDArray[np.float64],
|
|
664
|
+
D_EqToGL: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
611
665
|
""" Calculate the Jacobian of the mapping for a given element
|
|
612
666
|
"""
|
|
613
667
|
dim1 = xGeo_In.shape[0]
|
|
@@ -622,7 +676,7 @@ def evaluate_jacobian(xGeo_In: np.ndarray, VdmGLtoAP: np.ndarray, D_EqToGL: np.n
|
|
|
622
676
|
|
|
623
677
|
# Perform tensor contraction for the second derivative (Eta direction)
|
|
624
678
|
dXdEtaGL = np.tensordot(D_EqToGL, xGeo_In, axes=(1, 2))
|
|
625
|
-
dXdEtaGL = np.
|
|
679
|
+
dXdEtaGL = np.transpose(dXdEtaGL, (1, 2, 0, 3))
|
|
626
680
|
# PERF: This is actually slower than the individual contractions
|
|
627
681
|
# dXdEtaGL = np.einsum('qj,dijk->dqik', D_EqToGL, xGeo_In, optimize=True)
|
|
628
682
|
|
|
@@ -656,7 +710,9 @@ def evaluate_jacobian(xGeo_In: np.ndarray, VdmGLtoAP: np.ndarray, D_EqToGL: np.n
|
|
|
656
710
|
return np.einsum('ijkl,ijkl->jkl', dXdXiAP, cross_eta_zeta)
|
|
657
711
|
|
|
658
712
|
|
|
659
|
-
def evaluate_jacobian_simplex(xGeo_In:
|
|
713
|
+
def evaluate_jacobian_simplex(xGeo_In: npt.NDArray[np.float64],
|
|
714
|
+
_: Any,
|
|
715
|
+
D_EqToGL: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
660
716
|
# Perform tensor contraction for each derivative
|
|
661
717
|
# Change basis for each direction
|
|
662
718
|
dXdXiAP = xGeo_In[:, :] @ D_EqToGL[0, :, :]
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
26
26
|
# Standard libraries
|
|
27
27
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
28
|
+
from __future__ import annotations
|
|
28
29
|
import re
|
|
29
30
|
import sys
|
|
30
31
|
from typing import Final, Optional, cast
|
|
@@ -167,14 +168,15 @@ def CheckConnect() -> None:
|
|
|
167
168
|
if np_mtp > 0:
|
|
168
169
|
# Run in parallel with a chunk size
|
|
169
170
|
# > Dispatch the tasks to the workers, minimum 10 tasks per worker, maximum 1000 tasks per worker
|
|
170
|
-
res = run_in_parallel(process_chunk,
|
|
171
|
-
elems,
|
|
172
|
-
chunk_size=max(1, min(1000, max(10, int(len(elems)/(40.*np_mtp))))),
|
|
171
|
+
res = run_in_parallel(process_chunk, # noqa: E251
|
|
172
|
+
elems, # noqa: E251
|
|
173
|
+
chunk_size = max(1, min(1000, max(10, int(len(elems)/(40.*np_mtp))))), # noqa: E251
|
|
174
|
+
ordering = False, # noqa: E251
|
|
173
175
|
)
|
|
174
176
|
else:
|
|
175
177
|
res = [elem for elem in elems if check_sides(elem, failed_only=True)]
|
|
176
178
|
|
|
177
|
-
if len(res) > 0:
|
|
179
|
+
if len(res) > 0: # pragma: no cover
|
|
178
180
|
# Flatten per-element results (skip None placeholders)
|
|
179
181
|
results = tuple(result for elem_results in res if isinstance(elem_results, Iterable) and elem_results is not None
|
|
180
182
|
for result in elem_results) # noqa: E272
|