gvec.util#

GVEC utility module

This module is part of the gvec python package, but also used directly in the tests.

class gvec.util.CaseInsensitiveDict(data=(), /, **kwargs)#

Bases: MutableMapping

A dictionary-like Mutable Mapping where string keys are case-insensitive.

Implements all methods and operations of MutableMapping as well as dict’s copy. Also provides lower_items and lower_keys.

Keys that are not strings will be stored as-is. The structure remembers the case of the last used key, and iter(instance), keys(), items(), iterkeys(), and iteritems() will contain case-sensitive keys. However, querying and contains testing is case insensitive.

Raises:

ValueError – If the constructor, .update, or equality comparison operations are given keys that have equal .lower() representations. This is to avoid ambiguity in lookups and ensure consistent behavior.

Examples

>>> cid = CaseInsensitiveDict()
>>> cid['param'] = 'value'
>>> cid['Param'] == 'value'
True
copy()#

Return a deep copy.

lower_items()#
lower_keys()#
serialize()#

Recursively serialize this object, converting Mappings to dicts and Iterables to lists.

update([E, ]**F) None.  Update D from mapping/iterable E and F.#

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

gvec.util.adapt_parameter_file(source: str | Path, target: str | Path, **kwargs)#

Copy the source file to the target file and replace the parameters according to kwargs.

Parameters:
  • source (str or Path) – The path to the source parameter file.

  • target (str or Path) – The path to the target parameter file.

  • **kwargs – Keyword arguments representing the parameters to be replaced. if the value of the key is “!”, the line with the keyword is uncommented, if possible

Raises:

AssertionError – If the number of occurrences for any parameter is not exactly 1.

Notes

  • If no parameters are provided in kwargs, the function simply copies the source file to the target file.

  • The function replaces the parameters in the format key = value, where value is either a sequence of characters containing no whitespace or a single pair of parentheses with any content. The value from kwargs is inserted using the standard python string conversion. There may be a comment, starting with !, after the value.

  • If a parameter already exists in the source file, its value is replaced with the corresponding value from kwargs.

  • If a parameter does not exist in the source file, it is added to the target file.

  • If the value of the key starts with “!”, the line with the keyword is just uncommented. (i.e. "!key=2.5" -> "key=2.5") If no line with the keyword is found, the key is added with the value, excluding the leading "!" (i.e. value is "!0.5" -> "key=0.5" is added)

Example

adapt_parameter_file('/path/to/source.ini', '/path/to/target.ini', param1=1.2, param2="(1, 2, 3)")

gvec.util.axis_from_boundary(parameters: MutableMapping) MutableMapping#
gvec.util.boundary_generator(case: str, X1_00=1.0, a0=0.5, ellipticity=0.4, helix_r=0.5)#

Define parameters for some simple boundaries for testing.

Parameters:
  • case (str) –

    The name of the boundary:

    see boundary_generator_cases dictionary

  • X1_00 (float, optional) – =major radius if \(X^1=R\)

  • a0 (float, optional) – =minor radius scale

  • ellipticity (float, optional) – =ellipticity of the cross section

Return type:

parameter dictionary describing

gvec.util.boundary_generator_cases()#
gvec.util.bspl2gvec(name: Literal['iota', 'pres'], bspl: BSpline | None = None, knots: _Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] | None = None, coefs: _Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] | None = None, params: dict = {}) dict#

Translates a scipy B-spline object or B-spline coefficients and knots for either a iota or pressure profile into a dictionary entries that can be handed to adapt_parameter_file.

Parameters:
  • name (str) – profile identifyer, has to be either iota or pres.

  • bspl (scipy.interpolate.BSpline) – scipy BSpline object. If this is not provided knots and coefs are expected.

  • knots (ArrayLike) – Knots for the B-splines. Note that repeated edge knots according to the degree are expected.

  • coefs (ArrayLike) – Coefficients for the B-splines.

  • params (dict, optional) – Dictionary of gvec input parameters that will be adapted. Defaults to {}.

Raises:
  • ValueError – If name is neither iota nor pres.

  • TypeError – If neither bspl nor knots and coefs is provided.

