Source code for fluidsim_core.params

"""Solver parameters

.. autofunction:: iter_complete_params

.. autoclass:: Parameters
   :members:
   :private-members:

"""

from pathlib import Path

from typing import Iterable

import h5py
from fluiddyn.util import import_class, mpi
from fluiddyn.util.paramcontainer import ParamContainer

from .info import InfoSolverCore


[docs] def iter_complete_params(params, info_solver, classes: dict or Iterable): """Iterate over a collection of classes and invoke the static method ``_complete_params_with_default`` to populate an instance of :class:`Parameters` in-place. Parameters ---------- params : :class:`fluidsim_core.params.Parameters` or its subclass info_solver : :class:`fluidsim_core.info.InfoSolverCore` or its subclass classes : dict or iterable """ if isinstance(classes, dict): classes = [classes[key] for key in sorted(classes.keys())] for Class in classes: if hasattr(Class, "_complete_params_with_default"): try: Class._complete_params_with_default(params) except TypeError: try: Class._complete_params_with_default(params, info_solver) except TypeError as e: e.args += ("for class: " + repr(Class),) raise
[docs] class Parameters(ParamContainer): """Contain the parameters."""
[docs] @classmethod def _create_params(cls, input_info_solver): """Create a Parameters instance from an InfoSolverCore instance.""" if isinstance(input_info_solver, InfoSolverCore): info_solver = input_info_solver elif hasattr(input_info_solver, "Simul"): info_solver = input_info_solver.Simul.create_default_params() else: raise ValueError( "Can not create params from input input_info_solver." ) params = cls(tag="params") dict_classes = { "Solver": import_class( info_solver.module_name, info_solver.class_name ) } dict_classes.update(info_solver.import_classes()) iter_complete_params(params, info_solver, dict_classes.values()) return params
[docs] @classmethod def _load_params_simul(cls, path=None, only_mpi_rank0=True): """Load the parameters and return a Parameters instance.""" if mpi.rank > 0 and not only_mpi_rank0: params = None else: if path is None: path = Path.cwd() else: path = Path(path) path_xml = None if path.is_dir(): path_xml = path / "params_simul.xml" elif path.name.endswith(".xml"): if not path.exists(): raise ValueError(f"The file {path} does not exists.") path_xml = path if path_xml is not None and path_xml.exists(): params = cls(path_file=path_xml) else: if path.is_file(): paths = [path] else: paths = list(path.glob("state_*")) if paths: path = sorted(paths)[0] str_path = str(path) if len(str_path) > 100: str_path = "[...]" + str_path[-100:] print("Loading params from file\n" + str_path) with h5py.File(path, "r") as h5file: params = cls(hdf5_object=h5file["/info_simul/params"]) else: raise ValueError(f"No state files found in {path = }") if mpi.nb_proc > 1 and not only_mpi_rank0: params = mpi.comm.bcast(params, root=0) return params
[docs] @classmethod def _load_info_solver(cls, path_dir=None): """Load the solver information, return an InfoSolverCore instance.""" if path_dir is None: path_dir = Path.cwd() if not isinstance(path_dir, Path): path_dir = Path(path_dir) if not path_dir.is_dir(): raise ValueError(str(path_dir) + " is not a directory") path_info_solver = path_dir / "info_solver.xml" if path_info_solver.exists(): return cls(path_file=str(path_info_solver)) paths = sorted(path_dir.glob("state_*")) if not paths: raise ValueError("No result files in dir " + str(path_dir)) str_path = path = str(paths[0]) if len(path) > 100: str_path = "[...]" + path[-100:] mpi.printby0("load params from file\n" + str_path) with h5py.File(path, "r") as h5file: return cls(hdf5_object=h5file["/info_simul/solver"])
def __ior__(self, other): """Defines operator `|=` This operator performs a union with other Parameters instances. In simpler words, merge missing attributes and children (members). Do note, this does not check for mismatch in the parameter values. Parameters ---------- other: Parameters Another Parameters instance to look for missing members. Returns ------- Parameters """ if not isinstance(other, type(self)): raise TypeError( f"{type(other)}. Can only merge instances of Parameters." ) params1 = self params2 = other # Merge attributes diff_attribs = set(params2._key_attribs) - set(params1._key_attribs) if len(diff_attribs) > 0: print("Add parameter attributes: ", diff_attribs) for attrib in diff_attribs: params1._set_attrib(attrib, params2[attrib]) # Merge children diff_children = set(params2._tag_children) - set(params1._tag_children) internal_attribs = [ "attribs", "children", "key_attribs", "tag", "tag_children", ] if len(diff_children) > 0: print("Add parameter children: ", diff_children) for child in diff_children: child_attribs = params2[child]._make_dict() # Clean up internal attributes from dictionary list(map(child_attribs.__delitem__, internal_attribs)) params1._set_child(child, child_attribs) # Recursive for child in params2._tag_children: params1[child] |= params2[child] return self