/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/discretization/mesh/configuration_mesh.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/discretization/mesh/configuration_mesh.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
configuration_mesh.hh
Go to the documentation of this file.
1#pragma once
4#include <cmath>
5#include <stdexcept>
6#include <string>
7#include <vector>
8
9// fmt::format instead of std::format: libstdc++ ships <format> only from GCC
10// 13, and spdlog's fmt is bundled anyway -- this keeps GCC 12 viable.
11#include <spdlog/fmt/fmt.h>
12
13namespace DiFfRG
14{
15
16 namespace Config
17 {
18
19 namespace internal
20 {
21 inline std::vector<std::string> string_to_substrings_array(const std::string str)
22 {
23 std::vector<std::string> array;
24 std::istringstream ss(str);
25 std::string buf;
26 while (std::getline(ss, buf, ','))
27 array.push_back(buf);
28 return array;
29 }
30 inline std::array<double, 3> string_to_range(const std::string str)
31 {
32 std::vector<double> vec;
33 std::istringstream ss(str);
34 std::string buf;
35 while (std::getline(ss, buf, ':'))
36 vec.push_back(std::stod(buf));
37 if (vec.size() != 3) throw std::runtime_error(str + " is not a range");
38
39 std::array<double, 3> arr;
40 std::copy_n(vec.begin(), 3, arr.begin());
41 return arr;
42 }
43 } // namespace internal
44
46 {
47 public:
48 GridAxis() = delete;
49 GridAxis(double min_, double step_, double max_) : min(min_), max(max_), step(step_) { validate(); };
50
51 GridAxis(std::string json_string)
52 {
53 auto subrange = internal::string_to_range(json_string);
54 min = subrange[0];
55 step = subrange[1];
56 max = subrange[2];
57
58 validate();
59 };
60
61 static std::string get_default_range() { return "0:1e-4:7e-3,7e-3:5e-4:9e-3,9e-3:1e-3:1.1e-2"; }
62
63 double min;
64 double max;
65 double step;
66
76 std::vector<double> get_stepwiths(const bool origin_cell_centered = false, const uint refinement = 0) const
77 {
78 if (origin_cell_centered) {
79 if (!is_close(min, 0.0))
80 throw std::invalid_argument(
81 "Origin-centered rectangular meshes require every configured axis to start at zero.");
82
83 const double refinement_factor = std::ldexp(1.0, refinement);
84 auto steps = static_cast<uint>((max - min) / step);
85 double local_step;
86 do {
87 ++steps;
88 local_step = max / (static_cast<double>(steps) - 0.5 / refinement_factor);
89 } while (!(local_step < step));
90
91 return std::vector<double>(steps, local_step);
92 }
93
94 double local_step = step;
95 auto steps = static_cast<uint>((max - min) / local_step);
96 if (!is_close((min + local_step * steps), max)) {
97 local_step = (max - min) / (steps + 1);
98 ++steps;
99 }
100 return std::vector<double>(steps, local_step);
101 }
102
103 private:
104 void validate()
105 {
106 bool condition = (min < max) && (0.0 < step) && (step <= (max - min));
107 if (!condition) {
108 throw std::runtime_error(fmt::format(
109 "invalid range: min={}, step={}, max={} (require min < max and 0 < step <= max-min)", min, step, max));
110 }
111 }
112 };
113 namespace internal
114 {
115 inline void check_ranges_consistency(const std::vector<GridAxis> &ranges)
116 {
117 for (uint i = 1; i < ranges.size(); ++i)
118 if (!is_close(ranges[i].min, ranges[i - 1].max))
119 throw std::runtime_error("Your range definition is inconsistent!");
120 }
121
122 template <typename T, typename J> void append_range(T &to_append, const J &range)
123 {
124 for (const auto &element : range) {
125 to_append.push_back(element);
126 }
127 }
128 } // namespace internal
129
130 template <int dim> class ConfigurationMesh
131 {
132 public:
134 dealii::Point<dim, double> lower_left;
135 dealii::Point<dim, double> upper_right;
136 std::vector<std::vector<double>> step_sizes = std::vector<std::vector<double>>(dim);
137 };
138
140
141 template <typename... Grids> ConfigurationMesh(unsigned int refinement, Grids... grids_args) : refine(refinement)
142 {
143 static_assert(sizeof...(Grids) == dim, "Number of grids must match dimension");
144 static_assert((std::is_same_v<std::vector<GridAxis>, Grids> && ...),
145 "All grids must be of type std::vector<GridAxis>");
146 grids = {grids_args...};
147 }
148
150 {
151 static_assert(dim >= 1 && dim <= 3, "ConfigurationMesh only supports dim = 1, 2, 3");
152
153 const std::array<std::string, 3> grid_names = {"/discretization/grid/x_grid", "/discretization/grid/y_grid",
154 "/discretization/grid/z_grid"};
155
156 for (int i = 0; i < dim; ++i) {
157 auto subranges = internal::string_to_substrings_array(config.get_string_or_warn(grid_names[i], "0:0.1:1"));
158 for (const auto &subrange_str : subranges)
159 grids[i].emplace_back(subrange_str);
161 }
162
163 refine = config.get_uint("/discretization/grid/refine", 0);
164 }
165
166 static std::string get_defaults()
167 {
168 std::string json_str = R"({
169 "discretization": {
170 "grid": {
171 "x_grid": ")";
172 json_str += GridAxis::get_default_range();
173 json_str += R"(")";
174
175 if constexpr (dim >= 2) {
176 json_str += R"(,
177 "y_grid": ")";
178 json_str += GridAxis::get_default_range();
179 json_str += R"(")";
180 }
181
182 if constexpr (dim >= 3) {
183 json_str += R"(,
184 "z_grid": ")";
185 json_str += GridAxis::get_default_range();
186 json_str += R"(")";
187 }
188
189 json_str += R"(,
190 "refine": 0
191 }
192 }
193})";
194 return json_str;
195 }
196
203 inline TriangulationData get_triangulation_data(const bool origin_cell_centered = false) const
204 {
206 for (int i = 0; i < dim; ++i) {
207 data.lower_left[i] = grids[i].front().min;
208 data.upper_right[i] = grids[i].back().max;
209 for (std::size_t subrange = 0; subrange < grids[i].size(); ++subrange) {
210 const bool center_first_subrange = origin_cell_centered && subrange == 0;
211 internal::append_range(data.step_sizes[i], grids[i][subrange].get_stepwiths(center_first_subrange, refine));
212 }
213 }
214
215 if (!origin_cell_centered) return data;
216
217 const double refinement_factor = std::ldexp(1.0, refine);
218 for (int axis = 0; axis < dim; ++axis) {
219 data.lower_left[axis] = -data.step_sizes[axis].front() / (2.0 * refinement_factor);
220 }
221
222 return data;
223 }
224
225 inline std::vector<std::vector<double>> get_step_withs_for_triangulation() const
226 {
228 }
229
230 inline dealii::Point<dim, double> get_lower_left() const { return get_triangulation_data().lower_left; }
231
232 inline dealii::Point<dim, double> get_upper_right() const { return get_triangulation_data().upper_right; }
233
234 std::array<std::vector<GridAxis>, dim> grids;
236 };
237
238 } // namespace Config
239} // namespace DiFfRG
A hierarchical configuration tree, readable from JSON and TOML files.
Definition config_tree.hh:32
Definition configuration_mesh.hh:131
ConfigurationMesh(unsigned int refinement, Grids... grids_args)
Definition configuration_mesh.hh:141
ConfigurationMesh(const DiFfRG::ConfigTree &config)
Definition configuration_mesh.hh:149
dealii::Point< dim, double > get_lower_left() const
Definition configuration_mesh.hh:230
dealii::Point< dim, double > get_upper_right() const
Definition configuration_mesh.hh:232
uint refine
Definition configuration_mesh.hh:235
TriangulationData get_triangulation_data(const bool origin_cell_centered=false) const
Definition configuration_mesh.hh:203
std::array< std::vector< GridAxis >, dim > grids
Definition configuration_mesh.hh:234
static std::string get_defaults()
Definition configuration_mesh.hh:166
std::vector< std::vector< double > > get_step_withs_for_triangulation() const
Definition configuration_mesh.hh:225
Definition configuration_mesh.hh:46
GridAxis(double min_, double step_, double max_)
Definition configuration_mesh.hh:49
GridAxis(std::string json_string)
Definition configuration_mesh.hh:51
double min
Definition configuration_mesh.hh:63
static std::string get_default_range()
Definition configuration_mesh.hh:61
std::vector< double > get_stepwiths(const bool origin_cell_centered=false, const uint refinement=0) const
Definition configuration_mesh.hh:76
void validate()
Definition configuration_mesh.hh:104
double max
Definition configuration_mesh.hh:64
double step
Definition configuration_mesh.hh:65
void append_range(T &to_append, const J &range)
Definition configuration_mesh.hh:122
std::array< double, 3 > string_to_range(const std::string str)
Definition configuration_mesh.hh:30
void check_ranges_consistency(const std::vector< GridAxis > &ranges)
Definition configuration_mesh.hh:115
std::vector< std::string > string_to_substrings_array(const std::string str)
Definition configuration_mesh.hh:21
Definition complex_math.hh:10
@ config
/discretization/threads.
unsigned int uint
Definition utils.hh:24
bool KOKKOS_INLINE_FUNCTION is_close(T1 a, T2 b, T3 eps_)
Function to evaluate whether two floats are equal to numerical precision. Tests for both relative and...
Definition math.hh:177
Definition configuration_mesh.hh:133
dealii::Point< dim, double > lower_left
Definition configuration_mesh.hh:134
dealii::Point< dim, double > upper_right
Definition configuration_mesh.hh:135
std::vector< std::vector< double > > step_sizes
Definition configuration_mesh.hh:136