Skip to content

aragog.parser

parser

Parses the configuration file and scales and stores the parameters.

logger = logging.getLogger(__name__) module-attribute

Parameters(*, boundary_conditions, energy, initial_condition, mesh, phase_solid, phase_liquid, phase_mixed, radionuclides, scalings, solver) dataclass

Assembles all the parameters.

The parameters in each section are scaled here to ensure that all the parameters are scaled (non-dimensionalised) consistently with each other.

from_file(*filenames) classmethod

Parses the parameters in a configuration file(s)

Args: *filenames: Filenames of the configuration data

Source code in aragog/parser.py
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
@classmethod
def from_file(cls, *filenames) -> Self:
    """Parses the parameters in a configuration file(s)

    Args:
        *filenames: Filenames of the configuration data
    """
    parser: ConfigParser = ConfigParser()
    parser.read(*filenames)

    init_dict: dict[str, Any] = {}
    for section_name, dataclass_ in _get_dataclass_from_section_name().items():
        init_dict[section_name] = parser.parse_section(
            using_dataclass=dataclass_, section_name=section_name
        )
    radionuclides: list[_Radionuclide] = []
    for radionuclide_section in cls.radionuclide_sections(parser):
        radionuclide = parser.parse_section(
            using_dataclass=_Radionuclide, section_name=radionuclide_section
        )
        radionuclides.append(radionuclide)

    init_dict["radionuclides"] = radionuclides

    return cls(**init_dict)  # Unpacking gives required arguments so pylint: disable=E1125

radionuclide_sections(parser) staticmethod

Section names relating to radionuclides

Sections relating to radionuclides must have the prefix radionuclide_

Source code in aragog/parser.py
499
500
501
502
503
504
505
506
507
508
509
@staticmethod
def radionuclide_sections(parser: ConfigParser) -> list[str]:
    """Section names relating to radionuclides

    Sections relating to radionuclides must have the prefix radionuclide_
    """
    return [
        parser[section].name
        for section in parser.sections()
        if section.startswith("radionuclide_")
    ]

_BoundaryConditionsParameters(outer_boundary_condition, outer_boundary_value, inner_boundary_condition, inner_boundary_value, emissivity, equilibrium_temperature, core_heat_capacity) dataclass

Stores parameters in the boundary_conditions section in the configuration data.

scale_attributes(scalings)

Scales the attributes.

Args: scalings: scalings

Source code in aragog/parser.py
149
150
151
152
153
154
155
156
157
158
159
def scale_attributes(self, scalings: _ScalingsParameters) -> None:
    """Scales the attributes.

    Args:
        scalings: scalings
    """
    self.scalings_ = scalings
    self.equilibrium_temperature /= self.scalings_.temperature
    self.core_heat_capacity /= self.scalings_.heat_capacity
    self._scale_inner_boundary_condition()
    self._scale_outer_boundary_condition()

_EnergyParameters(conduction, convection, gravitational_separation, mixing, radionuclides, dilatation, tidal, tidal_array=(lambda: np.array([0.0], dtype=float))()) dataclass

Stores parameters in the energy section

scale_attributes(scalings)

Scales the attributes.

Args: scalings: scalings

Source code in aragog/parser.py
218
219
220
221
222
223
224
225
def scale_attributes(self, scalings: _ScalingsParameters) -> None:
    """Scales the attributes.

    Args:
        scalings: scalings
    """
    self.scalings_ = scalings
    self.tidal_array /= self.scalings_.power_per_mass

_InitialConditionParameters(initial_condition=1, surface_temperature=4000, basal_temperature=4000, init_file='') dataclass

Stores the settings in the initial_condition section in the configuration data.

scale_attributes(scalings)

Scales the attributes.

Initial condition method 1: Linear profile 2: User-defined temperature field (from file) 3: Adiabatic profile

Args: scalings: scalings

