b2api
B2000++ API Reference Manual, VERSION 4.6
 
Loading...
Searching...
No Matches
b2element_klt_util.H
1//------------------------------------------------------------------------
2// b2element_klt_util.H --
3//
4// Data structures for scalar and vector quantities with
5// derivatives by the dof and by the element-internal directions.
6//
7// written by Thomas Ludwig
8// Harald Klimach <harald.klimach@dlr.de>
9// Neda Ebrahimi Pour <neda.ebrahimipour@dlr.de>
10//
11// Copyright (c) 2015,2016,2017 SMR Engineering & Development SA
12// 2502 Bienne, Switzerland
13//
14// All Rights Reserved. Proprietary source code. The contents of
15// this file may not be disclosed to third parties, copied or
16// duplicated in any form, in whole or in part, without the prior
17// written permission of SMR.
18//------------------------------------------------------------------------
19
20#ifndef __B2ELEMENT_KLT_UTIL_H__
21#define __B2ELEMENT_KLT_UTIL_H__
22
23// #define KLT_WITH_HIGH_ORDER_ELEMENTS 1
24
25#include <iostream>
26#include <vector>
27
28#include "b2ppconfig.h"
29#include "utils/b2linear_algebra.H"
31#include "utils/b2vec3.H"
32
33namespace b2000::klt {
34
35enum {
36 DOF_TYPE_UNKNOWN = 0,
37 DOF_TYPE_DX = 1,
38 DOF_TYPE_DY = 2,
39 DOF_TYPE_DZ = 3,
40 DOF_TYPE_DW = 4,
41 DOF_TYPE_RX = 5,
42 DOF_TYPE_RY = 6,
43 DOF_TYPE_RZ = 7
44};
45
46enum {
47 SUB_ALL = 0,
48 SUB_EDGE_C0 = 1,
49 SUB_EDGE_C1 = 2,
50 SUB_EDGE_C2 = 3,
51 SUB_VERTEX_C0 = 4,
52 SUB_VERTEX_C1 = 5,
53 SUB_VERTEX_C2 = 6
54};
55
56enum {
57 GEOM_ISOPARAMETRIC,
58 GEOM_ANALYTIC_CYLINDER,
59 GEOM_ANALYTIC_HYPERBOLIC_PARABOLOID,
60 GEOM_ANALYTIC_STRAIGHT_EDGES
61};
62
63class IntegrationScheme {
64public:
65 size_t get_num() const { return int(points.size()); }
66
67 void get_point(const size_t ip, double xi[2], double& weight) const {
68 const Point& p = points[ip];
69 std::copy(p.xi, p.xi + 2, xi);
70 weight = p.weight;
71 }
72
73 struct Point {
74 double xi[2];
75 double weight;
76
77 Point(const double xi_[2], const double weight_) : weight(weight_) {
78 std::copy(xi_, xi_ + 2, xi);
79 }
80
81 Point(const double r, const double s, const double weight_) : weight(weight_) {
82 xi[0] = r;
83 xi[1] = s;
84 }
85 };
86
87 typedef std::vector<Point> PointVector;
88
89 PointVector points;
90};
91
92template <typename T>
93class Array2 {
94public:
95 Array2() : size1_(0), size2_(0), m2_(0), m3_(0) {}
96
97 Array2(size_t size1, size_t size2, const T& t = T())
98 : size1_(size1), size2_(size2), m2_(size1_), m3_(m2_ * size2_), data_(m3_, t) {}
99
100 void set_zero() { std::fill(data_.begin(), data_.end(), T()); }
101
102 void swap(Array2& o) {
103 std::swap(size1_, o.size1_);
104 std::swap(size2_, o.size2_);
105 std::swap(m2_, o.m2_);
106 std::swap(m3_, o.m3_);
107 data_.swap(o.data_);
108 }
109
110 template <typename T1>
111 Array2& operator=(const Array2<T1>& o) {
112 size1_ = o.size1_;
113 size2_ = o.size2_;
114 m2_ = o.m2_;
115 m3_ = o.m3_;
116 data_.resize(m3_);
117 for (size_t i = 0; i != m3_; ++i) { data_[i] = o.data_[i]; }
118 return *this;
119 }
120
121 Array2& operator=(const Array2& o) {
122 size1_ = o.size1_;
123 size2_ = o.size2_;
124 m2_ = o.m2_;
125 m3_ = o.m3_;
126 data_ = o.data_;
127 return *this;
128 }
129
130 size_t size1() const { return size1_; }
131
132 size_t size2() const { return size2_; }
133
134 size_t msize1() const { return 1; }
135
136 size_t msize2() const { return m2_; }
137
138 size_t msize3() const { return m3_; }
139
140 size_t esize() const { return m3_; }
141
142 void resize(size_t size1, size_t size2, const T& t = T()) {
143 size1_ = size1;
144 size2_ = size2;
145 m2_ = size1_;
146 m3_ = m2_ * size2_;
147 data_.resize(m3_, t);
148 }
149
150 size_t index(size_t i1, size_t i2) const { return i1 * m2_ + i2; }
151
152 const T& operator()(size_t i1, size_t i2) const { return data_[index(i1, i2)]; }
153
154 T& operator()(size_t i1, size_t i2) { return data_[index(i1, i2)]; }
155
156 const T& operator[](size_t i) const { return data_[i]; }
157
158 T& operator[](size_t i) { return data_[i]; }
159
160private:
161 size_t size1_;
162 size_t size2_;
163 size_t m2_;
164 size_t m3_;
165 std::vector<T> data_;
166};
167
168struct DofScalar {
169 size_t ndof;
170 bool first;
171 bool second;
172 double d0; // value
173 std::vector<double> d1; // first derivatives
174 Array2<double> d2; // second derivatives
175
176 DofScalar() : ndof(0), first(false), second(false), d0(0.) {}
177
178 DofScalar(const size_t ndof_, const bool first_, const bool second_)
179 : ndof(ndof_),
180 first(first_),
181 second(second_),
182 d0(0.),
183 d1((first ? ndof : 0), 0.),
184 d2((second ? ndof : 0), (second ? ndof : 0), 0.) {}
185
186 void resize(const size_t ndof_, const bool first_, const bool second_) {
187 first = first_;
188 second = second_;
189 d1.resize((first ? ndof_ : 0), 0.);
190 d2.resize((second ? ndof_ : 0), (second ? ndof_ : 0), 0.);
191 ndof = ndof_;
192 }
193
194 size_t size() const { return ndof; }
195
196 DofScalar& set_zero() {
197 d0 = 0.;
198 if (first) { std::fill(d1.begin(), d1.end(), 0); }
199 if (second) { d2.set_zero(); }
200 return *this;
201 }
202
203 DofScalar& operator*=(const double o) {
204 d0 *= o;
205 for (size_t i = 0; i != d1.size(); ++i) { d1[i] *= o; }
206 for (size_t i = 0; i != d2.esize(); ++i) { d2[i] *= o; }
207 return *this;
208 }
209
210 DofScalar& operator+=(const DofScalar& o) {
211 assert(size() == o.size());
212 d0 += o.d0;
213 if (first && o.first) {
214 assert(d1.size() == o.d1.size());
215 for (size_t i = 0; i != d1.size(); ++i) { d1[i] += o.d1[i]; }
216 }
217 if (second && o.second) {
218 assert(d2.esize() == o.d2.esize());
219 for (size_t i = 0; i != d2.esize(); ++i) { d2[i] += o.d2[i]; }
220 }
221 return *this;
222 }
223
224 DofScalar& assign(const DofScalar& o) {
225 assert(ndof == o.ndof);
226 d0 = o.d0;
227 if (first && o.first) {
228 assert(d1.size() == o.d1.size());
229 for (size_t i = 0; i != d1.size(); ++i) { d1[i] = o.d1[i]; }
230 } else if (first) {
231 std::fill(d1.begin(), d1.end(), 0);
232 }
233 if (second && o.second) {
234 assert(d2.esize() == o.d2.esize());
235 for (size_t i = 0; i != d2.esize(); ++i) { d2[i] = o.d2[i]; }
236 } else if (second) {
237 d2.set_zero();
238 }
239 return *this;
240 }
241
242 DofScalar& muladd(const DofScalar& o, const double f) {
243 assert(ndof == o.ndof);
244 d0 += o.d0 * f;
245 if (first && o.first) {
246 assert(d1.size() == o.d1.size());
247 for (size_t i = 0; i != d1.size(); ++i) { d1[i] += f * o.d1[i]; }
248 }
249 if (second && o.second) {
250 assert(d2.esize() == o.d2.esize());
251 for (size_t i = 0; i != d2.esize(); ++i) { d2[i] += f * o.d2[i]; }
252 }
253 return *this;
254 }
255
256 DofScalar& add_at_offset(const size_t offset, const DofScalar& o) {
257 if (ndof < offset + o.ndof) { resize(offset + o.ndof, first, second); }
258 d0 += o.d0;
259 for (size_t k = 0; k != o.ndof; ++k) { d1[offset + k] = o.d1[k]; }
260 for (size_t k = 0; k != o.ndof; ++k) {
261 for (size_t l = 0; l <= k; ++l) { d2(offset + k, offset + l) = o.d2(k, l); }
262 }
263 return *this;
264 }
265};
266
267//
268// Vector quantities with derivatives by the dof (up to 2x).
269//
270template <int NUMD>
271struct DofVector {
272 DofScalar e[NUMD];
273
274 DofVector() {}
275
276 DofVector(const size_t ndof, const bool first, const bool second) {
277 resize(ndof, first, second);
278 }
279
280 void resize(const size_t ndof, const bool first, const bool second) {
281 for (int j = 0; j != NUMD; ++j) { e[j].resize(ndof, first, second); }
282 }
283
284 size_t size() const { return e[0].size(); }
285
286 DofVector& set_zero() {
287 for (int j = 0; j != NUMD; ++j) { e[j].set_zero(); }
288 return *this;
289 }
290
291 const DofScalar& operator[](const size_t i) const { return e[i]; }
292
293 DofScalar& operator[](const size_t i) { return e[i]; }
294
295 DofVector& operator*=(const double o) {
296 for (int j = 0; j != NUMD; ++j) { e[j] *= o; }
297 return *this;
298 }
299
300 DofVector& operator+=(const DofVector& o) {
301 for (int j = 0; j != NUMD; ++j) { e[j] += o[j]; }
302 return *this;
303 }
304
305 DofVector& add_at_offset(const size_t offset, const DofVector& o) {
306 for (int j = 0; j != NUMD; ++j) { e[j].add_at_offset(offset, o[j]); }
307 return *this;
308 }
309};
310
311//
312// Matrix (3x3) quantities with derivatives by the dof (up to 2x).
313//
314struct DofMatrix {
315 DofVector<3> e[3];
316
317 DofMatrix() {}
318
319 DofMatrix(const size_t ndof, const bool first, const bool second) {
320 resize(ndof, first, second);
321 }
322
323 void resize(const size_t ndof, const bool first, const bool second) {
324 for (int j = 0; j != 3; ++j) { e[j].resize(ndof, first, second); }
325 }
326
327 size_t size() const { return e[0].size(); }
328
329 DofMatrix& set_zero() {
330 for (int j = 0; j != 3; ++j) { e[j].set_zero(); }
331 return *this;
332 }
333
334 const DofVector<3>& operator[](const size_t i) const { return e[i]; }
335
336 DofVector<3>& operator[](const size_t i) { return e[i]; }
337
338 DofMatrix& operator*=(const double o) {
339 for (int j = 0; j != 3; ++j) { e[j] *= o; }
340 return *this;
341 }
342
343 DofMatrix& operator+=(const DofMatrix& o) {
344 for (int j = 0; j != 3; ++j) { e[j] += o[j]; }
345 return *this;
346 }
347
348 DofMatrix& add_at_offset(const size_t offset, const DofMatrix& o) {
349 for (int j = 0; j != 3; ++j) { e[j].add_at_offset(offset, o[j]); }
350 return *this;
351 }
352};
353
354// Indices for derivatives by the element-local system directions.
355const int d00 = 0;
356const int d10 = 1;
357const int d01 = 2;
358const int d20 = 3;
359const int d11 = 4;
360const int d02 = 5;
361const int d30 = 6;
362const int d21 = 7;
363const int d12 = 8;
364const int d03 = 9;
365
366//
367// Scalar quantities with derivatives by the element-local system
368// directions (up to 3x), and derivatives by the dof (up to 2x).
369//
370template <int NUMD>
371struct ScalarXiDof {
372 DofScalar e[NUMD];
373
374 ScalarXiDof() {}
375
376 ScalarXiDof(const size_t ndof, const bool first, const bool second) {
377 resize(ndof, first, second);
378 }
379
380 void resize(const size_t ndof, const bool first, const bool second) {
381 for (int i = 0; i != NUMD; ++i) { e[i].resize(ndof, first, second); }
382 }
383
384 size_t size() const { return e[0].size(); }
385
386 ScalarXiDof& set_zero() {
387 for (int i = 0; i != NUMD; ++i) { e[i].set_zero(); }
388 return *this;
389 }
390
391 const DofScalar& operator[](const size_t i) const {
392 // assert(i < NUMD);
393 return e[i];
394 }
395
396 DofScalar& operator[](const size_t i) {
397 // assert(i < NUMD);
398 return e[i];
399 }
400
401 ScalarXiDof& operator*=(const double o) {
402 for (int i = 0; i != NUMD; ++i) { e[i] *= o; }
403 return *this;
404 }
405
406 ScalarXiDof& operator+=(const ScalarXiDof& o) {
407 for (int i = 0; i != NUMD; ++i) { e[i] += o[i]; }
408 return *this;
409 }
410
411 ScalarXiDof& muladd(const ScalarXiDof& o, const double f) {
412 for (int i = 0; i != NUMD; ++i) { e[i].muladd(o[i], f); }
413 return *this;
414 }
415
416 ScalarXiDof& add_at_offset(const size_t offset, const ScalarXiDof& o) {
417 for (int i = 0; i != NUMD; ++i) { e[i].add_at_offset(offset, o[i]); }
418 return *this;
419 }
420};
421
422//
423// Vector quantities with derivatives by the element-local system
424// directions (up to 3x), and derivatives by the dof (up to 2x).
425//
426template <int NUMD>
427struct VectorXiDof {
428 ScalarXiDof<NUMD> e[3];
429
430 VectorXiDof() {}
431
432 VectorXiDof(const size_t ndof, const bool first, const bool second) {
433 resize(ndof, first, second);
434 }
435
436 void resize(const size_t ndof, const bool first, const bool second) {
437 for (int j = 0; j != 3; ++j) { e[j].resize(ndof, first, second); }
438 }
439
440 size_t size() const { return e[0].size(); }
441
442 VectorXiDof& set_zero() {
443 for (int j = 0; j != 3; ++j) { e[j].set_zero(); }
444 return *this;
445 }
446
447 const ScalarXiDof<NUMD>& operator[](const size_t i) const {
448 // assert(i < 3);
449 return e[i];
450 }
451
452 ScalarXiDof<NUMD>& operator[](const size_t i) {
453 // assert(i < 3);
454 return e[i];
455 }
456
457 VectorXiDof& operator*=(const double o) {
458 for (int j = 0; j != 3; ++j) { e[j] *= o; }
459 return *this;
460 }
461
462 VectorXiDof& operator+=(const VectorXiDof& o) {
463 for (int j = 0; j != 3; ++j) { e[j] += o[j]; }
464 return *this;
465 }
466
467 VectorXiDof& add_at_offset(const size_t offset, const VectorXiDof& o) {
468 for (int j = 0; j != 3; ++j) { e[j].add_at_offset(offset, o[j]); }
469 return *this;
470 }
471};
472
473//
474// Matrix (3x3) quantities with derivatives by the element-local
475// system directions (up to 3x), and derivatives by the dof (up to
476// 2x).
477//
478template <int NUMD>
479struct MatrixXiDof {
480 VectorXiDof<NUMD> e[3];
481
482 MatrixXiDof() {}
483
484 MatrixXiDof(const size_t ndof, const bool first, const bool second) {
485 resize(ndof, first, second);
486 }
487
488 void resize(const size_t ndof, const bool first, const bool second) {
489 for (int j = 0; j != 3; ++j) { e[j].resize(ndof, first, second); }
490 }
491
492 size_t size() const { return e[0].size(); }
493
494 MatrixXiDof& set_zero() {
495 for (int j = 0; j != 3; ++j) { e[j].set_zero(); }
496 return *this;
497 }
498
499 const VectorXiDof<NUMD>& operator[](const size_t i) const { return e[i]; }
500
501 VectorXiDof<NUMD>& operator[](const size_t i) { return e[i]; }
502
503 MatrixXiDof& operator*=(const double o) {
504 for (int j = 0; j != 3; ++j) { e[j] *= o; }
505 return *this;
506 }
507
508 MatrixXiDof& operator+=(const MatrixXiDof& o) {
509 for (int j = 0; j != 3; ++j) { e[j] += o[j]; }
510 return *this;
511 }
512
513 MatrixXiDof& add_at_offset(const size_t offset, const MatrixXiDof& o) {
514 for (int j = 0; j != 3; ++j) { e[j].add_at_offset(offset, o[j]); }
515 return *this;
516 }
517};
518
519typedef Vec3<double> Vec3d;
520
521//
522// Value and up to 2nd derivatives of 3d vectors.
523//
524struct DofVec3d {
525 size_t ndof;
526 bool first;
527 bool second;
528 Vec3d d0; // value
529 std::vector<Vec3d> d1; // first derivatives
530 Array2<Vec3d> d2; // second derivatives
531
532 DofVec3d() : ndof(0), first(false), second(false) {}
533
534 DofVec3d(const size_t ndof_, const bool first_, const bool second_)
535 : ndof(ndof_),
536 first(first_),
537 second(second_),
538 d1((first ? ndof : 0), Vec3d()),
539 d2((second ? ndof : 0), (second ? ndof : 0), Vec3d()) {}
540
541 void resize(const size_t ndof_, const bool first_, const bool second_) {
542 first = first_;
543 second = second_;
544 d1.resize((first ? ndof_ : 0), Vec3d());
545 d2.resize((second ? ndof_ : 0), (second ? ndof_ : 0), Vec3d());
546 ndof = ndof_;
547 }
548
549 size_t size() const { return ndof; }
550
551 DofVec3d& set_zero() {
552 d0 = Vec3d();
553 if (first) { std::fill(d1.begin(), d1.end(), Vec3d()); }
554 if (second) { d2.set_zero(); }
555 return *this;
556 }
557
558 DofVec3d& operator*=(const double o) {
559 d0 *= o;
560 for (size_t i = 0; i != d1.size(); ++i) { d1[i] *= o; }
561 for (size_t i = 0; i != d2.esize(); ++i) { d2[i] *= o; }
562 return *this;
563 }
564
565 DofVec3d& operator+=(const DofVec3d& o) {
566 assert(size() == o.size());
567 d0 += o.d0;
568 if (first && o.first) {
569 assert(d1.size() == o.d1.size());
570 for (size_t i = 0; i != d1.size(); ++i) { d1[i] += o.d1[i]; }
571 }
572 if (second && o.second) {
573 assert(d2.esize() == o.d2.esize());
574 for (size_t i = 0; i != d2.esize(); ++i) { d2[i] += o.d2[i]; }
575 }
576 return *this;
577 }
578
579 DofVec3d& assign(const DofVec3d& o) {
580 assert(ndof == o.ndof);
581 d0 = o.d0;
582 if (first && o.first) {
583 assert(d1.size() == o.d1.size());
584 for (size_t i = 0; i != d1.size(); ++i) { d1[i] = o.d1[i]; }
585 } else if (first) {
586 for (size_t i = 0; i != d1.size(); ++i) { d1[i].set_zero(); }
587 }
588 if (second && o.second) {
589 assert(d2.esize() == o.d2.esize());
590 for (size_t i = 0; i != d2.esize(); ++i) { d2[i] = o.d2[i]; }
591 } else if (second) {
592 d2.set_zero();
593 }
594 return *this;
595 }
596
597 DofVec3d& muladd(const DofVec3d& o, const double f) {
598 assert(ndof == o.ndof);
599 d0 += o.d0 * f;
600 if (first && o.first) {
601 assert(d1.size() == o.d1.size());
602 for (size_t i = 0; i != d1.size(); ++i) { d1[i] += f * o.d1[i]; }
603 }
604 if (second && o.second) {
605 assert(d2.esize() == o.d2.esize());
606 for (size_t i = 0; i != d2.esize(); ++i) { d2[i] += f * o.d2[i]; }
607 }
608 return *this;
609 }
610};
611
612//
613// Vec3 quantities with derivatives by the element-local system
614// directions (up to 3x), and derivatives by the dof (up to 2x).
615//
616template <int NUMD>
617struct XiDofVec3d {
618 DofVec3d e[NUMD];
619
620 XiDofVec3d() {}
621
622 XiDofVec3d(const size_t ndof, const bool first, const bool second) {
623 resize(ndof, first, second);
624 }
625
626 void resize(const size_t ndof, const bool first, const bool second) {
627 for (int i = 0; i != NUMD; ++i) { e[i].resize(ndof, first, second); }
628 }
629
630 size_t size() const { return e[0].size(); }
631
632 XiDofVec3d& set_zero() {
633 for (int i = 0; i != NUMD; ++i) { e[i].set_zero(); }
634 return *this;
635 }
636
637 const DofVec3d& operator[](const size_t i) const {
638 // assert(i < NUMD);
639 return e[i];
640 }
641
642 DofVec3d& operator[](const size_t i) {
643 // assert(i < NUMD);
644 return e[i];
645 }
646
647 XiDofVec3d& operator*=(const double o) {
648 for (int i = 0; i != NUMD; ++i) { e[i] *= o; }
649 return *this;
650 }
651
652 XiDofVec3d& operator+=(const XiDofVec3d& o) {
653 for (int i = 0; i != NUMD; ++i) { e[i] += o[i]; }
654 return *this;
655 }
656
657 XiDofVec3d& muladd(const XiDofVec3d& o, const double f) {
658 for (int i = 0; i != NUMD; ++i) { e[i].muladd(o[i], f); }
659 return *this;
660 }
661
662 XiDofVec3d& add_at_offset(const size_t offset, const XiDofVec3d& o) {
663 for (int i = 0; i != NUMD; ++i) { e[i].add_at_offset(offset, o[i]); }
664 return *this;
665 }
666};
667
668} // namespace b2000::klt
669
670#endif // B2_ELEMENT_KLT_UTIL_H_