OpenFUSIONToolkit 26.6__py3-none-macosx_14_0_arm64.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.
Files changed (39) hide show
  1. OpenFUSIONToolkit/Marklin/__init__.py +14 -0
  2. OpenFUSIONToolkit/Marklin/_core.py +309 -0
  3. OpenFUSIONToolkit/Marklin/_interface.py +55 -0
  4. OpenFUSIONToolkit/ThinCurr/__init__.py +14 -0
  5. OpenFUSIONToolkit/ThinCurr/_core.py +899 -0
  6. OpenFUSIONToolkit/ThinCurr/_interface.py +121 -0
  7. OpenFUSIONToolkit/ThinCurr/coils.py +208 -0
  8. OpenFUSIONToolkit/ThinCurr/meshing.py +440 -0
  9. OpenFUSIONToolkit/ThinCurr/sensor.py +107 -0
  10. OpenFUSIONToolkit/ThinCurr/util.py +733 -0
  11. OpenFUSIONToolkit/TokaMaker/__init__.py +14 -0
  12. OpenFUSIONToolkit/TokaMaker/_core.py +3219 -0
  13. OpenFUSIONToolkit/TokaMaker/_interface.py +310 -0
  14. OpenFUSIONToolkit/TokaMaker/bootstrap.py +1111 -0
  15. OpenFUSIONToolkit/TokaMaker/eqdsk.py +2455 -0
  16. OpenFUSIONToolkit/TokaMaker/meshing.py +1264 -0
  17. OpenFUSIONToolkit/TokaMaker/pulse_design.py +5351 -0
  18. OpenFUSIONToolkit/TokaMaker/reconstruction.py +949 -0
  19. OpenFUSIONToolkit/TokaMaker/util.py +553 -0
  20. OpenFUSIONToolkit/__init__.py +15 -0
  21. OpenFUSIONToolkit/_core.py +280 -0
  22. OpenFUSIONToolkit/_interface.py +133 -0
  23. OpenFUSIONToolkit/io.py +457 -0
  24. OpenFUSIONToolkit/libgcc_s.1.1.dylib +0 -0
  25. OpenFUSIONToolkit/libgfortran.5.dylib +0 -0
  26. OpenFUSIONToolkit/libgomp.1.dylib +0 -0
  27. OpenFUSIONToolkit/libhdf5.310.dylib +0 -0
  28. OpenFUSIONToolkit/libhdf5_fortran.310.dylib +0 -0
  29. OpenFUSIONToolkit/liboft.dylib +0 -0
  30. OpenFUSIONToolkit/liboft_triangle.dylib +0 -0
  31. OpenFUSIONToolkit/liboftpy.dylib +0 -0
  32. OpenFUSIONToolkit/libquadmath.0.dylib +0 -0
  33. OpenFUSIONToolkit/libstdc++.6.dylib +0 -0
  34. OpenFUSIONToolkit/util.py +323 -0
  35. openfusiontoolkit-26.6.dist-info/METADATA +83 -0
  36. openfusiontoolkit-26.6.dist-info/RECORD +39 -0
  37. openfusiontoolkit-26.6.dist-info/WHEEL +5 -0
  38. openfusiontoolkit-26.6.dist-info/licenses/LICENSE +165 -0
  39. openfusiontoolkit-26.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,14 @@
