PyHOPE 0.0.9__tar.gz → 0.1.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.0.9 → pyhope-0.1.0}/PKG-INFO +9 -5
- {pyhope-0.0.9 → pyhope-0.1.0}/README.md +8 -4
- pyhope-0.1.0/pyhope/__init__.py +163 -0
- pyhope-0.1.0/pyhope/basis/basis_connect.py +190 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/basis/basis_watertight.py +1 -5
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/common/common.py +12 -2
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/common/common_parallel.py +5 -1
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/common/common_progress.py +9 -4
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/gmsh/gmsh_install.py +5 -6
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/io/formats/meshio.py +2 -3
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/io/io.py +3 -4
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/io/io_vars.py +2 -3
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/connect/connect.py +72 -42
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/connect/connect_mortar.py +6 -14
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/fem/fem.py +5 -9
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/mesh.py +6 -12
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/mesh_builtin.py +4 -8
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/mesh_common.py +168 -21
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/mesh_duplicates.py +9 -6
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/mesh_external.py +12 -10
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/reader/reader_gambit.py +17 -14
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/reader/reader_gmsh.py +28 -40
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/reader/reader_hopr.py +9 -100
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/topology/mesh_splittohex.py +6 -13
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/topology/mesh_topology.py +24 -33
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/transform/mesh_transform.py +3 -9
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/meshio/meshio_convert.py +1 -1
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/meshio/meshio_ordering.py +1 -1
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/output/output.py +48 -28
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/readintools/readintools.py +20 -49
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/script/pyhope_cli.py +2 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyproject.toml +1 -1
- {pyhope-0.0.9 → pyhope-0.1.0}/LICENSE.md +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/__main__.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/basis/__init__.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/basis/basis_basis.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/basis/basis_jacobian.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/common/__init__.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/common/common_tools.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/common/common_vars.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/config/__init__.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/config/config.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/gmsh/gmsh_override.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/io/__init__.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/io/formats/cgns.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/io/formats/gmsh.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/io/formats/vtk.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/__init__.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/connect/connect_rbtree.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/elements/elements_ordering.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/elements/elements_shapefunctions.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/mesh_orient.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/mesh_sides.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/mesh_sort.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/mesh_vars.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/topology/mesh_serendipity.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/transform/templates/convtest.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/transform/templates/cylinder.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/transform/templates/default.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/transform/templates/phill.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/mesh/transform/templates/sphere.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/output/__init__.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/readintools/__init__.py +0 -0
- {pyhope-0.0.9 → pyhope-0.1.0}/pyhope/readintools/commandline.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: PyHOPE
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: Python High-Order Preprocessing Environment
|
|
5
5
|
License: GPL-3.0-only
|
|
6
6
|
Keywords: PyHOPE,mesh generator
|
|
@@ -81,7 +81,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
81
81
|
├─────────────────────────────────────────────
|
|
82
82
|
│ INIT MESH...
|
|
83
83
|
│ Mode │ 1 [Internal] │ *CUSTOM │
|
|
84
|
-
│ NGeo │
|
|
84
|
+
│ NGeo │ 9 │ *CUSTOM │
|
|
85
85
|
├─────────────────────────────────────────────
|
|
86
86
|
│ GENERATE MESH...
|
|
87
87
|
├────
|
|
@@ -89,6 +89,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
89
89
|
├── Generating zone 1
|
|
90
90
|
│ Corner │ (/0.,0.,0. ,,1.,0.,0. ,,1.,1... │ *CUSTOM │
|
|
91
91
|
│ nElems │ (/8,8,8/) │ *CUSTOM │
|
|
92
|
+
│ ElemType │ 108 [hexahedron] │ *CUSTOM │
|
|
92
93
|
│ StretchType │ (/0,0,0/) │ DEFAULT │
|
|
93
94
|
│ BCIndex │ (/1,2,3,4,5,6/) │ *CUSTOM │
|
|
94
95
|
├────
|
|
@@ -111,8 +112,6 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
111
112
|
│ vv │ (/0., 1., 0./) │ *CUSTOM │
|
|
112
113
|
│ vv │ (/0., 0., 1./) │ *CUSTOM │
|
|
113
114
|
├────
|
|
114
|
-
│ ElemType │ 108 [hexahedron] │ *CUSTOM │
|
|
115
|
-
├────
|
|
116
115
|
├── Generated mesh with 512 cells
|
|
117
116
|
├─────────────────────────────────────────────
|
|
118
117
|
├── BUILD DATA STRUCTURE...
|
|
@@ -133,7 +132,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
133
132
|
├─────────────────────────────────────────────
|
|
134
133
|
│ CONNECT MESH...
|
|
135
134
|
├────
|
|
136
|
-
│ doPeriodicCorrect │
|
|
135
|
+
│ doPeriodicCorrect │ False │ DEFAULT │
|
|
137
136
|
│ doMortars │ True │ DEFAULT │
|
|
138
137
|
├────
|
|
139
138
|
│ Number of sides : 3072
|
|
@@ -143,6 +142,11 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
143
142
|
│ Number of boundary sides : 384
|
|
144
143
|
│ Number of periodic sides : 0
|
|
145
144
|
├─────────────────────────────────────────────
|
|
145
|
+
│ CHECK CONNECTIVITY...
|
|
146
|
+
├────
|
|
147
|
+
│ CheckConnectivity │ True │ DEFAULT │
|
|
148
|
+
│ Processing Elements |█████████████████████████████████| 512/512 [100%] in 0.0s (24000.00/s)
|
|
149
|
+
├─────────────────────────────────────────────
|
|
146
150
|
│ CHECK WATERTIGHTNESS...
|
|
147
151
|
├────
|
|
148
152
|
│ CheckWatertightness │ True │ DEFAULT │
|
|
@@ -49,7 +49,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
49
49
|
├─────────────────────────────────────────────
|
|
50
50
|
│ INIT MESH...
|
|
51
51
|
│ Mode │ 1 [Internal] │ *CUSTOM │
|
|
52
|
-
│ NGeo │
|
|
52
|
+
│ NGeo │ 9 │ *CUSTOM │
|
|
53
53
|
├─────────────────────────────────────────────
|
|
54
54
|
│ GENERATE MESH...
|
|
55
55
|
├────
|
|
@@ -57,6 +57,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
57
57
|
├── Generating zone 1
|
|
58
58
|
│ Corner │ (/0.,0.,0. ,,1.,0.,0. ,,1.,1... │ *CUSTOM │
|
|
59
59
|
│ nElems │ (/8,8,8/) │ *CUSTOM │
|
|
60
|
+
│ ElemType │ 108 [hexahedron] │ *CUSTOM │
|
|
60
61
|
│ StretchType │ (/0,0,0/) │ DEFAULT │
|
|
61
62
|
│ BCIndex │ (/1,2,3,4,5,6/) │ *CUSTOM │
|
|
62
63
|
├────
|
|
@@ -79,8 +80,6 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
79
80
|
│ vv │ (/0., 1., 0./) │ *CUSTOM │
|
|
80
81
|
│ vv │ (/0., 0., 1./) │ *CUSTOM │
|
|
81
82
|
├────
|
|
82
|
-
│ ElemType │ 108 [hexahedron] │ *CUSTOM │
|
|
83
|
-
├────
|
|
84
83
|
├── Generated mesh with 512 cells
|
|
85
84
|
├─────────────────────────────────────────────
|
|
86
85
|
├── BUILD DATA STRUCTURE...
|
|
@@ -101,7 +100,7 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
101
100
|
├─────────────────────────────────────────────
|
|
102
101
|
│ CONNECT MESH...
|
|
103
102
|
├────
|
|
104
|
-
│ doPeriodicCorrect │
|
|
103
|
+
│ doPeriodicCorrect │ False │ DEFAULT │
|
|
105
104
|
│ doMortars │ True │ DEFAULT │
|
|
106
105
|
├────
|
|
107
106
|
│ Number of sides : 3072
|
|
@@ -111,6 +110,11 @@ $ pyhope tutorials/1-01-cartbox/parameter.ini
|
|
|
111
110
|
│ Number of boundary sides : 384
|
|
112
111
|
│ Number of periodic sides : 0
|
|
113
112
|
├─────────────────────────────────────────────
|
|
113
|
+
│ CHECK CONNECTIVITY...
|
|
114
|
+
├────
|
|
115
|
+
│ CheckConnectivity │ True │ DEFAULT │
|
|
116
|
+
│ Processing Elements |█████████████████████████████████| 512/512 [100%] in 0.0s (24000.00/s)
|
|
117
|
+
├─────────────────────────────────────────────
|
|
114
118
|
│ CHECK WATERTIGHTNESS...
|
|
115
119
|
├────
|
|
116
120
|
│ CheckWatertightness │ True │ DEFAULT │
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
5
|
+
#
|
|
6
|
+
# This file is part of PyHOPE
|
|
7
|
+
#
|
|
8
|
+
# Copyright (c) 2024 Numerics Research Group, University of Stuttgart, Prof. Andrea Beck
|
|
9
|
+
#
|
|
10
|
+
# PyHOPE is free software: you can redistribute it and/or modify it under the
|
|
11
|
+
# terms of the GNU General Public License as published by the Free Software
|
|
12
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
|
13
|
+
# version.
|
|
14
|
+
#
|
|
15
|
+
# PyHOPE is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
17
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License along with
|
|
20
|
+
# PyHOPE. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# ==================================================================================================================================
|
|
24
|
+
# Mesh generation library
|
|
25
|
+
# ==================================================================================================================================
|
|
26
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
27
|
+
# Standard libraries
|
|
28
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
29
|
+
from collections import namedtuple
|
|
30
|
+
from contextlib import contextmanager
|
|
31
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
32
|
+
# Third-party libraries
|
|
33
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
34
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
35
|
+
# Local imports
|
|
36
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
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
|
+
# ==================================================================================================================================
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class Basis:
|
|
46
|
+
""" Basis class to hold all basis related functions and variables
|
|
47
|
+
"""
|
|
48
|
+
legendre_gauss_nodes = staticmethod(legendre_gauss_nodes)
|
|
49
|
+
legendre_gauss_lobatto_nodes = staticmethod(legendre_gauss_lobatto_nodes)
|
|
50
|
+
barycentric_weights = staticmethod(barycentric_weights)
|
|
51
|
+
polynomial_derivative_matrix = staticmethod(polynomial_derivative_matrix)
|
|
52
|
+
lagrange_interpolation_polys = staticmethod(lagrange_interpolation_polys)
|
|
53
|
+
calc_vandermonde = staticmethod(calc_vandermonde)
|
|
54
|
+
change_basis_3D = staticmethod(change_basis_3D)
|
|
55
|
+
change_basis_2D = staticmethod(change_basis_2D)
|
|
56
|
+
evaluate_jacobian = staticmethod(evaluate_jacobian)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# Define a named tuple to hold the mesh data
|
|
60
|
+
MeshContainer = namedtuple('Mesh',
|
|
61
|
+
['mesh', # The generated mesh object
|
|
62
|
+
'nGeo', # Polynomial order
|
|
63
|
+
'bcs', # Boundary conditions
|
|
64
|
+
'elems', # Elements
|
|
65
|
+
'sides' # Sides
|
|
66
|
+
])
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@contextmanager
|
|
70
|
+
def Mesh(*args, stdout=False, stderr=True):
|
|
71
|
+
""" Mesh context manager to generate a mesh from a given file
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
*args: The mesh file path(s) to be processed
|
|
75
|
+
stdout (bool): If False, standard output is suppressed
|
|
76
|
+
stderr (bool): If False, standard error is suppressed
|
|
77
|
+
|
|
78
|
+
Yields:
|
|
79
|
+
Mesh: An object containing the generated mesh and its properties
|
|
80
|
+
"""
|
|
81
|
+
# Standard libraries -----------------------------------
|
|
82
|
+
import os
|
|
83
|
+
# Third-party libraries --------------------------------
|
|
84
|
+
import h5py
|
|
85
|
+
from contextlib import redirect_stdout, redirect_stderr, ExitStack
|
|
86
|
+
# Local imports ----------------------------------------
|
|
87
|
+
import pyhope.config.config as config
|
|
88
|
+
import pyhope.mesh.mesh_vars as mesh_vars
|
|
89
|
+
from pyhope.common.common import DefineCommon, InitCommon
|
|
90
|
+
from pyhope.io.io import DefineIO, InitIO
|
|
91
|
+
from pyhope.mesh.connect.connect import ConnectMesh
|
|
92
|
+
from pyhope.mesh.mesh import DefineMesh, InitMesh, GenerateMesh
|
|
93
|
+
from pyhope.mesh.mesh_sides import GenerateSides
|
|
94
|
+
from pyhope.readintools.readintools import DefineConfig, ReadConfig
|
|
95
|
+
# ------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
# Check if the arguments provided are valid mesh files
|
|
99
|
+
if not args:
|
|
100
|
+
raise ValueError('No mesh file provided.')
|
|
101
|
+
|
|
102
|
+
for arg in args:
|
|
103
|
+
# Check if the argument is a valid file path
|
|
104
|
+
if not os.path.isfile(arg):
|
|
105
|
+
raise FileNotFoundError(f'Mesh file not found: {arg}')
|
|
106
|
+
|
|
107
|
+
# Check if the argument is a valid HDF5 file
|
|
108
|
+
if not h5py.is_hdf5(arg):
|
|
109
|
+
raise ValueError(f'Mesh file not a valid HDF5 file: {arg}')
|
|
110
|
+
|
|
111
|
+
# Suppress output to standard output
|
|
112
|
+
with ExitStack() as stack:
|
|
113
|
+
with open(os.devnull, 'w') as null:
|
|
114
|
+
if not stdout:
|
|
115
|
+
stack.enter_context(redirect_stdout(null))
|
|
116
|
+
if not stderr:
|
|
117
|
+
stack.enter_context(redirect_stderr(null))
|
|
118
|
+
|
|
119
|
+
# Perform the reduced PyHOPE initialization
|
|
120
|
+
with DefineConfig() as dc:
|
|
121
|
+
config.prms = dc
|
|
122
|
+
DefineCommon()
|
|
123
|
+
DefineIO()
|
|
124
|
+
DefineMesh()
|
|
125
|
+
|
|
126
|
+
with ReadConfig(args[0]) as rc:
|
|
127
|
+
config.params = rc
|
|
128
|
+
|
|
129
|
+
# Read-in required parameters
|
|
130
|
+
InitCommon()
|
|
131
|
+
InitIO()
|
|
132
|
+
InitMesh()
|
|
133
|
+
|
|
134
|
+
# Generate the actual mesh
|
|
135
|
+
GenerateMesh()
|
|
136
|
+
|
|
137
|
+
# Build our data structures
|
|
138
|
+
GenerateSides()
|
|
139
|
+
ConnectMesh()
|
|
140
|
+
|
|
141
|
+
# Export mesh variables
|
|
142
|
+
mesh = mesh_vars.mesh
|
|
143
|
+
|
|
144
|
+
nGeo = mesh_vars.nGeo
|
|
145
|
+
bcs = mesh_vars.bcs
|
|
146
|
+
|
|
147
|
+
elems = mesh_vars.elems
|
|
148
|
+
sides = mesh_vars.sides
|
|
149
|
+
|
|
150
|
+
yield MeshContainer(mesh = mesh, # noqa: E251
|
|
151
|
+
nGeo = nGeo, # noqa: E251
|
|
152
|
+
bcs = bcs, # noqa: E251
|
|
153
|
+
elems = elems, # noqa: E251
|
|
154
|
+
sides = sides # noqa: E251
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
finally:
|
|
158
|
+
# Cleanup resources after exiting the context
|
|
159
|
+
mesh_vars.mesh = None
|
|
160
|
+
mesh_vars.nGeo = None
|
|
161
|
+
mesh_vars.bcs = None
|
|
162
|
+
mesh_vars.elems = None
|
|
163
|
+
mesh_vars.sides = None
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
5
|
+
#
|
|
6
|
+
# This file is part of PyHOPE
|
|
7
|
+
#
|
|
8
|
+
# Copyright (c) 2024 Numerics Research Group, University of Stuttgart, Prof. Andrea Beck
|
|
9
|
+
#
|
|
10
|
+
# PyHOPE is free software: you can redistribute it and/or modify it under the
|
|
11
|
+
# terms of the GNU General Public License as published by the Free Software
|
|
12
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
|
13
|
+
# version.
|
|
14
|
+
#
|
|
15
|
+
# PyHOPE is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
17
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License along with
|
|
20
|
+
# PyHOPE. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
# ==================================================================================================================================
|
|
23
|
+
# Mesh generation library
|
|
24
|
+
# ==================================================================================================================================
|
|
25
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
26
|
+
# Standard libraries
|
|
27
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
28
|
+
import re
|
|
29
|
+
import sys
|
|
30
|
+
from typing import Final
|
|
31
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
32
|
+
# Third-party libraries
|
|
33
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
34
|
+
import numpy as np
|
|
35
|
+
import numpy.typing as npt
|
|
36
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
37
|
+
# Local imports
|
|
38
|
+
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
39
|
+
import pyhope.mesh.mesh_vars as mesh_vars
|
|
40
|
+
from pyhope.mesh.mesh_common import sidetovol2
|
|
41
|
+
from pyhope.mesh.mesh_common import face_to_nodes
|
|
42
|
+
# ==================================================================================================================================
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def check_sides(elem,
|
|
46
|
+
) -> list[bool | int | np.ndarray]:
|
|
47
|
+
results = []
|
|
48
|
+
elems: Final[list] = mesh_vars.elems
|
|
49
|
+
sides: Final[list] = mesh_vars.sides
|
|
50
|
+
nGeo: Final[int] = mesh_vars.nGeo
|
|
51
|
+
bcs: Final[list] = mesh_vars.bcs
|
|
52
|
+
# Tolerance for physical comparison
|
|
53
|
+
tol: Final[float] = mesh_vars.tolPeriodic
|
|
54
|
+
vvs: Final[list] = mesh_vars.vvs
|
|
55
|
+
points: Final[npt.NDArray] = mesh_vars.mesh.points
|
|
56
|
+
|
|
57
|
+
for SideID in elem.sides:
|
|
58
|
+
master = sides[SideID]
|
|
59
|
+
# Only connected sides that are master sides and not small mortar sides
|
|
60
|
+
if master.connection is None \
|
|
61
|
+
or master.connection < 0 \
|
|
62
|
+
or master.MS != 1 \
|
|
63
|
+
or master.sideType < 0: # noqa: E271
|
|
64
|
+
continue
|
|
65
|
+
|
|
66
|
+
side = (master, sides[master.connection])
|
|
67
|
+
|
|
68
|
+
# Only actual element sides
|
|
69
|
+
if side[0].face is None \
|
|
70
|
+
or side[1].face is None: # noqa: E271
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
# Sanity check the flip with the other nodes
|
|
74
|
+
elem0 = elems[side[0].elemID]
|
|
75
|
+
elem1 = elems[side[1].elemID]
|
|
76
|
+
if elem1.type % 100 != 8:
|
|
77
|
+
continue
|
|
78
|
+
|
|
79
|
+
# Map the meshio nodes to the tensor-product nodes
|
|
80
|
+
elemType = elem0.type
|
|
81
|
+
nodes = elem0.nodes[sidetovol2(nGeo, 0 , side[0].face, elemType)]
|
|
82
|
+
nbNodes = elem1.nodes[sidetovol2(nGeo, side[1].flip, side[1].face, elemType)]
|
|
83
|
+
|
|
84
|
+
# INFO: THIS CURRENTLY MIGHT NOT WORK SINCE WE POTENTIALLY ONLY HAVE THE CORNER NODES AVAILABLE
|
|
85
|
+
try:
|
|
86
|
+
# Translate to periodic nodes if required
|
|
87
|
+
if side[0].bcid is not None and side[1].bcid is not None and bcs[side[1].bcid].type[0] == 1:
|
|
88
|
+
nbNodes = np.vectorize(lambda s: mesh_vars.periNodes[(s, bcs[side[1].bcid].name)], otypes=[int])(nbNodes)
|
|
89
|
+
# Check if the node IDs match
|
|
90
|
+
success = np.array_equal(nodes, nbNodes)
|
|
91
|
+
# Fallback to comparison of physical coordinates
|
|
92
|
+
except KeyError:
|
|
93
|
+
# Check if periodic vector matches using vectorized np.allclose
|
|
94
|
+
iVV = bcs[side[0].bcid].type[3]
|
|
95
|
+
vv = vvs[np.abs(iVV) - 1]['Dir'] * np.sign(iVV)
|
|
96
|
+
success = np.allclose(points[nodes] + vv, points[nbNodes], rtol=tol, atol=tol)
|
|
97
|
+
|
|
98
|
+
results.append((success, SideID))
|
|
99
|
+
return results
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def process_chunk(chunk) -> np.ndarray:
|
|
103
|
+
"""Process a chunk of elements by checking surface normal orientation
|
|
104
|
+
"""
|
|
105
|
+
chunk_results = np.empty(len(chunk), dtype=object)
|
|
106
|
+
chunk_results[:] = [check_sides(elem_data) for elem_data in chunk]
|
|
107
|
+
return chunk_results
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def CheckConnect() -> None:
|
|
111
|
+
""" Check if the mesh is correctly connected
|
|
112
|
+
"""
|
|
113
|
+
# Local imports ----------------------------------------
|
|
114
|
+
import pyhope.output.output as hopout
|
|
115
|
+
import pyhope.mesh.mesh_vars as mesh_vars
|
|
116
|
+
from pyhope.common.common_parallel import run_in_parallel
|
|
117
|
+
from pyhope.common.common_vars import np_mtp
|
|
118
|
+
from pyhope.readintools.readintools import GetLogical
|
|
119
|
+
# ------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
hopout.separator()
|
|
122
|
+
hopout.info('CHECK CONNECTIVITY...')
|
|
123
|
+
hopout.sep()
|
|
124
|
+
|
|
125
|
+
checkConnectivity = GetLogical('CheckConnectivity')
|
|
126
|
+
if not checkConnectivity:
|
|
127
|
+
return None
|
|
128
|
+
|
|
129
|
+
# Check all sides
|
|
130
|
+
elems: Final[list] = mesh_vars.elems
|
|
131
|
+
|
|
132
|
+
# Only consider hexahedrons
|
|
133
|
+
if any(e.type % 100 != 8 for e in elems):
|
|
134
|
+
elemTypes = list(set([e.type for e in elems if e.type % 100 != 8]))
|
|
135
|
+
print(hopout.warn('Ignored element type: {}'.format(
|
|
136
|
+
[re.sub(r"\d+$", "", mesh_vars.ELEMTYPE.inam[e][0]) for e in elemTypes]
|
|
137
|
+
)))
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
# Prepare elements for parallel processing
|
|
141
|
+
if np_mtp > 0:
|
|
142
|
+
tasks = tuple((elem)
|
|
143
|
+
for elem in elems)
|
|
144
|
+
# Run in parallel with a chunk size
|
|
145
|
+
# > Dispatch the tasks to the workers, minimum 10 tasks per worker, maximum 1000 tasks per worker
|
|
146
|
+
res = run_in_parallel(process_chunk, tasks, chunk_size=max(1, min(1000, max(10, int(len(tasks)/(40.*np_mtp))))))
|
|
147
|
+
else:
|
|
148
|
+
res = np.empty(len(elems), dtype=object)
|
|
149
|
+
res[:] = [check_sides(elem) for elem in elems]
|
|
150
|
+
|
|
151
|
+
results = tuple(tuple(result for r in res for result in r if not bool(result[0]))
|
|
152
|
+
)
|
|
153
|
+
if len(results) > 0:
|
|
154
|
+
nGeo: Final[int] = mesh_vars.nGeo
|
|
155
|
+
sides: Final[list] = mesh_vars.sides
|
|
156
|
+
points: Final[np.ndarray] = mesh_vars.mesh.points
|
|
157
|
+
|
|
158
|
+
nconn = len(tuple(tuple(result for r in res for result in r)))
|
|
159
|
+
|
|
160
|
+
for result in results:
|
|
161
|
+
# Unpack the results
|
|
162
|
+
side = sides[result[1]]
|
|
163
|
+
elem = elems[side.elemID]
|
|
164
|
+
nbside = sides[side.connection]
|
|
165
|
+
nbelem = elems[nbside.elemID]
|
|
166
|
+
|
|
167
|
+
nodes = elem.nodes[face_to_nodes( side.face, elem.type, nGeo)]
|
|
168
|
+
nbnodes = nbelem.nodes[face_to_nodes(nbside.face, nbelem.type, nGeo)]
|
|
169
|
+
|
|
170
|
+
print()
|
|
171
|
+
# Check if side is oriented inwards
|
|
172
|
+
errStr = 'Side connectivity does not match the calculated neighbour side'
|
|
173
|
+
print(hopout.warn(errStr, length=len(errStr)+16))
|
|
174
|
+
|
|
175
|
+
# Print the information
|
|
176
|
+
strLen = max(len(str(side.sideID+1)), len(str(nbside.sideID+1)))
|
|
177
|
+
print(hopout.warn(f'> Element { elem.elemID+1:>{strLen}}, Side { side.face}, Side { side.sideID+1:>{strLen}}')) # noqa: E501
|
|
178
|
+
print(hopout.warn('- Coordinates : [' + ' '.join('{:12.3f}'.format(s) for s in points[ nodes[ 0, 0]]) + ']')) # noqa: E271
|
|
179
|
+
print(hopout.warn('- Coordinates : [' + ' '.join('{:12.3f}'.format(s) for s in points[ nodes[ 0, -1]]) + ']')) # noqa: E271
|
|
180
|
+
print(hopout.warn('- Coordinates : [' + ' '.join('{:12.3f}'.format(s) for s in points[ nodes[-1, 0]]) + ']')) # noqa: E271
|
|
181
|
+
print(hopout.warn('- Coordinates : [' + ' '.join('{:12.3f}'.format(s) for s in points[ nodes[-1, -1]]) + ']')) # noqa: E271
|
|
182
|
+
# print()
|
|
183
|
+
print(hopout.warn(f'> Element {nbelem.elemID+1:>{strLen}}, Side {nbside.face}, Side {nbside.sideID+1:>{strLen}}')) # noqa: E501
|
|
184
|
+
print(hopout.warn('- Coordinates : [' + ' '.join('{:12.3f}'.format(s) for s in points[nbnodes[ 0, 0]]) + ']')) # noqa: E271
|
|
185
|
+
print(hopout.warn('- Coordinates : [' + ' '.join('{:12.3f}'.format(s) for s in points[nbnodes[ 0, -1]]) + ']')) # noqa: E271
|
|
186
|
+
print(hopout.warn('- Coordinates : [' + ' '.join('{:12.3f}'.format(s) for s in points[nbnodes[-1, 0]]) + ']')) # noqa: E271
|
|
187
|
+
print(hopout.warn('- Coordinates : [' + ' '.join('{:12.3f}'.format(s) for s in points[nbnodes[-1, -1]]) + ']')) # noqa: E271
|
|
188
|
+
|
|
189
|
+
hopout.warning(f'Connectivity check failed for {len(results)} / {nconn} connections!')
|
|
190
|
+
sys.exit(1)
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
# Standard libraries
|
|
27
27
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
28
28
|
import re
|
|
29
|
-
import sys
|
|
30
29
|
from typing import Final
|
|
31
30
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
32
31
|
# Third-party libraries
|
|
@@ -76,8 +75,6 @@ def check_sides(elem,
|
|
|
76
75
|
weights : np.ndarray,
|
|
77
76
|
# sides : list
|
|
78
77
|
) -> list[bool | int | np.ndarray]:
|
|
79
|
-
# Local imports ----------------------------------------
|
|
80
|
-
# ------------------------------------------------------
|
|
81
78
|
results = []
|
|
82
79
|
points = mesh_vars.mesh.points
|
|
83
80
|
elems = mesh_vars.elems
|
|
@@ -276,5 +273,4 @@ def CheckWatertight() -> None:
|
|
|
276
273
|
print(hopout.warn('- Coordinates : [' + ' '.join('{:12.3f}'.format(s) for s in points[nbnodes[-1, 0]]) + ']')) # noqa: E271
|
|
277
274
|
print(hopout.warn('- Coordinates : [' + ' '.join('{:12.3f}'.format(s) for s in points[nbnodes[-1, -1]]) + ']')) # noqa: E271
|
|
278
275
|
|
|
279
|
-
hopout.
|
|
280
|
-
sys.exit(1)
|
|
276
|
+
hopout.error(f'Watertightness check failed for {len(results)} / {nconn} connections!')
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
# Standard libraries
|
|
27
27
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
28
28
|
import os
|
|
29
|
-
import sys
|
|
30
29
|
from io import TextIOWrapper
|
|
31
30
|
from typing import cast
|
|
32
31
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
@@ -104,6 +103,9 @@ def DebugEnabled() -> bool:
|
|
|
104
103
|
""" Check if program runs with debugger attached
|
|
105
104
|
> https://stackoverflow.com/a/77627075/23851165
|
|
106
105
|
"""
|
|
106
|
+
# Standard libraries -----------------------------------
|
|
107
|
+
import sys
|
|
108
|
+
# ------------------------------------------------------
|
|
107
109
|
try:
|
|
108
110
|
if sys.gettrace() is not None:
|
|
109
111
|
return True
|
|
@@ -120,12 +122,20 @@ def DebugEnabled() -> bool:
|
|
|
120
122
|
|
|
121
123
|
|
|
122
124
|
def IsInteractive() -> bool:
|
|
123
|
-
|
|
125
|
+
""" Check if the program is running in an interactive terminal
|
|
126
|
+
"""
|
|
127
|
+
# Standard libraries -----------------------------------
|
|
128
|
+
import sys
|
|
129
|
+
# ------------------------------------------------------
|
|
130
|
+
return cast(TextIOWrapper, sys.__stdin__).isatty() and cast(TextIOWrapper, sys.__stdout__).isatty()
|
|
124
131
|
|
|
125
132
|
|
|
126
133
|
def IsDisplay() -> bool:
|
|
127
134
|
""" Check if the program is running in a display environment
|
|
128
135
|
"""
|
|
136
|
+
# Standard libraries -----------------------------------
|
|
137
|
+
import sys
|
|
138
|
+
# ------------------------------------------------------
|
|
129
139
|
# Check if running on Linux, otherwise assume a display
|
|
130
140
|
if not sys.platform.startswith('linux'):
|
|
131
141
|
return True
|
|
@@ -58,6 +58,7 @@ def run_in_parallel(process_chunk: Callable, elems: tuple, chunk_size: int = 10)
|
|
|
58
58
|
"""Run the element processing in parallel using a specified number of processes
|
|
59
59
|
"""
|
|
60
60
|
# Local imports ----------------------------------------
|
|
61
|
+
from pyhope.common.common import IsInteractive
|
|
61
62
|
from pyhope.common.common_vars import np_mtp
|
|
62
63
|
# ------------------------------------------------------
|
|
63
64
|
|
|
@@ -65,8 +66,11 @@ def run_in_parallel(process_chunk: Callable, elems: tuple, chunk_size: int = 10)
|
|
|
65
66
|
total_elements = len(elems)
|
|
66
67
|
progress_queue = Queue()
|
|
67
68
|
|
|
69
|
+
# Create a progress bar target
|
|
70
|
+
target = update_progress if IsInteractive() else None
|
|
71
|
+
|
|
68
72
|
# Use a separate thread for the progress bar
|
|
69
|
-
progress_thread = threading.Thread(target=
|
|
73
|
+
progress_thread = threading.Thread(target=target, args=(progress_queue, total_elements))
|
|
70
74
|
progress_thread.start()
|
|
71
75
|
|
|
72
76
|
# Use multiprocessing Pool for parallel processing
|
|
@@ -45,14 +45,19 @@ class ProgressBar:
|
|
|
45
45
|
""" Provide a progress bar outside of the context manager
|
|
46
46
|
"""
|
|
47
47
|
def __init__(self, title: Optional[str], value: int, length: int = 33, threshold: int = barElems) -> None:
|
|
48
|
+
# Local imports ----------------------------------------
|
|
49
|
+
from pyhope.common.common import IsInteractive
|
|
50
|
+
# ------------------------------------------------------
|
|
51
|
+
if value <= threshold or not IsInteractive():
|
|
52
|
+
self.bar = None
|
|
53
|
+
return None
|
|
54
|
+
|
|
48
55
|
self._cm : Final = alive_bar(title=title, total=value, length=length)
|
|
49
56
|
self._title: Optional[str] = title
|
|
50
57
|
self._len : int = length
|
|
51
58
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
else:
|
|
55
|
-
self.bar = None
|
|
59
|
+
# Initialize the progress bar
|
|
60
|
+
self.bar = self._cm.__enter__()
|
|
56
61
|
|
|
57
62
|
def step(self, steps: int = 1) -> None:
|
|
58
63
|
if self.bar is not None:
|
|
@@ -29,7 +29,6 @@ import os
|
|
|
29
29
|
import shutil
|
|
30
30
|
import platform
|
|
31
31
|
import subprocess
|
|
32
|
-
import sys
|
|
33
32
|
from importlib import metadata
|
|
34
33
|
from packaging.version import Version
|
|
35
34
|
from typing import Optional, cast
|
|
@@ -97,8 +96,7 @@ def PkgsCheckGmsh() -> None:
|
|
|
97
96
|
PkgsInstallGmsh(system, arch, version='pypi')
|
|
98
97
|
return None
|
|
99
98
|
else:
|
|
100
|
-
hopout.
|
|
101
|
-
sys.exit(1)
|
|
99
|
+
hopout.error('Gmsh is not installed, exiting...')
|
|
102
100
|
|
|
103
101
|
gmsh_version = cast(str, gmsh_version)
|
|
104
102
|
# Assume that newer versions have updated CGNS
|
|
@@ -132,9 +130,11 @@ def PkgsCheckGmsh() -> None:
|
|
|
132
130
|
|
|
133
131
|
|
|
134
132
|
def PkgsInstallGmsh(system: str, arch: str, version: str) -> None:
|
|
135
|
-
#
|
|
133
|
+
# Standard libraries -----------------------------------
|
|
134
|
+
import sys
|
|
136
135
|
import hashlib
|
|
137
136
|
import tempfile
|
|
137
|
+
# Local imports ----------------------------------------
|
|
138
138
|
import pyhope.output.output as hopout
|
|
139
139
|
from pyhope.common.common_vars import Gitlab
|
|
140
140
|
# ------------------------------------------------------
|
|
@@ -185,8 +185,7 @@ def PkgsInstallGmsh(system: str, arch: str, version: str) -> None:
|
|
|
185
185
|
if sha256.hexdigest() == Gitlab.LIB_SUPPORT[system][arch]:
|
|
186
186
|
hopout.info('Hash matches, installing Gmsh wheel...')
|
|
187
187
|
else:
|
|
188
|
-
hopout.
|
|
189
|
-
sys.exit(1)
|
|
188
|
+
hopout.error('Hash mismatch, exiting...')
|
|
190
189
|
|
|
191
190
|
# Remove the old version
|
|
192
191
|
try:
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
28
28
|
from functools import cache
|
|
29
29
|
from typing import Tuple
|
|
30
|
-
import sys
|
|
31
30
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
32
31
|
# Third-party libraries
|
|
33
32
|
import numpy as np
|
|
@@ -144,7 +143,7 @@ def edgePointMESHIO(start: int, end: int, edge: int, node: int) -> np.ndarray:
|
|
|
144
143
|
case 11:
|
|
145
144
|
return np.array((start , end , node ), dtype=int)
|
|
146
145
|
case _:
|
|
147
|
-
|
|
146
|
+
raise ValueError(f'Invalid edge index: {edge}.')
|
|
148
147
|
|
|
149
148
|
|
|
150
149
|
@cache
|
|
@@ -171,7 +170,7 @@ def facePointMESHIO(start: int, end: int, face: int, pos: int) -> np.ndarray:
|
|
|
171
170
|
index = facePointMatrix(end-start-1, pos, orient=False)
|
|
172
171
|
return np.array((start+index[0]+1 , start+index[1]+1 , end ), dtype=int)
|
|
173
172
|
case _:
|
|
174
|
-
|
|
173
|
+
raise ValueError(f'Invalid face index: {face}.')
|
|
175
174
|
|
|
176
175
|
|
|
177
176
|
@cache
|
|
@@ -25,13 +25,11 @@
|
|
|
25
25
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
26
26
|
# Standard libraries
|
|
27
27
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
28
|
-
import sys
|
|
29
28
|
from collections import OrderedDict
|
|
30
29
|
from typing import Final
|
|
31
30
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
32
31
|
# Third-party libraries
|
|
33
32
|
import h5py
|
|
34
|
-
import heapq
|
|
35
33
|
import numpy as np
|
|
36
34
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
37
35
|
# ----------------------------------------------------------------------------------------------------------------------------------
|
|
@@ -197,8 +195,7 @@ def IO() -> None:
|
|
|
197
195
|
mesh.write(fname, file_format='gmsh')
|
|
198
196
|
|
|
199
197
|
case _: # Default
|
|
200
|
-
hopout.
|
|
201
|
-
sys.exit(1)
|
|
198
|
+
hopout.error('Unknown output format {}, exiting...'.format(io_vars.outputformat))
|
|
202
199
|
|
|
203
200
|
# hopout.sep()
|
|
204
201
|
# hopout.info('OUTPUT MESH DONE!')
|
|
@@ -215,6 +212,8 @@ def getMeshInfo() -> tuple[np.ndarray, # ElemInfo
|
|
|
215
212
|
np.ndarray | None, # Optional[EdgeConnectInfo]
|
|
216
213
|
dict[int, int]
|
|
217
214
|
]:
|
|
215
|
+
# Standard libraries -----------------------------------
|
|
216
|
+
import heapq
|
|
218
217
|
# Local imports ----------------------------------------
|
|
219
218
|
import pyhope.mesh.mesh_vars as mesh_vars
|
|
220
219
|
from pyhope.mesh.fem.fem import getFEMInfo
|