15#ifndef B2EIDW_MESH_DEFORMATION_H_
16#define B2EIDW_MESH_DEFORMATION_H_
23#include "utils/b2database.H"
24#include "utils/b2finite_rotation.H"
25#include "utils/b2linear_algebra.H"
30class EIDW_Mesh_deformation {
32 EIDW_Mesh_deformation() : power_disp(0), power_rot(0), power_rot_dist(0), boundary_size(0) {}
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_;
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]) {
53 double min_dist = 1e50;
57 std::fill_n(disp, ndim, 0);
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];
64 for (
int k = 0; k != ndim; ++k) {
65 const double tmp = node_coor(k, i) - node_coor(k, jj);
70 min_dist = std::min(min_dist, nv);
72 std::fill_n(vr, ndim, 0);
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];
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);
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]);
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; }
101 double boundary_size;
104class EIDW_Mesh_deformationDB :
public EIDW_Mesh_deformation {
106 EIDW_Mesh_deformationDB() : database(nullptr) {}
108 void init(DataBase& db) { database = &db; }
110 void compute_deformation(
const int ndim) {
111 b2linalg::Matrix<double> node_coor;
112 database->get(SetName(
"COOR", 1), node_coor);
114 b2linalg::Matrix<double> node_disp(ndim, node_coor.size2());
115 b2linalg::Index imposed_node_id;
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);
125 imposed_node_id.assign(imposed_node_id_set.begin(), imposed_node_id_set.end());
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());
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);
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);
146 Exception() <<
THROW;
150 database->set(SetName(
"DISP", 1, 0, 0, 1), node_disp);
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) {
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; }
175 for (
int i = 0; i != 2; ++i) {
176 double tmp = node_coor(i, nodes[1]) - node_coor(i, nodes[0]);
179 tmp += node_disp(i, nodes[1]) - node_disp(i, nodes[0]);
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);
188 for (
int i = 0; i != 2; ++i) {
189 const size_t node_id =
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;
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;
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) {
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)) {
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; }
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]);
233 dv[k][i] = tmp + node_disp(i, nodes[k + 1]) - node_disp(i, nodes[0]);
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(),
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];
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]};
269 for (
int k = 0; k != 2; ++k) {
270 for (
int i = 0; i != 3; ++i) {
272 node_coor(i, nodes[k + 1]) - node_coor(i, nodes[0]);
275 tmp + node_disp(i, nodes[k + 1]) - node_disp(i, nodes[0]);
286 const size_t node_id =
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];
302 for (
size_t j = 0; j != imposed_node_id.size(); ++j) {
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)));
#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