Skip to content

Commit 9a73525

Browse files
committed
Added: Option to merge multi-patches into a single VTF part
1 parent 7f0a806 commit 9a73525

2 files changed

Lines changed: 135 additions & 21 deletions

File tree

src/SIM/SIMoutput.C

Lines changed: 132 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ SIMoutput::SIMoutput (IntegrandBase* itg) : SIMinput(itg)
3737
myPtSize = 0.0;
3838
myGeomID = myGeofs1 = myGeofs2 = 0;
3939
myVtf = nullptr;
40-
logRpMap = false;
40+
mergeVtf = logRpMap = false;
4141
idxGrid = -1;
4242
}
4343

4444

4545
SIMoutput::~SIMoutput ()
4646
{
47-
if (myVtf) delete myVtf;
47+
delete myVtf;
4848

4949
for (std::pair<const std::string,RealFunc*>& func : myAddScalars)
5050
delete func.second;
@@ -106,6 +106,7 @@ bool SIMoutput::parseOutputTag (const tinyxml2::XMLElement* elem)
106106
{
107107
IFEM::cout <<" Parsing <"<< elem->Value() <<">"<< std::endl;
108108

109+
bool newGroup = false;
109110
if (const char* funcval = utl::getValue(elem,"function"); funcval)
110111
{
111112
std::string name;
@@ -122,10 +123,14 @@ bool SIMoutput::parseOutputTag (const tinyxml2::XMLElement* elem)
122123
myAddScalars[name] = f;
123124
return true;
124125
}
125-
else if (strcasecmp(elem->Value(),"resultpoints"))
126+
else if (!strcasecmp(elem->Value(),"resultpoints"))
127+
newGroup = true; // we are parsing result points, below
128+
else if (!strcasecmp(elem->Value(),"vtfformat"))
129+
utl::getAttribute(elem,"merge",mergeVtf);
130+
131+
if (!newGroup)
126132
return this->SIMinput::parseOutputTag(elem);
127133

128-
bool newGroup = true;
129134
// Lambda function for adding a new result point to the myPoints container.
130135
auto&& addPoint = [&newGroup,&points=myPoints](const ResultPoint& newPoint)
131136
{
@@ -711,12 +716,18 @@ bool SIMoutput::writeGlvG (int& nBlock, double time)
711716
// Get the ID list of current node blocks, if any
712717
IntVec nodeBlocks;
713718
int i, nodeBlock;
719+
size_t nNodeLast = 0;
714720
if (time > 0.0)
721+
{
715722
for (i = 1; (nodeBlock = myVtf->getNodeBlock(i)); i++)
716723
nodeBlocks.push_back(nodeBlock);
724+
if (mergeVtf) // Get the size of the last node block written
725+
nNodeLast = myVtf->getBlock(i-1)->getNoNodes();
726+
}
717727
if (time >= 0.0)
718728
myVtf->clearGeometryBlocks();
719729

730+
ElementBlock* singlePart = nullptr;
720731
ElementBlock* lvb;
721732
char pname[64];
722733

@@ -737,14 +748,40 @@ bool SIMoutput::writeGlvG (int& nBlock, double time)
737748
if (!pch->isElementActive(iel-1,time))
738749
lvb->removeElement(iel);
739750

751+
if (mergeVtf && myModel.size() > 1)
752+
{
753+
// Merge all element blocks into a single part
754+
if (!singlePart)
755+
singlePart = lvb;
756+
else
757+
{
758+
singlePart->merge(*lvb,false);
759+
delete lvb;
760+
}
761+
}
762+
else
763+
{
764+
if (msgLevel > 1)
765+
IFEM::cout <<"Writing geometry for patch "
766+
<< pch->idx+1 <<" ("<< lvb->getNoNodes() <<")"<< std::endl;
767+
768+
sprintf(pname,"Patch %zu",pch->idx+1);
769+
// Reuse the existing node block when time > 0.0
770+
nodeBlock = i < static_cast<int>(nodeBlocks.size()) ? nodeBlocks[i++] : 0;
771+
if (!myVtf->writeGrid(lvb,pname,++nBlock,nodeBlock))
772+
return false;
773+
}
774+
}
775+
776+
if (singlePart)
777+
{
740778
if (msgLevel > 1)
741-
IFEM::cout <<"Writing geometry for patch "
742-
<< pch->idx+1 <<" ("<< lvb->getNoNodes() <<")"<< std::endl;
779+
IFEM::cout <<"Writing new geometry ("
780+
<< singlePart->getNoNodes() <<")"<< std::endl;
743781

744-
sprintf(pname,"Patch %zu",pch->idx+1);
745-
// Reuse the existing node block when time > 0.0
746-
nodeBlock = i < static_cast<int>(nodeBlocks.size()) ? nodeBlocks[i++] : 0;
747-
if (!myVtf->writeGrid(lvb,pname,++nBlock,nodeBlock))
782+
// Reuse the last node block when time > 0.0 unless increased size
783+
nodeBlock = singlePart->getNoNodes() > nNodeLast ? 0 : nodeBlocks.back();
784+
if (!myVtf->writeGrid(singlePart,"FE model",++nBlock,nodeBlock))
748785
return false;
749786
}
750787

@@ -795,6 +832,8 @@ bool SIMoutput::writeGlvBC (int& nBlock, int iStep) const
795832
{
796833
if (!myVtf)
797834
return true;
835+
if (mergeVtf && myModel.size() > 1)
836+
return true; // not implemented for merged patches, ignore
798837

799838
Matrix field;
800839
std::array<IntVec,6> dID;
@@ -933,6 +972,8 @@ bool SIMoutput::writeGlvV (const RealArray& vec, const char* fieldName,
933972
{
934973
if (vec.empty() || !myVtf)
935974
return true;
975+
if (mergeVtf && myModel.size() > 1)
976+
return true; // not implemented for merged patches, ignore
936977

937978
Matrix field;
938979
Vector lovec;
@@ -973,6 +1014,8 @@ bool SIMoutput::writeGlvS (const Vector& scl, const char* fieldName,
9731014
{
9741015
if (scl.empty() || !myVtf)
9751016
return true;
1017+
if (mergeVtf && myModel.size() > 1)
1018+
return false; // not implemented for merged patches, abort..
9761019

9771020
const bool piolaMapping = myProblem ?
9781021
myProblem->getIntegrandType() & Integrand::PIOLA_MAPPING : false;
@@ -1086,6 +1129,14 @@ int SIMoutput::writeGlvS1 (const Vector& psol, int iStep, int& nBlock,
10861129
if (myVtf->getBlock(geo))
10871130
vID[0].push_back(dis);
10881131

1132+
// Find the last active patch at current time
1133+
size_t lastActive = 0;
1134+
if (mergeVtf)
1135+
for (const ASMbase* pch : myModel)
1136+
if (!pch->empty() && !pch->inActive(time))
1137+
lastActive = pch->idx;
1138+
1139+
Matrix singleField;
10891140
Matrix field;
10901141
Vector lovec;
10911142

@@ -1109,6 +1160,19 @@ int SIMoutput::writeGlvS1 (const Vector& psol, int iStep, int& nBlock,
11091160
if (!pch->evalSolution(field,lovec,opt.nViz,0,piolaMapping))
11101161
return -1;
11111162

1163+
if (lastActive > 0)
1164+
{
1165+
// We need to merge the results for all patches before writing them
1166+
if (singleField.empty())
1167+
std::swap(singleField,field);
1168+
else
1169+
singleField.augmentCols(field);
1170+
if (lastActive == pch->idx)
1171+
std::swap(field,singleField);
1172+
else
1173+
continue;
1174+
}
1175+
11121176
const ElementBlock* grid = myVtf->getBlock(++geomID);
11131177
pch->filterResults(field,grid);
11141178

@@ -1280,6 +1344,14 @@ int SIMoutput::writeGlvS2 (const Vector& psol, int iStep, int& nBlock,
12801344
std::vector<IntVec> sID;
12811345
sID.reserve((haveAsol ? 2*nf : nf) + nProj);
12821346

1347+
// Find the last active patch at current time
1348+
size_t lastActive = 0;
1349+
if (mergeVtf)
1350+
for (const ASMbase* pch : myModel)
1351+
if (!pch->empty() && !pch->inActive(time))
1352+
lastActive = pch->idx;
1353+
1354+
Matrix singleField, projField;
12831355
Matrix field, pdir;
12841356
Vector lovec;
12851357

@@ -1294,7 +1366,7 @@ int SIMoutput::writeGlvS2 (const Vector& psol, int iStep, int& nBlock,
12941366
else if (pch->empty() || pch->inActive(time))
12951367
continue; // skip empty and inactive patches
12961368

1297-
myProblem->initResultPoints(time,true); // include principal stresses
1369+
myProblem->initResultPoints(time,!lastActive); // include principal stresses
12981370
if (!this->initPatchForEvaluation(pch->idx+1))
12991371
return -2;
13001372

@@ -1307,12 +1379,29 @@ int SIMoutput::writeGlvS2 (const Vector& psol, int iStep, int& nBlock,
13071379
if (!pch->evalSolution(field,*myProblem,opt.nViz))
13081380
return -1;
13091381

1310-
const ElementBlock* grid = myVtf->getBlock(++geomID);
1311-
pch->filterResults(field,grid);
1312-
13131382
size_t k = 0;
1314-
if (!this->writeScalarFields(field,geomID,nBlock,sID,&k,ASM::SECONDARY))
1315-
return -4;
1383+
bool writeNow = true;
1384+
if (lastActive > 0)
1385+
{
1386+
// We need to merge the results for all patches before writing them
1387+
if (singleField.empty())
1388+
std::swap(singleField,field);
1389+
else
1390+
singleField.augmentCols(field);
1391+
if (lastActive == pch->idx)
1392+
std::swap(field,singleField);
1393+
else
1394+
writeNow = false;
1395+
}
1396+
1397+
const ElementBlock* grid = writeNow ? myVtf->getBlock(++geomID) : nullptr;
1398+
1399+
if (writeNow)
1400+
{
1401+
pch->filterResults(field,grid);
1402+
if (!this->writeScalarFields(field,geomID,nBlock,sID,&k,ASM::SECONDARY))
1403+
return -4;
1404+
}
13161405

13171406
// Write principal directions, if any, as vector fields
13181407

@@ -1334,9 +1423,23 @@ int SIMoutput::writeGlvS2 (const Vector& psol, int iStep, int& nBlock,
13341423
if (!pch->evalSolution(field,*myProblem,opt.nViz,'D'))
13351424
return -1;
13361425

1337-
pch->filterResults(field,grid);
1338-
if (!this->writeScalarFields(field,geomID,nBlock,sID,&k,ASM::PROJECTED))
1339-
return -4;
1426+
if (lastActive > 0)
1427+
{
1428+
// We need to merge the results for all patches before writing them
1429+
if (projField.empty())
1430+
std::swap(projField,field);
1431+
else
1432+
projField.augmentCols(field);
1433+
if (lastActive == pch->idx)
1434+
std::swap(field,projField);
1435+
}
1436+
1437+
if (writeNow)
1438+
{
1439+
pch->filterResults(field,grid);
1440+
if (!this->writeScalarFields(field,geomID,nBlock,sID,&k,ASM::PROJECTED))
1441+
return -4;
1442+
}
13401443
}
13411444

13421445
if (haveAsol && grid)
@@ -1445,6 +1548,8 @@ bool SIMoutput::writeGlvP (const RealArray& ssol, int iStep, int& nBlock,
14451548
{
14461549
if (ssol.empty() || !myVtf)
14471550
return true; // no projected solution
1551+
if (mergeVtf && myModel.size() > 1)
1552+
return true; // not implemented for merged patches, ignore
14481553

14491554
// Lambda function for updating (patch-wise) maximum result values.
14501555
auto&& updateMaxVal = [](PointValues& maxVal, double res,
@@ -1547,6 +1652,8 @@ bool SIMoutput::writeGlvF (const RealFunc& f, const char* fname,
15471652
{
15481653
if (!myVtf)
15491654
return true;
1655+
if (mergeVtf && myModel.size() > 1)
1656+
return true; // not implemented for merged patches, ignore
15501657

15511658
const bool piolaMapping = state && myProblem ?
15521659
myProblem->getIntegrandType() & Integrand::PIOLA_MAPPING : false;
@@ -1607,6 +1714,8 @@ bool SIMoutput::writeGlvM (const Mode& mode, bool freq, int& nBlock)
16071714
{
16081715
if (mode.eigVec.empty() || !myVtf)
16091716
return true; // no eigen modes
1717+
if (mergeVtf && myModel.size() > 1)
1718+
return true; // not implemented for merged patches, ignore
16101719

16111720
if (msgLevel > 1)
16121721
IFEM::cout <<"Writing eigenvector for Mode "<< mode.eigNo << std::endl;
@@ -1683,6 +1792,8 @@ bool SIMoutput::writeGlvN (const Matrix& norms, int iStep, int& nBlock,
16831792
{
16841793
if (norms.empty() || !myVtf)
16851794
return true; // no element norms
1795+
if (mergeVtf && myModel.size() > 1)
1796+
return true; // not implemented for merged patches, ignore
16861797

16871798
NormBase* norm = myProblem->getNormIntegrand(mySol);
16881799

@@ -1781,6 +1892,8 @@ bool SIMoutput::writeGlvE (const Vector& field, int iStep, int& nBlock,
17811892
{
17821893
if (!myVtf)
17831894
return true;
1895+
if (mergeVtf && myModel.size() > 1)
1896+
return true; // not implemented for merged patches, ignore
17841897

17851898
Vector lVec;
17861899
IntVec sID;

src/SIM/SIMoutput.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,9 +433,10 @@ class SIMoutput : public SIMinput
433433
int myPrec; //!< Output precision for result sampling
434434
double myPtSize; //!< Size of result point visualization in VTF-file
435435
int myGeomID; //!< Geometry block ID for the first patch in the VTF-file
436-
int myGeofs1; //!< Geometry block ID offset for immersed geometry in the VTF-file
437-
int myGeofs2; //!< Geometry block ID offset for extra geometry in the VTF-file
436+
int myGeofs1; //!< ID offset for immersed geometry block in the VTF-file
437+
int myGeofs2; //!< ID offset for extra geometry block in the VTF-file
438438
VTF* myVtf; //!< VTF-file for result visualization
439+
bool mergeVtf; //!< If \e true, merge multi-patches into one on the VTF-file
439440
bool logRpMap; //!< If \e true, print out the result point mapping
440441
int idxGrid; //!< Index into \ref myPoints for grid result output
441442
};

0 commit comments

Comments
 (0)