TRUST 1.9.8
HPC thermohydraulic platform
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 : dans CGNS on est limite a char de taille 32 max ! sinon pas supporte (regarde la methode 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. Premier essai : prefixer par le nom du cas si besoin
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. Si toujours trop long, on tente qlqs remplacements
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. Si encore trop long .. vraiment desole !
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// pour retirer boundaries_ du nom dom (ajoute par TRUST pour les bords ...)
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) // au cas ou
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_ toujours comme PARALLEL_OVER_ZONE, meme si c'est pas active
276 */
277void TRUST_2_CGNS::clear_vectors()
278{
279 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_) // XXX a voir plus tard si utile pour garder
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
312 const bool by_comm_grp = is_comm_group_mode(postraiter_domaine_);
313
314 if (by_comm_grp)
315 {
316 const auto& grp = PE_Groups::get_user_defined_group();
317 if (PE_Groups::enter_group(grp))
318 {
319 proc_me_local_comm_ = Process::me();
320 nb_proc_local_comm_ = Process::nproc();
322 }
323 }
324 else /* sinon au cas ou ... */
325 {
326 proc_me_local_comm_ = Process::me();
327 nb_proc_local_comm_ = Process::nproc();
328 }
329
330 const int nb_procs = by_comm_grp ? nb_proc_local_comm_ : Process::nproc();
331 const int nb_som = sommets_->dimension(0), nb_elem = elems_->dimension(0);
332
333 par_in_zone_ = (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_) ? true : false;
334
335 global_nb_elem_.assign(nb_procs, -123 /* default */);
336 global_nb_som_.assign(nb_procs, -123 /* default */);
337
338 allgather_int_on_active_comm(nb_elem, global_nb_elem_, by_comm_grp);
339 allgather_int_on_active_comm(nb_som, global_nb_som_, by_comm_grp);
340
341 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
342 {
343 compute_global_min_max(global_nb_elem_, global_incr_min_elem_, global_incr_max_elem_, ne_tot_);
344 compute_global_min_max(global_nb_som_, global_incr_min_som_, global_incr_max_som_, ns_tot_);
345 }
346
347 const auto min_nb_elem = std::min_element(global_nb_elem_.begin(), global_nb_elem_.end());
348 nb_procs_writing_ = nb_procs; // pour le moment
349
350 if (*min_nb_elem <= 0) // not all procs will write !
351 {
352 // remplir proc_non_zero_elem avec le numero de proc si nb_elem > 0 !!
353 for (int i = 0; i < static_cast<int>(global_nb_elem_.size()); i++)
354 if (global_nb_elem_[i] > 0) proc_non_zero_elem_.push_back(i);
355
356 nb_procs_writing_ = static_cast<int>(proc_non_zero_elem_.size());
357 all_procs_write_ = false;
358 }
359#endif
360}
361
362void TRUST_2_CGNS::get_domaine_dis_vf_if_poly(Domaine_dis_base*& domaine_dis, Domaine_VF*& vf)
363{
364 assert(dom_trust_);
365 domaine_dis = nullptr;
366 vf = nullptr;
367
368 if (!fs_dual_ && !ef_dual_)
369 {
370 if (domaine_dis_
371 && domaine_dis_->domaine().le_nom() == dom_trust_->le_nom() // XXX peut etre sous_zone ;)
372 && domaine_dis_->face_sommets().size() > 0) // see if well filled for example
373 {
374 domaine_dis = &(domaine_dis_.valeur());
375 }
376 else
377 {
378 if (discr_type_ != "")
379 domaine_dis = &(Domaine_dis_cache::Build_or_get_poly_post(discr_type_, dom_trust_.valeur()));
380 else
381 {
382 // 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
383 Nom type = "Domaine_PolyMAC_MPFA";
384 domaine_dis = &(Domaine_dis_cache::Build_or_get_poly_post(type, dom_trust_.valeur()));
385 }
386 }
387
388 vf = &(ref_cast (Domaine_VF, *domaine_dis));
389 }
390}
391
392void TRUST_2_CGNS::fill_global_infos_poly(const bool is_polyedre)
393{
394#ifdef MPI_
395 assert(dom_trust_);
396
397 const bool by_comm_grp = is_comm_group_mode(postraiter_domaine_);
398
399 int decal = 0; // a modifier plus tard !!!
400 const int nb_procs = by_comm_grp ? nb_proc_local_comm_ : Process::nproc();
401
402 par_in_zone_ = (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_) ? true : false;
403
404 if (is_polyedre)
405 {
406 Domaine_dis_base* domaine_dis = nullptr;
407 Domaine_VF* vf = nullptr;
408 get_domaine_dis_vf_if_poly(domaine_dis, vf);
409
410 const IntTab& fs = vf ? (*vf).face_sommets() : fs_dual_.valeur();
411 const IntTab& ef = vf ? (*vf).elem_faces() : ef_dual_.valeur();
412 const int nb_fs = fs.dimension(0), nb_ef = ef.dimension(0);
413
414 global_nb_face_som_.assign(nb_procs, -123 /* default */);
415 global_nb_elem_face_.assign(nb_procs, -123 /* default */);
416
417 allgather_int_on_active_comm(nb_fs, global_nb_face_som_, by_comm_grp);
418 allgather_int_on_active_comm(nb_ef, global_nb_elem_face_, by_comm_grp);
419
420 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
421 {
422 compute_global_min_max(global_nb_face_som_, global_incr_min_face_som_, global_incr_max_face_som_, nfs_tot_);
423 compute_global_min_max(global_nb_elem_face_, global_incr_min_elem_face_, global_incr_max_elem_face_, nef_tot_);
424 }
425
426 // face_sommets : local vectors + offset
427 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
428 decal = compute_shift(global_incr_max_som_); // shift by sommets !!
429
430 nb_fs_ = convert_connectivity_ngon(local_fs_, local_fs_offset_, is_polyedre, decal);
431
432 // elem_faces : local vectors + offset
433 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
434 decal = compute_shift(global_incr_max_face_som_); // shift by faces !!
435
436 nb_ef_ = convert_connectivity_nface(local_ef_, local_ef_offset_, decal);
437
438 // finalement : decalage
439 const int nb_fs_offset = static_cast<int>(local_fs_.size()), nb_ef_offset = static_cast<int>(local_ef_.size());
440
441 global_nb_face_som_offset_.assign(nb_procs, -123 /* default */);
442 global_nb_elem_face_offset_.assign(nb_procs, -123 /* default */);
443
444 allgather_int_on_active_comm(nb_fs_offset, global_nb_face_som_offset_, by_comm_grp);
445 allgather_int_on_active_comm(nb_ef_offset, global_nb_elem_face_offset_, by_comm_grp);
446
447 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
448 {
449 // incr sur nb_faces et nb_elem tot offset
450 std::vector<int> global_incr_max_face_som_offset, global_incr_max_elem_face_offset;
451 compute_global_max_only(global_nb_face_som_offset_, global_incr_max_face_som_offset, nfs_offset_tot_);
452 compute_global_max_only(global_nb_elem_face_offset_, global_incr_max_elem_face_offset, nef_offset_tot_);
453
454 decal = compute_shift(global_incr_max_face_som_offset); // shift by faces offset !!
455 for (auto &itr : local_fs_offset_) itr += decal;
456
457 decal = compute_shift(global_incr_max_elem_face_offset); // shift by elem offset !!
458 for (auto &itr : local_ef_offset_) itr += decal;
459 }
460 }
461 else // polygon
462 {
463 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
464 decal = compute_shift(global_incr_max_som_); // shift by sommets !!
465
466 nb_es_ = convert_connectivity_ngon(local_es_, local_es_offset_, is_polyedre, decal);
467
468 const int nb_es_offset = static_cast<int>(local_es_.size());
469
470 // incr sur nb_elem tot offset
471 global_nb_elem_som_offset_.assign(nb_procs, -123 /* default */);
472
473 allgather_int_on_active_comm(nb_es_offset, global_nb_elem_som_offset_, by_comm_grp);
474
475 if (!Option_CGNS::PARALLEL_OVER_ZONE && !postraiter_domaine_)
476 {
477 std::vector<int> global_incr_max_elem_som_offset;
478 compute_global_max_only(global_nb_elem_som_offset_, global_incr_max_elem_som_offset, nes_offset_tot_);
479
480 decal = compute_shift(global_incr_max_elem_som_offset); // shift by elem offset !!
481 for (auto &itr : local_es_offset_) itr += decal;
482 }
483 }
484#endif
485}
486
487int TRUST_2_CGNS::compute_shift(const std::vector<int>& vect_incr_max) const
488{
489#ifdef MPI_
490 assert(par_in_zone_);
491
492 const bool by_comm_grp = is_comm_group_mode(postraiter_domaine_);
493
494 int proc_me = by_comm_grp ? proc_me_local_comm_ : Process::me();
495
496 int decal = 0;
497 if (all_procs_write_)
498 {
499 if (proc_me > 0) // pas maitre
500 decal = vect_incr_max[proc_me - 1];
501 }
502 else
503 {
504 for (int i = 0; i < nb_procs_writing_; i++)
505 if (proc_non_zero_elem_[i] == proc_me)
506 if (i > 0) // pas premier case
507 {
508 decal = vect_incr_max[proc_non_zero_elem_[i] - 1];
509 break;
510 }
511 }
512 return decal;
513#else
514 return 0;
515#endif
516}
517
518int TRUST_2_CGNS::convert_connectivity(const CGNS_TYPE type, std::vector<cgsize_t>& conn_elem ) const
519{
520 const int nb_elem = elems_->dimension(0);
521 const IntTab& les_elems = elems_.valeur();
522 int decal = par_in_zone_ ? compute_shift(global_incr_max_som_) : 0;
523
524 int nodes_per_elem = -1;
525
526 switch(type)
527 {
528 case CGNS_ENUMV(HEXA_8):
529 nodes_per_elem = 8;
530 break;
531 case CGNS_ENUMV(QUAD_4):
532 nodes_per_elem = 4;
533 break;
534 case CGNS_ENUMV(TETRA_4):
535 nodes_per_elem = 4;
536 break;
537 case CGNS_ENUMV(TRI_3):
538 nodes_per_elem = 3;
539 break;
540 case CGNS_ENUMV(BAR_2):
541 nodes_per_elem = 2;
542 break;
543 case CGNS_ENUMV(NODE):
544 nodes_per_elem = 1;
545 break;
546 default:
547 Cerr << "Type not yet coded in TRUST_2_CGNS::convert_connectivity ! Call the 911 !" << finl;
549 return -100;
550 }
551
552 if (nodes_per_elem != elems_->dimension(1))
553 {
554 Cerr << "Big issue in TRUST_2_CGNS::convert_connectivity !!!" << finl;
555 Cerr << " We have nodes_per_elem = " << nodes_per_elem << " while we have a connectivity of width = " << elems_->dimension(1) << finl;
557 return -100;
558 }
559
560 conn_elem.resize(nb_elem * nodes_per_elem); // allocation une fois
561 cgsize_t* data = conn_elem.data();
562
563 switch(type)
564 {
565 case CGNS_ENUMV(HEXA_8):
566 for (int i = 0; i < nb_elem; i++)
567 {
568 *data++ = les_elems(i, 0) + 1 + decal;
569 *data++ = les_elems(i, 1) + 1 + decal;
570 *data++ = les_elems(i, 3) + 1 + decal;
571 *data++ = les_elems(i, 2) + 1 + decal;
572 *data++ = les_elems(i, 4) + 1 + decal;
573 *data++ = les_elems(i, 5) + 1 + decal;
574 *data++ = les_elems(i, 7) + 1 + decal;
575 *data++ = les_elems(i, 6) + 1 + decal;
576 }
577 break;
578
579 case CGNS_ENUMV(QUAD_4):
580 for (int i = 0; i < nb_elem; i++)
581 {
582 *data++ = les_elems(i, 0) + 1 + decal;
583 *data++ = les_elems(i, 1) + 1 + decal;
584 *data++ = les_elems(i, 3) + 1 + decal;
585 *data++ = les_elems(i, 2) + 1 + decal;
586 }
587 break;
588
589 case CGNS_ENUMV(TETRA_4):
590 case CGNS_ENUMV(TRI_3):
591 case CGNS_ENUMV(BAR_2):
592 case CGNS_ENUMV(NODE):
593 for (int i = 0; i < nb_elem; i++)
594 for (int j = 0; j < nodes_per_elem; j++)
595 *data++ = les_elems(i, j) + 1 + decal;
596 break;
597
598 default: /* already handled above */
599 break;
600 }
601
602 return nodes_per_elem;
603}
604
605CGNS_TYPE TRUST_2_CGNS::convert_elem_type(const Motcle& type) const
606{
607 assert(elems_);
608 const int nb_comp = elems_->dimension(1);
609
610 if (type.debute_par("HEXAEDRE"))
611 return CGNS_ENUMV(HEXA_8);
612 else if (type.debute_par("RECTANGLE") || type.debute_par("QUADRANGLE"))
613 return CGNS_ENUMV(QUAD_4);
614 else if (type == "TETRAEDRE")
615 return CGNS_ENUMV(TETRA_4);
616 else if (type.debute_par("TRIANGLE"))
617 return CGNS_ENUMV(TRI_3);
618 else if (type == "POINT")
619 return CGNS_ENUMV(NODE);
620 else if (type == "POLYEDRE" || type.debute_par("POLYGONE") || type.debute_par("PRISME"))
621 return CGNS_ENUMV(NGON_n);
622 else if (type.debute_par("SEGMENT"))
623 {
624 /* So bad ... EF defined Bds as segments not points ... */
625 if (nb_comp == 1) return CGNS_ENUMV(NODE);
626 if (nb_comp == 2) return CGNS_ENUMV(BAR_2);
627
628 Cerr << "Unexpected SEGMENT connectivity of width = " << nb_comp << finl;
629 return CGNS_ENUMV(ElementTypeNull);
630 }
631 else
632 {
633 Cerr << "The type " << type << " is not yet available for the CGNS format ! Call the 911 !" << finl;
635 return CGNS_ENUMV(ElementTypeNull);
636 }
637}
638
639int TRUST_2_CGNS::topo_dim_from_elem(CGNS_TYPE etype, bool is_polyedre) const
640{
641 if (etype == CGNS_ENUMV(BAR_2) || etype == CGNS_ENUMV(NODE))
642 return 1; // 1D
643
644 if (etype == CGNS_ENUMV(TRI_3) || etype == CGNS_ENUMV(QUAD_4))
645 return 2; // 2D classiques
646
647 if (etype == CGNS_ENUMV(NGON_n))
648 return is_polyedre ? 3 : 2; // NGON_n : 2D si polygone, 3D si polyedre (avec NFACE_n)
649
650 // 3D classiques
651 return 3; // TETRA_4, HEXA_8, NFACE_n
652}
653
654int TRUST_2_CGNS::convert_connectivity_nface(std::vector<cgsize_t>& econ, std::vector<cgsize_t>& eoff, int decal)
655{
656 assert (dom_trust_);
657
658 Domaine_dis_base *domaine_dis = nullptr;
659 Domaine_VF *vf = nullptr;
660 get_domaine_dis_vf_if_poly(domaine_dis, vf);
661
662 const IntTab& ef = vf ? (*vf).elem_faces() : ef_dual_.valeur();
663
664 const int nElem = ef.dimension(0), maxDeg = ef.dimension(1);
665
666 econ.clear(), eoff.clear();
667
668 econ.reserve(static_cast<size_t>(nElem) * maxDeg); // chaque elem a au plus maxDeg faces
669 eoff.reserve(static_cast<size_t>(nElem) + 1); // un par elem + 1 pour la fin
670
671 eoff.push_back(0); // first index = > 0 !
672
673 int s = 0;
674 for (int e = 0; e < nElem; ++e)
675 {
676 for (int j = 0; j < maxDeg; ++j)
677 {
678 const int f = ef(e, j);
679 if (f < 0)
680 break;
681
682 econ.push_back(static_cast<cgsize_t>(f + 1 + decal));
683 ++s;
684 }
685 eoff.push_back(s);
686 }
687
688 // XXX Elie Saikali ...
689 // on en a besoin pour eviter ce warning
690 // reading zone "Zone_0002"
691 // reading element set "NGON_n"
692 // reading element set "NFACE_n"
693 // ERROR: duplicate positive faces indices detected in NFace_n Elements connectivity
694 std::unordered_set<cgsize_t> seen;
695 for (auto& itr : econ)
696 {
697 if (seen.find(itr) != seen.end())
698 itr *= -1; // already seen -> times -1 !!!
699 else
700 seen.insert(itr);
701 }
702
703 return ef.dimension(0);
704}
705
706int TRUST_2_CGNS::convert_connectivity_ngon(std::vector<cgsize_t>& econ, std::vector<cgsize_t>& eoff, const bool is_polyedre, int decal)
707{
708 assert (dom_trust_);
709 if (is_polyedre)
710 {
711 Domaine_dis_base* domaine_dis = nullptr;
712 Domaine_VF* vf = nullptr;
713 get_domaine_dis_vf_if_poly(domaine_dis, vf);
714
715 const IntTab& fs = vf ? (*vf).face_sommets() : fs_dual_.valeur();
716
717 const int nFace = fs.dimension(0), maxDeg = fs.dimension(1);
718
719 econ.clear(), eoff.clear();
720
721 econ.reserve(static_cast<size_t>(nFace) * maxDeg);
722 eoff.reserve(static_cast<size_t>(nFace) + 1);
723
724 eoff.push_back(0); // first index = > 0 !
725 int s = 0;
726 for (int f = 0; f < nFace; ++f)
727 {
728 for (int j = 0; j < maxDeg; ++j)
729 {
730 const int v = fs(f, j);
731 if (v < 0)
732 break;
733
734 econ.push_back(static_cast<cgsize_t>(v + 1 + decal));
735 ++s;
736 }
737 eoff.push_back(s);
738 }
739
740 return fs.dimension(0);
741 }
742 else // POLYGONE
743 {
744 const IntTab& les_elems = dom_trust_->les_elems();
745
746 const int nElem = les_elems.dimension(0), maxDeg = les_elems.dimension(1);
747
748 econ.clear(), eoff.clear();
749
750 econ.reserve(static_cast<size_t>(nElem) * maxDeg);
751 eoff.reserve(static_cast<size_t>(nElem) + 1);
752
753 eoff.push_back(0); // first index = > 0 !
754 int s = 0;
755 for (int e = 0; e < nElem; ++e)
756 {
757 for (int j = 0; j < maxDeg; ++j)
758 {
759 const int v = les_elems(e, j);
760 if (v < 0)
761 break;
762 econ.push_back(static_cast<cgsize_t>(v + 1 + decal));
763 ++s;
764 }
765 eoff.push_back(s);
766 }
767
768 return les_elems.dimension(0);
769 }
770}
771
772#endif /* HAS_CGNS */
: Classe Comm_Group_MPI, derivee de la classe abstraite 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
renvoie le numero du ieme sommet de la face num_face.
Definition Domaine_VF.h:583
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
static Domaine_dis_base & Build_or_get_poly_post(const Nom &type, const Domaine &dom)
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
int debute_par(const char *const n) const override
Definition Motcle.cpp:309
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const std::string & getString() const
Definition Nom.h:92
static int dimension
Definition Objet_U.h:99
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
static int axi
Definition Objet_U.h:101
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)
Si le processeur local appartient au groupe, le groupe courant pour ce processeur devient "group" et ...
static const Comm_Group & get_user_defined_group()
Renvoie une reference au groupe sur defini par l'utilisateur.
static bool has_user_defined_group()
static void exit_group()
Retourne dans le groupe ou l'on etait avant le dernier enter_group() reussi (dont le resultat a ete 1...
static bool is_parallel()
Definition Process.cpp:110
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
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
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