64 ParMesh &pmesh,
char *title,
int position)
73 sock.
open(
"localhost", 19916);
80 sock <<
"window_title '"<< title <<
"'\n"
82 << position <<
" " << 0 <<
" " << 600 <<
" " << 600 <<
"\n"
83 <<
"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());
109 const int NE = pfes->GetParMesh()->GetNE(),
dim = pfes->GetFE(0)->GetDim(),
110 dof = pfes->GetFE(0)->GetDof(), nsp = ir.GetNPoints();
116 bool x_out_ok =
false;
117 const double energy_in = nlf->
GetEnergy(x);
118 double scale = 1.0, energy_out;
119 double norm0 = Norm(r);
120 x_gf.MakeTRef(pfes, x_out, 0);
123 for (
int i = 0; i < 12; i++)
125 add(x, -scale, c, x_out);
126 x_gf.SetFromTrueVector();
129 if (energy_out > 1.2*energy_in || std::isnan(energy_out) != 0)
131 if (print_level >= 0)
132 { cout <<
"Scale = " << scale <<
" Increasing energy." << endl; }
133 scale *= 0.5;
continue;
137 for (
int i = 0; i < NE; i++)
139 pfes->GetElementVDofs(i, xdofs);
140 x_gf.GetSubVector(xdofs, posV);
141 for (
int j = 0; j < nsp; j++)
143 pfes->GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
145 if (Jpr.Det() <= 0.0) { jac_ok = 0;
goto break2; }
150 MPI_Allreduce(&jac_ok, &jac_ok_all, 1, MPI_INT, MPI_LAND,
155 if (print_level >= 0)
156 { cout <<
"Scale = " << scale <<
" Neg det(J) found." << endl; }
157 scale *= 0.5;
continue;
160 oper->Mult(x_out, r);
161 if (have_b) { r -= b; }
162 double norm = Norm(r);
164 if (norm > 1.2*norm0)
166 if (print_level >= 0)
167 { cout <<
"Scale = " << scale <<
" Norm increased." << endl; }
168 scale *= 0.5;
continue;
170 else { x_out_ok =
true;
break; }
173 if (print_level >= 0)
175 cout <<
"Energy decrease: "
176 << (energy_in - energy_out) / energy_in * 100.0
177 <<
"% with " << scale <<
" scaling." << endl;
180 if (x_out_ok ==
false) { scale = 0.0; }
198 virtual double ComputeScalingFactor(
const Vector &x,
const Vector &b)
const;
201 double DescentNewtonSolver::ComputeScalingFactor(
const Vector &x,
205 MFEM_VERIFY(nlf != NULL,
"invalid Operator subclass");
207 const int NE = pfes->GetParMesh()->GetNE(),
dim = pfes->GetFE(0)->GetDim(),
208 dof = pfes->GetFE(0)->GetDof(), nsp = ir.GetNPoints();
213 x_gf.MakeTRef(pfes, x.
GetData());
214 x_gf.SetFromTrueVector();
217 for (
int i = 0; i < NE; i++)
219 pfes->GetElementVDofs(i, xdofs);
220 x_gf.GetSubVector(xdofs, posV);
221 for (
int j = 0; j < nsp; j++)
223 pfes->GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
225 min_detJ = min(min_detJ, Jpr.Det());
229 MPI_Allreduce(&min_detJ, &min_detJ_all, 1, MPI_DOUBLE, MPI_MIN,
231 if (print_level >= 0)
232 { cout <<
"Minimum det(J) = " << min_detJ_all << endl; }
235 bool x_out_ok =
false;
237 double scale = 1.0, energy_out;
239 for (
int i = 0; i < 7; i++)
241 add(x, -scale, c, x_out);
244 if (energy_out > energy_in || std::isnan(energy_out) != 0)
248 else { x_out_ok =
true;
break; }
251 if (print_level >= 0)
253 cout <<
"Energy decrease: "
254 << (energy_in - energy_out) / energy_in * 100.0
255 <<
"% with " << scale <<
" scaling." << endl;
258 if (x_out_ok ==
false) {
return 0.0; }
268 int main (
int argc,
char *argv[])
272 MPI_Init(&argc, &argv);
273 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
274 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
277 const char *mesh_file =
"icf.mesh";
278 int mesh_poly_deg = 1;
284 double lim_const = 0.0;
287 int newton_iter = 10;
288 double newton_rtol = 1e-12;
290 int max_lin_iter = 100;
291 bool move_bnd =
true;
293 bool normalization =
false;
294 bool visualization =
true;
295 int verbosity_level = 0;
299 args.
AddOption(&mesh_file,
"-m",
"--mesh",
300 "Mesh file to use.");
301 args.
AddOption(&mesh_poly_deg,
"-o",
"--order",
302 "Polynomial degree of mesh finite element space.");
303 args.
AddOption(&rs_levels,
"-rs",
"--refine-serial",
304 "Number of times to refine the mesh uniformly in serial.");
305 args.
AddOption(&rp_levels,
"-rp",
"--refine-parallel",
306 "Number of times to refine the mesh uniformly in parallel.");
307 args.
AddOption(&jitter,
"-ji",
"--jitter",
308 "Random perturbation scaling factor.");
309 args.
AddOption(&metric_id,
"-mid",
"--metric-id",
310 "Mesh optimization metric:\n\t"
311 "1 : |T|^2 -- 2D shape\n\t"
312 "2 : 0.5|T|^2/tau-1 -- 2D shape (condition number)\n\t"
313 "7 : |T-T^-t|^2 -- 2D shape+size\n\t"
314 "9 : tau*|T-T^-t|^2 -- 2D shape+size\n\t"
315 "22 : 0.5(|T|^2-2*tau)/(tau-tau_0) -- 2D untangling\n\t"
316 "50 : 0.5|T^tT|^2/tau^2-1 -- 2D shape\n\t"
317 "55 : (tau-1)^2 -- 2D size\n\t"
318 "56 : 0.5(sqrt(tau)-1/sqrt(tau))^2 -- 2D size\n\t"
319 "58 : |T^tT|^2/(tau^2)-2*|T|^2/tau+2 -- 2D shape\n\t"
320 "77 : 0.5(tau-1/tau)^2 -- 2D size\n\t"
321 "211: (tau-1)^2-tau+sqrt(tau^2) -- 2D untangling\n\t"
322 "252: 0.5(tau-1)^2/(tau-tau_0) -- 2D untangling\n\t"
323 "301: (|T||T^-1|)/3-1 -- 3D shape\n\t"
324 "302: (|T|^2|T^-1|^2)/9-1 -- 3D shape\n\t"
325 "303: (|T|^2)/3*tau^(2/3)-1 -- 3D shape\n\t"
326 "315: (tau-1)^2 -- 3D size\n\t"
327 "316: 0.5(sqrt(tau)-1/sqrt(tau))^2 -- 3D size\n\t"
328 "321: |T-T^-t|^2 -- 3D shape+size\n\t"
329 "352: 0.5(tau-1)^2/(tau-tau_0) -- 3D untangling");
330 args.
AddOption(&target_id,
"-tid",
"--target-id",
331 "Target (ideal element) type:\n\t"
332 "1: Ideal shape, unit size\n\t"
333 "2: Ideal shape, equal size\n\t"
334 "3: Ideal shape, initial size");
335 args.
AddOption(&lim_const,
"-lc",
"--limit-const",
"Limiting constant.");
336 args.
AddOption(&quad_type,
"-qt",
"--quad-type",
337 "Quadrature rule type:\n\t"
338 "1: Gauss-Lobatto\n\t"
339 "2: Gauss-Legendre\n\t"
340 "3: Closed uniform points");
341 args.
AddOption(&quad_order,
"-qo",
"--quad_order",
342 "Order of the quadrature rule.");
343 args.
AddOption(&newton_iter,
"-ni",
"--newton-iters",
344 "Maximum number of Newton iterations.");
345 args.
AddOption(&newton_rtol,
"-rtol",
"--newton-rel-tolerance",
346 "Relative tolerance for the Newton solver.");
347 args.
AddOption(&lin_solver,
"-ls",
"--lin-solver",
348 "Linear solver: 0 - l1-Jacobi, 1 - CG, 2 - MINRES.");
349 args.
AddOption(&max_lin_iter,
"-li",
"--lin-iter",
350 "Maximum number of iterations in the linear solve.");
351 args.
AddOption(&move_bnd,
"-bnd",
"--move-boundary",
"-fix-bnd",
353 "Enable motion along horizontal and vertical boundaries.");
354 args.
AddOption(&combomet,
"-cmb",
"--combo-met",
"-no-cmb",
"--no-combo-met",
355 "Combination of metrics.");
356 args.
AddOption(&normalization,
"-nor",
"--normalization",
"-no-nor",
357 "--no-normalization",
358 "Make all terms in the optimization functional unitless.");
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)
421 double vol_loc = 0.0;
423 for (
int i = 0; i < pmesh->
GetNE(); i++)
429 for (
int j = 0; j < dofs.
Size(); j++)
431 h0(dofs[j]) = min(h0(dofs[j]), hi);
436 MPI_Allreduce(&vol_loc, &volume, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
437 const double small_phys_size = pow(volume, 1.0 / dim) / 100.0;
449 for (
int i = 0; i < pfespace->
GetNDofs(); i++)
451 for (
int d = 0; d <
dim; d++)
457 for (
int i = 0; i < pfespace->
GetNBE(); i++)
462 for (
int j = 0; j < vdofs.
Size(); j++) { rdm(vdofs[j]) = 0.0; }
473 ostringstream mesh_name;
474 mesh_name <<
"perturbed." << setfill(
'0') << setw(6) << myid;
475 ofstream mesh_ofs(mesh_name.str().c_str());
476 mesh_ofs.precision(8);
477 pmesh->
Print(mesh_ofs);
485 double tauval = -0.1;
509 if (myid == 0) { cout <<
"Unknown metric_id: " << metric_id << endl; }
519 if (myid == 0) { cout <<
"Unknown target_id: " << target_id << endl; }
534 case 2: ir = &
IntRules.
Get(geom_type, quad_order);
break;
537 if (myid == 0) { cout <<
"Unknown quad_type: " << quad_type << endl; }
541 { cout <<
"Quadrature points per cell: " << ir->
GetNPoints() << endl; }
551 if (normalization) { dist = small_phys_size; }
553 if (lim_const != 0.0) { he_nlf_integ->
EnableLimiting(x0, dist, lim_coeff); }
571 if (normalization) { MFEM_ABORT(
"Not implemented."); }
599 char title[] =
"Initial metric values";
600 vis_metric(mesh_poly_deg, *metric, *target_c, *pmesh, title, 0);
608 if (move_bnd ==
false)
618 for (
int i = 0; i < pmesh->
GetNBE(); i++)
621 MFEM_VERIFY(!(dim == 2 && attr == 3),
622 "Boundary attribute 3 must be used only for 3D meshes. "
623 "Adjust the attributes (1/2/3/4 for fixed x/y/z/all "
624 "components, rest for free nodes), or use -fix-bnd.");
625 if (attr == 1 || attr == 2 || attr == 3) { n += nd; }
626 if (attr == 4) { n += nd *
dim; }
630 for (
int i = 0; i < pmesh->
GetNBE(); i++)
636 for (
int j = 0; j < nd; j++)
637 { ess_vdofs[n++] = vdofs[j]; }
641 for (
int j = 0; j < nd; j++)
642 { ess_vdofs[n++] = vdofs[j+nd]; }
646 for (
int j = 0; j < nd; j++)
647 { ess_vdofs[n++] = vdofs[j+2*nd]; }
651 for (
int j = 0; j < vdofs.
Size(); j++)
652 { ess_vdofs[n++] = vdofs[j]; }
661 const double linsol_rtol = 1e-12;
666 else if (lin_solver == 1)
687 const int NE = pmesh->
GetNE();
688 for (
int i = 0; i < NE; i++)
698 MPI_Allreduce(&tauval, &minJ0, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
701 { cout <<
"Minimum det(J) of the original mesh is " << tauval << endl; }
708 newton =
new RelaxedNewtonSolver(*ir, pfespace);
710 { cout <<
"RelaxedNewtonSolver is used (as all det(J) > 0)." << endl; }
714 if ( (dim == 2 && metric_id != 22 && metric_id != 252) ||
715 (dim == 3 && metric_id != 352) )
718 { cout <<
"The mesh is inverted. Use an untangling metric." << endl; }
721 double h0min = h0.Min(), h0min_all;
722 MPI_Allreduce(&h0min, &h0min_all, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
723 tauval -= 0.01 * h0min_all;
724 newton =
new DescentNewtonSolver(*ir, pfespace);
726 { cout <<
"DescentNewtonSolver is used (as some det(J) < 0)." << endl; }
738 cout <<
"NewtonIteration: rtol = " << newton_rtol <<
" not achieved."
746 ostringstream mesh_name;
747 mesh_name <<
"optimized." << setfill(
'0') << setw(6) << myid;
748 ofstream mesh_ofs(mesh_name.str().c_str());
749 mesh_ofs.precision(8);
750 pmesh->
Print(mesh_ofs);
755 double metric_part = fin_energy;
756 if (lim_const != 0.0)
764 cout <<
"Initial strain energy: " << init_energy
765 <<
" = metrics: " << init_energy
766 <<
" + limiting term: " << 0.0 << endl;
767 cout <<
" Final strain energy: " << fin_energy
768 <<
" = metrics: " << metric_part
769 <<
" + limiting term: " << fin_energy - metric_part << endl;
770 cout <<
"The strain energy decreased by: " << setprecision(12)
771 << (init_energy - fin_energy) * 100.0 / init_energy <<
" %." << endl;
777 char title[] =
"Final metric values";
778 vis_metric(mesh_poly_deg, *metric, *target_c, *pmesh, title, 600);
788 sock.
open(
"localhost", 19916);
789 sock <<
"solution\n";
795 sock <<
"window_title 'Displacements'\n"
796 <<
"window_geometry "
797 << 1200 <<
" " << 0 <<
" " << 600 <<
" " << 600 <<
"\n"
798 <<
"keys jRmclA" << endl;
820 const double r = sqrt(x(0)*x(0) + x(1)*x(1) + 1e-12);
821 const double den = 0.002;
822 double l2 = 0.2 + 0.5 * (std::tanh((r-0.16)/den) - std::tanh((r-0.17)/den)
823 + 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 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.
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.
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.
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.
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
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)
void EnableLimiting(const GridFunction &n0, const GridFunction &dist, Coefficient &w0, TMOP_LimiterFunction *lfunc=NULL)
Adds a limiting term to the integrator (general version).
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)
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.
const Vector & GetTrueVector() const
Read only access to the (optional) internal true-dof Vector.
double GetElementSize(int i, int type=0)
Get the size of the i-th element relative to the perfect reference element.
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.
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)
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
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
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...
Class for parallel meshes.
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
void ParEnableNormalization(const ParGridFunction &x)
double GetElementVolume(int i)
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.