MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
tmop_tools.hpp
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#ifndef MFEM_TMOP_TOOLS_HPP
13#define MFEM_TMOP_TOOLS_HPP
14
15#include "bilinearform.hpp"
16#include "pbilinearform.hpp"
17#include "tmop.hpp"
18#include "gslib.hpp"
19
20namespace mfem
21{
22
23// Performs the full remap advection loop.
25{
26private:
27 RK4Solver ode_solver;
28 Vector nodes0;
29 Vector field0;
30 const real_t dt_scale;
31 const AssemblyLevel al;
33
34 void ComputeAtNewPositionScalar(const Vector &new_mesh_nodes,
35 Vector &new_field);
36
37public:
39 real_t timestep_scale = 0.5)
41 ode_solver(), nodes0(), field0(), dt_scale(timestep_scale), al(al) { }
42
43 void SetInitialField(const Vector &init_nodes,
44 const Vector &init_field) override;
45
47 {
48 MFEM_ABORT("Not supported by AdvectorCG.");
49 }
50
51 /// Perform advection-based remap. Assumptions:
52 /// nodes0 and new_mesh_nodes have the same topology;
53 /// new_field is of the same FE space as field0.
54 void ComputeAtNewPosition(const Vector &new_mesh_nodes,
55 Vector &new_field,
56 int nodes_ordering = Ordering::byNODES) override;
57
58 void ComputeAtGivenPositions(const Vector &positions,
59 Vector &values,
60 int p_ordering = Ordering::byNODES) override
61 {
62 MFEM_ABORT("Not supported by AdvectorCG.");
63 }
64
65 /// Set the memory type used for large memory allocations. This memory type
66 /// is used when constructing the AdvectorCGOper but currently only for the
67 /// parallel variant.
68 void SetMemoryType(MemoryType mt) { opt_mt = mt; }
69};
70
71#ifdef MFEM_USE_GSLIB
73{
74private:
75 Vector nodes0;
76 GridFunction field0_gf;
77 FindPointsGSLIB *finder;
78 // FE space for the nodes of the solution GridFunction, not owned.
79 const FiniteElementSpace *fes_new_field;
80
81public:
82 InterpolatorFP() : finder(NULL), fes_new_field(NULL) { }
83
84 void SetInitialField(const Vector &init_nodes,
85 const Vector &init_field) override;
86
87 /// Must be called when the FE space of the final field is different than
88 /// the FE space of the initial field. This also includes the case when
89 /// the initial and final fields are on different meshes.
90 virtual void SetNewFieldFESpace(const FiniteElementSpace &fes) override
91 {
92 fes_new_field = &fes;
93 }
94
95 /// Perform interpolation-based remap.
96 /// Assumptions when SetNewFieldFESpace() has not been called:
97 /// new_field is of the same FE space and mesh as field0.
98 void ComputeAtNewPosition(const Vector &new_mesh_nodes,
99 Vector &new_field,
100 int nodes_ordering = Ordering::byNODES) override;
101
102 /// Direct interpolation of field0_gf at the given positions.
103 void ComputeAtGivenPositions(const Vector &positions,
104 Vector &values,
105 int p_ordering = Ordering::byNODES) override;
106
108 {
109 return finder;
110 }
111
113 {
114 finder->FreeData();
115 delete finder;
116 }
117};
118#endif
119
120/// Performs a single remap advection step in serial.
122{
123protected:
124 const Vector &x0;
128 mutable BilinearForm M, K;
130
131public:
132 /** Here @a fes is the FESpace of the function that will be moved. Note
133 that Mult() moves the nodes of the mesh corresponding to @a fes. */
137
138 void Mult(const Vector &ind, Vector &di_dt) const override;
139};
140
141#ifdef MFEM_USE_MPI
142/// Performs a single remap advection step in parallel.
144{
145protected:
146 const Vector &x0;
152
153public:
154 /** Here @a pfes is the ParFESpace of the function that will be moved. Note
155 that Mult() moves the nodes of the mesh corresponding to @a pfes.
156 @a mt is used to set the memory type of the integrators. */
157 ParAdvectorCGOper(const Vector &x_start, GridFunction &vel,
161
162 void Mult(const Vector &ind, Vector &di_dt) const override;
163};
164#endif
165
167{
168protected:
169 // 0 - Newton, 1 - LBFGS.
172
173 // Starting mesh positions. Updated by the call to Mult().
174 // This solver solves for d, where the final mesh is x = x_0 + d.
175 // The displacement d is always the tdof vector of an H1 function.
176 // For periodic meshes, x_0 is an L2 function, and the relation
177 // x = x_0 + d is used only per element with appropriate transitions.
179 mutable bool periodic = false;
180
181 // Line search step is rejected if min(detJ) <= min_detJ_limit.
183
184 // Surface fitting variables.
185 mutable real_t surf_fit_avg_err_prvs = 10000.0;
187 mutable bool surf_fit_coeff_update = false;
191 mutable int surf_fit_adapt_count = 0;
195
196 // Minimum determinant over the whole mesh. Used for mesh untangling.
197 real_t *min_det_ptr = nullptr;
198 // Flag to compute minimum determinant and maximum metric in ProcessNewState,
199 // which is required for TMOP_WorstCaseUntangleOptimizer_Metric.
200 mutable bool compute_metric_quantile_flag = true;
201
202 // Quadrature points that are checked for negative Jacobians etc.
204 // These fields are relevant for mixed meshes.
207
209
211 {
212 if (IntegRules)
213 {
214 return IntegRules->Get(el.GetGeomType(), integ_order);
215 }
216 return ir;
217 }
218
219 real_t ComputeMinDet(const Vector &d_loc,
220 const FiniteElementSpace &fes) const;
221
222 real_t MinDetJpr_2D(const FiniteElementSpace *, const Vector &) const;
223 real_t MinDetJpr_3D(const FiniteElementSpace *, const Vector &) const;
224
225 /** @name Methods for adaptive surface fitting weight. */
226 ///@{
227 /// Get the average and maximum surface fitting error at the marked nodes.
228 /// If there is more than 1 TMOP integrator, we get the maximum of the
229 /// average and maximum error over all integrators.
230 virtual void GetSurfaceFittingError(const Vector &d_loc,
231 real_t &err_avg, real_t &err_max) const;
232
233 /// Update surface fitting weight as surf_fit_weight *= factor.
234 void UpdateSurfaceFittingWeight(real_t factor) const;
235
236 /// Get the surface fitting weight for all the TMOP integrators.
237 void GetSurfaceFittingWeight(Array<real_t> &weights) const;
238 ///@}
239
240 /// Check if surface fitting is enabled.
241 bool IsSurfaceFittingEnabled() const;
242
243public:
244#ifdef MFEM_USE_MPI
245 TMOPNewtonSolver(MPI_Comm comm, const IntegrationRule &irule, int type = 0)
246 : LBFGSSolver(comm), solver_type(type), parallel(true), x_0(),
247 ir(irule), IntegRules(NULL), integ_order(-1) { }
248#endif
249 TMOPNewtonSolver(const IntegrationRule &irule, int type = 0)
250 : LBFGSSolver(), solver_type(type), parallel(false), x_0(),
251 ir(irule), IntegRules(NULL), integ_order(-1) { }
252
253 /// Prescribe a set of integration rules; relevant for mixed meshes.
254 /** If called, this function has priority over the IntegrationRule given to
255 the constructor of the class. */
256 void SetIntegrationRules(IntegrationRules &irules, int order)
257 {
258 IntegRules = &irules;
259 integ_order = order;
260 }
261
262 void SetMinDetPtr(real_t *md_ptr) { min_det_ptr = md_ptr; }
263
264 /// Set the memory type for temporary memory allocations.
266
267 /// Compute scaling factor for the node movement direction using line-search.
268 /// We impose constraints on TMOP energy, gradient, minimum Jacobian of
269 /// the mesh, and (optionally) on the surface fitting error.
270 real_t ComputeScalingFactor(const Vector &d, const Vector &b) const override;
271
272 /// Given the new displacements @a d (tdof Vector), update
273 /// (i) discrete functions at new nodal positions, and
274 /// (ii) surface fitting weight.
275 void ProcessNewState(const Vector &dx) const override;
276
277 /** @name Methods for adaptive surface fitting.
278 \brief These methods control the behavior of the weight and the
279 termination of the solver. (Experimental)
280
281 Adaptive fitting weight: The weight is modified after each
282 TMOPNewtonSolver iteration as:
283 w_{k+1} = w_{k} * \ref surf_fit_scale_factor if the relative
284 change in average fitting error < \ref surf_fit_err_rel_change_limit.
285 When converging based on the residual, we enforce the fitting weight
286 to be at-most \ref surf_fit_weight_limit, and increase it only if the
287 fitting error is below user prescribed threshold
288 (\ref surf_fit_max_err_limit).
289 See \ref SetAdaptiveSurfaceFittingScalingFactor and
290 \ref SetAdaptiveSurfaceFittingRelativeChangeThreshold.
291
292 Note that the solver stops if the maximum surface fitting error
293 does not sufficiently decrease for \ref surf_fit_adapt_count_limit (default 10)
294 consecutive increments of the fitting weight during weight adaptation.
295 This typically occurs when the mesh cannot align with the level-set
296 without degrading element quality.
297 See \ref SetMaxNumberofIncrementsForAdaptiveFitting.
298
299 Convergence criterion: There are two modes, residual- and error-based,
300 which can be toggled using \ref SetSurfaceFittingConvergenceBasedOnError.
301
302 (i) Residual based (default): Stop when the norm of the gradient of the
303 TMOP objective reaches the prescribed tolerance. This method is best used
304 with a reasonable value for \ref surf_fit_weight_limit when the
305 adaptive surface fitting scheme is used. See method
306 \ref SetSurfaceFittingWeightLimit.
307
308 (ii) Error based: Stop when the maximum fitting error
309 reaches the user-prescribed threshold, \ref surf_fit_max_err_limit.
310 In this case, \ref surf_fit_weight_limit is ignored during weight
311 adaptation.
312 */
313 ///@{
315 {
316 MFEM_VERIFY(factor > 1.0, "Scaling factor must be greater than 1.");
317 surf_fit_scale_factor = factor;
318 }
323 /// Used for stopping based on the number of consecutive failed weight
324 /// adaptation iterations.
325 // TODO: Rename to SetMaxNumberofIncrementsForAdaptiveSurfaceFitting
326 // in future.
331 /// Used for error-based surface fitting termination.
337 /// Could be used with both error-based or residual-based convergence.
339 {
340 surf_fit_max_err_limit = max_error;
341 }
342 /// Used for residual-based surface fitting termination.
344 {
345 surf_fit_weight_limit = weight;
346 }
347 /// Toggle convergence based on residual or error.
349 {
352 {
353 MFEM_VERIFY(surf_fit_max_err_limit >= 0,
354 "Fitting error based convergence requires the user to "
355 "first set the error threshold."
356 "See SetTerminationWithMaxSurfaceFittingError");
357 }
358 }
359 ///@}
360
361 /// Set minimum determinant enforced during line-search.
363 {
364 min_detJ_limit = threshold;
365 }
366
367 /// Optimizes the mesh positions given by @a x.
368 void Mult(const Vector &b, Vector &x) const override;
369
370 void SetSolver(Solver &solver) override
371 {
372 if (solver_type == 0)
373 {
375 }
376 else if (solver_type == 1)
377 {
379 }
380 else { MFEM_ABORT("Invalid type"); }
381 }
382 void SetPreconditioner(Solver &pr) override { SetSolver(pr); }
383};
384
385void vis_tmop_metric_s(int order, TMOP_QualityMetric &qm,
386 const TargetConstructor &tc, Mesh &pmesh,
387 char *title, int position);
388#ifdef MFEM_USE_MPI
389void vis_tmop_metric_p(int order, TMOP_QualityMetric &qm,
390 const TargetConstructor &tc, ParMesh &pmesh,
391 char *title, int position);
392#endif
393
394// Compute x = x_0 + d, where x and x_0 are L2, d is H1p, all ldof vectors.
395void GetPeriodicPositions(const Vector &x_0, const Vector &dx,
396 const FiniteElementSpace &fesL2,
397 const FiniteElementSpace &fesH1, Vector &x);
398}
399
400#endif
FiniteElementSpace * fes
Definition tmop.hpp:1409
AdvectorCG(AssemblyLevel al=AssemblyLevel::LEGACY, real_t timestep_scale=0.5)
void SetInitialField(const Vector &init_nodes, const Vector &init_field) override
void SetNewFieldFESpace(const FiniteElementSpace &fes) override
void ComputeAtGivenPositions(const Vector &positions, Vector &values, int p_ordering=Ordering::byNODES) override
Using the source mesh and field given by SetInitialField(), compute corresponding values at specified...
void ComputeAtNewPosition(const Vector &new_mesh_nodes, Vector &new_field, int nodes_ordering=Ordering::byNODES) override
void SetMemoryType(MemoryType mt)
A "square matrix" operator for the associated FE space and BLFIntegrators The sum of all the BLFInteg...
FindPointsGSLIB can robustly evaluate a GridFunction on an arbitrary collection of points.
Definition gslib.hpp:67
virtual void FreeData()
Definition gslib.cpp:1128
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:244
Abstract class for all finite elements.
Definition fe_base.hpp:244
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
Definition fe_base.hpp:331
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:100
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 ComputeAtGivenPositions(const Vector &positions, Vector &values, int p_ordering=Ordering::byNODES) override
Direct interpolation of field0_gf at the given positions.
virtual void SetNewFieldFESpace(const FiniteElementSpace &fes) override
void SetInitialField(const Vector &init_nodes, const Vector &init_field) override
void ComputeAtNewPosition(const Vector &new_mesh_nodes, Vector &new_field, int nodes_ordering=Ordering::byNODES) override
const FindPointsGSLIB * GetFindPointsGSLIB() const
void SetSolver(Solver &solver) override
Set the linear solver for inverting the Jacobian.
Definition solvers.hpp:830
virtual void SetSolver(Solver &solver)
Set the linear solver for inverting the Jacobian.
Definition solvers.hpp:739
Performs a single remap advection step in parallel.
ParAdvectorCGOper(const Vector &x_start, GridFunction &vel, ParFiniteElementSpace &pfes, AssemblyLevel al=AssemblyLevel::LEGACY, MemoryType mt=MemoryType::DEFAULT)
VectorGridFunctionCoefficient u_coeff
void Mult(const Vector &ind, Vector &di_dt) const override
Operator application: y=A(x).
const AssemblyLevel al
Class for parallel bilinear form.
Abstract parallel finite element space.
Definition pfespace.hpp:29
The classical explicit forth-order Runge-Kutta method, RK4.
Definition ode.hpp:272
Performs a single remap advection step in serial.
VectorGridFunctionCoefficient u_coeff
SerialAdvectorCGOper(const Vector &x_start, GridFunction &vel, FiniteElementSpace &fes, AssemblyLevel al=AssemblyLevel::LEGACY)
const AssemblyLevel al
void Mult(const Vector &ind, Vector &di_dt) const override
Operator application: y=A(x).
Base class for solvers.
Definition operator.hpp:780
void SetAdaptiveSurfaceFittingScalingFactor(real_t factor)
real_t ComputeScalingFactor(const Vector &d, const Vector &b) const override
virtual void GetSurfaceFittingError(const Vector &d_loc, real_t &err_avg, real_t &err_max) const
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 SetTempMemoryType(MemoryType mt)
Set the memory type for temporary memory allocations.
bool IsSurfaceFittingEnabled() const
Check if surface fitting is enabled.
real_t MinDetJpr_3D(const FiniteElementSpace *, const Vector &) const
const IntegrationRule & ir
IntegrationRules * IntegRules
void SetIntegrationRules(IntegrationRules &irules, int order)
Prescribe a set of integration rules; relevant for mixed meshes.
const IntegrationRule & GetIntegrationRule(const FiniteElement &el) const
void UpdateSurfaceFittingWeight(real_t factor) const
Update surface fitting weight as surf_fit_weight *= factor.
real_t MinDetJpr_2D(const FiniteElementSpace *, const Vector &) const
void SetAdaptiveSurfaceFittingRelativeChangeThreshold(real_t threshold)
void SetMaxNumberofIncrementsForAdaptiveFitting(int count)
void ProcessNewState(const Vector &dx) const override
void SetMinDetPtr(real_t *md_ptr)
void SetSurfaceFittingMaxErrorLimit(real_t max_error)
Could be used with both error-based or residual-based convergence.
TMOPNewtonSolver(const IntegrationRule &irule, int type=0)
void SetSurfaceFittingConvergenceBasedOnError(bool mode)
Toggle convergence based on residual or error.
void SetTerminationWithMaxSurfaceFittingError(real_t max_error)
Used for error-based surface fitting termination.
real_t ComputeMinDet(const Vector &d_loc, const FiniteElementSpace &fes) const
void SetSolver(Solver &solver) override
Set the linear solver for inverting the Jacobian.
void GetSurfaceFittingWeight(Array< real_t > &weights) const
Get the surface fitting weight for all the TMOP integrators.
void SetSurfaceFittingWeightLimit(real_t weight)
Used for residual-based surface fitting termination.
TMOPNewtonSolver(MPI_Comm comm, const IntegrationRule &irule, int type=0)
Base abstract class for first order time dependent operators.
Definition operator.hpp:332
Vector coefficient defined by a vector GridFunction.
Vector data type.
Definition vector.hpp:82
real_t b
Definition lissajous.cpp:42
AssemblyLevel
Enumeration defining the assembly level for bilinear and nonlinear form classes derived from Operator...
void vis_tmop_metric_s(int order, TMOP_QualityMetric &qm, const TargetConstructor &tc, Mesh &mesh, char *title, int position)
void vis_tmop_metric_p(int order, TMOP_QualityMetric &qm, const TargetConstructor &tc, ParMesh &pmesh, char *title, int position)
void GetPeriodicPositions(const Vector &x_0, const Vector &dx, const FiniteElementSpace &fesL2, const FiniteElementSpace &fesH1, Vector &x)
float real_t
Definition config.hpp:43
MemoryType
Memory types supported by MFEM.
void vel(const Vector &x, real_t t, Vector &u)