Arcane  4.2.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#include "arcane/utils/Convert.h"
27
28#include "arcane/core/IDataWriter.h"
29#include "arcane/core/Item.h"
31#include "arcane/core/IVariable.h"
32#include "arcane/core/ISubDomain.h"
33#include "arcane/core/IMesh.h"
34#include "arcane/core/IMeshSubMeshTransition.h"
35#include "arcane/core/StdNum.h"
36#include "arcane/core/ItemGroup.h"
37#include "arcane/core/IParallelMng.h"
38#include "arcane/core/Directory.h"
39#include "arcane/core/MeshVariable.h"
40#include "arcane/core/PostProcessorWriterBase.h"
41#include "arcane/core/Service.h"
42#include "arcane/core/SimpleProperty.h"
43#include "arcane/core/IItemFamily.h"
44#include "arcane/core/VariableCollection.h"
45#include "arcane/core/SharedVariable.h"
46
47#include "arcane/core/FactoryService.h"
49
50#include "arcane/std/Ensight7PostProcessor_axl.h"
51#include "arcane/std/DumpW.h"
52
53#include <string.h>
54#include <memory>
55#include <unordered_map>
56
57// TODO: Ajouter test avec des variables partielles
58
59/*---------------------------------------------------------------------------*/
60/*---------------------------------------------------------------------------*/
61
62namespace Arcane
63{
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
98class DumpWEnsight7
99: public DumpW
100, public TraceAccessor
101{
102 public:
103
104 static const int int_width = 10;
105 static const int g_line_length = 80;
106
107 public:
108
112 struct EnsightPart
113 {
114 public:
115
116 EnsightPart()
117 : m_type(-1)
118 , m_nb_node(0)
119 {}
120 EnsightPart(int type, Integer nb_node, const String& name)
121 : m_type(type)
122 , m_nb_node(nb_node)
123 , m_name(name)
124 {}
125 EnsightPart(const EnsightPart& part)
126 : m_type(part.m_type)
127 , m_nb_node(part.m_nb_node)
128 , m_name(part.m_name)
129 , m_items(part.m_items)
130 , m_reindex(part.m_reindex)
131 {
132 ;
133 }
134
135 public:
136
137 inline int type() const { return m_type; }
138 inline Integer nbNode() const { return m_nb_node; }
139 inline const String& name() const { return m_name; }
140 inline Array<Item>& items() { return m_items; }
141 inline ConstArrayView<Item> items() const { return m_items; }
142 inline bool hasReindex() const { return !m_reindex.empty(); }
143 inline void setReindex(Integer* reindex)
144 {
145 m_reindex.resize(m_nb_node);
146 for (Integer i = 0; i < m_nb_node; ++i)
147 m_reindex[i] = reindex[i];
148 }
149 inline ConstArrayView<Integer> reindex() const { return m_reindex; }
150
151 private:
152
153 int m_type;
157 UniqueArray<Integer> m_reindex;
158 };
159
163 struct GroupPartInfo
164 {
165 public:
166
168 Integer nbType() const { return m_parts.size(); }
169
170 public:
171
173 : m_group(0)
174 , m_part_id(0)
175 {}
176 GroupPartInfo(ItemGroup grp, Integer id, bool use_degenerated_hexa)
177 : m_group(grp)
178 , m_part_id(id)
179 {
180 m_general_item_types = std::make_unique<VariableItemInt32>(VariableBuildInfo{ m_group.mesh(), "GeneralItemTypesGroup" + m_group.name(), m_group.itemFamily()->name() }, m_group.itemKind());
181 _init(use_degenerated_hexa);
182 }
183 Integer totalNbElement() const
184 {
185 Integer n = 0;
186 for (Integer i = 0; i < nbType(); ++i)
187 n += m_parts[i].items().size();
188 return n;
189 }
190 const EnsightPart& typeInfo(Integer i) const { return m_parts[i]; }
191 EnsightPart& typeInfo(Integer i) { return m_parts[i]; }
192 ItemGroup group() const { return m_group; }
193 Integer partId() const { return m_part_id; }
194 Int32 generalItemTypeId(const Item& item) const
195 {
196 ARCANE_ASSERT(m_general_item_types, ("Cannot question an empty GroupPartInfo"));
197 return (*(m_general_item_types))[item];
198 }
199 EnsightPart* getTypeInfo(int type)
200 {
201 auto ensight_part_element = m_parts_map.find(type);
202 if (ensight_part_element != m_parts_map.end())
203 return ensight_part_element->second;
204 else
205 return nullptr;
206 }
207
208 private:
209
213 bool m_is_polygonal_type_registration_done = false;
214 bool m_is_polyhedral_type_registration_done = false;
216 std::unique_ptr<VariableItemInt32> m_general_item_types = nullptr;
217 using TypeId = int;
218 std::unordered_map<TypeId, EnsightPart*> m_parts_map; // utilisé pour gérer un grand nombre de types supplémentaires
219
220 private:
221
222 void _initPartMap()
223 {
224 for (auto& ensight_part : m_parts) {
225 m_parts_map[ensight_part.type()] = &ensight_part;
226 }
227 }
228
229 void _init(bool use_degenerated_hexa)
230 {
231 ItemTypeMng* item_type_mng = m_group.mesh()->itemTypeMng();
232
233 // NOTE: il est important que les éléments de type 'nfaced'
234 // et 'nsided' soient contigues car Ensight doit sauver
235 // ensemble leur valeurs
236 m_parts.reserve(ItemTypeMng::nbBasicItemType());
237 m_parts.add(EnsightPart(IT_Line2, 2, "bar2")); // Bar
238 m_parts.add(EnsightPart(IT_Triangle3, 3, "tria3")); // Triangle
239 m_parts.add(EnsightPart(IT_Quad4, 4, "quad4")); // Quandrangle
240 m_parts.add(EnsightPart(IT_Pentagon5, 5, "nsided")); // Pentagone
241 m_parts.add(EnsightPart(IT_Hexagon6, 6, "nsided")); // Hexagone
242 m_parts.add(EnsightPart(IT_Heptagon7, 7, "nsided")); // Heptagone
243 m_parts.add(EnsightPart(IT_Octogon8, 8, "nsided")); // Octogone
244 // Recherche des autres types 'polygone'
245 for (Integer i_type = ItemTypeMng::nbBuiltInItemType(); i_type < ItemTypeMng::nbBasicItemType(); ++i_type) {
246 ItemTypeInfo* type_info = item_type_mng->typeFromId(i_type);
247 if (type_info->nbLocalNode() == type_info->nbLocalEdge()) { // Polygone trouvé
248 m_parts.add(EnsightPart(i_type, type_info->nbLocalNode(), "nsided"));
249 }
250 }
251 // Ajout des polygones gérés dans le maillage polyédrique général : aucun type défini
252 Int32 type_id = ItemTypeMng::nbBasicItemType();
253 if (item_type_mng->hasGeneralCells(m_group.mesh())) {
254 if (!m_is_polygonal_type_registration_done) {
255 ENUMERATE_ITEM (iitem, m_group) {
256 ItemWithNodes item = iitem->toItemWithNodes();
257 if (item.nbNode() == item.itemBase().nbEdge()) { // polygone trouvé
258 (*(m_general_item_types))[item] = type_id;
259 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nsided"));
260 }
261 }
262 m_is_polygonal_type_registration_done = true;
263 }
264 }
265 m_parts.add(EnsightPart(IT_Tetraedron4, 4, "tetra4")); // Tetra
266 m_parts.add(EnsightPart(IT_Pyramid5, 5, "pyramid5")); // Pyramide
267 m_parts.add(EnsightPart(IT_Pentaedron6, 6, "penta6")); // Penta
268 m_parts.add(EnsightPart(IT_Hexaedron8, 8, "hexa8")); // Hexa
269 if (use_degenerated_hexa) {
270 m_parts.add(EnsightPart(IT_HemiHexa7, 8, "hexa8")); // HemiHexa7
271 {
272 Integer reindex[8] = { 1, 6, 5, 0, 2, 3, 4, 0 };
273 m_parts[m_parts.size() - 1].setReindex(reindex);
274 }
275 m_parts.add(EnsightPart(IT_HemiHexa6, 8, "hexa8")); // HemiHexa6
276 {
277 Integer reindex[8] = { 0, 1, 3, 5, 0, 2, 3, 4 };
278 m_parts[m_parts.size() - 1].setReindex(reindex);
279 }
280 m_parts.add(EnsightPart(IT_HemiHexa5, 8, "hexa8")); // HemiHexa5
281 {
282 Integer reindex[8] = { 0, 1, 3, 4, 0, 2, 3, 4 };
283 m_parts[m_parts.size() - 1].setReindex(reindex);
284 }
285 m_parts.add(EnsightPart(IT_AntiWedgeLeft6, 8, "hexa8")); // AntiWedgeLeft6
286 {
287 Integer reindex[8] = { 2, 0, 1, 2, 5, 3, 4, 4 };
288 m_parts[m_parts.size() - 1].setReindex(reindex);
289 }
290 m_parts.add(EnsightPart(IT_AntiWedgeRight6, 8, "hexa8")); // AntiWedgeRight6
291 {
292 Integer reindex[8] = { 2, 0, 1, 1, 5, 3, 4, 5 };
293 m_parts[m_parts.size() - 1].setReindex(reindex);
294 }
295 m_parts.add(EnsightPart(IT_DiTetra5, 8, "hexa8")); // DiTetra5
296 {
297 Integer reindex[8] = { 4, 4, 2, 3, 0, 1, 1, 3 };
298 m_parts[m_parts.size() - 1].setReindex(reindex);
299 }
300 }
301 else {
302 m_parts.add(EnsightPart(IT_HemiHexa7, 7, "nfaced")); // HemiHexa7
303 m_parts.add(EnsightPart(IT_HemiHexa6, 6, "nfaced")); // HemiHexa6
304 m_parts.add(EnsightPart(IT_HemiHexa5, 5, "nfaced")); // HemiHexa5
305 m_parts.add(EnsightPart(IT_AntiWedgeLeft6, 6, "nfaced")); // AntiWedgeLeft6
306 m_parts.add(EnsightPart(IT_AntiWedgeRight6, 6, "nfaced")); // AntiWedgeRight6
307 m_parts.add(EnsightPart(IT_DiTetra5, 5, "nfaced")); // DiTetra5
308 }
309 m_parts.add(EnsightPart(IT_Heptaedron10, 10, "nfaced")); // Wedge7
310 m_parts.add(EnsightPart(IT_Octaedron12, 12, "nfaced")); // Wedge8
311 m_parts.add(EnsightPart(IT_Enneedron14, 14, "nfaced")); // Wedge9
312 m_parts.add(EnsightPart(IT_Decaedron16, 16, "nfaced")); // Wedge10
313 // Recherche des autres types 'polyedre'
314 for (Integer i_type = ItemTypeMng::nbBuiltInItemType(); i_type < ItemTypeMng::nbBasicItemType(); ++i_type) {
315 ItemTypeInfo* type_info = item_type_mng->typeFromId(i_type);
316 if (type_info->nbLocalNode() != type_info->nbLocalEdge()) { // Polyèdre trouvé
317 m_parts.add(EnsightPart(i_type, type_info->nbLocalNode(), "nfaced"));
318 }
319 }
320 // Ajout des polyèdres gérés dans le maillage polyédrique général : aucun type défini
321 if (item_type_mng->hasGeneralCells(m_group.mesh())) {
322 if (!m_is_polyhedral_type_registration_done) {
323 ENUMERATE_ITEM (iitem, m_group) {
324 ItemWithNodes item = iitem->toItemWithNodes();
325 if (item.nbNode() == 1)
326 (*(m_general_item_types))[item] = IT_Vertex;
327 else if (item.nbNode() == 2)
328 (*(m_general_item_types))[item] = IT_Line2;
329 else if (item.typeInfo()->isPolyhedron()) { // polyèdre trouvé
330 (*(m_general_item_types))[item] = type_id;
331 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nfaced"));
332 }
333 else if (item.nbNode() != item.itemBase().nbEdge()) { // polyèdre trouvé
334 (*(m_general_item_types))[item] = type_id;
335 m_parts.add(EnsightPart(type_id++, item.nbNode(), "nfaced"));
336 }
337 }
338 m_is_polyhedral_type_registration_done = true;
339 }
340 }
341 // Si des types supplémentaires sont utilisés, initialiser une carte EnsightPart pour optimiser le remplissage de GroupPartInfo
343 _initPartMap();
344 }
345 }
346 };
347
348 public:
349
350 //void writeFileString(ostream& o,ConstCString str);
351 void writeFileString(std::ostream& o, const String& str);
352 void writeFileInt(std::ostream& o, int value);
353 void writeFileDouble(std::ostream& o, double value);
354 Integer writeDoubleSize() const;
355 Integer writeIntSize() const;
356 void writeFileArray(std::ostream& o, IntegerConstArrayView value);
357 bool isBinary() const { return m_is_binary; }
358
359 public:
360
373 class WriteBase
374 {
375 public:
376
377 explicit WriteBase(DumpWEnsight7& dw)
378 : m_dw(dw)
379 {}
380 WriteBase(DumpWEnsight7& dw, GroupIndexTable* idx)
381 : m_dw(dw)
382 , m_idx(idx)
383 {}
384 WriteBase(const WriteBase& wb)
385 : m_dw(wb.m_dw)
386 , m_idx(wb.m_idx)
387 {}
388 virtual ~WriteBase() {}
389
390 public:
391
392 virtual WriteBase* clone() = 0;
393 virtual void begin() { init(); }
394 virtual void end() {}
395 virtual void write(ConstArrayView<Item> items) = 0;
396
397 virtual void init()
398 {
399 m_ofile.precision(5);
400 m_ofile.flags(std::ios::scientific);
401 }
402 virtual void putValue(std::ostream& ofile)
403 {
404 ofile << m_ofile.str();
405 }
406 std::ostream& stream() { return m_ofile; }
407
408 protected:
409
410 DumpWEnsight7& m_dw;
411 std::ostringstream m_ofile;
412 GroupIndexTable* m_idx = nullptr;
413 };
414
418 template <typename FromType>
419 class WriteDouble
420 : public WriteBase
421 {
422 public:
423
424 WriteDouble(DumpWEnsight7& dw, ConstArrayView<FromType> ptr, GroupIndexTable* idx = nullptr)
425 : WriteBase(dw, idx)
426 , m_ptr(ptr)
427 {}
428 WriteDouble(const WriteDouble& wd)
429 : WriteBase(wd)
430 , m_ptr(wd.m_ptr)
431 {}
432
433 WriteBase* clone() override { return new WriteDouble(*this); }
434
435 public:
436
438
439 public:
440
441 inline void write(Integer index)
442 {
443 if (m_idx) {
444 int reindex = (*m_idx)[index];
445 if (reindex < 0)
446 ARCANE_FATAL("Invalid index");
447 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[reindex])));
448 }
449 else
450 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[index])));
451 }
452
453 void write(ConstArrayView<Item> items) override
454 {
455 for (Item e : items) {
456 write(e.localId());
457 }
458 }
459 };
460
464 template <typename FromType>
465 class WriteArrayDouble
466 : public WriteBase
467 {
468 public:
469
470 WriteArrayDouble(DumpWEnsight7& dw, ConstArray2View<FromType> ptr, const Integer idim2,
471 GroupIndexTable* idx = nullptr)
472 : WriteBase(dw, idx)
473 , m_ptr(ptr)
474 , m_idim2(idim2)
475 {}
476 WriteArrayDouble(const WriteArrayDouble& wd)
477 : WriteBase(wd)
478 , m_ptr(wd.m_ptr)
479 , m_idim2(wd.m_idim2)
480 {}
481
482 WriteBase* clone() override { return new WriteArrayDouble(*this); }
483
484 public:
485
487 const Integer m_idim2;
488
489 public:
490
491 void write(Integer index)
492 {
493 if (m_idx) {
494 int reindex = (*m_idx)[index];
495 if (reindex < 0)
496 ARCANE_FATAL("Invalid index");
497 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[reindex][m_idim2])));
498 }
499 else
500 m_dw.writeFileDouble(m_ofile, Convert::toDouble(Convert::toReal(m_ptr[index][m_idim2])));
501 }
502
503 void write(ConstArrayView<Item> items) override
504 {
505 for (Item e : items) {
506 write(e.localId());
507 }
508 }
509 };
510
514
518 class WriteReal3
519 : public WriteBase
520 {
521 public:
522
523 WriteReal3(DumpWEnsight7& dw, ConstArrayView<Real3> ptr, GroupIndexTable* idx = nullptr)
524 : WriteBase(dw, idx)
525 , m_ptr(ptr)
526 {}
527 WriteReal3(const WriteReal3& wd)
528 : WriteBase(wd)
529 , m_ptr(wd.m_ptr)
530 {}
531
532 WriteBase* clone() override { return new WriteReal3(*this); }
533
534 public:
535
537
538 public:
539
540 void begin() override
541 {
542 _init();
543 xostr.precision(5);
544 xostr.flags(std::ios::scientific);
545 yostr.precision(5);
546 yostr.flags(std::ios::scientific);
547 zostr.precision(5);
548 zostr.flags(std::ios::scientific);
549 }
550
551 void write(Integer index)
552 {
553 if (m_idx) {
554 int reindex = (*m_idx)[index];
555 if (reindex < 0)
556 ARCANE_FATAL("Invalid index");
557 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[reindex].x));
558 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[reindex].y));
559 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[reindex].z));
560 }
561 else {
562 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[index].x));
563 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[index].y));
564 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[index].z));
565 }
566 }
567
568 void write(ConstArrayView<Item> items) override
569 {
570 for (Item i : items) {
571 write(i.localId());
572 }
573 }
574
575 void end() override
576 {
577 m_ofile << xostr.str();
578 m_ofile << yostr.str();
579 m_ofile << zostr.str();
580 }
581
582 public:
583
584 std::ostringstream xostr;
585 std::ostringstream yostr;
586 std::ostringstream zostr;
587
588 private:
589
590 void _init()
591 {
592 init();
593 }
594 };
595
599 class WriteArrayReal3
600 : public WriteBase
601 {
602 public:
603
604 WriteArrayReal3(DumpWEnsight7& dw, ConstArray2View<Real3> ptr,
605 Integer idim2, GroupIndexTable* idx = nullptr)
606 : WriteBase(dw, idx)
607 , m_ptr(ptr)
608 , m_idim2(idim2)
609 {}
610 WriteArrayReal3(const WriteArrayReal3& wd)
611 : WriteBase(wd)
612 , m_ptr(wd.m_ptr)
613 , m_idim2(wd.m_idim2)
614 {}
615
616 WriteBase* clone() override { return new WriteArrayReal3(*this); }
617
618 public:
619
621 const Integer m_idim2;
622 public:
623
624 void begin() override
625 {
626 _init();
627 xostr.precision(5);
628 xostr.flags(std::ios::scientific);
629 yostr.precision(5);
630 yostr.flags(std::ios::scientific);
631 zostr.precision(5);
632 zostr.flags(std::ios::scientific);
633 }
634
635 inline void write(Integer index)
636 {
637 if (m_idx) {
638 int reindex = (*m_idx)[index];
639 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[reindex][m_idim2].x));
640 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[reindex][m_idim2].y));
641 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[reindex][m_idim2].z));
642 }
643 else {
644 m_dw.writeFileDouble(xostr, Convert::toDouble(m_ptr[index][m_idim2].x));
645 m_dw.writeFileDouble(yostr, Convert::toDouble(m_ptr[index][m_idim2].y));
646 m_dw.writeFileDouble(zostr, Convert::toDouble(m_ptr[index][m_idim2].z));
647 }
648 }
649
650 void write(ConstArrayView<Item> items) override
651 {
652 for (Item i : items) {
653 write(i.localId());
654 }
655 }
656
657 void end() override
658 {
659 m_ofile << xostr.str();
660 m_ofile << yostr.str();
661 m_ofile << zostr.str();
662 }
663
664 public:
665
666 std::ostringstream xostr;
667 std::ostringstream yostr;
668 std::ostringstream zostr;
669
670 private:
671
672 void _init()
673 {
674 init();
675 }
676 };
677
678 public:
679
680 DumpWEnsight7(IMesh* m, const String& filename, RealConstArrayView times,
681 VariableCollection variables, ItemGroupCollection groups,
682 bool is_binary, bool is_parallel, Integer fileset_size,
683 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids);
684 ~DumpWEnsight7();
685
686 public:
687
689 void writeVal(IVariable& v, ConstArrayView<Real> a) override { _writeRealValT<Real>(v, a); }
690 void writeVal(IVariable&, ConstArrayView<Real2>) override {}
691 void writeVal(IVariable&, ConstArrayView<Real3>) override;
692 void writeVal(IVariable& v, ConstArrayView<Int16> a) override { _writeRealValT<Int16>(v, a); }
693 void writeVal(IVariable& v, ConstArrayView<Int32> a) override { _writeRealValT<Int32>(v, a); }
694 void writeVal(IVariable& v, ConstArrayView<Int64> a) override { _writeRealValT<Int64>(v, a); }
695 void writeVal(IVariable&, ConstArrayView<Real2x2>) override {}
696 void writeVal(IVariable&, ConstArrayView<Real3x3>) override {}
697 void writeVal(IVariable&, ConstArrayView<String>) override {}
698
699 void writeVal(IVariable&, ConstArray2View<Byte>) override {}
700 void writeVal(IVariable& v, ConstArray2View<Real> a) override { _writeRealValT<Real>(v, a); }
701 void writeVal(IVariable&, ConstArray2View<Real2>) override {}
702 void writeVal(IVariable&, ConstArray2View<Real3>) override;
703 void writeVal(IVariable& v, ConstArray2View<Int16> a) override { _writeRealValT<Int16>(v, a); }
704 void writeVal(IVariable& v, ConstArray2View<Int32> a) override { _writeRealValT<Int32>(v, a); }
705 void writeVal(IVariable& v, ConstArray2View<Int64> a) override { _writeRealValT<Int64>(v, a); }
706 void writeVal(IVariable&, ConstArray2View<Real2x2>) override {}
707 void writeVal(IVariable&, ConstArray2View<Real3x3>) override {}
708
709 void writeVal(IVariable&, ConstMultiArray2View<Byte>) override {}
710 void writeVal(IVariable& v, ConstMultiArray2View<Real> a) override { _writeRealValT<Real>(v, a); }
711 void writeVal(IVariable&, ConstMultiArray2View<Real2>) override {}
712 void writeVal(IVariable&, ConstMultiArray2View<Real3> a) override;
713 void writeVal(IVariable& v, ConstMultiArray2View<Int16> a) override { _writeRealValT<Int16>(v, a); }
714 void writeVal(IVariable& v, ConstMultiArray2View<Int32> a) override { _writeRealValT<Int32>(v, a); }
715 void writeVal(IVariable& v, ConstMultiArray2View<Int64> a) override { _writeRealValT<Int64>(v, a); }
716 void writeVal(IVariable&, ConstMultiArray2View<Real2x2>) override {}
717 void writeVal(IVariable&, ConstMultiArray2View<Real3x3>) override {}
718
719 void beginWrite() override;
720 void endWrite() override;
721 void setMetaData(const String&) override {};
722
723 bool isParallelOutput() const { return m_is_parallel_output; }
724 bool isMasterProcessor() const { return m_is_master; }
725 bool isOneFilePerTime() const { return m_fileset_size == 0; }
726 Int32 rank() const { return m_parallel_mng->commRank(); }
727 IParallelMng* parallelMng() const { return m_parallel_mng; }
728
729 public:
730 private:
731
732 typedef UniqueArray<GroupPartInfo*> GroupPartInfoList;
733
734 private:
735
740 std::ofstream m_case_file;
741 std::ostringstream m_case_file_variables;
743 VariableList m_save_variables;
745 GroupPartInfoList m_parts;
751 bool m_use_degenerated_hexa;
752 bool m_force_first_geometry;
753 bool m_save_uids;
761 Integer m_fileset_size;
762
763 private:
764 private:
765
767 static const Integer m_max_prots_digit = 6;
768
769 private:
770 private:
771
772 bool _isValidVariable(IVariable&) const;
773 void _createCaseFile();
774 void _buildFileName(const String& varname, String& filename);
775 void _buildPartDirectory();
776 void _writeWildcardFilename(std::ostream& ofile, const String& filename, char joker = '*');
777 int _fileOuttype() const;
778 void _writeFileHeader(std::ostream& o, bool write_c_binary);
779 bool _isNewBlocFile() const;
780
781 void _computeGroupParts(ItemGroupList list_group, Integer& partid);
782 void _saveGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
783 ConstArrayView<Integer> nodes_index, WriteBase& wf);
784 void _saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
785 WriteBase& from_func);
786 bool _isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind);
787
789 template <typename T>
792 template <typename T>
795 template <typename T>
797};
798
799/*---------------------------------------------------------------------------*/
800/*---------------------------------------------------------------------------*/
801
802extern "C++" DumpW*
803createEnsight7(ISubDomain* m, const String& f,
805 VariableCollection variables,
806 ItemGroupCollection groups,
807 bool is_binary, bool is_parallel_output, Integer fileset_size,
808 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
809{
810 return new DumpWEnsight7(m->defaultMesh(), f, times, variables, groups, is_binary,
811 is_parallel_output, fileset_size, use_degenerated_hexa,
812 force_first_geometry, save_uids);
813}
814
815extern "C++" DumpW*
816createEnsight7(IMesh* m, const String& f,
817 ConstArrayView<Real> times,
818 VariableCollection variables,
819 ItemGroupCollection groups,
820 bool is_binary, bool is_parallel_output, Integer fileset_size,
821 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
822{
823 return new DumpWEnsight7(m, f, times, variables, groups, is_binary,
824 is_parallel_output, fileset_size, use_degenerated_hexa,
825 force_first_geometry, save_uids);
826}
827
828/*---------------------------------------------------------------------------*/
829/*---------------------------------------------------------------------------*/
830
831DumpWEnsight7::
832DumpWEnsight7(IMesh* mesh, const String& filename, ConstArrayView<Real> times,
833 VariableCollection variables, ItemGroupCollection groups,
834 bool is_binary, bool is_parallel_output, Integer fileset_size,
835 bool use_degenerated_hexa, bool force_first_geometry, bool save_uids)
836: TraceAccessor(mesh->traceMng())
837, m_mesh(mesh)
838, m_parallel_mng(mesh->parallelMng())
839, m_base_directory(filename)
840, m_times(times)
841, m_save_variables(variables.clone())
842, m_save_groups(groups.enumerator())
843, m_is_binary(is_binary)
844// , m_is_binary(false)
845, m_is_master(true)
846, m_is_parallel_output(is_parallel_output)
847, m_use_degenerated_hexa(use_degenerated_hexa)
848, m_force_first_geometry(force_first_geometry)
849, m_save_uids(save_uids)
850, m_total_nb_element(0)
851, m_total_nb_group(0)
852, m_fileset_size(fileset_size)
853{
854 //m_is_binary = true;
855 //m_fileset_size = 0;
856
857 if (m_times.empty()) {
858 m_times.resize(1);
859 m_times[0] = 0.;
860 }
861
862 //_createCaseFile();
863}
864
865/*---------------------------------------------------------------------------*/
866/*---------------------------------------------------------------------------*/
867
868DumpWEnsight7::
869~DumpWEnsight7()
870{
871 std::for_each(std::begin(m_parts), std::end(m_parts), Deleter());
872}
873
874/*---------------------------------------------------------------------------*/
875/*---------------------------------------------------------------------------*/
876
877/*---------------------------------------------------------------------------*/
878/*---------------------------------------------------------------------------*/
879
898void DumpWEnsight7::
899_computeGroupParts(ItemGroupList list_group, Integer& partid)
900{
901 for (ItemGroupList::Enumerator i(list_group); ++i;) {
902 ItemGroup grp(*i);
903 if (grp.null()) // Le groupe n'est pas du type souhaité.
904 continue;
905 if (!grp.isOwn()) // Si possible, prend le groupe d'éléments propres
906 grp = grp.own();
907 // Depuis la 7.6 de Ensight, les groupes vides sont autorisés
908 // et ils sont nécessaires lorsque le maillage évolue au cours du temps
909 //if (grp.empty()) // Le groupe est vide
910 //continue;
911 GroupPartInfo* gpi = new GroupPartInfo(grp, partid, m_use_degenerated_hexa);
912 m_parts.add(gpi);
913 ++partid;
914
915 GroupPartInfo& current_grp = *gpi;
916 // Maintenant, nous devons déterminer combien d'éléments de chaque type
917 // ensight (tria3, hexa8, ...) se trouvent dans le groupe.
918 // deux versions : si des types d'éléments supplémentaires sont ajoutés, passer à une version optimisée
919 // (une grande quantité de types peut être ajoutée, égale au nombre d'éléments)
920 if (ItemTypeMng::nbBuiltInItemType() == ItemTypeMng::nbBasicItemType()) // pas de type supplémentaire
921 {
922 debug(Trace::High) << "Utilisation de l'algorithme standard de construction de groupe de parties";
923 if (!grp.mesh()->itemTypeMng()->hasGeneralCells(grp.mesh())) { // types classiques
924 for (Integer z = 0; z < current_grp.nbType(); ++z) {
925 EnsightPart& type_info = current_grp.typeInfo(z);
926 Array<Item>& items = type_info.items();
927 Integer nb_of_type = 0;
928 Integer type_to_seek = type_info.type();
929 ENUMERATE_ITEM (i2, grp) {
930 const Item& e = *i2;
931 if (e.type() == type_to_seek)
932 ++nb_of_type;
933 }
934 items.resize(nb_of_type);
935 debug(Trace::High) << "Le groupe " << grp.name() << " contient "
936 << nb_of_type << " éléments de type " << type_info.name();
937 Integer index = 0;
938 ENUMERATE_ITEM (iz, grp) {
939 Item mi = *iz;
940 if (mi.type() == type_to_seek) {
942 items[index] = e;
943 ++index;
944 }
945 }
946 }
947 }
948 else { // éléments de maillage polyédrique
949 ENUMERATE_ITEM (i2, grp) {
950 const Item& item = *i2;
951 auto item_type = current_grp.generalItemTypeId(item);
952 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
953 if (!ensight_part)
954 continue;
955 ItemWithNodes item_wn = item.toItemWithNodes();
956 ensight_part->items().add(item_wn);
957 }
958 }
959 }
960 else // des types supplémentaires sont ajoutés (peuvent avoir autant de types que d'éléments...)
961 // Proposer une version optimisée lorsque de nombreux types existent (utilisation de fichier .format)
962 {
963 debug(Trace::High) << "Utilisation de l'algorithme de construction de groupe de parties avec types supplémentaires";
964 // travaille uniquement sur les groupes de faces et de mailles
965 auto item_kind = grp.itemKind();
966 if (item_kind == IK_Cell || item_kind == IK_Face) {
967 ENUMERATE_ITEM (item, grp) {
968 auto item_type = item->type();
969 EnsightPart* ensight_part = current_grp.getTypeInfo(item_type);
970 if (!ensight_part)
971 continue;
972 ItemWithNodes item_wn = item->toItemWithNodes();
973 ensight_part->items().add(item_wn); // quelques éléments sont ajoutés
974 }
975 }
976 }
977 }
978}
979
980/*---------------------------------------------------------------------------*/
981/*---------------------------------------------------------------------------*/
1003void DumpWEnsight7::
1004_saveGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
1005 ConstArrayView<Integer> nodes_index, WriteBase& wf)
1006{
1007 ItemGroup igrp = ensight_grp.group();
1008
1009 writeFileString(ofile, "part");
1010 writeFileInt(ofile, ensight_grp.partId());
1011 if (isParallelOutput()) {
1012 // Dans le cas d'une sortie parallele, prefixe le nom du groupe par le
1013 // numéro du CPU.
1014 std::ostringstream ostr;
1015 ostr << igrp.name().localstr() << "_CPU" << rank();
1016 writeFileString(ofile, ostr.str().c_str());
1017 }
1018 else
1019 writeFileString(ofile, igrp.name());
1020
1021 wf.putValue(ofile);
1022
1023 IntegerUniqueArray array_id(256);
1024
1025 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1026 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1027 ConstArrayView<Item> items = type_info.items();
1028 Integer nb_sub_part = items.size();
1029 if (nb_sub_part == 0)
1030 continue;
1031
1032 String type_name = type_info.name();
1033 writeFileString(ofile, type_name);
1034
1035 writeFileInt(ofile, nb_sub_part);
1036
1037#if 0
1038 // Sauve les uniqueId() des entités
1039 for( ConstArrayView<Item>::const_iter i(items); i(); ++i ){
1040 Item mi = *i;
1041 writeFileInt(ofile,mi.uniqueId()+1);
1042 }
1043#endif
1044
1045 if (type_name == "nfaced") {
1046 // Traitement particulier pour les mailles non standards
1047 // Comme nos faces ne sont pas orientées par rapport à une
1048 // maille, on utilise la connectivité locale de chaque face.
1049 // 1. Sauve le nombre de faces de chaque élément
1050 {
1051 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1052 // Tous les éléments ont le même nombre de faces
1053 Item mi = *items.data();
1054 Cell cell = mi.toCell();
1055 Integer nb_face = cell.nbFace();
1056 for (Integer z = 0; z < nb_sub_part; ++z)
1057 writeFileInt(ofile, nb_face);
1058 }
1059 else { // le maillage a des éléments généraux
1060 // Tous les éléments n'ont pas le même nombre de faces
1061 for (Item mi : items) {
1062 writeFileInt(ofile, mi.toCell().nbFace());
1063 }
1064 }
1065 }
1066 // 2. Sauve pour chaque elément, le nombre de noeuds de chacune
1067 // de ces faces
1068 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1069 for (Item mi : items) {
1070 const ItemTypeInfo* item_info = mi.typeInfo();
1071 Integer nb_face = item_info->nbLocalFace();
1072 for (Integer z = 0; z < nb_face; ++z)
1073 writeFileInt(ofile, item_info->localFace(z).nbNode());
1074 }
1075 }
1076 else { // le maillage a des éléments généraux
1077 for (Item mi : items) {
1078 Cell cell = mi.toCell();
1079 for (Face face : cell.faces()) {
1080 writeFileInt(ofile, face.nbNode());
1081 }
1082 }
1083 }
1084 // 3. Sauve pour chaque face de chaque élément la liste de ces
1085 // noeuds
1086 if (!m_mesh->itemTypeMng()->hasGeneralCells(m_mesh)) {
1087 for (Item item : items) {
1088 Cell cell(item.toCell());
1089 const ItemTypeInfo* item_info = cell.typeInfo();
1090 //Cell cell = mi.toCell();
1091 Integer nb_face = item_info->nbLocalFace();
1092 for (Integer z = 0; z < nb_face; ++z) {
1093 const ItemTypeInfo::LocalFace& local_face = item_info->localFace(z);
1094 Integer nb_node = local_face.nbNode();
1095 array_id.resize(nb_node);
1096 for (Integer y = 0; y < nb_node; ++y) {
1097 // Inversion du sens des noeuds
1098 // A priori, il y a un bug dans Ensight (7.4.1(g)) concernant les
1099 // intersections de ce type d'éléments avec les objets
1100 // Ensight (plan, sphere, ...). Quelle que soit l'orientation
1101 // des faces retenues, le comportant n'est pas correcte.
1102 array_id[y] = nodes_index[cell.node(local_face.node(y)).localId()];
1103 }
1104 writeFileArray(ofile, array_id);
1105 }
1106 }
1107 }
1108 else { // le maillage a des éléments généraux
1109 for (Item item : items) {
1110 Cell cell = item.toCell();
1111 Integer nb_face = cell.nbFace();
1112 for (Integer z = 0; z < nb_face; ++z) {
1113 const Face local_face = cell.face(z);
1114 Integer nb_node = local_face.nbNode();
1115 array_id.resize(nb_node);
1116 for (Integer y = 0; y < nb_node; ++y) {
1117 array_id[y] = nodes_index[local_face.node(y).localId()];
1118 }
1119 writeFileArray(ofile, array_id);
1120 }
1121 }
1122 }
1123 }
1124 else if (type_name == "nsided") {
1125 // Traitement particulier pour les faces à plus de 4 noeuds:
1126
1127 // 1. Sauve pour chaque elément, le nombre de ses noeuds
1128 //cerr << "** NSIDED ELEMENT\n";
1129 for (Item mi : items) {
1131 Integer nb_node = e.nbNode();
1132 writeFileInt(ofile, nb_node);
1133 }
1134 // 2. Sauve pour chaque elément la liste de ces noeuds
1135 for (Item mi : items) {
1137 Integer nb_node = e.nbNode();
1138 array_id.resize(nb_node);
1139 for (Integer z = 0; z < nb_node; ++z) {
1140 array_id[z] = nodes_index[e.node(z).localId()];
1141 }
1142 writeFileArray(ofile, array_id);
1143 }
1144 }
1145 else {
1146 // Cas général
1147
1148 Integer nb_node = type_info.nbNode();
1149 array_id.resize(nb_node);
1150
1151 // Sauvegarde les éléments.
1152
1153 // Sauve la connectivité des éléments
1154 if (type_info.hasReindex()) {
1155 ConstArrayView<Integer> reindex = type_info.reindex();
1156 for (Item mi : items) {
1158 for (Integer j = 0; j < nb_node; ++j) {
1159 array_id[j] = nodes_index[e.node(reindex[j]).localId()];
1160 }
1161 writeFileArray(ofile, array_id);
1162 }
1163 }
1164 else { // pas de reindex
1165 for (Item mi : items) {
1167 for (Integer j = 0; j < nb_node; ++j) {
1168 array_id[j] = nodes_index[e.node(j).localId()];
1169 }
1170 writeFileArray(ofile, array_id);
1171 }
1172 }
1173 }
1174 }
1175}
1176
1177/*---------------------------------------------------------------------------*/
1178/*---------------------------------------------------------------------------*/
1204void DumpWEnsight7::
1205_saveVariableOnGroup(std::ostream& ofile, const GroupPartInfo& ensight_grp,
1206 WriteBase& from_func)
1207{
1208 ItemGroup igrp = ensight_grp.group();
1209
1210 writeFileString(ofile, "part");
1211 writeFileInt(ofile, ensight_grp.partId());
1212
1213 // Les éléments de même types (en particulier les 'nfaced', 'haxa8' ou 'nsided')
1214 // doivent être écrits d'un seul bloc (donc label de type unifié).
1215 // Par ailleurs, les données vectorielles doivent être entrelacés.
1216 String last_type_name;
1218 for (Integer i = 0; i < ensight_grp.nbType(); ++i) {
1219 const EnsightPart& type_info = ensight_grp.typeInfo(i);
1220 ConstArrayView<Item> items(type_info.items());
1221 Integer nb_sub_part = items.size();
1222 if (nb_sub_part == 0)
1223 continue;
1224 String type_name = type_info.name();
1225 if (type_name != last_type_name) {
1226 // Cloture la précédente écriture
1227 if (func.get()) {
1228 func->end();
1229 func->putValue(ofile);
1230 }
1231 last_type_name = type_name;
1232 writeFileString(ofile, type_name);
1233 func = from_func.clone();
1234 func->begin();
1235 }
1236
1237 // Sauvegarde les variables.
1238 func->write(items);
1239 }
1240
1241 // Cloture finale
1242 if (func.get()) {
1243 func->end();
1244 func->putValue(ofile);
1245 }
1246}
1247
1248/*---------------------------------------------------------------------------*/
1249/*---------------------------------------------------------------------------*/
1250
1251void DumpWEnsight7::
1252writeFileInt(std::ostream& o, int value)
1253{
1254 if (m_is_binary) {
1255 o.write((const char*)&value, sizeof(int));
1256 }
1257 else {
1258 o.width(DumpWEnsight7::int_width);
1259 o << value;
1260 o << '\n';
1261 }
1262}
1263
1264/*---------------------------------------------------------------------------*/
1265/*---------------------------------------------------------------------------*/
1266
1267Integer DumpWEnsight7::
1268writeIntSize() const
1269{
1270 if (m_is_binary)
1271 return sizeof(int);
1272 return DumpWEnsight7::int_width + 1;
1273}
1274
1275/*---------------------------------------------------------------------------*/
1276/*---------------------------------------------------------------------------*/
1277
1278void DumpWEnsight7::
1279writeFileDouble(std::ostream& o, double value)
1280{
1281 if (m_is_binary) {
1282 float fvalue = (float)(value);
1283 o.write((const char*)&fvalue, sizeof(float));
1284 }
1285 else {
1286 o.width(12);
1287 o.precision(5);
1288 o.flags(std::ios::scientific);
1289 o << value;
1290 o << '\n';
1291 }
1292}
1293
1294/*---------------------------------------------------------------------------*/
1295/*---------------------------------------------------------------------------*/
1296
1297Integer DumpWEnsight7::
1298writeDoubleSize() const
1299{
1300 Integer float_size = (Integer)(sizeof(float));
1301 return (m_is_binary) ? float_size : (12 + 1);
1302}
1303
1304/*---------------------------------------------------------------------------*/
1305/*---------------------------------------------------------------------------*/
1306
1307void DumpWEnsight7::
1308writeFileArray(std::ostream& o, IntegerConstArrayView value)
1309{
1310 if (m_is_binary) {
1311 o.write((const char*)value.data(), sizeof(Integer) * value.size());
1312 }
1313 else {
1314 for (Integer i = 0, s = value.size(); i < s; ++i) {
1315 o.width(DumpWEnsight7::int_width);
1316 o << value[i];
1317 }
1318 o << '\n';
1319 }
1320}
1321
1322/*---------------------------------------------------------------------------*/
1323/*---------------------------------------------------------------------------*/
1324
1325void DumpWEnsight7::
1326writeFileString(std::ostream& o, const String& str)
1327{
1328 if (m_is_binary) {
1329 char buf[g_line_length];
1330 for (int i = 0; i < g_line_length; ++i)
1331 buf[i] = '\0';
1332 CStringUtils::copyn(buf, str.localstr(), g_line_length);
1333 buf[g_line_length - 1] = '\0';
1334 o.write(buf, g_line_length);
1335 }
1336 else {
1337 o << str << '\n';
1338 }
1339}
1340
1341/*---------------------------------------------------------------------------*/
1342/*---------------------------------------------------------------------------*/
1343
1344void DumpWEnsight7::
1345_writeFileHeader(std::ostream& o, bool write_c_binary)
1346{
1347 if (m_is_master) {
1348 if (_isNewBlocFile() && m_is_binary && write_c_binary)
1349 writeFileString(o, "C Binary");
1350 if (m_fileset_size != 0) {
1351 std::ostringstream ostr;
1352 ostr << "BEGIN TIME STEP "
1353 << "# " << m_times.size();
1354 writeFileString(o, ostr.str().c_str());
1355 }
1356 }
1357}
1358
1359/*---------------------------------------------------------------------------*/
1360/*---------------------------------------------------------------------------*/
1368class DumpWEnsight7OutFile
1369{
1370 public:
1371
1372 DumpWEnsight7OutFile(DumpWEnsight7& dw, const String& filename, int outtype)
1373 : m_dw(dw)
1374 , m_filename(filename)
1375 , m_is_master(dw.isMasterProcessor())
1376 , m_is_parallel_output(dw.isParallelOutput())
1377 , m_stream(0)
1378 , m_filestream(0)
1379 {
1380 if (m_is_master) {
1381 m_filestream = new std::ofstream(filename.localstr(), (std::ios_base::openmode)outtype);
1382 m_stream = &m_strstream;
1383 if (!(*m_filestream))
1384 m_dw.warning() << "Unable to open file " << filename;
1385 }
1386 else {
1387 // TODO attention fuites mémoires.
1388 m_stream = &m_strstream;
1389 }
1390 ARCANE_CHECK_PTR(m_stream);
1391 }
1392 ~DumpWEnsight7OutFile()
1393 {
1394 delete m_filestream;
1395 }
1396
1397 public:
1398
1399 void syncFile()
1400 {
1401 IParallelMng* parallel_mng = m_dw.parallelMng();
1402 if (m_is_master) {
1403 ARCANE_CHECK_PTR(m_filestream);
1404 ARCANE_CHECK_PTR(m_strstream);
1405 //Integer pos = m_strstream->tellp();
1406 (*m_filestream) << m_strstream.str();
1407 }
1408 if (m_is_parallel_output) {
1409 if (m_is_master) {
1410 ARCANE_CHECK_PTR(m_filestream);
1411
1412 // Le maitre parcours tous les processeurs et demande pour chacun
1413 // d'eux la taille de chaque sauvegarde et si elle n'est pas nulle,
1414 // réceptionne le message.
1415 Integer nb_proc = parallel_mng->commSize();
1416 UniqueArray<int> len_array(1);
1417 UniqueArray<Byte> str_array;
1418 for (Integer i = 1; i < nb_proc; ++i) {
1419 m_dw.debug(Trace::High) << "En attente de la longueur du processeur " << i;
1420 parallel_mng->recv(len_array, i);
1421 Integer len = len_array[0];
1422 m_dw.debug(Trace::High) << "Longueur du processeur " << i << " : " << len;
1423 if (len != 0) {
1424 str_array.resize(len);
1425 m_dw.debug(Trace::High) << "En attente de la réception de la géométrie du processeur " << i;
1426 parallel_mng->recv(str_array, i);
1427 m_dw.debug(Trace::High) << "Réception de la géométrie du processeur " << i;
1428 m_filestream->write((const char*)str_array.data(), str_array.size());
1429 }
1430 }
1431 }
1432 else {
1433 ARCANE_CHECK_PTR(m_strstream);
1434 // Un esclave envoie au processeur maître (actuellement le processeur 0)
1435 // la taille de ses données puis ces données.
1436 // Il faut bien prendre la longueur de la chaîne retournée par m_strstream
1437 // et pas uniquement c_str() car le flux pouvant contenant des informations
1438 // au format binaire, on s'arrêterait au premier zéro.
1439 UniqueArray<int> len_array(1);
1440 std::string str = m_strstream.str();
1441 Integer len = arcaneCheckArraySize(str.length());
1442 UniqueArray<Byte> bytes(len);
1443 {
1444 // Recopie dans bytes la chaîne \a str
1445 Integer index = 0;
1446 for (ConstIterT<std::string> i(str); i(); ++i, ++index)
1447 bytes[index] = *i;
1448 }
1449 m_dw.debug(Trace::High) << "Pas un maître. Taille de " << m_filename << " = " << len;
1450 //Integer len = m_strstream->tellp();
1451 //Integer len = str.length();
1452 len_array[0] = len;
1453 m_dw.debug(Trace::High) << "Envoi de la longueur pour le processeur 0";
1454 parallel_mng->send(len_array, 0);
1455 if (len != 0) {
1456 //UniqueArray<char> str_array(len);
1457 //std::string s = m_strstream->str();
1458 //platform::stdMemcpy(str_array.begin(),s.c_str(),s.length());
1459 m_dw.debug(Trace::High) << "Envoi des données pour le processeur 0";
1460 parallel_mng->send(bytes, 0); //str.c_str())__array,0);
1461 //parallel_mng->send(str_array,0);
1462 }
1463 }
1464 }
1465 if (m_is_master)
1466 if (!m_dw.isOneFilePerTime())
1467 m_dw.writeFileString(*m_filestream, "END TIME STEP");
1468 }
1469
1470 public:
1471
1472 std::ostream& operator()() { return *m_stream; }
1473
1474 private:
1475
1476 DumpWEnsight7& m_dw;
1477 String m_filename;
1478 bool m_is_master;
1479 bool m_is_parallel_output;
1480 std::ostream* m_stream;
1481 std::ostringstream m_strstream;
1482 std::ofstream* m_filestream;
1483};
1484
1485/*---------------------------------------------------------------------------*/
1486/*---------------------------------------------------------------------------*/
1487
1488/*---------------------------------------------------------------------------*/
1489/*---------------------------------------------------------------------------*/
1490
1492beginWrite()
1493{
1494 String buf = m_base_directory.file("ensight.case");
1495
1496 IParallelMng* parallel_mng = m_parallel_mng;
1497 bool is_parallel = parallel_mng->isParallel();
1498 m_is_master = true;
1499 if (is_parallel && m_is_parallel_output)
1500 m_is_master = parallel_mng->commRank() == 0;
1501
1502 // Détermine et créé le répertoire ou seront écrites les sorties
1503 // de cette itération.
1505
1506 IMesh* mesh = m_mesh;
1507
1508 // Récupère la liste des groupes et leur donne à chacun un identifiant
1509 // unique pour Ensight (part). Le numéro de l'identifiant débute à 2, le numéro 1
1510 // est pour la liste des noeuds
1511 {
1512
1513 ItemGroupList list_group;
1514 // Si la liste des groupes à sauver est vide, sauve tous les groupes.
1515 // Sinon, sauve uniquement les groupes spécifiés.
1516 Integer nb_group = m_save_groups.count();
1517 if (nb_group == 0)
1518 list_group.clone(mesh->groups());
1519 else
1520 list_group.clone(m_save_groups);
1521 // Regarde la liste des variables partielles, et ajoute leur groupe à la liste
1522 // des groupes à sauver.
1523 for (VariableList::Enumerator ivar(m_save_variables); ++ivar;) {
1524 IVariable* var = *ivar;
1525 if (!var->isPartial())
1526 continue;
1527 ItemGroup var_group = var->itemGroup();
1528 if (!list_group.contains(var_group))
1529 list_group.add(var_group);
1530 }
1531 Integer partid = 1;
1533 partid += parallel_mng->commRank() * list_group.count();
1534
1535 _computeGroupParts(list_group, partid);
1536
1537 // Récupère le nombre total d'eléments dans les groupes.
1538 Integer total_nb_element = 0;
1539 m_total_nb_group = 0;
1540 for (auto i : m_parts) {
1541 total_nb_element += i->totalNbElement();
1543 }
1544
1545 m_total_nb_element = total_nb_element;
1546 debug() << "Nombre total d'éléments " << m_total_nb_element << " et de groupes " << m_total_nb_group;
1547 debug() << "Ajout de nœuds " << mesh->nbNode();
1548 }
1549
1550 // Sauvegarde la géométrie au format Ensight7 gold
1551 if (!(m_times.size() > 1 && m_force_first_geometry)) {
1552 String filename;
1553 _buildFileName("ensight.geo", filename);
1554
1555 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1556
1557 _writeFileHeader(dw_ofile(), true);
1558
1559 if (m_is_master) {
1560 writeFileString(dw_ofile(), "Output ensight test");
1561 writeFileString(dw_ofile(), "File description");
1562 writeFileString(dw_ofile(), "node id assign");
1563 writeFileString(dw_ofile(), "element id assign");
1564 }
1565
1566 IMesh* mesh = m_mesh;
1567 NodeGroup all_nodes = mesh->allNodes();
1568
1569 // Ce tableau sert pour chaque entité maille, face ou arête pour
1570 // référencer ses noeuds par rapport au tableau de coordonnées
1571 // utilisé par Ensight. Le premier élément de ce tableau à pour indice 1
1572 UniqueArray<Integer> all_nodes_index(mesh->itemFamily(IK_Node)->maxLocalId());
1573 all_nodes_index.fill(0);
1574
1575 UniqueArray<Real3> coords_backup;
1576 ConstArrayView<Real3> coords_array;
1577 if (mesh->parentMesh()) {
1578 SharedVariableNodeReal3 nodes_coords(mesh->sharedNodesCoordinates());
1579 coords_backup.resize(mesh->nodeFamily()->maxLocalId());
1580 ENUMERATE_NODE (i_item, all_nodes) {
1581 coords_backup[i_item.localId()] = nodes_coords[i_item];
1582 }
1583 coords_array = coords_backup.view();
1584 }
1585 else {
1586 VariableNodeReal3& nodes_coords(mesh->toPrimaryMesh()->nodesCoordinates());
1587 coords_array = ConstArrayView<Real3>(nodes_coords.asArray());
1588 }
1589
1590 WriteReal3 wf(*this, coords_array);
1591 {
1592 wf.init();
1593 writeFileString(wf.stream(), "coordinates");
1594 writeFileInt(wf.stream(), all_nodes.size());
1595 wf.begin();
1596
1597 // Stocke les indices locaux pour Ensight
1598 {
1599 Integer ensight_index = 1;
1600 ENUMERATE_ITEM (i_item, all_nodes) {
1601 const Item& item = *i_item;
1602 all_nodes_index[item.localId()] = ensight_index;
1603 ++ensight_index;
1604 }
1605 }
1606
1607 // Affiche les numéros unique des noeuds
1608#if 0
1609 {
1610 ENUMERATE_ITEM(i_item,all_nodes){
1611 const Item& item = *i_item;
1612 writeFileInt(wf.stream(),item.uniqueId()+1);
1613 }
1614 }
1615#endif
1616 // Affiche les coordonnées de chaque noeud
1617 ENUMERATE_ITEM (i_item, all_nodes) {
1618 const Item& item = *i_item;
1619 wf.write(item.localId());
1620 }
1621 wf.end();
1622 }
1623
1624 for (const GroupPartInfo* part : m_parts)
1625 _saveGroup(dw_ofile(), *part, all_nodes_index, wf);
1626
1627 dw_ofile.syncFile();
1628 }
1629}
1630
1631/*---------------------------------------------------------------------------*/
1632/*---------------------------------------------------------------------------*/
1633
1635endWrite()
1636{
1637 // Sauvegarde des identifiants uniques
1638 if (m_save_uids) {
1640 ENUMERATE_CELL (icell, m_mesh->allCells()) {
1641 cell_uids[icell] = (Real)(icell->uniqueId().asInt64());
1642 }
1643 IVariable* cell_uid_var = cell_uids.variable();
1644 m_save_variables.add(cell_uid_var);
1645 cell_uid_var->setUsed(true);
1646 cell_uid_var->notifyBeginWrite();
1647 write(cell_uid_var, cell_uid_var->data());
1648
1649 // GG: NOTE: je ne suis pas sur que cela fonctionne bien.
1650 //TODO: supprimer l'utilisation de deux variables
1652 UniqueArray<Real> node_uids2(m_mesh->nodeFamily()->allItems().size());
1653 ENUMERATE_NODE (inode, m_mesh->allNodes()) {
1654 node_uids[inode] = inode->uniqueId().asInt32();
1655 node_uids2[inode.index()] = (Real)inode->uniqueId().asInt64();
1656 }
1657
1658 IVariable* node_uid_var = node_uids.variable();
1659 m_save_variables.add(node_uid_var);
1660 node_uid_var->setUsed(true);
1661 _writeRealValT<Real>(*node_uid_var, node_uids2); // contournement de bug pour les variables de nœuds
1662 }
1663
1664 String buf = m_base_directory.file("ensight.case");
1665
1666 // Seul un processeur maître génère un fichier 'case'
1667 if (m_is_master) {
1668
1669 m_case_file.open(buf.localstr());
1670
1671 if (!m_case_file)
1672 warning() << "Unable to write to file: <" << buf << "> error: " << m_case_file.rdstate();
1673
1674 debug() << "** Exportation des données vers " << m_base_directory.path();
1675 m_case_file << "FORMAT\ntype: ensight gold\n";
1676
1677 m_case_file << "\nGEOMETRY\n";
1678 m_case_file << "model: 1";
1679 if (m_fileset_size != 0)
1680 m_case_file << " 1 ";
1681 if (m_force_first_geometry)
1682 _writeWildcardFilename(m_case_file, "ensight.geo", '0');
1683 else
1684 _writeWildcardFilename(m_case_file, "ensight.geo", '*');
1685 //m_case_file << " [change_coords_only]\n";
1686 m_case_file << "\n";
1687
1688 m_case_file << "\nVARIABLE\n";
1689 m_case_file << m_case_file_variables.str();
1690
1691 // Sauvegarde en temps. Pour paraview, il faut le mettre apres les variables
1692 m_case_file << "\nTIME\n";
1693 m_case_file << "time set: 1\n";
1694 m_case_file << "number of steps: " << m_times.size() << '\n';
1695 m_case_file << "filename start number: 0\n";
1696 m_case_file << "filename increment: 1\n";
1697 m_case_file << "time values:\n";
1698 // Faire attention de ne pas dépasser les 79 caractères par ligne
1699 // autorisés par Ensight. Pour être sur, on n'écrit qu'un temps pas
1700 // ligne. Les temps sont sauvés le maximum de chiffres significatifs
1701 // car Ensight n'aime pas que deux temps soient égaux.
1702 std::streamsize old_precision = m_case_file.precision(FloatInfo<Real>::maxDigit());
1703 for (Integer i = 0, is = m_times.size(); i < is; ++i)
1704 m_case_file << m_times[i] << '\n';
1705 m_case_file << '\n';
1706 m_case_file.precision(old_precision);
1707
1708 if (m_fileset_size != 0) {
1709 m_case_file << "FILE\n";
1710 m_case_file << "file set: 1\n";
1711 if (m_fileset_size != 0) {
1712 Integer nb_timeset = (m_times.size() / m_fileset_size);
1713 for (Integer i = 0; i < nb_timeset; ++i) {
1714 m_case_file << "filename index: " << i << "\n";
1715 m_case_file << "number of steps: " << m_fileset_size << '\n';
1716 }
1717 if (nb_timeset > 0)
1718 m_case_file << "filename index: " << nb_timeset << "\n";
1719 m_case_file << "number of steps: " << m_times.size() - (nb_timeset * m_fileset_size) << '\n';
1720 }
1721 else {
1722 m_case_file << "number of steps: " << m_times.size() << '\n';
1723 }
1724 m_case_file << '\n';
1725 }
1726 }
1727 m_case_file.flush();
1728 m_case_file.close();
1729}
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/*---------------------------------------------------------------------------*/
1768
1782_buildFileName(const String& name, String& filename)
1783{
1784 StringBuilder fn_builder;
1785 if (m_fileset_size == 0) {
1786 Integer current_time = m_times.size() - 1;
1787 fn_builder = m_base_directory.path();
1788 fn_builder += "/";
1789 fn_builder += name;
1790 if (m_is_master) {
1791 Directory dir(fn_builder.toString());
1792 dir.createDirectory();
1793 }
1794 fn_builder += "/";
1795 fn_builder += name;
1796
1797 {
1798 OStringStream ostr;
1799 ostr().fill('0'); // Caractère de remplissage.
1800 ostr().width(m_max_prots_digit);
1801 ostr() << current_time;
1802 fn_builder += ostr.str();
1803 }
1804
1805 //fn_builder += current_time;
1806
1807 //info() << " BUILD FILE NAME name=" << name << " filename=" << fn_builder;
1808 }
1809 else {
1810 fn_builder = m_part_directory.path();
1811 fn_builder += "/";
1812 fn_builder += name;
1813 }
1814 filename = fn_builder;
1815}
1816
1817/*---------------------------------------------------------------------------*/
1818/*---------------------------------------------------------------------------*/
1819
1820bool DumpWEnsight7::
1821_isSameKindOfGroup(const ItemGroup& group, eItemKind item_kind)
1822{
1823 eItemKind group_kind = group.itemKind();
1824 if (item_kind == IK_Unknown)
1825 return false;
1826 return group_kind == item_kind;
1827}
1828
1829/*---------------------------------------------------------------------------*/
1830/*---------------------------------------------------------------------------*/
1843{
1844 Integer prot_index = 0;
1845 bool has_prot = false;
1846 if (m_fileset_size != 0) {
1847 Integer nb_time = m_times.size();
1848 if (nb_time != 0)
1849 prot_index = (nb_time - 1) / m_fileset_size;
1850 has_prot = true;
1851 }
1852
1853 if (m_is_master)
1854 m_base_directory.createDirectory();
1855
1856 if (has_prot) {
1857 OStringStream ostr;
1858 ostr() << "bloc";
1859 ostr().fill('0'); // Caractère de remplissage.
1860 ostr().width(m_max_prots_digit);
1861 ostr() << prot_index;
1862 //ostr() << '\0';
1863 String buf = ostr.str();
1865 if (m_is_master)
1866 m_part_directory.createDirectory();
1867 }
1868 else
1870}
1871
1872/*---------------------------------------------------------------------------*/
1873/*---------------------------------------------------------------------------*/
1874
1875void DumpWEnsight7::
1876_writeWildcardFilename(std::ostream& ofile, const String& filename, char joker)
1877{
1878 if (m_fileset_size == 0) {
1879 ofile << ' ' << filename << '/' << filename;
1880 for (Integer i = 0; i < m_max_prots_digit; ++i)
1881 ofile << joker;
1882 }
1883 else {
1884 ofile << " bloc";
1885 Integer nb_time = m_times.size();
1886 // Si le nombre de temps est inférieur à la taille d'un fileset-set,
1887 // il n'y a pas besoin de mettre une '*'. On peut directement
1888 // mettre des zéros. Cela est aussi indispensable pour empêcher
1889 // paraview de planter quand il relit ce genre de fichiers.
1890 if (nb_time <= m_fileset_size)
1891 joker = '0';
1892 for (Integer i = 0; i < m_max_prots_digit; ++i)
1893 ofile << joker;
1894 ofile << "/" << filename;
1895 }
1896}
1897
1898/*---------------------------------------------------------------------------*/
1899/*---------------------------------------------------------------------------*/
1900
1901bool DumpWEnsight7::
1902_isNewBlocFile() const
1903{
1904 Integer nb_time = m_times.size();
1905
1906 if (nb_time == 1)
1907 return true;
1908 if (m_fileset_size == 0)
1909 return true;
1910
1911 Integer modulo = (nb_time - 1) % m_fileset_size;
1912
1913 if (modulo == 0)
1914 return true;
1915 return false;
1916}
1917
1918/*---------------------------------------------------------------------------*/
1919/*---------------------------------------------------------------------------*/
1920
1921int DumpWEnsight7::
1922_fileOuttype() const
1923{
1924 return ((isBinary()) ? std::ios::binary : 0) | ((_isNewBlocFile()) ? std::ios::trunc : std::ios::app);
1925}
1926
1927/*---------------------------------------------------------------------------*/
1928/*---------------------------------------------------------------------------*/
1929
1933template <typename T>
1936{
1937 debug() << "Saving variable1 " << v.name() << " ptr=" << ptr.data() << " ps=" << ptr.size();
1938
1939 if (!_isValidVariable(v))
1940 return;
1941
1942 String filename;
1943 _buildFileName(v.name(), filename);
1944
1945 debug() << "Saving variable " << v.name() << " in " << filename;
1946
1947 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
1948
1949 _writeFileHeader(dw_ofile(), false);
1950
1951 if (m_is_master)
1952 writeFileString(dw_ofile(), v.name());
1953 String var_type_str;
1954
1955 if (m_is_master) {
1956 switch (v.itemKind()) {
1957 case IK_Cell:
1958 case IK_Face:
1959 var_type_str = "scalar per element: ";
1960 break;
1961 case IK_Node:
1962 var_type_str = "scalar per node: ";
1963 break;
1964 default:
1965 break;
1966 }
1967
1968 m_case_file_variables << var_type_str;
1969 m_case_file_variables << " 1 ";
1970 if (m_fileset_size != 0)
1971 m_case_file_variables << " 1 ";
1972 m_case_file_variables << v.name();
1973 _writeWildcardFilename(m_case_file_variables, v.name());
1974 m_case_file_variables << '\n';
1975 }
1976
1977 switch (v.itemKind()) {
1978 case IK_Cell:
1979 case IK_Face:
1980 case IK_Edge: {
1981 GroupIndexTable* idx = nullptr;
1982
1983 if (v.isPartial()) {
1984 idx = v.itemGroup().localIdToIndex().get();
1985 }
1986
1987 WriteDouble<T> wf(*this, ptr, idx);
1988 for (const GroupPartInfo* part : m_parts) {
1989 bool need_save = false;
1990 if (v.isPartial())
1991 need_save = v.itemGroup() == part->group();
1992 else
1993 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
1994 if (need_save)
1995 _saveVariableOnGroup(dw_ofile(), *part, wf);
1996 }
1997 } break;
1998 case IK_Node: {
1999 if (v.isPartial())
2000 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2001 WriteDouble<T> wf(*this, ptr);
2002 wf.begin();
2003 for (Integer i = 0; i < ptr.size(); ++i)
2004 wf.write(i);
2005 wf.end();
2006 for (const GroupPartInfo* part : m_parts) {
2007 writeFileString(dw_ofile(), "part");
2008 writeFileInt(dw_ofile(), part->partId());
2009 writeFileString(dw_ofile(), "coordinates");
2010 wf.putValue(dw_ofile());
2011 }
2012 } break;
2013 default:
2014 break;
2015 }
2016
2017 dw_ofile.syncFile();
2018
2019 //if (m_is_transient && m_is_master)
2020 //writeFileString(dw_ofile(),"END TIME STEP");
2021}
2022
2023/*---------------------------------------------------------------------------*/
2024/*---------------------------------------------------------------------------*/
2025
2029template <typename T>
2032{
2033 if (!_isValidVariable(v))
2034 return;
2035
2036 for (Integer idim2 = 0; idim2 < ptr.dim2Size(); ++idim2) {
2037 String vname = v.name() + String("_") + idim2;
2038 String filename;
2039 _buildFileName(vname, filename);
2040
2041 debug() << "Saving variable " << v.name() << " component " << idim2 << " in " << filename;
2042
2043 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2044
2045 _writeFileHeader(dw_ofile(), false);
2046
2047 if (m_is_master)
2048 writeFileString(dw_ofile(), vname);
2049 String var_type_str;
2050
2051 if (m_is_master) {
2052 switch (v.itemKind()) {
2053 case IK_Cell:
2054 case IK_Face:
2055 var_type_str = "scalar per element: ";
2056 break;
2057 case IK_Node:
2058 var_type_str = "scalar per node: ";
2059 break;
2060 default:
2061 break;
2062 }
2063
2064 m_case_file_variables << var_type_str;
2065 m_case_file_variables << " 1 ";
2066 if (m_fileset_size != 0)
2067 m_case_file_variables << " 1 ";
2068 m_case_file_variables << vname;
2069 _writeWildcardFilename(m_case_file_variables, vname);
2070 m_case_file_variables << '\n';
2071 }
2072
2073 switch (v.itemKind()) {
2074 case IK_Cell:
2075 case IK_Face:
2076 case IK_Edge: {
2077 GroupIndexTable* idx = nullptr;
2078
2079 if (v.isPartial()) {
2080 idx = v.itemGroup().localIdToIndex().get();
2081 }
2082
2083 WriteArrayDouble<T> wf(*this, ptr, idim2, idx);
2084 for (const GroupPartInfo* part : m_parts) {
2085 bool need_save = false;
2086 if (v.isPartial())
2087 need_save = v.itemGroup() == part->group();
2088 else
2089 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2090 if (need_save)
2091 _saveVariableOnGroup(dw_ofile(), *part, wf);
2092 }
2093 } break;
2094 case IK_Node: {
2095 if (v.isPartial())
2096 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2097 WriteArrayDouble<T> wf(*this, ptr, idim2);
2098 wf.begin();
2099 for (Integer i = 0; i < ptr.dim1Size(); ++i)
2100 wf.write(i);
2101 wf.end();
2102 for (const GroupPartInfo* part : m_parts) {
2103 writeFileString(dw_ofile(), "part");
2104 writeFileInt(dw_ofile(), part->partId());
2105 writeFileString(dw_ofile(), "coordinates");
2106 wf.putValue(dw_ofile());
2107 }
2108 } break;
2109 default:
2110 break;
2111 }
2112
2113 dw_ofile.syncFile();
2114 }
2115
2116 //if (m_is_transient && m_is_master)
2117 //writeFileString(dw_ofile(),"END TIME STEP");
2118}
2119
2120/*---------------------------------------------------------------------------*/
2121/*---------------------------------------------------------------------------*/
2122
2126template <typename T>
2129{
2130 ARCANE_UNUSED(ptr);
2131
2132 if (!_isValidVariable(v))
2133 return;
2134
2135 warning() << "Impossible to write array variable "
2136 << v.name() << " of non-constant size; variable saving skipped";
2137}
2138
2139/*---------------------------------------------------------------------------*/
2140/*---------------------------------------------------------------------------*/
2141
2147{
2148 if (!_isValidVariable(v))
2149 return;
2150
2151 String filename;
2152 _buildFileName(v.name(), filename);
2153
2154 debug() << "Saving variable " << v.name() << " in " << filename;
2155
2156 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2157
2158 _writeFileHeader(dw_ofile(), false);
2159 if (m_is_master)
2160 writeFileString(dw_ofile(), v.name());
2161
2162 if (m_is_master) {
2163 switch (v.itemKind()) {
2164 case IK_Cell:
2165 case IK_Face:
2166 m_case_file_variables << "vector per element: ";
2167 break;
2168 case IK_Node:
2169 m_case_file_variables << "vector per node: ";
2170 break;
2171 default:
2172 break;
2173 }
2174
2175 m_case_file_variables << " 1 ";
2176 if (m_fileset_size != 0)
2177 m_case_file_variables << " 1 ";
2178 m_case_file_variables << v.name();
2179
2180 _writeWildcardFilename(m_case_file_variables, v.name());
2181 m_case_file_variables << '\n';
2182 }
2183
2184 switch (v.itemKind()) {
2185 case IK_Cell:
2186 case IK_Face:
2187 case IK_Edge: {
2188 GroupIndexTable* idx = nullptr;
2189
2190 if (v.isPartial()) {
2191 idx = v.itemGroup().localIdToIndex().get();
2192 }
2193
2194 WriteReal3 wf(*this, ptr, idx);
2195 for (const GroupPartInfo* part : m_parts) {
2196 bool need_save = false;
2197 if (v.isPartial())
2198 need_save = v.itemGroup() == part->group();
2199 else
2200 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2201 if (need_save)
2202 _saveVariableOnGroup(dw_ofile(), *part, wf);
2203 }
2204 } break;
2205 case IK_Node: {
2206 if (v.isPartial())
2207 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2208 WriteReal3 wf(*this, ptr);
2209 wf.begin();
2210 for (Integer i = 0; i < ptr.size(); ++i)
2211 wf.write(i);
2212 wf.end();
2213 for (const GroupPartInfo* part : m_parts) {
2214 writeFileString(dw_ofile(), "part");
2215 writeFileInt(dw_ofile(), part->partId());
2216 writeFileString(dw_ofile(), "coordinates");
2217 wf.putValue(dw_ofile());
2218 }
2219 } break;
2220 default:
2221 break;
2222 }
2223
2224 dw_ofile.syncFile();
2225}
2226
2227/*---------------------------------------------------------------------------*/
2228/*---------------------------------------------------------------------------*/
2229
2235{
2236 if (!_isValidVariable(v))
2237 return;
2238
2239 for (Integer idim2 = 0; idim2 < ptr.dim2Size(); ++idim2) {
2240 String vname = v.name() + String("_") + idim2;
2241 String filename;
2242 _buildFileName(vname, filename);
2243
2244 debug() << "Saving variable " << v.name() << " component " << idim2 << " in " << filename;
2245
2246 DumpWEnsight7OutFile dw_ofile(*this, filename, _fileOuttype());
2247
2248 _writeFileHeader(dw_ofile(), false);
2249 if (m_is_master)
2250 writeFileString(dw_ofile(), vname);
2251
2252 if (m_is_master) {
2253 switch (v.itemKind()) {
2254 case IK_Cell:
2255 case IK_Face:
2256 m_case_file_variables << "vector per element: ";
2257 break;
2258 case IK_Node:
2259 m_case_file_variables << "vector per node: ";
2260 break;
2261 default:
2262 break;
2263 }
2264
2265 m_case_file_variables << " 1 ";
2266 if (m_fileset_size != 0)
2267 m_case_file_variables << " 1 ";
2268 m_case_file_variables << vname;
2269
2270 _writeWildcardFilename(m_case_file_variables, vname);
2271 m_case_file_variables << '\n';
2272 }
2273
2274 switch (v.itemKind()) {
2275 case IK_Cell:
2276 case IK_Face:
2277 case IK_Edge: {
2278 GroupIndexTable* idx = nullptr;
2279
2280 if (v.isPartial()) {
2281 idx = v.itemGroup().localIdToIndex().get();
2282 }
2283
2284 WriteArrayReal3 wf(*this, ptr, idim2, idx);
2285 for (const GroupPartInfo* part : m_parts) {
2286 bool need_save = false;
2287 if (v.isPartial())
2288 need_save = v.itemGroup() == part->group();
2289 else
2290 need_save = _isSameKindOfGroup(part->group(), v.itemKind());
2291 if (need_save)
2292 _saveVariableOnGroup(dw_ofile(), *part, wf);
2293 }
2294 } break;
2295 case IK_Node: {
2296 if (v.isPartial())
2297 throw NotImplementedException("DumpWEnsight7::writeVal()", "partial node variable");
2298 WriteArrayReal3 wf(*this, ptr, idim2);
2299 wf.begin();
2300 for (Integer i = 0; i < ptr.dim1Size(); ++i)
2301 wf.write(i);
2302 wf.end();
2303 for (const GroupPartInfo* part : m_parts) {
2304 writeFileString(dw_ofile(), "part");
2305 writeFileInt(dw_ofile(), part->partId());
2306 writeFileString(dw_ofile(), "coordinates");
2307 wf.putValue(dw_ofile());
2308 }
2309 } break;
2310 default:
2311 break;
2312 }
2313
2314 dw_ofile.syncFile();
2315 }
2316
2317 //if (m_is_transient && m_is_master)
2318 //writeFileString(dw_ofile(),"END TIME STEP");
2319}
2320
2321/*---------------------------------------------------------------------------*/
2322/*---------------------------------------------------------------------------*/
2323
2329{
2330 ARCANE_UNUSED(ptr);
2331
2332 if (!_isValidVariable(v))
2333 return;
2334
2335 warning() << "Impossible to write array variable " << v.name()
2336 << " of non-constant size; variable saving skipped";
2337}
2338
2339/*---------------------------------------------------------------------------*/
2340/*---------------------------------------------------------------------------*/
2341
2345class Ensight7PostProcessorService
2346: public PostProcessorWriterBase
2347{
2348 public:
2349
2350 Ensight7PostProcessorService(const ServiceBuildInfo& sbi)
2351 : PostProcessorWriterBase(sbi)
2352 , m_mesh(sbi.mesh())
2353 , m_writer(nullptr)
2354 {
2355 }
2356
2357 IDataWriter* dataWriter() override { return m_writer; }
2358 void notifyBeginWrite() override;
2359 void notifyEndWrite() override;
2360 void close() override {}
2361
2362 private:
2363
2364 IMesh* m_mesh;
2365 DumpW* m_writer;
2366};
2367
2368/*---------------------------------------------------------------------------*/
2369/*---------------------------------------------------------------------------*/
2370
2373{
2374 bool is_binary = true;
2375 Integer fileset_size = 100;
2376 bool is_parallel = subDomain()->parallelMng()->isParallel();
2377 bool use_degenerated_hexa = true;
2378 bool force_first_geometry = false;
2379 bool save_uids = false;
2380 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2381 variables(), groups(), is_binary, is_parallel,
2382 fileset_size, use_degenerated_hexa,
2383 force_first_geometry, save_uids);
2384}
2385
2388{
2389 delete m_writer;
2390 m_writer = 0;
2391}
2392
2393/*---------------------------------------------------------------------------*/
2394/*---------------------------------------------------------------------------*/
2395
2396/*---------------------------------------------------------------------------*/
2397/*---------------------------------------------------------------------------*/
2398
2402class Ensight7PostProcessorServiceV2
2404{
2405 public:
2406
2407 typedef ArcaneEnsight7PostProcessorObject BaseType;
2408
2409 public:
2410
2411 explicit Ensight7PostProcessorServiceV2(const ServiceBuildInfo& sbi)
2413 , m_mesh(sbi.mesh())
2414 , m_writer(nullptr)
2415 {
2416 }
2417
2418 IDataWriter* dataWriter() override { return m_writer; }
2419 void notifyBeginWrite() override;
2420 void notifyEndWrite() override;
2421 void close() override {}
2422
2423 void setMesh(IMesh* mesh) override
2424 {
2425 // TODO: A supprimer car méthode obsolète et n'est pas utilisé.
2426 m_mesh = mesh;
2427 }
2428
2429 private:
2430
2431 IMesh* m_mesh = nullptr;
2432 DumpW* m_writer = nullptr;
2433};
2434
2435/*---------------------------------------------------------------------------*/
2436/*---------------------------------------------------------------------------*/
2437
2440{
2441 // std::cout << " ############# IMesh = " << mesh() << " " << m_mesh << " ###########\n";
2442
2443 bool is_binary = true;
2444 Integer fileset_size = 0;
2445 bool is_parallel = m_mesh->parallelMng()->isParallel();
2446 is_binary = options()->binaryFile();
2447 fileset_size = options()->filesetSize();
2448 bool use_degenerated_hexa = options()->useDegeneratedHexa();
2449 bool force_first_geometry = options()->forceFirstGeometry();
2450 bool save_uids = options()->saveUids();
2451 m_writer = createEnsight7(m_mesh, baseDirectoryName(), times(),
2452 variables(), groups(), is_binary, is_parallel, fileset_size,
2453 use_degenerated_hexa, force_first_geometry, save_uids);
2454}
2455
2458{
2459 delete m_writer;
2460 m_writer = nullptr;
2461}
2462
2463/*---------------------------------------------------------------------------*/
2464/*---------------------------------------------------------------------------*/
2465
2467 Ensight7PostProcessor);
2468
2469ARCANE_REGISTER_SERVICE_ENSIGHT7POSTPROCESSOR(Ensight7PostProcessor, Ensight7PostProcessorServiceV2);
2470
2471/*---------------------------------------------------------------------------*/
2472/*---------------------------------------------------------------------------*/
2473
2474} // namespace Arcane
2475
2476/*---------------------------------------------------------------------------*/
2477/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour itérer sur les entités du maillage.
#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.
Ce fichier contient les différentes fabriques de services et macro pour enregistrer les services.
#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.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
ConstIterT< ConstArrayView< T > > const_iter
Type d'un itérateur constant sur tout le tableau.
interval d'itérateurs constant
Vue constante sur un MultiArray2.
Classe gérant un répertoire.
bool createDirectory() const override
Créé le répertoire.
Definition Directory.cc:102
Abstraction d'un fichier de sortie pour ensight.
Functeur 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 pour écrire une variable comme variable réelle.
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 notifyBeginWrite() override
Notifie qu'une sortie va être effectuée avec les paramètres courants.
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.
IDataWriter * dataWriter() override
Retourne l'écrivain associé à ce post-processeur.
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 à virgule flottante.
Definition FloatInfo.h:35
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:77
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:116
@ PPrivate
Indique que la variable est privée.
Definition IVariable.h:104
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:64
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.
ItemGroupCollection groups() override
Liste des groupes à sauver.
VariableCollection variables() override
Liste des variables à sauver.
ConstArrayView< Real > times() override
Liste des temps sauvés.
const String & baseDirectoryName() override
Nom du répertoire de sortie des fichiers.
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)
Convertit r en Real.
double toDouble(Real r)
Convertit 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:347
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:345
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:484
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:486
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.