Returns:

Dictionary of gvec input parameters

Return type:

dict

gvec.util.chdir(target: Path | str)#

Contextmanager to change the current working directory.

Using a context has the benefit of automatically changing back to the original directory when the context is exited, even if an exception is raised.

gvec.util.check_boundary_direction(parameters: Mapping) bool#

Determine whether the boundary is described by right-handed logical coordinates (θ,ζ).

GVEC requires a right-handed logical coordinate system (ρ,θ,ζ). The logical coordinate system of the poloidal plane, (ρ,θ) is also required to be right-handed, which requires the poloidal angle to increase in the counter-clockwise direction. As a consequence the toroidal angle has to increase in the clockwise direction when viewed from above. This is ensured in the definition of the h-maps.

Returns:

True if (ρ,θ) is right-handed / θ increases counter-clockwise, False otherwise.

Return type:

bool

gvec.util.compute_FD(f: ndarray, pos, coefs, axis=0)#

1D Finite difference of a function f on equispaced n-dimnesional grid, using FD coefficients coefficients coefs and relative integer positions to the central evaluation point pos, along one given axis.

Warning

  • if data is periodic, meaning that endpoints of periodic interval are excluded, result can be on all points.

  • If data is not periodic, the result at the boundaries is WRONG, for the points |min(pos)| on the left and max(pos) on the right along the given axis.

Parameters:
  • f (numpy.ndarray) – function values on equispaced n-dimnesional grid

  • pos (int) – relative integer positions to the central evaluation point, as 1d list or 1d array of integers

  • coefs (float) – FD coefficients for each position, as 1d list or 1d array, same size as pos!

  • axis (int, optional) – axis along which the FD is computed, default is 0

Returns:

df – Finite-Difference result, same shape as f (see warning above!)

Return type:

numpy.ndarray

Examples

  • examples for first derivative of f:
    • 1st order forward FD: pos=[1,0]; coefs=[-1,1]/(dx)

    • 2nd order central FD: pos=[-1,1]; coefs=[-1,1]/(2*dx)

    • 4th order central FD: pos=[-2,-1,1,2]; coefs=[1/12,-2/3,2/3,-1/12]/(dx)

    • 6th order central FD: pos=[-3,-2,-1,1,2,3]; coefs=[-1/60,3/20,-3/4,3/4,-3/20,1/60]/(dx)

    • 8th order central FD: pos=[-4,-3,-2,-1,1,2,3,4]; coefs=[1/280,-4/105,1/5,-4/5,4/5,-1/5,4/105,-1/280]/(dx)

  • examples for second derivatives of f:
    • 2nd order central FD: pos=[-1,0,1]; coefs=[1,-2,1]/(dx**2)

    • 4th order central FD: pos=[-2,-1,1,2]; coefs=[-1/12, 4/3,-5/2, 4/3,-1/12]/(dx**2)

    • 6th order central FD: pos=[-3,-2,-1,1,2,3]; coefs=[1/90,-3/20,3/2,-49/18,3/2,-3/20,1/90]/(dx**2)

    • 8th order central FD: pos=[-4,-3,-2,-1,1,2,3,4]; coefs=[-1/560,8/315,-1/5,8/5,-205/72,8/5,-1/5,8/315,-1/560]/(dx**2)

gvec.util.compute_boundary_perturbation(base_parameters: Mapping, perturbed_parameters: Mapping) tuple[CaseInsensitiveDict, CaseInsensitiveDict]#

Computes the difference between the perturbed and base boundary parameters as a perturbation.

gvec.util.effective_minor_radius(parameters: Mapping, resolution: tuple[int, int] = (1000, 100))#
gvec.util.ellipse_circumference_factor(epsilon: float) float#

Compute the circumference factor of an ellipse with elongation epsilon. This uses the approximation by Ramanujan, accurate up to h^5 (6.5% error at ε=10).

A = a b π = aeff^2 π ε = a / b >= 1 C = 2 π aeff Cf(ε) Cf ~ (1 + ε) / (2 √ε) [1 + 3 h / (10 + √(4 - 3 h))] h = (ε - 1)^2 / (ε + 1)^2

