Arcane  v3.14.10.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-2024 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-2024 */
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/*---------------------------------------------------------------------------*/
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
111 {
112 public:
113
115 : m_type(-1)
116 , m_nb_node(0)
117 {}
118 EnsightPart(int type, Integer nb_node, const String& name)
119 : m_type(type)
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;
152 Integer m_nb_node;
155 UniqueArray<Integer> m_reindex;
156 };
157
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
208 Integer m_part_id;
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 {
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'
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
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 // todo do not use internal, but how ?
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
366 {
367 public:
368
369 explicit WriteBase(DumpWEnsight7& dw)
370 : m_dw(dw)
371 {}
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>
412 : public WriteBase
413 {
414 public:
415
417 : WriteBase(dw, idx)
418 , m_ptr(ptr)
419 {}
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>
458 : public WriteBase
459 {
460 public:
461
463 GroupIndexTable* idx = nullptr)
464 : WriteBase(dw, idx)
465 , m_ptr(ptr)
466 , m_idim2(idim2)
467 {}
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
511 : public WriteBase
512 {
513 public:
514
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
592 : public WriteBase
593 {
594 public:
595
597 Integer idim2, GroupIndexTable* idx = nullptr)
598 : WriteBase(dw, idx)
599 , m_ptr(ptr)
600 , m_idim2(idim2)
601 {}
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,
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;
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,
777 void _saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
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,
802{
803 return new DumpWEnsight7(m->defaultMesh(), f, times, variables, groups, is_binary,
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{
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écessaire 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
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 type may be added, equal to number of elements)
913 {
914 debug(Trace::High) << "Using standard group part building algo";
915 auto nb_basic_item_types = grp.mesh()->itemTypeMng()->nbBasicItemType();
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 if (type_to_seek < nb_basic_item_types) { // "classical type"
923 const Item& e = *i2;
924 if (e.type() == type_to_seek)
925 ++nb_of_type;
926 }
927 }
928 else { // general items
930 const Item& e = *i2;
931 if (current_grp.generalItemTypeId(e) == type_to_seek)
932 ++nb_of_type;
933 }
934 }
935 items.resize(nb_of_type);
936 debug(Trace::High) << "Group " << grp.name() << " has "
937 << nb_of_type << " items of type " << type_info.name();
938 Integer index = 0;
939 if (type_to_seek < nb_basic_item_types) { // "classical type"
941 Item mi = *iz;
942 if (mi.type() == type_to_seek) {
943 ItemWithNodes e = mi.toItemWithNodes();
944 items[index] = e;
945 ++index;
946 }
947 }
948 }
949 else { // general items
951 Item mi = *iz;
952 if (current_grp.generalItemTypeId(mi) == type_to_seek) {
953 ItemWithNodes e = mi.toItemWithNodes();
954 items[index] = e;
955 ++index;
956 }
957 }
958 }
959 }
960 }
961 else // extra types are added (may have as many types as items...)
962 // Propose an optimized version when many types exist (use of .format file)
963 {
964 debug(Trace::High) << "Using extra type group part building algo";
965 // work only on face and cell groups
966 auto item_kind = grp.itemKind();
967 if (item_kind == IK_Cell || item_kind == IK_Face) {
968 ENUMERATE_ITEM (item, grp) {
969 auto item_type = item->type();
970 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
971 if (!ensight_part)
972 continue ;
973 ItemWithNodes item_wn = item->toItemWithNodes();
974 ensight_part->items().add(item_wn); // few elements are added
975 }
976 }
977 }
978 }
979}
980
981/*---------------------------------------------------------------------------*/
982/*---------------------------------------------------------------------------*/
1004void DumpWEnsight7::
1005_saveGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
1007{
1008 ItemGroup igrp = ensight_grp.group();
1009
1010 writeFileString(ofile, "part");
1011 writeFileInt(ofile, ensight_grp.partId());
1012 if (isParallelOutput()) {
1013 // Dans le cas d'une sortie parallele, prefixe le nom du groupe par le
1014 // numéro du CPU.
1015 std::ostringstream ostr;
1016 ostr << igrp.name().localstr() << "_CPU" << rank();
1017 writeFileString(ofile, ostr.str().c_str());
1018 }
1019 else
1020 writeFileString(ofile, igrp.name());
1021
1022 wf.putValue(ofile);
1023
1025
1026 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1027 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1028 ConstArrayView<Item> items = type_info.items();
1029 Integer nb_sub_part = items.size();
1030 if (nb_sub_part == 0)
1031 continue;
1032
1033 String type_name = type_info.name();
1034 writeFileString(ofile, type_name);
1035
1036 writeFileInt(ofile, nb_sub_part);
1037
1038#if 0
1039 // Sauve les uniqueId() des entités
1040 for( ConstArrayView<Item>::const_iter i(items); i(); ++i ){
1041 Item mi = *i;
1042 writeFileInt(ofile,mi.uniqueId()+1);
1043 }
1044#endif
1045
1046 if (type_name == "nfaced") {
1047 // Traitement particulier pour les mailles non standards
1048 // Comme nos faces ne sont pas orientées par rapport à une
1049 // maille, on utilise la connectivité locale de chaque face.
1050 // 1. Sauve le nombre de faces de chaque élément
1051 {
1052 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1053 // Tous les éléments ont le même nombre de faces
1054 Item mi = *items.data();
1055 Cell cell = mi.toCell();
1056 Integer nb_face = cell.nbFace();
1057 for (Integer z = 0; z < nb_sub_part; ++z)
1058 writeFileInt(ofile, nb_face);
1059 }
1060 else { // mesh has general items
1061 // All items do not have the same face number
1062 for (Item mi : items) {
1063 writeFileInt(ofile, mi.toCell().nbFace());
1064 }
1065 }
1066 }
1067 // 2. Sauve pour chaque elément, le nombre de noeuds de chacune
1068 // de ces faces
1069 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1070 for (Item mi : items) {
1071 const ItemTypeInfo* item_info = mi.typeInfo();
1072 Integer nb_face = item_info->nbLocalFace();
1073 for (Integer z = 0; z < nb_face; ++z)
1074 writeFileInt(ofile, item_info->localFace(z).nbNode());
1075 }
1076 }
1077 else { // mesh has general items
1078 for (Item mi : items) {
1079 Cell cell = mi.toCell();
1080 for (Face face : cell.faces()) {
1081 writeFileInt(ofile, face.nbNode());
1082 }
1083 }
1084 }
1085 // 3. Sauve pour chaque face de chaque élément la liste de ces
1086 // noeuds
1087 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1088 for (Item item : items) {
1089 Cell cell(item.toCell());
1090 const ItemTypeInfo* item_info = cell.typeInfo();
1091 //Cell cell = mi.toCell();
1092 Integer nb_face = item_info->nbLocalFace();
1093 for (Integer z = 0; z < nb_face; ++z) {
1094 const ItemTypeInfo::LocalFace& local_face = item_info->localFace(z);
1095 Integer nb_node = local_face.nbNode();
1096 array_id.resize(nb_node);
1097 for (Integer y = 0; y < nb_node; ++y) {
1098 // Inversion du sens des noeuds
1099 // A priori, il y a un bug dans Ensight (7.4.1(g)) concernant les
1100 // intersections de ce type d'éléments avec les objets
1101 // Ensight (plan, sphere, ...). Quelle que soit l'orientation
1102 // des faces retenues, le comportant n'est pas correcte.
1103 array_id[y] = nodes_index[cell.node(local_face.node(y)).localId()];
1104 }
1105 writeFileArray(ofile, array_id);
1106 }
1107 }
1108 }
1109 else { // mesh has general items
1110 for (Item item : items) {
1111 Cell cell = item.toCell();
1112 Integer nb_face = cell.nbFace();
1113 for (Integer z = 0; z < nb_face; ++z) {
1114 const Face local_face = cell.face(z);
1115 Integer nb_node = local_face.nbNode();
1116 array_id.resize(nb_node);
1117 for (Integer y = 0; y < nb_node; ++y) {
1118 array_id[y] = nodes_index[local_face.node(y).localId()];
1119 }
1120 writeFileArray(ofile, array_id);
1121 }
1122 }
1123 }
1124 }
1125 else if (type_name == "nsided") {
1126 // Traitement particulier pour les faces à plus de 4 noeuds:
1127
1128 // 1. Sauve pour chaque elément, le nombre de ses noeuds
1129 //cerr << "** NSIDED ELEMENT\n";
1130 for (Item mi : items) {
1131 ItemWithNodes e = mi.toItemWithNodes();
1132 Integer nb_node = e.nbNode();
1133 writeFileInt(ofile, nb_node);
1134 }
1135 // 2. Sauve pour chaque elément la liste de ces noeuds
1136 for (Item mi : items) {
1137 ItemWithNodes e = mi.toItemWithNodes();
1138 Integer nb_node = e.nbNode();
1139 array_id.resize(nb_node);
1140 for (Integer z = 0; z < nb_node; ++z) {
1141 array_id[z] = nodes_index[e.node(z).localId()];
1142 }
1143 writeFileArray(ofile, array_id);
1144 }
1145 }
1146 else {
1147 // Cas général
1148
1149 Integer nb_node = type_info.nbNode();
1150 array_id.resize(nb_node);
1151
1152 // Sauvegarde les éléments.
1153
1154 // Sauve la connectivité des éléments
1155 if (type_info.hasReindex()) {
1156 ConstArrayView<Integer> reindex = type_info.reindex();
1157 for (Item mi : items) {
1158 ItemWithNodes e = mi.toItemWithNodes();
1159 for (Integer j = 0; j < nb_node; ++j) {
1160 array_id[j] = nodes_index[e.node(reindex[j]).localId()];
1161 }
1162 writeFileArray(ofile, array_id);
1163 }
1164 }
1165 else { // no reindex
1166 for (Item mi : items) {
1167 ItemWithNodes e = mi.toItemWithNodes();
1168 for (Integer j = 0; j < nb_node; ++j) {
1170 }
1171 writeFileArray(ofile, array_id);
1172 }
1173 }
1174 }
1175 }
1176}
1177
1178/*---------------------------------------------------------------------------*/
1179/*---------------------------------------------------------------------------*/
1205void DumpWEnsight7::
1206_saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
1208{
1209 ItemGroup igrp = ensight_grp.group();
1210
1211 writeFileString(ofile, "part");
1212 writeFileInt(ofile, ensight_grp.partId());
1213
1214 // Les éléments de même types (en particulier les 'nfaced', 'haxa8' ou 'nsided')
1215 // doivent être écrits d'un seul bloc (donc label de type unifié).
1216 // Par ailleurs, les données vectorielles doivent être entrelacés.
1219 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1220 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1221 ConstArrayView<Item> items(type_info.items());
1222 Integer nb_sub_part = items.size();
1223 if (nb_sub_part == 0)
1224 continue;
1225 String type_name = type_info.name();
1226 if (type_name != last_type_name) {
1227 // Cloture la précédente écriture
1228 if (func.get()) {
1229 func->end();
1230 func->putValue(ofile);
1231 }
1233 writeFileString(ofile, type_name);
1234 func = from_func.clone();
1235 func->begin();
1236 }
1237
1238 // Sauvegarde les variables.
1239 func->write(items);
1240 }
1241
1242 // Cloture finale
1243 if (func.get()) {
1244 func->end();
1245 func->putValue(ofile);
1246 }
1247}
1248
1249/*---------------------------------------------------------------------------*/
1250/*---------------------------------------------------------------------------*/
1251
1252void DumpWEnsight7::
1253writeFileInt(std::ostream& o, int value)
1254{
1255 if (m_is_binary) {
1256 o.write((const char*)&value, sizeof(int));
1257 }
1258 else {
1259 o.width(DumpWEnsight7::int_width);
1260 o << value;
1261 o << '\n';
1262 }
1263}
1264
1265/*---------------------------------------------------------------------------*/
1266/*---------------------------------------------------------------------------*/
1267
1268Integer DumpWEnsight7::
1269writeIntSize() const
1270{
1271 if (m_is_binary)
1272 return sizeof(int);
1273 return DumpWEnsight7::int_width + 1;
1274}
1275
1276/*---------------------------------------------------------------------------*/
1277/*---------------------------------------------------------------------------*/
1278
1279void DumpWEnsight7::
1280writeFileDouble(std::ostream& o, double value)
1281{
1282 if (m_is_binary) {
1283 float fvalue = (float)(value);
1284 o.write((const char*)&fvalue, sizeof(float));
1285 }
1286 else {
1287 o.width(12);
1288 o.precision(5);
1289 o.flags(std::ios::scientific);
1290 o << value;
1291 o << '\n';
1292 }
1293}
1294
1295/*---------------------------------------------------------------------------*/
1296/*---------------------------------------------------------------------------*/
1297
1298Integer DumpWEnsight7::
1299writeDoubleSize() const
1300{
1301 Integer float_size = (Integer)(sizeof(float));
1302 return (m_is_binary) ? float_size : (12 + 1);
1303}
1304
1305/*---------------------------------------------------------------------------*/
1306/*---------------------------------------------------------------------------*/
1307
1308void DumpWEnsight7::
1309writeFileArray(std::ostream& o, IntegerConstArrayView value)
1310{
1311 if (m_is_binary) {
1312 o.write((const char*)value.data(), sizeof(Integer) * value.size());
1313 }
1314 else {
1315 for (Integer i = 0, s = value.size(); i < s; ++i) {
1316 o.width(DumpWEnsight7::int_width);
1317 o << value[i];
1318 }
1319 o << '\n';
1320 }
1321}
1322
1323/*---------------------------------------------------------------------------*/
1324/*---------------------------------------------------------------------------*/
1325
1326void DumpWEnsight7::
1327writeFileString(std::ostream& o, const String& str)
1328{
1329 if (m_is_binary) {
1330 char buf[g_line_length];
1331 for (int i = 0; i < g_line_length; ++i)
1332 buf[i] = '\0';
1333 CStringUtils::copyn(buf, str.localstr(), g_line_length);
1334 buf[g_line_length - 1] = '\0';
1335 o.write(buf, g_line_length);
1336 }
1337 else {
1338 o << str << '\n';
1339 }
1340}
1341
1342/*---------------------------------------------------------------------------*/
1343/*---------------------------------------------------------------------------*/
1344
1345void DumpWEnsight7::
1346_writeFileHeader(std::ostream& o, bool write_c_binary)
1347{
1348 if (m_is_master) {
1349 if (_isNewBlocFile() && m_is_binary && write_c_binary)
1350 writeFileString(o, "C Binary");
1351 if (m_fileset_size != 0) {
1352 std::ostringstream ostr;
1353 ostr << "BEGIN TIME STEP "
1354 << "# " << m_times.size();
1355 writeFileString(o, ostr.str().c_str());
1356 }
1357 }
1358}
1359
1360/*---------------------------------------------------------------------------*/
1361/*---------------------------------------------------------------------------*/
1370{
1371 public:
1372
1373 DumpWEnsight7OutFile(DumpWEnsight7& dw, const String& filename, int outtype)
1374 : m_dw(dw)
1375 , m_filename(filename)
1376 , m_is_master(dw.isMasterProcessor())
1377 , m_is_parallel_output(dw.isParallelOutput())
1378 , m_stream(0)
1379 , m_filestream(0)
1380 {
1381 if (m_is_master) {
1382 m_filestream = new std::ofstream(filename.localstr(), (std::ios_base::openmode)outtype);
1383 m_stream = &m_strstream;
1384 if (!(*m_filestream))
1385 m_dw.warning() << "Unable to open file " << filename;
1386 }
1387 else {
1388 // TODO attention fuites mémoires.
1389 m_stream = &m_strstream;
1390 }
1391 ARCANE_CHECK_PTR(m_stream);
1392 }
1394 {
1395 delete m_filestream;
1396 }
1397
1398 public:
1399
1400 void syncFile()
1401 {
1402 IParallelMng* parallel_mng = m_dw.parallelMng();
1403 if (m_is_master) {
1404 ARCANE_CHECK_PTR(m_filestream);
1405 ARCANE_CHECK_PTR(m_strstream);
1406 //Integer pos = m_strstream->tellp();
1407 (*m_filestream) << m_strstream.str();
1408 }
1409 if (m_is_parallel_output) {
1410 if (m_is_master) {
1411 ARCANE_CHECK_PTR(m_filestream);
1412
1413 // Le maitre parcours tous les processeurs et demande pour chacun
1414 // d'eux la taille de chaque sauvegarde et si elle n'est pas nulle,
1415 // réceptionne le message.
1416 Integer nb_proc = parallel_mng->commSize();
1419 for (Integer i = 1; i < nb_proc; ++i) {
1420 m_dw.debug(Trace::High) << "Waiting for length of processor " << i;
1421 parallel_mng->recv(len_array, i);
1422 Integer len = len_array[0];
1423 m_dw.debug(Trace::High) << "Length of processor " << i << " : " << len;
1424 if (len != 0) {
1425 str_array.resize(len);
1426 m_dw.debug(Trace::High) << "Waiting for receving geom of processor " << i;
1427 parallel_mng->recv(str_array, i);
1428 m_dw.debug(Trace::High) << "Receving geom of processor " << i;
1429 m_filestream->write((const char*)str_array.data(), str_array.size());
1430 }
1431 }
1432 }
1433 else {
1434 ARCANE_CHECK_PTR(m_strstream);
1435 // Un esclave envoie au processeur maître (actuellement le processeur 0)
1436 // la taille de ses données puis ces données.
1437 // Il faut bien prendre la longueur de la chaîne retournée par m_strstream
1438 // et pas uniquement c_str() car le flux pouvant contenant des informations
1439 // au format binaire, on s'arrêterait au premier zéro.
1441 std::string str = m_strstream.str();
1442 Integer len = arcaneCheckArraySize(str.length());
1443 UniqueArray<Byte> bytes(len);
1444 {
1445 // Recopie dans bytes la chaîne \a str
1446 Integer index = 0;
1447 for (ConstIterT<std::string> i(str); i(); ++i, ++index)
1448 bytes[index] = *i;
1449 }
1450 m_dw.debug(Trace::High) << "Not a master. " << m_filename << " size = " << len;
1451 //Integer len = m_strstream->tellp();
1452 //Integer len = str.length();
1453 len_array[0] = len;
1454 m_dw.debug(Trace::High) << "Sending length for processor 0";
1455 parallel_mng->send(len_array, 0);
1456 if (len != 0) {
1457 //UniqueArray<char> str_array(len);
1458 //std::string s = m_strstream->str();
1459 //platform::stdMemcpy(str_array.begin(),s.c_str(),s.length());
1460 m_dw.debug(Trace::High) << "Sending data for processor 0";
1461 parallel_mng->send(bytes, 0); //str.c_str())__array,0);
1462 //parallel_mng->send(str_array,0);
1463 }
1464 }
1465 }
1466 if (m_is_master)
1467 if (!m_dw.isOneFilePerTime())
1468 m_dw.writeFileString(*m_filestream, "END TIME STEP");
1469 }
1470
1471 public:
1472
1473 std::ostream& operator()() { return *m_stream; }
1474
1475 private:
1476
1477 DumpWEnsight7& m_dw;
1478 String m_filename;
1479 bool m_is_master;
1480 bool m_is_parallel_output;
1481 std::ostream* m_stream;
1482 std::ostringstream m_strstream;
1483 std::ofstream* m_filestream;
1484};
1485
1486/*---------------------------------------------------------------------------*/
1487/*---------------------------------------------------------------------------*/
1488
1489/*---------------------------------------------------------------------------*/
1490/*---------------------------------------------------------------------------*/
1491
1493beginWrite()
1494{
1495 String buf = m_base_directory.file("ensight.case");
1496
1498 bool is_parallel = parallel_mng->isParallel();
1499 m_is_master = true;
1500 if (is_parallel && m_is_parallel_output)
1501 m_is_master = parallel_mng->commRank() == 0;
1502
1503 // Détermine et créé le répertoire ou seront écrites les sorties
1504 // de cette itération.
1506
1507 IMesh* mesh = m_mesh;
1508
1509 // Récupère la liste des groupes et leur donne à chacun un identifiant
1510 // unique pour Ensight (part). Le numéro de l'identifiant débute à 2, le numéro 1
1511 // est pour la liste des noeuds
1512 {
1513
1515 // Si la liste des groupes à sauver est vide, sauve tous les groupes.
1516 // Sinon, sauve uniquement les groupes spécifiés.
1517 Integer nb_group = m_save_groups.count();
1518 if (nb_group == 0)
1519 list_group.clone(mesh->groups());
1520 else
1522 // Regarde la liste des variables partielles, et ajoute leur groupe à la liste
1523 // des groupes à sauver.
1525 IVariable* var = *ivar;
1526 if (!var->isPartial())
1527 continue;
1528 ItemGroup var_group = var->itemGroup();
1529 if (!list_group.contains(var_group))
1530 list_group.add(var_group);
1531 }
1532 Integer partid = 1;
1534 partid += parallel_mng->commRank() * list_group.count();
1535
1536 _computeGroupParts(list_group, partid);
1537
1538 // Récupère le nombre total d'eléments dans les groupes.
1539 Integer total_nb_element = 0;
1540 m_total_nb_group = 0;
1541 for (auto i : m_parts) {
1542 total_nb_element += i->totalNbElement();
1544 }
1545
1547 debug() << "Total nb element " << m_total_nb_element << " and group " << m_total_nb_group;
1548 debug() << "Add nodes " << mesh->nbNode();
1549 }
1550
1551 // Sauvegarde la géométrie au format Ensight7 gold
1552 if (!(m_times.size() > 1 && m_force_first_geometry)) {
1553 String filename;
1554 _buildFileName("ensight.geo", filename);
1555
1556 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1557
1558 _writeFileHeader(dw_ofile(), true);
1559
1560 if (m_is_master) {
1561 writeFileString(dw_ofile(), "Output ensight test");
1562 writeFileString(dw_ofile(), "File description");
1563 writeFileString(dw_ofile(), "node id assign");
1564 writeFileString(dw_ofile(), "element id assign");
1565 }
1566
1567 IMesh* mesh = m_mesh;
1568 NodeGroup all_nodes = mesh->allNodes();
1569
1570 // Ce tableau sert pour chaque entité maille, face ou arête pour
1571 // référencer ses noeuds par rapport au tableau de coordonnées
1572 // utilisé par Ensight. Le premier élément de ce tableau à pour indice 1
1574 all_nodes_index.fill(0);
1575
1578 if (mesh->parentMesh()) {
1580 coords_backup.resize(mesh->nodeFamily()->maxLocalId());
1583 }
1584 coords_array = coords_backup.view();
1585 }
1586 else {
1587 VariableNodeReal3& nodes_coords(mesh->toPrimaryMesh()->nodesCoordinates());
1589 }
1590
1591 WriteReal3 wf(*this, coords_array);
1592 {
1593 wf.init();
1594 writeFileString(wf.stream(), "coordinates");
1595 writeFileInt(wf.stream(), all_nodes.size());
1596 wf.begin();
1597
1598 // Stocke les indices locaux pour Ensight
1599 {
1600 Integer ensight_index = 1;
1602 const Item& item = *i_item;
1604 ++ensight_index;
1605 }
1606 }
1607
1608 // Affiche les numéros unique des noeuds
1609#if 0
1610 {
1612 const Item& item = *i_item;
1613 writeFileInt(wf.stream(),item.uniqueId()+1);
1614 }
1615 }
1616#endif
1617 // Affiche les coordonnées de chaque noeud
1619 const Item& item = *i_item;
1620 wf.write(item.localId());
1621 }
1622 wf.end();
1623 }
1624
1625 for (const GroupPartInfo* part : m_parts)
1626 _saveGroup(dw_ofile(), *part, all_nodes_index, wf);
1627
1628 dw_ofile.syncFile();
1629 }
1630}
1631
1632/*---------------------------------------------------------------------------*/
1633/*---------------------------------------------------------------------------*/
1634
1636endWrite()
1637{
1638 // Sauvegarde des identifiants uniques
1639 if (m_save_uids) {
1642 cell_uids[icell] = (Real)(icell->uniqueId().asInt64());
1643 }
1644 IVariable* cell_uid_var = cell_uids.variable();
1646 cell_uid_var->setUsed(true);
1647 cell_uid_var->notifyBeginWrite();
1649
1650 // GG: NOTE: je ne suis pas sur que cela fonctionne bien.
1651 //TODO: supprimer l'utilisation de deux variables
1653 UniqueArray<Real> node_uids2(m_mesh->nodeFamily()->allItems().size());
1655 node_uids[inode] = inode->uniqueId().asInt32();
1656 node_uids2[inode.index()] = (Real)inode->uniqueId().asInt64();
1657 }
1658
1659 IVariable* node_uid_var = node_uids.variable();
1661 node_uid_var->setUsed(true);
1662 _writeRealValT<Real>(*node_uid_var, node_uids2); // work around bug for node variables
1663 }
1664
1665 String buf = m_base_directory.file("ensight.case");
1666
1667 // Seul un processeur maître génère un fichier 'case'
1668 if (m_is_master) {
1669
1670 m_case_file.open(buf.localstr());
1671
1672 if (!m_case_file)
1673 warning() << "Unable to write to file: <" << buf << "> error: " << m_case_file.rdstate();
1674
1675 debug() << "** Exporting data to " << m_base_directory.path();
1676 m_case_file << "FORMAT\ntype: ensight gold\n";
1677
1678 m_case_file << "\nGEOMETRY\n";
1679 m_case_file << "model: 1";
1680 if (m_fileset_size != 0)
1681 m_case_file << " 1 ";
1682 if (m_force_first_geometry)
1683 _writeWildcardFilename(m_case_file, "ensight.geo", '0');
1684 else
1685 _writeWildcardFilename(m_case_file, "ensight.geo", '*');
1686 //m_case_file << " [change_coords_only]\n";
1687 m_case_file << "\n";
1688
1689 m_case_file << "\nVARIABLE\n";
1690 m_case_file << m_case_file_variables.str();
1691
1692 // Sauvegarde en temps. Pour paraview, il faut le mettre apres les variables
1693 m_case_file << "\nTIME\n";
1694 m_case_file << "time set: 1\n";
1695 m_case_file << "number of steps: " << m_times.size() << '\n';
1696 m_case_file << "filename start number: 0\n";
1697 m_case_file << "filename increment: 1\n";
1698 m_case_file << "time values:\n";
1699 // Faire attention de ne pas dépasser les 79 caractères par ligne
1700 // autorisés par Ensight. Pour être sur, on n'écrit qu'un temps pas
1701 // ligne. Les temps sont sauvés le maximum de chiffres significatifs
1702 // car Ensight n'aime pas que deux temps soient égaux.
1703 std::streamsize old_precision = m_case_file.precision(FloatInfo<Real>::maxDigit());
1704 for (Integer i = 0, is = m_times.size(); i < is; ++i)
1705 m_case_file << m_times[i] << '\n';
1706 m_case_file << '\n';
1707 m_case_file.precision(old_precision);
1708
1709 if (m_fileset_size != 0) {
1710 m_case_file << "FILE\n";
1711 m_case_file << "file set: 1\n";
1712 if (m_fileset_size != 0) {
1713 Integer nb_timeset = (m_times.size() / m_fileset_size);
1714 for (Integer i = 0; i < nb_timeset; ++i) {
1715 m_case_file << "filename index: " << i << "\n";
1716 m_case_file << "number of steps: " << m_fileset_size << '\n';
1717 }
1718 if (nb_timeset > 0)
1719 m_case_file << "filename index: " << nb_timeset << "\n";
1720 m_case_file << "number of steps: " << m_times.size() - (nb_timeset * m_fileset_size) << '\n';
1721 }
1722 else {
1723 m_case_file << "number of steps: " << m_times.size() << '\n';
1724 }
1725 m_case_file << '\n';
1726 }
1727 }
1728 m_case_file.flush();
1729 m_case_file.close();
1730}
1731
1732/*---------------------------------------------------------------------------*/
1733/*---------------------------------------------------------------------------*/
1734
1735/*---------------------------------------------------------------------------*/
1736/*---------------------------------------------------------------------------*/
1750{
1751 if (!v.isUsed())
1752 return false;
1753 eItemKind ik = v.itemKind();
1754 if (ik != IK_Cell && ik != IK_Node && ik != IK_Face)
1755 return false;
1756 // Si une liste de variable est spécifiée, vérifie que la variable est dans
1757 // cette liste. Si cette liste est vide, on sauve automatiquement toutes les
1758 // variables.
1759 Integer nb_var = m_save_variables.count();
1760 if (nb_var != 0) {
1761 return m_save_variables.contains(&v);
1762 }
1763 return true;
1764}
1765
1766/*---------------------------------------------------------------------------*/
1767/*---------------------------------------------------------------------------*/
1781_buildFileName(const String& name, String& filename)
1782{
1784 if (m_fileset_size == 0) {
1785 Integer current_time = m_times.size() - 1;
1787 fn_builder += "/";
1788 fn_builder += name;
1789 if (m_is_master) {
1790 Directory dir(fn_builder.toString());
1791 dir.createDirectory();
1792 }
1793 fn_builder += "/";
1794 fn_builder += name;
1795
1796 {
1798 ostr().fill('0'); // Caractère de remplissage.
1799 ostr().width(m_max_prots_digit);
1800 ostr() << current_time;
1801 fn_builder += ostr.str();
1802 }
1803
1804 //fn_builder += current_time;
1805
1806 //info() << " BUILD FILE NAME name=" << name << " filename=" << fn_builder;
1807 }
1808 else {
1810 fn_builder += "/";
1811 fn_builder += name;
1812 }
1813 filename = fn_builder;
1814}
1815
1816/*---------------------------------------------------------------------------*/
1817/*---------------------------------------------------------------------------*/
1818
1819bool DumpWEnsight7::
1820_isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind)
1821{
1822 eItemKind group_kind = group.itemKind();
1823 if (item_kind == IK_Unknown)
1824 return false;
1825 return group_kind == item_kind;
1826}
1827
1828/*---------------------------------------------------------------------------*/
1829/*---------------------------------------------------------------------------*/
1842{
1843 Integer prot_index = 0;
1844 bool has_prot = false;
1845 if (m_fileset_size != 0) {
1846 Integer nb_time = m_times.size();
1847 if (nb_time != 0)
1848 prot_index = (nb_time - 1) / m_fileset_size;
1849 has_prot = true;
1850 }
1851
1852 if (m_is_master)
1854
1855 if (has_prot) {
1857 ostr() << "bloc";
1858 ostr().fill('0'); // Caractère de remplissage.
1859 ostr().width(m_max_prots_digit);
1860 ostr() << prot_index;
1861 //ostr() << '\0';
1862 String buf = ostr.str();
1864 if (m_is_master)
1866 }
1867 else
1869}
1870
1871/*---------------------------------------------------------------------------*/
1872/*---------------------------------------------------------------------------*/
1873
1874void DumpWEnsight7::
1875_writeWildcardFilename(std::ostream& ofile, const String& filename, char joker)
1876{
1877 if (m_fileset_size == 0) {
1878 ofile << ' ' << filename << '/' << filename;
1879 for (Integer i = 0; i < m_max_prots_digit; ++i)
1880 ofile << joker;
1881 }
1882 else {
1883 ofile << " bloc";
1884 Integer nb_time = m_times.size();
1885 // Si le nombre de temps est inférieur à la taille d'un fileset-set,
1886 // il n'y a pas besoin de mettre une '*'. On peut directement
1887 // mettre des zéros. Cela est aussi indispensable pour empêcher
1888 // paraview de planter quand il relit ce genre de fichiers.
1889 if (nb_time <= m_fileset_size)
1890 joker = '0';
1891 for (Integer i = 0; i < m_max_prots_digit; ++i)
1892 ofile << joker;
1893 ofile << "/" << filename;
1894 }
1895}
1896
1897/*---------------------------------------------------------------------------*/
1898/*---------------------------------------------------------------------------*/
1899
1900bool DumpWEnsight7::
1901_isNewBlocFile() const
1902{
1903 Integer nb_time = m_times.size();
1904
1905 if (nb_time == 1)
1906 return true;
1907 if (m_fileset_size == 0)
1908 return true;
1909
1910 Integer modulo = (nb_time - 1) % m_fileset_size;
1911
1912 if (modulo == 0)
1913 return true;
1914 return false;
1915}
1916
1917/*---------------------------------------------------------------------------*/
1918/*---------------------------------------------------------------------------*/
1919
1920int DumpWEnsight7::
1921_fileOuttype() const
1922{
1923 return ((isBinary()) ? std::ios::binary : 0) | ((_isNewBlocFile()) ? std::ios::trunc : std::ios::app);
1924}
1925
1926/*---------------------------------------------------------------------------*/
1927/*---------------------------------------------------------------------------*/
1931template <typename T>
1934{
1935 debug() << "Saving variable1 " << v.name() << " ptr=" << ptr.data() << " ps=" << ptr.size();
1936
1937 if (!_isValidVariable(v))
1938 return;
1939
1940 String filename;
1941 _buildFileName(v.name(), filename);
1942
1943 debug() << "Saving variable " << v.name() << " in " << filename;
1944
1945 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1946
1947 _writeFileHeader(dw_ofile(), false);
1948
1949 if (m_is_master)
1950 writeFileString(dw_ofile(), v.name());
1952
1953 if (m_is_master) {
1954 switch (v.itemKind()) {
1955 case IK_Cell:
1956 case IK_Face:
1957 var_type_str = "scalar per element: ";
1958 break;
1959 case IK_Node:
1960 var_type_str = "scalar per node: ";
1961 break;
1962 default:
1963 break;
1964 }
1965
1966 m_case_file_variables << var_type_str;
1967 m_case_file_variables << " 1 ";
1968 if (m_fileset_size != 0)
1969 m_case_file_variables << " 1 ";
1970 m_case_file_variables << v.name();
1971 _writeWildcardFilename(m_case_file_variables, v.name());
1972 m_case_file_variables << '\n';
1973 }
1974
1975 switch (v.itemKind()) {
1976 case IK_Cell:
1977 case IK_Face:
1978 case IK_Edge: {
1979 GroupIndexTable* idx = nullptr;
1980
1981 if (v.isPartial()) {
1982 idx = v.itemGroup().localIdToIndex().get();
1983 }
1984
1985 WriteDouble<T> wf(*this, ptr, idx);
1986 for (const GroupPartInfo* part : m_parts) {
1987 bool need_save = false;
1988 if (v.isPartial())
1989 need_save = v.itemGroup() == part->group();
1990 else
1991 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
1992 if (need_save)
1993 _saveVariableOnGroup(dw_ofile(), *part, wf);
1994 }
1995 } break;
1996 case IK_Node: {
1997 if (v.isPartial())
1998 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
1999 WriteDouble<T> wf(*this, ptr);
2000 wf.begin();
2001 for (Integer i = 0; i < ptr.size(); ++i)
2002 wf.write(i);
2003 wf.end();
2004 for (const GroupPartInfo* part : m_parts) {
2005 writeFileString(dw_ofile(), "part");
2006 writeFileInt(dw_ofile(), part->partId());
2007 writeFileString(dw_ofile(), "coordinates");
2008 wf.putValue(dw_ofile());
2009 }
2010 } break;
2011 default:
2012 break;
2013 }
2014
2015 dw_ofile.syncFile();
2016
2017 //if (m_is_transient && m_is_master)
2018 //writeFileString(dw_ofile(),"END TIME STEP");
2019}
2020
2021/*---------------------------------------------------------------------------*/
2022/*---------------------------------------------------------------------------*/
2026template <typename T>
2029{
2030 if (!_isValidVariable(v))
2031 return;
2032
2033 for (Integer idim2 = 0; idim2 < ptr.dim2Size(); ++idim2) {
2034 String vname = v.name() + String("_") + idim2;
2035 String filename;
2036 _buildFileName(vname, filename);
2037
2038 debug() << "Saving variable " << v.name() << " component " << idim2 << " in " << filename;
2039
2040 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2041
2042 _writeFileHeader(dw_ofile(), false);
2043
2044 if (m_is_master)
2045 writeFileString(dw_ofile(), vname);
2047
2048 if (m_is_master) {
2049 switch (v.itemKind()) {
2050 case IK_Cell:
2051 case IK_Face:
2052 var_type_str = "scalar per element: ";
2053 break;
2054 case IK_Node:
2055 var_type_str = "scalar per node: ";
2056 break;
2057 default:
2058 break;
2059 }
2060
2061 m_case_file_variables << var_type_str;
2062 m_case_file_variables << " 1 ";
2063 if (m_fileset_size != 0)
2064 m_case_file_variables << " 1 ";
2065 m_case_file_variables << vname;
2066 _writeWildcardFilename(m_case_file_variables, vname);
2067 m_case_file_variables << '\n';
2068 }
2069
2070 switch (v.itemKind()) {
2071 case IK_Cell:
2072 case IK_Face:
2073 case IK_Edge: {
2074 GroupIndexTable* idx = nullptr;
2075
2076 if (v.isPartial()) {
2077 idx = v.itemGroup().localIdToIndex().get();
2078 }
2079
2080 WriteArrayDouble<T> wf(*this, ptr, idim2, idx);
2081 for (const GroupPartInfo* part : m_parts) {
2082 bool need_save = false;
2083 if (v.isPartial())
2084 need_save = v.itemGroup() == part->group();
2085 else
2086 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2087 if (need_save)
2088 _saveVariableOnGroup(dw_ofile(), *part, wf);
2089 }
2090 } break;
2091 case IK_Node: {
2092 if (v.isPartial())
2093 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2095 wf.begin();
2096 for (Integer i = 0; i < ptr.dim1Size(); ++i)
2097 wf.write(i);
2098 wf.end();
2099 for (const GroupPartInfo* part : m_parts) {
2100 writeFileString(dw_ofile(), "part");
2101 writeFileInt(dw_ofile(), part->partId());
2102 writeFileString(dw_ofile(), "coordinates");
2103 wf.putValue(dw_ofile());
2104 }
2105 } break;
2106 default:
2107 break;
2108 }
2109
2110 dw_ofile.syncFile();
2111 }
2112
2113 //if (m_is_transient && m_is_master)
2114 //writeFileString(dw_ofile(),"END TIME STEP");
2115}
2116
2117/*---------------------------------------------------------------------------*/
2118/*---------------------------------------------------------------------------*/
2122template <typename T>
2125{
2126 ARCANE_UNUSED(ptr);
2127
2128 if (!_isValidVariable(v))
2129 return;
2130
2131 warning() << "Impossible to write array variable "
2132 << v.name() << " of non-constant size; variable saving skipped";
2133}
2134
2135/*---------------------------------------------------------------------------*/
2136/*---------------------------------------------------------------------------*/
2142{
2143 if (!_isValidVariable(v))
2144 return;
2145
2146 String filename;
2147 _buildFileName(v.name(), filename);
2148
2149 debug() << "Saving variable " << v.name() << " in " << filename;
2150
2151 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2152
2153 _writeFileHeader(dw_ofile(), false);
2154 if (m_is_master)
2155 writeFileString(dw_ofile(), v.name());
2156
2157 if (m_is_master) {
2158 switch (v.itemKind()) {
2159 case IK_Cell:
2160 case IK_Face:
2161 m_case_file_variables << "vector per element: ";
2162 break;
2163 case IK_Node:
2164 m_case_file_variables << "vector per node: ";
2165 break;
2166 default:
2167 break;
2168 }
2169
2170 m_case_file_variables << " 1 ";
2171 if (m_fileset_size != 0)
2172 m_case_file_variables << " 1 ";
2173 m_case_file_variables << v.name();
2174
2175 _writeWildcardFilename(m_case_file_variables, v.name());
2176 m_case_file_variables << '\n';
2177 }
2178
2179 switch (v.itemKind()) {
2180 case IK_Cell:
2181 case IK_Face:
2182 case IK_Edge: {
2183 GroupIndexTable* idx = nullptr;
2184
2185 if (v.isPartial()) {
2186 idx = v.itemGroup().localIdToIndex().get();
2187 }
2188
2189 WriteReal3 wf(*this, ptr, idx);
2190 for (const GroupPartInfo* part : m_parts) {
2191 bool need_save = false;
2192 if (v.isPartial())
2193 need_save = v.itemGroup() == part->group();
2194 else
2195 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2196 if (need_save)
2197 _saveVariableOnGroup(dw_ofile(), *part, wf);
2198 }
2199 } break;
2200 case IK_Node: {
2201 if (v.isPartial())
2202 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2203 WriteReal3 wf(*this, ptr);
2204 wf.begin();
2205 for (Integer i = 0; i < ptr.size(); ++i)
2206 wf.write(i);
2207 wf.end();
2208 for (const GroupPartInfo* part : m_parts) {
2209 writeFileString(dw_ofile(), "part");
2210 writeFileInt(dw_ofile(), part->partId());
2211 writeFileString(dw_ofile(), "coordinates");
2212 wf.putValue(dw_ofile());
2213 }
2214 } break;
2215 default:
2216 break;
2217 }
2218
2219 dw_ofile.syncFile();
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/*---------------------------------------------------------------------------*/
2322{
2323 ARCANE_UNUSED(ptr);
2324
2325 if (!_isValidVariable(v))
2326 return;
2327
2328 warning() << "Impossible to write array variable " << v.name()
2329 << " of non-constant size; variable saving skipped";
2330}
2331
2332/*---------------------------------------------------------------------------*/
2333/*---------------------------------------------------------------------------*/
2339{
2340 public:
2341
2344 , m_mesh(sbi.mesh())
2345 , m_writer(nullptr)
2346 {
2347 }
2348
2349 IDataWriter* dataWriter() override { return m_writer; }
2350 void notifyBeginWrite() override;
2351 void notifyEndWrite() override;
2352 void close() override {}
2353
2354 private:
2355
2356 IMesh* m_mesh;
2357 DumpW* m_writer;
2358};
2359
2360/*---------------------------------------------------------------------------*/
2361/*---------------------------------------------------------------------------*/
2362
2365{
2366 bool is_binary = true;
2367 Integer fileset_size = 100;
2368 bool is_parallel = subDomain()->parallelMng()->isParallel();
2369 bool use_degenerated_hexa = true;
2370 bool force_first_geometry = false;
2371 bool save_uids = false;
2372 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2373 variables(), groups(), is_binary, is_parallel,
2376}
2377
2380{
2381 delete m_writer;
2382 m_writer = 0;
2383}
2384
2385/*---------------------------------------------------------------------------*/
2386/*---------------------------------------------------------------------------*/
2387
2388/*---------------------------------------------------------------------------*/
2389/*---------------------------------------------------------------------------*/
2395{
2396 public:
2397
2399
2400 public:
2401
2404 , m_mesh(sbi.mesh())
2405 , m_writer(nullptr)
2406 {
2407 }
2408
2409 void build() override
2410 {
2412 }
2413 IDataWriter* dataWriter() override { return m_writer; }
2414 void notifyBeginWrite() override;
2415 void notifyEndWrite() override;
2416 void close() override {}
2417
2422 const String& baseDirectoryName() override
2423 {
2425 }
2426 void setMesh(IMesh* mesh) override
2427 {
2428 m_mesh = mesh;
2429 }
2442
2443 private:
2444
2445 IMesh* m_mesh;
2446 DumpW* m_writer;
2447};
2448
2449/*---------------------------------------------------------------------------*/
2450/*---------------------------------------------------------------------------*/
2451
2454{
2455 // std::cout << " ############# IMesh = " << mesh() << " " << m_mesh << " ###########\n";
2456
2457 bool is_binary = true;
2458 Integer fileset_size = 0;
2459 bool is_parallel = m_mesh->parallelMng()->isParallel();
2460 is_binary = options()->binaryFile();
2461 fileset_size = options()->filesetSize();
2462 bool use_degenerated_hexa = options()->useDegeneratedHexa();
2463 bool force_first_geometry = options()->forceFirstGeometry();
2464 bool save_uids = options()->saveUids();
2465 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2466 variables(), groups(), is_binary, is_parallel, fileset_size,
2468}
2469
2472{
2473 delete m_writer;
2474 m_writer = nullptr;
2475}
2476
2477/*---------------------------------------------------------------------------*/
2478/*---------------------------------------------------------------------------*/
2479
2482
2483ARCANE_REGISTER_SERVICE_ENSIGHT7POSTPROCESSOR(Ensight7PostProcessor, Ensight7PostProcessorServiceV2);
2484
2485/*---------------------------------------------------------------------------*/
2486/*---------------------------------------------------------------------------*/
2487
2488} // namespace Arcane
2489
2490/*---------------------------------------------------------------------------*/
2491/*---------------------------------------------------------------------------*/
#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.
Generation de la classe de base du Service.
CaseOptionsEnsight7PostProcessor * options() const
Options du jeu de données du service.
Maille d'un maillage.
Definition Item.h:1178
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Definition Item.h:1258
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1255
Int32 nbFace() const
Nombre de faces de la maille.
Definition Item.h:1252
Integer count() const
Nombre d'éléments de la collection.
Definition Collection.h:70
Classe gérant un répertoire.
Definition Directory.h:33
virtual String file(const String &file_name) const
Retourne le chemin complet du fichier file_name dans le répertoire.
Definition Directory.cc:138
virtual bool createDirectory() const
Créé le répertoire.
Definition Directory.cc:120
virtual String path() const
Retourne le chemin du répertoire.
Definition Directory.cc:129
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
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:932
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:49
virtual String name() const =0
Nom de la famille.
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual IItemFamily * itemFamily(eItemKind ik)=0
Retourne la famille d'entité de type ik.
virtual Integer nbNode()=0
Nombre de noeuds du maillage.
virtual NodeGroup allNodes()=0
Groupe de tous les noeuds.
virtual CellGroup allCells()=0
Groupe de toutes les mailles.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual IMesh * parentMesh() const =0
Accès au maillage parent.
virtual SharedVariableNodeReal3 sharedNodesCoordinates()=0
Coordonnées des noeuds.
virtual ItemGroupCollection groups()=0
Liste des groupes.
virtual ItemTypeMng * itemTypeMng() const =0
Gestionnaire de types d'entités associé
virtual IPrimaryMesh * toPrimaryMesh()=0
Retourne l'instance sous la forme d'un IPrimaryMesh.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
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:54
virtual eItemKind itemKind() const =0
Type des entités du maillage sur lequel repose la variable.
virtual bool isPartial() const =0
Indique si la variable est partielle.
virtual bool isUsed() const =0
Etat d'utilisation de la variable.
virtual ItemGroup itemGroup() const =0
Groupe du maillage associé.
virtual String name() const =0
Nom de la variable.
@ PTemporary
Indique que la variable est temporaire.
Definition IVariable.h:126
@ PPrivate
Indique que la variable est privée.
Definition IVariable.h:114
Groupe d'entités de maillage.
Definition ItemGroup.h:49
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
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
IMesh * mesh() const
Maillage auquel appartient ce groupe (0 pour le group nul)
Definition ItemGroup.h:126
Informations locales sur une face d'une maille.
Infos sur un type d'entité du maillage.
Gestionnaire des types d'entités de maillage.
Definition ItemTypeMng.h:66
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:714
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:768
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:765
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:377
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:210
Cell toCell() const
Converti l'entité en le genre Cell.
Definition Item.h:1654
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:216
Int16 type() const
Type de l'entité
Definition Item.h:232
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Flot de sortie lié à une String.
Classe de base d'un écrivain pour les informations de post-traitement.
virtual void build()
Construction de niveau build du service.
virtual RealConstArrayView times()
Liste des temps sauvés.
virtual void setGroups(ItemGroupCollection groups)
Positionne la liste des groupes à sortir.
virtual const String & baseDirectoryName()
Nom du répertoire de sortie des fichiers.
virtual void setVariables(VariableCollection variables)
Positionne la liste des variables à sortir.
virtual ItemGroupCollection groups()
Liste des groupes à sauver.
virtual void setTimes(RealConstArrayView times)
Positionne la liste des temps.
virtual void setBaseDirectoryName(const String &dirname)
Positionne le nom du répertoire de sortie des fichiers. Ce répertoire doit exister.
virtual VariableCollection variables()
Liste des variables à sauver.
Structure contenant les informations pour créer un service.
Paramètres nécessaires à la construction d'une variable.
Collection de variables.
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
Integer size() const
Nombre d'éléments du vecteur.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
Vue constante d'un tableau de type T.
interval d'itérateurs constant
Exception lorsqu'une fonction n'est pas implémentée.
Constructeur de chaîne de caractère unicode.
Chaîne de caractères unicode.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
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).
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.
Definition Convert.h:87
double toDouble(Real r)
Converti un Real en double.
Definition Convert.h:40
-*- 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.
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.
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:644
Int32 Integer
Type représentant un entier.
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.