TrioCFD 1.9.8
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//cf 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 : indique le type de reduction qui va etre realisee
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 // position la plus a gauche
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 // on, envoye au maitre
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 Reduction_0D du champ source (au sens qu on le rend uniforme) en fonction de la methode (min, max, moyenne, moyenne_ponderee_volume_elem, somme, somme_ponderee)
205 *
206 * Dans le cas ou le champ possede plusieurs composantes, elles sont traitees une par une
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() sur le tableau de valeurs des champs PolyMAC_HFV renvoie -1 (plusieurs supports)
219 // ToDo: reecrire completement cette methode (horrible, tres mal ecrite) en deportant les methodes min/max/sum/... pour chaque 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 pour le 3D
231 if (nb_dim==2)
232 nb_dim= source.valeurs().dimension(1);
233
234 ConstDoubleTab_parts valeurs_source_parts(source.valeurs()); // pour ignorer les variables auxiliaires
235 const DoubleTab& valeurs_source = valeurs_source_parts[0]; // de PolyMAC_HFV (sinon : min, moyenne FAUX)
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 //Pour l'option somme vect_source doit avoir une structure parallele
298 //pour appliquer val_extraite = mp_prodscal(vect_source,un)
299 //Sa dimension est alors fixee par rapport au nombre d items de la source
300 //ex : zvf.nb_faces() si 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 //Dans le cas VDF avec nb_dim!=nb_comp
314 //Sa dimension est fixee par rapport aux nb_faces dont l orientation est comp
315 vect_source.resize(size_vect);
316
317 // Remplissage
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 // Passage si necessaire de la composante pour les Champ_face
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//Extrait la valeur du vecteur val_source dans 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 // On n'utilise pas mp_moyenne_vect car probleme en VDF avec un champ vectoriel pour faire un val_source distribue
387 // Pour calculer la moyenne, on utilise 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 // Si on est :
403 // - au ELEM -> on pondere par les volumes des elements,
404 // - au FACE -> on pondere par les volumes entrelaces (on ne prend pas en compte les volumes etendues car on n'y a pas acces),
405 // - au NODE -> on pondere par les volumes de controle nodal [Vol(som)= Somme_sur_elem_entourant_som(Vol_elem/nb_som_par_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 // au 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 // au FACE
437 if (get_localisation()==Entity::FACE)
438 {
439 // Calcul des volumes de controle a chaque 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 // au NODE
516 if (get_localisation()==Entity::NODE)
517 {
518 // Calcul des volumes de controle a chaque sommet
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 // Si on est :
566 // - au ELEM -> on pondere par les volumes des elements,
567 // - au FACE -> on pondere par les volumes entrelaces (on ne prend pas en compte les volumes etendues car on n'y a pas acces),
568 // - au NODE -> on pondere par les volumes de controle nodal [Vol(som)= Somme_sur_elem_entourant_som(Vol_elem/nb_som_par_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 // au ELEM
583 if (get_localisation()==Entity::ELEMENT)
584 {
585 zvf.compute_average(val_source, sum, volume, basis_function, composante_VDF);
586 }
587
588 // au FACE
589 else if (get_localisation()==Entity::FACE)
590 {
591 // Calcul des volumes de controle a chaque 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 // au NODE
638 else if (get_localisation()==Entity::NODE)
639 {
640 // Calcul des volumes de controle a chaque sommet
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 // - au ELEM -> on pondere par les volumes des elements *porosite_volumique
673 // si on n'est pas aux ELEM erreur
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 // au 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 // Pourquoi ne pas utiliser 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 // Dans le cas vectoriel en VDF, il ne faut compter que les
751 // faces de la composante etudiee :
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//Nomme le champ en tant que source par defaut
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}
classe Champ_Fonc_base Classe de base des champs qui sont fonction d'une grandeur calculee
Classe de base des champs generiques ayant comme source d'autres champs generiques L'utilisation des ...
Entity get_localisation(const int index=-1) const override
Renvoie le type des entites geometriques sur auxquelles les valeurs discretes sont attachees (NODE po...
LIST(OWN_PTR(Champ_Generique_base)) sources_
const Noms get_property(const Motcle &query) const override
Renvoie la propriete demandee.
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
Renvoie une ref au domaine_discretisee du domaine sur lequel sera evalue l espace de stockage.
double get_time() const override
Renvoie le temps du 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
Renvoie la propriete demandee.
const Champ_base & get_champ(OWN_PTR(Champ_base)&espace_stockage) const override
Reduction_0D du champ source (au sens qu on le rend uniforme) en fonction de la methode (min,...
const Motcle get_directive_pour_discr() const override
Renvoie la directive (champ_elem, champ_sommets, champ_face ou pression) pour lancer la discretisatio...
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
Renvoie la propriete demandee.
virtual const Domaine_dis_base & get_ref_domaine_dis_base() const
Renvoie une ref au domaine_discretisee du domaine sur lequel sera evalue l espace de stockage.
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
Donne un nom a l'Objet_U Methode virtuelle a surcharger.
virtual const Motcle get_directive_pour_discr() const
Renvoie la directive (champ_elem, champ_sommets, champ_face ou pression) pour lancer la discretisatio...
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
creation d'un tableau parallele de valeurs aux elements.
Definition Domaine.cpp:851
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
Cree un tableau ayant une "ligne" par sommet du maillage.
Definition Domaine.cpp:1000
int_t sommet_elem(int_t i, int j) const
Renvoie le numero (global) du j-ieme sommet du i-ieme element.
Definition Domaine.h:136
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
renvoie le nombre global de 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:646
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
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
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
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
Renvoie l'ordre des fonctions de base.
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
int debute_par(const char *const n) const override
Definition Motcle.cpp:309
Un tableau d'objets de la classe Motcle.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:321
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
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
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual const Nom & le_nom() const
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Objet_U.cpp:319
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
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
Classe de base pour l'ensemble des postraitements.
static double mp_min(double)
Definition Process.cpp:386
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:207
static Sortie & Journal(int message_level=0)
Renvoie un objet statique de type Sortie qui sert de journal d'evenements.
Definition Process.cpp:588
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Classe de base des flux de sortie.
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")