1#ifndef TATOOINE_FIELDS_AUTONOMOUS_PARTICLE_H
2#define TATOOINE_FIELDS_AUTONOMOUS_PARTICLE_H
23 requires range<
decltype(B::radii)>;
24 requires range<
decltype(B::offsets)>;
29template <
floating_po
int Real, std::
size_t NumDimensions>
41 constexpr static auto half = 1 / Real(2);
72 std::uint64_t
m_id = std::numeric_limits<std::uint64_t>::max();
75 static auto m = std::mutex{};
95 std::uint64_t
const id)
100 std::atomic_uint64_t &uuid_generator)
111 std::atomic_uint64_t &uuid_generator)
115 std::uint64_t
const id)
120 std::atomic_uint64_t &uuid_generator)
130 std::atomic_uint64_t &uuid_generator)
137 std::uint64_t
const id)
146 std::atomic_uint64_t &uuid_generator)
159 auto x0() const -> auto const & {
return m_x0; }
160 auto x0(std::size_t i)
const {
return x0()(i); }
166 auto t() ->
auto & {
return m_t; }
174 for (std::size_t i = 0; i < NumDimensions; ++i) {
175 eig_vals(i) = gcem::sqrt(eig_vals(i));
177 return eig_vecs * diag(eig_vals) *
transposed(eig_vecs);
328 template <split_behavior SplitBehavior,
typename Flowmap>
331 std::atomic_uint64_t &uuid_generator)
const {
332 using namespace detail::autonomous_particle;
333 auto hierarchy_mutex = std::mutex{};
335 auto [advected_particles, advected_simple_particles] =
336 advect<SplitBehavior>(std::forward<Flowmap>(phi), stepwidth, t_end,
337 {*
this}, hierarchy_pairs, hierarchy_mutex,
346 return std::tuple{std::move(advected_particles),
347 std::move(advected_simple_particles), std::move(edges)};
351 template <
typename Flowmap>
354 std::atomic_uint64_t &uuid_generator)
const {
355 return advect<typename split_behaviors::two_splits>(
356 std::forward<Flowmap>(phi), stepwidth, t_end, uuid_generator);
360 template <
typename Flowmap>
363 std::atomic_uint64_t &uuid_generator)
const {
364 return advect<typename split_behaviors::three_splits>(
365 std::forward<Flowmap>(phi), stepwidth, t_end, uuid_generator);
369 template <
typename Flowmap>
372 std::atomic_uint64_t &uuid_generator)
const {
373 return advect<typename split_behaviors::three_and_four_splits>(
374 std::forward<Flowmap>(phi), stepwidth, t_end, uuid_generator);
378 template <
typename Flowmap>
381 std::atomic_uint64_t &uuid_generator)
const {
382 return advect<typename split_behaviors::five_splits>(
383 std::forward<Flowmap>(phi), stepwidth, t_end, uuid_generator);
387 template <
typename Flowmap>
390 std::atomic_uint64_t &uuid_generator)
const {
391 return advect<typename split_behaviors::seven_splits>(
392 std::forward<Flowmap>(phi), stepwidth, t_end, uuid_generator);
404 template <split_behavior SplitBehavior,
typename Flowmap>
408 std::atomic_uint64_t &uuid_generator) {
409 using namespace detail::autonomous_particle;
411 auto hierarchy_mutex = std::mutex{};
412 auto hierarchy_pairs = std::vector<hierarchy_pair>{};
417 auto [advected_particles, advected_simple_particles] =
418 advect<SplitBehavior>(std::forward<Flowmap>(phi), stepwidth, t_end,
419 initial_particles, hierarchy_pairs,
420 hierarchy_mutex, uuid_generator);
423 auto map = std::unordered_map<
425 for (
auto const &p : advected_particles) {
426 map[p.id()] = edges.insert_vertex(p.center());
447 return std::tuple{std::move(advected_particles),
448 std::move(advected_simple_particles), std::move(edges)};
451 template <
typename Flowmap>
455 std::atomic_uint64_t &uuid_generator) {
456 return advect<typename split_behaviors::two_splits>(
457 std::forward<Flowmap>(phi), stepwidth, t_end, initial_particles,
461 template <
typename Flowmap>
465 std::atomic_uint64_t &uuid_generator) {
466 return advect<typename split_behaviors::three_splits>(
467 std::forward<Flowmap>(phi), stepwidth, t_end, initial_particles,
471 template <
typename Flowmap>
476 std::atomic_uint64_t &uuid_generator) {
477 return advect<typename split_behaviors::three_and_four_splits>(
478 std::forward<Flowmap>(phi), stepwidth, t_end, initial_particles,
482 template <
typename Flowmap>
486 std::atomic_uint64_t &uuid_generator) {
487 return advect<typename split_behaviors::five_splits>(
488 std::forward<Flowmap>(phi), stepwidth, t_end, initial_particles,
492 template <
typename Flowmap>
496 std::atomic_uint64_t &uuid_generator) {
497 return advect<typename split_behaviors::seven_splits>(
498 std::forward<Flowmap>(phi), stepwidth, t_end, initial_particles,
505 std::atomic_uint64_t &uuid_generator) {
513 std::atomic_uint64_t &uuid_generator) {
515 auto initial_particle_distribution = g.copy_without_properties();
516 for (std::size_t i = 0; i < NumDimensions; ++i) {
517 auto const spacing = initial_particle_distribution.dimension(i).spacing();
518 initial_particle_distribution.dimension(i).pop_front();
519 initial_particle_distribution.dimension(i).front() -= spacing / 2;
520 initial_particle_distribution.dimension(i).back() -= spacing / 2;
522 initial_particle_distribution.vertices().iterate_indices(
523 [&](
auto const... is) {
524 particles.emplace_back(
525 initial_particle_distribution.vertex_at(is...), t0,
526 initial_particle_distribution.dimension(0).spacing() / 2,
535 std::atomic_uint64_t &uuid_generator) {
544 std::atomic_uint64_t &uuid_generator) {
546 auto initial_particle_distribution = g.copy_without_properties();
548 initial_particle_distribution.dimension(0).spacing() / 2;
549 for (std::size_t i = 0; i < NumDimensions; ++i) {
550 auto const spacing = initial_particle_distribution.dimension(i).spacing();
551 initial_particle_distribution.dimension(i).pop_front();
552 initial_particle_distribution.dimension(i).front() -= spacing / 2;
553 initial_particle_distribution.dimension(i).back() -= spacing / 2;
555 initial_particle_distribution.vertices().iterate_indices(
556 [&](
auto const... is) {
557 particles.emplace_back(initial_particle_distribution.vertex_at(is...),
560 auto const small_radius =
561 (std::sqrt(2 * initial_particle_distribution.dimension(0).spacing() *
562 initial_particle_distribution.dimension(0).spacing()) -
563 initial_particle_distribution.dimension(0).spacing()) /
566 for (std::size_t i = 0; i < NumDimensions; ++i) {
567 auto const spacing = initial_particle_distribution.dimension(i).spacing();
568 initial_particle_distribution.dimension(i).pop_front();
569 initial_particle_distribution.dimension(i).front() -= spacing / 2;
570 initial_particle_distribution.dimension(i).back() -= spacing / 2;
572 initial_particle_distribution.vertices().iterate_indices(
573 [&](
auto const... is) {
574 particles.emplace_back(initial_particle_distribution.vertex_at(is...),
584 std::atomic_uint64_t &uuid_generator) {
593 std::atomic_uint64_t &uuid_generator) {
599 template <std::size_t... Is>
603 std::uint8_t
const max_split_depth, std::atomic_uint64_t &uuid_generator,
604 std::index_sequence<Is...> ) {
606 auto initial_particle_distribution = g.copy_without_properties();
608 initial_particle_distribution.dimension(0).spacing() / 2;
610 auto dim = initial_particle_distribution.template dimension<Is>();
611 auto const half_spacing = dim.spacing() / 2;
613 dim.front() -= half_spacing;
614 dim.back() -= half_spacing;
615 initial_particle_distribution.template set_dimension<Is>(dim);
617 initial_particle_distribution.vertices().iterate_positions(
624 auto dim = initial_particle_distribution.template dimension<Is>();
625 auto const half_spacing = dim.spacing() / 2;
627 dim.front() -= half_spacing;
628 dim.back() -= half_spacing;
629 initial_particle_distribution.template set_dimension<Is>(dim);
631 initial_particle_distribution.vertices().iterate_positions(
647 template <split_behavior SplitBehavior,
typename Flowmap>
648 [[nodiscard]]
static auto
652 using namespace detail::autonomous_particle;
653 auto uuid_generator = std::atomic_uint64_t{};
655 auto hierarchy_mutex = std::mutex{};
656 auto hierarchy_pairs = std::vector<hierarchy_pair>{};
661 auto [advected_particles, advected_simple_particles] =
662 advect<SplitBehavior>(std::forward<Flowmap>(phi), stepwidth, t_end,
663 particles, hierarchy_pairs, hierarchy_mutex,
667 auto map = std::unordered_map<
669 for (
auto const &p : advected_particles) {
670 map[p.id()] = edges.insert_vertex(p.center());
672 auto const h = hierarchy{hierarchy_pairs,
map, edges};
693 return std::tuple{std::move(advected_particles),
694 std::move(advected_simple_particles), std::move(edges)};
697 template <
typename Flowmap>
702 return advect<typename split_behaviors::two_splits>(
703 std::forward<Flowmap>(phi), stepwidth, t0, t_end, g);
706 template <
typename Flowmap>
711 return advect<typename split_behaviors::three_splits>(
712 std::forward<Flowmap>(phi), stepwidth, t0, t_end, g);
715 template <
typename Flowmap>
720 return advect<typename split_behaviors::three_and_four_splits>(
721 std::forward<Flowmap>(phi), stepwidth, t0, t_end, g);
724 template <
typename Flowmap>
729 return advect<typename split_behaviors::five_splits>(
730 std::forward<Flowmap>(phi), stepwidth, t0, t_end, g);
733 template <
typename Flowmap>
738 return advect<typename split_behaviors::seven_splits>(
739 std::forward<Flowmap>(phi), stepwidth, t0, t_end, g);
753 template <split_behavior SplitBehavior,
typename Flowmap>
757 std::vector<hierarchy_pair> &hierarchy_pairs,
758 std::mutex &hierarchy_mutex,
759 std::atomic_uint64_t &uuid_generator) {
766 auto particles_per_thread = std::vector<
769 while (particles.size() > 0) {
771 particles_per_thread);
772 advect_particle_pools<SplitBehavior>(
773 num_threads, std::forward<Flowmap>(phi), stepwidth, t_end,
774 particles_per_thread, hierarchy_pairs, hierarchy_mutex,
777 particles_per_thread);
779 return std::tuple{std::move(finished_particles),
780 std::move(finished_simple_particles)};
787 if (omp_get_thread_num() == 0) {
788 num_threads =
static_cast<std::size_t
>(omp_get_num_threads());
797 auto &particles_per_thread) {
798 using namespace std::ranges;
801 auto const thr_id = omp_get_thread_num();
805 auto &cont = std::get<0>(*particles_per_thread[thr_id]);
807 copy(particles.begin() +
begin, particles.begin() +
end,
808 std::back_inserter(cont));
813 template <split_behavior SplitBehavior,
typename Flowmap>
815 std::size_t
const , Flowmap &&phi,
817 auto &particles_per_thread, std::vector<hierarchy_pair> &hierarchy_pairs,
818 std::mutex &hierarchy_mutex, std::atomic_uint64_t &uuid_generator) {
821 auto const thr_id = omp_get_thread_num();
822 auto &[particles_at_t0, particles_at_t1, finished, simple_particles] =
823 *particles_per_thread[thr_id];
824 for (
auto const &
particle : particles_at_t0) {
825 particle.template advect_until_split<SplitBehavior>(
826 std::forward<Flowmap>(phi), stepwidth, t_end, particles_at_t1,
827 finished, simple_particles, hierarchy_pairs, hierarchy_mutex,
836 auto &particles_per_thread) {
837 using namespace std::ranges;
838 for (
auto &ps : particles_per_thread) {
839 auto &[base, advected, finished, simple] = *ps;
841 copy(advected, std::back_inserter(particles));
843 copy(finished, std::back_inserter(finished_particles));
845 copy(simple, std::back_inserter(simple_particles));
1029 split_behavior SplitBehavior =
typename split_behaviors::three_splits,
1036 std::vector<hierarchy_pair> & ,
1038 std::atomic_uint64_t &uuid_generator)
const {
1039 if constexpr (
is_cacheable<std::decay_t<
decltype(phi)>>()) {
1040 phi.use_caching(
false);
1046 static constexpr auto split_radii = SplitBehavior::radii;
1047 static constexpr auto split_offsets = SplitBehavior::offsets;
1048 auto const [eigvecs_S, eigvals_S] = this->
main_axes();
1049 auto const B = eigvecs_S * diag(eigvals_S);
1052 mat_type H, HHt, D, advected_nabla_phi, assembled_nabla_phi, advected_B,
1053 ghosts_positive_offset, ghosts_negative_offset, prev_ghosts_forward,
1054 prev_ghosts_backward;
1057 auto eig_HHt = std::pair<mat_type, vec_type>{};
1060 auto const &eigvecs_HHt = eig_HHt.first;
1061 auto const &eigvals_HHt = eig_HHt.second;
1065 ghosts_positive_offset.
col(i) =
x();
1066 ghosts_negative_offset.
col(i) =
x();
1068 ghosts_positive_offset += B;
1069 ghosts_negative_offset -= B;
1074 auto t_advected =
t();
1075 while (t_advected < t_end) {
1076 if (t_advected + stepwidth > t_end) {
1077 stepwidth = t_end - t_advected;
1081 advected_ellipse.center() =
1082 phi(advected_ellipse.center(), t_advected, stepwidth);
1083 ghosts_positive_offset =
1084 phi(ghosts_positive_offset, t_advected, stepwidth);
1085 ghosts_negative_offset =
1086 phi(ghosts_negative_offset, t_advected, stepwidth);
1089 if (t_advected + stepwidth + 1e-6 > t_end) {
1092 t_advected += stepwidth;
1096 H = (ghosts_positive_offset - ghosts_negative_offset) *
half;
1097 D = (ghosts_negative_offset + ghosts_positive_offset) *
half;
1099 D.
col(i) -= advected_ellipse.center();
1108 if (std::isnan(linearity)) {
1109 simple_particles.emplace_back(
x0(), advected_ellipse.center(),
1115 advected_nabla_phi = H * K;
1116 assembled_nabla_phi = advected_nabla_phi *
m_nabla_phi;
1118 current_radii =
sqrt(eigvals_HHt);
1119 advected_B = eigvecs_HHt * diag(current_radii);
1120 advected_ellipse.S() = advected_B *
transposed(eigvecs_HHt);
1123 if (t_advected == t_end) {
1124 finished_particles.emplace_back(advected_ellipse, t_advected,
x0(),
1131 static auto constexpr linearity_threshold = 1e-6;
1132 static auto constexpr distortion_threshold =
log(6);
1133 auto const distortion =
log(sqr_cond_H);
1135 (linearity >= linearity_threshold || distortion >= distortion_threshold)) {
1136 for (std::size_t i = 0; i <
size(split_radii); ++i) {
1137 auto const new_eigvals = current_radii * split_radii[i];
1138 auto const offset2 = advected_B * split_offsets[i];
1139 auto const offset0 = *
solve(assembled_nabla_phi, offset2);
1141 advected_ellipse.
center() + offset2,
1142 eigvecs_HHt * diag(new_eigvals) *
transposed(eigvecs_HHt)};
1144 splitted_particles.emplace_back(
1145 offset_ellipse, t_advected,
x0() + offset0, assembled_nabla_phi,
1168template <
floating_po
int Real>
1170 std::size_t
const num_points, filesystem::path
const &path,
1172 auto file = std::ofstream{path, std::ios::binary};
1173 if (!file.is_open()) {
1174 throw std::runtime_error{
"Could not write " + path.string()};
1176 auto offset = std::size_t{};
1177 using header_type = std::uint64_t;
1178 using connectivity_int = std::int32_t;
1179 using offset_int = connectivity_int;
1181 <<
" type=\"PolyData\""
1182 <<
" version=\"1.0\" "
1183 "byte_order=\"LittleEndian\""
1184 <<
" header_type=\"" << vtk::xml::to_data_type<header_type>() <<
"\">";
1185 file <<
"<PolyData>\n";
1186 for (std::size_t i = 0; i <
size(particles); ++i) {
1188 <<
" NumberOfPoints=\"" << num_points <<
"\""
1189 <<
" NumberOfPolys=\"0\""
1190 <<
" NumberOfVerts=\"0\""
1191 <<
" NumberOfLines=\"" << num_points - 1 <<
"\""
1192 <<
" NumberOfStrips=\"0\""
1197 file <<
"<DataArray"
1198 <<
" format=\"appended\""
1199 <<
" offset=\"" << offset <<
"\""
1200 <<
" type=\"" << vtk::xml::to_data_type<Real>()
1201 <<
"\" NumberOfComponents=\"" << 3 <<
"\"/>";
1202 auto const num_bytes_points = header_type(
sizeof(Real) * 3 * num_points);
1203 offset += num_bytes_points +
sizeof(header_type);
1204 file <<
"</Points>\n";
1207 file <<
"<Lines>\n";
1209 file <<
"<DataArray format=\"appended\" offset=\"" << offset <<
"\" type=\""
1210 << vtk::xml::to_data_type<connectivity_int>()
1211 <<
"\" Name=\"connectivity\"/>\n";
1212 auto const num_bytes_connectivity =
1213 (num_points - 1) * 2 *
sizeof(connectivity_int);
1214 offset += num_bytes_connectivity +
sizeof(header_type);
1216 file <<
"<DataArray format=\"appended\" offset=\"" << offset <<
"\" type=\""
1217 << vtk::xml::to_data_type<offset_int>()
1218 <<
"\" Name=\"offsets\"/>\n";
1219 auto const num_bytes_offsets =
1220 sizeof(offset_int) * (num_points - 1) * 2;
1221 offset += num_bytes_offsets +
sizeof(header_type);
1222 file <<
"</Lines>\n";
1223 file <<
"</Piece>\n";
1225 file <<
"</PolyData>\n";
1226 file <<
"<AppendedData encoding=\"raw\">_";
1228 for (
auto const &
particle : particles) {
1229 auto const num_bytes_points = header_type(
sizeof(Real) * 3 * num_points);
1230 using namespace std::ranges;
1235 auto radian_to_cartesian = [](
auto const t) {
1238 auto out_it = std::back_inserter(discretization);
1239 copy(radial | views::transform(radian_to_cartesian), out_it);
1240 discretization.set_closed(
true);
1241 for (
auto const v : discretization.vertices()) {
1243 discretization[v].x() = v2.x();
1244 discretization[v].y() = v2.y();
1248 file.write(
reinterpret_cast<char const *
>(&num_bytes_points),
1249 sizeof(header_type));
1250 for (
auto const v : discretization.vertices()) {
1251 file.write(
reinterpret_cast<char const *
>(discretization.at(v).data()),
1257 auto connectivity_data = std::vector<connectivity_int>{};
1258 connectivity_data.reserve((num_points - 1) * 2);
1259 for (std::size_t i = 0; i < num_points - 1; ++i) {
1260 connectivity_data.push_back(
static_cast<connectivity_int
>(i));
1261 connectivity_data.push_back(
1262 static_cast<connectivity_int
>(i + 1));
1265 auto const num_bytes_connectivity =
1266 header_type((num_points - 1) * 2 *
sizeof(connectivity_int));
1267 file.write(
reinterpret_cast<char const *
>(&num_bytes_connectivity),
1268 sizeof(header_type));
1269 file.write(
reinterpret_cast<char const *
>(connectivity_data.data()),
1270 static_cast<std::streamsize
>(num_bytes_connectivity));
1275 auto offsets = std::vector<offset_int>(num_points, 2);
1276 for (std::size_t i = 1; i <
size(offsets); ++i) {
1277 offsets[i] += offsets[i - 1];
1279 auto const num_bytes_offsets =
1280 header_type(
sizeof(offset_int) * (num_points - 1) * 2);
1281 file.write(
reinterpret_cast<char const *
>(&num_bytes_offsets),
1282 sizeof(header_type));
1283 file.write(
reinterpret_cast<char const *
>(offsets.data()),
1284 static_cast<std::streamsize
>(num_bytes_offsets));
1288 file <<
"</AppendedData>";
1289 file <<
"</VTKFile>";
1294template <std::
size_t NumDimensions>
1296template <
floating_po
int Real>
1298template <
floating_po
int Real>
Definition: cache_alignment.h:21
Definition: concepts.h:30
Definition: concepts.h:84
Definition: autonomous_particle.h:21
Definition: tensor_concepts.h:23
Definition: algorithm.h:6
constexpr auto is_cacheable()
Definition: is_cacheable.h:19
auto begin(Range &&range)
Definition: iterator_facade.h:318
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
auto end(Range &&range)
Definition: iterator_facade.h:322
constexpr auto inv(diag_static_tensor< Tensor, N, N > const &A) -> std::optional< diag_static_tensor< vec< tatooine::value_type< Tensor >, N >, N, N > >
Definition: diag_tensor.h:109
constexpr auto log(arithmetic auto const x)
Definition: math.h:23
auto eigenvectors_sym(Mat &&A)
Definition: eigenvalues.h:44
constexpr auto invoke(invocable auto &&...funcs)
Definition: functional.h:8
auto solve(polynomial< Real, 1 > const &p) -> std::vector< Real >
solve a + b*x
Definition: polynomial.h:187
auto write_vtp(Lines const &lines, filesystem::path const &path) -> void
Definition: write.h:38
detail::rectilinear_grid::creator_t< linspace< Real >, N > uniform_rectilinear_grid
Definition: rectilinear_grid.h:1904
auto constexpr map(F &&f, Ts &&... ts)
maps unary function f to all single parameters of parameter pack ts
Definition: map.h:10
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
constexpr auto dot(base_tensor< Tensor0, T0, N > const &lhs, base_tensor< Tensor1, T1, N > const &rhs)
Definition: tensor_operations.h:120
auto transposed(dynamic_tensor auto &&t)
Definition: transposed_tensor.h:170
constexpr auto sqrt(arithmetic auto const x)
Definition: math.h:29
Definition: autonomous_particle.h:30
static auto particles_from_grid_small_filling_gaps(real_type const t0, uniform_rectilinear_grid< Real, NumDimensions > const &g, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:532
static auto distribute_particles_to_thread_containers(std::size_t const num_threads, container_type &particles, auto &particles_per_thread)
Definition: autonomous_particle.h:795
autonomous_particle(ellipse_type const &ell, real_type const t, pos_type const &x0, mat_type const &nabla_phi, std::uint8_t const split_depth, std::uint8_t const max_split_depth, std::uint64_t const id)
Definition: autonomous_particle.h:133
static auto particles_from_grid_filling_gaps(real_type const t0, uniform_rectilinear_grid< Real, NumDimensions > const &g, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:581
autonomous_particle(ellipse_type const &ell, real_type const t, std::uint8_t max_split_depth, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:109
static constexpr auto num_dimensions() -> std::size_t
Definition: autonomous_particle.h:33
static auto advect_with_three_and_four_splits(Flowmap &&phi, real_type const stepwidth, real_type const t_end, container_type const &initial_particles, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:473
auto center() const -> auto const &
Definition: hyper_ellipse.h:91
std::vector< this_type > container_type
Definition: autonomous_particle.h:49
vec< real_type, NumDimensions > vec_type
Definition: autonomous_particle.h:46
static auto advect(Flowmap &&phi, real_type const stepwidth, real_type const t_end, container_type const &initial_particles, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:405
std::uint8_t m_max_split_depth
Definition: autonomous_particle.h:71
static auto advect_with_seven_splits(Flowmap &&phi, real_type const stepwidth, real_type const t_end, container_type const &initial_particles, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:493
auto operator=(autonomous_particle &&other) noexcept -> autonomous_particle &=default
auto x() -> auto &
Definition: autonomous_particle.h:162
auto initial_ellipse() const
Definition: autonomous_particle.h:180
auto x0() -> auto &
Definition: autonomous_particle.h:158
real_type m_t
Definition: autonomous_particle.h:68
static auto advect_with_three_splits(Flowmap &&phi, real_type const stepwidth, real_type const t0, real_type const t_end, uniform_rectilinear_grid< Real, NumDimensions > const &g)
Definition: autonomous_particle.h:707
static auto gather_particles(container_type &particles, container_type &finished_particles, simple_particle_container_type &simple_particles, auto &particles_per_thread)
Definition: autonomous_particle.h:833
auto sampler() const
Definition: autonomous_particle.h:1155
static constexpr auto default_max_split_depth
Definition: autonomous_particle.h:62
autonomous_particle(ellipse_type const &ell, real_type const t, pos_type const &x0, mat_type const &nabla_phi, std::uint8_t const split_depth, std::uint8_t const max_split_depth, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:142
static auto advect_with_five_splits(Flowmap &&phi, real_type const stepwidth, real_type const t0, real_type const t_end, uniform_rectilinear_grid< Real, NumDimensions > const &g)
Definition: autonomous_particle.h:725
static auto particles_from_grid_filling_gaps(real_type const t0, uniform_rectilinear_grid< Real, NumDimensions > const &g, std::uint8_t const max_split_depth, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:589
auto nabla_phi() const -> auto const &
Definition: autonomous_particle.h:169
auto split_depth() const
Definition: autonomous_particle.h:182
mat_type m_nabla_phi
Definition: autonomous_particle.h:69
static auto particles_from_grid_small_filling_gaps(real_type const t0, uniform_rectilinear_grid< Real, NumDimensions > const &g, std::uint8_t const max_split_depth, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:540
autonomous_particle(ellipse_type const &ell, real_type const t, std::uint8_t max_split_depth, std::uint64_t const id)
Definition: autonomous_particle.h:103
auto advect_with_five_splits(Flowmap &&phi, real_type const stepwidth, real_type const t_end, std::atomic_uint64_t &uuid_generator) const
Advects single particle.
Definition: autonomous_particle.h:379
autonomous_particle(pos_type const &x, real_type const t, real_type const r, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:119
static auto advect_with_two_splits(Flowmap &&phi, real_type const stepwidth, real_type const t0, real_type const t_end, uniform_rectilinear_grid< Real, NumDimensions > const &g)
Definition: autonomous_particle.h:698
autonomous_particle(autonomous_particle &&other) noexcept=default
auto id() const
Definition: autonomous_particle.h:185
static auto advect(Flowmap &&phi, real_type const stepwidth, real_type const t_end, container_type particles, std::vector< hierarchy_pair > &hierarchy_pairs, std::mutex &hierarchy_mutex, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:754
static constexpr auto half
Definition: autonomous_particle.h:41
static auto particles_from_grid(real_type const t0, uniform_rectilinear_grid< Real, NumDimensions > const &g, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:503
autonomous_particle(ellipse_type const &ell, real_type const t, std::uint64_t const id)
Definition: autonomous_particle.h:94
autonomous_particle(pos_type const &x, real_type const t, real_type const r, std::uint8_t max_split_depth, std::uint64_t const id)
Definition: autonomous_particle.h:123
std::uint64_t m_id
Definition: autonomous_particle.h:72
auto x0(std::size_t i) const
Definition: autonomous_particle.h:160
static auto advect(Flowmap &&phi, real_type const stepwidth, real_type const t0, real_type const t_end, uniform_rectilinear_grid< Real, NumDimensions > const &g)
Definition: autonomous_particle.h:649
autonomous_particle(pos_type const &x, real_type const t, real_type const r, std::uint64_t const id)
Definition: autonomous_particle.h:114
static auto advect_with_three_and_four_splits(Flowmap &&phi, real_type const stepwidth, real_type const t0, real_type const t_end, uniform_rectilinear_grid< Real, NumDimensions > const &g)
Definition: autonomous_particle.h:716
static auto particles_from_grid(real_type const t0, uniform_rectilinear_grid< Real, NumDimensions > const &g, std::uint8_t const max_split_depth, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:510
static auto mutex() -> auto &
Definition: autonomous_particle.h:74
auto discretize(std::size_t const n, backward_tag const) const
Definition: autonomous_particle.h:1163
auto x(std::size_t const i) const
Definition: autonomous_particle.h:164
auto advect_with_three_splits(Flowmap &&phi, real_type const stepwidth, real_type const t_end, std::atomic_uint64_t &uuid_generator) const
Advects single particle.
Definition: autonomous_particle.h:361
pos_type m_x0
Definition: autonomous_particle.h:67
std::vector< simple_particle_type > simple_particle_container_type
Definition: autonomous_particle.h:50
static auto particles_from_grid_filling_gaps(real_type const t0, uniform_rectilinear_grid< Real, NumDimensions > const &g, std::uint8_t const max_split_depth, std::atomic_uint64_t &uuid_generator, std::index_sequence< Is... >)
Definition: autonomous_particle.h:600
auto x() const -> auto const &
Definition: autonomous_particle.h:163
static auto advect_with_two_splits(Flowmap &&phi, real_type const stepwidth, real_type const t_end, container_type const &initial_particles, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:452
auto x0() const -> auto const &
Definition: autonomous_particle.h:159
static auto advect_with_seven_splits(Flowmap &&phi, real_type const stepwidth, real_type const t0, real_type const t_end, uniform_rectilinear_grid< Real, NumDimensions > const &g)
Definition: autonomous_particle.h:734
autonomous_particle(pos_type const &x, real_type const t, real_type const r, std::uint8_t max_split_depth, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:128
static auto advect_particle_pools(std::size_t const, Flowmap &&phi, real_type const stepwidth, real_type const t_end, auto &particles_per_thread, std::vector< hierarchy_pair > &hierarchy_pairs, std::mutex &hierarchy_mutex, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:814
auto advect_with_seven_splits(Flowmap &&phi, real_type const stepwidth, real_type const t_end, std::atomic_uint64_t &uuid_generator) const
Advects single particle.
Definition: autonomous_particle.h:388
auto S0() const
Definition: autonomous_particle.h:171
geometry::hyper_ellipse< Real, NumDimensions > ellipse_type
Definition: autonomous_particle.h:51
auto discretize(std::size_t const n, forward_tag const) const
Definition: autonomous_particle.h:1159
static auto advect_with_three_splits(Flowmap &&phi, real_type const stepwidth, real_type const t_end, container_type const &initial_particles, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:462
auto advect(Flowmap &&phi, real_type const stepwidth, real_type const t_end, std::atomic_uint64_t &uuid_generator) const
Definition: autonomous_particle.h:329
auto t() const
Definition: autonomous_particle.h:167
~autonomous_particle()=default
autonomous_particle(autonomous_particle const &other)=default
{
Real real_type
Definition: autonomous_particle.h:45
auto advect_with_three_and_four_splits(Flowmap &&phi, real_type const stepwidth, real_type const t_end, std::atomic_uint64_t &uuid_generator) const
Advects single particle.
Definition: autonomous_particle.h:370
static auto advect_with_five_splits(Flowmap &&phi, real_type const stepwidth, real_type const t_end, container_type const &initial_particles, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:483
autonomous_particle(ellipse_type const &ell, real_type const t, std::atomic_uint64_t &uuid_generator)
Definition: autonomous_particle.h:99
auto max_split_depth() const
Definition: autonomous_particle.h:183
auto t() -> auto &
Definition: autonomous_particle.h:166
auto advect_with_two_splits(Flowmap &&phi, real_type const stepwidth, real_type const t_end, std::atomic_uint64_t &uuid_generator) const
Advects single particle.
Definition: autonomous_particle.h:352
auto advect_until_split(Flowmap phi, real_type stepwidth, real_type const t_end, container_type &splitted_particles, container_type &finished_particles, simple_particle_container_type &simple_particles, std::vector< hierarchy_pair > &, std::mutex &, std::atomic_uint64_t &uuid_generator) const
Definition: autonomous_particle.h:1031
auto S() const -> auto const &
Definition: hyper_ellipse.h:88
std::uint8_t m_split_depth
Definition: autonomous_particle.h:70
static auto num_threads()
Definition: autonomous_particle.h:783
auto operator=(autonomous_particle const &other) -> autonomous_particle &=default
Definition: post_triangulation.h:15
Definition: split_behavior.h:13
Definition: vertex_handle.h:10
Definition: hyper_ellipse.h:12
auto center() const -> auto const &
Definition: hyper_ellipse.h:91
auto discretize(std::size_t const num_vertices=32) const
Definition: hyper_ellipse.h:178
auto main_axes() const
Definition: hyper_ellipse.h:259
auto S() const -> auto const &
Definition: hyper_ellipse.h:88
Definition: linspace.h:26
constexpr auto pop_back()
Definition: linspace.h:107
auto constexpr col(std::size_t i)
Definition: mat.h:175
Definition: particle.h:10