37#define NODE_EDGES(X_RO, X_RW) \
39 X_RO(shamrock::solvergraph::IDataEdge<Tscal>, constant_G) \
40 X_RO(shamrock::solvergraph::IDataEdge<Tscal>, gpart_mass) \
43 X_RO(shamrock::solvergraph::Indexes<u32>, part_counts) \
44 X_RO(shamrock::solvergraph::IFieldSpan<Tvec>, positions) \
47 X_RO(shamrock::solvergraph::IDataEdge<std::vector<Tvec>>, sink_positions) \
48 X_RO(shamrock::solvergraph::IDataEdge<std::vector<Tscal>>, sink_mass) \
49 X_RO(shamrock::solvergraph::IDataEdge<std::vector<Tscal>>, sink_accr_radii) \
52 X_RW(shamrock::solvergraph::IFieldSpan<Tvec>, accel_ext) \
53 X_RW(shamrock::solvergraph::IDataEdge<std::vector<Tvec>>, sink_acc_sph)
67 using Tscal = shambase::VecComponent<Tvec>;
70 SinkParticlesAddSPHForces() =
default;
74 void _impl_evaluate_internal();
76 inline virtual std::string _impl_get_label()
const {
return "SinkParticlesAddSPHForces"; }
78 virtual std::string _impl_get_tex()
const;
82 void SinkParticlesAddSPHForces<Tvec>::_impl_evaluate_internal() {
86 auto edges = get_edges();
88 auto dev_sched = shamsys::instance::get_compute_scheduler_ptr();
91 Tscal G = edges.constant_G.data;
92 Tscal gpart_mass = edges.gpart_mass.data;
94 const std::vector<Tvec> &sink_positions = edges.sink_positions.data;
95 const std::vector<Tscal> &sink_mass = edges.sink_mass.data;
96 const std::vector<Tscal> &sink_accr_radii = edges.sink_accr_radii.data;
97 std::vector<Tvec> &sink_acc_sph = edges.sink_acc_sph.data;
99 size_t sink_count = sink_positions.size();
101 if (sink_mass.size() != sink_count || sink_accr_radii.size() != sink_count
102 || sink_acc_sph.size() != sink_count) {
104 "sink edges size mismatch: pos={}, mass={}, accretion_radius={}, acc_sph={}",
107 sink_accr_radii.size(),
108 sink_acc_sph.size()));
111 edges.positions.check_sizes(edges.part_counts.indexes);
112 edges.accel_ext.check_sizes(edges.part_counts.indexes);
114 auto &pos_spans = edges.positions.get_spans();
115 auto &accel_ext_spans = edges.accel_ext.get_spans();
119 std::vector<Tvec> result_acc_sinks{};
121 for (
size_t sink_id = 0; sink_id < sink_count; sink_id++) {
123 Tvec sph_acc_sink = {};
125 Tscal s_mass = sink_mass[sink_id];
126 Tscal s_racc = sink_accr_radii[sink_id];
127 Tvec s_pos = sink_positions[sink_id];
129 edges.part_counts.indexes.for_each([&](
u64 id_patch,
u32 part_count) {
130 buf_sync_axyz.resize(part_count);
137 [s_pos, G, s_mass, s_racc, gpart_mass](
139 const Tvec *__restrict
xyz,
140 Tvec *__restrict axyz_ext,
141 Tvec *__restrict axyz_sync) {
142 Tvec r_a =
xyz[id_a];
144 Tvec delta = r_a - s_pos;
145 Tscal d = sycl::length(delta);
147 Tvec force = G * delta / (d * d * d);
156 axyz_sync[id_a] = force * gpart_mass;
157 axyz_ext[id_a] += -force * s_mass;
163 result_acc_sinks.push_back(sph_acc_sink);
166 std::vector<Tvec> gathered_result_acc_sinks{};
168 result_acc_sinks, gathered_result_acc_sinks, MPI_COMM_WORLD);
170 for (
size_t id_s = 0; id_s < sink_count; id_s++) {
172 sink_acc_sph[id_s] = {};
175 sink_acc_sph[id_s] += gathered_result_acc_sinks[rid * sink_count + id_s];
181 std::string SinkParticlesAddSPHForces<Tvec>::_impl_get_tex()
const {
183 auto constant_G = get_ro_edge_base(0).get_tex_symbol();
184 auto gpart_mass = get_ro_edge_base(1).get_tex_symbol();
185 auto positions = get_ro_edge_base(3).get_tex_symbol();
186 auto sink_positions = get_ro_edge_base(4).get_tex_symbol();
187 auto sink_mass = get_ro_edge_base(5).get_tex_symbol();
188 auto sink_accr_radii = get_ro_edge_base(6).get_tex_symbol();
189 auto axyz_ext = get_rw_edge_base(0).get_tex_symbol();
190 auto sink_acc_sph = get_rw_edge_base(1).get_tex_symbol();
192 std::string tex = R
"tex(
193 Add sink / SPH particles gravitational interaction
196 {\bf f}_{a,s} &= {constant_G} \frac{{positions}_a - {sink_positions}_s}{\vert {positions}_a - {sink_positions}_s \vert^3}
197 \quad (0 \text{ if } \vert {positions}_a - {sink_positions}_s \vert < {sink_accr_radii}_s) \\
198 {axyz_ext}_a &\mathrel{+}= - \sum_s {sink_mass}_s {\bf f}_{a,s} \\
199 {sink_acc_sph}_s &= \sum_a {gpart_mass} {\bf f}_{a,s}
219template<
class Tvec,
template<
class>
class SPHKernel>
220void shammodels::sph::modules::SinkParticlesUpdate<Tvec, SPHKernel>::compute_sph_forces() {
224 auto &sync = scheduler().synchronized_data;
225 if (!has_sinks<Tvec>(sync)) {
230 using namespace shamrock::patch;
231 using namespace shamrock::solvergraph;
238 auto part_counts = Indexes<u32>::make_shared(
"part_counts",
"N_{\\rm part}");
239 auto xyz_refs = FieldRefs<Tvec>::make_shared(
"xyz",
"\\mathbf{r}");
240 auto axyz_ext_refs = FieldRefs<Tvec>::make_shared(
"axyz_ext",
"\\mathbf{a}_{\\rm ext}");
248 xyz_field_refs.
add_obj(p.id_patch, std::ref(pdat.get_field<Tvec>(ixyz)));
249 axyz_ext_field_refs.
add_obj(p.id_patch, std::ref(pdat.get_field<Tvec>(iaxyz_ext)));
252 xyz_refs->set_refs(xyz_field_refs);
253 axyz_ext_refs->set_refs(axyz_ext_field_refs);
255 auto constant_G = IDataEdge<Tscal>::make_shared(
"constant_G",
"G");
256 auto gpart_mass = IDataEdge<Tscal>::make_shared(
"gpart_mass",
"m_{\\rm part}");
257 constant_G->data = solver_config.get_constant_G();
258 gpart_mass->data = solver_config.gpart_mass;
262 = sync.template get_edge_ptr<IDataEdgeSerializable<std::vector<Tvec>>>(
"sink_pos");
264 = sync.template get_edge_ptr<IDataEdgeSerializable<std::vector<Tscal>>>(
"sink_mass");
265 auto sink_accr_radii = sync.template get_edge_ptr<IDataEdgeSerializable<std::vector<Tscal>>>(
266 "sink_accretion_radius");
268 = sync.template get_edge_ptr<IDataEdgeSerializable<std::vector<Tvec>>>(
"sink_acc_sph");
270 SinkParticlesAddSPHForces<Tvec> add_sph_forces{};
271 add_sph_forces.set_edges(
281 add_sph_forces.evaluate();
#define NODE_EDGES(X_RO, X_RW)
declare the list of edges for this node
constexpr const char * xyz
Position field (3D coordinates).
constexpr const char * part_counts
Particle counts per patch.
shambase::DistributedData< PatchDataFieldRef< T > > DDPatchDataFieldRef
Alias for a DistributedData of PatchDataFieldRefs.
Header file describing a Node Instance.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
A buffer allocated in USM (Unified Shared Memory).
A SYCL queue associated with a device and a context.
iterator add_obj(u64 id, T &&obj)
Adds a new object to the collection.
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.
u32 get_obj_cnt() const
get the number of objects (particles) stored in this layer
Inode is node between data edges, takes multiple inputs, multiple outputs.
This header file contains utility functions related to exception handling in the code.
std::vector< int > vector_allgatherv(const std::vector< T > &send_vec, const MPI_Datatype &send_type, std::vector< T > &recv_vec, const MPI_Datatype &recv_type, const MPI_Comm comm)
allgatherv on vector with size query (size querying variant of vector_allgatherv_ks) //TODO add fault...
void kernel_call(sham::DeviceQueue &q, RefIn in, RefOut in_out, u32 n, Functor &&func, SourceLocation &&callsite=SourceLocation{})
Submit a kernel to a SYCL queue.
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.
void replace_all(std::string &inout, std::string_view what, std::string_view with)
replace all occurence of a search string with another
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...
ExcptTypes make_except_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Create an exception with a message and a location.
i32 world_size()
Gives the size of the MPI communicator.
namespace for math utility
namespace for the main framework
Helpers to access SPH sink particles stored as SoA synchronized data edges.
#define __shamrock_stack_entry()
Macro to create a stack entry.
shambase::details::BasicStackEntry StackEntry
Alias for shambase::details::BasicStackEntry.
A class that references multiple buffers or similar objects.
Patch object that contain generic patch information.
Functions related to the MPI communicator.