Added: Input of unstructured Lagrange mesh from xml-file
This commit is contained in:
parent
cf3261fa12
commit
a73c1b5a12
@ -32,7 +32,9 @@ ASMbase* ASM1D::create (ASM::Discretization discretization,
|
|||||||
return new ASMs1DC1(nd,nf);
|
return new ASMs1DC1(nd,nf);
|
||||||
|
|
||||||
case ASM::Lagrange:
|
case ASM::Lagrange:
|
||||||
if (nf > 10) // hack for mesh input from file
|
if (nf > 20) // hack for mesh input from XML-file
|
||||||
|
return new ASMu1DLag(nd,nf-20,'x');
|
||||||
|
else if (nf > 10) // hack for mesh input from Matlab file
|
||||||
return new ASMu1DLag(nd,nf-10,'m');
|
return new ASMu1DLag(nd,nf-10,'m');
|
||||||
else
|
else
|
||||||
return new ASMs1DLag(nd,nf);
|
return new ASMs1DLag(nd,nf);
|
||||||
|
@ -43,6 +43,9 @@ bool ASMu1DLag::read (std::istream& is)
|
|||||||
case 'm':
|
case 'm':
|
||||||
case 'M':
|
case 'M':
|
||||||
return ASM::readMatlab(is,myMNPC,myCoord,nodeSets);
|
return ASM::readMatlab(is,myMNPC,myCoord,nodeSets);
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
return ASM::readXML(is,myMNPC,myCoord,nodeSets,&elemSets);
|
||||||
default:
|
default:
|
||||||
std::cerr <<" *** ASMu1DLag::read: Undefined file format."<< std::endl;
|
std::cerr <<" *** ASMu1DLag::read: Undefined file format."<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -66,6 +66,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
char fileType; //!< Mesh file format
|
char fileType; //!< Mesh file format
|
||||||
std::vector<ASM::NodeSet> nodeSets; //!< Node sets for Dirichlet BCs
|
std::vector<ASM::NodeSet> nodeSets; //!< Node sets for Dirichlet BCs
|
||||||
|
std::vector<ASM::NodeSet> elemSets; //!< Element sets for properties
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,6 +43,9 @@ bool ASMu2DLag::read (std::istream& is)
|
|||||||
case 'm':
|
case 'm':
|
||||||
case 'M':
|
case 'M':
|
||||||
return ASM::readMatlab(is,myMNPC,myCoord,nodeSets);
|
return ASM::readMatlab(is,myMNPC,myCoord,nodeSets);
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
return ASM::readXML(is,myMNPC,myCoord,nodeSets);
|
||||||
default:
|
default:
|
||||||
std::cerr <<" *** ASMu2DLag::read: Undefined file format."<< std::endl;
|
std::cerr <<" *** ASMu2DLag::read: Undefined file format."<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -12,9 +12,12 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include "ASMutils.h"
|
#include "ASMutils.h"
|
||||||
|
#include "Utilities.h"
|
||||||
#include "Vec3Oper.h"
|
#include "Vec3Oper.h"
|
||||||
#include "Vec3.h"
|
#include "Vec3.h"
|
||||||
|
#include "tinyxml.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <cstring>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
|
|
||||||
@ -135,3 +138,118 @@ bool ASM::readMatlab (std::istream& is, IntMat& MNPC, std::vector<Vec3>& nodes,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ASM::readXML (std::istream& is, IntMat& MNPC, std::vector<Vec3>& nodes,
|
||||||
|
std::vector<NodeSet>& nodeSets,
|
||||||
|
std::vector<NodeSet>* elemSets)
|
||||||
|
{
|
||||||
|
char cline[128];
|
||||||
|
if (!is.getline(cline,128))
|
||||||
|
return false;
|
||||||
|
else if (!strstr(cline,"<patch>"))
|
||||||
|
{
|
||||||
|
std::cerr <<" *** ASM::readXML: Failed to read patch geometry."<< std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string data("<patch>\n");
|
||||||
|
while (is.getline(cline,128))
|
||||||
|
{
|
||||||
|
data.append(cline);
|
||||||
|
data.append("\n");
|
||||||
|
if (strstr(cline,"</patch>"))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TiXmlDocument doc;
|
||||||
|
doc.Parse(data.c_str(),nullptr,TIXML_ENCODING_UTF8);
|
||||||
|
const TiXmlElement* tag = doc.RootElement();
|
||||||
|
if (!tag)
|
||||||
|
{
|
||||||
|
std::cerr <<" *** ASM::readXML: Malformatted XML input."<< std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lambda function for parsing nodal points from a string.
|
||||||
|
auto&& parseNodes = [&nodes](const char* data)
|
||||||
|
{
|
||||||
|
Vec3 X;
|
||||||
|
std::istringstream iss(data);
|
||||||
|
for (size_t inod = 0; iss; inod++)
|
||||||
|
{
|
||||||
|
iss >> X;
|
||||||
|
if (iss)
|
||||||
|
{
|
||||||
|
#if SP_DEBUG > 1
|
||||||
|
std::cout << inod <<": "<< X << std::endl;
|
||||||
|
#endif
|
||||||
|
nodes.push_back(X);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lambda function for parsing element connectivities from a string.
|
||||||
|
auto&& parseElements = [&MNPC](const char* data, size_t nenod)
|
||||||
|
{
|
||||||
|
IntVec mnpc(nenod);
|
||||||
|
std::istringstream iss(data);
|
||||||
|
for (size_t iel = 0; iss; iel++)
|
||||||
|
{
|
||||||
|
for (int& n : mnpc) iss >> n;
|
||||||
|
if (iss)
|
||||||
|
{
|
||||||
|
#if SP_DEBUG > 1
|
||||||
|
std::cout << iel <<":";
|
||||||
|
for (int n : mnpc) std::cout <<" "<< n;
|
||||||
|
std::cout << std::endl;
|
||||||
|
#endif
|
||||||
|
MNPC.push_back(mnpc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (tag = tag->FirstChildElement(); tag; tag = tag->NextSiblingElement())
|
||||||
|
if (tag->Value() && tag->FirstChild())
|
||||||
|
{
|
||||||
|
std::vector<ASM::NodeSet>* nset = nullptr;
|
||||||
|
if (!strcasecmp(tag->Value(),"nodes"))
|
||||||
|
parseNodes(tag->FirstChild()->Value());
|
||||||
|
else if (!strcasecmp(tag->Value(),"elements"))
|
||||||
|
{
|
||||||
|
size_t nenod = 2;
|
||||||
|
utl::getAttribute(tag,"nenod",nenod);
|
||||||
|
parseElements(tag->FirstChild()->Value(),nenod);
|
||||||
|
}
|
||||||
|
else if (!strcasecmp(tag->Value(),"nodeset"))
|
||||||
|
nset = &nodeSets;
|
||||||
|
else if (!strcasecmp(tag->Value(),"elementset"))
|
||||||
|
nset = elemSets;
|
||||||
|
if (nset)
|
||||||
|
{
|
||||||
|
int node;
|
||||||
|
IntVec nodes;
|
||||||
|
std::string name;
|
||||||
|
utl::getAttribute(tag,"name",name);
|
||||||
|
std::istringstream iss(tag->FirstChild()->Value());
|
||||||
|
iss >> node;
|
||||||
|
while (iss)
|
||||||
|
{
|
||||||
|
nodes.push_back(1+node);
|
||||||
|
iss >> node;
|
||||||
|
}
|
||||||
|
#if SP_DEBUG > 1
|
||||||
|
if (nset == &nodeSets)
|
||||||
|
std::cout <<"Node ";
|
||||||
|
else
|
||||||
|
std::cout <<"Element ";
|
||||||
|
std::cout <<"set \""<< name <<"\":";
|
||||||
|
for (int n : nodes) std::cout <<" "<< n;
|
||||||
|
std::cout << std::endl;
|
||||||
|
#endif
|
||||||
|
nset->push_back(std::make_pair(name,nodes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -31,6 +31,11 @@ namespace ASM
|
|||||||
//! \brief Creates a mesh by reading Matlab commands from an input stream.
|
//! \brief Creates a mesh by reading Matlab commands from an input stream.
|
||||||
bool readMatlab(std::istream& is, IntMat& MNPC, std::vector<Vec3>& nodes,
|
bool readMatlab(std::istream& is, IntMat& MNPC, std::vector<Vec3>& nodes,
|
||||||
std::vector<NodeSet>& nodeSets);
|
std::vector<NodeSet>& nodeSets);
|
||||||
|
|
||||||
|
//! \brief Creates a mesh by reading XML tags from an input stream.
|
||||||
|
bool readXML(std::istream& is, IntMat& MNPC, std::vector<Vec3>& nodes,
|
||||||
|
std::vector<NodeSet>& nodeSets,
|
||||||
|
std::vector<NodeSet>* elemSets = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
52
src/ASM/Test/TestASMu1D.C
Normal file
52
src/ASM/Test/TestASMu1D.C
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//==============================================================================
|
||||||
|
//!
|
||||||
|
//! \file TestASMu1D.C
|
||||||
|
//!
|
||||||
|
//! \date Jun 1 2021
|
||||||
|
//!
|
||||||
|
//! \author Knut Morten Okstad / SINTEF
|
||||||
|
//!
|
||||||
|
//! \brief Tests for unstructured 1D FE models.
|
||||||
|
//!
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include "ASMbase.h"
|
||||||
|
#include "SIM1D.h"
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
|
||||||
|
TEST(TestASMu1D, Read)
|
||||||
|
{
|
||||||
|
std::string xml("<geometry dim='3'><patchfile type='xml'>"
|
||||||
|
" src/ASM/Test/refdata/bridge.xinp"
|
||||||
|
"</patchfile></geometry>");
|
||||||
|
|
||||||
|
SIM1D sim;
|
||||||
|
ASSERT_TRUE(sim.loadXML(xml.c_str()));
|
||||||
|
ASSERT_TRUE(sim.createFEMmodel());
|
||||||
|
|
||||||
|
ASMbase* pch1 = sim.getPatch(1);
|
||||||
|
EXPECT_EQ(pch1->getNoNodes(),58u);
|
||||||
|
EXPECT_EQ(pch1->getNoElms(),40u);
|
||||||
|
|
||||||
|
Vec3 Xn = pch1->getCoord(56);
|
||||||
|
EXPECT_EQ(Xn.x,4.25);
|
||||||
|
EXPECT_EQ(Xn.y,6.25);
|
||||||
|
EXPECT_EQ(Xn.z,2.0);
|
||||||
|
|
||||||
|
Matrix Xe;
|
||||||
|
EXPECT_TRUE(pch1->getElementCoordinates(Xe,2));
|
||||||
|
EXPECT_EQ(Xe.rows(),3U);
|
||||||
|
EXPECT_EQ(Xe.cols(),2U);
|
||||||
|
EXPECT_EQ(Xe(1,1),5.0);
|
||||||
|
EXPECT_EQ(Xe(2,1),10.0);
|
||||||
|
EXPECT_EQ(Xe(3,1),0.0);
|
||||||
|
EXPECT_EQ(Xe(1,2),2.5);
|
||||||
|
EXPECT_EQ(Xe(2,2),10.0);
|
||||||
|
EXPECT_EQ(Xe(3,2),0.0);
|
||||||
|
|
||||||
|
IntVec s3 = {19,20,21,22,23};
|
||||||
|
IntVec S3 = pch1->getNodeSet(pch1->getNodeSetIdx("S03"));
|
||||||
|
EXPECT_TRUE(S3 == s3);
|
||||||
|
}
|
117
src/ASM/Test/refdata/bridge.xinp
Normal file
117
src/ASM/Test/refdata/bridge.xinp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<patch>
|
||||||
|
<nodes>
|
||||||
|
5.0 0.0 0.0
|
||||||
|
5.0 10.0 0.0
|
||||||
|
5.0 1.25 2.0
|
||||||
|
5.0 8.75 2.0
|
||||||
|
2.5 0.0 0.0
|
||||||
|
2.5 10.0 0.0
|
||||||
|
2.5 1.25 2.0
|
||||||
|
2.5 8.75 2.0
|
||||||
|
5.0 1.75 0.0
|
||||||
|
5.0 3.25 0.0
|
||||||
|
4.25 2.5 0.0
|
||||||
|
5.0 2.102500794997615 0.635998728003816
|
||||||
|
5.0 2.897499205002385 0.635998728003816
|
||||||
|
5.0 4.25 0.0
|
||||||
|
5.0 5.75 0.0
|
||||||
|
4.25 5.0 0.0
|
||||||
|
5.0 4.602500794997615 0.635998728003816
|
||||||
|
5.0 5.397499205002385 0.635998728003816
|
||||||
|
5.0 6.75 0.0
|
||||||
|
5.0 8.25 0.0
|
||||||
|
4.25 7.5 0.0
|
||||||
|
5.0 7.102500794997615 0.635998728003816
|
||||||
|
5.0 7.897499205002385 0.635998728003816
|
||||||
|
2.5 3.25 0.0
|
||||||
|
2.5 1.75 0.0
|
||||||
|
3.25 2.5 0.0
|
||||||
|
2.5 2.897499205002385 0.635998728003816
|
||||||
|
2.5 2.102500794997615 0.635998728003816
|
||||||
|
2.5 5.75 0.0
|
||||||
|
2.5 4.25 0.0
|
||||||
|
3.25 5.0 0.0
|
||||||
|
2.5 5.397499205002385 0.635998728003816
|
||||||
|
2.5 4.602500794997615 0.635998728003816
|
||||||
|
2.5 8.25 0.0
|
||||||
|
2.5 6.75 0.0
|
||||||
|
3.25 7.5 0.0
|
||||||
|
2.5 7.897499205002385 0.635998728003816
|
||||||
|
2.5 7.102500794997615 0.635998728003816
|
||||||
|
2.5 3.0 2.0
|
||||||
|
2.5 4.5 2.0
|
||||||
|
3.25 3.75 2.0
|
||||||
|
2.5 3.352500794997615 1.364001271996184
|
||||||
|
2.5 4.147499205002385 1.364001271996184
|
||||||
|
2.5 5.5 2.0
|
||||||
|
2.5 7.0 2.0
|
||||||
|
3.25 6.25 2.0
|
||||||
|
2.5 5.852500794997615 1.364001271996184
|
||||||
|
2.5 6.647499205002385 1.364001271996184
|
||||||
|
5.0 4.5 2.0
|
||||||
|
5.0 3.0 2.0
|
||||||
|
4.25 3.75 2.0
|
||||||
|
5.0 4.147499205002385 1.364001271996184
|
||||||
|
5.0 3.352500794997615 1.364001271996184
|
||||||
|
5.0 7.0 2.0
|
||||||
|
5.0 5.5 2.0
|
||||||
|
4.25 6.25 2.0
|
||||||
|
5.0 6.647499205002385 1.364001271996184
|
||||||
|
5.0 5.852500794997615 1.364001271996184
|
||||||
|
</nodes>
|
||||||
|
|
||||||
|
<elements nenod="2">
|
||||||
|
0 4
|
||||||
|
1 5
|
||||||
|
2 6
|
||||||
|
3 7
|
||||||
|
0 2
|
||||||
|
1 3
|
||||||
|
4 6
|
||||||
|
5 7
|
||||||
|
12 52
|
||||||
|
11 2
|
||||||
|
8 0
|
||||||
|
17 57
|
||||||
|
16 51
|
||||||
|
13 9
|
||||||
|
19 1
|
||||||
|
22 3
|
||||||
|
21 56
|
||||||
|
18 14
|
||||||
|
19 1
|
||||||
|
26 41
|
||||||
|
27 6
|
||||||
|
24 4
|
||||||
|
10 25
|
||||||
|
31 46
|
||||||
|
32 42
|
||||||
|
29 23
|
||||||
|
15 30
|
||||||
|
33 5
|
||||||
|
36 7
|
||||||
|
37 47
|
||||||
|
34 28
|
||||||
|
20 35
|
||||||
|
38 6
|
||||||
|
43 39
|
||||||
|
44 7
|
||||||
|
49 2
|
||||||
|
40 50
|
||||||
|
54 48
|
||||||
|
45 55
|
||||||
|
53 3
|
||||||
|
</elements>
|
||||||
|
|
||||||
|
<nodeset name="S01"> 8 9 10 11 12</nodeset>
|
||||||
|
<nodeset name="S02">13 14 15 16 17</nodeset>
|
||||||
|
<nodeset name="S03">18 19 20 21 22</nodeset>
|
||||||
|
<nodeset name="S04">23 24 25 26 27</nodeset>
|
||||||
|
<nodeset name="S05">28 29 30 31 32</nodeset>
|
||||||
|
<nodeset name="S06">33 34 35 36 37</nodeset>
|
||||||
|
<nodeset name="S07">38 39 40 41 42</nodeset>
|
||||||
|
<nodeset name="S08">43 44 45 46 47</nodeset>
|
||||||
|
<nodeset name="S09">48 49 50 51 52</nodeset>
|
||||||
|
<nodeset name="S10">53 54 55 56 57</nodeset>
|
||||||
|
|
||||||
|
</patch>
|
@ -264,6 +264,8 @@ bool SIM1D::parse (const TiXmlElement* elem)
|
|||||||
{
|
{
|
||||||
if (type == "matlab")
|
if (type == "matlab")
|
||||||
nf += 10;
|
nf += 10;
|
||||||
|
else if (type == "xml")
|
||||||
|
nf += 20;
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
opt.discretization = ASM::Lagrange;
|
opt.discretization = ASM::Lagrange;
|
||||||
|
@ -417,23 +417,27 @@ bool SIM2D::parse (const TiXmlElement* elem)
|
|||||||
{
|
{
|
||||||
if (!strcasecmp(elem->Value(),"geometry"))
|
if (!strcasecmp(elem->Value(),"geometry"))
|
||||||
{
|
{
|
||||||
// Check for triangular/Matlab mesh or immersed boundary calculation.
|
// Check for triangular/unstructured Lagrange mesh
|
||||||
|
// or immersed boundary calculation.
|
||||||
// This code must be placed here (and not in parseGeometryTag)
|
// This code must be placed here (and not in parseGeometryTag)
|
||||||
// due to instantiation of the ASMs2D[Tri|IB|Matlab] class.
|
// due to instantiation of the ASMu2DLag and ASMs2D[Tri|IB] classes.
|
||||||
int maxDepth = 0;
|
|
||||||
std::string type;
|
|
||||||
const TiXmlElement* child = elem->FirstChildElement();
|
const TiXmlElement* child = elem->FirstChildElement();
|
||||||
for (; child; child = child->NextSiblingElement())
|
for (; child; child = child->NextSiblingElement())
|
||||||
if (!strcasecmp(child->Value(),"triangular"))
|
if (!strcasecmp(child->Value(),"triangular"))
|
||||||
opt.discretization = ASM::Triangle;
|
opt.discretization = ASM::Triangle;
|
||||||
else if (!strcasecmp(child->Value(),"patchfile") &&
|
else if (!strcasecmp(child->Value(),"patchfile"))
|
||||||
utl::getAttribute(child,"type",type,true) && type == "matlab")
|
|
||||||
{
|
{
|
||||||
opt.discretization = ASM::Lagrange;
|
std::string type;
|
||||||
nf.push_back('M');
|
if (utl::getAttribute(child,"type",type,true) && type[0] > 'l')
|
||||||
|
{
|
||||||
|
opt.discretization = ASM::Lagrange;
|
||||||
|
nf.push_back(type[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!strcasecmp(child->Value(),"immersedboundary"))
|
else if (!strcasecmp(child->Value(),"immersedboundary"))
|
||||||
if (utl::getAttribute(child,"max_depth",maxDepth))
|
{
|
||||||
|
int maxDepth = 0;
|
||||||
|
if (utl::getAttribute(child,"max_depth",maxDepth) && maxDepth > 0)
|
||||||
{
|
{
|
||||||
nf.push_back('I');
|
nf.push_back('I');
|
||||||
nf.push_back(maxDepth);
|
nf.push_back(maxDepth);
|
||||||
@ -443,6 +447,7 @@ bool SIM2D::parse (const TiXmlElement* elem)
|
|||||||
if (opt.discretization == ASM::SplineC1)
|
if (opt.discretization == ASM::SplineC1)
|
||||||
opt.discretization = ASM::Spline;
|
opt.discretization = ASM::Spline;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool result = this->SIMgeneric::parse(elem);
|
bool result = this->SIMgeneric::parse(elem);
|
||||||
|
Loading…
Reference in New Issue
Block a user