Skip to content

Commit 7436c41

Browse files
authored
Merge pull request #3566 from loganharbour/xdr_streams
Add EquationSystems read/write capability via istream/ostream
2 parents b937392 + 92ce4b7 commit 7436c41

5 files changed

Lines changed: 187 additions & 144 deletions

File tree

include/systems/equation_systems.h

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -458,28 +458,22 @@ class EquationSystems : public ReferenceCountedObject<EquationSystems>,
458458
* processes. This renumbering is not compatible with meshes
459459
* that have two nodes in exactly the same position!
460460
*/
461-
template <typename InValType>
461+
template <typename InValType = Number>
462462
void read (std::string_view name,
463463
const XdrMODE,
464464
const unsigned int read_flags=(READ_HEADER | READ_DATA),
465465
bool partition_agnostic = true);
466466

467-
void read (std::string_view name,
468-
const XdrMODE mode,
469-
const unsigned int read_flags=(READ_HEADER | READ_DATA),
470-
bool partition_agnostic = true)
471-
{ read<Number>(name, mode, read_flags, partition_agnostic); }
472-
473-
template <typename InValType>
467+
template <typename InValType = Number>
474468
void read (std::string_view name,
475469
const unsigned int read_flags=(READ_HEADER | READ_DATA),
476470
bool partition_agnostic = true);
477471

478-
void read (std::string_view name,
472+
template <typename InValType = Number>
473+
void read (Xdr & io,
474+
std::function<std::unique_ptr<Xdr>()> & local_io_functor,
479475
const unsigned int read_flags=(READ_HEADER | READ_DATA),
480-
bool partition_agnostic = true)
481-
{ read<Number>(name, read_flags, partition_agnostic); }
482-
476+
bool partition_agnostic = true);
483477

484478
/**
485479
* Write the systems to disk using the XDR data format.
@@ -514,6 +508,15 @@ class EquationSystems : public ReferenceCountedObject<EquationSystems>,
514508
const unsigned int write_flags=(WRITE_DATA),
515509
bool partition_agnostic = true) const;
516510

511+
void write (std::ostream name,
512+
const unsigned int write_flags=(WRITE_DATA),
513+
bool partition_agnostic = true) const;
514+
515+
void write (Xdr & io,
516+
const unsigned int write_flags=(WRITE_DATA),
517+
bool partition_agnostic = true,
518+
Xdr * const local_io = nullptr) const;
519+
517520
/**
518521
* \returns \p true when this equation system contains
519522
* identical data, up to the given threshold. Delegates
@@ -618,27 +621,6 @@ class EquationSystems : public ReferenceCountedObject<EquationSystems>,
618621
bool _enable_default_ghosting;
619622

620623
private:
621-
622-
/**
623-
* Actual read implementation. This can be called repeatedly
624-
* inside a try-catch block in an attempt to read broken files.
625-
*
626-
* \param name Name of the file to be read.
627-
* \param read_flags Single flag created by bitwise-OR'ing several flags together.
628-
* \param partition_agnostic If true then the mesh and degrees of freedom
629-
* will be temporarily renumbered in a partition agnostic way so that
630-
* files written using "n" mpi processes can be re-read on "m" mpi
631-
* processes.
632-
*
633-
* \note This renumbering is not compatible with meshes that have
634-
* two nodes in exactly the same position!
635-
*/
636-
template <typename InValType>
637-
void _read_impl (std::string_view name,
638-
const XdrMODE,
639-
const unsigned int read_flags,
640-
bool partition_agnostic = true);
641-
642624
/**
643625
* This function is used in the implementation of add_system,
644626
* it loops over the nodes and elements of the Mesh, adding the

include/utils/xdr_cxx.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,22 @@ class Xdr
7070
public:
7171

7272
/**
73-
* Constructor. Takes the filename and the mode.
73+
* File-based constructor. Takes the filename and the mode.
7474
* Valid modes are ENCODE, DECODE, READ, and WRITE.
7575
*/
7676
Xdr (std::string name="", const XdrMODE m=UNKNOWN);
7777

