MAST
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
mesh_field_function.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 // MAST includes
23 #include "base/nonlinear_system.h"
24 
25 // libMesh includes
26 #include "libmesh/dof_map.h"
27 
28 
31  const std::string& nm,
32  libMesh::ParallelType p_type):
34 _use_qp_sol (false),
35 _p_type (p_type),
36 _qp_sol (),
37 _sys (&sys.system()),
38 _function (nullptr),
39 _perturbed_function (nullptr)
40 { }
41 
42 
43 
45 MeshFieldFunction(libMesh::System& sys,
46  const std::string& nm,
47  libMesh::ParallelType p_type):
49 _use_qp_sol (false),
50 _p_type (p_type),
51 _qp_sol (),
52 _sys (&sys),
53 _function (nullptr),
54 _perturbed_function (nullptr)
55 { }
56 
57 
58 
59 
61 
62  this->clear();
63 }
64 
65 
66 
67 
68 
69 
70 
71 void
72 MAST::MeshFieldFunction::operator() (const libMesh::Point& p,
73  const Real t,
74  RealVectorX& v) const {
75 
76  // if the element has provided a quadrature point solution,
77  // then use it
78  if (_use_qp_sol) {
79  v = _qp_sol;
80  return;
81  }
82 
83  // make sure that the object was initialized
84  libmesh_assert(_function);
85 
86  unsigned int
87  n_vars = _sys->n_vars();
88 
89  DenseRealVector v1;
90  (*_function->_func)(p, t, v1);
91 
92  // make sure that the mesh function was able to find the element
93  // and a solution
94  libmesh_assert_equal_to(v1.size(), n_vars);
95 
96  // now copy this to the output vector
97  v = RealVectorX::Zero(n_vars);
98  for (unsigned int i=0; i<n_vars; i++)
99  v(i) = v1(i);
100 }
101 
102 
103 
104 void
105 MAST::MeshFieldFunction::gradient (const libMesh::Point& p,
106  const Real t,
107  RealMatrixX& v) const {
108 
109  // if the element has provided a quadrature point solution,
110  // then use it
111  if (_use_qp_sol) {
112  v = _qp_sol;
113  return;
114  }
115 
116  // make sure that the object was initialized
117  libmesh_assert(_function);
118 
119  unsigned int
120  n_vars = _sys->n_vars();
121 
122  std::vector<libMesh::Gradient> v1;
123  _function->_func->gradient(p, t, v1);
124 
125  // make sure that the mesh function was able to find the element
126  // and a solution
127  libmesh_assert_equal_to(v1.size(), n_vars);
128 
129  // now copy this to the output vector
130  v = RealMatrixX::Zero(n_vars, 3); // assume 3-dimensional by default
131  for (unsigned int i=0; i<n_vars; i++)
132  for (unsigned int j=0; j<3; j++)
133  v(i, j) = v1[i](j);
134 }
135 
136 
137 
138 void
140  const Real t,
141  RealVectorX& v) const {
142 
143  // if the element has provided a quadrature point solution,
144  // then use it
145  if (_use_qp_sol) {
146  v = _qp_sol;
147  return;
148  }
149 
150  // make sure that the object was initialized
151  libmesh_assert(_perturbed_function);
152 
153  unsigned int
154  n_vars = _sys->n_vars();
155 
156  DenseRealVector v1;
157  (*_perturbed_function->_func)(p, t, v1);
158 
159  // make sure that the mesh function was able to find the element
160  // and a solution
161  libmesh_assert_equal_to(v1.size(), n_vars);
162 
163  // now copy this to the output vector
164  v = RealVectorX::Zero(n_vars);
165  for (unsigned int i=0; i<n_vars; i++)
166  v(i) = v1(i);
167 }
168 
169 
170 void
172  const Real t,
173  RealMatrixX& v) const {
174 
175  // if the element has provided a quadrature point solution,
176  // then use it
177  if (_use_qp_sol) {
178  v = _qp_sol;
179  return;
180  }
181 
182  // make sure that the object was initialized
183  libmesh_assert(_function);
184 
185  unsigned int
186  n_vars = _sys->n_vars();
187 
188  std::vector<libMesh::Gradient> v1;
189  _perturbed_function->_func->gradient(p, t, v1);
190 
191  // make sure that the mesh function was able to find the element
192  // and a solution
193  libmesh_assert_equal_to(v1.size(), n_vars);
194 
195  // now copy this to the output vector
196  v = RealMatrixX::Zero(n_vars, 3); // assume 3-dimensional by default
197  for (unsigned int i=0; i<n_vars; i++)
198  for (unsigned int j=0; j<3; j++)
199  v(i, j) = v1[i](j);
200 }
201 
202 
203 
204 void
206  const libMesh::Point& p,
207  const Real t,
208  RealVectorX& v) const {
209 
210  // if the element has provided a quadrature point solution,
211  // then use it
212  if (_use_qp_sol) {
213  v = _qp_sol;
214  return;
215  }
216 
217  // make sure that the data for this function has been initialized
218  std::map<const MAST::FunctionBase*, MAST::MeshFieldFunction::SolFunc*>::const_iterator
219  it = _function_sens.find(&f);
220 
221  // make sure that the object was initialized
222  libmesh_assert(it != _function_sens.end());
223 
224  unsigned int
225  n_vars = _sys->n_vars();
226 
227  DenseRealVector v1;
228  (*it->second->_func)(p, t, v1);
229 
230  // make sure that the mesh function was able to find the element
231  // and a solution
232  libmesh_assert_equal_to(v1.size(), n_vars);
233 
234  // now copy this to the output vector
235  v = RealVectorX::Zero(n_vars);
236  for (unsigned int i=0; i<n_vars; i++)
237  v(i) = v1(i);
238 }
239 
240 
241 void
243  const libMesh::Point& p,
244  const Real t,
245  RealMatrixX& v) const {
246 
247  // if the element has provided a quadrature point solution,
248  // then use it
249  if (_use_qp_sol) {
250  v = _qp_sol;
251  return;
252  }
253 
254  // make sure that the data for this function has been initialized
255  std::map<const MAST::FunctionBase*, MAST::MeshFieldFunction::SolFunc*>::const_iterator
256  it = _function_sens.find(&f);
257 
258  // make sure that the object was initialized
259  libmesh_assert(it != _function_sens.end());
260 
261  unsigned int
262  n_vars = _sys->n_vars();
263 
264  std::vector<libMesh::Gradient> v1;
265  it->second->_func->gradient(p, t, v1);
266 
267  // make sure that the mesh function was able to find the element
268  // and a solution
269  libmesh_assert_equal_to(v1.size(), n_vars);
270 
271  // now copy this to the output vector
272  v = RealMatrixX::Zero(n_vars, 3); // assume 3-dimensional by default
273  for (unsigned int i=0; i<n_vars; i++)
274  for (unsigned int j=0; j<3; j++)
275  v(i, j) = v1[i](j);
276 }
277 
278 
279 
280 void
281 MAST::MeshFieldFunction::init(const libMesh::NumericVector<Real>& sol,
282  bool reuse_vector) {
283 
284  // first make sure that the object is not already initialized
285  libmesh_assert(!_function);
286 
288  _init_sol_func(reuse_vector, sol, *_function);
289 }
290 
291 
292 
293 void
295  const libMesh::NumericVector<Real>& sol,
296  bool reuse_vector) {
297 
298  // make sure the function has not already been initialized
299  std::map<const MAST::FunctionBase*, MAST::MeshFieldFunction::SolFunc*>::const_iterator
300  it = _function_sens.find(&f);
301 
302  // make sure that the object was initialized
303  libmesh_assert(it == _function_sens.end());
304 
306  _init_sol_func(reuse_vector, sol, *func);
307 
308  _function_sens[&f] = func;
309 }
310 
311 
312 
313 
314 void
316 
317  // if a pointer has been attached, then delete it and the
318  // associated vector, and clear the associated system
319  if (_function) {
320  delete _function;
321  _function = nullptr;
322  }
323 
324  if (_perturbed_function) {
325  delete _perturbed_function;
326  _perturbed_function = nullptr;
327  }
328 
329  // now clear all the sensitivity data
330  std::map<const MAST::FunctionBase*, MAST::MeshFieldFunction::SolFunc*>::const_iterator
331  it = _function_sens.begin(),
332  end = _function_sens.end();
333 
334  for ( ; it != end; it++)
335  delete it->second;
336 
337  _function_sens.clear();
338 
339  // clear flags for quadrature point solution
340  _use_qp_sol = false;
341 }
342 
343 
344 
345 
346 void
349 
350  _use_qp_sol = true;
351  _qp_sol = sol;
352 }
353 
354 
355 
356 void
359 
360  _use_qp_sol = false;
361  _qp_sol.setZero();
362 }
363 
364 
365 void
367  const libMesh::NumericVector<Real> &sol,
369 
370  // make sure it has not already been initialized
371  libmesh_assert(!sol_func._func);
372 
373  if (reuse_sol) {
374 
375  // make sure the given vector is of the same type as that specified for this object
376  libmesh_assert_equal_to(sol.type(), _p_type);
377  sol_func._sol = &sol;
378  }
379  else {
380 
381  sol_func._cloned_sol = libMesh::NumericVector<Real>::build(_sys->comm()).release();
382  sol_func._sol = sol_func._cloned_sol;
383 
384  switch (_p_type) {
385 
386  case libMesh::SERIAL: {
387  sol_func._cloned_sol->init(sol.size(), true, libMesh::SERIAL);
388  sol.localize(*sol_func._cloned_sol);
389  }
390  break;
391 
392  case libMesh::GHOSTED: {
393 
394  sol_func._cloned_sol->init(_sys->n_dofs(),
395  _sys->n_local_dofs(),
396  _sys->get_dof_map().get_send_list(),
397  true,
398  libMesh::GHOSTED);
399  sol.localize(*sol_func._cloned_sol, _sys->get_dof_map().get_send_list());
400  }
401  break;
402 
403  default:
404  // not implemented for other types.
405  libmesh_error();
406  break;
407  }
408  }
409 
410  // finally, create the mesh interpolation function
411  std::vector<unsigned int> vars;
412  _sys->get_all_variable_numbers(vars);
413 
414  sol_func._func = new libMesh::MeshFunction(_sys->get_equation_systems(),
415  *sol_func._sol,
416  _sys->get_dof_map(),
417  vars);
418  sol_func._func->init();
419 }
virtual void perturbation_gradient(const libMesh::Point &p, const Real t, RealMatrixX &v) const
calculates the value of the function at the specified point, p, and time, t, and returns it in v...
virtual void gradient(const libMesh::Point &p, const Real t, RealMatrixX &g) const
calculates the gradient of value of the function at the specified point, p, and time, t, and returns it in g.
virtual void perturbation(const libMesh::Point &p, const Real t, RealVectorX &v) const
calculates the value of perturbation in the function at the specified point, p, and time...
void init(const libMesh::NumericVector< Real > &sol, bool reuse_vector)
initializes the data structures to perform the interpolation function of sol.
void _init_sol_func(bool reuse_sol, const libMesh::NumericVector< Real > &sol, MAST::MeshFieldFunction::SolFunc &sol_func)
SolFunc * _function
current solution that is going to be interpolated
MeshFieldFunction(MAST::SystemInitialization &sys, const std::string &nm, libMesh::ParallelType p_type)
constructor
SolFunc * _perturbed_function
current perturbation solution that is going to be interpolated
virtual void derivative(const MAST::FunctionBase &f, const libMesh::Point &p, const Real t, RealVectorX &v) const
calculates the value of the function at the specified point, p, and time, t, and returns it in v...
libMesh::ParallelType _p_type
type of parallel vector required for this mesh function.
virtual void clear_element_quadrature_point_solution()
clears the quadrature point solution provided by the corresponding set method above.
libMesh::Real Real
virtual void derivative_gradient(const MAST::FunctionBase &f, const libMesh::Point &p, const Real t, RealMatrixX &v) const
calculates the value of the function at the specified point, p, and time, t, and returns it in v...
libMesh::NumericVector< Real > * _cloned_sol
RealVectorX _qp_sol
quadrature point solution of the element
virtual void set_element_quadrature_point_solution(RealVectorX &sol)
When a mesh field function is attached to an assembly routine during system assembly, then the current solution can be provided by the element quadrature point update.
libMesh::DenseVector< Real > DenseRealVector
Matrix< Real, Dynamic, Dynamic > RealMatrixX
virtual void operator()(const libMesh::Point &p, const Real t, RealVectorX &v) const
calculates the value of the function at the specified point, p, and time, t, and returns it in v...
This creates the base class for functions that have a saptial and temporal dependence, and provide sensitivity operations with respect to the functions and parameters.
void clear()
clear the solution
Matrix< Real, Dynamic, 1 > RealVectorX
const libMesh::NumericVector< Real > * _sol
bool _use_qp_sol
flag is set to true when the quadrature point solution is provided by an element
void init_sens(const MAST::FunctionBase &f, const libMesh::NumericVector< Real > &dsol, bool reuse_vector)
initializes the the data structures for computation of sensitivity for the specified function...
libMesh::System * _sys
current system for which solution is to be interpolated
virtual ~MeshFieldFunction()
destructor
std::map< const MAST::FunctionBase *, MAST::MeshFieldFunction::SolFunc * > _function_sens
solution sensitivity for specified value