605 * We start by including all the necessary deal.II header files and some
C++
606 * related ones. They have been discussed in detail in previous tutorial
607 * programs, so you need only refer to past tutorials
for details.
613 * #include <deal.II/base/function.h>
614 * #include <deal.II/base/parameter_handler.h>
615 * #include <deal.II/base/
point.h>
616 * #include <deal.II/base/quadrature_lib.h>
617 * #include <deal.II/base/symmetric_tensor.h>
618 * #include <deal.II/base/tensor.h>
619 * #include <deal.II/base/timer.h>
620 * #include <deal.II/base/work_stream.h>
621 * #include <deal.II/base/mpi.h>
622 * #include <deal.II/base/quadrature_point_data.h>
624 * #include <deal.II/differentiation/ad.h>
626 * #include <deal.II/distributed/shared_tria.h>
628 * #include <deal.II/dofs/dof_renumbering.h>
629 * #include <deal.II/dofs/dof_tools.h>
630 * #include <deal.II/dofs/dof_accessor.h>
632 * #include <deal.II/grid/filtered_iterator.h>
633 * #include <deal.II/grid/grid_generator.h>
634 * #include <deal.II/grid/grid_tools.h>
635 * #include <deal.II/grid/grid_in.h>
636 * #include <deal.II/grid/grid_out.h>
637 * #include <deal.II/grid/manifold_lib.h>
638 * #include <deal.II/grid/tria_accessor.h>
639 * #include <deal.II/grid/tria_iterator.h>
641 * #include <deal.II/fe/fe_dgp_monomial.h>
642 * #include <deal.II/fe/fe_q.h>
643 * #include <deal.II/fe/fe_system.h>
644 * #include <deal.II/fe/fe_tools.h>
645 * #include <deal.II/fe/fe_values.h>
647 * #include <deal.II/lac/block_sparsity_pattern.h>
648 * #include <deal.II/lac/affine_constraints.h>
649 * #include <deal.II/lac/dynamic_sparsity_pattern.h>
650 * #include <deal.II/lac/full_matrix.h>
652 * #include <deal.II/lac/packaged_operation.h>
654 * #include <deal.II/lac/trilinos_block_sparse_matrix.h>
655 * #include <deal.II/lac/trilinos_linear_operator.h>
656 * #include <deal.II/lac/trilinos_parallel_block_vector.h>
657 * #include <deal.II/lac/trilinos_precondition.h>
658 * #include <deal.II/lac/trilinos_sparse_matrix.h>
659 * #include <deal.II/lac/trilinos_sparsity_pattern.h>
660 * #include <deal.II/lac/trilinos_solver.h>
661 * #include <deal.II/lac/trilinos_vector.h>
663 * #include <deal.II/lac/block_vector.h>
664 * #include <deal.II/lac/vector.h>
666 * #include <deal.II/numerics/data_postprocessor.h>
667 * #include <deal.II/numerics/data_out.h>
668 * #include <deal.II/numerics/data_out_faces.h>
669 * #include <deal.II/numerics/fe_field_function.h>
670 * #include <deal.II/numerics/vector_tools.h>
672 * #include <deal.II/physics/transformations.h>
673 * #include <deal.II/physics/elasticity/kinematics.h>
674 * #include <deal.II/physics/elasticity/standard_tensors.h>
676 * #include <iostream>
684 * We create a
namespace for everything that relates to
685 * the nonlinear poro-viscoelastic formulation,
686 * and
import all the deal.II function and
class names into it:
689 * namespace NonLinearPoroViscoElasticity
696 * <a name=
"Runtimeparameters"></a>
697 * <h3>Run-time parameters</h3>
702 * introduced by the user through the file
"parameters.prm"
705 *
namespace Parameters
710 * <a name=
"FiniteElementsystem"></a>
711 * <h4>Finite Element system</h4>
712 * Here we specify the polynomial order used to
approximate the solution,
713 * both
for the displacements and pressure unknowns.
714 * The quadrature order should be adjusted accordingly.
719 *
unsigned int poly_degree_displ;
720 *
unsigned int poly_degree_pore;
721 *
unsigned int quad_order;
732 * prm.enter_subsection(
"Finite element system");
734 * prm.declare_entry(
"Polynomial degree displ",
"2",
736 *
"Displacement system polynomial order");
738 * prm.declare_entry(
"Polynomial degree pore",
"1",
740 *
"Pore pressure system polynomial order");
742 * prm.declare_entry(
"Quadrature order",
"3",
744 *
"Gauss quadrature order");
746 * prm.leave_subsection();
751 * prm.enter_subsection(
"Finite element system");
753 * poly_degree_displ = prm.get_integer(
"Polynomial degree displ");
754 * poly_degree_pore = prm.get_integer(
"Polynomial degree pore");
755 * quad_order = prm.get_integer(
"Quadrature order");
757 * prm.leave_subsection();
763 * <a name=
"Geometry"></a>
765 * These parameters are related to the geometry definition and mesh generation.
766 * We select the type of problem to solve and introduce the desired load
values.
771 * std::string geom_type;
772 *
unsigned int global_refinement;
774 * std::string load_type;
776 *
unsigned int num_cycle_sets;
778 *
double drained_pressure;
789 * prm.enter_subsection(
"Geometry");
791 * prm.declare_entry(
"Geometry type",
"Ehlers_tube_step_load",
793 *
"|Ehlers_tube_increase_load"
794 *
"|Ehlers_cube_consolidation"
795 *
"|Franceschini_consolidation"
796 *
"|Budday_cube_tension_compression"
797 *
"|Budday_cube_tension_compression_fully_fixed"
798 *
"|Budday_cube_shear_fully_fixed"),
799 *
"Type of geometry used. "
800 *
"For Ehlers verification examples see Ehlers and Eipper (1999). "
801 *
"For Franceschini brain consolidation see Franceschini et al. (2006)"
802 *
"For Budday brain examples see Budday et al. (2017)");
804 * prm.declare_entry(
"Global refinement",
"1",
806 *
"Global refinement level");
808 * prm.declare_entry(
"Grid scale",
"1.0",
810 *
"Global grid scaling factor");
812 * prm.declare_entry(
"Load type",
"pressure",
814 *
"Type of loading");
816 * prm.declare_entry(
"Load value",
"-7.5e+6",
820 * prm.declare_entry(
"Number of cycle sets",
"1",
822 *
"Number of times each set of 3 cycles is repeated, only for "
823 *
"Budday_cube_tension_compression and Budday_cube_tension_compression_fully_fixed. "
824 *
"Load value is doubled in second set, load rate is kept constant."
825 *
"Final time indicates end of second cycle set.");
827 * prm.declare_entry(
"Fluid flow value",
"0.0",
829 *
"Prescribed fluid flow. Not implemented in any example yet.");
831 * prm.declare_entry(
"Drained pressure",
"0.0",
833 *
"Increase of pressure value at drained boundary w.r.t the atmospheric pressure.");
835 * prm.leave_subsection();
840 * prm.enter_subsection(
"Geometry");
842 * geom_type = prm.get(
"Geometry type");
843 * global_refinement = prm.get_integer(
"Global refinement");
844 *
scale = prm.get_double(
"Grid scale");
845 * load_type = prm.get(
"Load type");
846 * load = prm.get_double(
"Load value");
847 * num_cycle_sets = prm.get_integer(
"Number of cycle sets");
848 * fluid_flow = prm.get_double(
"Fluid flow value");
849 * drained_pressure = prm.get_double(
"Drained pressure");
851 * prm.leave_subsection();
857 * <a name=
"Materials"></a>
862 * Here we select the type of material
for the solid component
863 * and define the corresponding material parameters.
864 * Then we define he fluid data, including the type of
865 * seepage velocity definition to use.
870 * std::string mat_type;
876 *
double alpha1_infty;
877 *
double alpha2_infty;
878 *
double alpha3_infty;
882 *
double alpha1_mode_1;
883 *
double alpha2_mode_1;
884 *
double alpha3_mode_1;
885 *
double viscosity_mode_1;
886 * std::string fluid_type;
887 *
double solid_vol_frac;
888 *
double kappa_darcy;
889 *
double init_intrinsic_perm;
890 *
double viscosity_FR;
891 *
double init_darcy_coef;
894 *
int gravity_direction;
895 *
double gravity_value;
909 * prm.enter_subsection(
"Material properties");
911 * prm.declare_entry(
"material",
"Neo-Hooke",
913 *
"Type of material used in the problem");
915 * prm.declare_entry(
"lambda",
"8.375e6",
917 *
"First Lamé parameter for extension function related to compactation point in solid material [Pa].");
919 * prm.declare_entry(
"shear modulus",
"5.583e6",
921 *
"shear modulus for Neo-Hooke materials [Pa].");
923 * prm.declare_entry(
"eigen solver",
"QL Implicit Shifts",
925 *
"The type of eigen solver to be used for Ogden and visco-Ogden models.");
927 * prm.declare_entry(
"mu1",
"0.0",
929 *
"Shear material parameter 'mu1' for Ogden material [Pa].");
931 * prm.declare_entry(
"mu2",
"0.0",
933 *
"Shear material parameter 'mu2' for Ogden material [Pa].");
935 * prm.declare_entry(
"mu3",
"0.0",
937 *
"Shear material parameter 'mu1' for Ogden material [Pa].");
939 * prm.declare_entry(
"alpha1",
"1.0",
941 *
"Stiffness material parameter 'alpha1' for Ogden material [-].");
943 * prm.declare_entry(
"alpha2",
"1.0",
945 *
"Stiffness material parameter 'alpha2' for Ogden material [-].");
947 * prm.declare_entry(
"alpha3",
"1.0",
949 *
"Stiffness material parameter 'alpha3' for Ogden material [-].");
951 * prm.declare_entry(
"mu1_1",
"0.0",
953 *
"Shear material parameter 'mu1' for first viscous mode in Ogden material [Pa].");
955 * prm.declare_entry(
"mu2_1",
"0.0",
957 *
"Shear material parameter 'mu2' for first viscous mode in Ogden material [Pa].");
959 * prm.declare_entry(
"mu3_1",
"0.0",
961 *
"Shear material parameter 'mu1' for first viscous mode in Ogden material [Pa].");
963 * prm.declare_entry(
"alpha1_1",
"1.0",
965 *
"Stiffness material parameter 'alpha1' for first viscous mode in Ogden material [-].");
967 * prm.declare_entry(
"alpha2_1",
"1.0",
969 *
"Stiffness material parameter 'alpha2' for first viscous mode in Ogden material [-].");
971 * prm.declare_entry(
"alpha3_1",
"1.0",
973 *
"Stiffness material parameter 'alpha3' for first viscous mode in Ogden material [-].");
975 * prm.declare_entry(
"viscosity_1",
"1e-10",
977 *
"Deformation-independent viscosity parameter 'eta_1' for first viscous mode in Ogden material [-].");
979 * prm.declare_entry(
"seepage definition",
"Ehlers",
981 *
"Type of formulation used to define the seepage velocity in the problem. "
982 *
"Choose between Markert formulation of deformation-dependent intrinsic permeability "
983 *
"and Ehlers formulation of deformation-dependent Darcy flow coefficient.");
985 * prm.declare_entry(
"initial solid volume fraction",
"0.67",
987 *
"Initial porosity (solid volume fraction, 0 < n_0s < 1)");
989 * prm.declare_entry(
"kappa",
"0.0",
991 *
"Deformation-dependency control parameter for specific permeability (kappa >= 0)");
993 * prm.declare_entry(
"initial intrinsic permeability",
"0.0",
995 *
"Initial intrinsic permeability parameter [m^2] (isotropic permeability). To be used with Markert formulation.");
997 * prm.declare_entry(
"fluid viscosity",
"0.0",
999 *
"Effective shear viscosity parameter of the fluid [Pa·s, (N·s)/m^2]. To be used with Markert formulation.");
1001 * prm.declare_entry(
"initial Darcy coefficient",
"1.0e-4",
1003 *
"Initial Darcy flow coefficient [m/s] (isotropic permeability). To be used with Ehlers formulation.");
1005 * prm.declare_entry(
"fluid weight",
"1.0e4",
1007 *
"Effective weight of the fluid [N/m^3]. To be used with Ehlers formulation.");
1009 * prm.declare_entry(
"gravity term",
"false",
1011 *
"Gravity term considered (true) or neglected (false)");
1013 * prm.declare_entry(
"fluid density",
"1.0",
1015 *
"Real (or effective) density of the fluid");
1017 * prm.declare_entry(
"solid density",
"1.0",
1019 *
"Real (or effective) density of the solid");
1021 * prm.declare_entry(
"gravity direction",
"2",
1023 *
"Direction of gravity (unit vector 0 for x, 1 for y, 2 for z)");
1025 * prm.declare_entry(
"gravity value",
"-9.81",
1027 *
"Value of gravity (be careful to have consistent units!)");
1029 * prm.leave_subsection();
1034 * prm.enter_subsection(
"Material properties");
1041 * mat_type = prm.get(
"material");
1042 *
lambda = prm.get_double(
"lambda");
1043 * mu = prm.get_double(
"shear modulus");
1044 * mu1_infty = prm.get_double(
"mu1");
1045 * mu2_infty = prm.get_double(
"mu2");
1046 * mu3_infty = prm.get_double(
"mu3");
1047 * alpha1_infty = prm.get_double(
"alpha1");
1048 * alpha2_infty = prm.get_double(
"alpha2");
1049 * alpha3_infty = prm.get_double(
"alpha3");
1050 * mu1_mode_1 = prm.get_double(
"mu1_1");
1051 * mu2_mode_1 = prm.get_double(
"mu2_1");
1052 * mu3_mode_1 = prm.get_double(
"mu3_1");
1053 * alpha1_mode_1 = prm.get_double(
"alpha1_1");
1054 * alpha2_mode_1 = prm.get_double(
"alpha2_1");
1055 * alpha3_mode_1 = prm.get_double(
"alpha3_1");
1056 * viscosity_mode_1 = prm.get_double(
"viscosity_1");
1062 * fluid_type = prm.get(
"seepage definition");
1063 * solid_vol_frac = prm.get_double(
"initial solid volume fraction");
1064 * kappa_darcy = prm.get_double(
"kappa");
1065 * init_intrinsic_perm = prm.get_double(
"initial intrinsic permeability");
1066 * viscosity_FR = prm.get_double(
"fluid viscosity");
1067 * init_darcy_coef = prm.get_double(
"initial Darcy coefficient");
1068 * weight_FR = prm.get_double(
"fluid weight");
1074 * gravity_term = prm.get_bool(
"gravity term");
1075 * density_FR = prm.get_double(
"fluid density");
1076 * density_SR = prm.get_double(
"solid density");
1077 * gravity_direction = prm.get_integer(
"gravity direction");
1078 * gravity_value = prm.get_double(
"gravity value");
1080 *
if ( (fluid_type ==
"Markert") && ((init_intrinsic_perm == 0.0) || (viscosity_FR == 0.0)) )
1081 *
AssertThrow(
false, ExcMessage(
"Markert seepage velocity formulation requires the definition of "
1082 *
"'initial intrinsic permeability' and 'fluid viscosity' greater than 0.0."));
1084 *
if ( (fluid_type ==
"Ehlers") && ((init_darcy_coef == 0.0) || (weight_FR == 0.0)) )
1085 *
AssertThrow(
false, ExcMessage(
"Ehler seepage velocity formulation requires the definition of "
1086 *
"'initial Darcy coefficient' and 'fluid weight' greater than 0.0."));
1088 *
const std::string eigen_solver_type = prm.get(
"eigen solver");
1089 *
if (eigen_solver_type ==
"QL Implicit Shifts")
1091 *
else if (eigen_solver_type ==
"Jacobi")
1095 *
AssertThrow(
false, ExcMessage(
"Unknown eigen solver selected."));
1098 * prm.leave_subsection();
1104 * <a name=
"Nonlinearsolver"></a>
1105 * <h4>Nonlinear solver</h4>
1109 * We now define the tolerances and the maximum number of iterations
for the
1110 * Newton-Raphson scheme used to solve the nonlinear system of governing equations.
1113 *
struct NonlinearSolver
1115 *
unsigned int max_iterations_NR;
1118 *
double tol_p_fluid;
1129 * prm.enter_subsection(
"Nonlinear solver");
1131 * prm.declare_entry(
"Max iterations Newton-Raphson",
"15",
1133 *
"Number of Newton-Raphson iterations allowed");
1135 * prm.declare_entry(
"Tolerance force",
"1.0e-8",
1137 *
"Force residual tolerance");
1139 * prm.declare_entry(
"Tolerance displacement",
"1.0e-6",
1141 *
"Displacement error tolerance");
1143 * prm.declare_entry(
"Tolerance pore pressure",
"1.0e-6",
1145 *
"Pore pressure error tolerance");
1147 * prm.leave_subsection();
1152 * prm.enter_subsection(
"Nonlinear solver");
1154 * max_iterations_NR = prm.get_integer(
"Max iterations Newton-Raphson");
1155 * tol_f = prm.get_double(
"Tolerance force");
1156 * tol_u = prm.get_double(
"Tolerance displacement");
1157 * tol_p_fluid = prm.get_double(
"Tolerance pore pressure");
1159 * prm.leave_subsection();
1165 * <a name=
"Time"></a>
1167 * Here we
set the timestep size @f$ \varDelta t @f$ and the simulation
end-time.
1183 * prm.enter_subsection(
"Time");
1185 * prm.declare_entry(
"End time",
"10.0",
1189 * prm.declare_entry(
"Time step size",
"0.002",
1191 *
"Time step size. The value must be larger than the displacement error tolerance defined.");
1193 * prm.leave_subsection();
1198 * prm.enter_subsection(
"Time");
1200 * end_time = prm.get_double(
"End time");
1201 * delta_t = prm.get_double(
"Time step size");
1203 * prm.leave_subsection();
1210 * <a name=
"Output"></a>
1212 * We can choose the frequency of the data
for the output files.
1215 *
struct OutputParam
1218 * std::string outfiles_requested;
1219 *
unsigned int timestep_output;
1220 * std::string outtype;
1231 * prm.enter_subsection(
"Output parameters");
1233 * prm.declare_entry(
"Output files",
"true",
1235 *
"Paraview output files to generate.");
1236 * prm.declare_entry(
"Time step number output",
"1",
1238 *
"Output data for time steps multiple of the given "
1239 *
"integer value.");
1240 * prm.declare_entry(
"Averaged results",
"nodes",
1242 *
"Output data associated with integration point values"
1243 *
" averaged on elements or on nodes.");
1245 * prm.leave_subsection();
1250 * prm.enter_subsection(
"Output parameters");
1252 * outfiles_requested = prm.get(
"Output files");
1253 * timestep_output = prm.get_integer(
"Time step number output");
1254 * outtype = prm.get(
"Averaged results");
1256 * prm.leave_subsection();
1262 * <a name=
"Allparameters"></a>
1263 * <h4>All parameters</h4>
1264 * We
finally consolidate all of the above structures into a single container that holds all the
run-time selections.
1267 *
struct AllParameters :
public FESystem,
1270 *
public NonlinearSolver,
1272 *
public OutputParam
1274 * AllParameters(
const std::string &input_file);
1283 * AllParameters::AllParameters(
const std::string &input_file)
1286 * declare_parameters(prm);
1287 * prm.parse_input(input_file);
1288 * parse_parameters(prm);
1293 * FESystem::declare_parameters(prm);
1294 * Geometry::declare_parameters(prm);
1295 * Materials::declare_parameters(prm);
1296 * NonlinearSolver::declare_parameters(prm);
1297 * Time::declare_parameters(prm);
1298 * OutputParam::declare_parameters(prm);
1303 * FESystem::parse_parameters(prm);
1304 * Geometry::parse_parameters(prm);
1305 * Materials::parse_parameters(prm);
1306 * NonlinearSolver::parse_parameters(prm);
1307 * Time::parse_parameters(prm);
1308 * OutputParam::parse_parameters(prm);
1315 * <a name=
"Timeclass"></a>
1316 * <h3>Time
class</h3>
1317 * A simple
class to store time data.
1318 * For simplicity we assume a
constant time step size.
1324 * Time (
const double time_end,
1325 *
const double delta_t)
1328 * time_current(0.0),
1329 * time_end(time_end),
1336 *
double get_current() const
1338 *
return time_current;
1340 *
double get_end() const
1344 *
double get_delta_t() const
1348 *
unsigned int get_timestep() const
1352 *
void increment_time ()
1354 * time_current += delta_t;
1359 *
unsigned int timestep;
1360 *
double time_current;
1362 *
const double delta_t;
1368 * <a name=
"Constitutiveequationforthesolidcomponentofthebiphasicmaterial"></a>
1369 * <h3>Constitutive equation
for the solid component of the biphasic material</h3>
1374 * <a name=
"Baseclassgenerichyperelasticmaterial"></a>
1375 * <h4>Base
class:
generic hyperelastic material</h4>
1376 * The ``extra
" Kirchhoff stress in the solid component is the sum of isochoric
1377 * and a volumetric part.
1378 * @f$\mathbf{\tau} = \mathbf{\tau}_E^{(\bullet)} + \mathbf{\tau}^{\textrm{vol}}@f$
1379 * The deviatoric part changes depending on the type of material model selected:
1380 * Neo-Hooken hyperelasticity, Ogden hyperelasticiy,
1381 * or a single-mode finite viscoelasticity based on the Ogden hyperelastic model.
1382 * In this base class we declare it as a virtual function,
1383 * and it will be defined for each model type in the corresponding derived class.
1384 * We define here the volumetric component, which depends on the
1385 * extension function @f$U(J_S)@f$ selected, and in this case is the same for all models.
1386 * We use the function proposed by
1387 * Ehlers & Eipper 1999 doi:10.1023/A:1006565509095
1388 * We also define some public functions to access and update the internal variables.
1391 * template <int dim, typename NumberType = Sacado::Fad::DFad<double> >
1392 * class Material_Hyperelastic
1395 * Material_Hyperelastic(const Parameters::AllParameters ¶meters,
1398 * n_OS (parameters.solid_vol_frac),
1399 * lambda (parameters.lambda),
1402 * det_F_converged (1.0),
1403 * eigen_solver (parameters.eigen_solver)
1405 * ~Material_Hyperelastic()
1408 * SymmetricTensor<2, dim, NumberType>
1409 * get_tau_E(const Tensor<2,dim, NumberType> &F) const
1411 * return ( get_tau_E_base(F) + get_tau_E_ext_func(F) );
1414 * SymmetricTensor<2, dim, NumberType>
1415 * get_Cauchy_E(const Tensor<2, dim, NumberType> &F) const
1417 * const NumberType det_F = determinant(F);
1418 * Assert(det_F > 0, ExcInternalError());
1419 * return get_tau_E(F)*NumberType(1/det_F);
1423 * get_converged_det_F() const
1425 * return det_F_converged;
1429 * update_end_timestep()
1431 * det_F_converged = det_F;
1435 * update_internal_equilibrium( const Tensor<2, dim, NumberType> &F )
1437 * det_F = Tensor<0,dim,double>(determinant(F));
1441 * get_viscous_dissipation( ) const = 0;
1443 * const double n_OS;
1444 * const double lambda;
1447 * double det_F_converged;
1448 * const enum SymmetricTensorEigenvectorMethod eigen_solver;
1451 * SymmetricTensor<2, dim, NumberType>
1452 * get_tau_E_ext_func(const Tensor<2,dim, NumberType> &F) const
1454 * const NumberType det_F = determinant(F);
1455 * Assert(det_F > 0, ExcInternalError());
1457 * static const SymmetricTensor< 2, dim, double>
1458 * I (Physics::Elasticity::StandardTensors<dim>::I);
1459 * return ( NumberType(lambda * (1.0-n_OS)*(1.0-n_OS)
1460 * * (det_F/(1.0-n_OS) - det_F/(det_F-n_OS))) * I );
1463 * virtual SymmetricTensor<2, dim, NumberType>
1464 * get_tau_E_base(const Tensor<2,dim, NumberType> &F) const = 0;
1470 * <a name="DerivedclassNeoHookeanhyperelasticmaterial
"></a>
1471 * <h4>Derived class: Neo-Hookean hyperelastic material</h4>
1474 * template <int dim, typename NumberType = Sacado::Fad::DFad<double> >
1475 * class NeoHooke : public Material_Hyperelastic < dim, NumberType >
1478 * NeoHooke(const Parameters::AllParameters ¶meters,
1481 * Material_Hyperelastic< dim, NumberType > (parameters,time),
1484 * virtual ~NeoHooke()
1488 * get_viscous_dissipation() const override
1496 * SymmetricTensor<2, dim, NumberType>
1497 * get_tau_E_base(const Tensor<2,dim, NumberType> &F) const override
1499 * static const SymmetricTensor< 2, dim, double>
1500 * I (Physics::Elasticity::StandardTensors<dim>::I);
1502 * const bool use_standard_model = true;
1504 * if (use_standard_model)
1508 * Standard Neo-Hooke
1511 * return ( mu * ( symmetrize(F * transpose(F)) - I ) );
1517 * Neo-Hooke in terms of principal stretches
1520 * const SymmetricTensor<2, dim, NumberType>
1521 * B = symmetrize(F * transpose(F));
1522 * const std::array< std::pair< NumberType, Tensor< 1, dim, NumberType > >, dim >
1523 * eigen_B = eigenvectors(B, this->eigen_solver);
1525 * SymmetricTensor<2, dim, NumberType> B_ev;
1526 * for (unsigned int d=0; d<dim; ++d)
1527 * B_ev += eigen_B[d].first*symmetrize(outer_product(eigen_B[d].second,eigen_B[d].second));
1529 * return ( mu*(B_ev-I) );
1537 * <a name="DerivedclassOgdenhyperelasticmaterial
"></a>
1538 * <h4>Derived class: Ogden hyperelastic material</h4>
1541 * template <int dim, typename NumberType = Sacado::Fad::DFad<double> >
1542 * class Ogden : public Material_Hyperelastic < dim, NumberType >
1545 * Ogden(const Parameters::AllParameters ¶meters,
1548 * Material_Hyperelastic< dim, NumberType > (parameters,time),
1549 * mu({parameters.mu1_infty,
1550 * parameters.mu2_infty,
1551 * parameters.mu3_infty}),
1552 * alpha({parameters.alpha1_infty,
1553 * parameters.alpha2_infty,
1554 * parameters.alpha3_infty})
1560 * get_viscous_dissipation() const override
1566 * std::vector<double> mu;
1567 * std::vector<double> alpha;
1569 * SymmetricTensor<2, dim, NumberType>
1570 * get_tau_E_base(const Tensor<2,dim, NumberType> &F) const override
1572 * const SymmetricTensor<2, dim, NumberType>
1573 * B = symmetrize(F * transpose(F));
1575 * const std::array< std::pair< NumberType, Tensor< 1, dim, NumberType > >, dim >
1576 * eigen_B = eigenvectors(B, this->eigen_solver);
1578 * SymmetricTensor<2, dim, NumberType> tau;
1579 * static const SymmetricTensor< 2, dim, double>
1580 * I (Physics::Elasticity::StandardTensors<dim>::I);
1582 * for (unsigned int i = 0; i < 3; ++i)
1584 * for (unsigned int A = 0; A < dim; ++A)
1586 * SymmetricTensor<2, dim, NumberType> tau_aux1 = symmetrize(
1587 * outer_product(eigen_B[A].second,eigen_B[A].second));
1588 * tau_aux1 *= mu[i]*std::pow(eigen_B[A].first, (alpha[i]/2.) );
1591 * SymmetricTensor<2, dim, NumberType> tau_aux2 (I);
1592 * tau_aux2 *= mu[i];
1602 * <a name="DerivedclassSinglemodeOgdenviscoelasticmaterial
"></a>
1603 * <h4>Derived class: Single-mode Ogden viscoelastic material</h4>
1604 * We use the finite viscoelastic model described in
1605 * Reese & Govindjee (1998) doi:10.1016/S0020-7683(97)00217-5
1606 * The algorithm for the implicit exponential time integration is given in
1607 * Budday et al. (2017) doi: 10.1016/j.actbio.2017.06.024
1610 * template <int dim, typename NumberType = Sacado::Fad::DFad<double> >
1611 * class visco_Ogden : public Material_Hyperelastic < dim, NumberType >
1614 * visco_Ogden(const Parameters::AllParameters ¶meters,
1617 * Material_Hyperelastic< dim, NumberType > (parameters,time),
1618 * mu_infty({parameters.mu1_infty,
1619 * parameters.mu2_infty,
1620 * parameters.mu3_infty}),
1621 * alpha_infty({parameters.alpha1_infty,
1622 * parameters.alpha2_infty,
1623 * parameters.alpha3_infty}),
1624 * mu_mode_1({parameters.mu1_mode_1,
1625 * parameters.mu2_mode_1,
1626 * parameters.mu3_mode_1}),
1627 * alpha_mode_1({parameters.alpha1_mode_1,
1628 * parameters.alpha2_mode_1,
1629 * parameters.alpha3_mode_1}),
1630 * viscosity_mode_1(parameters.viscosity_mode_1),
1631 * Cinv_v_1(Physics::Elasticity::StandardTensors<dim>::I),
1632 * Cinv_v_1_converged(Physics::Elasticity::StandardTensors<dim>::I)
1634 * virtual ~visco_Ogden()
1638 * update_internal_equilibrium( const Tensor<2, dim, NumberType> &F ) override
1640 * Material_Hyperelastic < dim, NumberType >::update_internal_equilibrium(F);
1642 * this->Cinv_v_1 = this->Cinv_v_1_converged;
1643 * SymmetricTensor<2, dim, NumberType> B_e_1_tr = symmetrize(F * this->Cinv_v_1 * transpose(F));
1645 * const std::array< std::pair< NumberType, Tensor< 1, dim, NumberType > >, dim >
1646 * eigen_B_e_1_tr = eigenvectors(B_e_1_tr, this->eigen_solver);
1648 * Tensor< 1, dim, NumberType > lambdas_e_1_tr;
1649 * Tensor< 1, dim, NumberType > epsilon_e_1_tr;
1650 * for (int a = 0; a < dim; ++a)
1652 * lambdas_e_1_tr[a] = std::sqrt(eigen_B_e_1_tr[a].first);
1653 * epsilon_e_1_tr[a] = std::log(lambdas_e_1_tr[a]);
1656 * const double tolerance = 1e-8;
1657 * double residual_check = tolerance*10.0;
1658 * Tensor< 1, dim, NumberType > residual;
1659 * Tensor< 2, dim, NumberType > tangent;
1660 * static const SymmetricTensor< 2, dim, double> I(Physics::Elasticity::StandardTensors<dim>::I);
1661 * NumberType J_e_1 = std::sqrt(determinant(B_e_1_tr));
1663 * std::vector<NumberType> lambdas_e_1_iso(dim);
1664 * SymmetricTensor<2, dim, NumberType> B_e_1;
1665 * int iteration = 0;
1667 * Tensor< 1, dim, NumberType > lambdas_e_1;
1668 * Tensor< 1, dim, NumberType > epsilon_e_1;
1669 * epsilon_e_1 = epsilon_e_1_tr;
1671 * while(residual_check > tolerance)
1673 * NumberType aux_J_e_1 = 1.0;
1674 * for (unsigned int a = 0; a < dim; ++a)
1676 * lambdas_e_1[a] = std::exp(epsilon_e_1[a]);
1677 * aux_J_e_1 *= lambdas_e_1[a];
1680 * J_e_1 = aux_J_e_1;
1682 * for (unsigned int a = 0; a < dim; ++a)
1683 * lambdas_e_1_iso[a] = lambdas_e_1[a]*std::pow(J_e_1,-1.0/dim);
1685 * for (unsigned int a = 0; a < dim; ++a)
1687 * residual[a] = get_beta_mode_1(lambdas_e_1_iso, a);
1688 * residual[a] *= this->time.get_delta_t()/(2.0*viscosity_mode_1);
1689 * residual[a] += epsilon_e_1[a];
1690 * residual[a] -= epsilon_e_1_tr[a];
1692 * for (unsigned int b = 0; b < dim; ++b)
1694 * tangent[a][b] = get_gamma_mode_1(lambdas_e_1_iso, a, b);
1695 * tangent[a][b] *= this->time.get_delta_t()/(2.0*viscosity_mode_1);
1696 * tangent[a][b] += I[a][b];
1700 * epsilon_e_1 -= invert(tangent)*residual;
1702 * residual_check = 0.0;
1703 * for (unsigned int a = 0; a < dim; ++a)
1705 * if ( std::abs(residual[a]) > residual_check)
1706 * residual_check = std::abs(Tensor<0,dim,double>(residual[a]));
1709 * if (iteration > 15 )
1710 * AssertThrow(false, ExcMessage("No convergence in local Newton iteration
for the
"
1711 * "viscoelastic exponential time integration algorithm.
"));
1714 * NumberType aux_J_e_1 = 1.0;
1715 * for (unsigned int a = 0; a < dim; ++a)
1717 * lambdas_e_1[a] = std::exp(epsilon_e_1[a]);
1718 * aux_J_e_1 *= lambdas_e_1[a];
1720 * J_e_1 = aux_J_e_1;
1722 * for (unsigned int a = 0; a < dim; ++a)
1723 * lambdas_e_1_iso[a] = lambdas_e_1[a]*std::pow(J_e_1,-1.0/dim);
1725 * for (unsigned int a = 0; a < dim; ++a)
1727 * SymmetricTensor<2, dim, NumberType>
1728 * B_e_1_aux = symmetrize(outer_product(eigen_B_e_1_tr[a].second,eigen_B_e_1_tr[a].second));
1729 * B_e_1_aux *= lambdas_e_1[a] * lambdas_e_1[a];
1730 * B_e_1 += B_e_1_aux;
1733 * Tensor<2, dim, NumberType>Cinv_v_1_AD = symmetrize(invert(F) * B_e_1 * invert(transpose(F)));
1735 * this->tau_neq_1 = 0;
1736 * for (unsigned int a = 0; a < dim; ++a)
1738 * SymmetricTensor<2, dim, NumberType>
1739 * tau_neq_1_aux = symmetrize(outer_product(eigen_B_e_1_tr[a].second,eigen_B_e_1_tr[a].second));
1740 * tau_neq_1_aux *= get_beta_mode_1(lambdas_e_1_iso, a);
1741 * this->tau_neq_1 += tau_neq_1_aux;
1749 * for (unsigned int a = 0; a < dim; ++a)
1750 * for (unsigned int b = 0; b < dim; ++b)
1751 * this->Cinv_v_1[a][b]= Tensor<0,dim,double>(Cinv_v_1_AD[a][b]);
1754 * void update_end_timestep() override
1756 * Material_Hyperelastic < dim, NumberType >::update_end_timestep();
1757 * this->Cinv_v_1_converged = this->Cinv_v_1;
1760 * double get_viscous_dissipation() const override
1762 * NumberType dissipation_term = get_tau_E_neq() * get_tau_E_neq(); //Double contract the two SymmetricTensor
1763 * dissipation_term /= (2*viscosity_mode_1);
1765 * return dissipation_term.val();
1769 * std::vector<double> mu_infty;
1770 * std::vector<double> alpha_infty;
1771 * std::vector<double> mu_mode_1;
1772 * std::vector<double> alpha_mode_1;
1773 * double viscosity_mode_1;
1774 * SymmetricTensor<2, dim, double> Cinv_v_1;
1775 * SymmetricTensor<2, dim, double> Cinv_v_1_converged;
1776 * SymmetricTensor<2, dim, NumberType> tau_neq_1;
1778 * SymmetricTensor<2, dim, NumberType>
1779 * get_tau_E_base(const Tensor<2,dim, NumberType> &F) const override
1781 * return ( get_tau_E_neq() + get_tau_E_eq(F) );
1784 * SymmetricTensor<2, dim, NumberType>
1785 * get_tau_E_eq(const Tensor<2,dim, NumberType> &F) const
1787 * const SymmetricTensor<2, dim, NumberType> B = symmetrize(F * transpose(F));
1789 * std::array< std::pair< NumberType, Tensor< 1, dim, NumberType > >, dim > eigen_B;
1790 * eigen_B = eigenvectors(B, this->eigen_solver);
1792 * SymmetricTensor<2, dim, NumberType> tau;
1793 * static const SymmetricTensor< 2, dim, double>
1794 * I (Physics::Elasticity::StandardTensors<dim>::I);
1796 * for (unsigned int i = 0; i < 3; ++i)
1798 * for (unsigned int A = 0; A < dim; ++A)
1800 * SymmetricTensor<2, dim, NumberType> tau_aux1 = symmetrize(
1801 * outer_product(eigen_B[A].second,eigen_B[A].second));
1802 * tau_aux1 *= mu_infty[i]*std::pow(eigen_B[A].first, (alpha_infty[i]/2.) );
1805 * SymmetricTensor<2, dim, NumberType> tau_aux2 (I);
1806 * tau_aux2 *= mu_infty[i];
1812 * SymmetricTensor<2, dim, NumberType>
1813 * get_tau_E_neq() const
1819 * get_beta_mode_1(std::vector< NumberType > &lambda, const int &A) const
1821 * NumberType beta = 0.0;
1823 * for (unsigned int i = 0; i < 3; ++i) //3rd-order Ogden model
1826 * NumberType aux = 0.0;
1827 * for (int p = 0; p < dim; ++p)
1828 * aux += std::pow(lambda[p],alpha_mode_1[i]);
1831 * aux += std::pow(lambda[A], alpha_mode_1[i]);
1832 * aux *= mu_mode_1[i];
1840 * get_gamma_mode_1(std::vector< NumberType > &lambda,
1842 * const int &B ) const
1844 * NumberType gamma = 0.0;
1848 * for (unsigned int i = 0; i < 3; ++i)
1850 * NumberType aux = 0.0;
1851 * for (int p = 0; p < dim; ++p)
1852 * aux += std::pow(lambda[p],alpha_mode_1[i]);
1854 * aux *= 1.0/(dim*dim);
1855 * aux += 1.0/dim * std::pow(lambda[A], alpha_mode_1[i]);
1856 * aux *= mu_mode_1[i]*alpha_mode_1[i];
1863 * for (unsigned int i = 0; i < 3; ++i)
1865 * NumberType aux = 0.0;
1866 * for (int p = 0; p < dim; ++p)
1867 * aux += std::pow(lambda[p],alpha_mode_1[i]);
1869 * aux *= 1.0/(dim*dim);
1870 * aux -= 1.0/dim * std::pow(lambda[A], alpha_mode_1[i]);
1871 * aux -= 1.0/dim * std::pow(lambda[B], alpha_mode_1[i]);
1872 * aux *= mu_mode_1[i]*alpha_mode_1[i];
1886 * <a name="Constitutiveequationforthefluidcomponentofthebiphasicmaterial
"></a>
1887 * <h3>Constitutive equation for the fluid component of the biphasic material</h3>
1888 * We consider two slightly different definitions to define the seepage velocity with a Darcy-like law.
1889 * Ehlers & Eipper 1999, doi:10.1023/A:1006565509095
1890 * Markert 2007, doi:10.1007/s11242-007-9107-6
1891 * The selection of one or another is made by the user via the parameters file.
1894 * template <int dim, typename NumberType = Sacado::Fad::DFad<double> >
1895 * class Material_Darcy_Fluid
1898 * Material_Darcy_Fluid(const Parameters::AllParameters ¶meters)
1900 * fluid_type(parameters.fluid_type),
1901 * n_OS(parameters.solid_vol_frac),
1902 * initial_intrinsic_permeability(parameters.init_intrinsic_perm),
1903 * viscosity_FR(parameters.viscosity_FR),
1904 * initial_darcy_coefficient(parameters.init_darcy_coef),
1905 * weight_FR(parameters.weight_FR),
1906 * kappa_darcy(parameters.kappa_darcy),
1907 * gravity_term(parameters.gravity_term),
1908 * density_FR(parameters.density_FR),
1909 * gravity_direction(parameters.gravity_direction),
1910 * gravity_value(parameters.gravity_value)
1912 * Assert(kappa_darcy >= 0, ExcInternalError());
1914 * ~Material_Darcy_Fluid()
1917 * Tensor<1, dim, NumberType> get_seepage_velocity_current
1918 * (const Tensor<2,dim, NumberType> &F,
1919 * const Tensor<1,dim, NumberType> &grad_p_fluid) const
1921 * const NumberType det_F = determinant(F);
1922 * Assert(det_F > 0.0, ExcInternalError());
1924 * Tensor<2, dim, NumberType> permeability_term;
1926 * if (fluid_type == "Markert
")
1927 * permeability_term = get_instrinsic_permeability_current(F) / viscosity_FR;
1929 * else if (fluid_type == "Ehlers
")
1930 * permeability_term = get_darcy_flow_current(F) / weight_FR;
1933 * AssertThrow(false, ExcMessage(
1934 * "Material_Darcy_Fluid --> Only Markert
"
1935 * "and Ehlers formulations have been implemented.
"));
1937 * return ( -1.0 * permeability_term * det_F
1938 * * (grad_p_fluid - get_body_force_FR_current()) );
1941 * double get_porous_dissipation(const Tensor<2,dim, NumberType> &F,
1942 * const Tensor<1,dim, NumberType> &grad_p_fluid) const
1944 * NumberType dissipation_term;
1945 * Tensor<1, dim, NumberType> seepage_velocity;
1946 * Tensor<2, dim, NumberType> permeability_term;
1948 * const NumberType det_F = determinant(F);
1949 * Assert(det_F > 0.0, ExcInternalError());
1951 * if (fluid_type == "Markert
")
1953 * permeability_term = get_instrinsic_permeability_current(F) / viscosity_FR;
1954 * seepage_velocity = get_seepage_velocity_current(F,grad_p_fluid);
1956 * else if (fluid_type == "Ehlers
")
1958 * permeability_term = get_darcy_flow_current(F) / weight_FR;
1959 * seepage_velocity = get_seepage_velocity_current(F,grad_p_fluid);
1962 * AssertThrow(false, ExcMessage(
1963 * "Material_Darcy_Fluid --> Only Markert and Ehlers
"
1964 * "formulations have been implemented.
"));
1966 * dissipation_term = ( invert(permeability_term) * seepage_velocity ) * seepage_velocity;
1967 * dissipation_term *= 1.0/(det_F*det_F);
1968 * return Tensor<0,dim,double>(dissipation_term);
1972 * const std::string fluid_type;
1973 * const double n_OS;
1974 * const double initial_intrinsic_permeability;
1975 * const double viscosity_FR;
1976 * const double initial_darcy_coefficient;
1977 * const double weight_FR;
1978 * const double kappa_darcy;
1979 * const bool gravity_term;
1980 * const double density_FR;
1981 * const int gravity_direction;
1982 * const double gravity_value;
1984 * Tensor<2, dim, NumberType>
1985 * get_instrinsic_permeability_current(const Tensor<2,dim, NumberType> &F) const
1987 * static const SymmetricTensor< 2, dim, double>
1988 * I (Physics::Elasticity::StandardTensors<dim>::I);
1989 * const Tensor<2, dim, NumberType> initial_instrinsic_permeability_tensor
1990 * = Tensor<2, dim, double>(initial_intrinsic_permeability * I);
1992 * const NumberType det_F = determinant(F);
1993 * Assert(det_F > 0.0, ExcInternalError());
1995 * const NumberType fraction = (det_F - n_OS)/(1 - n_OS);
1996 * return ( NumberType (std::pow(fraction, kappa_darcy))
1997 * * initial_instrinsic_permeability_tensor );
2000 * Tensor<2, dim, NumberType>
2001 * get_darcy_flow_current(const Tensor<2,dim, NumberType> &F) const
2003 * static const SymmetricTensor< 2, dim, double>
2004 * I (Physics::Elasticity::StandardTensors<dim>::I);
2005 * const Tensor<2, dim, NumberType> initial_darcy_flow_tensor
2006 * = Tensor<2, dim, double>(initial_darcy_coefficient * I);
2008 * const NumberType det_F = determinant(F);
2009 * Assert(det_F > 0.0, ExcInternalError());
2011 * const NumberType fraction = (1.0 - (n_OS / det_F) )/(1.0 - n_OS);
2012 * return ( NumberType (std::pow(fraction, kappa_darcy))
2013 * * initial_darcy_flow_tensor);
2016 * Tensor<1, dim, NumberType>
2017 * get_body_force_FR_current() const
2019 * Tensor<1, dim, NumberType> body_force_FR_current;
2021 * if (gravity_term == true)
2023 * Tensor<1, dim, NumberType> gravity_vector;
2024 * gravity_vector[gravity_direction] = gravity_value;
2025 * body_force_FR_current = density_FR * gravity_vector;
2027 * return body_force_FR_current;
2034 * <a name="Quadraturepointhistory
"></a>
2035 * <h3>Quadrature point history</h3>
2036 * As seen in @ref step_18 "step-18
", the <code> PointHistory </code> class offers a method
2037 * for storing data at the quadrature points. Here each quadrature point
2038 * holds a pointer to a material description. Thus, different material models
2039 * can be used in different regions of the domain. Among other data, we
2040 * choose to store the ``extra" Kirchhoff stress @f$\boldsymbol{\tau}_E@f$ and
2041 * the dissipation
values @f$\mathcal{D}_p@f$ and @f$\mathcal{D}_v@f$.
2044 *
template <
int dim,
typename NumberType = Sacado::Fad::DFad<
double> >
2045 *
class PointHistory
2051 *
virtual ~PointHistory()
2054 *
void setup_lqp (
const Parameters::AllParameters ¶meters,
2057 *
if (parameters.mat_type ==
"Neo-Hooke")
2058 * solid_material.reset(
new NeoHooke<dim,NumberType>(parameters,time));
2059 *
else if (parameters.mat_type ==
"Ogden")
2060 * solid_material.reset(
new Ogden<dim,NumberType>(parameters,time));
2061 *
else if (parameters.mat_type ==
"visco-Ogden")
2062 * solid_material.reset(
new visco_Ogden<dim,NumberType>(parameters,time));
2064 *
Assert (
false, ExcMessage(
"Material type not implemented"));
2066 * fluid_material.reset(
new Material_Darcy_Fluid<dim,NumberType>(parameters));
2072 *
return solid_material->get_tau_E(F);
2078 *
return solid_material->get_Cauchy_E(F);
2082 * get_converged_det_F() const
2084 *
return solid_material->get_converged_det_F();
2088 * update_end_timestep()
2090 * solid_material->update_end_timestep();
2096 * solid_material->update_internal_equilibrium(F);
2100 * get_viscous_dissipation() const
2102 *
return solid_material->get_viscous_dissipation();
2109 *
return fluid_material->get_seepage_velocity_current(F, grad_p_fluid);
2116 *
return fluid_material->get_porous_dissipation(F, grad_p_fluid);
2121 *
const Parameters::AllParameters ¶meters)
const
2125 *
if (parameters.gravity_term ==
true)
2128 *
Assert(det_F_AD > 0.0, ExcInternalError());
2130 *
const NumberType overall_density_ref
2131 * = parameters.density_SR * parameters.solid_vol_frac
2132 * + parameters.density_FR
2133 * * (det_F_AD - parameters.solid_vol_frac);
2136 * gravity_vector[parameters.gravity_direction] = parameters.gravity_value;
2137 * body_force = overall_density_ref * gravity_vector;
2140 *
return body_force;
2143 * std::shared_ptr< Material_Hyperelastic<dim, NumberType> > solid_material;
2144 * std::shared_ptr< Material_Darcy_Fluid<dim, NumberType> > fluid_material;
2150 * <a name=
"Nonlinearporoviscoelasticsolid"></a>
2151 * <h3>Nonlinear poro-viscoelastic solid</h3>
2152 * The Solid
class is the central class as it represents the problem at hand:
2153 * the nonlinear poro-viscoelastic solid
2156 * template <int dim>
2160 * Solid(
const Parameters::AllParameters ¶meters);
2165 *
using ADNumberType = Sacado::Fad::DFad<double>;
2167 * std::ofstream outfile;
2168 * std::ofstream pointfile;
2170 *
struct PerTaskData_ASM;
2171 *
template<
typename NumberType =
double>
struct ScratchData_ASM;
2178 *
virtual void make_grid() = 0;
2182 * Define points
for post-processing
2185 *
virtual void define_tracked_vertices(std::vector<
Point<dim> > &tracked_vertices) = 0;
2189 * Set up the finite element system to be solved:
2196 * Extract sub-blocks from the global
matrix
2199 *
void determine_component_extractors();
2203 * Several
functions to
assemble the system and right hand side matrices
using multithreading.
2206 *
void assemble_system
2208 *
void assemble_system_one_cell
2210 * ScratchData_ASM<ADNumberType> &scratch,
2211 * PerTaskData_ASM &data)
const;
2212 *
void copy_local_to_global_system(
const PerTaskData_ASM &data);
2216 * Define boundary conditions
2219 *
virtual void make_constraints(
const int &it_nr);
2225 *
virtual double get_prescribed_fluid_flow
2229 * get_reaction_boundary_id_for_output ()
const = 0;
2230 *
virtual std::pair<types::boundary_id,types::boundary_id>
2231 * get_drained_boundary_id_for_output ()
const = 0;
2232 *
virtual std::vector<double> get_dirichlet_load
2234 *
const int &direction)
const = 0;
2238 * Create and update the quadrature points.
2245 * Solve non-linear system
using a Newton-Raphson scheme
2252 * Solve the linearized equations
using a direct solver
2259 * Retrieve the solution
2267 * Store the converged
values of the
internal variables at the
end of each timestep
2270 *
void update_end_timestep();
2274 * Post-processing and writing data to files
2277 *
void output_results_to_vtu(
const unsigned int timestep,
2278 *
const double current_time,
2280 *
void output_results_to_plot(
const unsigned int timestep,
2281 *
const double current_time,
2283 * std::vector<
Point<dim> > &tracked_vertices,
2284 * std::ofstream &pointfile)
const;
2288 * Headers and footer
for the output files
2291 *
void print_console_file_header( std::ofstream &outfile)
const;
2292 *
void print_plot_file_header(std::vector<
Point<dim> > &tracked_vertices,
2293 * std::ofstream &pointfile)
const;
2294 *
void print_console_file_footer(std::ofstream &outfile)
const;
2295 *
void print_plot_file_footer( std::ofstream &pointfile)
const;
2309 * A collection of the parameters used to describe the problem setup
2312 *
const Parameters::AllParameters ¶meters;
2323 * Keep track of the current time and the time spent evaluating certain
functions
2332 * A storage
object for quadrature
point information.
2339 * Integers to store polynomial degree (needed
for output)
2342 *
const unsigned int degree_displ;
2343 *
const unsigned int degree_pore;
2347 * Declare an instance of
dealii FESystem class (finite element definition)
2361 * Integer to store DoFs per element (
this value will be used often)
2364 *
const unsigned int dofs_per_cell;
2368 * Declare an instance of
dealii Extractor objects used to retrieve information from the solution vectors
2369 * We will use
"u_fe" and
"p_fluid_fe"as subscript in
operator [] expressions on
FEValues and
FEFaceValues
2370 * objects to
extract the components of the displacement vector and fluid pressure, respectively.
2378 * Description of how the block-system is arranged. There are 3 blocks:
2379 * 0 - vector DOF displacements u
2380 * 1 -
scalar DOF fluid pressure p_fluid
2383 *
static const unsigned int n_blocks = 2;
2384 *
static const unsigned int n_components = dim+1;
2385 *
static const unsigned int first_u_component = 0;
2386 *
static const unsigned int p_fluid_component = dim;
2409 * std::vector<unsigned int> block_component;
2416 * std::vector<IndexSet> all_locally_owned_dofs;
2419 * std::vector<IndexSet> locally_owned_partitioning;
2420 * std::vector<IndexSet> locally_relevant_partitioning;
2422 * std::vector<types::global_dof_index> dofs_per_block;
2423 * std::vector<types::global_dof_index> element_indices_u;
2424 * std::vector<types::global_dof_index> element_indices_p_fluid;
2428 * Declare an instance of
dealii QGauss class (The Gauss-Legendre family of quadrature rules
for numerical integration)
2429 * Gauss Points in element, with n quadrature points (in each space direction <dim> )
2435 * Gauss Points on element faces (used
for definition of BCs)
2438 *
const QGauss<dim - 1> qf_face;
2441 * Integer to store num GPs per element (
this value will be used often)
2444 *
const unsigned int n_q_points;
2447 * Integer to store num GPs per face (
this value will be used often)
2450 *
const unsigned int n_q_points_f;
2454 * Declare an instance of
dealii AffineConstraints class (linear constraints on DoFs due to hanging nodes or BCs)
2461 * Declare an instance of
dealii classes necessary
for FE system
set-up and assembly
2469 * Right hand side vector of forces
2475 * Total displacement
values + pressure (accumulated solution to FE system)
2482 * Non-block system
for the direct solver. We will
copy the block system into these to solve the linearized system of equations.
2490 * We define variables to store norms and update norms and normalisation factors.
2497 *
norm(1.0), u(1.0), p_fluid(1.0)
2506 *
void normalise(
const Errors &rhs)
2508 *
if (rhs.norm != 0.0)
2512 *
if (rhs.p_fluid != 0.0)
2513 * p_fluid /= rhs.p_fluid;
2516 *
double norm, u, p_fluid;
2521 * Declare several instances of the
"Error" structure
2524 * Errors error_residual, error_residual_0, error_residual_norm, error_update,
2525 * error_update_0, error_update_norm;
2529 * Methods to calculate error measures
2532 *
void get_error_residual(Errors &error_residual_OUT);
2533 *
void get_error_update
2535 * Errors &error_update_OUT);
2539 * Print information to screen
2542 *
void print_conv_header();
2543 *
void print_conv_footer();
2547 * NOTE: In all
functions, we pass by reference (&), so these
functions work on the original
copy (not a clone copy),
2556 * <a name=
"ImplementationofthecodeSolidcodeclass"></a>
2557 * <h3>Implementation of the <code>Solid</code>
class</h3>
2559 * <a name=
"Publicinterface"></a>
2560 * <h4>Public interface</h4>
2561 * We initialise the Solid
class using data extracted from the parameter file.
2564 *
template <
int dim>
2565 * Solid<dim>::Solid(
const Parameters::AllParameters ¶meters)
2567 * mpi_communicator(MPI_COMM_WORLD),
2570 * pcout(std::cout, this_mpi_process == 0),
2571 * parameters(parameters),
2573 * time(parameters.end_time, parameters.delta_t),
2574 * timerconsole( mpi_communicator,
2578 * timerfile( mpi_communicator,
2582 * degree_displ(parameters.poly_degree_displ),
2583 * degree_pore(parameters.poly_degree_pore),
2584 * fe(
FE_Q<dim>(parameters.poly_degree_displ), dim,
2585 *
FE_Q<dim>(parameters.poly_degree_pore), 1 ),
2587 * dofs_per_cell (fe.dofs_per_cell),
2588 * u_fe(first_u_component),
2589 * p_fluid_fe(p_fluid_component),
2590 * x_displacement(first_u_component),
2591 * y_displacement(first_u_component+1),
2592 * z_displacement(first_u_component+2),
2593 * pressure(p_fluid_component),
2594 * dofs_per_block(n_blocks),
2595 * qf_cell(parameters.quad_order),
2596 * qf_face(parameters.quad_order),
2597 * n_q_points (qf_cell.size()),
2598 * n_q_points_f (qf_face.size())
2600 *
Assert(dim==3, ExcMessage(
"This problem only works in 3 space dimensions."));
2601 * determine_component_extractors();
2606 * The
class destructor simply clears the data held by the DOFHandler
2609 *
template <
int dim>
2610 * Solid<dim>::~Solid()
2612 * dof_handler_ref.clear();
2617 * Runs the 3D solid problem
2620 *
template <
int dim>
2621 *
void Solid<dim>::run()
2625 * The current solution increment is defined as a block vector to reflect the structure
2626 * of the PDE system, with multiple solution components
2636 *
if (this_mpi_process == 0)
2638 * outfile.open(
"console-output.sol");
2639 * print_console_file_header(outfile);
2651 * Assign DOFs and create the stiffness and right-hand-side force vector
2654 * system_setup(solution_delta);
2658 * Define points
for post-processing
2661 * std::vector<Point<dim> > tracked_vertices (2);
2662 * define_tracked_vertices(tracked_vertices);
2663 * std::vector<Point<dim>> reaction_force;
2665 *
if (this_mpi_process == 0)
2667 * pointfile.open(
"data-for-gnuplot.sol");
2668 * print_plot_file_header(tracked_vertices, pointfile);
2673 * Print results to output file
2676 *
if (parameters.outfiles_requested ==
"true")
2678 * output_results_to_vtu(time.get_timestep(),
2679 * time.get_current(),
2683 * output_results_to_plot(time.get_timestep(),
2684 * time.get_current(),
2691 * Increment time step (=load step)
2692 * NOTE: In solving the quasi-
static problem, the time becomes a loading parameter,
2693 * i.e. we increase the loading linearly with time, making the two
concepts interchangeable.
2696 * time.increment_time();
2700 * Print information on screen
2703 * pcout <<
"\nSolver:";
2704 * pcout <<
"\n CST = make constraints";
2705 * pcout <<
"\n ASM_SYS = assemble system";
2706 * pcout <<
"\n SLV = linear solver \n";
2710 * Print information on file
2713 * outfile <<
"\nSolver:";
2714 * outfile <<
"\n CST = make constraints";
2715 * outfile <<
"\n ASM_SYS = assemble system";
2716 * outfile <<
"\n SLV = linear solver \n";
2718 *
while ( (time.get_end() - time.get_current()) > -1.0*parameters.tol_u )
2722 * Initialize the current solution increment to zero
2725 * solution_delta = 0.0;
2729 * Solve the non-linear system
using a Newton-Rapshon scheme
2732 * solve_nonlinear_timestep(solution_delta);
2736 * Add the computed solution increment to total solution
2739 * solution_n += solution_delta;
2746 * update_end_timestep();
2753 *
if (( (time.get_timestep()%parameters.timestep_output) == 0 )
2754 * && (parameters.outfiles_requested ==
"true") )
2756 * output_results_to_vtu(time.get_timestep(),
2757 * time.get_current(),
2761 * output_results_to_plot(time.get_timestep(),
2762 * time.get_current(),
2769 * Increment the time step (=load step)
2772 * time.increment_time();
2777 * Print the footers and close files
2780 *
if (this_mpi_process == 0)
2782 * print_plot_file_footer(pointfile);
2783 * pointfile.close ();
2784 * print_console_file_footer(outfile);
2788 * NOTE: ideally, we should close the outfile here [ >> outfile.close (); ]
2789 * But
if we
do, then the timer output will not be printed. That is why we leave it open.
2798 * <a name=
"Privateinterface"></a>
2799 * <h4>Private interface</h4>
2800 * We define the structures needed
for parallelization with Threading Building Blocks (TBB)
2801 * Tangent
matrix and right-hand side force vector assembly structures.
2802 * PerTaskData_ASM stores local contributions
2805 *
template <
int dim>
2806 *
struct Solid<dim>::PerTaskData_ASM
2810 * std::vector<types::global_dof_index> local_dof_indices;
2812 * PerTaskData_ASM(
const unsigned int dofs_per_cell)
2815 * cell_rhs(dofs_per_cell),
2816 * local_dof_indices(dofs_per_cell)
2828 * ScratchData_ASM stores larger objects used during the assembly
2831 *
template <
int dim>
2832 *
template <
typename NumberType>
2833 *
struct Solid<dim>::ScratchData_ASM
2839 * Integration helper
2850 * std::vector<NumberType> local_dof_values;
2851 * std::vector<Tensor<2, dim, NumberType> > solution_grads_u_total;
2852 * std::vector<NumberType> solution_values_p_fluid_total;
2853 * std::vector<Tensor<1, dim, NumberType> > solution_grads_p_fluid_total;
2854 * std::vector<Tensor<1, dim, NumberType> > solution_grads_face_p_fluid_total;
2861 * std::vector<std::vector<Tensor<1,dim>>> Nx;
2862 * std::vector<std::vector<double>> Nx_p_fluid;
2868 * std::vector<std::vector<Tensor<2,dim, NumberType>>> grad_Nx;
2869 * std::vector<std::vector<SymmetricTensor<2,dim, NumberType>>> symm_grad_Nx;
2870 * std::vector<std::vector<Tensor<1,dim, NumberType>>> grad_Nx_p_fluid;
2877 * solution_total (solution_total),
2878 * fe_values_ref(fe_cell, qf_cell, uf_cell),
2879 * fe_face_values_ref(fe_cell, qf_face, uf_face),
2880 * local_dof_values(fe_cell.dofs_per_cell),
2881 * solution_grads_u_total(qf_cell.size()),
2882 * solution_values_p_fluid_total(qf_cell.size()),
2883 * solution_grads_p_fluid_total(qf_cell.size()),
2884 * solution_grads_face_p_fluid_total(qf_face.size()),
2885 * Nx(qf_cell.size(), std::vector<
Tensor<1,dim>>(fe_cell.dofs_per_cell)),
2886 * Nx_p_fluid(qf_cell.size(), std::vector<double>(fe_cell.dofs_per_cell)),
2892 * ScratchData_ASM(
const ScratchData_ASM &rhs)
2894 * solution_total (rhs.solution_total),
2895 * fe_values_ref(rhs.fe_values_ref.get_fe(),
2896 * rhs.fe_values_ref.get_quadrature(),
2897 * rhs.fe_values_ref.get_update_flags()),
2898 * fe_face_values_ref(rhs.fe_face_values_ref.get_fe(),
2899 * rhs.fe_face_values_ref.get_quadrature(),
2900 * rhs.fe_face_values_ref.get_update_flags()),
2901 * local_dof_values(rhs.local_dof_values),
2902 * solution_grads_u_total(rhs.solution_grads_u_total),
2903 * solution_values_p_fluid_total(rhs.solution_values_p_fluid_total),
2904 * solution_grads_p_fluid_total(rhs.solution_grads_p_fluid_total),
2905 * solution_grads_face_p_fluid_total(rhs.solution_grads_face_p_fluid_total),
2907 * Nx_p_fluid(rhs.Nx_p_fluid),
2908 * grad_Nx(rhs.grad_Nx),
2909 * symm_grad_Nx(rhs.symm_grad_Nx),
2910 * grad_Nx_p_fluid(rhs.grad_Nx_p_fluid)
2915 *
const unsigned int n_q_points = Nx_p_fluid.size();
2916 *
const unsigned int n_dofs_per_cell = Nx_p_fluid[0].size();
2918 *
Assert(local_dof_values.size() == n_dofs_per_cell, ExcInternalError());
2920 *
for (
unsigned int k = 0; k < n_dofs_per_cell; ++k)
2922 * local_dof_values[k] = 0.0;
2925 *
Assert(solution_grads_u_total.size() == n_q_points, ExcInternalError());
2926 *
Assert(solution_values_p_fluid_total.size() == n_q_points, ExcInternalError());
2927 *
Assert(solution_grads_p_fluid_total.size() == n_q_points, ExcInternalError());
2929 *
Assert(Nx.size() == n_q_points, ExcInternalError());
2930 *
Assert(grad_Nx.size() == n_q_points, ExcInternalError());
2931 *
Assert(symm_grad_Nx.size() == n_q_points, ExcInternalError());
2933 *
for (
unsigned int q_point = 0; q_point < n_q_points; ++q_point)
2935 *
Assert( Nx[q_point].size() == n_dofs_per_cell, ExcInternalError());
2936 *
Assert( grad_Nx[q_point].size() == n_dofs_per_cell, ExcInternalError());
2937 *
Assert( symm_grad_Nx[q_point].size() == n_dofs_per_cell, ExcInternalError());
2939 * solution_grads_u_total[q_point] = 0.0;
2940 * solution_values_p_fluid_total[q_point] = 0.0;
2941 * solution_grads_p_fluid_total[q_point] = 0.0;
2943 *
for (
unsigned int k = 0; k < n_dofs_per_cell; ++k)
2945 * Nx[q_point][k] = 0.0;
2946 * Nx_p_fluid[q_point][k] = 0.0;
2947 * grad_Nx[q_point][k] = 0.0;
2948 * symm_grad_Nx[q_point][k] = 0.0;
2949 * grad_Nx_p_fluid[q_point][k] = 0.0;
2953 *
const unsigned int n_f_q_points = solution_grads_face_p_fluid_total.size();
2954 *
Assert(solution_grads_face_p_fluid_total.size() == n_f_q_points, ExcInternalError());
2956 *
for (
unsigned int f_q_point = 0; f_q_point < n_f_q_points; ++f_q_point)
2957 * solution_grads_face_p_fluid_total[f_q_point] = 0.0;
2963 * Define the boundary conditions on the mesh
2966 *
template <
int dim>
2967 *
void Solid<dim>::make_constraints(
const int &it_nr_IN)
2969 * pcout <<
" CST " << std::flush;
2970 * outfile <<
" CST " << std::flush;
2972 *
if (it_nr_IN > 1)
return;
2974 *
const bool apply_dirichlet_bc = (it_nr_IN == 0);
2976 *
if (apply_dirichlet_bc)
2978 * constraints.clear();
2979 * make_dirichlet_constraints(constraints);
2983 *
for (
unsigned int i=0; i<dof_handler_ref.n_dofs(); ++i)
2984 *
if (constraints.is_inhomogeneously_constrained(i) ==
true)
2985 * constraints.set_inhomogeneity(i,0.0);
2987 * constraints.close();
2992 * Set-up the FE system
2995 *
template <
int dim>
2998 * timerconsole.enter_subsection(
"Setup system");
2999 * timerfile.enter_subsection(
"Setup system");
3003 * Determine number of components per block
3006 * std::vector<unsigned int> block_component(n_components, u_block);
3007 * block_component[p_fluid_component] = p_fluid_block;
3011 * The DOF handler is initialised and we renumber the grid in an efficient manner.
3014 * dof_handler_ref.distribute_dofs(fe);
3020 * Count the number of DoFs in each block
3027 * Setup the sparsity pattern and tangent
matrix
3031 * std::vector<IndexSet> all_locally_relevant_dofs
3034 * locally_owned_dofs.clear();
3035 * locally_owned_partitioning.clear();
3036 *
Assert(all_locally_owned_dofs.size() > this_mpi_process, ExcInternalError());
3039 * locally_relevant_dofs.clear();
3040 * locally_relevant_partitioning.clear();
3041 *
Assert(all_locally_relevant_dofs.size() > this_mpi_process, ExcInternalError());
3044 * locally_owned_partitioning.reserve(n_blocks);
3045 * locally_relevant_partitioning.reserve(n_blocks);
3050 * = std::accumulate(dofs_per_block.begin(),
3051 * std::next(dofs_per_block.begin(),b), 0);
3053 * = std::accumulate(dofs_per_block.begin(),
3054 * std::next(dofs_per_block.begin(),b+1), 0);
3055 * locally_owned_partitioning.push_back(locally_owned_dofs.get_view(idx_begin, idx_end));
3056 * locally_relevant_partitioning.push_back(locally_relevant_dofs.get_view(idx_begin, idx_end));
3061 * Print information on screen
3064 * pcout <<
"\nTriangulation:\n"
3065 * <<
" Number of active cells: "
3067 * <<
" (by partition:";
3069 * pcout << (p==0 ?
' ' :
'+')
3073 * pcout <<
" Number of degrees of freedom: "
3074 * << dof_handler_ref.n_dofs()
3075 * <<
" (by partition:";
3077 * pcout << (p==0 ?
' ' :
'+')
3081 * pcout <<
" Number of degrees of freedom per block: "
3082 * <<
"[n_u, n_p_fluid] = ["
3083 * << dofs_per_block[u_block]
3085 * << dofs_per_block[p_fluid_block]
3091 * Print information to file
3094 * outfile <<
"\nTriangulation:\n"
3095 * <<
" Number of active cells: "
3097 * <<
" (by partition:";
3099 * outfile << (p==0 ?
' ' :
'+')
3103 * outfile <<
" Number of degrees of freedom: "
3104 * << dof_handler_ref.n_dofs()
3105 * <<
" (by partition:";
3107 * outfile << (p==0 ?
' ' :
'+')
3111 * outfile <<
" Number of degrees of freedom per block: "
3112 * <<
"[n_u, n_p_fluid] = ["
3113 * << dofs_per_block[u_block]
3115 * << dofs_per_block[p_fluid_block]
3121 * We optimise the sparsity pattern to reflect
this structure and prevent
3122 * unnecessary data creation
for the right-
diagonal block components.
3126 *
for (
unsigned int ii = 0; ii < n_components; ++ii)
3127 *
for (
unsigned int jj = 0; jj < n_components; ++jj)
3131 * Identify
"zero" matrix components of FE-system (The two components
do not couple)
3134 *
if (((ii == p_fluid_component) && (jj < p_fluid_component))
3135 * || ((ii < p_fluid_component) && (jj == p_fluid_component)) )
3140 * The rest of components
always couple
3147 * mpi_communicator);
3150 *
false, this_mpi_process);
3155 * Reinitialize the (sparse) tangent
matrix with the given sparsity pattern.
3158 * tangent_matrix.reinit (bsp);
3162 * Initialize the right hand side and solution vectors with number of DoFs
3165 * system_rhs.reinit(locally_owned_partitioning, mpi_communicator);
3166 * solution_n.reinit(locally_owned_partitioning, mpi_communicator);
3167 * solution_delta_OUT.reinit(locally_owned_partitioning, mpi_communicator);
3175 * mpi_communicator);
3177 *
false, this_mpi_process);
3179 * tangent_matrix_nb.reinit (sp);
3180 * system_rhs_nb.reinit(locally_owned_dofs, mpi_communicator);
3184 * Set up the quadrature
point history
3189 * timerconsole.leave_subsection();
3190 * timerfile.leave_subsection();
3195 * Component extractors: used to
extract sub-blocks from the global
matrix
3196 * Description of which local element DOFs are attached to which block component
3199 *
template <
int dim>
3200 *
void Solid<dim>::determine_component_extractors()
3202 * element_indices_u.clear();
3203 * element_indices_p_fluid.clear();
3205 *
for (
unsigned int k = 0; k < fe.dofs_per_cell; ++k)
3207 *
const unsigned int k_group = fe.system_to_base_index(k).first.first;
3208 *
if (k_group == u_block)
3209 * element_indices_u.push_back(k);
3210 *
else if (k_group == p_fluid_block)
3211 * element_indices_p_fluid.push_back(k);
3214 *
Assert(k_group <= p_fluid_block, ExcInternalError());
3221 * Set-up quadrature
point history (QPH) data objects
3224 *
template <
int dim>
3225 *
void Solid<dim>::setup_qph()
3227 * pcout <<
"\nSetting up quadrature point data..." << std::endl;
3228 * outfile <<
"\nSetting up quadrature point data..." << std::endl;
3232 * Create QPH data objects.
3235 * quadrature_point_history.initialize(
triangulation.begin_active(),
3240 * Setup the
initial quadrature
point data
using the info stored in parameters
3245 * dof_handler_ref.begin_active()),
3247 * dof_handler_ref.end());
3248 *
for (; cell!=endc; ++cell)
3250 *
Assert(cell->is_locally_owned(), ExcInternalError());
3251 *
Assert(cell->subdomain_id() == this_mpi_process, ExcInternalError());
3253 *
const std::vector<std::shared_ptr<PointHistory<dim, ADNumberType> > >
3254 * lqph = quadrature_point_history.get_data(cell);
3255 *
Assert(lqph.size() == n_q_points, ExcInternalError());
3257 *
for (
unsigned int q_point = 0; q_point < n_q_points; ++q_point)
3258 * lqph[q_point]->setup_lqp(parameters, time);
3264 * Solve the non-linear system
using a Newton-Raphson scheme
3267 *
template <
int dim>
3272 * Print the load step
3275 * pcout << std::endl
3277 * << time.get_timestep()
3279 * << time.get_current()
3282 * outfile << std::endl
3284 * << time.get_timestep()
3286 * << time.get_current()
3292 * Declare newton_update vector (solution of a Newton iteration),
3293 * which must have as many positions as global DoFs.
3297 * (locally_owned_partitioning, mpi_communicator);
3301 * Reset the error storage objects
3304 * error_residual.reset();
3305 * error_residual_0.reset();
3306 * error_residual_norm.reset();
3307 * error_update.reset();
3308 * error_update_0.reset();
3309 * error_update_norm.reset();
3311 * print_conv_header();
3315 * Declare and initialize iterator
for the Newton-Raphson algorithm steps
3318 *
unsigned int newton_iteration = 0;
3322 * Iterate until error is below tolerance or
max number iterations are reached
3325 *
while(newton_iteration < parameters.max_iterations_NR)
3327 * pcout <<
" " << std::setw(2) << newton_iteration <<
" " << std::flush;
3328 * outfile <<
" " << std::setw(2) << newton_iteration <<
" " << std::flush;
3332 * Initialize global stiffness
matrix and global force vector to zero
3335 * tangent_matrix = 0.0;
3338 * tangent_matrix_nb = 0.0;
3339 * system_rhs_nb = 0.0;
3343 * Apply boundary conditions
3346 * make_constraints(newton_iteration);
3347 * assemble_system(solution_delta_OUT);
3351 * Compute the rhs residual (error between external and
internal forces in FE system)
3354 * get_error_residual(error_residual);
3358 * error_residual in
first iteration is stored to normalize posterior error measures
3361 *
if (newton_iteration == 0)
3362 * error_residual_0 = error_residual;
3366 * Determine the normalised residual error
3369 * error_residual_norm = error_residual;
3370 * error_residual_norm.normalise(error_residual_0);
3374 * If both errors are below the tolerances, exit the
loop.
3375 * We need to
check the residual vector directly
for convergence
3376 * in the load steps where no external forces or displacements are imposed.
3379 *
if ( ((newton_iteration > 0)
3380 * && (error_update_norm.u <= parameters.tol_u)
3381 * && (error_update_norm.p_fluid <= parameters.tol_p_fluid)
3382 * && (error_residual_norm.u <= parameters.tol_f)
3383 * && (error_residual_norm.p_fluid <= parameters.tol_f))
3384 * || ( (newton_iteration > 0)
3385 * && system_rhs.l2_norm() <= parameters.tol_f) )
3387 * pcout <<
"\n ***** CONVERGED! ***** "
3388 * << system_rhs.l2_norm() <<
" "
3389 * <<
" " << error_residual_norm.norm
3390 * <<
" " << error_residual_norm.u
3391 * <<
" " << error_residual_norm.p_fluid
3392 * <<
" " << error_update_norm.norm
3393 * <<
" " << error_update_norm.u
3394 * <<
" " << error_update_norm.p_fluid
3395 * <<
" " << std::endl;
3396 * outfile <<
"\n ***** CONVERGED! ***** "
3397 * << system_rhs.l2_norm() <<
" "
3398 * <<
" " << error_residual_norm.norm
3399 * <<
" " << error_residual_norm.u
3400 * <<
" " << error_residual_norm.p_fluid
3401 * <<
" " << error_update_norm.norm
3402 * <<
" " << error_update_norm.u
3403 * <<
" " << error_update_norm.p_fluid
3404 * <<
" " << std::endl;
3405 * print_conv_footer();
3412 * Solve the linearized system
3415 * solve_linear_system(newton_update);
3416 * constraints.distribute(newton_update);
3420 * Compute the displacement error
3423 * get_error_update(newton_update, error_update);
3427 * error_update in
first iteration is stored to normalize posterior error measures
3430 *
if (newton_iteration == 0)
3431 * error_update_0 = error_update;
3435 * Determine the normalised Newton update error
3438 * error_update_norm = error_update;
3439 * error_update_norm.normalise(error_update_0);
3443 * Determine the normalised residual error
3446 * error_residual_norm = error_residual;
3447 * error_residual_norm.normalise(error_residual_0);
3454 * pcout <<
" | " << std::fixed << std::setprecision(3)
3455 * << std::setw(7) << std::scientific
3456 * << system_rhs.l2_norm()
3457 * <<
" " << error_residual_norm.norm
3458 * <<
" " << error_residual_norm.u
3459 * <<
" " << error_residual_norm.p_fluid
3460 * <<
" " << error_update_norm.norm
3461 * <<
" " << error_update_norm.u
3462 * <<
" " << error_update_norm.p_fluid
3463 * <<
" " << std::endl;
3465 * outfile <<
" | " << std::fixed << std::setprecision(3)
3466 * << std::setw(7) << std::scientific
3467 * << system_rhs.l2_norm()
3468 * <<
" " << error_residual_norm.norm
3469 * <<
" " << error_residual_norm.u
3470 * <<
" " << error_residual_norm.p_fluid
3471 * <<
" " << error_update_norm.norm
3472 * <<
" " << error_update_norm.u
3473 * <<
" " << error_update_norm.p_fluid
3474 * <<
" " << std::endl;
3481 * solution_delta_OUT += newton_update;
3482 * newton_update = 0.0;
3483 * newton_iteration++;
3488 * If maximum allowed number of iterations
for Newton algorithm are reached, print non-convergence message and
abort program
3491 *
AssertThrow (newton_iteration < parameters.max_iterations_NR, ExcMessage(
"No convergence in nonlinear solver!"));
3496 * Prints the header
for convergence info on console
3499 *
template <
int dim>
3500 *
void Solid<dim>::print_conv_header()
3502 *
static const unsigned int l_width = 120;
3504 *
for (
unsigned int i = 0; i < l_width; ++i)
3510 * pcout << std::endl;
3511 * outfile << std::endl;
3513 * pcout <<
"\n SOLVER STEP | SYS_RES "
3514 * <<
"RES_NORM RES_U RES_P "
3515 * <<
"NU_NORM NU_U NU_P " << std::endl;
3516 * outfile <<
"\n SOLVER STEP | SYS_RES "
3517 * <<
"RES_NORM RES_U RES_P "
3518 * <<
"NU_NORM NU_U NU_P " << std::endl;
3520 *
for (
unsigned int i = 0; i < l_width; ++i)
3525 * pcout << std::endl << std::endl;
3526 * outfile << std::endl << std::endl;
3531 * Prints the footer
for convergence info on console
3534 *
template <
int dim>
3535 *
void Solid<dim>::print_conv_footer()
3537 *
static const unsigned int l_width = 120;
3539 *
for (
unsigned int i = 0; i < l_width; ++i)
3544 * pcout << std::endl << std::endl;
3545 * outfile << std::endl << std::endl;
3547 * pcout <<
"Relative errors:" << std::endl
3548 * <<
"Displacement: "
3549 * << error_update.u / error_update_0.u << std::endl
3550 * <<
"Force (displ): "
3551 * << error_residual.u / error_residual_0.u << std::endl
3552 * <<
"Pore pressure: "
3553 * << error_update.p_fluid / error_update_0.p_fluid << std::endl
3554 * <<
"Force (pore): "
3555 * << error_residual.p_fluid / error_residual_0.p_fluid << std::endl;
3556 * outfile <<
"Relative errors:" << std::endl
3557 * <<
"Displacement: "
3558 * << error_update.u / error_update_0.u << std::endl
3559 * <<
"Force (displ): "
3560 * << error_residual.u / error_residual_0.u << std::endl
3561 * <<
"Pore pressure: "
3562 * << error_update.p_fluid / error_update_0.p_fluid << std::endl
3563 * <<
"Force (pore): "
3564 * << error_residual.p_fluid / error_residual_0.p_fluid << std::endl;
3569 * Determine the
true residual error
for the problem
3572 *
template <
int dim>
3573 *
void Solid<dim>::get_error_residual(Errors &error_residual_OUT)
3576 * constraints.set_zero(error_res);
3578 * error_residual_OUT.norm = error_res.l2_norm();
3579 * error_residual_OUT.u = error_res.block(u_block).l2_norm();
3580 * error_residual_OUT.p_fluid = error_res.block(p_fluid_block).l2_norm();
3585 * Determine the
true Newton update error
for the problem
3588 *
template <
int dim>
3589 *
void Solid<dim>::get_error_update
3591 * Errors &error_update_OUT)
3594 * constraints.set_zero(error_ud);
3596 * error_update_OUT.norm = error_ud.l2_norm();
3597 * error_update_OUT.u = error_ud.block(u_block).l2_norm();
3598 * error_update_OUT.p_fluid = error_ud.block(p_fluid_block).l2_norm();
3603 * Compute the total solution, which is
valid at any Newton step. This is required as, to
reduce
3604 * computational error, the total solution is only updated at the
end of the timestep.
3607 *
template <
int dim>
3613 * Cell interpolation -> Ghosted vector
3617 * solution_total (locally_owned_partitioning,
3618 * locally_relevant_partitioning,
3622 * solution_total = solution_n;
3623 * tmp = solution_delta_IN;
3624 * solution_total += tmp;
3625 *
return solution_total;
3630 * Compute elemental stiffness tensor and right-hand side force vector, and
assemble into global ones
3633 *
template <
int dim>
3636 * timerconsole.enter_subsection(
"Assemble system");
3637 * timerfile.enter_subsection(
"Assemble system");
3638 * pcout <<
" ASM_SYS " << std::flush;
3639 * outfile <<
" ASM_SYS " << std::flush;
3645 * Info given to
FEValues and
FEFaceValues constructors, to indicate which data will be needed at each element.
3659 * Setup a
copy of the data structures required
for the process and pass them, along with the
3663 * PerTaskData_ASM per_task_data(dofs_per_cell);
3664 * ScratchData_ASM<ADNumberType> scratch_data(fe, qf_cell, uf_cell,
3670 * dof_handler_ref.begin_active()),
3672 * dof_handler_ref.end());
3673 *
for (; cell != endc; ++cell)
3675 *
Assert(cell->is_locally_owned(), ExcInternalError());
3676 *
Assert(cell->subdomain_id() == this_mpi_process, ExcInternalError());
3678 * assemble_system_one_cell(cell, scratch_data, per_task_data);
3679 * copy_local_to_global_system(per_task_data);
3687 * timerconsole.leave_subsection();
3688 * timerfile.leave_subsection();
3693 * Add the local elemental contribution to the global stiffness tensor
3694 * We
do it twice,
for the block and the non-block systems
3697 *
template <
int dim>
3698 *
void Solid<dim>::copy_local_to_global_system (
const PerTaskData_ASM &data)
3700 * constraints.distribute_local_to_global(data.cell_matrix,
3702 * data.local_dof_indices,
3706 * constraints.distribute_local_to_global(data.cell_matrix,
3708 * data.local_dof_indices,
3709 * tangent_matrix_nb,
3715 * Compute stiffness
matrix and corresponding rhs
for one element
3718 *
template <
int dim>
3719 *
void Solid<dim>::assemble_system_one_cell
3721 * ScratchData_ASM<ADNumberType> &scratch,
3722 * PerTaskData_ASM &data)
const
3724 *
Assert(cell->is_locally_owned(), ExcInternalError());
3728 * scratch.fe_values_ref.reinit(cell);
3729 * cell->get_dof_indices(data.local_dof_indices);
3733 * Setup automatic differentiation
3736 *
for (
unsigned int k = 0; k < dofs_per_cell; ++k)
3740 * Initialise the dofs
for the cell
using the current solution.
3743 * scratch.local_dof_values[k] = scratch.solution_total[data.local_dof_indices[k]];
3746 * Mark
this cell DoF as an independent variable
3749 * scratch.local_dof_values[k].diff(k, dofs_per_cell);
3754 * Update the quadrature
point solution
3755 * Compute the
values and
gradients of the solution in terms of the AD variables
3758 *
for (
unsigned int q = 0; q < n_q_points; ++q)
3760 *
for (
unsigned int k = 0; k < dofs_per_cell; ++k)
3762 *
const unsigned int k_group = fe.system_to_base_index(k).first.first;
3763 *
if (k_group == u_block)
3766 * scratch.fe_values_ref[u_fe].gradient(k, q);
3767 *
for (
unsigned int dd = 0; dd < dim; ++dd)
3769 *
for (
unsigned int ee = 0; ee < dim; ++ee)
3771 * scratch.solution_grads_u_total[q][dd][ee]
3772 * += scratch.local_dof_values[k] * Grad_Nx_u[dd][ee];
3776 *
else if (k_group == p_fluid_block)
3778 *
const double Nx_p = scratch.fe_values_ref[p_fluid_fe].value(k, q);
3780 * scratch.fe_values_ref[p_fluid_fe].gradient(k, q);
3782 * scratch.solution_values_p_fluid_total[q]
3783 * += scratch.local_dof_values[k] * Nx_p;
3784 *
for (
unsigned int dd = 0; dd < dim; ++dd)
3786 * scratch.solution_grads_p_fluid_total[q][dd]
3787 * += scratch.local_dof_values[k] * Grad_Nx_p[dd];
3791 *
Assert(k_group <= p_fluid_block, ExcInternalError());
3797 * Set up pointer
"lgph" to the PointHistory
object of
this element
3800 *
const std::vector<std::shared_ptr<const PointHistory<dim, ADNumberType> > >
3801 * lqph = quadrature_point_history.get_data(cell);
3802 *
Assert(lqph.size() == n_q_points, ExcInternalError());
3810 *
for (
unsigned int q_point = 0; q_point < n_q_points; ++q_point)
3817 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i)
3819 *
const unsigned int i_group = fe.system_to_base_index(i).first.first;
3821 *
if (i_group == u_block)
3823 * scratch.Nx[q_point][i] =
3824 * scratch.fe_values_ref[u_fe].value(i, q_point);
3825 * scratch.grad_Nx[q_point][i] =
3826 * scratch.fe_values_ref[u_fe].gradient(i, q_point)*F_inv_AD;
3827 * scratch.symm_grad_Nx[q_point][i] =
3830 *
else if (i_group == p_fluid_block)
3832 * scratch.Nx_p_fluid[q_point][i] =
3833 * scratch.fe_values_ref[p_fluid_fe].value(i, q_point);
3834 * scratch.grad_Nx_p_fluid[q_point][i] =
3835 * scratch.fe_values_ref[p_fluid_fe].gradient(i, q_point)*F_inv_AD;
3838 *
Assert(i_group <= p_fluid_block, ExcInternalError());
3844 * Assemble the stiffness
matrix and rhs vector
3847 * std::vector<ADNumberType> residual_ad (dofs_per_cell, ADNumberType(0.0));
3848 *
for (
unsigned int q_point = 0; q_point < n_q_points; ++q_point)
3852 *
const ADNumberType det_F_AD =
determinant(F_AD);
3854 *
Assert(det_F_AD > 0, ExcInternalError());
3857 *
const ADNumberType p_fluid = scratch.solution_values_p_fluid_total[q_point];
3860 * PointHistory<dim, ADNumberType> *lqph_q_point_nc =
3861 *
const_cast<PointHistory<dim, ADNumberType>*
>(lqph[q_point].get());
3862 * lqph_q_point_nc->update_internal_equilibrium(F_AD);
3867 * Get some info from constitutive model of solid
3873 * tau_E = lqph[q_point]->get_tau_E(F_AD);
3875 * tau_fluid_vol *= -1.0 * p_fluid * det_F_AD;
3879 * Get some info from constitutive model of fluid
3882 *
const ADNumberType det_F_aux = lqph[q_point]->get_converged_det_F();
3885 * = lqph[q_point]->get_overall_body_force(F_AD, parameters);
3889 * Define some aliases to make the assembly process easier to follow
3892 *
const std::vector<Tensor<1,dim>> &Nu = scratch.Nx[q_point];
3893 *
const std::vector<SymmetricTensor<2, dim, ADNumberType>>
3894 * &symm_grad_Nu = scratch.symm_grad_Nx[q_point];
3895 *
const std::vector<double> &Np = scratch.Nx_p_fluid[q_point];
3896 *
const std::vector<Tensor<1, dim, ADNumberType> > &grad_Np
3897 * = scratch.grad_Nx_p_fluid[q_point];
3899 * = scratch.solution_grads_p_fluid_total[q_point]*F_inv_AD;
3900 *
const double JxW = scratch.fe_values_ref.JxW(q_point);
3902 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i)
3904 *
const unsigned int i_group = fe.system_to_base_index(i).first.first;
3906 *
if (i_group == u_block)
3908 * residual_ad[i] += symm_grad_Nu[i] * ( tau_E + tau_fluid_vol ) * JxW;
3909 * residual_ad[i] -= Nu[i] * overall_body_force * JxW;
3911 *
else if (i_group == p_fluid_block)
3914 * = lqph[q_point]->get_seepage_velocity_current(F_AD, grad_p);
3915 * residual_ad[i] += Np[i] * (det_F_AD - det_F_converged) * JxW;
3916 * residual_ad[i] -= time.get_delta_t() * grad_Np[i]
3917 * * seepage_vel_current * JxW;
3920 *
Assert(i_group <= p_fluid_block, ExcInternalError());
3926 * Assemble the Neumann contribution (external force contribution).
3929 *
for (
unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
3931 *
if (cell->face(face)->at_boundary() ==
true)
3933 * scratch.fe_face_values_ref.reinit(cell, face);
3935 *
for (
unsigned int f_q_point = 0; f_q_point < n_q_points_f; ++f_q_point)
3938 * = scratch.fe_face_values_ref.normal_vector(f_q_point);
3940 * = scratch.fe_face_values_ref.quadrature_point(f_q_point);
3942 * = get_neumann_traction(cell->face(face)->boundary_id(), pt, N);
3944 * = get_prescribed_fluid_flow(cell->face(face)->boundary_id(), pt);
3946 *
if ( (traction.norm() < 1e-12) && (
std::abs(flow) < 1e-12) )
continue;
3948 *
const double JxW_f = scratch.fe_face_values_ref.JxW(f_q_point);
3950 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i)
3952 *
const unsigned int i_group = fe.system_to_base_index(i).first.first;
3954 *
if ((i_group == u_block) && (traction.norm() > 1e-12))
3956 *
const unsigned int component_i
3957 * = fe.system_to_component_index(i).first;
3959 * = scratch.fe_face_values_ref.shape_value(i, f_q_point);
3960 * residual_ad[i] -= (Nu_f * traction[component_i]) * JxW_f;
3962 *
if ((i_group == p_fluid_block) && (
std::abs(flow) > 1
e-12))
3965 * = scratch.fe_face_values_ref.shape_value(i, f_q_point);
3966 * residual_ad[i] -= (Nu_p * flow) * JxW_f;
3975 * Linearise the residual
3978 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i)
3980 *
const ADNumberType &R_i = residual_ad[i];
3982 * data.cell_rhs(i) -= R_i.val();
3983 *
for (
unsigned int j=0; j<dofs_per_cell; ++j)
3984 * data.cell_matrix(i,j) += R_i.fastAccessDx(j);
3993 *
template <
int dim>
3994 *
void Solid<dim>::update_end_timestep()
3998 * dof_handler_ref.begin_active()),
4000 * dof_handler_ref.end());
4001 *
for (; cell!=endc; ++cell)
4003 *
Assert(cell->is_locally_owned(), ExcInternalError());
4004 *
Assert(cell->subdomain_id() == this_mpi_process, ExcInternalError());
4006 *
const std::vector<std::shared_ptr<PointHistory<dim, ADNumberType> > >
4007 * lqph = quadrature_point_history.get_data(cell);
4008 *
Assert(lqph.size() == n_q_points, ExcInternalError());
4009 *
for (
unsigned int q_point = 0; q_point < n_q_points; ++q_point)
4010 * lqph[q_point]->update_end_timestep();
4017 * Solve the linearized equations
4020 *
template <
int dim>
4024 * timerconsole.enter_subsection(
"Linear solver");
4025 * timerfile.enter_subsection(
"Linear solver");
4026 * pcout <<
" SLV " << std::flush;
4027 * outfile <<
" SLV " << std::flush;
4030 * newton_update_nb.
reinit(locally_owned_dofs, mpi_communicator);
4033 * 1.0e-6 * system_rhs_nb.l2_norm());
4035 * solver.solve(tangent_matrix_nb, newton_update_nb, system_rhs_nb);
4039 * Copy the non-block solution back to block system
4042 *
for (
unsigned int i=0; i<locally_owned_dofs.n_elements(); ++i)
4045 * = locally_owned_dofs.nth_index_in_set(i);
4046 * newton_update_OUT(idx_i) = newton_update_nb(idx_i);
4050 * timerconsole.leave_subsection();
4051 * timerfile.leave_subsection();
4056 * Class to compute
gradient of the pressure
4059 *
template <
int dim>
4063 * GradientPostprocessor (
const unsigned int p_fluid_component)
4067 * p_fluid_component (p_fluid_component)
4070 *
virtual ~GradientPostprocessor(){}
4073 * evaluate_vector_field
4075 * std::vector<
Vector<double> > &computed_quantities)
const override
4078 * computed_quantities.size());
4079 *
for (
unsigned int p=0; p<input_data.solution_gradients.size(); ++p)
4082 *
for (
unsigned int d=0;
d<dim; ++
d)
4083 * computed_quantities[p][d]
4084 * = input_data.solution_gradients[p][p_fluid_component][d];
4089 *
const unsigned int p_fluid_component;
4095 * Print results to
vtu file
4098 *
template <
int dim>
void Solid<dim>::output_results_to_vtu
4099 * (
const unsigned int timestep,
4100 *
const double current_time,
4104 * locally_relevant_partitioning,
4107 * solution_total = solution_IN;
4110 * std::vector<types::subdomain_id> partition_int(
triangulation.n_active_cells());
4111 * GradientPostprocessor<dim> gradient_postprocessor(p_fluid_component);
4115 * Declare local variables with number of stress components
4119 *
unsigned int num_comp_symm_tensor = 6;
4123 * Declare local vectors to store
values
4124 * OUTPUT AVERAGED ON ELEMENTS -------------------------------------------
4127 * std::vector<Vector<double>>cauchy_stresses_total_elements
4128 * (num_comp_symm_tensor,
4130 * std::vector<Vector<double>>cauchy_stresses_E_elements
4131 * (num_comp_symm_tensor,
4133 * std::vector<Vector<double>>stretches_elements
4136 * std::vector<Vector<double>>seepage_velocity_elements
4148 * OUTPUT AVERAGED ON NODES ----------------------------------------------
4149 * We need to create a
new FE space with a single dof per node to avoid
4150 * duplication of the output on nodes
for our problem with dim+1 dofs.
4155 * vertex_handler_ref.distribute_dofs(fe_vertex);
4157 * ExcDimensionMismatch(vertex_handler_ref.n_dofs(),
4161 * (vertex_handler_ref.n_dofs());
4163 * (vertex_handler_ref.n_dofs());
4165 * std::vector<Vector<double>>cauchy_stresses_total_vertex_mpi
4166 * (num_comp_symm_tensor,
4168 * std::vector<Vector<double>>sum_cauchy_stresses_total_vertex
4169 * (num_comp_symm_tensor,
4171 * std::vector<Vector<double>>cauchy_stresses_E_vertex_mpi
4172 * (num_comp_symm_tensor,
4174 * std::vector<Vector<double>>sum_cauchy_stresses_E_vertex
4175 * (num_comp_symm_tensor,
4177 * std::vector<Vector<double>>stretches_vertex_mpi
4180 * std::vector<Vector<double>>sum_stretches_vertex
4183 *
Vector<double> porous_dissipation_vertex_mpi(vertex_handler_ref.n_dofs());
4184 *
Vector<double> sum_porous_dissipation_vertex(vertex_handler_ref.n_dofs());
4185 *
Vector<double> viscous_dissipation_vertex_mpi(vertex_handler_ref.n_dofs());
4186 *
Vector<double> sum_viscous_dissipation_vertex(vertex_handler_ref.n_dofs());
4187 *
Vector<double> solid_vol_fraction_vertex_mpi(vertex_handler_ref.n_dofs());
4188 *
Vector<double> sum_solid_vol_fraction_vertex(vertex_handler_ref.n_dofs());
4192 * We need to create a
new FE space with a dim dof per node to
4193 * be able to ouput data on nodes in vector form
4198 * vertex_vec_handler_ref.distribute_dofs(fe_vertex_vec);
4200 * ExcDimensionMismatch(vertex_vec_handler_ref.n_dofs(),
4203 *
Vector<double> seepage_velocity_vertex_vec_mpi(vertex_vec_handler_ref.n_dofs());
4204 *
Vector<double> sum_seepage_velocity_vertex_vec(vertex_vec_handler_ref.n_dofs());
4205 *
Vector<double> counter_on_vertices_vec_mpi(vertex_vec_handler_ref.n_dofs());
4206 *
Vector<double> sum_counter_on_vertices_vec(vertex_vec_handler_ref.n_dofs());
4209 * -----------------------------------------------------------------------
4213 * Declare and initialize local unit vectors (to construct tensor basis)
4216 * std::vector<Tensor<1,dim>> basis_vectors (dim,
Tensor<1,dim>() );
4217 *
for (
unsigned int i=0; i<dim; ++i)
4218 * basis_vectors[i][i] = 1;
4222 * Declare an instance of the material
class object
4225 *
if (parameters.mat_type ==
"Neo-Hooke")
4226 * NeoHooke<dim,ADNumberType> material(parameters,time);
4227 *
else if (parameters.mat_type ==
"Ogden")
4228 * Ogden<dim,ADNumberType> material(parameters,time);
4229 *
else if (parameters.mat_type ==
"visco-Ogden")
4230 * visco_Ogden <dim,ADNumberType>material(parameters,time);
4232 *
Assert (
false, ExcMessage(
"Material type not implemented"));
4236 * Define a local instance of
FEValues to compute updated
values required
4237 * to calculate stresses
4246 * Iterate through elements (cells) and Gauss Points
4251 * dof_handler_ref.begin_active()),
4253 * dof_handler_ref.end()),
4255 * vertex_handler_ref.begin_active()),
4257 * vertex_vec_handler_ref.begin_active());
4263 *
for (; cell!=endc; ++cell, ++cell_v, ++cell_v_vec)
4265 *
Assert(cell->is_locally_owned(), ExcInternalError());
4266 *
Assert(cell->subdomain_id() == this_mpi_process, ExcInternalError());
4269 *
static_cast<int>(cell->material_id());
4271 * fe_values_ref.reinit(cell);
4273 * std::vector<Tensor<2,dim>> solution_grads_u(n_q_points);
4274 * fe_values_ref[u_fe].get_function_gradients(solution_total,
4275 * solution_grads_u);
4277 * std::vector<double> solution_values_p_fluid_total(n_q_points);
4278 * fe_values_ref[p_fluid_fe].get_function_values(solution_total,
4279 * solution_values_p_fluid_total);
4281 * std::vector<Tensor<1,dim>> solution_grads_p_fluid_AD (n_q_points);
4282 * fe_values_ref[p_fluid_fe].get_function_gradients(solution_total,
4283 * solution_grads_p_fluid_AD);
4290 *
for (
unsigned int q_point=0; q_point<n_q_points; ++q_point)
4297 *
const std::vector<std::shared_ptr<const PointHistory<dim,ADNumberType>>>
4298 * lqph = quadrature_point_history.get_data(cell);
4299 *
Assert(lqph.size() == n_q_points, ExcInternalError());
4301 *
const double p_fluid = solution_values_p_fluid_total[q_point];
4312 * lqph[q_point]->get_Cauchy_E(F_AD);
4314 *
for (
unsigned int i=0; i<dim; ++i)
4315 *
for (
unsigned int j=0; j<dim; ++j)
4319 * sigma_fluid_vol *= -p_fluid;
4327 *
const double solid_vol_fraction = (parameters.solid_vol_frac)/det_F;
4331 * Green-Lagrange strain
4343 * solution_grads_p_fluid_AD[q_point]*F_inv;
4345 * lqph[q_point]->get_seepage_velocity_current(F_AD, grad_p_fluid_AD);
4352 *
const double porous_dissipation =
4353 * lqph[q_point]->get_porous_dissipation(F_AD, grad_p_fluid_AD);
4354 *
const double viscous_dissipation =
4355 * lqph[q_point]->get_viscous_dissipation();
4359 * OUTPUT AVERAGED ON ELEMENTS -------------------------------------------
4360 * Both average on elements and on nodes is NOT weighted with the
4362 * integration
point to the average. Ideally, it should be weighted,
4363 * but I haven
't invested time in getting it to work properly.
4366 * if (parameters.outtype == "elements")
4368 * for (unsigned int j=0; j<dim; ++j)
4370 * cauchy_stresses_total_elements[j](cell->active_cell_index())
4371 * += ((sigma*basis_vectors[j])*basis_vectors[j])/n_q_points;
4372 * cauchy_stresses_E_elements[j](cell->active_cell_index())
4373 * += ((sigma_E*basis_vectors[j])*basis_vectors[j])/n_q_points;
4374 * stretches_elements[j](cell->active_cell_index())
4375 * += std::sqrt(1.0+2.0*Tensor<0,dim,double>(E_strain[j][j]))
4377 * seepage_velocity_elements[j](cell->active_cell_index())
4378 * += Tensor<0,dim,double>(seepage_vel_AD[j])/n_q_points;
4381 * porous_dissipation_elements(cell->active_cell_index())
4382 * += porous_dissipation/n_q_points;
4383 * viscous_dissipation_elements(cell->active_cell_index())
4384 * += viscous_dissipation/n_q_points;
4385 * solid_vol_fraction_elements(cell->active_cell_index())
4386 * += solid_vol_fraction/n_q_points;
4388 * cauchy_stresses_total_elements[3](cell->active_cell_index())
4389 * += ((sigma*basis_vectors[0])*basis_vectors[1])/n_q_points; //sig_xy
4390 * cauchy_stresses_total_elements[4](cell->active_cell_index())
4391 * += ((sigma*basis_vectors[0])*basis_vectors[2])/n_q_points;//sig_xz
4392 * cauchy_stresses_total_elements[5](cell->active_cell_index())
4393 * += ((sigma*basis_vectors[1])*basis_vectors[2])/n_q_points;//sig_yz
4395 * cauchy_stresses_E_elements[3](cell->active_cell_index())
4396 * += ((sigma_E*basis_vectors[0])* basis_vectors[1])/n_q_points; //sig_xy
4397 * cauchy_stresses_E_elements[4](cell->active_cell_index())
4398 * += ((sigma_E*basis_vectors[0])* basis_vectors[2])/n_q_points;//sig_xz
4399 * cauchy_stresses_E_elements[5](cell->active_cell_index())
4400 * += ((sigma_E*basis_vectors[1])* basis_vectors[2])/n_q_points;//sig_yz
4405 * OUTPUT AVERAGED ON NODES -------------------------------------------
4408 * else if (parameters.outtype == "nodes")
4410 * for (unsigned int v=0; v<(GeometryInfo<dim>::vertices_per_cell); ++v)
4412 * types::global_dof_index local_vertex_indices =
4413 * cell_v->vertex_dof_index(v, 0);
4414 * counter_on_vertices_mpi(local_vertex_indices) += 1;
4415 * for (unsigned int k=0; k<dim; ++k)
4417 * cauchy_stresses_total_vertex_mpi[k](local_vertex_indices)
4418 * += (sigma*basis_vectors[k])*basis_vectors[k];
4419 * cauchy_stresses_E_vertex_mpi[k](local_vertex_indices)
4420 * += (sigma_E*basis_vectors[k])*basis_vectors[k];
4421 * stretches_vertex_mpi[k](local_vertex_indices)
4422 * += std::sqrt(1.0+2.0*Tensor<0,dim,double>(E_strain[k][k]));
4424 * types::global_dof_index local_vertex_vec_indices =
4425 * cell_v_vec->vertex_dof_index(v, k);
4426 * counter_on_vertices_vec_mpi(local_vertex_vec_indices) += 1;
4427 * seepage_velocity_vertex_vec_mpi(local_vertex_vec_indices)
4428 * += Tensor<0,dim,double>(seepage_vel_AD[k]);
4431 * porous_dissipation_vertex_mpi(local_vertex_indices)
4432 * += porous_dissipation;
4433 * viscous_dissipation_vertex_mpi(local_vertex_indices)
4434 * += viscous_dissipation;
4435 * solid_vol_fraction_vertex_mpi(local_vertex_indices)
4436 * += solid_vol_fraction;
4438 * cauchy_stresses_total_vertex_mpi[3](local_vertex_indices)
4439 * += (sigma*basis_vectors[0])*basis_vectors[1]; //sig_xy
4440 * cauchy_stresses_total_vertex_mpi[4](local_vertex_indices)
4441 * += (sigma*basis_vectors[0])*basis_vectors[2];//sig_xz
4442 * cauchy_stresses_total_vertex_mpi[5](local_vertex_indices)
4443 * += (sigma*basis_vectors[1])*basis_vectors[2]; //sig_yz
4445 * cauchy_stresses_E_vertex_mpi[3](local_vertex_indices)
4446 * += (sigma_E*basis_vectors[0])*basis_vectors[1]; //sig_xy
4447 * cauchy_stresses_E_vertex_mpi[4](local_vertex_indices)
4448 * += (sigma_E*basis_vectors[0])*basis_vectors[2];//sig_xz
4449 * cauchy_stresses_E_vertex_mpi[5](local_vertex_indices)
4450 * += (sigma_E*basis_vectors[1])*basis_vectors[2]; //sig_yz
4455 * ---------------------------------------------------------------
4458 * } //end gauss point loop
4463 * Different nodes might have different amount of contributions, e.g.,
4464 * corner nodes have less integration points contributing to the averaged.
4465 * This is why we need a counter and divide at the end, outside the cell loop.
4468 * if (parameters.outtype == "nodes")
4470 * for (unsigned int d=0; d<(vertex_handler_ref.n_dofs()); ++d)
4472 * sum_counter_on_vertices[d] =
4473 * Utilities::MPI::sum(counter_on_vertices_mpi[d],
4474 * mpi_communicator);
4475 * sum_porous_dissipation_vertex[d] =
4476 * Utilities::MPI::sum(porous_dissipation_vertex_mpi[d],
4477 * mpi_communicator);
4478 * sum_viscous_dissipation_vertex[d] =
4479 * Utilities::MPI::sum(viscous_dissipation_vertex_mpi[d],
4480 * mpi_communicator);
4481 * sum_solid_vol_fraction_vertex[d] =
4482 * Utilities::MPI::sum(solid_vol_fraction_vertex_mpi[d],
4483 * mpi_communicator);
4485 * for (unsigned int k=0; k<num_comp_symm_tensor; ++k)
4487 * sum_cauchy_stresses_total_vertex[k][d] =
4488 * Utilities::MPI::sum(cauchy_stresses_total_vertex_mpi[k][d],
4489 * mpi_communicator);
4490 * sum_cauchy_stresses_E_vertex[k][d] =
4491 * Utilities::MPI::sum(cauchy_stresses_E_vertex_mpi[k][d],
4492 * mpi_communicator);
4494 * for (unsigned int k=0; k<dim; ++k)
4496 * sum_stretches_vertex[k][d] =
4497 * Utilities::MPI::sum(stretches_vertex_mpi[k][d],
4498 * mpi_communicator);
4502 * for (unsigned int d=0; d<(vertex_vec_handler_ref.n_dofs()); ++d)
4504 * sum_counter_on_vertices_vec[d] =
4505 * Utilities::MPI::sum(counter_on_vertices_vec_mpi[d],
4506 * mpi_communicator);
4507 * sum_seepage_velocity_vertex_vec[d] =
4508 * Utilities::MPI::sum(seepage_velocity_vertex_vec_mpi[d],
4509 * mpi_communicator);
4512 * for (unsigned int d=0; d<(vertex_handler_ref.n_dofs()); ++d)
4514 * if (sum_counter_on_vertices[d]>0)
4516 * for (unsigned int i=0; i<num_comp_symm_tensor; ++i)
4518 * sum_cauchy_stresses_total_vertex[i][d] /= sum_counter_on_vertices[d];
4519 * sum_cauchy_stresses_E_vertex[i][d] /= sum_counter_on_vertices[d];
4521 * for (unsigned int i=0; i<dim; ++i)
4523 * sum_stretches_vertex[i][d] /= sum_counter_on_vertices[d];
4525 * sum_porous_dissipation_vertex[d] /= sum_counter_on_vertices[d];
4526 * sum_viscous_dissipation_vertex[d] /= sum_counter_on_vertices[d];
4527 * sum_solid_vol_fraction_vertex[d] /= sum_counter_on_vertices[d];
4531 * for (unsigned int d=0; d<(vertex_vec_handler_ref.n_dofs()); ++d)
4533 * if (sum_counter_on_vertices_vec[d]>0)
4535 * sum_seepage_velocity_vertex_vec[d] /= sum_counter_on_vertices_vec[d];
4543 * Add the results to the solution to create the output file for Paraview
4546 * DataOut<dim> data_out;
4547 * std::vector<DataComponentInterpretation::DataComponentInterpretation>
4549 * DataComponentInterpretation::component_is_part_of_vector);
4550 * comp_type.push_back(DataComponentInterpretation::component_is_scalar);
4552 * GridTools::get_subdomain_association(triangulation, partition_int);
4554 * std::vector<std::string> solution_name(dim, "displacement");
4555 * solution_name.push_back("pore_pressure");
4557 * data_out.attach_dof_handler(dof_handler_ref);
4558 * data_out.add_data_vector(solution_total,
4560 * DataOut<dim>::type_dof_data,
4563 * data_out.add_data_vector(solution_total,
4564 * gradient_postprocessor);
4566 * const Vector<double> partitioning(partition_int.begin(),
4567 * partition_int.end());
4569 * data_out.add_data_vector(partitioning, "partitioning");
4570 * data_out.add_data_vector(material_id, "material_id");
4574 * Integration point results -----------------------------------------------------------
4577 * if (parameters.outtype == "elements")
4579 * data_out.add_data_vector(cauchy_stresses_total_elements[0], "cauchy_xx");
4580 * data_out.add_data_vector(cauchy_stresses_total_elements[1], "cauchy_yy");
4581 * data_out.add_data_vector(cauchy_stresses_total_elements[2], "cauchy_zz");
4582 * data_out.add_data_vector(cauchy_stresses_total_elements[3], "cauchy_xy");
4583 * data_out.add_data_vector(cauchy_stresses_total_elements[4], "cauchy_xz");
4584 * data_out.add_data_vector(cauchy_stresses_total_elements[5], "cauchy_yz");
4586 * data_out.add_data_vector(cauchy_stresses_E_elements[0], "cauchy_E_xx");
4587 * data_out.add_data_vector(cauchy_stresses_E_elements[1], "cauchy_E_yy");
4588 * data_out.add_data_vector(cauchy_stresses_E_elements[2], "cauchy_E_zz");
4589 * data_out.add_data_vector(cauchy_stresses_E_elements[3], "cauchy_E_xy");
4590 * data_out.add_data_vector(cauchy_stresses_E_elements[4], "cauchy_E_xz");
4591 * data_out.add_data_vector(cauchy_stresses_E_elements[5], "cauchy_E_yz");
4593 * data_out.add_data_vector(stretches_elements[0], "stretch_xx");
4594 * data_out.add_data_vector(stretches_elements[1], "stretch_yy");
4595 * data_out.add_data_vector(stretches_elements[2], "stretch_zz");
4597 * data_out.add_data_vector(seepage_velocity_elements[0], "seepage_vel_x");
4598 * data_out.add_data_vector(seepage_velocity_elements[1], "seepage_vel_y");
4599 * data_out.add_data_vector(seepage_velocity_elements[2], "seepage_vel_z");
4601 * data_out.add_data_vector(porous_dissipation_elements, "dissipation_porous");
4602 * data_out.add_data_vector(viscous_dissipation_elements, "dissipation_viscous");
4603 * data_out.add_data_vector(solid_vol_fraction_elements, "solid_vol_fraction");
4605 * else if (parameters.outtype == "nodes")
4607 * data_out.add_data_vector(vertex_handler_ref,
4608 * sum_cauchy_stresses_total_vertex[0],
4610 * data_out.add_data_vector(vertex_handler_ref,
4611 * sum_cauchy_stresses_total_vertex[1],
4613 * data_out.add_data_vector(vertex_handler_ref,
4614 * sum_cauchy_stresses_total_vertex[2],
4616 * data_out.add_data_vector(vertex_handler_ref,
4617 * sum_cauchy_stresses_total_vertex[3],
4619 * data_out.add_data_vector(vertex_handler_ref,
4620 * sum_cauchy_stresses_total_vertex[4],
4622 * data_out.add_data_vector(vertex_handler_ref,
4623 * sum_cauchy_stresses_total_vertex[5],
4626 * data_out.add_data_vector(vertex_handler_ref,
4627 * sum_cauchy_stresses_E_vertex[0],
4629 * data_out.add_data_vector(vertex_handler_ref,
4630 * sum_cauchy_stresses_E_vertex[1],
4632 * data_out.add_data_vector(vertex_handler_ref,
4633 * sum_cauchy_stresses_E_vertex[2],
4635 * data_out.add_data_vector(vertex_handler_ref,
4636 * sum_cauchy_stresses_E_vertex[3],
4638 * data_out.add_data_vector(vertex_handler_ref,
4639 * sum_cauchy_stresses_E_vertex[4],
4641 * data_out.add_data_vector(vertex_handler_ref,
4642 * sum_cauchy_stresses_E_vertex[5],
4645 * data_out.add_data_vector(vertex_handler_ref,
4646 * sum_stretches_vertex[0],
4648 * data_out.add_data_vector(vertex_handler_ref,
4649 * sum_stretches_vertex[1],
4651 * data_out.add_data_vector(vertex_handler_ref,
4652 * sum_stretches_vertex[2],
4655 * std::vector<DataComponentInterpretation::DataComponentInterpretation>
4656 * comp_type_vec(dim,
4657 * DataComponentInterpretation::component_is_part_of_vector);
4658 * std::vector<std::string> solution_name_vec(dim,"seepage_velocity");
4660 * data_out.add_data_vector(vertex_vec_handler_ref,
4661 * sum_seepage_velocity_vertex_vec,
4662 * solution_name_vec,
4665 * data_out.add_data_vector(vertex_handler_ref,
4666 * sum_porous_dissipation_vertex,
4667 * "dissipation_porous");
4668 * data_out.add_data_vector(vertex_handler_ref,
4669 * sum_viscous_dissipation_vertex,
4670 * "dissipation_viscous");
4671 * data_out.add_data_vector(vertex_handler_ref,
4672 * sum_solid_vol_fraction_vertex,
4673 * "solid_vol_fraction");
4677 * ---------------------------------------------------------------------
4683 * data_out.build_patches(degree_displ);
4687 * static std::string get_filename_vtu(unsigned int process,
4688 * unsigned int timestep,
4689 * const unsigned int n_digits = 5)
4691 * std::ostringstream filename_vtu;
4694 * << Utilities::int_to_string(process, n_digits)
4696 * << Utilities::int_to_string(timestep, n_digits)
4698 * return filename_vtu.str();
4701 * static std::string get_filename_pvtu(unsigned int timestep,
4702 * const unsigned int n_digits = 5)
4704 * std::ostringstream filename_vtu;
4707 * << Utilities::int_to_string(timestep, n_digits)
4709 * return filename_vtu.str();
4712 * static std::string get_filename_pvd (void)
4714 * std::ostringstream filename_vtu;
4716 * << "solution.pvd";
4717 * return filename_vtu.str();
4721 * const std::string filename_vtu = Filename::get_filename_vtu(this_mpi_process,
4723 * std::ofstream output(filename_vtu.c_str());
4724 * data_out.write_vtu(output);
4728 * We have a collection of files written in parallel
4729 * This next set of steps should only be performed by master process
4732 * if (this_mpi_process == 0)
4736 * List of all files written out at this timestep by all processors
4739 * std::vector<std::string> parallel_filenames_vtu;
4740 * for (unsigned int p=0; p<n_mpi_processes; ++p)
4742 * parallel_filenames_vtu.push_back(Filename::get_filename_vtu(p, timestep));
4745 * const std::string filename_pvtu(Filename::get_filename_pvtu(timestep));
4746 * std::ofstream pvtu_master(filename_pvtu.c_str());
4747 * data_out.write_pvtu_record(pvtu_master,
4748 * parallel_filenames_vtu);
4752 * Time dependent data master file
4755 * static std::vector<std::pair<double,std::string>> time_and_name_history;
4756 * time_and_name_history.push_back(std::make_pair(current_time,
4758 * const std::string filename_pvd(Filename::get_filename_pvd());
4759 * std::ofstream pvd_output(filename_pvd.c_str());
4760 * DataOutBase::write_pvd_record(pvd_output, time_and_name_history);
4767 * Print results to plotting file
4770 * template <int dim>
4771 * void Solid<dim>::output_results_to_plot(
4772 * const unsigned int timestep,
4773 * const double current_time,
4774 * TrilinosWrappers::MPI::BlockVector solution_IN,
4775 * std::vector<Point<dim> > &tracked_vertices_IN,
4776 * std::ofstream &plotpointfile) const
4778 * TrilinosWrappers::MPI::BlockVector solution_total(locally_owned_partitioning,
4779 * locally_relevant_partitioning,
4784 * solution_total = solution_IN;
4788 * Variables needed to print the solution file for plotting
4791 * Point<dim> reaction_force;
4792 * Point<dim> reaction_force_pressure;
4793 * Point<dim> reaction_force_extra;
4794 * double total_fluid_flow = 0.0;
4795 * double total_porous_dissipation = 0.0;
4796 * double total_viscous_dissipation = 0.0;
4797 * double total_solid_vol = 0.0;
4798 * double total_vol_current = 0.0;
4799 * double total_vol_reference = 0.0;
4800 * std::vector<Point<dim+1>> solution_vertices(tracked_vertices_IN.size());
4804 * Auxiliar variables needed for mpi processing
4807 * Tensor<1,dim> sum_reaction_mpi;
4808 * Tensor<1,dim> sum_reaction_pressure_mpi;
4809 * Tensor<1,dim> sum_reaction_extra_mpi;
4810 * sum_reaction_mpi = 0.0;
4811 * sum_reaction_pressure_mpi = 0.0;
4812 * sum_reaction_extra_mpi = 0.0;
4813 * double sum_total_flow_mpi = 0.0;
4814 * double sum_porous_dissipation_mpi = 0.0;
4815 * double sum_viscous_dissipation_mpi = 0.0;
4816 * double sum_solid_vol_mpi = 0.0;
4817 * double sum_vol_current_mpi = 0.0;
4818 * double sum_vol_reference_mpi = 0.0;
4822 * Declare an instance of the material class object
4825 * if (parameters.mat_type == "Neo-Hooke")
4826 * NeoHooke<dim,ADNumberType> material(parameters,time);
4827 * else if (parameters.mat_type == "Ogden")
4828 * Ogden<dim,ADNumberType> material(parameters, time);
4829 * else if (parameters.mat_type == "visco-Ogden")
4830 * visco_Ogden <dim,ADNumberType>material(parameters,time);
4832 * Assert (false, ExcMessage("Material type not implemented"));
4836 * Define a local instance of FEValues to compute updated values required
4837 * to calculate stresses
4840 * const UpdateFlags uf_cell(update_values | update_gradients |
4841 * update_JxW_values);
4842 * FEValues<dim> fe_values_ref (fe, qf_cell, uf_cell);
4846 * Iterate through elements (cells) and Gauss Points
4849 * FilteredIterator<typename DoFHandler<dim>::active_cell_iterator>
4850 * cell(IteratorFilters::LocallyOwnedCell(),
4851 * dof_handler_ref.begin_active()),
4852 * endc(IteratorFilters::LocallyOwnedCell(),
4853 * dof_handler_ref.end());
4859 * for (; cell!=endc; ++cell)
4861 * Assert(cell->is_locally_owned(), ExcInternalError());
4862 * Assert(cell->subdomain_id() == this_mpi_process, ExcInternalError());
4864 * fe_values_ref.reinit(cell);
4866 * std::vector<Tensor<2,dim>> solution_grads_u(n_q_points);
4867 * fe_values_ref[u_fe].get_function_gradients(solution_total,
4868 * solution_grads_u);
4870 * std::vector<double> solution_values_p_fluid_total(n_q_points);
4871 * fe_values_ref[p_fluid_fe].get_function_values(solution_total,
4872 * solution_values_p_fluid_total);
4874 * std::vector<Tensor<1,dim >> solution_grads_p_fluid_AD(n_q_points);
4875 * fe_values_ref[p_fluid_fe].get_function_gradients(solution_total,
4876 * solution_grads_p_fluid_AD);
4880 * start gauss point loop
4883 * for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
4885 * const Tensor<2,dim,ADNumberType>
4886 * F_AD = Physics::Elasticity::Kinematics::F(solution_grads_u[q_point]);
4887 * ADNumberType det_F_AD = determinant(F_AD);
4888 * const double det_F = Tensor<0,dim,double>(det_F_AD);
4890 * const std::vector<std::shared_ptr<const PointHistory<dim,ADNumberType>>>
4891 * lqph = quadrature_point_history.get_data(cell);
4892 * Assert(lqph.size() == n_q_points, ExcInternalError());
4894 * double JxW = fe_values_ref.JxW(q_point);
4901 * sum_vol_current_mpi += det_F * JxW;
4902 * sum_vol_reference_mpi += JxW;
4903 * sum_solid_vol_mpi += parameters.solid_vol_frac * JxW * det_F;
4910 * const Tensor<2,dim,ADNumberType> F_inv = invert(F_AD);
4911 * const Tensor<1,dim,ADNumberType>
4912 * grad_p_fluid_AD = solution_grads_p_fluid_AD[q_point]*F_inv;
4913 * const Tensor<1,dim,ADNumberType> seepage_vel_AD
4914 * = lqph[q_point]->get_seepage_velocity_current(F_AD, grad_p_fluid_AD);
4921 * const double porous_dissipation =
4922 * lqph[q_point]->get_porous_dissipation(F_AD, grad_p_fluid_AD);
4923 * sum_porous_dissipation_mpi += porous_dissipation * det_F * JxW;
4925 * const double viscous_dissipation = lqph[q_point]->get_viscous_dissipation();
4926 * sum_viscous_dissipation_mpi += viscous_dissipation * det_F * JxW;
4930 * ---------------------------------------------------------------
4933 * } //end gauss point loop
4937 * Compute reaction force on load boundary & total fluid flow across
4939 * Define a local instance of FEFaceValues to compute values required
4940 * to calculate reaction force
4943 * const UpdateFlags uf_face( update_values | update_gradients |
4944 * update_normal_vectors | update_JxW_values );
4945 * FEFaceValues<dim> fe_face_values_ref(fe, qf_face, uf_face);
4952 * for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
4959 * if (cell->face(face)->at_boundary() == true &&
4960 * cell->face(face)->boundary_id() == get_reaction_boundary_id_for_output() )
4962 * fe_face_values_ref.reinit(cell, face);
4966 * Get displacement gradients for current face
4969 * std::vector<Tensor<2,dim> > solution_grads_u_f(n_q_points_f);
4970 * fe_face_values_ref[u_fe].get_function_gradients
4972 * solution_grads_u_f);
4976 * Get pressure for current element
4979 * std::vector< double > solution_values_p_fluid_total_f(n_q_points_f);
4980 * fe_face_values_ref[p_fluid_fe].get_function_values
4982 * solution_values_p_fluid_total_f);
4986 * start gauss points on faces loop
4989 * for (unsigned int f_q_point=0; f_q_point<n_q_points_f; ++f_q_point)
4991 * const Tensor<1,dim> &N = fe_face_values_ref.normal_vector(f_q_point);
4992 * const double JxW_f = fe_face_values_ref.JxW(f_q_point);
4996 * Compute deformation gradient from displacements gradient
4997 * (present configuration)
5000 * const Tensor<2,dim,ADNumberType> F_AD =
5001 * Physics::Elasticity::Kinematics::F(solution_grads_u_f[f_q_point]);
5003 * const std::vector<std::shared_ptr<const PointHistory<dim,ADNumberType>>>
5004 * lqph = quadrature_point_history.get_data(cell);
5005 * Assert(lqph.size() == n_q_points, ExcInternalError());
5007 * const double p_fluid = solution_values_p_fluid_total[f_q_point];
5014 * static const SymmetricTensor<2,dim,double>
5015 * I (Physics::Elasticity::StandardTensors<dim>::I);
5016 * SymmetricTensor<2,dim> sigma_E;
5017 * const SymmetricTensor<2,dim,ADNumberType> sigma_E_AD =
5018 * lqph[f_q_point]->get_Cauchy_E(F_AD);
5020 * for (unsigned int i=0; i<dim; ++i)
5021 * for (unsigned int j=0; j<dim; ++j)
5022 * sigma_E[i][j] = Tensor<0,dim,double>(sigma_E_AD[i][j]);
5024 * SymmetricTensor<2,dim> sigma_fluid_vol(I);
5025 * sigma_fluid_vol *= -1.0*p_fluid;
5026 * const SymmetricTensor<2,dim> sigma = sigma_E+sigma_fluid_vol;
5027 * sum_reaction_mpi += sigma * N * JxW_f;
5028 * sum_reaction_pressure_mpi += sigma_fluid_vol * N * JxW_f;
5029 * sum_reaction_extra_mpi += sigma_E * N * JxW_f;
5030 * }//end gauss points on faces loop
5038 * if (cell->face(face)->at_boundary() == true &&
5039 * (cell->face(face)->boundary_id() ==
5040 * get_drained_boundary_id_for_output().first ||
5041 * cell->face(face)->boundary_id() ==
5042 * get_drained_boundary_id_for_output().second ) )
5044 * fe_face_values_ref.reinit(cell, face);
5048 * Get displacement gradients for current face
5051 * std::vector<Tensor<2,dim>> solution_grads_u_f(n_q_points_f);
5052 * fe_face_values_ref[u_fe].get_function_gradients
5054 * solution_grads_u_f);
5058 * Get pressure gradients for current face
5061 * std::vector<Tensor<1,dim>> solution_grads_p_f(n_q_points_f);
5062 * fe_face_values_ref[p_fluid_fe].get_function_gradients
5064 * solution_grads_p_f);
5068 * start gauss points on faces loop
5071 * for (unsigned int f_q_point=0; f_q_point<n_q_points_f; ++f_q_point)
5073 * const Tensor<1,dim> &N =
5074 * fe_face_values_ref.normal_vector(f_q_point);
5075 * const double JxW_f = fe_face_values_ref.JxW(f_q_point);
5079 * Deformation gradient and inverse from displacements gradient
5080 * (present configuration)
5083 * const Tensor<2,dim,ADNumberType> F_AD
5084 * = Physics::Elasticity::Kinematics::F(solution_grads_u_f[f_q_point]);
5086 * const Tensor<2,dim,ADNumberType> F_inv_AD = invert(F_AD);
5087 * ADNumberType det_F_AD = determinant(F_AD);
5089 * const std::vector<std::shared_ptr<const PointHistory<dim,ADNumberType>>>
5090 * lqph = quadrature_point_history.get_data(cell);
5091 * Assert(lqph.size() == n_q_points, ExcInternalError());
5098 * Tensor<1,dim> seepage;
5099 * double det_F = Tensor<0,dim,double>(det_F_AD);
5100 * const Tensor<1,dim,ADNumberType> grad_p
5101 * = solution_grads_p_f[f_q_point]*F_inv_AD;
5102 * const Tensor<1,dim,ADNumberType> seepage_AD
5103 * = lqph[f_q_point]->get_seepage_velocity_current(F_AD, grad_p);
5105 * for (unsigned int i=0; i<dim; ++i)
5106 * seepage[i] = Tensor<0,dim,double>(seepage_AD[i]);
5108 * sum_total_flow_mpi += (seepage/det_F) * N * JxW_f;
5109 * }//end gauss points on faces loop
5116 * Sum the results from different MPI process and then add to the reaction_force vector
5117 * In theory, the solution on each surface (each cell) only exists in one MPI process
5118 * so, we add all MPI process, one will have the solution and the others will be zero
5121 * for (unsigned int d=0; d<dim; ++d)
5123 * reaction_force[d] = Utilities::MPI::sum(sum_reaction_mpi[d],
5124 * mpi_communicator);
5125 * reaction_force_pressure[d] = Utilities::MPI::sum(sum_reaction_pressure_mpi[d],
5126 * mpi_communicator);
5127 * reaction_force_extra[d] = Utilities::MPI::sum(sum_reaction_extra_mpi[d],
5128 * mpi_communicator);
5133 * Same for total fluid flow, and for porous and viscous dissipations
5136 * total_fluid_flow = Utilities::MPI::sum(sum_total_flow_mpi,
5137 * mpi_communicator);
5138 * total_porous_dissipation = Utilities::MPI::sum(sum_porous_dissipation_mpi,
5139 * mpi_communicator);
5140 * total_viscous_dissipation = Utilities::MPI::sum(sum_viscous_dissipation_mpi,
5141 * mpi_communicator);
5142 * total_solid_vol = Utilities::MPI::sum(sum_solid_vol_mpi,
5143 * mpi_communicator);
5144 * total_vol_current = Utilities::MPI::sum(sum_vol_current_mpi,
5145 * mpi_communicator);
5146 * total_vol_reference = Utilities::MPI::sum(sum_vol_reference_mpi,
5147 * mpi_communicator);
5151 * Extract solution for tracked vectors
5152 * Copying an MPI::BlockVector into MPI::Vector is not possible,
5153 * so we copy each block of MPI::BlockVector into an MPI::Vector
5154 * And then we copy the MPI::Vector into "normal" Vectors
5157 * TrilinosWrappers::MPI::Vector solution_vector_u_MPI(solution_total.block(u_block));
5158 * TrilinosWrappers::MPI::Vector solution_vector_p_MPI(solution_total.block(p_fluid_block));
5159 * Vector<double> solution_u_vector(solution_vector_u_MPI);
5160 * Vector<double> solution_p_vector(solution_vector_p_MPI);
5162 * if (this_mpi_process == 0)
5166 * Append the pressure solution vector to the displacement solution vector,
5167 * creating a single solution vector equivalent to the original BlockVector
5168 * so FEFieldFunction will work with the dof_handler_ref.
5171 * Vector<double> solution_vector(solution_p_vector.size()
5172 * +solution_u_vector.size());
5174 * for (unsigned int d=0; d<(solution_u_vector.size()); ++d)
5175 * solution_vector[d] = solution_u_vector[d];
5177 * for (unsigned int d=0; d<(solution_p_vector.size()); ++d)
5178 * solution_vector[solution_u_vector.size()+d] = solution_p_vector[d];
5180 * Functions::FEFieldFunction<dim,Vector<double>>
5181 * find_solution(dof_handler_ref, solution_vector);
5183 * for (unsigned int p=0; p<tracked_vertices_IN.size(); ++p)
5185 * Vector<double> update(dim+1);
5186 * Point<dim> pt_ref;
5188 * pt_ref[0]= tracked_vertices_IN[p][0];
5189 * pt_ref[1]= tracked_vertices_IN[p][1];
5190 * pt_ref[2]= tracked_vertices_IN[p][2];
5192 * find_solution.vector_value(pt_ref, update);
5194 * for (unsigned int d=0; d<(dim+1); ++d)
5198 * For values close to zero, set to 0.0
5201 * if (abs(update[d])<1.5*parameters.tol_u)
5203 * solution_vertices[p][d] = update[d];
5208 * Write the results to the plotting file.
5209 * Add two blank lines between cycles in the cyclic loading examples so GNUPLOT can detect each cycle as a different block
5212 * if (( (parameters.geom_type == "Budday_cube_tension_compression_fully_fixed")||
5213 * (parameters.geom_type == "Budday_cube_tension_compression")||
5214 * (parameters.geom_type == "Budday_cube_shear_fully_fixed") ) &&
5215 * ( (abs(current_time - parameters.end_time/3.) <0.9*parameters.delta_t)||
5216 * (abs(current_time - 2.*parameters.end_time/3.)<0.9*parameters.delta_t) ) &&
5217 * parameters.num_cycle_sets == 1 )
5219 * plotpointfile << std::endl<< std::endl;
5221 * if (( (parameters.geom_type == "Budday_cube_tension_compression_fully_fixed")||
5222 * (parameters.geom_type == "Budday_cube_tension_compression")||
5223 * (parameters.geom_type == "Budday_cube_shear_fully_fixed") ) &&
5224 * ( (abs(current_time - parameters.end_time/9.) <0.9*parameters.delta_t)||
5225 * (abs(current_time - 2.*parameters.end_time/9.)<0.9*parameters.delta_t)||
5226 * (abs(current_time - 3.*parameters.end_time/9.)<0.9*parameters.delta_t)||
5227 * (abs(current_time - 5.*parameters.end_time/9.)<0.9*parameters.delta_t)||
5228 * (abs(current_time - 7.*parameters.end_time/9.)<0.9*parameters.delta_t) ) &&
5229 * parameters.num_cycle_sets == 2 )
5231 * plotpointfile << std::endl<< std::endl;
5234 * plotpointfile << std::setprecision(6) << std::scientific;
5235 * plotpointfile << std::setw(16) << current_time << ","
5236 * << std::setw(15) << total_vol_reference << ","
5237 * << std::setw(15) << total_vol_current << ","
5238 * << std::setw(15) << total_solid_vol << ",";
5240 * if (current_time == 0.0)
5242 * for (unsigned int p=0; p<tracked_vertices_IN.size(); ++p)
5244 * for (unsigned int d=0; d<dim; ++d)
5245 * plotpointfile << std::setw(15) << 0.0 << ",";
5247 * plotpointfile << std::setw(15) << parameters.drained_pressure << ",";
5249 * for (unsigned int d=0; d<(3*dim+2); ++d)
5250 * plotpointfile << std::setw(15) << 0.0 << ",";
5252 * plotpointfile << std::setw(15) << 0.0;
5256 * for (unsigned int p=0; p<tracked_vertices_IN.size(); ++p)
5257 * for (unsigned int d=0; d<(dim+1); ++d)
5258 * plotpointfile << std::setw(15) << solution_vertices[p][d]<< ",";
5260 * for (unsigned int d=0; d<dim; ++d)
5261 * plotpointfile << std::setw(15) << reaction_force[d] << ",";
5263 * for (unsigned int d=0; d<dim; ++d)
5264 * plotpointfile << std::setw(15) << reaction_force_pressure[d] << ",";
5266 * for (unsigned int d=0; d<dim; ++d)
5267 * plotpointfile << std::setw(15) << reaction_force_extra[d] << ",";
5269 * plotpointfile << std::setw(15) << total_fluid_flow << ","
5270 * << std::setw(15) << total_porous_dissipation<< ","
5271 * << std::setw(15) << total_viscous_dissipation;
5273 * plotpointfile << std::endl;
5279 * Header for console output file
5282 * template <int dim>
5283 * void Solid<dim>::print_console_file_header(std::ofstream &outputfile) const
5285 * outputfile << "/*-----------------------------------------------------------------------------------------";
5286 * outputfile << "\n\n Poro-viscoelastic formulation to solve nonlinear solid mechanics problems using deal.ii";
5287 * outputfile << "\n\n Problem setup by E Comellas and J-P Pelteret, University of Erlangen-Nuremberg, 2018";
5288 * outputfile << "\n\n/*-----------------------------------------------------------------------------------------";
5289 * outputfile << "\n\nCONSOLE OUTPUT: \n\n";
5294 * Header for plotting output file
5297 * template <int dim>
5298 * void Solid<dim>::print_plot_file_header(std::vector<Point<dim> > &tracked_vertices,
5299 * std::ofstream &plotpointfile) const
5301 * plotpointfile << "#\n# *** Solution history for tracked vertices -- DOF: 0 = Ux, 1 = Uy, 2 = Uz, 3 = P ***"
5304 * for (unsigned int p=0; p<tracked_vertices.size(); ++p)
5306 * plotpointfile << "# Point " << p << " coordinates: ";
5307 * for (unsigned int d=0; d<dim; ++d)
5309 * plotpointfile << tracked_vertices[p][d];
5310 * if (!( (p == tracked_vertices.size()-1) && (d == dim-1) ))
5311 * plotpointfile << ", ";
5313 * plotpointfile << std::endl;
5315 * plotpointfile << "# The reaction force is the integral over the loaded surfaces in the "
5316 * << "undeformed configuration of the Cauchy stress times the normal surface unit vector.\n"
5317 * << "# reac(p) corresponds to the volumetric part of the Cauchy stress due to the pore fluid pressure"
5318 * << " and reac(E) corresponds to the extra part of the Cauchy stress due to the solid contribution."
5320 * << "# The fluid flow is the integral over the drained surfaces in the "
5321 * << "undeformed configuration of the seepage velocity times the normal surface unit vector."
5323 * << "# Column number:"
5327 * unsigned int columns = 24;
5328 * for (unsigned int d=1; d<columns; ++d)
5329 * plotpointfile << std::setw(15)<< d <<",";
5331 * plotpointfile << std::setw(15)<< columns
5334 * << std::right << std::setw(16) << "Time,"
5335 * << std::right << std::setw(16) << "ref vol,"
5336 * << std::right << std::setw(16) << "def vol,"
5337 * << std::right << std::setw(16) << "solid vol,";
5338 * for (unsigned int p=0; p<tracked_vertices.size(); ++p)
5339 * for (unsigned int d=0; d<(dim+1); ++d)
5340 * plotpointfile << std::right<< std::setw(11)
5341 * <<"P" << p << "[" << d << "],";
5343 * for (unsigned int d=0; d<dim; ++d)
5344 * plotpointfile << std::right<< std::setw(13)
5345 * << "reaction [" << d << "],";
5347 * for (unsigned int d=0; d<dim; ++d)
5348 * plotpointfile << std::right<< std::setw(13)
5349 * << "reac(p) [" << d << "],";
5351 * for (unsigned int d=0; d<dim; ++d)
5352 * plotpointfile << std::right<< std::setw(13)
5353 * << "reac(E) [" << d << "],";
5355 * plotpointfile << std::right<< std::setw(16)<< "fluid flow,"
5356 * << std::right<< std::setw(16)<< "porous dissip,"
5357 * << std::right<< std::setw(15)<< "viscous dissip"
5363 * Footer for console output file
5366 * template <int dim>
5367 * void Solid<dim>::print_console_file_footer(std::ofstream &outputfile) const
5371 * Copy "parameters" file at end of output file.
5374 * std::ifstream infile("parameters.prm");
5375 * std::string content = "";
5378 * for(i=0 ; infile.eof()!=true ; i++)
5380 * char aux = infile.get();
5382 * if(aux=='\n
') content += '#
';
5386 * content.erase(content.end()-1);
5389 * outputfile << "\n\n\n\n PARAMETERS FILE USED IN THIS COMPUTATION: \n#"
5396 * Footer for plotting output file
5399 * template <int dim>
5400 * void Solid<dim>::print_plot_file_footer(std::ofstream &plotpointfile) const
5404 * Copy "parameters" file at end of output file.
5407 * std::ifstream infile("parameters.prm");
5408 * std::string content = "";
5411 * for(i=0 ; infile.eof()!=true ; i++)
5413 * char aux = infile.get();
5415 * if(aux=='\n
') content += '#
';
5419 * content.erase(content.end()-1);
5422 * plotpointfile << "#"<< std::endl
5423 * << "#"<< std::endl
5424 * << "# PARAMETERS FILE USED IN THIS COMPUTATION:" << std::endl
5425 * << "#"<< std::endl
5433 * <a name="VerificationexamplesfromEhlersandEipper1999"></a>
5434 * <h3>Verification examples from Ehlers and Eipper 1999</h3>
5435 * We group the definition of the geometry, boundary and loading conditions specific to
5436 * the verification examples from Ehlers and Eipper 1999 into specific classes.
5441 * <a name="BaseclassTubegeometryandboundaryconditions"></a>
5442 * <h4>Base class: Tube geometry and boundary conditions</h4>
5445 * template <int dim>
5446 * class VerificationEhlers1999TubeBase
5447 * : public Solid<dim>
5450 * VerificationEhlers1999TubeBase (const Parameters::AllParameters ¶meters)
5451 * : Solid<dim> (parameters)
5454 * virtual ~VerificationEhlers1999TubeBase () {}
5457 * virtual void make_grid() override
5459 * GridGenerator::cylinder( this->triangulation,
5463 * const double rot_angle = 3.0*numbers::PI/2.0;
5464 * GridTools::rotate( Point<3>::unit_vector(1), rot_angle, this->triangulation);
5466 * this->triangulation.reset_manifold(0);
5467 * static const CylindricalManifold<dim> manifold_description_3d(2);
5468 * this->triangulation.set_manifold (0, manifold_description_3d);
5469 * GridTools::scale(this->parameters.scale, this->triangulation);
5470 * this->triangulation.refine_global(std::max (1U, this->parameters.global_refinement));
5471 * this->triangulation.reset_manifold(0);
5474 * virtual void define_tracked_vertices(std::vector<Point<dim> > &tracked_vertices) override
5476 * tracked_vertices[0][0] = 0.0*this->parameters.scale;
5477 * tracked_vertices[0][1] = 0.0*this->parameters.scale;
5478 * tracked_vertices[0][2] = 0.5*this->parameters.scale;
5480 * tracked_vertices[1][0] = 0.0*this->parameters.scale;
5481 * tracked_vertices[1][1] = 0.0*this->parameters.scale;
5482 * tracked_vertices[1][2] = -0.5*this->parameters.scale;
5485 * virtual void make_dirichlet_constraints(AffineConstraints<double> &constraints) override
5487 * if (this->time.get_timestep() < 2)
5489 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
5491 * Functions::ConstantFunction<dim>(this->parameters.drained_pressure,this->n_components),
5493 * (this->fe.component_mask(this->pressure)));
5497 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
5499 * Functions::ZeroFunction<dim>(this->n_components),
5501 * (this->fe.component_mask(this->pressure)));
5504 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
5506 * Functions::ZeroFunction<dim>(this->n_components),
5508 * (this->fe.component_mask(this->x_displacement)|
5509 * this->fe.component_mask(this->y_displacement) ) );
5511 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
5513 * Functions::ZeroFunction<dim>(this->n_components),
5515 * (this->fe.component_mask(this->x_displacement) |
5516 * this->fe.component_mask(this->y_displacement) |
5517 * this->fe.component_mask(this->z_displacement) ));
5521 * get_prescribed_fluid_flow (const types::boundary_id &boundary_id,
5522 * const Point<dim> &pt) const override
5525 * (void)boundary_id;
5529 * virtual types::boundary_id
5530 * get_reaction_boundary_id_for_output() const override
5535 * virtual std::pair<types::boundary_id,types::boundary_id>
5536 * get_drained_boundary_id_for_output() const override
5538 * return std::make_pair(2,2);
5541 * virtual std::vector<double>
5542 * get_dirichlet_load(const types::boundary_id &boundary_id,
5543 * const int &direction) const override
5545 * std::vector<double> displ_incr(dim, 0.0);
5546 * (void)boundary_id;
5548 * AssertThrow(false, ExcMessage("Displacement loading not implemented for Ehlers verification examples."));
5550 * return displ_incr;
5557 * <a name="DerivedclassSteploadexample"></a>
5558 * <h4>Derived class: Step load example</h4>
5561 * template <int dim>
5562 * class VerificationEhlers1999StepLoad
5563 * : public VerificationEhlers1999TubeBase<dim>
5566 * VerificationEhlers1999StepLoad (const Parameters::AllParameters ¶meters)
5567 * : VerificationEhlers1999TubeBase<dim> (parameters)
5570 * virtual ~VerificationEhlers1999StepLoad () {}
5573 * virtual Tensor<1,dim>
5574 * get_neumann_traction (const types::boundary_id &boundary_id,
5575 * const Point<dim> &pt,
5576 * const Tensor<1,dim> &N) const override
5578 * if (this->parameters.load_type == "pressure")
5580 * if (boundary_id == 2)
5582 * return this->parameters.load * N;
5588 * return Tensor<1,dim>();
5595 * <a name="DerivedclassLoadincreasingexample"></a>
5596 * <h4>Derived class: Load increasing example</h4>
5599 * template <int dim>
5600 * class VerificationEhlers1999IncreaseLoad
5601 * : public VerificationEhlers1999TubeBase<dim>
5604 * VerificationEhlers1999IncreaseLoad (const Parameters::AllParameters ¶meters)
5605 * : VerificationEhlers1999TubeBase<dim> (parameters)
5608 * virtual ~VerificationEhlers1999IncreaseLoad () {}
5611 * virtual Tensor<1,dim>
5612 * get_neumann_traction (const types::boundary_id &boundary_id,
5613 * const Point<dim> &pt,
5614 * const Tensor<1,dim> &N) const override
5616 * if (this->parameters.load_type == "pressure")
5618 * if (boundary_id == 2)
5620 * const double initial_load = this->parameters.load;
5621 * const double final_load = 20.0*initial_load;
5622 * const double initial_time = this->time.get_delta_t();
5623 * const double final_time = this->time.get_end();
5624 * const double current_time = this->time.get_current();
5625 * const double load = initial_load + (final_load-initial_load)*(current_time-initial_time)/(final_time-initial_time);
5632 * return Tensor<1,dim>();
5639 * <a name="ClassConsolidationcube"></a>
5640 * <h4>Class: Consolidation cube</h4>
5643 * template <int dim>
5644 * class VerificationEhlers1999CubeConsolidation
5645 * : public Solid<dim>
5648 * VerificationEhlers1999CubeConsolidation (const Parameters::AllParameters ¶meters)
5649 * : Solid<dim> (parameters)
5652 * virtual ~VerificationEhlers1999CubeConsolidation () {}
5656 * make_grid() override
5658 * GridGenerator::hyper_rectangle(this->triangulation,
5659 * Point<dim>(0.0, 0.0, 0.0),
5660 * Point<dim>(1.0, 1.0, 1.0),
5663 * GridTools::scale(this->parameters.scale, this->triangulation);
5664 * this->triangulation.refine_global(std::max (1U, this->parameters.global_refinement));
5666 * typename Triangulation<dim>::active_cell_iterator cell =
5667 * this->triangulation.begin_active(), endc = this->triangulation.end();
5668 * for (; cell != endc; ++cell)
5670 * for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
5671 * if (cell->face(face)->at_boundary() == true &&
5672 * cell->face(face)->center()[2] == 1.0 * this->parameters.scale)
5674 * if (cell->face(face)->center()[0] < 0.5 * this->parameters.scale &&
5675 * cell->face(face)->center()[1] < 0.5 * this->parameters.scale)
5676 * cell->face(face)->set_boundary_id(100);
5678 * cell->face(face)->set_boundary_id(101);
5684 * define_tracked_vertices(std::vector<Point<dim> > &tracked_vertices) override
5686 * tracked_vertices[0][0] = 0.0*this->parameters.scale;
5687 * tracked_vertices[0][1] = 0.0*this->parameters.scale;
5688 * tracked_vertices[0][2] = 1.0*this->parameters.scale;
5690 * tracked_vertices[1][0] = 0.0*this->parameters.scale;
5691 * tracked_vertices[1][1] = 0.0*this->parameters.scale;
5692 * tracked_vertices[1][2] = 0.0*this->parameters.scale;
5696 * make_dirichlet_constraints(AffineConstraints<double> &constraints) override
5698 * if (this->time.get_timestep() < 2)
5700 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
5702 * Functions::ConstantFunction<dim>(this->parameters.drained_pressure,this->n_components),
5704 * (this->fe.component_mask(this->pressure)));
5708 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
5710 * Functions::ZeroFunction<dim>(this->n_components),
5712 * (this->fe.component_mask(this->pressure)));
5715 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
5717 * Functions::ZeroFunction<dim>(this->n_components),
5719 * this->fe.component_mask(this->x_displacement));
5721 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
5723 * Functions::ZeroFunction<dim>(this->n_components),
5725 * this->fe.component_mask(this->x_displacement));
5727 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
5729 * Functions::ZeroFunction<dim>(this->n_components),
5731 * this->fe.component_mask(this->y_displacement));
5733 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
5735 * Functions::ZeroFunction<dim>(this->n_components),
5737 * this->fe.component_mask(this->y_displacement));
5739 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
5741 * Functions::ZeroFunction<dim>(this->n_components),
5743 * ( this->fe.component_mask(this->x_displacement) |
5744 * this->fe.component_mask(this->y_displacement) |
5745 * this->fe.component_mask(this->z_displacement) ));
5748 * virtual Tensor<1,dim>
5749 * get_neumann_traction (const types::boundary_id &boundary_id,
5750 * const Point<dim> &pt,
5751 * const Tensor<1,dim> &N) const override
5753 * if (this->parameters.load_type == "pressure")
5755 * if (boundary_id == 100)
5757 * return this->parameters.load * N;
5763 * return Tensor<1,dim>();
5767 * get_prescribed_fluid_flow (const types::boundary_id &boundary_id,
5768 * const Point<dim> &pt) const override
5771 * (void)boundary_id;
5775 * virtual types::boundary_id
5776 * get_reaction_boundary_id_for_output() const override
5781 * virtual std::pair<types::boundary_id,types::boundary_id>
5782 * get_drained_boundary_id_for_output() const override
5784 * return std::make_pair(101,101);
5787 * virtual std::vector<double>
5788 * get_dirichlet_load(const types::boundary_id &boundary_id,
5789 * const int &direction) const override
5791 * std::vector<double> displ_incr(dim, 0.0);
5792 * (void)boundary_id;
5794 * AssertThrow(false, ExcMessage("Displacement loading not implemented for Ehlers verification examples."));
5796 * return displ_incr;
5803 * <a name="Franceschiniexperiments"></a>
5804 * <h4>Franceschini experiments</h4>
5807 * template <int dim>
5808 * class Franceschini2006Consolidation
5809 * : public Solid<dim>
5812 * Franceschini2006Consolidation (const Parameters::AllParameters ¶meters)
5813 * : Solid<dim> (parameters)
5816 * virtual ~Franceschini2006Consolidation () {}
5819 * virtual void make_grid() override
5821 * const Point<dim-1> mesh_center(0.0, 0.0);
5822 * const double radius = 0.5;
5825 * const double height = 0.27; //8.1 mm for 30 mm radius
5828 * const double height = 0.23; //6.9 mm for 30 mm radius
5829 * Triangulation<dim-1> triangulation_in;
5830 * GridGenerator::hyper_ball( triangulation_in,
5834 * GridGenerator::extrude_triangulation(triangulation_in,
5837 * this->triangulation);
5839 * const CylindricalManifold<dim> cylinder_3d(2);
5840 * const types::manifold_id cylinder_id = 0;
5843 * this->triangulation.set_manifold(cylinder_id, cylinder_3d);
5845 * for (auto cell : this->triangulation.active_cell_iterators())
5847 * for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
5849 * if (cell->face(face)->at_boundary() == true)
5851 * if (cell->face(face)->center()[2] == 0.0)
5852 * cell->face(face)->set_boundary_id(1);
5854 * else if (cell->face(face)->center()[2] == height)
5855 * cell->face(face)->set_boundary_id(2);
5859 * cell->face(face)->set_boundary_id(0);
5860 * cell->face(face)->set_all_manifold_ids(cylinder_id);
5866 * GridTools::scale(this->parameters.scale, this->triangulation);
5867 * this->triangulation.refine_global(std::max (1U, this->parameters.global_refinement));
5870 * virtual void define_tracked_vertices(std::vector<Point<dim> > &tracked_vertices) override
5872 * tracked_vertices[0][0] = 0.0*this->parameters.scale;
5873 * tracked_vertices[0][1] = 0.0*this->parameters.scale;
5876 * tracked_vertices[0][2] = 0.27*this->parameters.scale;
5879 * tracked_vertices[0][2] = 0.23*this->parameters.scale;
5881 * tracked_vertices[1][0] = 0.0*this->parameters.scale;
5882 * tracked_vertices[1][1] = 0.0*this->parameters.scale;
5883 * tracked_vertices[1][2] = 0.0*this->parameters.scale;
5886 * virtual void make_dirichlet_constraints(AffineConstraints<double> &constraints) override
5888 * if (this->time.get_timestep() < 2)
5890 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
5892 * Functions::ConstantFunction<dim>(this->parameters.drained_pressure,this->n_components),
5894 * (this->fe.component_mask(this->pressure)));
5896 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
5898 * Functions::ConstantFunction<dim>(this->parameters.drained_pressure,this->n_components),
5900 * (this->fe.component_mask(this->pressure)));
5904 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
5906 * Functions::ZeroFunction<dim>(this->n_components),
5908 * (this->fe.component_mask(this->pressure)));
5910 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
5912 * Functions::ZeroFunction<dim>(this->n_components),
5914 * (this->fe.component_mask(this->pressure)));
5917 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
5919 * Functions::ZeroFunction<dim>(this->n_components),
5921 * (this->fe.component_mask(this->x_displacement)|
5922 * this->fe.component_mask(this->y_displacement) ) );
5924 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
5926 * Functions::ZeroFunction<dim>(this->n_components),
5928 * (this->fe.component_mask(this->x_displacement) |
5929 * this->fe.component_mask(this->y_displacement) |
5930 * this->fe.component_mask(this->z_displacement) ));
5932 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
5934 * Functions::ZeroFunction<dim>(this->n_components),
5936 * (this->fe.component_mask(this->x_displacement) |
5937 * this->fe.component_mask(this->y_displacement) ));
5941 * get_prescribed_fluid_flow (const types::boundary_id &boundary_id,
5942 * const Point<dim> &pt) const override
5945 * (void)boundary_id;
5949 * virtual types::boundary_id
5950 * get_reaction_boundary_id_for_output() const override
5955 * virtual std::pair<types::boundary_id,types::boundary_id>
5956 * get_drained_boundary_id_for_output() const override
5958 * return std::make_pair(1,2);
5961 * virtual std::vector<double>
5962 * get_dirichlet_load(const types::boundary_id &boundary_id,
5963 * const int &direction) const override
5965 * std::vector<double> displ_incr(dim, 0.0);
5966 * (void)boundary_id;
5968 * AssertThrow(false, ExcMessage("Displacement loading not implemented for Franceschini examples."));
5970 * return displ_incr;
5973 * virtual Tensor<1,dim>
5974 * get_neumann_traction (const types::boundary_id &boundary_id,
5975 * const Point<dim> &pt,
5976 * const Tensor<1,dim> &N) const override
5978 * if (this->parameters.load_type == "pressure")
5980 * if (boundary_id == 2)
5982 * return (this->parameters.load * N);
5984 * const double final_load = this->parameters.load;
5985 * const double final_load_time = 10 * this->time.get_delta_t();
5986 * const double current_time = this->time.get_current();
5989 * const double c = final_load_time / 2.0;
5990 * const double r = 200.0 * 0.03 / c;
5992 * const double load = final_load * std::exp(r * current_time)
5993 * / ( std::exp(c * current_time) + std::exp(r * current_time));
6001 * return Tensor<1,dim>();
6008 * <a name="ExamplestoreproduceexperimentsbyBuddayetal2017"></a>
6009 * <h3>Examples to reproduce experiments by Budday et al. 2017</h3>
6010 * We group the definition of the geometry, boundary and loading conditions specific to
6011 * the examples to reproduce experiments by Budday et al. 2017 into specific classes.
6016 * <a name="BaseclassCubegeometryandloadingpattern"></a>
6017 * <h4>Base class: Cube geometry and loading pattern</h4>
6020 * template <int dim>
6021 * class BrainBudday2017BaseCube
6022 * : public Solid<dim>
6025 * BrainBudday2017BaseCube (const Parameters::AllParameters ¶meters)
6026 * : Solid<dim> (parameters)
6029 * virtual ~BrainBudday2017BaseCube () {}
6033 * make_grid() override
6035 * GridGenerator::hyper_cube(this->triangulation,
6040 * typename Triangulation<dim>::active_cell_iterator cell =
6041 * this->triangulation.begin_active(), endc = this->triangulation.end();
6042 * for (; cell != endc; ++cell)
6044 * for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
6045 * if (cell->face(face)->at_boundary() == true &&
6046 * ( cell->face(face)->boundary_id() == 0 ||
6047 * cell->face(face)->boundary_id() == 1 ||
6048 * cell->face(face)->boundary_id() == 2 ||
6049 * cell->face(face)->boundary_id() == 3 ) )
6051 * cell->face(face)->set_boundary_id(100);
6055 * GridTools::scale(this->parameters.scale, this->triangulation);
6056 * this->triangulation.refine_global(std::max (1U, this->parameters.global_refinement));
6060 * get_prescribed_fluid_flow (const types::boundary_id &boundary_id,
6061 * const Point<dim> &pt) const override
6064 * (void)boundary_id;
6068 * virtual std::pair<types::boundary_id,types::boundary_id>
6069 * get_drained_boundary_id_for_output() const override
6071 * return std::make_pair(100,100);
6078 * <a name="DerivedclassUniaxialboundaryconditions"></a>
6079 * <h4>Derived class: Uniaxial boundary conditions</h4>
6082 * template <int dim>
6083 * class BrainBudday2017CubeTensionCompression
6084 * : public BrainBudday2017BaseCube<dim>
6087 * BrainBudday2017CubeTensionCompression (const Parameters::AllParameters ¶meters)
6088 * : BrainBudday2017BaseCube<dim> (parameters)
6091 * virtual ~BrainBudday2017CubeTensionCompression () {}
6095 * define_tracked_vertices(std::vector<Point<dim> > &tracked_vertices) override
6097 * tracked_vertices[0][0] = 0.5*this->parameters.scale;
6098 * tracked_vertices[0][1] = 0.5*this->parameters.scale;
6099 * tracked_vertices[0][2] = 1.0*this->parameters.scale;
6101 * tracked_vertices[1][0] = 0.5*this->parameters.scale;
6102 * tracked_vertices[1][1] = 0.5*this->parameters.scale;
6103 * tracked_vertices[1][2] = 0.5*this->parameters.scale;
6107 * make_dirichlet_constraints(AffineConstraints<double> &constraints) override
6109 * if (this->time.get_timestep() < 2)
6111 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
6113 * Functions::ConstantFunction<dim>(this->parameters.drained_pressure,this->n_components),
6115 * (this->fe.component_mask(this->pressure)));
6119 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6121 * Functions::ZeroFunction<dim>(this->n_components),
6123 * (this->fe.component_mask(this->pressure)));
6125 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6127 * Functions::ZeroFunction<dim>(this->n_components),
6129 * this->fe.component_mask(this->z_displacement) );
6131 * Point<dim> fix_node(0.5*this->parameters.scale, 0.5*this->parameters.scale, 0.0);
6132 * typename DoFHandler<dim>::active_cell_iterator
6133 * cell = this->dof_handler_ref.begin_active(), endc = this->dof_handler_ref.end();
6134 * for (; cell != endc; ++cell)
6135 * for (unsigned int node = 0; node < GeometryInfo<dim>::vertices_per_cell; ++node)
6137 * if ( (abs(cell->vertex(node)[2]-fix_node[2]) < (1e-6 * this->parameters.scale))
6138 * && (abs(cell->vertex(node)[0]-fix_node[0]) < (1e-6 * this->parameters.scale)))
6139 * constraints.add_line(cell->vertex_dof_index(node, 0));
6141 * if ( (abs(cell->vertex(node)[2]-fix_node[2]) < (1e-6 * this->parameters.scale))
6142 * && (abs(cell->vertex(node)[1]-fix_node[1]) < (1e-6 * this->parameters.scale)))
6143 * constraints.add_line(cell->vertex_dof_index(node, 1));
6146 * if (this->parameters.load_type == "displacement")
6148 * const std::vector<double> value = get_dirichlet_load(5,2);
6149 * FEValuesExtractors::Scalar direction;
6150 * direction = this->z_displacement;
6152 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6154 * Functions::ConstantFunction<dim>(value[2],this->n_components),
6156 * this->fe.component_mask(direction));
6160 * virtual Tensor<1,dim>
6161 * get_neumann_traction (const types::boundary_id &boundary_id,
6162 * const Point<dim> &pt,
6163 * const Tensor<1,dim> &N) const override
6165 * if (this->parameters.load_type == "pressure")
6167 * if (boundary_id == 5)
6169 * const double final_load = this->parameters.load;
6170 * const double current_time = this->time.get_current();
6171 * const double final_time = this->time.get_end();
6172 * const double num_cycles = 3.0;
6174 * return final_load/2.0 * (1.0 - std::sin(numbers::PI * (2.0*num_cycles*current_time/final_time + 0.5))) * N;
6180 * return Tensor<1,dim>();
6183 * virtual types::boundary_id
6184 * get_reaction_boundary_id_for_output() const override
6189 * virtual std::vector<double>
6190 * get_dirichlet_load(const types::boundary_id &boundary_id,
6191 * const int &direction) const override
6193 * std::vector<double> displ_incr(dim,0.0);
6195 * if ( (boundary_id == 5) && (direction == 2) )
6197 * const double final_displ = this->parameters.load;
6198 * const double current_time = this->time.get_current();
6199 * const double final_time = this->time.get_end();
6200 * const double delta_time = this->time.get_delta_t();
6201 * const double num_cycles = 3.0;
6202 * double current_displ = 0.0;
6203 * double previous_displ = 0.0;
6205 * if (this->parameters.num_cycle_sets == 1)
6207 * current_displ = final_displ/2.0 * (1.0
6208 * - std::sin(numbers::PI * (2.0*num_cycles*current_time/final_time + 0.5)));
6209 * previous_displ = final_displ/2.0 * (1.0
6210 * - std::sin(numbers::PI * (2.0*num_cycles*(current_time-delta_time)/final_time + 0.5)));
6214 * if ( current_time <= (final_time*1.0/3.0) )
6216 * current_displ = final_displ/2.0 * (1.0 - std::sin(numbers::PI *
6217 * (2.0*num_cycles*current_time/(final_time*1.0/3.0) + 0.5)));
6218 * previous_displ = final_displ/2.0 * (1.0 - std::sin(numbers::PI *
6219 * (2.0*num_cycles*(current_time-delta_time)/(final_time*1.0/3.0) + 0.5)));
6223 * current_displ = final_displ * (1.0 - std::sin(numbers::PI *
6224 * (2.0*num_cycles*current_time / (final_time*2.0/3.0)
6225 * - (num_cycles - 0.5) )));
6226 * previous_displ = final_displ * (1.0 - std::sin(numbers::PI *
6227 * (2.0*num_cycles*(current_time-delta_time) / (final_time*2.0/3.0)
6228 * - (num_cycles - 0.5))));
6231 * displ_incr[2] = current_displ - previous_displ;
6233 * return displ_incr;
6240 * <a name="DerivedclassNolateraldisplacementinloadingsurfaces"></a>
6241 * <h4>Derived class: No lateral displacement in loading surfaces</h4>
6244 * template <int dim>
6245 * class BrainBudday2017CubeTensionCompressionFullyFixed
6246 * : public BrainBudday2017BaseCube<dim>
6249 * BrainBudday2017CubeTensionCompressionFullyFixed (const Parameters::AllParameters ¶meters)
6250 * : BrainBudday2017BaseCube<dim> (parameters)
6253 * virtual ~BrainBudday2017CubeTensionCompressionFullyFixed () {}
6257 * define_tracked_vertices(std::vector<Point<dim> > &tracked_vertices) override
6259 * tracked_vertices[0][0] = 0.5*this->parameters.scale;
6260 * tracked_vertices[0][1] = 0.5*this->parameters.scale;
6261 * tracked_vertices[0][2] = 1.0*this->parameters.scale;
6263 * tracked_vertices[1][0] = 0.5*this->parameters.scale;
6264 * tracked_vertices[1][1] = 0.5*this->parameters.scale;
6265 * tracked_vertices[1][2] = 0.5*this->parameters.scale;
6269 * make_dirichlet_constraints(AffineConstraints<double> &constraints) override
6271 * if (this->time.get_timestep() < 2)
6273 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
6275 * Functions::ConstantFunction<dim>(this->parameters.drained_pressure,this->n_components),
6277 * (this->fe.component_mask(this->pressure)));
6281 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6283 * Functions::ZeroFunction<dim>(this->n_components),
6285 * (this->fe.component_mask(this->pressure)));
6288 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6290 * Functions::ZeroFunction<dim>(this->n_components),
6292 * (this->fe.component_mask(this->x_displacement) |
6293 * this->fe.component_mask(this->y_displacement) |
6294 * this->fe.component_mask(this->z_displacement) ));
6297 * if (this->parameters.load_type == "displacement")
6299 * const std::vector<double> value = get_dirichlet_load(5,2);
6300 * FEValuesExtractors::Scalar direction;
6301 * direction = this->z_displacement;
6303 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6305 * Functions::ConstantFunction<dim>(value[2],this->n_components),
6307 * this->fe.component_mask(direction) );
6309 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6311 * Functions::ZeroFunction<dim>(this->n_components),
6313 * (this->fe.component_mask(this->x_displacement) |
6314 * this->fe.component_mask(this->y_displacement) ));
6318 * virtual Tensor<1,dim>
6319 * get_neumann_traction (const types::boundary_id &boundary_id,
6320 * const Point<dim> &pt,
6321 * const Tensor<1,dim> &N) const override
6323 * if (this->parameters.load_type == "pressure")
6325 * if (boundary_id == 5)
6327 * const double final_load = this->parameters.load;
6328 * const double current_time = this->time.get_current();
6329 * const double final_time = this->time.get_end();
6330 * const double num_cycles = 3.0;
6332 * return final_load/2.0 * (1.0 - std::sin(numbers::PI * (2.0*num_cycles*current_time/final_time + 0.5))) * N;
6338 * return Tensor<1,dim>();
6341 * virtual types::boundary_id
6342 * get_reaction_boundary_id_for_output() const override
6347 * virtual std::vector<double>
6348 * get_dirichlet_load(const types::boundary_id &boundary_id,
6349 * const int &direction) const override
6351 * std::vector<double> displ_incr(dim,0.0);
6353 * if ( (boundary_id == 5) && (direction == 2) )
6355 * const double final_displ = this->parameters.load;
6356 * const double current_time = this->time.get_current();
6357 * const double final_time = this->time.get_end();
6358 * const double delta_time = this->time.get_delta_t();
6359 * const double num_cycles = 3.0;
6360 * double current_displ = 0.0;
6361 * double previous_displ = 0.0;
6363 * if (this->parameters.num_cycle_sets == 1)
6365 * current_displ = final_displ/2.0 * (1.0 - std::sin(numbers::PI * (2.0*num_cycles*current_time/final_time + 0.5)));
6366 * previous_displ = final_displ/2.0 * (1.0 - std::sin(numbers::PI * (2.0*num_cycles*(current_time-delta_time)/final_time + 0.5)));
6370 * if ( current_time <= (final_time*1.0/3.0) )
6372 * current_displ = final_displ/2.0 * (1.0 - std::sin(numbers::PI *
6373 * (2.0*num_cycles*current_time/(final_time*1.0/3.0) + 0.5)));
6374 * previous_displ = final_displ/2.0 * (1.0 - std::sin(numbers::PI *
6375 * (2.0*num_cycles*(current_time-delta_time)/(final_time*1.0/3.0) + 0.5)));
6379 * current_displ = final_displ * (1.0 - std::sin(numbers::PI *
6380 * (2.0*num_cycles*current_time / (final_time*2.0/3.0)
6381 * - (num_cycles - 0.5) )));
6382 * previous_displ = final_displ * (1.0 - std::sin(numbers::PI *
6383 * (2.0*num_cycles*(current_time-delta_time) / (final_time*2.0/3.0)
6384 * - (num_cycles - 0.5))));
6387 * displ_incr[2] = current_displ - previous_displ;
6389 * return displ_incr;
6396 * <a name="DerivedclassNolateralorverticaldisplacementinloadingsurface"></a>
6397 * <h4>Derived class: No lateral or vertical displacement in loading surface</h4>
6400 * template <int dim>
6401 * class BrainBudday2017CubeShearFullyFixed
6402 * : public BrainBudday2017BaseCube<dim>
6405 * BrainBudday2017CubeShearFullyFixed (const Parameters::AllParameters ¶meters)
6406 * : BrainBudday2017BaseCube<dim> (parameters)
6409 * virtual ~BrainBudday2017CubeShearFullyFixed () {}
6413 * define_tracked_vertices(std::vector<Point<dim> > &tracked_vertices) override
6415 * tracked_vertices[0][0] = 0.75*this->parameters.scale;
6416 * tracked_vertices[0][1] = 0.5*this->parameters.scale;
6417 * tracked_vertices[0][2] = 0.0*this->parameters.scale;
6419 * tracked_vertices[1][0] = 0.25*this->parameters.scale;
6420 * tracked_vertices[1][1] = 0.5*this->parameters.scale;
6421 * tracked_vertices[1][2] = 0.0*this->parameters.scale;
6425 * make_dirichlet_constraints(AffineConstraints<double> &constraints) override
6427 * if (this->time.get_timestep() < 2)
6429 * VectorTools::interpolate_boundary_values(this->dof_handler_ref,
6431 * Functions::ConstantFunction<dim>(this->parameters.drained_pressure,this->n_components),
6433 * (this->fe.component_mask(this->pressure)));
6437 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6439 * Functions::ZeroFunction<dim>(this->n_components),
6441 * (this->fe.component_mask(this->pressure)));
6444 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6446 * Functions::ZeroFunction<dim>(this->n_components),
6448 * (this->fe.component_mask(this->x_displacement) |
6449 * this->fe.component_mask(this->y_displacement) |
6450 * this->fe.component_mask(this->z_displacement) ));
6453 * if (this->parameters.load_type == "displacement")
6455 * const std::vector<double> value = get_dirichlet_load(4,0);
6456 * FEValuesExtractors::Scalar direction;
6457 * direction = this->x_displacement;
6459 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6461 * Functions::ConstantFunction<dim>(value[0],this->n_components),
6463 * this->fe.component_mask(direction));
6465 * VectorTools::interpolate_boundary_values( this->dof_handler_ref,
6467 * Functions::ZeroFunction<dim>(this->n_components),
6469 * (this->fe.component_mask(this->y_displacement) |
6470 * this->fe.component_mask(this->z_displacement) ));
6474 * virtual Tensor<1,dim>
6475 * get_neumann_traction (const types::boundary_id &boundary_id,
6476 * const Point<dim> &pt,
6477 * const Tensor<1,dim> &N) const override
6479 * if (this->parameters.load_type == "pressure")
6481 * if (boundary_id == 4)
6483 * const double final_load = this->parameters.load;
6484 * const double current_time = this->time.get_current();
6485 * const double final_time = this->time.get_end();
6486 * const double num_cycles = 3.0;
6487 * const Tensor<1,3> axis ({0.0,1.0,0.0});
6488 * const double angle = numbers::PI;
6489 * static const Tensor< 2, dim, double> R(Physics::Transformations::Rotations::rotation_matrix_3d(axis,angle));
6491 * return (final_load * (std::sin(2.0*(numbers::PI)*num_cycles*current_time/final_time)) * (R * N));
6497 * return Tensor<1,dim>();
6500 * virtual types::boundary_id
6501 * get_reaction_boundary_id_for_output() const override
6506 * virtual std::vector<double>
6507 * get_dirichlet_load(const types::boundary_id &boundary_id,
6508 * const int &direction) const override
6510 * std::vector<double> displ_incr (dim, 0.0);
6512 * if ( (boundary_id == 4) && (direction == 0) )
6514 * const double final_displ = this->parameters.load;
6515 * const double current_time = this->time.get_current();
6516 * const double final_time = this->time.get_end();
6517 * const double delta_time = this->time.get_delta_t();
6518 * const double num_cycles = 3.0;
6519 * double current_displ = 0.0;
6520 * double previous_displ = 0.0;
6522 * if (this->parameters.num_cycle_sets == 1)
6524 * current_displ = final_displ * (std::sin(2.0*(numbers::PI)*num_cycles*current_time/final_time));
6525 * previous_displ = final_displ * (std::sin(2.0*(numbers::PI)*num_cycles*(current_time-delta_time)/final_time));
6529 * AssertThrow(false, ExcMessage("Problem type not defined. Budday shear experiments implemented only for one set of cycles."));
6531 * displ_incr[0] = current_displ - previous_displ;
6533 * return displ_incr;
6542 * <a name="Mainfunction"></a>
6543 * <h3>Main function</h3>
6544 * Lastly we provide the main driver function which is similar to the other tutorials.
6547 * int main (int argc, char *argv[])
6549 * using namespace dealii;
6550 * using namespace NonLinearPoroViscoElasticity;
6552 * const unsigned int n_tbb_processes = 1;
6553 * Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, n_tbb_processes);
6557 * Parameters::AllParameters parameters ("parameters.prm");
6558 * if (parameters.geom_type == "Ehlers_tube_step_load")
6560 * VerificationEhlers1999StepLoad<3> solid_3d(parameters);
6563 * else if (parameters.geom_type == "Ehlers_tube_increase_load")
6565 * VerificationEhlers1999IncreaseLoad<3> solid_3d(parameters);
6568 * else if (parameters.geom_type == "Ehlers_cube_consolidation")
6570 * VerificationEhlers1999CubeConsolidation<3> solid_3d(parameters);
6573 * else if (parameters.geom_type == "Franceschini_consolidation")
6575 * Franceschini2006Consolidation<3> solid_3d(parameters);
6578 * else if (parameters.geom_type == "Budday_cube_tension_compression")
6580 * BrainBudday2017CubeTensionCompression<3> solid_3d(parameters);
6583 * else if (parameters.geom_type == "Budday_cube_tension_compression_fully_fixed")
6585 * BrainBudday2017CubeTensionCompressionFullyFixed<3> solid_3d(parameters);
6588 * else if (parameters.geom_type == "Budday_cube_shear_fully_fixed")
6590 * BrainBudday2017CubeShearFullyFixed<3> solid_3d(parameters);
6595 * AssertThrow(false, ExcMessage("Problem type not defined. Current setting: " + parameters.geom_type));
6599 * catch (std::exception &exc)
6601 * if (Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0)
6603 * std::cerr << std::endl << std::endl
6604 * << "----------------------------------------------------"
6606 * std::cerr << "Exception on processing: " << std::endl << exc.what()
6607 * << std::endl << "Aborting!" << std::endl
6608 * << "----------------------------------------------------"
6616 * if (Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0)
6618 * std::cerr << std::endl << std::endl
6619 * << "----------------------------------------------------"
6621 * std::cerr << "Unknown exception!" << std::endl << "Aborting!"
6623 * << "----------------------------------------------------"
void reinit(const Vector &v, const bool omit_zeroing_entries=false, const bool allow_different_maps=false)
__global__ void set(Number *val, const Number s, const size_type N)
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrow(cond, exc)
typename ActiveSelector::active_cell_iterator active_cell_iterator
LinearOperator< Range, Domain, Payload > linear_operator(const OperatorExemplar &, const Matrix &)
void loop(ITERATOR begin, std_cxx20::type_identity_t< ITERATOR > end, DOFINFO &dinfo, INFOBOX &info, const std::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &cell_worker, const std::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &boundary_worker, const std::function< void(DOFINFO &, DOFINFO &, typename INFOBOX::CellInfo &, typename INFOBOX::CellInfo &)> &face_worker, ASSEMBLER &assembler, const LoopControl &lctrl=LoopControl())
void make_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern, const AffineConstraints< number > &constraints=AffineConstraints< number >(), const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
@ update_values
Shape function values.
@ update_normal_vectors
Normal vectors.
@ update_JxW_values
Transformed quadrature weights.
@ update_gradients
Shape function gradients.
@ update_quadrature_points
Transformed quadrature points.
void approximate(SynchronousIterators< std::tuple< typename DoFHandler< dim, spacedim >::active_cell_iterator, Vector< float >::iterator > > const &cell, const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof_handler, const InputVector &solution, const unsigned int component)
void component_wise(DoFHandler< dim, spacedim > &dof_handler, const std::vector< unsigned int > &target_component=std::vector< unsigned int >())
void Cuthill_McKee(DoFHandler< dim, spacedim > &dof_handler, const bool reversed_numbering=false, const bool use_constraints=false, const std::vector< types::global_dof_index > &starting_indices=std::vector< types::global_dof_index >())
@ valid
Iterator points to a valid object.
@ matrix
Contents is actually a matrix.
@ diagonal
Matrix is diagonal.
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.)
double norm(const FEValuesBase< dim > &fe, const ArrayView< const std::vector< Tensor< 1, dim > > > &Du)
std::enable_if_t< IsBlockVector< VectorType >::value, unsigned int > n_blocks(const VectorType &vector)
Point< spacedim > point(const gp_Pnt &p, const double tolerance=1e-10)
SymmetricTensor< 2, dim, Number > C(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
Tensor< 2, dim, Number > F(const Tensor< 2, dim, Number > &Grad_u)
constexpr ReturnType< rank, T >::value_type & extract(T &t, const ArrayType &indices)
VectorType::value_type * end(VectorType &V)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
T reduce(const T &local_value, const MPI_Comm comm, const std::function< T(const T &, const T &)> &combiner, const unsigned int root_process=0)
void run(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)
void abort(const ExceptionBase &exc) noexcept
bool check(const ConstraintKinds kind_in, const unsigned int dim)
void copy(const T *begin, const T *end, U *dest)
int(&) functions(const void *v1, const void *v2)
void assemble(const MeshWorker::DoFInfoBox< dim, DOFINFO > &dinfo, A *assembler)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
DEAL_II_HOST constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)
SymmetricTensorEigenvectorMethod