GooseFEM 1.4.1.dev2+g78f16df
Loading...
Searching...
No Matches
MatrixPartitionedTyings.h
Go to the documentation of this file.
1
12#ifndef GOOSEFEM_MATRIXPARTITIONEDTYINGS_H
13#define GOOSEFEM_MATRIXPARTITIONEDTYINGS_H
14
15#include "Matrix.h"
16#include "config.h"
17
18#include <Eigen/Eigen>
19#include <Eigen/Sparse>
20#include <Eigen/SparseCholesky>
21
22namespace GooseFEM {
23
24// forward declaration
25template <class>
26class MatrixPartitionedTyingsSolver;
27
37class MatrixPartitionedTyings : public MatrixPartitionedTyingsBase<MatrixPartitionedTyings> {
38private:
42
43protected:
44 Eigen::SparseMatrix<double> m_Auu;
45 Eigen::SparseMatrix<double> m_Aup;
46 Eigen::SparseMatrix<double> m_Apu;
47 Eigen::SparseMatrix<double> m_App;
48 Eigen::SparseMatrix<double> m_Aud;
49 Eigen::SparseMatrix<double> m_Apd;
50 Eigen::SparseMatrix<double> m_Adu;
51 Eigen::SparseMatrix<double> m_Adp;
52 Eigen::SparseMatrix<double> m_Add;
53 Eigen::SparseMatrix<double> m_ACuu;
54 Eigen::SparseMatrix<double> m_ACup;
55 Eigen::SparseMatrix<double> m_ACpu;
56 Eigen::SparseMatrix<double> m_ACpp;
57 std::vector<Eigen::Triplet<double>> m_Tuu;
58 std::vector<Eigen::Triplet<double>> m_Tup;
59 std::vector<Eigen::Triplet<double>> m_Tpu;
60 std::vector<Eigen::Triplet<double>> m_Tpp;
61 std::vector<Eigen::Triplet<double>> m_Tud;
62 std::vector<Eigen::Triplet<double>> m_Tpd;
63 std::vector<Eigen::Triplet<double>> m_Tdu;
64 std::vector<Eigen::Triplet<double>> m_Tdp;
65 std::vector<Eigen::Triplet<double>> m_Tdd;
66 Eigen::SparseMatrix<double> m_Cdu;
67 Eigen::SparseMatrix<double> m_Cdp;
68 Eigen::SparseMatrix<double> m_Cud;
69 Eigen::SparseMatrix<double> m_Cpd;
70
71 // grant access to solver class
72 template <class>
74
75public:
76 MatrixPartitionedTyings() = default;
77
89 const Eigen::SparseMatrix<double>& Cdu,
90 const Eigen::SparseMatrix<double>& Cdp
91 )
92 {
93 GOOSEFEM_ASSERT(Cdu.rows() == Cdp.rows());
94
95 m_conn = conn;
96 m_dofs = dofs;
97 m_Cdu = Cdu;
98 m_Cdp = Cdp;
99 m_nnu = static_cast<size_t>(m_Cdu.cols());
100 m_nnp = static_cast<size_t>(m_Cdp.cols());
101 m_nnd = static_cast<size_t>(m_Cdp.rows());
102 m_nni = m_nnu + m_nnp;
103 m_ndof = m_nni + m_nnd;
104 m_iiu = xt::arange<size_t>(m_nnu);
105 m_iip = xt::arange<size_t>(m_nnu, m_nnu + m_nnp);
106 m_iii = xt::arange<size_t>(m_nni);
107 m_iid = xt::arange<size_t>(m_nni, m_nni + m_nnd);
108 m_nelem = m_conn.shape(0);
109 m_nne = m_conn.shape(1);
110 m_nnode = m_dofs.shape(0);
111 m_ndim = m_dofs.shape(1);
112 m_Cud = m_Cdu.transpose();
113 m_Cpd = m_Cdp.transpose();
114 m_Tuu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim);
115 m_Tup.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim);
116 m_Tpu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim);
117 m_Tpp.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim);
118 m_Tud.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim);
119 m_Tpd.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim);
120 m_Tdu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim);
121 m_Tdp.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim);
122 m_Tdd.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim);
123 m_Auu.resize(m_nnu, m_nnu);
124 m_Aup.resize(m_nnu, m_nnp);
125 m_Apu.resize(m_nnp, m_nnu);
126 m_App.resize(m_nnp, m_nnp);
127 m_Aud.resize(m_nnu, m_nnd);
128 m_Apd.resize(m_nnp, m_nnd);
129 m_Adu.resize(m_nnd, m_nnu);
130 m_Adp.resize(m_nnd, m_nnp);
131 m_Add.resize(m_nnd, m_nnd);
132
134 GOOSEFEM_ASSERT(m_ndof == xt::amax(m_dofs)() + 1);
135 }
136
140 const Eigen::SparseMatrix<double>& data_uu() const
141 {
142 return m_Auu;
143 }
144
148 const Eigen::SparseMatrix<double>& data_up() const
149 {
150 return m_Aup;
151 }
152
156 const Eigen::SparseMatrix<double>& data_pu() const
157 {
158 return m_Apu;
159 }
160
164 const Eigen::SparseMatrix<double>& data_pp() const
165 {
166 return m_App;
167 }
168
172 const Eigen::SparseMatrix<double>& data_ud() const
173 {
174 return m_Aud;
175 }
176
180 const Eigen::SparseMatrix<double>& data_pd() const
181 {
182 return m_Apd;
183 }
184
188 const Eigen::SparseMatrix<double>& data_du() const
189 {
190 return m_Adu;
191 }
192
196 const Eigen::SparseMatrix<double>& data_dp() const
197 {
198 return m_Adp;
199 }
200
204 const Eigen::SparseMatrix<double>& data_dd() const
205 {
206 return m_Add;
207 }
208
209private:
210 template <class T>
211 void assemble_impl(const T& elemmat)
212 {
213 GOOSEFEM_ASSERT(xt::has_shape(elemmat, {m_nelem, m_nne * m_ndim, m_nne * m_ndim}));
214
215 m_Tuu.clear();
216 m_Tup.clear();
217 m_Tpu.clear();
218 m_Tpp.clear();
219 m_Tud.clear();
220 m_Tpd.clear();
221 m_Tdu.clear();
222 m_Tdp.clear();
223 m_Tdd.clear();
224
225 for (size_t e = 0; e < m_nelem; ++e) {
226 for (size_t m = 0; m < m_nne; ++m) {
227 for (size_t i = 0; i < m_ndim; ++i) {
228
229 size_t di = m_dofs(m_conn(e, m), i);
230
231 for (size_t n = 0; n < m_nne; ++n) {
232 for (size_t j = 0; j < m_ndim; ++j) {
233
234 size_t dj = m_dofs(m_conn(e, n), j);
235
236 if (di < m_nnu && dj < m_nnu) {
237 m_Tuu.push_back(Eigen::Triplet<double>(
238 di, dj, elemmat(e, m * m_ndim + i, n * m_ndim + j)
239 ));
240 }
241 else if (di < m_nnu && dj < m_nni) {
242 m_Tup.push_back(Eigen::Triplet<double>(
243 di, dj - m_nnu, elemmat(e, m * m_ndim + i, n * m_ndim + j)
244 ));
245 }
246 else if (di < m_nnu) {
247 m_Tud.push_back(Eigen::Triplet<double>(
248 di, dj - m_nni, elemmat(e, m * m_ndim + i, n * m_ndim + j)
249 ));
250 }
251 else if (di < m_nni && dj < m_nnu) {
252 m_Tpu.push_back(Eigen::Triplet<double>(
253 di - m_nnu, dj, elemmat(e, m * m_ndim + i, n * m_ndim + j)
254 ));
255 }
256 else if (di < m_nni && dj < m_nni) {
257 m_Tpp.push_back(Eigen::Triplet<double>(
258 di - m_nnu,
259 dj - m_nnu,
260 elemmat(e, m * m_ndim + i, n * m_ndim + j)
261 ));
262 }
263 else if (di < m_nni) {
264 m_Tpd.push_back(Eigen::Triplet<double>(
265 di - m_nnu,
266 dj - m_nni,
267 elemmat(e, m * m_ndim + i, n * m_ndim + j)
268 ));
269 }
270 else if (dj < m_nnu) {
271 m_Tdu.push_back(Eigen::Triplet<double>(
272 di - m_nni, dj, elemmat(e, m * m_ndim + i, n * m_ndim + j)
273 ));
274 }
275 else if (dj < m_nni) {
276 m_Tdp.push_back(Eigen::Triplet<double>(
277 di - m_nni,
278 dj - m_nnu,
279 elemmat(e, m * m_ndim + i, n * m_ndim + j)
280 ));
281 }
282 else {
283 m_Tdd.push_back(Eigen::Triplet<double>(
284 di - m_nni,
285 dj - m_nni,
286 elemmat(e, m * m_ndim + i, n * m_ndim + j)
287 ));
288 }
289 }
290 }
291 }
292 }
293 }
294
295 m_Auu.setFromTriplets(m_Tuu.begin(), m_Tuu.end());
296 m_Aup.setFromTriplets(m_Tup.begin(), m_Tup.end());
297 m_Apu.setFromTriplets(m_Tpu.begin(), m_Tpu.end());
298 m_App.setFromTriplets(m_Tpp.begin(), m_Tpp.end());
299 m_Aud.setFromTriplets(m_Tud.begin(), m_Tud.end());
300 m_Apd.setFromTriplets(m_Tpd.begin(), m_Tpd.end());
301 m_Adu.setFromTriplets(m_Tdu.begin(), m_Tdu.end());
302 m_Adp.setFromTriplets(m_Tdp.begin(), m_Tdp.end());
303 m_Add.setFromTriplets(m_Tdd.begin(), m_Tdd.end());
304 m_changed = true;
305 }
306
307 // todo: test
308 template <class T>
309 void todense_impl(T& ret) const
310 {
311 ret.fill(0.0);
312
313 for (int k = 0; k < m_Auu.outerSize(); ++k) {
314 for (Eigen::SparseMatrix<double>::InnerIterator it(m_Auu, k); it; ++it) {
315 ret(m_iiu(it.row()), m_iiu(it.col())) = it.value();
316 }
317 }
318
319 for (int k = 0; k < m_Aup.outerSize(); ++k) {
320 for (Eigen::SparseMatrix<double>::InnerIterator it(m_Aup, k); it; ++it) {
321 ret(m_iiu(it.row()), m_iip(it.col())) = it.value();
322 }
323 }
324
325 for (int k = 0; k < m_Apu.outerSize(); ++k) {
326 for (Eigen::SparseMatrix<double>::InnerIterator it(m_Apu, k); it; ++it) {
327 ret(m_iip(it.row()), m_iiu(it.col())) = it.value();
328 }
329 }
330
331 for (int k = 0; k < m_App.outerSize(); ++k) {
332 for (Eigen::SparseMatrix<double>::InnerIterator it(m_App, k); it; ++it) {
333 ret(m_iip(it.row()), m_iip(it.col())) = it.value();
334 }
335 }
336
337 for (int k = 0; k < m_Adu.outerSize(); ++k) {
338 for (Eigen::SparseMatrix<double>::InnerIterator it(m_Adu, k); it; ++it) {
339 ret(m_iid(it.row()), m_iiu(it.col())) = it.value();
340 }
341 }
342
343 for (int k = 0; k < m_Adp.outerSize(); ++k) {
344 for (Eigen::SparseMatrix<double>::InnerIterator it(m_Adp, k); it; ++it) {
345 ret(m_iid(it.row()), m_iip(it.col())) = it.value();
346 }
347 }
348
349 for (int k = 0; k < m_Aud.outerSize(); ++k) {
350 for (Eigen::SparseMatrix<double>::InnerIterator it(m_Aud, k); it; ++it) {
351 ret(m_iiu(it.row()), m_iid(it.col())) = it.value();
352 }
353 }
354
355 for (int k = 0; k < m_Apd.outerSize(); ++k) {
356 for (Eigen::SparseMatrix<double>::InnerIterator it(m_Apd, k); it; ++it) {
357 ret(m_iip(it.row()), m_iid(it.col())) = it.value();
358 }
359 }
360
361 for (int k = 0; k < m_Add.outerSize(); ++k) {
362 for (Eigen::SparseMatrix<double>::InnerIterator it(m_Add, k); it; ++it) {
363 ret(m_iid(it.row()), m_iid(it.col())) = it.value();
364 }
365 }
366 }
367
368 template <class T>
369 void dot_nodevec_impl(const T& x, T& b) const
370 {
371 UNUSED(x);
372 UNUSED(b);
373 throw std::runtime_error("Not yet implemented");
374 }
375
376 template <class T>
377 void dot_dofval_impl(const T& x, T& b) const
378 {
379 UNUSED(x);
380 UNUSED(b);
381 throw std::runtime_error("Not yet implemented");
382 }
383
384 template <class T>
385 void reaction_nodevec_impl(const T& x, T& b) const
386 {
387 UNUSED(x);
388 UNUSED(b);
389 throw std::runtime_error("Not yet implemented");
390 }
391
392 template <class T>
393 void reaction_dofval_impl(const T& x, T& b) const
394 {
395 UNUSED(x);
396 UNUSED(b);
397 throw std::runtime_error("Not yet implemented");
398 }
399
400 void reaction_p_impl(
401 const array_type::tensor<double, 1>& x_u,
402 const array_type::tensor<double, 1>& x_p,
403 array_type::tensor<double, 1>& b_p
404 ) const
405 {
406 UNUSED(x_u);
407 UNUSED(x_p);
408 UNUSED(b_p);
409 throw std::runtime_error("Not yet implemented");
410 }
411
412private:
413 // Convert arrays (Eigen version of VectorPartitioned, which contains public functions)
414 Eigen::VectorXd AsDofs_u(const array_type::tensor<double, 1>& dofval) const
415 {
416 GOOSEFEM_ASSERT(dofval.size() == m_ndof);
417
418 Eigen::VectorXd dofval_u(m_nnu, 1);
419
420#pragma omp parallel for
421 for (size_t d = 0; d < m_nnu; ++d) {
422 dofval_u(d) = dofval(m_iiu(d));
423 }
424
425 return dofval_u;
426 }
427
428 Eigen::VectorXd AsDofs_u(const array_type::tensor<double, 2>& nodevec) const
429 {
430 GOOSEFEM_ASSERT(xt::has_shape(nodevec, {m_nnode, m_ndim}));
431
432 Eigen::VectorXd dofval_u = Eigen::VectorXd::Zero(m_nnu, 1);
433
434#pragma omp parallel for
435 for (size_t m = 0; m < m_nnode; ++m) {
436 for (size_t i = 0; i < m_ndim; ++i) {
437 if (m_dofs(m, i) < m_nnu) {
438 dofval_u(m_dofs(m, i)) = nodevec(m, i);
439 }
440 }
441 }
442
443 return dofval_u;
444 }
445
446 Eigen::VectorXd AsDofs_p(const array_type::tensor<double, 1>& dofval) const
447 {
448 GOOSEFEM_ASSERT(dofval.size() == m_ndof);
449
450 Eigen::VectorXd dofval_p(m_nnp, 1);
451
452#pragma omp parallel for
453 for (size_t d = 0; d < m_nnp; ++d) {
454 dofval_p(d) = dofval(m_iip(d));
455 }
456
457 return dofval_p;
458 }
459
460 Eigen::VectorXd AsDofs_p(const array_type::tensor<double, 2>& nodevec) const
461 {
462 GOOSEFEM_ASSERT(xt::has_shape(nodevec, {m_nnode, m_ndim}));
463
464 Eigen::VectorXd dofval_p = Eigen::VectorXd::Zero(m_nnp, 1);
465
466#pragma omp parallel for
467 for (size_t m = 0; m < m_nnode; ++m) {
468 for (size_t i = 0; i < m_ndim; ++i) {
469 if (m_dofs(m, i) >= m_nnu && m_dofs(m, i) < m_nni) {
470 dofval_p(m_dofs(m, i) - m_nnu) = nodevec(m, i);
471 }
472 }
473 }
474
475 return dofval_p;
476 }
477
478 Eigen::VectorXd AsDofs_d(const array_type::tensor<double, 1>& dofval) const
479 {
480 GOOSEFEM_ASSERT(dofval.size() == m_ndof);
481
482 Eigen::VectorXd dofval_d(m_nnd, 1);
483
484#pragma omp parallel for
485 for (size_t d = 0; d < m_nnd; ++d) {
486 dofval_d(d) = dofval(m_iip(d));
487 }
488
489 return dofval_d;
490 }
491
492 Eigen::VectorXd AsDofs_d(const array_type::tensor<double, 2>& nodevec) const
493 {
494 GOOSEFEM_ASSERT(xt::has_shape(nodevec, {m_nnode, m_ndim}));
495
496 Eigen::VectorXd dofval_d = Eigen::VectorXd::Zero(m_nnd, 1);
497
498#pragma omp parallel for
499 for (size_t m = 0; m < m_nnode; ++m) {
500 for (size_t i = 0; i < m_ndim; ++i) {
501 if (m_dofs(m, i) >= m_nni) {
502 dofval_d(m_dofs(m, i) - m_nni) = nodevec(m, i);
503 }
504 }
505 }
506
507 return dofval_d;
508 }
509};
510
527template <class Solver = Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>>>
529 : public MatrixSolverBase<MatrixPartitionedTyingsSolver<Solver>>,
530 public MatrixSolverPartitionedBase<MatrixPartitionedTyingsSolver<Solver>> {
531private:
534
535public:
537
538private:
539 template <class T>
540 void solve_nodevec_impl(MatrixPartitionedTyings& A, const T& b, T& x)
541 {
542 this->factorize(A);
543
544 Eigen::VectorXd B_u = A.AsDofs_u(b);
545 Eigen::VectorXd B_d = A.AsDofs_d(b);
546 Eigen::VectorXd X_p = A.AsDofs_p(x);
547
548 B_u += A.m_Cud * B_d;
549
550 Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - A.m_ACup * X_p));
551 Eigen::VectorXd X_d = A.m_Cdu * X_u + A.m_Cdp * X_p;
552
553#pragma omp parallel for
554 for (size_t m = 0; m < A.m_nnode; ++m) {
555 for (size_t i = 0; i < A.m_ndim; ++i) {
556 if (A.m_dofs(m, i) < A.m_nnu) {
557 x(m, i) = X_u(A.m_dofs(m, i));
558 }
559 else if (A.m_dofs(m, i) >= A.m_nni) {
560 x(m, i) = X_d(A.m_dofs(m, i) - A.m_nni);
561 }
562 }
563 }
564 }
565
566 template <class T>
567 void solve_dofval_impl(MatrixPartitionedTyings& A, const T& b, T& x)
568 {
569 this->factorize(A);
570
571 Eigen::VectorXd B_u = A.AsDofs_u(b);
572 Eigen::VectorXd B_d = A.AsDofs_d(b);
573 Eigen::VectorXd X_p = A.AsDofs_p(x);
574
575 Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - A.m_ACup * X_p));
576 Eigen::VectorXd X_d = A.m_Cdu * X_u + A.m_Cdp * X_p;
577
578#pragma omp parallel for
579 for (size_t d = 0; d < A.m_nnu; ++d) {
580 x(A.m_iiu(d)) = X_u(d);
581 }
582
583#pragma omp parallel for
584 for (size_t d = 0; d < A.m_nnd; ++d) {
585 x(A.m_iid(d)) = X_d(d);
586 }
587 }
588
589public:
606 )
607 {
608 array_type::tensor<double, 1> x_u = xt::empty<double>({A.m_nnu});
609 this->solve_u(A, b_u, b_d, x_p, x_u);
610 return x_u;
611 }
612
631 )
632 {
633 UNUSED(b_d);
634 GOOSEFEM_ASSERT(b_u.size() == A.m_nnu);
635 GOOSEFEM_ASSERT(b_d.size() == A.m_nnd);
636 GOOSEFEM_ASSERT(x_p.size() == A.m_nnp);
637 GOOSEFEM_ASSERT(x_u.size() == A.m_nnu);
638
639 this->factorize(A);
640
641 Eigen::Map<Eigen::VectorXd>(x_u.data(), x_u.size()).noalias() =
642 m_solver.solve(Eigen::VectorXd(
643 Eigen::Map<const Eigen::VectorXd>(b_u.data(), b_u.size()) -
644 A.m_ACup * Eigen::Map<const Eigen::VectorXd>(x_p.data(), x_p.size())
645 ));
646 }
647
648private:
649 Solver m_solver;
650 bool m_factor = true;
651
655 void factorize(MatrixPartitionedTyings& A)
656 {
657 if (!A.m_changed && !m_factor) {
658 return;
659 }
660
661 A.m_ACuu = A.m_Auu + A.m_Aud * A.m_Cdu + A.m_Cud * A.m_Adu + A.m_Cud * A.m_Add * A.m_Cdu;
662
663 A.m_ACup = A.m_Aup + A.m_Aud * A.m_Cdp + A.m_Cud * A.m_Adp + A.m_Cud * A.m_Add * A.m_Cdp;
664
665 // A.m_ACpu = A.m_Apu + A.m_Apd * A.m_Cdu + A.m_Cpd * A.m_Adu
666 // + A.m_Cpd * A.m_Add * A.m_Cdu;
667
668 // A.m_ACpp = A.m_App + A.m_Apd * A.m_Cdp + A.m_Cpd * A.m_Adp
669 // + A.m_Cpd * A.m_Add * A.m_Cdp;
670
671 m_solver.compute(A.m_ACuu);
672 m_factor = false;
673 A.m_changed = false;
674 }
675};
676
677} // namespace GooseFEM
678
679#endif
CRTP base class for a matrix.
Definition Matrix.h:198
const array_type::tensor< size_t, 2 > & dofs() const
DOFs per node.
Definition Matrix.h:278
const array_type::tensor< size_t, 2 > & conn() const
Connectivity.
Definition Matrix.h:287
array_type::tensor< size_t, 2 > m_dofs
DOF-numbers per node [nnode, ndim].
Definition Matrix.h:201
array_type::tensor< size_t, 2 > m_conn
Connectivity [nelem, nne].
Definition Matrix.h:200
size_t m_nelem
See nelem().
Definition Matrix.h:203
size_t m_nne
See nne().
Definition Matrix.h:204
bool m_changed
Signal changes to data.
Definition Matrix.h:209
size_t m_nnode
See nnode().
Definition Matrix.h:205
size_t m_ndim
See ndim().
Definition Matrix.h:206
size_t m_ndof
See ndof().
Definition Matrix.h:207
CRTP base class for a partitioned matrix.
Definition Matrix.h:416
array_type::tensor< size_t, 1 > m_iiu
See iiu()
Definition Matrix.h:418
array_type::tensor< size_t, 1 > m_iip
See iip()
Definition Matrix.h:419
CRTP base class for a partitioned matrix with tying.
Definition Matrix.h:585
array_type::tensor< size_t, 1 > m_iii
See iii()
Definition Matrix.h:587
array_type::tensor< size_t, 1 > m_iid
See iid()
Definition Matrix.h:588
Solver for MatrixPartitionedTyings().
array_type::tensor< double, 1 > Solve_u(MatrixPartitionedTyings &A, const array_type::tensor< double, 1 > &b_u, const array_type::tensor< double, 1 > &b_d, const array_type::tensor< double, 1 > &x_p)
Same as Solve(MatrixPartitionedTyings&, const array_type::tensor<double, 2>&, const array_type::tenso...
void solve_u(MatrixPartitionedTyings &A, const array_type::tensor< double, 1 > &b_u, const array_type::tensor< double, 1 > &b_d, const array_type::tensor< double, 1 > &x_p, array_type::tensor< double, 1 > &x_u)
Same as Solve_u(MatrixPartitionedTyings&, const array_type::tensor<double, 1>&, const array_type::ten...
Sparse matrix from with dependent DOFs are eliminated, and the remaining (small) independent system i...
std::vector< Eigen::Triplet< double > > m_Tpp
Matrix entries.
Eigen::SparseMatrix< double > m_Auu
The matrix.
const Eigen::SparseMatrix< double > & data_pd() const
Pointer to data.
std::vector< Eigen::Triplet< double > > m_Tup
Matrix entries.
Eigen::SparseMatrix< double > m_Cdu
Tying matrix, see Tyings::Periodic::Cdu().
Eigen::SparseMatrix< double > m_App
The matrix.
Eigen::SparseMatrix< double > m_ACup
// The matrix for which the tyings have been applied.
Eigen::SparseMatrix< double > m_Aup
The matrix.
Eigen::SparseMatrix< double > m_Adp
The matrix.
Eigen::SparseMatrix< double > m_Apd
The matrix.
std::vector< Eigen::Triplet< double > > m_Tdu
Matrix entries.
std::vector< Eigen::Triplet< double > > m_Tdd
Matrix entries.
const Eigen::SparseMatrix< double > & data_uu() const
Pointer to data.
Eigen::SparseMatrix< double > m_Apu
The matrix.
const Eigen::SparseMatrix< double > & data_dd() const
Pointer to data.
const Eigen::SparseMatrix< double > & data_pu() const
Pointer to data.
const Eigen::SparseMatrix< double > & data_ud() const
Pointer to data.
Eigen::SparseMatrix< double > m_ACpp
// The matrix for which the tyings have been applied.
std::vector< Eigen::Triplet< double > > m_Tpd
Matrix entries.
Eigen::SparseMatrix< double > m_Add
The matrix.
Eigen::SparseMatrix< double > m_Aud
The matrix.
Eigen::SparseMatrix< double > m_ACpu
// The matrix for which the tyings have been applied.
const Eigen::SparseMatrix< double > & data_pp() const
Pointer to data.
const Eigen::SparseMatrix< double > & data_up() const
Pointer to data.
Eigen::SparseMatrix< double > m_Adu
The matrix.
MatrixPartitionedTyings(const array_type::tensor< size_t, 2 > &conn, const array_type::tensor< size_t, 2 > &dofs, const Eigen::SparseMatrix< double > &Cdu, const Eigen::SparseMatrix< double > &Cdp)
Constructor.
const Eigen::SparseMatrix< double > & data_du() const
Pointer to data.
std::vector< Eigen::Triplet< double > > m_Tud
Matrix entries.
Eigen::SparseMatrix< double > m_Cpd
Transpose of "m_Cdp".
Eigen::SparseMatrix< double > m_ACuu
// The matrix for which the tyings have been applied.
std::vector< Eigen::Triplet< double > > m_Tuu
Matrix entries.
const Eigen::SparseMatrix< double > & data_dp() const
Pointer to data.
Eigen::SparseMatrix< double > m_Cdp
Tying matrix, see Tyings::Periodic::Cdp().
std::vector< Eigen::Triplet< double > > m_Tpu
Matrix entries.
std::vector< Eigen::Triplet< double > > m_Tdp
Matrix entries.
Eigen::SparseMatrix< double > m_Cud
Transpose of "m_Cdu".
CRTP base class for a solver class.
Definition Matrix.h:26
CRTP base class for a extra functions for a partitioned solver class.
Definition Matrix.h:136
Basic configuration:
#define GOOSEFEM_ASSERT(expr)
All assertions are implementation as::
Definition config.h:97
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Definition config.h:177
Toolbox to perform finite element computations.
Definition Allocate.h:14
auto AsTensor(const T &arg, const S &shape)
"Broadcast" a scalar stored in an array (e.g.
Definition Allocate.h:167