TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Discretisation_tools.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Discretisation_tools.h>
17#include <Check_espace_virtuel.h>
18#include <Champ_base.h>
19#include <Domaine_VF.h>
20#include <TRUSTTrav.h>
21#include <Device.h>
22#include <Debog.h>
23
25{
26 ToDo_Kokkos("critical for EF but not used in TRUST...");
27 const DoubleTab& tabHn=Hn.valeurs();
28 DoubleTab& tabHe=He.valeurs();
29 const Domaine_dis_base& domaine_dis_base=He.domaine_dis_base();
30
31 assert(tabHe.dimension_tot(0)==domaine_dis_base.nb_elem_tot());
32 assert(tabHn.dimension_tot(0)==domaine_dis_base.nb_som_tot());
33
34 const IntTab& les_elems=domaine_dis_base.domaine().les_elems();
35 int nb_som_elem=les_elems.dimension(1);
36 int nb_elem=domaine_dis_base.nb_elem();
37
38 tabHe=0;
39 for (int ele=0; ele<nb_elem; ele++)
40 {
41 for (int s=0; s<nb_som_elem; s++)
42 {
43 int sglob=les_elems(ele,s);
44 tabHe(ele)+=tabHn(sglob);
45 }
46 }
47 double inv_nb_som_elem=1./(nb_som_elem);
48 tabHe*=inv_nb_som_elem;
50}
52{
53 ToDo_Kokkos("critical for EF");
54 DoubleTab& tabHn=Hn.valeurs();
55 const DoubleTab& tabHe=He.valeurs();
56 Debog::verifier("elno entreee",tabHe);
57 assert_espace_virtuel_vect(tabHe);
58 const Domaine_dis_base& domaine_dis_base=He.domaine_dis_base();
59
60 assert(tabHe.dimension_tot(0)==domaine_dis_base.nb_elem_tot());
61 assert(tabHn.dimension_tot(0)==domaine_dis_base.nb_som_tot());
62
63 const IntTab& les_elems=domaine_dis_base.domaine().les_elems();
64 const DoubleVect& volumes=ref_cast(Domaine_VF,domaine_dis_base).volumes();
65
66 tabHn=0;
67 DoubleTrav vsom(tabHn.dimension_tot(0));
68 int nb_som_elem=les_elems.dimension(1);
69 int nb_elem_tot=domaine_dis_base.nb_elem_tot();
70 int N = tabHn.line_size();
71
72 for (int e = 0; e < nb_elem_tot; e++)
73 for (int s = 0, sglob; s < nb_som_elem && (sglob = les_elems(e, s)) >= 0; s++)
74 {
75 for (int n = 0; n < N; n++)
76 tabHn(sglob, n) += tabHe(e, n) * volumes(e);
77 vsom(sglob) += volumes(e);
78 }
79
80 for (int s = 0; s < domaine_dis_base.nb_som(); s++)
81 for (int n = 0; n < N; n++)
82 tabHn(s, n) /= vsom(s);
83
85 Debog::verifier("elno sortie",tabHn);
86}
88{
89 ToDo_Kokkos("critical but seems not used by TRUST...");
90 const DoubleTab& tabHf=Hf.valeurs();
91 DoubleTab& tabHe=He.valeurs();
92 const Domaine_dis_base& domaine_dis_base=He.domaine_dis_base();
93 const Domaine_VF& domaine_vf= ref_cast(Domaine_VF,domaine_dis_base);
94 assert(tabHe.dimension_tot(0)==domaine_dis_base.nb_elem_tot());
95 assert(tabHf.dimension_tot(0)==domaine_vf.nb_faces_tot());
96
97 const IntTab& elem_faces=domaine_vf.elem_faces();
98 int nb_face_elem=elem_faces.dimension(1);
99 int nb_elem=domaine_dis_base.nb_elem();
100
101 tabHe=0;
102 for (int ele=0; ele<nb_elem; ele++)
103 {
104 for (int s=0; s<nb_face_elem; s++)
105 {
106
107 tabHe(ele)+=tabHf(elem_faces(ele,s));
108 }
109 }
110 double inv_nb_face_elem=1./(nb_face_elem);
111 tabHe*=inv_nb_face_elem;
113}
114
115// Exemple of a dynamic kernel (can run on host or device)
116template<typename ExecSpace>
117void cells_to_faces_kernel(const Domaine_VF& domaine_vf, const DoubleTab& tabHe, DoubleTab& tab_vol_tot, DoubleTab& tabHf)
118{
119 static constexpr bool kernelOnDevice = !std::is_same<ExecSpace, Kokkos::DefaultHostExecutionSpace>::value;
120 int nb_elem_tot = domaine_vf.nb_elem_tot();
121 int nb_face_elem = domaine_vf.elem_faces().dimension(1);
122 auto elem_faces = domaine_vf.elem_faces().template view_ro<2, ExecSpace>();
123 auto volumes = domaine_vf.volumes().template view_ro<1, ExecSpace>();
124 auto He_v = static_cast<const ArrOfDouble&>(tabHe).template view_ro<1, ExecSpace>();
125 auto vol_tot = static_cast<ArrOfDouble&>(tab_vol_tot).template view_rw<1, ExecSpace>();
126 auto Hf_v = static_cast<ArrOfDouble&>(tabHf).template view_rw<1, ExecSpace>();
127 Kokkos::MDRangePolicy<ExecSpace, Kokkos::Rank<2>> policy({0, 0}, {nb_elem_tot, nb_face_elem});
128 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), policy, KOKKOS_LAMBDA(const int ele, const int s)
129 {
130 int face = elem_faces(ele, s);
131 double volume_elem = volumes(ele);
132 Kokkos::atomic_add(&Hf_v(face), He_v(ele) * volume_elem);
133 Kokkos::atomic_add(&vol_tot(face), volume_elem);
134 });
135 end_gpu_timer(__KERNEL_NAME__, kernelOnDevice);
136}
137
139{
140 DoubleTab& tabHf=Hf.valeurs();
141 const DoubleTab& tabHe=He.valeurs();
142 Debog::verifier("element_face entree",tabHe);
143 assert_espace_virtuel_vect(tabHe);
144 const Domaine_dis_base& domaine_dis_base=He.domaine_dis_base();
145 const Domaine_VF& domaine_vf= ref_cast(Domaine_VF,domaine_dis_base);
146 // in practice we do P1B to face
147 //assert(tabHe.dimension_tot(0)==domaine_dis_base.nb_elem_tot());
148 assert(tabHf.dimension_tot(0)==domaine_vf.nb_faces_tot());
149 const DoubleVect& volumes_entrelaces=domaine_vf.volumes_entrelaces();
150
151 tabHf=0;
152
153 // TODO : FIXME
154 // XXX : inconsistent coding... to check: volumes ou volumes_entrelaces ???
155 if (tabHe.line_size() == 1)
156 {
157 DoubleTrav tab_vol_tot(tabHf);
158 // Launch this multi-discretization kernel and copy data according to conditions (both arrays must already be on the device)
159 bool kernelOnDevice = tabHf.checkDataOnDevice(tabHe);
160 if (kernelOnDevice)
161 cells_to_faces_kernel<Kokkos::DefaultExecutionSpace>(domaine_vf, tabHe, tab_vol_tot, tabHf);
162 else
163 cells_to_faces_kernel<Kokkos::DefaultHostExecutionSpace>(domaine_vf, tabHe, tab_vol_tot, tabHf);
164
165 // Hf /= vol_tot
166 tab_divide_any_shape(tabHf, tab_vol_tot, VECT_REAL_ITEMS);
167 }
168 else
169 {
170 int nb_face_elem=domaine_vf.elem_faces().dimension(1);
171 int nb_elem_tot=domaine_dis_base.nb_elem_tot();
172 const IntTab& elem_faces = domaine_vf.elem_faces();
173 const DoubleVect& volumes = domaine_vf.volumes();
174 ToDo_Kokkos("critical");
175 // TODO : factorize these cases ...
176 if (tabHf.nb_dim()==1)
177 {
178 // VDF
179 double coeffb=1;
180 double coeffi=2;
181 assert(domaine_vf.que_suis_je()=="Domaine_VDF");
182 for (int ele=0; ele<nb_elem_tot; ele++)
183 for (int s=0; s<nb_face_elem; s++)
184 {
185 int face=elem_faces(ele,s);
186 for (int r = 0; r < domaine_vf.dimension; r++)
187 {
188 // Change of basis N.K.N, with N the normal of the face, and K the tensorial coefficient to get the value of the diffusivity
189 // on the direction of the surface normal.
190 double normOnSurf = domaine_vf.face_normales(face, r) / domaine_vf.face_surfaces(face);
191 tabHf(face) += tabHe(ele, r) * normOnSurf * normOnSurf * volumes(ele);
192 }
193 }
194 for (int f=0; f<domaine_vf.premiere_face_int(); f++)
195 tabHf(f)/=volumes_entrelaces(f)*coeffb;
196 for (int f=domaine_vf.premiere_face_int(); f<domaine_vf.nb_faces(); f++)
197 tabHf(f)/=volumes_entrelaces(f)*coeffi;
198 }
199 else
200 {
201 double coeffb=nb_face_elem;
202 double coeffi=coeffb;
203 int nb_comp=tabHf.dimension(1);
204 for (int ele=0; ele<nb_elem_tot; ele++)
205 for (int s=0; s<nb_face_elem; s++)
206 {
207 int face=elem_faces(ele,s);
208 for (int comp=0; comp<nb_comp; comp++)
209 tabHf(face,comp)+=tabHe(ele,comp)*volumes(ele);
210 }
211
212 for (int f=0; f<domaine_vf.premiere_face_int(); f++)
213 for (int comp=0; comp<nb_comp; comp++)
214 tabHf(f,comp)/=volumes_entrelaces(f)*coeffb;
215 for (int f=domaine_vf.premiere_face_int(); f<domaine_vf.nb_faces(); f++)
216 for (int comp=0; comp<nb_comp; comp++)
217 tabHf(f,comp)/=volumes_entrelaces(f)*coeffi;
218 }
219 }
221 Debog::verifier("element_face sortie",tabHf);
222}
223
224void Discretisation_tools::cells_to_faces(const Domaine_VF& domaine_vf, const DoubleTab& tab_elem, DoubleTab& tab_face)
225{
226 const int nb_face_elem = domaine_vf.elem_faces().line_size(), nb_comp = tab_face.line_size();
227
228 assert(tab_elem.dimension_tot(0) == domaine_vf.nb_elem_tot() && tab_face.dimension_tot(0) == domaine_vf.nb_faces_tot());
229 assert(tab_elem.line_size() == nb_comp);
230 if (domaine_vf.que_suis_je() != "Domaine_VEF")
231 Process::exit("Discretisation_tools::cells_to_faces limited to VEF."); // TODO FIXME
232
233 tab_face = 0.;
234 int nb_elem_tot = domaine_vf.nb_elem_tot();
235 auto elem_faces = domaine_vf.elem_faces().view_ro();
236 auto volumes = domaine_vf.volumes().view_ro();
237 auto tab_elem_v = tab_elem.view_ro();
238 auto tab_face_v = tab_face.view_rw();
239 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_2D({0, 0}, {nb_elem_tot, nb_face_elem}), KOKKOS_LAMBDA(const int ele, const int s)
240 {
241 int face = elem_faces(ele, s);
242 double volume_elem = volumes(ele);
243 for (int comp = 0; comp < nb_comp; comp++)
244 Kokkos::atomic_add(&tab_face_v(face, comp), tab_elem_v(ele, comp) * volume_elem);
245 });
246 end_gpu_timer(__KERNEL_NAME__);
247
248 CDoubleArrView volumes_entrelaces = domaine_vf.volumes_entrelaces().view_ro();
249 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_2D({0, 0}, {domaine_vf.nb_faces(), nb_comp}), KOKKOS_LAMBDA(const int f, const int comp)
250 {
251 tab_face_v(f, comp) /= volumes_entrelaces(f) * nb_face_elem;
252 });
253 end_gpu_timer(__KERNEL_NAME__);
254
255 // tab_face /= volumes_entrelaces * nb_face_elem :
256 // PL: does not understand, discrepancies on thermal_coupling_on_coincident_domain_jddX cases with:
257 // tab_face*=nb_face_elem;
258 // tab_divide_any_shape(tab_face, volumes_entrelaces, VECT_REAL_ITEMS);
259 tab_face.echange_espace_virtuel();
260}
261
262void Discretisation_tools::faces_to_cells(const Domaine_VF& domaine_vf, const DoubleTab& tab_face, DoubleTab& tab_elem)
263{
264 const int nb_face_elem = domaine_vf.elem_faces().dimension(1), nb_elem = domaine_vf.nb_elem(), nb_comp = tab_face.line_size();
265 assert(tab_elem.dimension_tot(0) == domaine_vf.nb_elem_tot() && tab_face.dimension_tot(0) == domaine_vf.nb_faces_tot());
266 assert(tab_elem.line_size() == nb_comp);
267
268 tab_elem = 0;
269
270 CIntTabView elem_faces = domaine_vf.elem_faces().view_ro();
271 CDoubleTabView face = tab_face.view_ro();
272 DoubleTabView elem = tab_elem.view_rw();
273 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_2D({0, 0}, {nb_elem, nb_comp}), KOKKOS_LAMBDA(const int ele, const int comp)
274 {
275 double sum = 0.;
276 for (int s = 0; s < nb_face_elem; s++)
277 sum += face(elem_faces(ele, s), comp);
278 elem(ele, comp) = sum;
279 });
280 end_gpu_timer(__KERNEL_NAME__);
281
282 double inv_nb_face_elem = 1. / nb_face_elem;
283 tab_elem *= inv_nb_face_elem;
284
285 tab_elem.echange_espace_virtuel();
286}
virtual DoubleTab & valeurs()=0
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
virtual const Domaine_dis_base & domaine_dis_base() const
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
static void cells_to_faces(const Champ_base &He, Champ_base &Hf)
static void nodes_to_cells(const Champ_base &Hn, Champ_base &He)
static void faces_to_cells(const Champ_base &Hf, Champ_base &He)
static void cells_to_nodes(const Champ_base &He, Champ_base &Hn)
IntTab_t & les_elems()
Definition Domaine.h:129
class Domaine_VF
Definition Domaine_VF.h:44
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
int nb_faces() const
Returns the total number of faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_tot() const
Returns the total number of faces.
Definition Domaine_VF.h:481
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
double volumes(int i) const
Definition Domaine_VF.h:113
int elem_faces(int i, int j) const
Returns the index of the i-th face of element num_elem; the face numbering convention is.
Definition Domaine_VF.h:542
int premiere_face_int() const
A face is internal if and only if it separates two elements.
Definition Domaine_VF.h:463
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
int nb_elem_tot() const
const Domaine & domaine() const
int nb_som_tot() const
static int dimension
Definition Objet_U.h:94
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
int nb_dim() const
Definition TRUSTTab.h:199
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, ConstView< _TYPE_, _SHAPE_ > > view_ro() const
Definition TRUSTTab.h:261
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, View< _TYPE_, _SHAPE_ > > view_rw()
Definition TRUSTTab.h:291
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
int line_size() const
Definition TRUSTVect.tpp:67
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")