Arcane  4.2.3.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.typeInfo()->isPolyhedron()) { // polyhedron found
328 (*(m_general_item_types))[item] = type_id;
329 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nfaced"));
330 }
331 else if (item.nbNode() != item.itemBase().nbEdge()) { // polyhedron found
332 (*(m_general_item_types))[item] = type_id;
333 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nfaced"));
334 }
335 }
336 m_is_polyhedral_type_registration_done = true;
337 }
338 }
339 // if extra types are used, init a EnsightPart map to optimize GroupPartInfo fill
341 _initPartMap();
342 }
343 }
344 };
345
346 public:
347
348 //void writeFileString(ostream& o,ConstCString str);
349 void writeFileString(std::ostream& o, const String& str);
350 void writeFileInt(std::ostream& o, int value);
351 void writeFileDouble(std::ostream& o, double value);
352 Integer writeDoubleSize() const;
353 Integer writeIntSize() const;
354 void writeFileArray(std::ostream& o, IntegerConstArrayView value);
355 bool isBinary() const { return m_is_binary; }
356
357 public:
358
372 class WriteBase
373 {
374 public:
375
376 explicit WriteBase(DumpWEnsight7& dw)
377 : m_dw(dw)
378 {}
379 WriteBase(DumpWEnsight7& dw, GroupIndexTable* idx)
380 : m_dw(dw)
381 , m_idx(idx)
382 {}
383 WriteBase(const WriteBase& wb)
384 : m_dw(wb.m_dw)
385 , m_idx(wb.m_idx)
386 {}
387 virtual ~WriteBase() {}
388
389 public:
390
391 virtual WriteBase* clone() = 0;
392 virtual void begin() { init(); }
393 virtual void end() {}
394 virtual void write(ConstArrayView<Item> items) = 0;
395
396 virtual void init()
397 {
398 m_ofile.precision(5);
399 m_ofile.flags(std::ios::scientific);
400 }
401 virtual void putValue(std::ostream& ofile)
402 {
403 ofile << m_ofile.str();
404 }
405 std::ostream& stream() { return m_ofile; }
406
407 protected:
408
409 DumpWEnsight7& m_dw;
410 std::ostringstream m_ofile;
411 GroupIndexTable* m_idx = nullptr;
412 };
413
417 template <typename FromType>
418 class WriteDouble
419 : public WriteBase
420 {
421 public:
422
423 WriteDouble(DumpWEnsight7& dw, ConstArrayView<FromType> ptr, GroupIndexTable* idx = nullptr)
424 : WriteBase(dw, idx)
425 , m_ptr(ptr)
426 {}
427 WriteDouble(const WriteDouble& wd)
428 : WriteBase(wd)
429 , m_ptr(wd.m_ptr)
430 {}
431
432 WriteBase* clone() override { return new WriteDouble(*this); }
433
434 public:
435
437
438 public:
439
440 inline void write(Integer index)
441 {
442 if (m_idx) {
443 int reindex = (*m_idx)[index];
444 if (reindex < 0)
445 ARCANE_FATAL("Invalid index");
446 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[reindex])));
447 }
448 else
449 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[index])));
450 }
451
452 void write(ConstArrayView<Item> items) override
453 {
454 for (Item e : items) {
455 write(e.localId());
456 }
457 }
458 };
459
463 template <typename FromType>
464 class WriteArrayDouble
465 : public WriteBase
466 {
467 public:
468
469 WriteArrayDouble(DumpWEnsight7& dw, ConstArray2View<FromType> ptr, const Integer idim2,
470 GroupIndexTable* idx = nullptr)
471 : WriteBase(dw, idx)
472 , m_ptr(ptr)
473 , m_idim2(idim2)
474 {}
475 WriteArrayDouble(const WriteArrayDouble& wd)
476 : WriteBase(wd)
477 , m_ptr(wd.m_ptr)
478 , m_idim2(wd.m_idim2)
479 {}
480
481 WriteBase* clone() override { return new WriteArrayDouble(*this); }
482
483 public:
484
486 const Integer m_idim2;
487
488 public:
489
490 void write(Integer index)
491 {
492 if (m_idx) {
493 int reindex = (*m_idx)[index];
494 if (reindex < 0)
495 ARCANE_FATAL("Invalid index");
496 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[reindex][m_idim2])));
497 }
498 else
499 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[index][m_idim2])));
500 }
501
502 void write(ConstArrayView<Item> items) override
503 {
504 for (Item e : items) {
505 write(e.localId());
506 }
507 }
508 };
509
513
517 class WriteReal3
518 : public WriteBase
519 {
520 public:
521
522 WriteReal3(DumpWEnsight7& dw, ConstArrayView<Real3> ptr, GroupIndexTable* idx = nullptr)
523 : WriteBase(dw, idx)
524 , m_ptr(ptr)
525 {}
526 WriteReal3(const WriteReal3& wd)
527 : WriteBase(wd)
528 , m_ptr(wd.m_ptr)
529 {}
530
531 WriteBase* clone() override { return new WriteReal3(*this); }
532
533 public:
534
536
537 public:
538
539 void begin() override
540 {
541 _init();
542 xostr.precision(5);
543 xostr.flags(std::ios::scientific);
544 yostr.precision(5);
545 yostr.flags(std::ios::scientific);
546 zostr.precision(5);
547 zostr.flags(std::ios::scientific);
548 }
549
550 void write(Integer index)
551 {
552 if (m_idx) {
553 int reindex = (*m_idx)[index];
554 if (reindex < 0)
555 ARCANE_FATAL("Invalid index");
556 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[reindex].x));
557 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[reindex].y));
558 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[reindex].z));
559 }
560 else {
561 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[index].x));
562 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[index].y));
563 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[index].z));
564 }
565 }
566
567 void write(ConstArrayView<Item> items) override
568 {
569 for (Item i : items) {
570 write(i.localId());
571 }
572 }
573
574 void end() override
575 {
576 m_ofile << xostr.str();
577 m_ofile << yostr.str();
578 m_ofile << zostr.str();
579 }
580
581 public:
582
583 std::ostringstream xostr;
584 std::ostringstream yostr;
585 std::ostringstream zostr;
586
587 private:
588
589 void _init()
590 {
591 init();
592 }
593 };
594
598 class WriteArrayReal3
599 : public WriteBase
600 {
601 public:
602
603 WriteArrayReal3(DumpWEnsight7& dw, ConstArray2View<Real3> ptr,
604 Integer idim2, GroupIndexTable* idx = nullptr)
605 : WriteBase(dw, idx)
606 , m_ptr(ptr)
607 , m_idim2(idim2)
608 {}
609 WriteArrayReal3(const WriteArrayReal3& wd)
610 : WriteBase(wd)
611 , m_ptr(wd.m_ptr)
612 , m_idim2(wd.m_idim2)
613 {}
614
615 WriteBase* clone() override { return new WriteArrayReal3(*this); }
616
617 public:
618
620 const Integer m_idim2;
621
622 public:
623
624 void begin() override
625 {
626 _init();
627 xostr.precision(5);
628 xostr.flags(std::ios::scientific);
629 yostr.precision(5);
630 yostr.flags(std::ios::scientific);
631 zostr.precision(5);
632 zostr.flags(std::ios::scientific);
633 }
634
635 inline void write(Integer index)
636 {
637 if (m_idx) {
638 int reindex = (*m_idx)[index];
639 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[reindex][m_idim2].x));
640 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[reindex][m_idim2].y));
641 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[reindex][m_idim2].z));
642 }
643 else {
644 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[index][m_idim2].x));
645 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[index][m_idim2].y));
646 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[index][m_idim2].z));
647 }
648 }
649
650 void write(ConstArrayView<Item> items) override
651 {
652 for (Item i : items) {
653 write(i.localId());
654 }
655 }
656
657 void end() override
658 {
659 m_ofile << xostr.str();
660 m_ofile << yostr.str();
661 m_ofile << zostr.str();
662 }
663
664 public:
665
666 std::ostringstream xostr;
667 std::ostringstream yostr;
668 std::ostringstream zostr;
669
670 private:
671
672 void _init()
673 {
674 init();
675 }
676 };
677
678 public:
679
680 DumpWEnsight7(IMesh* m, const String& filename, RealConstArrayView times,
681 VariableCollection variables, ItemGroupCollection groups,
682 bool is_binary, bool is_parallel, Integer fileset_size,
683 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids);
684 ~DumpWEnsight7();
685
686 public:
687
689 void writeVal(IVariable& v, ConstArrayView<Real> a) override { _writeRealValT<Real>(v, a); }
690 void writeVal(IVariable&, ConstArrayView<Real2>) override {}
691 void writeVal(IVariable&, ConstArrayView<Real3>) override;
692 void writeVal(IVariable& v, ConstArrayView<Int16> a) override { _writeRealValT<Int16>(v, a); }
693 void writeVal(IVariable& v, ConstArrayView<Int32> a) override { _writeRealValT<Int32>(v, a); }
694 void writeVal(IVariable& v, ConstArrayView<Int64> a) override { _writeRealValT<Int64>(v, a); }
695 void writeVal(IVariable&, ConstArrayView<Real2x2>) override {}
696 void writeVal(IVariable&, ConstArrayView<Real3x3>) override {}
697 void writeVal(IVariable&, ConstArrayView<String>) override {}
698
699 void writeVal(IVariable&, ConstArray2View<Byte>) override {}
700 void writeVal(IVariable& v, ConstArray2View<Real> a) override { _writeRealValT<Real>(v, a); }
701 void writeVal(IVariable&, ConstArray2View<Real2>) override {}
702 void writeVal(IVariable&, ConstArray2View<Real3>) override;
703 void writeVal(IVariable& v, ConstArray2View<Int16> a) override { _writeRealValT<Int16>(v, a); }
704 void writeVal(IVariable& v, ConstArray2View<Int32> a) override { _writeRealValT<Int32>(v, a); }
705 void writeVal(IVariable& v, ConstArray2View<Int64> a) override { _writeRealValT<Int64>(v, a); }
706 void writeVal(IVariable&, ConstArray2View<Real2x2>) override {}
707 void writeVal(IVariable&, ConstArray2View<Real3x3>) override {}
708
709 void writeVal(IVariable&, ConstMultiArray2View<Byte>) override {}
710 void writeVal(IVariable& v, ConstMultiArray2View<Real> a) override { _writeRealValT<Real>(v, a); }
711 void writeVal(IVariable&, ConstMultiArray2View<Real2>) override {}
712 void writeVal(IVariable&, ConstMultiArray2View<Real3> a) override;
713 void writeVal(IVariable& v, ConstMultiArray2View<Int16> a) override { _writeRealValT<Int16>(v, a); }
714 void writeVal(IVariable& v, ConstMultiArray2View<Int32> a) override { _writeRealValT<Int32>(v, a); }
715 void writeVal(IVariable& v, ConstMultiArray2View<Int64> a) override { _writeRealValT<Int64>(v, a); }
716 void writeVal(IVariable&, ConstMultiArray2View<Real2x2>) override {}
717 void writeVal(IVariable&, ConstMultiArray2View<Real3x3>) override {}
718
719 void beginWrite() override;
720 void endWrite() override;
721 void setMetaData(const String&) override {};
722
723 bool isParallelOutput() const { return m_is_parallel_output; }
724 bool isMasterProcessor() const { return m_is_master; }
725 bool isOneFilePerTime() const { return m_fileset_size == 0; }
726 Int32 rank() const { return m_parallel_mng->commRank(); }
727 IParallelMng* parallelMng() const { return m_parallel_mng; }
728
729 public:
730 private:
731
732 typedef UniqueArray<GroupPartInfo*> GroupPartInfoList;
733
734 private:
735
740 std::ofstream m_case_file;
741 std::ostringstream m_case_file_variables;
743 VariableList m_save_variables;
745 GroupPartInfoList m_parts;
751 bool m_use_degenerated_hexa;
752 bool m_force_first_geometry;
753 bool m_save_uids;
760 Integer m_fileset_size;
761
762 private:
763 private:
764
766 static const Integer m_max_prots_digit = 6;
767
768 private:
769 private:
770
771 bool _isValidVariable(IVariable&) const;
772 void _createCaseFile();
773 void _buildFileName(const String& varname, String& filename);
774 void _buildPartDirectory();
775 void _writeWildcardFilename(std::ostream& ofile, const String& filename, char joker = '*');
776 int _fileOuttype() const;
777 void _writeFileHeader(std::ostream& o, bool write_c_binary);
778 bool _isNewBlocFile() const;
779
780 void _computeGroupParts(ItemGroupList list_group, Integer& partid);
781 void _saveGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
782 ConstArrayView<Integer> nodes_index, WriteBase& wf);
783 void _saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
784 WriteBase& from_func);
785 bool _isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind);
786
788 template <typename T>
791 template <typename T>
794 template <typename T>
796};
797
798/*---------------------------------------------------------------------------*/
799/*---------------------------------------------------------------------------*/
800
801extern "C++" DumpW*
802createEnsight7(ISubDomain* m, const String& f,
804 VariableCollection variables,
805 ItemGroupCollection groups,
806 bool is_binary, bool is_parallel_output, Integer fileset_size,
807 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
808{
809 return new DumpWEnsight7(m->defaultMesh(), f, times, variables, groups, is_binary,
810 is_parallel_output, fileset_size, use_degenerated_hexa,
811 force_first_geometry, save_uids);
812}
813
814extern "C++" DumpW*
815createEnsight7(IMesh* m, const String& f,
816 ConstArrayView<Real> times,
817 VariableCollection variables,
818 ItemGroupCollection groups,
819 bool is_binary, bool is_parallel_output, Integer fileset_size,
820 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
821{
822 return new DumpWEnsight7(m, f, times, variables, groups, is_binary,
823 is_parallel_output, fileset_size, use_degenerated_hexa,
824 force_first_geometry, save_uids);
825}
826
827/*---------------------------------------------------------------------------*/
828/*---------------------------------------------------------------------------*/
829
830DumpWEnsight7::
831DumpWEnsight7(IMesh* mesh, const String& filename, ConstArrayView<Real> times,
832 VariableCollection variables, ItemGroupCollection groups,
833 bool is_binary, bool is_parallel_output, Integer fileset_size,
834 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
835: TraceAccessor(mesh->traceMng())
836, m_mesh(mesh)
837, m_parallel_mng(mesh->parallelMng())
838, m_base_directory(filename)
839, m_times(times)
840, m_save_variables(variables.clone())
841, m_save_groups(groups.enumerator())
842, m_is_binary(is_binary)
843// , m_is_binary(false)
844, m_is_master(true)
845, m_is_parallel_output(is_parallel_output)
846, m_use_degenerated_hexa(use_degenerated_hexa)
847, m_force_first_geometry(force_first_geometry)
848, m_save_uids(save_uids)
849, m_total_nb_element(0)
850, m_total_nb_group(0)
851, m_fileset_size(fileset_size)
852{
853 //m_is_binary = true;
854 //m_fileset_size = 0;
855
856 if (m_times.empty()) {
857 m_times.resize(1);
858 m_times[0] = 0.;
859 }
860
861 //_createCaseFile();
862}
863
864/*---------------------------------------------------------------------------*/
865/*---------------------------------------------------------------------------*/
866
867DumpWEnsight7::
868~DumpWEnsight7()
869{
870 std::for_each(std::begin(m_parts), std::end(m_parts), Deleter());
871}
872
873/*---------------------------------------------------------------------------*/
874/*---------------------------------------------------------------------------*/
875
876/*---------------------------------------------------------------------------*/
877/*---------------------------------------------------------------------------*/
878
897void DumpWEnsight7::
898_computeGroupParts(ItemGroupList list_group, Integer& partid)
899{
900 for (ItemGroupList::Enumerator i(list_group); ++i;) {
901 ItemGroup grp(*i);
902 if (grp.null()) // The group is not of the desired type.
903 continue;
904 if (!grp.isOwn()) // If possible, take the own element group
905 grp = grp.own();
906 // Since Ensight 7.6, empty groups are allowed
907 // and they are necessary when the mesh evolves over time
908 //if (grp.empty()) // The group is empty
909 //continue;
910 GroupPartInfo* gpi = new GroupPartInfo(grp, partid, m_use_degenerated_hexa);
911 m_parts.add(gpi);
912 ++partid;
913
914 GroupPartInfo& current_grp = *gpi;
915 // Now we must determine how many elements of each type
916 // ensight (tria3, hexa8, ...) are in the group.
917 // two versions: if extra item types are added switch to an optimized version
918 // (a large amount of types may be added, equal to the number of elements)
920 {
921 debug(Trace::High) << "Using standard group part building algo";
922 if (!grp.mesh()->itemTypeMng()->hasGeneralCells(grp.mesh())) { // classical types
923 for (Integer z = 0; z < current_grp.nbType(); ++z) {
924 EnsightPart& type_info = current_grp.typeInfo(z);
925 Array<Item>& items = type_info.items();
926 Integer nb_of_type = 0;
927 Integer type_to_seek = type_info.type();
928 ENUMERATE_ITEM (i2, grp) {
929 const Item& e = *i2;
930 if (e.type() == type_to_seek)
931 ++nb_of_type;
932 }
933 items.resize(nb_of_type);
934 debug(Trace::High) << "Group " << grp.name() << " has "
935 << nb_of_type << " items of type " << type_info.name();
936 Integer index = 0;
937 ENUMERATE_ITEM (iz, grp) {
938 Item mi = *iz;
939 if (mi.type() == type_to_seek) {
941 items[index] = e;
942 ++index;
943 }
944 }
945 }
946 }
947 else { // polyhedral mesh items
948 ENUMERATE_ITEM (i2, grp) {
949 const Item& item = *i2;
950 auto item_type = current_grp.generalItemTypeId(item);
951 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
952 if (!ensight_part)
953 continue;
954 ItemWithNodes item_wn = item.toItemWithNodes();
955 ensight_part->items().add(item_wn);
956 }
957 }
958 }
959 else // extra types are added (may have as many types as items...)
960 // Propose an optimized version when many types exist (use of .format file)
961 {
962 debug(Trace::High) << "Using extra type group part building algo";
963 // work only on face and cell groups
964 auto item_kind = grp.itemKind();
965 if (item_kind == IK_Cell || item_kind == IK_Face) {
966 ENUMERATE_ITEM (item, grp) {
967 auto item_type = item->type();
968 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
969 if (!ensight_part)
970 continue;
971 ItemWithNodes item_wn = item->toItemWithNodes();
972 ensight_part->items().add(item_wn); // few elements are added
973 }
974 }
975 }
976 }
977}
978
979/*---------------------------------------------------------------------------*/
980/*---------------------------------------------------------------------------*/
1001void DumpWEnsight7::
1002_saveGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
1003 ConstArrayView<Integer> nodes_index, WriteBase& wf)
1004{
1005 ItemGroup igrp = ensight_grp.group();
1006
1007 writeFileString(ofile, "part");
1008 writeFileInt(ofile, ensight_grp.partId());
1009 if (isParallelOutput()) {
1010 // In the case of parallel output, prefix the group name with the
1011 // CPU number.
1012 std::ostringstream ostr;
1013 ostr << igrp.name().localstr() << "_CPU" << rank();
1014 writeFileString(ofile, ostr.str().c_str());
1015 }
1016 else
1017 writeFileString(ofile, igrp.name());
1018
1019 wf.putValue(ofile);
1020
1021 IntegerUniqueArray array_id(256);
1022
1023 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1024 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1025 ConstArrayView<Item> items = type_info.items();
1026 Integer nb_sub_part = items.size();
1027 if (nb_sub_part == 0)
1028 continue;
1029
1030 String type_name = type_info.name();
1031 writeFileString(ofile, type_name);
1032
1033 writeFileInt(ofile, nb_sub_part);
1034
1035#if 0
1036 // Save the uniqueId() of the entities
1037 for( ConstArrayView<Item>::const_iter i(items); i(); ++i ){
1038 Item mi = *i;
1039 writeFileInt(ofile,mi.uniqueId()+1);
1040 }
1041#endif
1042
1043 if (type_name == "nfaced") {
1044 // Special handling for non-standard cells
1045 // Since our faces are not oriented relative to a
1046 // cell, we use the local connectivity of each face.
1047 // 1. Save the number of faces for each element
1048 {
1049 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1050 // All elements have the same number of faces
1051 Item mi = *items.data();
1052 Cell cell = mi.toCell();
1053 Integer nb_face = cell.nbFace();
1054 for (Integer z = 0; z < nb_sub_part; ++z)
1055 writeFileInt(ofile, nb_face);
1056 }
1057 else { // mesh has general items
1058 // All items do not have the same face number
1059 for (Item mi : items) {
1060 writeFileInt(ofile, mi.toCell().nbFace());
1061 }
1062 }
1063 }
1064 // 2. Save for each element, the number of nodes for each
1065 // of these faces
1066 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1067 for (Item mi : items) {
1068 const ItemTypeInfo* item_info = mi.typeInfo();
1069 Integer nb_face = item_info->nbLocalFace();
1070 for (Integer z = 0; z < nb_face; ++z)
1071 writeFileInt(ofile, item_info->localFace(z).nbNode());
1072 }
1073 }
1074 else { // mesh has general items
1075 for (Item mi : items) {
1076 Cell cell = mi.toCell();
1077 for (Face face : cell.faces()) {
1078 writeFileInt(ofile, face.nbNode());
1079 }
1080 }
1081 }
1082 // 3. Save for each face of each element the list of these
1083 // nodes
1084 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1085 for (Item item : items) {
1086 Cell cell(item.toCell());
1087 const ItemTypeInfo* item_info = cell.typeInfo();
1088 //Cell cell = mi.toCell();
1089 Integer nb_face = item_info->nbLocalFace();
1090 for (Integer z = 0; z < nb_face; ++z) {
1091 const ItemTypeInfo::LocalFace& local_face = item_info->localFace(z);
1092 Integer nb_node = local_face.nbNode();
1093 array_id.resize(nb_node);
1094 for (Integer y = 0; y < nb_node; ++y) {
1095 // Node direction inversion
1096 // A priori, there is a bug in Ensight (7.4.1(g)) concerning the
1097 // intersections of this type of elements with Ensight
1098 // objects (plane, sphere, ...). Regardless of the orientation
1099 // of the retained faces, the behavior is not correct.
1100 array_id[y] = nodes_index[cell.node(local_face.node(y)).localId()];
1101 }
1102 writeFileArray(ofile, array_id);
1103 }
1104 }
1105 }
1106 else { // mesh has general items
1107 for (Item item : items) {
1108 Cell cell = item.toCell();
1109 Integer nb_face = cell.nbFace();
1110 for (Integer z = 0; z < nb_face; ++z) {
1111 const Face local_face = cell.face(z);
1112 Integer nb_node = local_face.nbNode();
1113 array_id.resize(nb_node);
1114 for (Integer y = 0; y < nb_node; ++y) {
1115 array_id[y] = nodes_index[local_face.node(y).localId()];
1116 }
1117 writeFileArray(ofile, array_id);
1118 }
1119 }
1120 }
1121 }
1122 else if (type_name == "nsided") {
1123 // Special handling for faces with more than 4 nodes:
1124
1125 // 1. Save for each element, the number of its nodes
1126 //cerr << "** NSIDED ELEMENT\n";
1127 for (Item mi : items) {
1129 Integer nb_node = e.nbNode();
1130 writeFileInt(ofile, nb_node);
1131 }
1132 // 2. Save for each element the list of its nodes
1133 for (Item mi : items) {
1135 Integer nb_node = e.nbNode();
1136 array_id.resize(nb_node);
1137 for (Integer z = 0; z < nb_node; ++z) {
1138 array_id[z] = nodes_index[e.node(z).localId()];
1139 }
1140 writeFileArray(ofile, array_id);
1141 }
1142 }
1143 else {
1144 // General case
1145
1146 Integer nb_node = type_info.nbNode();
1147 array_id.resize(nb_node);
1148
1149 // Save the elements.
1150
1151 // Save the connectivity of the elements
1152 if (type_info.hasReindex()) {
1153 ConstArrayView<Integer> reindex = type_info.reindex();
1154 for (Item mi : items) {
1156 for (Integer j = 0; j < nb_node; ++j) {
1157 array_id[j] = nodes_index[e.node(reindex[j]).localId()];
1158 }
1159 writeFileArray(ofile, array_id);
1160 }
1161 }
1162 else { // no reindex
1163 for (Item mi : items) {
1165 for (Integer j = 0; j < nb_node; ++j) {
1166 array_id[j] = nodes_index[e.node(j).localId()];
1167 }
1168 writeFileArray(ofile, array_id);
1169 }
1170 }
1171 }
1172 }
1173}
1174
1175/*---------------------------------------------------------------------------*/
1176/*---------------------------------------------------------------------------*/
1200void DumpWEnsight7::
1201_saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
1202 WriteBase& from_func)
1203{
1204 ItemGroup igrp = ensight_grp.group();
1205
1206 writeFileString(ofile, "part");
1207 writeFileInt(ofile, ensight_grp.partId());
1208
1209 // Elements of the same type (especially 'nfaced', 'haxa8', or 'nsided')
1210 // must be written in a single block (thus unified type label).
1211 // Furthermore, vector data must be interleaved.
1212 String last_type_name;
1214 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1215 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1216 ConstArrayView<Item> items(type_info.items());
1217 Integer nb_sub_part = items.size();
1218 if (nb_sub_part == 0)
1219 continue;
1220 String type_name = type_info.name();
1221 if (type_name != last_type_name) {
1222 // Close the previous write
1223 if (func.get()) {
1224 func->end();
1225 func->putValue(ofile);
1226 }
1227 last_type_name = type_name;
1228 writeFileString(ofile, type_name);
1229 func = from_func.clone();
1230 func->begin();
1231 }
1232
1233 // Save the variables.
1234 func->write(items);
1235 }
1236
1237 // Final closure
1238 if (func.get()) {
1239 func->end();
1240 func->putValue(ofile);
1241 }
1242}
1243
1244/*---------------------------------------------------------------------------*/
1245/*---------------------------------------------------------------------------*/
1246
1247void DumpWEnsight7::
1248writeFileInt(std::ostream& o, int value)
1249{
1250 if (m_is_binary) {
1251 o.write((const char*)&value, sizeof(int));
1252 }
1253 else {
1254 o.width(DumpWEnsight7::int_width);
1255 o << value;
1256 o << '\n';
1257 }
1258}
1259
1260/*---------------------------------------------------------------------------*/
1261/*---------------------------------------------------------------------------*/
1262
1263Integer DumpWEnsight7::
1264writeIntSize() const
1265{
1266 if (m_is_binary)
1267 return sizeof(int);
1268 return DumpWEnsight7::int_width + 1;
1269}
1270
1271/*---------------------------------------------------------------------------*/
1272/*---------------------------------------------------------------------------*/
1273
1274void DumpWEnsight7::
1275writeFileDouble(std::ostream& o, double value)
1276{
1277 if (m_is_binary) {
1278 float fvalue = (float)(value);
1279 o.write((const char*)&fvalue, sizeof(float));
1280 }
1281 else {
1282 o.width(12);
1283 o.precision(5);
1284 o.flags(std::ios::scientific);
1285 o << value;
1286 o << '\n';
1287 }
1288}
1289
1290/*---------------------------------------------------------------------------*/
1291/*---------------------------------------------------------------------------*/
1292
1293Integer DumpWEnsight7::
1294writeDoubleSize() const
1295{
1296 Integer float_size = (Integer)(sizeof(float));
1297 return (m_is_binary) ? float_size : (12 + 1);
1298}
1299
1300/*---------------------------------------------------------------------------*/
1301/*---------------------------------------------------------------------------*/
1302
1303void DumpWEnsight7::
1304writeFileArray(std::ostream& o, IntegerConstArrayView value)
1305{
1306 if (m_is_binary) {
1307 o.write((const char*)value.data(), sizeof(Integer) * value.size());
1308 }
1309 else {
1310 for (Integer i = 0, s = value.size(); i < s; ++i) {
1311 o.width(DumpWEnsight7::int_width);
1312 o << value[i];
1313 }
1314 o << '\n';
1315 }
1316}
1317
1318/*---------------------------------------------------------------------------*/
1319/*---------------------------------------------------------------------------*/
1320
1321void DumpWEnsight7::
1322writeFileString(std::ostream& o, const String& str)
1323{
1324 if (m_is_binary) {
1325 char buf[g_line_length];
1326 for (int i = 0; i < g_line_length; ++i)
1327 buf[i] = '\0';
1328 CStringUtils::copyn(buf, str.localstr(), g_line_length);
1329 buf[g_line_length - 1] = '\0';
1330 o.write(buf, g_line_length);
1331 }
1332 else {
1333 o << str << '\n';
1334 }
1335}
1336
1337/*---------------------------------------------------------------------------*/
1338/*---------------------------------------------------------------------------*/
1339
1340void DumpWEnsight7::
1341_writeFileHeader(std::ostream& o, bool write_c_binary)
1342{
1343 if (m_is_master) {
1344 if (_isNewBlocFile() && m_is_binary && write_c_binary)
1345 writeFileString(o, "C Binary");
1346 if (m_fileset_size != 0) {
1347 std::ostringstream ostr;
1348 ostr << "BEGIN TIME STEP "
1349 << "# " << m_times.size();
1350 writeFileString(o, ostr.str().c_str());
1351 }
1352 }
1353}
1354
1355/*---------------------------------------------------------------------------*/
1356/*---------------------------------------------------------------------------*/
1364class DumpWEnsight7OutFile
1365{
1366 public:
1367
1368 DumpWEnsight7OutFile(DumpWEnsight7& dw, const String& filename, int outtype)
1369 : m_dw(dw)
1370 , m_filename(filename)
1371 , m_is_master(dw.isMasterProcessor())
1372 , m_is_parallel_output(dw.isParallelOutput())
1373 , m_stream(0)
1374 , m_filestream(0)
1375 {
1376 if (m_is_master) {
1377 m_filestream = new std::ofstream(filename.localstr(), (std::ios_base::openmode)outtype);
1378 m_stream = &m_strstream;
1379 if (!(*m_filestream))
1380 m_dw.warning() << "Unable to open file " << filename;
1381 }
1382 else {
1383 // TODO attention to memory leaks.
1384 m_stream = &m_strstream;
1385 }
1386 ARCANE_CHECK_PTR(m_stream);
1387 }
1388 ~DumpWEnsight7OutFile()
1389 {
1390 delete m_filestream;
1391 }
1392
1393 public:
1394
1395 void syncFile()
1396 {
1397 IParallelMng* parallel_mng = m_dw.parallelMng();
1398 if (m_is_master) {
1399 ARCANE_CHECK_PTR(m_filestream);
1400 ARCANE_CHECK_PTR(m_strstream);
1401 //Integer pos = m_strstream->tellp();
1402 (*m_filestream) << m_strstream.str();
1403 }
1404 if (m_is_parallel_output) {
1405 if (m_is_master) {
1406 ARCANE_CHECK_PTR(m_filestream);
1407
1408 // The master iterates through all processors and requests from each
1409 // the size of each save, and if it is not zero,
1410 // receives the message.
1411 Integer nb_proc = parallel_mng->commSize();
1412 UniqueArray<int> len_array(1);
1413 UniqueArray<Byte> str_array;
1414 for (Integer i = 1; i < nb_proc; ++i) {
1415 m_dw.debug(Trace::High) << "Waiting for length of processor " << i;
1416 parallel_mng->recv(len_array, i);
1417 Integer len = len_array[0];
1418 m_dw.debug(Trace::High) << "Length of processor " << i << " : " << len;
1419 if (len != 0) {
1420 str_array.resize(len);
1421 m_dw.debug(Trace::High) << "Waiting for receving geom of processor " << i;
1422 parallel_mng->recv(str_array, i);
1423 m_dw.debug(Trace::High) << "Receving geom of processor " << i;
1424 m_filestream->write((const char*)str_array.data(), str_array.size());
1425 }
1426 }
1427 }
1428 else {
1429 ARCANE_CHECK_PTR(m_strstream);
1430 // A slave sends to the master processor (currently processor 0)
1431 // the size of its data and then the data itself.
1432 // It is important to take the length of the string returned by m_strstream
1433 // and not just c_str() because the stream might contain information
1434 // in binary format, and we would stop at the first zero.
1435 UniqueArray<int> len_array(1);
1436 std::string str = m_strstream.str();
1437 Integer len = arcaneCheckArraySize(str.length());
1438 UniqueArray<Byte> bytes(len);
1439 {
1440 // Copy the string \a str into bytes
1441 Integer index = 0;
1442 for (ConstIterT<std::string> i(str); i(); ++i, ++index)
1443 bytes[index] = *i;
1444 }
1445 m_dw.debug(Trace::High) << "Not a master. " << m_filename << " size = " << len;
1446 //Integer len = m_strstream->tellp();
1447 //Integer len = str.length();
1448 len_array[0] = len;
1449 m_dw.debug(Trace::High) << "Sending length for processor 0";
1450 parallel_mng->send(len_array, 0);
1451 if (len != 0) {
1452 //UniqueArray<char> str_array(len);
1453 //std::string s = m_strstream->str();
1454 //platform::stdMemcpy(str_array.begin(),s.c_str(),s.length());
1455 m_dw.debug(Trace::High) << "Sending data for processor 0";
1456 parallel_mng->send(bytes, 0); //str.c_str())__array,0);
1457 //parallel_mng->send(str_array,0);
1458 }
1459 }
1460 }
1461 if (m_is_master)
1462 if (!m_dw.isOneFilePerTime())
1463 m_dw.writeFileString(*m_filestream, "END TIME STEP");
1464 }
1465
1466 public:
1467
1468 std::ostream& operator()() { return *m_stream; }
1469
1470 private:
1471
1472 DumpWEnsight7& m_dw;
1473 String m_filename;
1474 bool m_is_master;
1475 bool m_is_parallel_output;
1476 std::ostream* m_stream;
1477 std::ostringstream m_strstream;
1478 std::ofstream* m_filestream;
1479};
1480
1481/*---------------------------------------------------------------------------*/
1482/*---------------------------------------------------------------------------*/
1483
1484/*---------------------------------------------------------------------------*/
1485/*---------------------------------------------------------------------------*/
1486
1488beginWrite()
1489{
1490 String buf = m_base_directory.file("ensight.case");
1491
1492 IParallelMng* parallel_mng = m_parallel_mng;
1493 bool is_parallel = parallel_mng->isParallel();
1494 m_is_master = true;
1495 if (is_parallel && m_is_parallel_output)
1496 m_is_master = parallel_mng->commRank() == 0;
1497
1498 // Determines and creates the directory where the outputs will be written
1499 // for this iteration.
1501
1502 IMesh* mesh = m_mesh;
1503
1504 // Retrieves the list of groups and assigns each a unique identifier
1505 // unique for Ensight (part). The identifier number starts at 2, number 1
1506 // is for the node list
1507 {
1508
1509 ItemGroupList list_group;
1510 // If the list of groups to save is empty, save all groups.
1511 // Otherwise, save only the specified groups.
1512 Integer nb_group = m_save_groups.count();
1513 if (nb_group == 0)
1514 list_group.clone(mesh->groups());
1515 else
1516 list_group.clone(m_save_groups);
1517 // Looks at the list of partial variables, and adds their group to the list
1518 // of groups to save.
1519 for (VariableList::Enumerator ivar(m_save_variables); ++ivar;) {
1520 IVariable* var = *ivar;
1521 if (!var->isPartial())
1522 continue;
1523 ItemGroup var_group = var->itemGroup();
1524 if (!list_group.contains(var_group))
1525 list_group.add(var_group);
1526 }
1527 Integer partid = 1;
1529 partid += parallel_mng->commRank() * list_group.count();
1530
1531 _computeGroupParts(list_group, partid);
1532
1533 // Retrieves the total number of elements in the groups.
1534 Integer total_nb_element = 0;
1535 m_total_nb_group = 0;
1536 for (auto i : m_parts) {
1537 total_nb_element += i->totalNbElement();
1539 }
1540
1541 m_total_nb_element = total_nb_element;
1542 debug() << "Total nb element " << m_total_nb_element << " and group " << m_total_nb_group;
1543 debug() << "Add nodes " << mesh->nbNode();
1544 }
1545
1546 // Saves the geometry in Ensight7 gold format
1547 if (!(m_times.size() > 1 && m_force_first_geometry)) {
1548 String filename;
1549 _buildFileName("ensight.geo", filename);
1550
1551 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1552
1553 _writeFileHeader(dw_ofile(), true);
1554
1555 if (m_is_master) {
1556 writeFileString(dw_ofile(), "Output ensight test");
1557 writeFileString(dw_ofile(), "File description");
1558 writeFileString(dw_ofile(), "node id assign");
1559 writeFileString(dw_ofile(), "element id assign");
1560 }
1561
1562 IMesh* mesh = m_mesh;
1563 NodeGroup all_nodes = mesh->allNodes();
1564
1565 // This array is used for each cell entity, face, or edge to
1566 // reference its nodes relative to the coordinate array
1567 // used by Ensight. The first element of this array has index 1
1568 UniqueArray<Integer> all_nodes_index(mesh->itemFamily(IK_Node)->maxLocalId());
1569 all_nodes_index.fill(0);
1570
1571 UniqueArray<Real3> coords_backup;
1572 ConstArrayView<Real3> coords_array;
1573 if (mesh->parentMesh()) {
1574 SharedVariableNodeReal3 nodes_coords(mesh->sharedNodesCoordinates());
1575 coords_backup.resize(mesh->nodeFamily()->maxLocalId());
1576 ENUMERATE_NODE (i_item, all_nodes) {
1577 coords_backup[i_item.localId()] = nodes_coords[i_item];
1578 }
1579 coords_array = coords_backup.view();
1580 }
1581 else {
1582 VariableNodeReal3& nodes_coords(mesh->toPrimaryMesh()->nodesCoordinates());
1583 coords_array = ConstArrayView<Real3>(nodes_coords.asArray());
1584 }
1585
1586 WriteReal3 wf(*this, coords_array);
1587 {
1588 wf.init();
1589 writeFileString(wf.stream(), "coordinates");
1590 writeFileInt(wf.stream(), all_nodes.size());
1591 wf.begin();
1592
1593 // Stores the local indices for Ensight
1594 {
1595 Integer ensight_index = 1;
1596 ENUMERATE_ITEM (i_item, all_nodes) {
1597 const Item& item = *i_item;
1598 all_nodes_index[item.localId()] = ensight_index;
1599 ++ensight_index;
1600 }
1601 }
1602
1603 // Displays the unique node numbers
1604#if 0
1605 {
1606 ENUMERATE_ITEM(i_item,all_nodes){
1607 const Item& item = *i_item;
1608 writeFileInt(wf.stream(),item.uniqueId()+1);
1609 }
1610 }
1611#endif
1612 // Displays the coordinates of each node
1613 ENUMERATE_ITEM (i_item, all_nodes) {
1614 const Item& item = *i_item;
1615 wf.write(item.localId());
1616 }
1617 wf.end();
1618 }
1619
1620 for (const GroupPartInfo* part : m_parts)
1621 _saveGroup(dw_ofile(), *part, all_nodes_index, wf);
1622
1623 dw_ofile.syncFile();
1624 }
1625}
1626
1627/*---------------------------------------------------------------------------*/
1628/*---------------------------------------------------------------------------*/
1629
1631endWrite()
1632{
1633 // Saving unique identifiers
1634 if (m_save_uids) {
1636 ENUMERATE_CELL (icell, m_mesh->allCells()) {
1637 cell_uids[icell] = (Real)(icell->uniqueId().asInt64());
1638 }
1639 IVariable* cell_uid_var = cell_uids.variable();
1640 m_save_variables.add(cell_uid_var);
1641 cell_uid_var->setUsed(true);
1642 cell_uid_var->notifyBeginWrite();
1643 write(cell_uid_var, cell_uid_var->data());
1644
1645 // GG: NOTE: I am not sure this works well.
1646 //TODO: remove the use of two variables
1648 UniqueArray<Real> node_uids2(m_mesh->nodeFamily()->allItems().size());
1649 ENUMERATE_NODE (inode, m_mesh->allNodes()) {
1650 node_uids[inode] = inode->uniqueId().asInt32();
1651 node_uids2[inode.index()] = (Real)inode->uniqueId().asInt64();
1652 }
1653
1654 IVariable* node_uid_var = node_uids.variable();
1655 m_save_variables.add(node_uid_var);
1656 node_uid_var->setUsed(true);
1657 _writeRealValT<Real>(*node_uid_var, node_uids2); // work around bug for node variables
1658 }
1659
1660 String buf = m_base_directory.file("ensight.case");
1661
1662 // Only a master processor generates a 'case' file
1663 if (m_is_master) {
1664
1665 m_case_file.open(buf.localstr());
1666
1667 if (!m_case_file)
1668 warning() << "Unable to write to file: <" << buf << "> error: " << m_case_file.rdstate();
1669
1670 debug() << "** Exporting data to " << m_base_directory.path();
1671 m_case_file << "FORMAT\ntype: ensight gold\n";
1672
1673 m_case_file << "\nGEOMETRY\n";
1674 m_case_file << "model: 1";
1675 if (m_fileset_size != 0)
1676 m_case_file << " 1 ";
1677 if (m_force_first_geometry)
1678 _writeWildcardFilename(m_case_file, "ensight.geo", '0');
1679 else
1680 _writeWildcardFilename(m_case_file, "ensight.geo", '*');
1681 //m_case_file << " [change_coords_only]\n";
1682 m_case_file << "\n";
1683
1684 m_case_file << "\nVARIABLE\n";
1685 m_case_file << m_case_file_variables.str();
1686
1687 // Saving in time. For paraview, it must be placed after the variables
1688 m_case_file << "\nTIME\n";
1689 m_case_file << "time set: 1\n";
1690 m_case_file << "number of steps: " << m_times.size() << '\n';
1691 m_case_file << "filename start number: 0\n";
1692 m_case_file << "filename increment: 1\n";
1693 m_case_file << "time values:\n";
1694 // Be careful not to exceed 79 characters per line
1695 // allowed by Ensight. To be sure, we only write one time step
1696 // per line. The times are saved with the maximum number of significant digits
1697 // because Ensight does not like two times being equal.
1698 std::streamsize old_precision = m_case_file.precision(FloatInfo<Real>::maxDigit());
1699 for (Integer i = 0, is = m_times.size(); i < is; ++i)
1700 m_case_file << m_times[i] << '\n';
1701 m_case_file << '\n';
1702 m_case_file.precision(old_precision);
1703
1704 if (m_fileset_size != 0) {
1705 m_case_file << "FILE\n";
1706 m_case_file << "file set: 1\n";
1707 if (m_fileset_size != 0) {
1708 Integer nb_timeset = (m_times.size() / m_fileset_size);
1709 for (Integer i = 0; i < nb_timeset; ++i) {
1710 m_case_file << "filename index: " << i << "\n";
1711 m_case_file << "number of steps: " << m_fileset_size << '\n';
1712 }
1713 if (nb_timeset > 0)
1714 m_case_file << "filename index: " << nb_timeset << "\n";
1715 m_case_file << "number of steps: " << m_times.size() - (nb_timeset * m_fileset_size) << '\n';
1716 }
1717 else {
1718 m_case_file << "number of steps: " << m_times.size() << '\n';
1719 }
1720 m_case_file << '\n';
1721 }
1722 }
1723 m_case_file.flush();
1724 m_case_file.close();
1725}
1726
1727/*---------------------------------------------------------------------------*/
1728/*---------------------------------------------------------------------------*/
1729
1730/*---------------------------------------------------------------------------*/
1731/*---------------------------------------------------------------------------*/
1732
1746{
1747 if (!v.isUsed())
1748 return false;
1749 eItemKind ik = v.itemKind();
1750 if (ik != IK_Cell && ik != IK_Node && ik != IK_Face)
1751 return false;
1752 // If a variable list is specified, check that the variable is in
1753 // this list. If this list is empty, all are automatically saved.
1754 Integer nb_var = m_save_variables.count();
1755 if (nb_var != 0) {
1756 return m_save_variables.contains(&v);
1757 }
1758 return true;
1759}
1760
1761/*---------------------------------------------------------------------------*/
1762/*---------------------------------------------------------------------------*/
1776_buildFileName(const String& name, String& filename)
1777{
1778 StringBuilder fn_builder;
1779 if (m_fileset_size == 0) {
1780 Integer current_time = m_times.size() - 1;
1781 fn_builder = m_base_directory.path();
1782 fn_builder += "/";
1783 fn_builder += name;
1784 if (m_is_master) {
1785 Directory dir(fn_builder.toString());
1786 dir.createDirectory();
1787 }
1788 fn_builder += "/";
1789 fn_builder += name;
1790
1791 {
1792 OStringStream ostr;
1793 ostr().fill('0'); // Fill character.
1794 ostr().width(m_max_prots_digit);
1795 ostr() << current_time;
1796 fn_builder += ostr.str();
1797 }
1798
1799 //fn_builder += current_time;
1800
1801 //info() << " BUILD FILE NAME name=" << name << " filename=" << fn_builder;
1802 }
1803 else {
1804 fn_builder = m_part_directory.path();
1805 fn_builder += "/";
1806 fn_builder += name;
1807 }
1808 filename = fn_builder;
1809}
1810
1811/*---------------------------------------------------------------------------*/
1812/*---------------------------------------------------------------------------*/
1813
1814bool DumpWEnsight7::
1815_isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind)
1816{
1817 eItemKind group_kind = group.itemKind();
1818 if (item_kind == IK_Unknown)
1819 return false;
1820 return group_kind == item_kind;
1821}
1822
1823/*---------------------------------------------------------------------------*/
1824/*---------------------------------------------------------------------------*/
1837{
1838 Integer prot_index = 0;
1839 bool has_prot = false;
1840 if (m_fileset_size != 0) {
1841 Integer nb_time = m_times.size();
1842 if (nb_time != 0)
1843 prot_index = (nb_time - 1) / m_fileset_size;
1844 has_prot = true;
1845 }
1846
1847 if (m_is_master)
1848 m_base_directory.createDirectory();
1849
1850 if (has_prot) {
1851 OStringStream ostr;
1852 ostr() << "bloc";
1853 ostr().fill('0'); // Fill character.
1854 ostr().width(m_max_prots_digit);
1855 ostr() << prot_index;
1856 //ostr() << '\0';
1857 String buf = ostr.str();
1859 if (m_is_master)
1860 m_part_directory.createDirectory();
1861 }
1862 else
1864}
1865
1866/*---------------------------------------------------------------------------*/
1867/*---------------------------------------------------------------------------*/
1868
1869void DumpWEnsight7::
1870_writeWildcardFilename(std::ostream& ofile, const String& filename, char joker)
1871{
1872 if (m_fileset_size == 0) {
1873 ofile << ' ' << filename << '/' << filename;
1874 for (Integer i = 0; i < m_max_prots_digit; ++i)
1875 ofile << joker;
1876 }
1877 else {
1878 ofile << " bloc";
1879 Integer nb_time = m_times.size();
1880 // If the number of times is less than the size of a fileset-set,
1881 // there is no need to put a '*'. We can directly
1882 // put zeros. This is also essential to prevent
1883 // paraview from crashing when it rereads this type of files.
1884 if (nb_time <= m_fileset_size)
1885 joker = '0';
1886 for (Integer i = 0; i < m_max_prots_digit; ++i)
1887 ofile << joker;
1888 ofile << "/" << filename;
1889 }
1890}
1891
1892/*---------------------------------------------------------------------------*/
1893/*---------------------------------------------------------------------------*/
1894
1895bool DumpWEnsight7::
1896_isNewBlocFile() const
1897{
1898 Integer nb_time = m_times.size();
1899
1900 if (nb_time == 1)
1901 return true;
1902 if (m_fileset_size == 0)
1903 return true;
1904
1905 Integer modulo = (nb_time - 1) % m_fileset_size;
1906
1907 if (modulo == 0)
1908 return true;
1909 return false;
1910}
1911
1912/*---------------------------------------------------------------------------*/
1913/*---------------------------------------------------------------------------*/
1914
1915int DumpWEnsight7::
1916_fileOuttype() const
1917{
1918 return ((isBinary()) ? std::ios::binary : 0) | ((_isNewBlocFile()) ? std::ios::trunc : std::ios::app);
1919}
1920
1921/*---------------------------------------------------------------------------*/
1922/*---------------------------------------------------------------------------*/
1923
1927template <typename T>
1930{
1931 debug() << "Saving variable1 " << v.name() << " ptr=" << ptr.data() << " ps=" << ptr.size();
1932
1933 if (!_isValidVariable(v))
1934 return;
1935
1936 String filename;
1937 _buildFileName(v.name(), filename);
1938
1939 debug() << "Saving variable " << v.name() << " in " << filename;
1940
1941 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1942
1943 _writeFileHeader(dw_ofile(), false);
1944
1945 if (m_is_master)
1946 writeFileString(dw_ofile(), v.name());
1947 String var_type_str;
1948
1949 if (m_is_master) {
1950 switch (v.itemKind()) {
1951 case IK_Cell:
1952 case IK_Face:
1953 var_type_str = "scalar per element: ";
1954 break;
1955 case IK_Node:
1956 var_type_str = "scalar per node: ";
1957 break;
1958 default:
1959 break;
1960 }
1961
1962 m_case_file_variables << var_type_str;
1963 m_case_file_variables << " 1 ";
1964 if (m_fileset_size != 0)
1965 m_case_file_variables << " 1 ";
1966 m_case_file_variables << v.name();
1967 _writeWildcardFilename(m_case_file_variables, v.name());
1968 m_case_file_variables << '\n';
1969 }
1970
1971 switch (v.itemKind()) {
1972 case IK_Cell:
1973 case IK_Face:
1974 case IK_Edge: {
1975 GroupIndexTable* idx = nullptr;
1976
1977 if (v.isPartial()) {
1978 idx = v.itemGroup().localIdToIndex().get();
1979 }
1980
1981 WriteDouble<T> wf(*this, ptr, idx);
1982 for (const GroupPartInfo* part : m_parts) {
1983 bool need_save = false;
1984 if (v.isPartial())
1985 need_save = v.itemGroup() == part->group();
1986 else
1987 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
1988 if (need_save)
1989 _saveVariableOnGroup(dw_ofile(), *part, wf);
1990 }
1991 } break;
1992 case IK_Node: {
1993 if (v.isPartial())
1994 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
1995 WriteDouble<T> wf(*this, ptr);
1996 wf.begin();
1997 for (Integer i = 0; i < ptr.size(); ++i)
1998 wf.write(i);
1999 wf.end();
2000 for (const GroupPartInfo* part : m_parts) {
2001 writeFileString(dw_ofile(), "part");
2002 writeFileInt(dw_ofile(), part->partId());
2003 writeFileString(dw_ofile(), "coordinates");
2004 wf.putValue(dw_ofile());
2005 }
2006 } break;
2007 default:
2008 break;
2009 }
2010
2011 dw_ofile.syncFile();
2012
2013 //if (m_is_transient && m_is_master)
2014 //writeFileString(dw_ofile(),"END TIME STEP");
2015}
2016
2017/*---------------------------------------------------------------------------*/
2018/*---------------------------------------------------------------------------*/
2019
2023template <typename T>
2026{
2027 if (!_isValidVariable(v))
2028 return;
2029
2030 for (Integer idim2 = 0; idim2 < ptr.dim2Size(); ++idim2) {
2031 String vname = v.name() + String("_") + idim2;
2032 String filename;
2033 _buildFileName(vname, filename);
2034
2035 debug() << "Saving variable " << v.name() << " component " << idim2 << " in " << filename;
2036
2037 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2038
2039 _writeFileHeader(dw_ofile(), false);
2040
2041 if (m_is_master)
2042 writeFileString(dw_ofile(), vname);
2043 String var_type_str;
2044
2045 if (m_is_master) {
2046 switch (v.itemKind()) {
2047 case IK_Cell:
2048 case IK_Face:
2049 var_type_str = "scalar per element: ";
2050 break;
2051 case IK_Node:
2052 var_type_str = "scalar per node: ";
2053 break;
2054 default:
2055 break;
2056 }
2057
2058 m_case_file_variables << var_type_str;
2059 m_case_file_variables << " 1 ";
2060 if (m_fileset_size != 0)
2061 m_case_file_variables << " 1 ";
2062 m_case_file_variables << vname;
2063 _writeWildcardFilename(m_case_file_variables, vname);
2064 m_case_file_variables << '\n';
2065 }
2066
2067 switch (v.itemKind()) {
2068 case IK_Cell:
2069 case IK_Face:
2070 case IK_Edge: {
2071 GroupIndexTable* idx = nullptr;
2072
2073 if (v.isPartial()) {
2074 idx = v.itemGroup().localIdToIndex().get();
2075 }
2076
2077 WriteArrayDouble<T> wf(*this, ptr, idim2, idx);
2078 for (const GroupPartInfo* part : m_parts) {
2079 bool need_save = false;
2080 if (v.isPartial())
2081 need_save = v.itemGroup() == part->group();
2082 else
2083 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2084 if (need_save)
2085 _saveVariableOnGroup(dw_ofile(), *part, wf);
2086 }
2087 } break;
2088 case IK_Node: {
2089 if (v.isPartial())
2090 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2091 WriteArrayDouble<T> wf(*this, ptr, idim2);
2092 wf.begin();
2093 for (Integer i = 0; i < ptr.dim1Size(); ++i)
2094 wf.write(i);
2095 wf.end();
2096 for (const GroupPartInfo* part : m_parts) {
2097 writeFileString(dw_ofile(), "part");
2098 writeFileInt(dw_ofile(), part->partId());
2099 writeFileString(dw_ofile(), "coordinates");
2100 wf.putValue(dw_ofile());
2101 }
2102 } break;
2103 default:
2104 break;
2105 }
2106
2107 dw_ofile.syncFile();
2108 }
2109
2110 //if (m_is_transient && m_is_master)
2111 //writeFileString(dw_ofile(),"END TIME STEP");
2112}
2113
2114/*---------------------------------------------------------------------------*/
2115/*---------------------------------------------------------------------------*/
2116
2120template <typename T>
2123{
2124 ARCANE_UNUSED(ptr);
2125
2126 if (!_isValidVariable(v))
2127 return;
2128
2129 warning() << "Impossible to write array variable "
2130 << v.name() << " of non-constant size; variable saving skipped";
2131}
2132
2133/*---------------------------------------------------------------------------*/
2134/*---------------------------------------------------------------------------*/
2135
2141{
2142 if (!_isValidVariable(v))
2143 return;
2144
2145 String filename;
2146 _buildFileName(v.name(), filename);
2147
2148 debug() << "Saving variable " << v.name() << " in " << filename;
2149
2150 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2151
2152 _writeFileHeader(dw_ofile(), false);
2153 if (m_is_master)
2154 writeFileString(dw_ofile(), v.name());
2155
2156 if (m_is_master) {
2157 switch (v.itemKind()) {
2158 case IK_Cell:
2159 case IK_Face:
2160 m_case_file_variables << "vector per element: ";
2161 break;
2162 case IK_Node:
2163 m_case_file_variables << "vector per node: ";
2164 break;
2165 default:
2166 break;
2167 }
2168
2169 m_case_file_variables << " 1 ";
2170 if (m_fileset_size != 0)
2171 m_case_file_variables << " 1 ";
2172 m_case_file_variables << v.name();
2173
2174 _writeWildcardFilename(m_case_file_variables, v.name());
2175 m_case_file_variables << '\n';
2176 }
2177
2178 switch (v.itemKind()) {
2179 case IK_Cell:
2180 case IK_Face:
2181 case IK_Edge: {
2182 GroupIndexTable* idx = nullptr;
2183
2184 if (v.isPartial()) {
2185 idx = v.itemGroup().localIdToIndex().get();
2186 }
2187
2188 WriteReal3 wf(*this, ptr, idx);
2189 for (const GroupPartInfo* part : m_parts) {
2190 bool need_save = false;
2191 if (v.isPartial())
2192 need_save = v.itemGroup() == part->group();
2193 else
2194 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2195 if (need_save)
2196 _saveVariableOnGroup(dw_ofile(), *part, wf);
2197 }
2198 } break;
2199 case IK_Node: {
2200 if (v.isPartial())
2201 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2202 WriteReal3 wf(*this, ptr);
2203 wf.begin();
2204 for (Integer i = 0; i < ptr.size(); ++i)
2205 wf.write(i);
2206 wf.end();
2207 for (const GroupPartInfo* part : m_parts) {
2208 writeFileString(dw_ofile(), "part");
2209 writeFileInt(dw_ofile(), part->partId());
2210 writeFileString(dw_ofile(), "coordinates");
2211 wf.putValue(dw_ofile());
2212 }
2213 } break;
2214 default:
2215 break;
2216 }
2217
2218 dw_ofile.syncFile();
2219}
2220
2221/*---------------------------------------------------------------------------*/
2222/*---------------------------------------------------------------------------*/
2223
2229{
2230 if (!_isValidVariable(v))
2231 return;
2232
2233 for (Integer idim2 = 0; idim2 < ptr.dim2Size(); ++idim2) {
2234 String vname = v.name() + String("_") + idim2;
2235 String filename;
2236 _buildFileName(vname, filename);
2237
2238 debug() << "Saving variable " << v.name() << " component " << idim2 << " in " << filename;
2239
2240 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2241
2242 _writeFileHeader(dw_ofile(), false);
2243 if (m_is_master)
2244 writeFileString(dw_ofile(), vname);
2245
2246 if (m_is_master) {
2247 switch (v.itemKind()) {
2248 case IK_Cell:
2249 case IK_Face:
2250 m_case_file_variables << "vector per element: ";
2251 break;
2252 case IK_Node:
2253 m_case_file_variables << "vector per node: ";
2254 break;
2255 default:
2256 break;
2257 }
2258
2259 m_case_file_variables << " 1 ";
2260 if (m_fileset_size != 0)
2261 m_case_file_variables << " 1 ";
2262 m_case_file_variables << vname;
2263
2264 _writeWildcardFilename(m_case_file_variables, vname);
2265 m_case_file_variables << '\n';
2266 }
2267
2268 switch (v.itemKind()) {
2269 case IK_Cell:
2270 case IK_Face:
2271 case IK_Edge: {
2272 GroupIndexTable* idx = nullptr;
2273
2274 if (v.isPartial()) {
2275 idx = v.itemGroup().localIdToIndex().get();
2276 }
2277
2278 WriteArrayReal3 wf(*this, ptr, idim2, idx);
2279 for (const GroupPartInfo* part : m_parts) {
2280 bool need_save = false;
2281 if (v.isPartial())
2282 need_save = v.itemGroup() == part->group();
2283 else
2284 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2285 if (need_save)
2286 _saveVariableOnGroup(dw_ofile(), *part, wf);
2287 }
2288 } break;
2289 case IK_Node: {
2290 if (v.isPartial())
2291 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2292 WriteArrayReal3 wf(*this, ptr, idim2);
2293 wf.begin();
2294 for (Integer i = 0; i < ptr.dim1Size(); ++i)
2295 wf.write(i);
2296 wf.end();
2297 for (const GroupPartInfo* part : m_parts) {
2298 writeFileString(dw_ofile(), "part");
2299 writeFileInt(dw_ofile(), part->partId());
2300 writeFileString(dw_ofile(), "coordinates");
2301 wf.putValue(dw_ofile());
2302 }
2303 } break;
2304 default:
2305 break;
2306 }
2307
2308 dw_ofile.syncFile();
2309 }
2310
2311 //if (m_is_transient && m_is_master)
2312 //writeFileString(dw_ofile(),"END TIME STEP");
2313}
2314
2315/*---------------------------------------------------------------------------*/
2316/*---------------------------------------------------------------------------*/
2317
2323{
2324 ARCANE_UNUSED(ptr);
2325
2326 if (!_isValidVariable(v))
2327 return;
2328
2329 warning() << "Impossible to write array variable " << v.name()
2330 << " of non-constant size; variable saving skipped";
2331}
2332
2333/*---------------------------------------------------------------------------*/
2334/*---------------------------------------------------------------------------*/
2335
2339class Ensight7PostProcessorService
2340: public PostProcessorWriterBase
2341{
2342 public:
2343
2344 Ensight7PostProcessorService(const ServiceBuildInfo& sbi)
2345 : PostProcessorWriterBase(sbi)
2346 , m_mesh(sbi.mesh())
2347 , m_writer(nullptr)
2348 {
2349 }
2350
2351 IDataWriter* dataWriter() override { return m_writer; }
2352 void notifyBeginWrite() override;
2353 void notifyEndWrite() override;
2354 void close() override {}
2355
2356 private:
2357
2358 IMesh* m_mesh;
2359 DumpW* m_writer;
2360};
2361
2362/*---------------------------------------------------------------------------*/
2363/*---------------------------------------------------------------------------*/
2364
2367{
2368 bool is_binary = true;
2369 Integer fileset_size = 100;
2370 bool is_parallel = subDomain()->parallelMng()->isParallel();
2371 bool use_degenerated_hexa = true;
2372 bool force_first_geometry = false;
2373 bool save_uids = false;
2374 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2375 variables(), groups(), is_binary, is_parallel,
2376 fileset_size, use_degenerated_hexa,
2377 force_first_geometry, save_uids);
2378}
2379
2382{
2383 delete m_writer;
2384 m_writer = 0;
2385}
2386
2387/*---------------------------------------------------------------------------*/
2388/*---------------------------------------------------------------------------*/
2389
2390/*---------------------------------------------------------------------------*/
2391/*---------------------------------------------------------------------------*/
2392
2396class Ensight7PostProcessorServiceV2
2398{
2399 public:
2400
2401 typedef ArcaneEnsight7PostProcessorObject BaseType;
2402
2403 public:
2404
2405 explicit Ensight7PostProcessorServiceV2(const ServiceBuildInfo& sbi)
2407 , m_mesh(sbi.mesh())
2408 , m_writer(nullptr)
2409 {
2410 }
2411
2412 IDataWriter* dataWriter() override { return m_writer; }
2413 void notifyBeginWrite() override;
2414 void notifyEndWrite() override;
2415 void close() override {}
2416
2417 void setMesh(IMesh* mesh) override
2418 {
2419 // TODO: A supprimer car méthode obsolète et n'est pas utilisé.
2420 m_mesh = mesh;
2421 }
2422
2423 private:
2424
2425 IMesh* m_mesh = nullptr;
2426 DumpW* m_writer = nullptr;
2427};
2428
2429/*---------------------------------------------------------------------------*/
2430/*---------------------------------------------------------------------------*/
2431
2434{
2435 // std::cout << " ############# IMesh = " << mesh() << " " << m_mesh << " ###########\n";
2436
2437 bool is_binary = true;
2438 Integer fileset_size = 0;
2439 bool is_parallel = m_mesh->parallelMng()->isParallel();
2440 is_binary = options()->binaryFile();
2441 fileset_size = options()->filesetSize();
2442 bool use_degenerated_hexa = options()->useDegeneratedHexa();
2443 bool force_first_geometry = options()->forceFirstGeometry();
2444 bool save_uids = options()->saveUids();
2445 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2446 variables(), groups(), is_binary, is_parallel, fileset_size,
2447 use_degenerated_hexa, force_first_geometry, save_uids);
2448}
2449
2452{
2453 delete m_writer;
2454 m_writer = nullptr;
2455}
2456
2457/*---------------------------------------------------------------------------*/
2458/*---------------------------------------------------------------------------*/
2459
2461 Ensight7PostProcessor);
2462
2463ARCANE_REGISTER_SERVICE_ENSIGHT7POSTPROCESSOR(Ensight7PostProcessor, Ensight7PostProcessorServiceV2);
2464
2465/*---------------------------------------------------------------------------*/
2466/*---------------------------------------------------------------------------*/
2467
2468} // namespace Arcane
2469
2470/*---------------------------------------------------------------------------*/
2471/*---------------------------------------------------------------------------*/
#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.
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:78
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:64
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.