64 Mesh &mesh,
char *title,
int position)
75 sock <<
"window_title '"<< title <<
"'\n"
77 << position <<
" " << 0 <<
" " << 600 <<
" " << 600 <<
"\n"
78 <<
"keys jRmclA" << endl;
91 : ir(irule), fes(f) { }
93 virtual double ComputeScalingFactor(
const Vector &x,
const Vector &b)
const;
96 double RelaxedNewtonSolver::ComputeScalingFactor(
const Vector &x,
100 MFEM_VERIFY(nlf != NULL,
"invalid Operator subclass");
101 const bool have_b = (b.
Size() == Height());
103 const int NE = fes->GetMesh()->GetNE(),
dim = fes->GetFE(0)->GetDim(),
104 dof = fes->GetFE(0)->GetDof(), nsp = ir.GetNPoints();
110 bool x_out_ok =
false;
111 const double energy_in = nlf->
GetEnergy(x);
112 double scale = 1.0, energy_out;
113 double norm0 = Norm(r);
114 x_gf.MakeTRef(fes, x_out, 0);
117 for (
int i = 0; i < 12; i++)
119 add(x, -scale, c, x_out);
120 x_gf.SetFromTrueVector();
123 if (energy_out > 1.2*energy_in || isnan(energy_out) != 0)
125 if (print_level >= 0)
126 { cout <<
"Scale = " << scale <<
" Increasing energy." << endl; }
127 scale *= 0.5;
continue;
131 for (
int i = 0; i < NE; i++)
133 fes->GetElementVDofs(i, xdofs);
134 x_gf.GetSubVector(xdofs, posV);
135 for (
int j = 0; j < nsp; j++)
137 fes->GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
139 if (Jpr.Det() <= 0.0) { jac_ok = 0;
goto break2; }
145 if (print_level >= 0)
146 { cout <<
"Scale = " << scale <<
" Neg det(J) found." << endl; }
147 scale *= 0.5;
continue;
150 oper->Mult(x_out, r);
151 if (have_b) { r -= b; }
152 double norm = Norm(r);
154 if (norm > 1.2*norm0)
156 if (print_level >= 0)
157 { cout <<
"Scale = " << scale <<
" Norm increased." << endl; }
158 scale *= 0.5;
continue;
160 else { x_out_ok =
true;
break; }
163 if (print_level >= 0)
165 cout <<
"Energy decrease: "
166 << (energy_in - energy_out) / energy_in * 100.0
167 <<
"% with " << scale <<
" scaling." << endl;
170 if (x_out_ok ==
false) { scale = 0.0; }
186 : ir(irule), fes(f) { }
188 virtual double ComputeScalingFactor(
const Vector &x,
const Vector &b)
const;
191 double DescentNewtonSolver::ComputeScalingFactor(
const Vector &x,
195 MFEM_VERIFY(nlf != NULL,
"invalid Operator subclass");
197 const int NE = fes->GetMesh()->GetNE(),
dim = fes->GetFE(0)->GetDim(),
198 dof = fes->GetFE(0)->GetDof(), nsp = ir.GetNPoints();
203 x_gf.MakeTRef(fes, x.
GetData());
204 x_gf.SetFromTrueVector();
207 for (
int i = 0; i < NE; i++)
209 fes->GetElementVDofs(i, xdofs);
210 x_gf.GetSubVector(xdofs, posV);
211 for (
int j = 0; j < nsp; j++)
213 fes->GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
215 min_detJ = min(min_detJ, Jpr.Det());
218 cout <<
"Minimum det(J) = " << min_detJ << endl;
221 bool x_out_ok =
false;
223 double scale = 1.0, energy_out;
225 for (
int i = 0; i < 7; i++)
227 add(x, -scale, c, x_out);
230 if (energy_out > energy_in || isnan(energy_out) != 0)
234 else { x_out_ok =
true;
break; }
237 cout <<
"Energy decrease: " << (energy_in - energy_out) / energy_in * 100.0
238 <<
"% with " << scale <<
" scaling." << endl;
240 if (x_out_ok ==
false) {
return 0.0;}
250 int main (
int argc,
char *argv[])
253 const char *mesh_file =
"icf.mesh";
254 int mesh_poly_deg = 1;
259 double lim_const = 0.0;
262 int newton_iter = 10;
263 double newton_rtol = 1e-12;
265 int max_lin_iter = 100;
266 bool move_bnd =
true;
268 bool visualization =
true;
269 int verbosity_level = 0;
273 args.
AddOption(&mesh_file,
"-m",
"--mesh",
274 "Mesh file to use.");
275 args.
AddOption(&mesh_poly_deg,
"-o",
"--order",
276 "Polynomial degree of mesh finite element space.");
277 args.
AddOption(&rs_levels,
"-rs",
"--refine-serial",
278 "Number of times to refine the mesh uniformly in serial.");
279 args.
AddOption(&jitter,
"-ji",
"--jitter",
280 "Random perturbation scaling factor.");
281 args.
AddOption(&metric_id,
"-mid",
"--metric-id",
282 "Mesh optimization metric:\n\t"
283 "1 : |T|^2 -- 2D shape\n\t"
284 "2 : 0.5|T|^2/tau-1 -- 2D shape (condition number)\n\t"
285 "7 : |T-T^-t|^2 -- 2D shape+size\n\t"
286 "9 : tau*|T-T^-t|^2 -- 2D shape+size\n\t"
287 "22 : 0.5(|T|^2-2*tau)/(tau-tau_0) -- 2D untangling\n\t"
288 "50 : 0.5|T^tT|^2/tau^2-1 -- 2D shape\n\t"
289 "55 : (tau-1)^2 -- 2D size\n\t"
290 "56 : 0.5(sqrt(tau)-1/sqrt(tau))^2 -- 2D size\n\t"
291 "58 : |T^tT|^2/(tau^2)-2*|T|^2/tau+2 -- 2D shape\n\t"
292 "77 : 0.5(tau-1/tau)^2 -- 2D size\n\t"
293 "211: (tau-1)^2-tau+sqrt(tau^2) -- 2D untangling\n\t"
294 "252: 0.5(tau-1)^2/(tau-tau_0) -- 2D untangling\n\t"
295 "301: (|T||T^-1|)/3-1 -- 3D shape\n\t"
296 "302: (|T|^2|T^-1|^2)/9-1 -- 3D shape\n\t"
297 "303: (|T|^2)/3*tau^(2/3)-1 -- 3D shape\n\t"
298 "315: (tau-1)^2 -- 3D size\n\t"
299 "316: 0.5(sqrt(tau)-1/sqrt(tau))^2 -- 3D size\n\t"
300 "321: |T-T^-t|^2 -- 3D shape+size\n\t"
301 "352: 0.5(tau-1)^2/(tau-tau_0) -- 3D untangling");
302 args.
AddOption(&target_id,
"-tid",
"--target-id",
303 "Target (ideal element) type:\n\t"
304 "1: Ideal shape, unit size\n\t"
305 "2: Ideal shape, equal size\n\t"
306 "3: Ideal shape, initial size");
307 args.
AddOption(&lim_const,
"-lc",
"--limit-const",
"Limiting constant.");
308 args.
AddOption(&quad_type,
"-qt",
"--quad-type",
309 "Quadrature rule type:\n\t"
310 "1: Gauss-Lobatto\n\t"
311 "2: Gauss-Legendre\n\t"
312 "3: Closed uniform points");
313 args.
AddOption(&quad_order,
"-qo",
"--quad_order",
314 "Order of the quadrature rule.");
315 args.
AddOption(&newton_iter,
"-ni",
"--newton-iters",
316 "Maximum number of Newton iterations.");
317 args.
AddOption(&newton_rtol,
"-rtol",
"--newton-rel-tolerance",
318 "Relative tolerance for the Newton solver.");
319 args.
AddOption(&lin_solver,
"-ls",
"--lin-solver",
320 "Linear solver: 0 - l1-Jacobi, 1 - CG, 2 - MINRES.");
321 args.
AddOption(&max_lin_iter,
"-li",
"--lin-iter",
322 "Maximum number of iterations in the linear solve.");
323 args.
AddOption(&move_bnd,
"-bnd",
"--move-boundary",
"-fix-bnd",
325 "Enable motion along horizontal and vertical boundaries.");
326 args.
AddOption(&combomet,
"-cmb",
"--combo-met",
"-no-cmb",
"--no-combo-met",
327 "Combination of metrics.");
328 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
329 "--no-visualization",
330 "Enable or disable GLVis visualization.");
331 args.
AddOption(&verbosity_level,
"-vl",
"--verbosity-level",
332 "Set the verbosity level - 0, 1, or 2.");
342 Mesh *mesh =
new Mesh(mesh_file, 1, 1,
false);
345 cout <<
"Mesh curvature: ";
347 else { cout <<
"(NONE)"; }
355 if (mesh_poly_deg <= 0)
382 for (
int i = 0; i < mesh->
GetNE(); i++)
387 for (
int j = 0; j < dofs.
Size(); j++)
403 for (
int i = 0; i < fespace->
GetNDofs(); i++)
405 for (
int d = 0; d <
dim; d++)
411 for (
int i = 0; i < fespace->
GetNBE(); i++)
416 for (
int j = 0; j < vdofs.
Size(); j++) { rdm(vdofs[j]) = 0.0; }
426 ofstream mesh_ofs(
"perturbed.mesh");
427 mesh->
Print(mesh_ofs);
435 double tauval = -0.1;
458 default: cout <<
"Unknown metric_id: " << metric_id << endl;
return 3;
466 default: cout <<
"Unknown target_id: " << target_id << endl;
467 delete metric;
return 3;
479 case 2: ir = &
IntRules.
Get(geom_type, quad_order);
break;
481 default: cout <<
"Unknown quad_type: " << quad_type << endl;
482 delete he_nlf_integ;
return 3;
484 cout <<
"Quadrature points per cell: " << ir->
GetNPoints() << endl;
489 if (lim_const != 0.0) { he_nlf_integ->
EnableLimiting(x0, lim_coeff); }
523 cout <<
"Initial strain energy: " << init_en << endl;
528 char title[] =
"Initial metric values";
529 vis_metric(mesh_poly_deg, *metric, *target_c, *mesh, title, 0);
537 if (move_bnd ==
false)
547 for (
int i = 0; i < mesh->
GetNBE(); i++)
550 MFEM_VERIFY(!(dim == 2 && attr == 3),
551 "Boundary attribute 3 must be used only for 3D meshes. "
552 "Adjust the attributes (1/2/3/4 for fixed x/y/z/all "
553 "components, rest for free nodes), or use -fix-bnd.");
554 if (attr == 1 || attr == 2 || attr == 3) { n += nd; }
555 if (attr == 4) { n += nd *
dim; }
559 for (
int i = 0; i < mesh->
GetNBE(); i++)
565 for (
int j = 0; j < nd; j++)
566 { ess_vdofs[n++] = vdofs[j]; }
570 for (
int j = 0; j < nd; j++)
571 { ess_vdofs[n++] = vdofs[j+nd]; }
575 for (
int j = 0; j < nd; j++)
576 { ess_vdofs[n++] = vdofs[j+2*nd]; }
580 for (
int j = 0; j < vdofs.
Size(); j++)
581 { ess_vdofs[n++] = vdofs[j]; }
590 const double linsol_rtol = 1e-12;
595 else if (lin_solver == 1)
616 const int NE = mesh->
GetNE();
617 for (
int i = 0; i < NE; i++)
626 cout <<
"Minimum det(J) of the original mesh is " << tauval << endl;
633 newton =
new RelaxedNewtonSolver(*ir, fespace);
634 cout <<
"The RelaxedNewtonSolver is used (as all det(J)>0)." << endl;
638 if ( (dim == 2 && metric_id != 22 && metric_id != 252) ||
639 (dim == 3 && metric_id != 352) )
641 cout <<
"The mesh is inverted. Use an untangling metric." << endl;
644 tauval -= 0.01 * h0.Min();
645 newton =
new DescentNewtonSolver(*ir, fespace);
646 cout <<
"The DescentNewtonSolver is used (as some det(J)<0)." << endl;
658 cout <<
"NewtonIteration: rtol = " << newton_rtol <<
" not achieved."
666 ofstream mesh_ofs(
"optimized.mesh");
667 mesh_ofs.precision(14);
668 mesh->
Print(mesh_ofs);
673 cout <<
"Final strain energy : " << fin_en << endl;
674 cout <<
"The strain energy decreased by: " << setprecision(12)
675 << (init_en - fin_en) * 100.0 / init_en <<
" %." << endl;
680 char title[] =
"Final metric values";
681 vis_metric(mesh_poly_deg, *metric, *target_c, *mesh, title, 600);
689 sock <<
"solution\n";
693 sock <<
"window_title 'Displacements'\n"
694 <<
"window_geometry "
695 << 1200 <<
" " << 0 <<
" " << 600 <<
" " << 600 <<
"\n"
696 <<
"keys jRmclA" << endl;
716 const double r = sqrt(x(0)*x(0) + x(1)*x(1) + 1e-12);
717 const double den = 0.002;
718 double l2 = 0.2 + 0.5*std::tanh((r-0.16)/den) - 0.5*std::tanh((r-0.17)/den)
719 + 0.5*std::tanh((r-0.23)/den) - 0.5*std::tanh((r-0.24)/den);
int GetNPoints() const
Returns the number of the points in the integration rule.
int Size() const
Logical size of the array.
Shifted barrier form of metric 56 (area, ideal barrier metric), 2D.
Shifted barrier form of 3D metric 16 (volume, ideal barrier metric), 3D.
virtual void Print(std::ostream &out=mfem::out) const
Conjugate gradient method.
int GetNDofs() const
Returns number of degrees of freedom.
Class for an integration rule - an Array of IntegrationPoint.
Class for grid function - Vector with associated FE space.
int DofToVDof(int dof, int vd, int ndofs=-1) const
Shape & volume, ideal barrier metric, 3D.
Data type for scaled Jacobi-type smoother of sparse matrix.
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
void SetFromTrueVector()
Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
Subclass constant coefficient.
int GetNBE() const
Returns number of boundary elements.
void InterpolateTMOP_QualityMetric(TMOP_QualityMetric &metric, const TargetConstructor &tc, const Mesh &mesh, GridFunction &metric_gf)
Interpolates the metric's values at the nodes of metric_gf.
Shape, ideal barrier metric, 3D.
Container class for integration rules.
Data type dense matrix using column-major storage.
Shape, ideal barrier metric, 3D.
int Size() const
Returns the size of the vector.
void SetVolumeScale(double vol_scale)
Used by target type IDEAL_SHAPE_EQUAL_SIZE. The default volume scale is 1.
Shape, ideal barrier metric, 2D.
Area, ideal barrier metric, 2D.
int GetNE() const
Returns number of elements.
void Randomize(int seed=0)
Set random values in the vector.
int main(int argc, char *argv[])
double * GetData() const
Return a pointer to the beginning of the Vector data.
double weight_fun(const Vector &x)
Shape & area, ideal barrier metric, 2D.
void vis_metric(int order, TMOP_QualityMetric &qm, const TargetConstructor &tc, Mesh &mesh, char *title, int position)
Shifted barrier form of metric 2 (shape, ideal barrier metric), 2D.
void add(const Vector &v1, const Vector &v2, Vector &v)
Shape, ideal barrier metric, 2D.
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
Abstract class for local mesh quality metrics in the target-matrix optimization paradigm (TMOP) by P...
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
void SetTrueVector()
Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
void SetPrintLevel(int print_lvl)
int GetNBE() const
Returns number of boundary elements in the mesh.
void SetCoefficient(Coefficient &w1)
Sets a scaling Coefficient for the quality metric term of the integrator.
Volume, ideal barrier metric, 3D.
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
IntegrationRules IntRulesLo(0, Quadrature1D::GaussLobatto)
void SetNodes(const GridFunction &n)
Set the nodes to be used in the target-matrix construction.
void SetMaxIter(int max_it)
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
virtual void GetElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
Newton's method for solving F(x)=b for a given operator F.
Version of QuadraticFECollection with positive basis functions.
int GetAttribute() const
Return element's attribute.
void SetNodalFESpace(FiniteElementSpace *nfes)
void PrintUsage(std::ostream &out) const
virtual void Mult(const Vector &b, Vector &x) const
Solve the nonlinear system with right-hand side b.
const Vector & GetTrueVector() const
Read only access to the (optional) internal true-dof Vector.
int GetGeomType() const
Returns the Geometry::Type of the reference element.
double GetElementSize(int i, int type=0)
void SetAbsTol(double atol)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void SetRelTol(double rtol)
Shape, ideal barrier metric, 2D.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Area, ideal barrier metric, 2D.
Base class Coefficient that may optionally depend on time.
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)
void EnableLimiting(const GridFunction &n0, Coefficient &w0)
Adds a limiting term to the integrator.
Shape & area metric, 2D.
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement associated with i'th element.
void PrintOptions(std::ostream &out) const
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
class for C-function coefficient
void MultAtB(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &AtB)
Multiply the transpose of a matrix A with a matrix B: At*B.
IntegrationRules IntRulesCU(0, Quadrature1D::ClosedUniform)
void GetNodes(Vector &node_coord) const
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Arbitrary order H1-conforming (continuous) finite elements.
TargetType
Target-matrix construction algorithms supported by this class.
const FiniteElement * GetBE(int i) const
Returns pointer to the FiniteElement for the i'th boundary element.
void GetBdrElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom for i'th boundary element.
Base class representing target-matrix construction algorithms for mesh optimization via the target-ma...
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
const Element * GetBdrElement(int i) const
Shape, ideal barrier metric, 3D.
Metric without a type, 2D.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
Arbitrary order "L2-conforming" discontinuous finite elements.
A TMOP integrator class based on any given TMOP_QualityMetric and TargetConstructor.