Skip to content

Commit dfb8f5e

Browse files
committed
Introduce support for using cosmology with VL+CT solver (without bfields)
Strictly speaking, this only required 2 minor tweaks to EnzoMethodMHDVlct: - modify the compatability checking of EnzoMethodMHDVlct::post_init_checks_ related to using the VL+CT solver with cosmology. - modify all usage of the cell widths in EnzoMethodMHDVlct::compute (which would have defaulted to the cell width in the comoving frame) to instead use the proper cell width. As part of this commit, occurences of the variables named `cell_width` in the relevant code (i.e. paths executed by EnzoMethodMHDVlct::compute) were renamed so that they are called `proper_cell_width`. The docstrings of these functions were also updated accordingly.
1 parent 325e5e8 commit dfb8f5e

6 files changed

+104
-52
lines changed

src/Enzo/enzo_EnzoIntegrationQuanUpdate.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,12 @@ void EnzoIntegrationQuanUpdate::clear_dUcons_map
101101
//----------------------------------------------------------------------
102102

103103
void EnzoIntegrationQuanUpdate::accumulate_flux_component
104-
(int dim, double dt, enzo_float cell_width, const EnzoEFltArrayMap &flux_map,
105-
EnzoEFltArrayMap &dUcons_map, int stale_depth,
106-
const str_vec_t &passive_list) const noexcept
104+
(int dim, double dt, enzo_float proper_cell_width,
105+
const EnzoEFltArrayMap &flux_map, EnzoEFltArrayMap &dUcons_map,
106+
int stale_depth, const str_vec_t &passive_list) const noexcept
107107
{
108108
EnzoPermutedCoordinates coord(dim);
109-
enzo_float dtdx_i = dt/cell_width;
109+
enzo_float dtdx_i = dt/proper_cell_width;
110110

111111
auto accumulate = [dtdx_i,stale_depth,coord,
112112
&flux_map,&dUcons_map](const std::string& key)

src/Enzo/enzo_EnzoIntegrationQuanUpdate.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ class EnzoIntegrationQuanUpdate : public PUP::able
6666
/// @param[in] dim The dimension along which to compute the flux
6767
/// divergence.
6868
/// @param[in] dt The current timestep.
69-
/// @param[in] cell_width The cell width along dimension `dim`.
69+
/// @param[in] proper_cell_width The cell width along dimension `dim`.
70+
/// This should always be a proper distance (even in cosmological sims).
7071
/// @param[in] flux_map Map of arrays holding the fluxes computed for
7172
/// the current timestep. The values of these fields should be stored
7273
/// on the cell faces along the `dim` dimension.
@@ -77,7 +78,12 @@ class EnzoIntegrationQuanUpdate : public PUP::able
7778
/// call. This should match the stale depth at the time the fluxes were
7879
/// computed.
7980
/// @param[in] passive_list A list of keys for passive scalars.
80-
void accumulate_flux_component(int dim, double dt, enzo_float cell_width,
81+
///
82+
/// @note
83+
/// By always using the cell width measured in the proper frame, this is
84+
/// compatible with both cosmological and non-cosmological simulations.
85+
void accumulate_flux_component(int dim, double dt,
86+
enzo_float proper_cell_width,
8187
const EnzoEFltArrayMap &flux_map,
8288
EnzoEFltArrayMap &dUcons_map, int stale_depth,
8389
const str_vec_t &passive_list) const noexcept;

src/Enzo/enzo_EnzoMethodMHDVlct.cpp

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,8 @@ EnzoVlctScratchSpace* EnzoMethodMHDVlct::get_scratch_ptr_
246246
//----------------------------------------------------------------------
247247

248248
void EnzoMethodMHDVlct::save_fluxes_for_corrections_
249-
(Block * block, const EnzoEFltArrayMap &flux_map, int dim, double cell_width,
250-
double dt) const noexcept
249+
(Block * block, const EnzoEFltArrayMap &flux_map, int dim,
250+
double proper_cell_width, double dt) const noexcept
251251
{
252252

253253
Field field = block->data()->field();
@@ -259,7 +259,7 @@ void EnzoMethodMHDVlct::save_fluxes_for_corrections_
259259
int gx, gy, gz;
260260
field.ghost_depth(density_field_id, &gx, &gy, &gz);
261261

262-
double dt_dxi = dt/cell_width;
262+
double dt_dxi = dt/proper_cell_width;
263263

264264
FluxData * flux_data = block->data()->flux_data();
265265
const int nf = flux_data->num_fields();
@@ -415,9 +415,24 @@ void EnzoMethodMHDVlct::compute ( Block * block) throw()
415415
bfield_method_->register_target_block(block);
416416
}
417417

418-
const enzo_float* const cell_widths = enzo::block(block)->CellWidth;
419-
420-
double dt = block->dt();
418+
const double dt = block->dt();
419+
420+
// compute the proper_cell_widths (independent of whether we're using
421+
// comoving coordinates or not). For a pure hydro simulation, this is all
422+
// we need to do to be compatible with cosmology. Cosmology is not
423+
// currently supported with magnetic fields (an error is raised elsewhere).
424+
// - In the future we might want to compute different values of cosmo_a for
425+
// the partial and the full timestep
426+
double cosmo_a = 1.0;
427+
if (enzo::cosmology() != nullptr) {
428+
double cosmo_dadt = 0.0;
429+
enzo::cosmology()->compute_expansion_factor
430+
(&cosmo_a, &cosmo_dadt, block->time() + 0.5*dt);
431+
}
432+
const std::array<enzo_float,3> proper_cell_widths =
433+
{enzo::block(block)->CellWidth[0] * cosmo_a,
434+
enzo::block(block)->CellWidth[1] * cosmo_a,
435+
enzo::block(block)->CellWidth[2] * cosmo_a};
421436

422437
// stale_depth indicates the number of field entries from the outermost
423438
// field value that the region including "stale" values (need to be
@@ -426,7 +441,7 @@ void EnzoMethodMHDVlct::compute ( Block * block) throw()
426441

427442
// repeat the following loop twice (for half time-step and full time-step)
428443
for (int i=0;i<2;i++){
429-
double cur_dt = (i == 0) ? dt/2. : dt;
444+
const double cur_dt = (i == 0) ? dt/2. : dt;
430445
EnzoEFltArrayMap& cur_integration_map =
431446
(i == 0) ? external_integration_map : temp_integration_map;
432447
EnzoEFltArrayMap& out_integration_map =
@@ -480,7 +495,7 @@ void EnzoMethodMHDVlct::compute ( Block * block) throw()
480495
interface_vel_arr_ptr = nullptr;
481496
}
482497

483-
compute_flux_(dim, cur_dt, cell_widths[dim], primitive_map,
498+
compute_flux_(dim, cur_dt, proper_cell_widths[dim], primitive_map,
484499
pl_map, pr_map, *(flux_maps[dim]), dUcons_map,
485500
interface_vel_arr_ptr, *reconstructor, bfield_method_,
486501
stale_depth, passive_list);
@@ -492,11 +507,11 @@ void EnzoMethodMHDVlct::compute ( Block * block) throw()
492507
// different if using SMR/AMR. This means that the internal energy
493508
// source terms won't be fully self-consistent along the edges. This
494509
// same effect is also present in the Ppm Solver
495-
save_fluxes_for_corrections_(block, xflux_map, 0, cell_widths[0],
510+
save_fluxes_for_corrections_(block, xflux_map, 0, proper_cell_widths[0],
496511
cur_dt);
497-
save_fluxes_for_corrections_(block, yflux_map, 1, cell_widths[1],
512+
save_fluxes_for_corrections_(block, yflux_map, 1, proper_cell_widths[1],
498513
cur_dt);
499-
save_fluxes_for_corrections_(block, zflux_map, 2, cell_widths[2],
514+
save_fluxes_for_corrections_(block, zflux_map, 2, proper_cell_widths[2],
500515
cur_dt);
501516
}
502517

@@ -540,12 +555,18 @@ void EnzoMethodMHDVlct::compute ( Block * block) throw()
540555

541556
void EnzoMethodMHDVlct::post_init_checks_() const noexcept
542557
{
543-
ASSERT("EnzoMethodMHDVlct::post_init_checks_",
544-
"This solver isn't currently compatible with cosmological sims",
545-
enzo::cosmology() == nullptr);
546-
547558
const Problem* problem = enzo::problem();
548559

560+
if (enzo::cosmology() != nullptr){
561+
ASSERT("EnzoMethodMHDVlct::post_init_checks_",
562+
("This solver isn't currently compatible with cosmological sims "
563+
"when using bfields"), mhd_choice_ == bfield_choice::no_bfield);
564+
ASSERT("EnzoMethodMHDVlct::post_init_checks_",
565+
"when using cosmology, this method MUST precede the "
566+
"comoving_expansion method",
567+
problem->method_precedes("mhd_vlct","comoving_expansion"));
568+
}
569+
549570
// problems would arise relating to particle-mesh deposition (relating to
550571
// particle drift before deposition) and in cosmological simulations if the
551572
// the VL+CT method were to precede the gravity method.
@@ -574,7 +595,7 @@ void EnzoMethodMHDVlct::post_init_checks_() const noexcept
574595
//----------------------------------------------------------------------
575596

576597
void EnzoMethodMHDVlct::compute_flux_
577-
(const int dim, const double cur_dt, const enzo_float cell_width,
598+
(const int dim, const double cur_dt, const enzo_float proper_cell_width,
578599
EnzoEFltArrayMap &primitive_map,
579600
EnzoEFltArrayMap &priml_map, EnzoEFltArrayMap &primr_map,
580601
EnzoEFltArrayMap &flux_map, EnzoEFltArrayMap &dUcons_map,
@@ -609,7 +630,8 @@ void EnzoMethodMHDVlct::compute_flux_
609630
// from the fluxes and use these values to update dUcons_map (which is used
610631
// to accumulate the total change in these quantities over the current
611632
// [partial] timestep)
612-
integration_quan_updater_->accumulate_flux_component(dim, cur_dt, cell_width,
633+
integration_quan_updater_->accumulate_flux_component(dim, cur_dt,
634+
proper_cell_width,
613635
flux_map, dUcons_map,
614636
cur_stale_depth,
615637
passive_list);
@@ -618,7 +640,7 @@ void EnzoMethodMHDVlct::compute_flux_
618640
// energy source term for this dim (and update dUcons_map).
619641
if (eos_->uses_dual_energy_formalism()){
620642
EnzoSourceInternalEnergy eint_src;
621-
eint_src.calculate_source(dim, cur_dt, cell_width, primitive_map,
643+
eint_src.calculate_source(dim, cur_dt, proper_cell_width, primitive_map,
622644
dUcons_map, *interface_velocity_arr_ptr, eos_,
623645
cur_stale_depth);
624646
}

src/Enzo/enzo_EnzoMethodMHDVlct.hpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
/// - bfield (both integration and primitive)
3434
/// When using the dual energy formalism there is also:
3535
/// - internal_energy (just integration)
36+
/// - When using comoving coordinates, the integration and primitives are
37+
/// all defined in the comoving frame. Source terms related to comoving
38+
/// expansion are all handled externally by `EnzoMethodComovingExpansion`
3639
///
3740
/// EnzoEFltArrayMap Objects
3841
/// ------------------------
@@ -172,13 +175,16 @@ class EnzoMethodMHDVlct : public Method {
172175
///
173176
/// If using the dual energy formalism, this also computes a part of the
174177
/// internal energy density source term,
175-
/// `dt * pressure * (dvx/dx + dvy/dy + dvz/dz)`
176-
/// (`vx`, `vy`, `vz` are velocity components & scale factor dependence is
177-
/// omitted), and adds it to the 'internal_energy' entry in `dUcons_map`.
178-
/// More specifically, it handles the dimensionally split part of the term
179-
/// involving the derivative along `dim`. The velocity component along `dim`
180-
/// at the cell-interfaces (estimated by the Riemann Solver) to compute the
181-
/// derivatives.
178+
/// `dt * pressure * (dvx/dx + dvy/dy + dvz/dz)`. In detail, this computes
179+
/// - `-dt * pressure * dvx/dx`, when `dim == 0`
180+
/// - `-dt * pressure * dvy/dy`, when `dim == 1`
181+
/// - `-dt * pressure * dvz/dz`, when `dim == 2`
182+
/// and adds the results to the 'internal_energy' entry in `dUcons_map`. This
183+
/// estimates the velocity derivative using the velocity component along
184+
/// `dim` at the cell-interfaces (estimated by the Riemann Solver) and the
185+
/// `proper_cell_width`. This is valid for both cosmological and
186+
/// non-cosmological simulations. In cosmological simulations, the other
187+
/// cosmological expansion term is handled in a separate `Method` object.
182188
///
183189
/// This function should NOT be modified to directly compute any other source
184190
/// terms unless they similarly have dependence on dimensional quantites
@@ -188,7 +194,8 @@ class EnzoMethodMHDVlct : public Method {
188194
/// @param[in] dim Dimension along which to compute fluxes. Values of 0,
189195
/// 1, and 2 correspond to the x, y, and z directions, respectively.
190196
/// @param[in] dt The current timestep.
191-
/// @param[in] cell_width The cell width along dimension `dim`.
197+
/// @param[in] proper_cell_width The cell width along dimension `dim`.
198+
/// This should always be a proper distance (even in cosmological sims).
192199
/// @param[in] primitive_map Map of arrays holding cell-centered
193200
/// primitive quantities that are to be reconstructed (This includes
194201
/// specific passive scalars).
@@ -219,7 +226,7 @@ class EnzoMethodMHDVlct : public Method {
219226
/// performing reconstruction)
220227
/// @param[in] passive_list A list of keys for passively advected scalars.
221228
void compute_flux_
222-
(const int dim, const double cur_dt, const enzo_float cell_width,
229+
(const int dim, const double cur_dt, const enzo_float proper_cell_width,
223230
EnzoEFltArrayMap &primitive_map,
224231
EnzoEFltArrayMap &priml_map, EnzoEFltArrayMap &primr_map,
225232
EnzoEFltArrayMap &flux_map, EnzoEFltArrayMap &dUcons_map,
@@ -283,11 +290,12 @@ class EnzoMethodMHDVlct : public Method {
283290
/// @param[in] dim indicates the dimension that the fluxes in `flux_map`
284291
/// were computed along. Values of 0, 1, and 2 correspond to the x, y,
285292
/// and z directions, respectively.
286-
/// @param[in] cell_width is the width of a cell along the dimension `dim`
293+
/// @param[in] proper_cell_width The cell width along dimension `dim`. This
294+
/// should always be a proper distance (even in cosmological sims).
287295
/// @param[in] dt is the value of the current timestep
288296
void save_fluxes_for_corrections_
289-
(Block * block, const EnzoEFltArrayMap &flux_map, int dim, double cell_width,
290-
double dt) const noexcept;
297+
(Block * block, const EnzoEFltArrayMap &flux_map, int dim,
298+
double proper_cell_width, double dt) const noexcept;
291299

292300
/// Returns a pointer to the scratch space struct. If the scratch space has
293301
/// not already been allocated, it will be allocated now.

src/Enzo/enzo_EnzoSourceInternalEnergy.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//----------------------------------------------------------------------
1212

1313
void EnzoSourceInternalEnergy::calculate_source
14-
(const int dim, const double dt, const enzo_float cell_width,
14+
(const int dim, const double dt, const enzo_float proper_cell_width,
1515
const EnzoEFltArrayMap &prim_map, EnzoEFltArrayMap &dUcons_map,
1616
const CelloArray<const enzo_float,3> &interface_velocity,
1717
const EnzoEquationOfState *eos,
@@ -26,7 +26,7 @@ void EnzoSourceInternalEnergy::calculate_source
2626
"The EOS can't be barotropic and use the dual energy formalism.",
2727
!(eos->is_barotropic()) );
2828

29-
const enzo_float dtdx = dt/cell_width;
29+
const enzo_float dtdx = dt/proper_cell_width;
3030

3131
EnzoPermutedCoordinates coord(dim);
3232

@@ -37,9 +37,10 @@ void EnzoSourceInternalEnergy::calculate_source
3737
//
3838
// Note - deint_dens holds the accumulated change in the internal energy
3939
// density over the current time-step
40-
// - we compute pressure from the cell-centered density ane specific
41-
// internal from the start of the time-step (adopting convention from
42-
// flux_hll.F - we also could just use the precomputed field)
40+
// - we compute pressure from the cell-centered density and specific
41+
// internal energy that are taken from the start of the time-step
42+
// (if we adopted the convention from flux_hll.F, we could
43+
// alternatively use the precomputed pressure field)
4344

4445
CSlice full_ax(nullptr, nullptr);
4546

src/Enzo/enzo_EnzoSourceInternalEnergy.hpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,32 @@ class EnzoSourceInternalEnergy
3434
/// @brief [\ref Enzo] Encapsulates the calculation of the internal energy
3535
/// source term along a given dimension.
3636
///
37-
/// The source term in question for the internal energy density is formally
38-
/// defined as follows. We define the jth component of the interface velocity
39-
/// as vbar and grid width along this dimension as dx. For all cell
40-
/// locations (i,j,k) there is a source term, over a timestep dt, of:
41-
/// -1 * dt* pressure_j * (vbar_{j+1/2} - vbar_{j+1/2}) / (a * dx_j)
42-
/// a corresponding term is added for each dimension (although this
43-
/// implementation only handles a single dimension at a time).
37+
/// For convenience, we split the encapsulated source term up by into 3
38+
/// pieces; one for each dimension (this class needs to be called separately
39+
/// for each dimension). We define the portion of the source term for the ith
40+
/// dimension that get's applied at every cell locations as:
41+
/// @code{.unparsed}
42+
/// -1 * dt * pressure[i] * (vbar[i+1/2] - vbar[i-1/2]) / (a * cellwidth_i)
43+
/// @endcode
44+
/// In the above equation:
45+
/// * the bracketted variables indicate the relative positions of variables
46+
/// on the grid along the ith dimension (values of `i` map to a
47+
/// cell-centered position). You can assume that the omitted indices
48+
/// along the other dimensions are always cell-centered.
49+
/// * `vbar` is the ith component of the velocity at the cell interface
50+
/// * `a` is the current scale-factor.
51+
/// * `cellwidth_i` is the comoving cell width along the ith dimension. In
52+
/// practice, this calculation always expects to be passed the proper
53+
/// cell-width, which is always equal to `a * cellwidth_i`.
4454
///
45-
/// As in Enzo's PPM method, the cell-centerred pressure is computed from the
55+
/// This source-term is compatible with both non-cosmological and
56+
/// cosmological simulations. In cosmological calculations the internal
57+
/// energy density has another source term, but that get's handled separately
58+
/// by `EnzoMethodComovingExpansion`.
59+
///
60+
/// As in Enzo's PPM method, the cell-centered pressure is computed from the
4661
/// internal energy (although the internal energy and total energy should
4762
/// have been synchronized at the start of the timestep)
48-
///
49-
/// The current implementation ignores the scale factor.
5063

5164
public:
5265

@@ -58,6 +71,8 @@ class EnzoSourceInternalEnergy
5871
/// internal Energy source term. Values of 0, 1, and 2 correspond to the
5972
/// the x, y, and z directions, respectively.
6073
/// @param[in] dt The time time-step overwhich to apply the source term
74+
/// @param[in] proper_cell_width The cell width along dimension `dim`. This
75+
/// should always be a proper distance (even in cosmological sims).
6176
/// @param[in] prim_map Map holding the values of the cell-centered
6277
/// primitives from the start of the (partial) timestep (but after the
6378
/// synchronization of the internal energy with the total energy).
@@ -80,7 +95,7 @@ class EnzoSourceInternalEnergy
8095
/// reconstructor's delayed_staling_rate should be applied at some
8196
/// time after this function call.
8297
void calculate_source(const int dim, const double dt,
83-
const enzo_float cell_width,
98+
const enzo_float proper_cell_width,
8499
const EnzoEFltArrayMap &prim_map,
85100
EnzoEFltArrayMap &dUcons_map,
86101
const CelloArray<const enzo_float,3> &interface_velocity,

0 commit comments

Comments
 (0)