1
+ #------------------------------------------------------------------------------
2
+ # Flexible Unstructured Simulation Infrastructure with Open Numerics (Open FUSION Toolkit)
3
+ #
4
+ # SPDX-License-Identifier: LGPL-3.0-only
5
+ #------------------------------------------------------------------------------
6
+ '''! Python interface for Marklin force-free ideal MHD equilibrium functionality
7
+
8
+ @authors Chris Hansen
9
+ @date September 2023
10
+ @ingroup doxy_oft_python
11
+ '''
12
+ from ._core import Marklin
13
+
14
+ __all__ = ["Marklin"]
@@ -0,0 +1,309 @@
1
+ #------------------------------------------------------------------------------
2
+ # Flexible Unstructured Simulation Infrastructure with Open Numerics (Open FUSION Toolkit)
3
+ #
4
+ # SPDX-License-Identifier: LGPL-3.0-only
5
+ #------------------------------------------------------------------------------
6
+ '''! Core definitions for Marklin force-free ideal MHD equilibrium functionality
7
+
8
+ @authors Chris Hansen
9
+ @date September 2023
10
+ @ingroup doxy_oft_python
11
+ '''
12
+ import warnings
13
+ import numpy
14
+ from ._interface import *
15
+ from ..io import build_XDMF
16
+
17
+
18
+ class Marklin_field_interpolator():
19
+ '''! Interpolation class for force-free eigenstate vector fields'''
20
+ def __init__(self,marklin_obj,int_ptr,int_type,dim,fbary_tol=1.E-8):
21
+ '''! Initialize interpolation object
22
+
23
+ @param marklin_obj Marklin instance for interpolator
24
+ @param int_ptr Address of FORTRAN interpolation class
25
+ @param int_type Interpolation type (1: vector potential; 2: magnetic field)
26
+ @param dim Dimension of vector field
27
+ @param fbary_tol Tolerance for physical to logical mapping
28
+ '''
29
+ self.cell = c_int(-1)
30
+ self.int_type = int_type
31
+ self.dim = dim
32
+ self.val = numpy.zeros((self.dim,), dtype=numpy.float64)
33
+ self.marklin_obj = marklin_obj
34
+ self._int_ptr = int_ptr
35
+ self.fbary_tol = fbary_tol
36
+
37
+ def __del__(self):
38
+ '''Destroy underlying interpolation object'''
39
+ pt_eval = numpy.zeros((3,), dtype=numpy.float64)
40
+ marklin_apply_int(self.marklin_obj._marklin_ptr,self._int_ptr,-self.int_type,pt_eval,self.fbary_tol,ctypes.byref(self.cell),self.val)
41
+
42
+ def eval(self,pt):
43
+ '''! Evaluate field at a given location
44
+
45
+ @param pt Location for evaluation [3]
46
+ @result Field at evaluation point [self.dim]
47
+ '''
48
+ marklin_apply_int(self.marklin_obj._marklin_ptr,self._int_ptr,self.int_type,pt,self.fbary_tol,ctypes.byref(self.cell),self.val)
49
+ return self.val
50
+
51
+
52
+ class Marklin():
53
+ '''! Marklin force-free equilibrium solver class'''
54
+ def __init__(self,OFT_env):
55
+ '''! Initialize Marklin object
56
+
57
+ @param OFT_env OFT runtime environment object (See @ref OpenFUSIONToolkit._core.OFT_env "OFT_env")
58
+ '''
59
+ ## OFT execution environment
60
+ self._oft_env = OFT_env
61
+ ## Internal Marklin solver object
62
+ self._marklin_ptr = c_void_p()
63
+ ## Internal mesh object
64
+ self._mesh_ptr = c_void_p()
65
+ ## Number of regions in mesh
66
+ self.nregs = -1
67
+ ## Number of points in mesh
68
+ self.np = -1
69
+ ## Number of cells in mesh
70
+ self.nc = -1
71
+ ## Mesh vertices [np,3] (last column should be all zeros)
72
+ self.r = None
73
+ ## Mesh triangles [nc,3]
74
+ self.lc = None
75
+ ## Mesh regions [nc]
76
+ self.reg = None
77
+ ## Number of modes
78
+ self.nm = 0
79
+ ## Needs docs
80
+ self.nh = 0
81
+ ## Needs docs
82
+ self.hcpc = None
83
+ ## Needs docs
84
+ self.hcpv = None
85
+ ## Eigenvalues
86
+ self.eig_vals = None
87
+ ## I/O basepath for plotting/XDMF output
88
+ self._io_basepath = "."
89
+
90
+ def __del__(self):
91
+ if not self._marklin_ptr:
92
+ return # Nothing to do
93
+ error_string = self._oft_env.get_c_errorbuff()
94
+ marklin_destroy(self._marklin_ptr,error_string)
95
+ if error_string.value != b'':
96
+ raise Exception(error_string.value)
97
+
98
+ def print_ascii_logo(self, italic=True):
99
+ '''! Print Marklin ASCII logo
100
+
101
+ @param italic Print italicized logo?'''
102
+ if italic:
103
+ print(r'''
104
+ __ ___ __ ___
105
+ / |/ /___ ______/ /__/ (_)___
106
+ / /|_/ / __ `/ ___/ //_/ / / __ \
107
+ / / / / /_/ / / / ,< / / / / / /
108
+ /_/ /_/\__,_/_/ /_/|_/_/_/_/ /_/
109
+ ''')
110
+ else:
111
+ print(r'''
112
+ __ __ _ _ _
113
+ | \/ | __ _ _ __| | _| (_)_ __
114
+ | |\/| |/ _` | '__| |/ / | | '_ \
115
+ | | | | (_| | | | <| | | | | |
116
+ |_| |_|\__,_|_| |_|\_\_|_|_| |_|
117
+ ''')
118
+
119
+ def setup_mesh(self,r=None,lc=None,reg=None,mesh_file=None,grid_order=1):
120
+ '''! Setup mesh for Marklin force-free equilibrium calculations
121
+
122
+ A mesh should be specified by passing "r", "lc", and optionally "reg" or using a "mesh_file".
123
+
124
+ @param r Mesh point list [np,3]
125
+ @param lc Mesh cell list [nc,4] (base one)
126
+ @param reg Mesh region list [nc] (base one)
127
+ @param mesh_file Filename containing mesh to load (native format only)
128
+ '''
129
+ if self.nregs != -1:
130
+ raise ValueError('Mesh already setup, must call "reset" before loading new mesh')
131
+ nregs = c_int()
132
+ if mesh_file is not None:
133
+ np = c_int(-1)
134
+ rfake = numpy.ones((1,1),dtype=numpy.float64)
135
+ lcfake = numpy.ones((1,1),dtype=numpy.int32)
136
+ regfake = numpy.ones((1,),dtype=numpy.int32)
137
+ self._oft_env.oft_in_groups['mesh_options'] = {
138
+ 'cad_type': "0",
139
+ 'grid_order': '{0:d}'.format(grid_order)
140
+ }
141
+ self._oft_env.oft_in_groups['native_mesh_options'] = {'filename': '"{0}"'.format(mesh_file)}
142
+ self._oft_env.update_oft_in()
143
+ oft_setup_vmesh(np,rfake,np,np,lcfake,regfake,ctypes.byref(nregs),ctypes.byref(self._mesh_ptr))
144
+ elif r is not None:
145
+ if r.shape[1] != 3:
146
+ raise ValueError('Point list must have 3 spatial dimensions `[np,3]`')
147
+ r = numpy.ascontiguousarray(r, dtype=numpy.float64)
148
+ lc = numpy.ascontiguousarray(lc, dtype=numpy.int32)
149
+ np = c_int(r.shape[0])
150
+ npc = c_int(lc.shape[1])
151
+ nc = c_int(lc.shape[0])
152
+ if reg is None:
153
+ reg = numpy.ones((nc.value,),dtype=numpy.int32)
154
+ else:
155
+ reg = numpy.ascontiguousarray(reg, dtype=numpy.int32)
156
+ oft_setup_vmesh(np,r,npc,nc,lc+1,reg,ctypes.byref(nregs),ctypes.byref(self._mesh_ptr))
157
+ else:
158
+ raise ValueError('Mesh filename (native format) or mesh values required')
159
+ self.nregs = nregs.value
160
+
161
+ def setup(self,order=2,minlev=-1):
162
+ '''! Needs docs
163
+ '''
164
+ error_string = self._oft_env.get_c_errorbuff()
165
+ marklin_setup(ctypes.byref(self._marklin_ptr),self._mesh_ptr,order,minlev,error_string)
166
+ if error_string.value != b'':
167
+ raise Exception(error_string.value.decode())
168
+
169
+ def setup_io(self,basepath=None,legacy_hdf5=False):
170
+ '''! Setup XDMF+HDF5 I/O for 3D visualization
171
+
172
+ @param basepath Path to root directory to use for I/O
173
+ @param legacy_hdf5 Use legacy HDF5 format (required for VisIt)
174
+ '''
175
+ if basepath is None:
176
+ basepath_c = self._oft_env.path2c('')
177
+ self._io_basepath = "."
178
+ else:
179
+ if basepath[-1] != '/':
180
+ basepath += '/'
181
+ self._io_basepath = basepath[:-1]
182
+ basepath_c = self._oft_env.path2c(basepath)
183
+ error_string = self._oft_env.get_c_errorbuff()
184
+ marklin_setup_io(self._marklin_ptr,basepath_c,c_bool(legacy_hdf5),error_string)
185
+ if error_string.value != b'':
186
+ raise Exception(error_string.value.decode())
187
+
188
+ def build_XDMF(self,repeat_static=False,pretty=False):
189
+ '''! Build XDMF plot metadata files for model
190
+
191
+ @param repeat_static Repeat static fields (0-th timestep) in all timesteps?
192
+ @param pretty Use pretty printing (indentation) in XDMF files?
193
+ '''
194
+ return build_XDMF(path=self._io_basepath,repeat_static=repeat_static,pretty=pretty)
195
+
196
+ def compute_eig(self,nmodes=1,cache_file=None,save_rst=False):
197
+ r'''! Compute force-free eigenmodes
198
+
199
+ @param nmodes Number of eigenmodes to compute
200
+ @param cache_file Path to cache file to store/load modes
201
+ @param save_rst Save restart files? (deprecated)
202
+ '''
203
+ if self.nm != 0:
204
+ raise ValueError('Eigenstates already computed')
205
+ if save_rst:
206
+ warnings.warn("Argument `save_rst` is deprecated, use `cache_file` instead", DeprecationWarning)
207
+ cache_file = 'oft_Marklin.rst'
208
+ if cache_file is None:
209
+ cache_string = self._oft_env.path2c("")
210
+ else:
211
+ cache_string = self._oft_env.path2c(cache_file)
212
+ #
213
+ eig_vals = numpy.zeros((nmodes,),dtype=numpy.float64)
214
+ error_string = self._oft_env.get_c_errorbuff()
215
+ marklin_compute_eig(self._marklin_ptr,nmodes,eig_vals,cache_string,error_string)
216
+ if error_string.value != b'':
217
+ raise Exception(error_string.value)
218
+ self.nm = nmodes
219
+ self.eig_vals = eig_vals
220
+
221
+ def compute_vac(self,nh,hcpc,hcpv,cache_file=None):
222
+ r'''! Compute vacuum field with specified fluxes through jump planes
223
+
224
+ @param nh Number of jump planes
225
+ @param hcpc Plane specification points
226
+ @param hcpv Plane specification vectors
227
+ @param cache_file Path to cache file to store/load modes
228
+ '''
229
+ if hcpc.shape[0] != nh:
230
+ raise ValueError('Inconsistent sizes for "hcpc[0]" != {0}'.format(nh))
231
+ if hcpc.shape[1] != 3:
232
+ raise ValueError('Inconsistent sizes for "hcpc[0]" != {0}'.format(3))
233
+ if hcpv.shape[0] != nh:
234
+ raise ValueError('Inconsistent sizes for "hcpv[0]" != {0}'.format(nh))
235
+ if hcpv.shape[1] != 3:
236
+ raise ValueError('Inconsistent sizes for "hcpv[0]" != {0}'.format(3))
237
+ if cache_file is None:
238
+ cache_string = self._oft_env.path2c("")
239
+ else:
240
+ cache_string = self._oft_env.path2c(cache_file)
241
+ error_string = self._oft_env.get_c_errorbuff()
242
+ marklin_compute_vac(self._marklin_ptr,nh,hcpc,hcpv,cache_string,error_string)
243
+ if error_string.value != b'':
244
+ raise Exception(error_string.value)
245
+ self.nh = nh
246
+ self.hcpc = hcpc
247
+ self.hcpv = hcpv
248
+
249
+ def compute_par_diff(self,interpolator,k_perp):
250
+ r'''! Compute parallel diffusion with specified vector field and diffusivity
251
+
252
+ @param interpolator Interpolator defining vector field
253
+ @param k_perp Perpendicular diffusion value (k_par = 1.0)
254
+ '''
255
+ cstring = c_char_p(b""*200)
256
+ marklin_compute_pardiff(self._marklin_ptr,interpolator._int_ptr,interpolator.int_type,k_perp,cstring)
257
+ if cstring.value != b'':
258
+ raise Exception(cstring.value)
259
+
260
+ def save_field(self,field,tag):
261
+ '''! Save field to XDMF files for VisIt/Paraview
262
+
263
+ @param field Field interpolation object
264
+ @param tag Name for field in XDMF files
265
+ '''
266
+ #
267
+ error_string = self._oft_env.get_c_errorbuff()
268
+ ctag = self._oft_env.path2c(tag)
269
+ marklin_save_visit(self._marklin_ptr,field._int_ptr,field.int_type,ctag,error_string)
270
+ if error_string.value != b'':
271
+ raise Exception(error_string.value)
272
+
273
+ def get_ainterp(self,hmode_facs,bn_gauge=False):
274
+ r'''! Create field interpolator for vector potential
275
+
276
+ @param imode Index of eigenstate
277
+ @param bn_gauge Use B-field gauge (A_t = 0 @ wall)?
278
+ @result Field interpolation object
279
+ '''
280
+ if hmode_facs.shape[0] > self.nm:
281
+ raise ValueError("Requested mode number exceeds number of available modes")
282
+ interpolation_ptr = c_void_p()
283
+ error_string = self._oft_env.get_c_errorbuff()
284
+ marklin_get_aint(self._marklin_ptr,hmode_facs,ctypes.byref(interpolation_ptr),bn_gauge,error_string)
285
+ if error_string.value != b'':
286
+ raise Exception(error_string.value)
287
+ return Marklin_field_interpolator(self,interpolation_ptr,1,3)
288
+
289
+ def get_binterp(self,hmode_facs=None,vac_facs=None):
290
+ r'''! Create field interpolator for magnetic field
291
+
292
+ @param imode Index of eigenstate
293
+ @result Field interpolation object
294
+ '''
295
+ if hmode_facs is None:
296
+ if vac_facs is None:
297
+ raise ValueError('"hmode_facs" or "vac_facs" must be specified.')
298
+ hmode_facs = numpy.zeros((self.nm,), dtype=numpy.float64)
299
+ else:
300
+ if hmode_facs.shape[0] > self.nm:
301
+ raise ValueError("Requested mode number exceeds number of available modes")
302
+ if vac_facs is None:
303
+ vac_facs = numpy.zeros((self.nh,), dtype=numpy.float64)
304
+ interpolation_ptr = c_void_p()
305
+ error_string = self._oft_env.get_c_errorbuff()
306
+ marklin_get_bint(self._marklin_ptr,hmode_facs,vac_facs,ctypes.byref(interpolation_ptr),error_string)
307
+ if error_string.value != b'':
308
+ raise Exception(error_string.value)
309
+ return Marklin_field_interpolator(self,interpolation_ptr,2,3)
@@ -0,0 +1,55 @@
1
+ #------------------------------------------------------------------------------
2
+ # Flexible Unstructured Simulation Infrastructure with Open Numerics (Open FUSION Toolkit)
3
+ #
4
+ # SPDX-License-Identifier: LGPL-3.0-only
5
+ #------------------------------------------------------------------------------
6
+ '''! Fortran interface definitions for Marklin
7
+
8
+ @authors Chris Hansen
9
+ @date September 2023
10
+ @ingroup doxy_oft_python
11
+ '''
12
+ import numpy
13
+ from .._interface import *
14
+
15
+ ## @cond
16
+ # marklin_setup(marklin_ptr,mesh_ptr,order,minlev,error_str)
17
+ marklin_setup = ctypes_subroutine(oftpy_lib.marklin_setup,
18
+ [c_void_ptr_ptr, c_void_p, c_int, c_int, c_char_p])
19
+
20
+ # marklin_destroy(marklin_ptr,error_str)
21
+ marklin_destroy = ctypes_subroutine(oftpy_lib.marklin_destroy,
22
+ [c_void_p, c_char_p])
23
+
24
+ # marklin_compute(marklin_ptr,nmodes,eig_vals,cache_file,error_str)
25
+ marklin_compute_eig = ctypes_subroutine(oftpy_lib.marklin_compute_eig,
26
+ [c_void_p, c_int, ctypes_numpy_array(numpy.float64,1), c_char_p, c_char_p])
27
+
28
+ # marklin_compute_vac(marklin_ptr,nh,hcpc,hcpv,save_rst,error_str)
29
+ marklin_compute_vac = ctypes_subroutine(oftpy_lib.marklin_compute_vac,
30
+ [c_void_p, c_int, ctypes_numpy_array(numpy.float64,2), ctypes_numpy_array(numpy.float64,2), c_char_p, c_char_p])
31
+
32
+ # marklin_compute_pardiff(marklin_ptr,int_obj,int_type,k_perp,error_str)
33
+ marklin_compute_pardiff = ctypes_subroutine(oftpy_lib.marklin_compute_pardiff,
34
+ [c_void_p, c_void_p, c_int, c_double, c_char_p])
35
+
36
+ # marklin_setup_io(marklin_ptr,basepath,legacy_hdf5,error_str)
37
+ marklin_setup_io = ctypes_subroutine(oftpy_lib.marklin_setup_io,
38
+ [c_void_p, c_char_p, c_bool, c_char_p])
39
+
40
+ # marklin_save_visit(marklin_ptr,int_obj,int_type,key,error_str)
41
+ marklin_save_visit = ctypes_subroutine(oftpy_lib.marklin_save_visit,
42
+ [c_void_p, c_void_p, c_int, c_char_p, c_char_p])
43
+
44
+ # marklin_get_aint(marklin_ptr,hmode_facs,int_obj,zero_norm,error_str)
45
+ marklin_get_aint = ctypes_subroutine(oftpy_lib.marklin_get_aint,
46
+ [c_void_p, ctypes_numpy_array(numpy.float64,1), c_void_ptr_ptr, c_bool, c_char_p])
47
+
48
+ # marklin_get_bint(marklin_ptr,hmode_facs,vac_facs,int_obj,error_str)
49
+ marklin_get_bint = ctypes_subroutine(oftpy_lib.marklin_get_bint,
50
+ [c_void_p, ctypes_numpy_array(numpy.float64,1), ctypes_numpy_array(numpy.float64,1), c_void_ptr_ptr, c_char_p])
51
+
52
+ # marklin_apply_int(marklin_ptr,int_obj,int_type,pt,fbary_tol,cell,field)
53
+ marklin_apply_int = ctypes_subroutine(oftpy_lib.marklin_apply_int,
54
+ [c_void_p, c_void_p, c_int, ctypes_numpy_array(numpy.float64,1), c_double, c_int_ptr ,ctypes_numpy_array(numpy.float64,1)])
55
+ ## @endcond
@@ -0,0 +1,14 @@
1
+ #------------------------------------------------------------------------------
2
+ # Flexible Unstructured Simulation Infrastructure with Open Numerics (Open FUSION Toolkit)
3
+ #
4
+ # SPDX-License-Identifier: LGPL-3.0-only
5
+ #------------------------------------------------------------------------------
6
+ '''! Python interface for ThinCurr thin-wall E-M functionality
7
+
8
+ @authors Chris Hansen
9
+ @date March 2024
10
+ @ingroup doxy_oft_python
11
+ '''
12
+ from ._core import ThinCurr, ThinCurr_reduced
13
+
14
+ __all__ = ["ThinCurr", "ThinCurr_reduced"]