TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Champ_implementation_P0.cpp
1/****************************************************************************
2* Copyright (c) 2025, 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 <Champ_implementation_P0.h>
17#include <Champ_Uniforme_Morceaux.h>
18#include <Champ_Fonc_Morceaux.h>
19#include <Champ_Don_Fonc_txyz.h>
20#include <Champ_Uniforme.h>
21#include <Champ_base.h>
22#include <Domaine.h>
23#include <Domaine_VF.h>
24
25DoubleVect& Champ_implementation_P0::valeur_a_elem(const DoubleVect& position, DoubleVect& result, int poly) const
26{
27 const Champ_base& ch_base = le_champ();
28 int nb_components = ch_base.nb_comp();
29 const DoubleTab& values = ch_base.valeurs();
30
31 assert(result.size() == nb_components);
32 assert(poly >= 0);
33 assert(poly < values.dimension_tot(0));
34 assert(values.nb_dim() == 2);
35 assert(values.dimension(1) == nb_components);
36
37 for (int i = 0; i < nb_components; i++) result(i) = values(poly, i);
38
39 return result;
40}
41
42double Champ_implementation_P0::valeur_a_elem_compo(const DoubleVect& position, int poly, int ncomp) const
43{
44 const Champ_base& ch_base = le_champ();
45 const DoubleTab& values = ch_base.valeurs();
46
47 assert(ncomp >= 0);
48 assert(ncomp < ch_base.nb_comp());
49 assert(poly >= 0);
50 assert(poly < values.dimension_tot(0));
51
52 double result = 0;
53
54 assert(values.line_size() == ch_base.nb_comp());
55 result = values(poly, ncomp);
56
57 return result;
58}
59
60/**
61 * @brief Computes field values at centers of gravity
62 * @param[in] dom Domain for computation (must match geometric domain)
63 * @param[in,out] tab_result Output table for computed values
64 * @return Reference to modified tab_result
65 * @throws Process::exit() if domain mismatch
66 */
67DoubleTab& Champ_implementation_P0::valeur_aux_centres_de_gravite(const Domaine& dom, DoubleTab& tab_result) const
68{
69 if (get_domaine_geom() != dom)
70 Process::exit("Error, you must use valeur_aux_centres_de_gravite() on the whole discretized mesh.");
71 int nb_polys = tab_result.dimension(0);
72 if (nb_polys == 0)
73 return tab_result;
74
75 const DoubleTab& tab_values = le_champ().valeurs();
76 // TODO : FIXME
77 // For FT the resize should be done in its good position and not here ...
78 if (tab_result.nb_dim() == 1) tab_result.resize(nb_polys, 1);
79 int nb_components = le_champ().nb_comp();
80 int nb_dim = tab_values.nb_dim();
81 int line_size = tab_result.line_size();
82 assert(tab_values.line_size() == nb_components);
83 assert(tab_values.line_size() == nb_components || nb_components == 1);
84 DoubleTabView result = tab_result.view_wo();
85 if (nb_dim == 1)
86 {
87 CDoubleArrView values = static_cast<const ArrOfDouble&>(tab_values).view_ro();
88 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_2D({0, 0}, {nb_polys, line_size}), KOKKOS_LAMBDA(const int i, const int j)
89 {
90 result(i, j) = values(i);
91 });
92 }
93 else
94 {
95 CDoubleTabView values = tab_values.view_ro();
96 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_2D({0, 0}, {nb_polys, line_size}),
97 KOKKOS_LAMBDA(const int i, const int j)
98 {
99 result(i, j) = values(i, (line_size == nb_components) * j);
100 });
101 }
102 end_gpu_timer(__KERNEL_NAME__);
103 return tab_result;
104}
105
106template<typename ExecSpace>
107void valeur_aux_elems_kernel(const DoubleTab& tab_values, const IntVect& tab_polys, DoubleTab& tab_result, int nb_components)
108{
109 int nb_polys = tab_polys.size();
110 int line_size = tab_result.line_size();
111 int nb_dim = tab_values.nb_dim();
112 auto polys = tab_polys.template view_ro<1, ExecSpace>();
113 auto result = tab_result.template view_wo<2, ExecSpace>();
114 Kokkos::RangePolicy<ExecSpace> policy(0, nb_polys);
115 if (nb_dim==1)
116 {
117 auto values = tab_values.template view_ro<1, ExecSpace>();
118 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), policy, KOKKOS_LAMBDA(const int i)
119 {
120 int cell = polys(i);
121 if (cell>=0)
122 for (int j = 0; j < line_size; j++)
123 result(i, j) = values(cell);
124 });
125 }
126 else
127 {
128 auto values = tab_values.template view_ro<2, ExecSpace>();
129 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), policy, KOKKOS_LAMBDA(const int i)
130 {
131 int cell = polys(i);
132 if (cell>=0)
133 for (int j = 0; j < line_size; j++)
134 result(i, j) = values(cell, (line_size == nb_components) * j);
135 });
136 }
137 static constexpr bool kernelOnDevice = !std::is_same<ExecSpace, Kokkos::DefaultHostExecutionSpace>::value;
138 end_gpu_timer(__KERNEL_NAME__, kernelOnDevice);
139}
140
141DoubleTab& Champ_implementation_P0::valeur_aux_elems(const DoubleTab& positions, const IntVect& tab_polys, DoubleTab& tab_result) const
142{
143 int nb_polys = tab_polys.size();
144 if (nb_polys == 0)
145 return tab_result;
146
147 const DoubleTab& tab_values = le_champ().valeurs();
148 // TODO : FIXME
149 // For FT the resize should be done in its good position and not here ...
150 if (tab_result.nb_dim() == 1) tab_result.resize(nb_polys, 1);
151 int nb_components = le_champ().nb_comp();
152 assert(tab_values.line_size() == nb_components);
153 assert(tab_values.line_size() == nb_components || nb_components == 1);
154
155 bool kernelOnDevice = tab_result.checkDataOnDevice(tab_values);
156 if (kernelOnDevice)
157 valeur_aux_elems_kernel<Kokkos::DefaultExecutionSpace>(tab_values, tab_polys, tab_result, nb_components);
158 else
159 valeur_aux_elems_kernel<Kokkos::DefaultHostExecutionSpace>(tab_values, tab_polys, tab_result, nb_components);
160 return tab_result;
161}
162
163template<typename ExecSpace>
164void valeur_aux_elems_compo_kernel(const DoubleTab& tab_values, const IntVect& tab_polys, DoubleVect& tab_result, int ncomp)
165{
166 int nb_polys = tab_polys.size();
167 auto polys = tab_polys.template view_ro<1, ExecSpace>();
168 auto values = tab_values.template view_ro<2, ExecSpace>();
169 auto result = tab_result.template view_wo<1, ExecSpace>();
170 Kokkos::RangePolicy<ExecSpace> policy(0, nb_polys);
171 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), policy, KOKKOS_LAMBDA(const int i)
172 {
173 int cell = polys(i);
174 if (cell>=0)
175 result(i) = values(cell, ncomp);
176 });
177 static constexpr bool kernelOnDevice = !std::is_same<ExecSpace, Kokkos::DefaultHostExecutionSpace>::value;
178 end_gpu_timer(__KERNEL_NAME__, kernelOnDevice);
179}
180
181DoubleVect& Champ_implementation_P0::valeur_aux_elems_compo(const DoubleTab& positions, const IntVect& tab_polys, DoubleVect& tab_result, int ncomp) const
182{
183 const DoubleTab& tab_values = le_champ().valeurs();
184
185 assert(ncomp >= 0);
186 assert(ncomp < le_champ().nb_comp());
187 assert(tab_result.size() == tab_polys.size());
188 assert(tab_values.line_size() == le_champ().nb_comp());
189
190 bool kernelOnDevice = tab_result.checkDataOnDevice(tab_values);
191 if (kernelOnDevice)
192 valeur_aux_elems_compo_kernel<Kokkos::DefaultExecutionSpace>(tab_values, tab_polys, tab_result, ncomp);
193 else
194 valeur_aux_elems_compo_kernel<Kokkos::DefaultHostExecutionSpace>(tab_values, tab_polys, tab_result, ncomp);
195
196 return tab_result;
197}
198
199DoubleTab& Champ_implementation_P0::remplir_coord_noeuds(DoubleTab& positions) const
200{
201 const Domaine& domaine = get_domaine_geom();
202 positions.resize(domaine.nb_elem(), Objet_U::dimension);
203 domaine.calculer_centres_gravite(positions);
204 return positions;
205}
206
207int Champ_implementation_P0::remplir_coord_noeuds_et_polys(DoubleTab& positions, IntVect& polys) const
208{
209 const Domaine& domaine = get_domaine_geom();
210 int nb_elem = domaine.nb_elem();
211 polys.resize(nb_elem);
212 remplir_coord_noeuds(positions);
213 ToDo_Kokkos("critical");
214 for (int i = 0; i < nb_elem; i++) polys(i) = i;
215 return 1;
216}
217
218DoubleTab& Champ_implementation_P0::valeur_aux_sommets_impl(DoubleTab& tab_result) const
219{
220 const Champ_base& ch_base = le_champ();
221 int nb_components = ch_base.nb_comp();
222 const DoubleTab& tab_values = ch_base.valeurs();
223 const Domaine& domaine = get_domaine_geom();
224 int nb_cells = domaine.nb_elem_tot();
225 int nb_nodes = domaine.nb_som();
226 int nb_nodes_per_cell = domaine.nb_som_elem();
227 assert((tab_result.dimension_tot(0) == nb_nodes) || (tab_result.dimension(0) == nb_nodes));
228 assert(tab_result.line_size() == nb_components);
229 assert(tab_values.line_size() == nb_components);
230 int nb_dim = tab_values.nb_dim();
231 IntTrav tab_count(nb_nodes);
232 tab_result = 0;
233 CIntTabView sommet_elem = domaine.les_elems().view_ro();
234 CDoubleTabView values = tab_values.view_ro();
235 IntArrView count = static_cast<ArrOfInt&>(tab_count).view_rw();
236 DoubleTabView result = tab_result.view_rw();
237 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), Kokkos::MDRangePolicy<Kokkos::Rank<2>>({0,0}, {nb_cells,nb_nodes_per_cell}), KOKKOS_LAMBDA(const int i, const int j)
238 {
239 int node = sommet_elem(i, j);
240 if (node >= 0 && node < nb_nodes)
241 {
242 Kokkos::atomic_add(&count[node], 1);
243 for (int k = 0; k < nb_components; k++)
244 Kokkos::atomic_add(&result(node, k), values(i, nb_dim == 1 ? 0 : k));
245 }
246 });
247 end_gpu_timer(__KERNEL_NAME__);
248 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_nodes, KOKKOS_LAMBDA(const int i)
249 {
250 for (int j = 0; j < nb_components; j++)
251 result(i, j) /= count[i];
252 });
253 end_gpu_timer(__KERNEL_NAME__);
254 return tab_result;
255}
256
257DoubleVect& Champ_implementation_P0::valeur_aux_sommets_compo_impl(DoubleVect& result, int ncomp) const
258{
259 const Champ_base& ch_base = le_champ();
260 const DoubleTab& values = ch_base.valeurs();
261
262 const Domaine& domaine = get_domaine_geom();
263 int nb_cells = domaine.nb_elem_tot();
264 int nb_nodes = domaine.nb_som();
265 int nb_nodes_per_cell = domaine.nb_som_elem();
266
267 ArrOfInt count(nb_nodes);
268 // dvq ajout result=0;
269 result = 0;
270 assert(ncomp >= 0);
271 assert(ncomp < ch_base.nb_comp());
272 assert(result.size() == nb_nodes);
273 assert(values.line_size() == ch_base.nb_comp());
274 ToDo_Kokkos("critical");
275 for (int i = 0; i < nb_cells; i++)
276 for (int j = 0; j < nb_nodes_per_cell; j++)
277 {
278 int node = domaine.sommet_elem(i, j);
279 if (node < nb_nodes)
280 {
281 count[node]++;
282 result(node) += values(i, ncomp);
283 }
284 }
285 for (int i = 0; i < nb_nodes; i++) result(i) /= count[i];
286
287 return result;
288}
289
291{
292 const Champ_base& cha = le_champ();
293 const Domaine& le_dom = get_domaine_geom();
294 int nb_elem_tot = le_dom.nb_elem_tot();
295 const DoubleTab& val = cha.valeurs();
296 int elem;
297 // On recalcule les centres de gravite :
298 DoubleTab pos_centre;
299 le_dom.calculer_centres_gravite(pos_centre);
300 os << nb_elem_tot << finl;
301 for (elem = 0; elem < nb_elem_tot; elem++)
302 {
303 if (Objet_U::dimension == 3)
304 os << pos_centre(elem, 0) << " " << pos_centre(elem, 1) << " " << pos_centre(elem, 2) << " ";
305 if (Objet_U::dimension == 2)
306 os << pos_centre(elem, 0) << " " << pos_centre(elem, 1) << " ";
307 os << val(elem, ncomp) << finl;
308 }
309 os << finl;
310 Cout << "Champ_P0_implementation::imprime_P0 END >>>>>>>>>> " << finl;
311 return 1;
312}
313
315{
316 // if (le_champ().a_un_domaine_dis_base() && ch.a_un_domaine_dis_base() && le_champ().domaine_dis_base()==ch.domaine_dis_base())
317 // Plus general en comparant le domaine:
318 // Ajout de Champ_Uniforme_Morceaux/Champ_Fonc_Morceaux/Champ_Don_Fonc_txyz qui sont aux elements
319 if (sub_type(Champ_Uniforme_Morceaux, ch) ||
320 sub_type(Champ_Fonc_Morceaux, ch) ||
321 sub_type(Champ_Don_Fonc_txyz, ch) ||
322 (le_champ().a_un_domaine_dis_base() && ch.a_un_domaine_dis_base() && le_champ().domaine_dis_base().domaine() == ch.domaine_dis_base().domaine()))
323 {
324 // Meme support donc on utilise une methode plus rapide pour affecter_
325 // que la methode generale dans Champ_Fonc_base::affecter_ ou Champ_Inc_base::affecter_
326 ch.valeur_aux_centres_de_gravite(le_champ().domaine_dis_base().domaine(), le_champ().valeurs());
327 return 1;
328 }
329 else
330 {
331 if ((le_champ().domaine_dis_base().domaine().nb_elem() > 10000) && (!sub_type(Champ_Uniforme, ch)))
332 Cerr << "Warning (if called each time step): computing field " << le_champ().le_nom() << " on domain " << le_champ().domaine_dis_base().domaine().le_nom() << " is not optimized... " << finl;
333 return 0;
334 }
335}
class Champ_Don_Fonc_txyz Cette classe represente un champ de donnees fonction
classe Champ_Fonc_Morceaux Cette classe represente un champ prenant par morceaux des valuers fonction...
virtual DoubleTab & valeurs()=0
classe Champ_Uniforme_Morceaux Cette classe represente champ constant par morceaux dans l'espace
classe Champ_Uniforme Represente un champ constant dans l'espace et dans le temps.
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
virtual int a_un_domaine_dis_base() const
Definition Champ_base.h:69
virtual const Domaine_dis_base & domaine_dis_base() const
virtual DoubleTab & valeur_aux_centres_de_gravite(const Domaine &, DoubleTab &valeurs) const
Cette methode, generique mais lente (calcul des centres de gravite, remplissage les_poly,...
public_for_cuda DoubleTab & valeur_aux_sommets_impl(DoubleTab &result) const override
DoubleVect & valeur_a_elem(const DoubleVect &position, DoubleVect &result, int poly) const override
DoubleTab & valeur_aux_elems(const DoubleTab &positions, const IntVect &polys, DoubleTab &result) const override
int imprime_P0(Sortie &, int) const
double valeur_a_elem_compo(const DoubleVect &position, int poly, int ncomp) const override
DoubleVect & valeur_aux_sommets_compo_impl(DoubleVect &result, int ncomp) const override
int remplir_coord_noeuds_et_polys(DoubleTab &positions, IntVect &polys) const override
DoubleTab & valeur_aux_centres_de_gravite(const Domaine &, DoubleTab &valeurs) const
Computes field values at centers of gravity.
int affecter_(const Champ_base &)
DoubleTab & remplir_coord_noeuds(DoubleTab &positions) const override
DoubleVect & valeur_aux_elems_compo(const DoubleTab &positions, const IntVect &polys, DoubleVect &result, int ncomp) const override
const Domaine & get_domaine_geom() const
virtual Champ_base & le_champ()=0
int_t nb_elem_tot() const
Definition Domaine.h:132
void calculer_centres_gravite(DoubleTab_t &xp) const
Calcule les centres de gravites des elements du domaine.
Definition Domaine.h:503
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
const Domaine & domaine() const
const Nom & le_nom() const override
Renvoie le nom du champ.
virtual int nb_comp() const
Definition Field_base.h:56
static int dimension
Definition Objet_U.h:99
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, View< _TYPE_, _SHAPE_ > > view_wo()
Definition TRUSTTab.h:276
int nb_dim() const
Definition TRUSTTab.h:199
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_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
_SIZE_ size() const
Definition TRUSTVect.tpp:45
int line_size() const
Definition TRUSTVect.tpp:67
void resize(_SIZE_, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTVect.tpp:91