simnexus 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.
Files changed (38) hide show
  1. simnexus-0.1.0/LICENSE.md +22 -0
  2. simnexus-0.1.0/PKG-INFO +112 -0
  3. simnexus-0.1.0/README.md +72 -0
  4. simnexus-0.1.0/pyproject.toml +35 -0
  5. simnexus-0.1.0/setup.cfg +4 -0
  6. simnexus-0.1.0/simnexus/VTK/read_vtk.py +329 -0
  7. simnexus-0.1.0/simnexus/__init__.py +5 -0
  8. simnexus-0.1.0/simnexus/actions.py +250 -0
  9. simnexus-0.1.0/simnexus/args.py +56 -0
  10. simnexus-0.1.0/simnexus/d3plot_actions.py +317 -0
  11. simnexus-0.1.0/simnexus/dyna_actions.py +149 -0
  12. simnexus-0.1.0/simnexus/graph_actions.py +656 -0
  13. simnexus-0.1.0/simnexus/jinja_actions.py +207 -0
  14. simnexus-0.1.0/simnexus/openfoam_actions.py +211 -0
  15. simnexus-0.1.0/simnexus/protos/__init__.py +0 -0
  16. simnexus-0.1.0/simnexus/protos/remote_actions_pb2.py +48 -0
  17. simnexus-0.1.0/simnexus/protos/remote_actions_pb2_grpc.py +140 -0
  18. simnexus-0.1.0/simnexus/radioss_actions.py +465 -0
  19. simnexus-0.1.0/simnexus/rare.py +51 -0
  20. simnexus-0.1.0/simnexus/remote_actions.py +250 -0
  21. simnexus-0.1.0/simnexus/util/observer.py +34 -0
  22. simnexus-0.1.0/simnexus/util/openfoam_reader.py +1768 -0
  23. simnexus-0.1.0/simnexus/util/openradios_reader.py +258 -0
  24. simnexus-0.1.0/simnexus/variables.py +129 -0
  25. simnexus-0.1.0/simnexus.egg-info/PKG-INFO +112 -0
  26. simnexus-0.1.0/simnexus.egg-info/SOURCES.txt +36 -0
  27. simnexus-0.1.0/simnexus.egg-info/dependency_links.txt +1 -0
  28. simnexus-0.1.0/simnexus.egg-info/requires.txt +3 -0
  29. simnexus-0.1.0/simnexus.egg-info/top_level.txt +1 -0
  30. simnexus-0.1.0/tests/test_core.py +4 -0
  31. simnexus-0.1.0/tests/test_dyna.py +41 -0
  32. simnexus-0.1.0/tests/test_graph.py +218 -0
  33. simnexus-0.1.0/tests/test_openfoam_job.py +118 -0
  34. simnexus-0.1.0/tests/test_openradios_reader.py +417 -0
  35. simnexus-0.1.0/tests/test_remote_patterns.py +66 -0
  36. simnexus-0.1.0/tests/test_simulation_iterator.py +64 -0
  37. simnexus-0.1.0/tests/test_solve.py +184 -0
  38. simnexus-0.1.0/tests/test_vars.py +69 -0
