Arcane  4.2.1.0
Developer documentation
Loading...
Searching...
No Matches
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/* Exporting files in Ensight7 gold format. */
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: Add test with partial variables
58
59/*---------------------------------------------------------------------------*/
60/*---------------------------------------------------------------------------*/
61
62namespace Arcane
63{
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
96class DumpWEnsight7
97: public DumpW
98, public TraceAccessor
99{
100 public:
101
102 static const int int_width = 10;
103 static const int g_line_length = 80;
104
105 public:
106
110 struct EnsightPart
111 {
112 public:
113
114 EnsightPart()
115 : m_type(-1)
116 , m_nb_node(0)
117 {}
118 EnsightPart(int type, Integer nb_node, const String& name)
119 : m_type(type)
120 , m_nb_node(nb_node)
121 , m_name(name)
122 {}
123 EnsightPart(const EnsightPart& part)
124 : m_type(part.m_type)
125 , m_nb_node(part.m_nb_node)
126 , m_name(part.m_name)
127 , m_items(part.m_items)
128 , m_reindex(part.m_reindex)
129 {
130 ;
131 }
132
133 public:
134
135 inline int type() const { return m_type; }
136 inline Integer nbNode() const { return m_nb_node; }
137 inline const String& name() const { return m_name; }
138 inline Array<Item>& items() { return m_items; }
139 inline ConstArrayView<Item> items() const { return m_items; }
140 inline bool hasReindex() const { return !m_reindex.empty(); }
141 inline void setReindex(Integer* reindex)
142 {
143 m_reindex.resize(m_nb_node);
144 for (Integer i = 0; i < m_nb_node; ++i)
145 m_reindex[i] = reindex[i];
146 }
147 inline ConstArrayView<Integer> reindex() const { return m_reindex; }
148
149 private:
150
151 int m_type;
155 UniqueArray<Integer> m_reindex;
156 };
157
161 struct GroupPartInfo
162 {
163 public:
164
166 Integer nbType() const { return m_parts.size(); }
167
168 public:
169
171 : m_group(0)
172 , m_part_id(0)
173 {}
174 GroupPartInfo(ItemGroup grp, Integer id, bool use_degenerated_hexa)
175 : m_group(grp)
176 , m_part_id(id)
177 {
178 m_general_item_types = std::make_unique<VariableItemInt32>(VariableBuildInfo{ m_group.mesh(), "GeneralItemTypesGroup" + m_group.name(), m_group.itemFamily()->name() }, m_group.itemKind());
179 _init(use_degenerated_hexa);
180 }
181 Integer totalNbElement() const
182 {
183 Integer n = 0;
184 for (Integer i = 0; i < nbType(); ++i)
185 n += m_parts[i].items().size();
186 return n;
187 }
188 const EnsightPart& typeInfo(Integer i) const { return m_parts[i]; }
189 EnsightPart& typeInfo(Integer i) { return m_parts[i]; }
190 ItemGroup group() const { return m_group; }
191 Integer partId() const { return m_part_id; }
192 Int32 generalItemTypeId(const Item& item) const
193 {
194 ARCANE_ASSERT(m_general_item_types, ("Cannot question an empty GroupPartInfo"));
195 return (*(m_general_item_types))[item];
196 }
197 EnsightPart* getTypeInfo(int type)
198 {
199 auto ensight_part_element = m_parts_map.find(type);
200 if (ensight_part_element != m_parts_map.end())
201 return ensight_part_element->second;
202 else
203 return nullptr;
204 }
205
206 private:
207
211 bool m_is_polygonal_type_registration_done = false;
212 bool m_is_polyhedral_type_registration_done = false;
214 std::unique_ptr<VariableItemInt32> m_general_item_types = nullptr;
215 using TypeId = int;
216 std::unordered_map<TypeId, EnsightPart*> m_parts_map; // used to handle large number of extra types
217
218 private:
219
220 void _initPartMap()
221 {
222 for (auto& ensight_part : m_parts) {
223 m_parts_map[ensight_part.type()] = &ensight_part;
224 }
225 }
226
227 void _init(bool use_degenerated_hexa)
228 {
229 ItemTypeMng* item_type_mng = m_group.mesh()->itemTypeMng();
230
231 // NOTE: It is important that 'nfaced' type elements
232 // and 'nsided' are contiguous because Ensight must save
233 // their values together
234 m_parts.reserve(ItemTypeMng::nbBasicItemType());
235 m_parts.add(EnsightPart(IT_Line2, 2, "bar2")); // Bar
236 m_parts.add(EnsightPart(IT_Triangle3, 3, "tria3")); // Triangle
237 m_parts.add(EnsightPart(IT_Quad4, 4, "quad4")); // Quandrangle
238 m_parts.add(EnsightPart(IT_Pentagon5, 5, "nsided")); // Pentagone
239 m_parts.add(EnsightPart(IT_Hexagon6, 6, "nsided")); // Hexagone
240 m_parts.add(EnsightPart(IT_Heptagon7, 7, "nsided")); // Heptagone
241 m_parts.add(EnsightPart(IT_Octogon8, 8, "nsided")); // Octogone
242 // Search for other 'polygonal' types
243 for (Integer i_type = ItemTypeMng::nbBuiltInItemType(); i_type < ItemTypeMng::nbBasicItemType(); ++i_type) {
244 ItemTypeInfo* type_info = item_type_mng->typeFromId(i_type);
245 if (type_info->nbLocalNode() == type_info->nbLocalEdge()) { // Polygon found
246 m_parts.add(EnsightPart(i_type, type_info->nbLocalNode(), "nsided"));
247 }
248 }
249 // Add polygons handled in general polyhedral mesh: no types defined
250 Int32 type_id = ItemTypeMng::nbBasicItemType();
251 if (item_type_mng->hasGeneralCells(m_group.mesh())) {
252 if (!m_is_polygonal_type_registration_done) {
253 ENUMERATE_ITEM (iitem, m_group) {
254 ItemWithNodes item = iitem->toItemWithNodes();
255 if (item.nbNode() == item.itemBase().nbEdge()) { // polygon found
256 (*(m_general_item_types))[item] = type_id;
257 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nsided"));
258 }
259 }
260 m_is_polygonal_type_registration_done = true;
261 }
262 }
263 m_parts.add(EnsightPart(IT_Tetraedron4, 4, "tetra4")); // Tetra
264 m_parts.add(EnsightPart(IT_Pyramid5, 5, "pyramid5")); // Pyramide
265 m_parts.add(EnsightPart(IT_Pentaedron6, 6, "penta6")); // Penta
266 m_parts.add(EnsightPart(IT_Hexaedron8, 8, "hexa8")); // Hexa
267 if (use_degenerated_hexa) {
268 m_parts.add(EnsightPart(IT_HemiHexa7, 8, "hexa8")); // HemiHexa7
269 {
270 Integer reindex[8] = { 1, 6, 5, 0, 2, 3, 4, 0 };
271 m_parts[m_parts.size() - 1].setReindex(reindex);
272 }
273 m_parts.add(EnsightPart(IT_HemiHexa6, 8, "hexa8")); // HemiHexa6
274 {
275 Integer reindex[8] = { 0, 1, 3, 5, 0, 2, 3, 4 };
276 m_parts[m_parts.size() - 1].setReindex(reindex);
277 }
278 m_parts.add(EnsightPart(IT_HemiHexa5, 8, "hexa8")); // HemiHexa5
279 {
280 Integer reindex[8] = { 0, 1, 3, 4, 0, 2, 3, 4 };
281 m_parts[m_parts.size() - 1].setReindex(reindex);
282 }
283 m_parts.add(EnsightPart(IT_AntiWedgeLeft6, 8, "hexa8")); // AntiWedgeLeft6
284 {
285 Integer reindex[8] = { 2, 0, 1, 2, 5, 3, 4, 4 };
286 m_parts[m_parts.size() - 1].setReindex(reindex);
287 }
288 m_parts.add(EnsightPart(IT_AntiWedgeRight6, 8, "hexa8")); // AntiWedgeRight6
289 {
290 Integer reindex[8] = { 2, 0, 1, 1, 5, 3, 4, 5 };
291 m_parts[m_parts.size() - 1].setReindex(reindex);
292 }
293 m_parts.add(EnsightPart(IT_DiTetra5, 8, "hexa8")); // DiTetra5
294 {
295 Integer reindex[8] = { 4, 4, 2, 3, 0, 1, 1, 3 };
296 m_parts[m_parts.size() - 1].setReindex(reindex);
297 }
298 }
299 else {
300 m_parts.add(EnsightPart(IT_HemiHexa7, 7, "nfaced")); // HemiHexa7
301 m_parts.add(EnsightPart(IT_HemiHexa6, 6, "nfaced")); // HemiHexa6
302 m_parts.add(EnsightPart(IT_HemiHexa5, 5, "nfaced")); // HemiHexa5
303 m_parts.add(EnsightPart(IT_AntiWedgeLeft6, 6, "nfaced")); // AntiWedgeLeft6
304 m_parts.add(EnsightPart(IT_AntiWedgeRight6, 6, "nfaced")); // AntiWedgeRight6
305 m_parts.add(EnsightPart(IT_DiTetra5, 5, "nfaced")); // DiTetra5
306 }
307 m_parts.add(EnsightPart(IT_Heptaedron10, 10, "nfaced")); // Wedge7
308 m_parts.add(EnsightPart(IT_Octaedron12, 12, "nfaced")); // Wedge8
309 m_parts.add(EnsightPart(IT_Enneedron14, 14, "nfaced")); // Wedge9
310 m_parts.add(EnsightPart(IT_Decaedron16, 16, "nfaced")); // Wedge10
311 // Search for other 'polyhedral' types
312 for (Integer i_type = ItemTypeMng::nbBuiltInItemType(); i_type < ItemTypeMng::nbBasicItemType(); ++i_type) {
313 ItemTypeInfo* type_info = item_type_mng->typeFromId(i_type);
314 if (type_info->nbLocalNode() != type_info->nbLocalEdge()) { // Polyhedron found
315 m_parts.add(EnsightPart(i_type, type_info->nbLocalNode(), "nfaced"));
316 }
317 }
318 // Add polyhedra handled in general polyhedral mesh: no types defined
319 if (item_type_mng->hasGeneralCells(m_group.mesh())) {
320 if (!m_is_polyhedral_type_registration_done) {
321 ENUMERATE_ITEM (iitem, m_group) {
322 ItemWithNodes item = iitem->toItemWithNodes();
323 if (item.nbNode() == 1)
324 (*(m_general_item_types))[item] = IT_Vertex;
325 else if (item.nbNode() == 2)
326 (*(m_general_item_types))[item] = IT_Line2;
327 else if (item.nbNode() != item.itemBase().nbEdge()) { // polyhedron found
328 (*(m_general_item_types))[item] = type_id;
329 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nfaced"));
330 }
331 }
332 m_is_polyhedral_type_registration_done = true;
333 }
334 }
335 // if extra types are used, init a EnsightPart map to optimize GroupPartInfo fill
337 _initPartMap();
338 }
339 }
340 };
341
342 public:
343
344 //void writeFileString(ostream& o,ConstCString str);
345 void writeFileString(std::ostream& o, const String& str);
346 void writeFileInt(std::ostream& o, int value);
347 void writeFileDouble(std::ostream& o, double value);
348 Integer writeDoubleSize() const;
349 Integer writeIntSize() const;
350 void writeFileArray(std::ostream& o, IntegerConstArrayView value);
351 bool isBinary() const { return m_is_binary; }
352
353 public:
354
368 class WriteBase
369 {
370 public:
371
372 explicit WriteBase(DumpWEnsight7& dw)
373 : m_dw(dw)
374 {}
375 WriteBase(DumpWEnsight7& dw, GroupIndexTable* idx)
376 : m_dw(dw)
377 , m_idx(idx)
378 {}
379 WriteBase(const WriteBase& wb)
380 : m_dw(wb.m_dw)
381 , m_idx(wb.m_idx)
382 {}
383 virtual ~WriteBase() {}
384
385 public:
386
387 virtual WriteBase* clone() = 0;
388 virtual void begin() { init(); }
389 virtual void end() {}
390 virtual void write(ConstArrayView<Item> items) = 0;
391
392 virtual void init()
393 {
394 m_ofile.precision(5);
395 m_ofile.flags(std::ios::scientific);
396 }
397 virtual void putValue(std::ostream& ofile)
398 {
399 ofile << m_ofile.str();
400 }
401 std::ostream& stream() { return m_ofile; }
402
403 protected:
404
405 DumpWEnsight7& m_dw;
406 std::ostringstream m_ofile;
407 GroupIndexTable* m_idx = nullptr;
408 };
409
413 template <typename FromType>
414 class WriteDouble
415 : public WriteBase
416 {
417 public:
418
419 WriteDouble(DumpWEnsight7& dw, ConstArrayView<FromType> ptr, GroupIndexTable* idx = nullptr)
420 : WriteBase(dw, idx)
421 , m_ptr(ptr)
422 {}
423 WriteDouble(const WriteDouble& wd)
424 : WriteBase(wd)
425 , m_ptr(wd.m_ptr)
426 {}
427
428 WriteBase* clone() override { return new WriteDouble(*this); }
429
430 public:
431
433
434 public:
435
436 inline void write(Integer index)
437 {
438 if (m_idx) {
439 int reindex = (*m_idx)[index];
440 if (reindex < 0)
441 ARCANE_FATAL("Invalid index");
442 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[reindex])));
443 }
444 else
445 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[index])));
446 }
447
448 void write(ConstArrayView<Item> items) override
449 {
450 for (Item e : items) {
451 write(e.localId());
452 }
453 }
454 };
455
459 template <typename FromType>
460 class WriteArrayDouble
461 : public WriteBase
462 {
463 public:
464
465 WriteArrayDouble(DumpWEnsight7& dw, ConstArray2View<FromType> ptr, const Integer idim2,
466 GroupIndexTable* idx = nullptr)
467 : WriteBase(dw, idx)
468 , m_ptr(ptr)
469 , m_idim2(idim2)
470 {}
471 WriteArrayDouble(const WriteArrayDouble& wd)
472 : WriteBase(wd)
473 , m_ptr(wd.m_ptr)
474 , m_idim2(wd.m_idim2)
475 {}
476
477 WriteBase* clone() override { return new WriteArrayDouble(*this); }
478
479 public:
480
482 const Integer m_idim2;
483
484 public:
485
486 void write(Integer index)
487 {
488 if (m_idx) {
489 int reindex = (*m_idx)[index];
490 if (reindex < 0)
491 ARCANE_FATAL("Invalid index");
492 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[reindex][m_idim2])));
493 }
494 else
495 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[index][m_idim2])));
496 }
497
498 void write(ConstArrayView<Item> items) override
499 {
500 for (Item e : items) {
501 write(e.localId());
502 }
503 }
504 };
505
509
513 class WriteReal3
514 : public WriteBase
515 {
516 public:
517
518 WriteReal3(DumpWEnsight7& dw, ConstArrayView<Real3> ptr, GroupIndexTable* idx = nullptr)
519 : WriteBase(dw, idx)
520 , m_ptr(ptr)
521 {}
522 WriteReal3(const WriteReal3& wd)
523 : WriteBase(wd)
524 , m_ptr(wd.m_ptr)
525 {}
526
527 WriteBase* clone() override { return new WriteReal3(*this); }
528
529 public:
530
532
533 public:
534
535 void begin() override
536 {
537 _init();
538 xostr.precision(5);
539 xostr.flags(std::ios::scientific);
540 yostr.precision(5);
541 yostr.flags(std::ios::scientific);
542 zostr.precision(5);
543 zostr.flags(std::ios::scientific);
544 }
545
546 void write(Integer index)
547 {
548 if (m_idx) {
549 int reindex = (*m_idx)[index];
550 if (reindex < 0)
551 ARCANE_FATAL("Invalid index");
552 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[reindex].x));
553 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[reindex].y));
554 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[reindex].z));
555 }
556 else {
557 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[index].x));
558 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[index].y));
559 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[index].z));
560 }
561 }
562
563 void write(ConstArrayView<Item> items) override
564 {
565 for (Item i : items) {
566 write(i.localId());
567 }
568 }
569
570 void end() override
571 {
572 m_ofile << xostr.str();
573 m_ofile << yostr.str();
574 m_ofile << zostr.str();
575 }
576
577 public:
578
579 std::ostringstream xostr;
580 std::ostringstream yostr;
581 std::ostringstream zostr;
582
583 private:
584
585 void _init()
586 {
587 init();
588 }
589 };
590
594 class WriteArrayReal3
595 : public WriteBase
596 {
597 public:
598
599 WriteArrayReal3(DumpWEnsight7& dw, ConstArray2View<Real3> ptr,
600 Integer idim2, GroupIndexTable* idx = nullptr)
601 : WriteBase(dw, idx)
602 , m_ptr(ptr)
603 , m_idim2(idim2)
604 {}
605 WriteArrayReal3(const WriteArrayReal3& wd)
606 : WriteBase(wd)
607 , m_ptr(wd.m_ptr)
608 , m_idim2(wd.m_idim2)
609 {}
610
611 WriteBase* clone() override { return new WriteArrayReal3(*this); }
612
613 public:
614
616 const Integer m_idim2;
617
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;
756 Integer m_fileset_size;
757
758 private:
759 private:
760
762 static const Integer m_max_prots_digit = 6;
763
764 private:
765 private:
766
767 bool _isValidVariable(IVariable&) const;
768 void _createCaseFile();
769 void _buildFileName(const String& varname, String& filename);
770 void _buildPartDirectory();
771 void _writeWildcardFilename(std::ostream& ofile, const String& filename, char joker = '*');
772 int _fileOuttype() const;
773 void _writeFileHeader(std::ostream& o, bool write_c_binary);
774 bool _isNewBlocFile() const;
775
776 void _computeGroupParts(ItemGroupList list_group, Integer& partid);
777 void _saveGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
778 ConstArrayView<Integer> nodes_index, WriteBase& wf);
779 void _saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
780 WriteBase& from_func);
781 bool _isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind);
782
784 template <typename T>
787 template <typename T>
790 template <typename T>
792};
793
794/*---------------------------------------------------------------------------*/
795/*---------------------------------------------------------------------------*/
796
797extern "C++" DumpW*
798createEnsight7(ISubDomain* m, const String& f,
800 VariableCollection variables,
801 ItemGroupCollection groups,
802 bool is_binary, bool is_parallel_output, Integer fileset_size,
803 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
804{
805 return new DumpWEnsight7(m->defaultMesh(), f, times, variables, groups, is_binary,
806 is_parallel_output, fileset_size, use_degenerated_hexa,
807 force_first_geometry, save_uids);
808}
809
810extern "C++" DumpW*
811createEnsight7(IMesh* m, const String& f,
812 ConstArrayView<Real> times,
813 VariableCollection variables,
814 ItemGroupCollection groups,
815 bool is_binary, bool is_parallel_output, Integer fileset_size,
816 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
817{
818 return new DumpWEnsight7(m, f, times, variables, groups, is_binary,
819 is_parallel_output, fileset_size, use_degenerated_hexa,
820 force_first_geometry, save_uids);
821}
822
823/*---------------------------------------------------------------------------*/
824/*---------------------------------------------------------------------------*/
825
826DumpWEnsight7::
827DumpWEnsight7(IMesh* mesh, const String& filename, ConstArrayView<Real> times,
828 VariableCollection variables, ItemGroupCollection groups,
829 bool is_binary, bool is_parallel_output, Integer fileset_size,
830 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
831: TraceAccessor(mesh->traceMng())
832, m_mesh(mesh)
833, m_parallel_mng(mesh->parallelMng())
834, m_base_directory(filename)
835, m_times(times)
836, m_save_variables(variables.clone())
837, m_save_groups(groups.enumerator())
838, m_is_binary(is_binary)
839// , m_is_binary(false)
840, m_is_master(true)
841, m_is_parallel_output(is_parallel_output)
842, m_use_degenerated_hexa(use_degenerated_hexa)
843, m_force_first_geometry(force_first_geometry)
844, m_save_uids(save_uids)
845, m_total_nb_element(0)
846, m_total_nb_group(0)
847, m_fileset_size(fileset_size)
848{
849 //m_is_binary = true;
850 //m_fileset_size = 0;
851
852 if (m_times.empty()) {
853 m_times.resize(1);
854 m_times[0] = 0.;
855 }
856
857 //_createCaseFile();
858}
859
860/*---------------------------------------------------------------------------*/
861/*---------------------------------------------------------------------------*/
862
863DumpWEnsight7::
864~DumpWEnsight7()
865{
866 std::for_each(std::begin(m_parts), std::end(m_parts), Deleter());
867}
868
869/*---------------------------------------------------------------------------*/
870/*---------------------------------------------------------------------------*/
871
872/*---------------------------------------------------------------------------*/
873/*---------------------------------------------------------------------------*/
874
893void DumpWEnsight7::
894_computeGroupParts(ItemGroupList list_group, Integer& partid)
895{
896 for (ItemGroupList::Enumerator i(list_group); ++i;) {
897 ItemGroup grp(*i);
898 if (grp.null()) // The group is not of the desired type.
899 continue;
900 if (!grp.isOwn()) // If possible, take the own element group
901 grp = grp.own();
902 // Since Ensight 7.6, empty groups are allowed
903 // and they are necessary when the mesh evolves over time
904 //if (grp.empty()) // The group is empty
905 //continue;
906 GroupPartInfo* gpi = new GroupPartInfo(grp, partid, m_use_degenerated_hexa);
907 m_parts.add(gpi);
908 ++partid;
909
910 GroupPartInfo& current_grp = *gpi;
911 // Now we must determine how many elements of each type
912 // ensight (tria3, hexa8, ...) are in the group.
913 // two versions: if extra item types are added switch to an optimized version
914 // (a large amount of types may be added, equal to the number of elements)
916 {
917 debug(Trace::High) << "Using standard group part building algo";
918 if (!grp.mesh()->itemTypeMng()->hasGeneralCells(grp.mesh())) { // classical types
919 for (Integer z = 0; z < current_grp.nbType(); ++z) {
920 EnsightPart& type_info = current_grp.typeInfo(z);
921 Array<Item>& items = type_info.items();
922 Integer nb_of_type = 0;
923 Integer type_to_seek = type_info.type();
924 ENUMERATE_ITEM (i2, grp) {
925 const Item& e = *i2;
926 if (e.type() == type_to_seek)
927 ++nb_of_type;
928 }
929 items.resize(nb_of_type);
930 debug(Trace::High) << "Group " << grp.name() << " has "
931 << nb_of_type << " items of type " << type_info.name();
932 Integer index = 0;
933 ENUMERATE_ITEM (iz, grp) {
934 Item mi = *iz;
935 if (mi.type() == type_to_seek) {
937 items[index] = e;
938 ++index;
939 }
940 }
941 }
942 }
943 else { // polyhedral mesh items
944 ENUMERATE_ITEM (i2, grp) {
945 const Item& item = *i2;
946 auto item_type = current_grp.generalItemTypeId(item);
947 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
948 if (!ensight_part)
949 continue;
950 ItemWithNodes item_wn = item.toItemWithNodes();
951 ensight_part->items().add(item_wn);
952 }
953 }
954 }
955 else // extra types are added (may have as many types as items...)
956 // Propose an optimized version when many types exist (use of .format file)
957 {
958 debug(Trace::High) << "Using extra type group part building algo";
959 // work only on face and cell groups
960 auto item_kind = grp.itemKind();
961 if (item_kind == IK_Cell || item_kind == IK_Face) {
962 ENUMERATE_ITEM (item, grp) {
963 auto item_type = item->type();
964 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
965 if (!ensight_part)
966 continue;
967 ItemWithNodes item_wn = item->toItemWithNodes();
968 ensight_part->items().add(item_wn); // few elements are added
969 }
970 }
971 }
972 }
973}
974
975/*---------------------------------------------------------------------------*/
976/*---------------------------------------------------------------------------*/
997void DumpWEnsight7::
998_saveGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
999 ConstArrayView<Integer> nodes_index, WriteBase& wf)
1000{
1001 ItemGroup igrp = ensight_grp.group();
1002
1003 writeFileString(ofile, "part");
1004 writeFileInt(ofile, ensight_grp.partId());
1005 if (isParallelOutput()) {
1006 // In the case of parallel output, prefix the group name with the
1007 // CPU number.
1008 std::ostringstream ostr;
1009 ostr << igrp.name().localstr() << "_CPU" << rank();
1010 writeFileString(ofile, ostr.str().c_str());
1011 }
1012 else
1013 writeFileString(ofile, igrp.name());
1014
1015 wf.putValue(ofile);
1016
1017 IntegerUniqueArray array_id(256);
1018
1019 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1020 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1021 ConstArrayView<Item> items = type_info.items();
1022 Integer nb_sub_part = items.size();
1023 if (nb_sub_part == 0)
1024 continue;
1025
1026 String type_name = type_info.name();
1027 writeFileString(ofile, type_name);
1028
1029 writeFileInt(ofile, nb_sub_part);
1030
1031#if 0
1032 // Save the uniqueId() of the entities
1033 for( ConstArrayView<Item>::const_iter i(items); i(); ++i ){
1034 Item mi = *i;
1035 writeFileInt(ofile,mi.uniqueId()+1);
1036 }
1037#endif
1038
1039 if (type_name == "nfaced") {
1040 // Special handling for non-standard cells
1041 // Since our faces are not oriented relative to a
1042 // cell, we use the local connectivity of each face.
1043 // 1. Save the number of faces for each element
1044 {
1045 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1046 // All elements have the same number of faces
1047 Item mi = *items.data();
1048 Cell cell = mi.toCell();
1049 Integer nb_face = cell.nbFace();
1050 for (Integer z = 0; z < nb_sub_part; ++z)
1051 writeFileInt(ofile, nb_face);
1052 }
1053 else { // mesh has general items
1054 // All items do not have the same face number
1055 for (Item mi : items) {
1056 writeFileInt(ofile, mi.toCell().nbFace());
1057 }
1058 }
1059 }
1060 // 2. Save for each element, the number of nodes for each
1061 // of these faces
1062 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1063 for (Item mi : items) {
1064 const ItemTypeInfo* item_info = mi.typeInfo();
1065 Integer nb_face = item_info->nbLocalFace();
1066 for (Integer z = 0; z < nb_face; ++z)
1067 writeFileInt(ofile, item_info->localFace(z).nbNode());
1068 }
1069 }
1070 else { // mesh has general items
1071 for (Item mi : items) {
1072 Cell cell = mi.toCell();
1073 for (Face face : cell.faces()) {
1074 writeFileInt(ofile, face.nbNode());
1075 }
1076 }
1077 }
1078 // 3. Save for each face of each element the list of these
1079 // nodes
1080 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1081 for (Item item : items) {
1082 Cell cell(item.toCell());
1083 const ItemTypeInfo* item_info = cell.typeInfo();
1084 //Cell cell = mi.toCell();
1085 Integer nb_face = item_info->nbLocalFace();
1086 for (Integer z = 0; z < nb_face; ++z) {
1087 const ItemTypeInfo::LocalFace& local_face = item_info->localFace(z);
1088 Integer nb_node = local_face.nbNode();
1089 array_id.resize(nb_node);
1090 for (Integer y = 0; y < nb_node; ++y) {
1091 // Node direction inversion
1092 // A priori, there is a bug in Ensight (7.4.1(g)) concerning the
1093 // intersections of this type of elements with Ensight
1094 // objects (plane, sphere, ...). Regardless of the orientation
1095 // of the retained faces, the behavior is not correct.
1096 array_id[y] = nodes_index[cell.node(local_face.node(y)).localId()];
1097 }
1098 writeFileArray(ofile, array_id);
1099 }
1100 }
1101 }
1102 else { // mesh has general items
1103 for (Item item : items) {
1104 Cell cell = item.toCell();
1105 Integer nb_face = cell.nbFace();
1106 for (Integer z = 0; z < nb_face; ++z) {
1107 const Face local_face = cell.face(z);
1108 Integer nb_node = local_face.nbNode();
1109 array_id.resize(nb_node);
1110 for (Integer y = 0; y < nb_node; ++y) {
1111 array_id[y] = nodes_index[local_face.node(y).localId()];
1112 }
1113 writeFileArray(ofile, array_id);
1114 }
1115 }
1116 }
1117 }
1118 else if (type_name == "nsided") {
1119 // Special handling for faces with more than 4 nodes:
1120
1121 // 1. Save for each element, the number of its nodes
1122 //cerr << "** NSIDED ELEMENT\n";
1123 for (Item mi : items) {
1125 Integer nb_node = e.nbNode();
1126 writeFileInt(ofile, nb_node);
1127 }
1128 // 2. Save for each element the list of its nodes
1129 for (Item mi : items) {
1131 Integer nb_node = e.nbNode();
1132 array_id.resize(nb_node);
1133 for (Integer z = 0; z < nb_node; ++z) {
1134 array_id[z] = nodes_index[e.node(z).localId()];
1135 }
1136 writeFileArray(ofile, array_id);
1137 }
1138 }
1139 else {
1140 // General case
1141
1142 Integer nb_node = type_info.nbNode();
1143 array_id.resize(nb_node);
1144
1145 // Save the elements.
1146
1147 // Save the connectivity of the elements
1148 if (type_info.hasReindex()) {
1149 ConstArrayView<Integer> reindex = type_info.reindex();
1150 for (Item mi : items) {
1152 for (Integer j = 0; j < nb_node; ++j) {
1153 array_id[j] = nodes_index[e.node(reindex[j]).localId()];
1154 }
1155 writeFileArray(ofile, array_id);
1156 }
1157 }
1158 else { // no reindex
1159 for (Item mi : items) {
1161 for (Integer j = 0; j < nb_node; ++j) {
1162 array_id[j] = nodes_index[e.node(j).localId()];
1163 }
1164 writeFileArray(ofile, array_id);
1165 }
1166 }
1167 }
1168 }
1169}
1170
1171/*---------------------------------------------------------------------------*/
1172/*---------------------------------------------------------------------------*/
1196void DumpWEnsight7::
1197_saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
1198 WriteBase& from_func)
1199{
1200 ItemGroup igrp = ensight_grp.group();
1201
1202 writeFileString(ofile, "part");
1203 writeFileInt(ofile, ensight_grp.partId());
1204
1205 // Elements of the same type (especially 'nfaced', 'haxa8', or 'nsided')
1206 // must be written in a single block (thus unified type label).
1207 // Furthermore, vector data must be interleaved.
1208 String last_type_name;
1210 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1211 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1212 ConstArrayView<Item> items(type_info.items());
1213 Integer nb_sub_part = items.size();
1214 if (nb_sub_part == 0)
1215 continue;
1216 String type_name = type_info.name();
1217 if (type_name != last_type_name) {
1218 // Close the previous write
1219 if (func.get()) {
1220 func->end();
1221 func->putValue(ofile);
1222 }
1223 last_type_name = type_name;
1224 writeFileString(ofile, type_name);
1225 func = from_func.clone();
1226 func->begin();
1227 }
1228
1229 // Save the variables.
1230 func->write(items);
1231 }
1232
1233 // Final closure
1234 if (func.get()) {
1235 func->end();
1236 func->putValue(ofile);
1237 }
1238}
1239
1240/*---------------------------------------------------------------------------*/
1241/*---------------------------------------------------------------------------*/
1242
1243void DumpWEnsight7::
1244writeFileInt(std::ostream& o, int value)
1245{
1246 if (m_is_binary) {
1247 o.write((const char*)&value, sizeof(int));
1248 }
1249 else {
1250 o.width(DumpWEnsight7::int_width);
1251 o << value;
1252 o << '\n';
1253 }
1254}
1255
1256/*---------------------------------------------------------------------------*/
1257/*---------------------------------------------------------------------------*/
1258
1259Integer DumpWEnsight7::
1260writeIntSize() const
1261{
1262 if (m_is_binary)
1263 return sizeof(int);
1264 return DumpWEnsight7::int_width + 1;
1265}
1266
1267/*---------------------------------------------------------------------------*/
1268/*---------------------------------------------------------------------------*/
1269
1270void DumpWEnsight7::
1271writeFileDouble(std::ostream& o, double value)
1272{
1273 if (m_is_binary) {
1274 float fvalue = (float)(value);
1275 o.write((const char*)&fvalue, sizeof(float));
1276 }
1277 else {
1278 o.width(12);
1279 o.precision(5);
1280 o.flags(std::ios::scientific);
1281 o << value;
1282 o << '\n';
1283 }
1284}
1285
1286/*---------------------------------------------------------------------------*/
1287/*---------------------------------------------------------------------------*/
1288
1289Integer DumpWEnsight7::
1290writeDoubleSize() const
1291{
1292 Integer float_size = (Integer)(sizeof(float));
1293 return (m_is_binary) ? float_size : (12 + 1);
1294}
1295
1296/*---------------------------------------------------------------------------*/
1297/*---------------------------------------------------------------------------*/
1298
1299void DumpWEnsight7::
1300writeFileArray(std::ostream& o, IntegerConstArrayView value)
1301{
1302 if (m_is_binary) {
1303 o.write((const char*)value.data(), sizeof(Integer) * value.size());
1304 }
1305 else {
1306 for (Integer i = 0, s = value.size(); i < s; ++i) {
1307 o.width(DumpWEnsight7::int_width);
1308 o << value[i];
1309 }
1310 o << '\n';
1311 }
1312}
1313
1314/*---------------------------------------------------------------------------*/
1315/*---------------------------------------------------------------------------*/
1316
1317void DumpWEnsight7::
1318writeFileString(std::ostream& o, const String& str)
1319{
1320 if (m_is_binary) {
1321 char buf[g_line_length];
1322 for (int i = 0; i < g_line_length; ++i)
1323 buf[i] = '\0';
1324 CStringUtils::copyn(buf, str.localstr(), g_line_length);
1325 buf[g_line_length - 1] = '\0';
1326 o.write(buf, g_line_length);
1327 }
1328 else {
1329 o << str << '\n';
1330 }
1331}
1332
1333/*---------------------------------------------------------------------------*/
1334/*---------------------------------------------------------------------------*/
1335
1336void DumpWEnsight7::
1337_writeFileHeader(std::ostream& o, bool write_c_binary)
1338{
1339 if (m_is_master) {
1340 if (_isNewBlocFile() && m_is_binary && write_c_binary)
1341 writeFileString(o, "C Binary");
1342 if (m_fileset_size != 0) {
1343 std::ostringstream ostr;
1344 ostr << "BEGIN TIME STEP "
1345 << "# " << m_times.size();
1346 writeFileString(o, ostr.str().c_str());
1347 }
1348 }
1349}
1350
1351/*---------------------------------------------------------------------------*/
1352/*---------------------------------------------------------------------------*/
1360class DumpWEnsight7OutFile
1361{
1362 public:
1363
1364 DumpWEnsight7OutFile(DumpWEnsight7& dw, const String& filename, int outtype)
1365 : m_dw(dw)
1366 , m_filename(filename)
1367 , m_is_master(dw.isMasterProcessor())
1368 , m_is_parallel_output(dw.isParallelOutput())
1369 , m_stream(0)
1370 , m_filestream(0)
1371 {
1372 if (m_is_master) {
1373 m_filestream = new std::ofstream(filename.localstr(), (std::ios_base::openmode)outtype);
1374 m_stream = &m_strstream;
1375 if (!(*m_filestream))
1376 m_dw.warning() << "Unable to open file " << filename;
1377 }
1378 else {
1379 // TODO attention to memory leaks.
1380 m_stream = &m_strstream;
1381 }
1382 ARCANE_CHECK_PTR(m_stream);
1383 }
1384 ~DumpWEnsight7OutFile()
1385 {
1386 delete m_filestream;
1387 }
1388
1389 public:
1390
1391 void syncFile()
1392 {
1393 IParallelMng* parallel_mng = m_dw.parallelMng();
1394 if (m_is_master) {
1395 ARCANE_CHECK_PTR(m_filestream);
1396 ARCANE_CHECK_PTR(m_strstream);
1397 //Integer pos = m_strstream->tellp();
1398 (*m_filestream) << m_strstream.str();
1399 }
1400 if (m_is_parallel_output) {
1401 if (m_is_master) {
1402 ARCANE_CHECK_PTR(m_filestream);
1403
1404 // The master iterates through all processors and requests from each
1405 // the size of each save, and if it is not zero,
1406 // receives the message.
1407 Integer nb_proc = parallel_mng->commSize();
1408 UniqueArray<int> len_array(1);
1409 UniqueArray<Byte> str_array;
1410 for (Integer i = 1; i < nb_proc; ++i) {
1411 m_dw.debug(Trace::High) << "Waiting for length of processor " << i;
1412 parallel_mng->recv(len_array, i);
1413 Integer len = len_array[0];
1414 m_dw.debug(Trace::High) << "Length of processor " << i << " : " << len;
1415 if (len != 0) {
1416 str_array.resize(len);
1417 m_dw.debug(Trace::High) << "Waiting for receving geom of processor " << i;
1418 parallel_mng->recv(str_array, i);
1419 m_dw.debug(Trace::High) << "Receving geom of processor " << i;
1420 m_filestream->write((const char*)str_array.data(), str_array.size());
1421 }
1422 }
1423 }
1424 else {
1425 ARCANE_CHECK_PTR(m_strstream);
1426 // A slave sends to the master processor (currently processor 0)
1427 // the size of its data and then the data itself.
1428 // It is important to take the length of the string returned by m_strstream
1429 // and not just c_str() because the stream might contain information
1430 // in binary format, and we would stop at the first zero.
1431 UniqueArray<int> len_array(1);
1432 std::string str = m_strstream.str();
1433 Integer len = arcaneCheckArraySize(str.length());
1434 UniqueArray<Byte> bytes(len);
1435 {
1436 // Copy the string \a str into bytes
1437 Integer index = 0;
1438 for (ConstIterT<std::string> i(str); i(); ++i, ++index)
1439 bytes[index] = *i;
1440 }
1441 m_dw.debug(Trace::High) << "Not a master. " << m_filename << " size = " << len;
1442 //Integer len = m_strstream->tellp();
1443 //Integer len = str.length();
1444 len_array[0] = len;
1445 m_dw.debug(Trace::High) << "Sending length for processor 0";
1446 parallel_mng->send(len_array, 0);
1447 if (len != 0) {
1448 //UniqueArray<char> str_array(len);
1449 //std::string s = m_strstream->str();
1450 //platform::stdMemcpy(str_array.begin(),s.c_str(),s.length());
1451 m_dw.debug(Trace::High) << "Sending data for processor 0";
1452 parallel_mng->send(bytes, 0); //str.c_str())__array,0);
1453 //parallel_mng->send(str_array,0);
1454 }
1455 }
1456 }
1457 if (m_is_master)
1458 if (!m_dw.isOneFilePerTime())
1459 m_dw.writeFileString(*m_filestream, "END TIME STEP");
1460 }
1461
1462 public:
1463
1464 std::ostream& operator()() { return *m_stream; }
1465
1466 private:
1467
1468 DumpWEnsight7& m_dw;
1469 String m_filename;
1470 bool m_is_master;
1471 bool m_is_parallel_output;
1472 std::ostream* m_stream;
1473 std::ostringstream m_strstream;
1474 std::ofstream* m_filestream;
1475};
1476
1477/*---------------------------------------------------------------------------*/
1478/*---------------------------------------------------------------------------*/
1479
1480/*---------------------------------------------------------------------------*/
1481/*---------------------------------------------------------------------------*/
1482
1484beginWrite()
1485{
1486 String buf = m_base_directory.file("ensight.case");
1487
1488 IParallelMng* parallel_mng = m_parallel_mng;
1489 bool is_parallel = parallel_mng->isParallel();
1490 m_is_master = true;
1491 if (is_parallel && m_is_parallel_output)
1492 m_is_master = parallel_mng->commRank() == 0;
1493
1494 // Determines and creates the directory where the outputs will be written
1495 // for this iteration.
1497
1498 IMesh* mesh = m_mesh;
1499
1500 // Retrieves the list of groups and assigns each a unique identifier
1501 // unique for Ensight (part). The identifier number starts at 2, number 1
1502 // is for the node list
1503 {
1504
1505 ItemGroupList list_group;
1506 // If the list of groups to save is empty, save all groups.
1507 // Otherwise, save only the specified groups.
1508 Integer nb_group = m_save_groups.count();
1509 if (nb_group == 0)
1510 list_group.clone(mesh->groups());
1511 else
1512 list_group.clone(m_save_groups);
1513 // Looks at the list of partial variables, and adds their group to the list
1514 // of groups to save.
1515 for (VariableList::Enumerator ivar(m_save_variables); ++ivar;) {
1516 IVariable* var = *ivar;
1517 if (!var->isPartial())
1518 continue;
1519 ItemGroup var_group = var->itemGroup();
1520 if (!list_group.contains(var_group))
1521 list_group.add(var_group);
1522 }
1523 Integer partid = 1;
1525 partid += parallel_mng->commRank() * list_group.count();
1526
1527 _computeGroupParts(list_group, partid);
1528
1529 // Retrieves the total number of elements in the groups.
1530 Integer total_nb_element = 0;
1531 m_total_nb_group = 0;
1532 for (auto i : m_parts) {
1533 total_nb_element += i->totalNbElement();
1535 }
1536
1537 m_total_nb_element = total_nb_element;
1538 debug() << "Total nb element " << m_total_nb_element << " and group " << m_total_nb_group;
1539 debug() << "Add nodes " << mesh->nbNode();
1540 }
1541
1542 // Saves the geometry in Ensight7 gold format
1543 if (!(m_times.size() > 1 && m_force_first_geometry)) {
1544 String filename;
1545 _buildFileName("ensight.geo", filename);
1546
1547 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1548
1549 _writeFileHeader(dw_ofile(), true);
1550
1551 if (m_is_master) {
1552 writeFileString(dw_ofile(), "Output ensight test");
1553 writeFileString(dw_ofile(), "File description");
1554 writeFileString(dw_ofile(), "node id assign");
1555 writeFileString(dw_ofile(), "element id assign");
1556 }
1557
1558 IMesh* mesh = m_mesh;
1559 NodeGroup all_nodes = mesh->allNodes();
1560
1561 // This array is used for each cell entity, face, or edge to
1562 // reference its nodes relative to the coordinate array
1563 // used by Ensight. The first element of this array has index 1
1564 UniqueArray<Integer> all_nodes_index(mesh->itemFamily(IK_Node)->maxLocalId());
1565 all_nodes_index.fill(0);
1566
1567 UniqueArray<Real3> coords_backup;
1568 ConstArrayView<Real3> coords_array;
1569 if (mesh->parentMesh()) {
1570 SharedVariableNodeReal3 nodes_coords(mesh->sharedNodesCoordinates());
1571 coords_backup.resize(mesh->nodeFamily()->maxLocalId());
1572 ENUMERATE_NODE (i_item, all_nodes) {
1573 coords_backup[i_item.localId()] = nodes_coords[i_item];
1574 }
1575 coords_array = coords_backup.view();
1576 }
1577 else {
1578 VariableNodeReal3& nodes_coords(mesh->toPrimaryMesh()->nodesCoordinates());
1579 coords_array = ConstArrayView<Real3>(nodes_coords.asArray());
1580 }
1581
1582 WriteReal3 wf(*this, coords_array);
1583 {
1584 wf.init();
1585 writeFileString(wf.stream(), "coordinates");
1586 writeFileInt(wf.stream(), all_nodes.size());
1587 wf.begin();
1588
1589 // Stores the local indices for Ensight
1590 {
1591 Integer ensight_index = 1;
1592 ENUMERATE_ITEM (i_item, all_nodes) {
1593 const Item& item = *i_item;
1594 all_nodes_index[item.localId()] = ensight_index;
1595 ++ensight_index;
1596 }
1597 }
1598
1599 // Displays the unique node numbers
1600#if 0
1601 {
1602 ENUMERATE_ITEM(i_item,all_nodes){
1603 const Item& item = *i_item;
1604 writeFileInt(wf.stream(),item.uniqueId()+1);
1605 }
1606 }
1607#endif
1608 // Displays the coordinates of each node
1609 ENUMERATE_ITEM (i_item, all_nodes) {
1610 const Item& item = *i_item;
1611 wf.write(item.localId());
1612 }
1613 wf.end();
1614 }
1615
1616 for (const GroupPartInfo* part : m_parts)
1617 _saveGroup(dw_ofile(), *part, all_nodes_index, wf);
1618
1619 dw_ofile.syncFile();
1620 }
1621}
1622
1623/*---------------------------------------------------------------------------*/
1624/*---------------------------------------------------------------------------*/
1625
1627endWrite()
1628{
1629 // Saving unique identifiers
1630 if (m_save_uids) {
1632 ENUMERATE_CELL (icell, m_mesh->allCells()) {
1633 cell_uids[icell] = (Real)(icell->uniqueId().asInt64());
1634 }
1635 IVariable* cell_uid_var = cell_uids.variable();
1636 m_save_variables.add(cell_uid_var);
1637 cell_uid_var->setUsed(true);
1638 cell_uid_var->notifyBeginWrite();
1639 write(cell_uid_var, cell_uid_var->data());
1640
1641 // GG: NOTE: I am not sure this works well.
1642 //TODO: remove the use of two variables
1644 UniqueArray<Real> node_uids2(m_mesh->nodeFamily()->allItems().size());
1645 ENUMERATE_NODE (inode, m_mesh->allNodes()) {
1646 node_uids[inode] = inode->uniqueId().asInt32();
1647 node_uids2[inode.index()] = (Real)inode->uniqueId().asInt64();
1648 }
1649
1650 IVariable* node_uid_var = node_uids.variable();
1651 m_save_variables.add(node_uid_var);
1652 node_uid_var->setUsed(true);
1653 _writeRealValT<Real>(*node_uid_var, node_uids2); // work around bug for node variables
1654 }
1655
1656 String buf = m_base_directory.file("ensight.case");
1657
1658 // Only a master processor generates a 'case' file
1659 if (m_is_master) {
1660
1661 m_case_file.open(buf.localstr());
1662
1663 if (!m_case_file)
1664 warning() << "Unable to write to file: <" << buf << "> error: " << m_case_file.rdstate();
1665
1666 debug() << "** Exporting data to " << m_base_directory.path();
1667 m_case_file << "FORMAT\ntype: ensight gold\n";
1668
1669 m_case_file << "\nGEOMETRY\n";
1670 m_case_file << "model: 1";
1671 if (m_fileset_size != 0)
1672 m_case_file << " 1 ";
1673 if (m_force_first_geometry)
1674 _writeWildcardFilename(m_case_file, "ensight.geo", '0');
1675 else
1676 _writeWildcardFilename(m_case_file, "ensight.geo", '*');
1677 //m_case_file << " [change_coords_only]\n";
1678 m_case_file << "\n";
1679
1680 m_case_file << "\nVARIABLE\n";
1681 m_case_file << m_case_file_variables.str();
1682
1683 // Saving in time. For paraview, it must be placed after the variables
1684 m_case_file << "\nTIME\n";
1685 m_case_file << "time set: 1\n";
1686 m_case_file << "number of steps: " << m_times.size() << '\n';
1687 m_case_file << "filename start number: 0\n";
1688 m_case_file << "filename increment: 1\n";
1689 m_case_file << "time values:\n";
1690 // Be careful not to exceed 79 characters per line
1691 // allowed by Ensight. To be sure, we only write one time step
1692 // per line. The times are saved with the maximum number of significant digits
1693 // because Ensight does not like two times being equal.
1694 std::streamsize old_precision = m_case_file.precision(FloatInfo<Real>::maxDigit());
1695 for (Integer i = 0, is = m_times.size(); i < is; ++i)
1696 m_case_file << m_times[i] << '\n';
1697 m_case_file << '\n';
1698 m_case_file.precision(old_precision);
1699
1700 if (m_fileset_size != 0) {
1701 m_case_file << "FILE\n";
1702 m_case_file << "file set: 1\n";
1703 if (m_fileset_size != 0) {
1704 Integer nb_timeset = (m_times.size() / m_fileset_size);
1705 for (Integer i = 0; i < nb_timeset; ++i) {
1706 m_case_file << "filename index: " << i << "\n";
1707 m_case_file << "number of steps: " << m_fileset_size << '\n';
1708 }
1709 if (nb_timeset > 0)
1710 m_case_file << "filename index: " << nb_timeset << "\n";
1711 m_case_file << "number of steps: " << m_times.size() - (nb_timeset * m_fileset_size) << '\n';
1712 }
1713 else {
1714 m_case_file << "number of steps: " << m_times.size() << '\n';
1715 }
1716 m_case_file << '\n';
1717 }
1718 }
1719 m_case_file.flush();
1720 m_case_file.close();
1721}
1722
1723/*---------------------------------------------------------------------------*/
1724/*---------------------------------------------------------------------------*/
1725
1726/*---------------------------------------------------------------------------*/
1727/*---------------------------------------------------------------------------*/
1728
1742{
1743 if (!v.isUsed())
1744 return false;
1745 eItemKind ik = v.itemKind();
1746 if (ik != IK_Cell && ik != IK_Node && ik != IK_Face)
1747 return false;
1748 // If a variable list is specified, check that the variable is in
1749 // this list. If this list is empty, all are automatically saved.
1750 Integer nb_var = m_save_variables.count();
1751 if (nb_var != 0) {
1752 return m_save_variables.contains(&v);
1753 }
1754 return true;
1755}
1756
1757/*---------------------------------------------------------------------------*/
1758/*---------------------------------------------------------------------------*/
1772_buildFileName(const String& name, String& filename)
1773{
1774 StringBuilder fn_builder;
1775 if (m_fileset_size == 0) {
1776 Integer current_time = m_times.size() - 1;
1777 fn_builder = m_base_directory.path();
1778 fn_builder += "/";
1779 fn_builder += name;
1780 if (m_is_master) {
1781 Directory dir(fn_builder.toString());
1782 dir.createDirectory();
1783 }
1784 fn_builder += "/";
1785 fn_builder += name;
1786
1787 {
1788 OStringStream ostr;
1789 ostr().fill('0'); // Fill character.
1790 ostr().width(m_max_prots_digit);
1791 ostr() << current_time;
1792 fn_builder += ostr.str();
1793 }
1794
1795 //fn_builder += current_time;
1796
1797 //info() << " BUILD FILE NAME name=" << name << " filename=" << fn_builder;
1798 }
1799 else {
1800 fn_builder = m_part_directory.path();
1801 fn_builder += "/";
1802 fn_builder += name;
1803 }
1804 filename = fn_builder;
1805}
1806
1807/*---------------------------------------------------------------------------*/
1808/*---------------------------------------------------------------------------*/
1809
1810bool DumpWEnsight7::
1811_isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind)
1812{
1813 eItemKind group_kind = group.itemKind();
1814 if (item_kind == IK_Unknown)
1815 return false;
1816 return group_kind == item_kind;
1817}
1818
1819/*---------------------------------------------------------------------------*/
1820/*---------------------------------------------------------------------------*/
1833{
1834 Integer prot_index = 0;
1835 bool has_prot = false;
1836 if (m_fileset_size != 0) {
1837 Integer nb_time = m_times.size();
1838 if (nb_time != 0)
1839 prot_index = (nb_time - 1) / m_fileset_size;
1840 has_prot = true;
1841 }
1842
1843 if (m_is_master)
1844 m_base_directory.createDirectory();
1845
1846 if (has_prot) {
1847 OStringStream ostr;
1848 ostr() << "bloc";
1849 ostr().fill('0'); // Fill character.
1850 ostr().width(m_max_prots_digit);
1851 ostr() << prot_index;
1852 //ostr() << '\0';
1853 String buf = ostr.str();
1855 if (m_is_master)
1856 m_part_directory.createDirectory();
1857 }
1858 else
1860}
1861
1862/*---------------------------------------------------------------------------*/
1863/*---------------------------------------------------------------------------*/
1864
1865void DumpWEnsight7::
1866_writeWildcardFilename(std::ostream& ofile, const String& filename, char joker)
1867{
1868 if (m_fileset_size == 0) {
1869 ofile << ' ' << filename << '/' << filename;
1870 for (Integer i = 0; i < m_max_prots_digit; ++i)
1871 ofile << joker;
1872 }
1873 else {
1874 ofile << " bloc";
1875 Integer nb_time = m_times.size();
1876 // If the number of times is less than the size of a fileset-set,
1877 // there is no need to put a '*'. We can directly
1878 // put zeros. This is also essential to prevent
1879 // paraview from crashing when it rereads this type of files.
1880 if (nb_time <= m_fileset_size)
1881 joker = '0';
1882 for (Integer i = 0; i < m_max_prots_digit; ++i)
1883 ofile << joker;
1884 ofile << "/" << filename;
1885 }
1886}
1887
1888/*---------------------------------------------------------------------------*/
1889/*---------------------------------------------------------------------------*/
1890
1891bool DumpWEnsight7::
1892_isNewBlocFile() const
1893{
1894 Integer nb_time = m_times.size();
1895
1896 if (nb_time == 1)
1897 return true;
1898 if (m_fileset_size == 0)
1899 return true;
1900
1901 Integer modulo = (nb_time - 1) % m_fileset_size;
1902
1903 if (modulo == 0)
1904 return true;
1905 return false;
1906}
1907
1908/*---------------------------------------------------------------------------*/
1909/*---------------------------------------------------------------------------*/
1910
1911int DumpWEnsight7::
1912_fileOuttype() const
1913{
1914 return ((isBinary()) ? std::ios::binary : 0) | ((_isNewBlocFile()) ? std::ios::trunc : std::ios::app);
1915}
1916
1917/*---------------------------------------------------------------------------*/
1918/*---------------------------------------------------------------------------*/
1919
1923template <typename T>
1926{
1927 debug() << "Saving variable1 " << v.name() << " ptr=" << ptr.data() << " ps=" << ptr.size();
1928
1929 if (!_isValidVariable(v))
1930 return;
1931
1932 String filename;
1933 _buildFileName(v.name(), filename);
1934
1935 debug() << "Saving variable " << v.name() << " in " << filename;
1936
1937 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1938
1939 _writeFileHeader(dw_ofile(), false);
1940
1941 if (m_is_master)
1942 writeFileString(dw_ofile(), v.name());
1943 String var_type_str;
1944
1945 if (m_is_master) {
1946 switch (v.itemKind()) {
1947 case IK_Cell:
1948 case IK_Face:
1949 var_type_str = "scalar per element: ";
1950 break;
1951 case IK_Node:
1952 var_type_str = "scalar per node: ";
1953 break;
1954 default:
1955 break;
1956 }
1957
1958 m_case_file_variables << var_type_str;
1959 m_case_file_variables << " 1 ";
1960 if (m_fileset_size != 0)
1961 m_case_file_variables << " 1 ";
1962 m_case_file_variables << v.name();
1963 _writeWildcardFilename(m_case_file_variables, v.name());
1964 m_case_file_variables << '\n';
1965 }
1966
1967 switch (v.itemKind()) {
1968 case IK_Cell:
1969 case IK_Face:
1970 case IK_Edge: {
1971 GroupIndexTable* idx = nullptr;
1972
1973 if (v.isPartial()) {
1974 idx = v.itemGroup().localIdToIndex().get();
1975 }
1976
1977 WriteDouble<T> wf(*this, ptr, idx);
1978 for (const GroupPartInfo* part : m_parts) {
1979 bool need_save = false;
1980 if (v.isPartial())
1981 need_save = v.itemGroup() == part->group();
1982 else
1983 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
1984 if (need_save)
1985 _saveVariableOnGroup(dw_ofile(), *part, wf);
1986 }
1987 } break;
1988 case IK_Node: {
1989 if (v.isPartial())
1990 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
1991 WriteDouble<T> wf(*this, ptr);
1992 wf.begin();
1993 for (Integer i = 0; i < ptr.size(); ++i)
1994 wf.write(i);
1995 wf.end();
1996 for (const GroupPartInfo* part : m_parts) {
1997 writeFileString(dw_ofile(), "part");
1998 writeFileInt(dw_ofile(), part->partId());
1999 writeFileString(dw_ofile(), "coordinates");
2000 wf.putValue(dw_ofile());
2001 }
2002 } break;
2003 default:
2004 break;
2005 }
2006
2007 dw_ofile.syncFile();
2008
2009 //if (m_is_transient && m_is_master)
2010 //writeFileString(dw_ofile(),"END TIME STEP");
2011}
2012
2013/*---------------------------------------------------------------------------*/
2014/*---------------------------------------------------------------------------*/
2015
2019template <typename T>
2022{
2023 if (!_isValidVariable(v))
2024 return;
2025
2026 for (Integer idim2 = 0; idim2 < ptr.dim2Size(); ++idim2) {
2027 String vname = v.name() + String("_") + idim2;
2028 String filename;
2029 _buildFileName(vname, filename);
2030
2031 debug() << "Saving variable " << v.name() << " component " << idim2 << " in " << filename;
2032
2033 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2034
2035 _writeFileHeader(dw_ofile(), false);
2036
2037 if (m_is_master)
2038 writeFileString(dw_ofile(), vname);
2039 String var_type_str;
2040
2041 if (m_is_master) {
2042 switch (v.itemKind()) {
2043 case IK_Cell:
2044 case IK_Face:
2045 var_type_str = "scalar per element: ";
2046 break;
2047 case IK_Node:
2048 var_type_str = "scalar per node: ";
2049 break;
2050 default:
2051 break;
2052 }
2053
2054 m_case_file_variables << var_type_str;
2055 m_case_file_variables << " 1 ";
2056 if (m_fileset_size != 0)
2057 m_case_file_variables << " 1 ";
2058 m_case_file_variables << vname;
2059 _writeWildcardFilename(m_case_file_variables, vname);
2060 m_case_file_variables << '\n';
2061 }
2062
2063 switch (v.itemKind()) {
2064 case IK_Cell:
2065 case IK_Face:
2066 case IK_Edge: {
2067 GroupIndexTable* idx = nullptr;
2068
2069 if (v.isPartial()) {
2070 idx = v.itemGroup().localIdToIndex().get();
2071 }
2072
2073 WriteArrayDouble<T> wf(*this, ptr, idim2, idx);
2074 for (const GroupPartInfo* part : m_parts) {
2075 bool need_save = false;
2076 if (v.isPartial())
2077 need_save = v.itemGroup() == part->group();
2078 else
2079 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2080 if (need_save)
2081 _saveVariableOnGroup(dw_ofile(), *part, wf);
2082 }
2083 } break;
2084 case IK_Node: {
2085 if (v.isPartial())
2086 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2087 WriteArrayDouble<T> wf(*this, ptr, idim2);
2088 wf.begin();
2089 for (Integer i = 0; i < ptr.dim1Size(); ++i)
2090 wf.write(i);
2091 wf.end();
2092 for (const GroupPartInfo* part : m_parts) {
2093 writeFileString(dw_ofile(), "part");
2094 writeFileInt(dw_ofile(), part->partId());
2095 writeFileString(dw_ofile(), "coordinates");
2096 wf.putValue(dw_ofile());
2097 }
2098 } break;
2099 default:
2100 break;
2101 }
2102
2103 dw_ofile.syncFile();
2104 }
2105
2106 //if (m_is_transient && m_is_master)
2107 //writeFileString(dw_ofile(),"END TIME STEP");
2108}
2109
2110/*---------------------------------------------------------------------------*/
2111/*---------------------------------------------------------------------------*/
2112
2116template <typename T>
2119{
2120 ARCANE_UNUSED(ptr);
2121
2122 if (!_isValidVariable(v))
2123 return;
2124
2125 warning() << "Impossible to write array variable "
2126 << v.name() << " of non-constant size; variable saving skipped";
2127}
2128
2129/*---------------------------------------------------------------------------*/
2130/*---------------------------------------------------------------------------*/
2131
2137{
2138 if (!_isValidVariable(v))
2139 return;
2140
2141 String filename;
2142 _buildFileName(v.name(), filename);
2143
2144 debug() << "Saving variable " << v.name() << " in " << filename;
2145
2146 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2147
2148 _writeFileHeader(dw_ofile(), false);
2149 if (m_is_master)
2150 writeFileString(dw_ofile(), v.name());
2151
2152 if (m_is_master) {
2153 switch (v.itemKind()) {
2154 case IK_Cell:
2155 case IK_Face:
2156 m_case_file_variables << "vector per element: ";
2157 break;
2158 case IK_Node:
2159 m_case_file_variables << "vector per node: ";
2160 break;
2161 default:
2162 break;
2163 }
2164
2165 m_case_file_variables << " 1 ";
2166 if (m_fileset_size != 0)
2167 m_case_file_variables << " 1 ";
2168 m_case_file_variables << v.name();
2169
2170 _writeWildcardFilename(m_case_file_variables, v.name());
2171 m_case_file_variables << '\n';
2172 }
2173
2174 switch (v.itemKind()) {
2175 case IK_Cell:
2176 case IK_Face:
2177 case IK_Edge: {
2178 GroupIndexTable* idx = nullptr;
2179
2180 if (v.isPartial()) {
2181 idx = v.itemGroup().localIdToIndex().get();
2182 }
2183
2184 WriteReal3 wf(*this, ptr, idx);
2185 for (const GroupPartInfo* part : m_parts) {
2186 bool need_save = false;
2187 if (v.isPartial())
2188 need_save = v.itemGroup() == part->group();
2189 else
2190 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2191 if (need_save)
2192 _saveVariableOnGroup(dw_ofile(), *part, wf);
2193 }
2194 } break;
2195 case IK_Node: {
2196 if (v.isPartial())
2197 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2198 WriteReal3 wf(*this, ptr);
2199 wf.begin();
2200 for (Integer i = 0; i < ptr.size(); ++i)
2201 wf.write(i);
2202 wf.end();
2203 for (const GroupPartInfo* part : m_parts) {
2204 writeFileString(dw_ofile(), "part");
2205 writeFileInt(dw_ofile(), part->partId());
2206 writeFileString(dw_ofile(), "coordinates");
2207 wf.putValue(dw_ofile());
2208 }
2209 } break;
2210 default:
2211 break;
2212 }
2213
2214 dw_ofile.syncFile();
2215}
2216
2217/*---------------------------------------------------------------------------*/
2218/*---------------------------------------------------------------------------*/
2219
2225{
2226 if (!_isValidVariable(v))
2227 return;
2228
2229 for (Integer idim2 = 0; idim2 < ptr.dim2Size(); ++idim2) {
2230 String vname = v.name() + String("_") + idim2;
2231 String filename;
2232 _buildFileName(vname, filename);
2233
2234 debug() << "Saving variable " << v.name() << " component " << idim2 << " in " << filename;
2235
2236 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2237
2238 _writeFileHeader(dw_ofile(), false);
2239 if (m_is_master)
2240 writeFileString(dw_ofile(), vname);
2241
2242 if (m_is_master) {
2243 switch (v.itemKind()) {
2244 case IK_Cell:
2245 case IK_Face:
2246 m_case_file_variables << "vector per element: ";
2247 break;
2248 case IK_Node:
2249 m_case_file_variables << "vector per node: ";
2250 break;
2251 default:
2252 break;
2253 }
2254
2255 m_case_file_variables << " 1 ";
2256 if (m_fileset_size != 0)
2257 m_case_file_variables << " 1 ";
2258 m_case_file_variables << vname;
2259
2260 _writeWildcardFilename(m_case_file_variables, vname);
2261 m_case_file_variables << '\n';
2262 }
2263
2264 switch (v.itemKind()) {
2265 case IK_Cell:
2266 case IK_Face:
2267 case IK_Edge: {
2268 GroupIndexTable* idx = nullptr;
2269
2270 if (v.isPartial()) {
2271 idx = v.itemGroup().localIdToIndex().get();
2272 }
2273
2274 WriteArrayReal3 wf(*this, ptr, idim2, idx);
2275 for (const GroupPartInfo* part : m_parts) {
2276 bool need_save = false;
2277 if (v.isPartial())
2278 need_save = v.itemGroup() == part->group();
2279 else
2280 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2281 if (need_save)
2282 _saveVariableOnGroup(dw_ofile(), *part, wf);
2283 }
2284 } break;
2285 case IK_Node: {
2286 if (v.isPartial())
2287 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2288 WriteArrayReal3 wf(*this, ptr, idim2);
2289 wf.begin();
2290 for (Integer i = 0; i < ptr.dim1Size(); ++i)
2291 wf.write(i);
2292 wf.end();
2293 for (const GroupPartInfo* part : m_parts) {
2294 writeFileString(dw_ofile(), "part");
2295 writeFileInt(dw_ofile(), part->partId());
2296 writeFileString(dw_ofile(), "coordinates");
2297 wf.putValue(dw_ofile());
2298 }
2299 } break;
2300 default:
2301 break;
2302 }
2303
2304 dw_ofile.syncFile();
2305 }
2306
2307 //if (m_is_transient && m_is_master)
2308 //writeFileString(dw_ofile(),"END TIME STEP");
2309}
2310
2311/*---------------------------------------------------------------------------*/
2312/*---------------------------------------------------------------------------*/
2313
2319{
2320 ARCANE_UNUSED(ptr);
2321
2322 if (!_isValidVariable(v))
2323 return;
2324
2325 warning() << "Impossible to write array variable " << v.name()
2326 << " of non-constant size; variable saving skipped";
2327}
2328
2329/*---------------------------------------------------------------------------*/
2330/*---------------------------------------------------------------------------*/
2331
2335class Ensight7PostProcessorService
2336: public PostProcessorWriterBase
2337{
2338 public:
2339
2340 Ensight7PostProcessorService(const ServiceBuildInfo& sbi)
2341 : PostProcessorWriterBase(sbi)
2342 , m_mesh(sbi.mesh())
2343 , m_writer(nullptr)
2344 {
2345 }
2346
2347 IDataWriter* dataWriter() override { return m_writer; }
2348 void notifyBeginWrite() override;
2349 void notifyEndWrite() override;
2350 void close() override {}
2351
2352 private:
2353
2354 IMesh* m_mesh;
2355 DumpW* m_writer;
2356};
2357
2358/*---------------------------------------------------------------------------*/
2359/*---------------------------------------------------------------------------*/
2360
2363{
2364 bool is_binary = true;
2365 Integer fileset_size = 100;
2366 bool is_parallel = subDomain()->parallelMng()->isParallel();
2367 bool use_degenerated_hexa = true;
2368 bool force_first_geometry = false;
2369 bool save_uids = false;
2370 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2371 variables(), groups(), is_binary, is_parallel,
2372 fileset_size, use_degenerated_hexa,
2373 force_first_geometry, save_uids);
2374}
2375
2378{
2379 delete m_writer;
2380 m_writer = 0;
2381}
2382
2383/*---------------------------------------------------------------------------*/
2384/*---------------------------------------------------------------------------*/
2385
2386/*---------------------------------------------------------------------------*/
2387/*---------------------------------------------------------------------------*/
2388
2392class Ensight7PostProcessorServiceV2
2394{
2395 public:
2396
2397 typedef ArcaneEnsight7PostProcessorObject BaseType;
2398
2399 public:
2400
2401 explicit Ensight7PostProcessorServiceV2(const ServiceBuildInfo& sbi)
2403 , m_mesh(sbi.mesh())
2404 , m_writer(nullptr)
2405 {
2406 }
2407
2408 IDataWriter* dataWriter() override { return m_writer; }
2409 void notifyBeginWrite() override;
2410 void notifyEndWrite() override;
2411 void close() override {}
2412
2413 void setMesh(IMesh* mesh) override
2414 {
2415 // TODO: A supprimer car méthode obsolète et n'est pas utilisé.
2416 m_mesh = mesh;
2417 }
2418
2419 private:
2420
2421 IMesh* m_mesh = nullptr;
2422 DumpW* m_writer = nullptr;
2423};
2424
2425/*---------------------------------------------------------------------------*/
2426/*---------------------------------------------------------------------------*/
2427
2430{
2431 // std::cout << " ############# IMesh = " << mesh() << " " << m_mesh << " ###########\n";
2432
2433 bool is_binary = true;
2434 Integer fileset_size = 0;
2435 bool is_parallel = m_mesh->parallelMng()->isParallel();
2436 is_binary = options()->binaryFile();
2437 fileset_size = options()->filesetSize();
2438 bool use_degenerated_hexa = options()->useDegeneratedHexa();
2439 bool force_first_geometry = options()->forceFirstGeometry();
2440 bool save_uids = options()->saveUids();
2441 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2442 variables(), groups(), is_binary, is_parallel, fileset_size,
2443 use_degenerated_hexa, force_first_geometry, save_uids);
2444}
2445
2448{
2449 delete m_writer;
2450 m_writer = nullptr;
2451}
2452
2453/*---------------------------------------------------------------------------*/
2454/*---------------------------------------------------------------------------*/
2455
2457 Ensight7PostProcessor);
2458
2459ARCANE_REGISTER_SERVICE_ENSIGHT7POSTPROCESSOR(Ensight7PostProcessor, Ensight7PostProcessorServiceV2);
2460
2461/*---------------------------------------------------------------------------*/
2462/*---------------------------------------------------------------------------*/
2463
2464} // namespace Arcane
2465
2466/*---------------------------------------------------------------------------*/
2467/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Types and macros for iterating over mesh entities.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
#define ENUMERATE_NODE(name, group)
Generic enumerator for a node group.
This file contains the various service factories and macros for registering services.
#define ARCANE_REGISTER_SUB_DOMAIN_FACTORY(aclass, ainterface, aname)
Registers a factory service for the class aclass.
Integer size() const
Number of elements in the vector.
CaseOptionsEnsight7PostProcessor * options() const
Options du jeu de données du service.
ArcaneEnsight7PostProcessorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
Base class for 1D data vectors.
void fill(ConstReferenceType value)
Fills the array with the value value.
void resize(Int64 s)
Changes the number of elements in the array to s.
void add(ConstReferenceType val)
Adds element val to the end of the array.
const T * data() const
Access to the root of the array without any protection.
ArrayView< T > view() const
Mutable view of this array.
Cell of a mesh.
Definition Item.h:1300
FaceConnectedListViewType faces() const
List of faces of the cell.
Definition Item.h:1403
Face face(Int32 i) const
i-th face of the cell
Definition Item.h:1400
Int32 nbFace() const
Number of faces of the cell.
Definition Item.h:1397
Integer count() const
Number of elements in the collection.
Constant view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr Integer size() const noexcept
Number of elements in the array.
ConstIterT< ConstArrayView< T > > const_iter
Type of a constant iterator over the entire array.
Constant view on a MultiArray2.
Class managing a directory.
Definition Directory.h:36
bool createDirectory() const override
Creates the directory.
Definition Directory.cc:102
Abstraction of an output file for ensight.
Functor for writing a variable of type Real.
Functor to write a variable of type Real3.
Functor for writing a variable.
Functor for writing a variable of type Real.
Functor to write a variable of type Real2.
Writes in Ensight7 format.
void _writeRealValT(IVariable &v, ConstArrayView< T > a)
Template for writing variable as a real variable.
std::ofstream m_case_file
File describing the case.
bool m_is_binary
List of parts.
void writeVal(IVariable &, ConstArrayView< Byte >) override
Writing for variable v of array a.
void beginWrite() override
Notifies the start of writing.
Directory m_part_directory
Storage directory for the current iteration.
void _buildFileName(const String &varname, String &filename)
Constructs the filename for a variable or mesh name.
bool _isValidVariable(IVariable &) const
Checks the validity of the variable to be saved.
ItemGroupList m_save_groups
List of groups to export.
void _buildPartDirectory()
Constructs the directory where the variables will be saved.
IParallelMng * m_parallel_mng
Parallelism manager.
void endWrite() override
Notifies the end of writing.
RealUniqueArray m_times
description of saved variables
void setMetaData(const String &) override
Sets metadata information.
VariableList m_save_variables
List of variables to export.
static const Integer m_max_prots_digit
Maximum number of digits to indicate the protection number.
Directory m_base_directory
Storage directory name.
bool m_is_master
true if the processor manages the output
Integer m_total_nb_element
Total number of mesh elements across all groups to be saved.
Integer m_total_nb_group
Number of groups to save (== number of parts).
wrapper transforming calls to the IDataWriter interface into IDumpW
Definition DumpW.h:46
DumpW()
Constructor.
Definition DumpW.cc:155
void write(IVariable *var, IData *data)
Writes the data data of the variable var.
Definition DumpW.cc:179
Post-processing in Ensight7 format.
void notifyBeginWrite() override
Notifies that an output is going to be performed with the current parameters.
void close() override
Closes the writer. After closing, it can no longer be used.
void notifyEndWrite() override
Notifies that an output has just been performed.
IDataWriter * dataWriter() override
Returns the writer associated with this post-processor.
void setMesh(IMesh *mesh) override
Positions the mesh.
Post-processing in Ensight7 format.
IDataWriter * dataWriter() override
Returns the writer associated with this post-processor.
void close() override
Closes the writer. After closing, it can no longer be used.
void notifyEndWrite() override
Notifies that an output has just been performed.
void notifyBeginWrite() override
Notifies that an output is going to be performed with the current parameters.
Face of a cell.
Definition Item.h:1032
Information about the floating-point type.
Definition FloatInfo.h:35
Base class of a hash table between group items and their positions in the table.
Interface for writing variable data.
Definition IDataWriter.h:45
virtual String name() const =0
Family name.
virtual ItemTypeMng * itemTypeMng() const =0
Associated entity type manager.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual bool isParallel() const =0
Returns true if the execution is parallel.
Interface for a writer for post-processing information.
Interface of the subdomain manager.
Definition ISubDomain.h:75
virtual IMesh * defaultMesh()=0
Default mesh.
Interface of a variable.
Definition IVariable.h:40
virtual void setUsed(bool v)=0
Sets the usage state of the variable.
@ PTemporary
Indicates that the variable is temporary.
Definition IVariable.h:114
@ PPrivate
Indicates that the variable is private.
Definition IVariable.h:103
virtual eItemKind itemKind() const =0
Kind of mesh entities on which the variable is based.
virtual bool isPartial() const =0
Indicates if the variable is partial.
virtual IData * data()=0
Data associated with the variable.
virtual bool isUsed() const =0
Usage state of the variable.
virtual ItemGroup itemGroup() const =0
Associated mesh group.
virtual void notifyBeginWrite()=0
Notifies of the start of writing data().
virtual String name() const =0
Variable name.
Mesh entity group.
Definition ItemGroup.h:51
const String & name() const
Group name.
Definition ItemGroup.h:81
bool isOwn() const
Returns whether the group contains only elements belonging to the subdomain.
Definition ItemGroup.cc:149
SharedPtrT< GroupIndexTable > localIdToIndex() const
Table of local ids to a position for all entities in the group.
Definition ItemGroup.h:312
Integer size() const
Number of elements in the group.
Definition ItemGroup.h:93
IItemFamily * itemFamily() const
Entity family to which this group belongs (0 for the null group).
Definition ItemGroup.h:128
eItemKind itemKind() const
Group kind. This is the kind of its elements.
Definition ItemGroup.h:114
bool null() const
true means the group is the null group
Definition ItemGroup.h:75
IMesh * mesh() const
Mesh to which this group belongs (0 for the null group).
Definition ItemGroup.h:131
ItemGroup own() const
Group equivalent to this one but containing only the local elements of the subdomain.
Definition ItemGroup.cc:182
Local information about a cell face.
Integer node(Integer i) const
Local index in the cell of the i-th node of the face.
Integer nbNode() const
Number of nodes of the face.
Info on a mesh entity type.
LocalFace localFace(Integer id) const
Local connectivity of the i-th face of the cell.
Integer nbLocalEdge() const
Number of edges of the entity.
Integer nbLocalNode() const
Number of nodes of the entity.
Integer nbLocalFace() const
Number of faces of the entity.
Mesh entity type manager.
Definition ItemTypeMng.h:66
bool hasGeneralCells(IMesh *mesh) const
Indicates if the mesh mesh contains generic cells (outside of built-in or additional types).
static Integer nbBasicItemType()
number of available types
ItemTypeInfo * typeFromId(Integer id) const
Type corresponding to the number id.
static Integer nbBuiltInItemType()
number of built-in types (excluding additional types)
Mesh element based on nodes (Edge,Face,Cell).
Definition Item.h:773
Node node(Int32 i) const
i-th node of the entity
Definition Item.h:840
Int32 nbNode() const
Number of nodes of the entity.
Definition Item.h:837
Base class for a mesh element.
Definition Item.h:84
const ItemTypeInfo * typeInfo() const
Information about the entity type.
Definition Item.h:406
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
ItemWithNodes toItemWithNodes() const
Converts the entity to the ItemWithNodes kind.
Definition Item.h:1802
Cell toCell() const
Converts the entity to the Cell kind.
Definition Item.h:1830
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
Int16 type() const
Entity type.
Definition Item.h:255
void clone(const Collection< T > &base)
Clone the collection base.
Output stream linked to a String.
ItemGroupCollection groups() override
List of groups to save.
VariableCollection variables() override
List of variables to save.
ConstArrayView< Real > times() override
List of saved times.
const String & baseDirectoryName() override
Name of the output directory for files.
T * get() const
Returns the object referenced by the instance.
Definition Ptr.h:122
Encapsulation of an automatically destructing pointer.
Definition ScopedPtr.h:44
IMesh * mesh() const
Access to the associated IMesh.
Structure containing the information to create a service.
Unicode character string constructor.
String toString() const
Returns the constructed character string.
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:229
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage warning() const
Flow for a warning message.
1D data vector with value semantics (STL style).
Parameters necessary for building a variable.
IVariable * variable() const
Associated variable.
ItemGroupT< Node > NodeGroup
Group of nodes.
Definition ItemTypes.h:168
MeshVariableScalarRefT< Cell, Real > VariableCellReal
Real type quantity at cell center.
MeshVariableScalarRefT< Node, Integer > VariableNodeInteger
Quantity at the node of integer type.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
char * copyn(char *to, const char *from, Integer n)
Copies the first n characters of from into to.
Real toReal(Real r)
Converts r to a Real.
double toDouble(Real r)
Converts a Real to double.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Integer arcaneCheckArraySize(unsigned long long size)
Checks that size can be converted into an 'Integer' to serve as the size of an array....
Collection< ItemGroup > ItemGroupCollection
Collection of mesh item groups.
Int32 Integer
Type representing an integer.
List< ItemGroup > ItemGroupList
Array of mesh item groups.
SharedMeshVariableScalarRefT< Node, Real3 > SharedVariableNodeReal3
Quantity at the node of coordinate type.
UniqueArray< Real > RealUniqueArray
Dynamic 1D array of reals.
Definition UtilsTypes.h:343
eItemKind
Mesh entity type.
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
@ IK_Unknown
Unknown or uninitialized mesh entity.
@ IK_Face
Face mesh entity.
@ IK_Edge
Edge mesh entity.
double Real
Type representing a real number.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:341
ConstArrayView< Integer > IntegerConstArrayView
C equivalent of a 1D array of integers.
Definition UtilsTypes.h:480
std::int32_t Int32
Signed integer type of 32 bits.
ConstArrayView< Real > RealConstArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:482
Correspondence between Ensight element type and Arcane.
int m_type
Arcane type of the element.
UniqueArray< Item > m_items
Entities of elements of this type.
Integer m_nb_node
Number of nodes.
String m_name
Ensight name of this element.
Information to share a group into elements of the same subtype.
ItemGroup m_group
Associated group.
std::unique_ptr< VariableItemInt32 > m_general_item_types
Variable to store the types of general items (untyped).
Integer nbType() const
Number of subtypes.