TrioCFD 1.9.9_beta
TrioCFD documentation
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 // retrieve the problem
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 of one or several boundaries of the volumetric domain according to certain 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 // Copy of vertices
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 // mark the 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 // flag the boundary faces of interest
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 // mark all the faces to be added to the domain
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) // not a joint, or we are the owner
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 // compute the normal
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 // if normal is reversed, swap the two vertices
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 // if normal is reversed, swap the two vertices
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
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
void typer(const Nom &)
Sets the element type of the domain using the name passed as parameter.
Definition Domaine.h:457
int_t nb_som_tot() const
Returns the total number of vertices of the domain i.e. the number of real and virtual vertices on th...
Definition Domaine.h:123
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
Returns the total number of 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
Returns the index of the i-th vertex of face num_face.
Definition Domaine_VF.h:582
Frontiere_dis_base & frontiere_dis(int) override
Returns the i-th discrete boundary.
Definition Domaine_VF.h:630
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
int face_voisins(int num_face, int i) const
Returns the neighbouring element of num_face in direction i.
Definition Domaine_VF.h:418
void nommer(const Nom &nom) override
Assigns a name to the Objet_U. Virtual method to override.
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this 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
Class Extraire_surface Reading a file.
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
Returns the number of faces of the boundary.
Definition Frontiere.h:59
const Frontiere & frontiere() const
Returns the associated geometric boundary.
static Objet_U & objet(const Nom &)
See Interprete_bloc::objet_global(). BM: the Interprete class is not the best place for this.
const Joint_Items_t & joint_item(JOINT_ITEM type) const
Returns the joint information for the requested type (read-only).
Definition Joint.cpp:131
int PEvoisin() const
Definition Joint.h:49
const IntTab_t & renum_items_communs() const
Returns the renum_items_communs_ array (read-only). See renum_items_communs_.
A character string (Nom) in uppercase.
Definition Motcle.h:26
static void nettoie(Domaine_t &)
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
An array of character strings (VECT(Nom)).
Definition Noms.h:26
friend class Entree
Definition Objet_U.h:71
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 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_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
class Parser_U Version of the Parser class, deriving from 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
class Probleme_base It is a Probleme_U that is not a coupling.
const Domaine_dis_base & domaine_dis() const
Returns the discretized domain associated with the problem (const version).
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
Base class for output streams.
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")