TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Ecrire_CGNS_Links.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 <Comm_Group_MPI.h>
17#include <communications.h>
18#include <unordered_set>
19#include <Ecrire_CGNS.h>
20#include <Domaine.h>
21#include <unistd.h>
22
23#ifdef HAS_CGNS
24
25/*
26 * ***************** *
27 * METHODS POUR LINK *
28 * ***************** *
29 */
30
31/**
32 * This file implements the CGNS modes where mesh/support data and solution data are split across several files.
33 *
34 * Current design choices:
35 * - the grid/support file is written once and reused by links,
36 * - one solution file is written per post-processing time,
37 * - the final link file is rebuilt at each post time so the result stays
38 * directly visualizable while the simulation is still running.
39 *
40 * The final link file behaves like a small index/manifest file. Rebuilding it
41 * is intentionally preferred over incremental in-place updates because CGNS
42 * iterative nodes can be fragile to modify and the robustness/readability
43 * trade-off is better with full reconstruction.
44 */
45void Ecrire_CGNS::init_proc_maitre_local_comm()
46{
47 assert(is_comm_group_mode());
48
49 const auto& grp = PE_Groups::get_user_defined_group();
51 {
52 proc_maitre_local_comm_ = PE_Groups::groupe_TRUST().rank();
53 envoyer_broadcast(proc_maitre_local_comm_, 0); // XXX should do this !
55 }
56}
57
58void Ecrire_CGNS::cgns_open_grid_base_link_file()
59{
60 assert(Option_CGNS::USE_LINKS && !postraiter_domaine_);
61 std::string fn;
62
63 if (is_linked_files_comm_group_mode())
64 {
65 fn = (Nom(baseFile_name_)).nom_me(proc_maitre_local_comm_).getString() + ".grid.cgns"; // file name
66 unlink(fn.c_str());
67 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::PAR>(fn, fileId_, false);
68 Cerr << "**** Multiple parallel CGNS files " << baseFile_name_ << "_XXXX.grid.cgns opened !" << finl;
69 }
70 else
71 {
72 fn = baseFile_name_ + ".grid.cgns"; // file name
73 unlink(fn.c_str());
74
76 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::PAR>(fn, fileId_);
77 else
78 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::SEQ>(fn, fileId_);
79 }
80
81 grid_file_opened_ = true;
82}
83
84void Ecrire_CGNS::cgns_close_grid_or_solution_link_file(const double t, const TYPE_LINK_CGNS type, bool is_cerr)
85{
86 assert((Option_CGNS::USE_LINKS && !postraiter_domaine_) || is_lagrangian_);
87
88 std::string fn; // file name
89
90 if (type == TYPE_LINK_CGNS::GRID)
91 {
92 if (is_linked_files_comm_group_mode())
93 fn = baseFile_name_ + "_XXXX.grid.cgns";
94 else
95 fn = baseFile_name_ + ".grid.cgns";
96 }
97 else if (type == TYPE_LINK_CGNS::SOLUTION)
98 {
99 if (is_linked_files_comm_group_mode())
100 fn = baseFile_name_ + "_XXXX_" + ".solution." + cgns_helper_.convert_double_to_string(t) + ".cgns";
101 else
102 fn = baseFile_name_ + ".solution." + cgns_helper_.convert_double_to_string(t) + ".cgns";
103 }
104 else if (type == TYPE_LINK_CGNS::FINAL_LINK)
105 fn = baseFile_name_ + ".cgns";
106 else
107 Process::exit("Error in Ecrire_CGNS::cgns_close_grid_or_solution_link_file !!! \n");
108
109 if (Process::is_parallel() && (type != TYPE_LINK_CGNS::FINAL_LINK))
110 {
111 if (is_linked_files_comm_group_mode())
112 {
113 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::PAR>(fn /* inutile */, fileId_, false);
114 Cerr << "**** Multiple parallel CGNS files " << fn << " closed !" << finl;
115 }
116 else
117 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::PAR>(fn, fileId_, is_cerr);
118 }
119 else
120 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::SEQ>(fn, fileId_, is_cerr);
121
122 if (type == TYPE_LINK_CGNS::GRID)
123 grid_file_opened_ = false;
124
125 if (type == TYPE_LINK_CGNS::SOLUTION)
126 solution_file_opened_ = false;
127}
128
129void Ecrire_CGNS::cgns_fill_info_grid_link_file(const char* basename, const CGNS_TYPE& cgns_type_elem, const int icelldim, const int nb_som, const int nb_elem, const bool is_polyedre)
130{
131 cellDim_.push_back(icelldim);
132 baseZone_name_.push_back(std::string(basename));
133 sizeId_.push_back( { nb_som, nb_elem } );
134
135 if (cgns_type_elem == CGNS_ENUMV(NGON_n)) // cas polyedre
136 {
137 if (is_polyedre)
138 connectname_.push_back( { "NGON_n", "NFACE_n" });
139 else
140 connectname_.push_back({ "NGON_n" });
141 }
142 else
143 connectname_.push_back({ "Elem" }); // autre cas
144}
145
146void Ecrire_CGNS::cgns_init_solution_link_file(const std::string& LOC, const Nom& nom_dom)
147{
148 assert (LOC == "ELEM" || LOC == "SOM");
149 Cerr << "### Building a new CGNS base with a linked zone to host the field located at : " << LOC << " !" << finl;
150 doms_written_.push_back(nom_dom);
151 baseId_.push_back(-123); // pour chaque dom, on a une baseId
152 zoneId_.push_back(-123);
153}
154
155void Ecrire_CGNS::gather_local_sizeId_for_comm_group()
156{
157#ifdef MPI_
158 if (!vec_proc_maitre_local_comm_.empty()) return; /* rien a faire */
159
160 unique_vec_proc_maitre_local_comm_.clear();
161 sizeId_som_local_comm_.clear();
162 sizeId_elem_local_comm_.clear();
163
164 vec_proc_maitre_local_comm_.assign(Process::nproc(), -123 /* default */);
165 MPI_Allgather(&proc_maitre_local_comm_, 1, MPI_ENTIER, vec_proc_maitre_local_comm_.data(), 1, MPI_ENTIER, Comm_Group_MPI::get_trio_u_world());
166
167 std::unordered_set<int> seen;
168
169 for (int val : vec_proc_maitre_local_comm_)
170 if (seen.insert(val).second)
171 unique_vec_proc_maitre_local_comm_.push_back(val); // si val pas dedans
172
173 std::vector<std::vector<cgsize_t>> sizeId_som_local_comm_tmp, sizeId_elem_local_comm_tmp;
174 sizeId_som_local_comm_tmp.reserve(sizeId_.size());
175 sizeId_elem_local_comm_tmp.reserve(sizeId_.size());
176
177 MPI_Datatype CGNS_MPI_SIZE;
178 MPI_Type_match_size(MPI_TYPECLASS_INTEGER, sizeof(cgsize_t), &CGNS_MPI_SIZE);
179
180 for (int i = 0; i < static_cast<int>(sizeId_.size()); i++)
181 {
182 assert(sizeId_[i].size() == 2);
183
184 sizeId_som_local_comm_tmp.emplace_back(Process::nproc(), static_cast<cgsize_t>(-123));
185 sizeId_elem_local_comm_tmp.emplace_back(Process::nproc(), static_cast<cgsize_t>(-123));
186
187 MPI_Allgather(&sizeId_[i][0], 1, CGNS_MPI_SIZE, sizeId_som_local_comm_tmp[i].data(), 1, CGNS_MPI_SIZE, Comm_Group_MPI::get_trio_u_world());
188 MPI_Allgather(&sizeId_[i][1], 1, CGNS_MPI_SIZE, sizeId_elem_local_comm_tmp[i].data(), 1, CGNS_MPI_SIZE, Comm_Group_MPI::get_trio_u_world());
189 }
190
191 const int nb_grps = static_cast<int>(unique_vec_proc_maitre_local_comm_.size());
192 sizeId_som_local_comm_.reserve(sizeId_.size());
193 sizeId_elem_local_comm_.reserve(sizeId_.size());
194
195 for (int i = 0; i < static_cast<int>(sizeId_.size()); i++)
196 {
197 sizeId_som_local_comm_.emplace_back(nb_grps, static_cast<cgsize_t>(-123));
198 sizeId_elem_local_comm_.emplace_back(nb_grps, static_cast<cgsize_t>(-123));
199
200 for (int j = 0; j < nb_grps; j++)
201 {
202 int proc_grp = unique_vec_proc_maitre_local_comm_[j];
203 sizeId_som_local_comm_[i][j] = sizeId_som_local_comm_tmp[i][proc_grp];
204 sizeId_elem_local_comm_[i][j] = sizeId_elem_local_comm_tmp[i][proc_grp];
205 }
206 }
207#endif
208}
209
210/* Used to create a support in a single CGNS file
211 * ie : called once at the beginning while filling fld_loc_map_ */
212void Ecrire_CGNS::add_new_linked_base(const std::string& LOC, const Nom& nom_dom)
213{
214 assert (LOC == "ELEM" || LOC == "SOM");
215 Cerr << "### Building a new CGNS base with a linked zone to host the field located at : " << LOC << " !" << finl;
216
217 doms_written_.push_back(nom_dom);
218 baseId_.push_back(-123); // pour chaque dom, on a une baseId
219
220 const Nom nom_dom_mod = TRUST_2_CGNS::modify_domaine_name_for_link(nom_dom, LOC);
221 const int ind_base = TRUST_2_CGNS::get_index_nom_vector(doms_written_, nom_dom_mod); // get index of orig dom
222
223 if (cg_base_write(fileId_, nom_dom.getChar(), cellDim_[ind_base], Objet_U::dimension, &baseId_.back()) != CG_OK)
224 Cerr << "Error Ecrire_CGNS::add_new_linked_base : cg_base_write !" << finl, TRUST_CGNS_ERROR();
225
226 if (Process::is_parallel() && (Option_CGNS::PARALLEL_OVER_ZONE || postraiter_domaine_))
227 {
228 zoneId_.clear(); // XXX commencons par ca
229 TRUST_2_CGNS& TRUST2CGNS = T2CGNS_[ind_base];
230 const std::vector<int>& global_nb_elem = TRUST2CGNS.get_global_nb_elem(),
231 &global_nb_som = TRUST2CGNS.get_global_nb_som(),
232 &proc_non_zero_elem = TRUST2CGNS.get_proc_non_zero_elem();
233
234 const int nb_zones_to_write = TRUST2CGNS.nb_procs_writing();
235 const bool all_write = TRUST2CGNS.all_procs_write(); // all procs will write !
236 std::string zonename, zonename_link;
237
238 for (int i = 0; i != nb_zones_to_write; i++)
239 {
240 const int indZ = all_write ? i : proc_non_zero_elem[i]; // procID
241 const int ne_loc = global_nb_elem[indZ], ns_loc = global_nb_som[indZ]; /* nb_elem & nb_som local */
242 assert (ne_loc > 0);
243
244 zoneId_.push_back(-123);
245 const cgsize_t isize[3] = { ns_loc , ne_loc , 0 }; /* 0 => boundary vertex size (zero if elements not sorted) */
246
247 zonename = nom_dom.nom_me(indZ).getString();
248 zonename_link = nom_dom_mod.nom_me(indZ).getString();
249
250 cgns_helper_.cgns_write_zone_and_classic_links(true /* write_zone */, fileId_, baseId_.back(), zonename, isize, zoneId_.back(), indZ + 1,
251 "" /* meme fichier */, nom_dom_mod.getString(), zonename_link, connectname_[ind_base],
252 "Ecrire_CGNS::add_new_linked_base");
253 }
254
255 zoneId_par_.push_back(zoneId_); // XXX : Dont touch
256 }
257 else
258 {
259 zoneId_.push_back(-123);
260 const cgsize_t isize[3] = { sizeId_[ind_base][0] , sizeId_[ind_base][1] , 0 };
261
262 cgns_helper_.cgns_write_zone_and_classic_links(true /* write_zone */, fileId_, baseId_.back(), nom_dom.getString(), isize, zoneId_.back(), 1,
263 "" /* meme fichier */, baseZone_name_[ind_base], baseZone_name_[ind_base], connectname_[ind_base],
264 "Ecrire_CGNS::add_new_linked_base");
265 }
266}
267
268/* Used to open a new solution file, link all required supports to grid file (elem/som)
269 * ie : called once at the beginning while filling fld_loc_map_, and then at each add_time */
270void Ecrire_CGNS::cgns_open_solution_link_file(const double t)
271{
272 assert((Option_CGNS::USE_LINKS && !postraiter_domaine_) || is_lagrangian_);
273
274 const bool enter_group_comm = is_linked_files_comm_group_mode();
275 std::string fn;
276
277 if (enter_group_comm)
278 fn = (Nom(baseFile_name_)).nom_me(proc_maitre_local_comm_).getString() + ".solution." + cgns_helper_.convert_double_to_string(t) + ".cgns"; // file name
279 else
280 fn = baseFile_name_ + ".solution." + cgns_helper_.convert_double_to_string(t) + ".cgns"; // file name
281
282 unlink(fn.c_str());
283
285 {
286 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::PAR>(fn, fileId_, enter_group_comm ? false : true);
287
288 if (enter_group_comm)
289 Cerr << "**** Multiple parallel CGNS files " << baseFile_name_ << "_XXXX.solution." + cgns_helper_.convert_double_to_string(t) + ".cgns opened !" << finl;
290 }
291 else
292 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::SEQ>(fn, fileId_, true);
293
294 solution_file_opened_ = true;
295
296 if (is_deformable_)
297 return; /* Stop here if deformable */
298
299 /* Otherwise, we have a grid file already written ... we link the zones in the opened solution files to it (coords + connectivity) ! */
300 for (auto &itr : fld_loc_map_)
301 {
302 const std::string& LOC = itr.first;
303 const Nom& nom_dom = itr.second;
304
305 int index_glob = -123, ind_base = -123;
306 TRUST_2_CGNS::init_glob_base_domain_idx(doms_written_, nom_dom, true /* has_fields */, LOC, index_glob, ind_base);
307
308 if (cg_base_write(fileId_, nom_dom.getChar(), cellDim_[ind_base], Objet_U::dimension, &baseId_[index_glob]) != CG_OK)
309 Cerr << "Error Ecrire_CGNS::cgns_open_solution_link_file : cg_base_write !" << finl, TRUST_CGNS_ERROR();
310
311 /*
312 * XXX this is done in //, not like final link file which is done only on proc 0
313 * So no need to get sizes per local comm ... each proc available on its comm group take the good values
314 */
315 const cgsize_t isize[3] = { sizeId_[ind_base][0] , sizeId_[ind_base][1] , 0 };
316
317 std::string linkfile = baseFile_name_ + ".grid.cgns"; // file name
318
319 if (enter_group_comm)
320 linkfile = (Nom(baseFile_name_)).nom_me(proc_maitre_local_comm_).getString() + ".grid.cgns"; // file name
321
322 TRUST_2_CGNS::remove_slash_linkfile(linkfile);
323
324 cgns_helper_.cgns_write_zone_and_classic_links(true /* write_zone */, fileId_, baseId_[index_glob], nom_dom.getString(), isize, zoneId_[index_glob], 1,
325 linkfile, baseZone_name_[ind_base], baseZone_name_[ind_base], connectname_[ind_base],
326 "Ecrire_CGNS::cgns_open_solution_link_file");
327 }
328}
329
330void Ecrire_CGNS::cgns_write_final_link_file_for_single_file_comm_group()
331{
332#ifdef MPI_
333 if (vec_proc_maitre_local_comm_.empty())
334 gather_local_sizeId_for_comm_group();
335
336 int fileId_link;
337 std::string fn = baseFile_name_ + ".cgns";
338 unlink(fn.c_str());
339 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::PAR>(fn, fileId_link, true);
340
341 const int nb_grps = static_cast<int>(unique_vec_proc_maitre_local_comm_.size());
342 std::vector<int> zoneId_tmp;//(nb_grps, -123);
343 std::vector<int> baseId_tmp(baseId_);
344
345 for (auto &itr : doms_written_)
346 {
347 bool has_field = false;
348 std::string LOC = "rien";
349 TRUST_2_CGNS::init_has_field_and_loc_iters(itr, fld_loc_map_, has_field, LOC);
350
351 int index_glob = -123, ind_base = -123;
352 TRUST_2_CGNS::init_glob_base_domain_idx(doms_written_, itr, has_field, LOC, index_glob, ind_base);
353
354 if (cg_base_write(fileId_link, itr.getChar(), cellDim_[ind_base], Objet_U::dimension, &baseId_tmp[index_glob]) != CG_OK)
355 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_comm_group : cg_base_write !" << finl, TRUST_CGNS_ERROR();
356
357 int zone_goto_idx = 1;
358 zoneId_tmp.clear();
359
360 /* Loop on groups that have something to link to ;) */
361 for (int gid = 0; gid < nb_grps; gid++)
362 {
363 int proc_grp = unique_vec_proc_maitre_local_comm_[gid];
364 std::string zone_name = Nom("Zone").nom_me(proc_grp).getString();
365
366 std::string file_group_id = Nom(baseFile_name_).nom_me(proc_grp).getString();
367 TRUST_2_CGNS::remove_slash_linkfile(file_group_id);
368
369 const cgsize_t isize[3] = { sizeId_som_local_comm_[ind_base][gid], sizeId_elem_local_comm_[ind_base][gid], 0 };
370
371 if ((isize[0] == 0 && isize[1] == 0)) continue;
372
373 zoneId_tmp.push_back(-123);
374
375 if (is_deformable_)
376 {
377 cgns_helper_.cgns_write_zone_and_deformable_links(true /* write zone */, has_field, fileId_link, baseId_tmp[index_glob],
378 zone_name, isize, zoneId_tmp.back(), zone_goto_idx,
379 file_group_id, baseZone_name_[ind_base], baseZone_name_[ind_base],
380 connectname_[ind_base], itr, LOC, time_post_,
381 "Ecrire_CGNS::cgns_write_final_link_file_comm_group");
382 }
383 else
384 {
385 cgns_helper_.cgns_write_zone_and_classic_links(true /* write_zone */, fileId_link, baseId_tmp[index_glob], zone_name,
386 isize, zoneId_tmp.back(), zone_goto_idx,
387 file_group_id + ".cgns" /* linkfile */, baseZone_name_[ind_base],
388 baseZone_name_[ind_base], connectname_[ind_base],
389 "Ecrire_CGNS::cgns_write_final_link_file_for_single_file_comm_group");
390
391 if(has_field)
392 cgns_helper_.cgns_write_solution_classic_links(file_group_id, itr.getString(), itr.getString(), LOC, time_post_,
393 "Ecrire_CGNS::cgns_write_final_link_file_comm_group");
394 }
395
396 zone_goto_idx++;
397 }
398
399 /* Finally, write the iters ;) */
400 if (is_deformable_)
401 cgns_helper_.cgns_write_iters_deformable<TYPE_ECRITURE_CGNS::SEQ>(true, has_field, static_cast<int>(zoneId_tmp.size()) /* nb_zones_to_write */,
402 fileId_link, baseId_tmp[index_glob], ind_base,
403 zoneId_tmp, LOC, solname_som_, solname_elem_,
404 solname_faces_, grid_name_, time_post_);
405 else
406 cgns_helper_.cgns_write_iters<TYPE_ECRITURE_CGNS::SEQ>(has_field, static_cast<int>(zoneId_tmp.size()) /* nb_zones_to_write */,
407 fileId_link, baseId_tmp[index_glob], ind_base,
408 zoneId_tmp, LOC, solname_som_, solname_elem_,
409 solname_faces_, time_post_);
410 }
411 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::PAR>(fn, fileId_link, true);
412#endif
413}
414
415void Ecrire_CGNS::cgns_write_final_link_file_comm_group()
416{
417#ifdef MPI_
418 if (vec_proc_maitre_local_comm_.empty())
419 gather_local_sizeId_for_comm_group();
420
421 /* Fichier link : Only master proc writes the link file ! */
422 if (!Process::me())
423 {
424 std::string fn = baseFile_name_ + ".cgns";
425 unlink(fn.c_str());
426 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::SEQ>(fn, fileId_, true);
427
428 const int nb_grps = static_cast<int>(unique_vec_proc_maitre_local_comm_.size());
429 std::vector<int> zoneId_tmp;//(nb_grps, -123);
430
431 for (auto &itr : doms_written_)
432 {
433 bool has_field = false;
434 std::string LOC = "rien";
435 TRUST_2_CGNS::init_has_field_and_loc_iters(itr, fld_loc_map_, has_field, LOC);
436
437 int index_glob = -123, ind_base = -123;
438 TRUST_2_CGNS::init_glob_base_domain_idx(doms_written_, itr, has_field, LOC, index_glob, ind_base);
439
440 if (cg_base_write(fileId_, itr.getChar(), cellDim_[ind_base], Objet_U::dimension, &baseId_[index_glob]) != CG_OK)
441 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_comm_group : cg_base_write !" << finl, TRUST_CGNS_ERROR();
442
443 int zone_goto_idx = 1;
444 zoneId_tmp.clear();
445
446 /* Loop on groups that have something to link to ;) */
447 for (int gid = 0; gid < nb_grps; gid++)
448 {
449 int proc_grp = unique_vec_proc_maitre_local_comm_[gid];
450 std::string zone_name = Nom("Zone").nom_me(proc_grp).getString();
451
452 std::string file_group_id = Nom(baseFile_name_).nom_me(proc_grp).getString();
453 TRUST_2_CGNS::remove_slash_linkfile(file_group_id);
454
455 const cgsize_t isize[3] = { sizeId_som_local_comm_[ind_base][gid], sizeId_elem_local_comm_[ind_base][gid], 0 };
456
457 if ((isize[0] == 0 && isize[1] == 0)) continue;
458
459 zoneId_tmp.push_back(-123);
460
461 if (is_deformable_)
462 {
463 cgns_helper_.cgns_write_zone_and_deformable_links(true /* write zone */, has_field, fileId_, baseId_[index_glob],
464 zone_name, isize, zoneId_tmp.back(), zone_goto_idx,
465 file_group_id, baseZone_name_[ind_base], baseZone_name_[ind_base],
466 connectname_[ind_base], itr, LOC, time_post_,
467 "Ecrire_CGNS::cgns_write_final_link_file_comm_group");
468 }
469 else
470 {
471 cgns_helper_.cgns_write_zone_and_classic_links(true /* write_zone */, fileId_, baseId_[index_glob], zone_name,
472 isize, zoneId_tmp.back(), zone_goto_idx,
473 file_group_id + ".grid.cgns" /* linkfile */, baseZone_name_[ind_base],
474 baseZone_name_[ind_base], connectname_[ind_base],
475 "Ecrire_CGNS::cgns_write_final_link_file_comm_group");
476
477 if(has_field)
478 cgns_helper_.cgns_write_solution_classic_links(file_group_id, itr.getString(), itr.getString(), LOC, time_post_,
479 "Ecrire_CGNS::cgns_write_final_link_file_comm_group");
480 }
481
482 zone_goto_idx++;
483 }
484
485 /* Finally, write the iters ;) */
486 if (is_deformable_)
487 cgns_helper_.cgns_write_iters_deformable<TYPE_ECRITURE_CGNS::SEQ>(true, has_field, static_cast<int>(zoneId_tmp.size()) /* nb_zones_to_write */,
488 fileId_, baseId_[index_glob], ind_base,
489 zoneId_tmp, LOC, solname_som_, solname_elem_,
490 solname_faces_, grid_name_, time_post_);
491 else
492 cgns_helper_.cgns_write_iters<TYPE_ECRITURE_CGNS::SEQ>(has_field, static_cast<int>(zoneId_tmp.size()) /* nb_zones_to_write */,
493 fileId_, baseId_[index_glob], ind_base,
494 zoneId_tmp, LOC, solname_som_, solname_elem_,
495 solname_faces_, time_post_);
496 }
497 cgns_helper_.cgns_close_file<TYPE_RUN_CGNS::SEQ>(fn, fileId_, true);
498 }
499#endif
500}
501
502void Ecrire_CGNS::cgns_write_final_link_file()
503{
504 if (is_linked_files_comm_group_mode())
505 {
506 cgns_write_final_link_file_comm_group();
507 return;
508 }
509
510 /* Fichier link : Only master proc writes the link file ! */
511 if (!Process::me())
512 {
513 std::string fn = baseFile_name_ + ".cgns"; // file name
514 unlink(fn.c_str());
515 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::SEQ>(fn, fileId_, true);
516
517 std::string base_link_file = baseFile_name_;
518 TRUST_2_CGNS::remove_slash_linkfile(base_link_file);
519
520 for (auto &itr : doms_written_)
521 {
522 bool has_field = false;
523 std::string LOC = "rien";
524 TRUST_2_CGNS::init_has_field_and_loc_iters(itr, fld_loc_map_, has_field, LOC);
525
526 int index_glob = -123, ind_base = -123;
527 TRUST_2_CGNS::init_glob_base_domain_idx(doms_written_, itr, has_field, LOC, index_glob, ind_base);
528
529 if (cg_base_write(fileId_, itr.getChar(), cellDim_[ind_base], Objet_U::dimension, &baseId_[index_glob]) != CG_OK)
530 Cerr << "Error Ecrire_CGNS::cgns_open_solution_link_file : cg_base_write !" << finl, TRUST_CGNS_ERROR();
531
532 const cgsize_t isize[3] = { sizeId_[ind_base][0] , sizeId_[ind_base][1] , 0 };
533
534 if (is_deformable_)
535 {
536 cgns_helper_.cgns_write_zone_and_deformable_links(true /* write zone */, has_field, fileId_, baseId_[index_glob],
537 itr.getString(), isize, zoneId_[index_glob], 1,
538 base_link_file, baseZone_name_[ind_base], baseZone_name_[ind_base],
539 connectname_[ind_base], itr, LOC, time_post_,
540 "Ecrire_CGNS::cgns_open_solution_link_file");
541
542 cgns_helper_.cgns_write_iters_deformable<TYPE_ECRITURE_CGNS::SEQ>(true /* deformable */, has_field, 1 /* 1 zone per base */, fileId_,
543 baseId_[index_glob], index_glob /* 1st Zone */,
544 zoneId_, LOC, solname_som_, solname_elem_,
545 solname_faces_, grid_name_, time_post_);
546 }
547 else
548 {
549 cgns_helper_.cgns_write_zone_and_classic_links(true /* write_zone */, fileId_, baseId_[index_glob],
550 itr.getString(), isize, zoneId_[index_glob], 1,
551 base_link_file + ".grid.cgns" /* linkfile */, baseZone_name_[ind_base],
552 baseZone_name_[ind_base], connectname_[ind_base],
553 "Ecrire_CGNS::cgns_write_final_link_file");
554
555 if(has_field)
556 cgns_helper_.cgns_write_solution_classic_links(base_link_file, itr.getString(), itr.getString(), LOC, time_post_,
557 "Ecrire_CGNS::cgns_write_final_link_file");
558
559 cgns_helper_.cgns_write_iters<TYPE_ECRITURE_CGNS::SEQ>(has_field, 1, fileId_, baseId_[index_glob], index_glob /* 1st Zone */,
560 zoneId_, LOC, solname_som_, solname_elem_, solname_faces_, time_post_);
561
562 }
563 }
564
565 cgns_close_grid_or_solution_link_file(-123. /* inutile*/, TYPE_LINK_CGNS::FINAL_LINK, true); // on ferme
566 }
567}
568
569void Ecrire_CGNS::link_multi_loc_support_pb_deformable()
570{
571 if (is_lagrangian_)
572 {
573 link_multi_loc_support_lagrangian();
574 return;
575 }
576
577 // loop and write linked supports !
579 {
580 const bool enter_group_comm = is_linked_files_comm_group_mode();
581
582 for (auto &itr : fld_loc_map_)
583 {
584 const std::string& LOC = itr.first;
585 const Nom& nom_dom = itr.second;
586
587 int index_glob = -123, ind_base = -123;
588 TRUST_2_CGNS::init_glob_base_domain_idx(doms_written_, nom_dom, true /* has_field */, LOC, index_glob, ind_base);
589
590 if (cg_base_write(fileId_, nom_dom.getChar(), cellDim_[ind_base], Objet_U::dimension, &baseId_[index_glob]) != CG_OK)
591 Cerr << "Error Ecrire_CGNS::link_multi_loc_support_pb_deformable : cg_base_write !" << finl, TRUST_CGNS_ERROR();
592
593 const cgsize_t isize[3] = { sizeId_[ind_base][0], sizeId_[ind_base][1], 0 };
594
595 // XXX we use the helper but we dont write connectivity because it is a bit special : we link grid coords to same file while connectivity to 1st sol file ...
596 cgns_helper_.cgns_write_zone_and_classic_links(true /* write_zone */, fileId_, baseId_[index_glob], nom_dom.getString(), isize, zoneId_[index_glob], 1,
597 "" /* this file */, baseZone_name_[ind_base], baseZone_name_[ind_base], connectname_[ind_base],
598 "Ecrire_CGNS::link_multi_loc_support_pb_deformable", false /* DONT WRITE CONN */);
599
600 // Write conn : linked to 1st solution file since deformable ...
601 std::string linkfile;
602 if (!first_time_post_)
603 linkfile = (enter_group_comm ? Nom(baseFile_name_).nom_me(proc_maitre_local_comm_).getString() : baseFile_name_) +
604 ".solution." + cgns_helper_.convert_double_to_string(time_post_[0]) + ".cgns";
605
606 TRUST_2_CGNS::remove_slash_linkfile(linkfile);
607
608 cgns_helper_.cgns_write_connectivity_deformable_links(fileId_, baseId_[index_glob], zoneId_[index_glob], linkfile, baseZone_name_[ind_base], baseZone_name_[ind_base],
609 connectname_[ind_base], "Ecrire_CGNS::link_multi_loc_support_pb_deformable");
610 }
611 }
612 else
613 {
614 if (first_time_post_) return; /* Mais ouiiiiii car fait dans cgns_fill_field_loc_map !! */
615
616 for (auto &itr : fld_loc_map_)
617 {
618 const std::string& LOC = itr.first;
619 const Nom& nom_dom = itr.second;
620
621 int index_glob = -123, ind_base = -123;
622 TRUST_2_CGNS::init_glob_base_domain_idx(doms_written_, nom_dom, true /* has_field */, LOC, index_glob, ind_base);
623
624 std::string linkpath = "/" + baseZone_name_[ind_base] + "/" + baseZone_name_[ind_base] + "/" + grid_name_loc_ + "/";
625
626 if (cg_goto(fileId_, baseId_[index_glob], "Zone_t", 1, "end") != CG_OK)
627 Cerr << "Error Ecrire_CGNS::link_multi_loc_support_pb_deformable : cg_goto !" << finl, TRUST_CGNS_ERROR();
628
629 if (cg_link_write(grid_name_loc_.c_str(), "" /* this file */, linkpath.c_str()) != CG_OK)
630 Cerr << "Error Ecrire_CGNS::link_multi_loc_support_pb_deformable : cg_link_write !" << finl, TRUST_CGNS_ERROR();
631 }
632 }
633
634 multi_loc_deformable_support_linked_ = true; // of course !
635}
636
637// Specifique FT !!
638void Ecrire_CGNS::link_multi_loc_support_lagrangian()
639{
640 for (auto &itr : fld_loc_map_)
641 {
642 const std::string& LOC = itr.first;
643 const Nom& nom_dom = itr.second;
644
645 int index_glob = -123, ind_base = -123;
646 TRUST_2_CGNS::init_glob_base_domain_idx(doms_written_, nom_dom, true /* has_field */, LOC, index_glob, ind_base);
647 assert (ind_base == 0);
648
649 if (cg_base_write(fileId_, nom_dom.getChar(), cellDim_[ind_base], Objet_U::dimension, &baseId_[index_glob]) != CG_OK)
650 Cerr << "Error Ecrire_CGNS::link_multi_loc_support_lagrangian : cg_base_write !" << finl, TRUST_CGNS_ERROR();
651
652 const int nb_current_post = static_cast<int> (time_post_.size());
653 const cgsize_t isize[3] = { sizeId_[nb_current_post - 1][0], sizeId_[nb_current_post - 1][1], 0 };
654
655 cgns_helper_.cgns_write_zone_and_classic_links(true /* write_zone */, fileId_, baseId_[index_glob], nom_dom.getString(), isize, zoneId_[index_glob], 1,
656 "" /* this file */, baseZone_name_[ind_base], baseZone_name_[ind_base], connectname_[ind_base],
657 "Ecrire_CGNS::link_multi_loc_support_lagrangian");
658 }
659 multi_loc_deformable_support_linked_ = true; // of course !
660}
661
662void Ecrire_CGNS::cgns_write_final_link_file_lagrangian()
663{
664 if (Process::me()) return; // seul le proc 0 ecrit le fichier link
665
666 const int nsteps = static_cast<int>(time_post_.size());
667 const cgsize_t nuse = static_cast<cgsize_t>(nsteps);
668
669 if (nsteps == 0) return;
670
671 std::string fn = baseFile_name_ + ".cgns"; // file name
672 unlink(fn.c_str());
673 cgns_helper_.cgns_open_file<TYPE_RUN_CGNS::SEQ>(fn, fileId_, true);
674
675 for (auto &itr : fld_loc_map_)
676 {
677 const std::string& LOC = itr.first;
678 const Nom& nom_dom = itr.second;
679
680 int index_glob = -123, ind_base = -123;
681 TRUST_2_CGNS::init_glob_base_domain_idx(doms_written_, nom_dom, true /* has_field */, LOC, index_glob, ind_base);
682
683 if (cg_base_write(fileId_, nom_dom.getChar(), cellDim_[ind_base], Objet_U::dimension, &baseId_[index_glob]) != CG_OK)
684 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_base_write !" << finl, TRUST_CGNS_ERROR();
685
686 if (cg_biter_write(fileId_, baseId_[index_glob], "TimeIterValues", nsteps) != CG_OK)
687 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_biter_write !" << finl, TRUST_CGNS_ERROR();
688
689 if (cg_goto(fileId_, baseId_[index_glob], "BaseIterativeData_t", 1, "end") != CG_OK)
690 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_goto BaseIterativeData_t !" << finl, TRUST_CGNS_ERROR();
691
692 // TimeValues
693 if (cg_array_write("TimeValues", CGNS_DOUBLE_TYPE, 1, &nuse, time_post_.data()) != CG_OK)
694 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_array_write TimeValues !" << finl, TRUST_CGNS_ERROR();
695
696 if (cg_simulation_type_write(fileId_, baseId_[index_glob], CGNS_ENUMV(TimeAccurate)) != CG_OK)
697 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_simulation_type_write !" << finl, TRUST_CGNS_ERROR();
698
699 // NumberOfZones : 1 zone active par step
700 std::vector<int> number_of_zones(nsteps, 1);
701 if (cg_array_write("NumberOfZones", CGNS_ENUMV(Integer), 1, &nuse, number_of_zones.data()) != CG_OK)
702 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_array_write NumberOfZones !" << finl, TRUST_CGNS_ERROR();
703
704 cgsize_t zpdims[3] = { CGNS_STR_SIZE, 1, nuse };
705 std::string zone_ptrs;
706 zone_ptrs.reserve(static_cast<size_t>(CGNS_STR_SIZE) * nsteps);
707
708 bool first_zone = true;
709 for (int i = 0; i < nsteps; i++)
710 {
711 std::string zname = nom_dom.getString();
712 if (!first_zone)
713 {
714 zname += "_itr_";
715 zname += std::to_string(i);
716 }
717 first_zone = false;
718
719 zname.resize(CGNS_STR_SIZE, ' ');
720 zone_ptrs += zname;
721 }
722
723 if (cg_array_write("ZonePointers", CGNS_ENUMV(Character), 3, zpdims, zone_ptrs.c_str()) != CG_OK)
724 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_array_write ZonePointers !" << finl, TRUST_CGNS_ERROR();
725
726 for (int i = 0; i < nsteps; i++)
727 {
728 cgsize_t isize[3] = { sizeId_[i][0] , sizeId_[i][1] , 0 };
729 std::string zn = nom_dom.getString();
730
731 if (i > 0)
732 {
733 zn += "_itr_";
734 zn += std::to_string(i);
735 }
736
737 if (cg_zone_write(fileId_, baseId_[index_glob], zn.c_str(), isize, CGNS_ENUMV(Unstructured), &zoneId_[index_glob]) != CG_OK)
738 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_zone_write !" << finl, TRUST_CGNS_ERROR();
739
740 std::string linkfile = baseFile_name_ + ".solution." + cgns_helper_.convert_double_to_string(time_post_[i]) + ".cgns";
741 TRUST_2_CGNS::remove_slash_linkfile(linkfile);
742 std::string linkpath = "/" + baseZone_name_[ind_base] + "/" + baseZone_name_[ind_base] + "/GridCoordinates/";
743
744 if (cg_goto(fileId_, baseId_[index_glob], "Zone_t", zoneId_[index_glob], "end") != CG_OK)
745 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_goto Zone_t !" << finl, TRUST_CGNS_ERROR();
746
747 if (cg_link_write("GridCoordinates", linkfile.c_str(), linkpath.c_str()) != CG_OK)
748 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_link_write GridCoordinates !" << finl, TRUST_CGNS_ERROR();
749
750 for (auto& itr_conn : connectname_[ind_base])
751 {
752 linkpath = "/" + baseZone_name_[ind_base] + "/" + baseZone_name_[ind_base] + "/" + itr_conn + "/";
753 if (cg_link_write(itr_conn.c_str(), linkfile.c_str(), linkpath.c_str()) != CG_OK)
754 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_link_write connectivity !" << finl, TRUST_CGNS_ERROR();
755 }
756
757 std::string solname = "FlowSolution_itr_" + std::to_string(i);
758 linkpath = "/" + nom_dom.getString() + "/" + nom_dom.getString() + "/" + solname + "/";
759 if (cg_link_write(solname.c_str(), linkfile.c_str(), linkpath.c_str()) != CG_OK)
760 Cerr << "Error Ecrire_CGNS::cgns_write_final_link_file_lagrangian : cg_link_write FlowSolution !" << finl, TRUST_CGNS_ERROR();
761 }
762 }
763
764 cgns_close_grid_or_solution_link_file(-123., TYPE_LINK_CGNS::FINAL_LINK, true);
765}
766
767#endif /* HAS_CGNS */
int rank() const
Renvoie le rang du processeur local dans le groupe *this.
Definition Comm_Group.h:182
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
static int dimension
Definition Objet_U.h:99
static bool PARALLEL_OVER_ZONE
Definition Option_CGNS.h:48
static bool USE_LINKS
Definition Option_CGNS.h:52
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 const Comm_Group & groupe_TRUST()
Renvoie une reference au groupe de tous les processeurs TRUST.
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