MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
datacollection.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "fem.hpp"
13#include "../mesh/nurbs.hpp"
14#include "../mesh/vtk.hpp"
15#include "../mesh/vtkhdf.hpp"
17#include "../general/text.hpp"
18#include "picojson.h"
19
20#include <cerrno> // errno
21#include <sstream>
22#include <regex>
23
24#ifndef _WIN32
25#include <sys/stat.h> // mkdir
26#else
27#include <direct.h> // _mkdir
28#define mkdir(dir, mode) _mkdir(dir)
29#endif
30
31namespace mfem
32{
33
34// static method
35int DataCollection::create_directory(const std::string &dir_name,
36 const Mesh *mesh, int myid)
37{
38 // create directories recursively
39 const char path_delim = '/';
40 std::string::size_type pos = 0;
41 int err_flag = 0;
42#ifdef MFEM_USE_MPI
43 const ParMesh *pmesh = dynamic_cast<const ParMesh*>(mesh);
44 // In addition to the global root, let the lowest rank on each shared-memory
45 // node create the directory too, so that node-local (non-shared) filesystems
46 // get it on every node rather than only where the global root lives. On a
47 // shared filesystem the extra mkdir() hits EEXIST and is tolerated below.
48 bool node_root = true;
49 if (pmesh)
50 {
51 MPI_Comm node_comm;
52 MPI_Comm_split_type(pmesh->GetComm(), MPI_COMM_TYPE_SHARED, myid,
53 MPI_INFO_NULL, &node_comm);
54 int node_rank;
55 MPI_Comm_rank(node_comm, &node_rank);
56 node_root = (node_rank == 0);
57 MPI_Comm_free(&node_comm);
58 }
59#endif
60
61 do
62 {
63 pos = dir_name.find(path_delim, pos+1);
64 std::string subdir = dir_name.substr(0, pos);
65
66#ifndef MFEM_USE_MPI
67 err_flag = mkdir(subdir.c_str(), 0777);
68 err_flag = (err_flag && (errno != EEXIST)) ? 1 : 0;
69#else
70 if (node_root || pmesh == NULL)
71 {
72 err_flag = mkdir(subdir.c_str(), 0777);
73 err_flag = (err_flag && (errno != EEXIST)) ? 1 : 0;
74 }
75#endif
76 }
77 while ( pos != std::string::npos );
78
79#ifdef MFEM_USE_MPI
80 if (pmesh)
81 {
82 MPI_Allreduce(MPI_IN_PLACE, &err_flag, 1, MPI_INT, MPI_MAX,
83 pmesh->GetComm());
84 }
85#endif
86
87 return err_flag;
88}
89
90// class DataCollection implementation
91
92DataCollection::DataCollection(const std::string& collection_name, Mesh *mesh_)
93{
94 std::string::size_type pos = collection_name.find_last_of('/');
95 if (pos == std::string::npos)
96 {
97 name = collection_name;
98 // leave prefix_path empty
99 }
100 else
101 {
102 prefix_path = collection_name.substr(0, pos+1);
103 name = collection_name.substr(pos+1);
104 }
105 mesh = mesh_;
106 myid = 0;
107 num_procs = 1;
108 serial = true;
109 appendRankToFileName = false;
110
111#ifdef MFEM_USE_MPI
112 m_comm = MPI_COMM_NULL;
113 ParMesh *par_mesh = dynamic_cast<ParMesh*>(mesh);
114 if (par_mesh)
115 {
116 myid = par_mesh->GetMyRank();
117 num_procs = par_mesh->GetNRanks();
118 m_comm = par_mesh->GetComm();
119 serial = false;
121 }
122#endif
123 own_data = false;
124 cycle = -1;
125 time = 0.0;
126 time_step = 0.0;
129 format = SERIAL_FORMAT; // use serial mesh format
130 compression = 0;
131 error = No_Error;
132}
133
135{
136 if (own_data && new_mesh != mesh) { delete mesh; }
137 mesh = new_mesh;
138 myid = 0;
139 num_procs = 1;
140 serial = true;
141 appendRankToFileName = false;
142
143#ifdef MFEM_USE_MPI
144 m_comm = MPI_COMM_NULL;
145 ParMesh *par_mesh = dynamic_cast<ParMesh*>(mesh);
146 if (par_mesh)
147 {
148 myid = par_mesh->GetMyRank();
149 num_procs = par_mesh->GetNRanks();
150 m_comm = par_mesh->GetComm();
151 serial = false;
153 }
154#endif
155}
156
157#ifdef MFEM_USE_MPI
158void DataCollection::SetMesh(MPI_Comm comm, Mesh *new_mesh)
159{
160 // This seems to be the cleanest way to accomplish this
161 // and avoid duplicating fine grained details:
162
163 SetMesh(new_mesh);
164
165 m_comm = comm;
166 MPI_Comm_rank(comm, &myid);
167 MPI_Comm_size(comm, &num_procs);
168}
169#endif
170
172{
173 switch (fmt)
174 {
175 case SERIAL_FORMAT: break;
176#ifdef MFEM_USE_MPI
177 case PARALLEL_FORMAT: break;
178#endif
179 default: MFEM_ABORT("unknown format: " << fmt);
180 }
181 format = fmt;
182}
183
185{
186 compression = comp;
187#ifndef MFEM_USE_ZLIB
188 MFEM_VERIFY(!compression, "ZLib not enabled in MFEM build.");
189#endif
190}
191
192void DataCollection::SetPrefixPath(const std::string& prefix)
193{
194 if (!prefix.empty())
195 {
196 prefix_path = prefix;
197 if (!prefix_path.empty() && prefix_path[prefix_path.size()-1] != '/')
198 {
199 prefix_path += '/';
200 }
201 }
202 else
203 {
204 prefix_path.clear();
205 }
206}
207
208void DataCollection::Load(int cycle_)
209{
210 MFEM_ABORT("this method is not implemented");
211}
212
214{
215 SaveMesh();
216
217 if (error) { return; }
218
219 for (FieldMapIterator it = field_map.begin(); it != field_map.end(); ++it)
220 {
221 SaveOneField(it);
222 // Even if there is an error, try saving the other fields
223 }
224
226 ++it)
227 {
228 SaveOneQField(it);
229 }
230}
231
233{
234 std::string dir_name = prefix_path + name;
235 if (cycle != -1)
236 {
237 dir_name += "_" + to_padded_string(cycle, pad_digits_cycle);
238 }
239 int error_code = create_directory(dir_name, mesh, myid);
240 if (error_code)
241 {
243 MFEM_WARNING("Error creating directory: " << dir_name);
244 return; // do not even try to write the mesh
245 }
246
247 std::string mesh_name = GetMeshFileName();
248 mfem::ofgzstream mesh_file(mesh_name, compression);
249 mesh_file.precision(precision);
250#ifdef MFEM_USE_MPI
251 const ParMesh *pmesh = dynamic_cast<const ParMesh*>(mesh);
252 if (pmesh && format == PARALLEL_FORMAT)
253 {
254 pmesh->ParPrint(mesh_file);
255 }
256 else
257#endif
258 {
259 mesh->Print(mesh_file);
260 }
261 if (!mesh_file)
262 {
264 MFEM_WARNING("Error writing mesh to file: " << mesh_name);
265 }
266}
267
269{
270 return (serial || format == SERIAL_FORMAT) ? "mesh" : "pmesh";
271}
272
274{
276}
277
278std::string DataCollection::GetFieldFileName(const std::string &field_name)
279const
280{
281 std::string dir_name = prefix_path + name;
282 if (cycle != -1)
283 {
284 dir_name += "_" + to_padded_string(cycle, pad_digits_cycle);
285 }
286 std::string file_name = dir_name + "/" + field_name;
288 {
289 file_name += "." + to_padded_string(myid, pad_digits_rank);
290 }
291 return file_name;
292}
293
295{
296 mfem::ofgzstream field_file(GetFieldFileName(it->first), compression);
297
298 field_file.precision(precision);
299 (it->second)->Save(field_file);
300 if (!field_file)
301 {
303 MFEM_WARNING("Error writing field to file: " << it->first);
304 }
305}
306
308{
309 mfem::ofgzstream q_field_file(GetFieldFileName(it->first), compression);
310
311 q_field_file.precision(precision);
312 (it->second)->Save(q_field_file);
313 if (!q_field_file)
314 {
316 MFEM_WARNING("Error writing q-field to file: " << it->first);
317 }
318}
319
320void DataCollection::SaveField(const std::string &field_name)
321{
322 FieldMapIterator it = field_map.find(field_name);
323 if (it != field_map.end())
324 {
325 SaveOneField(it);
326 }
327}
328
329void DataCollection::SaveQField(const std::string &field_name)
330{
331 QFieldMapIterator it = q_field_map.find(field_name);
332 if (it != q_field_map.end())
333 {
334 SaveOneQField(it);
335 }
336}
337
339{
340 if (own_data) { delete mesh; }
341 mesh = NULL;
342
345 own_data = false;
346}
347
354
359
360
361// class VisItDataCollection implementation
362
364{
365 if (mesh)
366 {
369 if (mesh->NURBSext)
370 {
373 }
374 }
375 else
376 {
377 spatial_dim = 0;
378 topo_dim = 0;
379 }
380}
381
382VisItDataCollection::VisItDataCollection(const std::string& collection_name,
383 Mesh *mesh)
384 : DataCollection(collection_name, mesh)
385{
386 appendRankToFileName = true; // always include rank in file names
387 cycle = 0; // always include cycle in directory names
388
391
393}
394
395#ifdef MFEM_USE_MPI
397 const std::string& collection_name,
398 Mesh *mesh)
399 : DataCollection(collection_name, mesh)
400{
401 m_comm = comm;
402 MPI_Comm_rank(comm, &myid);
403 MPI_Comm_size(comm, &num_procs);
404 appendRankToFileName = true; // always include rank in file names
405 cycle = 0; // always include cycle in directory names
406
409
411}
412#endif
413
415{
416 DataCollection::SetMesh(new_mesh);
419}
420
421#ifdef MFEM_USE_MPI
422void VisItDataCollection::SetMesh(MPI_Comm comm, Mesh *new_mesh)
423{
424 // use VisItDataCollection's custom SetMesh, then set MPI info
425 SetMesh(new_mesh);
426 m_comm = comm;
427 MPI_Comm_rank(comm, &myid);
428 MPI_Comm_size(comm, &num_procs);
429}
430#endif
431
432void VisItDataCollection::RegisterField(const std::string& name,
433 GridFunction *gf)
434{
435 int LOD = 1;
436 if (gf->FESpace()->GetNURBSext())
437 {
438 LOD = gf->FESpace()->GetNURBSext()->GetOrder();
439 }
440 else
441 {
442 for (int e=0; e<gf->FESpace()->GetNE(); e++)
443 {
444 LOD = std::max(LOD,gf->FESpace()->GetFE(e)->GetOrder());
445 }
446 }
447
449 field_info_map[name] = VisItFieldInfo("nodes", gf->VectorDim(), LOD,
450 gf->FESpace()->FEColl()->Name(),
451 gf->FESpace()->FEColl()->GetOrder());
453}
454
455void VisItDataCollection::RegisterQField(const std::string& name,
457{
458 int LOD = -1;
459 Mesh *mesh = qf->GetSpace()->GetMesh();
460 for (int e=0; e<qf->GetSpace()->GetNE(); e++)
461 {
464 qf->GetIntRule(e).GetNPoints());
465
466 LOD = std::max(LOD,locLOD);
467 }
468
470 // For quadrature functions, use basis pattern:
471 // QF_{ORDER}_{VDIM}
472 int qf_vdim = qf->GetVDim();
473 int qf_order = qf->GetSpace()->GetOrder();
474 std::ostringstream oss;
475 oss << "QF_" << qf_order << "_" << qf_vdim;
476 field_info_map[name] = VisItFieldInfo("quadrature", qf->GetVDim(), LOD,
477 oss.str(), qf_order);
479}
480
482{
483 visit_levels_of_detail = levels_of_detail;
484}
485
486void VisItDataCollection::SetMaxLevelsOfDetail(int max_levels_of_detail)
487{
488 visit_max_levels_of_detail = max_levels_of_detail;
489}
490
496
502
504{
505 if (myid != 0) { return; }
506
507 std::string root_name = prefix_path + name + "_" +
509 ".mfem_root";
510 std::ofstream root_file(root_name);
511 MFEM_VERIFY(root_file.is_open(),
512 "Failed to open ofstream " << root_name);
513 root_file << GetVisItRootString();
514 if (!root_file)
515 {
517 MFEM_WARNING("Error writing VisIt root file: " << root_name);
518 }
519}
520
522{
523 DeleteAll();
524 time_step = 0.0;
525 error = No_Error;
526 cycle = cycle_;
527 std::string root_name = prefix_path + name + "_" +
529 ".mfem_root";
530 LoadVisItRootFile(root_name);
531 if (format != SERIAL_FORMAT || num_procs > 1)
532 {
533#ifndef MFEM_USE_MPI
534 MFEM_WARNING("Cannot load parallel VisIt root file in serial.");
536#else
537 if (m_comm == MPI_COMM_NULL)
538 {
539 MFEM_WARNING("Cannot load parallel VisIt root file without MPI"
540 " communicator");
542 }
543 else
544 {
545 // num_procs was read from the root file, check for consistency with
546 // the associated MPI_Comm, m_comm:
547 int comm_size;
548 MPI_Comm_size(m_comm, &comm_size);
549 if (comm_size != num_procs)
550 {
551 MFEM_WARNING("Processor number mismatch: VisIt root file: "
552 << num_procs << ", MPI_comm: " << comm_size);
554 }
555 else
556 {
557 // myid was set when setting m_comm
558 }
559 }
560#endif
561 }
562 if (!error)
563 {
564 LoadMesh(); // sets own_data to true, when there is no error
565 }
566 if (!error)
567 {
568 LoadFields();
569 }
570 if (error)
571 {
572 DeleteAll();
573 }
574}
575
576void VisItDataCollection::LoadVisItRootFile(const std::string& root_name)
577{
578 std::ifstream root_file(root_name);
579 std::stringstream buffer;
580 buffer << root_file.rdbuf();
581 if (!buffer)
582 {
584 MFEM_WARNING("Error reading the VisIt root file: " << root_name);
585 }
586 else
587 {
588 ParseVisItRootString(buffer.str());
589 }
590}
591
593{
594 // GetMeshFileName() uses 'serial', so we need to set it in advance.
596 std::string mesh_fname = GetMeshFileName();
597 named_ifgzstream file(mesh_fname);
598 // TODO: in parallel, check for errors on all processors
599 if (!file)
600 {
602 MFEM_WARNING("Unable to open mesh file: " << mesh_fname);
603 return;
604 }
605 // TODO: 1) load parallel mesh on one processor
606 if (format == SERIAL_FORMAT)
607 {
608 mesh = new Mesh(file, 1, 0, false);
609 serial = true;
610 }
611 else
612 {
613#ifdef MFEM_USE_MPI
614 mesh = new ParMesh(m_comm, file);
615 serial = false;
616#else
618 MFEM_WARNING("Reading parallel format in serial is not supported");
619 return;
620#endif
621 }
624 own_data = true;
625}
626
628{
629 std::string path_left = prefix_path + name + "_" +
631 std::string path_right = "." + to_padded_string(myid, pad_digits_rank);
632
634 for (FieldInfoMapIterator it = field_info_map.begin();
635 it != field_info_map.end(); ++it)
636 {
637 std::string fname = path_left + it->first + path_right;
638 mfem::ifgzstream file(fname);
639 // TODO: in parallel, check for errors on all processors
640 if (!file)
641 {
643 MFEM_WARNING("Unable to open field file: " << fname);
644 return;
645 }
646 // TODO: 1) load parallel GridFunction on one processor
647 if (serial)
648 {
649 if ((it->second).association == "nodes")
650 {
651 field_map.Register(it->first, new GridFunction(mesh, file), own_data);
652 }
653 else if ((it->second).association == "elements" || // old style
654 (it->second).association == "quadrature") // new style
655 {
656 q_field_map.Register(it->first, new QuadratureFunction(mesh, file), own_data);
657 }
658 }
659 else
660 {
661#ifdef MFEM_USE_MPI
662 if ((it->second).association == "nodes")
663 {
665 it->first,
666 new ParGridFunction(dynamic_cast<ParMesh*>(mesh), file), own_data);
667 }
668 else if ((it->second).association == "elements" || // old style
669 (it->second).association == "quadrature") // new style
670 {
671 q_field_map.Register(it->first, new QuadratureFunction(mesh, file), own_data);
672 }
673#else
675 MFEM_WARNING("Reading parallel format in serial is not supported");
676 return;
677#endif
678 }
679 }
680}
681
683{
684 // Get the path string (relative to where the root file is, i.e. no prefix).
685 std::string path_str =
687
688 // We have to build the json tree inside out to get all the values in there
689 picojson::object top, dsets, main, mesh, fields, field, mtags, ftags;
690
691 // Build the mesh data
692 std::string file_ext_format = ".%0" + to_string(pad_digits_rank) + "d";
693 mtags["spatial_dim"] = picojson::value(to_string(spatial_dim));
694 mtags["topo_dim"] = picojson::value(to_string(topo_dim));
695 mtags["max_lods"] = picojson::value(to_string(visit_max_levels_of_detail));
696 mesh["path"] = picojson::value(path_str + GetMeshShortFileName() +
697 file_ext_format);
698 mesh["tags"] = picojson::value(mtags);
699 mesh["format"] = picojson::value(to_string(format));
700
701 // Build the fields data entries
702 for (FieldInfoMapIterator it = field_info_map.begin();
703 it != field_info_map.end(); ++it)
704 {
705 ftags["assoc"] = picojson::value((it->second).association);
706 ftags["comps"] = picojson::value(to_string((it->second).num_components));
707 ftags["lod"] = picojson::value(to_string((it->second).lod));
708 ftags["basis"] = picojson::value((it->second).basis);
709 ftags["order"] = picojson::value(to_string((it->second).order));
710 field["path"] = picojson::value(path_str + it->first + file_ext_format);
711 field["tags"] = picojson::value(ftags);
712 fields[it->first] = picojson::value(field);
713 }
714
715 main["cycle"] = picojson::value(double(cycle));
716 main["time"] = picojson::value(time);
717 main["time_step"] = picojson::value(time_step);
718 main["domains"] = picojson::value(double(num_procs));
719 main["mesh"] = picojson::value(mesh);
720 if (!field_info_map.empty())
721 {
722 main["fields"] = picojson::value(fields);
723 }
724
725 dsets["main"] = picojson::value(main);
726 top["dsets"] = picojson::value(dsets);
727
728 return picojson::value(top).serialize(true);
729}
730
731void VisItDataCollection::ParseVisItRootString(const std::string& json)
732{
733 picojson::value top, dsets, main, mesh, fields;
734 std::string parse_err = picojson::parse(top, json);
735 if (!parse_err.empty())
736 {
738 MFEM_WARNING("Unable to parse VisIt root data.");
739 return;
740 }
741
742 // Process "main"
743 dsets = top.get("dsets");
744 main = dsets.get("main");
745 cycle = int(main.get("cycle").get<double>());
746 time = main.get("time").get<double>();
747 if (main.contains("time_step"))
748 {
749 time_step = main.get("time_step").get<double>();
750 }
751 num_procs = int(main.get("domains").get<double>());
752 mesh = main.get("mesh");
753 fields = main.get("fields");
754
755 // ... Process "mesh"
756
757 // Set the DataCollection::name using the mesh path
758 std::string path = mesh.get("path").get<std::string>();
759 size_t right_sep = path.rfind('_');
760 if (right_sep == std::string::npos)
761 {
763 MFEM_WARNING("Unable to parse VisIt root data.");
764 return;
765 }
766 name = path.substr(0, right_sep);
767
768 if (mesh.contains("format"))
769 {
770 format = to_int(mesh.get("format").get<std::string>());
771 }
772 spatial_dim = to_int(mesh.get("tags").get("spatial_dim").get<std::string>());
773 topo_dim = to_int(mesh.get("tags").get("topo_dim").get<std::string>());
775 to_int(mesh.get("tags").get("max_lods").get<std::string>());
776
777 // ... Process "fields"
778 field_info_map.clear();
779 if (fields.is<picojson::object>())
780 {
781 picojson::object fields_obj = fields.get<picojson::object>();
782 for (picojson::object::iterator it = fields_obj.begin();
783 it != fields_obj.end(); ++it)
784 {
785 picojson::value tags = it->second.get("tags");
786
787 // defaults that allow us to parse older mfem_root files
788 int lod = 1;
789 std::string basis = "";
790 int order = -1;
791
792 if (tags.contains("lod"))
793 {
794 lod = to_int(tags.get("lod").get<std::string>());
795 }
796
797 if (tags.contains("basis"))
798 {
799 basis = tags.get("comps").get<std::string>();
800 }
801
802 if (tags.contains("order"))
803 {
804 order = to_int(tags.get("comps").get<std::string>());
805 }
806
807 field_info_map[it->first] =
808 VisItFieldInfo(tags.get("assoc").get<std::string>(),
809 to_int(tags.get("comps").get<std::string>()),
810 lod, basis, order);
811 }
812 }
813}
814
816 const std::string &name, Mesh *mesh) : DataCollection(name, mesh)
817{
818 cycle = 0;
819#ifdef MFEM_USE_ZLIB
820 // If we have zlib, enable compression. Otherwise, compression is disabled in
821 // the DataCollection base class constructor.
822 compression = true;
823#endif
824}
825
827{
828 levels_of_detail = std::max(levels_of_detail_, 1);
829}
830
832{
833 high_order_output = high_order_output_;
834}
835
837{
838 bdr_output = bdr_output_;
839}
840
842{
843 MFEM_ASSERT(compression_level_ >= -1 && compression_level_ <= 9,
844 "Compression level must be between -1 and 9 (inclusive).");
845 if (compression_level_ != 0) { SetCompression(true);}
846 compression_level = compression_level_;
847}
848
853
858
863
865{
866 restart_mode = restart_mode_;
867}
868
870 const std::string& collection_name, Mesh *mesh_)
871 : ParaViewDataCollectionBase(collection_name, mesh_) { }
872
877
882
884{
885 return GeneratePVTUPath();
886}
887
889{
890 return GetCollectionName() + ".pvd";
891}
892
894 const std::string &prefix)
895{
896 return prefix + ".pvtu";
897}
898
900 const std::string &prefix, int rank)
901{
902 return prefix + to_padded_string(rank, pad_digits_rank) + ".vtu";
903}
904
906{
907 // add a new collection to the PDV file
908
909 std::string col_path = GenerateCollectionPath();
910 // check if the directories are created
911 {
912 std::string path = col_path + "/" + GenerateVTUPath();
913 int error_code = create_directory(path, mesh, myid);
914 if (error_code)
915 {
917 MFEM_WARNING("Error creating directory: " << path);
918 return; // do not even try to write the mesh
919 }
920 }
921 // the directory is created
922
923 // create pvd file if needed. If we are not in restart mode, a new pvd file
924 // is always created. In restart mode, we keep any previously defined
925 // timestep values as long as they are less than the currently defined time.
926
927 if (myid == 0 && !pvd_stream.is_open())
928 {
929 std::string pvdname = col_path + "/" + GeneratePVDFileName();
930
931 bool write_header = true;
932 std::ifstream pvd_in;
933 if (restart_mode && (pvd_in.open(pvdname,std::ios::binary),pvd_in.good()))
934 {
935 // PVD file exists and restart mode enabled: preserve existing time
936 // steps less than the current time.
937 std::fstream::pos_type pos_begin = pvd_in.tellg();
938 std::fstream::pos_type pos_end = pos_begin;
939
940 std::regex regexp("timestep=\"([^[:space:]]+)\".*file=\"Cycle(\\d+)");
941 std::smatch match;
942
943 std::string line;
944 while (getline(pvd_in,line))
945 {
946 if (regex_search(line,match,regexp))
947 {
948 MFEM_ASSERT(match.size() == 3, "Unable to parse DataSet");
949 double tvalue = std::stod(match[1]);
950 if (tvalue >= GetTime()) { break; }
951 int cvalue = std::stoi(match[2]);
952 MFEM_VERIFY(cvalue < GetCycle(), "Cycle " << GetCycle() <<
953 " is too small for restart mode: trying to overwrite"
954 " existing data.");
955 pos_end = pvd_in.tellg();
956 }
957 }
958 // Since pvd_in is opened in binary mode, count will store the number
959 // of bytes from the beginning of the file until the desired insertion
960 // point (in text mode on Windows this is not the case).
961 size_t count = pos_end - pos_begin;
962 if (count != 0)
963 {
964 write_header = false;
965 std::vector<char> buf(count);
966 // Read the contents of the PVD file, from the beginning to the
967 // insertion point.
968 pvd_in.clear();
969 pvd_in.seekg(pos_begin);
970 pvd_in.read(buf.data(), count);
971 pvd_in.close();
972 // Open the PVD file in truncate mode to delete the previous
973 // contents. Open in binary mode to write the data buffer without
974 // converting \r\n to \r\r\n on Windows.
975 pvd_stream.open(pvdname,std::ios::out|std::ios::trunc|std::ios::binary);
976 pvd_stream.write(buf.data(), count);
977 // Close and reopen the file in text mode, appending to the end.
978 pvd_stream.close();
979 pvd_stream.open(pvdname,std::ios::in|std::ios::out|std::ios::ate);
980 }
981 }
982 if (write_header)
983 {
984 // Initialize new pvd file.
985 pvd_stream.open(pvdname,std::ios::out|std::ios::trunc);
986 pvd_stream << "<?xml version=\"1.0\"?>\n";
987 pvd_stream << "<VTKFile type=\"Collection\" version=\"2.2\"";
988 pvd_stream << " byte_order=\"" << VTKByteOrder() << "\">\n";
989 pvd_stream << "<Collection>" << std::endl;
990 }
991 }
992
993 std::string vtu_prefix = col_path + "/" + GenerateVTUPath() + "/";
994
995 // Save the local part of the mesh and grid functions fields to the local
996 // VTU file. Also save coefficient fields.
997 {
998 std::string os_str = vtu_prefix + GenerateVTUFileName("proc", myid);
999 std::ofstream os(os_str);
1000 MFEM_VERIFY(os.is_open(),
1001 "Failed to open ofstream " << os_str);
1002 os.precision(precision);
1004 }
1005
1006 // Save the local part of the quadrature function fields.
1007 for (const auto &qfield : q_field_map)
1008 {
1009 MFEM_VERIFY(!bdr_output,
1010 "QuadratureFunction output is not supported for "
1011 "ParaViewDataCollection on domain boundary!");
1012 const std::string &field_name = qfield.first;
1013 std::string os_str = vtu_prefix + GenerateVTUFileName(field_name, myid);
1014 std::ofstream os(os_str);
1015 MFEM_VERIFY(os.is_open(),
1016 "Failed to open ofstream " << os_str);
1017 qfield.second->SaveVTU(os, pv_data_format, GetCompressionLevel(), field_name);
1018 }
1019
1020 // MPI rank 0 also creates a "PVTU" file that points to all of the separately
1021 // written VTU files.
1022 // This file path is then appended to the PVD file.
1023 if (myid == 0)
1024 {
1025 // Create the main PVTU file
1026 {
1027 std::string os_str = vtu_prefix + GeneratePVTUFileName("data");
1028 std::ofstream pvtu_out(os_str);
1029 MFEM_VERIFY(pvtu_out.is_open(),
1030 "Failed to open ofstream " << os_str);
1031 WritePVTUHeader(pvtu_out);
1032
1033 // Grid function fields and coefficient fields
1034 pvtu_out << "<PPointData>\n";
1035 for (auto &field_it : field_map)
1036 {
1037 int vec_dim = field_it.second->VectorDim();
1038 pvtu_out << "<PDataArray type=\"" << GetDataTypeString()
1039 << "\" Name=\"" << field_it.first
1040 << "\" NumberOfComponents=\"" << vec_dim << "\" "
1041 << VTKComponentLabels(vec_dim) << " "
1042 << "format=\"" << GetDataFormatString() << "\" />\n";
1043 }
1044 for (auto &field_it : coeff_field_map)
1045 {
1046 int vec_dim = 1;
1047 pvtu_out << "<PDataArray type=\"" << GetDataTypeString()
1048 << "\" Name=\"" << field_it.first
1049 << "\" NumberOfComponents=\"" << vec_dim << "\" "
1050 << "format=\"" << GetDataFormatString() << "\" />\n";
1051 }
1052 for (auto &field_it : vcoeff_field_map)
1053 {
1054 int vec_dim = field_it.second->GetVDim();
1055 pvtu_out << "<PDataArray type=\"" << GetDataTypeString()
1056 << "\" Name=\"" << field_it.first
1057 << "\" NumberOfComponents=\"" << vec_dim << "\" "
1058 << "format=\"" << GetDataFormatString() << "\" />\n";
1059 }
1060 pvtu_out << "</PPointData>\n";
1061
1062 // Element attributes
1063 pvtu_out << "<PCellData>\n";
1064 pvtu_out << "\t<PDataArray type=\"Int32\" Name=\"" << "attribute"
1065 << "\" NumberOfComponents=\"1\""
1066 << " format=\"" << GetDataFormatString() << "\"/>\n";
1067 pvtu_out << "</PCellData>\n";
1068
1069 WritePVTUFooter(pvtu_out, "proc");
1070 }
1071
1072 // Add the latest PVTU to the PVD
1073 pvd_stream << "<DataSet timestep=\"" << GetTime()
1074 << "\" group=\"\" part=\"" << 0 << "\" file=\""
1075 << GeneratePVTUPath() + "/" + GeneratePVTUFileName("data")
1076 << "\" name=\"mesh\"/>\n";
1077
1078 // Create PVTU files for each quadrature field and add them to the PVD
1079 // file
1080 for (auto &q_field : q_field_map)
1081 {
1082 const std::string &q_field_name = q_field.first;
1083 std::string q_fname = GeneratePVTUPath() + "/"
1084 + GeneratePVTUFileName(q_field_name);
1085 std::string os_str = col_path + "/" + q_fname;
1086 std::ofstream pvtu_out(os_str);
1087 MFEM_VERIFY(pvtu_out.is_open(),
1088 "Failed to open ofstream " << os_str);
1089 WritePVTUHeader(pvtu_out);
1090 int vec_dim = q_field.second->GetVDim();
1091 pvtu_out << "<PPointData>\n";
1092 pvtu_out << "<PDataArray type=\"" << GetDataTypeString()
1093 << "\" Name=\"" << q_field_name
1094 << "\" NumberOfComponents=\"" << vec_dim << "\" "
1095 << VTKComponentLabels(vec_dim) << " "
1096 << "format=\"" << GetDataFormatString() << "\" />\n";
1097 pvtu_out << "</PPointData>\n";
1098 WritePVTUFooter(pvtu_out, q_field_name);
1099
1100 pvd_stream << "<DataSet timestep=\"" << GetTime()
1101 << "\" group=\"\" part=\"" << 0 << "\" file=\""
1102 << q_fname << "\" name=\"" << q_field_name << "\"/>\n";
1103 }
1104 pvd_stream.flush();
1105 // Move the insertion point before the closing collection tag, so that
1106 // the PVD file is valid even when writing incrementally.
1107 std::fstream::pos_type pos = pvd_stream.tellp();
1108 pvd_stream << "</Collection>\n";
1109 pvd_stream << "</VTKFile>" << std::endl;
1110 pvd_stream.seekp(pos);
1111 }
1112}
1113
1115{
1116 os << "<?xml version=\"1.0\"?>\n";
1117 os << "<VTKFile type=\"PUnstructuredGrid\"";
1118 os << " version =\"2.2\" byte_order=\"" << VTKByteOrder() << "\">\n";
1119 os << "<PUnstructuredGrid GhostLevel=\"0\">\n";
1120
1121 os << "<PPoints>\n";
1122 os << "\t<PDataArray type=\"" << GetDataTypeString() << "\" ";
1123 os << " Name=\"Points\" NumberOfComponents=\"3\""
1124 << " format=\"" << GetDataFormatString() << "\"/>\n";
1125 os << "</PPoints>\n";
1126
1127 os << "<PCells>\n";
1128 os << "\t<PDataArray type=\"Int32\" ";
1129 os << " Name=\"connectivity\" NumberOfComponents=\"1\""
1130 << " format=\"" << GetDataFormatString() << "\"/>\n";
1131 os << "\t<PDataArray type=\"Int32\" ";
1132 os << " Name=\"offsets\" NumberOfComponents=\"1\""
1133 << " format=\"" << GetDataFormatString() << "\"/>\n";
1134 os << "\t<PDataArray type=\"UInt8\" ";
1135 os << " Name=\"types\" NumberOfComponents=\"1\""
1136 << " format=\"" << GetDataFormatString() << "\"/>\n";
1137 os << "</PCells>\n";
1138}
1139
1141 const std::string &vtu_prefix)
1142{
1143 for (int ii=0; ii<num_procs; ii++)
1144 {
1145 std::string vtu_filename = GenerateVTUFileName(vtu_prefix, ii);
1146 os << "<Piece Source=\"" << vtu_filename << "\"/>\n";
1147 }
1148 os << "</PUnstructuredGrid>\n";
1149 os << "</VTKFile>\n";
1150}
1151
1152void ParaViewDataCollection::SaveDataVTU(std::ostream &os, int ref)
1153{
1154 os << "<VTKFile type=\"UnstructuredGrid\"";
1155 if (GetCompressionLevel() != 0)
1156 {
1157 os << " compressor=\"vtkZLibDataCompressor\"";
1158 }
1159 os << " version=\"2.2\" byte_order=\"" << VTKByteOrder() << "\">\n";
1160 os << "<UnstructuredGrid>\n";
1162 bdr_output);
1163
1164 // dump out the grid functions as point data
1165 os << "<PointData >\n";
1166 // save the grid functions
1167 // iterate over all grid functions
1168 for (FieldMapIterator it=field_map.begin(); it!=field_map.end(); ++it)
1169 {
1170 MFEM_VERIFY(!bdr_output,
1171 "GridFunction output is not supported for "
1172 "ParaViewDataCollection on domain boundary!");
1173 SaveGFieldVTU(os,ref,it);
1174 }
1175 // save the coefficient functions
1176 // iterate over all Coefficient and VectorCoefficient functions
1177 for (const auto &kv : coeff_field_map)
1178 {
1179 SaveCoeffFieldVTU(os, ref, kv.first, *kv.second);
1180 }
1181 for (const auto &kv : vcoeff_field_map)
1182 {
1183 SaveVCoeffFieldVTU(os, ref, kv.first, *kv.second);
1184 }
1185 os << "</PointData>\n";
1186 // close the mesh
1187 os << "</Piece>\n"; // close the piece open in the PrintVTU method
1188 os << "</UnstructuredGrid>\n";
1189 os << "</VTKFile>" << std::endl;
1190}
1191
1192void ParaViewDataCollection::SaveGFieldVTU(std::ostream &os, int ref_,
1193 const FieldMapIterator &it)
1194{
1195 RefinedGeometry *RefG;
1196 Vector val;
1197 DenseMatrix vval, pmat;
1198 std::vector<char> buf;
1199 int vec_dim = it->second->VectorDim();
1200 int map_type = it->second->FESpace()->GetTypicalFE()->GetMapType();
1201 os << "<DataArray type=\"" << GetDataTypeString()
1202 << "\" Name=\"" << it->first
1203 << "\" NumberOfComponents=\"" << vec_dim << "\" "
1204 << VTKComponentLabels(vec_dim) << " "
1205 << "format=\"" << GetDataFormatString() << "\" >" << '\n';
1206 if (vec_dim == 1 && (map_type == FiniteElement::VALUE ||
1207 map_type == FiniteElement::INTEGRAL))
1208 {
1209 for (int i = 0; i < mesh->GetNE(); i++)
1210 {
1212 mesh->GetElementBaseGeometry(i), ref_, 1);
1213 it->second->GetValues(i, RefG->RefPts, val, pmat);
1214 for (int j = 0; j < val.Size(); j++)
1215 {
1216 WriteBinaryOrASCII(os, buf, val(j), "\n", pv_data_format);
1217 }
1218 }
1219 }
1220 else
1221 {
1222 // vector data
1223 for (int i = 0; i < mesh->GetNE(); i++)
1224 {
1226 mesh->GetElementBaseGeometry(i), ref_, 1);
1227 it->second->GetVectorValues(i, RefG->RefPts, vval, pmat);
1228 for (int jj = 0; jj < vval.Width(); jj++)
1229 {
1230 for (int ii = 0; ii < vval.Height(); ii++)
1231 {
1232 WriteBinaryOrASCII(os, buf, vval(ii,jj), " ", pv_data_format);
1233 }
1234 if (pv_data_format == VTKFormat::ASCII) { os << '\n'; }
1235 }
1236 }
1237 }
1239 {
1241 }
1242 os << "</DataArray>" << std::endl;
1243}
1244
1245void ParaViewDataCollection::SaveCoeffFieldVTU(std::ostream &os, int ref_,
1246 const std::string &name, Coefficient &coeff)
1247{
1248 RefinedGeometry *RefG;
1249 real_t val;
1250 std::vector<char> buf;
1251 int vec_dim = 1;
1252 os << "<DataArray type=\"" << GetDataTypeString()
1253 << "\" Name=\"" << name
1254 << "\" NumberOfComponents=\"" << vec_dim << "\""
1255 << " format=\"" << GetDataFormatString() << "\" >" << '\n';
1256 {
1257 // scalar data
1258 if (!bdr_output)
1259 {
1260 for (int i = 0; i < mesh->GetNE(); i++)
1261 {
1263 mesh->GetElementBaseGeometry(i), ref_, 1);
1264
1266 const IntegrationRule *ir = &RefG->RefPts;
1267 for (int j = 0; j < ir->GetNPoints(); j++)
1268 {
1269 const IntegrationPoint &ip = ir->IntPoint(j);
1270 eltrans->SetIntPoint(&ip);
1271 val = coeff.Eval(*eltrans, ip);
1272 WriteBinaryOrASCII(os, buf, val, "\n", pv_data_format);
1273 }
1274 }
1275 }
1276 else
1277 {
1278 for (int i = 0; i < mesh->GetNBE(); i++)
1279 {
1281 mesh->GetBdrElementBaseGeometry(i), ref_, 1);
1282
1284 const IntegrationRule *ir = &RefG->RefPts;
1285 for (int j = 0; j < ir->GetNPoints(); j++)
1286 {
1287 const IntegrationPoint &ip = ir->IntPoint(j);
1288 eltrans->SetIntPoint(&ip);
1289 val = coeff.Eval(*eltrans, ip);
1290 WriteBinaryOrASCII(os, buf, val, "\n", pv_data_format);
1291 }
1292 }
1293 }
1294 }
1296 {
1298 }
1299 os << "</DataArray>" << std::endl;
1300}
1301
1302void ParaViewDataCollection::SaveVCoeffFieldVTU(std::ostream &os, int ref_,
1303 const std::string &name, VectorCoefficient &coeff)
1304{
1305 RefinedGeometry *RefG;
1306 Vector val;
1307 std::vector<char> buf;
1308 int vec_dim = coeff.GetVDim();
1309 os << "<DataArray type=\"" << GetDataTypeString()
1310 << "\" Name=\"" << name
1311 << "\" NumberOfComponents=\"" << vec_dim << "\""
1312 << " format=\"" << GetDataFormatString() << "\" >" << '\n';
1313 {
1314 // vector data
1315 if (!bdr_output)
1316 {
1317 for (int i = 0; i < mesh->GetNE(); i++)
1318 {
1320 mesh->GetElementBaseGeometry(i), ref_, 1);
1321
1323 const IntegrationRule *ir = &RefG->RefPts;
1324 for (int j = 0; j < ir->GetNPoints(); j++)
1325 {
1326 const IntegrationPoint &ip = ir->IntPoint(j);
1327 eltrans->SetIntPoint(&ip);
1328 coeff.Eval(val, *eltrans, ip);
1329 for (int jj = 0; jj < val.Size(); jj++)
1330 {
1331 WriteBinaryOrASCII(os, buf, val(jj), " ", pv_data_format);
1332 }
1333 if (pv_data_format == VTKFormat::ASCII) { os << '\n'; }
1334 }
1335 }
1336 }
1337 else
1338 {
1339 for (int i = 0; i < mesh->GetNBE(); i++)
1340 {
1342 mesh->GetBdrElementBaseGeometry(i), ref_, 1);
1343
1345 const IntegrationRule *ir = &RefG->RefPts;
1346 for (int j = 0; j < ir->GetNPoints(); j++)
1347 {
1348 const IntegrationPoint &ip = ir->IntPoint(j);
1349 eltrans->SetIntPoint(&ip);
1350 coeff.Eval(val, *eltrans, ip);
1351 for (int jj = 0; jj < val.Size(); jj++)
1352 {
1353 WriteBinaryOrASCII(os, buf, val(jj), " ", pv_data_format);
1354 }
1355 if (pv_data_format == VTKFormat::ASCII) { os << '\n'; }
1356 }
1357 }
1358 }
1359 }
1361 {
1363 }
1364 os << "</DataArray>" << std::endl;
1365}
1366
1368{
1370 {
1371 return "ascii";
1372 }
1373 else
1374 {
1375 return "binary";
1376 }
1377}
1378
1380{
1382 {
1383 return "Float64";
1384 }
1385 else
1386 {
1387 return "Float32";
1388 }
1389}
1390
1391#ifdef MFEM_USE_HDF5
1392
1394 const std::string &collection_name, Mesh *mesh)
1395 : ParaViewDataCollectionBase(collection_name, mesh)
1396{
1397 compression = true;
1398}
1399
1401{
1402 compression = compression_;
1403}
1404
1405void ParaViewHDFDataCollection::EnsureVTKHDF()
1406{
1407 if (!vtkhdf)
1408 {
1409 if (!prefix_path.empty())
1410 {
1411 const int error_code = create_directory(prefix_path, mesh, myid);
1412 MFEM_VERIFY(error_code == 0, "Error creating directory " << prefix_path);
1413 }
1414
1415 std::string fname = prefix_path + name + ".vtkhdf";
1416 bool use_mpi = false;
1417#ifdef MFEM_USE_MPI
1418 if (ParMesh *pmesh = dynamic_cast<ParMesh*>(mesh))
1419 {
1420 use_mpi = true;
1421#ifdef MFEM_PARALLEL_HDF5
1422 vtkhdf.reset(new VTKHDF(fname, pmesh->GetComm(), {restart_mode, time}));
1423#else
1424 MFEM_ABORT("Requires HDF5 library with parallel support enabled");
1425#endif
1426 }
1427#endif
1428 if (!use_mpi)
1429 {
1430 vtkhdf.reset(new VTKHDF(fname, {restart_mode, time}));
1431 }
1432 }
1433}
1434
1435template <typename FP_T>
1436void ParaViewHDFDataCollection::TSave()
1437{
1438 EnsureVTKHDF();
1439
1440 if (compression)
1441 {
1442 vtkhdf->EnableCompression(compression_level >= 0 ? compression_level : 6);
1443 }
1444 else
1445 {
1446 vtkhdf->DisableCompression();
1447 }
1448
1449 vtkhdf->SaveMesh<FP_T>(*mesh, high_order_output, levels_of_detail);
1450 for (const auto &field : field_map)
1451 {
1452 vtkhdf->SaveGridFunction<FP_T>(*field.second, field.first);
1453 }
1454 vtkhdf->UpdateSteps(time);
1455 vtkhdf->Flush();
1456}
1457
1459{
1460 switch (pv_data_format)
1461 {
1462 case VTKFormat::BINARY32: TSave<float>(); break;
1463 case VTKFormat::BINARY: TSave<double>(); break;
1464 default: MFEM_ABORT("Unsupported VTK format.");
1465 }
1466}
1467
1469
1470#endif
1471
1472} // end namespace MFEM
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the coefficient in the element described by T at the point ip.
int cycle
Time cycle; for time-dependent simulations cycle >= 0, otherwise = -1.
real_t time
Physical time (for time-dependent simulations)
virtual void RegisterQField(const std::string &field_name, QuadratureFunction *qf)
Add a QuadratureFunction to the collection.
QFieldMap::iterator QFieldMapIterator
virtual void SetMesh(Mesh *new_mesh)
Set/change the mesh associated with the collection.
void SaveOneQField(const QFieldMapIterator &it)
Save one q-field to disk, assuming the collection directory exists.
const std::string & GetCollectionName() const
Get the name of the collection.
bool own_data
Should the collection delete its mesh and fields.
DataCollection(const std::string &collection_name, Mesh *mesh_=NULL)
Initialize the collection with its name and Mesh.
static int create_directory(const std::string &dir_name, const Mesh *mesh, int myid)
int GetCycle() const
Get time cycle (for time-dependent simulations)
GFieldMap::iterator FieldMapIterator
void SaveOneField(const FieldMapIterator &it)
Save one field to disk, assuming the collection directory exists.
void DeleteAll()
Delete data owned by the DataCollection including field information.
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection.
static const int precision_default
Default value for precision.
virtual void SaveQField(const std::string &field_name)
Save one q-field, assuming the collection directory already exists.
int pad_digits_cycle
Number of digits used for the cycle and MPI rank in filenames.
bool serial
Serial or parallel run? False iff mesh is a ParMesh.
virtual void SetCompression(bool comp)
Set the flag for use of gz compressed files.
std::string prefix_path
A path where the directory with results is saved. If not empty, it has '/' at the end.
std::string GetFieldFileName(const std::string &field_name) const
int myid
MPI rank (in parallel)
static const int pad_digits_default
Default value for pad_digits_*.
real_t time_step
Time step i.e. delta_t (for time-dependent simulations)
int num_procs
Number of MPI ranks (in parallel)
std::string GetMeshShortFileName() const
virtual void Load(int cycle_=0)
Load the collection. Not implemented in the base class DataCollection.
virtual void SetFormat(int fmt)
Set the desired output mesh and data format.
void SetPrefixPath(const std::string &prefix)
Set the path where the DataCollection will be saved.
virtual ~DataCollection()
Delete the mesh and fields if owned by the collection.
std::string GetMeshFileName() const
void DeleteData()
Delete data owned by the DataCollection keeping field information.
bool appendRankToFileName
Append rank to any output file names.
std::string name
Name of the collection, used as a directory name when saving.
virtual void Save()
Save the collection to disk.
virtual void SaveField(const std::string &field_name)
Save one field, assuming the collection directory already exists.
MPI_Comm m_comm
Associated MPI communicator.
Mesh * mesh
The (common) mesh for the collected fields.
virtual void SaveMesh()
Save the mesh, creating the collection directory.
int precision
Precision (number of digits) used for the text output of doubles.
int format
Output mesh format: see the Format enumeration.
real_t GetTime() const
Get physical time (for time-dependent simulations)
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition eltrans.hpp:106
int GetOrder() const
Return the order (polynomial degree) of the FE collection, corresponding to the order/degree returned...
Definition fe_coll.hpp:248
virtual const char * Name() const
Definition fe_coll.hpp:79
const NURBSExtension * GetNURBSext() const
Definition fespace.hpp:641
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Definition fespace.cpp:3860
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:854
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition fe_base.hpp:414
RefinedGeometry * Refine(Geometry::Type Geom, int Times, int ETimes=1)
Definition geom.cpp:1136
static int GetRefinementLevelFromElems(Geometry::Type geom, int Npts)
Get the Refinement level based on number of elements.
Definition geom.cpp:1972
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:53
FiniteElementSpace * FESpace()
int VectorDim() const
Shortcut for calling FiniteElementSpace::GetVectorDim() on the underlying fes.
Definition gridfunc.hpp:166
Class for integration point with weight.
Definition intrules.hpp:35
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:96
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:255
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:258
Mesh data type.
Definition mesh.hpp:67
NURBSExtension * NURBSext
Optional NURBS mesh extension.
Definition mesh.hpp:317
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
Print the mesh to the given stream using the default MFEM mesh format.
Definition mesh.hpp:2610
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1390
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
Builds the transformation defining the i-th element in ElTr. ElTr must be allocated in advance and wi...
Definition mesh.cpp:361
ElementTransformation * GetBdrElementTransformation(int i)
Returns a pointer to the transformation defining the i-th boundary element.
Definition mesh.cpp:533
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Definition mesh.hpp:1317
void PrintVTU(std::ostream &os, int ref=1, VTKFormat format=VTKFormat::ASCII, bool high_order_output=false, int compression_level=0, bool bdr_elements=false)
Definition mesh.cpp:12908
int GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1393
Geometry::Type GetElementBaseGeometry(int i) const
Definition mesh.hpp:1569
Geometry::Type GetBdrElementBaseGeometry(int i) const
Definition mesh.hpp:1572
int GetOrder() const
If all KnotVector orders are identical, return that number. Otherwise, return NURBSFECollection::Vari...
Definition nurbs.hpp:946
void Register(const std::string &fname, T *field, bool own_data)
Register field field with name fname.
iterator end()
Returns an end iterator to the registered fields.
iterator begin()
Returns a begin iterator to the registered fields.
void DeleteData(bool own_data)
Clear all associations between names and fields.
void clear()
Clears the map of registered fields without reclaiming memory.
iterator find(const std::string &fname)
Returns an iterator to the field fname.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:74
Class for parallel grid function.
Definition pgridfunc.hpp:50
Class for parallel meshes.
Definition pmesh.hpp:35
MPI_Comm GetComm() const
Definition pmesh.hpp:403
int GetMyRank() const
Definition pmesh.hpp:405
void ParPrint(std::ostream &out, const std::string &comments="") const
Definition pmesh.cpp:6579
int GetNRanks() const
Definition pmesh.hpp:404
Abstract base class for ParaViewDataCollection and ParaViewHDFDataCollection.
bool IsBinaryFormat() const
Returns true if the output format is BINARY or BINARY32, false if ASCII.
ParaViewDataCollectionBase(const std::string &name, Mesh *mesh)
void SetLevelsOfDetail(int levels_of_detail_)
Set the refinement level.
void UseRestartMode(bool restart_mode_)
Enable or disable restart mode.
void SetBoundaryOutput(bool bdr_output_)
Configures collection to save only fields evaluated on boundaries of the mesh.
void SetHighOrderOutput(bool high_order_output_)
Sets whether or not to output the data as high-order elements (false by default).
void SetDataFormat(VTKFormat fmt)
Set the data format for the ParaView output files.
void SetCompressionLevel(int compression_level_)
Set the zlib compression level.
int GetCompressionLevel() const
If compression is enabled, return the compression level, else return 0.
void SaveVCoeffFieldVTU(std::ostream &out, int ref_, const std::string &name, VectorCoefficient &coeff)
void WritePVTUHeader(std::ostream &out)
void SaveGFieldVTU(std::ostream &out, int ref_, const FieldMapIterator &it)
const char * GetDataFormatString() const
void WritePVTUFooter(std::ostream &out, const std::string &vtu_prefix)
void SaveDataVTU(std::ostream &out, int ref)
ParaViewDataCollection(const std::string &collection_name, Mesh *mesh_=nullptr)
Constructor. The collection name is used when saving the data.
void SaveCoeffFieldVTU(std::ostream &out, int ref_, const std::string &name, Coefficient &coeff)
std::string GenerateVTUFileName(const std::string &prefix, int rank)
const char * GetDataTypeString() const
std::string GeneratePVTUFileName(const std::string &prefix)
void Save() override
Save the collection.
ParaViewHDFDataCollection(const std::string &collection_name, Mesh *mesh_=nullptr)
Constructor. The collection name is used when saving the data.
void SetCompression(bool compression_) override
Enable or disable compression.
Represents values or vectors of values at quadrature points on a mesh.
Definition qfunction.hpp:24
QuadratureSpaceBase * GetSpace()
Get the associated QuadratureSpaceBase object.
Definition qfunction.hpp:94
int GetVDim() const
Get the vector dimension.
Definition qfunction.hpp:87
const IntegrationRule & GetIntRule(int idx) const
Get the IntegrationRule associated with entity (element or face) idx.
int GetOrder() const
Return the order of the quadrature rule(s) used by all elements.
Definition qspace.hpp:110
Mesh * GetMesh() const
Returns the mesh.
Definition qspace.hpp:116
IntegrationRule RefPts
Definition geom.hpp:321
Base class for vector Coefficients that optionally depend on time and space.
int GetVDim()
Returns dimension of the vector.
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
Vector data type.
Definition vector.hpp:82
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
void SaveRootFile()
Save a VisIt root file for the collection.
std::string GetVisItRootString()
Prepare the VisIt root file in JSON format for the current collection.
void RegisterQField(const std::string &q_field_name, QuadratureFunction *qf) override
Add a quadrature function to the collection and update the root file.
void LoadVisItRootFile(const std::string &root_name)
VisItDataCollection(const std::string &collection_name, Mesh *mesh_=NULL)
Constructor. The collection name is used when saving the data.
void Load(int cycle_=0) override
Load the collection based on its VisIt data (described in its root file)
void SetLevelsOfDetail(int levels_of_detail)
Set VisIt parameter: default levels of detail for the MultiresControl.
void Save() override
Save the collection and a VisIt root file.
void SetMaxLevelsOfDetail(int max_levels_of_detail)
Set VisIt parameter: maximum levels of detail for the MultiresControl.
std::map< std::string, VisItFieldInfo >::iterator FieldInfoMapIterator
void SetMesh(Mesh *new_mesh) override
Set/change the mesh associated with the collection.
void RegisterField(const std::string &field_name, GridFunction *gf) override
Add a grid function to the collection and update the root file.
std::map< std::string, VisItFieldInfo > field_info_map
void DeleteAll()
Delete all data owned by VisItDataCollection including field data information.
void ParseVisItRootString(const std::string &json)
Read in a VisIt root file in JSON format.
Helper class for VisIt visualization data.
int main()
GeometryRefiner GlobGeometryRefiner
Definition geom.cpp:2014
std::string to_padded_string(int i, int digits)
Convert an integer to a 0-padded string with the given number of digits.
Definition text.hpp:96
void WriteBase64WithSizeAndClear(std::ostream &os, std::vector< char > &buf, int compression_level)
Encode in base 64 (and potentially compress) the given data, write it to the output stream (with a he...
Definition vtk.cpp:654
VTKFormat
Data array format for VTK and VTU files.
Definition vtk.hpp:100
@ ASCII
Data arrays will be written in ASCII format.
int to_int(const std::string &str)
Convert a string to an int.
Definition text.hpp:104
void WriteBinaryOrASCII(std::ostream &os, std::vector< char > &buf, const T &val, const char *suffix, VTKFormat format)
Write either ASCII data to the stream or binary data to the buffer depending on the given format.
Definition vtk.hpp:148
float real_t
Definition config.hpp:46
const char * VTKByteOrder()
Determine the byte order and return either "BigEndian" or "LittleEndian".
Definition vtk.cpp:602
std::string VTKComponentLabels(int vdim)
Returns a string defining the component labels for vector-valued data arrays for use in XML VTU files...
Definition vtk.cpp:662