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