78+
/**
79+
* Output stream based constructor.
80+
* Assumes mode WRITE.
81+
*/
82+
Xdr (std::ostream & stream);
83+
/**
84+
* Input stream based constructor.
85+
* Assumes mode READ.
86+
*/
87+
Xdr (std::istream & stream);
88+
7889
/**
7990
* Destructor. Closes the file if it is open.
8091
*/

src/systems/equation_systems_io.C

Lines changed: 55 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,6 @@ void EquationSystems::read (std::string_view name,
8181
if (name.find(".xdr") != std::string::npos)
8282
mode = DECODE;
8383
this->read(name, mode, read_flags, partition_agnostic);
84-
85-
#ifdef LIBMESH_ENABLE_AMR
86-
MeshRefinement mesh_refine(_mesh);
87-
mesh_refine.clean_refinement_flags();
88-
#endif
8984
}
9085

9186

@@ -96,58 +91,24 @@ void EquationSystems::read (std::string_view name,
9691
const unsigned int read_flags,
9792
bool partition_agnostic)
9893
{
99-
// If we have exceptions enabled we can be considerate and try
100-
// to read old restart files which contain infinite element
101-
// information but do not have the " with infinite elements"
102-
// string in the version information.
103-
104-
// First try the read the user requested
105-
libmesh_try
106-
{
107-
this->_read_impl<InValType> (name, mode, read_flags, partition_agnostic);
108-
}
109-
110-
// If that fails, try it again but explicitly request we look for infinite element info
111-
libmesh_catch (...)
112-
{
113-
libMesh::out << "\n*********************************************************************\n"
114-
<< "READING THE FILE \"" << name << "\" FAILED.\n"
115-
<< "It is possible this file contains infinite element information,\n"
116-
<< "but the version string does not contain \" with infinite elements\"\n"
117-
<< "Let's try this again, but looking for infinite element information...\n"
118-
<< "*********************************************************************\n"
119-
<< std::endl;
120-
121-
libmesh_try
122-
{
123-
this->_read_impl<InValType> (name, mode, read_flags | EquationSystems::TRY_READ_IFEMS, partition_agnostic);
124-
}
94+
// This will unzip a file with .bz2 as the extension, otherwise it
95+
// simply returns the name if the file need not be unzipped.
96+
Xdr io ((this->processor_id() == 0) ? std::string(name) : "", mode);
12597

126-
// If all that failed, we are out of ideas here...
127-
libmesh_catch (...)
128-
{
129-
libMesh::out << "\n*********************************************************************\n"
130-
<< "Well, at least we tried!\n"
131-
<< "Good Luck!!\n"
132-
<< "*********************************************************************\n"
133-
<< std::endl;
134-
libmesh_error();
135-
}
136-
}
98+
std::function<std::unique_ptr<Xdr>()> local_io_functor;
99+
local_io_functor = [this,&name,&mode]() {
100+
return std::make_unique<Xdr>(local_file_name(this->processor_id(), name), mode); };
137101

138-
#ifdef LIBMESH_ENABLE_AMR
139-
MeshRefinement mesh_refine(_mesh);
140-
mesh_refine.clean_refinement_flags();
141-
#endif
102+
this->read(io, local_io_functor, read_flags, partition_agnostic);
142103
}
143104

144105

145106

