radia 1.3.3__py3-none-any.whl → 1.3.5__py3-none-any.whl

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.
python/nastran_reader.py DELETED
@@ -1,295 +0,0 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
- """
4
- Nastran Mesh Reader for Radia
5
-
6
- Reads Nastran .nas/.bdf files and converts to Python data structures.
7
- Supports GRID (nodes), CHEXA (hexahedron), CPENTA (pentahedron), CTETRA (tetrahedron), and CTRIA3 (triangle) elements.
8
-
9
- For surface meshes (CTRIA3), triangles with the same material ID (PID) are grouped into a single polyhedron,
10
- which is useful for linear magnetic analysis where only the surface representation is needed.
11
-
12
- Usage:
13
- from nastran_reader import read_nastran_mesh
14
-
15
- mesh = read_nastran_mesh('sphere.bdf')
16
- nodes = mesh['nodes'] # numpy array (N, 3)
17
- hex_elements = mesh['hex_elements'] # list of [n1, ..., n8]
18
- penta_elements = mesh['penta_elements'] # list of [n1, ..., n6]
19
- tetra_elements = mesh['tetra_elements'] # list of [n1, ..., n4]
20
- tria_groups = mesh['tria_groups'] # dict {material_id: {'faces': [[n1,n2,n3], ...], 'nodes': set(...)}}
21
-
22
- Date: 2025-11-01
23
- """
24
-
25
- import re
26
- import numpy as np
27
-
28
-
29
- def read_nastran_mesh(filename, verbose=True):
30
- """
31
- Read Nastran mesh file (.nas/.bdf format).
32
-
33
- Args:
34
- filename: Path to .nas or .bdf file
35
- verbose: Print progress messages (default: True)
36
-
37
- Returns:
38
- dict: Dictionary with mesh data
39
- - nodes: numpy array (N, 3) with node coordinates [mm]
40
- - hex_elements: list of hexahedra [n1, n2, n3, n4, n5, n6, n7, n8]
41
- - penta_elements: list of pentahedra [n1, n2, n3, n4, n5, n6]
42
- - tetra_elements: list of tetrahedra [n1, n2, n3, n4]
43
- - tria_groups: dict {material_id: {'faces': [[n1,n2,n3], ...], 'nodes': set(node_ids)}}
44
- - node_ids: dict mapping node_id to array index
45
- - node_id_list: list of node IDs in order
46
- """
47
- if verbose:
48
- print(f"Reading Nastran mesh: {filename}")
49
-
50
- with open(filename, 'r') as f:
51
- lines = f.readlines()
52
-
53
- # Parse GRID entries
54
- nodes = {} # node_id -> [x, y, z]
55
- hex_elements = [] # List of [n1, n2, n3, n4, n5, n6, n7, n8]
56
- penta_elements = [] # List of [n1, n2, n3, n4, n5, n6]
57
- tetra_elements = [] # List of [n1, n2, n3, n4]
58
- tria_groups = {} # material_id -> {'faces': [[n1,n2,n3], ...], 'nodes': set(node_ids)}
59
-
60
- i = 0
61
- while i < len(lines):
62
- line = lines[i].rstrip('\n')
63
-
64
- # Parse GRID* lines (Extended format with continuation)
65
- if line.startswith('GRID*'):
66
- try:
67
- # GRID* ID CP X1 X2
68
- # * X3
69
- # Field width: 16 characters
70
- node_id = int(line[8:24].strip())
71
- # Skip CP field (line[24:40])
72
- x = float(line[40:56].strip())
73
- y = float(line[56:72].strip())
74
-
75
- # Get continuation line for Z coordinate
76
- i += 1
77
- cont_line = lines[i].rstrip('\n')
78
- z = float(cont_line[8:24].strip())
79
-
80
- nodes[node_id] = [x, y, z]
81
- except (ValueError, IndexError) as e:
82
- if verbose:
83
- print(f"Warning: Failed to parse GRID* line {i}: {e}")
84
-
85
- # Parse GRID lines (Fixed format: 8 characters per field)
86
- elif line.startswith('GRID') and not line.startswith('GRID*'):
87
- try:
88
- # GRID ID CP X1 X2 X3
89
- # 01234567890123456789012345678901234567890123456789
90
- node_id = int(line[8:16])
91
- x = float(line[24:32])
92
- y = float(line[32:40])
93
- z = float(line[40:48])
94
- nodes[node_id] = [x, y, z]
95
- except ValueError as e:
96
- if verbose:
97
- print(f"Warning: Failed to parse GRID line {i+1}: {e}")
98
-
99
- # Parse CHEXA lines (Hexahedron with continuation)
100
- elif line.startswith('CHEXA'):
101
- try:
102
- # CHEXA EID PID G1 G2 G3 G4 G5 G6 +
103
- # + G7 G8
104
- # Get nodes from first line (6 nodes)
105
- n1 = int(line[24:32].strip())
106
- n2 = int(line[32:40].strip())
107
- n3 = int(line[40:48].strip())
108
- n4 = int(line[48:56].strip())
109
- n5 = int(line[56:64].strip())
110
- n6 = int(line[64:72].strip())
111
-
112
- # Get continuation line
113
- i += 1
114
- cont_line = lines[i].rstrip('\n')
115
- # + G7 G8
116
- n7 = int(cont_line[14:22].strip())
117
- n8 = int(cont_line[22:30].strip())
118
-
119
- hex_elements.append([n1, n2, n3, n4, n5, n6, n7, n8])
120
- except (ValueError, IndexError) as e:
121
- if verbose:
122
- print(f"Warning: Failed to parse CHEXA at line {i}: {e}")
123
-
124
- # Parse CPENTA lines (Pentahedron, single line)
125
- elif line.startswith('CPENTA'):
126
- try:
127
- # CPENTA EID PID G1 G2 G3 G4 G5 G6
128
- # All 6 nodes on one line
129
- n1 = int(line[24:32])
130
- n2 = int(line[32:40])
131
- n3 = int(line[40:48])
132
- n4 = int(line[48:56])
133
- n5 = int(line[56:64])
134
- n6 = int(line[64:72])
135
-
136
- penta_elements.append([n1, n2, n3, n4, n5, n6])
137
- except (ValueError, IndexError) as e:
138
- if verbose:
139
- print(f"Warning: Failed to parse CPENTA at line {i}: {e}")
140
-
141
- # Parse CTETRA lines (Tetrahedron, single line)
142
- elif line.startswith('CTETRA'):
143
- try:
144
- # CTETRA EID PID G1 G2 G3 G4
145
- # All 4 nodes on one line (10-node tetra has continuation, but we only use first 4)
146
- n1 = int(line[24:32])
147
- n2 = int(line[32:40])
148
- n3 = int(line[40:48])
149
- n4 = int(line[48:56])
150
-
151
- tetra_elements.append([n1, n2, n3, n4])
152
- except (ValueError, IndexError) as e:
153
- if verbose:
154
- print(f"Warning: Failed to parse CTETRA at line {i}: {e}")
155
-
156
- # Parse CTRIA3 lines (Triangle, single line)
157
- elif line.startswith('CTRIA3'):
158
- try:
159
- # CTRIA3 EID PID G1 G2 G3
160
- # Element ID, Property ID (material), and 3 node IDs
161
- element_id = int(line[8:16].strip())
162
- material_id = int(line[16:24].strip())
163
- n1 = int(line[24:32].strip())
164
- n2 = int(line[32:40].strip())
165
- n3 = int(line[40:48].strip())
166
-
167
- # Group triangles by material ID
168
- if material_id not in tria_groups:
169
- tria_groups[material_id] = {'faces': [], 'nodes': set()}
170
-
171
- tria_groups[material_id]['faces'].append([n1, n2, n3])
172
- tria_groups[material_id]['nodes'].update([n1, n2, n3])
173
- except (ValueError, IndexError) as e:
174
- if verbose:
175
- print(f"Warning: Failed to parse CTRIA3 at line {i}: {e}")
176
-
177
- i += 1
178
-
179
- # Convert to numpy arrays
180
- node_ids = sorted(nodes.keys())
181
- node_id_to_idx = {nid: idx for idx, nid in enumerate(node_ids)}
182
-
183
- nodes_array = np.array([nodes[nid] for nid in node_ids])
184
- hex_array = np.array(hex_elements, dtype=int) if hex_elements else np.array([])
185
- penta_array = np.array(penta_elements, dtype=int) if penta_elements else np.array([])
186
- tetra_array = np.array(tetra_elements, dtype=int) if tetra_elements else np.array([])
187
-
188
- if verbose:
189
- print(f" Nodes: {len(nodes_array)}")
190
- print(f" Elements (CHEXA): {len(hex_elements)}")
191
- print(f" Elements (CPENTA): {len(penta_elements)}")
192
- print(f" Elements (CTETRA): {len(tetra_elements)}")
193
- if tria_groups:
194
- total_trias = sum(len(group['faces']) for group in tria_groups.values())
195
- print(f" Elements (CTRIA3): {total_trias} triangles in {len(tria_groups)} material group(s)")
196
- for mat_id, group in tria_groups.items():
197
- print(f" Material {mat_id}: {len(group['faces'])} triangles, {len(group['nodes'])} unique nodes")
198
- total_elements = len(hex_elements) + len(penta_elements) + len(tetra_elements)
199
- if not tria_groups:
200
- print(f" Total elements: {total_elements}")
201
-
202
- return {
203
- 'nodes': nodes_array,
204
- 'hex_elements': hex_array,
205
- 'penta_elements': penta_array,
206
- 'tetra_elements': tetra_array,
207
- 'tria_groups': tria_groups,
208
- 'node_ids': node_id_to_idx,
209
- 'node_id_list': node_ids
210
- }
211
-
212
-
213
- # Element face connectivity for Radia ObjPolyhdr
214
- # Node numbering is 1-indexed (as used in connectivity arrays)
215
-
216
- # Hexahedron face connectivity (1-indexed)
217
- # Nastran CHEXA node numbering:
218
- # Nodes: G1, G2, G3, G4 (bottom), G5, G6, G7, G8 (top)
219
- HEX_FACES = [
220
- [1, 2, 3, 4], # Bottom face
221
- [5, 6, 7, 8], # Top face
222
- [1, 2, 6, 5], # Side face 1
223
- [2, 3, 7, 6], # Side face 2
224
- [3, 4, 8, 7], # Side face 3
225
- [4, 1, 5, 8], # Side face 4
226
- ]
227
-
228
- # Pentahedron face connectivity (1-indexed)
229
- # Nastran CPENTA node numbering:
230
- # Nodes: G1, G2, G3 (bottom triangle), G4, G5, G6 (top triangle)
231
- PENTA_FACES = [
232
- [1, 2, 3], # Bottom triangle
233
- [4, 5, 6], # Top triangle
234
- [1, 2, 5, 4], # Side face 1 (quad)
235
- [2, 3, 6, 5], # Side face 2 (quad)
236
- [3, 1, 4, 6], # Side face 3 (quad)
237
- ]
238
-
239
- # Tetrahedron face connectivity (1-indexed)
240
- # Nastran CTETRA node numbering:
241
- # Nodes: G1, G2, G3, G4
242
- TETRA_FACES = [
243
- [1, 2, 3], # Face 1
244
- [1, 4, 2], # Face 2
245
- [2, 4, 3], # Face 3
246
- [3, 4, 1], # Face 4
247
- ]
248
-
249
-
250
- if __name__ == '__main__':
251
- """Test the Nastran reader"""
252
- import os
253
- import sys
254
-
255
- # Try to find a test .bdf file
256
- test_files = [
257
- '../../examples/electromagnet/York.bdf',
258
- '../../examples/NGSolve_CoefficientFunction_to_Radia_BackgroundField/sphere.bdf',
259
- ]
260
-
261
- nas_file = None
262
- for f in test_files:
263
- if os.path.exists(f):
264
- nas_file = f
265
- break
266
-
267
- if nas_file:
268
- mesh = read_nastran_mesh(nas_file)
269
-
270
- print("\nMesh statistics:")
271
- print(f" Total nodes: {len(mesh['nodes'])}")
272
- print(f" Hexahedra (CHEXA): {len(mesh['hex_elements'])}")
273
- print(f" Pentahedra (CPENTA): {len(mesh['penta_elements'])}")
274
- print(f" Tetrahedra (CTETRA): {len(mesh['tetra_elements'])}")
275
- print(f"\nFirst 5 nodes:")
276
- for i in range(min(5, len(mesh['nodes']))):
277
- print(f" Node {mesh['node_id_list'][i]}: {mesh['nodes'][i]}")
278
-
279
- if len(mesh['hex_elements']) > 0:
280
- print(f"\nFirst 3 hexahedra (node IDs):")
281
- for i in range(min(3, len(mesh['hex_elements']))):
282
- print(f" Hex {i+1}: {mesh['hex_elements'][i]}")
283
-
284
- if len(mesh['penta_elements']) > 0:
285
- print(f"\nFirst 3 pentahedra (node IDs):")
286
- for i in range(min(3, len(mesh['penta_elements']))):
287
- print(f" Penta {i+1}: {mesh['penta_elements'][i]}")
288
-
289
- if len(mesh['tetra_elements']) > 0:
290
- print(f"\nFirst 3 tetrahedra (node IDs):")
291
- for i in range(min(3, len(mesh['tetra_elements']))):
292
- print(f" Tetra {i+1}: {mesh['tetra_elements'][i]}")
293
- else:
294
- print(f"Error: No test .bdf files found")
295
- print(f"Searched for: {test_files}")
python/radia.pyd DELETED
Binary file
@@ -1,134 +0,0 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
- """
4
- Radia VTK Export Utilities
5
-
6
- Functions for exporting Radia geometry to VTK format for visualization
7
- in ParaView and other VTK-compatible tools.
8
- """
9
-
10
- import radia as rad
11
- import csv
12
- from itertools import accumulate
13
-
14
- def chunks(lst, n):
15
- """
16
- Yield successive n-sized chunks from a list.
17
-
18
- Args:
19
- lst: List to be chunked
20
- n: Chunk size
21
-
22
- Yields:
23
- Chunks of size n from the input list
24
- """
25
- for i in range(0, len(lst), n):
26
- yield lst[i:i + n]
27
-
28
- def exportGeometryToVTK(obj, fileName='radia_Geometry'):
29
- """
30
- Export Radia object geometry to VTK Legacy format file.
31
-
32
- Writes the geometry of a Radia object to a .vtk file for visualization
33
- in ParaView. The format is VTK Legacy (ASCII), consisting of polygons only.
34
-
35
- Args:
36
- obj: Radia object ID (integer)
37
- fileName: Output filename without extension (default: 'radia_Geometry')
38
-
39
- Output:
40
- Creates fileName.vtk in the current directory
41
-
42
- Example:
43
- >>> import radia as rad
44
- >>> from radia_vtk_export import exportGeometryToVTK
45
- >>> mag = rad.ObjRecMag([0,0,0], [10,10,10], [0,0,1])
46
- >>> exportGeometryToVTK(mag, 'my_magnet')
47
- """
48
-
49
- vtkData = rad.ObjDrwVTK(obj, 'Axes->False')
50
-
51
- lengths = vtkData['polygons']['lengths']
52
- nPoly = len(lengths)
53
- offsets = list(accumulate(lengths))
54
- offsets.insert(0, 0) # prepend list with a zero
55
- points = vtkData['polygons']['vertices']
56
- nPnts = int(len(points)/3)
57
-
58
- # format the points array to be floats rather than double
59
- points = [round(num/1000.0, 8) for num in points]
60
- # Note: Converted from mm (Radia units) to m
61
- # define the connectivity list
62
- conn = list(range(nPnts))
63
- # define colours array
64
- colors = vtkData['polygons']['colors']
65
-
66
- # pre-process the output lists to have chunkLength items per line
67
- chunkLength = 9 # this writes 9 numbers per line (9 is the number used in Paraview if data is saved as the VTK Legacy format)
68
- offsets = list(chunks(offsets, chunkLength))
69
- points = list(chunks(points, chunkLength))
70
- conn = list(chunks(conn, chunkLength))
71
- colors = list(chunks(colors, chunkLength))
72
-
73
- # write the data to file
74
- with open(fileName + ".vtk", "w", newline="") as f:
75
- f.write('# vtk DataFile Version 5.1\n')
76
- f.write('vtk output\nASCII\nDATASET POLYDATA\n')
77
- f.write('POINTS ' + str(nPnts) + ' float\n')
78
- writer = csv.writer(f, delimiter=" ")
79
- writer.writerows(points)
80
- f.write('\n')
81
- f.write('POLYGONS ' + str(nPoly+1) + ' ' + str(nPnts) + '\n')
82
- f.write('OFFSETS vtktypeint64\n')
83
- writer.writerows(offsets)
84
- f.write('CONNECTIVITY vtktypeint64\n')
85
- writer.writerows(conn)
86
- f.write('\n')
87
- f.write('CELL_DATA ' + str(nPoly) + '\n')
88
- f.write('COLOR_SCALARS Radia_colours 3\n')
89
- writer.writerows(colors)
90
-
91
- print(f"VTK file exported: {fileName}.vtk")
92
- print(f" Polygons: {nPoly}")
93
- print(f" Points: {nPnts}")
94
-
95
-
96
- if __name__ == '__main__':
97
- """
98
- Demo: Export a simple Radia geometry to VTK format
99
- """
100
- import sys
101
- import os
102
-
103
- # Add build directory to path
104
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'build', 'lib', 'Release'))
105
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'dist'))
106
-
107
- print("=" * 60)
108
- print("Radia VTK Export Demo")
109
- print("=" * 60)
110
-
111
- # Create a simple test geometry
112
- print("\nCreating test geometry...")
113
-
114
- # Rectangular magnet
115
- mag = rad.ObjRecMag([0, 0, 0], [30, 30, 10], [0, 0, 1])
116
-
117
- # Cylindrical magnet
118
- cyl = rad.ObjCylMag([50, 0, 0], 15, 20, 16, 'z', [0, 0, 1])
119
-
120
- # Container
121
- container = rad.ObjCnt([mag, cyl])
122
-
123
- # Export to VTK
124
- output_file = 'radia_demo_geometry'
125
- print(f"\nExporting geometry to {output_file}.vtk...")
126
- exportGeometryToVTK(container, output_file)
127
-
128
- print("\n" + "=" * 60)
129
- print("Export complete!")
130
- print("\nTo view in ParaView:")
131
- print(f" 1. Open ParaView")
132
- print(f" 2. File → Open → {output_file}.vtk")
133
- print(f" 3. Click 'Apply' in the Properties panel")
134
- print("=" * 60)
@@ -1,15 +0,0 @@
1
- python/__init__.py,sha256=oUOAjf_vY8DNy5HRU7oArAMic8urvHCR9yHSi4HFkkQ,47
2
- python/nastran_reader.py,sha256=r4K2LJvHBtvBumbinbiQeyPA42iyvxNyAd6Y05lxeZs,10035
3
- python/rad_ngsolve.pyd,sha256=s5ZvpTIrjYeV_B3vQv5HrtP4u_RaPhvxuZf5aKv3oC0,566272
4
- python/rad_ngsolve_fast.py,sha256=GkC7ruKy3MESHsO0iRSWsrgLU4-DPPgctOi6pPpsWg4,5675
5
- python/radia.pyd,sha256=n9nOJQAzLDaoifMEMvHT160o7RIONFRINa3kdSvbjFE,1811968
6
- python/radia_coil_builder.py,sha256=nQkiAbfhueNvvxUARHdPD0C68ImidHmUQv_q4RsImeY,11253
7
- python/radia_field_cached.py,sha256=_9w9ETludvkoCx5Qiy6hXvmR7aJ_fzJXof2aF7JqM2Y,9235
8
- python/radia_ngsolve_field.py,sha256=suJr4wacfYFKOkyV-5AQuHWnW5rtUMb0gSSjq8VRSXc,10166
9
- python/radia_pyvista_viewer.py,sha256=JS33Mx4azGI7hUX0bzefc6zJfhv6qfRjM3Kl1bE9Mjs,4275
10
- python/radia_vtk_export.py,sha256=UbPvo7ftHYLREz6TSpWrpLw7JesFhMA58-22R63HHH4,3997
11
- radia-1.3.3.dist-info/licenses/LICENSE,sha256=a8e7Y3GCWv0nE5mpUTUbnjCAKgZadruvJSkJrZWIaCA,4281
12
- radia-1.3.3.dist-info/METADATA,sha256=kVPOR6CHhW7wcGzKdT4R3eUgvP_72xVTrDB-_TNITk0,13329
13
- radia-1.3.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
- radia-1.3.3.dist-info/top_level.txt,sha256=J-z0poNcsv31IHB413--iOY8LoHBKiTHeybHX3abokI,7
15
- radia-1.3.3.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- python
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes