TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Champ_Generique_Reduction_0D.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 <Champ_Generique_Reduction_0D.h>
17#include <Discretisation_base.h>
18#include <TRUSTTab_parts.h>
19#include <communications.h>
20#include <Probleme_base.h>
21#include <Synonyme_info.h>
22
23#include <Domaine_VF.h>
24#include <Param.h>
25
26Implemente_instanciable(Champ_Generique_Reduction_0D,"Reduction_0D",Champ_Gen_de_Champs_Gen);
27Add_synonym(Champ_Generique_Reduction_0D,"Champ_Post_Reduction_0D");
28// XD reduction_0d champ_post_de_champs_post reduction_0d INHERITS_BRACE To calculate the min, max, sum, average,
29// XD_CONT weighted sum, weighted average, weighted sum by porosity, weighted average by porosity, euclidian norm,
30// XD_CONT normalized euclidian norm, L1 norm, L2 norm of a field.
31
33{
34 return s << que_suis_je() << " " << le_nom();
35}
36
37//see Champ_Gen_de_Champs_Gen::readOn
39{
40 LIST(Motcle) mot_compris;
41 mot_compris.add("min");
42 mot_compris.add("max");
43 mot_compris.add("euclidian_norm"); // new name for norme_L2
44 mot_compris.add("normalized_euclidian_norm"); // new name for normalized_norm_L2
45 mot_compris.add("moyenne");
46 mot_compris.add("somme");
47 mot_compris.add("moyenne_ponderee");
48 mot_compris.add("somme_ponderee");
49 mot_compris.add("moyenne_ponderee_porosite");
50 mot_compris.add("somme_ponderee_porosite");
51 mot_compris.add("valeur_a_gauche");
52 mot_compris.add("L2_norm"); // L2 norm
53 mot_compris.add("L1_norm"); // L1 norm
54 mot_compris.add("average"); // new name for moyenne
55 mot_compris.add("sum"); // new name for somme
56 mot_compris.add("weighted_average"); // new name for moyenne_ponderee
57 mot_compris.add("weighted_sum"); // new name weighted_sum for somme_ponderee
58 mot_compris.add("weighted_average_porosity"); // new name for moyenne_ponderee_porosite
59 mot_compris.add("weighted_sum_porosity"); // new name for somme_ponderee_porosite
60 mot_compris.add("left_value"); // new name for valeur_a_gauche
61
63 if (mot_compris.rang(methode_)<0)
64 {
65 Cerr << "Method " << methode_ << " is an unknown option for methode keyword in "<< que_suis_je() << "." << finl;
66 Cerr << "Choose from " << mot_compris << finl;
68 }
69 return s ;
70}
71
72// methode : indicates the type of reduction to be performed
73// (min, max, moyenne, moyenne_ponderee_volume_elem, somme, somme_ponderee)
75{
77 param.ajouter("methode",&methode_,Param::REQUIRED); // XD_ADD_P chaine(into=["min","max","moyenne","average","moyenne_ponderee","weighted_average","somme","sum","somme_ponderee","weighted_sum","somme_ponderee_porosite","weighted_sum_porosity","euclidian_norm","normalized_euclidian_norm","L1_norm","L2_norm","valeur_a_gauche","left_value"])
78 // XD_CONT name of the reduction method: NL2 - min for the minimum value, NL2 - max for the maximum value, NL2 -
79 // XD_CONT average (or moyenne) for a mean, NL2 - weighted_average (or moyenne_ponderee) for a mean ponderated by
80 // XD_CONT integration volumes, e.g: cell volumes for temperature and pressure in VDF, volumes around faces for
81 // XD_CONT velocity and temperature in VEF, NL2 - sum (or somme) for the sum of all the values of the field, NL2 -
82 // XD_CONT weighted_sum (or somme_ponderee) for a weighted sum (integral), NL2 - weighted_average_porosity (or
83 // XD_CONT moyenne_ponderee_porosite) and weighted_sum_porosity (or somme_ponderee_porosite) for the mean and sum
84 // XD_CONT weighted by the volumes of the elements, only for ELEM localisation, NL2 - euclidian_norm for the euclidian
85 // XD_CONT norm, NL2 - normalized_euclidian_norm for the euclidian norm normalized, NL2 - L1_norm for norm L1, NL2 -
86 // XD_CONT L2_norm for norm L2
87}
88
90{
92 //Champ source_espace_stockage;
93 Motcle directive;
94 directive = get_directive_pour_discr();
95
96 if (directive=="pression")
97 {
98 const Noms& nom_champ = get_property("nom");
99 const Noms& nom_source = get_source(0).get_property("nom");
100 Cerr<<"Problem with the "<<que_suis_je()<<" post processing field named "<<nom_champ[0]<<"."<<finl;
101 Cerr<<"The source field named "<<nom_source[0]<<" of this last "<<que_suis_je()<<" field "<<finl;
102 Cerr<<"must be previously interpolated at the elem or som location."<<finl;
103 Cerr<<"Please use instead the syntax : "<<finl;
104 Cerr<<"..."<<que_suis_je()<<" { source Interpolation { localisation ... } ... }"<<finl;
105 Cerr<<"or contact TRUST support."<<finl;
106 exit();
107 }
108 if (methode_=="valeur_a_gauche" || methode_=="left_value")
109 {
110 numero_proc_=-1;
111 }
112
113 Journal()<<"METHODE "<<methode_<<finl;
114 if ((methode_=="valeur_a_gauche" || methode_=="left_value")&&(numero_proc_==-1))
115 {
116 const Domaine_dis_base& domaine_dis = get_source(0).get_ref_domaine_dis_base();
117
118 const Domaine_VF& zvf = ref_cast(Domaine_VF,domaine_dis);
119 // leftmost position
120 const DoubleTab& coords=zvf.domaine().les_sommets();
121 const IntTab& conn=zvf.domaine().les_elems();
122 double minp=mp_min_vect(coords);
123 //Cerr<<" uu "<<minp<<finl;
124 minp=Process::mp_min(minp);
125 // Cerr<<" uu "<<minp<<finl;
126 const Domaine& domaine =zvf.domaine();
127 int elemin=-1;
128 double dmin=DMAXFLOAT;
129 int nb_elem=domaine.nb_elem();
130 //ArrOfDouble xp(dimension);
131 for (int ele=0; ele<nb_elem; ele++)
132 {
133
134 double d=0;
135 for (int dir=0; dir<dimension; dir++)
136 {
137 double xp=0;
138 int nb_som_elem=conn.dimension(1);
139 for (int s=0; s<nb_som_elem; s++)
140 {
141 int som=conn(ele,s);
142 xp+=coords(som,dir);
143 }
144 xp/=nb_som_elem;
145 d+=(xp-minp)*(xp-minp);
146 }
147 if (d<dmin)
148 {
149 dmin=d;
150 elemin=ele;
151 }
152 }
153 double dming=mp_min(dmin);
154 // we send to the master
155 if (!je_suis_maitre())
156 {
157 envoyer(dmin,0,97);
158 envoyer(elemin,0,97);
159 }
160 if (je_suis_maitre())
161 {
163 numero_elem_=elemin;
164 for (int p=1; p<nproc(); p++)
165 {
166 double dminloc;
167 int eleminloc;
168 recevoir(dminloc,p,97);
169 recevoir(eleminloc,p,97);
170
171 if (dminloc<dmin)
172 {
173 dmin=dminloc;
174 numero_proc_=p;
175 numero_elem_=eleminloc;
176 }
177 }
178
179 if (!est_egal(dmin,dming))
180 {
181 Cerr<<" iiiiiiiiiii "<<dmin<<" "<<dming<<finl;
182 exit();
183 }
184 }
185 envoyer_broadcast(numero_proc_,0);
186 envoyer_broadcast(numero_elem_,0);
187
188 }
189
190}
191
193{
194
195 OWN_PTR(Champ_base) source_espace_stockage_tmp;
196 const Champ_base& source = get_source(0).get_champ_without_evaluation(source_espace_stockage_tmp);
197 Nature_du_champ nature_source = source.nature_du_champ();
198 int nb_comp = source.nb_comp();
199
200 OWN_PTR(Champ_Fonc_base) es_tmp;
201 espace_stockage = creer_espace_stockage(nature_source,nb_comp,es_tmp);
202 return espace_stockage;
203}
204/*! @brief 0D reduction of the source field (in the sense that we make it uniform) according to the method (min, max, moyenne, moyenne_ponderee_volume_elem, somme, somme_ponderee)
205 *
206 * In the case where the field has multiple components, they are processed one by one
207 *
208 */
210{
211 const Champ_base& source = get_source(0).get_champ(source_espace_stockage_);
212 const Domaine_dis_base& domaine_dis = get_source(0).get_ref_domaine_dis_base();
213 Nature_du_champ nature_source = source.nature_du_champ();
214 bool basis_function = source.is_basis_function();
215 int order = source.order_field();
216 int nb_comp = source.nb_vect_comp();
217
218 // dimension() on the value array of PolyMAC_HFV fields returns -1 (multiple supports)
219 // ToDo: completely rewrite this method (horrible, very poorly written) by delegating the min/max/sum/... methods for each OWN_PTR(Champ_base)!
220 if (source.que_suis_je()=="Champ_Face_PolyMAC_HFV" || source.que_suis_je()=="Champ_Face_PolyMAC_MPFA")
221 Process::exit("PolyMAC_HFV/PolyMAC_MPFA face field not supported yet for Reduction_0D");
222
223
224 if (!espace_stockage_)
225 creer_espace_stockage(nature_source,nb_comp,espace_stockage_);
226 else
227 espace_stockage_->changer_temps(get_time());
228
229 int nb_dim = source.valeurs().nb_dim();
230 // correction for 3D
231 if (nb_dim==2)
232 nb_dim= source.valeurs().dimension(1);
233
234 ConstDoubleTab_parts valeurs_source_parts(source.valeurs()); // to ignore auxiliary variables
235 const DoubleTab& valeurs_source = valeurs_source_parts[0]; // of PolyMAC_HFV (otherwise: min, moyenne WRONG)
236 DoubleTab& espace_valeurs = espace_stockage_->valeurs();
237 const Domaine_VF& zvf = ref_cast(Domaine_VF,domaine_dis);
238 double val_extraite=-100.;
239
240 if (source.is_basis_function() or source.is_quadrature())
241 {
242 if (nb_comp==1)
243 {
244 extraire(val_extraite,valeurs_source,basis_function,order);
245 espace_valeurs = val_extraite;
246 }
247 else
248 {
250 int size_vect = valeurs_source.dimension(0);
251 DoubleTrav vect_source;
252 vect_source.resize(size_vect);
253 for (int comp=0; comp<nb_comp; comp++)
254 {
255 {
256 ToDo_Kokkos("Code but check test!");
257 CDoubleTabView valeurs = valeurs_source.view_ro();
258 DoubleArrView vect = static_cast<ArrOfDouble&>(vect_source).view_wo();
259 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), size_vect, KOKKOS_LAMBDA(const int i)
260 {
261 vect(i) = valeurs(i,comp);
262 });
263 end_gpu_timer(__KERNEL_NAME__);
264 }
265 extraire(val_extraite,vect_source,basis_function,order);
266 {
267 DoubleTabView valeurs = espace_valeurs.view_wo();
268 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), size_vect, KOKKOS_LAMBDA(const int i)
269 {
270 valeurs(i,comp) = val_extraite;
271 });
272 end_gpu_timer(__KERNEL_NAME__);
273 }
274 }
275 }
276 }
277 else if (nb_comp==1)
278 {
279 extraire(val_extraite,valeurs_source,basis_function);
280 espace_valeurs = val_extraite;
281 }
282 else
283 {
284 for (int comp=0; comp<nb_comp; comp++)
285 {
286 int size_vect = valeurs_source.dimension(0);
287 if (nb_dim!=nb_comp) //Cas des Champ_Face_VDF
288 {
289 size_vect=0;
290 ToDo_Kokkos("critical, warning check you have a NR test case with .son !");
291 for (int i=0; i<valeurs_source.dimension(0); i++)
292 if (zvf.orientation(i)==comp)
293 ++size_vect;
294 }
295
296 DoubleTrav vect_source;
297 //For the somme option, vect_source must have a parallel structure
298 //to apply val_extraite = mp_prodscal(vect_source,un)
299 //Its dimension is then set relative to the number of items in the source
300 //ex: zvf.nb_faces() if loc==FACE
301 if (methode_=="somme" || methode_=="moyenne" || methode_=="sum" || methode_=="average")
302 {
303 Entity loc = get_localisation();
304 if (loc==Entity::ELEMENT)
305 zvf.domaine().creer_tableau_elements(vect_source,RESIZE_OPTIONS::NOCOPY_NOINIT);
306 else if (loc==Entity::NODE)
307 zvf.domaine().creer_tableau_sommets(vect_source,RESIZE_OPTIONS::NOCOPY_NOINIT);
308 else if (loc==Entity::FACE)
309 zvf.creer_tableau_faces(vect_source,RESIZE_OPTIONS::NOCOPY_NOINIT);
310 vect_source = 0.;
311 }
312 else
313 //In the VDF case with nb_dim!=nb_comp
314 //Its dimension is set relative to the nb_faces whose orientation is comp
315 vect_source.resize(size_vect);
316
317 // Filling
318 if (nb_dim==nb_comp)
319 {
320 CDoubleTabView valeurs = valeurs_source.view_ro();
321 DoubleArrView vect = static_cast<ArrOfDouble&>(vect_source).view_wo();
322 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), size_vect, KOKKOS_LAMBDA(const int i)
323 {
324 vect(i) = valeurs(i,comp);
325 });
326 end_gpu_timer(__KERNEL_NAME__);
327 }
328 else
329 {
330 ToDo_Kokkos("critical, warning check you have a NR test case with .son !");
331 int k=0;
332 for (int i=0; i<valeurs_source.dimension(0); i++)
333 if (zvf.orientation(i)==comp)
334 {
335 if (methode_=="somme" || methode_=="moyenne" || methode_=="sum" || methode_=="average")
336 vect_source(i) = valeurs_source(i);
337 else
338 {
339 vect_source(k) = valeurs_source(i);
340 k++;
341 }
342 }
343 }
344 // Pass the component if necessary for Champ_face fields
345 extraire(val_extraite,vect_source,basis_function,(nb_dim==nb_comp?-1:comp));
346
347 if (nb_dim==nb_comp)
348 {
349 DoubleTabView valeurs = espace_valeurs.view_wo();
350 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), size_vect, KOKKOS_LAMBDA(const int i)
351 {
352 valeurs(i,comp) = val_extraite;
353 });
354 end_gpu_timer(__KERNEL_NAME__);
355 }
356 else
357 {
358 ToDo_Kokkos("critical, warning check you have a NR test case with .son !");
359 for (int i=0; i<valeurs_source.dimension(0); i++)
360 if (zvf.orientation(i)==comp)
361 espace_valeurs(i) = val_extraite;
362 }
363 }
364 }
365 espace_valeurs.echange_espace_virtuel();
366
367 return espace_stockage_;
368}
369
370//Extracts the value from the vector val_source into val_extraite
371void Champ_Generique_Reduction_0D::extraire(double& val_extraite,const DoubleVect& val_source, const bool basis_function, const int composante_VDF) const
372{
373
374 // Careful :: the composante_VDF for DG gives the order of the source basis_functions
375
376 if (methode_=="min")
377 {
378 val_extraite = mp_min_vect(val_source);
379 }
380 else if (methode_=="max")
381 {
382 val_extraite = mp_max_vect(val_source);
383 }
384 /*
385 else if (methode_=="moyenne") {
386 // We do not use mp_moyenne_vect because of problems in VDF with a vector field to make a distributed val_source
387 // To calculate the mean, we use somme(val_source)/somme(1)
388 val_extraite = mp_moyenne_vect(val_source);
389 } */
390 else if (methode_=="euclidian_norm")
391 {
392 val_extraite = mp_norme_vect(val_source);
393 }
394 else if (methode_=="normalized_euclidian_norm")
395 {
396 DoubleVect val_un(val_source);
397 val_un=1.;
398 val_extraite = mp_norme_vect(val_source)/mp_norme_vect(val_un);
399 }
400 else if (methode_ =="L1_norm" || methode_ =="L2_norm")
401 {
402 // If we are:
403 // - at ELEM -> we weight by element volumes,
404 // - at FACE -> we weight by interleaved volumes (we do not account for extended volumes since they are not accessible),
405 // - at NODE -> we weight by nodal control volumes [Vol(som)= Sum_over_elem_surrounding_som(Vol_elem/nb_som_per_elem)].
406 const Domaine_dis_base& domaine_dis = get_ref_domaine_dis_base();
407 const Domaine_VF& zvf = ref_cast(Domaine_VF,domaine_dis);
408 double sum=0;
409 const DoubleVect& volumes = zvf.volumes();
410 //int volumes_size_tot = mp_sum(volumes.size_array());
411 if (volumes.size_array()<zvf.nb_elem())
412 {
413 Cerr << "The mesh volumes of the domain " << zvf.domaine().le_nom() << " are not available yet." << finl;
414 Cerr << "It is not implemented yet." << finl;
415 exit();
416 }
417
418 // at ELEM
419 if (get_localisation()==Entity::ELEMENT)
420 {
421 if (methode_ =="L1_norm")
422 {
423 sum = zvf.compute_L1_norm(val_source,basis_function,composante_VDF);
424 }
425 else if (methode_ =="L2_norm")
426 {
427 sum = zvf.compute_L2_norm(val_source,basis_function,composante_VDF);
428 }
429 else
430 {
431 Cerr << "Error in Champ_Generique_Reduction_0D::extraire" << finl;
432 exit();
433 }
434 }
435
436 // at FACE
437 if (get_localisation()==Entity::FACE)
438 {
439 // Computation of control volumes at each face
440 int nb_face = zvf.nb_faces();
441 if (!volume_controle_.size())
442 {
443 volume_controle_.resize(nb_face);
445 int nb_faces_par_elem = zvf.elem_faces().dimension_tot(1);
446 int nb_elem = zvf.nb_elem();
447 ToDo_Kokkos("Code but check test!");
448 for (int i=0; i<nb_elem; i++)
449 for (int j=0; j<nb_faces_par_elem; j++)
450 {
451 int face=zvf.elem_faces(i,j);
452 volume_controle_(face)+=volumes(i)/nb_faces_par_elem;
453 }
454 }
455 if (composante_VDF>=0)
456 {
457 const IntVect& ori = zvf.orientation();
458 int k=0;
459 if (methode_ =="L1_norm")
460 {
461 ToDo_Kokkos("Code but check test!");
462 for (int i=0; i<nb_face; i++)
463 {
464 if (ori(i)==composante_VDF)
465 {
466 sum+=std::fabs(val_source(k))*volume_controle_(i);
467 k++;
468 }
469 }
470 }
471 else if (methode_ =="L2_norm")
472 {
473 ToDo_Kokkos("Code but check test!");
474 for (int i=0; i<nb_face; i++)
475 {
476 if (ori(i)==composante_VDF)
477 {
478 sum+=val_source(k)*val_source(k)*volume_controle_(i);
479 k++;
480 }
481 }
482 }
483 else
484 {
485 Cerr << "Error in Champ_Generique_Reduction_0D::extraire" << finl;
486 exit();
487 }
488 }
489 else
490 {
491 if (methode_ =="L1_norm")
492 {
493 ToDo_Kokkos("Code but check test!");
494 for (int i=0; i<nb_face; i++)
495 {
496 sum+=std::fabs(val_source(i))*volume_controle_(i);
497 }
498 }
499 else if (methode_ =="L2_norm")
500 {
501 ToDo_Kokkos("Code but check test!");
502 for (int i=0; i<nb_face; i++)
503 {
504 sum+=val_source(i)*val_source(i)*volume_controle_(i);
505 }
506 }
507 else
508 {
509 Cerr << "Error in Champ_Generique_Reduction_0D::extraire" << finl;
510 exit();
511 }
512 }
513 }
514
515 // at NODE
516 if (get_localisation()==Entity::NODE)
517 {
518 // Computation of control volumes at each node
519 int nb_som = zvf.nb_som();
520 if (!volume_controle_.size())
521 {
522 volume_controle_.resize(nb_som);
524 int nb_som_par_elem = zvf.domaine().les_elems().dimension_tot(1);
525 int nb_elem = zvf.nb_elem();
526 ToDo_Kokkos("Code but check test!");
527 for (int i=0; i<nb_elem; i++)
528 for (int j=0; j<nb_som_par_elem; j++)
529 {
530 int som=zvf.domaine().sommet_elem(i,j);
531 volume_controle_(som)+=volumes(i)/nb_som_par_elem;
532 }
533 }
534 if (methode_ =="L1_norm")
535 {
536 ToDo_Kokkos("Code but check test!");
537 for (int i=0; i<nb_som; i++)
538 {
539 sum+=std::fabs(val_source(i))*volume_controle_(i);
540 }
541 }
542 else if (methode_ =="L2_norm")
543 {
544 ToDo_Kokkos("Code but check test!");
545 for (int i=0; i<nb_som; i++)
546 {
547 sum+=val_source(i)*val_source(i)*volume_controle_(i);
548 }
549 }
550 else
551 {
552 Cerr << "Error in Champ_Generique_Reduction_0D::extraire" << finl;
553 exit();
554 }
555 }
556 val_extraite = mp_sum(sum);
557 if (methode_ =="L2_norm")
558 {
559 val_extraite = sqrt(val_extraite);
560 }
561 }
562
563 else if (methode_=="weighted_average" || methode_=="weighted_sum" || methode_=="moyenne_ponderee" || methode_=="somme_ponderee")
564 {
565 // If we are:
566 // - at ELEM -> we weight by element volumes,
567 // - at FACE -> we weight by interleaved volumes (we do not account for extended volumes since they are not accessible),
568 // - at NODE -> we weight by nodal control volumes [Vol(som)= Sum_over_elem_surrounding_som(Vol_elem/nb_som_per_elem)].
569
570 const Domaine_dis_base& domaine_dis = get_ref_domaine_dis_base();
571 const Domaine_VF& zvf = ref_cast(Domaine_VF,domaine_dis);
572 double sum=0;
573 double volume=0;
574 //int volumes_size_tot = mp_sum(volumes.size_array());
575 if (zvf.volumes().size_array()<zvf.nb_elem())
576 {
577 Cerr << "The mesh volumes of the domain " << zvf.domaine().le_nom() << " are not available yet." << finl;
578 Cerr << "It is not implemented yet." << finl;
579 exit();
580 }
581
582 // at ELEM
583 if (get_localisation()==Entity::ELEMENT)
584 {
585 zvf.compute_average(val_source, sum, volume, basis_function, composante_VDF);
586 }
587
588 // at FACE
589 else if (get_localisation()==Entity::FACE)
590 {
591 // Computation of control volumes at each face
592 int nb_face = zvf.nb_faces();
593 if (!volume_controle_.size() || zvf.domaine().deformable())
594 {
595 volume_controle_.resize(nb_face);
597 int nb_faces_par_elem = zvf.elem_faces().dimension_tot(1);
598 int nb_elem = zvf.nb_elem();
599 CIntTabView elem_faces = zvf.elem_faces().view_ro();
600 CDoubleArrView volumes = zvf.volumes().view_ro();
601 DoubleArrView volume_controle = volume_controle_.view_rw();
602 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_2D({0, 0}, {nb_elem, nb_faces_par_elem}), KOKKOS_LAMBDA(const int i, const int j)
603 {
604 int face = elem_faces(i,j);
605 Kokkos::atomic_add(&volume_controle(face), volumes(i)/nb_faces_par_elem);
606 });
607 end_gpu_timer(__KERNEL_NAME__);
608 }
609 if (composante_VDF>=0)
610 {
611 ToDo_Kokkos("Code but check test!");
612 //const IntVect& ori = zvf.orientation();
613 int k=0;
614 for (int i=0; i<nb_face; i++)
615 //if (ori(i)==composante_VDF)
616 if (zvf.orientation(i)==composante_VDF)
617 {
618 sum+=val_source(k)*volume_controle_(i);
619 volume+=volume_controle_(i);
620 k++;
621 }
622 }
623 else
624 {
625 CDoubleArrView volume_controle = volume_controle_.view_ro();
626 CDoubleArrView val = val_source.view_ro();
627 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__), nb_face, KOKKOS_LAMBDA(const int i, double & sum_tmp, double & volume_tmp)
628 {
629 double vc = volume_controle(i);
630 sum_tmp += val(i) * vc;
631 volume_tmp += vc;
632 }, sum, volume);
633 end_gpu_timer(__KERNEL_NAME__);
634 }
635 }
636
637 // at NODE
638 else if (get_localisation()==Entity::NODE)
639 {
640 // Computation of control volumes at each node
641 int nb_som = zvf.nb_som();
642 if (!volume_controle_.size())
643 {
644 volume_controle_.resize(nb_som);
646 const DoubleVect& volumes = zvf.volumes();
647 int nb_som_par_elem = zvf.domaine().les_elems().dimension_tot(1);
648 int nb_elem = zvf.nb_elem();
649 ToDo_Kokkos("Code but check test!");
650 for (int i=0; i<nb_elem; i++)
651 for (int j=0; j<nb_som_par_elem; j++)
652 {
653 int som=zvf.domaine().sommet_elem(i,j);
654 volume_controle_(som)+=volumes(i)/nb_som_par_elem;
655 }
656 }
657 ToDo_Kokkos("Code but check test!");
658 for (int i=0; i<nb_som; i++)
659 {
660 sum+=val_source(i)*volume_controle_(i);
661 volume+=volume_controle_(i);
662 }
663 }
664 // Optimization: combine 2 mp_sum into 1 collective call
665 mp_sum_for_each(sum, volume);
666 val_extraite = sum;
667 if (methode_=="moyenne_ponderee" || methode_=="weighted_average")
668 val_extraite /= volume;
669 }
670 else if (methode_=="moyenne_ponderee_porosite" || methode_=="somme_ponderee_porosite" || methode_=="weighted_average_porosity" || methode_=="weighted_sum_porosity")
671 {
672 // - at ELEM -> we weight by element volumes *volumetric_porosity
673 // if not at ELEM, error
674
675 const Domaine_dis_base& domaine_dis = get_ref_domaine_dis_base();
676 const Domaine_VF& zvf = ref_cast(Domaine_VF,domaine_dis);
677 double sum=0;
678 double volume=0;
679 const DoubleVect& volumes = zvf.volumes();
680 // int volumes_size_tot = mp_sum(volumes.size_array());
681 if (volumes.size_array()<zvf.nb_elem())
682 {
683 Cerr << "The mesh volumes of the domain " << zvf.domaine().le_nom() << " are not available yet." << finl;
684 Cerr << "It is not implemented yet." << finl;
685 exit();
686 }
687 if (get_nb_sources()!=2)
688 {
689 Cerr<<" you must define the porosity "<<finl;
690 exit();
691 }
692
693 // at ELEM
694 if (get_localisation()==Entity::ELEMENT)
695 {
696 OWN_PTR(Champ_base) source_espace_stockage2;
697 const Champ_base& source2 = get_source(1).get_champ(source_espace_stockage2);
698 Motcle nom_source_1(get_source(1).get_nom_post());
699 if (!(nom_source_1.debute_par("porosite_volumique")||(nom_source_1.debute_par("beta"))))
700 {
701 Cerr<<" Error with option pondere_porosite !!! "<< get_source(1).get_nom_post()<<finl;
702 exit();
703
704 }
705 const DoubleVect& poro= source2.valeurs();
706 assert(volumes.size_array()==poro.size_array());
707 ToDo_Kokkos("Code but check test!");
708 zvf.compute_average_porosity(val_source,poro,sum,volume,basis_function,composante_VDF);
709 }
710 else
711 {
712 Cerr<<que_suis_je()<<" not implemented for this localisation "<<finl;
713 exit();
714
715 }
716
717 // Optimization: combine 2 mp_sum into 1 collective call
718 mp_sum_for_each(sum, volume);
719 val_extraite = sum;
720 if (methode_=="moyenne_ponderee_porosite" || methode_=="weighted_average_porosity")
721 val_extraite /= volume;
722 }
723
724 else if (methode_=="somme" || methode_=="moyenne" || methode_=="sum" || methode_=="average")
725 {
726 const Domaine_dis_base& domaine_dis = get_source(0).get_ref_domaine_dis_base();
727 const Domaine_VF& zvf = ref_cast(Domaine_VF,domaine_dis);
728 if (!un_.get_md_vector())
729 {
730 Entity loc = get_localisation();
731 if (loc == Entity::ELEMENT)
732 zvf.domaine().creer_tableau_elements(un_, RESIZE_OPTIONS::NOCOPY_NOINIT);
733 else if (loc == Entity::NODE)
734 zvf.domaine().creer_tableau_sommets(un_, RESIZE_OPTIONS::NOCOPY_NOINIT);
735 else if (loc == Entity::FACE)
736 zvf.creer_tableau_faces(un_, RESIZE_OPTIONS::NOCOPY_NOINIT);
737 mapToDevice(un_);
738 }
739 un_ = 1.;
740 if (methode_=="somme" || methode_=="sum")
741 {
742 val_extraite = mp_prodscal(val_source,un_);
743 // Why not use val_extraite = mp_somme_vect(val_source); ?
744 }
745 else if (methode_=="moyenne" || methode_=="average")
746 {
747 Entity loc = get_localisation();
748 if (loc==Entity::FACE && composante_VDF>=0)
749 {
750 // In the vector case in VDF, we must only count the
751 // faces of the studied component:
752 int nb_face = zvf.nb_faces();
753 CIntArrView ori = zvf.orientation().view_ro();
754 DoubleArrView un = un_.view_wo();
755 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_face, KOKKOS_LAMBDA(const int i)
756 {
757 if (ori(i)!=composante_VDF)
758 un(i) = 0;
759 });
760 end_gpu_timer(__KERNEL_NAME__);
761 }
762 val_extraite = mp_somme_vect(val_source) / mp_somme_vect(un_);
763 }
764 else
765 {
766 Cerr << "Error in Champ_Generique_Reduction_0D::extraire" << finl;
767 exit();
768 }
769 }
770 else if (methode_=="valeur_a_gauche" || methode_=="left_value")
771 {
772
773 assert(numero_proc_!=-1);
774 if (me()==numero_proc_)
775 {
776 val_extraite=val_source(numero_elem_);
777 envoyer(val_extraite,me(),-1,98);
778 }
779 else
780 recevoir(val_extraite,numero_proc_,me(),98 );
781 }
782 else
783 {
784 Cerr << "Method " << methode_ << " is an unknown option for methode keyword." << finl;
785 exit();
786 }
787}
788
790{
791
792 Motcles motcles(1);
793 motcles[0] = "composantes";
794 int rang = motcles.search(query);
795 switch(rang)
796 {
797
798 case 0:
799 {
800 Noms source_compos = get_source(0).get_property("composantes");
801 int nb_comp = source_compos.size();
802 Noms compo(nb_comp);
803
804 for (int i=0; i<nb_comp; i++)
805 {
806 Nom nume(i);
807 compo[i] = nom_post_+nume;
808 }
809
810 return compo;
811 }
812
813 }
815}
816
817//Name the field as a source by default
818//"Reduction_0D_"+nom_champ_source
820{
821 if (nom_post_=="??")
822 {
823 Nom nom_post_source, nom_champ_source;
824 const Noms nom = get_source(0).get_property("nom");
825 nom_champ_source = nom[0];
826 nom_post_source = "Reduction_0D_";
827 nom_post_source += nom_champ_source;
828 nommer(nom_post_source);
829 }
830}
831
833{
834 OWN_PTR(Champ_base) espace_stockage_tmp;
835 const Champ_base& source = get_source(0).get_champ_without_evaluation(espace_stockage_tmp);
836 if (source.is_basis_function() or source.is_quadrature())
837 return "champ_fonc_quad_dg";
838
840}
class Champ_Fonc_base Base class of fields that are functions of a calculated quantity
Base class of generic fields having other generic fields as source. The use of the class methods reli...
Entity get_localisation(const int index=-1) const override
Returns the type of geometric entities on which the discrete values are attached (NODE for a P1 field...
LIST(OWN_PTR(Champ_Generique_base)) sources_
const Noms get_property(const Motcle &query) const override
Returns the requested property.
void completer(const Postraitement_base &post) override
virtual const Champ_Generique_base & get_source(int i) const
void set_param(Param &param) const override
const Domaine_dis_base & get_ref_domaine_dis_base() const override
Returns a ref to the discretized domain on which the storage space will be evaluated.
double get_time() const override
Returns the time of the Champ_Generique_base.
class Champ_Generique_Reduction_0D
void extraire(double &val_extraites, const DoubleVect &val_source, const bool basis_function, const int composante_VDF=-1) const
const Noms get_property(const Motcle &query) const override
Returns the requested property.
const Champ_base & get_champ(OWN_PTR(Champ_base)&espace_stockage) const override
0D reduction of the source field (in the sense that we make it uniform) according to the method (min,...
const Motcle get_directive_pour_discr() const override
Returns the directive (champ_elem, champ_sommets, champ_face or pression) to launch the discretizatio...
void completer(const Postraitement_base &post) override
void set_param(Param &param) const override
const Champ_base & get_champ_without_evaluation(OWN_PTR(Champ_base)&espace_stockage) const override
virtual const Noms get_property(const Motcle &query) const
Returns the requested property.
virtual const Domaine_dis_base & get_ref_domaine_dis_base() const
Returns a ref to the discretized domain on which the storage space will be evaluated.
virtual const Champ_base & get_champ(OWN_PTR(Champ_base) &espace_stockage) const =0
virtual const Nom & get_nom_post() const
virtual const Champ_base & get_champ_without_evaluation(OWN_PTR(Champ_base)&espace_stockage) const =0
void nommer(const Nom &nom) override
Assigns a name to the Objet_U. Virtual method to override.
virtual const Motcle get_directive_pour_discr() const
Returns the directive (champ_elem, champ_sommets, champ_face or pression) to launch the discretizatio...
virtual DoubleTab & valeurs()=0
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Creates a parallel array of values at elements.
Definition Domaine.cpp:850
DoubleTab_t & les_sommets()
Definition Domaine.h:113
IntTab_t & les_elems()
Definition Domaine.h:129
int_t nb_elem() const
Definition Domaine.h:131
virtual void creer_tableau_sommets(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Creates an array with one "row" per mesh vertex.
Definition Domaine.cpp:999
int_t sommet_elem(int_t i, int j) const
Returns the (global) number of the j-th vertex of the i-th element.
Definition Domaine.h:136
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
Returns the total number of faces.
Definition Domaine_VF.h:471
virtual double compute_L1_norm(const DoubleVect &val_source, const bool basis_function, const int order) const
virtual double compute_L2_norm(const DoubleVect &val_source, const bool basis_function, const int order) const
void creer_tableau_faces(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
double volumes(int i) const
Definition Domaine_VF.h:113
virtual const IntVect & orientation() const
Definition Domaine_VF.h:645
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
virtual void compute_average_porosity(const DoubleVect &val_source, const DoubleVect &porosity, double &sum, double &volume, const bool basis_function, const int order) const
virtual void compute_average(const DoubleVect &val_source, double &sum, double &volume, const bool basis_function, const int order) const
bool deformable() const
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual int nb_vect_comp() const
virtual int nb_comp() const
Definition Field_base.h:56
bool is_quadrature() const
Definition Field_base.h:81
virtual Nature_du_champ nature_du_champ() const
Definition Field_base.h:77
bool is_basis_function() const
Definition Field_base.h:80
int order_field() const
Returns the order of the basis functions.
A character string (Nom) in uppercase.
Definition Motcle.h:26
int debute_par(const char *const n) const override
Definition Motcle.cpp:307
An array of Motcle objects.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:319
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
An array of character strings (VECT(Nom)).
Definition Noms.h:26
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
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
virtual const Nom & le_nom() const
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Definition Objet_U.cpp:317
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
Base class for all post-processing objects.
static double mp_min(double)
Definition Process.cpp:391
static void mp_sum_for_each(T &arg1, T &arg2)
C++14 compatible mp_sum_for_each: combine multiple mp_sum calls into one collective operation Usage: ...
Definition Process.cpp:208
static Sortie & Journal(int message_level=0)
Returns a static Sortie object used as an event journal.
Definition Process.cpp:592
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
Definition Process.cpp:102
static double mp_sum(double)
Computes the sum of x over all processors in the current group.
Definition Process.cpp:145
static int me()
Returns the rank of the local processor in the current communication group. See Comm_Group::rank() an...
Definition Process.cpp:122
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
Definition Process.cpp:82
Base class for output streams.
Definition Sortie.h:52
_SIZE_ size_array() const
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
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")