This program was contributed by Salvador Flores <sflores@dim.uchile.cl>.
It comes without any warranty or support by its authors or the authors of deal.II.
This program is part of the deal.II code gallery and consists of the following files (click to inspect):
Annotated version of ElastoplasticTorsion.cc
/ * ---------------------------------------------------------------------
*
* Copyright (C) 2010 - 2015 by the deal.II authors
* and Salvador Flores.
*
*
*
* This is
free software; you can use it, redistribute
* it, and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* The full text of the license can be found in the file LICENSE at
* the top level of the deal.II distribution.
*
* ---------------------------------------------------------------------
*
* Author: Salvador Flores,
* Center for Mathematical Modelling,
* Universidad de Chile, 2015.
* /
/ *
This piece of software solves the elliptic p-laplacian
boundary-value problems:
Min {∫ 1/2 W(|Du|²)+ 1/p |Du|^p -fu : u=g on ∂S } (1)
u
for large values of p, which approximates (see Alvarez & Flores 2015)
Min {∫ 1/2 W(|Du|²) -fu : |Du|<1 a.s. on S, u=g on ∂S }
u
By default W(t)=t and S=unit disk.
Large portions of this code are borrowed from the deal.ii tutorials
@ref step_15 "step-15" @ref step_29 "step-29".
For further details see the technical report
"Solving variational problems with uniform gradient bounds by p-Laplacian
approximation: Elastoplastic torsion implementation using the deal.II
library"
available at the documentation and at http:
* /
Include files
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/function.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/utilities.h>
#include <deal.II/base/convergence_table.h>
#include <deal.II/base/smartpointer.h>
#include <deal.II/base/parameter_handler.h>
#include <deal.II/base/timer.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/sparse_matrix.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/precondition.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/lac/dynamic_sparsity_pattern.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/manifold_lib.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/grid/grid_in.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/dofs/dof_renumbering.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/error_estimator.h>
#include <deal.II/numerics/solution_transfer.h>
#include <typeinfo>
#include <fstream>
#include <iostream>
#include <deal.II/numerics/solution_transfer.h>
Open a namespace for this program and import everything from the dealii namespace into it.
******************************************************** //
{
public:
void read_parameters(const std::string);
private:
void declare_parameters();
};
Constructor
prm(paramhandler)
{}
void ParameterReader::declare_parameters()
{
{
"Penalization parameter");
"Whether the exact solution is known");
}
{
"Number identifying the domain in which we solve the problem");
"Number of global mesh refinement steps applied to initial coarse grid");
"Number of global adaptive mesh refinements");
"refinement threshold");
"coarsening threshold");
}
{
"0: Preconditioned descent, 1: Newton Method");
"Initial p");
"increase of p");
"Maximum Number of CG iterations");
"Tolerance for CG iterations");
"Maximum Number of LS iterations");
"line search tolerance constant (c1 in Nocedal-Wright)");
"initial step length in line-search");
"Maximum Number of inner iterations");
"Threshold on norm of the derivative to declare optimality achieved");
"Threshold on norm of the derivative to declare optimality achieved in highly refined mesh");
"Number of adaptive refinement before change convergence threshold");
}
}
void ParameterReader::read_parameters (const std::string parameter_file)
{
declare_parameters();
}
****************************************************************************************** // The solution of the elastoplastic torsion problem on the unit disk with rhs=4.
template <int dim>
{
public:
virtual double value (
const Point<dim> &pto,
const unsigned int component = 0)
const;
};
template <int dim>
double Solution<dim>::value (
const Point<dim> &pto,
const unsigned int)
const {
if (r<0.5)
return -1.0*std::pow(r,2.0)+0.75;
else
return 1.0-r;
}
template <int dim>
{
if (r<0.5)
return -2.0*pto;
else
return -1.0*pto/r;
}
****************************************************************************************** //
/ * Compute the Lagrange multiplier (as a derived quantity) * /
template <int dim>
{
private:
double p;
public:
ComputeMultiplier (double pe);
virtual
void compute_derived_quantities_scalar (
const std::vector< double > &,
) const;
virtual std::vector<std::string>
get_names ()
const;
virtual
std::vector<DataComponentInterpretation::DataComponentInterpretation>
};
template <int dim>
ComputeMultiplier<dim>::ComputeMultiplier (double pe): p(pe)
{}
template <int dim>
void ComputeMultiplier<dim>::compute_derived_quantities_scalar(
const std::vector< double > & / *uh* /,
const std::vector<
Point< dim > > & / *evaluation_points* /,
{
const unsigned int n_quadrature_points = duh.size();
for (unsigned int q=0; q<n_quadrature_points; ++q)
{
long double sqrGrad=duh[q]* duh[q];
long double exponent=(p-2.0)/2*std::log(sqrGrad);
computed_quantities[q](0) = std::sqrt(sqrGrad);
computed_quantities[q](1)= std::exp(exponent);
}
}
template <int dim>
std::vector<std::string>
ComputeMultiplier<dim>::get_names() const
{
std::vector<std::string> solution_names;
solution_names.push_back ("Gradient norm");
solution_names.push_back ("Lagrange multiplier");
return solution_names;
}
template <int dim>
ComputeMultiplier<dim>::get_needed_update_flags () const
{
}
template <int dim>
std::vector<DataComponentInterpretation::DataComponentInterpretation>
ComputeMultiplier<dim>:: get_data_component_interpretation () const
{
std::vector<DataComponentInterpretation::DataComponentInterpretation>
interpretation;
norm of the gradient
Lagrange multiplier
*************************************************************************************** //
template <int dim>
class ElastoplasticTorsion
{
public:
~ElastoplasticTorsion ();
private:
void setup_system (const bool initial_step);
void assemble_system ();
bool solve (const int inner_it);
void init_mesh ();
void refine_mesh ();
void set_boundary_values ();
double phi (const double alpha) const;
bool checkWolfe(double &alpha, double &phi_alpha) const;
bool determine_step_length (const int inner_it);
void print_it_message (const int counter, bool ks);
void output_results (unsigned int refinement) const;
void format_convergence_tables();
void process_solution (const unsigned int cycle);
void process_multiplier (const unsigned int cycle,const int iter,double time);
double dual_error () const;
double dual_infty_error () const;
double W (double Du2) const;
double Wp (double Du2) const;
double G (double Du2) const;
double step_length,phi_zero,phi_alpha,phip,phip_zero;
double old_step,old_phi_zero,old_phip;
double L2_error;
double H1_error;
double Linfty_error;
double dual_L1_error;
double dual_L_infty_error;
double p;
double line_search_tolerence;
unsigned int dir_id;
std::string elements;
std::string Method;
};
/ ******************************************************************************************* /
Boundary condition
template <int dim>
class BoundaryValues :
public Function<dim>
{
public:
const unsigned int component = 0) const;
};
template <int dim>
double BoundaryValues<dim>::value (
const Point<dim> &/ *pto* /,
const unsigned int / *component* /) const
{
could be anything else (theory works provided |Dg|_infty < 1/2)
return 0.0;
/ * A challenging BC leading to overdetermined problems
it is regulated by the parameter 0<eta<1.
eta closer to 1 leads to more difficult problems.
double theta=std::atan2(p[1],p[0])+pii;
double eta=0.9;
if (theta <= 0.5)
return eta*(theta*theta);
else if ((theta >0.5) & (theta<= pii-0.5))
return eta*(theta-0.25);
else if ((theta>pii-0.5)&(theta<= pii+0.5))
return eta*(pii-0.75-(theta-(pii-0.5))*(theta-(pii+0.5)));
else if ((theta>pii+0.5)&(theta<= 2*pii-0.5))
return eta*((2*pii-theta)-0.25);
else
return eta*((theta-2*pii)*(theta-2*pii) );* /
}
/ ****************************************************************************** /
Right-Hand Side
template <int dim>
class RightHandSide :
public Function<dim>
{
public:
const unsigned int component = 0) const;
};
template <int dim>
double RightHandSide<dim>::value (
const Point<dim> &/ *p* /,
const unsigned int / *component* /) const
{
set to constant = 4, for which explicit solution to compare exists could be anything
double return_value = 4.0;
return return_value;
}
/ ******************************************************************* /
The ElastoplasticTorsion class implementation
Constructor of the class
template <int dim>
prm(param),
dof_handler (triangulation),
L2_error(1.0),
H1_error(1.0),
Linfty_error(1.0),
dual_L1_error(1.0),
dual_L_infty_error(1.0),
fe(2)
{
line_search_tolerence=prm.
get_double(
"line_search_tolerence");
elements="P1";
else elements="P2";
if (dir_id==0)
Method="Precond";
else
Method="Newton";
}
template <int dim>
ElastoplasticTorsion<dim>::~ElastoplasticTorsion ()
{
}
/ ***************************************************************************************** /
print iteration message
template <int dim>
void ElastoplasticTorsion<dim>::print_it_message (const int counter, bool ks)
{
if (ks)
{
process_solution (counter);
std::cout << "iteration="<< counter+1 << " J(u_h)= "<< phi_zero << ", H1 error: "
<< H1_error <<", W0-1,infty error: "<< Linfty_error<< " J'(u_h)(w)= "<< phip
<<
", |J'(u_h)|= "<< system_rhs.
l2_norm()<<std::endl;
}
else
{
std::cout << "iteration= " << counter+1 << " J(u_h)= "
<< phi_alpha << " J'(u_h)= "<< phip<<std::endl;
}
}
/ ***************************************************************************************** /
Convergence Tables
/ ************************************************************* /
formating
template <int dim>
void ElastoplasticTorsion<dim>::format_convergence_tables()
{
convergence_table.set_precision("L2", 3);
convergence_table.set_precision("H1", 3);
convergence_table.set_precision("Linfty", 3);
convergence_table.set_precision("function value", 3);
convergence_table.set_precision("derivative", 3);
dual_convergence_table.set_precision("dual_L1", 3);
dual_convergence_table.set_precision("dual_Linfty", 3);
dual_convergence_table.set_precision("L2", 3);
dual_convergence_table.set_precision("H1", 3);
dual_convergence_table.set_precision("Linfty", 3);
convergence_table.set_scientific("L2", true);
convergence_table.set_scientific("H1", true);
convergence_table.set_scientific("Linfty", true);
convergence_table.set_scientific("function value", true);
convergence_table.set_scientific("derivative", true);
dual_convergence_table.set_scientific("dual_L1", true);
dual_convergence_table.set_scientific("dual_Linfty", true);
dual_convergence_table.set_scientific("L2", true);
dual_convergence_table.set_scientific("H1", true);
dual_convergence_table.set_scientific("Linfty", true);
}
/ **************************************** /
fill-in entry for the solution
template <int dim>
void ElastoplasticTorsion<dim>::process_solution (const unsigned int it)
{
Vector<float> difference_per_cell (triangulation.n_active_cells());
compute L2 error (save to difference_per_cell)
L2_error = difference_per_cell.l2_norm();
compute H1 error (save to difference_per_cell)
H1_error = difference_per_cell.l2_norm();
compute W1infty error (save to difference_per_cell)
Linfty_error = difference_per_cell.linfty_norm();
convergence_table.add_value("cycle", it);
convergence_table.add_value("p", p);
convergence_table.add_value("L2", L2_error);
convergence_table.add_value("H1", H1_error);
convergence_table.add_value("Linfty", Linfty_error);
convergence_table.add_value("function value", phi_alpha);
convergence_table.add_value("derivative", phip);
}
/ *************************************** /
fill-in entry for the multiplier
template <int dim>
void ElastoplasticTorsion<dim>::process_multiplier (const unsigned int cycle, const int iter,double time)
{
const unsigned int n_active_cells=triangulation.n_active_cells();
const unsigned int n_dofs=dof_handler.
n_dofs();
dual_L1_error=dual_error();
dual_L_infty_error=dual_infty_error();
dual_convergence_table.add_value("cycle", cycle);
dual_convergence_table.add_value("p", p);
dual_convergence_table.add_value("iteration_number", iter);
dual_convergence_table.add_value("cpu_time", time);
dual_convergence_table.add_value("cells", n_active_cells);
dual_convergence_table.add_value("dofs", n_dofs);
dual_convergence_table.add_value("L2", L2_error);
dual_convergence_table.add_value("H1", H1_error);
dual_convergence_table.add_value("Linfty", Linfty_error);
dual_convergence_table.add_value("dual_L1", dual_L1_error);
dual_convergence_table.add_value("dual_Linfty", dual_L_infty_error);
}
/ **************************************************************************************** /
ElastoplasticTorsion::setup_system unchanged from step-15
template <int dim>
void ElastoplasticTorsion<dim>::setup_system (const bool initial_step)
{
if (initial_step)
{
present_solution.reinit (dof_handler.
n_dofs());
grad_norm.reinit (dof_handler.
n_dofs());
lambda.reinit (dof_handler.
n_dofs());
hanging_node_constraints.clear ();
hanging_node_constraints);
hanging_node_constraints.close ();
}
The remaining parts of the function
hanging_node_constraints.condense (c_sparsity);
system_matrix.reinit (sparsity_pattern);
}
/ *************************************************************************************** /
/ * the coeffcients W, W' and G defining the problem.
Min_u \int W(|Du|^2) dx
They must be consistent as G(s)=W'(s)+2s W''(s) for any s>0.
recall that they receive the SQUARED gradient. * /
template <int dim>
double ElastoplasticTorsion<dim>::W (double Du2) const
{
return Du2;
}
template <int dim>
double ElastoplasticTorsion<dim>::Wp (double / *Du2* /) const
{
return 1.0;
}
template <int dim>
double ElastoplasticTorsion<dim>::G (double / *Du2* /) const
{
return 1.0;
}
/ *************************************************************************************** /
template <int dim>
void ElastoplasticTorsion<dim>::assemble_system ()
{
const RightHandSide<dim> right_hand_side;
system_matrix = 0;
system_rhs = 0;
const unsigned int n_q_points = quadrature_formula.
size();
std::vector<Tensor<1, dim> > old_solution_gradients(n_q_points);
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
endc = dof_handler.
end();
for (; cell!=endc; ++cell)
{
cell_rhs = 0;
old_solution_gradients);
for (unsigned int q_point = 0; q_point < n_q_points; ++q_point)
{
long double coeff=0.0;
long double a=old_solution_gradients[q_point] * old_solution_gradients[q_point];
long double exponent=(p-2.0)/2*std::log(a);
coeff= std::exp( exponent);
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
{
if (dir_id==1)
{
* (G(a)+(p-1.0)*coeff) * fe_values.
JxW(q_point);
}
else
{
* (Wp(a)+coeff)
* fe_values.
JxW(q_point);
}
}
* old_solution_gradients[q_point]
* (Wp(a)+coeff)
)
* fe_values.
JxW(q_point);
}
}
cell->get_dof_indices (local_dof_indices);
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
system_matrix.add (local_dof_indices[i],
local_dof_indices[j],
system_rhs(local_dof_indices[i]) += cell_rhs(i);
}
}
hanging_node_constraints.condense (system_matrix);
hanging_node_constraints.condense (system_rhs);
std::map<types::global_dof_index,double> boundary_values;
0,
boundary_values);
system_matrix,
newton_update,
system_rhs);
}
/ ********************************** Refine Mesh **************************************** /
unchanged from step-15
template <int dim>
void ElastoplasticTorsion<dim>::refine_mesh ()
{
Vector<float> estimated_error_per_cell (triangulation.n_active_cells());
present_solution,
estimated_error_per_cell);
const double top_fraction=prm.
get_double(
"top_fraction_of_cells");
const double bottom_fraction=prm.
get_double(
"bottom_fraction_of_cells");
estimated_error_per_cell,
top_fraction, bottom_fraction);
triangulation.prepare_coarsening_and_refinement ();
solution_transfer.prepare_for_coarsening_and_refinement(present_solution);
triangulation.execute_coarsening_and_refinement();
solution_transfer.interpolate(present_solution, tmp);
present_solution = tmp;
set_boundary_values ();
hanging_node_constraints.clear();
hanging_node_constraints);
hanging_node_constraints.close();
hanging_node_constraints.distribute (present_solution);
setup_system (false);
}
/ ******************************************************************************************* /
Dump the norm of the gradient and the lagrange multiplier in vtu format for visualization
template <int dim>
void ElastoplasticTorsion<dim>::output_results (unsigned int counter) const
{
multiplier object contains both |Du| and lambda.
ComputeMultiplier<dim> multiplier(p);
std::ostringstream p_str;
p_str << p<<"-cycle-"<<counter;
std::string str = p_str.str();
const std::string filename = "solution-" + str+".vtu";
std::ofstream output (filename.c_str());
}
/ ******************************************************************************************** /
unchanged from step-15
template <int dim>
void ElastoplasticTorsion<dim>::set_boundary_values ()
{
std::map<types::global_dof_index, double> boundary_values;
0,
BoundaryValues<dim>(),
boundary_values);
for (std::map<types::global_dof_index, double>::const_iterator
bp = boundary_values.begin();
bp != boundary_values.end(); ++bp)
present_solution(bp->first) = bp->second;
}
/ **************************************************************************************** /
COMPUTE ()=J_p(u_h+ w)
template <int dim>
double ElastoplasticTorsion<dim>::phi (const double alpha) const
{
double obj = 0.0;
const RightHandSide<dim> right_hand_side;
evaluation_point = present_solution;
evaluation_point.
add (alpha, newton_update);
const unsigned int n_q_points = quadrature_formula.
size();
std::vector<Tensor<1, dim> > gradients(n_q_points);
std::vector<double> values(n_q_points);
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
endc = dof_handler.
end();
for (; cell!=endc; ++cell)
{
for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
{
double Du2=gradients[q_point] * gradients[q_point];
double penalty;
if (Du2<1.0e-10)
penalty=0.0;
else
penalty=std::pow(Du2,p/2.0);
obj+= 1/2 W(|Du|^2)+1/p |Du|^p -fu (see (1))
obj+=(
(0.5*W(Du2)+penalty/p)- right_hand_side.value(fe_values.
quadrature_point(q_point))*values[q_point]
) * fe_values.
JxW(q_point);
}
}
return obj;
}
/ *************************************************************************************************** /
Compute L^1 error norm of Lagrange Multiplier with respect to exact solution (cf. Alvarez & Flores, 2015)
template <int dim>
double ElastoplasticTorsion<dim>::dual_error () const
{
double obj = 0.0;
const unsigned int n_q_points = quadrature_formula.
size();
std::vector<Tensor<1, dim> > gradients(n_q_points);
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
endc = dof_handler.
end();
for (; cell!=endc; ++cell)
{
for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
{
double coeff=gradients[q_point] * gradients[q_point] ;
if (coeff<1.0e-15)
coeff=0.0;
else
coeff=std::pow(coeff,(p-2.0)/2.0);
double exact=0;
if (r>0.5)
exact= 2*r-1;
obj+=( std::abs(coeff-exact) ) * fe_values.
JxW(q_point);
}
}
return obj;
}
/ ******************************************************************************************* /
Compute L^infinity error norm of Lagrange Multiplier with respect to exact solution (cf. Alvarez & Flores, 2015)
template <int dim>
double ElastoplasticTorsion<dim>::dual_infty_error () const
{
double obj = 0.0;
const unsigned int n_q_points = quadrature_formula.
size();
std::vector<Tensor<1, dim> > gradients(n_q_points);
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
endc = dof_handler.
end();
for (; cell!=endc; ++cell)
{
for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
{
long double sqdGrad=gradients[q_point] * gradients[q_point] ;
double exact=0;
if (r>0.5)
exact= 2*r-1.0;
compute |Du|^(p-2) as exp(p-2/2*log(Du^2))
long double exponent=(p-2.0)/2*std::log(sqdGrad);
long double coeff=std::exp(exponent);
if (std::abs(coeff-exact)>obj )
obj=std::abs(coeff-exact);
}
}
return obj;
}
/ ***************************************************************************************** /
check whether putative step-length satisfies sufficient decrease conditions
template <int dim>
bool ElastoplasticTorsion<dim>::checkWolfe(double &alpha, double &phi_alpha) const
{
if (phi_alpha< phi_zero+line_search_tolerence*phip*alpha )
return true;
else
return false;
}
/ ***************************************************************************************** /
Find a step-length satisfying sufficient decrease condition by line-search uses quadratic interpolation
template <int dim>
bool ElastoplasticTorsion<dim>::determine_step_length(const int inner_it)
{
unsigned int it=0;
bool done;
double alpha,nalpha;
const unsigned int max_LS_it=prm.
get_integer(
"max_LS_it");
double init_SL=prm.
get_double(
"init_step_length");
if (inner_it==0)
alpha=init_SL;
else
{
alpha=std::min(1.45*old_step*old_phip/phip,1.0);
}
phi_alpha=phi(alpha);
std::cerr << "Step length=" << alpha << ", Value= " << phi_alpha;
check if step-size satisfies sufficient decrease condition
done=checkWolfe(alpha,phi_alpha);
if (done)
std::cerr << " accepted" << std::endl;
else
std::cerr << " rejected" ;
while ((!done) & (it<max_LS_it))
{
new try obtained by quadratic interpolation
nalpha=-(phip*alpha*alpha)/(2*(phi_alpha-phi_zero-phip*alpha));
if (nalpha<1e-3*alpha || std::abs(nalpha-alpha)/alpha<1
e-8)
nalpha=alpha/2;
else if ( phi_alpha-phi_zero>1e3*std::abs(phi_zero) )
nalpha=alpha/10;
alpha=nalpha;
phi_alpha=phi(alpha);
done=checkWolfe(alpha,phi_alpha);
if (done)
std::cerr << ", finished with steplength= "<< alpha<< ", fcn value= "<< phi_alpha<<std::endl;
it=it+1;
}
if (!done)
{
std::cerr << ", max. no. of iterations reached wiht steplength= "<< alpha
<< ", fcn value= "<< phi_alpha<<std::endl;
return false;
}
else
{
step_length=alpha;
return true;
}
}
/ ************************************************************************************************** /
ElastoplasticTorsion::init_mesh()
template <int dim>
void ElastoplasticTorsion<dim>::init_mesh ()
{
get parameters
const int domain_id=prm.
get_integer(
"Code for the domain");
const int init_ref=prm.
get_integer(
"No of initial refinements");
if (domain_id==0)
{
For the unit disk around the origin
triangulation.set_manifold (0, boundary);
}
else if (domain_id==1)
{
For the unit square
}
else if (domain_id==2)
{
/ * For Glowinski's domain
___ ___ __ 1
| |__| | __ .8
| |
| |
|__________| __ 0
| | | |
0 .4 .6 1
* /
Triangulation<dim> tria1;
Triangulation<dim> tria2;
Triangulation<dim> tria3;
Triangulation<dim> tria4;
Triangulation<dim> tria5;
Triangulation<dim> tria6;
GridGenerator::hyper_rectangle(tria1, Point<2>(0.0,0.0), Point<2>(0.4,0.8));
GridGenerator::hyper_rectangle(tria2, Point<2>(0.0,0.8), Point<2>(0.4,1.0));
GridGenerator::hyper_rectangle(tria3, Point<2>(0.4,0.0), Point<2>(0.6,0.8));
GridGenerator::hyper_rectangle(tria4, Point<2>(0.6,0.0), Point<2>(1.0,0.8));
GridGenerator::hyper_rectangle(tria5, Point<2>(0.6,0.8), Point<2>(1.0,1.0));
GridGenerator::merge_triangulations (tria1, tria2, tria6);
GridGenerator::merge_triangulations (tria6, tria3, tria6);
GridGenerator::merge_triangulations (tria6, tria4, tria6);
GridGenerator::merge_triangulations (tria6, tria5, triangulation);
}
perform initial refinements
triangulation.refine_global(init_ref);
}
/ ************************************************************************************************** /
ElastoplasticTorsion::solve(inner_it) Performs one inner iteration
template <int dim>
bool ElastoplasticTorsion<dim>::solve (const int inner_it)
{
const unsigned int max_CG_it=prm.
get_integer(
"Max_CG_it");
solver.solve (system_matrix, newton_update, system_rhs,
preconditioner);
hanging_node_constraints.distribute (newton_update);
/ ****** save current quantities for line-search **** * /
Recall that phi(alpha)=J(u+alpha w)
old_step=step_length;
old_phi_zero=phi_zero;
phi_zero=phi(0);
old_phip=phip;
phip=-1.0*(newton_update*system_rhs);
if (inner_it==0)
phip_zero=phip;
if (phip>0)
{
std::cout << "Not a descent direction!" <<std::endl;
present_solution.add (-1.0*step_length, newton_update);
step_length=step_length/2;
phip=old_phip;
return false;
}
else
{
if (determine_step_length(inner_it))
{
update u_{n+1}=u_n+alpha w_n
present_solution.add (step_length, newton_update);
return true;
}
else return false;
}
}
/ ************************************************************************************************************* /
ElastoplasticTorsion::run
template <int dim>
void ElastoplasticTorsion<dim>::run ()
{
get parameters
const int adapt_ref=prm.
get_integer(
"No of adaptive refinements");
bool known_solution=prm.
get_bool(
"known_solution");
/ ************************ /
init Timer
initalize mesh for the selected domain
setup FE space
setup_system (true);
set_boundary_values ();
init counters
int global_it=0;
int cycle=0;
int refinement = 0;
prepare to start first loop
p=init_p;
bool well_solved=true;
/ ***************************** First
loop *********************************** /
/ ****************** Prepare
initial condition
using increasing p ************************* /
while (p<actual_p)
{
std::cout <<"--Preparing initial condition with p="<<p<<" iter.= " << global_it<< " .-- "<< std::endl;
for (int inner_iteration=0; inner_iteration<max_inner; ++inner_iteration,++global_it)
{
assemble_system ();
well_solved=solve (inner_iteration);
print_it_message (global_it, known_solution);
if (
((system_rhs.
l2_norm()/std::sqrt(system_rhs.
size()) <1e-4) & (cycle<1)) |
((system_rhs.
l2_norm()/std::sqrt(system_rhs.
size()) <1e-5) & (cycle>=1)) |
!well_solved
)
break;
}
if (well_solved)
output_results (cycle);
if (known_solution)
{
process_multiplier(cycle,global_it,ptime);
dual_convergence_table.write_tex(dual_error_table_file);
}
refine_mesh();
cycle++;
p+=delta_p;
}
/ *************************** first
loop finished ******************** /
prepare for second loop
p=actual_p;
well_solved=true;
/ ***************************** Second
loop ********************************* /
/ **************************** Solve problem for target p ********************************* /
std::cout << "============ Solving problem with p=" <<p << " ==================" << std::endl;
/ ***** Outer iteration - refining mesh ****************** /
while ((cycle<adapt_ref) & well_solved)
{
inner iteration
for (int inner_iteration=0; inner_iteration<max_inner; ++inner_iteration,++global_it)
{
assemble_system ();
well_solved=solve (inner_iteration);
print_it_message (global_it, known_solution);
if (
((system_rhs.
l2_norm()/std::sqrt(system_rhs.
size()) < eps) & (refinement<hi_th)) |
(( system_rhs.
l2_norm()/ std::sqrt (system_rhs.
size()) <hi_eps) | (!well_solved))
)
break;
}
inner iterations finished
if (well_solved)
output_results (cycle);
compute and display error, if the explicit solution is known
if (known_solution)
{
process_multiplier(cycle,global_it,ptime);
std::cout << "finished with H1 error: " << H1_error << ", dual error (L1): "
<< dual_L1_error << "dual error (L infty): "<<dual_L_infty_error <<std::endl;
}
update counters
refine mesh
std::cout << "******** Refined mesh " << cycle << " ********" << std::endl;
refine_mesh();
}
write convergence tables to file
if (known_solution)
{
format_convergence_tables();
std::string error_filename = "error"+Method+elements+".tex";
std::ofstream error_table_file(error_filename.c_str());
std::string dual_error_filename = "dual_error"+Method+elements+".tex";
std::ofstream dual_error_table_file(dual_error_filename.c_str());
convergence_table.write_tex(error_table_file);
dual_convergence_table.write_tex(dual_error_table_file);
}
}
}
/ ********************************************************************************************** /
The main function
int main ()
{
try
{
using namespace nsp;
ParameterReader param(prm);
param.read_parameters("EPT.prm");
ElastoplasticTorsion<2> ElastoplasticTorsionProblem(prm);
ElastoplasticTorsionProblem .run ();
}
catch (std::exception &exc)
{
std::cerr << std::endl << std::endl
<< "----------------------------------------------------" << std::endl;
std::cerr << "Exception on processing: " << std::endl
<< exc.what() << std::endl
<< "Aborting!" << std::endl
<< "----------------------------------------------------"
<< std::endl;
return 1;
}
catch (...)
{
std::cerr << std::endl << std::endl
<< "----------------------------------------------------"
<< std::endl;
std::cerr << "Unknown exception!" << std::endl
<< "Aborting!" << std::endl
<< "----------------------------------------------------"
<< std::endl;
return 1;
}
return 0;
}