MAST
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
test_helpers.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 // We need access to the protected thermal_residual method to test it
21 // NOTE: Be careful with this, it could cause unexpected problems
22 #define protected public
23 
24 #include "test_helpers.h"
25 
26 #include "libmesh/point.h"
27 #include "libmesh/face_quad4.h"
28 
29 
30 #define pi 3.14159265358979323846
31 
32 
34 {
35  std::vector<double> vec(M.data(), M.data()+M.rows()*M.cols());
36  return vec;
37 }
38 
40 {
41  Real true_volume = 0.0;
42  uint n_nodes = X.cols();
43  for (uint i=0; i<n_nodes-1; i++)
44  {
45  true_volume += X(0,i)*X(1,i+1) - X(0,i+1)*X(1,i);
46  }
47  true_volume += X(0,n_nodes-1)*X(1,0) - X(0,0)*X(1,n_nodes-1);
48  true_volume = std::abs(true_volume);
49  true_volume *= 0.5;
50  return true_volume;
51 }
52 
55  const RealVectorX& initial_elem_solution,
56  RealMatrixX& jacobian)
57 {
58  Real delta = 3.4526698e-04; // sqrt(eps('single')) in MATLAB
59  //Real delta = 1.1920929e-07; // eps('single') in MATLAB
60  //Real delta = 1.490116119384766e-08; // sqrt(eps('double')) in MATLAB
61 
62  int n = jacobian.cols();
63  RealMatrixX dummy = RealMatrixX::Zero(n,n);
64  RealVectorX elem_solution = initial_elem_solution;
65 
66  // 6th order central finite difference
67  for (uint i=0; i<elem_solution.size(); i++)
68  {
69  elem_solution(i) = initial_elem_solution(i) + delta;
70  elem.set_solution(elem_solution);
71  RealVectorX residual_h = RealVectorX::Zero(n);
72  elem.internal_residual(false, residual_h, dummy);
73 
74  elem_solution(i) = initial_elem_solution(i) + 2.0*delta;
75  elem.set_solution(elem_solution);
76  RealVectorX residual_2h = RealVectorX::Zero(n);
77  elem.internal_residual(false, residual_2h, dummy);
78 
79  elem_solution(i) = initial_elem_solution(i) + 3.0*delta;
80  elem.set_solution(elem_solution);
81  RealVectorX residual_3h = RealVectorX::Zero(n);
82  elem.internal_residual(false, residual_3h, dummy);
83 
84  elem_solution(i) = initial_elem_solution(i) - delta;
85  elem.set_solution(elem_solution);
86  RealVectorX residual_n = RealVectorX::Zero(n);
87  elem.internal_residual(false, residual_n, dummy);
88 
89  elem_solution(i) = initial_elem_solution(i) - 2.0*delta;
90  elem.set_solution(elem_solution);
91  RealVectorX residual_2n = RealVectorX::Zero(n);
92  elem.internal_residual(false, residual_2n, dummy);
93 
94  elem_solution(i) = initial_elem_solution(i) - 3.0*delta;
95  elem.set_solution(elem_solution);
96  RealVectorX residual_3n = RealVectorX::Zero(n);
97  elem.internal_residual(false, residual_3n, dummy);
98 
99  elem_solution(i) = initial_elem_solution(i);
100 
101  //jacobian.col(i) = (residual_2n - 8.0*residual_n + 8.0*residual_h - residual_2h)/(12.0 * delta);
102 
103  jacobian.col(i) = (-residual_3n + 9.0*residual_2n - 45.0*residual_n + 45.0*residual_h - 9.0*residual_2h + residual_3h)/(60.0 * delta);
104  }
105 }
106 
107 
110  MAST::PhysicsDisciplineBase& discipline,
111  const RealVectorX& initial_elem_solution,
112  RealMatrixX& jacobian)
113 {
114  Real delta = 3.4526698e-04; // sqrt(eps('single')) in MATLAB
115 
116  int n = jacobian.cols();
117  RealMatrixX dummy = RealMatrixX::Zero(n,n);
118  RealVectorX elem_solution = initial_elem_solution;
119 
120  // 4th order central finite difference
121  for (uint i=0; i<elem_solution.size(); i++)
122  {
123  elem_solution(i) = initial_elem_solution(i) + delta;
124  elem.set_solution(elem_solution);
125  RealVectorX residual_h = RealVectorX::Zero(n);
126  elem.side_external_residual(false, residual_h, dummy, dummy, discipline.side_loads());
127 
128  elem_solution(i) = initial_elem_solution(i) + 2.0*delta;
129  elem.set_solution(elem_solution);
130  RealVectorX residual_2h = RealVectorX::Zero(n);
131  elem.side_external_residual(false, residual_2h, dummy, dummy, discipline.side_loads());
132 
133  elem_solution(i) = initial_elem_solution(i) - delta;
134  elem.set_solution(elem_solution);
135  RealVectorX residual_n = RealVectorX::Zero(n);
136  elem.side_external_residual(false, residual_n, dummy, dummy, discipline.side_loads());
137 
138  elem_solution(i) = initial_elem_solution(i) - 2.0*delta;
139  elem.set_solution(elem_solution);
140  RealVectorX residual_2n = RealVectorX::Zero(n);
141  elem.side_external_residual(false, residual_2n, dummy, dummy, discipline.side_loads());
142 
143  elem_solution(i) = initial_elem_solution(i);
144 
145  jacobian.col(i) = (residual_2n - 8.0*residual_n + 8.0*residual_h - residual_2h)/(12.0 * delta);
146  }
147 }
148 
149 
152  MAST::PhysicsDisciplineBase& discipline,
153  const RealVectorX& initial_elem_solution,
154  RealMatrixX& jacobian)
155 {
156  Real delta = 3.4526698e-04; // sqrt(eps('single')) in MATLAB
157 
158  int n = jacobian.cols();
159  RealMatrixX dummy = RealMatrixX::Zero(n,n);
160  RealVectorX elem_solution = initial_elem_solution;
161 
162  // 4th order central finite difference
163  for (uint i=0; i<elem_solution.size(); i++)
164  {
165  elem_solution(i) = initial_elem_solution(i) + delta;
166  elem.set_solution(elem_solution);
167  RealVectorX residual_h = RealVectorX::Zero(n);
168  elem.volume_external_residual(false, residual_h, dummy, dummy, discipline.volume_loads());
169 
170  elem_solution(i) = initial_elem_solution(i) + 2.0*delta;
171  elem.set_solution(elem_solution);
172  RealVectorX residual_2h = RealVectorX::Zero(n);
173  elem.volume_external_residual(false, residual_2h, dummy, dummy, discipline.volume_loads());
174 
175  elem_solution(i) = initial_elem_solution(i) - delta;
176  elem.set_solution(elem_solution);
177  RealVectorX residual_n = RealVectorX::Zero(n);
178  elem.volume_external_residual(false, residual_n, dummy, dummy, discipline.volume_loads());
179 
180  elem_solution(i) = initial_elem_solution(i) - 2.0*delta;
181  elem.set_solution(elem_solution);
182  RealVectorX residual_2n = RealVectorX::Zero(n);
183  elem.volume_external_residual(false, residual_2n, dummy, dummy, discipline.volume_loads());
184 
185  elem_solution(i) = initial_elem_solution(i);
186 
187  jacobian.col(i) = (residual_2n - 8.0*residual_n + 8.0*residual_h - residual_2h)/(12.0 * delta);
188  }
189 }
190 
191 
194  const RealVectorX& initial_elem_accel,
195  RealMatrixX& jacobian)
196 {
197  Real delta = 3.4526698e-04; // sqrt(eps('single')) in MATLAB
198  //Real delta = 1.1920929e-07; // eps('single') in MATLAB
199  //Real delta = 1.490116119384766e-08; // sqrt(eps('double')) in MATLAB
200 
201  int n = jacobian.cols();
202  RealMatrixX dummy = RealMatrixX::Zero(n,n);
203  RealVectorX elem_accel = initial_elem_accel;
204 
205  // 6th order central finite difference
206  for (uint i=0; i<elem_accel.size(); i++)
207  {
208  elem_accel(i) = initial_elem_accel(i) + delta;
209  elem.set_acceleration(elem_accel);
210  RealVectorX residual_h = RealVectorX::Zero(n);
211  elem.inertial_residual(false, residual_h, dummy, dummy, dummy);
212 
213  elem_accel(i) = initial_elem_accel(i) + 2.0*delta;
214  elem.set_acceleration(elem_accel);
215  RealVectorX residual_2h = RealVectorX::Zero(n);
216  elem.inertial_residual(false, residual_2h, dummy, dummy, dummy);
217 
218  elem_accel(i) = initial_elem_accel(i) + 3.0*delta;
219  elem.set_acceleration(elem_accel);
220  RealVectorX residual_3h = RealVectorX::Zero(n);
221  elem.inertial_residual(false, residual_3h, dummy, dummy, dummy);
222 
223  elem_accel(i) = initial_elem_accel(i) - delta;
224  elem.set_acceleration(elem_accel);
225  RealVectorX residual_n = RealVectorX::Zero(n);
226  elem.inertial_residual(false, residual_n, dummy, dummy, dummy);
227 
228  elem_accel(i) = initial_elem_accel(i) - 2.0*delta;
229  elem.set_acceleration(elem_accel);
230  RealVectorX residual_2n = RealVectorX::Zero(n);
231  elem.inertial_residual(false, residual_2n, dummy, dummy, dummy);
232 
233  elem_accel(i) = initial_elem_accel(i) - 3.0*delta;
234  elem.set_acceleration(elem_accel);
235  RealVectorX residual_3n = RealVectorX::Zero(n);
236  elem.inertial_residual(false, residual_3n, dummy, dummy, dummy);
237 
238  elem_accel(i) = initial_elem_accel(i);
239 
240  //jacobian.col(i) = (residual_2n - 8.0*residual_n + 8.0*residual_h - residual_2h)/(12.0 * delta);
241 
242  jacobian.col(i) = (-residual_3n + 9.0*residual_2n - 45.0*residual_n + 45.0*residual_h - 9.0*residual_2h + residual_3h)/(60.0 * delta);
243  }
244 }
245 
246 
249  const RealVectorX& initial_elem_solution,
250  RealMatrixX& jacobian,
251  MAST::BoundaryConditionBase& thermal_bc)
252 {
253  Real delta = 3.4526698e-04; // sqrt(eps('single')) in MATLAB
254  //Real delta = 1.1920929e-07; // eps('single') in MATLAB
255  //Real delta = 1.490116119384766e-08; // sqrt(eps('double')) in MATLAB
256 
257  int n = jacobian.cols();
258  RealMatrixX dummy = RealMatrixX::Zero(n,n);
259  RealVectorX elem_solution = initial_elem_solution;
260 
261  // 6th order central finite difference
262  for (uint i=0; i<elem_solution.size(); i++)
263  {
264  elem_solution(i) = initial_elem_solution(i) + delta;
265  elem.set_solution(elem_solution);
266  RealVectorX residual_h = RealVectorX::Zero(n);
267  elem.thermal_residual(false, residual_h, dummy, thermal_bc);
268 
269  elem_solution(i) = initial_elem_solution(i) + 2.0*delta;
270  elem.set_solution(elem_solution);
271  RealVectorX residual_2h = RealVectorX::Zero(n);
272  elem.thermal_residual(false, residual_2h, dummy, thermal_bc);
273 
274  elem_solution(i) = initial_elem_solution(i) + 3.0*delta;
275  elem.set_solution(elem_solution);
276  RealVectorX residual_3h = RealVectorX::Zero(n);
277  elem.thermal_residual(false, residual_3h, dummy, thermal_bc);
278 
279  elem_solution(i) = initial_elem_solution(i) - delta;
280  elem.set_solution(elem_solution);
281  RealVectorX residual_n = RealVectorX::Zero(n);
282  elem.thermal_residual(false, residual_n, dummy, thermal_bc);
283 
284  elem_solution(i) = initial_elem_solution(i) - 2.0*delta;
285  elem.set_solution(elem_solution);
286  RealVectorX residual_2n = RealVectorX::Zero(n);
287  elem.thermal_residual(false, residual_2n, dummy, thermal_bc);
288 
289  elem_solution(i) = initial_elem_solution(i) - 3.0*delta;
290  elem.set_solution(elem_solution);
291  RealVectorX residual_3n = RealVectorX::Zero(n);
292  elem.thermal_residual(false, residual_3n, dummy, thermal_bc);
293 
294  elem_solution(i) = initial_elem_solution(i);
295 
296  //jacobian.col(i) = (residual_2n - 8.0*residual_n + 8.0*residual_h - residual_2h)/(12.0 * delta);
297 
298  jacobian.col(i) = (-residual_3n + 9.0*residual_2n - 45.0*residual_n + 45.0*residual_h - 9.0*residual_2h + residual_3h)/(60.0 * delta);
299  }
300 }
301 
302 
303 void TEST::transform_element(libMesh::MeshBase& mesh, const RealMatrixX X0,
304  Real shift_x, Real shift_y, Real shift_z,
305  Real scale_x, Real scale_y,
306  Real rotation_x, Real rotation_y, Real rotation_z,
307  Real shear_x, Real shear_y)
308 {
309  const uint n_nodes = X0.cols();
310 
311  RealMatrixX Vi = RealMatrixX::Ones(1,n_nodes);
312 
313  //std::cout << "X0:\n" << X0 << "\n" << std::endl;
314 
315  // Vectors from element centroid to its nodes
316  RealMatrixX Vc = RealMatrixX::Zero(3,n_nodes);
317  Vc.row(0) = X0.row(0) - X0.row(0).mean()*Vi;
318  Vc.row(1) = X0.row(1) - X0.row(1).mean()*Vi;
319  Vc.row(2) = X0.row(2) - X0.row(2).mean()*Vi;
320 
321  //std::cout << "Vc:\n" << Vc << "\n" << std::endl;
322 
323  // Scaling Matrix
324  RealMatrixX S = RealMatrixX::Identity(3,3);
325  S(0,0) = scale_x;
326  S(1,1) = scale_y;
327 
328  //std::cout << "S:\n" << S << "\n" << std::endl;
329 
330  // Scale the element's vectors
331  RealMatrixX V = S * Vc;
332 
333  //std::cout << "V:\n" << V << "\n" << std::endl;
334 
335 
336  // Shear Matrix
337  RealMatrixX K = RealMatrixX::Identity(3,3);
338  K(0,1) = shear_x;
339  K(1,0) = shear_y;
340 
341  // Shear the element's vectors
342  V = K * V;
343 
344  // Rotation Matrices
345  RealMatrix3 Rz;
346  Real theta = rotation_z*pi/180.0;
347  Rz << cos(theta), -sin(theta), 0.0,
348  sin(theta), cos(theta), 0.0,
349  0.0, 0.0, 1.0;
350  //std::cout << "Rz:\n" << Rz << "\n" << std::endl;
351 
352  RealMatrix3 Ry;
353  theta = rotation_y*pi/180.0;
354  Ry << cos(theta), 0.0, -sin(theta),
355  0.0, 1.0, 0.0,
356  sin(theta), 0.0, cos(theta);
357  //std::cout << "Ry:\n" << Ry << "\n" << std::endl;
358 
359  RealMatrix3 Rx;
360  theta = rotation_x*pi/180.0;
361  Rx << 1.0, 0.0, 0.0,
362  0.0, cos(theta), -sin(theta),
363  0.0, sin(theta), cos(theta);
364  //std::cout << "Rx:\n" << Rx << "\n" << std::endl;
365 
366  // Rotate the element's vectors about the centroid
367  V = Rz * V;
368  V = Ry * V;
369  V = Rx * V;
370 
371  //std::cout << "V:\n" << V << "\n" << std::endl;
372 
373  RealMatrixX X = RealMatrixX::Zero(3,n_nodes);
374 
375  //std::cout << "xc:\n" << X0.row(0).mean()*Vi << "\n" << std::endl;
376  //std::cout << "yc:\n" << X0.row(1).mean()*Vi << "\n" << std::endl;
377  //std::cout << "zc:\n" << X0.row(2).mean()*Vi << "\n" << std::endl;
378 
379  X.row(0) = X0.row(0).mean()*Vi + V.row(0);
380  X.row(1) = X0.row(1).mean()*Vi + V.row(1);
381  X.row(2) = X0.row(2).mean()*Vi + V.row(2);
382 
383  // Shift the element
384  X.row(0) += shift_x*RealMatrixX::Ones(1,n_nodes);
385  X.row(1) += shift_y*RealMatrixX::Ones(1,n_nodes);
386  X.row(2) += shift_z*RealMatrixX::Ones(1,n_nodes);
387 
388  //std::cout << "Transformed X:\n" << X << "\n" << std::endl;
389 
390 
391  // Update the element with the new node Coordinates
392  for (int i=0; i<n_nodes; i++)
393  {
394  (*mesh.node_ptr(i)) = libMesh::Point(X(0,i), X(1,i), X(2,i));
395  }
396 }
void approximate_inertial_jacobian_with_finite_difference(MAST::StructuralElementBase &elem, const RealVectorX &initial_elem_solution, RealMatrixX &jacobian)
Approximates the inertial jacobian using a 6th order accurate central finite difference scheme...
virtual bool thermal_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, MAST::BoundaryConditionBase &bc)=0
Calculates the force vector and Jacobian due to thermal stresses.
virtual void set_acceleration(const RealVectorX &vec, bool if_sens=false)
stores vec as acceleration for element level calculations, or its sensitivity if if_sens is true...
Real get_shoelace_area(RealMatrixX X)
Calcualtes the area of a 2D polygon using the shoelace formula.
virtual bool inertial_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xddot, RealMatrixX &jac_xdot, RealMatrixX &jac)
inertial force contribution to system residual
void approximate_volume_external_jacobian_with_finite_difference(MAST::StructuralElementBase &elem, MAST::PhysicsDisciplineBase &discipline, const RealVectorX &initial_elem_solution, RealMatrixX &jacobian)
Approximates the volume external jacobian using a 4th order accurate central finite difference scheme...
libMesh::Real Real
void transform_element(libMesh::MeshBase &mesh, const RealMatrixX X0, Real shift_x, Real shift_y, Real shift_z, Real scale_x, Real scale_y, Real rotation_x, Real rotation_y, Real rotation_z, Real shear_x=0, Real shear_y=0)
Transform an element by applying any combination of: shifts, scales, rotations, and shears...
std::vector< double > eigen_matrix_to_std_vector(RealMatrixX M)
Converts an Eigen Matrix object to a std::vector.
void approximate_internal_jacobian_with_finite_difference(MAST::StructuralElementBase &elem, const RealVectorX &initial_elem_solution, RealMatrixX &jacobian)
Approximates the internal Jacobian of an element using a 6th order accurate central finite difference...
const MAST::SideBCMapType & side_loads() const
Matrix< Real, Dynamic, Dynamic > RealMatrixX
void approximate_side_external_jacobian_with_finite_difference(MAST::StructuralElementBase &elem, MAST::PhysicsDisciplineBase &discipline, const RealVectorX &initial_elem_solution, RealMatrixX &jacobian)
Approximates the side external jacobian using a 4th order accurate central finite difference scheme...
bool side_external_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac, std::multimap< libMesh::boundary_id_type, MAST::BoundaryConditionBase *> &bc)
side external force contribution to system residual.
virtual void set_solution(const RealVectorX &vec, bool if_sens=false)
stores vec as solution for element level calculations, or its sensitivity if if_sens is true...
Matrix< Real, Dynamic, 1 > RealVectorX
bool volume_external_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac, std::multimap< libMesh::subdomain_id_type, MAST::BoundaryConditionBase *> &bc)
volume external force contribution to system residual.
Matrix< Real, 3, 3 > RealMatrix3
const MAST::VolumeBCMapType & volume_loads() const
void approximate_thermal_jacobian_with_finite_difference(MAST::StructuralElementBase &elem, const RealVectorX &initial_elem_solution, RealMatrixX &jacobian, MAST::BoundaryConditionBase &thermal_bc)
Approximates the thermal jacobian using a 6th order accurate central finite difference scheme...
#define pi
virtual bool internal_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac)=0
internal force contribution to system residual