From 5b3e8ee64b535b13e904a1659b1f19b2db9c6ce5 Mon Sep 17 00:00:00 2001 From: Roberto Porcu Date: Tue, 25 Jun 2024 13:01:47 -0400 Subject: [PATCH 1/9] Improve the chemical reactions section --- .../user_guide/inputs/chemical_reactions.rst | 67 ++++++++++++++++--- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/docs/source_docs/user_guide/inputs/chemical_reactions.rst b/docs/source_docs/user_guide/inputs/chemical_reactions.rst index 73111dd..96ba227 100644 --- a/docs/source_docs/user_guide/inputs/chemical_reactions.rst +++ b/docs/source_docs/user_guide/inputs/chemical_reactions.rst @@ -1,14 +1,58 @@ Chemical Reactions ================== -Enabling the Chemical Reactions solver and specifying model options. +MFIX-Exa allows the definition of intra-phase and inter-phase chemical +reactions. Intra-phase reactions are those happening within the same phase, for +example from the fluid to the fluid phase, and from the solid to the solid phase +within each solid particle. Inter-phase reactions are those involving two +different phases, for example from the solid to the fluid phase, or vice-versa. -+-------------------------+----------------------------------------------------------------------+----------+-----------+ -| | Description | Type | Default | -+=========================+======================================================================+==========+===========+ -| chemistry.solve | Specified name(s) of the chemical reactions types or None to disable | String | None | -| | the reactions solver. | | | -+-------------------------+----------------------------------------------------------------------+----------+-----------+ +MFIX-Exa categorizes the chemical reactions into two classes, "Eulerian" and +"Lagrangian" reactions. Intra-phase reactions happening within the fluid phase +are Eulerian reactions, while intra-phase reactions happening within the solid +phase are Lagrangian reactions. Inter-phase reactions are always categorized as +Lagrangian reactions. + +MFIX-Exa solves the Eulerian reactions by looping over all the regular and +cut-cells and computing the reactions rates for all the intra-phase chemical +reactions happening within the fluid phase. MFIX-Exa solves the Lagrangian +reactions by looping over all the particles within each cell and computing the +reactions rates for the inter-phase reactions and for the intra-phase ones +happening within the solid phase. + +Users can define Eulerian and Lagrangian reaction rates by properly modifying +the file ``src/usr/mfix_usr_reactions_rates_K.H``. This header file is where +MFIX-Exa looks for the definitions of the "user-defined functions" (UDFs) for +the chemical reactions rates. Eulerian reactions are treated as volumetric +reactions, thus MFIX-Exa expects user-defined Eulerian rates in terms of moles +per second per cubic-meter (SI units :math:`[mol \cdot s^{-1} \cdot m^{-3}]`). +Lagrangian reactions instead are considered to happen at the location of the +solid particle involved, and MFIx-Exa expects user-defined Lagrangian rates in +terms of moles per second (SI units :math:`[mol \cdot s^{-1}]`). User-defined +rates for either Eulerian and Lagrangian reactions must be implemented in the +``operator()`` method of the corresponding classes that in file +``src/usr/mfix_usr_reactions_rates_K.H`` are declared as *EulerianReactionRates* +and *LagrangianReactionRates*. + +The ``operator()`` method for the *EulerianReactionRates* class gets two +arguments, *reactions* and *fluid*, that are two classes from which the user can +extract the data needed to implement the corresponding rates. For the +*LagrangianReactionRates* holds the same principle, with the addition of a third +argument, *solids*, which is a class containing data for the solid particle +involved in the reaction. + + + + +What follows is a description and an example of how inputs need to be specified +for enabling chemical reactions in MFIX-Exa. + ++------------------------+---------------------------------------------------------+----------+-----------+ +| | Description | Type | Default | ++========================+=========================================================+==========+===========+ +| chemistry.solve | Specified name(s) of the chemical reactions types or | String | None | +| | None to disable the reactions solver. | | | ++------------------------+---------------------------------------------------------+----------+-----------+ The following inputs must be preceded by the "chemistry." prefix @@ -24,7 +68,12 @@ The following inputs must be preceded by the "chemistry." prefix .. code-block:: none + species.solve = Fe2O3 CO FeO CO2 O2 + + fluid.species = CO CO2 O2 + solids.species = Fe2O3 FeO + chemistry.solve = my_reaction0 my_reaction1 - my_reaction0.reaction = Fe2O3(s)+CO(g)-->2.FeO(s)+CO2(g) - my_reaction1.reaction = FeO(s)+0.25O2(g)-->0.5Fe2O3(s) + chemistry.my_reaction0.reaction = Fe2O3(s)+CO(g)-->2.FeO(s)+CO2(g) + chemistry.my_reaction1.reaction = FeO(s)+0.25O2(g)-->0.5Fe2O3(s) -- GitLab From 307c1412ffb5f545924aed1f52b868ef1532d573 Mon Sep 17 00:00:00 2001 From: Roberto Porcu Date: Tue, 25 Jun 2024 13:08:56 -0400 Subject: [PATCH 2/9] minor changes --- .../user_guide/inputs/chemical_reactions.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source_docs/user_guide/inputs/chemical_reactions.rst b/docs/source_docs/user_guide/inputs/chemical_reactions.rst index 96ba227..d39a0df 100644 --- a/docs/source_docs/user_guide/inputs/chemical_reactions.rst +++ b/docs/source_docs/user_guide/inputs/chemical_reactions.rst @@ -30,16 +30,16 @@ Lagrangian reactions instead are considered to happen at the location of the solid particle involved, and MFIx-Exa expects user-defined Lagrangian rates in terms of moles per second (SI units :math:`[mol \cdot s^{-1}]`). User-defined rates for either Eulerian and Lagrangian reactions must be implemented in the -``operator()`` method of the corresponding classes that in file -``src/usr/mfix_usr_reactions_rates_K.H`` are declared as *EulerianReactionRates* -and *LagrangianReactionRates*. +``operator()`` method of the corresponding classes that are declared as +*EulerianReactionRates* and *LagrangianReactionRates* in the file +``src/usr/mfix_usr_reactions_rates_K.H``. The ``operator()`` method for the *EulerianReactionRates* class gets two arguments, *reactions* and *fluid*, that are two classes from which the user can extract the data needed to implement the corresponding rates. For the -*LagrangianReactionRates* holds the same principle, with the addition of a third -argument, *solids*, which is a class containing data for the solid particle -involved in the reaction. +``operator()`` of the *LagrangianReactionRates* class it holds the same +principle with the addition of a third argument, *solids*, which is a class +containing data for the solid particle involved in the reaction. -- GitLab From 18184c835f27499fe3064f408c9cccda1ee5dd78 Mon Sep 17 00:00:00 2001 From: Roberto Porcu Date: Wed, 26 Jun 2024 16:02:15 -0400 Subject: [PATCH 3/9] updated chemistry chapter --- docs/source_docs/Chemistry_Chapter.rst | 254 ++++++++++++++++ docs/source_docs/index.rst | 1 + .../user_guide/inputs/chemical_reactions.rst | 279 +++++++++++++----- 3 files changed, 468 insertions(+), 66 deletions(-) create mode 100644 docs/source_docs/Chemistry_Chapter.rst diff --git a/docs/source_docs/Chemistry_Chapter.rst b/docs/source_docs/Chemistry_Chapter.rst new file mode 100644 index 0000000..2829f74 --- /dev/null +++ b/docs/source_docs/Chemistry_Chapter.rst @@ -0,0 +1,254 @@ +.. _Chap:Chemistry: + +Here we describe the chemistry model. + +Chemical Reactions +================== + +MFIX-Exa allows the definition of intra-phase and inter-phase chemical +reactions. Intra-phase reactions are those happening within the same phase, for +example from the fluid to the fluid phase, and from the solid to the solid phase +within each solid particle. Inter-phase reactions are those involving two +different phases, for example from the solid to the fluid phase, or vice-versa. + +MFIX-Exa categorizes the chemical reactions into two classes, "Eulerian" and +"Lagrangian" reactions. Intra-phase reactions happening within the fluid phase +are Eulerian reactions, while intra-phase reactions happening within the solid +phase are Lagrangian reactions. Inter-phase reactions are always categorized as +Lagrangian reactions. + +MFIX-Exa solves the Eulerian reactions by looping over all the regular and +cut-cells and computing the reactions rates for all the intra-phase chemical +reactions happening within the fluid phase. MFIX-Exa solves the Lagrangian +reactions by looping over all the particles within each cell and computing the +reactions rates for the inter-phase reactions and for the intra-phase ones +happening within the solid phase. + +Users can define Eulerian and Lagrangian reaction rates by properly modifying +the file ``src/usr/mfix_usr_reactions_rates_K.H``. This header file is where +MFIX-Exa looks for the definitions of the "user-defined functions" (UDFs) for +the chemical reactions rates. Eulerian reactions are treated as volumetric +reactions, thus MFIX-Exa expects user-defined Eulerian rates in terms of moles +per second per cubic-meter (SI units :math:`[mol \cdot s^{-1} \cdot m^{-3}]`). +Lagrangian reactions instead are considered to happen at the location of the +solid particle involved, and MFIx-Exa expects user-defined Lagrangian rates in +terms of moles per second (SI units :math:`[mol \cdot s^{-1}]`). User-defined +rates for either Eulerian and Lagrangian reactions must be implemented in the +``operator()`` method of the corresponding classes that are declared as +*EulerianReactionRates* and *LagrangianReactionRates* in the file +``src/usr/mfix_usr_reactions_rates_K.H``. + +The ``operator()`` method for the *EulerianReactionRates* class gets two +arguments, *reactions* and *fluid*, that are two classes from which the user can +extract the data needed to implement the corresponding rates. For the +``operator()`` of the *LagrangianReactionRates* class it holds the same +principle with the addition of a third argument, *solids*, which is a class +containing data for the solid particle involved in the reaction. + +.. code-block:: cpp + + class LagrangianReactionRates + { + public: + /** + * Reactions class gives access to the following reactions quantities: + * - rate(q) with q in [0,reactions_nb] + * - rate("reaction_name") + * - time() + * - dt() + * - cell_volume() + * + * Fluid class gives access to the following fluid quantities: + * - shear_viscosity() + * - volume_fraction() + * - density() + * - velocity() and velocity(dir) with dir in [0,AMREX_SPACEDIM] + * - thermodynamic_pressure() + * - temperature() + * - specific_enthalpy() + * - mass_fraction(n_g) with n_g in [0,fluid_nb_species] + * - mass_fraction("species_name") + * - molar_concentration(n_g) with n_g in [0,fluid_nb_species] + * - molar_concentration("species_name") + * - molar_mass(n_g) with n_g in [0,fluid_nb_species] + * - molar_mass("species_name") + * - average_molar_mass() + * - mole_fraction(n_g) with n_g in [0,fluid_nb_species] + * - mole_fraction("species_name") + * + * Solids class gives access to the following solids quantities: + * - position() and position(dir) with dir in [0,AMREX_SPACEDIM] + * - radius() + * - volume() + * - density() + * - mass() + * - oneOverI() + * - statistical_weight() + * - velocity() and velocity(dir) with dir in [0,AMREX_SPACEDIM] + * - temperature() + * - specific_heat_capacity() + * - mass_fraction(n_s) with n_s in [0,solids_nb_species] + * - mass_fraction("species_name") + * - molar_concentration(n_g) with n_g in [0,solids_nb_species] + * - molar_concentration("species_name") + * - molar_mass(n_g) with n_g in [0,solids_nb_species] + * - molar_mass("species_name") + * - average_molar_mass() + * - mole_fraction(n_g) with n_g in [0,solids_nb_species] + * - mole_fraction("species_name") + */ + template + AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + void operator() (Reactions& reactions, + const Fluid& fluid, + const Solids& solids) const + { + // User defined Lagrangian reactions rates go here + } + }; + + + + + +.. code-block:: cpp + + class EulerianReactionRates + { + public: + /** + * Reactions class gives access to the following reactions quantities: + * - rate(q) with q in [0,reactions_nb] + * - rate("reaction_name") + * - time() + * - dt() + * - cell_volume() + * + * Fluid class gives access to the following fluid quantities: + * - shear_viscosity() + * - volume_fraction() + * - density() + * - velocity() and velocity(dir) with dir in [0,AMREX_SPACEDIM] + * - thermodynamic_pressure() + * - temperature() + * - specific_enthalpy() + * - mass_fraction(n_g) with n_g in [0,fluid_nb_species] + * - mass_fraction("species_name") + * - molar_concentration(n_g) with n_g in [0,fluid_nb_species] + * - molar_concentration("species_name") + * - molar_mass(n_g) with n_g in [0,fluid_nb_species] + * - molar_mass("species_name") + * - average_molar_mass() + * - mole_fraction(n_g) with n_g in [0,fluid_nb_species] + * - mole_fraction("species_name") + */ + template + AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + void operator() (Reactions& reactions, + const Fluid& fluid) const + { + // User defined Eulerian reactions rates go here + } + }; + + +Example rates UDFs +================== + +Abad + +.. code-block:: cpp + + class LagrangianReactionRates + { + public: + template + AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + void operator() (Reactions& reactions, + const Fluid& fluid, + const Solids& solids) const + { + // Gas constant + constexpr amrex::Real Ru = 8.314459; /* (J/mole.K) */ + + constexpr amrex::Real Tmax = 1200.; /* (K) */ + constexpr amrex::Real Tmin = 300.; /* (K) */ + + // Particle diameter, volume and initial density + constexpr amrex::Real vol_p = solids.volume(); /* (m^3) */ + constexpr amrex::Real ro_p_o = solids.density(); /* (kg/m^3) */ + + // Reduction reaction constants (m^2 / mole) + constexpr amrex::Real const_CH4 = 4.74 / ( 1.25e-6 * 13.59e+3); + constexpr amrex::Real const_H2 = 1.19 / ( 1.25e-6 * 13.59e+3); + constexpr amrex::Real const_CO = 1.19 / ( 1.25e-6 * 13.59e+3); + constexpr amrex::Real const_O2 = 4.00 / ( 1.20e-6 * 31.10e+3); + + // Initial mass of FE2O3 at time zero (kg) + constexpr amrex::Real mo = ro_p_o*vol_p; + + // Current particle mass (kg) + const amrex::Real mass_p = vol_p * ro_p; + + // maximum conversion + const amrex::Real Rlim = 0.25*0.5*MW_O2/MW_Fe2O3 - 1.0e-10; + + // conversion + const amrex::Real X_r = amrex::min(amrex::max((mo - mass_p)/ (Rlim * mo), 0.0), 1.0); + + const amrex::Real xTp = amrex::max(amrex::min(T_p, Tmax), Tmin); + + // Molar concentration of gas reactants (mole / m^3) + const amrex::Real c_CH4 = (fluid.mass_fraction("CH4") < 1.e-6) ? 0 : fluid.molar_concentration("CH4"); + const amrex::Real c_H2 = (fluid.mass_fraction("H2") < 1.e-6) ? 0 : fluid.molar_concentration("H2"); + const amrex::Real c_CO = (fluid.mass_fraction("CO") < 1.e-6) ? 0 : fluid.molar_concentration("CO"); + const amrex::Real c_O2 = (fluid.mass_fraction("O2") < 1.e-6) ? 0 : fluid.molar_concentration("O2"); + + // Constant multiplier common to all hematite REDUCTION reactions (mole) + const amrex::Real const_r = 6.0 * Rlim * (1./fluid.mass_fraction("O2")) * mo + * std::pow((1.0-X_r), 0.667); + + // Constant multiplier common to the wustite OXIDATION reaction (mole), note: X_o = 1 - X_r + const amrex::Real const_o = 12.0 * Rlim * (1./fluid.mass_fraction("O2")) * mo + * std::pow((X_r), 0.667); + + // Reduction by Methane: 4FE2O3 + CH4 --> 8FEO + CO2 + 2H2O + //---------------------------------------------------------------------// + + // reaction rate constant (as in the Arrhenius rate) in m/s + const amrex::Real k0_CH4 = 9.80 * std::exp(-135.2e+3/(Ru*xTp)); + + reactions.rate("Hem_CH4") = const_r * const_CH4 * k0_CH4 * c_CH4; + + + // Reduction by Hydrogen: Fe2O3 + H2 --> 2FeO + H2O + //---------------------------------------------------------------------// + + // reaction rate constant (as in the Arrhenius rate) in m/s + const amrex::Real k0_H2 = 0.062 * std::exp(-65.0e+3/(Ru*xTp)); + + reactions.rate("Hem_H2") = const_r * const_H2 * k0_H2 * c_H2; + + + // Reduction by Carbon Monoxide: Fe2O3 + CO --> 2FeO + CO2 + //---------------------------------------------------------------------// + + // reaction rate constant (as in the Arrhenius rate) in m/s + const amrex::Real k0_CO = 0.10 * std::exp(-80.7e+3/(Ru*xTp)); + + reactions.rate("Hem_CO") = const_r * const_CO * k0_CO * std::pow(c_CO, 0.8); + + + // Oxidation: 4FeO + O2 --> 2Fe2O3 + //---------------------------------------------------------------------// + + // reaction rate constant (as in the Arrhenius rate) in m/s + const amrex::Real k0_O2 = 1.9e-3 * std::exp(-25.5e+3/(Ru*xTp)); + + reactions.rate("Wus_O2") = const_o * const_O2 * k0_O2 * c_O2; + } + }; + + +.. toctree:: + :maxdepth: 0 diff --git a/docs/source_docs/index.rst b/docs/source_docs/index.rst index 7d9dc38..2a3e039 100644 --- a/docs/source_docs/index.rst +++ b/docs/source_docs/index.rst @@ -56,6 +56,7 @@ To learn more about the implementation, follow the following reference sections: references/units Fluids_Chapter Particles_Chapter + Chemistry_Chapter EB_Chapter references/hpc Debugging diff --git a/docs/source_docs/user_guide/inputs/chemical_reactions.rst b/docs/source_docs/user_guide/inputs/chemical_reactions.rst index d39a0df..63104ca 100644 --- a/docs/source_docs/user_guide/inputs/chemical_reactions.rst +++ b/docs/source_docs/user_guide/inputs/chemical_reactions.rst @@ -1,79 +1,226 @@ Chemical Reactions ================== -MFIX-Exa allows the definition of intra-phase and inter-phase chemical -reactions. Intra-phase reactions are those happening within the same phase, for -example from the fluid to the fluid phase, and from the solid to the solid phase -within each solid particle. Inter-phase reactions are those involving two -different phases, for example from the solid to the fluid phase, or vice-versa. - -MFIX-Exa categorizes the chemical reactions into two classes, "Eulerian" and -"Lagrangian" reactions. Intra-phase reactions happening within the fluid phase -are Eulerian reactions, while intra-phase reactions happening within the solid -phase are Lagrangian reactions. Inter-phase reactions are always categorized as -Lagrangian reactions. - -MFIX-Exa solves the Eulerian reactions by looping over all the regular and -cut-cells and computing the reactions rates for all the intra-phase chemical -reactions happening within the fluid phase. MFIX-Exa solves the Lagrangian -reactions by looping over all the particles within each cell and computing the -reactions rates for the inter-phase reactions and for the intra-phase ones -happening within the solid phase. - -Users can define Eulerian and Lagrangian reaction rates by properly modifying -the file ``src/usr/mfix_usr_reactions_rates_K.H``. This header file is where -MFIX-Exa looks for the definitions of the "user-defined functions" (UDFs) for -the chemical reactions rates. Eulerian reactions are treated as volumetric -reactions, thus MFIX-Exa expects user-defined Eulerian rates in terms of moles -per second per cubic-meter (SI units :math:`[mol \cdot s^{-1} \cdot m^{-3}]`). -Lagrangian reactions instead are considered to happen at the location of the -solid particle involved, and MFIx-Exa expects user-defined Lagrangian rates in -terms of moles per second (SI units :math:`[mol \cdot s^{-1}]`). User-defined -rates for either Eulerian and Lagrangian reactions must be implemented in the -``operator()`` method of the corresponding classes that are declared as -*EulerianReactionRates* and *LagrangianReactionRates* in the file -``src/usr/mfix_usr_reactions_rates_K.H``. - -The ``operator()`` method for the *EulerianReactionRates* class gets two -arguments, *reactions* and *fluid*, that are two classes from which the user can -extract the data needed to implement the corresponding rates. For the -``operator()`` of the *LagrangianReactionRates* class it holds the same -principle with the addition of a third argument, *solids*, which is a class -containing data for the solid particle involved in the reaction. - - - - -What follows is a description and an example of how inputs need to be specified -for enabling chemical reactions in MFIX-Exa. +The following inputs are defined using the ``chemistry`` prefix. +------------------------+---------------------------------------------------------+----------+-----------+ | | Description | Type | Default | +========================+=========================================================+==========+===========+ -| chemistry.solve | Specified name(s) of the chemical reactions types or | String | None | -| | None to disable the reactions solver. | | | +| solve | Specify the name(s) of the chemical reactions or set | String | None | +| | to None to disable the chemistry solver. The name(s) | | | +| | assigned to the chemistry solver are used to specify | | | +| | the chemical reactions equations. | | | +------------------------+---------------------------------------------------------+----------+-----------+ - -The following inputs must be preceded by the "chemistry." prefix - -+------------------------+---------------------------------------------------------+----------+-----------+ -| | Description | Type | Default | -+========================+=========================================================+==========+===========+ -| [reaction0].reaction | Chemical formula for the given reaction. The string | String | None | -| | given as input must not contain white spaces and | | | -| | the reaction direction has to be specified as '-->' | | | -| | or '<--'. Chemical species phases must be defined as | | | -| | '(g)' for the fluid phase or '(s)' for the solid phase. | | | +| [reaction0].reaction | Chemical equation for the given reaction. The reaction | String | None | +| | direction has to be specified as '\-\->' or '<\-\-'. | | | +| | The phase of each chemical species in the reaction must | | | +| | be defined by '(g)' for the fluid phase or '(s)' for | | | +| | the solid phase. | | | +------------------------+---------------------------------------------------------+----------+-----------+ -.. code-block:: none - - species.solve = Fe2O3 CO FeO CO2 O2 +Example inputs +============== + +The following setup shows how to define chemical reactions in the inputs file. +Only ``Ideal Gas`` constraint types can be used when solving chemistry, as the +``IncompressibleFluid`` constraint would be inconsistent with the nature of +a problem where the fluid density is not constant because of mass transfer due +to chemical reactions. + +.. code-block:: bash + + mfix.constraint_type = IdealGasOpenSystem + + mfix.advect_density = 1 + mfix.advect_enthalpy = 1 + mfix.solve_species = 1 + + # Species model settings + #---------------------------------------------------------------------- + species.solve = CH4 H2 CO H2O CO2 O2 N2 Fe2O3 FeO inert + + species.diffusivity = constant + species.diffusivity.constant = 2.31000e-5 # m^2 / sec + + species.specific_heat = NASA7-poly + + # Methane + species.CH4.molecular_weight = 16.04276e-3 + species.CH4.specific_heat.NASA7.a0 = 5.14911468E+00 1.65326226E+00 + species.CH4.specific_heat.NASA7.a1 = -1.36622009E-02 1.00263099E-02 + species.CH4.specific_heat.NASA7.a2 = 4.91453921E-05 -3.31661238E-06 + species.CH4.specific_heat.NASA7.a3 = -4.84246767E-08 5.36483138E-10 + species.CH4.specific_heat.NASA7.a4 = 1.66603441E-11 -3.14696758E-14 + species.CH4.specific_heat.NASA7.a5 = -1.02465983E+04 -1.00095936E+04 + + # Hydrogen + species.H2.molecular_weight = 2.01588e-3 + species.H2.specific_heat.NASA7.a0 = 2.34433112E+00 2.93286575E+00 + species.H2.specific_heat.NASA7.a1 = 7.98052075E-03 8.26608026E-04 + species.H2.specific_heat.NASA7.a2 = -1.94781510E-05 -1.46402364E-07 + species.H2.specific_heat.NASA7.a3 = 2.01572094E-08 1.54100414E-11 + species.H2.specific_heat.NASA7.a4 = -7.37611761E-12 -6.88804800E-16 + species.H2.specific_heat.NASA7.a5 = -9.17935173E+02 -8.13065581E+02 + + # Carbon monoxide + species.CO.molecular_weight = 28.01040e-3 + species.CO.specific_heat.NASA7.a0 = 3.57953350E+00 3.04848590E+00 + species.CO.specific_heat.NASA7.a1 = -6.10353690E-04 1.35172810E-03 + species.CO.specific_heat.NASA7.a2 = 1.01681430E-06 -4.85794050E-07 + species.CO.specific_heat.NASA7.a3 = 9.07005860E-10 7.88536440E-11 + species.CO.specific_heat.NASA7.a4 = -9.04424490E-13 -4.69807460E-15 + species.CO.specific_heat.NASA7.a5 = -1.43440860E+04 -1.42661170E+04 + + # Water vapor + species.H2O.molecular_weight = 18.01528e-3 + species.H2O.specific_heat.NASA7.a0 = 0.41986352E+01 0.26770389E+01 + species.H2O.specific_heat.NASA7.a1 = -0.20364017E-02 0.29731816E-02 + species.H2O.specific_heat.NASA7.a2 = 0.65203416E-05 -0.77376889E-06 + species.H2O.specific_heat.NASA7.a3 = -0.54879269E-08 0.94433514E-10 + species.H2O.specific_heat.NASA7.a4 = 0.17719680E-11 -0.42689991E-14 + species.H2O.specific_heat.NASA7.a5 = -0.30293726E+05 -0.29885894E+05 + + # Carbon dioxide + species.CO2.molecular_weight = 44.00980e-3 + species.CO2.specific_heat.NASA7.a0 = 2.35681300E+00 4.63651110E+00 + species.CO2.specific_heat.NASA7.a1 = 8.98412990E-03 2.74145690E-03 + species.CO2.specific_heat.NASA7.a2 = -7.12206320E-06 -9.95897590E-07 + species.CO2.specific_heat.NASA7.a3 = 2.45730080E-09 1.60386660E-10 + species.CO2.specific_heat.NASA7.a4 = -1.42885480E-13 -9.16198570E-15 + species.CO2.specific_heat.NASA7.a5 = -4.83719710E+04 -4.90249040E+04 + + # Oxygen + species.O2.molecular_weight = 31.99880e-3 + species.O2.specific_heat.NASA7.a0 = 3.78245636E+00 3.66096065E+00 + species.O2.specific_heat.NASA7.a1 = -2.99673416E-03 6.56365811E-04 + species.O2.specific_heat.NASA7.a2 = 9.84730201E-06 -1.41149627E-07 + species.O2.specific_heat.NASA7.a3 = -9.68129509E-09 2.05797935E-11 + species.O2.specific_heat.NASA7.a4 = 3.24372837E-12 -1.29913436E-15 + species.O2.specific_heat.NASA7.a5 = -1.06394356E+03 -1.21597718E+03 + + # Nitrogen + species.N2.molecular_weight = 28.01340e-3 + species.N2.specific_heat.NASA7.a0 = 3.53100528E+00 2.95257637E+00 + species.N2.specific_heat.NASA7.a1 = -1.23660988E-04 1.39690040E-03 + species.N2.specific_heat.NASA7.a2 = -5.02999433E-07 -4.92631603E-07 + species.N2.specific_heat.NASA7.a3 = 2.43530612E-09 7.86010195E-11 + species.N2.specific_heat.NASA7.a4 = -1.40881235E-12 -4.60755204E-15 + species.N2.specific_heat.NASA7.a5 = -1.04697628E+03 -9.23948688E+02 + + # Hematite + species.Fe2O3.molecular_weight = 159.68820e-3 + species.Fe2O3.specific_heat.NASA7.a0 = 1.52218166E-01 2.09445369E+01 + species.Fe2O3.specific_heat.NASA7.a1 = 6.70757040E-02 0.00000000E+00 + species.Fe2O3.specific_heat.NASA7.a2 = -1.12860954E-04 0.00000000E+00 + species.Fe2O3.specific_heat.NASA7.a3 = 9.93356662E-08 0.00000000E+00 + species.Fe2O3.specific_heat.NASA7.a4 = -3.27580975E-11 0.00000000E+00 + species.Fe2O3.specific_heat.NASA7.a5 = -1.01344092E+05 -1.07936580E+05 + + # Wustite + species.FeO.molecular_weight = 71.84440e-3 + species.FeO.specific_heat.NASA7.a0 = 3.68765953E+00 1.81588527E+00 + species.FeO.specific_heat.NASA7.a1 = 1.09133433E-02 1.70742829E-02 + species.FeO.specific_heat.NASA7.a2 = -1.61179493E-05 -2.39919190E-05 + species.FeO.specific_heat.NASA7.a3 = 1.06449256E-08 1.53690046E-08 + species.FeO.specific_heat.NASA7.a4 = -2.39514915E-12 -3.53442390E-12 + species.FeO.specific_heat.NASA7.a5 = -3.34867527E+04 -3.30239565E+04 + + # inert + species.inert.molecular_weight = 92.82399e-3 + species.inert.specific_heat.NASA7.a0 = 1.52218166E-01 2.09445369E+01 + species.inert.specific_heat.NASA7.a1 = 6.70757040E-02 0.00000000E+00 + species.inert.specific_heat.NASA7.a2 = -1.12860954E-04 0.00000000E+00 + species.inert.specific_heat.NASA7.a3 = 9.93356662E-08 0.00000000E+00 + species.inert.specific_heat.NASA7.a4 = -3.27580975E-11 0.00000000E+00 + species.inert.specific_heat.NASA7.a5 = -1.01344092E+05 -1.07936580E+05 + + + # Fluid model settings + #---------------------------------------------------------------------- + fluid.solve = fluid + + fluid.thermodynamic_pressure = 101325. + fluid.reference_temperature = 298.15 + + fluid.species = CH4 H2 CO H2O CO2 O2 N2 + + fluid.viscosity = constant + fluid.viscosity.constant = 4.73e-5 #air @ 1200K + + fluid.specific_heat = mixture + + fluid.thermal_conductivity = constant + fluid.thermal_conductivity.constant = 0.024 + + + # Solids model settings + #---------------------------------------------------------------------- + solids.types = solid0 + solids.reference_temperature = 298.15 + + solids.species = Fe2O3 FeO inert + + solids.specific_heat = mixture + + + # Chemistry model settings + #---------------------------------------------------------------------- + chemistry.solve = Hem_CH4 Hem_H2 Hem_CO Wus_O2 + + chemistry.Hem_CH4.reaction = Fe2O3(s)+0.25CH4(g)-->2.FeO(s)+0.25CO2(g)+0.5H2O(g) + chemistry.Hem_H2.reaction = Fe2O3(s)+H2(g)-->2.FeO(s)+H2O(g) + chemistry.Hem_CO.reaction = Fe2O3(s)+CO(g)-->2.FeO(s)+CO2(g) + chemistry.Wus_O2.reaction = FeO(s)+0.25O2(g)-->0.5Fe2O3(s) + + + # Initial Conditions + #---------------------------------------------------------------------- + ic.regions = full-domain + + ic.full-domain.fluid.volfrac = 0.725 + ic.full-domain.fluid.velocity = 0.015 0.00 0.00 + ic.full-domain.fluid.temperature = 1273. + ic.full-domain.fluid.species.CH4 = 0.1 + ic.full-domain.fluid.species.H2 = 0.2 + ic.full-domain.fluid.species.CO = 0.1 + ic.full-domain.fluid.species.H2O = 0.2 + ic.full-domain.fluid.species.CO2 = 0.1 + ic.full-domain.fluid.species.O2 = 0.1 + ic.full-domain.fluid.species.N2 = 0.2 + + ic.full-domain.solids = solid0 + ic.full-domain.packing = pseudo_random + + ic.full-domain.solid0.volfrac = 0.275 + ic.full-domain.solid0.velocity = 0.00 0.00 0.00 + + ic.full-domain.solid0.diameter = constant + ic.full-domain.solid0.density = constant + + ic.full-domain.solid0.diameter.constant = 100.0e-6 + ic.full-domain.solid0.density.constant = 2000.0 + + ic.full-domain.solid0.temperature = 1273. + ic.full-domain.solid0.species.Fe2O3 = 0.3 + ic.full-domain.solid0.species.FeO = 0.3 + ic.full-domain.solid0.species.inert = 0.4 + - fluid.species = CO CO2 O2 - solids.species = Fe2O3 FeO + # Boundary Conditions + #---------------------------------------------------------------------- + bc.regions = inflow outflow - chemistry.solve = my_reaction0 my_reaction1 + bc.inflow = mi + bc.inflow.fluid.volfrac = 1.0 + bc.inflow.fluid.velocity = 0.015 0.0 0.0 + bc.inflow.fluid.temperature = 1273. + bc.inflow.fluid.species.CH4 = 0.1 + bc.inflow.fluid.species.H2 = 0.2 + bc.inflow.fluid.species.CO = 0.1 + bc.inflow.fluid.species.H2O = 0.2 + bc.inflow.fluid.species.CO2 = 0.1 + bc.inflow.fluid.species.O2 = 0.1 + bc.inflow.fluid.species.N2 = 0.2 - chemistry.my_reaction0.reaction = Fe2O3(s)+CO(g)-->2.FeO(s)+CO2(g) - chemistry.my_reaction1.reaction = FeO(s)+0.25O2(g)-->0.5Fe2O3(s) + bc.outflow = po + bc.outflow.fluid.pressure = 101325. -- GitLab From e78f3db96ddd7ee1999bdc41b924911c73a53c74 Mon Sep 17 00:00:00 2001 From: Roberto Porcu Date: Sat, 29 Jun 2024 20:52:47 -0400 Subject: [PATCH 4/9] fix descriptive comments in chemistry UDFs --- docs/source_docs/Chemistry_Chapter.rst | 209 ++++++++++++++----------- 1 file changed, 114 insertions(+), 95 deletions(-) diff --git a/docs/source_docs/Chemistry_Chapter.rst b/docs/source_docs/Chemistry_Chapter.rst index 2829f74..8f098f5 100644 --- a/docs/source_docs/Chemistry_Chapter.rst +++ b/docs/source_docs/Chemistry_Chapter.rst @@ -6,44 +6,43 @@ Chemical Reactions ================== MFIX-Exa allows the definition of intra-phase and inter-phase chemical -reactions. Intra-phase reactions are those happening within the same phase, for -example from the fluid to the fluid phase, and from the solid to the solid phase -within each solid particle. Inter-phase reactions are those involving two -different phases, for example from the solid to the fluid phase, or vice-versa. - -MFIX-Exa categorizes the chemical reactions into two classes, "Eulerian" and -"Lagrangian" reactions. Intra-phase reactions happening within the fluid phase -are Eulerian reactions, while intra-phase reactions happening within the solid -phase are Lagrangian reactions. Inter-phase reactions are always categorized as -Lagrangian reactions. - -MFIX-Exa solves the Eulerian reactions by looping over all the regular and -cut-cells and computing the reactions rates for all the intra-phase chemical -reactions happening within the fluid phase. MFIX-Exa solves the Lagrangian -reactions by looping over all the particles within each cell and computing the -reactions rates for the inter-phase reactions and for the intra-phase ones -happening within the solid phase. - -Users can define Eulerian and Lagrangian reaction rates by properly modifying +reactions. Intra-phase reactions happen within the same phase, for example, from +the fluid to the fluid phase and from the solid to the solid phase within each +solid particle. Inter-phase reactions involve two phases, from the solid to the +fluid phase or vice versa. + +MFIX-Exa categorizes the chemical reactions into two classes: "Eulerian" and +"Lagrangian" reactions. Intra-phase reactions within the fluid phase are Eulerian +reactions. In contrast, intra-phase reactions within the solid phase are +Lagrangian reactions. Inter-phase reactions are Lagrangian reactions. + +MFIX-Exa solves the Eulerian reactions by looping over all the regular and cut +cells and computing the reaction rates for all the intra-phase chemical +reactions within the fluid phase. MFIX-Exa solves the Lagrangian reactions by +looping over all the particles within each cell and computing the reaction rates +for the inter-phase and intra-phase ones within the solid phase. + +Users can define Eulerian and Lagrangian reaction rates by adequately modifying the file ``src/usr/mfix_usr_reactions_rates_K.H``. This header file is where -MFIX-Exa looks for the definitions of the "user-defined functions" (UDFs) for -the chemical reactions rates. Eulerian reactions are treated as volumetric -reactions, thus MFIX-Exa expects user-defined Eulerian rates in terms of moles -per second per cubic-meter (SI units :math:`[mol \cdot s^{-1} \cdot m^{-3}]`). -Lagrangian reactions instead are considered to happen at the location of the -solid particle involved, and MFIx-Exa expects user-defined Lagrangian rates in -terms of moles per second (SI units :math:`[mol \cdot s^{-1}]`). User-defined -rates for either Eulerian and Lagrangian reactions must be implemented in the -``operator()`` method of the corresponding classes that are declared as +MFIX-Exa looks for the definitions of the "user-defined functions" (UDFs) for the +chemical reaction rates. Eulerian reactions are volumetric reactions. Thus, +MFIX-Exa expects user-defined Eulerian rates in units of moles per second per +cubic meter :math:`[mol \cdot s^{-1} \cdot m^{-3}]`. Lagrangian reactions, instead, happen +at the location of the solid particle involved, and MFIX-Exa expects +user-defined Lagrangian rates in units of moles per second :math:`[mol \cdot +s^{-1}]`. +User-defined rates for either Eulerian and Lagrangian reactions must be +implemented in the ``operator()`` method of the corresponding classes *EulerianReactionRates* and *LagrangianReactionRates* in the file ``src/usr/mfix_usr_reactions_rates_K.H``. -The ``operator()`` method for the *EulerianReactionRates* class gets two -arguments, *reactions* and *fluid*, that are two classes from which the user can -extract the data needed to implement the corresponding rates. For the -``operator()`` of the *LagrangianReactionRates* class it holds the same -principle with the addition of a third argument, *solids*, which is a class -containing data for the solid particle involved in the reaction. +The ``operator()`` method for the *EulerianReactionRates* class gets two arguments, +*reactions* and *fluid*, which are two classes from which the user can extract the +data needed to implement the corresponding rates. The ``operator()`` of the +*LagrangianReactionRates* class holds the same principle with the addition of +a third argument, *solids*, which is a class containing data for the solid +particle involved in the reaction. + .. code-block:: cpp @@ -52,50 +51,51 @@ containing data for the solid particle involved in the reaction. public: /** * Reactions class gives access to the following reactions quantities: - * - rate(q) with q in [0,reactions_nb] - * - rate("reaction_name") - * - time() - * - dt() - * - cell_volume() + * - rate(q), with q an integer from 0 to max number of lagrangian reactions + * - rate("reaction_name"), with reaction_name a string matching one of the reactions defined in inputs + * - time(), the current simulation time + * - dt(), the current simulation timestep + * - cell_volume(), this cell geometric volume + * - vfrac(), this cell geometric volume fraction * * Fluid class gives access to the following fluid quantities: * - shear_viscosity() * - volume_fraction() * - density() - * - velocity() and velocity(dir) with dir in [0,AMREX_SPACEDIM] + * - velocity() and velocity(dir), with dir an integer from 0 to 3 * - thermodynamic_pressure() * - temperature() * - specific_enthalpy() - * - mass_fraction(n_g) with n_g in [0,fluid_nb_species] - * - mass_fraction("species_name") - * - molar_concentration(n_g) with n_g in [0,fluid_nb_species] - * - molar_concentration("species_name") - * - molar_mass(n_g) with n_g in [0,fluid_nb_species] - * - molar_mass("species_name") + * - mass_fraction(n_g), with n_g an integer from 0 to max number of fluid species + * - mass_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs + * - molar_concentration(n_g), with n_g an integer from 0 to max number of fluid species + * - molar_concentration("species_name"), with species_name a string matching one of the fluid species defined in inputs + * - molar_mass(n_g), with n_g an integer from 0 to max number of fluid species + * - molar_mass("species_name"), with species_name a string matching one of the fluid species defined in inputs * - average_molar_mass() - * - mole_fraction(n_g) with n_g in [0,fluid_nb_species] - * - mole_fraction("species_name") + * - mole_fraction(n_g), with n_g an integer from 0 to max number of fluid species + * - mole_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs * * Solids class gives access to the following solids quantities: - * - position() and position(dir) with dir in [0,AMREX_SPACEDIM] + * - position() and position(dir), with dir an integer from 0 to 3 * - radius() * - volume() * - density() * - mass() - * - oneOverI() + * - oneOverI(), inverse of the particle momentum of inertia * - statistical_weight() - * - velocity() and velocity(dir) with dir in [0,AMREX_SPACEDIM] + * - velocity() and velocity(dir), with dir an integer from 0 to 3 * - temperature() * - specific_heat_capacity() - * - mass_fraction(n_s) with n_s in [0,solids_nb_species] - * - mass_fraction("species_name") - * - molar_concentration(n_g) with n_g in [0,solids_nb_species] - * - molar_concentration("species_name") - * - molar_mass(n_g) with n_g in [0,solids_nb_species] - * - molar_mass("species_name") + * - mass_fraction(n_s), with n_s an integer from 0 to max number of solids species + * - mass_fraction("species_name"), with species_name a string matching one of the solids species defined in inputs + * - molar_concentration(n_s), with n_s an integer from 0 to max number of solids species + * - molar_concentration("species_name"), with species_name a string matching one of the solids species defined in inputs + * - molar_mass(n_s), with n_s an integer from 0 to max number of solids species + * - molar_mass("species_name"), with species_name a string matching one of the solids species defined in inputs * - average_molar_mass() - * - mole_fraction(n_g) with n_g in [0,solids_nb_species] - * - mole_fraction("species_name") + * - mole_fraction(n_s), with n_s an integer from 0 to max number of solids species + * - mole_fraction("species_name"), with species_name a string matching one of the solids species defined in inputs */ template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE @@ -118,29 +118,30 @@ containing data for the solid particle involved in the reaction. public: /** * Reactions class gives access to the following reactions quantities: - * - rate(q) with q in [0,reactions_nb] - * - rate("reaction_name") - * - time() - * - dt() - * - cell_volume() + * - rate(q), with q an integer from 0 to max number of lagrangian reactions + * - rate("reaction_name"), with reaction_name a string matching one of the reactions defined in inputs + * - time(), the current simulation time + * - dt(), the current simulation timestep + * - cell_volume(), this cell geometric volume + * - vfrac(), this cell geometric volume fraction * * Fluid class gives access to the following fluid quantities: * - shear_viscosity() * - volume_fraction() * - density() - * - velocity() and velocity(dir) with dir in [0,AMREX_SPACEDIM] + * - velocity() and velocity(dir), with dir an integer from 0 to 3 * - thermodynamic_pressure() * - temperature() * - specific_enthalpy() - * - mass_fraction(n_g) with n_g in [0,fluid_nb_species] - * - mass_fraction("species_name") - * - molar_concentration(n_g) with n_g in [0,fluid_nb_species] - * - molar_concentration("species_name") - * - molar_mass(n_g) with n_g in [0,fluid_nb_species] - * - molar_mass("species_name") + * - mass_fraction(n_g), with n_g an integer from 0 to max number of fluid species + * - mass_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs + * - molar_concentration(n_g), with n_g an integer from 0 to max number of fluid species + * - molar_concentration("species_name"), with species_name a string matching one of the fluid species defined in inputs + * - molar_mass(n_g), with n_g an integer from 0 to max number of fluid species + * - molar_mass("species_name"), with species_name a string matching one of the fluid species defined in inputs * - average_molar_mass() - * - mole_fraction(n_g) with n_g in [0,fluid_nb_species] - * - mole_fraction("species_name") + * - mole_fraction(n_g), with n_g an integer from 0 to max number of fluid species + * - mole_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs */ template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE @@ -155,7 +156,12 @@ containing data for the solid particle involved in the reaction. Example rates UDFs ================== -Abad +The following code shows how to define a user-defined function for the desired +Lagrangian reaction rates. When accessing the fluid or solid quantities +corresponding to a specific species, the string passed as argument must match +the species name provided in the inputs file. Similarly, when assigning +a reaction rate, the string passed as argument must match the reaction name +provided in the inputs file. .. code-block:: cpp @@ -175,8 +181,8 @@ Abad constexpr amrex::Real Tmin = 300.; /* (K) */ // Particle diameter, volume and initial density - constexpr amrex::Real vol_p = solids.volume(); /* (m^3) */ - constexpr amrex::Real ro_p_o = solids.density(); /* (kg/m^3) */ + const amrex::Real vol_p = solids.volume(); /* (m^3) */ + constexpr amrex::Real ro_p_o = 4250.0; /* (kg/m^3) */ // Reduction reaction constants (m^2 / mole) constexpr amrex::Real const_CH4 = 4.74 / ( 1.25e-6 * 13.59e+3); @@ -185,35 +191,48 @@ Abad constexpr amrex::Real const_O2 = 4.00 / ( 1.20e-6 * 31.10e+3); // Initial mass of FE2O3 at time zero (kg) - constexpr amrex::Real mo = ro_p_o*vol_p; + const amrex::Real mo = ro_p_o*vol_p; // Current particle mass (kg) - const amrex::Real mass_p = vol_p * ro_p; + const amrex::Real mass_p = solids.mass(); - // maximum conversion + // maximum conversion + const amrex::Real MW_O2 = fluid.molar_mass("O2"); + const amrex::Real MW_Fe2O3 = solids.molar_mass("Fe2O3"); const amrex::Real Rlim = 0.25*0.5*MW_O2/MW_Fe2O3 - 1.0e-10; // conversion - const amrex::Real X_r = amrex::min(amrex::max((mo - mass_p)/ (Rlim * mo), 0.0), 1.0); + const amrex::Real X_r = + amrex::min(amrex::max((mo - mass_p)/ (Rlim * mo), 0.0), 1.0); const amrex::Real xTp = amrex::max(amrex::min(T_p, Tmax), Tmin); // Molar concentration of gas reactants (mole / m^3) - const amrex::Real c_CH4 = (fluid.mass_fraction("CH4") < 1.e-6) ? 0 : fluid.molar_concentration("CH4"); - const amrex::Real c_H2 = (fluid.mass_fraction("H2") < 1.e-6) ? 0 : fluid.molar_concentration("H2"); - const amrex::Real c_CO = (fluid.mass_fraction("CO") < 1.e-6) ? 0 : fluid.molar_concentration("CO"); - const amrex::Real c_O2 = (fluid.mass_fraction("O2") < 1.e-6) ? 0 : fluid.molar_concentration("O2"); + const amrex::Real c_CH4 = (fluid.mass_fraction("CH4") < 1.e-6) ? + 0 : fluid.molar_concentration("CH4"); + + const amrex::Real c_H2 = (fluid.mass_fraction("H2") < 1.e-6) ? + 0 : fluid.molar_concentration("H2"); + + const amrex::Real c_CO = (fluid.mass_fraction("CO") < 1.e-6) ? + 0 : fluid.molar_concentration("CO"); + + const amrex::Real c_O2 = (fluid.mass_fraction("O2") < 1.e-6) ? + 0 : fluid.molar_concentration("O2"); - // Constant multiplier common to all hematite REDUCTION reactions (mole) - const amrex::Real const_r = 6.0 * Rlim * (1./fluid.mass_fraction("O2")) * mo - * std::pow((1.0-X_r), 0.667); + // Constant multiplier common to all hematite REDUCTION reactions + // (mole) + const amrex::Real X_O2 = fluid.mass_fraction("O2"); + const amrex::Real const_r = + 6.0 * Rlim * (1./X_O2) * mo * std::pow((1.0-X_r), 0.667); - // Constant multiplier common to the wustite OXIDATION reaction (mole), note: X_o = 1 - X_r - const amrex::Real const_o = 12.0 * Rlim * (1./fluid.mass_fraction("O2")) * mo - * std::pow((X_r), 0.667); + // Constant multiplier common to the wustite OXIDATION reaction + // (mole), note: X_o = 1 - X_r + const amrex::Real const_o = + 12.0 * Rlim * (1./X_O2) * mo * std::pow((X_r), 0.667); // Reduction by Methane: 4FE2O3 + CH4 --> 8FEO + CO2 + 2H2O - //---------------------------------------------------------------------// + //------------------------------------------------------------------// // reaction rate constant (as in the Arrhenius rate) in m/s const amrex::Real k0_CH4 = 9.80 * std::exp(-135.2e+3/(Ru*xTp)); @@ -222,7 +241,7 @@ Abad // Reduction by Hydrogen: Fe2O3 + H2 --> 2FeO + H2O - //---------------------------------------------------------------------// + //------------------------------------------------------------------// // reaction rate constant (as in the Arrhenius rate) in m/s const amrex::Real k0_H2 = 0.062 * std::exp(-65.0e+3/(Ru*xTp)); @@ -231,16 +250,16 @@ Abad // Reduction by Carbon Monoxide: Fe2O3 + CO --> 2FeO + CO2 - //---------------------------------------------------------------------// + //------------------------------------------------------------------// // reaction rate constant (as in the Arrhenius rate) in m/s const amrex::Real k0_CO = 0.10 * std::exp(-80.7e+3/(Ru*xTp)); - reactions.rate("Hem_CO") = const_r * const_CO * k0_CO * std::pow(c_CO, 0.8); + reactions.rate("Hem_CO") = const_r*const_CO*k0_CO*std::pow(c_CO, 0.8); // Oxidation: 4FeO + O2 --> 2Fe2O3 - //---------------------------------------------------------------------// + //------------------------------------------------------------------// // reaction rate constant (as in the Arrhenius rate) in m/s const amrex::Real k0_O2 = 1.9e-3 * std::exp(-25.5e+3/(Ru*xTp)); -- GitLab From 145c3fee46e992fcf872e0a3b9e1c38bf8e8ccf7 Mon Sep 17 00:00:00 2001 From: Roberto Porcu Date: Tue, 1 Apr 2025 15:30:11 -0400 Subject: [PATCH 5/9] add instructions about the reaction rates optimization tool --- .../references/Chemistry_Chapter.rst | 131 +++++++++++------- 1 file changed, 80 insertions(+), 51 deletions(-) diff --git a/docs/source_docs/references/Chemistry_Chapter.rst b/docs/source_docs/references/Chemistry_Chapter.rst index 8f098f5..d2cc1a2 100644 --- a/docs/source_docs/references/Chemistry_Chapter.rst +++ b/docs/source_docs/references/Chemistry_Chapter.rst @@ -12,9 +12,9 @@ solid particle. Inter-phase reactions involve two phases, from the solid to the fluid phase or vice versa. MFIX-Exa categorizes the chemical reactions into two classes: "Eulerian" and -"Lagrangian" reactions. Intra-phase reactions within the fluid phase are Eulerian -reactions. In contrast, intra-phase reactions within the solid phase are -Lagrangian reactions. Inter-phase reactions are Lagrangian reactions. +"Lagrangian" reactions. Intra-phase reactions within the fluid phase are +Eulerian reactions. In contrast, intra-phase reactions within the solid phase +are Lagrangian reactions. Inter-phase reactions are Lagrangian reactions. MFIX-Exa solves the Eulerian reactions by looping over all the regular and cut cells and computing the reaction rates for all the intra-phase chemical @@ -24,33 +24,29 @@ for the inter-phase and intra-phase ones within the solid phase. Users can define Eulerian and Lagrangian reaction rates by adequately modifying the file ``src/usr/mfix_usr_reactions_rates_K.H``. This header file is where -MFIX-Exa looks for the definitions of the "user-defined functions" (UDFs) for the -chemical reaction rates. Eulerian reactions are volumetric reactions. Thus, +MFIX-Exa looks for the definitions of the "user-defined functions" (UDFs) for +the chemical reaction rates. Eulerian reactions are volumetric reactions. Thus, MFIX-Exa expects user-defined Eulerian rates in units of moles per second per -cubic meter :math:`[mol \cdot s^{-1} \cdot m^{-3}]`. Lagrangian reactions, instead, happen -at the location of the solid particle involved, and MFIX-Exa expects -user-defined Lagrangian rates in units of moles per second :math:`[mol \cdot -s^{-1}]`. -User-defined rates for either Eulerian and Lagrangian reactions must be -implemented in the ``operator()`` method of the corresponding classes +cubic meter :math:`[mol \cdot s^{-1} \cdot m^{-3}]`. Lagrangian reactions, +instead, happen at the location of the solid particle involved, and MFIX-Exa +expects user-defined Lagrangian rates in units of moles per second :math:`[mol +\cdot s^{-1}]`. User-defined rates for either Eulerian and Lagrangian reactions +must be implemented in the ``operator()`` method of the corresponding classes *EulerianReactionRates* and *LagrangianReactionRates* in the file ``src/usr/mfix_usr_reactions_rates_K.H``. -The ``operator()`` method for the *EulerianReactionRates* class gets two arguments, -*reactions* and *fluid*, which are two classes from which the user can extract the -data needed to implement the corresponding rates. The ``operator()`` of the -*LagrangianReactionRates* class holds the same principle with the addition of -a third argument, *solids*, which is a class containing data for the solid -particle involved in the reaction. - +The ``operator()`` method for the *EulerianReactionRates* class gets two +arguments, *reactions* and *fluid*, which are two classes from which the user +can extract the data needed to implement the corresponding rates. .. code-block:: cpp - class LagrangianReactionRates + class EulerianReactionRates { public: /** * Reactions class gives access to the following reactions quantities: + * - reaction_idx("reaction_name"), with reaction_name a string matching one of the reactions defined in inputs * - rate(q), with q an integer from 0 to max number of lagrangian reactions * - rate("reaction_name"), with reaction_name a string matching one of the reactions defined in inputs * - time(), the current simulation time @@ -66,6 +62,7 @@ particle involved in the reaction. * - thermodynamic_pressure() * - temperature() * - specific_enthalpy() + * - species_idx("species_name"), with species_name a string matching one of the fluid species defined in inputs * - mass_fraction(n_g), with n_g an integer from 0 to max number of fluid species * - mass_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs * - molar_concentration(n_g), with n_g an integer from 0 to max number of fluid species @@ -75,49 +72,28 @@ particle involved in the reaction. * - average_molar_mass() * - mole_fraction(n_g), with n_g an integer from 0 to max number of fluid species * - mole_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs - * - * Solids class gives access to the following solids quantities: - * - position() and position(dir), with dir an integer from 0 to 3 - * - radius() - * - volume() - * - density() - * - mass() - * - oneOverI(), inverse of the particle momentum of inertia - * - statistical_weight() - * - velocity() and velocity(dir), with dir an integer from 0 to 3 - * - temperature() - * - specific_heat_capacity() - * - mass_fraction(n_s), with n_s an integer from 0 to max number of solids species - * - mass_fraction("species_name"), with species_name a string matching one of the solids species defined in inputs - * - molar_concentration(n_s), with n_s an integer from 0 to max number of solids species - * - molar_concentration("species_name"), with species_name a string matching one of the solids species defined in inputs - * - molar_mass(n_s), with n_s an integer from 0 to max number of solids species - * - molar_mass("species_name"), with species_name a string matching one of the solids species defined in inputs - * - average_molar_mass() - * - mole_fraction(n_s), with n_s an integer from 0 to max number of solids species - * - mole_fraction("species_name"), with species_name a string matching one of the solids species defined in inputs */ - template + template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void operator() (Reactions& reactions, - const Fluid& fluid, - const Solids& solids) const + const Fluid& fluid) const { - // User defined Lagrangian reactions rates go here + // User defined Eulerian reactions rates go here } }; - - - +The ``operator()`` of the *LagrangianReactionRates* class holds the same +principle with the addition of a third argument, *solids*, which is a class +containing data for the solid particle involved in the reaction. .. code-block:: cpp - class EulerianReactionRates + class LagrangianReactionRates { public: /** * Reactions class gives access to the following reactions quantities: + * - reaction_idx("reaction_name"), with reaction_name a string matching one of the reactions defined in inputs * - rate(q), with q an integer from 0 to max number of lagrangian reactions * - rate("reaction_name"), with reaction_name a string matching one of the reactions defined in inputs * - time(), the current simulation time @@ -133,6 +109,7 @@ particle involved in the reaction. * - thermodynamic_pressure() * - temperature() * - specific_enthalpy() + * - species_idx("species_name"), with species_name a string matching one of the fluid species defined in inputs * - mass_fraction(n_g), with n_g an integer from 0 to max number of fluid species * - mass_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs * - molar_concentration(n_g), with n_g an integer from 0 to max number of fluid species @@ -142,16 +119,68 @@ particle involved in the reaction. * - average_molar_mass() * - mole_fraction(n_g), with n_g an integer from 0 to max number of fluid species * - mole_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs + * + * Solids class gives access to the following solids quantities: + * - id() + * - cpu() + * - position() and position(dir), with dir an integer from 0 to 3 + * - radius() + * - volume() + * - density() + * - mass() + * - oneOverI(), inverse of the particle momentum of inertia + * - statistical_weight() + * - velocity() and velocity(dir), with dir an integer from 0 to 3 + * - temperature() + * - specific_heat_capacity() + * - species_idx("species_name"), with species_name a string matching one of the solids species defined in inputs + * - mass_fraction(n_s), with n_s an integer from 0 to max number of solids species + * - mass_fraction("species_name"), with species_name a string matching one of the solids species defined in inputs + * - molar_concentration(n_s), with n_s an integer from 0 to max number of solids species + * - molar_concentration("species_name"), with species_name a string matching one of the solids species defined in inputs + * - molar_mass(n_s), with n_s an integer from 0 to max number of solids species + * - molar_mass("species_name"), with species_name a string matching one of the solids species defined in inputs + * - average_molar_mass() + * - mole_fraction(n_s), with n_s an integer from 0 to max number of solids species + * - mole_fraction("species_name"), with species_name a string matching one of the solids species defined in inputs */ - template + template AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void operator() (Reactions& reactions, - const Fluid& fluid) const + const Fluid& fluid, + const Solids& solids) const { - // User defined Eulerian reactions rates go here + // User defined Lagrangian reactions rates go here } }; +In an effort to give the user a high level of flexibility, when defining the +Eulerian and Lagrangian reaction rates it is possible to get fluid and solids +species-related quantities (such as the mass_fractions and the molar +concentrations) by calling the corresponding function with a string argument +corresponding to the name of the species specified in the inputs file. This is +a feature which allows the user to write more readable reaction rates, +especially when the number of chemical species is large. This flexibility comes +to a cost, specifically a larger computational cost. When accessing +species-related quantities through the string corresponding to the species name, +the cost of searching that species integer index (to be used to access +vectorized quantities in memory) can be significant. + +As a possible solution to this problem, we provide a python-script tool: +``tools/Chemistry/optimize_usr_rates.py``. The user can run this tool by passing +two arguments in this exact order: the ``inputs`` file that will be used to run +the desired simulation, and the ``mfix_usr_reactions_rates_K.H`` file in +a format that includes its relative path. The tool will optimize the reaction +rates in ``mfix_usr_reactions_rates_K.H`` by substituting all the strings that +define the species and reactions names with their corresponding indexes. + +Example usage: +.. code-block:: bash + + python tools/Chemistry/optimize_usr_rates.py .//inputs src/usr/mfix_usr_reactions_rates_K.H + +The tool will modify ``mfix_usr_reactions_rates_K.H`` and create a backup copy +of the original file in the same folder. Example rates UDFs ================== -- GitLab From 42947aa6c6280024680fa16bbcf30d5bc7c91010 Mon Sep 17 00:00:00 2001 From: Roberto Porcu Date: Tue, 1 Apr 2025 15:31:56 -0400 Subject: [PATCH 6/9] fix a minor layout style --- docs/source_docs/references/Chemistry_Chapter.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source_docs/references/Chemistry_Chapter.rst b/docs/source_docs/references/Chemistry_Chapter.rst index d2cc1a2..8780192 100644 --- a/docs/source_docs/references/Chemistry_Chapter.rst +++ b/docs/source_docs/references/Chemistry_Chapter.rst @@ -175,6 +175,7 @@ rates in ``mfix_usr_reactions_rates_K.H`` by substituting all the strings that define the species and reactions names with their corresponding indexes. Example usage: + .. code-block:: bash python tools/Chemistry/optimize_usr_rates.py .//inputs src/usr/mfix_usr_reactions_rates_K.H -- GitLab From 67bc66e95af38b668a16a94160046ee9ca3fe7dc Mon Sep 17 00:00:00 2001 From: Roberto Porcu Date: Wed, 23 Jul 2025 15:52:00 -0400 Subject: [PATCH 7/9] minor improvement in jacobian_type input description --- docs/source_docs/user_guide/inputs/chemical_reactions.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/source_docs/user_guide/inputs/chemical_reactions.rst b/docs/source_docs/user_guide/inputs/chemical_reactions.rst index a48a0b3..b72dd3d 100644 --- a/docs/source_docs/user_guide/inputs/chemical_reactions.rst +++ b/docs/source_docs/user_guide/inputs/chemical_reactions.rst @@ -77,8 +77,9 @@ is selected. The following inputs can be specified using the +-----------------------+---------------------------------------------------------------------+--------+-----------+ | ode_max_steps | The maximum number of substeps for the ODE integration | int | 150000 | +-----------------------+---------------------------------------------------------------------+--------+-----------+ -| jacobian_type | Select how to compute the jacobian for the ODE iterative | string | Numerical | -| | solver. Available choices are: | | | +| jacobian_type | Select how to compute the jacobian for the ODE iterative solver. | string | Numerical | +| | This option is available for ``StiffSolver::BackwardEuler`` and | | | +| | ``StiffSolver::VODE``. Available choices are: | | | | | | | | | | * ``Numerical`` for a first-order numerical approximation | | | | | * ``Broyden`` for Broyden's method (only for BackwardEuler) | | | -- GitLab From 2f88c0d6c049c477923f53a9a02b251a994cee1d Mon Sep 17 00:00:00 2001 From: Jordan Musser Date: Thu, 24 Jul 2025 16:21:32 -0400 Subject: [PATCH 8/9] Simplify chemistry description --- .../references/Chemistry_Chapter.rst | 272 +++++++----------- 1 file changed, 104 insertions(+), 168 deletions(-) diff --git a/docs/source_docs/references/Chemistry_Chapter.rst b/docs/source_docs/references/Chemistry_Chapter.rst index 8780192..6b75bde 100644 --- a/docs/source_docs/references/Chemistry_Chapter.rst +++ b/docs/source_docs/references/Chemistry_Chapter.rst @@ -1,42 +1,25 @@ .. _Chap:Chemistry: -Here we describe the chemistry model. - Chemical Reactions ================== -MFIX-Exa allows the definition of intra-phase and inter-phase chemical -reactions. Intra-phase reactions happen within the same phase, for example, from -the fluid to the fluid phase and from the solid to the solid phase within each -solid particle. Inter-phase reactions involve two phases, from the solid to the -fluid phase or vice versa. - -MFIX-Exa categorizes the chemical reactions into two classes: "Eulerian" and -"Lagrangian" reactions. Intra-phase reactions within the fluid phase are -Eulerian reactions. In contrast, intra-phase reactions within the solid phase -are Lagrangian reactions. Inter-phase reactions are Lagrangian reactions. - -MFIX-Exa solves the Eulerian reactions by looping over all the regular and cut -cells and computing the reaction rates for all the intra-phase chemical -reactions within the fluid phase. MFIX-Exa solves the Lagrangian reactions by -looping over all the particles within each cell and computing the reaction rates -for the inter-phase and intra-phase ones within the solid phase. - -Users can define Eulerian and Lagrangian reaction rates by adequately modifying -the file ``src/usr/mfix_usr_reactions_rates_K.H``. This header file is where -MFIX-Exa looks for the definitions of the "user-defined functions" (UDFs) for -the chemical reaction rates. Eulerian reactions are volumetric reactions. Thus, -MFIX-Exa expects user-defined Eulerian rates in units of moles per second per -cubic meter :math:`[mol \cdot s^{-1} \cdot m^{-3}]`. Lagrangian reactions, -instead, happen at the location of the solid particle involved, and MFIX-Exa -expects user-defined Lagrangian rates in units of moles per second :math:`[mol -\cdot s^{-1}]`. User-defined rates for either Eulerian and Lagrangian reactions -must be implemented in the ``operator()`` method of the corresponding classes -*EulerianReactionRates* and *LagrangianReactionRates* in the file +MFIX-Exa categorizes chemical reactions into two classes: + +* **Eulerian reactions** are homogeneous fluid reactions, reactions that only + reference fluid species. These reactions are calculated by looping over grid cells, + and are defined in units of moles per second per cubic meter + :math:`[mol \cdot s^{-1} \cdot m^{-3}]`. + +* **Lagrangian reactions** include homogeneous particle reactions and + heterogeneous fluid-particle reactions. These reactions are calculated + by looping over each particle, and are defined in units of moles per second + :math:`[mol \cdot s^{-1}]`. + +Users implement reaction rates by modifying the header file, ``src/usr/mfix_usr_reactions_rates_K.H``. -The ``operator()`` method for the *EulerianReactionRates* class gets two -arguments, *reactions* and *fluid*, which are two classes from which the user +The ``operator()`` method for the ``EulerianReactionRates`` class gets two +arguments, ``reactions`` and ``fluid``, which are two classes from which the user can extract the data needed to implement the corresponding rates. .. code-block:: cpp @@ -47,10 +30,10 @@ can extract the data needed to implement the corresponding rates. /** * Reactions class gives access to the following reactions quantities: * - reaction_idx("reaction_name"), with reaction_name a string matching one of the reactions defined in inputs - * - rate(q), with q an integer from 0 to max number of lagrangian reactions + * - rate(q), with q an integer from 0 to number of Eulerian reactions - 1 * - rate("reaction_name"), with reaction_name a string matching one of the reactions defined in inputs * - time(), the current simulation time - * - dt(), the current simulation timestep + * - dt(), the current simulation time step * - cell_volume(), this cell geometric volume * - vfrac(), this cell geometric volume fraction * @@ -58,19 +41,19 @@ can extract the data needed to implement the corresponding rates. * - shear_viscosity() * - volume_fraction() * - density() - * - velocity() and velocity(dir), with dir an integer from 0 to 3 + * - velocity() and velocity(dir), with dir an integer from 0 to 2 * - thermodynamic_pressure() * - temperature() * - specific_enthalpy() * - species_idx("species_name"), with species_name a string matching one of the fluid species defined in inputs - * - mass_fraction(n_g), with n_g an integer from 0 to max number of fluid species + * - mass_fraction(n), with n an integer from 0 to number of fluid species - 1 * - mass_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs - * - molar_concentration(n_g), with n_g an integer from 0 to max number of fluid species + * - molar_concentration(n), with n an integer from 0 to number of fluid species - 1 * - molar_concentration("species_name"), with species_name a string matching one of the fluid species defined in inputs - * - molar_mass(n_g), with n_g an integer from 0 to max number of fluid species + * - molar_mass(n), with n an integer from 0 to number of fluid species - 1 * - molar_mass("species_name"), with species_name a string matching one of the fluid species defined in inputs * - average_molar_mass() - * - mole_fraction(n_g), with n_g an integer from 0 to max number of fluid species + * - mole_fraction(n), with n an integer from 0 to number of fluid species - 1 * - mole_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs */ template @@ -82,9 +65,8 @@ can extract the data needed to implement the corresponding rates. } }; -The ``operator()`` of the *LagrangianReactionRates* class holds the same -principle with the addition of a third argument, *solids*, which is a class -containing data for the solid particle involved in the reaction. +The ``operator()`` of the ``LagrangianReactionRates`` class contains a third argument, +``solids``, which is a class containing data for the particle involved in the reaction. .. code-block:: cpp @@ -94,54 +76,54 @@ containing data for the solid particle involved in the reaction. /** * Reactions class gives access to the following reactions quantities: * - reaction_idx("reaction_name"), with reaction_name a string matching one of the reactions defined in inputs - * - rate(q), with q an integer from 0 to max number of lagrangian reactions + * - rate(q), with q an integer from 0 to max number of Lagrangian reactions - 1 * - rate("reaction_name"), with reaction_name a string matching one of the reactions defined in inputs * - time(), the current simulation time - * - dt(), the current simulation timestep - * - cell_volume(), this cell geometric volume - * - vfrac(), this cell geometric volume fraction + * - dt(), the current simulation time step + * - cell_volume(), cell geometric volume of cell containing this particle + * - vfrac(), geometric volume fraction of cell containing this particle * * Fluid class gives access to the following fluid quantities: * - shear_viscosity() * - volume_fraction() * - density() - * - velocity() and velocity(dir), with dir an integer from 0 to 3 + * - velocity() and velocity(dir), with dir an integer from 0 to 2 * - thermodynamic_pressure() * - temperature() * - specific_enthalpy() * - species_idx("species_name"), with species_name a string matching one of the fluid species defined in inputs - * - mass_fraction(n_g), with n_g an integer from 0 to max number of fluid species + * - mass_fraction(n), with n an integer from 0 to max number of fluid species * - mass_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs - * - molar_concentration(n_g), with n_g an integer from 0 to max number of fluid species + * - molar_concentration(n), with n an integer from 0 to max number of fluid species - 1 * - molar_concentration("species_name"), with species_name a string matching one of the fluid species defined in inputs - * - molar_mass(n_g), with n_g an integer from 0 to max number of fluid species + * - molar_mass(n), with n an integer from 0 to max number of fluid species - 1 * - molar_mass("species_name"), with species_name a string matching one of the fluid species defined in inputs * - average_molar_mass() - * - mole_fraction(n_g), with n_g an integer from 0 to max number of fluid species + * - mole_fraction(n), with n an integer from 0 to max number of fluid species - 1 * - mole_fraction("species_name"), with species_name a string matching one of the fluid species defined in inputs * * Solids class gives access to the following solids quantities: * - id() * - cpu() - * - position() and position(dir), with dir an integer from 0 to 3 + * - position() and position(dir), with dir an integer from 0 to 2 * - radius() * - volume() * - density() * - mass() * - oneOverI(), inverse of the particle momentum of inertia * - statistical_weight() - * - velocity() and velocity(dir), with dir an integer from 0 to 3 + * - velocity() and velocity(dir), with dir an integer from 0 to 2 * - temperature() * - specific_heat_capacity() * - species_idx("species_name"), with species_name a string matching one of the solids species defined in inputs - * - mass_fraction(n_s), with n_s an integer from 0 to max number of solids species + * - mass_fraction(n), with n an integer from 0 to max number of solids species - 1 * - mass_fraction("species_name"), with species_name a string matching one of the solids species defined in inputs - * - molar_concentration(n_s), with n_s an integer from 0 to max number of solids species + * - molar_concentration(n), with n an integer from 0 to max number of solids species - 1 * - molar_concentration("species_name"), with species_name a string matching one of the solids species defined in inputs - * - molar_mass(n_s), with n_s an integer from 0 to max number of solids species + * - molar_mass(n), with n an integer from 0 to max number of solids species - 1 * - molar_mass("species_name"), with species_name a string matching one of the solids species defined in inputs * - average_molar_mass() - * - mole_fraction(n_s), with n_s an integer from 0 to max number of solids species + * - mole_fraction(n), with n an integer from 0 to max number of solids species - 1 * - mole_fraction("species_name"), with species_name a string matching one of the solids species defined in inputs */ template @@ -154,150 +136,104 @@ containing data for the solid particle involved in the reaction. } }; -In an effort to give the user a high level of flexibility, when defining the -Eulerian and Lagrangian reaction rates it is possible to get fluid and solids -species-related quantities (such as the mass_fractions and the molar -concentrations) by calling the corresponding function with a string argument -corresponding to the name of the species specified in the inputs file. This is -a feature which allows the user to write more readable reaction rates, -especially when the number of chemical species is large. This flexibility comes -to a cost, specifically a larger computational cost. When accessing -species-related quantities through the string corresponding to the species name, -the cost of searching that species integer index (to be used to access -vectorized quantities in memory) can be significant. - -As a possible solution to this problem, we provide a python-script tool: -``tools/Chemistry/optimize_usr_rates.py``. The user can run this tool by passing -two arguments in this exact order: the ``inputs`` file that will be used to run -the desired simulation, and the ``mfix_usr_reactions_rates_K.H`` file in -a format that includes its relative path. The tool will optimize the reaction -rates in ``mfix_usr_reactions_rates_K.H`` by substituting all the strings that -define the species and reactions names with their corresponding indexes. - -Example usage: - -.. code-block:: bash - - python tools/Chemistry/optimize_usr_rates.py .//inputs src/usr/mfix_usr_reactions_rates_K.H - -The tool will modify ``mfix_usr_reactions_rates_K.H`` and create a backup copy -of the original file in the same folder. - -Example rates UDFs -================== - -The following code shows how to define a user-defined function for the desired -Lagrangian reaction rates. When accessing the fluid or solid quantities -corresponding to a specific species, the string passed as argument must match -the species name provided in the inputs file. Similarly, when assigning -a reaction rate, the string passed as argument must match the reaction name -provided in the inputs file. +To simply defining chemical reactions, fluid and solids species-related quantities +can be accessed by calling the variable function with the species name specified +in the inputs file. For example, if the fluid contains a species called ``CO``, +then the species mass fraction for ``CO`` can be accessed as follows: .. code-block:: cpp - class LagrangianReactionRates - { - public: - template - AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE - void operator() (Reactions& reactions, - const Fluid& fluid, - const Solids& solids) const - { - // Gas constant - constexpr amrex::Real Ru = 8.314459; /* (J/mole.K) */ - - constexpr amrex::Real Tmax = 1200.; /* (K) */ - constexpr amrex::Real Tmin = 300.; /* (K) */ + // Mass fraction of CO species + amrex::Real const X_CO = fluid.mass_fraction("CO"); - // Particle diameter, volume and initial density - const amrex::Real vol_p = solids.volume(); /* (m^3) */ - constexpr amrex::Real ro_p_o = 4250.0; /* (kg/m^3) */ +This feature allows the user to write readable reaction rates, especially when +the number of chemical species is large. However, at runtime this approach +requires the solver to search for the species index associated with the name. +The computational cost of the search can be non-trivial because it is preformed +for each grid cell or particle, every iteration of the chemistry solver, every +simulation time step. - // Reduction reaction constants (m^2 / mole) - constexpr amrex::Real const_CH4 = 4.74 / ( 1.25e-6 * 13.59e+3); - constexpr amrex::Real const_H2 = 1.19 / ( 1.25e-6 * 13.59e+3); - constexpr amrex::Real const_CO = 1.19 / ( 1.25e-6 * 13.59e+3); - constexpr amrex::Real const_O2 = 4.00 / ( 1.20e-6 * 31.10e+3); +A python-script is provided that substitutes the string references with their +corresponding indices to remove the runtime search. The tool is run by passing +the ``inputs`` file and the reaction header, ``mfix_usr_reactions_rates_K.H``. +The tool creates a backup copy of the original reaction header, appending a time stamp +for when the tool was run, before applying the optimizations. - // Initial mass of FE2O3 at time zero (kg) - const amrex::Real mo = ro_p_o*vol_p; +Example usage: - // Current particle mass (kg) - const amrex::Real mass_p = solids.mass(); +.. code-block:: bash - // maximum conversion - const amrex::Real MW_O2 = fluid.molar_mass("O2"); - const amrex::Real MW_Fe2O3 = solids.molar_mass("Fe2O3"); - const amrex::Real Rlim = 0.25*0.5*MW_O2/MW_Fe2O3 - 1.0e-10; + python tools/Chemistry/optimize_usr_rates.py inputs mfix/src/usr/mfix_usr_reactions_rates_K.H - // conversion - const amrex::Real X_r = - amrex::min(amrex::max((mo - mass_p)/ (Rlim * mo), 0.0), 1.0); - const amrex::Real xTp = amrex::max(amrex::min(T_p, Tmax), Tmin); +Example rates UDFs +================== - // Molar concentration of gas reactants (mole / m^3) - const amrex::Real c_CH4 = (fluid.mass_fraction("CH4") < 1.e-6) ? - 0 : fluid.molar_concentration("CH4"); +The following code shows a simple reaction rate for methane combustion. +The molar concentrations for oxygen (``O2``) and methane (``CH4``) are accessed +using the names provided in the inputs file. Similarly, the reaction rate +is stored using the name given in the inputs file. - const amrex::Real c_H2 = (fluid.mass_fraction("H2") < 1.e-6) ? - 0 : fluid.molar_concentration("H2"); +.. code-block:: bash + :caption: Snippet of inputs defining fluid species and adiabatic flame reaction - const amrex::Real c_CO = (fluid.mass_fraction("CO") < 1.e-6) ? - 0 : fluid.molar_concentration("CO"); + # Fluid model settings + # ----------------------------------------------------------------------- + fluid.solve = fluid - const amrex::Real c_O2 = (fluid.mass_fraction("O2") < 1.e-6) ? - 0 : fluid.molar_concentration("O2"); + fluid.species = CH4 O2 CO2 H2O N2 - // Constant multiplier common to all hematite REDUCTION reactions - // (mole) - const amrex::Real X_O2 = fluid.mass_fraction("O2"); - const amrex::Real const_r = - 6.0 * Rlim * (1./X_O2) * mo * std::pow((1.0-X_r), 0.667); + fluid.thermodynamic_pressure = 101325. + fluid.reference_temperature = 298.15 - // Constant multiplier common to the wustite OXIDATION reaction - // (mole), note: X_o = 1 - X_r - const amrex::Real const_o = - 12.0 * Rlim * (1./X_O2) * mo * std::pow((X_r), 0.667); + fluid.species = Air Vapor - // Reduction by Methane: 4FE2O3 + CH4 --> 8FEO + CO2 + 2H2O - //------------------------------------------------------------------// + fluid.viscosity.molecular = constant + fluid.viscosity.molecular.constant = 1.86e-5 - // reaction rate constant (as in the Arrhenius rate) in m/s - const amrex::Real k0_CH4 = 9.80 * std::exp(-135.2e+3/(Ru*xTp)); + fluid.specific_heat = mixture - reactions.rate("Hem_CH4") = const_r * const_CH4 * k0_CH4 * c_CH4; + fluid.thermal_conductivity = constant + fluid.thermal_conductivity.constant = 0.02662 - // Reduction by Hydrogen: Fe2O3 + H2 --> 2FeO + H2O - //------------------------------------------------------------------// + # Chemical reactions: + # ----------------------------------------------------------------------- + chemistry.solve = AdiabaticFlame - // reaction rate constant (as in the Arrhenius rate) in m/s - const amrex::Real k0_H2 = 0.062 * std::exp(-65.0e+3/(Ru*xTp)); + chemistry.AdiabaticFlame.reaction = CH4(g) + 2O2(g) --> CO2(g) + 2H2O(g) - reactions.rate("Hem_H2") = const_r * const_H2 * k0_H2 * c_H2; +.. code-block:: cpp + :caption: Snippet of reaction rate header defining reaction rate for adiabatic flame - // Reduction by Carbon Monoxide: Fe2O3 + CO --> 2FeO + CO2 - //------------------------------------------------------------------// + class EulerianReactionRates + { + public: + AMREX_GPU_HOST_DEVICE + EulerianReactionRates () = default; - // reaction rate constant (as in the Arrhenius rate) in m/s - const amrex::Real k0_CO = 0.10 * std::exp(-80.7e+3/(Ru*xTp)); + template + AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + void operator() (Reactions& reactions, + const Fluid& fluid) const + { - reactions.rate("Hem_CO") = const_r*const_CO*k0_CO*std::pow(c_CO, 0.8); + // Adiabatic flame: + // CH4 + 2O2 --> CO2 + 2H2O (mol/m^3.s) + //---------------------------------------------------------------------// + // Note: The CH4 combustion rate is artificial and used for the + // adiabatic flame test case. + amrex::Real const c_O2 = fluid.molar_concentration("O2"); // [mol/m^3] + amrex::Real const c_CH4 = fluid.molar_concentration("CH4"); // [mol/m^3] - // Oxidation: 4FeO + O2 --> 2Fe2O3 - //------------------------------------------------------------------// + amrex::Real k0(2.0e-1); // reaction rate coefficient - // reaction rate constant (as in the Arrhenius rate) in m/s - const amrex::Real k0_O2 = 1.9e-3 * std::exp(-25.5e+3/(Ru*xTp)); + reactions.rate("AdiabaticFlame") = k0 * c_O2 * c_CH4; - reactions.rate("Wus_O2") = const_o * const_O2 * k0_O2 * c_O2; } }; - .. toctree:: :maxdepth: 0 -- GitLab From a21c631f631d00f0a76e1bbc0796f275da81cdc0 Mon Sep 17 00:00:00 2001 From: Jordan Musser Date: Thu, 24 Jul 2025 16:26:59 -0400 Subject: [PATCH 9/9] Fix typo and word order --- docs/source_docs/references/Chemistry_Chapter.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source_docs/references/Chemistry_Chapter.rst b/docs/source_docs/references/Chemistry_Chapter.rst index 6b75bde..c167a40 100644 --- a/docs/source_docs/references/Chemistry_Chapter.rst +++ b/docs/source_docs/references/Chemistry_Chapter.rst @@ -146,12 +146,12 @@ then the species mass fraction for ``CO`` can be accessed as follows: // Mass fraction of CO species amrex::Real const X_CO = fluid.mass_fraction("CO"); -This feature allows the user to write readable reaction rates, especially when +This feature allows users to write readable reaction rates, especially when the number of chemical species is large. However, at runtime this approach requires the solver to search for the species index associated with the name. -The computational cost of the search can be non-trivial because it is preformed -for each grid cell or particle, every iteration of the chemistry solver, every -simulation time step. +The computational cost of the search can be non-trivial because it is performed +for each iteration of the chemistry solver every time step, for all grid cells +and all particles. A python-script is provided that substitutes the string references with their corresponding indices to remove the runtime search. The tool is run by passing -- GitLab