Reference documentation for deal.II version GIT relicensing-487-ge9eb5ab491 2024-04-25 07:20:02+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
goal_oriented_elastoplasticity.h
Go to the documentation of this file.
1
155 *  
156 * @endcode
157 *
158 *
159 * <a name="elastoplastic.cc-Includefiles"></a>
160 * <h3>Include files</h3>
161 * The set of include files is not much of a surprise any more at this time:
162 *
163 * @code
164 *   #include <deal.II/base/conditional_ostream.h>
165 *   #include <deal.II/base/parameter_handler.h>
166 *   #include <deal.II/base/utilities.h>
167 *   #include <deal.II/base/index_set.h>
168 *   #include <deal.II/base/quadrature_lib.h>
169 *   #include <deal.II/base/function.h>
170 *   #include <deal.II/base/logstream.h>
171 *   #include <deal.II/base/timer.h>
172 *   #include <deal.II/base/table_handler.h>
173 *  
174 *   #include <deal.II/lac/vector.h>
175 *   #include <deal.II/lac/full_matrix.h>
176 *   #include <deal.II/lac/sparsity_tools.h>
177 *   #include <deal.II/lac/sparse_matrix.h>
178 *   #include <deal.II/lac/dynamic_sparsity_pattern.h>
179 *   #include <deal.II/lac/block_sparsity_pattern.h>
180 *   #include <deal.II/lac/solver_bicgstab.h>
181 *   #include <deal.II/lac/precondition.h>
182 *   #include <deal.II/lac/affine_constraints.h>
183 *   #include <deal.II/lac/trilinos_sparse_matrix.h>
184 *   #include <deal.II/lac/trilinos_block_sparse_matrix.h>
185 *   #include <deal.II/lac/trilinos_vector.h>
186 *   #include <deal.II/lac/trilinos_precondition.h>
187 *   #include <deal.II/lac/trilinos_solver.h>
188 *   #include <deal.II/lac/sparse_direct.h>
189 *  
190 *   #include <deal.II/grid/tria.h>
191 *   #include <deal.II/grid/grid_generator.h>
192 *   #include <deal.II/grid/grid_refinement.h>
193 *   #include <deal.II/grid/grid_tools.h>
194 *   #include <deal.II/grid/tria_accessor.h>
195 *   #include <deal.II/grid/tria_iterator.h>
196 *   #include <deal.II/grid/grid_out.h>
197 *   #include <deal.II/grid/manifold_lib.h>
198 *  
199 *   #include <deal.II/distributed/tria.h>
200 *   #include <deal.II/distributed/grid_refinement.h>
201 *   #include <deal.II/distributed/solution_transfer.h>
202 *  
203 *   #include <deal.II/dofs/dof_handler.h>
204 *   #include <deal.II/dofs/dof_accessor.h>
205 *   #include <deal.II/dofs/dof_renumbering.h>
206 *   #include <deal.II/dofs/dof_tools.h>
207 *  
208 *   #include <deal.II/fe/fe_q.h>
209 *   #include <deal.II/fe/fe_system.h>
210 *   #include <deal.II/fe/fe_values.h>
211 *   #include <deal.II/fe/fe_dgq.h>
212 *   #include <deal.II/fe/fe_tools.h>
213 *  
214 *   #include <deal.II/numerics/vector_tools.h>
215 *   #include <deal.II/numerics/matrix_tools.h>
216 *   #include <deal.II/numerics/data_out.h>
217 *   #include <deal.II/numerics/error_estimator.h>
218 *   #include <deal.II/numerics/fe_field_function.h>
219 *   #include <deal.II/numerics/solution_transfer.h>
220 *  
221 * @endcode
222 *
223 * And here the only two new things among the header files: an include file in
224 * which symmetric tensors of rank 2 and 4 are implemented, as introduced in
225 * the introduction:
226 *
227 * @code
228 *   #include <deal.II/base/symmetric_tensor.h>
229 *  
230 * @endcode
231 *
232 * And a header that implements filters for iterators looping over all
233 * cells. We will use this when selecting only those cells for output that are
234 * owned by the present process in a %parallel program:
235 *
236 * @code
237 *   #include <deal.II/grid/filtered_iterator.h>
238 *  
239 *   #include <fstream>
240 *   #include <iostream>
241 *  
242 * @endcode
243 *
244 * This final include file provides the <code>mkdir</code> function
245 * that we will use to create a directory for output files, if necessary:
246 *
247 * @code
248 *   #include <sys/stat.h>
249 *  
250 *   namespace ElastoPlastic
251 *   {
252 *   using namespace dealii;
253 *  
254 *   void
256 *   const unsigned int n_slices,
257 *   const double height,
258 *   Triangulation<3,3> &result)
259 *   {
260 * @endcode
261 *
262 * Assert (input.n_levels() == 1,
263 * ExcMessage ("The input triangulations must be coarse meshes."));
264 *
265 * @code
266 *   Assert(result.n_cells()==0, ExcMessage("resultin Triangulation need to be empty upon calling extrude_triangulation."));
267 *   Assert(height>0, ExcMessage("The height in extrude_triangulation needs to be positive."));
268 *   Assert(n_slices>=2, ExcMessage("The number of slices in extrude_triangulation needs to be at least 2."));
269 *  
270 *   std::vector<Point<3> > points(n_slices*input.n_used_vertices());
271 *   std::vector<CellData<3> > cells;
272 *   cells.reserve((n_slices-1)*input.n_active_cells());
273 *  
274 *   for (unsigned int slice=0; slice<n_slices; ++slice)
275 *   {
276 *   for (unsigned int i=0; i<input.n_vertices(); ++i)
277 *  
278 *   {
279 *   if (input.get_used_vertices()[i])
280 *   {
281 *   const Point<2> &v = input.get_vertices()[i];
282 *   points[i+slice*input.n_vertices()](0) = v(0);
283 *   points[i+slice*input.n_vertices()](1) = v(1);
284 *   points[i+slice*input.n_vertices()](2) = height * slice / (n_slices-1);
285 *   }
286 *   }
287 *   }
288 *  
290 *   cell = input.begin_active(); cell != input.end(); ++cell)
291 *   {
292 *   for (unsigned int slice=0; slice<n_slices-1; ++slice)
293 *   {
294 *   CellData<3> this_cell;
295 *   for (unsigned int v=0; v<GeometryInfo<2>::vertices_per_cell; ++v)
296 *   {
297 *   this_cell.vertices[v]
298 *   = cell->vertex_index(v)+slice*input.n_used_vertices();
299 *   this_cell.vertices[v+GeometryInfo<2>::vertices_per_cell]
300 *   = cell->vertex_index(v)+(slice+1)*input.n_used_vertices();
301 *   }
302 *  
303 *   this_cell.material_id = cell->material_id();
304 *   cells.push_back(this_cell);
305 *   }
306 *   }
307 *  
308 *   SubCellData s;
309 *   types::boundary_id bid=0;
310 *   s.boundary_quads.reserve(input.n_active_lines()*(n_slices-1) + input.n_active_cells()*2);
312 *   cell = input.begin_active(); cell != input.end(); ++cell)
313 *   {
314 *   CellData<2> quad;
315 *   for (unsigned int f=0; f<4; ++f)
316 *   if (cell->at_boundary(f))
317 *   {
318 *   quad.boundary_id = cell->face(f)->boundary_id();
319 *   bid = std::max(bid, quad.boundary_id);
320 *   for (unsigned int slice=0; slice<n_slices-1; ++slice)
321 *   {
322 *   quad.vertices[0] = cell->face(f)->vertex_index(0)+slice*input.n_used_vertices();
323 *   quad.vertices[1] = cell->face(f)->vertex_index(1)+slice*input.n_used_vertices();
324 *   quad.vertices[2] = cell->face(f)->vertex_index(0)+(slice+1)*input.n_used_vertices();
325 *   quad.vertices[3] = cell->face(f)->vertex_index(1)+(slice+1)*input.n_used_vertices();
326 *   s.boundary_quads.push_back(quad);
327 *   }
328 *   }
329 *   }
330 *  
332 *   cell = input.begin_active(); cell != input.end(); ++cell)
333 *   {
334 *   CellData<2> quad;
335 *   quad.boundary_id = bid + 1;
336 *   quad.vertices[0] = cell->vertex_index(0);
337 *   quad.vertices[1] = cell->vertex_index(1);
338 *   quad.vertices[2] = cell->vertex_index(2);
339 *   quad.vertices[3] = cell->vertex_index(3);
340 *   s.boundary_quads.push_back(quad);
341 *  
342 *   quad.boundary_id = bid + 2;
343 *   for (int i=0; i<4; ++i)
344 *   quad.vertices[i] += (n_slices-1)*input.n_used_vertices();
345 *   s.boundary_quads.push_back(quad);
346 *   }
347 *  
348 *   result.create_triangulation (points,
349 *   cells,
350 *   s);
351 *   }
352 *  
353 *   namespace Evaluation
354 *   {
355 *  
356 *  
357 *   template <int dim>
358 *   double get_von_Mises_stress(const SymmetricTensor<2, dim> &stress)
359 *   {
360 *  
361 * @endcode
362 *
363 * if (dim == 2)
364 * {
365 * von_Mises_stress = std::sqrt( stress[0][0]*stress[0][0]
366 * + stress[1][1]*stress[1][1]
367 * - stress[0][0]*stress[1][1]
368 * + 3*stress[0][1]*stress[0][1]);
369 * }else if (dim == 3)
370 * {
371 * von_Mises_stress = std::sqrt( stress[0][0]*stress[0][0]
372 * + stress[1][1]*stress[1][1]
373 * + stress[2][2]*stress[2][2]
374 * - stress[0][0]*stress[1][1]
375 * - stress[1][1]*stress[2][2]
376 * - stress[0][0]*stress[2][2]
377 * + 3*( stress[0][1]*stress[0][1]
378 * +stress[1][2]*stress[1][2]
379 * +stress[0][2]*stress[0][2]) );
380 * }
381 *
382
383 *
384 * -----------------------------------------------
385 * "Perforated_strip_tension"
386 * plane stress
387 * const double von_Mises_stress = std::sqrt( stress[0][0]*stress[0][0]
388 * + stress[1][1]*stress[1][1]
389 * - stress[0][0]*stress[1][1]
390 * + 3*stress[0][1]*stress[0][1]);
391 * -----------------------------------------------
392 * otherwise
393 * plane strain / 3d case
394 *
395 * @code
396 *   const double von_Mises_stress = std::sqrt(1.5) * (deviator(stress)).norm();
397 * @endcode
398 *
399 * -----------------------------------------------
400 *
401
402 *
403 *
404
405 *
406 *
407
408 *
409 *
410 * @code
411 *   return von_Mises_stress;
412 *   }
413 *  
414 *  
415 *   template <int dim>
416 *   class PointValuesEvaluation
417 *   {
418 *   public:
419 *   PointValuesEvaluation (const Point<dim> &evaluation_point);
420 *  
421 *   void compute (const DoFHandler<dim> &dof_handler,
422 *   const Vector<double> &solution,
423 *   Vector<double> &point_values);
424 *  
425 *   DeclException1 (ExcEvaluationPointNotFound,
426 *   Point<dim>,
427 *   << "The evaluation point " << arg1
428 *   << " was not found among the vertices of the present grid.");
429 *   private:
430 *   const Point<dim> evaluation_point;
431 *   };
432 *  
433 *  
434 *   template <int dim>
435 *   PointValuesEvaluation<dim>::
436 *   PointValuesEvaluation (const Point<dim> &evaluation_point)
437 *   :
438 *   evaluation_point (evaluation_point)
439 *   {}
440 *  
441 *  
442 *  
443 *   template <int dim>
444 *   void
445 *   PointValuesEvaluation<dim>::
446 *   compute (const DoFHandler<dim> &dof_handler,
447 *   const Vector<double> &solution,
448 *   Vector<double> &point_values)
449 *   {
450 *   const unsigned int dofs_per_vertex = dof_handler.get_fe().dofs_per_vertex;
451 *   AssertThrow (point_values.size() == dofs_per_vertex,
452 *   ExcDimensionMismatch (point_values.size(), dofs_per_vertex));
453 *   point_values = 1e20;
454 *  
456 *   cell = dof_handler.begin_active(),
457 *   endc = dof_handler.end();
458 *   bool evaluation_point_found = false;
459 *   for (; (cell!=endc) && !evaluation_point_found; ++cell)
460 *   {
461 *   if (cell->is_locally_owned() && !evaluation_point_found)
462 *   for (unsigned int vertex=0;
463 *   vertex<GeometryInfo<dim>::vertices_per_cell;
464 *   ++vertex)
465 *   {
466 *   if (cell->vertex(vertex).distance (evaluation_point)
467 *   <
468 *   cell->diameter() * 1e-8)
469 *   {
470 *   for (unsigned int id=0; id!=dofs_per_vertex; ++id)
471 *   {
472 *   point_values[id] = solution(cell->vertex_dof_index(vertex,id));
473 *   }
474 *  
475 *   evaluation_point_found = true;
476 *   break;
477 *   }
478 *   }
479 *   }
480 *  
481 *   AssertThrow (evaluation_point_found,
482 *   ExcEvaluationPointNotFound(evaluation_point));
483 *   }
484 *  
485 *  
486 *   }
487 *  
488 * @endcode
489 *
490 *
491 * <a name="elastoplastic.cc-ThecodePointHistorycodeclass"></a>
492 * <h3>The <code>PointHistory</code> class</h3>
493 *
494
495 *
496 * As was mentioned in the introduction, we have to store the old stress in
497 * quadrature point so that we can compute the residual forces at this point
498 * during the next time step. This alone would not warrant a structure with
499 * only one member, but in more complicated applications, we would have to
500 * store more information in quadrature points as well, such as the history
501 * variables of plasticity, etc. In essence, we have to store everything
502 * that affects the present state of the material here, which in plasticity
503 * is determined by the deformation history variables.
504 *
505
506 *
507 * We will not give this class any meaningful functionality beyond being
508 * able to store data, i.e. there are no constructors, destructors, or other
509 * member functions. In such cases of `dumb' classes, we usually opt to
510 * declare them as <code>struct</code> rather than <code>class</code>, to
511 * indicate that they are closer to C-style structures than C++-style
512 * classes.
513 *
514 * @code
515 *   template <int dim>
516 *   struct PointHistory
517 *   {
518 *   SymmetricTensor<2,dim> old_stress;
519 *   SymmetricTensor<2,dim> old_strain;
520 *   Point<dim> point;
521 *   };
522 *  
523 *  
524 * @endcode
525 *
526 *
527 * <a name="elastoplastic.cc-ThecodeConstitutiveLawcodeclasstemplate"></a>
528 * <h3>The <code>ConstitutiveLaw</code> class template</h3>
529 *
530
531 *
532 * This class provides an interface for a constitutive law, i.e., for the
533 * relationship between strain @f$\varepsilon(\mathbf u)@f$ and stress
534 * @f$\sigma@f$. In this example we are using an elastoplastic material behavior
535 * with linear, isotropic hardening. Such materials are characterized by
536 * Young's modulus @f$E@f$, Poisson's ratio @f$\nu@f$, the initial yield stress
537 * @f$\sigma_0@f$ and the isotropic hardening parameter @f$\gamma@f$. For @f$\gamma =
538 * 0@f$ we obtain perfect elastoplastic behavior.
539 *
540
541 *
542 * As explained in the paper that describes this program, the first Newton
543 * steps are solved with a completely elastic material model to avoid having
544 * to deal with both nonlinearities (plasticity and contact) at once. To this
545 * end, this class has a function <code>set_sigma_0()</code> that we use later
546 * on to simply set @f$\sigma_0@f$ to a very large value -- essentially
547 * guaranteeing that the actual stress will not exceed it, and thereby
548 * producing an elastic material. When we are ready to use a plastic model, we
549 * set @f$\sigma_0@f$ back to its proper value, using the same function. As a
550 * result of this approach, we need to leave <code>sigma_0</code> as the only
551 * non-const member variable of this class.
552 *
553 * @code
554 *   template <int dim>
555 *   class ConstitutiveLaw
556 *   {
557 *   public:
558 *   ConstitutiveLaw (const double E,
559 *   const double nu,
560 *   const double sigma_0,
561 *   const double gamma);
562 *  
563 *   void
564 *   set_sigma_0 (double sigma_zero);
565 *  
566 *   bool
567 *   get_stress_strain_tensor (const SymmetricTensor<2, dim> &strain_tensor,
568 *   SymmetricTensor<4, dim> &stress_strain_tensor) const;
569 *  
570 *   bool
571 *   get_grad_stress_strain_tensor (const SymmetricTensor<2, dim> &strain_tensor,
572 *   const std::vector<Tensor<2, dim> > &point_hessian,
573 *   Tensor<5, dim> &stress_strain_tensor_grad) const;
574 *  
575 *   void
576 *   get_linearized_stress_strain_tensors (const SymmetricTensor<2, dim> &strain_tensor,
577 *   SymmetricTensor<4, dim> &stress_strain_tensor_linearized,
578 *   SymmetricTensor<4, dim> &stress_strain_tensor) const;
579 *  
580 *   private:
581 *   const double kappa;
582 *   const double mu;
583 *   double sigma_0;
584 *   const double gamma;
585 *  
586 *   const SymmetricTensor<4, dim> stress_strain_tensor_kappa;
587 *   const SymmetricTensor<4, dim> stress_strain_tensor_mu;
588 *   };
589 *  
590 * @endcode
591 *
592 * The constructor of the ConstitutiveLaw class sets the required material
593 * parameter for our deformable body. Material parameters for elastic
594 * isotropic media can be defined in a variety of ways, such as the pair @f$E,
595 * \nu@f$ (elastic modulus and Poisson's number), using the Lame parameters
596 * @f$\lambda,mu@f$ or several other commonly used conventions. Here, the
597 * constructor takes a description of material parameters in the form of
598 * @f$E,\nu@f$, but since this turns out to these are not the coefficients that
599 * appear in the equations of the plastic projector, we immediately convert
600 * them into the more suitable set @f$\kappa,\mu@f$ of bulk and shear moduli. In
601 * addition, the constructor takes @f$\sigma_0@f$ (the yield stress absent any
602 * plastic strain) and @f$\gamma@f$ (the hardening parameter) as arguments. In
603 * this constructor, we also compute the two principal components of the
604 * stress-strain relation and its linearization.
605 *
606 * @code
607 *   template <int dim>
608 *   ConstitutiveLaw<dim>::ConstitutiveLaw (double E,
609 *   double nu,
610 *   double sigma_0,
611 *   double gamma)
612 *   :
613 * @endcode
614 *
615 * --------------------
616 * Plane stress
617 * kappa (((E*(1+2*nu)) / (std::pow((1+nu),2))) / (3 * (1 - 2 * (nu / (1+nu))))),
618 * mu (((E*(1+2*nu)) / (std::pow((1+nu),2))) / (2 * (1 + (nu / (1+nu))))),
619 * --------------------
620 * 3d and plane strain
621 *
622 * @code
623 *   kappa (E / (3 * (1 - 2 * nu))),
624 *   mu (E / (2 * (1 + nu))),
625 * @endcode
626 *
627 * --------------------
628 *
629 * @code
630 *   sigma_0(sigma_0),
631 *   gamma(gamma),
632 *   stress_strain_tensor_kappa (kappa
633 *   * outer_product(unit_symmetric_tensor<dim>(),
634 *   unit_symmetric_tensor<dim>())),
635 *   stress_strain_tensor_mu (2 * mu
636 *   * (identity_tensor<dim>()
637 *   - outer_product(unit_symmetric_tensor<dim>(),
638 *   unit_symmetric_tensor<dim>()) / 3.0))
639 *   {}
640 *  
641 *  
642 *   template <int dim>
643 *   void
644 *   ConstitutiveLaw<dim>::set_sigma_0 (double sigma_zero)
645 *   {
646 *   sigma_0 = sigma_zero;
647 *   }
648 *  
649 *  
650 * @endcode
651 *
652 *
653 * <a name="elastoplastic.cc-ConstitutiveLawget_stress_strain_tensor"></a>
654 * <h4>ConstitutiveLaw::get_stress_strain_tensor</h4>
655 *
656
657 *
658 * This is the principal component of the constitutive law. It projects the
659 * deviatoric part of the stresses in a quadrature point back to the yield
660 * stress (i.e., the original yield stress @f$\sigma_0@f$ plus the term that
661 * describes linear isotropic hardening). We need this function to calculate
662 * the nonlinear residual in PlasticityContactProblem::residual_nl_system. The
663 * computations follow the formulas laid out in the introduction.
664 *
665
666 *
667 * The function returns whether the quadrature point is plastic to allow for
668 * some statistics downstream on how many of the quadrature points are
669 * plastic and how many are elastic.
670 *
671 * @code
672 *   template <int dim>
673 *   bool
674 *   ConstitutiveLaw<dim>::
675 *   get_stress_strain_tensor (const SymmetricTensor<2, dim> &strain_tensor,
676 *   SymmetricTensor<4, dim> &stress_strain_tensor) const
677 *   {
678 *   SymmetricTensor<2, dim> stress_tensor;
679 *   stress_tensor = (stress_strain_tensor_kappa + stress_strain_tensor_mu)
680 *   * strain_tensor;
681 *  
682 * @endcode
683 *
684 * const SymmetricTensor<2, dim> deviator_stress_tensor = deviator(stress_tensor);
685 * const double deviator_stress_tensor_norm = deviator_stress_tensor.norm();
686 *
687 * @code
688 *   const double von_Mises_stress = Evaluation::get_von_Mises_stress(stress_tensor);
689 *  
690 *   stress_strain_tensor = stress_strain_tensor_mu;
691 *   if (von_Mises_stress > sigma_0)
692 *   {
693 *   const double beta = sigma_0 / von_Mises_stress;
694 *   stress_strain_tensor *= (gamma + (1 - gamma) * beta);
695 *   }
696 *  
697 *   stress_strain_tensor += stress_strain_tensor_kappa;
698 *  
699 *   return (von_Mises_stress > sigma_0);
700 *   }
701 *  
702 *  
703 *   template <int dim>
704 *   bool
705 *   ConstitutiveLaw<dim>::
706 *   get_grad_stress_strain_tensor (const SymmetricTensor<2, dim> &strain_tensor,
707 *   const std::vector<Tensor<2, dim> > &point_hessian,
708 *   Tensor<5, dim> &stress_strain_tensor_grad) const
709 *   {
710 *   SymmetricTensor<2, dim> stress_tensor;
711 *   stress_tensor = (stress_strain_tensor_kappa + stress_strain_tensor_mu)
712 *   * strain_tensor;
713 *  
714 *   const double von_Mises_stress = Evaluation::get_von_Mises_stress(stress_tensor);
715 *  
716 *   if (von_Mises_stress > sigma_0)
717 *   {
718 *   const SymmetricTensor<2, dim> deviator_strain_tensor = deviator(strain_tensor);
719 *   const double deviator_strain_tensor_norm = deviator_strain_tensor.norm();
720 *   const double multiplier = -(1-gamma)*sigma_0/(2*mu*std::pow(deviator_strain_tensor_norm,3));
721 *  
722 *   Vector<double> multiplier_vector(dim);
723 *   multiplier_vector = 0;
724 *  
725 *   for (unsigned int i=0; i!=dim; ++i)
726 *   for (unsigned int m=0; m!=dim; ++m)
727 *   for (unsigned int n=0; n!=dim; ++n)
728 *   {
729 *   multiplier_vector(i) += deviator_strain_tensor[m][n] *
730 *   ( 0.5*( point_hessian[m][n][i] + point_hessian[n][m][i] )
731 *   + ( m==n && dim==2 ? -1/dim*(point_hessian[0][0][i]
732 *   + point_hessian[1][1][i]) : 0 )
733 *   + ( m==n && dim==3 ? -1/dim*(point_hessian[0][0][i]
734 *   + point_hessian[1][1][i]
735 *   + point_hessian[2][2][i]) : 0 ) );
736 *   }
737 *  
738 * @endcode
739 *
740 * -----------------------------------------------
741 * "Perforated_strip_tension"
742 * plane stress
743 * const double VM_factor = std::sqrt(2);
744 * -----------------------------------------------
745 * otherwise
746 * plane strain / 3d case
747 *
748 * @code
749 *   const double VM_factor = std::sqrt(1.5);
750 * @endcode
751 *
752 * -----------------------------------------------
753 *
754
755 *
756 *
757 * @code
758 *   for (unsigned int i=0; i!=dim; ++i)
759 *   for (unsigned int j=0; j!=dim; ++j)
760 *   for (unsigned int k=0; k!=dim; ++k)
761 *   for (unsigned int l=0; l!=dim; ++l)
762 *   for (unsigned int m=0; m!=dim; ++m)
763 *   {
764 *   stress_strain_tensor_grad[i][j][k][l][m] = 1/VM_factor
765 *   * multiplier
766 *   * stress_strain_tensor_mu[i][j][k][l]
767 *   * multiplier_vector(m);
768 *   }
769 *  
770 *   }
771 *   else
772 *   {
773 *   stress_strain_tensor_grad = 0;
774 *   }
775 *  
776 *   return (von_Mises_stress > sigma_0);
777 *   }
778 *  
779 *  
780 * @endcode
781 *
782 *
783 * <a name="elastoplastic.cc-ConstitutiveLawget_linearized_stress_strain_tensors"></a>
784 * <h4>ConstitutiveLaw::get_linearized_stress_strain_tensors</h4>
785 *
786
787 *
788 * This function returns the linearized stress strain tensor, linearized
789 * around the solution @f$u^{i-1}@f$ of the previous Newton step @f$i-1@f$. The
790 * parameter <code>strain_tensor</code> (commonly denoted
791 * @f$\varepsilon(u^{i-1})@f$) must be passed as an argument, and serves as the
792 * linearization point. The function returns the derivative of the nonlinear
793 * constitutive law in the variable stress_strain_tensor, as well as the
794 * stress-strain tensor of the linearized problem in
795 * stress_strain_tensor_linearized. See
796 * PlasticityContactProblem::assemble_nl_system where this function is used.
797 *
798 * @code
799 *   template <int dim>
800 *   void
801 *   ConstitutiveLaw<dim>::
802 *   get_linearized_stress_strain_tensors (const SymmetricTensor<2, dim> &strain_tensor,
803 *   SymmetricTensor<4, dim> &stress_strain_tensor_linearized,
804 *   SymmetricTensor<4, dim> &stress_strain_tensor) const
805 *   {
806 *   SymmetricTensor<2, dim> stress_tensor;
807 *   stress_tensor = (stress_strain_tensor_kappa + stress_strain_tensor_mu)
808 *   * strain_tensor;
809 *  
810 *   stress_strain_tensor = stress_strain_tensor_mu;
811 *   stress_strain_tensor_linearized = stress_strain_tensor_mu;
812 *  
813 *   SymmetricTensor<2, dim> deviator_stress_tensor = deviator(stress_tensor);
814 *   const double deviator_stress_tensor_norm = deviator_stress_tensor.norm();
815 *   const double von_Mises_stress = Evaluation::get_von_Mises_stress(stress_tensor);
816 *  
817 *   if (von_Mises_stress > sigma_0)
818 *   {
819 *   const double beta = sigma_0 / von_Mises_stress;
820 *   stress_strain_tensor *= (gamma + (1 - gamma) * beta);
821 *   stress_strain_tensor_linearized *= (gamma + (1 - gamma) * beta);
822 *   deviator_stress_tensor /= deviator_stress_tensor_norm;
823 *   stress_strain_tensor_linearized -= (1 - gamma) * beta * 2 * mu
824 *   * outer_product(deviator_stress_tensor,
825 *   deviator_stress_tensor);
826 *   }
827 *  
828 *   stress_strain_tensor += stress_strain_tensor_kappa;
829 *   stress_strain_tensor_linearized += stress_strain_tensor_kappa;
830 *   }
831 *  
832 * @endcode
833 *
834 * Finally, below we will need a function that computes the rotation matrix
835 * induced by a displacement at a given point. In fact, of course, the
836 * displacement at a single point only has a direction and a magnitude, it
837 * is the change in direction and magnitude that induces rotations. In
838 * effect, the rotation matrix can be computed from the gradients of a
839 * displacement, or, more specifically, from the curl.
840 *
841
842 *
843 * The formulas by which the rotation matrices are determined are a little
844 * awkward, especially in 3d. For 2d, there is a simpler way, so we
845 * implement this function twice, once for 2d and once for 3d, so that we
846 * can compile and use the program in both space dimensions if so desired --
847 * after all, deal.II is all about dimension independent programming and
848 * reuse of algorithm thoroughly tested with cheap computations in 2d, for
849 * the more expensive computations in 3d. Here is one case, where we have to
850 * implement different algorithms for 2d and 3d, but then can write the rest
851 * of the program in a way that is independent of the space dimension.
852 *
853
854 *
855 * So, without further ado to the 2d implementation:
856 *
857 * @code
858 *   Tensor<2,2>
859 *   get_rotation_matrix (const std::vector<Tensor<1,2> > &grad_u)
860 *   {
861 * @endcode
862 *
863 * First, compute the curl of the velocity field from the gradients. Note
864 * that we are in 2d, so the rotation is a scalar:
865 *
866 * @code
867 *   const double curl = (grad_u[1][0] - grad_u[0][1]);
868 *  
869 * @endcode
870 *
871 * From this, compute the angle of rotation:
872 *
873 * @code
874 *   const double angle = std::atan (curl);
875 *  
876 * @endcode
877 *
878 * And from this, build the antisymmetric rotation matrix:
879 *
880 * @code
881 *   const double t[2][2] = {{ cos(angle), sin(angle) },
882 *   {-sin(angle), cos(angle) }
883 *   };
884 *   return Tensor<2,2>(t);
885 *   }
886 *  
887 *  
888 * @endcode
889 *
890 * The 3d case is a little more contrived:
891 *
892 * @code
893 *   Tensor<2,3>
894 *   get_rotation_matrix (const std::vector<Tensor<1,3> > &grad_u)
895 *   {
896 * @endcode
897 *
898 * Again first compute the curl of the velocity field. This time, it is a
899 * real vector:
900 *
901 * @code
902 *   const Point<3> curl (grad_u[2][1] - grad_u[1][2],
903 *   grad_u[0][2] - grad_u[2][0],
904 *   grad_u[1][0] - grad_u[0][1]);
905 *  
906 * @endcode
907 *
908 * From this vector, using its magnitude, compute the tangent of the angle
909 * of rotation, and from it the actual angle:
910 *
911 * @code
912 *   const double tan_angle = std::sqrt(curl*curl);
913 *   const double angle = std::atan (tan_angle);
914 *  
915 * @endcode
916 *
917 * Now, here's one problem: if the angle of rotation is too small, that
918 * means that there is no rotation going on (for example a translational
919 * motion). In that case, the rotation matrix is the identity matrix.
920 *
921
922 *
923 * The reason why we stress that is that in this case we have that
924 * <code>tan_angle==0</code>. Further down, we need to divide by that
925 * number in the computation of the axis of rotation, and we would get
926 * into trouble when dividing doing so. Therefore, let's shortcut this and
927 * simply return the identity matrix if the angle of rotation is really
928 * small:
929 *
930 * @code
931 *   if (angle < 1e-9)
932 *   {
933 *   static const double rotation[3][3]
934 *   = {{ 1, 0, 0}, { 0, 1, 0 }, { 0, 0, 1 } };
935 *   const Tensor<2,3> rot(rotation);
936 *   return rot;
937 *   }
938 *  
939 * @endcode
940 *
941 * Otherwise compute the real rotation matrix. The algorithm for this is
942 * not exactly obvious, but can be found in a number of books,
943 * particularly on computer games where rotation is a very frequent
944 * operation. Online, you can find a description at
945 * http://www.makegames.com/3drotation/ and (this particular form, with
946 * the signs as here) at
947 * http://www.gamedev.net/reference/articles/article1199.asp:
948 *
949 * @code
950 *   const double c = std::cos(angle);
951 *   const double s = std::sin(angle);
952 *   const double t = 1-c;
953 *  
954 *   const Point<3> axis = curl/tan_angle;
955 *   const double rotation[3][3]
956 *   = {{
957 *   t *axis[0] *axis[0]+c,
958 *   t *axis[0] *axis[1]+s *axis[2],
959 *   t *axis[0] *axis[2]-s *axis[1]
960 *   },
961 *   {
962 *   t *axis[0] *axis[1]-s *axis[2],
963 *   t *axis[1] *axis[1]+c,
964 *   t *axis[1] *axis[2]+s *axis[0]
965 *   },
966 *   {
967 *   t *axis[0] *axis[2]+s *axis[1],
968 *   t *axis[1] *axis[1]-s *axis[0],
969 *   t *axis[2] *axis[2]+c
970 *   }
971 *   };
972 *   return Tensor<2,3>(rotation);
973 *   }
974 *  
975 *  
976 * @endcode
977 *
978 * <h3>Equation data: Body forces, boundary forces,
979 * incremental boundary values</h3>
980 *
981
982 *
983 * The following should be relatively standard. We need classes for
984 * the boundary forcing term (which we here choose to be zero)
985 * and incremental boundary values.
986 *
987 * @code
988 *   namespace EquationData
989 *   {
990 *  
991 *   /*
992 *   template <int dim>
993 *   class BoundaryForce : public Function<dim>
994 *   {
995 *   public:
996 *   BoundaryForce ();
997 *  
998 *   virtual
999 *   double value (const Point<dim> &p,
1000 *   const unsigned int component = 0) const override;
1001 *  
1002 *   virtual
1003 *   void vector_value (const Point<dim> &p,
1004 *   Vector<double> &values) const override;
1005 *   };
1006 *  
1007 *   template <int dim>
1008 *   BoundaryForce<dim>::BoundaryForce ()
1009 *   :
1010 *   Function<dim>(dim)
1011 *   {}
1012 *  
1013 *  
1014 *   template <int dim>
1015 *   double
1016 *   BoundaryForce<dim>::value (const Point<dim> &,
1017 *   const unsigned int) const
1018 *   {
1019 *   return 0.;
1020 *   }
1021 *  
1022 *   template <int dim>
1023 *   void
1024 *   BoundaryForce<dim>::vector_value (const Point<dim> &p,
1025 *   Vector<double> &values) const
1026 *   {
1027 *   for (unsigned int c = 0; c < this->n_components; ++c)
1028 *   values(c) = BoundaryForce<dim>::value(p, c);
1029 *   }
1030 *  
1031 * @endcode
1032 *
1033 *
1034 * <a name="elastoplastic.cc-ThecodeBodyForcecodeclass"></a>
1035 * <h3>The <code>BodyForce</code> class</h3>
1036 * Body forces are generally mediated by one of the four basic
1037 * physical types of forces:
1038 * gravity, strong and weak interaction, and electromagnetism. Unless one
1039 * wants to consider subatomic objects (for which quasistatic deformation is
1040 * irrelevant and an inappropriate description anyway), only gravity and
1041 * electromagnetic forces need to be considered. Let us, for simplicity
1042 * assume that our body has a certain mass density, but is either
1043 * non-magnetic and not electrically conducting or that there are no
1044 * significant electromagnetic fields around. In that case, the body forces
1045 * are simply <code>rho g</code>, where <code>rho</code> is the material
1046 * density and <code>g</code> is a vector in negative z-direction with
1047 * magnitude 9.81 m/s^2. Both the density and <code>g</code> are defined in
1048 * the function, and we take as the density 7700 kg/m^3, a value commonly
1049 * assumed for steel.
1050 *
1051
1052 *
1053 * To be a little more general and to be able to do computations in 2d as
1054 * well, we realize that the body force is always a function returning a
1055 * <code>dim</code> dimensional vector. We assume that gravity acts along
1056 * the negative direction of the last, i.e. <code>dim-1</code>th
1057 * coordinate. The rest of the implementation of this function should be
1058 * mostly self-explanatory given similar definitions in previous example
1059 * programs. Note that the body force is independent of the location; to
1060 * avoid compiler warnings about unused function arguments, we therefore
1061 * comment out the name of the first argument of the
1062 * <code>vector_value</code> function:
1063 *
1064 * @code
1065 *   template <int dim>
1066 *   class BodyForce : public Function<dim>
1067 *   {
1068 *   public:
1069 *   BodyForce ();
1070 *  
1071 *   virtual
1072 *   void
1073 *   vector_value (const Point<dim> &p,
1074 *   Vector<double> &values) const override;
1075 *  
1076 *   virtual
1077 *   void
1078 *   vector_value_list (const std::vector<Point<dim> > &points,
1079 *   std::vector<Vector<double> > &value_list) const override;
1080 *   };
1081 *  
1082 *  
1083 *   template <int dim>
1084 *   BodyForce<dim>::BodyForce ()
1085 *   :
1086 *   Function<dim> (dim)
1087 *   {}
1088 *  
1089 *  
1090 *   template <int dim>
1091 *   inline
1092 *   void
1093 *   BodyForce<dim>::vector_value (const Point<dim> &p,
1094 *   Vector<double> &values) const
1095 *   {
1096 *   Assert (values.size() == dim,
1097 *   ExcDimensionMismatch (values.size(), dim));
1098 *  
1099 *   const double g = 9.81;
1100 *   const double rho = 7700;
1101 *  
1102 *   values = 0;
1103 *   values(dim-1) = -rho * g;
1104 *   }
1105 *  
1106 *  
1107 *  
1108 *   template <int dim>
1109 *   void
1110 *   BodyForce<dim>::vector_value_list (const std::vector<Point<dim> > &points,
1111 *   std::vector<Vector<double> > &value_list) const
1112 *   {
1113 *   const unsigned int n_points = points.size();
1114 *  
1115 *   Assert (value_list.size() == n_points,
1116 *   ExcDimensionMismatch (value_list.size(), n_points));
1117 *  
1118 *   for (unsigned int p=0; p<n_points; ++p)
1119 *   BodyForce<dim>::vector_value (points[p],
1120 *   value_list[p]);
1121 *   }
1122 *  
1123 * @endcode
1124 *
1125 *
1126 * <a name="elastoplastic.cc-ThecodeIncrementalBoundaryValuecodeclass"></a>
1127 * <h3>The <code>IncrementalBoundaryValue</code> class</h3>
1128 *
1129
1130 *
1131 * In addition to body forces, movement can be induced by boundary forces
1132 * and forced boundary displacement. The latter case is equivalent to forces
1133 * being chosen in such a way that they induce certain displacement.
1134 *
1135
1136 *
1137 * For quasistatic displacement, typical boundary forces would be pressure
1138 * on a body, or tangential friction against another body. We chose a
1139 * somewhat simpler case here: we prescribe a certain movement of (parts of)
1140 * the boundary, or at least of certain components of the displacement
1141 * vector. We describe this by another vector-valued function that, for a
1142 * given point on the boundary, returns the prescribed displacement.
1143 *
1144
1145 *
1146 * Since we have a time-dependent problem, the displacement increment of the
1147 * boundary equals the displacement accumulated during the length of the
1148 * timestep. The class therefore has to know both the present time and the
1149 * length of the present time step, and can then approximate the incremental
1150 * displacement as the present velocity times the present timestep.
1151 *
1152
1153 *
1154 * For the purposes of this program, we choose a simple form of boundary
1155 * displacement: we displace the top boundary with constant velocity
1156 * downwards. The rest of the boundary is either going to be fixed (and is
1157 * then described using an object of type <code>Functions::ZeroFunction</code>) or free
1158 * (Neumann-type, in which case nothing special has to be done). The
1159 * implementation of the class describing the constant downward motion
1160 * should then be obvious using the knowledge we gained through all the
1161 * previous example programs:
1162 *
1163 * @code
1164 *   template <int dim>
1165 *   class IncrementalBoundaryValues : public Function<dim>
1166 *   {
1167 *   public:
1168 *   IncrementalBoundaryValues (const double present_time,
1169 *   const double present_timestep);
1170 *  
1171 *   virtual
1172 *   void
1173 *   vector_value (const Point<dim> &p,
1174 *   Vector<double> &values) const override;
1175 *  
1176 *   virtual
1177 *   void
1178 *   vector_value_list (const std::vector<Point<dim> > &points,
1179 *   std::vector<Vector<double> > &value_list) const override;
1180 *  
1181 *   private:
1182 *   const double velocity;
1183 *   const double present_time;
1184 *   const double present_timestep;
1185 *   };
1186 *  
1187 *  
1188 *   template <int dim>
1189 *   IncrementalBoundaryValues<dim>::
1190 *   IncrementalBoundaryValues (const double present_time,
1191 *   const double present_timestep)
1192 *   :
1193 *   Function<dim> (dim),
1194 *   velocity (.1),
1195 *   present_time (present_time),
1196 *   present_timestep (present_timestep)
1197 *   {}
1198 *  
1199 *  
1200 *   template <int dim>
1201 *   void
1202 *   IncrementalBoundaryValues<dim>::
1203 *   vector_value (const Point<dim> &p,
1204 *   Vector<double> &values) const
1205 *   {
1206 *   Assert (values.size() == dim,
1207 *   ExcDimensionMismatch (values.size(), dim));
1208 *  
1209 *   values = 0;
1210 *   values(2) = -present_timestep * velocity;
1211 *   }
1212 *  
1213 *  
1214 *  
1215 *   template <int dim>
1216 *   void
1217 *   IncrementalBoundaryValues<dim>::
1218 *   vector_value_list (const std::vector<Point<dim> > &points,
1219 *   std::vector<Vector<double> > &value_list) const
1220 *   {
1221 *   const unsigned int n_points = points.size();
1222 *  
1223 *   Assert (value_list.size() == n_points,
1224 *   ExcDimensionMismatch (value_list.size(), n_points));
1225 *  
1226 *   for (unsigned int p=0; p<n_points; ++p)
1227 *   IncrementalBoundaryValues<dim>::vector_value (points[p],
1228 *   value_list[p]);
1229 *   }
1230 *   */
1231 *  
1232 * @endcode
1233 *
1234 * ----------------------------- TimoshenkoBeam ---------------------------------------
1235 *
1236 * @code
1237 *   /*
1238 *   template <int dim>
1239 *   class IncrementalBoundaryForce : public Function<dim>
1240 *   {
1241 *   public:
1242 *   IncrementalBoundaryForce (const double present_time,
1243 *   const double end_time);
1244 *  
1245 *   virtual
1246 *   void vector_value (const Point<dim> &p,
1247 *   Vector<double> &values) const override;
1248 *  
1249 *   virtual
1250 *   void
1251 *   vector_value_list (const std::vector<Point<dim> > &points,
1252 *   std::vector<Vector<double> > &value_list) const override;
1253 *   private:
1254 *   const double present_time,
1255 *   end_time,
1256 *   shear_force,
1257 *   length,
1258 *   depth,
1259 *   thickness;
1260 *   };
1261 *  
1262 *   template <int dim>
1263 *   IncrementalBoundaryForce<dim>::
1264 *   IncrementalBoundaryForce (const double present_time,
1265 *   const double end_time)
1266 *   :
1267 *   Function<dim>(dim),
1268 *   present_time (present_time),
1269 *   end_time (end_time),
1270 *   shear_force (2e4),
1271 *   length (.48),
1272 *   depth (.12),
1273 *   thickness (.01)
1274 *   {}
1275 *  
1276 *   template <int dim>
1277 *   void
1278 *   IncrementalBoundaryForce<dim>::vector_value (const Point<dim> &p,
1279 *   Vector<double> &values) const
1280 *   {
1281 *   AssertThrow (values.size() == dim,
1282 *   ExcDimensionMismatch (values.size(), dim));
1283 *   AssertThrow (dim == 2, ExcNotImplemented());
1284 *  
1285 * @endcode
1286 *
1287 * compute traction on the right face of Timoshenko beam problem, t_bar
1288 *
1289 * @code
1290 *   double inertia_moment = (thickness*std::pow(depth,3)) / 12;
1291 *  
1292 *   double x = p(0);
1293 *   double y = p(1);
1294 *  
1295 *   AssertThrow(std::fabs(x-length)<1e-12, ExcNotImplemented());
1296 *  
1297 *   values(0) = 0;
1298 *   values(1) = - shear_force/(2*inertia_moment) * ( depth*depth/4-y*y );
1299 *  
1300 * @endcode
1301 *
1302 * compute the fraction of imposed force
1303 *
1304 * @code
1305 *   const double frac = present_time/end_time;
1306 *  
1307 *   values *= frac;
1308 *   }
1309 *  
1310 *   template <int dim>
1311 *   void
1312 *   IncrementalBoundaryForce<dim>::
1313 *   vector_value_list (const std::vector<Point<dim> > &points,
1314 *   std::vector<Vector<double> > &value_list) const
1315 *   {
1316 *   const unsigned int n_points = points.size();
1317 *  
1318 *   Assert (value_list.size() == n_points,
1319 *   ExcDimensionMismatch (value_list.size(), n_points));
1320 *  
1321 *   for (unsigned int p=0; p<n_points; ++p)
1322 *   IncrementalBoundaryForce<dim>::vector_value (points[p],
1323 *   value_list[p]);
1324 *   }
1325 *  
1326 *  
1327 *   template <int dim>
1328 *   class BodyForce : public Functions::ZeroFunction<dim>
1329 *   {
1330 *   public:
1331 *   BodyForce () : Functions::ZeroFunction<dim> (dim) {}
1332 *   };
1333 *  
1334 *   template <int dim>
1335 *   class IncrementalBoundaryValues : public Function<dim>
1336 *   {
1337 *   public:
1338 *   IncrementalBoundaryValues (const double present_time,
1339 *   const double end_time);
1340 *  
1341 *   virtual
1342 *   void
1343 *   vector_value (const Point<dim> &p,
1344 *   Vector<double> &values) const override;
1345 *  
1346 *   virtual
1347 *   void
1348 *   vector_value_list (const std::vector<Point<dim> > &points,
1349 *   std::vector<Vector<double> > &value_list) const override;
1350 *  
1351 *   private:
1352 *   const double present_time,
1353 *   end_time,
1354 *   shear_force,
1355 *   Youngs_modulus,
1356 *   Poissons_ratio,
1357 *   length,
1358 *   depth,
1359 *   thickness;
1360 *   };
1361 *  
1362 *  
1363 *   template <int dim>
1364 *   IncrementalBoundaryValues<dim>::
1365 *   IncrementalBoundaryValues (const double present_time,
1366 *   const double end_time)
1367 *   :
1368 *   Function<dim> (dim),
1369 *   present_time (present_time),
1370 *   end_time (end_time),
1371 *   shear_force (2e4),
1372 *   Youngs_modulus (2.e11),
1373 *   Poissons_ratio (.3),
1374 *   length (.48),
1375 *   depth (.12),
1376 *   thickness (.01)
1377 *   {}
1378 *  
1379 *  
1380 *   template <int dim>
1381 *   void
1382 *   IncrementalBoundaryValues<dim>::
1383 *   vector_value (const Point<dim> &p,
1384 *   Vector<double> &values) const
1385 *   {
1386 *   AssertThrow (values.size() == dim,
1387 *   ExcDimensionMismatch (values.size(), dim));
1388 *   AssertThrow (dim == 2, ExcNotImplemented());
1389 *  
1390 *  
1391 * @endcode
1392 *
1393 * compute exact displacement of Timoshenko beam problem, u_bar
1394 *
1395 * @code
1396 *   double inertia_moment = (thickness*std::pow(depth,3)) / 12;
1397 *  
1398 *   double x = p(0);
1399 *   double y = p(1);
1400 *  
1401 *   double fac = shear_force / (6*Youngs_modulus*inertia_moment);
1402 *  
1403 *   values(0) = fac * y * ( (6*length-3*x)*x + (2+Poissons_ratio)*(y*y-depth*depth/4) );
1404 *   values(1) = -fac* ( 3*Poissons_ratio*y*y*(length-x) + 0.25*(4+5*Poissons_ratio)*depth*depth*x + (3*length-x)*x*x );
1405 *  
1406 * @endcode
1407 *
1408 * compute the fraction of imposed force
1409 *
1410 * @code
1411 *   const double frac = present_time/end_time;
1412 *  
1413 *   values *= frac;
1414 *   }
1415 *  
1416 *  
1417 *  
1418 *   template <int dim>
1419 *   void
1420 *   IncrementalBoundaryValues<dim>::
1421 *   vector_value_list (const std::vector<Point<dim> > &points,
1422 *   std::vector<Vector<double> > &value_list) const
1423 *   {
1424 *   const unsigned int n_points = points.size();
1425 *  
1426 *   Assert (value_list.size() == n_points,
1427 *   ExcDimensionMismatch (value_list.size(), n_points));
1428 *  
1429 *   for (unsigned int p=0; p<n_points; ++p)
1430 *   IncrementalBoundaryValues<dim>::vector_value (points[p],
1431 *   value_list[p]);
1432 *   }
1433 *   */
1434 *  
1435 * @endcode
1436 *
1437 * ------------------------- Thick_tube_internal_pressure ----------------------------------
1438 *
1439 * @code
1440 *   /*
1441 *   template <int dim>
1442 *   class IncrementalBoundaryForce : public Function<dim>
1443 *   {
1444 *   public:
1445 *   IncrementalBoundaryForce (const double present_time,
1446 *   const double end_time);
1447 *  
1448 *   virtual
1449 *   void vector_value (const Point<dim> &p,
1450 *   Vector<double> &values) const override;
1451 *  
1452 *   virtual
1453 *   void
1454 *   vector_value_list (const std::vector<Point<dim> > &points,
1455 *   std::vector<Vector<double> > &value_list) const override;
1456 *   private:
1457 *   const double present_time,
1458 *   end_time,
1459 *   pressure,
1460 *   inner_radius;
1461 *   };
1462 *  
1463 *   template <int dim>
1464 *   IncrementalBoundaryForce<dim>::
1465 *   IncrementalBoundaryForce (const double present_time,
1466 *   const double end_time)
1467 *   :
1468 *   Function<dim>(dim),
1469 *   present_time (present_time),
1470 *   end_time (end_time),
1471 *   pressure (0.6*2.4e8),
1472 * @endcode
1473 *
1474 * pressure (1.94e8),
1475 *
1476 * @code
1477 *   inner_radius(.1)
1478 *   {}
1479 *  
1480 *   template <int dim>
1481 *   void
1482 *   IncrementalBoundaryForce<dim>::vector_value (const Point<dim> &p,
1483 *   Vector<double> &values) const
1484 *   {
1485 *   AssertThrow (dim == 2, ExcNotImplemented());
1486 *   AssertThrow (values.size() == dim,
1487 *   ExcDimensionMismatch (values.size(), dim));
1488 *  
1489 *   const double eps = 1.e-7 * inner_radius,
1490 *   radius = p.norm();
1491 * @endcode
1492 *
1493 * compute traction on the inner boundary, t_bar
1494 *
1495 * @code
1496 *   AssertThrow(radius < (eps+inner_radius), ExcInternalError());
1497 *  
1498 *   const double theta = std::atan2(p(1),p(0));
1499 *  
1500 *   values(0) = pressure * std::cos(theta);
1501 *   values(1) = pressure * std::sin(theta);
1502 *  
1503 * @endcode
1504 *
1505 * compute the fraction of imposed force
1506 *
1507 * @code
1508 *   const double frac = present_time/end_time;
1509 *  
1510 *   values *= frac;
1511 *   }
1512 *  
1513 *   template <int dim>
1514 *   void
1515 *   IncrementalBoundaryForce<dim>::
1516 *   vector_value_list (const std::vector<Point<dim> > &points,
1517 *   std::vector<Vector<double> > &value_list) const
1518 *   {
1519 *   const unsigned int n_points = points.size();
1520 *  
1521 *   Assert (value_list.size() == n_points,
1522 *   ExcDimensionMismatch (value_list.size(), n_points));
1523 *  
1524 *   for (unsigned int p=0; p<n_points; ++p)
1525 *   IncrementalBoundaryForce<dim>::vector_value (points[p],
1526 *   value_list[p]);
1527 *   }
1528 *  
1529 *  
1530 *   template <int dim>
1531 *   class BodyForce : public Functions::ZeroFunction<dim>
1532 *   {
1533 *   public:
1534 *   BodyForce () : Functions::ZeroFunction<dim> (dim) {}
1535 *   };
1536 *  
1537 *  
1538 *   template <int dim>
1539 *   class IncrementalBoundaryValues : public Function<dim>
1540 *   {
1541 *   public:
1542 *   IncrementalBoundaryValues (const double present_time,
1543 *   const double end_time);
1544 *  
1545 *   virtual
1546 *   void
1547 *   vector_value (const Point<dim> &p,
1548 *   Vector<double> &values) const override;
1549 *  
1550 *   virtual
1551 *   void
1552 *   vector_value_list (const std::vector<Point<dim> > &points,
1553 *   std::vector<Vector<double> > &value_list) const override;
1554 *  
1555 *   private:
1556 *   const double present_time,
1557 *   end_time;
1558 *   };
1559 *  
1560 *  
1561 *   template <int dim>
1562 *   IncrementalBoundaryValues<dim>::
1563 *   IncrementalBoundaryValues (const double present_time,
1564 *   const double end_time)
1565 *   :
1566 *   Function<dim> (dim),
1567 *   present_time (present_time),
1568 *   end_time (end_time)
1569 *   {}
1570 *  
1571 *  
1572 *   template <int dim>
1573 *   void
1574 *   IncrementalBoundaryValues<dim>::
1575 *   vector_value (const Point<dim> &p,
1576 *   Vector<double> &values) const
1577 *   {
1578 *   AssertThrow (values.size() == dim,
1579 *   ExcDimensionMismatch (values.size(), dim));
1580 *   AssertThrow (dim == 2, ExcNotImplemented());
1581 *  
1582 *   values = 0.;
1583 *   }
1584 *  
1585 *  
1586 *  
1587 *   template <int dim>
1588 *   void
1589 *   IncrementalBoundaryValues<dim>::
1590 *   vector_value_list (const std::vector<Point<dim> > &points,
1591 *   std::vector<Vector<double> > &value_list) const
1592 *   {
1593 *   const unsigned int n_points = points.size();
1594 *  
1595 *   Assert (value_list.size() == n_points,
1596 *   ExcDimensionMismatch (value_list.size(), n_points));
1597 *  
1598 *   for (unsigned int p=0; p<n_points; ++p)
1599 *   IncrementalBoundaryValues<dim>::vector_value (points[p],
1600 *   value_list[p]);
1601 *   }
1602 *   */
1603 *  
1604 * @endcode
1605 *
1606 * ------------------------- Perforated_strip_tension ----------------------------------
1607 *
1608 * @code
1609 *   /*
1610 *   template <int dim>
1611 *   class IncrementalBoundaryForce : public Function<dim>
1612 *   {
1613 *   public:
1614 *   IncrementalBoundaryForce (const double present_time,
1615 *   const double end_time);
1616 *  
1617 *   virtual
1618 *   void vector_value (const Point<dim> &p,
1619 *   Vector<double> &values) const override;
1620 *  
1621 *   virtual
1622 *   void
1623 *   vector_value_list (const std::vector<Point<dim> > &points,
1624 *   std::vector<Vector<double> > &value_list) const override;
1625 *   private:
1626 *   const double present_time,
1627 *   end_time;
1628 *   };
1629 *  
1630 *   template <int dim>
1631 *   IncrementalBoundaryForce<dim>::
1632 *   IncrementalBoundaryForce (const double present_time,
1633 *   const double end_time)
1634 *   :
1635 *   Function<dim>(dim),
1636 *   present_time (present_time),
1637 *   end_time (end_time)
1638 *   {}
1639 *  
1640 *   template <int dim>
1641 *   void
1642 *   IncrementalBoundaryForce<dim>::vector_value (const Point<dim> &p,
1643 *   Vector<double> &values) const
1644 *   {
1645 *   AssertThrow (values.size() == dim,
1646 *   ExcDimensionMismatch (values.size(), dim));
1647 *  
1648 *   values = 0;
1649 *  
1650 * @endcode
1651 *
1652 * compute the fraction of imposed force
1653 *
1654 * @code
1655 *   const double frac = present_time/end_time;
1656 *  
1657 *   values *= frac;
1658 *   }
1659 *  
1660 *   template <int dim>
1661 *   void
1662 *   IncrementalBoundaryForce<dim>::
1663 *   vector_value_list (const std::vector<Point<dim> > &points,
1664 *   std::vector<Vector<double> > &value_list) const
1665 *   {
1666 *   const unsigned int n_points = points.size();
1667 *  
1668 *   Assert (value_list.size() == n_points,
1669 *   ExcDimensionMismatch (value_list.size(), n_points));
1670 *  
1671 *   for (unsigned int p=0; p<n_points; ++p)
1672 *   IncrementalBoundaryForce<dim>::vector_value (points[p],
1673 *   value_list[p]);
1674 *   }
1675 *  
1676 *  
1677 *   template <int dim>
1678 *   class BodyForce : public Functions::ZeroFunction<dim>
1679 *   {
1680 *   public:
1681 *   BodyForce () : Functions::ZeroFunction<dim> (dim) {}
1682 *   };
1683 *  
1684 *  
1685 *   template <int dim>
1686 *   class IncrementalBoundaryValues : public Function<dim>
1687 *   {
1688 *   public:
1689 *   IncrementalBoundaryValues (const double present_time,
1690 *   const double end_time);
1691 *  
1692 *   virtual
1693 *   void
1694 *   vector_value (const Point<dim> &p,
1695 *   Vector<double> &values) const override;
1696 *  
1697 *   virtual
1698 *   void
1699 *   vector_value_list (const std::vector<Point<dim> > &points,
1700 *   std::vector<Vector<double> > &value_list) const override;
1701 *  
1702 *   private:
1703 *   const double present_time,
1704 *   end_time,
1705 *   imposed_displacement,
1706 *   height;
1707 *   };
1708 *  
1709 *  
1710 *   template <int dim>
1711 *   IncrementalBoundaryValues<dim>::
1712 *   IncrementalBoundaryValues (const double present_time,
1713 *   const double end_time)
1714 *   :
1715 *   Function<dim> (dim),
1716 *   present_time (present_time),
1717 *   end_time (end_time),
1718 *   imposed_displacement (0.00055),
1719 *   height (0.18)
1720 *   {}
1721 *  
1722 *  
1723 *   template <int dim>
1724 *   void
1725 *   IncrementalBoundaryValues<dim>::
1726 *   vector_value (const Point<dim> &p,
1727 *   Vector<double> &values) const
1728 *   {
1729 *   AssertThrow (values.size() == dim,
1730 *   ExcDimensionMismatch (values.size(), dim));
1731 *  
1732 *   const double eps = 1.e-8 * height;
1733 *  
1734 *   values = 0.;
1735 *  
1736 * @endcode
1737 *
1738 * impose displacement only on the top edge
1739 *
1740 * @code
1741 *   if (std::abs(p[1]-height) < eps)
1742 *   {
1743 * @endcode
1744 *
1745 * compute the fraction of imposed displacement
1746 *
1747 * @code
1748 *   const double inc_frac = 1/end_time;
1749 *  
1750 *   values(1) = inc_frac*imposed_displacement;
1751 *   }
1752 *  
1753 *   }
1754 *  
1755 *  
1756 *  
1757 *   template <int dim>
1758 *   void
1759 *   IncrementalBoundaryValues<dim>::
1760 *   vector_value_list (const std::vector<Point<dim> > &points,
1761 *   std::vector<Vector<double> > &value_list) const
1762 *   {
1763 *   const unsigned int n_points = points.size();
1764 *  
1765 *   Assert (value_list.size() == n_points,
1766 *   ExcDimensionMismatch (value_list.size(), n_points));
1767 *  
1768 *   for (unsigned int p=0; p<n_points; ++p)
1769 *   IncrementalBoundaryValues<dim>::vector_value (points[p],
1770 *   value_list[p]);
1771 *   }
1772 *   */
1773 *  
1774 * @endcode
1775 *
1776 * ------------------------- Cantiliver_beam_3d ----------------------------------
1777 *
1778 * @code
1779 *   template <int dim>
1780 *   class IncrementalBoundaryForce : public Function<dim>
1781 *   {
1782 *   public:
1783 *   IncrementalBoundaryForce (const double present_time,
1784 *   const double end_time);
1785 *  
1786 *   virtual
1787 *   void vector_value (const Point<dim> &p,
1788 *   Vector<double> &values) const override;
1789 *  
1790 *   virtual
1791 *   void
1792 *   vector_value_list (const std::vector<Point<dim> > &points,
1793 *   std::vector<Vector<double> > &value_list) const override;
1794 *  
1795 *   private:
1796 *   const double present_time,
1797 *   end_time,
1798 *   pressure,
1799 *   height;
1800 *   };
1801 *  
1802 *   template <int dim>
1803 *   IncrementalBoundaryForce<dim>::
1804 *   IncrementalBoundaryForce (const double present_time,
1805 *   const double end_time)
1806 *   :
1807 *   Function<dim>(dim),
1808 *   present_time (present_time),
1809 *   end_time (end_time),
1810 *   pressure (6e6),
1811 *   height (200e-3)
1812 *   {}
1813 *  
1814 *   template <int dim>
1815 *   void
1816 *   IncrementalBoundaryForce<dim>::vector_value (const Point<dim> &p,
1817 *   Vector<double> &values) const
1818 *   {
1819 *   AssertThrow (dim == 3, ExcNotImplemented());
1820 *   AssertThrow (values.size() == dim,
1821 *   ExcDimensionMismatch (values.size(), dim));
1822 *  
1823 *   const double eps = 1.e-7 * height;
1824 *  
1825 * @endcode
1826 *
1827 * pressure should be imposed on the top surface, y = height
1828 *
1829 * @code
1830 *   AssertThrow(std::abs(p[1]-(height/2)) < eps, ExcInternalError());
1831 *  
1832 *   values = 0;
1833 *  
1834 *   values(1) = -pressure;
1835 *  
1836 * @endcode
1837 *
1838 * compute the fraction of imposed force
1839 *
1840 * @code
1841 *   const double frac = present_time/end_time;
1842 *  
1843 *   values *= frac;
1844 *   }
1845 *  
1846 *   template <int dim>
1847 *   void
1848 *   IncrementalBoundaryForce<dim>::
1849 *   vector_value_list (const std::vector<Point<dim> > &points,
1850 *   std::vector<Vector<double> > &value_list) const
1851 *   {
1852 *   const unsigned int n_points = points.size();
1853 *  
1854 *   Assert (value_list.size() == n_points,
1855 *   ExcDimensionMismatch (value_list.size(), n_points));
1856 *  
1857 *   for (unsigned int p=0; p<n_points; ++p)
1858 *   IncrementalBoundaryForce<dim>::vector_value (points[p], value_list[p]);
1859 *   }
1860 *  
1861 *  
1862 *   template <int dim>
1863 *   class BodyForce : public Functions::ZeroFunction<dim>
1864 *   {
1865 *   public:
1866 *   BodyForce () : Functions::ZeroFunction<dim> (dim) {}
1867 *   };
1868 *  
1869 *  
1870 *   template <int dim>
1871 *   class IncrementalBoundaryValues : public Function<dim>
1872 *   {
1873 *   public:
1874 *   IncrementalBoundaryValues (const double present_time,
1875 *   const double end_time);
1876 *  
1877 *   virtual
1878 *   void
1879 *   vector_value (const Point<dim> &p,
1880 *   Vector<double> &values) const override;
1881 *  
1882 *   virtual
1883 *   void
1884 *   vector_value_list (const std::vector<Point<dim> > &points,
1885 *   std::vector<Vector<double> > &value_list) const override;
1886 *  
1887 *   private:
1888 *   const double present_time,
1889 *   end_time;
1890 *   };
1891 *  
1892 *  
1893 *   template <int dim>
1894 *   IncrementalBoundaryValues<dim>::
1895 *   IncrementalBoundaryValues (const double present_time,
1896 *   const double end_time)
1897 *   :
1898 *   Function<dim> (dim),
1899 *   present_time (present_time),
1900 *   end_time (end_time)
1901 *   {}
1902 *  
1903 *  
1904 *   template <int dim>
1905 *   void
1906 *   IncrementalBoundaryValues<dim>::
1907 *   vector_value (const Point<dim> &/*p*/,
1908 *   Vector<double> &values) const
1909 *   {
1910 *   AssertThrow (values.size() == dim,
1911 *   ExcDimensionMismatch (values.size(), dim));
1912 *   AssertThrow (dim == 3, ExcNotImplemented());
1913 *  
1914 *   values = 0.;
1915 *   }
1916 *  
1917 *  
1918 *   template <int dim>
1919 *   void
1920 *   IncrementalBoundaryValues<dim>::
1921 *   vector_value_list (const std::vector<Point<dim> > &points,
1922 *   std::vector<Vector<double> > &value_list) const
1923 *   {
1924 *   const unsigned int n_points = points.size();
1925 *  
1926 *   Assert (value_list.size() == n_points,
1927 *   ExcDimensionMismatch (value_list.size(), n_points));
1928 *  
1929 *   for (unsigned int p=0; p<n_points; ++p)
1930 *   IncrementalBoundaryValues<dim>::vector_value (points[p], value_list[p]);
1931 *   }
1932 *  
1933 * @endcode
1934 *
1935 * -------------------------------------------------------------------------------
1936 *
1937 * @code
1938 *   }
1939 *  
1940 *  
1941 *   namespace DualFunctional
1942 *   {
1943 *  
1944 *   template <int dim>
1945 *   class DualFunctionalBase : public Subscriptor
1946 *   {
1947 *   public:
1948 *   virtual
1949 *   void
1950 *   assemble_rhs (const DoFHandler<dim> &dof_handler,
1951 *   const Vector<double> &solution,
1952 *   const ConstitutiveLaw<dim> &constitutive_law,
1953 *   const DoFHandler<dim> &dof_handler_dual,
1954 *   Vector<double> &rhs_dual) const = 0;
1955 *   };
1956 *  
1957 *  
1958 *   template <int dim>
1959 *   class PointValuesEvaluation : public DualFunctionalBase<dim>
1960 *   {
1961 *   public:
1962 *   PointValuesEvaluation (const Point<dim> &evaluation_point);
1963 *  
1964 *   virtual
1965 *   void
1966 *   assemble_rhs (const DoFHandler<dim> &dof_handler,
1967 *   const Vector<double> &solution,
1968 *   const ConstitutiveLaw<dim> &constitutive_law,
1969 *   const DoFHandler<dim> &dof_handler_dual,
1970 *   Vector<double> &rhs_dual) const override;
1971 *  
1972 *   DeclException1 (ExcEvaluationPointNotFound,
1973 *   Point<dim>,
1974 *   << "The evaluation point " << arg1
1975 *   << " was not found among the vertices of the present grid.");
1976 *  
1977 *   protected:
1978 *   const Point<dim> evaluation_point;
1979 *   };
1980 *  
1981 *  
1982 *   template <int dim>
1983 *   PointValuesEvaluation<dim>::
1984 *   PointValuesEvaluation (const Point<dim> &evaluation_point)
1985 *   :
1986 *   evaluation_point (evaluation_point)
1987 *   {}
1988 *  
1989 *  
1990 *   template <int dim>
1991 *   void
1992 *   PointValuesEvaluation<dim>::
1993 *   assemble_rhs (const DoFHandler<dim> &/*dof_handler*/,
1994 *   const Vector<double> &/*solution*/,
1995 *   const ConstitutiveLaw<dim> &/*constitutive_law*/,
1996 *   const DoFHandler<dim> &dof_handler_dual,
1997 *   Vector<double> &rhs_dual) const
1998 *   {
1999 *   rhs_dual.reinit (dof_handler_dual.n_dofs());
2000 *   const unsigned int dofs_per_vertex = dof_handler_dual.get_fe().dofs_per_vertex;
2001 *  
2003 *   cell_dual = dof_handler_dual.begin_active(),
2004 *   endc_dual = dof_handler_dual.end();
2005 *   for (; cell_dual!=endc_dual; ++cell_dual)
2006 *   for (unsigned int vertex=0;
2007 *   vertex<GeometryInfo<dim>::vertices_per_cell;
2008 *   ++vertex)
2009 *   if (cell_dual->vertex(vertex).distance(evaluation_point)
2010 *   < cell_dual->diameter()*1e-8)
2011 *   {
2012 *   for (unsigned int id=0; id!=dofs_per_vertex; ++id)
2013 *   {
2014 *   rhs_dual(cell_dual->vertex_dof_index(vertex,id)) = 1;
2015 *   }
2016 *   return;
2017 *   }
2018 *  
2019 *   AssertThrow (false, ExcEvaluationPointNotFound(evaluation_point));
2020 *   }
2021 *  
2022 *  
2023 *   template <int dim>
2024 *   class PointXDerivativesEvaluation : public DualFunctionalBase<dim>
2025 *   {
2026 *   public:
2027 *   PointXDerivativesEvaluation (const Point<dim> &evaluation_point);
2028 *  
2029 *   virtual
2030 *   void
2031 *   assemble_rhs (const DoFHandler<dim> &dof_handler,
2032 *   const Vector<double> &solution,
2033 *   const ConstitutiveLaw<dim> &constitutive_law,
2034 *   const DoFHandler<dim> &dof_handler_dual,
2035 *   Vector<double> &rhs_dual) const override;
2036 *  
2037 *   DeclException1 (ExcEvaluationPointNotFound,
2038 *   Point<dim>,
2039 *   << "The evaluation point " << arg1
2040 *   << " was not found among the vertices of the present grid.");
2041 *  
2042 *   protected:
2043 *   const Point<dim> evaluation_point;
2044 *   };
2045 *  
2046 *  
2047 *   template <int dim>
2048 *   PointXDerivativesEvaluation<dim>::
2049 *   PointXDerivativesEvaluation (const Point<dim> &evaluation_point)
2050 *   :
2051 *   evaluation_point (evaluation_point)
2052 *   {}
2053 *  
2054 *  
2055 *   template <int dim>
2056 *   void
2057 *   PointXDerivativesEvaluation<dim>::
2058 *   assemble_rhs (const DoFHandler<dim> &/*dof_handler*/,
2059 *   const Vector<double> &/*solution*/,
2060 *   const ConstitutiveLaw<dim> &/*constitutive_law*/,
2061 *   const DoFHandler<dim> &dof_handler_dual,
2062 *   Vector<double> &rhs_dual) const
2063 *   {
2064 *   rhs_dual.reinit (dof_handler_dual.n_dofs());
2065 *  
2066 *   QGauss<dim> quadrature(4);
2067 *   FEValues<dim> fe_values (dof_handler_dual.get_fe(), quadrature,
2068 *   update_gradients |
2070 *   update_JxW_values);
2071 *   const unsigned int n_q_points = fe_values.n_quadrature_points;
2072 *   Assert ( n_q_points==quadrature.size() , ExcInternalError() );
2073 *   const unsigned int dofs_per_cell = dof_handler_dual.get_fe().dofs_per_cell;
2074 *  
2075 *   Vector<double> cell_rhs (dofs_per_cell);
2076 *   std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
2077 *  
2078 *   double total_volume = 0;
2079 *  
2081 *   cell = dof_handler_dual.begin_active(),
2082 *   endc = dof_handler_dual.end();
2083 *   for (; cell!=endc; ++cell)
2084 *   if (cell->center().distance(evaluation_point) <=
2085 *   cell->diameter())
2086 *   {
2087 *   fe_values.reinit (cell);
2088 *   cell_rhs = 0;
2089 *  
2090 *   for (unsigned int q=0; q<n_q_points; ++q)
2091 *   {
2092 *   for (unsigned int i=0; i<dofs_per_cell; ++i)
2093 *   {
2094 *   cell_rhs(i) += fe_values.shape_grad(i,q)[0] *
2095 *   fe_values.JxW (q);
2096 *   }
2097 *  
2098 *   total_volume += fe_values.JxW (q);
2099 *   }
2100 *  
2101 *   cell->get_dof_indices (local_dof_indices);
2102 *   for (unsigned int i=0; i<dofs_per_cell; ++i)
2103 *   {
2104 *   rhs_dual(local_dof_indices[i]) += cell_rhs(i);
2105 *   }
2106 *   }
2107 *  
2108 *   AssertThrow (total_volume > 0,
2109 *   ExcEvaluationPointNotFound(evaluation_point));
2110 *  
2111 *   rhs_dual *= 1./total_volume;
2112 *   }
2113 *  
2114 *  
2115 *  
2116 *   template <int dim>
2117 *   class MeanDisplacementFace : public DualFunctionalBase<dim>
2118 *   {
2119 *   public:
2120 *   MeanDisplacementFace (const unsigned int face_id,
2121 *   const std::vector<bool> comp_mask);
2122 *  
2123 *   virtual
2124 *   void
2125 *   assemble_rhs (const DoFHandler<dim> &dof_handler,
2126 *   const Vector<double> &solution,
2127 *   const ConstitutiveLaw<dim> &constitutive_law,
2128 *   const DoFHandler<dim> &dof_handler_dual,
2129 *   Vector<double> &rhs_dual) const override;
2130 *  
2131 *   protected:
2132 *   const unsigned int face_id;
2133 *   const std::vector<bool> comp_mask;
2134 *   };
2135 *  
2136 *  
2137 *   template <int dim>
2138 *   MeanDisplacementFace<dim>::
2139 *   MeanDisplacementFace (const unsigned int face_id,
2140 *   const std::vector<bool> comp_mask )
2141 *   :
2142 *   face_id (face_id),
2143 *   comp_mask (comp_mask)
2144 *   {
2145 *   AssertThrow(comp_mask.size() == dim,
2146 *   ExcDimensionMismatch (comp_mask.size(), dim) );
2147 *   }
2148 *  
2149 *  
2150 *   template <int dim>
2151 *   void
2152 *   MeanDisplacementFace<dim>::
2153 *   assemble_rhs (const DoFHandler<dim> &/*dof_handler*/,
2154 *   const Vector<double> &/*solution*/,
2155 *   const ConstitutiveLaw<dim> &/*constitutive_law*/,
2156 *   const DoFHandler<dim> &dof_handler_dual,
2157 *   Vector<double> &rhs_dual) const
2158 *   {
2159 *   AssertThrow (dim >= 2, ExcNotImplemented());
2160 *  
2161 *   rhs_dual.reinit (dof_handler_dual.n_dofs());
2162 *  
2163 *   const QGauss<dim-1> face_quadrature(dof_handler_dual.get_fe().tensor_degree()+1);
2164 *   FEFaceValues<dim> fe_face_values (dof_handler_dual.get_fe(), face_quadrature,
2166 *  
2167 *   const unsigned int dofs_per_vertex = dof_handler_dual.get_fe().dofs_per_vertex;
2168 *   const unsigned int dofs_per_cell = dof_handler_dual.get_fe().dofs_per_cell;
2169 *   const unsigned int n_face_q_points = face_quadrature.size();
2170 *  
2171 *   AssertThrow(dofs_per_vertex == dim,
2172 *   ExcDimensionMismatch (dofs_per_vertex, dim) );
2173 *  
2174 *   std::vector<unsigned int> comp_vector(dofs_per_vertex);
2175 *   for (unsigned int i=0; i!=dofs_per_vertex; ++i)
2176 *   {
2177 *   if (comp_mask[i])
2178 *   {
2179 *   comp_vector[i] = 1;
2180 *   }
2181 *   }
2182 *  
2183 *   Vector<double> cell_rhs (dofs_per_cell);
2184 *  
2185 *   std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
2186 *  
2187 * @endcode
2188 *
2189 * bound_size : size of the boundary, in 2d is the length
2190 * and in the 3d case, area
2191 *
2192 * @code
2193 *   double bound_size = 0.;
2194 *  
2196 *   cell = dof_handler_dual.begin_active(),
2197 *   endc = dof_handler_dual.end();
2198 *   bool evaluation_face_found = false;
2199 *   for (; cell!=endc; ++cell)
2200 *   {
2201 *   cell_rhs = 0;
2202 *   for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
2203 *   {
2204 *   if (cell->face(face)->at_boundary()
2205 *   &&
2206 *   cell->face(face)->boundary_id() == face_id)
2207 *   {
2208 *   if (!evaluation_face_found)
2209 *   {
2210 *   evaluation_face_found = true;
2211 *   }
2212 *   fe_face_values.reinit (cell, face);
2213 *  
2214 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
2215 *   {
2216 *   bound_size += fe_face_values.JxW(q_point);
2217 *  
2218 *   for (unsigned int i=0; i<dofs_per_cell; ++i)
2219 *   {
2220 *   const unsigned int
2221 *   component_i = dof_handler_dual.get_fe().system_to_component_index(i).first;
2222 *  
2223 *   cell_rhs(i) += (fe_face_values.shape_value(i,q_point) *
2224 *   comp_vector[component_i] *
2225 *   fe_face_values.JxW(q_point));
2226 *   }
2227 *  
2228 *   }
2229 *  
2230 *   }
2231 *   }
2232 *  
2233 *   cell->get_dof_indices (local_dof_indices);
2234 *   for (unsigned int i=0; i<dofs_per_cell; ++i)
2235 *   {
2236 *   rhs_dual(local_dof_indices[i]) += cell_rhs(i);
2237 *   }
2238 *  
2239 *   }
2240 *  
2241 *   AssertThrow(evaluation_face_found, ExcInternalError());
2242 *  
2243 *   rhs_dual /= bound_size;
2244 *   }
2245 *  
2246 *  
2247 *  
2248 *   template <int dim>
2249 *   class MeanStressFace : public DualFunctionalBase<dim>
2250 *   {
2251 *   public:
2252 *   MeanStressFace (const unsigned int face_id,
2253 *   const std::vector<std::vector<unsigned int> > &comp_stress);
2254 *  
2255 *   virtual
2256 *   void
2257 *   assemble_rhs (const DoFHandler<dim> &dof_handler,
2258 *   const Vector<double> &solution,
2259 *   const ConstitutiveLaw<dim> &constitutive_law,
2260 *   const DoFHandler<dim> &dof_handler_dual,
2261 *   Vector<double> &rhs_dual) const override;
2262 *  
2263 *   protected:
2264 *   const unsigned int face_id;
2265 *   const std::vector<std::vector<unsigned int> > comp_stress;
2266 *   };
2267 *  
2268 *  
2269 *   template <int dim>
2270 *   MeanStressFace<dim>::
2271 *   MeanStressFace (const unsigned int face_id,
2272 *   const std::vector<std::vector<unsigned int> > &comp_stress )
2273 *   :
2274 *   face_id (face_id),
2275 *   comp_stress (comp_stress)
2276 *   {
2277 *   AssertThrow(comp_stress.size() == dim,
2278 *   ExcDimensionMismatch (comp_stress.size(), dim) );
2279 *   }
2280 *  
2281 *  
2282 *   template <int dim>
2283 *   void
2284 *   MeanStressFace<dim>::
2285 *   assemble_rhs (const DoFHandler<dim> &dof_handler,
2286 *   const Vector<double> &solution,
2287 *   const ConstitutiveLaw<dim> &constitutive_law,
2288 *   const DoFHandler<dim> &dof_handler_dual,
2289 *   Vector<double> &rhs_dual) const
2290 *   {
2291 *   AssertThrow (dim >= 2, ExcNotImplemented());
2292 *  
2293 *   rhs_dual.reinit (dof_handler_dual.n_dofs());
2294 *  
2295 *   const QGauss<dim-1> face_quadrature(dof_handler_dual.get_fe().tensor_degree()+1);
2296 *  
2297 *   FEFaceValues<dim> fe_face_values (dof_handler.get_fe(), face_quadrature,
2298 *   update_gradients);
2299 *   FEFaceValues<dim> fe_face_values_dual (dof_handler_dual.get_fe(), face_quadrature,
2301 *  
2302 *   const unsigned int dofs_per_cell_dual = dof_handler_dual.get_fe().dofs_per_cell;
2303 *   const unsigned int n_face_q_points = face_quadrature.size();
2304 *  
2305 *   std::vector<SymmetricTensor<2, dim> > strain_tensor(n_face_q_points);
2306 *   SymmetricTensor<4, dim> stress_strain_tensor;
2307 *  
2308 *   Vector<double> cell_rhs (dofs_per_cell_dual);
2309 *  
2310 *   std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell_dual);
2311 *  
2312 * @endcode
2313 *
2314 * bound_size : size of the boundary, in 2d is the length
2315 * and in the 3d case, area
2316 *
2317 * @code
2318 *   double bound_size = 0.;
2319 *  
2320 *   bool evaluation_face_found = false;
2321 *  
2323 *   cell_dual = dof_handler_dual.begin_active(),
2324 *   endc_dual = dof_handler_dual.end(),
2325 *   cell = dof_handler.begin_active();
2326 *  
2327 *   const FEValuesExtractors::Vector displacement(0);
2328 *  
2329 *   for (; cell_dual!=endc_dual; ++cell_dual, ++cell)
2330 *   {
2331 *   cell_rhs = 0;
2332 *   for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
2333 *   {
2334 *   if (cell_dual->face(face)->at_boundary()
2335 *   &&
2336 *   cell_dual->face(face)->boundary_id() == face_id)
2337 *   {
2338 *   if (!evaluation_face_found)
2339 *   {
2340 *   evaluation_face_found = true;
2341 *   }
2342 *  
2343 *   fe_face_values.reinit (cell, face);
2344 *   fe_face_values_dual.reinit (cell_dual, face);
2345 *  
2346 *   fe_face_values[displacement].get_function_symmetric_gradients(solution,
2347 *   strain_tensor);
2348 *  
2349 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
2350 *   {
2351 *   bound_size += fe_face_values_dual.JxW(q_point);
2352 *  
2353 *   constitutive_law.get_stress_strain_tensor(strain_tensor[q_point],
2354 *   stress_strain_tensor);
2355 *  
2356 *   for (unsigned int i=0; i<dofs_per_cell_dual; ++i)
2357 *   {
2358 *   const SymmetricTensor<2, dim>
2359 *   stress_phi_i = stress_strain_tensor
2360 *   * fe_face_values_dual[displacement].symmetric_gradient(i, q_point);
2361 *  
2362 *   for (unsigned int k=0; k!=dim; ++k)
2363 *   {
2364 *   for (unsigned int l=0; l!=dim; ++l)
2365 *   {
2366 *   if ( comp_stress[k][l] == 1 )
2367 *   {
2368 *   cell_rhs(i) += stress_phi_i[k][l]
2369 *   *
2370 *   fe_face_values_dual.JxW(q_point);
2371 *   }
2372 *  
2373 *   }
2374 *   }
2375 *  
2376 *   }
2377 *  
2378 *   }
2379 *  
2380 *   }
2381 *   }
2382 *  
2383 *   cell_dual->get_dof_indices (local_dof_indices);
2384 *   for (unsigned int i=0; i<dofs_per_cell_dual; ++i)
2385 *   {
2386 *   rhs_dual(local_dof_indices[i]) += cell_rhs(i);
2387 *   }
2388 *  
2389 *   }
2390 *  
2391 *   AssertThrow(evaluation_face_found, ExcInternalError());
2392 *  
2393 *   rhs_dual /= bound_size;
2394 *  
2395 *   }
2396 *  
2397 *  
2398 *   template <int dim>
2399 *   class MeanStressDomain : public DualFunctionalBase<dim>
2400 *   {
2401 *   public:
2402 *   MeanStressDomain (const std::string &base_mesh,
2403 *   const std::vector<std::vector<unsigned int> > &comp_stress);
2404 *  
2405 *   virtual
2406 *   void
2407 *   assemble_rhs (const DoFHandler<dim> &dof_handler,
2408 *   const Vector<double> &solution,
2409 *   const ConstitutiveLaw<dim> &constitutive_law,
2410 *   const DoFHandler<dim> &dof_handler_dual,
2411 *   Vector<double> &rhs_dual) const override;
2412 *  
2413 *   protected:
2414 *   const std::string base_mesh;
2415 *   const std::vector<std::vector<unsigned int> > comp_stress;
2416 *   };
2417 *  
2418 *  
2419 *   template <int dim>
2420 *   MeanStressDomain<dim>::
2421 *   MeanStressDomain (const std::string &base_mesh,
2422 *   const std::vector<std::vector<unsigned int> > &comp_stress )
2423 *   :
2424 *   base_mesh (base_mesh),
2425 *   comp_stress (comp_stress)
2426 *   {
2427 *   AssertThrow(comp_stress.size() == dim,
2428 *   ExcDimensionMismatch (comp_stress.size(), dim) );
2429 *   }
2430 *  
2431 *  
2432 *   template <int dim>
2433 *   void
2434 *   MeanStressDomain<dim>::
2435 *   assemble_rhs (const DoFHandler<dim> &dof_handler,
2436 *   const Vector<double> &solution,
2437 *   const ConstitutiveLaw<dim> &constitutive_law,
2438 *   const DoFHandler<dim> &dof_handler_dual,
2439 *   Vector<double> &rhs_dual) const
2440 *   {
2441 *   AssertThrow (base_mesh == "Cantiliver_beam_3d", ExcNotImplemented());
2442 *   AssertThrow (dim == 3, ExcNotImplemented());
2443 *  
2444 * @endcode
2445 *
2446 * Mean stress at the specified domain is of interest.
2447 * The interest domains are located on the bottom and top of the flanges
2448 * close to the clamped face, z = 0
2449 * top domain: height/2 - thickness_flange <= y <= height/2
2450 * 0 <= z <= 2 * thickness_flange
2451 * bottom domain: -height/2 <= y <= -height/2 + thickness_flange
2452 * 0 <= z <= 2 * thickness_flange
2453 *
2454
2455 *
2456 *
2457 * @code
2458 *   const double height = 200e-3,
2459 *   thickness_flange = 10e-3;
2460 *  
2461 *   rhs_dual.reinit (dof_handler_dual.n_dofs());
2462 *  
2463 *   const QGauss<dim> quadrature_formula(dof_handler_dual.get_fe().tensor_degree()+1);
2464 *  
2465 *   FEValues<dim> fe_values (dof_handler.get_fe(), quadrature_formula,
2466 *   update_gradients);
2467 *   FEValues<dim> fe_values_dual (dof_handler_dual.get_fe(), quadrature_formula,
2469 *  
2470 *   const unsigned int dofs_per_cell_dual = dof_handler_dual.get_fe().dofs_per_cell;
2471 *   const unsigned int n_q_points = quadrature_formula.size();
2472 *  
2473 *   std::vector<SymmetricTensor<2, dim> > strain_tensor(n_q_points);
2474 *   SymmetricTensor<4, dim> stress_strain_tensor;
2475 *  
2476 *   Vector<double> cell_rhs (dofs_per_cell_dual);
2477 *  
2478 *   std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell_dual);
2479 *  
2480 * @endcode
2481 *
2482 * domain_size : size of the interested domain, in 2d is the area
2483 * and in the 3d case, volume
2484 *
2485 * @code
2486 *   double domain_size = 0.;
2487 *  
2488 *   bool evaluation_domain_found = false;
2489 *  
2491 *   cell_dual = dof_handler_dual.begin_active(),
2492 *   endc_dual = dof_handler_dual.end(),
2493 *   cell = dof_handler.begin_active();
2494 *  
2495 *   const FEValuesExtractors::Vector displacement(0);
2496 *  
2497 *   for (; cell_dual!=endc_dual; ++cell_dual, ++cell)
2498 *   {
2499 *   const double y = cell->center()[1],
2500 *   z = cell->center()[2];
2501 * @endcode
2502 *
2503 * top domain: height/2 - thickness_flange <= y <= height/2
2504 * 0 <= z <= 2 * thickness_flange
2505 * bottom domain: -height/2 <= y <= -height/2 + thickness_flange
2506 * 0 <= z <= 2 * thickness_flange
2507 *
2508 * @code
2509 *   if ( ((z > 0) && (z < 2*thickness_flange)) &&
2510 *   ( ((y > height/2 - thickness_flange) && (y < height/2)) ||
2511 *   ((y > -height/2) && (y < -height/2 + thickness_flange)) ) )
2512 *   {
2513 *   cell_rhs = 0;
2514 *  
2515 *   if (!evaluation_domain_found)
2516 *   {
2517 *   evaluation_domain_found = true;
2518 *   }
2519 *  
2520 *   fe_values.reinit(cell);
2521 *   fe_values_dual.reinit(cell_dual);
2522 *  
2523 *   fe_values[displacement].get_function_symmetric_gradients(solution,
2524 *   strain_tensor);
2525 *  
2526 *   for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
2527 *   {
2528 *   domain_size += fe_values_dual.JxW(q_point);
2529 *  
2530 *   constitutive_law.get_stress_strain_tensor(strain_tensor[q_point],
2531 *   stress_strain_tensor);
2532 *  
2533 *   for (unsigned int i=0; i<dofs_per_cell_dual; ++i)
2534 *   {
2535 *   const SymmetricTensor<2, dim>
2536 *   stress_phi_i = stress_strain_tensor
2537 *   * fe_values_dual[displacement].symmetric_gradient(i, q_point);
2538 *  
2539 *   for (unsigned int k=0; k!=dim; ++k)
2540 *   {
2541 *   for (unsigned int l=0; l!=dim; ++l)
2542 *   {
2543 *   if ( comp_stress[k][l] == 1 )
2544 *   {
2545 *   cell_rhs(i) += stress_phi_i[k][l]
2546 *   *
2547 *   fe_values_dual.JxW(q_point);
2548 *   }
2549 *  
2550 *   }
2551 *   }
2552 *  
2553 *   }
2554 *  
2555 *   }
2556 *  
2557 *   }
2558 *  
2559 *   cell_dual->get_dof_indices (local_dof_indices);
2560 *   for (unsigned int i=0; i<dofs_per_cell_dual; ++i)
2561 *   {
2562 *   rhs_dual(local_dof_indices[i]) += cell_rhs(i);
2563 *   }
2564 *  
2565 *   }
2566 *  
2567 *   AssertThrow(evaluation_domain_found, ExcInternalError());
2568 *  
2569 *   rhs_dual /= domain_size;
2570 *  
2571 *   }
2572 *  
2573 *  
2574 *   template <int dim>
2575 *   class MeanStrainEnergyFace : public DualFunctionalBase<dim>
2576 *   {
2577 *   public:
2578 *   MeanStrainEnergyFace (const unsigned int face_id,
2579 *   const Function<dim> &lambda_function,
2580 *   const Function<dim> &mu_function );
2581 *  
2582 *   void assemble_rhs_nonlinear (const DoFHandler<dim> &primal_dof_handler,
2583 *   const Vector<double> &primal_solution,
2584 *   const DoFHandler<dim> &dof_handler,
2585 *   Vector<double> &rhs) const;
2586 *  
2587 *   protected:
2588 *   const unsigned int face_id;
2589 *   const SmartPointer<const Function<dim> > lambda_function;
2590 *   const SmartPointer<const Function<dim> > mu_function;
2591 *   };
2592 *  
2593 *  
2594 *   template <int dim>
2595 *   MeanStrainEnergyFace<dim>::
2596 *   MeanStrainEnergyFace (const unsigned int face_id,
2597 *   const Function<dim> &lambda_function,
2598 *   const Function<dim> &mu_function )
2599 *   :
2600 *   face_id (face_id),
2601 *   lambda_function (&lambda_function),
2602 *   mu_function (&mu_function)
2603 *   {}
2604 *  
2605 *  
2606 *   template <int dim>
2607 *   void
2608 *   MeanStrainEnergyFace<dim>::
2609 *   assemble_rhs_nonlinear (const DoFHandler<dim> &primal_dof_handler,
2610 *   const Vector<double> &primal_solution,
2611 *   const DoFHandler<dim> &dof_handler,
2612 *   Vector<double> &rhs) const
2613 *   {
2614 * @endcode
2615 *
2616 * Assemble right hand side of the dual problem when the quantity of interest is
2617 * a nonlinear functinoal. In this case, the QoI should be linearized which depends
2618 * on the solution of the primal problem.
2619 * The extracter of the linearized QoI functional is the gradient of the the original
2620 * QoI functional with the primal solution values.
2621 *
2622
2623 *
2624 *
2625 * @code
2626 *   AssertThrow (dim >= 2, ExcNotImplemented());
2627 *  
2628 *   rhs.reinit (dof_handler.n_dofs());
2629 *  
2630 *   const QGauss<dim-1> face_quadrature(dof_handler.get_fe().tensor_degree()+1);
2631 *   FEFaceValues<dim> primal_fe_face_values (primal_dof_handler.get_fe(), face_quadrature,
2634 *   update_JxW_values);
2635 *  
2636 *   FEFaceValues<dim> fe_face_values (dof_handler.get_fe(), face_quadrature,
2637 *   update_values);
2638 *  
2639 *   const unsigned int dofs_per_vertex = primal_dof_handler.get_fe().dofs_per_vertex;
2640 *   const unsigned int n_face_q_points = face_quadrature.size();
2641 *   const unsigned int dofs_per_cell = dof_handler.get_fe().dofs_per_cell;
2642 *  
2643 *   AssertThrow(dofs_per_vertex == dim,
2644 *   ExcDimensionMismatch (dofs_per_vertex, dim) );
2645 *  
2646 *   std::vector< std::vector< Tensor<1,dim> > > primal_solution_gradients;
2647 *   primal_solution_gradients.resize(n_face_q_points);
2648 *  
2649 *   std::vector<std::vector<Tensor<2,dim> > > primal_solution_hessians;
2650 *   primal_solution_hessians.resize (n_face_q_points);
2651 *  
2652 *   for (unsigned int i=0; i!=n_face_q_points; ++i)
2653 *   {
2654 *   primal_solution_gradients[i].resize (dofs_per_vertex);
2655 *   primal_solution_hessians[i].resize (dofs_per_vertex);
2656 *   }
2657 *  
2658 *   std::vector<double> lambda_values (n_face_q_points);
2659 *   std::vector<double> mu_values (n_face_q_points);
2660 *  
2661 *   Vector<double> cell_rhs (dofs_per_cell);
2662 *  
2663 *   std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
2664 *  
2665 * @endcode
2666 *
2667 * bound_size : size of the boundary, in 2d is the length
2668 * and in the 3d case, area
2669 *
2670 * @code
2671 *   double bound_size = 0.;
2672 *  
2673 *   bool evaluation_face_found = false;
2674 *  
2676 *   primal_cell = primal_dof_handler.begin_active(),
2677 *   primal_endc = primal_dof_handler.end();
2678 *  
2680 *   cell = dof_handler.begin_active(),
2681 *   endc = dof_handler.end();
2682 *  
2683 *   for (; cell!=endc; ++cell, ++primal_cell)
2684 *   {
2685 *   cell_rhs = 0;
2686 *   for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
2687 *   {
2688 *   if (cell->face(face)->at_boundary()
2689 *   &&
2690 *   cell->face(face)->boundary_id() == face_id)
2691 *   {
2692 *   if (!evaluation_face_found)
2693 *   {
2694 *   evaluation_face_found = true;
2695 *   }
2696 *   primal_fe_face_values.reinit (primal_cell, face);
2697 *  
2698 *   primal_fe_face_values.get_function_gradients (primal_solution,
2699 *   primal_solution_gradients);
2700 *  
2701 *   primal_fe_face_values.get_function_hessians (primal_solution,
2702 *   primal_solution_hessians);
2703 *  
2704 *   lambda_function->value_list (primal_fe_face_values.get_quadrature_points(), lambda_values);
2705 *   mu_function->value_list (primal_fe_face_values.get_quadrature_points(), mu_values);
2706 *  
2707 *   fe_face_values.reinit (cell, face);
2708 *  
2709 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
2710 *   {
2711 *   bound_size += primal_fe_face_values.JxW(q_point);
2712 *  
2713 *   for (unsigned int m=0; m<dofs_per_cell; ++m)
2714 *   {
2715 *   const unsigned int
2716 *   component_m = dof_handler.get_fe().system_to_component_index(m).first;
2717 *  
2718 *   for (unsigned int i=0; i!=dofs_per_vertex; ++i)
2719 *   {
2720 *   for (unsigned int j=0; j!=dofs_per_vertex; ++j)
2721 *   {
2722 *   cell_rhs(m) += fe_face_values.shape_value(m,q_point) *
2723 *   (
2724 *   lambda_values[q_point] *
2725 *   (
2726 *   primal_solution_hessians[q_point][i][i][component_m] * primal_solution_gradients[q_point][j][j]
2727 *   +
2728 *   primal_solution_gradients[q_point][i][i] * primal_solution_hessians[q_point][j][j][component_m]
2729 *   )
2730 *   +
2731 *   mu_values[q_point] *
2732 *   (
2733 *   2*primal_solution_hessians[q_point][j][i][component_m] * primal_solution_gradients[q_point][j][i]
2734 *   +
2735 *   primal_solution_hessians[q_point][i][j][component_m] * primal_solution_gradients[q_point][j][i]
2736 *   +
2737 *   primal_solution_gradients[q_point][i][j] * primal_solution_hessians[q_point][j][i][component_m]
2738 *   )
2739 *   ) *
2740 *   primal_fe_face_values.JxW(q_point);
2741 *  
2742 *   }
2743 *   }
2744 *  
2745 *   } // end loop DoFs
2746 *  
2747 *  
2748 *   } // end loop Gauss points
2749 *  
2750 *   } // end if face
2751 *   } // end loop face
2752 *  
2753 *   cell->get_dof_indices (local_dof_indices);
2754 *   for (unsigned int i=0; i<dofs_per_cell; ++i)
2755 *   {
2756 *   rhs(local_dof_indices[i]) += cell_rhs(i);
2757 *   }
2758 *  
2759 *   } // end loop cell
2760 *  
2761 *   AssertThrow(evaluation_face_found, ExcInternalError());
2762 *  
2763 *   rhs *= 1./(2*bound_size);
2764 *  
2765 *   }
2766 *  
2767 *  
2768 *   }
2769 *  
2770 *  
2771 * @endcode
2772 *
2773 * DualSolver class
2774 *
2775 * @code
2776 *   template <int dim>
2777 *   class DualSolver
2778 *   {
2779 *   public:
2780 *   DualSolver (const Triangulation<dim> &triangulation,
2781 *   const FESystem<dim> &fe,
2782 *   const Vector<double> &solution,
2783 *   const ConstitutiveLaw<dim> &constitutive_law,
2784 *   const DualFunctional::DualFunctionalBase<dim> &dual_functional,
2785 *   const unsigned int &timestep_no,
2786 *   const std::string &output_dir,
2787 *   const std::string &base_mesh,
2788 *   const double &present_time,
2789 *   const double &end_time);
2790 *  
2791 *   void compute_error_DWR (Vector<float> &estimated_error_per_cell);
2792 *  
2793 *   ~DualSolver ();
2794 *  
2795 *   private:
2796 *   void setup_system ();
2797 *   void compute_dirichlet_constraints ();
2798 *   void assemble_matrix ();
2799 *   void assemble_rhs ();
2800 *   void solve ();
2801 *   void output_results ();
2802 *  
2803 *   const FESystem<dim> &fe;
2804 *   DoFHandler<dim> dof_handler;
2805 *   const Vector<double> solution;
2806 *  
2807 *   const unsigned int fe_degree;
2808 *  
2809 *  
2810 *   const unsigned int fe_degree_dual;
2811 *   FESystem<dim> fe_dual;
2812 *   DoFHandler<dim> dof_handler_dual;
2813 *  
2814 *   const QGauss<dim> quadrature_formula;
2815 *   const QGauss<dim - 1> face_quadrature_formula;
2816 *  
2817 *   AffineConstraints<double> constraints_hanging_nodes_dual;
2818 *   AffineConstraints<double> constraints_dirichlet_and_hanging_nodes_dual;
2819 *  
2820 *   SparsityPattern sparsity_pattern_dual;
2821 *   SparseMatrix<double> system_matrix_dual;
2822 *   Vector<double> system_rhs_dual;
2823 *   Vector<double> solution_dual;
2824 *  
2825 *   const ConstitutiveLaw<dim> constitutive_law;
2826 *  
2829 *  
2830 *   unsigned int timestep_no;
2831 *   std::string output_dir;
2832 *   const std::string base_mesh;
2833 *   double present_time;
2834 *   double end_time;
2835 *   };
2836 *  
2837 *  
2838 *   template<int dim>
2839 *   DualSolver<dim>::
2840 *   DualSolver (const Triangulation<dim> &triangulation,
2841 *   const FESystem<dim> &fe,
2842 *   const Vector<double> &solution,
2843 *   const ConstitutiveLaw<dim> &constitutive_law,
2844 *   const DualFunctional::DualFunctionalBase<dim> &dual_functional,
2845 *   const unsigned int &timestep_no,
2846 *   const std::string &output_dir,
2847 *   const std::string &base_mesh,
2848 *   const double &present_time,
2849 *   const double &end_time)
2850 *   :
2851 *   fe (fe),
2852 *   dof_handler (triangulation),
2853 *   solution(solution),
2854 *   fe_degree(fe.tensor_degree()),
2855 *   fe_degree_dual(fe_degree + 1),
2856 *   fe_dual(FE_Q<dim>(fe_degree_dual), dim),
2857 *   dof_handler_dual (triangulation),
2858 *   quadrature_formula (fe_degree_dual + 1),
2859 *   face_quadrature_formula (fe_degree_dual + 1),
2860 *   constitutive_law (constitutive_law),
2862 *   dual_functional (&dual_functional),
2863 *   timestep_no (timestep_no),
2864 *   output_dir (output_dir),
2865 *   base_mesh (base_mesh),
2866 *   present_time (present_time),
2867 *   end_time (end_time)
2868 *   {}
2869 *  
2870 *  
2871 *   template<int dim>
2872 *   DualSolver<dim>::~DualSolver()
2873 *   {
2874 *   dof_handler_dual.clear ();
2875 *   }
2876 *  
2877 *  
2878 *   template<int dim>
2879 *   void DualSolver<dim>::setup_system()
2880 *   {
2881 *   dof_handler.distribute_dofs(fe);
2882 *  
2883 *   dof_handler_dual.distribute_dofs (fe_dual);
2884 *   std::cout << " Number of degrees of freedom in dual problem: "
2885 *   << dof_handler_dual.n_dofs()
2886 *   << std::endl;
2887 *  
2888 *   constraints_hanging_nodes_dual.clear ();
2889 *   DoFTools::make_hanging_node_constraints (dof_handler_dual,
2890 *   constraints_hanging_nodes_dual);
2891 *   constraints_hanging_nodes_dual.close ();
2892 *  
2893 *   compute_dirichlet_constraints();
2894 *  
2895 *   sparsity_pattern_dual.reinit (dof_handler_dual.n_dofs(),
2896 *   dof_handler_dual.n_dofs(),
2897 *   dof_handler_dual.max_couplings_between_dofs());
2898 *   DoFTools::make_sparsity_pattern (dof_handler_dual, sparsity_pattern_dual);
2899 *  
2900 * @endcode
2901 *
2902 * constraints_hanging_nodes_dual.condense (sparsity_pattern_dual);
2903 *
2904 * @code
2905 *   constraints_dirichlet_and_hanging_nodes_dual.condense (sparsity_pattern_dual);
2906 *  
2907 *   sparsity_pattern_dual.compress();
2908 *  
2909 *   system_matrix_dual.reinit (sparsity_pattern_dual);
2910 *  
2911 *   solution_dual.reinit (dof_handler_dual.n_dofs());
2912 *   system_rhs_dual.reinit (dof_handler_dual.n_dofs());
2913 *  
2914 *   }
2915 *  
2916 *   template<int dim>
2917 *   void DualSolver<dim>::compute_dirichlet_constraints()
2918 *   {
2919 *   constraints_dirichlet_and_hanging_nodes_dual.clear ();
2920 *   constraints_dirichlet_and_hanging_nodes_dual.merge(constraints_hanging_nodes_dual);
2921 *  
2922 *   std::vector<bool> component_mask(dim);
2923 *  
2924 *   if (base_mesh == "Timoshenko beam")
2925 *   {
2926 *   VectorTools::interpolate_boundary_values(dof_handler_dual,
2927 *   0,
2928 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
2929 *   constraints_dirichlet_and_hanging_nodes_dual,
2930 *   ComponentMask());
2931 *   }
2932 *   else if (base_mesh == "Thick_tube_internal_pressure")
2933 *   {
2934 * @endcode
2935 *
2936 * the boundary x = 0
2937 *
2938 * @code
2939 *   component_mask[0] = true;
2940 *   component_mask[1] = false;
2941 *   VectorTools::interpolate_boundary_values (dof_handler_dual,
2942 *   2,
2943 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
2944 *   constraints_dirichlet_and_hanging_nodes_dual,
2945 *   component_mask);
2946 * @endcode
2947 *
2948 * the boundary y = 0
2949 *
2950 * @code
2951 *   component_mask[0] = false;
2952 *   component_mask[1] = true;
2953 *   VectorTools::interpolate_boundary_values (dof_handler_dual,
2954 *   3,
2955 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
2956 *   constraints_dirichlet_and_hanging_nodes_dual,
2957 *   component_mask);
2958 *   }
2959 *   else if (base_mesh == "Perforated_strip_tension")
2960 *   {
2961 * @endcode
2962 *
2963 * the boundary x = 0
2964 *
2965 * @code
2966 *   component_mask[0] = true;
2967 *   component_mask[1] = false;
2968 *   component_mask[2] = false;
2969 *   VectorTools::interpolate_boundary_values (dof_handler_dual,
2970 *   4,
2971 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
2972 *   constraints_dirichlet_and_hanging_nodes_dual,
2973 *   component_mask);
2974 * @endcode
2975 *
2976 * the boundary y = 0
2977 *
2978 * @code
2979 *   component_mask[0] = false;
2980 *   component_mask[1] = true;
2981 *   component_mask[2] = false;
2982 *   VectorTools::interpolate_boundary_values (dof_handler_dual,
2983 *   1,
2984 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
2985 *   constraints_dirichlet_and_hanging_nodes_dual,
2986 *   component_mask);
2987 * @endcode
2988 *
2989 * the boundary y = imposed incremental displacement
2990 *
2991 * @code
2992 *   component_mask[0] = false;
2993 *   component_mask[1] = true;
2994 *   component_mask[2] = false;
2995 *   VectorTools::interpolate_boundary_values (dof_handler_dual,
2996 *   3,
2997 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
2998 *   constraints_dirichlet_and_hanging_nodes_dual,
2999 *   component_mask);
3000 *   }
3001 *   else if (base_mesh == "Cantiliver_beam_3d")
3002 *   {
3003 * @endcode
3004 *
3005 * the boundary x = y = z = 0
3006 *
3007 * @code
3008 *   component_mask[0] = true;
3009 *   component_mask[1] = true;
3010 *   component_mask[2] = true;
3011 *   VectorTools::interpolate_boundary_values (dof_handler_dual,
3012 *   1,
3013 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
3014 *   constraints_dirichlet_and_hanging_nodes_dual,
3015 *   component_mask);
3016 *   }
3017 *   else
3018 *   {
3019 *   AssertThrow(false, ExcNotImplemented());
3020 *   }
3021 *  
3022 *   constraints_dirichlet_and_hanging_nodes_dual.close();
3023 *   }
3024 *  
3025 *  
3026 *   template<int dim>
3027 *   void DualSolver<dim>::assemble_matrix()
3028 *   {
3029 *   FEValues<dim> fe_values(fe, quadrature_formula, update_gradients);
3030 *  
3031 *   FEValues<dim> fe_values_dual(fe_dual, quadrature_formula,
3033 *  
3034 *   const unsigned int dofs_per_cell_dual = fe_dual.dofs_per_cell;
3035 *   const unsigned int n_q_points = quadrature_formula.size();
3036 *  
3037 *   FullMatrix<double> cell_matrix (dofs_per_cell_dual, dofs_per_cell_dual);
3038 *  
3039 *   std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell_dual);
3040 *  
3042 *   cell_dual = dof_handler_dual.begin_active(),
3043 *   endc_dual = dof_handler_dual.end(),
3044 *   cell = dof_handler.begin_active();
3045 *  
3046 *   const FEValuesExtractors::Vector displacement(0);
3047 *  
3048 *   for (; cell_dual != endc_dual; ++cell_dual, ++cell)
3049 *   if (cell_dual->is_locally_owned())
3050 *   {
3051 *   fe_values.reinit(cell);
3052 *  
3053 *   fe_values_dual.reinit(cell_dual);
3054 *   cell_matrix = 0;
3055 *  
3056 *   std::vector<SymmetricTensor<2, dim> > strain_tensor(n_q_points);
3057 *   fe_values[displacement].get_function_symmetric_gradients(solution,
3058 *   strain_tensor);
3059 *  
3060 *   for (unsigned int q_point = 0; q_point < n_q_points; ++q_point)
3061 *   {
3062 *   SymmetricTensor<4, dim> stress_strain_tensor_linearized;
3063 *   SymmetricTensor<4, dim> stress_strain_tensor;
3064 *   constitutive_law.get_linearized_stress_strain_tensors(strain_tensor[q_point],
3065 *   stress_strain_tensor_linearized,
3066 *   stress_strain_tensor);
3067 *  
3068 *   for (unsigned int i = 0; i < dofs_per_cell_dual; ++i)
3069 *   {
3070 *   const SymmetricTensor<2, dim>
3071 *   stress_phi_i = stress_strain_tensor_linearized
3072 *   * fe_values_dual[displacement].symmetric_gradient(i, q_point);
3073 *  
3074 *   for (unsigned int j = 0; j < dofs_per_cell_dual; ++j)
3075 *   cell_matrix(i, j) += (stress_phi_i
3076 *   * fe_values_dual[displacement].symmetric_gradient(j, q_point)
3077 *   * fe_values_dual.JxW(q_point));
3078 *  
3079 *   }
3080 *  
3081 *   }
3082 *  
3083 *   cell_dual->get_dof_indices(local_dof_indices);
3084 *   constraints_dirichlet_and_hanging_nodes_dual.distribute_local_to_global(cell_matrix,
3085 *   local_dof_indices,
3086 *   system_matrix_dual);
3087 *  
3088 *   }
3089 *  
3090 *   }
3091 *  
3092 *  
3093 *   template<int dim>
3094 *   void DualSolver<dim>::assemble_rhs()
3095 *   {
3096 *   dual_functional->assemble_rhs (dof_handler, solution, constitutive_law,
3097 *   dof_handler_dual, system_rhs_dual);
3098 *   constraints_dirichlet_and_hanging_nodes_dual.condense (system_rhs_dual);
3099 *   }
3100 *  
3101 *  
3102 *   template<int dim>
3103 *   void DualSolver<dim>::solve()
3104 *   {
3105 * @endcode
3106 *
3107 * +++ direct solver +++++++++
3108 *
3109 * @code
3110 *   SparseDirectUMFPACK A_direct;
3111 *   A_direct.initialize(system_matrix_dual);
3112 *  
3113 * @endcode
3114 *
3115 * After the decomposition, we can use A_direct like a matrix representing
3116 * the inverse of our system matrix, so to compute the solution we just
3117 * have to multiply with the right hand side vector:
3118 *
3119 * @code
3120 *   A_direct.vmult(solution_dual, system_rhs_dual);
3121 *  
3122 * @endcode
3123 *
3124 * ++++ iterative solver ++ CG ++++ doesn't work
3125 * SolverControl solver_control (5000, 1e-12);
3126 * SolverCG<> cg (solver_control);
3127 *
3128
3129 *
3130 * PreconditionSSOR<> preconditioner;
3131 * preconditioner.initialize(system_matrix_dual, 1.2);
3132 *
3133
3134 *
3135 * cg.solve (system_matrix_dual, solution_dual, system_rhs_dual,
3136 * preconditioner);
3137 *
3138
3139 *
3140 * ++++ iterative solver ++ BiCGStab ++++++ doesn't work
3141 * SolverControl solver_control (5000, 1e-12);
3142 * SolverBicgstab<> bicgstab (solver_control);
3143 *
3144
3145 *
3146 * PreconditionJacobi<> preconditioner;
3147 * preconditioner.initialize(system_matrix_dual, 1.0);
3148 *
3149
3150 *
3151 * bicgstab.solve (system_matrix_dual, solution_dual, system_rhs_dual,
3152 * preconditioner);
3153 *
3154
3155 *
3156 * +++++++++++++++++++++++++++++++++++++++++++++++++
3157 *
3158
3159 *
3160 *
3161 * @code
3162 *   constraints_dirichlet_and_hanging_nodes_dual.distribute (solution_dual);
3163 *   }
3164 *  
3165 *   template<int dim>
3166 *   void DualSolver<dim>::output_results()
3167 *   {
3168 *   std::string filename = (output_dir + "dual-solution-" +
3169 *   Utilities::int_to_string(timestep_no, 4) + ".vtk");
3170 *   std::ofstream output (filename.c_str());
3171 *   DataOut<dim> data_out;
3172 *   data_out.attach_dof_handler (dof_handler_dual);
3173 *   std::vector<std::string> solution_names;
3174 *   switch (dim)
3175 *   {
3176 *   case 1:
3177 *   solution_names.push_back ("displacement");
3178 *   break;
3179 *   case 2:
3180 *   solution_names.push_back ("x_displacement");
3181 *   solution_names.push_back ("y_displacement");
3182 *   break;
3183 *   case 3:
3184 *   solution_names.push_back ("x_displacement");
3185 *   solution_names.push_back ("y_displacement");
3186 *   solution_names.push_back ("z_displacement");
3187 *   break;
3188 *   default:
3189 *   Assert (false, ExcNotImplemented());
3190 *   }
3191 *   data_out.add_data_vector (solution_dual, solution_names);
3192 *   data_out.build_patches ();
3193 *   data_out.write_vtk (output);
3194 *   }
3195 *  
3196 *   template<int dim>
3197 *   void DualSolver<dim>::compute_error_DWR (Vector<float> &estimated_error_per_cell)
3198 *   {
3199 *   Assert (estimated_error_per_cell.size() == triangulation->n_global_active_cells(),
3200 *   ExcDimensionMismatch (estimated_error_per_cell.size(), triangulation->n_global_active_cells()));
3201 *  
3202 * @endcode
3203 *
3204 * solve the dual problem
3205 *
3206 * @code
3207 *   setup_system ();
3208 *   assemble_matrix ();
3209 *   assemble_rhs ();
3210 *   solve ();
3211 *   output_results ();
3212 *  
3213 * @endcode
3214 *
3215 * compuate the dual weights
3216 *
3217 * @code
3218 *   Vector<double> primal_solution (dof_handler_dual.n_dofs());
3219 *   FETools::interpolate (dof_handler,
3220 *   solution,
3221 *   dof_handler_dual,
3222 *   constraints_dirichlet_and_hanging_nodes_dual,
3223 *   primal_solution);
3224 *  
3225 *   AffineConstraints<double> constraints_hanging_nodes;
3227 *   constraints_hanging_nodes);
3228 *   constraints_hanging_nodes.close();
3229 *   Vector<double> dual_weights (dof_handler_dual.n_dofs());
3230 *   FETools::interpolation_difference (dof_handler_dual,
3231 *   constraints_dirichlet_and_hanging_nodes_dual,
3232 *   solution_dual,
3233 *   dof_handler,
3234 *   constraints_hanging_nodes,
3235 *   dual_weights);
3236 *  
3237 * @endcode
3238 *
3239 * estimate the error
3240 *
3241 * @code
3242 *   FEValues<dim> fe_values(fe_dual, quadrature_formula,
3243 *   update_values |
3244 *   update_gradients |
3245 *   update_hessians |
3247 *   update_JxW_values);
3248 *  
3249 *   const unsigned int n_q_points = quadrature_formula.size();
3250 *   std::vector<SymmetricTensor<2, dim> > strain_tensor(n_q_points);
3251 *   SymmetricTensor<4, dim> stress_strain_tensor_linearized;
3252 *   SymmetricTensor<4, dim> stress_strain_tensor;
3253 *   Tensor<5, dim> stress_strain_tensor_grad;
3254 *   std::vector<std::vector<Tensor<2,dim> > > cell_hessians (n_q_points);
3255 *   for (unsigned int i=0; i!=n_q_points; ++i)
3256 *   {
3257 *   cell_hessians[i].resize (dim);
3258 *   }
3259 *   std::vector<Vector<double> > dual_weights_cell_values (n_q_points, Vector<double>(dim));
3260 *  
3261 *   const EquationData::BodyForce<dim> body_force;
3262 *   std::vector<Vector<double> > body_force_values (n_q_points, Vector<double>(dim));
3263 *   const FEValuesExtractors::Vector displacement(0);
3264 *  
3265 *  
3266 *   FEFaceValues<dim> fe_face_values_cell(fe_dual, face_quadrature_formula,
3267 *   update_values |
3269 *   update_gradients |
3270 *   update_JxW_values |
3272 *   fe_face_values_neighbor (fe_dual, face_quadrature_formula,
3273 *   update_values |
3274 *   update_gradients |
3275 *   update_JxW_values |
3277 *   FESubfaceValues<dim> fe_subface_values_cell (fe_dual, face_quadrature_formula,
3278 *   update_gradients);
3279 *  
3280 *   const unsigned int n_face_q_points = face_quadrature_formula.size();
3281 *   std::vector<Vector<double> > jump_residual (n_face_q_points, Vector<double>(dim));
3282 *   std::vector<Vector<double> > dual_weights_face_values (n_face_q_points, Vector<double>(dim));
3283 *  
3284 *   std::vector<std::vector<Tensor<1,dim> > > cell_grads(n_face_q_points);
3285 *   for (unsigned int i=0; i!=n_face_q_points; ++i)
3286 *   {
3287 *   cell_grads[i].resize (dim);
3288 *   }
3289 *   std::vector<std::vector<Tensor<1,dim> > > neighbor_grads(n_face_q_points);
3290 *   for (unsigned int i=0; i!=n_face_q_points; ++i)
3291 *   {
3292 *   neighbor_grads[i].resize (dim);
3293 *   }
3294 *   SymmetricTensor<2, dim> q_cell_strain_tensor;
3295 *   SymmetricTensor<2, dim> q_neighbor_strain_tensor;
3296 *   SymmetricTensor<4, dim> cell_stress_strain_tensor;
3297 *   SymmetricTensor<4, dim> neighbor_stress_strain_tensor;
3298 *  
3299 *  
3300 *   typename std::map<typename DoFHandler<dim>::face_iterator, Vector<double> >
3301 *   face_integrals;
3303 *   cell = dof_handler_dual.begin_active(),
3304 *   endc = dof_handler_dual.end();
3305 *   for (; cell!=endc; ++cell)
3306 *   if (cell->is_locally_owned())
3307 *   {
3308 *   for (unsigned int face_no=0;
3309 *   face_no<GeometryInfo<dim>::faces_per_cell;
3310 *   ++face_no)
3311 *   {
3312 *   face_integrals[cell->face(face_no)].reinit (dim);
3313 *   face_integrals[cell->face(face_no)] = -1e20;
3314 *   }
3315 *   }
3316 *  
3317 *   std::vector<Vector<float> > error_indicators_vector;
3318 *   error_indicators_vector.resize( triangulation->n_active_cells(),
3319 *   Vector<float>(dim) );
3320 *  
3321 * @endcode
3322 *
3323 * ----------------- estimate_some -------------------------
3324 *
3325 * @code
3326 *   cell = dof_handler_dual.begin_active();
3327 *   unsigned int present_cell = 0;
3328 *   for (; cell!=endc; ++cell, ++present_cell)
3329 *   if (cell->is_locally_owned())
3330 *   {
3331 * @endcode
3332 *
3333 * --------------- integrate_over_cell -------------------
3334 *
3335 * @code
3336 *   fe_values.reinit(cell);
3337 *   body_force.vector_value_list(fe_values.get_quadrature_points(),
3338 *   body_force_values);
3339 *   fe_values[displacement].get_function_symmetric_gradients(primal_solution,
3340 *   strain_tensor);
3341 *   fe_values.get_function_hessians(primal_solution, cell_hessians);
3342 *  
3343 *   fe_values.get_function_values(dual_weights,
3344 *   dual_weights_cell_values);
3345 *  
3346 *   for (unsigned int q_point = 0; q_point < n_q_points; ++q_point)
3347 *   {
3348 *   constitutive_law.get_linearized_stress_strain_tensors(strain_tensor[q_point],
3349 *   stress_strain_tensor_linearized,
3350 *   stress_strain_tensor);
3351 *   constitutive_law.get_grad_stress_strain_tensor(strain_tensor[q_point],
3352 *   cell_hessians[q_point],
3353 *   stress_strain_tensor_grad);
3354 *  
3355 *   for (unsigned int i=0; i!=dim; ++i)
3356 *   {
3357 *   error_indicators_vector[present_cell](i) +=
3358 *   body_force_values[q_point](i)*
3359 *   dual_weights_cell_values[q_point](i)*
3360 *   fe_values.JxW(q_point);
3361 *   for (unsigned int j=0; j!=dim; ++j)
3362 *   {
3363 *   for (unsigned int k=0; k!=dim; ++k)
3364 *   {
3365 *   for (unsigned int l=0; l!=dim; ++l)
3366 *   {
3367 *   error_indicators_vector[present_cell](i) +=
3368 *   ( stress_strain_tensor[i][j][k][l]*
3369 *   0.5*(cell_hessians[q_point][k][l][j]
3370 *   +
3371 *   cell_hessians[q_point][l][k][j])
3372 *   + stress_strain_tensor_grad[i][j][k][l][j] * strain_tensor[q_point][k][l]
3373 *   ) *
3374 *   dual_weights_cell_values[q_point](i) *
3375 *   fe_values.JxW(q_point);
3376 *   }
3377 *   }
3378 *   }
3379 *  
3380 *   }
3381 *  
3382 *   }
3383 * @endcode
3384 *
3385 * -------------------------------------------------------
3386 * compute face_integrals
3387 *
3388 * @code
3389 *   for (unsigned int face_no=0;
3390 *   face_no<GeometryInfo<dim>::faces_per_cell;
3391 *   ++face_no)
3392 *   {
3393 *   if (cell->face(face_no)->at_boundary())
3394 *   {
3395 *   for (unsigned int id=0; id!=dim; ++id)
3396 *   {
3397 *   face_integrals[cell->face(face_no)](id) = 0;
3398 *   }
3399 *   continue;
3400 *   }
3401 *  
3402 *   if ((cell->neighbor(face_no)->has_children() == false) &&
3403 *   (cell->neighbor(face_no)->level() == cell->level()) &&
3404 *   (cell->neighbor(face_no)->index() < cell->index()))
3405 *   continue;
3406 *  
3407 *   if (cell->at_boundary(face_no) == false)
3408 *   if (cell->neighbor(face_no)->level() < cell->level())
3409 *   continue;
3410 *  
3411 *  
3412 *   if (cell->face(face_no)->has_children() == false)
3413 *   {
3414 * @endcode
3415 *
3416 * ------------- integrate_over_regular_face -----------
3417 *
3418 * @code
3419 *   fe_face_values_cell.reinit(cell, face_no);
3420 *   fe_face_values_cell.get_function_gradients (primal_solution,
3421 *   cell_grads);
3422 *  
3423 *   Assert (cell->neighbor(face_no).state() == IteratorState::valid,
3424 *   ExcInternalError());
3425 *   const unsigned int
3426 *   neighbor_neighbor = cell->neighbor_of_neighbor (face_no);
3427 *   const typename DoFHandler<dim>::active_cell_iterator
3428 *   neighbor = cell->neighbor(face_no);
3429 *  
3430 *   fe_face_values_neighbor.reinit(neighbor, neighbor_neighbor);
3431 *   fe_face_values_neighbor.get_function_gradients (primal_solution,
3432 *   neighbor_grads);
3433 *  
3434 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
3435 *   {
3436 *   q_cell_strain_tensor = 0.;
3437 *   q_neighbor_strain_tensor = 0.;
3438 *   for (unsigned int i=0; i!=dim; ++i)
3439 *   {
3440 *   for (unsigned int j=0; j!=dim; ++j)
3441 *   {
3442 *   q_cell_strain_tensor[i][j] = 0.5*(cell_grads[q_point][i][j] +
3443 *   cell_grads[q_point][j][i] );
3444 *   q_neighbor_strain_tensor[i][j] = 0.5*(neighbor_grads[q_point][i][j] +
3445 *   neighbor_grads[q_point][j][i] );
3446 *   }
3447 *   }
3448 *  
3449 *   constitutive_law.get_stress_strain_tensor (q_cell_strain_tensor,
3450 *   cell_stress_strain_tensor);
3451 *   constitutive_law.get_stress_strain_tensor (q_neighbor_strain_tensor,
3452 *   neighbor_stress_strain_tensor);
3453 *  
3454 *   jump_residual[q_point] = 0.;
3455 *   for (unsigned int i=0; i!=dim; ++i)
3456 *   {
3457 *   for (unsigned int j=0; j!=dim; ++j)
3458 *   {
3459 *   for (unsigned int k=0; k!=dim; ++k)
3460 *   {
3461 *   for (unsigned int l=0; l!=dim; ++l)
3462 *   {
3463 *   jump_residual[q_point](i) += (cell_stress_strain_tensor[i][j][k][l]*
3464 *   q_cell_strain_tensor[k][l]
3465 *   -
3466 *   neighbor_stress_strain_tensor[i][j][k][l]*
3467 *   q_neighbor_strain_tensor[k][l] )*
3468 *   fe_face_values_cell.normal_vector(q_point)[j];
3469 *   }
3470 *   }
3471 *   }
3472 *   }
3473 *  
3474 *   }
3475 *  
3476 *   fe_face_values_cell.get_function_values (dual_weights,
3477 *   dual_weights_face_values);
3478 *  
3479 *   Vector<double> face_integral_vector(dim);
3480 *   face_integral_vector = 0;
3481 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
3482 *   {
3483 *   for (unsigned int i=0; i!=dim; ++i)
3484 *   {
3485 *   face_integral_vector(i) += jump_residual[q_point](i) *
3486 *   dual_weights_face_values[q_point](i) *
3487 *   fe_face_values_cell.JxW(q_point);
3488 *   }
3489 *   }
3490 *  
3491 *   Assert (face_integrals.find (cell->face(face_no)) != face_integrals.end(),
3492 *   ExcInternalError());
3493 *  
3494 *   for (unsigned int i=0; i!=dim; ++i)
3495 *   {
3496 *   Assert (face_integrals[cell->face(face_no)](i) == -1e20,
3497 *   ExcInternalError());
3498 *   face_integrals[cell->face(face_no)](i) = face_integral_vector(i);
3499 *  
3500 *   }
3501 *  
3502 * @endcode
3503 *
3504 * -----------------------------------------------------
3505 *
3506 * @code
3507 *   }
3508 *   else
3509 *   {
3510 * @endcode
3511 *
3512 * ------------- integrate_over_irregular_face ---------
3513 *
3514 * @code
3515 *   const typename DoFHandler<dim>::face_iterator
3516 *   face = cell->face(face_no);
3517 *   const typename DoFHandler<dim>::cell_iterator
3518 *   neighbor = cell->neighbor(face_no);
3519 *   Assert (neighbor.state() == IteratorState::valid,
3520 *   ExcInternalError());
3521 *   Assert (neighbor->has_children(),
3522 *   ExcInternalError());
3523 *  
3524 *   const unsigned int
3525 *   neighbor_neighbor = cell->neighbor_of_neighbor (face_no);
3526 *  
3527 *   for (unsigned int subface_no=0;
3528 *   subface_no<face->n_children(); ++subface_no)
3529 *   {
3530 *   const typename DoFHandler<dim>::active_cell_iterator
3531 *   neighbor_child = cell->neighbor_child_on_subface (face_no, subface_no);
3532 *   Assert (neighbor_child->face(neighbor_neighbor) ==
3533 *   cell->face(face_no)->child(subface_no),
3534 *   ExcInternalError());
3535 *  
3536 *   fe_subface_values_cell.reinit (cell, face_no, subface_no);
3537 *   fe_subface_values_cell.get_function_gradients (primal_solution,
3538 *   cell_grads);
3539 *   fe_face_values_neighbor.reinit (neighbor_child,
3540 *   neighbor_neighbor);
3541 *   fe_face_values_neighbor.get_function_gradients (primal_solution,
3542 *   neighbor_grads);
3543 *  
3544 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
3545 *   {
3546 *   q_cell_strain_tensor = 0.;
3547 *   q_neighbor_strain_tensor = 0.;
3548 *   for (unsigned int i=0; i!=dim; ++i)
3549 *   {
3550 *   for (unsigned int j=0; j!=dim; ++j)
3551 *   {
3552 *   q_cell_strain_tensor[i][j] = 0.5*(cell_grads[q_point][i][j] +
3553 *   cell_grads[q_point][j][i] );
3554 *   q_neighbor_strain_tensor[i][j] = 0.5*(neighbor_grads[q_point][i][j] +
3555 *   neighbor_grads[q_point][j][i] );
3556 *   }
3557 *   }
3558 *  
3559 *   constitutive_law.get_stress_strain_tensor (q_cell_strain_tensor,
3560 *   cell_stress_strain_tensor);
3561 *   constitutive_law.get_stress_strain_tensor (q_neighbor_strain_tensor,
3562 *   neighbor_stress_strain_tensor);
3563 *  
3564 *   jump_residual[q_point] = 0.;
3565 *   for (unsigned int i=0; i!=dim; ++i)
3566 *   {
3567 *   for (unsigned int j=0; j!=dim; ++j)
3568 *   {
3569 *   for (unsigned int k=0; k!=dim; ++k)
3570 *   {
3571 *   for (unsigned int l=0; l!=dim; ++l)
3572 *   {
3573 *   jump_residual[q_point](i) += (-cell_stress_strain_tensor[i][j][k][l]*
3574 *   q_cell_strain_tensor[k][l]
3575 *   +
3576 *   neighbor_stress_strain_tensor[i][j][k][l]*
3577 *   q_neighbor_strain_tensor[k][l] )*
3578 *   fe_face_values_neighbor.normal_vector(q_point)[j];
3579 *   }
3580 *   }
3581 *   }
3582 *   }
3583 *  
3584 *   }
3585 *  
3586 *   fe_face_values_neighbor.get_function_values (dual_weights,
3587 *   dual_weights_face_values);
3588 *  
3589 *   Vector<double> face_integral_vector(dim);
3590 *   face_integral_vector = 0;
3591 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
3592 *   {
3593 *   for (unsigned int i=0; i!=dim; ++i)
3594 *   {
3595 *   face_integral_vector(i) += jump_residual[q_point](i) *
3596 *   dual_weights_face_values[q_point](i) *
3597 *   fe_face_values_neighbor.JxW(q_point);
3598 *   }
3599 *   }
3600 *  
3601 *   for (unsigned int i=0; i!=dim; ++i)
3602 *   {
3603 *   face_integrals[neighbor_child->face(neighbor_neighbor)](i) = face_integral_vector(i);
3604 *   }
3605 *  
3606 *   }
3607 *  
3608 *   Vector<double> sum (dim);
3609 *   sum = 0;
3610 *   for (unsigned int subface_no=0;
3611 *   subface_no<face->n_children(); ++subface_no)
3612 *   {
3613 *   Assert (face_integrals.find(face->child(subface_no)) !=
3614 *   face_integrals.end(),
3615 *   ExcInternalError());
3616 *   for (unsigned int i=0; i!=dim; ++i)
3617 *   {
3618 *   Assert (face_integrals[face->child(subface_no)](i) != -1e20,
3619 *   ExcInternalError());
3620 *   sum(i) += face_integrals[face->child(subface_no)](i);
3621 *   }
3622 *   }
3623 *   for (unsigned int i=0; i!=dim; ++i)
3624 *   {
3625 *   face_integrals[face](i) = sum(i);
3626 *   }
3627 *  
3628 *  
3629 * @endcode
3630 *
3631 * -----------------------------------------------------
3632 *
3633 * @code
3634 *   }
3635 *  
3636 *  
3637 *   }
3638 *   }
3639 * @endcode
3640 *
3641 * ----------------------------------------------------------
3642 *
3643
3644 *
3645 *
3646 * @code
3647 *   present_cell=0;
3648 *   cell = dof_handler_dual.begin_active();
3649 *   for (; cell!=endc; ++cell, ++present_cell)
3650 *   if (cell->is_locally_owned())
3651 *   {
3652 *   for (unsigned int face_no=0; face_no<GeometryInfo<dim>::faces_per_cell;
3653 *   ++face_no)
3654 *   {
3655 *   Assert(face_integrals.find(cell->face(face_no)) !=
3656 *   face_integrals.end(),
3657 *   ExcInternalError());
3658 *  
3659 *   for (unsigned int id=0; id!=dim; ++id)
3660 *   {
3661 *   error_indicators_vector[present_cell](id)
3662 *   -= 0.5*face_integrals[cell->face(face_no)](id);
3663 *   }
3664 *  
3665 *   }
3666 *  
3667 *   estimated_error_per_cell(present_cell) = error_indicators_vector[present_cell].l2_norm();
3668 *  
3669 *   }
3670 *   }
3671 *  
3672 *  
3673 *  
3674 * @endcode
3675 *
3676 *
3677 * <a name="elastoplastic.cc-ThecodePlasticityContactProblemcodeclasstemplate"></a>
3678 * <h3>The <code>PlasticityContactProblem</code> class template</h3>
3679 *
3680
3681 *
3682 * This is the main class of this program and supplies all functions
3683 * and variables needed to describe
3684 * the nonlinear contact problem. It is
3685 * close to @ref step_41 "step-41" but with some additional
3686 * features like handling hanging nodes,
3687 * a Newton method, using Trilinos and p4est
3688 * for parallel distributed computing.
3689 * To deal with hanging nodes makes
3690 * life a bit more complicated since
3691 * we need another AffineConstraints object now.
3692 * We create a Newton method for the
3693 * active set method for the contact
3694 * situation and to handle the nonlinear
3695 * operator for the constitutive law.
3696 *
3697
3698 *
3699 * The general layout of this class is very much like for most other tutorial programs.
3700 * To make our life a bit easier, this class reads a set of input parameters from an input file. These
3701 * parameters, using the ParameterHandler class, are declared in the <code>declare_parameters</code>
3702 * function (which is static so that it can be called before we even create an object of the current
3703 * type), and a ParameterHandler object that has been used to read an input file will then be passed
3704 * to the constructor of this class.
3705 *
3706
3707 *
3708 * The remaining member functions are by and large as we have seen in several of the other tutorial
3709 * programs, though with additions for the current nonlinear system. We will comment on their purpose
3710 * as we get to them further below.
3711 *
3712 * @code
3713 *   template <int dim>
3714 *   class ElastoPlasticProblem
3715 *   {
3716 *   public:
3717 *   ElastoPlasticProblem (const ParameterHandler &prm);
3718 *  
3719 *   void run ();
3720 *  
3721 *   static void declare_parameters (ParameterHandler &prm);
3722 *  
3723 *   private:
3724 *   void make_grid ();
3725 *   void setup_system ();
3726 *   void compute_dirichlet_constraints ();
3727 *   void assemble_newton_system (const TrilinosWrappers::MPI::Vector &linearization_point,
3728 *   const TrilinosWrappers::MPI::Vector &delta_linearization_point);
3729 *   void compute_nonlinear_residual (const TrilinosWrappers::MPI::Vector &linearization_point);
3730 *   void solve_newton_system ();
3731 *   void solve_newton ();
3732 *   void compute_error ();
3733 *   void compute_error_residual (const TrilinosWrappers::MPI::Vector &tmp_solution);
3734 *   void refine_grid ();
3735 *   void move_mesh (const TrilinosWrappers::MPI::Vector &displacement) const;
3736 *   void output_results (const std::string &filename_base);
3737 *  
3738 * @endcode
3739 *
3740 * Next are three functions that handle the history variables stored in each
3741 * quadrature point. The first one is called before the first timestep to
3742 * set up a pristine state for the history variables. It only works on
3743 * those quadrature points on cells that belong to the present processor:
3744 *
3745 * @code
3746 *   void setup_quadrature_point_history ();
3747 *  
3748 * @endcode
3749 *
3750 * The second one updates the history variables at the end of each
3751 * timestep:
3752 *
3753 * @code
3754 *   void update_quadrature_point_history ();
3755 *  
3756 * @endcode
3757 *
3758 * As far as member variables are concerned, we start with ones that we use to
3759 * indicate the MPI universe this program runs on, and then two numbers
3760 * telling us how many participating processors there are, and where in
3761 * this world we are., a stream we use to let
3762 * exactly one processor produce output to the console (see @ref step_17 "step-17") and
3763 * a variable that is used to time the various sections of the program:
3764 *
3765 * @code
3766 *   MPI_Comm mpi_communicator;
3767 *   const unsigned int n_mpi_processes;
3768 *   const unsigned int this_mpi_process;
3769 *   ConditionalOStream pcout;
3770 *   TimerOutput computing_timer;
3771 *  
3772 * @endcode
3773 *
3774 * The next group describes the mesh and the finite element space.
3775 * In particular, for this parallel program, the finite element
3776 * space has associated with it variables that indicate which degrees
3777 * of freedom live on the current processor (the index sets, see
3778 * also @ref step_40 "step-40" and the @ref distributed documentation module) as
3779 * well as a variety of constraints: those imposed by hanging nodes,
3780 * by Dirichlet boundary conditions, and by the active set of
3781 * contact nodes. Of the three AffineConstraints objects defined
3782 * here, the first only contains hanging node constraints, the
3783 * second also those associated with Dirichlet boundary conditions,
3784 * and the third these plus the contact constraints.
3785 *
3786
3787 *
3788 * The variable <code>active_set</code> consists of those degrees
3789 * of freedom constrained by the contact, and we use
3790 * <code>fraction_of_plastic_q_points_per_cell</code> to keep
3791 * track of the fraction of quadrature points on each cell where
3792 * the stress equals the yield stress. The latter is only used to
3793 * create graphical output showing the plastic zone, but not for
3794 * any further computation; the variable is a member variable of
3795 * this class since the information is computed as a by-product
3796 * of computing the residual, but is used only much later. (Note
3797 * that the vector is a vector of length equal to the number of
3798 * active cells on the <i>local mesh</i>; it is never used to
3799 * exchange information between processors and can therefore be
3800 * a regular deal.II vector.)
3801 *
3802 * @code
3803 *   const unsigned int n_initial_global_refinements;
3805 *  
3806 *   const unsigned int fe_degree;
3807 *   FESystem<dim> fe;
3808 *   DoFHandler<dim> dof_handler;
3809 *  
3810 *   IndexSet locally_owned_dofs;
3811 *   IndexSet locally_relevant_dofs;
3812 *  
3813 *   AffineConstraints<double> constraints_hanging_nodes;
3814 *   AffineConstraints<double> constraints_dirichlet_and_hanging_nodes;
3815 *  
3816 *   Vector<float> fraction_of_plastic_q_points_per_cell;
3817 *  
3818 * @endcode
3819 *
3820 * One difference of this program is that we declare the quadrature
3821 * formula in the class declaration. The reason is that in all the other
3822 * programs, it didn't do much harm if we had used different quadrature
3823 * formulas when computing the matrix and the right hand side, for
3824 * example. However, in the present case it does: we store information in
3825 * the quadrature points, so we have to make sure all parts of the program
3826 * agree on where they are and how many there are on each cell. Thus, let
3827 * us first declare the quadrature formula that will be used throughout...
3828 *
3829 * @code
3830 *   const QGauss<dim> quadrature_formula;
3831 *   const QGauss<dim - 1> face_quadrature_formula;
3832 *  
3833 * @endcode
3834 *
3835 * ... and then also have a vector of history objects, one per quadrature
3836 * point on those cells for which we are responsible (i.e. we don't store
3837 * history data for quadrature points on cells that are owned by other
3838 * processors).
3839 *
3840 * @code
3841 *   std::vector<PointHistory<dim> > quadrature_point_history;
3842 *  
3843 * @endcode
3844 *
3845 * The way this object is accessed is through a <code>user pointer</code>
3846 * that each cell, face, or edge holds: it is a <code>void*</code> pointer
3847 * that can be used by application programs to associate arbitrary data to
3848 * cells, faces, or edges. What the program actually does with this data
3849 * is within its own responsibility, the library just allocates some space
3850 * for these pointers, and application programs can set and read the
3851 * pointers for each of these objects.
3852 *
3853
3854 *
3855 *
3856
3857 *
3858 * The next block of variables corresponds to the solution
3859 * and the linear systems we need to form. In particular, this
3860 * includes the Newton matrix and right hand side; the vector
3861 * that corresponds to the residual (i.e., the Newton right hand
3862 * side) but from which we have not eliminated the various
3863 * constraints and that is used to determine which degrees of
3864 * freedom need to be constrained in the next iteration; and
3865 * a vector that corresponds to the diagonal of the @f$B@f$ matrix
3866 * briefly mentioned in the introduction and discussed in the
3867 * accompanying paper.
3868 *
3869 * @code
3870 *   TrilinosWrappers::SparseMatrix newton_matrix;
3871 *  
3872 *   TrilinosWrappers::MPI::Vector solution;
3873 *   TrilinosWrappers::MPI::Vector incremental_displacement;
3874 *   TrilinosWrappers::MPI::Vector newton_rhs;
3875 *   TrilinosWrappers::MPI::Vector newton_rhs_residual;
3876 *  
3877 * @endcode
3878 *
3879 * The next block of variables is then related to the time dependent
3880 * nature of the problem: they denote the length of the time interval
3881 * which we want to simulate, the present time and number of time step,
3882 * and length of present timestep:
3883 *
3884 * @code
3885 *   double present_time;
3886 *   double present_timestep;
3887 *   double end_time;
3888 *   unsigned int timestep_no;
3889 *  
3890 * @endcode
3891 *
3892 * The next block contains the variables that describe the material
3893 * response:
3894 *
3895 * @code
3896 *   const double e_modulus, nu, sigma_0, gamma;
3897 *   ConstitutiveLaw<dim> constitutive_law;
3898 *  
3899 * @endcode
3900 *
3901 * And then there is an assortment of other variables that are used
3902 * to identify the mesh we are asked to build as selected by the
3903 * parameter file, the obstacle that is being pushed into the
3904 * deformable body, the mesh refinement strategy, whether to transfer
3905 * the solution from one mesh to the next, and how many mesh
3906 * refinement cycles to perform. As possible, we mark these kinds
3907 * of variables as <code>const</code> to help the reader identify
3908 * which ones may or may not be modified later on (the output directory
3909 * being an exception -- it is never modified outside the constructor
3910 * but it is awkward to initialize in the member-initializer-list
3911 * following the colon in the constructor since there we have only
3912 * one shot at setting it; the same is true for the mesh refinement
3913 * criterion):
3914 *
3915 * @code
3916 *   const std::string base_mesh;
3917 *  
3918 *   struct RefinementStrategy
3919 *   {
3920 *   enum value
3921 *   {
3922 *   refine_global,
3923 *   refine_percentage,
3924 *   refine_fix_dofs
3925 *   };
3926 *   };
3927 *   typename RefinementStrategy::value refinement_strategy;
3928 *  
3929 *   struct ErrorEstimationStrategy
3930 *   {
3931 *   enum value
3932 *   {
3933 *   kelly_error,
3934 *   residual_error,
3935 *   weighted_residual_error,
3936 *   weighted_kelly_error
3937 *   };
3938 *   };
3939 *   typename ErrorEstimationStrategy::value error_estimation_strategy;
3940 *  
3941 *   Vector<float> estimated_error_per_cell;
3942 *  
3943 *   const bool transfer_solution;
3944 *   std::string output_dir;
3945 *   TableHandler table_results,
3946 *   table_results_2,
3947 *   table_results_3;
3948 *  
3949 *   unsigned int current_refinement_cycle;
3950 *  
3951 *   const double max_relative_error;
3952 *   float relative_error;
3953 *  
3954 *   const bool show_stresses;
3955 *   };
3956 *  
3957 *  
3958 * @endcode
3959 *
3960 *
3961 * <a name="elastoplastic.cc-ImplementationofthecodePlasticityContactProblemcodeclass"></a>
3962 * <h3>Implementation of the <code>PlasticityContactProblem</code> class</h3>
3963 *
3964
3965 *
3966 *
3967 * <a name="elastoplastic.cc-PlasticityContactProblemdeclare_parameters"></a>
3968 * <h4>PlasticityContactProblem::declare_parameters</h4>
3969 *
3970
3971 *
3972 * Let us start with the declaration of run-time parameters that can be
3973 * selected in the input file. These values will be read back in the
3974 * constructor of this class to initialize the member variables of this
3975 * class:
3976 *
3977 * @code
3978 *   template <int dim>
3979 *   void
3980 *   ElastoPlasticProblem<dim>::declare_parameters (ParameterHandler &prm)
3981 *   {
3982 *   prm.declare_entry("polynomial degree", "1",
3983 *   Patterns::Integer(),
3984 *   "Polynomial degree of the FE_Q finite element space, typically 1 or 2.");
3985 *   prm.declare_entry("number of initial refinements", "2",
3986 *   Patterns::Integer(),
3987 *   "Number of initial global mesh refinement steps before "
3988 *   "the first computation.");
3989 *   prm.declare_entry("refinement strategy", "percentage",
3990 *   Patterns::Selection("global|percentage"),
3991 *   "Mesh refinement strategy:\n"
3992 *   " global: one global refinement\n"
3993 *   " percentage: a fixed percentage of cells gets refined using the selected error estimator.");
3994 *   prm.declare_entry("error estimation strategy", "kelly_error",
3995 *   Patterns::Selection("kelly_error|residual_error|weighted_residual_error"),
3996 *   "Error estimation strategy:\n"
3997 *   " kelly_error: Kelly error estimator\n"
3998 *   " residual_error: residual-based error estimator\n"
3999 *   " weighted_residual_error: dual weighted residual (Goal-oriented) error estimator.\n");
4000 *   prm.declare_entry("maximum relative error","0.05",
4001 *   Patterns::Double(),
4002 *   "maximum relative error which plays the role of a criteria for refinement.");
4003 *   prm.declare_entry("number of cycles", "5",
4004 *   Patterns::Integer(),
4005 *   "Number of adaptive mesh refinement cycles to run.");
4006 *   prm.declare_entry("output directory", "",
4007 *   Patterns::Anything(),
4008 *   "Directory for output files (graphical output and benchmark "
4009 *   "statistics). If empty, use the current directory.");
4010 *   prm.declare_entry("transfer solution", "true",
4011 *   Patterns::Bool(),
4012 *   "Whether the solution should be used as a starting guess "
4013 *   "for the next finer mesh. If false, then the iteration starts at "
4014 *   "zero on every mesh.");
4015 *   prm.declare_entry("base mesh", "Thick_tube_internal_pressure",
4016 *   Patterns::Selection("Timoshenko beam|Thick_tube_internal_pressure|"
4017 *   "Perforated_strip_tension|Cantiliver_beam_3d"),
4018 *   "Select the shape of the domain: 'box' or 'half sphere'");
4019 *   prm.declare_entry("elasticity modulus","2.e11",
4020 *   Patterns::Double(),
4021 *   "Elasticity modulus of the material in MPa (N/mm2)");
4022 *   prm.declare_entry("Poissons ratio","0.3",
4023 *   Patterns::Double(),
4024 *   "Poisson's ratio of the material");
4025 *   prm.declare_entry("yield stress","2.e11",
4026 *   Patterns::Double(),
4027 *   "Yield stress of the material in MPa (N/mm2)");
4028 *   prm.declare_entry("isotropic hardening parameter","0.",
4029 *   Patterns::Double(),
4030 *   "Isotropic hardening parameter of the material");
4031 *   prm.declare_entry("show stresses", "false",
4032 *   Patterns::Bool(),
4033 *   "Whether illustrates the stresses and von Mises stresses or not.");
4034 *  
4035 *  
4036 *   }
4037 *  
4038 *  
4039 * @endcode
4040 *
4041 *
4042 * <a name="elastoplastic.cc-ThecodePlasticityContactProblemcodeconstructor"></a>
4043 * <h4>The <code>PlasticityContactProblem</code> constructor</h4>
4044 *
4045
4046 *
4047 * Given the declarations of member variables as well as the
4048 * declarations of run-time parameters that are read from the input
4049 * file, there is nothing surprising in this constructor. In the body
4050 * we initialize the mesh refinement strategy and the output directory,
4051 * creating such a directory if necessary.
4052 *
4053 * @code
4054 *   template <int dim>
4055 *   ElastoPlasticProblem<dim>::
4056 *   ElastoPlasticProblem (const ParameterHandler &prm)
4057 *   :
4058 *   mpi_communicator(MPI_COMM_WORLD),
4059 *   n_mpi_processes (Utilities::MPI::n_mpi_processes(mpi_communicator)),
4060 *   this_mpi_process (Utilities::MPI::this_mpi_process(mpi_communicator)),
4061 *   pcout(std::cout, this_mpi_process == 0),
4062 *   computing_timer(MPI_COMM_WORLD, pcout, TimerOutput::never,
4064 *  
4065 *   n_initial_global_refinements (prm.get_integer("number of initial refinements")),
4066 *   triangulation(mpi_communicator),
4067 *   fe_degree (prm.get_integer("polynomial degree")),
4068 *   fe(FE_Q<dim>(QGaussLobatto<1>(fe_degree+1)), dim),
4069 *   dof_handler(triangulation),
4070 *   quadrature_formula (fe_degree + 1),
4071 *   face_quadrature_formula (fe_degree + 1),
4072 *  
4073 *   e_modulus (prm.get_double("elasticity modulus")),
4074 *   nu (prm.get_double("Poissons ratio")),
4075 *   sigma_0(prm.get_double("yield stress")),
4076 *   gamma (prm.get_double("isotropic hardening parameter")),
4077 *   constitutive_law (e_modulus,
4078 *   nu,
4079 *   sigma_0,
4080 *   gamma),
4081 *  
4082 *   base_mesh (prm.get("base mesh")),
4083 *  
4084 *   transfer_solution (prm.get_bool("transfer solution")),
4085 *   table_results(),
4086 *   table_results_2(),
4087 *   table_results_3(),
4088 *   max_relative_error (prm.get_double("maximum relative error")),
4089 *   show_stresses (prm.get_bool("show stresses"))
4090 *   {
4091 *   std::string strat = prm.get("refinement strategy");
4092 *   if (strat == "global")
4093 *   refinement_strategy = RefinementStrategy::refine_global;
4094 *   else if (strat == "percentage")
4095 *   refinement_strategy = RefinementStrategy::refine_percentage;
4096 *   else
4097 *   AssertThrow (false, ExcNotImplemented());
4098 *  
4099 *   strat = prm.get("error estimation strategy");
4100 *   if (strat == "kelly_error")
4101 *   error_estimation_strategy = ErrorEstimationStrategy::kelly_error;
4102 *   else if (strat == "residual_error")
4103 *   error_estimation_strategy = ErrorEstimationStrategy::residual_error;
4104 *   else if (strat == "weighted_residual_error")
4105 *   error_estimation_strategy = ErrorEstimationStrategy::weighted_residual_error;
4106 *   else
4107 *   AssertThrow(false, ExcNotImplemented());
4108 *  
4109 *   output_dir = prm.get("output directory");
4110 *   if (output_dir != "" && *(output_dir.rbegin()) != '/')
4111 *   output_dir += "/";
4112 *   mkdir(output_dir.c_str(), 0777);
4113 *  
4114 *   pcout << " Using output directory '" << output_dir << "'" << std::endl;
4115 *   pcout << " FE degree " << fe_degree << std::endl;
4116 *   pcout << " transfer solution "
4117 *   << (transfer_solution ? "true" : "false") << std::endl;
4118 *   }
4119 *  
4120 *  
4121 *  
4122 * @endcode
4123 *
4124 *
4125 * <a name="elastoplastic.cc-PlasticityContactProblemmake_grid"></a>
4126 * <h4>PlasticityContactProblem::make_grid</h4>
4127 *
4128
4129 *
4130 * The next block deals with constructing the starting mesh.
4131 * We will use the following helper function and the first
4132 * block of the <code>make_grid()</code> to construct a
4133 * mesh that corresponds to a half sphere. deal.II has a function
4134 * that creates such a mesh, but it is in the wrong location
4135 * and facing the wrong direction, so we need to shift and rotate
4136 * it a bit before using it.
4137 *
4138
4139 *
4140 * For later reference, as described in the documentation of
4141 * GridGenerator::half_hyper_ball(), the flat surface of the halfsphere
4142 * has boundary indicator zero, while the remainder has boundary
4143 * indicator one.
4144 *
4145 * @code
4146 *   Point<3>
4147 *   rotate_half_sphere (const Point<3> &in)
4148 *   {
4149 *   return Point<3>(in(2), in(1), -in(0));
4150 *   }
4151 *  
4152 *   template <int dim>
4153 *   void
4154 *   ElastoPlasticProblem<dim>::make_grid ()
4155 *   {
4156 *   if (base_mesh == "Timoshenko beam")
4157 *   {
4158 *   AssertThrow (dim == 2, ExcNotImplemented());
4159 *  
4160 *   const double length = .48,
4161 *   depth = .12;
4162 *  
4163 *   const Point<dim> point_1(0, -depth/2),
4164 *   point_2(length, depth/2);
4165 *  
4166 *   std::vector<unsigned int> repetitions(2);
4167 *   repetitions[0] = 4;
4168 *   repetitions[1] = 1;
4169 *   GridGenerator::subdivided_hyper_rectangle(triangulation, repetitions, point_1, point_2);
4170 *  
4171 *  
4172 * @endcode
4173 *
4174 * give the indicators to boundaries for specification,
4175 *
4176
4177 *
4178 * ________100______
4179 * | |
4180 * 0 | | 5
4181 * |________________|
4182 * 100
4183 * 0 to essential boundary conditions (left edge) which are as default
4184 * 100 to the null boundaries (upper and lower edges) where we do not need to take care of them
4185 * 5 to the natural boundaries (right edge) for imposing the traction force
4186 *
4187 * @code
4189 *   cell = triangulation.begin_active(),
4190 *   endc = triangulation.end();
4191 *   for (; cell!=endc; ++cell)
4192 *   {
4193 *   for (unsigned int face=0; face!=GeometryInfo<dim>::faces_per_cell; ++face)
4194 *   {
4195 *   if ( std::fabs(cell->face(face)->center()(0)-length) < 1e-12 )
4196 *   {
4197 *   cell->face(face)->set_manifold_id(5);
4198 *   }
4199 *   else if ( ( std::fabs(cell->face(face)->center()(1)-(depth/2)) < 1e-12 )
4200 *   ||
4201 *   ( std::fabs(cell->face(face)->center()(1)-(-depth/2)) < 1e-12 ) )
4202 *   {
4203 *   cell->face(face)->set_manifold_id(100);
4204 *   }
4205 *  
4206 *   }
4207 *   }
4208 *  
4209 *   triangulation.refine_global(n_initial_global_refinements);
4210 *  
4211 *   }
4212 *   else if (base_mesh == "Thick_tube_internal_pressure")
4213 *   {
4214 * @endcode
4215 *
4216 * Example 1 from the paper: Zhong Z., .... A new numerical method for determining
4217 * collapse load-carrying capacity of structure made of elasto-plastic material,
4218 * J. Cent. South Univ. (2014) 21: 398-404
4219 *
4220 * @code
4221 *   AssertThrow (dim == 2, ExcNotImplemented());
4222 *  
4223 *   const Point<dim> center(0, 0);
4224 *   const double inner_radius = .1,
4225 *   outer_radius = .2;
4227 *   center, inner_radius, outer_radius,
4228 *   0, true);
4229 *  
4230 * @endcode
4231 *
4232 * give the indicators to boundaries for specification,
4233 *
4234
4235 *
4236 *
4237 * @code
4238 *   /* _____
4239 *   | \
4240 *   | \
4241 *   2 | \ 1
4242 *   |_ \
4243 *   \ \
4244 *   0 \ |
4245 *   |________|
4246 *   3
4247 *   */
4248 * @endcode
4249 *
4250 * 0 - inner boundary - natural boundary condition - impose the traction force
4251 * 1 - outer boundary - free boundary - we do not need to take care of them
4252 * 2 - left boundary - essential boundary condition - constrained to move along the x direction
4253 * 3 - bottom boundary - essential boundary condition - constrained to move along the y direction
4254 *
4255
4256 *
4257 *
4258 * @code
4259 *   const SphericalManifold<dim> inner_boundary_description(center);
4260 *   triangulation.set_manifold (0, inner_boundary_description);
4261 *  
4262 *   const SphericalManifold<dim> outer_boundary_description(center);
4263 *   triangulation.set_manifold (1, outer_boundary_description);
4264 *  
4265 *   triangulation.refine_global(n_initial_global_refinements);
4266 *  
4267 *   triangulation.reset_manifold (0);
4268 *   triangulation.reset_manifold (1);
4269 *  
4270 *   }
4271 *   else if (base_mesh == "Perforated_strip_tension")
4272 *   {
4273 * @endcode
4274 *
4275 * Example 2 from the paper: Zhong Z., .... A new numerical method for determining
4276 * collapse load-carrying capacity of structure made of elasto-plastic material,
4277 * J. Cent. South Univ. (2014) 21: 398-404
4278 *
4279 * @code
4280 *   AssertThrow (dim == 3, ExcNotImplemented());
4281 *  
4282 *   const int dim_2d = 2;
4283 *   const Point<dim_2d> center_2d(0, 0);
4284 *   const double inner_radius = 0.05,
4285 *   outer_radius = 0.1,
4286 *   height = 0.18,
4287 *   thickness = 0.004;
4288 * @endcode
4289 *
4290 * thickness = 0.01;
4291 *
4292
4293 *
4294 *
4295 * @code
4296 *   Triangulation<dim_2d> triangulation_1,
4297 *   triangulation_2,
4298 *   triangulation_2d;
4299 *  
4300 *   const double eps = 1e-7 * inner_radius;
4301 *   {
4302 *   Point<dim_2d> point;
4303 *  
4304 *   GridGenerator::quarter_hyper_shell(triangulation_1,
4305 *   center_2d, inner_radius, outer_radius,
4306 *   2);
4307 *  
4308 * @endcode
4309 *
4310 * Modify the triangulation_1
4311 *
4312 * @code
4314 *   cell = triangulation_1.begin_active(),
4315 *   endc = triangulation_1.end();
4316 *   std::vector<bool> treated_vertices(triangulation_1.n_vertices(), false);
4317 *   for (; cell != endc; ++cell)
4318 *   {
4319 *   for (unsigned int f=0; f<GeometryInfo<dim_2d>::faces_per_cell; ++f)
4320 *   if (cell->face(f)->at_boundary() && cell->face(f)->center()(0)>eps &&
4321 *   cell->face(f)->center()(1)>eps )
4322 *   {
4323 * @endcode
4324 *
4325 * distance of the face center from the center
4326 *
4327 * @code
4328 *   point(0) = cell->face(f)->center()(0) - center_2d(0);
4329 *   point(1) = cell->face(f)->center()(1) - center_2d(1);
4330 *   if ( point.norm() > (inner_radius + eps) )
4331 *   {
4332 *   for (unsigned int v=0; v < GeometryInfo<dim_2d>::vertices_per_face; ++v)
4333 *   {
4334 *   unsigned int vv = cell->face(f)->vertex_index(v);
4335 *   if (treated_vertices[vv] == false)
4336 *   {
4337 *   treated_vertices[vv] = true;
4338 *   if (vv==1)
4339 *   {
4340 *   cell->face(f)->vertex(v) = center_2d+Point<dim_2d>(outer_radius,outer_radius);
4341 *   }
4342 *   }
4343 *   }
4344 *   }
4345 *  
4346 *   }
4347 *   }
4348 *  
4349 *   }
4350 *  
4351 * @endcode
4352 *
4353 * Make the triangulation_2, a rectangular above the triangulation_1
4354 *
4355 * @code
4356 *   {
4357 *   const Point<dim_2d> point1 (0, outer_radius),
4358 *   point2 (outer_radius, height);
4359 *  
4360 *   GridGenerator::hyper_rectangle(triangulation_2, point1, point2);
4361 *  
4362 *   }
4363 *  
4364 * @endcode
4365 *
4366 * make the triangulation_2d and refine it
4367 *
4368 * @code
4369 *   {
4370 * @endcode
4371 *
4372 * Merge the two triangulation_1 and triangulation_2
4373 *
4374 * @code
4375 *   GridGenerator::merge_triangulations(triangulation_1, triangulation_2, triangulation_2d);
4376 *  
4377 * @endcode
4378 *
4379 * Assign boundary indicators to the boundary faces
4380 *
4381 * @code
4382 *   /*
4383 *   *
4384 *   * /\ y
4385 *   * |
4386 *   * _____3_____
4387 *   * | |
4388 *   * | |
4389 *   * 4 | |
4390 *   * | |
4391 *   * | | 2
4392 *   * |_ |
4393 *   * \ |
4394 *   * 10 \ |
4395 *   * |______| ____________\ x
4396 *   * 1 /
4397 *   */
4398 *   {
4400 *   cell = triangulation_2d.begin_active(),
4401 *   endc = triangulation_2d.end();
4402 *   for (; cell != endc; ++cell)
4403 *   {
4404 *   for (unsigned int f=0; f<GeometryInfo<dim_2d>::faces_per_cell; ++f)
4405 *   {
4406 *   if (cell->face(f)->at_boundary())
4407 *   {
4408 *   if ( std::fabs(cell->face(f)->center()(1)) < eps )
4409 *   {
4410 *   cell->face(f)->set_manifold_id(1);
4411 *   }
4412 *   else if ( std::fabs(cell->face(f)->center()(0)-outer_radius) < eps )
4413 *   {
4414 *   cell->face(f)->set_manifold_id(2);
4415 *   }
4416 *   else if ( std::fabs(cell->face(f)->center()(1)-height) < eps )
4417 *   {
4418 *   cell->face(f)->set_manifold_id(3);
4419 *   }
4420 *   else if ( std::fabs(cell->face(f)->center()(0)) < eps )
4421 *   {
4422 *   cell->face(f)->set_manifold_id(4);
4423 *   }
4424 *   else
4425 *   {
4426 *   cell->face(f)->set_all_boundary_ids(10);
4427 *   }
4428 *  
4429 *   }
4430 *   }
4431 *   }
4432 *  
4433 *   }
4434 *  
4435 *   const SphericalManifold<dim_2d> inner_boundary_description(center_2d);
4436 *   triangulation_2d.set_manifold (10, inner_boundary_description);
4437 *  
4438 *   triangulation_2d.refine_global(3);
4439 *  
4440 *   triangulation_2d.reset_manifold (10);
4441 *   }
4442 *  
4443 * @endcode
4444 *
4445 * Extrude the triangulation_2d and make it 3d
4446 * GridGenerator::extrude_triangulation(triangulation_2d,
4447 * 2, thickness, triangulation);
4448 *
4449 * @code
4450 *   extrude_triangulation(triangulation_2d,
4451 *   2, thickness, triangulation);
4452 *  
4453 * @endcode
4454 *
4455 * Assign boundary indicators to the boundary faces
4456 *
4457 * @code
4458 *   /*
4459 *   *
4460 *   * /\ y
4461 *   * |
4462 *   * _____3_____
4463 *   * | |
4464 *   * | |
4465 *   * 4 | |
4466 *   * | 5|6 |
4467 *   * | | 2
4468 *   * |_ |
4469 *   * \ |
4470 *   * 10 \ |
4471 *   * |______| ____________\ x
4472 *   * 1 /
4473 *   */
4474 *   {
4475 *   Tensor<1,dim> dist_vector;
4476 *   Point<dim> center(center_2d(0), center_2d(1), 0);
4477 *  
4479 *   cell = triangulation.begin_active(),
4480 *   endc = triangulation.end();
4481 *   for (; cell != endc; ++cell)
4482 *   {
4483 *   for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
4484 *   {
4485 *   if (cell->face(f)->at_boundary())
4486 *   {
4487 *   dist_vector = cell->face(f)->center() - center;
4488 *  
4489 *   if ( std::fabs(dist_vector[1]) < eps )
4490 *   {
4491 *   cell->face(f)->set_manifold_id(1);
4492 *   }
4493 *   else if ( std::fabs(dist_vector[0]-outer_radius) < eps )
4494 *   {
4495 *   cell->face(f)->set_manifold_id(2);
4496 *   }
4497 *   else if ( std::fabs(dist_vector[1]-height) < eps )
4498 *   {
4499 *   cell->face(f)->set_manifold_id(3);
4500 *   }
4501 *   else if ( std::fabs(dist_vector[0]) < eps )
4502 *   {
4503 *   cell->face(f)->set_manifold_id(4);
4504 *   }
4505 *   else if ( std::fabs(dist_vector[2]) < eps )
4506 *   {
4507 *   cell->face(f)->set_manifold_id(5);
4508 *   }
4509 *   else if ( std::fabs(dist_vector[2]-thickness) < eps )
4510 *   {
4511 *   cell->face(f)->set_manifold_id(6);
4512 *   }
4513 *   else
4514 *   {
4515 *   cell->face(f)->set_all_boundary_ids(10);
4516 *   }
4517 *  
4518 *   }
4519 *   }
4520 *   }
4521 *  
4522 *   }
4523 *  
4524 *   const CylindricalManifold<dim> inner_boundary_description(2);
4525 *   triangulation.set_manifold (10, inner_boundary_description);
4526 *  
4527 *   triangulation.refine_global(n_initial_global_refinements);
4528 *  
4529 *   triangulation.reset_manifold (10);
4530 *  
4531 *   }
4532 *   else if (base_mesh == "Cantiliver_beam_3d")
4533 *   {
4534 * @endcode
4535 *
4536 * A rectangular tube made of Aluminium
4537 * http://www.google.de/imgres?imgurl=http%3A%2F%2Fwww.americanaluminum.com%2Fimages%2Fstockshape-rectangletube.gif&imgrefurl=http%3A%2F%2Fwww.americanaluminum.com%2Fstandard%2FrectangleTube&h=280&w=300&tbnid=VPDNh4-DJz4wyM%3A&zoom=1&docid=9DoGJCkOeFqiSM&ei=L1AuVfG5GMvtO7DggdAF&tbm=isch&client=ubuntu&iact=rc&uact=3&dur=419&page=1&start=0&ndsp=33&ved=0CGYQrQMwFQ
4538 * approximation of beam 17250
4539 * units are in meter
4540 *
4541
4542 *
4543 *
4544 * @code
4545 *   AssertThrow (dim == 3, ExcNotImplemented());
4546 *  
4547 *   const int dim_2d = 2;
4548 *  
4549 *   const double length = .7,
4550 *   width = 80e-3,
4551 *   height = 200e-3,
4552 *   thickness_web = 10e-3,
4553 *   thickness_flange = 10e-3;
4554 *  
4555 *   Triangulation<dim_2d> triangulation_b,
4556 *   triangulation_t,
4557 *   triangulation_l,
4558 *   triangulation_r,
4559 *   triangulation_2d;
4560 *  
4561 *   const double eps = 1e-7 * width;
4562 * @endcode
4563 *
4564 * Make the triangulation_b, a rectangular at the bottom of rectangular tube
4565 *
4566 * @code
4567 *   {
4568 *   const Point<dim_2d> point1 (-width/2, -height/2),
4569 *   point2 (width/2, -(height/2)+thickness_flange);
4570 *  
4571 *   std::vector<unsigned int> repetitions(dim_2d);
4572 *   repetitions[0] = 8;
4573 *   repetitions[1] = 1;
4574 *  
4575 *   GridGenerator::subdivided_hyper_rectangle(triangulation_b, repetitions, point1, point2);
4576 *   }
4577 *  
4578 * @endcode
4579 *
4580 * Make the triangulation_t, a rectangular at the top of rectangular tube
4581 *
4582 * @code
4583 *   {
4584 *   const Point<dim_2d> point1 (-width/2, (height/2)-thickness_flange),
4585 *   point2 (width/2, height/2);
4586 *  
4587 *   std::vector<unsigned int> repetitions(dim_2d);
4588 *   repetitions[0] = 8;
4589 *   repetitions[1] = 1;
4590 *  
4591 *   GridGenerator::subdivided_hyper_rectangle(triangulation_t, repetitions, point1, point2);
4592 *   }
4593 *  
4594 * @endcode
4595 *
4596 * Make the triangulation_l, a rectangular at the left of rectangular tube
4597 *
4598 * @code
4599 *   {
4600 *   const Point<dim_2d> point1 (-width/2, -(height/2)+thickness_flange),
4601 *   point2 (-(width/2)+thickness_web, (height/2)-thickness_flange);
4602 *  
4603 *   std::vector<unsigned int> repetitions(dim_2d);
4604 *   repetitions[0] = 1;
4605 *   repetitions[1] = 18;
4606 *  
4607 *   GridGenerator::subdivided_hyper_rectangle(triangulation_l, repetitions, point1, point2);
4608 *   }
4609 *  
4610 * @endcode
4611 *
4612 * Make the triangulation_r, a rectangular at the right of rectangular tube
4613 *
4614 * @code
4615 *   {
4616 *   const Point<dim_2d> point1 ((width/2)-thickness_web, -(height/2)+thickness_flange),
4617 *   point2 (width/2, (height/2)-thickness_flange);
4618 *  
4619 *   std::vector<unsigned int> repetitions(dim_2d);
4620 *   repetitions[0] = 1;
4621 *   repetitions[1] = 18;
4622 *  
4623 *   GridGenerator::subdivided_hyper_rectangle(triangulation_r, repetitions, point1, point2);
4624 *   }
4625 *  
4626 * @endcode
4627 *
4628 * make the triangulation_2d
4629 *
4630 * @code
4631 *   {
4632 * @endcode
4633 *
4634 * merging every two triangles to make triangulation_2d
4635 *
4636 * @code
4637 *   Triangulation<dim_2d> triangulation_bl,
4638 *   triangulation_blr;
4639 *  
4640 *   GridGenerator::merge_triangulations(triangulation_b, triangulation_l, triangulation_bl);
4641 *   GridGenerator::merge_triangulations(triangulation_bl, triangulation_r, triangulation_blr);
4642 *   GridGenerator::merge_triangulations(triangulation_blr, triangulation_t, triangulation_2d);
4643 *   }
4644 *  
4645 * @endcode
4646 *
4647 * Extrude the triangulation_2d and make it 3d
4648 *
4649 * @code
4650 *   const unsigned int n_slices = static_cast<int>(length*1000/20) + 1;
4651 *   extrude_triangulation(triangulation_2d,
4652 *   n_slices, length, triangulation);
4653 *  
4654 * @endcode
4655 *
4656 * Assign boundary indicators to the boundary faces
4657 *
4658 * @code
4659 *   /*
4660 *   *
4661 *   * A
4662 *   * ---------*----------
4663 *   * / /|
4664 *   * / / |
4665 *   * / / |
4666 *   * / 2 length / |
4667 *   * / / |
4668 *   * / / |
4669 *   * / / |
4670 *   * / width / |
4671 *   * -------------------- |
4672 *   * | --------1-------. | |
4673 *   * | : : | |
4674 *   * | : : |h |
4675 *   * | : y z : |e |
4676 *   * | : | / : |i /
4677 *   * |1: |___ x :1|g /
4678 *   * | : : |h /
4679 *   * | : : |t /
4680 *   * | : : | /
4681 *   * | : : | /
4682 *   * | ----------------- |/
4683 *   * ---------1----------/
4684 *   *
4685 *   * face id:
4686 *   * Essential boundary condition:
4687 *   * 1: z = 0: clamped, fixed in x, y and z directions
4688 *   * Natural/Newmann boundary condition:
4689 *   * 2: y = height/2: traction face: pressure on the surface
4690 *   * Quantity of interest:
4691 *   * displacement at Point A (x=0, y=height/2, z=length)
4692 *   */
4693 *   {
4694 *   Tensor<1,dim> dist_vector;
4695 *   Point<dim> center(0, 0, 0);
4696 *  
4698 *   cell = triangulation.begin_active(),
4699 *   endc = triangulation.end();
4700 *   for (; cell != endc; ++cell)
4701 *   {
4702 *   for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
4703 *   {
4704 *   if (cell->face(f)->at_boundary())
4705 *   {
4706 *   dist_vector = cell->face(f)->center() - center;
4707 *  
4708 *   if ( std::fabs(dist_vector[2]) < eps )
4709 *   {
4710 *   cell->face(f)->set_manifold_id(1);
4711 *   }
4712 *   else if ( std::fabs(dist_vector[1]-(height/2)) < eps )
4713 *   {
4714 *   cell->face(f)->set_manifold_id(2);
4715 *   }
4716 *   else
4717 *   {
4718 *   cell->face(f)->set_all_boundary_ids(0);
4719 *   }
4720 *  
4721 *   }
4722 *   }
4723 *   }
4724 *  
4725 *   }
4726 *  
4727 *   triangulation.refine_global(n_initial_global_refinements);
4728 *  
4729 *   }
4730 *   else
4731 *   {
4732 *   AssertThrow(false, ExcNotImplemented());
4733 *   }
4734 *  
4735 *   pcout << " Number of active cells: "
4736 *   << triangulation.n_active_cells()
4737 *   << std::endl;
4738 *   }
4739 *  
4740 *  
4741 *  
4742 * @endcode
4743 *
4744 *
4745 * <a name="elastoplastic.cc-PlasticityContactProblemsetup_system"></a>
4746 * <h4>PlasticityContactProblem::setup_system</h4>
4747 *
4748
4749 *
4750 * The next piece in the puzzle is to set up the DoFHandler, resize
4751 * vectors and take care of various other status variables such as
4752 * index sets and constraint matrices.
4753 *
4754
4755 *
4756 * In the following, each group of operations is put into a brace-enclosed
4757 * block that is being timed by the variable declared at the top of the
4758 * block (the constructor of the TimerOutput::Scope variable starts the
4759 * timed section, the destructor that is called at the end of the block
4760 * stops it again).
4761 *
4762 * @code
4763 *   template <int dim>
4764 *   void
4765 *   ElastoPlasticProblem<dim>::setup_system ()
4766 *   {
4767 *   /* setup dofs and get index sets for locally owned and relevant dofs */
4768 *   TimerOutput::Scope t(computing_timer, "Setup");
4769 *   {
4770 *   TimerOutput::Scope t(computing_timer, "Setup: distribute DoFs");
4771 *   dof_handler.distribute_dofs(fe);
4772 *   pcout << " Number of degrees of freedom: "
4773 *   << dof_handler.n_dofs()
4774 *   << std::endl;
4775 *  
4776 *   locally_owned_dofs = dof_handler.locally_owned_dofs();
4777 *   locally_relevant_dofs =
4779 *   }
4780 *  
4781 *   /* setup hanging nodes and Dirichlet constraints */
4782 *   {
4783 *   TimerOutput::Scope t(computing_timer, "Setup: constraints");
4784 *   constraints_hanging_nodes.reinit(locally_relevant_dofs);
4786 *   constraints_hanging_nodes);
4787 *   constraints_hanging_nodes.close();
4788 *  
4789 *   pcout << " Number of active cells: "
4790 *   << triangulation.n_global_active_cells() << std::endl
4791 *   << " Number of degrees of freedom: " << dof_handler.n_dofs()
4792 *   << std::endl;
4793 *  
4794 *   compute_dirichlet_constraints();
4795 *   }
4796 *  
4797 *   /* initialization of vectors*/
4798 *   {
4799 *   TimerOutput::Scope t(computing_timer, "Setup: vectors");
4800 *   if (timestep_no==1 || current_refinement_cycle!=0)
4801 *   {
4802 *   solution.reinit(locally_relevant_dofs, mpi_communicator);
4803 *   }
4804 *   incremental_displacement.reinit(locally_relevant_dofs, mpi_communicator);
4805 *   newton_rhs.reinit(locally_owned_dofs, mpi_communicator);
4806 *   newton_rhs_residual.reinit(locally_owned_dofs, mpi_communicator);
4807 *   fraction_of_plastic_q_points_per_cell.reinit(triangulation.n_active_cells());
4808 *   }
4809 *  
4810 * @endcode
4811 *
4812 * Finally, we set up sparsity patterns and matrices.
4813 * We temporarily (ab)use the system matrix to also build the (diagonal)
4814 * matrix that we use in eliminating degrees of freedom that are in contact
4815 * with the obstacle, but we then immediately set the Newton matrix back
4816 * to zero.
4817 *
4818 * @code
4819 *   {
4820 *   TimerOutput::Scope t(computing_timer, "Setup: matrix");
4821 *   TrilinosWrappers::SparsityPattern sp(locally_owned_dofs,
4822 *   mpi_communicator);
4823 *  
4824 *   DoFTools::make_sparsity_pattern(dof_handler, sp,
4825 *   constraints_dirichlet_and_hanging_nodes, false,
4826 *   this_mpi_process);
4827 *   sp.compress();
4828 *   newton_matrix.reinit(sp);
4829 *   }
4830 *   }
4831 *  
4832 *  
4833 * @endcode
4834 *
4835 *
4836 * <a name="elastoplastic.cc-PlasticityContactProblemcompute_dirichlet_constraints"></a>
4837 * <h4>PlasticityContactProblem::compute_dirichlet_constraints</h4>
4838 *
4839
4840 *
4841 * This function, broken out of the preceding one, computes the constraints
4842 * associated with Dirichlet-type boundary conditions and puts them into the
4843 * <code>constraints_dirichlet_and_hanging_nodes</code> variable by merging
4844 * with the constraints that come from hanging nodes.
4845 *
4846
4847 *
4848 * As laid out in the introduction, we need to distinguish between two
4849 * cases:
4850 * - If the domain is a box, we set the displacement to zero at the bottom,
4851 * and allow vertical movement in z-direction along the sides. As
4852 * shown in the <code>make_grid()</code> function, the former corresponds
4853 * to boundary indicator 6, the latter to 8.
4854 * - If the domain is a half sphere, then we impose zero displacement along
4855 * the curved part of the boundary, associated with boundary indicator zero.
4856 *
4857 * @code
4858 *   template <int dim>
4859 *   void
4860 *   ElastoPlasticProblem<dim>::compute_dirichlet_constraints ()
4861 *   {
4862 *   constraints_dirichlet_and_hanging_nodes.reinit(locally_relevant_dofs);
4863 *   constraints_dirichlet_and_hanging_nodes.merge(constraints_hanging_nodes);
4864 *  
4865 *   std::vector<bool> component_mask(dim);
4866 *  
4867 *   if (base_mesh == "Timoshenko beam")
4868 *   {
4870 *   0,
4871 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
4872 *   constraints_dirichlet_and_hanging_nodes,
4873 *   ComponentMask());
4874 *   }
4875 *   else if (base_mesh == "Thick_tube_internal_pressure")
4876 *   {
4877 * @endcode
4878 *
4879 * the boundary x = 0
4880 *
4881 * @code
4882 *   component_mask[0] = true;
4883 *   component_mask[1] = false;
4885 *   2,
4886 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
4887 *   constraints_dirichlet_and_hanging_nodes,
4888 *   component_mask);
4889 * @endcode
4890 *
4891 * the boundary y = 0
4892 *
4893 * @code
4894 *   component_mask[0] = false;
4895 *   component_mask[1] = true;
4897 *   3,
4898 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
4899 *   constraints_dirichlet_and_hanging_nodes,
4900 *   component_mask);
4901 *   }
4902 *   else if (base_mesh == "Perforated_strip_tension")
4903 *   {
4904 * @endcode
4905 *
4906 * the boundary x = 0
4907 *
4908 * @code
4909 *   component_mask[0] = true;
4910 *   component_mask[1] = false;
4911 *   component_mask[2] = false;
4913 *   4,
4914 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
4915 *   constraints_dirichlet_and_hanging_nodes,
4916 *   component_mask);
4917 * @endcode
4918 *
4919 * the boundary y = 0
4920 *
4921 * @code
4922 *   component_mask[0] = false;
4923 *   component_mask[1] = true;
4924 *   component_mask[2] = false;
4926 *   1,
4927 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
4928 *   constraints_dirichlet_and_hanging_nodes,
4929 *   component_mask);
4930 * @endcode
4931 *
4932 * the boundary y = imposed incremental displacement
4933 *
4934 * @code
4935 *   component_mask[0] = false;
4936 *   component_mask[1] = true;
4937 *   component_mask[2] = false;
4939 *   3,
4940 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
4941 *   constraints_dirichlet_and_hanging_nodes,
4942 *   component_mask);
4943 *   }
4944 *   else if (base_mesh == "Cantiliver_beam_3d")
4945 *   {
4946 * @endcode
4947 *
4948 * the boundary x = y = z = 0
4949 *
4950 * @code
4951 *   component_mask[0] = true;
4952 *   component_mask[1] = true;
4953 *   component_mask[2] = true;
4955 *   1,
4956 *   EquationData::IncrementalBoundaryValues<dim>(present_time, end_time),
4957 *   constraints_dirichlet_and_hanging_nodes,
4958 *   component_mask);
4959 *   }
4960 *   else
4961 *   {
4962 *   AssertThrow(false, ExcNotImplemented());
4963 *   }
4964 *  
4965 *  
4966 *   constraints_dirichlet_and_hanging_nodes.close();
4967 *   }
4968 *  
4969 *  
4970 * @endcode
4971 *
4972 *
4973 * <a name="elastoplastic.cc-PlasticityContactProblemassemble_newton_system"></a>
4974 * <h4>PlasticityContactProblem::assemble_newton_system</h4>
4975 *
4976
4977 *
4978 * Given the complexity of the problem, it may come as a bit of a surprise
4979 * that assembling the linear system we have to solve in each Newton iteration
4980 * is actually fairly straightforward. The following function builds the Newton
4981 * right hand side and Newton matrix. It looks fairly innocent because the
4982 * heavy lifting happens in the call to
4983 * <code>ConstitutiveLaw::get_linearized_stress_strain_tensors()</code> and in
4985 * constraints we have previously computed.
4986 *
4987 * @code
4988 *   template <int dim>
4989 *   void
4990 *   ElastoPlasticProblem<dim>::
4991 *   assemble_newton_system (const TrilinosWrappers::MPI::Vector &/*linearization_point*/,
4992 *   const TrilinosWrappers::MPI::Vector &delta_linearization_point)
4993 *   {
4994 *   TimerOutput::Scope t(computing_timer, "Assembling");
4995 *  
4996 *   types::boundary_id traction_surface_id = numbers::invalid_boundary_id;
4997 *   if (base_mesh == "Timoshenko beam")
4998 *   {
4999 *   traction_surface_id = 5;
5000 *   }
5001 *   else if (base_mesh == "Thick_tube_internal_pressure")
5002 *   {
5003 *   traction_surface_id = 0;
5004 *   }
5005 *   else if (base_mesh == "Cantiliver_beam_3d")
5006 *   {
5007 *   traction_surface_id = 2;
5008 *   }
5009 *   else
5010 *   {
5011 *   AssertThrow(false, ExcNotImplemented());
5012 *   }
5013 *  
5014 *   FEValues<dim> fe_values(fe, quadrature_formula,
5017 *  
5018 *   FEFaceValues<dim> fe_values_face(fe, face_quadrature_formula,
5020 *  
5021 *   const unsigned int dofs_per_cell = fe.dofs_per_cell;
5022 *   const unsigned int n_q_points = quadrature_formula.size();
5023 *   const unsigned int n_face_q_points = face_quadrature_formula.size();
5024 *  
5025 *  
5026 *   const EquationData::BodyForce<dim> body_force;
5027 *   std::vector<Vector<double> > body_force_values(n_q_points,
5028 *   Vector<double>(dim));
5029 *  
5030 *   const EquationData::
5031 *   IncrementalBoundaryForce<dim> boundary_force(present_time, end_time);
5032 *   std::vector<Vector<double> > boundary_force_values(n_face_q_points,
5033 *   Vector<double>(dim));
5034 *  
5035 *   FullMatrix<double> cell_matrix(dofs_per_cell, dofs_per_cell);
5036 *   Vector<double> cell_rhs(dofs_per_cell);
5037 *  
5038 *   std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
5039 *  
5040 * @endcode
5041 *
5042 * std::vector<SymmetricTensor<2, dim> > strain_tensor(n_q_points);
5043 *
5044 * @code
5045 *   std::vector<SymmetricTensor<2, dim> > incremental_strain_tensor(n_q_points);
5046 *  
5048 *   cell = dof_handler.begin_active(),
5049 *   endc = dof_handler.end();
5050 *  
5051 *   const FEValuesExtractors::Vector displacement(0);
5052 *  
5053 *   for (; cell != endc; ++cell)
5054 *   if (cell->is_locally_owned())
5055 *   {
5056 *   fe_values.reinit(cell);
5057 *   cell_matrix = 0;
5058 *   cell_rhs = 0;
5059 *  
5060 *   fe_values[displacement].get_function_symmetric_gradients(delta_linearization_point,
5061 *   incremental_strain_tensor);
5062 *  
5063 * @endcode
5064 *
5065 * For assembling the local right hand side contributions, we need
5066 * to access the prior linearized stress value in this quadrature
5067 * point. To get it, we use the user pointer of this cell that
5068 * points into the global array to the quadrature point data
5069 * corresponding to the first quadrature point of the present cell,
5070 * and then add an offset corresponding to the index of the
5071 * quadrature point we presently consider:
5072 *
5073 * @code
5074 *   const PointHistory<dim> *local_quadrature_points_history
5075 *   = reinterpret_cast<PointHistory<dim>*>(cell->user_pointer());
5076 *   Assert (local_quadrature_points_history >=
5077 *   &quadrature_point_history.front(),
5078 *   ExcInternalError());
5079 *   Assert (local_quadrature_points_history <
5080 *   &quadrature_point_history.back(),
5081 *   ExcInternalError());
5082 *  
5083 * @endcode
5084 *
5085 * In addition, we need the values of the external body forces at
5086 * the quadrature points on this cell:
5087 *
5088 * @code
5089 *   body_force.vector_value_list(fe_values.get_quadrature_points(),
5090 *   body_force_values);
5091 *  
5092 *   for (unsigned int q_point = 0; q_point < n_q_points; ++q_point)
5093 *   {
5094 *   SymmetricTensor<2, dim> tmp_strain_tensor_qpoint;
5095 *   tmp_strain_tensor_qpoint = local_quadrature_points_history[q_point].old_strain
5096 *   + incremental_strain_tensor[q_point];
5097 *  
5098 *   SymmetricTensor<4, dim> stress_strain_tensor_linearized;
5099 *   SymmetricTensor<4, dim> stress_strain_tensor;
5100 *   constitutive_law.get_linearized_stress_strain_tensors(tmp_strain_tensor_qpoint,
5101 *   stress_strain_tensor_linearized,
5102 *   stress_strain_tensor);
5103 *  
5104 *   Tensor<1, dim> rhs_values_body_force;
5105 *   for (unsigned int i = 0; i < dim; ++i)
5106 *   {
5107 *   rhs_values_body_force[i] = body_force_values[q_point][i];
5108 *   }
5109 *  
5110 *   for (unsigned int i = 0; i < dofs_per_cell; ++i)
5111 *   {
5112 * @endcode
5113 *
5114 * Having computed the stress-strain tensor and its linearization,
5115 * we can now put together the parts of the matrix and right hand side.
5116 * In both, we need the linearized stress-strain tensor times the
5117 * symmetric gradient of @f$\varphi_i@f$, i.e. the term @f$I_\Pi\varepsilon(\varphi_i)@f$,
5118 * so we introduce an abbreviation of this term. Recall that the
5119 * matrix corresponds to the bilinear form
5120 * @f$A_{ij}=(I_\Pi\varepsilon(\varphi_i),\varepsilon(\varphi_j))@f$ in the
5121 * notation of the accompanying publication, whereas the right
5122 * hand side is @f$F_i=([I_\Pi-P_\Pi C]\varepsilon(\varphi_i),\varepsilon(\mathbf u))@f$
5123 * where @f$u@f$ is the current linearization points (typically the last solution).
5124 * This might suggest that the right hand side will be zero if the material
5125 * is completely elastic (where @f$I_\Pi=P_\Pi@f$) but this ignores the fact
5126 * that the right hand side will also contain contributions from
5127 * non-homogeneous constraints due to the contact.
5128 *
5129
5130 *
5131 * The code block that follows this adds contributions that are due to
5132 * boundary forces, should there be any.
5133 *
5134 * @code
5135 *   const SymmetricTensor<2, dim>
5136 *   stress_phi_i = stress_strain_tensor_linearized
5137 *   * fe_values[displacement].symmetric_gradient(i, q_point);
5138 *  
5139 *   for (unsigned int j = 0; j < dofs_per_cell; ++j)
5140 *   cell_matrix(i, j) += (stress_phi_i
5141 *   * fe_values[displacement].symmetric_gradient(j, q_point)
5142 *   * fe_values.JxW(q_point));
5143 *  
5144 *   cell_rhs(i) += (
5145 *   ( stress_phi_i
5146 *   * incremental_strain_tensor[q_point] )
5147 *   -
5148 *   ( ( stress_strain_tensor
5149 *   * fe_values[displacement].symmetric_gradient(i, q_point))
5150 *   * tmp_strain_tensor_qpoint )
5151 *   +
5152 *   ( fe_values[displacement].value(i, q_point)
5153 *   * rhs_values_body_force )
5154 *   ) * fe_values.JxW(q_point);
5155 *  
5156 *   }
5157 *   }
5158 *  
5159 *   for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
5160 *   if (cell->face(face)->at_boundary()
5161 *   &&
5162 *   cell->face(face)->boundary_id() == traction_surface_id)
5163 *   {
5164 *   fe_values_face.reinit(cell, face);
5165 *  
5166 *   boundary_force.vector_value_list(fe_values_face.get_quadrature_points(),
5167 *   boundary_force_values);
5168 *  
5169 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
5170 *   {
5171 *   Tensor<1, dim> rhs_values;
5172 *   for (unsigned int i = 0; i < dim; ++i)
5173 *   {
5174 *   rhs_values[i] = boundary_force_values[q_point][i];
5175 *   }
5176 *   for (unsigned int i = 0; i < dofs_per_cell; ++i)
5177 *   cell_rhs(i) += (fe_values_face[displacement].value(i, q_point)
5178 *   * rhs_values
5179 *   * fe_values_face.JxW(q_point));
5180 *   }
5181 *   }
5182 *  
5183 *   cell->get_dof_indices(local_dof_indices);
5184 *   constraints_dirichlet_and_hanging_nodes.distribute_local_to_global(cell_matrix, cell_rhs,
5185 *   local_dof_indices,
5186 *   newton_matrix,
5187 *   newton_rhs,
5188 *   true);
5189 *  
5190 *   }
5191 *  
5192 *   newton_matrix.compress(VectorOperation::add);
5193 *   newton_rhs.compress(VectorOperation::add);
5194 *   }
5195 *  
5196 *  
5197 *  
5198 * @endcode
5199 *
5200 *
5201 * <a name="elastoplastic.cc-PlasticityContactProblemcompute_nonlinear_residual"></a>
5202 * <h4>PlasticityContactProblem::compute_nonlinear_residual</h4>
5203 *
5204
5205 *
5206 * The following function computes the nonlinear residual of the equation
5207 * given the current solution (or any other linearization point). This
5208 * is needed in the linear search algorithm where we need to try various
5209 * linear combinations of previous and current (trial) solution to
5210 * compute the (real, globalized) solution of the current Newton step.
5211 *
5212
5213 *
5214 * That said, in a slight abuse of the name of the function, it actually
5215 * does significantly more. For example, it also computes the vector
5216 * that corresponds to the Newton residual but without eliminating
5217 * constrained degrees of freedom. We need this vector to compute contact
5218 * forces and, ultimately, to compute the next active set. Likewise, by
5219 * keeping track of how many quadrature points we encounter on each cell
5220 * that show plastic yielding, we also compute the
5221 * <code>fraction_of_plastic_q_points_per_cell</code> vector that we
5222 * can later output to visualize the plastic zone. In both of these cases,
5223 * the results are not necessary as part of the line search, and so we may
5224 * be wasting a small amount of time computing them. At the same time, this
5225 * information appears as a natural by-product of what we need to do here
5226 * anyway, and we want to collect it once at the end of each Newton
5227 * step, so we may as well do it here.
5228 *
5229
5230 *
5231 * The actual implementation of this function should be rather obvious:
5232 *
5233 * @code
5234 *   template <int dim>
5235 *   void
5236 *   ElastoPlasticProblem<dim>::
5237 *   compute_nonlinear_residual (const TrilinosWrappers::MPI::Vector &linearization_point)
5238 *   {
5239 *   types::boundary_id traction_surface_id = numbers::invalid_boundary_id;
5240 *   if (base_mesh == "Timoshenko beam")
5241 *   {
5242 *   traction_surface_id = 5;
5243 *   }
5244 *   else if (base_mesh == "Thick_tube_internal_pressure")
5245 *   {
5246 *   traction_surface_id = 0;
5247 *   }
5248 *   else if (base_mesh == "Cantiliver_beam_3d")
5249 *   {
5250 *   traction_surface_id = 2;
5251 *   }
5252 *   else
5253 *   {
5254 *   AssertThrow(false, ExcNotImplemented());
5255 *   }
5256 *  
5257 *   FEValues<dim> fe_values(fe, quadrature_formula,
5259 *   update_JxW_values);
5260 *  
5261 *   FEFaceValues<dim> fe_values_face(fe, face_quadrature_formula,
5263 *   update_JxW_values);
5264 *  
5265 *   const unsigned int dofs_per_cell = fe.dofs_per_cell;
5266 *   const unsigned int n_q_points = quadrature_formula.size();
5267 *   const unsigned int n_face_q_points = face_quadrature_formula.size();
5268 *  
5269 *   const EquationData::BodyForce<dim> body_force;
5270 *   std::vector<Vector<double> > body_force_values(n_q_points,
5271 *   Vector<double>(dim));
5272 *  
5273 *   const EquationData::
5274 *   IncrementalBoundaryForce<dim> boundary_force(present_time, end_time);
5275 *   std::vector<Vector<double> > boundary_force_values(n_face_q_points,
5276 *   Vector<double>(dim));
5277 *  
5278 *   Vector<double> cell_rhs(dofs_per_cell);
5279 *  
5280 *   std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
5281 *  
5282 *   const FEValuesExtractors::Vector displacement(0);
5283 *  
5284 *   newton_rhs_residual = 0;
5285 *  
5286 *   fraction_of_plastic_q_points_per_cell = 0;
5287 *  
5289 *   cell = dof_handler.begin_active(),
5290 *   endc = dof_handler.end();
5291 *   unsigned int cell_number = 0;
5292 *   for (; cell != endc; ++cell, ++cell_number)
5293 *   if (cell->is_locally_owned())
5294 *   {
5295 *   fe_values.reinit(cell);
5296 *   cell_rhs = 0;
5297 *  
5298 *   std::vector<SymmetricTensor<2, dim> > strain_tensors(n_q_points);
5299 *   fe_values[displacement].get_function_symmetric_gradients(linearization_point,
5300 *   strain_tensors);
5301 *  
5302 *   body_force.vector_value_list(fe_values.get_quadrature_points(),
5303 *   body_force_values);
5304 *  
5305 *   for (unsigned int q_point = 0; q_point < n_q_points; ++q_point)
5306 *   {
5307 *   SymmetricTensor<4, dim> stress_strain_tensor;
5308 *   const bool q_point_is_plastic
5309 *   = constitutive_law.get_stress_strain_tensor(strain_tensors[q_point],
5310 *   stress_strain_tensor);
5311 *   if (q_point_is_plastic)
5312 *   ++fraction_of_plastic_q_points_per_cell(cell_number);
5313 *  
5314 *   Tensor<1, dim> rhs_values_body_force;
5315 *   for (unsigned int i = 0; i < dim; ++i)
5316 *   {
5317 *   rhs_values_body_force[i] = body_force_values[q_point][i];
5318 *   }
5319 *  
5320 *   for (unsigned int i = 0; i < dofs_per_cell; ++i)
5321 *   {
5322 *   cell_rhs(i) += (fe_values[displacement].value(i, q_point)
5323 *   * rhs_values_body_force
5324 *   -
5325 *   strain_tensors[q_point]
5326 *   * stress_strain_tensor
5327 *   * fe_values[displacement].symmetric_gradient(i, q_point)
5328 *   )
5329 *   * fe_values.JxW(q_point);
5330 *  
5331 *   Tensor<1, dim> rhs_values;
5332 *   rhs_values = 0;
5333 *   cell_rhs(i) += (fe_values[displacement].value(i, q_point)
5334 *   * rhs_values
5335 *   * fe_values.JxW(q_point));
5336 *   }
5337 *   }
5338 *  
5339 *   for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
5340 *   if (cell->face(face)->at_boundary()
5341 *   && cell->face(face)->boundary_id() == traction_surface_id)
5342 *   {
5343 *   fe_values_face.reinit(cell, face);
5344 *  
5345 *   boundary_force.vector_value_list(fe_values_face.get_quadrature_points(),
5346 *   boundary_force_values);
5347 *  
5348 *   for (unsigned int q_point = 0; q_point < n_face_q_points;
5349 *   ++q_point)
5350 *   {
5351 *   Tensor<1, dim> rhs_values;
5352 *   for (unsigned int i = 0; i < dim; ++i)
5353 *   {
5354 *   rhs_values[i] = boundary_force_values[q_point][i];
5355 *   }
5356 *   for (unsigned int i = 0; i < dofs_per_cell; ++i)
5357 *   cell_rhs(i) += (fe_values_face[displacement].value(i, q_point) * rhs_values
5358 *   * fe_values_face.JxW(q_point));
5359 *   }
5360 *   }
5361 *  
5362 *   cell->get_dof_indices(local_dof_indices);
5363 *   constraints_dirichlet_and_hanging_nodes.distribute_local_to_global(cell_rhs,
5364 *   local_dof_indices,
5365 *   newton_rhs_residual);
5366 *  
5367 *   }
5368 *  
5369 *   fraction_of_plastic_q_points_per_cell /= quadrature_formula.size();
5370 *   newton_rhs_residual.compress(VectorOperation::add);
5371 *  
5372 *   }
5373 *  
5374 *  
5375 *  
5376 *  
5377 *  
5378 * @endcode
5379 *
5380 *
5381 * <a name="elastoplastic.cc-PlasticityContactProblemsolve_newton_system"></a>
5382 * <h4>PlasticityContactProblem::solve_newton_system</h4>
5383 *
5384
5385 *
5386 * The last piece before we can discuss the actual Newton iteration
5387 * on a single mesh is the solver for the linear systems. There are
5388 * a couple of complications that slightly obscure the code, but
5389 * mostly it is just setup then solve. Among the complications are:
5390 *
5391
5392 *
5393 * - For the hanging nodes we have to apply
5395 * This is necessary if a hanging node with solution value @f$x_0@f$
5396 * has one neighbor with value @f$x_1@f$ which is in contact with the
5397 * obstacle and one neighbor @f$x_2@f$ which is not in contact. Because
5398 * the update for the former will be prescribed, the hanging node constraint
5399 * will have an inhomogeneity and will look like @f$x_0 = x_1/2 + \text{gap}/2@f$.
5400 * So the corresponding entries in the
5401 * ride-hang-side are non-zero with a
5402 * meaningless value. These values we have to
5403 * to set to zero.
5404 * - Like in @ref step_40 "step-40", we need to shuffle between vectors that do and do
5405 * do not have ghost elements when solving or using the solution.
5406 *
5407
5408 *
5409 * The rest of the function is similar to @ref step_40 "step-40" and
5410 * @ref step_41 "step-41" except that we use a BiCGStab solver
5411 * instead of CG. This is due to the fact that for very small hardening
5412 * parameters @f$\gamma@f$, the linear system becomes almost semidefinite though
5413 * still symmetric. BiCGStab appears to have an easier time with such linear
5414 * systems.
5415 *
5416 * @code
5417 *   template <int dim>
5418 *   void
5419 *   ElastoPlasticProblem<dim>::solve_newton_system ()
5420 *   {
5421 *   TimerOutput::Scope t(computing_timer, "Solve");
5422 *  
5423 *   TrilinosWrappers::MPI::Vector distributed_solution(locally_owned_dofs, mpi_communicator);
5424 *   distributed_solution = incremental_displacement;
5425 *  
5426 *   constraints_hanging_nodes.set_zero(distributed_solution);
5427 *   constraints_hanging_nodes.set_zero(newton_rhs);
5428 *  
5429 * @endcode
5430 *
5431 * ------- Solver Bicgstab --- Preconditioner AMG -------------------
5432 * TrilinosWrappers::PreconditionAMG preconditioner;
5433 * {
5434 * TimerOutput::Scope t(computing_timer, "Solve: setup preconditioner");
5435 *
5436
5437 *
5438 * std::vector<std::vector<bool> > constant_modes;
5440 * constant_modes);
5441 *
5442
5443 *
5445 * additional_data.constant_modes = constant_modes;
5446 * additional_data.elliptic = true;
5447 * additional_data.n_cycles = 1;
5448 * additional_data.w_cycle = false;
5449 * additional_data.output_details = false;
5450 * additional_data.smoother_sweeps = 2;
5451 * additional_data.aggregation_threshold = 1e-2;
5452 *
5453
5454 *
5455 * preconditioner.initialize(newton_matrix, additional_data);
5456 * }
5457 *
5458
5459 *
5460 * {
5461 * TimerOutput::Scope t(computing_timer, "Solve: iterate");
5462 *
5463
5464 *
5465 * TrilinosWrappers::MPI::Vector tmp(locally_owned_dofs, mpi_communicator);
5466 *
5467
5468 *
5469 * // const double relative_accuracy = 1e-8;
5470 * const double relative_accuracy = 1e-2;
5471 * const double solver_tolerance = relative_accuracy
5472 * * newton_matrix.residual(tmp, distributed_solution,
5473 * newton_rhs);
5474 *
5475
5476 *
5477 * SolverControl solver_control(newton_matrix.m(),
5478 * solver_tolerance);
5479 * SolverBicgstab<TrilinosWrappers::MPI::Vector> solver(solver_control);
5480 * solver.solve(newton_matrix, distributed_solution,
5481 * newton_rhs, preconditioner);
5482 *
5483
5484 *
5485 * pcout << " Error: " << solver_control.initial_value()
5486 * << " -> " << solver_control.last_value() << " in "
5487 * << solver_control.last_step() << " Bicgstab iterations."
5488 * << std::endl;
5489 * }
5490 *
5491
5492 *
5493 * ------- Solver CG --- Preconditioner SSOR -------------------
5494 *
5495 * @code
5496 *   TrilinosWrappers::PreconditionSSOR preconditioner;
5497 *   {
5498 *   TimerOutput::Scope t(computing_timer, "Solve: setup preconditioner");
5499 *  
5501 *   preconditioner.initialize(newton_matrix, additional_data);
5502 *   }
5503 *  
5504 *   {
5505 *   TimerOutput::Scope t(computing_timer, "Solve: iterate");
5506 *  
5507 *   TrilinosWrappers::MPI::Vector tmp(locally_owned_dofs, mpi_communicator);
5508 *  
5509 * @endcode
5510 *
5511 * const double relative_accuracy = 1e-8;
5512 *
5513 * @code
5514 *   const double relative_accuracy = 1e-2;
5515 *   const double solver_tolerance = relative_accuracy
5516 *   * newton_matrix.residual(tmp, distributed_solution,
5517 *   newton_rhs);
5518 *  
5519 * @endcode
5520 *
5521 * SolverControl solver_control(newton_matrix.m(),
5522 * solver_tolerance);
5523 *
5524 * @code
5525 *   SolverControl solver_control(10*newton_matrix.m(),
5526 *   solver_tolerance);
5527 *   SolverCG<TrilinosWrappers::MPI::Vector> solver(solver_control);
5528 *   solver.solve(newton_matrix, distributed_solution,
5529 *   newton_rhs, preconditioner);
5530 *  
5531 *   pcout << " Error: " << solver_control.initial_value()
5532 *   << " -> " << solver_control.last_value() << " in "
5533 *   << solver_control.last_step() << " CG iterations."
5534 *   << std::endl;
5535 *   }
5536 * @endcode
5537 *
5538 * ........................................................
5539 *
5540
5541 *
5542 *
5543 * @code
5544 *   constraints_dirichlet_and_hanging_nodes.distribute(distributed_solution);
5545 *  
5546 *   incremental_displacement = distributed_solution;
5547 *   }
5548 *  
5549 *  
5550 * @endcode
5551 *
5552 *
5553 * <a name="elastoplastic.cc-PlasticityContactProblemsolve_newton"></a>
5554 * <h4>PlasticityContactProblem::solve_newton</h4>
5555 *
5556
5557 *
5558 * This is, finally, the function that implements the damped Newton method
5559 * on the current mesh. There are two nested loops: the outer loop for the Newton
5560 * iteration and the inner loop for the line search which
5561 * will be used only if necessary. To obtain a good and reasonable
5562 * starting value we solve an elastic problem in very first Newton step on each
5563 * mesh (or only on the first mesh if we transfer solutions between meshes). We
5564 * do so by setting the yield stress to an unreasonably large value in these
5565 * iterations and then setting it back to the correct value in subsequent
5566 * iterations.
5567 *
5568
5569 *
5570 * Other than this, the top part of this function should be reasonably
5571 * obvious:
5572 *
5573 * @code
5574 *   template <int dim>
5575 *   void
5576 *   ElastoPlasticProblem<dim>::solve_newton ()
5577 *   {
5578 *   TrilinosWrappers::MPI::Vector old_solution(locally_owned_dofs, mpi_communicator);
5579 *   TrilinosWrappers::MPI::Vector residual(locally_owned_dofs, mpi_communicator);
5580 *   TrilinosWrappers::MPI::Vector tmp_vector(locally_owned_dofs, mpi_communicator);
5581 *   TrilinosWrappers::MPI::Vector locally_relevant_tmp_vector(locally_relevant_dofs, mpi_communicator);
5582 *   TrilinosWrappers::MPI::Vector distributed_solution(locally_owned_dofs, mpi_communicator);
5583 *   TrilinosWrappers::MPI::Vector tmp_solution(locally_owned_dofs, mpi_communicator);
5584 *  
5585 *   double residual_norm;
5586 *   double previous_residual_norm = -std::numeric_limits<double>::max();
5587 *  
5588 *   double disp_norm,
5589 *   previous_disp_norm = 0;
5590 *  
5591 *   const double correct_sigma = sigma_0;
5592 *  
5593 *   const unsigned int max_newton_iter = 100;
5594 *  
5595 *   for (unsigned int newton_step = 1; newton_step <= max_newton_iter; ++newton_step)
5596 *   {
5597 *   if (newton_step == 1
5598 *   &&
5599 *   ((transfer_solution && timestep_no == 1)
5600 *   ||
5601 *   !transfer_solution))
5602 *   constitutive_law.set_sigma_0(1e+10);
5603 *   else
5604 *   constitutive_law.set_sigma_0(correct_sigma);
5605 *  
5606 *   pcout << " " << std::endl;
5607 *   pcout << " Newton iteration " << newton_step << std::endl;
5608 *  
5609 *   pcout << " Assembling system... " << std::endl;
5610 *   newton_matrix = 0;
5611 *   newton_rhs = 0;
5612 *   newton_rhs_residual = 0;
5613 *  
5614 *   tmp_solution = solution;
5615 *   tmp_solution += incremental_displacement;
5616 *   assemble_newton_system(tmp_solution,
5617 *   incremental_displacement);
5618 *  
5619 *   pcout << " Solving system... " << std::endl;
5620 *   solve_newton_system();
5621 *  
5622 * @endcode
5623 *
5624 * It gets a bit more hairy after we have computed the
5625 * trial solution @f$\tilde{\mathbf u}@f$ of the current Newton step.
5626 * We handle a highly nonlinear problem so we have to damp
5627 * Newton's method using a line search. To understand how we do this,
5628 * recall that in our formulation, we compute a trial solution
5629 * in each Newton step and not the update between old and new solution.
5630 * Since the solution set is a convex set, we will use a line
5631 * search that tries linear combinations of the
5632 * previous and the trial solution to guarantee that the
5633 * damped solution is in our solution set again.
5634 * At most we apply 5 damping steps.
5635 *
5636
5637 *
5638 * There are exceptions to when we use a line search. First,
5639 * if this is the first Newton step on any mesh, then we don't have
5640 * any point to compare the residual to, so we always accept a full
5641 * step. Likewise, if this is the second Newton step on the first mesh (or
5642 * the second on any mesh if we don't transfer solutions from
5643 * mesh to mesh), then we have computed the first of these steps using
5644 * just an elastic model (see how we set the yield stress sigma to
5645 * an unreasonably large value above). In this case, the first Newton
5646 * solution was a purely elastic one, the second one a plastic one,
5647 * and any linear combination would not necessarily be expected to
5648 * lie in the feasible set -- so we just accept the solution we just
5649 * got.
5650 *
5651
5652 *
5653 * In either of these two cases, we bypass the line search and just
5654 * update residual and other vectors as necessary.
5655 *
5656 * @code
5657 *   if ((newton_step==1)
5658 *   ||
5659 *   (transfer_solution && newton_step == 2 && current_refinement_cycle == 0)
5660 *   ||
5661 *   (!transfer_solution && newton_step == 2))
5662 *   {
5663 *   tmp_solution = solution;
5664 *   tmp_solution += incremental_displacement;
5665 *   compute_nonlinear_residual(tmp_solution);
5666 *   old_solution = incremental_displacement;
5667 *  
5668 *   residual = newton_rhs_residual;
5669 *  
5670 *   residual.compress(VectorOperation::insert);
5671 *  
5672 *   residual_norm = residual.l2_norm();
5673 *  
5674 *   pcout << " Accepting Newton solution with residual: "
5675 *   << residual_norm << std::endl;
5676 *   }
5677 *   else
5678 *   {
5679 *   for (unsigned int i = 0; i < 5; ++i)
5680 *   {
5681 *   distributed_solution = incremental_displacement;
5682 *  
5683 *   const double alpha = std::pow(0.5, static_cast<double>(i));
5684 *   tmp_vector = old_solution;
5685 *   tmp_vector.sadd(1 - alpha, alpha, distributed_solution);
5686 *  
5687 *   TimerOutput::Scope t(computing_timer, "Residual and lambda");
5688 *  
5689 *   locally_relevant_tmp_vector = tmp_vector;
5690 *   tmp_solution = solution;
5691 *   tmp_solution += locally_relevant_tmp_vector;
5692 *   compute_nonlinear_residual(tmp_solution);
5693 *   residual = newton_rhs_residual;
5694 *  
5695 *   residual.compress(VectorOperation::insert);
5696 *  
5697 *   residual_norm = residual.l2_norm();
5698 *  
5699 *   pcout << " Residual of the system: "
5700 *   << residual_norm << std::endl
5701 *   << " with a damping parameter alpha = " << alpha
5702 *   << std::endl;
5703 *  
5704 *   if (residual_norm < previous_residual_norm)
5705 *   break;
5706 *   }
5707 *  
5708 *   incremental_displacement = tmp_vector;
5709 *   old_solution = incremental_displacement;
5710 *   }
5711 *  
5712 *   disp_norm = incremental_displacement.l2_norm();
5713 *  
5714 *  
5715 * @endcode
5716 *
5717 * The final step is to check for convergence. If the residual is
5718 * less than a threshold of @f$10^{-10}@f$, then we terminate
5719 * the iteration on the current mesh:
5720 * if (residual_norm < 1e-10)
5721 *
5722 * @code
5723 *   if (residual_norm < 1e-7)
5724 *   break;
5725 *  
5726 *   pcout << " difference of two consecutive incremental displacement l2 norm : "
5727 *   << std::abs(disp_norm - previous_disp_norm) << std::endl;
5728 *   if ( std::abs(disp_norm - previous_disp_norm) < 1e-10 &&
5729 *   (residual_norm < 1e-5 || std::abs(residual_norm - previous_residual_norm)<1e-9) )
5730 *   {
5731 *   pcout << " Convergence by difference of two consecutive solution! " << std::endl;
5732 *   break;
5733 *   }
5734 *  
5735 *  
5736 *   previous_residual_norm = residual_norm;
5737 *   previous_disp_norm = disp_norm;
5738 *   }
5739 *   }
5740 *  
5741 * @endcode
5742 *
5743 *
5744 * <a name="elastoplastic.cc-PlasticityContactProblemcompute_error"></a>
5745 * <h4>PlasticityContactProblem::compute_error</h4>
5746 *
5747
5748 *
5749 *
5750 * @code
5751 *   template <int dim>
5752 *   void
5753 *   ElastoPlasticProblem<dim>::compute_error ()
5754 *   {
5755 *   TrilinosWrappers::MPI::Vector tmp_solution(locally_owned_dofs, mpi_communicator);
5756 *   tmp_solution = solution;
5757 *   tmp_solution += incremental_displacement;
5758 *  
5759 *   estimated_error_per_cell.reinit (triangulation.n_active_cells());
5760 *   if (error_estimation_strategy == ErrorEstimationStrategy::kelly_error)
5761 *   {
5762 *   using FunctionMap = std::map<types::boundary_id, const Function<dim> *>;
5763 *  
5764 *   KellyErrorEstimator<dim>::estimate(dof_handler,
5765 *   QGauss<dim - 1>(fe.degree + 2),
5766 *   std::map<types::boundary_id, const Function<dim> *>(),
5767 *   tmp_solution,
5768 *   estimated_error_per_cell);
5769 *  
5770 *   }
5771 *   else if (error_estimation_strategy == ErrorEstimationStrategy::residual_error)
5772 *   {
5773 *   compute_error_residual(tmp_solution);
5774 *  
5775 *   }
5776 *   else if (error_estimation_strategy == ErrorEstimationStrategy::weighted_residual_error)
5777 *   {
5778 * @endcode
5779 *
5780 * make a non-parallel copy of tmp_solution
5781 *
5782 * @code
5783 *   Vector<double> copy_solution(tmp_solution);
5784 *  
5785 * @endcode
5786 *
5787 * the dual function definition (it should be defined previously, e.g. input file)
5788 *
5789 * @code
5790 *   if (base_mesh == "Timoshenko beam")
5791 *   {
5792 *   double length = .48,
5793 *   depth = .12;
5794 *  
5795 *   const Point<dim> evaluation_point(length, -depth/2);
5796 *  
5797 *   DualFunctional::PointValuesEvaluation<dim> dual_functional(evaluation_point);
5798 *  
5799 *   DualSolver<dim> dual_solver(triangulation, fe,
5800 *   copy_solution,
5801 *   constitutive_law, dual_functional,
5802 *   timestep_no, output_dir, base_mesh,
5803 *   present_time, end_time);
5804 *  
5805 *   dual_solver.compute_error_DWR (estimated_error_per_cell);
5806 *  
5807 *   }
5808 *   else if (base_mesh == "Thick_tube_internal_pressure")
5809 *   {
5810 *   const unsigned int face_id = 0;
5811 *   std::vector<std::vector<unsigned int> > comp_stress(dim);
5812 *   for (unsigned int i=0; i!=dim; ++i)
5813 *   {
5814 *   comp_stress[i].resize(dim);
5815 *   for (unsigned int j=0; j!=dim; ++j)
5816 *   {
5817 *   comp_stress[i][j] = 1;
5818 *   }
5819 *   }
5820 *  
5821 *   DualFunctional::MeanStressFace<dim> dual_functional(face_id, comp_stress);
5822 *  
5823 *   DualSolver<dim> dual_solver(triangulation, fe,
5824 *   copy_solution,
5825 *   constitutive_law, dual_functional,
5826 *   timestep_no, output_dir, base_mesh,
5827 *   present_time, end_time);
5828 *  
5829 *   dual_solver.compute_error_DWR (estimated_error_per_cell);
5830 *  
5831 *   }
5832 *   else if (base_mesh == "Perforated_strip_tension")
5833 *   {
5834 * @endcode
5835 *
5836 * .........................................
5837 * Mean stress_yy over the bottom boundary
5838 *
5839 * @code
5840 *   const unsigned int face_id = 1;
5841 *   std::vector<std::vector<unsigned int> > comp_stress(dim);
5842 *   for (unsigned int i=0; i!=dim; ++i)
5843 *   {
5844 *   comp_stress[i].resize(dim);
5845 *   for (unsigned int j=0; j!=dim; ++j)
5846 *   {
5847 *   comp_stress[i][j] = 0;
5848 *   }
5849 *   }
5850 *   comp_stress[1][1] = 1;
5851 *  
5852 *   DualFunctional::MeanStressFace<dim> dual_functional(face_id, comp_stress);
5853 *  
5854 * @endcode
5855 *
5856 * .........................................
5857 *
5858
5859 *
5860 *
5861 * @code
5862 *   DualSolver<dim> dual_solver(triangulation, fe,
5863 *   copy_solution,
5864 *   constitutive_law, dual_functional,
5865 *   timestep_no, output_dir, base_mesh,
5866 *   present_time, end_time);
5867 *  
5868 *   dual_solver.compute_error_DWR (estimated_error_per_cell);
5869 *  
5870 *   }
5871 *   else if (base_mesh == "Cantiliver_beam_3d")
5872 *   {
5873 * @endcode
5874 *
5875 * Quantity of interest:
5876 * -----------------------------------------------------------
5877 * displacement at Point A (x=0, y=height/2, z=length)
5878 *
5879 * @code
5880 *   /*
5881 *   const double length = .7,
5882 *   height = 200e-3;
5883 *  
5884 *   const Point<dim> evaluation_point(0, height/2, length);
5885 *  
5886 *   DualFunctional::PointValuesEvaluation<dim> dual_functional(evaluation_point);
5887 *   */
5888 *  
5889 * @endcode
5890 *
5891 * -----------------------------------------------------------
5892 * Mean stress at the specified domain is of interest.
5893 * The interest domains are located on the bottom and top of the flanges
5894 * close to the clamped face, z = 0
5895 * top domain: height/2 - thickness_flange <= y <= height/2
5896 * 0 <= z <= 2 * thickness_flange
5897 * bottom domain: -height/2 <= y <= -height/2 + thickness_flange
5898 * 0 <= z <= 2 * thickness_flange
5899 *
5900
5901 *
5902 *
5903 * @code
5904 *   std::vector<std::vector<unsigned int> > comp_stress(dim);
5905 *   for (unsigned int i=0; i!=dim; ++i)
5906 *   {
5907 *   comp_stress[i].resize(dim);
5908 *   for (unsigned int j=0; j!=dim; ++j)
5909 *   {
5910 *   comp_stress[i][j] = 1;
5911 *   }
5912 *   }
5913 *   DualFunctional::MeanStressDomain<dim> dual_functional(base_mesh, comp_stress);
5914 *  
5915 * @endcode
5916 *
5917 * -----------------------------------------------------------
5918 *
5919
5920 *
5921 *
5922 * @code
5923 *   DualSolver<dim> dual_solver(triangulation, fe,
5924 *   copy_solution,
5925 *   constitutive_law, dual_functional,
5926 *   timestep_no, output_dir, base_mesh,
5927 *   present_time, end_time);
5928 *  
5929 *   dual_solver.compute_error_DWR (estimated_error_per_cell);
5930 *  
5931 *   }
5932 *   else
5933 *   {
5934 *   AssertThrow(false, ExcNotImplemented());
5935 *   }
5936 *  
5937 *  
5938 *   }
5939 *   else
5940 *   {
5941 *   AssertThrow(false, ExcNotImplemented());
5942 *   }
5943 *  
5944 *  
5945 *   relative_error = estimated_error_per_cell.l2_norm() / tmp_solution.l2_norm();
5946 *  
5947 *   pcout << "Estimated relative error = " << relative_error << std::endl;
5948 *  
5949 *   }
5950 *  
5951 *   template <int dim>
5952 *   void
5953 *   ElastoPlasticProblem<dim>::compute_error_residual (const TrilinosWrappers::MPI::Vector &tmp_solution)
5954 *   {
5955 *   FEValues<dim> fe_values(fe, quadrature_formula,
5956 *   update_values |
5957 *   update_gradients |
5958 *   update_hessians |
5959 *   update_quadrature_points |
5960 *   update_JxW_values);
5961 *  
5962 *   const unsigned int n_q_points = quadrature_formula.size();
5963 *   std::vector<SymmetricTensor<2, dim> > strain_tensor(n_q_points);
5964 *   SymmetricTensor<4, dim> stress_strain_tensor_linearized;
5965 *   SymmetricTensor<4, dim> stress_strain_tensor;
5966 *   Tensor<5, dim> stress_strain_tensor_grad;
5967 *   std::vector<std::vector<Tensor<2,dim> > > cell_hessians (n_q_points);
5968 *   for (unsigned int i=0; i!=n_q_points; ++i)
5969 *   {
5970 *   cell_hessians[i].resize (dim);
5971 *   }
5972 *   const EquationData::BodyForce<dim> body_force;
5973 *  
5974 *   std::vector<Vector<double> > body_force_values (n_q_points, Vector<double>(dim));
5975 *   const FEValuesExtractors::Vector displacement(0);
5976 *  
5977 *  
5978 *   FEFaceValues<dim> fe_face_values_cell(fe, face_quadrature_formula,
5979 *   update_values |
5980 *   update_quadrature_points|
5981 *   update_gradients |
5982 *   update_JxW_values |
5983 *   update_normal_vectors),
5984 *   fe_face_values_neighbor (fe, face_quadrature_formula,
5985 *   update_values |
5986 *   update_gradients |
5987 *   update_JxW_values |
5988 *   update_normal_vectors);
5989 *   FESubfaceValues<dim> fe_subface_values_cell (fe, face_quadrature_formula,
5990 *   update_gradients);
5991 *  
5992 *   const unsigned int n_face_q_points = face_quadrature_formula.size();
5993 *   std::vector<Vector<double> > jump_residual (n_face_q_points, Vector<double>(dim));
5994 *   std::vector<std::vector<Tensor<1,dim> > > cell_grads(n_face_q_points);
5995 *   for (unsigned int i=0; i!=n_face_q_points; ++i)
5996 *   {
5997 *   cell_grads[i].resize (dim);
5998 *   }
5999 *   std::vector<std::vector<Tensor<1,dim> > > neighbor_grads(n_face_q_points);
6000 *   for (unsigned int i=0; i!=n_face_q_points; ++i)
6001 *   {
6002 *   neighbor_grads[i].resize (dim);
6003 *   }
6004 *   SymmetricTensor<2, dim> q_cell_strain_tensor;
6005 *   SymmetricTensor<2, dim> q_neighbor_strain_tensor;
6006 *   SymmetricTensor<4, dim> cell_stress_strain_tensor;
6007 *   SymmetricTensor<4, dim> neighbor_stress_strain_tensor;
6008 *  
6009 *  
6010 *   typename std::map<typename DoFHandler<dim>::face_iterator, Vector<double> >
6011 *   face_integrals;
6012 *   typename DoFHandler<dim>::active_cell_iterator
6013 *   cell = dof_handler.begin_active(),
6014 *   endc = dof_handler.end();
6015 *   for (; cell!=endc; ++cell)
6016 *   if (cell->is_locally_owned())
6017 *   {
6018 *   for (unsigned int face_no=0;
6019 *   face_no<GeometryInfo<dim>::faces_per_cell;
6020 *   ++face_no)
6021 *   {
6022 *   face_integrals[cell->face(face_no)].reinit (dim);
6023 *   face_integrals[cell->face(face_no)] = -1e20;
6024 *   }
6025 *   }
6026 *  
6027 *   std::vector<Vector<float> > error_indicators_vector;
6028 *   error_indicators_vector.resize( triangulation.n_active_cells(),
6029 *   Vector<float>(dim) );
6030 *  
6031 * @endcode
6032 *
6033 * ----------------- estimate_some -------------------------
6034 *
6035 * @code
6036 *   cell = dof_handler.begin_active();
6037 *   unsigned int present_cell = 0;
6038 *   for (; cell!=endc; ++cell, ++present_cell)
6039 *   if (cell->is_locally_owned())
6040 *   {
6041 * @endcode
6042 *
6043 * --------------- integrate_over_cell -------------------
6044 *
6045 * @code
6046 *   fe_values.reinit(cell);
6047 *   body_force.vector_value_list(fe_values.get_quadrature_points(),
6048 *   body_force_values);
6049 *   fe_values[displacement].get_function_symmetric_gradients(tmp_solution,
6050 *   strain_tensor);
6051 *   fe_values.get_function_hessians(tmp_solution, cell_hessians);
6052 *  
6053 *   for (unsigned int q_point = 0; q_point < n_q_points; ++q_point)
6054 *   {
6055 *   constitutive_law.get_linearized_stress_strain_tensors(strain_tensor[q_point],
6056 *   stress_strain_tensor_linearized,
6057 *   stress_strain_tensor);
6058 *   constitutive_law.get_grad_stress_strain_tensor(strain_tensor[q_point],
6059 *   cell_hessians[q_point],
6060 *   stress_strain_tensor_grad);
6061 *  
6062 *   for (unsigned int i=0; i!=dim; ++i)
6063 *   {
6064 *   error_indicators_vector[present_cell](i) +=
6065 *   body_force_values[q_point](i)*fe_values.JxW(q_point);
6066 *   for (unsigned int j=0; j!=dim; ++j)
6067 *   {
6068 *   for (unsigned int k=0; k!=dim; ++k)
6069 *   {
6070 *   for (unsigned int l=0; l!=dim; ++l)
6071 *   {
6072 *   error_indicators_vector[present_cell](i) +=
6073 *   ( stress_strain_tensor[i][j][k][l]*
6074 *   0.5*(cell_hessians[q_point][k][l][j]
6075 *   +
6076 *   cell_hessians[q_point][l][k][j])
6077 *   + stress_strain_tensor_grad[i][j][k][l][j] * strain_tensor[q_point][k][l]
6078 *   ) *
6079 *   fe_values.JxW(q_point);
6080 *   }
6081 *   }
6082 *   }
6083 *  
6084 *   }
6085 *  
6086 *   }
6087 * @endcode
6088 *
6089 * -------------------------------------------------------
6090 * compute face_integrals
6091 *
6092 * @code
6093 *   for (unsigned int face_no=0;
6094 *   face_no<GeometryInfo<dim>::faces_per_cell;
6095 *   ++face_no)
6096 *   {
6097 *   if (cell->face(face_no)->at_boundary())
6098 *   {
6099 *   for (unsigned int id=0; id!=dim; ++id)
6100 *   {
6101 *   face_integrals[cell->face(face_no)](id) = 0;
6102 *   }
6103 *   continue;
6104 *   }
6105 *  
6106 *   if ((cell->neighbor(face_no)->has_children() == false) &&
6107 *   (cell->neighbor(face_no)->level() == cell->level()) &&
6108 *   (cell->neighbor(face_no)->index() < cell->index()))
6109 *   continue;
6110 *  
6111 *   if (cell->at_boundary(face_no) == false)
6112 *   if (cell->neighbor(face_no)->level() < cell->level())
6113 *   continue;
6114 *  
6115 *  
6116 *   if (cell->face(face_no)->has_children() == false)
6117 *   {
6118 * @endcode
6119 *
6120 * ------------- integrate_over_regular_face -----------
6121 *
6122 * @code
6123 *   fe_face_values_cell.reinit(cell, face_no);
6124 *   fe_face_values_cell.get_function_gradients (tmp_solution,
6125 *   cell_grads);
6126 *  
6127 *   Assert (cell->neighbor(face_no).state() == IteratorState::valid,
6128 *   ExcInternalError());
6129 *   const unsigned int
6130 *   neighbor_neighbor = cell->neighbor_of_neighbor (face_no);
6131 *   const typename DoFHandler<dim>::active_cell_iterator
6132 *   neighbor = cell->neighbor(face_no);
6133 *  
6134 *   fe_face_values_neighbor.reinit(neighbor, neighbor_neighbor);
6135 *   fe_face_values_neighbor.get_function_gradients (tmp_solution,
6136 *   neighbor_grads);
6137 *  
6138 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
6139 *   {
6140 *   q_cell_strain_tensor = 0.;
6141 *   q_neighbor_strain_tensor = 0.;
6142 *   for (unsigned int i=0; i!=dim; ++i)
6143 *   {
6144 *   for (unsigned int j=0; j!=dim; ++j)
6145 *   {
6146 *   q_cell_strain_tensor[i][j] = 0.5*(cell_grads[q_point][i][j] +
6147 *   cell_grads[q_point][j][i] );
6148 *   q_neighbor_strain_tensor[i][j] = 0.5*(neighbor_grads[q_point][i][j] +
6149 *   neighbor_grads[q_point][j][i] );
6150 *   }
6151 *   }
6152 *  
6153 *   constitutive_law.get_stress_strain_tensor (q_cell_strain_tensor,
6154 *   cell_stress_strain_tensor);
6155 *   constitutive_law.get_stress_strain_tensor (q_neighbor_strain_tensor,
6156 *   neighbor_stress_strain_tensor);
6157 *  
6158 *   jump_residual[q_point] = 0.;
6159 *   for (unsigned int i=0; i!=dim; ++i)
6160 *   {
6161 *   for (unsigned int j=0; j!=dim; ++j)
6162 *   {
6163 *   for (unsigned int k=0; k!=dim; ++k)
6164 *   {
6165 *   for (unsigned int l=0; l!=dim; ++l)
6166 *   {
6167 *   jump_residual[q_point](i) += (cell_stress_strain_tensor[i][j][k][l]*
6168 *   q_cell_strain_tensor[k][l]
6169 *   -
6170 *   neighbor_stress_strain_tensor[i][j][k][l]*
6171 *   q_neighbor_strain_tensor[k][l] )*
6172 *   fe_face_values_cell.normal_vector(q_point)[j];
6173 *   }
6174 *   }
6175 *   }
6176 *   }
6177 *  
6178 *   }
6179 *  
6180 *   Vector<double> face_integral_vector(dim);
6181 *   face_integral_vector = 0;
6182 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
6183 *   {
6184 *   for (unsigned int i=0; i!=dim; ++i)
6185 *   {
6186 *   face_integral_vector(i) += jump_residual[q_point](i) *
6187 *   fe_face_values_cell.JxW(q_point);
6188 *   }
6189 *   }
6190 *  
6191 *   Assert (face_integrals.find (cell->face(face_no)) != face_integrals.end(),
6192 *   ExcInternalError());
6193 *  
6194 *   for (unsigned int i=0; i!=dim; ++i)
6195 *   {
6196 *   Assert (face_integrals[cell->face(face_no)](i) == -1e20,
6197 *   ExcInternalError());
6198 *   face_integrals[cell->face(face_no)](i) = face_integral_vector(i);
6199 *  
6200 *   }
6201 *  
6202 * @endcode
6203 *
6204 * -----------------------------------------------------
6205 *
6206 * @code
6207 *   }
6208 *   else
6209 *   {
6210 * @endcode
6211 *
6212 * ------------- integrate_over_irregular_face ---------
6213 *
6214 * @code
6215 *   const typename DoFHandler<dim>::face_iterator
6216 *   face = cell->face(face_no);
6217 *   const typename DoFHandler<dim>::cell_iterator
6218 *   neighbor = cell->neighbor(face_no);
6219 *   Assert (neighbor.state() == IteratorState::valid,
6220 *   ExcInternalError());
6221 *   Assert (neighbor->has_children(),
6222 *   ExcInternalError());
6223 *  
6224 *   const unsigned int
6225 *   neighbor_neighbor = cell->neighbor_of_neighbor (face_no);
6226 *  
6227 *   for (unsigned int subface_no=0;
6228 *   subface_no<face->n_children(); ++subface_no)
6229 *   {
6230 *   const typename DoFHandler<dim>::active_cell_iterator
6231 *   neighbor_child = cell->neighbor_child_on_subface (face_no, subface_no);
6232 *   Assert (neighbor_child->face(neighbor_neighbor) ==
6233 *   cell->face(face_no)->child(subface_no),
6234 *   ExcInternalError());
6235 *  
6236 *   fe_subface_values_cell.reinit (cell, face_no, subface_no);
6237 *   fe_subface_values_cell.get_function_gradients (tmp_solution,
6238 *   cell_grads);
6239 *   fe_face_values_neighbor.reinit (neighbor_child,
6240 *   neighbor_neighbor);
6241 *   fe_face_values_neighbor.get_function_gradients (tmp_solution,
6242 *   neighbor_grads);
6243 *  
6244 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
6245 *   {
6246 *   q_cell_strain_tensor = 0.;
6247 *   q_neighbor_strain_tensor = 0.;
6248 *   for (unsigned int i=0; i!=dim; ++i)
6249 *   {
6250 *   for (unsigned int j=0; j!=dim; ++j)
6251 *   {
6252 *   q_cell_strain_tensor[i][j] = 0.5*(cell_grads[q_point][i][j] +
6253 *   cell_grads[q_point][j][i] );
6254 *   q_neighbor_strain_tensor[i][j] = 0.5*(neighbor_grads[q_point][i][j] +
6255 *   neighbor_grads[q_point][j][i] );
6256 *   }
6257 *   }
6258 *  
6259 *   constitutive_law.get_stress_strain_tensor (q_cell_strain_tensor,
6260 *   cell_stress_strain_tensor);
6261 *   constitutive_law.get_stress_strain_tensor (q_neighbor_strain_tensor,
6262 *   neighbor_stress_strain_tensor);
6263 *  
6264 *   jump_residual[q_point] = 0.;
6265 *   for (unsigned int i=0; i!=dim; ++i)
6266 *   {
6267 *   for (unsigned int j=0; j!=dim; ++j)
6268 *   {
6269 *   for (unsigned int k=0; k!=dim; ++k)
6270 *   {
6271 *   for (unsigned int l=0; l!=dim; ++l)
6272 *   {
6273 *   jump_residual[q_point](i) += (-cell_stress_strain_tensor[i][j][k][l]*
6274 *   q_cell_strain_tensor[k][l]
6275 *   +
6276 *   neighbor_stress_strain_tensor[i][j][k][l]*
6277 *   q_neighbor_strain_tensor[k][l] )*
6278 *   fe_face_values_neighbor.normal_vector(q_point)[j];
6279 *   }
6280 *   }
6281 *   }
6282 *   }
6283 *  
6284 *   }
6285 *  
6286 *   Vector<double> face_integral_vector(dim);
6287 *   face_integral_vector = 0;
6288 *   for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
6289 *   {
6290 *   for (unsigned int i=0; i!=dim; ++i)
6291 *   {
6292 *   face_integral_vector(i) += jump_residual[q_point](i) *
6293 *   fe_face_values_neighbor.JxW(q_point);
6294 *   }
6295 *   }
6296 *  
6297 *   for (unsigned int i=0; i!=dim; ++i)
6298 *   {
6299 *   face_integrals[neighbor_child->face(neighbor_neighbor)](i) = face_integral_vector(i);
6300 *   }
6301 *  
6302 *   }
6303 *  
6304 *   Vector<double> sum (dim);
6305 *   sum = 0;
6306 *   for (unsigned int subface_no=0;
6307 *   subface_no<face->n_children(); ++subface_no)
6308 *   {
6309 *   Assert (face_integrals.find(face->child(subface_no)) !=
6310 *   face_integrals.end(),
6311 *   ExcInternalError());
6312 *   for (unsigned int i=0; i!=dim; ++i)
6313 *   {
6314 *   Assert (face_integrals[face->child(subface_no)](i) != -1e20,
6315 *   ExcInternalError());
6316 *   sum(i) += face_integrals[face->child(subface_no)](i);
6317 *   }
6318 *   }
6319 *   for (unsigned int i=0; i!=dim; ++i)
6320 *   {
6321 *   face_integrals[face](i) = sum(i);
6322 *   }
6323 *  
6324 *  
6325 * @endcode
6326 *
6327 * -----------------------------------------------------
6328 *
6329 * @code
6330 *   }
6331 *  
6332 *  
6333 *   }
6334 *   }
6335 * @endcode
6336 *
6337 * ----------------------------------------------------------
6338 *
6339
6340 *
6341 *
6342 * @code
6343 *   present_cell=0;
6344 *   cell = dof_handler.begin_active();
6345 *   for (; cell!=endc; ++cell, ++present_cell)
6346 *   if (cell->is_locally_owned())
6347 *   {
6348 *   for (unsigned int face_no=0; face_no<GeometryInfo<dim>::faces_per_cell;
6349 *   ++face_no)
6350 *   {
6351 *   Assert(face_integrals.find(cell->face(face_no)) !=
6352 *   face_integrals.end(),
6353 *   ExcInternalError());
6354 *  
6355 *   for (unsigned int id=0; id!=dim; ++id)
6356 *   {
6357 *   error_indicators_vector[present_cell](id)
6358 *   -= 0.5*face_integrals[cell->face(face_no)](id);
6359 *   }
6360 *  
6361 *   }
6362 *  
6363 *   estimated_error_per_cell(present_cell) = error_indicators_vector[present_cell].l2_norm();
6364 *  
6365 *   }
6366 *  
6367 *   }
6368 *  
6369 *  
6370 * @endcode
6371 *
6372 *
6373 * <a name="elastoplastic.cc-PlasticityContactProblemrefine_grid"></a>
6374 * <h4>PlasticityContactProblem::refine_grid</h4>
6375 *
6376
6377 *
6378 * If you've made it this far into the deal.II tutorial, the following
6379 * function refining the mesh should not pose any challenges to you
6380 * any more. It refines the mesh, either globally or using the Kelly
6381 * error estimator, and if so asked also transfers the solution from
6382 * the previous to the next mesh. In the latter case, we also need
6383 * to compute the active set and other quantities again, for which we
6384 * need the information computed by <code>compute_nonlinear_residual()</code>.
6385 *
6386 * @code
6387 *   template <int dim>
6388 *   void
6389 *   ElastoPlasticProblem<dim>::refine_grid ()
6390 *   {
6391 * @endcode
6392 *
6393 * ---------------------------------------------------------------
6394 * Make a field variable for history varibales to be able to
6395 * transfer the data to the quadrature points of the new mesh
6396 *
6397 * @code
6398 *   FE_DGQ<dim> history_fe (1);
6399 *   DoFHandler<dim> history_dof_handler (triangulation);
6400 *   history_dof_handler.distribute_dofs (history_fe);
6401 *   std::vector< std::vector< Vector<double> > >
6402 *   history_stress_field (dim, std::vector< Vector<double> >(dim)),
6403 *   local_history_stress_values_at_qpoints (dim, std::vector< Vector<double> >(dim)),
6404 *   local_history_stress_fe_values (dim, std::vector< Vector<double> >(dim));
6405 *  
6406 *  
6407 *   std::vector< std::vector< Vector<double> > >
6408 *   history_strain_field (dim, std::vector< Vector<double> >(dim)),
6409 *   local_history_strain_values_at_qpoints (dim, std::vector< Vector<double> >(dim)),
6410 *   local_history_strain_fe_values (dim, std::vector< Vector<double> >(dim));
6411 *  
6412 *   for (unsigned int i=0; i<dim; ++i)
6413 *   for (unsigned int j=0; j<dim; ++j)
6414 *   {
6415 *   history_stress_field[i][j].reinit(history_dof_handler.n_dofs());
6416 *   local_history_stress_values_at_qpoints[i][j].reinit(quadrature_formula.size());
6417 *   local_history_stress_fe_values[i][j].reinit(history_fe.dofs_per_cell);
6418 *  
6419 *   history_strain_field[i][j].reinit(history_dof_handler.n_dofs());
6420 *   local_history_strain_values_at_qpoints[i][j].reinit(quadrature_formula.size());
6421 *   local_history_strain_fe_values[i][j].reinit(history_fe.dofs_per_cell);
6422 *   }
6423 *   FullMatrix<double> qpoint_to_dof_matrix (history_fe.dofs_per_cell,
6424 *   quadrature_formula.size());
6426 *   (history_fe,
6427 *   quadrature_formula, quadrature_formula,
6428 *   qpoint_to_dof_matrix);
6430 *   cell = dof_handler.begin_active(),
6431 *   endc = dof_handler.end(),
6432 *   dg_cell = history_dof_handler.begin_active();
6433 *   for (; cell!=endc; ++cell, ++dg_cell)
6434 *   if (cell->is_locally_owned())
6435 *   {
6436 *   PointHistory<dim> *local_quadrature_points_history
6437 *   = reinterpret_cast<PointHistory<dim> *>(cell->user_pointer());
6438 *   Assert (local_quadrature_points_history >=
6439 *   &quadrature_point_history.front(),
6440 *   ExcInternalError());
6441 *   Assert (local_quadrature_points_history <
6442 *   &quadrature_point_history.back(),
6443 *   ExcInternalError());
6444 *   for (unsigned int i=0; i<dim; ++i)
6445 *   for (unsigned int j=0; j<dim; ++j)
6446 *   {
6447 *   for (unsigned int q=0; q<quadrature_formula.size(); ++q)
6448 *   {
6449 *   local_history_stress_values_at_qpoints[i][j](q)
6450 *   = local_quadrature_points_history[q].old_stress[i][j];
6451 *  
6452 *   local_history_strain_values_at_qpoints[i][j](q)
6453 *   = local_quadrature_points_history[q].old_strain[i][j];
6454 *   }
6455 *   qpoint_to_dof_matrix.vmult (local_history_stress_fe_values[i][j],
6456 *   local_history_stress_values_at_qpoints[i][j]);
6457 *   dg_cell->set_dof_values (local_history_stress_fe_values[i][j],
6458 *   history_stress_field[i][j]);
6459 *  
6460 *   qpoint_to_dof_matrix.vmult (local_history_strain_fe_values[i][j],
6461 *   local_history_strain_values_at_qpoints[i][j]);
6462 *   dg_cell->set_dof_values (local_history_strain_fe_values[i][j],
6463 *   history_strain_field[i][j]);
6464 *   }
6465 *   }
6466 *  
6467 *  
6468 * @endcode
6469 *
6470 * ---------------------------------------------------------------
6471 * Refine the mesh
6472 *
6473 * @code
6474 *   if (refinement_strategy == RefinementStrategy::refine_global)
6475 *   {
6477 *   cell = triangulation.begin_active();
6478 *   cell != triangulation.end(); ++cell)
6479 *   if (cell->is_locally_owned())
6480 *   cell->set_refine_flag ();
6481 *   }
6482 *   else
6483 *   {
6484 *   const double refine_fraction_cells = .3,
6485 *   coarsen_fraction_cells = .03;
6486 * @endcode
6487 *
6488 * const double refine_fraction_cells = .1,
6489 * coarsen_fraction_cells = .3;
6490 *
6491
6492 *
6493 *
6494 * @code
6496 *   ::refine_and_coarsen_fixed_number(triangulation,
6497 *   estimated_error_per_cell,
6498 *   refine_fraction_cells, coarsen_fraction_cells);
6499 *   }
6500 *  
6501 *   triangulation.prepare_coarsening_and_refinement();
6502 *  
6504 *   TrilinosWrappers::MPI::Vector> solution_transfer(dof_handler);
6505 *   solution_transfer.prepare_for_coarsening_and_refinement(solution);
6506 *  
6507 *  
6509 *   TrilinosWrappers::MPI::Vector> incremental_displacement_transfer(dof_handler);
6510 *   if (transfer_solution)
6511 *   incremental_displacement_transfer.prepare_for_coarsening_and_refinement(incremental_displacement);
6512 *  
6513 *   SolutionTransfer<dim, Vector<double> > history_stress_field_transfer0(history_dof_handler),
6514 *   history_stress_field_transfer1(history_dof_handler),
6515 *   history_stress_field_transfer2(history_dof_handler);
6516 *   history_stress_field_transfer0.prepare_for_coarsening_and_refinement(history_stress_field[0]);
6517 *   if ( dim > 1)
6518 *   {
6519 *   history_stress_field_transfer1.prepare_for_coarsening_and_refinement(history_stress_field[1]);
6520 *   }
6521 *   if ( dim == 3)
6522 *   {
6523 *   history_stress_field_transfer2.prepare_for_coarsening_and_refinement(history_stress_field[2]);
6524 *   }
6525 *  
6526 *   SolutionTransfer<dim, Vector<double> > history_strain_field_transfer0(history_dof_handler),
6527 *   history_strain_field_transfer1(history_dof_handler),
6528 *   history_strain_field_transfer2(history_dof_handler);
6529 *   history_strain_field_transfer0.prepare_for_coarsening_and_refinement(history_strain_field[0]);
6530 *   if ( dim > 1)
6531 *   {
6532 *   history_strain_field_transfer1.prepare_for_coarsening_and_refinement(history_strain_field[1]);
6533 *   }
6534 *   if ( dim == 3)
6535 *   {
6536 *   history_strain_field_transfer2.prepare_for_coarsening_and_refinement(history_strain_field[2]);
6537 *   }
6538 *  
6539 *   triangulation.execute_coarsening_and_refinement();
6540 *   pcout << " Number of active cells: "
6541 *   << triangulation.n_active_cells()
6542 *   << std::endl;
6543 *  
6544 *   setup_system();
6545 *   setup_quadrature_point_history ();
6546 *  
6547 *  
6548 *   TrilinosWrappers::MPI::Vector distributed_solution(locally_owned_dofs, mpi_communicator);
6549 * @endcode
6550 *
6551 * distributed_solution = solution;
6552 *
6553 * @code
6554 *   solution_transfer.interpolate(distributed_solution);
6555 *   solution = distributed_solution;
6556 *  
6557 *   if (transfer_solution)
6558 *   {
6559 *   TrilinosWrappers::MPI::Vector distributed_incremental_displacement(locally_owned_dofs, mpi_communicator);
6560 * @endcode
6561 *
6562 * distributed_incremental_displacement = incremental_displacement;
6563 *
6564 * @code
6565 *   incremental_displacement_transfer.interpolate(distributed_incremental_displacement);
6566 *   incremental_displacement = distributed_incremental_displacement;
6567 * @endcode
6568 *
6569 * compute_nonlinear_residual(incremental_displacement);
6570 *
6571 * @code
6572 *   }
6573 *  
6574 * @endcode
6575 *
6576 * ---------------------------------------------------
6577 *
6578 * @code
6579 *   history_dof_handler.distribute_dofs (history_fe);
6580 * @endcode
6581 *
6582 * stress
6583 *
6584 * @code
6585 *   std::vector< std::vector< Vector<double> > >
6586 *   distributed_history_stress_field (dim, std::vector< Vector<double> >(dim));
6587 *   for (unsigned int i=0; i<dim; ++i)
6588 *   for (unsigned int j=0; j<dim; ++j)
6589 *   {
6590 *   distributed_history_stress_field[i][j].reinit(history_dof_handler.n_dofs());
6591 *   }
6592 *  
6593 *   history_stress_field_transfer0.interpolate(history_stress_field[0], distributed_history_stress_field[0]);
6594 *   if ( dim > 1)
6595 *   {
6596 *   history_stress_field_transfer1.interpolate(history_stress_field[1], distributed_history_stress_field[1]);
6597 *   }
6598 *   if ( dim == 3)
6599 *   {
6600 *   history_stress_field_transfer2.interpolate(history_stress_field[2], distributed_history_stress_field[2]);
6601 *   }
6602 *  
6603 *   history_stress_field = distributed_history_stress_field;
6604 *  
6605 * @endcode
6606 *
6607 * strain
6608 *
6609 * @code
6610 *   std::vector< std::vector< Vector<double> > >
6611 *   distributed_history_strain_field (dim, std::vector< Vector<double> >(dim));
6612 *   for (unsigned int i=0; i<dim; ++i)
6613 *   for (unsigned int j=0; j<dim; ++j)
6614 *   {
6615 *   distributed_history_strain_field[i][j].reinit(history_dof_handler.n_dofs());
6616 *   }
6617 *  
6618 *   history_strain_field_transfer0.interpolate(history_strain_field[0], distributed_history_strain_field[0]);
6619 *   if ( dim > 1)
6620 *   {
6621 *   history_strain_field_transfer1.interpolate(history_strain_field[1], distributed_history_strain_field[1]);
6622 *   }
6623 *   if ( dim == 3)
6624 *   {
6625 *   history_strain_field_transfer2.interpolate(history_strain_field[2], distributed_history_strain_field[2]);
6626 *   }
6627 *  
6628 *   history_strain_field = distributed_history_strain_field;
6629 *  
6630 * @endcode
6631 *
6632 * ---------------------------------------------------------------
6633 * Transfer the history data to the quadrature points of the new mesh
6634 * In a final step, we have to get the data back from the now
6635 * interpolated global field to the quadrature points on the
6636 * new mesh. The following code will do that:
6637 *
6638
6639 *
6640 *
6641 * @code
6642 *   FullMatrix<double> dof_to_qpoint_matrix (quadrature_formula.size(),
6643 *   history_fe.dofs_per_cell);
6645 *   (history_fe,
6646 *   quadrature_formula,
6647 *   dof_to_qpoint_matrix);
6648 *   cell = dof_handler.begin_active();
6649 *   endc = dof_handler.end();
6650 *   dg_cell = history_dof_handler.begin_active();
6651 *   for (; cell != endc; ++cell, ++dg_cell)
6652 *   if (cell->is_locally_owned())
6653 *   {
6654 *   PointHistory<dim> *local_quadrature_points_history
6655 *   = reinterpret_cast<PointHistory<dim> *>(cell->user_pointer());
6656 *   Assert (local_quadrature_points_history >=
6657 *   &quadrature_point_history.front(),
6658 *   ExcInternalError());
6659 *   Assert (local_quadrature_points_history <
6660 *   &quadrature_point_history.back(),
6661 *   ExcInternalError());
6662 *   for (unsigned int i=0; i<dim; ++i)
6663 *   for (unsigned int j=0; j<dim; ++j)
6664 *   {
6665 *   dg_cell->get_dof_values (history_stress_field[i][j],
6666 *   local_history_stress_fe_values[i][j]);
6667 *   dof_to_qpoint_matrix.vmult (local_history_stress_values_at_qpoints[i][j],
6668 *   local_history_stress_fe_values[i][j]);
6669 *  
6670 *   dg_cell->get_dof_values (history_strain_field[i][j],
6671 *   local_history_strain_fe_values[i][j]);
6672 *   dof_to_qpoint_matrix.vmult (local_history_strain_values_at_qpoints[i][j],
6673 *   local_history_strain_fe_values[i][j]);
6674 *   for (unsigned int q=0; q<quadrature_formula.size(); ++q)
6675 *   {
6676 *   local_quadrature_points_history[q].old_stress[i][j]
6677 *   = local_history_stress_values_at_qpoints[i][j](q);
6678 *  
6679 *   local_quadrature_points_history[q].old_strain[i][j]
6680 *   = local_history_strain_values_at_qpoints[i][j](q);
6681 *   }
6682 *   }
6683 *  
6684 *  
6685 *   }
6686 *   }
6687 *  
6688 * @endcode
6689 *
6690 *
6691 * <a name="elastoplastic.cc-ElastoPlasticProblemsetup_quadrature_point_history"></a>
6692 * <h4>ElastoPlasticProblem::setup_quadrature_point_history</h4>
6693 *
6694
6695 *
6696 * At the beginning of our computations, we needed to set up initial values
6697 * of the history variables, such as the existing stresses in the material,
6698 * that we store in each quadrature point. As mentioned above, we use the
6699 * <code>user_pointer</code> for this that is available in each cell.
6700 *
6701
6702 *
6703 * To put this into larger perspective, we note that if we had previously
6704 * available stresses in our model (which we assume do not exist for the
6705 * purpose of this program), then we would need to interpolate the field of
6706 * preexisting stresses to the quadrature points. Likewise, if we were to
6707 * simulate elasto-plastic materials with hardening/softening, then we would
6708 * have to store additional history variables like the present yield stress
6709 * of the accumulated plastic strains in each quadrature
6710 * points. Pre-existing hardening or weakening would then be implemented by
6711 * interpolating these variables in the present function as well.
6712 *
6713 * @code
6714 *   template <int dim>
6715 *   void ElastoPlasticProblem<dim>::setup_quadrature_point_history ()
6716 *   {
6717 * @endcode
6718 *
6719 * What we need to do here is to first count how many quadrature points
6720 * are within the responsibility of this processor. This, of course,
6721 * equals the number of cells that belong to this processor times the
6722 * number of quadrature points our quadrature formula has on each cell.
6723 *
6724
6725 *
6726 * For good measure, we also set all user pointers of all cells, whether
6727 * ours of not, to the null pointer. This way, if we ever access the user
6728 * pointer of a cell which we should not have accessed, a segmentation
6729 * fault will let us know that this should not have happened:
6730 *
6731 * @code
6732 *   unsigned int our_cells = 0;
6734 *   cell = triangulation.begin_active();
6735 *   cell != triangulation.end(); ++cell)
6736 *   if (cell->is_locally_owned())
6737 *   ++our_cells;
6738 *  
6739 *   triangulation.clear_user_data();
6740 *  
6741 * @endcode
6742 *
6743 * Next, allocate as many quadrature objects as we need. Since the
6744 * <code>resize</code> function does not actually shrink the amount of
6745 * allocated memory if the requested new size is smaller than the old
6746 * size, we resort to a trick to first free all memory, and then
6747 * reallocate it: we declare an empty vector as a temporary variable and
6748 * then swap the contents of the old vector and this temporary
6749 * variable. This makes sure that the
6750 * <code>quadrature_point_history</code> is now really empty, and we can
6751 * let the temporary variable that now holds the previous contents of the
6752 * vector go out of scope and be destroyed. In the next step. we can then
6753 * re-allocate as many elements as we need, with the vector
6754 * default-initializing the <code>PointHistory</code> objects, which
6755 * includes setting the stress variables to zero.
6756 *
6757 * @code
6758 *   {
6759 *   std::vector<PointHistory<dim> > tmp;
6760 *   tmp.swap (quadrature_point_history);
6761 *   }
6762 *   quadrature_point_history.resize (our_cells *
6763 *   quadrature_formula.size());
6764 *  
6765 * @endcode
6766 *
6767 * Finally loop over all cells again and set the user pointers from the
6768 * cells that belong to the present processor to point to the first
6769 * quadrature point objects corresponding to this cell in the vector of
6770 * such objects:
6771 *
6772 * @code
6773 *   unsigned int history_index = 0;
6775 *   cell = triangulation.begin_active();
6776 *   cell != triangulation.end(); ++cell)
6777 *   if (cell->is_locally_owned())
6778 *   {
6779 *   cell->set_user_pointer (&quadrature_point_history[history_index]);
6780 *   history_index += quadrature_formula.size();
6781 *   }
6782 *  
6783 * @endcode
6784 *
6785 * At the end, for good measure make sure that our count of elements was
6786 * correct and that we have both used up all objects we allocated
6787 * previously, and not point to any objects beyond the end of the
6788 * vector. Such defensive programming strategies are always good checks to
6789 * avoid accidental errors and to guard against future changes to this
6790 * function that forget to update all uses of a variable at the same
6791 * time. Recall that constructs using the <code>Assert</code> macro are
6792 * optimized away in optimized mode, so do not affect the run time of
6793 * optimized runs:
6794 *
6795 * @code
6796 *   Assert (history_index == quadrature_point_history.size(),
6797 *   ExcInternalError());
6798 *   }
6799 *  
6800 * @endcode
6801 *
6802 *
6803 * <a name="elastoplastic.cc-ElastoPlasticProblemupdate_quadrature_point_history"></a>
6804 * <h4>ElastoPlasticProblem::update_quadrature_point_history</h4>
6805 *
6806
6807 *
6808 * At the end of each time step, we should have computed an incremental
6809 * displacement update so that the material in its new configuration
6810 * accommodates for the difference between the external body and boundary
6811 * forces applied during this time step minus the forces exerted through
6812 * preexisting internal stresses. In order to have the preexisting
6813 * stresses available at the next time step, we therefore have to update the
6814 * preexisting stresses with the stresses due to the incremental
6815 * displacement computed during the present time step. Ideally, the
6816 * resulting sum of internal stresses would exactly counter all external
6817 * forces. Indeed, a simple experiment can make sure that this is so: if we
6818 * choose boundary conditions and body forces to be time independent, then
6819 * the forcing terms (the sum of external forces and internal stresses)
6820 * should be exactly zero. If you make this experiment, you will realize
6821 * from the output of the norm of the right hand side in each time step that
6822 * this is almost the case: it is not exactly zero, since in the first time
6823 * step the incremental displacement and stress updates were computed
6824 * relative to the undeformed mesh, which was then deformed. In the second
6825 * time step, we again compute displacement and stress updates, but this
6826 * time in the deformed mesh -- there, the resulting updates are very small
6827 * but not quite zero. This can be iterated, and in each such iteration the
6828 * residual, i.e. the norm of the right hand side vector, is reduced; if one
6829 * makes this little experiment, one realizes that the norm of this residual
6830 * decays exponentially with the number of iterations, and after an initial
6831 * very rapid decline is reduced by roughly a factor of about 3.5 in each
6832 * iteration (for one testcase I looked at, other testcases, and other
6833 * numbers of unknowns change the factor, but not the exponential decay).
6834 *
6835
6836 *
6837 * In a sense, this can then be considered as a quasi-timestepping scheme to
6838 * resolve the nonlinear problem of solving large-deformation elasticity on
6839 * a mesh that is moved along in a Lagrangian manner.
6840 *
6841
6842 *
6843 * Another complication is that the existing (old) stresses are defined on
6844 * the old mesh, which we will move around after updating the stresses. If
6845 * this mesh update involves rotations of the cell, then we need to also
6846 * rotate the updated stress, since it was computed relative to the
6847 * coordinate system of the old cell.
6848 *
6849
6850 *
6851 * Thus, what we need is the following: on each cell which the present
6852 * processor owns, we need to extract the old stress from the data stored
6853 * with each quadrature point, compute the stress update, add the two
6854 * together, and then rotate the result together with the incremental
6855 * rotation computed from the incremental displacement at the present
6856 * quadrature point. We will detail these steps below:
6857 *
6858 * @code
6859 *   template <int dim>
6860 *   void ElastoPlasticProblem<dim>::
6861 *   update_quadrature_point_history ()
6862 *   {
6863 * @endcode
6864 *
6865 * First, set up an <code>FEValues</code> object by which we will evaluate
6866 * the displacements and the gradients thereof at the
6867 * quadrature points, together with a vector that will hold this
6868 * information:
6869 *
6870 * @code
6871 *   FEValues<dim> fe_values (fe, quadrature_formula,
6874 *  
6875 *   const unsigned int n_q_points = quadrature_formula.size();
6876 *  
6877 *   std::vector<SymmetricTensor<2, dim> > incremental_strain_tensor(n_q_points);
6878 *   SymmetricTensor<4, dim> stress_strain_tensor;
6879 *  
6880 *  
6881 * @endcode
6882 *
6883 * Then loop over all cells and do the job in the cells that belong to our
6884 * subdomain:
6885 *
6886
6887 *
6888 *
6889 * @code
6891 *   cell = dof_handler.begin_active(),
6892 *   endc = dof_handler.end();
6893 *  
6894 *   const FEValuesExtractors::Vector displacement(0);
6895 *  
6896 *   for (; cell != endc; ++cell)
6897 *   if (cell->is_locally_owned())
6898 *   {
6899 * @endcode
6900 *
6901 * Next, get a pointer to the quadrature point history data local to
6902 * the present cell, and, as a defensive measure, make sure that
6903 * this pointer is within the bounds of the global array:
6904 *
6905 * @code
6906 *   PointHistory<dim> *local_quadrature_points_history
6907 *   = reinterpret_cast<PointHistory<dim> *>(cell->user_pointer());
6908 *   Assert (local_quadrature_points_history >=
6909 *   &quadrature_point_history.front(),
6910 *   ExcInternalError());
6911 *   Assert (local_quadrature_points_history <
6912 *   &quadrature_point_history.back(),
6913 *   ExcInternalError());
6914 *  
6915 * @endcode
6916 *
6917 * Then initialize the <code>FEValues</code> object on the present
6918 * cell, and extract the strains of the displacement at the
6919 * quadrature points
6920 *
6921 * @code
6922 *   fe_values.reinit (cell);
6923 *   fe_values[displacement].get_function_symmetric_gradients(incremental_displacement,
6924 *   incremental_strain_tensor);
6925 *  
6926 * @endcode
6927 *
6928 * Then loop over the quadrature points of this cell:
6929 *
6930 * @code
6931 *   for (unsigned int q=0; q<quadrature_formula.size(); ++q)
6932 *   {
6933 *   local_quadrature_points_history[q].old_strain +=
6934 *   incremental_strain_tensor[q];
6935 *  
6936 *   constitutive_law.get_stress_strain_tensor(local_quadrature_points_history[q].old_strain,
6937 *   stress_strain_tensor);
6938 *  
6939 * @endcode
6940 *
6941 * The result of these operations is then written back into
6942 * the original place:
6943 *
6944 * @code
6945 *   local_quadrature_points_history[q].old_stress
6946 *   = stress_strain_tensor * local_quadrature_points_history[q].old_strain;
6947 *  
6948 *   local_quadrature_points_history[q].point
6949 *   = fe_values.get_quadrature_points ()[q];
6950 *   }
6951 *   }
6952 *   }
6953 *  
6954 *  
6955 * @endcode
6956 *
6957 *
6958 * <a name="elastoplastic.cc-PlasticityContactProblemmove_mesh"></a>
6959 * <h4>PlasticityContactProblem::move_mesh</h4>
6960 *
6961
6962 *
6963 * The remaining three functions before we get to <code>run()</code>
6964 * have to do with generating output. The following one is an attempt
6965 * at showing the deformed body in its deformed configuration. To this
6966 * end, this function takes a displacement vector field and moves every
6967 * vertex of the (local part) of the mesh by the previously computed
6968 * displacement. We will call this function with the current
6969 * displacement field before we generate graphical output, and we will
6970 * call it again after generating graphical output with the negative
6971 * displacement field to undo the changes to the mesh so made.
6972 *
6973
6974 *
6975 * The function itself is pretty straightforward. All we have to do
6976 * is keep track which vertices we have already touched, as we
6977 * encounter the same vertices multiple times as we loop over cells.
6978 *
6979 * @code
6980 *   template <int dim>
6981 *   void
6982 *   ElastoPlasticProblem<dim>::
6983 *   move_mesh (const TrilinosWrappers::MPI::Vector &displacement) const
6984 *   {
6985 *   std::vector<bool> vertex_touched(triangulation.n_vertices(), false);
6986 *  
6987 *   for (typename DoFHandler<dim>::active_cell_iterator cell =
6988 *   dof_handler.begin_active();
6989 *   cell != dof_handler.end(); ++cell)
6990 *   if (cell->is_locally_owned())
6991 *   for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
6992 *   if (vertex_touched[cell->vertex_index(v)] == false)
6993 *   {
6994 *   vertex_touched[cell->vertex_index(v)] = true;
6995 *  
6996 *   Point<dim> vertex_displacement;
6997 *   for (unsigned int d = 0; d < dim; ++d)
6998 *   vertex_displacement[d] = displacement(cell->vertex_dof_index(v, d));
6999 *  
7000 *   cell->vertex(v) += vertex_displacement;
7001 *   }
7002 *   }
7003 *  
7004 *  
7005 *  
7006 * @endcode
7007 *
7008 *
7009 * <a name="elastoplastic.cc-PlasticityContactProblemoutput_results"></a>
7010 * <h4>PlasticityContactProblem::output_results</h4>
7011 *
7012
7013 *
7014 * Next is the function we use to actually generate graphical output. The
7015 * function is a bit tedious, but not actually particularly complicated.
7016 * It moves the mesh at the top (and moves it back at the end), then
7017 * computes the contact forces along the contact surface. We can do
7018 * so (as shown in the accompanying paper) by taking the untreated
7019 * residual vector and identifying which degrees of freedom
7020 * correspond to those with contact by asking whether they have an
7021 * inhomogeneous constraints associated with them. As always, we need
7022 * to be mindful that we can only write into completely distributed
7023 * vectors (i.e., vectors without ghost elements) but that when we
7024 * want to generate output, we need vectors that do indeed have
7025 * ghost entries for all locally relevant degrees of freedom.
7026 *
7027 * @code
7028 *   template <int dim>
7029 *   void
7030 *   ElastoPlasticProblem<dim>::output_results (const std::string &filename_base)
7031 *   {
7032 *   TimerOutput::Scope t(computing_timer, "Graphical output");
7033 *  
7034 *   pcout << " Writing graphical output... " << std::flush;
7035 *  
7036 *   TrilinosWrappers::MPI::Vector magnified_solution(solution);
7037 *  
7038 *   const double magnified_factor = 3;
7039 *   magnified_solution *= magnified_factor;
7040 *  
7041 *   move_mesh(magnified_solution);
7042 *  
7043 *   DataOut<dim> data_out;
7044 *  
7045 *   data_out.attach_dof_handler(dof_handler);
7046 *  
7047 *  
7048 *   const std::vector<DataComponentInterpretation::DataComponentInterpretation>
7049 *   data_component_interpretation(dim, DataComponentInterpretation::component_is_part_of_vector);
7050 *   data_out.add_data_vector(solution,
7051 *   std::vector<std::string> (dim, "displacement"),
7052 *   DataOut<dim>::type_dof_data, data_component_interpretation);
7053 *  
7054 *  
7055 *   std::vector<std::string> solution_names;
7056 *  
7057 *   switch (dim)
7058 *   {
7059 *   case 1:
7060 *   solution_names.push_back ("displacement");
7061 *   break;
7062 *   case 2:
7063 *   solution_names.push_back ("x_displacement");
7064 *   solution_names.push_back ("y_displacement");
7065 *   break;
7066 *   case 3:
7067 *   solution_names.push_back ("x_displacement");
7068 *   solution_names.push_back ("y_displacement");
7069 *   solution_names.push_back ("z_displacement");
7070 *   break;
7071 *   default:
7072 *   AssertThrow (false, ExcNotImplemented());
7073 *   }
7074 *  
7075 *   data_out.add_data_vector (solution, solution_names);
7076 *  
7077 *  
7078 *  
7079 *   Vector<float> subdomain(triangulation.n_active_cells());
7080 *   for (unsigned int i = 0; i < subdomain.size(); ++i)
7081 *   subdomain(i) = triangulation.locally_owned_subdomain();
7082 *   data_out.add_data_vector(subdomain, "subdomain");
7083 *  
7084 *  
7085 *   data_out.add_data_vector(fraction_of_plastic_q_points_per_cell,
7086 *   "fraction_of_plastic_q_points");
7087 *  
7088 *  
7089 *   data_out.build_patches();
7090 *  
7091 * @endcode
7092 *
7093 * In the remainder of the function, we generate one VTU file on
7094 * every processor, indexed by the subdomain id of this processor.
7095 * On the first processor, we then also create a <code>.pvtu</code>
7096 * file that indexes <i>all</i> of the VTU files so that the entire
7097 * set of output files can be read at once. These <code>.pvtu</code>
7098 * are used by Paraview to describe an entire parallel computation's
7099 * output files. We then do the same again for the competitor of
7100 * Paraview, the Visit visualization program, by creating a matching
7101 * <code>.visit</code> file.
7102 *
7103 * @code
7104 *   const std::string filename =
7105 *   (output_dir + filename_base + "-"
7106 *   + Utilities::int_to_string(triangulation.locally_owned_subdomain(), 4));
7107 *  
7108 *   std::ofstream output_vtu((filename + ".vtu").c_str());
7109 *   data_out.write_vtu(output_vtu);
7110 *   pcout << output_dir + filename_base << ".pvtu" << std::endl;
7111 *  
7112 *  
7113 *   if (this_mpi_process == 0)
7114 *   {
7115 *   std::vector<std::string> filenames;
7116 *   for (unsigned int i = 0; i < n_mpi_processes; ++i)
7117 *   filenames.push_back(filename_base + "-" +
7118 *   Utilities::int_to_string(i, 4) +
7119 *   ".vtu");
7120 *  
7121 *   std::ofstream pvtu_master_output((output_dir + filename_base + ".pvtu").c_str());
7122 *   data_out.write_pvtu_record(pvtu_master_output, filenames);
7123 *  
7124 *   std::ofstream visit_master_output((output_dir + filename_base + ".visit").c_str());
7125 *   data_out.write_pvtu_record(visit_master_output, filenames);
7126 *  
7127 * @endcode
7128 *
7129 * produce eps files for mesh illustration
7130 *
7131 * @code
7132 *   std::ofstream output_eps((filename + ".eps").c_str());
7133 *   GridOut grid_out;
7134 *   grid_out.write_eps(triangulation, output_eps);
7135 *   }
7136 *  
7137 * @endcode
7138 *
7139 * Extrapolate the stresses from Gauss point to the nodes
7140 *
7141 * @code
7142 *   SymmetricTensor<2, dim> stress_at_qpoint;
7143 *  
7144 *   FE_DGQ<dim> history_fe (1);
7145 *   DoFHandler<dim> history_dof_handler (triangulation);
7146 *   history_dof_handler.distribute_dofs (history_fe);
7147 *   std::vector< std::vector< Vector<double> > >
7148 *   history_stress_field (dim, std::vector< Vector<double> >(dim)),
7149 *   local_history_stress_values_at_qpoints (dim, std::vector< Vector<double> >(dim)),
7150 *   local_history_stress_fe_values (dim, std::vector< Vector<double> >(dim));
7151 *   for (unsigned int i=0; i<dim; ++i)
7152 *   for (unsigned int j=0; j<dim; ++j)
7153 *   {
7154 *   history_stress_field[i][j].reinit(history_dof_handler.n_dofs());
7155 *   local_history_stress_values_at_qpoints[i][j].reinit(quadrature_formula.size());
7156 *   local_history_stress_fe_values[i][j].reinit(history_fe.dofs_per_cell);
7157 *   }
7158 *  
7159 *   Vector<double> VM_stress_field (history_dof_handler.n_dofs()),
7160 *   local_VM_stress_values_at_qpoints (quadrature_formula.size()),
7161 *   local_VM_stress_fe_values (history_fe.dofs_per_cell);
7162 *  
7163 *   FullMatrix<double> qpoint_to_dof_matrix (history_fe.dofs_per_cell,
7164 *   quadrature_formula.size());
7165 *   FETools::compute_projection_from_quadrature_points_matrix
7166 *   (history_fe,
7167 *   quadrature_formula, quadrature_formula,
7168 *   qpoint_to_dof_matrix);
7169 *  
7170 *   typename DoFHandler<dim>::active_cell_iterator
7171 *   cell = dof_handler.begin_active(),
7172 *   endc = dof_handler.end(),
7173 *   dg_cell = history_dof_handler.begin_active();
7174 *  
7175 *   const FEValuesExtractors::Vector displacement(0);
7176 *  
7177 *   for (; cell!=endc; ++cell, ++dg_cell)
7178 *   if (cell->is_locally_owned())
7179 *   {
7180 *   PointHistory<dim> *local_quadrature_points_history
7181 *   = reinterpret_cast<PointHistory<dim> *>(cell->user_pointer());
7182 *   Assert (local_quadrature_points_history >=
7183 *   &quadrature_point_history.front(),
7184 *   ExcInternalError());
7185 *   Assert (local_quadrature_points_history <
7186 *   &quadrature_point_history.back(),
7187 *   ExcInternalError());
7188 *  
7189 * @endcode
7190 *
7191 * Then loop over the quadrature points of this cell:
7192 *
7193 * @code
7194 *   for (unsigned int q=0; q<quadrature_formula.size(); ++q)
7195 *   {
7196 *   stress_at_qpoint = local_quadrature_points_history[q].old_stress;
7197 *  
7198 *   for (unsigned int i=0; i<dim; ++i)
7199 *   for (unsigned int j=i; j<dim; ++j)
7200 *   {
7201 *   local_history_stress_values_at_qpoints[i][j](q) = stress_at_qpoint[i][j];
7202 *   }
7203 *  
7204 *   local_VM_stress_values_at_qpoints(q) = Evaluation::get_von_Mises_stress(stress_at_qpoint);
7205 *  
7206 *   }
7207 *  
7208 *  
7209 *   for (unsigned int i=0; i<dim; ++i)
7210 *   for (unsigned int j=i; j<dim; ++j)
7211 *   {
7212 *   qpoint_to_dof_matrix.vmult (local_history_stress_fe_values[i][j],
7213 *   local_history_stress_values_at_qpoints[i][j]);
7214 *   dg_cell->set_dof_values (local_history_stress_fe_values[i][j],
7215 *   history_stress_field[i][j]);
7216 *   }
7217 *  
7218 *   qpoint_to_dof_matrix.vmult (local_VM_stress_fe_values,
7219 *   local_VM_stress_values_at_qpoints);
7220 *   dg_cell->set_dof_values (local_VM_stress_fe_values,
7221 *   VM_stress_field);
7222 *  
7223 *  
7224 *   }
7225 *  
7226 * @endcode
7227 *
7228 * Save stresses on nodes by nodal averaging
7229 * construct a DoFHandler object based on FE_Q with 1 degree of freedom
7230 * in order to compute stresses on nodes (by applying nodal averaging)
7231 * Therefore, each vertex has one degree of freedom
7232 *
7233 * @code
7234 *   FE_Q<dim> fe_1 (1);
7235 *   DoFHandler<dim> dof_handler_1 (triangulation);
7236 *   dof_handler_1.distribute_dofs (fe_1);
7237 *  
7238 *   AssertThrow(dof_handler_1.n_dofs() == triangulation.n_vertices(),
7239 *   ExcDimensionMismatch(dof_handler_1.n_dofs(),triangulation.n_vertices()));
7240 *  
7241 *   std::vector< std::vector< Vector<double> > >
7242 *   history_stress_on_vertices (dim, std::vector< Vector<double> >(dim));
7243 *   for (unsigned int i=0; i<dim; ++i)
7244 *   for (unsigned int j=0; j<dim; ++j)
7245 *   {
7246 *   history_stress_on_vertices[i][j].reinit(dof_handler_1.n_dofs());
7247 *   }
7248 *  
7249 *   Vector<double> VM_stress_on_vertices (dof_handler_1.n_dofs()),
7250 *   counter_on_vertices (dof_handler_1.n_dofs());
7251 *   VM_stress_on_vertices = 0;
7252 *   counter_on_vertices = 0;
7253 *  
7254 *   cell = dof_handler.begin_active();
7255 *   dg_cell = history_dof_handler.begin_active();
7256 *   typename DoFHandler<dim>::active_cell_iterator
7257 *   cell_1 = dof_handler_1.begin_active();
7258 *   for (; cell!=endc; ++cell, ++dg_cell, ++cell_1)
7259 *   if (cell->is_locally_owned())
7260 *   {
7261 *   dg_cell->get_dof_values (VM_stress_field,
7262 *   local_VM_stress_fe_values);
7263 *  
7264 *   for (unsigned int i=0; i<dim; ++i)
7265 *   for (unsigned int j=0; j<dim; ++j)
7266 *   {
7267 *   dg_cell->get_dof_values (history_stress_field[i][j],
7268 *   local_history_stress_fe_values[i][j]);
7269 *   }
7270 *  
7271 *   for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
7272 *   {
7273 *   types::global_dof_index dof_1_vertex = cell_1->vertex_dof_index(v, 0);
7274 *  
7275 * @endcode
7276 *
7277 * begin check
7278 * Point<dim> point1, point2;
7279 * point1 = cell_1->vertex(v);
7280 * point2 = dg_cell->vertex(v);
7281 * AssertThrow(point1.distance(point2) < cell->diameter()*1e-8, ExcInternalError());
7282 * end check
7283 *
7284
7285 *
7286 *
7287 * @code
7288 *   counter_on_vertices (dof_1_vertex) += 1;
7289 *  
7290 *   VM_stress_on_vertices (dof_1_vertex) += local_VM_stress_fe_values (v);
7291 *  
7292 *   for (unsigned int i=0; i<dim; ++i)
7293 *   for (unsigned int j=0; j<dim; ++j)
7294 *   {
7295 *   history_stress_on_vertices[i][j](dof_1_vertex) +=
7296 *   local_history_stress_fe_values[i][j](v);
7297 *   }
7298 *  
7299 *   }
7300 *   }
7301 *  
7302 *   for (unsigned int id=0; id<dof_handler_1.n_dofs(); ++id)
7303 *   {
7304 *   VM_stress_on_vertices(id) /= counter_on_vertices(id);
7305 *  
7306 *   for (unsigned int i=0; i<dim; ++i)
7307 *   for (unsigned int j=0; j<dim; ++j)
7308 *   {
7309 *   history_stress_on_vertices[i][j](id) /= counter_on_vertices(id);
7310 *   }
7311 *   }
7312 *  
7313 * @endcode
7314 *
7315 * Save figures of stresses
7316 *
7317 * @code
7318 *   if (show_stresses)
7319 *   {
7320 *   {
7321 *   DataOut<dim> data_out;
7322 *   data_out.attach_dof_handler (history_dof_handler);
7323 *  
7324 *  
7325 *   data_out.add_data_vector (history_stress_field[0][0], "stress_xx");
7326 *   data_out.add_data_vector (history_stress_field[1][1], "stress_yy");
7327 *   data_out.add_data_vector (history_stress_field[0][1], "stress_xy");
7328 *   data_out.add_data_vector (VM_stress_field, "Von_Mises_stress");
7329 *  
7330 *   if (dim == 3)
7331 *   {
7332 *   data_out.add_data_vector (history_stress_field[0][2], "stress_xz");
7333 *   data_out.add_data_vector (history_stress_field[1][2], "stress_yz");
7334 *   data_out.add_data_vector (history_stress_field[2][2], "stress_zz");
7335 *   }
7336 *  
7337 *   data_out.build_patches ();
7338 *  
7339 *   const std::string filename_base_stress = ("stress-" + filename_base);
7340 *  
7341 *   const std::string filename =
7342 *   (output_dir + filename_base_stress + "-"
7343 *   + Utilities::int_to_string(triangulation.locally_owned_subdomain(), 4));
7344 *  
7345 *   std::ofstream output_vtu((filename + ".vtu").c_str());
7346 *   data_out.write_vtu(output_vtu);
7347 *   pcout << output_dir + filename_base_stress << ".pvtu" << std::endl;
7348 *  
7349 *   if (this_mpi_process == 0)
7350 *   {
7351 *   std::vector<std::string> filenames;
7352 *   for (unsigned int i = 0; i < n_mpi_processes; ++i)
7353 *   filenames.push_back(filename_base_stress + "-" +
7354 *   Utilities::int_to_string(i, 4) +
7355 *   ".vtu");
7356 *  
7357 *   std::ofstream pvtu_master_output((output_dir + filename_base_stress + ".pvtu").c_str());
7358 *   data_out.write_pvtu_record(pvtu_master_output, filenames);
7359 *  
7360 *   std::ofstream visit_master_output((output_dir + filename_base_stress + ".visit").c_str());
7361 *   data_out.write_pvtu_record(visit_master_output, filenames);
7362 *   }
7363 *  
7364 *  
7365 *   }
7366 *  
7367 *   {
7368 *   DataOut<dim> data_out;
7369 *   data_out.attach_dof_handler (dof_handler_1);
7370 *  
7371 *  
7372 *   data_out.add_data_vector (history_stress_on_vertices[0][0], "stress_xx_averaged");
7373 *   data_out.add_data_vector (history_stress_on_vertices[1][1], "stress_yy_averaged");
7374 *   data_out.add_data_vector (history_stress_on_vertices[0][1], "stress_xy_averaged");
7375 *   data_out.add_data_vector (VM_stress_on_vertices, "Von_Mises_stress_averaged");
7376 *  
7377 *   if (dim == 3)
7378 *   {
7379 *   data_out.add_data_vector (history_stress_on_vertices[0][2], "stress_xz_averaged");
7380 *   data_out.add_data_vector (history_stress_on_vertices[1][2], "stress_yz_averaged");
7381 *   data_out.add_data_vector (history_stress_on_vertices[2][2], "stress_zz_averaged");
7382 *   }
7383 *  
7384 *   data_out.build_patches ();
7385 *  
7386 *   const std::string filename_base_stress = ("averaged-stress-" + filename_base);
7387 *  
7388 *   const std::string filename =
7389 *   (output_dir + filename_base_stress + "-"
7390 *   + Utilities::int_to_string(triangulation.locally_owned_subdomain(), 4));
7391 *  
7392 *   std::ofstream output_vtu((filename + ".vtu").c_str());
7393 *   data_out.write_vtu(output_vtu);
7394 *   pcout << output_dir + filename_base_stress << ".pvtu" << std::endl;
7395 *  
7396 *   if (this_mpi_process == 0)
7397 *   {
7398 *   std::vector<std::string> filenames;
7399 *   for (unsigned int i = 0; i < n_mpi_processes; ++i)
7400 *   filenames.push_back(filename_base_stress + "-" +
7401 *   Utilities::int_to_string(i, 4) +
7402 *   ".vtu");
7403 *  
7404 *   std::ofstream pvtu_master_output((output_dir + filename_base_stress + ".pvtu").c_str());
7405 *   data_out.write_pvtu_record(pvtu_master_output, filenames);
7406 *  
7407 *   std::ofstream visit_master_output((output_dir + filename_base_stress + ".visit").c_str());
7408 *   data_out.write_pvtu_record(visit_master_output, filenames);
7409 *   }
7410 *  
7411 *  
7412 *   }
7413 * @endcode
7414 *
7415 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7416 *
7417
7418 *
7419 *
7420 * @code
7421 *   }
7422 *  
7423 *   magnified_solution *= -1;
7424 *   move_mesh(magnified_solution);
7425 *  
7426 * @endcode
7427 *
7428 * Timoshenko beam
7429 *
7430 * @code
7431 *   if (base_mesh == "Timoshenko beam")
7432 *   {
7433 *   const double length = .48,
7434 *   depth = .12;
7435 *  
7436 *   Point<dim> intersted_point(length, -depth/2);
7437 *   Point<dim> vertex_displacement;
7438 *   bool vertex_found = false;
7439 *  
7440 *   for (typename DoFHandler<dim>::active_cell_iterator cell =
7441 *   dof_handler.begin_active();
7442 *   cell != dof_handler.end(); ++cell)
7443 *   if (cell->is_locally_owned() && !vertex_found)
7444 *   for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
7445 *   if ( std::fabs(cell->vertex(v)[0] - intersted_point[0])<1e-6 &&
7446 *   std::fabs(cell->vertex(v)[1] - intersted_point[1])<1e-6)
7447 *   {
7448 *   vertex_found = true;
7449 *  
7450 *   for (unsigned int d = 0; d < dim; ++d)
7451 *   vertex_displacement[d] = solution(cell->vertex_dof_index(v, d));
7452 *  
7453 *   break;
7454 *   }
7455 *  
7456 *   pcout << " Number of active cells: "
7457 *   << triangulation.n_global_active_cells() << std::endl
7458 *   << " Number of degrees of freedom: " << dof_handler.n_dofs()
7459 *   << std::endl;
7460 *  
7461 *   AssertThrow(vertex_found, ExcInternalError());
7462 *   std::cout << "Displacement at the point (" << intersted_point[0]
7463 *   << ", " << intersted_point[1] << ") is "
7464 *   << "(" << vertex_displacement[0]
7465 *   << ", " << vertex_displacement[1] << ").\n";
7466 *  
7467 *   Vector<double> vertex_exact_displacement(dim);
7468 *   EquationData::IncrementalBoundaryValues<dim> incremental_boundary_values(present_time, end_time);
7469 *   incremental_boundary_values.vector_value (intersted_point, vertex_exact_displacement);
7470 *  
7471 *   std::cout << "Exact displacement at the point (" << intersted_point[0]
7472 *   << ", " << intersted_point[1] << ") is "
7473 *   << "(" << vertex_exact_displacement[0]
7474 *   << ", " << vertex_exact_displacement[1] << ").\n\n";
7475 *  
7476 *   }
7477 *   else if (base_mesh == "Thick_tube_internal_pressure")
7478 *   {
7479 *   const double pressure (0.6*2.4e8),
7480 *   inner_radius (.1);
7481 * @endcode
7482 *
7483 * const double pressure (1.94e8),
7484 * inner_radius (.1);
7485 *
7486
7487 *
7488 *
7489
7490 *
7491 * Plane stress
7492 * const double mu (((e_modulus*(1+2*nu)) / (std::pow((1+nu),2))) / (2 * (1 + (nu / (1+nu)))));
7493 * 3d and plane strain
7494 *
7495 * @code
7496 *   const double mu (e_modulus / (2 * (1 + nu)));
7497 *  
7498 *   const Point<dim> point_A(inner_radius, 0.);
7499 *   Vector<double> disp_A(dim);
7500 *  
7501 * @endcode
7502 *
7503 * make a non-parallel copy of solution
7504 *
7505 * @code
7506 *   Vector<double> copy_solution(solution);
7507 *  
7508 *   Evaluation::PointValuesEvaluation<dim> point_values_evaluation(point_A);
7509 *  
7510 *   point_values_evaluation.compute (dof_handler, copy_solution, disp_A);
7511 *  
7512 *   table_results.add_value("time step", timestep_no);
7513 *   table_results.add_value("Cells", triangulation.n_global_active_cells());
7514 *   table_results.add_value("DoFs", dof_handler.n_dofs());
7515 *   table_results.add_value("pressure/sigma_0", (pressure*present_time/end_time)/sigma_0);
7516 *   table_results.add_value("4*mu*u_A/(sigma_0*a)", 4*mu*disp_A(0)/(sigma_0*inner_radius));
7517 *  
7518 * @endcode
7519 *
7520 * Compute stresses in the POLAR coordinates, 1- save it on Gauss points,
7521 * 2- extrapolate them to nodes and taking their avarages (nodal avaraging)
7522 *
7523 * @code
7524 *   AssertThrow (dim == 2, ExcNotImplemented());
7525 *  
7526 * @endcode
7527 *
7528 * we define a rotation matrix to be able to transform the stress
7529 * from the Cartesian coordinate to the polar coordinate
7530 *
7531 * @code
7532 *   Tensor<2, dim> rotation_matrix; // [cos sin; -sin cos] , sigma_r = rot * sigma * rot^T
7533 *  
7534 *   FEValues<dim> fe_values (fe, quadrature_formula, update_quadrature_points |
7535 *   update_values | update_gradients);
7536 *  
7537 *   const unsigned int n_q_points = quadrature_formula.size();
7538 *  
7539 *   std::vector<SymmetricTensor<2, dim> > strain_tensor(n_q_points);
7540 *   SymmetricTensor<4, dim> stress_strain_tensor;
7541 *   Tensor<2, dim> stress_at_qpoint;
7542 *  
7543 *   FE_DGQ<dim> history_fe (1);
7544 *   DoFHandler<dim> history_dof_handler (triangulation);
7545 *   history_dof_handler.distribute_dofs (history_fe);
7546 *   std::vector< std::vector< Vector<double> > >
7547 *   history_stress_field (dim, std::vector< Vector<double> >(dim)),
7548 *   local_history_stress_values_at_qpoints (dim, std::vector< Vector<double> >(dim)),
7549 *   local_history_stress_fe_values (dim, std::vector< Vector<double> >(dim));
7550 *   for (unsigned int i=0; i<dim; ++i)
7551 *   for (unsigned int j=0; j<dim; ++j)
7552 *   {
7553 *   history_stress_field[i][j].reinit(history_dof_handler.n_dofs());
7554 *   local_history_stress_values_at_qpoints[i][j].reinit(quadrature_formula.size());
7555 *   local_history_stress_fe_values[i][j].reinit(history_fe.dofs_per_cell);
7556 *   }
7557 *  
7558 *   FullMatrix<double> qpoint_to_dof_matrix (history_fe.dofs_per_cell,
7559 *   quadrature_formula.size());
7560 *   FETools::compute_projection_from_quadrature_points_matrix
7561 *   (history_fe,
7562 *   quadrature_formula, quadrature_formula,
7563 *   qpoint_to_dof_matrix);
7564 *  
7565 *   typename DoFHandler<dim>::active_cell_iterator
7566 *   cell = dof_handler.begin_active(),
7567 *   endc = dof_handler.end(),
7568 *   dg_cell = history_dof_handler.begin_active();
7569 *  
7570 *   const FEValuesExtractors::Vector displacement(0);
7571 *  
7572 *   for (; cell!=endc; ++cell, ++dg_cell)
7573 *   if (cell->is_locally_owned())
7574 *   {
7575 *   PointHistory<dim> *local_quadrature_points_history
7576 *   = reinterpret_cast<PointHistory<dim> *>(cell->user_pointer());
7577 *   Assert (local_quadrature_points_history >=
7578 *   &quadrature_point_history.front(),
7579 *   ExcInternalError());
7580 *   Assert (local_quadrature_points_history <
7581 *   &quadrature_point_history.back(),
7582 *   ExcInternalError());
7583 *  
7584 * @endcode
7585 *
7586 * Then loop over the quadrature points of this cell:
7587 *
7588 * @code
7589 *   for (unsigned int q=0; q<quadrature_formula.size(); ++q)
7590 *   {
7591 *   stress_at_qpoint = local_quadrature_points_history[q].old_stress;
7592 *  
7593 * @endcode
7594 *
7595 * transform the stress from the Cartesian coordinate to the polar coordinate
7596 *
7597 * @code
7598 *   const Point<dim> point = local_quadrature_points_history[q].point;
7599 *   const double theta = std::atan2(point(1),point(0));
7600 *  
7601 * @endcode
7602 *
7603 * rotation matrix
7604 *
7605 * @code
7606 *   rotation_matrix[0][0] = std::cos(theta);
7607 *   rotation_matrix[0][1] = std::sin(theta);
7608 *   rotation_matrix[1][0] = -std::sin(theta);
7609 *   rotation_matrix[1][1] = std::cos(theta);
7610 *  
7611 * @endcode
7612 *
7613 * stress in polar coordinate
7614 *
7615 * @code
7616 *   stress_at_qpoint = rotation_matrix * stress_at_qpoint * transpose(rotation_matrix);
7617 *  
7618 *   for (unsigned int i=0; i<dim; ++i)
7619 *   for (unsigned int j=i; j<dim; ++j)
7620 *   {
7621 *   local_history_stress_values_at_qpoints[i][j](q) = stress_at_qpoint[i][j];
7622 *   }
7623 *  
7624 *   }
7625 *  
7626 *  
7627 *   for (unsigned int i=0; i<dim; ++i)
7628 *   for (unsigned int j=i; j<dim; ++j)
7629 *   {
7630 *   qpoint_to_dof_matrix.vmult (local_history_stress_fe_values[i][j],
7631 *   local_history_stress_values_at_qpoints[i][j]);
7632 *   dg_cell->set_dof_values (local_history_stress_fe_values[i][j],
7633 *   history_stress_field[i][j]);
7634 *   }
7635 *  
7636 *   }
7637 *  
7638 *   {
7639 *   DataOut<dim> data_out;
7640 *   data_out.attach_dof_handler (history_dof_handler);
7641 *  
7642 *  
7643 *   data_out.add_data_vector (history_stress_field[0][0], "stress_rr");
7644 *   data_out.add_data_vector (history_stress_field[1][1], "stress_tt");
7645 *   data_out.add_data_vector (history_stress_field[0][1], "stress_rt");
7646 *  
7647 *   data_out.build_patches ();
7648 *  
7649 *   const std::string filename_base_stress = ("stress-polar-" + filename_base);
7650 *  
7651 *   const std::string filename =
7652 *   (output_dir + filename_base_stress + "-"
7653 *   + Utilities::int_to_string(triangulation.locally_owned_subdomain(), 4));
7654 *  
7655 *   std::ofstream output_vtu((filename + ".vtu").c_str());
7656 *   data_out.write_vtu(output_vtu);
7657 *   pcout << output_dir + filename_base_stress << ".pvtu" << std::endl;
7658 *  
7659 *   if (this_mpi_process == 0)
7660 *   {
7661 *   std::vector<std::string> filenames;
7662 *   for (unsigned int i = 0; i < n_mpi_processes; ++i)
7663 *   filenames.push_back(filename_base_stress + "-" +
7664 *   Utilities::int_to_string(i, 4) +
7665 *   ".vtu");
7666 *  
7667 *   std::ofstream pvtu_master_output((output_dir + filename_base_stress + ".pvtu").c_str());
7668 *   data_out.write_pvtu_record(pvtu_master_output, filenames);
7669 *  
7670 *   std::ofstream visit_master_output((output_dir + filename_base_stress + ".visit").c_str());
7671 *   data_out.write_pvtu_record(visit_master_output, filenames);
7672 *   }
7673 *  
7674 *  
7675 *   }
7676 *  
7677 * @endcode
7678 *
7679 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7680 * construct a DoFHandler object based on FE_Q with 1 degree of freedom
7681 * in order to compute stresses on nodes (by applying nodal averaging)
7682 * Therefore, each vertex has one degree of freedom
7683 *
7684 * @code
7685 *   FE_Q<dim> fe_1 (1);
7686 *   DoFHandler<dim> dof_handler_1 (triangulation);
7687 *   dof_handler_1.distribute_dofs (fe_1);
7688 *  
7689 *   AssertThrow(dof_handler_1.n_dofs() == triangulation.n_vertices(),
7690 *   ExcDimensionMismatch(dof_handler_1.n_dofs(),triangulation.n_vertices()));
7691 *  
7692 *   std::vector< std::vector< Vector<double> > >
7693 *   history_stress_on_vertices (dim, std::vector< Vector<double> >(dim));
7694 *   for (unsigned int i=0; i<dim; ++i)
7695 *   for (unsigned int j=0; j<dim; ++j)
7696 *   {
7697 *   history_stress_on_vertices[i][j].reinit(dof_handler_1.n_dofs());
7698 *   }
7699 *  
7700 *   Vector<double> counter_on_vertices (dof_handler_1.n_dofs());
7701 *   counter_on_vertices = 0;
7702 *  
7703 *   cell = dof_handler.begin_active();
7704 *   dg_cell = history_dof_handler.begin_active();
7705 *   typename DoFHandler<dim>::active_cell_iterator
7706 *   cell_1 = dof_handler_1.begin_active();
7707 *   for (; cell!=endc; ++cell, ++dg_cell, ++cell_1)
7708 *   if (cell->is_locally_owned())
7709 *   {
7710 *  
7711 *   for (unsigned int i=0; i<dim; ++i)
7712 *   for (unsigned int j=0; j<dim; ++j)
7713 *   {
7714 *   dg_cell->get_dof_values (history_stress_field[i][j],
7715 *   local_history_stress_fe_values[i][j]);
7716 *   }
7717 *  
7718 *   for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
7719 *   {
7720 *   types::global_dof_index dof_1_vertex = cell_1->vertex_dof_index(v, 0);
7721 *  
7722 * @endcode
7723 *
7724 * begin check
7725 * Point<dim> point1, point2;
7726 * point1 = cell_1->vertex(v);
7727 * point2 = dg_cell->vertex(v);
7728 * AssertThrow(point1.distance(point2) < cell->diameter()*1e-8, ExcInternalError());
7729 * end check
7730 *
7731
7732 *
7733 *
7734 * @code
7735 *   counter_on_vertices (dof_1_vertex) += 1;
7736 *  
7737 *   for (unsigned int i=0; i<dim; ++i)
7738 *   for (unsigned int j=0; j<dim; ++j)
7739 *   {
7740 *   history_stress_on_vertices[i][j](dof_1_vertex) +=
7741 *   local_history_stress_fe_values[i][j](v);
7742 *   }
7743 *  
7744 *   }
7745 *   }
7746 *  
7747 *   for (unsigned int id=0; id<dof_handler_1.n_dofs(); ++id)
7748 *   {
7749 *   for (unsigned int i=0; i<dim; ++i)
7750 *   for (unsigned int j=0; j<dim; ++j)
7751 *   {
7752 *   history_stress_on_vertices[i][j](id) /= counter_on_vertices(id);
7753 *   }
7754 *   }
7755 *  
7756 *  
7757 *   {
7758 *   DataOut<dim> data_out;
7759 *   data_out.attach_dof_handler (dof_handler_1);
7760 *  
7761 *  
7762 *   data_out.add_data_vector (history_stress_on_vertices[0][0], "stress_rr_averaged");
7763 *   data_out.add_data_vector (history_stress_on_vertices[1][1], "stress_tt_averaged");
7764 *   data_out.add_data_vector (history_stress_on_vertices[0][1], "stress_rt_averaged");
7765 *  
7766 *   data_out.build_patches ();
7767 *  
7768 *   const std::string filename_base_stress = ("averaged-stress-polar-" + filename_base);
7769 *  
7770 *   const std::string filename =
7771 *   (output_dir + filename_base_stress + "-"
7772 *   + Utilities::int_to_string(triangulation.locally_owned_subdomain(), 4));
7773 *  
7774 *   std::ofstream output_vtu((filename + ".vtu").c_str());
7775 *   data_out.write_vtu(output_vtu);
7776 *   pcout << output_dir + filename_base_stress << ".pvtu" << std::endl;
7777 *  
7778 *   if (this_mpi_process == 0)
7779 *   {
7780 *   std::vector<std::string> filenames;
7781 *   for (unsigned int i = 0; i < n_mpi_processes; ++i)
7782 *   filenames.push_back(filename_base_stress + "-" +
7783 *   Utilities::int_to_string(i, 4) +
7784 *   ".vtu");
7785 *  
7786 *   std::ofstream pvtu_master_output((output_dir + filename_base_stress + ".pvtu").c_str());
7787 *   data_out.write_pvtu_record(pvtu_master_output, filenames);
7788 *  
7789 *   std::ofstream visit_master_output((output_dir + filename_base_stress + ".visit").c_str());
7790 *   data_out.write_pvtu_record(visit_master_output, filenames);
7791 *   }
7792 *  
7793 *  
7794 *   }
7795 * @endcode
7796 *
7797 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7798 *
7799
7800 *
7801 *
7802 * @code
7803 *   if ( std::abs( (present_time/end_time)*(pressure/sigma_0) - 0.6 ) <
7804 *   .501*(present_timestep/end_time)*(pressure/sigma_0) )
7805 *   {
7806 *  
7807 * @endcode
7808 *
7809 * table_results_2: presenting the stress_rr and stress_tt on the nodes of bottom edge
7810 *
7811 * @code
7812 *   const unsigned int face_id = 3;
7813 *  
7814 *   std::vector<bool> vertices_found (dof_handler_1.n_dofs(), false);
7815 *  
7816 *   bool evaluation_face_found = false;
7817 *  
7818 *   typename DoFHandler<dim>::active_cell_iterator
7819 *   cell = dof_handler.begin_active(),
7820 *   endc = dof_handler.end(),
7821 *   cell_1 = dof_handler_1.begin_active();
7822 *   for (; cell!=endc; ++cell, ++cell_1)
7823 *   if (cell->is_locally_owned())
7824 *   {
7825 *   for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
7826 *   {
7827 *   if (cell->face(face)->at_boundary()
7828 *   &&
7829 *   cell->face(face)->boundary_id() == face_id)
7830 *   {
7831 *   if (!evaluation_face_found)
7832 *   {
7833 *   evaluation_face_found = true;
7834 *   }
7835 *  
7836 *  
7837 *   for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_face; ++v)
7838 *   {
7839 *   types::global_dof_index dof_1_vertex =
7840 *   cell_1->face(face)->vertex_dof_index(v, 0);
7841 *   if (!vertices_found[dof_1_vertex])
7842 *   {
7843 *  
7844 *   const Point<dim> vertex_coordinate = cell_1->face(face)->vertex(v);
7845 *  
7846 *   table_results_2.add_value("x coordinate", vertex_coordinate[0]);
7847 *   table_results_2.add_value("stress_rr", history_stress_on_vertices[0][0](dof_1_vertex));
7848 *   table_results_2.add_value("stress_tt", history_stress_on_vertices[1][1](dof_1_vertex));
7849 *   table_results_2.add_value("pressure/sigma_0", (pressure*present_time/end_time)/sigma_0);
7850 *  
7851 *   vertices_found[dof_1_vertex] = true;
7852 *   }
7853 *   }
7854 *  
7855 *   }
7856 *   }
7857 *  
7858 *   }
7859 *  
7860 *   AssertThrow(evaluation_face_found, ExcInternalError());
7861 *  
7862 * @endcode
7863 *
7864 * table_results_3: presenting the mean stress_rr of the nodes on the inner radius
7865 *
7866 * @code
7867 *   const unsigned int face_id_2 = 0;
7868 *  
7869 *   Tensor<2, dim> stress_node,
7870 *   mean_stress_polar;
7871 *   mean_stress_polar = 0;
7872 *  
7873 *   std::vector<bool> vertices_found_2 (dof_handler_1.n_dofs(), false);
7874 *   unsigned int no_vertices_found = 0;
7875 *  
7876 *   evaluation_face_found = false;
7877 *  
7878 *   cell = dof_handler.begin_active(),
7879 *   endc = dof_handler.end(),
7880 *   cell_1 = dof_handler_1.begin_active();
7881 *   for (; cell!=endc; ++cell, ++cell_1)
7882 *   if (cell->is_locally_owned())
7883 *   {
7884 *   for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
7885 *   {
7886 *   if (cell->face(face)->at_boundary()
7887 *   &&
7888 *   cell->face(face)->boundary_id() == face_id_2)
7889 *   {
7890 *   if (!evaluation_face_found)
7891 *   {
7892 *   evaluation_face_found = true;
7893 *   }
7894 *  
7895 *  
7896 *   for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_face; ++v)
7897 *   {
7898 *   types::global_dof_index dof_1_vertex =
7899 *   cell_1->face(face)->vertex_dof_index(v, 0);
7900 *   if (!vertices_found_2[dof_1_vertex])
7901 *   {
7902 *   for (unsigned int ir=0; ir<dim; ++ir)
7903 *   for (unsigned int ic=0; ic<dim; ++ic)
7904 *   stress_node[ir][ic] = history_stress_on_vertices[ir][ic](dof_1_vertex);
7905 *  
7906 *   mean_stress_polar += stress_node;
7907 *  
7908 *   vertices_found_2[dof_1_vertex] = true;
7909 *   ++no_vertices_found;
7910 *   }
7911 *   }
7912 *  
7913 *   }
7914 *   }
7915 *  
7916 *   }
7917 *  
7918 *   AssertThrow(evaluation_face_found, ExcInternalError());
7919 *  
7920 *   mean_stress_polar /= no_vertices_found;
7921 *  
7922 *   table_results_3.add_value("time step", timestep_no);
7923 *   table_results_3.add_value("pressure/sigma_0", (pressure*present_time/end_time)/sigma_0);
7924 *   table_results_3.add_value("Cells", triangulation.n_global_active_cells());
7925 *   table_results_3.add_value("DoFs", dof_handler.n_dofs());
7926 *   table_results_3.add_value("radius", inner_radius);
7927 *   table_results_3.add_value("mean stress_rr", mean_stress_polar[0][0]);
7928 *   table_results_3.add_value("mean stress_tt", mean_stress_polar[1][1]);
7929 *  
7930 *  
7931 *   }
7932 *  
7933 *  
7934 *   }
7935 *   else if (base_mesh == "Perforated_strip_tension")
7936 *   {
7937 *   const double imposed_displacement (0.00055),
7938 *   inner_radius (0.05);
7939 *  
7940 * @endcode
7941 *
7942 * Plane stress
7943 * const double mu (((e_modulus*(1+2*nu)) / (std::pow((1+nu),2))) / (2 * (1 + (nu / (1+nu)))));
7944 * 3d and plane strain
7945 *
7946
7947 *
7948 * table_results: Demonstrates the result of displacement at the top left corner versus imposed tension
7949 *
7950 * @code
7951 *   /*
7952 *   {
7953 *   const Point<dim> point_C(0., height);
7954 *   Vector<double> disp_C(dim);
7955 *  
7956 * @endcode
7957 *
7958 * make a non-parallel copy of solution
7959 *
7960 * @code
7961 *   Vector<double> copy_solution(solution);
7962 *  
7963 *   typename Evaluation::PointValuesEvaluation<dim>::
7964 *   PointValuesEvaluation point_values_evaluation(point_C);
7965 *  
7966 *   point_values_evaluation.compute (dof_handler, copy_solution, disp_C);
7967 *  
7968 *   table_results.add_value("time step", timestep_no);
7969 *   table_results.add_value("Cells", triangulation.n_global_active_cells());
7970 *   table_results.add_value("DoFs", dof_handler.n_dofs());
7971 *   table_results.add_value("4*mu*u_C/(sigma_0*r)", 4*mu*disp_C(1)/(sigma_0*inner_radius));
7972 *   }
7973 *   */
7974 *  
7975 * @endcode
7976 *
7977 * compute average sigma_yy on the bottom edge
7978 *
7979 * @code
7980 *   double stress_yy_av;
7981 *   {
7982 *   stress_yy_av = 0;
7983 *   const unsigned int face_id = 1;
7984 *  
7985 *   std::vector<bool> vertices_found (dof_handler_1.n_dofs(), false);
7986 *   unsigned int no_vertices_in_face = 0;
7987 *  
7988 *   bool evaluation_face_found = false;
7989 *  
7990 *   typename DoFHandler<dim>::active_cell_iterator
7991 *   cell = dof_handler.begin_active(),
7992 *   endc = dof_handler.end(),
7993 *   cell_1 = dof_handler_1.begin_active();
7994 *   for (; cell!=endc; ++cell, ++cell_1)
7995 *   if (cell->is_locally_owned())
7996 *   {
7997 *   for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
7998 *   {
7999 *   if (cell->face(face)->at_boundary()
8000 *   &&
8001 *   cell->face(face)->boundary_id() == face_id)
8002 *   {
8003 *   if (!evaluation_face_found)
8004 *   {
8005 *   evaluation_face_found = true;
8006 *   }
8007 *  
8008 *  
8009 *   for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_face; ++v)
8010 *   {
8011 *   types::global_dof_index dof_1_vertex =
8012 *   cell_1->face(face)->vertex_dof_index(v, 0);
8013 *   if (!vertices_found[dof_1_vertex])
8014 *   {
8015 *   stress_yy_av += history_stress_on_vertices[1][1](dof_1_vertex);
8016 *   ++no_vertices_in_face;
8017 *  
8018 *   vertices_found[dof_1_vertex] = true;
8019 *   }
8020 *   }
8021 *  
8022 *   }
8023 *   }
8024 *  
8025 *   }
8026 *  
8027 *   AssertThrow(evaluation_face_found, ExcInternalError());
8028 *  
8029 *   stress_yy_av /= no_vertices_in_face;
8030 *  
8031 *   }
8032 *  
8033 * @endcode
8034 *
8035 * table_results_2: Demonstrate the stress_yy on the nodes of bottom edge
8036 *
8037
8038 *
8039 * if ( std::abs( (stress_yy_av/sigma_0) - .91 ) < .2 )
8040 *
8041 * @code
8042 *   if ( (timestep_no) % 19 == 0 )
8043 * @endcode
8044 *
8045 * if ( true )
8046 *
8047 * @code
8048 *   {
8049 *   const unsigned int face_id = 1;
8050 *  
8051 *   std::vector<bool> vertices_found (dof_handler_1.n_dofs(), false);
8052 *  
8053 *   bool evaluation_face_found = false;
8054 *  
8055 *   typename DoFHandler<dim>::active_cell_iterator
8056 *   cell = dof_handler.begin_active(),
8057 *   endc = dof_handler.end(),
8058 *   cell_1 = dof_handler_1.begin_active();
8059 *   for (; cell!=endc; ++cell, ++cell_1)
8060 *   if (cell->is_locally_owned())
8061 *   {
8062 *   for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
8063 *   {
8064 *   if (cell->face(face)->at_boundary()
8065 *   &&
8066 *   cell->face(face)->boundary_id() == face_id)
8067 *   {
8068 *   if (!evaluation_face_found)
8069 *   {
8070 *   evaluation_face_found = true;
8071 *   }
8072 *  
8073 *  
8074 *   for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_face; ++v)
8075 *   {
8076 *   types::global_dof_index dof_1_vertex =
8077 *   cell_1->face(face)->vertex_dof_index(v, 0);
8078 *  
8079 *   const Point<dim> vertex_coordinate = cell_1->face(face)->vertex(v);
8080 *  
8081 *   if (!vertices_found[dof_1_vertex] && std::abs(vertex_coordinate[2])<1.e-8)
8082 *   {
8083 *   table_results_2.add_value("x", vertex_coordinate[0]);
8084 *   table_results_2.add_value("x/r", vertex_coordinate[0]/inner_radius);
8085 *   table_results_2.add_value("stress_xx/sigma_0", history_stress_on_vertices[0][0](dof_1_vertex)/sigma_0);
8086 *   table_results_2.add_value("stress_yy/sigma_0", history_stress_on_vertices[1][1](dof_1_vertex)/sigma_0);
8087 *   table_results_2.add_value("stress_yy_av/sigma_0", stress_yy_av/sigma_0);
8088 *   table_results_2.add_value("Imposed u_y", (imposed_displacement*present_time/end_time));
8089 *  
8090 *   vertices_found[dof_1_vertex] = true;
8091 *   }
8092 *   }
8093 *  
8094 *   }
8095 *   }
8096 *  
8097 *   }
8098 *  
8099 *   AssertThrow(evaluation_face_found, ExcInternalError());
8100 *  
8101 *   }
8102 *  
8103 * @endcode
8104 *
8105 * table_results_3: Demonstrate the Stress_mean (average tensile stress)
8106 * on the bottom edge versus epsilon_yy on the bottom left corner
8107 *
8108 * @code
8109 *   {
8110 *   double strain_yy_A = 0.;
8111 *  
8112 * @endcode
8113 *
8114 * compute strain_yy_A
8115 * Since the point A is the node on the bottom left corner,
8116 * we need to work just with one element
8117 *
8118 * @code
8119 *   {
8120 *   const Point<dim> point_A(inner_radius, 0, 0);
8121 *  
8122 *   Vector<double> local_strain_yy_values_at_qpoints (quadrature_formula.size()),
8123 *   local_strain_yy_fe_values (history_fe.dofs_per_cell);
8124 *  
8125 *   SymmetricTensor<2, dim> strain_at_qpoint;
8126 *  
8127 *   typename DoFHandler<dim>::active_cell_iterator
8128 *   cell = dof_handler.begin_active(),
8129 *   endc = dof_handler.end(),
8130 *   dg_cell = history_dof_handler.begin_active();
8131 *  
8132 *   bool cell_found = false;
8133 *  
8134 *   for (; cell!=endc; ++cell, ++dg_cell)
8135 *   if (cell->is_locally_owned() && !cell_found)
8136 *   {
8137 *   for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
8138 *   if ( std::fabs(cell->vertex(v)[0] - point_A[0])<1e-6 &&
8139 *   std::fabs(cell->vertex(v)[1] - point_A[1])<1e-6 &&
8140 *   std::fabs(cell->vertex(v)[2] - point_A[2])<1e-6)
8141 *   {
8142 *   PointHistory<dim> *local_quadrature_points_history
8143 *   = reinterpret_cast<PointHistory<dim> *>(cell->user_pointer());
8144 *   Assert (local_quadrature_points_history >=
8145 *   &quadrature_point_history.front(),
8146 *   ExcInternalError());
8147 *   Assert (local_quadrature_points_history <
8148 *   &quadrature_point_history.back(),
8149 *   ExcInternalError());
8150 *  
8151 * @endcode
8152 *
8153 * Then loop over the quadrature points of this cell:
8154 *
8155 * @code
8156 *   for (unsigned int q=0; q<quadrature_formula.size(); ++q)
8157 *   {
8158 *   strain_at_qpoint = local_quadrature_points_history[q].old_strain;
8159 *  
8160 *   local_strain_yy_values_at_qpoints(q) = strain_at_qpoint[1][1];
8161 *   }
8162 *  
8163 *   qpoint_to_dof_matrix.vmult (local_strain_yy_fe_values,
8164 *   local_strain_yy_values_at_qpoints);
8165 *  
8166 *   strain_yy_A = local_strain_yy_fe_values (v);
8167 *  
8168 *   cell_found = true;
8169 *   break;
8170 *   }
8171 *  
8172 *   }
8173 *  
8174 *   }
8175 *  
8176 *   table_results_3.add_value("time step", timestep_no);
8177 *   table_results_3.add_value("Cells", triangulation.n_global_active_cells());
8178 *   table_results_3.add_value("DoFs", dof_handler.n_dofs());
8179 *   table_results_3.add_value("Imposed u_y", (imposed_displacement*present_time/end_time));
8180 *   table_results_3.add_value("mean_tensile_stress/sigma_0", stress_yy_av/sigma_0);
8181 *   table_results_3.add_value("E*strain_yy-A/sigma_0", e_modulus*strain_yy_A/sigma_0);
8182 *  
8183 *   }
8184 *  
8185 *  
8186 *   if (std::abs(present_time-end_time) < 1.e-7)
8187 *   {
8188 *   table_results_2.set_precision("Imposed u_y", 6);
8189 *   table_results_3.set_precision("Imposed u_y", 6);
8190 *   }
8191 *  
8192 *   }
8193 *   else if (base_mesh == "Cantiliver_beam_3d")
8194 *   {
8195 *   const double pressure (6e6),
8196 *   length (.7),
8197 *   height (200e-3);
8198 *  
8199 * @endcode
8200 *
8201 * table_results: Demonstrates the result of displacement at the top front point, Point A
8202 *
8203 * @code
8204 *   {
8205 * @endcode
8206 *
8207 * Quantity of interest:
8208 * displacement at Point A (x=0, y=height/2, z=length)
8209 *
8210
8211 *
8212 *
8213 * @code
8214 *   const Point<dim> point_A(0, height/2, length);
8215 *   Vector<double> disp_A(dim);
8216 *  
8217 * @endcode
8218 *
8219 * make a non-parallel copy of solution
8220 *
8221 * @code
8222 *   Vector<double> copy_solution(solution);
8223 *  
8224 *   Evaluation::PointValuesEvaluation<dim> point_values_evaluation(point_A);
8225 *  
8226 *   point_values_evaluation.compute (dof_handler, copy_solution, disp_A);
8227 *  
8228 *   table_results.add_value("time step", timestep_no);
8229 *   table_results.add_value("Cells", triangulation.n_global_active_cells());
8230 *   table_results.add_value("DoFs", dof_handler.n_dofs());
8231 *   table_results.add_value("pressure", pressure*present_time/end_time);
8232 *   table_results.add_value("u_A", disp_A(1));
8233 *   }
8234 *  
8235 *   {
8236 * @endcode
8237 *
8238 * demonstrate the location and maximum von-Mises stress in the
8239 * specified domain close to the clamped face, z = 0
8240 * top domain: height/2 - thickness_flange <= y <= height/2
8241 * 0 <= z <= 2 * thickness_flange
8242 * bottom domain: -height/2 <= y <= -height/2 + thickness_flange
8243 * 0 <= z <= 2 * thickness_flange
8244 *
8245
8246 *
8247 *
8248 * @code
8249 *   double VM_stress_max (0);
8250 *   Point<dim> point_max;
8251 *  
8252 *   SymmetricTensor<2, dim> stress_at_qpoint;
8253 *  
8254 *   typename DoFHandler<dim>::active_cell_iterator
8255 *   cell = dof_handler.begin_active(),
8256 *   endc = dof_handler.end();
8257 *  
8258 *   const FEValuesExtractors::Vector displacement(0);
8259 *  
8260 *   for (; cell!=endc; ++cell)
8261 *   if (cell->is_locally_owned())
8262 *   {
8263 *   PointHistory<dim> *local_quadrature_points_history
8264 *   = reinterpret_cast<PointHistory<dim> *>(cell->user_pointer());
8265 *   Assert (local_quadrature_points_history >=
8266 *   &quadrature_point_history.front(),
8267 *   ExcInternalError());
8268 *   Assert (local_quadrature_points_history <
8269 *   &quadrature_point_history.back(),
8270 *   ExcInternalError());
8271 *  
8272 * @endcode
8273 *
8274 * Then loop over the quadrature points of this cell:
8275 *
8276 * @code
8277 *   for (unsigned int q=0; q<quadrature_formula.size(); ++q)
8278 *   {
8279 *   stress_at_qpoint = local_quadrature_points_history[q].old_stress;
8280 *  
8281 *   const double VM_stress = Evaluation::get_von_Mises_stress(stress_at_qpoint);
8282 *   if (VM_stress > VM_stress_max)
8283 *   {
8284 *   VM_stress_max = VM_stress;
8285 *   point_max = local_quadrature_points_history[q].point;
8286 *   }
8287 *  
8288 *   }
8289 *   }
8290 *  
8291 *   table_results.add_value("maximum von_Mises stress", VM_stress_max);
8292 *   table_results.add_value("x", point_max[0]);
8293 *   table_results.add_value("y", point_max[1]);
8294 *   table_results.add_value("z", point_max[2]);
8295 *  
8296 *   }
8297 *  
8298 *   }
8299 *  
8300 *  
8301 *   }
8302 *  
8303 *  
8304 * @endcode
8305 *
8306 *
8307 * <a name="elastoplastic.cc-PlasticityContactProblemrun"></a>
8308 * <h4>PlasticityContactProblem::run</h4>
8309 *
8310
8311 *
8312 * As in all other tutorial programs, the <code>run()</code> function contains
8313 * the overall logic. There is not very much to it here: in essence, it
8314 * performs the loops over all mesh refinement cycles, and within each, hands
8315 * things over to the Newton solver in <code>solve_newton()</code> on the
8316 * current mesh and calls the function that creates graphical output for
8317 * the so-computed solution. It then outputs some statistics concerning both
8318 * run times and memory consumption that has been collected over the course of
8319 * computations on this mesh.
8320 *
8321 * @code
8322 *   template <int dim>
8323 *   void
8324 *   ElastoPlasticProblem<dim>::run ()
8325 *   {
8326 *   computing_timer.reset();
8327 *  
8328 *   present_time = 0;
8329 *   present_timestep = 1;
8330 *   end_time = 10;
8331 *   timestep_no = 0;
8332 *  
8333 *   make_grid();
8334 *  
8335 * @endcode
8336 *
8337 * ----------------------------------------------------------------
8338 * base_mesh == "Thick_tube_internal_pressure"
8339 *
8340 * @code
8341 *   /*
8342 *   const Point<dim> center(0, 0);
8343 *   const double inner_radius = .1,
8344 *   outer_radius = .2;
8345 *  
8346 *   const SphericalManifold<dim> inner_boundary_description(center, inner_radius);
8347 *   triangulation.set_manifold (0, inner_boundary_description);
8348 *  
8349 *   const SphericalManifold<dim> outer_boundary_description(center, outer_radius);
8350 *   triangulation.set_manifold (1, outer_boundary_description);
8351 *   */
8352 * @endcode
8353 *
8354 * ----------------------------------------------------------------
8355 * base_mesh == "Perforated_strip_tension"
8356 *
8357 * @code
8358 *   /*
8359 *   const double inner_radius = 0.05;
8360 *  
8361 *   const CylinderBoundary<dim> inner_boundary_description(inner_radius, 2);
8362 *   triangulation.set_manifold (10, inner_boundary_description);
8363 *   */
8364 * @endcode
8365 *
8366 * ----------------------------------------------------------------
8367 *
8368
8369 *
8370 *
8371 * @code
8372 *   setup_quadrature_point_history ();
8373 *  
8374 *   while (present_time < end_time)
8375 *   {
8376 *   present_time += present_timestep;
8377 *   ++timestep_no;
8378 *  
8379 *   if (present_time > end_time)
8380 *   {
8381 *   present_timestep -= (present_time - end_time);
8382 *   present_time = end_time;
8383 *   }
8384 *   pcout << std::endl;
8385 *   pcout << "Time step " << timestep_no << " at time " << present_time
8386 *   << std::endl;
8387 *  
8388 *   relative_error = max_relative_error * 10;
8389 *   current_refinement_cycle = 0;
8390 *  
8391 *   setup_system();
8392 *  
8393 *  
8394 * @endcode
8395 *
8396 * ------------------------ Refinement based on the relative error -------------------------------
8397 *
8398
8399 *
8400 *
8401 * @code
8402 *   while (relative_error >= max_relative_error)
8403 *   {
8404 *   solve_newton();
8405 *   compute_error();
8406 *  
8407 *   if ( (timestep_no > 1) && (current_refinement_cycle>0) && (relative_error >= max_relative_error) )
8408 *   {
8409 *   pcout << "The relative error, " << relative_error
8410 *   << " , is still more than maximum relative error, "
8411 *   << max_relative_error << ", but we move to the next increment.\n";
8412 *   relative_error = .1 * max_relative_error;
8413 *   }
8414 *  
8415 *   if (relative_error >= max_relative_error)
8416 *   {
8417 *   TimerOutput::Scope t(computing_timer, "Setup: refine mesh");
8418 *   ++current_refinement_cycle;
8419 *   refine_grid();
8420 *   }
8421 *  
8422 *   }
8423 *  
8424 * @endcode
8425 *
8426 * ------------------------ Refinement based on the number of refinement --------------------------
8427 *
8428 * @code
8429 *   /*
8430 *   bool continue_loop = true;
8431 *   while (continue_loop)
8432 *   {
8433 *   solve_newton();
8434 *   compute_error();
8435 *  
8436 *   if ( (timestep_no == 1) && (current_refinement_cycle < 1) )
8437 *   {
8438 *   TimerOutput::Scope t(computing_timer, "Setup: refine mesh");
8439 *   ++current_refinement_cycle;
8440 *   refine_grid();
8441 *   }else
8442 *   {
8443 *   continue_loop = false;
8444 *   }
8445 *  
8446 *   }
8447 *   */
8448 *  
8449 * @endcode
8450 *
8451 * -------------------------------------------------------------------------------------------------
8452 *
8453
8454 *
8455 *
8456 * @code
8457 *   solution += incremental_displacement;
8458 *  
8459 *   update_quadrature_point_history ();
8460 *  
8461 *   output_results((std::string("solution-") +
8462 *   Utilities::int_to_string(timestep_no, 4)).c_str());
8463 *  
8464 *   computing_timer.print_summary();
8465 *   computing_timer.reset();
8466 *  
8467 *   Utilities::System::MemoryStats stats;
8468 *   Utilities::System::get_memory_stats(stats);
8469 *   pcout << "Peak virtual memory used, resident in kB: " << stats.VmSize << " "
8470 *   << stats.VmRSS << std::endl;
8471 *  
8472 *  
8473 *   if (std::abs(present_time-end_time) < 1.e-7)
8474 *   {
8475 *   const std::string filename = (output_dir + "Results");
8476 *  
8477 *   std::ofstream output_txt((filename + ".txt").c_str());
8478 *  
8479 *   pcout << std::endl;
8480 *   table_results.write_text(output_txt);
8481 *   pcout << std::endl;
8482 *   table_results_2.write_text(output_txt);
8483 *   pcout << std::endl;
8484 *   table_results_3.write_text(output_txt);
8485 *   pcout << std::endl;
8486 *   }
8487 *  
8488 *   }
8489 *  
8490 *   if (base_mesh == "Thick_tube_internal_pressure")
8491 *   {
8492 *   triangulation.reset_manifold (0);
8493 *   triangulation.reset_manifold (1);
8494 *   }
8495 *   else if (base_mesh == "Perforated_strip_tension")
8496 *   {
8497 *   triangulation.reset_manifold (10);
8498 *   }
8499 *  
8500 *   }
8501 *   }
8502 *  
8503 * @endcode
8504 *
8505 *
8506 * <a name="elastoplastic.cc-Thecodemaincodefunction"></a>
8507 * <h3>The <code>main</code> function</h3>
8508 *
8509
8510 *
8511 * There really isn't much to the <code>main()</code> function. It looks
8512 * like they always do:
8513 *
8514 * @code
8515 *   int main (int argc, char *argv[])
8516 *   {
8517 *   using namespace dealii;
8518 *   using namespace ElastoPlastic;
8519 *  
8520 *   try
8521 *   {
8522 *   deallog.depth_console(0);
8523 *   ParameterHandler prm;
8524 *   const int dim = 3;
8525 *   ElastoPlasticProblem<dim>::declare_parameters(prm);
8526 *   if (argc != 2)
8527 *   {
8528 *   std::cerr << "*** Call this program as <./elastoplastic input.prm>" << std::endl;
8529 *   return 1;
8530 *   }
8531 *  
8532 *   prm.parse_input(argv[1]);
8533 *   Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv);
8534 *   {
8535 *   ElastoPlasticProblem<dim> problem(prm);
8536 *   problem.run();
8537 *   }
8538 *   }
8539 *   catch (std::exception &exc)
8540 *   {
8541 *   std::cerr << std::endl << std::endl
8542 *   << "----------------------------------------------------"
8543 *   << std::endl;
8544 *   std::cerr << "Exception on processing: " << std::endl
8545 *   << exc.what() << std::endl
8546 *   << "Aborting!" << std::endl
8547 *   << "----------------------------------------------------"
8548 *   << std::endl;
8549 *  
8550 *   return 1;
8551 *   }
8552 *   catch (...)
8553 *   {
8554 *   std::cerr << std::endl << std::endl
8555 *   << "----------------------------------------------------"
8556 *   << std::endl;
8557 *   std::cerr << "Unknown exception!" << std::endl
8558 *   << "Aborting!" << std::endl
8559 *   << "----------------------------------------------------"
8560 *   << std::endl;
8561 *   return 1;
8562 *   }
8563 *  
8564 *   return 0;
8565 *   }
8566 * @endcode
8567
8568
8569*/
void distribute_local_to_global(const InVector &local_vector, const std::vector< size_type > &local_dof_indices, OutVector &global_vector) const
void attach_dof_handler(const DoFHandler< dim, spacedim > &)
Definition fe_q.h:550
virtual void vector_value_list(const std::vector< Point< dim > > &points, std::vector< Vector< RangeNumberType > > &values) const
virtual void vector_value(const Point< dim > &p, Vector< RangeNumberType > &values) const
unsigned int depth_console(const unsigned int n)
Definition logstream.cc:349
Definition point.h:111
void initialize(const MatrixType &A, const AdditionalData &parameters=AdditionalData())
void initialize(const SparsityPattern &sparsity_pattern)
numbers::NumberTraits< Number >::real_type norm() const
@ wall_times
Definition timer.h:651
iterator end()
Point< 3 > center
float depth
Point< 3 > vertices[4]
Point< 2 > second
Definition grid_out.cc:4624
Point< 2 > first
Definition grid_out.cc:4623
__global__ void set(Number *val, const Number s, const size_type N)
#define Assert(cond, exc)
#define DeclException1(Exception1, type1, outsequence)
Definition exceptions.h:516
#define AssertThrow(cond, exc)
typename ActiveSelector::cell_iterator cell_iterator
typename ActiveSelector::face_iterator face_iterator
typename ActiveSelector::active_cell_iterator active_cell_iterator
void loop(IteratorType begin, std_cxx20::type_identity_t< IteratorType > end, DOFINFO &dinfo, INFOBOX &info, const std::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &cell_worker, const std::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &boundary_worker, const std::function< void(DOFINFO &, DOFINFO &, typename INFOBOX::CellInfo &, typename INFOBOX::CellInfo &)> &face_worker, AssemblerType &assembler, const LoopControl &lctrl=LoopControl())
Definition loop.h:442
void make_hanging_node_constraints(const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< number > &constraints)
void make_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern, const AffineConstraints< number > &constraints={}, const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
@ update_hessians
Second derivatives of shape functions.
@ update_values
Shape function values.
@ update_normal_vectors
Normal vectors.
@ update_JxW_values
Transformed quadrature weights.
@ update_gradients
Shape function gradients.
@ update_quadrature_points
Transformed quadrature points.
LogStream deallog
Definition logstream.cc:36
const Event initial
Definition event.cc:64
void downstream(DoFHandler< dim, spacedim > &dof_handler, const Tensor< 1, spacedim > &direction, const bool dof_wise_renumbering=false)
IndexSet extract_locally_relevant_dofs(const DoFHandler< dim, spacedim > &dof_handler)
void extract_constant_modes(const DoFHandler< dim, spacedim > &dof_handler, const ComponentMask &component_mask, std::vector< std::vector< bool > > &constant_modes)
void interpolation_difference(const DoFHandler< dim, spacedim > &dof1, const InVector &z1, const FiniteElement< dim, spacedim > &fe2, OutVector &z1_difference)
void compute_interpolation_to_quadrature_points_matrix(const FiniteElement< dim, spacedim > &fe, const Quadrature< dim > &quadrature, FullMatrix< double > &I_q)
void compute_projection_from_quadrature_points_matrix(const FiniteElement< dim, spacedim > &fe, const Quadrature< dim > &lhs_quadrature, const Quadrature< dim > &rhs_quadrature, FullMatrix< double > &X)
void interpolate(const DoFHandler< dim, spacedim > &dof1, const InVector &u1, const DoFHandler< dim, spacedim > &dof2, OutVector &u2)
void hyper_rectangle(Triangulation< dim, spacedim > &tria, const Point< dim > &p1, const Point< dim > &p2, const bool colorize=false)
void extrude_triangulation(const Triangulation< 2, 2 > &input, const unsigned int n_slices, const double height, Triangulation< 3, 3 > &result, const bool copy_manifold_ids=false, const std::vector< types::manifold_id > &manifold_priorities={})
void subdivided_hyper_rectangle(Triangulation< dim, spacedim > &tria, const std::vector< unsigned int > &repetitions, const Point< dim > &p1, const Point< dim > &p2, const bool colorize=false)
void quarter_hyper_shell(Triangulation< dim > &tria, const Point< dim > &center, const double inner_radius, const double outer_radius, const unsigned int n_cells=0, const bool colorize=false)
void merge_triangulations(const Triangulation< dim, spacedim > &triangulation_1, const Triangulation< dim, spacedim > &triangulation_2, Triangulation< dim, spacedim > &result, const double duplicated_vertex_tolerance=1.0e-12, const bool copy_manifold_ids=false, const bool copy_boundary_ids=false)
void half_hyper_ball(Triangulation< dim > &tria, const Point< dim > &center=Point< dim >(), const double radius=1.)
void refine(Triangulation< dim, spacedim > &tria, const Vector< Number > &criteria, const double threshold, const unsigned int max_to_mark=numbers::invalid_unsigned_int)
spacedim const Point< spacedim > & p
Definition grid_tools.h:990
void rotate(const double angle, Triangulation< dim, spacedim > &triangulation)
const std::vector< bool > & used
const Triangulation< dim, spacedim > & tria
void shift(const Tensor< 1, spacedim > &shift_vector, Triangulation< dim, spacedim > &triangulation)
spacedim & mesh
Definition grid_tools.h:989
double volume(const Triangulation< dim, spacedim > &tria)
double diameter(const Triangulation< dim, spacedim > &tria)
for(unsigned int j=best_vertex+1;j< vertices.size();++j) if(vertices_to_use[j])
@ valid
Iterator points to a valid object.
@ matrix
Contents is actually a matrix.
@ symmetric
Matrix is symmetric.
@ diagonal
Matrix is diagonal.
@ general
No special properties.
void cell_matrix(FullMatrix< double > &M, const FEValuesBase< dim > &fe, const FEValuesBase< dim > &fetest, const ArrayView< const std::vector< double > > &velocity, const double factor=1.)
Definition advection.h:74
double norm(const FEValuesBase< dim > &fe, const ArrayView< const std::vector< Tensor< 1, dim > > > &Du)
Definition divergence.h:471
Point< spacedim > point(const gp_Pnt &p, const double tolerance=1e-10)
Definition utilities.cc:191
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
Number angle(const Tensor< 1, spacedim, Number > &a, const Tensor< 1, spacedim, Number > &b)
void apply(const Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type &team_member, const Kokkos::View< Number *, MemorySpace::Default::kokkos_space > shape_data, const ViewTypeIn in, ViewTypeOut out)
constexpr ReturnType< rank, T >::value_type & extract(T &t, const ArrayType &indices)
void free(T *&pointer)
Definition cuda.h:96
T sum(const T &t, const MPI_Comm mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
Definition mpi.cc:92
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
Definition mpi.cc:107
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:470
void interpolate_boundary_values(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const std::map< types::boundary_id, const Function< spacedim, number > * > &function_map, std::map< types::global_dof_index, number > &boundary_values, const ComponentMask &component_mask={})
spacedim const DoFHandler< dim, spacedim > const FullMatrix< double > & transfer
void run(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)
long double gamma(const unsigned int n)
int(&) functions(const void *v1, const void *v2)
const types::boundary_id invalid_boundary_id
Definition types.h:292
const InputIterator OutputIterator out
Definition parallel.h:167
const Iterator const std_cxx20::type_identity_t< Iterator > & end
Definition parallel.h:610
const InputIterator OutputIterator const Function & function
Definition parallel.h:168
STL namespace.
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sin(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
void swap(SmartPointer< T, P > &t1, SmartPointer< T, Q > &t2)
std::vector< unsigned int > vertices
types::boundary_id boundary_id
DEAL_II_HOST constexpr SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > deviator(const SymmetricTensor< 2, dim, Number > &)