Source code in aragog/parser.py
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
def scale_attributes(self, scalings: _ScalingsParameters) -> None:
    """Scales the attributes.

    Initial condition method
        1: Linear profile
        2: User-defined temperature field (from file)
        3: Adiabatic profile

    Args:
        scalings: scalings
    """
    self.scalings_ = scalings
    self.surface_temperature /= self.scalings_.temperature
    self.basal_temperature /= self.scalings_.temperature

    if self.initial_condition == 2:
        if self.init_file == "":
            msg: str = (f"you must provide an initial temperature file")
            raise ValueError(msg)
        self.init_temperature = np.loadtxt(self.init_file)
        self.init_temperature /= self.scalings_.temperature

_MeshParameters(outer_radius, inner_radius, number_of_nodes, mixing_length_profile, core_density, eos_method=1, surface_density=4000, gravitational_acceleration=9.81, adiabatic_bulk_modulus=260000000000.0, mass_coordinates=False, eos_file='') dataclass

Stores parameters in the mesh section in the configuration data.

scale_attributes(scalings)

Scales the attributes

Args: scalings: scalings

Source code in aragog/parser.py
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
def scale_attributes(self, scalings: _ScalingsParameters) -> None:
    """Scales the attributes

    Args:
        scalings: scalings
    """
    self.scalings_ = scalings
    self.outer_radius /= self.scalings_.radius
    self.inner_radius /= self.scalings_.radius
    self.core_density /= self.scalings_.density
    self.surface_density /= self.scalings_.density
    self.gravitational_acceleration /= self.scalings_.gravitational_acceleration
    self.adiabatic_bulk_modulus /= self.scalings_.pressure

    if self.eos_method == 2:
        if self.eos_file == "":
            msg: str = (f"you must provide a file for setting up equation of state")
            raise ValueError(msg)
        arr = np.loadtxt(self.eos_file)
        self.eos_radius = arr[:,0] / self.scalings_.radius
        self.eos_pressure = arr[:,1] / self.scalings_.pressure
        self.eos_density = arr[:,2] / self.scalings_.density
        self.eos_gravity = arr[:,3] / self.scalings_.gravitational_acceleration
        # Check that provided eos radius roughly match with Aragog mesh
        if ((self.eos_radius[0] < self.inner_radius) or
            (self.eos_radius[-1] > self.outer_radius) or
            (self.eos_radius[-1]-self.eos_radius[0]) < 0.75*(self.outer_radius-self.inner_radius)):
            msg: str = (f"Radius array in EOS file: Values out of range.")
            raise ValueError(msg)

_PhaseMixedParameters(latent_heat_of_fusion, rheological_transition_melt_fraction, rheological_transition_width, solidus, liquidus, phase, phase_transition_width, grain_size) dataclass

Stores settings in the phase_mixed section in the configuration data.

scale_attributes(scalings)

Scales the attributes

Args: scalings: scalings

Source code in aragog/parser.py
323
324
325
326
327
328
329
330
331
def scale_attributes(self, scalings: _ScalingsParameters) -> None:
    """Scales the attributes

    Args:
        scalings: scalings
    """
    self.scalings_ = scalings
    self.latent_heat_of_fusion /= self.scalings_.latent_heat_per_mass
    self.grain_size /= self.scalings_.radius

_PhaseParameters(density, heat_capacity, melt_fraction, thermal_conductivity, thermal_expansivity, viscosity) dataclass

Stores settings in a phase section in the configuration data.

This is used to store settings from phase_liquid and phase_solid.

scale_attributes(scalings)

Scales the attributes if they are numbers.

Args: scalings: scalings

