MAST
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
geom_elem.cpp
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2020 Manav Bhatia and MAST authors
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 
21 // MAST includes
22 #include "mesh/geom_elem.h"
23 #include "mesh/fe_base.h"
24 #include "base/nonlinear_system.h"
26 
27 // libMesh includes
28 #include "libmesh/mesh_base.h"
29 #include "libmesh/boundary_info.h"
30 
31 
33 _sys_init (nullptr),
34 _use_local_elem (false),
35 _ref_elem (nullptr),
36 _local_elem (nullptr) {
37 
38 }
39 
40 
42 
43  if (_local_elem) {
44  delete _local_elem;
45 
46  for (unsigned int i=0; i<_local_nodes.size(); i++)
47  delete _local_nodes[i];
48  }
49 }
50 
51 
52 
53 const libMesh::Elem&
55 
56  libmesh_assert(_ref_elem);
57 
58  return *_ref_elem;
59 }
60 
61 
62 const libMesh::Elem&
64 
65  libmesh_assert(_local_elem);
66 
67  return *_local_elem;
68 }
69 
70 
71 const libMesh::Elem&
73 
74  libmesh_assert(_ref_elem);
75 
76  return *_ref_elem;
77 }
78 
79 
80 const libMesh::Elem&
82 
83  libmesh_assert(_local_elem);
84 
85  return *_local_elem;
86 }
87 
88 
89 
90 unsigned int
92 
93  libmesh_assert(_ref_elem);
94 
95  return _ref_elem->dim();
96 }
97 
98 
99 
100 unsigned int
102 
103  libmesh_assert(_ref_elem);
104 
105  return _ref_elem->n_sides();
106 }
107 
108 
109 libMesh::FEType
110 MAST::GeomElem::get_fe_type(unsigned int i) const {
111 
112  libmesh_assert(_ref_elem);
113 
114  return _sys_init->fetype(i);
115 }
116 
117 
118 void
120 
121  libmesh_assert_equal_to(y_vec.size(), 3);
122 
123  _local_y = y_vec;
124 }
125 
126 
127 void
129  _bending = onoff;;
130 }
131 
132 
133 void
134 MAST::GeomElem::init(const libMesh::Elem& elem,
135  const MAST::SystemInitialization& sys_init) {
136 
137  libmesh_assert(!_ref_elem);
138 
139  _ref_elem = &elem;
140  _sys_init = &sys_init;
141 
142  // initialize the local element if needed.
144 }
145 
146 
147 std::unique_ptr<MAST::FEBase>
148 MAST::GeomElem::init_fe(bool init_grads,
149  bool init_second_order_derivative,
150  int extra_quadrature_order) const {
151 
152  libmesh_assert(_ref_elem);
153 
154  std::unique_ptr<MAST::FEBase> fe(new MAST::FEBase(*_sys_init));
155  fe->set_extra_quadrature_order(extra_quadrature_order);
156  fe->set_evaluate_second_order_derivatives(init_second_order_derivative);
157 
158  fe->init(*this, init_grads);
159 
160  return fe;
161 }
162 
163 
164 std::unique_ptr<MAST::FEBase>
166  bool init_grads,
167  bool init_second_order_derivative,
168  int extra_quadrature_order) const {
169 
170  std::unique_ptr<MAST::FEBase> fe(new MAST::FEBase(*_sys_init));
171  fe->set_extra_quadrature_order(extra_quadrature_order);
172  fe->set_evaluate_second_order_derivatives(init_second_order_derivative);
173 
174  fe->init_for_side(*this, s, init_grads);
175 
176  return fe;
177 }
178 
179 
180 
181 void
183 (std::multimap<libMesh::boundary_id_type, MAST::BoundaryConditionBase*>& bc,
184  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>>& loads) const {
185 
186  // this assumes that the quadrature element is the same as the local element
187 
188  typedef std::multimap<libMesh::boundary_id_type, MAST::BoundaryConditionBase*> maptype;
189  std::pair<maptype::const_iterator, maptype::const_iterator> range;
190 
191  loads.clear();
192 
193  const libMesh::BoundaryInfo&
194  binfo = *_sys_init->system().get_mesh().boundary_info;
195 
196  std::vector<libMesh::boundary_id_type> bids;
197 
198  for (unsigned int i=0; i<_ref_elem->n_sides(); i++) {
199 
200  bids.clear();
201  binfo.boundary_ids(_ref_elem, i, bids);
202 
203  for (unsigned int j=0; j<bids.size(); j++) {
204 
205  range = bc.equal_range(bids[j]);
206 
207  maptype::const_iterator it = range.first;
208  for ( ; it != range.second; it++) loads[i].push_back(it->second);
209  }
210  }
211 }
212 
213 
214 
215 void
217 (unsigned int s, std::vector<libMesh::boundary_id_type>& bc_ids) const {
218 
219  // this assumes that the quadrature element is the same as the local element
220  bc_ids.clear();
221 
222  _sys_init->system().get_mesh().boundary_info->boundary_ids(_ref_elem, s, bc_ids);
223 }
224 
225 
226 const RealVectorX&
228 
229  libmesh_assert(_ref_elem);
230 
231  return _domain_surface_normal;
232 }
233 
234 
235 const RealMatrixX&
237 
238  libmesh_assert(_local_elem);
239 
240  return _T_mat;
241 }
242 
243 
244 void
246 transform_point_to_global_coordinate(const libMesh::Point& local_pt,
247  libMesh::Point& global_pt) const {
248 
249  libmesh_assert(_local_elem);
250 
251  global_pt.zero();
252 
253  // now calculate the global coordinates with respect to the origin
254  for (unsigned int j=0; j<3; j++)
255  for (unsigned int k=0; k<3; k++)
256  global_pt(j) += _T_mat(j,k)*local_pt(k);
257 
258  // shift to the global coordinate
259  global_pt += (*_ref_elem->node_ptr(0));
260 }
261 
262 
263 
264 void
266 transform_vector_to_global_coordinate(const libMesh::Point& local_vec,
267  libMesh::Point& global_vec) const {
268 
269  libmesh_assert(_local_elem);
270 
271  global_vec.zero();
272 
273  // now calculate the global coordinates with respect to the origin
274  for (unsigned int j=0; j<3; j++)
275  for (unsigned int k=0; k<3; k++)
276  global_vec(j) += _T_mat(j,k)*local_vec(k);
277 }
278 
279 
280 
281 void
283 transform_vector_to_local_coordinate(const libMesh::Point& global_vec,
284  libMesh::Point& local_vec) const {
285 
286  libmesh_assert(_local_elem);
287 
288  local_vec.zero();
289 
290  // now calculate the global coordinates with respect to the origin
291  for (unsigned int j=0; j<3; j++)
292  for (unsigned int k=0; k<3; k++)
293  local_vec(j) += _T_mat(k,j) * global_vec(k);
294 }
295 
296 
297 
298 void
301  RealVectorX& global_vec) const {
302 
303  libmesh_assert(_local_elem);
304 
305  global_vec = _T_mat * local_vec;
306 }
307 
308 
309 void
312  RealVectorX& local_vec) const {
313 
314  libmesh_assert(_local_elem);
315 
316  local_vec = _T_mat.transpose() * global_vec;
317 }
318 
319 
320 
321 bool
323 
324  libmesh_assert(_ref_elem);
325  return _use_local_elem;
326 }
327 
328 
329 
330 void
332 
333  libmesh_assert(_ref_elem);
334  libmesh_assert(!_local_elem);
335 
336  switch (_ref_elem->dim()) {
337 
338  case 1: {
339 
340  // if the y and z cooedinates of the nodes are the same then
341  // the element is along the x-axis and should not need any
342  // local element.
343  const Real
344  y = _ref_elem->point(0)(1),
345  z = _ref_elem->point(0)(2);
346 
347  for (unsigned int i=1; i<_ref_elem->n_nodes(); i++) {
348  if (std::fabs(y-_ref_elem->point(i)(1)) != 0. ||
349  std::fabs(z-_ref_elem->point(i)(2)) != 0.)
350  _use_local_elem = true;
351  }
352 
353  if (_use_local_elem)
355  }
356  break;
357 
358  case 2: {
359 
360  // if the z cooedinate of the nodes are the same then
361  // the element is in the xy-plane and should not need any
362  // local element.
363  const Real
364  z = _ref_elem->point(0)(2);
365 
366  for (unsigned int i=1; i<_ref_elem->n_nodes(); i++) {
367  if (std::fabs(z-_ref_elem->point(i)(2)) != 0.)
368  _use_local_elem = true;
369  }
370 
371  if (_use_local_elem)
373  }
374  break;
375 
376  case 3:
377  _use_local_elem = false;
378  break;
379 
380  default:
381  libmesh_error(); // should not get here.
382  }
383 
384 }
385 
386 
387 void
389 
390  libmesh_assert(_ref_elem);
391  libmesh_assert(_use_local_elem);
392  libmesh_assert(!_local_elem);
393  libmesh_assert(_local_y.size());
394  libmesh_assert_equal_to(_ref_elem->dim(), 1);
395 
396  if (_local_y.size()==0) // if the orientation vector has not been defined
397  {
398  if (!_bending) // if bending is not used in this element
399  { // then create a random orientation vector that is not collinear
400  // with the element's local x-axis. Added for github issue #40
401 
402  // Get element x-axis vector
403  libMesh::Point v1;
404  v1 = *_ref_elem->node_ptr(1); v1 -= *_ref_elem->node_ptr(0);
405 
406  // Perturb it by an arbitrary value and assign it to the _local_y vector.
407  _local_y = RealVectorX::Zero(3);
408  _local_y(0) = v1(0)+1.000;
409  _local_y(1) = v1(1)-0.625;
410  _local_y(2) = v1(2)+0.275;
411  }
412  else
413  {
414  libmesh_error_msg("ERROR: y_vector (for orientation of 1D element) not defined; In " << __PRETTY_FUNCTION__ << " in " << __FILE__ << " at line " << __LINE__);
415  }
416  }
417 
418  // first node is the origin of the new cs
419  // calculate the coordinate system for the plane of the element
420  libMesh::Point v1, v2, v3, p;
421  v1 = *_ref_elem->node_ptr(1); v1 -= *_ref_elem->node_ptr(0); v1 /= v1.norm(); // local x
422  for (unsigned int i=0; i<3; i++) v2(i) = _local_y(i); // vector in local x-y plane
423  v3 = v1.cross(v2); // local z
424  libmesh_assert_greater(v3.norm(), 0.); // 0. implies x == y
425  v3 /= v3.norm();
426  v2 = v3.cross(v1); v2 /= v2.norm(); // local y
427 
428  _T_mat = RealMatrixX::Zero(3,3);
429 
430  _local_elem = libMesh::Elem::build(_ref_elem->type()).release();
431  _local_nodes.resize(_ref_elem->n_nodes());
432  for (unsigned int i=0; i<_ref_elem->n_nodes(); i++) {
433  _local_nodes[i] = new libMesh::Node;
434  _local_nodes[i]->set_id() = _ref_elem->node_ptr(i)->id();
435  _local_elem->set_node(i) = _local_nodes[i];
436  }
437 
438  // now the transformation matrix from old to new cs
439  // an_i vn_i = a_i v_i
440  // an_j = a_i v_i.vn_j = a_i t_ij = T^t a_i
441  // t_ij = v_i.vn_j
442 
443  for (unsigned int i=0; i<3; i++) {
444  _T_mat(i,0) = v1(i);
445  _T_mat(i,1) = v2(i);
446  _T_mat(i,2) = v3(i);
447  }
448 
449  // now calculate the new coordinates with respect to the origin
450  for (unsigned int i=0; i<_local_nodes.size(); i++) {
451  p = *_ref_elem->node_ptr(i);
452  p -= *_ref_elem->node_ptr(0); // local wrt origin
453  for (unsigned int j=0; j<3; j++)
454  for (unsigned int k=0; k<3; k++)
455  (*_local_nodes[i])(j) += _T_mat(k,j)*p(k);
456  }
457 }
458 
459 
460 void
462 
463  libmesh_assert(_ref_elem);
464  libmesh_assert(_use_local_elem);
465  libmesh_assert(!_local_elem);
466  libmesh_assert_equal_to(_ref_elem->dim(), 2);
467 
468  // first node is the origin of the new cs
469  // calculate the coordinate system for the plane of the element
470  libMesh::Point v1, v2, v3, p;
471  v1 = *_ref_elem->node_ptr(1); v1 -= *_ref_elem->node_ptr(0); v1 /= v1.norm(); // local x
472  v2 = *_ref_elem->node_ptr(2); v2 -= *_ref_elem->node_ptr(0); v2 /= v2.norm();
473  v3 = v1.cross(v2); v3 /= v3.norm(); // local z
474  v2 = v3.cross(v1); v2 /= v2.norm(); // local y
475 
476  // copy the surface normal
477  _domain_surface_normal = RealVectorX::Zero(3);
478  for (unsigned int i=0; i<3; i++)
479  _domain_surface_normal(i) = v3(i);
480 
481  _T_mat = RealMatrixX::Zero(3,3);
482 
483  _local_elem = libMesh::Elem::build(_ref_elem->type()).release();
484  _local_nodes.resize(_ref_elem->n_nodes());
485  for (unsigned int i=0; i<_ref_elem->n_nodes(); i++) {
486  _local_nodes[i] = new libMesh::Node;
487  _local_nodes[i]->set_id() = _ref_elem->node_ptr(i)->id();
488  _local_elem->set_node(i) = _local_nodes[i];
489  }
490 
491  // now the transformation matrix from old to new cs
492  // an_i vn_i = a_i v_i
493  // an_j = a_i v_i.vn_j = a_i t_ij = T^t a_i
494  // t_ij = v_i.vn_j
495 
496  for (unsigned int i=0; i<3; i++) {
497  _T_mat(i,0) = v1(i);
498  _T_mat(i,1) = v2(i);
499  _T_mat(i,2) = v3(i);
500  }
501 
502  // now calculate the new coordinates with respect to the origin
503  for (unsigned int i=0; i<_local_nodes.size(); i++) {
504  p = *_ref_elem->node_ptr(i);
505  p -= *_ref_elem->node_ptr(0); // local wrt origin
506  for (unsigned int j=0; j<3; j++)
507  for (unsigned int k=0; k<3; k++)
508  (*_local_nodes[i])(j) += _T_mat(k,j)*p(k);
509  }
510 
511 }
virtual const libMesh::Elem & get_reference_local_elem() const
Definition: geom_elem.cpp:63
virtual void get_boundary_ids_on_quadrature_elem_side(unsigned int s, std::vector< libMesh::boundary_id_type > &bc_ids) const
Definition: geom_elem.cpp:217
void transform_vector_to_local_coordinate(const libMesh::Point &global_vec, libMesh::Point &local_vec) const
Definition: geom_elem.cpp:283
bool _use_local_elem
Definition: geom_elem.h:233
MAST::NonlinearSystem & system()
virtual void external_side_loads_for_quadrature_elem(std::multimap< libMesh::boundary_id_type, MAST::BoundaryConditionBase *> &bc, std::map< unsigned int, std::vector< MAST::BoundaryConditionBase *>> &loads) const
From the given list of boundary loads, this identifies the sides of the quadrature element and the lo...
Definition: geom_elem.cpp:183
const MAST::SystemInitialization * _sys_init
system initialization object for this element
Definition: geom_elem.h:231
virtual const libMesh::Elem & get_reference_elem() const
Definition: geom_elem.cpp:54
void _init_local_elem_1d()
initializes the local element
Definition: geom_elem.cpp:388
const RealVectorX & domain_surface_normal() const
Definition: geom_elem.cpp:227
libMesh::FEType get_fe_type(unsigned int i) const
Definition: geom_elem.cpp:110
virtual void clear() libmesh_override
Clear all the data structures associated with the system.
const libMesh::FEType & fetype(unsigned int i) const
const libMesh::Elem * _ref_elem
reference element in the mesh for which the data structure is initialized
Definition: geom_elem.h:239
RealVectorX _local_y
the y-axis that is used to define the coordinate system for a 1-D element.
Definition: geom_elem.h:250
void _init_local_elem()
initializes the local element
Definition: geom_elem.cpp:331
virtual const libMesh::Elem & get_quadrature_local_elem() const
Definition: geom_elem.cpp:81
RealMatrixX _T_mat
Transformation matrix defines T_ij = V_i^t .
Definition: geom_elem.h:269
void set_local_y_vector(const RealVectorX &y_vec)
for 1D elements the transformed coordinate system attached to the element defines the local x-axis al...
Definition: geom_elem.cpp:119
libMesh::Real Real
void transform_point_to_global_coordinate(const libMesh::Point &local_pt, libMesh::Point &global_pt) const
Definition: geom_elem.cpp:246
virtual std::unique_ptr< MAST::FEBase > init_fe(bool init_grads, bool init_second_order_derivative, int extra_quadrature_order=0) const
initializes the finite element shape function and quadrature object with the order of quadrature rule...
Definition: geom_elem.cpp:148
libMesh::Elem * _local_elem
a local element is created if
Definition: geom_elem.h:244
unsigned int n_sides_quadrature_elem() const
number of sides on quadrature element.
Definition: geom_elem.cpp:101
Matrix< Real, Dynamic, Dynamic > RealMatrixX
RealVectorX _domain_surface_normal
surface normal of the 1D/2D element.
Definition: geom_elem.h:255
bool _bending
Defines if bending is used in this element or not.
Definition: geom_elem.h:275
Matrix< Real, Dynamic, 1 > RealVectorX
std::vector< libMesh::Node * > _local_nodes
nodes for local element
Definition: geom_elem.h:260
const RealMatrixX & T_matrix() const
O.
Definition: geom_elem.cpp:236
unsigned int dim() const
Definition: geom_elem.cpp:91
virtual const libMesh::Elem & get_quadrature_elem() const
Definition: geom_elem.cpp:72
virtual std::unique_ptr< MAST::FEBase > init_side_fe(unsigned int s, bool init_grads, bool init_second_order_derivative, int extra_quadrature_order=0) const
initializes the finite element shape function and quadrature object for the side with the order of qu...
Definition: geom_elem.cpp:165
void set_bending(bool onoff)
This sets the 1D elements to extension/torsional stiffness only.
Definition: geom_elem.cpp:128
void _init_local_elem_2d()
initializes the local element
Definition: geom_elem.cpp:461
virtual void init(const libMesh::Elem &elem, const MAST::SystemInitialization &sys_init)
initialize the object for the specified reference elem.
Definition: geom_elem.cpp:134
virtual ~GeomElem()
Definition: geom_elem.cpp:41
bool use_local_elem() const
Vector and matrix quantities defined on one- and two-dimensional elements that are oriented in two or...
Definition: geom_elem.cpp:322
void transform_vector_to_global_coordinate(const libMesh::Point &local_vec, libMesh::Point &global_vec) const
Definition: geom_elem.cpp:266