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