MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
contact.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12// MFEM Contact Miniapp
13
14// Compile with: make contact
15
16// Sample runs
17// Problem 0: two-block (linear elasticity)
18// mpirun -np 4 ./contact -prob 0 -sr 0 -pr 0 -tr 2 -nsteps 4 -msteps 0 -amgf -amgf-fsolver auto
19// mpirun -np 4 ./contact -prob 0 -sr 0 -pr 0 -tr 2 -nsteps 4 -msteps 0 -no-amgf
20
21// Problem 1: ironing (linear elasticity)
22// mpirun -np 4 ./contact -prob 1 -sr 0 -pr 0 -tr 2 -nsteps 4 -msteps 6 -amgf -amgf-fsolver auto
23// mpirun -np 4 ./contact -prob 1 -sr 0 -pr 0 -tr 2 -nsteps 4 -msteps 6 -no-amgf
24
25// Problem 2: beam–sphere (linear or non-linear elasticity)
26// mpirun -np 4 ./contact -prob 2 -sr 0 -pr 0 -tr 2 -nsteps 6 -msteps 0 -lin -amgf -amgf-fsolver auto
27// mpirun -np 4 ./contact -prob 2 -sr 0 -pr 0 -tr 2 -nsteps 6 -msteps 0 -lin -no-amgf
28// mpirun -np 4 ./contact -prob 2 -sr 0 -pr 0 -tr 2 -nsteps 6 -msteps 0 -nonlin -amgf -amgf-fsolver auto
29// mpirun -np 4 ./contact -prob 2 -sr 0 -pr 0 -tr 2 -nsteps 6 -msteps 0 -nonlin -no-amgf
30
31// Description:
32// This miniapp solves benchmark frictionless contact problems using a
33// self-contained Interior Point (IP) optimizer. Contact constraints
34// are supplied by Tribol. The linear systems inside the IP iterations
35// are solved with PCG, preconditioned by either standard HypreBoomerAMG
36// or AMG with Filtering (AMGF). AMGF enhances AMG by applying an additional
37// subspace-correction step on a small subspace associated with the contact interface.
38
39// Notes:
40// 1. Non-linear elasticity is supported only for -prob 2. If -nonlin is
41// requested for -prob 0/1, the app falls back to the linear model.
42// 2. The required meshes for -prob 0,1 are generated on the fly. For -prob 2,
43// the mesh is constructed from the file ./meshes/beam-sphere.mesh.
44// 3. AMGF requires a parallel direct solver for the filtered subspace; build
45// MFEM with MUMPS or MKL CPardiso. If unavailable, requesting -amgf aborts
46// with an error.
47// 4. This miniapp requires MFEM build with Tribol, an open source contact mechanics library
48// available at https://github.com/LLNL/Tribol.
49
50#include "mfem.hpp"
51#include <fstream>
52#include <iostream>
53#include "ip.hpp"
54#include "solver_utils.hpp"
55
56using namespace std;
57using namespace mfem;
58
65
67
68int main(int argc, char *argv[])
69{
70#ifdef MFEM_USE_SINGLE
71 cout << "Contact miniapp is not supported in single precision.\n\n";
72 return MFEM_SKIP_RETURN_VALUE;
73#endif
74 // 0. Initialize MPI and HYPRE.
75 Mpi::Init();
76 int myid = Mpi::WorldRank();
77 int num_procs = Mpi::WorldSize();
79
80 problem_name prob_name;
81
82 // 1. Command-line options.
83 // Number of serial uniform refinements
84 int sref = 1;
85 // Number of parallel uniform refinements
86 int pref = 0;
87 // Enable/disable GLVis visualization
88 bool visualization = true;
89 // Enable/disable ParaView output
90 bool paraview = false;
91 // Problem choice (0,1,2)
92 int prob_no = 0;
93 // number of times steps in the z-direction (problem 0)
94 int nsteps = 1;
95 // number of times steps in the x-direction (problem 1)
96 int msteps = 0;
97 // Use non-linear elasticity (only for problem 2)
98 bool nonlinear = false;
99 // Tribol search proximity ratio
100 real_t tribol_ratio = 8.0;
101 // Enable/disable AMGF preconditioner (default is AMG)
102 bool amgf = false;
103
104 // Direct solver for AMGF filtered subspace
105 // Choices:"auto", "mumps", "cpardiso", "superlu", "strumpack"
106 const char *amgf_fsolver = "auto";
107
108
109 // 1. Parse command-line options.
110 OptionsParser args(argc, argv);
111 args.AddOption(&prob_no, "-prob", "--problem-number",
112 "Choice of problem:"
113 "0: two-block problem"
114 "1: ironing 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",
121 "Number of steps.");
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(&paraview, "-paraview", "--paraview", "-no-paraview",
135 "--no-paraview",
136 "Enable or disable ParaView visualization.");
137 args.AddOption(&tribol_ratio, "-tr", "--tribol-proximity-parameter",
138 "Tribol-proximity-parameter.");
139
140 args.Parse();
141 if (!args.Good())
142 {
143 if (myid == 0)
144 {
145 args.PrintUsage(cout);
146 }
147 return 1;
148 }
149 if (myid == 0)
150 {
151 args.PrintOptions(cout);
152 }
153
154 // Validate selection and convert to enum.
155 MFEM_VERIFY(prob_no >= 0 &&
156 prob_no <= 2, "Unknown test problem number: " << prob_no);
157
158 prob_name = (problem_name)prob_no;
159
160 // Only the beam–sphere supports non-linear elasticity; fall back if needed.
161 if (nonlinear && prob_name!=problem_name::beamsphere)
162 {
163 if (myid == 0)
164 {
165 cout << "Non-linear elasticity not supported for the two-block and ironing problems"
166 << endl;
167 cout << "Switching to the linear model ..." << endl;
168 }
169 nonlinear = false;
170 }
171
172 // Bound constraints are used only for the non-linear case
173 // (activated later after a few load steps).
174 bool bound_constraints = (nonlinear) ? true : false;
175
176
177 // 2. Get the problem mesh.
178 Mesh * mesh = GetProblemMesh(prob_name);
179
180 // 3. Refine the mesh serially.
181 for (int i = 0; i<sref; i++)
182 {
183 mesh->UniformRefinement();
184 }
185
186 // 4. Convert to ParMesh and refine in parallel.
187 ParMesh pmesh(MPI_COMM_WORLD,*mesh);
188 delete mesh;
189 for (int i = 0; i<pref; i++)
190 {
191 pmesh.UniformRefinement();
192 }
193
194 // Material parameters per attribute (Young’s modulus and Poisson ratio).
195 Vector E(pmesh.attributes.Max());
196 Vector nu(pmesh.attributes.Max());
197
198 // Essential boundary specification:
199 // - ess_bdr_attr: boundary attribute ids to constrain
200 // - ess_bdr_attr_comp: component to constrain (0=x,1=y,2=z, -1=all)
201 Array<int> ess_bdr_attr;
202 Array<int> ess_bdr_attr_comp;
203
204 // 5. Define problem-dependent BCs and material properties.
205 switch (prob_name)
206 {
207 case twoblock:
208 case ironing:
209 ess_bdr_attr.Append(2); ess_bdr_attr_comp.Append(-1);
210 ess_bdr_attr.Append(6); ess_bdr_attr_comp.Append(-1);
211 E[0] = 1.0; E[1] = 1e3;
212 nu[0] = 0.499; nu[1] = 0.0;
213 break;
214 case beamsphere:
215 ess_bdr_attr.Append(1); ess_bdr_attr_comp.Append(0);
216 ess_bdr_attr.Append(2); ess_bdr_attr_comp.Append(1);
217 ess_bdr_attr.Append(4); ess_bdr_attr_comp.Append(2);
218 ess_bdr_attr.Append(5); ess_bdr_attr_comp.Append(-1);
219 E = 1.e3;
220 nu = 0.4;
221 break;
222 default:
223 MFEM_ABORT("Should be unreachable");
224 break;
225 }
226
227 // 6. Build the elasticity problem object (linear or non-linear).
228 // It owns the FE space and will assemble the stiffness and RHS.
229 ElasticityOperator prob(&pmesh, ess_bdr_attr,ess_bdr_attr_comp, E, nu,
230 nonlinear);
231
232 ParFiniteElementSpace * fes = prob.GetFESpace();
233 HYPRE_BigInt gndofs = fes->GlobalTrueVSize();
234 if (myid == 0)
235 {
236 mfem::out << "\n --------------------------------------" << endl;
237 mfem::out << " Global number of dofs = " << gndofs << endl;
238 mfem::out << " --------------------------------------" << endl;
239 }
240
241 // 7. Set up the contact interface for Tribol.
242 std::set<int> mortar_attr;
243 std::set<int> nonmortar_attr;
244 switch (prob_name)
245 {
246 case twoblock:
247 case ironing:
248 mortar_attr.insert(3);
249 nonmortar_attr.insert(4);
250 break;
251 case beamsphere:
252 mortar_attr.insert(6);
253 mortar_attr.insert(9);
254 nonmortar_attr.insert(7);
255 nonmortar_attr.insert(8);
256 break;
257 default:
258 MFEM_ABORT("Should be unreachable");
259 break;
260 }
261
262 // Displacement field (current step), and a copy for visualization.
263 ParGridFunction x_gf(fes); x_gf = 0.0;
264 ParMesh pmesh_copy(pmesh);
265 ParFiniteElementSpace fes_copy(*fes,pmesh_copy);
266 ParGridFunction xcopy_gf(&fes_copy); xcopy_gf = x_gf;
267
268 // Optional ParaView data collection
269 ParaViewDataCollection * paraview_dc = nullptr;
270 if (paraview)
271 {
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;
277 paraview_dc = new ParaViewDataCollection(paraview_file_name.str(), &pmesh_copy);
278 paraview_dc->SetPrefixPath("ParaView");
279 paraview_dc->SetLevelsOfDetail(2);
280 paraview_dc->SetDataFormat(VTKFormat::BINARY);
281 paraview_dc->SetHighOrderOutput(true);
282 paraview_dc->RegisterField("u", &xcopy_gf);
283 paraview_dc->SetCycle(0);
284 paraview_dc->SetTime(0.0);
285 paraview_dc->Save();
286 }
287
288 // Optional GLVis connection.
289 socketstream sol_sock;
290 if (visualization)
291 {
292 char vishost[] = "localhost";
293 int visport = 19916;
294 sol_sock.open(vishost, visport);
295 sol_sock.precision(8);
296 }
297
298 // Reference vs current coordinates (used to visualize total deformation).
299 ParGridFunction ref_coords(prob.GetFESpace());
300 ParGridFunction new_coords(prob.GetFESpace());
301 pmesh.GetNodes(new_coords);
302 pmesh.GetNodes(ref_coords);
303
304 // Load magnitude for problem 2 (beam-sphere).
305 real_t p = 40.0;
307
308 // 8. Construct the contact optimization problem wrapper. It sets up the
309 // contact system using Tribol and provides operators for objective evaluation,
310 // gradients, Hessians, and constraints. It also provides the filtered subspace
311 // transfer operator used by AMGF
312 OptContactProblem contact(&prob, mortar_attr, nonmortar_attr,
313 tribol_ratio, bound_constraints);
314
315 int dim = pmesh.Dimension();
316 Vector ess_values(dim); ess_values = 0.0;
317 Array<int> ess_bdr;
318 if (pmesh.bdr_attributes.Size())
319 {
320 ess_bdr.SetSize(pmesh.bdr_attributes.Max());
321 }
322
323 // 9. Time/load stepping loop.
324 int total_steps = nsteps + msteps;
325 for (int i = 0; i<total_steps; i++)
326 {
327 if (Mpi::Root())
328 {
329 std::ostringstream oss;
330 oss << "\n Solving optimization problem for time step: " << i;
331 mfem::out << oss.str() << endl;
332 mfem::out << " " <<std::string(oss.str().size()-2, '-') << endl;
333 }
334 ess_values = 0.0;
335 // 9(a). Apply problem-specific boundary conditions / loads for this step.
336 switch (prob_name)
337 {
338 case twoblock:
339 case ironing:
340 if (ess_bdr.Size())
341 {
342 ess_bdr = 0; ess_bdr[5] = 1;
343 }
344 if (i < nsteps)
345 {
346 ess_values[2] = -1.0/1.4*(i+1)/nsteps;
347 }
348 else
349 {
350 ess_values[0] = 3.0/1.4*(i+1-nsteps)/msteps;
351 ess_values[2] = -1.0/1.4;
352 }
353 prob.SetDisplacementDirichletData(ess_values, ess_bdr);
354 break;
355 case beamsphere:
356 if (ess_bdr.Size())
357 {
358 ess_bdr = 0; ess_bdr[2] = 1;
359 }
360 f.constant = -p*(i+1)/nsteps;
361 prob.SetNeumanPressureData(f,ess_bdr);
362 break;
363 default:
364 MFEM_ABORT("Should be unreachable");
365 break;
366 }
367
368 // 9(b). Assemble the elasticity system with current BCs.
369 prob.FormLinearSystem();
370
371 // Store the current (reference) displacement in true dofs.
372 Vector xref;
373 x_gf.GetTrueDofs(xref);
374
375 // 9(c). Form the contact system. This also builds the filtered subspace
376 // transfer used by AMGF.
377 contact.FormContactSystem(&new_coords, xref);
378
379 // 9(d). Activate bound constraints after a few steps in the non-linear case.
380 int activation_step = 2;
381 if (bound_constraints && i>activation_step)
382 {
383 contact.ActivateBoundConstraints();
384 }
385
386 // 9(e). Choose preconditioner: AMGF (with direct solver for subspace) or AMG.
387 Solver * prec = nullptr;
388 ParallelDirectSolver * subspacesolver = nullptr;
389#if MFEM_HYPRE_VERSION >= 23000
390 // new l1-hybrid symmetric Gauss-Seidel smoother
391 int amg_relax_type = 88;
392#else
393 int amg_relax_type = (!amgf && prob_name==problem_name::ironing) ? 18 : 8;
394#endif
395
396 if (amgf)
397 {
398 prec = new AMGFSolver();
399 auto * amgfprec = dynamic_cast<AMGFSolver *>(prec);
400 amgfprec->GetAMG().SetSystemsOptions(3);
401 amgfprec->GetAMG().SetPrintLevel(0);
402 amgfprec->GetAMG().SetRelaxType(amg_relax_type);
403 subspacesolver = new ParallelDirectSolver(MPI_COMM_WORLD, amgf_fsolver);
404 subspacesolver->SetPrintLevel(0);
405 amgfprec->SetFilteredSubspaceSolver(*subspacesolver);
406 amgfprec->SetFilteredSubspaceTransferOperator(
408 }
409 else
410 {
411 prec = new HypreBoomerAMG();
412 auto * amgprec = dynamic_cast<HypreBoomerAMG *>(prec);
413 amgprec->SetSystemsOptions(3);
414 amgprec->SetPrintLevel(0);
415 amgprec->SetRelaxType(amg_relax_type);
416 }
417
418 // 9(f). Linear solver used inside the IP optimizer.
419 CGSolver cgsolver(MPI_COMM_WORLD);
420 cgsolver.SetPrintLevel(0);
421 cgsolver.SetRelTol(1e-10);
422 cgsolver.SetMaxIter(10000);
423 cgsolver.SetPreconditioner(*prec);
424
425 // 9(g). Interior-Point optimizer driving contact resolution.
426 IPSolver optimizer(&contact);
427 optimizer.SetTol(1e-6);
428 optimizer.SetMaxIter(100);
429 optimizer.SetLinearSolver(&cgsolver);
430 optimizer.SetPrintLevel(0);
431
432 // Initial guess = previous reference configuration.
433 x_gf.SetTrueVector();
434 int ndofs = prob.GetFESpace()->GetTrueVSize();
435 Vector x0(ndofs); x0 = 0.0;
436 x0.Set(1.0, xref);
437
438 // Solve for the next step displacement (xf).
439 Vector xf(ndofs); xf = 0.0;
440 optimizer.Mult(x0, xf);
441
442 delete prec;
443 if (subspacesolver) { delete subspacesolver; }
444
445 // Update internal state for next step (for bound constraints).
446 Vector dx(xf); dx -= x0;
447 if (bound_constraints)
448 {
449 contact.SetDisplacement(dx, (i>=activation_step));
450 }
451
452 // 9(h). Report objective values, dofs, IP and CG iteration counts.
453 int eval_err;
454 real_t Einitial = contact.E(x0, eval_err);
455 real_t Efinal = contact.E(xf, eval_err);
456 Array<int> & PCGiterations = optimizer.GetLinearSolverIterations();
457
458 if (Mpi::Root())
459 {
460 mfem::out << " Initial Energy objective = " << Einitial << endl;
461 mfem::out << " Final Energy objective = " << Efinal << endl;
462 mfem::out << " Optimizer number of iterations = " <<
463 optimizer.GetNumIterations() << endl;
464 mfem::out << " PCG number of iterations = " ;
465 for (int i = 0; i < PCGiterations.Size(); ++i)
466 {
467 std::cout << PCGiterations[i] << " ";
468 }
469 mfem::out << "\n";
470 }
471
472 // 9(i). Visualization outputs.
473 x_gf.SetFromTrueDofs(xf);
474 add(ref_coords,x_gf,new_coords);
475 pmesh_copy.SetNodes(new_coords);
476 xcopy_gf = x_gf;
477 xcopy_gf.SetTrueVector();
478 if (paraview)
479 {
480 paraview_dc->SetCycle(i+1);
481 paraview_dc->SetTime(real_t(i+1));
482 paraview_dc->Save();
483 }
484
485 if (visualization)
486 {
487 sol_sock << "parallel " << num_procs << " " << myid << "\n"
488 << "solution\n" << pmesh_copy << x_gf << flush;
489
490 if (i == total_steps - 1)
491 {
492 pmesh.MoveNodes(x_gf);
493 char vishost[] = "localhost";
494 int visport = 19916;
495 socketstream sol_sock_final(vishost, visport);
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;
499 }
500 }
501
502 // 9(j). Update RHS/load for the next step (if any).
503 if (i == total_steps-1) { break; }
504 prob.UpdateRHS();
505 }
506
507 // 10. Cleanup.
508 if (paraview_dc) { delete paraview_dc; }
509 return 0;
510}
511
513{
514
515 if (prob_name == problem_name::beamsphere)
516 {
517 return new Mesh("meshes/beam-sphere.mesh",1);
518 }
519 else // construct the two-block or ironing mesh
520 {
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;
525 Mesh mesh0 = Mesh::MakeCartesian3D(nx0, ny0, nz0, Element::HEXAHEDRON,
526 lx0, ly0, lz0);
527
528 // adjust boundary attributes
529 for (int i = 0; i<mesh0.GetNBE(); i++)
530 {
531 int battr = mesh0.GetBdrElement(i)->GetAttribute();
532 int new_battr;
533 switch (battr)
534 {
535 case 1: new_battr = 2; break;
536 case 6: new_battr = 3; break;
537 default: new_battr = 1; break;
538 }
539 mesh0.SetBdrAttribute(i, new_battr);
540 }
541 mesh0.SetAttributes();
542 if (prob_name == problem_name::twoblock)
543 {
544 constexpr real_t lx = 1.0, ly = 1.0, lz = 1.0;
545 constexpr int nx = 5, ny = 5, nz = 5;
546 Mesh mesh = Mesh::MakeCartesian3D(nx, ny, nz, Element::HEXAHEDRON, lx, ly, lz);
547
548 // adjust element attributes
549 for (int i = 0; i<mesh.GetNE(); i++) { mesh.GetElement(i)->SetAttribute(2); }
550 mesh.SetAttributes();
551
552 // adjust boundary attributes
553 for (int i = 0; i<mesh.GetNBE(); i++)
554 {
555 int battr = mesh.GetBdrElement(i)->GetAttribute();
556 int new_battr;
557 switch (battr)
558 {
559 case 1: new_battr = 4; break;
560 case 6: new_battr = 6; break;
561 default: new_battr = 5; break;
562 }
563 mesh.SetBdrAttribute(i, new_battr);
564 }
565 mesh.SetAttributes();
566
567 Vector shift(3);
568 shift(0) = (ly0-ly)/3;
569 shift(1) = (ly0-ly)/2;
570 shift(2) = lz0;
571
572 auto shift_map = [&](const Vector &x, Vector &y)
573 {
574 y.SetSize(3);
575 y = x;
576 y+=shift;
577 };
578
579 mesh.Transform(shift_map);
580
581 Mesh *mesh_array2[] = {&mesh, &mesh0};
582 combined_mesh = new Mesh(mesh_array2, 2);
583
584
585 }
586 else if (prob_name == problem_name::ironing)
587 {
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;
590 Mesh mesh = Mesh::MakeCartesian3D(nx, ny, nz, Element::HEXAHEDRON, lx, ly, lz);
591
592 // adjust element attributes
593 for (int i = 0; i<mesh.GetNE(); i++) { mesh.GetElement(i)->SetAttribute(2); }
594 mesh.SetAttributes();
595
596 // adjust boundary attributes
597 for (int i = 0; i<mesh.GetNBE(); i++)
598 {
599 int battr = mesh.GetBdrElement(i)->GetAttribute();
600 int new_battr;
601 switch (battr)
602 {
603 case 1: new_battr = 6; break;
604 case 6: new_battr = 4; break;
605 default: new_battr = 5; break;
606 }
607 mesh.SetBdrAttribute(i, new_battr);
608 }
609 mesh.SetAttributes();
610
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;
614
615 constexpr real_t xshift = lx0/4;
616 constexpr real_t yshift = 0.5*(ly0-ly);
617 constexpr real_t zshift = rout + lz0;
618
619 auto bend_map = [&](const Vector &x, Vector &y)
620 {
621 const real_t theta = -((x(0) / lx + 0.5) * theta_arc);
622 const real_t r = rin + (x(2) + lz);
623 y.SetSize(3);
624 y(0) = xshift + r * std::cos(theta);
625 y(1) = yshift + x(1);
626 y(2) = zshift + r * std::sin(theta);
627 };
628
629 mesh.Transform(bend_map);
630 Mesh *mesh_array2[] = {&mesh, &mesh0};
631 combined_mesh = new Mesh(mesh_array2, 2);
632 }
633
634 return combined_mesh;
635 }
636}
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.
Definition array.cpp:69
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:840
int Size() const
Return the logical size of the array.
Definition array.hpp:166
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:912
Conjugate gradient method.
Definition solvers.hpp:627
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.
Definition element.hpp:61
int GetAttribute() const
Return element's attribute.
Definition element.hpp:58
void SetTrueVector()
Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:148
The BoomerAMG solver in hypre.
Definition hypre.hpp:1737
void SetSystemsOptions(int dim, bool order_bynodes=false)
Definition hypre.cpp:5185
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Definition hypre.cpp:33
Class for interior-point solvers of contact-problems described by a OptContactProblem.
Definition ip.hpp:55
int GetNumIterations()
get number of interior-point iterations of most recent Mult call
Definition ip.hpp:82
void SetTol(real_t tol)
Set absolute tolerance.
Definition ip.hpp:67
void SetLinearSolver(Solver *solver_)
Set linear solver.
Definition ip.hpp:73
Array< int > & GetLinearSolverIterations()
Get solver iteration counts.
Definition ip.hpp:85
void SetPrintLevel(int print_level_)
Set print level.
Definition ip.hpp:76
void Mult(const Vector &, Vector &)
Apply the interior-point solver.
Definition ip.cpp:132
void SetMaxIter(int max_it)
Set maximum number of interior-point steps.
Definition ip.hpp:70
void SetRelTol(real_t rtol)
Definition solvers.hpp:238
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Definition solvers.cpp:178
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:76
void SetMaxIter(int max_it)
Definition solvers.hpp:240
Mesh data type.
Definition mesh.hpp:65
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:304
const Element * GetElement(int i) const
Return pointer to the i'th element object.
Definition mesh.hpp:1434
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1377
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1306
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
Definition mesh.hpp:1449
void Transform(std::function< void(const Vector &, Vector &)> f)
Definition mesh.cpp:13540
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 =...
Definition mesh.cpp:4627
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...
Definition mesh.cpp:1937
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:9627
int GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1380
void MoveNodes(const Vector &displacements)
Definition mesh.cpp:9612
void SetNodes(const Vector &node_coord)
Updates the vertex/node locations. Invokes NodesUpdated().
Definition mesh.cpp:9639
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11637
void SetBdrAttribute(int i, int attr)
Set the attribute of boundary element i.
Definition mesh.hpp:1493
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition mesh.hpp:302
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).
Contact optimization problem with mortar and non-mortar interfaces.
void FormContactSystem(ParGridFunction *coords_, const Vector &xref)
Build contact system, assemble gap Jacobian and mass matrices.
real_t E(const Vector &d, int &eval_err)
Evaluate elastic energy functional.
void ActivateBoundConstraints()
Activate bound constraints (if enabled).
HypreParMatrix * GetContactSubspaceTransferOperator()
Return transfer operator from contact to displacement subspace.
void SetDisplacement(const Vector &dx, bool active_constraints)
Update displacement and eps for bound constraints.
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...
Definition optparser.hpp:82
bool Good() const
Return true if the command line options were parsed successfully.
Abstract parallel finite element space.
Definition pfespace.hpp:31
HYPRE_BigInt GlobalTrueVSize() const
Definition pfespace.hpp:349
Class for parallel grid function.
Definition pgridfunc.hpp:50
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.
Definition pmesh.hpp:34
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)
Base class for solvers.
Definition operator.hpp:792
Vector data type.
Definition vector.hpp:82
Vector & Set(const real_t a, const Vector &x)
(*this) = a * x
Definition vector.cpp:341
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:584
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
problem_name
Definition contact.cpp:60
@ beamsphere
Definition contact.cpp:63
@ ironing
Definition contact.cpp:62
@ twoblock
Definition contact.cpp:61
Mesh * GetProblemMesh(problem_name prob_name)
Definition contact.cpp:512
int dim
Definition ex24.cpp:53
prob_type prob
Definition ex25.cpp:156
int main()
HYPRE_Int HYPRE_BigInt
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition globals.hpp:66
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition vector.cpp:414
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
const char vishost[]
real_t p(const Vector &x, real_t t)