18 std::vector<double> get_normal_random_vector(
unsigned int length,
19 unsigned int n_rejected_draws,
20 double mean,
double stddev,
23 ASSERT(stddev >= 0.,
"Internal Error");
25 std::mt19937 pseudorandom_number_generator;
26 std::normal_distribution<> normal_dist_generator(mean, stddev);
27 for (
unsigned int i = 0; i < n_rejected_draws; ++i)
29 normal_dist_generator(pseudorandom_number_generator);
32 std::vector<double> output_vector(length);
33 for (
unsigned int i = 0; i < length; ++i)
40 output_vector[i] = normal_dist_generator(pseudorandom_number_generator);
42 if (verbose && output_vector[i] < 0.)
44 std::cout <<
"Random value rejected because it was negative: "
45 << output_vector[i] << std::endl;
48 }
while (output_vector[i] < 0.);
57 std::vector<boost::property_tree::ptree>
const &database_ensemble,
58 MPI_Comm global_communicator)
65 std::vector<std::vector<std::vector<double>>> diameter_depth_ensemble;
66 for (
auto const &database : database_ensemble)
68 std::vector<std::vector<double>> diameter_depth_beams;
69 boost::property_tree::ptree
const &source_database =
70 database.get_child(
"sources");
72 unsigned int const n_beams = source_database.get<
unsigned int>(
"n_beams");
73 for (
unsigned int i = 0; i < n_beams; ++i)
75 boost::property_tree::ptree
const &beam_database =
76 source_database.get_child(
"beam_" + std::to_string(i));
79 std::string type = beam_database.get<std::string>(
"type");
83 double diameter = beam_database.get<
double>(
"diameter");
85 double depth = beam_database.get<
double>(
"diameter");
86 diameter_depth_beams.push_back({diameter, depth});
89 diameter_depth_ensemble.push_back(diameter_depth_beams);
93 auto all_diameter_depth = dealii::Utilities::MPI::all_gather(
94 global_communicator, diameter_depth_ensemble);
97 std::vector<double> diameter_max(diameter_depth_ensemble[0].size(), -1.);
98 std::vector<double> depth_max(diameter_depth_ensemble[0].size(), -1.);
99 for (
auto const &diameter_depth_rank : all_diameter_depth)
101 for (
unsigned int member = 0; member < diameter_depth_rank.size(); ++member)
103 for (
unsigned int beam = 0; beam < diameter_depth_rank[member].size();
106 if (diameter_depth_rank[member][beam][0] > diameter_max[beam])
108 diameter_max[beam] = diameter_depth_rank[member][beam][0];
110 if (diameter_depth_rank[member][beam][1] > depth_max[beam])
112 depth_max[beam] = diameter_depth_rank[member][beam][1];
119 boost::optional<boost::property_tree::ptree const &> units_optional_database =
120 database_ensemble[0].get_child_optional(
"units");
123 boost::property_tree::ptree
const &source_database =
124 database_ensemble[0].get_child(
"sources");
126 unsigned int const n_beams = source_database.get<
unsigned int>(
"n_beams");
127 std::vector<std::shared_ptr<HeatSource<dim>>> bounding_heat_sources(n_beams);
128 unsigned int bounding_source = 0;
129 for (
unsigned int i = 0; i < n_beams; ++i)
131 boost::property_tree::ptree
const &beam_database =
132 source_database.get_child(
"beam_" + std::to_string(i));
135 std::string type = beam_database.get<std::string>(
"type");
136 if (type ==
"goldak")
138 boost::property_tree::ptree modified_beam_database = beam_database;
139 modified_beam_database.put(
"diameter", diameter_max[bounding_source]);
140 modified_beam_database.put(
"depth", depth_max[bounding_source]);
143 bounding_heat_sources[i] = std::make_shared<GoldakHeatSource<dim>>(
144 modified_beam_database, units_optional_database);
146 else if (type ==
"electron_beam")
148 boost::property_tree::ptree modified_beam_database = beam_database;
149 modified_beam_database.put(
"diameter", diameter_max[bounding_source]);
150 modified_beam_database.put(
"depth", depth_max[bounding_source]);
153 bounding_heat_sources[i] = std::make_shared<ElectronBeamHeatSource<dim>>(
154 modified_beam_database, units_optional_database);
156 else if (type ==
"cube")
158 bounding_heat_sources[i] = std::make_shared<CubeHeatSource<dim>>(
159 beam_database, units_optional_database);
163 return bounding_heat_sources;
166 void traverse(boost::property_tree::ptree
const &ensemble_ptree,
167 std::vector<boost::property_tree::ptree> &database_ensemble,
168 std::vector<std::string> &keys,
unsigned int &n_rejected_draws,
169 unsigned int local_ensemble_size,
170 unsigned int global_ensemble_size, std::string
const &path =
"")
172 for (
auto const &[key, child] : ensemble_ptree)
174 std::string full_path = path.empty() ? key : path +
"." + key;
180 if ((full_path ==
"ensemble_simulation") ||
181 (full_path ==
"ensemble_size"))
186 double stddev = database_ensemble[0].get<
double>(
"ensemble." + full_path);
188 full_path.erase(full_path.length() - 7);
189 double mean = database_ensemble[0].get<
double>(full_path);
191 std::vector<double> values = get_normal_random_vector(
192 local_ensemble_size, n_rejected_draws, mean, stddev,
193 database_ensemble[0].get(
"verbose_output",
false));
194 n_rejected_draws += global_ensemble_size;
197 keys.push_back(full_path);
200 for (
unsigned int member = 0; member < local_ensemble_size; ++member)
202 database_ensemble[member].put(full_path, values[member]);
207 traverse(child, database_ensemble, keys, n_rejected_draws,
208 local_ensemble_size, global_ensemble_size, full_path);
214 boost::property_tree::ptree
const &database, MPI_Comm local_communicator,
215 unsigned int first_local_member,
unsigned int local_ensemble_size,
216 unsigned int global_ensemble_size)
218 std::vector<boost::property_tree::ptree> database_ensemble(
219 local_ensemble_size, database);
224 std::vector<std::string> keys;
227 unsigned int n_rejected_draws = first_local_member;
228 traverse(database.get_child(
"ensemble"), database_ensemble, keys,
229 n_rejected_draws, local_ensemble_size, global_ensemble_size);
231 catch (boost::property_tree::ptree_bad_path &exception)
233 std::cerr << std::endl;
234 std::cerr <<
"Aborting in ensemble management." << std::endl;
235 std::cerr <<
"Error: " << exception.what() << std::endl << std::endl;
236 std::cerr <<
"There is a problem with the input file." << std::endl;
237 std::cerr <<
"Make sure that the keys in ensemble match" << std::endl;
238 std::cerr <<
"the keys in the rest of the input file." << std::endl;
239 std::cerr <<
"Note the keys must have been set explicitly" << std::endl;
240 std::cerr <<
"even if they normally have a default value." << std::endl;
241 std::cerr << std::endl;
246 if (dealii::Utilities::MPI::this_mpi_process(local_communicator) == 0)
248 for (
unsigned int member = 0; member < local_ensemble_size; ++member)
250 std::string output_dir =
251 database.get<std::string>(
"post_processor.output_dir",
"");
252 std::string member_data_filename =
254 database.get<std::string>(
"post_processor.filename_prefix") +
"_m" +
255 std::to_string(first_local_member + member) +
"_data.txt";
256 std::ofstream file(member_data_filename);
257 for (
auto const &k : keys)
259 file << k <<
": " << database_ensemble[member].get<
double>(k) <<
"\n";
264 return database_ensemble;
272 std::vector<boost::property_tree::ptree>
const &property_trees,
273 MPI_Comm global_communicator);
275 std::vector<boost::property_tree::ptree>
const &property_trees,
276 MPI_Comm global_communicator);
void traverse(boost::property_tree::ptree const &ensemble_ptree, std::vector< boost::property_tree::ptree > &database_ensemble, std::vector< std::string > &keys, unsigned int &n_rejected_draws, unsigned int local_ensemble_size, unsigned int global_ensemble_size, std::string const &path="")
std::vector< boost::property_tree::ptree > create_database_ensemble(boost::property_tree::ptree const &database, MPI_Comm local_communicator, unsigned int first_local_member, unsigned int local_ensemble_size, unsigned int global_ensemble_size)
std::vector< std::shared_ptr< HeatSource< dim > > > get_bounding_heat_sources(std::vector< boost::property_tree::ptree > const &database_ensemble, MPI_Comm global_communicator)
#define ASSERT(condition, message)