PyHOPE 0.1.0__tar.gz → 0.8.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.8.0/AUTHORS.md +24 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/PKG-INFO +56 -18
- {pyhope-0.1.0 → pyhope-0.8.0}/README.md +50 -14
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/__init__.py +7 -7
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/basis/basis_basis.py +24 -4
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/basis/basis_connect.py +9 -4
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/basis/basis_jacobian.py +25 -8
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/basis/basis_watertight.py +10 -9
- pyhope-0.8.0/pyhope/check/check.py +79 -0
- pyhope-0.8.0/pyhope/check/check_health.py +314 -0
- pyhope-0.8.0/pyhope/check/check_install.py +463 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/common/common.py +39 -39
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/common/common_parallel.py +32 -12
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/common/common_progress.py +7 -4
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/common/common_tools.py +12 -1
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/common/common_vars.py +40 -8
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/gmsh/gmsh_install.py +3 -3
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/io/io.py +128 -84
- pyhope-0.8.0/pyhope/io/io_debug.py +345 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/io/io_vars.py +13 -13
- pyhope-0.8.0/pyhope/io/io_xdmf.py +249 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/connect/connect.py +47 -34
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/connect/connect_mortar.py +5 -2
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/connect/connect_rbtree.py +9 -8
- pyhope-0.8.0/pyhope/mesh/fem/fem.py +450 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/mesh.py +15 -8
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/mesh_builtin.py +56 -15
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/mesh_common.py +9 -8
- pyhope-0.8.0/pyhope/mesh/mesh_duplicates.py +291 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/mesh_external.py +14 -5
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/mesh_orient.py +8 -3
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/mesh_sides.py +29 -2
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/mesh_sort.py +228 -110
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/mesh_vars.py +31 -10
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/reader/reader_gambit.py +94 -36
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/reader/reader_gmsh.py +107 -112
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/reader/reader_hopr.py +57 -44
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/topology/mesh_topology.py +13 -13
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/transform/mesh_transform.py +6 -3
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/meshio/meshio_ordering.py +44 -41
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/output/output.py +47 -21
- pyhope-0.8.0/pyhope/readintools/__init__.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/readintools/commandline.py +32 -8
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/readintools/readintools.py +118 -57
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/script/pyhope_cli.py +15 -14
- pyhope-0.8.0/pyproject.toml +168 -0
- pyhope-0.1.0/pyhope/mesh/fem/fem.py +0 -324
- pyhope-0.1.0/pyhope/mesh/mesh_duplicates.py +0 -193
- pyhope-0.1.0/pyproject.toml +0 -89
- {pyhope-0.1.0 → pyhope-0.8.0}/LICENSE.md +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/__main__.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/basis/__init__.py +0 -0
- {pyhope-0.1.0/pyhope/common → pyhope-0.8.0/pyhope/check}/__init__.py +0 -0
- {pyhope-0.1.0/pyhope/config → pyhope-0.8.0/pyhope/common}/__init__.py +0 -0
- {pyhope-0.1.0/pyhope/io → pyhope-0.8.0/pyhope/config}/__init__.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/config/config.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/gmsh/gmsh_override.py +0 -0
- {pyhope-0.1.0/pyhope/mesh → pyhope-0.8.0/pyhope/io}/__init__.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/io/formats/cgns.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/io/formats/gmsh.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/io/formats/meshio.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/io/formats/vtk.py +0 -0
- {pyhope-0.1.0/pyhope/output → pyhope-0.8.0/pyhope/mesh}/__init__.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/elements/elements_ordering.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/elements/elements_shapefunctions.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/topology/mesh_serendipity.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/topology/mesh_splittohex.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/transform/templates/convtest.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/transform/templates/cylinder.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/transform/templates/default.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/transform/templates/phill.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/mesh/transform/templates/sphere.py +0 -0
- {pyhope-0.1.0 → pyhope-0.8.0}/pyhope/meshio/meshio_convert.py +0 -0
- {pyhope-0.1.0/pyhope/readintools → pyhope-0.8.0/pyhope/output}/__init__.py +0 -0
pyhope-0.8.0/AUTHORS.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<div class="no-extra-css"></div>
|
|
2
|
+
# Authors
|
|
3
|
+
|
|
4
|
+
PyHOPE's development is coordinated by the Numerics Research Group (NRG) at
|
|
5
|
+
University of Stuttgart. The primary contact is Patrick Kopper, who is the *principal developer*
|
|
6
|
+
and main contributor. In addition, there are *contributors* who have
|
|
7
|
+
provided substantial additions or modifications. Together, these two groups form
|
|
8
|
+
authors as mentioned in the [LICENSE.md](LICENSE.md) file.
|
|
9
|
+
|
|
10
|
+
## Principal Developers
|
|
11
|
+
* [Patrick Kopper](https://www.iag.uni-stuttgart.de/en/institute/team/Kopper-00001/),
|
|
12
|
+
University of Stuttgart, Germany
|
|
13
|
+
|
|
14
|
+
## Contributors
|
|
15
|
+
The following people contributed major additions or modifications to PyHOPE and
|
|
16
|
+
are listed in alphabetical order:
|
|
17
|
+
|
|
18
|
+
* Daniel Appel
|
|
19
|
+
* Marcel Blind
|
|
20
|
+
* Stephen Copplestone
|
|
21
|
+
* Patrick Kopper
|
|
22
|
+
* Marius Kurz
|
|
23
|
+
* Felix Rodach
|
|
24
|
+
* Anna Schwarz
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: PyHOPE
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Python High-Order Preprocessing Environment
|
|
5
5
|
License: GPL-3.0-only
|
|
6
|
+
License-File: AUTHORS.md
|
|
7
|
+
License-File: LICENSE.md
|
|
6
8
|
Keywords: PyHOPE,mesh generator
|
|
7
9
|
Author: Numerics Research Group (NRG)
|
|
8
10
|
Author-email: numerics@iag.uni-stuttgart.de
|
|
@@ -24,17 +26,17 @@ Requires-Dist: numpy (>=2.0.0)
|
|
|
24
26
|
Requires-Dist: packaging
|
|
25
27
|
Requires-Dist: plotext
|
|
26
28
|
Requires-Dist: scipy
|
|
27
|
-
Requires-Dist: sortedcontainers
|
|
28
29
|
Requires-Dist: typing-extensions
|
|
30
|
+
Project-URL: Documentation, https://hopr-framework.github.io/PyHOPE
|
|
29
31
|
Project-URL: Homepage, https://numericsresearchgroup.org
|
|
30
|
-
Project-URL: Repository, https://
|
|
32
|
+
Project-URL: Repository, https://github.com/hopr-framework/pyhope
|
|
31
33
|
Description-Content-Type: text/markdown
|
|
32
34
|
|
|
33
35
|
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.
|
|
34
36
|
|
|
35
37
|
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
38
|
|
|
37
|
-
PyHOPE is heavily inspired by [HOPR (High Order Preprocessor)](https://github.com/hopr-framework/hopr) and shares the same input/output format.
|
|
39
|
+
PyHOPE is heavily inspired by [HOPR (High Order Preprocessor)](https://github.com/hopr-framework/hopr) and shares the same input/output format. Furthermore, PyHOPE utilizes [Gmsh](https://gmsh.info) for the initial mesh generation and conversion before converting it to its internal representation. The internal representation is loosely based on [meshio](https://github.com/nschloe/meshio) but augmented with additional information required for high-order meshes.
|
|
38
40
|
|
|
39
41
|
This is a scientific project. If you use PyHOPE for publications or presentations in science, please support the project by citing our publications given at [numericsresearchgroup.org](https://numericsresearchgroup.org/publications.html).
|
|
40
42
|
|
|
@@ -49,22 +51,47 @@ PyHOPE is built using standard Python packages. You can install PyHOPE by follow
|
|
|
49
51
|
```
|
|
50
52
|
If you choose not to use a virtual environment, skip this step and proceed directly to the installation of PyHOPE.
|
|
51
53
|
|
|
54
|
+
> [!IMPORTANT]
|
|
55
|
+
> For new shell sessions, the virtual environment must be re-sourced using `source venv/bin/activate` before using `pyhope` commands.
|
|
56
|
+
|
|
52
57
|
2. **Install PyHOPE**
|
|
53
58
|
PyHOPE is installed using `pip`, the Python package installer. This command fetches the PyHOPE package and its dependencies from PyPI (Python Package Index) and installs them.
|
|
54
59
|
```bash
|
|
55
60
|
python -m pip install pyhope
|
|
56
61
|
```
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
# Testing
|
|
64
|
+
PyHOPE features internal health checks to verify that everything works as expected. The checks can be invoked directly from the terminal.
|
|
65
|
+
```bash
|
|
66
|
+
pyhope --verify [tutorials] # Run all health checks
|
|
67
|
+
pyhope --verify-health # Run Python health checks
|
|
68
|
+
pyhope --verify-install [tutorials] # Run PyHOPE mesh generation checks
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
> [!NOTE]
|
|
72
|
+
> By default, PyHOPE looks for the `tutorials` directory relative to the current working directory or the git root. If neither exists, PyHOPE downloads the tests from GitHub while using available authentication methods.
|
|
73
|
+
|
|
74
|
+
> [!IMPORTANT]
|
|
75
|
+
> Be aware that the PyHOPE repository uses [Git Large File Storage (LFS)](https://git-lfs.com) for some of its larger mesh files.
|
|
63
76
|
|
|
64
|
-
|
|
77
|
+
# Getting Help
|
|
78
|
+
PyHOPE help output is formatted to serve as self-hosting [INI format](https://hopr-framework.github.io/PyHOPE/user-guide/parameter-file). A list of all options and the default values can be accessed by running the following command.
|
|
79
|
+
```bash
|
|
80
|
+
pyhope --help
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
# Documentation
|
|
84
|
+
Refer to the [PyHOPE documentation](https://hopr-framework.github.io/PyHOPE) for the getting started guide, examples, and usage instructions. PyHOPE is heavily inspired by [HOPR (High Order Preprocessor)](https://github.com/hopr-framework/hopr) and shares the same input/output format. For technical details and the reference mesh format specification, see the [HOPR documentation](https://hopr.readthedocs.io).
|
|
65
85
|
|
|
66
86
|
# Usage
|
|
67
|
-
PyHOPE
|
|
87
|
+
PyHOPE can either be invoked directly from the command line or used as a Python library.
|
|
88
|
+
|
|
89
|
+
## Command Line Usage
|
|
90
|
+
PyHOPE can be invoked from the command line. After installation, its functionalities can be accessed directly from the terminal by passing a valid configuration file.
|
|
91
|
+
```bash
|
|
92
|
+
pyhope [parameter.ini]
|
|
93
|
+
```
|
|
94
|
+
The following output is obtained when running the example configuration file `tutorials/1-01-cartbox/parameter.ini`.
|
|
68
95
|
```
|
|
69
96
|
$ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
70
97
|
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -72,11 +99,12 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
72
99
|
┃ PyHOPE version x.x.x
|
|
73
100
|
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
74
101
|
│ INIT PROGRAM...
|
|
75
|
-
│ nThreads │
|
|
102
|
+
│ nThreads │ nProcs-2 │ DEFAULT │
|
|
76
103
|
├─────────────────────────────────────────────
|
|
77
104
|
│ INIT OUTPUT...
|
|
78
105
|
│ ProjectName │ 1-01-cartbox │ *CUSTOM │
|
|
79
106
|
│ OutputFormat │ 0 [HDF5] │ *CUSTOM │
|
|
107
|
+
│ DebugMesh │ T │ *CUSTOM │
|
|
80
108
|
│ DebugVisu │ F │ *CUSTOM │
|
|
81
109
|
├─────────────────────────────────────────────
|
|
82
110
|
│ INIT MESH...
|
|
@@ -87,7 +115,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
87
115
|
├────
|
|
88
116
|
│ nZones │ 1 │ *CUSTOM │
|
|
89
117
|
├── Generating zone 1
|
|
90
|
-
│ Corner │ (/0.,0.,0
|
|
118
|
+
│ Corner │ (/0.,0.,0.,,1.,0.,0.,,1.,1.,... │ *CUSTOM │
|
|
91
119
|
│ nElems │ (/8,8,8/) │ *CUSTOM │
|
|
92
120
|
│ ElemType │ 108 [hexahedron] │ *CUSTOM │
|
|
93
121
|
│ StretchType │ (/0,0,0/) │ DEFAULT │
|
|
@@ -108,9 +136,9 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
108
136
|
│ BoundaryName │ BC_zplus │ *CUSTOM │
|
|
109
137
|
│ BoundaryType │ (/9,0,0,0/) │ *CUSTOM │
|
|
110
138
|
├────
|
|
111
|
-
│ vv │ (/1.,
|
|
112
|
-
│ vv │ (/0.,
|
|
113
|
-
│ vv │ (/0.,
|
|
139
|
+
│ vv │ (/1.,0.,0./) │ *CUSTOM │
|
|
140
|
+
│ vv │ (/0.,1.,0./) │ *CUSTOM │
|
|
141
|
+
│ vv │ (/0.,0.,1./) │ *CUSTOM │
|
|
114
142
|
├────
|
|
115
143
|
├── Generated mesh with 512 cells
|
|
116
144
|
├─────────────────────────────────────────────
|
|
@@ -126,7 +154,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
126
154
|
├─────────────────────────────────────────────
|
|
127
155
|
│ SORT MESH...
|
|
128
156
|
├────
|
|
129
|
-
│
|
|
157
|
+
│ MeshSorting │ 1 [SFC] │ DEFAULT │
|
|
130
158
|
├────
|
|
131
159
|
├── Sorting elements along space-filling curve
|
|
132
160
|
├─────────────────────────────────────────────
|
|
@@ -177,8 +205,18 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
177
205
|
│ Curved Hexahedra : 512
|
|
178
206
|
├────
|
|
179
207
|
├── Writing HDF5 mesh to "1-01-cartbox_mesh.h5"
|
|
208
|
+
├── Writing XDMF mesh to "1-01-cartbox_DebugMesh.xdmf"
|
|
180
209
|
┢━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
181
210
|
┃ PyHOPE completed in [0.25 sec]
|
|
182
211
|
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
183
212
|
```
|
|
184
213
|
|
|
214
|
+
## Python Library Usage
|
|
215
|
+
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 [source code](https://github.com/hopr-framework/PyHOPE/blob/main/pyhope/__init__.py).
|
|
216
|
+
```python
|
|
217
|
+
from pyhope import Basis, Mesh
|
|
218
|
+
with Mesh('1-01-cartbox_mesh.h5') as m:
|
|
219
|
+
elems = m.elems
|
|
220
|
+
lobatto_nodes = Basis.legendre_gauss_lobatto_nodes(order=m.nGeo)
|
|
221
|
+
```
|
|
222
|
+
|
|
@@ -2,7 +2,7 @@ PyHOPE (Python High-Order Preprocessing Environment) is an open-source Python fr
|
|
|
2
2
|
|
|
3
3
|
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.
|
|
4
4
|
|
|
5
|
-
PyHOPE is heavily inspired by [HOPR (High Order Preprocessor)](https://github.com/hopr-framework/hopr) and shares the same input/output format.
|
|
5
|
+
PyHOPE is heavily inspired by [HOPR (High Order Preprocessor)](https://github.com/hopr-framework/hopr) and shares the same input/output format. Furthermore, PyHOPE utilizes [Gmsh](https://gmsh.info) for the initial mesh generation and conversion before converting it to its internal representation. The internal representation is loosely based on [meshio](https://github.com/nschloe/meshio) but augmented with additional information required for high-order meshes.
|
|
6
6
|
|
|
7
7
|
This is a scientific project. If you use PyHOPE for publications or presentations in science, please support the project by citing our publications given at [numericsresearchgroup.org](https://numericsresearchgroup.org/publications.html).
|
|
8
8
|
|
|
@@ -17,22 +17,47 @@ PyHOPE is built using standard Python packages. You can install PyHOPE by follow
|
|
|
17
17
|
```
|
|
18
18
|
If you choose not to use a virtual environment, skip this step and proceed directly to the installation of PyHOPE.
|
|
19
19
|
|
|
20
|
+
> [!IMPORTANT]
|
|
21
|
+
> For new shell sessions, the virtual environment must be re-sourced using `source venv/bin/activate` before using `pyhope` commands.
|
|
22
|
+
|
|
20
23
|
2. **Install PyHOPE**
|
|
21
24
|
PyHOPE is installed using `pip`, the Python package installer. This command fetches the PyHOPE package and its dependencies from PyPI (Python Package Index) and installs them.
|
|
22
25
|
```bash
|
|
23
26
|
python -m pip install pyhope
|
|
24
27
|
```
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
# Testing
|
|
30
|
+
PyHOPE features internal health checks to verify that everything works as expected. The checks can be invoked directly from the terminal.
|
|
31
|
+
```bash
|
|
32
|
+
pyhope --verify [tutorials] # Run all health checks
|
|
33
|
+
pyhope --verify-health # Run Python health checks
|
|
34
|
+
pyhope --verify-install [tutorials] # Run PyHOPE mesh generation checks
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> [!NOTE]
|
|
38
|
+
> By default, PyHOPE looks for the `tutorials` directory relative to the current working directory or the git root. If neither exists, PyHOPE downloads the tests from GitHub while using available authentication methods.
|
|
39
|
+
|
|
40
|
+
> [!IMPORTANT]
|
|
41
|
+
> Be aware that the PyHOPE repository uses [Git Large File Storage (LFS)](https://git-lfs.com) for some of its larger mesh files.
|
|
31
42
|
|
|
32
|
-
|
|
43
|
+
# Getting Help
|
|
44
|
+
PyHOPE help output is formatted to serve as self-hosting [INI format](https://hopr-framework.github.io/PyHOPE/user-guide/parameter-file). A list of all options and the default values can be accessed by running the following command.
|
|
45
|
+
```bash
|
|
46
|
+
pyhope --help
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
# Documentation
|
|
50
|
+
Refer to the [PyHOPE documentation](https://hopr-framework.github.io/PyHOPE) for the getting started guide, examples, and usage instructions. PyHOPE is heavily inspired by [HOPR (High Order Preprocessor)](https://github.com/hopr-framework/hopr) and shares the same input/output format. For technical details and the reference mesh format specification, see the [HOPR documentation](https://hopr.readthedocs.io).
|
|
33
51
|
|
|
34
52
|
# Usage
|
|
35
|
-
PyHOPE
|
|
53
|
+
PyHOPE can either be invoked directly from the command line or used as a Python library.
|
|
54
|
+
|
|
55
|
+
## Command Line Usage
|
|
56
|
+
PyHOPE can be invoked from the command line. After installation, its functionalities can be accessed directly from the terminal by passing a valid configuration file.
|
|
57
|
+
```bash
|
|
58
|
+
pyhope [parameter.ini]
|
|
59
|
+
```
|
|
60
|
+
The following output is obtained when running the example configuration file `tutorials/1-01-cartbox/parameter.ini`.
|
|
36
61
|
```
|
|
37
62
|
$ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
38
63
|
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -40,11 +65,12 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
40
65
|
┃ PyHOPE version x.x.x
|
|
41
66
|
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
42
67
|
│ INIT PROGRAM...
|
|
43
|
-
│ nThreads │
|
|
68
|
+
│ nThreads │ nProcs-2 │ DEFAULT │
|
|
44
69
|
├─────────────────────────────────────────────
|
|
45
70
|
│ INIT OUTPUT...
|
|
46
71
|
│ ProjectName │ 1-01-cartbox │ *CUSTOM │
|
|
47
72
|
│ OutputFormat │ 0 [HDF5] │ *CUSTOM │
|
|
73
|
+
│ DebugMesh │ T │ *CUSTOM │
|
|
48
74
|
│ DebugVisu │ F │ *CUSTOM │
|
|
49
75
|
├─────────────────────────────────────────────
|
|
50
76
|
│ INIT MESH...
|
|
@@ -55,7 +81,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
55
81
|
├────
|
|
56
82
|
│ nZones │ 1 │ *CUSTOM │
|
|
57
83
|
├── Generating zone 1
|
|
58
|
-
│ Corner │ (/0.,0.,0
|
|
84
|
+
│ Corner │ (/0.,0.,0.,,1.,0.,0.,,1.,1.,... │ *CUSTOM │
|
|
59
85
|
│ nElems │ (/8,8,8/) │ *CUSTOM │
|
|
60
86
|
│ ElemType │ 108 [hexahedron] │ *CUSTOM │
|
|
61
87
|
│ StretchType │ (/0,0,0/) │ DEFAULT │
|
|
@@ -76,9 +102,9 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
76
102
|
│ BoundaryName │ BC_zplus │ *CUSTOM │
|
|
77
103
|
│ BoundaryType │ (/9,0,0,0/) │ *CUSTOM │
|
|
78
104
|
├────
|
|
79
|
-
│ vv │ (/1.,
|
|
80
|
-
│ vv │ (/0.,
|
|
81
|
-
│ vv │ (/0.,
|
|
105
|
+
│ vv │ (/1.,0.,0./) │ *CUSTOM │
|
|
106
|
+
│ vv │ (/0.,1.,0./) │ *CUSTOM │
|
|
107
|
+
│ vv │ (/0.,0.,1./) │ *CUSTOM │
|
|
82
108
|
├────
|
|
83
109
|
├── Generated mesh with 512 cells
|
|
84
110
|
├─────────────────────────────────────────────
|
|
@@ -94,7 +120,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
94
120
|
├─────────────────────────────────────────────
|
|
95
121
|
│ SORT MESH...
|
|
96
122
|
├────
|
|
97
|
-
│
|
|
123
|
+
│ MeshSorting │ 1 [SFC] │ DEFAULT │
|
|
98
124
|
├────
|
|
99
125
|
├── Sorting elements along space-filling curve
|
|
100
126
|
├─────────────────────────────────────────────
|
|
@@ -145,7 +171,17 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
145
171
|
│ Curved Hexahedra : 512
|
|
146
172
|
├────
|
|
147
173
|
├── Writing HDF5 mesh to "1-01-cartbox_mesh.h5"
|
|
174
|
+
├── Writing XDMF mesh to "1-01-cartbox_DebugMesh.xdmf"
|
|
148
175
|
┢━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
149
176
|
┃ PyHOPE completed in [0.25 sec]
|
|
150
177
|
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
151
178
|
```
|
|
179
|
+
|
|
180
|
+
## Python Library Usage
|
|
181
|
+
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 [source code](https://github.com/hopr-framework/PyHOPE/blob/main/pyhope/__init__.py).
|
|
182
|
+
```python
|
|
183
|
+
from pyhope import Basis, Mesh
|
|
184
|
+
with Mesh('1-01-cartbox_mesh.h5') as m:
|
|
185
|
+
elems = m.elems
|
|
186
|
+
lobatto_nodes = Basis.legendre_gauss_lobatto_nodes(order=m.nGeo)
|
|
187
|
+
```
|
|
@@ -66,8 +66,8 @@ MeshContainer = namedtuple('Mesh',
|
|
|
66
66
|
])
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
@contextmanager
|
|
70
|
-
def Mesh(*args, stdout=False, stderr=True):
|
|
69
|
+
@contextmanager # pragma: no cover
|
|
70
|
+
def Mesh(*args: str, stdout: bool = False, stderr: bool = True):
|
|
71
71
|
""" Mesh context manager to generate a mesh from a given file
|
|
72
72
|
|
|
73
73
|
Args:
|
|
@@ -156,8 +156,8 @@ def Mesh(*args, stdout=False, stderr=True):
|
|
|
156
156
|
|
|
157
157
|
finally:
|
|
158
158
|
# Cleanup resources after exiting the context
|
|
159
|
-
mesh_vars.mesh
|
|
160
|
-
mesh_vars.nGeo
|
|
161
|
-
mesh_vars.bcs
|
|
162
|
-
mesh_vars.elems
|
|
163
|
-
mesh_vars.sides
|
|
159
|
+
del mesh_vars.mesh
|
|
160
|
+
del mesh_vars.nGeo
|
|
161
|
+
del mesh_vars.bcs
|
|
162
|
+
del mesh_vars.elems
|
|
163
|
+
del mesh_vars.sides
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
26
26
|
# Standard libraries
|
|
27
27
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
28
|
+
from typing import Union
|
|
28
29
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
29
30
|
# Third-party libraries
|
|
30
31
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
@@ -111,7 +112,7 @@ def polynomial_derivative_matrix(order: int, xGP: np.ndarray) -> np.ndarray:
|
|
|
111
112
|
return D
|
|
112
113
|
|
|
113
114
|
|
|
114
|
-
def lagrange_interpolation_polys(x: float, order: int, xGP: np.ndarray, wBary: np.ndarray) -> np.ndarray:
|
|
115
|
+
def lagrange_interpolation_polys(x: Union[float, np.ndarray], order: int, xGP: np.ndarray, wBary: np.ndarray) -> np.ndarray:
|
|
115
116
|
""" Computes all Lagrange functions evaluated at position x in [-1;1]
|
|
116
117
|
> Algorithm 34, Kopriva
|
|
117
118
|
"""
|
|
@@ -147,10 +148,10 @@ def change_basis_3D(Vdm: np.ndarray, x3D_In: np.ndarray) -> np.ndarray:
|
|
|
147
148
|
""" Interpolate a 3D tensor product Lagrange basis defined by (N_in+1) 1D interpolation point positions xi_In(0:N_In)
|
|
148
149
|
to another 3D tensor product node positions (number of nodes N_out+1)
|
|
149
150
|
defined by (N_out+1) interpolation point positions xi_Out(0:N_Out)
|
|
150
|
-
xi is defined in the
|
|
151
|
+
xi is defined in the 1D reference element xi=[-1,1]
|
|
151
152
|
"""
|
|
152
153
|
# First contraction along the iN_In axis (axis 1 of Vdm, axis 1 of x3D_In)
|
|
153
|
-
x3D_Buf1 = np.tensordot(Vdm, x3D_In, axes=(1, 1))
|
|
154
|
+
x3D_Buf1 = np.tensordot(Vdm, x3D_In , axes=(1, 1))
|
|
154
155
|
x3D_Buf1 = np.moveaxis(x3D_Buf1, 0, 1) # Correct the shape to (dim1, n_Out, n_In, n_In)
|
|
155
156
|
|
|
156
157
|
# Second contraction along the jN_In axis (axis 1 of Vdm, axis 2 of x3D_Buf1)
|
|
@@ -160,6 +161,8 @@ def change_basis_3D(Vdm: np.ndarray, x3D_In: np.ndarray) -> np.ndarray:
|
|
|
160
161
|
# Third contraction along the kN_In axis (axis 1 of Vdm, axis 3 of x3D_Buf2)
|
|
161
162
|
x3D_Out = np.tensordot(Vdm, x3D_Buf2, axes=(1, 3))
|
|
162
163
|
x3D_Out = np.moveaxis(x3D_Out , 0, 3) # Correct the shape to (dim1, n_Out, n_Out, n_Out)
|
|
164
|
+
# PERF: This is actually slower than the individual contractions
|
|
165
|
+
# x3D_Out = np.einsum('pi,qj,rk,dijk->dpqr', Vdm, Vdm, Vdm, x3D_In, optimize=True)
|
|
163
166
|
|
|
164
167
|
return x3D_Out
|
|
165
168
|
|
|
@@ -177,22 +180,32 @@ def change_basis_2D(Vdm: np.ndarray, x2D_In: np.ndarray) -> np.ndarray:
|
|
|
177
180
|
# Second contraction along the jN_In axis (axis 1 of Vdm, axis 2 of x2D_Buf1)
|
|
178
181
|
x2D_Out = np.tensordot(Vdm, x2D_Buf1, axes=(1, 2))
|
|
179
182
|
x2D_Out = np.moveaxis(x2D_Out, 0, 2) # Correct the shape to (dim1, n_Out, n_Out, n_In)
|
|
183
|
+
# PERF: This is actually slower than the individual contractions
|
|
184
|
+
# x2D_Out = np.einsum('pi,qj,dij->dpq', Vdm, Vdm, x2D_In, optimize=True)
|
|
180
185
|
|
|
181
186
|
return x2D_Out
|
|
182
187
|
|
|
183
188
|
|
|
184
189
|
def evaluate_jacobian(xGeo_In: np.ndarray, VdmGLtoAP: np.ndarray, D_EqToGL: np.ndarray) -> np.ndarray:
|
|
190
|
+
""" Calculate the Jacobian of the mapping for a given element
|
|
191
|
+
"""
|
|
185
192
|
# Perform tensor contraction for the first derivative (Xi direction)
|
|
186
193
|
dXdXiGL = np.tensordot(D_EqToGL, xGeo_In, axes=(1, 1))
|
|
187
194
|
dXdXiGL = np.moveaxis(dXdXiGL , 1, 0) # Correct the shape to (3, nGeoRef, nGeoRef, nGeoRef)
|
|
195
|
+
# PERF: This is actually slower than the individual contractions
|
|
196
|
+
# dXdXiGL = np.einsum('pi,dijk->dpjk', D_EqToGL, xGeo_In, optimize=True)
|
|
188
197
|
|
|
189
198
|
# Perform tensor contraction for the second derivative (Eta direction)
|
|
190
199
|
dXdEtaGL = np.tensordot(D_EqToGL, xGeo_In, axes=(1, 2))
|
|
191
200
|
dXdEtaGL = np.moveaxis(dXdEtaGL , 1, 0) # Correct the shape to (3, nGeoRef, nGeoRef, nGeoRef)
|
|
201
|
+
# PERF: This is actually slower than the individual contractions
|
|
202
|
+
# dXdEtaGL = np.einsum('qj,dijk->dqik', D_EqToGL, xGeo_In, optimize=True)
|
|
192
203
|
|
|
193
204
|
# Perform tensor contraction for the third derivative (Zeta direction)
|
|
194
205
|
dXdZetaGL = np.tensordot(D_EqToGL, xGeo_In, axes=(1, 3))
|
|
195
206
|
dXdZetaGL = np.moveaxis(dXdZetaGL, 1, 0) # Correct the shape to (3, nGeoRef, nGeoRef, nGeoRef)
|
|
207
|
+
# PERF: This is actually slower than the individual contractions
|
|
208
|
+
# dXdZetaGL = np.einsum('rk,dijk->drij', D_EqToGL, xGeo_In, optimize=True)
|
|
196
209
|
|
|
197
210
|
# Change basis for each direction
|
|
198
211
|
dXdXiAP = change_basis_3D(VdmGLtoAP, dXdXiGL )
|
|
@@ -200,10 +213,17 @@ def evaluate_jacobian(xGeo_In: np.ndarray, VdmGLtoAP: np.ndarray, D_EqToGL: np.n
|
|
|
200
213
|
dXdZetaAP = change_basis_3D(VdmGLtoAP, dXdZetaGL)
|
|
201
214
|
|
|
202
215
|
# Precompute cross products between dXdEtaAP and dXdZetaAP for all points
|
|
203
|
-
cross_eta_zeta = np.cross(dXdEtaAP, dXdZetaAP, axis=0) # Shape: (3, nGeoRef, nGeoRef, nGeoRef)
|
|
216
|
+
# cross_eta_zeta = np.cross(dXdEtaAP, dXdZetaAP, axis=0) # Shape: (3, nGeoRef, nGeoRef, nGeoRef)
|
|
217
|
+
# > Manually compute cross product
|
|
218
|
+
cross_eta_zeta = np.empty_like(dXdEtaAP)
|
|
219
|
+
cross_eta_zeta[0] = dXdEtaAP[1] * dXdZetaAP[2] - dXdEtaAP[2] * dXdZetaAP[1]
|
|
220
|
+
cross_eta_zeta[1] = dXdEtaAP[2] * dXdZetaAP[0] - dXdEtaAP[0] * dXdZetaAP[2]
|
|
221
|
+
cross_eta_zeta[2] = dXdEtaAP[0] * dXdZetaAP[1] - dXdEtaAP[1] * dXdZetaAP[0]
|
|
204
222
|
|
|
205
223
|
# Fill output Jacobian array
|
|
206
224
|
jacOut = np.einsum('ijkl,ijkl->jkl', dXdXiAP, cross_eta_zeta)
|
|
225
|
+
# PERF: This is actually slower than the individual contractions
|
|
226
|
+
# jacOut = np.sum(dXdXiAP * cross_eta_zeta, axis=0)
|
|
207
227
|
|
|
208
228
|
return jacOut
|
|
209
229
|
|
|
@@ -27,12 +27,17 @@
|
|
|
27
27
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
28
28
|
import re
|
|
29
29
|
import sys
|
|
30
|
-
from typing import Final
|
|
30
|
+
from typing import Final, cast
|
|
31
31
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
32
32
|
# Third-party libraries
|
|
33
33
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
34
34
|
import numpy as np
|
|
35
|
-
|
|
35
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
36
|
+
# Typing libraries
|
|
37
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
38
|
+
import typing
|
|
39
|
+
if typing.TYPE_CHECKING:
|
|
40
|
+
import numpy.typing as npt
|
|
36
41
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
37
42
|
# Local imports
|
|
38
43
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
@@ -43,7 +48,7 @@ from pyhope.mesh.mesh_common import face_to_nodes
|
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
def check_sides(elem,
|
|
46
|
-
|
|
51
|
+
) -> list[bool | int | np.ndarray]:
|
|
47
52
|
results = []
|
|
48
53
|
elems: Final[list] = mesh_vars.elems
|
|
49
54
|
sides: Final[list] = mesh_vars.sides
|
|
@@ -130,7 +135,7 @@ def CheckConnect() -> None:
|
|
|
130
135
|
elems: Final[list] = mesh_vars.elems
|
|
131
136
|
|
|
132
137
|
# Only consider hexahedrons
|
|
133
|
-
if any(e.type % 100 != 8 for e in elems):
|
|
138
|
+
if any(cast(int, e.type) % 100 != 8 for e in elems):
|
|
134
139
|
elemTypes = list(set([e.type for e in elems if e.type % 100 != 8]))
|
|
135
140
|
print(hopout.warn('Ignored element type: {}'.format(
|
|
136
141
|
[re.sub(r"\d+$", "", mesh_vars.ELEMTYPE.inam[e][0]) for e in elemTypes]
|
|
@@ -142,8 +142,18 @@ def CheckJacobians() -> None:
|
|
|
142
142
|
# Prepare elements for parallel processing
|
|
143
143
|
tasks = []
|
|
144
144
|
|
|
145
|
-
#
|
|
146
|
-
linCache
|
|
145
|
+
# Pre-compute LINTEN mappings for all element types
|
|
146
|
+
linCache = {}
|
|
147
|
+
elemOrder = 100 if mesh_vars.nGeo == 1 else 200
|
|
148
|
+
elemTypes = tuple([s + elemOrder for s in (4, 5, 6, 8)])
|
|
149
|
+
for elemType in elemTypes:
|
|
150
|
+
try:
|
|
151
|
+
_, mapLin = LINTEN(elemType, order=mesh_vars.nGeo)
|
|
152
|
+
mapLin = np.array(tuple(mapLin[np.int64(i)] for i in range(len(mapLin))))
|
|
153
|
+
linCache[elemType] = mapLin
|
|
154
|
+
# Only hexahedrons supported for specific nGeo
|
|
155
|
+
except ValueError:
|
|
156
|
+
pass
|
|
147
157
|
|
|
148
158
|
for elem in elems:
|
|
149
159
|
elemType = elem.type
|
|
@@ -153,12 +163,7 @@ def CheckJacobians() -> None:
|
|
|
153
163
|
continue
|
|
154
164
|
|
|
155
165
|
# Get the mapping
|
|
156
|
-
|
|
157
|
-
mapLin = linCache[elemType]
|
|
158
|
-
else:
|
|
159
|
-
_, mapLin = LINTEN(elemType, order=mesh_vars.nGeo)
|
|
160
|
-
mapLin = np.array(tuple(mapLin[np.int64(i)] for i in range(len(mapLin))))
|
|
161
|
-
linCache[elemType] = mapLin
|
|
166
|
+
mapLin = linCache[elemType]
|
|
162
167
|
|
|
163
168
|
# Fill the NodeCoords
|
|
164
169
|
nodeCoords = np.empty((nGeo ** 3, 3), dtype=np.float64)
|
|
@@ -197,3 +202,15 @@ def CheckJacobians() -> None:
|
|
|
197
202
|
# Plot the histogram of the Jacobians
|
|
198
203
|
if len(jacs) > 0:
|
|
199
204
|
plot_histogram(np.array(jacs))
|
|
205
|
+
|
|
206
|
+
# Append the Jacobians to the elements
|
|
207
|
+
jacIter = iter(jacs)
|
|
208
|
+
for elem in elems:
|
|
209
|
+
elemType = elem.type
|
|
210
|
+
|
|
211
|
+
# Only consider hexahedrons
|
|
212
|
+
if int(elemType) % 100 != 8:
|
|
213
|
+
elem.jacobian = 1.
|
|
214
|
+
continue
|
|
215
|
+
|
|
216
|
+
elem.jacobian = next(jacIter)
|
|
@@ -57,7 +57,12 @@ def eval_nsurf(XGeo: np.ndarray, Vdm: np.ndarray, DGP: np.ndarray, weights: np.n
|
|
|
57
57
|
|
|
58
58
|
# Compute the cross product at each Gauss point
|
|
59
59
|
VDMSize = Vdm.shape[-1]
|
|
60
|
-
nVec = np.cross(dXdxiGP, dXdetaGP, axis=0) # Shape: (3, N_GP*N_GP)
|
|
60
|
+
# nVec = np.cross(dXdxiGP, dXdetaGP, axis=0) # Shape: (3, N_GP*N_GP)
|
|
61
|
+
# > Manually compute cross product
|
|
62
|
+
nVec = np.empty_like(dXdxiGP)
|
|
63
|
+
nVec[0] = dXdxiGP[1] * dXdetaGP[2] - dXdxiGP[2] * dXdetaGP[1]
|
|
64
|
+
nVec[1] = dXdxiGP[2] * dXdetaGP[0] - dXdxiGP[0] * dXdetaGP[2]
|
|
65
|
+
nVec[2] = dXdxiGP[0] * dXdetaGP[1] - dXdxiGP[1] * dXdetaGP[0]
|
|
61
66
|
nVec = nVec.reshape(3, VDMSize, VDMSize) # Reshape to (3, N_GP+1, N_GP+1)
|
|
62
67
|
|
|
63
68
|
# Compute the weighted normals
|
|
@@ -86,10 +91,6 @@ def check_sides(elem,
|
|
|
86
91
|
elemType = elem.type
|
|
87
92
|
|
|
88
93
|
for SideID in elem.sides:
|
|
89
|
-
# TODO: THIS IS CURRENTLY IGNORED, MEANING WE CHECK EVERY CONNECTION DOUBLE
|
|
90
|
-
# if checked[SideID]:
|
|
91
|
-
# continue
|
|
92
|
-
|
|
93
94
|
side = sides[SideID]
|
|
94
95
|
|
|
95
96
|
# Only connected sides and not small mortar sides
|
|
@@ -109,7 +110,6 @@ def check_sides(elem,
|
|
|
109
110
|
# Calculate the L2 norm of the side and take the maximum
|
|
110
111
|
sideTol = np.linalg.norm(nSurf, ord=2)
|
|
111
112
|
tol = np.max((elemTol, sideTol)) * mesh_vars.tolInternal
|
|
112
|
-
# checked[SideID] = True
|
|
113
113
|
|
|
114
114
|
# Mortar sides are the following virtual sides
|
|
115
115
|
nMortar = 4 if mortarType == 1 else 2
|
|
@@ -122,7 +122,6 @@ def check_sides(elem,
|
|
|
122
122
|
nbelem = elems[nbside.elemID]
|
|
123
123
|
idx = nbelem.nodes[face_to_nodes(nbside.face, nbelem.type, nGeo)]
|
|
124
124
|
nnbSurf += eval_nsurf(np.transpose(points[idx], axes=(2, 0, 1)), VdmEqToGP, DGP, weights)
|
|
125
|
-
# checked[nbside] = True
|
|
126
125
|
|
|
127
126
|
# Check if side normals are within tolerance
|
|
128
127
|
nSurfErr = np.sum(np.abs(nnbSurf + nSurf))
|
|
@@ -130,6 +129,10 @@ def check_sides(elem,
|
|
|
130
129
|
|
|
131
130
|
# Internal side
|
|
132
131
|
elif side.connection >= 0:
|
|
132
|
+
# Only process the side with the smaller ID
|
|
133
|
+
if SideID > side.connection:
|
|
134
|
+
continue
|
|
135
|
+
|
|
133
136
|
# Ignore the virtual mortar sides
|
|
134
137
|
if side.locMortar is not None:
|
|
135
138
|
continue
|
|
@@ -142,7 +145,6 @@ def check_sides(elem,
|
|
|
142
145
|
# Calculate the L2 norm of the side and take the maximum
|
|
143
146
|
sideTol = np.linalg.norm(nSurf, ord=2)
|
|
144
147
|
tol = np.max((elemTol, sideTol)) * mesh_vars.tolInternal
|
|
145
|
-
# checked[SideID] = True
|
|
146
148
|
|
|
147
149
|
# Connected side
|
|
148
150
|
nbside = sides[side.connection]
|
|
@@ -151,7 +153,6 @@ def check_sides(elem,
|
|
|
151
153
|
# nnbSurf = eval_nsurf(np.moveaxis(points[nbnodes], 2, 0), VdmEqToGP, DGP, weights)
|
|
152
154
|
idx = nbelem.nodes[face_to_nodes(nbside.face, nbelem.type, nGeo)]
|
|
153
155
|
nnbSurf = eval_nsurf(np.transpose(points[idx]), VdmEqToGP, DGP, weights)
|
|
154
|
-
# checked[nbside] = True
|
|
155
156
|
|
|
156
157
|
# Check if side normals are within tolerance
|
|
157
158
|
nSurfErr = np.sum(np.abs(nnbSurf + nSurf))
|