diff --git a/Apps/Common/MultiPatchModelGenerator.C b/Apps/Common/MultiPatchModelGenerator.C index acba7384..f46346cf 100644 --- a/Apps/Common/MultiPatchModelGenerator.C +++ b/Apps/Common/MultiPatchModelGenerator.C @@ -108,16 +108,6 @@ std::string MultiPatchModelGenerator2D::createG2 (int nsd) const } -SIMdependency::PatchVec -MultiPatchModelGenerator2D::createGeometry (const SIMbase& sim) const -{ - std::istringstream rect(this->createG2(sim.getNoSpaceDim())); - SIMdependency::PatchVec result; - sim.readPatches(rect,result,"\t"); - return result; -} - - bool MultiPatchModelGenerator2D::createTopology (SIMbase& sim) const { auto&& IJ = [this](int i, int j) { return 1 + j*nx + i; }; @@ -133,27 +123,29 @@ bool MultiPatchModelGenerator2D::createTopology (SIMbase& sim) const return false; if (periodic_x) - for (int i = 0; i < ny; ++i) + for (int j = 0; j < ny; ++j) if (nx > 1) { - if (!sim.addConnection(IJ(0, i), IJ(nx-1, i), 1, 2, 0, 0, false)) + if (!sim.addConnection(IJ(0,j), IJ(nx-1,j), 1, 2, 0, 0, false)) return false; - } else { - IFEM::cout <<"\tPeriodic I-direction P"<< IJ(0,i) << std::endl; - ASMs2D* pch = dynamic_cast(sim.getPatch(IJ(0,i), true)); - if (pch) - pch->closeEdges(1); + } + else { + IFEM::cout <<"\tPeriodic I-direction P"<< IJ(0,j) << std::endl; + ASMs2D* pch = dynamic_cast(sim.getPatch(IJ(0,j), true)); + if (pch) + pch->closeEdges(1); } if (periodic_y) for (int i = 0; i < nx; ++i) - if (ny > 1) + if (ny > 1) { if (!sim.addConnection(IJ(i,0), IJ(i,ny-1), 3, 4, 0, 0, false)) return false; + } else { - IFEM::cout <<"\tPeriodic J-direction P"<< IJ(i,0)<< std::endl; - ASMs2D* pch = dynamic_cast(sim.getPatch(IJ(i,0), true)); - if (pch) - pch->closeEdges(2); + IFEM::cout <<"\tPeriodic J-direction P"<< IJ(i,0)<< std::endl; + ASMs2D* pch = dynamic_cast(sim.getPatch(IJ(i,0), true)); + if (pch) + pch->closeEdges(2); } return true; @@ -163,10 +155,10 @@ bool MultiPatchModelGenerator2D::createTopology (SIMbase& sim) const TopologySet MultiPatchModelGenerator2D::createTopologySets (const SIMbase& sim) const { - if (!sets) - return TopologySet(); - TopologySet result; + if (!this->topologySets()) + return result; + TopEntity& e1 = result["Edge1"]; TopEntity& e2 = result["Edge2"]; TopEntity& e3 = result["Edge3"]; @@ -289,8 +281,8 @@ std::string MultiPatchModelGenerator3D::createG2 (int) const for (size_t i = 0; i < nodes.size(); i += 3) { std::stringstream str; - std::array N {x,y,z}; - std::array L {Lx,Ly,Lz}; + std::array N = {{x,y,z}}; + std::array L = {{Lx,Ly,Lz}}; for (size_t j = 0; j < 3; j++) str << (j==0?"":" ") << X0[j]+N[j]*L[j]+nodes[i+j]*L[j]; g2.append(str.str()); @@ -304,16 +296,6 @@ std::string MultiPatchModelGenerator3D::createG2 (int) const } -SIMdependency::PatchVec -MultiPatchModelGenerator3D::createGeometry (const SIMbase& sim) const -{ - std::istringstream hex(this->createG2(sim.getNoSpaceDim())); - SIMdependency::PatchVec result; - sim.readPatches(hex,result,"\t"); - return result; -} - - bool MultiPatchModelGenerator3D::createTopology (SIMbase& sim) const { auto&& IJK = [this](int i, int j, int k) { return 1 + (k*ny+j)*nx + i; }; @@ -382,8 +364,9 @@ bool MultiPatchModelGenerator3D::createTopology (SIMbase& sim) const TopologySet MultiPatchModelGenerator3D::createTopologySets (const SIMbase& sim) const { - if (!sets) - return TopologySet(); + TopologySet result; + if (!this->topologySets()) + return result; // 0-based -> 1-based IJK auto&& IJK = [this](int i, int j, int k) { return 1 + (k*ny+j)*nx + i; }; @@ -405,8 +388,6 @@ MultiPatchModelGenerator3D::createTopologySets (const SIMbase& sim) const // start/end K auto&& IJK2K = [this,IJK](int i, int j, int k) { return IJK(i, j, k*(nz-1)); }; - TopologySet result; - // insertion lambda auto&& insertion = [&sim,&result](TopItem top, const std::string& glob, diff --git a/Apps/Common/MultiPatchModelGenerator.h b/Apps/Common/MultiPatchModelGenerator.h index c54c47ac..e5d01371 100644 --- a/Apps/Common/MultiPatchModelGenerator.h +++ b/Apps/Common/MultiPatchModelGenerator.h @@ -11,11 +11,10 @@ //! //============================================================================== -#ifndef _MULTIPATCH_MODEL_GENERATOR_H -#define _MULTIPATCH_MODEL_GENERATOR_H +#ifndef _MULTI_PATCH_MODEL_GENERATOR_H +#define _MULTI_PATCH_MODEL_GENERATOR_H #include "ModelGenerator.h" -#include /*! @@ -26,29 +25,22 @@ class MultiPatchModelGenerator2D : public ModelGenerator { public: - //! \brief Constructor initializes common members. + //! \brief The constructor initializes common members. //!\ param[in] elem XML element to parse MultiPatchModelGenerator2D(const TiXmlElement* elem); - //! \brief Empty destructor. virtual ~MultiPatchModelGenerator2D() {} - //! \brief Creates a geometry. - //! \param[in] sim SIM with patch read function to use - SIMdependency::PatchVec createGeometry(const SIMbase& sim) const override; - //! \brief Creates topology for geometry. - //! \param sim Simulator to apply topology to - bool createTopology(SIMbase& sim) const override; - + virtual bool createTopology(SIMbase& sim) const; //! \brief Creates topology sets for geometry. - TopologySet createTopologySets(const SIMbase& sim) const override; + virtual TopologySet createTopologySets(const SIMbase& sim) const; protected: //! \brief Generates the G2 description of the geometry. - //! \param nsd Number of spatial dimension - std::string createG2 (int nsd = 2) const; + virtual std::string createG2(int nsd) const; +private: int nx; //!< Number of blocks in x int ny; //!< Number of blocks in y int periodic_x; //!< If non-zero, make model periodic in x for given bases @@ -59,36 +51,27 @@ protected: /*! \brief 3D multi-patch model generator for FEM simulators. \details Generates a hexahedra split in a given number of blocks. - */ +*/ class MultiPatchModelGenerator3D : public ModelGenerator { public: - //! \brief Constructor initializes common members. + //! \brief The constructor initializes common members. //! \param[in] elem XML element to parse MultiPatchModelGenerator3D(const TiXmlElement* geo); - //! \brief Empty destructor. virtual ~MultiPatchModelGenerator3D() {} - //! \brief Creates a geometry. - //! \param[in] sim SIM with patch read function to use - SIMdependency::PatchVec createGeometry(const SIMbase& sim) const override; - //! \brief Creates topology for geometry. - //! \param[in] geo XML element containing geometry defintion - //! \param sim Simulator to apply topology to - bool createTopology(SIMbase& sim) const override; - + virtual bool createTopology(SIMbase& sim) const; //! \brief Creates topology sets for geometry. - //! \param[in] SIM Simulator with patch ownerships virtual TopologySet createTopologySets(const SIMbase& sim) const; protected: //! \brief Generates the G2 description of the geometry. - //! \param nsd Number of spatial dimension - std::string createG2 (int nsd = 3) const; + virtual std::string createG2(int) const; +private: int nx; //!< Number of blocks in x int ny; //!< Number of blocks in y int nz; //!< Number of blocks in z diff --git a/Apps/Common/SIMMultiPatchModelGen.h b/Apps/Common/SIMMultiPatchModelGen.h index 98669197..a62ea710 100644 --- a/Apps/Common/SIMMultiPatchModelGen.h +++ b/Apps/Common/SIMMultiPatchModelGen.h @@ -37,9 +37,9 @@ public: virtual ~SIMMultiPatchModelGen() {} protected: - //! \brief Instantiate a generator for the finite element model. + //! \brief Instantiates a generator for the finite element model. //! \param[in] geo XML element containing geometry defintion - ModelGenerator* createModelGenerator(const TiXmlElement* geo) const override; + virtual ModelGenerator* createModelGenerator(const TiXmlElement* geo) const; }; #endif diff --git a/src/SIM/ModelGenerator.C b/src/SIM/ModelGenerator.C index 7939a88b..26e29834 100644 --- a/src/SIM/ModelGenerator.C +++ b/src/SIM/ModelGenerator.C @@ -12,8 +12,8 @@ //============================================================================== #include "ModelGenerator.h" -#include "IFEM.h" #include "SIMbase.h" +#include "IFEM.h" #include "Utilities.h" #include "Vec3.h" #include "Vec3Oper.h" @@ -21,10 +21,19 @@ #include -ModelGenerator::ModelGenerator (const TiXmlElement* elem) : - sets(false), geo(elem) +bool ModelGenerator::topologySets () const { - utl::getAttribute(geo, "sets", sets); + bool sets = false; + return utl::getAttribute(geo,"sets",sets) && sets; +} + + +SIMdependency::PatchVec ModelGenerator::createGeometry (const SIMbase& m) const +{ + std::istringstream g2(this->createG2(m.getNoSpaceDim())); + SIMdependency::PatchVec result; + m.readPatches(g2,result,"\t"); + return result; } @@ -78,27 +87,18 @@ std::string DefaultGeometry1D::createG2 (int nsd) const } -SIMdependency::PatchVec DefaultGeometry1D::createGeometry (const SIMbase& sim) const -{ - std::istringstream unitLine(this->createG2(sim.getNoSpaceDim())); - SIMdependency::PatchVec result; - sim.readPatches(unitLine,result,"\t"); - return result; -} - - TopologySet DefaultGeometry1D::createTopologySets (const SIMbase&) const { - if (!sets) - return TopologySet(); - TopologySet result; - result["Vertex1"].insert(TopItem(1,1,0)); - result["Vertex2"].insert(TopItem(1,2,0)); - result["Boundary"].insert(TopItem(1,1,0)); - result["Boundary"].insert(TopItem(1,2,0)); - result["Corners"].insert(TopItem(1,1,0)); - result["Corners"].insert(TopItem(1,2,0)); + if (this->topologySets()) + { + result["Vertex1"].insert(TopItem(1,1,0)); + result["Vertex2"].insert(TopItem(1,2,0)); + result["Boundary"].insert(TopItem(1,1,0)); + result["Boundary"].insert(TopItem(1,2,0)); + result["Corners"].insert(TopItem(1,1,0)); + result["Corners"].insert(TopItem(1,2,0)); + } return result; } @@ -160,28 +160,20 @@ std::string DefaultGeometry2D::createG2 (int nsd) const } -SIMdependency::PatchVec DefaultGeometry2D::createGeometry (const SIMbase& sim) const -{ - std::istringstream unitSquare(this->createG2(sim.getNoSpaceDim())); - SIMdependency::PatchVec result; - sim.readPatches(unitSquare,result,"\t"); - return result; -} - - TopologySet DefaultGeometry2D::createTopologySets (const SIMbase&) const { - if (!sets) - return TopologySet(); - TopologySet result; - std::string vert = "Vertex1"; - std::string edge = "Edge1"; - for (size_t i = 1; i <= 4; ++i, ++vert.back(), ++edge.back()) { - result[vert].insert(TopItem(1,i,0)); - result[edge].insert(TopItem(1,i,1)); - result["Corners"].insert(TopItem(1,i,0)); - result["Boundary"].insert(TopItem(1,i,1)); + if (this->topologySets()) + { + std::string vert = "Vertex1"; + std::string edge = "Edge1"; + for (size_t i = 1; i <= 4; ++i, ++vert.back(), ++edge.back()) + { + result[vert].insert(TopItem(1,i,0)); + result[edge].insert(TopItem(1,i,1)); + result["Corners"].insert(TopItem(1,i,0)); + result["Boundary"].insert(TopItem(1,i,1)); + } } return result; @@ -261,40 +253,31 @@ std::string DefaultGeometry3D::createG2 (int) const } -SIMdependency::PatchVec DefaultGeometry3D::createGeometry (const SIMbase& sim) const -{ - std::istringstream unitCube(this->createG2()); - SIMdependency::PatchVec result; - sim.readPatches(unitCube,result,"\t"); - return result; -} - - TopologySet DefaultGeometry3D::createTopologySets (const SIMbase&) const { - if (!sets) - return TopologySet(); - TopologySet result; + if (this->topologySets()) + { + std::string face = "Face1"; + for (size_t i = 1; i <= 6; ++i, ++face.back()) + { + result[face].insert(TopItem(1,i,2)); + result["Boundary"].insert(TopItem(1,i,2)); + } - std::string face = "Face1"; - for (size_t i = 1; i <= 6; ++i, ++face.back()) { - result[face].insert(TopItem(1,i,2)); - result["Boundary"].insert(TopItem(1,i,2)); - } + std::string edge = "Edge1"; + for (size_t i = 1; i <= 12; ++i, ++edge.back()) { + result[edge].insert(TopItem(1,i,1)); + result["Frame"].insert(TopItem(1,i,1)); + if (i == 9) + edge = "Edge1/"; // '/' + 1 == '0' + } - std::string edge = "Edge1"; - for (size_t i = 1; i <= 12; ++i, ++edge.back()) { - result[edge].insert(TopItem(1,i,1)); - result["Frame"].insert(TopItem(1,i,1)); - if (i == 9) - edge = "Edge1/"; // '/' + 1 == '0' - } - - std::string vert = "Vertex1"; - for (size_t i = 1; i <= 8; ++i, ++vert.back()) { - result[vert].insert(TopItem(1,i,0)); - result["Corners"].insert(TopItem(1,i,0)); + std::string vert = "Vertex1"; + for (size_t i = 1; i <= 8; ++i, ++vert.back()) { + result[vert].insert(TopItem(1,i,0)); + result["Corners"].insert(TopItem(1,i,0)); + } } return result; diff --git a/src/SIM/ModelGenerator.h b/src/SIM/ModelGenerator.h index ea6d5c2d..f6f4ef3e 100644 --- a/src/SIM/ModelGenerator.h +++ b/src/SIM/ModelGenerator.h @@ -21,6 +21,7 @@ class SIMbase; class TiXmlElement; + /*! \brief Base class for model generators for FEM simulators. */ @@ -28,120 +29,104 @@ class TiXmlElement; class ModelGenerator { public: - //! \brief Constructor initializes common members + //! \brief The constructor initializes the common members. //!\ param elem XML element to parse - ModelGenerator(const TiXmlElement* elem); - + ModelGenerator(const TiXmlElement* elem) : geo(elem) {} //! \brief Empty destructor. virtual ~ModelGenerator() {} //! \brief Creates a geometry. - //! \param[in] sim SIM with patch read function to use - virtual SIMdependency::PatchVec createGeometry(const SIMbase& sim) const = 0; + //! \param[in] m Simulator object with patch read function to use + virtual SIMdependency::PatchVec createGeometry(const SIMbase& m) const; - //! \brief Creates topology for geometry. - //! \param[in] geo XML element containing geometry defintion - //! \param sim Simulator to apply topology to - virtual bool createTopology(SIMbase& sim) const = 0; + //! \brief Creates topology for multi-patch geometries. + virtual bool createTopology(SIMbase&) const { return true; } //! \brief Creates topology sets for geometry. - //! \param[in] sim Simulator with patch ownerships + //! \param[in] sim Simulator object with patch ownerships virtual TopologySet createTopologySets(const SIMbase& sim) const = 0; protected: - bool sets; //!< Whether to generate topologysets or not + //! \brief Generates the G2 description of the geometry. + //! \param nsd Number of spatial dimension + virtual std::string createG2(int nsd) const { return ""; } + + //! \brief Returns \e true if topology sets is to be generated. + bool topologySets() const; + +protected: const TiXmlElement* geo; //!< Pointer to xml element describing geometry }; /*! \brief Default model generator for 1D FEM simulators. - \details Generates a line. + \details Generates a line domain. */ -class DefaultGeometry1D : public ModelGenerator { +class DefaultGeometry1D : public ModelGenerator +{ public: //! \brief The constructor forwards to the base class. //! \param[in] geo XML element containing geometry defintion DefaultGeometry1D(const TiXmlElement* geo) : ModelGenerator(geo) {} - - //! \brief Creates a 1D single-patch geometry. - //! \param[in] sim SIM with patch read function to use - SIMdependency::PatchVec createGeometry(const SIMbase& sim) const override; - - //! \brief Creates the topology - //! \details No topology information for single patch models - bool createTopology(SIMbase&) const override - { return true; } + //! \brief Empty destructor. + virtual ~DefaultGeometry1D() {} //! \brief Creates topology sets for geometry. - TopologySet createTopologySets(const SIMbase&) const override; + virtual TopologySet createTopologySets(const SIMbase&) const; protected: //! \brief Generates the G2 description of the geometry. //! \param nsd Number of spatial dimension - std::string createG2 (int nsd = 2) const; + virtual std::string createG2(int nsd) const; }; /*! \brief Default model generator for 2D FEM simulators. - \details Generates a rectangle. + \details Generates a quadrilateral domain. */ -class DefaultGeometry2D : public ModelGenerator { +class DefaultGeometry2D : public ModelGenerator +{ public: //! \brief The constructor forwards to the base class. //! \param[in] geo XML element containing geometry defintion DefaultGeometry2D(const TiXmlElement* geo) : ModelGenerator(geo) {} - - //! \brief Creates a 2D rectangular single-patch geometry. - //! \param[in] sim SIM with patch read function to use - SIMdependency::PatchVec createGeometry(const SIMbase& sim) const override; - - //! \brief Creates the topology - //! \param sim Simulator to apply topology to - //! \details No topology information for single patch models - bool createTopology(SIMbase&) const override - { return true; } + //! \brief Empty destructor. + virtual ~DefaultGeometry2D() {} //! \brief Creates topology sets for geometry. - TopologySet createTopologySets(const SIMbase&) const override; + virtual TopologySet createTopologySets(const SIMbase&) const; protected: //! \brief Generates the G2 description of the geometry. //! \param nsd Number of spatial dimension - std::string createG2 (int nsd = 3) const; + virtual std::string createG2(int nsd) const; }; /*! \brief Default model generator for 3D FEM simulators. - \details Generates a hexahedra. + \details Generates a hexahedral domain. */ -class DefaultGeometry3D : public ModelGenerator { +class DefaultGeometry3D : public ModelGenerator +{ public: //! \brief The constructor forwards to the base class. //! \param[in] geo XML element containing geometry defintion DefaultGeometry3D(const TiXmlElement* geo) : ModelGenerator(geo) {} - - //! \brief Creates a 3D hexahedral single-patch geometry. - //! \param[in] sim Simulator with patch read function to use - SIMdependency::PatchVec createGeometry(const SIMbase& sim) const override; - - //! \brief Creates the topology - //! \param sim Simulator to apply topology to - //! \details No topology information for single patch models - bool createTopology(SIMbase&) const override - { return true; } + //! \brief Empty destructor. + virtual ~DefaultGeometry3D() {} //! \brief Creates topology sets for geometry. - TopologySet createTopologySets(const SIMbase&) const override; + virtual TopologySet createTopologySets(const SIMbase&) const; protected: //! \brief Generates the G2 description of the geometry. - std::string createG2 (int = 3) const; + virtual std::string createG2(int) const; }; #endif diff --git a/src/SIM/Test/TestSIM.C b/src/SIM/Test/TestSIM.C index 6efe9d17..ee3b0ddd 100644 --- a/src/SIM/Test/TestSIM.C +++ b/src/SIM/Test/TestSIM.C @@ -10,10 +10,10 @@ //! //============================================================================== -#include "IntegrandBase.h" #include "IFEM.h" #include "SIM2D.h" #include "SIM3D.h" +#include "IntegrandBase.h" #include "gtest/gtest.h" #include "tinyxml.h" @@ -31,26 +31,21 @@ public: { return this->addMADOF(basis, nndof); } + private: class TestProjectIntegrand : public IntegrandBase { public: TestProjectIntegrand(int dim) : IntegrandBase(dim) {} - //! \brief Evaluates the secondary solution at a result point. - //! \param[out] s The solution field values at current point - //! \param[in] fe Finite element data at current point - //! \param[in] X Cartesian coordinates of current point - //! \param[in] MNPC Nodal point correspondance for the basis function values - bool evalSol(Vector& s, const FiniteElement& fe, const Vec3& X, - const std::vector& MNPC) const override + virtual bool evalSol(Vector& s, const FiniteElement&, const Vec3& X, + const std::vector&) const { s.resize(1); s(1) = X[0] + X[1] + X[2]; - return true; } - size_t getNoFields(int = 2) const override { return 1; } + virtual size_t getNoFields(int) const { return 1; } }; };