8 #include <deal.II/arborx/bvh.h>
9 #include <deal.II/grid/filtered_iterator.h>
11 #include <boost/algorithm/string.hpp>
20 std::tuple<std::vector<dealii::BoundingBox<dim>>, std::vector<double>,
21 std::vector<double>, std::vector<double>>
23 boost::property_tree::ptree
const &geometry_database,
27 bool material_deposition =
28 geometry_database.get(
"material_deposition",
false);
30 if (!material_deposition)
31 return {{}, {}, {}, {}};
34 geometry_database.get<std::string>(
"material_deposition_method");
38 return read_material_deposition<dim>(geometry_database);
43 std::tuple<std::vector<dealii::BoundingBox<dim>>, std::vector<double>,
44 std::vector<double>, std::vector<double>>>
46 for (
auto const &source : heat_sources)
48 deposition_paths.emplace_back(deposition_along_scan_path<dim>(
49 geometry_database, source->get_scan_path()));
52 return merge_deposition_paths<dim>(deposition_paths);
57 std::tuple<std::vector<dealii::BoundingBox<dim>>, std::vector<double>,
58 std::vector<double>, std::vector<double>>
62 std::string material_deposition_filename =
63 geometry_database.get<std::string>(
"material_deposition_file");
65 std::vector<dealii::BoundingBox<dim>> material_deposition_boxes;
66 std::vector<double> material_deposition_times;
67 std::vector<double> material_deposition_cos;
68 std::vector<double> material_deposition_sin;
72 "Waiting for material deposition file: " +
73 material_deposition_filename);
75 file.open(material_deposition_filename);
78 int dim_ = std::stoi(
line);
79 ASSERT_THROW(dim_ == dim,
"Dimension in " + material_deposition_filename +
80 " does not match " + std::to_string(dim) +
82 while (getline(file,
line))
84 std::vector<std::string> split_line;
85 boost::split(split_line,
line, boost::is_any_of(
" "),
86 boost::token_compress_on);
88 std::vector<double> center(dim);
89 for (
int d = 0; d < dim; ++d)
91 center[d] = std::stod(split_line[d]);
94 std::vector<double> box_size(dim);
95 for (
int d = 0; d < dim; ++d)
97 box_size[d] = std::stod(split_line[dim + d]);
100 material_deposition_times.push_back(std::stod(split_line[2 * dim]));
102 unsigned int times_size = material_deposition_times.size();
104 ASSERT_THROW(material_deposition_times[times_size - 2] <=
105 material_deposition_times[times_size - 1],
106 "Time stamp not increasing.");
108 double deposition_angle = std::stod(split_line[2 * dim + 1]);
109 material_deposition_cos.push_back(std::cos(deposition_angle));
110 material_deposition_sin.push_back(std::sin(deposition_angle));
113 dealii::Point<dim> bounding_pt_a;
114 dealii::Point<dim> bounding_pt_b;
115 for (
int d = 0; d < dim; ++d)
117 bounding_pt_a[d] = center[d] - 0.5 * box_size[d];
118 bounding_pt_b[d] = center[d] + 0.5 * box_size[d];
120 material_deposition_boxes.emplace_back(
121 std::make_pair(bounding_pt_a, bounding_pt_b));
125 return std::make_tuple(material_deposition_boxes, material_deposition_times,
126 material_deposition_cos, material_deposition_sin);
130 std::tuple<std::vector<dealii::BoundingBox<dim>>, std::vector<double>,
131 std::vector<double>, std::vector<double>>
135 std::tuple<std::vector<dealii::BoundingBox<dim>>, std::vector<double>,
136 std::vector<double>, std::vector<double>>
138 int constexpr tuple_box = 0;
139 int constexpr tuple_time = 1;
140 int constexpr tuple_cos = 2;
141 int constexpr tuple_sin = 3;
146 double deposition_length = geometry_database.get<
double>(
"deposition_length");
148 double deposition_height = geometry_database.get<
double>(
"deposition_height");
150 double deposition_width =
151 geometry_database.get<
double>(
"deposition_width", 0.0);
154 double lead_time = geometry_database.get<
double>(
"deposition_lead_time");
158 double segment_start_time = 0.0;
159 Quaternion segment_start_rotation = segment_list.at(0).end_rotation;
160 dealii::Point<3> segment_start_point = segment_list.at(0).end_point;
161 dealii::Point<3> build_ref_segment_start_point =
163 ? segment_start_rotation.
inv_rotate(segment_start_point)
164 : segment_start_point;
168 double const eps = 1.0e-10;
169 double const eps_time = 1.0e-10;
170 if (segment.power_modifier > eps)
172 Quaternion segment_end_rotation = segment.end_rotation;
173 dealii::Point<3> segment_end_point = segment.end_point;
174 dealii::Point<3> build_ref_segment_end_point =
176 ? segment_end_rotation.
inv_rotate(segment_end_point)
178 double const segment_length =
179 segment_end_point.distance(segment_start_point);
180 bool in_segment =
true;
181 dealii::Point<3> center = build_ref_segment_start_point;
182 double const segment_velocity =
183 segment_length / (segment.end_time - segment_start_time);
189 ? (segment_end_point[0] - segment_start_point[0]) / segment_length
193 ? (segment_end_point[1] - segment_start_point[1]) / segment_length
195 double next_box_length = deposition_length;
199 double distance_to_box_center =
200 center.distance(build_ref_segment_start_point);
201 double time_to_box_center =
202 segment_velocity != 0. ? distance_to_box_center / segment_velocity
205 dealii::Point<dim> bounding_pt_a;
206 dealii::Point<dim> bounding_pt_b;
208 if (segment_end_rotation.
is_valid())
210 if constexpr (dim == 3)
212 double x_length = std::abs(cos) * next_box_length +
213 std::abs(sin) * deposition_width;
214 double y_length = std::abs(cos) * deposition_width +
215 std::abs(sin) * next_box_length;
217 dealii::Point<3> max_corner(x_length / 2., y_length / 2., 0.);
218 dealii::Point<3> min_corner(-x_length / 2., -y_length / 2.,
222 dealii::Point<3> rotated_max_corner =
223 segment_end_rotation.
rotate(max_corner);
224 dealii::Point<3> rotated_min_corner =
225 segment_end_rotation.
rotate(min_corner);
228 dealii::Point<3> new_max_corner;
229 dealii::Point<3> new_min_corner;
230 for (
int d = 0; d < 3; ++d)
233 std::max(rotated_max_corner[d], rotated_min_corner[d]);
235 std::min(rotated_max_corner[d], rotated_min_corner[d]);
238 bounding_pt_a = center + new_min_corner;
239 bounding_pt_b = center + new_max_corner;
248 std::vector<double> box_size(dim);
251 if constexpr (dim == 2)
257 box_size.at(
axis<dim>::x) = std::abs(cos) * next_box_length +
258 std::abs(sin) * deposition_width;
259 box_size.at(
axis<dim>::y) = std::abs(cos) * deposition_width +
260 std::abs(sin) * next_box_length;
263 for (
int d = 0; d < dim - 1; ++d)
265 bounding_pt_a[d] = center[d] - 0.5 * box_size[d];
266 bounding_pt_b[d] = center[d] + 0.5 * box_size[d];
268 bounding_pt_a[dim - 1] = center[dim - 1] - box_size[dim - 1];
269 bounding_pt_b[dim - 1] = center[dim - 1];
272 std::get<tuple_box>(deposition_path)
273 .push_back(std::make_pair(bounding_pt_a, bounding_pt_b));
274 std::get<tuple_time>(deposition_path)
276 segment_start_time + time_to_box_center - lead_time, eps_time));
277 std::get<tuple_cos>(deposition_path).push_back(cos);
278 std::get<tuple_sin>(deposition_path).push_back(sin);
281 if (distance_to_box_center + eps > segment_length)
289 double center_increment = deposition_length;
290 if (distance_to_box_center + deposition_length > segment_length)
292 center_increment = (segment_length - distance_to_box_center);
293 next_box_length = segment_length - distance_to_box_center;
296 if (segment_end_rotation.
is_valid())
298 if constexpr (dim == 3)
300 dealii::Point<3> incr_direction = build_ref_segment_end_point;
301 incr_direction -= center;
302 incr_direction /= incr_direction.norm();
303 dealii::Point<3> incr = center_increment * incr_direction;
309 center[0] += cos * center_increment;
310 center[1] += sin * center_increment;
315 segment_start_point = segment.end_point;
316 segment_start_time = segment.end_time;
317 segment_start_rotation = segment.end_rotation;
318 build_ref_segment_start_point =
320 ? segment_start_rotation.
inv_rotate(segment_start_point)
321 : segment_start_point;
323 return deposition_path;
327 std::tuple<std::vector<dealii::BoundingBox<dim>>, std::vector<double>,
328 std::vector<double>, std::vector<double>>
330 std::vector<std::tuple<std::vector<dealii::BoundingBox<dim>>,
331 std::vector<double>, std::vector<double>,
332 std::vector<double>>>
const &deposition_paths)
335 std::vector<dealii::BoundingBox<dim>> bounding_boxes;
336 std::vector<double> time;
337 std::vector<double> cos;
338 std::vector<double> sin;
339 for (
auto const &path : deposition_paths)
341 bounding_boxes.insert(bounding_boxes.end(), std::get<0>(path).begin(),
342 std::get<0>(path).end());
343 time.insert(time.end(), std::get<1>(path).begin(), std::get<1>(path).end());
344 cos.insert(cos.end(), std::get<2>(path).begin(), std::get<2>(path).end());
345 sin.insert(sin.end(), std::get<3>(path).begin(), std::get<3>(path).end());
349 unsigned int const n_boxes = bounding_boxes.size();
350 std::vector<int> permutation(n_boxes);
351 std::iota(permutation.begin(), permutation.end(), 0);
352 std::sort(permutation.begin(), permutation.end(),
353 [&](
int const &i,
int const &j) { return time[i] < time[j]; });
358 std::vector<dealii::BoundingBox<dim>> permutated_bounding_boxes(n_boxes);
359 std::vector<double> permutated_time(n_boxes);
360 std::vector<double> permutated_cos(n_boxes);
361 std::vector<double> permutated_sin(n_boxes);
362 for (
unsigned int i = 0; i < n_boxes; ++i)
364 permutated_bounding_boxes[i] = bounding_boxes[permutation[i]];
365 permutated_time[i] = time[permutation[i]];
366 permutated_cos[i] = cos[permutation[i]];
367 permutated_sin[i] = sin[permutation[i]];
370 return std::make_tuple(permutated_bounding_boxes, permutated_time,
371 permutated_cos, permutated_sin);
375 std::vector<std::vector<typename dealii::DoFHandler<dim>::active_cell_iterator>>
378 dealii::DoFHandler<dim>
const &dof_handler,
379 std::vector<dealii::BoundingBox<dim>>
const &material_deposition_boxes)
382 if (material_deposition_boxes.size() == 0)
384 std::vector<typename dealii::DoFHandler<dim>::active_cell_iterator>>();
388 std::vector<dealii::BoundingBox<dim>> bounding_boxes;
389 std::vector<typename dealii::DoFHandler<dim>::active_cell_iterator>
391 #if ARBORX_VERSION_MAJOR >= 2
392 if (geometry.use_stl())
394 for (
auto const &cell : dealii::filter_iterators(
395 dof_handler.active_cell_iterators(),
396 dealii::IteratorFilters::LocallyOwnedCell(),
397 dealii::IteratorFilters::ActiveFEIndexEqualTo(1)))
399 if (geometry.is_within_stl(cell))
401 bounding_boxes.push_back(cell->bounding_box());
402 cell_iterators.push_back(cell);
409 for (
auto const &cell : dealii::filter_iterators(
410 dof_handler.active_cell_iterators(),
411 dealii::IteratorFilters::LocallyOwnedCell(),
412 dealii::IteratorFilters::ActiveFEIndexEqualTo(1)))
414 bounding_boxes.push_back(cell->bounding_box());
415 cell_iterators.push_back(cell);
420 dealii::ArborXWrappers::BVH bvh(bounding_boxes);
421 dealii::ArborXWrappers::BoundingBoxIntersectPredicate bb_intersect(
422 material_deposition_boxes);
423 auto [indices, offset] = bvh.query(bb_intersect);
425 unsigned int const n_queries = material_deposition_boxes.size();
427 std::vector<typename dealii::DoFHandler<dim>::active_cell_iterator>>
428 elements_to_activate(n_queries);
429 for (
unsigned int i = 0; i < n_queries; ++i)
431 for (
int j = offset[i]; j < offset[i + 1]; ++j)
433 elements_to_activate[i].push_back(cell_iterators[indices[j]]);
437 return elements_to_activate;
444 template std::tuple<std::vector<dealii::BoundingBox<2>>, std::vector<double>,
445 std::vector<double>, std::vector<double>>
447 boost::property_tree::ptree
const &geometry_database,
449 template std::tuple<std::vector<dealii::BoundingBox<3>>, std::vector<double>,
450 std::vector<double>, std::vector<double>>
452 boost::property_tree::ptree
const &geometry_database,
455 template std::tuple<std::vector<dealii::BoundingBox<2>>, std::vector<double>,
456 std::vector<double>, std::vector<double>>
458 template std::tuple<std::vector<dealii::BoundingBox<3>>, std::vector<double>,
459 std::vector<double>, std::vector<double>>
462 template std::vector<
463 std::vector<typename dealii::DoFHandler<2>::active_cell_iterator>>
465 Geometry<2> const &geometry, dealii::DoFHandler<2>
const &dof_handler,
466 std::vector<dealii::BoundingBox<2>>
const &material_deposition_boxes);
467 template std::vector<
468 std::vector<typename dealii::DoFHandler<3>::active_cell_iterator>>
470 Geometry<3> const &geometry, dealii::DoFHandler<3>
const &dof_handler,
471 std::vector<dealii::BoundingBox<3>>
const &material_deposition_boxes);
473 template std::tuple<std::vector<dealii::BoundingBox<2, double>>,
474 std::vector<double>, std::vector<double>,
477 std::vector<std::tuple<std::vector<dealii::BoundingBox<2, double>>,
478 std::vector<double>, std::vector<double>,
479 std::vector<double>>>
const &deposition_paths);
480 template std::tuple<std::vector<dealii::BoundingBox<3, double>>,
481 std::vector<double>, std::vector<double>,
484 std::vector<std::tuple<std::vector<dealii::BoundingBox<3, double>>,
485 std::vector<double>, std::vector<double>,
486 std::vector<double>>>
const &deposition_paths);
488 template std::tuple<std::vector<dealii::BoundingBox<2>>, std::vector<double>,
489 std::vector<double>, std::vector<double>>
492 template std::tuple<std::vector<dealii::BoundingBox<3>>, std::vector<double>,
493 std::vector<double>, std::vector<double>>
dealii::Point< 3, double > rotate(dealii::Point< 3, double > const &point) const
dealii::Point< 3, double > inv_rotate(dealii::Point< 3, double > const &point) const
std::vector< ScanPathSegment > get_segment_list() const
bool is_five_axis() const
std::tuple< std::vector< dealii::BoundingBox< dim > >, std::vector< double >, std::vector< double >, std::vector< double > > deposition_along_scan_path(boost::property_tree::ptree const &geometry_database, ScanPath const &scan_path)
void ASSERT_THROW_NOT_IMPLEMENTED()
void wait_for_file(std::string const &filename, std::string const &message)
std::tuple< std::vector< dealii::BoundingBox< dim > >, std::vector< double >, std::vector< double >, std::vector< double > > create_material_deposition_boxes(boost::property_tree::ptree const &geometry_database, std::vector< std::shared_ptr< HeatSource< dim >>> &heat_sources)
std::tuple< std::vector< dealii::BoundingBox< dim > >, std::vector< double >, std::vector< double >, std::vector< double > > merge_deposition_paths(std::vector< std::tuple< std::vector< dealii::BoundingBox< dim >>, std::vector< double >, std::vector< double >, std::vector< double >>> const &deposition_paths)
std::tuple< std::vector< dealii::BoundingBox< dim > >, std::vector< double >, std::vector< double >, std::vector< double > > read_material_deposition(boost::property_tree::ptree const &geometry_database)
std::vector< std::vector< typename dealii::DoFHandler< dim >::active_cell_iterator > > get_elements_to_activate([[maybe_unused]] Geometry< dim > const &geometry, dealii::DoFHandler< dim > const &dof_handler, std::vector< dealii::BoundingBox< dim >> const &material_deposition_boxes)
void ASSERT_THROW(bool cond, std::string const &message)