MAST
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
level_set_nonlinear_implicit_assembly.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
26 #include "level_set/sub_cell_fe.h"
27 #include "level_set/filter_base.h"
30 #include "base/nonlinear_system.h"
34 #include "base/elem_base.h"
35 #include "numerics/utility.h"
36 
37 
38 // libMesh includes
39 #include "libmesh/nonlinear_solver.h"
40 #include "libmesh/numeric_vector.h"
41 #include "libmesh/sparse_matrix.h"
42 #include "libmesh/dof_map.h"
43 
44 
45 
47 LevelSetNonlinearImplicitAssembly(bool enable_dof_handler):
49 _enable_dof_handler (enable_dof_handler),
50 _evaluate_output_on_negative_phi (false),
51 _level_set (nullptr),
52 _indicator (nullptr),
53 _intersection (nullptr),
54 _dof_handler (nullptr),
55 _void_solution_monitor (nullptr),
56 _velocity (nullptr),
57 _filter (nullptr) {
58 
59 }
60 
61 
62 
64 
65  if (_intersection) delete _intersection;
66  if (_dof_handler) delete _dof_handler;
68 }
69 
70 
73 
74  libmesh_assert(_level_set);
75  return *_intersection;
76 }
77 
78 
79 
80 void
82 
84 }
85 
86 
87 bool
89  return _enable_dof_handler;
90 }
91 
92 
95 
96  libmesh_assert(_level_set);
97  libmesh_assert(_dof_handler);
98  return *_dof_handler;
99 }
100 
101 
102 void
105  const MAST::FilterBase& filter) {
106 
107  libmesh_assert(!_level_set);
108  libmesh_assert(!_intersection);
109  libmesh_assert(_system);
110 
111  _level_set = &level_set;
112  _filter = &filter;
114  if (_enable_dof_handler) {
119  }
120 }
121 
122 
123 
124 void
127 
128  libmesh_assert(!_indicator);
129  libmesh_assert(_system);
130 
131  _indicator = &indicator;
132 }
133 
134 
135 
136 void
138 
139  _level_set = nullptr;
140  _filter = nullptr;
141 
142  if (_intersection) {
143  delete _intersection;
144  delete _dof_handler;
145  delete _void_solution_monitor;
146 
147  _intersection = nullptr;
148  _dof_handler = nullptr;
149  _void_solution_monitor = nullptr;
150  }
151 }
152 
153 
154 
155 
156 void
159 
160  libmesh_assert(_level_set);
161  libmesh_assert(_intersection);
162  libmesh_assert(_system);
163  libmesh_assert(!_velocity);
164 
165  _velocity = &velocity;
166 }
167 
168 
169 
170 void
172 
173  _velocity = nullptr;
174 }
175 
176 
177 
178 #if MAST_ENABLE_PLPLOT == 1
179 
180 #include <numeric>
181 #include "plplot/plplot.h"
182 
183 void plot_elem(const libMesh::Elem& e) {
184 
185  unsigned int
186  n = e.n_nodes();
187 
189  x = RealVectorX::Zero(n+1),
190  y = RealVectorX::Zero(n+1);
191 
192  for (unsigned int i=0; i<n+1; i++) {
193  x(i) = e.point(i%n)(0);
194  y(i) = e.point(i%n)(1);
195  }
196 
197  plline(n+1, x.data(), y.data());
198  plflush();
199 }
200 
201 
202 void plot_points(const std::vector<libMesh::Point>& pts) {
203 
204  unsigned int
205  n = pts.size();
206 
208  x = RealVectorX::Zero(n),
209  y = RealVectorX::Zero(n);
210 
211  for (unsigned int i=0; i<n; i++) {
212  x(i) = pts[i](0);
213  y(i) = pts[i](1);
214  }
215 
216  plpoin(n, x.data(), y.data(), -1);
217  plflush();
218 }
219 
220 
221 void
222 MAST::LevelSetNonlinearImplicitAssembly::plot_sub_elems(bool plot_reference_elem,
223  bool plot_low_phi_elem,
224  bool plot_high_phi_elem) {
225 
226  libmesh_assert(_system);
227  libmesh_assert(_discipline);
228  libmesh_assert(_level_set);
229 
230  MAST::NonlinearSystem& nonlin_sys = _system->system();
231 
232 
233  libMesh::MeshBase::const_element_iterator el =
234  nonlin_sys.get_mesh().active_local_elements_begin();
235  const libMesh::MeshBase::const_element_iterator end_el =
236  nonlin_sys.get_mesh().active_local_elements_end();
237 
238 
239  plsdev("xwin");
240  plinit();
241  plenv(0,.3,0,.3,0,0);
242 
243 
244  for ( ; el != end_el; ++el) {
245 
246  const libMesh::Elem* elem = *el;
247 
248  {
249  MAST::FEBase fe(*_system);
250  fe.init(*elem);
251  const std::vector<Real>& JxW = fe.get_JxW();
252  std::cout << "==== original JxW: " << std::accumulate(JxW.begin(),
253  JxW.end(), 0.) << std::endl;
254  }
255 
256 
257  if (plot_reference_elem) {
258  plcol0(1); // red color for elements
259  plot_elem(*elem);
260  }
261 
262  _intersection->init(*_level_set, *elem, nonlin_sys.time);
263 
264  // now get elements on either side and plot
265  const std::vector<const libMesh::Elem *> &
268 
269 
270  if (plot_low_phi_elem) {
271 
272  for (unsigned int i = 0; i < elems_low.size(); i++) {
273 
274  plcol0(3); // green color for sub elements
275  plot_elem(*elems_low[i]);
276 
277  // create FE
278  std::unique_ptr<MAST::FEBase> fe(new MAST::SubCellFE(*_system, *_intersection));
279  fe->init(*elems_low[i]);
280  const std::vector<Real>& JxW = fe->get_JxW();
281  const std::vector<libMesh::Point>& xyz = fe->get_xyz();
282  std::cout << "low: JxW: " << std::accumulate(JxW.begin(),
283  JxW.end(), 0.) << std::endl;
284  plot_points(xyz);
285  }
286  }
287 
288 
289  if (plot_high_phi_elem) {
290 
291  for (unsigned int i=0; i<elems_hi.size(); i++) {
292 
293  plcol0(15); // white color for sub elements
294  plot_elem(*elems_hi[i]);
295 
296  // create FE
297  std::unique_ptr<MAST::FEBase> fe(new MAST::SubCellFE(*_system, *_intersection));
298  fe->init(*elems_hi[i]);
299  const std::vector<Real>& JxW = fe->get_JxW();
300  const std::vector<libMesh::Point>& xyz = fe->get_xyz();
301  std::cout << "hi: JxW: " << std::accumulate(JxW.begin(),
302  JxW.end(), 0.) << std::endl;
303  plot_points(xyz);
304  }
305  }
306 
307  _intersection->clear();
308  }
309 
310  // if a solution function is attached, clear it
311  if (_sol_function)
312  _sol_function->clear();
313 }
314 
315 #endif // HAVE_PLPLOT
316 
317 
318 
319 
320 void
322 residual_and_jacobian (const libMesh::NumericVector<Real>& X,
323  libMesh::NumericVector<Real>* R,
324  libMesh::SparseMatrix<Real>* J,
325  libMesh::NonlinearImplicitSystem& S) {
326 
327  libmesh_assert(_system);
328  libmesh_assert(_discipline);
329  libmesh_assert(_elem_ops);
330  libmesh_assert(_level_set);
331 
332  MAST::NonlinearSystem& nonlin_sys = _system->system();
333 
334  // make sure that the system for which this object was created,
335  // and the system passed through the function call are the same
336  libmesh_assert_equal_to(&S, &(nonlin_sys));
337 
338  if (R) R->zero();
339  if (J) J->zero();
340 
341  const Real
342  tol = 1.e-10;
343 
344  // iterate over each element, initialize it and get the relevant
345  // analysis quantities
347  vec,
348  sol,
349  sub_elem_vec,
350  res_factored_u,
351  nd_indicator = RealVectorX::Ones(1),
352  indicator = RealVectorX::Zero(1);
354  mat,
355  sub_elem_mat,
356  jac_factored_uu;
357 
358  std::vector<libMesh::dof_id_type>
359  dof_indices,
360  material_rows;
361  const libMesh::DofMap& dof_map = _system->system().get_dof_map();
362 
363 
364  std::unique_ptr<libMesh::NumericVector<Real> > localized_solution;
365  localized_solution.reset(build_localized_vector(nonlin_sys,
366  X).release());
367 
368 
369  // if a solution function is attached, initialize it
370  if (_sol_function)
371  _sol_function->init( X, false);
372 
373 
374  libMesh::MeshBase::const_element_iterator el =
375  nonlin_sys.get_mesh().active_local_elements_begin();
376  const libMesh::MeshBase::const_element_iterator end_el =
377  nonlin_sys.get_mesh().active_local_elements_end();
378 
380  &ops = dynamic_cast<MAST::NonlinearImplicitAssemblyElemOperations&>(*_elem_ops);
381 
382  for ( ; el != end_el; ++el) {
383 
384  const libMesh::Elem* elem = *el;
385 
386  _intersection->init(*_level_set, *elem, nonlin_sys.time,
387  nonlin_sys.get_mesh().max_elem_id(),
388  nonlin_sys.get_mesh().max_node_id());
389  dof_map.dof_indices (elem, dof_indices);
390 
391  // use the indicator if it was provided
392  if (_indicator) {
393 
394  nd_indicator.setZero(elem->n_nodes());
395  for (unsigned int i=0; i<elem->n_nodes(); i++) {
396  (*_indicator)(elem->node_ref(i), nonlin_sys.time, indicator);
397  nd_indicator(i) = indicator(0);
398  }
399  }
400 
401  unsigned int ndofs = (unsigned int)dof_indices.size();
402 
403  // Petsc needs that every diagonal term be provided some contribution,
404  // even if zero. Otherwise, it complains about lack of diagonal entry.
405  // So, if the element is NOT completely on the positive side, we still
406  // add a zero matrix to get around this issue.
408  nd_indicator.maxCoeff() < tol) && J) {
409 
410  DenseRealMatrix m(ndofs, ndofs);
411  //dof_map.constrain_element_matrix(m, dof_indices);
412  for (unsigned int i=0; i<ndofs; i++)
413  m(i,i) = 1.e-14;
414  dof_map.constrain_element_matrix(m, dof_indices);
415  J->add_matrix(m, dof_indices);
416  }
417 
418 
419  if (nd_indicator.maxCoeff() > tol &&
421 
422  // get the solution
423  sol.setZero(ndofs);
424  vec.setZero(ndofs);
425  sub_elem_vec.setZero(ndofs);
426  mat.setZero(ndofs, ndofs);
427  sub_elem_mat.setZero(ndofs, ndofs);
428 
429  for (unsigned int i=0; i<dof_indices.size(); i++)
430  sol(i) = (*localized_solution)(dof_indices[i]);
431 
432  // if the element has been marked for factorization then
433  // get the void solution from the storage
436 
437  // if the element has been marked for factorization,
438  // get the factorized jacobian and residual contributions
440 
441  // the Jacobian is based on the homogenizaton method to maintain
442  // a well conditioned global Jacobian.
443  MAST::GeomElem geom_elem;
444  ops.set_elem_data(elem->dim(), *elem, geom_elem);
445  geom_elem.init(*elem, *_system);
446 
447  ops.init(geom_elem);
448  ops.set_elem_solution(sol);
449  ops.elem_calculations(true, vec, mat);
450  ops.clear_elem();
452  // the residual based on homogenization is used for factorized
453  // elements since the factorization depends on exact Jacobian
454  // and the homogenization based Jacobian is not exact linearization
455  // of residual based on sub cells.
457 
459  mat,
460  vec,
461  material_rows,
462  jac_factored_uu,
463  res_factored_u);
464 
465  // zero the element matrix and update with the
466  // factored matrix
467  mat.setIdentity(); mat *= 1.e-6; // set a small value on the diagonal to avoid nans
468  vec.setZero();
469 
470  for (unsigned int i=0; i<material_rows.size(); i++) {
471 
472  vec(material_rows[i]) = res_factored_u(i);
473 
474  for (unsigned int j=0; j<material_rows.size(); j++)
475  mat(material_rows[i], material_rows[j]) = jac_factored_uu(i,j);
476  }
477  }
478  else {
479 
480  // get the residual from the sub elements
481  mat.setZero();
482  vec.setZero();
483 
484  const std::vector<const libMesh::Elem *> &
486 
487  std::vector<const libMesh::Elem*>::const_iterator
488  hi_sub_elem_it = elems_hi.begin(),
489  hi_sub_elem_end = elems_hi.end();
490 
491  for (; hi_sub_elem_it != hi_sub_elem_end; hi_sub_elem_it++ ) {
492 
493  const libMesh::Elem* sub_elem = *hi_sub_elem_it;
494 
496  ops.set_elem_data(elem->dim(), *elem, geom_elem);
497  geom_elem.init(*sub_elem, *_system, *_intersection);
498 
499  ops.init(geom_elem);
500  ops.set_elem_solution(sol);
501 
502  ops.elem_calculations(J!=nullptr?true:false, sub_elem_vec, sub_elem_mat);
503 
504  mat += sub_elem_mat;
505  vec += sub_elem_vec;
506 
507  ops.clear_elem();
508  }
509  }
510 
511  // copy to the libMesh matrix for further processing
512  DenseRealVector v;
513  DenseRealMatrix m;
514  if (R)
515  MAST::copy(v, vec);
516  if (J)
517  MAST::copy(m, mat);
518 
519  // constrain the quantities to account for hanging dofs,
520  // Dirichlet constraints, etc.
521  if (R && J)
522  dof_map.constrain_element_matrix_and_vector(m, v, dof_indices);
523  else if (R)
524  dof_map.constrain_element_vector(v, dof_indices);
525  else
526  dof_map.constrain_element_matrix(m, dof_indices);
527 
528  // add to the global matrices
529  if (R) R->add_vector(v, dof_indices);
530  if (J) J->add_matrix(m, dof_indices);
531  dof_indices.clear();
532  }
533 
534  _intersection->clear();
535  }
536 
537  // call the post assembly object, if provided by user
538  if (_post_assembly)
539  _post_assembly->post_assembly(X, R, J, S);
540 
541 
542  // if a solution function is attached, clear it
543  if (_sol_function)
544  _sol_function->clear();
545 
546  if (R) R->close();
547  if (J && close_matrix) J->close();
548 }
549 
550 
551 bool
553 sensitivity_assemble (const libMesh::NumericVector<Real>& X,
554  bool if_localize_sol,
555  const MAST::FunctionBase& f,
556  libMesh::NumericVector<Real>& sensitivity_rhs,
557  bool close_vector) {
558 
559  libmesh_assert(_system);
560  libmesh_assert(_discipline);
561  libmesh_assert(_elem_ops);
562  // we need the velocity for topology parameter
563  if (f.is_topology_parameter()) libmesh_assert(_velocity);
564 
565  // we need the velocity for topology parameter
567  *p_ls = nullptr;
568  if (f.is_topology_parameter()) {
569  libmesh_assert(_velocity);
570  p_ls = dynamic_cast<const MAST::LevelSetParameter*>(&f);
571  }
572 
573  MAST::NonlinearSystem& nonlin_sys = _system->system();
574 
575  sensitivity_rhs.zero();
576 
577  const Real
578  tol = 1.e-10;
579 
580  // iterate over each element, initialize it and get the relevant
581  // analysis quantities
583  vec1,
584  vec2,
585  vec_total,
586  sol,
587  res_factored_u,
588  nd_indicator = RealVectorX::Ones(1),
589  indicator = RealVectorX::Zero(1);
591  mat,
592  jac_factored_uu;
593 
594  std::vector<libMesh::dof_id_type>
595  dof_indices,
596  material_rows;
597  const libMesh::DofMap& dof_map = nonlin_sys.get_dof_map();
598 
599  const libMesh::NumericVector<Real>
600  *sol_vec = nullptr;
601 
602  std::unique_ptr<libMesh::NumericVector<Real> > localized_solution;
603 
604  if (if_localize_sol) {
605  localized_solution.reset(build_localized_vector(nonlin_sys, X).release());
606  sol_vec = localized_solution.get();
607  }
608  else
609  sol_vec = &X;
610 
611  // if a solution function is attached, initialize it
612  if (_sol_function)
613  _sol_function->init( *nonlin_sys.solution, false);
614 
615  libMesh::MeshBase::const_element_iterator el =
616  nonlin_sys.get_mesh().active_local_elements_begin();
617  const libMesh::MeshBase::const_element_iterator end_el =
618  nonlin_sys.get_mesh().active_local_elements_end();
619 
621  ops = dynamic_cast<MAST::NonlinearImplicitAssemblyElemOperations&>(*_elem_ops);
622 
623  for ( ; el != end_el; ++el) {
624 
625  const libMesh::Elem* elem = *el;
626 
627  // no sensitivity computation assembly is neeed in these cases
628  if (_param_dependence &&
629  // if object is specified and elem does not depend on it
631  continue;
632 
633  _intersection->init(*_level_set, *elem, nonlin_sys.time,
634  nonlin_sys.get_mesh().max_elem_id(),
635  nonlin_sys.get_mesh().max_node_id());
636 
637  dof_map.dof_indices (elem, dof_indices);
638 
639  // use the indicator if it was provided
640  if (_indicator) {
641 
642  nd_indicator.setZero(elem->n_nodes());
643  for (unsigned int i=0; i<elem->n_nodes(); i++) {
644  (*_indicator)(elem->node_ref(i), nonlin_sys.time, indicator);
645  nd_indicator(i) = indicator(0);
646  }
647  }
648 
649  if (nd_indicator.maxCoeff() > tol &&
651 
652  // get the solution
653  unsigned int ndofs = (unsigned int)dof_indices.size();
654  sol.setZero(ndofs);
655  vec_total.setZero(ndofs);
656  vec1.setZero(ndofs);
657  vec2.setZero(ndofs);
658 
659  for (unsigned int i=0; i<dof_indices.size(); i++)
660  sol(i) = (*sol_vec)(dof_indices[i]);
661 
662  // if the element has been marked for factorization then
663  // get the void solution from the storage
666 
667  const std::vector<const libMesh::Elem *> &
669 
670  std::vector<const libMesh::Elem*>::const_iterator
671  hi_sub_elem_it = elems_hi.begin(),
672  hi_sub_elem_end = elems_hi.end();
673 
674  for (; hi_sub_elem_it != hi_sub_elem_end; hi_sub_elem_it++ ) {
675 
676  const libMesh::Elem* sub_elem = *hi_sub_elem_it;
677 
679  ops.set_elem_data(elem->dim(), *elem, geom_elem);
680  geom_elem.init(*sub_elem, *_system, *_intersection);
681 
682  ops.init(geom_elem);
683  ops.set_elem_solution(sol);
684 
685  // if (_sol_function)
686  // physics_elem->attach_active_solution_function(*_sol_function);
687 
688  // perform the element level calculations
689  ops.elem_sensitivity_calculations(f, vec1);
690 
691  // if the quantity is also defined as a topology parameter,
692  // then calculate sensitivity from boundary movement.
693  if (f.is_topology_parameter()) {
694 
696  *_velocity,
697  vec2);
698  vec1 += vec2;
699  }
700  ops.clear_elem();
701 
702  // if the element has been identified for factoring then
703  // we will factor the residual and replace it in the
704  // residual vector. For this we need to compute the
705  // element Jacobian matrix
707 
708  vec2.setZero(ndofs);
709  mat.setZero(ndofs, ndofs);
710 
711  MAST::GeomElem geom_elem;
712  ops.set_elem_data(elem->dim(), *elem, geom_elem);
713  geom_elem.init(*elem, *_system);
714 
715  ops.init(geom_elem);
716  ops.set_elem_solution(sol);
717  ops.elem_calculations(true, vec2, mat);
718  ops.clear_elem();
720 
722  mat,
723  vec1,
724  material_rows,
725  jac_factored_uu,
726  res_factored_u);
727 
728  vec1.setZero();
729 
730  for (unsigned int i=0; i<material_rows.size(); i++)
731  vec1(material_rows[i]) = res_factored_u(i);
732  }
733 
734  vec_total += vec1;
735 
736 
737  // physics_elem->detach_active_solution_function();
738  ops.clear_elem();
739  }
740 
741  // copy to the libMesh matrix for further processing
742  DenseRealVector v;
743  MAST::copy(v, vec_total);
744 
745  // constrain the quantities to account for hanging dofs,
746  // Dirichlet constraints, etc.
747  dof_map.constrain_element_vector(v, dof_indices);
748 
749  // add to the global matrices
750  sensitivity_rhs.add_vector(v, dof_indices);
751  dof_indices.clear();
752  }
753 
754  _intersection->clear();
755  }
756 
757  // if a solution function is attached, initialize it
758  if (_sol_function)
759  _sol_function->clear();
760 
761  if (close_vector)
762  sensitivity_rhs.close();
763 
764  return true;
765 }
766 
767 
768 
769 
770 void
772 calculate_output(const libMesh::NumericVector<Real>& X,
773  bool if_localize_sol,
775 
776  libmesh_assert(_system);
777  libmesh_assert(_discipline);
778  libmesh_assert(_level_set);
779 
780  output.zero_for_analysis();
781 
782  MAST::NonlinearSystem& nonlin_sys = _system->system();
783  output.set_assembly(*this);
784 
785  const Real
786  tol = 1.e-10;
787 
789  sol,
790  nd_indicator = RealVectorX::Ones(1),
791  indicator = RealVectorX::Zero(1);
792 
793  std::vector<libMesh::dof_id_type> dof_indices;
794  const libMesh::DofMap& dof_map = _system->system().get_dof_map();
795 
796  const libMesh::NumericVector<Real>
797  *sol_vec = nullptr;
798 
799  std::unique_ptr<libMesh::NumericVector<Real> > localized_solution;
800 
801  if (if_localize_sol) {
802  localized_solution.reset(build_localized_vector(nonlin_sys, X).release());
803  sol_vec = localized_solution.get();
804  }
805  else
806  sol_vec = &X;
807 
808 
809  // if a solution function is attached, initialize it
810  //if (_sol_function)
811  // _sol_function->init( X, false);
812 
813 
814  libMesh::MeshBase::const_element_iterator el =
815  nonlin_sys.get_mesh().active_local_elements_begin();
816  const libMesh::MeshBase::const_element_iterator end_el =
817  nonlin_sys.get_mesh().active_local_elements_end();
818 
819 
820  for ( ; el != end_el; ++el) {
821 
822  const libMesh::Elem* elem = *el;
823 
824  // use the indicator if it was provided
825  if (_indicator) {
826 
827  nd_indicator.setZero(elem->n_nodes());
828  for (unsigned int i=0; i<elem->n_nodes(); i++) {
829  (*_indicator)(elem->node_ref(i), nonlin_sys.time, indicator);
830  nd_indicator(i) = indicator(0);
831  }
832  }
833 
834  _intersection->init(*_level_set, *elem, nonlin_sys.time,
835  nonlin_sys.get_mesh().max_elem_id(),
836  nonlin_sys.get_mesh().max_node_id());
837 
840 
841  dof_map.dof_indices (elem, dof_indices);
842 
843  // get the solution
844  unsigned int ndofs = (unsigned int)dof_indices.size();
845  sol.setZero(ndofs);
846 
847  for (unsigned int i=0; i<dof_indices.size(); i++)
848  sol(i) = (*sol_vec)(dof_indices[i]);
849 
850  // if the element has been marked for factorization then
851  // get the void solution from the storage
854 
855  const std::vector<const libMesh::Elem *> &
857 
858  std::vector<const libMesh::Elem*>::const_iterator
859  low_sub_elem_it = elems_low.begin(),
860  low_sub_elem_end = elems_low.end();
861 
862  for (; low_sub_elem_it != low_sub_elem_end; low_sub_elem_it++ ) {
863 
864  const libMesh::Elem* sub_elem = *low_sub_elem_it;
865 
866  // if (_sol_function)
867  // physics_elem->attach_active_solution_function(*_sol_function);
869  output.set_elem_data(elem->dim(), *elem, geom_elem);
870  geom_elem.init(*sub_elem, *_system, *_intersection);
871 
872  output.init(geom_elem);
873  output.set_elem_solution(sol);
874  output.evaluate();
875  output.clear_elem();
876  }
877  }
878 
879  if (nd_indicator.maxCoeff() > tol &&
881 
882  dof_map.dof_indices (elem, dof_indices);
883 
884  // get the solution
885  unsigned int ndofs = (unsigned int)dof_indices.size();
886  sol.setZero(ndofs);
887 
888  for (unsigned int i=0; i<dof_indices.size(); i++)
889  sol(i) = (*sol_vec)(dof_indices[i]);
890 
891  // if the element has been marked for factorization then
892  // get the void solution from the storage
895 
896  const std::vector<const libMesh::Elem *> &
897  //elems_low = intersect.get_sub_elems_negative_phi(),
899 
900  std::vector<const libMesh::Elem*>::const_iterator
901  hi_sub_elem_it = elems_hi.begin(),
902  hi_sub_elem_end = elems_hi.end();
903 
904  for (; hi_sub_elem_it != hi_sub_elem_end; hi_sub_elem_it++ ) {
905 
906  const libMesh::Elem* sub_elem = *hi_sub_elem_it;
907 
908  // if (_sol_function)
909  // physics_elem->attach_active_solution_function(*_sol_function);
911  output.set_elem_data(elem->dim(), *elem, geom_elem);
912  geom_elem.init(*sub_elem, *_system, *_intersection);
913 
914  output.init(geom_elem);
915  output.set_elem_solution(sol);
916  output.evaluate();
917  output.clear_elem();
918  }
919  }
920 
921  _intersection->clear();
922  }
923 
924  // if a solution function is attached, clear it
925  if (_sol_function)
926  _sol_function->clear();
927  output.clear_assembly();
928 }
929 
930 
931 
932 
933 void
935 calculate_output_derivative(const libMesh::NumericVector<Real>& X,
936  bool if_localize_sol,
938  libMesh::NumericVector<Real>& dq_dX) {
939 
940  libmesh_assert(_discipline);
941  libmesh_assert(_system);
942 
943  output.zero_for_sensitivity();
944 
945  MAST::NonlinearSystem& nonlin_sys = _system->system();
946  output.set_assembly(*this);
947 
948  dq_dX.zero();
949 
950  const Real
951  tol = 1.e-10;
952 
953  // iterate over each element, initialize it and get the relevant
954  // analysis quantities
956  vec1,
957  vec2,
958  vec_total,
959  sol,
960  res_factored_u,
961  nd_indicator = RealVectorX::Ones(1),
962  indicator = RealVectorX::Zero(1);
964  mat,
965  jac_factored_uu;
966 
967  std::vector<libMesh::dof_id_type>
968  dof_indices,
969  material_rows;
970  const libMesh::DofMap& dof_map = _system->system().get_dof_map();
971 
973  ops = dynamic_cast<MAST::NonlinearImplicitAssemblyElemOperations&>(*_elem_ops);
974 
975  const libMesh::NumericVector<Real>
976  *sol_vec = nullptr;
977 
978  std::unique_ptr<libMesh::NumericVector<Real> > localized_solution;
979 
980  if (if_localize_sol) {
981  localized_solution.reset(build_localized_vector(nonlin_sys, X).release());
982  sol_vec = localized_solution.get();
983  }
984  else
985  sol_vec = &X;
986 
987 
988  // if a solution function is attached, initialize it
989  if (_sol_function)
990  _sol_function->init( X, false);
991 
992 
993  libMesh::MeshBase::const_element_iterator el =
994  nonlin_sys.get_mesh().active_local_elements_begin();
995  const libMesh::MeshBase::const_element_iterator end_el =
996  nonlin_sys.get_mesh().active_local_elements_end();
997 
998 
999  for ( ; el != end_el; ++el) {
1000 
1001  const libMesh::Elem* elem = *el;
1002 
1003  _intersection->init(*_level_set, *elem, nonlin_sys.time,
1004  nonlin_sys.get_mesh().max_elem_id(),
1005  nonlin_sys.get_mesh().max_node_id());
1006 
1007  // use the indicator if it was provided
1008  if (_indicator) {
1009 
1010  nd_indicator.setZero(elem->n_nodes());
1011  for (unsigned int i=0; i<elem->n_nodes(); i++) {
1012  (*_indicator)(elem->node_ref(i), nonlin_sys.time, indicator);
1013  nd_indicator(i) = indicator(0);
1014  }
1015  }
1016 
1017 
1020 
1021  dof_map.dof_indices (elem, dof_indices);
1022 
1023  // get the solution
1024  unsigned int ndofs = (unsigned int)dof_indices.size();
1025  sol.setZero(ndofs);
1026  vec1.setZero(ndofs);
1027  vec2.setZero(ndofs);
1028  vec_total.setZero(ndofs);
1029 
1030  for (unsigned int i=0; i<dof_indices.size(); i++)
1031  sol(i) = (*sol_vec)(dof_indices[i]);
1032 
1033  // if the element has been marked for factorization then
1034  // get the void solution from the storage
1037 
1038  const std::vector<const libMesh::Elem *> &
1040 
1041  std::vector<const libMesh::Elem*>::const_iterator
1042  low_sub_elem_it = elems_low.begin(),
1043  low_sub_elem_end = elems_low.end();
1044 
1045  for (; low_sub_elem_it != low_sub_elem_end; low_sub_elem_it++ ) {
1046 
1047  const libMesh::Elem* sub_elem = *low_sub_elem_it;
1048 
1049  // if (_sol_function)
1050  // physics_elem->attach_active_solution_function(*_sol_function);
1051  MAST::LevelSetIntersectedElem geom_sub_elem;
1052  output.set_elem_data(elem->dim(), *elem, geom_sub_elem);
1053  geom_sub_elem.init(*sub_elem, *_system, *_intersection);
1054 
1055  output.init(geom_sub_elem);
1056  output.set_elem_solution(sol);
1057  output.output_derivative_for_elem(vec1);
1058  output.clear_elem();
1059 
1060  vec_total += vec1;
1061  }
1062 
1063  DenseRealVector v;
1064  MAST::copy(v, vec_total);
1065  dof_map.constrain_element_vector(v, dof_indices);
1066  dq_dX.add_vector(v, dof_indices);
1067  dof_indices.clear();
1068  }
1069 
1070 
1071  if (nd_indicator.maxCoeff() > tol &&
1073 
1074  dof_map.dof_indices (elem, dof_indices);
1075 
1076  // get the solution
1077  unsigned int ndofs = (unsigned int)dof_indices.size();
1078  sol.setZero(ndofs);
1079  vec1.setZero(ndofs);
1080  vec2.setZero(ndofs);
1081  vec_total.setZero(ndofs);
1082 
1083  for (unsigned int i=0; i<dof_indices.size(); i++)
1084  sol(i) = (*sol_vec)(dof_indices[i]);
1085 
1086  // if the element has been marked for factorization then
1087  // get the void solution from the storage
1090 
1091  const std::vector<const libMesh::Elem *> &
1093 
1094  std::vector<const libMesh::Elem*>::const_iterator
1095  hi_sub_elem_it = elems_hi.begin(),
1096  hi_sub_elem_end = elems_hi.end();
1097 
1098  for (; hi_sub_elem_it != hi_sub_elem_end; hi_sub_elem_it++ ) {
1099 
1100  const libMesh::Elem* sub_elem = *hi_sub_elem_it;
1101 
1102  // if (_sol_function)
1103  // physics_elem->attach_active_solution_function(*_sol_function);
1104  MAST::LevelSetIntersectedElem geom_sub_elem;
1105  output.set_elem_data(elem->dim(), *elem, geom_sub_elem);
1106  geom_sub_elem.init(*sub_elem, *_system, *_intersection);
1107 
1108  output.init(geom_sub_elem);
1109  output.set_elem_solution(sol);
1110  output.output_derivative_for_elem(vec1);
1111  output.clear_elem();
1112 
1113  if (_dof_handler && _dof_handler->if_factor_element(*elem)) {
1114 
1115  vec2.setZero(ndofs);
1116  mat.setZero(ndofs, ndofs);
1117 
1118  MAST::GeomElem geom_elem;
1119  ops.set_elem_data(elem->dim(), *elem, geom_elem);
1120  geom_elem.init(*elem, *_system);
1121 
1122  ops.init(geom_elem);
1123  ops.set_elem_solution(sol);
1124  ops.elem_calculations(true, vec2, mat);
1125  ops.clear_elem();
1127 
1129  mat.transpose(),
1130  vec1,
1131  material_rows,
1132  jac_factored_uu,
1133  res_factored_u);
1134 
1135  vec1.setZero();
1136 
1137  for (unsigned int i=0; i<material_rows.size(); i++)
1138  vec1(material_rows[i]) = res_factored_u(i);
1139  }
1140 
1141  vec_total += vec1;
1142  }
1143 
1144  DenseRealVector v;
1145  MAST::copy(v, vec_total);
1146  dof_map.constrain_element_vector(v, dof_indices);
1147  dq_dX.add_vector(v, dof_indices);
1148  dof_indices.clear();
1149  }
1150 
1151  _intersection->clear();
1152  }
1153 
1154  // if a solution function is attached, clear it
1155  if (_sol_function)
1156  _sol_function->clear();
1157 
1158  dq_dX.close();
1159  output.clear_assembly();
1160 }
1161 
1162 
1163 
1164 
1165 void
1167 calculate_output_direct_sensitivity(const libMesh::NumericVector<Real>& X,
1168  bool if_localize_sol,
1169  const libMesh::NumericVector<Real>* dXdp,
1170  bool if_localize_sol_sens,
1171  const MAST::FunctionBase& p,
1173 
1174  libmesh_assert(_system);
1175  libmesh_assert(_discipline);
1176  libmesh_assert(_level_set);
1177 
1178  // we need the velocity for topology parameter
1180  *p_ls = nullptr;
1181  if (p.is_topology_parameter()) {
1182  libmesh_assert(_velocity);
1183  p_ls = dynamic_cast<const MAST::LevelSetParameter*>(&p);
1184  }
1185 
1186  output.zero_for_sensitivity();
1187 
1188  MAST::NonlinearSystem& nonlin_sys = _system->system();
1189  output.set_assembly(*this);
1190 
1191  const Real
1192  tol = 1.e-10;
1193 
1194  // iterate over each element, initialize it and get the relevant
1195  // analysis quantities
1196  RealVectorX
1197  sol,
1198  dsol,
1199  nd_indicator = RealVectorX::Ones(1),
1200  indicator = RealVectorX::Zero(1);
1201 
1202  std::vector<libMesh::dof_id_type> dof_indices;
1203  const libMesh::DofMap& dof_map = _system->system().get_dof_map();
1204 
1205 
1206  const libMesh::NumericVector<Real>
1207  *sol_vec = nullptr,
1208  *dsol_vec = nullptr;
1209 
1210  std::unique_ptr<libMesh::NumericVector<Real> >
1211  localized_solution,
1212  localized_perturbed_solution;
1213 
1214  if (if_localize_sol) {
1215  localized_solution.reset(build_localized_vector(nonlin_sys, X).release());
1216  sol_vec = localized_solution.get();
1217  }
1218  else
1219  sol_vec = &X;
1220 
1221  if (if_localize_sol_sens) {
1222  localized_perturbed_solution.reset(build_localized_vector(nonlin_sys, *dXdp).release());
1223  dsol_vec = localized_perturbed_solution.get();
1224  }
1225  else
1226  dsol_vec = dXdp;
1227 
1228 
1229  // if a solution function is attached, initialize it
1230  //if (_sol_function)
1231  // _sol_function->init( X, false);
1232 
1233 
1234  libMesh::MeshBase::const_element_iterator el =
1235  nonlin_sys.get_mesh().active_local_elements_begin();
1236  const libMesh::MeshBase::const_element_iterator end_el =
1237  nonlin_sys.get_mesh().active_local_elements_end();
1238 
1239 
1240  for ( ; el != end_el; ++el) {
1241 
1242  const libMesh::Elem* elem = *el;
1243 
1244  // no sensitivity computation assembly is neeed in these cases
1245  if (_param_dependence &&
1246  // if object is specified and elem does not depend on it
1248  // and if no sol_sens is given
1249  (!dXdp ||
1250  // or if it can be ignored for elem
1251  (dXdp && _param_dependence->override_flag)))
1252  continue;
1253 
1254  // use the indicator if it was provided
1255  if (_indicator) {
1256 
1257  nd_indicator.setZero(elem->n_nodes());
1258  for (unsigned int i=0; i<elem->n_nodes(); i++) {
1259  (*_indicator)(elem->node_ref(i), nonlin_sys.time, indicator);
1260  nd_indicator(i) = indicator(0);
1261  }
1262  }
1263 
1264  _intersection->init(*_level_set, *elem, nonlin_sys.time,
1265  nonlin_sys.get_mesh().max_elem_id(),
1266  nonlin_sys.get_mesh().max_node_id());
1267 
1270 
1271  dof_map.dof_indices (elem, dof_indices);
1272 
1273 
1274  // get the solution
1275  unsigned int ndofs = (unsigned int)dof_indices.size();
1276  sol.setZero(ndofs);
1277  dsol.setZero(ndofs);
1278 
1279  for (unsigned int i=0; i<dof_indices.size(); i++) {
1280  sol(i) = (*sol_vec)(dof_indices[i]);
1281  if (dXdp)
1282  dsol(i) = (*dsol_vec)(dof_indices[i]);
1283  }
1284 
1285  // if the element has been marked for factorization then
1286  // get the void solution from the storage
1289 
1290  const std::vector<const libMesh::Elem *> &
1292 
1293  std::vector<const libMesh::Elem*>::const_iterator
1294  low_sub_elem_it = elems_low.begin(),
1295  low_sub_elem_end = elems_low.end();
1296 
1297  for (; low_sub_elem_it != low_sub_elem_end; low_sub_elem_it++ ) {
1298 
1299  const libMesh::Elem* sub_elem = *low_sub_elem_it;
1300 
1301  // if (_sol_function)
1302  // physics_elem->attach_active_solution_function(*_sol_function);
1304  output.set_elem_data(elem->dim(), *elem, geom_elem);
1305  geom_elem.init(*sub_elem, *_system, *_intersection);
1306 
1307  output.init(geom_elem);
1308  output.set_elem_solution(sol);
1309  output.set_elem_solution_sensitivity(dsol);
1310  output.evaluate_sensitivity(p);
1311  if (p.is_topology_parameter())
1313 
1314  output.clear_elem();
1315  }
1316  }
1317 
1318 
1319  if (nd_indicator.maxCoeff() > tol &&
1321 
1322  dof_map.dof_indices (elem, dof_indices);
1323 
1324 
1325  // get the solution
1326  unsigned int ndofs = (unsigned int)dof_indices.size();
1327  sol.setZero(ndofs);
1328  dsol.setZero(ndofs);
1329 
1330  for (unsigned int i=0; i<dof_indices.size(); i++) {
1331  sol(i) = (*sol_vec)(dof_indices[i]);
1332  if (dXdp)
1333  dsol(i) = (*dsol_vec)(dof_indices[i]);
1334  }
1335 
1336  // if the element has been marked for factorization then
1337  // get the void solution from the storage
1340 
1341  const std::vector<const libMesh::Elem *> &
1342  //elems_low = intersect.get_sub_elems_negative_phi(),
1344 
1345  std::vector<const libMesh::Elem*>::const_iterator
1346  hi_sub_elem_it = elems_hi.begin(),
1347  hi_sub_elem_end = elems_hi.end();
1348 
1349  for (; hi_sub_elem_it != hi_sub_elem_end; hi_sub_elem_it++ ) {
1350 
1351  const libMesh::Elem* sub_elem = *hi_sub_elem_it;
1352 
1353  // if (_sol_function)
1354  // physics_elem->attach_active_solution_function(*_sol_function);
1356  output.set_elem_data(elem->dim(), *elem, geom_elem);
1357  geom_elem.init(*sub_elem, *_system, *_intersection);
1358 
1359  output.init(geom_elem);
1360  output.set_elem_solution(sol);
1361  output.set_elem_solution_sensitivity(dsol);
1362  output.evaluate_sensitivity(p);
1363  if (p.is_topology_parameter())
1365 
1366  output.clear_elem();
1367  }
1368  }
1369 
1370  _intersection->clear();
1371  }
1372 
1373  // if a solution function is attached, clear it
1374  if (_sol_function)
1375  _sol_function->clear();
1376 
1377  output.clear_assembly();
1378 }
1379 
MAST::AssemblyElemOperations * _elem_ops
provides assembly elem operations for use by this class
MAST::NonlinearSystem & system()
const std::vector< const libMesh::Elem * > & get_sub_elems_positive_phi() const
void init(const libMesh::NumericVector< Real > &sol, bool reuse_vector)
initializes the data structures to perform the interpolation function of sol.
virtual bool if_elem_depends_on_parameter(const libMesh::Elem &e, const MAST::FunctionBase &p) const =0
libMesh::DenseMatrix< Real > DenseRealMatrix
virtual void init(MAST::AssemblyBase &assembly)
This class implements a system for solution of nonlinear systems.
This defines a parameter that is a level set function and stores a pointer to the node in the level-s...
bool override_flag
if true, assume zero solution sensitivity when elem does not dependent on parameter.
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_sensitivity(const RealVectorX &sol)
sets the element solution sensitivity
virtual void set_assembly(MAST::AssemblyBase &assembly)
sets the assembly object
virtual void init(const libMesh::Elem &elem, const MAST::SystemInitialization &sys_init)
This method should not get called for this class.
This provides the base class for definitin of element level contribution of output quantity in an ana...
LevelSetNonlinearImplicitAssembly(bool enable_dof_handler)
constructor associates this assembly object with the system
virtual void zero_for_sensitivity()=0
zeroes the output quantity values stored inside this object so that assembly process can begin...
bool close_matrix
flag to control the closing fo the Jacobian after assembly
virtual void set_indicator_function(MAST::FieldFunction< RealVectorX > &indicator)
attaches indicator function to this.
virtual void calculate_output_direct_sensitivity(const libMesh::NumericVector< Real > &X, bool if_localize_sol, const libMesh::NumericVector< Real > *dXdp, bool if_localize_sol_sens, const MAST::FunctionBase &p, MAST::OutputAssemblyElemOperations &output)
evaluates the sensitivity of the outputs in the attached discipline with respect to the parametrs in ...
virtual void set_elem_solution(const RealVectorX &sol)
sets the element solution
libMesh::Real Real
virtual void evaluate()=0
this is the abstract interface to be implemented by derived classes.
virtual void calculate_output(const libMesh::NumericVector< Real > &X, bool if_localize_sol, MAST::OutputAssemblyElemOperations &output)
calculates the value of quantity .
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::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 bool is_topology_parameter() const
Definition: function_base.h:97
virtual void clear_level_set_function()
clears association with level set function
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 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 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 post_assembly(const libMesh::NumericVector< Real > &X, libMesh::NumericVector< Real > *R, libMesh::SparseMatrix< Real > *J, libMesh::NonlinearImplicitSystem &S)=0
libMesh::DenseVector< Real > DenseRealVector
MAST::NonlinearImplicitAssembly::PostAssemblyOperation * _post_assembly
this object, if non-NULL is user-provided to perform actions after assembly and before returning to t...
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...
virtual void clear_assembly()
clears the assembly object
void copy(DenseRealMatrix &m1, const RealMatrixX &m2)
Definition: utility.h:167
This will compute the solution at the interface under the assumption of zero surface normal flux...
Creates a geometric filter for the level-set design variables.
Definition: filter_base.h:39
void element_factored_residual_and_jacobian(const libMesh::Elem &elem, const RealMatrixX &jac, const RealVectorX &res, std::vector< libMesh::dof_id_type > &material_dof_ids, RealMatrixX &jac_factored_uu, RealVectorX &res_factored_u)
factorizes the residual and jacobian into the components for the dofs on material nodes...
virtual void elem_topology_sensitivity_calculations(const MAST::FunctionBase &f, RealVectorX &vec)=0
performs the element topology sensitivity calculations over elem, and returns the element residual se...
void clear()
clear the solution
This class inherits from MAST::GeomElem and provides an interface to initialize FE objects on sub-ele...
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.
virtual void output_derivative_for_elem(RealVectorX &dq_dX)=0
returns the output quantity derivative with respect to state vector in dq_dX.
virtual void set_level_set_function(MAST::FieldFunction< Real > &level_set, const MAST::FilterBase &filter)
attaches level set function to this
const std::vector< const libMesh::Elem * > & get_sub_elems_negative_phi() const
virtual bool sensitivity_assemble(const libMesh::NumericVector< Real > &X, bool if_localize_sol, const MAST::FunctionBase &f, libMesh::NumericVector< Real > &sensitivity_rhs, bool close_vector=true)
Assembly function.
virtual void clear_level_set_velocity_function()
clears the velocity function
This class acts as a wrapper around libMesh::Elem for the purpose of providing a uniform interface fo...
Definition: geom_elem.h:59
virtual void init(const MAST::GeomElem &elem, bool init_grads, const std::vector< libMesh::Point > *pts=nullptr)
Initializes the quadrature and finite element for element volume integration.
Definition: fe_base.cpp:64
virtual void calculate_output_derivative(const libMesh::NumericVector< Real > &X, bool if_localize_sol, MAST::OutputAssemblyElemOperations &output, libMesh::NumericVector< Real > &dq_dX)
calculates
virtual void zero_for_analysis()=0
zeroes the output quantity values stored inside this object so that assembly process can begin...
void init(const MAST::SystemInitialization &sys_init, MAST::LevelSetIntersection &intersection, MAST::FieldFunction< Real > &phi)
MAST::AssemblyBase::ElemParameterDependence * _param_dependence
If provided by user, this object is used by sensitiivty analysis to check for whether or the current ...
virtual void clear_elem()
clears the element initialization
virtual const std::vector< Real > & get_JxW() const
Definition: fe_base.cpp:220
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
virtual void evaluate_topology_sensitivity(const MAST::FunctionBase &f)=0
this evaluates all relevant topological sensitivity components on the element.
virtual ~LevelSetNonlinearImplicitAssembly()
destructor resets the association of this assembly object with the system
This class specializes the MAST::FEBase class for level-set applications where integration is to be p...
Definition: sub_cell_fe.h:40
virtual void set_level_set_velocity_function(MAST::FieldFunction< RealVectorX > &velocity)
the velocity function used to calculate topology sensitivity
void set_evaluate_output_on_negative_phi(bool f)
sets the flag on whether or not to evaluate the output on negative level set function ...
virtual void evaluate_sensitivity(const MAST::FunctionBase &f)=0
this evaluates all relevant sensitivity components on the element.
void clear()
clears the data structures
MAST::MeshFieldFunction * _sol_function
system solution that will be initialized before each solution