radia 1.0.8__py3-none-any.whl → 1.0.9__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.
@@ -0,0 +1,374 @@
1
+ """
2
+ Radia-NGSolve Field Integration
3
+
4
+ Provides arbitrary background field from NGSolve CoefficientFunction or analytical functions.
5
+
6
+ Date: 2025-10-31
7
+ """
8
+
9
+ import radia as rad
10
+ import numpy as np
11
+
12
+
13
+ def create_cf_field_source(cf, unit='m'):
14
+ """
15
+ Create Radia background field source from NGSolve CoefficientFunction.
16
+
17
+ Parameters
18
+ ----------
19
+ cf : ngsolve.CoefficientFunction or callable
20
+ NGSolve CF defining the field [Bx, By, Bz]
21
+ CF should be evaluable at (x, y, z) and return 3-vector
22
+ Can also be a Python function (x, y, z) -> [Bx, By, Bz]
23
+ unit : str, optional
24
+ Unit of CF coordinates: 'm' (meters) or 'mm' (millimeters)
25
+ Default: 'm' (NGSolve standard)
26
+
27
+ Returns
28
+ -------
29
+ int
30
+ Radia object key for the field source
31
+
32
+ Examples
33
+ --------
34
+ >>> from ngsolve import CF, x, y, z
35
+ >>> # Create spatially varying field
36
+ >>> Bx = CF(0)
37
+ >>> By = CF(0)
38
+ >>> Bz = 1.0 + 0.01 * x # Linear gradient in x
39
+ >>> B_cf = CF((Bx, By, Bz))
40
+ >>>
41
+ >>> # Register as Radia background field
42
+ >>> field_obj = create_cf_field_source(B_cf, unit='m')
43
+ >>> magnet = rad.ObjRecMag([0,0,0], [5,5,5], [0,0,1])
44
+ >>> container = rad.ObjCnt([magnet, field_obj])
45
+ >>> rad.Solve(container, 0.0001, 10000)
46
+
47
+ >>> # Check total field
48
+ >>> B_total = rad.Fld(container, 'b', [0, 0, 0])
49
+
50
+ Notes
51
+ -----
52
+ - Radia uses millimeters internally
53
+ - NGSolve typically uses meters
54
+ - This function handles unit conversion automatically
55
+ - For best performance with NGSolve CF, evaluate on a mesh with specialcf
56
+ """
57
+
58
+ # Check if cf is NGSolve CF or Python callable
59
+ has_ngsolve = False
60
+ try:
61
+ import ngsolve
62
+ has_ngsolve = True
63
+ is_ngsolve_cf = isinstance(cf, ngsolve.CoefficientFunction)
64
+ except ImportError:
65
+ is_ngsolve_cf = False
66
+
67
+ if is_ngsolve_cf:
68
+ # NGSolve CoefficientFunction: need special handling
69
+ print("Warning: Direct NGSolve CF evaluation without mesh may be limited.")
70
+ print("For best results, use create_analytical_field() with a function that")
71
+ print("evaluates the CF on a GridFunction.")
72
+
73
+ # Create wrapper for NGSolve CF
74
+ def cf_wrapper(coords):
75
+ """
76
+ Wrapper to evaluate NGSolve CF at given point.
77
+
78
+ Args:
79
+ coords: [x, y, z] in mm (Radia units)
80
+
81
+ Returns:
82
+ [Bx, By, Bz] in Tesla
83
+ """
84
+ # Convert Radia mm to NGSolve units
85
+ if unit == 'm':
86
+ x_ngs = coords[0] / 1000.0 # mm → m
87
+ y_ngs = coords[1] / 1000.0
88
+ z_ngs = coords[2] / 1000.0
89
+ else: # unit == 'mm'
90
+ x_ngs = coords[0]
91
+ y_ngs = coords[1]
92
+ z_ngs = coords[2]
93
+
94
+ try:
95
+ # Try to evaluate CF
96
+ # Note: This may not work for all CFs without a mesh context
97
+ B_value = cf(ngsolve.mesh.MakeIntegrationPoint(x_ngs, y_ngs, z_ngs))
98
+
99
+ if hasattr(B_value, '__len__') and len(B_value) >= 3:
100
+ return [float(B_value[0]), float(B_value[1]), float(B_value[2])]
101
+ elif hasattr(B_value, '__len__'):
102
+ # Scalar or less than 3 components
103
+ return [0.0, 0.0, float(B_value[0]) if len(B_value) > 0 else 0.0]
104
+ else:
105
+ # Scalar CF
106
+ return [0.0, 0.0, float(B_value)]
107
+
108
+ except Exception as e:
109
+ print(f"Warning: CF evaluation failed at ({x_ngs}, {y_ngs}, {z_ngs}): {e}")
110
+ print("Returning zero field. Consider using create_analytical_field() instead.")
111
+ return [0.0, 0.0, 0.0]
112
+
113
+ return rad.ObjBckgCF(cf_wrapper)
114
+
115
+ elif callable(cf):
116
+ # Python callable
117
+ def wrapper(coords):
118
+ """
119
+ Wrapper for Python function with unit conversion.
120
+
121
+ Args:
122
+ coords: [x, y, z] in mm (Radia units)
123
+
124
+ Returns:
125
+ [Bx, By, Bz] in Tesla
126
+ """
127
+ if unit == 'm':
128
+ x_m = coords[0] / 1000.0
129
+ y_m = coords[1] / 1000.0
130
+ z_m = coords[2] / 1000.0
131
+ return cf(x_m, y_m, z_m)
132
+ else: # unit == 'mm'
133
+ return cf(coords[0], coords[1], coords[2])
134
+
135
+ return rad.ObjBckgCF(wrapper)
136
+
137
+ else:
138
+ raise TypeError("cf must be NGSolve CoefficientFunction or Python callable")
139
+
140
+
141
+ def create_analytical_field(field_func, unit='mm'):
142
+ """
143
+ Create background field from analytical Python function.
144
+
145
+ Parameters
146
+ ----------
147
+ field_func : callable
148
+ Python function: [Bx, By, Bz] = field_func(x, y, z)
149
+ Coordinates in specified units
150
+ unit : str, optional
151
+ Unit of coordinates: 'm' or 'mm'
152
+ Default: 'mm' (Radia internal units)
153
+
154
+ Returns
155
+ -------
156
+ int
157
+ Radia object key for the field source
158
+
159
+ Examples
160
+ --------
161
+ >>> # Quadrupole field
162
+ >>> def quadrupole_field(x, y, z):
163
+ ... gradient = 10.0 # T/m
164
+ ... Bx = gradient * y / 1000 # Convert mm to m for gradient
165
+ ... By = gradient * x / 1000
166
+ ... Bz = 0.0
167
+ ... return [Bx, By, Bz]
168
+ >>>
169
+ >>> field_obj = create_analytical_field(quadrupole_field, unit='mm')
170
+ >>>
171
+ >>> # Use in Radia
172
+ >>> magnet = rad.ObjRecMag([0,0,0], [10,10,10], [0,0,1])
173
+ >>> container = rad.ObjCnt([magnet, field_obj])
174
+ >>> rad.Solve(container, 0.0001, 10000)
175
+
176
+ >>> # Linear gradient in z
177
+ >>> def gradient_field(x, y, z):
178
+ ... B0 = 1.0 # T
179
+ ... grad = 0.01 # T/mm
180
+ ... return [0, 0, B0 + grad * z]
181
+ >>>
182
+ >>> field_obj = create_analytical_field(gradient_field, unit='mm')
183
+ """
184
+
185
+ def wrapper(coords):
186
+ """
187
+ Wrapper with unit conversion.
188
+
189
+ Args:
190
+ coords: [x, y, z] in mm (Radia units)
191
+
192
+ Returns:
193
+ [Bx, By, Bz] in Tesla
194
+ """
195
+ if unit == 'mm':
196
+ return field_func(coords[0], coords[1], coords[2])
197
+ else: # unit == 'm'
198
+ x_m = coords[0] / 1000.0
199
+ y_m = coords[1] / 1000.0
200
+ z_m = coords[2] / 1000.0
201
+ return field_func(x_m, y_m, z_m)
202
+
203
+ return rad.ObjBckgCF(wrapper)
204
+
205
+
206
+ def create_uniform_field(Bx, By, Bz):
207
+ """
208
+ Create uniform background field (alternative to rad.ObjBckg).
209
+
210
+ Parameters
211
+ ----------
212
+ Bx, By, Bz : float
213
+ Uniform field components in Tesla
214
+
215
+ Returns
216
+ -------
217
+ int
218
+ Radia object key
219
+
220
+ Examples
221
+ --------
222
+ >>> # Equivalent to rad.ObjBckg([0, 0, 1.0])
223
+ >>> field_obj = create_uniform_field(0, 0, 1.0)
224
+
225
+ Notes
226
+ -----
227
+ This is provided for completeness. For uniform fields,
228
+ rad.ObjBckg() is more efficient.
229
+ """
230
+
231
+ def uniform(x, y, z):
232
+ return [Bx, By, Bz]
233
+
234
+ return create_analytical_field(uniform, unit='mm')
235
+
236
+
237
+ # Predefined field templates
238
+
239
+ def dipole_field(moment, position=(0, 0, 0), unit='m'):
240
+ """
241
+ Create magnetic dipole field.
242
+
243
+ Parameters
244
+ ----------
245
+ moment : array_like
246
+ Magnetic dipole moment [mx, my, mz] in A·m²
247
+ position : array_like, optional
248
+ Dipole position [x0, y0, z0] in specified units
249
+ Default: (0, 0, 0)
250
+ unit : str, optional
251
+ Unit of coordinates: 'm' or 'mm'
252
+ Default: 'm'
253
+
254
+ Returns
255
+ -------
256
+ int
257
+ Radia object key
258
+
259
+ Examples
260
+ --------
261
+ >>> # Dipole at origin with moment in z
262
+ >>> field_obj = dipole_field([0, 0, 1.0], unit='m')
263
+
264
+ Notes
265
+ -----
266
+ B(r) = (μ₀/4π) * (3(m·r)r/r⁵ - m/r³)
267
+ """
268
+
269
+ m = np.array(moment, dtype=float)
270
+ r0 = np.array(position, dtype=float)
271
+ mu0_4pi = 1e-7 # T·m/A
272
+
273
+ def dipole(x, y, z):
274
+ # Position relative to dipole
275
+ if unit == 'm':
276
+ r = np.array([x - r0[0], y - r0[1], z - r0[2]])
277
+ else: # mm
278
+ r = np.array([(x - r0[0])/1000, (y - r0[1])/1000, (z - r0[2])/1000])
279
+
280
+ r_mag = np.linalg.norm(r)
281
+
282
+ if r_mag < 1e-10:
283
+ # Avoid singularity at dipole location
284
+ return [0.0, 0.0, 0.0]
285
+
286
+ r3 = r_mag**3
287
+ r5 = r_mag**5
288
+
289
+ m_dot_r = np.dot(m, r)
290
+
291
+ B = mu0_4pi * (3 * m_dot_r * r / r5 - m / r3)
292
+
293
+ return [float(B[0]), float(B[1]), float(B[2])]
294
+
295
+ return create_analytical_field(dipole, unit=unit)
296
+
297
+
298
+ def solenoid_field(I, turns_per_m, radius, length, center=(0, 0, 0), unit='m'):
299
+ """
300
+ Create ideal solenoid field (uniform inside, zero outside).
301
+
302
+ Parameters
303
+ ----------
304
+ I : float
305
+ Current in Amperes
306
+ turns_per_m : float
307
+ Number of turns per meter
308
+ radius : float
309
+ Solenoid radius in specified units
310
+ length : float
311
+ Solenoid length in specified units
312
+ center : array_like, optional
313
+ Solenoid center [x0, y0, z0]
314
+ unit : str, optional
315
+ Unit: 'm' or 'mm'
316
+
317
+ Returns
318
+ -------
319
+ int
320
+ Radia object key
321
+
322
+ Examples
323
+ --------
324
+ >>> # 1000 A·turns/m solenoid, 0.1m radius, 1m long
325
+ >>> field_obj = solenoid_field(10.0, 100, 0.1, 1.0, unit='m')
326
+ """
327
+
328
+ mu0 = 4*np.pi*1e-7 # H/m
329
+ B_inside = mu0 * I * turns_per_m # T
330
+
331
+ c = np.array(center, dtype=float)
332
+
333
+ def solenoid(x, y, z):
334
+ # Check if inside solenoid
335
+ if unit == 'm':
336
+ r_perp = np.sqrt((x - c[0])**2 + (y - c[1])**2)
337
+ z_rel = z - c[2]
338
+ else: # mm
339
+ r_perp = np.sqrt((x - c[0])**2 + (y - c[1])**2) / 1000
340
+ z_rel = (z - c[2]) / 1000
341
+ radius_m = radius / 1000
342
+ length_m = length / 1000
343
+
344
+ if r_perp < radius and abs(z_rel) < length/2:
345
+ return [0.0, 0.0, B_inside]
346
+ else:
347
+ return [0.0, 0.0, 0.0]
348
+
349
+ return create_analytical_field(solenoid, unit=unit)
350
+
351
+
352
+ if __name__ == "__main__":
353
+ # Test examples
354
+ print("Radia-NGSolve Field Integration Module")
355
+ print("=======================================")
356
+ print()
357
+ print("Example usage:")
358
+ print()
359
+ print("1. Uniform field:")
360
+ print(" field = create_uniform_field(0, 0, 1.0)")
361
+ print()
362
+ print("2. Quadrupole field:")
363
+ print(" def quad(x, y, z):")
364
+ print(" g = 10.0 # T/m")
365
+ print(" return [g*y, g*x, 0]")
366
+ print(" field = create_analytical_field(quad, unit='m')")
367
+ print()
368
+ print("3. Dipole field:")
369
+ print(" field = dipole_field([0, 0, 1.0], unit='m')")
370
+ print()
371
+ print("4. With NGSolve CF:")
372
+ print(" from ngsolve import CF, x, y, z")
373
+ print(" B_cf = CF((0, 0, 1 + 0.01*x))")
374
+ print(" field = create_cf_field_source(B_cf, unit='m')")
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ PyVista-based viewer for Radia objects
4
+ This is a modern alternative to rad.ObjDrwOpenGL()
5
+ """
6
+
7
+ import sys, os
8
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'dist'))
9
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'build', 'lib', 'Release'))
10
+
11
+ import radia as rad
12
+ import numpy as np
13
+
14
+ def view_radia_object(obj, plotter=None, show=True, color=None, opacity=1.0):
15
+ """
16
+ View a Radia object using PyVista
17
+
18
+ Parameters:
19
+ -----------
20
+ obj : int
21
+ Radia object ID
22
+ plotter : pyvista.Plotter, optional
23
+ Existing plotter to add to (for combining multiple objects)
24
+ show : bool, default True
25
+ Whether to show the plotter immediately
26
+ color : str or list, optional
27
+ Color override (e.g., 'red', [1,0,0])
28
+ opacity : float, default 1.0
29
+ Opacity (0=transparent, 1=opaque)
30
+
31
+ Returns:
32
+ --------
33
+ plotter : pyvista.Plotter
34
+ The plotter object (can be reused)
35
+ """
36
+ try:
37
+ import pyvista as pv
38
+ except ImportError:
39
+ print("ERROR: PyVista is not installed.")
40
+ print("Install it with: pip install pyvista")
41
+ return None
42
+
43
+ # Get VTK data from Radia
44
+ vtk_data = rad.ObjDrwVTK(obj, 'Axes->False')
45
+
46
+ if 'polygons' not in vtk_data:
47
+ print("ERROR: No polygon data found in Radia object")
48
+ return None
49
+
50
+ poly = vtk_data['polygons']
51
+
52
+ # Extract vertices (flatten x,y,z triplets)
53
+ vertices = np.array(poly['vertices']).reshape(-1, 3)
54
+
55
+ # Extract polygon connectivity
56
+ lengths = poly['lengths']
57
+ n_polys = len(lengths)
58
+
59
+ # Build faces array for PyVista
60
+ # PyVista format: [n_points, p0, p1, p2, ..., n_points, p0, p1, ...]
61
+ faces = []
62
+ offset = 0
63
+ for length in lengths:
64
+ faces.append(length)
65
+ for i in range(length):
66
+ faces.append(offset + i)
67
+ offset += length
68
+
69
+ faces = np.array(faces)
70
+
71
+ # Create PyVista mesh
72
+ mesh = pv.PolyData(vertices, faces)
73
+
74
+ # Create or use existing plotter
75
+ if plotter is None:
76
+ plotter = pv.Plotter()
77
+ plotter.add_axes()
78
+ plotter.add_text("Radia Object Viewer (PyVista)", position='upper_left', font_size=10)
79
+
80
+ # Determine color
81
+ if color is None:
82
+ # Use Radia's color if available
83
+ colors = poly.get('colors', None)
84
+ if colors is not None and len(colors) > 0:
85
+ # Use first color (all polygons typically same color)
86
+ rgb = colors[0:3]
87
+ # Radia uses -1 for default, convert to actual color
88
+ if rgb[0] < 0:
89
+ color = 'lightblue'
90
+ else:
91
+ color = rgb
92
+
93
+ # Add mesh to plotter
94
+ plotter.add_mesh(mesh, color=color, opacity=opacity, show_edges=True,
95
+ edge_color='black', line_width=0.5)
96
+
97
+ if show:
98
+ plotter.show()
99
+
100
+ return plotter
101
+
102
+
103
+ def view_radia_vtk_file(filename):
104
+ """
105
+ View a VTK file generated by exportGeometryToVTK
106
+
107
+ Parameters:
108
+ -----------
109
+ filename : str
110
+ Path to .vtk file
111
+ """
112
+ try:
113
+ import pyvista as pv
114
+ except ImportError:
115
+ print("ERROR: PyVista is not installed.")
116
+ print("Install it with: pip install pyvista")
117
+ return
118
+
119
+ # Read VTK file
120
+ mesh = pv.read(filename)
121
+
122
+ # Create plotter
123
+ plotter = pv.Plotter()
124
+ plotter.add_axes()
125
+ plotter.add_text(f"Viewing: {os.path.basename(filename)}",
126
+ position='upper_left', font_size=10)
127
+
128
+ # Add mesh
129
+ plotter.add_mesh(mesh, show_edges=True, edge_color='black', line_width=0.5)
130
+
131
+ # Show
132
+ plotter.show()
133
+
134
+
135
+ if __name__ == '__main__':
136
+ print("="*60)
137
+ print("Radia PyVista Viewer Demo")
138
+ print("="*60)
139
+
140
+ # Check if PyVista is available
141
+ try:
142
+ import pyvista as pv
143
+ print(f"\nPyVista version: {pv.__version__}")
144
+ except ImportError:
145
+ print("\nERROR: PyVista is not installed.")
146
+ print("Install it with:")
147
+ print(" pip install pyvista")
148
+ sys.exit(1)
149
+
150
+ # Create a simple test object
151
+ print("\nCreating test objects...")
152
+
153
+ # Arc current
154
+ g1 = rad.ObjArcCur([0,0,0], [95, 105], [0, 2*np.pi], 20, 36, 1e6/20/10, "man")
155
+
156
+ # Rectangular magnet
157
+ g2 = rad.ObjRecMag([0,0,0], [30,30,10], [0,0,1])
158
+
159
+ # Container
160
+ g = rad.ObjCnt([g1, g2])
161
+
162
+ print("Objects created. Opening PyVista viewer...")
163
+ print("\nControls:")
164
+ print(" - Left click + drag: Rotate")
165
+ print(" - Right click + drag: Pan")
166
+ print(" - Scroll wheel: Zoom")
167
+ print(" - 'q': Quit")
168
+
169
+ # View the object
170
+ view_radia_object(g)
171
+
172
+ print("\nViewer closed.")
@@ -0,0 +1,134 @@
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: radia
3
- Version: 1.0.8
3
+ Version: 1.0.9
4
4
  Summary: Radia 3D Magnetostatics with NGSolve Integration and OpenMP Parallelization
5
5
  Home-page: https://github.com/ksugahar/Radia_NGSolve
6
6
  Author: Pascal Elleaume
@@ -0,0 +1,13 @@
1
+ python/__init__.py,sha256=o4JtQw0g5WcRpQAUi97FgL5BIUAlfMBrn4442GGdGuc,47
2
+ python/nastran_reader.py,sha256=r4K2LJvHBtvBumbinbiQeyPA42iyvxNyAd6Y05lxeZs,10035
3
+ python/rad_ngsolve.pyd,sha256=pfLmNoFQtTqS_Uzey4v3WWwD_KpqrOjuZeXuK1_8LEs,576512
4
+ python/radia.pyd,sha256=aSCAxppUbllAM0AJPOKvHxBQ_Iio61U0uiosZevirOk,1820672
5
+ python/radia_coil_builder.py,sha256=nQkiAbfhueNvvxUARHdPD0C68ImidHmUQv_q4RsImeY,11253
6
+ python/radia_ngsolve_field.py,sha256=suJr4wacfYFKOkyV-5AQuHWnW5rtUMb0gSSjq8VRSXc,10166
7
+ python/radia_pyvista_viewer.py,sha256=JS33Mx4azGI7hUX0bzefc6zJfhv6qfRjM3Kl1bE9Mjs,4275
8
+ python/radia_vtk_export.py,sha256=UbPvo7ftHYLREz6TSpWrpLw7JesFhMA58-22R63HHH4,3997
9
+ radia-1.0.9.dist-info/licenses/LICENSE,sha256=Db6_UKUk2lyGv0e4MMLNG74LJ-aep64N2FEYQ8eA9DU,29796
10
+ radia-1.0.9.dist-info/METADATA,sha256=iN0Z0S9aCOvMKldmXLbpDseSBciwPOarHz84E01fLgE,12323
11
+ radia-1.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
+ radia-1.0.9.dist-info/top_level.txt,sha256=J-z0poNcsv31IHB413--iOY8LoHBKiTHeybHX3abokI,7
13
+ radia-1.0.9.dist-info/RECORD,,