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