9#ifndef GOOSEFEM_TYINGSPERIODIC_H
10#define GOOSEFEM_TYINGSPERIODIC_H
16#include <Eigen/Sparse>
62 template <
class C,
class D,
class S,
class T>
82 template <
class C,
class D,
class S,
class T,
class U>
93 m_ndim = m_coor.shape(1);
94 m_nties = m_tyings.shape(0);
191 return xt::arange<size_t>(m_nni, m_nni + m_nnd);
201 return xt::arange<size_t>(m_nni);
211 return xt::arange<size_t>(m_nnu);
221 return xt::arange<size_t>(m_nnp) + m_nnu;
238 Eigen::SparseMatrix<double>
Cdi()
const
240 std::vector<Eigen::Triplet<double>> data;
242 data.reserve(m_nties * m_ndim * (m_ndim + 1));
244 for (
size_t i = 0;
i < m_nties; ++
i) {
245 for (
size_t j = 0;
j < m_ndim; ++
j) {
247 size_t ni = m_tyings(
i, 0);
248 size_t nd = m_tyings(
i, 1);
250 data.push_back(Eigen::Triplet<double>(
i * m_ndim +
j, m_dofs(
ni,
j), +1.0));
252 for (
size_t k = 0;
k < m_ndim; ++
k) {
253 data.push_back(Eigen::Triplet<double>(
254 i * m_ndim +
j, m_control(
j,
k), m_coor(
nd,
k) - m_coor(
ni,
k)
260 Eigen::SparseMatrix<double>
Cdi;
261 Cdi.resize(m_nnd, m_nni);
262 Cdi.setFromTriplets(data.begin(), data.end());
272 Eigen::SparseMatrix<double>
Cdu()
const
274 std::vector<Eigen::Triplet<double>> data;
276 data.reserve(m_nties * m_ndim * (m_ndim + 1));
278 for (
size_t i = 0;
i < m_nties; ++
i) {
279 for (
size_t j = 0;
j < m_ndim; ++
j) {
281 size_t ni = m_tyings(
i, 0);
282 size_t nd = m_tyings(
i, 1);
284 if (m_dofs(
ni,
j) < m_nnu) {
285 data.push_back(Eigen::Triplet<double>(
i * m_ndim +
j, m_dofs(
ni,
j), +1.0));
288 for (
size_t k = 0;
k < m_ndim; ++
k) {
289 if (m_control(
j,
k) < m_nnu) {
290 data.push_back(Eigen::Triplet<double>(
291 i * m_ndim +
j, m_control(
j,
k), m_coor(
nd,
k) - m_coor(
ni,
k)
298 Eigen::SparseMatrix<double>
Cdu;
299 Cdu.resize(m_nnd, m_nnu);
300 Cdu.setFromTriplets(data.begin(), data.end());
310 Eigen::SparseMatrix<double>
Cdp()
const
312 std::vector<Eigen::Triplet<double>> data;
314 data.reserve(m_nties * m_ndim * (m_ndim + 1));
316 for (
size_t i = 0;
i < m_nties; ++
i) {
317 for (
size_t j = 0;
j < m_ndim; ++
j) {
319 size_t ni = m_tyings(
i, 0);
320 size_t nd = m_tyings(
i, 1);
322 if (m_dofs(
ni,
j) >= m_nnu) {
324 Eigen::Triplet<double>(
i * m_ndim +
j, m_dofs(
ni,
j) - m_nnu, +1.0)
328 for (
size_t k = 0;
k < m_ndim; ++
k) {
329 if (m_control(
j,
k) >= m_nnu) {
330 data.push_back(Eigen::Triplet<double>(
331 i * m_ndim +
j, m_control(
j,
k) - m_nnu, m_coor(
nd,
k) - m_coor(
ni,
k)
338 Eigen::SparseMatrix<double>
Cdp;
339 Cdp.resize(m_nnd, m_nnp);
340 Cdp.setFromTriplets(data.begin(), data.end());
373 template <
class C,
class N>
382 size_t nnode =
coor.shape(0);
383 size_t ndim =
coor.shape(1);
385 m_control_dofs = xt::arange<size_t>(ndim * ndim).reshape({ndim, ndim});
386 m_control_dofs += xt::amax(
dofs)() + 1;
388 m_control_nodes = nnode + xt::arange<size_t>(ndim);
390 m_coor = xt::concatenate(xt::xtuple(
coor, xt::zeros<double>({ndim, ndim})));
391 m_dofs = xt::concatenate(xt::xtuple(
dofs, m_control_dofs));
421 return m_control_dofs;
431 return m_control_nodes;
Reorder to lowest possible index, in specific order.
Add control nodes to an existing system.
const array_type::tensor< double, 2 > & coor() const
Nodal coordinates, for the system with control nodes added to it.
const array_type::tensor< size_t, 2 > & dofs() const
DOF-numbers per node, for the system with control nodes added to it.
const array_type::tensor< size_t, 1 > & controlNodes() const
Node-numbers of the control nodes.
Control(const C &coor, const N &dofs)
Constructor.
const array_type::tensor< size_t, 2 > & controlDofs() const
DOF-numbers of each control node.
Nodal tyings per periodic boundary conditions.
Periodic(const C &coor, const D &dofs, const S &control_dofs, const T &nodal_tyings)
Constructor.
Periodic(const C &coor, const D &dofs, const S &control_dofs, const T &nodal_tyings, const U &iip)
Constructor.
Eigen::SparseMatrix< double > Cdp() const
Prescribed part of the partitioned tying matrix, see Cdi().
Eigen::SparseMatrix< double > Cdu() const
Unknown part of the partitioned tying matrix, see Cdi().
array_type::tensor< size_t, 1 > iip() const
Independent prescribed DOFs.
array_type::tensor< size_t, 1 > iiu() const
Independent unknown DOFs.
array_type::tensor< size_t, 1 > iid() const
Dependent DOFs.
array_type::tensor< size_t, 1 > iii() const
Independent DOFs.
const array_type::tensor< size_t, 2 > & dofs() const
const array_type::tensor< size_t, 2 > & control() const
Eigen::SparseMatrix< double > Cdi() const
Return tying matrix such as to get the dependent DOFs from the independent DOFs as follows.
const array_type::tensor< size_t, 2 > & nodal_tyings() const
Return the applied nodal tyings.
#define GOOSEFEM_ASSERT(expr)
All assertions are implementation as::
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Toolbox to perform finite element computations.
auto AsTensor(const T &arg, const S &shape)
"Broadcast" a scalar stored in an array (e.g.