Changed: Removed reimplementation of identical createGeometry methods in the

ModelGenerator sub-classes. Instead, the createG2 method is made virtual.
Also let the createTopology method have an empty default implementation such
that it does not need to be overridden in the single-patch default generators.

And please don't use the override keyword (at least not in the IFEM kernel)
which is not supported i gcc 4.6. I still use that compiler for debugging.
This commit is contained in:
Knut Morten Okstad 2016-10-03 05:45:31 +02:00
parent ff557f5f86
commit 49bcd4f618
6 changed files with 131 additions and 204 deletions

View File

@ -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 bool MultiPatchModelGenerator2D::createTopology (SIMbase& sim) const
{ {
auto&& IJ = [this](int i, int j) { return 1 + j*nx + i; }; auto&& IJ = [this](int i, int j) { return 1 + j*nx + i; };
@ -133,27 +123,29 @@ bool MultiPatchModelGenerator2D::createTopology (SIMbase& sim) const
return false; return false;
if (periodic_x) if (periodic_x)
for (int i = 0; i < ny; ++i) for (int j = 0; j < ny; ++j)
if (nx > 1) { 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; return false;
} else { }
IFEM::cout <<"\tPeriodic I-direction P"<< IJ(0,i) << std::endl; else {
ASMs2D* pch = dynamic_cast<ASMs2D*>(sim.getPatch(IJ(0,i), true)); IFEM::cout <<"\tPeriodic I-direction P"<< IJ(0,j) << std::endl;
if (pch) ASMs2D* pch = dynamic_cast<ASMs2D*>(sim.getPatch(IJ(0,j), true));
pch->closeEdges(1); if (pch)
pch->closeEdges(1);
} }
if (periodic_y) if (periodic_y)
for (int i = 0; i < nx; ++i) 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)) if (!sim.addConnection(IJ(i,0), IJ(i,ny-1), 3, 4, 0, 0, false))
return false; return false;
}
else { else {
IFEM::cout <<"\tPeriodic J-direction P"<< IJ(i,0)<< std::endl; IFEM::cout <<"\tPeriodic J-direction P"<< IJ(i,0)<< std::endl;
ASMs2D* pch = dynamic_cast<ASMs2D*>(sim.getPatch(IJ(i,0), true)); ASMs2D* pch = dynamic_cast<ASMs2D*>(sim.getPatch(IJ(i,0), true));
if (pch) if (pch)
pch->closeEdges(2); pch->closeEdges(2);
} }
return true; return true;
@ -163,10 +155,10 @@ bool MultiPatchModelGenerator2D::createTopology (SIMbase& sim) const
TopologySet TopologySet
MultiPatchModelGenerator2D::createTopologySets (const SIMbase& sim) const MultiPatchModelGenerator2D::createTopologySets (const SIMbase& sim) const
{ {
if (!sets)
return TopologySet();
TopologySet result; TopologySet result;
if (!this->topologySets())
return result;
TopEntity& e1 = result["Edge1"]; TopEntity& e1 = result["Edge1"];
TopEntity& e2 = result["Edge2"]; TopEntity& e2 = result["Edge2"];
TopEntity& e3 = result["Edge3"]; TopEntity& e3 = result["Edge3"];
@ -289,8 +281,8 @@ std::string MultiPatchModelGenerator3D::createG2 (int) const
for (size_t i = 0; i < nodes.size(); i += 3) for (size_t i = 0; i < nodes.size(); i += 3)
{ {
std::stringstream str; std::stringstream str;
std::array<int,3> N {x,y,z}; std::array<int,3> N = {{x,y,z}};
std::array<double,3> L {Lx,Ly,Lz}; std::array<double,3> L = {{Lx,Ly,Lz}};
for (size_t j = 0; j < 3; j++) for (size_t j = 0; j < 3; j++)
str << (j==0?"":" ") << X0[j]+N[j]*L[j]+nodes[i+j]*L[j]; str << (j==0?"":" ") << X0[j]+N[j]*L[j]+nodes[i+j]*L[j];
g2.append(str.str()); 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 bool MultiPatchModelGenerator3D::createTopology (SIMbase& sim) const
{ {
auto&& IJK = [this](int i, int j, int k) { return 1 + (k*ny+j)*nx + i; }; 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 TopologySet
MultiPatchModelGenerator3D::createTopologySets (const SIMbase& sim) const MultiPatchModelGenerator3D::createTopologySets (const SIMbase& sim) const
{ {
if (!sets) TopologySet result;
return TopologySet(); if (!this->topologySets())
return result;
// 0-based -> 1-based IJK // 0-based -> 1-based IJK
auto&& IJK = [this](int i, int j, int k) { return 1 + (k*ny+j)*nx + i; }; 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 // start/end K
auto&& IJK2K = [this,IJK](int i, int j, int k) { return IJK(i, j, k*(nz-1)); }; auto&& IJK2K = [this,IJK](int i, int j, int k) { return IJK(i, j, k*(nz-1)); };
TopologySet result;
// insertion lambda // insertion lambda
auto&& insertion = [&sim,&result](TopItem top, auto&& insertion = [&sim,&result](TopItem top,
const std::string& glob, const std::string& glob,

View File

@ -11,11 +11,10 @@
//! //!
//============================================================================== //==============================================================================
#ifndef _MULTIPATCH_MODEL_GENERATOR_H #ifndef _MULTI_PATCH_MODEL_GENERATOR_H
#define _MULTIPATCH_MODEL_GENERATOR_H #define _MULTI_PATCH_MODEL_GENERATOR_H
#include "ModelGenerator.h" #include "ModelGenerator.h"
#include <string>
/*! /*!
@ -26,29 +25,22 @@
class MultiPatchModelGenerator2D : public ModelGenerator class MultiPatchModelGenerator2D : public ModelGenerator
{ {
public: public:
//! \brief Constructor initializes common members. //! \brief The constructor initializes common members.
//!\ param[in] elem XML element to parse //!\ param[in] elem XML element to parse
MultiPatchModelGenerator2D(const TiXmlElement* elem); MultiPatchModelGenerator2D(const TiXmlElement* elem);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~MultiPatchModelGenerator2D() {} 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. //! \brief Creates topology for geometry.
//! \param sim Simulator to apply topology to virtual bool createTopology(SIMbase& sim) const;
bool createTopology(SIMbase& sim) const override;
//! \brief Creates topology sets for geometry. //! \brief Creates topology sets for geometry.
TopologySet createTopologySets(const SIMbase& sim) const override; virtual TopologySet createTopologySets(const SIMbase& sim) const;
protected: protected:
//! \brief Generates the G2 description of the geometry. //! \brief Generates the G2 description of the geometry.
//! \param nsd Number of spatial dimension virtual std::string createG2(int nsd) const;
std::string createG2 (int nsd = 2) const;
private:
int nx; //!< Number of blocks in x int nx; //!< Number of blocks in x
int ny; //!< Number of blocks in y int ny; //!< Number of blocks in y
int periodic_x; //!< If non-zero, make model periodic in x for given bases 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. \brief 3D multi-patch model generator for FEM simulators.
\details Generates a hexahedra split in a given number of blocks. \details Generates a hexahedra split in a given number of blocks.
*/ */
class MultiPatchModelGenerator3D : public ModelGenerator class MultiPatchModelGenerator3D : public ModelGenerator
{ {
public: public:
//! \brief Constructor initializes common members. //! \brief The constructor initializes common members.
//! \param[in] elem XML element to parse //! \param[in] elem XML element to parse
MultiPatchModelGenerator3D(const TiXmlElement* geo); MultiPatchModelGenerator3D(const TiXmlElement* geo);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~MultiPatchModelGenerator3D() {} 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. //! \brief Creates topology for geometry.
//! \param[in] geo XML element containing geometry defintion virtual bool createTopology(SIMbase& sim) const;
//! \param sim Simulator to apply topology to
bool createTopology(SIMbase& sim) const override;
//! \brief Creates topology sets for geometry. //! \brief Creates topology sets for geometry.
//! \param[in] SIM Simulator with patch ownerships
virtual TopologySet createTopologySets(const SIMbase& sim) const; virtual TopologySet createTopologySets(const SIMbase& sim) const;
protected: protected:
//! \brief Generates the G2 description of the geometry. //! \brief Generates the G2 description of the geometry.
//! \param nsd Number of spatial dimension virtual std::string createG2(int) const;
std::string createG2 (int nsd = 3) const;
private:
int nx; //!< Number of blocks in x int nx; //!< Number of blocks in x
int ny; //!< Number of blocks in y int ny; //!< Number of blocks in y
int nz; //!< Number of blocks in z int nz; //!< Number of blocks in z

View File

@ -37,9 +37,9 @@ public:
virtual ~SIMMultiPatchModelGen() {} virtual ~SIMMultiPatchModelGen() {}
protected: 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 //! \param[in] geo XML element containing geometry defintion
ModelGenerator* createModelGenerator(const TiXmlElement* geo) const override; virtual ModelGenerator* createModelGenerator(const TiXmlElement* geo) const;
}; };
#endif #endif

View File

@ -12,8 +12,8 @@
//============================================================================== //==============================================================================
#include "ModelGenerator.h" #include "ModelGenerator.h"
#include "IFEM.h"
#include "SIMbase.h" #include "SIMbase.h"
#include "IFEM.h"
#include "Utilities.h" #include "Utilities.h"
#include "Vec3.h" #include "Vec3.h"
#include "Vec3Oper.h" #include "Vec3Oper.h"
@ -21,10 +21,19 @@
#include <array> #include <array>
ModelGenerator::ModelGenerator (const TiXmlElement* elem) : bool ModelGenerator::topologySets () const
sets(false), geo(elem)
{ {
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 TopologySet DefaultGeometry1D::createTopologySets (const SIMbase&) const
{ {
if (!sets)
return TopologySet();
TopologySet result; TopologySet result;
result["Vertex1"].insert(TopItem(1,1,0)); if (this->topologySets())
result["Vertex2"].insert(TopItem(1,2,0)); {
result["Boundary"].insert(TopItem(1,1,0)); result["Vertex1"].insert(TopItem(1,1,0));
result["Boundary"].insert(TopItem(1,2,0)); result["Vertex2"].insert(TopItem(1,2,0));
result["Corners"].insert(TopItem(1,1,0)); result["Boundary"].insert(TopItem(1,1,0));
result["Corners"].insert(TopItem(1,2,0)); result["Boundary"].insert(TopItem(1,2,0));
result["Corners"].insert(TopItem(1,1,0));
result["Corners"].insert(TopItem(1,2,0));
}
return result; 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 TopologySet DefaultGeometry2D::createTopologySets (const SIMbase&) const
{ {
if (!sets)
return TopologySet();
TopologySet result; TopologySet result;
std::string vert = "Vertex1"; if (this->topologySets())
std::string edge = "Edge1"; {
for (size_t i = 1; i <= 4; ++i, ++vert.back(), ++edge.back()) { std::string vert = "Vertex1";
result[vert].insert(TopItem(1,i,0)); std::string edge = "Edge1";
result[edge].insert(TopItem(1,i,1)); for (size_t i = 1; i <= 4; ++i, ++vert.back(), ++edge.back())
result["Corners"].insert(TopItem(1,i,0)); {
result["Boundary"].insert(TopItem(1,i,1)); 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; 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 TopologySet DefaultGeometry3D::createTopologySets (const SIMbase&) const
{ {
if (!sets)
return TopologySet();
TopologySet result; 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"; std::string edge = "Edge1";
for (size_t i = 1; i <= 6; ++i, ++face.back()) { for (size_t i = 1; i <= 12; ++i, ++edge.back()) {
result[face].insert(TopItem(1,i,2)); result[edge].insert(TopItem(1,i,1));
result["Boundary"].insert(TopItem(1,i,2)); result["Frame"].insert(TopItem(1,i,1));
} if (i == 9)
edge = "Edge1/"; // '/' + 1 == '0'
}
std::string edge = "Edge1"; std::string vert = "Vertex1";
for (size_t i = 1; i <= 12; ++i, ++edge.back()) { for (size_t i = 1; i <= 8; ++i, ++vert.back()) {
result[edge].insert(TopItem(1,i,1)); result[vert].insert(TopItem(1,i,0));
result["Frame"].insert(TopItem(1,i,1)); result["Corners"].insert(TopItem(1,i,0));
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));
} }
return result; return result;

View File

@ -21,6 +21,7 @@
class SIMbase; class SIMbase;
class TiXmlElement; class TiXmlElement;
/*! /*!
\brief Base class for model generators for FEM simulators. \brief Base class for model generators for FEM simulators.
*/ */
@ -28,120 +29,104 @@ class TiXmlElement;
class ModelGenerator class ModelGenerator
{ {
public: public:
//! \brief Constructor initializes common members //! \brief The constructor initializes the common members.
//!\ param elem XML element to parse //!\ param elem XML element to parse
ModelGenerator(const TiXmlElement* elem); ModelGenerator(const TiXmlElement* elem) : geo(elem) {}
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~ModelGenerator() {} virtual ~ModelGenerator() {}
//! \brief Creates a geometry. //! \brief Creates a geometry.
//! \param[in] sim SIM with patch read function to use //! \param[in] m Simulator object with patch read function to use
virtual SIMdependency::PatchVec createGeometry(const SIMbase& sim) const = 0; virtual SIMdependency::PatchVec createGeometry(const SIMbase& m) const;
//! \brief Creates topology for geometry. //! \brief Creates topology for multi-patch geometries.
//! \param[in] geo XML element containing geometry defintion virtual bool createTopology(SIMbase&) const { return true; }
//! \param sim Simulator to apply topology to
virtual bool createTopology(SIMbase& sim) const = 0;
//! \brief Creates topology sets for geometry. //! \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; virtual TopologySet createTopologySets(const SIMbase& sim) const = 0;
protected: 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 const TiXmlElement* geo; //!< Pointer to xml element describing geometry
}; };
/*! /*!
\brief Default model generator for 1D FEM simulators. \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: public:
//! \brief The constructor forwards to the base class. //! \brief The constructor forwards to the base class.
//! \param[in] geo XML element containing geometry defintion //! \param[in] geo XML element containing geometry defintion
DefaultGeometry1D(const TiXmlElement* geo) : ModelGenerator(geo) {} DefaultGeometry1D(const TiXmlElement* geo) : ModelGenerator(geo) {}
//! \brief Empty destructor.
//! \brief Creates a 1D single-patch geometry. virtual ~DefaultGeometry1D() {}
//! \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 Creates topology sets for geometry. //! \brief Creates topology sets for geometry.
TopologySet createTopologySets(const SIMbase&) const override; virtual TopologySet createTopologySets(const SIMbase&) const;
protected: protected:
//! \brief Generates the G2 description of the geometry. //! \brief Generates the G2 description of the geometry.
//! \param nsd Number of spatial dimension //! \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. \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: public:
//! \brief The constructor forwards to the base class. //! \brief The constructor forwards to the base class.
//! \param[in] geo XML element containing geometry defintion //! \param[in] geo XML element containing geometry defintion
DefaultGeometry2D(const TiXmlElement* geo) : ModelGenerator(geo) {} DefaultGeometry2D(const TiXmlElement* geo) : ModelGenerator(geo) {}
//! \brief Empty destructor.
//! \brief Creates a 2D rectangular single-patch geometry. virtual ~DefaultGeometry2D() {}
//! \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 Creates topology sets for geometry. //! \brief Creates topology sets for geometry.
TopologySet createTopologySets(const SIMbase&) const override; virtual TopologySet createTopologySets(const SIMbase&) const;
protected: protected:
//! \brief Generates the G2 description of the geometry. //! \brief Generates the G2 description of the geometry.
//! \param nsd Number of spatial dimension //! \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. \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: public:
//! \brief The constructor forwards to the base class. //! \brief The constructor forwards to the base class.
//! \param[in] geo XML element containing geometry defintion //! \param[in] geo XML element containing geometry defintion
DefaultGeometry3D(const TiXmlElement* geo) : ModelGenerator(geo) {} DefaultGeometry3D(const TiXmlElement* geo) : ModelGenerator(geo) {}
//! \brief Empty destructor.
//! \brief Creates a 3D hexahedral single-patch geometry. virtual ~DefaultGeometry3D() {}
//! \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 Creates topology sets for geometry. //! \brief Creates topology sets for geometry.
TopologySet createTopologySets(const SIMbase&) const override; virtual TopologySet createTopologySets(const SIMbase&) const;
protected: protected:
//! \brief Generates the G2 description of the geometry. //! \brief Generates the G2 description of the geometry.
std::string createG2 (int = 3) const; virtual std::string createG2(int) const;
}; };
#endif #endif

View File

@ -10,10 +10,10 @@
//! //!
//============================================================================== //==============================================================================
#include "IntegrandBase.h"
#include "IFEM.h" #include "IFEM.h"
#include "SIM2D.h" #include "SIM2D.h"
#include "SIM3D.h" #include "SIM3D.h"
#include "IntegrandBase.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "tinyxml.h" #include "tinyxml.h"
@ -31,26 +31,21 @@ public:
{ {
return this->addMADOF(basis, nndof); return this->addMADOF(basis, nndof);
} }
private: private:
class TestProjectIntegrand : public IntegrandBase { class TestProjectIntegrand : public IntegrandBase {
public: public:
TestProjectIntegrand(int dim) : IntegrandBase(dim) {} TestProjectIntegrand(int dim) : IntegrandBase(dim) {}
//! \brief Evaluates the secondary solution at a result point. virtual bool evalSol(Vector& s, const FiniteElement&, const Vec3& X,
//! \param[out] s The solution field values at current point const std::vector<int>&) const
//! \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<int>& MNPC) const override
{ {
s.resize(1); s.resize(1);
s(1) = X[0] + X[1] + X[2]; s(1) = X[0] + X[1] + X[2];
return true; return true;
} }
size_t getNoFields(int = 2) const override { return 1; } virtual size_t getNoFields(int) const { return 1; }
}; };
}; };