b2api
B2000++ API Reference Manual, VERSION 4.6
 
Loading...
Searching...
No Matches
b2eidw_mesh_deformation.H
1//------------------------------------------------------------------------
2// b2eidw_mesh_deformation.H --
3//
4// written by Mathias Doreille
5//
6// Copyright (c) 2011-2012 SMR Engineering & Development SA
7// 2502 Bienne, Switzerland
8//
9// All Rights Reserved. Proprietary source code. The contents of
10// this file may not be disclosed to third parties, copied or
11// duplicated in any form, in whole or in part, without the prior
12// written permission of SMR.
13//------------------------------------------------------------------------
14
15#ifndef B2EIDW_MESH_DEFORMATION_H_
16#define B2EIDW_MESH_DEFORMATION_H_
17
18#include <algorithm>
19#include <cmath>
20#include <set>
21#include <vector>
22
23#include "utils/b2database.H"
24#include "utils/b2finite_rotation.H"
25#include "utils/b2linear_algebra.H"
27
28namespace b2000 {
29
30class EIDW_Mesh_deformation {
31public:
32 EIDW_Mesh_deformation() : power_disp(0), power_rot(0), power_rot_dist(0), boundary_size(0) {}
33
34 void set_parameter(
35 int power_disp_, int power_rot_, int power_rot_dist_, double boundary_size_) {
36 power_disp = power_disp_;
37 power_rot = power_rot_;
38 power_rot_dist = power_rot_dist_;
39 boundary_size = boundary_size_;
40 }
41
42 template <int ndim>
43 void compute_deformation(
44 const b2linalg::Matrix<double>& node_coor, b2linalg::Matrix<double>& node_disp,
45 const b2linalg::Index& imposed_node_id, const b2linalg::Vector<double>& node_area,
46 const b2linalg::Matrix<double>& node_normal,
47 const b2linalg::Matrix<double>& node_rotation) {
48 size_t imposed_node_ptr = 0;
49 for (size_t i = 0; i != node_disp.size2(); ++i) {
50 if (i == imposed_node_id[imposed_node_ptr]) {
51 ++imposed_node_ptr;
52 } else {
53 double min_dist = 1e50;
54 double p = 0;
55 double pr = 0;
56 double disp[ndim];
57 std::fill_n(disp, ndim, 0);
58 double disp_r[ndim];
59 std::fill_n(disp_r, ndim, 0);
60 for (size_t j = 0; j != imposed_node_id.size(); ++j) {
61 const size_t jj = imposed_node_id[j];
62 double v[ndim];
63 double nv = 0;
64 for (int k = 0; k != ndim; ++k) {
65 const double tmp = node_coor(k, i) - node_coor(k, jj);
66 v[k] = tmp;
67 nv += tmp * tmp;
68 }
69 nv = std::sqrt(nv);
70 min_dist = std::min(min_dist, nv);
71 double vr[ndim];
72 std::fill_n(vr, ndim, 0);
73 {
74 const double* rotator = &node_rotation(0, j);
75 for (int lj = 0; lj != ndim; ++lj) {
76 for (int li = 0; li != ndim; ++li, ++rotator) {
77 vr[li] += *rotator * v[lj];
78 }
79 }
80 }
81 const double omega = node_area[j] * std::pow(nv, -power_disp);
82 const double omega_r = node_area[j] * std::pow(nv, -power_rot);
83 p += omega;
84 pr += omega_r;
85 for (int k = 0; k != ndim; ++k) {
86 disp[k] += omega * node_disp(k, jj);
87 disp_r[k] += omega_r * (vr[k] - v[k]);
88 }
89 }
90 p = 1.0 / p;
91 pr = std::pow(std::max(1.0, min_dist - boundary_size + 1), -power_rot_dist) / pr;
92 for (int k = 0; k != ndim; ++k) { node_disp(k, i) = disp[k] * p + disp_r[k] * pr; }
93 }
94 }
95 }
96
97private:
98 int power_disp;
99 int power_rot;
100 int power_rot_dist;
101 double boundary_size;
102};
103
104class EIDW_Mesh_deformationDB : public EIDW_Mesh_deformation {
105public:
106 EIDW_Mesh_deformationDB() : database(nullptr) {}
107
108 void init(DataBase& db) { database = &db; }
109
110 void compute_deformation(const int ndim) {
111 b2linalg::Matrix<double> node_coor;
112 database->get(SetName("COOR", 1), node_coor);
113
114 b2linalg::Matrix<double> node_disp(ndim, node_coor.size2());
115 b2linalg::Index imposed_node_id;
116 {
117 std::set<size_t> imposed_node_id_set;
118 b2linalg::Matrix<double> ebc;
119 database->get(SetName("EBC", 1, 0, 0, 1), ebc);
120 for (size_t i = 0; i != ebc.size2(); ++i) {
121 const size_t n = int(ebc(0, i)) - 1;
122 imposed_node_id_set.insert(n);
123 node_disp(int(ebc(1, i)) - 1, n) = ebc(2, i);
124 }
125 imposed_node_id.assign(imposed_node_id_set.begin(), imposed_node_id_set.end());
126 }
127
128 b2linalg::Vector<double> node_area(imposed_node_id.size());
129 b2linalg::Matrix<double> node_normal(ndim, imposed_node_id.size());
130 b2linalg::Matrix<double> node_rotation(ndim * ndim, imposed_node_id.size());
131
132 switch (ndim) {
133 case 2:
134 compute_surface_node_2(
135 node_coor, node_disp, imposed_node_id, node_area, node_normal, node_rotation);
136 EIDW_Mesh_deformation::compute_deformation<2>(
137 node_coor, node_disp, imposed_node_id, node_area, node_normal, node_rotation);
138 break;
139 case 3:
140 compute_surface_node_3(
141 node_coor, node_disp, imposed_node_id, node_area, node_normal, node_rotation);
142 EIDW_Mesh_deformation::compute_deformation<3>(
143 node_coor, node_disp, imposed_node_id, node_area, node_normal, node_rotation);
144 break;
145 default:
146 Exception() << THROW;
147 break;
148 }
149
150 database->set(SetName("DISP", 1, 0, 0, 1), node_disp);
151 }
152
153private:
154 DataBase* database;
155
156 void compute_surface_node_2(
157 const b2linalg::Matrix<double>& node_coor, const b2linalg::Matrix<double>& node_disp,
158 const b2linalg::Index& imposed_node_id, b2linalg::Vector<double>& node_area,
159 b2linalg::Matrix<double>& node_normal, b2linalg::Matrix<double>& node_rotation) {
160 ArrayRTable etab;
161 database->get(SetName("ETAB", 1), etab);
162 std::vector<int> nb_contrib(imposed_node_id.size());
163 for (size_t j = 0; j != etab.size(); ++j) {
164 const RTable& rtable = etab[j];
165 if (rtable.get_int("ITYP", -1) != 266) { continue; }
166 std::vector<int> nodes;
167 rtable.get("NODES", nodes);
168 if (nodes.size() != 2) { Exception() << THROW; }
169 nodes[0] -= 1;
170 nodes[1] -= 1;
171 double v[2];
172 double dv[2];
173 double nv = 0;
174 double ndv = 0;
175 for (int i = 0; i != 2; ++i) {
176 double tmp = node_coor(i, nodes[1]) - node_coor(i, nodes[0]);
177 v[i] = tmp;
178 nv += tmp * tmp;
179 tmp += node_disp(i, nodes[1]) - node_disp(i, nodes[0]);
180 dv[i] = tmp;
181 ndv += tmp * tmp;
182 }
183 nv = std::sqrt(nv);
184 ndv = std::sqrt(ndv);
185 const double n[2] = {v[1] / nv, -v[0] / nv};
186 const double omega = (v[0] * dv[1] - v[1] * dv[0]) / (nv * ndv);
187 nv *= 0.5;
188 for (int i = 0; i != 2; ++i) {
189 const size_t node_id =
190 std::lower_bound(
191 imposed_node_id.begin(), imposed_node_id.end(), size_t(nodes[i]))
192 - imposed_node_id.begin();
193 ++nb_contrib[node_id];
194 node_area[node_id] += nv;
195 for (int k = 0; k != 2; ++k) { node_normal(k, node_id) += n[k]; }
196 node_rotation(0, node_id) += omega;
197 }
198 }
199 for (size_t j = 0; j != imposed_node_id.size(); ++j) {
200 const double omega = node_rotation(0, j) / nb_contrib[j];
201 const double c = std::cos(omega);
202 const double s = std::sin(omega);
203 node_rotation(0, j) = c;
204 node_rotation(1, j) = s;
205 node_rotation(2, j) = -s;
206 node_rotation(3, j) = c;
207 normalise_2(&node_normal(0, j));
208 }
209 }
210
211 void compute_surface_node_3(
212 const b2linalg::Matrix<double>& node_coor, const b2linalg::Matrix<double>& node_disp,
213 const b2linalg::Index& imposed_node_id, b2linalg::Vector<double>& node_area,
214 b2linalg::Matrix<double>& node_normal, b2linalg::Matrix<double>& node_rotation) {
215 ArrayRTable etab;
216 database->get(SetName("ETAB", 1), etab);
217 std::vector<int> nb_contrib(imposed_node_id.size());
218 for (size_t j = 0; j != etab.size(); ++j) {
219 const RTable& rtable = etab[j];
220 switch (rtable.get_int("ITYP", -1)) {
221 case 268: // T3
222 {
223 std::vector<int> nodes;
224 rtable.get("NODES", nodes);
225 if (nodes.size() != 3) { Exception() << THROW; }
226 for (int k = 0; k != 3; ++k) { nodes[k] -= 1; }
227 double v[2][3];
228 double dv[2][3];
229 for (int k = 0; k != 2; ++k) {
230 for (int i = 0; i != 3; ++i) {
231 const double tmp = node_coor(i, nodes[k + 1]) - node_coor(i, nodes[0]);
232 v[k][i] = tmp;
233 dv[k][i] = tmp + node_disp(i, nodes[k + 1]) - node_disp(i, nodes[0]);
234 }
235 }
236 double n[3];
237 outer_product_3(v[0], v[1], n);
238 const double s = normalise_3(n) / 3;
239 double dn[3];
240 outer_product_3(dv[0], dv[1], dn);
241 normalise_3(dn);
242 double rot[3];
243 outer_product_3(n, dn, rot);
244 for (int k = 0; k != 3; ++k) {
245 const size_t node_id = std::lower_bound(
246 imposed_node_id.begin(), imposed_node_id.end(),
247 size_t(nodes[k]))
248 - imposed_node_id.begin();
249 ++nb_contrib[node_id];
250 node_area[node_id] += s;
251 for (int i = 0; i != 3; ++i) {
252 node_normal(i, node_id) += n[i];
253 node_rotation(i, node_id) += rot[i];
254 }
255 }
256 break;
257 }
258 case 267: // Q4
259 {
260 std::vector<int> nodesq;
261 rtable.get("NODES", nodesq);
262 if (nodesq.size() != 4) { Exception() << THROW; }
263 for (int k = 0; k != 4; ++k) { nodesq[k] -= 1; }
264 for (int kk = 0; kk != 4; ++kk) {
265 const int nodes[3] = {
266 nodesq[kk], nodesq[(kk + 1) % 4], nodesq[(kk + 2) % 4]};
267 double v[2][3];
268 double dv[2][3];
269 for (int k = 0; k != 2; ++k) {
270 for (int i = 0; i != 3; ++i) {
271 const double tmp =
272 node_coor(i, nodes[k + 1]) - node_coor(i, nodes[0]);
273 v[k][i] = tmp;
274 dv[k][i] =
275 tmp + node_disp(i, nodes[k + 1]) - node_disp(i, nodes[0]);
276 }
277 }
278 double n[3];
279 outer_product_3(v[0], v[1], n);
280 const double s = normalise_3(n) / 2;
281 double dn[3];
282 outer_product_3(dv[0], dv[1], dn);
283 normalise_3(dn);
284 double rot[3];
285 outer_product_3(n, dn, rot);
286 const size_t node_id =
287 std::lower_bound(
288 imposed_node_id.begin(), imposed_node_id.end(), nodes[1])
289 - imposed_node_id.begin();
290 ++nb_contrib[node_id];
291 node_area[node_id] += s;
292 for (int i = 0; i != 3; ++i) {
293 node_normal(i, node_id) += n[i];
294 node_rotation(i, node_id) += rot[i];
295 }
296 }
297 break;
298 }
299 }
300 }
301
302 for (size_t j = 0; j != imposed_node_id.size(); ++j) {
303 double omega[3];
304 for (int i = 0; i != 3; ++i) { omega[i] = node_rotation(i, j) / nb_contrib[j]; }
305 FiniteRotation<double>(omega).get_rotator(
306 reinterpret_cast<double(*)[3]>(&node_rotation(0, j)));
307 normalise_3(&node_normal(0, j));
308 }
309 }
310};
311
312} // namespace b2000
313
314#endif /* B2EIDW_MESH_DEFORMATION_H_ */
#define THROW
Definition b2exception.H:198
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
T normalise_3(T a[3])
Definition b2tensor_calculus.H:418
void outer_product_3(const T1 a[3], const T2 b[3], T3 c[3])
Definition b2tensor_calculus.H:389
T normalise_2(T a[2])
Definition b2tensor_calculus.H:460