MAST
transient_assembly.cpp
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2019 Manav Bhatia
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
25 #include "base/nonlinear_system.h"
28 #include "numerics/utility.h"
29 #include "mesh/geom_elem.h"
30 
31 // libMesh includes
32 #include "libmesh/nonlinear_solver.h"
33 #include "libmesh/numeric_vector.h"
34 #include "libmesh/sparse_matrix.h"
35 #include "libmesh/dof_map.h"
36 
37 
38 
40 MAST::AssemblyBase (),
41 _post_assembly (nullptr) {
42 
43 }
44 
45 
46 
48 
49 }
50 
51 
52 
53 void
56 
57  _post_assembly = &post;
58 }
59 
60 
61 
62 void
64 residual_and_jacobian (const libMesh::NumericVector<Real>& X,
65  libMesh::NumericVector<Real>* R,
66  libMesh::SparseMatrix<Real>* J,
67  libMesh::NonlinearImplicitSystem& S) {
68 
69  libmesh_assert(_system);
70  libmesh_assert(_discipline);
71  libmesh_assert(_elem_ops);
72 
73 
75  &solver = dynamic_cast<MAST::TransientSolverBase&>(*_elem_ops);
77  transient_sys = _system->system();
78 
79  // make sure that the system for which this object was created,
80  // and the system passed through the function call are the same
81  libmesh_assert_equal_to(&S, &transient_sys);
82 
83  if (R) R->zero();
84  if (J) J->zero();
85 
86  // iterate over each element, initialize it and get the relevant
87  // analysis quantities
88  RealVectorX vec;
89  RealMatrixX mat;
90 
91  std::vector<libMesh::dof_id_type> dof_indices;
92  const libMesh::DofMap& dof_map = transient_sys.get_dof_map();
93 
94 
95 
96  // stores the localized solution, velocity, acceleration, etc. vectors.
97  // These pointers will have to be deleted
98  std::vector<libMesh::NumericVector<Real>*>
99  local_qtys;
100 
101  // if a solution function is attached, initialize it
102  if (_sol_function)
103  _sol_function->init( X);
104 
105  // ask the solver to localize the relevant solutions
106  solver.build_local_quantities(X, local_qtys);
107 
108  libMesh::MeshBase::const_element_iterator el =
109  transient_sys.get_mesh().active_local_elements_begin();
110  const libMesh::MeshBase::const_element_iterator end_el =
111  transient_sys.get_mesh().active_local_elements_end();
112 
113  for ( ; el != end_el; ++el) {
114 
115  const libMesh::Elem* elem = *el;
116 
117  dof_map.dof_indices (elem, dof_indices);
118 
119  MAST::GeomElem geom_elem;
120  solver.set_elem_data(elem->dim(), *elem, geom_elem);
121  geom_elem.init(*elem, *_system);
122 
123  solver.init(geom_elem);
124 
125  // get the solution
126  unsigned int ndofs = (unsigned int)dof_indices.size();
127  vec.setZero(ndofs);
128  mat.setZero(ndofs, ndofs);
129 
130  solver.set_element_data(dof_indices, local_qtys);
131 
132 // if (_sol_function)
133 // physics_elem->attach_active_solution_function(*_sol_function);
134 
135  // perform the element level calculations
136  solver.elem_calculations(J!=nullptr?true:false,
137  vec, mat);
138  solver.clear_elem();
139 
140  // copy to the libMesh matrix for further processing
141  DenseRealVector v;
142  DenseRealMatrix m;
143  if (R)
144  MAST::copy(v, vec);
145  if (J)
146  MAST::copy(m, mat);
147 
148  // constrain the quantities to account for hanging dofs,
149  // Dirichlet constraints, etc.
150  if (R && J)
151  dof_map.constrain_element_matrix_and_vector(m, v, dof_indices);
152  else if (R)
153  dof_map.constrain_element_vector(v, dof_indices);
154  else
155  dof_map.constrain_element_matrix(m, dof_indices);
156 
157  // add to the global matrices
158  if (R) R->add_vector(v, dof_indices);
159  if (J) J->add_matrix(m, dof_indices);
160  }
161 
162  // call the post assembly object, if provided by user
163  if (_post_assembly)
164  _post_assembly->post_assembly(X, R, J, S);
165 
166  // delete pointers to the local solutions
167  for (unsigned int i=0; i<local_qtys.size(); i++)
168  delete local_qtys[i];
169 
170  // if a solution function is attached, clear it
171  if (_sol_function)
172  _sol_function->clear();
173 
174  if (R) R->close();
175  if (J && close_matrix) J->close();
176 }
177 
178 
179 
180 
181 void
183 linearized_jacobian_solution_product (const libMesh::NumericVector<Real>& X,
184  const libMesh::NumericVector<Real>& dX,
185  libMesh::NumericVector<Real>& JdX,
186  libMesh::NonlinearImplicitSystem& S) {
187 
188  libmesh_assert(_system);
189  libmesh_assert(_discipline);
190  libmesh_assert(_elem_ops);
191 
193  &solver = dynamic_cast<MAST::TransientSolverBase&>(*_elem_ops);
195  &transient_sys = _system->system();
196 
197  // make sure that the system for which this object was created,
198  // and the system passed through the function call are the same
199  libmesh_assert_equal_to(&S, &transient_sys);
200 
201  JdX.zero();
202 
203  // iterate over each element, initialize it and get the relevant
204  // analysis quantities
205  RealVectorX vec;
206 
207  std::vector<libMesh::dof_id_type> dof_indices;
208  const libMesh::DofMap& dof_map = transient_sys.get_dof_map();
209 
210 
211  // stores the localized solution, velocity, acceleration, etc. vectors.
212  // These pointers will have to be deleted
213  std::vector<libMesh::NumericVector<Real>*>
214  local_qtys,
215  local_perturbed_qtys;
216 
217  // if a solution function is attached, initialize it
218  if (_sol_function)
219  _sol_function->init( X);
220 
221  // ask the solver to localize the relevant solutions
222  solver.build_local_quantities(X, local_qtys);
223  solver.build_perturbed_local_quantities(dX, local_perturbed_qtys);
224 
225  libMesh::MeshBase::const_element_iterator el =
226  transient_sys.get_mesh().active_local_elements_begin();
227  const libMesh::MeshBase::const_element_iterator end_el =
228  transient_sys.get_mesh().active_local_elements_end();
229 
230  for ( ; el != end_el; ++el) {
231 
232  const libMesh::Elem* elem = *el;
233 
234  dof_map.dof_indices (elem, dof_indices);
235 
236  MAST::GeomElem geom_elem;
237  _elem_ops->set_elem_data(elem->dim(), *elem, geom_elem);
238  geom_elem.init(*elem, *_system);
239 
240  _elem_ops->init(geom_elem);
241 
242  // get the solution
243  unsigned int ndofs = (unsigned int)dof_indices.size();
244  vec.setZero(ndofs);
245 
246 
247  solver.set_element_data(dof_indices, local_qtys);
248  solver.set_element_perturbed_data(dof_indices, local_perturbed_qtys);
249 
250 // if (_sol_function)
251 // physics_elem->attach_active_solution_function(*_sol_function);
252 
253  // perform the element level calculations
255 
256  solver.clear_elem();
257 
258  // copy to the libMesh matrix for further processing
259  DenseRealVector v;
260  MAST::copy(v, vec);
261 
262  // constrain the quantities to account for hanging dofs,
263  // Dirichlet constraints, etc.
264  dof_map.constrain_element_vector(v, dof_indices);
265 
266  // add to the global matrices
267  JdX.add_vector(v, dof_indices);
268  dof_indices.clear();
269  }
270 
271  // delete pointers to the local solutions
272  for (unsigned int i=0; i<local_qtys.size(); i++) {
273 
274  delete local_qtys[i];
275  delete local_perturbed_qtys[i];
276  }
277 
278  // if a solution function is attached, clear it
279  if (_sol_function)
280  _sol_function->clear();
281 
282  JdX.close();
283 }
284 
285 
286 
287 bool
290  libMesh::NumericVector<Real>& sensitivity_rhs) {
291 
292  libmesh_assert(_system);
293  libmesh_assert(_discipline);
294  libmesh_assert(_elem_ops);
295 
297  &solver = dynamic_cast<MAST::TransientSolverBase&>(*_elem_ops);
299  &nonlin_sys = _system->system();
300 
301  sensitivity_rhs.zero();
302 
303  // iterate over each element, initialize it and get the relevant
304  // analysis quantities
305  RealVectorX vec, vec2;
306  std::vector<RealVectorX> prev_local_sols;
307 
308  std::vector<libMesh::dof_id_type> dof_indices;
309  const libMesh::DofMap& dof_map = nonlin_sys.get_dof_map();
310 
311 
312  std::vector<libMesh::NumericVector<Real>*>
313  local_qtys,
314  prev_local_qtys;
315  solver.build_local_quantities(*nonlin_sys.solution, local_qtys);
316  solver.build_sensitivity_local_quantities(1, prev_local_qtys);
317 
318  // if a solution function is attached, initialize it
319  if (_sol_function)
320  _sol_function->init( *nonlin_sys.solution);
321 
322  libMesh::MeshBase::const_element_iterator el =
323  nonlin_sys.get_mesh().active_local_elements_begin();
324  const libMesh::MeshBase::const_element_iterator end_el =
325  nonlin_sys.get_mesh().active_local_elements_end();
326 
327  for ( ; el != end_el; ++el) {
328 
329  const libMesh::Elem* elem = *el;
330 
331  dof_map.dof_indices (elem, dof_indices);
332 
333  MAST::GeomElem geom_elem;
334  _elem_ops->set_elem_data(elem->dim(), *elem, geom_elem);
335  geom_elem.init(*elem, *_system);
336 
337  _elem_ops->init(geom_elem);
338 
339  // get the solution
340  unsigned int ndofs = (unsigned int)dof_indices.size();
341  vec.setZero(ndofs);
342  vec2.setZero(ndofs);
343 
344  solver.set_element_data(dof_indices, local_qtys);
345  solver.extract_element_sensitivity_data(dof_indices, prev_local_qtys, prev_local_sols);
346 
347  // if (_sol_function)
348  // physics_elem->attach_active_solution_function(*_sol_function);
349 
350  // perform the element level calculations
351  solver.elem_sensitivity_contribution_previous_timestep(prev_local_sols, vec2);
352  solver.elem_sensitivity_calculations(f, vec);
353 
354  vec += vec2;
355 
356  // physics_elem->detach_active_solution_function();
357  solver.clear_elem();
358 
359  // copy to the libMesh matrix for further processing
360  DenseRealVector v;
361  MAST::copy(v, vec);
362 
363  // constrain the quantities to account for hanging dofs,
364  // Dirichlet constraints, etc.
365  dof_map.constrain_element_vector(v, dof_indices);
366 
367  // add to the global matrices
368  sensitivity_rhs.add_vector(v, dof_indices);
369  dof_indices.clear();
370  }
371 
372  for (unsigned int i=0; i<local_qtys.size(); i++) {
373 
374  delete local_qtys[i];
375  delete prev_local_qtys[i];
376  }
377 
378  // if a solution function is attached, initialize it
379  if (_sol_function)
380  _sol_function->clear();
381 
382  sensitivity_rhs.close();
383 
384  return true;
385 }
386 
387 
MAST::AssemblyElemOperations * _elem_ops
provides assembly elem operations for use by this class
MAST::NonlinearSystem & system()
TransientAssembly()
constructor associates this assembly object with the system
libMesh::DenseMatrix< Real > DenseRealMatrix
This class implements a system for solution of nonlinear systems.
MAST::TransientAssembly::PostAssemblyOperation * _post_assembly
this object, if non-NULL is user-provided to perform actions after assembly and before returning to t...
bool close_matrix
flag to control the closing fo the Jacobian after assembly
MAST::SystemInitialization * _system
System for which this assembly is performed.
virtual void elem_sensitivity_calculations(const MAST::FunctionBase &f, RealVectorX &vec)=0
performs the element sensitivity calculations over elem, and returns the element residual sensitivity...
virtual void elem_calculations(bool if_jac, RealVectorX &vec, RealMatrixX &mat)=0
performs the element calculations over elem, and returns the element vector and matrix quantities in ...
MAST::PhysicsDisciplineBase * _discipline
PhysicsDisciplineBase object for which this class is assembling.
virtual ~TransientAssembly()
destructor resets the association of this assembly object with the system
virtual void set_elem_data(unsigned int dim, const libMesh::Elem &ref_elem, MAST::GeomElem &elem) const =0
some analyses may want to set additional element data before initialization of the GeomElem...
virtual void linearized_jacobian_solution_product(const libMesh::NumericVector< Real > &X, const libMesh::NumericVector< Real > &dX, libMesh::NumericVector< Real > &JdX, libMesh::NonlinearImplicitSystem &S)
calculates the product of the Jacobian and a perturbation in solution vector .
virtual void post_assembly(const libMesh::NumericVector< Real > &X, libMesh::NumericVector< Real > *R, libMesh::SparseMatrix< Real > *J, libMesh::NonlinearImplicitSystem &S)=0
libMesh::DenseVector< Real > DenseRealVector
Matrix< Real, Dynamic, Dynamic > RealMatrixX
virtual bool sensitivity_assemble(const MAST::FunctionBase &f, libMesh::NumericVector< Real > &sensitivity_rhs)
Assembly function.
void copy(DenseRealMatrix &m1, const RealMatrixX &m2)
Definition: utility.h:167
virtual void build_local_quantities(const libMesh::NumericVector< Real > &current_sol, std::vector< libMesh::NumericVector< Real > * > &qtys)
localizes the relevant solutions for system assembly.
virtual void build_sensitivity_local_quantities(unsigned int prev_iter, std::vector< libMesh::NumericVector< Real > * > &qtys)
localizes the relevant solutions for system assembly.
void clear()
clear the solution
Matrix< Real, Dynamic, 1 > RealVectorX
virtual void init(const MAST::GeomElem &elem)=0
initializes the object for calculation of element quantities for the specified elem.
This class acts as a wrapper around libMesh::Elem for the purpose of providing a uniform interface fo...
Definition: geom_elem.h:59
void set_post_assembly_operation(MAST::TransientAssembly::PostAssemblyOperation &post)
sets the PostAssemblyOperation object for use after assembly.
void init(const libMesh::NumericVector< Real > &sol, const libMesh::NumericVector< Real > *dsol=nullptr)
initializes the data structures to perform the interpolation function of sol.
virtual void clear_elem()
clears the element initialization
virtual void residual_and_jacobian(const libMesh::NumericVector< Real > &X, libMesh::NumericVector< Real > *R, libMesh::SparseMatrix< Real > *J, libMesh::NonlinearImplicitSystem &S)
function that assembles the matrices and vectors quantities for nonlinear solution ...
virtual void init(const libMesh::Elem &elem, const MAST::SystemInitialization &sys_init)
initialize the object for the specified reference elem.
Definition: geom_elem.cpp:128
user-provided object to perform actions after assembly and before returning to the solver...
virtual void elem_linearized_jacobian_solution_product(RealVectorX &vec)=0
performs the element calculations over elem, and returns the element vector quantity in vec...
MAST::MeshFieldFunction * _sol_function
system solution that will be initialized before each solution