MAST
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
level_set_void_solution.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
27 #include "base/nonlinear_system.h"
29 #include "base/elem_base.h"
30 #include "mesh/geom_elem.h"
31 
32 // libMesh includes
33 #include "libmesh/petsc_nonlinear_solver.h"
34 #include "libmesh/petsc_vector.h"
35 #include "libmesh/dof_map.h"
36 
37 
38 // monitor function for PETSc solver so that
39 // the incompatible solution can be updated after each converged iterate
40 PetscErrorCode
42  PetscInt its,
43  PetscReal norm2,
44  void* ctx) {
45 
46  // convert the context pointer to the assembly object pointer
48 
49  // system for which this is being processed
50  MAST::NonlinearSystem& sys = sol_update->get_assembly().system();
51 
53  return 0;
54 
55  // if this is the first iteration, create a vector in system
56  // as the initial approximation of the system solution
57  if (its == 0) {
58  sys.add_vector("old_solution");
59  }
60  else {
61  // use the previous solution as the base solution
62 
63  // get the solution update from SNES
64  Vec dx;
65  PetscErrorCode ierr = SNESGetSolutionUpdate(snes, &dx);
66  libmesh_assert(!ierr);
67 
68  // attach the vector to a NumericVector object
69  std::unique_ptr<libMesh::NumericVector<Real> >
70  vec(new libMesh::PetscVector<Real>(dx, sys.comm())),
71  vec_scaled(vec->clone().release());
72 
73  // the solution update provided by SNES is -ve of the dX
74  // hence, scale the vector by -1
75  vec_scaled->scale(-1.);
76  vec_scaled->close();
77 
78  // ask the assembly to update the incompatible mode solution
79  // for all the 3D elements based on the solution update here
80  sol_update->update_void_solution(sys.get_vector("old_solution"),
81  *vec_scaled);
82  }
83 
84 
85 
86  // finally, update the solution
87  sys.get_vector("old_solution") = *sys.solution;
88  sys.get_vector("old_solution").close();
89 
90 
91  return 0;
92 }
93 
94 
95 
97 MAST::AssemblyBase::SolverMonitor(),
98 _assembly (nullptr),
99 _intersection (nullptr),
100 _dof_handler (nullptr) {
101 
102 
103 }
104 
105 
106 
108 
109  this->clear();
110 }
111 
112 
113 
114 
115 void
117  MAST::LevelSetIntersection &intersection,
118  MAST::LevelSetInterfaceDofHandler &dof_handler) {
119 
120  // should be cleared before initialization
121  libmesh_assert(!_assembly);
122 
123  _assembly = &assembly;
124  _intersection= &intersection;
125  _dof_handler = &dof_handler;
126 
127  // get the nonlinear solver SNES object from System and
128  // add a monitor to it so that it can be used to update the
129  // incompatible mode solution after each update
130 
131  libMesh::PetscNonlinearSolver<Real> &petsc_nonlinear_solver =
132  *(dynamic_cast<libMesh::PetscNonlinearSolver<Real>*>
133  (dynamic_cast<MAST::NonlinearSystem&>(assembly.system()).nonlinear_solver.get()));
134 
135 
136  // initialize the solver before getting the snes object
137  if (libMesh::on_command_line("--solver_system_names"))
138  petsc_nonlinear_solver.init((assembly.system().name()+"_").c_str());
139 
140  // get the SNES object
141  SNES snes = petsc_nonlinear_solver.snes();
142 
143  PetscErrorCode ierr =
144  SNESMonitorSet(snes,
146  (void*)this,
147  PETSC_NULL);
148 
149  libmesh_assert(!ierr);
150 }
151 
152 
153 
154 void
156 
157  if (_assembly) {
158 
159  // next, remove the monitor function from the snes object
160  libMesh::PetscNonlinearSolver<Real> &petsc_nonlinear_solver =
161  *(dynamic_cast<libMesh::PetscNonlinearSolver<Real>*>
162  (dynamic_cast<MAST::NonlinearSystem&>(_assembly->system()).nonlinear_solver.get()));
163 
164  // get the SNES object
165  SNES snes = petsc_nonlinear_solver.snes();
166 
167  PetscErrorCode ierr =
168  SNESMonitorCancel(snes);
169  libmesh_assert(!ierr);
170 
171  _assembly = nullptr;
172  _intersection = nullptr;
173  _dof_handler = nullptr;
174  }
175 }
176 
177 
178 
179 void
181 update_void_solution(libMesh::NumericVector<Real>& X,
182  libMesh::NumericVector<Real>& dX) {
183 
186 
188  sys = _assembly->system();
189 
192 
193  // iterate over each element, initialize it and get the relevant
194  // analysis quantities
196  sol,
197  dsol,
198  sub_elem_vec,
199  res;
200 
202  sub_elem_mat,
203  jac;
204 
205  std::vector<libMesh::dof_id_type>
206  dof_indices,
207  system_dofs,
208  free_dofs;
209 
210  const libMesh::DofMap& dof_map = sys.get_dof_map();
211 
212  std::unique_ptr<libMesh::NumericVector<Real> >
213  localized_solution (_assembly->build_localized_vector (sys, X).release()),
214  localized_dsolution(_assembly->build_localized_vector (sys, dX).release());
215 
216 
217  libMesh::MeshBase::const_element_iterator el =
218  sys.get_mesh().active_local_elements_begin();
219  const libMesh::MeshBase::const_element_iterator end_el =
220  sys.get_mesh().active_local_elements_end();
221 
222  for ( ; el != end_el; ++el) {
223 
224  const libMesh::Elem* elem = *el;
225  if (_dof_handler->if_factor_element(*elem)) {
226 
227  dof_map.dof_indices (elem, dof_indices);
228 
229  // get the solution from the system vector
230  unsigned int ndofs = (unsigned int)dof_indices.size();
231  sol.setZero(ndofs);
232  dsol.setZero(ndofs);
233  sub_elem_vec.setZero(ndofs);
234  res.setZero(ndofs);
235  sub_elem_mat.setZero(ndofs, ndofs);
236  jac.setZero(ndofs, ndofs);
237 
238  for (unsigned int i=0; i<dof_indices.size(); i++) {
239  sol(i) = (*localized_solution)(dof_indices[i]);
240  dsol(i) = (*localized_dsolution)(dof_indices[i]);
241  }
242 
244 
245  // get the intersection and compute the residual and jacobian
246  // with contribution from all elements.
247  _intersection->init(phi, *elem, sys.time,
248  sys.get_mesh().max_elem_id(),
249  sys.get_mesh().max_node_id());
250 
251  // the Jacobian is based on the homogenization method
252  MAST::GeomElem geom_elem;
253  elem_ops.set_elem_data(elem->dim(), *elem, geom_elem);
254  geom_elem.init(*elem, _assembly->system_init());
255 
256  elem_ops.init(geom_elem);
257  elem_ops.set_elem_solution(sol);
258  elem_ops.elem_calculations(true, res, jac);
259  elem_ops.clear_elem();
262  //res.setZero();
263 
264 
265  /*const std::vector<const libMesh::Elem *> &
266  elems_hi = _intersection->get_sub_elems_positive_phi();
267 
268  std::vector<const libMesh::Elem*>::const_iterator
269  hi_sub_elem_it = elems_hi.begin(),
270  hi_sub_elem_end = elems_hi.end();
271 
272  for (; hi_sub_elem_it != hi_sub_elem_end; hi_sub_elem_it++ ) {
273 
274  const libMesh::Elem* sub_elem = *hi_sub_elem_it;
275 
276  MAST::LevelSetIntersectedElem geom_elem;
277  ops.set_elem_data(elem->dim(), *elem, geom_elem);
278  geom_elem.init(*sub_elem, *_intersection);
279 
280  ops.init(geom_elem);
281  elem_ops.set_elem_solution(sol);
282 
283  // if the element has been marked for factorization,
284  // get the factorized jacobian and residual contributions
285  elem_ops.elem_calculations(true, sub_elem_vec, sub_elem_mat);
286 
287  //jac += sub_elem_mat;
288  res += sub_elem_vec;
289 
290  elem_ops.clear_elem();
291  }*/
292 
293  _intersection->clear();
294 
296  res,
297  jac,
298  sol,
299  dsol,
300  sol);
301  }
302  }
303 }
304 
const MAST::NonlinearSystem & system() const
void update_factored_element_solution(const libMesh::Elem &elem, const RealMatrixX &res, const RealMatrixX &jac, const RealMatrixX &sol, const RealMatrixX &dsol, RealVectorX &updated_sol)
PetscErrorCode _snes_level_set_void_solution_assembly_monitor_function(SNES snes, PetscInt its, PetscReal norm2, void *ctx)
virtual void init(MAST::AssemblyBase &assembly)
This class implements a system for solution of nonlinear systems.
void solution_of_factored_element(const libMesh::Elem &elem, RealVectorX &elem_sol)
updates the components of the solution vector in elem_sol for the void domain using the stored soluti...
bool if_factor_element(const libMesh::Elem &elem) const
virtual void set_elem_solution(const RealVectorX &sol)
sets the element solution
void init(const MAST::FieldFunction< Real > &phi, const libMesh::Elem &e, const Real t, unsigned int max_elem_id, unsigned int max_node_id)
MAST::LevelSetIntersection * _intersection
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 ...
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...
void update_void_solution(libMesh::NumericVector< Real > &X, libMesh::NumericVector< Real > &dX)
Matrix< Real, Dynamic, Dynamic > RealMatrixX
std::unique_ptr< libMesh::NumericVector< Real > > build_localized_vector(const libMesh::System &sys, const libMesh::NumericVector< Real > &global) const
localizes the parallel vector so that the local copy stores all values necessary for calculation of t...
This will compute the solution at the interface under the assumption of zero surface normal flux...
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.
MAST::LevelSetInterfaceDofHandler * _dof_handler
This class acts as a wrapper around libMesh::Elem for the purpose of providing a uniform interface fo...
Definition: geom_elem.h:59
MAST::SystemInitialization & system_init()
void init(const MAST::SystemInitialization &sys_init, MAST::LevelSetIntersection &intersection, MAST::FieldFunction< Real > &phi)
MAST::AssemblyBase & get_assembly()
virtual void clear_elem()
clears the element initialization
MAST::AssemblyElemOperations & get_elem_ops()
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
MAST::NonlinearSystem::Operation operation()
MAST::FieldFunction< Real > & get_level_set_function()
void clear()
clears the data structures