MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
pmesh-fitting.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// --------------------------------------------------------------
13// Boundary and Interface Fitting Miniapp
14// --------------------------------------------------------------
15//
16// This miniapp performs mesh optimization for controlling mesh quality and
17// aligning a selected set of nodes to boundary and/or interface of interest
18// defined using a level-set function. The mesh quality aspect is based on a
19// variational formulation of the Target-Matrix Optimization Paradigm (TMOP).
20// Boundary/interface alignment is weakly enforced using a penalization term
21// that moves a selected set of nodes towards the zero level set of a signed
22// smooth discrete function.
23//
24// See the following papers for more details:
25//
26// [1] "Adaptive Surface Fitting and Tangential Relaxation for High-Order Mesh Optimization" by
27// Knupp, Kolev, Mittal, Tomov.
28// [2] "High-Order Mesh Morphing for Boundary and Interface Fitting to Implicit Geometries" by
29// Barrera, Kolev, Mittal, Tomov.
30// [3] "The target-matrix optimization paradigm for high-order meshes" by
31// Dobrev, Knupp, Kolev, Mittal, Tomov.
32//
33// Compile with: make pmesh-fitting
34//
35// Sample runs:
36// Surface fitting:
37// mpirun -np 4 pmesh-fitting -o 3 -mid 58 -tid 1 -vl 1 -sfc 5e4 -rtol 1e-5
38// mpirun -np 4 pmesh-fitting -m square01-tri.mesh -o 3 -rs 0 -mid 58 -tid 1 -vl 1 -sfc 1e4 -rtol 1e-5
39// Surface fitting with weight adaptation and termination based on fitting error:
40// mpirun -np 4 pmesh-fitting -o 2 -mid 2 -tid 1 -vl 2 -sfc 10 -rtol 1e-20 -sfa 10.0 -sft 1e-5 -no-resid -ni 40
41// Surface fitting with weight adaptation, limit on max weight, and convergence based on residual.
42// * mpirun -np 4 pmesh-fitting -m ../../data/inline-tri.mesh -o 2 -mid 2 -tid 4 -vl 2 -sfc 10 -rtol 1e-10 -sfa 10.0 -sft 1e-5 -bgamriter 3 -sbgmesh -ae 1 -marking -slstype 3 -resid -sfcmax 10000 -mod-bndr-attr
43// Surface fitting to Fischer-Tropsch reactor like domain (requires GSLIB):
44// * mpirun -np 6 pmesh-fitting -m ../../data/inline-tri.mesh -o 2 -rs 4 -mid 2 -tid 1 -vl 2 -sfc 100 -rtol 1e-12 -li 20 -ae 1 -bnd -sbgmesh -slstype 2 -smtype 0 -sfa 10.0 -sft 1e-4 -no-resid -bgamriter 5 -dist -mod-bndr-attr -ni 50
45
46#include "mesh-fitting.hpp"
47
48using namespace mfem;
49using namespace std;
50
51int main (int argc, char *argv[])
52{
53#ifdef HYPRE_USING_GPU
54 cout << "\nThis miniapp is NOT supported with the GPU version of hypre.\n\n";
55 return MFEM_SKIP_RETURN_VALUE;
56#endif
57
58 Mpi::Init(argc, argv);
59 int myid = Mpi::WorldRank();
61
62 // Set the method's default parameters.
63 const char *mesh_file = "square01.mesh";
64 int mesh_poly_deg = 1;
65 int rs_levels = 1;
66 int rp_levels = 0;
67 int metric_id = 2;
68 int target_id = 1;
69 real_t surface_fit_const = 100.0;
70 int quad_order = 8;
71 int solver_type = 0;
72 int solver_iter = 20;
73#ifdef MFEM_USE_SINGLE
74 real_t solver_rtol = 1e-4;
75#else
76 real_t solver_rtol = 1e-10;
77#endif
78 int lin_solver = 2;
79 int max_lin_iter = 100;
80 bool move_bnd = true;
81 bool visualization = false;
82 int verbosity_level = 0;
83 int adapt_eval = 0;
84 const char *devopt = "cpu";
85 real_t surface_fit_adapt = 0.0;
86 real_t surface_fit_threshold = -10;
87 real_t surf_fit_const_max = 1e20;
88 bool adapt_marking = false;
89 bool surf_bg_mesh = false;
90 bool comp_dist = false;
91 int surf_ls_type = 1;
92 int marking_type = 0;
93 bool mod_bndr_attr = false;
94 bool material = false;
95 int mesh_node_ordering = 0;
96 int bg_amr_iters = 0;
97 bool conv_residual = true;
98
99 // Parse command-line options.
100 OptionsParser args(argc, argv);
101 args.AddOption(&mesh_file, "-m", "--mesh",
102 "Mesh file to use.");
103 args.AddOption(&mesh_poly_deg, "-o", "--order",
104 "Polynomial degree of mesh finite element space.");
105 args.AddOption(&rs_levels, "-rs", "--refine-serial",
106 "Number of times to refine the mesh uniformly in serial.");
107 args.AddOption(&rp_levels, "-rp", "--refine-parallel",
108 "Number of times to refine the mesh uniformly in parallel.");
109 args.AddOption(&metric_id, "-mid", "--metric-id",
110 "Mesh optimization metric. See list in mesh-optimizer.");
111 args.AddOption(&target_id, "-tid", "--target-id",
112 "Target (ideal element) type:\n\t"
113 "1: Ideal shape, unit size\n\t"
114 "2: Ideal shape, equal size\n\t"
115 "3: Ideal shape, initial size\n\t"
116 "4: Given full analytic Jacobian (in physical space)\n\t"
117 "5: Ideal shape, given size (in physical space)");
118 args.AddOption(&surface_fit_const, "-sfc", "--surface-fit-const",
119 "Surface preservation constant.");
120 args.AddOption(&quad_order, "-qo", "--quad_order",
121 "Order of the quadrature rule.");
122 args.AddOption(&solver_type, "-st", "--solver-type",
123 " Type of solver: (default) 0: Newton, 1: LBFGS");
124 args.AddOption(&solver_iter, "-ni", "--newton-iters",
125 "Maximum number of Newton iterations.");
126 args.AddOption(&solver_rtol, "-rtol", "--newton-rel-tolerance",
127 "Relative tolerance for the Newton solver.");
128 args.AddOption(&lin_solver, "-ls", "--lin-solver",
129 "Linear solver:\n\t"
130 "0: l1-Jacobi\n\t"
131 "1: CG\n\t"
132 "2: MINRES\n\t"
133 "3: MINRES + Jacobi preconditioner\n\t"
134 "4: MINRES + l1-Jacobi preconditioner");
135 args.AddOption(&max_lin_iter, "-li", "--lin-iter",
136 "Maximum number of iterations in the linear solve.");
137 args.AddOption(&move_bnd, "-bnd", "--move-boundary", "-fix-bnd",
138 "--fix-boundary",
139 "Enable motion along horizontal and vertical boundaries.");
140 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
141 "--no-visualization",
142 "Enable or disable GLVis visualization.");
143 args.AddOption(&verbosity_level, "-vl", "--verbosity-level",
144 "Set the verbosity level - 0, 1, or 2.");
145 args.AddOption(&adapt_eval, "-ae", "--adaptivity-evaluator",
146 "0 - Advection based (DEFAULT), 1 - GSLIB.");
147 args.AddOption(&devopt, "-d", "--device",
148 "Device configuration string, see Device::Configure().");
149 args.AddOption(&surface_fit_adapt, "-sfa", "--adaptive-surface-fit",
150 "Scaling factor for surface fitting weight.");
151 args.AddOption(&surface_fit_threshold, "-sft", "--surf-fit-threshold",
152 "Set threshold for surface fitting. TMOP solver will"
153 "terminate when max surface fitting error is below this limit");
154 args.AddOption(&surf_fit_const_max, "-sfcmax", "--surf-fit-const-max",
155 "Max surface fitting weight allowed");
156 args.AddOption(&adapt_marking, "-marking", "--adaptive-marking", "-no-amarking",
157 "--no-adaptive-marking",
158 "Enable or disable adaptive marking surface fitting.");
159 args.AddOption(&surf_bg_mesh, "-sbgmesh", "--surf-bg-mesh",
160 "-no-sbgmesh","--no-surf-bg-mesh",
161 "Use background mesh for surface fitting.");
162 args.AddOption(&comp_dist, "-dist", "--comp-dist",
163 "-no-dist","--no-comp-dist",
164 "Compute distance from 0 level set or not.");
165 args.AddOption(&surf_ls_type, "-slstype", "--surf-ls-type",
166 "1 - Circle (DEFAULT), 2 - reactor level-set, 3 - squircle.");
167 args.AddOption(&marking_type, "-smtype", "--surf-marking-type",
168 "0 - Interface (DEFAULT), otherwise Boundary attribute.");
169 args.AddOption(&mod_bndr_attr, "-mod-bndr-attr", "--modify-boundary-attribute",
170 "-fix-bndr-attr", "--fix-boundary-attribute",
171 "Change boundary attribute based on alignment with Cartesian axes.");
172 args.AddOption(&material, "-mat", "--mat",
173 "-no-mat","--no-mat", "Use default material attributes.");
174 args.AddOption(&mesh_node_ordering, "-mno", "--mesh_node_ordering",
175 "Ordering of mesh nodes."
176 "0 (default): byNodes, 1: byVDIM");
177 args.AddOption(&bg_amr_iters, "-bgamriter", "--amr-iter",
178 "Number of amr iterations on background mesh");
179 args.AddOption(&conv_residual, "-resid", "--resid", "-no-resid",
180 "--no-resid",
181 "Enable residual based convergence.");
182 args.Parse();
183 if (!args.Good())
184 {
185 if (myid == 0) { args.PrintUsage(cout); }
186 return 1;
187 }
188 if (myid == 0) { args.PrintOptions(cout); }
189
190 Device device(devopt);
191 if (myid == 0) { device.Print();}
192
193 MFEM_VERIFY(surface_fit_const > 0.0,
194 "This miniapp is for surface fitting only. See (p)mesh-optimizer"
195 "miniapps for general high-order mesh optimization.");
196
197 // Initialize and refine the starting mesh.
198 Mesh *mesh = new Mesh(mesh_file, 1, 1, false);
199 for (int lev = 0; lev < rs_levels; lev++)
200 {
201 mesh->UniformRefinement();
202 }
203 const int dim = mesh->Dimension();
204
205 // Define level-set coefficient
206 FunctionCoefficient *ls_coeff = NULL;
207 if (surf_ls_type == 1) //Circle
208 {
210 }
211 else if (surf_ls_type == 2) // reactor
212 {
213 ls_coeff = new FunctionCoefficient(reactor);
214 }
215 else if (surf_ls_type == 3) //squircle
216 {
218 }
219 else if (surf_ls_type == 6) // 3D shape
220 {
221 ls_coeff = new FunctionCoefficient(csg_cubecylsph);
222 }
223 else
224 {
225 MFEM_ABORT("Surface fitting level set type not implemented yet.")
226 }
227
228 ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
229 delete mesh;
230 for (int lev = 0; lev < rp_levels; lev++) { pmesh->UniformRefinement(); }
231
232 // Setup background mesh for surface fitting
233 ParMesh *pmesh_surf_fit_bg = NULL;
234 if (surf_bg_mesh)
235 {
236 Mesh *mesh_surf_fit_bg = NULL;
237 if (dim == 2)
238 {
239 mesh_surf_fit_bg =
241 }
242 else if (dim == 3)
243 {
244 mesh_surf_fit_bg =
246 }
247 mesh_surf_fit_bg->EnsureNCMesh();
248 pmesh_surf_fit_bg = new ParMesh(MPI_COMM_WORLD, *mesh_surf_fit_bg);
249 delete mesh_surf_fit_bg;
250 }
251
252 // Define a finite element space on the mesh. Here we use vector finite
253 // elements which are tensor products of quadratic finite elements. The
254 // number of components in the vector finite element space is specified by
255 // the last parameter of the FiniteElementSpace constructor.
257 if (mesh_poly_deg <= 0)
258 {
259 fec = new QuadraticPosFECollection;
260 mesh_poly_deg = 2;
261 }
262 else { fec = new H1_FECollection(mesh_poly_deg, dim); }
263 ParFiniteElementSpace *pfespace =
264 new ParFiniteElementSpace(pmesh, fec, dim, mesh_node_ordering);
265
266 // Make the mesh curved based on the above finite element space. This
267 // means that we define the mesh elements through a fespace-based
268 // transformation of the reference element.
269 pmesh->SetNodalFESpace(pfespace);
270
271 // Get the mesh nodes (vertices and other degrees of freedom in the finite
272 // element space) as a finite element grid function in fespace. Note that
273 // changing x automatically changes the shapes of the mesh elements.
274 ParGridFunction x(pfespace);
275 pmesh->SetNodalGridFunction(&x);
276 x.SetTrueVector();
277
278 // Save the starting (prior to the optimization) mesh to a file. This
279 // output can be viewed later using GLVis: "glvis -m perturbed -np
280 // num_mpi_tasks".
281 {
282 ostringstream mesh_name;
283 mesh_name << "perturbed.mesh";
284 ofstream mesh_ofs(mesh_name.str().c_str());
285 mesh_ofs.precision(8);
286 pmesh->PrintAsSerial(mesh_ofs);
287 }
288
289 // Store the starting (prior to the optimization) positions.
290 ParGridFunction x0(pfespace);
291 x0 = x;
292
293 // Form the integrator that uses the chosen metric and target.
294 TMOP_QualityMetric *metric = NULL;
295 switch (metric_id)
296 {
297 // T-metrics
298 case 2: metric = new TMOP_Metric_002; break;
299 case 58: metric = new TMOP_Metric_058; break;
300 case 80: metric = new TMOP_Metric_080(0.5); break;
301 case 303: metric = new TMOP_Metric_303; break;
302 case 328: metric = new TMOP_Metric_328; break;
303 default:
304 if (myid == 0) { cout << "Unknown metric_id: " << metric_id << endl; }
305 return 3;
306 }
307
308 if (metric_id < 300)
309 {
310 MFEM_VERIFY(dim == 2, "Incompatible metric for 3D meshes");
311 }
312 if (metric_id >= 300)
313 {
314 MFEM_VERIFY(dim == 3, "Incompatible metric for 2D meshes");
315 }
316
318 TargetConstructor *target_c = NULL;
319 switch (target_id)
320 {
321 case 1: target_t = TargetConstructor::IDEAL_SHAPE_UNIT_SIZE; break;
322 case 2: target_t = TargetConstructor::IDEAL_SHAPE_EQUAL_SIZE; break;
323 case 3: target_t = TargetConstructor::IDEAL_SHAPE_GIVEN_SIZE; break;
324 case 4: target_t = TargetConstructor::GIVEN_SHAPE_AND_SIZE; break;
325 default:
326 if (myid == 0) { cout << "Unknown target_id: " << target_id << endl; }
327 return 3;
328 }
329
330 if (target_c == NULL)
331 {
332 target_c = new TargetConstructor(target_t, MPI_COMM_WORLD);
333 }
334 target_c->SetNodes(x0);
335 TMOP_Integrator *tmop_integ = new TMOP_Integrator(metric, target_c);
336
337 // Setup the quadrature rules for the TMOP integrator.
338 IntegrationRules *irules = &IntRulesLo;
339 tmop_integ->SetIntegrationRules(*irules, quad_order);
340 if (myid == 0 && dim == 2)
341 {
342 cout << "Triangle quadrature points: "
343 << irules->Get(Geometry::TRIANGLE, quad_order).GetNPoints()
344 << "\nQuadrilateral quadrature points: "
345 << irules->Get(Geometry::SQUARE, quad_order).GetNPoints() << endl;
346 }
347 if (myid == 0 && dim == 3)
348 {
349 cout << "Tetrahedron quadrature points: "
350 << irules->Get(Geometry::TETRAHEDRON, quad_order).GetNPoints()
351 << "\nHexahedron quadrature points: "
352 << irules->Get(Geometry::CUBE, quad_order).GetNPoints()
353 << "\nPrism quadrature points: "
354 << irules->Get(Geometry::PRISM, quad_order).GetNPoints() << endl;
355 }
356
357 // Modify boundary attribute for surface node movement
358 // Sets attributes of a boundary element to 1/2/3 if it is parallel to x/y/z.
359 if (mod_bndr_attr)
360 {
362 pmesh->SetAttributes();
363 }
364 pmesh->ExchangeFaceNbrData();
365
366 // Surface fitting.
367 L2_FECollection mat_coll(0, dim);
368 H1_FECollection surf_fit_fec(mesh_poly_deg, dim);
369 ParFiniteElementSpace surf_fit_fes(pmesh, &surf_fit_fec);
370 ParFiniteElementSpace mat_fes(pmesh, &mat_coll);
371 ParGridFunction mat(&mat_fes);
372 ParGridFunction surf_fit_mat_gf(&surf_fit_fes);
373 ParGridFunction surf_fit_gf0(&surf_fit_fes);
374 Array<bool> surf_fit_marker(surf_fit_gf0.Size());
375 ConstantCoefficient surf_fit_coeff(surface_fit_const);
376 AdaptivityEvaluator *adapt_surface = NULL;
377 AdaptivityEvaluator *adapt_grad_surface = NULL;
378 AdaptivityEvaluator *adapt_hess_surface = NULL;
379
380 // Background mesh FECollection, FESpace, and GridFunction
381 H1_FECollection *surf_fit_bg_fec = NULL;
382 ParFiniteElementSpace *surf_fit_bg_fes = NULL;
383 ParGridFunction *surf_fit_bg_gf0 = NULL;
384 ParFiniteElementSpace *surf_fit_bg_grad_fes = NULL;
385 ParGridFunction *surf_fit_bg_grad = NULL;
386 ParFiniteElementSpace *surf_fit_bg_hess_fes = NULL;
387 ParGridFunction *surf_fit_bg_hess = NULL;
388
389 // If a background mesh is used, we interpolate the Gradient and Hessian
390 // from that mesh to the current mesh being optimized.
391 ParFiniteElementSpace *surf_fit_grad_fes = NULL;
392 ParGridFunction *surf_fit_grad = NULL;
393 ParFiniteElementSpace *surf_fit_hess_fes = NULL;
394 ParGridFunction *surf_fit_hess = NULL;
395
396 if (surf_bg_mesh)
397 {
398 pmesh_surf_fit_bg->SetCurvature(mesh_poly_deg);
399
400 Vector p_min(dim), p_max(dim);
401 pmesh->GetBoundingBox(p_min, p_max);
402 GridFunction &x_bg = *pmesh_surf_fit_bg->GetNodes();
403 const int num_nodes = x_bg.Size() / dim;
404 for (int i = 0; i < num_nodes; i++)
405 {
406 for (int d = 0; d < dim; d++)
407 {
408 real_t length_d = p_max(d) - p_min(d),
409 extra_d = 0.2 * length_d;
410 x_bg(i + d*num_nodes) = p_min(d) - extra_d +
411 x_bg(i + d*num_nodes) * (length_d + 2*extra_d);
412 }
413 }
414 surf_fit_bg_fec = new H1_FECollection(mesh_poly_deg+1, dim);
415 surf_fit_bg_fes = new ParFiniteElementSpace(pmesh_surf_fit_bg, surf_fit_bg_fec);
416 surf_fit_bg_gf0 = new ParGridFunction(surf_fit_bg_fes);
417 }
418
419 Array<int> vdofs;
420 if (surface_fit_const > 0.0)
421 {
422 surf_fit_gf0.ProjectCoefficient(*ls_coeff);
423 if (surf_bg_mesh)
424 {
425 OptimizeMeshWithAMRAroundZeroLevelSet(*pmesh_surf_fit_bg, *ls_coeff,
426 bg_amr_iters, *surf_fit_bg_gf0);
427 pmesh_surf_fit_bg->Rebalance();
428 surf_fit_bg_fes->Update();
429 surf_fit_bg_gf0->Update();
430
431 if (comp_dist)
432 {
433 ComputeScalarDistanceFromLevelSet(*pmesh_surf_fit_bg, *ls_coeff,
434 *surf_fit_bg_gf0);
435 }
436 else { surf_fit_bg_gf0->ProjectCoefficient(*ls_coeff); }
437
438 surf_fit_bg_grad_fes =
439 new ParFiniteElementSpace(pmesh_surf_fit_bg, surf_fit_bg_fec, dim);
440 surf_fit_bg_grad = new ParGridFunction(surf_fit_bg_grad_fes);
441
442 surf_fit_grad_fes =
443 new ParFiniteElementSpace(pmesh, &surf_fit_fec, dim);
444 surf_fit_grad = new ParGridFunction(surf_fit_grad_fes);
445
446 surf_fit_bg_hess_fes =
447 new ParFiniteElementSpace(pmesh_surf_fit_bg, surf_fit_bg_fec, dim * dim);
448 surf_fit_bg_hess = new ParGridFunction(surf_fit_bg_hess_fes);
449
450 surf_fit_hess_fes =
451 new ParFiniteElementSpace(pmesh, &surf_fit_fec, dim * dim);
452 surf_fit_hess = new ParGridFunction(surf_fit_hess_fes);
453
454 //Setup gradient of the background mesh
455 const int size_bg = surf_fit_bg_gf0->Size();
456 for (int d = 0; d < pmesh_surf_fit_bg->Dimension(); d++)
457 {
458 ParGridFunction surf_fit_bg_grad_comp(
459 surf_fit_bg_fes, surf_fit_bg_grad->GetData() + d * size_bg);
460 surf_fit_bg_gf0->GetDerivative(1, d, surf_fit_bg_grad_comp);
461 }
462
463 //Setup Hessian on background mesh
464 int id = 0;
465 for (int d = 0; d < pmesh_surf_fit_bg->Dimension(); d++)
466 {
467 for (int idir = 0; idir < pmesh_surf_fit_bg->Dimension(); idir++)
468 {
469 ParGridFunction surf_fit_bg_grad_comp(
470 surf_fit_bg_fes, surf_fit_bg_grad->GetData() + d * size_bg);
471 ParGridFunction surf_fit_bg_hess_comp(
472 surf_fit_bg_fes, surf_fit_bg_hess->GetData()+ id * size_bg);
473 surf_fit_bg_grad_comp.GetDerivative(1, idir,
474 surf_fit_bg_hess_comp);
475 id++;
476 }
477 }
478 }
479 else // !surf_bg_mesh
480 {
481 if (comp_dist)
482 {
483 ComputeScalarDistanceFromLevelSet(*pmesh, *ls_coeff, surf_fit_gf0);
484 }
485 }
486
487 // Set material grid function
488 for (int i = 0; i < pmesh->GetNE(); i++)
489 {
490 if (material)
491 {
492 mat(i) = pmesh->GetAttribute(i)-1;
493 }
494 else
495 {
496 mat(i) = material_id(i, surf_fit_gf0);
497 pmesh->SetAttribute(i, mat(i) + 1);
498 }
499 }
500
501 // Adapt attributes for marking such that if all but 1 face of an element
502 // are marked, the element attribute is switched.
503 if (adapt_marking)
504 {
505 ModifyAttributeForMarkingDOFS(pmesh, mat, 0);
506 ModifyAttributeForMarkingDOFS(pmesh, mat, 1);
507 }
508 pmesh->SetAttributes();
509
510 GridFunctionCoefficient coeff_mat(&mat);
511 surf_fit_mat_gf.ProjectDiscCoefficient(coeff_mat,
513 surf_fit_mat_gf.SetTrueVector();
514 surf_fit_mat_gf.SetFromTrueVector();
515
516 // Set DOFs for fitting
517 surf_fit_marker = false;
518 surf_fit_mat_gf = 0.;
519
520 // Strategy 1: Choose face between elements of different attributes.
521 if (marking_type == 0)
522 {
524 const Vector &FaceNbrData = mat.FaceNbrData();
525 Array<int> dof_list;
526 Array<int> dofs;
527
528 for (int i = 0; i < pmesh->GetNumFaces(); i++)
529 {
530 auto tr = pmesh->GetInteriorFaceTransformations(i);
531 if (tr != NULL)
532 {
533 int mat1 = mat(tr->Elem1No);
534 int mat2 = mat(tr->Elem2No);
535 if (mat1 != mat2)
536 {
537 surf_fit_gf0.ParFESpace()->GetFaceDofs(i, dofs);
538 dof_list.Append(dofs);
539 }
540 }
541 }
542 for (int i = 0; i < pmesh->GetNSharedFaces(); i++)
543 {
544 auto tr = pmesh->GetSharedFaceTransformations(i);
545 if (tr != NULL)
546 {
547 int faceno = pmesh->GetSharedFace(i);
548 int mat1 = mat(tr->Elem1No);
549 int mat2 = FaceNbrData(tr->Elem2No-pmesh->GetNE());
550 if (mat1 != mat2)
551 {
552 surf_fit_gf0.ParFESpace()->GetFaceDofs(faceno, dofs);
553 dof_list.Append(dofs);
554 }
555 }
556 }
557 for (int i = 0; i < dof_list.Size(); i++)
558 {
559 surf_fit_marker[dof_list[i]] = true;
560 surf_fit_mat_gf(dof_list[i]) = 1.0;
561 }
562 }
563 // Strategy 2: Mark all boundaries with attribute marking_type
564 else if (marking_type > 0)
565 {
566 for (int i = 0; i < pmesh->GetNBE(); i++)
567 {
568 const int attr = pmesh->GetBdrElement(i)->GetAttribute();
569 if (attr == marking_type)
570 {
571 surf_fit_fes.GetBdrElementVDofs(i, vdofs);
572 for (int j = 0; j < vdofs.Size(); j++)
573 {
574 surf_fit_marker[vdofs[j]] = true;
575 surf_fit_mat_gf(vdofs[j]) = 1.0;
576 }
577 }
578 }
579 }
580
581 // Unify marker across processor boundary
582 surf_fit_mat_gf.ExchangeFaceNbrData();
583 {
584 GroupCommunicator &gcomm = surf_fit_mat_gf.ParFESpace()->GroupComm();
585 Array<real_t> gf_array(surf_fit_mat_gf.GetData(),
586 surf_fit_mat_gf.Size());
587 gcomm.Reduce<real_t>(gf_array, GroupCommunicator::Max);
588 gcomm.Bcast(gf_array);
589 }
590 surf_fit_mat_gf.ExchangeFaceNbrData();
591
592 for (int i = 0; i < surf_fit_mat_gf.Size(); i++)
593 {
594 surf_fit_marker[i] = surf_fit_mat_gf(i) == 1.0;
595 }
596
597 // Set AdaptivityEvaluators for transferring information from initial
598 // mesh to current mesh as it moves during adaptivity.
599 if (adapt_eval == 0)
600 {
601 adapt_surface = new AdvectorCG;
602 MFEM_VERIFY(!surf_bg_mesh, "Background meshes require GSLIB.");
603 }
604 else if (adapt_eval == 1)
605 {
606#ifdef MFEM_USE_GSLIB
607 adapt_surface = new InterpolatorFP;
608 adapt_grad_surface = new InterpolatorFP;
609 adapt_hess_surface = new InterpolatorFP;
610#else
611 MFEM_ABORT("MFEM is not built with GSLIB support!");
612#endif
613 }
614 else { MFEM_ABORT("Bad interpolation option."); }
615
616 if (!surf_bg_mesh)
617 {
618 tmop_integ->EnableSurfaceFitting(surf_fit_gf0, surf_fit_marker,
619 surf_fit_coeff, *adapt_surface,
620 adapt_grad_surface,
621 adapt_hess_surface);
622 }
623 else
624 {
626 *surf_fit_bg_gf0, surf_fit_gf0,
627 surf_fit_marker, surf_fit_coeff, *adapt_surface,
628 *surf_fit_bg_grad, *surf_fit_grad, *adapt_grad_surface,
629 *surf_fit_bg_hess, *surf_fit_hess, *adapt_hess_surface);
630 }
631
632 if (visualization)
633 {
634 socketstream vis1, vis2, vis3, vis4, vis5;
635 common::VisualizeField(vis1, "localhost", 19916, surf_fit_gf0,
636 "Level Set", 0, 0, 300, 300);
637 common::VisualizeField(vis2, "localhost", 19916, mat,
638 "Materials", 300, 0, 300, 300);
639 common::VisualizeField(vis3, "localhost", 19916, surf_fit_mat_gf,
640 "Surface DOFs", 600, 0, 300, 300);
641 if (surf_bg_mesh)
642 {
643 common::VisualizeField(vis4, "localhost", 19916, *surf_fit_bg_gf0,
644 "Level Set - Background",
645 0, 400, 300, 300);
646 }
647 }
648 }
649
650 // Setup the final NonlinearForm.
651 ParNonlinearForm a(pfespace);
652 a.AddDomainIntegrator(tmop_integ);
653
654 // Compute the minimum det(J) of the starting mesh.
655 real_t min_detJ = infinity();
656 const int NE = pmesh->GetNE();
657 for (int i = 0; i < NE; i++)
658 {
659 const IntegrationRule &ir =
660 irules->Get(pfespace->GetFE(i)->GetGeomType(), quad_order);
662 for (int j = 0; j < ir.GetNPoints(); j++)
663 {
664 transf->SetIntPoint(&ir.IntPoint(j));
665 min_detJ = min(min_detJ, transf->Jacobian().Det());
666 }
667 }
668 MPI_Allreduce(MPI_IN_PLACE, &min_detJ, 1,
669 MPITypeMap<real_t>::mpi_type, MPI_MIN, MPI_COMM_WORLD);
670 if (myid == 0)
671 { cout << "Minimum det(J) of the original mesh is " << min_detJ << endl; }
672
673 MFEM_VERIFY(min_detJ > 0, "The input mesh is inverted, use mesh-optimizer.");
674
675 const real_t init_energy = a.GetParGridFunctionEnergy(x);
676 real_t init_metric_energy = init_energy;
677 if (surface_fit_const > 0.0)
678 {
679 surf_fit_coeff.constant = 0.0;
680 init_metric_energy = a.GetParGridFunctionEnergy(x);
681 surf_fit_coeff.constant = surface_fit_const;
682 }
683
684 // Fix all boundary nodes, or fix only a given component depending on the
685 // boundary attributes of the given mesh. Attributes 1/2/3 correspond to
686 // fixed x/y/z components of the node. Attribute dim+1 corresponds to
687 // an entirely fixed node.
688 if (move_bnd == false)
689 {
690 Array<int> ess_bdr(pmesh->bdr_attributes.Max());
691 ess_bdr = 1;
692 if (marking_type > 0)
693 {
694 ess_bdr[marking_type-1] = 0;
695 }
696 a.SetEssentialBC(ess_bdr);
697 }
698 else
699 {
700 int n = 0;
701 for (int i = 0; i < pmesh->GetNBE(); i++)
702 {
703 const int nd = pfespace->GetBE(i)->GetDof();
704 const int attr = pmesh->GetBdrElement(i)->GetAttribute();
705 MFEM_VERIFY(!(dim == 2 && attr == 3),
706 "Boundary attribute 3 must be used only for 3D meshes. "
707 "Adjust the attributes (1/2/3/4 for fixed x/y/z/all "
708 "components, rest for free nodes), or use -fix-bnd.");
709 if (attr == 1 || attr == 2 || attr == 3) { n += nd; }
710 if (attr == 4) { n += nd * dim; }
711 }
712 Array<int> ess_vdofs(n);
713 n = 0;
714 for (int i = 0; i < pmesh->GetNBE(); i++)
715 {
716 const int nd = pfespace->GetBE(i)->GetDof();
717 const int attr = pmesh->GetBdrElement(i)->GetAttribute();
718 pfespace->GetBdrElementVDofs(i, vdofs);
719 if (attr == 1) // Fix x components.
720 {
721 for (int j = 0; j < nd; j++)
722 { ess_vdofs[n++] = vdofs[j]; }
723 }
724 else if (attr == 2) // Fix y components.
725 {
726 for (int j = 0; j < nd; j++)
727 { ess_vdofs[n++] = vdofs[j+nd]; }
728 }
729 else if (attr == 3) // Fix z components.
730 {
731 for (int j = 0; j < nd; j++)
732 { ess_vdofs[n++] = vdofs[j+2*nd]; }
733 }
734 else if (attr == 4) // Fix all components.
735 {
736 for (int j = 0; j < vdofs.Size(); j++)
737 { ess_vdofs[n++] = vdofs[j]; }
738 }
739 }
740 a.SetEssentialVDofs(ess_vdofs);
741 }
742
743 // Setup the linear solver for the system's Jacobian.
744 Solver *S = NULL, *S_prec = NULL;
745#ifdef MFEM_USE_SINGLE
746 const real_t linsol_rtol = 1e-5;
747#else
748 const real_t linsol_rtol = 1e-12;
749#endif
750 if (lin_solver == 0)
751 {
752 S = new DSmoother(1, 1.0, max_lin_iter);
753 }
754 else if (lin_solver == 1)
755 {
756 CGSolver *cg = new CGSolver(MPI_COMM_WORLD);
757 cg->SetMaxIter(max_lin_iter);
758 cg->SetRelTol(linsol_rtol);
759 cg->SetAbsTol(0.0);
760 cg->SetPrintLevel(verbosity_level >= 2 ? 3 : -1);
761 S = cg;
762 }
763 else
764 {
765 MINRESSolver *minres = new MINRESSolver(MPI_COMM_WORLD);
766 minres->SetMaxIter(max_lin_iter);
767 minres->SetRelTol(linsol_rtol);
768 minres->SetAbsTol(0.0);
769 if (verbosity_level > 2) { minres->SetPrintLevel(1); }
770 else { minres->SetPrintLevel(verbosity_level == 2 ? 3 : -1); }
771 if (lin_solver == 3 || lin_solver == 4)
772 {
773 auto hs = new HypreSmoother;
774 hs->SetType((lin_solver == 3) ? HypreSmoother::Jacobi
775 /* */ : HypreSmoother::l1Jacobi, 1);
776 hs->SetPositiveDiagonal(true);
777 S_prec = hs;
778 minres->SetPreconditioner(*S_prec);
779 }
780 S = minres;
781 }
782
783 // Perform the nonlinear optimization.
784 const IntegrationRule &ir =
785 irules->Get(pmesh->GetTypicalElementGeometry(), quad_order);
786 TMOPNewtonSolver solver(pfespace->GetComm(), ir, solver_type);
787 if (surface_fit_adapt > 0.0)
788 {
789 solver.SetAdaptiveSurfaceFittingScalingFactor(surface_fit_adapt);
790 }
791 if (surface_fit_threshold > 0)
792 {
793 solver.SetSurfaceFittingMaxErrorLimit(surface_fit_threshold);
794 }
795 solver.SetSurfaceFittingConvergenceBasedOnError(!conv_residual);
796 if (conv_residual)
797 {
798 solver.SetSurfaceFittingWeightLimit(surf_fit_const_max);
799 }
800
801 // Provide all integration rules in case of a mixed mesh.
802 solver.SetIntegrationRules(*irules, quad_order);
803 if (solver_type == 0)
804 {
805 // Specify linear solver when we use a Newton-based solver.
806 solver.SetPreconditioner(*S);
807 }
808 solver.SetMaxIter(solver_iter);
809 solver.SetRelTol(solver_rtol);
810 solver.SetAbsTol(0.0);
811 solver.SetMinimumDeterminantThreshold(0.001*min_detJ);
812 solver.SetPrintLevel(verbosity_level >= 1 ? 1 : 0);
813 solver.SetOperator(a);
814 Vector b(0);
815 solver.Mult(b, x.GetTrueVector());
817
818 // Save the optimized mesh to a file. This output can be viewed later
819 // using GLVis: "glvis -m optimized -np num_mpi_tasks".
820 {
821 ostringstream mesh_name;
822 mesh_name << "optimized.mesh";
823 ofstream mesh_ofs(mesh_name.str().c_str());
824 mesh_ofs.precision(8);
825 pmesh->PrintAsSerial(mesh_ofs);
826 }
827
828 // Compute the final energy of the functional.
829 const real_t fin_energy = a.GetParGridFunctionEnergy(x);
830 real_t fin_metric_energy = fin_energy;
831 if (surface_fit_const > 0.0)
832 {
833 surf_fit_coeff.constant = 0.0;
834 fin_metric_energy = a.GetParGridFunctionEnergy(x);
835 surf_fit_coeff.constant = surface_fit_const;
836 }
837
838 if (myid == 0)
839 {
840 std::cout << std::scientific << std::setprecision(4);
841 cout << "Initial strain energy: " << init_energy
842 << " = metrics: " << init_metric_energy
843 << " + extra terms: " << init_energy - init_metric_energy << endl;
844 cout << " Final strain energy: " << fin_energy
845 << " = metrics: " << fin_metric_energy
846 << " + extra terms: " << fin_energy - fin_metric_energy << endl;
847 cout << "The strain energy decreased by: "
848 << (init_energy - fin_energy) * 100.0 / init_energy << " %." << endl;
849 }
850
851 if (surface_fit_const > 0.0)
852 {
853 adapt_surface->ComputeAtNewPosition(x, surf_fit_gf0,
854 x.FESpace()->GetOrdering());
855 if (visualization)
856 {
857 socketstream vis1, vis2, vis3;
858 common::VisualizeField(vis1, "localhost", 19916, surf_fit_gf0,
859 "Level Set", 000, 400, 300, 300);
860 common::VisualizeField(vis2, "localhost", 19916, mat,
861 "Materials", 300, 400, 300, 300);
862 common::VisualizeField(vis3, "localhost", 19916, surf_fit_mat_gf,
863 "Surface DOFs", 600, 400, 300, 300);
864 }
865 real_t err_avg, err_max;
866 tmop_integ->GetSurfaceFittingErrors(x, err_avg, err_max);
867 if (myid == 0)
868 {
869 std::cout << "Avg fitting error: " << err_avg << std::endl
870 << "Max fitting error: " << err_max << std::endl;
871 }
872 }
873
874 // Visualize the mesh displacement.
875 if (visualization)
876 {
877 x0 -= x;
878 socketstream vis;
879 common::VisualizeField(vis, "localhost", 19916, x0,
880 "Displacements", 900, 400, 300, 300, "jRmclA");
881 }
882
883 delete S;
884 delete S_prec;
885 delete adapt_surface;
886 delete adapt_grad_surface;
887 delete adapt_hess_surface;
888 delete ls_coeff;
889 delete surf_fit_hess;
890 delete surf_fit_hess_fes;
891 delete surf_fit_bg_hess;
892 delete surf_fit_bg_hess_fes;
893 delete surf_fit_grad;
894 delete surf_fit_grad_fes;
895 delete surf_fit_bg_grad;
896 delete surf_fit_bg_grad_fes;
897 delete surf_fit_bg_gf0;
898 delete surf_fit_bg_fes;
899 delete surf_fit_bg_fec;
900 delete target_c;
901 delete metric;
902 delete pfespace;
903 delete fec;
904 delete pmesh_surf_fit_bg;
905 delete pmesh;
906
907 return 0;
908}
virtual void ComputeAtNewPosition(const Vector &new_mesh_nodes, Vector &new_field, int nodes_ordering=Ordering::byNODES)=0
Perform field transfer between the original and a new mesh. The source mesh and field are given by Se...
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:68
int Size() const
Return the logical size of the array.
Definition array.hpp:147
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:830
Conjugate gradient method.
Definition solvers.hpp:538
A coefficient that is constant across space and time.
Data type for scaled Jacobi-type smoother of sparse matrix.
real_t Det() const
Definition densemat.cpp:516
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
Definition device.hpp:123
void Print(std::ostream &out=mfem::out)
Print the configuration of the MFEM virtual device object.
Definition device.cpp:297
const DenseMatrix & Jacobian()
Return the Jacobian matrix of the transformation at the currently set IntegrationPoint,...
Definition eltrans.hpp:132
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition eltrans.hpp:106
int GetAttribute() const
Return element's attribute.
Definition element.hpp:58
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
const FiniteElement * GetBE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th boundary fac...
Definition fespace.cpp:3881
Ordering::Type GetOrdering() const
Return the ordering method.
Definition fespace.hpp:876
DofTransformation * GetBdrElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for i'th boundary element. The returned indices are offsets int...
Definition fespace.cpp:348
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
Definition fe_base.hpp:331
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition fe_base.hpp:334
A general function coefficient.
Coefficient defined by a GridFunction. This coefficient is mesh dependent.
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
void SetTrueVector()
Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:147
void SetFromTrueVector()
Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:153
const Vector & GetTrueVector() const
Read only access to the (optional) internal true-dof Vector.
Definition gridfunc.hpp:133
FiniteElementSpace * FESpace()
Communicator performing operations within groups defined by a GroupTopology with arbitrary-size data ...
void Reduce(T *ldata, void(*Op)(OpData< T >)) const
Reduce within each group where the master is the root.
void Bcast(T *ldata, int layout) const
Broadcast within each group where the master is the root.
static void Max(OpData< T >)
Reduce operation Max, instantiated for int and double.
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:275
Parallel smoothers in hypre.
Definition hypre.hpp:1046
void SetType(HypreSmoother::Type type, int relax_times=1)
Set the relaxation type and number of sweeps.
Definition hypre.cpp:3608
@ l1Jacobi
l1-scaled Jacobi
Definition hypre.hpp:1106
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Definition hypre.cpp:33
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:100
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:256
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:259
Container class for integration rules.
Definition intrules.hpp:422
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
void SetRelTol(real_t rtol)
Definition solvers.hpp:229
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:72
void SetMaxIter(int max_it)
Definition solvers.hpp:231
void SetAbsTol(real_t atol)
Definition solvers.hpp:230
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:346
void SetOperator(const Operator &op) override
Also calls SetOperator for the preconditioner if there is one.
Definition solvers.hpp:812
MINRES method.
Definition solvers.hpp:653
void SetPreconditioner(Solver &pr) override
This should be called before SetOperator.
Definition solvers.hpp:665
Mesh data type.
Definition mesh.hpp:64
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:290
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Definition mesh.cpp:6531
int GetAttribute(int i) const
Return the attribute of element i.
Definition mesh.hpp:1389
Geometry::Type GetTypicalElementGeometry() const
If the local mesh is not empty, return GetElementGeometry(0); otherwise, return a typical Geometry pr...
Definition mesh.cpp:1528
void SetAttribute(int i, int attr)
Set the attribute of element i.
Definition mesh.cpp:7629
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1282
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
Definition mesh.hpp:1354
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
Builds the transformation defining the i-th element in ElTr. ElTr must be allocated in advance and wi...
Definition mesh.cpp:357
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:4481
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
Definition mesh.cpp:6473
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:9294
int GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1285
FaceElementTransformations * GetInteriorFaceTransformations(int FaceNo)
See GetFaceElementTransformations().
Definition mesh.cpp:1103
void EnsureNCMesh(bool simplices_nonconforming=false)
Definition mesh.cpp:10951
static Mesh MakeCartesian2D(int nx, int ny, Element::Type type, bool generate_edges=false, real_t sx=1.0, real_t sy=1.0, bool sfc_ordering=true)
Creates mesh for the rectangle [0,sx]x[0,sy], divided into nx*ny quadrilaterals if type = QUADRILATER...
Definition mesh.cpp:4471
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11295
static int WorldRank()
Return the MPI rank in 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...
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:29
MPI_Comm GetComm() const
Definition pfespace.hpp:334
GroupCommunicator & GroupComm()
Return a reference to the internal GroupCommunicator (on VDofs)
Definition pfespace.hpp:405
int GetFaceDofs(int i, Array< int > &dofs, int variant=0) const override
Definition pfespace.cpp:611
void Update(bool want_transform=true) override
const FiniteElement * GetFE(int i) const override
Definition pfespace.cpp:627
Class for parallel grid function.
Definition pgridfunc.hpp:50
void GetDerivative(int comp, int der_comp, ParGridFunction &der) const
Parallel version of GridFunction::GetDerivative(); see its documentation.
void ProjectDiscCoefficient(VectorCoefficient &coeff) override
Project a discontinuous vector coefficient as a grid function on a continuous finite element space....
ParFiniteElementSpace * ParFESpace() const
void ProjectCoefficient(Coefficient &coeff) override
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
void Update() override
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition pgridfunc.cpp:91
Class for parallel meshes.
Definition pmesh.hpp:34
void ExchangeFaceNbrData(Table *gr_sface, int *s2l_face)
Definition pmesh.cpp:2158
int GetNSharedFaces() const
Return the number of shared faces (3D), edges (2D), vertices (1D)
Definition pmesh.cpp:3152
void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1) override
Set the curvature of the mesh nodes using the given polynomial degree.
Definition pmesh.cpp:2006
void SetAttributes() override
Determine the sets of unique attribute values in domain and boundary elements.
Definition pmesh.cpp:1588
void SetNodalFESpace(FiniteElementSpace *nfes) override
Definition pmesh.cpp:2027
void Rebalance()
Definition pmesh.cpp:4008
int GetSharedFace(int sface) const
Return the local face index for the given shared face.
Definition pmesh.cpp:3171
FaceElementTransformations * GetSharedFaceTransformations(int sf, bool fill2=true)
Get the FaceElementTransformations for the given shared face (edge 2D) using the shared face index sf...
Definition pmesh.cpp:2922
void PrintAsSerial(std::ostream &out=mfem::out, const std::string &comments="") const
Definition pmesh.cpp:5280
void GetBoundingBox(Vector &p_min, Vector &p_max, int ref=2)
Definition pmesh.cpp:6153
Parallel non-linear operator on the true dofs.
Version of QuadraticFECollection with positive basis functions.
Definition fe_coll.hpp:918
Base class for solvers.
Definition operator.hpp:780
void SetAdaptiveSurfaceFittingScalingFactor(real_t factor)
void SetMinimumDeterminantThreshold(real_t threshold)
Set minimum determinant enforced during line-search.
void Mult(const Vector &b, Vector &x) const override
Optimizes the mesh positions given by x.
void SetPreconditioner(Solver &pr) override
This should be called before SetOperator.
void SetIntegrationRules(IntegrationRules &irules, int order)
Prescribe a set of integration rules; relevant for mixed meshes.
void SetSurfaceFittingMaxErrorLimit(real_t max_error)
Could be used with both error-based or residual-based convergence.
void SetSurfaceFittingConvergenceBasedOnError(bool mode)
Toggle convergence based on residual or error.
void SetSurfaceFittingWeightLimit(real_t weight)
Used for residual-based surface fitting termination.
A TMOP integrator class based on any given TMOP_QualityMetric and TargetConstructor.
Definition tmop.hpp:1885
void GetSurfaceFittingErrors(const Vector &d_loc, real_t &err_avg, real_t &err_max)
Definition tmop.cpp:3829
void EnableSurfaceFittingFromSource(const ParGridFunction &s_bg, ParGridFunction &s0, const Array< bool > &smarker, Coefficient &coeff, AdaptivityEvaluator &ae, const ParGridFunction &s_bg_grad, ParGridFunction &s0_grad, AdaptivityEvaluator &age, const ParGridFunction &s_bg_hess, ParGridFunction &s0_hess, AdaptivityEvaluator &ahe)
Fitting of certain DOFs in the current mesh to the zero level set of a function defined on another (f...
Definition tmop.cpp:3754
void SetIntegrationRules(IntegrationRules &irules, int order)
Prescribe a set of integration rules; relevant for mixed meshes.
Definition tmop.hpp:2180
void EnableSurfaceFitting(const GridFunction &s0, const Array< bool > &smarker, Coefficient &coeff, AdaptivityEvaluator &ae)
Fitting of certain DOFs to the zero level set of a function.
Definition tmop.cpp:3588
2D barrier shape (S) metric (not polyconvex).
Definition tmop.hpp:504
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition tmop.hpp:741
3D compound barrier Shape+Size (VS) metric (polyconvex, balanced).
Definition tmop.hpp:944
Abstract class for local mesh quality metrics in the target-matrix optimization paradigm (TMOP) by P....
Definition tmop.hpp:24
Base class representing target-matrix construction algorithms for mesh optimization via the target-ma...
Definition tmop.hpp:1481
void SetNodes(const GridFunction &n)
Set the nodes to be used in the target-matrix construction.
Definition tmop.hpp:1560
TargetType
Target-matrix construction algorithms supported by this class.
Definition tmop.hpp:1485
Vector data type.
Definition vector.hpp:82
int Size() const
Returns the size of the vector.
Definition vector.hpp:226
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:235
int dim
Definition ex24.cpp:53
int main()
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
real_t reactor(const Vector &x)
real_t csg_cubecylsph(const Vector &x)
void ModifyBoundaryAttributesForNodeMovement(ParMesh *pmesh, ParGridFunction &x)
void ModifyAttributeForMarkingDOFS(ParMesh *pmesh, ParGridFunction &mat, int attr_to_switch)
real_t squircle_level_set(const Vector &x)
void OptimizeMeshWithAMRAroundZeroLevelSet(ParMesh &pmesh, FunctionCoefficient &ls_coeff, int amr_iter, ParGridFunction &distance_s, const int quad_order=5, Array< ParGridFunction * > *pgf_to_update=NULL)
void ComputeScalarDistanceFromLevelSet(ParMesh &pmesh, FunctionCoefficient &ls_coeff, ParGridFunction &distance_s, const int nDiffuse=2, const int pLapOrder=5, const int pLapNewton=50)
real_t circle_level_set(const Vector &x)
int material_id(int el_id, const GridFunction &g)
IntegrationRules IntRulesLo(0, Quadrature1D::GaussLobatto)
void VisualizeField(socketstream &sock, const char *vishost, int visport, GridFunction &gf, const char *title, int x, int y, int w, int h, const char *keys, bool vec)
real_t infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
Definition vector.hpp:47
float real_t
Definition config.hpp:43
int material(Vector &x, Vector &xmin, Vector &xmax)
Definition shaper.cpp:53
Helper struct to convert a C++ type to an MPI type.