GooseFEM 1.4.1.dev2+g78f16df
Loading...
Searching...
No Matches
MatrixDiagonalPartitioned.h
Go to the documentation of this file.
1
11#ifndef GOOSEFEM_MATRIXDIAGONALPARTITIONED_H
12#define GOOSEFEM_MATRIXDIAGONALPARTITIONED_H
13
14#include "MatrixDiagonal.h"
15#include "Mesh.h"
16#include "config.h"
17
18namespace GooseFEM {
19
25class MatrixDiagonalPartitioned : public MatrixPartitionedBase<MatrixDiagonalPartitioned>,
26 public MatrixDiagonalBase<MatrixDiagonalPartitioned> {
27private:
31
32public:
33 MatrixDiagonalPartitioned() = default;
34
46 )
47 {
48 m_conn = conn;
49 m_dofs = dofs;
50 m_nelem = m_conn.shape(0);
51 m_nne = m_conn.shape(1);
52 m_nnode = m_dofs.shape(0);
53 m_ndim = m_dofs.shape(1);
54 m_ndof = xt::amax(m_dofs)() + 1;
55
57 GOOSEFEM_ASSERT(xt::amax(conn)() + 1 <= m_nnode);
59 GOOSEFEM_ASSERT(xt::amax(iip)() <= xt::amax(dofs)());
60
61 m_iip = iip;
62 m_iiu = xt::setdiff1d(dofs, iip);
63 m_nnp = m_iip.size();
64 m_nnu = m_iiu.size();
65 m_part = Mesh::Reorder({m_iiu, m_iip}).apply(m_dofs);
66 m_Auu = xt::empty<double>({m_nnu});
67 m_App = xt::empty<double>({m_nnp});
68 m_inv_uu = xt::empty<double>({m_nnu});
69 }
70
71private:
72 template <class T>
73 void assemble_impl(const T& elemmat)
74 {
75 GOOSEFEM_ASSERT(xt::has_shape(elemmat, {m_nelem, m_nne * m_ndim, m_nne * m_ndim}));
77
78 m_Auu.fill(0.0);
79 m_App.fill(0.0);
80
81 for (size_t e = 0; e < m_nelem; ++e) {
82 for (size_t m = 0; m < m_nne; ++m) {
83 for (size_t i = 0; i < m_ndim; ++i) {
84
85 size_t d = m_part(m_conn(e, m), i);
86
87 if (d < m_nnu) {
88 m_Auu(d) += elemmat(e, m * m_ndim + i, m * m_ndim + i);
89 }
90 else {
91 m_App(d - m_nnu) += elemmat(e, m * m_ndim + i, m * m_ndim + i);
92 }
93 }
94 }
95 }
96
97 m_changed = true;
98 }
99
100 template <class T>
101 void todense_impl(T& ret) const
102 {
103 ret.fill(0.0);
104
105#pragma omp parallel for
106 for (size_t d = 0; d < m_nnu; ++d) {
107 ret(m_iiu(d), m_iiu(d)) = m_Auu(d);
108 }
109
110#pragma omp parallel for
111 for (size_t d = 0; d < m_nnp; ++d) {
112 ret(m_iip(d), m_iip(d)) = m_App(d);
113 }
114 }
115
116public:
122 {
123 GOOSEFEM_ASSERT(A.size() == m_ndof);
124
125#pragma omp parallel for
126 for (size_t d = 0; d < m_nnu; ++d) {
127 m_Auu(d) = A(m_iiu(d));
128 }
129
130#pragma omp parallel for
131 for (size_t d = 0; d < m_nnp; ++d) {
132 m_App(d) = A(m_iip(d));
133 }
134
135 m_changed = true;
136 }
137
143 {
144 array_type::tensor<double, 1> ret = xt::zeros<double>({m_ndof});
145
146#pragma omp parallel for
147 for (size_t d = 0; d < m_nnu; ++d) {
148 ret(m_iiu(d)) = m_Auu(d);
149 }
150
151#pragma omp parallel for
152 for (size_t d = 0; d < m_nnp; ++d) {
153 ret(m_iip(d)) = m_App(d);
154 }
155
156 return ret;
157 }
158
164 {
165 return m_Auu;
166 }
167
173 {
174 return m_App;
175 }
176
181 [[deprecated]]
183 {
184 return this->data();
185 }
186
187private:
188 template <class T>
189 void dot_nodevec_impl(const T& x, T& b) const
190 {
191 GOOSEFEM_ASSERT(xt::has_shape(x, {m_nnode, m_ndim}));
192 GOOSEFEM_ASSERT(xt::has_shape(b, {m_nnode, m_ndim}));
193
194#pragma omp parallel for
195 for (size_t m = 0; m < m_nnode; ++m) {
196 for (size_t i = 0; i < m_ndim; ++i) {
197
198 size_t d = m_part(m, i);
199
200 if (d < m_nnu) {
201 b(m, i) = m_Auu(d) * x(m, i);
202 }
203 else {
204 b(m, i) = m_App(d - m_nnu) * x(m, i);
205 }
206 }
207 }
208 }
209
210 template <class T>
211 void dot_dofval_impl(const T& x, T& b) const
212 {
213 GOOSEFEM_ASSERT(x.size() == m_ndof);
214 GOOSEFEM_ASSERT(b.size() == m_ndof);
215
216#pragma omp parallel for
217 for (size_t d = 0; d < m_nnu; ++d) {
218 b(m_iiu(d)) = m_Auu(d) * x(m_iiu(d));
219 }
220
221#pragma omp parallel for
222 for (size_t d = 0; d < m_nnp; ++d) {
223 b(m_iip(d)) = m_App(d) * x(m_iip(d));
224 }
225 }
226
227public:
234 array_type::tensor<double, 1>
236 {
237 array_type::tensor<double, 1> b_u = xt::empty<double>({m_nnu});
238 this->dot_u(x_u, x_p, b_u);
239 return b_u;
240 }
241
248 void dot_u(
252 ) const
253 {
254 UNUSED(x_p);
255
256 GOOSEFEM_ASSERT(x_u.size() == m_nnu);
257 GOOSEFEM_ASSERT(x_p.size() == m_nnp);
258 GOOSEFEM_ASSERT(b_u.size() == m_nnu);
259
260#pragma omp parallel for
261 for (size_t d = 0; d < m_nnu; ++d) {
262 b_u(d) = m_Auu(d) * x_u(d);
263 }
264 }
265
274 {
275 array_type::tensor<double, 1> b_p = xt::empty<double>({m_nnp});
276 this->dot_p(x_u, x_p, b_p);
277 return b_p;
278 }
279
286 void dot_p(
290 ) const
291 {
292 UNUSED(x_u);
293
294 GOOSEFEM_ASSERT(x_u.size() == m_nnu);
295 GOOSEFEM_ASSERT(x_p.size() == m_nnp);
296 GOOSEFEM_ASSERT(b_p.size() == m_nnp);
297
298#pragma omp parallel for
299 for (size_t d = 0; d < m_nnp; ++d) {
300 b_p(d) = m_App(d) * x_p(d);
301 }
302 }
303
304private:
305 template <class T>
306 void solve_nodevec_impl(const T& b, T& x)
307 {
308 GOOSEFEM_ASSERT(xt::has_shape(b, {m_nnode, m_ndim}));
309 GOOSEFEM_ASSERT(xt::has_shape(x, {m_nnode, m_ndim}));
310
311 this->factorize();
312
313#pragma omp parallel for
314 for (size_t m = 0; m < m_nnode; ++m) {
315 for (size_t i = 0; i < m_ndim; ++i) {
316 if (m_part(m, i) < m_nnu) {
317 x(m, i) = m_inv_uu(m_part(m, i)) * b(m, i);
318 }
319 }
320 }
321 }
322
323 template <class T>
324 void solve_dofval_impl(const T& b, T& x)
325 {
326 GOOSEFEM_ASSERT(b.size() == m_ndof);
327 GOOSEFEM_ASSERT(x.size() == m_ndof);
328
329 this->factorize();
330
331#pragma omp parallel for
332 for (size_t d = 0; d < m_nnu; ++d) {
333 x(m_iiu(d)) = m_inv_uu(d) * b(m_iiu(d));
334 }
335 }
336
337public:
343 array_type::tensor<double, 1>
345 {
346 array_type::tensor<double, 1> x_u = xt::empty<double>({m_nnu});
347 this->solve_u(b_u, x_p, x_u);
348 return x_u;
349 }
350
360 )
361 {
362 UNUSED(x_p);
363
364 GOOSEFEM_ASSERT(b_u.size() == m_nnu);
365 GOOSEFEM_ASSERT(x_p.size() == m_nnp);
366 GOOSEFEM_ASSERT(x_u.size() == m_nnu);
367
368 this->factorize();
369
370#pragma omp parallel for
371 for (size_t d = 0; d < m_nnu; ++d) {
372 x_u(d) = m_inv_uu(d) * b_u(d);
373 }
374 }
375
376private:
377 template <class T>
378 void reaction_nodevec_impl(const T& x, T& b) const
379 {
380 GOOSEFEM_ASSERT(xt::has_shape(x, {m_nnode, m_ndim}));
381 GOOSEFEM_ASSERT(xt::has_shape(b, {m_nnode, m_ndim}));
382
383#pragma omp parallel for
384 for (size_t m = 0; m < m_nnode; ++m) {
385 for (size_t i = 0; i < m_ndim; ++i) {
386 if (m_part(m, i) >= m_nnu) {
387 b(m, i) = m_App(m_part(m, i) - m_nnu) * x(m, i);
388 }
389 }
390 }
391 }
392
393 template <class T>
394 void reaction_dofval_impl(const T& x, T& b) const
395 {
396 GOOSEFEM_ASSERT(x.size() == m_ndof);
397 GOOSEFEM_ASSERT(b.size() == m_ndof);
398
399#pragma omp parallel for
400 for (size_t d = 0; d < m_nnp; ++d) {
401 b(m_iip(d)) = m_App(d) * x(m_iip(d));
402 }
403 }
404
405 void reaction_p_impl(
406 const array_type::tensor<double, 1>& x_u,
407 const array_type::tensor<double, 1>& x_p,
408 array_type::tensor<double, 1>& b_p
409 ) const
410 {
411 UNUSED(x_u);
412
413 GOOSEFEM_ASSERT(x_u.size() == m_nnu);
414 GOOSEFEM_ASSERT(x_p.size() == m_nnp);
415 GOOSEFEM_ASSERT(b_p.size() == m_nnp);
416
417#pragma omp parallel for
418 for (size_t d = 0; d < m_nnp; ++d) {
419 b_p(d) = m_App(d) * x_p(d);
420 }
421 }
422
423private:
424 // The diagonal matrix, and its inverse (re-used to solve different RHS)
425 array_type::tensor<double, 1> m_Auu;
426 array_type::tensor<double, 1> m_App;
427 array_type::tensor<double, 1> m_inv_uu;
428
429 // Bookkeeping
430 array_type::tensor<size_t, 2> m_part; // DOF-numbers per node, renumbered [nnode, ndim]
431 array_type::tensor<size_t, 1> m_iiu; // DOF-numbers that are unknown [nnu]
432 array_type::tensor<size_t, 1> m_iip; // DOF-numbers that are prescribed [nnp]
433
434 // Dimensions
435 size_t m_nnu; // number of unknown DOFs
436 size_t m_nnp; // number of prescribed DOFs
437
438 // Compute inverse (automatically evaluated by "solve")
439 void factorize()
440 {
441 if (!m_changed) {
442 return;
443 }
444
445#pragma omp parallel for
446 for (size_t d = 0; d < m_nnu; ++d) {
447 m_inv_uu(d) = 1.0 / m_Auu(d);
448 }
449
450 m_changed = false;
451 }
452};
453
454} // namespace GooseFEM
455
456#endif
Diagonal matrix.
Generic mesh operations.
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 with tying.
array_type::tensor< double, 1 > Solve_u(const array_type::tensor< double, 1 > &b_u, const array_type::tensor< double, 1 > &x_p)
MatrixDiagonalPartitioned(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.
void dot_u(const array_type::tensor< double, 1 > &x_u, const array_type::tensor< double, 1 > &x_p, array_type::tensor< double, 1 > &b_u) const
const array_type::tensor< double, 1 > & data_uu() const
Pointer to data.
array_type::tensor< double, 1 > Dot_p(const array_type::tensor< double, 1 > &x_u, const array_type::tensor< double, 1 > &x_p) const
array_type::tensor< double, 1 > data() const
Assemble to diagonal matrix (involves copies).
array_type::tensor< double, 1 > Todiagonal() const
Pointer to data.
array_type::tensor< double, 1 > Dot_u(const array_type::tensor< double, 1 > &x_u, const array_type::tensor< double, 1 > &x_p) const
void solve_u(const array_type::tensor< double, 1 > &b_u, const array_type::tensor< double, 1 > &x_p, array_type::tensor< double, 1 > &x_u)
void set(const array_type::tensor< double, 1 > &A)
Set all (diagonal) matrix components.
const array_type::tensor< double, 1 > & data_pp() const
Pointer to data.
void dot_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
CRTP base class for a partitioned matrix.
Definition Matrix.h:416
const array_type::tensor< size_t, 1 > & iip() const
Prescribed DOFs.
Definition Matrix.h:473
Reorder to lowest possible index, in specific order.
Definition Mesh.h:2384
Basic configuration:
#define GOOSEFEM_ASSERT(expr)
All assertions are implementation as::
Definition config.h:97
bool isDiagonal(const array_type::tensor< double, 3 > &elemmat)
Check that all of the matrices stored per elemmat (shape: [nelem, nne * ndim, nne * ndim]) are diagon...
Definition Element.h:122
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Definition config.h:177
Toolbox to perform finite element computations.
Definition Allocate.h:14
bool is_unique(const T &arg)
Returns true is a list is unique (has not duplicate items).
Definition assertions.h:20
auto AsTensor(const T &arg, const S &shape)
"Broadcast" a scalar stored in an array (e.g.
Definition Allocate.h:167