62 ParMesh &pmesh,
char *title,
int position)
71 sock.
open(
"localhost", 19916);
78 sock <<
"window_title '"<< title <<
"'\n"
80 << position <<
" " << 0 <<
" " << 600 <<
" " << 600 <<
"\n"
81 <<
"keys jRmclA" << endl;
99 virtual double ComputeScalingFactor(
const Vector &x,
const Vector &b)
const;
102 double RelaxedNewtonSolver::ComputeScalingFactor(
const Vector &x,
106 MFEM_VERIFY(nlf != NULL,
"invalid Operator subclass");
107 const bool have_b = (b.
Size() == Height());
111 dof = pfes->
GetFE(0)->
GetDof(), nsp = ir.GetNPoints();
118 bool x_out_ok =
false;
119 const double energy_in = nlf->
GetEnergy(x);
120 double scale = 1.0, energy_out;
121 double norm0 = Norm(r);
124 for (
int i = 0; i < 12; i++)
126 add(x, -scale, c, x_out);
127 x_out_gf.Distribute(x_out);
130 if (energy_out > 1.2*energy_in || isnan(energy_out) != 0)
132 if (print_level >= 0)
133 { cout <<
"Scale = " << scale <<
" Increasing energy." << endl; }
134 scale *= 0.5;
continue;
138 for (
int i = 0; i < NE; i++)
141 x_out_gf.GetSubVector(xdofs, posV);
142 for (
int j = 0; j < nsp; j++)
146 if (Jpr.Det() <= 0.0) { jac_ok = 0;
goto break2; }
151 MPI_Allreduce(&jac_ok, &jac_ok_all, 1, MPI_INT, MPI_LAND,
156 if (print_level >= 0)
157 { cout <<
"Scale = " << scale <<
" Neg det(J) found." << endl; }
158 scale *= 0.5;
continue;
161 oper->Mult(x_out, r);
162 if (have_b) { r -= b; }
163 double norm = Norm(r);
165 if (norm > 1.2*norm0)
167 if (print_level >= 0)
168 { cout <<
"Scale = " << scale <<
" Norm increased." << endl; }
169 scale *= 0.5;
continue;
171 else { x_out_ok =
true;
break; }
174 if (print_level >= 0)
176 cout <<
"Energy decrease: "
177 << (energy_in - energy_out) / energy_in * 100.0
178 <<
"% with " << scale <<
" scaling." << endl;
181 if (x_out_ok ==
false) { scale = 0.0; }
201 virtual double ComputeScalingFactor(
const Vector &x,
const Vector &b)
const;
204 double DescentNewtonSolver::ComputeScalingFactor(
const Vector &x,
208 MFEM_VERIFY(nlf != NULL,
"invalid Operator subclass");
212 dof = pfes->
GetFE(0)->
GetDof(), nsp = ir.GetNPoints();
220 double min_detJ = numeric_limits<double>::infinity();
221 for (
int i = 0; i < NE; i++)
224 x_gf.GetSubVector(xdofs, posV);
225 for (
int j = 0; j < nsp; j++)
229 min_detJ = min(min_detJ, Jpr.Det());
233 MPI_Allreduce(&min_detJ, &min_detJ_all, 1, MPI_DOUBLE, MPI_MIN,
235 if (print_level >= 0)
236 { cout <<
"Minimum det(J) = " << min_detJ_all << endl; }
239 bool x_out_ok =
false;
240 const double energy_in = nlf->
GetEnergy(x_gf);
241 double scale = 1.0, energy_out;
243 for (
int i = 0; i < 7; i++)
245 add(x, -scale, c, x_out);
248 if (energy_out > energy_in || isnan(energy_out) != 0)
252 else { x_out_ok =
true;
break; }
255 if (print_level >= 0)
257 cout <<
"Energy decrease: "
258 << (energy_in - energy_out) / energy_in * 100.0
259 <<
"% with " << scale <<
" scaling." << endl;
262 if (x_out_ok ==
false) {
return 0.0; }
272 int main (
int argc,
char *argv[])
276 MPI_Init(&argc, &argv);
277 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
278 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
281 const char *mesh_file =
"icf.mesh";
282 int mesh_poly_deg = 1;
288 double lim_const = 0.0;
291 int newton_iter = 10;
292 double newton_rtol = 1e-12;
294 int max_lin_iter = 100;
295 bool move_bnd =
true;
297 bool visualization =
true;
298 int verbosity_level = 0;
302 args.
AddOption(&mesh_file,
"-m",
"--mesh",
303 "Mesh file to use.");
304 args.
AddOption(&mesh_poly_deg,
"-o",
"--order",
305 "Polynomial degree of mesh finite element space.");
306 args.
AddOption(&rs_levels,
"-rs",
"--refine-serial",
307 "Number of times to refine the mesh uniformly in serial.");
308 args.
AddOption(&rp_levels,
"-rp",
"--refine-parallel",
309 "Number of times to refine the mesh uniformly in parallel.");
310 args.
AddOption(&jitter,
"-ji",
"--jitter",
311 "Random perturbation scaling factor.");
312 args.
AddOption(&metric_id,
"-mid",
"--metric-id",
313 "Mesh optimization metric:\n\t"
314 "1 : |T|^2 -- 2D shape\n\t"
315 "2 : 0.5|T|^2/tau-1 -- 2D shape (condition number)\n\t"
316 "7 : |T-T^-t|^2 -- 2D shape+size\n\t"
317 "9 : tau*|T-T^-t|^2 -- 2D shape+size\n\t"
318 "22 : 0.5(|T|^2-2*tau)/(tau-tau_0) -- 2D untangling\n\t"
319 "50 : 0.5|T^tT|^2/tau^2-1 -- 2D shape\n\t"
320 "55 : (tau-1)^2 -- 2D size\n\t"
321 "56 : 0.5(sqrt(tau)-1/sqrt(tau))^2 -- 2D size\n\t"
322 "58 : |T^tT|^2/(tau^2)-2*|T|^2/tau+2 -- 2D shape\n\t"
323 "77 : 0.5(tau-1/tau)^2 -- 2D size\n\t"
324 "211: (tau-1)^2-tau+sqrt(tau^2) -- 2D untangling\n\t"
325 "252: 0.5(tau-1)^2/(tau-tau_0) -- 2D untangling\n\t"
326 "301: (|T||T^-1|)/3-1 -- 3D shape\n\t"
327 "302: (|T|^2|T^-1|^2)/9-1 -- 3D shape\n\t"
328 "303: (|T|^2)/3*tau^(2/3)-1 -- 3D shape\n\t"
329 "315: (tau-1)^2 -- 3D size\n\t"
330 "316: 0.5(sqrt(tau)-1/sqrt(tau))^2 -- 3D size\n\t"
331 "321: |T-T^-t|^2 -- 3D shape+size\n\t"
332 "352: 0.5(tau-1)^2/(tau-tau_0) -- 3D untangling");
333 args.
AddOption(&target_id,
"-tid",
"--target-id",
334 "Target (ideal element) type:\n\t"
335 "1: Ideal shape, unit size\n\t"
336 "2: Ideal shape, equal size\n\t"
337 "3: Ideal shape, initial size");
338 args.
AddOption(&lim_const,
"-lc",
"--limit-const",
"Limiting constant.");
339 args.
AddOption(&quad_type,
"-qt",
"--quad-type",
340 "Quadrature rule type:\n\t"
341 "1: Gauss-Lobatto\n\t"
342 "2: Gauss-Legendre\n\t"
343 "3: Closed uniform points");
344 args.
AddOption(&quad_order,
"-qo",
"--quad_order",
345 "Order of the quadrature rule.");
346 args.
AddOption(&newton_iter,
"-ni",
"--newton-iters",
347 "Maximum number of Newton iterations.");
348 args.
AddOption(&newton_rtol,
"-rtol",
"--newton-rel-tolerance",
349 "Relative tolerance for the Newton solver.");
350 args.
AddOption(&lin_solver,
"-ls",
"--lin-solver",
351 "Linear solver: 0 - l1-Jacobi, 1 - CG, 2 - MINRES.");
352 args.
AddOption(&max_lin_iter,
"-li",
"--lin-iter",
353 "Maximum number of iterations in the linear solve.");
354 args.
AddOption(&move_bnd,
"-bnd",
"--move-boundary",
"-fix-bnd",
356 "Enable motion along horizontal and vertical boundaries.");
357 args.
AddOption(&combomet,
"-cmb",
"--combo-met",
"-no-cmb",
"--no-combo-met",
358 "Combination of metrics.");
359 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
360 "--no-visualization",
361 "Enable or disable GLVis visualization.");
362 args.
AddOption(&verbosity_level,
"-vl",
"--verbosity-level",
363 "Set the verbosity level - 0, 1, or 2.");
373 Mesh *mesh =
new Mesh(mesh_file, 1, 1,
false);
378 cout <<
"Mesh curvature: ";
380 else { cout <<
"(NONE)"; }
392 if (mesh_poly_deg <= 0)
418 h0 = numeric_limits<double>::infinity();
420 for (
int i = 0; i < pmesh->
GetNE(); i++)
425 for (
int j = 0; j < dofs.
Size(); j++)
441 for (
int i = 0; i < pfespace->
GetNDofs(); i++)
443 for (
int d = 0; d <
dim; d++)
449 for (
int i = 0; i < pfespace->
GetNBE(); i++)
454 for (
int j = 0; j < vdofs.
Size(); j++) { rdm(vdofs[j]) = 0.0; }
466 ostringstream mesh_name;
467 mesh_name <<
"perturbed." << setfill(
'0') << setw(6) << myid;
468 ofstream mesh_ofs(mesh_name.str().c_str());
469 mesh_ofs.precision(8);
470 pmesh->
Print(mesh_ofs);
478 double tauval = -0.1;
502 if (myid == 0) { cout <<
"Unknown metric_id: " << metric_id << endl; }
512 if (myid == 0) { cout <<
"Unknown target_id: " << target_id << endl; }
527 case 2: ir = &
IntRules.
Get(geom_type, quad_order);
break;
530 if (myid == 0) { cout <<
"Unknown quad_type: " << quad_type << endl; }
534 { cout <<
"Quadrature points per cell: " << ir->
GetNPoints() << endl; }
539 if (lim_const != 0.0) { he_nlf_integ->
EnableLimiting(x0, lim_coeff); }
574 if (myid == 0) { cout <<
"Initial strain energy: " << init_en << endl; }
579 char title[] =
"Initial metric values";
580 vis_metric(mesh_poly_deg, *metric, *target_c, *pmesh, title, 0);
588 if (move_bnd ==
false)
598 for (
int i = 0; i < pmesh->
GetNBE(); i++)
601 if (attr == 1 || attr == 2 || attr == 3) { n += nd; }
602 if (attr == 4) { n += nd *
dim; }
606 for (
int i = 0; i < pmesh->
GetNBE(); i++)
612 for (
int j = 0; j < nd; j++)
613 { ess_vdofs[n++] = vdofs[j]; }
617 for (
int j = 0; j < nd; j++)
618 { ess_vdofs[n++] = vdofs[j+nd]; }
622 for (
int j = 0; j < nd; j++)
623 { ess_vdofs[n++] = vdofs[j+2*nd]; }
627 for (
int j = 0; j < vdofs.
Size(); j++)
628 { ess_vdofs[n++] = vdofs[j]; }
637 const double linsol_rtol = 1e-12;
642 else if (lin_solver == 1)
662 tauval = numeric_limits<double>::infinity();
663 const int NE = pmesh->
GetNE();
664 for (
int i = 0; i < NE; i++)
674 MPI_Allreduce(&tauval, &minJ0, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
677 { cout <<
"Minimum det(J) of the original mesh is " << tauval << endl; }
684 newton =
new RelaxedNewtonSolver(*ir, MPI_COMM_WORLD);
686 { cout <<
"RelaxedNewtonSolver is used (as all det(J) > 0)." << endl; }
690 if ( (dim == 2 && metric_id != 22 && metric_id != 252) ||
691 (dim == 3 && metric_id != 352) )
694 { cout <<
"The mesh is inverted. Use an untangling metric." << endl; }
697 double h0min = h0.Min(), h0min_all;
698 MPI_Allreduce(&h0min, &h0min_all, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
699 tauval -= 0.01 * h0min_all;
700 newton =
new DescentNewtonSolver(*ir, MPI_COMM_WORLD);
702 { cout <<
"DescentNewtonSolver is used (as some det(J) < 0)." << endl; }
715 cout <<
"NewtonIteration: rtol = " << newton_rtol <<
" not achieved."
724 ostringstream mesh_name;
725 mesh_name <<
"optimized." << setfill(
'0') << setw(6) << myid;
726 ofstream mesh_ofs(mesh_name.str().c_str());
727 mesh_ofs.precision(8);
728 pmesh->
Print(mesh_ofs);
735 cout <<
"Final strain energy : " << fin_en << endl;
736 cout <<
"The strain energy decreased by: " << setprecision(12)
737 << (init_en - fin_en) * 100.0 / init_en <<
" %." << endl;
743 char title[] =
"Final metric values";
744 vis_metric(mesh_poly_deg, *metric, *target_c, *pmesh, title, 600);
754 sock.
open(
"localhost", 19916);
755 sock <<
"solution\n";
761 sock <<
"window_title 'Displacements'\n"
762 <<
"window_geometry "
763 << 1200 <<
" " << 0 <<
" " << 600 <<
" " << 600 <<
"\n"
764 <<
"keys jRmclA" << endl;
786 const double r = sqrt(x(0)*x(0) + x(1)*x(1) + 1e-12);
787 const double den = 0.002;
788 double l2 = 0.2 + 0.5 * (std::tanh((r-0.16)/den) - std::tanh((r-0.17)/den)
789 + std::tanh((r-0.23)/den) - 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.
Conjugate gradient method.
int GetDim() const
Returns the reference space dimension for the finite element.
int GetNDofs() const
Returns number of degrees of freedom.
Class for an integration rule - an Array of IntegrationPoint.
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.
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.
void GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
Shape, ideal barrier metric, 3D.
void SaveAsOne(std::ostream &out=mfem::out)
Merge the local grid functions.
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.
Abstract parallel finite element space.
virtual const SparseMatrix * GetRestrictionMatrix()
Get the R matrix which restricts a local dof vector to true dof vector.
void Randomize(int seed=0)
Set random values in the vector.
double weight_fun(const Vector &x)
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0)
Computes y = alpha * A * x + beta * y.
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.
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 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 PrintAsOne(std::ostream &out=mfem::out)
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)
HypreParMatrix * Dof_TrueDof_Matrix() const
The true dof-to-dof interpolation matrix.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Newton's method for solving F(x)=b for a given operator F.
virtual void Print(std::ostream &out=mfem::out) const
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.
int GetGeomType() const
Returns the Geometry::Type of the reference element.
double GetElementSize(int i, int type=0)
Wrapper for hypre's parallel vector class.
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.
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Area, ideal barrier metric, 2D.
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
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.
virtual void GetElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
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
int open(const char hostname[], int port)
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.
Class for parallel grid function.
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.
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
Base class representing target-matrix construction algorithms for mesh optimization via the target-ma...
virtual void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const =0
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Class for parallel meshes.
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
void ParallelAverage(Vector &tv) const
Returns the vector averaged on the true dofs.
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.