TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Extruder_en3.cpp
1/****************************************************************************
2* Copyright (c) 2024, 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 <Connectivite_som_elem.h>
17#include <Static_Int_Lists.h>
18#include <Faces_builder.h>
19#include <Extruder_en3.h>
20#include <Domaine.h>
21#include <Scatter.h>
22#include <Param.h>
23
24Implemente_instanciable_sans_constructeur(Extruder_en3,"Extruder_en3",Interprete_geometrique_base);
25// XD extruder_en3 extruder extruder_en3 BRACE Class to create a 3D tetrahedral/hexahedral mesh (a prism is cut in 3)
26// XD_CONT from a 2D triangular/quadrangular mesh. The names of the boundaries (by default, devant (front) and derriere
27// XD_CONT (back)) may be edited by the keyword nom_cl_devant and nom_cl_derriere. If 'null' is written for nom_cl, then
28// XD_CONT no boundary condition is generated at this place. NL2 Recommendation : to ensure conformity between meshes
29// XD_CONT (in case of fluid/solid coupling) it is recommended to extrude all the domains at the same time.
30
32 NZ_(-1),
33 nom_dvt_("devant"),
34 nom_derriere_("derriere")
35{
36 direction_.resize(3,RESIZE_OPTIONS::NOCOPY_NOINIT);
37}
38
40
42
43/*! @brief Main function of the Extruder_en3 interpreter
44 *
45 * Extrudes one by one all the domains specified by the directive.
46 * The domain is extruded through the method:
47 * void Extruder_en3::extruder(Domaine& domaine) const
48 * Extruder_en3 means here to transform geometric
49 * elements of a domain into a triangular mesh.
50 *
51 * @param (Entree& is) an input stream
52 * @return (Entree&) the input stream
53 * @throws the object to be meshed is not of Domaine type
54 */
56{
57 if (Objet_U::dimension!=2)
58 {
59 Cerr << " We only can extruder_en3 the 2D meshes ! " << finl;
60 exit();
61 }
62
63 int nb_dom=0;
64 Noms noms_dom;
65 Param param(que_suis_je());
66 param.ajouter("domaine",&noms_dom,Param::REQUIRED); // XD attr domaine listchaine domain_name REQ List of the domains
67 param.ajouter("nb_tranches",&NZ_,Param::REQUIRED);
69 param.ajouter("nom_cl_devant",&nom_dvt_); // XD attr nom_cl_devant chaine nom_cl_devant OPT New name of the
70 // XD_CONT first boundary.
71 param.ajouter("nom_cl_derriere",&nom_derriere_); // XD attr nom_cl_derriere chaine nom_cl_derriere OPT New name of
72 // XD_CONT the second boundary.
74 nb_dom=noms_dom.size();
75
76 // Create the index correspondence table
77 // to ensure conforming splitting between domains
78 //////////////////////////////////////////////////////
79
80 // PQ : 07/09/08 : splitting of prisms after extrusion is based on a global
81 // numbering of indices that ensures mesh conformity. These indices, referenced
82 // in the nums array, result from merging all domains into one.
83 // We concatenate the domains into "dom_tot" so as not to interfere
84 // with the original domains.
85 Domaine dom_tot; // just to get correct renumbering
86 for(int i=0; i<nb_dom; i++)
87 {
88 associer_domaine(noms_dom[nb_dom-1-i]);
89 Domaine& domi=domaine(i);
90 IntVect num;
91 dom_tot.ajouter(domi.coord_sommets(), num);
92
93 /////////////////////////
94 // domain extrusion
95 /////////////////////////
97 extruder(domi,num);
99 }
100
101 return is;
102}
103
104/*! @brief Extrudes a surface domain.
105 *
106 * @param dom The domain to extrude.
107 * @param num Global vertex index correspondence array for conforming splitting.
108 */
109void Extruder_en3::extruder(Domaine& dom, const IntVect& num)
110{
111 if(dom.type_elem()->que_suis_je() == "Triangle")
112 {
113 int oldnbsom = dom.nb_som();
114 IntTab& les_elems=dom.les_elems();
115 int oldsz=les_elems.dimension(0);
116 double dx = direction_[0]/NZ_;
117 double dy = direction_[1]/NZ_;
118 double dz = direction_[2]/NZ_;
119
120 Faces les_faces;
121 {
122 // block to be factored out with Domaine_VF.cpp :
123 Type_Face type_face = dom.type_elem()->type_face(0);
124 les_faces.typer(type_face);
125 les_faces.associer_domaine(dom);
126
127 Static_Int_Lists connectivite_som_elem;
128 const IntTab& elements = dom.les_elems();
129 const int nb_sommets_tot = dom.nb_som_tot();
130
131 construire_connectivite_som_elem(nb_sommets_tot,
132 elements,
133 connectivite_som_elem,
134 1 /* include virtual elements */);
135
136 Faces_builder faces_builder;
137 IntTab dnu; // Array that will not be needed
138 faces_builder.creer_faces_reeles(dom,
139 connectivite_som_elem,
140 les_faces,
141 dnu);
142 }
143
144 int newnbsom = oldnbsom*(NZ_+1);
145 DoubleTab new_soms(newnbsom, 3);
146 DoubleTab& coord_sommets=dom.les_sommets();
148
149 // vertices of the 2D mesh are translated first
150 for (int i=0; i<oldnbsom; i++)
151 {
152 double x = coord_sommets(i,0);
153 double y = coord_sommets(i,1);
154 double z=0.;
155 if (coord_sommets.dimension(1)>2)
156 z=coord_sommets(i,2);
157 for (int k=0; k<=NZ_; k++)
158 {
159 new_soms(k*oldnbsom+i,0)=x;
160 new_soms(k*oldnbsom+i,1)=y;
161 new_soms(k*oldnbsom+i,2)=z;
162
163 x += dx;
164 y += dy;
165 z += dz;
166 }
167 }
168
169 coord_sommets.resize(0);
170 dom.ajouter(new_soms);
171
172 int newnbelem = 3*NZ_*oldsz;
173 IntTab new_elems(newnbelem, 4); // the new elements
174 for (int i=0; i<oldsz; i++)
175 {
176 int i1=les_elems(i,0);
177 int i2=les_elems(i,1);
178 int i3=les_elems(i,2);
179
180 int ii1 = num[i1];
181 int ii2 = num[i2];
182 int ii3 = num[i3];
183 int i4=i1+oldnbsom;
184 int i5=i2+oldnbsom;
185 int i6=i3+oldnbsom;
186
187 for (int k=0; k<NZ_; k++)
188 {
189 int j=3*k*oldsz+3*i;
190 if (ii1>ii2 && ii1>ii3)
191 {
192 new_elems(j,0) = i1;
193 new_elems(j,1) = i2;
194 new_elems(j,2) = i3;
195 new_elems(j,3) = i4;
196 if (ii3>ii2)
197 {
198 new_elems(j+1,0) = i2;
199 new_elems(j+1,1) = i3;
200 new_elems(j+1,2) = i4;
201 new_elems(j+1,3) = i6;
202
203 new_elems(j+2,0) = i2;
204 new_elems(j+2,1) = i4;
205 new_elems(j+2,2) = i5;
206 new_elems(j+2,3) = i6;
207 }
208 else
209 {
210 new_elems(j+1,0) = i2;
211 new_elems(j+1,1) = i3;
212 new_elems(j+1,2) = i4;
213 new_elems(j+1,3) = i5;
214
215 new_elems(j+2,0) = i3;
216 new_elems(j+2,1) = i4;
217 new_elems(j+2,2) = i5;
218 new_elems(j+2,3) = i6;
219 }
220 }
221
222 if (ii2>ii1 && ii2>ii3)
223 {
224 new_elems(j,0) = i1;
225 new_elems(j,1) = i2;
226 new_elems(j,2) = i3;
227 new_elems(j,3) = i5;
228 if (ii1>ii3)
229 {
230 new_elems(j+1,0) = i1;
231 new_elems(j+1,1) = i3;
232 new_elems(j+1,2) = i4;
233 new_elems(j+1,3) = i5;
234
235 new_elems(j+2,0) = i3;
236 new_elems(j+2,1) = i4;
237 new_elems(j+2,2) = i5;
238 new_elems(j+2,3) = i6;
239 }
240 else
241 {
242 new_elems(j+1,0) = i1;
243 new_elems(j+1,1) = i3;
244 new_elems(j+1,2) = i5;
245 new_elems(j+1,3) = i6;
246
247 new_elems(j+2,0) = i1;
248 new_elems(j+2,1) = i4;
249 new_elems(j+2,2) = i5;
250 new_elems(j+2,3) = i6;
251 }
252 }
253
254 if (ii3>ii1 && ii3>ii2)
255 {
256 new_elems(j,0) = i1;
257 new_elems(j,1) = i2;
258 new_elems(j,2) = i3;
259 new_elems(j,3) = i6;
260 if (ii2>ii1)
261 {
262 new_elems(j+1,0) = i1;
263 new_elems(j+1,1) = i2;
264 new_elems(j+1,2) = i5;
265 new_elems(j+1,3) = i6;
266
267 new_elems(j+2,0) = i1;
268 new_elems(j+2,1) = i4;
269 new_elems(j+2,2) = i5;
270 new_elems(j+2,3) = i6;
271 }
272 else
273 {
274 new_elems(j+1,0) = i1;
275 new_elems(j+1,1) = i2;
276 new_elems(j+1,2) = i4;
277 new_elems(j+1,3) = i6;
278
279 new_elems(j+2,0) = i2;
280 new_elems(j+2,1) = i4;
281 new_elems(j+2,2) = i5;
282 new_elems(j+2,3) = i6;
283 }
284 }
285
287 i1+=oldnbsom;
288 i2+=oldnbsom;
289 i3+=oldnbsom;
290 i4+=oldnbsom;
291 i5+=oldnbsom;
292 i6+=oldnbsom;
293 }
294 }
295 // Rebuild the octree
296 dom.invalide_octree();
297 dom.typer("Tetraedre");
298
299 les_elems.ref(new_elems);
300 construire_bords(dom, les_faces,oldnbsom, oldsz, num);
301 }
302 else
303 Cerr << "TRUST doesn't know how to extrude " << dom.type_elem()->que_suis_je() <<"s"<<finl;
304}
305
306/*! @brief Creates the boundaries of the extruded domain.
307 *
308 * @param dom The extruded domain.
309 * @param les_faces The internal faces of the 2D domain.
310 * @param oldnbsom Number of vertices in the 2D mesh.
311 * @param oldsz Number of elements in the 2D mesh.
312 * @param num Global vertex index correspondence array.
313 */
314void Extruder_en3::construire_bords(Domaine& dom, Faces& les_faces, int oldnbsom, int oldsz, const IntVect& num)
315{
316 IntTab& les_elems = dom.les_elems();
317 // Boundaries:
318 for (auto &itr : dom.faces_bord())
319 {
320 Faces& les_faces_du_bord = itr.faces();
321 construire_bord_lateral(les_faces_du_bord, les_faces, oldnbsom, num);
322 }
323
324 // Connections (raccords):
325 for (auto &itr : dom.faces_raccord())
326 {
327 Faces& les_faces_du_bord = itr->faces();
328 construire_bord_lateral(les_faces_du_bord, les_faces, oldnbsom, num);
329 }
330
331 // Devant
332 if(nom_dvt_=="NULL")
333 {
334 Cerr << "We don't associate any boundary to the front of the domain " << dom.le_nom() << finl;
335 }
336 else
337 {
338 Bord& devant = dom.faces_bord().add(Bord());
339 devant.nommer(nom_dvt_);
340 Faces& les_faces_dvt=devant.faces();
341 les_faces_dvt.typer(Type_Face::triangle_3D);
342
343 IntTab som_dvt(oldsz, 3);
344 les_faces_dvt.voisins().resize(oldsz, 2);
345 les_faces_dvt.voisins()=-1;
346
347 for (int i=0; i<oldsz; i++)
348 {
349 int i0=les_elems(3*i,0);
350 int i1=les_elems(3*i,1);
351 int i2=les_elems(3*i,2);
352
353 som_dvt(i,0) = i0;
354 som_dvt(i,1) = i1;
355 som_dvt(i,2) = i2;
356 }
357 les_faces_dvt.les_sommets().ref(som_dvt);
358 }
359
360 // Derriere
361 if(nom_derriere_=="NULL")
362 {
363 Cerr << "We don't associate any boundary to the back of the domain " << dom.le_nom() << finl;
364 }
365 else
366 {
367 Bord& derriere = dom.faces_bord().add(Bord());
368 derriere.nommer(nom_derriere_);
369 Faces& les_faces_der=derriere.faces();
370 les_faces_der.typer(Type_Face::triangle_3D);
371
372 IntTab som_der(oldsz, 3);
373 les_faces_der.voisins().resize(oldsz, 2);
374 les_faces_der.voisins()=-1;
375
376 for (int i=0; i<oldsz; i++)
377 {
378 int i0=les_elems(3*i,0);
379 int i1=les_elems(3*i,1);
380 int i2=les_elems(3*i,2);
381
382 som_der(i,0) = i0+oldnbsom*NZ_;
383 som_der(i,1) = i1+oldnbsom*NZ_;
384 som_der(i,2) = i2+oldnbsom*NZ_;
385 }
386 les_faces_der.les_sommets().ref(som_der);
387 }
388}
389
390/*! @brief Creates a lateral boundary.
391 *
392 * @param les_faces_du_bord The boundary faces to fill.
393 * @param les_faces The internal faces of the 2D domain.
394 * @param oldnbsom Number of vertices in the 2D mesh.
395 * @param num Global vertex index correspondence array.
396 */
397void Extruder_en3::construire_bord_lateral(Faces& les_faces_du_bord, Faces& les_faces, int oldnbsom, const IntVect& num)
398{
399 // oldnbsom = number of nodes of the 2D mesh
400 int nb_faces = les_faces_du_bord.nb_faces();
401 IntTab les_sommets(2*nb_faces*NZ_,3);
402 for (int i=0; i<nb_faces; i++)
403 {
404 int i0=les_faces_du_bord.sommet(i,0);
405 int i1=les_faces_du_bord.sommet(i,1);
406 int ii0= num[i0];
407 int ii1= num[i1];
408 for (int k=0; k<NZ_; k++)
409 {
410 int j=2*nb_faces*k+2*i;
411
412 if (ii0>ii1)
413 {
414 les_sommets(j,0) = i0;
415 les_sommets(j,1) = i1;
416 les_sommets(j,2) = i0+oldnbsom;
417
418 les_sommets(j+1,0) = i1;
419 les_sommets(j+1,1) = i0+oldnbsom;
420 les_sommets(j+1,2) = i1+oldnbsom;
421 }
422 else
423 {
424 les_sommets(j,0) = i0;
425 les_sommets(j,1) = i1;
426 les_sommets(j,2) = i1+oldnbsom;
427
428 les_sommets(j+1,0) = i0;
429 les_sommets(j+1,1) = i0+oldnbsom;
430 les_sommets(j+1,2) = i1+oldnbsom;
431 }
432 i0+=oldnbsom;
433 i1+=oldnbsom;
434 }
435 }
436
437 les_faces_du_bord.typer(Type_Face::triangle_3D);
438 les_faces_du_bord.les_sommets().ref(les_sommets);
439 les_faces_du_bord.voisins().resize(2*nb_faces*NZ_, 2);
440 les_faces_du_bord.voisins()=-1;
441}
442
DoubleTab_t & les_sommets()
Definition Domaine.h:113
Bords_t & faces_bord()
Definition Domaine.h:198
Raccords_t & faces_raccord()
Definition Domaine.h:253
IntTab_t & les_elems()
Definition Domaine.h:129
void invalide_octree()
Definition Domaine.cpp:809
void typer(const Nom &)
Sets the element type of the domain using the name passed as parameter.
Definition Domaine.h:457
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
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
int_t nb_som() const
Returns the number of vertices of the domain.
Definition Domaine.h:121
void ajouter(const DoubleTab_t &soms)
Adds nodes (or vertices) to the domain (without checking for duplicates).
Definition Domaine.cpp:908
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Class Extruder_en3 This class is an interpreter that serves to read and execute.
void construire_bord_lateral(Faces &, Faces &, int, const IntVect &)
Creates a lateral boundary.
void extruder(Domaine &, const IntVect &)
Extrudes a surface domain.
void construire_bords(Domaine &, Faces &, int, int, const IntVect &)
Creates the boundaries of the extruded domain.
Entree & interpreter_(Entree &) override
Main function of the Extruder_en3 interpreter.
ArrOfDouble direction_
void typer(const Motcle &)
Sets the type of the faces.
Definition Faces.cpp:382
void associer_domaine(const Domaine_t &z)
Definition Faces.h:94
IntTab_t & voisins()
Returns the array of neighbors (of the faces).
Definition Faces.h:89
int_t nb_faces() const
Definition Faces.h:66
const IntTab_t & les_sommets() const
Returns the array of vertices of all faces.
Definition Faces.h:74
int_t sommet(int_t, int) const
Returns the number of the j-th vertex of the i-th face.
Definition Faces.h:130
void creer_faces_reeles(Domaine_t &domaine, const Static_Int_Lists_t &connect_som_elem, Faces_t &les_faces, IntTab_t &elem_faces)
From the description of the domain elements and boundaries (borders, connections, face groups,...
void nommer(const Nom &) override
Gives a name to the boundary.
Definition Frontiere.cpp:74
const Faces_t & faces() const
Definition Frontiere.h:54
void mettre_a_jour_sous_domaine(Domaine_t &domaine, int_t &elem, int_t num_premier_elem, int_t nb_elem) const
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_arr_size_predefinie(const char *keyword, const ArrOfInt *value, Param::Nature nat=Param::OPTIONAL)
Register an ArrOfInt whose size has already been fixed.
Definition Param.cpp:411
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
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
static void init_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
Create parallel descriptors for the vertex and element arrays of the domain (necessary because Scatte...
Definition Scatter.cpp:2739
static void uninit_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
Method used by interpreters that modify the domain (sequential), destroys the descriptors of vertices...
Definition Scatter.cpp:2754
Base class for output streams.
Definition Sortie.h:52
virtual void ref(const TRUSTTab &)
Definition TRUSTTab.tpp:308
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133