MAST
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
piston_theory_1D_and_2D.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 // BOOST includes
22 #include <boost/test/unit_test.hpp>
23 
24 
25 // MAST includes
26 #include "tests/structural/build_structural_elem_1D.h"
27 #include "tests/structural/build_structural_elem_2D.h"
30 #include "tests/base/test_comparisons.h"
32 #include "elasticity/structural_discipline.h"
34 #include "base/parameter.h"
38 #include "base/nonlinear_system.h"
39 
40 
41 // libMesh includes
42 #include "libmesh/dof_map.h"
43 
44 
45 
46 template <typename ValType>
47 void
49 
50  const Real
51  delta = 1.e-5,
52  tol = 1.e-2;
53 
54  // tell the discipline about the section property and the piston theory
55  // boundary condition
56  v._discipline->add_volume_load(0, *v._p_theory);
57 
58 
59  // get reference to the element in this mesh
60  const libMesh::Elem& elem = **(v._mesh->local_elements_begin());
61 
62  // now create the structural element
63  std::unique_ptr<MAST::StructuralElementBase>
64  e(MAST::build_structural_element(*v._structural_sys,
65  elem,
66  *v._p_card).release());
67 
68 
69  // number of dofs in this element
70  const libMesh::DofMap& dofmap = v._sys->get_dof_map();
71  std::vector<unsigned int> dof_ids;
72  dofmap.dof_indices(&elem, dof_ids);
73 
74  const unsigned int ndofs = (unsigned int)dof_ids.size();
75 
76  // now get the residual and Jacobian evaluations
78  x0 = RealVectorX::Zero(ndofs),
79  xdot0 = RealVectorX::Zero(ndofs),
80  x = RealVectorX::Zero(ndofs),
81  xdot = RealVectorX::Zero(ndofs),
82  res0 = RealVectorX::Zero(ndofs),
83  res = RealVectorX::Zero(ndofs);
84 
86  jac_x = RealMatrixX::Zero(ndofs, ndofs),
87  jac_xdot = RealMatrixX::Zero(ndofs, ndofs),
88  jac_x_fd = RealMatrixX::Zero(ndofs, ndofs),
89  jac_xdot_fd = RealMatrixX::Zero(ndofs, ndofs),
90  dummy;
91 
92 
93  // tell the element about the solution and velocity
94  e->set_solution(x);
95  e->set_velocity(xdot);
96 
97  // get the base residual vector and the Jacobians for numerical comparisons
98  // later.
99  e->volume_external_residual(true,
100  res0,
101  jac_xdot,
102  jac_x,
103  v._discipline->volume_loads());
104 
105  for (unsigned int i=0; i<ndofs; i++) {
106 
107  // first the Jacobian due to x
108  x = x0;
109  xdot = xdot0;
110  // perturb the i^th element of the solution
111  x(i) += delta;
112  e->set_solution(x);
113  e->set_velocity(xdot);
114 
115  // get the new residual
116  res.setZero();
117  e->volume_external_residual(false,
118  res,
119  dummy,
120  dummy,
121  v._discipline->volume_loads());
122 
123  // set the i^th column of the finite-differenced Jacobian
124  jac_x_fd.col(i) = (res-res0)/delta;
125 
126 
127 
128  // do the same for the Jacobian due to x_dot
129  x = x0;
130  xdot = xdot0;
131  // perturb the i^th element of the velocity
132  xdot(i) += delta;
133  e->set_solution(x);
134  e->set_velocity(xdot);
135 
136  // get the new residual
137  res.setZero();
138  e->volume_external_residual(false,
139  res,
140  dummy,
141  dummy,
142  v._discipline->volume_loads());
143 
144  // set the i^th column of the finite-differenced Jacobian
145  jac_xdot_fd.col(i) = (res-res0)/delta;
146  }
147 
148  // now compare the matrices
149  BOOST_CHECK(MAST::compare_matrix( jac_x_fd, jac_x, tol));
150  BOOST_CHECK(MAST::compare_matrix(jac_xdot_fd, jac_xdot, tol));
151 }
152 
153 
154 BOOST_FIXTURE_TEST_SUITE (Structural1DJacobianEvaluation, MAST::BuildStructural1DElem)
155 
156 
157 void
159  std::vector<MAST::Parameter*>& params) {
160 
161  const Real
162  delta = 1.e-5,
163  tol = 1.e-3;
164 
165  // calculate the base pressure
166  Real
167  p0 = 0.,
168  dp = 0.,
169  dp_fd = 0.,
170  v0 = 0.,
171  dv = 0.;
172 
173  libMesh::Point pt;
174 
175  func(pt, 0., p0);
176 
177  // now calculate sensitivity wrt the parameters
178  for (unsigned int i=0; i<params.size(); i++) {
179 
180  MAST::Parameter& f = *params[i];
181 
182  // calculate the partial derivative
183  func.derivative(*params[i],
184  pt,
185  0.,
186  dp);
187 
188  // now perturb the parameter and calculate the finite difference
189  // sensitivity of pressure.
190  v0 = f();
191  (fabs(v0) > 0)? dv=delta*v0 : dv=delta;
192  f() += dv;
193 
194 
195  func(pt, 0., dp_fd);
196 
197  dp_fd -= p0;
198  dp_fd /= dv;
199 
200  // reset the parameter value
201  f() = v0;
202 
203  BOOST_TEST_MESSAGE(" ** dfunc/dp (total) wrt : " << f.name() << " **");
204  BOOST_CHECK(MAST::compare_value( dp_fd, dp, tol));
205  }
206 }
207 
208 
209 BOOST_AUTO_TEST_CASE (PistonTheoryPressure) {
210 
211  const Real
212  tol = 1.e-2;
213 
214  this->init(false, false);
215 
216  // calculate the surface pressure and its sensitivity with respect to the
217  // relevant parameters
218  std::unique_ptr<MAST::FieldFunction<Real> >
219  pressure (_p_theory->get_pressure_function(*_dwdx_f, *_dwdt_f).release()),
220  dpressure_dx (_p_theory->get_dpdx_function (*_dwdx_f, *_dwdt_f).release()),
221  dpressure_dxdot(_p_theory->get_dpdxdot_function (*_dwdx_f, *_dwdt_f).release());
222 
223 
224  // first make sure that the sensitivity from pressure wrt x and xdot
225  // is the same as analysis from the other two respective functions
226  Real
227  dpdx1 = 0.,
228  dpdx2 = 0.,
229  dpdxdot1 = 0.,
230  dpdxdot2 = 0.;
231 
232  libMesh::Point pt;
233 
234  // first the sensitivity results
235  pressure->derivative(*_dwdx, pt, 0., dpdx1);
236  pressure->derivative(*_dwdt, pt, 0., dpdxdot1);
237 
238  // next, the analysis from the derivative functions
239  (*dpressure_dx) (pt, 0., dpdx2);
240  (*dpressure_dxdot)(pt, 0., dpdxdot2);
241 
242  BOOST_TEST_MESSAGE(" ***** dpress/dx (total) **");
243  BOOST_CHECK(MAST::compare_value( dpdx1, dpdx2, tol));
244 
245  BOOST_TEST_MESSAGE(" ***** dpress/dxdot (total) **");
246  BOOST_CHECK(MAST::compare_value( dpdxdot1, dpdxdot2, tol));
247 
248 
249  // now get sensitivity wrt all parameters
250  std::vector<MAST::Parameter*> params(4);
251  params[0] = _velocity;
252  params[1] = _mach;
253  params[2] = _rho_air;
254  params[3] = _gamma_air;
255 
256  // sensitivity of these two functions is only wrt 4 params
257  BOOST_TEST_MESSAGE(" ***** dpress_dx/dp (total) **");
258  check_value_sensitivity(*dpressure_dx, params);
259 
260  BOOST_TEST_MESSAGE(" ***** dpress_dxdot/dp (total) **");
261  check_value_sensitivity(*dpressure_dxdot, params);
262 
263 
264  // now add the two parameters to check the sensitivity of the pressure
265  params.push_back(_dwdx);
266  params.push_back(_dwdt);
267 
268  BOOST_TEST_MESSAGE(" ***** dpress/dp (total) **");
269  check_value_sensitivity(*pressure, params);
270 
271 }
272 
273 
274 
275 BOOST_AUTO_TEST_CASE (PistonTheory1D) {
276 
277  this->init(false, false); // keeping nonlinear strain off, since it does not influence piston theory
278  check_piston_theory_jacobian<MAST::BuildStructural1DElem>(*this);
279 
280 }
281 
282 BOOST_AUTO_TEST_SUITE_END()
283 
284 
285 
286 BOOST_FIXTURE_TEST_SUITE (Structural2DJacobianEvaluation, MAST::BuildStructural2DElem)
287 
288 BOOST_AUTO_TEST_CASE (PistonTheory2DQUAD4) {
289 
290  this->init(false, false, libMesh::QUAD4);
291  check_piston_theory_jacobian<MAST::BuildStructural2DElem>(*this);
292 }
293 
294 
295 BOOST_AUTO_TEST_CASE (PistonTheory2DTRI3) {
296 
297  this->init(false, false, libMesh::TRI3);
298  check_piston_theory_jacobian<MAST::BuildStructural2DElem>(*this);
299 }
300 
301 
302 BOOST_AUTO_TEST_SUITE_END()
303 
304 
const std::string & name() const
returns the name of this function
Definition: function_base.h:60
This is a scalar function whose value can be changed and one that can be used as a design variable in...
Definition: parameter.h:35
BOOST_FIXTURE_TEST_SUITE(PanelSmallDisturbanceFrequencyDomain2D, MAST::PanelInviscidSmallDisturbanceFrequencyDomain2DAnalysis) BOOST_AUTO_TEST_CASE(FreqDomainSensitivityWrtOmega)
bool compare_matrix(const RealMatrixX &m0, const RealMatrixX &m, const Real tol)
virtual void derivative(const MAST::FunctionBase &f, ValType &v) const
calculates the value of the function derivative and returns it in v.
libMesh::Real Real
void check_piston_theory_jacobian(ValType &v)
Matrix< Real, Dynamic, Dynamic > RealMatrixX
Matrix< Real, Dynamic, 1 > RealVectorX
std::unique_ptr< MAST::StructuralElementBase > build_structural_element(MAST::SystemInitialization &sys, const MAST::GeomElem &elem, const MAST::ElementPropertyCardBase &p)
builds the structural element for the specified element type
bool compare_value(const Real v0, const Real v, const Real tol)
BOOST_AUTO_TEST_CASE(PistonTheoryPressure)
void check_value_sensitivity(MAST::FieldFunction< Real > &func, std::vector< MAST::Parameter *> &params)