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 || 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 || 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 visualization =
true;
294 int verbosity_level = 0;
298 args.
AddOption(&mesh_file,
"-m",
"--mesh",
299 "Mesh file to use.");
300 args.
AddOption(&mesh_poly_deg,
"-o",
"--order",
301 "Polynomial degree of mesh finite element space.");
302 args.
AddOption(&rs_levels,
"-rs",
"--refine-serial",
303 "Number of times to refine the mesh uniformly in serial.");
304 args.
AddOption(&rp_levels,
"-rp",
"--refine-parallel",
305 "Number of times to refine the mesh uniformly in parallel.");
306 args.
AddOption(&jitter,
"-ji",
"--jitter",
307 "Random perturbation scaling factor.");
308 args.
AddOption(&metric_id,
"-mid",
"--metric-id",
309 "Mesh optimization metric:\n\t"
310 "1 : |T|^2 -- 2D shape\n\t"
311 "2 : 0.5|T|^2/tau-1 -- 2D shape (condition number)\n\t"
312 "7 : |T-T^-t|^2 -- 2D shape+size\n\t"
313 "9 : tau*|T-T^-t|^2 -- 2D shape+size\n\t"
314 "22 : 0.5(|T|^2-2*tau)/(tau-tau_0) -- 2D untangling\n\t"
315 "50 : 0.5|T^tT|^2/tau^2-1 -- 2D shape\n\t"
316 "55 : (tau-1)^2 -- 2D size\n\t"
317 "56 : 0.5(sqrt(tau)-1/sqrt(tau))^2 -- 2D size\n\t"
318 "58 : |T^tT|^2/(tau^2)-2*|T|^2/tau+2 -- 2D shape\n\t"
319 "77 : 0.5(tau-1/tau)^2 -- 2D size\n\t"
320 "211: (tau-1)^2-tau+sqrt(tau^2) -- 2D untangling\n\t"
321 "252: 0.5(tau-1)^2/(tau-tau_0) -- 2D untangling\n\t"
322 "301: (|T||T^-1|)/3-1 -- 3D shape\n\t"
323 "302: (|T|^2|T^-1|^2)/9-1 -- 3D shape\n\t"
324 "303: (|T|^2)/3*tau^(2/3)-1 -- 3D shape\n\t"
325 "315: (tau-1)^2 -- 3D size\n\t"
326 "316: 0.5(sqrt(tau)-1/sqrt(tau))^2 -- 3D size\n\t"
327 "321: |T-T^-t|^2 -- 3D shape+size\n\t"
328 "352: 0.5(tau-1)^2/(tau-tau_0) -- 3D untangling");
329 args.
AddOption(&target_id,
"-tid",
"--target-id",
330 "Target (ideal element) type:\n\t"
331 "1: Ideal shape, unit size\n\t"
332 "2: Ideal shape, equal size\n\t"
333 "3: Ideal shape, initial size");
334 args.
AddOption(&lim_const,
"-lc",
"--limit-const",
"Limiting constant.");
335 args.
AddOption(&quad_type,
"-qt",
"--quad-type",
336 "Quadrature rule type:\n\t"
337 "1: Gauss-Lobatto\n\t"
338 "2: Gauss-Legendre\n\t"
339 "3: Closed uniform points");
340 args.
AddOption(&quad_order,
"-qo",
"--quad_order",
341 "Order of the quadrature rule.");
342 args.
AddOption(&newton_iter,
"-ni",
"--newton-iters",
343 "Maximum number of Newton iterations.");
344 args.
AddOption(&newton_rtol,
"-rtol",
"--newton-rel-tolerance",
345 "Relative tolerance for the Newton solver.");
346 args.
AddOption(&lin_solver,
"-ls",
"--lin-solver",
347 "Linear solver: 0 - l1-Jacobi, 1 - CG, 2 - MINRES.");
348 args.
AddOption(&max_lin_iter,
"-li",
"--lin-iter",
349 "Maximum number of iterations in the linear solve.");
350 args.
AddOption(&move_bnd,
"-bnd",
"--move-boundary",
"-fix-bnd",
352 "Enable motion along horizontal and vertical boundaries.");
353 args.
AddOption(&combomet,
"-cmb",
"--combo-met",
"-no-cmb",
"--no-combo-met",
354 "Combination of metrics.");
355 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
356 "--no-visualization",
357 "Enable or disable GLVis visualization.");
358 args.
AddOption(&verbosity_level,
"-vl",
"--verbosity-level",
359 "Set the verbosity level - 0, 1, or 2.");
369 Mesh *mesh =
new Mesh(mesh_file, 1, 1,
false);
374 cout <<
"Mesh curvature: ";
376 else { cout <<
"(NONE)"; }
388 if (mesh_poly_deg <= 0)
416 for (
int i = 0; i < pmesh->
GetNE(); i++)
421 for (
int j = 0; j < dofs.
Size(); j++)
437 for (
int i = 0; i < pfespace->
GetNDofs(); i++)
439 for (
int d = 0; d <
dim; d++)
445 for (
int i = 0; i < pfespace->
GetNBE(); i++)
450 for (
int j = 0; j < vdofs.
Size(); j++) { rdm(vdofs[j]) = 0.0; }
461 ostringstream mesh_name;
462 mesh_name <<
"perturbed." << setfill(
'0') << setw(6) << myid;
463 ofstream mesh_ofs(mesh_name.str().c_str());
464 mesh_ofs.precision(8);
465 pmesh->
Print(mesh_ofs);
473 double tauval = -0.1;
497 if (myid == 0) { cout <<
"Unknown metric_id: " << metric_id << endl; }
507 if (myid == 0) { cout <<
"Unknown target_id: " << target_id << endl; }
522 case 2: ir = &
IntRules.
Get(geom_type, quad_order);
break;
525 if (myid == 0) { cout <<
"Unknown quad_type: " << quad_type << endl; }
529 { cout <<
"Quadrature points per cell: " << ir->
GetNPoints() << endl; }
534 if (lim_const != 0.0) { he_nlf_integ->
EnableLimiting(x0, lim_coeff); }
570 if (myid == 0) { cout <<
"Initial strain energy: " << init_en << endl; }
575 char title[] =
"Initial metric values";
576 vis_metric(mesh_poly_deg, *metric, *target_c, *pmesh, title, 0);
584 if (move_bnd ==
false)
594 for (
int i = 0; i < pmesh->
GetNBE(); i++)
597 MFEM_VERIFY(!(dim == 2 && attr == 3),
598 "Boundary attribute 3 must be used only for 3D meshes. "
599 "Adjust the attributes (1/2/3/4 for fixed x/y/z/all "
600 "components, rest for free nodes), or use -fix-bnd.");
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)
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, pfespace);
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, pfespace);
702 { cout <<
"DescentNewtonSolver is used (as some det(J) < 0)." << endl; }
714 cout <<
"NewtonIteration: rtol = " << newton_rtol <<
" not achieved."
722 ostringstream mesh_name;
723 mesh_name <<
"optimized." << setfill(
'0') << setw(6) << myid;
724 ofstream mesh_ofs(mesh_name.str().c_str());
725 mesh_ofs.precision(8);
726 pmesh->
Print(mesh_ofs);
733 cout <<
"Final strain energy : " << fin_en << endl;
734 cout <<
"The strain energy decreased by: " << setprecision(12)
735 << (init_en - fin_en) * 100.0 / init_en <<
" %." << endl;
741 char title[] =
"Final metric values";
742 vis_metric(mesh_poly_deg, *metric, *target_c, *pmesh, title, 600);
752 sock.
open(
"localhost", 19916);
753 sock <<
"solution\n";
759 sock <<
"window_title 'Displacements'\n"
760 <<
"window_geometry "
761 << 1200 <<
" " << 0 <<
" " << 600 <<
" " << 600 <<
"\n"
762 <<
"keys jRmclA" << endl;
784 const double r = sqrt(x(0)*x(0) + x(1)*x(1) + 1e-12);
785 const double den = 0.002;
786 double l2 = 0.2 + 0.5 * (std::tanh((r-0.16)/den) - std::tanh((r-0.17)/den)
787 + 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.
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 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.
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.
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.
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)
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.