Source code for nrv.fmod._materials

"""
NRV-:class:`.material` handling.
"""

import faulthandler
import os
import numpy as np
from scipy.constants import pi, epsilon_0

from ..backend._log_interface import rise_warning
from ..backend._NRV_Class import NRV_class
from ..backend._parameters import parameters

# enable faulthandler to ease "segmentation faults" debug
faulthandler.enable()

# get the built-in material librairy
dir_path = parameters.nrv_path + "/_misc"
material_library = os.listdir(dir_path + "/materials/")

###############
## Functions ##
###############


[docs] def is_mat(mat): """ check if an object is a material, return True if yes, else False Parameters ---------- mat : object object to test Returns ------- bool True it the type is a material object """ return isinstance(mat, material)
[docs] def get_mat_file_as_dict(fname): """ Open .mat material librairy file and return all lines as a dictionnary Returns ------- d : dictionnary physical properties of the material """ d = {} with open(fname, "r") as f: for line in f: key, value = line.split() d[key] = value return d
[docs] def load_material(f_material): """ Load a material by its name. if the name is in the NRV2 material librairy, the extention is automatically added. Parameters ---------- f_material : str either material name if the material is in the NRV2 Librairy or path to the corresponding\ .mat material file """ # load from librairy or from file f_in_librairy = str(f_material) + ".mat" if f_in_librairy in material_library: mat_file = get_mat_file_as_dict(dir_path + "/materials/" + f_in_librairy) else: mat_file = get_mat_file_as_dict(f_material) # creat material instance mat_obj = material() if "name" in mat_file: mat_obj.set_name(mat_file["name"]) if "source" in mat_file: mat_obj.set_source(mat_file["source"]) if "sigma_xx" in mat_file: mat_obj.set_anisotropic_conductivity( mat_file["sigma_xx"], mat_file["sigma_yy"], mat_file["sigma_zz"] ) elif "sigma" in mat_file: mat_obj.set_isotropic_conductivity(mat_file["sigma"]) else: rise_warning("loading a material with 0 conductivity, \ this may induce further division by 0") if "epsilon_r" in mat_file: mat_obj.set_permitivity(mat_file["epsilon_r"]) return mat_obj
[docs] def compute_effective_conductivity(sigma: float, epsilon: float, freq: float) -> float: r""" return the effective conductivity of the material. Two cases are psooible: - purely conductive material (when both `epsilon` or `freq` are set) .. math:: \sigma_{eff} = \sigma - dielectric material at a fixe frequency: .. math:: \sigma_{eff} = |\sigma+2j\pi f\epsilon_0\epsilon_r| Parameters ---------- sigma : float conductivity """ if epsilon is None or freq is None: return sigma return abs(sigma + 2j * pi * freq * epsilon_0 * epsilon)
#################### ## material class ## ####################
[docs] class material(NRV_class): """ a class for material, where all the physical properties constants are stored. by default materials in NRV are considerated as purely conductive. Yet, """
[docs] def __init__(self): """ material instantiation """ super().__init__() self.name = "" self.source = "" # Conduction properties self.isotrop_cond = True self._sigma = 0 self._sigma_xx = 0 self._sigma_yy = 0 self._sigma_zz = 0 self._sigma_func = None # permitivity property self.epsilon = None self.freq = None
@property def sigma(self): """ get the conductivity of the material """ if not self.is_isotropic(): return np.array([self.sigma_xx, self.sigma_yy, self.sigma_zz]) return compute_effective_conductivity( sigma=self._sigma, epsilon=self.epsilon, freq=self.freq ) @property def sigma_xx(self) -> float: """ get the conductivity of the material along ox """ if self.isotrop_cond: rise_warning("Isotropic conductor sigma_xx is sigma") return self.sigma return compute_effective_conductivity( sigma=self._sigma_xx, epsilon=self.epsilon, freq=self.freq ) @property def sigma_yy(self) -> float: """ get the conductivity of the material along oy """ if self.isotrop_cond: rise_warning("Isotropic conductor sigma_yy is sigma") return self.sigma return compute_effective_conductivity( sigma=self._sigma_yy, epsilon=self.epsilon, freq=self.freq ) @property def sigma_zz(self) -> float: """ get the conductivity of the material along oz """ if self.isotrop_cond: rise_warning("Isotropic conductor sigma_zz is sigma") return self.sigma return compute_effective_conductivity( sigma=self._sigma_zz, epsilon=self.epsilon, freq=self.freq )
[docs] def save_material(self, save=False, fname="material.json"): """ Deprecated alias of :meth:`save`. """ rise_warning("save_material is a deprecated method use save") self.save(save=save, fname=fname)
[docs] def load_material(self, data="material.json"): """ Deprecated alias of :meth:`load`. """ rise_warning("load_material is a deprecated method use load") self.load(data=data)
[docs] def set_name(self, name: str) -> None: """ set a name to a material Parameters ---------- name : str name of the material """ self.name = name
[docs] def set_source(self, source: str) -> None: """ set a source to a material. Note that this source is a string without spaces Parameters ---------- source : str scientific reference to the value, for clarity only """ self.source = source
[docs] def set_isotropic_conductivity(self, sigma: float | complex) -> None: """ set the conductivity for an isotropic material Parameters ---------- sigma : float conductivity in S/m """ self.isotrop_cond = True if isinstance(sigma, complex): self._sigma = sigma else: self._sigma = float(sigma)
[docs] def set_anisotropic_conductivity( self, sigma_xx: float, sigma_yy: float, sigma_zz: float ) -> None: """ set the conductivity tensor for an anisotropic material Parameters ---------- sigma_xx : float conductivity along the x axis, in S/m sigma_yy : float conductivity along the y axis, in S/m sigma_zz : float conductivity along the z axis, in S/m """ self.isotrop_cond = False self._sigma_xx = float(sigma_xx) self._sigma_yy = float(sigma_yy) self._sigma_zz = float(sigma_zz)
[docs] def is_isotropic(self) -> bool: """ check that the material is isotropic or not, return true if isotropic, else false Returns ------- bool : True if the per """ return self.isotrop_cond
## Permitivity relatied methods
[docs] def set_permitivity(self, epsilon: float) -> None: """ set the relative permitivity of the material. Note ---- The relative permetivity is used to compute an apparent conductivity at a frequency when ``freq``-attribute is set. Parameters ---------- epsilon : float relative permetivity in F/m """ self.epsilon = float(epsilon)
[docs] def set_frequency(self, freq: float) -> None: """ set the frequency of the electric field in the material Parameters ---------- freq : float frequency of the fields in to set in kHz """ self.freq = float(freq)
[docs] def clear_frequency(self) -> None: """ set the woking frequency to None Parameters ---------- freq : float frequency of the fields in to set in kHz """ self.freq = None
[docs] def is_permitive(self): """ check if the material permitivity and the electric field frequency are set """ return self.epsilon is not None and self.freq is not None