11import math
2- from pathlib import Path
2+ from pathlib import Path , PosixPath
33import concurrent .futures
44import os
55import sys
1212from pystell import read_vmec
1313import matplotlib .pyplot as plt
1414
15+ from . import invessel_build
1516from . import log
1617from .utils import m2cm
1718
@@ -90,12 +91,12 @@ def fire_rays(dagmc_geom, source_mesh, toroidal_extent, strengths, num_parts):
9091 return "surface_source.h5"
9192
9293
93- def compute_residual (poloidal_guess , vmec_obj , wall_s , toroidal_angle , point ):
94+ def compute_residual (poloidal_guess , ref_surf , wall_s , toroidal_angle , point ):
9495 """Minimization problem to solve for the poloidal angle.
9596
9697 Arguments:
9798 poloidal_guess (float): poloidal angle guess [rad].
98- vmec_obj (object): plasma equilibrium VMEC object.
99+ ref_surf (object): ReferenceSurface object.
99100 wall_s (float): closed flux surface label extrapolation at wall.
100101 toroidal_angle (float): toroidal angle [rad].
101102 point (numpy.array): Cartesian coordinates [cm].
@@ -104,9 +105,8 @@ def compute_residual(poloidal_guess, vmec_obj, wall_s, toroidal_angle, point):
104105 (float): L2 norm of difference between coordinates of interest and
105106 computed point [cm].
106107 """
107- fw_guess = (
108- np .array (vmec_obj .vmec2xyz (wall_s , poloidal_guess , toroidal_angle ))
109- * m2cm
108+ fw_guess = np .array (
109+ ref_surf .angles_to_xyz (toroidal_angle , poloidal_guess , wall_s , m2cm )[0 ]
110110 )
111111
112112 return np .linalg .norm (point - fw_guess )
@@ -119,9 +119,8 @@ def solve_poloidal_angles(data):
119119
120120 Arguments:
121121 data (iterable): data for root-finding algorithm. Entries in order:
122- 1) path to plasma equilibrium VMEC file (str). Because the VMEC
123- dataset is not picklable, a separate object is created for each
124- thread.
122+ 1) path to plasma equilibrium VMEC file (str) or ReferenceSurface
123+ object (object).
125124 2) first wall CFS reference value (float).
126125 3) convergence tolerance for root-finding (float).
127126 4) toroidal angles at which to solve for poloidal angles
@@ -133,7 +132,12 @@ def solve_poloidal_angles(data):
133132 poloidal_angles (list): poloidal angles corresponding to supplied
134133 coordinates [rad].
135134 """
136- vmec_obj = read_vmec .VMECData (data [0 ])
135+ if isinstance (data [0 ], (str , PosixPath )):
136+ vmec_obj = read_vmec .VMECData (data [0 ])
137+ ref_surf = invessel_build .VMECSurface (vmec_obj )
138+ else :
139+ ref_surf = data [0 ]
140+
137141 wall_s = data [1 ]
138142 conv_tol = data [2 ]
139143 toroidal_angles = data [3 ]
@@ -145,19 +149,20 @@ def solve_poloidal_angles(data):
145149 result = direct (
146150 compute_residual ,
147151 bounds = [(0 , 2 * np .pi )],
148- args = (vmec_obj , wall_s , toroidal_angle , point ),
152+ args = (ref_surf , wall_s , toroidal_angle , point ),
149153 vol_tol = conv_tol ,
150154 )
151155 poloidal_angles .append (result .x [0 ])
152156
153157 return poloidal_angles
154158
155159
156- def compute_flux_coordinates (vmec_file , wall_s , coords , num_threads , conv_tol ):
160+ def compute_flux_coordinates (ref_surf , wall_s , coords , num_threads , conv_tol ):
157161 """Computes flux coordinates of specified Cartesian coordinates.
158162
159163 Arguments:
160- vmec_file (str): path to plasma equilibrium VMEC file.
164+ ref_surf: path to plasma equilibrium VMEC file (str) or ReferenceSurface
165+ object (object).
161166 wall_s (float): closed flux surface extrapolation at first wall.
162167 coords (numpy.array): Cartesian coordinates of surface crossings [cm].
163168 conv_tol (float): convergence tolerance for root-finding.
@@ -174,7 +179,7 @@ def compute_flux_coordinates(vmec_file, wall_s, coords, num_threads, conv_tol):
174179 for chunk_start in range (0 , len (toroidal_angles ), chunk_size ):
175180 chunks .append (
176181 (
177- vmec_file ,
182+ ref_surf ,
178183 wall_s ,
179184 conv_tol ,
180185 toroidal_angles [chunk_start : chunk_start + chunk_size ],
@@ -247,7 +252,7 @@ def compute_quadrilateral_area(corners):
247252
248253def compute_nwl (
249254 source_file ,
250- vmec_file ,
255+ ref_surf ,
251256 wall_s ,
252257 toroidal_extent ,
253258 neutron_power ,
@@ -263,7 +268,12 @@ def compute_nwl(
263268
264269 Arguments:
265270 source_file (str): path to OpenMC surface source file.
266- vmec_file (str): path to plasma equilibrium VMEC file.
271+ ref_surf (object): path to plasma equilibrium VMEC file (str) or
272+ ReferenceSurface object (object). If ReferenceSurface, must have a
273+ method 'angles_to_xyz(toroidal_angles, poloidal_angles, s, scale)'
274+ that returns an Nx3 numpy array of cartesian coordinates for any
275+ closed flux surface label, s, poloidal angle, and toroidal angle.
276+ Cannot be VMECSurface object, since those are not picklable.
267277 wall_s (float): closed flux surface label extrapolation at wall.
268278 toroidal_extent (float): toroidal extent of model [deg].
269279 neutron_power (float): reference neutron power [MW].
@@ -315,7 +325,7 @@ def compute_nwl(
315325 logger .info (f"Processing batch { batch_num } " )
316326
317327 toroidal_angle_batch , poloidal_angle_batch = compute_flux_coordinates (
318- vmec_file ,
328+ ref_surf ,
319329 wall_s ,
320330 coords [batch_start : batch_start + batch_size ],
321331 num_threads ,
@@ -362,13 +372,16 @@ def compute_nwl(
362372
363373 nwl_mat = count_mat * neutron_power / num_particles
364374
375+ if isinstance (ref_surf , (str , PosixPath )):
376+ vmec_obj = read_vmec .VMECData (ref_surf )
377+ ref_surf = invessel_build .VMECSurface (vmec_obj )
378+
365379 # Construct matrix of bin boundaries
366- vmec_obj = read_vmec .VMECData (vmec_file )
367380 bin_mat = np .zeros ((num_toroidal_bins + 1 , num_poloidal_bins + 1 , 3 ))
368381 for toroidal_id , toroidal_edge in enumerate (toroidal_bin_edges ):
369- for poloidal_id , poloidal_edge in enumerate ( poloidal_bin_edges ):
370- x , y , z = vmec_obj . vmec2xyz ( wall_s , poloidal_edge , toroidal_edge )
371- bin_mat [ toroidal_id , poloidal_id , :] = [ x , y , z ]
382+ bin_mat [ toroidal_id , :, :] = ref_surf . angles_to_xyz (
383+ toroidal_edge , poloidal_bin_edges , wall_s , m2cm
384+ )
372385
373386 # Construct matrix of bin areas
374387 area_mat = np .zeros ((num_toroidal_bins , num_poloidal_bins ))
0 commit comments