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