TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Extraire_surface.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 <Extraire_surface.h>
17#include <Probleme_base.h>
18#include <Equation_base.h>
19#include <NettoieNoeuds.h>
20#include <Parser_U.h>
21#include <Domaine.h>
22#include <Domaine_VF.h>
23#include <Param.h>
24#include <ParserView.h>
25#include <Extraire_plan.h>
26
27Implemente_instanciable(Extraire_surface,"Extraire_surface",Interprete_geometrique_base);
28// XD extraire_surface interprete extraire_surface BRACE This keyword extracts a surface mesh named domain_name (this
29// XD_CONT domain should have been declared before) from the mesh of the pb_name problem. The surface mesh is defined by
30// XD_CONT one or two conditions. The first condition is about elements with Condition_elements. For example:
31// XD_CONT Condition_elements x*x+y*y+z*z<1 NL2 Will define a surface mesh with external faces of the mesh elements
32// XD_CONT inside the sphere of radius 1 located at (0,0,0). The second condition Condition_faces is useful to give a
33// XD_CONT restriction.NL2 By default, the faces from the boundaries are not added to the surface mesh excepted if
34// XD_CONT option avec_les_bords is given (all the boundaries are added), or if the option avec_certains_bords is used
35// XD_CONT to add only some boundaries. The first condition is about elements with Condition_elements. For example:
36// XD_CONT Condition_elements x*x+y*y+z*z<1 NL2 Will define a surface mesh with external faces of the mesh elements
37// XD_CONT inside the sphere of radius 1 located at (0,0,0). The second condition Condition_faces is useful to give a
38// XD_CONT restriction.NL2 By default, the faces from the boundaries are not added to the surface mesh excepted if
39// XD_CONT option avec_les_bords is given (all the boundaries are added), or if the option avec_certains_bords is used
40// XD_CONT to add only some boundaries.
41
43
45
47{
48 Nom nom_pb;
49 Nom nom_domaine_surfacique;
50 Nom expr_elements("1"),expr_faces("1");
51 bool avec_les_bords = false;
52 Noms noms_des_bords;
53 Param param(que_suis_je());
54 param.ajouter("domaine",&nom_domaine_surfacique,Param::REQUIRED); // XD_ADD_P ref_domaine
55 // XD_CONT Domain in which faces are saved
56 param.ajouter("probleme",&nom_pb,Param::REQUIRED); // XD_ADD_P ref_Pb_base
57 // XD_CONT Problem from which faces should be extracted
58 param.ajouter("condition_elements",&expr_elements); // XD_ADD_P chaine
59 // XD_CONT condition on center of elements
60 param.ajouter("condition_faces",&expr_faces); // XD_ADD_P chaine
61 // XD_CONT not_set
62 param.ajouter_flag("avec_les_bords",&avec_les_bords); // XD_ADD_P rien
63 // XD_CONT not_set
64 param.ajouter("avec_certains_bords",&noms_des_bords); // XD_ADD_P listchaine
65 // XD_CONT not_set
67
68 associer_domaine(nom_domaine_surfacique);
69 Domaine& domaine_surfacique=domaine();
70
71 if (domaine_surfacique.nb_som_tot()!=0)
72 {
73 Cerr << "Error!" << finl;
74 Cerr <<"The domain " << domaine_surfacique.le_nom() << " can't be used by the Extraire_surface keyword." <<finl;
75 Cerr <<"The domain for Extraire_surface keyword should be empty and created just before." << finl;
76 exit();
77 }
78
79 // on recupere le pb
80 if(! sub_type(Probleme_base, objet(nom_pb)))
81 {
82 Cerr << nom_pb << " is of type " << objet(nom_pb).que_suis_je() << finl;
83 Cerr << "and not of type Probleme_base" << finl;
84 exit();
85 }
86 Probleme_base& pb=ref_cast(Probleme_base, objet(nom_pb));
87 const Domaine_VF& domaine_vf=ref_cast(Domaine_VF,pb.domaine_dis());
88 const Domaine& domaine_volumique = domaine_vf.domaine();
89
90 extraire_surface(domaine_surfacique,domaine_volumique,nom_domaine_surfacique,domaine_vf,expr_elements,expr_faces,avec_les_bords,noms_des_bords);
91
92 return is;
93}
94
95// Extraction d'une ou plusieurs frontieres du domaine volumique selon certaines conditions
96
97void Extraire_surface::extraire_surface(Domaine& domaine_surfacique,const Domaine& domaine_volumique, const Nom& nom_domaine_surfacique, const Domaine_VF& domaine_vf, const Nom& expr_elements,const Nom& expr_faces, bool avec_les_bords, const Noms& noms_des_bords)
98{
99 extraire_surface_without_cleaning(domaine_surfacique,domaine_volumique,nom_domaine_surfacique,domaine_vf,expr_elements,expr_faces,avec_les_bords,noms_des_bords);
100 NettoieNoeuds::nettoie(domaine_surfacique);
101}
102void Extraire_surface::extraire_surface_without_cleaning(Domaine& domaine_surfacique,const Domaine& domaine_volumique, const Nom& nom_domaine_surfacique, const Domaine_VF& domaine_vf, const Nom& expr_elements,const Nom& expr_faces, bool avec_les_bords, const Noms& noms_des_bords)
103{
104 domaine_surfacique.nommer(nom_domaine_surfacique);
105 Parser_U condition_elements,condition_faces;
106 condition_elements.setNbVar(dimension);
107 condition_elements.addVar("x");
108 condition_elements.addVar("y");
109 if (dimension==3)
110 condition_elements.addVar("z");
111 condition_faces.setNbVar(dimension);
112 condition_faces.addVar("x");
113 condition_faces.addVar("y");
114 if (dimension==3)
115 condition_faces.addVar("z");
116
117 condition_faces.setString(expr_faces);
118 condition_faces.parseString();
119 condition_elements.setString(expr_elements);
120 condition_elements.parseString();
121
122 // Copie des sommets
123 domaine_surfacique.les_sommets()=domaine_volumique.les_sommets();
124 const Nom& type_elem=domaine_vf.domaine().type_elem()->que_suis_je();
125
126 if (dimension==3)
127 if (type_elem==Motcle("Tetraedre"))
128 domaine_surfacique.typer("Triangle");
129 else if (type_elem==Motcle("Segment"))
130 domaine_surfacique.typer("Point");
131 else if (type_elem==Motcle("Segment_axi"))
132 domaine_surfacique.typer("Point");
133 else if ((type_elem==Motcle("Hexaedre"))|| (type_elem==Motcle("Hexaedre_VEF")))
134 domaine_surfacique.typer("Quadrangle");
135 else if (type_elem==Motcle("Polyedre"))
136 domaine_surfacique.typer("Polygone");
137 else
138 {
139 Cerr<<"WARNING "<<type_elem<< " not coded, use Quadrangle" <<finl;
140 domaine_surfacique.typer("Quadrangle");
141 // exit();
142 }
143 else
144 domaine_surfacique.typer("segment");
145
146 int dim = Objet_U::dimension;
147 int nb_elem=domaine_vf.nb_elem();
148 IntTrav tab_marq_elem;
149 domaine_vf.domaine().creer_tableau_elements(tab_marq_elem);
150
151 ParserView parser_condition_elements(condition_elements);
152 parser_condition_elements.parseString();
153 CDoubleTabView xp = domaine_vf.xp().view_ro();
154 IntArrView marq_elem = static_cast<ArrOfInt&>(tab_marq_elem).view_wo();
155 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_elem, KOKKOS_LAMBDA(const int elem)
156 {
157 int threadId = parser_condition_elements.acquire();
158 parser_condition_elements.setVar(0,xp(elem,0),threadId);
159 parser_condition_elements.setVar(1,xp(elem,1),threadId);
160 if (dim==3)
161 parser_condition_elements.setVar(2,xp(elem,2),threadId);
162 double res = parser_condition_elements.eval(threadId);
163 parser_condition_elements.release(threadId);
164 marq_elem(elem) = std::fabs(res)>1e-5 ? 1 : 0;
165 });
166 end_gpu_timer(__KERNEL_NAME__);
167 tab_marq_elem.echange_espace_virtuel();
168
169 int nb_faces=domaine_vf.nb_faces();
170
171 ArrOfInt tab_marq(nb_faces);
172 // on marque les joints
173 int nbjoints=domaine_vf.nb_joints();
174 for(int njoint=0; njoint<nbjoints; njoint++)
175 {
176 const Joint& joint_temp = domaine_vf.joint(njoint);
177 int pe_voisin=joint_temp.PEvoisin();
178 if (pe_voisin<me())
179 {
180 const IntTab& tab_indices_faces_joint = joint_temp.joint_item(JOINT_ITEM::FACE).renum_items_communs();
181 const int nbfaces = tab_indices_faces_joint.dimension(0);
182 CIntTabView indices_faces_joint = tab_indices_faces_joint.view_ro();
183 IntArrView marq = tab_marq.view_rw();
184 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(0, nbfaces), KOKKOS_LAMBDA(const int j)
185 {
186 int face_de_joint = indices_faces_joint(j, 1);
187 marq[face_de_joint] = -1;
188 });
189 end_gpu_timer(__KERNEL_NAME__);
190 }
191 }
192 int nb_t=0;
193
194 // on flage les face sde bords qui nous interesse
195 ArrOfInt tab_face_bord_int(nb_faces);
196 if (avec_les_bords)
197 tab_face_bord_int=1;
198 if (noms_des_bords.size()!=0)
199 {
200 if (avec_les_bords)
201 {
202 Cerr<<" the option avec_les_bords is incompatible with the option avec_certains_bords"<<finl;
203 exit();
204 }
205 for (int b=0; b<noms_des_bords.size(); b++)
206 {
207 const Frontiere& fr=domaine_vf.frontiere_dis(domaine_vf.rang_frontiere(noms_des_bords[b])).frontiere();
208 int deb=fr.num_premiere_face();
209 int fin=deb+fr.nb_faces();
210 IntArrView face_bord_int = tab_face_bord_int.view_rw();
211 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), range_1D(deb, fin), KOKKOS_LAMBDA(const int f)
212 {
213 face_bord_int[f]=1;
214 });
215 end_gpu_timer(__KERNEL_NAME__);
216 }
217 }
218
219 // on marque toutes les faces que l'on veut mettre dans le domaine
220 ParserView parser_condition_faces(condition_faces);
221 parser_condition_faces.parseString();
222 CDoubleTabView xv = domaine_vf.xv().view_ro();
223 CIntTabView face_voisin = domaine_vf.face_voisins().view_ro();
224 CIntArrView face_bord_int = tab_face_bord_int.view_ro();
225 IntArrView marq = tab_marq.view_rw();
226 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__), nb_faces, KOKKOS_LAMBDA(const int fac, int& local_nb_t)
227 {
228 int elem0=face_voisin(fac,0);
229 int elem1=face_voisin(fac,1);
230 int val0=-1;
231 if (elem0!=-1) val0=marq_elem(elem0);
232 int val1=-1;
233 if (elem1!=-1) val1=marq_elem(elem1);
234
235 if (val0!=val1)
236 {
237 if (((val0*val1==0)&&(val0+val1==1))||((val0==1)&&(face_bord_int[fac]==1))||((val1==1)&&(face_bord_int[fac]==1)))
238 //if (domaine_test.chercher_elements(xv(fac,0),xv(fac,1),xv(fac,2))==0)
239 {
240 int threadId = parser_condition_faces.acquire();
241 parser_condition_faces.setVar(0,xv(fac,0),threadId);
242 parser_condition_faces.setVar(1,xv(fac,1),threadId);
243 if (dim==3)
244 parser_condition_faces.setVar(2,xv(fac,2),threadId);
245 double res=parser_condition_faces.eval(threadId);
246 parser_condition_faces.release(threadId);
247 if (std::fabs(res)>1e-5)
248 if (marq[fac]!=-1) // pas un joint, ou on est le proprietaire
249 {
250 marq[fac]=1;
251 local_nb_t++;
252 }
253
254 }
255 }
256 }, nb_t);
257 end_gpu_timer(__KERNEL_NAME__);
258
259 ArrOfInt tab_indices(nb_faces);
260 IntArrView indices = tab_indices.view_wo();
261 Kokkos::parallel_scan(start_gpu_timer(__KERNEL_NAME__), nb_faces, KOKKOS_LAMBDA(const int fac, int& update, const bool final)
262 {
263 if (marq[fac] == 1)
264 {
265 if (final) indices(fac) = update;
266 update++;
267 }
268 });
269 end_gpu_timer(__KERNEL_NAME__);
270
271 Cerr<<"Number of elements of the new domain : "<<nb_t<<finl;
272 CIntTabView face_sommets = domaine_vf.face_sommets().view_ro();
273 int nb_sommet_face=(int)face_sommets.extent(1);
274 IntTab& tab_les_elems=domaine_surfacique.les_elems();
275 tab_les_elems.resize(nb_t,nb_sommet_face);
276 CDoubleTabView coord = domaine_surfacique.les_sommets().view_ro();
277 IntTabView les_elems = tab_les_elems.view_wo();
278 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_faces, KOKKOS_LAMBDA(const int fac)
279 {
280 if (marq[fac] == 1)
281 {
282 int nb = indices(fac);
283 double normal[3] = {0., 0., 0.} , normal_b[3], point0b[3], point1b[3], point2b[3];
284 int el1 = face_voisin(fac, 0);
285 if (el1 == -1) el1 = face_voisin(fac, 1);
286 if (marq_elem(el1) != 1)
287 el1 = face_voisin(fac, 1);
288 for (int i = 0; i < dim; i++)
289 normal[i] = xv(fac, i) - xp(el1, i);
290 for (int s = 0; s < nb_sommet_face; s++)
291 les_elems(nb, s) = face_sommets(fac, s);
292 // on calcule la normale
293 if (nb_sommet_face > 1)
294 {
295 if (dim == 3)
296 {
297 for (int i = 0; i < 3; i++)
298 {
299 point0b[i] = coord(les_elems(nb, 0), i);
300 point1b[i] = coord(les_elems(nb, 1), i);
301 point2b[i] = coord(les_elems(nb, 2), i);
302 }
303 calcul_normal(point0b, point1b, point2b, normal_b);
304 double dot_product=0;
305 for (int i = 0; i < dim; i++)
306 dot_product+=normal[i]*normal_b[i];
307 if (dot_product < 0)
308 {
309 // si normal a l'envers on inverse les deux sommets
310 les_elems(nb, 1) = face_sommets(fac, 2);
311 les_elems(nb, 2) = face_sommets(fac, 1);
312 }
313 }
314 else
315 {
316 for (int i = 0; i < nb_sommet_face; i++)
317 point0b[i] = coord(les_elems(nb, 1), i) - coord(les_elems(nb, 0), i);
318 double produit = normal[0] * point0b[1] - normal[1] * point0b[0];
319 if (produit < 0)
320 {
321 // si normal a l'envers on inverse les deux sommets
322 les_elems(nb, 0) = face_sommets(fac, 1);
323 les_elems(nb, 1) = face_sommets(fac, 0);
324 }
325 }
326 }
327 }
328 });
329 end_gpu_timer(__KERNEL_NAME__);
330}
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
void typer(const Nom &)
Type les elements du domaine avec le nom passe en parametre.
Definition Domaine.h:457
int_t nb_som_tot() const
Renvoie le nombre total de sommets du domaine i.e. le nombre de sommets reels et virtuels sur le proc...
Definition Domaine.h:123
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
int nb_joints() const
Definition Domaine_VF.h:65
const Joint & joint(int i) const
Definition Domaine_VF.h:105
int face_sommets(int i, int j) const
renvoie le numero du ieme sommet de la face num_face.
Definition Domaine_VF.h:583
Frontiere_dis_base & frontiere_dis(int) override
renvoie la ieme frontiere_discrete.
Definition Domaine_VF.h:631
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
void nommer(const Nom &nom) override
Donne un nom a l'Objet_U Methode virtuelle a surcharger.
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
int rang_frontiere(const Nom &)
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Classe Extraire_surface Lecture d'un fichier.
Entree & interpreter_(Entree &) override
static void extraire_surface(Domaine &domaine_surfacique, const Domaine &domaine_volumique, const Nom &nom_domaine_surfacique, const Domaine_VF &domaine_vf, const Nom &expr_elements, const Nom &expr_faces, bool avec_les_bords, const Noms &noms_des_bords)
static void extraire_surface_without_cleaning(Domaine &domaine_surfacique, const Domaine &domaine_volumique, const Nom &nom_domaine_surfacique, const Domaine_VF &domaine_vf, const Nom &expr_elements, const Nom &expr_faces, bool avec_les_bords, const Noms &noms_des_bords)
int_t num_premiere_face() const
Definition Frontiere.h:67
int_t nb_faces() const
Renvoie le nombre de faces de la frontiere.
Definition Frontiere.h:59
const Frontiere & frontiere() const
Renvoie la frontiere geometrique associee.
static Objet_U & objet(const Nom &)
Voir Interprete_bloc::objet_global() BM: la classe Interprete n'est pas le meilleur endroit pour cett...
const Joint_Items_t & joint_item(JOINT_ITEM type) const
Renvoie les informations de joint pour le type demande.
Definition Joint.cpp:128
int PEvoisin() const
Definition Joint.h:49
const IntTab_t & renum_items_communs() const
Voir renum_items_communs_.
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
static void nettoie(Domaine_t &)
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
friend class Entree
Definition Objet_U.h:76
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 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_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
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
int lire_avec_accolades_depuis(Entree &is)
Parse the parameter block { ... } from is.
Definition Param.cpp:32
KOKKOS_INLINE_FUNCTION int acquire() const
Definition ParserView.h:77
KOKKOS_INLINE_FUNCTION void setVar(int i, double val, int threadId) const
Definition ParserView.h:64
void parseString() override
Definition ParserView.h:52
KOKKOS_INLINE_FUNCTION void release(int threadId) const
Definition ParserView.h:79
KOKKOS_INLINE_FUNCTION double eval(int threadId) const
Definition ParserView.h:69
classe Parser_U Version de la classe Parser, derivant de Objet_U.
Definition Parser_U.h:32
void setString(const std::string &s)
Definition Parser_U.h:194
void setNbVar(int nvar)
Definition Parser_U.h:174
void parseString()
Definition Parser_U.h:116
void addVar(const char *v)
Definition Parser_U.h:183
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
const Domaine_dis_base & domaine_dis() const
Renvoie le domaine discretise associe au probleme.
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
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
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
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")