Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DumpWEnsight7.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* DumpWEnsight7.cc (C) 2000-2026 */
9/* */
10/* Exportations des fichiers au format Ensight7 gold. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/StringBuilder.h"
15#include "arcane/utils/Enumerator.h"
16#include "arcane/utils/Iterator.h"
17#include "arcane/utils/List.h"
18#include "arcane/utils/ScopedPtr.h"
19#include "arcane/utils/PlatformUtils.h"
20#include "arcane/utils/Iostream.h"
21#include "arcane/utils/Deleter.h"
22#include "arcane/utils/ITraceMng.h"
23#include "arcane/utils/OStringStream.h"
24#include "arcane/utils/NotImplementedException.h"
25#include "arcane/utils/CStringUtils.h"
26#include "arcane/utils/Convert.h"
27
28#include "arcane/core/IDataWriter.h"
29#include "arcane/core/Item.h"
31#include "arcane/core/IVariable.h"
32#include "arcane/core/ISubDomain.h"
33#include "arcane/core/IMesh.h"
34#include "arcane/core/IMeshSubMeshTransition.h"
35#include "arcane/core/StdNum.h"
36#include "arcane/core/ItemGroup.h"
37#include "arcane/core/IParallelMng.h"
38#include "arcane/core/Directory.h"
39#include "arcane/core/MeshVariable.h"
40#include "arcane/core/PostProcessorWriterBase.h"
41#include "arcane/core/Service.h"
42#include "arcane/core/SimpleProperty.h"
43#include "arcane/core/IItemFamily.h"
44#include "arcane/core/VariableCollection.h"
45#include "arcane/core/SharedVariable.h"
46
47#include "arcane/core/FactoryService.h"
49
50#include "arcane/std/Ensight7PostProcessor_axl.h"
51#include "arcane/std/DumpW.h"
52
53#include <string.h>
54#include <memory>
55#include <unordered_map>
56
57// TODO: Ajouter test avec des variables partielles
58
59/*---------------------------------------------------------------------------*/
60/*---------------------------------------------------------------------------*/
61
62namespace Arcane
63{
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
98class DumpWEnsight7
99: public DumpW
100, public TraceAccessor
101{
102 public:
103
104 static const int int_width = 10;
105 static const int g_line_length = 80;
106
107 public:
108
112 struct EnsightPart
113 {
114 public:
115
116 EnsightPart()
117 : m_type(-1)
118 , m_nb_node(0)
119 {}
120 EnsightPart(int type, Integer nb_node, const String& name)
121 : m_type(type)
122 , m_nb_node(nb_node)
123 , m_name(name)
124 {}
125 EnsightPart(const EnsightPart& part)
126 : m_type(part.m_type)
127 , m_nb_node(part.m_nb_node)
128 , m_name(part.m_name)
129 , m_items(part.m_items)
130 , m_reindex(part.m_reindex)
131 {
132 ;
133 }
134
135 public:
136
137 inline int type() const { return m_type; }
138 inline Integer nbNode() const { return m_nb_node; }
139 inline const String& name() const { return m_name; }
140 inline Array<Item>& items() { return m_items; }
141 inline ConstArrayView<Item> items() const { return m_items; }
142 inline bool hasReindex() const { return !m_reindex.empty(); }
143 inline void setReindex(Integer* reindex)
144 {
145 m_reindex.resize(m_nb_node);
146 for (Integer i = 0; i < m_nb_node; ++i)
147 m_reindex[i] = reindex[i];
148 }
149 inline ConstArrayView<Integer> reindex() const { return m_reindex; }
150
151 private:
152
153 int m_type;
157 UniqueArray<Integer> m_reindex;
158 };
159
163 struct GroupPartInfo
164 {
165 public:
166
168 Integer nbType() const { return m_parts.size(); }
169
170 public:
171
173 : m_group(0)
174 , m_part_id(0)
175 {}
176 GroupPartInfo(ItemGroup grp, Integer id, bool use_degenerated_hexa)
177 : m_group(grp)
178 , m_part_id(id)
179 {
180 m_general_item_types = std::make_unique<VariableItemInt32>(VariableBuildInfo{ m_group.mesh(), "GeneralItemTypesGroup" + m_group.name(), m_group.itemFamily()->name() }, m_group.itemKind());
181 _init(use_degenerated_hexa);
182 }
183 Integer totalNbElement() const
184 {
185 Integer n = 0;
186 for (Integer i = 0; i < nbType(); ++i)
187 n += m_parts[i].items().size();
188 return n;
189 }
190 const EnsightPart& typeInfo(Integer i) const { return m_parts[i]; }
191 EnsightPart& typeInfo(Integer i) { return m_parts[i]; }
192 ItemGroup group() const { return m_group; }
193 Integer partId() const { return m_part_id; }
194 Int32 generalItemTypeId(const Item& item) const
195 {
196 ARCANE_ASSERT(m_general_item_types, ("Cannot question an empty GroupPartInfo"));
197 return (*(m_general_item_types))[item];
198 }
199 EnsightPart* getTypeInfo(int type)
200 {
201 auto ensight_part_element = m_parts_map.find(type);
202 if (ensight_part_element != m_parts_map.end())
203 return ensight_part_element->second;
204 else
205 return nullptr;
206 }
207
208 private:
209
213 bool m_is_polygonal_type_registration_done = false;
214 bool m_is_polyhedral_type_registration_done = false;
216 std::unique_ptr<VariableItemInt32> m_general_item_types = nullptr;
217 using TypeId = int;
218 std::unordered_map<TypeId, EnsightPart*> m_parts_map; // utilisé pour gérer un grand nombre de types supplémentaires
219
220 private:
221
222 void _initPartMap()
223 {
224 for (auto& ensight_part : m_parts) {
225 m_parts_map[ensight_part.type()] = &ensight_part;
226 }
227 }
228
229 void _init(bool use_degenerated_hexa)
230 {
231 ItemTypeMng* item_type_mng = m_group.mesh()->itemTypeMng();
232
233 // NOTE: il est important que les éléments de type 'nfaced'
234 // et 'nsided' soient contigues car Ensight doit sauver
235 // ensemble leur valeurs
236 m_parts.reserve(ItemTypeMng::nbBasicItemType());
237 m_parts.add(EnsightPart(IT_Line2, 2, "bar2")); // Bar
238 m_parts.add(EnsightPart(IT_Triangle3, 3, "tria3")); // Triangle
239 m_parts.add(EnsightPart(IT_Quad4, 4, "quad4")); // Quandrangle
240 m_parts.add(EnsightPart(IT_Pentagon5, 5, "nsided")); // Pentagone
241 m_parts.add(EnsightPart(IT_Hexagon6, 6, "nsided")); // Hexagone
242 m_parts.add(EnsightPart(IT_Heptagon7, 7, "nsided")); // Heptagone
243 m_parts.add(EnsightPart(IT_Octogon8, 8, "nsided")); // Octogone
244 // Recherche des autres types 'polygone'
245 for (Integer i_type = ItemTypeMng::nbBuiltInItemType(); i_type < ItemTypeMng::nbBasicItemType(); ++i_type) {
246 ItemTypeInfo* type_info = item_type_mng->typeFromId(i_type);
247 if (type_info->nbLocalNode() == type_info->nbLocalEdge()) { // Polygone trouvé
248 m_parts.add(EnsightPart(i_type, type_info->nbLocalNode(), "nsided"));
249 }
250 }
251 // Ajout des polygones gérés dans le maillage polyédrique général : aucun type défini
252 Int32 type_id = ItemTypeMng::nbBasicItemType();
253 if (item_type_mng->hasGeneralCells(m_group.mesh())) {
254 if (!m_is_polygonal_type_registration_done) {
255 ENUMERATE_ITEM (iitem, m_group) {
256 ItemWithNodes item = iitem->toItemWithNodes();
257 if (item.nbNode() == item.itemBase().nbEdge()) { // polygone trouvé
258 (*(m_general_item_types))[item] = type_id;
259 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nsided"));
260 }
261 }
262 m_is_polygonal_type_registration_done = true;
263 }
264 }
265 m_parts.add(EnsightPart(IT_Tetraedron4, 4, "tetra4")); // Tetra
266 m_parts.add(EnsightPart(IT_Pyramid5, 5, "pyramid5")); // Pyramide
267 m_parts.add(EnsightPart(IT_Pentaedron6, 6, "penta6")); // Penta
268 m_parts.add(EnsightPart(IT_Hexaedron8, 8, "hexa8")); // Hexa
269 if (use_degenerated_hexa) {
270 m_parts.add(EnsightPart(IT_HemiHexa7, 8, "hexa8")); // HemiHexa7
271 {
272 Integer reindex[8] = { 1, 6, 5, 0, 2, 3, 4, 0 };
273 m_parts[m_parts.size() - 1].setReindex(reindex);
274 }
275 m_parts.add(EnsightPart(IT_HemiHexa6, 8, "hexa8")); // HemiHexa6
276 {
277 Integer reindex[8] = { 0, 1, 3, 5, 0, 2, 3, 4 };
278 m_parts[m_parts.size() - 1].setReindex(reindex);
279 }
280 m_parts.add(EnsightPart(IT_HemiHexa5, 8, "hexa8")); // HemiHexa5
281 {
282 Integer reindex[8] = { 0, 1, 3, 4, 0, 2, 3, 4 };
283 m_parts[m_parts.size() - 1].setReindex(reindex);
284 }
285 m_parts.add(EnsightPart(IT_AntiWedgeLeft6, 8, "hexa8")); // AntiWedgeLeft6
286 {
287 Integer reindex[8] = { 2, 0, 1, 2, 5, 3, 4, 4 };
288 m_parts[m_parts.size() - 1].setReindex(reindex);
289 }
290 m_parts.add(EnsightPart(IT_AntiWedgeRight6, 8, "hexa8")); // AntiWedgeRight6
291 {
292 Integer reindex[8] = { 2, 0, 1, 1, 5, 3, 4, 5 };
293 m_parts[m_parts.size() - 1].setReindex(reindex);
294 }
295 m_parts.add(EnsightPart(IT_DiTetra5, 8, "hexa8")); // DiTetra5
296 {
297 Integer reindex[8] = { 4, 4, 2, 3, 0, 1, 1, 3 };
298 m_parts[m_parts.size() - 1].setReindex(reindex);
299 }
300 }
301 else {
302 m_parts.add(EnsightPart(IT_HemiHexa7, 7, "nfaced")); // HemiHexa7
303 m_parts.add(EnsightPart(IT_HemiHexa6, 6, "nfaced")); // HemiHexa6
304 m_parts.add(EnsightPart(IT_HemiHexa5, 5, "nfaced")); // HemiHexa5
305 m_parts.add(EnsightPart(IT_AntiWedgeLeft6, 6, "nfaced")); // AntiWedgeLeft6
306 m_parts.add(EnsightPart(IT_AntiWedgeRight6, 6, "nfaced")); // AntiWedgeRight6
307 m_parts.add(EnsightPart(IT_DiTetra5, 5, "nfaced")); // DiTetra5
308 }
309 m_parts.add(EnsightPart(IT_Heptaedron10, 10, "nfaced")); // Wedge7
310 m_parts.add(EnsightPart(IT_Octaedron12, 12, "nfaced")); // Wedge8
311 m_parts.add(EnsightPart(IT_Enneedron14, 14, "nfaced")); // Wedge9
312 m_parts.add(EnsightPart(IT_Decaedron16, 16, "nfaced")); // Wedge10
313 // Recherche des autres types 'polyedre'
314 for (Integer i_type = ItemTypeMng::nbBuiltInItemType(); i_type < ItemTypeMng::nbBasicItemType(); ++i_type) {
315 ItemTypeInfo* type_info = item_type_mng->typeFromId(i_type);
316 if (type_info->nbLocalNode() != type_info->nbLocalEdge()) { // Polyèdre trouvé
317 m_parts.add(EnsightPart(i_type, type_info->nbLocalNode(), "nfaced"));
318 }
319 }
320 // Ajout des polyèdres gérés dans le maillage polyédrique général : aucun type défini
321 if (item_type_mng->hasGeneralCells(m_group.mesh())) {
322 if (!m_is_polyhedral_type_registration_done) {
323 ENUMERATE_ITEM (iitem, m_group) {
324 ItemWithNodes item = iitem->toItemWithNodes();
325 if (item.nbNode() == 1)
326 (*(m_general_item_types))[item] = IT_Vertex;
327 else if (item.nbNode() == 2)
328 (*(m_general_item_types))[item] = IT_Line2;
329 else if (item.nbNode() != item.itemBase().nbEdge()) { // polyèdre trouvé
330 (*(m_general_item_types))[item] = type_id;
331 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nfaced"));
332 }
333 }
334 m_is_polyhedral_type_registration_done = true;
335 }
336 }
337 // Si des types supplémentaires sont utilisés, initialiser une carte EnsightPart pour optimiser le remplissage de GroupPartInfo
339 _initPartMap();
340 }
341 }
342 };
343
344 public:
345
346 //void writeFileString(ostream& o,ConstCString str);
347 void writeFileString(std::ostream& o, const String& str);
348 void writeFileInt(std::ostream& o, int value);
349 void writeFileDouble(std::ostream& o, double value);
350 Integer writeDoubleSize() const;
351 Integer writeIntSize() const;
352 void writeFileArray(std::ostream& o, IntegerConstArrayView value);
353 bool isBinary() const { return m_is_binary; }
354
355 public:
356
369 class WriteBase
370 {
371 public:
372
373 explicit WriteBase(DumpWEnsight7& dw)
374 : m_dw(dw)
375 {}
376 WriteBase(DumpWEnsight7& dw, GroupIndexTable* idx)
377 : m_dw(dw)
378 , m_idx(idx)
379 {}
380 WriteBase(const WriteBase& wb)
381 : m_dw(wb.m_dw)
382 , m_idx(wb.m_idx)
383 {}
384 virtual ~WriteBase() {}
385
386 public:
387
388 virtual WriteBase* clone() = 0;
389 virtual void begin() { init(); }
390 virtual void end() {}
391 virtual void write(ConstArrayView<Item> items) = 0;
392
393 virtual void init()
394 {
395 m_ofile.precision(5);
396 m_ofile.flags(std::ios::scientific);
397 }
398 virtual void putValue(std::ostream& ofile)
399 {
400 ofile << m_ofile.str();
401 }
402 std::ostream& stream() { return m_ofile; }
403
404 protected:
405
406 DumpWEnsight7& m_dw;
407 std::ostringstream m_ofile;
408 GroupIndexTable* m_idx = nullptr;
409 };
410
414 template <typename FromType>
415 class WriteDouble
416 : public WriteBase
417 {
418 public:
419
420 WriteDouble(DumpWEnsight7& dw, ConstArrayView<FromType> ptr, GroupIndexTable* idx = nullptr)
421 : WriteBase(dw, idx)
422 , m_ptr(ptr)
423 {}
424 WriteDouble(const WriteDouble& wd)
425 : WriteBase(wd)
426 , m_ptr(wd.m_ptr)
427 {}
428
429 WriteBase* clone() override { return new WriteDouble(*this); }
430
431 public:
432
434
435 public:
436
437 inline void write(Integer index)
438 {
439 if (m_idx) {
440 int reindex = (*m_idx)[index];
441 if (reindex < 0)
442 ARCANE_FATAL("Invalid index");
443 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[reindex])));
444 }
445 else
446 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[index])));
447 }
448
449 void write(ConstArrayView<Item> items) override
450 {
451 for (Item e : items) {
452 write(e.localId());
453 }
454 }
455 };
456
460 template <typename FromType>
461 class WriteArrayDouble
462 : public WriteBase
463 {
464 public:
465
466 WriteArrayDouble(DumpWEnsight7& dw, ConstArray2View<FromType> ptr, const Integer idim2,
467 GroupIndexTable* idx = nullptr)
468 : WriteBase(dw, idx)
469 , m_ptr(ptr)
470 , m_idim2(idim2)
471 {}
472 WriteArrayDouble(const WriteArrayDouble& wd)
473 : WriteBase(wd)
474 , m_ptr(wd.m_ptr)
475 , m_idim2(wd.m_idim2)
476 {}
477
478 WriteBase* clone() override { return new WriteArrayDouble(*this); }
479
480 public:
481
483 const Integer m_idim2;
484
485 public:
486
487 void write(Integer index)
488 {
489 if (m_idx) {
490 int reindex = (*m_idx)[index];
491 if (reindex < 0)
492 ARCANE_FATAL("Invalid index");
493 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[reindex][m_idim2])));
494 }
495 else
496 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[index][m_idim2])));
497 }
498
499 void write(ConstArrayView<Item> items) override
500 {
501 for (Item e : items) {
502 write(e.localId());
503 }
504 }
505 };
506
510
514 class WriteReal3
515 : public WriteBase
516 {
517 public:
518
519 WriteReal3(DumpWEnsight7& dw, ConstArrayView<Real3> ptr, GroupIndexTable* idx = nullptr)
520 : WriteBase(dw, idx)
521 , m_ptr(ptr)
522 {}
523 WriteReal3(const WriteReal3& wd)
524 : WriteBase(wd)
525 , m_ptr(wd.m_ptr)
526 {}
527
528 WriteBase* clone() override { return new WriteReal3(*this); }
529
530 public:
531
533
534 public:
535
536 void begin() override
537 {
538 _init();
539 xostr.precision(5);
540 xostr.flags(std::ios::scientific);
541 yostr.precision(5);
542 yostr.flags(std::ios::scientific);
543 zostr.precision(5);
544 zostr.flags(std::ios::scientific);
545 }
546
547 void write(Integer index)
548 {
549 if (m_idx) {
550 int reindex = (*m_idx)[index];
551 if (reindex < 0)
552 ARCANE_FATAL("Invalid index");
553 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[reindex].x));
554 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[reindex].y));
555 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[reindex].z));
556 }
557 else {
558 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[index].x));
559 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[index].y));
560 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[index].z));
561 }
562 }
563
564 void write(ConstArrayView<Item> items) override
565 {
566 for (Item i : items) {
567 write(i.localId());
568 }
569 }
570
571 void end() override
572 {
573 m_ofile << xostr.str();
574 m_ofile << yostr.str();
575 m_ofile << zostr.str();
576 }
577
578 public:
579
580 std::ostringstream xostr;
581 std::ostringstream yostr;
582 std::ostringstream zostr;
583
584 private:
585
586 void _init()
587 {
588 init();
589 }
590 };
591
595 class WriteArrayReal3
596 : public WriteBase
597 {
598 public:
599
600 WriteArrayReal3(DumpWEnsight7& dw, ConstArray2View<Real3> ptr,
601 Integer idim2, GroupIndexTable* idx = nullptr)
602 : WriteBase(dw, idx)
603 , m_ptr(ptr)
604 , m_idim2(idim2)
605 {}
606 WriteArrayReal3(const WriteArrayReal3& wd)
607 : WriteBase(wd)
608 , m_ptr(wd.m_ptr)
609 , m_idim2(wd.m_idim2)
610 {}
611
612 WriteBase* clone() override { return new WriteArrayReal3(*this); }
613
614 public:
615
617 const Integer m_idim2;
618 public:
619
620 void begin() override
621 {
622 _init();
623 xostr.precision(5);
624 xostr.flags(std::ios::scientific);
625 yostr.precision(5);
626 yostr.flags(std::ios::scientific);
627 zostr.precision(5);
628 zostr.flags(std::ios::scientific);
629 }
630
631 inline void write(Integer index)
632 {
633 if (m_idx) {
634 int reindex = (*m_idx)[index];
635 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[reindex][m_idim2].x));
636 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[reindex][m_idim2].y));
637 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[reindex][m_idim2].z));
638 }
639 else {
640 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[index][m_idim2].x));
641 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[index][m_idim2].y));
642 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[index][m_idim2].z));
643 }
644 }
645
646 void write(ConstArrayView<Item> items) override
647 {
648 for (Item i : items) {
649 write(i.localId());
650 }
651 }
652
653 void end() override
654 {
655 m_ofile << xostr.str();
656 m_ofile << yostr.str();
657 m_ofile << zostr.str();
658 }
659
660 public:
661
662 std::ostringstream xostr;
663 std::ostringstream yostr;
664 std::ostringstream zostr;
665
666 private:
667
668 void _init()
669 {
670 init();
671 }
672 };
673
674 public:
675
676 DumpWEnsight7(IMesh* m, const String& filename, RealConstArrayView times,
677 VariableCollection variables, ItemGroupCollection groups,
678 bool is_binary, bool is_parallel, Integer fileset_size,
679 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids);
680 ~DumpWEnsight7();
681
682 public:
683
685 void writeVal(IVariable& v, ConstArrayView<Real> a) override { _writeRealValT<Real>(v, a); }
686 void writeVal(IVariable&, ConstArrayView<Real2>) override {}
687 void writeVal(IVariable&, ConstArrayView<Real3>) override;
688 void writeVal(IVariable& v, ConstArrayView<Int16> a) override { _writeRealValT<Int16>(v, a); }
689 void writeVal(IVariable& v, ConstArrayView<Int32> a) override { _writeRealValT<Int32>(v, a); }
690 void writeVal(IVariable& v, ConstArrayView<Int64> a) override { _writeRealValT<Int64>(v, a); }
691 void writeVal(IVariable&, ConstArrayView<Real2x2>) override {}
692 void writeVal(IVariable&, ConstArrayView<Real3x3>) override {}
693 void writeVal(IVariable&, ConstArrayView<String>) override {}
694
695 void writeVal(IVariable&, ConstArray2View<Byte>) override {}
696 void writeVal(IVariable& v, ConstArray2View<Real> a) override { _writeRealValT<Real>(v, a); }
697 void writeVal(IVariable&, ConstArray2View<Real2>) override {}
698 void writeVal(IVariable&, ConstArray2View<Real3>) override;
699 void writeVal(IVariable& v, ConstArray2View<Int16> a) override { _writeRealValT<Int16>(v, a); }
700 void writeVal(IVariable& v, ConstArray2View<Int32> a) override { _writeRealValT<Int32>(v, a); }
701 void writeVal(IVariable& v, ConstArray2View<Int64> a) override { _writeRealValT<Int64>(v, a); }
702 void writeVal(IVariable&, ConstArray2View<Real2x2>) override {}
703 void writeVal(IVariable&, ConstArray2View<Real3x3>) override {}
704
705 void writeVal(IVariable&, ConstMultiArray2View<Byte>) override {}
706 void writeVal(IVariable& v, ConstMultiArray2View<Real> a) override { _writeRealValT<Real>(v, a); }
707 void writeVal(IVariable&, ConstMultiArray2View<Real2>) override {}
708 void writeVal(IVariable&, ConstMultiArray2View<Real3> a) override;
709 void writeVal(IVariable& v, ConstMultiArray2View<Int16> a) override { _writeRealValT<Int16>(v, a); }
710 void writeVal(IVariable& v, ConstMultiArray2View<Int32> a) override { _writeRealValT<Int32>(v, a); }
711 void writeVal(IVariable& v, ConstMultiArray2View<Int64> a) override { _writeRealValT<Int64>(v, a); }
712 void writeVal(IVariable&, ConstMultiArray2View<Real2x2>) override {}
713 void writeVal(IVariable&, ConstMultiArray2View<Real3x3>) override {}
714
715 void beginWrite() override;
716 void endWrite() override;
717 void setMetaData(const String&) override {};
718
719 bool isParallelOutput() const { return m_is_parallel_output; }
720 bool isMasterProcessor() const { return m_is_master; }
721 bool isOneFilePerTime() const { return m_fileset_size == 0; }
722 Int32 rank() const { return m_parallel_mng->commRank(); }
723 IParallelMng* parallelMng() const { return m_parallel_mng; }
724
725 public:
726 private:
727
728 typedef UniqueArray<GroupPartInfo*> GroupPartInfoList;
729
730 private:
731
736 std::ofstream m_case_file;
737 std::ostringstream m_case_file_variables;
739 VariableList m_save_variables;
741 GroupPartInfoList m_parts;
747 bool m_use_degenerated_hexa;
748 bool m_force_first_geometry;
749 bool m_save_uids;
757 Integer m_fileset_size;
758
759 private:
760 private:
761
763 static const Integer m_max_prots_digit = 6;
764
765 private:
766 private:
767
768 bool _isValidVariable(IVariable&) const;
769 void _createCaseFile();
770 void _buildFileName(const String& varname, String& filename);
771 void _buildPartDirectory();
772 void _writeWildcardFilename(std::ostream& ofile, const String& filename, char joker = '*');
773 int _fileOuttype() const;
774 void _writeFileHeader(std::ostream& o, bool write_c_binary);
775 bool _isNewBlocFile() const;
776
777 void _computeGroupParts(ItemGroupList list_group, Integer& partid);
778 void _saveGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
779 ConstArrayView<Integer> nodes_index, WriteBase& wf);
780 void _saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
781 WriteBase& from_func);
782 bool _isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind);
783
785 template <typename T>
788 template <typename T>
791 template <typename T>
793};
794
795/*---------------------------------------------------------------------------*/
796/*---------------------------------------------------------------------------*/
797
798extern "C++" DumpW*
799createEnsight7(ISubDomain* m, const String& f,
801 VariableCollection variables,
802 ItemGroupCollection groups,
803 bool is_binary, bool is_parallel_output, Integer fileset_size,
804 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
805{
806 return new DumpWEnsight7(m->defaultMesh(), f, times, variables, groups, is_binary,
807 is_parallel_output, fileset_size, use_degenerated_hexa,
808 force_first_geometry, save_uids);
809}
810
811extern "C++" DumpW*
812createEnsight7(IMesh* m, const String& f,
813 ConstArrayView<Real> times,
814 VariableCollection variables,
815 ItemGroupCollection groups,
816 bool is_binary, bool is_parallel_output, Integer fileset_size,
817 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
818{
819 return new DumpWEnsight7(m, f, times, variables, groups, is_binary,
820 is_parallel_output, fileset_size, use_degenerated_hexa,
821 force_first_geometry, save_uids);
822}
823
824/*---------------------------------------------------------------------------*/
825/*---------------------------------------------------------------------------*/
826
827DumpWEnsight7::
828DumpWEnsight7(IMesh* mesh, const String& filename, ConstArrayView<Real> times,
829 VariableCollection variables, ItemGroupCollection groups,
830 bool is_binary, bool is_parallel_output, Integer fileset_size,
831 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
832: TraceAccessor(mesh->traceMng())
833, m_mesh(mesh)
834, m_parallel_mng(mesh->parallelMng())
835, m_base_directory(filename)
836, m_times(times)
837, m_save_variables(variables.clone())
838, m_save_groups(groups.enumerator())
839, m_is_binary(is_binary)
840// , m_is_binary(false)
841, m_is_master(true)
842, m_is_parallel_output(is_parallel_output)
843, m_use_degenerated_hexa(use_degenerated_hexa)
844, m_force_first_geometry(force_first_geometry)
845, m_save_uids(save_uids)
846, m_total_nb_element(0)
847, m_total_nb_group(0)
848, m_fileset_size(fileset_size)
849{
850 //m_is_binary = true;
851 //m_fileset_size = 0;
852
853 if (m_times.empty()) {
854 m_times.resize(1);
855 m_times[0] = 0.;
856 }
857
858 //_createCaseFile();
859}
860
861/*---------------------------------------------------------------------------*/
862/*---------------------------------------------------------------------------*/
863
864DumpWEnsight7::
865~DumpWEnsight7()
866{
867 std::for_each(std::begin(m_parts), std::end(m_parts), Deleter());
868}
869
870/*---------------------------------------------------------------------------*/
871/*---------------------------------------------------------------------------*/
872
873/*---------------------------------------------------------------------------*/
874/*---------------------------------------------------------------------------*/
875
894void DumpWEnsight7::
895_computeGroupParts(ItemGroupList list_group, Integer& partid)
896{
897 for (ItemGroupList::Enumerator i(list_group); ++i;) {
898 ItemGroup grp(*i);
899 if (grp.null()) // Le groupe n'est pas du type souhaité.
900 continue;
901 if (!grp.isOwn()) // Si possible, prend le groupe d'éléments propres
902 grp = grp.own();
903 // Depuis la 7.6 de Ensight, les groupes vides sont autorisés
904 // et ils sont nécessaires lorsque le maillage évolue au cours du temps
905 //if (grp.empty()) // Le groupe est vide
906 //continue;
907 GroupPartInfo* gpi = new GroupPartInfo(grp, partid, m_use_degenerated_hexa);
908 m_parts.add(gpi);
909 ++partid;
910
911 GroupPartInfo& current_grp = *gpi;
912 // Maintenant, nous devons déterminer combien d'éléments de chaque type
913 // ensight (tria3, hexa8, ...) se trouvent dans le groupe.
914 // deux versions : si des types d'éléments supplémentaires sont ajoutés, passer à une version optimisée
915 // (une grande quantité de types peut être ajoutée, égale au nombre d'éléments)
916 if (ItemTypeMng::nbBuiltInItemType() == ItemTypeMng::nbBasicItemType()) // pas de type supplémentaire
917 {
918 debug(Trace::High) << "Utilisation de l'algorithme standard de construction de groupe de parties";
919 if (!grp.mesh()->itemTypeMng()->hasGeneralCells(grp.mesh())) { // types classiques
920 for (Integer z = 0; z < current_grp.nbType(); ++z) {
921 EnsightPart& type_info = current_grp.typeInfo(z);
922 Array<Item>& items = type_info.items();
923 Integer nb_of_type = 0;
924 Integer type_to_seek = type_info.type();
925 ENUMERATE_ITEM (i2, grp) {
926 const Item& e = *i2;
927 if (e.type() == type_to_seek)
928 ++nb_of_type;
929 }
930 items.resize(nb_of_type);
931 debug(Trace::High) << "Le groupe " << grp.name() << " contient "
932 << nb_of_type << " éléments de type " << type_info.name();
933 Integer index = 0;
934 ENUMERATE_ITEM (iz, grp) {
935 Item mi = *iz;
936 if (mi.type() == type_to_seek) {
938 items[index] = e;
939 ++index;
940 }
941 }
942 }
943 }
944 else { // éléments de maillage polyédrique
945 ENUMERATE_ITEM (i2, grp) {
946 const Item& item = *i2;
947 auto item_type = current_grp.generalItemTypeId(item);
948 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
949 if (!ensight_part)
950 continue;
951 ItemWithNodes item_wn = item.toItemWithNodes();
952 ensight_part->items().add(item_wn);
953 }
954 }
955 }
956 else // des types supplémentaires sont ajoutés (peuvent avoir autant de types que d'éléments...)
957 // Proposer une version optimisée lorsque de nombreux types existent (utilisation de fichier .format)
958 {
959 debug(Trace::High) << "Utilisation de l'algorithme de construction de groupe de parties avec types supplémentaires";
960 // travaille uniquement sur les groupes de faces et de mailles
961 auto item_kind = grp.itemKind();
962 if (item_kind == IK_Cell || item_kind == IK_Face) {
963 ENUMERATE_ITEM (item, grp) {
964 auto item_type = item->type();
965 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
966 if (!ensight_part)
967 continue;
968 ItemWithNodes item_wn = item->toItemWithNodes();
969 ensight_part->items().add(item_wn); // quelques éléments sont ajoutés
970 }
971 }
972 }
973 }
974}
975
976/*---------------------------------------------------------------------------*/
977/*---------------------------------------------------------------------------*/
999void DumpWEnsight7::
1000_saveGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
1001 ConstArrayView<Integer> nodes_index, WriteBase& wf)
1002{
1003 ItemGroup igrp = ensight_grp.group();
1004
1005 writeFileString(ofile, "part");
1006 writeFileInt(ofile, ensight_grp.partId());
1007 if (isParallelOutput()) {
1008 // Dans le cas d'une sortie parallele, prefixe le nom du groupe par le
1009 // numéro du CPU.
1010 std::ostringstream ostr;
1011 ostr << igrp.name().localstr() << "_CPU" << rank();
1012 writeFileString(ofile, ostr.str().c_str());
1013 }
1014 else
1015 writeFileString(ofile, igrp.name());
1016
1017 wf.putValue(ofile);
1018
1019 IntegerUniqueArray array_id(256);
1020
1021 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1022 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1023 ConstArrayView<Item> items = type_info.items();
1024 Integer nb_sub_part = items.size();
1025 if (nb_sub_part == 0)
1026 continue;
1027
1028 String type_name = type_info.name();
1029 writeFileString(ofile, type_name);
1030
1031 writeFileInt(ofile, nb_sub_part);
1032
1033#if 0
1034 // Sauve les uniqueId() des entités
1035 for( ConstArrayView<Item>::const_iter i(items); i(); ++i ){
1036 Item mi = *i;
1037 writeFileInt(ofile,mi.uniqueId()+1);
1038 }
1039#endif
1040
1041 if (type_name == "nfaced") {
1042 // Traitement particulier pour les mailles non standards
1043 // Comme nos faces ne sont pas orientées par rapport à une
1044 // maille, on utilise la connectivité locale de chaque face.
1045 // 1. Sauve le nombre de faces de chaque élément
1046 {
1047 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1048 // Tous les éléments ont le même nombre de faces
1049 Item mi = *items.data();
1050 Cell cell = mi.toCell();
1051 Integer nb_face = cell.nbFace();
1052 for (Integer z = 0; z < nb_sub_part; ++z)
1053 writeFileInt(ofile, nb_face);
1054 }
1055 else { // le maillage a des éléments généraux
1056 // Tous les éléments n'ont pas le même nombre de faces
1057 for (Item mi : items) {
1058 writeFileInt(ofile, mi.toCell().nbFace());
1059 }
1060 }
1061 }
1062 // 2. Sauve pour chaque elément, le nombre de noeuds de chacune
1063 // de ces faces
1064 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1065 for (Item mi : items) {
1066 const ItemTypeInfo* item_info = mi.typeInfo();
1067 Integer nb_face = item_info->nbLocalFace();
1068 for (Integer z = 0; z < nb_face; ++z)
1069 writeFileInt(ofile, item_info->localFace(z).nbNode());
1070 }
1071 }
1072 else { // le maillage a des éléments généraux
1073 for (Item mi : items) {
1074 Cell cell = mi.toCell();
1075 for (Face face : cell.faces()) {
1076 writeFileInt(ofile, face.nbNode());
1077 }
1078 }
1079 }
1080 // 3. Sauve pour chaque face de chaque élément la liste de ces
1081 // noeuds
1082 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1083 for (Item item : items) {
1084 Cell cell(item.toCell());
1085 const ItemTypeInfo* item_info = cell.typeInfo();
1086 //Cell cell = mi.toCell();
1087 Integer nb_face = item_info->nbLocalFace();
1088 for (Integer z = 0; z < nb_face; ++z) {
1089 const ItemTypeInfo::LocalFace& local_face = item_info->localFace(z);
1090 Integer nb_node = local_face.nbNode();
1091 array_id.resize(nb_node);
1092 for (Integer y = 0; y < nb_node; ++y) {
1093 // Inversion du sens des noeuds
1094 // A priori, il y a un bug dans Ensight (7.4.1(g)) concernant les
1095 // intersections de ce type d'éléments avec les objets
1096 // Ensight (plan, sphere, ...). Quelle que soit l'orientation
1097 // des faces retenues, le comportant n'est pas correcte.
1098 array_id[y] = nodes_index[cell.node(local_face.node(y)).localId()];
1099 }
1100 writeFileArray(ofile, array_id);
1101 }
1102 }
1103 }
1104 else { // le maillage a des éléments généraux
1105 for (Item item : items) {
1106 Cell cell = item.toCell();
1107 Integer nb_face = cell.nbFace();
1108 for (Integer z = 0; z < nb_face; ++z) {
1109 const Face local_face = cell.face(z);
1110 Integer nb_node = local_face.nbNode();
1111 array_id.resize(nb_node);
1112 for (Integer y = 0; y < nb_node; ++y) {
1113 array_id[y] = nodes_index[local_face.node(y).localId()];
1114 }
1115 writeFileArray(ofile, array_id);
1116 }
1117 }
1118 }
1119 }
1120 else if (type_name == "nsided") {
1121 // Traitement particulier pour les faces à plus de 4 noeuds:
1122
1123 // 1. Sauve pour chaque elément, le nombre de ses noeuds
1124 //cerr << "** NSIDED ELEMENT\n";
1125 for (Item mi : items) {
1127 Integer nb_node = e.nbNode();
1128 writeFileInt(ofile, nb_node);
1129 }
1130 // 2. Sauve pour chaque elément la liste de ces noeuds
1131 for (Item mi : items) {
1133 Integer nb_node = e.nbNode();
1134 array_id.resize(nb_node);
1135 for (Integer z = 0; z < nb_node; ++z) {
1136 array_id[z] = nodes_index[e.node(z).localId()];
1137 }
1138 writeFileArray(ofile, array_id);
1139 }
1140 }
1141 else {
1142 // Cas général
1143
1144 Integer nb_node = type_info.nbNode();
1145 array_id.resize(nb_node);
1146
1147 // Sauvegarde les éléments.
1148
1149 // Sauve la connectivité des éléments
1150 if (type_info.hasReindex()) {
1151 ConstArrayView<Integer> reindex = type_info.reindex();
1152 for (Item mi : items) {
1154 for (Integer j = 0; j < nb_node; ++j) {
1155 array_id[j] = nodes_index[e.node(reindex[j]).localId()];
1156 }
1157 writeFileArray(ofile, array_id);
1158 }
1159 }
1160 else { // pas de reindex
1161 for (Item mi : items) {
1163 for (Integer j = 0; j < nb_node; ++j) {
1164 array_id[j] = nodes_index[e.node(j).localId()];
1165 }
1166 writeFileArray(ofile, array_id);
1167 }
1168 }
1169 }
1170 }
1171}
1172
1173/*---------------------------------------------------------------------------*/
1174/*---------------------------------------------------------------------------*/
1200void DumpWEnsight7::
1201_saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
1202 WriteBase& from_func)
1203{
1204 ItemGroup igrp = ensight_grp.group();
1205
1206 writeFileString(ofile, "part");
1207 writeFileInt(ofile, ensight_grp.partId());
1208
1209 // Les éléments de même types (en particulier les 'nfaced', 'haxa8' ou 'nsided')
1210 // doivent être écrits d'un seul bloc (donc label de type unifié).
1211 // Par ailleurs, les données vectorielles doivent être entrelacés.
1212 String last_type_name;
1214 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1215 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1216 ConstArrayView<Item> items(type_info.items());
1217 Integer nb_sub_part = items.size();
1218 if (nb_sub_part == 0)
1219 continue;
1220 String type_name = type_info.name();
1221 if (type_name != last_type_name) {
1222 // Cloture la précédente écriture
1223 if (func.get()) {
1224 func->end();
1225 func->putValue(ofile);
1226 }
1227 last_type_name = type_name;
1228 writeFileString(ofile, type_name);
1229 func = from_func.clone();
1230 func->begin();
1231 }
1232
1233 // Sauvegarde les variables.
1234 func->write(items);
1235 }
1236
1237 // Cloture finale
1238 if (func.get()) {
1239 func->end();
1240 func->putValue(ofile);
1241 }
1242}
1243
1244/*---------------------------------------------------------------------------*/
1245/*---------------------------------------------------------------------------*/
1246
1247void DumpWEnsight7::
1248writeFileInt(std::ostream& o, int value)
1249{
1250 if (m_is_binary) {
1251 o.write((const char*)&value, sizeof(int));
1252 }
1253 else {
1254 o.width(DumpWEnsight7::int_width);
1255 o << value;
1256 o << '\n';
1257 }
1258}
1259
1260/*---------------------------------------------------------------------------*/
1261/*---------------------------------------------------------------------------*/
1262
1263Integer DumpWEnsight7::
1264writeIntSize() const
1265{
1266 if (m_is_binary)
1267 return sizeof(int);
1268 return DumpWEnsight7::int_width + 1;
1269}
1270
1271/*---------------------------------------------------------------------------*/
1272/*---------------------------------------------------------------------------*/
1273
1274void DumpWEnsight7::
1275writeFileDouble(std::ostream& o, double value)
1276{
1277 if (m_is_binary) {
1278 float fvalue = (float)(value);
1279 o.write((const char*)&fvalue, sizeof(float));
1280 }
1281 else {
1282 o.width(12);
1283 o.precision(5);
1284 o.flags(std::ios::scientific);
1285 o << value;
1286 o << '\n';
1287 }
1288}
1289
1290/*---------------------------------------------------------------------------*/
1291/*---------------------------------------------------------------------------*/
1292
1293Integer DumpWEnsight7::
1294writeDoubleSize() const
1295{
1296 Integer float_size = (Integer)(sizeof(float));
1297 return (m_is_binary) ? float_size : (12 + 1);
1298}
1299
1300/*---------------------------------------------------------------------------*/
1301/*---------------------------------------------------------------------------*/
1302
1303void DumpWEnsight7::
1304writeFileArray(std::ostream& o, IntegerConstArrayView value)
1305{
1306 if (m_is_binary) {
1307 o.write((const char*)value.data(), sizeof(Integer) * value.size());
1308 }
1309 else {
1310 for (Integer i = 0, s = value.size(); i < s; ++i) {
1311 o.width(DumpWEnsight7::int_width);
1312 o << value[i];
1313 }
1314 o << '\n';
1315 }
1316}
1317
1318/*---------------------------------------------------------------------------*/
1319/*---------------------------------------------------------------------------*/
1320
1321void DumpWEnsight7::
1322writeFileString(std::ostream& o, const String& str)
1323{
1324 if (m_is_binary) {
1325 char buf[g_line_length];
1326 for (int i = 0; i < g_line_length; ++i)
1327 buf[i] = '\0';
1328 CStringUtils::copyn(buf, str.localstr(), g_line_length);
1329 buf[g_line_length - 1] = '\0';
1330 o.write(buf, g_line_length);
1331 }
1332 else {
1333 o << str << '\n';
1334 }
1335}
1336
1337/*---------------------------------------------------------------------------*/
1338/*---------------------------------------------------------------------------*/
1339
1340void DumpWEnsight7::
1341_writeFileHeader(std::ostream& o, bool write_c_binary)
1342{
1343 if (m_is_master) {
1344 if (_isNewBlocFile() && m_is_binary && write_c_binary)
1345 writeFileString(o, "C Binary");
1346 if (m_fileset_size != 0) {
1347 std::ostringstream ostr;
1348 ostr << "BEGIN TIME STEP "
1349 << "# " << m_times.size();
1350 writeFileString(o, ostr.str().c_str());
1351 }
1352 }
1353}
1354
1355/*---------------------------------------------------------------------------*/
1356/*---------------------------------------------------------------------------*/
1364class DumpWEnsight7OutFile
1365{
1366 public:
1367
1368 DumpWEnsight7OutFile(DumpWEnsight7& dw, const String& filename, int outtype)
1369 : m_dw(dw)
1370 , m_filename(filename)
1371 , m_is_master(dw.isMasterProcessor())
1372 , m_is_parallel_output(dw.isParallelOutput())
1373 , m_stream(0)
1374 , m_filestream(0)
1375 {
1376 if (m_is_master) {
1377 m_filestream = new std::ofstream(filename.localstr(), (std::ios_base::openmode)outtype);
1378 m_stream = &m_strstream;
1379 if (!(*m_filestream))
1380 m_dw.warning() << "Unable to open file " << filename;
1381 }
1382 else {
1383 // TODO attention fuites mémoires.
1384 m_stream = &m_strstream;
1385 }
1386 ARCANE_CHECK_PTR(m_stream);
1387 }
1388 ~DumpWEnsight7OutFile()
1389 {
1390 delete m_filestream;
1391 }
1392
1393 public:
1394
1395 void syncFile()
1396 {
1397 IParallelMng* parallel_mng = m_dw.parallelMng();
1398 if (m_is_master) {
1399 ARCANE_CHECK_PTR(m_filestream);
1400 ARCANE_CHECK_PTR(m_strstream);
1401 //Integer pos = m_strstream->tellp();
1402 (*m_filestream) << m_strstream.str();
1403 }
1404 if (m_is_parallel_output) {
1405 if (m_is_master) {
1406 ARCANE_CHECK_PTR(m_filestream);
1407
1408 // Le maitre parcours tous les processeurs et demande pour chacun
1409 // d'eux la taille de chaque sauvegarde et si elle n'est pas nulle,
1410 // réceptionne le message.
1411 Integer nb_proc = parallel_mng->commSize();
1412 UniqueArray<int> len_array(1);
1413 UniqueArray<Byte> str_array;
1414 for (Integer i = 1; i < nb_proc; ++i) {
1415 m_dw.debug(Trace::High) << "En attente de la longueur du processeur " << i;
1416 parallel_mng->recv(len_array, i);
1417 Integer len = len_array[0];
1418 m_dw.debug(Trace::High) << "Longueur du processeur " << i << " : " << len;
1419 if (len != 0) {
1420 str_array.resize(len);
1421 m_dw.debug(Trace::High) << "En attente de la réception de la géométrie du processeur " << i;
1422 parallel_mng->recv(str_array, i);
1423 m_dw.debug(Trace::High) << "Réception de la géométrie du processeur " << i;
1424 m_filestream->write((const char*)str_array.data(), str_array.size());
1425 }
1426 }
1427 }
1428 else {
1429 ARCANE_CHECK_PTR(m_strstream);
1430 // Un esclave envoie au processeur maître (actuellement le processeur 0)
1431 // la taille de ses données puis ces données.
1432 // Il faut bien prendre la longueur de la chaîne retournée par m_strstream
1433 // et pas uniquement c_str() car le flux pouvant contenant des informations
1434 // au format binaire, on s'arrêterait au premier zéro.
1435 UniqueArray<int> len_array(1);
1436 std::string str = m_strstream.str();
1437 Integer len = arcaneCheckArraySize(str.length());
1438 UniqueArray<Byte> bytes(len);
1439 {
1440 // Recopie dans bytes la chaîne \a str
1441 Integer index = 0;
1442 for (ConstIterT<std::string> i(str); i(); ++i, ++index)
1443 bytes[index] = *i;
1444 }
1445 m_dw.debug(Trace::High) << "Pas un maître. Taille de " << m_filename << " = " << len;
1446 //Integer len = m_strstream->tellp();
1447 //Integer len = str.length();
1448 len_array[0] = len;
1449 m_dw.debug(Trace::High) << "Envoi de la longueur pour le processeur 0";
1450 parallel_mng->send(len_array, 0);
1451 if (len != 0) {
1452 //UniqueArray<char> str_array(len);
1453 //std::string s = m_strstream->str();
1454 //platform::stdMemcpy(str_array.begin(),s.c_str(),s.length());
1455 m_dw.debug(Trace::High) << "Envoi des données pour le processeur 0";
1456 parallel_mng->send(bytes, 0); //str.c_str())__array,0);
1457 //parallel_mng->send(str_array,0);
1458 }
1459 }
1460 }
1461 if (m_is_master)
1462 if (!m_dw.isOneFilePerTime())
1463 m_dw.writeFileString(*m_filestream, "END TIME STEP");
1464 }
1465
1466 public:
1467
1468 std::ostream& operator()() { return *m_stream; }
1469
1470 private:
1471
1472 DumpWEnsight7& m_dw;
1473 String m_filename;
1474 bool m_is_master;
1475 bool m_is_parallel_output;
1476 std::ostream* m_stream;
1477 std::ostringstream m_strstream;
1478 std::ofstream* m_filestream;
1479};
1480
1481/*---------------------------------------------------------------------------*/
1482/*---------------------------------------------------------------------------*/
1483
1484/*---------------------------------------------------------------------------*/
1485/*---------------------------------------------------------------------------*/
1486
1488beginWrite()
1489{
1490 String buf = m_base_directory.file("ensight.case");
1491
1492 IParallelMng* parallel_mng = m_parallel_mng;
1493 bool is_parallel = parallel_mng->isParallel();
1494 m_is_master = true;
1495 if (is_parallel && m_is_parallel_output)
1496 m_is_master = parallel_mng->commRank() == 0;
1497
1498 // Détermine et créé le répertoire ou seront écrites les sorties
1499 // de cette itération.
1501
1502 IMesh* mesh = m_mesh;
1503
1504 // Récupère la liste des groupes et leur donne à chacun un identifiant
1505 // unique pour Ensight (part). Le numéro de l'identifiant débute à 2, le numéro 1
1506 // est pour la liste des noeuds
1507 {
1508
1509 ItemGroupList list_group;
1510 // Si la liste des groupes à sauver est vide, sauve tous les groupes.
1511 // Sinon, sauve uniquement les groupes spécifiés.
1512 Integer nb_group = m_save_groups.count();
1513 if (nb_group == 0)
1514 list_group.clone(mesh->groups());
1515 else
1516 list_group.clone(m_save_groups);
1517 // Regarde la liste des variables partielles, et ajoute leur groupe à la liste
1518 // des groupes à sauver.
1519 for (VariableList::Enumerator ivar(m_save_variables); ++ivar;) {
1520 IVariable* var = *ivar;
1521 if (!var->isPartial())
1522 continue;
1523 ItemGroup var_group = var->itemGroup();
1524 if (!list_group.contains(var_group))
1525 list_group.add(var_group);
1526 }
1527 Integer partid = 1;
1529 partid += parallel_mng->commRank() * list_group.count();
1530
1531 _computeGroupParts(list_group, partid);
1532
1533 // Récupère le nombre total d'eléments dans les groupes.
1534 Integer total_nb_element = 0;
1535 m_total_nb_group = 0;
1536 for (auto i : m_parts) {
1537 total_nb_element += i->totalNbElement();
1539 }
1540
1541 m_total_nb_element = total_nb_element;
1542 debug() << "Nombre total d'éléments " << m_total_nb_element << " et de groupes " << m_total_nb_group;
1543 debug() << "Ajout de nœuds " << mesh->nbNode();
1544 }
1545
1546 // Sauvegarde la géométrie au format Ensight7 gold
1547 if (!(m_times.size() > 1 && m_force_first_geometry)) {
1548 String filename;
1549 _buildFileName("ensight.geo", filename);
1550
1551 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1552
1553 _writeFileHeader(dw_ofile(), true);
1554
1555 if (m_is_master) {
1556 writeFileString(dw_ofile(), "Output ensight test");
1557 writeFileString(dw_ofile(), "File description");
1558 writeFileString(dw_ofile(), "node id assign");
1559 writeFileString(dw_ofile(), "element id assign");
1560 }
1561
1562 IMesh* mesh = m_mesh;
1563 NodeGroup all_nodes = mesh->allNodes();
1564
1565 // Ce tableau sert pour chaque entité maille, face ou arête pour
1566 // référencer ses noeuds par rapport au tableau de coordonnées
1567 // utilisé par Ensight. Le premier élément de ce tableau à pour indice 1
1568 UniqueArray<Integer> all_nodes_index(mesh->itemFamily(IK_Node)->maxLocalId());
1569 all_nodes_index.fill(0);
1570
1571 UniqueArray<Real3> coords_backup;
1572 ConstArrayView<Real3> coords_array;
1573 if (mesh->parentMesh()) {
1574 SharedVariableNodeReal3 nodes_coords(mesh->sharedNodesCoordinates());
1575 coords_backup.resize(mesh->nodeFamily()->maxLocalId());
1576 ENUMERATE_NODE (i_item, all_nodes) {
1577 coords_backup[i_item.localId()] = nodes_coords[i_item];
1578 }
1579 coords_array = coords_backup.view();
1580 }
1581 else {
1582 VariableNodeReal3& nodes_coords(mesh->toPrimaryMesh()->nodesCoordinates());
1583 coords_array = ConstArrayView<Real3>(nodes_coords.asArray());
1584 }
1585
1586 WriteReal3 wf(*this, coords_array);
1587 {
1588 wf.init();
1589 writeFileString(wf.stream(), "coordinates");
1590 writeFileInt(wf.stream(), all_nodes.size());
1591 wf.begin();
1592
1593 // Stocke les indices locaux pour Ensight
1594 {
1595 Integer ensight_index = 1;
1596 ENUMERATE_ITEM (i_item, all_nodes) {
1597 const Item& item = *i_item;
1598 all_nodes_index[item.localId()] = ensight_index;
1599 ++ensight_index;
1600 }
1601 }
1602
1603 // Affiche les numéros unique des noeuds
1604#if 0
1605 {
1606 ENUMERATE_ITEM(i_item,all_nodes){
1607 const Item& item = *i_item;
1608 writeFileInt(wf.stream(),item.uniqueId()+1);
1609 }
1610 }
1611#endif
1612 // Affiche les coordonnées de chaque noeud
1613 ENUMERATE_ITEM (i_item, all_nodes) {
1614 const Item& item = *i_item;
1615 wf.write(item.localId());
1616 }
1617 wf.end();
1618 }
1619
1620 for (const GroupPartInfo* part : m_parts)
1621 _saveGroup(dw_ofile(), *part, all_nodes_index, wf);
1622
1623 dw_ofile.syncFile();
1624 }
1625}
1626
1627/*---------------------------------------------------------------------------*/
1628/*---------------------------------------------------------------------------*/
1629
1631endWrite()
1632{
1633 // Sauvegarde des identifiants uniques
1634 if (m_save_uids) {
1636 ENUMERATE_CELL (icell, m_mesh->allCells()) {
1637 cell_uids[icell] = (Real)(icell->uniqueId().asInt64());
1638 }
1639 IVariable* cell_uid_var = cell_uids.variable();
1640 m_save_variables.add(cell_uid_var);
1641 cell_uid_var->setUsed(true);
1642 cell_uid_var->notifyBeginWrite();
1643 write(cell_uid_var, cell_uid_var->data());
1644
1645 // GG: NOTE: je ne suis pas sur que cela fonctionne bien.
1646 //TODO: supprimer l'utilisation de deux variables
1648 UniqueArray<Real> node_uids2(m_mesh->nodeFamily()->allItems().size());
1649 ENUMERATE_NODE (inode, m_mesh->allNodes()) {
1650 node_uids[inode] = inode->uniqueId().asInt32();
1651 node_uids2[inode.index()] = (Real)inode->uniqueId().asInt64();
1652 }
1653
1654 IVariable* node_uid_var = node_uids.variable();
1655 m_save_variables.add(node_uid_var);
1656 node_uid_var->setUsed(true);
1657 _writeRealValT<Real>(*node_uid_var, node_uids2); // contournement de bug pour les variables de nœuds
1658 }
1659
1660 String buf = m_base_directory.file("ensight.case");
1661
1662 // Seul un processeur maître génère un fichier 'case'
1663 if (m_is_master) {
1664
1665 m_case_file.open(buf.localstr());
1666
1667 if (!m_case_file)
1668 warning() << "Unable to write to file: <" << buf << "> error: " << m_case_file.rdstate();
1669
1670 debug() << "** Exportation des données vers " << m_base_directory.path();
1671 m_case_file << "FORMAT\ntype: ensight gold\n";
1672
1673 m_case_file << "\nGEOMETRY\n";
1674 m_case_file << "model: 1";
1675 if (m_fileset_size != 0)
1676 m_case_file << " 1 ";
1677 if (m_force_first_geometry)
1678 _writeWildcardFilename(m_case_file, "ensight.geo", '0');
1679 else
1680 _writeWildcardFilename(m_case_file, "ensight.geo", '*');
1681 //m_case_file << " [change_coords_only]\n";
1682 m_case_file << "\n";
1683
1684 m_case_file << "\nVARIABLE\n";
1685 m_case_file << m_case_file_variables.str();
1686
1687 // Sauvegarde en temps. Pour paraview, il faut le mettre apres les variables
1688 m_case_file << "\nTIME\n";
1689 m_case_file << "time set: 1\n";
1690 m_case_file << "number of steps: " << m_times.size() << '\n';
1691 m_case_file << "filename start number: 0\n";
1692 m_case_file << "filename increment: 1\n";
1693 m_case_file << "time values:\n";
1694 // Faire attention de ne pas dépasser les 79 caractères par ligne
1695 // autorisés par Ensight. Pour être sur, on n'écrit qu'un temps pas
1696 // ligne. Les temps sont sauvés le maximum de chiffres significatifs
1697 // car Ensight n'aime pas que deux temps soient égaux.
1698 std::streamsize old_precision = m_case_file.precision(FloatInfo<Real>::maxDigit());
1699 for (Integer i = 0, is = m_times.size(); i < is; ++i)
1700 m_case_file << m_times[i] << '\n';
1701 m_case_file << '\n';
1702 m_case_file.precision(old_precision);
1703
1704 if (m_fileset_size != 0) {
1705 m_case_file << "FILE\n";
1706 m_case_file << "file set: 1\n";
1707 if (m_fileset_size != 0) {
1708 Integer nb_timeset = (m_times.size() / m_fileset_size);
1709 for (Integer i = 0; i < nb_timeset; ++i) {
1710 m_case_file << "filename index: " << i << "\n";
1711 m_case_file << "number of steps: " << m_fileset_size << '\n';
1712 }
1713 if (nb_timeset > 0)
1714 m_case_file << "filename index: " << nb_timeset << "\n";
1715 m_case_file << "number of steps: " << m_times.size() - (nb_timeset * m_fileset_size) << '\n';
1716 }
1717 else {
1718 m_case_file << "number of steps: " << m_times.size() << '\n';
1719 }
1720 m_case_file << '\n';
1721 }
1722 }
1723 m_case_file.flush();
1724 m_case_file.close();
1725}
1726
1727/*---------------------------------------------------------------------------*/
1728/*---------------------------------------------------------------------------*/
1729
1730/*---------------------------------------------------------------------------*/
1731/*---------------------------------------------------------------------------*/
1732
1746{
1747 if (!v.isUsed())
1748 return false;
1749 eItemKind ik = v.itemKind();
1750 if (ik != IK_Cell && ik != IK_Node && ik != IK_Face)
1751 return false;
1752 // Si une liste de variable est spécifiée, vérifie que la variable est dans
1753 // cette liste. Si cette liste est vide, on sauve automatiquement toutes les
1754 // variables.
1755 Integer nb_var = m_save_variables.count();
1756 if (nb_var != 0) {
1757 return m_save_variables.contains(&v);
1758 }
1759 return true;
1760}
1761
1762/*---------------------------------------------------------------------------*/
1763/*---------------------------------------------------------------------------*/
1764
1778_buildFileName(const String& name, String& filename)
1779{
1780 StringBuilder fn_builder;
1781 if (m_fileset_size == 0) {
1782 Integer current_time = m_times.size() - 1;
1783 fn_builder = m_base_directory.path();
1784 fn_builder += "/";
1785 fn_builder += name;
1786 if (m_is_master) {
1787 Directory dir(fn_builder.toString());
1788 dir.createDirectory();
1789 }
1790 fn_builder += "/";
1791 fn_builder += name;
1792
1793 {
1794 OStringStream ostr;
1795 ostr().fill('0'); // Caractère de remplissage.
1796 ostr().width(m_max_prots_digit);
1797 ostr() << current_time;
1798 fn_builder += ostr.str();
1799 }
1800
1801 //fn_builder += current_time;
1802
1803 //info() << " BUILD FILE NAME name=" << name << " filename=" << fn_builder;
1804 }
1805 else {
1806 fn_builder = m_part_directory.path();
1807 fn_builder += "/";
1808 fn_builder += name;
1809 }
1810 filename = fn_builder;
1811}
1812
1813/*---------------------------------------------------------------------------*/
1814/*---------------------------------------------------------------------------*/
1815
1816bool DumpWEnsight7::
1817_isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind)
1818{
1819 eItemKind group_kind = group.itemKind();
1820 if (item_kind == IK_Unknown)
1821 return false;
1822 return group_kind == item_kind;
1823}
1824
1825/*---------------------------------------------------------------------------*/
1826/*---------------------------------------------------------------------------*/
1839{
1840 Integer prot_index = 0;
1841 bool has_prot = false;
1842 if (m_fileset_size != 0) {
1843 Integer nb_time = m_times.size();
1844 if (nb_time != 0)
1845 prot_index = (nb_time - 1) / m_fileset_size;
1846 has_prot = true;
1847 }
1848
1849 if (m_is_master)
1850 m_base_directory.createDirectory();
1851
1852 if (has_prot) {
1853 OStringStream ostr;
1854 ostr() << "bloc";
1855 ostr().fill('0'); // Caractère de remplissage.
1856 ostr().width(m_max_prots_digit);
1857 ostr() << prot_index;
1858 //ostr() << '\0';
1859 String buf = ostr.str();
1861 if (m_is_master)
1862 m_part_directory.createDirectory();
1863 }
1864 else
1866}
1867
1868/*---------------------------------------------------------------------------*/
1869/*---------------------------------------------------------------------------*/
1870
1871void DumpWEnsight7::
1872_writeWildcardFilename(std::ostream& ofile, const String& filename, char joker)
1873{
1874 if (m_fileset_size == 0) {
1875 ofile << ' ' << filename << '/' << filename;
1876 for (Integer i = 0; i < m_max_prots_digit; ++i)
1877 ofile << joker;
1878 }
1879 else {
1880 ofile << " bloc";
1881 Integer nb_time = m_times.size();
1882 // Si le nombre de temps est inférieur à la taille d'un fileset-set,
1883 // il n'y a pas besoin de mettre une '*'. On peut directement
1884 // mettre des zéros. Cela est aussi indispensable pour empêcher
1885 // paraview de planter quand il relit ce genre de fichiers.
1886 if (nb_time <= m_fileset_size)
1887 joker = '0';
1888 for (Integer i = 0; i < m_max_prots_digit; ++i)
1889 ofile << joker;
1890 ofile << "/" << filename;
1891 }
1892}
1893
1894/*---------------------------------------------------------------------------*/
1895/*---------------------------------------------------------------------------*/
1896
1897bool DumpWEnsight7::
1898_isNewBlocFile() const
1899{
1900 Integer nb_time = m_times.size();
1901
1902 if (nb_time == 1)
1903 return true;
1904 if (m_fileset_size == 0)
1905 return true;
1906
1907 Integer modulo = (nb_time - 1) % m_fileset_size;
1908
1909 if (modulo == 0)
1910 return true;
1911 return false;
1912}
1913
1914/*---------------------------------------------------------------------------*/
1915/*---------------------------------------------------------------------------*/
1916
1917int DumpWEnsight7::
1918_fileOuttype() const
1919{
1920 return ((isBinary()) ? std::ios::binary : 0) | ((_isNewBlocFile()) ? std::ios::trunc : std::ios::app);
1921}
1922
1923/*---------------------------------------------------------------------------*/
1924/*---------------------------------------------------------------------------*/
1925
1929template <typename T>
1932{
1933 debug() << "Saving variable1 " << v.name() << " ptr=" << ptr.data() << " ps=" << ptr.size();
1934
1935 if (!_isValidVariable(v))
1936 return;
1937
1938 String filename;
1939 _buildFileName(v.name(), filename);
1940
1941 debug() << "Saving variable " << v.name() << " in " << filename;
1942
1943 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1944
1945 _writeFileHeader(dw_ofile(), false);
1946
1947 if (m_is_master)
1948 writeFileString(dw_ofile(), v.name());
1949 String var_type_str;
1950
1951 if (m_is_master) {
1952 switch (v.itemKind()) {
1953 case IK_Cell:
1954 case IK_Face:
1955 var_type_str = "scalar per element: ";
1956 break;
1957 case IK_Node:
1958 var_type_str = "scalar per node: ";
1959 break;
1960 default:
1961 break;
1962 }
1963
1964 m_case_file_variables << var_type_str;
1965 m_case_file_variables << " 1 ";
1966 if (m_fileset_size != 0)
1967 m_case_file_variables << " 1 ";
1968 m_case_file_variables << v.name();
1969 _writeWildcardFilename(m_case_file_variables, v.name());
1970 m_case_file_variables << '\n';
1971 }
1972
1973 switch (v.itemKind()) {
1974 case IK_Cell:
1975 case IK_Face:
1976 case IK_Edge: {
1977 GroupIndexTable* idx = nullptr;
1978
1979 if (v.isPartial()) {
1980 idx = v.itemGroup().localIdToIndex().get();
1981 }
1982
1983 WriteDouble<T> wf(*this, ptr, idx);
1984 for (const GroupPartInfo* part : m_parts) {
1985 bool need_save = false;
1986 if (v.isPartial())
1987 need_save = v.itemGroup() == part->group();
1988 else
1989 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
1990 if (need_save)
1991 _saveVariableOnGroup(dw_ofile(), *part, wf);
1992 }
1993 } break;
1994 case IK_Node: {
1995 if (v.isPartial())
1996 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
1997 WriteDouble<T> wf(*this, ptr);
1998 wf.begin();
1999 for (Integer i = 0; i < ptr.size(); ++i)
2000 wf.write(i);
2001 wf.end();
2002 for (const GroupPartInfo* part : m_parts) {
2003 writeFileString(dw_ofile(), "part");
2004 writeFileInt(dw_ofile(), part->partId());
2005 writeFileString(dw_ofile(), "coordinates");
2006 wf.putValue(dw_ofile());
2007 }
2008 } break;
2009 default:
2010 break;
2011 }
2012
2013 dw_ofile.syncFile();
2014
2015 //if (m_is_transient && m_is_master)
2016 //writeFileString(dw_ofile(),"END TIME STEP");
2017}
2018
2019/*---------------------------------------------------------------------------*/
2020/*---------------------------------------------------------------------------*/
2021
2025template <typename T>
2028{
2029 if (!_isValidVariable(v))
2030 return;
2031
2032 for (Integer idim2 = 0; idim2 < ptr.dim2Size(); ++idim2) {
2033 String vname = v.name() + String("_") + idim2;
2034 String filename;
2035 _buildFileName(vname, filename);
2036
2037 debug() << "Saving variable " << v.name() << " component " << idim2 << " in " << filename;
2038
2039 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2040
2041 _writeFileHeader(dw_ofile(), false);
2042
2043 if (m_is_master)
2044 writeFileString(dw_ofile(), vname);
2045 String var_type_str;
2046
2047 if (m_is_master) {
2048 switch (v.itemKind()) {
2049 case IK_Cell:
2050 case IK_Face:
2051 var_type_str = "scalar per element: ";
2052 break;
2053 case IK_Node:
2054 var_type_str = "scalar per node: ";
2055 break;
2056 default:
2057 break;
2058 }
2059
2060 m_case_file_variables << var_type_str;
2061 m_case_file_variables << " 1 ";
2062 if (m_fileset_size != 0)
2063 m_case_file_variables << " 1 ";
2064 m_case_file_variables << vname;
2065 _writeWildcardFilename(m_case_file_variables, vname);
2066 m_case_file_variables << '\n';
2067 }
2068
2069 switch (v.itemKind()) {
2070 case IK_Cell:
2071 case IK_Face:
2072 case IK_Edge: {
2073 GroupIndexTable* idx = nullptr;
2074
2075 if (v.isPartial()) {
2076 idx = v.itemGroup().localIdToIndex().get();
2077 }
2078
2079 WriteArrayDouble<T> wf(*this, ptr, idim2, idx);
2080 for (const GroupPartInfo* part : m_parts) {
2081 bool need_save = false;
2082 if (v.isPartial())
2083 need_save = v.itemGroup() == part->group();
2084 else
2085 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2086 if (need_save)
2087 _saveVariableOnGroup(dw_ofile(), *part, wf);
2088 }
2089 } break;
2090 case IK_Node: {
2091 if (v.isPartial())
2092 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2093 WriteArrayDouble<T> wf(*this, ptr, idim2);
2094 wf.begin();
2095 for (Integer i = 0; i < ptr.dim1Size(); ++i)
2096 wf.write(i);
2097 wf.end();
2098 for (const GroupPartInfo* part : m_parts) {
2099 writeFileString(dw_ofile(), "part");
2100 writeFileInt(dw_ofile(), part->partId());
2101 writeFileString(dw_ofile(), "coordinates");
2102 wf.putValue(dw_ofile());
2103 }
2104 } break;
2105 default:
2106 break;
2107 }
2108
2109 dw_ofile.syncFile();
2110 }
2111
2112 //if (m_is_transient && m_is_master)
2113 //writeFileString(dw_ofile(),"END TIME STEP");
2114}
2115
2116/*---------------------------------------------------------------------------*/
2117/*---------------------------------------------------------------------------*/
2118
2122template <typename T>
2125{
2126 ARCANE_UNUSED(ptr);
2127
2128 if (!_isValidVariable(v))
2129 return;
2130
2131 warning() << "Impossible to write array variable "
2132 << v.name() << " of non-constant size; variable saving skipped";
2133}
2134
2135/*---------------------------------------------------------------------------*/
2136/*---------------------------------------------------------------------------*/
2137
2143{
2144 if (!_isValidVariable(v))
2145 return;
2146
2147 String filename;
2148 _buildFileName(v.name(), filename);
2149
2150 debug() << "Saving variable " << v.name() << " in " << filename;
2151
2152 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2153
2154 _writeFileHeader(dw_ofile(), false);
2155 if (m_is_master)
2156 writeFileString(dw_ofile(), v.name());
2157
2158 if (m_is_master) {
2159 switch (v.itemKind()) {
2160 case IK_Cell:
2161 case IK_Face:
2162 m_case_file_variables << "vector per element: ";
2163 break;
2164 case IK_Node:
2165 m_case_file_variables << "vector per node: ";
2166 break;
2167 default:
2168 break;
2169 }
2170
2171 m_case_file_variables << " 1 ";
2172 if (m_fileset_size != 0)
2173 m_case_file_variables << " 1 ";
2174 m_case_file_variables << v.name();
2175
2176 _writeWildcardFilename(m_case_file_variables, v.name());
2177 m_case_file_variables << '\n';
2178 }
2179
2180 switch (v.itemKind()) {
2181 case IK_Cell:
2182 case IK_Face:
2183 case IK_Edge: {
2184 GroupIndexTable* idx = nullptr;
2185
2186 if (v.isPartial()) {
2187 idx = v.itemGroup().localIdToIndex().get();
2188 }
2189
2190 WriteReal3 wf(*this, ptr, idx);
2191 for (const GroupPartInfo* part : m_parts) {
2192 bool need_save = false;
2193 if (v.isPartial())
2194 need_save = v.itemGroup() == part->group();
2195 else
2196 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2197 if (need_save)
2198 _saveVariableOnGroup(dw_ofile(), *part, wf);
2199 }
2200 } break;
2201 case IK_Node: {
2202 if (v.isPartial())
2203 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2204 WriteReal3 wf(*this, ptr);
2205 wf.begin();
2206 for (Integer i = 0; i < ptr.size(); ++i)
2207 wf.write(i);
2208 wf.end();
2209 for (const GroupPartInfo* part : m_parts) {
2210 writeFileString(dw_ofile(), "part");
2211 writeFileInt(dw_ofile(), part->partId());
2212 writeFileString(dw_ofile(), "coordinates");
2213 wf.putValue(dw_ofile());
2214 }
2215 } break;
2216 default:
2217 break;
2218 }
2219
2220 dw_ofile.syncFile();
2221}
2222
2223/*---------------------------------------------------------------------------*/
2224/*---------------------------------------------------------------------------*/
2225
2231{
2232 if (!_isValidVariable(v))
2233 return;
2234
2235 for (Integer idim2 = 0; idim2 < ptr.dim2Size(); ++idim2) {
2236 String vname = v.name() + String("_") + idim2;
2237 String filename;
2238 _buildFileName(vname, filename);
2239
2240 debug() << "Saving variable " << v.name() << " component " << idim2 << " in " << filename;
2241
2242 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2243
2244 _writeFileHeader(dw_ofile(), false);
2245 if (m_is_master)
2246 writeFileString(dw_ofile(), vname);
2247
2248 if (m_is_master) {
2249 switch (v.itemKind()) {
2250 case IK_Cell:
2251 case IK_Face:
2252 m_case_file_variables << "vector per element: ";
2253 break;
2254 case IK_Node:
2255 m_case_file_variables << "vector per node: ";
2256 break;
2257 default:
2258 break;
2259 }
2260
2261 m_case_file_variables << " 1 ";
2262 if (m_fileset_size != 0)
2263 m_case_file_variables << " 1 ";
2264 m_case_file_variables << vname;
2265
2266 _writeWildcardFilename(m_case_file_variables, vname);
2267 m_case_file_variables << '\n';
2268 }
2269
2270 switch (v.itemKind()) {
2271 case IK_Cell:
2272 case IK_Face:
2273 case IK_Edge: {
2274 GroupIndexTable* idx = nullptr;
2275
2276 if (v.isPartial()) {
2277 idx = v.itemGroup().localIdToIndex().get();
2278 }
2279
2280 WriteArrayReal3 wf(*this, ptr, idim2, idx);
2281 for (const GroupPartInfo* part : m_parts) {
2282 bool need_save = false;
2283 if (v.isPartial())
2284 need_save = v.itemGroup() == part->group();
2285 else
2286 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2287 if (need_save)
2288 _saveVariableOnGroup(dw_ofile(), *part, wf);
2289 }
2290 } break;
2291 case IK_Node: {
2292 if (v.isPartial())
2293 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2294 WriteArrayReal3 wf(*this, ptr, idim2);
2295 wf.begin();
2296 for (Integer i = 0; i < ptr.dim1Size(); ++i)
2297 wf.write(i);
2298 wf.end();
2299 for (const GroupPartInfo* part : m_parts) {
2300 writeFileString(dw_ofile(), "part");
2301 writeFileInt(dw_ofile(), part->partId());
2302 writeFileString(dw_ofile(), "coordinates");
2303 wf.putValue(dw_ofile());
2304 }
2305 } break;
2306 default:
2307 break;
2308 }
2309
2310 dw_ofile.syncFile();
2311 }
2312
2313 //if (m_is_transient && m_is_master)
2314 //writeFileString(dw_ofile(),"END TIME STEP");
2315}
2316
2317/*---------------------------------------------------------------------------*/
2318/*---------------------------------------------------------------------------*/
2319
2325{
2326 ARCANE_UNUSED(ptr);
2327
2328 if (!_isValidVariable(v))
2329 return;
2330
2331 warning() << "Impossible to write array variable " << v.name()
2332 << " of non-constant size; variable saving skipped";
2333}
2334
2335/*---------------------------------------------------------------------------*/
2336/*---------------------------------------------------------------------------*/
2337
2341class Ensight7PostProcessorService
2342: public PostProcessorWriterBase
2343{
2344 public:
2345
2346 Ensight7PostProcessorService(const ServiceBuildInfo& sbi)
2347 : PostProcessorWriterBase(sbi)
2348 , m_mesh(sbi.mesh())
2349 , m_writer(nullptr)
2350 {
2351 }
2352
2353 IDataWriter* dataWriter() override { return m_writer; }
2354 void notifyBeginWrite() override;
2355 void notifyEndWrite() override;
2356 void close() override {}
2357
2358 private:
2359
2360 IMesh* m_mesh;
2361 DumpW* m_writer;
2362};
2363
2364/*---------------------------------------------------------------------------*/
2365/*---------------------------------------------------------------------------*/
2366
2369{
2370 bool is_binary = true;
2371 Integer fileset_size = 100;
2372 bool is_parallel = subDomain()->parallelMng()->isParallel();
2373 bool use_degenerated_hexa = true;
2374 bool force_first_geometry = false;
2375 bool save_uids = false;
2376 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2377 variables(), groups(), is_binary, is_parallel,
2378 fileset_size, use_degenerated_hexa,
2379 force_first_geometry, save_uids);
2380}
2381
2384{
2385 delete m_writer;
2386 m_writer = 0;
2387}
2388
2389/*---------------------------------------------------------------------------*/
2390/*---------------------------------------------------------------------------*/
2391
2392/*---------------------------------------------------------------------------*/
2393/*---------------------------------------------------------------------------*/
2394
2398class Ensight7PostProcessorServiceV2
2400{
2401 public:
2402
2403 typedef ArcaneEnsight7PostProcessorObject BaseType;
2404
2405 public:
2406
2407 explicit Ensight7PostProcessorServiceV2(const ServiceBuildInfo& sbi)
2409 , m_mesh(sbi.mesh())
2410 , m_writer(nullptr)
2411 {
2412 }
2413
2414 IDataWriter* dataWriter() override { return m_writer; }
2415 void notifyBeginWrite() override;
2416 void notifyEndWrite() override;
2417 void close() override {}
2418
2419 void setMesh(IMesh* mesh) override
2420 {
2421 // TODO: A supprimer car méthode obsolète et n'est pas utilisé.
2422 m_mesh = mesh;
2423 }
2424
2425 private:
2426
2427 IMesh* m_mesh = nullptr;
2428 DumpW* m_writer = nullptr;
2429};
2430
2431/*---------------------------------------------------------------------------*/
2432/*---------------------------------------------------------------------------*/
2433
2436{
2437 // std::cout << " ############# IMesh = " << mesh() << " " << m_mesh << " ###########\n";
2438
2439 bool is_binary = true;
2440 Integer fileset_size = 0;
2441 bool is_parallel = m_mesh->parallelMng()->isParallel();
2442 is_binary = options()->binaryFile();
2443 fileset_size = options()->filesetSize();
2444 bool use_degenerated_hexa = options()->useDegeneratedHexa();
2445 bool force_first_geometry = options()->forceFirstGeometry();
2446 bool save_uids = options()->saveUids();
2447 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2448 variables(), groups(), is_binary, is_parallel, fileset_size,
2449 use_degenerated_hexa, force_first_geometry, save_uids);
2450}
2451
2454{
2455 delete m_writer;
2456 m_writer = nullptr;
2457}
2458
2459/*---------------------------------------------------------------------------*/
2460/*---------------------------------------------------------------------------*/
2461
2463 Ensight7PostProcessor);
2464
2465ARCANE_REGISTER_SERVICE_ENSIGHT7POSTPROCESSOR(Ensight7PostProcessor, Ensight7PostProcessorServiceV2);
2466
2467/*---------------------------------------------------------------------------*/
2468/*---------------------------------------------------------------------------*/
2469
2470} // namespace Arcane
2471
2472/*---------------------------------------------------------------------------*/
2473/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour itérer sur les entités du maillage.
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
Ce fichier contient les différentes fabriques de services et macro pour enregistrer les services.
#define ARCANE_REGISTER_SUB_DOMAIN_FACTORY(aclass, ainterface, aname)
Enregistre un service de fabrique pour la classe aclass.
Integer size() const
Nombre d'éléments du vecteur.
CaseOptionsEnsight7PostProcessor * options() const
Options du jeu de données du service.
ArcaneEnsight7PostProcessorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
Tableau d'items de types quelconques.
void fill(const DataType &data)
Remplissage du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
const T * data() const
Accès à la racine du tableau hors toute protection.
ArrayView< T > view() const
Vue mutable sur ce tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Maille d'un maillage.
Definition Item.h:1214
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Definition Item.h:1298
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1295
Int32 nbFace() const
Nombre de faces de la maille.
Definition Item.h:1292
Integer count() const
Nombre d'éléments de la collection.
Vue constante d'un tableau de type T.
constexpr const_pointer data() const noexcept
Pointeur sur la mémoire allouée.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
ConstIterT< ConstArrayView< T > > const_iter
Type d'un itérateur constant sur tout le tableau.
interval d'itérateurs constant
Vue constante sur un MultiArray2.
Classe gérant un répertoire.
Definition Directory.h:35
bool createDirectory() const override
Créé le répertoire.
Definition Directory.cc:102
Abstraction d'un fichier de sortie pour ensight.
Functeur pour écrire une variable de type Real.
Functor pour écrire une variable de type Real3.
Fonctor pour écrire une variable.
Functor pour écrire une variable de type Real.
Functor pour écrire une variable de type Real2.
Ecriture au format Ensight7.
void _writeRealValT(IVariable &v, ConstArrayView< T > a)
Template pour écrire une variable comme variable réelle.
std::ofstream m_case_file
Fichier décrivant le cas.
bool m_is_binary
Liste des parties.
void writeVal(IVariable &, ConstArrayView< Byte >) override
Ecriture pour la variable v du tableau a.
void beginWrite() override
Notifie le début d'écriture.
Directory m_part_directory
Répertoire de stockage de l'itération courante.
void _buildFileName(const String &varname, String &filename)
Construit le nom de fichier pour un nom de variable ou de maillage.
IMesh * m_mesh
Maillage.
bool _isValidVariable(IVariable &) const
Vérifie la validité de la variable à sauvegarder.
ItemGroupList m_save_groups
Liste des groupes a exporter.
void _buildPartDirectory()
Construit le répertoire où seront sauvées les variables.
IParallelMng * m_parallel_mng
Gestionnaire du parallélisme.
void endWrite() override
Notifie la fin d'écriture.
RealUniqueArray m_times
description des variables sauvées
void setMetaData(const String &) override
Positionne les infos des méta-données.
VariableList m_save_variables
Liste des variables a exporter.
static const Integer m_max_prots_digit
Nombre maximum de chiffres pour indiquer le numéro de protection.
Directory m_base_directory
Nom du répertoire de stockage.
bool m_is_master
true si le processeur dirige la sortie
Integer m_total_nb_element
Nombre total d'éléments de maillage de tous les groupes à sauver.
Integer m_total_nb_group
Nombre de groupes à sauver (== nombre de part).
wrapper transformant des appels à l'interface IDataWriter en ex IDumpW
Definition DumpW.h:45
DumpW()
Constructeur.
Definition DumpW.cc:155
void write(IVariable *var, IData *data)
Ecrit les données data de la variable var.
Definition DumpW.cc:179
Post-traitement au format Ensight7.
void notifyBeginWrite() override
Notifie qu'une sortie va être effectuée avec les paramètres courants.
void close() override
Ferme l'écrivain. Après fermeture, il ne peut plus être utilisé
void notifyEndWrite() override
Notifie qu'une sortie vient d'être effectuée.
IDataWriter * dataWriter() override
Retourne l'écrivain associé à ce post-processeur.
void setMesh(IMesh *mesh) override
Positionne le maillage.
Post-traitement au format Ensight7.
IDataWriter * dataWriter() override
Retourne l'écrivain associé à ce post-processeur.
void close() override
Ferme l'écrivain. Après fermeture, il ne peut plus être utilisé
void notifyEndWrite() override
Notifie qu'une sortie vient d'être effectuée.
void notifyBeginWrite() override
Notifie qu'une sortie va être effectuée avec les paramètres courants.
Face d'une maille.
Definition Item.h:964
Informations sur le type à virgule flottante.
Definition FloatInfo.h:35
Classe de base d'une table de hachage entre les items d'un groupe et leurs positions dans la table.
Interface d'écriture des données d'une variable.
Definition IDataWriter.h:44
virtual String name() const =0
Nom de la famille.
virtual ItemTypeMng * itemTypeMng() const =0
Gestionnaire de types d'entités associé
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
Interface d'un écrivain pour les informations de post-traitement.
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual IMesh * defaultMesh()=0
Maillage par défaut.
Interface d'une variable.
Definition IVariable.h:39
virtual void setUsed(bool v)=0
Positionne l'état d'utilisation de la variable.
@ PTemporary
Indique que la variable est temporaire.
Definition IVariable.h:116
@ PPrivate
Indique que la variable est privée.
Definition IVariable.h:104
virtual eItemKind itemKind() const =0
Genre des entités du maillage sur lequel repose la variable.
virtual bool isPartial() const =0
Indique si la variable est partielle.
virtual IData * data()=0
Données associées à la variable.
virtual bool isUsed() const =0
Etat d'utilisation de la variable.
virtual ItemGroup itemGroup() const =0
Groupe du maillage associé.
virtual void notifyBeginWrite()=0
Notifie du début d'écriture de data().
virtual String name() const =0
Nom de la variable.
Groupe d'entités de maillage.
Definition ItemGroup.h:49
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
bool isOwn() const
Retourne si le groupe contient uniquement des éléments propres au sous-domaine.
Definition ItemGroup.cc:158
SharedPtrT< GroupIndexTable > localIdToIndex() const
Table des local ids vers une position pour toutes les entités du groupe.
Definition ItemGroup.h:307
Integer size() const
Nombre d'éléments du groupe.
Definition ItemGroup.h:88
IItemFamily * itemFamily() const
Famille d'entité à laquelle appartient ce groupe (0 pour le group nul).
Definition ItemGroup.h:123
eItemKind itemKind() const
Genre du groupe. Il s'agit du genre de ses éléments.
Definition ItemGroup.h:109
bool null() const
true is le groupe est le groupe nul
Definition ItemGroup.h:70
IMesh * mesh() const
Maillage auquel appartient ce groupe (0 pour le group nul).
Definition ItemGroup.h:126
ItemGroup own() const
Groupe équivalent à celui-ci mais contenant uniquement les éléments propres au sous-domaine.
Definition ItemGroup.cc:190
Informations locales sur une face d'une maille.
Integer node(Integer i) const
Indice locale dans la maille du i-ème noeud de la face.
Integer nbNode() const
Nombre de noeuds de la face.
Infos sur un type d'entité du maillage.
LocalFace localFace(Integer id) const
Connectivité locale de la i-ème face de la maille.
Integer nbLocalEdge() const
Nombre d'arêtes de l'entité
Integer nbLocalNode() const
Nombre de noeuds de l'entité
Integer nbLocalFace() const
Nombre de faces de l'entité
Gestionnaire des types d'entités d'un maillage.
Definition ItemTypeMng.h:65
bool hasGeneralCells(IMesh *mesh) const
Indique si le maillage mesh contient des mailles génériques (en dehors des types intégrés ou addition...
static Integer nbBasicItemType()
nombre de types disponibles
ItemTypeInfo * typeFromId(Integer id) const
Type correspondant au numéro id.
static Integer nbBuiltInItemType()
nombre de types intégrés (hors types additionnels)
Elément de maillage s'appuyant sur des noeuds (Edge,Face,Cell).
Definition Item.h:736
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:791
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:788
Classe de base d'un élément de maillage.
Definition Item.h:83
const ItemTypeInfo * typeInfo() const
Infos sur le type de l'entité.
Definition Item.h:392
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
ItemWithNodes toItemWithNodes() const
Converti l'entité en le genre ItemWithNodes.
Definition Item.h:1674
Cell toCell() const
Converti l'entité en le genre Cell.
Definition Item.h:1702
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
Int16 type() const
Type de l'entité
Definition Item.h:241
void clone(const Collection< T > &base)
Clone la collection base.
Exception lorsqu'une fonction n'est pas implémentée.
Flot de sortie lié à une String.
ItemGroupCollection groups() override
Liste des groupes à sauver.
VariableCollection variables() override
Liste des variables à sauver.
ConstArrayView< Real > times() override
Liste des temps sauvés.
const String & baseDirectoryName() override
Nom du répertoire de sortie des fichiers.
T * get() const
Retourne l'objet référé par l'instance.
Definition Ptr.h:121
Encapsulation d'un pointeur qui se détruit automatiquement.
Definition ScopedPtr.h:44
IMesh * mesh() const
Accès au IMesh associé.
Structure contenant les informations pour créer un service.
Constructeur de chaîne de caractère unicode.
String toString() const
Retourne la chaîne de caractères construite.
Chaîne de caractères unicode.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:228
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage warning() const
Flot pour un message d'avertissement.
Vecteur 1D de données avec sémantique par valeur (style STL).
Paramètres nécessaires à la construction d'une variable.
Collection de variables.
IVariable * variable() const
Variable associée.
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
Definition ItemTypes.h:167
MeshVariableScalarRefT< Cell, Real > VariableCellReal
Grandeur au centre des mailles de type réel.
MeshVariableScalarRefT< Node, Integer > VariableNodeInteger
Grandeur au noeud de type entier.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
char * copyn(char *to, const char *from, Integer n)
Copie les n premiers caractères de from dans to.
Real toReal(Real r)
Convertit r en Real.
double toDouble(Real r)
Convertit un Real en double.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Integer arcaneCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....
Collection< ItemGroup > ItemGroupCollection
Collection de groupes d'éléments du maillage.
Int32 Integer
Type représentant un entier.
List< ItemGroup > ItemGroupList
Tableau de groupes d'éléments du maillage.
SharedMeshVariableScalarRefT< Node, Real3 > SharedVariableNodeReal3
Grandeur au noeud de type coordonnées.
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:347
eItemKind
Genre d'entité de maillage.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
@ IK_Unknown
Entité de maillage de genre inconnu ou non initialisé
@ IK_Face
Entité de maillage de genre face.
@ IK_Edge
Entité de maillage de genre arête.
double Real
Type représentant un réel.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:345
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:484
std::int32_t Int32
Type entier signé sur 32 bits.
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:486
Correspondance entre le type des éléments ensight et Arcane.
int m_type
Type Arcane de l'élément.
UniqueArray< Item > m_items
Entités des éléments de ce type.
Integer m_nb_node
Nombre de noeud.
String m_name
Nom Ensight de cet élément.
Information pour partagé un groupe en éléments de même sous-type.
Integer m_part_id
Numéro de la partie.
std::unique_ptr< VariableItemInt32 > m_general_item_types
Variable pour stocker les types des items généraux (non typés).
Integer nbType() const
Nombre de sous-types.