Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
NodeMonofluidTVIAddSourceTerm.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#pragma once
11
18
20#include "shambackends/math.hpp"
21#include "shambackends/vec.hpp"
27#include <experimental/mdspan>
28
29#define NODE_EDGES(X_RO, X_RW) \
30 /* counts */ \
31 X_RO(shamrock::solvergraph::Indexes<u32>, part_counts) \
32 X_RO(shamrock::solvergraph::ScalarEdge<Tscal>, rhodust_eps) \
33 \
34 /* fields */ \
35 X_RO(shamrock::solvergraph::IFieldSpan<Tscal>, S) \
36 X_RO(shamrock::solvergraph::IFieldSpan<Tscal>, s_j) \
37 \
38 /* outputs */ \
39 X_RW(shamrock::solvergraph::IFieldSpan<Tscal>, ds_j_dt)
40
42
43 template<class Tvec>
44 class NodeMonofluidTVIAddSourceTerm : public shamrock::solvergraph::INode {
45
46 using Tscal = shambase::VecComponent<Tvec>;
47
48 u32 nbins;
49
50 public:
51 NodeMonofluidTVIAddSourceTerm(u32 nbins) : nbins(nbins) {}
52
53 EXPAND_NODE_EDGES(NODE_EDGES)
54
56
58
59 auto edges = get_edges();
60
61 edges.S.check_sizes(edges.part_counts.indexes);
62 edges.s_j.check_sizes(edges.part_counts.indexes);
63 edges.ds_j_dt.check_sizes(edges.part_counts.indexes);
64
65 auto rhodust_eps = edges.rhodust_eps.value;
66
67 shambase::DistributedData<u32> counts = edges.part_counts.indexes.template map<u32>(
68 [nbins = this->nbins](u64 /**/, u32 count) -> u32 {
69 return count * nbins;
70 });
71
73 shamsys::instance::get_compute_scheduler_ptr(),
74 sham::DDMultiRef{edges.S.get_spans(), edges.s_j.get_spans()},
75 sham::DDMultiRef{edges.ds_j_dt.get_spans()},
76 counts,
77 [rhodust_eps](
78 u32 id,
79 const Tscal *__restrict S,
80 const Tscal *__restrict s_j,
81 Tscal *__restrict ds_j_dt) {
82 auto sj = s_j[id];
83
84 Tscal ds_j_dt_val = 0;
85
86 if (sj * sj > rhodust_eps) {
87 ds_j_dt_val = S[id] / (2 * sham::abs(sj));
88 } else {
89 // we need this trick otherwise the bin would never start to get filled
90 // because of the cuttof, so the trick is to add the threshold in the
91 // denominator. yeah dirty i know i know ...
92 ds_j_dt_val = S[id] / (2 * (sham::abs(sj) + sycl::sqrt(rhodust_eps)));
93 }
94
95 ds_j_dt[id] += ds_j_dt_val;
96 });
97 }
98
99 inline virtual std::string _impl_get_label() const {
100 return "NodeMonofluidTVIAddSourceTerm";
101 };
102
103 inline virtual std::string _impl_get_tex() const {
104
105 auto S_edge = get_ro_edge_base(2).get_tex_symbol();
106 auto s_j_edge = get_ro_edge_base(3).get_tex_symbol();
107 auto ds_j_dt_edge = get_rw_edge_base(0).get_tex_symbol();
108 auto rhodust_eps_edge = get_ro_edge_base(1).get_tex_symbol();
109 auto part_counts_edge = get_ro_edge_base(0).get_tex_symbol();
110
111 std::string tex = R"tex(
112 Monofluid TVI: dust-density source term $\rightarrow$ ${s_j}$ time derivative
113
114 Per gas particle $a$ and mass bin $j$ (monofluid: $\rho_{{\rm d},j,a} = {s_j}_{j,a}^2$):
115
116 \begin{align}
117 \rho_{{\rm d},j,a} &= {s_j}_{j,a}^2 \\
118 {S}_{j,a} &= \text{dust density source term } (\mathrm{d}\rho_{{\rm d},j,a}/\mathrm{d}t) \\
119 \delta_{j,a} &= \begin{cases}
120 {S}_{j,a} / (2 |{s_j}_{j,a}|) & |{s_j}_{j,a}|^2 > \rho_{\rm eps} \\
121 {S}_{j,a} / \bigl(2 (|{s_j}_{j,a}| + \sqrt{\rho_{\rm eps}})\bigr) & \text{otherwise}
122 \end{cases} \\
123 {ds_j_dt}_{j,a} &\mathrel{+}= \delta_{j,a}
124 \end{align}
125
126 Unsaturated: $\mathrm{d}{s_j}_{j,a}^2/\mathrm{d}t = {S}_{j,a}
127 \Rightarrow \mathrm{d}{s_j}_{j,a}/\mathrm{d}t = {S}_{j,a}/(2|{s_j}_{j,a}|)$.
128 The floor ($\sqrt{\rho_{\rm eps}}$ in the denominator) lets bins with $|{s_j}_{j,a}|^2 \le \rho_{\rm eps}$ start accumulating.
129
130 $a \in [0, {part_counts})$, $j \in [0, N_{\rm bins})$,
131 $\rho_{\rm eps} = {rhodust_eps}$, $N_{\rm bins} = {nbins}$
132 )tex";
133
134 shambase::replace_all(tex, "{S}", S_edge);
135 shambase::replace_all(tex, "{s_j}", s_j_edge);
136 shambase::replace_all(tex, "{ds_j_dt}", ds_j_dt_edge);
137 shambase::replace_all(tex, "{rhodust_eps}", rhodust_eps_edge);
138 shambase::replace_all(tex, "{part_counts}", part_counts_edge);
139 shambase::replace_all(tex, "{nbins}", shambase::format("{}", nbins));
140
141 return tex;
142 }
143 };
144} // namespace shammodels::sph::modules
145
146#undef NODE_EDGES
Header file describing a Node Instance.
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
Represents a collection of objects distributed across patches identified by a u64 id.
virtual std::string _impl_get_tex() const
get the tex of the node
virtual std::string _impl_get_label() const
get the label of the node
Inode is node between data edges, takes multiple inputs, multiple outputs.
Definition INode.hpp:30
IEdge & get_rw_edge_base(int slot)
Get a reference to a read write edge and cast it to the type IEdge.
Definition INode.hpp:100
const IEdge & get_ro_edge_base(int slot)
Get a reference to a read only edge.
Definition INode.hpp:91
void distributed_data_kernel_call(sham::DeviceScheduler_ptr dev_sched, RefIn in, RefOut in_out, const shambase::DistributedData< index_t > &thread_counts, Functor &&func)
A variant of sham::kernel_call for distributed data.
void replace_all(std::string &inout, std::string_view what, std::string_view with)
replace all occurence of a search string with another
Definition string.hpp:110
namespace for the sph model modules
#define __shamrock_stack_entry()
Macro to create a stack entry.
A variant of sham::MultiRef for distributed data.