Source code for festim.exports.xdmf_export

import warnings
from festim import Export
import fenics as f
import numpy as np

field_to_label = {
    "solute": "mobile_concentration",
    "T": "temperature",
    "retention": "retention",
    "trap": "trap_i_concentration",
}


[docs] class XDMFExport(Export): """ Args: field (str): the exported field ("solute", "1", "retention", "T"...) label (str, optional): label of the field in the written file. If None, an automatic label will be given. Defaults to None. filename (str, optional): the file path, needs to end with '.xdmf'. If None, the label will be used. Defaults to None. mode (int, str, optional): if "last" only the last timestep will be exported. Otherwise the number of iterations between each export can be provided as an integer. Defaults to 1. checkpoint (bool, optional): If set to True, fenics.XDMFFile.write_checkpoint will be use, else fenics.XDMFFile.write. Defaults to True. folder (str, optional): path of the export folder. Defaults to None. """ def __init__( self, field, label=None, filename=None, mode=1, checkpoint=True, folder=None ) -> None: super().__init__(field=field) self.label = label self.folder = folder self.filename = filename self.files = None self.define_xdmf_file() self.mode = mode self.checkpoint = checkpoint if type(self.checkpoint) != bool: raise TypeError("checkpoint must be a bool") self.append = False @property def label(self): return self._label @label.setter def label(self, value): if value is None: if self.field in field_to_label.keys(): self._label = field_to_label[self.field] elif self.field.isdigit(): self._label = field_to_label["trap"].replace("i", self.field, 1) else: self._label = value @property def mode(self): return self._mode @mode.setter def mode(self, value): accepted_values = "accepted values for mode are int and 'last'" if not isinstance(value, (str, int)): raise ValueError(accepted_values) if isinstance(value, int) and value <= 0: raise ValueError("mode must be positive") if isinstance(value, str) and value != "last": raise ValueError(accepted_values) self._mode = value @property def folder(self): return self._folder @folder.setter def folder(self, value): if value is not None: if not isinstance(value, str): raise TypeError("folder must be a string") self._folder = value @property def filename(self): return self._filename @filename.setter def filename(self, value): if value is not None: if not isinstance(value, str): raise TypeError("filename must be a string") if not value.endswith(".xdmf"): raise ValueError("filename must end with .xdmf") self._filename = value else: self._filename = "{}.xdmf".format(self.label)
[docs] def define_xdmf_file(self): """Creates the file""" if self.folder is None: filename = self.filename else: filename = "{}/{}".format(self.folder, self.filename) self.file = f.XDMFFile(filename) self.file.parameters["flush_output"] = True self.file.parameters["rewrite_function_mesh"] = False
[docs] def write(self, t): """Writes to file Args: t (float): current time """ self.function.rename(self.label, "label") if self.checkpoint: # warn users if checkpoint is True and 1D dimension = self.function.function_space().mesh().topology().dim() if dimension == 1: msg = "in 1D, checkpoint needs to be set to False to " msg += "visualise the XDMF file in Paraview (see issue " msg += "https://github.com/festim-dev/festim/issues/134)" warnings.warn(msg) self.file.write_checkpoint( self.function, self.label, t, f.XDMFFile.Encoding.HDF5, append=self.append, ) else: self.file.write(self.function, t)
[docs] def is_export(self, t, final_time, nb_iterations): """Checks if export should be exported. Args: t (float): the current time final_time (float): the final time of the simulation nb_iterations (int): the current number of time steps Returns: bool: True if export should be exported, else False """ if self.mode == "last" and np.isclose(t, final_time, atol=0): return True elif isinstance(self.mode, int): if nb_iterations % self.mode == 0: return True return False