68int main(
int argc,
char *argv[])
71 cout <<
"Contact miniapp is not supported in single precision.\n\n";
72 return MFEM_SKIP_RETURN_VALUE;
88 bool visualization =
true;
90 bool paraview =
false;
98 bool nonlinear =
false;
100 real_t tribol_ratio = 8.0;
106 const char *amgf_fsolver =
"auto";
111 args.
AddOption(&prob_no,
"-prob",
"--problem-number",
113 "0: two-block problem"
115 "2: beam-sphere problem");
116 args.
AddOption(&nonlinear,
"-nonlin",
"--nonlinear",
"-lin",
117 "--linear",
"Choice between linear and non-linear Elasticiy model.");
118 args.
AddOption(&sref,
"-sr",
"--serial-refinements",
119 "Number of uniform refinements.");
120 args.
AddOption(&nsteps,
"-nsteps",
"--nsteps",
122 args.
AddOption(&msteps,
"-msteps",
"--msteps",
123 "Number of extra steps.");
124 args.
AddOption(&pref,
"-pr",
"--parallel-refinements",
125 "Number of uniform refinements.");
126 args.
AddOption(&amgf,
"-amgf",
"--amgf",
"-no-amgf",
127 "--no-amgf",
"Enable or disable AMG with Filtering solver.");
128 args.
AddOption(&amgf_fsolver,
"-amgf-fsolver",
"--amgf-filtered-solver",
129 "Direct solver for AMGF filtered subspace.\n"
130 "Choices: auto, mumps, cpardiso, superlu, strumpack.");
131 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
132 "--no-visualization",
133 "Enable or disable GLVis visualization.");
134 args.
AddOption(¶view,
"-paraview",
"--paraview",
"-no-paraview",
136 "Enable or disable ParaView visualization.");
137 args.
AddOption(&tribol_ratio,
"-tr",
"--tribol-proximity-parameter",
138 "Tribol-proximity-parameter.");
155 MFEM_VERIFY(prob_no >= 0 &&
156 prob_no <= 2,
"Unknown test problem number: " << prob_no);
165 cout <<
"Non-linear elasticity not supported for the two-block and ironing problems"
167 cout <<
"Switching to the linear model ..." << endl;
174 bool bound_constraints = (nonlinear) ?
true :
false;
181 for (
int i = 0; i<sref; i++)
187 ParMesh pmesh(MPI_COMM_WORLD,*mesh);
189 for (
int i = 0; i<pref; i++)
211 E[0] = 1.0; E[1] = 1e3;
212 nu[0] = 0.499; nu[1] = 0.0;
223 MFEM_ABORT(
"Should be unreachable");
236 mfem::out <<
"\n --------------------------------------" << endl;
237 mfem::out <<
" Global number of dofs = " << gndofs << endl;
238 mfem::out <<
" --------------------------------------" << endl;
242 std::set<int> mortar_attr;
243 std::set<int> nonmortar_attr;
248 mortar_attr.insert(3);
249 nonmortar_attr.insert(4);
252 mortar_attr.insert(6);
253 mortar_attr.insert(9);
254 nonmortar_attr.insert(7);
255 nonmortar_attr.insert(8);
258 MFEM_ABORT(
"Should be unreachable");
272 std::ostringstream paraview_file_name;
273 paraview_file_name <<
"contact-problem_" << prob_no
274 <<
"_par_ref_" << pref
275 <<
"_ser_ref_" << sref
276 <<
"_nonlinear_" << nonlinear;
295 sol_sock.precision(8);
313 tribol_ratio, bound_constraints);
316 Vector ess_values(
dim); ess_values = 0.0;
324 int total_steps = nsteps + msteps;
325 for (
int i = 0; i<total_steps; i++)
329 std::ostringstream oss;
330 oss <<
"\n Solving optimization problem for time step: " << i;
332 mfem::out <<
" " <<std::string(oss.str().size()-2,
'-') << endl;
342 ess_bdr = 0; ess_bdr[5] = 1;
346 ess_values[2] = -1.0/1.4*(i+1)/nsteps;
350 ess_values[0] = 3.0/1.4*(i+1-nsteps)/msteps;
351 ess_values[2] = -1.0/1.4;
353 prob.SetDisplacementDirichletData(ess_values, ess_bdr);
358 ess_bdr = 0; ess_bdr[2] = 1;
360 f.constant = -
p*(i+1)/nsteps;
361 prob.SetNeumanPressureData(
f,ess_bdr);
364 MFEM_ABORT(
"Should be unreachable");
369 prob.FormLinearSystem();
380 int activation_step = 2;
381 if (bound_constraints && i>activation_step)
389#if MFEM_HYPRE_VERSION >= 23000
391 int amg_relax_type = 88;
399 auto * amgfprec =
dynamic_cast<AMGFSolver *
>(prec);
401 amgfprec->GetAMG().SetPrintLevel(0);
402 amgfprec->GetAMG().SetRelaxType(amg_relax_type);
405 amgfprec->SetFilteredSubspaceSolver(*subspacesolver);
406 amgfprec->SetFilteredSubspaceTransferOperator(
414 amgprec->SetPrintLevel(0);
415 amgprec->SetRelaxType(amg_relax_type);
434 int ndofs =
prob.GetFESpace()->GetTrueVSize();
435 Vector x0(ndofs); x0 = 0.0;
439 Vector xf(ndofs); xf = 0.0;
440 optimizer.
Mult(x0, xf);
443 if (subspacesolver) {
delete subspacesolver; }
447 if (bound_constraints)
454 real_t Einitial = contact.
E(x0, eval_err);
455 real_t Efinal = contact.
E(xf, eval_err);
460 mfem::out <<
" Initial Energy objective = " << Einitial << endl;
461 mfem::out <<
" Final Energy objective = " << Efinal << endl;
462 mfem::out <<
" Optimizer number of iterations = " <<
464 mfem::out <<
" PCG number of iterations = " ;
465 for (
int i = 0; i < PCGiterations.
Size(); ++i)
467 std::cout << PCGiterations[i] <<
" ";
474 add(ref_coords,x_gf,new_coords);
487 sol_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n"
488 <<
"solution\n" << pmesh_copy << x_gf << flush;
490 if (i == total_steps - 1)
496 sol_sock_final <<
"parallel " << num_procs <<
" " << myid <<
"\n";
497 sol_sock_final.precision(8);
498 sol_sock_final <<
"solution\n" << pmesh << x_gf << flush;
503 if (i == total_steps-1) {
break; }
508 if (paraview_dc) {
delete paraview_dc; }
517 return new Mesh(
"meshes/beam-sphere.mesh",1);
521 Mesh * combined_mesh =
nullptr;
522 constexpr real_t scale = 9.0/3.6;
523 constexpr real_t lx0 = 3.6*scale, ly0 = 1.6*scale, lz0 = 1.0*scale;
524 constexpr int nx0 = 24, ny0 = 12, nz0 = 6;
529 for (
int i = 0; i<mesh0.
GetNBE(); i++)
535 case 1: new_battr = 2;
break;
536 case 6: new_battr = 3;
break;
537 default: new_battr = 1;
break;
544 constexpr real_t lx = 1.0, ly = 1.0, lz = 1.0;
545 constexpr int nx = 5, ny = 5, nz = 5;
553 for (
int i = 0; i<mesh.
GetNBE(); i++)
559 case 1: new_battr = 4;
break;
560 case 6: new_battr = 6;
break;
561 default: new_battr = 5;
break;
568 shift(0) = (ly0-ly)/3;
569 shift(1) = (ly0-ly)/2;
581 Mesh *mesh_array2[] = {&mesh, &mesh0};
582 combined_mesh =
new Mesh(mesh_array2, 2);
588 constexpr real_t lx = 1.6*scale, ly = 2.0*scale, lz = 0.2*scale;
589 constexpr int nx = 16, ny = 20, nz = 2;
597 for (
int i = 0; i<mesh.
GetNBE(); i++)
603 case 1: new_battr = 6;
break;
604 case 6: new_battr = 4;
break;
605 default: new_battr = 5;
break;
611 constexpr real_t theta_arc = M_PI/2;
612 constexpr real_t rin = lx / theta_arc - lz;
613 constexpr real_t rout = lx / theta_arc + lz;
615 constexpr real_t xshift = lx0/4;
616 constexpr real_t yshift = 0.5*(ly0-ly);
617 constexpr real_t zshift = rout + lz0;
621 const real_t theta = -((x(0) / lx + 0.5) * theta_arc);
622 const real_t r = rin + (x(2) + lz);
624 y(0) = xshift + r * std::cos(theta);
625 y(1) = yshift + x(1);
626 y(2) = zshift + r * std::sin(theta);
630 Mesh *mesh_array2[] = {&mesh, &mesh0};
631 combined_mesh =
new Mesh(mesh_array2, 2);
634 return combined_mesh;
AMG with Filtering: specialization of FilteredSolver.
HypreBoomerAMG & GetAMG()
Access to the internal HypreBoomerAMG instance.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Conjugate gradient method.
A coefficient that is constant across space and time.
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection.
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
void SetTime(real_t t)
Set physical time (for time-dependent simulations)
void SetPrefixPath(const std::string &prefix)
Set the path where the DataCollection will be saved.
Parallel finite element operator for linear and nonlinear elasticity.
void SetAttribute(const int attr)
Set element's attribute.
int GetAttribute() const
Return element's attribute.
void SetTrueVector()
Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
The BoomerAMG solver in hypre.
void SetSystemsOptions(int dim, bool order_bynodes=false)
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Class for interior-point solvers of contact-problems described by a OptContactProblem.
int GetNumIterations()
get number of interior-point iterations of most recent Mult call
void SetTol(real_t tol)
Set absolute tolerance.
void SetLinearSolver(Solver *solver_)
Set linear solver.
Array< int > & GetLinearSolverIterations()
Get solver iteration counts.
void SetPrintLevel(int print_level_)
Set print level.
void Mult(const Vector &, Vector &)
Apply the interior-point solver.
void SetMaxIter(int max_it)
Set maximum number of interior-point steps.
void SetRelTol(real_t rtol)
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
void SetMaxIter(int max_it)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
const Element * GetElement(int i) const
Return pointer to the i'th element object.
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
void Transform(std::function< void(const Vector &, Vector &)> f)
static Mesh MakeCartesian3D(int nx, int ny, int nz, Element::Type type, real_t sx=1.0, real_t sy=1.0, real_t sz=1.0, bool sfc_ordering=true)
Creates a mesh for the parallelepiped [0,sx]x[0,sy]x[0,sz], divided into nx*ny*nz hexahedra if type =...
virtual void SetAttributes(bool elem_attrs_changed=true, bool bdr_face_attrs_changed=true)
Determine the sets of unique attribute values in domain if elem_attrs_changed and boundary elements i...
void GetNodes(Vector &node_coord) const
int GetNBE() const
Returns number of boundary elements.
void MoveNodes(const Vector &displacements)
void SetNodes(const Vector &node_coord)
Updates the vertex/node locations. Invokes NodesUpdated().
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
void SetBdrAttribute(int i, int attr)
Set the attribute of boundary element i.
Array< int > attributes
A list of all unique element attributes used by the Mesh.
static bool Root()
Return true if the rank in MPI_COMM_WORLD is zero.
static int WorldRank()
Return the MPI rank in MPI_COMM_WORLD.
static int WorldSize()
Return the size of MPI_COMM_WORLD.
static void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void PrintUsage(std::ostream &out) const
Print the usage message.
void PrintOptions(std::ostream &out) const
Print the options.
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set 'var' to receive the value. Enable/disable tags are used to set the bool...
bool Good() const
Return true if the command line options were parsed successfully.
Abstract parallel finite element space.
HYPRE_BigInt GlobalTrueVSize() const
Class for parallel grid function.
HypreParVector * GetTrueDofs() const
Returns the true dofs in a new HypreParVector.
void SetFromTrueDofs(const Vector &tv) override
Set the GridFunction from the given true-dof vector.
Class for parallel meshes.
void SetLevelsOfDetail(int levels_of_detail_)
Set the refinement level.
void SetHighOrderOutput(bool high_order_output_)
Sets whether or not to output the data as high-order elements (false by default).
void SetDataFormat(VTKFormat fmt)
Set the data format for the ParaView output files.
Writer for ParaView visualization (PVD and VTU format)
Wrapper around parallel sparse direct solvers (MUMPS, SuperLU_DIST, STRUMPACK, CPARDISO).
virtual void SetPrintLevel(int print_lvl)
Vector & Set(const real_t a, const Vector &x)
(*this) = a * x
void SetSize(int s)
Resize the vector to size s.
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void add(const Vector &v1, const Vector &v2, Vector &v)
std::function< real_t(const Vector &)> f(real_t mass_coeff)
real_t p(const Vector &x, real_t t)