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-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
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 
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...
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
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.
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...
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
bool if_factor_element(const libMesh::Elem &elem) const
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:128
MAST::NonlinearSystem::Operation operation()
MAST::FieldFunction< Real > & get_level_set_function()
const MAST::NonlinearSystem & system() const
void clear()
clears the data structures