r""":mod:`mirgecom.materials.carbon_fiber` evaluate carbon fiber data.
.. autoclass:: Oxidation
.. autoclass:: FiberEOS
"""
__copyright__ = """
Copyright (C) 2023 University of Illinois Board of Trustees
"""
__license__ = """
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from abc import abstractmethod
import numpy as np
from meshmode.dof_array import DOFArray
from mirgecom.wall_model import PorousWallEOS
from pytools.obj_array import make_obj_array
[docs]
class Oxidation:
"""Abstract interface for wall oxidation model.
.. automethod:: get_source_terms
"""
[docs]
@abstractmethod
def get_source_terms(self, temperature: DOFArray,
tau: DOFArray, rhoY_o2: DOFArray) -> DOFArray: # noqa N803
r"""Source terms of fiber oxidation."""
raise NotImplementedError()
# TODO per MTC review, can we generalize the oxidation model?
# should we keep this in the driver?
class Y2_Oxidation_Model(Oxidation): # noqa N801
"""Evaluate the source terms for the Y2 model of carbon fiber oxidation.
.. automethod:: puma_effective_surface_area
.. automethod:: get_source_terms
"""
def puma_effective_surface_area(self, progress) -> DOFArray:
"""Polynomial fit based on PUMA data.
Parameters
----------
progress: meshmode.dof_array.DOFArray
the rate of decomposition of the fibers
"""
# Original fit function: -1.1012e5*x**2 - 0.0646e5*x + 1.1794e5
# Rescale by x==0 value and rearrange
return 1.1794e5*(1.0 - 0.0547736137*progress - 0.9336950992*progress**2)
def _get_wall_effective_surface_area_fiber(self, progress) -> DOFArray:
"""Evaluate the effective surface of the fibers.
Parameters
----------
progress: meshmode.dof_array.DOFArray
the rate of decomposition of the fibers
"""
return self.puma_effective_surface_area(progress)
def get_source_terms(self, temperature, tau, rhoY_o2) -> DOFArray: # noqa N803
"""Return the effective source terms for the oxidation.
Parameters
----------
temperature: meshmode.dof_array.DOFArray
tau: meshmode.dof_array.DOFArray
the progress ratio of the oxidation
ox_mass: meshmode.dof_array.DOFArray
the mass fraction of oxygen
"""
actx = temperature.array_context
mw_o = 15.999
mw_o2 = mw_o*2
mw_co = 28.010
univ_gas_const = 8314.46261815324
eff_surf_area = self._get_wall_effective_surface_area_fiber(1.0-tau)
alpha = (
(0.00143+0.01*actx.np.exp(-1450.0/temperature))
/ (1.0+0.0002*actx.np.exp(13000.0/temperature)))
k = alpha*actx.np.sqrt(
(univ_gas_const*temperature)/(2.0*np.pi*mw_o2))
return (mw_co/mw_o2 + mw_o/mw_o2 - 1)*rhoY_o2*k*eff_surf_area
[docs]
class FiberEOS(PorousWallEOS):
r"""Evaluate the properties of the solid state containing only fibers.
The properties are obtained as a function of oxidation progress. It can
be computed based on the mass $m$, which is related to the void fraction
$\epsilon$ and radius $r$ as:
.. math::
\tau = \frac{m}{m_0} = \frac{\rho_i \epsilon}{\rho_i \epsilon_0}
= \frac{r^2}{r_0^2}
.. automethod:: void_fraction
.. automethod:: enthalpy
.. automethod:: heat_capacity
.. automethod:: thermal_conductivity
.. automethod:: volume_fraction
.. automethod:: permeability
.. automethod:: emissivity
.. automethod:: tortuosity
.. automethod:: decomposition_progress
"""
def __init__(self, dim, anisotropic_direction, char_mass, virgin_mass):
"""Bulk density considering the porosity and intrinsic density."""
self._char_mass = char_mass
self._virgin_mass = virgin_mass
self._dim = dim
self._anisotropic_dir = anisotropic_direction
if anisotropic_direction > dim:
raise ValueError("Anisotropic axis must be less or equal than dim.")
[docs]
def void_fraction(self, tau: DOFArray) -> DOFArray:
r"""Return the volumetric fraction $\epsilon$ filled with gas.
The fractions of gas and solid phases must sum to one,
$\epsilon_g + \epsilon_s = 1$. Both depend only on the oxidation
progress ratio $\tau$.
"""
return 1.0 - self.volume_fraction(tau)
[docs]
def enthalpy(self, temperature, tau=None) -> DOFArray:
r"""Evaluate the solid enthalpy $h_s$ of the fibers."""
return (
- 3.37112113e-11*temperature**5 + 3.13156695e-07*temperature**4
- 1.17026962e-03*temperature**3 + 2.29194901e+00*temperature**2
- 3.62422269e+02*temperature**1 - 5.96993843e+04)
[docs]
def heat_capacity(self, temperature, tau=None) -> DOFArray:
r"""Evaluate the heat capacity $C_{p_s}$ of the fibers.
The coefficients are obtained with the analytical derivative of the
enthalpy fit.
"""
return (
- 1.68556056e-10*temperature**4 + 1.25262678e-06*temperature**3
- 3.51080885e-03*temperature**2 + 4.58389802e+00*temperature**1
- 3.62422269e+02)
# ~~~~~~~~ fiber conductivity
[docs]
def thermal_conductivity(self, temperature, tau=None) -> DOFArray:
r"""Evaluate the thermal conductivity $\kappa$ of the fibers.
It accounts for anisotropy and oxidation progress.
"""
kappa_ij = (
+ 2.86518890e-24*temperature**5 - 2.13976832e-20*temperature**4
+ 3.36320767e-10*temperature**3 - 6.14199551e-07*temperature**2
+ 7.92469194e-04*temperature**1 + 1.18270446e-01)
kappa_k = (
- 1.89693642e-24*temperature**5 + 1.43737973e-20*temperature**4
+ 1.93072961e-10*temperature**3 - 3.52595953e-07*temperature**2
+ 4.54935976e-04*temperature**1 + 5.08960039e-02)
# initialize with the in-plane value
kappa = make_obj_array([kappa_ij for _ in range(self._dim)])
# modify only the normal direction
kappa[self._anisotropic_dir] = kappa_k
# account for fiber shrinkage via "tau"
return kappa*tau
# ~~~~~~~~ other properties
[docs]
def volume_fraction(self, tau: DOFArray) -> DOFArray:
r"""Fraction $\phi$ occupied by the solid."""
return 0.12*tau
[docs]
def permeability(self, tau: DOFArray) -> DOFArray:
r"""Permeability $K$ of the porous material."""
# FIXME find a relation to make it change as a function of "tau"
actx = tau.array_context
permeability = np.zeros(self._dim,)
permeability[:] = 5.57e-11 + actx.np.zeros_like(tau)
permeability[self._anisotropic_dir] = 2.62e-11 + actx.np.zeros_like(tau)
return permeability
[docs]
def emissivity(self, temperature=None, tau=None) -> DOFArray:
"""Emissivity for energy radiation."""
return (
+ 2.26413679e-18*temperature**5 - 2.03008004e-14*temperature**4
+ 7.05300324e-11*temperature**3 - 1.22131715e-07*temperature**2
+ 1.21137817e-04*temperature**1 + 8.66656964e-01)
[docs]
def tortuosity(self, tau: DOFArray) -> DOFArray:
r"""Tortuosity $\eta$ affects the species diffusivity."""
# FIXME find a relation to make it change as a function of "tau"
actx = tau.array_context
return 1.1 + actx.np.zeros_like(tau)
[docs]
def decomposition_progress(self, mass: DOFArray) -> DOFArray:
r"""Evaluate the mass loss progress ratio $\tau$ of the oxidation."""
return mass/self._virgin_mass