Changed: [extract|inject]PatchSolution signature + some HDF5Writer cleaning

This commit is contained in:
Knut Morten Okstad 2018-05-19 12:09:38 +02:00
parent f94a20126a
commit 607c9771cf
7 changed files with 116 additions and 163 deletions

View File

@ -27,28 +27,25 @@ static bool compute(Vector& result, const SIMbase& model,
{ {
result.resize(model.getNoElms()); result.resize(model.getNoElms());
for (int l = 0; l < model.getNoPatches(); l++) { for (int idx = 1; idx <= model.getNoPatches(); idx++) {
Vector locvec; ASMbase* pch = model.getPatch(idx,true);
int loc = model.getLocalPatchIndex(l+1); if (!pch) continue;
if (loc == 0)
continue;
model.extractPatchSolution(displacement,locvec,loc-1); Vector locvec;
const ASMbase* pch = model.getPatch(loc);
if (!displacement.empty()) { if (!displacement.empty()) {
model.extractPatchSolution(displacement,locvec,loc-1); model.extractPatchSolution(displacement,locvec,pch);
const_cast<ASMbase*>(pch)->updateCoords(locvec); pch->updateCoords(locvec);
} }
int iel = 0; int iel = 0;
IntMat::const_iterator elm_it = pch->begin_elm(); size_t nel = pch->getNoElms(true);
for (size_t e = 1; elm_it != pch->end_elm(); ++elm_it, ++e) for (size_t e = 1; e <= nel; e++)
if ((iel = pch->getElmID(e)) > 0) if ((iel = pch->getElmID(e)) > 0)
result(iel) = func(*pch,e); result(iel) = func(*pch,e);
if (!displacement.empty()) { if (!displacement.empty()) {
locvec *= -1; locvec *= -1.0;
const_cast<ASMbase*>(pch)->updateCoords(locvec); pch->updateCoords(locvec);
} }
} }

View File

@ -1361,7 +1361,7 @@ bool SIMbase::solutionNorms (const TimeDomain& time,
norm->setProjectedFields(f, k); norm->setProjectedFields(f, k);
projOfs += ndof; projOfs += ndof;
} else } else
this->extractPatchSolution(ssol[k],norm->getProjection(k),lp-1,nCmp,1); this->extractPatchSolution(ssol[k],norm->getProjection(k),pch,nCmp,1);
if (mySol) if (mySol)
mySol->initPatch(pch->idx); mySol->initPatch(pch->idx);
@ -1396,7 +1396,7 @@ bool SIMbase::solutionNorms (const TimeDomain& time,
norm->setProjectedFields(f, k); norm->setProjectedFields(f, k);
projOfs += ndof; projOfs += ndof;
} else } else
this->extractPatchSolution(ssol[k],norm->getProjection(k),i,nCmp,1); this->extractPatchSolution(ssol[k],norm->getProjection(k),myModel[i],nCmp,1);
if (mySol) if (mySol)
mySol->initPatch(myModel[i]->idx); mySol->initPatch(myModel[i]->idx);
@ -1860,10 +1860,9 @@ bool SIMbase::projectAnaSol (Vector& ssol,
size_t SIMbase::extractPatchSolution (const Vector& sol, Vector& vec, size_t SIMbase::extractPatchSolution (const Vector& sol, Vector& vec,
int pindx, unsigned char nndof, const ASMbase* pch, unsigned char nndof,
unsigned char basis) const unsigned char basis) const
{ {
ASMbase* pch = pindx >= 0 ? this->getPatch(pindx+1) : nullptr;
if (!pch || sol.empty()) return 0; if (!pch || sol.empty()) return 0;
if (basis != 0 && nndof != 0 && if (basis != 0 && nndof != 0 &&
@ -1881,10 +1880,9 @@ size_t SIMbase::extractPatchSolution (const Vector& sol, Vector& vec,
bool SIMbase::injectPatchSolution (Vector& sol, const Vector& vec, bool SIMbase::injectPatchSolution (Vector& sol, const Vector& vec,
int pindx, unsigned char nndof, const ASMbase* pch, unsigned char nndof,
unsigned char basis) const unsigned char basis) const
{ {
ASMbase* pch = pindx >= 0 ? this->getPatch(pindx+1) : nullptr;
if (!pch) return false; if (!pch) return false;
if (basis > 0 && nndof > 0 && if (basis > 0 && nndof > 0 &&

View File

@ -566,21 +566,23 @@ public:
//! \brief Extracts a local solution vector for a specified patch. //! \brief Extracts a local solution vector for a specified patch.
//! \param[in] sol Global primary solution vector in DOF-order //! \param[in] sol Global primary solution vector in DOF-order
//! \param[out] vec Local solution vector associated with specified patch //! \param[out] vec Local solution vector associated with specified patch
//! \param[in] pindx Local patch index to extract solution vector for //! \param[in] pch The patch to extract solution vector for
//! \param[in] nndof Number of DOFs per node (optional) //! \param[in] nndof Number of DOFs per node (optional)
//! \param[in] basis Basis to extract for (optional) //! \param[in] basis Basis to extract for (optional)
//! \return Total number of DOFs in the patch (first basis only if mixed) //! \return Total number of DOFs in the patch (first basis only if mixed)
size_t extractPatchSolution(const Vector& sol, Vector& vec, int pindx, size_t extractPatchSolution(const Vector& sol, Vector& vec,
const ASMbase* pch,
unsigned char nndof = 0, unsigned char nndof = 0,
unsigned char basis = 0) const; unsigned char basis = 0) const;
//! \brief Injects a patch-wise solution vector into the global vector. //! \brief Injects a patch-wise solution vector into the global vector.
//! \param sol Global primary solution vector in DOF-order //! \param sol Global primary solution vector in DOF-order
//! \param[in] vec Local solution vector associated with specified patch //! \param[in] vec Local solution vector associated with specified patch
//! \param[in] pindx Local patch index to inject solution vector for //! \param[in] pch The patch to inject solution vector for
//! \param[in] nndof Number of DOFs per node (optional) //! \param[in] nndof Number of DOFs per node (optional)
//! \param[in] basis Basis to inject for (optional) //! \param[in] basis Basis to inject for (optional)
bool injectPatchSolution(Vector& sol, const Vector& vec, int pindx, bool injectPatchSolution(Vector& sol, const Vector& vec,
const ASMbase* pch,
unsigned char nndof = 0, unsigned char nndof = 0,
unsigned char basis = 0) const; unsigned char basis = 0) const;

View File

@ -544,7 +544,7 @@ int SIMoutput::writeGlvS1 (const Vector& psol, int iStep, int& nBlock,
if (msgLevel > 1) if (msgLevel > 1)
IFEM::cout <<"Writing primary solution for patch " IFEM::cout <<"Writing primary solution for patch "
<< pch->idx << std::endl; << pch->idx+1 << std::endl;
// Evaluate primary solution variables // Evaluate primary solution variables
@ -851,25 +851,25 @@ bool SIMoutput::writeGlvP (const Vector& ssol, int iStep, int& nBlock,
Vector::const_iterator ssolIt = ssol.begin(); Vector::const_iterator ssolIt = ssol.begin();
int geomID = myGeomID; int geomID = myGeomID;
for (size_t i = 0; i < myModel.size(); i++) for (ASMbase* pch : myModel)
{ {
if (myModel[i]->empty()) continue; // skip empty patches if (pch->empty()) continue; // skip empty patches
if (msgLevel > 1) if (msgLevel > 1)
IFEM::cout <<"Writing projected solution for patch "<< i+1 << std::endl; IFEM::cout <<"Writing projected solution for patch "
<< pch->idx+1 << std::endl;
if (this->fieldProjections()) if (this->fieldProjections())
{ {
size_t nval = nComp*myModel[i]->getNoProjectionNodes(); size_t nval = nComp*pch->getNoProjectionNodes();
lovec.resize(nval); lovec = RealArray(ssolIt,ssolIt+nval);
std::copy(ssolIt,ssolIt+nval,lovec.begin());
ssolIt += nval; ssolIt += nval;
} }
else else
this->extractPatchSolution(ssol,lovec,i,nComp,1); this->extractPatchSolution(ssol,lovec,pch,nComp,1);
// Evaluate the solution variables at the visualization points // Evaluate the solution variables at the visualization points
if (!myModel[i]->evalProjSolution(field,lovec,opt.nViz,nComp)) if (!pch->evalProjSolution(field,lovec,opt.nViz,nComp))
return false; return false;
size_t j = 1; // Write out to VTF-file as scalar fields size_t j = 1; // Write out to VTF-file as scalar fields

View File

@ -131,6 +131,7 @@ TEST(TestSIM3D, ProjectSolutionMixed)
TEST(TestSIM, InjectPatchSolution) TEST(TestSIM, InjectPatchSolution)
{ {
TestProjectSIM<SIM2D> sim({1,1}); TestProjectSIM<SIM2D> sim({1,1});
ASMbase* pch = sim.getPatch(1);
Vector sol(2*sim.getNoNodes(1) + sim.getNoNodes(2)); Vector sol(2*sim.getNoNodes(1) + sim.getNoNodes(2));
Vector lsol(2*sim.getNoNodes(1)); Vector lsol(2*sim.getNoNodes(1));
@ -139,7 +140,7 @@ TEST(TestSIM, InjectPatchSolution)
lsol[2*i] = lsol[2*i+1] = i+1; lsol[2*i] = lsol[2*i+1] = i+1;
ASSERT_TRUE(sim.addMixedMADOF(1, 2)); ASSERT_TRUE(sim.addMixedMADOF(1, 2));
sim.injectPatchSolution(sol, lsol, 0, 2, 1); sim.injectPatchSolution(sol, lsol, pch, 2, 1);
for (i = ofs = 0; i < sim.getNoNodes(1); i++, ofs += 2) { for (i = ofs = 0; i < sim.getNoNodes(1); i++, ofs += 2) {
EXPECT_FLOAT_EQ(sol[ofs], i+1); EXPECT_FLOAT_EQ(sol[ofs], i+1);
EXPECT_FLOAT_EQ(sol[ofs+1], i+1); EXPECT_FLOAT_EQ(sol[ofs+1], i+1);
@ -153,7 +154,7 @@ TEST(TestSIM, InjectPatchSolution)
for (i = 0; i < sim.getNoNodes(2); i++) for (i = 0; i < sim.getNoNodes(2); i++)
lsol2[2*i] = lsol2[2*i+1] = i+1; lsol2[2*i] = lsol2[2*i+1] = i+1;
sim.injectPatchSolution(sol2, lsol2, 0, 2, 2); sim.injectPatchSolution(sol2, lsol2, pch, 2, 2);
for (i = ofs = 0; i < sim.getNoNodes(1); i++, ofs++) for (i = ofs = 0; i < sim.getNoNodes(1); i++, ofs++)
EXPECT_FLOAT_EQ(sol2[ofs], 0); EXPECT_FLOAT_EQ(sol2[ofs], 0);

View File

@ -288,31 +288,24 @@ void HDF5Writer::writeVector(int level, const DataEntry& entry)
if (!entry.second.enabled) if (!entry.second.enabled)
return; return;
#ifdef HAS_HDF5 #ifdef HAS_HDF5
int redundant = entry.second.results & DataExporter::REDUNDANT;
int rank = 0; int rank = 0;
#ifdef HAVE_MPI #ifdef HAVE_MPI
if (entry.second.results & DataExporter::REDUNDANT) if (redundant)
MPI_Comm_rank(*m_adm.getCommunicator(), &rank); MPI_Comm_rank(*m_adm.getCommunicator(), &rank);
#endif #endif
std::stringstream str; std::stringstream str;
str << level; str << level;
hid_t group = H5Gopen2(m_file,str.str().c_str(),H5P_DEFAULT); hid_t group = H5Gopen2(m_file,str.str().c_str(),H5P_DEFAULT);
if (entry.second.field == DataExporter::VECTOR) { if (entry.second.field == DataExporter::VECTOR) {
Vector* vector = (Vector*)entry.second.data; Vector* dvec = (Vector*)entry.second.data;
if (!(entry.second.results & DataExporter::REDUNDANT) || rank == 0) int len = !redundant || rank == 0 ? dvec->size() : 0;
writeArray(level,entry.first,vector->size(),vector->data(),H5T_NATIVE_DOUBLE); this->writeArray(level,entry.first,len,dvec->data(),H5T_NATIVE_DOUBLE);
if ((entry.second.results & DataExporter::REDUNDANT) && rank != 0) { }
double dummy; else if (entry.second.field == DataExporter::INTVECTOR) {
writeArray(group,entry.first,0,&dummy,H5T_NATIVE_DOUBLE); std::vector<int>* ivec = (std::vector<int>*)entry.second.data;
} int len = !redundant || rank == 0 ? ivec->size() : 0;
} else if (entry.second.field == DataExporter::INTVECTOR) { this->writeArray(group,entry.first,len,ivec->data(),H5T_NATIVE_INT);
std::vector<int>* data = (std::vector<int>*)entry.second.data;
if (!(entry.second.results & DataExporter::REDUNDANT) || rank == 0)
writeArray(group,entry.first,data->size(),&data->front(),H5T_NATIVE_INT);
if ((entry.second.results & DataExporter::REDUNDANT) && rank != 0) {
int dummy;
writeArray(group,entry.first,0,&dummy,H5T_NATIVE_INT);
}
} }
H5Gclose(group); H5Gclose(group);
#endif #endif
@ -347,65 +340,45 @@ bool HDF5Writer::readVector(int level, const std::string& name,
void HDF5Writer::writeBasis (int level, const DataEntry& entry, void HDF5Writer::writeBasis (int level, const DataEntry& entry,
const std::string& prefix) const std::string& prefix)
{ {
if (!entry.second.enabled) if (!entry.second.enabled || !entry.second.data)
return; return;
SIMbase* sim = static_cast<SIMbase*>(const_cast<void*>(entry.second.data)); const SIMbase* sim = static_cast<const SIMbase*>(entry.second.data);
if (!sim)
return;
std::string basisname; this->writeBasis(sim, prefix+sim->getName()+"-1", 1, level,
if (prefix.empty()) entry.second.results & DataExporter::REDUNDANT);
basisname = sim->getName()+"-1";
else
basisname = prefix+sim->getName()+"-1";
writeBasis(sim,basisname,1,level,
entry.second.results & DataExporter::REDUNDANT);
} }
void HDF5Writer::writeSIM (int level, const DataEntry& entry, void HDF5Writer::writeSIM (int level, const DataEntry& entry,
bool geometryUpdated, const std::string& prefix) bool geometryUpdated, const std::string& prefix)
{ {
if (!entry.second.enabled) if (!entry.second.enabled || !entry.second.data || !entry.second.data2)
return; return;
SIMbase* sim = static_cast<SIMbase*>(const_cast<void*>(entry.second.data)); const SIMbase* sim = static_cast<const SIMbase*>(entry.second.data);
const Vector* sol = static_cast<const Vector*>(entry.second.data2); const Vector* sol = static_cast<const Vector*>(entry.second.data2);
if (!sim || !sol) return; const int results = abs(entry.second.results);
std::string basisname; if (level == 0 || geometryUpdated || (results & DataExporter::GRID)) {
if (prefix.empty()) this->writeBasis(sim,prefix+sim->getName()+"-1",1,level);
basisname = sim->getName()+"-1";
else
basisname = prefix+sim->getName()+"-1";
if (level == 0 || geometryUpdated || (abs(entry.second.results) & DataExporter::GRID)) {
writeBasis(sim,basisname,1,level);
if (sim->mixedProblem()) if (sim->mixedProblem())
for (size_t b=2; b <= sim->getNoBasis(); ++b) { for (size_t b=2; b <= sim->getNoBasis(); ++b) {
std::stringstream str; std::stringstream str;
str << sim->getName() << "-" << b; str << sim->getName() << "-" << b;
writeBasis(sim,str.str(),b,level); this->writeBasis(sim,str.str(),b,level);
} }
} }
Matrix eNorm; Matrix eNorm;
Vectors gNorm; Vectors gNorm;
if (abs(entry.second.results) & DataExporter::NORMS) if (results & DataExporter::NORMS)
sim->solutionNorms(*sol,eNorm,gNorm); const_cast<SIMbase*>(sim)->solutionNorms(*sol,eNorm,gNorm);
NormBase* norm = sim->getNormIntegrand();
#ifdef HAS_HDF5 #ifdef HAS_HDF5
NormBase* norm = sim->getNormIntegrand();
const IntegrandBase* prob = sim->getProblem(); const IntegrandBase* prob = sim->getProblem();
int results = entry.second.results; bool usedescription = entry.second.results < 0;
bool usedescription=false;
if (results < 0) {
results = -results;
usedescription = true;
}
size_t j, k, l; size_t j, k, l;
for (int i = 0; i < sim->getNoPatches(); ++i) { for (int i = 0; i < sim->getNoPatches(); ++i) {
@ -419,23 +392,24 @@ void HDF5Writer::writeSIM (int level, const DataEntry& entry,
else else
group2 = H5Gcreate2(m_file,str.str().c_str(),0,H5P_DEFAULT,H5P_DEFAULT); group2 = H5Gcreate2(m_file,str.str().c_str(),0,H5P_DEFAULT,H5P_DEFAULT);
int loc = sim->getLocalPatchIndex(i+1); int loc = sim->getLocalPatchIndex(i+1);
if (loc > 0 && (!(abs(results) & DataExporter::REDUNDANT) || if (loc > 0 && (!(results & DataExporter::REDUNDANT) ||
sim->getGlobalProcessID() == 0)) // we own the patch sim->getGlobalProcessID() == 0)) // we own the patch
{ {
if (abs(results) & DataExporter::PRIMARY) { ASMbase* pch = sim->getPatch(loc);
if (results & DataExporter::PRIMARY) {
Vector psol; Vector psol;
int ncmps = entry.second.ncmps; int ncmps = entry.second.ncmps;
if (entry.second.results < 0) { // field assumed to be on basis 1 for now if (entry.second.results < 0) { // field assumed to be on basis 1 for now
size_t ndof1 = sim->extractPatchSolution(*sol, psol, loc-1, ncmps, 1); size_t ndof1 = sim->extractPatchSolution(*sol,psol,pch,ncmps,1);
writeArray(group2, entry.second.description, writeArray(group2, entry.second.description,
ndof1, psol.ptr(), H5T_NATIVE_DOUBLE); ndof1, psol.ptr(), H5T_NATIVE_DOUBLE);
} else { } else {
size_t ndof1 = sim->extractPatchSolution(*sol,psol,loc-1,ncmps); size_t ndof1 = sim->extractPatchSolution(*sol,psol,pch,ncmps);
if (sim->mixedProblem()) if (sim->mixedProblem())
{ {
size_t ofs = 0; size_t ofs = 0;
for (size_t b=1; b <= sim->getNoBasis(); ++b) { for (size_t b=1; b <= sim->getNoBasis(); ++b) {
ndof1 = sim->getPatch(loc)->getNoNodes(b)*sim->getPatch(loc)->getNoFields(b); ndof1 = pch->getNoNodes(b)*pch->getNoFields(b);
writeArray(group2,prefix+prob->getField1Name(10+b),ndof1, writeArray(group2,prefix+prob->getField1Name(10+b),ndof1,
psol.ptr()+ofs,H5T_NATIVE_DOUBLE); psol.ptr()+ofs,H5T_NATIVE_DOUBLE);
ofs += ndof1; ofs += ndof1;
@ -449,16 +423,16 @@ void HDF5Writer::writeSIM (int level, const DataEntry& entry,
} }
} }
if (abs(results) & DataExporter::SECONDARY) { if (results & DataExporter::SECONDARY) {
Matrix field; Matrix field;
if (prefix.empty()) { if (prefix.empty()) {
sim->setMode(SIM::RECOVERY); const_cast<SIMbase*>(sim)->setMode(SIM::RECOVERY);
sim->extractPatchSolution(Vectors(1,*sol), loc-1); sim->extractPatchSolution(Vectors(1,*sol), loc-1);
sim->evalSecondarySolution(field,loc-1); sim->evalSecondarySolution(field,loc-1);
} }
else { else {
Vector locvec; Vector locvec;
sim->extractPatchSolution(*sol,locvec,loc-1,prob->getNoFields(2)); sim->extractPatchSolution(*sol,locvec,pch,prob->getNoFields(2));
field.resize(prob->getNoFields(2),locvec.size()/prob->getNoFields(2)); field.resize(prob->getNoFields(2),locvec.size()/prob->getNoFields(2));
field.fill(locvec.ptr()); field.fill(locvec.ptr());
} }
@ -467,7 +441,7 @@ void HDF5Writer::writeSIM (int level, const DataEntry& entry,
field.getRow(j+1).ptr(),H5T_NATIVE_DOUBLE); field.getRow(j+1).ptr(),H5T_NATIVE_DOUBLE);
} }
if (abs(results) & DataExporter::NORMS && norm) { if (results & DataExporter::NORMS && norm) {
Matrix patchEnorm; Matrix patchEnorm;
sim->extractPatchElmRes(eNorm,patchEnorm,loc-1); sim->extractPatchElmRes(eNorm,patchEnorm,loc-1);
for (j = l = 1; j <= norm->getNoFields(0); j++) for (j = l = 1; j <= norm->getNoFields(0); j++)
@ -478,13 +452,13 @@ void HDF5Writer::writeSIM (int level, const DataEntry& entry,
patchEnorm.cols(),patchEnorm.getRow(l++).ptr(), patchEnorm.cols(),patchEnorm.getRow(l++).ptr(),
H5T_NATIVE_DOUBLE); H5T_NATIVE_DOUBLE);
} }
if (abs(results) & DataExporter::EIGENMODES) { if (results & DataExporter::EIGENMODES) {
const std::vector<Mode>* vec2 = static_cast<const std::vector<Mode>* >(entry.second.data2); const std::vector<Mode>* vec2 = static_cast<const std::vector<Mode>*>(entry.second.data2);
const std::vector<Mode>& vec = static_cast<const std::vector<Mode>& >(*vec2); const std::vector<Mode>& vec = static_cast<const std::vector<Mode>&>(*vec2);
H5Gclose(group2); H5Gclose(group2);
for (k = 0; k < vec.size(); ++k) { for (k = 0; k < vec.size(); ++k) {
Vector psol; Vector psol;
size_t ndof1 = sim->extractPatchSolution(vec[k].eigVec,psol,loc-1); size_t ndof1 = sim->extractPatchSolution(vec[k].eigVec,psol,pch);
std::stringstream name; std::stringstream name;
name << entry.second.description << "-" << k+1; name << entry.second.description << "-" << k+1;
std::stringstream str; std::stringstream str;
@ -514,7 +488,7 @@ void HDF5Writer::writeSIM (int level, const DataEntry& entry,
else // must write empty dummy records for the other patches else // must write empty dummy records for the other patches
{ {
double dummy; double dummy;
if (abs(results) & DataExporter::PRIMARY) { if (results & DataExporter::PRIMARY) {
if (entry.second.results < 0) { if (entry.second.results < 0) {
writeArray(group2, entry.second.description, writeArray(group2, entry.second.description,
0, &dummy, H5T_NATIVE_DOUBLE); 0, &dummy, H5T_NATIVE_DOUBLE);
@ -530,11 +504,11 @@ void HDF5Writer::writeSIM (int level, const DataEntry& entry,
0, &dummy, H5T_NATIVE_DOUBLE); 0, &dummy, H5T_NATIVE_DOUBLE);
} }
if (abs(results) & DataExporter::SECONDARY) if (results & DataExporter::SECONDARY)
for (j = 0; j < prob->getNoFields(2); j++) for (j = 0; j < prob->getNoFields(2); j++)
writeArray(group2,prefix+prob->getField2Name(j),0,&dummy,H5T_NATIVE_DOUBLE); writeArray(group2,prefix+prob->getField2Name(j),0,&dummy,H5T_NATIVE_DOUBLE);
if (abs(results) & DataExporter::NORMS && norm) if (results & DataExporter::NORMS && norm)
for (j = l = 1; j <= norm->getNoFields(0); j++) for (j = l = 1; j <= norm->getNoFields(0); j++)
for (k = 1; k <= norm->getNoFields(j); k++) for (k = 1; k <= norm->getNoFields(j); k++)
if (norm->hasElementContributions(j,k)) if (norm->hasElementContributions(j,k))
@ -544,29 +518,23 @@ void HDF5Writer::writeSIM (int level, const DataEntry& entry,
} }
H5Gclose(group2); H5Gclose(group2);
} }
delete norm;
#else #else
std::cout << "HDF5Writer: compiled without HDF5 support, no data written" << std::endl; std::cout << "HDF5Writer: compiled without HDF5 support, no data written" << std::endl;
#endif #endif
delete norm;
} }
void HDF5Writer::writeKnotspan (int level, const DataEntry& entry, void HDF5Writer::writeKnotspan (int level, const DataEntry& entry,
const std::string& prefix) const std::string& prefix)
{ {
SIMbase* sim = static_cast<SIMbase*>(const_cast<void*>(entry.second.data)); const SIMbase* sim = static_cast<const SIMbase*>(entry.second.data);
const Vector* sol = static_cast<const Vector*>(entry.second.data2); const Vector* sol = static_cast<const Vector*>(entry.second.data2);
if (!sim || !sol) return; if (!sim || !sol) return;
Matrix infield(1,sol->size()); Matrix infield(1,sol->size());
infield.fillRow(1,sol->ptr()); infield.fillRow(1,sol->ptr());
std::string basisname;
if (prefix.empty())
basisname = sim->getName()+"-1";
else
basisname = prefix+sim->getName()+"-1";
#ifdef HAS_HDF5 #ifdef HAS_HDF5
for (int i = 0; i < sim->getNoPatches(); ++i) { for (int i = 0; i < sim->getNoPatches(); ++i) {
std::stringstream str; std::stringstream str;
@ -600,7 +568,7 @@ void HDF5Writer::writeKnotspan (int level, const DataEntry& entry,
} }
void HDF5Writer::writeBasis (SIMbase* sim, const std::string& name, void HDF5Writer::writeBasis (const SIMbase* sim, const std::string& name,
int basis, int level, bool redundant) int basis, int level, bool redundant)
{ {
#ifdef HAS_HDF5 #ifdef HAS_HDF5
@ -792,27 +760,22 @@ bool HDF5Writer::writeRestartData(int level, const DataExporter::SerializeData&
pid = m_adm.getProcId(); pid = m_adm.getProcId();
ptot = m_adm.getNoProcs(); ptot = m_adm.getNoProcs();
#endif #endif
for (int p = 0; p < ptot; ++p) { for (int p = 0; p < ptot; p++)
for (auto& it : data) { for (const std::pair<std::string,std::string>& it : data) {
std::stringstream str; std::stringstream str;
str << level << '/' << p; str << level << '/' << p;
int group; int group;
if (checkGroupExistence(m_restart_file,str.str().c_str())) if (checkGroupExistence(m_restart_file,str.str().c_str()))
group = H5Gopen2(m_restart_file,str.str().c_str(),H5P_DEFAULT); group = H5Gopen2(m_restart_file,str.str().c_str(),H5P_DEFAULT);
else else
group = H5Gcreate2(m_restart_file,str.str().c_str(),0,H5P_DEFAULT,H5P_DEFAULT); group = H5Gcreate2(m_restart_file,str.str().c_str(),0,H5P_DEFAULT,H5P_DEFAULT);
if (!H5Lexists(group, it.first.c_str(), 0)) { if (!H5Lexists(group, it.first.c_str(), 0)) {
if (pid == p) int len = pid == p ? it.second.size() : 0;
writeArray(group, it.first, it.second.size(), it.second.data(), H5T_NATIVE_CHAR); writeArray(group, it.first, len, it.second.data(), H5T_NATIVE_CHAR);
else
writeArray(group, it.first, 0, nullptr, H5T_NATIVE_CHAR);
} }
H5Gclose(group); H5Gclose(group);
} }
}
H5Fclose(m_restart_file); H5Fclose(m_restart_file);
m_restart_file = 0; m_restart_file = 0;
#else #else
@ -823,11 +786,8 @@ bool HDF5Writer::writeRestartData(int level, const DataExporter::SerializeData&
} }
//! \brief A struct holding the context for a restart. //! \brief Convenience type for restart IO.
struct read_restart_ctx { typedef std::pair<HDF5Writer*,DataExporter::SerializeData*> read_restart_ctx;
HDF5Writer* w; //!< HDF5 reader/writer to use
DataExporter::SerializeData* data; //!< The serialized data
};
#ifdef HAS_HDF5 #ifdef HAS_HDF5
@ -837,11 +797,8 @@ static herr_t read_restart_data(hid_t group_id, const char* member_name, void* d
char* c; char* c;
int len; int len;
ctx->w->readArray(group_id, member_name, len, c); ctx->first->readArray(group_id,member_name,len,c);
std::string tmp; ctx->second->insert(std::make_pair(std::string(member_name),std::string(c,len)));
tmp.resize(len);
tmp.assign(c, len);
ctx->data->insert(std::make_pair(std::string(member_name),tmp));
return 0; return 0;
} }
#endif #endif
@ -863,16 +820,14 @@ int HDF5Writer::readRestartData(DataExporter::SerializeData& data, int level)
} }
std::stringstream str; std::stringstream str;
str << '/' << level << '/' str << '/' << level << '/';
#ifdef HAVE_MPI #ifdef HAVE_MPI
<< m_adm.getProcId(); str << m_adm.getProcId();
#else #else
<< 0; str << 0;
#endif #endif
int idx = 0; int idx = 0;
read_restart_ctx ctx; read_restart_ctx ctx(this,&data);
ctx.w = this;
ctx.data = &data;
int it = H5Giterate(m_file, str.str().c_str(), &idx, read_restart_data, &ctx); int it = H5Giterate(m_file, str.str().c_str(), &idx, read_restart_data, &ctx);
closeFile(0); closeFile(0);
return it < 0 ? it : level; return it < 0 ? it : level;

View File

@ -31,12 +31,12 @@ class HDF5Writer : public DataWriter
{ {
public: public:
//! \brief The constructor opens a named HDF5-file. //! \brief The constructor opens a named HDF5-file.
//! \param[in] name The name (filename without extension) of data file //! \param[in] name The name (without extension) of the data file
//! \param[in] adm The process administrator //! \param[in] adm The process administrator
//! \param[in] append Whether to append to or overwrite an existing file //! \param[in] append Whether to append to or overwrite an existing file
//! \param[in] keepopen Whether to always keep the HDF5 open //! \param[in] keepopen Whether to always keep the HDF5 open
HDF5Writer(const std::string& name, const ProcessAdm& adm, bool append = false, HDF5Writer(const std::string& name, const ProcessAdm& adm,
bool keepopen = false); bool append = false, bool keepopen = false);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~HDF5Writer() {} virtual ~HDF5Writer() {}
@ -46,7 +46,7 @@ public:
//! \brief Opens the file at a given time level. //! \brief Opens the file at a given time level.
//! \param[in] level The requested time level //! \param[in] level The requested time level
virtual void openFile(int level) { openFile(level, false); } virtual void openFile(int level) { this->openFile(level,false); }
//! \brief Opens the file at a given time level. //! \brief Opens the file at a given time level.
//! \param[in] level The requested time level //! \param[in] level The requested time level
@ -70,7 +70,7 @@ public:
//! \brief Writes data from a SIM to file. //! \brief Writes data from a SIM to file.
//! \param[in] level The time level to write the data at //! \param[in] level The time level to write the data at
//! \param[in] entry The DataEntry describing the vector //! \param[in] entry The DataEntry describing the data to write
//! \param[in] geometryUpdated Whether or not geometries should be written //! \param[in] geometryUpdated Whether or not geometries should be written
//! \param[in] prefix Field name prefix //! \param[in] prefix Field name prefix
//! //!
@ -82,7 +82,7 @@ public:
//! \brief Writes nodal forces to file. //! \brief Writes nodal forces to file.
//! \param[in] level The time level to write the data at //! \param[in] level The time level to write the data at
//! \param[in] entry The DataEntry describing the vector //! \param[in] entry The DataEntry describing the data to write
virtual void writeNodalForces(int level, const DataEntry& entry); virtual void writeNodalForces(int level, const DataEntry& entry);
//! \brief Writes knot span field to file. //! \brief Writes knot span field to file.
@ -92,7 +92,7 @@ public:
virtual void writeKnotspan(int level, const DataEntry& entry, virtual void writeKnotspan(int level, const DataEntry& entry,
const std::string& prefix); const std::string& prefix);
//! \brief Write a basis to file //! \brief Writes a basis to file.
//! \param[in] level The time level to write the basis at //! \param[in] level The time level to write the basis at
//! \param[in] entry The DataEntry describing the basis //! \param[in] entry The DataEntry describing the basis
//! \param[in] prefix Prefix for basis //! \param[in] prefix Prefix for basis
@ -140,26 +140,26 @@ public:
//! \param[in] basisName Check for a particular basis //! \param[in] basisName Check for a particular basis
bool hasGeometries(int level, const std::string& basisName = ""); bool hasGeometries(int level, const std::string& basisName = "");
//! \brief Write restart data. //! \brief Writes restart data to file.
//! \param level Level to write data at //! \param[in] level Level to write data at
//! \param data Data to write //! \param[in] data Data to write
bool writeRestartData(int level, const DataExporter::SerializeData& data); bool writeRestartData(int level, const DataExporter::SerializeData& data);
//! \brief Read restart data from file. //! \brief Reads restart data from file.
//! \param data The map to store data in //! \param[out] data The map to store data in
//! \param level Level to read (-1 to read last level in file) //! \param[in] level Level to read (-1 to read last level in file)
//! \returns Negative value on error, else restart level loaded //! \returns Negative value on error, else restart level loaded
int readRestartData(DataExporter::SerializeData& data, int level = -1); int readRestartData(DataExporter::SerializeData& data, int level = -1);
//! \brief Internal helper function. Reads an array into an array of chars. //! \brief Internal helper function reading into an array of chars.
//! \param[in] group The HDF5 group to read data from //! \param[in] group The HDF5 group to read data from
//! \param[in] name The name of the array //! \param[in] name The name of the array
//! \param[in] len The length of the data to read //! \param[out] len The length of the data read
//! \param[out] data The array to read data into //! \param[out] data The array to read data into
void readArray(int group, const std::string& name, int& len, char*& data); void readArray(int group, const std::string& name, int& len, char*& data);
protected: protected:
//! \brief Internal helper function. Writes a data array to HDF5 file. //! \brief Internal helper function writing a data array to file.
//! \param[in] group The HDF5 group to write data into //! \param[in] group The HDF5 group to write data into
//! \param[in] name The name of the array //! \param[in] name The name of the array
//! \param[in] len The length of the array //! \param[in] len The length of the array
@ -168,30 +168,30 @@ protected:
void writeArray(int group, const std::string& name, void writeArray(int group, const std::string& name,
int len, const void* data, int type); int len, const void* data, int type);
//! \brief Internal helper function. Writes a SIM's basis (geometry) to file. //! \brief Internal helper function writing a SIM's basis (geometry) to file.
//! \param[in] SIM The SIM we want to write basis for //! \param[in] SIM The SIM we want to write basis for
//! \param[in] name The name of the basis //! \param[in] name The name of the basis
//! \param[in] basis 1/2 Write primary or secondary basis from SIM //! \param[in] basis 1/2 Write primary or secondary basis from SIM
//! \param[in] level The time level to write the basis at //! \param[in] level The time level to write the basis at
//! \param[in] redundant Whether or not basis is redundant across processes //! \param[in] redundant Whether or not basis is redundant across processes
void writeBasis(SIMbase* SIM, const std::string& name, int basis, void writeBasis(const SIMbase* SIM, const std::string& name,
int level, bool redundant=false); int basis, int level, bool redundant = false);
//! \brief Internal helper function. Reads an array into a array of doubles. //! \brief Internal helper function reading into an array of doubles.
//! \param[in] group The HDF5 group to read data from //! \param[in] group The HDF5 group to read data from
//! \param[in] name The name of the array //! \param[in] name The name of the array
//! \param[in] len The length of the data to read //! \param[out] len The length of the data read
//! \param[out] data The array to read data into //! \param[out] data The array to read data into
void readArray(int group, const std::string& name, int& len, double*& data); void readArray(int group, const std::string& name, int& len, double*& data);
//! \brief Internal helper function. Reads an array into a array of integers. //! \brief Internal helper function reading into an array of integers.
//! \param[in] group The HDF5 group to read data from //! \param[in] group The HDF5 group to read data from
//! \param[in] name The name of the array //! \param[in] name The name of the array
//! \param[in] len The length of the data to read //! \param[out] len The length of the data read
//! \param[out] data The array to read data into //! \param[out] data The array to read data into
void readArray(int group, const std::string& name, int& len, int*& data); void readArray(int group, const std::string& name, int& len, int*& data);
//! \brief Internal helper function. Checks if a group exists in the file. //! \brief Internal helper function checking if a group exists in the file.
//! \param[in] parent The HDF5 group of the parent //! \param[in] parent The HDF5 group of the parent
//! \param[in] group The name of the group to check for //! \param[in] group The name of the group to check for
//! \return \e true if group exists, otherwise \e false //! \return \e true if group exists, otherwise \e false