TRUST 1.9.8
HPC thermohydraulic platform
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 // en realite on fait P1B vers 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 : codage pas coherent... a voir : volumes ou volumes_entrelaces ???
155 if (tabHe.line_size() == 1)
156 {
157 DoubleTrav tab_vol_tot(tabHf);
158 // Lancement de ce kernel multi-discretisation et copie de donnees selon conditions (les deux tableaux doivent etre deja sur le 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: comprends pas, ecarts sur les cas thermal_coupling_on_coincident_domain_jddX avec:
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
classe Champ_base Cette classe est la base de la hierarchie des champs.
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
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int nb_faces_tot() const
renvoie le nombre total de 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
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
int nb_elem_tot() const
const Domaine & domaine() const
int nb_som_tot() const
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
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")