TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Ecrire_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 <Sortie_Fichier_base.h>
17#include <Format_Post_CGNS.h>
18#include <Comm_Group_MPI.h>
19#include <communications.h>
20#include <TRUST_2_MED.h>
21#include <Ecrire_CGNS.h>
22#include <Domaine_VF.h>
23#include <Polyedre.h>
24#include <Polygone.h>
25#include <Domaine.h>
26#include <unistd.h>
27
28#ifdef HAS_CGNS
29#include <cgns_io.h> // to flush !
30
31void Ecrire_CGNS::cgns_set_base_name(const Nom& fn)
32{
33 // See if root is set ... utile pour champ parametrique ... on fait comme dan sla methode cgns_resetTime
34 std::string dir_to_use = Sortie_Fichier_base::root;
35
36 if (dir_to_use == "." || dir_to_use == "./")
37 dir_to_use.clear();
38
39 while (!dir_to_use.empty() && dir_to_use.back() == '/')
40 dir_to_use.pop_back();
41
42 if (!dir_to_use.empty())
43 baseFile_name_ = dir_to_use + "/" + fn.getString();
44 else
45 baseFile_name_ = fn.getString();
46}
47
48void Ecrire_CGNS::cgns_resetTime(const double t, const std::string& dirname, const Nom& basefile)
49{
50 if (dirname.empty())
51 Process::exit("\nError in Ecrire_CGNS::cgns_resetTime. The name of the directory is empty !!! \n");
52
53 /* 1. Reset */
54 solname_elem_ = "", solname_som_ = "", solname_faces_ = "";
55 grid_name_ = "", grid_name_loc_ = "";
56 need_post_field_ = true, first_time_post_ = true;
57 has_elem_field_ = false, has_faces_field_ = false, has_som_field_ = false;
58 solname_elem_written_ = false, solname_som_written_ = false, solname_faces_written_ = false;
59 multi_loc_deformable_support_linked_ = false, grid_name_written_ = false;
60 grid_file_opened_ = false, solution_file_opened_ = false;
61 ensure_modify_done_ = false, singlefile_open_ = false;
62 flowId_elem_ = 0, flowId_som_ = 0, flowId_faces_ = 0;
63 fieldId_elem_ = 0, fieldId_som_ = 0, fieldId_faces_ = 0;
64 step_single_file_counter_ = 0;
65
66 fieldName_dumped_.clear(), time_post_.clear();
67 T2CGNS_.clear();
68 fld_loc_map_.clear(), doms_written_.clear();
69 baseId_.clear(), zoneId_.clear(), sizeId_.clear();
70 baseZone_name_.clear(), connectname_.clear();
71 cellDim_.clear(), zoneId_par_.clear();
72
73 /* 2. Management of file name*/
75 baseFile_name_vect_.push_back(baseFile_name_);
76
77 std::string dir_to_use(dirname);
78
79 // evite ./basefile et .//basefile ...
80 if (dir_to_use == "." || dir_to_use == "./")
81 dir_to_use.clear();
82
83 // Supprimer les / a la fin (sauf si dir_to_use devient vide haha)
84 while (!dir_to_use.empty() && dir_to_use.back() == '/')
85 dir_to_use.pop_back();
86
87 if (!dir_to_use.empty())
88 baseFile_name_ = dir_to_use + "/" + basefile.getString();
89 else
90 baseFile_name_ = basefile.getString();
91
93 if (std::find(baseFile_name_vect_.begin(), baseFile_name_vect_.end(), baseFile_name_) != baseFile_name_vect_.end())
94 {
95 baseFile_name_ += "_reset_";
96 baseFile_name_ += std::to_string(static_cast<int>(baseFile_name_vect_.size()));
97 }
98}
99
100void Ecrire_CGNS::cgns_associer_domaine_dis(const Domaine_dis_base& domaine_dis_base)
101{
102 domaine_dis_ = domaine_dis_base;
103}
104
105void Ecrire_CGNS::cgns_init_MPI()
106{
107#ifdef MPI_
108 if (is_comm_group_mode())
109 {
110 const Comm_Group_MPI& comm_loc = ref_cast(Comm_Group_MPI, PE_Groups::get_user_defined_group());
111 if (cgp_mpi_comm(comm_loc.get_mpi_comm()) != CG_OK)
112 Cerr << "Error Ecrire_CGNS::cgns_init_MPI : cgp_mpi_comm -- Comm_Group_MPI !" << finl, TRUST_CGNS_ERROR();
113
114 if (proc_maitre_local_comm_ == -123)
115 init_proc_maitre_local_comm();
116 }
117 else
118 {
119 if (cgp_mpi_comm(/* XXX MPI_COMM_WORLD */ Comm_Group_MPI::get_trio_u_world()) != CG_OK)
120 Cerr << "Error Ecrire_CGNS::cgns_init_MPI : cgp_mpi_comm -- trio_u_world !" << finl, TRUST_CGNS_ERROR();
121 }
122
123 /*
124 * Elie Saikali XXX NOTA BENE XXX : We need sometimes to write planes, boundaries where some processors have no elements/vertices ...
125 * This wont work because the default PIO mode of CGNS is COLLECTIVE. We want it to be INDEPENDENT !
126 */
127 if (cgp_pio_mode((CGNS_ENUMT(PIOmode_t)) CGP_INDEPENDENT) != CG_OK)
128 Cerr << "Error Ecrire_CGNS::cgns_init_MPI : cgp_pio_mode !" << finl, TRUST_CGNS_ERROR();
129#endif
130}
131
132void Ecrire_CGNS::cgns_open_file()
133{
134 if (Process::is_parallel()) cgns_init_MPI(); // 1er truc a faire
135
136 fill_infos_loc();
137
138 if (is_lagrangian_) return; /* for FT post and since we have a change of topology => one file per dt post */
139
140 if (Option_CGNS::USE_LINKS && !postraiter_domaine_)
141 return; /* rien a faire si USE_LINKS ou LINKED_FILES_PER_COMM_GROUP */
142
143 std::string fn = baseFile_name_ + ".cgns"; // file name
144
146 {
147 if (is_single_file_comm_group_mode())
148 {
149 fn = (Nom(baseFile_name_)).nom_me(proc_maitre_local_comm_).getString() + ".cgns"; // file name
150 unlink(fn.c_str());
151 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::PAR>(fn, fileId_, false);
152 Cerr << "**** Multiple parallel CGNS files " << baseFile_name_ << "_XXXX.cgns opened !" << finl;
153 }
154 else
155 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::PAR>(fn, fileId_);
156 }
157 else
158 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::SEQ>(fn, fileId_);
159
160 singlefile_open_ = true;
161}
162
163void Ecrire_CGNS::fill_infos_loc()
164{
165 has_elem_field_ = false, has_faces_field_ = false, has_som_field_ = false;
166 if (postraiter_domaine_)
167 {
168 has_som_field_ = true;
169 has_elem_field_ = true;
170 return;
171 }
172
173 assert (loc_vect_);
174 assert (static_cast<int>(loc_vect_->size()) <= 3);
175
176 if (static_cast<int>(loc_vect_->size()) == 0)
177 {
178 need_post_field_ = false;
179 return;
180 }
181
182 for (auto& itr : loc_vect_.valeur())
183 {
184 if (itr == "FACES") has_faces_field_ = true;
185 else if (itr == "SOM") has_som_field_ = true;
186 else if (itr == "ELEM") has_elem_field_ = true;
187 else
188 throw std::runtime_error("Ecrire_CGNS::fill_infos_loc => Unsupported LOC : " + itr);
189 }
190
191 if (has_faces_field_ && is_deformable_)
192 {
193 Cerr << "Error in Ecrire_CGNS::" << __func__ << " !!! Postprocessing face fields with a deformable problem is not yet allowed ..." << finl;
194 Cerr << "Contact the TRUST team" << finl;
196 }
197
198 // j'ajoute ce test pour le moment ...
199 if (Process::is_parallel() && Option_CGNS::PARALLEL_OVER_ZONE && is_deformable_)
200 {
201 Cerr << "Error in Ecrire_CGNS::" << __func__ << " !!! You can not use the CGNS option PARALLEL_OVER_ZONE with your problem ..." << finl;
202 Cerr << "Contact the TRUST team" << finl;
204 }
205}
206
207void Ecrire_CGNS::finir_ecriture(double temps)
208{
209 if (postraiter_domaine_) return; /* rien a faire */
210
211 if (Option_CGNS::USE_LINKS || is_lagrangian_)
212 {
213 cgns_close_grid_or_solution_link_file(temps, TYPE_LINK_CGNS::SOLUTION);
214
215 /* rewrite the link file so you can visualize during simulation !!! */
216 if (is_lagrangian_)
217 cgns_write_final_link_file_lagrangian();
218 else
219 cgns_write_final_link_file();
220 }
221 else
222 {
223 if (singlefile_open_)
224 {
225 const bool will_flush = (Option_CGNS::FLUSH_EVERY_N > 0) &&
226 (step_single_file_counter_ % Option_CGNS::FLUSH_EVERY_N == 0);
227
228 const bool will_close = (Option_CGNS::CLOSE_EVERY_N > 0) &&
229 (step_single_file_counter_ % Option_CGNS::CLOSE_EVERY_N == 0);
230
231 /* single but SAFE file => update iterateurs + close to force flush on disc so you can visualize during simulation !!! */
232 if (will_flush || will_close)
233 {
234 if (!first_time_post_ && !is_single_file_comm_group_mode()) /* write iters */
235 cgns_write_iters();
236
237 if (!will_close)
238 cgns_flush_to_disk();
239 }
240
241 if (will_close)
242 {
244 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::PAR>(baseFile_name_ /* inutile */, fileId_, false /* print */);
245 else
246 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::SEQ>(baseFile_name_ /* inutile */, fileId_, false /* print */);
247
248 singlefile_open_ = false;
249 }
250 }
251 }
252
253 if (is_single_file_comm_group_mode())
254 cgns_write_final_link_file_for_single_file_comm_group();
255}
256
257void Ecrire_CGNS::cgns_finir()
258{
259 if (is_lagrangian_)
260 return; /* All done */
261
262 if (Option_CGNS::USE_LINKS && !postraiter_domaine_)
263 return; /* All done */
264
265 if (!is_single_file_comm_group_mode())
266 if (!postraiter_domaine_ && !first_time_post_)
267 cgns_write_iters();
268
269 if (!singlefile_open_) return;
270
271 std::string fn = baseFile_name_ + ".cgns"; // file name
272
274 {
275 if (is_single_file_comm_group_mode())
276 {
277 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::PAR>(fn /* inutile */, fileId_, false);
278 Cerr << "**** Multiple parallel CGNS files " << baseFile_name_ << "_XXXX.cgns closed !" << finl;
279 }
280 else
281 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::PAR>(fn, fileId_);
282 }
283 else
284 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::SEQ>(fn, fileId_);
285}
286
287void Ecrire_CGNS::cgns_add_time(const double t)
288{
289 if (first_time_post_ && !time_post_.empty())
290 first_time_post_ = false;
291
292 if (is_lagrangian_)
293 cgns_open_solution_link_file(t); /* FT toujours un fichier par post ... */
294 else if (Option_CGNS::USE_LINKS && !postraiter_domaine_)
295 {
296 if (!first_time_post_ || is_deformable_) /* Si pas deformable, la 1er fois dans cgns_write_field (fill field_loc_map) */
297 cgns_open_solution_link_file(t);
298 }
299
300 if (!Option_CGNS::USE_LINKS && !postraiter_domaine_ && !is_lagrangian_)
301 {
302 step_single_file_counter_++; // XXX
303
304 if (!singlefile_open_)
305 {
306 if (!first_time_post_)
307 {
308 std::string fn = baseFile_name_ + ".cgns";
309
311 {
312 if (is_single_file_comm_group_mode())
313 {
314 fn = (Nom(baseFile_name_)).nom_me(proc_maitre_local_comm_).getString() + ".cgns"; // file name
315 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::PAR, TYPE_MODE_CGNS::MODIFY>(fn, fileId_, false);
316 }
317 else
318 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::PAR, TYPE_MODE_CGNS::MODIFY>(fn, fileId_, /*print*/false);
319 }
320 else
321 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::SEQ, TYPE_MODE_CGNS::MODIFY>(fn, fileId_, /*print*/false);
322 }
323
324 singlefile_open_ = true;
325 }
326 }
327
328 time_post_.push_back(t); // add time_post
329 fieldName_dumped_.clear();
330 flowId_elem_++, flowId_som_++, flowId_faces_++; // increment
331 fieldId_elem_ = 0, fieldId_som_ = 0, fieldId_faces_ = 0; // reset
332 solname_elem_written_ = false, solname_som_written_ = false, solname_faces_written_ = false; // reset
333 multi_loc_deformable_support_linked_ = false, grid_name_written_ = false; // reset
334}
335
336void Ecrire_CGNS::cgns_flush_to_disk() const
337{
338 int cgio_num = 0;
339
340 if (cg_get_cgio(fileId_, &cgio_num) != CG_OK)
341 Cerr << "Error Ecrire_CGNS::cgns_flush_to_disk : cg_get_cgio !" << finl, TRUST_CGNS_ERROR();
342
343 if (cgio_flush_to_disk(cgio_num) != 0)
344 Cerr << "Error Ecrire_CGNS::cgns_flush_to_disk : cgio_flush_to_disk !" << finl, TRUST_CGNS_ERROR();
345}
346
347void Ecrire_CGNS::ensure_modify_open_singlefile()
348{
349 if (ensure_modify_done_ || Option_CGNS::USE_LINKS || postraiter_domaine_ || is_lagrangian_)
350 return; /* Do nothing */
351
352 std::string fn = baseFile_name_ + ".cgns";
353
354 /* Close file for first time */
356 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::PAR>(fn /* inutile */, fileId_, /*print*/ false);
357 else
358 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::SEQ>(fn /* inutile */, fileId_, /*print*/ false);
359
360 /* Reopen file for first time with MODIFY mode */
362 {
363 if (is_single_file_comm_group_mode())
364 {
365 fn = (Nom(baseFile_name_)).nom_me(proc_maitre_local_comm_).getString() + ".cgns"; // file name
366 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::PAR, TYPE_MODE_CGNS::MODIFY>(fn, fileId_, false);
367 }
368 else
369 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::PAR, TYPE_MODE_CGNS::MODIFY>(fn, fileId_, /*print*/ false);
370 }
371 else
372 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::SEQ, TYPE_MODE_CGNS::MODIFY>(fn, fileId_, /*print*/ false);
373
374 ensure_modify_done_ = true;
375}
376
377void Ecrire_CGNS::update_grid_name()
378{
379 grid_name_loc_ = "GridCoordinates";
380
381 if (!first_time_post_) // Pas la premiere fois
382 {
383 grid_name_loc_ += "_itr_";
384 grid_name_loc_ += std::to_string(static_cast<int>(time_post_.size() - 1));
385 }
386
387 std::string c = grid_name_loc_;
388 c.resize(CGNS_STR_SIZE, ' ');
389 grid_name_ += c;
390
391 grid_name_written_ = true;
392}
393
394void Ecrire_CGNS::cgns_write_domaine(const Domaine * dom,const Nom& nom_dom, const DoubleTab& som, const IntTab& elem, const Motcle& type_e)
395{
396 if (!grid_name_written_ && (first_time_post_ || is_deformable_))
397 update_grid_name();
398
399 std::string nom_dom_modifie = TRUST_2_CGNS::modify_domaine_name_for_post(nom_dom);
400
401 if (Option_CGNS::USE_LINKS && !postraiter_domaine_ && !is_deformable_)
402 if (!grid_file_opened_)
403 cgns_open_grid_base_link_file();
404
406 {
407 if (Option_CGNS::PARALLEL_OVER_ZONE || postraiter_domaine_)
408 cgns_write_domaine_par_over_zone(dom, Nom(nom_dom_modifie), som, elem, type_e);
409 else
410 cgns_write_domaine_par_in_zone(dom, Nom(nom_dom_modifie), som, elem, type_e);
411 }
412 else
413 cgns_write_domaine_seq(dom, Nom(nom_dom_modifie), som, elem, type_e);
414}
415
416void Ecrire_CGNS::cgns_write_field(const Domaine& domaine, const Noms& noms_compo, double temps,
417 const Nom& id_du_champ, const Nom& id_du_domaine, const Nom& localisation,
418 const DoubleTab& valeurs)
419{
420 assert (need_post_field_);
421 /* Gestion multi-loc support */
422 if (fld_loc_map_.empty()) /* Build different links to support mixed locations : just once for all ! */
423 cgns_fill_field_loc_map(domaine.le_nom());
424
425 if (is_deformable_ && !multi_loc_deformable_support_linked_) /* si link et deformable et multi-loc : at each time step ! */
426 link_multi_loc_support_pb_deformable();
427
428 /* Write fields */
429 const std::string LOC = Motcle(localisation).getString();
430 const int nb_cmp = valeurs.dimension(1);
431 assert(fld_loc_map_.count(LOC));
433 {
434 for (int i = 0; i < nb_cmp; i++)
435 {
436 const Motcle field_name = nb_cmp > 1 ? Motcle(noms_compo[i]) : id_du_champ;
437 const std::string field_name_check = is_lagrangian_ ? field_name.getString() + LOC : field_name.getString();
438
439 if (fieldName_dumped_.insert(field_name_check).second)
440 {
441 if (Option_CGNS::PARALLEL_OVER_ZONE || postraiter_domaine_)
442 cgns_write_field_par_over_zone(i /* compo */, temps, field_name, id_du_domaine, localisation, fld_loc_map_.at(LOC), valeurs);
443 else
444 cgns_write_field_par_in_zone(i /* compo */, temps, field_name, id_du_domaine, localisation, fld_loc_map_.at(LOC), valeurs);
445 }
446 else
447 Cerr << "Field " << field_name << " is already written => we skip it ..." << finl;
448 }
449 }
450 else
451 for (int i = 0; i < nb_cmp; i++)
452 {
453 const Motcle field_name = nb_cmp > 1 ? Motcle(noms_compo[i]) : id_du_champ;
454 const std::string field_name_check = is_lagrangian_ ? field_name.getString() + LOC : field_name.getString();
455
456 if (fieldName_dumped_.insert(field_name_check).second)
457 cgns_write_field_seq(i /* compo */, temps, field_name, id_du_domaine, localisation, fld_loc_map_.at(LOC), valeurs);
458 else
459 Cerr << "Field " << field_name << " is already written => we skip it ..." << finl;
460 }
461}
462
463/*
464 * *********************************** *
465 * METHODES PRIVEES CLASSE Ecrire_CGNS *
466 * *********************************** *
467 */
468void Ecrire_CGNS::cgns_fill_field_loc_map(const Nom& nom_dom_init)
469{
470 assert (static_cast<int>(time_post_.size()) == 1 && first_time_post_);
471
472 /* helplers juste pour cette methode */
473 enum class InitMode { SOLUTIONLINK, LINKEDBASE };
474
475 auto modify_name_for_support = [&](const std::string& loc)
476 {
477 Nom nom_dom = nom_dom_init;
478 nom_dom += "_";
479 nom_dom += loc.c_str();
480 return nom_dom;
481 };
482
483 auto insert_loc_map_and_init = [&](const std::string& loc, InitMode mode)
484 {
485 assert(!fld_loc_map_.count(loc));
486 const Nom nom_dom = modify_name_for_support(loc);
487 fld_loc_map_.insert({ loc, nom_dom });
488
489 if (loc != "FACES")
490 (mode == InitMode::SOLUTIONLINK) ? cgns_init_solution_link_file(loc, nom_dom) :
491 add_new_linked_base(loc, nom_dom);
492 };
493
494 /* pour les champs aux faces, il faut un support ! */
495 if (has_faces_field_ && !is_dual_)
496 {
497 Cerr << "### Building a new CGNS zone to host the fields located at FACES !" << finl;
498 cgns_write_domaine_dual(nom_dom_init, 0 /* inutile */, modify_name_for_support("FACES"));
499 }
500
501 if (is_lagrangian_)
502 {
503 if (!multi_loc_deformable_support_linked_)
504 {
505 if (has_elem_field_) insert_loc_map_and_init("ELEM", InitMode::SOLUTIONLINK);
506
507 if (has_som_field_) insert_loc_map_and_init("SOM", InitMode::SOLUTIONLINK);
508
509 if (has_faces_field_) Process::exit("Error in Ecrire_CGNS::cgns_fill_field_loc_map : FACES fields are not yet supported ! \n");
510 }
511 }
512 else if (!Option_CGNS::USE_LINKS || postraiter_domaine_)
513 {
514 if (has_elem_field_) insert_loc_map_and_init("ELEM", InitMode::LINKEDBASE);
515
516 if (has_som_field_) insert_loc_map_and_init("SOM", InitMode::LINKEDBASE);
517
518 if (has_faces_field_) insert_loc_map_and_init("FACES", InitMode::LINKEDBASE);
519 }
520 else // Option_CGNS::USE_LINKS
521 {
523 if (grid_file_opened_ && !is_deformable_)
524 cgns_close_grid_or_solution_link_file(0. /* inutile */, TYPE_LINK_CGNS::GRID, false);
525
526 if (!solution_file_opened_ || (is_deformable_ && !multi_loc_deformable_support_linked_))
527 {
528 if (has_elem_field_) insert_loc_map_and_init("ELEM", InitMode::SOLUTIONLINK);
529
530 if (has_som_field_) insert_loc_map_and_init("SOM", InitMode::SOLUTIONLINK);
531
532 if (has_faces_field_) insert_loc_map_and_init("FACES", InitMode::SOLUTIONLINK);
533
534 if (!is_deformable_)
535 cgns_open_solution_link_file(time_post_.back()); // 1ere ouverture sol file ici ! puis dans cgns_add_time
536 }
537 }
538}
539
540void Ecrire_CGNS::cgns_write_iters()
541{
542 if (first_time_post_ || is_lagrangian_) return; /* Do nothing */
543
544 if (!Option_CGNS::USE_LINKS && !ensure_modify_done_)
545 ensure_modify_open_singlefile(); /* to make sure we can modify !! */
546
547 for (auto &itr : doms_written_)
548 {
549 bool has_field = false;
550 std::string LOC = "rien";
551 TRUST_2_CGNS::init_has_field_and_loc_iters(itr, fld_loc_map_, has_field, LOC);
552
553 const int ind_glob = TRUST_2_CGNS::get_index_nom_vector(doms_written_, itr); // Glob means can be with fields ..
554 assert(ind_glob > -1);
555
556 if (is_deformable_)
557 cgns_helper_.cgns_write_iters_deformable<TYPE_ECRITURE_CGNS::SEQ>(true /* deformable */, has_field, 1 /* 1 zone per base */, fileId_, baseId_[ind_glob],
558 ind_glob /* 1st Zone */, zoneId_, LOC, solname_som_, solname_elem_, solname_faces_, grid_name_, time_post_);
560 {
561#ifdef MPI_
562 int ind_base = TRUST_2_CGNS::get_base_domain_idx(doms_written_, itr, has_field, LOC, ind_glob);
563 const TRUST_2_CGNS& TRUST2CGNS = T2CGNS_[ind_base];
564 const int nb_zones_to_write = TRUST2CGNS.nb_procs_writing();
565
566 cgns_helper_.cgns_write_iters<TYPE_ECRITURE_CGNS::PAR_OVER>(has_field, nb_zones_to_write, fileId_, baseId_[ind_glob], ind_glob, zoneId_par_[ind_glob], LOC,
567 solname_som_, solname_elem_, solname_faces_, time_post_);
568#endif /* MPI_ */
569 }
570 else
571 cgns_helper_.cgns_write_iters<TYPE_ECRITURE_CGNS::SEQ>(has_field, 1 /* nb_zones_to_write */, fileId_, baseId_[ind_glob], ind_glob, zoneId_, LOC,
572 solname_som_, solname_elem_, solname_faces_, time_post_);
573 }
574}
575
576/*
577 * ******************** *
578 * VERSION SEQUENTIELLE *
579 * ******************** *
580 */
581void Ecrire_CGNS::cgns_write_domaine_seq(const Domaine * domaine,const Nom& nom_dom, const DoubleTab& les_som, const IntTab& les_elem, const Motcle& type_elem)
582{
583 if (is_deformable_ && !first_time_post_)
584 {
585 cgns_write_domaine_deformable_seq(domaine, nom_dom, les_som, les_elem, type_elem);
586 return;
587 }
588
589 /* 1 : Instance of TRUST_2_CGNS */
590 T2CGNS_.push_back(TRUST_2_CGNS());
591 TRUST_2_CGNS& TRUST2CGNS = T2CGNS_.back();
592 TRUST2CGNS.associer_domaine_TRUST(domaine, domaine_dis_ ? &(domaine_dis_.valeur()) : nullptr,
593 les_som, les_elem, postraiter_domaine_, discr_type_);
594 if (is_dual_ && Objet_U::dimension == 3)
595 {
596 assert(fs_dual_.size() > 0 && ef_dual_.size() > 0);
597 TRUST2CGNS.associer_connec_pour_dual(fs_dual_, ef_dual_);
598 }
599
600 doms_written_.push_back(nom_dom);
601
602 CGNS_TYPE cgns_type_elem = TRUST2CGNS.convert_elem_type(type_elem);
603 const bool is_polyedre = (type_elem == "POLYEDRE" || type_elem == "PRISME" || type_elem == "PRISME_HEXAG");
604 const int icelldim = TRUST2CGNS.topo_dim_from_elem(cgns_type_elem, is_polyedre); // avant ca : icelldim = les_som.dimension(1)
605 const int iphysdim = Objet_U::dimension, nb_som = les_som.dimension(0), nb_elem = les_elem.dimension(0);
606
607 /* 2 : Fill coords */
608 std::vector<double> xCoords, yCoords, zCoords;
609 TRUST2CGNS.fill_coords(xCoords, yCoords, zCoords);
610
611 int coordsId;
612
613 /* 3 : Base write */
614 baseId_.push_back(-123); // pour chaque dom, on a une baseId
615 char basename[CGNS_STR_SIZE];
616 strcpy(basename, nom_dom.getChar()); // dom name
617
618 if (cg_base_write(fileId_, basename, icelldim, iphysdim, &baseId_.back()) != CG_OK)
619 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_seq : cg_base_write !" << finl, TRUST_CGNS_ERROR();
620
621 /* 4 : Vertex, cell & boundary vertex sizes */
622 const cgsize_t isize[3] = { (cgsize_t)nb_som , (cgsize_t)nb_elem , 0 }; /* 0 => boundary vertex size (zero if elements not sorted) */
623
624 cgns_fill_info_grid_link_file(basename, cgns_type_elem, icelldim, nb_som, nb_elem, is_polyedre);
625
626 zoneId_.push_back(-123);
627
628 /* 5 : Write all */
629 if (nb_elem)
630 {
631 /* 5.1 : Create zone & grid coords */
632 cgns_helper_.cgns_write_zone_grid_coord<TYPE_ECRITURE_CGNS::SEQ>(icelldim, fileId_, baseId_.back(), basename /* Dom name */, isize,
633 zoneId_.back(), xCoords, yCoords, zCoords, coordsId, coordsId, coordsId);
634
635 /* 5.2 : Set element connectivity */
636 int sectionId;
637 cgsize_t start = 1, end;
638
639 if (cgns_type_elem == CGNS_ENUMV(NGON_n)) // cas polyedre
640 {
641 assert (domaine != nullptr);
642 std::vector<cgsize_t> sf, sf_offset;
643
644 end = start + static_cast<cgsize_t>(TRUST2CGNS.convert_connectivity_ngon(sf, sf_offset, is_polyedre)) -1;
645
646 if (cg_poly_section_write(fileId_, baseId_.back(), zoneId_.back(), "NGON_n", CGNS_ENUMV(NGON_n), start, end, 0, sf.data(), sf_offset.data(), &sectionId))
647 TRUST_CGNS_ERROR();
648
649 if (is_polyedre) // Pas pour polygone
650 {
651 std::vector<cgsize_t> ef, ef_offset;
652
653 start = end + 1;
654 end = start + static_cast<cgsize_t>(TRUST2CGNS.convert_connectivity_nface(ef, ef_offset)) -1;
655
656 if (cg_poly_section_write(fileId_, baseId_.back(), zoneId_.back(), "NFACE_n", CGNS_ENUMV(NFACE_n), start, end, 0, ef.data(), ef_offset.data(), &sectionId))
657 TRUST_CGNS_ERROR();
658 }
659 }
660 else
661 {
662 std::vector<cgsize_t> elems;
663 const int nsom = TRUST2CGNS.convert_connectivity(cgns_type_elem, elems);
664
665 end = start + static_cast<cgsize_t>(elems.size()) / nsom - 1;
666
667 if (cg_section_write(fileId_, baseId_.back(), zoneId_.back(), "Elem", cgns_type_elem, start, end, 0, elems.data(), &sectionId) != CG_OK)
668 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_seq : cg_section_write !" << finl, TRUST_CGNS_ERROR();
669 }
670 }
671 TRUST2CGNS.clear_vectors();
672}
673
674void Ecrire_CGNS::cgns_write_field_seq(const int comp, const double temps, const Nom& id_du_champ, const Nom& id_du_domaine, const Nom& localisation, const Nom& nom_dom, const DoubleTab& valeurs)
675{
676 const std::string LOC = Motcle(localisation).getString();
677 Motcle id_du_champ_modifie = TRUST_2_CGNS::modify_field_name_for_post(id_du_champ, id_du_domaine, LOC, fieldId_som_, fieldId_elem_, fieldId_faces_);
678 const Nom& id_champ = id_du_champ_modifie;
679
680 /* 1 : Get corresponding domain index */
681 const int ind = TRUST_2_CGNS::get_index_nom_vector(doms_written_, nom_dom);
682 assert(ind > -1);
683
684 const int nb_vals = valeurs.dimension(0);
685
686 if (nb_vals)
687 {
688 /* 2 : Write solution names for iterative data later */
689 cgns_helper_.cgns_sol_write<TYPE_ECRITURE_CGNS::SEQ>(1 /* nb_zones_to_write */, fileId_, baseId_[ind], ind,
690 static_cast<int>(time_post_.size() - 1), zoneId_, LOC,
691 solname_som_, solname_elem_, solname_faces_,
692 solname_som_written_, solname_elem_written_, solname_faces_written_,
693 flowId_som_, flowId_elem_, flowId_faces_);
694
695 /* 3 : Fill field values & dump to cgns file */
696 if (LOC == "FACES")
697 {
698 const Domaine_VF& dom_vf = ref_cast(Domaine_VF, domaine_dis_.valeur());
699 DoubleTrav new_vals;
700 TRUST_2_CGNS::map_face_values(dom_vf, valeurs, new_vals);
701
702 cgns_helper_.cgns_field_write_data<TYPE_ECRITURE_CGNS::SEQ>(fileId_, baseId_[ind], ind, zoneId_, LOC,
703 flowId_som_, flowId_elem_, flowId_faces_, comp,
704 id_champ, new_vals, fieldId_som_, fieldId_elem_, fieldId_faces_);
705
706 }
707 else
708 cgns_helper_.cgns_field_write_data<TYPE_ECRITURE_CGNS::SEQ>(fileId_, baseId_[ind], ind, zoneId_, LOC,
709 flowId_som_, flowId_elem_, flowId_faces_, comp,
710 id_champ, valeurs, fieldId_som_, fieldId_elem_, fieldId_faces_);
711 }
712}
713
714/* cas deformable : 2eme passage ici ! */
715void Ecrire_CGNS::cgns_write_domaine_deformable_seq(const Domaine * domaine,const Nom& nom_dom, const DoubleTab& les_som, const IntTab& les_elem, const Motcle& type_elem)
716{
717 const int ind = TRUST_2_CGNS::get_index_nom_vector(doms_written_, nom_dom);
718 TRUST_2_CGNS& TRUST2CGNS = T2CGNS_[ind];
719 TRUST2CGNS.associer_domaine_TRUST(domaine, domaine_dis_ ? &(domaine_dis_.valeur()) : nullptr,
720 les_som, les_elem, postraiter_domaine_, discr_type_);
721
722 CGNS_TYPE cgns_type_elem = TRUST2CGNS.convert_elem_type(type_elem);
723 const bool is_polyedre = (type_elem == "POLYEDRE" || type_elem == "PRISME" || type_elem == "PRISME_HEXAG");
724 const int icelldim = TRUST2CGNS.topo_dim_from_elem(cgns_type_elem, is_polyedre); // avant ca : icelldim = les_som.dimension(1)
725 const int iphysdim = Objet_U::dimension, nb_som = les_som.dimension(0), nb_elem = les_elem.dimension(0);
726
727 std::vector<double> xCoords, yCoords, zCoords;
728 TRUST2CGNS.fill_coords(xCoords, yCoords, zCoords);
729
730 const cgsize_t isize[3] = { (cgsize_t)nb_som, (cgsize_t)nb_elem, 0 }; /* 0 => boundary vertex size (zero if elements not sorted) */
731
732 int coordsId = -1;
733 char basename[CGNS_STR_SIZE];
734 strcpy(basename, nom_dom.getChar()); // dom name
735
736 /* If deformable only and single_file, connectivity is already seen in same file. we just write new coords */
737 if (!Option_CGNS::USE_LINKS && !is_lagrangian_)
738 {
739 if (nb_elem)
740 {
741 int G = -1;
742 if (cg_grid_write(fileId_, baseId_[ind], zoneId_[ind], grid_name_loc_.c_str(), &G) != CG_OK)
743 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_seq : cg_grid_write !" << finl, TRUST_CGNS_ERROR();
744
745 if (cg_goto(fileId_, baseId_[ind], "Zone_t",zoneId_[ind], "GridCoordinates_t", G, "end") != CG_OK)
746 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_seq : cg_goto Zone_t !" << finl, TRUST_CGNS_ERROR();
747
748 const cgsize_t dims[1] = { (cgsize_t)nb_som };
749
750 if (cg_array_write("CoordinateX", CGNS_ENUMV(RealDouble), 1, dims, xCoords.data()) != CG_OK)
751 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_seq : cg_array_write CoordinateX !" << finl, TRUST_CGNS_ERROR();
752
753 if (cg_array_write("CoordinateY", CGNS_ENUMV(RealDouble), 1, dims, yCoords.data()) != CG_OK)
754 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_seq : cg_array_write CoordinateY !" << finl, TRUST_CGNS_ERROR();
755
756 if (Objet_U::dimension > 2)
757 if (cg_array_write("CoordinateZ", CGNS_ENUMV(RealDouble), 1, dims, zCoords.data()) != CG_OK)
758 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_seq : cg_array_write CoordinateZ !" << finl, TRUST_CGNS_ERROR();
759 }
760 }
761 else
762 /* Here we use links. So we write coords in new solution file. However for connectivity we have 2 cases :
763 * - Deformable => We link to conn from 1st solution file
764 * - Lagrangian => We write new conn in the considered file
765 */
766 {
767 if (cg_base_write(fileId_, basename, icelldim, iphysdim, &baseId_[ind]) != CG_OK)
768 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_seq : cg_base_write !" << finl, TRUST_CGNS_ERROR();
769
770 if (nb_elem)
771 {
772 /* Create zone & grid coords */
773 cgns_helper_.cgns_write_zone_grid_coord<TYPE_ECRITURE_CGNS::SEQ>(icelldim, fileId_, baseId_[ind], basename /* Dom name */, isize,
774 zoneId_[ind], xCoords, yCoords, zCoords, coordsId, coordsId, coordsId);
775
776 if (is_lagrangian_) /* Set element connectivity : we rewrite since topology can change !! */
777 {
778 sizeId_.push_back( { (cgsize_t)nb_som, (cgsize_t)nb_elem } ); // XXX required for links later !
779
780 int sectionId;
781 cgsize_t start = 1, end;
782
783 if (cgns_type_elem == CGNS_ENUMV(NGON_n)) // cas polyedre
784 throw std::runtime_error("Ecrire_CGNS::cgns_write_domaine_deformable_seq => You should not be here !!! ");
785 else
786 {
787 std::vector<cgsize_t> elems;
788 const int nsom = TRUST2CGNS.convert_connectivity(cgns_type_elem, elems);
789
790 end = start + static_cast<cgsize_t>(elems.size()) / nsom - 1;
791
792 if (cg_section_write(fileId_, baseId_[ind], zoneId_[ind], "Elem", cgns_type_elem, start, end, 0, elems.data(), &sectionId) != CG_OK)
793 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_seq : cg_section_write !" << finl, TRUST_CGNS_ERROR();
794 }
795 }
796 else
797 {
798 /* Set element connectivity : by links */
799 std::string linkfile = baseFile_name_ + ".solution." + cgns_helper_.convert_double_to_string(time_post_[0]) + ".cgns";
800 TRUST_2_CGNS::remove_slash_linkfile(linkfile);
801 cgns_helper_.cgns_write_connectivity_deformable_links(fileId_, baseId_[ind], zoneId_[ind], linkfile, baseZone_name_[ind], baseZone_name_[ind],
802 connectname_[ind], "Ecrire_CGNS::cgns_write_domaine_deformable_seq");
803 }
804 }
805 }
806}
807
808/*
809 * *************************** *
810 * VERSION PARALLELE OVER ZONE *
811 * *************************** *
812 */
813void Ecrire_CGNS::cgns_write_domaine_par_over_zone(const Domaine * domaine,const Nom& nom_dom, const DoubleTab& les_som, const IntTab& les_elem, const Motcle& type_elem)
814{
815#ifdef MPI_
816 assert (!Option_CGNS::USE_LINKS || postraiter_domaine_);
817 assert (!is_deformable_);
818 doms_written_.push_back(nom_dom);
819
820 /* 1 : Instance of TRUST_2_CGNS */
821 T2CGNS_.push_back(TRUST_2_CGNS());
822 TRUST_2_CGNS& TRUST2CGNS = T2CGNS_.back();
823 TRUST2CGNS.associer_domaine_TRUST(domaine, domaine_dis_ ? &(domaine_dis_.valeur()) : nullptr,
824 les_som, les_elem, postraiter_domaine_, discr_type_);
825
826 if (is_dual_ && Objet_U::dimension == 3)
827 {
828 assert(fs_dual_.size() > 0 && ef_dual_.size() > 0);
829 TRUST2CGNS.associer_connec_pour_dual(fs_dual_, ef_dual_);
830 }
831 CGNS_TYPE cgns_type_elem = TRUST2CGNS.convert_elem_type(type_elem);
832 const bool is_polyedre = (type_elem == "POLYEDRE" || type_elem == "PRISME" || type_elem == "PRISME_HEXAG");
833 const int icelldim = TRUST2CGNS.topo_dim_from_elem(cgns_type_elem, is_polyedre); // avant ca : icelldim = les_som.dimension(1)
834 const int iphysdim = Objet_U::dimension, proc_me = Process::me(),
835 nb_som = les_som.dimension(0), nb_elem = les_elem.dimension(0);
836
837 /* 2 : Fill coords */
838 std::vector<double> xCoords, yCoords, zCoords;
839 TRUST2CGNS.fill_coords(xCoords, yCoords, zCoords);
840
841
842 /* 3 : Base write */
843 baseId_.push_back(-123); // pour chaque dom, on a une baseId
844 char basename[CGNS_STR_SIZE];
845 strcpy(basename, nom_dom.getChar()); // dom name
846
847 if (cg_base_write(fileId_, basename, icelldim, iphysdim, &baseId_.back()) != CG_OK)
848 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_over_zone : cg_base_write !" << finl, TRUST_CGNS_ERROR();
849
850 /* 4 : We need global nb_elems/nb_soms => MPI_Allgather. Thats the only information required ! */
851
852 cgns_fill_info_grid_link_file(basename, cgns_type_elem, icelldim, nb_som, nb_elem, is_polyedre);
853
854 TRUST2CGNS.fill_global_infos(); // XXX
855
856 if (cgns_type_elem == CGNS_ENUMV(NGON_n)) /*cas polygone/polyedre */
857 TRUST2CGNS.fill_global_infos_poly(is_polyedre);
858
859 /* 5 : CREATION OF FILE STRUCTURE : zones, coords & sections
860 *
861 * - All processors THAT HAVE nb_elem > 0 write the same information.
862 * - Only zone meta-data is written to the library at this stage ... So no worries ^^
863 */
864 std::vector<int> coordsIdx, coordsIdy, coordsIdz, sectionId, sectionId2;
865 std::string zonename;
866
867 const int nb_zones_to_write = TRUST2CGNS.nb_procs_writing();
868 const bool all_write = TRUST2CGNS.all_procs_write(); // all procs will write !
869
870 zoneId_.reserve(nb_zones_to_write);
871 coordsIdx.reserve(nb_zones_to_write);
872 coordsIdy.reserve(nb_zones_to_write);
873
874 if (Objet_U::dimension > 2)
875 coordsIdz.reserve(nb_zones_to_write);
876
877 sectionId.reserve(nb_zones_to_write);
878 if (cgns_type_elem == CGNS_ENUMV(NGON_n) && is_polyedre)
879 sectionId2.reserve(nb_zones_to_write);
880
881 // on boucle seulement sur les procs qui n'ont pas des nb_elem 0
882 zoneId_.clear(); // XXX commencons par ca
883 const std::vector<int>& global_nb_elem = TRUST2CGNS.get_global_nb_elem(),
884 &global_nb_som = TRUST2CGNS.get_global_nb_som(),
885 &proc_non_zero_elem = TRUST2CGNS.get_proc_non_zero_elem();
886
887 for (int i = 0; i != nb_zones_to_write; i++)
888 {
889 const int indZ = all_write ? i : proc_non_zero_elem[i]; // procID
890 const int ne_loc = global_nb_elem[indZ], ns_loc = global_nb_som[indZ]; /* nb_elem & nb_som local */
891 assert (ne_loc > 0);
892
893 cgsize_t start = 1, end = ne_loc;
894 const cgsize_t isize[3] = { ns_loc , end , 0 }; /* 0 => boundary vertex size (zero if elements not sorted) */
895
896 zoneId_.push_back(-123);
897 zonename = nom_dom.nom_me(indZ).getString();
898 zonename.resize(CGNS_STR_SIZE, ' ');
899
900 coordsIdx.push_back(-123), coordsIdy.push_back(-123);
901 if (Objet_U::dimension > 2)
902 coordsIdz.push_back(-123);
903
904 /* 5.1 : Create zone & Construct the grid coordinates nodes */
905 cgns_helper_.cgns_write_zone_grid_coord<TYPE_ECRITURE_CGNS::PAR_OVER>(icelldim, fileId_, baseId_.back(), zonename.c_str(), isize,
906 zoneId_.back(), xCoords, yCoords, zCoords,
907 coordsIdx.back(), coordsIdy.back(), coordsIdz.back());
908
909 /* 5.2 : Construct the sections to host connectivity later */
910 sectionId.push_back(-123);
911
912 if (cgns_type_elem == CGNS_ENUMV(NGON_n)) // cas polyedre
913 {
914 if (is_polyedre) // Pas pour polygone
915 {
916 end = start + static_cast<cgsize_t>(TRUST2CGNS.get_global_nb_face_som()[indZ]) -1;
917 cgsize_t maxoffset = static_cast<cgsize_t>(TRUST2CGNS.get_global_nb_face_som_offset()[indZ]);
918
919 if (cgp_poly_section_write(fileId_, baseId_.back(), zoneId_.back(), "NGON_n", CGNS_ENUMV(NGON_n), start, end, maxoffset, 0, &sectionId.back()) != CG_OK)
920 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_over_zone : cgp_poly_section_write !" << finl, TRUST_CGNS_ERROR();
921
922 sectionId2.push_back(-123);
923 start = end + 1;
924
925 end = start + static_cast<cgsize_t>(TRUST2CGNS.get_global_nb_elem_face()[indZ]) -1;
926 maxoffset = static_cast<cgsize_t>(TRUST2CGNS.get_global_nb_elem_face_offset()[indZ]);
927
928 if (cgp_poly_section_write(fileId_, baseId_.back(), zoneId_.back(), "NFACE_n", CGNS_ENUMV(NFACE_n), start, end, maxoffset, 0, &sectionId2.back()) != CG_OK)
929 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_over_zone : cgp_poly_section_write !" << finl, TRUST_CGNS_ERROR();
930 }
931 else // polygon
932 {
933 end = start + static_cast<cgsize_t>(TRUST2CGNS.get_global_nb_elem()[indZ]) -1; /* ici pareil comme get_global_nb_elem_som ... fais moi confiance ... */
934 cgsize_t maxoffset = static_cast<cgsize_t>(TRUST2CGNS.get_global_nb_elem_som_offset()[indZ]);
935
936 if (cgp_poly_section_write(fileId_, baseId_.back(), zoneId_.back(), "NGON_n", CGNS_ENUMV(NGON_n), start, end, maxoffset, 0, &sectionId.back()) != CG_OK)
937 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_over_zone : cgp_poly_section_write !" << finl, TRUST_CGNS_ERROR();
938 }
939 }
940 else
941 {
942 if (cgp_section_write(fileId_, baseId_.back(), zoneId_.back(), "Elem", cgns_type_elem, start, end, 0, &sectionId.back()) != CG_OK)
943 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_over_zone : cgp_section_write !" << finl, TRUST_CGNS_ERROR();
944 }
945 }
946
947 zoneId_par_.push_back(zoneId_); // XXX : Dont touch
948
949 /* 6 : Write grid coordinates & set connectivity */
950 if (nb_elem > 0) // this proc will write !
951 {
952 cgsize_t min = 1, max = nb_som;
953 int indx = -123;
954 if (all_write) indx = proc_me;
955 else
956 for (int i = 0; i < nb_zones_to_write; i++)
957 if (proc_non_zero_elem[i] == proc_me)
958 {
959 indx = i;
960 break;
961 }
962
963 /* 6.1 : Write grid coordinates */
964 cgns_helper_.cgns_write_grid_coord_data<TYPE_ECRITURE_CGNS::PAR_OVER>(icelldim, fileId_, baseId_.back(), zoneId_par_.back()[indx],
965 coordsIdx[indx], coordsIdy[indx], coordsIdz.empty() ? -123 : coordsIdz[indx],
966 min, max, xCoords, yCoords, zCoords);
967
968 /* 6.2 : Set element connectivity */
969 if (cgns_type_elem == CGNS_ENUMV(NGON_n)) // cas polyedre
970 {
971 if (is_polyedre) // Pas pour polygone
972 {
973 const std::vector<cgsize_t>& fs = TRUST2CGNS.get_local_fs(),
974 &fs_offset = TRUST2CGNS.get_local_fs_offset();
975
976 max = min + TRUST2CGNS.get_nb_fs() - 1;
977
978 if (cgp_poly_elements_write_data(fileId_, baseId_.back(), zoneId_par_.back()[indx], sectionId[indx], min, max, fs.data(), fs_offset.data()) != CG_OK)
979 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_over_zone : cgp_poly_elements_write_data !" << finl, TRUST_CGNS_ERROR();
980
981 const std::vector<cgsize_t>& ef = TRUST2CGNS.get_local_ef(),
982 &ef_offset = TRUST2CGNS.get_local_ef_offset();
983
984 min = max + 1, max = min + TRUST2CGNS.get_nb_ef() - 1;
985
986 if (cgp_poly_elements_write_data(fileId_, baseId_.back(), zoneId_par_.back()[indx], sectionId2[indx], min, max, ef.data(), ef_offset.data()) != CG_OK)
987 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_over_zone : cgp_poly_elements_write_data !" << finl, TRUST_CGNS_ERROR();
988 }
989 else
990 {
991 const std::vector<cgsize_t>& es = TRUST2CGNS.get_local_es(),
992 &es_offset = TRUST2CGNS.get_local_es_offset();
993
994 max = min + TRUST2CGNS.get_nb_es() -1;
995
996 if (cgp_poly_elements_write_data(fileId_, baseId_.back(), zoneId_par_.back()[indx], sectionId[indx], min, max, es.data(), es_offset.data()) != CG_OK)
997 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_over_zone : cgp_poly_elements_write_data !" << finl, TRUST_CGNS_ERROR();
998 }
999 }
1000 else
1001 {
1002 std::vector<cgsize_t> elems;
1003 TRUST2CGNS.convert_connectivity(cgns_type_elem, elems);
1004
1005 max = nb_elem; /* now we need local elem */
1006 if (cgp_elements_write_data(fileId_, baseId_.back(), zoneId_par_.back()[indx], sectionId[indx], min, max, elems.data()) != CG_OK)
1007 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_over_zone : cgp_elements_write_data !" << finl, TRUST_CGNS_ERROR();
1008 }
1009 }
1010 TRUST2CGNS.clear_vectors();
1011#endif
1012}
1013
1014void Ecrire_CGNS::cgns_write_field_par_over_zone(const int comp, const double temps, const Nom& id_du_champ, const Nom& id_du_domaine, const Nom& localisation, const Nom& nom_dom, const DoubleTab& valeurs)
1015{
1016#ifdef MPI_
1017 assert (!Option_CGNS::USE_LINKS || postraiter_domaine_);
1018 const std::string LOC = Motcle(localisation).getString();
1019 Motcle id_du_champ_modifie = TRUST_2_CGNS::modify_field_name_for_post(id_du_champ, id_du_domaine, LOC, fieldId_som_, fieldId_elem_, fieldId_faces_);
1020 const Nom& id_champ = id_du_champ_modifie;
1021
1022 /* 1 : Get corresponding domain index */
1023 int ind_glob = -123, ind_base = -123;
1024 TRUST_2_CGNS::init_glob_base_domain_idx(doms_written_, nom_dom, true /* has_field */, LOC, ind_glob, ind_base);
1025
1026 /* 2 : CREATION OF FILE STRUCTURE
1027 *
1028 * - All processors THAT HAVE nb_vals > 0 write the same information.
1029 * - Only field meta-data is written to the library at this stage ... So no worries ^^
1030 * - And just once per dt !
1031 */
1032 const TRUST_2_CGNS& TRUST2CGNS = T2CGNS_[ind_base];
1033
1034 const int nb_zones_to_write = TRUST2CGNS.nb_procs_writing();
1035 const bool all_write = TRUST2CGNS.all_procs_write(); // all procs will write !
1036
1037 cgns_helper_.cgns_sol_write<TYPE_ECRITURE_CGNS::PAR_OVER>(nb_zones_to_write, fileId_, baseId_[ind_glob], ind_glob,
1038 static_cast<int>(time_post_.size() - 1), zoneId_par_[ind_glob], LOC,
1039 solname_som_, solname_elem_, solname_faces_,
1040 solname_som_written_, solname_elem_written_, solname_faces_written_,
1041 flowId_som_, flowId_elem_, flowId_faces_);
1042
1043 cgns_helper_.cgns_field_write<TYPE_ECRITURE_CGNS::PAR_OVER>(nb_zones_to_write, fileId_, baseId_[ind_glob], ind_glob, zoneId_par_[ind_glob], LOC,
1044 flowId_som_, flowId_elem_, flowId_faces_, id_champ.getChar(),
1045 fieldId_som_, fieldId_elem_, fieldId_faces_);
1046
1047 /* 3 : Fill field values & dump to cgns file */
1048 const int proc_me = Process::me(), nb_vals = valeurs.dimension(0);
1049 if (nb_vals > 0) // this proc will write !
1050 {
1051 cgsize_t min = 1, max = nb_vals;
1052 int indx = -123;
1053 const std::vector<int>& proc_non_zero_write= TRUST2CGNS.get_proc_non_zero_elem();
1054 if (all_write) indx = proc_me;
1055 else
1056 for (int i = 0; i < nb_zones_to_write; i++)
1057 if (proc_non_zero_write[i] == proc_me)
1058 {
1059 indx = i;
1060 break;
1061 }
1062
1063 if (LOC == "FACES")
1064 {
1065 const Domaine_VF& dom_vf = ref_cast(Domaine_VF, domaine_dis_.valeur());
1066 DoubleTrav new_vals;
1067 TRUST_2_CGNS::map_face_values(dom_vf, valeurs, new_vals);
1068
1069 max = new_vals.dimension(0); // XXX
1070
1071 cgns_helper_.cgns_field_write_data<TYPE_ECRITURE_CGNS::PAR_OVER>(fileId_, baseId_[ind_glob], indx /* XXX */, zoneId_par_[ind_glob], LOC,
1072 flowId_som_, flowId_elem_, flowId_faces_,
1073 fieldId_som_, fieldId_elem_, fieldId_faces_,
1074 comp, min, max, new_vals);
1075 }
1076 else
1077 cgns_helper_.cgns_field_write_data<TYPE_ECRITURE_CGNS::PAR_OVER>(fileId_, baseId_[ind_glob], indx /* XXX */, zoneId_par_[ind_glob], LOC,
1078 flowId_som_, flowId_elem_, flowId_faces_,
1079 fieldId_som_, fieldId_elem_, fieldId_faces_,
1080 comp, min, max, valeurs);
1081 }
1082#endif
1083}
1084
1085/*
1086 * ************************* *
1087 * VERSION PARALLELE IN ZONE *
1088 * ************************* *
1089 */
1090void Ecrire_CGNS::cgns_write_domaine_par_in_zone(const Domaine * domaine,const Nom& nom_dom, const DoubleTab& les_som, const IntTab& les_elem, const Motcle& type_elem)
1091{
1092#ifdef MPI_
1093
1094 if (is_deformable_ && !first_time_post_)
1095 {
1096 cgns_write_domaine_deformable_par_in_zone(domaine, nom_dom, les_som, les_elem, type_elem);
1097 return;
1098 }
1099
1100 doms_written_.push_back(nom_dom);
1101
1102 /* 1 : Instance of TRUST_2_CGNS */
1103 T2CGNS_.push_back(TRUST_2_CGNS());
1104 TRUST_2_CGNS& TRUST2CGNS = T2CGNS_.back();
1105 TRUST2CGNS.associer_domaine_TRUST(domaine, domaine_dis_ ? &(domaine_dis_.valeur()) : nullptr,
1106 les_som, les_elem, postraiter_domaine_, discr_type_);
1107
1108 if (is_dual_ && Objet_U::dimension == 3)
1109 {
1110 assert(fs_dual_.size() > 0 && ef_dual_.size() > 0);
1111 TRUST2CGNS.associer_connec_pour_dual(fs_dual_, ef_dual_);
1112 }
1113
1114 CGNS_TYPE cgns_type_elem = TRUST2CGNS.convert_elem_type(type_elem);
1115 const bool is_polyedre = (type_elem == "POLYEDRE" || type_elem == "PRISME" || type_elem == "PRISME_HEXAG");
1116 const int icelldim = TRUST2CGNS.topo_dim_from_elem(cgns_type_elem, is_polyedre); // avant ca : icelldim = les_som.dimension(1)
1117 const int nb_elem = les_elem.dimension(0), iphysdim = Objet_U::dimension;
1118
1119 /* 2 : Fill coords */
1120 std::vector<double> xCoords, yCoords, zCoords;
1121 TRUST2CGNS.fill_coords(xCoords, yCoords, zCoords);
1122
1123 TRUST2CGNS.fill_global_infos(); // XXX
1124
1125 const bool enter_group_comm = is_comm_group_mode();
1126
1127 const int proc_me = enter_group_comm ? TRUST2CGNS.get_proc_me_local_comm() : Process::me();
1128
1129 if (cgns_type_elem == CGNS_ENUMV(NGON_n)) /*cas polygone/polyedre */
1130 TRUST2CGNS.fill_global_infos_poly(is_polyedre);
1131
1132 const int ns_tot = TRUST2CGNS.get_ns_tot(), ne_tot = TRUST2CGNS.get_ne_tot();
1133
1134 assert (enter_group_comm || (!enter_group_comm && ns_tot > 0 && ne_tot > 0));
1135
1136 char basename[CGNS_STR_SIZE];
1137 strcpy(basename, nom_dom.getChar()); // dom name
1138
1139 cgns_fill_info_grid_link_file(basename, cgns_type_elem, icelldim, ns_tot, ne_tot, is_polyedre);
1140
1141 /* 3-4 : CREATION OF FILE STRUCTURE : base, zones, coords & sections
1142 *
1143 * - All processors write the same information.
1144 * - XXX XXX XXX Only ONE zone meta-data is written to the library at this stage ...
1145 */
1146
1147 // XXX on touche pas, avant le return oui .
1148 baseId_.push_back(-123); // pour chaque dom, on a une baseId
1149 zoneId_.push_back(-123); // pareil, pour chaque dom, on a une zoneId
1150
1151 // XXX Elie Saikali : zone vide, rien a ecrire (base aussi !) ... (cas LINKED_FILES_PER_COMM_GROUP !!!)
1152 if (ne_tot == 0 && ns_tot == 0)
1153 return;
1154
1155 if (cg_base_write(fileId_, basename, icelldim, iphysdim, &baseId_.back()) != CG_OK)
1156 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_in_zone : cg_base_write !" << finl, TRUST_CGNS_ERROR();
1157
1158 /* 4.1 : Create zone & grid */
1159 const cgsize_t isize[3]= { ns_tot, ne_tot, 0 }; /* boundary vertex size (zero if elements not sorted) */
1160 int coordsIdx = -123, coordsIdy = -123, coordsIdz = -123, sectionId = -123, sectionId2 = -123;
1161
1162 cgns_helper_.cgns_write_zone_grid_coord<TYPE_ECRITURE_CGNS::PAR_IN>(icelldim, fileId_, baseId_.back(), basename /* Dom name */, isize,
1163 zoneId_.back(), xCoords, yCoords, zCoords, coordsIdx, coordsIdy, coordsIdz);
1164
1165 /* 4.2 : Construct the sections to host connectivity later */
1166 const int ind_base_zone = static_cast<int>(baseId_.size()) - 1; // we need back() !!
1167 assert(ind_base_zone == static_cast<int>(zoneId_.size()) - 1);
1168 cgns_build_connectivity_sections_par_in_zone(cgns_type_elem, is_polyedre, TRUST2CGNS, ind_base_zone, ne_tot, sectionId, sectionId2);
1169
1170 /* 5 : Write grid coordinates & set connectivity */
1171 if (nb_elem > 0) // seulement si le proc a qlq chose a ecrire
1172 {
1173 const std::vector<int>& incr_max_som = TRUST2CGNS.get_global_incr_max_som(),
1174 &incr_min_som = TRUST2CGNS.get_global_incr_min_som();
1175
1176 cgsize_t min = incr_min_som[proc_me], max = incr_max_som[proc_me];
1177 assert (min <= max);
1178
1179 /* 5.1 : Write grid coordinates */
1180 cgns_helper_.cgns_write_grid_coord_data<TYPE_ECRITURE_CGNS::PAR_IN>(icelldim, fileId_, baseId_.back(), zoneId_.back(),
1181 coordsIdx, coordsIdy, coordsIdz, min, max, xCoords, yCoords, zCoords);
1182
1183 /* 5.2 : Set element connectivity */
1184 cgns_write_connectivity_par_in_zone(cgns_type_elem, is_polyedre, TRUST2CGNS, ind_base_zone, sectionId, sectionId2);
1185 }
1186
1187 if (!is_deformable_)
1188 TRUST2CGNS.clear_vectors();
1189#endif
1190}
1191
1192void Ecrire_CGNS::cgns_build_connectivity_sections_par_in_zone(const CGNS_TYPE cgns_type_elem, const bool is_polyedre,
1193 const TRUST_2_CGNS& TRUST2CGNS, const int ind_base_zone,
1194 const int ne_tot, int& sectionId, int& sectionId2 ) const
1195{
1196#ifdef MPI_
1197 cgsize_t start = -123, end = -123;
1198 if (cgns_type_elem == CGNS_ENUMV(NGON_n)) // cas polyedre
1199 {
1200 cgsize_t maxoffset = -123;
1201
1202 if (is_polyedre) // Pas pour polygone
1203 {
1204 const int nb_fs = TRUST2CGNS.get_nfs_tot();
1205 const int nb_fs_offset = TRUST2CGNS.get_nfs_offset_tot();
1206
1207 start = 1, end = start + nb_fs - 1;
1208 maxoffset = nb_fs_offset;
1209 assert(start <= end);
1210
1211 if (cgp_poly_section_write(fileId_, baseId_[ind_base_zone], zoneId_[ind_base_zone], "NGON_n", CGNS_ENUMV(NGON_n), start, end, maxoffset, 0, &sectionId) != CG_OK)
1212 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_in_zone : cgp_poly_section_write !" << finl, TRUST_CGNS_ERROR();
1213
1214 const int nb_ef = TRUST2CGNS.get_nef_tot();
1215 const int nb_ef_offset = TRUST2CGNS.get_nef_offset_tot();
1216
1217 start = end + 1, end = start + nb_ef - 1;
1218 maxoffset = nb_ef_offset;
1219 assert(start <= end);
1220
1221 if (cgp_poly_section_write(fileId_, baseId_[ind_base_zone], zoneId_[ind_base_zone], "NFACE_n", CGNS_ENUMV(NFACE_n), start, end, maxoffset, 0, &sectionId2) != CG_OK)
1222 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_in_zone : cgp_poly_section_write !" << finl, TRUST_CGNS_ERROR();
1223 }
1224 else // polygon
1225 {
1226 const int nb_es = ne_tot;
1227 const int nb_es_offset = TRUST2CGNS.get_nes_offset_tot();
1228
1229 start = 1, end = start + nb_es - 1;
1230 maxoffset = nb_es_offset;
1231
1232 if (cgp_poly_section_write(fileId_, baseId_[ind_base_zone], zoneId_[ind_base_zone], "NGON_n", CGNS_ENUMV(NGON_n), start, end, maxoffset, 0, &sectionId) != CG_OK)
1233 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_in_zone : cgp_poly_section_write !" << finl, TRUST_CGNS_ERROR();
1234 }
1235 }
1236 else
1237 {
1238 start = 1, end = ne_tot;
1239 assert(start <= end);
1240
1241 if (cgp_section_write(fileId_, baseId_[ind_base_zone], zoneId_[ind_base_zone], "Elem", cgns_type_elem, start, end, 0, &sectionId) != CG_OK)
1242 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_in_zone : cgp_section_write !" << finl, TRUST_CGNS_ERROR();
1243 }
1244#endif
1245}
1246
1247void Ecrire_CGNS::cgns_write_connectivity_par_in_zone(const CGNS_TYPE cgns_type_elem, const bool is_polyedre,
1248 const TRUST_2_CGNS& TRUST2CGNS, const int ind_base_zone,
1249 const int sectionId, const int sectionId2) const
1250{
1251#ifdef MPI_
1252 const bool enter_group_comm = is_comm_group_mode();
1253
1254 const int proc_me = enter_group_comm ? TRUST2CGNS.get_proc_me_local_comm() : Process::me();
1255 cgsize_t min, max;
1256
1257 if (cgns_type_elem == CGNS_ENUMV(NGON_n)) // cas polyedre
1258 {
1259 if (is_polyedre)
1260 {
1261 const std::vector<cgsize_t>& fs = TRUST2CGNS.get_local_fs(),
1262 &fs_offset = TRUST2CGNS.get_local_fs_offset();
1263
1264 const std::vector<int>& incr_min_face_som = TRUST2CGNS.get_global_incr_min_face_som(),
1265 &incr_max_face_som = TRUST2CGNS.get_global_incr_max_face_som();
1266
1267 min = incr_min_face_som[proc_me], max = incr_max_face_som[proc_me];
1268 assert (min <= max);
1269
1270 if (cgp_poly_elements_write_data(fileId_, baseId_[ind_base_zone], zoneId_[ind_base_zone], sectionId, min, max, fs.data(), fs_offset.data()) != CG_OK)
1271 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_in_zone : cgp_poly_elements_write_data !" << finl, TRUST_CGNS_ERROR();
1272
1273 const std::vector<cgsize_t>& ef = TRUST2CGNS.get_local_ef(),
1274 &ef_offset = TRUST2CGNS.get_local_ef_offset();
1275
1276 const std::vector<int>& incr_min_elem_face = TRUST2CGNS.get_global_incr_min_elem_face(),
1277 &incr_max_elem_face = TRUST2CGNS.get_global_incr_max_elem_face();
1278
1279 min = incr_max_face_som.back() + incr_min_elem_face[proc_me]; // BOOM
1280 max = incr_max_face_som.back() + incr_max_elem_face[proc_me]; // BEEM
1281 assert (min <= max);
1282
1283 if (cgp_poly_elements_write_data(fileId_, baseId_[ind_base_zone], zoneId_[ind_base_zone], sectionId2, min, max, ef.data(), ef_offset.data()) != CG_OK)
1284 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_in_zone : cgp_poly_elements_write_data !" << finl, TRUST_CGNS_ERROR();
1285 }
1286 else
1287 {
1288 const std::vector<cgsize_t>& es = TRUST2CGNS.get_local_es(),
1289 &es_offset = TRUST2CGNS.get_local_es_offset();
1290
1291 const std::vector<int>& incr_max_elem = TRUST2CGNS.get_global_incr_max_elem(),
1292 &incr_min_elem = TRUST2CGNS.get_global_incr_min_elem();
1293
1294 min = incr_min_elem[proc_me], max = incr_max_elem[proc_me];
1295 assert (min <= max);
1296
1297 if (cgp_poly_elements_write_data(fileId_, baseId_[ind_base_zone], zoneId_[ind_base_zone], sectionId, min, max, es.data(), es_offset.data()) != CG_OK)
1298 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_in_zone : cgp_poly_elements_write_data !" << finl, TRUST_CGNS_ERROR();
1299 }
1300 }
1301 else
1302 {
1303 std::vector<cgsize_t> elems;
1304 TRUST2CGNS.convert_connectivity(cgns_type_elem, elems);
1305
1306 const std::vector<int>& incr_max_elem = TRUST2CGNS.get_global_incr_max_elem(),
1307 &incr_min_elem = TRUST2CGNS.get_global_incr_min_elem();
1308
1309 min = incr_min_elem[proc_me], max = incr_max_elem[proc_me];
1310 assert (min <= max);
1311
1312 if (cgp_elements_write_data(fileId_, baseId_[ind_base_zone], zoneId_[ind_base_zone], sectionId, min, max, elems.data()) != CG_OK)
1313 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_par_in_zone : cgp_elements_write_data !" << finl, TRUST_CGNS_ERROR();
1314 }
1315#endif
1316}
1317
1318void Ecrire_CGNS::cgns_write_field_par_in_zone(const int comp, const double temps, const Nom& id_du_champ, const Nom& id_du_domaine, const Nom& localisation, const Nom& nom_dom, const DoubleTab& valeurs)
1319{
1320#ifdef MPI_
1321 const int nb_vals = valeurs.dimension(0);
1322 const std::string LOC = Motcle(localisation).getString();
1323 Motcle id_du_champ_modifie = TRUST_2_CGNS::modify_field_name_for_post(id_du_champ, id_du_domaine, LOC, fieldId_som_, fieldId_elem_, fieldId_faces_);
1324 const Nom& id_champ = id_du_champ_modifie;
1325
1326 /* 1 : Get corresponding domain index */
1327 int ind_glob = -123, ind_base = -123;
1328 TRUST_2_CGNS::init_glob_base_domain_idx(doms_written_, nom_dom, true /* has_field */, LOC, ind_glob, ind_base);
1329
1330 /* 2 : CREATION OF FILE STRUCTURE
1331 *
1332 * - All processors write the same information.
1333 * - Only field meta-data is written to the library at this stage ... So no worries ^^
1334 * - And just once per dt !
1335 */
1336 cgns_helper_.cgns_sol_write<TYPE_ECRITURE_CGNS::PAR_IN>(1 /* nb_zones_to_write */, fileId_, baseId_[ind_glob], ind_glob,
1337 static_cast<int>(time_post_.size() - 1), zoneId_, LOC,
1338 solname_som_, solname_elem_, solname_faces_,
1339 solname_som_written_, solname_elem_written_, solname_faces_written_,
1340 flowId_som_, flowId_elem_, flowId_faces_);
1341
1342 cgns_helper_.cgns_field_write<TYPE_ECRITURE_CGNS::PAR_IN>(1 /* nb_zones_to_write */, fileId_, baseId_[ind_glob], ind_glob, zoneId_, LOC,
1343 flowId_som_, flowId_elem_,flowId_faces_,
1344 id_champ.getChar(), fieldId_som_, fieldId_elem_, fieldId_faces_);
1345
1346 /* 3 : Fill field values & dump to cgns file */
1347 if (nb_vals > 0) // this proc will write !
1348 {
1349 const TRUST_2_CGNS& TRUST2CGNS = T2CGNS_[ind_base];
1350 const bool enter_group_comm = is_comm_group_mode();
1351
1352 const int proc_me = enter_group_comm ? TRUST2CGNS.get_proc_me_local_comm() : Process::me();
1353
1354 cgsize_t min = -123, max = -123;
1355
1356 if (LOC == "SOM")
1357 {
1358 const std::vector<int>& incr_max_som = TRUST2CGNS.get_global_incr_max_som(),
1359 &incr_min_som = TRUST2CGNS.get_global_incr_min_som();
1360
1361 min = incr_min_som[proc_me], max = incr_max_som[proc_me];
1362 }
1363 else
1364 {
1365 const std::vector<int>& incr_max_elem = TRUST2CGNS.get_global_incr_max_elem(),
1366 &incr_min_elem = TRUST2CGNS.get_global_incr_min_elem();
1367
1368 min = incr_min_elem[proc_me], max = incr_max_elem[proc_me];
1369 }
1370
1371 if (LOC == "FACES")
1372 {
1373 const Domaine_VF& dom_vf = ref_cast(Domaine_VF, domaine_dis_.valeur());
1374 DoubleTrav new_vals;
1375 TRUST_2_CGNS::map_face_values(dom_vf, valeurs, new_vals);
1376
1377 cgns_helper_.cgns_field_write_data<TYPE_ECRITURE_CGNS::PAR_IN>(fileId_, baseId_[ind_glob], ind_glob, zoneId_, LOC,
1378 flowId_som_, flowId_elem_, flowId_faces_,
1379 fieldId_som_, fieldId_elem_, fieldId_faces_,
1380 comp, min, max, new_vals);
1381 }
1382 else
1383 cgns_helper_.cgns_field_write_data<TYPE_ECRITURE_CGNS::PAR_IN>(fileId_, baseId_[ind_glob], ind_glob, zoneId_, LOC,
1384 flowId_som_, flowId_elem_, flowId_faces_,
1385 fieldId_som_, fieldId_elem_, fieldId_faces_,
1386 comp, min, max, valeurs);
1387 }
1388#endif
1389}
1390
1391/* cas deformable : 2eme passage ici ! */
1392void Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone(const Domaine * domaine,const Nom& nom_dom, const DoubleTab& les_som, const IntTab& les_elem, const Motcle& type_elem)
1393{
1394#ifdef MPI_
1395 const int ind = TRUST_2_CGNS::get_index_nom_vector(doms_written_, nom_dom);
1396 TRUST_2_CGNS& TRUST2CGNS = T2CGNS_[ind];
1397 TRUST2CGNS.associer_domaine_TRUST(domaine, domaine_dis_ ? &(domaine_dis_.valeur()) : nullptr,
1398 les_som, les_elem, postraiter_domaine_, discr_type_);
1399
1400 CGNS_TYPE cgns_type_elem = TRUST2CGNS.convert_elem_type(type_elem);
1401 const bool is_polyedre = (type_elem == "POLYEDRE" || type_elem == "PRISME" || type_elem == "PRISME_HEXAG");
1402 const int icelldim = TRUST2CGNS.topo_dim_from_elem(cgns_type_elem, is_polyedre); // avant ca : icelldim = les_som.dimension(1)
1403 const int nb_elem = les_elem.dimension(0), iphysdim = Objet_U::dimension;
1404
1405 std::vector<double> xCoords, yCoords, zCoords;
1406 TRUST2CGNS.fill_coords(xCoords, yCoords, zCoords);
1407
1408 char basename[CGNS_STR_SIZE];
1409 strcpy(basename, nom_dom.getChar()); // dom name
1410
1411 if (is_lagrangian_)
1412 {
1413 TRUST2CGNS.fill_global_infos(); // XXX utile car info change en //
1414 if (cgns_type_elem == CGNS_ENUMV(NGON_n)) /*cas polygone/polyedre */
1415 TRUST2CGNS.fill_global_infos_poly(is_polyedre);
1416 }
1417
1418 const int ns_tot = TRUST2CGNS.get_ns_tot(), ne_tot = TRUST2CGNS.get_ne_tot();
1419 const bool enter_group_comm = is_comm_group_mode();
1420 const int proc_me = enter_group_comm ? TRUST2CGNS.get_proc_me_local_comm() : Process::me();
1421
1422 int coordsIdx = -123, coordsIdy = -123, coordsIdz = -123;
1423
1424 /* If deformable only and single_file, connectivity is already seen in same file. we just write new coords */
1425 if (!Option_CGNS::USE_LINKS && !is_lagrangian_)
1426 {
1427 // XXX Elie Saikali : zone vide, rien a ecrire (base aussi !) ... (cas SINGLE_FILE_PER_COMM_GROUP !!!)
1428 if (ne_tot == 0 && ns_tot == 0)
1429 return;
1430
1431 int G = -1;
1432
1433 if (cg_grid_write(fileId_, baseId_[ind], zoneId_[ind], grid_name_loc_.c_str(), &G) != CG_OK)
1434 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone : cg_grid_write !" << finl, TRUST_CGNS_ERROR();
1435
1436 if (cg_goto(fileId_, baseId_[ind], "Zone_t",zoneId_[ind], "GridCoordinates_t", G, "end") != CG_OK)
1437 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone : cg_goto Zone_t !" << finl, TRUST_CGNS_ERROR();
1438
1439 const cgsize_t dims[1] = { ns_tot };
1440
1441 if (cgp_array_write("CoordinateX", CGNS_ENUMV(RealDouble), 1, dims, &coordsIdx) != CG_OK)
1442 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone : cgp_array_write CoordinateX !" << finl, TRUST_CGNS_ERROR();
1443
1444 if (cgp_array_write("CoordinateY", CGNS_ENUMV(RealDouble), 1, dims, &coordsIdy) != CG_OK)
1445 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone : cgp_array_write CoordinateY !" << finl, TRUST_CGNS_ERROR();
1446
1447 if (Objet_U::dimension > 2)
1448 if (cgp_array_write("CoordinateZ", CGNS_ENUMV(RealDouble), 1, dims, &coordsIdz) != CG_OK)
1449 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone : cgp_array_write CoordinateZ !" << finl, TRUST_CGNS_ERROR();
1450
1451 if (nb_elem > 0) // seulement si le proc a qlq chose a ecrire
1452 {
1453 const std::vector<int>& incr_max_som = TRUST2CGNS.get_global_incr_max_som(),
1454 &incr_min_som = TRUST2CGNS.get_global_incr_min_som();
1455
1456 const cgsize_t min = incr_min_som[proc_me], max = incr_max_som[proc_me];
1457 assert (min <= max);
1458
1459 if (cgp_array_write_data(coordsIdx, &min, &max, xCoords.data()) != CG_OK)
1460 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone : cgp_array_write_data CoordinateX !" << finl, TRUST_CGNS_ERROR();
1461
1462 if (cgp_array_write_data(coordsIdy, &min, &max, yCoords.data()) != CG_OK)
1463 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone : cgp_array_write_data CoordinateY !" << finl, TRUST_CGNS_ERROR();
1464
1465 if (Objet_U::dimension > 2)
1466 if (cgp_array_write_data(coordsIdz, &min, &max, zCoords.data()) != CG_OK)
1467 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone : cgp_array_write_data CoordinateZ !" << finl, TRUST_CGNS_ERROR();
1468 }
1469 }
1470 else
1471 /* Here we use links. So we write coords in new solution file. However for connectivity we have 2 cases :
1472 * - Deformable => We link to conn from 1st solution file if all procs have something to write (ie : not domaine cl),
1473 * otherwise we write it to prevent MPI blocage in cg_link_write ...
1474 * - Lagrangian => We write new conn in the considered file
1475 */
1476 {
1477 int glob_min_nb_elem = Process::mp_min(nb_elem); // XXX avant sinon blocage !
1478
1479 // XXX Elie Saikali : zone vide, rien a ecrire (base aussi !) ... (cas LINKED_FILES_PER_COMM_GROUP !!!)
1480 if (ne_tot == 0 && ns_tot == 0)
1481 return;
1482
1483 if (cg_base_write(fileId_, basename, icelldim, iphysdim, &baseId_[ind]) != CG_OK)
1484 Cerr << "Error Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone : cg_base_write !" << finl, TRUST_CGNS_ERROR();
1485
1486 const cgsize_t isize[3]= { ns_tot, ne_tot, 0 }; /* boundary vertex size (zero if elements not sorted) */
1487
1488 cgns_helper_.cgns_write_zone_grid_coord<TYPE_ECRITURE_CGNS::PAR_IN>(icelldim, fileId_, baseId_[ind], basename /* Dom name */, isize,
1489 zoneId_[ind], xCoords, yCoords, zCoords, coordsIdx, coordsIdy, coordsIdz);
1490
1491 int sectionId = -123, sectionId2 = -123;
1492
1493 const bool should_write_conn = (is_lagrangian_ || glob_min_nb_elem <= 0);
1494
1495 if (is_lagrangian_)
1496 sizeId_.push_back( { isize[0], isize[1] } ); // XXX required for links later !
1497
1498 /* Connectivity to be written => Construct the sections to host connectivity later */
1499 if (should_write_conn)
1500 cgns_build_connectivity_sections_par_in_zone(cgns_type_elem, is_polyedre, TRUST2CGNS, ind, ne_tot, sectionId, sectionId2);
1501
1502 if (nb_elem > 0) // seulement si le proc a qlq chose a ecrire
1503 {
1504 const std::vector<int>& incr_max_som = TRUST2CGNS.get_global_incr_max_som(),
1505 &incr_min_som = TRUST2CGNS.get_global_incr_min_som();
1506
1507 cgsize_t min = incr_min_som[proc_me], max = incr_max_som[proc_me];
1508 assert (min <= max);
1509
1510 /* Write grid coordinates */
1511 cgns_helper_.cgns_write_grid_coord_data<TYPE_ECRITURE_CGNS::PAR_IN>(icelldim, fileId_, baseId_[ind], zoneId_[ind],
1512 coordsIdx, coordsIdy, coordsIdz, min, max, xCoords, yCoords, zCoords);
1513
1514 /* Set element connectivity : we rewrite since either topology changes or we need to do that !! */
1515 if (should_write_conn)
1516 cgns_write_connectivity_par_in_zone(cgns_type_elem, is_polyedre, TRUST2CGNS, ind, sectionId, sectionId2);
1517 }
1518
1519 if (!should_write_conn) /* Set element connectivity : by links */
1520 {
1521 std::string linkfile = (enter_group_comm ? Nom(baseFile_name_).nom_me(proc_maitre_local_comm_).getString() : baseFile_name_) +
1522 ".solution." + cgns_helper_.convert_double_to_string(time_post_[0]) + ".cgns";
1523
1524 TRUST_2_CGNS::remove_slash_linkfile(linkfile);
1525
1526 cgns_helper_.cgns_write_connectivity_deformable_links(fileId_, baseId_[ind], zoneId_[ind], linkfile, baseZone_name_[ind], baseZone_name_[ind],
1527 connectname_[ind], "Ecrire_CGNS::cgns_write_domaine_deformable_par_in_zone");
1528 }
1529 }
1530#endif /*MPI_*/
1531}
1532
1533/*
1534 * *************** *
1535 * Write Dual Mesh *
1536 * *************** *
1537 */
1538void Ecrire_CGNS::cgns_write_domaine_dual(const Nom& nom_dom_init, const int est_le_premier_post, const Nom& nom_dom_faces)
1539{
1540 Cerr << "Writing the Dual mesh of " << nom_dom_init << " in a CGNS format ..." << finl;
1541 assert(domaine_dis_);
1542 if (Objet_U::dimension==0)
1543 Process::exit("Dimension is not defined. Check your data file.");
1544 const Domaine_VF& dom_vf = ref_cast(Domaine_VF, domaine_dis_.valeur());
1545 const auto& dual_m = dom_vf.get_mc_dual_mesh();
1546
1547 // Check the mesh
1548#ifndef NDEBUG
1549 dual_m->checkConsistency();
1550#endif
1551
1552 const Nom dom_dual_nom = (nom_dom_faces != "??") ? nom_dom_faces : Nom(dual_m->getName());
1553 Domaine dom_dual;
1554 dom_dual.nommer(dom_dual_nom);
1555
1556 DoubleTab sommets;
1557
1558 // Get the nodes: size and fill sommets
1559 int nnodes = static_cast<int>(dual_m->getNumberOfNodes());
1560 const double *coord = dual_m->getCoords()->begin();
1561 sommets.resize(nnodes, Objet_U::dimension);
1562 std::copy(coord, coord+sommets.size_array(), sommets.addr());
1563
1564 // Get cell connectivity
1565 int ncells = static_cast<int>(dual_m->getNumberOfCells());
1566
1567 ArrOfInt conn, connIndex;
1568 int conn_size = static_cast<int>(dual_m->getNodalConnectivity()->getNbOfElems()),
1569 conn_indx_size= static_cast<int>(dual_m->getNodalConnectivityIndex()->getNbOfElems());
1570
1571 const auto *c = dual_m->getNodalConnectivity()->begin(),
1572 *cI = dual_m->getNodalConnectivityIndex()->begin();
1573
1574 conn.resize(conn_size);
1575 std::copy(c, c + conn_size, conn.addr());
1576 connIndex.resize(conn_indx_size);
1577 std::copy(cI, cI + conn_indx_size, connIndex.addr());
1578
1579 int mesh_type_cell = static_cast<int>(conn[connIndex[0]]); // type is always an int.
1580 Motcle type_cell;
1581
1582 if (mesh_type_cell == INTERP_KERNEL::NORM_TRI3)
1583 type_cell = "Triangle";
1584 else if (mesh_type_cell == INTERP_KERNEL::NORM_POLYHED)
1585 type_cell = "Polyedre";
1586 else
1587 {
1588 Cerr << "Cell type " << mesh_type_cell << " is not supported yet. It should be only triangle (2D) and polyedre (3D). Call the 911 !!" << finl;
1589 Process::exit();
1590 }
1591
1592 Elem_geom type_elem;
1593 type_elem.typer(type_cell);
1594
1595 IntTab les_elems;
1596 // Fill les_elem : Different treatment according type_elem:
1597 if (sub_type(Polyedre, type_elem.valeur()))
1598 {
1599 int marker = 0;
1600 for (int i = 0; i < conn_size; i++)
1601 if (conn[i]<0) marker++;
1602 int num_nodes = conn_size - ncells - marker;
1603 int nfaces = ncells + marker;
1604 ArrOfInt nodes(num_nodes), facesIndex(nfaces+1), polyhedronIndex(ncells+1);
1605 int face=0, node = 0;
1606 for (int i = 0; i < ncells; i++)
1607 {
1608 polyhedronIndex[i] = face; // Index des polyedres
1609
1610 const int index = connIndex[i] + 1;
1611 const int nb_som = static_cast<int>(connIndex[i + 1] - index);
1612 for (int j = 0; j < nb_som; j++)
1613 {
1614 if (j==0 || conn[index + j]<0)
1615 facesIndex[face++] = node; // Index des faces:
1616 if (conn[index + j]>=0)
1617 nodes[node++] = conn[index + j]; // Index local des sommets de la face
1618 }
1619 }
1620 facesIndex[nfaces] = node;
1621 polyhedronIndex[ncells] = face;
1622 ref_cast(Polyedre,type_elem.valeur()).affecte_connectivite_numero_global(nodes, facesIndex, polyhedronIndex, les_elems);
1623 }
1624 else // Tous les autres types
1625 {
1626 for (int i = 0; i < ncells; i++)
1627 {
1628 const int index = connIndex[i] + 1;
1629 const int nb_som = static_cast<int>(connIndex[i + 1] - index);
1630 if (i==0) les_elems.resize(ncells, nb_som); // Size les_elems2
1631 for (int j = 0; j < nb_som; j++)
1632 les_elems(i, j) = conn[index + j];
1633 }
1634 }
1635
1636 // Converting from MED to TRUST connectivity
1637 conn_trust_to_med(les_elems,type_elem->que_suis_je(),false);
1638
1639 dom_dual.les_sommets() = sommets; // fill sommets
1640 dom_dual.type_elem() = type_elem;
1641
1642 dom_dual.type_elem()->associer_domaine(dom_dual);
1643 dom_dual.les_elems() = les_elems;
1644
1645 // write dual_mesh
1646 is_dual_ = true;
1647 // we fill face/som & elem faces conn ET seulement si poly !!!
1648 if (Objet_U::dimension == 3)
1649 fill_connectivity_from_mc_mesh(dual_m, fs_dual_, ef_dual_);
1650
1651 cgns_write_domaine(&dom_dual, dom_dual_nom, sommets, les_elems, type_cell);
1652}
1653
1654#endif /* HAS_CGNS */
DoubleTab_t & les_sommets()
Definition Domaine.h:113
IntTab_t & les_elems()
Definition Domaine.h:129
void nommer(const Nom &nom) override
Donne un nom a l'Objet_U Methode virtuelle a surcharger.
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const char * getChar() const
Definition Nom.h:91
Nom nom_me(int, const char *prefix=0, int without_padding=0) const
Insere _prefix000n (n=me() ou nproc()) dans un nom de fichier (par ex:toto.
Definition Nom.cpp:387
const std::string & getString() const
Definition Nom.h:92
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
static int dimension
Definition Objet_U.h:99
static bool KEEP_FILES_BEFORE_RESET_TIME
Definition Option_CGNS.h:55
static bool PARALLEL_OVER_ZONE
Definition Option_CGNS.h:48
static int CLOSE_EVERY_N
Definition Option_CGNS.h:49
static bool USE_LINKS
Definition Option_CGNS.h:52
static int FLUSH_EVERY_N
Definition Option_CGNS.h:49
static const Comm_Group & get_user_defined_group()
Renvoie une reference au groupe sur defini par l'utilisateur.
static double mp_min(double)
Definition Process.cpp:386
static bool is_parallel()
Definition Process.cpp:110
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
static std::string root
_SIZE_ size_array() const
_TYPE_ * addr()
_TYPE_ * data()
Iterator_ begin()
Definition TRUSTArray.h:111
void resize(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTArray.h:156
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45