b2api
B2000++ API Reference Manual, VERSION 4.6
 
Loading...
Searching...
No Matches
b2beam_cross_section_solver.H
1//------------------------------------------------------------------------
2// b2beam_cross_section_solver.H --
3//
4// written by Mathias Doreille
5// Neda Ebrahimi Pour <neda.ebrahimipour@dlr.de>
6// Thomas Blome <thomas.blome@dlr.de>
7//
8// (c) 2011-2012,2016 SMR Engineering & Development SA
9// 2502 Bienne, Switzerland
10//
11// (c) 2023 Deutsches Zentrum für Luft- und Raumfahrt (DLR) e.V.
12// Linder Höhe, 51147 Köln
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 B2BEAM_CROSS_SECTION_SOLVER_H_
21#define B2BEAM_CROSS_SECTION_SOLVER_H_
22
23// #undef DEBUG
24
25#include "b2blaslapack.H"
26#include "b2ppconfig.h"
27#include "elements/smr/b2element_beam_cross_section.H"
29#include "model/b2domain.H"
30#include "model/b2element.H"
31#include "model/b2model.H"
32#include "model/b2node.H"
33#include "model/b2solution.H"
34#include "model/b2solver.H"
35#include "utils/b2logging.H"
36#include "utils/b2object.H"
38#include "utils/b2util.H"
39
40namespace b2000::solver {
41
42// Reference:
43// On the structural behavior and the Saint Venant solution in the exact beam theory:
44// Application to laminated composite beams
45// Rached El Fatmi and Hatem Zenzri
46// Computers and Structures 80 (2002) 1441-1456
47
48// #define BCSC_ORIG_BC
49// #define BCSC_V1
50
51class BeamCrossSectionSolver : public Solver {
52public:
53 using mrbc_t = TypedModelReductionBoundaryCondition<double>;
54 using type_t = ObjectTypeComplete<BeamCrossSectionSolver, Solver::type_t>;
55
56 void solve() override {
57 while (solve_iteration()) { ; }
58 }
59
60 bool solve_iteration() override {
61 logging::Logger& logger = logging::get_logger("solver.beam_cross_section");
62 if (model_ == nullptr) { Exception() << THROW; }
63 if (case_iterator_.get() == nullptr) {
64 case_iterator_ = model_->get_case_list().get_case_iterator();
65 }
66 case_ = case_iterator_->next();
67 if (!case_) { return false; }
68
69 if (case_->get_stage_size() != 1.0) {
70 logging::get_logger("solver.beam_cross_section")
71 << logging::warning << "The stage size of the case " << case_->get_id()
72 << " is equal to " << case_->get_stage_size()
73 << " but the beam cross section solver only handle a case with one stage of size "
74 "equal to one. The specified stage size is ignored."
75 << logging::LOGFLUSH;
76 }
77 if (case_->get_number_of_stage() != 1) {
78 logging::get_logger("solver.beam_cross_section")
79 << logging::warning << "The number of stage of the case" << case_->get_id()
80 << " is " << case_->get_stage_size()
81 << " but the beam cross section solver only handle a case with one stage of size "
82 "equal to one. The extra stages are ignored."
83 << logging::LOGFLUSH;
84 }
85
87 Domain& domain = model_->get_domain();
88 SolutionBeamCrossSection* solution =
89 &dynamic_cast<SolutionBeamCrossSection&>(model_->get_solution());
90 if (solution == nullptr) {
91 TypeError() << "The solver only accept a solution of type SolutionBeamCrossSection"
92 << THROW;
93 }
94
95 const size_t number_of_dof = domain.get_number_of_dof();
96
97 // Get the model reduction (x = R * x_r + r)
98 mrbc_t* mrbc = &dynamic_cast<mrbc_t&>(
99 model_->get_model_reduction_boundary_condition(mrbc_t::type.get_subtype(
100 "TypedModelReductionBoundaryConditionListComponent" + type_name<double>())));
101 b2linalg::Vector<double, b2linalg::Vdense> r(number_of_dof);
102 b2linalg::Matrix<double, b2linalg::Mcompressed_col> trans_R;
103 mrbc->get_linear_value(r, trans_R);
104
105 {
106 // Add constraint to obtain a determined system
107 // first find two nodes with different coordinate.
108
109 Node* n1 = nullptr;
110 bool n1_lookdof1 = false;
111 std::pair<int, const double*> coor1;
112 {
113 Domain::node_iterator i = domain.get_node_iterator();
114 for (Node* n = i->next(); n != nullptr; n = i->next()) {
115 coor1 = n->get_coor<double>();
116 if (coor1.first == 3 && trans_R.get_nb_nonzero(coor1.second[0]) == 0) {
117 n1 = n;
118 n1_lookdof1 = true;
119 break;
120 }
121 }
122 }
123 if (n1 == nullptr) {
124 Domain::node_iterator i = domain.get_node_iterator();
125 for (Node* n = i->next(); n != nullptr; n = i->next()) {
126 coor1 = n->get_coor<double>();
127 if (coor1.first == 3) {
128 n1 = n;
129 break;
130 }
131 }
132 }
133 if (n1 == nullptr) { Exception() << THROW; }
134 Node* n2 = nullptr;
135 double dist = 0;
136 {
137 Domain::node_iterator i = domain.get_node_iterator();
138 for (Node* n = i->next(); n != nullptr; n = i->next()) {
139 std::pair<int, const double*> coor2 = n->get_coor<double>();
140 if (coor2.first == 3) {
141 double tmp[3];
142 sub_3(coor1.second, coor2.second, tmp);
143 double dtmp = dot_3(tmp, tmp);
144 if (dtmp > dist) {
145 dist = dtmp;
146 n2 = n;
147 }
148 }
149 }
150 }
151 if (n2 == nullptr) { Exception() << THROW; }
152
153 b2linalg::Index ind(5);
154 n2->get_global_dof_numbering(&ind[2]);
155 n1->get_global_dof_numbering(&ind[0]);
156 if (n1_lookdof1) { ind.erase(ind.begin()); }
157
158 std::set<size_t> col_to_remove;
159 for (size_t i = 0; i != ind.size(); ++i) {
160 size_t* rowind;
161 double* value;
162 const size_t nbz = trans_R.get_col_value(ind[i], rowind, value);
163 if (nbz == 0) { Exception() << THROW; }
164 col_to_remove.insert(rowind, rowind + nbz);
165 }
166 ind.assign(col_to_remove.begin(), col_to_remove.end());
167 trans_R.remove_row(ind);
168 }
169
170 double neutral_point[2];
171 double mass;
172 double inertia_point[2];
173 double inertia_moment[3];
174 b2linalg::Matrix<double> u;
175 b2linalg::Matrix<double> lambda;
176 b2linalg::Vector<double> lambdad;
177 b2linalg::Matrix<double> strain[7];
178 b2linalg::Matrix<double> stress[7];
179
180 solve_static(
181 logger, *case_, model_, domain, trans_R, neutral_point, mass, inertia_point,
182 inertia_moment, u, lambda, lambdad, strain, stress);
183
184 solution->set_solution(
185 neutral_point, mass, inertia_point, inertia_moment, u, strain, stress, lambda,
186 lambdad);
187
188 RTable attributes;
189 solution->terminate_case(true, attributes);
191
192 return true;
193 }
194
195 static void solve_static(
196 logging::Logger& logger, Case& case_, Model* model, Domain& domain,
197 b2linalg::Matrix<double, b2linalg::Mcompressed_col>& trans_R, double neutral_point[2],
198 double& inertia_mass, double inertia_point[2], double inertia_moment[3],
199 b2linalg::Matrix<double>& u, b2linalg::Matrix<double>& lambda,
200 b2linalg::Vector<double>& lambdad, b2linalg::Matrix<double> strain[7],
201 b2linalg::Matrix<double> stress[7]);
202
203 static type_t type;
204};
205
206} // namespace b2000::solver
207
208// #define TEST_WITOUT_SYMMETRISATION
209void b2000::solver::BeamCrossSectionSolver::solve_static(
210 logging::Logger& logger, Case& case_, Model* model, Domain& domain,
211 b2linalg::Matrix<double, b2linalg::Mcompressed_col>& trans_R, double neutral_point[2],
212 double& inertia_mass, double inertia_point[2], double inertia_moment[3],
213 b2linalg::Matrix<double>& u, b2linalg::Matrix<double>& lambda,
214 b2linalg::Vector<double>& lambdad, b2linalg::Matrix<double> strain[7],
215 b2linalg::Matrix<double> stress[7]) {
216 logger << logging::info << "Start the beam cross section solver" << logging::LOGFLUSH;
217
218 const size_t number_of_dof = domain.get_number_of_dof();
219
220 const bool log_el_flag = logger.is_enabled_for(logging::data);
221 logger << logging::info << "Computation of centre, first and second moment of area"
222 << logging::LOGFLUSH;
223
224 neutral_point[0] = neutral_point[1] = 0;
225 inertia_mass = 0;
226 inertia_point[0] = inertia_point[1] = 0;
227 {
228 double area = 0;
229 Domain::element_iterator i = domain.get_element_iterator();
230 for (Element* e = i->next(); e != nullptr; e = i->next()) {
231 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_0(
232 model, area, neutral_point, inertia_mass, inertia_point);
233 }
234 neutral_point[0] /= area;
235 neutral_point[1] /= area;
236 if (inertia_mass > 0) {
237 inertia_point[0] = inertia_point[0] / inertia_mass - neutral_point[0];
238 inertia_point[1] = inertia_point[1] / inertia_mass - neutral_point[1];
239 }
240 }
241
242 double inertia_axis[2][2];
243 {
244 double inertia[3] = {};
245 std::fill_n(inertia_moment, 3, 0);
246 Domain::element_iterator i = domain.get_element_iterator();
247 for (Element* e = i->next(); e != nullptr; e = i->next()) {
248 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_01(
249 model, neutral_point, inertia, inertia_moment);
250 }
251 {
252 double value[2];
253 double m[2][2] = {{inertia[0], inertia[2]}, {inertia[2], inertia[1]}};
254 eigenvector_2(m, value, inertia_axis);
255 normalise_2(inertia_axis[0]);
256 normalise_2(inertia_axis[1]);
257 if (determinant_2_2(inertia_axis) < 0) {
258 for (int j = 0; j != 2; ++j) { inertia_axis[1][j] *= -1; }
259 }
260 }
261 }
262
263 logger << logging::info << "Element matrix assembly" << logging::LOGFLUSH;
264
265 // we add the diagonal one for additional dof
266 for (int i = 0; i != 4; ++i) { trans_R.push_back(trans_R.size1(), trans_R.size2(), 1); }
267
268 size_t K_augm_size = trans_R.size1();
269 b2linalg::Matrix<double, b2linalg::Msym_compressed_col_update_inv> K_augm(
270 K_augm_size, domain.get_dof_connectivity_type(), case_);
271 domain.set_dof(b2linalg::Vector<double, b2linalg::Vdense_constref>::null);
272 {
273 Domain::element_iterator i = domain.get_element_iterator();
274 b2linalg::Index index;
275 b2linalg::Matrix<double, b2linalg::Mpacked> Ke;
276 for (Element* e = i->next(); e != nullptr; e = i->next()) {
277 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_1(
278 model, neutral_point, inertia_axis, number_of_dof, index, Ke);
279 K_augm +=
280 trans_R * StructuredMatrix(number_of_dof + 4, index, Ke) * transposed(trans_R);
281 if (log_el_flag) {
282 b2linalg::Matrix<double> tmp(Ke);
283 logger << logging::data << "elementary second variation "
284 << logging::DBName("ELSV", 0, e->get_object_name()) << tmp
285 << " of element id " << e->get_object_name() << logging::LOGFLUSH;
286 }
287 }
288 }
289
290 logger << logging::info << "First system resolution" << logging::LOGFLUSH;
291
292 b2linalg::Matrix<double> v(number_of_dof + 4, 6);
293 lambda.resize(6, 6);
294 {
295 b2linalg::Matrix<double> v_augm(K_augm.size1(), 4);
296 for (int i = 0; i != 4; ++i) { v_augm(K_augm.size1() - 4 + i, i) = 1; }
297 v_augm = b2linalg::inverse(K_augm) * v_augm;
298 v(b2linalg::Interval(2, 6)) = transposed(trans_R) * v_augm;
299 v[0] = v[2];
300 }
301 for (int j = 0; j != 4; ++j) {
302 const int jj = j == 0 ? 0 : j + 2;
303 for (int i = 0; i != 4; ++i) {
304 const int ii = i == 0 ? 0 : i + 2;
305#ifdef TEST_WITOUT_SYMMETRISATION
306 lambda(ii, jj) = v(number_of_dof + i, jj);
307#else
308 lambda(ii, jj) = 0.5 * (v(number_of_dof + i, jj) + v(number_of_dof + j, ii));
309#endif
310 }
311 }
312
313 logger << logging::info << "Factorisation and first computation of beta" << logging::LOGFLUSH;
314
315 b2float128 beta[6][6] = {};
316 {
317 const bool beta_cd[6][6] = {{1, 0, 0, 1, 1, 1}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
318 {1, 0, 0, 1, 1, 1}, {1, 0, 0, 1, 1, 1}, {1, 0, 0, 1, 1, 1}};
319 const int beta_c[] = {0, 3, 4, 5};
320 const int beta_d[] = {0, 3, 4, 5};
321 Domain::element_iterator i = domain.get_element_iterator();
322 for (Element* e = i->next(); e != nullptr; e = i->next()) {
323 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_2(
324 model, neutral_point, inertia_axis, v, lambda, beta_cd, 4, beta_c, 4, beta_d,
325 beta);
326 }
327 }
328 for (int j = 0; j != 4; ++j) {
329 const int jj = j == 0 ? 0 : j + 2;
330#ifdef TEST_WITOUT_SYMMETRISATION
331 lambda(1, jj) = beta[jj][5];
332 lambda(2, jj) = -beta[jj][4];
333#else
334 lambda(1, jj) = lambda(jj, 1) = beta[jj][5];
335 lambda(2, jj) = lambda(jj, 2) = -beta[jj][4];
336#endif
337 }
338
339 logger << logging::info << "Second system resolution" << logging::LOGFLUSH;
340 {
341 b2linalg::Matrix<double> u(number_of_dof + 4, 2);
342 Domain::element_iterator i = domain.get_element_iterator();
343 for (Element* e = i->next(); e != nullptr; e = i->next()) {
344 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_3(
345 model, neutral_point, inertia_axis, number_of_dof, v, lambda, beta, u);
346 }
347
348 b2linalg::Matrix<double> u_augm;
349 u_augm = trans_R * u;
350 u_augm = b2linalg::inverse(K_augm) * u_augm;
351 v(b2linalg::Interval(1, 3)) = transposed(trans_R) * u_augm;
352 }
353 for (int j = 1; j != 3; ++j) {
354 for (int i = 0; i != 4; ++i) {
355 const int ii = i == 0 ? 0 : i + 2;
356#ifdef TEST_WITOUT_SYMMETRISATION
357 lambda(ii, j) = v(number_of_dof + i, j);
358#else
359 lambda(ii, j) = 0.5 * (lambda(ii, j) + v(number_of_dof + i, j));
360 lambda(j, ii) = 0.5 * (lambda(j, ii) + v(number_of_dof + i, j));
361#endif
362 }
363 }
364
365 // computation of u from v
366 u.resize(number_of_dof, 7);
367 for (int i = 0; i != 6; ++i) {
368 const double tmp1[3] = {double(beta[i][0]), double(beta[i][1]), double(beta[i][2])};
369 double tmp2[3] = {double(beta[i][3]), double(beta[i][4]), double(beta[i][5])};
370
371 Domain::node_iterator iter = domain.get_node_iterator();
372 for (Node* n = iter->next(); n != nullptr; n = iter->next()) {
373 double tmp3[3];
374 const double* ptr = n->get_coor<double>().second;
375 const double tmp4[3] = {0, ptr[1] - neutral_point[0], ptr[2] - neutral_point[1]};
376 outer_product_3(tmp2, tmp4, tmp3);
377 const size_t pos = n->get_global_dof_numbering().first;
378 for (int ii = 0; ii != 3; ++ii) {
379 u(pos + ii, i) = v(pos + ii, i) + tmp1[ii] + tmp3[ii];
380 }
381 }
382 }
383
384 logger << logging::info << "Second computation of beta" << logging::LOGFLUSH;
385 {
386 const bool beta_cd[6][6] = {{0, 1, 1, 0, 0, 0}, {1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1},
387 {0, 1, 1, 0, 0, 0}, {0, 1, 1, 0, 0, 0}, {0, 1, 1, 0, 0, 0}};
388 const int beta_c[] = {0, 1, 2, 3, 4, 5};
389 const int beta_d[] = {0, 1, 2, 3, 4, 5};
390 Domain::element_iterator i = domain.get_element_iterator();
391 for (Element* e = i->next(); e != nullptr; e = i->next()) {
392 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_2(
393 model, neutral_point, inertia_axis, v, lambda, beta_cd, 6, beta_c, 6, beta_d,
394 beta);
395 }
396 }
397 lambda(1, 1) = beta[5][1] + beta[1][5];
398 lambda(2, 1) = beta[5][2] - beta[1][4];
399 lambda(1, 2) = -beta[4][1] + beta[2][5];
400 lambda(2, 2) = -beta[4][2] - beta[2][4];
401#ifndef TEST_WITOUT_SYMMETRISATION
402 lambda(2, 1) = 0.5 * (lambda(2, 1) + lambda(1, 2));
403 lambda(1, 2) = lambda(2, 1);
404#endif
405
406 logger << logging::info << "Strain and stress computation" << logging::LOGFLUSH;
407
408 const size_t number_of_node = domain.get_number_of_nodes();
409 {
410 for (int i = 0; i != 7; ++i) {
411 strain[i].resize(6, number_of_node);
412 stress[i].resize(3, number_of_node);
413 }
414 }
415
416 std::vector<size_t> node_weight(number_of_dof);
417 std::vector<std::pair<const Node*, const Node*> > slave_nodes;
418 domain.get_slave_node(slave_nodes);
419 {
420 Domain::element_iterator i = domain.get_element_iterator();
421 for (Element* e = i->next(); e != nullptr; e = i->next()) {
422 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_4(
423 model, neutral_point, inertia_axis, v, lambda, beta, node_weight, strain, stress);
424 }
425
426 for (size_t ptr = 0; ptr != slave_nodes.size(); ++ptr) {
427 const size_t sn = slave_nodes[ptr].first->get_id();
428 const size_t mn = slave_nodes[ptr].second->get_id();
429 node_weight[mn] += node_weight[sn];
430 for (int i = 0; i != 6; ++i) {
431 for (int j = 0; j != 6; ++j) { strain[i](j, mn) += strain[i](j, sn); }
432 for (int j = 0; j != 3; ++j) { stress[i](j, mn) += stress[i](j, sn); }
433 }
434 }
435
436 for (size_t k = 0; k != number_of_node; ++k) {
437 const double s = 1.0 / node_weight[k];
438 for (int i = 0; i != 6; ++i) {
439 for (int j = 0; j != 6; ++j) { strain[i](j, k) *= s; }
440 for (int j = 0; j != 3; ++j) { stress[i](j, k) *= s; }
441 }
442 }
443
444 for (size_t ptr = 0; ptr != slave_nodes.size(); ++ptr) {
445 const size_t sn = slave_nodes[ptr].first->get_id();
446 const size_t mn = slave_nodes[ptr].second->get_id();
447 for (int i = 0; i != 6; ++i) {
448 for (int j = 0; j != 6; ++j) { strain[i](j, sn) = strain[i](j, mn); }
449 for (int j = 0; j != 3; ++j) { stress[i](j, sn) = stress[i](j, mn); }
450 }
451 }
452 }
453
454 logger << logging::info << "Computation of f due to the initial stress and bc"
455 << logging::LOGFLUSH;
456 double f[6];
457 std::fill_n(f, 6, 0);
458 {
459 Domain::element_iterator i = domain.get_element_iterator();
460 for (Element* e = i->next(); e != nullptr; e = i->next()) {
461 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_5(
462 model, neutral_point, inertia_axis, f);
463 }
464 }
465
466 b2linalg::Vector<double> vd(trans_R.size2());
467#ifdef BCSC_V1
468 logger << logging::info << "Third system resolution due to initial stress and bc"
469 << logging::LOGFLUSH;
470 {
471 b2linalg::Vector<double> value(number_of_dof + 4);
472 Domain::element_iterator i = domain.get_element_iterator();
473 for (Element* e = i->next(); e != 0; e = i->next()) {
474 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_6(
475 model, neutral_point, inertia_axis, number_of_dof, f, u, stress, value);
476 }
477#ifdef BCSC_ORIG_BC
478 b2linalg::Vector<double> u_augm;
479 u_augm = trans_R * value;
480 u_augm = b2linalg::inverse(K_augm) * u_augm;
481 vd = transposed(trans_R) * u_augm;
482
483 lambdad.resize(6);
484 lambdad[0] = vd[number_of_dof];
485 for (int i = 1; i != 4; ++i) { lambdad[i + 2] = vd[number_of_dof + i]; }
486#else
487 b2linalg::Matrix<double> u_augm(trans_R.size1(), 5);
488 u_augm[4] = trans_R * value;
489 for (int i = 0; i != 4; ++i) { u_augm(trans_R.size1() - 4 + i, i) = 1; }
490 u_augm = b2linalg::inverse(K_augm) * u_augm;
491
492 b2linalg::Vector<double> lm;
493 b2linalg::Interval int1(K_augm.size1() - 4, K_augm.size1());
494 // lm = b2linalg::inverse(u_augm(int1, b2linalg::Interval(0, 4))) * u_augm[4](int1);
495 {
496 int ipiv[4];
497 int info;
498 lm = u_augm[4](int1);
499 lapack::gesv(
500 4, 1, &u_augm(K_augm.size1() - 4, 0), u_augm.size1(), ipiv, &lm[0], 4, info);
501 if (info != 0) { Exception() << THROW; }
502 }
503
504 u_augm[4] = trans_R * value;
505 u_augm[4](int1) -= lm;
506 {
507 b2linalg::Vector<double> tmp;
508 tmp = b2linalg::inverse(K_augm) * u_augm[4];
509 vd = transposed(trans_R) * tmp;
510 }
511
512 lambdad.resize(6);
513 lambdad[0] = lm[0];
514 for (int i = 1; i != 4; ++i) { lambdad[i + 2] = lm[i]; }
515#endif
516 }
517#else
518 lambdad.resize(6);
519 for (int i = 0; i != 6; ++i) { lambdad[i] = f[i]; }
520#endif
521
522 logger << logging::info << "Strain and stress computation due to initial stress and bc"
523 << logging::LOGFLUSH;
524 {
525 b2linalg::Vector<double> value;
526 Domain::element_iterator i = domain.get_element_iterator();
527 for (Element* e = i->next(); e != nullptr; e = i->next()) {
528 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_7(
529 model, neutral_point, inertia_axis, f, u, vd,
530 vd(b2linalg::Interval(number_of_dof, number_of_dof + 4)), strain[6], stress[6]);
531 }
532
533 for (size_t ptr = 0; ptr != slave_nodes.size(); ++ptr) {
534 const size_t sn = slave_nodes[ptr].first->get_id();
535 const size_t mn = slave_nodes[ptr].second->get_id();
536 for (int j = 0; j != 6; ++j) { strain[6](j, mn) += strain[6](j, sn); }
537 for (int j = 0; j != 3; ++j) { stress[6](j, mn) += stress[6](j, sn); }
538 }
539
540 for (size_t k = 0; k != number_of_node; ++k) {
541 const double s = 1.0 / node_weight[k];
542 for (int j = 0; j != 6; ++j) { strain[6](j, k) *= s; }
543 for (int j = 0; j != 3; ++j) { stress[6](j, k) *= s; }
544 }
545
546 for (size_t ptr = 0; ptr != slave_nodes.size(); ++ptr) {
547 const size_t sn = slave_nodes[ptr].first->get_id();
548 const size_t mn = slave_nodes[ptr].second->get_id();
549 for (int i = 0; i != 6; ++i) {
550 for (int j = 0; j != 6; ++j) { strain[6](j, sn) = strain[6](j, mn); }
551 for (int j = 0; j != 3; ++j) { stress[6](j, sn) = stress[6](j, mn); }
552 }
553 }
554 }
555
556#ifdef BCSC_V1
557 logger << logging::info << "beta computation due to initial stress and bc" << logging::LOGFLUSH;
558 {
559 double betad[6];
560 std::fill_n(betad, 6, 0);
561 Domain::element_iterator i = domain.get_element_iterator();
562 for (Element* e = i->next(); e != 0; e = i->next()) {
563 static_cast<BeamCrossSectionBaseElement&>(*e).add_value_8(
564 model, neutral_point, inertia_axis, u, vd, stress, stress[6], betad);
565 }
566 lambdad[1] = betad[5];
567 lambdad[2] = -betad[4];
568
569 // computation of ud from vd
570 const double tmp1[3] = {betad[0], betad[1], betad[2]};
571 double tmp2[3] = {betad[3], betad[4], betad[5]};
572
573 Domain::node_iterator iter = domain.get_node_iterator();
574 for (Node* n = iter->next(); n != 0; n = iter->next()) {
575 double tmp3[3];
576 const double* ptr = n->get_coor<double>().second;
577 const double tmp4[3] = {0, ptr[1] - neutral_point[0], ptr[2] - neutral_point[1]};
578 outer_product_3(tmp2, tmp4, tmp3);
579 const size_t pos = n->get_global_dof_numbering().first;
580 for (int ii = 0; ii != 3; ++ii) { u(pos + ii, 6) = vd[pos + ii] + tmp1[ii] + tmp3[ii]; }
581 }
582 }
583#endif
584
585 // update u in function of the inertia axis
586 {
587 for (int i = 0; i != 7; ++i) {
588 Domain::node_iterator iter = domain.get_node_iterator();
589 for (Node* n = iter->next(); n != nullptr; n = iter->next()) {
590 const size_t pos = n->get_global_dof_numbering().first;
591 const double tmp[2] = {u(pos + 1, i), u(pos + 2, i)};
592 u(pos + 1, i) = inertia_axis[0][0] * tmp[0] + inertia_axis[1][0] * tmp[1];
593 u(pos + 2, i) = inertia_axis[0][1] * tmp[0] + inertia_axis[1][1] * tmp[1];
594 }
595 }
596 }
597
598 // update the strain and stress in function of the inertia axis
599 {
600 for (size_t k = 0; k != number_of_node; ++k) {
601 for (int i = 0; i != 7; ++i) {
602 const double tmp[2] = {stress[i](1, k), stress[i](2, k)};
603 stress[i](1, k) = inertia_axis[0][0] * tmp[0] + inertia_axis[1][0] * tmp[1];
604 stress[i](2, k) = inertia_axis[0][1] * tmp[0] + inertia_axis[1][1] * tmp[1];
605 }
606 }
607 }
608
609 // update lambda in function of the inertia axis
610 {
611 b2linalg::Matrix<double> trans(6, 6);
612 trans(0, 0) = trans(3, 3) = 1;
613 for (int j = 0; j != 2; ++j) {
614 for (int i = 0; i != 2; ++i) {
615 trans(i + 1, j + 1) = trans(i + 4, j + 4) = inertia_axis[j][i];
616 }
617 }
618 /*
619 trans(4, 0) = -neutral_point[1];
620 trans(5, 0) = neutral_point[0];
621 trans(3, 1) = neutral_point[1] * inertia_axis[0][0] - neutral_point[0] * inertia_axis[0][1];
622 trans(3, 2) = neutral_point[1] * inertia_axis[1][0] - neutral_point[0] * inertia_axis[1][1];
623 */
624
625 {
626 b2linalg::Matrix<double> tmp;
627 tmp = trans * lambda;
628 lambda = tmp * transposed(trans);
629 }
630#ifdef BCSC_ORIG_BC
631 {
632 b2linalg::Vector<double> tmp;
633 tmp = trans * lambdad;
634 lambdad = tmp * transposed(trans);
635 }
636#else
637 {
638 b2linalg::Vector<double> tmp;
639 tmp = transposed(trans) * lambdad;
640 lambdad = tmp * trans;
641 }
642#endif
643 }
644
645#ifdef DEBUG
646 std::cout << "beta=" << std::endl;
647 for (int i = 0; i != 6; ++i) {
648 for (int j = 0; j != 6; ++j) { std::cout << double(beta[j][i]) << " "; }
649 std::cout << std::endl;
650 }
651 double sum[4] = {};
652 for (int i = 0; i != 3; ++i) {
653 sum[0] += beta[i][i];
654 sum[1] += beta[i + 3][i + 3];
655 sum[2] += beta[i][i + 3];
656 sum[3] += beta[i + 3][i];
657 }
658 std::cout << "localisation prop: " << sum[0] << " " << sum[1] << " " << sum[2] << " " << sum[3]
659 << std::endl;
660 std::cout << "lambda=\n" << lambda << std::endl;
661#endif
662
663 b2linalg::Matrix<double, b2linalg::Mrectangle_increment_ref>(lambda).in_place_invert();
664#ifdef BCSC_ORIG_BC
665 {
666 b2linalg::Vector<double> tmp;
667 tmp = lambda * lambdad;
668 lambdad = -tmp;
669 }
670#endif
671
672#ifdef DEBUG
673 std::cout << lambda << std::endl;
674
675 {
676 b2linalg::Matrix<double> lambda_svd(lambda);
677 double work[48];
678 Vector<double> eigenvalue(6);
679 int info;
680 lapack::syev('V', 'L', 6, &lambda_svd(0, 0), 6, &eigenvalue[0], work, 48, info);
681 assert(info == 0);
682 std::cout << "eigenvalue=\n" << eigenvalue << std::endl;
683 std::cout << "lambda_svd=\n" << lambda_svd << std::endl;
684 }
685#endif
686}
687
688#endif // B2BEAM_CROSS_SECTION_SOLVER_H_
#define THROW
Definition b2exception.H:198
Interface to C++ representations of FE solvers.
virtual double get_stage_size(int stage=-1) const =0
virtual std::string get_id() const =0
virtual size_t get_number_of_stage() const =0
virtual void warn_on_non_used_key() const =0
virtual size_t get_number_of_dof() const =0
virtual Solution & get_solution()=0
virtual CaseList & get_case_list()=0
virtual void set_case(Case &case_)=0
virtual Domain & get_domain()=0
virtual ModelReductionBoundaryCondition & get_model_reduction_boundary_condition(ObjectTypeIncomplete< ModelReductionBoundaryCondition > *bc_type)=0
Case * case_
This also.
Definition b2solver.H:93
Model * model_
Definition b2solver.H:91
Logger & get_logger(const std::string &logger_name="")
Definition b2logging.H:829
void sub_3(const T1 v1[3], const T2 v2[3], T3 dest[3])
Definition b2tensor_calculus.H:239
void eigenvector_2(const std::array< std::array< T, 2 >, 2 > &matrix, std::array< T, 2 > &eigenvalues, std::array< std::array< T, 2 >, 2 > &eigenvector)
Definition b2tensor_calculus.H:181
void outer_product_3(const T1 a[3], const T2 b[3], T3 c[3])
Definition b2tensor_calculus.H:389
GenericException< TypeError_name > TypeError
Definition b2exception.H:325
T normalise_2(T a[2])
Definition b2tensor_calculus.H:460
T dot_3(const T a[3], const T b[3])
Definition b2tensor_calculus.H:328
T determinant_2_2(const T a[2][2])
Definition b2tensor_calculus.H:683