TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
TroisDto2D.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 <TroisDto2D.h>
17#include <Interprete_bloc.h>
18#include <Scatter.h>
19
20Implemente_instanciable_32_64(TroisDto2D_32_64, "Extract_2D_from_3D", Interprete_geometrique_base_32_64<_T_>);
21// XD extract_2d_from_3d interprete extract_2d_from_3d INHERITS_BRACE Keyword to extract a 2D mesh by selecting a
22// XD_CONT boundary of the 3D mesh. To generate a 2D axisymmetric mesh prefer Extract_2Daxi_from_3D keyword.
23// XD attr dom3D ref_domaine dom3D REQ Domain name of the 3D mesh
24// XD attr bord chaine bord REQ Boundary name. This boundary becomes the new 2D mesh and all the boundaries, in 3D,
25// XD_CONT attached to the selected boundary, give their name to the new boundaries, in 2D.
26// XD attr dom2D chaine dom2D REQ Domain name of the new 2D mesh
27
28
29template <typename _SIZE_>
31{
32 return Interprete::printOn(os);
33}
34
35
36template <typename _SIZE_>
38{
39 return Interprete::readOn(is);
40}
41
42/*! @brief Main function of the Extract_2D_from_3D interpreter. Data set structure (in dimension 3):
43 *
44 * Extract_2D_from_3D dom3D bord3D dom2D
45 *
46 * @param is Input stream.
47 * @return The input stream.
48 * @throws The object to mesh is not of type Domaine.
49 */
50template <typename _SIZE_>
52{
54 {
55 Cerr << finl;
56 Cerr << "You can not use " << this->que_suis_je() << " on a case already 2D" << finl;
58 }
59 Objet_U::dimension=3; // waooo!! violent :-)
60 int test_axi=0;
61 if (this->que_suis_je()=="Extract_2Daxi_from_3D")
62 {
63 test_axi=1;
64 Cerr<<"We generate a 2D axi domain"<<finl;
65 }
66 Nom nom_bord, nom_dom2D;
67 this->associer_domaine(is);
68 is >> nom_bord >> nom_dom2D;
69 Cerr << "Extraction of boundary " << nom_bord
70 << " of domain " << this->domaine().le_nom()
71 << " --> " << nom_dom2D << finl;
72 {
73 // If the object nom_dom2D does not yet exist,
74 // add a new object to the current block interpreter
76 if (interp.objet_global_existant(nom_dom2D))
77 {
78 if (sub_type(Domaine_t, interp.objet_global(nom_dom2D)))
79 {
80 Cerr << "Domain " << nom_dom2D
81 << " already exists, writing to this object." << finl;
82 }
83 else
84 {
85 Cerr << "Error : object " << nom_dom2D
86 << " already exists and is not a domain." << finl;
88 }
89 }
90 else
91 {
92 Cerr << "Declaring a new domain with name " << nom_dom2D << finl;
93 DerObjU ob;
94 ob.typer("Domaine");
95 interp.ajouter(nom_dom2D, ob);
96 }
97 }
98 Domaine_t& dom2D = ref_cast(Domaine_t, this->objet(nom_dom2D));
99 const Domaine_t& dom3D = this->domaine();
100 const Bord_t& bord3D=dom3D.bord(nom_bord);
102 extraire_2D(dom3D, dom2D, bord3D,nom_bord, test_axi);
104 return is;
105
106}
107
108template <typename _SIZE_>
109void TroisDto2D_32_64<_SIZE_>::extraire_2D(const Domaine_t& dom3D, Domaine_t& dom2D, const Bord_t& bord3D, const Nom& nom_bord, int test_axi)
110{
111 const DoubleTab_t& coord_sommets3D=dom3D.coord_sommets();
112 DoubleTab_t& coord_sommets2D=dom2D.les_sommets();
113 const Faces_t& faces3D=bord3D.faces();
114 const IntTab_t& les_faces3D=faces3D.les_sommets();
115 int_t nb_som3D=coord_sommets3D.dimension(0);
116 Cerr << "number of 3D nodes :" << nb_som3D << finl;
117 int_t nb_faces3D=les_faces3D.dimension(0);
118 Cerr << "number of 3D faces of " << nom_bord << " :" << nb_faces3D << finl;
119 int nb_som_fac3D=les_faces3D.dimension_int(1);
120 Cerr << "number of nodes per faces in 3D :" << nb_som_fac3D << finl;
121
122 // Build renum_som3D2D
123 ArrOfInt_t renum_som3D2D(nb_som3D);
124 for (int_t i=0; i<nb_som3D ; i++)
125 renum_som3D2D[i]=-1;
126 int_t compteur=0;
127 for (int i=0; i<nb_faces3D; i++)
128 for (int j=0; j<nb_som_fac3D; j++)
129 {
130 int_t& tmp=renum_som3D2D[les_faces3D(i,j)];
131 if(tmp==-1)
132 tmp=compteur++;
133 }
134
135 int_t nb_som2D=compteur;
136 // Build renum_som2D3D
137 ArrOfInt_t renum_som2D3D(nb_som2D);
138
139 for (int_t i=0; i<nb_som3D ; i++)
140 {
141 int_t j;
142 if((j=renum_som3D2D[i])!=-1)
143 renum_som2D3D[j]=i;
144 }
145 coord_sommets2D.resize(nb_som2D,2);
146 if (coupe_==2) coord_sommets2D.resize(nb_som2D,3);
147 if(dom3D.type_elem()->que_suis_je()=="Hexaedre")
148 if (test_axi)
149 dom2D.typer("Rectangle_2D_axi");
150 else
151 dom2D.typer("Rectangle");
152 else if(dom3D.type_elem()->que_suis_je()=="Tetraedre")
153 dom2D.typer("Triangle");
154 else if(dom3D.type_elem()->que_suis_je()=="Hexaedre_VEF")
155 dom2D.typer("Quadrangle");
156
157 if (coupe_!=1)
158 {
159 // General algorithm
160 // The boundary must be planar (not verified), parallel to an axis or not
161 // Warning: the coordinates of the 2D domain are in the new frame
162 double xb,yb,zb;
163 double xc,yc,zc;
164 double ux,uy,uz;
165 double norm;
166 double scalI,scalJ;
167
168 xa=0.;
169 ya=0.;
170 za=0.;
171 xb=0.;
172 yb=0.;
173 zb=0.;
174 xc=0.;
175 yc=0.;
176 zc=0;
177 ux=0.;
178 uy=0.;
179 uz=0.;
180 norm=0.;
181 scalI=0.;
182 scalJ=0.;
183
184 // determine an orthonormal frame (A;IJK) on the boundary to extract
185 xa = coord_sommets3D(les_faces3D(0,0),0);
186 ya = coord_sommets3D(les_faces3D(0,0),1);
187 za = coord_sommets3D(les_faces3D(0,0),2);
188
189 xb = coord_sommets3D(les_faces3D(0,1),0);
190 yb = coord_sommets3D(les_faces3D(0,1),1);
191 zb = coord_sommets3D(les_faces3D(0,1),2);
192
193 xc = coord_sommets3D(les_faces3D(0,2),0);
194 yc = coord_sommets3D(les_faces3D(0,2),1);
195 zc = coord_sommets3D(les_faces3D(0,2),2);
196
197 // compute I = AB/norm(AB)
198 Ix=xb-xa;
199 Iy=yb-ya;
200 Iz=zb-za;
201 norm = sqrt(Ix*Ix+Iy*Iy+Iz*Iz);
202 Ix/=norm;
203 Iy/=norm;
204 Iz/=norm;
205
206 // compute K = AB^AC/norm(AB^AC)
207 ux=xc-xa;
208 uy=yc-ya;
209 uz=zc-za;
210 norm = sqrt(ux*ux+uy*uy+uz*uz);
211 ux/=norm;
212 uy/=norm;
213 uz/=norm;
214 Kx = Iy*uz-uy*Iz;
215 Ky = Iz*ux-Ix*uz;
216 Kz = Ix*uy-Iy*ux;
217 norm = sqrt(Kx*Kx+Ky*Ky+Kz*Kz);
218 Kx/=norm;
219 Ky/=norm;
220 Kz/=norm;
221
222 // compute J = K^I
223 Jx = Ky*Iz-Iy*Kz;
224 Jy = Kz*Ix-Iz*Kx;
225 Jz = Kx*Iy-Ky*Ix;
226
227 // dot products OA.I and OA.J
228 scalI = xa*Ix+ya*Iy+za*Iz;
229 scalJ = xa*Jx+ya*Jy+za*Jz;
230
231 // compute the coordinates of the boundary points in the new 2D frame (A;I;J)
232 // by performing a change of frame from the 3D frame to (A;I;J)
233 for(int_t i=0; i<nb_som2D; i++)
234 {
235 double x = coord_sommets3D(renum_som2D3D[i],0);
236 double y = coord_sommets3D(renum_som2D3D[i],1);
237 double z = coord_sommets3D(renum_som2D3D[i],2);
238 if (coupe_==0)
239 {
240 coord_sommets2D(i,0) = -scalI + x*Ix + y*Iy + z*Iz;
241 coord_sommets2D(i,1) = -scalJ + x*Jx + y*Jy + z*Jz;
242 }
243 else
244 {
245 assert(coupe_==2);
246// do not reduce to 2D
247 coord_sommets2D(i,0)=x;
248 coord_sommets2D(i,1)=y;
249 coord_sommets2D(i,2)=z;
250 }
251 // Cout << "coord 1 = " << coord_sommets2D(i,0) << finl;
252 // Cout << "coord 2 = " << coord_sommets2D(i,1) << finl;
253 // Cout << "coord 3 = " << -xa*Kx-ya*Ky-za*Kz+x*Kx + y*Ky + z*Kz << finl;
254 }
255 }
256 else
257 {
258 // Cutting algorithm used by Xprepro in VDF
259 // Warning: limited to a planar boundary parallel to an axis
260 // The coordinates of the 2D domain are preserved
261 int test=0;
262 double precision=DMAXFLOAT;
263 for (test=2; test>-1; test--)
264 {
265 double x1,x2,x3;
266 x1=coord_sommets3D(les_faces3D(0,0),test);
267 x2=coord_sommets3D(les_faces3D(0,1),test);
268 x3=coord_sommets3D(les_faces3D(0,2),test);
269 double tmp=std::fabs(x1-x2);
270 precision=(tmp<precision && tmp>0?tmp:precision);
271 tmp=std::fabs(x3-x2);
272 precision=(tmp<precision && tmp>0?tmp:precision);
273 if (est_egal(x1,x2)&&est_egal(x2,x3)) break;
274 }
275 if (test==-1)
276 {
277 Cerr << "Error into TroisDto2D_32_64.cpp..." << finl;
278 Cerr << "May be the " << dom2D.le_nom() << " boundary domain is not plane enough" << finl;
279 Cerr << "Try to use: PrecisionGeom " << 100*precision << " in your data file" << finl;
280 Cerr << "Or contact TRUST support." << finl;
282 }
283 IntVect dir(2);
284 int kk=0;
285 for (int jj=0; jj<3; jj++)
286 if (test!=jj)
287 {
288 dir[kk]=jj;
289 kk++;
290 }
291 for(int_t i=0; i<nb_som2D; i++)
292 for(int j=0; j<2; j++)
293 coord_sommets2D(i,j)=coord_sommets3D(renum_som2D3D[i],dir[j]);
294 }
295
296 IntTab_t& les_elems2D=dom2D.les_elems();
297 les_elems2D=les_faces3D;
298 for (int_t i=0; i< nb_faces3D; i++)
299 for (int j=0; j< nb_som_fac3D; j++)
300 les_elems2D(i,j)=renum_som3D2D[les_elems2D(i,j)];
301
303 // Retrieve the boundaries:
304 for (const auto& itr: dom3D.faces_bord())
305 {
306 const Frontiere_t& front = itr;
307 const Faces_t& faces3D_front=front.faces();
308 if ( (front.le_nom()!=nom_bord))
309 {
310 Bord_t tmp;
311 Bord_t& bord2D=dom2D.faces_bord().add(tmp);
312 bord2D.nommer(front.le_nom());
313 bord2D.associer_domaine(dom2D);
314 if (test_axi)
315 bord2D.typer_faces("QUADRILATERE_2D_AXI");
316 else
317 bord2D.typer_faces("segment_2D");
318 // create the 2D boundary faces here!
319 int_t compteur2=0;
320 const IntTab_t& faces_sommets=faces3D_front.les_sommets();
321 int_t nb_faces=faces_sommets.dimension(0);
322 IntTab_t& aretes=bord2D.les_sommets_des_faces();
323 IntTab_t& faces_voisins=bord2D.faces().voisins();
324
325 aretes.resize(nb_faces, 2);
326 // Loop over the faces of the 2D domain
327 bool doublons=false;
328 for(int_t face=0; face < nb_faces; face++)
329 {
330 int ok=0;
331 int_t tmpbis;
332 for(int i=0; i<nb_som_fac3D; i++)
333 {
334 tmpbis=renum_som3D2D[faces_sommets(face,i)];
335 if (tmpbis!=-1)
336 {
337 ok++;
338 if(ok==1)
339 aretes(compteur2,0)=tmpbis;
340 if(ok==2)
341 {
342 aretes(compteur2,1)=tmpbis;
343 compteur2++;
344 }
345 if(ok==3)
346 {
347 // If 3 vertices of the face belong to the boundary
348 // there is a problem: add all 3 edges and look for
349 // the duplicates that will need to be removed...
350 doublons=true;
351 aretes(compteur2,0)=aretes(compteur2-1,1);
352 aretes(compteur2,1)=tmpbis;
353 compteur2++;
354 aretes(compteur2,0)=aretes(compteur2-1,1);
355 aretes(compteur2,1)=aretes(compteur2-2,0);
356 compteur2++;
357 }
358 }
359 }
360 }
361 if (doublons)
362 {
363 // Search for duplicates (O(n^2) algorithm)
364 for (int_t i=0; i<compteur2; i++)
365 {
366 int_t& S10=aretes(i,0);
367 int_t& S11=aretes(i,1);
368 for (int_t j=i+1; j<compteur2; j++)
369 {
370 int_t& S20=aretes(j,0);
371 int_t& S21=aretes(j,1);
372 if ( (S10==S20 && S11==S21) || (S10==S21 && S11==S20) )
373 {
374 S10=-1;
375 S11=-1;
376 S20=-1;
377 S21=-1;
378 }
379 }
380 }
381 // Remove duplicates
382 for (int_t i=0; i<compteur2; i++)
383 if (aretes(i,0)==-1)
384 {
385 for (int_t j=i; j<compteur2-1; j++)
386 {
387 aretes(j,0)=aretes(j+1,0);
388 aretes(j,1)=aretes(j+1,1);
389 }
390 compteur2--;
391 }
392 }
393 aretes.resize(compteur2, 2);
394 faces_voisins.resize(compteur2,2);
395 faces_voisins=-1;
396 if (compteur2==0)
397 {
398 Cerr<<"boundary to eliminate " << front.le_nom()<<finl;
399 dom2D.faces_bord().suppr(bord2D);
400 }
401 else
402 {
403 Cerr<<"boundary maintained " << front.le_nom()<<finl;
404 }
405 }
406 }
407
408 // Retrieve the connectors:
409 for (const auto& itr: dom3D.faces_raccord())
410 {
411 const Frontiere_t& front = itr;
412 const Faces_t& faces3Dfront=front.faces();
413 if ( (front.le_nom()!=nom_bord))
414 {
415 Raccord_t tmpbis;
416 Raccord_t& bord2D=dom2D.faces_raccord().add(tmpbis);
417 bord2D.typer(itr->le_type());
418 bord2D->nommer(front.le_nom());
419 bord2D->associer_domaine(dom2D);
420 if (test_axi)
421 bord2D->typer_faces("QUADRILATERE_2D_AXI");
422 else
423 bord2D->typer_faces("segment_2D");
424 // create the 2D boundary faces here!
425 int_t compteur2=0;
426 const IntTab_t& faces_sommets=faces3Dfront.les_sommets();
427 int_t nb_faces=faces_sommets.dimension(0);
428 IntTab_t& aretes=bord2D->les_sommets_des_faces();
429 IntTab_t& faces_voisins=bord2D->faces().voisins();
430
431 aretes.resize(nb_faces, 2);
432 for(int_t face=0; face < nb_faces; face++)
433 {
434 int ok=0;
435 int_t tmp;
436 for(int i=0; i<nb_som_fac3D; i++)
437 {
438 tmp=renum_som3D2D[faces_sommets(face,i)];
439 if (tmp!=-1)
440 {
441 ok++;
442 if(ok==1)
443 aretes(compteur2,0)=tmp;
444 else if(ok==2)
445 {
446 aretes(compteur2,1)=tmp;
447 compteur2++;
448 i=nb_som_fac3D;
449 }
450 }
451 }
452 }
453 aretes.resize(compteur2, 2);
454 faces_voisins.resize(compteur2,2);
455 faces_voisins=-1;
456 if (compteur2==0)
457 {
458 Cerr<<"connector to eliminate " << front.le_nom()<<finl;
459 dom2D.faces_raccord().suppr(bord2D);
460 }
461 else
462 Cerr<<"connector maintained " << front.le_nom()<<finl;
463 }
464 }
465
466 if(dom3D.type_elem()->que_suis_je()!="Hexaedre_VEF")
467 if (coupe_!=2)
468 dom2D.reordonner();
470}
471
472
473template class TroisDto2D_32_64<int>;
474#if INT_is_64_ == 2
475template class TroisDto2D_32_64<trustIdType>;
476#endif
477
478
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
Bord_t & bord(int i)
Definition Domaine.h:193
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
void reordonner()
Definition Domaine.h:104
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
IntTab_t & voisins()
Returns the array of neighbors (of the faces).
Definition Faces.h:89
const IntTab_t & les_sommets() const
Returns the array of vertices of all faces.
Definition Faces.h:74
void nommer(const Nom &) override
Gives a name to the boundary.
Definition Frontiere.cpp:74
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Definition Frontiere.h:49
void typer_faces(const Motcle &)
Sets the type of the boundary faces.
Definition Frontiere.cpp:96
void associer_domaine(const Domaine_t &)
Associates the boundary to the domain it belongs to.
Definition Frontiere.cpp:63
IntTab_t & les_sommets_des_faces()
Returns the vertices of the boundary faces.
const Faces_t & faces() const
Definition Frontiere.h:54
Interprets a block of instructions in the data set.
Objet_U & ajouter(const Nom &nom, DerObjU &object_to_add)
Adds object ob to the interpreter's object list and names it with nom.
static int objet_global_existant(const Nom &nom)
Returns a flag indicating whether an object with this name exists in interprete_courant() or one of i...
static Interprete_bloc & interprete_courant()
Returns the Interprete_bloc currently being read from the data set.
static Objet_U & objet_global(const Nom &nom)
Searches for the requested object in the current Interprete_bloc (Interprete_bloc::interprete_courant...
Class Interprete_geometrique_base.
static Objet_U & objet(const Nom &)
See Interprete_bloc::objet_global(). BM: the Interprete class is not the best place for this.
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
Objet_U * typer(const char *nom_type)
Tries to create an instance of type "type".
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
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
void associer_domaine(const Domaine_t &)
Associates a domain with all connectors in the list.
Definition Raccords.cpp:31
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
int dimension_int(int d) const
Definition TRUSTTab.tpp:152
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
Class TroisDto2D x->alpha x.
Definition TroisDto2D.h:29
void extraire_2D(const Domaine_t &, Domaine_t &, const Bord_t &, const Nom &, int)
Entree & interpreter_(Entree &) override
Main function of the Extract_2D_from_3D interpreter. Data set structure (in dimension 3):
DoubleTab_T< _SIZE_ > DoubleTab_t
Definition TroisDto2D.h:36
Bord_32_64< _SIZE_ > Bord_t
Definition TroisDto2D.h:39
ArrOfInt_T< _SIZE_ > ArrOfInt_t
Definition TroisDto2D.h:34
Domaine_32_64< _SIZE_ > Domaine_t
Definition TroisDto2D.h:38
Frontiere_32_64< _SIZE_ > Frontiere_t
Definition TroisDto2D.h:41
OWN_PTR(Raccord_base_32_64< _SIZE_ >) Raccord_t
Definition TroisDto2D.h:42
Faces_32_64< _SIZE_ > Faces_t
Definition TroisDto2D.h:40
IntTab_T< _SIZE_ > IntTab_t
Definition TroisDto2D.h:35