8#ifndef model_FiniteElement_H_
9#define model_FiniteElement_H_
41 template<
typename _ElementType>
42 class FiniteElement :
public std::enable_shared_from_this<FiniteElement<_ElementType>>,
47 public std::map<typename SimplexTraits<_ElementType::dim,_ElementType::dim>::SimplexIDType,
51 public std::deque<typename _ElementType::NodeType>,
52 public std::map<Eigen::Matrix<double,_ElementType::dim,1>,
53 typename _ElementType::NodeType* const,
54 CompareVectorsByComponent<double,_ElementType::dim,float>
56 private std::map<size_t,std::deque<const typename _ElementType::NodeType*>>,
57 private std::map<size_t,const typename _ElementType::NodeType* const>
61 std::shared_ptr<const SimplicialMesh<_ElementType::dim>> meshOwner;
62 std::shared_ptr<const int> lifetime=std::make_shared<const int>(0);
63 std::weak_ptr<const int> meshLifetime;
64 Eigen::Matrix<double,_ElementType::dim,1> _xMin;
65 Eigen::Matrix<double,_ElementType::dim,1> _xMax;
66 Eigen::Matrix<double,_ElementType::dim,1> _xMean;
76 typedef typename ElementType::NodeType
NodeType;
82 constexpr static int dim=ElementType::dim;
89 typedef std::map<typename SimplexTraits<_ElementType::dim,_ElementType::dim>::SimplexIDType,
92 typedef std::map<Eigen::Matrix<double,_ElementType::dim,1>,
93 typename _ElementType::NodeType*
const,
101 _xMin(
Eigen::Matrix<double,
dim,1>::Zero()),
102 _xMax(
Eigen::Matrix<double,
dim,1>::Zero()),
106 meshLifetime=
m.lifetimeToken();
114 std::cout<<
"Element barycentric coordinates:\n"<<ElementType::baryNodalCoordinates<<std::endl;
117 for (
const auto& simpl :
mesh.simplices())
119 auto temp=ElementContainerType::emplace(simpl.first,ElementType(*simpl.second,*this,*this,mesh2femIDmap()));
123 throw std::runtime_error(
"UNABLE TO INSERT ELEMENT IN ELEMENT CONTAINER.");
127 for(
int n=0;n<ElementType::nodesPerElement;++n)
129 auto temp1=temp.first->second.node(n).emplace(&temp.first->second);
132 throw std::runtime_error(
"UNABLE TO INSERT ELEMENT IN NODE.");
138 if(std::is_same<ElementType,LagrangeElement<ElementType::dim,ElementType::order>>::value)
140 if(mesh2femIDmap().size()!=
mesh.template simplexFactory<0>().liveSimplices().size())
142 std::cout<<
"mesh2femIDmap().size()="<<mesh2femIDmap().size()<<std::endl;
143 std::cout<<
"mesh.template simplexFactory<0>().liveSimplices().size()="<<
mesh.template simplexFactory<0>().liveSimplices().size()<<std::endl;
144 throw std::runtime_error(
"mesh2femIDmap has wrong size.");
151 for(
size_t n=0;
n<nodes().size();++
n)
155 throw std::runtime_error(
"node(n).gID!=n");
167 for (
size_t n=0;
n<nodeSize();++
n)
169 for(
int d=0;d<
dim;++d)
171 if (node(n).
P0(d)<_xMin(d))
173 _xMin(d)=node(n).P0(d);
175 if (node(n).
P0(d)>_xMax(d))
177 _xMax(d)=node(n).P0(d);
181 _xMean=0.5*(_xMin+_xMax);
185 updatePeriodicNodePairs();
186 std::cout<<
" # elements: "<<elementSize() <<
"\n";
187 std::cout<<
" # nodes: " <<nodeSize() <<
"\n";
188 std::cout<<
" xMin= " <<_xMin.transpose()<<
"\n";
189 std::cout<<
" xMax= " <<_xMax.transpose()<<std::endl;
195 meshOwner=std::move(
m);
201 throw std::invalid_argument(
"Null FEM mesh.");
213 if(meshLifetime.expired())
215 throw std::runtime_error(
"FEM space outlived its borrowed mesh. Use an owning mesh constructor.");
222 if constexpr(std::is_same_v<ElementType,LagrangeElement<dim,ElementType::order>>)
225 _periodicNodes=std::move(staged);
230 _periodicNodes.representatives.resize(
nodeSize());
231 _periodicNodes.shifts.assign(
nodeSize(),Eigen::Matrix<double,dim,1>::Zero());
234 _periodicNodes.representatives[
i]=
i;
240 return _periodicNodes.pairs;
244 return _periodicNodes.representatives.at(nodeID);
248 return _periodicNodes.shifts.at(nodeID);
251 template<
int nComponents>
257 template <
char name,
int nComponents>
260 return std::make_shared<TrialFunction<name,nComponents,FiniteElementType>>(*this);
273 return ElementContainerType::size();
285 return NodeContainerType::size();
293 return NodeContainerType::operator[](n);
303 const Eigen::Matrix<double,dim,1>&
xMin()
const
309 const double&
xMin(
const int&
k)
const
315 const Eigen::Matrix<double,dim,1>&
xMax()
const
321 const double&
xMax(
const int&
k)
const
327 const Eigen::Matrix<double,dim,1>&
xMean()
const
339 template <
typename BndType,
int qOrder,
template <
short unsigned int,
size_t>
class QuadratureRule>
346 template <
typename DomainType,
int qOrder,
template <
short unsigned int,
size_t>
class QuadratureRule>
353 const std::map<size_t,const typename _ElementType::NodeType* const>&
mesh2femIDmap()
const
359 std::map<size_t,const typename _ElementType::NodeType* const>&
mesh2femIDmap()
365 template <
typename NodeSelectorType,
typename... NodeSelectorArgs>
369 auto pair=NodeListContainerType::emplace(nodeListID,
NodeListType());
371 const NodeSelectorType nodeSelector(*
this,args...);
374 if(nodeSelector(
node))
376 pair.first->second.emplace_back(&
node);
380 return pair.first->first;
386 return NodeListContainerType::clear();
394 return NodeListContainerType::at(
k);
396 catch (
const std::out_of_range& oor)
398 std::cerr <<
"FiniteElement::nodeList(), out_of_range error: " << oor.what() <<
"\n";
399 return NodeListContainerType::at(
k);
404 std::pair<bool,const ElementType*>
search(
const Eigen::Matrix<double,dim,1>& P)
const
425 const std::pair<bool,const Simplex<dim,dim>*>
temp(
mesh.searchWithGuess(P,guess));
426 const typename ElementContainerType::const_iterator eIter(ElementContainerType::find(
temp.second->xID));
428 assert(eIter!=
elements().
end() &&
"ELEMENT NOT FOUND");
429 return std::pair<bool,const ElementType*>(
temp.first,&(eIter->second));
std::pair< bool, const ElementType * > searchWithGuess(const Eigen::Matrix< double, dim, 1 > &P, const Simplex< dim, dim > *const guess) const
const double & xMean(const int &k) const
ElementType::NodeType NodeType
const Eigen::Matrix< double, dim, 1 > & xMin() const
const auto & periodicNodePairs() const
std::map< typename SimplexTraits< ElementType::dim, ElementType::dim >::SimplexIDType, ElementType > ElementContainerType
FiniteElement(FiniteElement &&)=delete
std::deque< const NodeType * > NodeListType
static constexpr int nodesPerElement
const NodeContainerType & nodes() const
SimplicialMesh< dim > MeshType
FiniteElement< ElementType > FiniteElementType
std::map< size_t, NodeListType > NodeListContainerType
size_t periodicRepresentative(size_t nodeID) const
size_t createNodeList(const NodeSelectorArgs &... args)
FiniteElement(std::shared_ptr< const MeshType > m)
IntegrationDomain< FiniteElementType, 1, qOrder, QuadratureRule > boundary() const
const NodeListType & nodeList(const size_t &k) const
const Eigen::Matrix< double, dim, 1 > & xMean() const
void updatePeriodicNodePairs()
const NodeFinderType & nodeFinder() const
size_t elementSize() const
FiniteElement(const SimplicialMesh< dim > &m)
std::map< size_t, const typename _ElementType::NodeType *const > & mesh2femIDmap()
const std::map< size_t, const typename _ElementType::NodeType *const > & mesh2femIDmap() const
std::weak_ptr< const int > lifetimeToken() const
std::deque< typename ElementType::NodeType > NodeContainerType
std::map< Eigen::Matrix< double, ElementType::dim, 1 >, typename ElementType::NodeType *const, CompareVectorsByComponent< double, ElementType::dim, float > > NodeFinderType
std::pair< bool, const ElementType * > search(const Eigen::Matrix< double, dim, 1 > &P) const
static const MeshType & requireMesh(const std::shared_ptr< const MeshType > &m)
const ElementContainerType & elements() const
const double & xMax(const int &k) const
const Eigen::Matrix< double, dim, 1 > & xMax() const
IntegrationDomain< FiniteElementType, 0, qOrder, QuadratureRule > domain() const
const NodeType & node(const size_t &n) const
const double & xMin(const int &k) const
FiniteElement(const FiniteElement &)=delete
const Eigen::Matrix< double, dim, 1 > & periodicShift(size_t nodeID) const
void validateMeshLifetime() const
static std::string greenBoldColor
static std::string defaultColor