@@ -0,0 +1,22 @@
1
+
2
+ MIT License
3
+
4
+ Copyright (c) 2026 Willem Roux
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,112 @@
1
+ Metadata-Version: 2.4
2
+ Name: simnexus
3
+ Version: 0.1.0
4
+ Summary: A Python module for modelling complex simulation workflows.
5
+ Author-email: Willem <willem4540@gmail.com>
6
+ License:
7
+ MIT License
8
+
9
+ Copyright (c) 2026 Willem Roux
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Project-URL: Homepage, https://github.com/WillemJR/simnexus
30
+ Classifier: Development Status :: 3 - Alpha
31
+ Classifier: Programming Language :: Python :: 3
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Operating System :: OS Independent
34
+ Requires-Python: >=3.7
35
+ Description-Content-Type: text/markdown
36
+ License-File: LICENSE.md
37
+ Provides-Extra: dev
38
+ Requires-Dist: pytest; extra == "dev"
39
+ Dynamic: license-file
40
+
41
+
42
+ # SimNexus
43
+
44
+ A Python module for orchestrating complex simulations
45
+ with native support for LS-DYNA, OpenRadioss, and OpenFOAM.
46
+
47
+ ## Overview
48
+
49
+ SimNexus enables the automation and coordination of
50
+ multi-physics simulation workflows.
51
+ The module is particularly suited for simulations that span multiple domains, such as combined structural and fluid dynamics analyses.
52
+
53
+ It supports tasks from from input preparation and
54
+ remote execution to results extraction and post-processing.
55
+
56
+
57
+ SimNexus has a native support for
58
+ solvers like LS-DYNA, OpenRadioss, and OpenFOAM.
59
+
60
+ ## Key Features
61
+
62
+ - **Workflow Management**: Define simulation workflows as directed acyclic graphs (DAGs) where actions are executed based on dependency relationships and completion status of prerequisite tasks
63
+ - **Native Solver Support**: Specify input parameter values and the results to extract for a supported solver. Currently implemented are LS-DYNA and OpenRadioss for structural analysis, and OpenFOAM for computational fluid dynamics
64
+ - **Remote Execution**: Submit computational subgraphs to remote computing resources while maintaining local workflow coordination
65
+ - **Dependency Resolution**: Automatically manages execution order based on inter-action dependencies, ensuring downstream actions wait for required upstream results
66
+ - **Discoverability**: Query any graph for its inputs (`variables()`) and outputs (`outputs()`) without running it — solver actions read their parameterised input files to report variable names, types, and default values
67
+ - **Scalability using ML**: Designed to scale through integration with the Gemini CLI for the extension and use of the module.
68
+
69
+ ## Typical Workflow
70
+
71
+ 1. Configure input files for target solvers
72
+ 2. Define analysis actions and their dependencies
73
+ 3. Execute simulations on designated compute resources (local or remote)
74
+ 4. Extract relevant results from solver outputs
75
+ 5. Aggregate and summarize findings
76
+
77
+ SimNexus streamlines the complexity of managing heterogeneous simulation environments, enabling researchers and engineers to focus on analysis rather than workflow orchestration.
78
+
79
+
80
+ ## Documentation
81
+ (Path to be added. One provided is not yet active)
82
+
83
+ [Online documentation is available here](https://willemjr.github.io/simnexus/)
84
+
85
+ See also the docs directory.
86
+
87
+
88
+ ## Installation
89
+
90
+ ```bash
91
+ pip install simnexus
92
+ ```
93
+
94
+ ## Usage
95
+ See the documentation and the examples directory for examples.
96
+
97
+ (Coming soon)
98
+
99
+
100
+
101
+ # Example problems
102
+ The example problems demonstrate:
103
+
104
+ - An LS-DYNA workflow consisting of editing parameter values, job submission, and results extraction.
105
+ - An OpenRadioss workflow consisting of editing parameter values, job submission, and results extraction.
106
+ - An OpenFOAM. workflow consisting of editing parameter values, job submission, and results extraction.
107
+ - Remote execution examples.
108
+
109
+
110
+ ## License
111
+ This project is licensed under the MIT License.
112
+
@@ -0,0 +1,72 @@
1
+
2
+ # SimNexus
3
+
4
+ A Python module for orchestrating complex simulations
5
+ with native support for LS-DYNA, OpenRadioss, and OpenFOAM.
6
+
7
+ ## Overview
8
+
9
+ SimNexus enables the automation and coordination of
10
+ multi-physics simulation workflows.
11
+ The module is particularly suited for simulations that span multiple domains, such as combined structural and fluid dynamics analyses.
12
+
13
+ It supports tasks from from input preparation and
14
+ remote execution to results extraction and post-processing.
15
+
16
+
17
+ SimNexus has a native support for
18
+ solvers like LS-DYNA, OpenRadioss, and OpenFOAM.
19
+
20
+ ## Key Features
21
+
22
+ - **Workflow Management**: Define simulation workflows as directed acyclic graphs (DAGs) where actions are executed based on dependency relationships and completion status of prerequisite tasks
23
+ - **Native Solver Support**: Specify input parameter values and the results to extract for a supported solver. Currently implemented are LS-DYNA and OpenRadioss for structural analysis, and OpenFOAM for computational fluid dynamics
24
+ - **Remote Execution**: Submit computational subgraphs to remote computing resources while maintaining local workflow coordination
25
+ - **Dependency Resolution**: Automatically manages execution order based on inter-action dependencies, ensuring downstream actions wait for required upstream results
26
+ - **Discoverability**: Query any graph for its inputs (`variables()`) and outputs (`outputs()`) without running it — solver actions read their parameterised input files to report variable names, types, and default values
27
+ - **Scalability using ML**: Designed to scale through integration with the Gemini CLI for the extension and use of the module.
28
+
29
+ ## Typical Workflow
30
+
31
+ 1. Configure input files for target solvers
32
+ 2. Define analysis actions and their dependencies
33
+ 3. Execute simulations on designated compute resources (local or remote)
34
+ 4. Extract relevant results from solver outputs
35
+ 5. Aggregate and summarize findings
36
+
37
+ SimNexus streamlines the complexity of managing heterogeneous simulation environments, enabling researchers and engineers to focus on analysis rather than workflow orchestration.
38
+
39
+
40
+ ## Documentation
41
+ (Path to be added. One provided is not yet active)
42
+
43
+ [Online documentation is available here](https://willemjr.github.io/simnexus/)
44
+
45
+ See also the docs directory.
46
+
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ pip install simnexus
52
+ ```
53
+
54
+ ## Usage
55
+ See the documentation and the examples directory for examples.
56
+
57
+ (Coming soon)
58
+
59
+
60
+
61
+ # Example problems
62
+ The example problems demonstrate:
63
+
64
+ - An LS-DYNA workflow consisting of editing parameter values, job submission, and results extraction.
65
+ - An OpenRadioss workflow consisting of editing parameter values, job submission, and results extraction.
66
+ - An OpenFOAM. workflow consisting of editing parameter values, job submission, and results extraction.
67
+ - Remote execution examples.
68
+
69
+
70
+ ## License
71
+ This project is licensed under the MIT License.
72
+
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "simnexus"
7
+ version = "0.1.0"
8
+ description = "A Python module for modelling complex simulation workflows."
9
+ readme = "README.md"
10
+ license = {file = "LICENSE.md"}
11
+ authors = [
12
+ { name = "Willem", email = "willem4540@gmail.com" },
13
+ ]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Programming Language :: Python :: 3",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ ]
20
+ requires-python = ">=3.7"
21
+ dependencies = []
22
+
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/WillemJR/simnexus"
26
+
27
+
28
+ [project.optional-dependencies]
29
+ dev = [
30
+ "pytest",
31
+ ]
32
+
33
+ [tool.setuptools.packages.find]
34
+ where = ["."]
35
+ include = ["simnexus*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,329 @@
1
+
2
+ import pyvista as pv
3
+ from vtk.util.numpy_support import vtk_to_numpy
4
+ import numpy as np
5
+
6
+ from collections import namedtuple
7
+
8
+ from vtk import VTK_EMPTY_CELL, VTK_TRIANGLE, VTK_QUAD
9
+ from vtk import VTK_HEXAHEDRON, VTK_WEDGE, VTK_TETRA
10
+
11
+ ########################
12
+ # // Linear cells
13
+ # VTK_EMPTY_CELL = 0,
14
+ # VTK_VERTEX = 1,
15
+ # VTK_POLY_VERTEX = 2,
16
+ # VTK_LINE = 3, <<<<<<<<<<
17
+ # VTK_POLY_LINE = 4,
18
+ # VTK_TRIANGLE = 5, <<<<<<<<<<
19
+ # VTK_TRIANGLE_STRIP = 6,
20
+ # VTK_POLYGON = 7,
21
+ # VTK_PIXEL = 8,
22
+ # VTK_QUAD = 9,
23
+ # VTK_TETRA = 10, <<<<<<<<<<
24
+ # VTK_VOXEL = 11,
25
+ # VTK_HEXAHEDRON = 12, <<<<<<<<<<
26
+ # VTK_WEDGE = 13,
27
+ # VTK_PYRAMID = 14, # 5 nodes, rectangular base
28
+ # VTK_PENTAGONAL_PRISM = 15,
29
+ # VTK_HEXAGONAL_PRISM = 16,
30
+
31
+ ElProp = namedtuple( 'ElProp', ['vtk_type', 'num_node'], defaults=[0] )
32
+
33
+ el_props = {
34
+ 0: ElProp(VTK_EMPTY_CELL, 0),
35
+ 5: ElProp(VTK_TRIANGLE, 3),
36
+ 9: ElProp(VTK_QUAD, 4),
37
+ 10: ElProp(VTK_TETRA, 4),
38
+ 12: ElProp(VTK_HEXAHEDRON, 8),
39
+ 13: ElProp(VTK_WEDGE, 6),
40
+ }
41
+ #MAX_CONN = 8 # increase if needed
42
+
43
+
44
+ def print_mesh_data( vtk_file_name ):
45
+
46
+ print( '==========================================================' )
47
+ print( '== MESH DATA for', vtk_file_name )
48
+ print( '==========================================================' )
49
+
50
+ mesh = pv.read( vtk_file_name )
51
+
52
+ print( 'num_points', mesh.n_points ) # nodes for all parts
53
+ print( 'num_cells', mesh.n_cells ) # for all parts
54
+
55
+
56
+ print( '\n\ndata at nodes:\n', mesh.point_data )
57
+ print( '\n\ndata at els:\n', mesh.cell_data )
58
+
59
+
60
+ print( '\n\nSOME ARRAY DATA\n' )
61
+ print( 'points', mesh.points ) # nodes for all parts
62
+
63
+ print( 'cells', mesh.cells ) # nodes for all parts
64
+
65
+
66
+ #node_ids = mesh.point_data['NODE_ID']
67
+ #print( 'node_ids', node_ids )
68
+ #print( mesh.point_data['Contact_Forces'] ) # nodes for all parts
69
+
70
+ #part_ids = mesh.cell_data['PART_ID']
71
+ #print( part_ids )
72
+ #el_ids = mesh.cell_data['ELEMENT_ID']
73
+ #print( el_ids )
74
+ #print( mesh.cell_data['3DELEM_Von_Mises'] ) # nodes for all parts
75
+
76
+ cells = mesh.GetCells()
77
+ num_cell = cells.GetNumberOfCells()
78
+ cellConns = vtk_to_numpy( cells.GetConnectivityArray() )
79
+ cellOffsets = vtk_to_numpy( cells.GetOffsetsArray() )
80
+ cellTypes = vtk_to_numpy( mesh.GetCellTypesArray() )
81
+ coords = vtk_to_numpy( mesh.GetPoints().GetData() )
82
+
83
+ #print( 'part_ids', part_ids )
84
+ print( 'cellConns', cellConns.shape, cellConns.shape[0]+num_cell, cellConns )
85
+ print( 'cellTypes', cellTypes.shape, cellTypes )
86
+ print( 'coords', coords.shape, coords )
87
+ print( 'cellOffsets', cellOffsets )
88
+ print( 'cellOffsets', cellOffsets[0] )
89
+
90
+ print( '==========================================================' )
91
+ print( '== END MESH DATA for', vtk_file_name )
92
+ print( '==========================================================\n\n' )
93
+
94
+
95
+
96
+ def read_mesh_conns( vtk_file_name, required_part_id,
97
+ node_data_names=None, el_data_names=None, el_nodal_data_names=None ):
98
+
99
+ mesh = pv.read( vtk_file_name )
100
+
101
+ node_ids = mesh.point_data['NODE_ID']
102
+
103
+ part_ids = mesh.cell_data['PART_ID']
104
+ el_ids = mesh.cell_data['ELEMENT_ID']
105
+
106
+ cells = mesh.GetCells()
107
+ num_cell = cells.GetNumberOfCells()
108
+ cellConns = vtk_to_numpy( cells.GetConnectivityArray() )
109
+ cellOffsets = vtk_to_numpy( cells.GetOffsetsArray() )
110
+ cellTypes = vtk_to_numpy( mesh.GetCellTypesArray() )
111
+ coords = vtk_to_numpy( mesh.GetPoints().GetData() )
112
+
113
+ if el_data_names :
114
+ el_data = {}
115
+ for d_name in el_data_names:
116
+ el_data[d_name] = mesh.cell_data[ d_name ]
117
+ else: el_data = None
118
+ node_data = {'node_ids':node_ids}
119
+ if node_data_names :
120
+ for d_name in node_data_names:
121
+ node_data[d_name] = mesh.point_data[ d_name ]
122
+ #else: node_data = None
123
+
124
+ if el_nodal_data_names:
125
+ el_nodal_mesh = mesh.cell_data_to_point_data()
126
+ #if node_data is None : node_data = {}
127
+ for d_name in el_nodal_data_names:
128
+ node_data[d_name] = el_nodal_mesh.point_data[ d_name ]
129
+
130
+ #
131
+ # Build connectivity matrix for required part
132
+ #
133
+
134
+ subset_el_types = []
135
+
136
+ if el_data_names:
137
+ subset_el_data = {}
138
+ for d_name in el_data_names:
139
+ subset_el_data[d_name] = []
140
+ else: subset_el_data = None
141
+
142
+ new_conn_offset = 0
143
+ new_cellCons = np.array( [], dtype=np.int64 )
144
+ new_cellOffsets = []
145
+
146
+
147
+ for i, e_type in enumerate( cellTypes ):
148
+ if el_ids[i] == 0:
149
+ pass # internal elements
150
+ elif part_ids[i] == required_part_id:
151
+ if e_type in( VTK_TRIANGLE, VTK_QUAD,VTK_HEXAHEDRON, VTK_WEDGE):
152
+ num_node = el_props[ e_type ].num_node
153
+ #assert( num_node <= MAX_CONN )
154
+ offset = cellOffsets[i]
155
+ conn = cellConns[ offset: offset+num_node]
156
+ if e_type == VTK_QUAD and conn[3] == conn[2]:
157
+ conn = conn[:-1]
158
+ e_type = VTK_TRIANGLE
159
+
160
+ subset_el_types.append( e_type )
161
+
162
+ new_cellCons = np.append( new_cellCons, conn )
163
+ new_cellOffsets.append( new_conn_offset )
164
+ new_conn_offset = new_conn_offset + len(conn)
165
+
166
+ if el_data_names:
167
+ for d_name in el_data_names:
168
+ subset_el_data[d_name].append( el_data[d_name][i] )
169
+
170
+ else:
171
+ pass
172
+
173
+ return coords, node_data, \
174
+ { 'subset_el_data':subset_el_data,
175
+ 'cell_conns':new_cellCons,
176
+ 'cell_offsets': np.array(new_cellOffsets),
177
+ 'el_types': np.array(subset_el_types) }
178
+
179
+ def compact_nodes( coords, node_data, el_dict ):
180
+ """
181
+ Remove nodes not connected to elements (of the part)
182
+ """
183
+
184
+ num_node_all = coords.shape[0]
185
+
186
+ used = np.zeros( num_node_all ).astype( bool )
187
+ new_node_idx = np.zeros( num_node_all )
188
+
189
+ cell_con = el_dict['cell_conns']
190
+ for idx in cell_con:
191
+ used[idx]=True
192
+
193
+ num_node_new = 0
194
+ for old_idx in range( num_node_all ):
195
+ if used[old_idx]:
196
+ new_node_idx[old_idx] = num_node_new
197
+ num_node_new += 1
198
+ else:
199
+ pass
200
+
201
+
202
+ # data at nodes
203
+ if node_data is not None:
204
+ node_data_subset = {}
205
+ for k in node_data.keys():
206
+ shape = list( node_data[k].shape )
207
+ shape[0] = num_node_new
208
+ node_data_subset[k] = np.zeros( shape, dtype=node_data[k].dtype )
209
+
210
+ nidx = 0
211
+ for old_idx in range( num_node_all ):
212
+ if used[old_idx]:
213
+ for k in node_data.keys():
214
+ node_data_subset[k] [ nidx ] = node_data[k][ old_idx ]
215
+ nidx += 1
216
+ else:
217
+ pass
218
+ else:
219
+ node_data_subset = None
220
+
221
+ # reset coords
222
+ coords_subset = np.zeros( (num_node_new,3), dtype=float ) # NYI 2D
223
+ nidx = 0
224
+ for old_idx in range( num_node_all ):
225
+ if used[old_idx]:
226
+ coords_subset[nidx] = coords[old_idx]
227
+ nidx += 1
228
+ else:
229
+ #print( 'idx', old_idx, 'not used' )
230
+ pass
231
+
232
+
233
+
234
+ # reset connectivity
235
+ cell_con = el_dict['cell_conns']
236
+ cell_off = el_dict['cell_offsets']
237
+ new_cell_con = np.zeros_like( cell_con)
238
+ #new_cell_off = np.zeros_like( cell_off )
239
+ for i,n_idx in enumerate( cell_con ):
240
+ new_cell_con[i] = new_node_idx[n_idx]
241
+ el_dict['cell_conns'] = new_cell_con
242
+
243
+ return coords_subset, node_data_subset
244
+
245
+
246
+ def to_cells( el_types, cell_conns, cell_offsets ):
247
+
248
+ cells = {}
249
+ for etype,ep in el_props.items() :
250
+ numn = ep.num_node
251
+ mask = np.where( el_types == etype )
252
+ oo = cell_offsets[mask]
253
+ cells[etype] = [cell_conns[k:k+numn] for k in oo]
254
+ cells = { k:np.array(v) for k,v in cells.items() }
255
+ return cells
256
+
257
+
258
+ def read_part_mesh( vtk_file_name, required_part_id,
259
+ node_data_names=None, el_data_names=None, el_nodal_data_names=None ):
260
+
261
+ coords, node_data, el_dict = read_mesh_conns( vtk_file_name,
262
+ required_part_id,
263
+ node_data_names, el_data_names, el_nodal_data_names )
264
+
265
+
266
+ coords_subset, node_data_subset = compact_nodes( coords, node_data, el_dict )
267
+
268
+ cells = to_cells( el_dict['el_types'], el_dict['cell_conns'], el_dict['cell_offsets'] )
269
+
270
+ return { 'coords' : coords_subset,
271
+ 'data' : node_data_subset,
272
+ }, \
273
+ { #'conns' : new_subset_el_conns,
274
+ #'types' : el_dict['el_types'],
275
+ #'cell_conns' : el_dict['cell_conns'],
276
+ #'cell_conn_offset' : el_dict['cell_offsets'],
277
+ 'cells' : cells,
278
+ 'data' : el_dict['subset_el_data'],
279
+ }
280
+
281
+
282
+ def to_lcl_id( trgt_ids, srcs_ids, srcs_vals):
283
+ """ remap data to follow id sorting in trgt_ids instead of srcs_ids"""
284
+ idx_for_node_id = np.full( int(trgt_ids.max())+1, -1, dtype=int )
285
+ for idx,nid in enumerate(srcs_ids):
286
+ idx_for_node_id [int(nid)] = np.where( trgt_ids==nid )[0][0]
287
+
288
+ lcl_vals = np.zeros_like( srcs_vals )
289
+ #lcl_i = np.zeros_like( trgt_ids )
290
+ for i,nid in enumerate( srcs_ids ):
291
+ lcl_vals[ idx_for_node_id[nid] ] = srcs_vals[i]
292
+ #lcl_i[ idx_for_node_id[nid] ] = nid
293
+
294
+ return lcl_vals
295
+
296
+
297
+
298
+
299
+ if __name__ == '__main__':
300
+ #fname = 'RUBBER_SEAL_IMPDISP_GEOM_001.vtk'
301
+ fname = 'test.vtk'
302
+ #fname = 'test2.vtk'
303
+ #fname = 'test2_us.vtk'
304
+
305
+ required_part_id = 3
306
+ node_data_names = [ 'NODE_ID' ]
307
+ el_data_names = [ 'ELEMENT_ID' ]
308
+
309
+ print_mesh_data( fname )
310
+
311
+ node_data, el_data = \
312
+ read_part_mesh( fname, required_part_id,
313
+ node_data_names = node_data_names,
314
+ el_data_names = el_data_names )
315
+
316
+ print( '****** NODAL' )
317
+ print( 'coords:\n', node_data['coords'] )
318
+ print( 'node_data:\n', node_data['data'])
319
+
320
+ print( '****** ELEMENTS' )
321
+ #print( 'conns:\n', el_data['conns'] )
322
+ #print( 'cell_conns:\n', el_data['cell_conns'] )
323
+ for i,e_type in enumerate( el_data['types'] ):
324
+ co = el_data['cell_conn_offset']
325
+ num_node = el_props[ e_type ].num_node
326
+ #print( e_type, co[i], el_data['cell_conns'][ co[i]:co[i]+num_node ] )
327
+ print( e_type, el_data['cell_conns'][ co[i]:co[i]+num_node ] )
328
+ print( 'data:\n', el_data['data'] )
329
+
@@ -0,0 +1,5 @@
1
+ __version__ = '0.1.0'
2
+
3
+ import logging
4
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
5
+