146107
template <typename InValType>
147-
void EquationSystems::_read_impl (std::string_view name,
148-
const XdrMODE mode,
149-
const unsigned int read_flags,
150-
bool partition_agnostic)
108+
void EquationSystems::read (Xdr & io,
109+
std::function<std::unique_ptr<Xdr>()> & local_io_functor,
110+
const unsigned int read_flags,
111+
bool partition_agnostic)
151112
{
152113
/**
153114
* This program implements the output of an
@@ -223,9 +184,6 @@ void EquationSystems::_read_impl (std::string_view name,
223184

224185
std::vector<std::pair<std::string, System *>> xda_systems;
225186

226-
// This will unzip a file with .bz2 as the extension, otherwise it
227-
// simply returns the name if the file need not be unzipped.
228-
Xdr io ((this->processor_id() == 0) ? std::string(name) : "", mode);
229187
libmesh_assert (io.reading());
230188

231189
{
@@ -247,7 +205,7 @@ void EquationSystems::_read_impl (std::string_view name,
247205

248206
// Recursively call this read() function but with the
249207
// EquationSystems::READ_LEGACY_FORMAT bit set.
250-
this->read (name, mode, (read_flags | EquationSystems::READ_LEGACY_FORMAT), partition_agnostic);
208+
this->read (io, local_io_functor, (read_flags | EquationSystems::READ_LEGACY_FORMAT), partition_agnostic);
251209
return;
252210
}
253211

@@ -328,6 +286,8 @@ void EquationSystems::_read_impl (std::string_view name,
328286
// Read and set the numeric vector values
329287
if (read_data)
330288
{
289+
std::unique_ptr<Xdr> local_io;
290+
331291
// the EquationSystems::read() method should look constant from the mesh
332292
// perspective, but we need to assign a temporary numbering to the nodes
333293
// and elements in the mesh, which requires that we abuse const_cast
@@ -337,8 +297,6 @@ void EquationSystems::_read_impl (std::string_view name,
337297
MeshTools::Private::globally_renumber_nodes_and_elements(mesh);
338298
}
339299

340-
Xdr local_io (read_parallel_files ? local_file_name(this->processor_id(),name) : "", mode);
341-
342300
for (auto & pr : xda_systems)
343301
if (read_legacy_format)
344302
{
@@ -349,7 +307,14 @@ void EquationSystems::_read_impl (std::string_view name,
349307
}
350308
else
351309
if (read_parallel_files)
352-
pr.second->read_parallel_data<InValType> (local_io, read_additional_data);
310+
{
311+
if (!local_io)
312+
{
313+
local_io = local_io_functor();
314+
libmesh_assert(local_io->reading());
315+
}
316+
pr.second->read_parallel_data<InValType> (*local_io, read_additional_data);
317+
}
353318
else
354319
pr.second->read_serialized_data<InValType> (io, read_additional_data);
355320

@@ -361,6 +326,11 @@ void EquationSystems::_read_impl (std::string_view name,
361326

362327
// Localize each system's data
363328
this->update();
329+
330+
#ifdef LIBMESH_ENABLE_AMR
331+
MeshRefinement mesh_refine(_mesh);
332+
mesh_refine.clean_refinement_flags();
333+
#endif
364334
}
365335

366336

@@ -381,6 +351,23 @@ void EquationSystems::write(std::string_view name,
381351
const XdrMODE mode,
382352
const unsigned int write_flags,
383353
bool partition_agnostic) const
354+
{
355+
Xdr io((this->processor_id()==0) ? std::string(name) : "", mode);
356+
357+
std::unique_ptr<Xdr> local_io;
358+
// open a parallel buffer if warranted
359+
if (write_flags & EquationSystems::WRITE_PARALLEL_FILES && write_flags & EquationSystems::WRITE_DATA)
360+
local_io = std::make_unique<Xdr>(local_file_name(this->processor_id(),name), mode);
361+
362+
this->write(io, write_flags, partition_agnostic, local_io.get());
363+
}
364+
365+
366+
367+
void EquationSystems::write(Xdr & io,
368+
const unsigned int write_flags,
369+
bool partition_agnostic,
370+
Xdr * const local_io) const
384371
{
385372
/**
386373
* This program implements the output of an
@@ -474,9 +461,10 @@ void EquationSystems::write(std::string_view name,
474461
// !this->get_mesh().is_serial())
475462
;
476463

477-
// New scope so that io will close before we try to zip the file
464+
if (write_parallel_files && write_data)
465+
libmesh_assert(local_io);
466+
478467
{
479-
Xdr io((this->processor_id()==0) ? std::string(name) : "", mode);
480468
libmesh_assert (io.writing());
481469

482470
LOG_SCOPE("write()", "EquationSystems");
@@ -554,21 +542,23 @@ void EquationSystems::write(std::string_view name,
554542
// to write vectors to disk, if wanted
555543
if (write_data)
556544
{
557-
// open a parallel buffer if warranted.
558-
Xdr local_io (write_parallel_files ? local_file_name(this->processor_id(),name) : "", mode);
559-
560545
for (auto & pr : _systems)
561546
{
562547
// Ignore this system if it has been marked as hidden
563548
if (pr.second->hide_output()) continue;
564549

565550
// 10.) + 11.)
566551
if (write_parallel_files)
567-
pr.second->write_parallel_data (local_io,write_additional_data);
552+
pr.second->write_parallel_data (*local_io,write_additional_data);
568553
else
569554
pr.second->write_serialized_data (io,write_additional_data);
570555
}
556+
557+
if (local_io)
558+
local_io->close();
571559
}
560+
561+
io.close();
572562
}
573563

574564
// the EquationSystems::write() method should look constant,
@@ -582,13 +572,13 @@ void EquationSystems::write(std::string_view name,
582572

583573
// template specialization
584574

575+
template LIBMESH_EXPORT void EquationSystems::read<Number> (Xdr & io, std::function<std::unique_ptr<Xdr>()> & local_io_functor, const unsigned int read_flags, bool partition_agnostic);
585576
template LIBMESH_EXPORT void EquationSystems::read<Number> (std::string_view name, const unsigned int read_flags, bool partition_agnostic);
586577
template LIBMESH_EXPORT void EquationSystems::read<Number> (std::string_view name, const XdrMODE mode, const unsigned int read_flags, bool partition_agnostic);
587-
template LIBMESH_EXPORT void EquationSystems::_read_impl<Number> (std::string_view name, const XdrMODE mode, const unsigned int read_flags, bool partition_agnostic);
588578
#ifdef LIBMESH_USE_COMPLEX_NUMBERS
579+
template LIBMESH_EXPORT void EquationSystems::read<Real> (Xdr & io, std::function<std::unique_ptr<Xdr>()> & local_io_functor, const unsigned int read_flags, bool partition_agnostic);
589580
template LIBMESH_EXPORT void EquationSystems::read<Real> (std::string_view name, const unsigned int read_flags, bool partition_agnostic);
590581
template LIBMESH_EXPORT void EquationSystems::read<Real> (std::string_view name, const XdrMODE mode, const unsigned int read_flags, bool partition_agnostic);
591-
template LIBMESH_EXPORT void EquationSystems::_read_impl<Real> (std::string_view name, const XdrMODE mode, const unsigned int read_flags, bool partition_agnostic);
592582
#endif
593583

594584
} // namespace libMesh

src/utils/xdr_cxx.C

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,42 @@ Xdr::Xdr (std::string name,
122122

123123

124124

125+
Xdr::Xdr (std::ostream & stream) :
126+
mode(WRITE),
127+
file_name(),
128+
#ifdef LIBMESH_HAVE_XDR
129+
fp(nullptr),
130+
#endif
131+
in(),
132+
out(std::make_unique<std::ostream>(stream.rdbuf())),
133+
comm_len(xdr_MAX_STRING_LENGTH),
134+
gzipped_file(false),
135+
bzipped_file(false),
136+
xzipped_file(false),
137+
version_number(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION, LIBMESH_MINOR_VERSION, LIBMESH_MICRO_VERSION))
138+
{
139+
}
140+
141+
142+
143+
Xdr::Xdr (std::istream & stream) :
144+
mode(READ),
145+
file_name(),
146+
#ifdef LIBMESH_HAVE_XDR
147+
fp(nullptr),
148+
#endif
149+
in(std::make_unique<std::istream>(stream.rdbuf())),
150+
out(),
151+
comm_len(xdr_MAX_STRING_LENGTH),
152+
gzipped_file(false),
153+
bzipped_file(false),
154+
xzipped_file(false),
155+
version_number(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION, LIBMESH_MINOR_VERSION, LIBMESH_MICRO_VERSION))
156+
{
157+
}
158+
159+
160+
125161
Xdr::~Xdr()
126162
{
127163
this->close();

0 commit comments

Comments
 (0)