GooseFEM 1.4.1.dev2+g78f16df
Loading...
Searching...
No Matches
TyingsPeriodic.h
Go to the documentation of this file.
1
9#ifndef GOOSEFEM_TYINGSPERIODIC_H
10#define GOOSEFEM_TYINGSPERIODIC_H
11
12#include "Mesh.h"
13#include "config.h"
14
15#include <Eigen/Eigen>
16#include <Eigen/Sparse>
17
18namespace GooseFEM {
19
23namespace Tyings {
24
46class Periodic {
47public:
48 Periodic() = default;
49
62 template <class C, class D, class S, class T>
63 Periodic(const C& coor, const D& dofs, const S& control_dofs, const T& nodal_tyings)
65 {
66 }
67
82 template <class C, class D, class S, class T, class U>
84 const C& coor,
85 const D& dofs,
86 const S& control_dofs,
87 const T& nodal_tyings,
88 const U& iip
89 )
90 {
91 m_tyings = nodal_tyings;
92 m_coor = coor;
93 m_ndim = m_coor.shape(1);
94 m_nties = m_tyings.shape(0);
95
96 GOOSEFEM_ASSERT(xt::has_shape(m_tyings, {m_nties, size_t(2)}));
97 GOOSEFEM_ASSERT(xt::has_shape(control_dofs, {m_ndim, m_ndim}));
98 GOOSEFEM_ASSERT(xt::has_shape(dofs, m_coor.shape()));
99 GOOSEFEM_ASSERT(xt::amax(control_dofs)() <= xt::amax(dofs)());
100 GOOSEFEM_ASSERT(xt::amin(control_dofs)() >= xt::amin(dofs)());
101 GOOSEFEM_ASSERT(xt::amax(iip)() <= xt::amax(dofs)());
102 GOOSEFEM_ASSERT(xt::amin(iip)() >= xt::amin(dofs)());
103 GOOSEFEM_ASSERT(xt::amax(nodal_tyings)() < m_coor.shape(0));
104
105 array_type::tensor<size_t, 1> dependent = xt::view(m_tyings, xt::all(), 1);
107 xt::view(dofs, xt::keep(dependent), xt::all());
108 U iid = xt::flatten(dependent_dofs);
109 U iii = xt::setdiff1d(dofs, iid);
110 U iiu = xt::setdiff1d(iii, iip);
111
112 m_nnu = iiu.size();
113 m_nnp = iip.size();
114 m_nni = iii.size();
115 m_nnd = iid.size();
116
118
119 m_dofs = reorder.apply(dofs);
120 m_control = reorder.apply(control_dofs);
121 }
122
126 size_t nnd() const
127 {
128 return m_nnd;
129 }
130
134 size_t nni() const
135 {
136 return m_nni;
137 }
138
142 size_t nnu() const
143 {
144 return m_nnu;
145 }
146
150 size_t nnp() const
151 {
152 return m_nnp;
153 }
154
159 {
160 return m_dofs;
161 }
162
168 {
169 return m_control;
170 }
171
180 {
181 return m_tyings;
182 }
183
190 {
191 return xt::arange<size_t>(m_nni, m_nni + m_nnd);
192 }
193
200 {
201 return xt::arange<size_t>(m_nni);
202 }
203
210 {
211 return xt::arange<size_t>(m_nnu);
212 }
213
220 {
221 return xt::arange<size_t>(m_nnp) + m_nnu;
222 }
223
238 Eigen::SparseMatrix<double> Cdi() const
239 {
240 std::vector<Eigen::Triplet<double>> data;
241
242 data.reserve(m_nties * m_ndim * (m_ndim + 1));
243
244 for (size_t i = 0; i < m_nties; ++i) {
245 for (size_t j = 0; j < m_ndim; ++j) {
246
247 size_t ni = m_tyings(i, 0);
248 size_t nd = m_tyings(i, 1);
249
250 data.push_back(Eigen::Triplet<double>(i * m_ndim + j, m_dofs(ni, j), +1.0));
251
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)
255 ));
256 }
257 }
258 }
259
260 Eigen::SparseMatrix<double> Cdi;
261 Cdi.resize(m_nnd, m_nni);
262 Cdi.setFromTriplets(data.begin(), data.end());
263
264 return Cdi;
265 }
266
272 Eigen::SparseMatrix<double> Cdu() const
273 {
274 std::vector<Eigen::Triplet<double>> data;
275
276 data.reserve(m_nties * m_ndim * (m_ndim + 1));
277
278 for (size_t i = 0; i < m_nties; ++i) {
279 for (size_t j = 0; j < m_ndim; ++j) {
280
281 size_t ni = m_tyings(i, 0);
282 size_t nd = m_tyings(i, 1);
283
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));
286 }
287
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)
292 ));
293 }
294 }
295 }
296 }
297
298 Eigen::SparseMatrix<double> Cdu;
299 Cdu.resize(m_nnd, m_nnu);
300 Cdu.setFromTriplets(data.begin(), data.end());
301
302 return Cdu;
303 }
304
310 Eigen::SparseMatrix<double> Cdp() const
311 {
312 std::vector<Eigen::Triplet<double>> data;
313
314 data.reserve(m_nties * m_ndim * (m_ndim + 1));
315
316 for (size_t i = 0; i < m_nties; ++i) {
317 for (size_t j = 0; j < m_ndim; ++j) {
318
319 size_t ni = m_tyings(i, 0);
320 size_t nd = m_tyings(i, 1);
321
322 if (m_dofs(ni, j) >= m_nnu) {
323 data.push_back(
324 Eigen::Triplet<double>(i * m_ndim + j, m_dofs(ni, j) - m_nnu, +1.0)
325 );
326 }
327
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)
332 ));
333 }
334 }
335 }
336 }
337
338 Eigen::SparseMatrix<double> Cdp;
339 Cdp.resize(m_nnd, m_nnp);
340 Cdp.setFromTriplets(data.begin(), data.end());
341
342 return Cdp;
343 }
344
345private:
346 size_t m_nnu;
347 size_t m_nnp;
348 size_t m_nni;
349 size_t m_nnd;
350 size_t m_ndim;
351 size_t m_nties;
356};
357
361class Control {
362public:
363 Control() = default;
364
373 template <class C, class N>
374 Control(const C& coor, const N& dofs)
375 {
376 GOOSEFEM_ASSERT(coor.shape().size() == 2);
377 GOOSEFEM_ASSERT(coor.shape() == dofs.shape());
378
379 m_coor = coor;
380 m_dofs = dofs;
381
382 size_t nnode = coor.shape(0);
383 size_t ndim = coor.shape(1);
384
385 m_control_dofs = xt::arange<size_t>(ndim * ndim).reshape({ndim, ndim});
386 m_control_dofs += xt::amax(dofs)() + 1;
387
388 m_control_nodes = nnode + xt::arange<size_t>(ndim);
389
390 m_coor = xt::concatenate(xt::xtuple(coor, xt::zeros<double>({ndim, ndim})));
391 m_dofs = xt::concatenate(xt::xtuple(dofs, m_control_dofs));
392 }
393
400 {
401 return m_coor;
402 }
403
410 {
411 return m_dofs;
412 }
413
420 {
421 return m_control_dofs;
422 }
423
430 {
431 return m_control_nodes;
432 }
433
434private:
437 array_type::tensor<size_t, 2> m_control_dofs;
438 array_type::tensor<size_t, 1> m_control_nodes;
439};
440
441} // namespace Tyings
442} // namespace GooseFEM
443
444#endif
Generic mesh operations.
Reorder to lowest possible index, in specific order.
Definition Mesh.h:2384
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.
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