Alamo
Flame.cpp
Go to the documentation of this file.
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/PointList.H"
8#include "IC/PSRead.H"
9#include "Numeric/Function.H"
10#include "IC/Expression.H"
11#include "IC/BMP.H"
12#include "IC/PNG.H"
13#include "Base/Mechanics.H"
14#include "Util/Util.H"
18#include <cmath>
19
20namespace Integrator
21{
22
25
27{
28 pp_queryclass(*this);
29}
30
31
32void
34{
35 pp.forbid("pressure.P","use chamber.pressure instead");
36
37 pp.forbid("geometry.x_len","This is specified by geometry.prob_lo/hi");
38 pp.forbid("geometry.y_len","This is specified by geometry.prob_lo/hi");
39 pp.forbid("amr.ghost_cells", "This should not be adjustable ");
40
41 pp.forbid("pf.gamma","use propellant.powerlaw.gamma");
42
43 pp.forbid("pressure.r_ap", "use propellant.powerlaw.r_ap");
44 pp.forbid("pressure.r_htpb", "use propellant.powerlaw.r_htpb");
45 pp.forbid("pressure.r_comb", "use propellant.powerlaw.r_comb");
46 pp.forbid("pressure.n_ap", "use propellant.powerlaw.n_ap");
47 pp.forbid("pressure.n_htpb", "use propellant.powerlaw.n_htpb");
48 pp.forbid("pressure.n_comb", "use propellant.powerlaw.n_comb");
49
50 pp.forbid("thermal.bound", "use thermal.Tref");
51 pp.forbid("thermal.T_fluid", "use thermal.Tfluid (or nothing)");
52 pp.forbid("thermal.m_ap", "use propellant.fullfeedback.m_ap");
53 pp.forbid("thermal.m_htpb", "use propellant.fullfeedback.m_htpb");
54 pp.forbid("thermal.E_ap", "use propellant.fullfeedback.E_ap");
55 pp.forbid("thermal.E_htpb", "use propellant.fullfeedback.E_htpb");
56 pp.forbid("thermal.modeling_ap", "Old debug variable. Should equal 1 ");
57 pp.forbid("thermal.modeling_htpb", "Old debug variable. Should equal 1");
58
59 pp.forbid("pressure.a1", "use propellant.fullfeedback.a1 instead");
60 pp.forbid("pressure.a2", "use propellant.fullfeedback.a2 instead");
61 pp.forbid("pressure.a3", "use propellant.fullfeedback.a3 instead");
62 pp.forbid("pressure.b1", "use propellant.fullfeedback.b1 instead");
63 pp.forbid("pressure.b2", "use propellant.fullfeedback.b2 instead");
64 pp.forbid("pressure.b3", "use propellant.fullfeedback.b3 instead");
65 pp.forbid("pressure.c1", "use propellant.fullfeedback.c1 instead");
66 pp.forbid("pressure.mob_ap", "no longer used");
67 pp.forbid("pressure.dependency", "use propellant.fullfeedback.pressure_dependency");
68 pp.forbid("pressure.h1", "use propellant.homogenize.h1 instead");
69 pp.forbid("pressure.h2", "use propellant.homogenize.h2 instead");
70 pp.forbid("thermal.mlocal_ap", "use propellant.homogenize.mlocal_ap");
71 pp.forbid("thermal.mlocal_comb", "use propellant.homogenize.mlocal_comb");
72 pp.forbid("thermal.mlocal_htpb", "this actually did **nothing** - it was overridden by a hard code using massfraction.");
73
74 pp.forbid("thermal.disperssion1", "use propellant.homogenize.dispersion1");
75 pp.forbid("thermal.disperssion2", "use propellant.homogenize.dispersion2");
76 pp.forbid("thermal.disperssion3", "use propellant.homogenize.dispersion3");
77
78 pp.forbid("thermal.rho_ap", "use propellant.fullfeedback/homogenize.rho_ap ");
79 pp.forbid("thermal.rho_htpb","use propellant.fullfeedback/homogenize.rho_htpb ");
80 pp.forbid("thermal.k_ap", "use propellant.fullfeedback/homogenize.k_ap ");
81 pp.forbid("thermal.k_htpb", "use propellant.fullfeedback/homogenize.k_htpb ");
82 pp.forbid("thermal.cp_ap", "use propellant.fullfeedback/homogenize.cp_ap ");
83 pp.forbid("thermal.cp_htpb","use propellant.fullfeedback/homogenize.cp_htpb ");
84}
85
86
87// [parser]
88void
90{
91 BL_PROFILE("Integrator::Flame::Flame()");
92
93 Forbids(pp);
94
95 // Whether to include extra fields (such as mdot, etc) in the plot output
96 pp.query_default("plot_field",value.plot_field,true);
97
98 //
99 // PHASE FIELD VARIABLES
100 //
101
102 // Burn width thickness
103 pp.query_default("pf.eps", value.pf.eps, "1.0_m", Unit::Length());
104 // Interface energy param
105 pp.query_default("pf.kappa", value.pf.kappa, "0.0_J/m^2", Unit::Energy() / Unit::Area());
106 // Chemical potential multiplier
107 pp.query_default("pf.lambda", value.pf.lambda, "0.0_J/m^2", Unit::Energy()/Unit::Area());
108 // Unburned rest energy
109 pp.query_default("pf.w1", value.pf.w1, "0.0",Unit::Less());
110 // Barrier energy
111 pp.query_default("pf.w12", value.pf.w12, "0.0", Unit::Less());
112 // Burned rest energy
113 pp.query_default("pf.w0", value.pf.w0, "0.0",Unit::Less());
114
115 // Boundary conditions for phase field order params
116 pp.select<BC::Constant>("pf.eta.bc", value.bc_eta, pp.forward_args(1));
117 value.RegisterNewFab(value.eta_mf, value.bc_eta, 1, 2, "eta", true);
118 value.RegisterNewFab(value.eta_old_mf, value.bc_eta, 1, 2, "eta_old", 0);
119
120 // Inital value of eta that doesn't evolve and is used during refiment to set the updated values of eta with voids in the domain.
121 // Used to fix a bug where duirn refinement, a void won't be updated correctly and would be a square, not a circle
122 value.RegisterNewFab(value.eta_0_mf, value.bc_eta, 1, 2, "eta_0", 0);
123
124 // value.RegisterNewFab(value.eta_mf_frozen, value.bc_eta, 1, 2, "eta_frozen", value.plot_field);
125
126 // phase field initial condition
128
129
130 // Select reduced order model to capture heat feedback
134 ("propellant",value.propellant);
135
136
137 // Reference temperature
138 // Used to set all other reference temperatures by default.
139 pp_query_default("thermal.Tref", value.thermal.Tref, "300.0_K",Unit::Temperature());
140
141 // Whether to use the Thermal Transport Model
142 pp.query_if("thermal.on", [&](){
143 value.thermal.on = true;
144
145 // Used to change heat flux units
146 pp_query_default("thermal.hc", value.thermal.hc, "1.0", Unit::Power()/Unit::Area());
147
148 // Effective fluid temperature, temp of the eta = 0 (fluid) region
149 pp_query_default("thermal.Tfluid", value.thermal.Tfluid, value.thermal.Tref);
150
151 // Cutoff value for regression, if T < Tcutoff eta won't evolve/regress
152 pp.query_default("thermal.Tcutoff", value.thermal.Tcutoff, "0.0", Unit::Temperature());
153
154 // Switch time of the improved regridding where eta and the temperature field are both used. It is recommended to make this time ~10x the timestep.
155 // Before this the refinement is based on the gradient of eta which helps the laser IC start correctly. A regrid is forced when this time is reached.
156 pp.query_default("thermal.end_initial_refine_time", value.thermal.end_initial_refine_time, "0.0", Unit::Time());
157
158 // Inital refinement of the phi field based on phi gradient. After time > end_initial_refine_time stops refining at these phi values.
159 pp.query_default("thermal.phi_refinement_criterion_inital", value.thermal.phi_refinement_criterion_inital, 1.0e100);
160
161 //Temperature boundary condition
162 pp.select_default<BC::Constant>("thermal.temp.bc", value.bc_temp, pp.forward_args(1, Unit::Temperature()));
163
164 value.RegisterNewFab(value.temp_mf, value.bc_temp, 1, 3, "temp", true);
165 value.RegisterNewFab(value.temp_old_mf, value.bc_temp, 1, 3, "temp_old", false);
166 value.RegisterNewFab(value.temps_mf, value.bc_temp, 1, 0, "temps", false);
167
168 value.RegisterNewFab(value.mdot_mf, value.bc_temp, 1, 0, "mdot", value.plot_field);
169 value.RegisterNewFab(value.alpha_mf, value.bc_temp, 1, 0, "alpha", value.plot_field);
170 value.RegisterNewFab(value.heatflux_mf, value.bc_temp, 1, 0, "heatflux", value.plot_field);
171 value.RegisterNewFab(value.laser_mf, value.bc_temp, 1, 0, "laser", value.plot_field);
172
173 value.RegisterIntegratedVariable(&value.chamber.volume, "volume");
174 value.RegisterIntegratedVariable(&value.chamber.area, "area");
175 value.RegisterIntegratedVariable(&value.chamber.massflux, "mass_flux");
176
177 value.RegisterNewFab(value.thermal.has_exceeded_Tcutoff, value.bc_temp, 1, 2, "exceeded_Tcutoff", 0); // Used to determine where regression has started
178
179 // laser initial condition
182 ("laser.ic",value.ic_laser, pp.forward_args(value.geom, Unit::Power()/Unit::Area()));
183
184 // thermal initial condition
187 IC::BMP,
188 IC::PNG >
189 ("temp.ic",value.thermal.ic_temp,pp.forward_args(value.geom, Unit::Temperature()));
190 });
191
192
193 // Constant pressure value
194 pp_query_default("chamber.pressure", value.chamber.pressure, "1.0_MPa", Unit::Pressure());
195
196 // Whether to compute the pressure evolution
197 pp_query_default("variable_pressure", value.variable_pressure, false);
198
199 // Refinement criterion for eta field, if thermal is on, cells will only be tagged for refinement if T>0.9*TCutoff,
200 // and the gradient of eta > m_refinement_criterion at each cell
201 pp_query_default( "amr.refinement_criterion", value.m_refinement_criterion, "0.001",
202 Unit::Less());
203
204 // Refinement criterion for temperature field
205 pp.query_default( "amr.refinement_criterion_temp", value.t_refinement_criterion, "0.001_K",
207
208 // Eta value to restrict the refinament for the temperature field
209 pp.query_default( "amr.refinament_restriction", value.t_refinement_restriction, "0.1",
210 Unit::Less());
211
212 // Refinement criterion for phi field [infinity]
213 pp_query_default("amr.phi_refinement_criterion", value.phi_refinement_criterion, 1.0e100);
214
215 // Minimum allowable threshold for $\eta$
216 pp_query_default("small", value.small, 1.0e-8);
217
218 // Initial condition for $\phi$ field.
220 ("phi.ic",value.ic_phi,pp.forward_args(value.geom));
221
222 value.RegisterNodalFab(value.phi_mf, 1, 2, "phi", true);
223
224 // Whether to use Neo-hookean Elastic model
226 pp.query_if("elastic.on", [&]() {
227 value.elastic.on = true;
228
229 // Body force
230 pp_query_default("elastic.traction", value.elastic.traction, 0.0);
231
232 // Phi refinement criteria
233 pp_query_default("elastic.phirefinement", value.elastic.phirefinement, 1);
234
235 // Elastic integrator
236 pp.queryclass<Base::Mechanics<model_type>>("elastic",value);
237
238
239
240 // Reference temperature for thermal expansion
241 // (temperature at which the material is strain-free)
242 pp_query_default("Telastic", value.elastic.Telastic, value.thermal.Tref);
243 // elastic model of AP
245 // elastic model of HTPB
247
248 // eta cutoff value to stop applying the traction force and/or chamber pressure to the RHS.
249 // Below this vlaue the RHS is set to 0.0
250 pp.query_default("etacutoff",value.elastic.etacutoff, "0", Unit::Less());
251
252 // Boolean value, when not 0 the chamber.pressure value is applied at the diffuse interface where t>Tcutoff
253 pp.query_default("apply_chamber_pressure",value.elastic.apply_chamber_pressure, "0", Unit::Less());
254
255 // Use our current eta field as the psi field for the solver
256 value.psi_on = false;
257 value.solver.setPsi(value.eta_mf);
258
259 if (IO::ParmParse::InTraversalMode()) return;
260
261 Util::AssertException(INFO, TEST(value.m_type != Disable), "You must specify elastic type to be dynamic or static");
262 });
263
264
265
266 bool allow_unused;
267 // Set this to true to allow unused inputs without error.
268 // (Not recommended.)
269 pp.query_default("allow_unused",allow_unused,false);
270 if (!allow_unused && pp.AnyUnusedInputs())
271 {
272 Util::Warning(INFO,"The following inputs were specified but not used:");
273 pp.AllUnusedInputs();
274 Util::Exception(INFO,"Aborting. Specify 'allow_unused=True` to ignore this error.");
275 }
276}
277
278void Flame::Initialize(int lev)
279{
280 BL_PROFILE("Integrator::Flame::Initialize");
282
283 ic_eta->Initialize(lev, eta_mf);
285 ic_phi->Initialize(lev, phi_mf);
286 //ic_phicell->Initialize(lev, phicell_mf);
287
288 if (elastic.on) {
289 rhs_mf[lev]->setVal(Set::Vector::Zero());
290 }
291 if (thermal.on) {
292 if (thermal.ic_temp)
293 {
294 thermal.ic_temp->Initialize(lev,temp_mf);
295 thermal.ic_temp->Initialize(lev,temp_old_mf);
296 thermal.ic_temp->Initialize(lev,temps_mf);
297 }
298 else
299 {
300 temp_mf[lev]->setVal(thermal.Tref);
301 temp_old_mf[lev]->setVal(thermal.Tref);
302 temps_mf[lev]->setVal(thermal.Tref);
303 }
304 alpha_mf[lev]->setVal(0.0);
305 mdot_mf[lev]->setVal(0.0);
306 heatflux_mf[lev]->setVal(0.0);
308 }
309 if (variable_pressure) chamber.pressure = 1.0;
310}
311
312void Flame::UpdateModel(int /*a_step*/, Set::Scalar /*a_time*/)
313{
315
316 for (int lev = 0; lev <= finest_level; ++lev)
317 {
318 amrex::Box domain = this->geom[lev].Domain();
319 domain.convert(amrex::IntVect::TheNodeVector());
320 const Set::Scalar* DX = geom[lev].CellSize();
321
322 phi_mf[lev]->FillBoundary();
323 eta_mf[lev]->FillBoundary();
324 temp_mf[lev]->FillBoundary();
325
326 for (MFIter mfi(*model_mf[lev], false); mfi.isValid(); ++mfi)
327 {
328 amrex::Box smallbox = mfi.nodaltilebox();
329 amrex::Box bx = mfi.grownnodaltilebox() & domain;
330 Set::Patch<model_type> model = model_mf.Patch(lev,mfi);
333 Set::Patch<Set::Vector> rhs = rhs_mf.Patch(lev,mfi);
334 Set::Scalar Tcutoff = thermal.Tcutoff;
335
336 if (elastic.on)
337 {
339 amrex::ParallelFor(smallbox, [=] AMREX_GPU_DEVICE(int i, int j, int k)
340
341 {
342 Set::Vector grad_eta = Numeric::CellGradientOnNode(eta, i, j, k, 0, DX);
343
344 if (temp(i,j,k) > Tcutoff && eta(i,j,k) > elastic.etacutoff && elastic.apply_chamber_pressure)
345 {
346 rhs(i, j, k) = (elastic.traction) * grad_eta - chamber.pressure*grad_eta;
347 // std::cout << "Applying chamber pressure" << std::endl;
348 }
349 else if (temp(i,j,k) > Tcutoff && eta(i,j,k) > elastic.etacutoff && !elastic.apply_chamber_pressure)
350 {
351 rhs(i, j, k) = (elastic.traction) * grad_eta;
352 // std::cout << "Applying traction" << std::endl;
353 }
354 else
355 rhs(i, j, k) = 0.0 * grad_eta;
356 // std::cout << "Applying neither" << std::endl;
357
358 });
359 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
360 {
361 Set::Scalar phi_avg = phi(i, j, k, 0);
362 Set::Scalar temp_avg = Numeric::Interpolate::CellToNodeAverage(temp, i, j, k, 0);
363 model_type model_ap = elastic.model_ap;
364 model_ap.F0 -= Set::Matrix::Identity();
365 model_ap.F0 *= (temp_avg - elastic.Telastic);
366 model_ap.F0 += Set::Matrix::Identity();
367 model_type model_htpb = elastic.model_htpb;
368 model_htpb.F0 -= Set::Matrix::Identity();
369 model_htpb.F0 *= (temp_avg - elastic.Telastic);
370 model_htpb.F0 += Set::Matrix::Identity();
371
372 model(i, j, k) = (model_ap * phi_avg + model_htpb * (1. - phi_avg));
373 });
374 }
375 else
376 {
377 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
378 {
379 Set::Scalar phi_avg = Numeric::Interpolate::CellToNodeAverage(phi, i, j, k, 0);
380 //phi_avg = phi(i,j,k,0);
381 model_type model_ap = elastic.model_ap;
382 model_ap.F0 *= Set::Matrix::Zero();
383 model_type model_htpb = elastic.model_htpb;
384 model_htpb.F0 *= Set::Matrix::Zero();
385 model(i, j, k) = (model_ap * phi_avg + model_htpb * (1. - phi_avg));
386 });
387 }
388 }
389 Util::RealFillBoundary(*model_mf[lev], geom[lev]);
390
391 }
392}
393
394void Flame::TimeStepBegin(Set::Scalar a_time, int a_iter)
395{
396 BL_PROFILE("Integrator::Flame::TimeStepBegin");
398 if (thermal.on) {
399 for (int lev = 0; lev <= finest_level; ++lev)
400 ic_laser->Initialize(lev, laser_mf, a_time);
401 }
402
403 if (a_time > thermal.end_initial_refine_time)
404 {
405 if (!end_initial_refine) {
406 for (int lev = 0; lev <= finest_level; ++lev)
407 Flame::Regrid(lev, a_time);
409 }
410
411 prev_finest_ba = grids[finest_level];
412 prev_finest_level = finest_level;
413 }
414}
415
416void Flame::TimeStepComplete(Set::Scalar /*a_time*/, int /*a_iter*/)
417{
418 BL_PROFILE("Integrator::Flame::TimeStepComplete");
419 if (variable_pressure) {
420 //Set::Scalar x_len = geom[0].ProbDomain().length(0);
421 //Set::Scalar y_len = geom[0].ProbDomain().length(1);
422 // Set::Scalar domain_area = x_len * y_len;
423 Util::Message(INFO, "Mass = ", chamber.massflux);
424 Util::Message(INFO, "Pressure = ", chamber.pressure);
425 }
426}
427
429{
430 BL_PROFILE("Integrador::Flame::Advance");
432 const Set::Scalar* DX = geom[lev].CellSize();
433
434 std::swap(eta_old_mf[lev], eta_mf[lev]);
435
436 //
437 // Chamber pressure update
438 //
439 if (variable_pressure) {
440 chamber.pressure = exp(0.00075 * chamber.massflux);
441 if (chamber.pressure > 10.0) {
442 chamber.pressure = 10.0;
443 }
444 else if (chamber.pressure <= 0.99) {
445 chamber.pressure = 0.99;
446 }
447 elastic.traction = chamber.pressure;
448 }
449
450
451 //
452 // Multi-well chemical potential
453 //
455 0.0,
456 -5.0 * pf.w1 + 16.0 * pf.w12 - 11.0 * pf.w0,
457 14.0 * pf.w1 - 32.0 * pf.w12 + 18.0 * pf.w0,
458 -8.0 * pf.w1 + 16.0 * pf.w12 - 8.0 * pf.w0);
460
462
463 for (amrex::MFIter mfi(*eta_mf[lev], true); mfi.isValid(); ++mfi)
464 {
465 const amrex::Box& bx = mfi.tilebox();
466 // Phase fields
467 Set::Patch<Set::Scalar> etanew = eta_mf.Patch(lev,mfi);
470 // Heat transfer fields
472 Set::Patch<Set::Scalar> alpha = alpha_mf.Patch(lev,mfi);
473 Set::Patch<Set::Scalar> laser = laser_mf.Patch(lev,mfi);
474 // Diagnostic fields
475 Set::Patch<Set::Scalar> mdot = mdot_mf.Patch(lev,mfi);
476 Set::Patch<Set::Scalar> heatflux = heatflux_mf.Patch(lev,mfi);
477
478 Set::Patch<Set::Scalar> exceeded_Tcutoff = thermal.has_exceeded_Tcutoff.Patch(lev, mfi);
479 Set::Scalar Tcutoff = thermal.Tcutoff;
480
481
482 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
483 {
484 //
485 // CALCULATE PHI-AVERAGED QUANTITIES
486 //
487 Set::Scalar phi_avg = Numeric::Interpolate::NodeToCellAverage(phi, i, j, k, 0);
488 Set::Scalar T = thermal.on ? temp(i,j,k) : NAN;
489
490 Set::Scalar K = propellant.get_K(phi_avg);
491
493
494 Set::Scalar cp = propellant.get_cp(phi_avg);
495
496 //
497 // CALCULATE MOBILITY
498 //
499 Set::Scalar L = propellant.get_L( phi_avg, T);
500
501 //
502 // EVOLVE PHASE FIELD (ETA)
503 //
504
505 Set::Scalar eta_lap = Numeric::Laplacian(eta, i, j, k, 0, DX);
506 Set::Scalar df_deta = ((pf.lambda / pf.eps) * dw(eta(i, j, k)) - pf.eps * pf.kappa * eta_lap);
507
508 if (df_deta < 0) {
509 // Prevent eta from increasing/healing. A bug was found where if the diffuse thickness was too large compared to a void
510 // (region of eta = 0), eta would heal/increase in a non-physcial way, this statement stops that behavior
511 df_deta = 0.0;
512 }
513 if (thermal.on && T < thermal.Tcutoff) {
514 // If the temperature is lower then the cutoff temperature don't evolve the eta field
515 df_deta = 0.0;
516 }
517 etanew(i, j, k) = eta(i, j, k) - L * dt * df_deta;
518
519 if (etanew(i, j, k) <= small) etanew(i, j, k) = small;
520
521 if (thermal.on)
522 {
523 //
524 // Calculate thermal diffisivity and store for later gradient
525 //
526
527 alpha(i, j, k) = K / rho / cp;
528
529 //
530 // CALCULATE MASS FLUX BASED ON EVOLVING ETA
531 //
532
533 mdot(i, j, k) = rho * fabs(eta(i, j, k) - etanew(i, j, k)) / dt;
534
535 //
536 // CALCULATE HEAT FLUX BASED ON THE CALCULATED MASS FLUX
537 //
538
539 Set::Scalar q0 = propellant.get_qdot(mdot(i,j,k), phi_avg);
540 heatflux(i,j,k) = ( thermal.hc*q0 + laser(i,j,k) ) / K;
541
542 if (temp(i,j,k) > Tcutoff)
543 {
544 exceeded_Tcutoff(i,j,k) = 1;
545 }
546
547 }
548
549 });
550
551 } // MFi For loop
552
553
554 //
555 // THERMAL TRANSPORT
556 //
557 if (thermal.on)
558 {
559 std::swap(temp_old_mf[lev], temp_mf[lev]);
560
561 for (amrex::MFIter mfi(*eta_mf[lev], true); mfi.isValid(); ++mfi)
562 {
563 const amrex::Box& bx = mfi.tilebox();
564
565 Set::Patch<Set::Scalar> tempnew = temp_mf.Patch(lev,mfi);
568
569 Set::Patch<Set::Scalar> temps = temps_mf.Patch(lev,mfi);
570
571
572 // Phase field
573 Set::Patch<Set::Scalar> etanew = (*eta_mf[lev]).array(mfi);
574 Set::Patch<const Set::Scalar> eta = (*eta_old_mf[lev]).array(mfi);
575 // Diagnostic fields
577
578 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
579 {
580 auto sten = Numeric::GetStencil(i, j, k, bx);
581 Set::Vector grad_eta = Numeric::Gradient(eta, i, j, k, 0, DX);
582 Set::Vector grad_temp = Numeric::Gradient(temp, i, j, k, 0, DX);
583 Set::Scalar lap_temp = Numeric::Laplacian(temp, i, j, k, 0, DX);
584 Set::Scalar grad_eta_mag = grad_eta.lpNorm<2>();
585 Set::Vector grad_alpha = Numeric::Gradient(alpha, i, j, k, 0, DX, sten);
586 Set::Scalar dTdt = 0.0;
587 dTdt += grad_eta.dot(grad_temp * alpha(i, j, k));
588 dTdt += grad_alpha.dot(eta(i, j, k) * grad_temp);
589 dTdt += eta(i, j, k) * alpha(i, j, k) * lap_temp;
590 dTdt += alpha(i, j, k) * heatflux(i, j, k) * grad_eta_mag;
591
592 Set::Scalar Tsolid = dTdt + temps(i, j, k) * (etanew(i, j, k) - eta(i, j, k)) / dt;
593 temps(i, j, k) = temps(i, j, k) + dt * Tsolid;
594 tempnew(i, j, k) = etanew(i, j, k) * temps(i, j, k) + (1.0 - etanew(i, j, k)) * thermal.Tfluid;
595 });
596 }
597 }
598
599} //Function
600
601
602void Flame::TagCellsForRefinement(int lev, amrex::TagBoxArray& a_tags, Set::Scalar time, int ngrow)
603{
604 BL_PROFILE("Integrator::Flame::TagCellsForRefinement");
606
607 const Set::Scalar* DX = geom[lev].CellSize();
608 Set::Scalar dr = sqrt(AMREX_D_TERM(DX[0] * DX[0], +DX[1] * DX[1], +DX[2] * DX[2]));
609
610 // Eta criterion for refinement
611 for (amrex::MFIter mfi(*eta_mf[lev], true); mfi.isValid(); ++mfi)
612 {
613 const amrex::Box& bx = mfi.tilebox();
614 amrex::Array4<char> const& tags = a_tags.array(mfi);
617
618 if (thermal.on) {
619 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
620 {
621 Set::Vector gradeta = Numeric::Gradient(eta, i, j, k, 0, DX);
622 if (gradeta.lpNorm<2>() * dr * 2 > m_refinement_criterion && eta(i, j, k) >= t_refinement_restriction && temp(i,j,k) > thermal.Tcutoff*0.9)
623 tags(i, j, k) = amrex::TagBox::SET;
624 });
625
626 } else {
627 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
628 {
629 Set::Vector gradeta = Numeric::Gradient(eta, i, j, k, 0, DX);
630 if (gradeta.lpNorm<2>() * dr * 2 > m_refinement_criterion && eta(i, j, k) >= t_refinement_restriction)
631 tags(i, j, k) = amrex::TagBox::SET;
632 });
633 }
634 }
635
636 // Phi criterion for refinement
637 if (elastic.phirefinement) {
638 for (amrex::MFIter mfi(*eta_mf[lev], true); mfi.isValid(); ++mfi)
639 {
640 const amrex::Box& bx = mfi.tilebox();
641 amrex::Array4<char> const& tags = a_tags.array(mfi);
643
644 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
645 {
646 Set::Vector gradphi = Numeric::Gradient(phi, i, j, k, 0, DX);
647 if (gradphi.lpNorm<2>() * dr >= phi_refinement_criterion)
648 tags(i, j, k) = amrex::TagBox::SET;
649 });
650 }
651 }
652
653
654 // Thermal criterion for refinement
655 if (thermal.on) {
656 for (amrex::MFIter mfi(*temp_mf[lev], true); mfi.isValid(); ++mfi)
657 {
658 const amrex::Box& bx = mfi.tilebox();
659 amrex::Array4<char> const& tags = a_tags.array(mfi);
662 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
663 {
664 Set::Vector tempgrad = Numeric::Gradient(temp, i, j, k, 0, DX);
665 if (tempgrad.lpNorm<2>() * dr > t_refinement_criterion && eta(i, j, k) >= t_refinement_restriction)
666 tags(i, j, k) = amrex::TagBox::SET;
667 });
668 }
669 }
670
671 // Refine at start
672 for (amrex::MFIter mfi(*eta_mf[lev], true); mfi.isValid(); ++mfi)
673 {
674 const amrex::Box& bx = mfi.tilebox();
675 amrex::Array4<char> const& tags = a_tags.array(mfi);
678
679 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
680 {
681 Set::Vector gradeta = Numeric::Gradient(eta, i, j, k, 0, DX);
682 Set::Vector gradphi = Numeric::Gradient(phi, i, j, k, 0, DX);
683 if ((gradeta.lpNorm<2>() * dr * 2 > m_refinement_criterion || gradphi.lpNorm<2>() * dr >= thermal.phi_refinement_criterion_inital) && time < thermal.end_initial_refine_time)
684 tags(i, j, k) = amrex::TagBox::SET;
685 });
686 }
687}
688
689void Flame::Regrid(int lev, Set::Scalar time)
690{
691 BL_PROFILE("Integrator::Flame::Regrid");
692
693 ic_phi->Initialize(lev, phi_mf, time);
694 ic_eta->Initialize(lev, eta_0_mf, time);
695
696 if (thermal.on) {
697 /*
698 This regrid function works by using the "has_exceeded_Tcutoff" field. If the temperature in a cell is greater than Tcutoff,
699 eta will change and when regridding won't use the initial eta field. If T < T_cutoff, when regriding happens it applies the inital
700 eta field condition. This gives at leat a 4x speed improvement in 2D when doing regression with voids. This is because orgionally
701 there was a bug where when regridding, the orgional eta field wouldn't be applied, so there would be "squares" of voids instead of
702 circles/spheres when using .xyzr files as the inital condition.
703 */
704 for (amrex::MFIter mfi(*eta_mf[lev], true); mfi.isValid(); ++mfi)
705 {
706 const amrex::Box &bx = mfi.tilebox();
707 Set::Patch<Set::Scalar> eta = eta_mf.Patch(lev, mfi);
710 Set::Patch<Set::Scalar> exceeded_Tcutoff = thermal.has_exceeded_Tcutoff.Patch(lev, mfi);
711
712 Set::Scalar Tcutoff = thermal.Tcutoff;
713
714 amrex::BoxList boxes_to_update;
715 if (lev == finest_level && prev_finest_level == finest_level)
716 boxes_to_update = amrex::complementIn(bx, prev_finest_ba).boxList();
717 else
718 boxes_to_update.push_back(bx);
719
720 for (const amrex::Box &box : boxes_to_update)
721 amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE(int i, int j, int k)
722 {
723
724 if (!exceeded_Tcutoff(i,j,k) && temp(i,j,k) < Tcutoff)
725 {
726 eta(i, j, k) = eta_0(i, j, k);
727 }
728 });
729 }
730
731 if (lev == finest_level)
732 {
733 prev_finest_ba = grids[finest_level];
734 prev_finest_level = finest_level;
735 }
736 }
737}
738
739void Flame::Integrate(int amrlev, Set::Scalar time, int /*step*/,
740 const amrex::MFIter& mfi, const amrex::Box& box)
741{
742 BL_PROFILE("Flame::Integrate");
743
745
746 const Set::Scalar* DX = geom[amrlev].CellSize();
747 Set::Scalar dv = AMREX_D_TERM(DX[0], *DX[1], *DX[2]);
750 if (variable_pressure) {
751 amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE(int i, int j, int k)
752 {
753 chamber.volume += eta(i, j, k, 0) * dv;
754 Set::Vector grad = Numeric::Gradient(eta, i, j, k, 0, DX);
755 Set::Scalar normgrad = grad.lpNorm<2>();
756 Set::Scalar da = normgrad * dv;
757 chamber.area += da;
758
759 Set::Vector mgrad = Numeric::Gradient(mdot, i, j, k, 0, DX);
760 Set::Scalar mnormgrad = mgrad.lpNorm<2>();
761 Set::Scalar dm = mnormgrad * dv;
762 chamber.massflux += dm;
763
764 });
765 }
766 else {
767 amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE(int i, int j, int k)
768 {
769 chamber.volume += eta(i, j, k, 0) * dv;
770 Set::Vector grad = Numeric::Gradient(eta, i, j, k, 0, DX);
771 Set::Scalar normgrad = grad.lpNorm<2>();
772 Set::Scalar da = normgrad * dv;
773 chamber.area += da;
774 });
775 }
776 // time dependent pressure data from experimenta -> p = 0.0954521220950523 * exp(15.289993148880678 * t)
777}
778} // namespace Integrator
#define pp_query_default(...)
Definition ParmParse.H:120
#define pp_queryclass(...)
Definition ParmParse.H:130
#define TEST(x)
Definition Util.H:25
#define INFO
Definition Util.H:24
Definition BMP.H:22
void Initialize(const int &a_lev, Set::Field< T > &a_field, Set::Scalar a_time=0.0)
Definition IC.H:39
Initialize Laminates in a matrix.
Definition Laminate.H:16
Definition PNG.H:26
void select_default(std::string name, PTRTYPE *&ic_eta, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1978
void queryclass(std::string name, T *value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1767
void forbid(std::string name, std::string explanation, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:301
int AnyUnusedInputs(bool inscopeonly=true, bool verbose=false)
Definition ParmParse.H:1702
static ForwardArgs< ForwardArgStorage< Args >... > forward_args(Args &&... args)
Definition ParmParse.H:153
int query_default(std::string name, T &value, T defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:492
static int AllUnusedInputs()
Definition ParmParse.H:1740
static bool InTraversalMode()
Definition ParmParse.cpp:14
int query_if(std::string name, Action &&action, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:817
void select(std::string name, PTRTYPE *&ic_eta, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1883
virtual void TimeStepBegin(Set::Scalar a_time, int a_step) override
Definition Mechanics.H:191
void Integrate(int amrlev, Set::Scalar, int, const amrex::MFIter &mfi, const amrex::Box &a_box) override
Definition Mechanics.H:418
void Initialize(int lev) override
Use the #ic object to initialize::Temp.
Definition Mechanics.H:171
void Advance(int lev, Set::Scalar time, Set::Scalar dt) override
Definition Mechanics.H:278
Solver::Nonlocal::Newton< MODEL > solver
Definition Mechanics.H:533
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, Set::Scalar, int) override
Definition Mechanics.H:477
Set::Field< Model::Solid::Finite::NeoHookeanPredeformed > model_mf
Definition Mechanics.H:501
Set::Scalar Tcutoff
Definition Flame.H:108
Model::Propellant::Propellant< Model::Propellant::PowerLaw, Model::Propellant::FullFeedback, Model::Propellant::Homogenize > propellant
Definition Flame.H:141
Set::Scalar volume
Definition Flame.H:129
Set::Scalar Telastic
Definition Flame.H:118
IC::IC< Set::Scalar > * ic_eta
Definition Flame.H:85
Set::Field< Set::Scalar > laser_mf
Definition Flame.H:73
Set::Field< Set::Scalar > alpha_mf
Definition Flame.H:70
amrex::BoxArray prev_finest_ba
Definition Flame.H:89
int prev_finest_level
Definition Flame.H:90
BC::BC< Set::Scalar > * bc_temp
Definition Flame.H:75
void UpdateModel(int a_step, Set::Scalar a_time) override
Definition Flame.cpp:312
Set::Scalar lambda
Definition Flame.H:96
Set::Scalar phi_refinement_criterion_inital
Definition Flame.H:110
Set::Scalar w1
Definition Flame.H:98
Set::Field< Set::Scalar > eta_0_mf
Definition Flame.H:65
Set::Field< Set::Scalar > phi_mf
Definition Flame.H:68
Set::Field< Set::Scalar > temp_old_mf
Definition Flame.H:60
struct Integrator::Flame::@2 pf
Set::Scalar small
Definition Flame.H:84
IC::IC< Set::Scalar > * ic_temp
Definition Flame.H:112
int variable_pressure
Definition Flame.H:87
Set::Scalar area
Definition Flame.H:130
void Regrid(int lev, Set::Scalar time) override
Definition Flame.cpp:689
Set::Scalar pressure
Definition Flame.H:133
model_type model_ap
Definition Flame.H:119
Set::Scalar w0
Definition Flame.H:98
void TimeStepComplete(Set::Scalar a_time, int a_iter) override
Definition Flame.cpp:416
static void Forbids(IO::ParmParse &pp)
Definition Flame.cpp:33
Set::Field< Set::Scalar > eta_mf
Definition Flame.H:63
Set::Scalar phi_refinement_criterion
Definition Flame.H:80
void TimeStepBegin(Set::Scalar a_time, int a_iter) override
Definition Flame.cpp:394
struct Integrator::Flame::@5 chamber
static void Parse(Flame &value, IO::ParmParse &pp)
Definition Flame.cpp:89
void Initialize(int lev) override
Definition Flame.cpp:278
Set::Scalar massflux
Definition Flame.H:131
Set::Scalar kappa
Definition Flame.H:97
Set::Scalar end_initial_refine_time
Definition Flame.H:109
Set::Scalar traction
Definition Flame.H:120
Set::Scalar Tref
Definition Flame.H:106
Set::Field< Set::Scalar > temps_mf
Definition Flame.H:61
void Advance(int lev, Set::Scalar time, Set::Scalar dt) override
Definition Flame.cpp:428
Set::Scalar t_refinement_restriction
Definition Flame.H:83
Set::Scalar t_refinement_criterion
Definition Flame.H:82
struct Integrator::Flame::@3 thermal
Set::Scalar etacutoff
Definition Flame.H:122
Set::Field< Set::Scalar > eta_old_mf
Definition Flame.H:64
Set::Scalar m_refinement_criterion
Definition Flame.H:81
Set::Scalar apply_chamber_pressure
Definition Flame.H:123
Set::Field< Set::Scalar > has_exceeded_Tcutoff
Definition Flame.H:111
Set::Scalar hc
Definition Flame.H:105
void Integrate(int amrlev, Set::Scalar time, int step, const amrex::MFIter &mfi, const amrex::Box &box) override
Definition Flame.cpp:739
model_type model_htpb
Definition Flame.H:119
Set::Scalar Tfluid
Definition Flame.H:107
BC::BC< Set::Scalar > * bc_eta
Definition Flame.H:76
int end_initial_refine
Definition Flame.H:91
IC::IC< Set::Scalar > * ic_laser
Definition Flame.H:78
void TagCellsForRefinement(int lev, amrex::TagBoxArray &tags, amrex::Real, int) override
Definition Flame.cpp:602
struct Integrator::Flame::@4 elastic
Set::Field< Set::Scalar > temp_mf
Definition Flame.H:59
Set::Scalar w12
Definition Flame.H:98
Set::Field< Set::Scalar > heatflux_mf
Definition Flame.H:71
bool plot_field
Definition Flame.H:86
Set::Field< Set::Scalar > mdot_mf
Definition Flame.H:66
IC::IC< Set::Scalar > * ic_phi
Definition Flame.H:77
Set::Scalar eps
Definition Flame.H:95
amrex::Real timestep
Timestep for the base level of refinement.
Definition Integrator.H:393
void RegisterNodalFab(Set::Field< Set::Scalar > &new_fab, int ncomp, int nghost, std::string name, bool writeout, bool evolving=true, std::vector< std::string > suffix={})
Add a new node-based scalar field.
void RegisterNewFab(Set::Field< Set::Scalar > &new_fab, BC::BC< Set::Scalar > *new_bc, int ncomp, int nghost, std::string name, bool writeout, bool evolving=true, std::vector< std::string > suffix={})
Add a new cell-based scalar field.
std::vector< amrex::Box > box
Definition Integrator.H:465
amrex::Vector< amrex::Real > dt
Timesteps for each level of refinement.
Definition Integrator.H:394
void RegisterIntegratedVariable(Set::Scalar *integrated_variable, std::string name, bool extensive=true)
Register a variable to be integrated over the spatial domain using the Integrate function.
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Set::Scalar get_cp(const Set::Scalar phi)
Definition Propellant.H:78
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Set::Scalar get_qdot(const Set::Scalar mdot, const Set::Scalar phi)
Definition Propellant.H:91
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE void set_pressure(Set::Scalar P)
Definition Propellant.H:40
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Set::Scalar get_L(const Set::Scalar phi, const Set::Scalar T)
Definition Propellant.H:104
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Set::Scalar get_rho(const Set::Scalar phi)
Definition Propellant.H:65
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Set::Scalar get_K(const Set::Scalar phi)
Definition Propellant.H:52
amrex::Array4< Set::Scalar > Patch(const int lev, const amrex::MFIter &mfi) const &
Definition Set.H:263
amrex::Array4< T > Patch(int lev, amrex::MFIter &mfi) const &
Definition Set.H:76
void setPsi(Set::Field< Set::Scalar > &a_psi)
Definition Newton.H:124
Collection of numerical integrator objects.
Definition AllenCahn.H:43
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Set::Vector CellGradientOnNode(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k, const int &m, const Set::Scalar dx[AMREX_SPACEDIM])
Definition Stencil.H:705
static AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE std::array< StencilType, AMREX_SPACEDIM > GetStencil(const int i, const int j, const int k, const amrex::Box domain)
Definition Stencil.H:51
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Set::Vector Gradient(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k, const int &m, const Set::Scalar dx[AMREX_SPACEDIM], std::array< StencilType, AMREX_SPACEDIM > stencil=DefaultType())
Definition Stencil.H:687
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Set::Scalar Laplacian(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k, const int &m, const Set::Scalar dx[AMREX_SPACEDIM], std::array< StencilType, AMREX_SPACEDIM > stencil=DefaultType())
Definition Stencil.H:561
amrex::Real Scalar
Definition Base.H:19
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:21
AMREX_FORCE_INLINE void AssertException(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition Util.H:265
void Warning(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:213
void Message(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:140
void Exception(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:237
AMREX_FORCE_INLINE void RealFillBoundary(amrex::FabArray< amrex::BaseFab< T > > &a_mf, const amrex::Geometry &, const int nghost=2)
Definition Util.H:350
static AMREX_FORCE_INLINE T NodeToCellAverage(const amrex::Array4< const T > &f, const int &i, const int &j, const int &k, const int &m)
Definition Stencil.H:1483
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE T CellToNodeAverage(const amrex::Array4< const T > &f, const int &i, const int &j, const int &k, const int &m, std::array< StencilType, AMREX_SPACEDIM > stencil=DefaultType())
Definition Stencil.H:1445
static Unit Area()
Definition Unit.H:209
static Unit Energy()
Definition Unit.H:218
static Unit Time()
Definition Unit.H:199
static Unit Temperature()
Definition Unit.H:201
static Unit Pressure()
Definition Unit.H:217
static Unit Power()
Definition Unit.H:219
static Unit Length()
Definition Unit.H:198
static Unit Less()
Definition Unit.H:197