diff --git a/include/GooseFEM/Element.hpp b/include/GooseFEM/Element.hpp index f786978..1c68cbb 100644 --- a/include/GooseFEM/Element.hpp +++ b/include/GooseFEM/Element.hpp @@ -1,111 +1,108 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_ELEMENT_HPP #define GOOSEFEM_ELEMENT_HPP -// ------------------------------------------------------------------------------------------------- - #include "Element.h" -// ================================================================================================= - namespace GooseFEM { namespace Element { -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor asElementVector( - const xt::xtensor& conn, - const xt::xtensor& nodevec) +inline xt::xtensor +asElementVector(const xt::xtensor& conn, const xt::xtensor& nodevec) { - size_t nelem = conn.shape(0); - size_t nne = conn.shape(1); - size_t ndim = nodevec.shape(1); - - xt::xtensor elemvec = xt::empty({nelem, nne, ndim}); - - #pragma omp parallel for - for (size_t e = 0 ; e < nelem ; ++e) - for (size_t m = 0 ; m < nne ; ++m) - for (size_t i = 0 ; i < ndim ; ++i) - elemvec(e,m,i) = nodevec(conn(e,m),i); - - return elemvec; + size_t nelem = conn.shape(0); + size_t nne = conn.shape(1); + size_t ndim = nodevec.shape(1); + + xt::xtensor elemvec = xt::empty({nelem, nne, ndim}); + + #pragma omp parallel for + for (size_t e = 0; e < nelem; ++e) { + for (size_t m = 0; m < nne; ++m) { + for (size_t i = 0; i < ndim; ++i) { + elemvec(e, m, i) = nodevec(conn(e, m), i); + } + } + } + + return elemvec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor assembleNodeVector( - const xt::xtensor& conn, - const xt::xtensor& elemvec) +inline xt::xtensor +assembleNodeVector(const xt::xtensor& conn, const xt::xtensor& elemvec) { - size_t nelem = conn.shape(0); - size_t nne = conn.shape(1); - size_t ndim = elemvec.shape(2); - size_t nnode = xt::amax(conn)[0]+1; + size_t nelem = conn.shape(0); + size_t nne = conn.shape(1); + size_t ndim = elemvec.shape(2); + size_t nnode = xt::amax(conn)[0] + 1; - GOOSEFEM_ASSERT(elemvec.shape(0) == nelem); - GOOSEFEM_ASSERT(elemvec.shape(1) == nne); + GOOSEFEM_ASSERT(elemvec.shape(0) == nelem); + GOOSEFEM_ASSERT(elemvec.shape(1) == nne); - xt::xtensor nodevec = xt::zeros({nnode, ndim}); + xt::xtensor nodevec = xt::zeros({nnode, ndim}); - for (size_t e = 0 ; e < nelem ; ++e) - for (size_t m = 0 ; m < nne ; ++m) - for (size_t i = 0 ; i < ndim ; ++i) - nodevec(conn(e,m),i) += elemvec(e,m,i); + for (size_t e = 0; e < nelem; ++e) { + for (size_t m = 0; m < nne; ++m) { + for (size_t i = 0; i < ndim; ++i) { + nodevec(conn(e, m), i) += elemvec(e, m, i); + } + } + } - return nodevec; + return nodevec; } -// ------------------------------------------------------------------------------------------------- - -template +template inline bool isSequential(const E& dofs) { - size_t ndof = xt::amax(dofs)[0] + 1; + size_t ndof = xt::amax(dofs)[0] + 1; - xt::xtensor exists = xt::zeros({ndof}); + xt::xtensor exists = xt::zeros({ndof}); - for (auto& i: dofs) - exists[i]++; + for (auto& i : dofs) { + exists[i]++; + } - for (auto& i: dofs) - if (exists[i] == 0) - return false; + for (auto& i : dofs) { + if (exists[i] == 0) { + return false; + } + } - return true; + return true; } -// ------------------------------------------------------------------------------------------------- - inline bool isDiagonal(const xt::xtensor& elemmat) { - GOOSEFEM_ASSERT(elemmat.shape(1) == elemmat.shape(2)); - - size_t nelem = elemmat.shape(0); - size_t N = elemmat.shape(1); - - double eps = std::numeric_limits::epsilon(); - - #pragma omp parallel for - for (size_t e = 0 ; e < nelem ; ++e) - for (size_t i = 0 ; i < N ; ++i) - for (size_t j = 0 ; j < N ; ++j) - if (i != j) - if (std::abs(elemmat(e,i,j)) > eps) - return false; - - return true; + GOOSEFEM_ASSERT(elemmat.shape(1) == elemmat.shape(2)); + + size_t nelem = elemmat.shape(0); + size_t N = elemmat.shape(1); + + double eps = std::numeric_limits::epsilon(); + + #pragma omp parallel for + for (size_t e = 0; e < nelem; ++e) { + for (size_t i = 0; i < N; ++i) { + for (size_t j = 0; j < N; ++j) { + if (i != j) { + if (std::abs(elemmat(e, i, j)) > eps) { + return false; + } + } + } + } + } + + return true; } -// ------------------------------------------------------------------------------------------------- - -}} // namespace ... - -// ================================================================================================= +} // namespace Element +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/ElementHex8.hpp b/include/GooseFEM/ElementHex8.hpp index 143f851..d01c483 100644 --- a/include/GooseFEM/ElementHex8.hpp +++ b/include/GooseFEM/ElementHex8.hpp @@ -1,707 +1,655 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_ELEMENTHEX8_HPP #define GOOSEFEM_ELEMENTHEX8_HPP -// ------------------------------------------------------------------------------------------------- - #include "ElementHex8.h" -// ================================================================================================= - namespace GooseFEM { namespace Element { namespace Hex8 { -// ================================================================================================= - -inline double inv( - const xt::xtensor_fixed>& A, - xt::xtensor_fixed>& Ainv) +inline double inv(const xt::xtensor_fixed>& A, + xt::xtensor_fixed>& Ainv) { - // compute determinant - double det = ( A(0,0) * A(1,1) * A(2,2) + - A(0,1) * A(1,2) * A(2,0) + - A(0,2) * A(1,0) * A(2,1) ) - - ( A(0,2) * A(1,1) * A(2,0) + - A(0,1) * A(1,0) * A(2,2) + - A(0,0) * A(1,2) * A(2,1) ); + double det = + (A(0, 0) * A(1, 1) * A(2, 2) + A(0, 1) * A(1, 2) * A(2, 0) + A(0, 2) * A(1, 0) * A(2, 1)) - + (A(0, 2) * A(1, 1) * A(2, 0) + A(0, 1) * A(1, 0) * A(2, 2) + A(0, 0) * A(1, 2) * A(2, 1)); - // compute inverse - Ainv(0,0) = (A(1,1)*A(2,2)-A(1,2)*A(2,1)) / det; - Ainv(0,1) = (A(0,2)*A(2,1)-A(0,1)*A(2,2)) / det; - Ainv(0,2) = (A(0,1)*A(1,2)-A(0,2)*A(1,1)) / det; - Ainv(1,0) = (A(1,2)*A(2,0)-A(1,0)*A(2,2)) / det; - Ainv(1,1) = (A(0,0)*A(2,2)-A(0,2)*A(2,0)) / det; - Ainv(1,2) = (A(0,2)*A(1,0)-A(0,0)*A(1,2)) / det; - Ainv(2,0) = (A(1,0)*A(2,1)-A(1,1)*A(2,0)) / det; - Ainv(2,1) = (A(0,1)*A(2,0)-A(0,0)*A(2,1)) / det; - Ainv(2,2) = (A(0,0)*A(1,1)-A(0,1)*A(1,0)) / det; + Ainv(0, 0) = (A(1, 1) * A(2, 2) - A(1, 2) * A(2, 1)) / det; + Ainv(0, 1) = (A(0, 2) * A(2, 1) - A(0, 1) * A(2, 2)) / det; + Ainv(0, 2) = (A(0, 1) * A(1, 2) - A(0, 2) * A(1, 1)) / det; - return det; -} + Ainv(1, 0) = (A(1, 2) * A(2, 0) - A(1, 0) * A(2, 2)) / det; + Ainv(1, 1) = (A(0, 0) * A(2, 2) - A(0, 2) * A(2, 0)) / det; + Ainv(1, 2) = (A(0, 2) * A(1, 0) - A(0, 0) * A(1, 2)) / det; -// ================================================================================================= + Ainv(2, 0) = (A(1, 0) * A(2, 1) - A(1, 1) * A(2, 0)) / det; + Ainv(2, 1) = (A(0, 1) * A(2, 0) - A(0, 0) * A(2, 1)) / det; + Ainv(2, 2) = (A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0)) / det; -namespace Gauss { + return det; +} -// ------------------------------------------------------------------------------------------------- +namespace Gauss { inline size_t nip() { - return 8; + return 8; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor xi() { - size_t nip = 8; - size_t ndim = 3; + size_t nip = 8; + size_t ndim = 3; - xt::xtensor xi = xt::empty({nip,ndim}); + xt::xtensor xi = xt::empty({nip, ndim}); - xi(0,0) = -1./std::sqrt(3.); xi(0,1) = -1./std::sqrt(3.); xi(0,2) = -1./std::sqrt(3.); - xi(1,0) = +1./std::sqrt(3.); xi(1,1) = -1./std::sqrt(3.); xi(1,2) = -1./std::sqrt(3.); - xi(2,0) = +1./std::sqrt(3.); xi(2,1) = +1./std::sqrt(3.); xi(2,2) = -1./std::sqrt(3.); - xi(3,0) = -1./std::sqrt(3.); xi(3,1) = +1./std::sqrt(3.); xi(3,2) = -1./std::sqrt(3.); - xi(4,0) = -1./std::sqrt(3.); xi(4,1) = -1./std::sqrt(3.); xi(4,2) = +1./std::sqrt(3.); - xi(5,0) = +1./std::sqrt(3.); xi(5,1) = -1./std::sqrt(3.); xi(5,2) = +1./std::sqrt(3.); - xi(6,0) = +1./std::sqrt(3.); xi(6,1) = +1./std::sqrt(3.); xi(6,2) = +1./std::sqrt(3.); - xi(7,0) = -1./std::sqrt(3.); xi(7,1) = +1./std::sqrt(3.); xi(7,2) = +1./std::sqrt(3.); + xi(0, 0) = -1.0 / std::sqrt(3.0); + xi(0, 1) = -1.0 / std::sqrt(3.0); + xi(0, 2) = -1.0 / std::sqrt(3.0); - return xi; -} + xi(1, 0) = +1.0 / std::sqrt(3.0); + xi(1, 1) = -1.0 / std::sqrt(3.0); + xi(1, 2) = -1.0 / std::sqrt(3.0); -// ------------------------------------------------------------------------------------------------- + xi(2, 0) = +1.0 / std::sqrt(3.0); + xi(2, 1) = +1.0 / std::sqrt(3.0); + xi(2, 2) = -1.0 / std::sqrt(3.0); -inline xt::xtensor w() -{ - size_t nip = 8; + xi(3, 0) = -1.0 / std::sqrt(3.0); + xi(3, 1) = +1.0 / std::sqrt(3.0); + xi(3, 2) = -1.0 / std::sqrt(3.0); + + xi(4, 0) = -1.0 / std::sqrt(3.0); + xi(4, 1) = -1.0 / std::sqrt(3.0); + xi(4, 2) = +1.0 / std::sqrt(3.0); - xt::xtensor w = xt::empty({nip}); + xi(5, 0) = +1.0 / std::sqrt(3.0); + xi(5, 1) = -1.0 / std::sqrt(3.0); + xi(5, 2) = +1.0 / std::sqrt(3.0); - w(0) = 1.; - w(1) = 1.; - w(2) = 1.; - w(3) = 1.; - w(4) = 1.; - w(5) = 1.; - w(6) = 1.; - w(7) = 1.; + xi(6, 0) = +1.0 / std::sqrt(3.0); + xi(6, 1) = +1.0 / std::sqrt(3.0); + xi(6, 2) = +1.0 / std::sqrt(3.0); - return w; + xi(7, 0) = -1.0 / std::sqrt(3.0); + xi(7, 1) = +1.0 / std::sqrt(3.0); + xi(7, 2) = +1.0 / std::sqrt(3.0); + + return xi; } -// ------------------------------------------------------------------------------------------------- +inline xt::xtensor w() +{ + size_t nip = 8; + + xt::xtensor w = xt::empty({nip}); + w(0) = 1.0; + w(1) = 1.0; + w(2) = 1.0; + w(3) = 1.0; + w(4) = 1.0; + w(5) = 1.0; + w(6) = 1.0; + w(7) = 1.0; + + return w; } -// ================================================================================================= +} // namespace Gauss namespace Nodal { -// ------------------------------------------------------------------------------------------------- - inline size_t nip() { - return 8; + return 8; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor xi() { - size_t nip = 8; - size_t ndim = 3; + size_t nip = 8; + size_t ndim = 3; - xt::xtensor xi = xt::empty({nip,ndim}); + xt::xtensor xi = xt::empty({nip, ndim}); - xi(0,0) = -1.; xi(0,1) = -1.; xi(0,2) = -1.; - xi(1,0) = +1.; xi(1,1) = -1.; xi(1,2) = -1.; - xi(2,0) = +1.; xi(2,1) = +1.; xi(2,2) = -1.; - xi(3,0) = -1.; xi(3,1) = +1.; xi(3,2) = -1.; - xi(4,0) = -1.; xi(4,1) = -1.; xi(4,2) = +1.; - xi(5,0) = +1.; xi(5,1) = -1.; xi(5,2) = +1.; - xi(6,0) = +1.; xi(6,1) = +1.; xi(6,2) = +1.; - xi(7,0) = -1.; xi(7,1) = +1.; xi(7,2) = +1.; + xi(0, 0) = -1.0; + xi(0, 1) = -1.0; + xi(0, 2) = -1.0; - return xi; -} + xi(1, 0) = +1.0; + xi(1, 1) = -1.0; + xi(1, 2) = -1.0; + + xi(2, 0) = +1.0; + xi(2, 1) = +1.0; + xi(2, 2) = -1.0; + + xi(3, 0) = -1.0; + xi(3, 1) = +1.0; + xi(3, 2) = -1.0; + + xi(4, 0) = -1.0; + xi(4, 1) = -1.0; + xi(4, 2) = +1.0; + + xi(5, 0) = +1.0; + xi(5, 1) = -1.0; + xi(5, 2) = +1.0; -// ------------------------------------------------------------------------------------------------- + xi(6, 0) = +1.0; + xi(6, 1) = +1.0; + xi(6, 2) = +1.0; + + xi(7, 0) = -1.0; + xi(7, 1) = +1.0; + xi(7, 2) = +1.0; + + return xi; +} inline xt::xtensor w() { - size_t nip = 8; + size_t nip = 8; - xt::xtensor w = xt::empty({nip}); + xt::xtensor w = xt::empty({nip}); - w(0) = 1.; - w(1) = 1.; - w(2) = 1.; - w(3) = 1.; - w(4) = 1.; - w(5) = 1.; - w(6) = 1.; - w(7) = 1.; + w(0) = 1.0; + w(1) = 1.0; + w(2) = 1.0; + w(3) = 1.0; + w(4) = 1.0; + w(5) = 1.0; + w(6) = 1.0; + w(7) = 1.0; - return w; + return w; } -// ------------------------------------------------------------------------------------------------- +} // namespace Nodal +inline Quadrature::Quadrature(const xt::xtensor& x) + : Quadrature(x, Gauss::xi(), Gauss::w()) +{ } -// ================================================================================================= - -inline Quadrature::Quadrature(const xt::xtensor& x) : - Quadrature(x, Gauss::xi(), Gauss::w()) {} +inline Quadrature::Quadrature( + const xt::xtensor& x, + const xt::xtensor& xi, + const xt::xtensor& w) + : m_x(x), m_w(w), m_xi(xi) +{ + GOOSEFEM_ASSERT(m_x.shape(1) == m_nne); + GOOSEFEM_ASSERT(m_x.shape(2) == m_ndim); + + m_nelem = m_x.shape(0); + m_nip = m_w.size(); + + GOOSEFEM_ASSERT(m_xi.shape(0) == m_nip); + GOOSEFEM_ASSERT(m_xi.shape(1) == m_ndim); + GOOSEFEM_ASSERT(m_w.size() == m_nip); + + m_N = xt::empty({m_nip, m_nne}); + m_dNxi = xt::empty({m_nip, m_nne, m_ndim}); + m_dNx = xt::empty({m_nelem, m_nip, m_nne, m_ndim}); + m_vol = xt::empty({m_nelem, m_nip}); + + // shape functions + for (size_t q = 0; q < m_nip; ++q) { + m_N(q, 0) = 0.125 * (1.0 - m_xi(q, 0)) * (1.0 - m_xi(q, 1)) * (1.0 - m_xi(q, 2)); + m_N(q, 1) = 0.125 * (1.0 + m_xi(q, 0)) * (1.0 - m_xi(q, 1)) * (1.0 - m_xi(q, 2)); + m_N(q, 2) = 0.125 * (1.0 + m_xi(q, 0)) * (1.0 + m_xi(q, 1)) * (1.0 - m_xi(q, 2)); + m_N(q, 3) = 0.125 * (1.0 - m_xi(q, 0)) * (1.0 + m_xi(q, 1)) * (1.0 - m_xi(q, 2)); + m_N(q, 4) = 0.125 * (1.0 - m_xi(q, 0)) * (1.0 - m_xi(q, 1)) * (1.0 + m_xi(q, 2)); + m_N(q, 5) = 0.125 * (1.0 + m_xi(q, 0)) * (1.0 - m_xi(q, 1)) * (1.0 + m_xi(q, 2)); + m_N(q, 6) = 0.125 * (1.0 + m_xi(q, 0)) * (1.0 + m_xi(q, 1)) * (1.0 + m_xi(q, 2)); + m_N(q, 7) = 0.125 * (1.0 - m_xi(q, 0)) * (1.0 + m_xi(q, 1)) * (1.0 + m_xi(q, 2)); + } -// ------------------------------------------------------------------------------------------------- + // shape function gradients in local coordinates + for (size_t q = 0; q < m_nip; ++q) { + // - dN / dxi_0 + m_dNxi(q, 0, 0) = -0.125 * (1.0 - m_xi(q, 1)) * (1.0 - m_xi(q, 2)); + m_dNxi(q, 1, 0) = +0.125 * (1.0 - m_xi(q, 1)) * (1.0 - m_xi(q, 2)); + m_dNxi(q, 2, 0) = +0.125 * (1.0 + m_xi(q, 1)) * (1.0 - m_xi(q, 2)); + m_dNxi(q, 3, 0) = -0.125 * (1.0 + m_xi(q, 1)) * (1.0 - m_xi(q, 2)); + m_dNxi(q, 4, 0) = -0.125 * (1.0 - m_xi(q, 1)) * (1.0 + m_xi(q, 2)); + m_dNxi(q, 5, 0) = +0.125 * (1.0 - m_xi(q, 1)) * (1.0 + m_xi(q, 2)); + m_dNxi(q, 6, 0) = +0.125 * (1.0 + m_xi(q, 1)) * (1.0 + m_xi(q, 2)); + m_dNxi(q, 7, 0) = -0.125 * (1.0 + m_xi(q, 1)) * (1.0 + m_xi(q, 2)); + // - dN / dxi_1 + m_dNxi(q, 0, 1) = -0.125 * (1.0 - m_xi(q, 0)) * (1.0 - m_xi(q, 2)); + m_dNxi(q, 1, 1) = -0.125 * (1.0 + m_xi(q, 0)) * (1.0 - m_xi(q, 2)); + m_dNxi(q, 2, 1) = +0.125 * (1.0 + m_xi(q, 0)) * (1.0 - m_xi(q, 2)); + m_dNxi(q, 3, 1) = +0.125 * (1.0 - m_xi(q, 0)) * (1.0 - m_xi(q, 2)); + m_dNxi(q, 4, 1) = -0.125 * (1.0 - m_xi(q, 0)) * (1.0 + m_xi(q, 2)); + m_dNxi(q, 5, 1) = -0.125 * (1.0 + m_xi(q, 0)) * (1.0 + m_xi(q, 2)); + m_dNxi(q, 6, 1) = +0.125 * (1.0 + m_xi(q, 0)) * (1.0 + m_xi(q, 2)); + m_dNxi(q, 7, 1) = +0.125 * (1.0 - m_xi(q, 0)) * (1.0 + m_xi(q, 2)); + // - dN / dxi_2 + m_dNxi(q, 0, 2) = -0.125 * (1.0 - m_xi(q, 0)) * (1.0 - m_xi(q, 1)); + m_dNxi(q, 1, 2) = -0.125 * (1.0 + m_xi(q, 0)) * (1.0 - m_xi(q, 1)); + m_dNxi(q, 2, 2) = -0.125 * (1.0 + m_xi(q, 0)) * (1.0 + m_xi(q, 1)); + m_dNxi(q, 3, 2) = -0.125 * (1.0 - m_xi(q, 0)) * (1.0 + m_xi(q, 1)); + m_dNxi(q, 4, 2) = +0.125 * (1.0 - m_xi(q, 0)) * (1.0 - m_xi(q, 1)); + m_dNxi(q, 5, 2) = +0.125 * (1.0 + m_xi(q, 0)) * (1.0 - m_xi(q, 1)); + m_dNxi(q, 6, 2) = +0.125 * (1.0 + m_xi(q, 0)) * (1.0 + m_xi(q, 1)); + m_dNxi(q, 7, 2) = +0.125 * (1.0 - m_xi(q, 0)) * (1.0 + m_xi(q, 1)); + } -inline Quadrature::Quadrature( - const xt::xtensor& x, - const xt::xtensor& xi, - const xt::xtensor& w) : - m_x(x), m_w(w), m_xi(xi) -{ - GOOSEFEM_ASSERT(m_x.shape(1) == m_nne); - GOOSEFEM_ASSERT(m_x.shape(2) == m_ndim); - - m_nelem = m_x.shape(0); - m_nip = m_w.size(); - - GOOSEFEM_ASSERT(m_xi.shape(0) == m_nip); - GOOSEFEM_ASSERT(m_xi.shape(1) == m_ndim); - GOOSEFEM_ASSERT(m_w.size() == m_nip); - - m_N = xt::empty({m_nip, m_nne}); - m_dNxi = xt::empty({m_nip, m_nne, m_ndim}); - m_dNx = xt::empty({m_nelem, m_nip, m_nne, m_ndim}); - m_vol = xt::empty({m_nelem, m_nip}); - - // shape functions - for (size_t q = 0 ; q < m_nip ; ++q) - { - m_N(q,0) = .125 * (1.-m_xi(q,0)) * (1.-m_xi(q,1)) * (1.-m_xi(q,2)); - m_N(q,1) = .125 * (1.+m_xi(q,0)) * (1.-m_xi(q,1)) * (1.-m_xi(q,2)); - m_N(q,2) = .125 * (1.+m_xi(q,0)) * (1.+m_xi(q,1)) * (1.-m_xi(q,2)); - m_N(q,3) = .125 * (1.-m_xi(q,0)) * (1.+m_xi(q,1)) * (1.-m_xi(q,2)); - m_N(q,4) = .125 * (1.-m_xi(q,0)) * (1.-m_xi(q,1)) * (1.+m_xi(q,2)); - m_N(q,5) = .125 * (1.+m_xi(q,0)) * (1.-m_xi(q,1)) * (1.+m_xi(q,2)); - m_N(q,6) = .125 * (1.+m_xi(q,0)) * (1.+m_xi(q,1)) * (1.+m_xi(q,2)); - m_N(q,7) = .125 * (1.-m_xi(q,0)) * (1.+m_xi(q,1)) * (1.+m_xi(q,2)); - } - - // shape function gradients in local coordinates - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - dN / dxi_0 - m_dNxi(q,0,0) = -.125*(1.-m_xi(q,1))*(1.-m_xi(q,2)); - m_dNxi(q,1,0) = +.125*(1.-m_xi(q,1))*(1.-m_xi(q,2)); - m_dNxi(q,2,0) = +.125*(1.+m_xi(q,1))*(1.-m_xi(q,2)); - m_dNxi(q,3,0) = -.125*(1.+m_xi(q,1))*(1.-m_xi(q,2)); - m_dNxi(q,4,0) = -.125*(1.-m_xi(q,1))*(1.+m_xi(q,2)); - m_dNxi(q,5,0) = +.125*(1.-m_xi(q,1))*(1.+m_xi(q,2)); - m_dNxi(q,6,0) = +.125*(1.+m_xi(q,1))*(1.+m_xi(q,2)); - m_dNxi(q,7,0) = -.125*(1.+m_xi(q,1))*(1.+m_xi(q,2)); - // - dN / dxi_1 - m_dNxi(q,0,1) = -.125*(1.-m_xi(q,0))*(1.-m_xi(q,2)); - m_dNxi(q,1,1) = -.125*(1.+m_xi(q,0))*(1.-m_xi(q,2)); - m_dNxi(q,2,1) = +.125*(1.+m_xi(q,0))*(1.-m_xi(q,2)); - m_dNxi(q,3,1) = +.125*(1.-m_xi(q,0))*(1.-m_xi(q,2)); - m_dNxi(q,4,1) = -.125*(1.-m_xi(q,0))*(1.+m_xi(q,2)); - m_dNxi(q,5,1) = -.125*(1.+m_xi(q,0))*(1.+m_xi(q,2)); - m_dNxi(q,6,1) = +.125*(1.+m_xi(q,0))*(1.+m_xi(q,2)); - m_dNxi(q,7,1) = +.125*(1.-m_xi(q,0))*(1.+m_xi(q,2)); - // - dN / dxi_2 - m_dNxi(q,0,2) = -.125*(1.-m_xi(q,0))*(1.-m_xi(q,1)); - m_dNxi(q,1,2) = -.125*(1.+m_xi(q,0))*(1.-m_xi(q,1)); - m_dNxi(q,2,2) = -.125*(1.+m_xi(q,0))*(1.+m_xi(q,1)); - m_dNxi(q,3,2) = -.125*(1.-m_xi(q,0))*(1.+m_xi(q,1)); - m_dNxi(q,4,2) = +.125*(1.-m_xi(q,0))*(1.-m_xi(q,1)); - m_dNxi(q,5,2) = +.125*(1.+m_xi(q,0))*(1.-m_xi(q,1)); - m_dNxi(q,6,2) = +.125*(1.+m_xi(q,0))*(1.+m_xi(q,1)); - m_dNxi(q,7,2) = +.125*(1.-m_xi(q,0))*(1.+m_xi(q,1)); - } - - // compute the shape function gradients, based on "x" - compute_dN(); -} - -// ------------------------------------------------------------------------------------------------- + // compute the shape function gradients, based on "x" + compute_dN(); +} inline size_t Quadrature::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t Quadrature::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t Quadrature::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t Quadrature::nip() const { - return m_nip; + return m_nip; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Quadrature::GradN() const { - return m_dNx; + return m_dNx; } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::dV(xt::xtensor& qscalar) const { - GOOSEFEM_ASSERT(qscalar.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip})); + GOOSEFEM_ASSERT( + qscalar.shape() == std::decay_t::shape_type({m_nelem, m_nip})); - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t q = 0 ; q < m_nip ; ++q) - qscalar(e,q) = m_vol(e,q); + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t q = 0; q < m_nip; ++q) { + qscalar(e, q) = m_vol(e, q); + } + } } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::dV(xt::xtensor& qtensor) const { - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t q = 0 ; q < m_nip ; ++q) - for (size_t i = 0 ; i < m_ndim ; ++i) - for (size_t j = 0 ; j < m_ndim ; ++j) - qtensor(e,q,i,j) = m_vol(e,q); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t q = 0; q < m_nip; ++q) { + for (size_t i = 0; i < m_ndim; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + qtensor(e, q, i, j) = m_vol(e, q); + } + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::dV(xt::xarray& qtensor) const { - GOOSEFEM_ASSERT(qtensor.shape(0) == m_nelem); - GOOSEFEM_ASSERT(qtensor.shape(1) == m_nip); + GOOSEFEM_ASSERT(qtensor.shape(0) == m_nelem); + GOOSEFEM_ASSERT(qtensor.shape(1) == m_nip); - xt::dynamic_shape strides = { - static_cast(m_vol.strides()[0]), - static_cast(m_vol.strides()[1])}; + xt::dynamic_shape strides = {static_cast(m_vol.strides()[0]), + static_cast(m_vol.strides()[1])}; - for (size_t i = 2; i < qtensor.shape().size(); ++i) - strides.push_back(0); + for (size_t i = 2; i < qtensor.shape().size(); ++i) { + strides.push_back(0); + } - qtensor = xt::strided_view(m_vol, qtensor.shape(), std::move(strides), 0ul, xt::layout_type::dynamic); + qtensor = + xt::strided_view(m_vol, qtensor.shape(), std::move(strides), 0ul, xt::layout_type::dynamic); } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::update_x(const xt::xtensor& x) { - GOOSEFEM_ASSERT(x.shape() == m_x.shape()); - - xt::noalias(m_x) = x; - - // update the shape function gradients for the new "x" - compute_dN(); + GOOSEFEM_ASSERT(x.shape() == m_x.shape()); + xt::noalias(m_x) = x; + compute_dN(); } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::compute_dN() { - #pragma omp parallel - { - // allocate local variables - xt::xtensor_fixed> J, Jinv; - - // loop over all elements (in parallel) - #pragma omp for - for (size_t e = 0 ; e < m_nelem ; ++e) + #pragma omp parallel { - // alias nodal positions - auto x = xt::adapt(&m_x(e,0,0), xt::xshape()); - - // loop over integration points - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNxi = xt::adapt(&m_dNxi( q,0,0), xt::xshape()); - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - - // - zero-initialize - J.fill(0.0); - - // - Jacobian - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - for (size_t j = 0 ; j < m_ndim ; ++j) - J(i,j) += dNxi(m,i) * x(m,j); - - // - determinant and inverse of the Jacobian - double Jdet = inv(J, Jinv); - - // - shape function gradients wrt global coordinates (loops partly unrolled for efficiency) - // dNx(m,i) += Jinv(i,j) * dNxi(m,j); - for (size_t m = 0 ; m < m_nne ; ++m) - { - dNx(m,0) = Jinv(0,0) * dNxi(m,0) + Jinv(0,1) * dNxi(m,1) + Jinv(0,2) * dNxi(m,2); - dNx(m,1) = Jinv(1,0) * dNxi(m,0) + Jinv(1,1) * dNxi(m,1) + Jinv(1,2) * dNxi(m,2); - dNx(m,2) = Jinv(2,0) * dNxi(m,0) + Jinv(2,1) * dNxi(m,1) + Jinv(2,2) * dNxi(m,2); + xt::xtensor_fixed> J, Jinv; + + #pragma omp for + for (size_t e = 0; e < m_nelem; ++e) { + + auto x = xt::adapt(&m_x(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNxi = xt::adapt(&m_dNxi(q, 0, 0), xt::xshape()); + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + + J.fill(0.0); + + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + J(i, j) += dNxi(m, i) * x(m, j); + } + } + } + + double Jdet = inv(J, Jinv); + + // dNx(m,i) += Jinv(i,j) * dNxi(m,j); + for (size_t m = 0; m < m_nne; ++m) { + dNx(m, 0) + = Jinv(0, 0) * dNxi(m, 0) + + Jinv(0, 1) * dNxi(m, 1) + + Jinv(0, 2) * dNxi(m, 2); + dNx(m, 1) + = Jinv(1, 0) * dNxi(m, 0) + + Jinv(1, 1) * dNxi(m, 1) + + Jinv(1, 2) * dNxi(m, 2); + dNx(m, 2) + = Jinv(2, 0) * dNxi(m, 0) + + Jinv(2, 1) * dNxi(m, 1) + + Jinv(2, 2) * dNxi(m, 2); + } + + m_vol(e, q) = m_w(q) * Jdet; + } } - - // - integration point volume - m_vol(e,q) = m_w(q) * Jdet; - } } - } } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::gradN_vector( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); - - // zero-initialize - qtensor.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto gradu = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - - // - evaluate dyadic product - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - for (size_t j = 0 ; j < m_ndim ; ++j) - gradu(i,j) += dNx(m,i) * u(m,j); - } - } -} + const xt::xtensor& elemvec, xt::xtensor& qtensor) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); -// ------------------------------------------------------------------------------------------------- + qtensor.fill(0.0); -inline void Quadrature::gradN_vector_T( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); - - // zero-initialize - qtensor.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto gradu = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - - // - evaluate transpose of dyadic product - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - for (size_t j = 0 ; j < m_ndim ; ++j) - gradu(j,i) += dNx(m,i) * u(m,j); + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto gradu = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + gradu(i, j) += dNx(m, i) * u(m, j); + } + } + } + } } - } } -// ------------------------------------------------------------------------------------------------- +inline void Quadrature::gradN_vector_T( + const xt::xtensor& elemvec, xt::xtensor& qtensor) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); -inline void Quadrature::symGradN_vector( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); - - // zero-initialize - qtensor.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto eps = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - - // - evaluate symmetrized dyadic product - for (size_t m = 0 ; m < m_nne ; ++m ){ - for (size_t i = 0 ; i < m_ndim ; ++i ){ - for (size_t j = 0 ; j < m_ndim ; ++j ){ - eps(i,j) += dNx(m,i) * u(m,j) / 2.; - eps(j,i) += dNx(m,i) * u(m,j) / 2.; - } + qtensor.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto gradu = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + gradu(j, i) += dNx(m, i) * u(m, j); + } + } + } } - } } - } } -// ------------------------------------------------------------------------------------------------- +inline void Quadrature::symGradN_vector( + const xt::xtensor& elemvec, xt::xtensor& qtensor) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); + + qtensor.fill(0.0); -inline void Quadrature::int_N_scalar_NT_dV( - const xt::xtensor& qscalar, - xt::xtensor& elemmat) const -{ - GOOSEFEM_ASSERT(qscalar.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip})); - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - // zero-initialize: matrix of matrices - elemmat.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. mass matrix) - auto M = xt::adapt(&elemmat(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto N = xt::adapt(&m_N(q,0), xt::xshape()); - auto& vol = m_vol (e,q); - auto& rho = qscalar(e,q); - - // - evaluate scalar product, for all dimensions, and assemble - // M(m*ndim+i,n*ndim+i) += N(m) * scalar * N(n) * dV - for (size_t m = 0 ; m < m_nne ; ++m ){ - for (size_t n = 0 ; n < m_nne ; ++n ){ - M(m*m_ndim+0, n*m_ndim+0) += N(m) * rho * N(n) * vol; - M(m*m_ndim+1, n*m_ndim+1) += N(m) * rho * N(n) * vol; - M(m*m_ndim+2, n*m_ndim+2) += N(m) * rho * N(n) * vol; + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto eps = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + eps(i, j) += 0.5 * dNx(m, i) * u(m, j); + eps(j, i) += 0.5 * dNx(m, i) * u(m, j); + } + } + } } - } } - } } -// ------------------------------------------------------------------------------------------------- +inline void Quadrature::int_N_scalar_NT_dV( + const xt::xtensor& qscalar, xt::xtensor& elemmat) const +{ + GOOSEFEM_ASSERT( + qscalar.shape() == std::decay_t::shape_type({m_nelem, m_nip})); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); -inline void Quadrature::int_gradN_dot_tensor2_dV( - const xt::xtensor& qtensor, - xt::xtensor& elemvec) const -{ - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - - // zero-initialize output: matrix of vectors - elemvec.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. nodal force) - auto f = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto sig = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - auto& vol = m_vol(e,q); - - // - evaluate dot product, and assemble - for (size_t m = 0 ; m < m_nne ; ++m) - { - f(m,0) += ( dNx(m,0) * sig(0,0) + dNx(m,1) * sig(1,0) + dNx(m,2) * sig(2,0) ) * vol; - f(m,1) += ( dNx(m,0) * sig(0,1) + dNx(m,1) * sig(1,1) + dNx(m,2) * sig(2,1) ) * vol; - f(m,2) += ( dNx(m,0) * sig(0,2) + dNx(m,1) * sig(1,2) + dNx(m,2) * sig(2,2) ) * vol; - } + elemmat.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto M = xt::adapt(&elemmat(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto N = xt::adapt(&m_N(q, 0), xt::xshape()); + auto& vol = m_vol(e, q); + auto& rho = qscalar(e, q); + + // M(m * ndim + i, n * ndim + i) += N(m) * scalar * N(n) * dV + for (size_t m = 0; m < m_nne; ++m) { + for (size_t n = 0; n < m_nne; ++n) { + M(m * m_ndim + 0, n * m_ndim + 0) += N(m) * rho * N(n) * vol; + M(m * m_ndim + 1, n * m_ndim + 1) += N(m) * rho * N(n) * vol; + M(m * m_ndim + 2, n * m_ndim + 2) += N(m) * rho * N(n) * vol; + } + } + } } - } } -// ------------------------------------------------------------------------------------------------- +inline void Quadrature::int_gradN_dot_tensor2_dV( + const xt::xtensor& qtensor, xt::xtensor& elemvec) const +{ + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + + elemvec.fill(0.0); -inline void Quadrature::int_gradN_dot_tensor4_dot_gradNT_dV( - const xt::xtensor& qtensor, - xt::xtensor& elemmat) const -{ - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim, m_ndim, m_ndim})); - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - // zero-initialize output: matrix of vector - elemmat.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. nodal force) - auto K = xt::adapt(&elemmat(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx(e,q,0,0), xt::xshape()); - auto C = xt::adapt(&qtensor(e,q,0,0,0,0), xt::xshape()); - auto& vol = m_vol(e,q); + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { - // - evaluate dot product, and assemble - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t n = 0 ; n < m_nne ; ++n) - for (size_t i = 0 ; i < m_ndim ; ++i) - for (size_t j = 0 ; j < m_ndim ; ++j) - for (size_t k = 0 ; k < m_ndim ; ++k) - for (size_t l = 0 ; l < m_ndim ; ++l) - K(m*m_ndim+j, n*m_ndim+k) += dNx(m,i) * C(i,j,k,l) * dNx(n,l) * vol; - } - } + auto f = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto sig = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + auto& vol = m_vol(e, q); + + for (size_t m = 0; m < m_nne; ++m) { + f(m, 0) += + (dNx(m, 0) * sig(0, 0) + dNx(m, 1) * sig(1, 0) + dNx(m, 2) * sig(2, 0)) * vol; + f(m, 1) += + (dNx(m, 0) * sig(0, 1) + dNx(m, 1) * sig(1, 1) + dNx(m, 2) * sig(2, 1)) * vol; + f(m, 2) += + (dNx(m, 0) * sig(0, 2) + dNx(m, 1) * sig(1, 2) + dNx(m, 2) * sig(2, 2)) * vol; + } + } + } } -// ------------------------------------------------------------------------------------------------- +inline void Quadrature::int_gradN_dot_tensor4_dot_gradNT_dV( + const xt::xtensor& qtensor, xt::xtensor& elemmat) const +{ + GOOSEFEM_ASSERT( + qtensor.shape() == std::decay_t::shape_type( + {m_nelem, m_nip, m_ndim, m_ndim, m_ndim, m_ndim})); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + + elemmat.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto K = xt::adapt(&elemmat(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e,q,0,0), xt::xshape()); + auto C = xt::adapt(&qtensor(e,q,0,0,0,0), xt::xshape()); + auto& vol = m_vol(e, q); + + for (size_t m = 0; m < m_nne; ++m) { + for (size_t n = 0; n < m_nne; ++n) { + for (size_t i = 0; i < m_ndim; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + for (size_t k = 0; k < m_ndim; ++k) { + for (size_t l = 0; l < m_ndim; ++l) { + K(m * m_ndim + j, n * m_ndim + k) += + dNx(m, i) * C(i, j, k, l) * dNx(n, l) * vol; + } + } + } + } + } + } + } + } +} inline xt::xtensor Quadrature::DV() const { - xt::xtensor out = xt::empty({m_nelem, m_nip}); - this->dV(out); - return out; + xt::xtensor out = xt::empty({m_nelem, m_nip}); + this->dV(out); + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xarray Quadrature::DV(size_t rank) const { - std::vector shape = {m_nelem, m_nip}; + std::vector shape = {m_nelem, m_nip}; - for (size_t i = 0; i < rank; ++i) - shape.push_back(static_cast(m_ndim)); + for (size_t i = 0; i < rank; ++i) { + shape.push_back(static_cast(m_ndim)); + } - xt::xarray out = xt::empty(shape); - this->dV(out); - return out; + xt::xarray out = xt::empty(shape); + this->dV(out); + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::GradN_vector( - const xt::xtensor& elemvec) const +inline xt::xtensor Quadrature::GradN_vector(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); - this->gradN_vector(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); + this->gradN_vector(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::GradN_vector_T( - const xt::xtensor& elemvec) const +inline xt::xtensor +Quadrature::GradN_vector_T(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); - this->gradN_vector_T(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); + this->gradN_vector_T(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::SymGradN_vector( - const xt::xtensor& elemvec) const +inline xt::xtensor +Quadrature::SymGradN_vector(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); - this->symGradN_vector(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); + this->symGradN_vector(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::Int_N_scalar_NT_dV( - const xt::xtensor& qscalar) const +inline xt::xtensor +Quadrature::Int_N_scalar_NT_dV(const xt::xtensor& qscalar) const { - xt::xtensor elemmat = xt::empty({m_nelem, m_nne*m_ndim, m_nne*m_ndim}); - this->int_N_scalar_NT_dV(qscalar, elemmat); - return elemmat; + xt::xtensor elemmat = xt::empty({m_nelem, m_nne * m_ndim, m_nne * m_ndim}); + this->int_N_scalar_NT_dV(qscalar, elemmat); + return elemmat; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::Int_gradN_dot_tensor2_dV( - const xt::xtensor& qtensor) const +inline xt::xtensor +Quadrature::Int_gradN_dot_tensor2_dV(const xt::xtensor& qtensor) const { - xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); - this->int_gradN_dot_tensor2_dV(qtensor, elemvec); - return elemvec; + xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); + this->int_gradN_dot_tensor2_dV(qtensor, elemvec); + return elemvec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::Int_gradN_dot_tensor4_dot_gradNT_dV( - const xt::xtensor& qtensor) const - { - xt::xtensor elemmat = xt::empty({m_nelem, m_ndim*m_nne, m_ndim*m_nne}); - this->int_gradN_dot_tensor4_dot_gradNT_dV(qtensor, elemmat); - return elemmat; - } - -// ------------------------------------------------------------------------------------------------- - -}}} // namespace ... +inline xt::xtensor +Quadrature::Int_gradN_dot_tensor4_dot_gradNT_dV(const xt::xtensor& qtensor) const +{ + xt::xtensor elemmat = xt::empty({m_nelem, m_ndim * m_nne, m_ndim * m_nne}); + this->int_gradN_dot_tensor4_dot_gradNT_dV(qtensor, elemmat); + return elemmat; +} -// ================================================================================================= +} // namespace Hex8 +} // namespace Element +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/ElementQuad4.hpp b/include/GooseFEM/ElementQuad4.hpp index 6b1225e..c103027 100644 --- a/include/GooseFEM/ElementQuad4.hpp +++ b/include/GooseFEM/ElementQuad4.hpp @@ -1,692 +1,638 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_ELEMENTQUAD4_HPP #define GOOSEFEM_ELEMENTQUAD4_HPP -// ------------------------------------------------------------------------------------------------- - #include "ElementQuad4.h" -// ================================================================================================= - namespace GooseFEM { namespace Element { namespace Quad4 { -// ================================================================================================= - -inline double inv( - const xt::xtensor_fixed>& A, - xt::xtensor_fixed>& Ainv) +inline double inv(const xt::xtensor_fixed>& A, + xt::xtensor_fixed>& Ainv) { - // compute determinant - double det = A(0,0) * A(1,1) - A(0,1) * A(1,0); + double det = A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0); - // compute inverse - Ainv(0,0) = A(1,1) / det; - Ainv(0,1) = -1. * A(0,1) / det; - Ainv(1,0) = -1. * A(1,0) / det; - Ainv(1,1) = A(0,0) / det; + Ainv(0, 0) = A(1, 1) / det; + Ainv(0, 1) = -1.0 * A(0, 1) / det; + Ainv(1, 0) = -1.0 * A(1, 0) / det; + Ainv(1, 1) = A(0, 0) / det; - return det; + return det; } -// ================================================================================================= - namespace Gauss { -// ------------------------------------------------------------------------------------------------- - inline size_t nip() { - return 4; + return 4; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor xi() { - size_t nip = 4; - size_t ndim = 2; + size_t nip = 4; + size_t ndim = 2; - xt::xtensor xi = xt::empty({nip,ndim}); + xt::xtensor xi = xt::empty({nip, ndim}); - xi(0,0) = -1./std::sqrt(3.); xi(0,1) = -1./std::sqrt(3.); - xi(1,0) = +1./std::sqrt(3.); xi(1,1) = -1./std::sqrt(3.); - xi(2,0) = +1./std::sqrt(3.); xi(2,1) = +1./std::sqrt(3.); - xi(3,0) = -1./std::sqrt(3.); xi(3,1) = +1./std::sqrt(3.); + xi(0, 0) = -1.0 / std::sqrt(3.0); + xi(0, 1) = -1.0 / std::sqrt(3.0); + xi(1, 0) = +1.0 / std::sqrt(3.0); + xi(1, 1) = -1.0 / std::sqrt(3.0); + xi(2, 0) = +1.0 / std::sqrt(3.0); + xi(2, 1) = +1.0 / std::sqrt(3.0); + xi(3, 0) = -1.0 / std::sqrt(3.0); + xi(3, 1) = +1.0 / std::sqrt(3.0); - return xi; + return xi; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor w() { - size_t nip = 4; + size_t nip = 4; - xt::xtensor w = xt::empty({nip}); + xt::xtensor w = xt::empty({nip}); - w(0) = 1.; - w(1) = 1.; - w(2) = 1.; - w(3) = 1.; + w(0) = 1.0; + w(1) = 1.0; + w(2) = 1.0; + w(3) = 1.0; - return w; + return w; } -// ------------------------------------------------------------------------------------------------- - -} - -// ================================================================================================= +} // namespace Gauss namespace Nodal { -// ------------------------------------------------------------------------------------------------- - inline size_t nip() { - return 4; + return 4; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor xi() { - size_t nip = 4; - size_t ndim = 2; + size_t nip = 4; + size_t ndim = 2; - xt::xtensor xi = xt::empty({nip,ndim}); + xt::xtensor xi = xt::empty({nip, ndim}); - xi(0,0) = -1.; xi(0,1) = -1.; - xi(1,0) = +1.; xi(1,1) = -1.; - xi(2,0) = +1.; xi(2,1) = +1.; - xi(3,0) = -1.; xi(3,1) = +1.; + xi(0, 0) = -1.0; + xi(0, 1) = -1.0; - return xi; -} + xi(1, 0) = +1.0; + xi(1, 1) = -1.0; -// ------------------------------------------------------------------------------------------------- + xi(2, 0) = +1.0; + xi(2, 1) = +1.0; -inline xt::xtensor w() -{ - size_t nip = 4; + xi(3, 0) = -1.0; + xi(3, 1) = +1.0; - xt::xtensor w = xt::empty({nip}); + return xi; +} - w(0) = 1.; - w(1) = 1.; - w(2) = 1.; - w(3) = 1.; +inline xt::xtensor w() +{ + size_t nip = 4; - return w; -} + xt::xtensor w = xt::empty({nip}); -// ------------------------------------------------------------------------------------------------- + w(0) = 1.0; + w(1) = 1.0; + w(2) = 1.0; + w(3) = 1.0; + return w; } -// ================================================================================================= +} // namespace Nodal namespace MidPoint { -// ------------------------------------------------------------------------------------------------- - inline size_t nip() { - return 1; + return 1; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor xi() { - size_t nip = 1; - size_t ndim = 2; + size_t nip = 1; + size_t ndim = 2; - xt::xtensor xi = xt::empty({nip,ndim}); + xt::xtensor xi = xt::empty({nip, ndim}); - xi(0,0) = 0.; xi(0,1) = 0.; + xi(0, 0) = 0.0; + xi(0, 1) = 0.0; - return xi; + return xi; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor w() { - size_t nip = 1; + size_t nip = 1; - xt::xtensor w = xt::empty({nip}); + xt::xtensor w = xt::empty({nip}); - w(0) = 1.; + w(0) = 1.0; - return w; + return w; } -// ------------------------------------------------------------------------------------------------- +} // namespace MidPoint +inline Quadrature::Quadrature(const xt::xtensor& x) + : Quadrature(x, Gauss::xi(), Gauss::w()) +{ } -// ================================================================================================= - -inline Quadrature::Quadrature(const xt::xtensor& x) : - Quadrature(x, Gauss::xi(), Gauss::w()) {} +inline Quadrature::Quadrature( + const xt::xtensor& x, + const xt::xtensor& xi, + const xt::xtensor& w) + : m_x(x), m_w(w), m_xi(xi) +{ + GOOSEFEM_ASSERT(m_x.shape(1) == m_nne); + GOOSEFEM_ASSERT(m_x.shape(2) == m_ndim); + + m_nelem = m_x.shape(0); + m_nip = m_w.size(); + + GOOSEFEM_ASSERT(m_xi.shape(0) == m_nip); + GOOSEFEM_ASSERT(m_xi.shape(1) == m_ndim); + GOOSEFEM_ASSERT(m_w.size() == m_nip); + + m_N = xt::empty({m_nip, m_nne}); + m_dNxi = xt::empty({m_nip, m_nne, m_ndim}); + m_dNx = xt::empty({m_nelem, m_nip, m_nne, m_ndim}); + m_vol = xt::empty({m_nelem, m_nip}); + + for (size_t q = 0; q < m_nip; ++q) { + m_N(q, 0) = 0.25 * (1.0 - m_xi(q, 0)) * (1.0 - m_xi(q, 1)); + m_N(q, 1) = 0.25 * (1.0 + m_xi(q, 0)) * (1.0 - m_xi(q, 1)); + m_N(q, 2) = 0.25 * (1.0 + m_xi(q, 0)) * (1.0 + m_xi(q, 1)); + m_N(q, 3) = 0.25 * (1.0 - m_xi(q, 0)) * (1.0 + m_xi(q, 1)); + } -// ------------------------------------------------------------------------------------------------- + for (size_t q = 0; q < m_nip; ++q) { + // - dN / dxi_0 + m_dNxi(q, 0, 0) = -0.25 * (1.0 - m_xi(q, 1)); + m_dNxi(q, 1, 0) = +0.25 * (1.0 - m_xi(q, 1)); + m_dNxi(q, 2, 0) = +0.25 * (1.0 + m_xi(q, 1)); + m_dNxi(q, 3, 0) = -0.25 * (1.0 + m_xi(q, 1)); + // - dN / dxi_1 + m_dNxi(q, 0, 1) = -0.25 * (1.0 - m_xi(q, 0)); + m_dNxi(q, 1, 1) = -0.25 * (1.0 + m_xi(q, 0)); + m_dNxi(q, 2, 1) = +0.25 * (1.0 + m_xi(q, 0)); + m_dNxi(q, 3, 1) = +0.25 * (1.0 - m_xi(q, 0)); + } -inline Quadrature::Quadrature( - const xt::xtensor& x, - const xt::xtensor& xi, - const xt::xtensor& w) : - m_x(x), m_w(w), m_xi(xi) -{ - GOOSEFEM_ASSERT(m_x.shape(1) == m_nne); - GOOSEFEM_ASSERT(m_x.shape(2) == m_ndim); - - m_nelem = m_x.shape(0); - m_nip = m_w.size(); - - GOOSEFEM_ASSERT(m_xi.shape(0) == m_nip); - GOOSEFEM_ASSERT(m_xi.shape(1) == m_ndim); - GOOSEFEM_ASSERT(m_w.size() == m_nip); - - m_N = xt::empty({m_nip, m_nne}); - m_dNxi = xt::empty({m_nip, m_nne, m_ndim}); - m_dNx = xt::empty({m_nelem, m_nip, m_nne, m_ndim}); - m_vol = xt::empty({m_nelem, m_nip}); - - // shape functions - for (size_t q = 0 ; q < m_nip ; ++q) - { - m_N(q,0) = .25 * (1.-m_xi(q,0)) * (1.-m_xi(q,1)); - m_N(q,1) = .25 * (1.+m_xi(q,0)) * (1.-m_xi(q,1)); - m_N(q,2) = .25 * (1.+m_xi(q,0)) * (1.+m_xi(q,1)); - m_N(q,3) = .25 * (1.-m_xi(q,0)) * (1.+m_xi(q,1)); - } - - // shape function gradients in local coordinates - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - dN / dxi_0 - m_dNxi(q,0,0) = -.25*(1.-m_xi(q,1)); - m_dNxi(q,1,0) = +.25*(1.-m_xi(q,1)); - m_dNxi(q,2,0) = +.25*(1.+m_xi(q,1)); - m_dNxi(q,3,0) = -.25*(1.+m_xi(q,1)); - // - dN / dxi_1 - m_dNxi(q,0,1) = -.25*(1.-m_xi(q,0)); - m_dNxi(q,1,1) = -.25*(1.+m_xi(q,0)); - m_dNxi(q,2,1) = +.25*(1.+m_xi(q,0)); - m_dNxi(q,3,1) = +.25*(1.-m_xi(q,0)); - } - - // compute the shape function gradients, based on "x" - compute_dN(); -} - -// ------------------------------------------------------------------------------------------------- + compute_dN(); +} inline size_t Quadrature::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t Quadrature::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t Quadrature::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t Quadrature::nip() const { - return m_nip; + return m_nip; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Quadrature::GradN() const { - return m_dNx; + return m_dNx; } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::dV(xt::xtensor& qscalar) const { - GOOSEFEM_ASSERT(qscalar.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip})); + GOOSEFEM_ASSERT( + qscalar.shape() == std::decay_t::shape_type({m_nelem, m_nip})); - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t q = 0 ; q < m_nip ; ++q) - qscalar(e,q) = m_vol(e,q); + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t q = 0; q < m_nip; ++q) { + qscalar(e, q) = m_vol(e, q); + } + } } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::dV(xt::xtensor& qtensor) const { - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t q = 0 ; q < m_nip ; ++q) - for (size_t i = 0 ; i < m_ndim ; ++i) - for (size_t j = 0 ; j < m_ndim ; ++j) - qtensor(e,q,i,j) = m_vol(e,q); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t q = 0; q < m_nip; ++q) { + for (size_t i = 0; i < m_ndim; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + qtensor(e, q, i, j) = m_vol(e, q); + } + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::dV(xt::xarray& qtensor) const { - GOOSEFEM_ASSERT(qtensor.shape(0) == m_nelem); - GOOSEFEM_ASSERT(qtensor.shape(1) == m_nip); + GOOSEFEM_ASSERT(qtensor.shape(0) == m_nelem); + GOOSEFEM_ASSERT(qtensor.shape(1) == m_nip); - xt::dynamic_shape strides = { - static_cast(m_vol.strides()[0]), - static_cast(m_vol.strides()[1])}; + xt::dynamic_shape strides = {static_cast(m_vol.strides()[0]), + static_cast(m_vol.strides()[1])}; - for (size_t i = 2; i < qtensor.shape().size(); ++i) - strides.push_back(0); + for (size_t i = 2; i < qtensor.shape().size(); ++i) { + strides.push_back(0); + } - qtensor = xt::strided_view(m_vol, qtensor.shape(), std::move(strides), 0ul, xt::layout_type::dynamic); + qtensor = + xt::strided_view(m_vol, qtensor.shape(), std::move(strides), 0ul, xt::layout_type::dynamic); } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::update_x(const xt::xtensor& x) { - GOOSEFEM_ASSERT(x.shape() == m_x.shape()); - - xt::noalias(m_x) = x; - - // update the shape function gradients for the new "x" - compute_dN(); + GOOSEFEM_ASSERT(x.shape() == m_x.shape()); + xt::noalias(m_x) = x; + compute_dN(); } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::compute_dN() { - #pragma omp parallel - { - // allocate local variables - xt::xtensor_fixed> J, Jinv; - - // loop over all elements (in parallel) - #pragma omp for - for (size_t e = 0 ; e < m_nelem ; ++e) + #pragma omp parallel { - // alias nodal positions - auto x = xt::adapt(&m_x(e,0,0), xt::xshape()); - - // loop over integration points - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNxi = xt::adapt(&m_dNxi( q,0,0), xt::xshape()); - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - - // - Jacobian (loops unrolled for efficiency) - // J(i,j) += dNxi(m,i) * x(m,j); - J(0,0) = dNxi(0,0)*x(0,0) + dNxi(1,0)*x(1,0) + dNxi(2,0)*x(2,0) + dNxi(3,0)*x(3,0); - J(0,1) = dNxi(0,0)*x(0,1) + dNxi(1,0)*x(1,1) + dNxi(2,0)*x(2,1) + dNxi(3,0)*x(3,1); - J(1,0) = dNxi(0,1)*x(0,0) + dNxi(1,1)*x(1,0) + dNxi(2,1)*x(2,0) + dNxi(3,1)*x(3,0); - J(1,1) = dNxi(0,1)*x(0,1) + dNxi(1,1)*x(1,1) + dNxi(2,1)*x(2,1) + dNxi(3,1)*x(3,1); - - // - determinant and inverse of the Jacobian - double Jdet = inv(J, Jinv); - - // - shape function gradients wrt global coordinates (loops partly unrolled for efficiency) - // dNx(m,i) += Jinv(i,j) * dNxi(m,j); - for (size_t m = 0 ; m < m_nne ; ++m) - { - dNx(m,0) = Jinv(0,0) * dNxi(m,0) + Jinv(0,1) * dNxi(m,1); - dNx(m,1) = Jinv(1,0) * dNxi(m,0) + Jinv(1,1) * dNxi(m,1); + xt::xtensor_fixed> J; + xt::xtensor_fixed> Jinv; + + #pragma omp for + for (size_t e = 0; e < m_nelem; ++e) { + + auto x = xt::adapt(&m_x(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNxi = xt::adapt(&m_dNxi(q, 0, 0), xt::xshape()); + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + + // J(i,j) += dNxi(m,i) * x(m,j); + J(0, 0) + = dNxi(0, 0) * x(0, 0) + + dNxi(1, 0) * x(1, 0) + + dNxi(2, 0) * x(2, 0) + + dNxi(3, 0) * x(3, 0); + J(0, 1) + = dNxi(0, 0) * x(0, 1) + + dNxi(1, 0) * x(1, 1) + + dNxi(2, 0) * x(2, 1) + + dNxi(3, 0) * x(3, 1); + J(1, 0) + = dNxi(0, 1) * x(0, 0) + + dNxi(1, 1) * x(1, 0) + + dNxi(2, 1) * x(2, 0) + + dNxi(3, 1) * x(3, 0); + J(1, 1) + = dNxi(0, 1) * x(0, 1) + + dNxi(1, 1) * x(1, 1) + + dNxi(2, 1) * x(2, 1) + + dNxi(3, 1) * x(3, 1); + + double Jdet = inv(J, Jinv); + + // dNx(m,i) += Jinv(i,j) * dNxi(m,j); + for (size_t m = 0; m < m_nne; ++m) { + dNx(m, 0) = Jinv(0, 0) * dNxi(m, 0) + Jinv(0, 1) * dNxi(m, 1); + dNx(m, 1) = Jinv(1, 0) * dNxi(m, 0) + Jinv(1, 1) * dNxi(m, 1); + } + + m_vol(e, q) = m_w(q) * Jdet; + } } - - // - integration point volume - m_vol(e,q) = m_w(q) * Jdet; - } } - } } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::gradN_vector( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); - - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto gradu = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - - // - evaluate dyadic product (loops unrolled for efficiency) - // gradu(i,j) += dNx(m,i) * u(m,j) - gradu(0,0) = dNx(0,0)*u(0,0) + dNx(1,0)*u(1,0) + dNx(2,0)*u(2,0) + dNx(3,0)*u(3,0); - gradu(0,1) = dNx(0,0)*u(0,1) + dNx(1,0)*u(1,1) + dNx(2,0)*u(2,1) + dNx(3,0)*u(3,1); - gradu(1,0) = dNx(0,1)*u(0,0) + dNx(1,1)*u(1,0) + dNx(2,1)*u(2,0) + dNx(3,1)*u(3,0); - gradu(1,1) = dNx(0,1)*u(0,1) + dNx(1,1)*u(1,1) + dNx(2,1)*u(2,1) + dNx(3,1)*u(3,1); + const xt::xtensor& elemvec, xt::xtensor& qtensor) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto gradu = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + // gradu(i,j) += dNx(m,i) * u(m,j) + gradu(0, 0) + = dNx(0, 0) * u(0, 0) + + dNx(1, 0) * u(1, 0) + + dNx(2, 0) * u(2, 0) + + dNx(3, 0) * u(3, 0); + gradu(0, 1) + = dNx(0, 0) * u(0, 1) + + dNx(1, 0) * u(1, 1) + + dNx(2, 0) * u(2, 1) + + dNx(3, 0) * u(3, 1); + gradu(1, 0) + = dNx(0, 1) * u(0, 0) + + dNx(1, 1) * u(1, 0) + + dNx(2, 1) * u(2, 0) + + dNx(3, 1) * u(3, 0); + gradu(1, 1) + = dNx(0, 1) * u(0, 1) + + dNx(1, 1) * u(1, 1) + + dNx(2, 1) * u(2, 1) + + dNx(3, 1) * u(3, 1); + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::gradN_vector_T( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); - - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto gradu = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - - // - evaluate transpose of dyadic product (loops unrolled for efficiency) - // gradu(j,i) += dNx(m,i) * u(m,j) - gradu(0,0) = dNx(0,0)*u(0,0) + dNx(1,0)*u(1,0) + dNx(2,0)*u(2,0) + dNx(3,0)*u(3,0); - gradu(1,0) = dNx(0,0)*u(0,1) + dNx(1,0)*u(1,1) + dNx(2,0)*u(2,1) + dNx(3,0)*u(3,1); - gradu(0,1) = dNx(0,1)*u(0,0) + dNx(1,1)*u(1,0) + dNx(2,1)*u(2,0) + dNx(3,1)*u(3,0); - gradu(1,1) = dNx(0,1)*u(0,1) + dNx(1,1)*u(1,1) + dNx(2,1)*u(2,1) + dNx(3,1)*u(3,1); + const xt::xtensor& elemvec, xt::xtensor& qtensor) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto gradu = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + // gradu(j,i) += dNx(m,i) * u(m,j) + gradu(0, 0) + = dNx(0, 0) * u(0, 0) + + dNx(1, 0) * u(1, 0) + + dNx(2, 0) * u(2, 0) + + dNx(3, 0) * u(3, 0); + gradu(1, 0) + = dNx(0, 0) * u(0, 1) + + dNx(1, 0) * u(1, 1) + + dNx(2, 0) * u(2, 1) + + dNx(3, 0) * u(3, 1); + gradu(0, 1) + = dNx(0, 1) * u(0, 0) + + dNx(1, 1) * u(1, 0) + + dNx(2, 1) * u(2, 0) + + dNx(3, 1) * u(3, 0); + gradu(1, 1) + = dNx(0, 1) * u(0, 1) + + dNx(1, 1) * u(1, 1) + + dNx(2, 1) * u(2, 1) + + dNx(3, 1) * u(3, 1); + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::symGradN_vector( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const + const xt::xtensor& elemvec, xt::xtensor& qtensor) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto eps = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + // gradu(i,j) += dNx(m,i) * u(m,j) + // eps(j,i) = 0.5 * (gradu(i,j) + gradu(j,i)) + eps(0, 0) + = dNx(0, 0) * u(0, 0) + + dNx(1, 0) * u(1, 0) + + dNx(2, 0) * u(2, 0) + + dNx(3, 0) * u(3, 0); + eps(1, 1) + = dNx(0, 1) * u(0, 1) + + dNx(1, 1) * u(1, 1) + + dNx(2, 1) * u(2, 1) + + dNx(3, 1) * u(3, 1); + eps(0, 1) = 0.5 * + ( dNx(0, 0) * u(0, 1) + + dNx(1, 0) * u(1, 1) + + dNx(2, 0) * u(2, 1) + + dNx(3, 0) * u(3, 1) + + dNx(0, 1) * u(0, 0) + + dNx(1, 1) * u(1, 0) + + dNx(2, 1) * u(2, 0) + + dNx(3, 1) * u(3, 0)); + eps(1, 0) = eps(0, 1); + } + } +} + +inline void Quadrature::int_N_scalar_NT_dV( + const xt::xtensor& qscalar, xt::xtensor& elemmat) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); + GOOSEFEM_ASSERT( + qscalar.shape() == std::decay_t::shape_type({m_nelem, m_nip})); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + elemmat.fill(0.0); - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto eps = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - - // - evaluate symmetrized dyadic product (loops unrolled for efficiency) - // gradu(i,j) += dNx(m,i) * u(m,j) - // eps (j,i) = 0.5 * ( gradu(i,j) + gradu(j,i) ) - eps(0,0) = dNx(0,0)*u(0,0) + dNx(1,0)*u(1,0) + dNx(2,0)*u(2,0) + dNx(3,0)*u(3,0); - eps(1,1) = dNx(0,1)*u(0,1) + dNx(1,1)*u(1,1) + dNx(2,1)*u(2,1) + dNx(3,1)*u(3,1); - eps(0,1) = ( dNx(0,0)*u(0,1) + dNx(1,0)*u(1,1) + dNx(2,0)*u(2,1) + dNx(3,0)*u(3,1) + - dNx(0,1)*u(0,0) + dNx(1,1)*u(1,0) + dNx(2,1)*u(2,0) + dNx(3,1)*u(3,0) ) * 0.5; - eps(1,0) = eps(0,1); - } - } -} + auto M = xt::adapt(&elemmat(e, 0, 0), xt::xshape()); -// ------------------------------------------------------------------------------------------------- + for (size_t q = 0; q < m_nip; ++q) { -inline void Quadrature::int_N_scalar_NT_dV( - const xt::xtensor& qscalar, - xt::xtensor& elemmat) const -{ - GOOSEFEM_ASSERT(qscalar.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip})); - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - // zero-initialize: matrix of matrices - elemmat.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. mass matrix) - auto M = xt::adapt(&elemmat(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto N = xt::adapt(&m_N(q,0), xt::xshape()); - auto& vol = m_vol (e,q); - auto& rho = qscalar(e,q); - - // - evaluate scalar product, for all dimensions, and assemble - // M(m*ndim+i,n*ndim+i) += N(m) * scalar * N(n) * dV - for (size_t m = 0 ; m < m_nne ; ++m ){ - for (size_t n = 0 ; n < m_nne ; ++n ){ - M(m*m_ndim+0, n*m_ndim+0) += N(m) * rho * N(n) * vol; - M(m*m_ndim+1, n*m_ndim+1) += N(m) * rho * N(n) * vol; + auto N = xt::adapt(&m_N(q, 0), xt::xshape()); + auto& vol = m_vol(e, q); + auto& rho = qscalar(e, q); + + // M(m*ndim+i,n*ndim+i) += N(m) * scalar * N(n) * dV + for (size_t m = 0; m < m_nne; ++m) { + for (size_t n = 0; n < m_nne; ++n) { + M(m * m_ndim + 0, n * m_ndim + 0) += N(m) * rho * N(n) * vol; + M(m * m_ndim + 1, n * m_ndim + 1) += N(m) * rho * N(n) * vol; + } + } } - } } - } } -// ------------------------------------------------------------------------------------------------- - inline void Quadrature::int_gradN_dot_tensor2_dV( - const xt::xtensor& qtensor, - xt::xtensor& elemvec) const -{ - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - - // zero-initialize output: matrix of vectors - elemvec.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. nodal force) - auto f = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto sig = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - auto& vol = m_vol(e,q); - - // - evaluate dot product, and assemble - for (size_t m = 0 ; m < m_nne ; ++m) - { - f(m,0) += ( dNx(m,0) * sig(0,0) + dNx(m,1) * sig(1,0) ) * vol; - f(m,1) += ( dNx(m,0) * sig(0,1) + dNx(m,1) * sig(1,1) ) * vol; - } - } - } -} + const xt::xtensor& qtensor, xt::xtensor& elemvec) const +{ + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim})); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); -// ------------------------------------------------------------------------------------------------- + elemvec.fill(0.0); -inline void Quadrature::int_gradN_dot_tensor4_dot_gradNT_dV( - const xt::xtensor& qtensor, - xt::xtensor& elemmat) const -{ - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_ndim, m_ndim, m_ndim, m_ndim})); - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - // zero-initialize output: matrix of vector - elemmat.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. nodal force) - auto K = xt::adapt(&elemmat(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx(e,q,0,0), xt::xshape()); - auto C = xt::adapt(&qtensor(e,q,0,0,0,0), xt::xshape()); - auto& vol = m_vol(e,q); + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto f = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto sig = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + auto& vol = m_vol(e, q); - // - evaluate dot product, and assemble - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t n = 0 ; n < m_nne ; ++n) - for (size_t i = 0 ; i < m_ndim ; ++i) - for (size_t j = 0 ; j < m_ndim ; ++j) - for (size_t k = 0 ; k < m_ndim ; ++k) - for (size_t l = 0 ; l < m_ndim ; ++l) - K(m*m_ndim+j, n*m_ndim+k) += dNx(m,i) * C(i,j,k,l) * dNx(n,l) * vol; - } - } + for (size_t m = 0; m < m_nne; ++m) { + f(m, 0) += (dNx(m, 0) * sig(0, 0) + dNx(m, 1) * sig(1, 0)) * vol; + f(m, 1) += (dNx(m, 0) * sig(0, 1) + dNx(m, 1) * sig(1, 1)) * vol; + } + } + } } -// ------------------------------------------------------------------------------------------------- +inline void Quadrature::int_gradN_dot_tensor4_dot_gradNT_dV( + const xt::xtensor& qtensor, xt::xtensor& elemmat) const +{ + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem,m_nip,m_ndim,m_ndim,m_ndim,m_ndim})); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + + elemmat.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto K = xt::adapt(&elemmat(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e,q,0,0), xt::xshape()); + auto C = xt::adapt(&qtensor(e,q,0,0,0,0), xt::xshape()); + auto& vol = m_vol(e, q); + + for (size_t m = 0; m < m_nne; ++m) { + for (size_t n = 0; n < m_nne; ++n) { + for (size_t i = 0; i < m_ndim; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + for (size_t k = 0; k < m_ndim; ++k) { + for (size_t l = 0; l < m_ndim; ++l) { + K(m * m_ndim + j, n * m_ndim + k) += + dNx(m, i) * C(i, j, k, l) * dNx(n, l) * vol; + } + } + } + } + } + } + } + } +} inline xt::xtensor Quadrature::DV() const { - xt::xtensor out = xt::empty({m_nelem, m_nip}); - this->dV(out); - return out; + xt::xtensor out = xt::empty({m_nelem, m_nip}); + this->dV(out); + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xarray Quadrature::DV(size_t rank) const { - std::vector shape = {m_nelem, m_nip}; + std::vector shape = {m_nelem, m_nip}; - for (size_t i = 0; i < rank; ++i) - shape.push_back(static_cast(m_ndim)); + for (size_t i = 0; i < rank; ++i) { + shape.push_back(static_cast(m_ndim)); + } - xt::xarray out = xt::empty(shape); - this->dV(out); - return out; + xt::xarray out = xt::empty(shape); + this->dV(out); + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::GradN_vector( - const xt::xtensor& elemvec) const +inline xt::xtensor Quadrature::GradN_vector(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); - this->gradN_vector(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); + this->gradN_vector(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::GradN_vector_T( - const xt::xtensor& elemvec) const +inline xt::xtensor +Quadrature::GradN_vector_T(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); - this->gradN_vector_T(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); + this->gradN_vector_T(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::SymGradN_vector( - const xt::xtensor& elemvec) const +inline xt::xtensor +Quadrature::SymGradN_vector(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); - this->symGradN_vector(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_ndim, m_ndim}); + this->symGradN_vector(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::Int_N_scalar_NT_dV( - const xt::xtensor& qscalar) const +inline xt::xtensor +Quadrature::Int_N_scalar_NT_dV(const xt::xtensor& qscalar) const { - xt::xtensor elemmat = xt::empty({m_nelem, m_nne*m_ndim, m_nne*m_ndim}); - this->int_N_scalar_NT_dV(qscalar, elemmat); - return elemmat; + xt::xtensor elemmat = xt::empty({m_nelem, m_nne * m_ndim, m_nne * m_ndim}); + this->int_N_scalar_NT_dV(qscalar, elemmat); + return elemmat; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::Int_gradN_dot_tensor2_dV( - const xt::xtensor& qtensor) const +inline xt::xtensor +Quadrature::Int_gradN_dot_tensor2_dV(const xt::xtensor& qtensor) const { - xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); - this->int_gradN_dot_tensor2_dV(qtensor, elemvec); - return elemvec; + xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); + this->int_gradN_dot_tensor2_dV(qtensor, elemvec); + return elemvec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Quadrature::Int_gradN_dot_tensor4_dot_gradNT_dV( - const xt::xtensor& qtensor) const - { - xt::xtensor elemmat = xt::empty({m_nelem, m_ndim*m_nne, m_ndim*m_nne}); - this->int_gradN_dot_tensor4_dot_gradNT_dV(qtensor, elemmat); - return elemmat; - } - -// ------------------------------------------------------------------------------------------------- - -}}} // namespace ... +inline xt::xtensor +Quadrature::Int_gradN_dot_tensor4_dot_gradNT_dV(const xt::xtensor& qtensor) const +{ + xt::xtensor elemmat = xt::empty({m_nelem, m_ndim * m_nne, m_ndim * m_nne}); + this->int_gradN_dot_tensor4_dot_gradNT_dV(qtensor, elemmat); + return elemmat; +} -// ================================================================================================= +} // namespace Quad4 +} // namespace Element +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/ElementQuad4Axisymmetric.hpp b/include/GooseFEM/ElementQuad4Axisymmetric.hpp index 3e97c3e..60534df 100644 --- a/include/GooseFEM/ElementQuad4Axisymmetric.hpp +++ b/include/GooseFEM/ElementQuad4Axisymmetric.hpp @@ -1,583 +1,593 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_ELEMENTQUADAXISYMMETRIC_HPP #define GOOSEFEM_ELEMENTQUADAXISYMMETRIC_HPP -// ------------------------------------------------------------------------------------------------- - #include "ElementQuad4Axisymmetric.h" -// ================================================================================================= - namespace GooseFEM { namespace Element { namespace Quad4 { -// ================================================================================================= - -inline QuadratureAxisymmetric::QuadratureAxisymmetric(const xt::xtensor& x) : - QuadratureAxisymmetric(x, Gauss::xi(), Gauss::w()) {} - -// ------------------------------------------------------------------------------------------------- +inline QuadratureAxisymmetric::QuadratureAxisymmetric(const xt::xtensor& x) + : QuadratureAxisymmetric(x, Gauss::xi(), Gauss::w()) +{ +} inline QuadratureAxisymmetric::QuadratureAxisymmetric( - const xt::xtensor& x, - const xt::xtensor& xi, - const xt::xtensor& w) : - m_x(x), m_w(w), m_xi(xi) + const xt::xtensor& x, + const xt::xtensor& xi, + const xt::xtensor& w) + : m_x(x), m_w(w), m_xi(xi) { - GOOSEFEM_ASSERT(m_x.shape(1) == m_nne); - GOOSEFEM_ASSERT(m_x.shape(2) == m_ndim); - - m_nelem = m_x.shape(0); - m_nip = m_w.size(); - - GOOSEFEM_ASSERT(m_xi.shape(0) == m_nip); - GOOSEFEM_ASSERT(m_xi.shape(1) == m_ndim); - GOOSEFEM_ASSERT(m_w.size() == m_nip); - - m_N = xt::empty({m_nip, m_nne}); - m_dNxi = xt::empty({m_nip, m_nne, m_ndim}); - m_B = xt::empty({m_nelem, m_nip, m_nne, m_tdim, m_tdim, m_tdim}); - m_vol = xt::empty({m_nelem, m_nip}); - - // shape functions - for (size_t q = 0 ; q < m_nip ; ++q) - { - m_N(q,0) = .25 * (1.-m_xi(q,0)) * (1.-m_xi(q,1)); - m_N(q,1) = .25 * (1.+m_xi(q,0)) * (1.-m_xi(q,1)); - m_N(q,2) = .25 * (1.+m_xi(q,0)) * (1.+m_xi(q,1)); - m_N(q,3) = .25 * (1.-m_xi(q,0)) * (1.+m_xi(q,1)); - } - - // shape function gradients in local coordinates - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - dN / dxi_0 - m_dNxi(q,0,0) = -.25*(1.-m_xi(q,1)); - m_dNxi(q,1,0) = +.25*(1.-m_xi(q,1)); - m_dNxi(q,2,0) = +.25*(1.+m_xi(q,1)); - m_dNxi(q,3,0) = -.25*(1.+m_xi(q,1)); - // - dN / dxi_1 - m_dNxi(q,0,1) = -.25*(1.-m_xi(q,0)); - m_dNxi(q,1,1) = -.25*(1.+m_xi(q,0)); - m_dNxi(q,2,1) = +.25*(1.+m_xi(q,0)); - m_dNxi(q,3,1) = +.25*(1.-m_xi(q,0)); - } - - // compute the shape function gradients, based on "x" - compute_dN(); -} + GOOSEFEM_ASSERT(m_x.shape(1) == m_nne); + GOOSEFEM_ASSERT(m_x.shape(2) == m_ndim); + + m_nelem = m_x.shape(0); + m_nip = m_w.size(); + + GOOSEFEM_ASSERT(m_xi.shape(0) == m_nip); + GOOSEFEM_ASSERT(m_xi.shape(1) == m_ndim); + GOOSEFEM_ASSERT(m_w.size() == m_nip); + + m_N = xt::empty({m_nip, m_nne}); + m_dNxi = xt::empty({m_nip, m_nne, m_ndim}); + m_B = xt::empty({m_nelem, m_nip, m_nne, m_tdim, m_tdim, m_tdim}); + m_vol = xt::empty({m_nelem, m_nip}); + + for (size_t q = 0; q < m_nip; ++q) { + m_N(q, 0) = 0.25 * (1.0 - m_xi(q, 0)) * (1.0 - m_xi(q, 1)); + m_N(q, 1) = 0.25 * (1.0 + m_xi(q, 0)) * (1.0 - m_xi(q, 1)); + m_N(q, 2) = 0.25 * (1.0 + m_xi(q, 0)) * (1.0 + m_xi(q, 1)); + m_N(q, 3) = 0.25 * (1.0 - m_xi(q, 0)) * (1.0 + m_xi(q, 1)); + } -// ------------------------------------------------------------------------------------------------- + for (size_t q = 0; q < m_nip; ++q) { + // - dN / dxi_0 + m_dNxi(q, 0, 0) = -0.25 * (1.0 - m_xi(q, 1)); + m_dNxi(q, 1, 0) = +0.25 * (1.0 - m_xi(q, 1)); + m_dNxi(q, 2, 0) = +0.25 * (1.0 + m_xi(q, 1)); + m_dNxi(q, 3, 0) = -0.25 * (1.0 + m_xi(q, 1)); + // - dN / dxi_1 + m_dNxi(q, 0, 1) = -0.25 * (1.0 - m_xi(q, 0)); + m_dNxi(q, 1, 1) = -0.25 * (1.0 + m_xi(q, 0)); + m_dNxi(q, 2, 1) = +0.25 * (1.0 + m_xi(q, 0)); + m_dNxi(q, 3, 1) = +0.25 * (1.0 - m_xi(q, 0)); + } + + compute_dN(); +} inline size_t QuadratureAxisymmetric::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t QuadratureAxisymmetric::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t QuadratureAxisymmetric::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t QuadratureAxisymmetric::nip() const { - return m_nip; + return m_nip; } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::dV(xt::xtensor& qscalar) const { - GOOSEFEM_ASSERT(qscalar.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip})); + GOOSEFEM_ASSERT( + qscalar.shape() == std::decay_t::shape_type({m_nelem, m_nip})); - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t q = 0 ; q < m_nip ; ++q) - qscalar(e,q) = m_vol(e,q); + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t q = 0; q < m_nip; ++q) { + qscalar(e, q) = m_vol(e, q); + } + } } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::dV(xt::xtensor& qtensor) const { - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t q = 0 ; q < m_nip ; ++q) - for (size_t i = 0 ; i < m_tdim ; ++i) - for (size_t j = 0 ; j < m_tdim ; ++j) - qtensor(e,q,i,j) = m_vol(e,q); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t q = 0; q < m_nip; ++q) { + for (size_t i = 0; i < m_tdim; ++i) { + for (size_t j = 0; j < m_tdim; ++j) { + qtensor(e, q, i, j) = m_vol(e, q); + } + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::dV(xt::xarray& qtensor) const { - GOOSEFEM_ASSERT(qtensor.shape(0) == m_nelem); - GOOSEFEM_ASSERT(qtensor.shape(1) == m_nip); + GOOSEFEM_ASSERT(qtensor.shape(0) == m_nelem); + GOOSEFEM_ASSERT(qtensor.shape(1) == m_nip); - xt::dynamic_shape strides = { - static_cast(m_vol.strides()[0]), - static_cast(m_vol.strides()[1])}; + xt::dynamic_shape strides = {static_cast(m_vol.strides()[0]), + static_cast(m_vol.strides()[1])}; - for (size_t i = 2; i < qtensor.shape().size(); ++i) - strides.push_back(0); + for (size_t i = 2; i < qtensor.shape().size(); ++i) { + strides.push_back(0); + } - qtensor = xt::strided_view(m_vol, qtensor.shape(), std::move(strides), 0ul, xt::layout_type::dynamic); + qtensor = + xt::strided_view(m_vol, qtensor.shape(), std::move(strides), 0ul, xt::layout_type::dynamic); } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::update_x(const xt::xtensor& x) { - GOOSEFEM_ASSERT(x.shape() == m_x.shape()); - - xt::noalias(m_x) = x; - - // update the shape function gradients for the new "x" - compute_dN(); + GOOSEFEM_ASSERT(x.shape() == m_x.shape()); + xt::noalias(m_x) = x; + compute_dN(); } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::compute_dN() { - // zero-initialize full B-matrix (most component remain zero, and are not written) - m_B.fill(0.0); + // most components remain zero, and are not written + m_B.fill(0.0); - #pragma omp parallel - { - // allocate local variables - xt::xtensor_fixed> J, Jinv; - - // loop over all elements (in parallel) - #pragma omp for - for (size_t e = 0 ; e < m_nelem ; ++e) + #pragma omp parallel { - // alias nodal positions - auto x = xt::adapt(&m_x(e,0,0), xt::xshape()); - - // loop over integration points - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNxi = xt::adapt(&m_dNxi( q,0,0 ), xt::xshape()); - auto B = xt::adapt(&m_B (e,q,0,0,0,0), xt::xshape()); - auto N = xt::adapt(&m_N ( q,0 ), xt::xshape()); - - // - Jacobian (loops unrolled for efficiency) - // J(i,j) += dNxi(m,i) * x(m,j); - J(0,0) = dNxi(0,0)*x(0,0) + dNxi(1,0)*x(1,0) + dNxi(2,0)*x(2,0) + dNxi(3,0)*x(3,0); - J(0,1) = dNxi(0,0)*x(0,1) + dNxi(1,0)*x(1,1) + dNxi(2,0)*x(2,1) + dNxi(3,0)*x(3,1); - J(1,0) = dNxi(0,1)*x(0,0) + dNxi(1,1)*x(1,0) + dNxi(2,1)*x(2,0) + dNxi(3,1)*x(3,0); - J(1,1) = dNxi(0,1)*x(0,1) + dNxi(1,1)*x(1,1) + dNxi(2,1)*x(2,1) + dNxi(3,1)*x(3,1); - - // - determinant and inverse of the Jacobian - double Jdet = inv(J, Jinv); - - // - get radius for computation of volume - double rq = N(0)*x(0,1) + N(1)*x(1,1) + N(2)*x(2,1) + N(3)*x(3,1); - - // - compute the B matrix (loops partly unrolled for efficiency) - // N.B. "dNx(m,i) += Jinv(i,j) * dNxi(m,j);" - for (size_t m = 0; m < m_nne; ++m) - { - B(m,0,0,0) = Jinv(1,0) * dNxi(m,0) + Jinv(1,1) * dNxi(m,1); // B(m, r, r, r) = dNdx(m,1) - B(m,0,2,2) = Jinv(1,0) * dNxi(m,0) + Jinv(1,1) * dNxi(m,1); // B(m, r, z, z) = dNdx(m,1) - B(m,1,1,0) = 1./rq * N(m); // B(m, t, t, r) - B(m,2,0,0) = Jinv(0,0) * dNxi(m,0) + Jinv(0,1) * dNxi(m,1); // B(m, z, r, r) = dNdx(m,0) - B(m,2,2,2) = Jinv(0,0) * dNxi(m,0) + Jinv(0,1) * dNxi(m,1); // B(m, z, z, z) = dNdx(m,0) + xt::xtensor_fixed> J; + xt::xtensor_fixed> Jinv; + + #pragma omp for + for (size_t e = 0; e < m_nelem; ++e) { + + auto x = xt::adapt(&m_x(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNxi = xt::adapt(&m_dNxi(q,0,0), xt::xshape()); + auto B = xt::adapt(&m_B(e,q,0,0,0,0), xt::xshape()); + auto N = xt::adapt(&m_N(q,0), xt::xshape()); + + // J(i,j) += dNxi(m,i) * x(m,j); + J(0, 0) + = dNxi(0, 0) * x(0, 0) + + dNxi(1, 0) * x(1, 0) + + dNxi(2, 0) * x(2, 0) + + dNxi(3, 0) * x(3, 0); + J(0, 1) + = dNxi(0, 0) * x(0, 1) + + dNxi(1, 0) * x(1, 1) + + dNxi(2, 0) * x(2, 1) + + dNxi(3, 0) * x(3, 1); + J(1, 0) + = dNxi(0, 1) * x(0, 0) + + dNxi(1, 1) * x(1, 0) + + dNxi(2, 1) * x(2, 0) + + dNxi(3, 1) * x(3, 0); + J(1, 1) + = dNxi(0, 1) * x(0, 1) + + dNxi(1, 1) * x(1, 1) + + dNxi(2, 1) * x(2, 1) + + dNxi(3, 1) * x(3, 1); + + double Jdet = inv(J, Jinv); + + // radius for computation of volume + double rq = N(0) * x(0, 1) + N(1) * x(1, 1) + N(2) * x(2, 1) + N(3) * x(3, 1); + + // dNx(m,i) += Jinv(i,j) * dNxi(m,j) + for (size_t m = 0; m < m_nne; ++m) { + // B(m, r, r, r) = dNdx(m,1) + B(m, 0, 0, 0) = Jinv(1, 0) * dNxi(m, 0) + Jinv(1, 1) * dNxi(m, 1); + // B(m, r, z, z) = dNdx(m,1) + B(m, 0, 2, 2) = Jinv(1, 0) * dNxi(m, 0) + Jinv(1, 1) * dNxi(m, 1); + // B(m, t, t, r) + B(m, 1, 1, 0) = 1.0 / rq * N(m); + // B(m, z, r, r) = dNdx(m,0) + B(m, 2, 0, 0) = Jinv(0, 0) * dNxi(m, 0) + Jinv(0, 1) * dNxi(m, 1); + // B(m, z, z, z) = dNdx(m,0) + B(m, 2, 2, 2) = Jinv(0, 0) * dNxi(m, 0) + Jinv(0, 1) * dNxi(m, 1); + } + + m_vol(e, q) = m_w(q) * Jdet * 2.0 * M_PI * rq; + } } - - // - integration point volume - m_vol(e, q) = m_w(q) * Jdet * 2. * M_PI * rq; - } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::gradN_vector( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const + const xt::xtensor& elemvec, xt::xtensor& qtensor) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); - - // zero-initialize (zero components not written below) - qtensor.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto B = xt::adapt(&m_B (e,q,0,0,0,0), xt::xshape()); - auto gradu = xt::adapt(&qtensor(e,q,0,0 ), xt::xshape()); - - // - evaluate dyadic product (loops unrolled for efficiency) - // gradu(i,j) += B(m,i,j,k) * u(m,perm(k)) - // (where perm(0) = 1, perm(2) = 0) - gradu(0,0) = B(0,0,0,0)*u(0,1) + B(1,0,0,0)*u(1,1) + B(2,0,0,0)*u(2,1) + B(3,0,0,0)*u(3,1); - gradu(1,1) = B(0,1,1,0)*u(0,1) + B(1,1,1,0)*u(1,1) + B(2,1,1,0)*u(2,1) + B(3,1,1,0)*u(3,1); - gradu(2,2) = B(0,2,2,2)*u(0,0) + B(1,2,2,2)*u(1,0) + B(2,2,2,2)*u(2,0) + B(3,2,2,2)*u(3,0); - gradu(0,2) = B(0,0,2,2)*u(0,0) + B(1,0,2,2)*u(1,0) + B(2,0,2,2)*u(2,0) + B(3,0,2,2)*u(3,0); - gradu(2,0) = B(0,2,0,0)*u(0,1) + B(1,2,0,0)*u(1,1) + B(2,2,0,0)*u(2,1) + B(3,2,0,0)*u(3,1); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); + + qtensor.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto B = xt::adapt(&m_B(e, q, 0, 0, 0, 0), xt::xshape()); + auto gradu = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + // gradu(i,j) += B(m,i,j,k) * u(m,perm(k)) + // (where perm(0) = 1, perm(2) = 0) + gradu(0, 0) + = B(0, 0, 0, 0) * u(0, 1) + + B(1, 0, 0, 0) * u(1, 1) + + B(2, 0, 0, 0) * u(2, 1) + + B(3, 0, 0, 0) * u(3, 1); + gradu(1, 1) + = B(0, 1, 1, 0) * u(0, 1) + + B(1, 1, 1, 0) * u(1, 1) + + B(2, 1, 1, 0) * u(2, 1) + + B(3, 1, 1, 0) * u(3, 1); + gradu(2, 2) + = B(0, 2, 2, 2) * u(0, 0) + + B(1, 2, 2, 2) * u(1, 0) + + B(2, 2, 2, 2) * u(2, 0) + + B(3, 2, 2, 2) * u(3, 0); + gradu(0, 2) + = B(0, 0, 2, 2) * u(0, 0) + + B(1, 0, 2, 2) * u(1, 0) + + B(2, 0, 2, 2) * u(2, 0) + + B(3, 0, 2, 2) * u(3, 0); + gradu(2, 0) + = B(0, 2, 0, 0) * u(0, 1) + + B(1, 2, 0, 0) * u(1, 1) + + B(2, 2, 0, 0) * u(2, 1) + + B(3, 2, 0, 0) * u(3, 1); + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::gradN_vector_T( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const + const xt::xtensor& elemvec, xt::xtensor& qtensor) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); - - // zero-initialize (zero components not written below) - qtensor.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto B = xt::adapt(&m_B (e,q,0,0,0,0), xt::xshape()); - auto gradu = xt::adapt(&qtensor(e,q,0,0 ), xt::xshape()); - - // - evaluate transpose of dyadic product (loops unrolled for efficiency) - // gradu(j,i) += B(m,i,j,k) * u(m,perm(k)) - // (where perm(0) = 1, perm(2) = 0) - gradu(0,0) = B(0,0,0,0)*u(0,1) + B(1,0,0,0)*u(1,1) + B(2,0,0,0)*u(2,1) + B(3,0,0,0)*u(3,1); - gradu(1,1) = B(0,1,1,0)*u(0,1) + B(1,1,1,0)*u(1,1) + B(2,1,1,0)*u(2,1) + B(3,1,1,0)*u(3,1); - gradu(2,2) = B(0,2,2,2)*u(0,0) + B(1,2,2,2)*u(1,0) + B(2,2,2,2)*u(2,0) + B(3,2,2,2)*u(3,0); - gradu(2,0) = B(0,0,2,2)*u(0,0) + B(1,0,2,2)*u(1,0) + B(2,0,2,2)*u(2,0) + B(3,0,2,2)*u(3,0); - gradu(0,2) = B(0,2,0,0)*u(0,1) + B(1,2,0,0)*u(1,1) + B(2,2,0,0)*u(2,1) + B(3,2,0,0)*u(3,1); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); + + qtensor.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto B = xt::adapt(&m_B(e, q, 0, 0, 0, 0), xt::xshape()); + auto gradu = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + // gradu(j,i) += B(m,i,j,k) * u(m,perm(k)) + // (where perm(0) = 1, perm(2) = 0) + gradu(0, 0) + = B(0, 0, 0, 0) * u(0, 1) + + B(1, 0, 0, 0) * u(1, 1) + + B(2, 0, 0, 0) * u(2, 1) + + B(3, 0, 0, 0) * u(3, 1); + gradu(1, 1) + = B(0, 1, 1, 0) * u(0, 1) + + B(1, 1, 1, 0) * u(1, 1) + + B(2, 1, 1, 0) * u(2, 1) + + B(3, 1, 1, 0) * u(3, 1); + gradu(2, 2) + = B(0, 2, 2, 2) * u(0, 0) + + B(1, 2, 2, 2) * u(1, 0) + + B(2, 2, 2, 2) * u(2, 0) + + B(3, 2, 2, 2) * u(3, 0); + gradu(2, 0) + = B(0, 0, 2, 2) * u(0, 0) + + B(1, 0, 2, 2) * u(1, 0) + + B(2, 0, 2, 2) * u(2, 0) + + B(3, 0, 2, 2) * u(3, 0); + gradu(0, 2) + = B(0, 2, 0, 0) * u(0, 1) + + B(1, 2, 0, 0) * u(1, 1) + + B(2, 2, 0, 0) * u(2, 1) + + B(3, 2, 0, 0) * u(3, 1); + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::symGradN_vector( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const + const xt::xtensor& elemvec, xt::xtensor& qtensor) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); - - // zero-initialize (zero components not written below) - qtensor.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto B = xt::adapt(&m_B (e,q,0,0,0,0), xt::xshape()); - auto eps = xt::adapt(&qtensor(e,q,0,0 ), xt::xshape()); - - // - evaluate symmetrized dyadic product (loops unrolled for efficiency) - // gradu(j,i) += B(m,i,j,k) * u(m,perm(k)) - // eps (j,i) = 0.5 * ( gradu(i,j) + gradu(j,i) ) - // (where perm(0) = 1, perm(2) = 0) - eps(0,0) = B(0,0,0,0)*u(0,1) + B(1,0,0,0)*u(1,1) + B(2,0,0,0)*u(2,1) + B(3,0,0,0)*u(3,1); - eps(1,1) = B(0,1,1,0)*u(0,1) + B(1,1,1,0)*u(1,1) + B(2,1,1,0)*u(2,1) + B(3,1,1,0)*u(3,1); - eps(2,2) = B(0,2,2,2)*u(0,0) + B(1,2,2,2)*u(1,0) + B(2,2,2,2)*u(2,0) + B(3,2,2,2)*u(3,0); - eps(2,0) = ( B(0,0,2,2)*u(0,0) + B(1,0,2,2)*u(1,0) + B(2,0,2,2)*u(2,0) + B(3,0,2,2)*u(3,0) + - B(0,2,0,0)*u(0,1) + B(1,2,0,0)*u(1,1) + B(2,2,0,0)*u(2,1) + B(3,2,0,0)*u(3,1) ) * 0.5; - eps(0,2) = eps(2,0); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); + + qtensor.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto B = xt::adapt(&m_B(e, q, 0, 0, 0, 0), xt::xshape()); + auto eps = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + // gradu(j,i) += B(m,i,j,k) * u(m,perm(k)) + // eps(j,i) = 0.5 * (gradu(i,j) + gradu(j,i)) + // (where perm(0) = 1, perm(2) = 0) + eps(0, 0) + = B(0, 0, 0, 0) * u(0, 1) + + B(1, 0, 0, 0) * u(1, 1) + + B(2, 0, 0, 0) * u(2, 1) + + B(3, 0, 0, 0) * u(3, 1); + eps(1, 1) + = B(0, 1, 1, 0) * u(0, 1) + + B(1, 1, 1, 0) * u(1, 1) + + B(2, 1, 1, 0) * u(2, 1) + + B(3, 1, 1, 0) * u(3, 1); + eps(2, 2) + = B(0, 2, 2, 2) * u(0, 0) + + B(1, 2, 2, 2) * u(1, 0) + + B(2, 2, 2, 2) * u(2, 0) + + B(3, 2, 2, 2) * u(3, 0); + eps(2, 0) = 0.5 * + ( B(0, 0, 2, 2) * u(0, 0) + + B(1, 0, 2, 2) * u(1, 0) + + B(2, 0, 2, 2) * u(2, 0) + + B(3, 0, 2, 2) * u(3, 0) + + B(0, 2, 0, 0) * u(0, 1) + + B(1, 2, 0, 0) * u(1, 1) + + B(2, 2, 0, 0) * u(2, 1) + + B(3, 2, 0, 0) * u(3, 1)); + eps(0, 2) = eps(2, 0); + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::int_N_scalar_NT_dV( - const xt::xtensor& qscalar, - xt::xtensor& elemmat) const + const xt::xtensor& qscalar, xt::xtensor& elemmat) const { - GOOSEFEM_ASSERT(qscalar.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip})); - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - // zero-initialize: matrix of matrices - elemmat.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. mass matrix) - auto M = xt::adapt(&elemmat(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto N = xt::adapt(&m_N(q,0), xt::xshape()); - auto& vol = m_vol (e,q); - auto& rho = qscalar(e,q); - - // - evaluate scalar product, for all dimensions, and assemble - // M(m*ndim+i,n*ndim+i) += N(m) * scalar * N(n) * dV - for (size_t m = 0 ; m < m_nne ; ++m ){ - for (size_t n = 0 ; n < m_nne ; ++n ){ - M(m*m_ndim+0, n*m_ndim+0) += N(m) * rho * N(n) * vol; - M(m*m_ndim+1, n*m_ndim+1) += N(m) * rho * N(n) * vol; + GOOSEFEM_ASSERT( + qscalar.shape() == std::decay_t::shape_type({m_nelem, m_nip})); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + + elemmat.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto M = xt::adapt(&elemmat(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto N = xt::adapt(&m_N(q, 0), xt::xshape()); + auto& vol = m_vol(e, q); + auto& rho = qscalar(e, q); + + // M(m*ndim+i,n*ndim+i) += N(m) * scalar * N(n) * dV + for (size_t m = 0; m < m_nne; ++m) { + for (size_t n = 0; n < m_nne; ++n) { + M(m * m_ndim + 0, n * m_ndim + 0) += N(m) * rho * N(n) * vol; + M(m * m_ndim + 1, n * m_ndim + 1) += N(m) * rho * N(n) * vol; + } + } } - } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::int_gradN_dot_tensor2_dV( - const xt::xtensor& qtensor, - xt::xtensor& elemvec) const + const xt::xtensor& qtensor, xt::xtensor& elemvec) const { - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - - // zero-initialize output: matrix of vectors - elemvec.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. nodal force) - auto f = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto B = xt::adapt(&m_B(e,q,0,0,0,0), xt::xshape()); - auto sig = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - auto& vol = m_vol(e,q); - - // - evaluate dot product, and assemble - // f(m,i) += B(m,i,j,perm(k)) * sig(i,j) * dV - // (where perm(0) = 1, perm(2) = 0) - for (size_t m = 0 ; m < m_nne ; ++m) - { - f(m,0) += ( B(m,2,2,2)*sig(2,2) + B(m,0,2,2)*sig(0,2) ) * vol; - f(m,1) += ( B(m,0,0,0)*sig(0,0) + B(m,1,1,0)*sig(1,1) + B(m,2,0,0)*sig(2,0) ) * vol; - } + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + + elemvec.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto f = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto B = xt::adapt(&m_B(e, q, 0, 0, 0, 0), xt::xshape()); + auto sig = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + auto& vol = m_vol(e, q); + + // f(m,i) += B(m,i,j,perm(k)) * sig(i,j) * dV + // (where perm(0) = 1, perm(2) = 0) + for (size_t m = 0; m < m_nne; ++m) { + f(m, 0) += vol * + ( B(m, 2, 2, 2) * sig(2, 2) + + B(m, 0, 2, 2) * sig(0, 2)); + f(m, 1) += vol * + ( B(m, 0, 0, 0) * sig(0, 0) + + B(m, 1, 1, 0) * sig(1, 1) + + B(m, 2, 0, 0) * sig(2, 0)); + } + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadratureAxisymmetric::int_gradN_dot_tensor4_dot_gradNT_dV( - const xt::xtensor& qtensor, - xt::xtensor& elemmat) const + const xt::xtensor& qtensor, xt::xtensor& elemmat) const { - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim, m_tdim, m_tdim})); - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - // zero-initialize output: matrix of vector - elemmat.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. nodal force) - auto K = xt::adapt(&elemmat(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto B = xt::adapt(&m_B(e,q,0,0,0,0), xt::xshape()); - auto C = xt::adapt(&qtensor(e,q,0,0,0,0), xt::xshape()); - auto& vol = m_vol(e,q); - - // - compute product: - // K(m*m_ndim+perm(c), n*m_ndim+perm(f)) = B(m,a,b,c) * C(a,b,d,e) * B(n,e,d,f) * vol; - // (where perm(0) = 1, perm(2) = 0) - for (size_t m = 0 ; m < m_nne ; ++m) - { - for (size_t n = 0 ; n < m_nne ; ++n) - { - K(m*m_ndim+1, n*m_ndim+1) += B(m,0,0,0) * C(0,0,0,0) * B(n,0,0,0) * vol; - K(m*m_ndim+1, n*m_ndim+1) += B(m,0,0,0) * C(0,0,1,1) * B(n,1,1,0) * vol; - K(m*m_ndim+1, n*m_ndim+0) += B(m,0,0,0) * C(0,0,2,2) * B(n,2,2,2) * vol; - K(m*m_ndim+1, n*m_ndim+0) += B(m,0,0,0) * C(0,0,2,0) * B(n,0,2,2) * vol; - K(m*m_ndim+1, n*m_ndim+1) += B(m,0,0,0) * C(0,0,0,2) * B(n,2,0,0) * vol; - - K(m*m_ndim+1, n*m_ndim+1) += B(m,1,1,0) * C(1,1,0,0) * B(n,0,0,0) * vol; - K(m*m_ndim+1, n*m_ndim+1) += B(m,1,1,0) * C(1,1,1,1) * B(n,1,1,0) * vol; - K(m*m_ndim+1, n*m_ndim+0) += B(m,1,1,0) * C(1,1,2,2) * B(n,2,2,2) * vol; - K(m*m_ndim+1, n*m_ndim+0) += B(m,1,1,0) * C(1,1,2,0) * B(n,0,2,2) * vol; - K(m*m_ndim+1, n*m_ndim+1) += B(m,1,1,0) * C(1,1,0,2) * B(n,2,0,0) * vol; - - K(m*m_ndim+0, n*m_ndim+1) += B(m,2,2,2) * C(2,2,0,0) * B(n,0,0,0) * vol; - K(m*m_ndim+0, n*m_ndim+1) += B(m,2,2,2) * C(2,2,1,1) * B(n,1,1,0) * vol; - K(m*m_ndim+0, n*m_ndim+0) += B(m,2,2,2) * C(2,2,2,2) * B(n,2,2,2) * vol; - K(m*m_ndim+0, n*m_ndim+0) += B(m,2,2,2) * C(2,2,2,0) * B(n,0,2,2) * vol; - K(m*m_ndim+0, n*m_ndim+1) += B(m,2,2,2) * C(2,2,0,2) * B(n,2,0,0) * vol; - - K(m*m_ndim+0, n*m_ndim+1) += B(m,0,2,2) * C(0,2,0,0) * B(n,0,0,0) * vol; - K(m*m_ndim+0, n*m_ndim+1) += B(m,0,2,2) * C(0,2,1,1) * B(n,1,1,0) * vol; - K(m*m_ndim+0, n*m_ndim+0) += B(m,0,2,2) * C(0,2,2,2) * B(n,2,2,2) * vol; - K(m*m_ndim+0, n*m_ndim+0) += B(m,0,2,2) * C(0,2,2,0) * B(n,0,2,2) * vol; - K(m*m_ndim+0, n*m_ndim+1) += B(m,0,2,2) * C(0,2,0,2) * B(n,2,0,0) * vol; - - K(m*m_ndim+1, n*m_ndim+1) += B(m,2,0,0) * C(2,0,0,0) * B(n,0,0,0) * vol; - K(m*m_ndim+1, n*m_ndim+1) += B(m,2,0,0) * C(2,0,1,1) * B(n,1,1,0) * vol; - K(m*m_ndim+1, n*m_ndim+0) += B(m,2,0,0) * C(2,0,2,2) * B(n,2,2,2) * vol; - K(m*m_ndim+1, n*m_ndim+0) += B(m,2,0,0) * C(2,0,2,0) * B(n,0,2,2) * vol; - K(m*m_ndim+1, n*m_ndim+1) += B(m,2,0,0) * C(2,0,0,2) * B(n,2,0,0) * vol; + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem,m_nip,m_tdim,m_tdim,m_tdim,m_tdim})); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + + elemmat.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto K = xt::adapt(&elemmat(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto B = xt::adapt(&m_B(e,q,0,0,0,0), xt::xshape()); + auto C = xt::adapt(&qtensor(e,q,0,0,0,0), xt::xshape()); + auto& vol = m_vol(e, q); + + // K(m*m_ndim+perm(c), n*m_ndim+perm(f)) = B(m,a,b,c) * C(a,b,d,e) * B(n,e,d,f) * vol; + // (where perm(0) = 1, perm(2) = 0) + for (size_t m = 0; m < m_nne; ++m) { + for (size_t n = 0; n < m_nne; ++n) { + K(m * m_ndim + 1, n * m_ndim + 1) += + B(m, 0, 0, 0) * C(0, 0, 0, 0) * B(n, 0, 0, 0) * vol; + K(m * m_ndim + 1, n * m_ndim + 1) += + B(m, 0, 0, 0) * C(0, 0, 1, 1) * B(n, 1, 1, 0) * vol; + K(m * m_ndim + 1, n * m_ndim + 0) += + B(m, 0, 0, 0) * C(0, 0, 2, 2) * B(n, 2, 2, 2) * vol; + K(m * m_ndim + 1, n * m_ndim + 0) += + B(m, 0, 0, 0) * C(0, 0, 2, 0) * B(n, 0, 2, 2) * vol; + K(m * m_ndim + 1, n * m_ndim + 1) += + B(m, 0, 0, 0) * C(0, 0, 0, 2) * B(n, 2, 0, 0) * vol; + + K(m * m_ndim + 1, n * m_ndim + 1) += + B(m, 1, 1, 0) * C(1, 1, 0, 0) * B(n, 0, 0, 0) * vol; + K(m * m_ndim + 1, n * m_ndim + 1) += + B(m, 1, 1, 0) * C(1, 1, 1, 1) * B(n, 1, 1, 0) * vol; + K(m * m_ndim + 1, n * m_ndim + 0) += + B(m, 1, 1, 0) * C(1, 1, 2, 2) * B(n, 2, 2, 2) * vol; + K(m * m_ndim + 1, n * m_ndim + 0) += + B(m, 1, 1, 0) * C(1, 1, 2, 0) * B(n, 0, 2, 2) * vol; + K(m * m_ndim + 1, n * m_ndim + 1) += + B(m, 1, 1, 0) * C(1, 1, 0, 2) * B(n, 2, 0, 0) * vol; + + K(m * m_ndim + 0, n * m_ndim + 1) += + B(m, 2, 2, 2) * C(2, 2, 0, 0) * B(n, 0, 0, 0) * vol; + K(m * m_ndim + 0, n * m_ndim + 1) += + B(m, 2, 2, 2) * C(2, 2, 1, 1) * B(n, 1, 1, 0) * vol; + K(m * m_ndim + 0, n * m_ndim + 0) += + B(m, 2, 2, 2) * C(2, 2, 2, 2) * B(n, 2, 2, 2) * vol; + K(m * m_ndim + 0, n * m_ndim + 0) += + B(m, 2, 2, 2) * C(2, 2, 2, 0) * B(n, 0, 2, 2) * vol; + K(m * m_ndim + 0, n * m_ndim + 1) += + B(m, 2, 2, 2) * C(2, 2, 0, 2) * B(n, 2, 0, 0) * vol; + + K(m * m_ndim + 0, n * m_ndim + 1) += + B(m, 0, 2, 2) * C(0, 2, 0, 0) * B(n, 0, 0, 0) * vol; + K(m * m_ndim + 0, n * m_ndim + 1) += + B(m, 0, 2, 2) * C(0, 2, 1, 1) * B(n, 1, 1, 0) * vol; + K(m * m_ndim + 0, n * m_ndim + 0) += + B(m, 0, 2, 2) * C(0, 2, 2, 2) * B(n, 2, 2, 2) * vol; + K(m * m_ndim + 0, n * m_ndim + 0) += + B(m, 0, 2, 2) * C(0, 2, 2, 0) * B(n, 0, 2, 2) * vol; + K(m * m_ndim + 0, n * m_ndim + 1) += + B(m, 0, 2, 2) * C(0, 2, 0, 2) * B(n, 2, 0, 0) * vol; + + K(m * m_ndim + 1, n * m_ndim + 1) += + B(m, 2, 0, 0) * C(2, 0, 0, 0) * B(n, 0, 0, 0) * vol; + K(m * m_ndim + 1, n * m_ndim + 1) += + B(m, 2, 0, 0) * C(2, 0, 1, 1) * B(n, 1, 1, 0) * vol; + K(m * m_ndim + 1, n * m_ndim + 0) += + B(m, 2, 0, 0) * C(2, 0, 2, 2) * B(n, 2, 2, 2) * vol; + K(m * m_ndim + 1, n * m_ndim + 0) += + B(m, 2, 0, 0) * C(2, 0, 2, 0) * B(n, 0, 2, 2) * vol; + K(m * m_ndim + 1, n * m_ndim + 1) += + B(m, 2, 0, 0) * C(2, 0, 0, 2) * B(n, 2, 0, 0) * vol; + } + } } - } } - } } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor QuadratureAxisymmetric::DV() const { - xt::xtensor out = xt::empty({m_nelem, m_nip}); - this->dV(out); - return out; + xt::xtensor out = xt::empty({m_nelem, m_nip}); + this->dV(out); + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xarray QuadratureAxisymmetric::DV(size_t rank) const { - std::vector shape = {m_nelem, m_nip}; + std::vector shape = {m_nelem, m_nip}; - for (size_t i = 0; i < rank; ++i) - shape.push_back(static_cast(m_tdim)); + for (size_t i = 0; i < rank; ++i) { + shape.push_back(static_cast(m_tdim)); + } - xt::xarray out = xt::empty(shape); - this->dV(out); - return out; + xt::xarray out = xt::empty(shape); + this->dV(out); + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadratureAxisymmetric::GradN_vector( - const xt::xtensor& elemvec) const +inline xt::xtensor +QuadratureAxisymmetric::GradN_vector(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); - this->gradN_vector(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); + this->gradN_vector(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadratureAxisymmetric::GradN_vector_T( - const xt::xtensor& elemvec) const +inline xt::xtensor +QuadratureAxisymmetric::GradN_vector_T(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); - this->gradN_vector_T(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); + this->gradN_vector_T(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadratureAxisymmetric::SymGradN_vector( - const xt::xtensor& elemvec) const +inline xt::xtensor +QuadratureAxisymmetric::SymGradN_vector(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); - this->symGradN_vector(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); + this->symGradN_vector(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadratureAxisymmetric::Int_N_scalar_NT_dV( - const xt::xtensor& qscalar) const +inline xt::xtensor +QuadratureAxisymmetric::Int_N_scalar_NT_dV(const xt::xtensor& qscalar) const { - xt::xtensor elemmat = xt::empty({m_nelem, m_nne*m_ndim, m_nne*m_ndim}); - this->int_N_scalar_NT_dV(qscalar, elemmat); - return elemmat; + xt::xtensor elemmat = xt::empty({m_nelem, m_nne * m_ndim, m_nne * m_ndim}); + this->int_N_scalar_NT_dV(qscalar, elemmat); + return elemmat; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadratureAxisymmetric::Int_gradN_dot_tensor2_dV( - const xt::xtensor& qtensor) const +inline xt::xtensor +QuadratureAxisymmetric::Int_gradN_dot_tensor2_dV(const xt::xtensor& qtensor) const { - xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); - this->int_gradN_dot_tensor2_dV(qtensor, elemvec); - return elemvec; + xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); + this->int_gradN_dot_tensor2_dV(qtensor, elemvec); + return elemvec; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor QuadratureAxisymmetric::Int_gradN_dot_tensor4_dot_gradNT_dV( - const xt::xtensor& qtensor) const - { - xt::xtensor elemmat = xt::empty({m_nelem, m_ndim*m_nne, m_ndim*m_nne}); - this->int_gradN_dot_tensor4_dot_gradNT_dV(qtensor, elemmat); - return elemmat; - } - -// ------------------------------------------------------------------------------------------------- - -}}} // namespace ... + const xt::xtensor& qtensor) const +{ + xt::xtensor elemmat = xt::empty({m_nelem, m_ndim * m_nne, m_ndim * m_nne}); + this->int_gradN_dot_tensor4_dot_gradNT_dV(qtensor, elemmat); + return elemmat; +} -// ================================================================================================= +} // namespace Quad4 +} // namespace Element +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/ElementQuad4Planar.hpp b/include/GooseFEM/ElementQuad4Planar.hpp index 7ecfafe..97ec69b 100644 --- a/include/GooseFEM/ElementQuad4Planar.hpp +++ b/include/GooseFEM/ElementQuad4Planar.hpp @@ -1,543 +1,513 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_ELEMENTQUAD4PLANAR_HPP #define GOOSEFEM_ELEMENTQUAD4PLANAR_HPP -// ------------------------------------------------------------------------------------------------- - #include "ElementQuad4Planar.h" -// ================================================================================================= - namespace GooseFEM { namespace Element { namespace Quad4 { -// ================================================================================================= - -inline QuadraturePlanar::QuadraturePlanar(const xt::xtensor& x, double thick) : - QuadraturePlanar(x, Gauss::xi(), Gauss::w(), thick) {} - -// ------------------------------------------------------------------------------------------------- +inline QuadraturePlanar::QuadraturePlanar(const xt::xtensor& x, double thick) + : QuadraturePlanar(x, Gauss::xi(), Gauss::w(), thick) +{ +} inline QuadraturePlanar::QuadraturePlanar( - const xt::xtensor& x, - const xt::xtensor& xi, - const xt::xtensor& w, - double thick) : - m_x(x), m_w(w), m_xi(xi), m_thick(thick) + const xt::xtensor& x, + const xt::xtensor& xi, + const xt::xtensor& w, + double thick) + : m_x(x), m_w(w), m_xi(xi), m_thick(thick) { - GOOSEFEM_ASSERT(m_x.shape(1) == m_nne); - GOOSEFEM_ASSERT(m_x.shape(2) == m_ndim); - - m_nelem = m_x.shape(0); - m_nip = m_w.size(); - - GOOSEFEM_ASSERT(m_xi.shape(0) == m_nip); - GOOSEFEM_ASSERT(m_xi.shape(1) == m_ndim); - GOOSEFEM_ASSERT(m_w.size() == m_nip); - - m_N = xt::empty({m_nip, m_nne}); - m_dNxi = xt::empty({m_nip, m_nne, m_ndim}); - m_dNx = xt::empty({m_nelem, m_nip, m_nne, m_ndim}); - m_vol = xt::empty({m_nelem, m_nip}); - - // shape functions - for (size_t q = 0 ; q < m_nip ; ++q) - { - m_N(q,0) = .25 * (1.-m_xi(q,0)) * (1.-m_xi(q,1)); - m_N(q,1) = .25 * (1.+m_xi(q,0)) * (1.-m_xi(q,1)); - m_N(q,2) = .25 * (1.+m_xi(q,0)) * (1.+m_xi(q,1)); - m_N(q,3) = .25 * (1.-m_xi(q,0)) * (1.+m_xi(q,1)); - } - - // shape function gradients in local coordinates - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - dN / dxi_0 - m_dNxi(q,0,0) = -.25*(1.-m_xi(q,1)); - m_dNxi(q,1,0) = +.25*(1.-m_xi(q,1)); - m_dNxi(q,2,0) = +.25*(1.+m_xi(q,1)); - m_dNxi(q,3,0) = -.25*(1.+m_xi(q,1)); - // - dN / dxi_1 - m_dNxi(q,0,1) = -.25*(1.-m_xi(q,0)); - m_dNxi(q,1,1) = -.25*(1.+m_xi(q,0)); - m_dNxi(q,2,1) = +.25*(1.+m_xi(q,0)); - m_dNxi(q,3,1) = +.25*(1.-m_xi(q,0)); - } - - // compute the shape function gradients, based on "x" - compute_dN(); -} + GOOSEFEM_ASSERT(m_x.shape(1) == m_nne); + GOOSEFEM_ASSERT(m_x.shape(2) == m_ndim); + + m_nelem = m_x.shape(0); + m_nip = m_w.size(); + + GOOSEFEM_ASSERT(m_xi.shape(0) == m_nip); + GOOSEFEM_ASSERT(m_xi.shape(1) == m_ndim); + GOOSEFEM_ASSERT(m_w.size() == m_nip); + + m_N = xt::empty({m_nip, m_nne}); + m_dNxi = xt::empty({m_nip, m_nne, m_ndim}); + m_dNx = xt::empty({m_nelem, m_nip, m_nne, m_ndim}); + m_vol = xt::empty({m_nelem, m_nip}); + + for (size_t q = 0; q < m_nip; ++q) { + m_N(q, 0) = 0.25 * (1.0 - m_xi(q, 0)) * (1.0 - m_xi(q, 1)); + m_N(q, 1) = 0.25 * (1.0 + m_xi(q, 0)) * (1.0 - m_xi(q, 1)); + m_N(q, 2) = 0.25 * (1.0 + m_xi(q, 0)) * (1.0 + m_xi(q, 1)); + m_N(q, 3) = 0.25 * (1.0 - m_xi(q, 0)) * (1.0 + m_xi(q, 1)); + } + + for (size_t q = 0; q < m_nip; ++q) { + // - dN / dxi_0 + m_dNxi(q, 0, 0) = -0.25 * (1.0 - m_xi(q, 1)); + m_dNxi(q, 1, 0) = +0.25 * (1.0 - m_xi(q, 1)); + m_dNxi(q, 2, 0) = +0.25 * (1.0 + m_xi(q, 1)); + m_dNxi(q, 3, 0) = -0.25 * (1.0 + m_xi(q, 1)); + // - dN / dxi_1 + m_dNxi(q, 0, 1) = -0.25 * (1.0 - m_xi(q, 0)); + m_dNxi(q, 1, 1) = -0.25 * (1.0 + m_xi(q, 0)); + m_dNxi(q, 2, 1) = +0.25 * (1.0 + m_xi(q, 0)); + m_dNxi(q, 3, 1) = +0.25 * (1.0 - m_xi(q, 0)); + } -// ------------------------------------------------------------------------------------------------- + compute_dN(); +} inline size_t QuadraturePlanar::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t QuadraturePlanar::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t QuadraturePlanar::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t QuadraturePlanar::nip() const { - return m_nip; + return m_nip; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor QuadraturePlanar::GradN() const { - return m_dNx; + return m_dNx; } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::dV(xt::xtensor& qscalar) const { - GOOSEFEM_ASSERT(qscalar.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip})); + GOOSEFEM_ASSERT( + qscalar.shape() == std::decay_t::shape_type({m_nelem, m_nip})); - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t q = 0 ; q < m_nip ; ++q) - qscalar(e,q) = m_vol(e,q); + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t q = 0; q < m_nip; ++q) { + qscalar(e, q) = m_vol(e, q); + } + } } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::dV(xt::xtensor& qtensor) const { - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t q = 0 ; q < m_nip ; ++q) - for (size_t i = 0 ; i < m_tdim ; ++i) - for (size_t j = 0 ; j < m_tdim ; ++j) - qtensor(e,q,i,j) = m_vol(e,q); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t q = 0; q < m_nip; ++q) { + for (size_t i = 0; i < m_tdim; ++i) { + for (size_t j = 0; j < m_tdim; ++j) { + qtensor(e, q, i, j) = m_vol(e, q); + } + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::dV(xt::xarray& qtensor) const { - GOOSEFEM_ASSERT(qtensor.shape(0) == m_nelem); - GOOSEFEM_ASSERT(qtensor.shape(1) == m_nip); + GOOSEFEM_ASSERT(qtensor.shape(0) == m_nelem); + GOOSEFEM_ASSERT(qtensor.shape(1) == m_nip); - xt::dynamic_shape strides = { - static_cast(m_vol.strides()[0]), - static_cast(m_vol.strides()[1])}; + xt::dynamic_shape strides = {static_cast(m_vol.strides()[0]), + static_cast(m_vol.strides()[1])}; - for (size_t i = 2; i < qtensor.shape().size(); ++i) - strides.push_back(0); + for (size_t i = 2; i < qtensor.shape().size(); ++i) { + strides.push_back(0); + } - qtensor = xt::strided_view(m_vol, qtensor.shape(), std::move(strides), 0ul, xt::layout_type::dynamic); + qtensor = + xt::strided_view(m_vol, qtensor.shape(), std::move(strides), 0ul, xt::layout_type::dynamic); } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::update_x(const xt::xtensor& x) { - GOOSEFEM_ASSERT(x.shape() == m_x.shape()); - - xt::noalias(m_x) = x; - - // update the shape function gradients for the new "x" - compute_dN(); + GOOSEFEM_ASSERT(x.shape() == m_x.shape()); + xt::noalias(m_x) = x; + compute_dN(); } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::compute_dN() { - #pragma omp parallel - { - // allocate local variables - xt::xtensor_fixed> J, Jinv; - - // loop over all elements (in parallel) - #pragma omp for - for (size_t e = 0 ; e < m_nelem ; ++e) + #pragma omp parallel { - // alias nodal positions - auto x = xt::adapt(&m_x(e,0,0), xt::xshape()); - - // loop over integration points - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNxi = xt::adapt(&m_dNxi( q,0,0), xt::xshape()); - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - - // - Jacobian (loops unrolled for efficiency) - // J(i,j) += dNxi(m,i) * x(m,j); - J(0,0) = dNxi(0,0)*x(0,0) + dNxi(1,0)*x(1,0) + dNxi(2,0)*x(2,0) + dNxi(3,0)*x(3,0); - J(0,1) = dNxi(0,0)*x(0,1) + dNxi(1,0)*x(1,1) + dNxi(2,0)*x(2,1) + dNxi(3,0)*x(3,1); - J(1,0) = dNxi(0,1)*x(0,0) + dNxi(1,1)*x(1,0) + dNxi(2,1)*x(2,0) + dNxi(3,1)*x(3,0); - J(1,1) = dNxi(0,1)*x(0,1) + dNxi(1,1)*x(1,1) + dNxi(2,1)*x(2,1) + dNxi(3,1)*x(3,1); - - // - determinant and inverse of the Jacobian - double Jdet = inv(J, Jinv); - - // - shape function gradients wrt global coordinates (loops partly unrolled for efficiency) - // dNx(m,i) += Jinv(i,j) * dNxi(m,j); - for (size_t m = 0 ; m < m_nne ; ++m) - { - dNx(m,0) = Jinv(0,0) * dNxi(m,0) + Jinv(0,1) * dNxi(m,1); - dNx(m,1) = Jinv(1,0) * dNxi(m,0) + Jinv(1,1) * dNxi(m,1); + xt::xtensor_fixed> J; + xt::xtensor_fixed> Jinv; + + #pragma omp for + for (size_t e = 0; e < m_nelem; ++e) { + + auto x = xt::adapt(&m_x(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNxi = xt::adapt(&m_dNxi(q, 0, 0), xt::xshape()); + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + + // J(i,j) += dNxi(m,i) * x(m,j); + J(0, 0) + = dNxi(0, 0) * x(0, 0) + + dNxi(1, 0) * x(1, 0) + + dNxi(2, 0) * x(2, 0) + + dNxi(3, 0) * x(3, 0); + J(0, 1) + = dNxi(0, 0) * x(0, 1) + + dNxi(1, 0) * x(1, 1) + + dNxi(2, 0) * x(2, 1) + + dNxi(3, 0) * x(3, 1); + J(1, 0) + = dNxi(0, 1) * x(0, 0) + + dNxi(1, 1) * x(1, 0) + + dNxi(2, 1) * x(2, 0) + + dNxi(3, 1) * x(3, 0); + J(1, 1) + = dNxi(0, 1) * x(0, 1) + + dNxi(1, 1) * x(1, 1) + + dNxi(2, 1) * x(2, 1) + + dNxi(3, 1) * x(3, 1); + + double Jdet = inv(J, Jinv); + + // dNx(m,i) += Jinv(i,j) * dNxi(m,j); + for (size_t m = 0; m < m_nne; ++m) { + dNx(m, 0) = Jinv(0, 0) * dNxi(m, 0) + Jinv(0, 1) * dNxi(m, 1); + dNx(m, 1) = Jinv(1, 0) * dNxi(m, 0) + Jinv(1, 1) * dNxi(m, 1); + } + + m_vol(e, q) = m_w(q) * Jdet * m_thick; + } } - - // - integration point volume - m_vol(e,q) = m_w(q) * Jdet * m_thick; - } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::gradN_vector( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const + const xt::xtensor& elemvec, xt::xtensor& qtensor) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); - - // zero-initialize (zero z-components not written below) - qtensor.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto gradu = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - - // - evaluate dyadic product (loops unrolled for efficiency) - // gradu(i,j) += dNx(m,i) * u(m,j) - gradu(0,0) = dNx(0,0)*u(0,0) + dNx(1,0)*u(1,0) + dNx(2,0)*u(2,0) + dNx(3,0)*u(3,0); - gradu(0,1) = dNx(0,0)*u(0,1) + dNx(1,0)*u(1,1) + dNx(2,0)*u(2,1) + dNx(3,0)*u(3,1); - gradu(1,0) = dNx(0,1)*u(0,0) + dNx(1,1)*u(1,0) + dNx(2,1)*u(2,0) + dNx(3,1)*u(3,0); - gradu(1,1) = dNx(0,1)*u(0,1) + dNx(1,1)*u(1,1) + dNx(2,1)*u(2,1) + dNx(3,1)*u(3,1); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); + + qtensor.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto gradu = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + // gradu(i,j) += dNx(m,i) * u(m,j) + gradu(0, 0) + = dNx(0, 0) * u(0, 0) + + dNx(1, 0) * u(1, 0) + + dNx(2, 0) * u(2, 0) + + dNx(3, 0) * u(3, 0); + gradu(0, 1) + = dNx(0, 0) * u(0, 1) + + dNx(1, 0) * u(1, 1) + + dNx(2, 0) * u(2, 1) + + dNx(3, 0) * u(3, 1); + gradu(1, 0) + = dNx(0, 1) * u(0, 0) + + dNx(1, 1) * u(1, 0) + + dNx(2, 1) * u(2, 0) + + dNx(3, 1) * u(3, 0); + gradu(1, 1) + = dNx(0, 1) * u(0, 1) + + dNx(1, 1) * u(1, 1) + + dNx(2, 1) * u(2, 1) + + dNx(3, 1) * u(3, 1); + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::gradN_vector_T( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const + const xt::xtensor& elemvec, xt::xtensor& qtensor) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); - - // zero-initialize (zero z-components not written below) - qtensor.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto gradu = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - - // - evaluate transpose of dyadic product (loops unrolled for efficiency) - // gradu(j,i) += dNx(m,i) * u(m,j) - gradu(0,0) = dNx(0,0)*u(0,0) + dNx(1,0)*u(1,0) + dNx(2,0)*u(2,0) + dNx(3,0)*u(3,0); - gradu(1,0) = dNx(0,0)*u(0,1) + dNx(1,0)*u(1,1) + dNx(2,0)*u(2,1) + dNx(3,0)*u(3,1); - gradu(0,1) = dNx(0,1)*u(0,0) + dNx(1,1)*u(1,0) + dNx(2,1)*u(2,0) + dNx(3,1)*u(3,0); - gradu(1,1) = dNx(0,1)*u(0,1) + dNx(1,1)*u(1,1) + dNx(2,1)*u(2,1) + dNx(3,1)*u(3,1); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); + + qtensor.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto gradu = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + // gradu(j,i) += dNx(m,i) * u(m,j) + gradu(0, 0) + = dNx(0, 0) * u(0, 0) + + dNx(1, 0) * u(1, 0) + + dNx(2, 0) * u(2, 0) + + dNx(3, 0) * u(3, 0); + gradu(1, 0) + = dNx(0, 0) * u(0, 1) + + dNx(1, 0) * u(1, 1) + + dNx(2, 0) * u(2, 1) + + dNx(3, 0) * u(3, 1); + gradu(0, 1) + = dNx(0, 1) * u(0, 0) + + dNx(1, 1) * u(1, 0) + + dNx(2, 1) * u(2, 0) + + dNx(3, 1) * u(3, 0); + gradu(1, 1) + = dNx(0, 1) * u(0, 1) + + dNx(1, 1) * u(1, 1) + + dNx(2, 1) * u(2, 1) + + dNx(3, 1) * u(3, 1); + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::symGradN_vector( - const xt::xtensor& elemvec, - xt::xtensor& qtensor) const + const xt::xtensor& elemvec, xt::xtensor& qtensor) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); - - // zero-initialize (zero z-components not written below) - qtensor.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias element vector (e.g. nodal displacements) - auto u = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto eps = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - - // - evaluate symmetrized dyadic product (loops unrolled for efficiency) - // grad(i,j) += dNx(m,i) * u(m,j) - // eps (j,i) = 0.5 * ( grad(i,j) + grad(j,i) ) - eps(0,0) = dNx(0,0)*u(0,0) + dNx(1,0)*u(1,0) + dNx(2,0)*u(2,0) + dNx(3,0)*u(3,0); - eps(1,1) = dNx(0,1)*u(0,1) + dNx(1,1)*u(1,1) + dNx(2,1)*u(2,1) + dNx(3,1)*u(3,1); - eps(0,1) = ( dNx(0,0)*u(0,1) + dNx(1,0)*u(1,1) + dNx(2,0)*u(2,1) + dNx(3,0)*u(3,1) + - dNx(0,1)*u(0,0) + dNx(1,1)*u(1,0) + dNx(2,1)*u(2,0) + dNx(3,1)*u(3,0) ) * 0.5; - eps(1,0) = eps(0,1); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); + + qtensor.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto u = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto eps = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + + // gradu(i,j) += dNx(m,i) * u(m,j) + // eps(j,i) = 0.5 * (gradu(i,j) + gradu(j,i)) + eps(0, 0) + = dNx(0, 0) * u(0, 0) + + dNx(1, 0) * u(1, 0) + + dNx(2, 0) * u(2, 0) + + dNx(3, 0) * u(3, 0); + eps(1, 1) + = dNx(0, 1) * u(0, 1) + + dNx(1, 1) * u(1, 1) + + dNx(2, 1) * u(2, 1) + + dNx(3, 1) * u(3, 1); + eps(0, 1) = 0.5 * + ( dNx(0, 0) * u(0, 1) + + dNx(1, 0) * u(1, 1) + + dNx(2, 0) * u(2, 1) + + dNx(3, 0) * u(3, 1) + + dNx(0, 1) * u(0, 0) + + dNx(1, 1) * u(1, 0) + + dNx(2, 1) * u(2, 0) + + dNx(3, 1) * u(3, 0)); + eps(1, 0) = eps(0, 1); + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::int_N_scalar_NT_dV( - const xt::xtensor& qscalar, - xt::xtensor& elemmat) const + const xt::xtensor& qscalar, xt::xtensor& elemmat) const { - GOOSEFEM_ASSERT(qscalar.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip})); - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - // zero-initialize: matrix of matrices - elemmat.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. mass matrix) - auto M = xt::adapt(&elemmat(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto N = xt::adapt(&m_N(q,0), xt::xshape()); - auto& vol = m_vol (e,q); - auto& rho = qscalar(e,q); - - // - evaluate scalar product, for all dimensions, and assemble - // M(m*ndim+i,n*ndim+i) += N(m) * scalar * N(n) * dV - for (size_t m = 0 ; m < m_nne ; ++m ){ - for (size_t n = 0 ; n < m_nne ; ++n ){ - M(m*m_ndim+0, n*m_ndim+0) += N(m) * rho * N(n) * vol; - M(m*m_ndim+1, n*m_ndim+1) += N(m) * rho * N(n) * vol; + GOOSEFEM_ASSERT( + qscalar.shape() == std::decay_t::shape_type({m_nelem, m_nip})); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + + elemmat.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto M = xt::adapt(&elemmat(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto N = xt::adapt(&m_N(q, 0), xt::xshape()); + auto& vol = m_vol(e, q); + auto& rho = qscalar(e, q); + + // M(m*ndim+i,n*ndim+i) += N(m) * scalar * N(n) * dV + for (size_t m = 0; m < m_nne; ++m) { + for (size_t n = 0; n < m_nne; ++n) { + M(m * m_ndim + 0, n * m_ndim + 0) += N(m) * rho * N(n) * vol; + M(m * m_ndim + 1, n * m_ndim + 1) += N(m) * rho * N(n) * vol; + } + } } - } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::int_gradN_dot_tensor2_dV( - const xt::xtensor& qtensor, - xt::xtensor& elemvec) const + const xt::xtensor& qtensor, xt::xtensor& elemvec) const { - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - - // zero-initialize output: matrix of vectors - elemvec.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. nodal force) - auto f = xt::adapt(&elemvec(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx (e,q,0,0), xt::xshape()); - auto sig = xt::adapt(&qtensor(e,q,0,0), xt::xshape()); - auto& vol = m_vol(e,q); - - // - evaluate dot product, and assemble - for (size_t m = 0 ; m < m_nne ; ++m) - { - f(m,0) += ( dNx(m,0) * sig(0,0) + dNx(m,1) * sig(1,0) ) * vol; - f(m,1) += ( dNx(m,0) * sig(0,1) + dNx(m,1) * sig(1,1) ) * vol; - } + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim})); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + + elemvec.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto f = xt::adapt(&elemvec(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e, q, 0, 0), xt::xshape()); + auto sig = xt::adapt(&qtensor(e, q, 0, 0), xt::xshape()); + auto& vol = m_vol(e, q); + + for (size_t m = 0; m < m_nne; ++m) { + f(m, 0) += (dNx(m, 0) * sig(0, 0) + dNx(m, 1) * sig(1, 0)) * vol; + f(m, 1) += (dNx(m, 0) * sig(0, 1) + dNx(m, 1) * sig(1, 1)) * vol; + } + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void QuadraturePlanar::int_gradN_dot_tensor4_dot_gradNT_dV( - const xt::xtensor& qtensor, - xt::xtensor& elemmat) const + const xt::xtensor& qtensor, xt::xtensor& elemmat) const { - GOOSEFEM_ASSERT(qtensor.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nip, m_tdim, m_tdim, m_tdim, m_tdim})); - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - // zero-initialize output: matrix of vector - elemmat.fill(0.0); - - // loop over all elements (in parallel) - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - { - // alias (e.g. nodal force) - auto K = xt::adapt(&elemmat(e,0,0), xt::xshape()); - - // loop over all integration points in element "e" - for (size_t q = 0 ; q < m_nip ; ++q) - { - // - alias - auto dNx = xt::adapt(&m_dNx(e,q,0,0), xt::xshape()); - auto C = xt::adapt(&qtensor(e,q,0,0,0,0), xt::xshape()); - auto& vol = m_vol(e,q); - - // - evaluate dot product, and assemble - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t n = 0 ; n < m_nne ; ++n) - for (size_t i = 0 ; i < m_ndim ; ++i) - for (size_t j = 0 ; j < m_ndim ; ++j) - for (size_t k = 0 ; k < m_ndim ; ++k) - for (size_t l = 0 ; l < m_ndim ; ++l) - K(m*m_ndim+j, n*m_ndim+k) += dNx(m,i) * C(i,j,k,l) * dNx(n,l) * vol; - } - } + GOOSEFEM_ASSERT( + qtensor.shape() == + std::decay_t::shape_type({m_nelem,m_nip,m_tdim,m_tdim,m_tdim,m_tdim})); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + + elemmat.fill(0.0); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + + auto K = xt::adapt(&elemmat(e, 0, 0), xt::xshape()); + + for (size_t q = 0; q < m_nip; ++q) { + + auto dNx = xt::adapt(&m_dNx(e,q,0,0), xt::xshape()); + auto C = xt::adapt(&qtensor(e,q,0,0,0,0), xt::xshape()); + auto& vol = m_vol(e, q); + + for (size_t m = 0; m < m_nne; ++m) { + for (size_t n = 0; n < m_nne; ++n) { + for (size_t i = 0; i < m_ndim; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + for (size_t k = 0; k < m_ndim; ++k) { + for (size_t l = 0; l < m_ndim; ++l) { + K(m * m_ndim + j, n * m_ndim + k) += + dNx(m, i) * C(i, j, k, l) * dNx(n, l) * vol; + } + } + } + } + } + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor QuadraturePlanar::DV() const { - xt::xtensor out = xt::empty({m_nelem, m_nip}); - this->dV(out); - return out; + xt::xtensor out = xt::empty({m_nelem, m_nip}); + this->dV(out); + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xarray QuadraturePlanar::DV(size_t rank) const { - std::vector shape = {m_nelem, m_nip}; + std::vector shape = {m_nelem, m_nip}; - for (size_t i = 0; i < rank; ++i) - shape.push_back(static_cast(m_tdim)); + for (size_t i = 0; i < rank; ++i) { + shape.push_back(static_cast(m_tdim)); + } - xt::xarray out = xt::empty(shape); - this->dV(out); - return out; + xt::xarray out = xt::empty(shape); + this->dV(out); + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadraturePlanar::GradN_vector( - const xt::xtensor& elemvec) const +inline xt::xtensor +QuadraturePlanar::GradN_vector(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); - this->gradN_vector(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); + this->gradN_vector(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadraturePlanar::GradN_vector_T( - const xt::xtensor& elemvec) const +inline xt::xtensor +QuadraturePlanar::GradN_vector_T(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); - this->gradN_vector_T(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); + this->gradN_vector_T(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadraturePlanar::SymGradN_vector( - const xt::xtensor& elemvec) const +inline xt::xtensor +QuadraturePlanar::SymGradN_vector(const xt::xtensor& elemvec) const { - xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); - this->symGradN_vector(elemvec, qtensor); - return qtensor; + xt::xtensor qtensor = xt::empty({m_nelem, m_nip, m_tdim, m_tdim}); + this->symGradN_vector(elemvec, qtensor); + return qtensor; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadraturePlanar::Int_N_scalar_NT_dV( - const xt::xtensor& qscalar) const +inline xt::xtensor +QuadraturePlanar::Int_N_scalar_NT_dV(const xt::xtensor& qscalar) const { - xt::xtensor elemmat = xt::empty({m_nelem, m_nne*m_ndim, m_nne*m_ndim}); - this->int_N_scalar_NT_dV(qscalar, elemmat); - return elemmat; + xt::xtensor elemmat = xt::empty({m_nelem, m_nne * m_ndim, m_nne * m_ndim}); + this->int_N_scalar_NT_dV(qscalar, elemmat); + return elemmat; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadraturePlanar::Int_gradN_dot_tensor2_dV( - const xt::xtensor& qtensor) const +inline xt::xtensor +QuadraturePlanar::Int_gradN_dot_tensor2_dV(const xt::xtensor& qtensor) const { - xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); - this->int_gradN_dot_tensor2_dV(qtensor, elemvec); - return elemvec; + xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); + this->int_gradN_dot_tensor2_dV(qtensor, elemvec); + return elemvec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor QuadraturePlanar::Int_gradN_dot_tensor4_dot_gradNT_dV( - const xt::xtensor& qtensor) const - { - xt::xtensor elemmat = xt::empty({m_nelem, m_ndim*m_nne, m_ndim*m_nne}); - this->int_gradN_dot_tensor4_dot_gradNT_dV(qtensor, elemmat); - return elemmat; - } - -// ------------------------------------------------------------------------------------------------- - -}}} // namespace ... +inline xt::xtensor +QuadraturePlanar::Int_gradN_dot_tensor4_dot_gradNT_dV(const xt::xtensor& qtensor) const +{ + xt::xtensor elemmat = xt::empty({m_nelem, m_ndim * m_nne, m_ndim * m_nne}); + this->int_gradN_dot_tensor4_dot_gradNT_dV(qtensor, elemmat); + return elemmat; +} -// ================================================================================================= +} // namespace Quad4 +} // namespace Element +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/Iterate.hpp b/include/GooseFEM/Iterate.hpp index a01b2c9..549d6aa 100644 --- a/include/GooseFEM/Iterate.hpp +++ b/include/GooseFEM/Iterate.hpp @@ -1,81 +1,65 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_ITERATE_HPP #define GOOSEFEM_ITERATE_HPP -// ------------------------------------------------------------------------------------------------- - #include "Iterate.h" -// ================================================================================================= - namespace GooseFEM { namespace Iterate { -// ------------------------------------------------------------------------------------------------- - inline StopList::StopList(size_t n) { - // resize list - m_res.resize(n); - - // set all residual to infinity - reset(); + m_res.resize(n); + reset(); } -// ------------------------------------------------------------------------------------------------- - inline void StopList::reset() { - // set all residual to infinity - for ( auto &i : m_res ) - i = std::numeric_limits::infinity(); + for (auto& i : m_res) { + i = std::numeric_limits::infinity(); + } } -// ------------------------------------------------------------------------------------------------- - inline void StopList::reset(size_t n) { - // resize list - m_res.resize(n); - - // set all residual to infinity - reset(); + m_res.resize(n); + reset(); } -// ------------------------------------------------------------------------------------------------- - inline bool StopList::stop(double res, double tol) { - // move residual one place back (forgetting the first) - for ( size_t i = 1 ; i < m_res.size() ; ++i ) - m_res[i-1] = m_res[i]; - - // add new residual to the end - m_res[m_res.size()-1] = res; - - // check for convergence: all residuals should be below the tolerance - for ( size_t i = 0 ; i < m_res.size() ; ++i ) - if ( m_res[i] > tol ) - return false; - - // check for convergence: all residuals should be decreasing - for ( size_t i = 1 ; i < m_res.size() ; ++i ) - if ( m_res[i] > m_res[i-1] ) - return false; - - // all checks passed: signal convergence - return true; + // move residual one place back (forgetting the first) + for (size_t i = 1; i < m_res.size(); ++i) { + m_res[i - 1] = m_res[i]; + } + + // add new residual to the end + m_res[m_res.size() - 1] = res; + + // check for convergence: all residuals should be below the tolerance + for (size_t i = 0; i < m_res.size(); ++i) { + if (m_res[i] > tol) { + return false; + } + } + + // check for convergence: all residuals should be decreasing + for (size_t i = 1; i < m_res.size(); ++i) { + if (m_res[i] > m_res[i - 1]) { + return false; + } + } + + // all checks passed: signal convergence + return true; } -// ------------------------------------------------------------------------------------------------- - -}} // namespace ... - -// ================================================================================================= +} // namespace Iterate +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/Matrix.hpp b/include/GooseFEM/Matrix.hpp index 45835b6..9cc038b 100644 --- a/include/GooseFEM/Matrix.hpp +++ b/include/GooseFEM/Matrix.hpp @@ -1,222 +1,182 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_MATRIX_HPP #define GOOSEFEM_MATRIX_HPP -// ------------------------------------------------------------------------------------------------- - #include "Matrix.h" -// ================================================================================================= - namespace GooseFEM { -// ------------------------------------------------------------------------------------------------- - template inline Matrix::Matrix( - const xt::xtensor &conn, - const xt::xtensor &dofs) : - m_conn(conn), m_dofs(dofs) + const xt::xtensor& conn, const xt::xtensor& dofs) + : m_conn(conn), m_dofs(dofs) { - m_nelem = m_conn.shape(0); - m_nne = m_conn.shape(1); - m_nnode = m_dofs.shape(0); - m_ndim = m_dofs.shape(1); - - m_ndof = xt::amax(m_dofs)[0] + 1; - - m_T.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); - - m_A.resize(m_ndof,m_ndof); - - GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); - GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); + m_nelem = m_conn.shape(0); + m_nne = m_conn.shape(1); + m_nnode = m_dofs.shape(0); + m_ndim = m_dofs.shape(1); + m_ndof = xt::amax(m_dofs)[0] + 1; + m_T.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_A.resize(m_ndof, m_ndof); + + GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); + GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); } -// ------------------------------------------------------------------------------------------------- - template inline size_t Matrix::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - template inline size_t Matrix::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - template inline size_t Matrix::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - template inline size_t Matrix::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - template inline size_t Matrix::ndof() const { - return m_ndof; + return m_ndof; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor Matrix::dofs() const { - return m_dofs; + return m_dofs; } -// ------------------------------------------------------------------------------------------------- - template inline void Matrix::factorize() { - if ( ! m_factor ) return; + if (!m_factor) { + return; + } - m_solver.compute(m_A); - m_factor = false; + m_solver.compute(m_A); + m_factor = false; } -// ------------------------------------------------------------------------------------------------- - template -inline void Matrix::assemble(const xt::xtensor &elemmat) +inline void Matrix::assemble(const xt::xtensor& elemmat) { - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - m_T.clear(); - - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - for (size_t n = 0 ; n < m_nne ; ++n) - for (size_t j = 0 ; j < m_ndim ; ++j) - m_T.push_back(Eigen::Triplet( - m_dofs(m_conn(e,m),i), m_dofs(m_conn(e,n),j), elemmat(e,m*m_ndim+i,n*m_ndim+j) - )); - - m_A.setFromTriplets(m_T.begin(), m_T.end()); - - m_factor = true; + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + + m_T.clear(); + + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + for (size_t n = 0; n < m_nne; ++n) { + for (size_t j = 0; j < m_ndim; ++j) { + m_T.push_back(Eigen::Triplet( + m_dofs(m_conn(e, m), i), + m_dofs(m_conn(e, n), j), + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + } + } + } + } + + m_A.setFromTriplets(m_T.begin(), m_T.end()); + + m_factor = true; } -// ------------------------------------------------------------------------------------------------- - template -inline void Matrix::solve( - const xt::xtensor &b, - xt::xtensor &x) +inline void Matrix::solve(const xt::xtensor& b, xt::xtensor& x) { - GOOSEFEM_ASSERT(b.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(x.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - - this->factorize(); - Eigen::VectorXd B = this->asDofs(b); - Eigen::VectorXd X = m_solver.solve(B); - this->asNode(X, x); -} + GOOSEFEM_ASSERT(b.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(x.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); -// ------------------------------------------------------------------------------------------------- + this->factorize(); + Eigen::VectorXd B = this->asDofs(b); + Eigen::VectorXd X = m_solver.solve(B); + this->asNode(X, x); +} template -inline void Matrix::solve( - const xt::xtensor &b, - xt::xtensor &x) +inline void Matrix::solve(const xt::xtensor& b, xt::xtensor& x) { - GOOSEFEM_ASSERT(b.size() == m_ndof); - GOOSEFEM_ASSERT(x.size() == m_ndof); - - this->factorize(); - Eigen::VectorXd B(m_ndof,1); - std::copy(b.begin(), b.end(), B.data()); - Eigen::VectorXd X = m_solver.solve(B); - std::copy(X.data(), X.data()+m_ndof, x.begin()); + GOOSEFEM_ASSERT(b.size() == m_ndof); + GOOSEFEM_ASSERT(x.size() == m_ndof); + + this->factorize(); + Eigen::VectorXd B(m_ndof, 1); + std::copy(b.begin(), b.end(), B.data()); + Eigen::VectorXd X = m_solver.solve(B); + std::copy(X.data(), X.data() + m_ndof, x.begin()); } -// ------------------------------------------------------------------------------------------------- - template -inline xt::xtensor Matrix::Solve( - const xt::xtensor &b) +inline xt::xtensor Matrix::Solve(const xt::xtensor& b) { - xt::xtensor x = xt::empty({m_nnode, m_ndim}); - this->solve(b, x); - return x; + xt::xtensor x = xt::empty({m_nnode, m_ndim}); + this->solve(b, x); + return x; } -// ------------------------------------------------------------------------------------------------- - template -inline xt::xtensor Matrix::Solve( - const xt::xtensor &b) +inline xt::xtensor Matrix::Solve(const xt::xtensor& b) { - xt::xtensor x = xt::empty({m_ndof}); - this->solve(b, x); - return x; + xt::xtensor x = xt::empty({m_ndof}); + this->solve(b, x); + return x; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd Matrix::asDofs(const xt::xtensor &nodevec) const +inline Eigen::VectorXd Matrix::asDofs(const xt::xtensor& nodevec) const { - assert(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + assert(nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - Eigen::VectorXd dofval(m_ndof,1); + Eigen::VectorXd dofval(m_ndof, 1); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - dofval(m_dofs(m,i)) = nodevec(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + dofval(m_dofs(m, i)) = nodevec(m, i); + } + } - return dofval; + return dofval; } -// ------------------------------------------------------------------------------------------------- - template -inline void Matrix::asNode( - const Eigen::VectorXd &dofval, - xt::xtensor &nodevec) const +inline void +Matrix::asNode(const Eigen::VectorXd& dofval, xt::xtensor& nodevec) const { - assert(static_cast(dofval.size()) == m_ndof); - assert(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - nodevec(m,i) = dofval(m_dofs(m,i)); + assert(static_cast(dofval.size()) == m_ndof); + assert(nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + nodevec(m, i) = dofval(m_dofs(m, i)); + } + } } -// ------------------------------------------------------------------------------------------------- - -} // namespace ... - -// ================================================================================================= +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/MatrixDiagonal.hpp b/include/GooseFEM/MatrixDiagonal.hpp index 3957c75..9a4a208 100644 --- a/include/GooseFEM/MatrixDiagonal.hpp +++ b/include/GooseFEM/MatrixDiagonal.hpp @@ -1,233 +1,179 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_MATRIXDIAGONAL_HPP #define GOOSEFEM_MATRIXDIAGONAL_HPP -// ------------------------------------------------------------------------------------------------- - #include "MatrixDiagonal.h" -// ================================================================================================= - namespace GooseFEM { -// ------------------------------------------------------------------------------------------------- - inline MatrixDiagonal::MatrixDiagonal( - const xt::xtensor &conn, - const xt::xtensor &dofs) : - m_conn(conn), m_dofs(dofs) + const xt::xtensor& conn, const xt::xtensor& dofs) + : m_conn(conn), m_dofs(dofs) { - m_nelem = m_conn.shape(0); - m_nne = m_conn.shape(1); - m_nnode = m_dofs.shape(0); - m_ndim = m_dofs.shape(1); - - m_ndof = xt::amax(m_dofs)[0] + 1; + m_nelem = m_conn.shape(0); + m_nne = m_conn.shape(1); + m_nnode = m_dofs.shape(0); + m_ndim = m_dofs.shape(1); + m_ndof = xt::amax(m_dofs)[0] + 1; + m_A = xt::empty({m_ndof}); + m_inv = xt::empty({m_ndof}); - m_A = xt::empty({m_ndof}); - - m_inv = xt::empty({m_ndof}); - - GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); - GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); + GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); + GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonal::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonal::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonal::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonal::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonal::ndof() const { - return m_ndof; + return m_ndof; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonal::dofs() const { - return m_dofs; + return m_dofs; } -// ------------------------------------------------------------------------------------------------- - inline void MatrixDiagonal::factorize() { - if (!m_factor) return; + if (!m_factor) { + return; + } - #pragma omp parallel for - for (size_t d = 0 ; d < m_ndof ; ++d) - m_inv(d) = 1. / m_A(d); + #pragma omp parallel for + for (size_t d = 0; d < m_ndof; ++d) + m_inv(d) = 1.0 / m_A(d); - m_factor = false; + m_factor = false; } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonal::set(const xt::xtensor &A) +inline void MatrixDiagonal::set(const xt::xtensor& A) { - GOOSEFEM_ASSERT(A.size() == m_ndof); - std::copy(A.begin(), A.end(), m_A.begin()); - m_factor = true; + GOOSEFEM_ASSERT(A.size() == m_ndof); + std::copy(A.begin(), A.end(), m_A.begin()); + m_factor = true; } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonal::assemble(const xt::xtensor &elemmat) +inline void MatrixDiagonal::assemble(const xt::xtensor& elemmat) { - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - GOOSEFEM_ASSERT(Element::isDiagonal(elemmat)); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + GOOSEFEM_ASSERT(Element::isDiagonal(elemmat)); - m_A.fill(0.0); + m_A.fill(0.0); - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - m_A(m_dofs(m_conn(e,m),i)) += elemmat(e,m*m_ndim+i,m*m_ndim+i); + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + m_A(m_dofs(m_conn(e, m), i)) += elemmat(e, m * m_ndim + i, m * m_ndim + i); + } + } + } - m_factor = true; + m_factor = true; } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonal::dot( - const xt::xtensor &x, - xt::xtensor &b) const +inline void MatrixDiagonal::dot(const xt::xtensor& x, xt::xtensor& b) const { - GOOSEFEM_ASSERT(x.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(b.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(x.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(b.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - b(m,i) = m_A(m_dofs(m,i)) * x(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + b(m, i) = m_A(m_dofs(m, i)) * x(m, i); + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonal::dot( - const xt::xtensor &x, - xt::xtensor &b) const +inline void MatrixDiagonal::dot(const xt::xtensor& x, xt::xtensor& b) const { - GOOSEFEM_ASSERT(x.size() == m_ndof); - GOOSEFEM_ASSERT(b.size() == m_ndof); + GOOSEFEM_ASSERT(x.size() == m_ndof); + GOOSEFEM_ASSERT(b.size() == m_ndof); - xt::noalias(b) = m_A * x; + xt::noalias(b) = m_A * x; } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonal::solve( - const xt::xtensor &b, - xt::xtensor &x) +inline void MatrixDiagonal::solve(const xt::xtensor& b, xt::xtensor& x) { - GOOSEFEM_ASSERT(b.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(x.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(b.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(x.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - this->factorize(); + this->factorize(); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - x(m,i) = m_inv(m_dofs(m,i)) * b(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + x(m, i) = m_inv(m_dofs(m, i)) * b(m, i); + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonal::solve( - const xt::xtensor &b, - xt::xtensor &x) +inline void MatrixDiagonal::solve(const xt::xtensor& b, xt::xtensor& x) { - GOOSEFEM_ASSERT(b.size() == m_ndof); - GOOSEFEM_ASSERT(x.size() == m_ndof); - - this->factorize(); - - xt::noalias(x) = m_inv * b; + GOOSEFEM_ASSERT(b.size() == m_ndof); + GOOSEFEM_ASSERT(x.size() == m_ndof); + this->factorize(); + xt::noalias(x) = m_inv * b; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonal::AsDiagonal() const { - return m_A; + return m_A; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor MatrixDiagonal::Dot(const xt::xtensor &x) const +inline xt::xtensor MatrixDiagonal::Dot(const xt::xtensor& x) const { - xt::xtensor b = xt::empty({m_nnode, m_ndim}); - this->dot(x, b); - return b; + xt::xtensor b = xt::empty({m_nnode, m_ndim}); + this->dot(x, b); + return b; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor MatrixDiagonal::Dot(const xt::xtensor &x) const +inline xt::xtensor MatrixDiagonal::Dot(const xt::xtensor& x) const { - xt::xtensor b = xt::empty({m_ndof}); - this->dot(x, b); - return b; + xt::xtensor b = xt::empty({m_ndof}); + this->dot(x, b); + return b; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor MatrixDiagonal::Solve(const xt::xtensor &b) +inline xt::xtensor MatrixDiagonal::Solve(const xt::xtensor& b) { - xt::xtensor x = xt::empty({m_nnode, m_ndim}); - this->solve(b, x); - return x; + xt::xtensor x = xt::empty({m_nnode, m_ndim}); + this->solve(b, x); + return x; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor MatrixDiagonal::Solve(const xt::xtensor &b) +inline xt::xtensor MatrixDiagonal::Solve(const xt::xtensor& b) { - xt::xtensor x = xt::empty({m_ndof}); - this->solve(b, x); - return x; + xt::xtensor x = xt::empty({m_ndof}); + this->solve(b, x); + return x; } -// ------------------------------------------------------------------------------------------------- - -} // namespace ... - -// ================================================================================================= +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/MatrixDiagonalPartitioned.hpp b/include/GooseFEM/MatrixDiagonalPartitioned.hpp index c089401..f7c4635 100644 --- a/include/GooseFEM/MatrixDiagonalPartitioned.hpp +++ b/include/GooseFEM/MatrixDiagonalPartitioned.hpp @@ -1,475 +1,398 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_MATRIXDIAGONALPARTITIONED_HPP #define GOOSEFEM_MATRIXDIAGONALPARTITIONED_HPP -// ------------------------------------------------------------------------------------------------- - #include "MatrixDiagonalPartitioned.h" #include "Mesh.h" -// ================================================================================================= - namespace GooseFEM { -// ------------------------------------------------------------------------------------------------- - inline MatrixDiagonalPartitioned::MatrixDiagonalPartitioned( - const xt::xtensor &conn, - const xt::xtensor &dofs, - const xt::xtensor &iip) : - m_conn(conn), m_dofs(dofs), m_iip(iip) -{ - m_nelem = m_conn.shape(0); - m_nne = m_conn.shape(1); - m_nnode = m_dofs.shape(0); - m_ndim = m_dofs.shape(1); - - m_iiu = xt::setdiff1d(dofs, iip); - - m_ndof = xt::amax(m_dofs)[0] + 1; - m_nnp = m_iip.size(); - m_nnu = m_iiu.size(); - - m_part = Mesh::Reorder({m_iiu, m_iip}).get(m_dofs); - - m_Auu = xt::empty({m_nnu}); - m_App = xt::empty({m_nnp}); - - m_inv_uu = xt::empty({m_nnu}); - - GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); - GOOSEFEM_ASSERT(xt::amax(m_iip)[0] <= xt::amax(m_dofs)[0]); - GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); + const xt::xtensor& conn, + const xt::xtensor& dofs, + const xt::xtensor& iip) + : m_conn(conn), m_dofs(dofs), m_iip(iip) +{ + m_nelem = m_conn.shape(0); + m_nne = m_conn.shape(1); + m_nnode = m_dofs.shape(0); + m_ndim = m_dofs.shape(1); + m_iiu = xt::setdiff1d(dofs, iip); + m_ndof = xt::amax(m_dofs)[0] + 1; + m_nnp = m_iip.size(); + m_nnu = m_iiu.size(); + m_part = Mesh::Reorder({m_iiu, m_iip}).get(m_dofs); + m_Auu = xt::empty({m_nnu}); + m_App = xt::empty({m_nnp}); + m_inv_uu = xt::empty({m_nnu}); + + GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); + GOOSEFEM_ASSERT(xt::amax(m_iip)[0] <= xt::amax(m_dofs)[0]); + GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonalPartitioned::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonalPartitioned::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonalPartitioned::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonalPartitioned::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonalPartitioned::ndof() const { - return m_ndof; + return m_ndof; } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonalPartitioned::nnu() const { - return m_nnu; + return m_nnu; } -// ------------------------------------------------------------------------------------------------- - inline size_t MatrixDiagonalPartitioned::nnp() const { - return m_nnp; + return m_nnp; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonalPartitioned::dofs() const { - return m_dofs; + return m_dofs; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonalPartitioned::iiu() const { - return m_iiu; + return m_iiu; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonalPartitioned::iip() const { - return m_iip; + return m_iip; } -// ------------------------------------------------------------------------------------------------- - inline void MatrixDiagonalPartitioned::factorize() { - if (!m_factor) return; + if (!m_factor) { + return; + } - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - m_inv_uu(d) = 1. / m_Auu(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + m_inv_uu(d) = 1.0 / m_Auu(d); + } - m_factor = false; + m_factor = false; } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonalPartitioned::assemble(const xt::xtensor &elemmat) +inline void MatrixDiagonalPartitioned::assemble(const xt::xtensor& elemmat) { - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - GOOSEFEM_ASSERT(Element::isDiagonal(elemmat)); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + GOOSEFEM_ASSERT(Element::isDiagonal(elemmat)); - m_Auu.fill(0.0); - m_App.fill(0.0); + m_Auu.fill(0.0); + m_App.fill(0.0); - for (size_t e = 0 ; e < m_nelem ; ++e) { - for (size_t m = 0 ; m < m_nne ; ++m) { - for (size_t i = 0 ; i < m_ndim ; ++i) { + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { - size_t d = m_part(m_conn(e,m),i); + size_t d = m_part(m_conn(e, m), i); - if ( d < m_nnu ) - m_Auu(d ) += elemmat(e,m*m_ndim+i,m*m_ndim+i); - else - m_App(d-m_nnu) += elemmat(e,m*m_ndim+i,m*m_ndim+i); - } + if (d < m_nnu) { + m_Auu(d) += elemmat(e, m * m_ndim + i, m * m_ndim + i); + } + else { + m_App(d - m_nnu) += elemmat(e, m * m_ndim + i, m * m_ndim + i); + } + } + } } - } - m_factor = true; + m_factor = true; } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonalPartitioned::dot( - const xt::xtensor &x, - xt::xtensor &b) const +inline void +MatrixDiagonalPartitioned::dot(const xt::xtensor& x, xt::xtensor& b) const { - GOOSEFEM_ASSERT(x.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(b.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(x.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(b.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) { - for (size_t i = 0 ; i < m_ndim ; ++i) { + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { - size_t d = m_part(m,i); + size_t d = m_part(m, i); - if ( d < m_nnu ) b(m,i) = m_Auu(d ) * x(m,i); - else b(m,i) = m_App(d-m_nnu) * x(m,i); + if (d < m_nnu) { + b(m, i) = m_Auu(d) * x(m, i); + } + else { + b(m, i) = m_App(d - m_nnu) * x(m, i); + } + } } - } } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonalPartitioned::dot( - const xt::xtensor &x, - xt::xtensor &b) const +inline void +MatrixDiagonalPartitioned::dot(const xt::xtensor& x, xt::xtensor& b) const { - GOOSEFEM_ASSERT(x.size() == m_ndof); - GOOSEFEM_ASSERT(b.size() == m_ndof); + GOOSEFEM_ASSERT(x.size() == m_ndof); + GOOSEFEM_ASSERT(b.size() == m_ndof); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - b(m_iiu(d)) = m_Auu(d) * x(m_iiu(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + b(m_iiu(d)) = m_Auu(d) * x(m_iiu(d)); + } - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnp ; ++d) - b(m_iip(d)) = m_App(d) * x(m_iip(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnp; ++d) { + b(m_iip(d)) = m_App(d) * x(m_iip(d)); + } } -// ------------------------------------------------------------------------------------------------- - inline void MatrixDiagonalPartitioned::dot_u( - const xt::xtensor &x_u, - const xt::xtensor &x_p, - xt::xtensor &b_u) const + const xt::xtensor& x_u, + const xt::xtensor& x_p, + xt::xtensor& b_u) const { - UNUSED(x_p); + UNUSED(x_p); - GOOSEFEM_ASSERT(x_u.size() == m_nnu); - GOOSEFEM_ASSERT(x_p.size() == m_nnp); - GOOSEFEM_ASSERT(b_u.size() == m_nnu); + GOOSEFEM_ASSERT(x_u.size() == m_nnu); + GOOSEFEM_ASSERT(x_p.size() == m_nnp); + GOOSEFEM_ASSERT(b_u.size() == m_nnu); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - b_u(d) = m_Auu(d) * x_u(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + b_u(d) = m_Auu(d) * x_u(d); + } } -// ------------------------------------------------------------------------------------------------- - inline void MatrixDiagonalPartitioned::dot_p( - const xt::xtensor &x_u, - const xt::xtensor &x_p, - xt::xtensor &b_p) const + const xt::xtensor& x_u, + const xt::xtensor& x_p, + xt::xtensor& b_p) const { - UNUSED(x_u); + UNUSED(x_u); - GOOSEFEM_ASSERT(x_u.size() == m_nnu); - GOOSEFEM_ASSERT(x_p.size() == m_nnp); - GOOSEFEM_ASSERT(b_p.size() == m_nnp); + GOOSEFEM_ASSERT(x_u.size() == m_nnu); + GOOSEFEM_ASSERT(x_p.size() == m_nnp); + GOOSEFEM_ASSERT(b_p.size() == m_nnp); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnp ; ++d) - b_p(d) = m_App(d) * x_p(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnp; ++d) { + b_p(d) = m_App(d) * x_p(d); + } } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonalPartitioned::solve( - const xt::xtensor &b, - xt::xtensor &x) +inline void +MatrixDiagonalPartitioned::solve(const xt::xtensor& b, xt::xtensor& x) { - GOOSEFEM_ASSERT(b.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(x.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(b.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(x.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - this->factorize(); + this->factorize(); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if ( m_part(m,i) < m_nnu ) - x(m,i) = m_inv_uu(m_part(m,i)) * b(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) < m_nnu) { + x(m, i) = m_inv_uu(m_part(m, i)) * b(m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void MatrixDiagonalPartitioned::solve( - const xt::xtensor &b, - xt::xtensor &x) +inline void +MatrixDiagonalPartitioned::solve(const xt::xtensor& b, xt::xtensor& x) { - GOOSEFEM_ASSERT(b.size() == m_ndof); - GOOSEFEM_ASSERT(x.size() == m_ndof); + GOOSEFEM_ASSERT(b.size() == m_ndof); + GOOSEFEM_ASSERT(x.size() == m_ndof); - this->factorize(); + this->factorize(); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - x(m_iiu(d)) = m_inv_uu(d) * b(m_iiu(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + x(m_iiu(d)) = m_inv_uu(d) * b(m_iiu(d)); + } } -// ------------------------------------------------------------------------------------------------- - inline void MatrixDiagonalPartitioned::solve_u( - const xt::xtensor &b_u, - const xt::xtensor &x_p, - xt::xtensor &x_u) + const xt::xtensor& b_u, + const xt::xtensor& x_p, + xt::xtensor& x_u) { - UNUSED(x_p); + UNUSED(x_p); - GOOSEFEM_ASSERT(b_u.size() == m_nnu); - GOOSEFEM_ASSERT(x_p.size() == m_nnp); - GOOSEFEM_ASSERT(x_u.size() == m_nnu); + GOOSEFEM_ASSERT(b_u.size() == m_nnu); + GOOSEFEM_ASSERT(x_p.size() == m_nnp); + GOOSEFEM_ASSERT(x_u.size() == m_nnu); - this->factorize(); + this->factorize(); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - x_u(d) = m_inv_uu(d) * b_u(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + x_u(d) = m_inv_uu(d) * b_u(d); + } } -// ------------------------------------------------------------------------------------------------- - inline void MatrixDiagonalPartitioned::reaction( - const xt::xtensor &x, - xt::xtensor &b) const -{ - GOOSEFEM_ASSERT(x.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(b.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m,i) >= m_nnu) - b(m,i) = m_App(m_part(m,i)-m_nnu) * x(m,i); + const xt::xtensor& x, xt::xtensor& b) const +{ + GOOSEFEM_ASSERT(x.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(b.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) >= m_nnu) { + b(m, i) = m_App(m_part(m, i) - m_nnu) * x(m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void MatrixDiagonalPartitioned::reaction( - const xt::xtensor &x, - xt::xtensor &b) const + const xt::xtensor& x, xt::xtensor& b) const { - GOOSEFEM_ASSERT(x.size() == m_ndof); - GOOSEFEM_ASSERT(b.size() == m_ndof); + GOOSEFEM_ASSERT(x.size() == m_ndof); + GOOSEFEM_ASSERT(b.size() == m_ndof); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnp ; ++d) - b(m_iip(d)) = m_App(d) * x(m_iip(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnp; ++d) { + b(m_iip(d)) = m_App(d) * x(m_iip(d)); + } } -// ------------------------------------------------------------------------------------------------- - inline void MatrixDiagonalPartitioned::reaction_p( - const xt::xtensor &x_u, - const xt::xtensor &x_p, - xt::xtensor &b_p) const + const xt::xtensor& x_u, + const xt::xtensor& x_p, + xt::xtensor& b_p) const { - UNUSED(x_u); + UNUSED(x_u); - GOOSEFEM_ASSERT(x_u.size() == m_nnu); - GOOSEFEM_ASSERT(x_p.size() == m_nnp); - GOOSEFEM_ASSERT(b_p.size() == m_nnp); + GOOSEFEM_ASSERT(x_u.size() == m_nnu); + GOOSEFEM_ASSERT(x_p.size() == m_nnp); + GOOSEFEM_ASSERT(b_p.size() == m_nnp); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnp ; ++d) - b_p(d) = m_App(d) * x_p(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnp; ++d) { + b_p(d) = m_App(d) * x_p(d); + } } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonalPartitioned::AsDiagonal() const { - xt::xtensor out = xt::zeros({m_ndof}); + xt::xtensor out = xt::zeros({m_ndof}); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - out(m_iiu(d)) = m_Auu(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + out(m_iiu(d)) = m_Auu(d); + } - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnp ; ++d) - out(m_iip(d)) = m_App(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnp; ++d) { + out(m_iip(d)) = m_App(d); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor MatrixDiagonalPartitioned::Dot( - const xt::xtensor &x) const +inline xt::xtensor MatrixDiagonalPartitioned::Dot(const xt::xtensor& x) const { - xt::xtensor b = xt::empty({m_nnode, m_ndim}); - this->dot(x, b); - return b; + xt::xtensor b = xt::empty({m_nnode, m_ndim}); + this->dot(x, b); + return b; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor MatrixDiagonalPartitioned::Dot( - const xt::xtensor &x) const +inline xt::xtensor MatrixDiagonalPartitioned::Dot(const xt::xtensor& x) const { - xt::xtensor b = xt::empty({m_ndof}); - this->dot(x, b); - return b; + xt::xtensor b = xt::empty({m_ndof}); + this->dot(x, b); + return b; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonalPartitioned::Dot_u( - const xt::xtensor &x_u, - const xt::xtensor &x_p) const + const xt::xtensor& x_u, const xt::xtensor& x_p) const { - xt::xtensor b_u = xt::empty({m_nnu}); - this->dot_u(x_u, x_p, b_u); - return b_u; + xt::xtensor b_u = xt::empty({m_nnu}); + this->dot_u(x_u, x_p, b_u); + return b_u; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonalPartitioned::Dot_p( - const xt::xtensor &x_u, - const xt::xtensor &x_p) const + const xt::xtensor& x_u, const xt::xtensor& x_p) const { - xt::xtensor b_p = xt::empty({m_nnp}); - this->dot_p(x_u, x_p, b_p); - return b_p; + xt::xtensor b_p = xt::empty({m_nnp}); + this->dot_p(x_u, x_p, b_p); + return b_p; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor MatrixDiagonalPartitioned::Solve( - const xt::xtensor &b, - const xt::xtensor &x) +inline xt::xtensor +MatrixDiagonalPartitioned::Solve(const xt::xtensor& b, const xt::xtensor& x) { - xt::xtensor out = x; - this->solve(b, out); - return out; + xt::xtensor out = x; + this->solve(b, out); + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor MatrixDiagonalPartitioned::Solve( - const xt::xtensor &b, - const xt::xtensor &x) +inline xt::xtensor +MatrixDiagonalPartitioned::Solve(const xt::xtensor& b, const xt::xtensor& x) { - xt::xtensor out = x; - this->solve(b, out); - return out; + xt::xtensor out = x; + this->solve(b, out); + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonalPartitioned::Solve_u( - const xt::xtensor &b_u, - const xt::xtensor &x_p) + const xt::xtensor& b_u, const xt::xtensor& x_p) { - xt::xtensor x_u = xt::empty({m_nnu}); - this->solve_u(b_u, x_p, x_u); - return x_u; + xt::xtensor x_u = xt::empty({m_nnu}); + this->solve_u(b_u, x_p, x_u); + return x_u; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonalPartitioned::Reaction( - const xt::xtensor &x, - const xt::xtensor &b) const + const xt::xtensor& x, const xt::xtensor& b) const { - xt::xtensor out = b; - this->reaction(x, out); - return out; + xt::xtensor out = b; + this->reaction(x, out); + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonalPartitioned::Reaction( - const xt::xtensor &x, - const xt::xtensor &b) const + const xt::xtensor& x, const xt::xtensor& b) const { - xt::xtensor out = b; - this->reaction(x, out); - return out; + xt::xtensor out = b; + this->reaction(x, out); + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor MatrixDiagonalPartitioned::Reaction_p( - const xt::xtensor &x_u, - const xt::xtensor &x_p) const + const xt::xtensor& x_u, const xt::xtensor& x_p) const { - xt::xtensor b_p = xt::empty({m_nnp}); - this->reaction_p(x_u, x_p, b_p); - return b_p; + xt::xtensor b_p = xt::empty({m_nnp}); + this->reaction_p(x_u, x_p, b_p); + return b_p; } -// ------------------------------------------------------------------------------------------------- - -} // namespace ... - -// ================================================================================================= +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/MatrixPartitioned.hpp b/include/GooseFEM/MatrixPartitioned.hpp index 33efd49..8b4500d 100644 --- a/include/GooseFEM/MatrixPartitioned.hpp +++ b/include/GooseFEM/MatrixPartitioned.hpp @@ -1,500 +1,432 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_MATRIXPARTITIONED_HPP #define GOOSEFEM_MATRIXPARTITIONED_HPP -// ------------------------------------------------------------------------------------------------- - #include "MatrixPartitioned.h" #include "Mesh.h" -// ================================================================================================= - namespace GooseFEM { -// ------------------------------------------------------------------------------------------------- - template inline MatrixPartitioned::MatrixPartitioned( - const xt::xtensor &conn, - const xt::xtensor &dofs, - const xt::xtensor &iip) : - m_conn(conn), m_dofs(dofs), m_iip(iip) + const xt::xtensor& conn, + const xt::xtensor& dofs, + const xt::xtensor& iip) + : m_conn(conn), m_dofs(dofs), m_iip(iip) { - m_nelem = m_conn.shape(0); - m_nne = m_conn.shape(1); - m_nnode = m_dofs.shape(0); - m_ndim = m_dofs.shape(1); - - m_iiu = xt::setdiff1d(dofs, iip); - - m_ndof = xt::amax(m_dofs)[0] + 1; - m_nnp = m_iip.size(); - m_nnu = m_iiu.size(); - - m_part = Mesh::Reorder({m_iiu, m_iip}).get(m_dofs); - - m_Tuu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); - m_Tup.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); - m_Tpu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); - m_Tpp.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); - - m_Auu.resize(m_nnu, m_nnu); - m_Aup.resize(m_nnu, m_nnp); - m_Apu.resize(m_nnp, m_nnu); - m_App.resize(m_nnp, m_nnp); - - GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); - GOOSEFEM_ASSERT(xt::amax(m_iip)[0] <= xt::amax(m_dofs)[0]); - GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); + m_nelem = m_conn.shape(0); + m_nne = m_conn.shape(1); + m_nnode = m_dofs.shape(0); + m_ndim = m_dofs.shape(1); + m_iiu = xt::setdiff1d(dofs, iip); + m_ndof = xt::amax(m_dofs)[0] + 1; + m_nnp = m_iip.size(); + m_nnu = m_iiu.size(); + m_part = Mesh::Reorder({m_iiu, m_iip}).get(m_dofs); + m_Tuu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tup.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tpu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tpp.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Auu.resize(m_nnu, m_nnu); + m_Aup.resize(m_nnu, m_nnp); + m_Apu.resize(m_nnp, m_nnu); + m_App.resize(m_nnp, m_nnp); + + GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); + GOOSEFEM_ASSERT(xt::amax(m_iip)[0] <= xt::amax(m_dofs)[0]); + GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitioned::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitioned::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitioned::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitioned::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitioned::ndof() const { - return m_ndof; + return m_ndof; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitioned::nnu() const { - return m_nnu; + return m_nnu; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitioned::nnp() const { - return m_nnp; + return m_nnp; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitioned::dofs() const { - return m_dofs; + return m_dofs; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitioned::iiu() const { - return m_iiu; + return m_iiu; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitioned::iip() const { - return m_iip; + return m_iip; } -// ------------------------------------------------------------------------------------------------- - template inline void MatrixPartitioned::factorize() { - if (!m_factor) return; - m_solver.compute(m_Auu); - m_factor = false; + if (!m_factor) { + return; + } + m_solver.compute(m_Auu); + m_factor = false; } -// ------------------------------------------------------------------------------------------------- - template -inline void MatrixPartitioned::assemble(const xt::xtensor &elemmat) +inline void MatrixPartitioned::assemble(const xt::xtensor& elemmat) { - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - m_Tuu.clear(); - m_Tup.clear(); - m_Tpu.clear(); - m_Tpp.clear(); - - for (size_t e = 0 ; e < m_nelem ; ++e) { - for (size_t m = 0 ; m < m_nne ; ++m) { - for (size_t i = 0 ; i < m_ndim ; ++i) { - - size_t di = m_part(m_conn(e,m),i); - - for (size_t n = 0 ; n < m_nne ; ++n) { - for (size_t j = 0 ; j < m_ndim ; ++j) { - - size_t dj = m_part(m_conn(e,n),j); - - if (di < m_nnu && dj < m_nnu) { - m_Tuu.push_back(Eigen::Triplet( - di, - dj, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - else if (di < m_nnu) { - m_Tup.push_back(Eigen::Triplet( - di, - dj - m_nnu, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + + m_Tuu.clear(); + m_Tup.clear(); + m_Tpu.clear(); + m_Tpp.clear(); + + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + + size_t di = m_part(m_conn(e, m), i); + + for (size_t n = 0; n < m_nne; ++n) { + for (size_t j = 0; j < m_ndim; ++j) { + + size_t dj = m_part(m_conn(e, n), j); + + if (di < m_nnu && dj < m_nnu) { + m_Tuu.push_back(Eigen::Triplet( + di, + dj, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else if (di < m_nnu) { + m_Tup.push_back(Eigen::Triplet( + di, + dj - m_nnu, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else if (dj < m_nnu) { + m_Tpu.push_back(Eigen::Triplet( + di - m_nnu, + dj, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else { + m_Tpp.push_back(Eigen::Triplet( + di - m_nnu, + dj - m_nnu, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + } + } } - else if (dj < m_nnu) { - m_Tpu.push_back(Eigen::Triplet( - di - m_nnu, - dj, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - else { - m_Tpp.push_back(Eigen::Triplet( - di - m_nnu, - dj - m_nnu, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - } } - } } - } - m_Auu.setFromTriplets(m_Tuu.begin(), m_Tuu.end()); - m_Aup.setFromTriplets(m_Tup.begin(), m_Tup.end()); - m_Apu.setFromTriplets(m_Tpu.begin(), m_Tpu.end()); - m_App.setFromTriplets(m_Tpp.begin(), m_Tpp.end()); + m_Auu.setFromTriplets(m_Tuu.begin(), m_Tuu.end()); + m_Aup.setFromTriplets(m_Tup.begin(), m_Tup.end()); + m_Apu.setFromTriplets(m_Tpu.begin(), m_Tpu.end()); + m_App.setFromTriplets(m_Tpp.begin(), m_Tpp.end()); - m_factor = true; + m_factor = true; } -// ------------------------------------------------------------------------------------------------- - template -inline void MatrixPartitioned::solve( - const xt::xtensor &b, - xt::xtensor &x) +inline void +MatrixPartitioned::solve(const xt::xtensor& b, xt::xtensor& x) { - GOOSEFEM_ASSERT(b.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(x.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(b.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(x.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - this->factorize(); + this->factorize(); - Eigen::VectorXd B_u = this->asDofs_u(b); - Eigen::VectorXd X_p = this->asDofs_p(x); + Eigen::VectorXd B_u = this->asDofs_u(b); + Eigen::VectorXd X_p = this->asDofs_p(x); - Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_Aup * X_p)); + Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_Aup * X_p)); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if ( m_part(m,i) < m_nnu ) - x(m,i) = X_u(m_part(m,i)); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) < m_nnu) { + x(m, i) = X_u(m_part(m, i)); + } + } + } } -// ------------------------------------------------------------------------------------------------- - template -inline void MatrixPartitioned::solve( - const xt::xtensor &b, - xt::xtensor &x) +inline void +MatrixPartitioned::solve(const xt::xtensor& b, xt::xtensor& x) { - GOOSEFEM_ASSERT(b.size() == m_ndof); - GOOSEFEM_ASSERT(x.size() == m_ndof); + GOOSEFEM_ASSERT(b.size() == m_ndof); + GOOSEFEM_ASSERT(x.size() == m_ndof); - this->factorize(); + this->factorize(); - Eigen::VectorXd B_u = this->asDofs_u(b); - Eigen::VectorXd X_p = this->asDofs_p(x); + Eigen::VectorXd B_u = this->asDofs_u(b); + Eigen::VectorXd X_p = this->asDofs_p(x); - Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_Aup * X_p)); + Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_Aup * X_p)); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - x(m_iiu(d)) = X_u(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + x(m_iiu(d)) = X_u(d); + } } -// ------------------------------------------------------------------------------------------------- - template inline void MatrixPartitioned::solve_u( - const xt::xtensor &b_u, - const xt::xtensor &x_p, - xt::xtensor &x_u) + const xt::xtensor& b_u, + const xt::xtensor& x_p, + xt::xtensor& x_u) { - GOOSEFEM_ASSERT(b_u.size() == m_nnu); - GOOSEFEM_ASSERT(x_p.size() == m_nnp); - GOOSEFEM_ASSERT(x_u.size() == m_nnu); + GOOSEFEM_ASSERT(b_u.size() == m_nnu); + GOOSEFEM_ASSERT(x_p.size() == m_nnp); + GOOSEFEM_ASSERT(x_u.size() == m_nnu); - this->factorize(); + this->factorize(); - Eigen::VectorXd B_u(m_nnu,1); - Eigen::VectorXd X_p(m_nnp,1); + Eigen::VectorXd B_u(m_nnu, 1); + Eigen::VectorXd X_p(m_nnp, 1); - std::copy(b_u.begin(), b_u.end(), B_u.data()); - std::copy(x_p.begin(), x_p.end(), X_p.data()); + std::copy(b_u.begin(), b_u.end(), B_u.data()); + std::copy(x_p.begin(), x_p.end(), X_p.data()); - Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_Aup * X_p)); + Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_Aup * X_p)); - std::copy(X_u.data(), X_u.data()+m_nnu, x_u.begin()); + std::copy(X_u.data(), X_u.data() + m_nnu, x_u.begin()); } -// ------------------------------------------------------------------------------------------------- - template inline void MatrixPartitioned::reaction( - const xt::xtensor &x, - xt::xtensor &b) const + const xt::xtensor& x, xt::xtensor& b) const { - GOOSEFEM_ASSERT(x.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(b.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(x.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(b.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - Eigen::VectorXd X_u = this->asDofs_u(x); - Eigen::VectorXd X_p = this->asDofs_p(x); + Eigen::VectorXd X_u = this->asDofs_u(x); + Eigen::VectorXd X_p = this->asDofs_p(x); - Eigen::VectorXd B_p = m_Apu * X_u + m_App * X_p; + Eigen::VectorXd B_p = m_Apu * X_u + m_App * X_p; - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m,i) >= m_nnu) - b(m,i) = B_p(m_part(m,i)-m_nnu); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) >= m_nnu) { + b(m, i) = B_p(m_part(m, i) - m_nnu); + } + } + } } -// ------------------------------------------------------------------------------------------------- - template inline void MatrixPartitioned::reaction( - const xt::xtensor &x, - xt::xtensor &b) const + const xt::xtensor& x, xt::xtensor& b) const { - GOOSEFEM_ASSERT(x.size() == m_ndof); - GOOSEFEM_ASSERT(b.size() == m_ndof); + GOOSEFEM_ASSERT(x.size() == m_ndof); + GOOSEFEM_ASSERT(b.size() == m_ndof); - Eigen::VectorXd X_u = this->asDofs_u(x); - Eigen::VectorXd X_p = this->asDofs_p(x); + Eigen::VectorXd X_u = this->asDofs_u(x); + Eigen::VectorXd X_p = this->asDofs_p(x); - Eigen::VectorXd B_p = m_Apu * X_u + m_App * X_p; + Eigen::VectorXd B_p = m_Apu * X_u + m_App * X_p; - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnp ; ++d) - b(m_iip(d)) = B_p(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnp; ++d) { + b(m_iip(d)) = B_p(d); + } } -// ------------------------------------------------------------------------------------------------- - template inline void MatrixPartitioned::reaction_p( - const xt::xtensor &x_u, - const xt::xtensor &x_p, - xt::xtensor &b_p) const + const xt::xtensor& x_u, + const xt::xtensor& x_p, + xt::xtensor& b_p) const { - GOOSEFEM_ASSERT(x_u.size() == m_nnu); - GOOSEFEM_ASSERT(x_p.size() == m_nnp); - GOOSEFEM_ASSERT(b_p.size() == m_nnp); + GOOSEFEM_ASSERT(x_u.size() == m_nnu); + GOOSEFEM_ASSERT(x_p.size() == m_nnp); + GOOSEFEM_ASSERT(b_p.size() == m_nnp); - Eigen::VectorXd X_u(m_nnu,1); - Eigen::VectorXd X_p(m_nnp,1); + Eigen::VectorXd X_u(m_nnu, 1); + Eigen::VectorXd X_p(m_nnp, 1); - std::copy(x_u.begin(), x_u.end(), X_u.data()); - std::copy(x_p.begin(), x_p.end(), X_p.data()); + std::copy(x_u.begin(), x_u.end(), X_u.data()); + std::copy(x_p.begin(), x_p.end(), X_p.data()); - Eigen::VectorXd B_p = m_Apu * X_u + m_App * X_p; + Eigen::VectorXd B_p = m_Apu * X_u + m_App * X_p; - std::copy(B_p.data(), B_p.data()+m_nnp, b_p.begin()); + std::copy(B_p.data(), B_p.data() + m_nnp, b_p.begin()); } -// ------------------------------------------------------------------------------------------------- - template -inline xt::xtensor MatrixPartitioned::Solve( - const xt::xtensor &b, - const xt::xtensor &x) +inline xt::xtensor +MatrixPartitioned::Solve(const xt::xtensor& b, const xt::xtensor& x) { - xt::xtensor out = x; - this->solve(b, out); - return out; + xt::xtensor out = x; + this->solve(b, out); + return out; } -// ------------------------------------------------------------------------------------------------- - template -inline xt::xtensor MatrixPartitioned::Solve( - const xt::xtensor &b, - const xt::xtensor &x) +inline xt::xtensor +MatrixPartitioned::Solve(const xt::xtensor& b, const xt::xtensor& x) { - xt::xtensor out = x; - this->solve(b, out); - return out; + xt::xtensor out = x; + this->solve(b, out); + return out; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitioned::Solve_u( - const xt::xtensor &b_u, - const xt::xtensor &x_p) + const xt::xtensor& b_u, const xt::xtensor& x_p) { - xt::xtensor x_u = xt::empty({m_nnu}); - this->solve_u(b_u, x_p, x_u); - return x_u; + xt::xtensor x_u = xt::empty({m_nnu}); + this->solve_u(b_u, x_p, x_u); + return x_u; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitioned::Reaction( - const xt::xtensor &x, - const xt::xtensor &b) const + const xt::xtensor& x, const xt::xtensor& b) const { - xt::xtensor out = b; - this->reaction(x, out); - return out; + xt::xtensor out = b; + this->reaction(x, out); + return out; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitioned::Reaction( - const xt::xtensor &x, - const xt::xtensor &b) const + const xt::xtensor& x, const xt::xtensor& b) const { - xt::xtensor out = b; - this->reaction(x, out); - return out; + xt::xtensor out = b; + this->reaction(x, out); + return out; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitioned::Reaction_p( - const xt::xtensor &x_u, - const xt::xtensor &x_p) const + const xt::xtensor& x_u, const xt::xtensor& x_p) const { - xt::xtensor b_p = xt::empty({m_nnp}); - this->reaction_p(x_u, x_p, b_p); - return b_p; + xt::xtensor b_p = xt::empty({m_nnp}); + this->reaction_p(x_u, x_p, b_p); + return b_p; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd MatrixPartitioned::asDofs_u( - const xt::xtensor &dofval) const +inline Eigen::VectorXd +MatrixPartitioned::asDofs_u(const xt::xtensor& dofval) const { - assert(dofval.size() == m_ndof); + assert(dofval.size() == m_ndof); - Eigen::VectorXd dofval_u(m_nnu,1); + Eigen::VectorXd dofval_u(m_nnu, 1); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - dofval_u(d) = dofval(m_iiu(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + dofval_u(d) = dofval(m_iiu(d)); + } - return dofval_u; + return dofval_u; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd MatrixPartitioned::asDofs_u( - const xt::xtensor &nodevec) const +inline Eigen::VectorXd +MatrixPartitioned::asDofs_u(const xt::xtensor& nodevec) const { - assert(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + assert(nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - Eigen::VectorXd dofval_u(m_nnu,1); + Eigen::VectorXd dofval_u(m_nnu, 1); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m,i) < m_nnu) - dofval_u(m_part(m,i)) = nodevec(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) < m_nnu) { + dofval_u(m_part(m, i)) = nodevec(m, i); + } + } + } - return dofval_u; + return dofval_u; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd MatrixPartitioned::asDofs_p( - const xt::xtensor &dofval) const +inline Eigen::VectorXd +MatrixPartitioned::asDofs_p(const xt::xtensor& dofval) const { - assert(dofval.size() == m_ndof); + assert(dofval.size() == m_ndof); - Eigen::VectorXd dofval_p(m_nnp,1); + Eigen::VectorXd dofval_p(m_nnp, 1); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnp ; ++d) - dofval_p(d) = dofval(m_iip(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnp; ++d) { + dofval_p(d) = dofval(m_iip(d)); + } - return dofval_p; + return dofval_p; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd MatrixPartitioned::asDofs_p( - const xt::xtensor &nodevec) const +inline Eigen::VectorXd +MatrixPartitioned::asDofs_p(const xt::xtensor& nodevec) const { - assert(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + assert(nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - Eigen::VectorXd dofval_p(m_nnp,1); + Eigen::VectorXd dofval_p(m_nnp, 1); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m,i) >= m_nnu) - dofval_p(m_part(m,i)-m_nnu) = nodevec(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) >= m_nnu) { + dofval_p(m_part(m, i) - m_nnu) = nodevec(m, i); + } + } + } - return dofval_p; + return dofval_p; } -// ------------------------------------------------------------------------------------------------- - -} // namespace ... - -// ================================================================================================= +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/MatrixPartitionedTyings.hpp b/include/GooseFEM/MatrixPartitionedTyings.hpp index 82ee2c5..4ab7068 100644 --- a/include/GooseFEM/MatrixPartitionedTyings.hpp +++ b/include/GooseFEM/MatrixPartitionedTyings.hpp @@ -1,553 +1,487 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_MATRIXPARTITIONEDTYINGS_HPP #define GOOSEFEM_MATRIXPARTITIONEDTYINGS_HPP -// ------------------------------------------------------------------------------------------------- - #include "MatrixPartitionedTyings.h" -// ================================================================================================= - namespace GooseFEM { -// ------------------------------------------------------------------------------------------------- - template inline MatrixPartitionedTyings::MatrixPartitionedTyings( - const xt::xtensor& conn, - const xt::xtensor& dofs, - const Eigen::SparseMatrix& Cdu, - const Eigen::SparseMatrix& Cdp) : - m_conn(conn), - m_dofs(dofs), - m_Cdu(Cdu), - m_Cdp(Cdp) + const xt::xtensor& conn, + const xt::xtensor& dofs, + const Eigen::SparseMatrix& Cdu, + const Eigen::SparseMatrix& Cdp) + : m_conn(conn), m_dofs(dofs), m_Cdu(Cdu), m_Cdp(Cdp) { - GOOSEFEM_ASSERT(Cdu.rows() == Cdp.rows()); - - m_nnu = static_cast(m_Cdu.cols()); - m_nnp = static_cast(m_Cdp.cols()); - m_nnd = static_cast(m_Cdp.rows()); - m_nni = m_nnu + m_nnp; - m_ndof = m_nni + m_nnd; - - m_iiu = xt::arange(m_nnu); - m_iip = xt::arange(m_nnu, m_nnu + m_nnp); - m_iid = xt::arange(m_nni, m_nni + m_nnd); - - m_nelem = m_conn.shape(0); - m_nne = m_conn.shape(1); - m_nnode = m_dofs.shape(0); - m_ndim = m_dofs.shape(1); - - m_Cud = m_Cdu.transpose(); - m_Cpd = m_Cdp.transpose(); - - m_Tuu.reserve(m_nelem*m_nne*m_ndim*m_nne*m_ndim); - m_Tup.reserve(m_nelem*m_nne*m_ndim*m_nne*m_ndim); - m_Tpu.reserve(m_nelem*m_nne*m_ndim*m_nne*m_ndim); - m_Tpp.reserve(m_nelem*m_nne*m_ndim*m_nne*m_ndim); - m_Tud.reserve(m_nelem*m_nne*m_ndim*m_nne*m_ndim); - m_Tpd.reserve(m_nelem*m_nne*m_ndim*m_nne*m_ndim); - m_Tdu.reserve(m_nelem*m_nne*m_ndim*m_nne*m_ndim); - m_Tdp.reserve(m_nelem*m_nne*m_ndim*m_nne*m_ndim); - m_Tdd.reserve(m_nelem*m_nne*m_ndim*m_nne*m_ndim); - - m_Auu.resize(m_nnu,m_nnu); - m_Aup.resize(m_nnu,m_nnp); - m_Apu.resize(m_nnp,m_nnu); - m_App.resize(m_nnp,m_nnp); - m_Aud.resize(m_nnu,m_nnd); - m_Apd.resize(m_nnp,m_nnd); - m_Adu.resize(m_nnd,m_nnu); - m_Adp.resize(m_nnd,m_nnp); - m_Add.resize(m_nnd,m_nnd); - - GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); - GOOSEFEM_ASSERT(m_ndof == xt::amax(m_dofs)[0] + 1); + GOOSEFEM_ASSERT(Cdu.rows() == Cdp.rows()); + + m_nnu = static_cast(m_Cdu.cols()); + m_nnp = static_cast(m_Cdp.cols()); + m_nnd = static_cast(m_Cdp.rows()); + m_nni = m_nnu + m_nnp; + m_ndof = m_nni + m_nnd; + m_iiu = xt::arange(m_nnu); + m_iip = xt::arange(m_nnu, m_nnu + m_nnp); + m_iid = xt::arange(m_nni, m_nni + m_nnd); + m_nelem = m_conn.shape(0); + m_nne = m_conn.shape(1); + m_nnode = m_dofs.shape(0); + m_ndim = m_dofs.shape(1); + m_Cud = m_Cdu.transpose(); + m_Cpd = m_Cdp.transpose(); + m_Tuu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tup.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tpu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tpp.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tud.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tpd.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tdu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tdp.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Tdd.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); + m_Auu.resize(m_nnu, m_nnu); + m_Aup.resize(m_nnu, m_nnp); + m_Apu.resize(m_nnp, m_nnu); + m_App.resize(m_nnp, m_nnp); + m_Aud.resize(m_nnu, m_nnd); + m_Apd.resize(m_nnp, m_nnd); + m_Adu.resize(m_nnd, m_nnu); + m_Adp.resize(m_nnd, m_nnp); + m_Add.resize(m_nnd, m_nnd); + + GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); + GOOSEFEM_ASSERT(m_ndof == xt::amax(m_dofs)[0] + 1); } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitionedTyings::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitionedTyings::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitionedTyings::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitionedTyings::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitionedTyings::ndof() const { - return m_ndof; + return m_ndof; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitionedTyings::nnu() const { - return m_nnu; + return m_nnu; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitionedTyings::nnp() const { - return m_nnp; + return m_nnp; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitionedTyings::nni() const { - return m_nni; + return m_nni; } -// ------------------------------------------------------------------------------------------------- - template inline size_t MatrixPartitionedTyings::nnd() const { - return m_nnd; + return m_nnd; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitionedTyings::dofs() const { - return m_dofs; + return m_dofs; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitionedTyings::iiu() const { - return m_iiu; + return m_iiu; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitionedTyings::iip() const { - return m_iip; + return m_iip; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitionedTyings::iii() const { - return xt::arange(m_nni); + return xt::arange(m_nni); } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitionedTyings::iid() const { - return m_iid; + return m_iid; } -// ------------------------------------------------------------------------------------------------- - template inline void MatrixPartitionedTyings::factorize() { - if (!m_factor) return; + if (!m_factor) { + return; + } - m_ACuu = m_Auu + m_Aud * m_Cdu + m_Cud * m_Adu + m_Cud * m_Add * m_Cdu; - m_ACup = m_Aup + m_Aud * m_Cdp + m_Cud * m_Adp + m_Cud * m_Add * m_Cdp; - // m_ACpu = m_Apu + m_Apd * m_Cdu + m_Cpd * m_Adu + m_Cpd * m_Add * m_Cdu; - // m_ACpp = m_App + m_Apd * m_Cdp + m_Cpd * m_Adp + m_Cpd * m_Add * m_Cdp; + m_ACuu = m_Auu + m_Aud * m_Cdu + m_Cud * m_Adu + m_Cud * m_Add * m_Cdu; + m_ACup = m_Aup + m_Aud * m_Cdp + m_Cud * m_Adp + m_Cud * m_Add * m_Cdp; + // m_ACpu = m_Apu + m_Apd * m_Cdu + m_Cpd * m_Adu + m_Cpd * m_Add * m_Cdu; + // m_ACpp = m_App + m_Apd * m_Cdp + m_Cpd * m_Adp + m_Cpd * m_Add * m_Cdp; - m_solver.compute(m_ACuu); + m_solver.compute(m_ACuu); - m_factor = false; + m_factor = false; } -// ------------------------------------------------------------------------------------------------- - template inline void MatrixPartitionedTyings::assemble(const xt::xtensor& elemmat) { - GOOSEFEM_ASSERT(elemmat.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne*m_ndim, m_nne*m_ndim})); - - m_Tuu.clear(); - m_Tup.clear(); - m_Tpu.clear(); - m_Tpp.clear(); - m_Tud.clear(); - m_Tpd.clear(); - m_Tdu.clear(); - m_Tdp.clear(); - m_Tdd.clear(); - - for (size_t e = 0 ; e < m_nelem ; ++e) { - for (size_t m = 0 ; m < m_nne ; ++m) { - for (size_t i = 0 ; i < m_ndim ; ++i) { - - size_t di = m_dofs(m_conn(e,m),i); - - for (size_t n = 0 ; n < m_nne ; ++n) { - for (size_t j = 0 ; j < m_ndim ; ++j) { - - size_t dj = m_dofs(m_conn(e,n),j); - - if (di < m_nnu && dj < m_nnu) { - m_Tuu.push_back(Eigen::Triplet( - di, - dj, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - else if (di < m_nnu && dj < m_nni) { - m_Tup.push_back(Eigen::Triplet( - di, - dj - m_nnu, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - else if (di < m_nnu) { - m_Tud.push_back(Eigen::Triplet( - di, - dj - m_nni, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - else if (di < m_nni && dj < m_nnu) { - m_Tpu.push_back(Eigen::Triplet( - di - m_nnu, - dj, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - else if (di < m_nni && dj < m_nni) { - m_Tpp.push_back(Eigen::Triplet( - di - m_nnu, - dj - m_nnu, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); + GOOSEFEM_ASSERT( + elemmat.shape() == + std::decay_t::shape_type({m_nelem, m_nne * m_ndim, m_nne * m_ndim})); + + m_Tuu.clear(); + m_Tup.clear(); + m_Tpu.clear(); + m_Tpp.clear(); + m_Tud.clear(); + m_Tpd.clear(); + m_Tdu.clear(); + m_Tdp.clear(); + m_Tdd.clear(); + + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + + size_t di = m_dofs(m_conn(e, m), i); + + for (size_t n = 0; n < m_nne; ++n) { + for (size_t j = 0; j < m_ndim; ++j) { + + size_t dj = m_dofs(m_conn(e, n), j); + + if (di < m_nnu && dj < m_nnu) { + m_Tuu.push_back(Eigen::Triplet( + di, + dj, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else if (di < m_nnu && dj < m_nni) { + m_Tup.push_back(Eigen::Triplet( + di, + dj - m_nnu, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else if (di < m_nnu) { + m_Tud.push_back(Eigen::Triplet( + di, + dj - m_nni, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else if (di < m_nni && dj < m_nnu) { + m_Tpu.push_back(Eigen::Triplet( + di - m_nnu, + dj, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else if (di < m_nni && dj < m_nni) { + m_Tpp.push_back(Eigen::Triplet( + di - m_nnu, + dj - m_nnu, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else if (di < m_nni) { + m_Tpd.push_back(Eigen::Triplet( + di - m_nnu, + dj - m_nni, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else if (dj < m_nnu) { + m_Tdu.push_back(Eigen::Triplet( + di - m_nni, + dj, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else if (dj < m_nni) { + m_Tdp.push_back(Eigen::Triplet( + di - m_nni, + dj - m_nnu, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + else { + m_Tdd.push_back(Eigen::Triplet( + di - m_nni, + dj - m_nni, + elemmat(e, m * m_ndim + i, n * m_ndim + j))); + } + } + } } - else if (di < m_nni) { - m_Tpd.push_back(Eigen::Triplet( - di - m_nnu, - dj - m_nni, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - else if (dj < m_nnu) { - m_Tdu.push_back(Eigen::Triplet( - di - m_nni, - dj, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - else if (dj < m_nni) { - m_Tdp.push_back(Eigen::Triplet( - di - m_nni, - dj - m_nnu, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - else { - m_Tdd.push_back(Eigen::Triplet( - di - m_nni, - dj - m_nni, - elemmat(e, m * m_ndim + i, n * m_ndim + j))); - } - } } - } } - } - - m_Auu.setFromTriplets(m_Tuu.begin(), m_Tuu.end()); - m_Aup.setFromTriplets(m_Tup.begin(), m_Tup.end()); - m_Apu.setFromTriplets(m_Tpu.begin(), m_Tpu.end()); - m_App.setFromTriplets(m_Tpp.begin(), m_Tpp.end()); - m_Aud.setFromTriplets(m_Tud.begin(), m_Tud.end()); - m_Apd.setFromTriplets(m_Tpd.begin(), m_Tpd.end()); - m_Adu.setFromTriplets(m_Tdu.begin(), m_Tdu.end()); - m_Adp.setFromTriplets(m_Tdp.begin(), m_Tdp.end()); - m_Add.setFromTriplets(m_Tdd.begin(), m_Tdd.end()); - - m_factor = true; -} -// ------------------------------------------------------------------------------------------------- + m_Auu.setFromTriplets(m_Tuu.begin(), m_Tuu.end()); + m_Aup.setFromTriplets(m_Tup.begin(), m_Tup.end()); + m_Apu.setFromTriplets(m_Tpu.begin(), m_Tpu.end()); + m_App.setFromTriplets(m_Tpp.begin(), m_Tpp.end()); + m_Aud.setFromTriplets(m_Tud.begin(), m_Tud.end()); + m_Apd.setFromTriplets(m_Tpd.begin(), m_Tpd.end()); + m_Adu.setFromTriplets(m_Tdu.begin(), m_Tdu.end()); + m_Adp.setFromTriplets(m_Tdp.begin(), m_Tdp.end()); + m_Add.setFromTriplets(m_Tdd.begin(), m_Tdd.end()); + + m_factor = true; +} template -inline void MatrixPartitionedTyings::solve( - const xt::xtensor& b, - xt::xtensor& x) +inline void +MatrixPartitionedTyings::solve(const xt::xtensor& b, xt::xtensor& x) { - GOOSEFEM_ASSERT(b.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(x.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(b.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(x.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - this->factorize(); + this->factorize(); - Eigen::VectorXd B_u = this->asDofs_u(b); - Eigen::VectorXd B_d = this->asDofs_d(b); - Eigen::VectorXd X_p = this->asDofs_p(x); + Eigen::VectorXd B_u = this->asDofs_u(b); + Eigen::VectorXd B_d = this->asDofs_d(b); + Eigen::VectorXd X_p = this->asDofs_p(x); - B_u += m_Cud * B_d; + B_u += m_Cud * B_d; - Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_ACup * X_p)); - Eigen::VectorXd X_d = m_Cdu * X_u + m_Cdp * X_p; + Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_ACup * X_p)); + Eigen::VectorXd X_d = m_Cdu * X_u + m_Cdp * X_p; - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) { - for (size_t i = 0 ; i < m_ndim ; ++i) { - if (m_dofs(m,i) < m_nnu) - x(m,i) = X_u(m_dofs(m,i)); - else if (m_dofs(m,i) >= m_nni) - x(m,i) = X_d(m_dofs(m,i)-m_nni); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_dofs(m, i) < m_nnu) { + x(m, i) = X_u(m_dofs(m, i)); + } + else if (m_dofs(m, i) >= m_nni) { + x(m, i) = X_d(m_dofs(m, i) - m_nni); + } + } } - } } -// ------------------------------------------------------------------------------------------------- - template -inline void MatrixPartitionedTyings::solve( - const xt::xtensor& b, - xt::xtensor& x) +inline void +MatrixPartitionedTyings::solve(const xt::xtensor& b, xt::xtensor& x) { - GOOSEFEM_ASSERT(b.size() == m_ndof); - GOOSEFEM_ASSERT(x.size() == m_ndof); + GOOSEFEM_ASSERT(b.size() == m_ndof); + GOOSEFEM_ASSERT(x.size() == m_ndof); - this->factorize(); + this->factorize(); - Eigen::VectorXd B_u = this->asDofs_u(b); - Eigen::VectorXd B_d = this->asDofs_d(b); - Eigen::VectorXd X_p = this->asDofs_p(x); + Eigen::VectorXd B_u = this->asDofs_u(b); + Eigen::VectorXd B_d = this->asDofs_d(b); + Eigen::VectorXd X_p = this->asDofs_p(x); - Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_ACup * X_p)); - Eigen::VectorXd X_d = m_Cdu * X_u + m_Cdp * X_p; + Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_ACup * X_p)); + Eigen::VectorXd X_d = m_Cdu * X_u + m_Cdp * X_p; - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - x(m_iiu(d)) = X_u(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + x(m_iiu(d)) = X_u(d); + } - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnd ; ++d) - x(m_iid(d)) = X_d(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnd; ++d) { + x(m_iid(d)) = X_d(d); + } } -// ------------------------------------------------------------------------------------------------- - template inline void MatrixPartitionedTyings::solve_u( - const xt::xtensor& b_u, - const xt::xtensor& b_d, - const xt::xtensor& x_p, - xt::xtensor& x_u) + const xt::xtensor& b_u, + const xt::xtensor& b_d, + const xt::xtensor& x_p, + xt::xtensor& x_u) { - GOOSEFEM_ASSERT(b_u.size() == m_nnu); - GOOSEFEM_ASSERT(b_d.size() == m_nnd); - GOOSEFEM_ASSERT(x_p.size() == m_nnp); - GOOSEFEM_ASSERT(x_u.size() == m_nnu); + GOOSEFEM_ASSERT(b_u.size() == m_nnu); + GOOSEFEM_ASSERT(b_d.size() == m_nnd); + GOOSEFEM_ASSERT(x_p.size() == m_nnp); + GOOSEFEM_ASSERT(x_u.size() == m_nnu); - this->factorize(); + this->factorize(); - Eigen::VectorXd B_u(m_nnu,1); - Eigen::VectorXd B_d(m_nnd,1); - Eigen::VectorXd X_p(m_nnp,1); + Eigen::VectorXd B_u(m_nnu, 1); + Eigen::VectorXd B_d(m_nnd, 1); + Eigen::VectorXd X_p(m_nnp, 1); - std::copy(b_u.begin(), b_u.end(), B_u.data()); - std::copy(b_d.begin(), b_d.end(), B_d.data()); - std::copy(x_p.begin(), x_p.end(), X_p.data()); + std::copy(b_u.begin(), b_u.end(), B_u.data()); + std::copy(b_d.begin(), b_d.end(), B_d.data()); + std::copy(x_p.begin(), x_p.end(), X_p.data()); - Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_ACup * X_p)); + Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - m_ACup * X_p)); - std::copy(X_u.data(), X_u.data()+m_nnu, x_u.begin()); + std::copy(X_u.data(), X_u.data() + m_nnu, x_u.begin()); } -// ------------------------------------------------------------------------------------------------- - -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitionedTyings::Solve( - const xt::xtensor &b, - const xt::xtensor &x) + const xt::xtensor& b, const xt::xtensor& x) { - xt::xtensor out = x; - this->solve(b, out); - return out; + xt::xtensor out = x; + this->solve(b, out); + return out; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitionedTyings::Solve( - const xt::xtensor &b, - const xt::xtensor &x) + const xt::xtensor& b, const xt::xtensor& x) { - xt::xtensor out = x; - this->solve(b, out); - return out; + xt::xtensor out = x; + this->solve(b, out); + return out; } -// ------------------------------------------------------------------------------------------------- - template inline xt::xtensor MatrixPartitionedTyings::Solve_u( - const xt::xtensor &b_u, - const xt::xtensor &b_d, - const xt::xtensor &x_p) + const xt::xtensor& b_u, + const xt::xtensor& b_d, + const xt::xtensor& x_p) { - xt::xtensor x_u = xt::empty({m_nnu}); - this->solve_u(b_u, b_d, x_p, x_u); - return x_u; + xt::xtensor x_u = xt::empty({m_nnu}); + this->solve_u(b_u, b_d, x_p, x_u); + return x_u; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd MatrixPartitionedTyings::asDofs_u( - const xt::xtensor& dofval) const +inline Eigen::VectorXd +MatrixPartitionedTyings::asDofs_u(const xt::xtensor& dofval) const { - assert(dofval.size() == m_ndof); + assert(dofval.size() == m_ndof); - Eigen::VectorXd dofval_u(m_nnu,1); + Eigen::VectorXd dofval_u(m_nnu, 1); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - dofval_u(d) = dofval(m_iiu(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + dofval_u(d) = dofval(m_iiu(d)); + } - return dofval_u; + return dofval_u; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd MatrixPartitionedTyings::asDofs_u( - const xt::xtensor& nodevec) const +inline Eigen::VectorXd +MatrixPartitionedTyings::asDofs_u(const xt::xtensor& nodevec) const { - assert(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + assert(nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - Eigen::VectorXd dofval_u(m_nnu,1); + Eigen::VectorXd dofval_u(m_nnu, 1); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_dofs(m,i) < m_nnu) - dofval_u(m_dofs(m,i)) = nodevec(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_dofs(m, i) < m_nnu) { + dofval_u(m_dofs(m, i)) = nodevec(m, i); + } + } + } - return dofval_u; + return dofval_u; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd MatrixPartitionedTyings::asDofs_p( - const xt::xtensor& dofval) const +inline Eigen::VectorXd +MatrixPartitionedTyings::asDofs_p(const xt::xtensor& dofval) const { - assert(dofval.size() == m_ndof); + assert(dofval.size() == m_ndof); - Eigen::VectorXd dofval_p(m_nnp,1); + Eigen::VectorXd dofval_p(m_nnp, 1); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnp ; ++d) - dofval_p(d) = dofval(m_iip(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnp; ++d) { + dofval_p(d) = dofval(m_iip(d)); + } - return dofval_p; + return dofval_p; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd MatrixPartitionedTyings::asDofs_p( - const xt::xtensor& nodevec) const +inline Eigen::VectorXd +MatrixPartitionedTyings::asDofs_p(const xt::xtensor& nodevec) const { - assert(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + assert(nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - Eigen::VectorXd dofval_p(m_nnp,1); + Eigen::VectorXd dofval_p(m_nnp, 1); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_dofs(m,i) >= m_nnu && m_dofs(m,i) < m_nni) - dofval_p(m_dofs(m,i)-m_nnu) = nodevec(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_dofs(m, i) >= m_nnu && m_dofs(m, i) < m_nni) { + dofval_p(m_dofs(m, i) - m_nnu) = nodevec(m, i); + } + } + } - return dofval_p; + return dofval_p; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd MatrixPartitionedTyings::asDofs_d( - const xt::xtensor& dofval) const +inline Eigen::VectorXd +MatrixPartitionedTyings::asDofs_d(const xt::xtensor& dofval) const { - assert(dofval.size() == m_ndof); + assert(dofval.size() == m_ndof); - Eigen::VectorXd dofval_d(m_nnd,1); + Eigen::VectorXd dofval_d(m_nnd, 1); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnd ; ++d) - dofval_d(d) = dofval(m_iip(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnd; ++d) { + dofval_d(d) = dofval(m_iip(d)); + } - return dofval_d; + return dofval_d; } -// ------------------------------------------------------------------------------------------------- - template -inline Eigen::VectorXd MatrixPartitionedTyings::asDofs_d( - const xt::xtensor& nodevec) const +inline Eigen::VectorXd +MatrixPartitionedTyings::asDofs_d(const xt::xtensor& nodevec) const { - assert(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + assert(nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - Eigen::VectorXd dofval_d(m_nnd,1); + Eigen::VectorXd dofval_d(m_nnd, 1); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_dofs(m,i) >= m_nni) - dofval_d(m_dofs(m,i)-m_nni) = nodevec(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_dofs(m, i) >= m_nni) { + dofval_d(m_dofs(m, i) - m_nni) = nodevec(m, i); + } + } + } - return dofval_d; + return dofval_d; } -// ------------------------------------------------------------------------------------------------- - -} // namespace ... - -// ================================================================================================= +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/Mesh.hpp b/include/GooseFEM/Mesh.hpp index e672a5b..d2612e5 100644 --- a/include/GooseFEM/Mesh.hpp +++ b/include/GooseFEM/Mesh.hpp @@ -1,193 +1,156 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_MESH_HPP #define GOOSEFEM_MESH_HPP -// ------------------------------------------------------------------------------------------------- - #include "Mesh.h" -// ================================================================================================= - namespace GooseFEM { namespace Mesh { -// ------------------------------------------------------------------------------------------------- - inline Renumber::Renumber(const xt::xarray& dofs) { - size_t n = xt::amax(dofs)[0]+1; - size_t i = 0; + size_t n = xt::amax(dofs)[0] + 1; + size_t i = 0; - xt::xtensor unique = xt::unique(dofs); + xt::xtensor unique = xt::unique(dofs); - m_renum = xt::empty({n}); + m_renum = xt::empty({n}); - for (auto& j : unique) { - m_renum(j) = i; - ++i; - } + for (auto& j : unique) { + m_renum(j) = i; + ++i; + } } -// ------------------------------------------------------------------------------------------------- - -// apply renumbering, e.g. for a matrix: -// -// out(i,j) = renum(list(i,j)) - +// out(i,j) = renum(list(i,j)) template T Renumber::apply(const T& list) const { - T out = T::from_shape(list.shape()); + T out = T::from_shape(list.shape()); - auto jt = out.begin(); + auto jt = out.begin(); - for (auto it = list.begin(); it != list.end(); ++it, ++jt) - *jt = m_renum(*it); + for (auto it = list.begin(); it != list.end(); ++it, ++jt) { + *jt = m_renum(*it); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Renumber::get(const xt::xtensor& dofs) const { - return this->apply(dofs); + return this->apply(dofs); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Renumber::index() const { - return m_renum; + return m_renum; } -// ------------------------------------------------------------------------------------------------- - inline Reorder::Reorder(const std::initializer_list> args) { - size_t n = 0; - size_t i = 0; - - for (auto& arg : args) { - if (arg.size() == 0) continue; - n = std::max(n, xt::amax(arg)[0]+1); - } + size_t n = 0; + size_t i = 0; + + for (auto& arg : args) { + if (arg.size() == 0) { + continue; + } + n = std::max(n, xt::amax(arg)[0] + 1); + } - #ifdef GOOSEFEM_ENABLE_ASSERT +#ifdef GOOSEFEM_ENABLE_ASSERT for (auto& arg : args) - GOOSEFEM_ASSERT(xt::unique(arg) == xt::sort(arg)); - #endif + GOOSEFEM_ASSERT(xt::unique(arg) == xt::sort(arg)); +#endif - m_renum = xt::empty({n}); + m_renum = xt::empty({n}); - for (auto& arg : args) - { - for (auto& j : arg) - { - m_renum(j) = i; - ++i; + for (auto& arg : args) { + for (auto& j : arg) { + m_renum(j) = i; + ++i; + } } - } } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Reorder::get(const xt::xtensor& dofs) const { - return this->apply(dofs); + return this->apply(dofs); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Reorder::index() const { - return m_renum; + return m_renum; } -// ------------------------------------------------------------------------------------------------- - // apply renumbering, e.g. for a matrix: // // out(i,j) = renum(list(i,j)) template T Reorder::apply(const T& list) const { - T out = T::from_shape(list.shape()); + T out = T::from_shape(list.shape()); - auto jt = out.begin(); + auto jt = out.begin(); - for (auto it = list.begin(); it != list.end(); ++it, ++jt) - *jt = m_renum(*it); + for (auto it = list.begin(); it != list.end(); ++it, ++jt) { + *jt = m_renum(*it); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor renumber(const xt::xtensor &dofs) +inline xt::xtensor renumber(const xt::xtensor& dofs) { - return Renumber(dofs).get(dofs); + return Renumber(dofs).get(dofs); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor dofs(size_t nnode, size_t ndim) { - return xt::reshape_view(xt::arange(nnode*ndim),{nnode,ndim}); + return xt::reshape_view(xt::arange(nnode * ndim), {nnode, ndim}); } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor coordination(const xt::xtensor &conn) +inline xt::xtensor coordination(const xt::xtensor& conn) { - // get number of nodes - size_t nnode = xt::amax(conn)[0] + 1; + size_t nnode = xt::amax(conn)[0] + 1; - // number of elements connected to each node - // - allocate - xt::xtensor N = xt::zeros({nnode}); - // - fill from connectivity - for (auto it = conn.begin(); it != conn.end(); ++it) N(*it) += 1; + xt::xtensor N = xt::zeros({nnode}); - return N; -} + for (auto it = conn.begin(); it != conn.end(); ++it) { + N(*it) += 1; + } -// ------------------------------------------------------------------------------------------------- + return N; +} -inline std::vector> elem2node(const xt::xtensor &conn) +inline std::vector> elem2node(const xt::xtensor& conn) { - // get coordination per node - auto N = coordination(conn); - - // get number of nodes - auto nnode = N.size(); - - // allocate - std::vector> out; - // reserve outer size - out.resize(nnode); - // reserve inner sizes - for (size_t i = 0; i < nnode; ++i ) - out[i].reserve(N(i)); - - // fill - for (size_t e = 0; e < conn.shape(0); ++e) - for (size_t m = 0; m < conn.shape(1); ++m) - out[conn(e,m)].push_back(e); - - return out; -} + auto N = coordination(conn); + auto nnode = N.size(); -// ------------------------------------------------------------------------------------------------- + std::vector> out; + out.resize(nnode); + for (size_t i = 0; i < nnode; ++i) { + out[i].reserve(N(i)); + } -}} // namespace ... + for (size_t e = 0; e < conn.shape(0); ++e) { + for (size_t m = 0; m < conn.shape(1); ++m) { + out[conn(e, m)].push_back(e); + } + } + + return out; +} -// ================================================================================================= +} // namespace Mesh +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/MeshHex8.hpp b/include/GooseFEM/MeshHex8.hpp index 9401815..7d59c85 100644 --- a/include/GooseFEM/MeshHex8.hpp +++ b/include/GooseFEM/MeshHex8.hpp @@ -1,2639 +1,3019 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_MESHHEX8_HPP #define GOOSEFEM_MESHHEX8_HPP -// ------------------------------------------------------------------------------------------------- - #include "MeshHex8.h" -// ================================================================================================= - namespace GooseFEM { namespace Mesh { namespace Hex8 { -// ------------------------------------------------------------------------------------------------- - -inline Regular::Regular(size_t nelx, size_t nely, size_t nelz, double h): -m_h(h), m_nelx(nelx), m_nely(nely), m_nelz(nelz) +inline Regular::Regular(size_t nelx, size_t nely, size_t nelz, double h) + : m_h(h), m_nelx(nelx), m_nely(nely), m_nelz(nelz) { - GOOSEFEM_ASSERT(m_nelx >= 1ul); - GOOSEFEM_ASSERT(m_nely >= 1ul); - GOOSEFEM_ASSERT(m_nelz >= 1ul); + GOOSEFEM_ASSERT(m_nelx >= 1ul); + GOOSEFEM_ASSERT(m_nely >= 1ul); + GOOSEFEM_ASSERT(m_nelz >= 1ul); - m_nnode = (m_nelx+1) * (m_nely+1) * (m_nelz+1); - m_nelem = m_nelx * m_nely * m_nelz ; + m_nnode = (m_nelx + 1) * (m_nely + 1) * (m_nelz + 1); + m_nelem = m_nelx * m_nely * m_nelz; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline ElementType Regular::getElementType() const { - return ElementType::Hex8; + return ElementType::Hex8; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::coor() const { - xt::xtensor out = xt::empty({m_nnode, m_ndim}); - - xt::xtensor x = xt::linspace(0.0, m_h*static_cast(m_nelx), m_nelx+1); - xt::xtensor y = xt::linspace(0.0, m_h*static_cast(m_nely), m_nely+1); - xt::xtensor z = xt::linspace(0.0, m_h*static_cast(m_nelz), m_nelz+1); - - size_t inode = 0; - - for ( size_t iz = 0 ; iz < m_nelz+1 ; ++iz ) { - for ( size_t iy = 0 ; iy < m_nely+1 ; ++iy ) { - for ( size_t ix = 0 ; ix < m_nelx+1 ; ++ix ) { - out(inode,0) = x(ix); - out(inode,1) = y(iy); - out(inode,2) = z(iz); - ++inode; - } + xt::xtensor out = xt::empty({m_nnode, m_ndim}); + + xt::xtensor x = + xt::linspace(0.0, m_h * static_cast(m_nelx), m_nelx + 1); + xt::xtensor y = + xt::linspace(0.0, m_h * static_cast(m_nely), m_nely + 1); + xt::xtensor z = + xt::linspace(0.0, m_h * static_cast(m_nelz), m_nelz + 1); + + size_t inode = 0; + + for (size_t iz = 0; iz < m_nelz + 1; ++iz) { + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(inode, 0) = x(ix); + out(inode, 1) = y(iy); + out(inode, 2) = z(iz); + ++inode; + } + } } - } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::conn() const { - xt::xtensor out = xt::empty({m_nelem,m_nne}); - - size_t ielem = 0; - - for ( size_t iz = 0 ; iz < m_nelz ; ++iz ) { - for ( size_t iy = 0 ; iy < m_nely ; ++iy ) { - for ( size_t ix = 0 ; ix < m_nelx ; ++ix ) { - out(ielem,0) = (iy )*(m_nelx+1) + (ix ) + (iz )*(m_nely+1)*(m_nelx+1); - out(ielem,1) = (iy )*(m_nelx+1) + (ix+1) + (iz )*(m_nely+1)*(m_nelx+1); - out(ielem,3) = (iy+1)*(m_nelx+1) + (ix ) + (iz )*(m_nely+1)*(m_nelx+1); - out(ielem,2) = (iy+1)*(m_nelx+1) + (ix+1) + (iz )*(m_nely+1)*(m_nelx+1); - out(ielem,4) = (iy )*(m_nelx+1) + (ix ) + (iz+1)*(m_nely+1)*(m_nelx+1); - out(ielem,5) = (iy )*(m_nelx+1) + (ix+1) + (iz+1)*(m_nely+1)*(m_nelx+1); - out(ielem,7) = (iy+1)*(m_nelx+1) + (ix ) + (iz+1)*(m_nely+1)*(m_nelx+1); - out(ielem,6) = (iy+1)*(m_nelx+1) + (ix+1) + (iz+1)*(m_nely+1)*(m_nelx+1); - ++ielem; - } + xt::xtensor out = xt::empty({m_nelem, m_nne}); + + size_t ielem = 0; + + for (size_t iz = 0; iz < m_nelz; ++iz) { + for (size_t iy = 0; iy < m_nely; ++iy) { + for (size_t ix = 0; ix < m_nelx; ++ix) { + out(ielem, 0) = + iy * (m_nelx + 1) + ix + iz * (m_nely + 1) * (m_nelx + 1); + out(ielem, 1) = + iy * (m_nelx + 1) + (ix + 1) + iz * (m_nely + 1) * (m_nelx + 1); + out(ielem, 3) = + (iy + 1) * (m_nelx + 1) + ix + iz * (m_nely + 1) * (m_nelx + 1); + out(ielem, 2) = + (iy + 1) * (m_nelx + 1) + (ix + 1) + iz * (m_nely + 1) * (m_nelx + 1); + out(ielem, 4) = + iy * (m_nelx + 1) + ix + (iz + 1) * (m_nely + 1) * (m_nelx + 1); + out(ielem, 5) = + (iy) * (m_nelx + 1) + (ix + 1) + (iz + 1) * (m_nely + 1) * (m_nelx + 1); + out(ielem, 7) = + (iy + 1) * (m_nelx + 1) + ix + (iz + 1) * (m_nely + 1) * (m_nelx + 1); + out(ielem, 6) = + (iy + 1) * (m_nelx + 1) + (ix + 1) + (iz + 1) * (m_nely + 1) * (m_nelx + 1); + ++ielem; + } + } } - } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesFront() const { - xt::xtensor out = xt::empty({(m_nelx+1)*(m_nely+1)}); + xt::xtensor out = xt::empty({(m_nelx + 1) * (m_nely + 1)}); - for ( size_t iy = 0 ; iy < m_nely+1 ; ++iy ) - for ( size_t ix = 0 ; ix < m_nelx+1 ; ++ix ) - out(iy*(m_nelx+1)+ix) = iy*(m_nelx+1) + ix; + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(iy * (m_nelx + 1) + ix) = iy * (m_nelx + 1) + ix; + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBack() const { - xt::xtensor out = xt::empty({(m_nelx+1)*(m_nely+1)}); + xt::xtensor out = xt::empty({(m_nelx + 1) * (m_nely + 1)}); - for ( size_t iy = 0 ; iy < m_nely+1 ; ++iy ) - for ( size_t ix = 0 ; ix < m_nelx+1 ; ++ix ) - out(iy*(m_nelx+1)+ix) = iy*(m_nelx+1) + ix + m_nelz*(m_nely+1)*(m_nelx+1); + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(iy * (m_nelx + 1) + ix) = + iy * (m_nelx + 1) + ix + m_nelz * (m_nely + 1) * (m_nelx + 1); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesLeft() const { - xt::xtensor out = xt::empty({(m_nely+1)*(m_nelz+1)}); + xt::xtensor out = xt::empty({(m_nely + 1) * (m_nelz + 1)}); - for ( size_t iz = 0 ; iz < m_nelz+1 ; ++iz ) - for ( size_t iy = 0 ; iy < m_nely+1 ; ++iy ) - out(iz*(m_nely+1)+iy) = iy*(m_nelx+1) + iz*(m_nelx+1)*(m_nely+1); + for (size_t iz = 0; iz < m_nelz + 1; ++iz) { + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + out(iz * (m_nely + 1) + iy) = iy * (m_nelx + 1) + iz * (m_nelx + 1) * (m_nely + 1); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesRight() const { - xt::xtensor out = xt::empty({(m_nely+1)*(m_nelz+1)}); + xt::xtensor out = xt::empty({(m_nely + 1) * (m_nelz + 1)}); - for ( size_t iz = 0 ; iz < m_nelz+1 ; ++iz ) - for ( size_t iy = 0 ; iy < m_nely+1 ; ++iy ) - out(iz*(m_nely+1)+iy) = iy*(m_nelx+1) + iz*(m_nelx+1)*(m_nely+1) + m_nelx; + for (size_t iz = 0; iz < m_nelz + 1; ++iz) { + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + out(iz * (m_nely + 1) + iy) = + iy * (m_nelx + 1) + iz * (m_nelx + 1) * (m_nely + 1) + m_nelx; + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBottom() const { - xt::xtensor out = xt::empty({(m_nelx+1)*(m_nelz+1)}); + xt::xtensor out = xt::empty({(m_nelx + 1) * (m_nelz + 1)}); - for ( size_t iz = 0 ; iz < m_nelz+1 ; ++iz ) - for ( size_t ix = 0 ; ix < m_nelx+1 ; ++ix ) - out(iz*(m_nelx+1)+ix) = ix + iz*(m_nelx+1)*(m_nely+1); + for (size_t iz = 0; iz < m_nelz + 1; ++iz) { + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(iz * (m_nelx + 1) + ix) = ix + iz * (m_nelx + 1) * (m_nely + 1); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesTop() const { - xt::xtensor out = xt::empty({(m_nelx+1)*(m_nelz+1)}); + xt::xtensor out = xt::empty({(m_nelx + 1) * (m_nelz + 1)}); - for ( size_t iz = 0 ; iz < m_nelz+1 ; ++iz ) - for ( size_t ix = 0 ; ix < m_nelx+1 ; ++ix ) - out(iz*(m_nelx+1)+ix) = ix + m_nely*(m_nelx+1) + iz*(m_nelx+1)*(m_nely+1); + for (size_t iz = 0; iz < m_nelz + 1; ++iz) { + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(iz * (m_nelx + 1) + ix) = + ix + m_nely * (m_nelx + 1) + iz * (m_nelx + 1) * (m_nely + 1); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesFrontFace() const { - xt::xtensor out = xt::empty({(m_nelx-1)*(m_nely-1)}); + xt::xtensor out = xt::empty({(m_nelx - 1) * (m_nely - 1)}); - for ( size_t iy = 1 ; iy < m_nely ; ++iy ) - for ( size_t ix = 1 ; ix < m_nelx ; ++ix ) - out((iy-1)*(m_nelx-1)+(ix-1)) = iy*(m_nelx+1) + ix; + for (size_t iy = 1; iy < m_nely; ++iy) { + for (size_t ix = 1; ix < m_nelx; ++ix) { + out((iy - 1) * (m_nelx - 1) + (ix - 1)) = iy * (m_nelx + 1) + ix; + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBackFace() const { - xt::xtensor out = xt::empty({(m_nelx-1)*(m_nely-1)}); + xt::xtensor out = xt::empty({(m_nelx - 1) * (m_nely - 1)}); - for ( size_t iy = 1 ; iy < m_nely ; ++iy ) { - for ( size_t ix = 1 ; ix < m_nelx ; ++ix ) { - out((iy-1)*(m_nelx-1)+(ix-1)) = iy*(m_nelx+1) + ix + m_nelz*(m_nely+1)*(m_nelx+1); + for (size_t iy = 1; iy < m_nely; ++iy) { + for (size_t ix = 1; ix < m_nelx; ++ix) { + out((iy - 1) * (m_nelx - 1) + (ix - 1)) = + iy * (m_nelx + 1) + ix + m_nelz * (m_nely + 1) * (m_nelx + 1); + } } - } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesLeftFace() const { - xt::xtensor out = xt::empty({(m_nely-1)*(m_nelz-1)}); + xt::xtensor out = xt::empty({(m_nely - 1) * (m_nelz - 1)}); - for ( size_t iz = 1 ; iz < m_nelz ; ++iz ) - for ( size_t iy = 1 ; iy < m_nely ; ++iy ) - out((iz-1)*(m_nely-1)+(iy-1)) = iy*(m_nelx+1) + iz*(m_nelx+1)*(m_nely+1); + for (size_t iz = 1; iz < m_nelz; ++iz) { + for (size_t iy = 1; iy < m_nely; ++iy) { + out((iz - 1) * (m_nely - 1) + (iy - 1)) = + iy * (m_nelx + 1) + iz * (m_nelx + 1) * (m_nely + 1); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesRightFace() const { - xt::xtensor out = xt::empty({(m_nely-1)*(m_nelz-1)}); + xt::xtensor out = xt::empty({(m_nely - 1) * (m_nelz - 1)}); - for ( size_t iz = 1 ; iz < m_nelz ; ++iz ) - for ( size_t iy = 1 ; iy < m_nely ; ++iy ) - out((iz-1)*(m_nely-1)+(iy-1)) = iy*(m_nelx+1) + iz*(m_nelx+1)*(m_nely+1) + m_nelx; + for (size_t iz = 1; iz < m_nelz; ++iz) { + for (size_t iy = 1; iy < m_nely; ++iy) { + out((iz - 1) * (m_nely - 1) + (iy - 1)) = + iy * (m_nelx + 1) + iz * (m_nelx + 1) * (m_nely + 1) + m_nelx; + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBottomFace() const { - xt::xtensor out = xt::empty({(m_nelx-1)*(m_nelz-1)}); + xt::xtensor out = xt::empty({(m_nelx - 1) * (m_nelz - 1)}); - for ( size_t iz = 1 ; iz < m_nelz ; ++iz ) - for ( size_t ix = 1 ; ix < m_nelx ; ++ix ) - out((iz-1)*(m_nelx-1)+(ix-1)) = ix + iz*(m_nelx+1)*(m_nely+1); + for (size_t iz = 1; iz < m_nelz; ++iz) { + for (size_t ix = 1; ix < m_nelx; ++ix) { + out((iz - 1) * (m_nelx - 1) + (ix - 1)) = ix + iz * (m_nelx + 1) * (m_nely + 1); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesTopFace() const { - xt::xtensor out = xt::empty({(m_nelx-1)*(m_nelz-1)}); + xt::xtensor out = xt::empty({(m_nelx - 1) * (m_nelz - 1)}); - for ( size_t iz = 1 ; iz < m_nelz ; ++iz ) - for ( size_t ix = 1 ; ix < m_nelx ; ++ix ) - out((iz-1)*(m_nelx-1)+(ix-1)) = ix + m_nely*(m_nelx+1) + iz*(m_nelx+1)*(m_nely+1); + for (size_t iz = 1; iz < m_nelz; ++iz) { + for (size_t ix = 1; ix < m_nelx; ++ix) { + out((iz - 1) * (m_nelx - 1) + (ix - 1)) = + ix + m_nely * (m_nelx + 1) + iz * (m_nelx + 1) * (m_nely + 1); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesFrontBottomEdge() const { - xt::xtensor out = xt::empty({m_nelx+1}); + xt::xtensor out = xt::empty({m_nelx + 1}); - for ( size_t ix = 0 ; ix < m_nelx+1 ; ++ix ) - out(ix) = ix; + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(ix) = ix; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesFrontTopEdge() const { - xt::xtensor out = xt::empty({m_nelx+1}); + xt::xtensor out = xt::empty({m_nelx + 1}); - for ( size_t ix = 0 ; ix < m_nelx+1 ; ++ix ) - out(ix) = ix + m_nely*(m_nelx+1); + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(ix) = ix + m_nely * (m_nelx + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesFrontLeftEdge() const { - xt::xtensor out = xt::empty({m_nely+1}); + xt::xtensor out = xt::empty({m_nely + 1}); - for ( size_t iy = 0 ; iy < m_nely+1 ; ++iy ) - out(iy) = iy*(m_nelx+1); + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + out(iy) = iy * (m_nelx + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesFrontRightEdge() const { - xt::xtensor out = xt::empty({m_nely+1}); + xt::xtensor out = xt::empty({m_nely + 1}); - for ( size_t iy = 0 ; iy < m_nely+1 ; ++iy ) - out(iy) = iy*(m_nelx+1) + m_nelx; + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + out(iy) = iy * (m_nelx + 1) + m_nelx; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBackBottomEdge() const { - xt::xtensor out = xt::empty({m_nelx+1}); + xt::xtensor out = xt::empty({m_nelx + 1}); - for ( size_t ix = 0 ; ix < m_nelx+1 ; ++ix ) - out(ix) = ix + m_nelz*(m_nely+1)*(m_nelx+1); + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(ix) = ix + m_nelz * (m_nely + 1) * (m_nelx + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBackTopEdge() const { - xt::xtensor out = xt::empty({m_nelx+1}); + xt::xtensor out = xt::empty({m_nelx + 1}); - for ( size_t ix = 0 ; ix < m_nelx+1 ; ++ix ) - out(ix) = m_nely*(m_nelx+1) + ix + m_nelz*(m_nely+1)*(m_nelx+1); + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(ix) = m_nely * (m_nelx + 1) + ix + m_nelz * (m_nely + 1) * (m_nelx + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBackLeftEdge() const { - xt::xtensor out = xt::empty({m_nely+1}); + xt::xtensor out = xt::empty({m_nely + 1}); - for ( size_t iy = 0 ; iy < m_nely+1 ; ++iy ) - out(iy) = iy*(m_nelx+1) + m_nelz*(m_nelx+1)*(m_nely+1); + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + out(iy) = iy * (m_nelx + 1) + m_nelz * (m_nelx + 1) * (m_nely + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBackRightEdge() const { - xt::xtensor out = xt::empty({m_nely+1}); + xt::xtensor out = xt::empty({m_nely + 1}); - for ( size_t iy = 0 ; iy < m_nely+1 ; ++iy ) - out(iy) = iy*(m_nelx+1) + m_nelz*(m_nelx+1)*(m_nely+1) + m_nelx; + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + out(iy) = iy * (m_nelx + 1) + m_nelz * (m_nelx + 1) * (m_nely + 1) + m_nelx; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBottomLeftEdge() const { - xt::xtensor out = xt::empty({m_nelz+1}); + xt::xtensor out = xt::empty({m_nelz + 1}); - for ( size_t iz = 0 ; iz < m_nelz+1 ; ++iz ) - out(iz) = iz*(m_nelx+1)*(m_nely+1); + for (size_t iz = 0; iz < m_nelz + 1; ++iz) { + out(iz) = iz * (m_nelx + 1) * (m_nely + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBottomRightEdge() const { - xt::xtensor out = xt::empty({m_nelz+1}); + xt::xtensor out = xt::empty({m_nelz + 1}); - for ( size_t iz = 0 ; iz < m_nelz+1 ; ++iz ) - out(iz) = iz*(m_nelx+1)*(m_nely+1) + m_nelx; + for (size_t iz = 0; iz < m_nelz + 1; ++iz) { + out(iz) = iz * (m_nelx + 1) * (m_nely + 1) + m_nelx; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesTopLeftEdge() const { - xt::xtensor out = xt::empty({m_nelz+1}); + xt::xtensor out = xt::empty({m_nelz + 1}); - for ( size_t iz = 0 ; iz < m_nelz+1 ; ++iz ) - out(iz) = m_nely*(m_nelx+1) + iz*(m_nelx+1)*(m_nely+1); + for (size_t iz = 0; iz < m_nelz + 1; ++iz) { + out(iz) = m_nely * (m_nelx + 1) + iz * (m_nelx + 1) * (m_nely + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesTopRightEdge() const { - xt::xtensor out = xt::empty({m_nelz+1}); + xt::xtensor out = xt::empty({m_nelz + 1}); - for ( size_t iz = 0 ; iz < m_nelz+1 ; ++iz ) - out(iz) = m_nely*(m_nelx+1) + iz*(m_nelx+1)*(m_nely+1) + m_nelx; + for (size_t iz = 0; iz < m_nelz + 1; ++iz) { + out(iz) = m_nely * (m_nelx + 1) + iz * (m_nelx + 1) * (m_nely + 1) + m_nelx; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Regular::nodesBottomFrontEdge() const { return nodesFrontBottomEdge(); } -inline xt::xtensor Regular::nodesBottomBackEdge() const { return nodesBackBottomEdge(); } -inline xt::xtensor Regular::nodesTopFrontEdge() const { return nodesFrontTopEdge(); } -inline xt::xtensor Regular::nodesTopBackEdge() const { return nodesBackTopEdge(); } -inline xt::xtensor Regular::nodesLeftBottomEdge() const { return nodesBottomLeftEdge(); } -inline xt::xtensor Regular::nodesLeftFrontEdge() const { return nodesFrontLeftEdge(); } -inline xt::xtensor Regular::nodesLeftBackEdge() const { return nodesBackLeftEdge(); } -inline xt::xtensor Regular::nodesLeftTopEdge() const { return nodesTopLeftEdge(); } -inline xt::xtensor Regular::nodesRightBottomEdge() const { return nodesBottomRightEdge(); } -inline xt::xtensor Regular::nodesRightTopEdge() const { return nodesTopRightEdge(); } -inline xt::xtensor Regular::nodesRightFrontEdge() const { return nodesFrontRightEdge(); } -inline xt::xtensor Regular::nodesRightBackEdge() const { return nodesBackRightEdge(); } - -// ------------------- node-numbers along the front-bottom edge, without corners ------------------- +inline xt::xtensor Regular::nodesBottomFrontEdge() const +{ + return nodesFrontBottomEdge(); +} +inline xt::xtensor Regular::nodesBottomBackEdge() const +{ + return nodesBackBottomEdge(); +} +inline xt::xtensor Regular::nodesTopFrontEdge() const +{ + return nodesFrontTopEdge(); +} +inline xt::xtensor Regular::nodesTopBackEdge() const +{ + return nodesBackTopEdge(); +} +inline xt::xtensor Regular::nodesLeftBottomEdge() const +{ + return nodesBottomLeftEdge(); +} +inline xt::xtensor Regular::nodesLeftFrontEdge() const +{ + return nodesFrontLeftEdge(); +} +inline xt::xtensor Regular::nodesLeftBackEdge() const +{ + return nodesBackLeftEdge(); +} +inline xt::xtensor Regular::nodesLeftTopEdge() const +{ + return nodesTopLeftEdge(); +} +inline xt::xtensor Regular::nodesRightBottomEdge() const +{ + return nodesBottomRightEdge(); +} +inline xt::xtensor Regular::nodesRightTopEdge() const +{ + return nodesTopRightEdge(); +} +inline xt::xtensor Regular::nodesRightFrontEdge() const +{ + return nodesFrontRightEdge(); +} +inline xt::xtensor Regular::nodesRightBackEdge() const +{ + return nodesBackRightEdge(); +} inline xt::xtensor Regular::nodesFrontBottomOpenEdge() const { - xt::xtensor out = xt::empty({m_nelx-1}); + xt::xtensor out = xt::empty({m_nelx - 1}); - for ( size_t ix = 1 ; ix < m_nelx ; ++ix ) - out(ix-1) = ix; + for (size_t ix = 1; ix < m_nelx; ++ix) { + out(ix - 1) = ix; + } - return out; + return out; } -// -------------------- node-numbers along the front-top edge, without corners --------------------- - inline xt::xtensor Regular::nodesFrontTopOpenEdge() const { - xt::xtensor out = xt::empty({m_nelx-1}); + xt::xtensor out = xt::empty({m_nelx - 1}); - for ( size_t ix = 1 ; ix < m_nelx ; ++ix ) - out(ix-1) = ix + m_nely*(m_nelx+1); + for (size_t ix = 1; ix < m_nelx; ++ix) { + out(ix - 1) = ix + m_nely * (m_nelx + 1); + } - return out; + return out; } -// -------------------- node-numbers along the front-left edge, without corners -------------------- - inline xt::xtensor Regular::nodesFrontLeftOpenEdge() const { - xt::xtensor out = xt::empty({m_nely-1}); + xt::xtensor out = xt::empty({m_nely - 1}); - for ( size_t iy = 1 ; iy < m_nely ; ++iy ) - out(iy-1) = iy*(m_nelx+1); + for (size_t iy = 1; iy < m_nely; ++iy) { + out(iy - 1) = iy * (m_nelx + 1); + } - return out; + return out; } -// ------------------- node-numbers along the front-right edge, without corners -------------------- - inline xt::xtensor Regular::nodesFrontRightOpenEdge() const { - xt::xtensor out = xt::empty({m_nely-1}); + xt::xtensor out = xt::empty({m_nely - 1}); - for ( size_t iy = 1 ; iy < m_nely ; ++iy ) - out(iy-1) = iy*(m_nelx+1) + m_nelx; + for (size_t iy = 1; iy < m_nely; ++iy) { + out(iy - 1) = iy * (m_nelx + 1) + m_nelx; + } - return out; + return out; } -// ------------------- node-numbers along the back-bottom edge, without corners -------------------- - inline xt::xtensor Regular::nodesBackBottomOpenEdge() const { - xt::xtensor out = xt::empty({m_nelx-1}); + xt::xtensor out = xt::empty({m_nelx - 1}); - for ( size_t ix = 1 ; ix < m_nelx ; ++ix ) - out(ix-1) = ix + m_nelz*(m_nely+1)*(m_nelx+1); + for (size_t ix = 1; ix < m_nelx; ++ix) { + out(ix - 1) = ix + m_nelz * (m_nely + 1) * (m_nelx + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBackTopOpenEdge() const { - xt::xtensor out = xt::empty({m_nelx-1}); + xt::xtensor out = xt::empty({m_nelx - 1}); - for ( size_t ix = 1 ; ix < m_nelx ; ++ix ) - out(ix-1) = m_nely*(m_nelx+1) + ix + m_nelz*(m_nely+1)*(m_nelx+1); + for (size_t ix = 1; ix < m_nelx; ++ix) { + out(ix - 1) = m_nely * (m_nelx + 1) + ix + m_nelz * (m_nely + 1) * (m_nelx + 1); + } - return out; + return out; } -// -------------------- node-numbers along the back-left edge, without corners --------------------- - inline xt::xtensor Regular::nodesBackLeftOpenEdge() const { - xt::xtensor out = xt::empty({m_nely-1}); + xt::xtensor out = xt::empty({m_nely - 1}); - for ( size_t iy = 1 ; iy < m_nely ; ++iy ) - out(iy-1) = iy*(m_nelx+1) + m_nelz*(m_nelx+1)*(m_nely+1); + for (size_t iy = 1; iy < m_nely; ++iy) { + out(iy - 1) = iy * (m_nelx + 1) + m_nelz * (m_nelx + 1) * (m_nely + 1); + } - return out; + return out; } -// -------------------- node-numbers along the back-right edge, without corners -------------------- - inline xt::xtensor Regular::nodesBackRightOpenEdge() const { - xt::xtensor out = xt::empty({m_nely-1}); + xt::xtensor out = xt::empty({m_nely - 1}); - for ( size_t iy = 1 ; iy < m_nely ; ++iy ) - out(iy-1) = iy*(m_nelx+1) + m_nelz*(m_nelx+1)*(m_nely+1) + m_nelx; + for (size_t iy = 1; iy < m_nely; ++iy) { + out(iy - 1) = iy * (m_nelx + 1) + m_nelz * (m_nelx + 1) * (m_nely + 1) + m_nelx; + } - return out; + return out; } -// ------------------- node-numbers along the bottom-left edge, without corners -------------------- - inline xt::xtensor Regular::nodesBottomLeftOpenEdge() const { - xt::xtensor out = xt::empty({m_nelz-1}); + xt::xtensor out = xt::empty({m_nelz - 1}); - for ( size_t iz = 1 ; iz < m_nelz ; ++iz ) - out(iz-1) = iz*(m_nelx+1)*(m_nely+1); + for (size_t iz = 1; iz < m_nelz; ++iz) { + out(iz - 1) = iz * (m_nelx + 1) * (m_nely + 1); + } - return out; + return out; } -// ------------------- node-numbers along the bottom-right edge, without corners ------------------- - inline xt::xtensor Regular::nodesBottomRightOpenEdge() const { - xt::xtensor out = xt::empty({m_nelz-1}); + xt::xtensor out = xt::empty({m_nelz - 1}); - for ( size_t iz = 1 ; iz < m_nelz ; ++iz ) - out(iz-1) = iz*(m_nelx+1)*(m_nely+1) + m_nelx; + for (size_t iz = 1; iz < m_nelz; ++iz) { + out(iz - 1) = iz * (m_nelx + 1) * (m_nely + 1) + m_nelx; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesTopLeftOpenEdge() const { - xt::xtensor out = xt::empty({m_nelz-1}); + xt::xtensor out = xt::empty({m_nelz - 1}); - for ( size_t iz = 1 ; iz < m_nelz ; ++iz ) - out(iz-1) = m_nely*(m_nelx+1) + iz*(m_nelx+1)*(m_nely+1); + for (size_t iz = 1; iz < m_nelz; ++iz) { + out(iz - 1) = m_nely * (m_nelx + 1) + iz * (m_nelx + 1) * (m_nely + 1); + } - return out; + return out; } -// -------------------- node-numbers along the top-right edge, without corners --------------------- - inline xt::xtensor Regular::nodesTopRightOpenEdge() const { - xt::xtensor out = xt::empty({m_nelz-1}); + xt::xtensor out = xt::empty({m_nelz - 1}); - for ( size_t iz = 1 ; iz < m_nelz ; ++iz ) - out(iz-1) = m_nely*(m_nelx+1) + iz*(m_nelx+1)*(m_nely+1) + m_nelx; + for (size_t iz = 1; iz < m_nelz; ++iz) { + out(iz - 1) = m_nely * (m_nelx + 1) + iz * (m_nelx + 1) * (m_nely + 1) + m_nelx; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Regular::nodesBottomFrontOpenEdge() const { return nodesFrontBottomOpenEdge(); } -inline xt::xtensor Regular::nodesBottomBackOpenEdge() const { return nodesBackBottomOpenEdge(); } -inline xt::xtensor Regular::nodesTopFrontOpenEdge() const { return nodesFrontTopOpenEdge(); } -inline xt::xtensor Regular::nodesTopBackOpenEdge() const { return nodesBackTopOpenEdge(); } -inline xt::xtensor Regular::nodesLeftBottomOpenEdge() const { return nodesBottomLeftOpenEdge(); } -inline xt::xtensor Regular::nodesLeftFrontOpenEdge() const { return nodesFrontLeftOpenEdge(); } -inline xt::xtensor Regular::nodesLeftBackOpenEdge() const { return nodesBackLeftOpenEdge(); } -inline xt::xtensor Regular::nodesLeftTopOpenEdge() const { return nodesTopLeftOpenEdge(); } -inline xt::xtensor Regular::nodesRightBottomOpenEdge() const { return nodesBottomRightOpenEdge(); } -inline xt::xtensor Regular::nodesRightTopOpenEdge() const { return nodesTopRightOpenEdge(); } -inline xt::xtensor Regular::nodesRightFrontOpenEdge() const { return nodesFrontRightOpenEdge(); } -inline xt::xtensor Regular::nodesRightBackOpenEdge() const { return nodesBackRightOpenEdge(); } - -// ------------------------------------------------------------------------------------------------- +inline xt::xtensor Regular::nodesBottomFrontOpenEdge() const +{ + return nodesFrontBottomOpenEdge(); +} +inline xt::xtensor Regular::nodesBottomBackOpenEdge() const +{ + return nodesBackBottomOpenEdge(); +} +inline xt::xtensor Regular::nodesTopFrontOpenEdge() const +{ + return nodesFrontTopOpenEdge(); +} +inline xt::xtensor Regular::nodesTopBackOpenEdge() const +{ + return nodesBackTopOpenEdge(); +} +inline xt::xtensor Regular::nodesLeftBottomOpenEdge() const +{ + return nodesBottomLeftOpenEdge(); +} +inline xt::xtensor Regular::nodesLeftFrontOpenEdge() const +{ + return nodesFrontLeftOpenEdge(); +} +inline xt::xtensor Regular::nodesLeftBackOpenEdge() const +{ + return nodesBackLeftOpenEdge(); +} +inline xt::xtensor Regular::nodesLeftTopOpenEdge() const +{ + return nodesTopLeftOpenEdge(); +} +inline xt::xtensor Regular::nodesRightBottomOpenEdge() const +{ + return nodesBottomRightOpenEdge(); +} +inline xt::xtensor Regular::nodesRightTopOpenEdge() const +{ + return nodesTopRightOpenEdge(); +} +inline xt::xtensor Regular::nodesRightFrontOpenEdge() const +{ + return nodesFrontRightOpenEdge(); +} +inline xt::xtensor Regular::nodesRightBackOpenEdge() const +{ + return nodesBackRightOpenEdge(); +} inline size_t Regular::nodesFrontBottomLeftCorner() const { - return 0; + return 0; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesFrontBottomRightCorner() const { - return m_nelx; + return m_nelx; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesFrontTopLeftCorner() const { - return m_nely*(m_nelx+1); + return m_nely * (m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesFrontTopRightCorner() const { - return m_nely*(m_nelx+1) + m_nelx; + return m_nely * (m_nelx + 1) + m_nelx; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesBackBottomLeftCorner() const { - return m_nelz*(m_nely+1)*(m_nelx+1); + return m_nelz * (m_nely + 1) * (m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesBackBottomRightCorner() const { - return m_nelx + m_nelz*(m_nely+1)*(m_nelx+1); + return m_nelx + m_nelz * (m_nely + 1) * (m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesBackTopLeftCorner() const { - return m_nely*(m_nelx+1) + m_nelz*(m_nely+1)*(m_nelx+1); + return m_nely * (m_nelx + 1) + m_nelz * (m_nely + 1) * (m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesBackTopRightCorner() const { - return m_nely*(m_nelx+1) + m_nelx + m_nelz*(m_nely+1)*(m_nelx+1); -} - -// ------------------------------------------------------------------------------------------------- - -inline size_t Regular::nodesFrontLeftBottomCorner() const { return nodesFrontBottomLeftCorner(); } -inline size_t Regular::nodesBottomFrontLeftCorner() const { return nodesFrontBottomLeftCorner(); } -inline size_t Regular::nodesBottomLeftFrontCorner() const { return nodesFrontBottomLeftCorner(); } -inline size_t Regular::nodesLeftFrontBottomCorner() const { return nodesFrontBottomLeftCorner(); } -inline size_t Regular::nodesLeftBottomFrontCorner() const { return nodesFrontBottomLeftCorner(); } -inline size_t Regular::nodesFrontRightBottomCorner()const { return nodesFrontBottomRightCorner(); } -inline size_t Regular::nodesBottomFrontRightCorner()const { return nodesFrontBottomRightCorner(); } -inline size_t Regular::nodesBottomRightFrontCorner()const { return nodesFrontBottomRightCorner(); } -inline size_t Regular::nodesRightFrontBottomCorner()const { return nodesFrontBottomRightCorner(); } -inline size_t Regular::nodesRightBottomFrontCorner()const { return nodesFrontBottomRightCorner(); } -inline size_t Regular::nodesFrontLeftTopCorner() const { return nodesFrontTopLeftCorner(); } -inline size_t Regular::nodesTopFrontLeftCorner() const { return nodesFrontTopLeftCorner(); } -inline size_t Regular::nodesTopLeftFrontCorner() const { return nodesFrontTopLeftCorner(); } -inline size_t Regular::nodesLeftFrontTopCorner() const { return nodesFrontTopLeftCorner(); } -inline size_t Regular::nodesLeftTopFrontCorner() const { return nodesFrontTopLeftCorner(); } -inline size_t Regular::nodesFrontRightTopCorner() const { return nodesFrontTopRightCorner(); } -inline size_t Regular::nodesTopFrontRightCorner() const { return nodesFrontTopRightCorner(); } -inline size_t Regular::nodesTopRightFrontCorner() const { return nodesFrontTopRightCorner(); } -inline size_t Regular::nodesRightFrontTopCorner() const { return nodesFrontTopRightCorner(); } -inline size_t Regular::nodesRightTopFrontCorner() const { return nodesFrontTopRightCorner(); } -inline size_t Regular::nodesBackLeftBottomCorner() const { return nodesBackBottomLeftCorner(); } -inline size_t Regular::nodesBottomBackLeftCorner() const { return nodesBackBottomLeftCorner(); } -inline size_t Regular::nodesBottomLeftBackCorner() const { return nodesBackBottomLeftCorner(); } -inline size_t Regular::nodesLeftBackBottomCorner() const { return nodesBackBottomLeftCorner(); } -inline size_t Regular::nodesLeftBottomBackCorner() const { return nodesBackBottomLeftCorner(); } -inline size_t Regular::nodesBackRightBottomCorner() const { return nodesBackBottomRightCorner(); } -inline size_t Regular::nodesBottomBackRightCorner() const { return nodesBackBottomRightCorner(); } -inline size_t Regular::nodesBottomRightBackCorner() const { return nodesBackBottomRightCorner(); } -inline size_t Regular::nodesRightBackBottomCorner() const { return nodesBackBottomRightCorner(); } -inline size_t Regular::nodesRightBottomBackCorner() const { return nodesBackBottomRightCorner(); } -inline size_t Regular::nodesBackLeftTopCorner() const { return nodesBackTopLeftCorner(); } -inline size_t Regular::nodesTopBackLeftCorner() const { return nodesBackTopLeftCorner(); } -inline size_t Regular::nodesTopLeftBackCorner() const { return nodesBackTopLeftCorner(); } -inline size_t Regular::nodesLeftBackTopCorner() const { return nodesBackTopLeftCorner(); } -inline size_t Regular::nodesLeftTopBackCorner() const { return nodesBackTopLeftCorner(); } -inline size_t Regular::nodesBackRightTopCorner() const { return nodesBackTopRightCorner(); } -inline size_t Regular::nodesTopBackRightCorner() const { return nodesBackTopRightCorner(); } -inline size_t Regular::nodesTopRightBackCorner() const { return nodesBackTopRightCorner(); } -inline size_t Regular::nodesRightBackTopCorner() const { return nodesBackTopRightCorner(); } -inline size_t Regular::nodesRightTopBackCorner() const { return nodesBackTopRightCorner(); } - -// ------------------------------------------------------------------------------------------------- + return m_nely * (m_nelx + 1) + m_nelx + m_nelz * (m_nely + 1) * (m_nelx + 1); +} -inline xt::xtensor Regular::nodesPeriodic() const +inline size_t Regular::nodesFrontLeftBottomCorner() const { - // faces - xt::xtensor fro = nodesFrontFace(); - xt::xtensor bck = nodesBackFace(); - xt::xtensor lft = nodesLeftFace(); - xt::xtensor rgt = nodesRightFace(); - xt::xtensor bot = nodesBottomFace(); - xt::xtensor top = nodesTopFace(); - - // edges - xt::xtensor froBot = nodesFrontBottomOpenEdge(); - xt::xtensor froTop = nodesFrontTopOpenEdge(); - xt::xtensor froLft = nodesFrontLeftOpenEdge(); - xt::xtensor froRgt = nodesFrontRightOpenEdge(); - xt::xtensor bckBot = nodesBackBottomOpenEdge(); - xt::xtensor bckTop = nodesBackTopOpenEdge(); - xt::xtensor bckLft = nodesBackLeftOpenEdge(); - xt::xtensor bckRgt = nodesBackRightOpenEdge(); - xt::xtensor botLft = nodesBottomLeftOpenEdge(); - xt::xtensor botRgt = nodesBottomRightOpenEdge(); - xt::xtensor topLft = nodesTopLeftOpenEdge(); - xt::xtensor topRgt = nodesTopRightOpenEdge(); - - // allocate nodal ties - // - number of tying per category - size_t tface = fro.size() + lft.size() + bot.size(); - size_t tedge = 3*froBot.size() + 3*froLft.size() + 3*botLft.size(); - size_t tnode = 7; - // - allocate - xt::xtensor out = xt::empty({tface+tedge+tnode, std::size_t(2)}); - - // counter - size_t i = 0; - - // tie all corners to one corner - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesFrontBottomRightCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesBackBottomRightCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesBackBottomLeftCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesFrontTopLeftCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesFrontTopRightCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesBackTopRightCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesBackTopLeftCorner(); ++i; - - // tie all corresponding edges to each other (exclude corners) - for ( size_t j = 0 ; j Regular::dofs() const +inline size_t Regular::nodesBottomLeftFrontCorner() const { - return GooseFEM::Mesh::dofs(m_nnode,m_ndim); + return nodesFrontBottomLeftCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Regular::dofsPeriodic() const +inline size_t Regular::nodesLeftFrontBottomCorner() const { - // DOF-numbers for each component of each node (sequential) - xt::xtensor out = GooseFEM::Mesh::dofs(m_nnode,m_ndim); - - // periodic node-pairs - xt::xtensor nodePer = nodesPeriodic(); - - // eliminate 'dependent' DOFs; renumber "out" to be sequential for the remaining DOFs - for (size_t i = 0; i < nodePer.shape(0); ++i) - for (size_t j = 0; j < m_ndim; ++j) - out(nodePer(i,1),j) = out(nodePer(i,0),j); - - // renumber "out" to be sequential - return GooseFEM::Mesh::renumber(out); -} - -// ------------------------------------------------------------------------------------------------- - -inline FineLayer::FineLayer(size_t nelx, size_t nely, size_t nelz, double h, size_t nfine): -m_h(h) -{ - // basic assumptions - GOOSEFEM_ASSERT(nelx >= 1ul); - GOOSEFEM_ASSERT(nely >= 1ul); - GOOSEFEM_ASSERT(nelz >= 1ul); - - // store basic info - m_Lx = m_h * static_cast(nelx); - m_Lz = m_h * static_cast(nelz); - - // compute element size in y-direction (use symmetry, compute upper half) - // ------------------------------------------------------------------------------------------------- - - // temporary variables - size_t nmin, ntot; - xt::xtensor nhx = xt::ones({nely}); - xt::xtensor nhy = xt::ones({nely}); - xt::xtensor nhz = xt::ones({nely}); - xt::xtensor refine = -1 * xt::ones ({nely}); - - // minimum height in y-direction (half of the height because of symmetry) - if ( nely % 2 == 0 ) nmin = nely /2; - else nmin = (nely +1)/2; - - // minimum number of fine layers in y-direction (minimum 1, middle layer part of this half) - if ( nfine % 2 == 0 ) nfine = nfine /2 + 1; - else nfine = (nfine+1)/2; - if ( nfine < 1 ) nfine = 1; - if ( nfine > nmin ) nfine = nmin; - - // loop over element layers in y-direction, try to coarsen using these rules: - // (1) element size in y-direction <= distance to origin in y-direction - // (2) element size in x-(z-)direction should fit the total number of elements in x-(z-)direction - // (3) a certain number of layers have the minimum size "1" (are fine) - for ( size_t iy = nfine ; ; ) - { - // initialize current size in y-direction - if ( iy == nfine ) ntot = nfine; - // check to stop - if ( iy >= nely || ntot >= nmin ) { nely = iy; break; } - - // rules (1,2) satisfied: coarsen in x-direction (and z-direction) - if ( 3*nhy(iy) <= ntot && nelx%(3*nhx(iy)) == 0 && ntot+nhy(iy) < nmin ) - { - // - process refinement in x-direction - refine(iy) = 0; - nhy (iy) *= 2; - auto vnhy = xt::view(nhy, xt::range(iy+1, _)); - auto vnhx = xt::view(nhx, xt::range(iy , _)); - vnhy *= 3; - vnhx *= 3; - - // - rule (2) satisfied: coarsen next element layer in z-direction - if ( iy+1 < nely && ntot+2*nhy(iy) < nmin ) - { - if ( nelz%(3*nhz(iy+1)) == 0 ) - { - // - update the number of elements in y-direction - ntot += nhy(iy); - // - proceed to next element layer in y-direction - ++iy; - // - process refinement in z-direction - refine(iy) = 2; - nhy (iy) = nhy(iy-1); - auto vnhz = xt::view(nhz, xt::range(iy, _)); - vnhz *= 3; - } - } - } - - // rules (1,2) satisfied: coarse in z-direction - else if ( 3*nhy(iy) <= ntot && nelz%(3*nhz(iy)) == 0 && ntot+nhy(iy) < nmin ) - { - // - process refinement in z-direction - refine(iy) = 2; - nhy (iy) *= 2; - auto vnhy = xt::view(nhy, xt::range(iy+1, _)); - auto vnhz = xt::view(nhz, xt::range(iy , _)); - vnhy *= 3; - vnhz *= 3; - } - - // update the number of elements in y-direction - ntot += nhy(iy); - // proceed to next element layer in y-direction - ++iy; - // check to stop - if ( iy >= nely || ntot >= nmin ) { nely = iy; break; } - } - - // symmetrize, compute full information - // ------------------------------------------------------------------------------------------------- - - // allocate mesh constructor parameters - m_nhx = xt::empty({nely*2-1}); - m_nhy = xt::empty({nely*2-1}); - m_nhz = xt::empty({nely*2-1}); - m_refine = xt::empty ({nely*2-1}); - m_nelx = xt::empty({nely*2-1}); - m_nelz = xt::empty({nely*2-1}); - m_nnd = xt::empty({nely*2 }); - m_startElem = xt::empty({nely*2-1}); - m_startNode = xt::empty({nely*2 }); - - // fill - // - lower half - for ( size_t iy = 0 ; iy < nely ; ++iy ) - { - m_nhx (iy) = nhx (nely-iy-1); - m_nhy (iy) = nhy (nely-iy-1); - m_nhz (iy) = nhz (nely-iy-1); - m_refine(iy) = refine(nely-iy-1); - } - // - upper half - for ( size_t iy = 0 ; iy < nely-1 ; ++iy ) - { - m_nhx (iy+nely) = nhx (iy+1); - m_nhy (iy+nely) = nhy (iy+1); - m_nhz (iy+nely) = nhz (iy+1); - m_refine(iy+nely) = refine(iy+1); - } - - // update size - nely = m_nhx.size(); - - // compute the number of elements per element layer in y-direction - for ( size_t iy = 0 ; iy < nely ; ++iy ) - { - m_nelx(iy) = nelx / m_nhx(iy); - m_nelz(iy) = nelz / m_nhz(iy); - } - - // compute the number of nodes per node layer in y-direction - // - bottom half - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - m_nnd(iy) = (m_nelx(iy)+1) * (m_nelz(iy)+1); - // - top half - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - m_nnd(iy+1) = (m_nelx(iy)+1) * (m_nelz(iy)+1); - - // compute mesh dimensions - // ------------------------------------------------------------------------------------------------- - - // initialize - m_nnode = 0; - m_nelem = 0; - m_startNode(0) = 0; - - // loop over element layers (bottom -> middle, elements become finer) - for ( size_t i = 0 ; i < (nely-1)/2 ; ++i ) - { - // - store the first element of the layer - m_startElem(i) = m_nelem; - // - add the nodes of this layer - if ( m_refine(i) == 0 ) { m_nnode += (3*m_nelx(i)+1) * ( m_nelz(i)+1); } - else if ( m_refine(i) == 2 ) { m_nnode += ( m_nelx(i)+1) * (3*m_nelz(i)+1); } - else { m_nnode += ( m_nelx(i)+1) * ( m_nelz(i)+1); } - // - add the elements of this layer - if ( m_refine(i) == 0 ) { m_nelem += (4*m_nelx(i) ) * ( m_nelz(i) ); } - else if ( m_refine(i) == 2 ) { m_nelem += ( m_nelx(i) ) * (4*m_nelz(i) ); } - else { m_nelem += ( m_nelx(i) ) * ( m_nelz(i) ); } - // - store the starting node of the next layer - m_startNode(i+1) = m_nnode; - } - - // loop over element layers (middle -> top, elements become coarser) - for ( size_t i = (nely-1)/2 ; i < nely ; ++i ) - { - // - store the first element of the layer - m_startElem(i) = m_nelem; - // - add the nodes of this layer - if ( m_refine(i) == 0 ) { m_nnode += (5*m_nelx(i)+1) * ( m_nelz(i)+1); } - else if ( m_refine(i) == 2 ) { m_nnode += ( m_nelx(i)+1) * (5*m_nelz(i)+1); } - else { m_nnode += ( m_nelx(i)+1) * ( m_nelz(i)+1); } - // - add the elements of this layer - if ( m_refine(i) == 0 ) { m_nelem += (4*m_nelx(i) ) * ( m_nelz(i) ); } - else if ( m_refine(i) == 2 ) { m_nelem += ( m_nelx(i) ) * (4*m_nelz(i) ); } - else { m_nelem += ( m_nelx(i) ) * ( m_nelz(i) ); } - // - store the starting node of the next layer - m_startNode(i+1) = m_nnode; - } - // - add the top row of nodes - m_nnode += (m_nelx(nely-1)+1) * (m_nelz(nely-1)+1); -} - -// ------------------------------------------------------------------------------------------------- - -inline size_t FineLayer::nelem() const + return nodesFrontBottomLeftCorner(); +} +inline size_t Regular::nodesLeftBottomFrontCorner() const { - return m_nelem; + return nodesFrontBottomLeftCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline size_t FineLayer::nnode() const +inline size_t Regular::nodesFrontRightBottomCorner() const { - return m_nnode; + return nodesFrontBottomRightCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline size_t FineLayer::nne() const +inline size_t Regular::nodesBottomFrontRightCorner() const { - return m_nne; + return nodesFrontBottomRightCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline size_t FineLayer::ndim() const +inline size_t Regular::nodesBottomRightFrontCorner() const { - return m_ndim; + return nodesFrontBottomRightCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline size_t FineLayer::nelx() const +inline size_t Regular::nodesRightFrontBottomCorner() const { - return xt::amax(m_nelx)[0]; + return nodesFrontBottomRightCorner(); } - -inline size_t FineLayer::nely() const +inline size_t Regular::nodesRightBottomFrontCorner() const { - return xt::sum(m_nhy)[0]; + return nodesFrontBottomRightCorner(); } - -inline size_t FineLayer::nelz() const +inline size_t Regular::nodesFrontLeftTopCorner() const { - return xt::amax(m_nelz)[0]; + return nodesFrontTopLeftCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline ElementType FineLayer::getElementType() const +inline size_t Regular::nodesTopFrontLeftCorner() const { - return ElementType::Hex8; + return nodesFrontTopLeftCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::coor() const +inline size_t Regular::nodesTopLeftFrontCorner() const { - // allocate output - xt::xtensor out = xt::empty({m_nnode, m_ndim}); - - // current node, number of element layers - size_t inode = 0; - size_t nely = static_cast(m_nhy.size()); - - // y-position of each main node layer (i.e. excluding node layers for refinement/coarsening) - // - allocate - xt::xtensor y = xt::empty({nely+1}); - // - initialize - y(0) = 0.0; - // - compute - for ( size_t iy = 1 ; iy < nely+1 ; ++iy ) - y(iy) = y(iy-1) + m_nhy(iy-1) * m_h; - - // loop over element layers (bottom -> middle) : add bottom layer (+ refinement layer) of nodes - // ------------------------------------------------------------------------------------------------- - - for ( size_t iy = 0 ; ; ++iy ) - { - // get positions along the x- and z-axis - xt::xtensor x = xt::linspace(0.0, m_Lx, m_nelx(iy)+1); - xt::xtensor z = xt::linspace(0.0, m_Lz, m_nelz(iy)+1); - - // add nodes of the bottom layer of this element - for ( size_t iz = 0 ; iz < m_nelz(iy)+1 ; ++iz ) { - for ( size_t ix = 0 ; ix < m_nelx(iy)+1 ; ++ix ) { - out(inode,0) = x(ix); - out(inode,1) = y(iy); - out(inode,2) = z(iz); - ++inode; - } - } - - // stop at middle layer - if ( iy == (nely-1)/2 ) - break; - - // add extra nodes of the intermediate layer, for refinement in x-direction - if ( m_refine(iy) == 0 ) - { - // - get position offset in x- and y-direction - double dx = m_h * static_cast(m_nhx(iy)/3); - double dy = m_h * static_cast(m_nhy(iy)/2); - // - add nodes of the intermediate layer - for ( size_t iz = 0 ; iz < m_nelz(iy)+1 ; ++iz ) { - for ( size_t ix = 0 ; ix < m_nelx(iy) ; ++ix ) { - for ( size_t j = 0 ; j < 2 ; ++j ) { - out(inode,0) = x(ix) + dx * static_cast(j+1); - out(inode,1) = y(iy) + dy; - out(inode,2) = z(iz); - ++inode; - } - } - } - } - - // add extra nodes of the intermediate layer, for refinement in z-direction - else if ( m_refine(iy) == 2 ) - { - // - get position offset in y- and z-direction - double dz = m_h * static_cast(m_nhz(iy)/3); - double dy = m_h * static_cast(m_nhy(iy)/2); - // - add nodes of the intermediate layer - for ( size_t iz = 0 ; iz < m_nelz(iy) ; ++iz ) { - for ( size_t j = 0 ; j < 2 ; ++j ) { - for ( size_t ix = 0 ; ix < m_nelx(iy)+1 ; ++ix ) { - out(inode,0) = x(ix); - out(inode,1) = y(iy) + dy; - out(inode,2) = z(iz) + dz * static_cast(j+1); - ++inode; - } - } - } - } - } - - // loop over element layers (middle -> top) : add (refinement layer +) top layer of nodes - // ------------------------------------------------------------------------------------------------- - - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - { - // get positions along the x- and z-axis - xt::xtensor x = xt::linspace(0.0, m_Lx, m_nelx(iy)+1); - xt::xtensor z = xt::linspace(0.0, m_Lz, m_nelz(iy)+1); - - // add extra nodes of the intermediate layer, for refinement in x-direction - if ( m_refine(iy) == 0 ) - { - // - get position offset in x- and y-direction - double dx = m_h * static_cast(m_nhx(iy)/3); - double dy = m_h * static_cast(m_nhy(iy)/2); - // - add nodes of the intermediate layer - for ( size_t iz = 0 ; iz < m_nelz(iy)+1 ; ++iz ) { - for ( size_t ix = 0 ; ix < m_nelx(iy) ; ++ix ) { - for ( size_t j = 0 ; j < 2 ; ++j ) { - out(inode,0) = x(ix) + dx * static_cast(j+1); - out(inode,1) = y(iy) + dy; - out(inode,2) = z(iz); - ++inode; - } - } - } - } - - // add extra nodes of the intermediate layer, for refinement in z-direction - else if ( m_refine(iy) == 2 ) - { - // - get position offset in y- and z-direction - double dz = m_h * static_cast(m_nhz(iy)/3); - double dy = m_h * static_cast(m_nhy(iy)/2); - // - add nodes of the intermediate layer - for ( size_t iz = 0 ; iz < m_nelz(iy) ; ++iz ) { - for ( size_t j = 0 ; j < 2 ; ++j ) { - for ( size_t ix = 0 ; ix < m_nelx(iy)+1 ; ++ix ) { - out(inode,0) = x(ix); - out(inode,1) = y(iy) + dy; - out(inode,2) = z(iz) + dz * static_cast(j+1); - ++inode; - } - } - } - } - - // add nodes of the top layer of this element - for ( size_t iz = 0 ; iz < m_nelz(iy)+1 ; ++iz ) { - for ( size_t ix = 0 ; ix < m_nelx(iy)+1 ; ++ix ) { - out(inode,0) = x(ix ); - out(inode,1) = y(iy+1); - out(inode,2) = z(iz ); - ++inode; - } - } - } - - return out; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::conn() const + return nodesFrontTopLeftCorner(); +} +inline size_t Regular::nodesLeftFrontTopCorner() const { - // allocate output - xt::xtensor out = xt::empty({m_nelem, m_nne}); - - // current element, number of element layers, starting nodes of each node layer - size_t ielem = 0; - size_t nely = static_cast(m_nhy.size()); - size_t bot,mid,top; - - // loop over all element layers - for ( size_t iy = 0 ; iy < nely ; ++iy ) - { - // - get: starting nodes of bottom(, middle) and top layer - bot = m_startNode(iy ); - mid = m_startNode(iy ) + m_nnd(iy); - top = m_startNode(iy+1); - - // - define connectivity: no coarsening/refinement - if ( m_refine(iy) == -1 ) - { - for ( size_t iz = 0 ; iz < m_nelz(iy) ; ++iz ) { - for ( size_t ix = 0 ; ix < m_nelx(iy) ; ++ix ) { - out(ielem,0) = bot + (ix ) + (iz ) * (m_nelx(iy)+1); - out(ielem,1) = bot + (ix+1) + (iz ) * (m_nelx(iy)+1); - out(ielem,2) = top + (ix+1) + (iz ) * (m_nelx(iy)+1); - out(ielem,3) = top + (ix ) + (iz ) * (m_nelx(iy)+1); - out(ielem,4) = bot + (ix ) + (iz+1) * (m_nelx(iy)+1); - out(ielem,5) = bot + (ix+1) + (iz+1) * (m_nelx(iy)+1); - out(ielem,6) = top + (ix+1) + (iz+1) * (m_nelx(iy)+1); - out(ielem,7) = top + (ix ) + (iz+1) * (m_nelx(iy)+1); - ielem++; - } - } - } - - // - define connectivity: refinement along the x-direction (below the middle layer) - else if ( m_refine(iy) == 0 && iy <= (nely-1)/2 ) - { - for ( size_t iz = 0 ; iz < m_nelz(iy) ; ++iz ) { - for ( size_t ix = 0 ; ix < m_nelx(iy) ; ++ix ) { - // -- bottom element - out(ielem,0) = bot + ( ix ) + (iz ) * ( m_nelx(iy)+1); - out(ielem,1) = bot + ( ix+1) + (iz ) * ( m_nelx(iy)+1); - out(ielem,2) = mid + (2*ix+1) + (iz ) * (2*m_nelx(iy) ); - out(ielem,3) = mid + (2*ix ) + (iz ) * (2*m_nelx(iy) ); - out(ielem,4) = bot + ( ix ) + (iz+1) * ( m_nelx(iy)+1); - out(ielem,5) = bot + ( ix+1) + (iz+1) * ( m_nelx(iy)+1); - out(ielem,6) = mid + (2*ix+1) + (iz+1) * (2*m_nelx(iy) ); - out(ielem,7) = mid + (2*ix ) + (iz+1) * (2*m_nelx(iy) ); - ielem++; - // -- top-right element - out(ielem,0) = bot + ( ix+1) + (iz ) * ( m_nelx(iy)+1); - out(ielem,1) = top + (3*ix+3) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,2) = top + (3*ix+2) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,3) = mid + (2*ix+1) + (iz ) * (2*m_nelx(iy) ); - out(ielem,4) = bot + ( ix+1) + (iz+1) * ( m_nelx(iy)+1); - out(ielem,5) = top + (3*ix+3) + (iz+1) * (3*m_nelx(iy)+1); - out(ielem,6) = top + (3*ix+2) + (iz+1) * (3*m_nelx(iy)+1); - out(ielem,7) = mid + (2*ix+1) + (iz+1) * (2*m_nelx(iy) ); - ielem++; - // -- top-center element - out(ielem,0) = mid + (2*ix ) + (iz ) * (2*m_nelx(iy) ); - out(ielem,1) = mid + (2*ix+1) + (iz ) * (2*m_nelx(iy) ); - out(ielem,2) = top + (3*ix+2) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,3) = top + (3*ix+1) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,4) = mid + (2*ix ) + (iz+1) * (2*m_nelx(iy) ); - out(ielem,5) = mid + (2*ix+1) + (iz+1) * (2*m_nelx(iy) ); - out(ielem,6) = top + (3*ix+2) + (iz+1) * (3*m_nelx(iy)+1); - out(ielem,7) = top + (3*ix+1) + (iz+1) * (3*m_nelx(iy)+1); - ielem++; - // -- top-left element - out(ielem,0) = bot + ( ix ) + (iz ) * ( m_nelx(iy)+1); - out(ielem,1) = mid + (2*ix ) + (iz ) * (2*m_nelx(iy) ); - out(ielem,2) = top + (3*ix+1) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,3) = top + (3*ix ) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,4) = bot + ( ix ) + (iz+1) * ( m_nelx(iy)+1); - out(ielem,5) = mid + (2*ix ) + (iz+1) * (2*m_nelx(iy) ); - out(ielem,6) = top + (3*ix+1) + (iz+1) * (3*m_nelx(iy)+1); - out(ielem,7) = top + (3*ix ) + (iz+1) * (3*m_nelx(iy)+1); - ielem++; - } - } - } - - // - define connectivity: coarsening along the x-direction (above the middle layer) - else if ( m_refine(iy) == 0 && iy > (nely-1)/2 ) - { - for ( size_t iz = 0 ; iz < m_nelz(iy) ; ++iz ) { - for ( size_t ix = 0 ; ix < m_nelx(iy) ; ++ix ) { - // -- lower-left element - out(ielem,0) = bot + (3*ix ) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,1) = bot + (3*ix+1) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,2) = mid + (2*ix ) + (iz ) * (2*m_nelx(iy) ); - out(ielem,3) = top + ( ix ) + (iz ) * ( m_nelx(iy)+1); - out(ielem,4) = bot + (3*ix ) + (iz+1) * (3*m_nelx(iy)+1); - out(ielem,5) = bot + (3*ix+1) + (iz+1) * (3*m_nelx(iy)+1); - out(ielem,6) = mid + (2*ix ) + (iz+1) * (2*m_nelx(iy) ); - out(ielem,7) = top + ( ix ) + (iz+1) * ( m_nelx(iy)+1); - ielem++; - // -- lower-center element - out(ielem,0) = bot + (3*ix+1) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,1) = bot + (3*ix+2) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,2) = mid + (2*ix+1) + (iz ) * (2*m_nelx(iy) ); - out(ielem,3) = mid + (2*ix ) + (iz ) * (2*m_nelx(iy) ); - out(ielem,4) = bot + (3*ix+1) + (iz+1) * (3*m_nelx(iy)+1); - out(ielem,5) = bot + (3*ix+2) + (iz+1) * (3*m_nelx(iy)+1); - out(ielem,6) = mid + (2*ix+1) + (iz+1) * (2*m_nelx(iy) ); - out(ielem,7) = mid + (2*ix ) + (iz+1) * (2*m_nelx(iy) ); - ielem++; - // -- lower-right element - out(ielem,0) = bot + (3*ix+2) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,1) = bot + (3*ix+3) + (iz ) * (3*m_nelx(iy)+1); - out(ielem,2) = top + ( ix+1) + (iz ) * ( m_nelx(iy)+1); - out(ielem,3) = mid + (2*ix+1) + (iz ) * (2*m_nelx(iy) ); - out(ielem,4) = bot + (3*ix+2) + (iz+1) * (3*m_nelx(iy)+1); - out(ielem,5) = bot + (3*ix+3) + (iz+1) * (3*m_nelx(iy)+1); - out(ielem,6) = top + ( ix+1) + (iz+1) * ( m_nelx(iy)+1); - out(ielem,7) = mid + (2*ix+1) + (iz+1) * (2*m_nelx(iy) ); - ielem++; - // -- upper element - out(ielem,0) = mid + (2*ix ) + (iz ) * (2*m_nelx(iy) ); - out(ielem,1) = mid + (2*ix+1) + (iz ) * (2*m_nelx(iy) ); - out(ielem,2) = top + ( ix+1) + (iz ) * ( m_nelx(iy)+1); - out(ielem,3) = top + ( ix ) + (iz ) * ( m_nelx(iy)+1); - out(ielem,4) = mid + (2*ix ) + (iz+1) * (2*m_nelx(iy) ); - out(ielem,5) = mid + (2*ix+1) + (iz+1) * (2*m_nelx(iy) ); - out(ielem,6) = top + ( ix+1) + (iz+1) * ( m_nelx(iy)+1); - out(ielem,7) = top + ( ix ) + (iz+1) * ( m_nelx(iy)+1); - ielem++; - } - } - } - - // - define connectivity: refinement along the z-direction (below the middle layer) - else if ( m_refine(iy) == 2 && iy <= (nely-1)/2 ) - { - for ( size_t iz = 0 ; iz < m_nelz(iy) ; ++iz ) { - for ( size_t ix = 0 ; ix < m_nelx(iy) ; ++ix ) { - // -- bottom element - out(ielem,0) = bot + (ix ) + iz * (m_nelx(iy)+1); - out(ielem,1) = bot + (ix ) + ( iz+1) * (m_nelx(iy)+1); - out(ielem,2) = bot + (ix+1) + ( iz+1) * (m_nelx(iy)+1); - out(ielem,3) = bot + (ix+1) + iz * (m_nelx(iy)+1); - out(ielem,4) = mid + (ix ) + 2*iz * (m_nelx(iy)+1); - out(ielem,5) = mid + (ix ) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,6) = mid + (ix+1) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,7) = mid + (ix+1) + 2*iz * (m_nelx(iy)+1); - ielem++; - // -- top-back element - out(ielem,0) = mid + (ix ) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,1) = mid + (ix+1) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,2) = top + (ix+1) + (3*iz+2) * (m_nelx(iy)+1); - out(ielem,3) = top + (ix ) + (3*iz+2) * (m_nelx(iy)+1); - out(ielem,4) = bot + (ix ) + ( iz+1) * (m_nelx(iy)+1); - out(ielem,5) = bot + (ix+1) + ( iz+1) * (m_nelx(iy)+1); - out(ielem,6) = top + (ix+1) + (3*iz+3) * (m_nelx(iy)+1); - out(ielem,7) = top + (ix ) + (3*iz+3) * (m_nelx(iy)+1); - ielem++; - // -- top-center element - out(ielem,0) = mid + (ix ) + (2*iz ) * (m_nelx(iy)+1); - out(ielem,1) = mid + (ix+1) + (2*iz ) * (m_nelx(iy)+1); - out(ielem,2) = top + (ix+1) + (3*iz+1) * (m_nelx(iy)+1); - out(ielem,3) = top + (ix ) + (3*iz+1) * (m_nelx(iy)+1); - out(ielem,4) = mid + (ix ) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,5) = mid + (ix+1) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,6) = top + (ix+1) + (3*iz+2) * (m_nelx(iy)+1); - out(ielem,7) = top + (ix ) + (3*iz+2) * (m_nelx(iy)+1); - ielem++; - // -- top-front element - out(ielem,0) = bot + (ix ) + ( iz ) * (m_nelx(iy)+1); - out(ielem,1) = bot + (ix+1) + ( iz ) * (m_nelx(iy)+1); - out(ielem,2) = top + (ix+1) + (3*iz ) * (m_nelx(iy)+1); - out(ielem,3) = top + (ix ) + (3*iz ) * (m_nelx(iy)+1); - out(ielem,4) = mid + (ix ) + (2*iz ) * (m_nelx(iy)+1); - out(ielem,5) = mid + (ix+1) + (2*iz ) * (m_nelx(iy)+1); - out(ielem,6) = top + (ix+1) + (3*iz+1) * (m_nelx(iy)+1); - out(ielem,7) = top + (ix ) + (3*iz+1) * (m_nelx(iy)+1); - ielem++; - } - } - } - - // - define connectivity: coarsening along the z-direction (above the middle layer) - else if ( m_refine(iy) == 2 && iy > (nely-1)/2 ) - { - for ( size_t iz = 0 ; iz < m_nelz(iy) ; ++iz ) { - for ( size_t ix = 0 ; ix < m_nelx(iy) ; ++ix ) { - // -- bottom-front element - out(ielem,0) = bot + (ix ) + (3*iz ) * (m_nelx(iy)+1); - out(ielem,1) = bot + (ix+1) + (3*iz ) * (m_nelx(iy)+1); - out(ielem,2) = top + (ix+1) + ( iz ) * (m_nelx(iy)+1); - out(ielem,3) = top + (ix ) + ( iz ) * (m_nelx(iy)+1); - out(ielem,4) = bot + (ix ) + (3*iz+1) * (m_nelx(iy)+1); - out(ielem,5) = bot + (ix+1) + (3*iz+1) * (m_nelx(iy)+1); - out(ielem,6) = mid + (ix+1) + (2*iz ) * (m_nelx(iy)+1); - out(ielem,7) = mid + (ix ) + (2*iz ) * (m_nelx(iy)+1); - ielem++; - // -- bottom-center element - out(ielem,0) = bot + (ix ) + (3*iz+1) * (m_nelx(iy)+1); - out(ielem,1) = bot + (ix+1) + (3*iz+1) * (m_nelx(iy)+1); - out(ielem,2) = mid + (ix+1) + (2*iz ) * (m_nelx(iy)+1); - out(ielem,3) = mid + (ix ) + (2*iz ) * (m_nelx(iy)+1); - out(ielem,4) = bot + (ix ) + (3*iz+2) * (m_nelx(iy)+1); - out(ielem,5) = bot + (ix+1) + (3*iz+2) * (m_nelx(iy)+1); - out(ielem,6) = mid + (ix+1) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,7) = mid + (ix ) + (2*iz+1) * (m_nelx(iy)+1); - ielem++; - // -- bottom-back element - out(ielem,0) = bot + (ix ) + (3*iz+2) * (m_nelx(iy)+1); - out(ielem,1) = bot + (ix+1) + (3*iz+2) * (m_nelx(iy)+1); - out(ielem,2) = mid + (ix+1) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,3) = mid + (ix ) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,4) = bot + (ix ) + (3*iz+3) * (m_nelx(iy)+1); - out(ielem,5) = bot + (ix+1) + (3*iz+3) * (m_nelx(iy)+1); - out(ielem,6) = top + (ix+1) + ( iz+1) * (m_nelx(iy)+1); - out(ielem,7) = top + (ix ) + ( iz+1) * (m_nelx(iy)+1); - ielem++; - // -- top element - out(ielem,0) = mid + (ix ) + (2*iz ) * (m_nelx(iy)+1); - out(ielem,1) = mid + (ix+1) + (2*iz ) * (m_nelx(iy)+1); - out(ielem,2) = top + (ix+1) + ( iz ) * (m_nelx(iy)+1); - out(ielem,3) = top + (ix ) + ( iz ) * (m_nelx(iy)+1); - out(ielem,4) = mid + (ix ) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,5) = mid + (ix+1) + (2*iz+1) * (m_nelx(iy)+1); - out(ielem,6) = top + (ix+1) + ( iz+1) * (m_nelx(iy)+1); - out(ielem,7) = top + (ix ) + ( iz+1) * (m_nelx(iy)+1); - ielem++; - } - } - } - } - - return out; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::elementsMiddleLayer() const + return nodesFrontTopLeftCorner(); +} +inline size_t Regular::nodesLeftTopFrontCorner() const { - // number of element layers in y-direction, the index of the middle layer - size_t nely = static_cast(m_nhy.size()); - size_t iy = (nely-1)/2; - - xt::xtensor out = xt::empty({m_nelx(iy)*m_nelz(iy)}); - - for ( size_t ix = 0 ; ix < m_nelx(iy) ; ++ix ) - for ( size_t iz = 0 ; iz < m_nelz(iy) ; ++iz ) - out(ix+iz*m_nelx(iy)) = m_startElem(iy) + ix + iz*m_nelx(iy); - - return out; + return nodesFrontTopLeftCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesFront() const +inline size_t Regular::nodesFrontRightTopCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // number of boundary nodes - // - initialize - size_t n = 0; - // - bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - { - if ( m_refine(iy) == 0 ) n += m_nelx(iy) * 3 + 1; - else n += m_nelx(iy) + 1; - } - // - top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - { - if ( m_refine(iy) == 0 ) n += m_nelx(iy) * 3 + 1; - else n += m_nelx(iy) + 1; - } - - // allocate node-list - xt::xtensor out = xt::empty({n}); - - // initialize counter: current index in the node-list "out" - size_t j = 0; - - // bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - { - // -- bottom node layer - for ( size_t ix = 0 ; ix < m_nelx(iy)+1 ; ++ix ) { - out(j) = m_startNode(iy) + ix; - ++j; - } - // -- refinement layer - if ( m_refine(iy) == 0 ) { - for ( size_t ix = 0 ; ix < 2*m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy) + ix + m_nnd(iy); - ++j; - } - } - } - - // top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - { - // -- refinement layer - if ( m_refine(iy) == 0 ) { - for ( size_t ix = 0 ; ix < 2*m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy) + ix + m_nnd(iy); - ++j; - } - } - // -- top node layer - for ( size_t ix = 0 ; ix < m_nelx(iy)+1 ; ++ix ) { - out(j) = m_startNode(iy+1) + ix; - ++j; - } - } - - return out; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesBack() const + return nodesFrontTopRightCorner(); +} +inline size_t Regular::nodesTopFrontRightCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // number of boundary nodes - // - initialize - size_t n = 0; - // - bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - { - if ( m_refine(iy) == 0 ) n += m_nelx(iy) * 3 + 1; - else n += m_nelx(iy) + 1; - } - // - top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - { - if ( m_refine(iy) == 0 ) n += m_nelx(iy) * 3 + 1; - else n += m_nelx(iy) + 1; - } - - // allocate node-list - xt::xtensor out = xt::empty({n}); - - // initialize counter: current index in the node-list "out" - size_t j = 0; - - // bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - { - // -- bottom node layer - for ( size_t ix = 0 ; ix < m_nelx(iy)+1 ; ++ix ) { - out(j) = m_startNode(iy) + ix + (m_nelx(iy)+1)*m_nelz(iy); - ++j; - } - // -- refinement layer - if ( m_refine(iy) == 0 ) { - for ( size_t ix = 0 ; ix < 2*m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy) + ix + m_nnd(iy) + 2*m_nelx(iy)*m_nelz(iy); - ++j; - } - } - } - - // top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - { - // -- refinement layer - if ( m_refine(iy) == 0 ) { - for ( size_t ix = 0 ; ix < 2*m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy) + ix + m_nnd(iy) + 2*m_nelx(iy)*m_nelz(iy); - ++j; - } - } - // -- top node layer - for ( size_t ix = 0 ; ix < m_nelx(iy)+1 ; ++ix ) { - out(j) = m_startNode(iy+1) + ix + (m_nelx(iy)+1)*m_nelz(iy); - ++j; - } - } - - return out; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesLeft() const + return nodesFrontTopRightCorner(); +} +inline size_t Regular::nodesTopRightFrontCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // number of boundary nodes - // - initialize - size_t n = 0; - // - bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - { - if ( m_refine(iy) == 2 ) n += m_nelz(iy) * 3 + 1; - else n += m_nelz(iy) + 1; - } - // - top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - { - if ( m_refine(iy) == 2 ) n += m_nelz(iy) * 3 + 1; - else n += m_nelz(iy) + 1; - } - - // allocate node-list - xt::xtensor out = xt::empty({n}); - - // initialize counter: current index in the node-list "out" - size_t j = 0; - - // bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - { - // -- bottom node layer - for ( size_t iz = 0 ; iz < m_nelz(iy)+1 ; ++iz ) { - out(j) = m_startNode(iy) + iz * (m_nelx(iy)+1); - ++j; - } - // -- refinement layer - if ( m_refine(iy) == 2 ) { - for ( size_t iz = 0 ; iz < 2*m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy) + iz * (m_nelx(iy)+1) + m_nnd(iy); - ++j; - } - } - } - - // top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - { - // -- refinement layer - if ( m_refine(iy) == 2 ) { - for ( size_t iz = 0 ; iz < 2*m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy) + iz * (m_nelx(iy)+1) + m_nnd(iy); - ++j; - } - } - // -- top node layer - for ( size_t iz = 0 ; iz < m_nelz(iy)+1 ; ++iz ) { - out(j) = m_startNode(iy+1) + iz * (m_nelx(iy)+1); - ++j; - } - } - - return out; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesRight() const + return nodesFrontTopRightCorner(); +} +inline size_t Regular::nodesRightFrontTopCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // number of boundary nodes - // - initialize - size_t n = 0; - // - bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - { - if ( m_refine(iy) == 2 ) n += m_nelz(iy) * 3 + 1; - else n += m_nelz(iy) + 1; - } - // - top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - { - if ( m_refine(iy) == 2 ) n += m_nelz(iy) * 3 + 1; - else n += m_nelz(iy) + 1; - } - - // allocate node-list - xt::xtensor out = xt::empty({n}); - - // initialize counter: current index in the node-list "out" - size_t j = 0; - - // bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - { - // -- bottom node layer - for ( size_t iz = 0 ; iz < m_nelz(iy)+1 ; ++iz ) { - out(j) = m_startNode(iy) + iz * (m_nelx(iy)+1) + m_nelx(iy); - ++j; - } - // -- refinement layer - if ( m_refine(iy) == 2 ) { - for ( size_t iz = 0 ; iz < 2*m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy) + m_nnd(iy) + iz * (m_nelx(iy)+1) + m_nelx(iy); - ++j; - } - } - } - - // top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - { - // -- refinement layer - if ( m_refine(iy) == 2 ) { - for ( size_t iz = 0 ; iz < 2*m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy) + m_nnd(iy) + iz * (m_nelx(iy)+1) + m_nelx(iy); - ++j; - } - } - // -- top node layer - for ( size_t iz = 0 ; iz < m_nelz(iy)+1 ; ++iz ) { - out(j) = m_startNode(iy+1) + iz * (m_nelx(iy)+1) + m_nelx(iy); - ++j; - } - } - - return out; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesBottom() const + return nodesFrontTopRightCorner(); +} +inline size_t Regular::nodesRightTopFrontCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // allocate node list - xt::xtensor out = xt::empty({m_nnd(nely)}); - - // counter - size_t j = 0; - - // fill node list - for ( size_t ix = 0 ; ix < m_nelx(0)+1 ; ++ix ) { - for ( size_t iz = 0 ; iz < m_nelz(0)+1 ; ++iz ) { - out(j) = m_startNode(0) + ix + iz * (m_nelx(0)+1); - ++j; - } - } - - return out; + return nodesFrontTopRightCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesTop() const +inline size_t Regular::nodesBackLeftBottomCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // allocate node list - xt::xtensor out = xt::empty({m_nnd(nely)}); - - // counter - size_t j = 0; - - // fill node list - for ( size_t ix = 0 ; ix < m_nelx(nely-1)+1 ; ++ix ) { - for ( size_t iz = 0 ; iz < m_nelz(nely-1)+1 ; ++iz ) { - out(j) = m_startNode(nely) + ix + iz * (m_nelx(nely-1)+1); - ++j; - } - } - - return out; + return nodesBackBottomLeftCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesFrontFace() const +inline size_t Regular::nodesBottomBackLeftCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // number of boundary nodes - // - initialize - size_t n = 0; - // - bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - { - if ( m_refine(iy) == 0 ) n += m_nelx(iy) * 3 - 1; - else n += m_nelx(iy) - 1; - } - // - top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - { - if ( m_refine(iy) == 0 ) n += m_nelx(iy) * 3 - 1; - else n += m_nelx(iy) - 1; - } - - // allocate node-list - xt::xtensor out = xt::empty({n}); - - // initialize counter: current index in the node-list "out" - size_t j = 0; - - // bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - { - // -- bottom node layer - for ( size_t ix = 1 ; ix < m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy) + ix; - ++j; - } - // -- refinement layer - if ( m_refine(iy) == 0 ) { - for ( size_t ix = 0 ; ix < 2*m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy) + ix + m_nnd(iy); - ++j; - } - } - } - - // top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - { - // -- refinement layer - if ( m_refine(iy) == 0 ) { - for ( size_t ix = 0 ; ix < 2*m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy) + ix + m_nnd(iy); - ++j; - } - } - // -- top node layer - for ( size_t ix = 1 ; ix < m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy+1) + ix; - ++j; - } - } - - return out; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesBackFace() const + return nodesBackBottomLeftCorner(); +} +inline size_t Regular::nodesBottomLeftBackCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // number of boundary nodes - // - initialize - size_t n = 0; - // - bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - { - if ( m_refine(iy) == 0 ) n += m_nelx(iy) * 3 - 1; - else n += m_nelx(iy) - 1; - } - // - top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - { - if ( m_refine(iy) == 0 ) n += m_nelx(iy) * 3 - 1; - else n += m_nelx(iy) - 1; - } - - // allocate node-list - xt::xtensor out = xt::empty({n}); - - // initialize counter: current index in the node-list "out" - size_t j = 0; - - // bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - { - // -- bottom node layer - for ( size_t ix = 1 ; ix < m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy) + ix + (m_nelx(iy)+1)*m_nelz(iy); - ++j; - } - // -- refinement layer - if ( m_refine(iy) == 0 ) { - for ( size_t ix = 0 ; ix < 2*m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy) + ix + m_nnd(iy) + 2*m_nelx(iy)*m_nelz(iy); - ++j; - } - } - } - - // top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - { - // -- refinement layer - if ( m_refine(iy) == 0 ) { - for ( size_t ix = 0 ; ix < 2*m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy) + ix + m_nnd(iy) + 2*m_nelx(iy)*m_nelz(iy); - ++j; - } - } - // -- top node layer - for ( size_t ix = 1 ; ix < m_nelx(iy) ; ++ix ) { - out(j) = m_startNode(iy+1) + ix + (m_nelx(iy)+1)*m_nelz(iy); - ++j; - } - } - - return out; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesLeftFace() const + return nodesBackBottomLeftCorner(); +} +inline size_t Regular::nodesLeftBackBottomCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // number of boundary nodes - // - initialize - size_t n = 0; - // - bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - { - if ( m_refine(iy) == 2 ) n += m_nelz(iy) * 3 - 1; - else n += m_nelz(iy) - 1; - } - // - top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - { - if ( m_refine(iy) == 2 ) n += m_nelz(iy) * 3 - 1; - else n += m_nelz(iy) - 1; - } - - // allocate node-list - xt::xtensor out = xt::empty({n}); - - // initialize counter: current index in the node-list "out" - size_t j = 0; - - // bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - { - // -- bottom node layer - for ( size_t iz = 1 ; iz < m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy) + iz * (m_nelx(iy)+1); - ++j; - } - // -- refinement layer - if ( m_refine(iy) == 2 ) { - for ( size_t iz = 0 ; iz < 2*m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy) + iz * (m_nelx(iy)+1) + m_nnd(iy); - ++j; - } - } - } - - // top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - { - // -- refinement layer - if ( m_refine(iy) == 2 ) { - for ( size_t iz = 0 ; iz < 2*m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy) + iz * (m_nelx(iy)+1) + m_nnd(iy); - ++j; - } - } - // -- top node layer - for ( size_t iz = 1 ; iz < m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy+1) + iz * (m_nelx(iy)+1); - ++j; - } - } - - return out; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesRightFace() const + return nodesBackBottomLeftCorner(); +} +inline size_t Regular::nodesLeftBottomBackCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // number of boundary nodes - // - initialize - size_t n = 0; - // - bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - { - if ( m_refine(iy) == 2 ) n += m_nelz(iy) * 3 - 1; - else n += m_nelz(iy) - 1; - } - // - top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - { - if ( m_refine(iy) == 2 ) n += m_nelz(iy) * 3 - 1; - else n += m_nelz(iy) - 1; - } - - // allocate node-list - xt::xtensor out = xt::empty({n}); - - // initialize counter: current index in the node-list "out" - size_t j = 0; - - // bottom half: bottom node layer (+ middle node layer) - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - { - // -- bottom node layer - for ( size_t iz = 1 ; iz < m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy) + iz * (m_nelx(iy)+1) + m_nelx(iy); - ++j; - } - // -- refinement layer - if ( m_refine(iy) == 2 ) { - for ( size_t iz = 0 ; iz < 2*m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy) + m_nnd(iy) + iz * (m_nelx(iy)+1) + m_nelx(iy); - ++j; - } - } - } - - // top half: (middle node layer +) top node layer - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - { - // -- refinement layer - if ( m_refine(iy) == 2 ) { - for ( size_t iz = 0 ; iz < 2*m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy) + m_nnd(iy) + iz * (m_nelx(iy)+1) + m_nelx(iy); - ++j; - } - } - // -- top node layer - for ( size_t iz = 1 ; iz < m_nelz(iy) ; ++iz ) { - out(j) = m_startNode(iy+1) + iz * (m_nelx(iy)+1) + m_nelx(iy); - ++j; - } - } - - return out; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesBottomFace() const + return nodesBackBottomLeftCorner(); +} +inline size_t Regular::nodesBackRightBottomCorner() const { - // allocate node list - xt::xtensor out = xt::empty({(m_nelx(0)-1)*(m_nelz(0)-1)}); - - // counter - size_t j = 0; - - // fill node list - for ( size_t ix = 1 ; ix < m_nelx(0) ; ++ix ) { - for ( size_t iz = 1 ; iz < m_nelz(0) ; ++iz ) { - out(j) = m_startNode(0) + ix + iz * (m_nelx(0)+1); - ++j; - } - } - - return out; + return nodesBackBottomRightCorner(); } - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesTopFace() const +inline size_t Regular::nodesBottomBackRightCorner() const { - // number of element layers in y-direction - size_t nely = static_cast(m_nhy.size()); - - // allocate node list - xt::xtensor out = xt::empty({(m_nelx(nely-1)-1)*(m_nelz(nely-1)-1)}); - - // counter - size_t j = 0; - - // fill node list - for ( size_t ix = 1 ; ix < m_nelx(nely-1) ; ++ix ) { - for ( size_t iz = 1 ; iz < m_nelz(nely-1) ; ++iz ) { - out(j) = m_startNode(nely) + ix + iz * (m_nelx(nely-1)+1); - ++j; + return nodesBackBottomRightCorner(); +} +inline size_t Regular::nodesBottomRightBackCorner() const +{ + return nodesBackBottomRightCorner(); +} +inline size_t Regular::nodesRightBackBottomCorner() const +{ + return nodesBackBottomRightCorner(); +} +inline size_t Regular::nodesRightBottomBackCorner() const +{ + return nodesBackBottomRightCorner(); +} +inline size_t Regular::nodesBackLeftTopCorner() const +{ + return nodesBackTopLeftCorner(); +} +inline size_t Regular::nodesTopBackLeftCorner() const +{ + return nodesBackTopLeftCorner(); +} +inline size_t Regular::nodesTopLeftBackCorner() const +{ + return nodesBackTopLeftCorner(); +} +inline size_t Regular::nodesLeftBackTopCorner() const +{ + return nodesBackTopLeftCorner(); +} +inline size_t Regular::nodesLeftTopBackCorner() const +{ + return nodesBackTopLeftCorner(); +} +inline size_t Regular::nodesBackRightTopCorner() const +{ + return nodesBackTopRightCorner(); +} +inline size_t Regular::nodesTopBackRightCorner() const +{ + return nodesBackTopRightCorner(); +} +inline size_t Regular::nodesTopRightBackCorner() const +{ + return nodesBackTopRightCorner(); +} +inline size_t Regular::nodesRightBackTopCorner() const +{ + return nodesBackTopRightCorner(); +} +inline size_t Regular::nodesRightTopBackCorner() const +{ + return nodesBackTopRightCorner(); +} + +inline xt::xtensor Regular::nodesPeriodic() const +{ + xt::xtensor fro = nodesFrontFace(); + xt::xtensor bck = nodesBackFace(); + xt::xtensor lft = nodesLeftFace(); + xt::xtensor rgt = nodesRightFace(); + xt::xtensor bot = nodesBottomFace(); + xt::xtensor top = nodesTopFace(); + + xt::xtensor froBot = nodesFrontBottomOpenEdge(); + xt::xtensor froTop = nodesFrontTopOpenEdge(); + xt::xtensor froLft = nodesFrontLeftOpenEdge(); + xt::xtensor froRgt = nodesFrontRightOpenEdge(); + xt::xtensor bckBot = nodesBackBottomOpenEdge(); + xt::xtensor bckTop = nodesBackTopOpenEdge(); + xt::xtensor bckLft = nodesBackLeftOpenEdge(); + xt::xtensor bckRgt = nodesBackRightOpenEdge(); + xt::xtensor botLft = nodesBottomLeftOpenEdge(); + xt::xtensor botRgt = nodesBottomRightOpenEdge(); + xt::xtensor topLft = nodesTopLeftOpenEdge(); + xt::xtensor topRgt = nodesTopRightOpenEdge(); + + size_t tface = fro.size() + lft.size() + bot.size(); + size_t tedge = 3 * froBot.size() + 3 * froLft.size() + 3 * botLft.size(); + size_t tnode = 7; + xt::xtensor out = xt::empty({tface + tedge + tnode, std::size_t(2)}); + + size_t i = 0; + + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesFrontBottomRightCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesBackBottomRightCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesBackBottomLeftCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesFrontTopLeftCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesFrontTopRightCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesBackTopRightCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesBackTopLeftCorner(); + ++i; + + for (size_t j = 0; j < froBot.size(); ++j) { + out(i, 0) = froBot(j); + out(i, 1) = bckBot(j); + ++i; + } + for (size_t j = 0; j < froBot.size(); ++j) { + out(i, 0) = froBot(j); + out(i, 1) = bckTop(j); + ++i; + } + for (size_t j = 0; j < froBot.size(); ++j) { + out(i, 0) = froBot(j); + out(i, 1) = froTop(j); + ++i; + } + for (size_t j = 0; j < botLft.size(); ++j) { + out(i, 0) = botLft(j); + out(i, 1) = botRgt(j); + ++i; + } + for (size_t j = 0; j < botLft.size(); ++j) { + out(i, 0) = botLft(j); + out(i, 1) = topRgt(j); + ++i; + } + for (size_t j = 0; j < botLft.size(); ++j) { + out(i, 0) = botLft(j); + out(i, 1) = topLft(j); + ++i; + } + for (size_t j = 0; j < froLft.size(); ++j) { + out(i, 0) = froLft(j); + out(i, 1) = froRgt(j); + ++i; + } + for (size_t j = 0; j < froLft.size(); ++j) { + out(i, 0) = froLft(j); + out(i, 1) = bckRgt(j); + ++i; + } + for (size_t j = 0; j < froLft.size(); ++j) { + out(i, 0) = froLft(j); + out(i, 1) = bckLft(j); + ++i; + } + + for (size_t j = 0; j < fro.size(); ++j) { + out(i, 0) = fro(j); + out(i, 1) = bck(j); + ++i; + } + for (size_t j = 0; j < lft.size(); ++j) { + out(i, 0) = lft(j); + out(i, 1) = rgt(j); + ++i; + } + for (size_t j = 0; j < bot.size(); ++j) { + out(i, 0) = bot(j); + out(i, 1) = top(j); + ++i; + } + + return out; +} + +inline size_t Regular::nodesOrigin() const +{ + return nodesFrontBottomLeftCorner(); +} + +inline xt::xtensor Regular::dofs() const +{ + return GooseFEM::Mesh::dofs(m_nnode, m_ndim); +} + +inline xt::xtensor Regular::dofsPeriodic() const +{ + xt::xtensor out = GooseFEM::Mesh::dofs(m_nnode, m_ndim); + xt::xtensor nodePer = nodesPeriodic(); + + for (size_t i = 0; i < nodePer.shape(0); ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + out(nodePer(i, 1), j) = out(nodePer(i, 0), j); + } + } + + return GooseFEM::Mesh::renumber(out); +} + +inline FineLayer::FineLayer(size_t nelx, size_t nely, size_t nelz, double h, size_t nfine) : m_h(h) +{ + // basic assumptions + GOOSEFEM_ASSERT(nelx >= 1ul); + GOOSEFEM_ASSERT(nely >= 1ul); + GOOSEFEM_ASSERT(nelz >= 1ul); + + // store basic info + m_Lx = m_h * static_cast(nelx); + m_Lz = m_h * static_cast(nelz); + + // compute element size in y-direction (use symmetry, compute upper half) + + // temporary variables + size_t nmin, ntot; + xt::xtensor nhx = xt::ones({nely}); + xt::xtensor nhy = xt::ones({nely}); + xt::xtensor nhz = xt::ones({nely}); + xt::xtensor refine = -1 * xt::ones({nely}); + + // minimum height in y-direction (half of the height because of symmetry) + if (nely % 2 == 0) { + nmin = nely / 2; + } + else { + nmin = (nely + 1) / 2; + } + + // minimum number of fine layers in y-direction (minimum 1, middle layer part of this half) + if (nfine % 2 == 0) { + nfine = nfine / 2 + 1; + } + else { + nfine = (nfine + 1) / 2; + } + + if (nfine < 1) { + nfine = 1; + } + + if (nfine > nmin) { + nfine = nmin; + } + + // loop over element layers in y-direction, try to coarsen using these rules: + // (1) element size in y-direction <= distance to origin in y-direction + // (2) element size in x-(z-)direction should fit the total number of elements in + // x-(z-)direction (3) a certain number of layers have the minimum size "1" (are fine) + for (size_t iy = nfine;;) { + // initialize current size in y-direction + if (iy == nfine) { + ntot = nfine; + } + // check to stop + if (iy >= nely || ntot >= nmin) { + nely = iy; + break; + } + + // rules (1,2) satisfied: coarsen in x-direction (and z-direction) + if (3 * nhy(iy) <= ntot && nelx % (3 * nhx(iy)) == 0 && ntot + nhy(iy) < nmin) { + // - process refinement in x-direction + refine(iy) = 0; + nhy(iy) *= 2; + auto vnhy = xt::view(nhy, xt::range(iy + 1, _)); + auto vnhx = xt::view(nhx, xt::range(iy, _)); + vnhy *= 3; + vnhx *= 3; + + // - rule (2) satisfied: coarsen next element layer in z-direction + if (iy + 1 < nely && ntot + 2 * nhy(iy) < nmin) { + if (nelz % (3 * nhz(iy + 1)) == 0) { + // - update the number of elements in y-direction + ntot += nhy(iy); + // - proceed to next element layer in y-direction + ++iy; + // - process refinement in z-direction + refine(iy) = 2; + nhy(iy) = nhy(iy - 1); + auto vnhz = xt::view(nhz, xt::range(iy, _)); + vnhz *= 3; + } + } + } + + // rules (1,2) satisfied: coarse in z-direction + else if (3 * nhy(iy) <= ntot && nelz % (3 * nhz(iy)) == 0 && ntot + nhy(iy) < nmin) { + // - process refinement in z-direction + refine(iy) = 2; + nhy(iy) *= 2; + auto vnhy = xt::view(nhy, xt::range(iy + 1, _)); + auto vnhz = xt::view(nhz, xt::range(iy, _)); + vnhy *= 3; + vnhz *= 3; + } + + // update the number of elements in y-direction + ntot += nhy(iy); + // proceed to next element layer in y-direction + ++iy; + // check to stop + if (iy >= nely || ntot >= nmin) { + nely = iy; + break; + } + } + + // symmetrize, compute full information + + // allocate mesh constructor parameters + m_nhx = xt::empty({nely * 2 - 1}); + m_nhy = xt::empty({nely * 2 - 1}); + m_nhz = xt::empty({nely * 2 - 1}); + m_refine = xt::empty({nely * 2 - 1}); + m_nelx = xt::empty({nely * 2 - 1}); + m_nelz = xt::empty({nely * 2 - 1}); + m_nnd = xt::empty({nely * 2}); + m_startElem = xt::empty({nely * 2 - 1}); + m_startNode = xt::empty({nely * 2}); + + // fill + // - lower half + for (size_t iy = 0; iy < nely; ++iy) { + m_nhx(iy) = nhx(nely - iy - 1); + m_nhy(iy) = nhy(nely - iy - 1); + m_nhz(iy) = nhz(nely - iy - 1); + m_refine(iy) = refine(nely - iy - 1); + } + // - upper half + for (size_t iy = 0; iy < nely - 1; ++iy) { + m_nhx(iy + nely) = nhx(iy + 1); + m_nhy(iy + nely) = nhy(iy + 1); + m_nhz(iy + nely) = nhz(iy + 1); + m_refine(iy + nely) = refine(iy + 1); + } + + // update size + nely = m_nhx.size(); + + // compute the number of elements per element layer in y-direction + for (size_t iy = 0; iy < nely; ++iy) { + m_nelx(iy) = nelx / m_nhx(iy); + m_nelz(iy) = nelz / m_nhz(iy); + } + + // compute the number of nodes per node layer in y-direction + // - bottom half + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) + m_nnd(iy) = (m_nelx(iy) + 1) * (m_nelz(iy) + 1); + // - top half + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) + m_nnd(iy + 1) = (m_nelx(iy) + 1) * (m_nelz(iy) + 1); + + // compute mesh dimensions + + // initialize + m_nnode = 0; + m_nelem = 0; + m_startNode(0) = 0; + + // loop over element layers (bottom -> middle, elements become finer) + for (size_t i = 0; i < (nely - 1) / 2; ++i) { + // - store the first element of the layer + m_startElem(i) = m_nelem; + // - add the nodes of this layer + if (m_refine(i) == 0) { + m_nnode += (3 * m_nelx(i) + 1) * (m_nelz(i) + 1); + } + else if (m_refine(i) == 2) { + m_nnode += (m_nelx(i) + 1) * (3 * m_nelz(i) + 1); + } + else { + m_nnode += (m_nelx(i) + 1) * (m_nelz(i) + 1); + } + // - add the elements of this layer + if (m_refine(i) == 0) { + m_nelem += (4 * m_nelx(i)) * (m_nelz(i)); + } + else if (m_refine(i) == 2) { + m_nelem += (m_nelx(i)) * (4 * m_nelz(i)); + } + else { + m_nelem += (m_nelx(i)) * (m_nelz(i)); + } + // - store the starting node of the next layer + m_startNode(i + 1) = m_nnode; + } + + // loop over element layers (middle -> top, elements become coarser) + for (size_t i = (nely - 1) / 2; i < nely; ++i) { + // - store the first element of the layer + m_startElem(i) = m_nelem; + // - add the nodes of this layer + if (m_refine(i) == 0) { + m_nnode += (5 * m_nelx(i) + 1) * (m_nelz(i) + 1); + } + else if (m_refine(i) == 2) { + m_nnode += (m_nelx(i) + 1) * (5 * m_nelz(i) + 1); + } + else { + m_nnode += (m_nelx(i) + 1) * (m_nelz(i) + 1); + } + // - add the elements of this layer + if (m_refine(i) == 0) { + m_nelem += (4 * m_nelx(i)) * (m_nelz(i)); + } + else if (m_refine(i) == 2) { + m_nelem += (m_nelx(i)) * (4 * m_nelz(i)); + } + else { + m_nelem += (m_nelx(i)) * (m_nelz(i)); + } + // - store the starting node of the next layer + m_startNode(i + 1) = m_nnode; + } + // - add the top row of nodes + m_nnode += (m_nelx(nely - 1) + 1) * (m_nelz(nely - 1) + 1); +} + +inline size_t FineLayer::nelem() const +{ + return m_nelem; +} + +inline size_t FineLayer::nnode() const +{ + return m_nnode; +} + +inline size_t FineLayer::nne() const +{ + return m_nne; +} + +inline size_t FineLayer::ndim() const +{ + return m_ndim; +} + +inline size_t FineLayer::nelx() const +{ + return xt::amax(m_nelx)[0]; +} + +inline size_t FineLayer::nely() const +{ + return xt::sum(m_nhy)[0]; +} + +inline size_t FineLayer::nelz() const +{ + return xt::amax(m_nelz)[0]; +} + +inline ElementType FineLayer::getElementType() const +{ + return ElementType::Hex8; +} + +inline xt::xtensor FineLayer::coor() const +{ + // allocate output + xt::xtensor out = xt::empty({m_nnode, m_ndim}); + + // current node, number of element layers + size_t inode = 0; + size_t nely = static_cast(m_nhy.size()); + + // y-position of each main node layer (i.e. excluding node layers for refinement/coarsening) + // - allocate + xt::xtensor y = xt::empty({nely + 1}); + // - initialize + y(0) = 0.0; + // - compute + for (size_t iy = 1; iy < nely + 1; ++iy) { + y(iy) = y(iy - 1) + m_nhy(iy - 1) * m_h; + } + + // loop over element layers (bottom -> middle) : add bottom layer (+ refinement layer) of nodes + + for (size_t iy = 0;; ++iy) { + // get positions along the x- and z-axis + xt::xtensor x = xt::linspace(0.0, m_Lx, m_nelx(iy) + 1); + xt::xtensor z = xt::linspace(0.0, m_Lz, m_nelz(iy) + 1); + + // add nodes of the bottom layer of this element + for (size_t iz = 0; iz < m_nelz(iy) + 1; ++iz) { + for (size_t ix = 0; ix < m_nelx(iy) + 1; ++ix) { + out(inode, 0) = x(ix); + out(inode, 1) = y(iy); + out(inode, 2) = z(iz); + ++inode; + } + } + + // stop at middle layer + if (iy == (nely - 1) / 2) { + break; + } + + // add extra nodes of the intermediate layer, for refinement in x-direction + if (m_refine(iy) == 0) { + // - get position offset in x- and y-direction + double dx = m_h * static_cast(m_nhx(iy) / 3); + double dy = m_h * static_cast(m_nhy(iy) / 2); + // - add nodes of the intermediate layer + for (size_t iz = 0; iz < m_nelz(iy) + 1; ++iz) { + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + for (size_t j = 0; j < 2; ++j) { + out(inode, 0) = x(ix) + dx * static_cast(j + 1); + out(inode, 1) = y(iy) + dy; + out(inode, 2) = z(iz); + ++inode; + } + } + } + } + + // add extra nodes of the intermediate layer, for refinement in z-direction + else if (m_refine(iy) == 2) { + // - get position offset in y- and z-direction + double dz = m_h * static_cast(m_nhz(iy) / 3); + double dy = m_h * static_cast(m_nhy(iy) / 2); + // - add nodes of the intermediate layer + for (size_t iz = 0; iz < m_nelz(iy); ++iz) { + for (size_t j = 0; j < 2; ++j) { + for (size_t ix = 0; ix < m_nelx(iy) + 1; ++ix) { + out(inode, 0) = x(ix); + out(inode, 1) = y(iy) + dy; + out(inode, 2) = z(iz) + dz * static_cast(j + 1); + ++inode; + } + } + } + } + } + + // loop over element layers (middle -> top) : add (refinement layer +) top layer of nodes + + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + // get positions along the x- and z-axis + xt::xtensor x = xt::linspace(0.0, m_Lx, m_nelx(iy) + 1); + xt::xtensor z = xt::linspace(0.0, m_Lz, m_nelz(iy) + 1); + + // add extra nodes of the intermediate layer, for refinement in x-direction + if (m_refine(iy) == 0) { + // - get position offset in x- and y-direction + double dx = m_h * static_cast(m_nhx(iy) / 3); + double dy = m_h * static_cast(m_nhy(iy) / 2); + // - add nodes of the intermediate layer + for (size_t iz = 0; iz < m_nelz(iy) + 1; ++iz) { + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + for (size_t j = 0; j < 2; ++j) { + out(inode, 0) = x(ix) + dx * static_cast(j + 1); + out(inode, 1) = y(iy) + dy; + out(inode, 2) = z(iz); + ++inode; + } + } + } + } + + // add extra nodes of the intermediate layer, for refinement in z-direction + else if (m_refine(iy) == 2) { + // - get position offset in y- and z-direction + double dz = m_h * static_cast(m_nhz(iy) / 3); + double dy = m_h * static_cast(m_nhy(iy) / 2); + // - add nodes of the intermediate layer + for (size_t iz = 0; iz < m_nelz(iy); ++iz) { + for (size_t j = 0; j < 2; ++j) { + for (size_t ix = 0; ix < m_nelx(iy) + 1; ++ix) { + out(inode, 0) = x(ix); + out(inode, 1) = y(iy) + dy; + out(inode, 2) = z(iz) + dz * static_cast(j + 1); + ++inode; + } + } + } + } + + // add nodes of the top layer of this element + for (size_t iz = 0; iz < m_nelz(iy) + 1; ++iz) { + for (size_t ix = 0; ix < m_nelx(iy) + 1; ++ix) { + out(inode, 0) = x(ix); + out(inode, 1) = y(iy + 1); + out(inode, 2) = z(iz); + ++inode; + } + } + } + + return out; +} + +inline xt::xtensor FineLayer::conn() const +{ + // allocate output + xt::xtensor out = xt::empty({m_nelem, m_nne}); + + // current element, number of element layers, starting nodes of each node layer + size_t ielem = 0; + size_t nely = static_cast(m_nhy.size()); + size_t bot, mid, top; + + // loop over all element layers + for (size_t iy = 0; iy < nely; ++iy) { + // - get: starting nodes of bottom(, middle) and top layer + bot = m_startNode(iy); + mid = m_startNode(iy) + m_nnd(iy); + top = m_startNode(iy + 1); + + // - define connectivity: no coarsening/refinement + if (m_refine(iy) == -1) { + for (size_t iz = 0; iz < m_nelz(iy); ++iz) { + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + out(ielem, 0) = bot + ix + iz * (m_nelx(iy) + 1); + out(ielem, 1) = bot + (ix + 1) + iz * (m_nelx(iy) + 1); + out(ielem, 2) = top + (ix + 1) + iz * (m_nelx(iy) + 1); + out(ielem, 3) = top + ix + iz * (m_nelx(iy) + 1); + out(ielem, 4) = bot + ix + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 5) = bot + (ix + 1) + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 6) = top + (ix + 1) + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 7) = top + ix + (iz + 1) * (m_nelx(iy) + 1); + ielem++; + } + } + } + + // - define connectivity: refinement along the x-direction (below the middle layer) + else if (m_refine(iy) == 0 && iy <= (nely - 1) / 2) { + for (size_t iz = 0; iz < m_nelz(iy); ++iz) { + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + // -- bottom element + out(ielem, 0) = bot + ix + iz * (m_nelx(iy) + 1); + out(ielem, 1) = bot + (ix + 1) + iz * (m_nelx(iy) + 1); + out(ielem, 2) = mid + (2 * ix + 1) + iz * (2 * m_nelx(iy)); + out(ielem, 3) = mid + (2 * ix) + iz * (2 * m_nelx(iy)); + out(ielem, 4) = bot + ix + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 5) = bot + (ix + 1) + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 6) = mid + (2 * ix + 1) + (iz + 1) * (2 * m_nelx(iy)); + out(ielem, 7) = mid + (2 * ix) + (iz + 1) * (2 * m_nelx(iy)); + ielem++; + // -- top-right element + out(ielem, 0) = bot + (ix + 1) + iz * (m_nelx(iy) + 1); + out(ielem, 1) = top + (3 * ix + 3) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 2) = top + (3 * ix + 2) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 3) = mid + (2 * ix + 1) + iz * (2 * m_nelx(iy)); + out(ielem, 4) = bot + (ix + 1) + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 5) = top + (3 * ix + 3) + (iz + 1) * (3 * m_nelx(iy) + 1); + out(ielem, 6) = top + (3 * ix + 2) + (iz + 1) * (3 * m_nelx(iy) + 1); + out(ielem, 7) = mid + (2 * ix + 1) + (iz + 1) * (2 * m_nelx(iy)); + ielem++; + // -- top-center element + out(ielem, 0) = mid + (2 * ix) + iz * (2 * m_nelx(iy)); + out(ielem, 1) = mid + (2 * ix + 1) + iz * (2 * m_nelx(iy)); + out(ielem, 2) = top + (3 * ix + 2) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 3) = top + (3 * ix + 1) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 4) = mid + (2 * ix) + (iz + 1) * (2 * m_nelx(iy)); + out(ielem, 5) = mid + (2 * ix + 1) + (iz + 1) * (2 * m_nelx(iy)); + out(ielem, 6) = top + (3 * ix + 2) + (iz + 1) * (3 * m_nelx(iy) + 1); + out(ielem, 7) = top + (3 * ix + 1) + (iz + 1) * (3 * m_nelx(iy) + 1); + ielem++; + // -- top-left element + out(ielem, 0) = bot + ix + iz * (m_nelx(iy) + 1); + out(ielem, 1) = mid + (2 * ix) + iz * (2 * m_nelx(iy)); + out(ielem, 2) = top + (3 * ix + 1) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 3) = top + (3 * ix) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 4) = bot + ix + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 5) = mid + (2 * ix) + (iz + 1) * (2 * m_nelx(iy)); + out(ielem, 6) = top + (3 * ix + 1) + (iz + 1) * (3 * m_nelx(iy) + 1); + out(ielem, 7) = top + (3 * ix) + (iz + 1) * (3 * m_nelx(iy) + 1); + ielem++; + } + } + } + + // - define connectivity: coarsening along the x-direction (above the middle layer) + else if (m_refine(iy) == 0 && iy > (nely - 1) / 2) { + for (size_t iz = 0; iz < m_nelz(iy); ++iz) { + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + // -- lower-left element + out(ielem, 0) = bot + (3 * ix) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 1) = bot + (3 * ix + 1) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 2) = mid + (2 * ix) + iz * (2 * m_nelx(iy)); + out(ielem, 3) = top + ix + iz * (m_nelx(iy) + 1); + out(ielem, 4) = bot + (3 * ix) + (iz + 1) * (3 * m_nelx(iy) + 1); + out(ielem, 5) = bot + (3 * ix + 1) + (iz + 1) * (3 * m_nelx(iy) + 1); + out(ielem, 6) = mid + (2 * ix) + (iz + 1) * (2 * m_nelx(iy)); + out(ielem, 7) = top + ix + (iz + 1) * (m_nelx(iy) + 1); + ielem++; + // -- lower-center element + out(ielem, 0) = bot + (3 * ix + 1) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 1) = bot + (3 * ix + 2) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 2) = mid + (2 * ix + 1) + iz * (2 * m_nelx(iy)); + out(ielem, 3) = mid + (2 * ix) + iz * (2 * m_nelx(iy)); + out(ielem, 4) = bot + (3 * ix + 1) + (iz + 1) * (3 * m_nelx(iy) + 1); + out(ielem, 5) = bot + (3 * ix + 2) + (iz + 1) * (3 * m_nelx(iy) + 1); + out(ielem, 6) = mid + (2 * ix + 1) + (iz + 1) * (2 * m_nelx(iy)); + out(ielem, 7) = mid + (2 * ix) + (iz + 1) * (2 * m_nelx(iy)); + ielem++; + // -- lower-right element + out(ielem, 0) = bot + (3 * ix + 2) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 1) = bot + (3 * ix + 3) + iz * (3 * m_nelx(iy) + 1); + out(ielem, 2) = top + (ix + 1) + iz * (m_nelx(iy) + 1); + out(ielem, 3) = mid + (2 * ix + 1) + iz * (2 * m_nelx(iy)); + out(ielem, 4) = bot + (3 * ix + 2) + (iz + 1) * (3 * m_nelx(iy) + 1); + out(ielem, 5) = bot + (3 * ix + 3) + (iz + 1) * (3 * m_nelx(iy) + 1); + out(ielem, 6) = top + (ix + 1) + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 7) = mid + (2 * ix + 1) + (iz + 1) * (2 * m_nelx(iy)); + ielem++; + // -- upper element + out(ielem, 0) = mid + (2 * ix) + iz * (2 * m_nelx(iy)); + out(ielem, 1) = mid + (2 * ix + 1) + iz * (2 * m_nelx(iy)); + out(ielem, 2) = top + (ix + 1) + iz * (m_nelx(iy) + 1); + out(ielem, 3) = top + ix + iz * (m_nelx(iy) + 1); + out(ielem, 4) = mid + (2 * ix) + (iz + 1) * (2 * m_nelx(iy)); + out(ielem, 5) = mid + (2 * ix + 1) + (iz + 1) * (2 * m_nelx(iy)); + out(ielem, 6) = top + (ix + 1) + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 7) = top + ix + (iz + 1) * (m_nelx(iy) + 1); + ielem++; + } + } + } + + // - define connectivity: refinement along the z-direction (below the middle layer) + else if (m_refine(iy) == 2 && iy <= (nely - 1) / 2) { + for (size_t iz = 0; iz < m_nelz(iy); ++iz) { + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + // -- bottom element + out(ielem, 0) = bot + ix + iz * (m_nelx(iy) + 1); + out(ielem, 1) = bot + ix + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 2) = bot + (ix + 1) + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 3) = bot + (ix + 1) + iz * (m_nelx(iy) + 1); + out(ielem, 4) = mid + ix + 2 * iz * (m_nelx(iy) + 1); + out(ielem, 5) = mid + ix + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 6) = mid + (ix + 1) + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 7) = mid + (ix + 1) + 2 * iz * (m_nelx(iy) + 1); + ielem++; + // -- top-back element + out(ielem, 0) = mid + ix + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 1) = mid + (ix + 1) + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 2) = top + (ix + 1) + (3 * iz + 2) * (m_nelx(iy) + 1); + out(ielem, 3) = top + ix + (3 * iz + 2) * (m_nelx(iy) + 1); + out(ielem, 4) = bot + ix + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 5) = bot + (ix + 1) + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 6) = top + (ix + 1) + (3 * iz + 3) * (m_nelx(iy) + 1); + out(ielem, 7) = top + ix + (3 * iz + 3) * (m_nelx(iy) + 1); + ielem++; + // -- top-center element + out(ielem, 0) = mid + ix + (2 * iz) * (m_nelx(iy) + 1); + out(ielem, 1) = mid + (ix + 1) + (2 * iz) * (m_nelx(iy) + 1); + out(ielem, 2) = top + (ix + 1) + (3 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 3) = top + ix + (3 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 4) = mid + ix + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 5) = mid + (ix + 1) + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 6) = top + (ix + 1) + (3 * iz + 2) * (m_nelx(iy) + 1); + out(ielem, 7) = top + ix + (3 * iz + 2) * (m_nelx(iy) + 1); + ielem++; + // -- top-front element + out(ielem, 0) = bot + ix + iz * (m_nelx(iy) + 1); + out(ielem, 1) = bot + (ix + 1) + iz * (m_nelx(iy) + 1); + out(ielem, 2) = top + (ix + 1) + (3 * iz) * (m_nelx(iy) + 1); + out(ielem, 3) = top + ix + (3 * iz) * (m_nelx(iy) + 1); + out(ielem, 4) = mid + ix + (2 * iz) * (m_nelx(iy) + 1); + out(ielem, 5) = mid + (ix + 1) + (2 * iz) * (m_nelx(iy) + 1); + out(ielem, 6) = top + (ix + 1) + (3 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 7) = top + ix + (3 * iz + 1) * (m_nelx(iy) + 1); + ielem++; + } + } + } + + // - define connectivity: coarsening along the z-direction (above the middle layer) + else if (m_refine(iy) == 2 && iy > (nely - 1) / 2) { + for (size_t iz = 0; iz < m_nelz(iy); ++iz) { + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + // -- bottom-front element + out(ielem, 0) = bot + ix + (3 * iz) * (m_nelx(iy) + 1); + out(ielem, 1) = bot + (ix + 1) + (3 * iz) * (m_nelx(iy) + 1); + out(ielem, 2) = top + (ix + 1) + iz * (m_nelx(iy) + 1); + out(ielem, 3) = top + ix + iz * (m_nelx(iy) + 1); + out(ielem, 4) = bot + ix + (3 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 5) = bot + (ix + 1) + (3 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 6) = mid + (ix + 1) + (2 * iz) * (m_nelx(iy) + 1); + out(ielem, 7) = mid + ix + (2 * iz) * (m_nelx(iy) + 1); + ielem++; + // -- bottom-center element + out(ielem, 0) = bot + ix + (3 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 1) = bot + (ix + 1) + (3 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 2) = mid + (ix + 1) + (2 * iz) * (m_nelx(iy) + 1); + out(ielem, 3) = mid + ix + (2 * iz) * (m_nelx(iy) + 1); + out(ielem, 4) = bot + ix + (3 * iz + 2) * (m_nelx(iy) + 1); + out(ielem, 5) = bot + (ix + 1) + (3 * iz + 2) * (m_nelx(iy) + 1); + out(ielem, 6) = mid + (ix + 1) + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 7) = mid + ix + (2 * iz + 1) * (m_nelx(iy) + 1); + ielem++; + // -- bottom-back element + out(ielem, 0) = bot + ix + (3 * iz + 2) * (m_nelx(iy) + 1); + out(ielem, 1) = bot + (ix + 1) + (3 * iz + 2) * (m_nelx(iy) + 1); + out(ielem, 2) = mid + (ix + 1) + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 3) = mid + ix + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 4) = bot + ix + (3 * iz + 3) * (m_nelx(iy) + 1); + out(ielem, 5) = bot + (ix + 1) + (3 * iz + 3) * (m_nelx(iy) + 1); + out(ielem, 6) = top + (ix + 1) + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 7) = top + ix + (iz + 1) * (m_nelx(iy) + 1); + ielem++; + // -- top element + out(ielem, 0) = mid + ix + (2 * iz) * (m_nelx(iy) + 1); + out(ielem, 1) = mid + (ix + 1) + (2 * iz) * (m_nelx(iy) + 1); + out(ielem, 2) = top + (ix + 1) + iz * (m_nelx(iy) + 1); + out(ielem, 3) = top + ix + iz * (m_nelx(iy) + 1); + out(ielem, 4) = mid + ix + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 5) = mid + (ix + 1) + (2 * iz + 1) * (m_nelx(iy) + 1); + out(ielem, 6) = top + (ix + 1) + (iz + 1) * (m_nelx(iy) + 1); + out(ielem, 7) = top + ix + (iz + 1) * (m_nelx(iy) + 1); + ielem++; + } + } + } + } + + return out; +} + +inline xt::xtensor FineLayer::elementsMiddleLayer() const +{ + size_t nely = static_cast(m_nhy.size()); + size_t iy = (nely - 1) / 2; + + xt::xtensor out = xt::empty({m_nelx(iy) * m_nelz(iy)}); + + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + for (size_t iz = 0; iz < m_nelz(iy); ++iz) { + out(ix + iz * m_nelx(iy)) = m_startElem(iy) + ix + iz * m_nelx(iy); + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesFront() const +{ + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); + + // number of boundary nodes + // - initialize + size_t n = 0; + // - bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + if (m_refine(iy) == 0) { + n += m_nelx(iy) * 3 + 1; + } + else { + n += m_nelx(iy) + 1; + } + } + // - top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + if (m_refine(iy) == 0) { + n += m_nelx(iy) * 3 + 1; + } + else { + n += m_nelx(iy) + 1; + } + } + + // allocate node-list + xt::xtensor out = xt::empty({n}); + + // initialize counter: current index in the node-list "out" + size_t j = 0; + + // bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + // -- bottom node layer + for (size_t ix = 0; ix < m_nelx(iy) + 1; ++ix) { + out(j) = m_startNode(iy) + ix; + ++j; + } + // -- refinement layer + if (m_refine(iy) == 0) { + for (size_t ix = 0; ix < 2 * m_nelx(iy); ++ix) { + out(j) = m_startNode(iy) + ix + m_nnd(iy); + ++j; + } + } + } + + // top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + // -- refinement layer + if (m_refine(iy) == 0) { + for (size_t ix = 0; ix < 2 * m_nelx(iy); ++ix) { + out(j) = m_startNode(iy) + ix + m_nnd(iy); + ++j; + } + } + // -- top node layer + for (size_t ix = 0; ix < m_nelx(iy) + 1; ++ix) { + out(j) = m_startNode(iy + 1) + ix; + ++j; + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesBack() const +{ + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); + + // number of boundary nodes + // - initialize + size_t n = 0; + // - bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + if (m_refine(iy) == 0) { + n += m_nelx(iy) * 3 + 1; + } + else { + n += m_nelx(iy) + 1; + } + } + // - top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + if (m_refine(iy) == 0) { + n += m_nelx(iy) * 3 + 1; + } + else { + n += m_nelx(iy) + 1; + } + } + + // allocate node-list + xt::xtensor out = xt::empty({n}); + + // initialize counter: current index in the node-list "out" + size_t j = 0; + + // bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + // -- bottom node layer + for (size_t ix = 0; ix < m_nelx(iy) + 1; ++ix) { + out(j) = m_startNode(iy) + ix + (m_nelx(iy) + 1) * m_nelz(iy); + ++j; + } + // -- refinement layer + if (m_refine(iy) == 0) { + for (size_t ix = 0; ix < 2 * m_nelx(iy); ++ix) { + out(j) = m_startNode(iy) + ix + m_nnd(iy) + 2 * m_nelx(iy) * m_nelz(iy); + ++j; + } + } + } + + // top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + // -- refinement layer + if (m_refine(iy) == 0) { + for (size_t ix = 0; ix < 2 * m_nelx(iy); ++ix) { + out(j) = m_startNode(iy) + ix + m_nnd(iy) + 2 * m_nelx(iy) * m_nelz(iy); + ++j; + } + } + // -- top node layer + for (size_t ix = 0; ix < m_nelx(iy) + 1; ++ix) { + out(j) = m_startNode(iy + 1) + ix + (m_nelx(iy) + 1) * m_nelz(iy); + ++j; + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesLeft() const +{ + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); + + // number of boundary nodes + // - initialize + size_t n = 0; + // - bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + if (m_refine(iy) == 2) { + n += m_nelz(iy) * 3 + 1; + } + else { + n += m_nelz(iy) + 1; + } + } + // - top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + if (m_refine(iy) == 2) { + n += m_nelz(iy) * 3 + 1; + } + else { + n += m_nelz(iy) + 1; + } + } + + // allocate node-list + xt::xtensor out = xt::empty({n}); + + // initialize counter: current index in the node-list "out" + size_t j = 0; + + // bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + // -- bottom node layer + for (size_t iz = 0; iz < m_nelz(iy) + 1; ++iz) { + out(j) = m_startNode(iy) + iz * (m_nelx(iy) + 1); + ++j; + } + // -- refinement layer + if (m_refine(iy) == 2) { + for (size_t iz = 0; iz < 2 * m_nelz(iy); ++iz) { + out(j) = m_startNode(iy) + iz * (m_nelx(iy) + 1) + m_nnd(iy); + ++j; + } + } + } + + // top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + // -- refinement layer + if (m_refine(iy) == 2) { + for (size_t iz = 0; iz < 2 * m_nelz(iy); ++iz) { + out(j) = m_startNode(iy) + iz * (m_nelx(iy) + 1) + m_nnd(iy); + ++j; + } + } + // -- top node layer + for (size_t iz = 0; iz < m_nelz(iy) + 1; ++iz) { + out(j) = m_startNode(iy + 1) + iz * (m_nelx(iy) + 1); + ++j; + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesRight() const +{ + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); + + // number of boundary nodes + // - initialize + size_t n = 0; + // - bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + if (m_refine(iy) == 2) + n += m_nelz(iy) * 3 + 1; + else + n += m_nelz(iy) + 1; + } + // - top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + if (m_refine(iy) == 2) + n += m_nelz(iy) * 3 + 1; + else + n += m_nelz(iy) + 1; + } + + // allocate node-list + xt::xtensor out = xt::empty({n}); + + // initialize counter: current index in the node-list "out" + size_t j = 0; + + // bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + // -- bottom node layer + for (size_t iz = 0; iz < m_nelz(iy) + 1; ++iz) { + out(j) = m_startNode(iy) + iz * (m_nelx(iy) + 1) + m_nelx(iy); + ++j; + } + // -- refinement layer + if (m_refine(iy) == 2) { + for (size_t iz = 0; iz < 2 * m_nelz(iy); ++iz) { + out(j) = m_startNode(iy) + m_nnd(iy) + iz * (m_nelx(iy) + 1) + m_nelx(iy); + ++j; + } + } + } + + // top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + // -- refinement layer + if (m_refine(iy) == 2) { + for (size_t iz = 0; iz < 2 * m_nelz(iy); ++iz) { + out(j) = m_startNode(iy) + m_nnd(iy) + iz * (m_nelx(iy) + 1) + m_nelx(iy); + ++j; + } + } + // -- top node layer + for (size_t iz = 0; iz < m_nelz(iy) + 1; ++iz) { + out(j) = m_startNode(iy + 1) + iz * (m_nelx(iy) + 1) + m_nelx(iy); + ++j; + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesBottom() const +{ + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); + + // allocate node list + xt::xtensor out = xt::empty({m_nnd(nely)}); + + // counter + size_t j = 0; + + // fill node list + for (size_t ix = 0; ix < m_nelx(0) + 1; ++ix) { + for (size_t iz = 0; iz < m_nelz(0) + 1; ++iz) { + out(j) = m_startNode(0) + ix + iz * (m_nelx(0) + 1); + ++j; + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesTop() const +{ + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); + + // allocate node list + xt::xtensor out = xt::empty({m_nnd(nely)}); + + // counter + size_t j = 0; + + // fill node list + for (size_t ix = 0; ix < m_nelx(nely - 1) + 1; ++ix) { + for (size_t iz = 0; iz < m_nelz(nely - 1) + 1; ++iz) { + out(j) = m_startNode(nely) + ix + iz * (m_nelx(nely - 1) + 1); + ++j; + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesFrontFace() const +{ + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); + + // number of boundary nodes + // - initialize + size_t n = 0; + // - bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + if (m_refine(iy) == 0) { + n += m_nelx(iy) * 3 - 1; + } + else { + n += m_nelx(iy) - 1; + } + } + // - top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + if (m_refine(iy) == 0) { + n += m_nelx(iy) * 3 - 1; + } + else { + n += m_nelx(iy) - 1; + } + } + + // allocate node-list + xt::xtensor out = xt::empty({n}); + + // initialize counter: current index in the node-list "out" + size_t j = 0; + + // bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + // -- bottom node layer + for (size_t ix = 1; ix < m_nelx(iy); ++ix) { + out(j) = m_startNode(iy) + ix; + ++j; + } + // -- refinement layer + if (m_refine(iy) == 0) { + for (size_t ix = 0; ix < 2 * m_nelx(iy); ++ix) { + out(j) = m_startNode(iy) + ix + m_nnd(iy); + ++j; + } + } + } + + // top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + // -- refinement layer + if (m_refine(iy) == 0) { + for (size_t ix = 0; ix < 2 * m_nelx(iy); ++ix) { + out(j) = m_startNode(iy) + ix + m_nnd(iy); + ++j; + } + } + // -- top node layer + for (size_t ix = 1; ix < m_nelx(iy); ++ix) { + out(j) = m_startNode(iy + 1) + ix; + ++j; + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesBackFace() const +{ + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); + + // number of boundary nodes + // - initialize + size_t n = 0; + // - bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + if (m_refine(iy) == 0) { + n += m_nelx(iy) * 3 - 1; + } + else { + n += m_nelx(iy) - 1; + } + } + // - top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + if (m_refine(iy) == 0) { + n += m_nelx(iy) * 3 - 1; + } + else { + n += m_nelx(iy) - 1; + } + } + + // allocate node-list + xt::xtensor out = xt::empty({n}); + + // initialize counter: current index in the node-list "out" + size_t j = 0; + + // bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + // -- bottom node layer + for (size_t ix = 1; ix < m_nelx(iy); ++ix) { + out(j) = m_startNode(iy) + ix + (m_nelx(iy) + 1) * m_nelz(iy); + ++j; + } + // -- refinement layer + if (m_refine(iy) == 0) { + for (size_t ix = 0; ix < 2 * m_nelx(iy); ++ix) { + out(j) = m_startNode(iy) + ix + m_nnd(iy) + 2 * m_nelx(iy) * m_nelz(iy); + ++j; + } + } + } + + // top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + // -- refinement layer + if (m_refine(iy) == 0) { + for (size_t ix = 0; ix < 2 * m_nelx(iy); ++ix) { + out(j) = m_startNode(iy) + ix + m_nnd(iy) + 2 * m_nelx(iy) * m_nelz(iy); + ++j; + } + } + // -- top node layer + for (size_t ix = 1; ix < m_nelx(iy); ++ix) { + out(j) = m_startNode(iy + 1) + ix + (m_nelx(iy) + 1) * m_nelz(iy); + ++j; + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesLeftFace() const +{ + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); + + // number of boundary nodes + // - initialize + size_t n = 0; + // - bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + if (m_refine(iy) == 2) { + n += m_nelz(iy) * 3 - 1; + } + else { + n += m_nelz(iy) - 1; + } + } + // - top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + if (m_refine(iy) == 2) { + n += m_nelz(iy) * 3 - 1; + } + else { + n += m_nelz(iy) - 1; + } + } + + // allocate node-list + xt::xtensor out = xt::empty({n}); + + // initialize counter: current index in the node-list "out" + size_t j = 0; + + // bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + // -- bottom node layer + for (size_t iz = 1; iz < m_nelz(iy); ++iz) { + out(j) = m_startNode(iy) + iz * (m_nelx(iy) + 1); + ++j; + } + // -- refinement layer + if (m_refine(iy) == 2) { + for (size_t iz = 0; iz < 2 * m_nelz(iy); ++iz) { + out(j) = m_startNode(iy) + iz * (m_nelx(iy) + 1) + m_nnd(iy); + ++j; + } + } + } + + // top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + // -- refinement layer + if (m_refine(iy) == 2) { + for (size_t iz = 0; iz < 2 * m_nelz(iy); ++iz) { + out(j) = m_startNode(iy) + iz * (m_nelx(iy) + 1) + m_nnd(iy); + ++j; + } + } + // -- top node layer + for (size_t iz = 1; iz < m_nelz(iy); ++iz) { + out(j) = m_startNode(iy + 1) + iz * (m_nelx(iy) + 1); + ++j; + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesRightFace() const +{ + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); + + // number of boundary nodes + // - initialize + size_t n = 0; + // - bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + if (m_refine(iy) == 2) { + n += m_nelz(iy) * 3 - 1; + } + else { + n += m_nelz(iy) - 1; + } + } + // - top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + if (m_refine(iy) == 2) { + n += m_nelz(iy) * 3 - 1; + } + else { + n += m_nelz(iy) - 1; + } + } + + // allocate node-list + xt::xtensor out = xt::empty({n}); + + // initialize counter: current index in the node-list "out" + size_t j = 0; + + // bottom half: bottom node layer (+ middle node layer) + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + // -- bottom node layer + for (size_t iz = 1; iz < m_nelz(iy); ++iz) { + out(j) = m_startNode(iy) + iz * (m_nelx(iy) + 1) + m_nelx(iy); + ++j; + } + // -- refinement layer + if (m_refine(iy) == 2) { + for (size_t iz = 0; iz < 2 * m_nelz(iy); ++iz) { + out(j) = m_startNode(iy) + m_nnd(iy) + iz * (m_nelx(iy) + 1) + m_nelx(iy); + ++j; + } + } + } + + // top half: (middle node layer +) top node layer + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + // -- refinement layer + if (m_refine(iy) == 2) { + for (size_t iz = 0; iz < 2 * m_nelz(iy); ++iz) { + out(j) = m_startNode(iy) + m_nnd(iy) + iz * (m_nelx(iy) + 1) + m_nelx(iy); + ++j; + } + } + // -- top node layer + for (size_t iz = 1; iz < m_nelz(iy); ++iz) { + out(j) = m_startNode(iy + 1) + iz * (m_nelx(iy) + 1) + m_nelx(iy); + ++j; + } } - } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- +inline xt::xtensor FineLayer::nodesBottomFace() const +{ + // allocate node list + xt::xtensor out = xt::empty({(m_nelx(0) - 1) * (m_nelz(0) - 1)}); + + // counter + size_t j = 0; -inline xt::xtensor FineLayer::nodesFrontBottomEdge() const + // fill node list + for (size_t ix = 1; ix < m_nelx(0); ++ix) { + for (size_t iz = 1; iz < m_nelz(0); ++iz) { + out(j) = m_startNode(0) + ix + iz * (m_nelx(0) + 1); + ++j; + } + } + + return out; +} + +inline xt::xtensor FineLayer::nodesTopFace() const { - xt::xtensor out = xt::empty({m_nelx(0)+1}); + // number of element layers in y-direction + size_t nely = static_cast(m_nhy.size()); - for ( size_t ix = 0 ; ix < m_nelx(0)+1 ; ++ix ) - out(ix) = m_startNode(0) + ix; + // allocate node list + xt::xtensor out = + xt::empty({(m_nelx(nely - 1) - 1) * (m_nelz(nely - 1) - 1)}); + + // counter + size_t j = 0; + + // fill node list + for (size_t ix = 1; ix < m_nelx(nely - 1); ++ix) { + for (size_t iz = 1; iz < m_nelz(nely - 1); ++iz) { + out(j) = m_startNode(nely) + ix + iz * (m_nelx(nely - 1) + 1); + ++j; + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- +inline xt::xtensor FineLayer::nodesFrontBottomEdge() const +{ + xt::xtensor out = xt::empty({m_nelx(0) + 1}); + + for (size_t ix = 0; ix < m_nelx(0) + 1; ++ix) { + out(ix) = m_startNode(0) + ix; + } + + return out; +} inline xt::xtensor FineLayer::nodesFrontTopEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({m_nelx(nely-1)+1}); + xt::xtensor out = xt::empty({m_nelx(nely - 1) + 1}); - for ( size_t ix = 0 ; ix < m_nelx(nely-1)+1 ; ++ix ) - out(ix) = m_startNode(nely) + ix; + for (size_t ix = 0; ix < m_nelx(nely - 1) + 1; ++ix) { + out(ix) = m_startNode(nely) + ix; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesFrontLeftEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({nely+1}); + xt::xtensor out = xt::empty({nely + 1}); - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - out(iy) = m_startNode(iy); + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + out(iy) = m_startNode(iy); + } - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - out(iy+1) = m_startNode(iy+1); + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + out(iy + 1) = m_startNode(iy + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesFrontRightEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({nely+1}); + xt::xtensor out = xt::empty({nely + 1}); - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - out(iy) = m_startNode(iy) + m_nelx(iy); + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + out(iy) = m_startNode(iy) + m_nelx(iy); + } - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - out(iy+1) = m_startNode(iy+1) + m_nelx(iy); + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + out(iy + 1) = m_startNode(iy + 1) + m_nelx(iy); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesBackBottomEdge() const { - xt::xtensor out = xt::empty({m_nelx(0)+1}); + xt::xtensor out = xt::empty({m_nelx(0) + 1}); - for ( size_t ix = 0 ; ix < m_nelx(0)+1 ; ++ix ) - out(ix) = m_startNode(0) + ix + (m_nelx(0)+1)*(m_nelz(0)); + for (size_t ix = 0; ix < m_nelx(0) + 1; ++ix) { + out(ix) = m_startNode(0) + ix + (m_nelx(0) + 1) * (m_nelz(0)); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesBackTopEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({m_nelx(nely-1)+1}); + xt::xtensor out = xt::empty({m_nelx(nely - 1) + 1}); - for ( size_t ix = 0 ; ix < m_nelx(nely-1)+1 ; ++ix ) - out(ix) = m_startNode(nely) + ix + (m_nelx(nely-1)+1)*(m_nelz(nely-1)); + for (size_t ix = 0; ix < m_nelx(nely - 1) + 1; ++ix) { + out(ix) = m_startNode(nely) + ix + (m_nelx(nely - 1) + 1) * (m_nelz(nely - 1)); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesBackLeftEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({nely+1}); + xt::xtensor out = xt::empty({nely + 1}); - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - out(iy) = m_startNode(iy) + (m_nelx(iy)+1)*(m_nelz(iy)); + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + out(iy) = m_startNode(iy) + (m_nelx(iy) + 1) * (m_nelz(iy)); + } - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - out(iy+1) = m_startNode(iy+1) + (m_nelx(iy)+1)*(m_nelz(iy)); + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + out(iy + 1) = m_startNode(iy + 1) + (m_nelx(iy) + 1) * (m_nelz(iy)); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesBackRightEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({nely+1}); + xt::xtensor out = xt::empty({nely + 1}); - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) - out(iy) = m_startNode(iy) + m_nelx(iy) + (m_nelx(iy)+1)*(m_nelz(iy)); + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + out(iy) = m_startNode(iy) + m_nelx(iy) + (m_nelx(iy) + 1) * (m_nelz(iy)); + } - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - out(iy+1) = m_startNode(iy+1) + m_nelx(iy) + (m_nelx(iy)+1)*(m_nelz(iy)); + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + out(iy + 1) = m_startNode(iy + 1) + m_nelx(iy) + (m_nelx(iy) + 1) * (m_nelz(iy)); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesBottomLeftEdge() const { - xt::xtensor out = xt::empty({m_nelz(0)+1}); + xt::xtensor out = xt::empty({m_nelz(0) + 1}); - for ( size_t iz = 0 ; iz < m_nelz(0)+1 ; ++iz ) - out(iz) = m_startNode(0) + iz * (m_nelx(0)+1); + for (size_t iz = 0; iz < m_nelz(0) + 1; ++iz) { + out(iz) = m_startNode(0) + iz * (m_nelx(0) + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesBottomRightEdge() const { - xt::xtensor out = xt::empty({m_nelz(0)+1}); + xt::xtensor out = xt::empty({m_nelz(0) + 1}); - for ( size_t iz = 0 ; iz < m_nelz(0)+1 ; ++iz ) - out(iz) = m_startNode(0) + m_nelx(0) + iz * (m_nelx(0)+1); + for (size_t iz = 0; iz < m_nelz(0) + 1; ++iz) { + out(iz) = m_startNode(0) + m_nelx(0) + iz * (m_nelx(0) + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesTopLeftEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({m_nelz(nely-1)+1}); + xt::xtensor out = xt::empty({m_nelz(nely - 1) + 1}); - for ( size_t iz = 0 ; iz < m_nelz(nely-1)+1 ; ++iz ) - out(iz) = m_startNode(nely) + iz * (m_nelx(nely-1)+1); + for (size_t iz = 0; iz < m_nelz(nely - 1) + 1; ++iz) { + out(iz) = m_startNode(nely) + iz * (m_nelx(nely - 1) + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesTopRightEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({m_nelz(nely-1)+1}); + xt::xtensor out = xt::empty({m_nelz(nely - 1) + 1}); - for ( size_t iz = 0 ; iz < m_nelz(nely-1)+1 ; ++iz ) - out(iz) = m_startNode(nely) + m_nelx(nely-1) + iz * (m_nelx(nely-1)+1); + for (size_t iz = 0; iz < m_nelz(nely - 1) + 1; ++iz) { + out(iz) = m_startNode(nely) + m_nelx(nely - 1) + iz * (m_nelx(nely - 1) + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesBottomFrontEdge() const { return nodesFrontBottomEdge(); } -inline xt::xtensor FineLayer::nodesBottomBackEdge() const { return nodesBackBottomEdge(); } -inline xt::xtensor FineLayer::nodesTopFrontEdge() const { return nodesFrontTopEdge(); } -inline xt::xtensor FineLayer::nodesTopBackEdge() const { return nodesBackTopEdge(); } -inline xt::xtensor FineLayer::nodesLeftBottomEdge() const { return nodesBottomLeftEdge(); } -inline xt::xtensor FineLayer::nodesLeftFrontEdge() const { return nodesFrontLeftEdge(); } -inline xt::xtensor FineLayer::nodesLeftBackEdge() const { return nodesBackLeftEdge(); } -inline xt::xtensor FineLayer::nodesLeftTopEdge() const { return nodesTopLeftEdge(); } -inline xt::xtensor FineLayer::nodesRightBottomEdge() const { return nodesBottomRightEdge(); } -inline xt::xtensor FineLayer::nodesRightTopEdge() const { return nodesTopRightEdge(); } -inline xt::xtensor FineLayer::nodesRightFrontEdge() const { return nodesFrontRightEdge(); } -inline xt::xtensor FineLayer::nodesRightBackEdge() const { return nodesBackRightEdge(); } - -// ------------------- node-numbers along the front-bottom edge, without corners ------------------- +inline xt::xtensor FineLayer::nodesBottomFrontEdge() const +{ + return nodesFrontBottomEdge(); +} +inline xt::xtensor FineLayer::nodesBottomBackEdge() const +{ + return nodesBackBottomEdge(); +} +inline xt::xtensor FineLayer::nodesTopFrontEdge() const +{ + return nodesFrontTopEdge(); +} +inline xt::xtensor FineLayer::nodesTopBackEdge() const +{ + return nodesBackTopEdge(); +} +inline xt::xtensor FineLayer::nodesLeftBottomEdge() const +{ + return nodesBottomLeftEdge(); +} +inline xt::xtensor FineLayer::nodesLeftFrontEdge() const +{ + return nodesFrontLeftEdge(); +} +inline xt::xtensor FineLayer::nodesLeftBackEdge() const +{ + return nodesBackLeftEdge(); +} +inline xt::xtensor FineLayer::nodesLeftTopEdge() const +{ + return nodesTopLeftEdge(); +} +inline xt::xtensor FineLayer::nodesRightBottomEdge() const +{ + return nodesBottomRightEdge(); +} +inline xt::xtensor FineLayer::nodesRightTopEdge() const +{ + return nodesTopRightEdge(); +} +inline xt::xtensor FineLayer::nodesRightFrontEdge() const +{ + return nodesFrontRightEdge(); +} +inline xt::xtensor FineLayer::nodesRightBackEdge() const +{ + return nodesBackRightEdge(); +} inline xt::xtensor FineLayer::nodesFrontBottomOpenEdge() const { - xt::xtensor out = xt::empty({m_nelx(0)-1}); + xt::xtensor out = xt::empty({m_nelx(0) - 1}); - for ( size_t ix = 1 ; ix < m_nelx(0) ; ++ix ) - out(ix-1) = m_startNode(0) + ix; + for (size_t ix = 1; ix < m_nelx(0); ++ix) { + out(ix - 1) = m_startNode(0) + ix; + } - return out; + return out; } -// -------------------- node-numbers along the front-top edge, without corners --------------------- - inline xt::xtensor FineLayer::nodesFrontTopOpenEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({m_nelx(nely-1)-1}); + xt::xtensor out = xt::empty({m_nelx(nely - 1) - 1}); - for ( size_t ix = 1 ; ix < m_nelx(nely-1) ; ++ix ) - out(ix-1) = m_startNode(nely) + ix; + for (size_t ix = 1; ix < m_nelx(nely - 1); ++ix) { + out(ix - 1) = m_startNode(nely) + ix; + } - return out; + return out; } -// -------------------- node-numbers along the front-left edge, without corners -------------------- - inline xt::xtensor FineLayer::nodesFrontLeftOpenEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({nely-1}); + xt::xtensor out = xt::empty({nely - 1}); - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - out(iy-1) = m_startNode(iy); + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + out(iy - 1) = m_startNode(iy); + } - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - out(iy) = m_startNode(iy+1); + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + out(iy) = m_startNode(iy + 1); + } - return out; + return out; } -// ------------------- node-numbers along the front-right edge, without corners -------------------- - inline xt::xtensor FineLayer::nodesFrontRightOpenEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({nely-1}); + xt::xtensor out = xt::empty({nely - 1}); - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - out(iy-1) = m_startNode(iy) + m_nelx(iy); + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + out(iy - 1) = m_startNode(iy) + m_nelx(iy); + } - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - out(iy) = m_startNode(iy+1) + m_nelx(iy); + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + out(iy) = m_startNode(iy + 1) + m_nelx(iy); + } - return out; + return out; } -// ------------------- node-numbers along the back-bottom edge, without corners -------------------- - inline xt::xtensor FineLayer::nodesBackBottomOpenEdge() const { - xt::xtensor out = xt::empty({m_nelx(0)-1}); + xt::xtensor out = xt::empty({m_nelx(0) - 1}); - for ( size_t ix = 1 ; ix < m_nelx(0) ; ++ix ) - out(ix-1) = m_startNode(0) + ix + (m_nelx(0)+1)*(m_nelz(0)); + for (size_t ix = 1; ix < m_nelx(0); ++ix) { + out(ix - 1) = m_startNode(0) + ix + (m_nelx(0) + 1) * (m_nelz(0)); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesBackTopOpenEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({m_nelx(nely-1)-1}); + xt::xtensor out = xt::empty({m_nelx(nely - 1) - 1}); - for ( size_t ix = 1 ; ix < m_nelx(nely-1) ; ++ix ) - out(ix-1) = m_startNode(nely) + ix + (m_nelx(nely-1)+1)*(m_nelz(nely-1)); + for (size_t ix = 1; ix < m_nelx(nely - 1); ++ix) { + out(ix - 1) = m_startNode(nely) + ix + (m_nelx(nely - 1) + 1) * (m_nelz(nely - 1)); + } - return out; + return out; } -// -------------------- node-numbers along the back-left edge, without corners --------------------- - inline xt::xtensor FineLayer::nodesBackLeftOpenEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({nely-1}); + xt::xtensor out = xt::empty({nely - 1}); - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - out(iy-1) = m_startNode(iy) + (m_nelx(iy)+1)*(m_nelz(iy)); + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + out(iy - 1) = m_startNode(iy) + (m_nelx(iy) + 1) * (m_nelz(iy)); + } - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - out(iy) = m_startNode(iy+1) + (m_nelx(iy)+1)*(m_nelz(iy)); + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + out(iy) = m_startNode(iy + 1) + (m_nelx(iy) + 1) * (m_nelz(iy)); + } - return out; + return out; } -// -------------------- node-numbers along the back-right edge, without corners -------------------- - inline xt::xtensor FineLayer::nodesBackRightOpenEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({nely-1}); + xt::xtensor out = xt::empty({nely - 1}); - for ( size_t iy = 1 ; iy < (nely+1)/2 ; ++iy ) - out(iy-1) = m_startNode(iy) + m_nelx(iy) + (m_nelx(iy)+1)*(m_nelz(iy)); + for (size_t iy = 1; iy < (nely + 1) / 2; ++iy) { + out(iy - 1) = m_startNode(iy) + m_nelx(iy) + (m_nelx(iy) + 1) * (m_nelz(iy)); + } - for ( size_t iy = (nely-1)/2 ; iy < nely-1 ; ++iy ) - out(iy) = m_startNode(iy+1) + m_nelx(iy) + (m_nelx(iy)+1)*(m_nelz(iy)); + for (size_t iy = (nely - 1) / 2; iy < nely - 1; ++iy) { + out(iy) = m_startNode(iy + 1) + m_nelx(iy) + (m_nelx(iy) + 1) * (m_nelz(iy)); + } - return out; + return out; } -// ------------------- node-numbers along the bottom-left edge, without corners -------------------- - inline xt::xtensor FineLayer::nodesBottomLeftOpenEdge() const { - xt::xtensor out = xt::empty({m_nelz(0)-1}); + xt::xtensor out = xt::empty({m_nelz(0) - 1}); - for ( size_t iz = 1 ; iz < m_nelz(0) ; ++iz ) - out(iz-1) = m_startNode(0) + iz * (m_nelx(0)+1); + for (size_t iz = 1; iz < m_nelz(0); ++iz) { + out(iz - 1) = m_startNode(0) + iz * (m_nelx(0) + 1); + } - return out; + return out; } -// ------------------- node-numbers along the bottom-right edge, without corners ------------------- - inline xt::xtensor FineLayer::nodesBottomRightOpenEdge() const { - xt::xtensor out = xt::empty({m_nelz(0)-1}); + xt::xtensor out = xt::empty({m_nelz(0) - 1}); - for ( size_t iz = 1 ; iz < m_nelz(0) ; ++iz ) - out(iz-1) = m_startNode(0) + m_nelx(0) + iz * (m_nelx(0)+1); + for (size_t iz = 1; iz < m_nelz(0); ++iz) { + out(iz - 1) = m_startNode(0) + m_nelx(0) + iz * (m_nelx(0) + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesTopLeftOpenEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({m_nelz(nely-1)-1}); + xt::xtensor out = xt::empty({m_nelz(nely - 1) - 1}); - for ( size_t iz = 1 ; iz < m_nelz(nely-1) ; ++iz ) - out(iz-1) = m_startNode(nely) + iz * (m_nelx(nely-1)+1); + for (size_t iz = 1; iz < m_nelz(nely - 1); ++iz) { + out(iz - 1) = m_startNode(nely) + iz * (m_nelx(nely - 1) + 1); + } - return out; + return out; } -// -------------------- node-numbers along the top-right edge, without corners --------------------- - inline xt::xtensor FineLayer::nodesTopRightOpenEdge() const { - size_t nely = static_cast(m_nhy.size()); + size_t nely = static_cast(m_nhy.size()); - xt::xtensor out = xt::empty({m_nelz(nely-1)-1}); + xt::xtensor out = xt::empty({m_nelz(nely - 1) - 1}); - for ( size_t iz = 1 ; iz < m_nelz(nely-1) ; ++iz ) - out(iz-1) = m_startNode(nely) + m_nelx(nely-1) + iz * (m_nelx(nely-1)+1); + for (size_t iz = 1; iz < m_nelz(nely - 1); ++iz) { + out(iz - 1) = m_startNode(nely) + m_nelx(nely - 1) + iz * (m_nelx(nely - 1) + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer::nodesBottomFrontOpenEdge() const { return nodesFrontBottomOpenEdge(); } -inline xt::xtensor FineLayer::nodesBottomBackOpenEdge() const { return nodesBackBottomOpenEdge(); } -inline xt::xtensor FineLayer::nodesTopFrontOpenEdge() const { return nodesFrontTopOpenEdge(); } -inline xt::xtensor FineLayer::nodesTopBackOpenEdge() const { return nodesBackTopOpenEdge(); } -inline xt::xtensor FineLayer::nodesLeftBottomOpenEdge() const { return nodesBottomLeftOpenEdge(); } -inline xt::xtensor FineLayer::nodesLeftFrontOpenEdge() const { return nodesFrontLeftOpenEdge(); } -inline xt::xtensor FineLayer::nodesLeftBackOpenEdge() const { return nodesBackLeftOpenEdge(); } -inline xt::xtensor FineLayer::nodesLeftTopOpenEdge() const { return nodesTopLeftOpenEdge(); } -inline xt::xtensor FineLayer::nodesRightBottomOpenEdge() const { return nodesBottomRightOpenEdge(); } -inline xt::xtensor FineLayer::nodesRightTopOpenEdge() const { return nodesTopRightOpenEdge(); } -inline xt::xtensor FineLayer::nodesRightFrontOpenEdge() const { return nodesFrontRightOpenEdge(); } -inline xt::xtensor FineLayer::nodesRightBackOpenEdge() const { return nodesBackRightOpenEdge(); } - -// ------------------------------------------------------------------------------------------------- +inline xt::xtensor FineLayer::nodesBottomFrontOpenEdge() const +{ + return nodesFrontBottomOpenEdge(); +} +inline xt::xtensor FineLayer::nodesBottomBackOpenEdge() const +{ + return nodesBackBottomOpenEdge(); +} +inline xt::xtensor FineLayer::nodesTopFrontOpenEdge() const +{ + return nodesFrontTopOpenEdge(); +} +inline xt::xtensor FineLayer::nodesTopBackOpenEdge() const +{ + return nodesBackTopOpenEdge(); +} +inline xt::xtensor FineLayer::nodesLeftBottomOpenEdge() const +{ + return nodesBottomLeftOpenEdge(); +} +inline xt::xtensor FineLayer::nodesLeftFrontOpenEdge() const +{ + return nodesFrontLeftOpenEdge(); +} +inline xt::xtensor FineLayer::nodesLeftBackOpenEdge() const +{ + return nodesBackLeftOpenEdge(); +} +inline xt::xtensor FineLayer::nodesLeftTopOpenEdge() const +{ + return nodesTopLeftOpenEdge(); +} +inline xt::xtensor FineLayer::nodesRightBottomOpenEdge() const +{ + return nodesBottomRightOpenEdge(); +} +inline xt::xtensor FineLayer::nodesRightTopOpenEdge() const +{ + return nodesTopRightOpenEdge(); +} +inline xt::xtensor FineLayer::nodesRightFrontOpenEdge() const +{ + return nodesFrontRightOpenEdge(); +} +inline xt::xtensor FineLayer::nodesRightBackOpenEdge() const +{ + return nodesBackRightOpenEdge(); +} inline size_t FineLayer::nodesFrontBottomLeftCorner() const { - return m_startNode(0); + return m_startNode(0); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesFrontBottomRightCorner() const { - return m_startNode(0) + m_nelx(0); + return m_startNode(0) + m_nelx(0); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesFrontTopLeftCorner() const { - size_t nely = static_cast(m_nhy.size()); - - return m_startNode(nely); + size_t nely = static_cast(m_nhy.size()); + return m_startNode(nely); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesFrontTopRightCorner() const { - size_t nely = static_cast(m_nhy.size()); - - return m_startNode(nely) + m_nelx(nely-1); + size_t nely = static_cast(m_nhy.size()); + return m_startNode(nely) + m_nelx(nely - 1); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesBackBottomLeftCorner() const { - return m_startNode(0) + (m_nelx(0)+1)*(m_nelz(0)); + return m_startNode(0) + (m_nelx(0) + 1) * (m_nelz(0)); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesBackBottomRightCorner() const { - return m_startNode(0) + m_nelx(0) + (m_nelx(0)+1)*(m_nelz(0)); + return m_startNode(0) + m_nelx(0) + (m_nelx(0) + 1) * (m_nelz(0)); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesBackTopLeftCorner() const { - size_t nely = static_cast(m_nhy.size()); - - return m_startNode(nely) + (m_nelx(nely-1)+1)*(m_nelz(nely-1)); + size_t nely = static_cast(m_nhy.size()); + return m_startNode(nely) + (m_nelx(nely - 1) + 1) * (m_nelz(nely - 1)); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesBackTopRightCorner() const { - size_t nely = static_cast(m_nhy.size()); - - return m_startNode(nely) + m_nelx(nely-1) + (m_nelx(nely-1)+1)*(m_nelz(nely-1)); -} - -// ------------------------------------------------------------------------------------------------- - -inline size_t FineLayer::nodesFrontLeftBottomCorner() const { return nodesFrontBottomLeftCorner(); } -inline size_t FineLayer::nodesBottomFrontLeftCorner() const { return nodesFrontBottomLeftCorner(); } -inline size_t FineLayer::nodesBottomLeftFrontCorner() const { return nodesFrontBottomLeftCorner(); } -inline size_t FineLayer::nodesLeftFrontBottomCorner() const { return nodesFrontBottomLeftCorner(); } -inline size_t FineLayer::nodesLeftBottomFrontCorner() const { return nodesFrontBottomLeftCorner(); } -inline size_t FineLayer::nodesFrontRightBottomCorner() const { return nodesFrontBottomRightCorner(); } -inline size_t FineLayer::nodesBottomFrontRightCorner() const { return nodesFrontBottomRightCorner(); } -inline size_t FineLayer::nodesBottomRightFrontCorner() const { return nodesFrontBottomRightCorner(); } -inline size_t FineLayer::nodesRightFrontBottomCorner() const { return nodesFrontBottomRightCorner(); } -inline size_t FineLayer::nodesRightBottomFrontCorner() const { return nodesFrontBottomRightCorner(); } -inline size_t FineLayer::nodesFrontLeftTopCorner() const { return nodesFrontTopLeftCorner(); } -inline size_t FineLayer::nodesTopFrontLeftCorner() const { return nodesFrontTopLeftCorner(); } -inline size_t FineLayer::nodesTopLeftFrontCorner() const { return nodesFrontTopLeftCorner(); } -inline size_t FineLayer::nodesLeftFrontTopCorner() const { return nodesFrontTopLeftCorner(); } -inline size_t FineLayer::nodesLeftTopFrontCorner() const { return nodesFrontTopLeftCorner(); } -inline size_t FineLayer::nodesFrontRightTopCorner() const { return nodesFrontTopRightCorner(); } -inline size_t FineLayer::nodesTopFrontRightCorner() const { return nodesFrontTopRightCorner(); } -inline size_t FineLayer::nodesTopRightFrontCorner() const { return nodesFrontTopRightCorner(); } -inline size_t FineLayer::nodesRightFrontTopCorner() const { return nodesFrontTopRightCorner(); } -inline size_t FineLayer::nodesRightTopFrontCorner() const { return nodesFrontTopRightCorner(); } -inline size_t FineLayer::nodesBackLeftBottomCorner() const { return nodesBackBottomLeftCorner(); } -inline size_t FineLayer::nodesBottomBackLeftCorner() const { return nodesBackBottomLeftCorner(); } -inline size_t FineLayer::nodesBottomLeftBackCorner() const { return nodesBackBottomLeftCorner(); } -inline size_t FineLayer::nodesLeftBackBottomCorner() const { return nodesBackBottomLeftCorner(); } -inline size_t FineLayer::nodesLeftBottomBackCorner() const { return nodesBackBottomLeftCorner(); } -inline size_t FineLayer::nodesBackRightBottomCorner() const { return nodesBackBottomRightCorner(); } -inline size_t FineLayer::nodesBottomBackRightCorner() const { return nodesBackBottomRightCorner(); } -inline size_t FineLayer::nodesBottomRightBackCorner() const { return nodesBackBottomRightCorner(); } -inline size_t FineLayer::nodesRightBackBottomCorner() const { return nodesBackBottomRightCorner(); } -inline size_t FineLayer::nodesRightBottomBackCorner() const { return nodesBackBottomRightCorner(); } -inline size_t FineLayer::nodesBackLeftTopCorner() const { return nodesBackTopLeftCorner(); } -inline size_t FineLayer::nodesTopBackLeftCorner() const { return nodesBackTopLeftCorner(); } -inline size_t FineLayer::nodesTopLeftBackCorner() const { return nodesBackTopLeftCorner(); } -inline size_t FineLayer::nodesLeftBackTopCorner() const { return nodesBackTopLeftCorner(); } -inline size_t FineLayer::nodesLeftTopBackCorner() const { return nodesBackTopLeftCorner(); } -inline size_t FineLayer::nodesBackRightTopCorner() const { return nodesBackTopRightCorner(); } -inline size_t FineLayer::nodesTopBackRightCorner() const { return nodesBackTopRightCorner(); } -inline size_t FineLayer::nodesTopRightBackCorner() const { return nodesBackTopRightCorner(); } -inline size_t FineLayer::nodesRightBackTopCorner() const { return nodesBackTopRightCorner(); } -inline size_t FineLayer::nodesRightTopBackCorner() const { return nodesBackTopRightCorner(); } - -// ------------------------------------------------------------------------------------------------- + size_t nely = static_cast(m_nhy.size()); + return m_startNode(nely) + m_nelx(nely - 1) + (m_nelx(nely - 1) + 1) * (m_nelz(nely - 1)); +} + +inline size_t FineLayer::nodesFrontLeftBottomCorner() const +{ + return nodesFrontBottomLeftCorner(); +} +inline size_t FineLayer::nodesBottomFrontLeftCorner() const +{ + return nodesFrontBottomLeftCorner(); +} +inline size_t FineLayer::nodesBottomLeftFrontCorner() const +{ + return nodesFrontBottomLeftCorner(); +} +inline size_t FineLayer::nodesLeftFrontBottomCorner() const +{ + return nodesFrontBottomLeftCorner(); +} +inline size_t FineLayer::nodesLeftBottomFrontCorner() const +{ + return nodesFrontBottomLeftCorner(); +} +inline size_t FineLayer::nodesFrontRightBottomCorner() const +{ + return nodesFrontBottomRightCorner(); +} +inline size_t FineLayer::nodesBottomFrontRightCorner() const +{ + return nodesFrontBottomRightCorner(); +} +inline size_t FineLayer::nodesBottomRightFrontCorner() const +{ + return nodesFrontBottomRightCorner(); +} +inline size_t FineLayer::nodesRightFrontBottomCorner() const +{ + return nodesFrontBottomRightCorner(); +} +inline size_t FineLayer::nodesRightBottomFrontCorner() const +{ + return nodesFrontBottomRightCorner(); +} +inline size_t FineLayer::nodesFrontLeftTopCorner() const +{ + return nodesFrontTopLeftCorner(); +} +inline size_t FineLayer::nodesTopFrontLeftCorner() const +{ + return nodesFrontTopLeftCorner(); +} +inline size_t FineLayer::nodesTopLeftFrontCorner() const +{ + return nodesFrontTopLeftCorner(); +} +inline size_t FineLayer::nodesLeftFrontTopCorner() const +{ + return nodesFrontTopLeftCorner(); +} +inline size_t FineLayer::nodesLeftTopFrontCorner() const +{ + return nodesFrontTopLeftCorner(); +} +inline size_t FineLayer::nodesFrontRightTopCorner() const +{ + return nodesFrontTopRightCorner(); +} +inline size_t FineLayer::nodesTopFrontRightCorner() const +{ + return nodesFrontTopRightCorner(); +} +inline size_t FineLayer::nodesTopRightFrontCorner() const +{ + return nodesFrontTopRightCorner(); +} +inline size_t FineLayer::nodesRightFrontTopCorner() const +{ + return nodesFrontTopRightCorner(); +} +inline size_t FineLayer::nodesRightTopFrontCorner() const +{ + return nodesFrontTopRightCorner(); +} +inline size_t FineLayer::nodesBackLeftBottomCorner() const +{ + return nodesBackBottomLeftCorner(); +} +inline size_t FineLayer::nodesBottomBackLeftCorner() const +{ + return nodesBackBottomLeftCorner(); +} +inline size_t FineLayer::nodesBottomLeftBackCorner() const +{ + return nodesBackBottomLeftCorner(); +} +inline size_t FineLayer::nodesLeftBackBottomCorner() const +{ + return nodesBackBottomLeftCorner(); +} +inline size_t FineLayer::nodesLeftBottomBackCorner() const +{ + return nodesBackBottomLeftCorner(); +} +inline size_t FineLayer::nodesBackRightBottomCorner() const +{ + return nodesBackBottomRightCorner(); +} +inline size_t FineLayer::nodesBottomBackRightCorner() const +{ + return nodesBackBottomRightCorner(); +} +inline size_t FineLayer::nodesBottomRightBackCorner() const +{ + return nodesBackBottomRightCorner(); +} +inline size_t FineLayer::nodesRightBackBottomCorner() const +{ + return nodesBackBottomRightCorner(); +} +inline size_t FineLayer::nodesRightBottomBackCorner() const +{ + return nodesBackBottomRightCorner(); +} +inline size_t FineLayer::nodesBackLeftTopCorner() const +{ + return nodesBackTopLeftCorner(); +} +inline size_t FineLayer::nodesTopBackLeftCorner() const +{ + return nodesBackTopLeftCorner(); +} +inline size_t FineLayer::nodesTopLeftBackCorner() const +{ + return nodesBackTopLeftCorner(); +} +inline size_t FineLayer::nodesLeftBackTopCorner() const +{ + return nodesBackTopLeftCorner(); +} +inline size_t FineLayer::nodesLeftTopBackCorner() const +{ + return nodesBackTopLeftCorner(); +} +inline size_t FineLayer::nodesBackRightTopCorner() const +{ + return nodesBackTopRightCorner(); +} +inline size_t FineLayer::nodesTopBackRightCorner() const +{ + return nodesBackTopRightCorner(); +} +inline size_t FineLayer::nodesTopRightBackCorner() const +{ + return nodesBackTopRightCorner(); +} +inline size_t FineLayer::nodesRightBackTopCorner() const +{ + return nodesBackTopRightCorner(); +} +inline size_t FineLayer::nodesRightTopBackCorner() const +{ + return nodesBackTopRightCorner(); +} inline xt::xtensor FineLayer::nodesPeriodic() const { - // faces - xt::xtensor fro = nodesFrontFace(); - xt::xtensor bck = nodesBackFace(); - xt::xtensor lft = nodesLeftFace(); - xt::xtensor rgt = nodesRightFace(); - xt::xtensor bot = nodesBottomFace(); - xt::xtensor top = nodesTopFace(); - - // edges - xt::xtensor froBot = nodesFrontBottomOpenEdge(); - xt::xtensor froTop = nodesFrontTopOpenEdge(); - xt::xtensor froLft = nodesFrontLeftOpenEdge(); - xt::xtensor froRgt = nodesFrontRightOpenEdge(); - xt::xtensor bckBot = nodesBackBottomOpenEdge(); - xt::xtensor bckTop = nodesBackTopOpenEdge(); - xt::xtensor bckLft = nodesBackLeftOpenEdge(); - xt::xtensor bckRgt = nodesBackRightOpenEdge(); - xt::xtensor botLft = nodesBottomLeftOpenEdge(); - xt::xtensor botRgt = nodesBottomRightOpenEdge(); - xt::xtensor topLft = nodesTopLeftOpenEdge(); - xt::xtensor topRgt = nodesTopRightOpenEdge(); - - // allocate nodal ties - // - number of tying per category - size_t tface = fro.size() + lft.size() + bot.size(); - size_t tedge = 3*froBot.size() + 3*froLft.size() + 3*botLft.size(); - size_t tnode = 7; - // - allocate - xt::xtensor out = xt::empty({tface+tedge+tnode, std::size_t(2)}); - - // counter - size_t i = 0; - - // tie all corners to one corner - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesFrontBottomRightCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesBackBottomRightCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesBackBottomLeftCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesFrontTopLeftCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesFrontTopRightCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesBackTopRightCorner(); ++i; - out(i,0) = nodesFrontBottomLeftCorner(); out(i,1) = nodesBackTopLeftCorner(); ++i; - - // tie all corresponding edges to each other (exclude corners) - for ( size_t j = 0 ; j fro = nodesFrontFace(); + xt::xtensor bck = nodesBackFace(); + xt::xtensor lft = nodesLeftFace(); + xt::xtensor rgt = nodesRightFace(); + xt::xtensor bot = nodesBottomFace(); + xt::xtensor top = nodesTopFace(); + + xt::xtensor froBot = nodesFrontBottomOpenEdge(); + xt::xtensor froTop = nodesFrontTopOpenEdge(); + xt::xtensor froLft = nodesFrontLeftOpenEdge(); + xt::xtensor froRgt = nodesFrontRightOpenEdge(); + xt::xtensor bckBot = nodesBackBottomOpenEdge(); + xt::xtensor bckTop = nodesBackTopOpenEdge(); + xt::xtensor bckLft = nodesBackLeftOpenEdge(); + xt::xtensor bckRgt = nodesBackRightOpenEdge(); + xt::xtensor botLft = nodesBottomLeftOpenEdge(); + xt::xtensor botRgt = nodesBottomRightOpenEdge(); + xt::xtensor topLft = nodesTopLeftOpenEdge(); + xt::xtensor topRgt = nodesTopRightOpenEdge(); + + size_t tface = fro.size() + lft.size() + bot.size(); + size_t tedge = 3 * froBot.size() + 3 * froLft.size() + 3 * botLft.size(); + size_t tnode = 7; + xt::xtensor out = xt::empty({tface + tedge + tnode, std::size_t(2)}); + + size_t i = 0; + + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesFrontBottomRightCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesBackBottomRightCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesBackBottomLeftCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesFrontTopLeftCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesFrontTopRightCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesBackTopRightCorner(); + ++i; + out(i, 0) = nodesFrontBottomLeftCorner(); + out(i, 1) = nodesBackTopLeftCorner(); + ++i; + + for (size_t j = 0; j < froBot.size(); ++j) { + out(i, 0) = froBot(j); + out(i, 1) = bckBot(j); + ++i; + } + for (size_t j = 0; j < froBot.size(); ++j) { + out(i, 0) = froBot(j); + out(i, 1) = bckTop(j); + ++i; + } + for (size_t j = 0; j < froBot.size(); ++j) { + out(i, 0) = froBot(j); + out(i, 1) = froTop(j); + ++i; + } + for (size_t j = 0; j < botLft.size(); ++j) { + out(i, 0) = botLft(j); + out(i, 1) = botRgt(j); + ++i; + } + for (size_t j = 0; j < botLft.size(); ++j) { + out(i, 0) = botLft(j); + out(i, 1) = topRgt(j); + ++i; + } + for (size_t j = 0; j < botLft.size(); ++j) { + out(i, 0) = botLft(j); + out(i, 1) = topLft(j); + ++i; + } + for (size_t j = 0; j < froLft.size(); ++j) { + out(i, 0) = froLft(j); + out(i, 1) = froRgt(j); + ++i; + } + for (size_t j = 0; j < froLft.size(); ++j) { + out(i, 0) = froLft(j); + out(i, 1) = bckRgt(j); + ++i; + } + for (size_t j = 0; j < froLft.size(); ++j) { + out(i, 0) = froLft(j); + out(i, 1) = bckLft(j); + ++i; + } + + for (size_t j = 0; j < fro.size(); ++j) { + out(i, 0) = fro(j); + out(i, 1) = bck(j); + ++i; + } + for (size_t j = 0; j < lft.size(); ++j) { + out(i, 0) = lft(j); + out(i, 1) = rgt(j); + ++i; + } + for (size_t j = 0; j < bot.size(); ++j) { + out(i, 0) = bot(j); + out(i, 1) = top(j); + ++i; + } + + return out; +} inline size_t FineLayer::nodesOrigin() const { - return nodesFrontBottomLeftCorner(); + return nodesFrontBottomLeftCorner(); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::dofs() const { - return GooseFEM::Mesh::dofs(m_nnode,m_ndim); + return GooseFEM::Mesh::dofs(m_nnode, m_ndim); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::dofsPeriodic() const { - // DOF-numbers for each component of each node (sequential) - xt::xtensor out = GooseFEM::Mesh::dofs(m_nnode,m_ndim); - - // periodic node-pairs - xt::xtensor nodePer = nodesPeriodic(); + xt::xtensor out = GooseFEM::Mesh::dofs(m_nnode, m_ndim); + xt::xtensor nodePer = nodesPeriodic(); - // eliminate 'dependent' DOFs; renumber "out" to be sequential for the remaining DOFs - for (size_t i = 0; i < nodePer.shape(0); ++i) - for (size_t j = 0; j < m_ndim; ++j) - out(nodePer(i,1),j) = out(nodePer(i,0),j); + for (size_t i = 0; i < nodePer.shape(0); ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + out(nodePer(i, 1), j) = out(nodePer(i, 0), j); + } + } - // renumber "out" to be sequential - return GooseFEM::Mesh::renumber(out); + return GooseFEM::Mesh::renumber(out); } -// ------------------------------------------------------------------------------------------------- - -}}} // namespace ... - -// ================================================================================================= +} // namespace Hex8 +} // namespace Mesh +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/MeshQuad4.hpp b/include/GooseFEM/MeshQuad4.hpp index fc8c101..bdc19da 100644 --- a/include/GooseFEM/MeshQuad4.hpp +++ b/include/GooseFEM/MeshQuad4.hpp @@ -1,1498 +1,1325 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_MESHQUAD4_HPP #define GOOSEFEM_MESHQUAD4_HPP -// ------------------------------------------------------------------------------------------------- - #include "MeshQuad4.h" -// ================================================================================================= - namespace GooseFEM { namespace Mesh { namespace Quad4 { -// ------------------------------------------------------------------------------------------------- - -inline Regular::Regular(size_t nelx, size_t nely, double h): -m_h(h), m_nelx(nelx), m_nely(nely) +inline Regular::Regular(size_t nelx, size_t nely, double h) : m_h(h), m_nelx(nelx), m_nely(nely) { - GOOSEFEM_ASSERT(m_nelx >= 1ul); - GOOSEFEM_ASSERT(m_nely >= 1ul); + GOOSEFEM_ASSERT(m_nelx >= 1ul); + GOOSEFEM_ASSERT(m_nely >= 1ul); - m_nnode = (m_nelx+1) * (m_nely+1); - m_nelem = m_nelx * m_nely ; + m_nnode = (m_nelx + 1) * (m_nely + 1); + m_nelem = m_nelx * m_nely; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nelx() const { - return m_nelx; + return m_nelx; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nely() const { - return m_nely; + return m_nely; } -// ------------------------------------------------------------------------------------------------- - inline double Regular::h() const { - return m_h; + return m_h; } -// ------------------------------------------------------------------------------------------------- - inline ElementType Regular::getElementType() const { - return ElementType::Quad4; + return ElementType::Quad4; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::coor() const { - xt::xtensor out = xt::empty({m_nnode, m_ndim}); + xt::xtensor out = xt::empty({m_nnode, m_ndim}); - xt::xtensor x = xt::linspace(0.0, m_h*static_cast(m_nelx), m_nelx+1); - xt::xtensor y = xt::linspace(0.0, m_h*static_cast(m_nely), m_nely+1); + xt::xtensor x = + xt::linspace(0.0, m_h * static_cast(m_nelx), m_nelx + 1); + xt::xtensor y = + xt::linspace(0.0, m_h * static_cast(m_nely), m_nely + 1); - size_t inode = 0; + size_t inode = 0; - for (size_t iy = 0; iy < m_nely + 1; ++iy) { - for (size_t ix = 0; ix < m_nelx + 1; ++ix) { - out(inode,0) = x(ix); - out(inode,1) = y(iy); - ++inode; + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(inode, 0) = x(ix); + out(inode, 1) = y(iy); + ++inode; + } } - } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::conn() const { - xt::xtensor out = xt::empty({m_nelem,m_nne}); + xt::xtensor out = xt::empty({m_nelem, m_nne}); - size_t ielem = 0; + size_t ielem = 0; - for (size_t iy = 0; iy < m_nely; ++iy) { - for (size_t ix = 0; ix < m_nelx; ++ix) { - out(ielem,0) = (iy )*(m_nelx+1) + (ix ); - out(ielem,1) = (iy )*(m_nelx+1) + (ix+1); - out(ielem,3) = (iy+1)*(m_nelx+1) + (ix ); - out(ielem,2) = (iy+1)*(m_nelx+1) + (ix+1); - ++ielem; + for (size_t iy = 0; iy < m_nely; ++iy) { + for (size_t ix = 0; ix < m_nelx; ++ix) { + out(ielem, 0) = (iy) * (m_nelx + 1) + (ix); + out(ielem, 1) = (iy) * (m_nelx + 1) + (ix + 1); + out(ielem, 3) = (iy + 1) * (m_nelx + 1) + (ix); + out(ielem, 2) = (iy + 1) * (m_nelx + 1) + (ix + 1); + ++ielem; + } } - } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBottomEdge() const { - return xt::arange(m_nelx+1); + return xt::arange(m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesTopEdge() const { - return xt::arange(m_nelx+1) + m_nely*(m_nelx+1); + return xt::arange(m_nelx + 1) + m_nely * (m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesLeftEdge() const { - return xt::arange(m_nely+1) * (m_nelx+1); + return xt::arange(m_nely + 1) * (m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesRightEdge() const { - return xt::arange(m_nely+1) * (m_nelx+1) + m_nelx; + return xt::arange(m_nely + 1) * (m_nelx + 1) + m_nelx; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBottomOpenEdge() const { - return xt::arange(1, m_nelx); + return xt::arange(1, m_nelx); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesTopOpenEdge() const { - return xt::arange(1, m_nelx) + m_nely*(m_nelx+1); + return xt::arange(1, m_nelx) + m_nely * (m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesLeftOpenEdge() const { - return xt::arange(1, m_nely) * (m_nelx+1); + return xt::arange(1, m_nely) * (m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesRightOpenEdge() const { - return xt::arange(1, m_nely) * (m_nelx+1) + m_nelx; + return xt::arange(1, m_nely) * (m_nelx + 1) + m_nelx; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesBottomLeftCorner() const { - return 0; + return 0; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesBottomRightCorner() const { - return m_nelx; + return m_nelx; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesTopLeftCorner() const { - return m_nely * (m_nelx+1); + return m_nely * (m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesTopRightCorner() const { - return m_nely * (m_nelx+1) + m_nelx; + return m_nely * (m_nelx + 1) + m_nelx; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesLeftBottomCorner() const { - return nodesBottomLeftCorner(); + return nodesBottomLeftCorner(); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesLeftTopCorner() const { - return nodesTopLeftCorner(); + return nodesTopLeftCorner(); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesRightBottomCorner() const { - return nodesBottomRightCorner(); + return nodesBottomRightCorner(); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesRightTopCorner() const { - return nodesTopRightCorner(); + return nodesTopRightCorner(); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesPeriodic() const { - // edges (without corners) - xt::xtensor bot = nodesBottomOpenEdge(); - xt::xtensor top = nodesTopOpenEdge(); - xt::xtensor lft = nodesLeftOpenEdge(); - xt::xtensor rgt = nodesRightOpenEdge(); + xt::xtensor bot = nodesBottomOpenEdge(); + xt::xtensor top = nodesTopOpenEdge(); + xt::xtensor lft = nodesLeftOpenEdge(); + xt::xtensor rgt = nodesRightOpenEdge(); - // allocate nodal ties - xt::xtensor out = xt::empty({bot.size() + lft.size() + 3ul, 2ul}); + xt::xtensor out = xt::empty({bot.size() + lft.size() + 3ul, 2ul}); - // tie all corners to one corner + out(0, 0) = nodesBottomLeftCorner(); + out(0, 1) = nodesBottomRightCorner(); - out(0,0) = nodesBottomLeftCorner(); out(0,1) = nodesBottomRightCorner(); - out(1,0) = nodesBottomLeftCorner(); out(1,1) = nodesTopRightCorner(); - out(2,0) = nodesBottomLeftCorner(); out(2,1) = nodesTopLeftCorner(); + out(1, 0) = nodesBottomLeftCorner(); + out(1, 1) = nodesTopRightCorner(); - // tie all corresponding edges to each other + out(2, 0) = nodesBottomLeftCorner(); + out(2, 1) = nodesTopLeftCorner(); - size_t i = 3; + size_t i = 3; - xt::view(out, xt::range(i, i+bot.size()), 0) = bot; - xt::view(out, xt::range(i, i+bot.size()), 1) = top; + xt::view(out, xt::range(i, i + bot.size()), 0) = bot; + xt::view(out, xt::range(i, i + bot.size()), 1) = top; - i += bot.size(); + i += bot.size(); - xt::view(out, xt::range(i, i+lft.size()), 0) = lft; - xt::view(out, xt::range(i, i+lft.size()), 1) = rgt; + xt::view(out, xt::range(i, i + lft.size()), 0) = lft; + xt::view(out, xt::range(i, i + lft.size()), 1) = rgt; - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesOrigin() const { - return nodesBottomLeftCorner(); + return nodesBottomLeftCorner(); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::dofs() const { - return GooseFEM::Mesh::dofs(m_nnode, m_ndim); + return GooseFEM::Mesh::dofs(m_nnode, m_ndim); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::dofsPeriodic() const { - // DOF-numbers for each component of each node (sequential) - xt::xtensor out = GooseFEM::Mesh::dofs(m_nnode, m_ndim); - - // periodic node-pairs - xt::xtensor nodePer = nodesPeriodic(); + xt::xtensor out = GooseFEM::Mesh::dofs(m_nnode, m_ndim); + xt::xtensor nodePer = nodesPeriodic(); + xt::xtensor independent = xt::view(nodePer, xt::all(), 0); + xt::xtensor dependent = xt::view(nodePer, xt::all(), 1); - // node sets - xt::xtensor independent = xt::view(nodePer, xt::all(), 0); - xt::xtensor dependent = xt::view(nodePer, xt::all(), 1); - - // eliminate 'dependent' DOFs; renumber "out" to be sequential for the remaining DOFs - for (size_t j = 0; j < m_ndim; ++j) - xt::view(out, xt::keep(dependent), j) = xt::view(out, xt::keep(independent), j); + for (size_t j = 0; j < m_ndim; ++j) { + xt::view(out, xt::keep(dependent), j) = xt::view(out, xt::keep(independent), j); + } - // renumber "out" to be sequential - return GooseFEM::Mesh::renumber(out); + return GooseFEM::Mesh::renumber(out); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::elementMatrix() const { - return xt::arange(m_nelem).reshape({m_nely, m_nelx}); -} - -// ------------------------------------------------------------------------------------------------- - -inline FineLayer::FineLayer(size_t nelx, size_t nely, double h, size_t nfine) : - m_h(h) -{ - // basic assumptions - GOOSEFEM_ASSERT(nelx >= 1ul); - GOOSEFEM_ASSERT(nely >= 1ul); - - // store basic info - m_Lx = m_h * static_cast(nelx); - - // compute element size in y-direction (use symmetry, compute upper half) - // ---------------------------------------------------------------------- - - // temporary variables - size_t nmin, ntot; - xt::xtensor nhx = xt::ones({nely}); - xt::xtensor nhy = xt::ones({nely}); - xt::xtensor refine = -1 * xt::ones ({nely}); - - // minimum height in y-direction (half of the height because of symmetry) - if (nely % 2 == 0) nmin = nely /2; - else nmin = (nely +1)/2; - - // minimum number of fine layers in y-direction (minimum 1, middle layer part of this half) - if (nfine % 2 == 0) nfine = nfine /2 + 1; - else nfine = (nfine+1)/2; - if (nfine < 1 ) nfine = 1; - if (nfine > nmin ) nfine = nmin; - - // loop over element layers in y-direction, try to coarsen using these rules: - // (1) element size in y-direction <= distance to origin in y-direction - // (2) element size in x-direction should fit the total number of elements in x-direction - // (3) a certain number of layers have the minimum size "1" (are fine) - for (size_t iy = nfine ; ; ) - { - // initialize current size in y-direction - if (iy == nfine) ntot = nfine; - // check to stop - if (iy >= nely || ntot >= nmin) { nely = iy; break; } - - // rules (1,2) satisfied: coarsen in x-direction - if (3*nhy(iy) <= ntot && nelx%(3*nhx(iy)) == 0 && ntot+nhy(iy) < nmin) - { - refine(iy) = 0; - nhy (iy) *= 2; - auto vnhy = xt::view(nhy, xt::range(iy+1, _)); - auto vnhx = xt::view(nhx, xt::range(iy , _)); - vnhy *= 3; - vnhx *= 3; + return xt::arange(m_nelem).reshape({m_nely, m_nelx}); +} + +inline FineLayer::FineLayer(size_t nelx, size_t nely, double h, size_t nfine) : m_h(h) +{ + GOOSEFEM_ASSERT(nelx >= 1ul); + GOOSEFEM_ASSERT(nely >= 1ul); + + m_Lx = m_h * static_cast(nelx); + + // compute element size in y-direction (use symmetry, compute upper half) + + // temporary variables + size_t nmin, ntot; + xt::xtensor nhx = xt::ones({nely}); + xt::xtensor nhy = xt::ones({nely}); + xt::xtensor refine = -1 * xt::ones({nely}); + + // minimum height in y-direction (half of the height because of symmetry) + if (nely % 2 == 0) { + nmin = nely / 2; + } + else { + nmin = (nely + 1) / 2; + } + + // minimum number of fine layers in y-direction (minimum 1, middle layer part of this half) + if (nfine % 2 == 0) { + nfine = nfine / 2 + 1; + } + else { + nfine = (nfine + 1) / 2; + } + + if (nfine < 1) { + nfine = 1; + } + + if (nfine > nmin) { + nfine = nmin; } - // update the number of elements in y-direction - ntot += nhy(iy); - // proceed to next element layer in y-direction - ++iy; - // check to stop - if ( iy >= nely || ntot >= nmin ) { nely = iy; break; } - } - - // symmetrize, compute full information - // ------------------------------------ - - // allocate mesh constructor parameters - m_nhx = xt::empty({nely*2-1}); - m_nhy = xt::empty({nely*2-1}); - m_refine = xt::empty ({nely*2-1}); - m_nelx = xt::empty({nely*2-1}); - m_nnd = xt::empty({nely*2 }); - m_startElem = xt::empty({nely*2-1}); - m_startNode = xt::empty({nely*2 }); - - // fill - // - lower half - for (size_t iy = 0; iy < nely; ++iy) - { - m_nhx (iy) = nhx (nely-iy-1); - m_nhy (iy) = nhy (nely-iy-1); - m_refine(iy) = refine(nely-iy-1); - } - // - upper half - for (size_t iy = 0; iy < nely-1; ++iy) - { - m_nhx (iy+nely) = nhx (iy+1); - m_nhy (iy+nely) = nhy (iy+1); - m_refine(iy+nely) = refine(iy+1); - } - - // update size - nely = m_nhx.size(); - - // compute the number of elements per element layer in y-direction - for (size_t iy = 0; iy < nely; ++iy) - m_nelx(iy) = nelx / m_nhx(iy); - - // compute the number of nodes per node layer in y-direction - for ( size_t iy = 0 ; iy < (nely+1)/2 ; ++iy ) m_nnd(iy ) = m_nelx(iy)+1; - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) m_nnd(iy+1) = m_nelx(iy)+1; - - // compute mesh dimensions - // ----------------------- - - // initialize - m_nnode = 0; - m_nelem = 0; - m_startNode(0) = 0; - - // loop over element layers (bottom -> middle, elements become finer) - for (size_t i = 0; i < (nely-1)/2; ++i) - { - // - store the first element of the layer - m_startElem(i) = m_nelem; - // - add the nodes of this layer - if ( m_refine(i) == 0 ) { m_nnode += (3*m_nelx(i)+1); } - else { m_nnode += ( m_nelx(i)+1); } - // - add the elements of this layer - if ( m_refine(i) == 0 ) { m_nelem += (4*m_nelx(i) ); } - else { m_nelem += ( m_nelx(i) ); } - // - store the starting node of the next layer - m_startNode(i+1) = m_nnode; - } - - // loop over element layers (middle -> top, elements become coarser) - for (size_t i = (nely-1)/2; i < nely; ++i) - { - // - store the first element of the layer - m_startElem(i) = m_nelem; - // - add the nodes of this layer - if ( m_refine(i) == 0 ) { m_nnode += (5*m_nelx(i)+1); } - else { m_nnode += ( m_nelx(i)+1); } - // - add the elements of this layer - if ( m_refine(i) == 0 ) { m_nelem += (4*m_nelx(i) ); } - else { m_nelem += ( m_nelx(i) ); } - // - store the starting node of the next layer - m_startNode(i+1) = m_nnode; - } - // - add the top row of nodes - m_nnode += m_nelx(nely-1)+1; -} - -// ------------------------------------------------------------------------------------------------- + // loop over element layers in y-direction, try to coarsen using these rules: + // (1) element size in y-direction <= distance to origin in y-direction + // (2) element size in x-direction should fit the total number of elements in x-direction + // (3) a certain number of layers have the minimum size "1" (are fine) + for (size_t iy = nfine;;) { + // initialize current size in y-direction + if (iy == nfine) { + ntot = nfine; + } + // check to stop + if (iy >= nely || ntot >= nmin) { + nely = iy; + break; + } + + // rules (1,2) satisfied: coarsen in x-direction + if (3 * nhy(iy) <= ntot && nelx % (3 * nhx(iy)) == 0 && ntot + nhy(iy) < nmin) { + refine(iy) = 0; + nhy(iy) *= 2; + auto vnhy = xt::view(nhy, xt::range(iy + 1, _)); + auto vnhx = xt::view(nhx, xt::range(iy, _)); + vnhy *= 3; + vnhx *= 3; + } + + // update the number of elements in y-direction + ntot += nhy(iy); + // proceed to next element layer in y-direction + ++iy; + // check to stop + if (iy >= nely || ntot >= nmin) { + nely = iy; + break; + } + } + + // symmetrize, compute full information + + // allocate mesh constructor parameters + m_nhx = xt::empty({nely * 2 - 1}); + m_nhy = xt::empty({nely * 2 - 1}); + m_refine = xt::empty({nely * 2 - 1}); + m_nelx = xt::empty({nely * 2 - 1}); + m_nnd = xt::empty({nely * 2}); + m_startElem = xt::empty({nely * 2 - 1}); + m_startNode = xt::empty({nely * 2}); + + // fill + // - lower half + for (size_t iy = 0; iy < nely; ++iy) { + m_nhx(iy) = nhx(nely - iy - 1); + m_nhy(iy) = nhy(nely - iy - 1); + m_refine(iy) = refine(nely - iy - 1); + } + // - upper half + for (size_t iy = 0; iy < nely - 1; ++iy) { + m_nhx(iy + nely) = nhx(iy + 1); + m_nhy(iy + nely) = nhy(iy + 1); + m_refine(iy + nely) = refine(iy + 1); + } + + // update size + nely = m_nhx.size(); + + // compute the number of elements per element layer in y-direction + for (size_t iy = 0; iy < nely; ++iy) { + m_nelx(iy) = nelx / m_nhx(iy); + } + + // compute the number of nodes per node layer in y-direction + for (size_t iy = 0; iy < (nely + 1) / 2; ++iy) { + m_nnd(iy) = m_nelx(iy) + 1; + } + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + m_nnd(iy + 1) = m_nelx(iy) + 1; + } + + // compute mesh dimensions + + // initialize + m_nnode = 0; + m_nelem = 0; + m_startNode(0) = 0; + + // loop over element layers (bottom -> middle, elements become finer) + for (size_t i = 0; i < (nely - 1) / 2; ++i) { + // - store the first element of the layer + m_startElem(i) = m_nelem; + // - add the nodes of this layer + if (m_refine(i) == 0) { + m_nnode += (3 * m_nelx(i) + 1); + } + else { + m_nnode += (m_nelx(i) + 1); + } + // - add the elements of this layer + if (m_refine(i) == 0) { + m_nelem += (4 * m_nelx(i)); + } + else { + m_nelem += (m_nelx(i)); + } + // - store the starting node of the next layer + m_startNode(i + 1) = m_nnode; + } + + // loop over element layers (middle -> top, elements become coarser) + for (size_t i = (nely - 1) / 2; i < nely; ++i) { + // - store the first element of the layer + m_startElem(i) = m_nelem; + // - add the nodes of this layer + if (m_refine(i) == 0) { + m_nnode += (5 * m_nelx(i) + 1); + } + else { + m_nnode += (m_nelx(i) + 1); + } + // - add the elements of this layer + if (m_refine(i) == 0) { + m_nelem += (4 * m_nelx(i)); + } + else { + m_nelem += (m_nelx(i)); + } + // - store the starting node of the next layer + m_startNode(i + 1) = m_nnode; + } + // - add the top row of nodes + m_nnode += m_nelx(nely - 1) + 1; +} inline size_t FineLayer::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nelx() const { - return xt::amax(m_nelx)[0]; + return xt::amax(m_nelx)[0]; } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nely() const { - return xt::sum(m_nhy)[0]; + return xt::sum(m_nhy)[0]; } -// ------------------------------------------------------------------------------------------------- - inline double FineLayer::h() const { - return m_h; + return m_h; } -// ------------------------------------------------------------------------------------------------- - inline ElementType FineLayer::getElementType() const { - return ElementType::Quad4; + return ElementType::Quad4; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::coor() const { - // allocate output - xt::xtensor out = xt::empty({m_nnode, m_ndim}); - - // current node, number of element layers - size_t inode = 0; - size_t nely = static_cast(m_nhy.size()); - - // y-position of each main node layer (i.e. excluding node layers for refinement/coarsening) - // - allocate - xt::xtensor y = xt::empty({nely+1}); - // - initialize - y(0) = 0.0; - // - compute - for ( size_t iy = 1 ; iy < nely+1 ; ++iy ) - y(iy) = y(iy-1) + m_nhy(iy-1) * m_h; - - // loop over element layers (bottom -> middle) : add bottom layer (+ refinement layer) of nodes - // -------------------------------------------------------------------------------------------- - - for (size_t iy = 0; ; ++iy) - { - // get positions along the x- and z-axis - xt::xtensor x = xt::linspace(0.0, m_Lx, m_nelx(iy)+1); - - // add nodes of the bottom layer of this element - for (size_t ix = 0; ix < m_nelx(iy)+1; ++ix) { - out(inode,0) = x(ix); - out(inode,1) = y(iy); - ++inode; + // allocate output + xt::xtensor out = xt::empty({m_nnode, m_ndim}); + + // current node, number of element layers + size_t inode = 0; + size_t nely = static_cast(m_nhy.size()); + + // y-position of each main node layer (i.e. excluding node layers for refinement/coarsening) + // - allocate + xt::xtensor y = xt::empty({nely + 1}); + // - initialize + y(0) = 0.0; + // - compute + for (size_t iy = 1; iy < nely + 1; ++iy) { + y(iy) = y(iy - 1) + m_nhy(iy - 1) * m_h; } - // stop at middle layer - if (iy == (nely-1)/2) - break; - - // add extra nodes of the intermediate layer, for refinement in x-direction - if (m_refine(iy) == 0) - { - // - get position offset in x- and y-direction - double dx = m_h * static_cast(m_nhx(iy)/3); - double dy = m_h * static_cast(m_nhy(iy)/2); - // - add nodes of the intermediate layer - for (size_t ix = 0; ix < m_nelx(iy); ++ix) { - for (size_t j = 0; j < 2; ++j) { - out(inode,0) = x(ix) + dx * static_cast(j+1); - out(inode,1) = y(iy) + dy; - ++inode; + // loop over element layers (bottom -> middle) : add bottom layer (+ refinement layer) of nodes + + for (size_t iy = 0;; ++iy) { + // get positions along the x- and z-axis + xt::xtensor x = xt::linspace(0.0, m_Lx, m_nelx(iy) + 1); + + // add nodes of the bottom layer of this element + for (size_t ix = 0; ix < m_nelx(iy) + 1; ++ix) { + out(inode, 0) = x(ix); + out(inode, 1) = y(iy); + ++inode; } - } - } - } - - // loop over element layers (middle -> top) : add (refinement layer +) top layer of nodes - // -------------------------------------------------------------------------------------- - - for ( size_t iy = (nely-1)/2 ; iy < nely ; ++iy ) - { - // get positions along the x- and z-axis - xt::xtensor x = xt::linspace(0.0, m_Lx, m_nelx(iy)+1); - - // add extra nodes of the intermediate layer, for refinement in x-direction - if (m_refine(iy) == 0) - { - // - get position offset in x- and y-direction - double dx = m_h * static_cast(m_nhx(iy)/3); - double dy = m_h * static_cast(m_nhy(iy)/2); - // - add nodes of the intermediate layer - for (size_t ix = 0; ix < m_nelx(iy); ++ix) { - for (size_t j = 0; j < 2; ++j) { - out(inode,0) = x(ix) + dx * static_cast(j+1); - out(inode,1) = y(iy) + dy; - ++inode; + + // stop at middle layer + if (iy == (nely - 1) / 2) { + break; + } + + // add extra nodes of the intermediate layer, for refinement in x-direction + if (m_refine(iy) == 0) { + // - get position offset in x- and y-direction + double dx = m_h * static_cast(m_nhx(iy) / 3); + double dy = m_h * static_cast(m_nhy(iy) / 2); + // - add nodes of the intermediate layer + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + for (size_t j = 0; j < 2; ++j) { + out(inode, 0) = x(ix) + dx * static_cast(j + 1); + out(inode, 1) = y(iy) + dy; + ++inode; + } + } } - } } - // add nodes of the top layer of this element - for (size_t ix = 0; ix < m_nelx(iy)+1; ++ix) { - out(inode,0) = x(ix ); - out(inode,1) = y(iy+1); - ++inode; + // loop over element layers (middle -> top) : add (refinement layer +) top layer of nodes + + for (size_t iy = (nely - 1) / 2; iy < nely; ++iy) { + // get positions along the x- and z-axis + xt::xtensor x = xt::linspace(0.0, m_Lx, m_nelx(iy) + 1); + + // add extra nodes of the intermediate layer, for refinement in x-direction + if (m_refine(iy) == 0) { + // - get position offset in x- and y-direction + double dx = m_h * static_cast(m_nhx(iy) / 3); + double dy = m_h * static_cast(m_nhy(iy) / 2); + // - add nodes of the intermediate layer + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + for (size_t j = 0; j < 2; ++j) { + out(inode, 0) = x(ix) + dx * static_cast(j + 1); + out(inode, 1) = y(iy) + dy; + ++inode; + } + } + } + + // add nodes of the top layer of this element + for (size_t ix = 0; ix < m_nelx(iy) + 1; ++ix) { + out(inode, 0) = x(ix); + out(inode, 1) = y(iy + 1); + ++inode; + } } - } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::conn() const { - // allocate output - xt::xtensor out = xt::empty({m_nelem, m_nne}); - - // current element, number of element layers, starting nodes of each node layer - size_t ielem = 0; - size_t nely = static_cast(m_nhy.size()); - size_t bot,mid,top; - - // loop over all element layers - for (size_t iy = 0; iy < nely; ++iy) - { - // - get: starting nodes of bottom(, middle) and top layer - bot = m_startNode(iy ); - mid = m_startNode(iy ) + m_nnd(iy); - top = m_startNode(iy+1); - - // - define connectivity: no coarsening/refinement - if (m_refine(iy) == -1) - { - for (size_t ix = 0; ix < m_nelx(iy); ++ix) { - out(ielem,0) = bot + (ix ); - out(ielem,1) = bot + (ix+1); - out(ielem,2) = top + (ix+1); - out(ielem,3) = top + (ix ); - ielem++; - } - } + // allocate output + xt::xtensor out = xt::empty({m_nelem, m_nne}); + + // current element, number of element layers, starting nodes of each node layer + size_t ielem = 0; + size_t nely = static_cast(m_nhy.size()); + size_t bot, mid, top; + + // loop over all element layers + for (size_t iy = 0; iy < nely; ++iy) { + // - get: starting nodes of bottom(, middle) and top layer + bot = m_startNode(iy); + mid = m_startNode(iy) + m_nnd(iy); + top = m_startNode(iy + 1); + + // - define connectivity: no coarsening/refinement + if (m_refine(iy) == -1) { + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + out(ielem, 0) = bot + (ix); + out(ielem, 1) = bot + (ix + 1); + out(ielem, 2) = top + (ix + 1); + out(ielem, 3) = top + (ix); + ielem++; + } + } - // - define connectivity: refinement along the x-direction (below the middle layer) - else if (m_refine(iy) == 0 && iy <= (nely-1)/2) - { - for (size_t ix = 0; ix < m_nelx(iy); ++ix) { - // -- bottom element - out(ielem,0) = bot + ( ix ); - out(ielem,1) = bot + ( ix+1); - out(ielem,2) = mid + (2*ix+1); - out(ielem,3) = mid + (2*ix ); - ielem++; - // -- top-right element - out(ielem,0) = bot + ( ix+1); - out(ielem,1) = top + (3*ix+3); - out(ielem,2) = top + (3*ix+2); - out(ielem,3) = mid + (2*ix+1); - ielem++; - // -- top-center element - out(ielem,0) = mid + (2*ix ); - out(ielem,1) = mid + (2*ix+1); - out(ielem,2) = top + (3*ix+2); - out(ielem,3) = top + (3*ix+1); - ielem++; - // -- top-left element - out(ielem,0) = bot + ( ix ); - out(ielem,1) = mid + (2*ix ); - out(ielem,2) = top + (3*ix+1); - out(ielem,3) = top + (3*ix ); - ielem++; - } - } + // - define connectivity: refinement along the x-direction (below the middle layer) + else if (m_refine(iy) == 0 && iy <= (nely - 1) / 2) { + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + // -- bottom element + out(ielem, 0) = bot + (ix); + out(ielem, 1) = bot + (ix + 1); + out(ielem, 2) = mid + (2 * ix + 1); + out(ielem, 3) = mid + (2 * ix); + ielem++; + // -- top-right element + out(ielem, 0) = bot + (ix + 1); + out(ielem, 1) = top + (3 * ix + 3); + out(ielem, 2) = top + (3 * ix + 2); + out(ielem, 3) = mid + (2 * ix + 1); + ielem++; + // -- top-center element + out(ielem, 0) = mid + (2 * ix); + out(ielem, 1) = mid + (2 * ix + 1); + out(ielem, 2) = top + (3 * ix + 2); + out(ielem, 3) = top + (3 * ix + 1); + ielem++; + // -- top-left element + out(ielem, 0) = bot + (ix); + out(ielem, 1) = mid + (2 * ix); + out(ielem, 2) = top + (3 * ix + 1); + out(ielem, 3) = top + (3 * ix); + ielem++; + } + } - // - define connectivity: coarsening along the x-direction (above the middle layer) - else if (m_refine(iy) == 0 && iy > (nely-1)/2) - { - for (size_t ix = 0; ix < m_nelx(iy); ++ix) { - // -- lower-left element - out(ielem,0) = bot + (3*ix ); - out(ielem,1) = bot + (3*ix+1); - out(ielem,2) = mid + (2*ix ); - out(ielem,3) = top + ( ix ); - ielem++; - // -- lower-center element - out(ielem,0) = bot + (3*ix+1); - out(ielem,1) = bot + (3*ix+2); - out(ielem,2) = mid + (2*ix+1); - out(ielem,3) = mid + (2*ix ); - ielem++; - // -- lower-right element - out(ielem,0) = bot + (3*ix+2); - out(ielem,1) = bot + (3*ix+3); - out(ielem,2) = top + ( ix+1); - out(ielem,3) = mid + (2*ix+1); - ielem++; - // -- upper element - out(ielem,0) = mid + (2*ix ); - out(ielem,1) = mid + (2*ix+1); - out(ielem,2) = top + ( ix+1); - out(ielem,3) = top + ( ix ); - ielem++; - } + // - define connectivity: coarsening along the x-direction (above the middle layer) + else if (m_refine(iy) == 0 && iy > (nely - 1) / 2) { + for (size_t ix = 0; ix < m_nelx(iy); ++ix) { + // -- lower-left element + out(ielem, 0) = bot + (3 * ix); + out(ielem, 1) = bot + (3 * ix + 1); + out(ielem, 2) = mid + (2 * ix); + out(ielem, 3) = top + (ix); + ielem++; + // -- lower-center element + out(ielem, 0) = bot + (3 * ix + 1); + out(ielem, 1) = bot + (3 * ix + 2); + out(ielem, 2) = mid + (2 * ix + 1); + out(ielem, 3) = mid + (2 * ix); + ielem++; + // -- lower-right element + out(ielem, 0) = bot + (3 * ix + 2); + out(ielem, 1) = bot + (3 * ix + 3); + out(ielem, 2) = top + (ix + 1); + out(ielem, 3) = mid + (2 * ix + 1); + ielem++; + // -- upper element + out(ielem, 0) = mid + (2 * ix); + out(ielem, 1) = mid + (2 * ix + 1); + out(ielem, 2) = top + (ix + 1); + out(ielem, 3) = top + (ix); + ielem++; + } + } } - } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::elementsMiddleLayer() const { - // number of element layers in y-direction - size_t nely = m_nhy.size(); - - // index of the middle layer - size_t iy = (nely-1)/2; - - // element indices - return m_startElem(iy) + xt::arange(m_nelx(iy)); + size_t nely = m_nhy.size(); + size_t iy = (nely - 1) / 2; + return m_startElem(iy) + xt::arange(m_nelx(iy)); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesBottomEdge() const { - return m_startNode(0) + xt::arange(m_nelx(0)+1); + return m_startNode(0) + xt::arange(m_nelx(0) + 1); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesTopEdge() const { - size_t nely = m_nhy.size(); - - return m_startNode(nely) + xt::arange(m_nelx(nely-1)+1); + size_t nely = m_nhy.size(); + return m_startNode(nely) + xt::arange(m_nelx(nely - 1) + 1); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesLeftEdge() const { - size_t nely = m_nhy.size(); + size_t nely = m_nhy.size(); - xt::xtensor out = xt::empty({nely+1}); + xt::xtensor out = xt::empty({nely + 1}); - size_t i = 0; - size_t j = (nely+1)/2; - size_t k = (nely-1)/2; - size_t l = nely; + size_t i = 0; + size_t j = (nely + 1) / 2; + size_t k = (nely - 1) / 2; + size_t l = nely; - xt::view(out, xt::range(i , j )) = xt::view(m_startNode, xt::range(i , j )); - xt::view(out, xt::range(k+1, l+1)) = xt::view(m_startNode, xt::range(k+1, l+1)); + xt::view(out, xt::range(i, j)) = xt::view(m_startNode, xt::range(i, j)); + xt::view(out, xt::range(k + 1, l + 1)) = xt::view(m_startNode, xt::range(k + 1, l + 1)); - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesRightEdge() const { - size_t nely = m_nhy.size(); + size_t nely = m_nhy.size(); - xt::xtensor out = xt::empty({nely+1}); + xt::xtensor out = xt::empty({nely + 1}); - size_t i = 0; - size_t j = (nely+1)/2; - size_t k = (nely-1)/2; - size_t l = nely; + size_t i = 0; + size_t j = (nely + 1) / 2; + size_t k = (nely - 1) / 2; + size_t l = nely; - xt::view(out, xt::range(i, j)) = - xt::view(m_startNode, xt::range(i, j)) + xt::view(m_nelx, xt::range(i, j)); + xt::view(out, xt::range(i, j)) = + xt::view(m_startNode, xt::range(i, j)) + xt::view(m_nelx, xt::range(i, j)); - xt::view(out, xt::range(k+1, l+1)) = - xt::view(m_startNode, xt::range(k+1, l+1)) + xt::view(m_nelx, xt::range(k, l)); + xt::view(out, xt::range(k + 1, l + 1)) = + xt::view(m_startNode, xt::range(k + 1, l + 1)) + xt::view(m_nelx, xt::range(k, l)); - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesBottomOpenEdge() const { - return m_startNode(0) + xt::arange(1, m_nelx(0)); + return m_startNode(0) + xt::arange(1, m_nelx(0)); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesTopOpenEdge() const { - size_t nely = m_nhy.size(); + size_t nely = m_nhy.size(); - return m_startNode(nely) + xt::arange(1, m_nelx(nely-1)); + return m_startNode(nely) + xt::arange(1, m_nelx(nely - 1)); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesLeftOpenEdge() const { - size_t nely = m_nhy.size(); + size_t nely = m_nhy.size(); - xt::xtensor out = xt::empty({nely-1}); + xt::xtensor out = xt::empty({nely - 1}); - size_t i = 0; - size_t j = (nely+1)/2; - size_t k = (nely-1)/2; - size_t l = nely; + size_t i = 0; + size_t j = (nely + 1) / 2; + size_t k = (nely - 1) / 2; + size_t l = nely; - xt::view(out, xt::range(i, j-1)) = xt::view(m_startNode, xt::range(i+1, j)); - xt::view(out, xt::range(k, l-1)) = xt::view(m_startNode, xt::range(k+1, l)); + xt::view(out, xt::range(i, j - 1)) = xt::view(m_startNode, xt::range(i + 1, j)); + xt::view(out, xt::range(k, l - 1)) = xt::view(m_startNode, xt::range(k + 1, l)); - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesRightOpenEdge() const { - size_t nely = m_nhy.size(); + size_t nely = m_nhy.size(); - xt::xtensor out = xt::empty({nely-1}); + xt::xtensor out = xt::empty({nely - 1}); - size_t i = 0; - size_t j = (nely+1)/2; - size_t k = (nely-1)/2; - size_t l = nely; + size_t i = 0; + size_t j = (nely + 1) / 2; + size_t k = (nely - 1) / 2; + size_t l = nely; - xt::view(out, xt::range(i, j-1)) = - xt::view(m_startNode, xt::range(i+1, j)) + xt::view(m_nelx, xt::range(i+1, j)); + xt::view(out, xt::range(i, j - 1)) = + xt::view(m_startNode, xt::range(i + 1, j)) + xt::view(m_nelx, xt::range(i + 1, j)); - xt::view(out, xt::range(k, l-1)) = - xt::view(m_startNode, xt::range(k+1, l)) + xt::view(m_nelx, xt::range(k, l-1)); + xt::view(out, xt::range(k, l - 1)) = + xt::view(m_startNode, xt::range(k + 1, l)) + xt::view(m_nelx, xt::range(k, l - 1)); - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesBottomLeftCorner() const { - return m_startNode(0); + return m_startNode(0); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesBottomRightCorner() const { - return m_startNode(0) + m_nelx(0); + return m_startNode(0) + m_nelx(0); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesTopLeftCorner() const { - size_t nely = m_nhy.size(); + size_t nely = m_nhy.size(); - return m_startNode(nely); + return m_startNode(nely); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesTopRightCorner() const { - size_t nely = m_nhy.size(); + size_t nely = m_nhy.size(); - return m_startNode(nely) + m_nelx(nely-1); + return m_startNode(nely) + m_nelx(nely - 1); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesLeftBottomCorner() const { - return nodesBottomLeftCorner(); + return nodesBottomLeftCorner(); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesRightBottomCorner() const { - return nodesBottomRightCorner(); + return nodesBottomRightCorner(); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesLeftTopCorner() const { - return nodesTopLeftCorner(); + return nodesTopLeftCorner(); } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesRightTopCorner() const { - return nodesTopRightCorner(); + return nodesTopRightCorner(); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::nodesPeriodic() const { - // edges (without corners) - xt::xtensor bot = nodesBottomOpenEdge(); - xt::xtensor top = nodesTopOpenEdge(); - xt::xtensor lft = nodesLeftOpenEdge(); - xt::xtensor rgt = nodesRightOpenEdge(); + xt::xtensor bot = nodesBottomOpenEdge(); + xt::xtensor top = nodesTopOpenEdge(); + xt::xtensor lft = nodesLeftOpenEdge(); + xt::xtensor rgt = nodesRightOpenEdge(); - // allocate nodal ties - xt::xtensor out = xt::empty({bot.size() + lft.size() + 3ul, 2ul}); + xt::xtensor out = xt::empty({bot.size() + lft.size() + 3ul, 2ul}); - // tie all corners to one corner + out(0, 0) = nodesBottomLeftCorner(); + out(0, 1) = nodesBottomRightCorner(); - out(0,0) = nodesBottomLeftCorner(); out(0,1) = nodesBottomRightCorner(); - out(1,0) = nodesBottomLeftCorner(); out(1,1) = nodesTopRightCorner(); - out(2,0) = nodesBottomLeftCorner(); out(2,1) = nodesTopLeftCorner(); + out(1, 0) = nodesBottomLeftCorner(); + out(1, 1) = nodesTopRightCorner(); - // tie all corresponding edges to each other + out(2, 0) = nodesBottomLeftCorner(); + out(2, 1) = nodesTopLeftCorner(); - size_t i = 3; + size_t i = 3; - xt::view(out, xt::range(i, i+bot.size()), 0) = bot; - xt::view(out, xt::range(i, i+bot.size()), 1) = top; + xt::view(out, xt::range(i, i + bot.size()), 0) = bot; + xt::view(out, xt::range(i, i + bot.size()), 1) = top; - i += bot.size(); + i += bot.size(); - xt::view(out, xt::range(i, i+lft.size()), 0) = lft; - xt::view(out, xt::range(i, i+lft.size()), 1) = rgt; + xt::view(out, xt::range(i, i + lft.size()), 0) = lft; + xt::view(out, xt::range(i, i + lft.size()), 1) = rgt; - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline size_t FineLayer::nodesOrigin() const { - return nodesBottomLeftCorner(); + return nodesBottomLeftCorner(); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::dofs() const { - return GooseFEM::Mesh::dofs(m_nnode, m_ndim); + return GooseFEM::Mesh::dofs(m_nnode, m_ndim); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor FineLayer::dofsPeriodic() const { - // DOF-numbers for each component of each node (sequential) - xt::xtensor out = GooseFEM::Mesh::dofs(m_nnode, m_ndim); - - // periodic node-pairs - xt::xtensor nodePer = nodesPeriodic(); - - // node sets - xt::xtensor independent = xt::view(nodePer, xt::all(), 0); - xt::xtensor dependent = xt::view(nodePer, xt::all(), 1); + xt::xtensor out = GooseFEM::Mesh::dofs(m_nnode, m_ndim); + xt::xtensor nodePer = nodesPeriodic(); + xt::xtensor independent = xt::view(nodePer, xt::all(), 0); + xt::xtensor dependent = xt::view(nodePer, xt::all(), 1); - // eliminate 'dependent' DOFs; renumber "out" to be sequential for the remaining DOFs - for (size_t j = 0; j < m_ndim; ++j) - xt::view(out, xt::keep(dependent), j) = xt::view(out, xt::keep(independent), j); + for (size_t j = 0; j < m_ndim; ++j) { + xt::view(out, xt::keep(dependent), j) = xt::view(out, xt::keep(independent), j); + } - // renumber "out" to be sequential - return GooseFEM::Mesh::renumber(out); + return GooseFEM::Mesh::renumber(out); } -// ------------------------------------------------------------------------------------------------- - -namespace Map -{ - -// ------------------------------------------------------------------------------------------------- +namespace Map { inline RefineRegular::RefineRegular( - const GooseFEM::Mesh::Quad4::Regular &mesh, - size_t nx, - size_t ny) : - m_coarse(mesh) + const GooseFEM::Mesh::Quad4::Regular& mesh, size_t nx, size_t ny) + : m_coarse(mesh) { - m_fine = Regular(nx * m_coarse.nelx(), ny * m_coarse.nely(), m_coarse.h()); + m_fine = Regular(nx * m_coarse.nelx(), ny * m_coarse.nely(), m_coarse.h()); - xt::xtensor elmat_coarse = m_coarse.elementMatrix(); - xt::xtensor elmat_fine = m_fine.elementMatrix(); + xt::xtensor elmat_coarse = m_coarse.elementMatrix(); + xt::xtensor elmat_fine = m_fine.elementMatrix(); - m_coarse2fine = xt::empty({m_coarse.nelem(), nx * ny}); + m_coarse2fine = xt::empty({m_coarse.nelem(), nx * ny}); - for (size_t i = 0; i < elmat_coarse.shape(0); ++i) { - for (size_t j = 0; j < elmat_coarse.shape(1); ++j) { - xt::view(m_coarse2fine, elmat_coarse(i, j), xt::all()) = - xt::flatten(xt::view( - elmat_fine, - xt::range(i*ny, (i+1)*ny), - xt::range(j*nx, (j+1)*nx))); + for (size_t i = 0; i < elmat_coarse.shape(0); ++i) { + for (size_t j = 0; j < elmat_coarse.shape(1); ++j) { + xt::view(m_coarse2fine, elmat_coarse(i, j), xt::all()) = xt::flatten(xt::view( + elmat_fine, xt::range(i * ny, (i + 1) * ny), xt::range(j * nx, (j + 1) * nx))); + } } - } } -// ------------------------------------------------------------------------------------------------- - inline GooseFEM::Mesh::Quad4::Regular RefineRegular::getCoarseMesh() const { - return m_coarse; + return m_coarse; } -// ------------------------------------------------------------------------------------------------- - inline GooseFEM::Mesh::Quad4::Regular RefineRegular::getFineMesh() const { - return m_fine; + return m_fine; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor RefineRegular::getMap() const { - return m_coarse2fine; + return m_coarse2fine; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor RefineRegular::mapToCoarse(const xt::xtensor &data) const +inline xt::xtensor RefineRegular::mapToCoarse(const xt::xtensor& data) const { - GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.size()); + GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.size()); - size_t m = m_coarse2fine.shape(0); - size_t n = m_coarse2fine.shape(1); + size_t m = m_coarse2fine.shape(0); + size_t n = m_coarse2fine.shape(1); - xt::xtensor out = xt::empty({m, n}); + xt::xtensor out = xt::empty({m, n}); - for (size_t i = 0; i < m; ++i) { - auto e = xt::view(m_coarse2fine, i, xt::all()); - xt::view(out, i) = xt::view(data, xt::keep(e)); - } + for (size_t i = 0; i < m; ++i) { + auto e = xt::view(m_coarse2fine, i, xt::all()); + xt::view(out, i) = xt::view(data, xt::keep(e)); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor RefineRegular::mapToCoarse(const xt::xtensor &data) const +inline xt::xtensor RefineRegular::mapToCoarse(const xt::xtensor& data) const { - GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.size()); + GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.size()); - size_t m = m_coarse2fine.shape(0); - size_t n = m_coarse2fine.shape(1); - size_t N = data.shape(1); + size_t m = m_coarse2fine.shape(0); + size_t n = m_coarse2fine.shape(1); + size_t N = data.shape(1); - xt::xtensor out = xt::empty({m, n * N}); + xt::xtensor out = xt::empty({m, n * N}); - for (size_t i = 0; i < m; ++i) { - auto e = xt::view(m_coarse2fine, i, xt::all()); - for (size_t q = 0; q < data.shape(1); ++q) - xt::view(out, i, xt::range(q + 0, q + n * N, N)) = xt::view(data, xt::keep(e), q); - } + for (size_t i = 0; i < m; ++i) { + auto e = xt::view(m_coarse2fine, i, xt::all()); + for (size_t q = 0; q < data.shape(1); ++q) { + xt::view(out, i, xt::range(q + 0, q + n * N, N)) = xt::view(data, xt::keep(e), q); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor RefineRegular::mapToCoarse(const xt::xtensor &data) const +inline xt::xtensor RefineRegular::mapToCoarse(const xt::xtensor& data) const { - GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.size()); + GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.size()); - size_t m = m_coarse2fine.shape(0); - size_t n = m_coarse2fine.shape(1); - size_t N = data.shape(1); + size_t m = m_coarse2fine.shape(0); + size_t n = m_coarse2fine.shape(1); + size_t N = data.shape(1); - xt::xtensor out = xt::empty({m, n * N, data.shape(2), data.shape(3)}); + xt::xtensor out = xt::empty({m, n * N, data.shape(2), data.shape(3)}); - for (size_t i = 0; i < m; ++i) { - auto e = xt::view(m_coarse2fine, i, xt::all()); - for (size_t q = 0; q < data.shape(1); ++q) - xt::view(out, i, xt::range(q + 0, q + n * N, N)) = xt::view(data, xt::keep(e), q); - } + for (size_t i = 0; i < m; ++i) { + auto e = xt::view(m_coarse2fine, i, xt::all()); + for (size_t q = 0; q < data.shape(1); ++q) { + xt::view(out, i, xt::range(q + 0, q + n * N, N)) = xt::view(data, xt::keep(e), q); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor RefineRegular::mapToFine(const xt::xtensor &data) const +inline xt::xtensor RefineRegular::mapToFine(const xt::xtensor& data) const { - GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.shape(0)); + GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.shape(0)); - xt::xtensor out = xt::empty({m_coarse2fine.size()}); + xt::xtensor out = xt::empty({m_coarse2fine.size()}); - for (size_t i = 0; i < m_coarse2fine.shape(0); ++i) { - auto e = xt::view(m_coarse2fine, i, xt::all()); - xt::view(out, xt::keep(e)) = data(i); - } + for (size_t i = 0; i < m_coarse2fine.shape(0); ++i) { + auto e = xt::view(m_coarse2fine, i, xt::all()); + xt::view(out, xt::keep(e)) = data(i); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor RefineRegular::mapToFine(const xt::xtensor &data) const +inline xt::xtensor RefineRegular::mapToFine(const xt::xtensor& data) const { - GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.shape(0)); + GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.shape(0)); - xt::xtensor out = xt::empty({m_coarse2fine.size(), data.shape(1)}); + xt::xtensor out = xt::empty({m_coarse2fine.size(), data.shape(1)}); - for (size_t i = 0; i < m_coarse2fine.shape(0); ++i) { - auto e = xt::view(m_coarse2fine, i, xt::all()); - xt::view(out, xt::keep(e)) = xt::view(data, i); - } + for (size_t i = 0; i < m_coarse2fine.shape(0); ++i) { + auto e = xt::view(m_coarse2fine, i, xt::all()); + xt::view(out, xt::keep(e)) = xt::view(data, i); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor RefineRegular::mapToFine(const xt::xtensor &data) const +inline xt::xtensor RefineRegular::mapToFine(const xt::xtensor& data) const { - GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.shape(0)); + GOOSEFEM_ASSERT(data.shape(0) == m_coarse2fine.shape(0)); - xt::xtensor out = - xt::empty({m_coarse2fine.size(), data.shape(1), data.shape(2), data.shape(3)}); + xt::xtensor out = + xt::empty({m_coarse2fine.size(), data.shape(1), data.shape(2), data.shape(3)}); - for (size_t i = 0; i < m_coarse2fine.shape(0); ++i) { - auto e = xt::view(m_coarse2fine, i, xt::all()); - xt::view(out, xt::keep(e)) = xt::view(data, i); - } + for (size_t i = 0; i < m_coarse2fine.shape(0); ++i) { + auto e = xt::view(m_coarse2fine, i, xt::all()); + xt::view(out, xt::keep(e)) = xt::view(data, i); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline FineLayer2Regular::FineLayer2Regular(const GooseFEM::Mesh::Quad4::FineLayer &mesh) : - m_finelayer(mesh) +inline FineLayer2Regular::FineLayer2Regular(const GooseFEM::Mesh::Quad4::FineLayer& mesh) + : m_finelayer(mesh) { - // ------------ - // Regular-mesh - // ------------ + // ------------ + // Regular-mesh + // ------------ - m_regular = GooseFEM::Mesh::Quad4::Regular( - xt::amax(m_finelayer.m_nelx)[0], - xt::sum(m_finelayer.m_nhy)[0], - m_finelayer.m_h - ); + m_regular = GooseFEM::Mesh::Quad4::Regular( + xt::amax(m_finelayer.m_nelx)[0], xt::sum(m_finelayer.m_nhy)[0], m_finelayer.m_h); - // ------- - // mapping - // ------- + // ------- + // mapping + // ------- - // allocate mapping - m_elem_regular.resize(m_finelayer.m_nelem); - m_frac_regular.resize(m_finelayer.m_nelem); + // allocate mapping + m_elem_regular.resize(m_finelayer.m_nelem); + m_frac_regular.resize(m_finelayer.m_nelem); - // alias - xt::xtensor nhx = m_finelayer.m_nhx; - xt::xtensor nhy = m_finelayer.m_nhy; - xt::xtensor nelx = m_finelayer.m_nelx; - xt::xtensor start = m_finelayer.m_startElem; + // alias + xt::xtensor nhx = m_finelayer.m_nhx; + xt::xtensor nhy = m_finelayer.m_nhy; + xt::xtensor nelx = m_finelayer.m_nelx; + xt::xtensor start = m_finelayer.m_startElem; - // 'matrix' of element numbers of the Regular-mesh - xt::xtensor elementMatrix = m_regular.elementMatrix(); + // 'matrix' of element numbers of the Regular-mesh + xt::xtensor elementMatrix = m_regular.elementMatrix(); - // cumulative number of element-rows of the Regular-mesh per layer of the FineLayer-mesh - xt::xtensor cum_nhy = - xt::concatenate(xt::xtuple(xt::zeros({1}), xt::cumsum(nhy))); + // cumulative number of element-rows of the Regular-mesh per layer of the FineLayer-mesh + xt::xtensor cum_nhy = + xt::concatenate(xt::xtuple(xt::zeros({1}), xt::cumsum(nhy))); - // number of element layers in y-direction of the FineLayer-mesh - size_t nely = nhy.size(); + // number of element layers in y-direction of the FineLayer-mesh + size_t nely = nhy.size(); - // loop over layers of the FineLayer-mesh - for (size_t iy = 0; iy < nely; ++iy) - { - // element numbers of the Regular-mesh along this layer of the FineLayer-mesh - auto el_new = xt::view(elementMatrix, xt::range(cum_nhy(iy), cum_nhy(iy+1)), xt::all()); + // loop over layers of the FineLayer-mesh + for (size_t iy = 0; iy < nely; ++iy) { + // element numbers of the Regular-mesh along this layer of the FineLayer-mesh + auto el_new = xt::view(elementMatrix, xt::range(cum_nhy(iy), cum_nhy(iy + 1)), xt::all()); - // no coarsening/refinement - // ------------------------ + // no coarsening/refinement + // ------------------------ - if (m_finelayer.m_refine(iy) == -1) - { - // element numbers of the FineLayer-mesh along this layer - xt::xtensor el_old = start(iy) + xt::arange(nelx(iy)); + if (m_finelayer.m_refine(iy) == -1) { + // element numbers of the FineLayer-mesh along this layer + xt::xtensor el_old = start(iy) + xt::arange(nelx(iy)); - // loop along this layer of the FineLayer-mesh - for (size_t ix = 0; ix < nelx(iy); ++ix) - { - // get the element numbers of the Regular-mesh for this element of the FineLayer-mesh - auto block = xt::view(el_new, xt::all(), xt::range(ix*nhx(iy), (ix+1)*nhx(iy))); + // loop along this layer of the FineLayer-mesh + for (size_t ix = 0; ix < nelx(iy); ++ix) { + // get the element numbers of the Regular-mesh for this element of the + // FineLayer-mesh + auto block = + xt::view(el_new, xt::all(), xt::range(ix * nhx(iy), (ix + 1) * nhx(iy))); - // write to mapping - for (auto &i: block) { - m_elem_regular[el_old(ix)].push_back(i); - m_frac_regular[el_old(ix)].push_back(1.0); - } - } - } - - // refinement along the x-direction (below the middle layer) - // --------------------------------------------------------- - - else if (m_finelayer.m_refine(iy) == 0 && iy <= (nely-1)/2) - { - // element numbers of the FineLayer-mesh along this layer - // rows: coarse block, columns element numbers per block - xt::xtensor el_old = start(iy) + xt::arange(nelx(iy)*4ul).reshape({-1, 4}); - - // loop along this layer of the FineLayer-mesh - for (size_t ix = 0; ix < nelx(iy); ++ix) - { - // get the element numbers of the Regular-mesh for this block of the FineLayer-mesh - auto block = xt::view(el_new, xt::all(), xt::range(ix*nhx(iy), (ix+1)*nhx(iy))); - - // bottom: wide-to-narrow - { - for (size_t j = 0; j < nhy(iy)/2; ++j) - { - auto e = xt::view(block, j, xt::range(j, nhx(iy)-j)); - - m_elem_regular[el_old(ix,0)].push_back(e(0)); - m_frac_regular[el_old(ix,0)].push_back(0.5); - - for (size_t k = 1; k < e.size()-1; ++k) { - m_elem_regular[el_old(ix,0)].push_back(e(k)); - m_frac_regular[el_old(ix,0)].push_back(1.0); + // write to mapping + for (auto& i : block) { + m_elem_regular[el_old(ix)].push_back(i); + m_frac_regular[el_old(ix)].push_back(1.0); + } } - - m_elem_regular[el_old(ix,0)].push_back(e(e.size()-1)); - m_frac_regular[el_old(ix,0)].push_back(0.5); - } - } - - // top: regular small element - { - auto e = xt::view(block, - xt::range(nhy(iy)/2, nhy(iy)), - xt::range(1*nhx(iy)/3, 2*nhx(iy)/3)); - - for (auto &i: e) { - m_elem_regular[el_old(ix,2)].push_back(i); - m_frac_regular[el_old(ix,2)].push_back(1.0); - } } - // left - { - // left-bottom: narrow-to-wide - for (size_t j = 0; j < nhy(iy)/2; ++j) - { - auto e = xt::view(block, j, xt::range(0, j+1)); - - for (size_t k = 0; k < e.size()-1; ++k) { - m_elem_regular[el_old(ix,3)].push_back(e(k)); - m_frac_regular[el_old(ix,3)].push_back(1.0); + // refinement along the x-direction (below the middle layer) + // --------------------------------------------------------- + + else if (m_finelayer.m_refine(iy) == 0 && iy <= (nely - 1) / 2) { + // element numbers of the FineLayer-mesh along this layer + // rows: coarse block, columns element numbers per block + xt::xtensor el_old = + start(iy) + xt::arange(nelx(iy) * 4ul).reshape({-1, 4}); + + // loop along this layer of the FineLayer-mesh + for (size_t ix = 0; ix < nelx(iy); ++ix) { + // get the element numbers of the Regular-mesh for this block of the FineLayer-mesh + auto block = + xt::view(el_new, xt::all(), xt::range(ix * nhx(iy), (ix + 1) * nhx(iy))); + + // bottom: wide-to-narrow + { + for (size_t j = 0; j < nhy(iy) / 2; ++j) { + auto e = xt::view(block, j, xt::range(j, nhx(iy) - j)); + + m_elem_regular[el_old(ix, 0)].push_back(e(0)); + m_frac_regular[el_old(ix, 0)].push_back(0.5); + + for (size_t k = 1; k < e.size() - 1; ++k) { + m_elem_regular[el_old(ix, 0)].push_back(e(k)); + m_frac_regular[el_old(ix, 0)].push_back(1.0); + } + + m_elem_regular[el_old(ix, 0)].push_back(e(e.size() - 1)); + m_frac_regular[el_old(ix, 0)].push_back(0.5); + } + } + + // top: regular small element + { + auto e = xt::view( + block, + xt::range(nhy(iy) / 2, nhy(iy)), + xt::range(1 * nhx(iy) / 3, 2 * nhx(iy) / 3)); + + for (auto& i : e) { + m_elem_regular[el_old(ix, 2)].push_back(i); + m_frac_regular[el_old(ix, 2)].push_back(1.0); + } + } + + // left + { + // left-bottom: narrow-to-wide + for (size_t j = 0; j < nhy(iy) / 2; ++j) { + auto e = xt::view(block, j, xt::range(0, j + 1)); + + for (size_t k = 0; k < e.size() - 1; ++k) { + m_elem_regular[el_old(ix, 3)].push_back(e(k)); + m_frac_regular[el_old(ix, 3)].push_back(1.0); + } + + m_elem_regular[el_old(ix, 3)].push_back(e(e.size() - 1)); + m_frac_regular[el_old(ix, 3)].push_back(0.5); + } + + // left-top: regular + { + auto e = xt::view( + block, + xt::range(nhy(iy) / 2, nhy(iy)), + xt::range(0 * nhx(iy) / 3, 1 * nhx(iy) / 3)); + + for (auto& i : e) { + m_elem_regular[el_old(ix, 3)].push_back(i); + m_frac_regular[el_old(ix, 3)].push_back(1.0); + } + } + } + + // right + { + // right-bottom: narrow-to-wide + for (size_t j = 0; j < nhy(iy) / 2; ++j) { + auto e = xt::view(block, j, xt::range(nhx(iy) - j - 1, nhx(iy))); + + m_elem_regular[el_old(ix, 1)].push_back(e(0)); + m_frac_regular[el_old(ix, 1)].push_back(0.5); + + for (size_t k = 1; k < e.size(); ++k) { + m_elem_regular[el_old(ix, 1)].push_back(e(k)); + m_frac_regular[el_old(ix, 1)].push_back(1.0); + } + } + + // right-top: regular + { + auto e = xt::view( + block, + xt::range(nhy(iy) / 2, nhy(iy)), + xt::range(2 * nhx(iy) / 3, 3 * nhx(iy) / 3)); + + for (auto& i : e) { + m_elem_regular[el_old(ix, 1)].push_back(i); + m_frac_regular[el_old(ix, 1)].push_back(1.0); + } + } + } } - - m_elem_regular[el_old(ix,3)].push_back(e(e.size()-1)); - m_frac_regular[el_old(ix,3)].push_back(0.5); - } - - // left-top: regular - { - auto e = xt::view(block, - xt::range(nhy(iy)/2, nhy(iy)), - xt::range(0*nhx(iy)/3, 1*nhx(iy)/3)); - - for (auto &i: e) { - m_elem_regular[el_old(ix,3)].push_back(i); - m_frac_regular[el_old(ix,3)].push_back(1.0); - } - } } - // right - { - // right-bottom: narrow-to-wide - for (size_t j = 0; j < nhy(iy)/2; ++j) - { - auto e = xt::view(block, j, xt::range(nhx(iy)-j-1, nhx(iy))); - - m_elem_regular[el_old(ix,1)].push_back(e(0)); - m_frac_regular[el_old(ix,1)].push_back(0.5); - - for (size_t k = 1; k < e.size(); ++k) { - m_elem_regular[el_old(ix,1)].push_back(e(k)); - m_frac_regular[el_old(ix,1)].push_back(1.0); + // coarsening along the x-direction (above the middle layer) + else if (m_finelayer.m_refine(iy) == 0 && iy > (nely - 1) / 2) { + // element numbers of the FineLayer-mesh along this layer + // rows: coarse block, columns element numbers per block + xt::xtensor el_old = + start(iy) + xt::arange(nelx(iy) * 4ul).reshape({-1, 4}); + + // loop along this layer of the FineLayer-mesh + for (size_t ix = 0; ix < nelx(iy); ++ix) { + // get the element numbers of the Regular-mesh for this block of the FineLayer-mesh + auto block = + xt::view(el_new, xt::all(), xt::range(ix * nhx(iy), (ix + 1) * nhx(iy))); + + // top: narrow-to-wide + { + for (size_t j = 0; j < nhy(iy) / 2; ++j) { + auto e = xt::view( + block, + nhy(iy) / 2 + j, + xt::range(1 * nhx(iy) / 3 - j - 1, 2 * nhx(iy) / 3 + j + 1)); + + m_elem_regular[el_old(ix, 3)].push_back(e(0)); + m_frac_regular[el_old(ix, 3)].push_back(0.5); + + for (size_t k = 1; k < e.size() - 1; ++k) { + m_elem_regular[el_old(ix, 3)].push_back(e(k)); + m_frac_regular[el_old(ix, 3)].push_back(1.0); + } + + m_elem_regular[el_old(ix, 3)].push_back(e(e.size() - 1)); + m_frac_regular[el_old(ix, 3)].push_back(0.5); + } + } + + // bottom: regular small element + { + auto e = xt::view( + block, + xt::range(0, nhy(iy) / 2), + xt::range(1 * nhx(iy) / 3, 2 * nhx(iy) / 3)); + + for (auto& i : e) { + m_elem_regular[el_old(ix, 1)].push_back(i); + m_frac_regular[el_old(ix, 1)].push_back(1.0); + } + } + + // left + { + // left-bottom: regular + { + auto e = xt::view( + block, + xt::range(0, nhy(iy) / 2), + xt::range(0 * nhx(iy) / 3, 1 * nhx(iy) / 3)); + + for (auto& i : e) { + m_elem_regular[el_old(ix, 0)].push_back(i); + m_frac_regular[el_old(ix, 0)].push_back(1.0); + } + } + + // left-top: narrow-to-wide + for (size_t j = 0; j < nhy(iy) / 2; ++j) { + auto e = + xt::view(block, nhy(iy) / 2 + j, xt::range(0, 1 * nhx(iy) / 3 - j)); + + for (size_t k = 0; k < e.size() - 1; ++k) { + m_elem_regular[el_old(ix, 0)].push_back(e(k)); + m_frac_regular[el_old(ix, 0)].push_back(1.0); + } + + m_elem_regular[el_old(ix, 0)].push_back(e(e.size() - 1)); + m_frac_regular[el_old(ix, 0)].push_back(0.5); + } + } + + // right + { + // right-bottom: regular + { + auto e = xt::view( + block, + xt::range(0, nhy(iy) / 2), + xt::range(2 * nhx(iy) / 3, 3 * nhx(iy) / 3)); + + for (auto& i : e) { + m_elem_regular[el_old(ix, 2)].push_back(i); + m_frac_regular[el_old(ix, 2)].push_back(1.0); + } + } + + // right-top: narrow-to-wide + for (size_t j = 0; j < nhy(iy) / 2; ++j) { + auto e = xt::view( + block, nhy(iy) / 2 + j, xt::range(2 * nhx(iy) / 3 + j, nhx(iy))); + + m_elem_regular[el_old(ix, 2)].push_back(e(0)); + m_frac_regular[el_old(ix, 2)].push_back(0.5); + + for (size_t k = 1; k < e.size(); ++k) { + m_elem_regular[el_old(ix, 2)].push_back(e(k)); + m_frac_regular[el_old(ix, 2)].push_back(1.0); + } + } + } } - } - - // right-top: regular - { - auto e = xt::view(block, - xt::range(nhy(iy)/2, nhy(iy)), - xt::range(2*nhx(iy)/3, 3*nhx(iy)/3)); - - for (auto &i: e) { - m_elem_regular[el_old(ix,1)].push_back(i); - m_frac_regular[el_old(ix,1)].push_back(1.0); - } - } } - } } - - // coarsening along the x-direction (above the middle layer) - else if (m_finelayer.m_refine(iy) == 0 && iy > (nely-1)/2) - { - // element numbers of the FineLayer-mesh along this layer - // rows: coarse block, columns element numbers per block - xt::xtensor el_old = start(iy) + xt::arange(nelx(iy)*4ul).reshape({-1, 4}); - - // loop along this layer of the FineLayer-mesh - for (size_t ix = 0; ix < nelx(iy); ++ix) - { - // get the element numbers of the Regular-mesh for this block of the FineLayer-mesh - auto block = xt::view(el_new, xt::all(), xt::range(ix*nhx(iy), (ix+1)*nhx(iy))); - - // top: narrow-to-wide - { - for (size_t j = 0; j < nhy(iy)/2; ++j) - { - auto e = xt::view(block, - nhy(iy)/2+j, - xt::range(1*nhx(iy)/3-j-1, 2*nhx(iy)/3+j+1)); - - m_elem_regular[el_old(ix,3)].push_back(e(0)); - m_frac_regular[el_old(ix,3)].push_back(0.5); - - for (size_t k = 1; k < e.size()-1; ++k) { - m_elem_regular[el_old(ix,3)].push_back(e(k)); - m_frac_regular[el_old(ix,3)].push_back(1.0); - } - - m_elem_regular[el_old(ix,3)].push_back(e(e.size()-1)); - m_frac_regular[el_old(ix,3)].push_back(0.5); - } - } - - // bottom: regular small element - { - auto e = xt::view(block, - xt::range(0, nhy(iy)/2), - xt::range(1*nhx(iy)/3, 2*nhx(iy)/3)); - - for (auto &i: e) { - m_elem_regular[el_old(ix,1)].push_back(i); - m_frac_regular[el_old(ix,1)].push_back(1.0); - } - } - - // left - { - // left-bottom: regular - { - auto e = xt::view(block, - xt::range(0, nhy(iy)/2), - xt::range(0*nhx(iy)/3, 1*nhx(iy)/3)); - - for (auto &i: e) { - m_elem_regular[el_old(ix,0)].push_back(i); - m_frac_regular[el_old(ix,0)].push_back(1.0); - } - } - - // left-top: narrow-to-wide - for (size_t j = 0; j < nhy(iy)/2; ++j) - { - auto e = xt::view(block, - nhy(iy)/2+j, - xt::range(0, 1*nhx(iy)/3-j)); - - for (size_t k = 0; k < e.size()-1; ++k) { - m_elem_regular[el_old(ix,0)].push_back(e(k)); - m_frac_regular[el_old(ix,0)].push_back(1.0); - } - - m_elem_regular[el_old(ix,0)].push_back(e(e.size()-1)); - m_frac_regular[el_old(ix,0)].push_back(0.5); - } - } - - // right - { - // right-bottom: regular - { - auto e = xt::view(block, - xt::range(0, nhy(iy)/2), - xt::range(2*nhx(iy)/3, 3*nhx(iy)/3)); - - for (auto &i: e) { - m_elem_regular[el_old(ix,2)].push_back(i); - m_frac_regular[el_old(ix,2)].push_back(1.0); - } - } - - // right-top: narrow-to-wide - for (size_t j = 0; j < nhy(iy)/2; ++j) - { - auto e = xt::view(block, - nhy(iy)/2+j, - xt::range(2*nhx(iy)/3+j, nhx(iy))); - - m_elem_regular[el_old(ix,2)].push_back(e(0)); - m_frac_regular[el_old(ix,2)].push_back(0.5); - - for (size_t k = 1; k < e.size(); ++k) { - m_elem_regular[el_old(ix,2)].push_back(e(k)); - m_frac_regular[el_old(ix,2)].push_back(1.0); - } - } - } - } - } - } } -// ------------------------------------------------------------------------------------------------- - inline GooseFEM::Mesh::Quad4::Regular FineLayer2Regular::getRegularMesh() const { - return m_regular; + return m_regular; } -// ------------------------------------------------------------------------------------------------- - inline GooseFEM::Mesh::Quad4::FineLayer FineLayer2Regular::getFineLayerMesh() const { - return m_finelayer; + return m_finelayer; } -// ------------------------------------------------------------------------------------------------- - inline std::vector> FineLayer2Regular::getMap() const { - return m_elem_regular; + return m_elem_regular; } -// ------------------------------------------------------------------------------------------------- - inline std::vector> FineLayer2Regular::getMapFraction() const { - return m_frac_regular; + return m_frac_regular; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer2Regular::mapToRegular( - const xt::xtensor &data) const +inline xt::xtensor +FineLayer2Regular::mapToRegular(const xt::xtensor& data) const { - GOOSEFEM_ASSERT(data.shape(0) == m_finelayer.nelem()); + GOOSEFEM_ASSERT(data.shape(0) == m_finelayer.nelem()); - xt::xtensor out = xt::zeros({m_regular.nelem()}); + xt::xtensor out = xt::zeros({m_regular.nelem()}); - for (size_t e = 0; e < m_finelayer.nelem(); ++e) - for (size_t i = 0; i < m_elem_regular[e].size(); ++i) - out(m_elem_regular[e][i]) += m_frac_regular[e][i] * data(e); + for (size_t e = 0; e < m_finelayer.nelem(); ++e) { + for (size_t i = 0; i < m_elem_regular[e].size(); ++i) { + out(m_elem_regular[e][i]) += m_frac_regular[e][i] * data(e); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer2Regular::mapToRegular( - const xt::xtensor &data) const +inline xt::xtensor +FineLayer2Regular::mapToRegular(const xt::xtensor& data) const { - GOOSEFEM_ASSERT(data.shape(0) == m_finelayer.nelem()); + GOOSEFEM_ASSERT(data.shape(0) == m_finelayer.nelem()); - xt::xtensor out = xt::zeros({m_regular.nelem(), data.shape(1)}); + xt::xtensor out = xt::zeros({m_regular.nelem(), data.shape(1)}); - for (size_t e = 0; e < m_finelayer.nelem(); ++e) - for (size_t i = 0; i < m_elem_regular[e].size(); ++i) - xt::view(out, m_elem_regular[e][i]) += m_frac_regular[e][i] * xt::view(data, e); + for (size_t e = 0; e < m_finelayer.nelem(); ++e) { + for (size_t i = 0; i < m_elem_regular[e].size(); ++i) { + xt::view(out, m_elem_regular[e][i]) += m_frac_regular[e][i] * xt::view(data, e); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor FineLayer2Regular::mapToRegular( - const xt::xtensor &data) const +inline xt::xtensor +FineLayer2Regular::mapToRegular(const xt::xtensor& data) const { - GOOSEFEM_ASSERT(data.shape(0) == m_finelayer.nelem()); + GOOSEFEM_ASSERT(data.shape(0) == m_finelayer.nelem()); - xt::xtensor out = - xt::zeros({m_regular.nelem(), data.shape(1), data.shape(2), data.shape(3)}); + xt::xtensor out = + xt::zeros({m_regular.nelem(), data.shape(1), data.shape(2), data.shape(3)}); - for (size_t e = 0; e < m_finelayer.nelem(); ++e) - for (size_t i = 0; i < m_elem_regular[e].size(); ++i) - xt::view(out, m_elem_regular[e][i]) += m_frac_regular[e][i] * xt::view(data, e); + for (size_t e = 0; e < m_finelayer.nelem(); ++e) { + for (size_t i = 0; i < m_elem_regular[e].size(); ++i) { + xt::view(out, m_elem_regular[e][i]) += m_frac_regular[e][i] * xt::view(data, e); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - } // namespace Map -// ------------------------------------------------------------------------------------------------- - -}}} // namespace ... - -// ================================================================================================= +} // namespace Quad4 +} // namespace Mesh +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/MeshTri3.hpp b/include/GooseFEM/MeshTri3.hpp index 5f30a8d..cc71dd7 100644 --- a/include/GooseFEM/MeshTri3.hpp +++ b/include/GooseFEM/MeshTri3.hpp @@ -1,414 +1,354 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_MESHTRI3_HPP #define GOOSEFEM_MESHTRI3_HPP -// ------------------------------------------------------------------------------------------------- - #include "MeshTri3.h" -// ================================================================================================= - namespace GooseFEM { namespace Mesh { namespace Tri3 { -// ------------------------------------------------------------------------------------------------- - -inline Regular::Regular(size_t nelx, size_t nely, double h): -m_h(h), m_nelx(nelx), m_nely(nely) +inline Regular::Regular(size_t nelx, size_t nely, double h) : m_h(h), m_nelx(nelx), m_nely(nely) { - GOOSEFEM_ASSERT(m_nelx >= 1ul); - GOOSEFEM_ASSERT(m_nely >= 1ul); + GOOSEFEM_ASSERT(m_nelx >= 1ul); + GOOSEFEM_ASSERT(m_nely >= 1ul); - m_nnode = (m_nelx+1) * (m_nely+1); - m_nelem = m_nelx * m_nely * 2; + m_nnode = (m_nelx + 1) * (m_nely + 1); + m_nelem = m_nelx * m_nely * 2; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline ElementType Regular::getElementType() const { - return ElementType::Tri3; + return ElementType::Tri3; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::coor() const { - xt::xtensor out = xt::empty({m_nnode, m_ndim}); + xt::xtensor out = xt::empty({m_nnode, m_ndim}); - xt::xtensor x = xt::linspace(0.0, m_h*static_cast(m_nelx), m_nelx+1); - xt::xtensor y = xt::linspace(0.0, m_h*static_cast(m_nely), m_nely+1); + xt::xtensor x = + xt::linspace(0.0, m_h * static_cast(m_nelx), m_nelx + 1); + xt::xtensor y = + xt::linspace(0.0, m_h * static_cast(m_nely), m_nely + 1); - size_t inode = 0; + size_t inode = 0; - for ( size_t iy = 0; iy < m_nely+1; ++iy) { - for ( size_t ix = 0; ix < m_nelx+1; ++ix) { - out(inode,0) = x(ix); - out(inode,1) = y(iy); - ++inode; + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(inode, 0) = x(ix); + out(inode, 1) = y(iy); + ++inode; + } } - } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::conn() const { - xt::xtensor out = xt::empty({m_nelem,m_nne}); - - size_t ielem = 0; - - for ( size_t iy = 0; iy < m_nely; ++iy) { - for ( size_t ix = 0; ix < m_nelx; ++ix) { - out(ielem,0) = (iy )*(m_nelx+1) + (ix ); - out(ielem,1) = (iy )*(m_nelx+1) + (ix+1); - out(ielem,2) = (iy+1)*(m_nelx+1) + (ix ); - ++ielem; - out(ielem,0) = (iy )*(m_nelx+1) + (ix+1); - out(ielem,1) = (iy+1)*(m_nelx+1) + (ix+1); - out(ielem,2) = (iy+1)*(m_nelx+1) + (ix ); - ++ielem; + xt::xtensor out = xt::empty({m_nelem, m_nne}); + + size_t ielem = 0; + + for (size_t iy = 0; iy < m_nely; ++iy) { + for (size_t ix = 0; ix < m_nelx; ++ix) { + out(ielem, 0) = (iy) * (m_nelx + 1) + (ix); + out(ielem, 1) = (iy) * (m_nelx + 1) + (ix + 1); + out(ielem, 2) = (iy + 1) * (m_nelx + 1) + (ix); + ++ielem; + out(ielem, 0) = (iy) * (m_nelx + 1) + (ix + 1); + out(ielem, 1) = (iy + 1) * (m_nelx + 1) + (ix + 1); + out(ielem, 2) = (iy + 1) * (m_nelx + 1) + (ix); + ++ielem; + } } - } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBottomEdge() const { - xt::xtensor out = xt::empty({m_nelx+1}); + xt::xtensor out = xt::empty({m_nelx + 1}); - for (size_t ix = 0; ix < m_nelx+1; ++ix) - out(ix) = ix; + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(ix) = ix; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesTopEdge() const { - xt::xtensor out = xt::empty({m_nelx+1}); + xt::xtensor out = xt::empty({m_nelx + 1}); - for (size_t ix = 0; ix < m_nelx+1; ++ix) - out(ix) = ix + m_nely*(m_nelx+1); + for (size_t ix = 0; ix < m_nelx + 1; ++ix) { + out(ix) = ix + m_nely * (m_nelx + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesLeftEdge() const { - xt::xtensor out = xt::empty({m_nely+1}); + xt::xtensor out = xt::empty({m_nely + 1}); - for (size_t iy = 0; iy < m_nely+1; ++iy) - out(iy) = iy*(m_nelx+1); + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + out(iy) = iy * (m_nelx + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesRightEdge() const { - xt::xtensor out = xt::empty({m_nely+1}); + xt::xtensor out = xt::empty({m_nely + 1}); - for (size_t iy = 0; iy < m_nely+1; ++iy) - out(iy) = iy*(m_nelx+1) + m_nelx; + for (size_t iy = 0; iy < m_nely + 1; ++iy) { + out(iy) = iy * (m_nelx + 1) + m_nelx; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesBottomOpenEdge() const { - xt::xtensor out = xt::empty({m_nelx-1}); + xt::xtensor out = xt::empty({m_nelx - 1}); - for (size_t ix = 1; ix < m_nelx; ++ix) - out(ix-1) = ix; + for (size_t ix = 1; ix < m_nelx; ++ix) { + out(ix - 1) = ix; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesTopOpenEdge() const { - xt::xtensor out = xt::empty({m_nelx-1}); + xt::xtensor out = xt::empty({m_nelx - 1}); - for (size_t ix = 1; ix < m_nelx; ++ix) - out(ix-1) = ix + m_nely*(m_nelx+1); + for (size_t ix = 1; ix < m_nelx; ++ix) { + out(ix - 1) = ix + m_nely * (m_nelx + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesLeftOpenEdge() const { - xt::xtensor out = xt::empty({m_nely-1}); + xt::xtensor out = xt::empty({m_nely - 1}); - for (size_t iy = 1; iy < m_nely; ++iy) - out(iy-1) = iy*(m_nelx+1); + for (size_t iy = 1; iy < m_nely; ++iy) { + out(iy - 1) = iy * (m_nelx + 1); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesRightOpenEdge() const { - xt::xtensor out = xt::empty({m_nely-1}); + xt::xtensor out = xt::empty({m_nely - 1}); - for (size_t iy = 1; iy < m_nely; ++iy) - out(iy-1) = iy*(m_nelx+1) + m_nelx; + for (size_t iy = 1; iy < m_nely; ++iy) { + out(iy - 1) = iy * (m_nelx + 1) + m_nelx; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesBottomLeftCorner() const { - return 0; + return 0; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesBottomRightCorner() const { - return m_nelx; + return m_nelx; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesTopLeftCorner() const { - return m_nely*(m_nelx+1); + return m_nely * (m_nelx + 1); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesTopRightCorner() const { - return m_nely*(m_nelx+1) + m_nelx; + return m_nely * (m_nelx + 1) + m_nelx; } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesLeftBottomCorner() const { - return nodesBottomLeftCorner(); + return nodesBottomLeftCorner(); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesLeftTopCorner() const { - return nodesTopLeftCorner(); + return nodesTopLeftCorner(); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesRightBottomCorner() const { - return nodesBottomRightCorner(); + return nodesBottomRightCorner(); } -// ------------------------------------------------------------------------------------------------- - inline size_t Regular::nodesRightTopCorner() const { - return nodesTopRightCorner(); + return nodesTopRightCorner(); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::nodesPeriodic() const { - // edges (without corners) - xt::xtensor bot = nodesBottomOpenEdge(); - xt::xtensor top = nodesTopOpenEdge(); - xt::xtensor lft = nodesLeftOpenEdge(); - xt::xtensor rgt = nodesRightOpenEdge(); - - // allocate nodal ties - // - number of tying per category - size_t tedge = bot.size() + lft.size(); - size_t tnode = 3; - // - allocate - xt::xtensor out = xt::empty({tedge+tnode, std::size_t(2)}); - - // counter - size_t i = 0; - - // tie all corners to one corner - out(i,0) = nodesBottomLeftCorner(); out(i,1) = nodesBottomRightCorner(); ++i; - out(i,0) = nodesBottomLeftCorner(); out(i,1) = nodesTopRightCorner(); ++i; - out(i,0) = nodesBottomLeftCorner(); out(i,1) = nodesTopLeftCorner(); ++i; - - // tie all corresponding edges to each other - for (size_t j = 0; j < bot.size(); ++j) { - out(i,0) = bot(j); - out(i,1) = top(j); + xt::xtensor bot = nodesBottomOpenEdge(); + xt::xtensor top = nodesTopOpenEdge(); + xt::xtensor lft = nodesLeftOpenEdge(); + xt::xtensor rgt = nodesRightOpenEdge(); + + size_t tedge = bot.size() + lft.size(); + size_t tnode = 3; + xt::xtensor out = xt::empty({tedge + tnode, std::size_t(2)}); + + size_t i = 0; + + out(i, 0) = nodesBottomLeftCorner(); + out(i, 1) = nodesBottomRightCorner(); ++i; - } - for (size_t j = 0; j < lft.size(); ++j) { - out(i,0) = lft(j); - out(i,1) = rgt(j); + out(i, 0) = nodesBottomLeftCorner(); + out(i, 1) = nodesTopRightCorner(); + ++i; + out(i, 0) = nodesBottomLeftCorner(); + out(i, 1) = nodesTopLeftCorner(); ++i; - } - return out; -} + for (size_t j = 0; j < bot.size(); ++j) { + out(i, 0) = bot(j); + out(i, 1) = top(j); + ++i; + } + for (size_t j = 0; j < lft.size(); ++j) { + out(i, 0) = lft(j); + out(i, 1) = rgt(j); + ++i; + } -// ------------------------------------------------------------------------------------------------- + return out; +} inline size_t Regular::nodesOrigin() const { - return nodesBottomLeftCorner(); + return nodesBottomLeftCorner(); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::dofs() const { - return GooseFEM::Mesh::dofs(m_nnode,m_ndim); + return GooseFEM::Mesh::dofs(m_nnode, m_ndim); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Regular::dofsPeriodic() const { - // DOF-numbers for each component of each node (sequential) - xt::xtensor out = GooseFEM::Mesh::dofs(m_nnode,m_ndim); + xt::xtensor out = GooseFEM::Mesh::dofs(m_nnode, m_ndim); + xt::xtensor nodePer = nodesPeriodic(); - // periodic node-pairs - xt::xtensor nodePer = nodesPeriodic(); - - // eliminate 'dependent' DOFs; renumber "out" to be sequential for the remaining DOFs - for (size_t i = 0; i < nodePer.shape(0); ++i) - for (size_t j = 0; j < m_ndim; ++j) - out(nodePer(i,1),j) = out(nodePer(i,0),j); + for (size_t i = 0; i < nodePer.shape(0); ++i) { + for (size_t j = 0; j < m_ndim; ++j) { + out(nodePer(i, 1), j) = out(nodePer(i, 0), j); + } + } - // renumber "out" to be sequential - return GooseFEM::Mesh::renumber(out); + return GooseFEM::Mesh::renumber(out); } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor getOrientation( - const xt::xtensor &coor, - const xt::xtensor &conn) +inline xt::xtensor +getOrientation(const xt::xtensor& coor, const xt::xtensor& conn) { - GOOSEFEM_ASSERT(conn.shape(1) == 3ul); - GOOSEFEM_ASSERT(coor.shape(1) == 2ul); + GOOSEFEM_ASSERT(conn.shape(1) == 3ul); + GOOSEFEM_ASSERT(coor.shape(1) == 2ul); - double k; - size_t nelem = conn.shape(0); + double k; + size_t nelem = conn.shape(0); - xt::xtensor out = xt::empty({nelem}); + xt::xtensor out = xt::empty({nelem}); - for (size_t ielem = 0; ielem < nelem; ++ielem ) - { - auto v1 = xt::view(coor, conn(ielem,0), xt::all()) - xt::view(coor, conn(ielem,1), xt::all()); - auto v2 = xt::view(coor, conn(ielem,2), xt::all()) - xt::view(coor, conn(ielem,1), xt::all()); + for (size_t ielem = 0; ielem < nelem; ++ielem) { + auto v1 = + xt::view(coor, conn(ielem, 0), xt::all()) - xt::view(coor, conn(ielem, 1), xt::all()); + auto v2 = + xt::view(coor, conn(ielem, 2), xt::all()) - xt::view(coor, conn(ielem, 1), xt::all()); - k = v1(0) * v2(1) - v2(0) * v1(1); + k = v1(0) * v2(1) - v2(0) * v1(1); - if ( k < 0 ) out(ielem) = -1; - else out(ielem) = +1; - } + if (k < 0) { + out(ielem) = -1; + } + else { + out(ielem) = +1; + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor setOrientation( - const xt::xtensor &coor, - const xt::xtensor &conn, - int orientation) + const xt::xtensor& coor, const xt::xtensor& conn, int orientation) { - GOOSEFEM_ASSERT(conn.shape(1) == 3ul); - GOOSEFEM_ASSERT(coor.shape(1) == 2ul); - GOOSEFEM_ASSERT(orientation == -1 || orientation == +1); + GOOSEFEM_ASSERT(conn.shape(1) == 3ul); + GOOSEFEM_ASSERT(coor.shape(1) == 2ul); + GOOSEFEM_ASSERT(orientation == -1 || orientation == +1); - xt::xtensor val = getOrientation(coor, conn); + xt::xtensor val = getOrientation(coor, conn); - return setOrientation(coor, conn, val, orientation); + return setOrientation(coor, conn, val, orientation); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor setOrientation( - const xt::xtensor &coor, - const xt::xtensor &conn, - const xt::xtensor &val, - int orientation) + const xt::xtensor& coor, + const xt::xtensor& conn, + const xt::xtensor& val, + int orientation) { - GOOSEFEM_ASSERT(conn.shape(1) == 3ul); - GOOSEFEM_ASSERT(coor.shape(1) == 2ul); - GOOSEFEM_ASSERT(conn.shape(0) == val.size()); - GOOSEFEM_ASSERT(orientation == -1 || orientation == +1); + GOOSEFEM_ASSERT(conn.shape(1) == 3ul); + GOOSEFEM_ASSERT(coor.shape(1) == 2ul); + GOOSEFEM_ASSERT(conn.shape(0) == val.size()); + GOOSEFEM_ASSERT(orientation == -1 || orientation == +1); - // avoid compiler warning - UNUSED(coor); + UNUSED(coor); - size_t nelem = conn.shape(0); - xt::xtensor out = conn; + size_t nelem = conn.shape(0); + xt::xtensor out = conn; - for (size_t ielem = 0; ielem < nelem; ++ielem) - if ((orientation == -1 && val(ielem) > 0) || (orientation == +1 && val(ielem) < 0)) - std::swap(out(ielem,2) , out(ielem,1)); + for (size_t ielem = 0; ielem < nelem; ++ielem) { + if ((orientation == -1 && val(ielem) > 0) || (orientation == +1 && val(ielem) < 0)) { + std::swap(out(ielem, 2), out(ielem, 1)); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -}}} // namespace ... - -// ================================================================================================= +} // namespace Tri3 +} // namespace Mesh +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/ParaView.hpp b/include/GooseFEM/ParaView.hpp index 6483e21..c8dd4d0 100644 --- a/include/GooseFEM/ParaView.hpp +++ b/include/GooseFEM/ParaView.hpp @@ -1,804 +1,671 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_PARAVIEW_HPP #define GOOSEFEM_PARAVIEW_HPP -// ------------------------------------------------------------------------------------------------- - #include "ParaView.h" -// ================================================================================================= - namespace GooseFEM { namespace ParaView { namespace HDF5 { -// ------------------------------------------------------------------------------------------------- - -inline std::string join(const std::vector& lines, const std::string &sep) +inline std::string join(const std::vector& lines, const std::string& sep) { - if (lines.size() == 1) - return lines[0]; - - std::string out = ""; - - for (auto line: lines) - { - if (out.size() == 0) - { - out += line; - continue; + if (lines.size() == 1) { + return lines[0]; } - if (line[0] == sep[0]) out += line; - else if (out[out.size()-1] == sep[0]) out += line; - else out += sep + line; - } + std::string out = ""; + + for (auto line : lines) { + if (out.size() == 0) { + out += line; + continue; + } + + if (line[0] == sep[0]) { + out += line; + } + else if (out[out.size() - 1] == sep[0]) { + out += line; + } + else { + out += sep + line; + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------- ------ - inline std::string indent(size_t n) { - std::string out = ""; + std::string out = ""; - for (size_t i = 0; i < n; ++i) - out += " "; + for (size_t i = 0; i < n; ++i) { + out += " "; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - -xt::xtensor as3d(const xt::xtensor &data) +xt::xtensor as3d(const xt::xtensor& data) { - GOOSEFEM_ASSERT(data.shape(1) > 0 && data.shape(1) < 4) + GOOSEFEM_ASSERT(data.shape(1) > 0 && data.shape(1) < 4) - if (data.shape(1) == 3ul) - return data; + if (data.shape(1) == 3ul) { + return data; + } - xt::xtensor out = xt::zeros({data.shape(0), 3ul}); + xt::xtensor out = xt::zeros({data.shape(0), 3ul}); - if (data.shape(1) == 2ul) - xt::view(out, xt::all(), xt::keep(0,1)) = data; + if (data.shape(1) == 2ul) { + xt::view(out, xt::all(), xt::keep(0, 1)) = data; + } - if (data.shape(1) == 1ul) - xt::view(out, xt::all(), xt::keep(0)) = data; + if (data.shape(1) == 1ul) { + xt::view(out, xt::all(), xt::keep(0)) = data; + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline ElementType convert(GooseFEM::Mesh::ElementType type) { - if (type == GooseFEM::Mesh::ElementType::Tri3) - return ElementType::Triangle; + if (type == GooseFEM::Mesh::ElementType::Tri3) { + return ElementType::Triangle; + } - if (type == GooseFEM::Mesh::ElementType::Quad4) - return ElementType::Quadrilateral; + if (type == GooseFEM::Mesh::ElementType::Quad4) { + return ElementType::Quadrilateral; + } - if (type == GooseFEM::Mesh::ElementType::Hex8) - return ElementType::Hexahedron; + if (type == GooseFEM::Mesh::ElementType::Hex8) { + return ElementType::Hexahedron; + } - throw std::runtime_error("Unknown GooseFEM::Mesh::ElementType"); + throw std::runtime_error("Unknown GooseFEM::Mesh::ElementType"); } -// ------------------------------------------------------------------------------------------------- - inline std::string to_string(ElementType type) { - if (type == ElementType::Triangle) - return "Triangle"; + if (type == ElementType::Triangle) { + return "Triangle"; + } - if (type == ElementType::Quadrilateral) - return "Quadrilateral"; + if (type == ElementType::Quadrilateral) { + return "Quadrilateral"; + } - if (type == ElementType::Hexahedron) - return "Hexahedron"; + if (type == ElementType::Hexahedron) { + return "Hexahedron"; + } - throw std::runtime_error("Unknown GooseFEM::ParaView::HDF5::ElementType"); + throw std::runtime_error("Unknown GooseFEM::ParaView::HDF5::ElementType"); } -// ------------------------------------------------------------------------------------------------- - inline std::string to_string(AttributeType type) { - if (type == AttributeType::Cell) - return "Cell"; + if (type == AttributeType::Cell) { + return "Cell"; + } - if (type == AttributeType::Node) - return "Node"; + if (type == AttributeType::Node) { + return "Node"; + } - throw std::runtime_error("Unknown GooseFEM::ParaView::HDF5::AttributeType"); + throw std::runtime_error("Unknown GooseFEM::ParaView::HDF5::AttributeType"); } -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline Connectivity::Connectivity( - const H5Easy::File& data, - const std::string& dataset, - GooseFEM::Mesh::ElementType type) + const H5Easy::File& data, const std::string& dataset, GooseFEM::Mesh::ElementType type) { - init(data, dataset, convert(type)); + init(data, dataset, convert(type)); } #endif -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline Connectivity::Connectivity( - const std::string& fname, - const std::string& dataset, - GooseFEM::Mesh::ElementType type) + const std::string& fname, const std::string& dataset, GooseFEM::Mesh::ElementType type) { - init(fname, dataset, convert(type)); + init(fname, dataset, convert(type)); } #endif -// ------------------------------------------------------------------------------------------------- - inline Connectivity::Connectivity( - const std::string& fname, - const std::string& dataset, - GooseFEM::Mesh::ElementType type, - const std::vector& shape) + const std::string& fname, + const std::string& dataset, + GooseFEM::Mesh::ElementType type, + const std::vector& shape) { - init(fname, dataset, convert(type), shape); + init(fname, dataset, convert(type), shape); } -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline Connectivity::Connectivity( - const H5Easy::File& data, - const std::string& dataset, - ElementType type) + const H5Easy::File& data, const std::string& dataset, ElementType type) { - init(data, dataset, type); + init(data, dataset, type); } #endif -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline Connectivity::Connectivity( - const std::string& fname, - const std::string& dataset, - ElementType type) + const std::string& fname, const std::string& dataset, ElementType type) { - init(fname, dataset, type); + init(fname, dataset, type); } #endif -// ------------------------------------------------------------------------------------------------- - inline Connectivity::Connectivity( - const std::string& fname, - const std::string& dataset, - ElementType type, - const std::vector& shape) + const std::string& fname, + const std::string& dataset, + ElementType type, + const std::vector& shape) { - init(fname, dataset, type, shape); + init(fname, dataset, type, shape); } -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE -inline void Connectivity::init( - const H5Easy::File& data, - const std::string& dataset, - ElementType type) +inline void +Connectivity::init(const H5Easy::File& data, const std::string& dataset, ElementType type) { - m_type = type; - m_dataset = dataset; + m_type = type; + m_dataset = dataset; - this->readShape(data); + this->readShape(data); } #endif -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE -inline void Connectivity::init( - const std::string& fname, - const std::string& dataset, - ElementType type) +inline void +Connectivity::init(const std::string& fname, const std::string& dataset, ElementType type) { - m_type = type; - m_fname = fname; - m_dataset = dataset; + m_type = type; + m_fname = fname; + m_dataset = dataset; - H5Easy::File data(m_fname, H5Easy::File::ReadOnly); + H5Easy::File data(m_fname, H5Easy::File::ReadOnly); - this->readShape(data); + this->readShape(data); } #endif -// ------------------------------------------------------------------------------------------------- - inline void Connectivity::init( - const std::string& fname, - const std::string& dataset, - ElementType type, - const std::vector& shape) + const std::string& fname, + const std::string& dataset, + ElementType type, + const std::vector& shape) { - m_type = type; - m_fname = fname; - m_dataset = dataset; - m_shape = shape; + m_type = type; + m_fname = fname; + m_dataset = dataset; + m_shape = shape; - GOOSEFEM_ASSERT(m_shape.size() == 2); + GOOSEFEM_ASSERT(m_shape.size() == 2); - #ifdef GOOSEFEM_ENABLE_ASSERT - if (m_type == ElementType::Triangle) { - GOOSEFEM_ASSERT(m_shape[1] == 3); - } - else if (m_type == ElementType::Quadrilateral) { - GOOSEFEM_ASSERT(m_shape[1] == 4); - } - else if (m_type == ElementType::Hexahedron) { - GOOSEFEM_ASSERT(m_shape[1] == 8); - } - #endif + #ifdef GOOSEFEM_ENABLE_ASSERT + if (m_type == ElementType::Triangle) { + GOOSEFEM_ASSERT(m_shape[1] == 3); + } + else if (m_type == ElementType::Quadrilateral) { + GOOSEFEM_ASSERT(m_shape[1] == 4); + } + else if (m_type == ElementType::Hexahedron) { + GOOSEFEM_ASSERT(m_shape[1] == 8); + } + #endif } -// ------------------------------------------------------------------------------------------------- - inline size_t Connectivity::nelem() const { - return m_shape[0]; + return m_shape[0]; } -// ------------------------------------------------------------------------------------------------- - inline size_t Connectivity::nne() const { - return m_shape[1]; + return m_shape[1]; } -// ------------------------------------------------------------------------------------------------- - inline std::vector Connectivity::shape() const { - return m_shape; + return m_shape; } -// ------------------------------------------------------------------------------------------------- - inline std::string Connectivity::fname() const { - return m_fname; + return m_fname; } -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline void Connectivity::checkShape() { - if (m_verified) - return; + if (m_verified) + return; - H5Easy::File data(m_fname, H5Easy::File::ReadOnly); + H5Easy::File data(m_fname, H5Easy::File::ReadOnly); - GOOSEFEM_CHECK(m_shape == H5Easy::getShape(data, m_dataset)); + GOOSEFEM_CHECK(m_shape == H5Easy::getShape(data, m_dataset)); - m_verified = true; + m_verified = true; } #endif -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline void Connectivity::readShape(const H5Easy::File& data) { - if (m_fname.size() == 0) - m_fname = data.getName(); + if (m_fname.size() == 0) + m_fname = data.getName(); - m_shape = H5Easy::getShape(data, m_dataset); + m_shape = H5Easy::getShape(data, m_dataset); - GOOSEFEM_ASSERT(m_shape.size() == 2); + GOOSEFEM_ASSERT(m_shape.size() == 2); - #ifdef GOOSEFEM_ENABLE_ASSERT - if (m_type == ElementType::Triangle) { - GOOSEFEM_ASSERT(m_shape[1] == 3); - } - else if (m_type == ElementType::Quadrilateral) { - GOOSEFEM_ASSERT(m_shape[1] == 4); - } - else if (m_type == ElementType::Hexahedron) { - GOOSEFEM_ASSERT(m_shape[1] == 8); - } - #endif + #ifdef GOOSEFEM_ENABLE_ASSERT + if (m_type == ElementType::Triangle) { + GOOSEFEM_ASSERT(m_shape[1] == 3); + } + else if (m_type == ElementType::Quadrilateral) { + GOOSEFEM_ASSERT(m_shape[1] == 4); + } + else if (m_type == ElementType::Hexahedron) { + GOOSEFEM_ASSERT(m_shape[1] == 8); + } + #endif - m_verified = true; + m_verified = true; } #endif -// ------------------------------------------------------------------------------------------------- - inline std::vector Connectivity::xdmf(size_t n_indent) const { - std::vector out; + std::vector out; - out.push_back( - ""); + out.push_back( + ""); - out.push_back(indent(n_indent) + - "" + m_fname + ":" + m_dataset + ""); + out.push_back( + indent(n_indent) + "" + m_fname + ":" + m_dataset + + ""); - out.push_back(""); + out.push_back(""); - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE -inline Coordinates::Coordinates( - const H5Easy::File& data, - const std::string& dataset) : - m_dataset(dataset) +inline Coordinates::Coordinates(const H5Easy::File& data, const std::string& dataset) + : m_dataset(dataset) { - this->readShape(data); + this->readShape(data); } #endif -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE -inline Coordinates::Coordinates( - const std::string& fname, - const std::string& dataset) : - m_fname(fname), - m_dataset(dataset) +inline Coordinates::Coordinates(const std::string& fname, const std::string& dataset) + : m_fname(fname), m_dataset(dataset) { - H5Easy::File data(m_fname, H5Easy::File::ReadOnly); + H5Easy::File data(m_fname, H5Easy::File::ReadOnly); - this->readShape(data); + this->readShape(data); } #endif -// ------------------------------------------------------------------------------------------------- - inline Coordinates::Coordinates( - const std::string& fname, - const std::string& dataset, - const std::vector& shape) : - m_fname(fname), - m_dataset(dataset), - m_shape(shape) + const std::string& fname, const std::string& dataset, const std::vector& shape) + : m_fname(fname), m_dataset(dataset), m_shape(shape) { - GOOSEFEM_ASSERT(m_shape.size() == 2); + GOOSEFEM_ASSERT(m_shape.size() == 2); } -// ------------------------------------------------------------------------------------------------- - inline size_t Coordinates::nnode() const { - return m_shape[0]; + return m_shape[0]; } -// ------------------------------------------------------------------------------------------------- - inline size_t Coordinates::ndim() const { - return m_shape[1]; + return m_shape[1]; } -// ------------------------------------------------------------------------------------------------- - inline std::vector Coordinates::shape() const { - return m_shape; + return m_shape; } -// ------------------------------------------------------------------------------------------------- - inline std::string Coordinates::fname() const { - return m_fname; + return m_fname; } -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline void Coordinates::checkShape() { - if (m_verified) - return; + if (m_verified) + return; - H5Easy::File data(m_fname, H5Easy::File::ReadOnly); + H5Easy::File data(m_fname, H5Easy::File::ReadOnly); - GOOSEFEM_CHECK(m_shape == H5Easy::getShape(data, m_dataset)); + GOOSEFEM_CHECK(m_shape == H5Easy::getShape(data, m_dataset)); - m_verified = true; + m_verified = true; } #endif -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline void Coordinates::readShape(const H5Easy::File& data) { - if (m_fname.size() == 0) - m_fname = data.getName(); + if (m_fname.size() == 0) + m_fname = data.getName(); - m_shape = H5Easy::getShape(data, m_dataset); + m_shape = H5Easy::getShape(data, m_dataset); - GOOSEFEM_ASSERT(m_shape.size() == 2); + GOOSEFEM_ASSERT(m_shape.size() == 2); - m_verified = true; + m_verified = true; } #endif -// ------------------------------------------------------------------------------------------------- - inline std::vector Coordinates::xdmf(size_t n_indent) const { - std::vector out; + std::vector out; - if (m_shape[1] == 1) - out.push_back(""); - else if (m_shape[1] == 2) - out.push_back(""); - else if (m_shape[1] == 3) - out.push_back(""); + if (m_shape[1] == 1) { + out.push_back(""); + } + else if (m_shape[1] == 2) { + out.push_back(""); + } + else if (m_shape[1] == 3) { + out.push_back(""); + } - out.push_back(indent(n_indent) + - "" + m_fname + ":" + m_dataset + ""); + out.push_back( + indent(n_indent) + "" + m_fname + ":" + m_dataset + + ""); - out.push_back(")"); + out.push_back(")"); - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline Attribute::Attribute( - const H5Easy::File& data, - const std::string& dataset, - const std::string& name, - AttributeType type) : - m_type(type), - m_dataset(dataset), - m_name(name) + const H5Easy::File& data, + const std::string& dataset, + const std::string& name, + AttributeType type) + : m_type(type), m_dataset(dataset), m_name(name) { - this->readShape(data); + this->readShape(data); } #endif -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline Attribute::Attribute( - const std::string& fname, - const std::string& dataset, - const std::string& name, - AttributeType type) : - m_type(type), - m_fname(fname), - m_dataset(dataset), - m_name(name) + const std::string& fname, + const std::string& dataset, + const std::string& name, + AttributeType type) + : m_type(type), m_fname(fname), m_dataset(dataset), m_name(name) { - H5Easy::File data(m_fname, H5Easy::File::ReadOnly); + H5Easy::File data(m_fname, H5Easy::File::ReadOnly); - this->readShape(data); + this->readShape(data); } #endif -// ------------------------------------------------------------------------------------------------- - inline Attribute::Attribute( - const std::string& fname, - const std::string& dataset, - const std::string& name, - AttributeType type, - const std::vector& shape) : - m_type(type), - m_fname(fname), - m_dataset(dataset), - m_name(name), - m_shape(shape) + const std::string& fname, + const std::string& dataset, + const std::string& name, + AttributeType type, + const std::vector& shape) + : m_type(type), m_fname(fname), m_dataset(dataset), m_name(name), m_shape(shape) { - GOOSEFEM_ASSERT(m_shape.size() > 0); + GOOSEFEM_ASSERT(m_shape.size() > 0); } -// ------------------------------------------------------------------------------------------------- - inline std::vector Attribute::shape() const { - return m_shape; + return m_shape; } -// ------------------------------------------------------------------------------------------------- - inline std::string Attribute::fname() const { - return m_fname; + return m_fname; } -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline void Attribute::checkShape() { - if (m_verified) - return; + if (m_verified) + return; - H5Easy::File data(m_fname, H5Easy::File::ReadOnly); + H5Easy::File data(m_fname, H5Easy::File::ReadOnly); - GOOSEFEM_CHECK(m_shape == H5Easy::getShape(data, m_dataset)); + GOOSEFEM_CHECK(m_shape == H5Easy::getShape(data, m_dataset)); - m_verified = true; + m_verified = true; } #endif -// ------------------------------------------------------------------------------------------------- - #ifndef GOOSEFEM_NO_HIGHFIVE inline void Attribute::readShape(const H5Easy::File& data) { - if (m_fname.size() == 0) - m_fname = data.getName(); + if (m_fname.size() == 0) { + m_fname = data.getName(); + } - m_shape = H5Easy::getShape(data, m_dataset); + m_shape = H5Easy::getShape(data, m_dataset); - GOOSEFEM_ASSERT(m_shape.size() > 0); + GOOSEFEM_ASSERT(m_shape.size() > 0); - m_verified = true; + m_verified = true; } #endif -// ------------------------------------------------------------------------------------------------- - inline std::vector Attribute::xdmf(size_t n_indent) const { - GOOSEFEM_ASSERT(m_shape.size() > 0); - GOOSEFEM_ASSERT(m_shape.size() < 3); + GOOSEFEM_ASSERT(m_shape.size() > 0); + GOOSEFEM_ASSERT(m_shape.size() < 3); - std::vector out; + std::vector out; - if (m_shape.size() == 1) - { - out.push_back( - ""); - - out.push_back(indent(n_indent) + - "" + m_fname + ":" + m_dataset + ""); - } - else if (m_shape.size() == 2) - { - out.push_back( - ""); + if (m_shape.size() == 1) { + out.push_back( + ""); - out.push_back(indent(n_indent) + - "" + m_fname + ":" + m_dataset + ""); - } + out.push_back( + indent(n_indent) + "" + m_fname + ":" + m_dataset + ""); + } + else if (m_shape.size() == 2) { + out.push_back( + ""); + + out.push_back( + indent(n_indent) + "" + m_fname + ":" + m_dataset + + ""); + } - out.push_back(")"); + out.push_back(")"); - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline Mesh::Mesh(const Connectivity& conn, const Coordinates& coor) : m_conn(conn), m_coor(coor) { } -// ------------------------------------------------------------------------------------------------- - inline void Mesh::push_back(const Attribute& data) { - m_attr.push_back(data); + m_attr.push_back(data); } -// ------------------------------------------------------------------------------------------------- - inline std::vector Mesh::xdmf(size_t n_indent) const { - std::vector out; + std::vector out; - { - std::vector lines = m_conn.xdmf(n_indent); + { + std::vector lines = m_conn.xdmf(n_indent); - for (auto& line: lines) - out.push_back(line); - } + for (auto& line : lines) { + out.push_back(line); + } + } - { - std::vector lines = m_coor.xdmf(n_indent); + { + std::vector lines = m_coor.xdmf(n_indent); - for (auto& line: lines) - out.push_back(line); - } + for (auto& line : lines) { + out.push_back(line); + } + } - for (auto& i: m_attr) - { - std::vector lines = i.xdmf(n_indent); + for (auto& i : m_attr) { + std::vector lines = i.xdmf(n_indent); - for (auto& line: lines) - out.push_back(line); - } + for (auto& line : lines) { + out.push_back(line); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline void Mesh::write(const std::string& fname, size_t n_indent) const { - TimeSeries({Increment(m_conn, m_coor, m_attr)}).write(fname, n_indent); + TimeSeries({Increment(m_conn, m_coor, m_attr)}).write(fname, n_indent); } -// ------------------------------------------------------------------------------------------------- - -inline Increment::Increment( - const Connectivity& conn, - const Coordinates& coor) +inline Increment::Increment(const Connectivity& conn, const Coordinates& coor) { - m_conn.push_back(conn); - m_coor.push_back(coor); + m_conn.push_back(conn); + m_coor.push_back(coor); } -// ------------------------------------------------------------------------------------------------- - inline Increment::Increment( - const Connectivity& conn, - const Coordinates& coor, - const std::vector& attr) : - m_attr(attr) + const Connectivity& conn, const Coordinates& coor, const std::vector& attr) + : m_attr(attr) { - m_conn.push_back(conn); - m_coor.push_back(coor); + m_conn.push_back(conn); + m_coor.push_back(coor); } -// ------------------------------------------------------------------------------------------------- - inline void Increment::push_back(const Connectivity& data) { - m_conn.push_back(data); + m_conn.push_back(data); } -// ------------------------------------------------------------------------------------------------- - inline void Increment::push_back(const Coordinates& data) { - m_coor.push_back(data); + m_coor.push_back(data); } -// ------------------------------------------------------------------------------------------------- - inline void Increment::push_back(const Attribute& data) { - m_attr.push_back(data); + m_attr.push_back(data); } -// ------------------------------------------------------------------------------------------------- - inline std::vector Increment::xdmf(size_t n_indent) const { - std::vector out; + std::vector out; - for (auto& i: m_conn) - { - std::vector lines = i.xdmf(n_indent); + for (auto& i : m_conn) { + std::vector lines = i.xdmf(n_indent); - for (auto& line: lines) - out.push_back(line); - } + for (auto& line : lines) { + out.push_back(line); + } + } - for (auto& i: m_coor) - { - std::vector lines = i.xdmf(n_indent); + for (auto& i : m_coor) { + std::vector lines = i.xdmf(n_indent); - for (auto& line: lines) - out.push_back(line); - } + for (auto& line : lines) { + out.push_back(line); + } + } - for (auto& i: m_attr) - { - std::vector lines = i.xdmf(n_indent); + for (auto& i : m_attr) { + std::vector lines = i.xdmf(n_indent); - for (auto& line: lines) - out.push_back(line); - } + for (auto& line : lines) { + out.push_back(line); + } + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline TimeSeries::TimeSeries(const std::vector& data) : m_data(data) { } -// ------------------------------------------------------------------------------------------------- - inline void TimeSeries::push_back(const Increment& data) { - m_data.push_back(data); + m_data.push_back(data); } -// ------------------------------------------------------------------------------------------------- - inline std::vector TimeSeries::xdmf(size_t n_indent) const { - std::vector out; + std::vector out; - for (size_t inc = 0; inc < m_data.size(); ++inc) - { - out.push_back( - ""); + for (size_t inc = 0; inc < m_data.size(); ++inc) { + out.push_back(""); - out.push_back(indent(n_indent) + - ")"); - } + out.push_back(")"); + } - return out; + return out; } -// ------------------------------------------------------------------------------------------------- - inline void TimeSeries::write(const std::string& fname, size_t n_indent) const { - std::ofstream myfile; - - myfile.open(fname); + std::ofstream myfile; - myfile << - "" << std::endl; + myfile.open(fname); - myfile << indent(n_indent) + - "" << std::endl; + myfile << "" << std::endl; + myfile << indent(n_indent) + "" << std::endl; + myfile << indent(n_indent * 2) + + "" + << std::endl; - myfile << indent(n_indent * 2) + - "" << std::endl; + std::vector lines = this->xdmf(n_indent); - std::vector lines = this->xdmf(n_indent); - - for (auto& line: lines) - myfile << indent(n_indent * 3) + line << std::endl; - - myfile << indent(n_indent * 2) + - "" << std::endl; - - myfile << indent(n_indent) + - "" << std::endl; + for (auto& line : lines) { + myfile << indent(n_indent * 3) + line << std::endl; + } - myfile << - "" << std::endl; + myfile << indent(n_indent * 2) + "" << std::endl; + myfile << indent(n_indent) + "" << std::endl; + myfile << "" << std::endl; - myfile.close(); + myfile.close(); } -// ------------------------------------------------------------------------------------------------- - -}}} // namespace ... - -// ================================================================================================= +} // namespace HDF5 +} // namespace ParaView +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/TyingsPeriodic.hpp b/include/GooseFEM/TyingsPeriodic.hpp index 7681647..2f07df1 100644 --- a/include/GooseFEM/TyingsPeriodic.hpp +++ b/include/GooseFEM/TyingsPeriodic.hpp @@ -1,285 +1,245 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_TYINGSPERIODIC_HPP #define GOOSEFEM_TYINGSPERIODIC_HPP -// ------------------------------------------------------------------------------------------------- - -#include "TyingsPeriodic.h" #include "Mesh.h" +#include "TyingsPeriodic.h" #include #include -// ================================================================================================= - namespace GooseFEM { namespace Tyings { -// ------------------------------------------------------------------------------------------------- - inline Periodic::Periodic( - const xt::xtensor& coor, - const xt::xtensor& dofs, - const xt::xtensor& control, - const xt::xtensor& nodal_tyings) : - Periodic(coor, dofs, control, nodal_tyings, xt::empty({0})) + const xt::xtensor& coor, + const xt::xtensor& dofs, + const xt::xtensor& control, + const xt::xtensor& nodal_tyings) + : Periodic(coor, dofs, control, nodal_tyings, xt::empty({0})) { } -// ------------------------------------------------------------------------------------------------- - inline Periodic::Periodic( - const xt::xtensor& coor, - const xt::xtensor& dofs, - const xt::xtensor& control, - const xt::xtensor& nodal_tyings, - const xt::xtensor& iip) : - m_tyings(nodal_tyings), - m_coor(coor) + const xt::xtensor& coor, + const xt::xtensor& dofs, + const xt::xtensor& control, + const xt::xtensor& nodal_tyings, + const xt::xtensor& iip) + : m_tyings(nodal_tyings), m_coor(coor) { - m_ndim = m_coor.shape(1); - m_nties = m_tyings.shape(0); + m_ndim = m_coor.shape(1); + m_nties = m_tyings.shape(0); - xt::xtensor dependent = xt::view(m_tyings, xt::all(), 1); - xt::xtensor dependent_dofs = xt::view(dofs, xt::keep(dependent), xt::all()); - xt::xtensor iid = xt::flatten(dependent_dofs); - xt::xtensor iii = xt::setdiff1d(dofs, iid); - xt::xtensor iiu = xt::setdiff1d(iii , iip); + xt::xtensor dependent = xt::view(m_tyings, xt::all(), 1); + xt::xtensor dependent_dofs = xt::view(dofs, xt::keep(dependent), xt::all()); + xt::xtensor iid = xt::flatten(dependent_dofs); + xt::xtensor iii = xt::setdiff1d(dofs, iid); + xt::xtensor iiu = xt::setdiff1d(iii, iip); - m_nnu = iiu.size(); - m_nnp = iip.size(); - m_nni = iii.size(); - m_nnd = iid.size(); + m_nnu = iiu.size(); + m_nnp = iip.size(); + m_nni = iii.size(); + m_nnd = iid.size(); - GooseFEM::Mesh::Reorder reorder({iiu, iip, iid}); + GooseFEM::Mesh::Reorder reorder({iiu, iip, iid}); - m_dofs = reorder.apply(dofs); - m_control = reorder.apply(control); + m_dofs = reorder.apply(dofs); + m_control = reorder.apply(control); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Periodic::dofs() const { - return m_dofs; + return m_dofs; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Periodic::control() const { - return m_control; + return m_control; } -// ------------------------------------------------------------------------------------------------- - inline size_t Periodic::nnu() const { - return m_nnu; + return m_nnu; } -// ------------------------------------------------------------------------------------------------- - inline size_t Periodic::nnp() const { - return m_nnp; + return m_nnp; } -// ------------------------------------------------------------------------------------------------- - inline size_t Periodic::nni() const { - return m_nni; + return m_nni; } -// ------------------------------------------------------------------------------------------------- - inline size_t Periodic::nnd() const { - return m_nnd; + return m_nnd; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Periodic::iiu() const { - return xt::arange(m_nnu); + return xt::arange(m_nnu); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Periodic::iip() const { - return xt::arange(m_nnp) + m_nnu; + return xt::arange(m_nnp) + m_nnu; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Periodic::iii() const { - return xt::arange(m_nni); + return xt::arange(m_nni); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Periodic::iid() const { - return xt::arange(m_nni, m_nni + m_nnd); + return xt::arange(m_nni, m_nni + m_nnd); } -// ------------------------------------------------------------------------------------------------- - inline Eigen::SparseMatrix Periodic::Cdi() const { - std::vector> data; + std::vector> data; - data.reserve(m_nties*m_ndim*(m_ndim+1)); + data.reserve(m_nties * m_ndim * (m_ndim + 1)); - for (size_t i = 0; i < m_nties; ++i) { - for (size_t j = 0; j < m_ndim; ++j) { + for (size_t i = 0; i < m_nties; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { - size_t ni = m_tyings(i,0); - size_t nd = m_tyings(i,1); + size_t ni = m_tyings(i, 0); + size_t nd = m_tyings(i, 1); - data.push_back(Eigen::Triplet(i*m_ndim+j, m_dofs(ni,j), +1.)); + data.push_back(Eigen::Triplet(i * m_ndim + j, m_dofs(ni, j), +1.0)); - for (size_t k = 0; k < m_ndim; ++k) - data.push_back(Eigen::Triplet(i*m_ndim+j, m_control(j,k), m_coor(nd,k)-m_coor(ni,k))); + for (size_t k = 0; k < m_ndim; ++k) { + data.push_back(Eigen::Triplet( + i * m_ndim + j, + m_control(j, k), + m_coor(nd, k) - m_coor(ni, k))); + } + } } - } - - Eigen::SparseMatrix Cdi; - Cdi.resize(m_nnd, m_nni); + Eigen::SparseMatrix Cdi; + Cdi.resize(m_nnd, m_nni); + Cdi.setFromTriplets(data.begin(), data.end()); - Cdi.setFromTriplets(data.begin(), data.end()); - - return Cdi; + return Cdi; } -// ------------------------------------------------------------------------------------------------- - inline Eigen::SparseMatrix Periodic::Cdu() const { - std::vector> data; + std::vector> data; - data.reserve(m_nties*m_ndim*(m_ndim+1)); + data.reserve(m_nties * m_ndim * (m_ndim + 1)); - for (size_t i = 0; i < m_nties; ++i) { - for (size_t j = 0; j < m_ndim; ++j) { + for (size_t i = 0; i < m_nties; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { - size_t ni = m_tyings(i,0); - size_t nd = m_tyings(i,1); + size_t ni = m_tyings(i, 0); + size_t nd = m_tyings(i, 1); - if (m_dofs(ni,j) < m_nnu) - data.push_back(Eigen::Triplet(i*m_ndim+j, m_dofs(ni,j), +1.)); + if (m_dofs(ni, j) < m_nnu) { + data.push_back(Eigen::Triplet(i * m_ndim + j, m_dofs(ni, j), +1.0)); + } - for (size_t k = 0; k < m_ndim; ++k) - if (m_control(j,k) < m_nnu) - data.push_back(Eigen::Triplet(i*m_ndim+j, m_control(j,k), m_coor(nd,k)-m_coor(ni,k))); + for (size_t k = 0; k < m_ndim; ++k) { + if (m_control(j, k) < m_nnu) { + data.push_back(Eigen::Triplet( + i * m_ndim + j, + m_control(j, k), + m_coor(nd, k) - m_coor(ni, k))); + } + } + } } - } - Eigen::SparseMatrix Cdu; + Eigen::SparseMatrix Cdu; + Cdu.resize(m_nnd, m_nnu); + Cdu.setFromTriplets(data.begin(), data.end()); - Cdu.resize(m_nnd, m_nnu); - - Cdu.setFromTriplets(data.begin(), data.end()); - - return Cdu; + return Cdu; } -// ------------------------------------------------------------------------------------------------- - inline Eigen::SparseMatrix Periodic::Cdp() const { - std::vector> data; + std::vector> data; - data.reserve(m_nties*m_ndim*(m_ndim+1)); + data.reserve(m_nties * m_ndim * (m_ndim + 1)); - for (size_t i = 0; i < m_nties; ++i) { - for (size_t j = 0; j < m_ndim; ++j) { + for (size_t i = 0; i < m_nties; ++i) { + for (size_t j = 0; j < m_ndim; ++j) { - size_t ni = m_tyings(i,0); - size_t nd = m_tyings(i,1); + size_t ni = m_tyings(i, 0); + size_t nd = m_tyings(i, 1); - if (m_dofs(ni,j) >= m_nnu) - data.push_back(Eigen::Triplet(i*m_ndim+j, m_dofs(ni,j)-m_nnu, +1.)); + if (m_dofs(ni, j) >= m_nnu) { + data.push_back(Eigen::Triplet(i * m_ndim + j, m_dofs(ni, j) - m_nnu, +1.0)); + } - for (size_t k = 0; k < m_ndim; ++k) - if (m_control(j,k) >= m_nnu) - data.push_back(Eigen::Triplet(i*m_ndim+j, m_control(j,k)-m_nnu, m_coor(nd,k)-m_coor(ni,k))); + for (size_t k = 0; k < m_ndim; ++k) { + if (m_control(j, k) >= m_nnu) { + data.push_back(Eigen::Triplet( + i * m_ndim + j, + m_control(j, k) - m_nnu, + m_coor(nd, k) - m_coor(ni, k))); + } + } + } } - } - - Eigen::SparseMatrix Cdp; - Cdp.resize(m_nnd, m_nnp); + Eigen::SparseMatrix Cdp; + Cdp.resize(m_nnd, m_nnp); + Cdp.setFromTriplets(data.begin(), data.end()); - Cdp.setFromTriplets(data.begin(), data.end()); - - return Cdp; + return Cdp; } -// ------------------------------------------------------------------------------------------------- - -inline Control::Control( - const xt::xtensor& coor, - const xt::xtensor& dofs) : - m_coor(coor), m_dofs(dofs) +inline Control::Control(const xt::xtensor& coor, const xt::xtensor& dofs) + : m_coor(coor), m_dofs(dofs) { - GOOSEFEM_ASSERT(coor.shape().size() == 2); - GOOSEFEM_ASSERT(coor.shape() == dofs.shape()); + GOOSEFEM_ASSERT(coor.shape().size() == 2); + GOOSEFEM_ASSERT(coor.shape() == dofs.shape()); - size_t nnode = coor.shape(0); - size_t ndim = coor.shape(1); + size_t nnode = coor.shape(0); + size_t ndim = coor.shape(1); - m_control_dofs = xt::arange(ndim*ndim).reshape({ndim,ndim}); - m_control_dofs += xt::amax(dofs)[0] + 1; + m_control_dofs = xt::arange(ndim * ndim).reshape({ndim, ndim}); + m_control_dofs += xt::amax(dofs)[0] + 1; - m_control_nodes = nnode + xt::arange(ndim); + m_control_nodes = nnode + xt::arange(ndim); - m_coor = xt::concatenate(xt::xtuple(coor, xt::zeros({ndim,ndim}))); - m_dofs = xt::concatenate(xt::xtuple(dofs, m_control_dofs)); + m_coor = xt::concatenate(xt::xtuple(coor, xt::zeros({ndim, ndim}))); + m_dofs = xt::concatenate(xt::xtuple(dofs, m_control_dofs)); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Control::coor() const { - return m_coor; + return m_coor; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Control::dofs() const { - return m_dofs; + return m_dofs; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Control::controlDofs() const { - return m_control_dofs; + return m_control_dofs; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Control::controlNodes() const { - return m_control_nodes; + return m_control_nodes; } -// ------------------------------------------------------------------------------------------------- - -}} // namespace ... - -// ================================================================================================= +} // namespace Tyings +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/Vector.hpp b/include/GooseFEM/Vector.hpp index 8bd8e13..7d38bf6 100644 --- a/include/GooseFEM/Vector.hpp +++ b/include/GooseFEM/Vector.hpp @@ -1,347 +1,279 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_VECTOR_HPP #define GOOSEFEM_VECTOR_HPP -// ------------------------------------------------------------------------------------------------- - #include "Vector.h" -// ================================================================================================= - namespace GooseFEM { -// ------------------------------------------------------------------------------------------------- - -inline Vector::Vector( - const xt::xtensor& conn, - const xt::xtensor& dofs) : - m_conn(conn), - m_dofs(dofs) +inline Vector::Vector(const xt::xtensor& conn, const xt::xtensor& dofs) + : m_conn(conn), m_dofs(dofs) { - // mesh dimensions - m_nelem = m_conn.shape(0); - m_nne = m_conn.shape(1); - m_nnode = m_dofs.shape(0); - m_ndim = m_dofs.shape(1); - - // dimensions of the system - m_ndof = xt::amax(m_dofs)[0] + 1; - - // check consistency - GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); - GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); + m_nelem = m_conn.shape(0); + m_nne = m_conn.shape(1); + m_nnode = m_dofs.shape(0); + m_ndim = m_dofs.shape(1); + m_ndof = xt::amax(m_dofs)[0] + 1; + + GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); + GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); } -// ------------------------------------------------------------------------------------------------- - inline size_t Vector::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t Vector::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t Vector::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - inline size_t Vector::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t Vector::ndof() const { - return m_ndof; + return m_ndof; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor Vector::dofs() const { - return m_dofs; + return m_dofs; } -// ------------------------------------------------------------------------------------------------- - -inline void Vector::copy( - const xt::xtensor& nodevec_src, - xt::xtensor& nodevec_dest) const +inline void +Vector::copy(const xt::xtensor& nodevec_src, xt::xtensor& nodevec_dest) const { - GOOSEFEM_ASSERT(nodevec_src.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(nodevec_dest.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + nodevec_src.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + nodevec_dest.shape() == std::decay_t::shape_type({m_nnode,m_ndim})); - xt::noalias(nodevec_dest) = nodevec_src; + xt::noalias(nodevec_dest) = nodevec_src; } -// ------------------------------------------------------------------------------------------------- - -inline void Vector::asDofs( - const xt::xtensor& nodevec, - xt::xtensor& dofval) const +inline void +Vector::asDofs(const xt::xtensor& nodevec, xt::xtensor& dofval) const { - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - dofval(m_dofs(m,i)) = nodevec(m,i); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + dofval(m_dofs(m, i)) = nodevec(m, i); + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void Vector::asDofs( - const xt::xtensor& elemvec, - xt::xtensor& dofval) const +inline void +Vector::asDofs(const xt::xtensor& elemvec, xt::xtensor& dofval) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - dofval(m_dofs(m_conn(e,m),i)) = elemvec(e,m,i); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + dofval(m_dofs(m_conn(e, m), i)) = elemvec(e, m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void Vector::asNode( - const xt::xtensor& dofval, - xt::xtensor& nodevec) const +inline void +Vector::asNode(const xt::xtensor& dofval, xt::xtensor& nodevec) const { - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - nodevec(m,i) = dofval(m_dofs(m,i)); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + nodevec(m, i) = dofval(m_dofs(m, i)); + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void Vector::asNode( - const xt::xtensor& elemvec, - xt::xtensor& nodevec) const +inline void +Vector::asNode(const xt::xtensor& elemvec, xt::xtensor& nodevec) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - nodevec(m_conn(e,m),i) = elemvec(e,m,i); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + nodevec(m_conn(e, m), i) = elemvec(e, m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void Vector::asElement( - const xt::xtensor& dofval, - xt::xtensor& elemvec) const +inline void +Vector::asElement(const xt::xtensor& dofval, xt::xtensor& elemvec) const { - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - elemvec(e,m,i) = dofval(m_dofs(m_conn(e,m),i)); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + elemvec(e, m, i) = dofval(m_dofs(m_conn(e, m), i)); + } + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void Vector::asElement( - const xt::xtensor& nodevec, - xt::xtensor& elemvec) const +inline void +Vector::asElement(const xt::xtensor& nodevec, xt::xtensor& elemvec) const { - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - elemvec(e,m,i) = nodevec(m_conn(e,m),i); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + elemvec(e, m, i) = nodevec(m_conn(e, m), i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void Vector::assembleDofs( - const xt::xtensor& nodevec, - xt::xtensor& dofval) const +inline void +Vector::assembleDofs(const xt::xtensor& nodevec, xt::xtensor& dofval) const { - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); - dofval.fill(0.0); + dofval.fill(0.0); - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - dofval(m_dofs(m,i)) += nodevec(m,i); + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + dofval(m_dofs(m, i)) += nodevec(m, i); + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void Vector::assembleDofs( - const xt::xtensor& elemvec, - xt::xtensor& dofval) const +inline void +Vector::assembleDofs(const xt::xtensor& elemvec, xt::xtensor& dofval) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - - dofval.fill(0.0); - - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - dofval(m_dofs(m_conn(e,m),i)) += elemvec(e,m,i); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + + dofval.fill(0.0); + + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + dofval(m_dofs(m_conn(e, m), i)) += elemvec(e, m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - -inline void Vector::assembleNode( - const xt::xtensor& elemvec, - xt::xtensor& nodevec) const +inline void +Vector::assembleNode(const xt::xtensor& elemvec, xt::xtensor& nodevec) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - // assemble to DOFs - xt::xtensor dofval = this->AssembleDofs(elemvec); - - // read from DOFs - this->asNode(dofval, nodevec); + xt::xtensor dofval = this->AssembleDofs(elemvec); + this->asNode(dofval, nodevec); } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Vector::AsDofs( - const xt::xtensor& nodevec) const +inline xt::xtensor Vector::AsDofs(const xt::xtensor& nodevec) const { - xt::xtensor dofval = xt::empty({m_ndof}); - this->asDofs(nodevec, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_ndof}); + this->asDofs(nodevec, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Vector::AsDofs( - const xt::xtensor& elemvec) const +inline xt::xtensor Vector::AsDofs(const xt::xtensor& elemvec) const { - xt::xtensor dofval = xt::empty({m_ndof}); - this->asDofs(elemvec, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_ndof}); + this->asDofs(elemvec, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Vector::AsNode( - const xt::xtensor& dofval) const +inline xt::xtensor Vector::AsNode(const xt::xtensor& dofval) const { - xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); - this->asNode(dofval, nodevec); - return nodevec; + xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); + this->asNode(dofval, nodevec); + return nodevec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Vector::AsNode( - const xt::xtensor& elemvec) const +inline xt::xtensor Vector::AsNode(const xt::xtensor& elemvec) const { - xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); - this->asNode(elemvec, nodevec); - return nodevec; + xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); + this->asNode(elemvec, nodevec); + return nodevec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Vector::AsElement( - const xt::xtensor& dofval) const +inline xt::xtensor Vector::AsElement(const xt::xtensor& dofval) const { - xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); - this->asElement(dofval, elemvec); - return elemvec; + xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); + this->asElement(dofval, elemvec); + return elemvec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Vector::AsElement( - const xt::xtensor& nodevec) const +inline xt::xtensor Vector::AsElement(const xt::xtensor& nodevec) const { - xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); - this->asElement(nodevec, elemvec); - return elemvec; + xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); + this->asElement(nodevec, elemvec); + return elemvec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Vector::AssembleDofs( - const xt::xtensor& nodevec) const +inline xt::xtensor Vector::AssembleDofs(const xt::xtensor& nodevec) const { - xt::xtensor dofval = xt::empty({m_ndof}); - this->assembleDofs(nodevec, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_ndof}); + this->assembleDofs(nodevec, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Vector::AssembleDofs( - const xt::xtensor& elemvec) const +inline xt::xtensor Vector::AssembleDofs(const xt::xtensor& elemvec) const { - xt::xtensor dofval = xt::empty({m_ndof}); - this->assembleDofs(elemvec, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_ndof}); + this->assembleDofs(elemvec, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor Vector::AssembleNode( - const xt::xtensor& elemvec) const +inline xt::xtensor Vector::AssembleNode(const xt::xtensor& elemvec) const { - xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); - this->assembleNode(elemvec, nodevec); - return nodevec; + xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); + this->assembleNode(elemvec, nodevec); + return nodevec; } -// ------------------------------------------------------------------------------------------------- - -} // namespace ... - -// ================================================================================================= +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/VectorPartitioned.hpp b/include/GooseFEM/VectorPartitioned.hpp index 87ce419..48f035b 100644 --- a/include/GooseFEM/VectorPartitioned.hpp +++ b/include/GooseFEM/VectorPartitioned.hpp @@ -1,821 +1,718 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_VECTORPARTITIONED_HPP #define GOOSEFEM_VECTORPARTITIONED_HPP -// ------------------------------------------------------------------------------------------------- - -#include "VectorPartitioned.h" #include "Mesh.h" - -// ================================================================================================= +#include "VectorPartitioned.h" namespace GooseFEM { -// ------------------------------------------------------------------------------------------------- - inline VectorPartitioned::VectorPartitioned( - const xt::xtensor& conn, - const xt::xtensor& dofs, - const xt::xtensor& iip) : - m_conn(conn), - m_dofs(dofs), - m_iip(iip) -{ - m_nelem = m_conn.shape(0); - m_nne = m_conn.shape(1); - m_nnode = m_dofs.shape(0); - m_ndim = m_dofs.shape(1); - - m_iiu = xt::setdiff1d(dofs, iip); - - m_ndof = xt::amax(m_dofs)[0] + 1; - m_nnp = m_iip.size(); - m_nnu = m_iiu.size(); - - m_part = Mesh::Reorder({m_iiu, m_iip}).get(m_dofs); - - GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); - GOOSEFEM_ASSERT(xt::amax(m_iip)[0] <= xt::amax(m_dofs)[0]); - GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); + const xt::xtensor& conn, + const xt::xtensor& dofs, + const xt::xtensor& iip) + : m_conn(conn), m_dofs(dofs), m_iip(iip) +{ + m_nelem = m_conn.shape(0); + m_nne = m_conn.shape(1); + m_nnode = m_dofs.shape(0); + m_ndim = m_dofs.shape(1); + m_iiu = xt::setdiff1d(dofs, iip); + m_ndof = xt::amax(m_dofs)[0] + 1; + m_nnp = m_iip.size(); + m_nnu = m_iiu.size(); + m_part = Mesh::Reorder({m_iiu, m_iip}).get(m_dofs); + + GOOSEFEM_ASSERT(xt::amax(m_conn)[0] + 1 == m_nnode); + GOOSEFEM_ASSERT(xt::amax(m_iip)[0] <= xt::amax(m_dofs)[0]); + GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitioned::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitioned::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitioned::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitioned::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitioned::ndof() const { - return m_ndof; + return m_ndof; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitioned::nnu() const { - return m_nnu; + return m_nnu; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitioned::nnp() const { - return m_nnp; + return m_nnp; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitioned::dofs() const { - return m_dofs; + return m_dofs; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitioned::iiu() const { - return m_iiu; + return m_iiu; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitioned::iip() const { - return m_iip; + return m_iip; } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::copy( - const xt::xtensor& nodevec_src, - xt::xtensor& nodevec_dest) const + const xt::xtensor& nodevec_src, xt::xtensor& nodevec_dest) const { - GOOSEFEM_ASSERT(nodevec_src.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(nodevec_dest.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + nodevec_src.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + nodevec_dest.shape() == std::decay_t::shape_type({m_nnode,m_ndim})); - xt::noalias(nodevec_dest) = nodevec_src; + xt::noalias(nodevec_dest) = nodevec_src; } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::copy_u( - const xt::xtensor& nodevec_src, - xt::xtensor& nodevec_dest) const -{ - GOOSEFEM_ASSERT(nodevec_src.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(nodevec_dest.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m,i) < m_nnu) - nodevec_dest(m,i) = nodevec_src(m,i); + const xt::xtensor& nodevec_src, xt::xtensor& nodevec_dest) const +{ + GOOSEFEM_ASSERT( + nodevec_src.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + nodevec_dest.shape() == std::decay_t::shape_type({m_nnode,m_ndim})); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) < m_nnu) { + nodevec_dest(m, i) = nodevec_src(m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::copy_p( - const xt::xtensor& nodevec_src, - xt::xtensor& nodevec_dest) const -{ - GOOSEFEM_ASSERT(nodevec_src.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(nodevec_dest.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m,i) >= m_nnu) - nodevec_dest(m,i) = nodevec_src(m,i); + const xt::xtensor& nodevec_src, xt::xtensor& nodevec_dest) const +{ + GOOSEFEM_ASSERT( + nodevec_src.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + nodevec_dest.shape() == + std::decay_t::shape_type({m_nnode, m_ndim})); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) >= m_nnu) { + nodevec_dest(m, i) = nodevec_src(m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asDofs( - const xt::xtensor& dofval_u, - const xt::xtensor& dofval_p, - xt::xtensor& dofval) const + const xt::xtensor& dofval_u, + const xt::xtensor& dofval_p, + xt::xtensor& dofval) const { - GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); - GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); - GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); + GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - dofval(m_iiu(d)) = dofval_u(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + dofval(m_iiu(d)) = dofval_u(d); + } - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnp ; ++d) - dofval(m_iip(d)) = dofval_p(d); + #pragma omp parallel for + for (size_t d = 0; d < m_nnp; ++d) { + dofval(m_iip(d)) = dofval_p(d); + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asDofs( - const xt::xtensor& nodevec, - xt::xtensor& dofval) const + const xt::xtensor& nodevec, xt::xtensor& dofval) const { - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - dofval(m_dofs(m,i)) = nodevec(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + dofval(m_dofs(m, i)) = nodevec(m, i); + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asDofs_u( - const xt::xtensor& dofval, - xt::xtensor& dofval_u) const + const xt::xtensor& dofval, xt::xtensor& dofval_u) const { - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnu ; ++d) - dofval_u(d) = dofval(m_iiu(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnu; ++d) { + dofval_u(d) = dofval(m_iiu(d)); + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asDofs_u( - const xt::xtensor& nodevec, - xt::xtensor& dofval_u) const -{ - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m,i) < m_nnu) - dofval_u(m_part(m,i)) = nodevec(m,i); + const xt::xtensor& nodevec, xt::xtensor& dofval_u) const +{ + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) < m_nnu) { + dofval_u(m_part(m, i)) = nodevec(m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asDofs_p( - const xt::xtensor& dofval, - xt::xtensor& dofval_p) const + const xt::xtensor& dofval, xt::xtensor& dofval_p) const { - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); - #pragma omp parallel for - for (size_t d = 0 ; d < m_nnp ; ++d) - dofval_p(d) = dofval(m_iip(d)); + #pragma omp parallel for + for (size_t d = 0; d < m_nnp; ++d) { + dofval_p(d) = dofval(m_iip(d)); + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asDofs_p( - const xt::xtensor& nodevec, - xt::xtensor& dofval_p) const -{ - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m,i) >= m_nnu) - dofval_p(m_part(m,i)-m_nnu) = nodevec(m,i); + const xt::xtensor& nodevec, xt::xtensor& dofval_p) const +{ + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) >= m_nnu) { + dofval_p(m_part(m, i) - m_nnu) = nodevec(m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asDofs( - const xt::xtensor& elemvec, - xt::xtensor& dofval) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - dofval(m_dofs(m_conn(e,m),i)) = elemvec(e,m,i); + const xt::xtensor& elemvec, xt::xtensor& dofval) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + dofval(m_dofs(m_conn(e, m), i)) = elemvec(e, m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asDofs_u( - const xt::xtensor& elemvec, - xt::xtensor& dofval_u) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m_conn(e,m),i) < m_nnu) - dofval_u(m_part(m_conn(e,m),i)) = elemvec(e,m,i); + const xt::xtensor& elemvec, xt::xtensor& dofval_u) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m_conn(e, m), i) < m_nnu) { + dofval_u(m_part(m_conn(e, m), i)) = elemvec(e, m, i); + } + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asDofs_p( - const xt::xtensor& elemvec, - xt::xtensor& dofval_p) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m_conn(e,m),i) >= m_nnu) - dofval_p(m_part(m_conn(e,m),i)-m_nnu) = elemvec(e,m,i); + const xt::xtensor& elemvec, xt::xtensor& dofval_p) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m_conn(e, m), i) >= m_nnu) { + dofval_p(m_part(m_conn(e, m), i) - m_nnu) = elemvec(e, m, i); + } + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asNode( - const xt::xtensor& dofval, - xt::xtensor& nodevec) const + const xt::xtensor& dofval, xt::xtensor& nodevec) const { - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - nodevec(m,i) = dofval(m_dofs(m,i)); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + nodevec(m, i) = dofval(m_dofs(m, i)); + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asNode( - const xt::xtensor& dofval_u, - const xt::xtensor& dofval_p, - xt::xtensor& nodevec) const -{ - GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); - GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) { - for (size_t i = 0 ; i < m_ndim ; ++i) { - if (m_part(m,i) < m_nnu) - nodevec(m,i) = dofval_u(m_part(m,i)); - else - nodevec(m,i) = dofval_p(m_part(m,i)-m_nnu); + const xt::xtensor& dofval_u, + const xt::xtensor& dofval_p, + xt::xtensor& nodevec) const +{ + GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); + GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) < m_nnu) { + nodevec(m, i) = dofval_u(m_part(m, i)); + } + else { + nodevec(m, i) = dofval_p(m_part(m, i) - m_nnu); + } + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asNode( - const xt::xtensor& elemvec, - xt::xtensor& nodevec) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - nodevec(m_conn(e,m),i) = elemvec(e,m,i); + const xt::xtensor& elemvec, xt::xtensor& nodevec) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + nodevec(m_conn(e, m), i) = elemvec(e, m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asElement( - const xt::xtensor& dofval, - xt::xtensor& elemvec) const -{ - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - elemvec(e,m,i) = dofval(m_dofs(m_conn(e,m),i)); + const xt::xtensor& dofval, xt::xtensor& elemvec) const +{ + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + elemvec(e, m, i) = dofval(m_dofs(m_conn(e, m), i)); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asElement( - const xt::xtensor& dofval_u, - const xt::xtensor& dofval_p, - xt::xtensor& elemvec) const -{ - GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); - GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) { - for (size_t m = 0 ; m < m_nne ; ++m) { - for (size_t i = 0 ; i < m_ndim ; ++i) { - if (m_part(m_conn(e,m),i)& dofval_u, + const xt::xtensor& dofval_p, + xt::xtensor& elemvec) const +{ + GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); + GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m_conn(e, m), i) < m_nnu) { + elemvec(e, m, i) = dofval_u(m_part(m_conn(e, m), i)); + } + else { + elemvec(e, m, i) = dofval_p(m_part(m_conn(e, m), i) - m_nnu); + } + } + } } - } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::asElement( - const xt::xtensor& nodevec, - xt::xtensor& elemvec) const -{ - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - elemvec(e,m,i) = nodevec(m_conn(e,m),i); + const xt::xtensor& nodevec, xt::xtensor& elemvec) const +{ + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + elemvec(e, m, i) = nodevec(m_conn(e, m), i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::assembleDofs( - const xt::xtensor& nodevec, - xt::xtensor& dofval) const + const xt::xtensor& nodevec, xt::xtensor& dofval) const { - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); - dofval.fill(0.0); + dofval.fill(0.0); - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - dofval(m_dofs(m,i)) += nodevec(m,i); + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + dofval(m_dofs(m, i)) += nodevec(m, i); + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::assembleDofs_u( - const xt::xtensor& nodevec, - xt::xtensor& dofval_u) const + const xt::xtensor& nodevec, xt::xtensor& dofval_u) const { - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); - dofval_u.fill(0.0); + dofval_u.fill(0.0); - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m,i) < m_nnu) - dofval_u(m_part(m,i)) += nodevec(m,i); + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) < m_nnu) { + dofval_u(m_part(m, i)) += nodevec(m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::assembleDofs_p( - const xt::xtensor& nodevec, - xt::xtensor& dofval_p) const + const xt::xtensor& nodevec, xt::xtensor& dofval_p) const { - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); - dofval_p.fill(0.0); + dofval_p.fill(0.0); - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m,i) >= m_nnu) - dofval_p(m_part(m,i)-m_nnu) += nodevec(m,i); + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m, i) >= m_nnu) { + dofval_p(m_part(m, i) - m_nnu) += nodevec(m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::assembleDofs( - const xt::xtensor& elemvec, - xt::xtensor& dofval) const + const xt::xtensor& elemvec, xt::xtensor& dofval) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); - dofval.fill(0.0); + dofval.fill(0.0); - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - dofval(m_dofs(m_conn(e,m),i)) += elemvec(e,m,i); + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + dofval(m_dofs(m_conn(e, m), i)) += elemvec(e, m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::assembleDofs_u( - const xt::xtensor& elemvec, - xt::xtensor& dofval_u) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); - - dofval_u.fill(0.0); - - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m_conn(e,m),i) < m_nnu) - dofval_u(m_part(m_conn(e,m),i)) += elemvec(e,m,i); + const xt::xtensor& elemvec, xt::xtensor& dofval_u) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT(dofval_u.size() == m_nnu); + + dofval_u.fill(0.0); + + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m_conn(e, m), i) < m_nnu) { + dofval_u(m_part(m_conn(e, m), i)) += elemvec(e, m, i); + } + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::assembleDofs_p( - const xt::xtensor& elemvec, - xt::xtensor& dofval_p) const -{ - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); - - dofval_p.fill(0.0); - - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_part(m_conn(e,m),i) >= m_nnu) - dofval_p(m_part(m_conn(e,m),i)-m_nnu) += elemvec(e,m,i); + const xt::xtensor& elemvec, xt::xtensor& dofval_p) const +{ + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT(dofval_p.size() == m_nnp); + + dofval_p.fill(0.0); + + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_part(m_conn(e, m), i) >= m_nnu) { + dofval_p(m_part(m_conn(e, m), i) - m_nnu) += elemvec(e, m, i); + } + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitioned::assembleNode( - const xt::xtensor& elemvec, - xt::xtensor& nodevec) const + const xt::xtensor& elemvec, xt::xtensor& nodevec) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - xt::xtensor dofval = this->AssembleDofs(elemvec); - this->asNode(dofval, nodevec); + xt::xtensor dofval = this->AssembleDofs(elemvec); + this->asNode(dofval, nodevec); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitioned::AsDofs( - const xt::xtensor& dofval_u, - const xt::xtensor& dofval_p) const + const xt::xtensor& dofval_u, const xt::xtensor& dofval_p) const { - xt::xtensor dofval = xt::empty({m_ndof}); - this->asDofs(dofval_u, dofval_p, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_ndof}); + this->asDofs(dofval_u, dofval_p, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsDofs( - const xt::xtensor& nodevec) const +inline xt::xtensor VectorPartitioned::AsDofs(const xt::xtensor& nodevec) const { - xt::xtensor dofval = xt::empty({m_ndof}); - this->asDofs(nodevec, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_ndof}); + this->asDofs(nodevec, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsDofs_u( - const xt::xtensor& dofval) const +inline xt::xtensor +VectorPartitioned::AsDofs_u(const xt::xtensor& dofval) const { - xt::xtensor dofval_u = xt::empty({m_nnu}); - this->asDofs_u(dofval, dofval_u); - return dofval_u; + xt::xtensor dofval_u = xt::empty({m_nnu}); + this->asDofs_u(dofval, dofval_u); + return dofval_u; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsDofs_u( - const xt::xtensor& nodevec) const +inline xt::xtensor +VectorPartitioned::AsDofs_u(const xt::xtensor& nodevec) const { - xt::xtensor dofval_u = xt::empty({m_nnu}); - this->asDofs_u(nodevec, dofval_u); - return dofval_u; + xt::xtensor dofval_u = xt::empty({m_nnu}); + this->asDofs_u(nodevec, dofval_u); + return dofval_u; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsDofs_p( - const xt::xtensor& dofval) const +inline xt::xtensor +VectorPartitioned::AsDofs_p(const xt::xtensor& dofval) const { - xt::xtensor dofval_p = xt::empty({m_nnp}); - this->asDofs_p(dofval, dofval_p); - return dofval_p; + xt::xtensor dofval_p = xt::empty({m_nnp}); + this->asDofs_p(dofval, dofval_p); + return dofval_p; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsDofs_p( - const xt::xtensor& nodevec) const +inline xt::xtensor +VectorPartitioned::AsDofs_p(const xt::xtensor& nodevec) const { - xt::xtensor dofval_p = xt::empty({m_nnp}); - this->asDofs_p(nodevec, dofval_p); - return dofval_p; + xt::xtensor dofval_p = xt::empty({m_nnp}); + this->asDofs_p(nodevec, dofval_p); + return dofval_p; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsDofs( - const xt::xtensor& elemvec) const +inline xt::xtensor VectorPartitioned::AsDofs(const xt::xtensor& elemvec) const { - xt::xtensor dofval = xt::empty({m_ndof}); - this->asDofs(elemvec, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_ndof}); + this->asDofs(elemvec, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsDofs_u( - const xt::xtensor& elemvec) const +inline xt::xtensor +VectorPartitioned::AsDofs_u(const xt::xtensor& elemvec) const { - xt::xtensor dofval_u = xt::empty({m_nnu}); - this->asDofs_u(elemvec, dofval_u); - return dofval_u; + xt::xtensor dofval_u = xt::empty({m_nnu}); + this->asDofs_u(elemvec, dofval_u); + return dofval_u; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsDofs_p( - const xt::xtensor& elemvec) const +inline xt::xtensor +VectorPartitioned::AsDofs_p(const xt::xtensor& elemvec) const { - xt::xtensor dofval_p = xt::empty({m_nnp}); - this->asDofs_p(elemvec, dofval_p); - return dofval_p; + xt::xtensor dofval_p = xt::empty({m_nnp}); + this->asDofs_p(elemvec, dofval_p); + return dofval_p; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsNode( - const xt::xtensor& dofval) const +inline xt::xtensor VectorPartitioned::AsNode(const xt::xtensor& dofval) const { - xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); - this->asNode(dofval, nodevec); - return nodevec; + xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); + this->asNode(dofval, nodevec); + return nodevec; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitioned::AsNode( - const xt::xtensor& dofval_u, - const xt::xtensor& dofval_p) const + const xt::xtensor& dofval_u, const xt::xtensor& dofval_p) const { - xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); - this->asNode(dofval_u, dofval_p, nodevec); - return nodevec; + xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); + this->asNode(dofval_u, dofval_p, nodevec); + return nodevec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsNode( - const xt::xtensor& elemvec) const +inline xt::xtensor VectorPartitioned::AsNode(const xt::xtensor& elemvec) const { - xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); - this->asNode(elemvec, nodevec); - return nodevec; + xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); + this->asNode(elemvec, nodevec); + return nodevec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsElement( - const xt::xtensor& dofval) const +inline xt::xtensor +VectorPartitioned::AsElement(const xt::xtensor& dofval) const { - xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); - this->asElement(dofval, elemvec); - return elemvec; + xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); + this->asElement(dofval, elemvec); + return elemvec; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitioned::AsElement( - const xt::xtensor& dofval_u, - const xt::xtensor& dofval_p) const + const xt::xtensor& dofval_u, const xt::xtensor& dofval_p) const { - xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); - this->asElement(dofval_u, dofval_p, elemvec); - return elemvec; + xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); + this->asElement(dofval_u, dofval_p, elemvec); + return elemvec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AsElement( - const xt::xtensor& nodevec) const +inline xt::xtensor +VectorPartitioned::AsElement(const xt::xtensor& nodevec) const { - xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); - this->asElement(nodevec, elemvec); - return elemvec; + xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); + this->asElement(nodevec, elemvec); + return elemvec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AssembleDofs( - const xt::xtensor& nodevec) const +inline xt::xtensor +VectorPartitioned::AssembleDofs(const xt::xtensor& nodevec) const { - xt::xtensor dofval = xt::empty({m_ndof}); - this->assembleDofs(nodevec, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_ndof}); + this->assembleDofs(nodevec, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AssembleDofs_u( - const xt::xtensor& nodevec) const +inline xt::xtensor +VectorPartitioned::AssembleDofs_u(const xt::xtensor& nodevec) const { - xt::xtensor dofval_u = xt::empty({m_nnu}); - this->assembleDofs_u(nodevec, dofval_u); - return dofval_u; + xt::xtensor dofval_u = xt::empty({m_nnu}); + this->assembleDofs_u(nodevec, dofval_u); + return dofval_u; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AssembleDofs_p( - const xt::xtensor& nodevec) const +inline xt::xtensor +VectorPartitioned::AssembleDofs_p(const xt::xtensor& nodevec) const { - xt::xtensor dofval_p = xt::empty({m_nnp}); - this->assembleDofs_p(nodevec, dofval_p); - return dofval_p; + xt::xtensor dofval_p = xt::empty({m_nnp}); + this->assembleDofs_p(nodevec, dofval_p); + return dofval_p; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AssembleDofs( - const xt::xtensor& elemvec) const +inline xt::xtensor +VectorPartitioned::AssembleDofs(const xt::xtensor& elemvec) const { - xt::xtensor dofval = xt::empty({m_ndof}); - this->assembleDofs(elemvec, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_ndof}); + this->assembleDofs(elemvec, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AssembleDofs_u( - const xt::xtensor& elemvec) const +inline xt::xtensor +VectorPartitioned::AssembleDofs_u(const xt::xtensor& elemvec) const { - xt::xtensor dofval_u = xt::empty({m_nnu}); - this->assembleDofs_u(elemvec, dofval_u); - return dofval_u; + xt::xtensor dofval_u = xt::empty({m_nnu}); + this->assembleDofs_u(elemvec, dofval_u); + return dofval_u; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AssembleDofs_p( - const xt::xtensor& elemvec) const +inline xt::xtensor +VectorPartitioned::AssembleDofs_p(const xt::xtensor& elemvec) const { - xt::xtensor dofval_p = xt::empty({m_nnp}); - this->assembleDofs_p(elemvec, dofval_p); - return dofval_p; + xt::xtensor dofval_p = xt::empty({m_nnp}); + this->assembleDofs_p(elemvec, dofval_p); + return dofval_p; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitioned::AssembleNode( - const xt::xtensor& elemvec) const +inline xt::xtensor +VectorPartitioned::AssembleNode(const xt::xtensor& elemvec) const { - xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); - this->assembleNode(elemvec, nodevec); - return nodevec; + xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); + this->assembleNode(elemvec, nodevec); + return nodevec; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitioned::Copy( - const xt::xtensor& nodevec_src, - const xt::xtensor& nodevec_dest) const + const xt::xtensor& nodevec_src, const xt::xtensor& nodevec_dest) const { - xt::xtensor out = nodevec_dest; - this->copy(nodevec_src, out); - return out; + xt::xtensor out = nodevec_dest; + this->copy(nodevec_src, out); + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitioned::Copy_u( - const xt::xtensor& nodevec_src, - const xt::xtensor& nodevec_dest) const + const xt::xtensor& nodevec_src, const xt::xtensor& nodevec_dest) const { - xt::xtensor out = nodevec_dest; - this->copy_u(nodevec_src, out); - return out; + xt::xtensor out = nodevec_dest; + this->copy_u(nodevec_src, out); + return out; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitioned::Copy_p( - const xt::xtensor& nodevec_src, - const xt::xtensor& nodevec_dest) const + const xt::xtensor& nodevec_src, const xt::xtensor& nodevec_dest) const { - xt::xtensor out = nodevec_dest; - this->copy_p(nodevec_src, out); - return out; + xt::xtensor out = nodevec_dest; + this->copy_p(nodevec_src, out); + return out; } -// ------------------------------------------------------------------------------------------------- - -} // namespace ... - -// ================================================================================================= +} // namespace GooseFEM #endif diff --git a/include/GooseFEM/VectorPartitionedTyings.hpp b/include/GooseFEM/VectorPartitionedTyings.hpp index 907ade0..8f03722 100644 --- a/include/GooseFEM/VectorPartitionedTyings.hpp +++ b/include/GooseFEM/VectorPartitionedTyings.hpp @@ -1,342 +1,283 @@ -/* ================================================================================================= +/* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM -================================================================================================= */ +*/ #ifndef GOOSEFEM_VECTORPARTITIONEDTYINGS_HPP #define GOOSEFEM_VECTORPARTITIONEDTYINGS_HPP -// ------------------------------------------------------------------------------------------------- - #include "VectorPartitionedTyings.h" -// ================================================================================================= - namespace GooseFEM { -// ------------------------------------------------------------------------------------------------- - inline VectorPartitionedTyings::VectorPartitionedTyings( - const xt::xtensor& conn, - const xt::xtensor& dofs, - const Eigen::SparseMatrix& Cdu, - const Eigen::SparseMatrix& Cdp, - const Eigen::SparseMatrix& Cdi) : - m_conn(conn), - m_dofs(dofs), - m_Cdu(Cdu), - m_Cdp(Cdp), - m_Cdi(Cdi) + const xt::xtensor& conn, + const xt::xtensor& dofs, + const Eigen::SparseMatrix& Cdu, + const Eigen::SparseMatrix& Cdp, + const Eigen::SparseMatrix& Cdi) + : m_conn(conn), m_dofs(dofs), m_Cdu(Cdu), m_Cdp(Cdp), m_Cdi(Cdi) { - GOOSEFEM_ASSERT(Cdu.rows() == Cdp.rows()); - GOOSEFEM_ASSERT(Cdi.rows() == Cdp.rows()); - - m_nnu = static_cast(m_Cdu.cols()); - m_nnp = static_cast(m_Cdp.cols()); - m_nnd = static_cast(m_Cdp.rows()); - m_nni = m_nnu + m_nnp; - m_ndof = m_nni + m_nnd; - - m_iiu = xt::arange(m_nnu); - m_iip = xt::arange(m_nnu, m_nnu + m_nnp); - m_iid = xt::arange(m_nni, m_nni + m_nnd); - - m_nelem = m_conn.shape(0); - m_nne = m_conn.shape(1); - m_nnode = m_dofs.shape(0); - m_ndim = m_dofs.shape(1); - - m_Cud = m_Cdu.transpose(); - m_Cpd = m_Cdp.transpose(); - m_Cid = m_Cdi.transpose(); - - GOOSEFEM_ASSERT(static_cast(m_Cdi.cols()) == m_nni); - GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); - GOOSEFEM_ASSERT(m_ndof == xt::amax(m_dofs)[0] + 1); + GOOSEFEM_ASSERT(Cdu.rows() == Cdp.rows()); + GOOSEFEM_ASSERT(Cdi.rows() == Cdp.rows()); + + m_nnu = static_cast(m_Cdu.cols()); + m_nnp = static_cast(m_Cdp.cols()); + m_nnd = static_cast(m_Cdp.rows()); + m_nni = m_nnu + m_nnp; + m_ndof = m_nni + m_nnd; + m_iiu = xt::arange(m_nnu); + m_iip = xt::arange(m_nnu, m_nnu + m_nnp); + m_iid = xt::arange(m_nni, m_nni + m_nnd); + m_nelem = m_conn.shape(0); + m_nne = m_conn.shape(1); + m_nnode = m_dofs.shape(0); + m_ndim = m_dofs.shape(1); + m_Cud = m_Cdu.transpose(); + m_Cpd = m_Cdp.transpose(); + m_Cid = m_Cdi.transpose(); + + GOOSEFEM_ASSERT(static_cast(m_Cdi.cols()) == m_nni); + GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); + GOOSEFEM_ASSERT(m_ndof == xt::amax(m_dofs)[0] + 1); } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitionedTyings::nelem() const { - return m_nelem; + return m_nelem; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitionedTyings::nne() const { - return m_nne; + return m_nne; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitionedTyings::nnode() const { - return m_nnode; + return m_nnode; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitionedTyings::ndim() const { - return m_ndim; + return m_ndim; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitionedTyings::ndof() const { - return m_ndof; + return m_ndof; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitionedTyings::nnu() const { - return m_nnu; + return m_nnu; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitionedTyings::nnp() const { - return m_nnp; + return m_nnp; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitionedTyings::nni() const { - return m_nni; + return m_nni; } -// ------------------------------------------------------------------------------------------------- - inline size_t VectorPartitionedTyings::nnd() const { - return m_nnd; + return m_nnd; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitionedTyings::dofs() const { - return m_dofs; + return m_dofs; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitionedTyings::iiu() const { - return m_iiu; + return m_iiu; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitionedTyings::iip() const { - return m_iip; + return m_iip; } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitionedTyings::iii() const { - return xt::arange(m_nni); + return xt::arange(m_nni); } -// ------------------------------------------------------------------------------------------------- - inline xt::xtensor VectorPartitionedTyings::iid() const { - return m_iid; + return m_iid; } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitionedTyings::copy_p( - const xt::xtensor& dofval_src, - xt::xtensor& dofval_dest) const + const xt::xtensor& dofval_src, xt::xtensor& dofval_dest) const { - GOOSEFEM_ASSERT(dofval_src.size() == m_ndof || dofval_src.size() == m_nni); - GOOSEFEM_ASSERT(dofval_dest.size() == m_ndof || dofval_dest.size() == m_nni); + GOOSEFEM_ASSERT(dofval_src.size() == m_ndof || dofval_src.size() == m_nni); + GOOSEFEM_ASSERT(dofval_dest.size() == m_ndof || dofval_dest.size() == m_nni); - #pragma omp parallel for - for (size_t i = m_nnu; i < m_nni; ++i) - dofval_dest(i) = dofval_src(i); + #pragma omp parallel for + for (size_t i = m_nnu; i < m_nni; ++i) { + dofval_dest(i) = dofval_src(i); + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitionedTyings::asDofs_i( - const xt::xtensor& nodevec, - xt::xtensor& dofval_i, - bool apply_tyings) const + const xt::xtensor& nodevec, + xt::xtensor& dofval_i, + bool apply_tyings) const { - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(dofval_i.size() == m_nni); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_dofs(m,i) < m_nni) - dofval_i(m_dofs(m,i)) = nodevec(m,i); - - if (!apply_tyings) - return; - - Eigen::VectorXd Dofval_d = this->Eigen_asDofs_d(nodevec); - Eigen::VectorXd Dofval_i = m_Cid * Dofval_d; - - #pragma omp parallel for - for (size_t i = 0 ; i < m_nni ; ++i) - dofval_i(i) += Dofval_i(i); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT(dofval_i.size() == m_nni); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_dofs(m, i) < m_nni) { + dofval_i(m_dofs(m, i)) = nodevec(m, i); + } + } + } + + if (!apply_tyings) + return; + + Eigen::VectorXd Dofval_d = this->Eigen_asDofs_d(nodevec); + Eigen::VectorXd Dofval_i = m_Cid * Dofval_d; + + #pragma omp parallel for + for (size_t i = 0; i < m_nni; ++i) { + dofval_i(i) += Dofval_i(i); + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitionedTyings::asNode( - const xt::xtensor& dofval, - xt::xtensor& nodevec) const + const xt::xtensor& dofval, xt::xtensor& nodevec) const { - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - nodevec(m,i) = dofval(m_dofs(m,i)); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + nodevec(m, i) = dofval(m_dofs(m, i)); + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitionedTyings::asElement( - const xt::xtensor& nodevec, - xt::xtensor& elemvec) const + const xt::xtensor& nodevec, xt::xtensor& elemvec) const { - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - - #pragma omp parallel for - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - elemvec(e,m,i) = nodevec(m_conn(e,m),i); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + + #pragma omp parallel for + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + elemvec(e, m, i) = nodevec(m_conn(e, m), i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitionedTyings::assembleDofs( - const xt::xtensor& elemvec, - xt::xtensor& dofval) const + const xt::xtensor& elemvec, xt::xtensor& dofval) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(dofval.size() == m_ndof); - - dofval.fill(0.0); - - for (size_t e = 0 ; e < m_nelem ; ++e) - for (size_t m = 0 ; m < m_nne ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - dofval(m_dofs(m_conn(e,m),i)) += elemvec(e,m,i); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT(dofval.size() == m_ndof); + + dofval.fill(0.0); + + for (size_t e = 0; e < m_nelem; ++e) { + for (size_t m = 0; m < m_nne; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + dofval(m_dofs(m_conn(e, m), i)) += elemvec(e, m, i); + } + } + } } -// ------------------------------------------------------------------------------------------------- - inline void VectorPartitionedTyings::assembleNode( - const xt::xtensor& elemvec, - xt::xtensor& nodevec) const + const xt::xtensor& elemvec, xt::xtensor& nodevec) const { - GOOSEFEM_ASSERT(elemvec.shape() ==\ - std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + elemvec.shape() == std::decay_t::shape_type({m_nelem, m_nne, m_ndim})); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - xt::xtensor dofval = this->AssembleDofs(elemvec); - - this->asNode(dofval, nodevec); + xt::xtensor dofval = this->AssembleDofs(elemvec); + this->asNode(dofval, nodevec); } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitionedTyings::AsDofs_i( - const xt::xtensor& nodevec) const +inline xt::xtensor +VectorPartitionedTyings::AsDofs_i(const xt::xtensor& nodevec) const { - xt::xtensor dofval = xt::empty({m_nni}); - this->asDofs_i(nodevec, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_nni}); + this->asDofs_i(nodevec, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitionedTyings::AsNode( - const xt::xtensor& dofval) const +inline xt::xtensor +VectorPartitionedTyings::AsNode(const xt::xtensor& dofval) const { - xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); - this->asNode(dofval, nodevec); - return nodevec; + xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); + this->asNode(dofval, nodevec); + return nodevec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitionedTyings::AsElement( - const xt::xtensor& nodevec) const +inline xt::xtensor +VectorPartitionedTyings::AsElement(const xt::xtensor& nodevec) const { - xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); - this->asElement(nodevec, elemvec); - return elemvec; + xt::xtensor elemvec = xt::empty({m_nelem, m_nne, m_ndim}); + this->asElement(nodevec, elemvec); + return elemvec; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitionedTyings::AssembleDofs( - const xt::xtensor& elemvec) const +inline xt::xtensor +VectorPartitionedTyings::AssembleDofs(const xt::xtensor& elemvec) const { - xt::xtensor dofval = xt::empty({m_ndof}); - this->assembleDofs(elemvec, dofval); - return dofval; + xt::xtensor dofval = xt::empty({m_ndof}); + this->assembleDofs(elemvec, dofval); + return dofval; } -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor VectorPartitionedTyings::AssembleNode( - const xt::xtensor& elemvec) const +inline xt::xtensor +VectorPartitionedTyings::AssembleNode(const xt::xtensor& elemvec) const { - xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); - this->assembleNode(elemvec, nodevec); - return nodevec; + xt::xtensor nodevec = xt::empty({m_nnode, m_ndim}); + this->assembleNode(elemvec, nodevec); + return nodevec; } -// ------------------------------------------------------------------------------------------------- - -inline Eigen::VectorXd VectorPartitionedTyings::Eigen_asDofs_d( - const xt::xtensor& nodevec) const +inline Eigen::VectorXd +VectorPartitionedTyings::Eigen_asDofs_d(const xt::xtensor& nodevec) const { - GOOSEFEM_ASSERT(nodevec.shape() ==\ - std::decay_t::shape_type({m_nnode, m_ndim})); + GOOSEFEM_ASSERT( + nodevec.shape() == std::decay_t::shape_type({m_nnode, m_ndim})); - Eigen::VectorXd dofval_d(m_nnd,1); + Eigen::VectorXd dofval_d(m_nnd, 1); - #pragma omp parallel for - for (size_t m = 0 ; m < m_nnode ; ++m) - for (size_t i = 0 ; i < m_ndim ; ++i) - if (m_dofs(m,i) >= m_nni) - dofval_d(m_dofs(m,i)-m_nni) = nodevec(m,i); + #pragma omp parallel for + for (size_t m = 0; m < m_nnode; ++m) { + for (size_t i = 0; i < m_ndim; ++i) { + if (m_dofs(m, i) >= m_nni) { + dofval_d(m_dofs(m, i) - m_nni) = nodevec(m, i); + } + } + } - return dofval_d; + return dofval_d; } -// ------------------------------------------------------------------------------------------------- - -} // namespace ... - -// ================================================================================================= +} // namespace GooseFEM #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 852d7c1..9d3ae8b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,29 +1,42 @@ cmake_minimum_required(VERSION 3.0) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) project(GooseFEM-test) find_package(GooseFEM REQUIRED CONFIG) endif() option(WARNINGS "Show build warnings" ON) option(SIMD "Enable xsimd" ON) +option(ASSERT "Enable assertions" ON) option(DEBUG "Enable all assertions" ON) find_package(Catch2 REQUIRED) -add_executable(main main.cpp) +add_executable(main + main.cpp + ElementHex8.cpp + ElementQuad4.cpp + Iterate.cpp + MatrixDiagonal.cpp + MeshQuad4.cpp + Vector.cpp + VectorPartitioned.cpp) target_link_libraries(main PRIVATE Catch2::Catch2 GooseFEM) if (SIMD) target_link_libraries(main PRIVATE xtensor::optimize xtensor::use_xsimd) endif() if (WARNINGS) target_link_libraries(main PRIVATE GooseFEM::compiler_warnings) endif() +if (ASSERT) + target_link_libraries(main PRIVATE GooseFEM::assert) +endif() + if (DEBUG) target_link_libraries(main PRIVATE GooseFEM::debug) endif() diff --git a/test/support.h b/test/support.h index 049867c..78f18ea 100644 --- a/test/support.h +++ b/test/support.h @@ -1,17 +1,16 @@ #ifndef SUPPORT_H #define SUPPORT_H #include #include #include #include -#define GOOSEFEM_ENABLE_ASSERT -#include "../include/GooseFEM/GooseFEM.h" +#include #define EQ(a,b) REQUIRE_THAT((a), Catch::WithinAbs((b), 1.e-12)); #endif