789 *
#include <deal.II/grid/tria.h>
790 *
#include <deal.II/grid/grid_generator.h>
791 *
#include <deal.II/grid/grid_refinement.h>
792 *
#include <deal.II/grid/grid_out.h>
793 *
#include <deal.II/grid/grid_in.h>
794 *
#include <deal.II/grid/manifold_lib.h>
796 *
#include <deal.II/dofs/dof_handler.h>
797 *
#include <deal.II/dofs/dof_tools.h>
798 *
#include <deal.II/dofs/dof_renumbering.h>
800 *
#include <deal.II/fe/fe_values.h>
801 *
#include <deal.II/fe/fe_system.h>
802 *
#include <deal.II/fe/fe_q.h>
803 *
#include <deal.II/fe/fe_dgp_monomial.h>
804 *
#include <deal.II/fe/mapping_q_eulerian.h>
806 *
#include <deal.II/base/timer.h>
807 *
#include <deal.II/base/quadrature_point_data.h>
808 *
#include <deal.II/base/parameter_handler.h>
810 *
#include <deal.II/lac/affine_constraints.h>
811 *
#include <deal.II/lac/vector.h>
812 *
#include <deal.II/lac/full_matrix.h>
813 *
#include <deal.II/lac/sparse_matrix.h>
814 *
#include <deal.II/lac/dynamic_sparsity_pattern.h>
815 *
#include <deal.II/lac/block_sparse_matrix.h>
816 *
#include <deal.II/lac/block_vector.h>
819 *
#include <deal.II/numerics/vector_tools.h>
820 *
#include <deal.II/numerics/matrix_tools.h>
821 *
#include <deal.II/numerics/data_out.h>
823 *
#include <deal.II/lac/solver_cg.h>
824 *
#include <deal.II/lac/precondition.h>
826 *
#include <deal.II/lac/packaged_operation.h>
827 *
#include <deal.II/lac/precondition_selector.h>
828 *
#include <deal.II/lac/solver_selector.h>
829 *
#include <deal.II/lac/sparse_direct.h>
831 *
#include <deal.II/numerics/error_estimator.h>
833 *
#include <deal.II/physics/elasticity/standard_tensors.h>
835 *
#include <deal.II/base/quadrature_point_data.h>
837 *
#include <deal.II/grid/grid_tools.h>
839 *
#include <deal.II/base/work_stream.h>
841 *
#include <deal.II/numerics/solution_transfer.h>
844 *
#include <iostream>
845 *
#include <deal.II/base/logstream.h>
847 *
#include
"SpectrumDecomposition.h"
848 *
#include
"Utilities.h"
850 *
namespace PhaseField
860 *
void right_hand_side(
const std::vector<
Point<dim>> &points,
867 *
ExcDimensionMismatch(
values.size(), points.size()));
868 *
Assert(dim >= 2, ExcNotImplemented());
870 *
for (
unsigned int point_n = 0; point_n < points.size(); ++point_n)
874 *
values[point_n][0] = fx;
875 *
values[point_n][1] = fy;
879 *
values[point_n][0] = fx;
880 *
values[point_n][1] = fy;
881 *
values[point_n][2] = fz;
886 *
double degradation_function(
const double d)
888 *
return (1.0 - d) * (1.0 -
d);
891 *
double degradation_function_derivative(
const double d)
893 *
return 2.0 * (
d - 1.0);
896 *
double degradation_function_2nd_order_derivative(
const double d)
902 *
namespace Parameters
906 *
unsigned int m_scenario;
907 *
std::string m_logfile_name;
908 *
bool m_output_iteration_history;
909 *
std::string m_type_nonlinear_solver;
910 *
std::string m_type_line_search;
911 *
std::string m_type_linear_solver;
912 *
std::string m_refinement_strategy;
913 *
unsigned int m_LBFGS_m;
914 *
unsigned int m_global_refine_times;
915 *
unsigned int m_local_prerefine_times;
916 *
unsigned int m_max_adaptive_refine_times;
917 *
int m_max_allowed_refinement_level;
918 *
double m_phasefield_refine_threshold;
919 *
double m_allowed_max_h_l_ratio;
920 *
unsigned int m_total_material_regions;
921 *
std::string m_material_file_name;
922 *
int m_reaction_force_face_id;
930 *
prm.enter_subsection(
"Scenario");
932 *
prm.declare_entry(
"Scenario number",
935 *
"Geometry, loading and boundary conditions scenario");
937 *
prm.declare_entry(
"Log file name",
940 *
"Name of the file for log");
942 *
prm.declare_entry(
"Output iteration history",
945 *
"Shall we write iteration history to the log file?");
947 *
prm.declare_entry(
"Nonlinear solver type",
950 *
"Type of solver used to solve the nonlinear system");
952 *
prm.declare_entry(
"Line search type",
955 *
"Type of line search method, the gradient-based method "
956 *
"should be preferred since it is generally faster");
958 *
prm.declare_entry(
"Linear solver type",
961 *
"Type of solver used to solve the linear system B0");
963 *
prm.declare_entry(
"Mesh refinement strategy",
966 *
"Mesh refinement strategy: pre-refine or adaptive-refine");
968 *
prm.declare_entry(
"LBFGS m",
971 *
"Number of vectors used for LBFGS");
973 *
prm.declare_entry(
"Global refinement times",
976 *
"Global refinement times (across the entire domain)");
978 *
prm.declare_entry(
"Local prerefinement times",
981 *
"Local pre-refinement times (assume crack path is known a priori), "
982 *
"only refine along the crack path.");
984 *
prm.declare_entry(
"Max adaptive refinement times",
987 *
"Maximum number of adaptive refinement times allowed in each step");
989 *
prm.declare_entry(
"Max allowed refinement level",
992 *
"Maximum allowed cell refinement level");
994 *
prm.declare_entry(
"Phasefield refine threshold",
997 *
"Phasefield-based refinement threshold value");
999 *
prm.declare_entry(
"Allowed max hl ratio",
1002 *
"Allowed maximum ratio between mesh size h and length scale l");
1004 *
prm.declare_entry(
"Material regions",
1007 *
"Number of material regions");
1009 *
prm.declare_entry(
"Material data file",
1012 *
"Material data file");
1014 *
prm.declare_entry(
"Reaction force face ID",
1017 *
"Face id where reaction forces should be calculated "
1018 *
"(negative integer means not to calculate reaction force)");
1020 *
prm.leave_subsection();
1025 *
prm.enter_subsection(
"Scenario");
1027 *
m_scenario = prm.get_integer(
"Scenario number");
1028 *
m_logfile_name = prm.get(
"Log file name");
1029 *
m_output_iteration_history = prm.get_bool(
"Output iteration history");
1030 *
m_type_nonlinear_solver = prm.get(
"Nonlinear solver type");
1031 *
m_type_line_search = prm.get(
"Line search type");
1032 *
m_type_linear_solver = prm.get(
"Linear solver type");
1033 *
m_refinement_strategy = prm.get(
"Mesh refinement strategy");
1034 *
m_LBFGS_m = prm.get_integer(
"LBFGS m");
1035 *
m_global_refine_times = prm.get_integer(
"Global refinement times");
1036 *
m_local_prerefine_times = prm.get_integer(
"Local prerefinement times");
1037 *
m_max_adaptive_refine_times = prm.get_integer(
"Max adaptive refinement times");
1038 *
m_max_allowed_refinement_level = prm.get_integer(
"Max allowed refinement level");
1039 *
m_phasefield_refine_threshold = prm.get_double(
"Phasefield refine threshold");
1040 *
m_allowed_max_h_l_ratio = prm.get_double(
"Allowed max hl ratio");
1041 *
m_total_material_regions = prm.get_integer(
"Material regions");
1042 *
m_material_file_name = prm.get(
"Material data file");
1043 *
m_reaction_force_face_id = prm.get_integer(
"Reaction force face ID");
1045 *
prm.leave_subsection();
1050 *
unsigned int m_poly_degree;
1051 *
unsigned int m_quad_order;
1061 *
prm.enter_subsection(
"Finite element system");
1063 *
prm.declare_entry(
"Polynomial degree",
1066 *
"Phase field polynomial order");
1068 *
prm.declare_entry(
"Quadrature order",
1071 *
"Gauss quadrature order");
1073 *
prm.leave_subsection();
1078 *
prm.enter_subsection(
"Finite element system");
1080 *
m_poly_degree = prm.get_integer(
"Polynomial degree");
1081 *
m_quad_order = prm.get_integer(
"Quadrature order");
1083 *
prm.leave_subsection();
1088 * body force (N/m^3)
1093 *
double m_x_component;
1094 *
double m_y_component;
1095 *
double m_z_component;
1104 *
prm.enter_subsection(
"Body force");
1106 *
prm.declare_entry(
"Body force x component",
1109 *
"Body force x-component (N/m^3)");
1111 *
prm.declare_entry(
"Body force y component",
1114 *
"Body force y-component (N/m^3)");
1116 *
prm.declare_entry(
"Body force z component",
1119 *
"Body force z-component (N/m^3)");
1121 *
prm.leave_subsection();
1126 *
prm.enter_subsection(
"Body force");
1128 *
m_x_component = prm.get_double(
"Body force x component");
1129 *
m_y_component = prm.get_double(
"Body force y component");
1130 *
m_z_component = prm.get_double(
"Body force z component");
1132 *
prm.leave_subsection();
1135 *
struct NonlinearSolver
1137 *
unsigned int m_max_iterations_NR;
1138 *
unsigned int m_max_iterations_BFGS;
1139 *
bool m_relative_residual;
1141 *
double m_tol_u_residual;
1142 *
double m_tol_d_residual;
1143 *
double m_tol_u_incr;
1144 *
double m_tol_d_incr;
1153 *
prm.enter_subsection(
"Nonlinear solver");
1155 *
prm.declare_entry(
"Max iterations Newton-Raphson",
1158 *
"Number of Newton-Raphson iterations allowed");
1160 *
prm.declare_entry(
"Max iterations BFGS",
1163 *
"Number of BFGS iterations allowed");
1165 *
prm.declare_entry(
"Relative residual",
1168 *
"Shall we use relative residual for convergence?");
1170 *
prm.declare_entry(
"Tolerance displacement residual",
1173 *
"Displacement residual tolerance");
1175 *
prm.declare_entry(
"Tolerance phasefield residual",
1178 *
"Phasefield residual tolerance");
1180 *
prm.declare_entry(
"Tolerance displacement increment",
1183 *
"Displacement increment tolerance");
1185 *
prm.declare_entry(
"Tolerance phasefield increment",
1188 *
"Phasefield increment tolerance");
1190 *
prm.leave_subsection();
1195 *
prm.enter_subsection(
"Nonlinear solver");
1197 *
m_max_iterations_NR = prm.get_integer(
"Max iterations Newton-Raphson");
1198 *
m_max_iterations_BFGS = prm.get_integer(
"Max iterations BFGS");
1199 *
m_relative_residual = prm.get_bool(
"Relative residual");
1201 *
m_tol_u_residual = prm.get_double(
"Tolerance displacement residual");
1202 *
m_tol_d_residual = prm.get_double(
"Tolerance phasefield residual");
1203 *
m_tol_u_incr = prm.get_double(
"Tolerance displacement increment");
1204 *
m_tol_d_incr = prm.get_double(
"Tolerance phasefield increment");
1206 *
prm.leave_subsection();
1211 *
double m_end_time;
1212 *
std::string m_time_file_name;
1221 *
prm.enter_subsection(
"Time");
1225 *
prm.declare_entry(
"Time data file",
1228 *
"Time data file");
1230 *
prm.leave_subsection();
1235 *
prm.enter_subsection(
"Time");
1237 *
m_end_time = prm.get_double(
"End time");
1238 *
m_time_file_name = prm.get(
"Time data file");
1240 *
prm.leave_subsection();
1243 *
struct AllParameters :
public Scenario,
1246 *
public NonlinearSolver,
1249 *
AllParameters(
const std::string &input_file);
1256 *
AllParameters::AllParameters(
const std::string &input_file)
1259 *
declare_parameters(prm);
1260 *
prm.parse_input(input_file);
1261 *
parse_parameters(prm);
1266 *
Scenario::declare_parameters(prm);
1267 *
FESystem::declare_parameters(prm);
1268 *
BodyForce::declare_parameters(prm);
1269 *
NonlinearSolver::declare_parameters(prm);
1270 *
TimeInfo::declare_parameters(prm);
1275 *
Scenario::parse_parameters(prm);
1276 *
FESystem::parse_parameters(prm);
1277 *
BodyForce::parse_parameters(prm);
1278 *
NonlinearSolver::parse_parameters(prm);
1279 *
TimeInfo::parse_parameters(prm);
1286 *
Time(
const double time_end)
1288 *
, m_time_current(0.0)
1289 *
, m_time_end(time_end)
1291 *
, m_magnitude(1.0)
1294 *
virtual ~Time() =
default;
1296 *
double current() const
1298 *
return m_time_current;
1300 *
double end() const
1302 *
return m_time_end;
1304 *
double get_delta_t() const
1308 *
double get_magnitude() const
1310 *
return m_magnitude;
1312 *
unsigned int get_timestep() const
1314 *
return m_timestep;
1316 *
void increment(std::vector<std::array<double, 4>> time_table)
1318 *
double t_1, t_delta, t_magnitude;
1319 *
for (
auto & time_group : time_table)
1321 *
t_1 = time_group[1];
1322 *
t_delta = time_group[2];
1323 *
t_magnitude = time_group[3];
1325 *
if (m_time_current < t_1 - 1.0e-6*t_delta)
1327 *
m_delta_t = t_delta;
1328 *
m_magnitude = t_magnitude;
1333 *
m_time_current += m_delta_t;
1338 *
unsigned int m_timestep;
1339 *
double m_time_current;
1340 *
const double m_time_end;
1342 *
double m_magnitude;
1345 *
template <
int dim>
1346 *
class LinearIsotropicElasticityAdditiveSplit
1349 *
LinearIsotropicElasticityAdditiveSplit(
const double lame_lambda,
1350 *
const double lame_mu,
1351 *
const double residual_k,
1352 *
const double length_scale,
1353 *
const double viscosity,
1355 *
: m_lame_lambda(lame_lambda)
1356 *
, m_lame_mu(lame_mu)
1357 *
, m_residual_k(residual_k)
1358 *
, m_length_scale(length_scale)
1359 *
, m_eta(viscosity)
1361 *
, m_phase_field_value(0.0)
1367 *
, m_strain_energy_positive(0.0)
1368 *
, m_strain_energy_negative(0.0)
1369 *
, m_strain_energy_total(0.0)
1370 *
, m_crack_energy_dissipation(0.0)
1372 *
Assert( ( lame_lambda / (2*(lame_lambda + lame_mu)) <= 0.5)
1373 *
& ( lame_lambda / (2*(lame_lambda + lame_mu)) >=-1.0),
1374 *
ExcInternalError() );
1379 *
return m_mechanical_C;
1389 *
return m_stress_positive;
1392 *
double get_positive_strain_energy() const
1394 *
return m_strain_energy_positive;
1397 *
double get_negative_strain_energy() const
1399 *
return m_strain_energy_negative;
1402 *
double get_total_strain_energy() const
1404 *
return m_strain_energy_total;
1407 *
double get_crack_energy_dissipation() const
1409 *
return m_crack_energy_dissipation;
1412 *
double get_phase_field_value() const
1414 *
return m_phase_field_value;
1419 *
return m_grad_phasefield;
1423 *
const double phase_field_value,
1425 *
const double phase_field_value_previous_step,
1426 *
const double delta_time)
1428 *
m_strain = strain;
1429 *
m_phase_field_value = phase_field_value;
1430 *
m_grad_phasefield = grad_phasefield;
1433 *
usr_spectrum_decomposition::spectrum_decomposition<dim>(m_strain,
1442 *
usr_spectrum_decomposition::positive_negative_projectors(
eigenvalues,
1444 *
projector_positive,
1445 *
projector_negative);
1448 *
const double degradation = degradation_function(m_phase_field_value) + m_residual_k;
1449 *
const double I_1 =
trace(m_strain);
1450 *
stress_positive = m_lame_lambda * usr_spectrum_decomposition::positive_ramp_function(I_1)
1452 *
+ 2 * m_lame_mu * strain_positive;
1453 *
stress_negative = m_lame_lambda * usr_spectrum_decomposition::negative_ramp_function(I_1)
1455 *
+ 2 * m_lame_mu * strain_negative;
1457 *
m_stress = degradation * stress_positive + stress_negative;
1458 *
m_stress_positive = stress_positive;
1461 *
C_positive = m_lame_lambda * usr_spectrum_decomposition::heaviside_function(I_1)
1463 *
+ 2 * m_lame_mu * projector_positive;
1464 *
C_negative = m_lame_lambda * usr_spectrum_decomposition::heaviside_function(-I_1)
1466 *
+ 2 * m_lame_mu * projector_negative;
1467 *
m_mechanical_C = degradation * C_positive + C_negative;
1469 *
m_strain_energy_positive = 0.5 * m_lame_lambda * usr_spectrum_decomposition::positive_ramp_function(I_1)
1470 *
* usr_spectrum_decomposition::positive_ramp_function(I_1)
1471 *
+ m_lame_mu * strain_positive * strain_positive;
1473 *
m_strain_energy_negative = 0.5 * m_lame_lambda * usr_spectrum_decomposition::negative_ramp_function(I_1)
1474 *
* usr_spectrum_decomposition::negative_ramp_function(I_1)
1475 *
+ m_lame_mu * strain_negative * strain_negative;
1477 *
m_strain_energy_total = degradation * m_strain_energy_positive + m_strain_energy_negative;
1479 *
m_crack_energy_dissipation = m_gc * ( 0.5 / m_length_scale * m_phase_field_value * m_phase_field_value
1480 *
+ 0.5 * m_length_scale * m_grad_phasefield * m_grad_phasefield)
1483 * the term due to viscosity regularization
1486 *
+ (m_phase_field_value - phase_field_value_previous_step)
1487 *
* (m_phase_field_value - phase_field_value_previous_step)
1488 *
* 0.5 * m_eta / delta_time;
1492 * (void)phase_field_value_previous_step;
1498 *
const double m_lame_lambda;
1499 *
const double m_lame_mu;
1500 *
const double m_residual_k;
1501 *
const double m_length_scale;
1502 *
const double m_eta;
1503 *
const double m_gc;
1504 *
double m_phase_field_value;
1510 *
double m_strain_energy_positive;
1511 *
double m_strain_energy_negative;
1512 *
double m_strain_energy_total;
1513 *
double m_crack_energy_dissipation;
1517 *
template <
int dim>
1518 *
class PointHistory
1522 *
: m_length_scale(0.0)
1524 *
, m_viscosity(0.0)
1525 *
, m_history_max_positive_strain_energy(0.0)
1528 *
virtual ~PointHistory() =
default;
1530 *
void setup_lqp(
const double lame_lambda,
1531 *
const double lame_mu,
1532 *
const double length_scale,
1534 *
const double viscosity,
1535 *
const double residual_k)
1538 *
std::make_shared<LinearIsotropicElasticityAdditiveSplit<dim>>(lame_lambda,
1544 *
m_history_max_positive_strain_energy = 0.0;
1545 *
m_length_scale = length_scale;
1547 *
m_viscosity = viscosity;
1553 *
const double phase_field_value,
1555 *
const double phase_field_value_previous_step,
1556 *
const double delta_time)
1558 *
m_material->update_material_data(strain, phase_field_value, grad_phasefield,
1559 *
phase_field_value_previous_step, delta_time);
1562 *
void update_history_variable()
1564 *
double current_positive_strain_energy = m_material->get_positive_strain_energy();
1565 *
m_history_max_positive_strain_energy = std::fmax(m_history_max_positive_strain_energy,
1566 *
current_positive_strain_energy);
1569 *
double get_current_positive_strain_energy() const
1571 *
return m_material->get_positive_strain_energy();
1576 *
return m_material->get_mechanical_C();
1581 *
return m_material->get_cauchy_stress();
1586 *
return m_material->get_cauchy_stress_positive();
1589 *
double get_total_strain_energy() const
1591 *
return m_material->get_total_strain_energy();
1594 *
double get_crack_energy_dissipation() const
1596 *
return m_material->get_crack_energy_dissipation();
1599 *
double get_phase_field_value() const
1601 *
return m_material->get_phase_field_value();
1606 *
return m_material->get_phase_field_gradient();
1609 *
double get_history_max_positive_strain_energy() const
1611 *
return m_history_max_positive_strain_energy;
1614 *
double get_length_scale() const
1616 *
return m_length_scale;
1619 *
double get_critical_energy_release_rate() const
1624 *
double get_viscosity() const
1626 *
return m_viscosity;
1629 *
std::shared_ptr<LinearIsotropicElasticityAdditiveSplit<dim>> m_material;
1630 *
double m_length_scale;
1632 *
double m_viscosity;
1633 *
double m_history_max_positive_strain_energy;
1636 *
template <
int dim>
1637 *
class PhaseFieldMonolithicSolve
1640 *
PhaseFieldMonolithicSolve(
const std::string &input_file);
1642 *
virtual ~PhaseFieldMonolithicSolve() =
default;
1646 *
struct PerTaskData_ASM;
1647 *
struct ScratchData_ASM;
1649 *
struct PerTaskData_ASM_RHS_BFGS;
1650 *
struct ScratchData_ASM_RHS_BFGS;
1652 *
struct PerTaskData_UQPH;
1653 *
struct ScratchData_UQPH;
1655 *
Parameters::AllParameters m_parameters;
1659 *
PointHistory<dim>>
1660 *
m_quadrature_point_history;
1663 *
std::ofstream m_logfile;
1668 *
const unsigned int m_dofs_per_cell;
1672 *
static const unsigned int m_n_blocks = 2;
1673 *
static const unsigned int m_n_components = dim + 1;
1674 *
static const unsigned int m_first_u_component = 0;
1675 *
static const unsigned int m_d_component = dim;
1683 *
std::vector<types::global_dof_index> m_dofs_per_block;
1686 *
const QGauss<dim - 1> m_qf_face;
1687 *
const unsigned int m_n_q_points;
1689 *
double m_vol_reference;
1699 *
std::map<unsigned int, std::vector<double>> m_material_data;
1701 *
std::vector<std::pair<double, std::vector<double>>> m_history_reaction_force;
1702 *
std::vector<std::pair<double, std::array<double, 3>>> m_history_energy;
1720 *
void normalize(
const Errors &rhs)
1722 *
if (rhs.m_norm != 0.0)
1723 *
m_norm /= rhs.m_norm;
1724 *
if (rhs.m_u != 0.0)
1726 *
if (rhs.m_d != 0.0)
1730 *
double m_norm, m_u, m_d;
1733 *
Errors m_error_residual, m_error_residual_0, m_error_residual_norm, m_error_update,
1734 *
m_error_update_0, m_error_update_norm;
1736 *
void get_error_residual(Errors &error_residual);
1738 *
Errors & error_update);
1741 *
void make_grid_case_1();
1742 *
void make_grid_case_2();
1743 *
void make_grid_case_3();
1744 *
void make_grid_case_4();
1745 *
void make_grid_case_5();
1746 *
void make_grid_case_6();
1747 *
void make_grid_case_7();
1748 *
void make_grid_case_8();
1749 *
void make_grid_case_9();
1750 *
void make_grid_case_11();
1752 *
void setup_system();
1754 *
void determine_component_extractors();
1756 *
void make_constraints(
const unsigned int it_nr);
1762 *
void assemble_system_newton_one_cell(
1764 *
ScratchData_ASM & scratch,
1765 *
PerTaskData_ASM &
data)
const;
1767 *
void assemble_system_B0_one_cell(
1769 *
ScratchData_ASM & scratch,
1770 *
PerTaskData_ASM &
data)
const;
1772 *
void assemble_system_rhs_BFGS_one_cell(
1774 *
ScratchData_ASM_RHS_BFGS & scratch,
1775 *
PerTaskData_ASM_RHS_BFGS &
data)
const;
1790 *
double line_search_stepsize_strong_wolfe(
const double phi_0,
1791 *
const double phi_0_prime,
1798 *
double line_search_zoom_strong_wolfe(
double phi_low,
double phi_low_prime,
double alpha_low,
1799 *
double phi_high,
double phi_high_prime,
double alpha_high,
1801 *
double c1,
double c2,
unsigned int max_iter,
1804 *
double line_search_interpolation_cubic(
const double alpha_0,
const double phi_0,
const double phi_0_prime,
1805 *
const double alpha_1,
const double phi_1,
const double phi_1_prime);
1807 *
std::pair<double, double> calculate_phi_and_phi_prime(
const double alpha,
1816 *
void update_history_field_step();
1818 *
void output_results()
const;
1824 *
const bool is_print);
1826 *
void update_qph_incremental_one_cell(
1828 *
ScratchData_UQPH & scratch,
1829 *
PerTaskData_UQPH &
data);
1831 *
void copy_local_to_global_UQPH(
const PerTaskData_UQPH & )
1839 * Should not make
this function
const
1842 *
void read_material_data(
const std::string &data_file,
1843 *
const unsigned int total_material_regions);
1845 *
void read_time_data(
const std::string &data_file,
1846 *
std::vector<std::array<double, 4>> & time_table);
1848 *
void print_conv_header_newton();
1850 *
void print_conv_header_BFGS();
1852 *
void print_conv_header_LBFGS();
1854 *
void print_parameter_information();
1856 *
void calculate_reaction_force(
unsigned int face_ID);
1858 *
void write_history_data();
1860 *
double calculate_energy_functional()
const;
1862 *
std::pair<double, double> calculate_total_strain_energy_and_crack_energy_dissipation()
const;
1869 *
template <
int dim>
1870 *
void PhaseFieldMonolithicSolve<dim>::get_error_residual(Errors &error_residual)
1874 *
for (
unsigned int i = 0; i < m_dof_handler.n_dofs(); ++i)
1875 *
if (!m_constraints.is_constrained(i))
1876 *
error_res(i) = m_system_rhs(i);
1878 *
error_residual.m_norm = error_res.l2_norm();
1879 *
error_residual.m_u = error_res.block(m_u_dof).l2_norm();
1880 *
error_residual.m_d = error_res.block(m_d_dof).l2_norm();
1883 *
template <
int dim>
1884 *
void PhaseFieldMonolithicSolve<dim>::get_error_update(
const BlockVector<double> &newton_update,
1885 *
Errors & error_update)
1888 *
for (
unsigned int i = 0; i < m_dof_handler.n_dofs(); ++i)
1889 *
if (!m_constraints.is_constrained(i))
1890 *
error_ud(i) = newton_update(i);
1892 *
error_update.m_norm = error_ud.l2_norm();
1893 *
error_update.m_u = error_ud.block(m_u_dof).l2_norm();
1894 *
error_update.m_d = error_ud.block(m_d_dof).l2_norm();
1897 *
template <
int dim>
1898 *
void PhaseFieldMonolithicSolve<dim>::read_material_data(
const std::string &data_file,
1899 *
const unsigned int total_material_regions)
1901 *
std::ifstream myfile (data_file);
1903 *
double lame_lambda, lame_mu, length_scale, gc, viscosity, residual_k;
1904 *
int material_region;
1905 *
double poisson_ratio;
1906 *
if (myfile.is_open())
1908 *
m_logfile <<
"Reading material data file ..." << std::endl;
1910 *
while ( myfile >> material_region
1918 *
m_material_data[material_region] = {lame_lambda,
1924 *
poisson_ratio = lame_lambda / (2*(lame_lambda + lame_mu));
1925 *
Assert( (poisson_ratio <= 0.5)&(poisson_ratio >=-1.0) , ExcInternalError());
1927 *
m_logfile <<
"\tRegion " << material_region <<
" : " << std::endl;
1928 *
m_logfile <<
"\t\tLame lambda = " << lame_lambda << std::endl;
1929 *
m_logfile <<
"\t\tLame mu = " << lame_mu << std::endl;
1930 *
m_logfile <<
"\t\tPoisson ratio = " << poisson_ratio << std::endl;
1931 *
m_logfile <<
"\t\tPhase field length scale (l) = " << length_scale << std::endl;
1932 *
m_logfile <<
"\t\tCritical energy release rate (gc) = " << gc << std::endl;
1933 *
m_logfile <<
"\t\tViscosity for regularization (eta) = " << viscosity << std::endl;
1934 *
m_logfile <<
"\t\tResidual_k (k) = " << residual_k << std::endl;
1937 *
if (m_material_data.size() != total_material_regions)
1939 *
m_logfile <<
"Material data file has " << m_material_data.size() <<
" rows. However, "
1940 *
<<
"the mesh has " << total_material_regions <<
" material regions."
1942 *
Assert(m_material_data.size() == total_material_regions,
1943 *
ExcDimensionMismatch(m_material_data.size(), total_material_regions));
1949 *
m_logfile <<
"Material data file : " << data_file <<
" not exist!" << std::endl;
1950 *
Assert(
false, ExcMessage(
"Failed to read material data file"));
1954 *
template <
int dim>
1955 *
void PhaseFieldMonolithicSolve<dim>::read_time_data(
const std::string &data_file,
1956 *
std::vector<std::array<double, 4>> & time_table)
1958 *
std::ifstream myfile (data_file);
1960 *
double t_0, t_1, delta_t, t_magnitude;
1962 *
if (myfile.is_open())
1964 *
m_logfile <<
"Reading time data file ..." << std::endl;
1966 *
while ( myfile >> t_0
1972 *
ExcMessage(
"For each time pair, "
1973 *
"the start time should be smaller than the end time"));
1974 *
time_table.push_back({{t_0, t_1, delta_t, t_magnitude}});
1977 *
Assert(std::fabs(t_1 - m_parameters.m_end_time) < 1.0e-9,
1978 *
ExcMessage(
"End time in time table is inconsistent with input data in parameters.prm"));
1980 *
Assert(time_table.size() > 0,
1981 *
ExcMessage(
"Time data file is empty."));
1986 *
m_logfile <<
"Time data file : " << data_file <<
" not exist!" << std::endl;
1987 *
Assert(
false, ExcMessage(
"Failed to read time data file"));
1990 *
for (
auto & time_group : time_table)
1992 *
m_logfile <<
"\t\t"
1993 *
<< time_group[0] <<
",\t"
1994 *
<< time_group[1] <<
",\t"
1995 *
<< time_group[2] <<
",\t"
1996 *
<< time_group[3] <<
std::endl;
2000 *
template <
int dim>
2001 *
void PhaseFieldMonolithicSolve<dim>::setup_qph()
2003 *
m_logfile <<
"\t\tSetting up quadrature point data ("
2005 *
<<
" points per cell)" << std::endl;
2007 *
m_quadrature_point_history.clear();
2008 *
for (
auto const & cell : m_triangulation.active_cell_iterators())
2010 *
m_quadrature_point_history.initialize(cell, m_n_q_points);
2014 *
double lame_lambda = 0.0;
2015 *
double lame_mu = 0.0;
2016 *
double length_scale = 0.0;
2018 *
double viscosity = 0.0;
2019 *
double residual_k = 0.0;
2021 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2024 *
if (m_material_data.find(material_id) != m_material_data.end())
2035 *
m_logfile <<
"Could not find material data for material id: " <<
material_id << std::endl;
2036 *
AssertThrow(
false, ExcMessage(
"Could not find material data for material id."));
2039 *
const std::vector<std::shared_ptr<PointHistory<dim>>> lqph =
2040 *
m_quadrature_point_history.get_data(cell);
2041 *
Assert(lqph.size() == m_n_q_points, ExcInternalError());
2043 *
for (
unsigned int q_point = 0; q_point < m_n_q_points; ++q_point)
2044 *
lqph[q_point]->setup_lqp(lame_lambda, lame_mu, length_scale,
2045 *
gc, viscosity, residual_k);
2049 *
template <
int dim>
2054 *
solution_total += solution_delta;
2055 *
return solution_total;
2058 *
template <
int dim>
2060 *
PhaseFieldMonolithicSolve<dim>::update_qph_incremental(
const BlockVector<double> &solution_delta,
2062 *
const bool is_print)
2064 *
m_timer.enter_subsection(
"Update QPH data");
2065 *
if (is_print && m_parameters.m_output_iteration_history)
2066 *
m_logfile <<
" UQPH " << std::flush;
2071 *
PerTaskData_UQPH per_task_data_UQPH;
2072 *
ScratchData_UQPH scratch_data_UQPH(m_fe,
2077 *
m_time.get_delta_t());
2080 *
ScratchData_UQPH & scratch,
2081 *
PerTaskData_UQPH &
data)
2083 *
this->update_qph_incremental_one_cell(cell, scratch,
data);
2086 *
auto copier = [
this](
const PerTaskData_UQPH &
data)
2088 *
this->copy_local_to_global_UQPH(
data);
2092 *
m_dof_handler.begin_active(),
2093 *
m_dof_handler.end(),
2096 *
scratch_data_UQPH,
2097 *
per_task_data_UQPH);
2099 *
m_timer.leave_subsection();
2102 *
template <
int dim>
2103 *
struct PhaseFieldMonolithicSolve<dim>::PerTaskData_UQPH
2109 *
template <
int dim>
2110 *
struct PhaseFieldMonolithicSolve<dim>::ScratchData_UQPH
2114 *
std::vector<SymmetricTensor<2, dim>> m_solution_symm_grads_u_cell;
2115 *
std::vector<double> m_solution_values_phasefield_cell;
2116 *
std::vector<Tensor<1, dim>> m_solution_grad_phasefield_cell;
2121 *
std::vector<double> m_phasefield_previous_step_cell;
2123 *
const double m_delta_time;
2130 *
const double delta_time)
2131 *
: m_solution_UQPH(solution_total)
2132 *
, m_solution_symm_grads_u_cell(qf_cell.size())
2133 *
, m_solution_values_phasefield_cell(qf_cell.size())
2134 *
, m_solution_grad_phasefield_cell(qf_cell.size())
2135 *
, m_fe_values(fe_cell, qf_cell, uf_cell)
2136 *
, m_solution_previous_step(solution_old)
2137 *
, m_phasefield_previous_step_cell(qf_cell.size())
2138 *
, m_delta_time(delta_time)
2141 *
ScratchData_UQPH(
const ScratchData_UQPH &rhs)
2142 *
: m_solution_UQPH(rhs.m_solution_UQPH)
2143 *
, m_solution_symm_grads_u_cell(rhs.m_solution_symm_grads_u_cell)
2144 *
, m_solution_values_phasefield_cell(rhs.m_solution_values_phasefield_cell)
2145 *
, m_solution_grad_phasefield_cell(rhs.m_solution_grad_phasefield_cell)
2146 *
, m_fe_values(rhs.m_fe_values.get_fe(),
2147 *
rhs.m_fe_values.get_quadrature(),
2148 *
rhs.m_fe_values.get_update_flags())
2149 *
, m_solution_previous_step(rhs.m_solution_previous_step)
2150 *
, m_phasefield_previous_step_cell(rhs.m_phasefield_previous_step_cell)
2151 *
, m_delta_time(rhs.m_delta_time)
2156 *
const unsigned int n_q_points = m_solution_symm_grads_u_cell.
size();
2157 *
for (
unsigned int q = 0; q < n_q_points; ++q)
2159 *
m_solution_symm_grads_u_cell[q] = 0.0;
2160 *
m_solution_values_phasefield_cell[q] = 0.0;
2161 *
m_solution_grad_phasefield_cell[q] = 0.0;
2162 *
m_phasefield_previous_step_cell[q] = 0.0;
2167 *
template <
int dim>
2168 *
void PhaseFieldMonolithicSolve<dim>::update_qph_incremental_one_cell(
2170 *
ScratchData_UQPH & scratch,
2171 *
PerTaskData_UQPH & )
2175 *
scratch.m_fe_values.
reinit(cell);
2177 *
const std::vector<std::shared_ptr<PointHistory<dim>>> lqph =
2178 *
m_quadrature_point_history.get_data(cell);
2179 *
Assert(lqph.size() == m_n_q_points, ExcInternalError());
2183 *
scratch.m_fe_values[m_u_fe].get_function_symmetric_gradients(
2184 *
scratch.m_solution_UQPH, scratch.m_solution_symm_grads_u_cell);
2185 *
scratch.m_fe_values[m_d_fe].get_function_values(
2186 *
scratch.m_solution_UQPH, scratch.m_solution_values_phasefield_cell);
2187 *
scratch.m_fe_values[m_d_fe].get_function_gradients(
2188 *
scratch.m_solution_UQPH, scratch.m_solution_grad_phasefield_cell);
2190 *
scratch.m_fe_values[m_d_fe].get_function_values(
2191 *
scratch.m_solution_previous_step, scratch.m_phasefield_previous_step_cell);
2193 *
for (
const unsigned int q_point :
2194 *
scratch.m_fe_values.quadrature_point_indices())
2195 *
lqph[q_point]->update_field_values(scratch.m_solution_symm_grads_u_cell[q_point],
2196 *
scratch.m_solution_values_phasefield_cell[q_point],
2197 *
scratch.m_solution_grad_phasefield_cell[q_point],
2198 *
scratch.m_phasefield_previous_step_cell[q_point],
2199 *
scratch.m_delta_time);
2202 *
template <
int dim>
2203 *
struct PhaseFieldMonolithicSolve<dim>::PerTaskData_ASM
2207 *
std::vector<types::global_dof_index> m_local_dof_indices;
2209 *
PerTaskData_ASM(
const unsigned int dofs_per_cell)
2210 *
: m_cell_matrix(dofs_per_cell, dofs_per_cell)
2211 *
, m_cell_rhs(dofs_per_cell)
2212 *
, m_local_dof_indices(dofs_per_cell)
2217 *
m_cell_matrix = 0.0;
2222 *
template <
int dim>
2223 *
struct PhaseFieldMonolithicSolve<dim>::PerTaskData_ASM_RHS_BFGS
2226 *
std::vector<types::global_dof_index> m_local_dof_indices;
2228 *
PerTaskData_ASM_RHS_BFGS(
const unsigned int dofs_per_cell)
2229 *
: m_cell_rhs(dofs_per_cell)
2230 *
, m_local_dof_indices(dofs_per_cell)
2239 *
template <
int dim>
2240 *
struct PhaseFieldMonolithicSolve<dim>::ScratchData_ASM
2245 *
std::vector<std::vector<double>> m_Nx_phasefield;
2246 *
std::vector<std::vector<Tensor<1, dim>>> m_grad_Nx_phasefield;
2248 *
std::vector<std::vector<Tensor<1, dim>>> m_Nx_disp;
2249 *
std::vector<std::vector<Tensor<2, dim>>> m_grad_Nx_disp;
2250 *
std::vector<std::vector<SymmetricTensor<2, dim>>> m_symm_grad_Nx_disp;
2253 *
std::vector<double> m_phasefield_previous_step_cell;
2261 *
: m_fe_values(fe_cell, qf_cell, uf_cell)
2262 *
, m_fe_face_values(fe_cell, qf_face, uf_face)
2263 *
, m_Nx_phasefield(qf_cell.size(),
2264 *
std::vector<double>(fe_cell.n_dofs_per_cell()))
2265 *
, m_grad_Nx_phasefield(qf_cell.size(),
2267 *
, m_Nx_disp(qf_cell.size(),
2269 *
, m_grad_Nx_disp(qf_cell.size(),
2271 *
, m_symm_grad_Nx_disp(qf_cell.size(),
2273 *
, m_solution_previous_step(solution_old)
2274 *
, m_phasefield_previous_step_cell(qf_cell.size())
2277 *
ScratchData_ASM(
const ScratchData_ASM &rhs)
2278 *
: m_fe_values(rhs.m_fe_values.get_fe(),
2279 *
rhs.m_fe_values.get_quadrature(),
2280 *
rhs.m_fe_values.get_update_flags())
2281 *
, m_fe_face_values(rhs.m_fe_face_values.get_fe(),
2282 *
rhs.m_fe_face_values.get_quadrature(),
2283 *
rhs.m_fe_face_values.get_update_flags())
2284 *
, m_Nx_phasefield(rhs.m_Nx_phasefield)
2285 *
, m_grad_Nx_phasefield(rhs.m_grad_Nx_phasefield)
2286 *
, m_Nx_disp(rhs.m_Nx_disp)
2287 *
, m_grad_Nx_disp(rhs.m_grad_Nx_disp)
2288 *
, m_symm_grad_Nx_disp(rhs.m_symm_grad_Nx_disp)
2289 *
, m_solution_previous_step(rhs.m_solution_previous_step)
2290 *
, m_phasefield_previous_step_cell(rhs.m_phasefield_previous_step_cell)
2295 *
const unsigned int n_q_points = m_Nx_phasefield.
size();
2296 *
const unsigned int n_dofs_per_cell = m_Nx_phasefield[0].size();
2297 *
for (
unsigned int q_point = 0; q_point < n_q_points; ++q_point)
2299 *
Assert(m_Nx_phasefield[q_point].
size() == n_dofs_per_cell,
2300 *
ExcInternalError());
2302 *
Assert(m_grad_Nx_phasefield[q_point].
size() == n_dofs_per_cell,
2303 *
ExcInternalError());
2305 *
Assert(m_Nx_disp[q_point].
size() == n_dofs_per_cell,
2306 *
ExcInternalError());
2308 *
Assert(m_grad_Nx_disp[q_point].
size() == n_dofs_per_cell,
2309 *
ExcInternalError());
2311 *
Assert(m_symm_grad_Nx_disp[q_point].
size() == n_dofs_per_cell,
2312 *
ExcInternalError());
2314 *
m_phasefield_previous_step_cell[q_point] = 0.0;
2315 *
for (
unsigned int k = 0; k < n_dofs_per_cell; ++k)
2317 *
m_Nx_phasefield[q_point][k] = 0.0;
2318 *
m_grad_Nx_phasefield[q_point][k] = 0.0;
2319 *
m_Nx_disp[q_point][k] = 0.0;
2320 *
m_grad_Nx_disp[q_point][k] = 0.0;
2321 *
m_symm_grad_Nx_disp[q_point][k] = 0.0;
2328 *
template <
int dim>
2329 *
struct PhaseFieldMonolithicSolve<dim>::ScratchData_ASM_RHS_BFGS
2334 *
std::vector<std::vector<double>> m_Nx_phasefield;
2335 *
std::vector<std::vector<Tensor<1, dim>>> m_grad_Nx_phasefield;
2337 *
std::vector<std::vector<Tensor<1, dim>>> m_Nx_disp;
2338 *
std::vector<std::vector<Tensor<2, dim>>> m_grad_Nx_disp;
2339 *
std::vector<std::vector<SymmetricTensor<2, dim>>> m_symm_grad_Nx_disp;
2342 *
std::vector<double> m_phasefield_previous_step_cell;
2350 *
: m_fe_values(fe_cell, qf_cell, uf_cell)
2351 *
, m_fe_face_values(fe_cell, qf_face, uf_face)
2352 *
, m_Nx_phasefield(qf_cell.size(),
2353 *
std::vector<double>(fe_cell.n_dofs_per_cell()))
2354 *
, m_grad_Nx_phasefield(qf_cell.size(),
2356 *
, m_Nx_disp(qf_cell.size(),
2358 *
, m_grad_Nx_disp(qf_cell.size(),
2360 *
, m_symm_grad_Nx_disp(qf_cell.size(),
2362 *
, m_solution_previous_step(solution_old)
2363 *
, m_phasefield_previous_step_cell(qf_cell.size())
2366 *
ScratchData_ASM_RHS_BFGS(
const ScratchData_ASM_RHS_BFGS &rhs)
2367 *
: m_fe_values(rhs.m_fe_values.get_fe(),
2368 *
rhs.m_fe_values.get_quadrature(),
2369 *
rhs.m_fe_values.get_update_flags())
2370 *
, m_fe_face_values(rhs.m_fe_face_values.get_fe(),
2371 *
rhs.m_fe_face_values.get_quadrature(),
2372 *
rhs.m_fe_face_values.get_update_flags())
2373 *
, m_Nx_phasefield(rhs.m_Nx_phasefield)
2374 *
, m_grad_Nx_phasefield(rhs.m_grad_Nx_phasefield)
2375 *
, m_Nx_disp(rhs.m_Nx_disp)
2376 *
, m_grad_Nx_disp(rhs.m_grad_Nx_disp)
2377 *
, m_symm_grad_Nx_disp(rhs.m_symm_grad_Nx_disp)
2378 *
, m_solution_previous_step(rhs.m_solution_previous_step)
2379 *
, m_phasefield_previous_step_cell(rhs.m_phasefield_previous_step_cell)
2384 *
const unsigned int n_q_points = m_Nx_phasefield.
size();
2385 *
const unsigned int n_dofs_per_cell = m_Nx_phasefield[0].size();
2386 *
for (
unsigned int q_point = 0; q_point < n_q_points; ++q_point)
2388 *
Assert(m_Nx_phasefield[q_point].
size() == n_dofs_per_cell,
2389 *
ExcInternalError());
2391 *
Assert(m_grad_Nx_phasefield[q_point].
size() == n_dofs_per_cell,
2392 *
ExcInternalError());
2394 *
Assert(m_Nx_disp[q_point].
size() == n_dofs_per_cell,
2395 *
ExcInternalError());
2397 *
Assert(m_grad_Nx_disp[q_point].
size() == n_dofs_per_cell,
2398 *
ExcInternalError());
2400 *
Assert(m_symm_grad_Nx_disp[q_point].
size() == n_dofs_per_cell,
2401 *
ExcInternalError());
2403 *
m_phasefield_previous_step_cell[q_point] = 0.0;
2404 *
for (
unsigned int k = 0; k < n_dofs_per_cell; ++k)
2406 *
m_Nx_phasefield[q_point][k] = 0.0;
2407 *
m_grad_Nx_phasefield[q_point][k] = 0.0;
2408 *
m_Nx_disp[q_point][k] = 0.0;
2409 *
m_grad_Nx_disp[q_point][k] = 0.0;
2410 *
m_symm_grad_Nx_disp[q_point][k] = 0.0;
2418 * constructor has no
return type
2421 *
template <
int dim>
2422 *
PhaseFieldMonolithicSolve<dim>::PhaseFieldMonolithicSolve(
const std::string &input_file)
2423 *
: m_parameters(input_file)
2425 *
, m_time(m_parameters.m_end_time)
2426 *
, m_logfile(m_parameters.m_logfile_name)
2428 *
, m_dof_handler(m_triangulation)
2429 *
, m_fe(
FE_Q<dim>(m_parameters.m_poly_degree),
2431 *
FE_Q<dim>(m_parameters.m_poly_degree),
2433 *
, m_dofs_per_cell(m_fe.n_dofs_per_cell())
2434 *
, m_u_fe(m_first_u_component)
2435 *
, m_d_fe(m_d_component)
2436 *
, m_dofs_per_block(m_n_blocks)
2437 *
, m_qf_cell(m_parameters.m_quad_order)
2438 *
, m_qf_face(m_parameters.m_quad_order)
2439 *
, m_n_q_points(m_qf_cell.size())
2440 *
, m_vol_reference(0.0)
2443 *
template <
int dim>
2444 *
void PhaseFieldMonolithicSolve<dim>::make_grid()
2446 *
if (m_parameters.m_scenario == 1)
2447 *
make_grid_case_1();
2448 *
else if (m_parameters.m_scenario == 2)
2449 *
make_grid_case_2();
2450 *
else if (m_parameters.m_scenario == 3)
2451 *
make_grid_case_3();
2452 *
else if (m_parameters.m_scenario == 4)
2453 *
make_grid_case_4();
2454 *
else if (m_parameters.m_scenario == 5)
2455 *
make_grid_case_5();
2456 *
else if (m_parameters.m_scenario == 6)
2457 *
make_grid_case_6();
2458 *
else if (m_parameters.m_scenario == 7)
2459 *
make_grid_case_7();
2460 *
else if (m_parameters.m_scenario == 8)
2461 *
make_grid_case_8();
2462 *
else if (m_parameters.m_scenario == 9)
2463 *
make_grid_case_9();
2464 *
else if (m_parameters.m_scenario == 11)
2465 *
make_grid_case_11();
2467 *
Assert(
false, ExcMessage(
"The scenario has not been implemented!"));
2469 *
m_logfile <<
"\t\tTriangulation:"
2470 *
<<
"\n\t\t\tNumber of active cells: "
2471 *
<< m_triangulation.n_active_cells()
2472 *
<<
"\n\t\t\tNumber of used vertices: "
2473 *
<< m_triangulation.n_used_vertices()
2476 *
std::ofstream out(
"original_mesh.vtu");
2478 *
grid_out.
write_vtu(m_triangulation, out);
2481 *
m_logfile <<
"\t\tGrid:\n\t\t\tReference volume: " << m_vol_reference << std::endl;
2484 *
template <
int dim>
2485 *
void PhaseFieldMonolithicSolve<dim>::make_grid_case_1()
2487 *
for (
unsigned int i = 0; i < 80; ++i)
2489 *
m_logfile << std::endl;
2490 *
m_logfile <<
"\t\t\tSquare tension (unstructured)" << std::endl;
2491 *
for (
unsigned int i = 0; i < 80; ++i)
2493 *
m_logfile << std::endl;
2495 *
AssertThrow(dim==2, ExcMessage(
"The dimension has to be 2D!"));
2499 *
std::ifstream f(
"square_tension_unstructured.msh");
2500 *
gridin.read_msh(f);
2502 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2503 *
for (
const auto &face : cell->face_iterators())
2505 *
if (face->at_boundary() == true)
2507 *
if (
std::
fabs(face->center()[1] + 0.5 ) < 1.0e-9 )
2508 *
face->set_boundary_id(0);
2509 *
else if (std::fabs(face->center()[1] - 0.5 ) < 1.0e-9)
2510 *
face->set_boundary_id(1);
2512 *
face->set_boundary_id(2);
2516 *
m_triangulation.refine_global(m_parameters.m_global_refine_times);
2518 *
if (m_parameters.m_refinement_strategy ==
"pre-refine")
2521 *
double length_scale;
2522 *
for (
unsigned int i = 0; i < m_parameters.m_local_prerefine_times; i++)
2524 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2526 *
if (
std::
fabs(cell->center()[1]) < 0.01
2527 *
&& cell->center()[0] > 0.495)
2532 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
2533 *
cell->set_refine_flag();
2536 *
m_triangulation.execute_coarsening_and_refinement();
2539 *
else if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
2542 *
double length_scale;
2543 *
bool initiation_point_refine_unfinished =
true;
2544 *
while (initiation_point_refine_unfinished)
2546 *
initiation_point_refine_unfinished =
false;
2547 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2549 *
if (
std::
fabs(cell->center()[1] - 0.0) < 0.05
2550 *
&&
std::
fabs(cell->center()[0] - 0.5) < 0.05)
2555 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
2557 *
cell->set_refine_flag();
2558 *
initiation_point_refine_unfinished =
true;
2562 *
m_triangulation.execute_coarsening_and_refinement();
2568 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
2573 *
template <
int dim>
2574 *
void PhaseFieldMonolithicSolve<dim>::make_grid_case_2()
2576 *
for (
unsigned int i = 0; i < 80; ++i)
2578 *
m_logfile << std::endl;
2579 *
m_logfile <<
"\t\t\t\tSquare shear (unstructured)" << std::endl;
2580 *
for (
unsigned int i = 0; i < 80; ++i)
2582 *
m_logfile << std::endl;
2584 *
AssertThrow(dim==2, ExcMessage(
"The dimension has to be 2D!"));
2588 *
std::ifstream f(
"square_shear_unstructured.msh");
2589 *
gridin.read_msh(f);
2591 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2592 *
for (
const auto &face : cell->face_iterators())
2594 *
if (face->at_boundary() == true)
2596 *
if (
std::
fabs(face->center()[1] + 0.5 ) < 1.0e-9 )
2597 *
face->set_boundary_id(0);
2598 *
else if (std::fabs(face->center()[1] - 0.5 ) < 1.0e-9)
2599 *
face->set_boundary_id(1);
2600 *
else if ( (std::fabs(face->center()[0] - 0.0 ) < 1.0e-9)
2601 *
|| (std::fabs(face->center()[0] - 1.0 ) < 1.0e-9))
2602 *
face->set_boundary_id(2);
2604 *
face->set_boundary_id(3);
2608 *
m_triangulation.refine_global(m_parameters.m_global_refine_times);
2610 *
if (m_parameters.m_refinement_strategy ==
"pre-refine")
2613 *
double length_scale;
2614 *
for (
unsigned int i = 0; i < m_parameters.m_local_prerefine_times; i++)
2616 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2618 *
if ( (cell->center()[0] > 0.45)
2619 *
&& (cell->center()[1] < 0.05) )
2624 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
2625 *
cell->set_refine_flag();
2628 *
m_triangulation.execute_coarsening_and_refinement();
2631 *
else if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
2634 *
double length_scale;
2635 *
bool initiation_point_refine_unfinished =
true;
2636 *
while (initiation_point_refine_unfinished)
2638 *
initiation_point_refine_unfinished =
false;
2639 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2641 *
if (
std::
fabs(cell->center()[0] - 0.5) < 0.025
2642 *
&& cell->center()[1] < 0.0 && cell->center()[1] > -0.025)
2647 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
2649 *
cell->set_refine_flag();
2650 *
initiation_point_refine_unfinished =
true;
2654 *
m_triangulation.execute_coarsening_and_refinement();
2660 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
2664 *
template <
int dim>
2665 *
void PhaseFieldMonolithicSolve<dim>::make_grid_case_3()
2667 *
for (
unsigned int i = 0; i < 80; ++i)
2669 *
m_logfile << std::endl;
2670 *
m_logfile <<
"\t\t\tSquare tension (structured)" << std::endl;
2671 *
for (
unsigned int i = 0; i < 80; ++i)
2673 *
m_logfile << std::endl;
2675 *
AssertThrow(dim==2, ExcMessage(
"The dimension has to be 2D!"));
2679 *
std::ifstream f(
"square_tension_structured.msh");
2680 *
gridin.read_msh(f);
2682 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2683 *
for (
const auto &face : cell->face_iterators())
2685 *
if (face->at_boundary() == true)
2687 *
if (
std::
fabs(face->center()[1] - 0.0 ) < 1.0e-9 )
2688 *
face->set_boundary_id(0);
2689 *
else if (std::fabs(face->center()[1] - 1.0 ) < 1.0e-9)
2690 *
face->set_boundary_id(1);
2692 *
face->set_boundary_id(2);
2696 *
m_triangulation.refine_global(m_parameters.m_global_refine_times);
2698 *
if (m_parameters.m_refinement_strategy ==
"pre-refine")
2701 *
double length_scale;
2702 *
for (
unsigned int i = 0; i < m_parameters.m_local_prerefine_times; i++)
2704 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2706 *
if ( (
std::
fabs(cell->center()[1] - 0.5) < 0.025)
2707 *
&& (cell->center()[0] > 0.475) )
2712 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
2713 *
cell->set_refine_flag();
2716 *
m_triangulation.execute_coarsening_and_refinement();
2719 *
else if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
2722 *
double length_scale;
2723 *
bool initiation_point_refine_unfinished =
true;
2724 *
while (initiation_point_refine_unfinished)
2726 *
initiation_point_refine_unfinished =
false;
2727 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2729 *
if (
std::
fabs(cell->center()[0] - 0.5) < 0.025
2730 *
&&
std::
fabs(cell->center()[1] - 0.5) < 0.025 )
2735 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
2737 *
cell->set_refine_flag();
2738 *
initiation_point_refine_unfinished =
true;
2742 *
m_triangulation.execute_coarsening_and_refinement();
2748 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
2752 *
template <
int dim>
2753 *
void PhaseFieldMonolithicSolve<dim>::make_grid_case_4()
2755 *
for (
unsigned int i = 0; i < 80; ++i)
2757 *
m_logfile << std::endl;
2758 *
m_logfile <<
"\t\t\t\tSquare shear (structured)" << std::endl;
2759 *
for (
unsigned int i = 0; i < 80; ++i)
2761 *
m_logfile << std::endl;
2763 *
AssertThrow(dim==2, ExcMessage(
"The dimension has to be 2D!"));
2767 *
std::ifstream f(
"square_shear_structured.msh");
2768 *
gridin.read_msh(f);
2770 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2771 *
for (
const auto &face : cell->face_iterators())
2773 *
if (face->at_boundary() == true)
2775 *
if (
std::
fabs(face->center()[1] - 0.0 ) < 1.0e-9 )
2776 *
face->set_boundary_id(0);
2777 *
else if (std::fabs(face->center()[1] - 1.0 ) < 1.0e-9)
2778 *
face->set_boundary_id(1);
2779 *
else if ( (std::fabs(face->center()[0] - 0.0 ) < 1.0e-9)
2780 *
|| (std::fabs(face->center()[0] - 1.0 ) < 1.0e-9))
2781 *
face->set_boundary_id(2);
2783 *
face->set_boundary_id(3);
2787 *
m_triangulation.refine_global(m_parameters.m_global_refine_times);
2789 *
if (m_parameters.m_refinement_strategy ==
"pre-refine")
2792 *
double length_scale;
2793 *
for (
unsigned int i = 0; i < m_parameters.m_local_prerefine_times; i++)
2795 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2797 *
if ( (cell->center()[0] > 0.475)
2798 *
&& (cell->center()[1] < 0.525) )
2803 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
2804 *
cell->set_refine_flag();
2807 *
m_triangulation.execute_coarsening_and_refinement();
2810 *
else if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
2813 *
double length_scale;
2814 *
bool initiation_point_refine_unfinished =
true;
2815 *
while (initiation_point_refine_unfinished)
2817 *
initiation_point_refine_unfinished =
false;
2818 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2820 *
if (
std::
fabs(cell->center()[0] - 0.5) < 0.025
2821 *
&& cell->center()[1] < 0.5 && cell->center()[1] > 0.475 )
2826 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
2828 *
cell->set_refine_flag();
2829 *
initiation_point_refine_unfinished =
true;
2833 *
m_triangulation.execute_coarsening_and_refinement();
2839 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
2843 *
template <
int dim>
2844 *
void PhaseFieldMonolithicSolve<dim>::make_grid_case_5()
2846 *
for (
unsigned int i = 0; i < 80; ++i)
2848 *
m_logfile << std::endl;
2849 *
m_logfile <<
"\t\t\t\tThree-point bending (structured)" << std::endl;
2850 *
for (
unsigned int i = 0; i < 80; ++i)
2852 *
m_logfile << std::endl;
2854 *
AssertThrow(dim==2, ExcMessage(
"The dimension has to be 2D!"));
2858 *
std::ifstream f(
"three_point_bending_structured.msh");
2859 *
gridin.read_msh(f);
2861 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2862 *
for (
const auto &face : cell->face_iterators())
2864 *
if (face->at_boundary() == true)
2866 *
if (
std::
fabs(face->center()[1] - 0.0 ) < 1.0e-9 )
2867 *
face->set_boundary_id(0);
2868 *
else if (std::fabs(face->center()[1] - 2.0 ) < 1.0e-9)
2869 *
face->set_boundary_id(1);
2871 *
face->set_boundary_id(2);
2875 *
m_triangulation.refine_global(m_parameters.m_global_refine_times);
2877 *
if (m_parameters.m_refinement_strategy ==
"pre-refine")
2879 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2881 *
if (
std::
fabs(cell->center()[0] - 4.0) < 0.075
2882 *
&& cell->center()[1] < 1.6)
2884 *
cell->set_refine_flag();
2887 *
m_triangulation.execute_coarsening_and_refinement();
2890 *
double length_scale;
2891 *
for (
unsigned int i = 0; i < m_parameters.m_local_prerefine_times; i++)
2893 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2895 *
if (
std::
fabs(cell->center()[0] - 4.0) < 0.05
2896 *
&& cell->center()[1] < 1.6)
2901 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
2902 *
cell->set_refine_flag();
2905 *
m_triangulation.execute_coarsening_and_refinement();
2908 *
else if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
2911 *
double length_scale;
2912 *
bool initiation_point_refine_unfinished =
true;
2913 *
while (initiation_point_refine_unfinished)
2915 *
initiation_point_refine_unfinished =
false;
2916 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
2918 *
if (
std::
fabs(cell->center()[0] - 4.0) < 0.075
2919 *
&&
std::
fabs(cell->center()[1] - 0.4) < 0.075 )
2924 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
2926 *
cell->set_refine_flag();
2927 *
initiation_point_refine_unfinished =
true;
2931 *
m_triangulation.execute_coarsening_and_refinement();
2937 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
2941 *
template <
int dim>
2942 *
void PhaseFieldMonolithicSolve<dim>::make_grid_case_6()
2944 *
AssertThrow(dim==3, ExcMessage(
"The dimension has to be 3D!"));
2946 *
for (
unsigned int i = 0; i < 80; ++i)
2948 *
m_logfile << std::endl;
2949 *
m_logfile <<
"\t\t\t\tSphere inclusion (3D structured)" << std::endl;
2950 *
for (
unsigned int i = 0; i < 80; ++i)
2952 *
m_logfile << std::endl;
2965 *
tmp_triangulation.reset_all_manifolds();
2966 *
tmp_triangulation.set_all_manifold_ids(0);
2968 *
for (
const auto &cell : tmp_triangulation.cell_iterators())
2970 *
for (
const auto &face : cell->face_iterators())
2972 *
bool face_at_sphere_boundary = true;
2975 *
if (
std::
abs(face->vertex(v).norm_square() - 0.25) > 1
e-12)
2976 *
face_at_sphere_boundary = false;
2978 *
if (face_at_sphere_boundary)
2979 *
face->set_all_manifold_ids(1);
2981 *
if (cell->center().norm_square() < 0.25)
2982 *
cell->set_material_id(1);
2984 *
cell->set_material_id(0);
2990 *
transfinite_manifold.
initialize(tmp_triangulation);
2991 *
tmp_triangulation.set_manifold(0, transfinite_manifold);
2993 *
tmp_triangulation.refine_global(m_parameters.m_global_refine_times);
2995 *
std::set<typename Triangulation< dim >::active_cell_iterator >
2998 *
for (
const auto &cell : tmp_triangulation.active_cell_iterators())
3000 *
if ( cell->center()[0] < 0.0
3001 *
|| cell->center()[1] < 0.0
3002 *
|| cell->center()[2] < 0.0)
3004 *
cells_to_remove.
insert(cell);
3012 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3013 *
for (
const auto &face : cell->face_iterators())
3015 *
if (face->at_boundary() == true)
3017 *
if (
std::
fabs(face->center()[0] - 0.0 ) < 1.0e-9 )
3018 *
face->set_boundary_id(0);
3019 *
else if (std::fabs(face->center()[1] - 0.0 ) < 1.0e-9)
3020 *
face->set_boundary_id(1);
3021 *
else if (std::fabs(face->center()[2] - 0.0 ) < 1.0e-9)
3022 *
face->set_boundary_id(2);
3023 *
else if (std::fabs(face->center()[2] - 1.0 ) < 1.0e-9)
3024 *
face->set_boundary_id(3);
3026 *
face->set_boundary_id(4);
3030 *
if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
3033 *
double length_scale;
3034 *
bool initiation_point_refine_unfinished =
true;
3035 *
while (initiation_point_refine_unfinished)
3037 *
initiation_point_refine_unfinished =
false;
3038 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3040 *
if ( cell->center()[2] > 0.525
3041 *
&& cell->center()[2] < 0.575
3042 *
&& cell->center()[0] < 0.05
3043 *
&& cell->center()[1] < 0.05 )
3047 *
if ( std::cbrt(cell->measure())
3048 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
3050 *
cell->set_refine_flag();
3051 *
initiation_point_refine_unfinished =
true;
3055 *
m_triangulation.execute_coarsening_and_refinement();
3061 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
3065 *
template <
int dim>
3066 *
void PhaseFieldMonolithicSolve<dim>::make_grid_case_7()
3068 *
AssertThrow(dim==3, ExcMessage(
"The dimension has to be 3D!"));
3070 *
for (
unsigned int i = 0; i < 80; ++i)
3072 *
m_logfile << std::endl;
3073 *
m_logfile <<
"\t\t\t\tSphere inclusion (3D structured version 2)" << std::endl;
3074 *
for (
unsigned int i = 0; i < 80; ++i)
3076 *
m_logfile << std::endl;
3094 *
&cube1, &cube2, &cube3}, tmp_triangulation);
3097 *
tmp_triangulation.set_all_manifold_ids(0);
3099 *
for (
const auto &cell : tmp_triangulation.cell_iterators())
3101 *
for (
const auto &face : cell->face_iterators())
3103 *
bool face_at_sphere_boundary = true;
3106 *
if (
std::
abs(face->vertex(v).norm_square() - 0.49 * 0.49) > 1
e-12)
3107 *
face_at_sphere_boundary = false;
3109 *
if (face_at_sphere_boundary)
3110 *
face->set_all_manifold_ids(1);
3112 *
if (cell->center().norm_square() < 0.1)
3113 *
cell->set_material_id(1);
3115 *
cell->set_material_id(0);
3121 *
transfinite_manifold.
initialize(tmp_triangulation);
3122 *
tmp_triangulation.set_manifold(0, transfinite_manifold);
3124 *
tmp_triangulation.refine_global(m_parameters.m_global_refine_times);
3126 *
std::set<typename Triangulation< dim >::active_cell_iterator >
3129 *
for (
const auto &cell : tmp_triangulation.active_cell_iterators())
3131 *
if ( cell->center()[0] < 0.0
3132 *
|| cell->center()[1] < 0.0
3133 *
|| cell->center()[2] < 0.0
3134 *
|| cell->center()[0] > 1.0
3135 *
|| cell->center()[1] > 1.0
3136 *
|| cell->center()[2] > 1.0)
3138 *
cells_to_remove.
insert(cell);
3146 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3147 *
for (
const auto &face : cell->face_iterators())
3149 *
if (face->at_boundary() == true)
3151 *
if (
std::
fabs(face->center()[0] - 0.0 ) < 1.0e-9 )
3152 *
face->set_boundary_id(0);
3153 *
else if (std::fabs(face->center()[1] - 0.0 ) < 1.0e-9)
3154 *
face->set_boundary_id(1);
3155 *
else if (std::fabs(face->center()[2] - 0.0 ) < 1.0e-9)
3156 *
face->set_boundary_id(2);
3157 *
else if (std::fabs(face->center()[2] - 1.0 ) < 1.0e-9)
3158 *
face->set_boundary_id(3);
3160 *
face->set_boundary_id(4);
3164 *
if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
3167 *
double length_scale;
3168 *
bool initiation_point_refine_unfinished =
true;
3169 *
while (initiation_point_refine_unfinished)
3171 *
initiation_point_refine_unfinished =
false;
3172 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3174 *
if ( cell->center()[2] > 0.505
3175 *
&& cell->center()[2] < 0.575
3176 *
&& cell->center()[0] < 0.05
3177 *
&& cell->center()[1] < 0.05 )
3181 *
if ( std::cbrt(cell->measure())
3182 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
3184 *
cell->set_refine_flag();
3185 *
initiation_point_refine_unfinished =
true;
3189 *
m_triangulation.execute_coarsening_and_refinement();
3195 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
3200 *
template <
int dim>
3201 *
void PhaseFieldMonolithicSolve<dim>::make_grid_case_8()
3203 *
AssertThrow(dim==3, ExcMessage(
"The dimension has to be 3D!"));
3205 *
for (
unsigned int i = 0; i < 80; ++i)
3207 *
m_logfile << std::endl;
3208 *
m_logfile <<
"\t\t\t\tSphere inclusion (3D structured version 2 with barriers)" << std::endl;
3209 *
for (
unsigned int i = 0; i < 80; ++i)
3211 *
m_logfile << std::endl;
3229 *
&cube1, &cube2, &cube3}, tmp_triangulation);
3232 *
tmp_triangulation.set_all_manifold_ids(0);
3234 *
for (
const auto &cell : tmp_triangulation.cell_iterators())
3236 *
for (
const auto &face : cell->face_iterators())
3238 *
bool face_at_sphere_boundary = true;
3241 *
if (
std::
abs(face->vertex(v).norm_square() - 0.49 * 0.49) > 1
e-12)
3242 *
face_at_sphere_boundary = false;
3244 *
if (face_at_sphere_boundary)
3245 *
face->set_all_manifold_ids(1);
3247 *
if (cell->center().norm_square() < 0.1)
3248 *
cell->set_material_id(1);
3250 *
cell->set_material_id(0);
3256 *
transfinite_manifold.
initialize(tmp_triangulation);
3257 *
tmp_triangulation.set_manifold(0, transfinite_manifold);
3259 *
tmp_triangulation.refine_global(m_parameters.m_global_refine_times);
3263 * some extra barriers
3266 *
for (
const auto &cell : tmp_triangulation.cell_iterators())
3268 *
if (
std::
fabs(cell->center()[1] - 0.75) < 0.05
3269 *
&&
std::
fabs(cell->center()[2] - 0.5625) < 0.05
3270 *
&&
std::
fabs(cell->center()[0] - 0.0) < 0.2)
3271 *
cell->set_material_id(1);
3273 *
if ( std::fabs(cell->center()[1] - 0.0) < 0.2
3274 *
&& std::fabs(cell->center()[2] - 0.5) < 0.1
3275 *
&& std::fabs(cell->center()[0] - 0.75) < 0.05)
3276 *
cell->set_material_id(1);
3279 *
std::set<typename Triangulation< dim >::active_cell_iterator >
3282 *
for (
const auto &cell : tmp_triangulation.active_cell_iterators())
3284 *
if ( cell->center()[0] < 0.0
3285 *
|| cell->center()[1] < 0.0
3286 *
|| cell->center()[2] < 0.0
3287 *
|| cell->center()[0] > 1.0
3288 *
|| cell->center()[1] > 1.0
3289 *
|| cell->center()[2] > 1.0)
3291 *
cells_to_remove.
insert(cell);
3299 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3300 *
for (
const auto &face : cell->face_iterators())
3302 *
if (face->at_boundary() == true)
3304 *
if (
std::
fabs(face->center()[0] - 0.0 ) < 1.0e-9 )
3305 *
face->set_boundary_id(0);
3306 *
else if (std::fabs(face->center()[1] - 0.0 ) < 1.0e-9)
3307 *
face->set_boundary_id(1);
3308 *
else if (std::fabs(face->center()[2] - 0.0 ) < 1.0e-9)
3309 *
face->set_boundary_id(2);
3310 *
else if (std::fabs(face->center()[2] - 1.0 ) < 1.0e-9)
3311 *
face->set_boundary_id(3);
3313 *
face->set_boundary_id(4);
3317 *
if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
3320 *
double length_scale;
3321 *
bool initiation_point_refine_unfinished =
true;
3322 *
while (initiation_point_refine_unfinished)
3324 *
initiation_point_refine_unfinished =
false;
3325 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3327 *
if ( cell->center()[2] > 0.505
3328 *
&& cell->center()[2] < 0.575
3329 *
&& cell->center()[0] < 0.05
3330 *
&& cell->center()[1] < 0.05 )
3334 *
if ( std::cbrt(cell->measure())
3335 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
3337 *
cell->set_refine_flag();
3338 *
initiation_point_refine_unfinished =
true;
3342 *
m_triangulation.execute_coarsening_and_refinement();
3348 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
3353 *
template <
int dim>
3354 *
void PhaseFieldMonolithicSolve<dim>::make_grid_case_9()
3356 *
AssertThrow(dim==2, ExcMessage(
"The dimension has to be 2D!"));
3358 *
for (
unsigned int i = 0; i < 80; ++i)
3360 *
m_logfile << std::endl;
3361 *
m_logfile <<
"\t\t\t\tL-shape bending (2D structured)" << std::endl;
3362 *
for (
unsigned int i = 0; i < 80; ++i)
3364 *
m_logfile << std::endl;
3368 *
std::ifstream f(
"L-Shape.msh");
3369 *
gridin.read_msh(f);
3371 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3372 *
for (
const auto &face : cell->face_iterators())
3374 *
if (face->at_boundary() == true)
3376 *
if (
std::
fabs(face->center()[1] - 0.0 ) < 1.0e-9 )
3377 *
face->set_boundary_id(0);
3379 *
face->set_boundary_id(1);
3383 *
m_triangulation.refine_global(m_parameters.m_global_refine_times);
3385 *
if (m_parameters.m_refinement_strategy ==
"pre-refine")
3388 *
double length_scale;
3389 *
for (
unsigned int i = 0; i < m_parameters.m_local_prerefine_times; i++)
3391 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3393 *
if ( (cell->center()[1] > 242.0)
3394 *
&& (cell->center()[1] < 312.5)
3395 *
&& (cell->center()[0] < 258.0) )
3400 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
3401 *
cell->set_refine_flag();
3404 *
m_triangulation.execute_coarsening_and_refinement();
3407 *
else if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
3410 *
double length_scale;
3411 *
bool initiation_point_refine_unfinished =
true;
3412 *
while (initiation_point_refine_unfinished)
3414 *
initiation_point_refine_unfinished =
false;
3415 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3417 *
if ( (cell->center()[0] - 250) < 0.0
3418 *
&& (cell->center()[0] - 240) > 0.0
3419 *
&&
std::
fabs(cell->center()[1] - 250) < 10.0 )
3424 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
3426 *
cell->set_refine_flag();
3427 *
initiation_point_refine_unfinished =
true;
3431 *
m_triangulation.execute_coarsening_and_refinement();
3437 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
3441 *
template <
int dim>
3442 *
void PhaseFieldMonolithicSolve<dim>::make_grid_case_11()
3444 *
AssertThrow(dim==3, ExcMessage(
"The dimension has to be 3D!"));
3446 *
for (
unsigned int i = 0; i < 80; ++i)
3448 *
m_logfile << std::endl;
3449 *
m_logfile <<
"\t\t\t\tBrokenshire torsion (3D structured)" << std::endl;
3450 *
for (
unsigned int i = 0; i < 80; ++i)
3452 *
m_logfile << std::endl;
3456 *
double const length = 200.0;
3457 *
double const width = 50.0;
3458 *
double const height = 50.0;
3459 *
double const delta_L = 25.0;
3460 *
double const tan_theta = delta_L / (0.5*width);
3462 *
std::vector<unsigned int> repetitions(2, 1);
3463 *
repetitions[0] = 20;
3464 *
repetitions[1] = 5;
3475 *
vertex_ptr = triangulation_2d.begin_active_vertex();
3476 *
while (vertex_ptr != triangulation_2d.end_vertex())
3478 *
Point<2> & vertex_point = vertex_ptr->vertex();
3480 *
const double delta_x = (vertex_point(1) - 0.5*width) * tan_theta;
3482 *
if (std::fabs(vertex_point(0) - 0.5*length) < 1.0e-6)
3484 *
vertex_point(0) += delta_x;
3486 *
else if (std::fabs(vertex_point(0) + length/repetitions[0] - 0.5*length) < 1.0e-6)
3488 *
vertex_point(0) += (delta_x + length/repetitions[0]*0.5);
3490 *
else if (std::fabs(vertex_point(0) - length/repetitions[0] - 0.5*length) < 1.0e-6)
3492 *
vertex_point(0) += (delta_x - length/repetitions[0]*0.5);
3494 *
else if (vertex_point(0) < 0.5*length - length/repetitions[0] - 1.0e-6)
3496 *
vertex_point(0) += (delta_x + length/repetitions[0]*0.5) * vertex_point(0)/(0.5*length - length/repetitions[0]);
3498 *
else if (vertex_point(0) > 0.5*length + length/repetitions[0] + 1.0e-6)
3500 *
vertex_point(0) += (delta_x - length/repetitions[0]*0.5) * (length - vertex_point(0))/(0.5*length - length/repetitions[0]);
3507 *
const unsigned int n_layer = repetitions[1] + 1;
3510 *
tmp_triangulation.refine_global(m_parameters.m_global_refine_times);
3512 *
std::set<typename Triangulation< dim >::active_cell_iterator >
3515 *
for (
const auto &cell : tmp_triangulation.active_cell_iterators())
3517 *
if ( (
std::
fabs(cell->center()[0] - (cell->center()[1] - 0.5*width)*tan_theta - 0.5*length) < 2.5)
3518 *
&& cell->center()[2] > 0.5*
height )
3520 *
cells_to_remove.
insert(cell);
3528 *
if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
3531 *
double length_scale;
3532 *
bool initiation_point_refine_unfinished =
true;
3533 *
while (initiation_point_refine_unfinished)
3535 *
initiation_point_refine_unfinished =
false;
3536 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3538 *
if ( (
std::
fabs(cell->center()[0] - (cell->center()[1] - 0.5*width)*tan_theta - 0.5*length) < 5.0)
3539 *
&& cell->center()[2] <= 0.5*
height
3540 *
&& cell->center()[2] > 0.5*
height - 5.0 )
3544 *
if ( std::cbrt(cell->measure())
3545 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
3547 *
cell->set_refine_flag();
3548 *
initiation_point_refine_unfinished =
true;
3552 *
m_triangulation.execute_coarsening_and_refinement();
3558 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
3562 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
3563 *
for (
const auto &face : cell->face_iterators())
3565 *
if (face->at_boundary() == true)
3567 *
if (
std::
fabs(face->center()[0] - length) < 1.0e-6 )
3568 *
face->set_boundary_id(0);
3569 *
else if (std::fabs(face->center()[0] - 0.0) < 1.0e-6 )
3570 *
face->set_boundary_id(1);
3572 *
face->set_boundary_id(2);
3577 *
template <
int dim>
3578 *
void PhaseFieldMonolithicSolve<dim>::setup_system()
3580 *
m_timer.enter_subsection(
"Setup system");
3582 *
std::vector<unsigned int> block_component(m_n_components,
3584 *
block_component[m_d_component] = m_d_dof;
3586 *
m_dof_handler.distribute_dofs(m_fe);
3590 *
m_constraints.clear();
3592 *
m_constraints.close();
3594 *
m_dofs_per_block =
3597 *
m_logfile <<
"\t\tTriangulation:"
3598 *
<<
"\n\t\t\t Number of active cells: "
3599 *
<< m_triangulation.n_active_cells()
3600 *
<<
"\n\t\t\t Number of used vertices: "
3601 *
<< m_triangulation.n_used_vertices()
3602 *
<<
"\n\t\t\t Number of active edges: "
3603 *
<< m_triangulation.n_active_lines()
3604 *
<<
"\n\t\t\t Number of active faces: "
3605 *
<< m_triangulation.n_active_faces()
3606 *
<<
"\n\t\t\t Number of degrees of freedom (total): "
3607 *
<< m_dof_handler.n_dofs()
3608 *
<<
"\n\t\t\t Number of degrees of freedom (disp): "
3609 *
<< m_dofs_per_block[m_u_dof]
3610 *
<<
"\n\t\t\t Number of degrees of freedom (phasefield): "
3611 *
<< m_dofs_per_block[m_d_dof]
3614 *
m_tangent_matrix.clear();
3619 *
for (
unsigned int ii = 0; ii < m_n_components; ++ii)
3620 *
for (
unsigned int jj = 0; jj < m_n_components; ++jj)
3624 *
m_dof_handler, coupling, dsp, m_constraints,
false);
3625 *
m_sparsity_pattern.copy_from(dsp);
3628 *
m_tangent_matrix.reinit(m_sparsity_pattern);
3630 *
m_system_rhs.reinit(m_dofs_per_block);
3631 *
m_solution.reinit(m_dofs_per_block);
3635 *
m_timer.leave_subsection();
3638 *
template <
int dim>
3639 *
void PhaseFieldMonolithicSolve<dim>::make_constraints(
const unsigned int it_nr)
3641 *
const bool apply_dirichlet_bc = (it_nr == 0);
3645 *
if (m_parameters.m_output_iteration_history)
3646 *
m_logfile <<
" --- " << std::flush;
3650 *
if (m_parameters.m_output_iteration_history)
3651 *
m_logfile <<
" CST " << std::flush;
3653 *
if (apply_dirichlet_bc)
3655 *
m_constraints.clear();
3665 *
if ( m_parameters.m_scenario == 1
3666 *
|| m_parameters.m_scenario == 3)
3670 * Dirichlet B,
C. bottom surface
3673 *
const int boundary_id_bottom_surface = 0;
3675 *
boundary_id_bottom_surface,
3678 *
m_fe.component_mask(y_displacement));
3681 *
vertex_itr = m_triangulation.begin_active_vertex();
3682 *
std::vector<types::global_dof_index> node_xy(m_fe.dofs_per_vertex);
3684 *
for (; vertex_itr != m_triangulation.end_vertex(); ++vertex_itr)
3686 *
if ( (std::fabs(vertex_itr->vertex()[0] - 0.0) < 1.0e-9)
3687 *
&& (std::fabs(vertex_itr->vertex()[1] - 0.0) < 1.0e-9) )
3689 *
node_xy = usr_utilities::get_vertex_dofs(vertex_itr, m_dof_handler);
3692 *
m_constraints.add_line(node_xy[0]);
3693 *
m_constraints.set_inhomogeneity(node_xy[0], 0.0);
3695 *
m_constraints.add_line(node_xy[1]);
3696 *
m_constraints.set_inhomogeneity(node_xy[1], 0.0);
3698 *
const int boundary_id_top_surface = 1;
3706 *
const double time_inc = m_time.get_delta_t();
3707 *
double disp_magnitude = m_time.get_magnitude();
3709 *
boundary_id_top_surface,
3711 *
disp_magnitude*time_inc, m_n_components),
3713 *
m_fe.component_mask(y_displacement));
3715 *
else if ( m_parameters.m_scenario == 2
3716 *
|| m_parameters.m_scenario == 4)
3720 * Dirichlet B,
C. bottom surface
3723 *
const int boundary_id_bottom_surface = 0;
3725 *
boundary_id_bottom_surface,
3728 *
m_fe.component_mask(displacements));
3730 *
const int boundary_id_top_surface = 1;
3732 *
boundary_id_top_surface,
3735 *
m_fe.component_mask(y_displacement));
3737 *
const double time_inc = m_time.get_delta_t();
3738 *
double disp_magnitude = m_time.get_magnitude();
3740 *
boundary_id_top_surface,
3742 *
disp_magnitude*time_inc, m_n_components),
3744 *
m_fe.component_mask(x_displacement));
3746 *
const int boundary_id_side_surfaces = 2;
3748 *
boundary_id_side_surfaces,
3751 *
m_fe.component_mask(y_displacement));
3753 *
else if (m_parameters.m_scenario == 5)
3756 *
vertex_itr = m_triangulation.begin_active_vertex();
3757 *
std::vector<types::global_dof_index> node_bottomleft(m_fe.dofs_per_vertex);
3758 *
std::vector<types::global_dof_index> node_bottomright(m_fe.dofs_per_vertex);
3759 *
std::vector<types::global_dof_index> node_topcenter(m_fe.dofs_per_vertex);
3761 *
for (; vertex_itr != m_triangulation.end_vertex(); ++vertex_itr)
3763 *
if ( (std::fabs(vertex_itr->vertex()[0] - 0.0) < 1.0e-9)
3764 *
&& (std::fabs(vertex_itr->vertex()[1] - 0.0) < 1.0e-9) )
3766 *
node_bottomleft = usr_utilities::get_vertex_dofs(vertex_itr, m_dof_handler);
3768 *
if ( (std::fabs(vertex_itr->vertex()[0] - 8.0) < 1.0e-9)
3769 *
&& (std::fabs(vertex_itr->vertex()[1] - 0.0) < 1.0e-9) )
3771 *
node_bottomright = usr_utilities::get_vertex_dofs(vertex_itr, m_dof_handler);
3773 *
if ( (std::fabs(vertex_itr->vertex()[0] - 4.0) < 1.0e-9)
3774 *
&& (std::fabs(vertex_itr->vertex()[1] - 2.0) < 1.0e-9) )
3776 *
node_topcenter = usr_utilities::get_vertex_dofs(vertex_itr, m_dof_handler);
3781 * bottom-left node fixed in both x- and y-directions
3784 *
m_constraints.add_line(node_bottomleft[0]);
3785 *
m_constraints.set_inhomogeneity(node_bottomleft[0], 0.0);
3787 *
m_constraints.add_line(node_bottomleft[1]);
3788 *
m_constraints.set_inhomogeneity(node_bottomleft[1], 0.0);
3792 * bottom-right node only fixed in y-direction
3795 *
m_constraints.add_line(node_bottomright[1]);
3796 *
m_constraints.set_inhomogeneity(node_bottomright[1], 0.0);
3800 * top-center node applied with y-displacement
3803 *
const double time_inc = m_time.get_delta_t();
3804 *
double disp_magnitude = m_time.get_magnitude();
3806 *
m_constraints.add_line(node_topcenter[1]);
3807 *
m_constraints.set_inhomogeneity(node_topcenter[1], disp_magnitude*time_inc);
3809 *
else if ( m_parameters.m_scenario == 6
3810 *
|| m_parameters.m_scenario == 7
3811 *
|| m_parameters.m_scenario == 8)
3813 *
const int x0_surface = 0;
3818 *
m_fe.component_mask(x_displacement));
3819 *
const int y0_surface = 1;
3824 *
m_fe.component_mask(y_displacement));
3825 *
const int z0_surface = 2;
3830 *
m_fe.component_mask(z_displacement));
3832 *
const int z1_surface = 3;
3833 *
const double time_inc = m_time.get_delta_t();
3834 *
double disp_magnitude = m_time.get_magnitude();
3838 *
disp_magnitude*time_inc, m_n_components),
3840 *
m_fe.component_mask(z_displacement));
3842 *
else if (m_parameters.m_scenario == 9)
3846 * Dirichlet B,
C. bottom surface
3849 *
const int boundary_id_bottom_surface = 0;
3851 *
boundary_id_bottom_surface,
3854 *
m_fe.component_mask(displacements));
3857 *
vertex_itr = m_triangulation.begin_active_vertex();
3858 *
std::vector<types::global_dof_index> node_disp_control(m_fe.dofs_per_vertex);
3860 *
for (; vertex_itr != m_triangulation.end_vertex(); ++vertex_itr)
3862 *
if ( (std::fabs(vertex_itr->vertex()[0] - 470.0) < 1.0e-9)
3863 *
&& (std::fabs(vertex_itr->vertex()[1] - 250.0) < 1.0e-9) )
3865 *
node_disp_control = usr_utilities::get_vertex_dofs(vertex_itr, m_dof_handler);
3868 * node applied with y-displacement
3871 *
const double time_inc = m_time.get_delta_t();
3872 *
double disp_magnitude = m_time.get_magnitude();
3874 *
m_constraints.add_line(node_disp_control[1]);
3875 *
m_constraints.set_inhomogeneity(node_disp_control[1], disp_magnitude*time_inc);
3879 *
else if (m_parameters.m_scenario == 11)
3883 * Dirichlet B,
C. right surface
3886 *
const int boundary_id_right_surface = 0;
3888 *
boundary_id_right_surface,
3891 *
m_fe.component_mask(displacements));
3895 * Dirichlet B,
C. left surface
3898 *
const int boundary_id_left_surface = 1;
3900 *
boundary_id_left_surface,
3903 *
m_fe.component_mask(x_displacement));
3906 *
vertex_itr = m_triangulation.begin_active_vertex();
3907 *
std::vector<types::global_dof_index> node_rotate(m_fe.dofs_per_vertex);
3908 *
double node_dist = 0.0;
3909 *
double disp_mag = 0.0;
3910 *
double angle_theta = 0.0;
3911 *
double disp_y = 0;
3912 *
double disp_z = 0;
3914 *
for (; vertex_itr != m_triangulation.end_vertex(); ++vertex_itr)
3916 *
if (std::fabs(vertex_itr->vertex()[0] - 0.0) < 1.0e-9)
3918 *
node_rotate = usr_utilities::get_vertex_dofs(vertex_itr, m_dof_handler);
3919 *
node_dist =
std::sqrt( vertex_itr->vertex()[1] * vertex_itr->vertex()[1]
3920 *
+ vertex_itr->vertex()[2] * vertex_itr->vertex()[2]);
3922 *
angle_theta = m_time.get_delta_t() * m_time.get_magnitude();
3923 *
disp_mag = node_dist *
std::tan(angle_theta);
3925 *
if (node_dist > 0)
3927 *
disp_y = vertex_itr->vertex()[2]/node_dist * disp_mag;
3928 *
disp_z = -vertex_itr->vertex()[1]/node_dist * disp_mag;
3936 *
m_constraints.add_line(node_rotate[1]);
3937 *
m_constraints.set_inhomogeneity(node_rotate[1], disp_y);
3939 *
m_constraints.add_line(node_rotate[2]);
3940 *
m_constraints.set_inhomogeneity(node_rotate[2], disp_z);
3945 *
Assert(
false, ExcMessage(
"The scenario has not been implemented!"));
3949 *
if (m_constraints.has_inhomogeneities())
3952 *
for (
unsigned int dof = 0; dof != m_dof_handler.n_dofs(); ++dof)
3953 *
if (homogeneous_constraints.is_inhomogeneously_constrained(dof))
3954 *
homogeneous_constraints.set_inhomogeneity(dof, 0.0);
3955 *
m_constraints.clear();
3956 *
m_constraints.copy_from(homogeneous_constraints);
3959 *
m_constraints.close();
3962 *
template <
int dim>
3963 *
void PhaseFieldMonolithicSolve<dim>::assemble_system_newton(
const BlockVector<double> & solution_old)
3965 *
m_timer.enter_subsection(
"Assemble system");
3967 *
if (m_parameters.m_output_iteration_history)
3968 *
m_logfile <<
" ASM_SYS " << std::flush;
3970 *
m_tangent_matrix = 0.0;
3971 *
m_system_rhs = 0.0;
3978 *
PerTaskData_ASM per_task_data(m_fe.n_dofs_per_cell());
3979 *
ScratchData_ASM scratch_data(m_fe, m_qf_cell, uf_cell, m_qf_face, uf_face, solution_old);
3983 *
ScratchData_ASM & scratch,
3984 *
PerTaskData_ASM &
data)
3986 *
this->assemble_system_newton_one_cell(cell, scratch,
data);
3989 *
auto copier = [
this](
const PerTaskData_ASM &
data)
3991 *
this->m_constraints.distribute_local_to_global(
data.m_cell_matrix,
3993 *
data.m_local_dof_indices,
3999 *
m_dof_handler.active_cell_iterators(),
4005 *
m_timer.leave_subsection();
4009 *
template <
int dim>
4010 *
void PhaseFieldMonolithicSolve<dim>::assemble_system_B0(
const BlockVector<double> & solution_old)
4012 *
m_timer.enter_subsection(
"Assemble B0");
4014 *
m_tangent_matrix = 0.0;
4021 *
PerTaskData_ASM per_task_data(m_fe.n_dofs_per_cell());
4022 *
ScratchData_ASM scratch_data(m_fe, m_qf_cell, uf_cell, m_qf_face, uf_face, solution_old);
4026 *
ScratchData_ASM & scratch,
4027 *
PerTaskData_ASM &
data)
4029 *
this->assemble_system_B0_one_cell(cell, scratch,
data);
4032 *
auto copier = [
this](
const PerTaskData_ASM &
data)
4034 *
this->m_constraints.distribute_local_to_global(
data.m_cell_matrix,
4035 *
data.m_local_dof_indices,
4036 *
m_tangent_matrix);
4040 *
m_dof_handler.active_cell_iterators(),
4046 *
m_timer.leave_subsection();
4049 *
template <
int dim>
4050 *
void PhaseFieldMonolithicSolve<dim>::assemble_system_rhs_BFGS_parallel(
const BlockVector<double> & solution_old,
4053 *
m_timer.enter_subsection(
"Assemble RHS");
4057 * m_logfile <<
" A_RHS " << std::flush;
4070 *
PerTaskData_ASM_RHS_BFGS per_task_data(m_fe.n_dofs_per_cell());
4071 *
ScratchData_ASM_RHS_BFGS scratch_data(m_fe, m_qf_cell, uf_cell, m_qf_face, uf_face, solution_old);
4075 *
ScratchData_ASM_RHS_BFGS & scratch,
4076 *
PerTaskData_ASM_RHS_BFGS &
data)
4078 *
this->assemble_system_rhs_BFGS_one_cell(cell, scratch,
data);
4081 *
auto copier = [
this, &system_rhs](
const PerTaskData_ASM_RHS_BFGS &
data)
4083 *
this->m_constraints.distribute_local_to_global(
data.m_cell_rhs,
4084 *
data.m_local_dof_indices,
4089 *
m_dof_handler.active_cell_iterators(),
4095 *
m_timer.leave_subsection();
4098 *
template <
int dim>
4099 *
void PhaseFieldMonolithicSolve<dim>::assemble_system_rhs_BFGS_one_cell(
4101 *
ScratchData_ASM_RHS_BFGS & scratch,
4102 *
PerTaskData_ASM_RHS_BFGS &
data)
const
4106 *
scratch.m_fe_values.reinit(cell);
4107 *
cell->get_dof_indices(
data.m_local_dof_indices);
4109 *
scratch.m_fe_values[m_d_fe].get_function_values(
4110 *
scratch.m_solution_previous_step, scratch.m_phasefield_previous_step_cell);
4112 *
const std::vector<std::shared_ptr<const PointHistory<dim>>> lqph =
4113 *
m_quadrature_point_history.get_data(cell);
4114 *
Assert(lqph.size() == m_n_q_points, ExcInternalError());
4116 *
const double time_ramp = (m_time.current() / m_time.end());
4117 *
std::vector<Tensor<1, dim>> rhs_values(m_n_q_points);
4119 *
right_hand_side(scratch.m_fe_values.get_quadrature_points(),
4121 *
m_parameters.m_x_component*1.0,
4122 *
m_parameters.m_y_component*1.0,
4123 *
m_parameters.m_z_component*1.0);
4125 *
const double delta_time = m_time.get_delta_t();
4127 *
for (
const unsigned int q_point : scratch.m_fe_values.quadrature_point_indices())
4129 *
for (
const unsigned
int k : scratch.m_fe_values.dof_indices())
4133 *
if (k_group == m_u_dof)
4135 *
scratch.m_Nx_disp[q_point][k] =
4136 *
scratch.m_fe_values[m_u_fe].value(k, q_point);
4137 *
scratch.m_grad_Nx_disp[q_point][k] =
4138 *
scratch.m_fe_values[m_u_fe].gradient(k, q_point);
4139 *
scratch.m_symm_grad_Nx_disp[q_point][k] =
4140 *
symmetrize(scratch.m_grad_Nx_disp[q_point][k]);
4142 *
else if (k_group == m_d_dof)
4144 *
scratch.m_Nx_phasefield[q_point][k] =
4145 *
scratch.m_fe_values[m_d_fe].value(k, q_point);
4146 *
scratch.m_grad_Nx_phasefield[q_point][k] =
4147 *
scratch.m_fe_values[m_d_fe].gradient(k, q_point);
4150 *
Assert(k_group <= m_d_dof, ExcInternalError());
4154 *
for (
const unsigned int q_point : scratch.m_fe_values.quadrature_point_indices())
4156 *
const double length_scale = lqph[q_point]->get_length_scale();
4157 *
const double gc = lqph[q_point]->get_critical_energy_release_rate();
4158 *
const double eta = lqph[q_point]->get_viscosity();
4159 *
const double history_strain_energy = lqph[q_point]->get_history_max_positive_strain_energy();
4160 *
const double current_positive_strain_energy = lqph[q_point]->get_current_positive_strain_energy();
4162 *
double history_value = history_strain_energy;
4163 *
if (current_positive_strain_energy > history_strain_energy)
4164 *
history_value = current_positive_strain_energy;
4166 *
const double phasefield_value = lqph[q_point]->get_phase_field_value();
4167 *
const Tensor<1, dim> phasefield_grad = lqph[q_point]->get_phase_field_gradient();
4169 *
const std::vector<double> & N_phasefield = scratch.m_Nx_phasefield[q_point];
4170 *
const std::vector<Tensor<1, dim>> & grad_N_phasefield = scratch.m_grad_Nx_phasefield[q_point];
4171 *
const double old_phasefield = scratch.m_phasefield_previous_step_cell[q_point];
4175 *
const std::vector<Tensor<1,dim>> & N_disp = scratch.m_Nx_disp[q_point];
4176 *
const std::vector<SymmetricTensor<2, dim>> & symm_grad_N_disp =
4177 *
scratch.m_symm_grad_Nx_disp[q_point];
4178 *
const double JxW = scratch.m_fe_values.JxW(q_point);
4182 *
for (
const unsigned int i : scratch.m_fe_values.dof_indices())
4186 *
if (i_group == m_u_dof)
4188 *
data.m_cell_rhs(i) += (symm_grad_N_disp[i] * cauchy_stress) * JxW;
4192 * contributions from the body force to right-hand side
4195 *
data.m_cell_rhs(i) -= N_disp[i] * rhs_values[q_point] * JxW;
4197 *
else if (i_group == m_d_dof)
4199 *
data.m_cell_rhs(i) += ( gc * length_scale * grad_N_phasefield[i] * phasefield_grad
4200 *
+ ( gc / length_scale * phasefield_value
4201 *
+ eta / delta_time * (phasefield_value - old_phasefield)
4202 *
+ degradation_function_derivative(phasefield_value) * history_value )
4207 *
Assert(i_group <= m_d_dof, ExcInternalError());
4213 *
if there is surface pressure,
this surface pressure
always applied to the
4217 *
const unsigned int face_pressure_id = 100;
4218 *
const double p0 = 0.0;
4220 *
for (
const auto &face : cell->face_iterators())
4221 *
if (face->at_boundary() && face->
boundary_id() == face_pressure_id)
4223 *
scratch.m_fe_face_values.
reinit(cell, face);
4225 *
for (
const unsigned int f_q_point : scratch.m_fe_face_values.quadrature_point_indices())
4227 *
const Tensor<1, dim> &
N = scratch.m_fe_face_values.normal_vector(f_q_point);
4229 *
const double pressure = p0 * time_ramp;
4232 *
for (
const unsigned int i : scratch.m_fe_values.dof_indices())
4236 *
if (i_group == m_u_dof)
4238 *
const unsigned int component_i = m_fe.system_to_component_index(i).first;
4239 *
const double Ni = scratch.m_fe_face_values.shape_value(i, f_q_point);
4240 *
const double JxW = scratch.m_fe_face_values.JxW(f_q_point);
4241 *
data.m_cell_rhs(i) -= (Ni * traction[component_i]) * JxW;
4248 *
template <
int dim>
4249 *
void PhaseFieldMonolithicSolve<dim>::assemble_system_newton_one_cell(
4251 *
ScratchData_ASM & scratch,
4252 *
PerTaskData_ASM &
data)
const
4256 *
scratch.m_fe_values.reinit(cell);
4257 *
cell->get_dof_indices(
data.m_local_dof_indices);
4259 *
scratch.m_fe_values[m_d_fe].get_function_values(
4260 *
scratch.m_solution_previous_step, scratch.m_phasefield_previous_step_cell);
4262 *
const std::vector<std::shared_ptr<const PointHistory<dim>>> lqph =
4263 *
m_quadrature_point_history.get_data(cell);
4264 *
Assert(lqph.size() == m_n_q_points, ExcInternalError());
4266 *
const double time_ramp = (m_time.current() / m_time.end());
4267 *
std::vector<Tensor<1, dim>> rhs_values(m_n_q_points);
4269 *
right_hand_side(scratch.m_fe_values.get_quadrature_points(),
4271 *
m_parameters.m_x_component*1.0,
4272 *
m_parameters.m_y_component*1.0,
4273 *
m_parameters.m_z_component*1.0);
4275 *
const double delta_time = m_time.get_delta_t();
4277 *
for (
const unsigned int q_point : scratch.m_fe_values.quadrature_point_indices())
4279 *
for (
const unsigned
int k : scratch.m_fe_values.dof_indices())
4283 *
if (k_group == m_u_dof)
4285 *
scratch.m_Nx_disp[q_point][k] =
4286 *
scratch.m_fe_values[m_u_fe].value(k, q_point);
4287 *
scratch.m_grad_Nx_disp[q_point][k] =
4288 *
scratch.m_fe_values[m_u_fe].gradient(k, q_point);
4289 *
scratch.m_symm_grad_Nx_disp[q_point][k] =
4290 *
symmetrize(scratch.m_grad_Nx_disp[q_point][k]);
4292 *
else if (k_group == m_d_dof)
4294 *
scratch.m_Nx_phasefield[q_point][k] =
4295 *
scratch.m_fe_values[m_d_fe].value(k, q_point);
4296 *
scratch.m_grad_Nx_phasefield[q_point][k] =
4297 *
scratch.m_fe_values[m_d_fe].gradient(k, q_point);
4300 *
Assert(k_group <= m_d_dof, ExcInternalError());
4304 *
for (
const unsigned int q_point : scratch.m_fe_values.quadrature_point_indices())
4306 *
const double length_scale = lqph[q_point]->get_length_scale();
4307 *
const double gc = lqph[q_point]->get_critical_energy_release_rate();
4308 *
const double eta = lqph[q_point]->get_viscosity();
4309 *
const double history_strain_energy = lqph[q_point]->get_history_max_positive_strain_energy();
4310 *
const double current_positive_strain_energy = lqph[q_point]->get_current_positive_strain_energy();
4312 *
double history_value = history_strain_energy;
4313 *
if (current_positive_strain_energy > history_strain_energy)
4314 *
history_value = current_positive_strain_energy;
4316 *
const double phasefield_value = lqph[q_point]->get_phase_field_value();
4317 *
const Tensor<1, dim> phasefield_grad = lqph[q_point]->get_phase_field_gradient();
4319 *
const std::vector<double> & N_phasefield = scratch.m_Nx_phasefield[q_point];
4320 *
const std::vector<Tensor<1, dim>> & grad_N_phasefield = scratch.m_grad_Nx_phasefield[q_point];
4321 *
const double old_phasefield = scratch.m_phasefield_previous_step_cell[q_point];
4327 *
const std::vector<Tensor<1,dim>> & N_disp = scratch.m_Nx_disp[q_point];
4328 *
const std::vector<SymmetricTensor<2, dim>> & symm_grad_N_disp =
4329 *
scratch.m_symm_grad_Nx_disp[q_point];
4330 *
const double JxW = scratch.m_fe_values.JxW(q_point);
4334 *
for (
const unsigned int i : scratch.m_fe_values.dof_indices())
4338 *
if (i_group == m_u_dof)
4340 *
data.m_cell_rhs(i) -= (symm_grad_N_disp[i] * cauchy_stress) * JxW;
4344 * contributions from the body force to right-hand side
4347 *
data.m_cell_rhs(i) += N_disp[i] * rhs_values[q_point] * JxW;
4349 *
else if (i_group == m_d_dof)
4351 *
data.m_cell_rhs(i) -= ( gc * length_scale * grad_N_phasefield[i] * phasefield_grad
4352 *
+ ( gc / length_scale * phasefield_value
4353 *
+ eta / delta_time * (phasefield_value - old_phasefield)
4354 *
+ degradation_function_derivative(phasefield_value) * history_value )
4359 *
Assert(i_group <= m_d_dof, ExcInternalError());
4361 *
if (i_group == m_u_dof)
4363 *
symm_grad_Nx_i_x_C = symm_grad_N_disp[i] * mechanical_C;
4366 *
for (
const unsigned int j : scratch.m_fe_values.dof_indices())
4370 *
if ((i_group == j_group) && (i_group == m_u_dof))
4372 *
data.m_cell_matrix(i, j) += symm_grad_Nx_i_x_C * symm_grad_N_disp[j] * JxW;
4374 *
else if ((i_group == j_group) && (i_group == m_d_dof))
4376 *
data.m_cell_matrix(i, j) += ( ( gc/length_scale + eta/delta_time +
4377 *
degradation_function_2nd_order_derivative(phasefield_value)
4379 *
* N_phasefield[i] * N_phasefield[j]
4380 *
+ gc * length_scale * grad_N_phasefield[i] * grad_N_phasefield[j]
4383 *
else if ((i_group == m_u_dof) && (j_group == m_d_dof))
4385 *
data.m_cell_matrix(i, j) += symm_grad_N_disp[i] * cauchy_stress_positive
4386 *
* degradation_function_derivative(phasefield_value)
4387 *
* N_phasefield[j] * JxW;
4389 *
else if ((i_group == m_d_dof) && (j_group == m_u_dof))
4391 *
if (current_positive_strain_energy > history_strain_energy)
4392 *
data.m_cell_matrix(i, j) += N_phasefield[i]
4393 *
* degradation_function_derivative(phasefield_value)
4394 *
* cauchy_stress_positive
4395 *
* symm_grad_N_disp[j]
4398 *
data.m_cell_matrix(i, j) += 0.0;
4401 *
Assert((i_group <= m_d_dof) && (j_group <= m_d_dof),
4402 *
ExcInternalError());
4409 *
if there is surface pressure,
this surface pressure
always applied to the
4413 *
const unsigned int face_pressure_id = 100;
4414 *
const double p0 = 0.0;
4416 *
for (
const auto &face : cell->face_iterators())
4417 *
if (face->at_boundary() && face->
boundary_id() == face_pressure_id)
4419 *
scratch.m_fe_face_values.
reinit(cell, face);
4421 *
for (
const unsigned int f_q_point : scratch.m_fe_face_values.quadrature_point_indices())
4423 *
const Tensor<1, dim> &
N = scratch.m_fe_face_values.normal_vector(f_q_point);
4425 *
const double pressure = p0 * time_ramp;
4428 *
for (
const unsigned int i : scratch.m_fe_values.dof_indices())
4432 *
if (i_group == m_u_dof)
4434 *
const unsigned int component_i = m_fe.system_to_component_index(i).first;
4435 *
const double Ni = scratch.m_fe_face_values.shape_value(i, f_q_point);
4436 *
const double JxW = scratch.m_fe_face_values.JxW(f_q_point);
4437 *
data.m_cell_rhs(i) += (Ni * traction[component_i]) * JxW;
4444 *
template <
int dim>
4445 *
void PhaseFieldMonolithicSolve<dim>::assemble_system_B0_one_cell(
4447 *
ScratchData_ASM & scratch,
4448 *
PerTaskData_ASM &
data)
const
4452 *
scratch.m_fe_values.reinit(cell);
4453 *
cell->get_dof_indices(
data.m_local_dof_indices);
4455 *
scratch.m_fe_values[m_d_fe].get_function_values(
4456 *
scratch.m_solution_previous_step, scratch.m_phasefield_previous_step_cell);
4458 *
const std::vector<std::shared_ptr<const PointHistory<dim>>> lqph =
4459 *
m_quadrature_point_history.get_data(cell);
4460 *
Assert(lqph.size() == m_n_q_points, ExcInternalError());
4462 *
const double delta_time = m_time.get_delta_t();
4464 *
for (
const unsigned int q_point : scratch.m_fe_values.quadrature_point_indices())
4466 *
for (
const unsigned
int k : scratch.m_fe_values.dof_indices())
4470 *
if (k_group == m_u_dof)
4472 *
scratch.m_Nx_disp[q_point][k] =
4473 *
scratch.m_fe_values[m_u_fe].value(k, q_point);
4474 *
scratch.m_grad_Nx_disp[q_point][k] =
4475 *
scratch.m_fe_values[m_u_fe].gradient(k, q_point);
4476 *
scratch.m_symm_grad_Nx_disp[q_point][k] =
4477 *
symmetrize(scratch.m_grad_Nx_disp[q_point][k]);
4479 *
else if (k_group == m_d_dof)
4481 *
scratch.m_Nx_phasefield[q_point][k] =
4482 *
scratch.m_fe_values[m_d_fe].value(k, q_point);
4483 *
scratch.m_grad_Nx_phasefield[q_point][k] =
4484 *
scratch.m_fe_values[m_d_fe].gradient(k, q_point);
4487 *
Assert(k_group <= m_d_dof, ExcInternalError());
4491 *
for (
const unsigned int q_point : scratch.m_fe_values.quadrature_point_indices())
4493 *
const double length_scale = lqph[q_point]->get_length_scale();
4494 *
const double gc = lqph[q_point]->get_critical_energy_release_rate();
4495 *
const double eta = lqph[q_point]->get_viscosity();
4496 *
const double history_strain_energy = lqph[q_point]->get_history_max_positive_strain_energy();
4497 *
const double current_positive_strain_energy = lqph[q_point]->get_current_positive_strain_energy();
4499 *
double history_value = history_strain_energy;
4500 *
if (current_positive_strain_energy > history_strain_energy)
4501 *
history_value = current_positive_strain_energy;
4503 *
const double phasefield_value = lqph[q_point]->get_phase_field_value();
4505 *
const std::vector<double> & N_phasefield = scratch.m_Nx_phasefield[q_point];
4506 *
const std::vector<Tensor<1, dim>> & grad_N_phasefield = scratch.m_grad_Nx_phasefield[q_point];
4515 *
const std::vector<SymmetricTensor<2, dim>> & symm_grad_N_disp =
4516 *
scratch.m_symm_grad_Nx_disp[q_point];
4517 *
const double JxW = scratch.m_fe_values.JxW(q_point);
4521 *
for (
const unsigned int i : scratch.m_fe_values.dof_indices())
4525 *
if (i_group == m_u_dof)
4527 *
symm_grad_Nx_i_x_C = symm_grad_N_disp[i] * mechanical_C;
4530 *
for (
const unsigned int j : scratch.m_fe_values.dof_indices())
4534 *
if ((i_group == j_group) && (i_group == m_u_dof))
4536 *
data.m_cell_matrix(i, j) += symm_grad_Nx_i_x_C * symm_grad_N_disp[j] * JxW;
4538 *
else if ((i_group == j_group) && (i_group == m_d_dof))
4540 *
data.m_cell_matrix(i, j) += ( ( gc/length_scale + eta/delta_time
4541 *
+ degradation_function_2nd_order_derivative(phasefield_value)
4543 *
* N_phasefield[i] * N_phasefield[j]
4544 *
+ gc * length_scale * grad_N_phasefield[i] * grad_N_phasefield[j]
4548 *
Assert((i_group <= m_d_dof) && (j_group <= m_d_dof),
4549 *
ExcInternalError());
4555 *
template <
int dim>
4556 *
void PhaseFieldMonolithicSolve<dim>::assemble_system_rhs_BFGS(
const BlockVector<double> & solution_old,
4559 *
m_timer.enter_subsection(
"Assemble RHS");
4563 * m_logfile <<
" A_RHS " << std::flush;
4572 *
std::vector<types::global_dof_index> local_dof_indices(m_dofs_per_cell);
4574 *
const double time_ramp = (m_time.current() / m_time.end());
4575 *
const double delta_time = m_time.get_delta_t();
4577 *
std::vector<Tensor<1, dim>> rhs_values(m_n_q_points);
4588 * shape function
values for displacement field
4591 *
std::vector<std::vector<Tensor<1, dim>>>
4592 *
Nx_disp(m_qf_cell.size(), std::vector<
Tensor<1, dim>>(m_dofs_per_cell));
4593 *
std::vector<std::vector<Tensor<2, dim>>>
4594 *
grad_Nx_disp(m_qf_cell.size(), std::vector<
Tensor<2, dim>>(m_dofs_per_cell));
4595 *
std::vector<std::vector<SymmetricTensor<2, dim>>>
4600 * shape function
values for phase field
4603 *
std::vector<std::vector<double>>
4604 *
Nx_phasefield(m_qf_cell.size(), std::vector<double>(m_dofs_per_cell));
4605 *
std::vector<std::vector<Tensor<1, dim>>>
4606 *
grad_Nx_phasefield(m_qf_cell.size(), std::vector<
Tensor<1, dim>>(m_dofs_per_cell));
4608 *
std::vector<double> phasefield_previous_step_cell(m_qf_cell.size());
4610 *
for (
const auto &cell : m_dof_handler.active_cell_iterators())
4612 *
const std::vector<
std::shared_ptr< PointHistory<dim>>> lqph =
4613 *
m_quadrature_point_history.get_data(cell);
4614 *
Assert(lqph.size() == m_n_q_points, ExcInternalError());
4617 *
fe_values.reinit(cell);
4618 *
right_hand_side(fe_values.get_quadrature_points(),
4620 *
m_parameters.m_x_component*time_ramp,
4621 *
m_parameters.m_y_component*time_ramp,
4622 *
m_parameters.m_z_component*time_ramp);
4624 *
fe_values[m_d_fe].get_function_values(
4625 *
solution_old, phasefield_previous_step_cell);
4627 *
for (
const unsigned int q_point : fe_values.quadrature_point_indices())
4629 *
for (
const unsigned
int k : fe_values.dof_indices())
4633 *
if (k_group == m_u_dof)
4635 *
Nx_disp[q_point][k] = fe_values[m_u_fe].value(k, q_point);
4636 *
grad_Nx_disp[q_point][k] = fe_values[m_u_fe].gradient(k, q_point);
4637 *
symm_grad_Nx_disp[q_point][k] =
symmetrize(grad_Nx_disp[q_point][k]);
4639 *
else if (k_group == m_d_dof)
4641 *
Nx_phasefield[q_point][k] = fe_values[m_d_fe].value(k, q_point);
4642 *
grad_Nx_phasefield[q_point][k] = fe_values[m_d_fe].gradient(k, q_point);
4645 *
Assert(k_group <= m_d_dof, ExcInternalError());
4649 *
for (
const unsigned int q_point : fe_values.quadrature_point_indices())
4651 *
const double length_scale = lqph[q_point]->get_length_scale();
4652 *
const double gc = lqph[q_point]->get_critical_energy_release_rate();
4653 *
const double eta = lqph[q_point]->get_viscosity();
4654 *
const double history_strain_energy = lqph[q_point]->get_history_max_positive_strain_energy();
4655 *
const double current_positive_strain_energy = lqph[q_point]->get_current_positive_strain_energy();
4657 *
double history_value = history_strain_energy;
4658 *
if (current_positive_strain_energy > history_strain_energy)
4659 *
history_value = current_positive_strain_energy;
4661 *
const double phasefield_value = lqph[q_point]->get_phase_field_value();
4662 *
const Tensor<1, dim> phasefield_grad = lqph[q_point]->get_phase_field_gradient();
4664 *
const std::vector<double> & N_phasefield = Nx_phasefield[q_point];
4665 *
const std::vector<Tensor<1, dim>> & grad_N_phasefield = grad_Nx_phasefield[q_point];
4666 *
const double old_phasefield = phasefield_previous_step_cell[q_point];
4670 *
const std::vector<Tensor<1,dim>> &
N = Nx_disp[q_point];
4671 *
const std::vector<SymmetricTensor<2, dim>> & symm_grad_N = symm_grad_Nx_disp[q_point];
4672 *
const double JxW = fe_values.JxW(q_point);
4674 *
for (
const unsigned int i : fe_values.dof_indices())
4678 *
if (i_group == m_u_dof)
4680 *
cell_rhs(i) += (symm_grad_N[i] * cauchy_stress) * JxW;
4683 * contributions from the body force to right-hand side
4686 *
cell_rhs(i) -=
N[i] * rhs_values[q_point] * JxW;
4688 *
else if (i_group == m_d_dof)
4690 *
cell_rhs(i) += ( gc * length_scale * grad_N_phasefield[i] * phasefield_grad
4691 *
+ ( gc / length_scale * phasefield_value
4692 *
+ eta / delta_time * (phasefield_value - old_phasefield)
4693 *
+ degradation_function_derivative(phasefield_value) * history_value )
4698 *
Assert(i_group <= m_d_dof, ExcInternalError());
4704 *
if there is surface pressure,
this surface pressure
always applied to the
4708 *
const unsigned int face_pressure_id = 100;
4709 *
const double p0 = 0.0;
4711 *
for (
const auto &face : cell->face_iterators())
4713 *
if (face->at_boundary() && face->
boundary_id() == face_pressure_id)
4715 *
fe_face_values.
reinit(cell, face);
4717 *
for (
const unsigned int f_q_point : fe_face_values.quadrature_point_indices())
4719 *
const Tensor<1, dim> &
N = fe_face_values.normal_vector(f_q_point);
4721 *
const double pressure = p0 * time_ramp;
4724 *
for (
const unsigned int i : fe_values.dof_indices())
4728 *
if (i_group == m_u_dof)
4730 *
const unsigned int component_i = m_fe.system_to_component_index(i).first;
4731 *
const double Ni = fe_face_values.shape_value(i, f_q_point);
4732 *
const double JxW = fe_face_values.JxW(f_q_point);
4733 *
cell_rhs(i) -= (Ni * traction[component_i]) * JxW;
4740 *
cell->get_dof_indices(local_dof_indices);
4741 *
for (
const unsigned int i : fe_values.dof_indices())
4742 *
system_rhs(local_dof_indices[i]) += cell_rhs(i);
4745 *
m_timer.leave_subsection();
4748 *
template <
int dim>
4749 *
void PhaseFieldMonolithicSolve<dim>::update_history_field_step()
4751 *
m_logfile <<
"\t\tUpdate history variable" << std::endl;
4753 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
4755 *
std::vector<
std::shared_ptr< PointHistory<dim>>> lqph =
4756 *
m_quadrature_point_history.get_data(cell);
4757 *
Assert(lqph.size() == m_n_q_points, ExcInternalError());
4759 *
for (
unsigned int q_point = 0; q_point < m_n_q_points; ++q_point)
4761 *
lqph[q_point]->update_history_variable();
4766 *
template <
int dim>
4767 *
double PhaseFieldMonolithicSolve<dim>::line_search_stepsize_gradient_based(
const BlockVector<double> & BFGS_p_vector,
4774 * BFGS_p_vector is the search direction
4780 * take a full step
size 1.0
4783 *
solution_delta_trial.add(1.0, BFGS_p_vector);
4785 *
update_qph_incremental(solution_delta_trial, m_solution,
false);
4788 *
assemble_system_rhs_BFGS_parallel(m_solution, g_new);
4792 *
y_old = g_new - g_old;
4794 *
double alpha = 1.0;
4796 *
double alpha_old = 0.0;
4798 *
double delta_alpha_old = alpha - alpha_old;
4800 *
double delta_alpha_new;
4802 *
unsigned int ls_max = 10;
4804 *
for (
unsigned int i = 1; i <= ls_max; ++i)
4806 *
delta_alpha_new = -delta_alpha_old
4807 *
* (g_new * BFGS_p_vector)/(y_old * BFGS_p_vector);
4808 *
alpha += delta_alpha_new;
4810 *
if (std::fabs(delta_alpha_new) < 1.0e-5)
4823 * BFGS_p_vector is the search direction
4826 *
solution_delta_trial = solution_delta;
4827 *
solution_delta_trial.add(alpha, BFGS_p_vector);
4828 *
update_qph_incremental(solution_delta_trial, m_solution,
false);
4829 *
assemble_system_rhs_BFGS_parallel(m_solution, g_new);
4831 *
y_old = g_new - g_old;
4833 *
delta_alpha_old = delta_alpha_new;
4836 *
if (alpha < 1.0e-3)
4842 *
template <
int dim>
4843 *
double PhaseFieldMonolithicSolve<dim>::line_search_stepsize_strong_wolfe(
const double phi_0,
4844 *
const double phi_0_prime,
4851 * ExcMessage(
"The derivative of phi at alpha = 0 should be negative!"));
4855 * Some line search parameters
4858 *
const double c1 = 0.0001;
4859 *
const double c2 = 0.9;
4860 *
const double alpha_max = 100.0;
4861 *
const unsigned int max_iter = 20;
4862 *
double alpha = 1.0;
4864 *
double phi_old = phi_0;
4865 *
double phi_prime_old = phi_0_prime;
4866 *
double alpha_old = 0.0;
4868 *
double phi, phi_prime;
4870 *
std::pair<double, double> current_phi_phi_prime;
4872 *
unsigned int i = 0;
4873 *
for (; i < max_iter; ++i)
4875 *
current_phi_phi_prime = calculate_phi_and_phi_prime(alpha, BFGS_p_vector, solution_delta);
4876 *
phi = current_phi_phi_prime.first;
4877 *
phi_prime = current_phi_phi_prime.second;
4879 *
if ( ( phi > (phi_0 + c1 * alpha * phi_0_prime) )
4880 *
|| ( i > 0 && phi > phi_old ) )
4882 *
return line_search_zoom_strong_wolfe(phi_old, phi_prime_old, alpha_old,
4883 *
phi, phi_prime, alpha,
4884 *
phi_0, phi_0_prime, BFGS_p_vector,
4885 *
c1, c2, max_iter, solution_delta);
4888 *
if (std::fabs(phi_prime) <= c2 * std::fabs(phi_0_prime))
4893 *
if (phi_prime >= 0)
4895 *
return line_search_zoom_strong_wolfe(phi, phi_prime, alpha,
4896 *
phi_old, phi_prime_old, alpha_old,
4897 *
phi_0, phi_0_prime, BFGS_p_vector,
4898 *
c1, c2, max_iter, solution_delta);
4902 *
phi_prime_old = phi_prime;
4903 *
alpha_old = alpha;
4905 *
alpha =
std::min(2.0*alpha, alpha_max);
4910 * ExcMessage(
"alpha is bigger than alpha_max, line search failed!"));
4918 * ExcMessage(
"max number attempts arrived, line search failed!"));
4919 * Instead of terminating the program, we can just take a full step.
4922 *
if (i == max_iter)
4928 *
template <
int dim>
4929 *
double PhaseFieldMonolithicSolve<dim>::
4930 *
line_search_zoom_strong_wolfe(
double phi_low,
double phi_low_prime,
double alpha_low,
4931 *
double phi_high,
double phi_high_prime,
double alpha_high,
4933 *
double c1,
double c2,
unsigned int max_iter,
const BlockVector<double> & solution_delta)
4936 *
std::pair<double, double> current_phi_phi_prime;
4937 *
double phi, phi_prime;
4939 *
unsigned int i = 0;
4940 *
for (; i < max_iter; ++i)
4944 * a simple bisection is faster than cubic interpolation
4947 *
alpha = 0.5 * (alpha_low + alpha_high);
4950 * alpha = line_search_interpolation_cubic(alpha_low, phi_low, phi_low_prime,
4951 * alpha_high, phi_high, phi_high_prime);
4954 *
current_phi_phi_prime = calculate_phi_and_phi_prime(alpha, BFGS_p_vector, solution_delta);
4955 *
phi = current_phi_phi_prime.first;
4956 *
phi_prime = current_phi_phi_prime.second;
4958 *
if ( (phi > phi_0 + c1 * alpha * phi_0_prime)
4959 *
|| (phi > phi_low) )
4961 *
alpha_high = alpha;
4963 *
phi_high_prime = phi_prime;
4967 *
if (std::fabs(phi_prime) <= c2 * std::fabs(phi_0_prime))
4971 *
if (alpha < 1.0e-3)
4978 *
if (phi_prime * (alpha_high - alpha_low) >= 0.0)
4980 *
alpha_high = alpha_low;
4981 *
phi_high_prime = phi_low_prime;
4982 *
phi_high = phi_low;
4985 *
alpha_low = alpha;
4986 *
phi_low_prime = phi_prime;
4991 *
if (alpha < 1.0e-3)
4996 * avoid unused variable warnings from compiler
5000 *
(
void)phi_high_prime;
5004 *
template <
int dim>
5005 *
double PhaseFieldMonolithicSolve<dim>::
5006 *
line_search_interpolation_cubic(
const double alpha_0,
const double phi_0,
const double phi_0_prime,
5007 *
const double alpha_1,
const double phi_1,
const double phi_1_prime)
5009 *
const double d1 = phi_0_prime + phi_1_prime - 3.0 * (phi_0 - phi_1) / (alpha_0 - alpha_1);
5011 *
const double temp = d1 * d1 - phi_0_prime * phi_1_prime;
5014 *
return 0.5 * (alpha_0 + alpha_1);
5017 *
if (alpha_1 > alpha_0)
5024 *
const double alpha = alpha_1 - (alpha_1 - alpha_0)
5025 *
* (phi_1_prime + d2 - d1) / (phi_1_prime - phi_0_prime + 2*d2);
5027 *
if ( (alpha_1 > alpha_0)
5028 *
&& (alpha > alpha_1 || alpha < alpha_0))
5029 *
return 0.5 * (alpha_0 + alpha_1);
5031 *
if ( (alpha_0 > alpha_1)
5032 *
&& (alpha > alpha_0 || alpha < alpha_1))
5033 *
return 0.5 * (alpha_0 + alpha_1);
5038 *
template <
int dim>
5039 *
std::pair<double, double> PhaseFieldMonolithicSolve<dim>::
5040 *
calculate_phi_and_phi_prime(
const double alpha,
5049 *
std::pair<double, double> phi_values;
5052 *
solution_delta_trial.add(alpha, BFGS_p_vector);
5054 *
update_qph_incremental(solution_delta_trial, m_solution,
false);
5057 *
assemble_system_rhs_BFGS_parallel(m_solution, system_rhs);
5060 * m_constraints.condense(system_rhs);
5066 *
phi_values.first = calculate_energy_functional();
5067 *
phi_values.second = system_rhs * BFGS_p_vector;
5068 *
return phi_values;
5071 *
template <
int dim>
5075 *
m_timer.enter_subsection(
"Solve B0");
5077 *
assemble_system_B0(m_solution);
5079 *
if (m_parameters.m_type_linear_solver ==
"Direct")
5083 *
A_direct.vmult(LBFGS_r_vector,
5086 *
else if (m_parameters.m_type_linear_solver ==
"CG")
5104 *
preconditioner_uu.
initialize(m_tangent_matrix.block(m_u_dof, m_u_dof), 1.0);
5105 *
cg_uu.solve(m_tangent_matrix.block(m_u_dof, m_u_dof),
5106 *
LBFGS_r_vector.block(m_u_dof),
5107 *
LBFGS_q_vector.block(m_u_dof),
5108 *
preconditioner_uu);
5114 *
preconditioner_dd.
initialize(m_tangent_matrix.block(m_d_dof, m_d_dof), 1.0);
5115 *
cg_dd.solve(m_tangent_matrix.block(m_d_dof, m_d_dof),
5116 *
LBFGS_r_vector.block(m_d_dof),
5117 *
LBFGS_q_vector.block(m_d_dof),
5118 *
preconditioner_dd);
5123 *
ExcMessage(
"Selected linear solver not implemented!"));
5126 *
m_timer.leave_subsection();
5129 *
template <
int dim>
5130 *
std::vector<double>
5131 *
PhaseFieldMonolithicSolve<dim>::solve_linear_system(
BlockVector<double> & newton_update)
5133 *
m_timer.enter_subsection(
"Solve coupled linear system");
5135 *
if (m_parameters.m_output_iteration_history)
5136 *
m_logfile <<
" SLV " << std::flush;
5138 *
std::vector<double> linear_solver_parameters(3);
5175 *
A_direct.vmult(newton_update,
5178 *
m_constraints.distribute(newton_update);
5180 *
m_timer.leave_subsection();
5181 *
return linear_solver_parameters;
5184 *
template <
int dim>
5185 *
void PhaseFieldMonolithicSolve<dim>::print_conv_header_newton()
5187 *
static const unsigned int l_width = 135;
5188 *
m_logfile <<
'\t' <<
'\t';
5189 *
for (
unsigned int i = 0; i < l_width; ++i)
5191 *
m_logfile << std::endl;
5193 *
m_logfile <<
" SOLVER STEP (Newton) "
5194 *
<<
" | Cond No. Lin_Iter Lin_Res Res_Norm "
5195 *
<<
" Res_u Res_d Inc_Norm "
5196 *
<<
" Inc_u Inc_d" << std::endl;
5198 *
m_logfile <<
'\t' <<
'\t';
5199 *
for (
unsigned int i = 0; i < l_width; ++i)
5201 *
m_logfile << std::endl;
5204 *
template <
int dim>
5205 *
void PhaseFieldMonolithicSolve<dim>::print_conv_header_BFGS()
5207 *
static const unsigned int l_width = 125;
5208 *
m_logfile <<
'\t' <<
'\t';
5209 *
for (
unsigned int i = 0; i < l_width; ++i)
5211 *
m_logfile << std::endl;
5213 *
m_logfile <<
" SOLVER STEP (BFGS) "
5214 *
<<
" | Line Search alpha Energy Res_Norm "
5215 *
<<
" Res_u Res_d Inc_Norm "
5216 *
<<
" Inc_u Inc_d" << std::endl;
5218 *
m_logfile <<
'\t' <<
'\t';
5219 *
for (
unsigned int i = 0; i < l_width; ++i)
5221 *
m_logfile << std::endl;
5224 *
template <
int dim>
5225 *
void PhaseFieldMonolithicSolve<dim>::print_conv_header_LBFGS()
5227 *
static const unsigned int l_width = 120;
5228 *
m_logfile <<
'\t' <<
'\t';
5229 *
for (
unsigned int i = 0; i < l_width; ++i)
5231 *
m_logfile << std::endl;
5233 *
m_logfile <<
" SOLVER STEP (LBFGS) "
5234 *
<<
" | LS-alpha Energy Res_Norm "
5235 *
<<
" Res_u Res_d Inc_Norm "
5236 *
<<
" Inc_u Inc_d" << std::endl;
5238 *
m_logfile <<
'\t' <<
'\t';
5239 *
for (
unsigned int i = 0; i < l_width; ++i)
5241 *
m_logfile << std::endl;
5244 *
template <
int dim>
5245 *
bool PhaseFieldMonolithicSolve<dim>::
5250 *
m_error_residual.reset();
5251 *
m_error_residual_0.reset();
5252 *
m_error_residual_norm.reset();
5253 *
m_error_update.reset();
5254 *
m_error_update_0.reset();
5255 *
m_error_update_norm.reset();
5257 *
if (m_parameters.m_output_iteration_history)
5258 *
print_conv_header_newton();
5260 *
unsigned int newton_iteration = 0;
5261 *
for (; newton_iteration < m_parameters.m_max_iterations_NR; ++newton_iteration)
5263 *
if (m_parameters.m_output_iteration_history)
5264 *
m_logfile <<
'\t' <<
'\t' << std::setw(2) << newton_iteration <<
' '
5267 *
make_constraints(newton_iteration);
5268 *
assemble_system_newton(m_solution);
5270 *
get_error_residual(m_error_residual);
5271 *
if (newton_iteration == 0)
5272 *
m_error_residual_0 = m_error_residual;
5274 *
m_error_residual_norm = m_error_residual;
5275 *
m_error_residual_norm.normalize(m_error_residual_0);
5277 *
if (newton_iteration > 0 && m_error_update_norm.m_u <= m_parameters.m_tol_u_incr
5278 *
&& m_error_residual_norm.m_u <= m_parameters.m_tol_u_residual
5279 *
&& m_error_update_norm.m_d <= m_parameters.m_tol_d_incr
5280 *
&& m_error_residual_norm.m_d <= m_parameters.m_tol_d_residual)
5282 *
if (m_parameters.m_output_iteration_history)
5284 *
m_logfile <<
" CONVERGED!";
5285 *
m_logfile <<
" | " << std::fixed << std::setprecision(3) << std::setw(7)
5286 *
<< std::scientific
5287 *
<<
" " <<
" ---- "
5288 *
<<
" " <<
" ---- "
5289 *
<<
" " <<
" ---- "
5290 *
<<
" " << m_error_residual_norm.m_norm
5291 *
<<
" " << m_error_residual_norm.m_u
5292 *
<<
" " << m_error_residual_norm.m_d
5293 *
<<
" " << m_error_update_norm.m_norm
5294 *
<<
" " << m_error_update_norm.m_u
5295 *
<<
" " << m_error_update_norm.m_d
5296 *
<<
" " << std::endl;
5298 *
m_logfile <<
'\t' <<
'\t';
5299 *
for (
unsigned int i = 0; i < 135; ++i)
5301 *
m_logfile << std::endl;
5304 *
m_logfile <<
"\t\tConvergence is reached after "
5305 *
<< newton_iteration <<
" Newton iterations."<< std::endl;
5307 *
m_logfile <<
"\t\tResidual information of convergence:" << std::endl;
5309 *
m_logfile <<
"\t\t\tRelative residual of disp. equation: "
5310 *
<< m_error_residual_norm.m_u << std::endl;
5312 *
m_logfile <<
"\t\t\tAbsolute residual of disp. equation: "
5313 *
<< m_error_residual_norm.m_u * m_error_residual_0.m_u << std::endl;
5315 *
m_logfile <<
"\t\t\tRelative residual of phasefield equation: "
5316 *
<< m_error_residual_norm.m_d << std::endl;
5318 *
m_logfile <<
"\t\t\tAbsolute residual of phasefield equation: "
5319 *
<< m_error_residual_norm.m_d * m_error_residual_0.m_d << std::endl;
5321 *
m_logfile <<
"\t\t\tRelative increment of disp.: "
5322 *
<< m_error_update_norm.m_u << std::endl;
5324 *
m_logfile <<
"\t\t\tAbsolute increment of disp.: "
5325 *
<< m_error_update_norm.m_u * m_error_update_0.m_u << std::endl;
5327 *
m_logfile <<
"\t\t\tRelative increment of phasefield: "
5328 *
<< m_error_update_norm.m_d << std::endl;
5330 *
m_logfile <<
"\t\t\tAbsolute increment of phasefield: "
5331 *
<< m_error_update_norm.m_d * m_error_update_0.m_d << std::endl;
5341 *
std::vector<double> linear_solver_parameters(3);
5343 *
linear_solver_parameters = solve_linear_system(newton_update);
5345 *
get_error_update(newton_update, m_error_update);
5346 *
if (newton_iteration == 0)
5347 *
m_error_update_0 = m_error_update;
5349 *
m_error_update_norm = m_error_update;
5350 *
m_error_update_norm.normalize(m_error_update_0);
5352 *
solution_delta += newton_update;
5353 *
update_qph_incremental(solution_delta, m_solution,
true);
5355 *
if (m_parameters.m_output_iteration_history)
5357 *
m_logfile <<
" | " << std::fixed << std::setprecision(3) << std::setw(7)
5358 *
<< std::scientific
5359 *
<<
" " << linear_solver_parameters[0]
5360 *
<<
" " << linear_solver_parameters[1]
5361 *
<<
" " << linear_solver_parameters[2]
5362 *
<<
" " << m_error_residual_norm.m_norm
5363 *
<<
" " << m_error_residual_norm.m_u
5364 *
<<
" " << m_error_residual_norm.m_d
5365 *
<<
" " << m_error_update_norm.m_norm
5366 *
<<
" " << m_error_update_norm.m_u
5367 *
<<
" " << m_error_update_norm.m_d
5368 *
<<
" " << std::endl;
5374 *
AssertThrow(newton_iteration < m_parameters.m_max_iterations_NR,
5375 * ExcMessage(
"No convergence in Newton-Raphson nonlinear solver!"));
5381 *
template <
int dim>
5382 *
void PhaseFieldMonolithicSolve<dim>::
5386 *
ExcMessage(
"BFGS requires too much memory. Please use L-BFGS!"));
5390 *
m_error_residual.reset();
5391 *
m_error_residual_0.reset();
5392 *
m_error_residual_norm.reset();
5393 *
m_error_update.reset();
5394 *
m_error_update_0.reset();
5395 *
m_error_update_norm.reset();
5397 *
print_conv_header_BFGS();
5399 *
unsigned int BFGS_iteration = 0;
5403 * Initial guess B_0, which is a full
matrix and takes a lot of memory
5412 *
double line_search_parameter, rho;
5416 * Most likely, we will not be able to create a
second full
matrix since
5417 * we will
run out of memory on a laptop workstation
5423 *
for (; BFGS_iteration < m_parameters.m_max_iterations_BFGS; ++BFGS_iteration)
5425 *
m_logfile <<
'\t' <<
'\t' << std::setw(2) << BFGS_iteration <<
' '
5428 *
make_constraints(BFGS_iteration);
5432 * At the
first step, we simply distribute the inhomogeneous part of
5436 *
if (BFGS_iteration == 0)
5438 *
m_constraints.distribute(BFGS_update);
5439 *
solution_delta += BFGS_update;
5440 *
m_logfile <<
" --- " << std::flush;
5441 *
m_logfile <<
" --- " << std::flush;
5442 *
update_qph_incremental(solution_delta, m_solution,
false);
5443 *
m_logfile <<
" --- |" << std::flush;
5444 *
m_logfile << std::endl;
5447 *
else if (BFGS_iteration == 1)
5451 * Calculate the residual vector r. NOTICE that in the context of
5452 * BFGS,
this r is the
gradient of the energy functional (objective function),
5456 *
assemble_system_rhs_BFGS(m_solution, m_system_rhs);
5460 * We cannot simply
zero out the dofs that are constrained, since we might
5461 * have hanging node constraints. In
this case, we need to modify the RHS
5462 * as
C^
T *
b, which
C contains entries of 0.5 (x_3 = 0.5*x_1 + 0.5*x_2)
5463 *
for (
unsigned int i = 0; i < m_dof_handler.n_dofs(); ++i)
5464 *
if (m_constraints.is_constrained(i))
5465 * m_system_rhs(i) = 0.0;
5469 *
if m_constraints has inhomogeneity, we cannot call m_constraints.condense(m_system_rhs),
5470 * since the m_system_matrix needs to be provided to modify the RHS properly. However,
this
5471 * error will not be detected in the
release mode and only will be detected on the
debug mode
5474 *
m_constraints.condense(m_system_rhs);
5477 *
m_logfile <<
" --- " << std::flush;
5478 *
m_logfile <<
" --- " << std::flush;
5479 *
m_logfile <<
" --- " << std::flush;
5481 *
get_error_residual(m_error_residual);
5482 *
if (BFGS_iteration == 1)
5483 *
m_error_residual_0 = m_error_residual;
5485 *
m_error_residual_norm = m_error_residual;
5486 *
m_error_residual_norm.normalize(m_error_residual_0);
5488 *
if (BFGS_iteration > 1 && m_error_update_norm.m_u <= m_parameters.m_tol_u_incr
5489 *
&& m_error_residual_norm.m_u <= m_parameters.m_tol_u_residual
5490 *
&& m_error_update_norm.m_d <= m_parameters.m_tol_d_incr
5491 *
&& m_error_residual_norm.m_d <= m_parameters.m_tol_d_residual)
5493 *
m_logfile <<
" CONVERGED!";
5494 *
m_logfile <<
"| " << std::fixed << std::setprecision(3) << std::setw(7)
5495 *
<< std::scientific
5496 *
<<
" " <<
" ---- "
5497 *
<<
" " <<
" ---- "
5498 *
<<
" " <<
" ---- "
5499 *
<<
" " << m_error_residual_norm.m_norm
5500 *
<<
" " << m_error_residual_norm.m_u
5501 *
<<
" " << m_error_residual_norm.m_d
5502 *
<<
" " << m_error_update_norm.m_norm
5503 *
<<
" " << m_error_update_norm.m_u
5504 *
<<
" " << m_error_update_norm.m_d
5505 *
<<
" " << std::endl;
5507 *
m_logfile <<
'\t' <<
'\t';
5508 *
for (
unsigned int i = 0; i < 135; ++i)
5510 *
m_logfile << std::endl;
5520 *
BFGS_r_vector = m_system_rhs;
5521 *
BFGS_matrix.vmult(BFGS_p_vector, BFGS_r_vector);
5522 *
BFGS_p_vector *= -1.0;
5523 *
m_constraints.distribute(BFGS_p_vector);
5527 * We need a line search algorithm to decide line_search_parameter
5530 *
const double phi_0 = calculate_energy_functional();
5531 *
const double phi_0_prime = BFGS_r_vector * BFGS_p_vector;
5534 *
BFGS_p_vector_block = BFGS_p_vector;
5535 *
line_search_parameter = line_search_stepsize_strong_wolfe(phi_0,
5537 *
BFGS_p_vector_block,
5540 *
BFGS_p_vector *= line_search_parameter;
5541 *
BFGS_update = BFGS_p_vector;
5543 *
get_error_update(BFGS_update, m_error_update);
5544 *
if (BFGS_iteration == 1)
5545 *
m_error_update_0 = m_error_update;
5547 *
m_error_update_norm = m_error_update;
5548 *
m_error_update_norm.normalize(m_error_update_0);
5550 *
solution_delta += BFGS_update;
5551 *
update_qph_incremental(solution_delta, m_solution,
false);
5553 *
BFGS_y_vector = m_system_rhs;
5554 *
BFGS_y_vector *= -1.0;
5555 *
assemble_system_rhs_BFGS(m_solution, m_system_rhs);
5556 *
m_constraints.condense(m_system_rhs);
5557 *
BFGS_temp_vector = m_system_rhs;
5558 *
BFGS_y_vector += BFGS_temp_vector;
5562 * rho should be
positive with the proper line search
5565 *
rho = BFGS_y_vector * BFGS_p_vector;
5569 *
m_logfile <<
"Rho is negative!" << std::endl;
5577 *
if (BFGS_iteration == 1)
5579 *
double scale_parameter = (BFGS_y_vector * BFGS_p_vector) / (BFGS_y_vector.norm_sqr());
5580 *
BFGS_matrix *= scale_parameter;
5583 *
temp_matrix_1.outer_product(BFGS_p_vector, BFGS_y_vector);
5585 *
temp_matrix_2.add(-rho, temp_matrix_1);
5587 *
temp_matrix_2.mmult(temp_matrix_1, BFGS_matrix);
5588 *
temp_matrix_1.mTmult(BFGS_matrix, temp_matrix_2);
5590 *
temp_matrix_1.outer_product(BFGS_p_vector, BFGS_p_vector);
5592 *
BFGS_matrix.add(rho, temp_matrix_1);
5594 *
const double energy_functional = calculate_energy_functional();
5596 *
m_logfile <<
" | " << std::fixed << std::setprecision(3) << std::setw(7)
5597 *
<< std::scientific
5598 *
<<
" " << line_search_parameter
5599 *
<<
" " << energy_functional
5600 *
<<
" " << m_error_residual_norm.m_norm
5601 *
<<
" " << m_error_residual_norm.m_u
5602 *
<<
" " << m_error_residual_norm.m_d
5603 *
<<
" " << m_error_update_norm.m_norm
5604 *
<<
" " << m_error_update_norm.m_u
5605 *
<<
" " << m_error_update_norm.m_d
5606 *
<<
" " << std::endl;
5609 *
AssertThrow(BFGS_iteration < m_parameters.m_max_iterations_BFGS,
5610 *
ExcMessage(
"No convergence in BFGS nonlinear solver!"));
5613 *
template <
int dim>
5614 *
void PhaseFieldMonolithicSolve<dim>::
5620 *
LBFGS_update = 0.0;
5622 *
m_error_residual.reset();
5623 *
m_error_residual_0.reset();
5624 *
m_error_residual_norm.reset();
5625 *
m_error_update.reset();
5626 *
m_error_update_0.reset();
5627 *
m_error_update_norm.reset();
5629 *
if (m_parameters.m_output_iteration_history)
5630 *
print_conv_header_LBFGS();
5632 *
unsigned int LBFGS_iteration = 0;
5638 *
std::list<std::pair< std::pair<BlockVector<double>,
5640 *
double>> LBFGS_vector_list;
5642 *
const unsigned int LBFGS_m = m_parameters.m_LBFGS_m;
5643 *
std::list<double> LBFGS_alpha_list;
5645 *
double line_search_parameter = 0.0;
5646 *
double LBFGS_beta = 0.0;
5649 *
for (; LBFGS_iteration < m_parameters.m_max_iterations_BFGS; ++LBFGS_iteration)
5651 *
if (m_parameters.m_output_iteration_history)
5652 *
m_logfile <<
'\t' <<
'\t' << std::setw(2) << LBFGS_iteration <<
' '
5655 *
make_constraints(LBFGS_iteration);
5659 * At the
first step, we simply distribute the inhomogeneous part of
5663 *
if (LBFGS_iteration == 0)
5667 * use the solution from the previous solve on the
5668 * refined mesh as
initial guess
5671 *
LBFGS_update = LBFGS_update_refine;
5673 *
m_constraints.distribute(LBFGS_update);
5674 *
solution_delta += LBFGS_update;
5675 *
if (m_parameters.m_output_iteration_history)
5677 *
m_logfile <<
" --- " << std::flush;
5678 *
m_logfile <<
" --- " << std::flush;
5680 *
update_qph_incremental(solution_delta, m_solution,
false);
5681 *
if (m_parameters.m_output_iteration_history)
5683 *
m_logfile <<
" --- |" << std::flush;
5684 *
m_logfile << std::endl;
5688 *
else if (LBFGS_iteration == 1)
5692 * Calculate the residual vector r. NOTICE that in the context of
5693 * BFGS,
this r is the
gradient of the energy functional (objective function),
5697 *
assemble_system_rhs_BFGS_parallel(m_solution, m_system_rhs);
5701 * We cannot simply
zero out the dofs that are constrained, since we might
5702 * have hanging node constraints. In
this case, we need to modify the RHS
5703 * as
C^
T *
b, which
C contains entries of 0.5 (x_3 = 0.5*x_1 + 0.5*x_2)
5704 *
for (
unsigned int i = 0; i < m_dof_handler.n_dofs(); ++i)
5705 *
if (m_constraints.is_constrained(i))
5706 * m_system_rhs(i) = 0.0;
5710 *
if m_constraints has inhomogeneity, we cannot call m_constraints.condense(m_system_rhs),
5711 * since the m_system_matrix needs to be provided to modify the RHS properly. However,
this
5712 * error will not be detected in the
release mode and only will be detected on the
debug mode
5713 *
if we use assemble_system_rhs_BFGS_parallel, then condense() is not necessary
5714 * m_constraints.condense(m_system_rhs);
5718 *
if (m_parameters.m_output_iteration_history)
5720 *
m_logfile <<
" --- " << std::flush;
5721 *
m_logfile <<
" --- " << std::flush;
5722 *
m_logfile <<
" --- " << std::flush;
5725 *
get_error_residual(m_error_residual);
5726 *
if (LBFGS_iteration == 1)
5727 *
m_error_residual_0 = m_error_residual;
5729 *
m_error_residual_norm = m_error_residual;
5732 * For three-
point bending problem and 3D problem, we use absolute residual
5733 *
for convergence test
5736 *
if (m_parameters.m_relative_residual)
5737 *
m_error_residual_norm.normalize(m_error_residual_0);
5739 *
if (LBFGS_iteration > 1 && m_error_update_norm.m_u <= m_parameters.m_tol_u_incr
5740 *
&& m_error_residual_norm.m_u <= m_parameters.m_tol_u_residual
5741 *
&& m_error_update_norm.m_d <= m_parameters.m_tol_d_incr
5742 *
&& m_error_residual_norm.m_d <= m_parameters.m_tol_d_residual
5745 *
if (m_parameters.m_output_iteration_history)
5747 *
m_logfile <<
" | ";
5748 *
m_logfile <<
" CONVERGED! " << std::fixed << std::setprecision(3) << std::setw(7)
5749 *
<< std::scientific
5751 *
<<
" " << m_error_residual_norm.m_norm
5752 *
<<
" " << m_error_residual_norm.m_u
5753 *
<<
" " << m_error_residual_norm.m_d
5754 *
<<
" " << m_error_update_norm.m_norm
5755 *
<<
" " << m_error_update_norm.m_u
5756 *
<<
" " << m_error_update_norm.m_d
5757 *
<<
" " << std::endl;
5759 *
m_logfile <<
'\t' <<
'\t';
5760 *
for (
unsigned int i = 0; i < 120; ++i)
5762 *
m_logfile << std::endl;
5765 *
m_logfile <<
"\t\tConvergence is reached after "
5766 *
<< LBFGS_iteration <<
" L-BFGS iterations."<< std::endl;
5768 *
m_logfile <<
"\t\tResidual information of convergence:" << std::endl;
5770 *
if (m_parameters.m_relative_residual)
5772 *
m_logfile <<
"\t\t\tRelative residual of disp. equation: "
5773 *
<< m_error_residual_norm.m_u << std::endl;
5775 *
m_logfile <<
"\t\t\tAbsolute residual of disp. equation: "
5776 *
<< m_error_residual_norm.m_u * m_error_residual_0.m_u << std::endl;
5778 *
m_logfile <<
"\t\t\tRelative residual of phasefield equation: "
5779 *
<< m_error_residual_norm.m_d << std::endl;
5781 *
m_logfile <<
"\t\t\tAbsolute residual of phasefield equation: "
5782 *
<< m_error_residual_norm.m_d * m_error_residual_0.m_d << std::endl;
5784 *
m_logfile <<
"\t\t\tRelative increment of disp.: "
5785 *
<< m_error_update_norm.m_u << std::endl;
5787 *
m_logfile <<
"\t\t\tAbsolute increment of disp.: "
5788 *
<< m_error_update_norm.m_u * m_error_update_0.m_u << std::endl;
5790 *
m_logfile <<
"\t\t\tRelative increment of phasefield: "
5791 *
<< m_error_update_norm.m_d << std::endl;
5793 *
m_logfile <<
"\t\t\tAbsolute increment of phasefield: "
5794 *
<< m_error_update_norm.m_d * m_error_update_0.m_d << std::endl;
5798 *
m_logfile <<
"\t\t\tAbsolute residual of disp. equation: "
5799 *
<< m_error_residual_norm.m_u << std::endl;
5801 *
m_logfile <<
"\t\t\tAbsolute residual of phasefield equation: "
5802 *
<< m_error_residual_norm.m_d << std::endl;
5804 *
m_logfile <<
"\t\t\tAbsolute increment of disp.: "
5805 *
<< m_error_update_norm.m_u << std::endl;
5807 *
m_logfile <<
"\t\t\tAbsolute increment of phasefield: "
5808 *
<< m_error_update_norm.m_d << std::endl;
5819 *
LBFGS_q_vector = m_system_rhs;
5821 *
LBFGS_alpha_list.
clear();
5822 *
for (
auto itr = LBFGS_vector_list.begin(); itr != LBFGS_vector_list.end(); ++itr)
5824 *
LBFGS_s_vector = (itr->first).
first;
5825 *
LBFGS_y_vector = (itr->first).
second;
5826 *
rho = itr->second;
5828 *
const double alpha = rho * (LBFGS_s_vector * LBFGS_q_vector);
5829 *
LBFGS_alpha_list.push_back(alpha);
5831 *
LBFGS_q_vector.add(-alpha, LBFGS_y_vector);
5849 *
LBFGS_B0(LBFGS_r_vector,
5852 *
for (
auto itr = LBFGS_vector_list.rbegin(); itr != LBFGS_vector_list.rend(); ++itr)
5854 *
LBFGS_s_vector = (itr->first).
first;
5855 *
LBFGS_y_vector = (itr->first).
second;
5856 *
rho = itr->second;
5858 *
LBFGS_beta = rho * (LBFGS_y_vector * LBFGS_r_vector);
5860 *
const double alpha = LBFGS_alpha_list.back();
5861 *
LBFGS_alpha_list.pop_back();
5863 *
LBFGS_r_vector.add(alpha - LBFGS_beta, LBFGS_s_vector);
5866 *
LBFGS_r_vector *= -1.0;
5868 *
m_constraints.distribute(LBFGS_r_vector);
5872 * We need a line search algorithm to decide line_search_parameter
5875 *
if(m_parameters.m_type_line_search ==
"StrongWolfe")
5877 *
const double phi_0 = calculate_energy_functional();
5878 *
const double phi_0_prime = m_system_rhs * LBFGS_r_vector;
5880 *
line_search_parameter = line_search_stepsize_strong_wolfe(phi_0,
5885 *
else if(m_parameters.m_type_line_search ==
"GradientBased")
5889 * LBFGS_r_vector is the search direction
5892 *
line_search_parameter = line_search_stepsize_gradient_based(LBFGS_r_vector,
5897 *
Assert(
false, ExcMessage(
"An unknown line search method is called!"));
5900 *
LBFGS_r_vector *= line_search_parameter;
5901 *
LBFGS_update = LBFGS_r_vector;
5903 *
get_error_update(LBFGS_update, m_error_update);
5904 *
if (LBFGS_iteration == 1)
5905 *
m_error_update_0 = m_error_update;
5907 *
m_error_update_norm = m_error_update;
5910 * For three-
point bending problem and the sphere inclusion problem,
5911 * we use absolute residual
for convergence test
5914 *
if (m_parameters.m_relative_residual)
5915 *
m_error_update_norm.normalize(m_error_update_0);
5917 *
solution_delta += LBFGS_update;
5918 *
update_qph_incremental(solution_delta, m_solution,
false);
5920 *
LBFGS_y_vector = m_system_rhs;
5921 *
LBFGS_y_vector *= -1.0;
5922 *
assemble_system_rhs_BFGS_parallel(m_solution, m_system_rhs);
5925 *
if we use assemble_system_rhs_BFGS_parallel, then condense() is not necessary
5926 * m_constraints.condense(m_system_rhs);
5929 *
LBFGS_y_vector += m_system_rhs;
5931 *
LBFGS_s_vector = LBFGS_update;
5933 *
const
double g_norm = m_system_rhs.l2_norm();
5935 *
const
double yxs = LBFGS_y_vector * LBFGS_s_vector;
5937 *
const
double sxs = LBFGS_s_vector * LBFGS_s_vector;
5939 *
if (yxs/sxs >= 1.0e-6 * g_norm)
5941 *
if (LBFGS_iteration > LBFGS_m)
5942 *
LBFGS_vector_list.pop_back();
5946 *
LBFGS_vector_list.push_front(std::make_pair(std::make_pair(LBFGS_s_vector,
5951 *
if (m_parameters.m_output_iteration_history)
5953 *
const double energy_functional = calculate_energy_functional();
5955 *
m_logfile <<
" | " << std::fixed << std::setprecision(3) << std::setw(1)
5956 *
<< std::scientific
5957 *
<<
"" << line_search_parameter
5958 *
<< std::fixed << std::setprecision(6) << std::setw(1)
5959 *
<< std::scientific
5960 *
<<
" " << energy_functional
5961 *
<< std::fixed << std::setprecision(3) << std::setw(1)
5962 *
<< std::scientific
5963 *
<<
" " << m_error_residual_norm.m_norm
5964 *
<<
" " << m_error_residual_norm.m_u
5965 *
<<
" " << m_error_residual_norm.m_d
5966 *
<<
" " << m_error_update_norm.m_norm
5967 *
<<
" " << m_error_update_norm.m_u
5968 *
<<
" " << m_error_update_norm.m_d
5969 *
<<
" " << std::endl;
5973 *
AssertThrow(LBFGS_iteration < m_parameters.m_max_iterations_BFGS,
5974 *
ExcMessage(
"No convergence in L-BFGS nonlinear solver!"));
5977 *
template <
int dim>
5978 *
void PhaseFieldMonolithicSolve<dim>::output_results() const
5980 *
m_timer.enter_subsection(
"Output results");
5984 *
std::vector<DataComponentInterpretation::DataComponentInterpretation>
5985 *
data_component_interpretation(
5988 *
data_component_interpretation.push_back(
5991 *
std::vector<std::string> solution_name(dim,
"displacement");
5992 *
solution_name.emplace_back(
"phasefield");
5994 *
data_out.attach_dof_handler(m_dof_handler);
5995 *
data_out.add_data_vector(m_solution,
5998 *
data_component_interpretation);
6001 *
Vector<double> cell_material_id(m_triangulation.n_active_cells());
6004 * output material ID
for each cell
6007 *
for (
const auto &cell : m_triangulation.active_cell_iterators())
6009 *
cell_material_id(cell->active_cell_index()) = cell->
material_id();
6011 *
data_out.add_data_vector(cell_material_id,
"materialID");
6015 * Stress
L2 projection
6019 *
FE_Q<dim> stresses_fe_L2(m_parameters.m_poly_degree);
6020 *
stresses_dof_handler_L2.distribute_dofs(stresses_fe_L2);
6022 *
constraints.
clear();
6024 *
constraints.close();
6025 *
std::vector<DataComponentInterpretation::DataComponentInterpretation>
6026 *
data_component_interpretation_stress(1,
6029 *
for (
unsigned int i = 0; i < dim; ++i)
6030 *
for (
unsigned int j = i; j < dim; ++j)
6033 *
stress_field_L2.
reinit(stresses_dof_handler_L2.n_dofs());
6037 *
stresses_dof_handler_L2,
6041 *
const unsigned int q) ->
double
6043 *
return m_quadrature_point_history.get_data(cell)[q]->get_cauchy_stress()[i][j];
6047 *
std::string stress_name =
"Cauchy_stress_" + std::to_string(i+1) + std::to_string(j+1)
6050 *
data_out.add_data_vector(stresses_dof_handler_L2,
6053 *
data_component_interpretation_stress);
6056 *
data_out.build_patches(m_parameters.m_poly_degree);
6058 *
std::ofstream output(
"Solution-" + std::to_string(dim) +
"d-" +
6061 *
data_out.write_vtu(output);
6062 *
m_timer.leave_subsection();
6065 *
template <
int dim>
6066 *
void PhaseFieldMonolithicSolve<dim>::calculate_reaction_force(
unsigned int face_ID)
6068 *
m_timer.enter_subsection(
"Calculate reaction force");
6071 *
system_rhs.
reinit(m_dofs_per_block);
6074 *
std::vector<types::global_dof_index> local_dof_indices(m_dofs_per_cell);
6076 *
const double time_ramp = (m_time.current() / m_time.end());
6077 *
std::vector<Tensor<1, dim>> rhs_values(m_n_q_points);
6088 * shape function
values for displacement field
6091 *
std::vector<std::vector<Tensor<1, dim>>>
6092 *
Nx(m_qf_cell.size(), std::vector<
Tensor<1, dim>>(m_dofs_per_cell));
6093 *
std::vector<std::vector<Tensor<2, dim>>>
6094 *
grad_Nx(m_qf_cell.size(), std::vector<
Tensor<2, dim>>(m_dofs_per_cell));
6095 *
std::vector<std::vector<SymmetricTensor<2, dim>>>
6098 *
for (
const auto &cell : m_dof_handler.active_cell_iterators())
6102 *
if calculate_reaction_force() is defined as
const, then
6103 * we also need to put a
const in
std::shared_ptr,
6104 * that is,
std::shared_ptr<
const PointHistory<dim>>
6107 *
const std::vector<
std::shared_ptr< PointHistory<dim>>> lqph =
6108 *
m_quadrature_point_history.get_data(cell);
6109 *
Assert(lqph.size() == m_n_q_points, ExcInternalError());
6111 *
fe_values.reinit(cell);
6112 *
right_hand_side(fe_values.get_quadrature_points(),
6114 *
m_parameters.m_x_component*time_ramp,
6115 *
m_parameters.m_y_component*time_ramp,
6116 *
m_parameters.m_z_component*time_ramp);
6118 *
for (
const unsigned int q_point : fe_values.quadrature_point_indices())
6120 *
for (
const unsigned
int k : fe_values.dof_indices())
6124 *
if (k_group == m_u_dof)
6126 *
Nx[q_point][k] = fe_values[m_u_fe].value(k, q_point);
6127 *
grad_Nx[q_point][k] = fe_values[m_u_fe].gradient(k, q_point);
6128 *
symm_grad_Nx[q_point][k] =
symmetrize(grad_Nx[q_point][k]);
6133 *
for (
const unsigned int q_point : fe_values.quadrature_point_indices())
6137 *
const std::vector<Tensor<1,dim>> &
N = Nx[q_point];
6138 *
const std::vector<SymmetricTensor<2, dim>> & symm_grad_N = symm_grad_Nx[q_point];
6139 *
const double JxW = fe_values.JxW(q_point);
6141 *
for (
const unsigned int i : fe_values.dof_indices())
6145 *
if (i_group == m_u_dof)
6147 *
cell_rhs(i) -= (symm_grad_N[i] * cauchy_stress) * JxW;
6150 * contributions from the body force to right-hand side
6153 *
cell_rhs(i) +=
N[i] * rhs_values[q_point] * JxW;
6160 *
if there is surface pressure,
this surface pressure
always applied to the
6164 *
const unsigned int face_pressure_id = 100;
6165 *
const double p0 = 0.0;
6167 *
for (
const auto &face : cell->face_iterators())
6169 *
if (face->at_boundary() && face->
boundary_id() == face_pressure_id)
6171 *
fe_face_values.
reinit(cell, face);
6173 *
for (
const unsigned int f_q_point : fe_face_values.quadrature_point_indices())
6175 *
const Tensor<1, dim> &
N = fe_face_values.normal_vector(f_q_point);
6177 *
const double pressure = p0 * time_ramp;
6180 *
for (
const unsigned int i : fe_values.dof_indices())
6184 *
if (i_group == m_u_dof)
6186 *
const unsigned int component_i = m_fe.system_to_component_index(i).first;
6187 *
const double Ni = fe_face_values.shape_value(i, f_q_point);
6188 *
const double JxW = fe_face_values.JxW(f_q_point);
6189 *
cell_rhs(i) += (Ni * traction[component_i]) * JxW;
6196 *
cell->get_dof_indices(local_dof_indices);
6197 *
for (
const unsigned int i : fe_values.dof_indices())
6198 *
system_rhs(local_dof_indices[i]) += cell_rhs(i);
6203 * The difference between the above assembled system_rhs and m_system_rhs
6204 * is that m_system_rhs is condensed by the m_constraints, which
zero out
6205 * the rhs
values associated with the constrained DOFs and modify the rhs
6212 *
std::vector< types::global_dof_index > mapping;
6213 *
std::set<types::boundary_id> boundary_ids;
6214 *
boundary_ids.insert(face_ID);
6219 *
std::vector<double> reaction_force(dim, 0.0);
6221 *
for (
unsigned int i = 0; i < m_dofs_per_block[m_u_dof]; ++i)
6225 *
reaction_force[i % dim] += system_rhs.block(m_u_dof)(i);
6229 *
for (
unsigned int i = 0; i < dim; i++)
6230 *
m_logfile <<
"\t\tReaction force in direction " << i <<
" on boundary ID " << face_ID
6232 *
<< std::fixed << std::setprecision(3) << std::setw(1)
6233 *
<< std::scientific
6234 *
<< reaction_force[i] << std::endl;
6236 *
std::pair<double, std::vector<double>> time_force;
6237 *
time_force.first = m_time.current();
6238 *
time_force.second = reaction_force;
6239 *
m_history_reaction_force.push_back(time_force);
6241 *
m_timer.leave_subsection();
6244 *
template <
int dim>
6245 *
void PhaseFieldMonolithicSolve<dim>::write_history_data()
6247 *
m_logfile <<
"\t\tWrite history data ... \n"<<std::endl;
6249 *
std::ofstream myfile_reaction_force (
"Reaction_force.hist");
6250 *
if (myfile_reaction_force.is_open())
6252 *
myfile_reaction_force << 0.0 <<
"\t";
6254 *
myfile_reaction_force << 0.0 <<
"\t"
6255 *
<< 0.0 << std::endl;
6257 *
myfile_reaction_force << 0.0 <<
"\t"
6259 *
<< 0.0 << std::endl;
6261 *
for (
const auto &time_force : m_history_reaction_force)
6263 *
myfile_reaction_force << time_force.
first <<
"\t";
6265 *
myfile_reaction_force << time_force.second[0] <<
"\t"
6266 *
<< time_force.second[1] << std::endl;
6268 *
myfile_reaction_force << time_force.second[0] <<
"\t"
6269 *
<< time_force.second[1] <<
"\t"
6270 *
<< time_force.second[2] << std::endl;
6272 *
myfile_reaction_force.close();
6275 *
m_logfile <<
"Unable to open file";
6277 *
std::ofstream myfile_energy (
"Energy.hist");
6278 *
if (myfile_energy.is_open())
6280 *
myfile_energy << std::fixed << std::setprecision(10) << std::scientific
6284 *
<< 0.0 << std::endl;
6286 *
for (
const auto &time_energy : m_history_energy)
6288 *
myfile_energy <<
std::fixed <<
std::setprecision(10) <<
std::scientific
6289 *
<< time_energy.
first <<
"\t"
6290 *
<< time_energy.
second[0] <<
"\t"
6291 *
<< time_energy.
second[1] <<
"\t"
6292 *
<< time_energy.
second[2] <<
std::endl;
6294 *
myfile_energy.close();
6297 *
m_logfile <<
"Unable to open file";
6300 *
template <
int dim>
6301 *
double PhaseFieldMonolithicSolve<dim>::calculate_energy_functional() const
6303 *
double energy_functional = 0.0;
6307 *
for (
const auto &cell : m_dof_handler.active_cell_iterators())
6309 *
fe_values.
reinit(cell);
6311 *
const std::vector<std::shared_ptr<const PointHistory<dim>>> lqph =
6312 *
m_quadrature_point_history.get_data(cell);
6313 *
Assert(lqph.size() == m_n_q_points, ExcInternalError());
6315 *
for (
unsigned int q_point = 0; q_point < m_n_q_points; ++q_point)
6317 *
const double JxW = fe_values.JxW(q_point);
6318 *
energy_functional += lqph[q_point]->get_total_strain_energy() * JxW;
6319 *
energy_functional += lqph[q_point]->get_crack_energy_dissipation() * JxW;
6323 *
return energy_functional;
6326 *
template <
int dim>
6327 *
std::pair<double, double>
6328 *
PhaseFieldMonolithicSolve<dim>::calculate_total_strain_energy_and_crack_energy_dissipation() const
6330 *
double total_strain_energy = 0.0;
6331 *
double crack_energy_dissipation = 0.0;
6335 *
for (
const auto &cell : m_dof_handler.active_cell_iterators())
6337 *
fe_values.
reinit(cell);
6339 *
const std::vector<std::shared_ptr<const PointHistory<dim>>> lqph =
6340 *
m_quadrature_point_history.get_data(cell);
6341 *
Assert(lqph.size() == m_n_q_points, ExcInternalError());
6343 *
for (
unsigned int q_point = 0; q_point < m_n_q_points; ++q_point)
6345 *
const double JxW = fe_values.JxW(q_point);
6346 *
total_strain_energy += lqph[q_point]->get_total_strain_energy() * JxW;
6347 *
crack_energy_dissipation += lqph[q_point]->get_crack_energy_dissipation() * JxW;
6351 *
return std::make_pair(total_strain_energy, crack_energy_dissipation);
6355 *
template <
int dim>
6356 *
bool PhaseFieldMonolithicSolve<dim>::local_refine_and_solution_transfer(
BlockVector<double> & solution_delta,
6361 * This is the solution at (n+1) obtained from the old (coarse) mesh
6364 *
BlockVector<
double> solution_next_step(m_dofs_per_block);
6365 *
solution_next_step = m_solution + solution_delta;
6366 *
bool mesh_is_same = true;
6367 *
bool cell_refine_flag = true;
6369 *
unsigned int material_id;
6370 *
double length_scale;
6371 *
double cell_length;
6372 *
while(cell_refine_flag)
6374 *
cell_refine_flag =
false;
6376 *
std::vector<types::global_dof_index> local_dof_indices(m_fe.dofs_per_cell);
6377 *
for (
const auto &cell : m_dof_handler.active_cell_iterators())
6379 *
cell->get_dof_indices(local_dof_indices);
6381 *
for (
unsigned int i = 0; i< m_fe.dofs_per_cell; ++i)
6383 *
const unsigned int comp_i = m_fe.system_to_component_index(i).first;
6384 *
if (comp_i == m_d_component)
6386 *
if ( solution_next_step(local_dof_indices[i])
6387 *
> m_parameters.m_phasefield_refine_threshold )
6392 *
cell_length =
std::sqrt(cell->measure());
6394 *
cell_length = std::cbrt(cell->measure());
6396 *
> length_scale * m_parameters.m_allowed_max_h_l_ratio )
6398 *
if (cell->level() < m_parameters.m_max_allowed_refinement_level)
6400 *
cell->set_refine_flag();
6409 *
for (
const auto &cell : m_dof_handler.active_cell_iterators())
6411 *
if (cell->refine_flag_set())
6413 *
cell_refine_flag = true;
6420 *
if any cell is refined, we need to
project the solution
6421 * to the newly refined mesh
6424 *
if (cell_refine_flag)
6426 *
mesh_is_same =
false;
6428 *
std::vector<BlockVector<double> > old_solutions(2);
6429 *
old_solutions[0] = solution_next_step;
6430 *
old_solutions[1] = m_solution;
6432 *
m_triangulation.prepare_coarsening_and_refinement();
6434 *
solution_transfer.prepare_for_coarsening_and_refinement(old_solutions);
6435 *
m_triangulation.execute_coarsening_and_refinement();
6439 *
std::vector<BlockVector<double>> tmp_solutions(2);
6440 *
tmp_solutions[0].reinit(m_dofs_per_block);
6441 *
tmp_solutions[1].reinit(m_dofs_per_block);
6442 *
solution_transfer.interpolate(tmp_solutions);
6443 *
solution_next_step = tmp_solutions[0];
6444 *
m_solution = tmp_solutions[1];
6448 * make sure the projected solutions still satisfy
6449 * hanging node constraints
6452 *
m_constraints.distribute(solution_next_step);
6453 *
m_constraints.distribute(m_solution);
6459 * calculate field variables
for newly refined cells
6462 *
if (!mesh_is_same)
6466 *
temp_solution_delta = 0.0;
6467 *
temp_previous_solution = 0.0;
6468 *
update_qph_incremental(temp_solution_delta, temp_previous_solution,
false);
6469 *
update_history_field_step();
6473 *
initial guess
for the resolve on the refined mesh
6476 *
LBFGS_update_refine = solution_next_step - m_solution;
6479 *
return mesh_is_same;
6482 *
template <
int dim>
6483 *
void PhaseFieldMonolithicSolve<dim>::print_parameter_information()
6485 *
m_logfile <<
"Scenario number = " << m_parameters.m_scenario << std::endl;
6486 *
m_logfile <<
"Log file = " << m_parameters.m_logfile_name << std::endl;
6487 *
m_logfile <<
"Write iteration history to log file? = " << std::boolalpha
6488 *
<< m_parameters.m_output_iteration_history << std::endl;
6489 *
m_logfile <<
"Nonlinear solver type = " << m_parameters.m_type_nonlinear_solver << std::endl;
6490 *
m_logfile <<
"Line search type = " << m_parameters.m_type_line_search << std::endl;
6491 *
m_logfile <<
"Linear solver type = " << m_parameters.m_type_linear_solver << std::endl;
6492 *
m_logfile <<
"Mesh refinement strategy = " << m_parameters.m_refinement_strategy << std::endl;
6493 *
m_logfile <<
"L-BFGS_m = " << m_parameters.m_LBFGS_m << std::endl;
6494 *
m_logfile <<
"Global refinement times = " << m_parameters.m_global_refine_times << std::endl;
6495 *
m_logfile <<
"Local prerefinement times = " <<m_parameters. m_local_prerefine_times << std::endl;
6496 *
m_logfile <<
"Maximum adaptive refinement times allowed in each step = "
6497 *
<< m_parameters.m_max_adaptive_refine_times << std::endl;
6498 *
m_logfile <<
"Maximum allowed cell refinement level = "
6499 *
<< m_parameters.m_max_allowed_refinement_level << std::endl;
6500 *
m_logfile <<
"Phasefield-based refinement threshold value = "
6501 *
<< m_parameters.m_phasefield_refine_threshold << std::endl;
6502 *
m_logfile <<
"Allowed maximum h/l ratio = " << m_parameters.m_allowed_max_h_l_ratio << std::endl;
6503 *
m_logfile <<
"total number of material types = " << m_parameters.m_total_material_regions << std::endl;
6504 *
m_logfile <<
"material data file name = " << m_parameters.m_material_file_name << std::endl;
6505 *
if (m_parameters.m_reaction_force_face_id >= 0)
6506 *
m_logfile <<
"Calculate reaction forces on Face ID = " << m_parameters.m_reaction_force_face_id << std::endl;
6508 *
m_logfile <<
"No need to calculate reaction forces." << std::endl;
6510 *
if (m_parameters.m_relative_residual)
6511 *
m_logfile <<
"Relative residual for convergence." << std::endl;
6513 *
m_logfile <<
"Absolute residual for convergence." << std::endl;
6515 *
m_logfile <<
"Body force = (" << m_parameters.m_x_component <<
", "
6516 *
<< m_parameters.m_y_component <<
", "
6517 *
<< m_parameters.m_z_component <<
") (N/m^3)"
6520 *
m_logfile <<
"End time = " << m_parameters.m_end_time << std::endl;
6521 *
m_logfile <<
"Time data file name = " << m_parameters.m_time_file_name << std::endl;
6524 *
template <
int dim>
6525 *
void PhaseFieldMonolithicSolve<dim>::run()
6527 *
print_parameter_information();
6529 *
read_material_data(m_parameters.m_material_file_name,
6530 *
m_parameters.m_total_material_regions);
6532 *
std::vector<std::array<double, 4>> time_table;
6534 *
read_time_data(m_parameters.m_time_file_name, time_table);
6540 *
m_time.increment(time_table);
6542 *
while(m_time.current() < m_time.end() + m_time.get_delta_t()*1.0e-6)
6544 *
m_logfile << std::endl
6545 *
<<
"Timestep " << m_time.get_timestep() <<
" @ " << m_time.current()
6546 *
<<
's' << std::endl;
6548 *
bool mesh_is_same =
false;
6552 *
initial guess
for the resolve on the refined mesh
6556 *
LBFGS_update_refine = 0.0;
6560 * local adaptive mesh refinement
loop
6563 *
unsigned int adp_refine_iteration = 0;
6564 *
for (; adp_refine_iteration < m_parameters.m_max_adaptive_refine_times + 1; ++adp_refine_iteration)
6566 *
if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
6567 *
m_logfile <<
"\tAdaptive refinement-"<< adp_refine_iteration <<
": " << std::endl;
6570 *
solution_delta = 0.0;
6572 *
if (m_parameters.m_type_nonlinear_solver ==
"Newton")
6574 *
bool newton_success =
false;
6575 *
newton_success = solve_nonlinear_timestep_newton(solution_delta);
6577 *
ExcMessage(
"No convergence in Newton-Raphson nonlinear solver!"));
6591 *
else if (m_parameters.m_type_nonlinear_solver ==
"BFGS")
6592 *
solve_nonlinear_timestep_BFGS(solution_delta);
6593 *
else if (m_parameters.m_type_nonlinear_solver ==
"LBFGS")
6594 *
solve_nonlinear_timestep_LBFGS(solution_delta, LBFGS_update_refine);
6596 *
AssertThrow(
false, ExcMessage(
"Nonlinear solver type not implemented"));
6598 *
if (m_parameters.m_refinement_strategy ==
"adaptive-refine")
6601 *
if (adp_refine_iteration == m_parameters.m_max_adaptive_refine_times)
6603 *
m_solution += solution_delta;
6607 *
mesh_is_same = local_refine_and_solution_transfer(solution_delta,
6608 *
LBFGS_update_refine);
6612 *
m_solution += solution_delta;
6616 *
else if (m_parameters.m_refinement_strategy ==
"pre-refine")
6618 *
m_solution += solution_delta;
6624 *
ExcMessage(
"Selected mesh refinement strategy not implemented!"));
6630 *
AssertThrow(adp_refine_iteration < m_parameters.m_max_adaptive_refine_times,
6631 * ExcMessage(
"Number of local adaptive mesh refinement exceeds allowed maximum times!"));
6637 *
update_history_field_step();
6640 * output
vtk files every 10 steps
if there are too
6642 *
if (m_time.get_timestep() % 10 == 0)
6647 *
double energy_functional_current = calculate_energy_functional();
6648 *
m_logfile <<
"\t\tEnergy functional (J) = " << std::fixed << std::setprecision(10) << std::scientific
6649 *
<< energy_functional_current << std::endl;
6651 *
std::pair<double, double> energy_pair = calculate_total_strain_energy_and_crack_energy_dissipation();
6652 *
m_logfile <<
"\t\tTotal strain energy (J) = " << std::fixed << std::setprecision(10) << std::scientific
6653 *
<< energy_pair.first << std::endl;
6654 *
m_logfile <<
"\t\tCrack energy dissipation (J) = " << std::fixed << std::setprecision(10) << std::scientific
6655 *
<< energy_pair.second << std::endl;
6657 *
std::pair<double, std::array<double, 3>> time_energy;
6658 *
time_energy.first = m_time.current();
6659 *
time_energy.second[0] = energy_pair.first;
6660 *
time_energy.second[1] = energy_pair.second;
6661 *
time_energy.second[2] = energy_pair.first + energy_pair.second;
6662 *
m_history_energy.push_back(time_energy);
6664 *
int face_ID = m_parameters.m_reaction_force_face_id;
6666 *
calculate_reaction_force(face_ID);
6668 *
write_history_data();
6670 *
m_time.increment(time_table);
6676 *
int main(
int argc,
char* argv[])
6679 *
using namespace dealii;
6683 *
ExcMessage(
"The number of arguments provided to the program has to be 2!"));
6685 *
const unsigned int dim = std::stoi(argv[1]);
6688 *
PhaseField::PhaseFieldMonolithicSolve<2> FEQ1Full(
"parameters.prm");
6691 *
else if (dim == 3)
6693 *
PhaseField::PhaseFieldMonolithicSolve<3> SphereInclusion3D(
"parameters.prm");
6694 *
SphereInclusion3D.run();
6699 *
ExcMessage(
"Dimension has to be either 2 or 3"));
* * for(const auto &cell :triangulation.active_cell_iterators())
* * int main(int argc, char **argv)
* * * struct InterferenceTaperTransform *
virtual size_type size() const override
void reinit(const unsigned int n_blocks, const size_type block_size=0, const bool omit_zeroing_entries=false)
void reinit(const Triangulation< dim, spacedim > &tria)
void attach_triangulation(Triangulation< dim, spacedim > &tria)
void write_vtu(const Triangulation< dim, spacedim > &tria, std::ostream &out) const
void initialize(const MatrixType &A, const AdditionalData ¶meters=AdditionalData())
void initialize(const SparsityPattern &sparsity_pattern)
void initialize(const Triangulation< dim, spacedim > &triangulation)
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
#define Assert(cond, exc)
#define AssertThrow(cond, exc)
typename ActiveSelector::active_cell_iterator active_cell_iterator
LinearOperator< Range, Domain, Payload > linear_operator(const OperatorExemplar &, const Matrix &)
void loop(IteratorType begin, std_cxx20::type_identity_t< IteratorType > end, DOFINFO &dinfo, INFOBOX &info, const std::function< void(std_cxx20::type_identity_t< DOFINFO > &, typename INFOBOX::CellInfo &)> &cell_worker, const std::function< void(std_cxx20::type_identity_t< DOFINFO > &, typename INFOBOX::CellInfo &)> &boundary_worker, const std::function< void(std_cxx20::type_identity_t< DOFINFO > &, std_cxx20::type_identity_t< DOFINFO > &, typename INFOBOX::CellInfo &, typename INFOBOX::CellInfo &)> &face_worker, AssemblerType &assembler, const LoopControl &lctrl=LoopControl())
void make_hanging_node_constraints(const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< number > &constraints)
void make_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern, const AffineConstraints< number > &constraints={}, const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
@ update_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 reset_all_manifolds()
std::vector< index_type > data
@ component_is_part_of_vector
Expression fabs(const Expression &x)
Expression sign(const Expression &x)
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 >())
void hyper_shell(Triangulation< dim, spacedim > &tria, const Point< spacedim > ¢er, const double inner_radius, const double outer_radius, const unsigned int n_cells=0, bool colorize=false)
void hyper_rectangle(Triangulation< dim, spacedim > &tria, const Point< dim > &p1, const Point< dim > &p2, const bool colorize=false)
void extrude_triangulation(const Triangulation< 2, 2 > &input, const unsigned int n_slices, const double height, Triangulation< 3, 3 > &result, const bool copy_manifold_ids=false, const std::vector< types::manifold_id > &manifold_priorities={})
void hyper_ball(Triangulation< dim, spacedim > &tria, const Point< spacedim > ¢er={}, const double radius=1., const bool attach_spherical_manifold_on_boundary_cells=false)
void subdivided_hyper_rectangle(Triangulation< dim, spacedim > &tria, const std::vector< unsigned int > &repetitions, const Point< dim > &p1, const Point< dim > &p2, const bool colorize=false)
void create_triangulation_with_removed_cells(const Triangulation< dim, spacedim > &input_triangulation, const std::set< typename Triangulation< dim, spacedim >::active_cell_iterator > &cells_to_remove, Triangulation< dim, spacedim > &result)
void merge_triangulations(const Triangulation< dim, spacedim > &triangulation_1, const Triangulation< dim, spacedim > &triangulation_2, Triangulation< dim, spacedim > &result, const double duplicated_vertex_tolerance=1.0e-12, const bool copy_manifold_ids=false, const bool copy_boundary_ids=false)
@ matrix
Contents is actually a matrix.
constexpr types::blas_int zero
void L2(Vector< number > &result, const FEValuesBase< dim > &fe, const std::vector< double > &input, const double factor=1.)
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)
* * * ScaleZFunction< dim, Number, components >::ScaleZFunction * component(component)
* * if(update_pressure &update_flags) * compute_pressure(constitutive_request
* * * * std::vector< Number > ThermoPlasticMaterial< dim, ViscoplasticYieldLaw, Number >::get_state_parameters const
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
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 run(const std::vector< std::vector< Iterator > > &colored_iterators, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length=2 *MultithreadInfo::n_threads(), const unsigned int chunk_size=8)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
constexpr types::global_dof_index invalid_dof_index
::VectorizedArray< Number, width > tan(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
constexpr SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
constexpr Number trace(const SymmetricTensor< 2, dim2, Number > &)
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)