Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
generators.hpp
Go to the documentation of this file.
1// -------------------------------------------------------//
2//
3// SHAMROCK code for hydrodynamics
4// Copyright (c) 2021-2026 Timothée David--Cléris <tim.shamrock@proton.me>
5// SPDX-License-Identifier: CeCILL Free Software License Agreement v2.1
6// Shamrock is licensed under the CeCILL 2.1 License, see LICENSE for more information
7//
8// -------------------------------------------------------//
9
10//%Impl status : Good
11
12#pragma once
13
22#include "shamalgs/random.hpp"
23#include "shambackends/sycl.hpp"
27
28namespace generic::setup::generators {
29
30 template<class flt>
31 inline sycl::vec<flt, 3> get_box_dim(flt r_particle, u32 xcnt, u32 ycnt, u32 zcnt) {
32
33 using vec3 = sycl::vec<flt, 3>;
34
35 u32 im = xcnt;
36 u32 jm = ycnt;
37 u32 km = zcnt;
38
39 auto get_pos = [&](u32 i, u32 j, u32 k) -> vec3 {
40 vec3 r_a
41 = {2 * i + ((j + k) % 2),
42 sycl::sqrt(3.) * (j + (1. / 3.) * (k % 2)),
43 2 * sycl::sqrt(6.) * k / 3};
44
45 r_a *= r_particle;
46
47 return r_a;
48 };
49
50 return get_pos(im, jm, km);
51 }
52
53 template<class flt>
54 inline std::tuple<sycl::vec<flt, 3>, sycl::vec<flt, 3>> get_ideal_fcc_box(
55 flt r_particle, std::tuple<sycl::vec<flt, 3>, sycl::vec<flt, 3>> box) {
56
57 using vec3 = sycl::vec<flt, 3>;
58
59 vec3 box_min = std::get<0>(box);
60 vec3 box_max = std::get<1>(box);
61
62 vec3 box_dim = box_max - box_min;
63
64 vec3 iboc_dim = (box_dim / vec3({2, sycl::sqrt(3.), 2 * sycl::sqrt(6.) / 3})) / r_particle;
65
66 u32 i = iboc_dim.x();
67 u32 j = iboc_dim.y();
68 u32 k = iboc_dim.z();
69
70 // std::cout << "get_ideal_box_idim :" << i << " " << j << " " << k << std::endl;
71
72 i -= i % 2;
73 j -= j % 2;
74 k -= k % 2;
75
76 vec3 m1 = get_box_dim(r_particle, i, j, k);
77
78 return {box_min, box_min + m1};
79 }
80
81 template<class flt, class Tpred_select, class Tpred_pusher>
82 inline void add_particles_fcc(
83 flt r_particle,
84 std::tuple<sycl::vec<flt, 3>, sycl::vec<flt, 3>> box,
85 Tpred_select &&selector,
86 Tpred_pusher &&part_pusher) {
87
88 using vec3 = sycl::vec<flt, 3>;
89
90 vec3 box_min = std::get<0>(box);
91 vec3 box_max = std::get<1>(box);
92
93 vec3 box_dim = box_max - box_min;
94
95 vec3 iboc_dim = (box_dim / vec3({2, sycl::sqrt(3.), 2 * sycl::sqrt(6.) / 3})) / r_particle;
96
97 // std::cout << "part box size : (" << iboc_dim.x() << ", " << iboc_dim.y() << ", " <<
98 // iboc_dim.z() << ")" << std::endl;
99 u32 ix = std::ceil(iboc_dim.x());
100 u32 iy = std::ceil(iboc_dim.y());
101 u32 iz = std::ceil(iboc_dim.z());
102
103 if (shamcomm::world_rank() == 0)
104 logger::info_ln("SPH", "Add fcc lattice size : (", ix, iy, iz, ")");
105 // std::cout << "part box size : (" << ix << ", " << iy << ", " << iz << ")" << std::endl;
106
107 if ((iy % 2) != 0 && (iz % 2) != 0) {
108 std::cout << "Warning : particle count is odd on axis y or z -> this may lead to "
109 "periodicity issues";
110 }
111
112 for (u32 i = 0; i < ix; i++) {
113 for (u32 j = 0; j < iy; j++) {
114 for (u32 k = 0; k < iz; k++) {
115
116 vec3 r_a
117 = {2 * i + ((j + k) % 2),
118 sycl::sqrt(3.) * (j + (1. / 3.) * (k % 2)),
119 2 * sycl::sqrt(6.) * k / 3};
120
121 r_a *= r_particle;
122 r_a += box_min;
123
124 if (selector(r_a))
125 part_pusher(r_a, r_particle);
126 }
127 }
128 }
129 }
130
131 template<class Tscal>
132 struct DiscOutput {
133 sycl::vec<Tscal, 3> pos;
134 sycl::vec<Tscal, 3> velocity;
135 Tscal cs;
136 Tscal rho;
137 };
138
151 template<class flt>
152 inline void add_disc2(
153 u32 Npart,
154 flt r_in,
155 flt r_out,
156 std::function<flt(flt)> sigma_profile,
157 std::function<flt(flt)> cs_profile,
158 std::function<flt(flt)> rot_profile,
159 std::function<void(DiscOutput<flt>)> pusher) {
160 constexpr flt _2pi = 2 * shambase::constants::pi<flt>;
161
162 auto f_func = [&](flt r) {
163 return r * sigma_profile(r);
164 };
165
166 flt fmax = f_func(r_out);
167
168 std::mt19937 eng(0x111);
169
170 auto find_r = [&]() {
171 while (true) {
172 flt u2 = shamalgs::primitives::mock_value<flt>(eng, 0, fmax);
173 flt r = shamalgs::primitives::mock_value<flt>(eng, r_in, r_out);
174 if (u2 < f_func(r)) {
175 return r;
176 }
177 }
178 };
179
180 // eq 298 phantom paper & appendix A.7
181
182 for (u32 i = 0; i < Npart; i++) {
183
184 flt theta = shamalgs::primitives::mock_value<flt>(eng, 0, _2pi);
185 flt Gauss = shamalgs::random::mock_gaussian<flt>(eng);
186
187 flt r = find_r();
188
189 flt vk = rot_profile(r);
190 flt cs = cs_profile(r);
191 flt sigma = sigma_profile(r);
192
193 flt H_r = cs / vk;
194 flt H = H_r * r;
195
196 flt z = H * Gauss;
197
198 auto pos = sycl::vec<flt, 3>{r * sycl::cos(theta), z, r * sycl::sin(theta)};
199
200 auto etheta = sycl::vec<flt, 3>{-pos.z(), 0, pos.x()};
201 etheta /= sycl::length(etheta);
202
203 auto vel = vk * etheta;
204
205 flt rho = 0.1 * (sigma / (H * shambase::constants::pi2_sqrt<flt>) )
206 * sycl::exp(-z * z / (2 * H * H));
207
208 DiscOutput<flt> out{pos, vel, cs, rho};
209
210 pusher(out);
211 }
212 }
213
227 template<class flt, class Tpred_pusher>
228 inline void add_disc(
229 u32 Npart,
230 flt p,
231 flt rho_0,
232 flt m,
233 flt r_in,
234 flt r_out,
235 flt q,
236 Tpred_pusher &&part_pusher) {
237 flt _2pi = 2 * M_PI;
238
239 flt K = _2pi * rho_0 / m;
240 flt c = 2 - p;
241
242 flt y = K * (r_out - r_in) / c;
243
244 std::mt19937 eng(0x111);
245
246 for (u32 i = 0; i < Npart; i++) {
247
248 flt r_1 = shamalgs::primitives::mock_value<flt>(eng, 0, y);
249
250 flt r = sycl::pow(sycl::pow(r_in, c) + c * r_1 / K, 1 / c);
251
252 flt theta = shamalgs::primitives::mock_value<flt>(eng, 0, _2pi);
253
254 flt u = shamalgs::random::mock_gaussian<flt>(eng);
255
256 flt H = 0.1 * sycl::pow(r, (flt) (3. / 2. - q / 2));
257
258 part_pusher(
259 sycl::vec<flt, 3>({r * sycl::cos(theta), u * H, r * sycl::sin(theta)}), 0.1);
260 }
261 }
262
263} // namespace generic::setup::generators
Header file describing a Node Instance.
std::uint32_t u32
32 bit unsigned integer
Class holding the value of numerous constants generated from the following source.
void add_disc2(u32 Npart, flt r_in, flt r_out, std::function< flt(flt)> sigma_profile, std::function< flt(flt)> cs_profile, std::function< flt(flt)> rot_profile, std::function< void(DiscOutput< flt >)> pusher)
void add_disc(u32 Npart, flt p, flt rho_0, flt m, flt r_in, flt r_out, flt q, Tpred_pusher &&part_pusher)
i32 world_rank()
Gives the rank of the current process in the MPI communicator.
Definition worldInfo.cpp:40