|
| 1 | +//===----------------------------------------------------------------------===// |
| 2 | +// |
| 3 | +// See the LICENSE file for license and copyright information |
| 4 | +// SPDX-License-Identifier: NCSA AND BSD-3-Clause |
| 5 | +// |
| 6 | +//===----------------------------------------------------------------------===// |
| 7 | +/// |
| 8 | +/// @file |
| 9 | +/// define fill_field_vals |
| 10 | +/// |
| 11 | +//===----------------------------------------------------------------------===// |
| 12 | +#ifndef GRTESTUTILS_FILL_FIELD_VALS_HPP |
| 13 | +#define GRTESTUTILS_FILL_FIELD_VALS_HPP |
| 14 | + |
| 15 | +#include "GrackleCtxPack.hpp" |
| 16 | +#include "grackle.h" |
| 17 | +#include "status_reporting.h" |
| 18 | +#include "./field_container.hpp" |
| 19 | +#include "./field_info_detail.hpp" |
| 20 | +#include "./status.hpp" |
| 21 | + |
| 22 | +#include <optional> |
| 23 | +#include <string_view> |
| 24 | +#include <vector> |
| 25 | + |
| 26 | +namespace grtest { |
| 27 | + |
| 28 | +/// Fill in the values of @p fc by repeating the values from @p field_tile |
| 29 | +/// |
| 30 | +/// @param[in, out] fc The field container that will be filled |
| 31 | +/// @param[in] field_tile Specifies the values to use |
| 32 | +template <class Tile> |
| 33 | +Status fill_field_vals(FieldContainer& fc, const Tile& field_tile) { |
| 34 | + // access field grid index properties |
| 35 | + int rank = fc.rank(); |
| 36 | + int ix_start = fc.get_ptr()->grid_start[0]; |
| 37 | + int ix_stop = fc.get_ptr()->grid_end[0] + 1; |
| 38 | + int iy_start = (rank >= 2) ? fc.get_ptr()->grid_start[1] : 0; |
| 39 | + int iy_stop = (rank >= 2) ? fc.get_ptr()->grid_end[1] + 1 : 1; |
| 40 | + int iz_start = (rank == 3) ? fc.get_ptr()->grid_start[2] : 0; |
| 41 | + int iz_stop = (rank == 3) ? fc.get_ptr()->grid_end[2] + 1 : 1; |
| 42 | + |
| 43 | + int mx = fc.get_ptr()->grid_dimension[0]; |
| 44 | + int my = (rank >= 2) ? fc.get_ptr()->grid_dimension[1] : 1; |
| 45 | + |
| 46 | + int n_x_vals = ix_stop - ix_start; |
| 47 | + |
| 48 | + // access properties about the tile |
| 49 | + int tile_len = field_tile.get_n_vals(); |
| 50 | + |
| 51 | + // a few error consistency checks |
| 52 | + if (tile_len <= 0) { |
| 53 | + return error::Adhoc("tile_len must be positive"); |
| 54 | + } else if (tile_len > n_x_vals) { |
| 55 | + // we may want to revisit this in the future |
| 56 | + return error::Adhoc("tile_len can't exceed length of contiguous axis"); |
| 57 | + } |
| 58 | + |
| 59 | + // allocate the buffer |
| 60 | + std::vector<gr_float> tile_buf(tile_len); |
| 61 | + |
| 62 | + for (auto [field_name, field_ptr] : fc) { |
| 63 | + if (!field_tile.fill_buf(tile_buf.data(), field_name)) { |
| 64 | + return error::Adhoc("field_tile doesn't recognize field name: " + |
| 65 | + field_name); |
| 66 | + } |
| 67 | + |
| 68 | + for (int iz = iz_start; iz < iz_stop; iz++) { |
| 69 | + for (int iy = iy_start; iy < iy_stop; iy++) { |
| 70 | + for (int ix = ix_start; ix < ix_stop; ix++) { |
| 71 | + int i = ix + mx * (iy + my * iz); |
| 72 | + field_ptr[i] = tile_buf[ix % tile_len]; |
| 73 | + } |
| 74 | + } |
| 75 | + } |
| 76 | + } |
| 77 | + |
| 78 | + return OkStatus(); |
| 79 | +} |
| 80 | + |
| 81 | +/// Represents a very simplistic set of conditions |
| 82 | +struct SimpleFieldTile { |
| 83 | + double mfrac_metal; |
| 84 | + double mfrac_H; |
| 85 | + double mfrac_He; |
| 86 | + double mfrac_D; |
| 87 | + |
| 88 | + // both of these are in code-units |
| 89 | + double common_density; |
| 90 | + double common_eint; |
| 91 | + |
| 92 | + int get_n_vals() const noexcept { return 1; } |
| 93 | + |
| 94 | + bool fill_buf(gr_float* buf, std::string_view field_name) const noexcept { |
| 95 | + if (field_name == "density") { |
| 96 | + buf[0] = common_density; |
| 97 | + } else if (field_name == "internal_energy") { |
| 98 | + buf[0] = common_eint; |
| 99 | + } else if (field_name == "metal_density") { |
| 100 | + buf[0] = mfrac_metal * common_density; |
| 101 | + } else if (field_name == "HI_density") { |
| 102 | + buf[0] = mfrac_H * common_density; |
| 103 | + } else if (field_name == "HeI_density") { |
| 104 | + buf[0] = mfrac_He * common_density; |
| 105 | + } else if (field_name == "DI_density") { |
| 106 | + buf[0] = mfrac_D * common_density; |
| 107 | + } else { |
| 108 | + field_detail::Kind kind = field_detail::Kind::UNSET; |
| 109 | + std::optional<field_detail::FieldInfo> maybe_field_info = |
| 110 | + field_detail::query_field_info(field_name); |
| 111 | + if (maybe_field_info.has_value()) { |
| 112 | + kind = maybe_field_info->kind; |
| 113 | + } |
| 114 | + |
| 115 | + if (kind == field_detail::Kind::ELEMENTWISE_SOLVER_ARG) { |
| 116 | + buf[0] = 0.0; |
| 117 | + } else if (kind == field_detail::Kind::PRIMORDIAL_SPECIES) { |
| 118 | + gr_float tiny_number = 1.e-20; |
| 119 | + buf[0] = tiny_number * common_density; |
| 120 | + } else { |
| 121 | + return false; |
| 122 | + } |
| 123 | + } |
| 124 | + return true; |
| 125 | + } |
| 126 | +}; |
| 127 | + |
| 128 | +inline SimpleFieldTile make_simple_tile(const GrackleCtxPack& ctx_pack, |
| 129 | + code_units units, double metallicity) { |
| 130 | + GR_INTERNAL_REQUIRE(ctx_pack.is_initialized(), "ctx_pack was initialized"); |
| 131 | + |
| 132 | + const chemistry_data* my_chem = ctx_pack.my_chemistry(); |
| 133 | + |
| 134 | + // the internal energy roughly corresponds to 1000 K |
| 135 | + double common_eint = 1000.0 / get_temperature_units(&units); |
| 136 | + |
| 137 | + return SimpleFieldTile{ |
| 138 | + /* mfrac_metal = */ metallicity * my_chem->SolarMetalFractionByMass, |
| 139 | + /* mfrac_H = */ my_chem->HydrogenFractionByMass, |
| 140 | + /* mfrac_He = */ (1.0 - my_chem->HydrogenFractionByMass), |
| 141 | + /* mfrac_D = */ 2.0 * 3.4e-5, |
| 142 | + |
| 143 | + // both of these are in code-units |
| 144 | + /* common_density = */ 1.0, |
| 145 | + /* common_eint = */ common_eint}; |
| 146 | +} |
| 147 | + |
| 148 | +} // namespace grtest |
| 149 | + |
| 150 | +#endif // GRTESTUTILS_SET_FIELD_CONDITIONS_HPP |
0 commit comments