gvec.util.evaluate_axis(zeta: ndarray, parameters: Mapping) tuple[ndarray, ndarray]#

Evaluate the magnetic axis at the given zeta points.

Parameters:
  • zeta (1D np.ndarray) – The toroidal angles at which to evaluate the axis.

  • parameters (Mapping) – The parameters defining the axis.

Returns:

The (X^1, X^2) coordinates of the axis at the given zeta points.

Return type:

tuple[1D np.ndarray, 1D np.ndarray]

gvec.util.evaluate_boundary(theta: ndarray, zeta: ndarray, parameters: Mapping) tuple[ndarray, ndarray]#

Evaluate the boundary at the given (theta, zeta) points.

Parameters:
  • theta (1D np.ndarray) – The poloidal angles at which to evaluate the boundary.

  • zeta (1D np.ndarray) – The toroidal angles at which to evaluate the boundary.

  • parameters (Mapping) – The parameters defining the boundary.

Returns:

The (X^1, X^2) coordinates of the boundary at the given (theta, zeta) points.

Return type:

tuple[2D np.ndarray, 2D np.ndarray]

gvec.util.flatten_parameters(parameters: Mapping) CaseInsensitiveDict#

Flatten parameters from a hierarchical dictionary

gvec.util.flip_boundary_theta(parameters: MutableMapping) MutableMapping#

Flip the boundary parameters in the poloidal direction. θ → -θ.

gvec.util.flip_boundary_zeta(parameters: MutableMapping) MutableMapping#
gvec.util.flip_parameters_theta(parameters: MutableMapping) MutableMapping#
gvec.util.flip_parameters_zeta(parameters: MutableMapping) MutableMapping#
gvec.util.get_compile_options() str#
gvec.util.logging_setup()#

Setup default logging configuration for GVEC.

gvec.util.parameters_from_vmec(nml: Mapping, name: str) CaseInsensitiveDict#
gvec.util.read_parameter_file_ini(path: str | Path) CaseInsensitiveDict#

Read the parameters from the specified parameter file in GVEC-ini format.

Parameters:

path (str | Path) – The path to the parameter file.

Returns:

A mapping (with case insensitive keys) containing the parameters from the parameter file.

Return type:

CaseInsensitiveDict

Example: >>> read_parameter_file_ini(‘/path/to/parameter.ini’) {‘param1’: 1.2, ‘param2’: (1, 2, 3), ‘param3’: {(-1, 0): 0.5, (0, 0): 1.0}}

gvec.util.read_parameters(path: Path | str, format: Literal['ini', 'yaml', 'toml'] | None = None) CaseInsensitiveDict#
gvec.util.shift_boundary_theta_pi(parameters: MutableMapping) MutableMapping#

Shift the theta origin of the boundary by pi.

cos(m(θ+π)-nζ) = (-1)^m cos(mθ-nζ) sin(m(θ+π)-nζ) = (-1)^m sin(mθ-nζ)

gvec.util.signed_cross_sectional_area(parameters: Mapping, zeta: float, resolution: int = 1000) float#
gvec.util.stack_parameters(parameters: Mapping) CaseInsensitiveDict#

Stack parameters into a hierarchical dictionary

gvec.util.stringify_mn_parameters(parameters: Mapping) CaseInsensitiveDict#

Serialize parameters into a string

gvec.util.unstringify_mn_parameters(parameters: Mapping) CaseInsensitiveDict#

Deserialize parameters from a string

gvec.util.version_info() str#
gvec.util.write_parameter_file_ini(parameters: Mapping, path: str | Path = 'parameter.ini', header: str = '')#

Write the parameters to the specified parameter file in GVEC-ini format.

Parameters:
  • parameters – A mapping containing the parameters to be written to the parameter file.

  • path – The path to the parameter file.

gvec.util.write_parameters(parameters: Mapping, path: Path | str = 'parameter.ini', format: Literal['ini', 'yaml', 'toml'] | None = None)#