Source code in aragog/parser.py
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
def scale_attributes(self, scalings: _ScalingsParameters) -> None:
    """Scales the attributes if they are numbers.

    Args:
        scalings: scalings
    """
    self.scalings_ = scalings
    cls_fields: tuple[Field, ...] = fields(self.__class__)
    for field_ in cls_fields:
        value: Any = getattr(self, field_.name)
        try:
            scaling: float = getattr(self.scalings_, field_.name)
            scaled_value = value / scaling
            setattr(self, field_.name, scaled_value)
            logger.info(
                "%s is a number (value = %s, scaling = %s, scaled_value = %s)",
                field_.name,
                value,
                scaling,
                scaled_value,
            )
        except AttributeError:
            logger.info("No scaling found for %s", field_.name)
        except TypeError:
            logger.info(
                "%s is a string (path to a filename) so the data will be scaled later",
                field_.name,
            )

_Radionuclide(name, t0_years, abundance, concentration, heat_production, half_life_years) dataclass

Stores the settings in a radionuclide section in the configuration data.

get_heating(time)

Radiogenic heating

Args: time: Time

Returns: Radiogenic heat production (power per unit mass) as a float if time is a float, otherwise a numpy row array where each entry in the row is associated with a single time in the time array.

Source code in aragog/parser.py
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
def get_heating(self, time: npt.NDArray | float) -> npt.NDArray | float:
    """Radiogenic heating

    Args:
        time: Time

    Returns:
        Radiogenic heat production (power per unit mass) as a float if time is a float,
            otherwise a numpy row array where each entry in the row is associated
            with a single time in the time array.
    """
    arg: npt.NDArray | float = np.log(2) * (self.t0_years - time) / self.half_life_years
    heating: npt.NDArray | float = (
        self.heat_production * self.abundance * self.concentration * np.exp(arg)
    )

    return heating

scale_attributes(scalings)

Scales the attributes.

Args: scalings: scalings

Source code in aragog/parser.py
391
392
393
394
395
396
397
398
399
400
401
def scale_attributes(self, scalings: _ScalingsParameters) -> None:
    """Scales the attributes.

    Args:
        scalings: scalings
    """
    self.scalings_ = scalings
    self.t0_years /= self.scalings_.time_years
    self.concentration *= 1e-6  # to mass fraction
    self.heat_production /= self.scalings_.power_per_mass
    self.half_life_years /= self.scalings_.time_years

_ScalingsParameters(radius=1, temperature=1, density=1, time=1) dataclass

Stores parameters in the scalings section in the configuration data. All units are SI.

Args: radius: Radius in metres. Defaults to 1. temperature: Temperature in Kelvin. Defaults to 1. density: Density in kg/m^3. Defaults to 1. time: Time in seconds. Defaults to 1.

Attributes: radius, m temperature, K density, kg/m^3 time, s area, m^2 kinetic_energy_per_volume, J/m^3 gravitational_acceleration, m/s^2 heat_capacity, J/kg/K heat_flux, W/m^2 latent_heat_per_mass, J/kg power_per_mass, W/kg power_per_volume, W/m^3 pressure, Pa temperature_gradient, K/m thermal_expansivity, 1/K thermal_conductivity, W/m/K velocity, m/s viscosity, Pa s time_years, years stefan_boltzmann_constant (non-dimensional)

_SolverParameters(start_time, end_time, atol, rtol, tsurf_poststep_change=30.0, event_triggering=False) dataclass

Stores settings in the solver section in the configuration data.

_get_dataclass_from_section_name()

Maps the section names in the configuration data to the dataclasses that stores the data.

Source code in aragog/parser.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def _get_dataclass_from_section_name() -> dict[str, Any]:
    """Maps the section names in the configuration data to the dataclasses that stores the data."""
    mapping: dict[str, Any] = {
        "scalings": _ScalingsParameters,
        "solver": _SolverParameters,
        "boundary_conditions": _BoundaryConditionsParameters,
        "mesh": _MeshParameters,
        "energy": _EnergyParameters,
        "initial_condition": _InitialConditionParameters,
        "phase_liquid": _PhaseParameters,
        "phase_solid": _PhaseParameters,
        "phase_mixed": _PhaseMixedParameters,
        # radionuclides are dealt with separately
    }

    return mapping