diff --git a/include/GooseFEM/MeshQuad4.h b/include/GooseFEM/MeshQuad4.h index 93f059d..ccb0a77 100644 --- a/include/GooseFEM/MeshQuad4.h +++ b/include/GooseFEM/MeshQuad4.h @@ -1,275 +1,286 @@ /* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM */ #ifndef GOOSEFEM_MESHQUAD4_H #define GOOSEFEM_MESHQUAD4_H #include "config.h" namespace GooseFEM { namespace Mesh { namespace Quad4 { +// pre-allocation + namespace Map { class FineLayer2Regular; -} // namespace Map +} + +// Regular mesh: equi-sized elements class Regular { public: Regular() = default; Regular(size_t nelx, size_t nely, double h = 1.0); // size size_t nelem() const; // number of elements size_t nnode() const; // number of nodes size_t nne() const; // number of nodes-per-element size_t ndim() const; // number of dimensions size_t nelx() const; // number of elements in x-direction size_t nely() const; // number of elements in y-direction double h() const; // edge size // type ElementType getElementType() const; // mesh xt::xtensor coor() const; // nodal positions [nnode, ndim] xt::xtensor conn() const; // connectivity [nelem, nne] // boundary nodes: edges xt::xtensor nodesBottomEdge() const; xt::xtensor nodesTopEdge() const; xt::xtensor nodesLeftEdge() const; xt::xtensor nodesRightEdge() const; // boundary nodes: edges, without corners xt::xtensor nodesBottomOpenEdge() const; xt::xtensor nodesTopOpenEdge() const; xt::xtensor nodesLeftOpenEdge() const; xt::xtensor nodesRightOpenEdge() const; // boundary nodes: corners (including aliases) size_t nodesBottomLeftCorner() const; size_t nodesBottomRightCorner() const; size_t nodesTopLeftCorner() const; size_t nodesTopRightCorner() const; size_t nodesLeftBottomCorner() const; size_t nodesLeftTopCorner() const; size_t nodesRightBottomCorner() const; size_t nodesRightTopCorner() const; // DOF-numbers for each component of each node (sequential) xt::xtensor dofs() const; // DOF-numbers for the case that the periodicity if fully eliminated xt::xtensor dofsPeriodic() const; // periodic node pairs [:,2]: (independent, dependent) xt::xtensor nodesPeriodic() const; // front-bottom-left node, used as reference for periodicity size_t nodesOrigin() const; // element numbers as matrix xt::xtensor elementgrid() const; private: double m_h; // elementary element edge-size (in all directions) size_t m_nelx; // number of elements in x-direction (length == "m_nelx * m_h") size_t m_nely; // number of elements in y-direction (length == "m_nely * m_h") size_t m_nelem; // number of elements size_t m_nnode; // number of nodes static const size_t m_nne = 4; // number of nodes-per-element static const size_t m_ndim = 2; // number of dimensions }; +// Mesh with fine middle layer, and coarser elements towards the top and bottom + class FineLayer { public: FineLayer() = default; FineLayer(size_t nelx, size_t nely, double h = 1.0, size_t nfine = 1); // Reconstruct class for given coordinates / connectivity FineLayer(const xt::xtensor& coor, const xt::xtensor& conn); // size size_t nelem() const; // number of elements size_t nnode() const; // number of nodes size_t nne() const; // number of nodes-per-element size_t ndim() const; // number of dimensions size_t nelx() const; // number of elements in x-direction size_t nely() const; // number of elements in y-direction double h() const; // edge size // type ElementType getElementType() const; // mesh xt::xtensor coor() const; // nodal positions [nnode, ndim] xt::xtensor conn() const; // connectivity [nelem, nne] // elements in the middle (fine) layer xt::xtensor elementsMiddleLayer() const; // select region of elements from 'matrix' of element numbers xt::xtensor elementgrid_ravel( std::vector rows_range, std::vector cols_range) const; // select region of elements from 'matrix' of element numbers around an element xt::xtensor elementgrid_around_ravel( size_t element, size_t size, bool periodic = true); xt::xtensor elementgrid_leftright( size_t element, size_t left, size_t right, bool periodic = true); // boundary nodes: edges xt::xtensor nodesBottomEdge() const; xt::xtensor nodesTopEdge() const; xt::xtensor nodesLeftEdge() const; xt::xtensor nodesRightEdge() const; // boundary nodes: edges, without corners xt::xtensor nodesBottomOpenEdge() const; xt::xtensor nodesTopOpenEdge() const; xt::xtensor nodesLeftOpenEdge() const; xt::xtensor nodesRightOpenEdge() const; // boundary nodes: corners (including aliases) size_t nodesBottomLeftCorner() const; size_t nodesBottomRightCorner() const; size_t nodesTopLeftCorner() const; size_t nodesTopRightCorner() const; size_t nodesLeftBottomCorner() const; size_t nodesLeftTopCorner() const; size_t nodesRightBottomCorner() const; size_t nodesRightTopCorner() const; // DOF-numbers for each component of each node (sequential) xt::xtensor dofs() const; // DOF-numbers for the case that the periodicity if fully eliminated xt::xtensor dofsPeriodic() const; // periodic node pairs [:,2]: (independent, dependent) xt::xtensor nodesPeriodic() const; // front-bottom-left node, used as reference for periodicity size_t nodesOrigin() const; // mapping to 'roll' periodically in the x-direction, // returns element mapping, such that: new_elemvar = elemvar[elem_map] xt::xtensor roll(size_t n); private: double m_h; // elementary element edge-size (in all directions) double m_Lx; // mesh size in "x" size_t m_nelem; // number of elements size_t m_nnode; // number of nodes static const size_t m_nne = 4; // number of nodes-per-element static const size_t m_ndim = 2; // number of dimensions xt::xtensor m_nelx; // number of elements in "x" (*) xt::xtensor m_nnd; // total number of nodes in the main node layer (**) xt::xtensor m_nhx; // element size in x-direction (*) xt::xtensor m_nhy; // element size in y-direction (*) xt::xtensor m_refine; // refine direction (-1:no refine, 0:"x" (*) xt::xtensor m_startElem; // start element (*) xt::xtensor m_startNode; // start node (**) // (*) per element layer in "y" // (**) per node layer in "y" void init(size_t nelx, size_t nely, double h, size_t nfine = 1); void map(const xt::xtensor& coor, const xt::xtensor& conn); friend class GooseFEM::Mesh::Quad4::Map::FineLayer2Regular; }; -namespace Map { - -// Return "FineLayer"-class responsible for generating a connectivity -// Throws if conversion is not possible -GooseFEM::Mesh::Quad4::FineLayer FineLayer( - const xt::xtensor& coor, - const xt::xtensor& conn); - -class RefineRegular { -public: - // constructor - RefineRegular() = default; - RefineRegular(const GooseFEM::Mesh::Quad4::Regular& mesh, size_t nx, size_t ny); - - // return the one of the two meshes - GooseFEM::Mesh::Quad4::Regular getCoarseMesh() const; - GooseFEM::Mesh::Quad4::Regular getFineMesh() const; - - // elements of the Fine mesh per element of the Coarse mesh - xt::xtensor getMap() const; - - // map field - xt::xtensor mapToCoarse(const xt::xtensor& data) const; // scalar per el - xt::xtensor mapToCoarse(const xt::xtensor& data) const; // scalar per intpnt - xt::xtensor mapToCoarse(const xt::xtensor& data) const; // tensor per intpnt - - // map field - xt::xtensor mapToFine(const xt::xtensor& data) const; // scalar per el - xt::xtensor mapToFine(const xt::xtensor& data) const; // scalar per intpnt - xt::xtensor mapToFine(const xt::xtensor& data) const; // tensor per intpnt - -private: - // the meshes - GooseFEM::Mesh::Quad4::Regular m_coarse; - GooseFEM::Mesh::Quad4::Regular m_fine; - - // mapping - xt::xtensor m_fine2coarse; - xt::xtensor m_fine2coarse_index; - xt::xtensor m_coarse2fine; -}; - -class FineLayer2Regular { -public: - // constructor - FineLayer2Regular() = default; - FineLayer2Regular(const GooseFEM::Mesh::Quad4::FineLayer& mesh); - - // return either of the meshes - GooseFEM::Mesh::Quad4::Regular getRegularMesh() const; - GooseFEM::Mesh::Quad4::FineLayer getFineLayerMesh() const; +// Mesh mappings - // elements of the Regular mesh per element of the FineLayer mesh - // and the fraction by which the overlap is - std::vector> getMap() const; - std::vector> getMapFraction() const; - - // map field - xt::xtensor mapToRegular(const xt::xtensor& data) const; // scalar per el - xt::xtensor mapToRegular(const xt::xtensor& data) const; // scalar per intpnt - xt::xtensor mapToRegular(const xt::xtensor& data) const; // tensor per intpnt - -private: - // the "FineLayer" mesh to map - GooseFEM::Mesh::Quad4::FineLayer m_finelayer; - - // the new "Regular" mesh to which to map - GooseFEM::Mesh::Quad4::Regular m_regular; +namespace Map { - // mapping - std::vector> m_elem_regular; - std::vector> m_frac_regular; -}; + // Return "FineLayer"-class responsible for generating a connectivity + // Throws if conversion is not possible + + GooseFEM::Mesh::Quad4::FineLayer FineLayer( + const xt::xtensor& coor, + const xt::xtensor& conn); + + // Refine a regular mesh: sub-divide elements in several smaller elements + + class RefineRegular { + public: + // Constructors + RefineRegular() = default; + RefineRegular(const GooseFEM::Mesh::Quad4::Regular& mesh, size_t nx, size_t ny); + + // return the coarse or the fine mesh objects + GooseFEM::Mesh::Quad4::Regular getCoarseMesh() const; + GooseFEM::Mesh::Quad4::Regular getFineMesh() const; + + // elements of the fine mesh per element of the coarse mesh + xt::xtensor getMap() const; + + // map field + xt::xtensor mapToCoarse(const xt::xtensor& data) const; // scalar per el + xt::xtensor mapToCoarse(const xt::xtensor& data) const; // scalar per intpnt + xt::xtensor mapToCoarse(const xt::xtensor& data) const; // tensor per intpnt + + // map field + xt::xtensor mapToFine(const xt::xtensor& data) const; // scalar per el + xt::xtensor mapToFine(const xt::xtensor& data) const; // scalar per intpnt + xt::xtensor mapToFine(const xt::xtensor& data) const; // tensor per intpnt + + private: + // the meshes + GooseFEM::Mesh::Quad4::Regular m_coarse; + GooseFEM::Mesh::Quad4::Regular m_fine; + + // mapping + xt::xtensor m_fine2coarse; + xt::xtensor m_fine2coarse_index; + xt::xtensor m_coarse2fine; + }; + + class FineLayer2Regular { + public: + // constructor + FineLayer2Regular() = default; + FineLayer2Regular(const GooseFEM::Mesh::Quad4::FineLayer& mesh); + + // return either of the meshes + GooseFEM::Mesh::Quad4::Regular getRegularMesh() const; + GooseFEM::Mesh::Quad4::FineLayer getFineLayerMesh() const; + + // elements of the Regular mesh per element of the FineLayer mesh + // and the fraction by which the overlap is + std::vector> getMap() const; + std::vector> getMapFraction() const; + + // map field + xt::xtensor mapToRegular(const xt::xtensor& data) const; // scalar per el + xt::xtensor mapToRegular(const xt::xtensor& data) const; // scalar per intpnt + xt::xtensor mapToRegular(const xt::xtensor& data) const; // tensor per intpnt + + private: + // the "FineLayer" mesh to map + GooseFEM::Mesh::Quad4::FineLayer m_finelayer; + + // the new "Regular" mesh to which to map + GooseFEM::Mesh::Quad4::Regular m_regular; + + // mapping + std::vector> m_elem_regular; + std::vector> m_frac_regular; + }; } // namespace Map } // namespace Quad4 } // namespace Mesh } // namespace GooseFEM #include "MeshQuad4.hpp" #endif