LCOV - code coverage report
Current view: top level - src/Integrator - Flame.cpp (source / functions) Coverage Total Hit
Test: coverage_merged.info Lines: 75.8 % 322 244
Test Date: 2025-06-26 20:08:28 Functions: 63.0 % 27 17

            Line data    Source code
       1              : #include "Flame.H"
       2              : #include "IO/ParmParse.H"
       3              : #include "BC/Constant.H"
       4              : #include "Numeric/Stencil.H"
       5              : #include "IC/Laminate.H"
       6              : #include "IC/Constant.H"
       7              : #include "IC/PSRead.H"
       8              : #include "Numeric/Function.H"
       9              : #include "IC/Expression.H"
      10              : #include "IC/BMP.H"
      11              : #include "IC/PNG.H"
      12              : #include "Base/Mechanics.H"
      13              : #include "Util/Util.H"
      14              : #include "Model/Propellant/Propellant.H"
      15              : #include "Model/Propellant/FullFeedback.H"
      16              : #include "Model/Propellant/Homogenize.H"
      17              : 
      18              : #include <cmath>
      19              : 
      20              : namespace Integrator
      21              : {
      22              : 
      23            3 : Flame::Flame() : Base::Mechanics<model_type>() {}
      24              : 
      25            3 : Flame::Flame(IO::ParmParse& pp) : Flame()
      26              : {
      27            9 :     pp_queryclass(*this);
      28            3 : }
      29              : 
      30              : 
      31              : void
      32            3 : Flame::Forbids(IO::ParmParse& pp)
      33              : {
      34           24 :     pp.forbid("pressure.P","use chamber.pressure instead");
      35              : 
      36           24 :     pp.forbid("geometry.x_len","This is specified by geometry.prob_lo/hi");
      37           24 :     pp.forbid("geometry.y_len","This is specified by geometry.prob_lo/hi");
      38           24 :     pp.forbid("amr.ghost_cells", "This should not be adjustable ");
      39              : 
      40           24 :     pp.forbid("pf.gamma","implemented in regression rate law objects now"); 
      41              : 
      42           24 :     pp.forbid("pressure.r_ap",   "use regression.powerlaw.r_ap");
      43           24 :     pp.forbid("pressure.r_htpb", "use regression.powerlaw.r_htpb");
      44           24 :     pp.forbid("pressure.r_comb", "use regression.powerlaw.r_comb");
      45           24 :     pp.forbid("pressure.n_ap",   "use regression.powerlaw.n_ap");
      46           24 :     pp.forbid("pressure.n_htpb", "use regression.powerlaw.n_htpb");
      47           24 :     pp.forbid("pressure.n_comb", "use regression.powerlaw.n_comb");
      48              : 
      49           24 :     pp.forbid("thermal.bound",   "use thermal.Tref");
      50           24 :     pp.forbid("thermal.T_fluid",   "use thermal.Tfluid (or nothing)");
      51           24 :     pp.forbid("thermal.m_ap",   "use regression.arrhenius.m_ap");
      52           24 :     pp.forbid("thermal.m_htpb", "use regression.arrhenius.m_htpb");
      53           24 :     pp.forbid("thermal.E_ap",   "use regression.arrhenius.E_ap");
      54           24 :     pp.forbid("thermal.E_htpb", "use regression.arrhenius.E_htpb");
      55           24 :     pp.forbid("thermal.modeling_ap",   "Old debug variable. Should equal 1 "); 
      56           24 :     pp.forbid("thermal.modeling_htpb", "Old debug variable. Should equal 1"); 
      57              : 
      58           24 :     pp.forbid("pressure.a1", "use propellant.mesoscale.a1 instead");
      59           24 :     pp.forbid("pressure.a2", "use propellant.mesoscale.a2 instead");
      60           24 :     pp.forbid("pressure.a3", "use propellant.mesoscale.a3 instead");
      61           24 :     pp.forbid("pressure.b1", "use propellant.mesoscale.b1 instead");
      62           24 :     pp.forbid("pressure.b2", "use propellant.mesoscale.b2 instead");
      63           24 :     pp.forbid("pressure.b3", "use propellant.mesoscale.b3 instead");
      64           24 :     pp.forbid("pressure.c1", "use propellant.mesoscale.c1 instead");
      65           24 :     pp.forbid("pressure.mob_ap", "no longer used"); 
      66           24 :     pp.forbid("pressure.dependency", "use propellant.mesoscale.arrhenius_dependency"); 
      67           24 :     pp.forbid("pressure.h1", "use propellant.mesoscale.h1 instead"); 
      68           24 :     pp.forbid("pressure.h2", "use propellant.mesoscale.h2 instead"); 
      69           24 :     pp.forbid("thermal.mlocal_ap", "use propellant.mesoscale.mlocal_ap");
      70           24 :     pp.forbid("thermal.mlocal_comb", "use propellant.mesoscale.mlocal_comb");
      71           24 :     pp.forbid("thermal.mlocal_htpb", "this actually did **nothing** - it was overridden by a hard code using massfraction.");
      72              : 
      73           24 :     pp.forbid("thermal.disperssion1", "use propellant.mesoscale.dispersion1");
      74           24 :     pp.forbid("thermal.disperssion2", "use propellant.mesoscale.dispersion2");
      75           24 :     pp.forbid("thermal.disperssion3", "use propellant.mesoscale.dispersion3"); 
      76              : 
      77           24 :     pp.forbid("thermal.rho_ap", "use propellant.XX.rho_ap ");
      78           24 :     pp.forbid("thermal.rho_htpb","use propellant.XX.rho_htpb ");
      79           24 :     pp.forbid("thermal.k_ap",   "use propellant.XX.k_ap ");
      80           24 :     pp.forbid("thermal.k_htpb", "use propellant.XX.k_htpb ");
      81           24 :     pp.forbid("thermal.cp_ap", "use propellant.XX.cp_ap ");
      82           21 :     pp.forbid("thermal.cp_htpb","use propellant.XX.cp_htpb "); 
      83            3 : }
      84              : 
      85              : 
      86              : // [parser]
      87              : void
      88            3 : Flame::Parse(Flame& value, IO::ParmParse& pp)
      89              : {
      90              :     BL_PROFILE("Integrator::Flame::Flame()");
      91              : 
      92            3 :     Forbids(pp);
      93              : 
      94              :     // Whether to include extra fields (such as mdot, etc) in the plot output
      95           18 :     pp_query_default("plot_field",value.plot_field,true); 
      96              :         
      97              :     //
      98              :     // PHASE FIELD VARIABLES
      99              :     //
     100              :         
     101           18 :     pp_query_default("pf.eps", value.pf.eps, 0.0); // Burn width thickness
     102           18 :     pp_query_default("pf.kappa", value.pf.kappa, 0.0); // Interface energy param
     103           18 :     pp_query_default("pf.lambda", value.pf.lambda, 0.0); // Chemical potential multiplier
     104           18 :     pp_query_default("pf.w1", value.pf.w1, 0.0); // Unburned rest energy
     105           18 :     pp_query_default("pf.w12", value.pf.w12, 0.0);  // Barrier energy
     106           15 :     pp_query_default("pf.w0", value.pf.w0, 0.0);    // Burned rest energy
     107              : 
     108              :     // Boundary conditions for phase field order params
     109            6 :     pp.select<BC::Constant>("pf.eta.bc", value.bc_eta, 1 ); 
     110            9 :     value.RegisterNewFab(value.eta_mf, value.bc_eta, 1, 2, "eta", true);
     111            9 :     value.RegisterNewFab(value.eta_old_mf, value.bc_eta, 1, 2, "eta_old", false);
     112              : 
     113              :     // phase field initial condition
     114            6 :     pp.select<IC::Laminate,IC::Constant,IC::Expression,IC::BMP,IC::PNG>("pf.eta.ic",value.ic_eta,value.geom); 
     115              : 
     116              : 
     117              : 
     118              :     // Select reduced order model to capture heat feedback
     119              :     pp.select<  Model::Propellant::PowerLaw, 
     120              :                 Model::Propellant::FullFeedback,
     121              :                 Model::Propellant::Homogenize>
     122            9 :         ("propellant",value.propellant);
     123              : 
     124              : 
     125              :     // Whether to use the Thermal Transport Model
     126           18 :     pp_query_default("thermal.on", value.thermal.on, false); 
     127              : 
     128              :     // Reference temperature
     129              :     // Used to set all other reference temperatures by default.
     130           15 :     pp_query_default("thermal.Tref", value.thermal.Tref, 300.0); 
     131              : 
     132            3 :     if (value.thermal.on) {
     133              : 
     134              :         // Used to change heat flux units
     135            6 :         pp_query_default("thermal.hc", value.thermal.hc, 1.0);
     136              :         // System AP mass fraction
     137              :         //pp_query_default("thermal.massfraction", value.thermal.massfraction, 0.8);
     138              : 
     139              :         // Effective fluid temperature
     140            5 :         pp_query_default("thermal.Tfluid", value.thermal.Tfluid, value.thermal.Tref); 
     141              : 
     142              :         //Temperature boundary condition
     143            2 :         pp.select_default<BC::Constant>("thermal.temp.bc", value.bc_temp, 1);
     144              :             
     145            3 :         value.RegisterNewFab(value.temp_mf, value.bc_temp, 1, 3, "temp", true);
     146            3 :         value.RegisterNewFab(value.temp_old_mf, value.bc_temp, 1, 3, "temp_old", false);
     147            3 :         value.RegisterNewFab(value.temps_mf, value.bc_temp, 1, 0, "temps", false);
     148              : 
     149            3 :         value.RegisterNewFab(value.mdot_mf, value.bc_temp, 1, 0, "mdot", value.plot_field);
     150            3 :         value.RegisterNewFab(value.alpha_mf, value.bc_temp, 1, 0, "alpha", value.plot_field);
     151            3 :         value.RegisterNewFab(value.heatflux_mf, value.bc_temp, 1, 0, "heatflux", value.plot_field);
     152            3 :         value.RegisterNewFab(value.laser_mf, value.bc_temp, 1, 0, "laser", value.plot_field);
     153              : 
     154            2 :         value.RegisterIntegratedVariable(&value.chamber.volume, "volume");
     155            2 :         value.RegisterIntegratedVariable(&value.chamber.area, "area");
     156            2 :         value.RegisterIntegratedVariable(&value.chamber.massflux, "mass_flux");
     157              : 
     158              :         // laser initial condition
     159            2 :         pp.select_default<IC::Constant,IC::Expression>("laser.ic",value.ic_laser, value.geom);
     160              : 
     161              :         // thermal initial condition
     162            3 :         pp.select_default<IC::Constant,IC::Expression,IC::BMP,IC::PNG>("temp.ic",value.thermal.ic_temp,value.geom);
     163              :     }
     164              : 
     165              : 
     166              :     // Constant pressure value
     167           18 :     pp_query_default("chamber.pressure", value.chamber.pressure, 1.0); 
     168              : 
     169              :     // Whether to compute the pressure evolution
     170           18 :     pp_query_default("variable_pressure", value.variable_pressure, 0);
     171              : 
     172              :     // Refinement criterion for eta field   
     173           18 :     pp_query_default("amr.refinement_criterion", value.m_refinement_criterion, 0.001);
     174              : 
     175              :     // Refinement criterion for temperature field    
     176           18 :     pp_query_default("amr.refinement_criterion_temp", value.t_refinement_criterion, 0.001);
     177              : 
     178              :     // Eta value to restrict the refinament for the temperature field 
     179           18 :     pp_query_default("amr.refinament_restriction", value.t_refinement_restriction, 0.1);
     180              : 
     181              :     // Refinement criterion for phi field [infinity]
     182           18 :     pp_query_default("amr.phi_refinement_criterion", value.phi_refinement_criterion, 1.0e100);
     183              : 
     184              :     // Minimum allowable threshold for $\eta$
     185           15 :     pp_query_default("small", value.small, 1.0e-8); 
     186              : 
     187              :     // Initial condition for $\phi$ field.
     188              :     pp.select_default<IC::PSRead,IC::Laminate,IC::Expression,IC::Constant,IC::BMP,IC::PNG>
     189            6 :         ("phi.ic",value.ic_phi,value.geom);
     190              : 
     191            9 :     value.RegisterNodalFab(value.phi_mf, 1, 2, "phi", true);
     192              : 
     193              :     // Whether to use Neo-hookean Elastic model
     194           18 :     pp_query_default("elastic.on", value.elastic.on, 0); 
     195              : 
     196              :     // Body force
     197           18 :     pp_query_default("elastic.traction", value.elastic.traction, 0.0); 
     198              : 
     199              :     // Phi refinement criteria 
     200           18 :     pp_query_default("elastic.phirefinement", value.elastic.phirefinement, 1); 
     201              : 
     202           15 :     pp.queryclass<Base::Mechanics<model_type>>("elastic",value);
     203              : 
     204            3 :     if (value.m_type != Type::Disable)
     205              :     {
     206              :         // Reference temperature for thermal expansion 
     207              :         // (temperature at which the material is strain-free)
     208            0 :         pp_query_default("Telastic", value.elastic.Telastic, value.thermal.Tref); 
     209              :         // elastic model of AP
     210            0 :         pp.queryclass<Model::Solid::Finite::NeoHookeanPredeformed>("model_ap", value.elastic.model_ap);
     211              :         // elastic model of HTPB
     212            0 :         pp.queryclass<Model::Solid::Finite::NeoHookeanPredeformed>("model_htpb", value.elastic.model_htpb);
     213              : 
     214              :         // Use our current eta field as the psi field for the solver
     215            0 :         value.psi_on = false;
     216            0 :         value.solver.setPsi(value.eta_mf);
     217              :     }
     218              : 
     219              :     bool allow_unused;
     220              :     // Set this to true to allow unused inputs without error.
     221              :     // (Not recommended.)
     222           15 :     pp.query_default("allow_unused",allow_unused,false);
     223            3 :     if (!allow_unused && pp.AnyUnusedInputs())
     224              :     {
     225            0 :         Util::Warning(INFO,"The following inputs were specified but not used:");
     226            0 :         pp.AllUnusedInputs();
     227            0 :         Util::Exception(INFO,"Aborting. Specify 'allow_unused=True` to ignore this error.");
     228              :     }
     229            3 : }
     230              : 
     231           14 : void Flame::Initialize(int lev)
     232              : {
     233              :     BL_PROFILE("Integrator::Flame::Initialize");
     234           14 :     Base::Mechanics<model_type>::Initialize(lev);
     235              : 
     236           14 :     ic_eta->Initialize(lev, eta_mf);
     237           14 :     ic_eta->Initialize(lev, eta_old_mf);
     238           14 :     ic_phi->Initialize(lev, phi_mf);
     239              :     //ic_phicell->Initialize(lev, phicell_mf);
     240              : 
     241           14 :     if (elastic.on) {
     242            0 :         rhs_mf[lev]->setVal(Set::Vector::Zero());
     243              :     }
     244           14 :     if (thermal.on) {
     245            8 :         if (thermal.ic_temp)
     246              :         {
     247            8 :             thermal.ic_temp->Initialize(lev,temp_mf);
     248            8 :             thermal.ic_temp->Initialize(lev,temp_old_mf);
     249            8 :             thermal.ic_temp->Initialize(lev,temps_mf);
     250              :         }
     251              :         else
     252              :         {
     253            0 :             temp_mf[lev]->setVal(thermal.Tref);
     254            0 :             temp_old_mf[lev]->setVal(thermal.Tref);
     255            0 :             temps_mf[lev]->setVal(thermal.Tref);
     256              :         }
     257            8 :         alpha_mf[lev]->setVal(0.0);
     258            8 :         mdot_mf[lev]->setVal(0.0);
     259            8 :         heatflux_mf[lev]->setVal(0.0);
     260            8 :         thermal.w1 = 0.2 * chamber.pressure + 0.9;
     261            8 :         ic_laser->Initialize(lev, laser_mf);
     262              :     }
     263           14 :     if (variable_pressure) chamber.pressure = 1.0;
     264           14 : }
     265              : 
     266            0 : void Flame::UpdateModel(int /*a_step*/, Set::Scalar /*a_time*/)
     267              : {
     268            0 :     if (m_type == Base::Mechanics<model_type>::Type::Disable) return;
     269              : 
     270            0 :     for (int lev = 0; lev <= finest_level; ++lev)
     271              :     {
     272            0 :         amrex::Box domain = this->geom[lev].Domain();
     273            0 :         domain.convert(amrex::IntVect::TheNodeVector());
     274            0 :         const Set::Scalar* DX = geom[lev].CellSize();
     275              : 
     276            0 :         phi_mf[lev]->FillBoundary();
     277            0 :         eta_mf[lev]->FillBoundary();
     278            0 :         temp_mf[lev]->FillBoundary();
     279              : 
     280            0 :         for (MFIter mfi(*model_mf[lev], false); mfi.isValid(); ++mfi)
     281              :         {
     282            0 :             amrex::Box smallbox = mfi.nodaltilebox();
     283            0 :             amrex::Box bx = mfi.grownnodaltilebox() & domain;
     284            0 :             Set::Patch<model_type>        model = model_mf.Patch(lev,mfi);
     285            0 :             Set::Patch<const Set::Scalar> phi   = phi_mf.Patch(lev,mfi);
     286            0 :             Set::Patch<const Set::Scalar> eta   = eta_mf.Patch(lev,mfi);
     287            0 :             Set::Patch<Set::Vector>       rhs   = rhs_mf.Patch(lev,mfi);
     288              : 
     289            0 :             if (elastic.on)
     290              :             {
     291            0 :                 Set::Patch <const Set::Scalar> temp = temp_mf.Patch(lev,mfi);
     292            0 :                 amrex::ParallelFor(smallbox, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     293              :                 {
     294            0 :                     Set::Vector grad_eta = Numeric::CellGradientOnNode(eta, i, j, k, 0, DX);
     295            0 :                     rhs(i, j, k) = elastic.traction * grad_eta;
     296            0 :                 });
     297            0 :                 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     298              :                 {
     299            0 :                     Set::Scalar phi_avg = phi(i, j, k, 0);
     300            0 :                     Set::Scalar temp_avg = Numeric::Interpolate::CellToNodeAverage(temp, i, j, k, 0);
     301            0 :                     model_type model_ap = elastic.model_ap;
     302            0 :                     model_ap.F0 -= Set::Matrix::Identity();
     303            0 :                     model_ap.F0 *= (temp_avg - elastic.Telastic);
     304            0 :                     model_ap.F0 += Set::Matrix::Identity();
     305            0 :                     model_type model_htpb = elastic.model_htpb;
     306            0 :                     model_htpb.F0 -= Set::Matrix::Identity();
     307            0 :                     model_htpb.F0 *= (temp_avg - elastic.Telastic);
     308            0 :                     model_htpb.F0 += Set::Matrix::Identity();
     309              : 
     310            0 :                     model(i, j, k) = model_ap * phi_avg + model_htpb * (1. - phi_avg);
     311            0 :                 });
     312              :             }
     313              :             else
     314              :             {
     315            0 :                 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     316              :                 {
     317            0 :                     Set::Scalar phi_avg = Numeric::Interpolate::CellToNodeAverage(phi, i, j, k, 0);
     318              :                     //phi_avg = phi(i,j,k,0);
     319            0 :                     model_type model_ap = elastic.model_ap;
     320            0 :                     model_ap.F0 *= Set::Matrix::Zero();
     321            0 :                     model_type model_htpb = elastic.model_htpb;
     322            0 :                     model_htpb.F0 *= Set::Matrix::Zero();
     323            0 :                     model(i, j, k) = model_ap * phi_avg + model_htpb * (1. - phi_avg);
     324            0 :                 });
     325              :             }
     326            0 :         }
     327            0 :         Util::RealFillBoundary(*model_mf[lev], geom[lev]);
     328              : 
     329              :     }
     330              : }
     331              : 
     332          818 : void Flame::TimeStepBegin(Set::Scalar a_time, int a_iter)
     333              : {
     334              :     BL_PROFILE("Integrator::Flame::TimeStepBegin");
     335          818 :     Base::Mechanics<model_type>::TimeStepBegin(a_time, a_iter);
     336          818 :     if (thermal.on) {
     337           90 :         for (int lev = 0; lev <= finest_level; ++lev)
     338           80 :             ic_laser->Initialize(lev, laser_mf, a_time);
     339              :     }
     340          818 : }
     341              : 
     342          818 : void Flame::TimeStepComplete(Set::Scalar /*a_time*/, int /*a_iter*/)
     343              : {
     344              :     BL_PROFILE("Integrator::Flame::TimeStepComplete");
     345          818 :     if (variable_pressure) {
     346              :         //Set::Scalar x_len = geom[0].ProbDomain().length(0);
     347              :         //Set::Scalar y_len = geom[0].ProbDomain().length(1);
     348              :         // Set::Scalar domain_area = x_len * y_len;
     349            0 :         Util::Message(INFO, "Mass = ", chamber.massflux);
     350            0 :         Util::Message(INFO, "Pressure = ", chamber.pressure);
     351              :     }
     352          818 : }
     353              : 
     354         8206 : void Flame::Advance(int lev, Set::Scalar time, Set::Scalar dt)
     355              : {
     356              :     BL_PROFILE("Integrador::Flame::Advance");
     357         8206 :     Base::Mechanics<model_type>::Advance(lev, time, dt);
     358         8206 :     const Set::Scalar* DX = geom[lev].CellSize();
     359              : 
     360         8206 :     std::swap(eta_old_mf[lev], eta_mf[lev]);
     361              : 
     362              :     //
     363              :     // Chamber pressure update
     364              :     //
     365         8206 :     if (variable_pressure) {
     366            0 :         chamber.pressure = exp(0.00075 * chamber.massflux);
     367            0 :         if (chamber.pressure > 10.0) {
     368            0 :             chamber.pressure = 10.0;
     369              :         }
     370            0 :         else if (chamber.pressure <= 0.99) {
     371            0 :             chamber.pressure = 0.99;
     372              :         }
     373            0 :         elastic.traction = chamber.pressure;
     374              :     }
     375              : 
     376              : 
     377              :     //
     378              :     // Multi-well chemical potential
     379              :     //
     380              :     Numeric::Function::Polynomial<4> w( pf.w0,
     381              :                                         0.0,
     382         8206 :                                         -5.0 * pf.w1 + 16.0 * pf.w12 - 11.0 * pf.w0,
     383         8206 :                                         14.0 * pf.w1 - 32.0 * pf.w12 + 18.0 * pf.w0,
     384         8206 :                                         -8.0 * pf.w1 + 16.0 * pf.w12 - 8.0 * pf.w0);
     385         8206 :     Numeric::Function::Polynomial<3> dw = w.D();
     386              : 
     387         8206 :     propellant.set_pressure(chamber.pressure);
     388              : 
     389        30068 :     for (amrex::MFIter mfi(*eta_mf[lev], true); mfi.isValid(); ++mfi)
     390              :     {
     391        21862 :         const amrex::Box& bx = mfi.tilebox();
     392              :         // Phase fields
     393        21862 :         Set::Patch<Set::Scalar> etanew    = eta_mf.Patch(lev,mfi);
     394        21862 :         Set::Patch<const Set::Scalar> eta = eta_old_mf.Patch(lev,mfi);
     395        21862 :         Set::Patch<const Set::Scalar> phi = phi_mf.Patch(lev,mfi);
     396              :         // Heat transfer fields
     397        21862 :         Set::Patch<const Set::Scalar> temp = temp_mf.Patch(lev,mfi);
     398        21862 :         Set::Patch<Set::Scalar>       alpha = alpha_mf.Patch(lev,mfi);
     399        21862 :         Set::Patch<Set::Scalar>       laser = laser_mf.Patch(lev,mfi);
     400              :         // Diagnostic fields
     401        21862 :         Set::Patch<Set::Scalar> mdot     = mdot_mf.Patch(lev,mfi);
     402        21862 :         Set::Patch<Set::Scalar> heatflux = heatflux_mf.Patch(lev,mfi);
     403              : 
     404              : 
     405        21862 :         amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     406              :         {
     407              :             //
     408              :             // CALCULATE PHI-AVERAGED QUANTITIES
     409              :             //
     410     59108224 :             Set::Scalar phi_avg = Numeric::Interpolate::NodeToCellAverage(phi, i, j, k, 0);
     411     60856064 :             Set::Scalar T = thermal.on ? temp(i,j,k) : NAN;
     412              : 
     413     59108224 :             Set::Scalar K = propellant.get_K(phi_avg);
     414              : 
     415     59108224 :             Set::Scalar rho = propellant.get_rho(phi_avg);
     416              : 
     417     59108224 :             Set::Scalar cp = propellant.get_cp(phi_avg);
     418              : 
     419              :             //
     420              :             // CALCULATE MOBILITY
     421              :             // 
     422     59108224 :             Set::Scalar L = propellant.get_L(  phi_avg, T);
     423              : 
     424              :             // 
     425              :             // EVOLVE PHASE FIELD (ETA)
     426              :             // 
     427              : 
     428     59108224 :             Set::Scalar eta_lap = Numeric::Laplacian(eta, i, j, k, 0, DX);
     429    118216448 :             Set::Scalar df_deta = ((pf.lambda / pf.eps) * dw(eta(i, j, k)) - pf.eps * pf.kappa * eta_lap);
     430    118216448 :             etanew(i, j, k) = eta(i, j, k) - L * dt * df_deta;
     431    118216448 :             if (etanew(i, j, k) <= small) etanew(i, j, k) = small;
     432              : 
     433     59108224 :             if (thermal.on)
     434              :             {
     435              :                 //
     436              :                 // Calculate thermal diffisivity and store for later gradient
     437              :                 //
     438              : 
     439      1747840 :                 alpha(i, j, k) = K / rho / cp; 
     440              : 
     441              :                 //
     442              :                 // CALCULATE MASS FLUX BASED ON EVOLVING ETA
     443              :                 //
     444              :             
     445      5243520 :                 mdot(i, j, k) = rho * fabs(eta(i, j, k) - etanew(i, j, k)) / dt; 
     446              : 
     447              :                 //
     448              :                 // CALCULATE HEAT FLUX BASED ON THE CALCULATED MASS FLUX
     449              :                 //
     450              : 
     451      3495680 :                 Set::Scalar q0 = propellant.get_qdot(mdot(i,j,k), phi_avg);
     452      5243520 :                 heatflux(i,j,k) = ( thermal.hc*q0 + laser(i,j,k) ) / K;
     453              : 
     454              :             }
     455              : 
     456     59108224 :         });
     457              : 
     458         8206 :     } // MFi For loop 
     459              : 
     460              : 
     461              :     //
     462              :     // THERMAL TRANSPORT
     463              :     // 
     464         8206 :     if (thermal.on)
     465              :     {
     466         2550 :         std::swap(temp_old_mf[lev], temp_mf[lev]);
     467              : 
     468        13100 :         for (amrex::MFIter mfi(*eta_mf[lev], true); mfi.isValid(); ++mfi)
     469              :         {
     470        10550 :             const amrex::Box& bx = mfi.tilebox();
     471              : 
     472        10550 :             Set::Patch<Set::Scalar>       tempnew = temp_mf.Patch(lev,mfi);
     473        10550 :             Set::Patch<const Set::Scalar> temp = temp_old_mf.Patch(lev,mfi);
     474        10550 :             Set::Patch<const Set::Scalar> alpha = alpha_mf.Patch(lev,mfi);
     475              : 
     476        10550 :             Set::Patch<Set::Scalar>       temps = temps_mf.Patch(lev,mfi);
     477              : 
     478              : 
     479              :             // Phase field
     480        10550 :             Set::Patch<Set::Scalar>       etanew = (*eta_mf[lev]).array(mfi);
     481        10550 :             Set::Patch<const Set::Scalar> eta = (*eta_old_mf[lev]).array(mfi);
     482              :             // Diagnostic fields
     483        10550 :             Set::Patch<const Set::Scalar> heatflux = heatflux_mf.Patch(lev,mfi);
     484              : 
     485        10550 :             amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     486              :             {
     487      1747840 :                 auto sten = Numeric::GetStencil(i, j, k, bx);
     488      1747840 :                 Set::Vector grad_eta = Numeric::Gradient(eta, i, j, k, 0, DX);
     489      1747840 :                 Set::Vector grad_temp = Numeric::Gradient(temp, i, j, k, 0, DX);
     490      1747840 :                 Set::Scalar lap_temp = Numeric::Laplacian(temp, i, j, k, 0, DX);
     491      1747840 :                 Set::Scalar grad_eta_mag = grad_eta.lpNorm<2>();
     492      1747840 :                 Set::Vector grad_alpha = Numeric::Gradient(alpha, i, j, k, 0, DX, sten);
     493      1747840 :                 Set::Scalar dTdt = 0.0;
     494      3495680 :                 dTdt += grad_eta.dot(grad_temp * alpha(i, j, k));
     495      3495680 :                 dTdt += grad_alpha.dot(eta(i, j, k) * grad_temp);
     496      3495680 :                 dTdt += eta(i, j, k) * alpha(i, j, k) * lap_temp;
     497      3495680 :                 dTdt += alpha(i, j, k) * heatflux(i, j, k) * grad_eta_mag;
     498              : 
     499      5243520 :                 Set::Scalar Tsolid = dTdt + temps(i, j, k) * (etanew(i, j, k) - eta(i, j, k)) / dt;
     500      3495680 :                 temps(i, j, k) = temps(i, j, k) + dt * Tsolid;
     501      6991360 :                 tempnew(i, j, k) = etanew(i, j, k) * temps(i, j, k) + (1.0 - etanew(i, j, k)) * thermal.Tfluid;
     502      1747840 :             });
     503         2550 :         }
     504              :     }
     505              :  
     506         8206 : } //Function
     507              : 
     508              : 
     509          190 : void Flame::TagCellsForRefinement(int lev, amrex::TagBoxArray& a_tags, Set::Scalar time, int ngrow)
     510              : {
     511              :     BL_PROFILE("Integrator::Flame::TagCellsForRefinement");
     512          190 :     Base::Mechanics<model_type>::TagCellsForRefinement(lev, a_tags, time, ngrow);
     513              : 
     514          190 :     const Set::Scalar* DX = geom[lev].CellSize();
     515          190 :     Set::Scalar dr = sqrt(AMREX_D_TERM(DX[0] * DX[0], +DX[1] * DX[1], +DX[2] * DX[2]));
     516              : 
     517              :     // Eta criterion for refinement
     518          602 :     for (amrex::MFIter mfi(*eta_mf[lev], true); mfi.isValid(); ++mfi)
     519              :     {
     520          412 :         const amrex::Box& bx = mfi.tilebox();
     521          412 :         amrex::Array4<char> const& tags = a_tags.array(mfi);
     522          412 :         Set::Patch<const Set::Scalar> eta = eta_mf.Patch(lev,mfi);
     523              : 
     524          412 :         amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     525              :         {
     526       519920 :             Set::Vector gradeta = Numeric::Gradient(eta, i, j, k, 0, DX);
     527       541390 :             if (gradeta.lpNorm<2>() * dr * 2 > m_refinement_criterion && eta(i, j, k) >= t_refinement_restriction)
     528        41936 :                 tags(i, j, k) = amrex::TagBox::SET;
     529       519920 :         });
     530          190 :     }
     531              : 
     532              :     // Phi criterion for refinement 
     533          190 :     if (elastic.phirefinement) {
     534          602 :         for (amrex::MFIter mfi(*eta_mf[lev], true); mfi.isValid(); ++mfi)
     535              :         {
     536          412 :             const amrex::Box& bx = mfi.tilebox();
     537          412 :             amrex::Array4<char> const& tags = a_tags.array(mfi);
     538          412 :             Set::Patch<const Set::Scalar> phi = phi_mf.Patch(lev,mfi);
     539              : 
     540          412 :             amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     541              :             {
     542       519920 :                 Set::Vector gradphi = Numeric::Gradient(phi, i, j, k, 0, DX);
     543       519920 :                 if (gradphi.lpNorm<2>() * dr >= phi_refinement_criterion)
     544            0 :                     tags(i, j, k) = amrex::TagBox::SET;
     545       519920 :             });
     546          190 :         }
     547              :     }
     548              : 
     549              : 
     550              :     // Thermal criterion for refinement 
     551          190 :     if (thermal.on) {
     552          507 :         for (amrex::MFIter mfi(*temp_mf[lev], true); mfi.isValid(); ++mfi)
     553              :         {
     554          345 :             const amrex::Box& bx = mfi.tilebox();
     555          345 :             amrex::Array4<char> const& tags = a_tags.array(mfi);
     556          345 :             Set::Patch<const Set::Scalar> temp = temp_mf.Patch(lev,mfi);
     557          345 :             Set::Patch<const Set::Scalar> eta  = eta_mf.Patch(lev,mfi);
     558          345 :             amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     559              :             {
     560        50928 :                 Set::Vector tempgrad = Numeric::Gradient(temp, i, j, k, 0, DX);
     561        50928 :                 if (tempgrad.lpNorm<2>() * dr > t_refinement_criterion && eta(i, j, k) >= t_refinement_restriction)
     562            0 :                     tags(i, j, k) = amrex::TagBox::SET;
     563        50928 :             });
     564          162 :         }
     565              :     }
     566          190 : }
     567              : 
     568            2 : void Flame::Regrid(int lev, Set::Scalar time)
     569              : {
     570              :     BL_PROFILE("Integrator::Flame::Regrid");
     571              :     //if (lev < finest_level) return;
     572              :     //phi_mf[lev]->setVal(0.0);
     573            2 :     ic_phi->Initialize(lev, phi_mf, time);
     574              :     //ic_phicell->Initialize(lev, phi_mf, time);
     575            2 : }
     576              : 
     577          220 : void Flame::Integrate(int amrlev, Set::Scalar /*time*/, int /*step*/,
     578              :     const amrex::MFIter& mfi, const amrex::Box& box)
     579              : {
     580              :     BL_PROFILE("Flame::Integrate");
     581          220 :     const Set::Scalar* DX = geom[amrlev].CellSize();
     582          220 :     Set::Scalar dv = AMREX_D_TERM(DX[0], *DX[1], *DX[2]);
     583          220 :     Set::Patch<const Set::Scalar> eta  = eta_mf.Patch(amrlev,mfi);
     584          220 :     Set::Patch<const Set::Scalar> mdot = mdot_mf.Patch(amrlev,mfi);
     585          220 :     if (variable_pressure) {
     586            0 :         amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     587              :         {
     588            0 :             chamber.volume += eta(i, j, k, 0) * dv;
     589            0 :             Set::Vector grad = Numeric::Gradient(eta, i, j, k, 0, DX);
     590            0 :             Set::Scalar normgrad = grad.lpNorm<2>();
     591            0 :             Set::Scalar da = normgrad * dv;
     592            0 :             chamber.area += da;
     593              : 
     594            0 :             Set::Vector mgrad = Numeric::Gradient(mdot, i, j, k, 0, DX);
     595            0 :             Set::Scalar mnormgrad = mgrad.lpNorm<2>();
     596            0 :             Set::Scalar dm = mnormgrad * dv;
     597            0 :             chamber.massflux += dm;
     598              : 
     599            0 :         });
     600              :     }
     601              :     else {
     602          220 :         amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     603              :         {
     604        15560 :             chamber.volume += eta(i, j, k, 0) * dv;
     605        15560 :             Set::Vector grad = Numeric::Gradient(eta, i, j, k, 0, DX);
     606        15560 :             Set::Scalar normgrad = grad.lpNorm<2>();
     607        15560 :             Set::Scalar da = normgrad * dv;
     608        15560 :             chamber.area += da;
     609        15560 :         });
     610              :     }
     611              :     // time dependent pressure data from experimenta -> p = 0.0954521220950523 * exp(15.289993148880678 * t)
     612          220 : }
     613              : } // namespace Integrator
     614              : 
     615              : 
        

Generated by: LCOV version 2.0-1