Arcane  v4.1.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DumpWEnsight7.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* DumpWEnsight7.cc (C) 2000-2026 */
9/* */
10/* Exportations des fichiers au format Ensight7 gold. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/StringBuilder.h"
15#include "arcane/utils/Enumerator.h"
16#include "arcane/utils/Iterator.h"
17#include "arcane/utils/List.h"
18#include "arcane/utils/ScopedPtr.h"
19#include "arcane/utils/PlatformUtils.h"
20#include "arcane/utils/Iostream.h"
21#include "arcane/utils/Deleter.h"
22#include "arcane/utils/ITraceMng.h"
23#include "arcane/utils/OStringStream.h"
24#include "arcane/utils/NotImplementedException.h"
25#include "arcane/utils/CStringUtils.h"
26
27#include "arcane/IDataWriter.h"
28#include "arcane/Item.h"
29#include "arcane/ItemEnumerator.h"
30#include "arcane/IVariable.h"
31#include "arcane/ISubDomain.h"
32#include "arcane/IMesh.h"
33#include "arcane/IMeshSubMeshTransition.h"
34#include "arcane/StdNum.h"
35#include "arcane/ItemGroup.h"
36#include "arcane/IParallelMng.h"
37#include "arcane/Directory.h"
38#include "arcane/MeshVariable.h"
39#include "arcane/PostProcessorWriterBase.h"
40#include "arcane/Service.h"
41#include "arcane/SimpleProperty.h"
42#include "arcane/IItemFamily.h"
43#include "arcane/VariableCollection.h"
44#include "arcane/SharedVariable.h"
45
46#include "arcane/FactoryService.h"
47#include "arcane/ServiceFactory.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: Ajouter test avec des variables partielles
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61namespace Arcane
62{
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
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 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 void _initPartMap()
219 {
220 for (auto& ensight_part : m_parts) {
221 m_parts_map[ensight_part.type()] = &ensight_part;
222 }
223 }
224
225 void _init(bool use_degenerated_hexa)
226 {
227 ItemTypeMng* item_type_mng = m_group.mesh()->itemTypeMng();
228
229 // NOTE: il est important que les éléments de type 'nfaced'
230 // et 'nsided' soient contigues car Ensight doit sauver
231 // ensemble leur valeurs
232 m_parts.reserve(ItemTypeMng::nbBasicItemType());
233 m_parts.add(EnsightPart(IT_Line2, 2, "bar2")); // Bar
234 m_parts.add(EnsightPart(IT_Triangle3, 3, "tria3")); // Triangle
235 m_parts.add(EnsightPart(IT_Quad4, 4, "quad4")); // Quandrangle
236 m_parts.add(EnsightPart(IT_Pentagon5, 5, "nsided")); // Pentagone
237 m_parts.add(EnsightPart(IT_Hexagon6, 6, "nsided")); // Hexagone
238 m_parts.add(EnsightPart(IT_Heptagon7, 7, "nsided")); // Heptagone
239 m_parts.add(EnsightPart(IT_Octogon8, 8, "nsided")); // Octogone
240 // Recherche des autres types 'polygone'
241 for (Integer i_type = ItemTypeMng::nbBuiltInItemType(); i_type < ItemTypeMng::nbBasicItemType(); ++i_type) {
242 ItemTypeInfo* type_info = item_type_mng->typeFromId(i_type);
243 if (type_info->nbLocalNode() == type_info->nbLocalEdge()) { // Polygone trouvé
244 m_parts.add(EnsightPart(i_type, type_info->nbLocalNode(), "nsided"));
245 }
246 }
247 // Add polygons handled in general polyhedral mesh: no types defined
248 Int32 type_id = ItemTypeMng::nbBasicItemType();
249 if (item_type_mng->hasGeneralCells(m_group.mesh())) {
250 if (!m_is_polygonal_type_registration_done) {
251 ENUMERATE_ITEM (iitem, m_group) {
252 ItemWithNodes item = iitem->toItemWithNodes();
253 if (item.nbNode() == item.itemBase().nbEdge()) { // polygon found
254 (*(m_general_item_types))[item] = type_id;
255 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nsided"));
256 }
257 }
258 m_is_polygonal_type_registration_done = true;
259 }
260 }
261 m_parts.add(EnsightPart(IT_Tetraedron4, 4, "tetra4")); // Tetra
262 m_parts.add(EnsightPart(IT_Pyramid5, 5, "pyramid5")); // Pyramide
263 m_parts.add(EnsightPart(IT_Pentaedron6, 6, "penta6")); // Penta
264 m_parts.add(EnsightPart(IT_Hexaedron8, 8, "hexa8")); // Hexa
265 if (use_degenerated_hexa) {
266 m_parts.add(EnsightPart(IT_HemiHexa7, 8, "hexa8")); // HemiHexa7
267 {
268 Integer reindex[8] = { 1, 6, 5, 0, 2, 3, 4, 0 };
269 m_parts[m_parts.size() - 1].setReindex(reindex);
270 }
271 m_parts.add(EnsightPart(IT_HemiHexa6, 8, "hexa8")); // HemiHexa6
272 {
273 Integer reindex[8] = { 0, 1, 3, 5, 0, 2, 3, 4 };
274 m_parts[m_parts.size() - 1].setReindex(reindex);
275 }
276 m_parts.add(EnsightPart(IT_HemiHexa5, 8, "hexa8")); // HemiHexa5
277 {
278 Integer reindex[8] = { 0, 1, 3, 4, 0, 2, 3, 4 };
279 m_parts[m_parts.size() - 1].setReindex(reindex);
280 }
281 m_parts.add(EnsightPart(IT_AntiWedgeLeft6, 8, "hexa8")); // AntiWedgeLeft6
282 {
283 Integer reindex[8] = { 2, 0, 1, 2, 5, 3, 4, 4 };
284 m_parts[m_parts.size() - 1].setReindex(reindex);
285 }
286 m_parts.add(EnsightPart(IT_AntiWedgeRight6, 8, "hexa8")); // AntiWedgeRight6
287 {
288 Integer reindex[8] = { 2, 0, 1, 1, 5, 3, 4, 5 };
289 m_parts[m_parts.size() - 1].setReindex(reindex);
290 }
291 m_parts.add(EnsightPart(IT_DiTetra5, 8, "hexa8")); // DiTetra5
292 {
293 Integer reindex[8] = { 4, 4, 2, 3, 0, 1, 1, 3 };
294 m_parts[m_parts.size() - 1].setReindex(reindex);
295 }
296 }
297 else {
298 m_parts.add(EnsightPart(IT_HemiHexa7, 7, "nfaced")); // HemiHexa7
299 m_parts.add(EnsightPart(IT_HemiHexa6, 6, "nfaced")); // HemiHexa6
300 m_parts.add(EnsightPart(IT_HemiHexa5, 5, "nfaced")); // HemiHexa5
301 m_parts.add(EnsightPart(IT_AntiWedgeLeft6, 6, "nfaced")); // AntiWedgeLeft6
302 m_parts.add(EnsightPart(IT_AntiWedgeRight6, 6, "nfaced")); // AntiWedgeRight6
303 m_parts.add(EnsightPart(IT_DiTetra5, 5, "nfaced")); // DiTetra5
304 }
305 m_parts.add(EnsightPart(IT_Heptaedron10, 10, "nfaced")); // Wedge7
306 m_parts.add(EnsightPart(IT_Octaedron12, 12, "nfaced")); // Wedge8
307 m_parts.add(EnsightPart(IT_Enneedron14, 14, "nfaced")); // Wedge9
308 m_parts.add(EnsightPart(IT_Decaedron16, 16, "nfaced")); // Wedge10
309 // Recherche des autres types 'polyedre'
310 for (Integer i_type = ItemTypeMng::nbBuiltInItemType(); i_type < ItemTypeMng::nbBasicItemType(); ++i_type) {
311 ItemTypeInfo* type_info = item_type_mng->typeFromId(i_type);
312 if (type_info->nbLocalNode() != type_info->nbLocalEdge()) { // Polyèdre trouvé
313 m_parts.add(EnsightPart(i_type, type_info->nbLocalNode(), "nfaced"));
314 }
315 }
316 // Add polyhedra handled in general polyhedral mesh: no types defined
317 if (item_type_mng->hasGeneralCells(m_group.mesh())) {
318 if (!m_is_polyhedral_type_registration_done) {
319 ENUMERATE_ITEM (iitem, m_group) {
320 ItemWithNodes item = iitem->toItemWithNodes();
321 if (item.nbNode() == 1)
322 (*(m_general_item_types))[item] = IT_Vertex;
323 else if (item.nbNode() == 2)
324 (*(m_general_item_types))[item] = IT_Line2;
325 else if (item.nbNode() != item.itemBase().nbEdge()) { // polyhedron found
326 (*(m_general_item_types))[item] = type_id;
327 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nfaced"));
328 }
329 }
330 m_is_polyhedral_type_registration_done = true;
331 }
332 }
333 // if extra types are used, init a EnsightPart map to optimize GroupPartInfo fill
335 _initPartMap();
336 }
337 }
338 };
339
340 public:
341
342 //void writeFileString(ostream& o,ConstCString str);
343 void writeFileString(std::ostream& o, const String& str);
344 void writeFileInt(std::ostream& o, int value);
345 void writeFileDouble(std::ostream& o, double value);
346 Integer writeDoubleSize() const;
347 Integer writeIntSize() const;
348 void writeFileArray(std::ostream& o, IntegerConstArrayView value);
349 bool isBinary() const { return m_is_binary; }
350
351 public:
352
365 class WriteBase
366 {
367 public:
368
369 explicit WriteBase(DumpWEnsight7& dw)
370 : m_dw(dw)
371 {}
372 WriteBase(DumpWEnsight7& dw, GroupIndexTable* idx)
373 : m_dw(dw)
374 , m_idx(idx)
375 {}
376 WriteBase(const WriteBase& wb)
377 : m_dw(wb.m_dw)
378 , m_idx(wb.m_idx)
379 {}
380 virtual ~WriteBase() {}
381
382 public:
383
384 virtual WriteBase* clone() = 0;
385 virtual void begin() { init(); }
386 virtual void end() {}
387 virtual void write(ConstArrayView<Item> items) = 0;
388
389 virtual void init()
390 {
391 m_ofile.precision(5);
392 m_ofile.flags(std::ios::scientific);
393 }
394 virtual void putValue(std::ostream& ofile)
395 {
396 ofile << m_ofile.str();
397 }
398 std::ostream& stream() { return m_ofile; }
399
400 protected:
401
402 DumpWEnsight7& m_dw;
403 std::ostringstream m_ofile;
404 GroupIndexTable* m_idx = nullptr;
405 };
406
410 template <typename FromType>
411 class WriteDouble
412 : public WriteBase
413 {
414 public:
415
416 WriteDouble(DumpWEnsight7& dw, ConstArrayView<FromType> ptr, GroupIndexTable* idx = nullptr)
417 : WriteBase(dw, idx)
418 , m_ptr(ptr)
419 {}
420 WriteDouble(const WriteDouble& wd)
421 : WriteBase(wd)
422 , m_ptr(wd.m_ptr)
423 {}
424
425 WriteBase* clone() override { return new WriteDouble(*this); }
426
427 public:
428
430
431 public:
432
433 inline void write(Integer index)
434 {
435 if (m_idx) {
436 int reindex = (*m_idx)[index];
437 if (reindex < 0)
438 ARCANE_FATAL("Invalid index");
439 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[reindex])));
440 }
441 else
442 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[index])));
443 }
444
445 void write(ConstArrayView<Item> items) override
446 {
447 for (Item e : items) {
448 write(e.localId());
449 }
450 }
451 };
452
456 template <typename FromType>
457 class WriteArrayDouble
458 : public WriteBase
459 {
460 public:
461
462 WriteArrayDouble(DumpWEnsight7& dw, ConstArray2View<FromType> ptr, const Integer idim2,
463 GroupIndexTable* idx = nullptr)
464 : WriteBase(dw, idx)
465 , m_ptr(ptr)
466 , m_idim2(idim2)
467 {}
468 WriteArrayDouble(const WriteArrayDouble& wd)
469 : WriteBase(wd)
470 , m_ptr(wd.m_ptr)
471 , m_idim2(wd.m_idim2)
472 {}
473
474 WriteBase* clone() override { return new WriteArrayDouble(*this); }
475
476 public:
477
479 const Integer m_idim2;
480
481 public:
482
483 void write(Integer index)
484 {
485 if (m_idx) {
486 int reindex = (*m_idx)[index];
487 if (reindex < 0)
488 ARCANE_FATAL("Invalid index");
489 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[reindex][m_idim2])));
490 }
491 else
492 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[index][m_idim2])));
493 }
494
495 void write(ConstArrayView<Item> items) override
496 {
497 for (Item e : items) {
498 write(e.localId());
499 }
500 }
501 };
502
506
510 class WriteReal3
511 : public WriteBase
512 {
513 public:
514
515 WriteReal3(DumpWEnsight7& dw, ConstArrayView<Real3> ptr, GroupIndexTable* idx = nullptr)
516 : WriteBase(dw, idx)
517 , m_ptr(ptr)
518 {}
519 WriteReal3(const WriteReal3& wd)
520 : WriteBase(wd)
521 , m_ptr(wd.m_ptr)
522 {}
523
524 WriteBase* clone() override { return new WriteReal3(*this); }
525
526 public:
527
529
530 public:
531
532 void begin() override
533 {
534 _init();
535 xostr.precision(5);
536 xostr.flags(std::ios::scientific);
537 yostr.precision(5);
538 yostr.flags(std::ios::scientific);
539 zostr.precision(5);
540 zostr.flags(std::ios::scientific);
541 }
542
543 void write(Integer index)
544 {
545 if (m_idx) {
546 int reindex = (*m_idx)[index];
547 if (reindex < 0)
548 ARCANE_FATAL("Invalid index");
549 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[reindex].x));
550 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[reindex].y));
551 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[reindex].z));
552 }
553 else {
554 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[index].x));
555 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[index].y));
556 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[index].z));
557 }
558 }
559
560 void write(ConstArrayView<Item> items) override
561 {
562 for (Item i : items) {
563 write(i.localId());
564 }
565 }
566
567 void end() override
568 {
569 m_ofile << xostr.str();
570 m_ofile << yostr.str();
571 m_ofile << zostr.str();
572 }
573
574 public:
575
576 std::ostringstream xostr;
577 std::ostringstream yostr;
578 std::ostringstream zostr;
579
580 private:
581
582 void _init()
583 {
584 init();
585 }
586 };
587
591 class WriteArrayReal3
592 : public WriteBase
593 {
594 public:
595
596 WriteArrayReal3(DumpWEnsight7& dw, ConstArray2View<Real3> ptr,
597 Integer idim2, GroupIndexTable* idx = nullptr)
598 : WriteBase(dw, idx)
599 , m_ptr(ptr)
600 , m_idim2(idim2)
601 {}
602 WriteArrayReal3(const WriteArrayReal3& wd)
603 : WriteBase(wd)
604 , m_ptr(wd.m_ptr)
605 , m_idim2(wd.m_idim2)
606 {}
607
608 WriteBase* clone() override { return new WriteArrayReal3(*this); }
609
610 public:
611
613 const Integer m_idim2;
614
615 public:
616
617 void begin() override
618 {
619 _init();
620 xostr.precision(5);
621 xostr.flags(std::ios::scientific);
622 yostr.precision(5);
623 yostr.flags(std::ios::scientific);
624 zostr.precision(5);
625 zostr.flags(std::ios::scientific);
626 }
627
628 inline void write(Integer index)
629 {
630 if (m_idx) {
631 int reindex = (*m_idx)[index];
632 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[reindex][m_idim2].x));
633 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[reindex][m_idim2].y));
634 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[reindex][m_idim2].z));
635 }
636 else {
637 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[index][m_idim2].x));
638 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[index][m_idim2].y));
639 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[index][m_idim2].z));
640 }
641 }
642
643 void write(ConstArrayView<Item> items) override
644 {
645 for (Item i : items) {
646 write(i.localId());
647 }
648 }
649
650 void end() override
651 {
652 m_ofile << xostr.str();
653 m_ofile << yostr.str();
654 m_ofile << zostr.str();
655 }
656
657 public:
658
659 std::ostringstream xostr;
660 std::ostringstream yostr;
661 std::ostringstream zostr;
662
663 private:
664
665 void _init()
666 {
667 init();
668 }
669 };
670
671 public:
672
673 DumpWEnsight7(IMesh* m, const String& filename, RealConstArrayView times,
674 VariableCollection variables, ItemGroupCollection groups,
675 bool is_binary, bool is_parallel, Integer fileset_size,
676 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids);
677 ~DumpWEnsight7();
678
679 public:
680
682 void writeVal(IVariable& v, ConstArrayView<Real> a) override { _writeRealValT<Real>(v, a); }
683 void writeVal(IVariable&, ConstArrayView<Real2>) override {}
684 void writeVal(IVariable&, ConstArrayView<Real3>) override;
685 void writeVal(IVariable& v, ConstArrayView<Int16> a) override { _writeRealValT<Int16>(v, a); }
686 void writeVal(IVariable& v, ConstArrayView<Int32> a) override { _writeRealValT<Int32>(v, a); }
687 void writeVal(IVariable& v, ConstArrayView<Int64> a) override { _writeRealValT<Int64>(v, a); }
688 void writeVal(IVariable&, ConstArrayView<Real2x2>) override {}
689 void writeVal(IVariable&, ConstArrayView<Real3x3>) override {}
690 void writeVal(IVariable&, ConstArrayView<String>) override {}
691
692 void writeVal(IVariable&, ConstArray2View<Byte>) override {}
693 void writeVal(IVariable& v, ConstArray2View<Real> a) override { _writeRealValT<Real>(v, a); }
694 void writeVal(IVariable&, ConstArray2View<Real2>) override {}
695 void writeVal(IVariable&, ConstArray2View<Real3>) override;
696 void writeVal(IVariable& v, ConstArray2View<Int16> a) override { _writeRealValT<Int16>(v, a); }
697 void writeVal(IVariable& v, ConstArray2View<Int32> a) override { _writeRealValT<Int32>(v, a); }
698 void writeVal(IVariable& v, ConstArray2View<Int64> a) override { _writeRealValT<Int64>(v, a); }
699 void writeVal(IVariable&, ConstArray2View<Real2x2>) override {}
700 void writeVal(IVariable&, ConstArray2View<Real3x3>) override {}
701
702 void writeVal(IVariable&, ConstMultiArray2View<Byte>) override {}
703 void writeVal(IVariable& v, ConstMultiArray2View<Real> a) override { _writeRealValT<Real>(v, a); }
704 void writeVal(IVariable&, ConstMultiArray2View<Real2>) override {}
705 void writeVal(IVariable&, ConstMultiArray2View<Real3> a) override;
706 void writeVal(IVariable& v, ConstMultiArray2View<Int16> a) override { _writeRealValT<Int16>(v, a); }
707 void writeVal(IVariable& v, ConstMultiArray2View<Int32> a) override { _writeRealValT<Int32>(v, a); }
708 void writeVal(IVariable& v, ConstMultiArray2View<Int64> a) override { _writeRealValT<Int64>(v, a); }
709 void writeVal(IVariable&, ConstMultiArray2View<Real2x2>) override {}
710 void writeVal(IVariable&, ConstMultiArray2View<Real3x3>) override {}
711
712 void beginWrite() override;
713 void endWrite() override;
714 void setMetaData(const String&) override{};
715
716 bool isParallelOutput() const { return m_is_parallel_output; }
717 bool isMasterProcessor() const { return m_is_master; }
718 bool isOneFilePerTime() const { return m_fileset_size == 0; }
719 Int32 rank() const { return m_parallel_mng->commRank(); }
720 IParallelMng* parallelMng() const { return m_parallel_mng; }
721
722 public:
723 private:
724
725 typedef UniqueArray<GroupPartInfo*> GroupPartInfoList;
726
727 private:
728
733 std::ofstream m_case_file;
734 std::ostringstream m_case_file_variables;
736 VariableList m_save_variables;
738 GroupPartInfoList m_parts;
744 bool m_use_degenerated_hexa;
745 bool m_force_first_geometry;
746 bool m_save_uids;
754 Integer m_fileset_size;
755
756 private:
757 private:
758
760 static const Integer m_max_prots_digit = 6;
761
762 private:
763 private:
764
765 bool _isValidVariable(IVariable&) const;
766 void _createCaseFile();
767 void _buildFileName(const String& varname, String& filename);
768 void _buildPartDirectory();
769 void _writeWildcardFilename(std::ostream& ofile, const String& filename, char joker = '*');
770 int _fileOuttype() const;
771 void _writeFileHeader(std::ostream& o, bool write_c_binary);
772 bool _isNewBlocFile() const;
773
774 void _computeGroupParts(ItemGroupList list_group, Integer& partid);
775 void _saveGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
776 ConstArrayView<Integer> nodes_index, WriteBase& wf);
777 void _saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
778 WriteBase& from_func);
779 bool _isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind);
780
782 template <typename T>
785 template <typename T>
788 template <typename T>
790};
791
792/*---------------------------------------------------------------------------*/
793/*---------------------------------------------------------------------------*/
794
795extern "C++" DumpW*
796createEnsight7(ISubDomain* m, const String& f,
798 VariableCollection variables,
799 ItemGroupCollection groups,
800 bool is_binary, bool is_parallel_output, Integer fileset_size,
801 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
802{
803 return new DumpWEnsight7(m->defaultMesh(), f, times, variables, groups, is_binary,
804 is_parallel_output, fileset_size, use_degenerated_hexa,
805 force_first_geometry, save_uids);
806}
807
808extern "C++" DumpW*
809createEnsight7(IMesh* m, const String& f,
810 ConstArrayView<Real> times,
811 VariableCollection variables,
812 ItemGroupCollection groups,
813 bool is_binary, bool is_parallel_output, Integer fileset_size,
814 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
815{
816 return new DumpWEnsight7(m, f, times, variables, groups, is_binary,
817 is_parallel_output, fileset_size, use_degenerated_hexa,
818 force_first_geometry, save_uids);
819}
820
821/*---------------------------------------------------------------------------*/
822/*---------------------------------------------------------------------------*/
823
824DumpWEnsight7::
825DumpWEnsight7(IMesh* mesh, const String& filename, ConstArrayView<Real> times,
826 VariableCollection variables, ItemGroupCollection groups,
827 bool is_binary, bool is_parallel_output, Integer fileset_size,
828 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
829: TraceAccessor(mesh->traceMng())
830, m_mesh(mesh)
831, m_parallel_mng(mesh->parallelMng())
832, m_base_directory(filename)
833, m_times(times)
834, m_save_variables(variables.clone())
835, m_save_groups(groups.enumerator())
836, m_is_binary(is_binary)
837// , m_is_binary(false)
838, m_is_master(true)
839, m_is_parallel_output(is_parallel_output)
840, m_use_degenerated_hexa(use_degenerated_hexa)
841, m_force_first_geometry(force_first_geometry)
842, m_save_uids(save_uids)
843, m_total_nb_element(0)
844, m_total_nb_group(0)
845, m_fileset_size(fileset_size)
846{
847 //m_is_binary = true;
848 //m_fileset_size = 0;
849
850 if (m_times.empty()) {
851 m_times.resize(1);
852 m_times[0] = 0.;
853 }
854
855 //_createCaseFile();
856}
857
858/*---------------------------------------------------------------------------*/
859/*---------------------------------------------------------------------------*/
860
861DumpWEnsight7::
862~DumpWEnsight7()
863{
864 std::for_each(std::begin(m_parts), std::end(m_parts), Deleter());
865}
866
867/*---------------------------------------------------------------------------*/
868/*---------------------------------------------------------------------------*/
869
870/*---------------------------------------------------------------------------*/
871/*---------------------------------------------------------------------------*/
890void DumpWEnsight7::
891_computeGroupParts(ItemGroupList list_group, Integer& partid)
892{
893 for (ItemGroupList::Enumerator i(list_group); ++i;) {
894 ItemGroup grp(*i);
895 if (grp.null()) // Le groupe n'est pas du type souhaité.
896 continue;
897 if (!grp.isOwn()) // Si possible, prend le groupe d'éléments propres
898 grp = grp.own();
899 // Depuis la 7.6 de Ensight, les groupes vides sont autorisés
900 // et ils sont nécessaires lorsque le maillage évolue au cours du temps
901 //if (grp.empty()) // Le groupe est vide
902 //continue;
903 GroupPartInfo* gpi = new GroupPartInfo(grp, partid, m_use_degenerated_hexa);
904 m_parts.add(gpi);
905 ++partid;
906
907 GroupPartInfo& current_grp = *gpi;
908 // Il faut maintenant déterminer combien d'éléments de chaque type
909 // ensight (tria3, hexa8, ...) on a dans le groupe.
910 // two versions: if extra item types are added switch to an optimized version
911 // (a large amount of types may be added, equal to the number of elements)
913 {
914 debug(Trace::High) << "Using standard group part building algo";
915 if (!grp.mesh()->itemTypeMng()->hasGeneralCells(grp.mesh())) {// classical types
916 for (Integer z = 0; z < current_grp.nbType(); ++z) {
917 EnsightPart& type_info = current_grp.typeInfo(z);
918 Array<Item>& items = type_info.items();
919 Integer nb_of_type = 0;
920 Integer type_to_seek = type_info.type();
921 ENUMERATE_ITEM (i2, grp) {
922 const Item& e = *i2;
923 if (e.type() == type_to_seek)
924 ++nb_of_type;
925 }
926 items.resize(nb_of_type);
927 debug(Trace::High) << "Group " << grp.name() << " has "
928 << nb_of_type << " items of type " << type_info.name();
929 Integer index = 0;
930 ENUMERATE_ITEM (iz, grp)
931 {
932 Item mi = *iz;
933 if (mi.type() == type_to_seek) {
935 items[index] = e;
936 ++index;
937 }
938 }
939 }
940 }
941 else {// polyhedral mesh items
942 ENUMERATE_ITEM (i2, grp) {
943 const Item& item = *i2;
944 auto item_type = current_grp.generalItemTypeId(item);
945 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
946 if (!ensight_part)
947 continue ;
948 ItemWithNodes item_wn = item.toItemWithNodes();
949 ensight_part->items().add(item_wn);
950 }
951 }
952 }
953 else // extra types are added (may have as many types as items...)
954 // Propose an optimized version when many types exist (use of .format file)
955 {
956 debug(Trace::High) << "Using extra type group part building algo";
957 // work only on face and cell groups
958 auto item_kind = grp.itemKind();
959 if (item_kind == IK_Cell || item_kind == IK_Face) {
960 ENUMERATE_ITEM (item, grp) {
961 auto item_type = item->type();
962 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
963 if (!ensight_part)
964 continue ;
965 ItemWithNodes item_wn = item->toItemWithNodes();
966 ensight_part->items().add(item_wn); // few elements are added
967 }
968 }
969 }
970 }
971}
972
973/*---------------------------------------------------------------------------*/
974/*---------------------------------------------------------------------------*/
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 // Dans le cas d'une sortie parallele, prefixe le nom du groupe par le
1006 // numéro du CPU.
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 // Sauve les uniqueId() des entités
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 // Traitement particulier pour les mailles non standards
1040 // Comme nos faces ne sont pas orientées par rapport à une
1041 // maille, on utilise la connectivité locale de chaque face.
1042 // 1. Sauve le nombre de faces de chaque élément
1043 {
1044 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1045 // Tous les éléments ont le même nombre de 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. Sauve pour chaque elément, le nombre de noeuds de chacune
1060 // de ces 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. Sauve pour chaque face de chaque élément la liste de ces
1078 // noeuds
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 // Inversion du sens des noeuds
1091 // A priori, il y a un bug dans Ensight (7.4.1(g)) concernant les
1092 // intersections de ce type d'éléments avec les objets
1093 // Ensight (plan, sphere, ...). Quelle que soit l'orientation
1094 // des faces retenues, le comportant n'est pas correcte.
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 // Traitement particulier pour les faces à plus de 4 noeuds:
1119
1120 // 1. Sauve pour chaque elément, le nombre de ses noeuds
1121 //cerr << "** NSIDED ELEMENT\n";
1122 for (Item mi : items) {
1124 Integer nb_node = e.nbNode();
1125 writeFileInt(ofile, nb_node);
1126 }
1127 // 2. Sauve pour chaque elément la liste de ces noeuds
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 // Cas général
1140
1141 Integer nb_node = type_info.nbNode();
1142 array_id.resize(nb_node);
1143
1144 // Sauvegarde les éléments.
1145
1146 // Sauve la connectivité des éléments
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/*---------------------------------------------------------------------------*/
1197void DumpWEnsight7::
1198_saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
1199 WriteBase& from_func)
1200{
1201 ItemGroup igrp = ensight_grp.group();
1202
1203 writeFileString(ofile, "part");
1204 writeFileInt(ofile, ensight_grp.partId());
1205
1206 // Les éléments de même types (en particulier les 'nfaced', 'haxa8' ou 'nsided')
1207 // doivent être écrits d'un seul bloc (donc label de type unifié).
1208 // Par ailleurs, les données vectorielles doivent être entrelacés.
1209 String last_type_name;
1211 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1212 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1213 ConstArrayView<Item> items(type_info.items());
1214 Integer nb_sub_part = items.size();
1215 if (nb_sub_part == 0)
1216 continue;
1217 String type_name = type_info.name();
1218 if (type_name != last_type_name) {
1219 // Cloture la précédente écriture
1220 if (func.get()) {
1221 func->end();
1222 func->putValue(ofile);
1223 }
1224 last_type_name = type_name;
1225 writeFileString(ofile, type_name);
1226 func = from_func.clone();
1227 func->begin();
1228 }
1229
1230 // Sauvegarde les variables.
1231 func->write(items);
1232 }
1233
1234 // Cloture finale
1235 if (func.get()) {
1236 func->end();
1237 func->putValue(ofile);
1238 }
1239}
1240
1241/*---------------------------------------------------------------------------*/
1242/*---------------------------------------------------------------------------*/
1243
1244void DumpWEnsight7::
1245writeFileInt(std::ostream& o, int value)
1246{
1247 if (m_is_binary) {
1248 o.write((const char*)&value, sizeof(int));
1249 }
1250 else {
1251 o.width(DumpWEnsight7::int_width);
1252 o << value;
1253 o << '\n';
1254 }
1255}
1256
1257/*---------------------------------------------------------------------------*/
1258/*---------------------------------------------------------------------------*/
1259
1260Integer DumpWEnsight7::
1261writeIntSize() const
1262{
1263 if (m_is_binary)
1264 return sizeof(int);
1265 return DumpWEnsight7::int_width + 1;
1266}
1267
1268/*---------------------------------------------------------------------------*/
1269/*---------------------------------------------------------------------------*/
1270
1271void DumpWEnsight7::
1272writeFileDouble(std::ostream& o, double value)
1273{
1274 if (m_is_binary) {
1275 float fvalue = (float)(value);
1276 o.write((const char*)&fvalue, sizeof(float));
1277 }
1278 else {
1279 o.width(12);
1280 o.precision(5);
1281 o.flags(std::ios::scientific);
1282 o << value;
1283 o << '\n';
1284 }
1285}
1286
1287/*---------------------------------------------------------------------------*/
1288/*---------------------------------------------------------------------------*/
1289
1290Integer DumpWEnsight7::
1291writeDoubleSize() const
1292{
1293 Integer float_size = (Integer)(sizeof(float));
1294 return (m_is_binary) ? float_size : (12 + 1);
1295}
1296
1297/*---------------------------------------------------------------------------*/
1298/*---------------------------------------------------------------------------*/
1299
1300void DumpWEnsight7::
1301writeFileArray(std::ostream& o, IntegerConstArrayView value)
1302{
1303 if (m_is_binary) {
1304 o.write((const char*)value.data(), sizeof(Integer) * value.size());
1305 }
1306 else {
1307 for (Integer i = 0, s = value.size(); i < s; ++i) {
1308 o.width(DumpWEnsight7::int_width);
1309 o << value[i];
1310 }
1311 o << '\n';
1312 }
1313}
1314
1315/*---------------------------------------------------------------------------*/
1316/*---------------------------------------------------------------------------*/
1317
1318void DumpWEnsight7::
1319writeFileString(std::ostream& o, const String& str)
1320{
1321 if (m_is_binary) {
1322 char buf[g_line_length];
1323 for (int i = 0; i < g_line_length; ++i)
1324 buf[i] = '\0';
1325 CStringUtils::copyn(buf, str.localstr(), g_line_length);
1326 buf[g_line_length - 1] = '\0';
1327 o.write(buf, g_line_length);
1328 }
1329 else {
1330 o << str << '\n';
1331 }
1332}
1333
1334/*---------------------------------------------------------------------------*/
1335/*---------------------------------------------------------------------------*/
1336
1337void DumpWEnsight7::
1338_writeFileHeader(std::ostream& o, bool write_c_binary)
1339{
1340 if (m_is_master) {
1341 if (_isNewBlocFile() && m_is_binary && write_c_binary)
1342 writeFileString(o, "C Binary");
1343 if (m_fileset_size != 0) {
1344 std::ostringstream ostr;
1345 ostr << "BEGIN TIME STEP "
1346 << "# " << m_times.size();
1347 writeFileString(o, ostr.str().c_str());
1348 }
1349 }
1350}
1351
1352/*---------------------------------------------------------------------------*/
1353/*---------------------------------------------------------------------------*/
1361class DumpWEnsight7OutFile
1362{
1363 public:
1364
1365 DumpWEnsight7OutFile(DumpWEnsight7& dw, const String& filename, int outtype)
1366 : m_dw(dw)
1367 , m_filename(filename)
1368 , m_is_master(dw.isMasterProcessor())
1369 , m_is_parallel_output(dw.isParallelOutput())
1370 , m_stream(0)
1371 , m_filestream(0)
1372 {
1373 if (m_is_master) {
1374 m_filestream = new std::ofstream(filename.localstr(), (std::ios_base::openmode)outtype);
1375 m_stream = &m_strstream;
1376 if (!(*m_filestream))
1377 m_dw.warning() << "Unable to open file " << filename;
1378 }
1379 else {
1380 // TODO attention fuites mémoires.
1381 m_stream = &m_strstream;
1382 }
1383 ARCANE_CHECK_PTR(m_stream);
1384 }
1385 ~DumpWEnsight7OutFile()
1386 {
1387 delete m_filestream;
1388 }
1389
1390 public:
1391
1392 void syncFile()
1393 {
1394 IParallelMng* parallel_mng = m_dw.parallelMng();
1395 if (m_is_master) {
1396 ARCANE_CHECK_PTR(m_filestream);
1397 ARCANE_CHECK_PTR(m_strstream);
1398 //Integer pos = m_strstream->tellp();
1399 (*m_filestream) << m_strstream.str();
1400 }
1401 if (m_is_parallel_output) {
1402 if (m_is_master) {
1403 ARCANE_CHECK_PTR(m_filestream);
1404
1405 // Le maitre parcours tous les processeurs et demande pour chacun
1406 // d'eux la taille de chaque sauvegarde et si elle n'est pas nulle,
1407 // réceptionne le message.
1408 Integer nb_proc = parallel_mng->commSize();
1409 UniqueArray<int> len_array(1);
1410 UniqueArray<Byte> str_array;
1411 for (Integer i = 1; i < nb_proc; ++i) {
1412 m_dw.debug(Trace::High) << "Waiting for length of processor " << i;
1413 parallel_mng->recv(len_array, i);
1414 Integer len = len_array[0];
1415 m_dw.debug(Trace::High) << "Length of processor " << i << " : " << len;
1416 if (len != 0) {
1417 str_array.resize(len);
1418 m_dw.debug(Trace::High) << "Waiting for receving geom of processor " << i;
1419 parallel_mng->recv(str_array, i);
1420 m_dw.debug(Trace::High) << "Receving geom of processor " << i;
1421 m_filestream->write((const char*)str_array.data(), str_array.size());
1422 }
1423 }
1424 }
1425 else {
1426 ARCANE_CHECK_PTR(m_strstream);
1427 // Un esclave envoie au processeur maître (actuellement le processeur 0)
1428 // la taille de ses données puis ces données.
1429 // Il faut bien prendre la longueur de la chaîne retournée par m_strstream
1430 // et pas uniquement c_str() car le flux pouvant contenant des informations
1431 // au format binaire, on s'arrêterait au premier zéro.
1432 UniqueArray<int> len_array(1);
1433 std::string str = m_strstream.str();
1434 Integer len = arcaneCheckArraySize(str.length());
1435 UniqueArray<Byte> bytes(len);
1436 {
1437 // Recopie dans bytes la chaîne \a str
1438 Integer index = 0;
1439 for (ConstIterT<std::string> i(str); i(); ++i, ++index)
1440 bytes[index] = *i;
1441 }
1442 m_dw.debug(Trace::High) << "Not a master. " << m_filename << " size = " << len;
1443 //Integer len = m_strstream->tellp();
1444 //Integer len = str.length();
1445 len_array[0] = len;
1446 m_dw.debug(Trace::High) << "Sending length for processor 0";
1447 parallel_mng->send(len_array, 0);
1448 if (len != 0) {
1449 //UniqueArray<char> str_array(len);
1450 //std::string s = m_strstream->str();
1451 //platform::stdMemcpy(str_array.begin(),s.c_str(),s.length());
1452 m_dw.debug(Trace::High) << "Sending data for processor 0";
1453 parallel_mng->send(bytes, 0); //str.c_str())__array,0);
1454 //parallel_mng->send(str_array,0);
1455 }
1456 }
1457 }
1458 if (m_is_master)
1459 if (!m_dw.isOneFilePerTime())
1460 m_dw.writeFileString(*m_filestream, "END TIME STEP");
1461 }
1462
1463 public:
1464
1465 std::ostream& operator()() { return *m_stream; }
1466
1467 private:
1468
1469 DumpWEnsight7& m_dw;
1470 String m_filename;
1471 bool m_is_master;
1472 bool m_is_parallel_output;
1473 std::ostream* m_stream;
1474 std::ostringstream m_strstream;
1475 std::ofstream* m_filestream;
1476};
1477
1478/*---------------------------------------------------------------------------*/
1479/*---------------------------------------------------------------------------*/
1480
1481/*---------------------------------------------------------------------------*/
1482/*---------------------------------------------------------------------------*/
1483
1485beginWrite()
1486{
1487 String buf = m_base_directory.file("ensight.case");
1488
1489 IParallelMng* parallel_mng = m_parallel_mng;
1490 bool is_parallel = parallel_mng->isParallel();
1491 m_is_master = true;
1492 if (is_parallel && m_is_parallel_output)
1493 m_is_master = parallel_mng->commRank() == 0;
1494
1495 // Détermine et créé le répertoire ou seront écrites les sorties
1496 // de cette itération.
1498
1499 IMesh* mesh = m_mesh;
1500
1501 // Récupère la liste des groupes et leur donne à chacun un identifiant
1502 // unique pour Ensight (part). Le numéro de l'identifiant débute à 2, le numéro 1
1503 // est pour la liste des noeuds
1504 {
1505
1506 ItemGroupList list_group;
1507 // Si la liste des groupes à sauver est vide, sauve tous les groupes.
1508 // Sinon, sauve uniquement les groupes spécifiés.
1509 Integer nb_group = m_save_groups.count();
1510 if (nb_group == 0)
1511 list_group.clone(mesh->groups());
1512 else
1513 list_group.clone(m_save_groups);
1514 // Regarde la liste des variables partielles, et ajoute leur groupe à la liste
1515 // des groupes à sauver.
1516 for (VariableList::Enumerator ivar(m_save_variables); ++ivar;) {
1517 IVariable* var = *ivar;
1518 if (!var->isPartial())
1519 continue;
1520 ItemGroup var_group = var->itemGroup();
1521 if (!list_group.contains(var_group))
1522 list_group.add(var_group);
1523 }
1524 Integer partid = 1;
1526 partid += parallel_mng->commRank() * list_group.count();
1527
1528 _computeGroupParts(list_group, partid);
1529
1530 // Récupère le nombre total d'eléments dans les groupes.
1531 Integer total_nb_element = 0;
1532 m_total_nb_group = 0;
1533 for (auto i : m_parts) {
1534 total_nb_element += i->totalNbElement();
1536 }
1537
1538 m_total_nb_element = total_nb_element;
1539 debug() << "Total nb element " << m_total_nb_element << " and group " << m_total_nb_group;
1540 debug() << "Add nodes " << mesh->nbNode();
1541 }
1542
1543 // Sauvegarde la géométrie au format Ensight7 gold
1544 if (!(m_times.size() > 1 && m_force_first_geometry)) {
1545 String filename;
1546 _buildFileName("ensight.geo", filename);
1547
1548 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1549
1550 _writeFileHeader(dw_ofile(), true);
1551
1552 if (m_is_master) {
1553 writeFileString(dw_ofile(), "Output ensight test");
1554 writeFileString(dw_ofile(), "File description");
1555 writeFileString(dw_ofile(), "node id assign");
1556 writeFileString(dw_ofile(), "element id assign");
1557 }
1558
1559 IMesh* mesh = m_mesh;
1560 NodeGroup all_nodes = mesh->allNodes();
1561
1562 // Ce tableau sert pour chaque entité maille, face ou arête pour
1563 // référencer ses noeuds par rapport au tableau de coordonnées
1564 // utilisé par Ensight. Le premier élément de ce tableau à pour indice 1
1565 UniqueArray<Integer> all_nodes_index(mesh->itemFamily(IK_Node)->maxLocalId());
1566 all_nodes_index.fill(0);
1567
1568 UniqueArray<Real3> coords_backup;
1569 ConstArrayView<Real3> coords_array;
1570 if (mesh->parentMesh()) {
1571 SharedVariableNodeReal3 nodes_coords(mesh->sharedNodesCoordinates());
1572 coords_backup.resize(mesh->nodeFamily()->maxLocalId());
1573 ENUMERATE_NODE (i_item, all_nodes) {
1574 coords_backup[i_item.localId()] = nodes_coords[i_item];
1575 }
1576 coords_array = coords_backup.view();
1577 }
1578 else {
1579 VariableNodeReal3& nodes_coords(mesh->toPrimaryMesh()->nodesCoordinates());
1580 coords_array = ConstArrayView<Real3>(nodes_coords.asArray());
1581 }
1582
1583 WriteReal3 wf(*this, coords_array);
1584 {
1585 wf.init();
1586 writeFileString(wf.stream(), "coordinates");
1587 writeFileInt(wf.stream(), all_nodes.size());
1588 wf.begin();
1589
1590 // Stocke les indices locaux pour Ensight
1591 {
1592 Integer ensight_index = 1;
1593 ENUMERATE_ITEM (i_item, all_nodes) {
1594 const Item& item = *i_item;
1595 all_nodes_index[item.localId()] = ensight_index;
1596 ++ensight_index;
1597 }
1598 }
1599
1600 // Affiche les numéros unique des noeuds
1601#if 0
1602 {
1603 ENUMERATE_ITEM(i_item,all_nodes){
1604 const Item& item = *i_item;
1605 writeFileInt(wf.stream(),item.uniqueId()+1);
1606 }
1607 }
1608#endif
1609 // Affiche les coordonnées de chaque noeud
1610 ENUMERATE_ITEM (i_item, all_nodes) {
1611 const Item& item = *i_item;
1612 wf.write(item.localId());
1613 }
1614 wf.end();
1615 }
1616
1617 for (const GroupPartInfo* part : m_parts)
1618 _saveGroup(dw_ofile(), *part, all_nodes_index, wf);
1619
1620 dw_ofile.syncFile();
1621 }
1622}
1623
1624/*---------------------------------------------------------------------------*/
1625/*---------------------------------------------------------------------------*/
1626
1628endWrite()
1629{
1630 // Sauvegarde des identifiants uniques
1631 if (m_save_uids) {
1633 ENUMERATE_CELL (icell, m_mesh->allCells()) {
1634 cell_uids[icell] = (Real)(icell->uniqueId().asInt64());
1635 }
1636 IVariable* cell_uid_var = cell_uids.variable();
1637 m_save_variables.add(cell_uid_var);
1638 cell_uid_var->setUsed(true);
1639 cell_uid_var->notifyBeginWrite();
1640 write(cell_uid_var, cell_uid_var->data());
1641
1642 // GG: NOTE: je ne suis pas sur que cela fonctionne bien.
1643 //TODO: supprimer l'utilisation de deux variables
1645 UniqueArray<Real> node_uids2(m_mesh->nodeFamily()->allItems().size());
1646 ENUMERATE_NODE (inode, m_mesh->allNodes()) {
1647 node_uids[inode] = inode->uniqueId().asInt32();
1648 node_uids2[inode.index()] = (Real)inode->uniqueId().asInt64();
1649 }
1650
1651 IVariable* node_uid_var = node_uids.variable();
1652 m_save_variables.add(node_uid_var);
1653 node_uid_var->setUsed(true);
1654 _writeRealValT<Real>(*node_uid_var, node_uids2); // work around bug for node variables
1655 }
1656
1657 String buf = m_base_directory.file("ensight.case");
1658
1659 // Seul un processeur maître génère un fichier 'case'
1660 if (m_is_master) {
1661
1662 m_case_file.open(buf.localstr());
1663
1664 if (!m_case_file)
1665 warning() << "Unable to write to file: <" << buf << "> error: " << m_case_file.rdstate();
1666
1667 debug() << "** Exporting data to " << m_base_directory.path();
1668 m_case_file << "FORMAT\ntype: ensight gold\n";
1669
1670 m_case_file << "\nGEOMETRY\n";
1671 m_case_file << "model: 1";
1672 if (m_fileset_size != 0)
1673 m_case_file << " 1 ";
1674 if (m_force_first_geometry)
1675 _writeWildcardFilename(m_case_file, "ensight.geo", '0');
1676 else
1677 _writeWildcardFilename(m_case_file, "ensight.geo", '*');
1678 //m_case_file << " [change_coords_only]\n";
1679 m_case_file << "\n";
1680
1681 m_case_file << "\nVARIABLE\n";
1682 m_case_file << m_case_file_variables.str();
1683
1684 // Sauvegarde en temps. Pour paraview, il faut le mettre apres les variables
1685 m_case_file << "\nTIME\n";
1686 m_case_file << "time set: 1\n";
1687 m_case_file << "number of steps: " << m_times.size() << '\n';
1688 m_case_file << "filename start number: 0\n";
1689 m_case_file << "filename increment: 1\n";
1690 m_case_file << "time values:\n";
1691 // Faire attention de ne pas dépasser les 79 caractères par ligne
1692 // autorisés par Ensight. Pour être sur, on n'écrit qu'un temps pas
1693 // ligne. Les temps sont sauvés le maximum de chiffres significatifs
1694 // car Ensight n'aime pas que deux temps soient égaux.
1695 std::streamsize old_precision = m_case_file.precision(FloatInfo<Real>::maxDigit());
1696 for (Integer i = 0, is = m_times.size(); i < is; ++i)
1697 m_case_file << m_times[i] << '\n';
1698 m_case_file << '\n';
1699 m_case_file.precision(old_precision);
1700
1701 if (m_fileset_size != 0) {
1702 m_case_file << "FILE\n";
1703 m_case_file << "file set: 1\n";
1704 if (m_fileset_size != 0) {
1705 Integer nb_timeset = (m_times.size() / m_fileset_size);
1706 for (Integer i = 0; i < nb_timeset; ++i) {
1707 m_case_file << "filename index: " << i << "\n";
1708 m_case_file << "number of steps: " << m_fileset_size << '\n';
1709 }
1710 if (nb_timeset > 0)
1711 m_case_file << "filename index: " << nb_timeset << "\n";
1712 m_case_file << "number of steps: " << m_times.size() - (nb_timeset * m_fileset_size) << '\n';
1713 }
1714 else {
1715 m_case_file << "number of steps: " << m_times.size() << '\n';
1716 }
1717 m_case_file << '\n';
1718 }
1719 }
1720 m_case_file.flush();
1721 m_case_file.close();
1722}
1723
1724/*---------------------------------------------------------------------------*/
1725/*---------------------------------------------------------------------------*/
1726
1727/*---------------------------------------------------------------------------*/
1728/*---------------------------------------------------------------------------*/
1742{
1743 if (!v.isUsed())
1744 return false;
1745 eItemKind ik = v.itemKind();
1746 if (ik != IK_Cell && ik != IK_Node && ik != IK_Face)
1747 return false;
1748 // Si une liste de variable est spécifiée, vérifie que la variable est dans
1749 // cette liste. Si cette liste est vide, on sauve automatiquement toutes les
1750 // variables.
1751 Integer nb_var = m_save_variables.count();
1752 if (nb_var != 0) {
1753 return m_save_variables.contains(&v);
1754 }
1755 return true;
1756}
1757
1758/*---------------------------------------------------------------------------*/
1759/*---------------------------------------------------------------------------*/
1773_buildFileName(const String& name, String& filename)
1774{
1775 StringBuilder fn_builder;
1776 if (m_fileset_size == 0) {
1777 Integer current_time = m_times.size() - 1;
1778 fn_builder = m_base_directory.path();
1779 fn_builder += "/";
1780 fn_builder += name;
1781 if (m_is_master) {
1782 Directory dir(fn_builder.toString());
1783 dir.createDirectory();
1784 }
1785 fn_builder += "/";
1786 fn_builder += name;
1787
1788 {
1789 OStringStream ostr;
1790 ostr().fill('0'); // Caractère de remplissage.
1791 ostr().width(m_max_prots_digit);
1792 ostr() << current_time;
1793 fn_builder += ostr.str();
1794 }
1795
1796 //fn_builder += current_time;
1797
1798 //info() << " BUILD FILE NAME name=" << name << " filename=" << fn_builder;
1799 }
1800 else {
1801 fn_builder = m_part_directory.path();
1802 fn_builder += "/";
1803 fn_builder += name;
1804 }
1805 filename = fn_builder;
1806}
1807
1808/*---------------------------------------------------------------------------*/
1809/*---------------------------------------------------------------------------*/
1810
1811bool DumpWEnsight7::
1812_isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind)
1813{
1814 eItemKind group_kind = group.itemKind();
1815 if (item_kind == IK_Unknown)
1816 return false;
1817 return group_kind == item_kind;
1818}
1819
1820/*---------------------------------------------------------------------------*/
1821/*---------------------------------------------------------------------------*/
1834{
1835 Integer prot_index = 0;
1836 bool has_prot = false;
1837 if (m_fileset_size != 0) {
1838 Integer nb_time = m_times.size();
1839 if (nb_time != 0)
1840 prot_index = (nb_time - 1) / m_fileset_size;
1841 has_prot = true;
1842 }
1843
1844 if (m_is_master)
1845 m_base_directory.createDirectory();
1846
1847 if (has_prot) {
1848 OStringStream ostr;
1849 ostr() << "bloc";
1850 ostr().fill('0'); // Caractère de remplissage.
1851 ostr().width(m_max_prots_digit);
1852 ostr() << prot_index;
1853 //ostr() << '\0';
1854 String buf = ostr.str();
1856 if (m_is_master)
1857 m_part_directory.createDirectory();
1858 }
1859 else
1861}
1862
1863/*---------------------------------------------------------------------------*/
1864/*---------------------------------------------------------------------------*/
1865
1866void DumpWEnsight7::
1867_writeWildcardFilename(std::ostream& ofile, const String& filename, char joker)
1868{
1869 if (m_fileset_size == 0) {
1870 ofile << ' ' << filename << '/' << filename;
1871 for (Integer i = 0; i < m_max_prots_digit; ++i)
1872 ofile << joker;
1873 }
1874 else {
1875 ofile << " bloc";
1876 Integer nb_time = m_times.size();
1877 // Si le nombre de temps est inférieur à la taille d'un fileset-set,
1878 // il n'y a pas besoin de mettre une '*'. On peut directement
1879 // mettre des zéros. Cela est aussi indispensable pour empêcher
1880 // paraview de planter quand il relit ce genre de fichiers.
1881 if (nb_time <= m_fileset_size)
1882 joker = '0';
1883 for (Integer i = 0; i < m_max_prots_digit; ++i)
1884 ofile << joker;
1885 ofile << "/" << filename;
1886 }
1887}
1888
1889/*---------------------------------------------------------------------------*/
1890/*---------------------------------------------------------------------------*/
1891
1892bool DumpWEnsight7::
1893_isNewBlocFile() const
1894{
1895 Integer nb_time = m_times.size();
1896
1897 if (nb_time == 1)
1898 return true;
1899 if (m_fileset_size == 0)
1900 return true;
1901
1902 Integer modulo = (nb_time - 1) % m_fileset_size;
1903
1904 if (modulo == 0)
1905 return true;
1906 return false;
1907}
1908
1909/*---------------------------------------------------------------------------*/
1910/*---------------------------------------------------------------------------*/
1911
1912int DumpWEnsight7::
1913_fileOuttype() const
1914{
1915 return ((isBinary()) ? std::ios::binary : 0) | ((_isNewBlocFile()) ? std::ios::trunc : std::ios::app);
1916}
1917
1918/*---------------------------------------------------------------------------*/
1919/*---------------------------------------------------------------------------*/
1923template <typename T>
1926{
1927 debug() << "Saving variable1 " << v.name() << " ptr=" << ptr.data() << " ps=" << ptr.size();
1928
1929 if (!_isValidVariable(v))
1930 return;
1931
1932 String filename;
1933 _buildFileName(v.name(), filename);
1934
1935 debug() << "Saving variable " << v.name() << " in " << filename;
1936
1937 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1938
1939 _writeFileHeader(dw_ofile(), false);
1940
1941 if (m_is_master)
1942 writeFileString(dw_ofile(), v.name());
1943 String var_type_str;
1944
1945 if (m_is_master) {
1946 switch (v.itemKind()) {
1947 case IK_Cell:
1948 case IK_Face:
1949 var_type_str = "scalar per element: ";
1950 break;
1951 case IK_Node:
1952 var_type_str = "scalar per node: ";
1953 break;
1954 default:
1955 break;
1956 }
1957
1958 m_case_file_variables << var_type_str;
1959 m_case_file_variables << " 1 ";
1960 if (m_fileset_size != 0)
1961 m_case_file_variables << " 1 ";
1962 m_case_file_variables << v.name();
1963 _writeWildcardFilename(m_case_file_variables, v.name());
1964 m_case_file_variables << '\n';
1965 }
1966
1967 switch (v.itemKind()) {
1968 case IK_Cell:
1969 case IK_Face:
1970 case IK_Edge: {
1971 GroupIndexTable* idx = nullptr;
1972
1973 if (v.isPartial()) {
1974 idx = v.itemGroup().localIdToIndex().get();
1975 }
1976
1977 WriteDouble<T> wf(*this, ptr, idx);
1978 for (const GroupPartInfo* part : m_parts) {
1979 bool need_save = false;
1980 if (v.isPartial())
1981 need_save = v.itemGroup() == part->group();
1982 else
1983 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
1984 if (need_save)
1985 _saveVariableOnGroup(dw_ofile(), *part, wf);
1986 }
1987 } break;
1988 case IK_Node: {
1989 if (v.isPartial())
1990 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
1991 WriteDouble<T> wf(*this, ptr);
1992 wf.begin();
1993 for (Integer i = 0; i < ptr.size(); ++i)
1994 wf.write(i);
1995 wf.end();
1996 for (const GroupPartInfo* part : m_parts) {
1997 writeFileString(dw_ofile(), "part");
1998 writeFileInt(dw_ofile(), part->partId());
1999 writeFileString(dw_ofile(), "coordinates");
2000 wf.putValue(dw_ofile());
2001 }
2002 } break;
2003 default:
2004 break;
2005 }
2006
2007 dw_ofile.syncFile();
2008
2009 //if (m_is_transient && m_is_master)
2010 //writeFileString(dw_ofile(),"END TIME STEP");
2011}
2012
2013/*---------------------------------------------------------------------------*/
2014/*---------------------------------------------------------------------------*/
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/*---------------------------------------------------------------------------*/
2114template <typename T>
2117{
2118 ARCANE_UNUSED(ptr);
2119
2120 if (!_isValidVariable(v))
2121 return;
2122
2123 warning() << "Impossible to write array variable "
2124 << v.name() << " of non-constant size; variable saving skipped";
2125}
2126
2127/*---------------------------------------------------------------------------*/
2128/*---------------------------------------------------------------------------*/
2134{
2135 if (!_isValidVariable(v))
2136 return;
2137
2138 String filename;
2139 _buildFileName(v.name(), filename);
2140
2141 debug() << "Saving variable " << v.name() << " in " << filename;
2142
2143 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2144
2145 _writeFileHeader(dw_ofile(), false);
2146 if (m_is_master)
2147 writeFileString(dw_ofile(), v.name());
2148
2149 if (m_is_master) {
2150 switch (v.itemKind()) {
2151 case IK_Cell:
2152 case IK_Face:
2153 m_case_file_variables << "vector per element: ";
2154 break;
2155 case IK_Node:
2156 m_case_file_variables << "vector per node: ";
2157 break;
2158 default:
2159 break;
2160 }
2161
2162 m_case_file_variables << " 1 ";
2163 if (m_fileset_size != 0)
2164 m_case_file_variables << " 1 ";
2165 m_case_file_variables << v.name();
2166
2167 _writeWildcardFilename(m_case_file_variables, v.name());
2168 m_case_file_variables << '\n';
2169 }
2170
2171 switch (v.itemKind()) {
2172 case IK_Cell:
2173 case IK_Face:
2174 case IK_Edge: {
2175 GroupIndexTable* idx = nullptr;
2176
2177 if (v.isPartial()) {
2178 idx = v.itemGroup().localIdToIndex().get();
2179 }
2180
2181 WriteReal3 wf(*this, ptr, idx);
2182 for (const GroupPartInfo* part : m_parts) {
2183 bool need_save = false;
2184 if (v.isPartial())
2185 need_save = v.itemGroup() == part->group();
2186 else
2187 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2188 if (need_save)
2189 _saveVariableOnGroup(dw_ofile(), *part, wf);
2190 }
2191 } break;
2192 case IK_Node: {
2193 if (v.isPartial())
2194 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2195 WriteReal3 wf(*this, ptr);
2196 wf.begin();
2197 for (Integer i = 0; i < ptr.size(); ++i)
2198 wf.write(i);
2199 wf.end();
2200 for (const GroupPartInfo* part : m_parts) {
2201 writeFileString(dw_ofile(), "part");
2202 writeFileInt(dw_ofile(), part->partId());
2203 writeFileString(dw_ofile(), "coordinates");
2204 wf.putValue(dw_ofile());
2205 }
2206 } break;
2207 default:
2208 break;
2209 }
2210
2211 dw_ofile.syncFile();
2212}
2213
2214/*---------------------------------------------------------------------------*/
2215/*---------------------------------------------------------------------------*/
2221{
2222 if (!_isValidVariable(v))
2223 return;
2224
2225 for (Integer idim2 = 0; idim2 < ptr.dim2Size(); ++idim2) {
2226 String vname = v.name() + String("_") + idim2;
2227 String filename;
2228 _buildFileName(vname, filename);
2229
2230 debug() << "Saving variable " << v.name() << " component " << idim2 << " in " << filename;
2231
2232 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2233
2234 _writeFileHeader(dw_ofile(), false);
2235 if (m_is_master)
2236 writeFileString(dw_ofile(), vname);
2237
2238 if (m_is_master) {
2239 switch (v.itemKind()) {
2240 case IK_Cell:
2241 case IK_Face:
2242 m_case_file_variables << "vector per element: ";
2243 break;
2244 case IK_Node:
2245 m_case_file_variables << "vector per node: ";
2246 break;
2247 default:
2248 break;
2249 }
2250
2251 m_case_file_variables << " 1 ";
2252 if (m_fileset_size != 0)
2253 m_case_file_variables << " 1 ";
2254 m_case_file_variables << vname;
2255
2256 _writeWildcardFilename(m_case_file_variables, vname);
2257 m_case_file_variables << '\n';
2258 }
2259
2260 switch (v.itemKind()) {
2261 case IK_Cell:
2262 case IK_Face:
2263 case IK_Edge: {
2264 GroupIndexTable* idx = nullptr;
2265
2266 if (v.isPartial()) {
2267 idx = v.itemGroup().localIdToIndex().get();
2268 }
2269
2270 WriteArrayReal3 wf(*this, ptr, idim2, idx);
2271 for (const GroupPartInfo* part : m_parts) {
2272 bool need_save = false;
2273 if (v.isPartial())
2274 need_save = v.itemGroup() == part->group();
2275 else
2276 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2277 if (need_save)
2278 _saveVariableOnGroup(dw_ofile(), *part, wf);
2279 }
2280 } break;
2281 case IK_Node: {
2282 if (v.isPartial())
2283 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2284 WriteArrayReal3 wf(*this, ptr, idim2);
2285 wf.begin();
2286 for (Integer i = 0; i < ptr.dim1Size(); ++i)
2287 wf.write(i);
2288 wf.end();
2289 for (const GroupPartInfo* part : m_parts) {
2290 writeFileString(dw_ofile(), "part");
2291 writeFileInt(dw_ofile(), part->partId());
2292 writeFileString(dw_ofile(), "coordinates");
2293 wf.putValue(dw_ofile());
2294 }
2295 } break;
2296 default:
2297 break;
2298 }
2299
2300 dw_ofile.syncFile();
2301 }
2302
2303 //if (m_is_transient && m_is_master)
2304 //writeFileString(dw_ofile(),"END TIME STEP");
2305}
2306
2307/*---------------------------------------------------------------------------*/
2308/*---------------------------------------------------------------------------*/
2314{
2315 ARCANE_UNUSED(ptr);
2316
2317 if (!_isValidVariable(v))
2318 return;
2319
2320 warning() << "Impossible to write array variable " << v.name()
2321 << " of non-constant size; variable saving skipped";
2322}
2323
2324/*---------------------------------------------------------------------------*/
2325/*---------------------------------------------------------------------------*/
2329class Ensight7PostProcessorService
2330: public PostProcessorWriterBase
2331{
2332 public:
2333
2334 Ensight7PostProcessorService(const ServiceBuildInfo& sbi)
2335 : PostProcessorWriterBase(sbi)
2336 , m_mesh(sbi.mesh())
2337 , m_writer(nullptr)
2338 {
2339 }
2340
2341 IDataWriter* dataWriter() override { return m_writer; }
2342 void notifyBeginWrite() override;
2343 void notifyEndWrite() override;
2344 void close() override {}
2345
2346 private:
2347
2348 IMesh* m_mesh;
2349 DumpW* m_writer;
2350};
2351
2352/*---------------------------------------------------------------------------*/
2353/*---------------------------------------------------------------------------*/
2354
2357{
2358 bool is_binary = true;
2359 Integer fileset_size = 100;
2360 bool is_parallel = subDomain()->parallelMng()->isParallel();
2361 bool use_degenerated_hexa = true;
2362 bool force_first_geometry = false;
2363 bool save_uids = false;
2364 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2365 variables(), groups(), is_binary, is_parallel,
2366 fileset_size, use_degenerated_hexa,
2367 force_first_geometry, save_uids);
2368}
2369
2372{
2373 delete m_writer;
2374 m_writer = 0;
2375}
2376
2377/*---------------------------------------------------------------------------*/
2378/*---------------------------------------------------------------------------*/
2379
2380/*---------------------------------------------------------------------------*/
2381/*---------------------------------------------------------------------------*/
2385class Ensight7PostProcessorServiceV2
2387{
2388 public:
2389
2390 typedef ArcaneEnsight7PostProcessorObject BaseType;
2391
2392 public:
2393
2394 Ensight7PostProcessorServiceV2(const ServiceBuildInfo& sbi)
2396 , m_mesh(sbi.mesh())
2397 , m_writer(nullptr)
2398 {
2399 }
2400
2401 void build() override
2402 {
2404 }
2405 IDataWriter* dataWriter() override { return m_writer; }
2406 void notifyBeginWrite() override;
2407 void notifyEndWrite() override;
2408 void close() override {}
2409
2410 void setBaseDirectoryName(const String& dirname) override
2411 {
2413 }
2414 const String& baseDirectoryName() override
2415 {
2417 }
2418 void setMesh(IMesh* mesh) override
2419 {
2420 m_mesh = mesh;
2421 }
2434
2435 private:
2436
2437 IMesh* m_mesh;
2438 DumpW* m_writer;
2439};
2440
2441/*---------------------------------------------------------------------------*/
2442/*---------------------------------------------------------------------------*/
2443
2446{
2447 // std::cout << " ############# IMesh = " << mesh() << " " << m_mesh << " ###########\n";
2448
2449 bool is_binary = true;
2450 Integer fileset_size = 0;
2451 bool is_parallel = m_mesh->parallelMng()->isParallel();
2452 is_binary = options()->binaryFile();
2453 fileset_size = options()->filesetSize();
2454 bool use_degenerated_hexa = options()->useDegeneratedHexa();
2455 bool force_first_geometry = options()->forceFirstGeometry();
2456 bool save_uids = options()->saveUids();
2457 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2458 variables(), groups(), is_binary, is_parallel, fileset_size,
2459 use_degenerated_hexa, force_first_geometry, save_uids);
2460}
2461
2464{
2465 delete m_writer;
2466 m_writer = nullptr;
2467}
2468
2469/*---------------------------------------------------------------------------*/
2470/*---------------------------------------------------------------------------*/
2471
2473 Ensight7PostProcessor);
2474
2475ARCANE_REGISTER_SERVICE_ENSIGHT7POSTPROCESSOR(Ensight7PostProcessor, Ensight7PostProcessorServiceV2);
2476
2477/*---------------------------------------------------------------------------*/
2478/*---------------------------------------------------------------------------*/
2479
2480} // namespace Arcane
2481
2482/*---------------------------------------------------------------------------*/
2483/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
#define ARCANE_REGISTER_SUB_DOMAIN_FACTORY(aclass, ainterface, aname)
Enregistre un service de fabrique pour la classe aclass.
Integer size() const
Nombre d'éléments du vecteur.
CaseOptionsEnsight7PostProcessor * options() const
Options du jeu de données du service.
ArcaneEnsight7PostProcessorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
Tableau d'items de types quelconques.
void fill(const DataType &data)
Remplissage du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
const T * data() const
Accès à la racine du tableau hors toute protection.
ArrayView< T > view() const
Vue mutable sur ce tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Maille d'un maillage.
Definition Item.h:1214
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Definition Item.h:1298
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1295
Int32 nbFace() const
Nombre de faces de la maille.
Definition Item.h:1292
Integer count() const
Nombre d'éléments de la collection.
Vue constante d'un tableau de type T.
constexpr const_pointer data() const noexcept
Pointeur sur la mémoire allouée.
ConstIterT< ConstArrayView< T > > const_iter
Type d'un itérateur constant sur tout le tableau.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
interval d'itérateurs constant
Vue constante sur un MultiArray2.
Classe gérant un répertoire.
Definition Directory.h:35
bool createDirectory() const override
Créé le répertoire.
Definition Directory.cc:102
Abstraction d'un fichier de sortie pour ensight.
Functor pour écrire une variable de type Real
Functor pour écrire une variable de type Real3
Fonctor pour écrire une variable.
Functor pour écrire une variable de type Real
Functor pour écrire une variable de type Real2
Ecriture au format Ensight7.
void _writeRealValT(IVariable &v, ConstArrayView< T > a)
Template for writing variable as a real variable.
std::ofstream m_case_file
Fichier décrivant le cas.
bool m_is_binary
Liste des parties.
void writeVal(IVariable &, ConstArrayView< Byte >) override
Ecriture pour la variable v du tableau a.
void beginWrite() override
Notifie le début d'écriture.
Directory m_part_directory
Répertoire de stockage de l'itération courante.
void _buildFileName(const String &varname, String &filename)
Construit le nom de fichier pour un nom de variable ou de maillage.
IMesh * m_mesh
Maillage.
bool _isValidVariable(IVariable &) const
Vérifie la validité de la variable à sauvegarder.
ItemGroupList m_save_groups
Liste des groupes a exporter.
void _buildPartDirectory()
Construit le répertoire où seront sauvées les variables.
IParallelMng * m_parallel_mng
Gestionnaire du parallélisme.
void endWrite() override
Notifie la fin d'écriture.
RealUniqueArray m_times
description des variables sauvées
void setMetaData(const String &) override
Positionne les infos des méta-données.
VariableList m_save_variables
Liste des variables a exporter.
static const Integer m_max_prots_digit
Nombre maximum de chiffres pour indiquer le numéro de protection.
Directory m_base_directory
Nom du répertoire de stockage.
bool m_is_master
true si le processeur dirige la sortie
Integer m_total_nb_element
Nombre total d'éléments de maillage de tous les groupes à sauver.
Integer m_total_nb_group
Nombre de groupes à sauver (== nombre de part)
wrapper transformant des appels à l'interface IDataWriter en ex IDumpW
Definition DumpW.h:45
DumpW()
Constructeur.
Definition DumpW.cc:155
void write(IVariable *var, IData *data)
Ecrit les données data de la variable var.
Definition DumpW.cc:179
Post-traitement au format Ensight7.
void build() override
Construction de niveau build du service.
void notifyBeginWrite() override
Notifie qu'une sortie va être effectuée avec les paramètres courants.
void setBaseDirectoryName(const String &dirname) override
Positionne le nom du répertoire de sortie des fichiers. Ce répertoire doit exister.
void close() override
Ferme l'écrivain. Après fermeture, il ne peut plus être utilisé
void setGroups(ItemGroupCollection groups) override
Positionne la liste des groupes à sortir.
void notifyEndWrite() override
Notifie qu'une sortie vient d'être effectuée.
void setVariables(VariableCollection variables) override
Positionne la liste des variables à sortir.
void setTimes(RealConstArrayView times) override
Positionne la liste des temps.
IDataWriter * dataWriter() override
Retourne l'écrivain associé à ce post-processeur.
const String & baseDirectoryName() override
Nom du répertoire de sortie des fichiers.
void setMesh(IMesh *mesh) override
Positionne le maillage.
Post-traitement au format Ensight7.
IDataWriter * dataWriter() override
Retourne l'écrivain associé à ce post-processeur.
void close() override
Ferme l'écrivain. Après fermeture, il ne peut plus être utilisé
void notifyEndWrite() override
Notifie qu'une sortie vient d'être effectuée.
void notifyBeginWrite() override
Notifie qu'une sortie va être effectuée avec les paramètres courants.
Face d'une maille.
Definition Item.h:964
Informations sur le type flottant.
Definition Limits.h:48
Classe de base d'une table de hachage entre les items d'un groupe et leurs positions dans la table.
Interface d'écriture des données d'une variable.
Definition IDataWriter.h:44
virtual String name() const =0
Nom de la famille.
virtual ItemTypeMng * itemTypeMng() const =0
Gestionnaire de types d'entités associé
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
Interface d'un écrivain pour les informations de post-traitement.
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual IMesh * defaultMesh()=0
Maillage par défaut.
Interface d'une variable.
Definition IVariable.h:39
virtual void setUsed(bool v)=0
Positionne l'état d'utilisation de la variable.
@ PTemporary
Indique que la variable est temporaire.
Definition IVariable.h:111
@ PPrivate
Indique que la variable est privée.
Definition IVariable.h:99
virtual eItemKind itemKind() const =0
Genre des entités du maillage sur lequel repose la variable.
virtual bool isPartial() const =0
Indique si la variable est partielle.
virtual IData * data()=0
Données associées à la variable.
virtual bool isUsed() const =0
Etat d'utilisation de la variable.
virtual ItemGroup itemGroup() const =0
Groupe du maillage associé.
virtual void notifyBeginWrite()=0
Notifie du début d'écriture de data().
virtual String name() const =0
Nom de la variable.
Groupe d'entités de maillage.
Definition ItemGroup.h:49
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
bool isOwn() const
Retourne si le groupe contient uniquement des éléments propres au sous-domaine.
Definition ItemGroup.cc:158
SharedPtrT< GroupIndexTable > localIdToIndex() const
Table des local ids vers une position pour toutes les entités du groupe.
Definition ItemGroup.h:307
Integer size() const
Nombre d'éléments du groupe.
Definition ItemGroup.h:88
IItemFamily * itemFamily() const
Famille d'entité à laquelle appartient ce groupe (0 pour le group nul)
Definition ItemGroup.h:123
eItemKind itemKind() const
Genre du groupe. Il s'agit du genre de ses éléments.
Definition ItemGroup.h:109
bool null() const
true is le groupe est le groupe nul
Definition ItemGroup.h:70
IMesh * mesh() const
Maillage auquel appartient ce groupe (0 pour le group nul)
Definition ItemGroup.h:126
ItemGroup own() const
Groupe équivalent à celui-ci mais contenant uniquement les éléments propres au sous-domaine.
Definition ItemGroup.cc:190
Informations locales sur une face d'une maille.
Integer node(Integer i) const
Indice locale dans la maille du i-ème noeud de la face.
Integer nbNode() const
Nombre de noeuds de la face.
Infos sur un type d'entité du maillage.
LocalFace localFace(Integer id) const
Connectivité locale de la i-ème face de la maille.
Integer nbLocalEdge() const
Nombre d'arêtes de l'entité
Integer nbLocalNode() const
Nombre de noeuds de l'entité
Integer nbLocalFace() const
Nombre de faces de l'entité
Gestionnaire des types d'entités d'un maillage.
Definition ItemTypeMng.h:65
bool hasGeneralCells(IMesh *mesh) const
Indique si le maillage mesh contient des mailles génériques (en dehors des types intégrés ou addition...
static Integer nbBasicItemType()
nombre de types disponibles
ItemTypeInfo * typeFromId(Integer id) const
Type correspondant au numéro id.
static Integer nbBuiltInItemType()
nombre de types intégrés (hors types additionnels)
Elément de maillage s'appuyant sur des noeuds (Edge,Face,Cell).
Definition Item.h:736
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:791
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:788
Classe de base d'un élément de maillage.
Definition Item.h:83
const ItemTypeInfo * typeInfo() const
Infos sur le type de l'entité.
Definition Item.h:392
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
ItemWithNodes toItemWithNodes() const
Converti l'entité en le genre ItemWithNodes.
Definition Item.h:1674
Cell toCell() const
Converti l'entité en le genre Cell.
Definition Item.h:1702
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
Int16 type() const
Type de l'entité
Definition Item.h:241
void clone(const Collection< T > &base)
Clone la collection base.
Exception lorsqu'une fonction n'est pas implémentée.
Flot de sortie lié à une String.
void setTimes(RealConstArrayView times) override
Positionne la liste des temps.
void setBaseDirectoryName(const String &dirname) override
Positionne le nom du répertoire de sortie des fichiers. Ce répertoire doit exister.
VariableCollection variables() override
Liste des variables à sauver.
void build() override
Construction de niveau build du service.
RealConstArrayView times() override
Liste des temps sauvés.
void setVariables(VariableCollection variables) override
Positionne la liste des variables à sortir.
const String & baseDirectoryName() override
Nom du répertoire de sortie des fichiers.
ItemGroupCollection groups() override
Liste des groupes à sauver.
void setGroups(ItemGroupCollection groups) override
Positionne la liste des groupes à sortir.
T * get() const
Retourne l'objet référé par l'instance.
Definition Ptr.h:121
Encapsulation d'un pointeur qui se détruit automatiquement.
Definition ScopedPtr.h:44
IMesh * mesh() const
Accès au IMesh associé.
Structure contenant les informations pour créer un service.
Constructeur de chaîne de caractère unicode.
String toString() const
Retourne la chaîne de caractères construite.
Chaîne de caractères unicode.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:228
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage warning() const
Flot pour un message d'avertissement.
Vecteur 1D de données avec sémantique par valeur (style STL).
Paramètres nécessaires à la construction d'une variable.
Collection de variables.
IVariable * variable() const
Variable associée.
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
Definition ItemTypes.h:167
MeshVariableScalarRefT< Cell, Real > VariableCellReal
Grandeur au centre des mailles de type réel.
MeshVariableScalarRefT< Node, Integer > VariableNodeInteger
Grandeur au noeud de type entier.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
char * copyn(char *to, const char *from, Integer n)
Copie les n premiers caractères de from dans to.
Real toReal(Real r)
Converti r en un Real.
double toDouble(Real r)
Converti un Real en double.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Integer arcaneCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....
Collection< ItemGroup > ItemGroupCollection
Collection de groupes d'éléments du maillage.
Int32 Integer
Type représentant un entier.
List< ItemGroup > ItemGroupList
Tableau de groupes d'éléments du maillage.
SharedMeshVariableScalarRefT< Node, Real3 > SharedVariableNodeReal3
Grandeur au noeud de type coordonnées.
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:349
eItemKind
Genre d'entité de maillage.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
@ IK_Unknown
Entité de maillage de genre inconnu ou non initialisé
@ IK_Face
Entité de maillage de genre face.
@ IK_Edge
Entité de maillage de genre arête.
double Real
Type représentant un réel.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:347
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:486
std::int32_t Int32
Type entier signé sur 32 bits.
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:488
Correspondance entre le type des éléments ensight et Arcane.
int m_type
Type Arcane de l'élément.
UniqueArray< Item > m_items
Entités des éléments de ce type.
Integer m_nb_node
Nombre de noeud.
String m_name
Nom Ensight de cet élément.
Information pour partagé un groupe en éléments de même sous-type.
Integer m_part_id
Numéro de la partie.
std::unique_ptr< VariableItemInt32 > m_general_item_types
Variable pour stocker les types des items généraux (non typés)
Integer nbType() const
Nombre de sous-types.