Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
ExternalForces.cpp
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
18#include "shambase/memory.hpp"
21#include "shamcomm/logs.hpp"
38
39namespace shambase {
40
41 template<class T>
42 std::shared_ptr<T> to_shared(T &&t) {
43 return std::make_shared<T>(std::forward<T>(t));
44 }
45} // namespace shambase
46
47template<class Tvec, template<class> class SPHKernel>
49
50 StackEntry stack_loc{};
51
52 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
53
54 Tscal gpart_mass = solver_config.gpart_mass;
55
56 using namespace shamrock;
57 using namespace shamrock::patch;
58
59 PatchDataLayerLayout &pdl = scheduler().pdl_old();
60
61 const u32 iaxyz_ext = pdl.get_field_idx<Tvec>("axyz_ext");
62 modules::SinkParticlesUpdate<Tvec, SPHKernel> sink_update(context, solver_config, storage);
63
64 scheduler().for_each_patchdata_nonempty([&](Patch cur_p, PatchDataLayer &pdat) {
65 PatchDataField<Tvec> &field = pdat.get_field<Tvec>(iaxyz_ext);
66 field.field_raz();
67 });
68
69 sink_update.compute_sph_forces();
70
71 if (solver_config.ext_force_config.ext_forces.empty()) {
72 return;
73 }
74
76
78 [&](shamrock::solvergraph::FieldRefs<Tvec> &field_xyz_edge) {
80 scheduler().for_each_patchdata_nonempty([&](const Patch p, PatchDataLayer &pdat) {
81 auto &field = pdat.get_field<Tvec>(0);
82 field_xyz_refs.add_obj(p.id_patch, std::ref(field));
83 });
84 field_xyz_edge.set_refs(field_xyz_refs);
85 });
86 set_field_xyz.set_edges(field_xyz);
87 set_field_xyz.evaluate();
88
89 auto field_axyz_ext = shamrock::solvergraph::FieldRefs<Tvec>::make_shared("", "");
90
92 [&](shamrock::solvergraph::FieldRefs<Tvec> &field_axyz_ext_edge) {
94 scheduler().for_each_patchdata_nonempty([&](const Patch p, PatchDataLayer &pdat) {
95 auto &field = pdat.get_field<Tvec>(iaxyz_ext);
96 field_axyz_ext_refs.add_obj(p.id_patch, std::ref(field));
97 });
98 field_axyz_ext_edge.set_refs(field_axyz_ext_refs);
99 });
100 set_field_axyz_ext.set_edges(field_axyz_ext);
101 set_field_axyz_ext.evaluate();
102
104
107 sizes.indexes = {};
108 scheduler().for_each_patchdata_nonempty([&](const Patch p, PatchDataLayer &pdat) {
109 sizes.indexes.add_obj(p.id_patch, pdat.get_obj_cnt());
110 });
111 });
112 set_sizes.set_edges(sizes);
113 set_sizes.evaluate();
114
116
119 constant_G.data = solver_config.get_constant_G();
120 });
121
122 set_constant_G.set_edges(constant_G);
123
124 std::vector<std::shared_ptr<shamrock::solvergraph::INode>> add_ext_forces_seq{};
125
126 for (auto var_force : solver_config.ext_force_config.ext_forces) {
127 if (EF_PointMass *ext_force = std::get_if<EF_PointMass>(&var_force.val)) {
128
131
133 set_central_mass([&](shamrock::solvergraph::IDataEdge<Tscal> &central_mass) {
134 central_mass.data = ext_force->central_mass;
135 });
136 set_central_mass.set_edges(central_mass);
137
139 set_central_pos([&](shamrock::solvergraph::IDataEdge<Tvec> &central_pos) {
140 central_pos.data = {}; // no support for offset yet
141 });
142 set_central_pos.set_edges(central_pos);
143
144 common::modules::AddForceCentralGravPotential<Tvec> add_force_central_grav_potential;
145 add_force_central_grav_potential.set_edges(
146 constant_G, central_mass, central_pos, field_xyz, sizes, field_axyz_ext);
147
148 add_ext_forces_seq.push_back(
149 std::make_shared<shamrock::solvergraph::OperationSequence>(
150 "Point mass",
151 std::vector<std::shared_ptr<shamrock::solvergraph::INode>>{
152 shambase::to_shared(std::move(set_central_pos)),
153 shambase::to_shared(std::move(set_central_mass)),
154 shambase::to_shared(std::move(add_force_central_grav_potential))}));
155
156 } else if (EF_LenseThirring *ext_force = std::get_if<EF_LenseThirring>(&var_force.val)) {
157
160
162 set_central_mass([&](shamrock::solvergraph::IDataEdge<Tscal> &central_mass) {
163 central_mass.data = ext_force->central_mass;
164 });
165 set_central_mass.set_edges(central_mass);
166
168 set_central_pos([&](shamrock::solvergraph::IDataEdge<Tvec> &central_pos) {
169 central_pos.data = {}; // no support for offset yet
170 });
171 set_central_pos.set_edges(central_pos);
172
173 common::modules::AddForceCentralGravPotential<Tvec> add_force_central_grav_potential;
174 add_force_central_grav_potential.set_edges(
175 constant_G, central_mass, central_pos, field_xyz, sizes, field_axyz_ext);
176
177 add_ext_forces_seq.push_back(
178 std::make_shared<shamrock::solvergraph::OperationSequence>(
179 "Point mass",
180 std::vector<std::shared_ptr<shamrock::solvergraph::INode>>{
181 shambase::to_shared(std::move(set_central_pos)),
182 shambase::to_shared(std::move(set_central_mass)),
183 shambase::to_shared(std::move(add_force_central_grav_potential))}));
184
185 } else if (
186 EF_ShearingBoxForce *ext_force = std::get_if<EF_ShearingBoxForce>(&var_force.val)) {
187
191 eta.data = ext_force->eta;
192 });
193 set_eta.set_edges(eta);
194
196 add_force_shearing_box_inertial_part{};
197 add_force_shearing_box_inertial_part.set_edges(eta, field_xyz, sizes, field_axyz_ext);
198
199 add_ext_forces_seq.push_back(
200 std::make_shared<shamrock::solvergraph::OperationSequence>(
201 "Shearing box force",
202 std::vector<std::shared_ptr<shamrock::solvergraph::INode>>{
203 shambase::to_shared(std::move(set_eta)),
204 shambase::to_shared(std::move(add_force_shearing_box_inertial_part))}));
205
206 } else if (
207 EF_VerticalDiscPotential *ext_force
208 = std::get_if<EF_VerticalDiscPotential>(&var_force.val)) {
209
212
214 set_central_mass([cmass = ext_force->central_mass](
216 central_mass.data = cmass;
217 });
218 set_central_mass.set_edges(central_mass);
219
221 [r = ext_force->R0](shamrock::solvergraph::IDataEdge<Tscal> &R0) {
222 R0.data = r; // no support for offset yet
223 });
224 set_R0.set_edges(R0);
225
226 common::modules::AddForceVerticalDiscPotential<Tvec> add_force_vertical_disc_potential;
227 add_force_vertical_disc_potential.set_edges(
228 constant_G, central_mass, R0, field_xyz, sizes, field_axyz_ext);
229
230 add_ext_forces_seq.push_back(
231 std::make_shared<shamrock::solvergraph::OperationSequence>(
232 "Vertical disc potential",
233 std::vector<std::shared_ptr<shamrock::solvergraph::INode>>{
234 shambase::to_shared(std::move(set_R0)),
235 shambase::to_shared(std::move(set_central_mass)),
236 shambase::to_shared(std::move(add_force_vertical_disc_potential))}));
237
238 } else if (
239 EF_VelocityDissipation *ext_force
240 = std::get_if<EF_VelocityDissipation>(&var_force.val)) {
241
242 } else {
243 shambase::throw_unimplemented("this force is not handled, yet ...");
244 }
245 }
246
247 set_constant_G.evaluate();
248
249 if (add_ext_forces_seq.size() > 0) {
251 "Add external forces", std::move(add_ext_forces_seq));
252 seq.evaluate();
253 }
254}
255
256template<class T>
257std::shared_ptr<shamrock::solvergraph::INode> register_constant_set(
258 shamrock::solvergraph::SolverGraph &solver_graph, std::string name, std::function<T()> getter) {
259 solver_graph.register_edge(name, shamrock::solvergraph::IDataEdge<T>("", ""));
260
261 solver_graph.register_node(
262 "set_" + name,
265 edge.data = getter();
266 }));
267
268 solver_graph
270 "set_" + name)
271 .set_edges(solver_graph.get_edge_ptr_base(name));
272
273 return solver_graph.get_node_ptr_base("set_" + name);
274}
275
276template<class Tvec, template<class> class SPHKernel>
278
279 StackEntry stack_loc{};
280
281 sham::DeviceQueue &q = shamsys::instance::get_compute_scheduler().get_queue();
282
283 Tscal gpart_mass = solver_config.gpart_mass;
284
285 using namespace shamrock;
286 using namespace shamrock::patch;
287
288 PatchDataLayerLayout &pdl = scheduler().pdl_old();
289
290 const u32 iaxyz = pdl.get_field_idx<Tvec>("axyz");
291 const u32 ivxyz = pdl.get_field_idx<Tvec>("vxyz");
292 const u32 iaxyz_ext = pdl.get_field_idx<Tvec>("axyz_ext");
293
294 scheduler().for_each_patchdata_nonempty([&](Patch cur_p, PatchDataLayer &pdat) {
295 sham::DeviceBuffer<Tvec> &buf_axyz = pdat.get_field_buf_ref<Tvec>(iaxyz);
296 sham::DeviceBuffer<Tvec> &buf_axyz_ext = pdat.get_field_buf_ref<Tvec>(iaxyz_ext);
297
298 sham::EventList depends_list;
299 auto axyz = buf_axyz.get_write_access(depends_list);
300 auto axyz_ext = buf_axyz_ext.get_read_access(depends_list);
301
302 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
303 shambase::parallel_for(
304 cgh, pdat.get_obj_cnt(), "add ext force acc to acc", [=](u64 gid) {
305 axyz[gid] += axyz_ext[gid];
306 });
307 });
308
309 buf_axyz.complete_event_state(e);
310 buf_axyz_ext.complete_event_state(e);
311 });
312
313 if (solver_config.ext_force_config.ext_forces.empty()) {
314 return; // skip if no external forces
315 }
316
317 using SolverConfigExtForce = typename Config::ExtForceConfig;
318 using EF_PointMass = typename SolverConfigExtForce::PointMass;
319 using EF_LenseThirring = typename SolverConfigExtForce::LenseThirring;
320
321 using namespace shamrock::solvergraph;
322 SolverGraph solver_graph{};
323
324 auto set_constant_G = register_constant_set<Tscal>(solver_graph, "constant_G", [&]() {
325 return solver_config.get_constant_G();
326 });
327 auto set_constant_c = register_constant_set<Tscal>(solver_graph, "constant_c", [&]() {
328 return solver_config.get_constant_c();
329 });
330
331 bool is_G_needed = false;
332 bool is_c_needed = false;
333
334 for (auto var_force : solver_config.ext_force_config.ext_forces) {
335 if (EF_PointMass *ext_force = std::get_if<EF_PointMass>(&var_force.val)) {
336
337 } else if (EF_LenseThirring *ext_force = std::get_if<EF_LenseThirring>(&var_force.val)) {
338 is_G_needed = true;
339 is_c_needed = true;
340 } else if (
341 EF_ShearingBoxForce *ext_force = std::get_if<EF_ShearingBoxForce>(&var_force.val)) {
342 } else if (
343 EF_VerticalDiscPotential *ext_force
344 = std::get_if<EF_VerticalDiscPotential>(&var_force.val)) {
345 } else if (
346 EF_VelocityDissipation *ext_force
347 = std::get_if<EF_VelocityDissipation>(&var_force.val)) {
348 } else {
349 shambase::throw_unimplemented("this force is not handled, yet ...");
350 }
351 }
352
353 std::vector<std::shared_ptr<shamrock::solvergraph::INode>> add_ext_forces_seq{};
354
355 if (is_G_needed) {
356 add_ext_forces_seq.push_back(set_constant_G);
357 }
358 if (is_c_needed) {
359 add_ext_forces_seq.push_back(set_constant_c);
360 }
361
362 auto field_xyz = solver_graph.register_edge("field_xyz", FieldRefs<Tvec>("", ""));
363 auto field_vxyz = solver_graph.register_edge("field_vxyz", FieldRefs<Tvec>("", ""));
364 auto field_axyz = solver_graph.register_edge("field_axyz", FieldRefs<Tvec>("", ""));
365 auto field_sizes = solver_graph.register_edge("field_sizes", Indexes<u32>("", ""));
366
367 auto set_field_xyz = solver_graph.register_node(
368 "set_field_xyz", NodeSetEdge<FieldRefs<Tvec>>([&](FieldRefs<Tvec> &field_xyz_edge) {
369 DDPatchDataFieldRef<Tvec> field_xyz_refs = {};
370 scheduler().for_each_patchdata_nonempty([&](const Patch p, PatchDataLayer &pdat) {
371 auto &field = pdat.get_field<Tvec>(0);
372 field_xyz_refs.add_obj(p.id_patch, std::ref(field));
373 });
374 field_xyz_edge.set_refs(field_xyz_refs);
375 }));
376 shambase::get_check_ref(set_field_xyz).set_edges(field_xyz);
377
378 auto set_field_vxyz = solver_graph.register_node(
379 "set_field_vxyz", NodeSetEdge<FieldRefs<Tvec>>([&](FieldRefs<Tvec> &field_vxyz_edge) {
380 DDPatchDataFieldRef<Tvec> field_vxyz_refs = {};
381 scheduler().for_each_patchdata_nonempty([&](const Patch p, PatchDataLayer &pdat) {
382 auto &field = pdat.get_field<Tvec>(ivxyz);
383 field_vxyz_refs.add_obj(p.id_patch, std::ref(field));
384 });
385 field_vxyz_edge.set_refs(field_vxyz_refs);
386 }));
387 shambase::get_check_ref(set_field_vxyz).set_edges(field_vxyz);
388
389 auto set_field_axyz = solver_graph.register_node(
390 "set_field_axyz", NodeSetEdge<FieldRefs<Tvec>>([&](FieldRefs<Tvec> &field_axyz_edge) {
391 DDPatchDataFieldRef<Tvec> field_axyz_refs = {};
392 scheduler().for_each_patchdata_nonempty([&](const Patch p, PatchDataLayer &pdat) {
393 auto &field = pdat.get_field<Tvec>(iaxyz);
394 field_axyz_refs.add_obj(p.id_patch, std::ref(field));
395 });
396 field_axyz_edge.set_refs(field_axyz_refs);
397 }));
398 shambase::get_check_ref(set_field_axyz).set_edges(field_axyz);
399
400 auto set_field_sizes = solver_graph.register_node(
401 "set_field_sizes", NodeSetEdge<Indexes<u32>>([&](Indexes<u32> &sizes) {
402 sizes.indexes = {};
403 scheduler().for_each_patchdata_nonempty([&](const Patch p, PatchDataLayer &pdat) {
404 sizes.indexes.add_obj(p.id_patch, pdat.get_obj_cnt());
405 });
406 }));
407 shambase::get_check_ref(set_field_sizes).set_edges(field_sizes);
408
409 add_ext_forces_seq.push_back(set_field_xyz);
410 add_ext_forces_seq.push_back(set_field_vxyz);
411 add_ext_forces_seq.push_back(set_field_axyz);
412 add_ext_forces_seq.push_back(set_field_sizes);
413
414 for (u32 i = 0; i < solver_config.ext_force_config.ext_forces.size(); i++) {
415
416 auto &var_force = solver_config.ext_force_config.ext_forces[i];
417
418 std::string prefix = shambase::format("ext_force_{}_", i);
419
420 if (EF_PointMass *ext_force = std::get_if<EF_PointMass>(&var_force.val)) {
421
422 } else if (EF_LenseThirring *ext_force = std::get_if<EF_LenseThirring>(&var_force.val)) {
423
424 std::string prefix_cmass = prefix + "cmass_";
425 std::string prefix_central_pos = prefix + "central_pos_";
426 std::string prefix_a_spin = prefix + "a_spin_";
427 std::string prefix_dir_spin = prefix + "dir_spin_";
428 std::string prefix_lt = prefix + "lt_";
429
430 auto set_cmass = register_constant_set<Tscal>(solver_graph, prefix_cmass, [&]() {
431 return ext_force->central_mass;
432 });
433
434 auto set_central_pos
435 = register_constant_set<Tvec>(solver_graph, prefix_central_pos, [&]() {
436 return Tvec{0, 0, 0}; // no support for offset yet
437 });
438
439 auto set_a_spin = register_constant_set<Tscal>(solver_graph, prefix_a_spin, [&]() {
440 return ext_force->a_spin;
441 });
442
443 auto set_dir_spin = register_constant_set<Tvec>(solver_graph, prefix_dir_spin, [&]() {
444 return ext_force->dir_spin;
445 });
446
447 auto add_force_lense_thirring = solver_graph.register_node(
449 shambase::get_check_ref(add_force_lense_thirring)
450 .set_edges(
451 solver_graph.get_edge_ptr<IDataEdge<Tscal>>("constant_G"),
452 solver_graph.get_edge_ptr<IDataEdge<Tscal>>("constant_c"),
453 solver_graph.get_edge_ptr<IDataEdge<Tscal>>(prefix_cmass),
454 solver_graph.get_edge_ptr<IDataEdge<Tvec>>(prefix_central_pos),
455 solver_graph.get_edge_ptr<IDataEdge<Tscal>>(prefix_a_spin),
456 solver_graph.get_edge_ptr<IDataEdge<Tvec>>(prefix_dir_spin),
457 solver_graph.get_edge_ptr<IFieldSpan<Tvec>>("field_xyz"),
458 solver_graph.get_edge_ptr<IFieldSpan<Tvec>>("field_vxyz"),
459 solver_graph.get_edge_ptr<Indexes<u32>>("field_sizes"),
460 solver_graph.get_edge_ptr<IFieldSpan<Tvec>>("field_axyz"));
461
462 add_ext_forces_seq.push_back(set_cmass);
463 add_ext_forces_seq.push_back(set_central_pos);
464 add_ext_forces_seq.push_back(set_a_spin);
465 add_ext_forces_seq.push_back(set_dir_spin);
466 add_ext_forces_seq.push_back(solver_graph.get_node_ptr_base(prefix_lt));
467
468 } else if (
469 EF_ShearingBoxForce *ext_force = std::get_if<EF_ShearingBoxForce>(&var_force.val)) {
470
471 std::string prefix_Omega_0 = prefix + "Omega_0_";
472 std::string prefix_q = prefix + "q_";
473 std::string prefix_shearing_box = prefix + "shearing_box_";
474
475 auto set_Omega_0 = register_constant_set<Tscal>(solver_graph, prefix_Omega_0, [&]() {
476 return ext_force->Omega_0;
477 });
478
479 auto set_q = register_constant_set<Tscal>(solver_graph, prefix_q, [&]() {
480 return ext_force->q;
481 });
482
483 auto add_force_shearing_box_non_inertial = solver_graph.register_node(
484 prefix_shearing_box,
486 shambase::get_check_ref(add_force_shearing_box_non_inertial)
487 .set_edges(
488 solver_graph.get_edge_ptr<IDataEdge<Tscal>>(prefix_Omega_0),
489 solver_graph.get_edge_ptr<IDataEdge<Tscal>>(prefix_q),
490 solver_graph.get_edge_ptr<IFieldSpan<Tvec>>("field_xyz"),
491 solver_graph.get_edge_ptr<IFieldSpan<Tvec>>("field_vxyz"),
492 solver_graph.get_edge_ptr<Indexes<u32>>("field_sizes"),
493 solver_graph.get_edge_ptr<IFieldSpan<Tvec>>("field_axyz"));
494
495 add_ext_forces_seq.push_back(set_Omega_0);
496 add_ext_forces_seq.push_back(set_q);
497 add_ext_forces_seq.push_back(solver_graph.get_node_ptr_base(prefix_shearing_box));
498
499 } else if (
500 EF_VerticalDiscPotential *ext_force
501 = std::get_if<EF_VerticalDiscPotential>(&var_force.val)) {
502 } else if (
503 EF_VelocityDissipation *ext_force
504 = std::get_if<EF_VelocityDissipation>(&var_force.val)) {
505 std::string prefix_eta = prefix + "eta_";
506 std::string prefix_velocity_dissipation = prefix + "velocity_dissipation_";
507
508 auto set_eta
509 = register_constant_set<Tscal>(solver_graph, prefix_eta, [eta = ext_force->eta]() {
510 return eta;
511 });
512
513 auto add_force_velocity_dissipation = solver_graph.register_node(
514 prefix_velocity_dissipation,
516 shambase::get_check_ref(add_force_velocity_dissipation)
517 .set_edges(
518 solver_graph.get_edge_ptr<IDataEdge<Tscal>>(prefix_eta),
519 solver_graph.get_edge_ptr<IFieldSpan<Tvec>>("field_vxyz"),
520 solver_graph.get_edge_ptr<Indexes<u32>>("field_sizes"),
521 solver_graph.get_edge_ptr<IFieldSpan<Tvec>>("field_axyz"));
522
523 add_ext_forces_seq.push_back(set_eta);
524 add_ext_forces_seq.push_back(
525 solver_graph.get_node_ptr_base(prefix_velocity_dissipation));
526
527 } else {
528 shambase::throw_unimplemented("this force is not handled, yet ...");
529 }
530 }
531
532 if (add_ext_forces_seq.size() > 0) {
533 OperationSequence seq("Add external forces", std::move(add_ext_forces_seq));
534 seq.evaluate();
535 }
536}
537
538template<class Tvec, template<class> class SPHKernel>
540
541 StackEntry stack_loc{};
542
543 Tscal gpart_mass = solver_config.gpart_mass;
544
545 using namespace shamrock;
546 using namespace shamrock::patch;
547
548 using SolverConfigExtForce = typename Config::ExtForceConfig;
549 using EF_PointMass = typename SolverConfigExtForce::PointMass;
550 using EF_LenseThirring = typename SolverConfigExtForce::LenseThirring;
551
552 PatchDataLayerLayout &pdl = scheduler().pdl_old();
553 const u32 ixyz = pdl.get_field_idx<Tvec>("xyz");
554 const u32 ivxyz = pdl.get_field_idx<Tvec>("vxyz");
555
556 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
557
558 sham::DeviceQueue &q = shambase::get_check_ref(dev_sched).get_queue();
559
560 for (auto var_force : solver_config.ext_force_config.ext_forces) {
561
562 Tvec pos_accretion;
563 Tscal Racc;
564
565 if (EF_PointMass *ext_force = std::get_if<EF_PointMass>(&var_force.val)) {
566 pos_accretion = {0, 0, 0};
567 Racc = ext_force->Racc;
568 } else if (EF_LenseThirring *ext_force = std::get_if<EF_LenseThirring>(&var_force.val)) {
569 pos_accretion = {0, 0, 0};
570 Racc = ext_force->Racc;
571 } else {
572 continue;
573 }
574
575 scheduler().for_each_patchdata_nonempty([&](Patch cur_p, PatchDataLayer &pdat) {
576 u32 Nobj = pdat.get_obj_cnt();
577
578 sham::DeviceBuffer<Tvec> &buf_xyz = pdat.get_field_buf_ref<Tvec>(ixyz);
579 sham::DeviceBuffer<Tvec> &buf_vxyz = pdat.get_field_buf_ref<Tvec>(ivxyz);
580
581 sycl::buffer<u32> not_accreted(Nobj);
582 sycl::buffer<u32> accreted(Nobj);
583
584 sham::EventList depends_list;
585 auto xyz = buf_xyz.get_read_access(depends_list);
586
587 auto e = q.submit(depends_list, [&](sycl::handler &cgh) {
588 sycl::accessor not_acc{not_accreted, cgh, sycl::write_only, sycl::no_init};
589 sycl::accessor acc{accreted, cgh, sycl::write_only, sycl::no_init};
590
591 Tvec r_sink = pos_accretion;
592 Tscal acc_rad2 = Racc * Racc;
593
594 shambase::parallel_for(cgh, Nobj, "check accretion", [=](i32 id_a) {
595 Tvec r = xyz[id_a] - r_sink;
596 bool not_accreted = sycl::dot(r, r) > acc_rad2;
597 not_acc[id_a] = (not_accreted) ? 1 : 0;
598 acc[id_a] = (!not_accreted) ? 1 : 0;
599 });
600 });
601
602 buf_xyz.complete_event_state(e);
603
604 std::tuple<std::optional<sycl::buffer<u32>>, u32> id_list_keep
605 = shamalgs::numeric::stream_compact(q.q, not_accreted, Nobj);
606
607 std::tuple<std::optional<sycl::buffer<u32>>, u32> id_list_accrete
608 = shamalgs::numeric::stream_compact(q.q, accreted, Nobj);
609
610 // sum accreted values onto sink
611
612 if (std::get<1>(id_list_accrete) > 0) {
613
614 u32 Naccrete = std::get<1>(id_list_accrete);
615
616 Tscal acc_mass = gpart_mass * Naccrete;
617
618 sham::DeviceBuffer<Tvec> pxyz_acc(Naccrete, dev_sched);
619
620 sham::EventList depends_list;
621
622 auto vxyz = buf_vxyz.get_read_access(depends_list);
623 auto accretion_p = pxyz_acc.get_write_access(depends_list);
624
625 auto e = q.submit(depends_list, [&, gpart_mass](sycl::handler &cgh) {
626 sycl::accessor id_acc{*std::get<0>(id_list_accrete), cgh, sycl::read_only};
627
628 shambase::parallel_for(
629 cgh, Naccrete, "compute sum momentum accretion", [=](i32 id_a) {
630 accretion_p[id_a] = gpart_mass * vxyz[id_acc[id_a]];
631 });
632 });
633
634 buf_vxyz.complete_event_state(e);
635 pxyz_acc.complete_event_state(e);
636
637 Tvec acc_pxyz = shamalgs::primitives::sum(dev_sched, pxyz_acc, 0, Naccrete);
638
639 logger::raw_ln("central potential accretion : += ", acc_mass);
640
641 pdat.keep_ids(*std::get<0>(id_list_keep), std::get<1>(id_list_keep));
642 }
643 });
644 }
645}
646
647using namespace shammath;
651
Adds the acceleration from a central gravitational potential (point mass).
Adds the Lense-Thirring force acceleration.
Adds the inertial part of the acceleration for a shearing box force.
Adds the non-inertial part of the acceleration for a shearing box force.
Adds the acceleration from a velocity dissipation force.
Adds the acceleration from a vertical disc potential.
constexpr const char * vxyz
3-velocity field
constexpr const char * xyz
Position field (3D coordinates)
Node that applies a custom function to modify connected edges.
Declare a class to register and retrieve nodes and edges from a unique container.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
std::int32_t i32
32 bit integer
A buffer allocated in USM (Unified Shared Memory)
void complete_event_state(sycl::event e) const
Complete the event state of the buffer.
T * get_write_access(sham::EventList &depends_list, SourceLocation src_loc=SourceLocation{})
Get a read-write pointer to the buffer's data.
const T * get_read_access(sham::EventList &depends_list, SourceLocation src_loc=SourceLocation{}) const
Get a read-only pointer to the buffer's data.
A SYCL queue associated with a device and a context.
sycl::queue q
The SYCL queue associated with this context.
sycl::event submit(Fct &&fct)
Submits a kernel to the SYCL queue.
DeviceQueue & get_queue(u32 id=0)
Get a reference to a DeviceQueue.
Class to manage a list of SYCL events.
Definition EventList.hpp:31
Represents a collection of objects distributed across patches identified by a u64 id.
iterator add_obj(u64 id, T &&obj)
Adds a new object to the collection.
void add_ext_forces()
add external forces to the particle acceleration, note that forces dependant on velocity shlould be a...
void compute_ext_forces_indep_v()
is ran once per timestep, it computes the forces that are independant of velocity
u32 get_field_idx(const std::string &field_name) const
Get the field id if matching name & type.
PatchDataLayer container class, the layout is described in patchdata_layout.
Interface for a solver graph edge representing a field as spans.
void evaluate()
Evaluate the node.
Definition INode.hpp:109
A node that applies a custom function to modify connected edges.
void set_edges(std::shared_ptr< IEdge > to_set)
Set the edges of the node.
A graph container for managing solver nodes and edges with type-safe access.
std::shared_ptr< INode > & get_node_ptr_base(const std::string &name)
Retrieve a node by name as a shared pointer to the base interface.
std::shared_ptr< T > get_edge_ptr(const std::string &name)
Get a typed shared pointer to an edge by name.
std::shared_ptr< T > register_edge(const std::string &name, T &&edge)
Register an edge with automatic type deduction and shared pointer creation.
std::shared_ptr< IEdge > & get_edge_ptr_base(const std::string &name)
Retrieve an edge by name as a shared pointer to the base interface.
std::shared_ptr< T > register_node(const std::string &name, T &&node)
Register a node with automatic type deduction and shared pointer creation.
T & get_node_ref(const std::string &name)
Get a typed reference to a node by name.
std::tuple< std::optional< sycl::buffer< u32 > >, u32 > stream_compact(sycl::queue &q, sycl::buffer< u32 > &buf_flags, u32 len)
Stream compaction algorithm.
Definition numeric.cpp:84
T sum(const sham::DeviceScheduler_ptr &sched, const sham::DeviceBuffer< T > &buf1, u32 start_id, u32 end_id)
Compute the sum of elements in a device buffer within a specified range.
namespace for basic c++ utilities
T & get_check_ref(const std::unique_ptr< T > &ptr, SourceLocation loc=SourceLocation())
Takes a std::unique_ptr and returns a reference to the object it holds. It throws a std::runtime_erro...
Definition memory.hpp:110
void throw_unimplemented(SourceLocation loc=SourceLocation{})
Throw a std::runtime_error saying that the function is unimplemented.
namespace for math utility
Definition AABB.hpp:26
namespace for the main framework
Definition __init__.py:1
sph kernels
Patch object that contain generic patch information.
Definition Patch.hpp:33