11#ifndef GOOSEFEM_MATRIXPARTITIONED_H
12#define GOOSEFEM_MATRIXPARTITIONED_H
18#include <Eigen/Sparse>
19#include <Eigen/SparseCholesky>
25class MatrixPartitionedSolver;
40 Eigen::SparseMatrix<double>
m_Auu;
41 Eigen::SparseMatrix<double>
m_Aup;
42 Eigen::SparseMatrix<double>
m_Apu;
43 Eigen::SparseMatrix<double>
m_App;
45 std::vector<Eigen::Triplet<double>>
m_Tuu;
46 std::vector<Eigen::Triplet<double>>
m_Tup;
47 std::vector<Eigen::Triplet<double>>
m_Tpu;
48 std::vector<Eigen::Triplet<double>>
m_Tpp;
126 const Eigen::SparseMatrix<double>&
data_uu()
const
134 const Eigen::SparseMatrix<double>&
data_up()
const
142 const Eigen::SparseMatrix<double>&
data_pu()
const
150 const Eigen::SparseMatrix<double>&
data_pp()
const
157 void assemble_impl(
const T&
elemmat)
167 for (
size_t m = 0;
m <
m_nne; ++
m) {
172 for (
size_t n = 0;
n <
m_nne; ++
n) {
178 m_Tuu.push_back(Eigen::Triplet<double>(
183 m_Tup.push_back(Eigen::Triplet<double>(
188 m_Tpu.push_back(Eigen::Triplet<double>(
193 m_Tpp.push_back(Eigen::Triplet<double>(
230 std::vector<Eigen::Triplet<double>>
Tuu;
231 std::vector<Eigen::Triplet<double>>
Tup;
232 std::vector<Eigen::Triplet<double>>
Tpu;
233 std::vector<Eigen::Triplet<double>>
Tpp;
235 for (
size_t i = 0;
i <
rows.size(); ++
i) {
236 for (
size_t j = 0;
j <
cols.size(); ++
j) {
242 Tuu.push_back(Eigen::Triplet<double>(
di,
dj,
v));
280 std::vector<Eigen::Triplet<double>>
Tuu;
281 std::vector<Eigen::Triplet<double>>
Tup;
282 std::vector<Eigen::Triplet<double>>
Tpu;
283 std::vector<Eigen::Triplet<double>>
Tpp;
290 for (
size_t i = 0;
i <
rows.size(); ++
i) {
291 for (
size_t j = 0;
j <
cols.size(); ++
j) {
297 Tuu.push_back(Eigen::Triplet<double>(
di,
dj,
v));
311 Auu.setFromTriplets(
Tuu.begin(),
Tuu.end());
312 Aup.setFromTriplets(
Tup.begin(),
Tup.end());
313 Apu.setFromTriplets(
Tpu.begin(),
Tpu.end());
314 App.setFromTriplets(
Tpp.begin(),
Tpp.end());
324 void todense_impl(
T&
ret)
const
328 for (
int k = 0;
k <
m_Auu.outerSize(); ++
k) {
329 for (Eigen::SparseMatrix<double>::InnerIterator
it(
m_Auu,
k);
it; ++
it) {
334 for (
int k = 0;
k <
m_Aup.outerSize(); ++
k) {
335 for (Eigen::SparseMatrix<double>::InnerIterator
it(
m_Aup,
k);
it; ++
it) {
340 for (
int k = 0;
k <
m_Apu.outerSize(); ++
k) {
341 for (Eigen::SparseMatrix<double>::InnerIterator
it(
m_Apu,
k);
it; ++
it) {
346 for (
int k = 0;
k <
m_App.outerSize(); ++
k) {
347 for (Eigen::SparseMatrix<double>::InnerIterator
it(
m_App,
k);
it; ++
it) {
354 void dot_nodevec_impl(
const T&
x,
T&
b)
const
359 Eigen::VectorXd
X_u = this->AsDofs_u(
x);
360 Eigen::VectorXd
X_p = this->AsDofs_p(
x);
364#pragma omp parallel for
378 void dot_dofval_impl(
const T&
x,
T&
b)
const
383 Eigen::VectorXd
X_u = this->AsDofs_u(
x);
384 Eigen::VectorXd
X_p = this->AsDofs_p(
x);
389#pragma omp parallel for
390 for (
size_t d = 0;
d <
m_nnu; ++
d) {
394#pragma omp parallel for
395 for (
size_t d = 0;
d <
m_nnp; ++
d) {
401 void reaction_nodevec_impl(
const T&
x,
T&
b)
const
406 Eigen::VectorXd
X_u = this->AsDofs_u(
x);
407 Eigen::VectorXd
X_p = this->AsDofs_p(
x);
410#pragma omp parallel for
421 void reaction_dofval_impl(
const T&
x,
T&
b)
const
426 Eigen::VectorXd
X_u = this->AsDofs_u(
x);
427 Eigen::VectorXd
X_p = this->AsDofs_p(
x);
430#pragma omp parallel for
431 for (
size_t d = 0;
d <
m_nnp; ++
d) {
436 void reaction_p_impl(
437 const array_type::tensor<double, 1>&
x_u,
438 const array_type::tensor<double, 1>&
x_p,
439 array_type::tensor<double, 1>&
b_p
446 Eigen::Map<Eigen::VectorXd>(
b_p.data(),
b_p.size()).noalias() =
447 m_Apu * Eigen::Map<const Eigen::VectorXd>(
x_u.data(),
x_u.size()) +
448 m_App * Eigen::Map<const Eigen::VectorXd>(
x_p.data(),
x_p.size());
453 Eigen::VectorXd AsDofs_u(
const array_type::tensor<double, 1>&
dofval)
const
459#pragma omp parallel for
460 for (
size_t d = 0;
d <
m_nnu; ++
d) {
467 Eigen::VectorXd AsDofs_u(
const array_type::tensor<double, 2>&
nodevec)
const
473#pragma omp parallel for
485 Eigen::VectorXd AsDofs_p(
const array_type::tensor<double, 1>&
dofval)
const
491#pragma omp parallel for
492 for (
size_t d = 0;
d <
m_nnp; ++
d) {
499 Eigen::VectorXd AsDofs_p(
const array_type::tensor<double, 2>&
nodevec)
const
505#pragma omp parallel for
525template <
class Solver = Eigen::SimplicialLDLT<Eigen::SparseMatrix<
double>>>
586 Eigen::VectorXd
B_u =
A.AsDofs_u(
b);
587 Eigen::VectorXd
X_p =
A.AsDofs_p(
x);
588 Eigen::VectorXd
X_u = m_solver.solve(Eigen::VectorXd(
B_u -
A.m_Aup *
X_p));
590#pragma omp parallel for
591 for (
size_t m = 0;
m <
A.m_nnode; ++
m) {
592 for (
size_t i = 0;
i <
A.m_ndim; ++
i) {
593 if (
A.m_part(
m,
i) <
A.m_nnu) {
601 void solve_dofval_impl(MatrixPartitioned&
A,
const T&
b,
T&
x)
604 Eigen::VectorXd
B_u =
A.AsDofs_u(
b);
605 Eigen::VectorXd
X_p =
A.AsDofs_p(
x);
606 Eigen::VectorXd
X_u = m_solver.solve(Eigen::VectorXd(
B_u -
A.m_Aup *
X_p));
608#pragma omp parallel for
609 for (
size_t d = 0;
d <
A.m_nnu; ++
d) {
615 void solve_u_impl(MatrixPartitioned&
A,
const T&
b_u,
const T&
x_p,
T&
x_u)
619 Eigen::Map<Eigen::VectorXd>(
x_u.data(),
x_u.size()).noalias() =
620 m_solver.solve(Eigen::VectorXd(
621 Eigen::Map<const Eigen::VectorXd>(
b_u.data(),
b_u.size()) -
622 A.m_Aup * Eigen::Map<const Eigen::VectorXd>(
x_p.data(),
x_p.size())
628 bool m_factor =
true;
633 void factorize(MatrixPartitioned&
A)
635 if (!
A.m_changed && !m_factor) {
638 m_solver.compute(
A.m_Auu);
CRTP base class for a matrix.
const array_type::tensor< size_t, 2 > & dofs() const
DOFs per node.
const array_type::tensor< size_t, 2 > & conn() const
Connectivity.
array_type::tensor< size_t, 2 > m_dofs
DOF-numbers per node [nnode, ndim].
array_type::tensor< size_t, 2 > m_conn
Connectivity [nelem, nne].
size_t m_nelem
See nelem().
bool m_changed
Signal changes to data.
size_t m_nnode
See nnode().
CRTP base class for a partitioned matrix.
array_type::tensor< size_t, 1 > m_iiu
See iiu()
array_type::tensor< size_t, 1 > m_iip
See iip()
const array_type::tensor< size_t, 1 > & iip() const
Prescribed DOFs.
Solve for A of the MatrixPartitioned() class.
array_type::tensor< double, 1 > Solve_u(M &A, const array_type::tensor< double, 1 > &b_u, const array_type::tensor< double, 1 > &x_p)
Solve .
void solve_u(M &A, const array_type::tensor< double, 1 > &b_u, const array_type::tensor< double, 1 > &x_p, array_type::tensor< double, 1 > &x_u)
Same as Solve .
Sparse matrix partitioned in an unknown and a prescribed part.
std::vector< Eigen::Triplet< double > > m_Tuu
Matrix entries.
const Eigen::SparseMatrix< double > & data_uu() const
Pointer to data.
const Eigen::SparseMatrix< double > & data_pu() const
Pointer to data.
void add(const array_type::tensor< size_t, 1 > &rows, const array_type::tensor< size_t, 1 > &cols, const array_type::tensor< double, 2 > &matrix)
Add matrix.
const Eigen::SparseMatrix< double > & data_up() const
Pointer to data.
array_type::tensor< size_t, 1 > m_part1d
Map real DOF to DOF in partitioned system.
Eigen::SparseMatrix< double > m_App
The matrix.
void set(const array_type::tensor< size_t, 1 > &rows, const array_type::tensor< size_t, 1 > &cols, const array_type::tensor< double, 2 > &matrix)
Overwrite matrix.
Eigen::SparseMatrix< double > m_Aup
The matrix.
std::vector< Eigen::Triplet< double > > m_Tup
Matrix entries.
array_type::tensor< size_t, 2 > m_part
Renumbered DOFs per node, such that:
Eigen::SparseMatrix< double > m_Auu
The matrix.
std::vector< Eigen::Triplet< double > > m_Tpu
Matrix entries.
const Eigen::SparseMatrix< double > & data_pp() const
Pointer to data.
Eigen::SparseMatrix< double > m_Apu
The matrix.
MatrixPartitioned(const array_type::tensor< size_t, 2 > &conn, const array_type::tensor< size_t, 2 > &dofs, const array_type::tensor< size_t, 1 > &iip)
Constructor.
std::vector< Eigen::Triplet< double > > m_Tpp
Matrix entries.
CRTP base class for a solver class.
CRTP base class for a extra functions for a partitioned solver class.
Reorder to lowest possible index, in specific order.
#define GOOSEFEM_ASSERT(expr)
All assertions are implementation as::
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Toolbox to perform finite element computations.
bool is_unique(const T &arg)
Returns true is a list is unique (has not duplicate items).
auto AsTensor(const T &arg, const S &shape)
"Broadcast" a scalar stored in an array (e.g.