Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
NodeMonofluidTVAAddSourceTerm.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 X_RO(shamrock::solvergraph::ScalarEdge<Tscal>, dt_hydro) \
34 \
35 /* fields */ \
36 X_RO(shamrock::solvergraph::IFieldSpan<Tscal>, S) \
37 X_RO(shamrock::solvergraph::IFieldSpan<Tscal>, s_j) \
38 \
39 /* outputs */ \
40 X_RW(shamrock::solvergraph::IFieldSpan<Tscal>, ds_j_dt)
41
43
44 template<class Tvec>
45 class NodeMonofluidTVAAddSourceTerm : public shamrock::solvergraph::INode {
46
47 using Tscal = shambase::VecComponent<Tvec>;
48
49 u32 nbins;
50
51 public:
52 NodeMonofluidTVAAddSourceTerm(u32 nbins) : nbins(nbins) {}
53
54 EXPAND_NODE_EDGES(NODE_EDGES)
55
57
59
60 auto edges = get_edges();
61
62 edges.S.check_sizes(edges.part_counts.indexes);
63 edges.s_j.check_sizes(edges.part_counts.indexes);
64 edges.ds_j_dt.check_sizes(edges.part_counts.indexes);
65
66 auto rhodust_eps = edges.rhodust_eps.value;
67
68 shambase::DistributedData<u32> counts = edges.part_counts.indexes.template map<u32>(
69 [nbins = this->nbins](u64 /**/, u32 count) -> u32 {
70 return count * nbins;
71 });
72
73 auto epsilon = sycl::sqrt(rhodust_eps);
74 auto dt_hydro = edges.dt_hydro.value;
75
77 shamsys::instance::get_compute_scheduler_ptr(),
78 sham::DDMultiRef{edges.S.get_spans(), edges.s_j.get_spans()},
79 sham::DDMultiRef{edges.ds_j_dt.get_spans()},
80 counts,
81 [rhodust_eps, epsilon, dt_hydro, nbins = this->nbins](
82 u32 id,
83 const Tscal *__restrict S,
84 const Tscal *__restrict s_j,
85 Tscal *__restrict ds_j_dt) {
86 Tscal sj = s_j[id];
87
88 Tscal ds_j_dt_val = S[id] / (2 * (sham::abs(sj) + epsilon));
89
90 if (sham::abs(dt_hydro * ds_j_dt_val) > 1e-2 * sham::abs(sj) || dt_hydro == 0) {
91 // here there is high likelihood of overshoot, so we go semi implicit
92 Tscal s_next = sycl::sqrt(sj * sj + S[id] * dt_hydro);
93 ds_j_dt_val = (dt_hydro > 0) ? (s_next - sj) / dt_hydro : 0;
94 }
95
96 ds_j_dt[id] += ds_j_dt_val;
97 });
98 }
99
100 inline virtual std::string _impl_get_label() const {
101 return "NodeMonofluidTVAAddSourceTerm";
102 };
103
104 inline virtual std::string _impl_get_tex() const {
105
106 auto S_edge = get_ro_edge_base(2).get_tex_symbol();
107 auto s_j_edge = get_ro_edge_base(3).get_tex_symbol();
108 auto ds_j_dt_edge = get_rw_edge_base(0).get_tex_symbol();
109 auto rhodust_eps_edge = get_ro_edge_base(1).get_tex_symbol();
110 auto part_counts_edge = get_ro_edge_base(0).get_tex_symbol();
111
112 std::string tex = R"tex(
113 Monofluid TVA: dust-density source term $\rightarrow$ ${s_j}$ time derivative
114
115 Per gas particle $a$ and mass bin $j$ (monofluid: $\rho_{{\rm d},j,a} = {s_j}_{j,a}^2$):
116
117 \begin{align}
118 \rho_{{\rm d},j,a} &= {s_j}_{j,a}^2 \\
119 {S}_{j,a} &= \text{dust density source term } (\mathrm{d}\rho_{{\rm d},j,a}/\mathrm{d}t) \\
120 \delta_{j,a} &= \begin{cases}
121 {S}_{j,a} / (2 |{s_j}_{j,a}|) & |{s_j}_{j,a}|^2 > \rho_{\rm eps} \\
122 {S}_{j,a} / \bigl(2 (|{s_j}_{j,a}| + \sqrt{\rho_{\rm eps}})\bigr) & \text{otherwise}
123 \end{cases} \\
124 {ds_j_dt}_{j,a} &\mathrel{+}= \delta_{j,a}
125 \end{align}
126
127 Unsaturated: $\mathrm{d}{s_j}_{j,a}^2/\mathrm{d}t = {S}_{j,a}
128 \Rightarrow \mathrm{d}{s_j}_{j,a}/\mathrm{d}t = {S}_{j,a}/(2|{s_j}_{j,a}|)$.
129 The floor ($\sqrt{\rho_{\rm eps}}$ in the denominator) lets bins with $|{s_j}_{j,a}|^2 \le \rho_{\rm eps}$ start accumulating.
130
131 $a \in [0, {part_counts})$, $j \in [0, N_{\rm bins})$,
132 $\rho_{\rm eps} = {rhodust_eps}$, $N_{\rm bins} = {nbins}$
133 )tex";
134
135 shambase::replace_all(tex, "{S}", S_edge);
136 shambase::replace_all(tex, "{s_j}", s_j_edge);
137 shambase::replace_all(tex, "{ds_j_dt}", ds_j_dt_edge);
138 shambase::replace_all(tex, "{rhodust_eps}", rhodust_eps_edge);
139 shambase::replace_all(tex, "{part_counts}", part_counts_edge);
140 shambase::replace_all(tex, "{nbins}", shambase::format("{}", nbins));
141
142 return tex;
143 }
144 };
145} // namespace shammodels::sph::modules
146
147#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:31
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:137
const IEdge & get_ro_edge_base(int slot)
Get a reference to a read only edge.
Definition INode.hpp:128
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.