TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
TRUST_2_CGNS.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 <Domaine_dis_cache.h>
17#include <communications.h>
18#include <Comm_Group_MPI.h>
19#include <TRUST_2_CGNS.h>
20#include <unordered_set>
21#include <Domaine_VF.h>
22#include <Domaine.h>
23#include <cstring>
24
25#ifdef HAS_CGNS
26
27namespace
28{
29#ifdef MPI_
30bool is_comm_group_mode(const bool postraiter_domaine)
31{
33 && Process::is_parallel() && PE_Groups::has_user_defined_group() && !postraiter_domaine;
34}
35
36void allgather_int_on_active_comm(const int local_value, std::vector<int>& global_values, const bool by_comm_grp)
37{
38 if (by_comm_grp)
39 {
41 MPI_Allgather(&local_value, 1, MPI_ENTIER, global_values.data(), 1, MPI_ENTIER, comm_loc.get_mpi_comm());
42 }
43 else
44 MPI_Allgather(&local_value, 1, MPI_ENTIER, global_values.data(), 1, MPI_ENTIER, MPI_COMM_WORLD);
45}
46
47void compute_global_min_max(const std::vector<int>& global_counts, std::vector<int>& global_min, std::vector<int>& global_max, int& total)
48{
49 const int nb_procs = static_cast<int>(global_counts.size());
50 global_min.assign(nb_procs, -123);
51 global_max.assign(nb_procs, -123);
52 total = 0;
53
54 for (int i = 0; i < nb_procs; i++) // now we fill global incremented min/max stuff
55 {
56 global_min[i] = total + 1; // 1 : min
57 total += global_counts[i]; // 2 : increment
58 global_max[i] = total; // 3 : max
59 }
60}
61
62void compute_global_max_only(const std::vector<int>& global_counts, std::vector<int>& global_max, int& total)
63{
64 const int nb_procs = static_cast<int>(global_counts.size());
65 global_max.assign(nb_procs, -123);
66 total = 0;
67
68 for (int i = 0; i < nb_procs; i++)
69 {
70 total += global_counts[i]; // 1 : increment
71 global_max[i] = total; // 2 : max
72 }
73}
74#endif
75}
76
77Motcle TRUST_2_CGNS::modify_field_name_for_post(const Nom& id_du_champ, const Nom& id_du_domaine, const std::string& LOC, int& fieldId_som, int& fieldId_elem, int& fieldId_faces)
78{
79 Motcle id_du_champ_modifie(id_du_champ), iddomaine(id_du_domaine);
80
81 if (LOC == "SOM")
82 {
83 id_du_champ_modifie.prefix(id_du_domaine);
84 id_du_champ_modifie.prefix(iddomaine);
85 id_du_champ_modifie.prefix("_SOM_");
86 }
87 else if (LOC == "ELEM")
88 {
89 id_du_champ_modifie.prefix(id_du_domaine);
90 id_du_champ_modifie.prefix(iddomaine);
91 id_du_champ_modifie.prefix("_ELEM_");
92 }
93 else if (LOC == "FACES")
94 {
95 id_du_champ_modifie.prefix(id_du_domaine);
96 id_du_champ_modifie.prefix(iddomaine);
97 id_du_champ_modifie.prefix("_FACES_");
98 }
99 else
100 throw std::runtime_error("TRUST_2_CGNS::modify_field_name_for_post => Unsupported LOC : " + LOC);
101
102 (LOC == "SOM") ? fieldId_som++ : ( (LOC == "ELEM") ? fieldId_elem++ : fieldId_faces++);
103
104 /*
105 * XXX Elie Saikali : in CGNS we are limited to char size 32 max ! otherwise not supported (see method cgi_check_strlen ...)
106 * Go Bricorama !
107 */
108
109 const char * id_char = id_du_champ_modifie.getChar();
110 size_t sz = std::strlen(id_char);
111 if (sz > CGNS_STR_SIZE)
112 {
113#ifndef NDEBUG
114 Cerr << "The field " << id_char << " contains " << sz << " chars & CGNS is limited to " << CGNS_STR_SIZE << " ==> renamed to ";
115#endif
116
117 std::string new_id_du_champ_modifie(id_char);
118
119 auto replace_all = [](std::string& s, const std::string& from, const std::string& to)
120 {
121 size_t pos = 0;
122 while ((pos = s.find(from, pos)) != std::string::npos)
123 {
124 s.replace(pos, from.length(), to);
125 pos += to.length();
126 }
127 };
128
129 // 1. First attempt: remove case name prefix if needed
130 Motcle truncate_try_1(id_du_champ_modifie), nom_du_cas(Objet_U::nom_du_cas());
131 truncate_try_1.suffix(nom_du_cas.getChar());
132 truncate_try_1.suffix("_");
133
134 if (std::strlen(truncate_try_1.getChar()) <= CGNS_STR_SIZE)
135 new_id_du_champ_modifie = truncate_try_1.getChar();
136
137
138 // 2. If still too long, try a few abbreviation replacements
139 if (new_id_du_champ_modifie.size() > CGNS_STR_SIZE)
140 {
141 replace_all(new_id_du_champ_modifie, "VITESSE", "VIT");
142 replace_all(new_id_du_champ_modifie, "TEMPERATURE", "TEMP");
143 replace_all(new_id_du_champ_modifie, "CONCENTRATION", "CONC");
144 replace_all(new_id_du_champ_modifie, "CONVECTION", "CONV");
145 replace_all(new_id_du_champ_modifie, "DIFFUSION", "DIFF");
146 replace_all(new_id_du_champ_modifie, "VISQUEUSE", "VISQ");
147 replace_all(new_id_du_champ_modifie, "MASSE_VOLUMIQUE", "RHO");
148 replace_all(new_id_du_champ_modifie, "LIQUIDE", "LIQ");
149 }
150
151 // 3. If still too long .. truly sorry !
152 if (new_id_du_champ_modifie.size() > CGNS_STR_SIZE)
153 {
154 static constexpr size_t keep_first = 25;
155 static constexpr size_t keep_last = 5;
156
157 const size_t new_sz = new_id_du_champ_modifie.size();
158 const std::string prem = new_id_du_champ_modifie.substr(0, keep_first);
159 const std::string der = new_id_du_champ_modifie.substr(new_sz - keep_last, keep_last);
160
161 new_id_du_champ_modifie = prem + "__" + der;
162 }
163
164 id_du_champ_modifie = Motcle(new_id_du_champ_modifie.c_str());
165
166#ifndef NDEBUG
167 Cerr << id_du_champ_modifie << " !!! " << finl;
168#endif
169 }
170
171 return id_du_champ_modifie;
172}
173
174// to strip boundaries_ from the domain name (added by TRUST for boundary subdomains ...)
175std::string TRUST_2_CGNS::modify_domaine_name_for_post(const Nom& nom_dom)
176{
177 std::string nom_dom_modifie = nom_dom.getString();
178
179 if (static_cast<int>(nom_dom_modifie.size()) >= CGNS_STR_SIZE)
180 {
181 size_t found = nom_dom_modifie.find("boundaries_");
182 if (found != std::string::npos)
183 nom_dom_modifie.erase(found, 11); // 11 is the length of "boundaries_"
184
185// if (static_cast<int>(nom_dom_modifie.size()) >= CGNS_STR_SIZE)
186// nom_dom_modifie.resize(CGNS_STR_SIZE, ' ');
187 if (static_cast<int>(nom_dom_modifie.size()) >= CGNS_STR_SIZE)
188 nom_dom_modifie.erase(CGNS_STR_SIZE-1);
189 }
190
191 return nom_dom_modifie;
192}
193
194void TRUST_2_CGNS::map_face_values(const Domaine_VF& dom_vf, const DoubleTab& val_src, DoubleTrav& val_trgt)
195{
196 const auto& dual_m = dom_vf.get_mc_dual_mesh();
197 const int nb_cells = static_cast<int>(dual_m->getNumberOfCells());
198 const auto& face_voisins = dom_vf.get_face_voisins_dual();
199
200 assert (val_src.nb_dim() == 2);
201 const int nb_j = val_src.dimension(1);
202 val_trgt.resize(nb_cells, nb_j);
203
204 for (int f = 0; f < val_src.dimension(0); f++)
205 {
206 const int e1 = face_voisins(f, 0), e2 = face_voisins(f, 1);
207 for (int e: {e1, e2})
208 {
209 if (e < 0) continue;
210
211// for (int comp = 0; comp < nb_j; comp++)
212// val_trgt(e, comp) = val_src(f, comp);
213 std::copy_n(&val_src(f, 0), nb_j, &val_trgt(e, 0));
214 }
215 }
216}
217
218void TRUST_2_CGNS::associer_domaine_TRUST(const Domaine * dom, const Domaine_dis_base* dom_dis, const DoubleTab& som, const IntTab& elem, const bool post_dom, const std::string& discr_type)
219{
220 if (dom) dom_trust_ = *dom;
221 if (dom_dis) domaine_dis_ = *dom_dis;
222 sommets_ = som;
223 elems_ = elem;
224 postraiter_domaine_ = post_dom;
225 discr_type_ = discr_type;
226}
227
228void TRUST_2_CGNS::associer_connec_pour_dual(const IntTab& fs, const IntTab& ef)
229{
230 fs_dual_ = fs;
231 ef_dual_ = ef;
232}
233
234void TRUST_2_CGNS::fill_coords(std::vector<double>& xCoords, std::vector<double>& yCoords, std::vector<double>& zCoords) const
235{
236 const int nb_som = sommets_->dimension(0), phys_dim = Objet_U::dimension;
237 const DoubleTab& sommets = sommets_.valeur();
238 assert (sommets_->dimension(1) > 1);
239
240 xCoords.resize(nb_som);
241 yCoords.resize(nb_som);
242
243 if (phys_dim == 3)
244 {
245 assert(sommets_->dimension(1) > 2);
246 zCoords.resize(nb_som);
247 }
248 else
249 zCoords.clear();
250
251 if (Objet_U::axi) // just in case
252 {
253 for (int i = 0; i < nb_som; ++i)
254 {
255 const double r = sommets(i, 0), theta = sommets(i, 1);
256 xCoords[i] = r * cos(theta);
257 yCoords[i] = r * sin(theta);
258 if (phys_dim == 3)
259 zCoords[i] = sommets(i, 2);
260 }
261 }
262 else
263 {
264 for (int i = 0; i < nb_som; ++i)
265 {
266 xCoords[i] = sommets(i, 0);
267 yCoords[i] = sommets(i, 1);
268 if (phys_dim == 3)
269 zCoords[i] = sommets(i, 2);
270 }
271 }
272}
273
274/*
275 * NOTA BENE : postraiter_domaine_ always behaves like PARALLEL_OVER_ZONE, even when it is not active
276 */
277void TRUST_2_CGNS::clear_vectors()
278{
279 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_) // XXX to be revisited later if still useful to keep
280 {
281 proc_non_zero_elem_.clear();
282 global_nb_elem_.clear();
283 global_nb_som_.clear();
284 }
285
286 // globaux
287 global_nb_face_som_.clear();
288 global_nb_face_som_offset_.clear();
289 global_nb_elem_face_.clear();
290 global_nb_elem_face_offset_.clear();
291 global_nb_elem_som_offset_.clear();
292
293 global_incr_min_face_som_.clear();
294 global_incr_max_face_som_.clear();
295 global_incr_min_elem_face_.clear();
296 global_incr_max_elem_face_.clear();
297
298 // locaux
299 local_fs_.clear();
300 local_fs_offset_.clear();
301 local_ef_.clear();
302 local_ef_offset_.clear();
303 local_es_.clear();
304 local_es_offset_.clear();
305}
306
307void TRUST_2_CGNS::fill_global_infos()
308{
309#ifdef MPI_
310 assert (sommets_ && elems_);
311 proc_non_zero_elem_.clear();
312 all_procs_write_ = true;
313
314 const bool by_comm_grp = is_comm_group_mode(postraiter_domaine_);
315
316 if (by_comm_grp)
317 {
318 const auto& grp = PE_Groups::get_user_defined_group();
319 if (PE_Groups::enter_group(grp))
320 {
321 proc_me_local_comm_ = Process::me();
322 nb_proc_local_comm_ = Process::nproc();
324 }
325 }
326 else /* otherwise, just in case ... */
327 {
328 proc_me_local_comm_ = Process::me();
329 nb_proc_local_comm_ = Process::nproc();
330 }
331
332 const int nb_procs = by_comm_grp ? nb_proc_local_comm_ : Process::nproc();
333 const int nb_som = sommets_->dimension(0), nb_elem = elems_->dimension(0);
334
335 par_in_zone_ = (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_) ? true : false;
336
337 global_nb_elem_.assign(nb_procs, -123 /* default */);
338 global_nb_som_.assign(nb_procs, -123 /* default */);
339
340 allgather_int_on_active_comm(nb_elem, global_nb_elem_, by_comm_grp);
341 allgather_int_on_active_comm(nb_som, global_nb_som_, by_comm_grp);
342
343 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
344 {
345 compute_global_min_max(global_nb_elem_, global_incr_min_elem_, global_incr_max_elem_, ne_tot_);
346 compute_global_min_max(global_nb_som_, global_incr_min_som_, global_incr_max_som_, ns_tot_);
347 }
348
349 const auto min_nb_elem = std::min_element(global_nb_elem_.begin(), global_nb_elem_.end());
350 nb_procs_writing_ = nb_procs; // for now
351
352 if (*min_nb_elem <= 0) // not all procs will write !
353 {
354 // fill proc_non_zero_elem with the proc number if nb_elem > 0 !!
355 for (int i = 0; i < static_cast<int>(global_nb_elem_.size()); i++)
356 if (global_nb_elem_[i] > 0) proc_non_zero_elem_.push_back(i);
357
358 nb_procs_writing_ = static_cast<int>(proc_non_zero_elem_.size());
359 all_procs_write_ = false;
360 }
361#endif
362}
363
364void TRUST_2_CGNS::get_domaine_dis_vf_if_poly(Domaine_dis_base*& domaine_dis, Domaine_VF*& vf)
365{
366 assert(dom_trust_);
367 domaine_dis = nullptr;
368 vf = nullptr;
369
370 if (!fs_dual_ && !ef_dual_)
371 {
372 if (domaine_dis_
373 && domaine_dis_->domaine().le_nom() == dom_trust_->le_nom() // XXX peut etre sous_zone ;)
374 && domaine_dis_->face_sommets().size() > 0) // see if well filled for example
375 {
376 domaine_dis = &(domaine_dis_.valeur());
377 }
378 else
379 {
380 if (discr_type_ != "")
381 domaine_dis = &(Domaine_dis_cache::Build_or_get_poly_post(discr_type_, dom_trust_.valeur()));
382 else
383 {
384 // the user seems to post the domaine before discretizing the domain of before filling the post bloc ... we try our chance with Domaine_PolyMAC_MPFA
385 Nom type = "Domaine_PolyMAC_MPFA";
386 domaine_dis = &(Domaine_dis_cache::Build_or_get_poly_post(type, dom_trust_.valeur()));
387 }
388 }
389
390 vf = &(ref_cast (Domaine_VF, *domaine_dis));
391 }
392}
393
394void TRUST_2_CGNS::fill_global_infos_poly(const bool is_polyedre)
395{
396#ifdef MPI_
397 assert(dom_trust_);
398
399 const bool by_comm_grp = is_comm_group_mode(postraiter_domaine_);
400
401 int decal = 0; // to be updated later !!!
402 const int nb_procs = by_comm_grp ? nb_proc_local_comm_ : Process::nproc();
403
404 par_in_zone_ = (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_) ? true : false;
405
406 if (is_polyedre)
407 {
408 Domaine_dis_base* domaine_dis = nullptr;
409 Domaine_VF* vf = nullptr;
410 get_domaine_dis_vf_if_poly(domaine_dis, vf);
411
412 const IntTab& fs = vf ? (*vf).face_sommets() : fs_dual_.valeur();
413 const IntTab& ef = vf ? (*vf).elem_faces() : ef_dual_.valeur();
414 const int nb_fs = fs.dimension(0), nb_ef = ef.dimension(0);
415
416 global_nb_face_som_.assign(nb_procs, -123 /* default */);
417 global_nb_elem_face_.assign(nb_procs, -123 /* default */);
418
419 allgather_int_on_active_comm(nb_fs, global_nb_face_som_, by_comm_grp);
420 allgather_int_on_active_comm(nb_ef, global_nb_elem_face_, by_comm_grp);
421
422 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
423 {
424 compute_global_min_max(global_nb_face_som_, global_incr_min_face_som_, global_incr_max_face_som_, nfs_tot_);
425 compute_global_min_max(global_nb_elem_face_, global_incr_min_elem_face_, global_incr_max_elem_face_, nef_tot_);
426 }
427
428 // face_sommets : local vectors + offset
429 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
430 decal = compute_shift(global_incr_max_som_); // shift by sommets !!
431
432 nb_fs_ = convert_connectivity_ngon(local_fs_, local_fs_offset_, is_polyedre, decal);
433
434 // elem_faces : local vectors + offset
435 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
436 decal = compute_shift(global_incr_max_face_som_); // shift by faces !!
437
438 nb_ef_ = convert_connectivity_nface(local_ef_, local_ef_offset_, decal);
439
440 // finally: compute offset shift
441 const int nb_fs_offset = static_cast<int>(local_fs_.size()), nb_ef_offset = static_cast<int>(local_ef_.size());
442
443 global_nb_face_som_offset_.assign(nb_procs, -123 /* default */);
444 global_nb_elem_face_offset_.assign(nb_procs, -123 /* default */);
445
446 allgather_int_on_active_comm(nb_fs_offset, global_nb_face_som_offset_, by_comm_grp);
447 allgather_int_on_active_comm(nb_ef_offset, global_nb_elem_face_offset_, by_comm_grp);
448
449 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
450 {
451 // increment on nb_faces and nb_elem total offset
452 std::vector<int> global_incr_max_face_som_offset, global_incr_max_elem_face_offset;
453 compute_global_max_only(global_nb_face_som_offset_, global_incr_max_face_som_offset, nfs_offset_tot_);
454 compute_global_max_only(global_nb_elem_face_offset_, global_incr_max_elem_face_offset, nef_offset_tot_);
455
456 decal = compute_shift(global_incr_max_face_som_offset); // shift by faces offset !!
457 for (auto &itr : local_fs_offset_) itr += decal;
458
459 decal = compute_shift(global_incr_max_elem_face_offset); // shift by elem offset !!
460 for (auto &itr : local_ef_offset_) itr += decal;
461 }
462 }
463 else // polygon
464 {
465 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
466 decal = compute_shift(global_incr_max_som_); // shift by sommets !!
467
468 nb_es_ = convert_connectivity_ngon(local_es_, local_es_offset_, is_polyedre, decal);
469
470 const int nb_es_offset = static_cast<int>(local_es_.size());
471
472 // increment on nb_elem total offset
473 global_nb_elem_som_offset_.assign(nb_procs, -123 /* default */);
474
475 allgather_int_on_active_comm(nb_es_offset, global_nb_elem_som_offset_, by_comm_grp);
476
477 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
478 {
479 std::vector<int> global_incr_max_elem_som_offset;
480 compute_global_max_only(global_nb_elem_som_offset_, global_incr_max_elem_som_offset, nes_offset_tot_);
481
482 decal = compute_shift(global_incr_max_elem_som_offset); // shift by elem offset !!
483 for (auto &itr : local_es_offset_) itr += decal;
484 }
485 }
486#endif
487}
488
489int TRUST_2_CGNS::compute_shift(const std::vector<int>& vect_incr_max) const
490{
491#ifdef MPI_
492 assert(par_in_zone_);
493
494 const bool by_comm_grp = is_comm_group_mode(postraiter_domaine_);
495
496 int proc_me = by_comm_grp ? proc_me_local_comm_ : Process::me();
497
498 int decal = 0;
499 if (all_procs_write_)
500 {
501 if (proc_me > 0) // not master
502 decal = vect_incr_max[proc_me - 1];
503 }
504 else
505 {
506 for (int i = 0; i < nb_procs_writing_; i++)
507 if (proc_non_zero_elem_[i] == proc_me)
508 if (i > 0) // not the first case
509 {
510 decal = vect_incr_max[proc_non_zero_elem_[i] - 1];
511 break;
512 }
513 }
514 return decal;
515#else
516 return 0;
517#endif
518}
519
520int TRUST_2_CGNS::convert_connectivity(const CGNS_TYPE type, std::vector<cgsize_t>& conn_elem ) const
521{
522 const int nb_elem = elems_->dimension(0);
523 const IntTab& les_elems = elems_.valeur();
524 int decal = par_in_zone_ ? compute_shift(global_incr_max_som_) : 0;
525
526 int nodes_per_elem = -1;
527
528 switch(type)
529 {
530 case CGNS_ENUMV(HEXA_8):
531 nodes_per_elem = 8;
532 break;
533 case CGNS_ENUMV(QUAD_4):
534 nodes_per_elem = 4;
535 break;
536 case CGNS_ENUMV(TETRA_4):
537 nodes_per_elem = 4;
538 break;
539 case CGNS_ENUMV(TRI_3):
540 nodes_per_elem = 3;
541 break;
542 case CGNS_ENUMV(BAR_2):
543 nodes_per_elem = 2;
544 break;
545 case CGNS_ENUMV(NODE):
546 nodes_per_elem = 1;
547 break;
548 default:
549 Cerr << "Type not yet coded in TRUST_2_CGNS::convert_connectivity ! Call the 911 !" << finl;
551 return -100;
552 }
553
554 if (nodes_per_elem != elems_->dimension(1))
555 {
556 Cerr << "Big issue in TRUST_2_CGNS::convert_connectivity !!!" << finl;
557 Cerr << " We have nodes_per_elem = " << nodes_per_elem << " while we have a connectivity of width = " << elems_->dimension(1) << finl;
559 return -100;
560 }
561
562 conn_elem.resize(nb_elem * nodes_per_elem); // allocation une fois
563 cgsize_t* data = conn_elem.data();
564
565 switch(type)
566 {
567 case CGNS_ENUMV(HEXA_8):
568 for (int i = 0; i < nb_elem; i++)
569 {
570 *data++ = les_elems(i, 0) + 1 + decal;
571 *data++ = les_elems(i, 1) + 1 + decal;
572 *data++ = les_elems(i, 3) + 1 + decal;
573 *data++ = les_elems(i, 2) + 1 + decal;
574 *data++ = les_elems(i, 4) + 1 + decal;
575 *data++ = les_elems(i, 5) + 1 + decal;
576 *data++ = les_elems(i, 7) + 1 + decal;
577 *data++ = les_elems(i, 6) + 1 + decal;
578 }
579 break;
580
581 case CGNS_ENUMV(QUAD_4):
582 for (int i = 0; i < nb_elem; i++)
583 {
584 *data++ = les_elems(i, 0) + 1 + decal;
585 *data++ = les_elems(i, 1) + 1 + decal;
586 *data++ = les_elems(i, 3) + 1 + decal;
587 *data++ = les_elems(i, 2) + 1 + decal;
588 }
589 break;
590
591 case CGNS_ENUMV(TETRA_4):
592 case CGNS_ENUMV(TRI_3):
593 case CGNS_ENUMV(BAR_2):
594 case CGNS_ENUMV(NODE):
595 for (int i = 0; i < nb_elem; i++)
596 for (int j = 0; j < nodes_per_elem; j++)
597 *data++ = les_elems(i, j) + 1 + decal;
598 break;
599
600 default: /* already handled above */
601 break;
602 }
603
604 return nodes_per_elem;
605}
606
607CGNS_TYPE TRUST_2_CGNS::convert_elem_type(const Motcle& type) const
608{
609 assert(elems_);
610 const int nb_comp = elems_->dimension(1);
611
612 if (type.debute_par("HEXAEDRE"))
613 return CGNS_ENUMV(HEXA_8);
614 else if (type.debute_par("RECTANGLE") || type.debute_par("QUADRANGLE"))
615 return CGNS_ENUMV(QUAD_4);
616 else if (type == "TETRAEDRE")
617 return CGNS_ENUMV(TETRA_4);
618 else if (type.debute_par("TRIANGLE"))
619 return CGNS_ENUMV(TRI_3);
620 else if (type == "POINT")
621 return CGNS_ENUMV(NODE);
622 else if (type == "POLYEDRE" || type.debute_par("POLYGONE") || type.debute_par("PRISME"))
623 return CGNS_ENUMV(NGON_n);
624 else if (type.debute_par("SEGMENT"))
625 {
626 /* So bad ... EF defined Bds as segments not points ... */
627 if (nb_comp == 1) return CGNS_ENUMV(NODE);
628 if (nb_comp == 2) return CGNS_ENUMV(BAR_2);
629
630 Cerr << "Unexpected SEGMENT connectivity of width = " << nb_comp << finl;
631 return CGNS_ENUMV(ElementTypeNull);
632 }
633 else
634 {
635 Cerr << "The type " << type << " is not yet available for the CGNS format ! Call the 911 !" << finl;
637 return CGNS_ENUMV(ElementTypeNull);
638 }
639}
640
641int TRUST_2_CGNS::topo_dim_from_elem(CGNS_TYPE etype, bool is_polyedre) const
642{
643 if (etype == CGNS_ENUMV(BAR_2) || etype == CGNS_ENUMV(NODE))
644 return 1; // 1D
645
646 if (etype == CGNS_ENUMV(TRI_3) || etype == CGNS_ENUMV(QUAD_4))
647 return 2; // 2D classiques
648
649 if (etype == CGNS_ENUMV(NGON_n))
650 return is_polyedre ? 3 : 2; // NGON_n : 2D if polygon, 3D if polyhedron (with NFACE_n)
651
652 // 3D classiques
653 return 3; // TETRA_4, HEXA_8, NFACE_n
654}
655
656int TRUST_2_CGNS::convert_connectivity_nface(std::vector<cgsize_t>& econ, std::vector<cgsize_t>& eoff, int decal)
657{
658 assert (dom_trust_);
659
660 Domaine_dis_base *domaine_dis = nullptr;
661 Domaine_VF *vf = nullptr;
662 get_domaine_dis_vf_if_poly(domaine_dis, vf);
663
664 const IntTab& ef = vf ? (*vf).elem_faces() : ef_dual_.valeur();
665
666 const int nElem = ef.dimension(0), maxDeg = ef.dimension(1);
667
668 econ.clear(), eoff.clear();
669
670 econ.reserve(static_cast<size_t>(nElem) * maxDeg); // each element has at most maxDeg faces
671 eoff.reserve(static_cast<size_t>(nElem) + 1); // one per element + 1 for the end
672
673 eoff.push_back(0); // first index = > 0 !
674
675 int s = 0;
676 for (int e = 0; e < nElem; ++e)
677 {
678 for (int j = 0; j < maxDeg; ++j)
679 {
680 const int f = ef(e, j);
681 if (f < 0)
682 break;
683
684 econ.push_back(static_cast<cgsize_t>(f + 1 + decal));
685 ++s;
686 }
687 eoff.push_back(s);
688 }
689
690 // XXX Elie Saikali ...
691 // we need this to avoid the following warning
692 // reading zone "Zone_0002"
693 // reading element set "NGON_n"
694 // reading element set "NFACE_n"
695 // ERROR: duplicate positive faces indices detected in NFace_n Elements connectivity
696 std::unordered_set<cgsize_t> seen;
697 for (auto& itr : econ)
698 {
699 if (seen.find(itr) != seen.end())
700 itr *= -1; // already seen -> times -1 !!!
701 else
702 seen.insert(itr);
703 }
704
705 return ef.dimension(0);
706}
707
708int TRUST_2_CGNS::convert_connectivity_ngon(std::vector<cgsize_t>& econ, std::vector<cgsize_t>& eoff, const bool is_polyedre, int decal)
709{
710 assert (dom_trust_);
711 if (is_polyedre)
712 {
713 Domaine_dis_base* domaine_dis = nullptr;
714 Domaine_VF* vf = nullptr;
715 get_domaine_dis_vf_if_poly(domaine_dis, vf);
716
717 const IntTab& fs = vf ? (*vf).face_sommets() : fs_dual_.valeur();
718
719 const int nFace = fs.dimension(0), maxDeg = fs.dimension(1);
720
721 econ.clear(), eoff.clear();
722
723 econ.reserve(static_cast<size_t>(nFace) * maxDeg);
724 eoff.reserve(static_cast<size_t>(nFace) + 1);
725
726 eoff.push_back(0); // first index = > 0 !
727 int s = 0;
728 for (int f = 0; f < nFace; ++f)
729 {
730 for (int j = 0; j < maxDeg; ++j)
731 {
732 const int v = fs(f, j);
733 if (v < 0)
734 break;
735
736 econ.push_back(static_cast<cgsize_t>(v + 1 + decal));
737 ++s;
738 }
739 eoff.push_back(s);
740 }
741
742 return fs.dimension(0);
743 }
744 else // POLYGONE
745 {
746 const IntTab& les_elems = dom_trust_->les_elems();
747
748 const int nElem = les_elems.dimension(0), maxDeg = les_elems.dimension(1);
749
750 econ.clear(), eoff.clear();
751
752 econ.reserve(static_cast<size_t>(nElem) * maxDeg);
753 eoff.reserve(static_cast<size_t>(nElem) + 1);
754
755 eoff.push_back(0); // first index = > 0 !
756 int s = 0;
757 for (int e = 0; e < nElem; ++e)
758 {
759 for (int j = 0; j < maxDeg; ++j)
760 {
761 const int v = les_elems(e, j);
762 if (v < 0)
763 break;
764 econ.push_back(static_cast<cgsize_t>(v + 1 + decal));
765 ++s;
766 }
767 eoff.push_back(s);
768 }
769
770 return les_elems.dimension(0);
771 }
772}
773
774#endif /* HAS_CGNS */
: Class Comm_Group_MPI, derived from the abstract class Comm_Group.
class Domaine_VF
Definition Domaine_VF.h:44
const IntTab & get_face_voisins_dual() const
Definition Domaine_VF.h:195
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
int elem_faces(int i, int j) const
Returns the index of the i-th face of element num_elem; the face numbering convention is.
Definition Domaine_VF.h:542
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
static Domaine_dis_base & Build_or_get_poly_post(const Nom &type, const Domaine &dom)
A character string (Nom) in uppercase.
Definition Motcle.h:26
int debute_par(const char *const n) const override
Definition Motcle.cpp:307
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
const std::string & getString() const
Definition Nom.h:92
static int dimension
Definition Objet_U.h:94
static const Nom & nom_du_cas()
Returns a constant reference to the case name. This method is static.
Definition Objet_U.cpp:145
static int axi
Definition Objet_U.h:96
static bool LINKED_FILES_PER_COMM_GROUP
Definition Option_CGNS.h:52
static bool PARALLEL_OVER_ZONE
Definition Option_CGNS.h:48
static bool SINGLE_FILE_PER_COMM_GROUP
Definition Option_CGNS.h:48
static int enter_group(const Comm_Group &group)
If the local processor belongs to the group, the current group for this processor becomes "group" and...
static const Comm_Group & get_user_defined_group()
Returns a reference to the user-defined group.
static bool has_user_defined_group()
static void exit_group()
Returns to the group that was active before the last successful enter_group() call (which returned 1)...
static bool is_parallel()
Definition Process.cpp:108
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
Definition Process.cpp:102
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
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(int d) const
Definition TRUSTTab.tpp:133