7#ifndef GOOSEFEM_MATRIX_H
8#define GOOSEFEM_MATRIX_H
13#include <Eigen/Sparse>
14#include <Eigen/SparseCholesky>
57 derived_cast().solve_nodevec_impl(A, b, x);
72 derived_cast().solve_dofval_impl(A, b, x);
111 derived_cast().solve_nodevec_impl(A, b, x);
127 derived_cast().solve_dofval_impl(A, b, x);
164 array_type::tensor<double, 2>
170 derived_cast().solve_nodevec_impl(A, b, ret);
189 derived_cast().solve_dofval_impl(A, b, ret);
235 return derived_cast().m_nelem;
244 return derived_cast().m_nne;
253 return derived_cast().m_nnode;
262 return derived_cast().m_ndim;
271 return derived_cast().m_ndof;
280 return derived_cast().m_dofs;
289 return derived_cast().m_conn;
298 return std::array<size_t, 1>{derived_cast().m_ndof};
307 return std::array<size_t, 2>{derived_cast().m_nnode, derived_cast().m_ndim};
316 return std::array<size_t, 3>{
317 derived_cast().m_nelem,
318 derived_cast().m_nne * derived_cast().m_ndim,
319 derived_cast().m_nne * derived_cast().m_ndim};
330 derived_cast().assemble_impl(elemmat);
339 size_t ndof = derived_cast().m_ndof;
341 derived_cast().todense_impl(ret);
352 GOOSEFEM_ASSERT(xt::has_shape(ret, {derived_cast().m_ndof, derived_cast().m_ndof}));
353 derived_cast().todense_impl(ret);
366 derived_cast().dot_nodevec_impl(x, b);
380 derived_cast().dot_dofval_impl(x, b);
394 derived_cast().dot_nodevec_impl(x, b);
407 derived_cast().dot_dofval_impl(x, b);
447 return derived_cast().m_nnu;
456 return derived_cast().m_nnp;
465 return derived_cast().m_iiu;
474 return derived_cast().m_iip;
494 derived_cast().reaction_nodevec_impl(x, ret);
512 derived_cast().reaction_dofval_impl(x, ret);
527 derived_cast().reaction_nodevec_impl(x, b);
541 derived_cast().reaction_dofval_impl(x, b);
557 derived_cast().reaction_p_impl(x_u, x_p, b_p);
574 derived_cast().reaction_p_impl(x_u, x_p, b_p);
614 return derived_cast().m_nni;
623 return derived_cast().m_nnd;
632 return derived_cast().m_iii;
641 return derived_cast().m_iid;
655 bool m_changed =
true;
657 Eigen::SparseMatrix<double> m_A;
659 std::vector<Eigen::Triplet<double>> m_T;
695 const Eigen::SparseMatrix<double>&
data()
const
702 void assemble_impl(
const T& elemmat)
706 for (
size_t e = 0; e <
m_nelem; ++e) {
707 for (
size_t m = 0; m <
m_nne; ++m) {
708 for (
size_t i = 0; i <
m_ndim; ++i) {
709 for (
size_t n = 0; n <
m_nne; ++n) {
710 for (
size_t j = 0; j <
m_ndim; ++j) {
711 m_T.push_back(Eigen::Triplet<double>(
721 m_A.setFromTriplets(m_T.begin(), m_T.end());
743 std::vector<Eigen::Triplet<double>> T;
745 for (
size_t i = 0; i < rows.size(); ++i) {
746 for (
size_t j = 0; j < cols.size(); ++j) {
747 T.push_back(Eigen::Triplet<double>(rows(i), cols(j), matrix(i, j)));
751 m_A.setFromTriplets(T.begin(), T.end());
772 std::vector<Eigen::Triplet<double>> T;
776 for (
size_t i = 0; i < rows.size(); ++i) {
777 for (
size_t j = 0; j < cols.size(); ++j) {
778 T.push_back(Eigen::Triplet<double>(rows(i), cols(j), matrix(i, j)));
782 A.setFromTriplets(T.begin(), T.end());
789 void todense_impl(T& ret)
const
793 for (
int k = 0; k < m_A.outerSize(); ++k) {
794 for (Eigen::SparseMatrix<double>::InnerIterator it(m_A, k); it; ++it) {
795 ret(it.row(), it.col()) = it.value();
801 void dot_nodevec_impl(
const T& x, T& b)
const
803 this->Eigen_asNode_dofval_nodevec(m_A * this->Eigen_AsDofs_nodevec(x), b);
807 void dot_dofval_impl(
const T& x, T& b)
const
809 Eigen::Map<Eigen::VectorXd>(b.data(), b.size()).noalias() =
810 m_A * Eigen::Map<const Eigen::VectorXd>(x.data(), x.size());
821 Eigen::VectorXd Eigen_AsDofs_nodevec(
const T& nodevec)
const
825 Eigen::VectorXd dofval = Eigen::VectorXd::Zero(
m_ndof, 1);
827#pragma omp parallel for
828 for (
size_t m = 0; m <
m_nnode; ++m) {
829 for (
size_t i = 0; i <
m_ndim; ++i) {
830 dofval(
m_dofs(m, i)) = nodevec(m, i);
844 void Eigen_asNode_dofval_nodevec(
const Eigen::VectorXd& dofval, T& nodevec)
const
849#pragma omp parallel for
850 for (
size_t m = 0; m <
m_nnode; ++m) {
851 for (
size_t i = 0; i <
m_ndim; ++i) {
852 nodevec(m, i) = dofval(
m_dofs(m, i));
862template <
class Solver = Eigen::SimplicialLDLT<Eigen::SparseMatrix<
double>>>
874 void solve_nodevec_impl(
Matrix& A,
const T& b, T& x)
877 Eigen::VectorXd X = m_solver.solve(A.Eigen_AsDofs_nodevec(b));
878 A.Eigen_asNode_dofval_nodevec(X, x);
882 void solve_dofval_impl(
Matrix& A,
const T& b, T& x)
885 Eigen::Map<Eigen::VectorXd>(x.data(), x.size()).noalias() =
886 m_solver.solve(Eigen::Map<const Eigen::VectorXd>(b.data(), A.
m_ndof));
891 bool m_factor =
true;
898 if (!A.m_changed && !m_factor) {
901 m_solver.compute(A.m_A);
CRTP base class for a matrix.
const array_type::tensor< size_t, 2 > & dofs() const
DOFs per node.
size_t nne() const
Number of nodes per element.
const array_type::tensor< size_t, 2 > & conn() const
Connectivity.
array_type::tensor< size_t, 2 > m_dofs
DOF-numbers per node [nnode, ndim].
size_t nnode() const
Number of nodes.
array_type::tensor< size_t, 2 > m_conn
Connectivity [nelem, nne].
std::array< size_t, 2 > shape_nodevec() const
Shape of "nodevec".
size_t m_nelem
See nelem().
array_type::tensor< double, 1 > Dot(const array_type::tensor< double, 1 > &x) const
Dot-product .
void dot(const array_type::tensor< double, 1 > &x, array_type::tensor< double, 1 > &b) const
Dot-product .
void assemble(const T &elemmat)
Assemble from "elemmat".
std::array< size_t, 3 > shape_elemmat() const
Shape of "elemmat".
array_type::tensor< double, 2 > Dot(const array_type::tensor< double, 2 > &x) const
Dot-product .
size_t nelem() const
Number of elements.
bool m_changed
Signal changes to data.
size_t ndim() const
Number of dimensions.
array_type::tensor< double, 2 > Todense() const
Copy as dense matrix.
std::array< size_t, 1 > shape_dofval() const
Shape of "dofval".
size_t m_nnode
See nnode().
size_t ndof() const
Number of DOFs.
void todense(T &ret) const
Copy to dense matrix.
D derived_type
Underlying type.
void dot(const array_type::tensor< double, 2 > &x, array_type::tensor< double, 2 > &b) const
Dot-product .
CRTP base class for a partitioned matrix.
const array_type::tensor< size_t, 1 > & iiu() const
Unknown DOFs.
array_type::tensor< size_t, 1 > m_iiu
See iiu()
void reaction(const array_type::tensor< double, 1 > &x, array_type::tensor< double, 1 > &b) const
Same as Reaction(const array_type::tensor<double, 1>&, const array_type::tensor<double,...
size_t nnu() const
Number of unknown DOFs.
size_t nnp() const
Number of prescribed DOFs.
D derived_type
Underlying type.
array_type::tensor< size_t, 1 > m_iip
See iip()
const array_type::tensor< size_t, 1 > & iip() const
Prescribed DOFs.
void reaction_p(const array_type::tensor< double, 1 > &x_u, const array_type::tensor< double, 1 > &x_p, array_type::tensor< double, 1 > &b_p) const
Same as Reaction_p(const array_type::tensor<double, 1>&, const array_type::tensor<double,...
array_type::tensor< double, 1 > Reaction(const array_type::tensor< double, 1 > &x, const array_type::tensor< double, 1 > &b) const
Same as Reaction(const array_type::tensor<double, 2>&, const array_type::tensor<double,...
void reaction(const array_type::tensor< double, 2 > &x, array_type::tensor< double, 2 > &b) const
Same as Reaction(const array_type::tensor<double, 2>&, const array_type::tensor<double,...
array_type::tensor< double, 1 > Reaction_p(const array_type::tensor< double, 1 > &x_u, const array_type::tensor< double, 1 > &x_p) const
Same as Reaction(const array_type::tensor<double, 1>&, const array_type::tensor<double,...
array_type::tensor< double, 2 > Reaction(const array_type::tensor< double, 2 > &x, const array_type::tensor< double, 2 > &b) const
Right-hand-size for corresponding to the prescribed DOFs:
CRTP base class for a partitioned matrix with tying.
array_type::tensor< size_t, 1 > m_iii
See iii()
array_type::tensor< size_t, 1 > m_iid
See iid()
size_t nnd() const
Number of dependent DOFs.
size_t nni() const
Number of independent DOFs.
D derived_type
Underlying type.
const array_type::tensor< size_t, 1 > & iii() const
Independent DOFs.
const array_type::tensor< size_t, 1 > & iid() const
Dependent DOFs.
CRTP base class for a solver class.
void solve(M &A, const array_type::tensor< double, 2 > &b, array_type::tensor< double, 2 > &x)
Solve .
void solve(M &A, const array_type::tensor< double, 1 > &b, array_type::tensor< double, 1 > &x)
Solve .
D derived_type
Underlying type.
CRTP base class for a extra functions for a partitioned solver class.
array_type::tensor< double, 1 > Solve(M &A, const array_type::tensor< double, 1 > &b, const array_type::tensor< double, 1 > &x)
Solve .
D derived_type
Underlying type.
array_type::tensor< double, 2 > Solve(M &A, const array_type::tensor< double, 2 > &b, const array_type::tensor< double, 2 > &x)
Solve .
CRTP base class for a solver class.
array_type::tensor< double, 2 > Solve(M &A, const array_type::tensor< double, 2 > &b)
Solve .
array_type::tensor< double, 1 > Solve(M &A, const array_type::tensor< double, 1 > &b)
Solve .
D derived_type
Underlying type.
Solve , for A of the GooseFEM::Matrix() class.
Matrix(const array_type::tensor< size_t, 2 > &conn, const array_type::tensor< size_t, 2 > &dofs)
Constructor.
const Eigen::SparseMatrix< double > & data() 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.
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.
#define GOOSEFEM_ASSERT(expr)
All assertions are implementation as::
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Toolbox to perform finite element computations.