4747
4848AuxFType = typing .Annotated [
4949 _ArrayType ,
50- pydantic .BeforeValidator (lambda x : _util .pad_to_target (x , ndfmax , 0.0 )),
50+ pydantic .BeforeValidator (lambda x : _util .right_pad (x , ndfmax , 0.0 )),
5151]
5252AuxSType = typing .Annotated [
5353 _ArrayType ,
54- pydantic .BeforeValidator (lambda x : _util .pad_to_target (x , ndfmax , - 1.0 )),
54+ pydantic .BeforeValidator (lambda x : _util .right_pad (x , ndfmax , - 1.0 )),
5555]
5656
5757MgridModeType : typing .TypeAlias = typing .Annotated [
@@ -770,7 +770,8 @@ class VmecWOut(BaseModelWithNumpy):
770770 """Radial derivative of enclosed toroidal magnetic flux ``phi'`` on the full-
771771 grid."""
772772
773- chipf : jt .Float [np .ndarray , "n_surfaces" ]
773+ # Defaulted for backwards compatibility with old wout files
774+ chipf : jt .Float [np .ndarray , "n_surfaces" ] = np .array ([])
774775 """Radial derivative of enclosed poloidal magnetic flux ``chi'`` on the full-
775776 grid."""
776777
@@ -1095,11 +1096,13 @@ class VmecWOut(BaseModelWithNumpy):
10951096 """Volume-averaged magnetic field strength."""
10961097
10971098 # In the C++ WOutFileContents this is called safety_factor.
1098- q_factor : jt .Float [np .ndarray , "n_surfaces" ]
1099+ # Defaulted for backwards compatibility with old wout files.
1100+ q_factor : jt .Float [np .ndarray , "n_surfaces" ] = np .array ([])
10991101 r"""Safety factor :math:`q = 1/\iota` on the full-grid."""
11001102
11011103 # In the C++ WOutFileContents this is called poloidal_flux.
1102- chi : jt .Float [np .ndarray , "n_surfaces" ]
1104+ # Defaulted for backwards compatibility with old wout files.
1105+ chi : jt .Float [np .ndarray , "n_surfaces" ] = np .array ([])
11031106 r"""Enclosed poloidal magnetic flux :math:`\chi` on the full-grid."""
11041107
11051108 # In the C++ WOutFileContents this is called spectral_width.
@@ -1417,45 +1420,15 @@ def _from_cpp_wout(cpp_wout: _vmecpp.VmecppWOut) -> VmecWOut:
14171420 attrs ["gmnc" ] = _pad_and_transpose (cpp_wout .gmnc , attrs ["mnmax_nyq" ])
14181421
14191422 # These attributes have zero-padding at the end up to a fixed length
1420- attrs ["am" ] = np .pad (cpp_wout .am , (0 , preset - len (cpp_wout .am )))
1421- attrs ["ac" ] = np .pad (cpp_wout .ac , (0 , preset - len (cpp_wout .ac )))
1422- attrs ["ai" ] = np .pad (cpp_wout .ai , (0 , preset - len (cpp_wout .ai )))
1423- attrs ["am_aux_s" ] = np .pad (
1424- cpp_wout .am_aux_s ,
1425- (0 , ndfmax - len (cpp_wout .am_aux_s )),
1426- mode = "constant" ,
1427- constant_values = - 1.0 ,
1428- )
1429- attrs ["am_aux_f" ] = np .pad (
1430- cpp_wout .am_aux_f ,
1431- (0 , ndfmax - len (cpp_wout .am_aux_f )),
1432- mode = "constant" ,
1433- constant_values = 0.0 ,
1434- )
1435- attrs ["ac_aux_s" ] = np .pad (
1436- cpp_wout .ac_aux_s ,
1437- (0 , ndfmax - len (cpp_wout .ac_aux_s )),
1438- mode = "constant" ,
1439- constant_values = - 1.0 ,
1440- )
1441- attrs ["ac_aux_f" ] = np .pad (
1442- cpp_wout .ac_aux_f ,
1443- (0 , ndfmax - len (cpp_wout .ac_aux_f )),
1444- mode = "constant" ,
1445- constant_values = 0.0 ,
1446- )
1447- attrs ["ai_aux_s" ] = np .pad (
1448- cpp_wout .ai_aux_s ,
1449- (0 , ndfmax - len (cpp_wout .ai_aux_s )),
1450- mode = "constant" ,
1451- constant_values = - 1.0 ,
1452- )
1453- attrs ["ai_aux_f" ] = np .pad (
1454- cpp_wout .ai_aux_f ,
1455- (0 , ndfmax - len (cpp_wout .ai_aux_f )),
1456- mode = "constant" ,
1457- constant_values = 0.0 ,
1458- )
1423+ attrs ["am" ] = _util .right_pad (cpp_wout .am , preset )
1424+ attrs ["ac" ] = _util .right_pad (cpp_wout .ac , preset )
1425+ attrs ["ai" ] = _util .right_pad (cpp_wout .ai , preset )
1426+ attrs ["am_aux_s" ] = _util .right_pad (cpp_wout .am_aux_s , ndfmax , - 1.0 )
1427+ attrs ["am_aux_f" ] = _util .right_pad (cpp_wout .am_aux_f , ndfmax )
1428+ attrs ["ac_aux_s" ] = _util .right_pad (cpp_wout .ac_aux_s , ndfmax , - 1.0 )
1429+ attrs ["ac_aux_f" ] = _util .right_pad (cpp_wout .ac_aux_f , ndfmax )
1430+ attrs ["ai_aux_s" ] = _util .right_pad (cpp_wout .ai_aux_s , ndfmax , - 1.0 )
1431+ attrs ["ai_aux_f" ] = _util .right_pad (cpp_wout .ai_aux_f , ndfmax )
14591432
14601433 attrs ["restart_reason_timetrace" ] = cpp_wout .restart_reasons
14611434
@@ -2020,6 +1993,46 @@ def _pad_and_transpose(
20201993 return stacked
20211994
20221995
1996+ def populate_raw_profile (
1997+ vmec_input : VmecInput ,
1998+ field : typing .Literal ["pressure" , "iota" , "current" ],
1999+ f : typing .Callable [[np .ndarray ], np .ndarray ],
2000+ ) -> None :
2001+ """Populate a line segment profile using callable ``f``.
2002+
2003+ The callable is evaluated on all unique ``s`` values required for the
2004+ multi-grid steps (full and half grids). The resulting knots and values are
2005+ stored in the auxiliary arrays for the chosen profile.
2006+ """
2007+ s_values : set [float ] = set ()
2008+ for ns in vmec_input .ns_array :
2009+ full_grid = np .linspace (0.0 , 1.0 , ns )
2010+ half_grid = full_grid - 0.5 * (full_grid [1 ] - full_grid [0 ])
2011+ s_values .update (full_grid )
2012+ s_values .update (half_grid )
2013+ knots = np .array (np .sort (np .array (list (s_values ))))
2014+ values = np .array (f (knots ))
2015+
2016+ if field == "pressure" :
2017+ vmec_input .pmass_type = "line_segment"
2018+ vmec_input .am_aux_s = knots
2019+ vmec_input .am_aux_f = values
2020+ vmec_input .am = np .array ([])
2021+ elif field == "iota" :
2022+ vmec_input .piota_type = "line_segment"
2023+ vmec_input .ai_aux_s = knots
2024+ vmec_input .ai_aux_f = values
2025+ vmec_input .ai = np .array ([])
2026+ elif field == "current" :
2027+ vmec_input .pcurr_type = "line_segment_i"
2028+ vmec_input .ac_aux_s = knots
2029+ vmec_input .ac_aux_f = values
2030+ vmec_input .ac = np .array ([])
2031+ else :
2032+ msg = "field must be one of 'pressure', 'iota', 'current'"
2033+ raise ValueError (msg )
2034+
2035+
20232036# Ordered this way to ensure run, VmecInput, and VmecOutput are the first three
20242037# items in the generated documentation.
20252038__all__ = [
@@ -2032,4 +2045,5 @@ def _pad_and_transpose(
20322045 "Threed1Volumetrics" ,
20332046 "MakegridParameters" ,
20342047 "MagneticFieldResponseTable" ,
2048+ "populate_raw_profile" ,
20352049]
0 commit comments