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