87 #include "../common/mfem-common.hpp"
95 int main (
int argc,
char *argv[])
99 MPI_Init(&argc, &argv);
100 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
101 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
104 const char *mesh_file =
"icf.mesh";
105 int mesh_poly_deg = 1;
111 double lim_const = 0.0;
112 double adapt_lim_const = 0.0;
116 int solver_iter = 10;
117 double solver_rtol = 1e-10;
119 int max_lin_iter = 100;
120 bool move_bnd =
true;
122 bool normalization =
false;
123 bool visualization =
true;
124 int verbosity_level = 0;
125 bool fdscheme =
false;
127 bool exactaction =
false;
131 args.
AddOption(&mesh_file,
"-m",
"--mesh",
132 "Mesh file to use.");
133 args.
AddOption(&mesh_poly_deg,
"-o",
"--order",
134 "Polynomial degree of mesh finite element space.");
135 args.
AddOption(&rs_levels,
"-rs",
"--refine-serial",
136 "Number of times to refine the mesh uniformly in serial.");
137 args.
AddOption(&rp_levels,
"-rp",
"--refine-parallel",
138 "Number of times to refine the mesh uniformly in parallel.");
139 args.
AddOption(&jitter,
"-ji",
"--jitter",
140 "Random perturbation scaling factor.");
141 args.
AddOption(&metric_id,
"-mid",
"--metric-id",
142 "Mesh optimization metric:\n\t"
143 "1 : |T|^2 -- 2D shape\n\t"
144 "2 : 0.5|T|^2/tau-1 -- 2D shape (condition number)\n\t"
145 "7 : |T-T^-t|^2 -- 2D shape+size\n\t"
146 "9 : tau*|T-T^-t|^2 -- 2D shape+size\n\t"
147 "22 : 0.5(|T|^2-2*tau)/(tau-tau_0) -- 2D untangling\n\t"
148 "50 : 0.5|T^tT|^2/tau^2-1 -- 2D shape\n\t"
149 "55 : (tau-1)^2 -- 2D size\n\t"
150 "56 : 0.5(sqrt(tau)-1/sqrt(tau))^2 -- 2D size\n\t"
151 "58 : |T^tT|^2/(tau^2)-2*|T|^2/tau+2 -- 2D shape\n\t"
152 "77 : 0.5(tau-1/tau)^2 -- 2D size\n\t"
153 "211: (tau-1)^2-tau+sqrt(tau^2) -- 2D untangling\n\t"
154 "252: 0.5(tau-1)^2/(tau-tau_0) -- 2D untangling\n\t"
155 "301: (|T||T^-1|)/3-1 -- 3D shape\n\t"
156 "302: (|T|^2|T^-1|^2)/9-1 -- 3D shape\n\t"
157 "303: (|T|^2)/3*tau^(2/3)-1 -- 3D shape\n\t"
158 "315: (tau-1)^2 -- 3D size\n\t"
159 "316: 0.5(sqrt(tau)-1/sqrt(tau))^2 -- 3D size\n\t"
160 "321: |T-T^-t|^2 -- 3D shape+size\n\t"
161 "352: 0.5(tau-1)^2/(tau-tau_0) -- 3D untangling");
162 args.
AddOption(&target_id,
"-tid",
"--target-id",
163 "Target (ideal element) type:\n\t"
164 "1: Ideal shape, unit size\n\t"
165 "2: Ideal shape, equal size\n\t"
166 "3: Ideal shape, initial size\n\t"
167 "4: Given full analytic Jacobian (in physical space)\n\t"
168 "5: Ideal shape, given size (in physical space)");
169 args.
AddOption(&lim_const,
"-lc",
"--limit-const",
"Limiting constant.");
170 args.
AddOption(&adapt_lim_const,
"-alc",
"--adapt-limit-const",
171 "Adaptive limiting coefficient constant.");
172 args.
AddOption(&quad_type,
"-qt",
"--quad-type",
173 "Quadrature rule type:\n\t"
174 "1: Gauss-Lobatto\n\t"
175 "2: Gauss-Legendre\n\t"
176 "3: Closed uniform points");
177 args.
AddOption(&quad_order,
"-qo",
"--quad_order",
178 "Order of the quadrature rule.");
179 args.
AddOption(&solver_type,
"-st",
"--solver-type",
180 " Type of solver: (default) 0: Newton, 1: LBFGS");
181 args.
AddOption(&solver_iter,
"-ni",
"--newton-iters",
182 "Maximum number of Newton iterations.");
183 args.
AddOption(&solver_rtol,
"-rtol",
"--newton-rel-tolerance",
184 "Relative tolerance for the Newton solver.");
185 args.
AddOption(&lin_solver,
"-ls",
"--lin-solver",
186 "Linear solver: 0 - l1-Jacobi, 1 - CG, 2 - MINRES.");
187 args.
AddOption(&max_lin_iter,
"-li",
"--lin-iter",
188 "Maximum number of iterations in the linear solve.");
189 args.
AddOption(&move_bnd,
"-bnd",
"--move-boundary",
"-fix-bnd",
191 "Enable motion along horizontal and vertical boundaries.");
192 args.
AddOption(&combomet,
"-cmb",
"--combo-type",
193 "Combination of metrics options:"
194 "0: Use single metric\n\t"
195 "1: Shape + space-dependent size given analytically\n\t"
196 "2: Shape + adapted size given discretely; shared target");
197 args.
AddOption(&normalization,
"-nor",
"--normalization",
"-no-nor",
198 "--no-normalization",
199 "Make all terms in the optimization functional unitless.");
200 args.
AddOption(&fdscheme,
"-fd",
"--fd_approximation",
201 "-no-fd",
"--no-fd-approx",
202 "Enable finite difference based derivative computations.");
203 args.
AddOption(&exactaction,
"-ex",
"--exact_action",
204 "-no-ex",
"--no-exact-action",
205 "Enable exact action of TMOP_Integrator.");
206 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
207 "--no-visualization",
208 "Enable or disable GLVis visualization.");
209 args.
AddOption(&verbosity_level,
"-vl",
"--verbosity-level",
210 "Set the verbosity level - 0, 1, or 2.");
211 args.
AddOption(&adapt_eval,
"-ae",
"--adaptivity-evaluator",
212 "0 - Advection based (DEFAULT), 1 - GSLIB.");
222 Mesh *mesh =
new Mesh(mesh_file, 1, 1,
false);
223 for (
int lev = 0; lev < rs_levels; lev++)
230 cout <<
"Mesh curvature: ";
232 else { cout <<
"(NONE)"; }
239 for (
int lev = 0; lev < rp_levels; lev++)
249 if (mesh_poly_deg <= 0)
278 double vol_loc = 0.0;
280 for (
int i = 0; i < pmesh->
GetNE(); i++)
286 for (
int j = 0; j < dofs.
Size(); j++)
288 h0(dofs[j]) = min(h0(dofs[j]), hi);
293 MPI_Allreduce(&vol_loc, &volume, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
294 const double small_phys_size = pow(volume, 1.0 / dim) / 100.0;
306 for (
int i = 0; i < pfespace->
GetNDofs(); i++)
308 for (
int d = 0; d <
dim; d++)
314 for (
int i = 0; i < pfespace->
GetNBE(); i++)
319 for (
int j = 0; j < vdofs.
Size(); j++) { rdm(vdofs[j]) = 0.0; }
330 ostringstream mesh_name;
331 mesh_name <<
"perturbed.mesh";
332 ofstream mesh_ofs(mesh_name.str().c_str());
333 mesh_ofs.precision(8);
342 double tauval = -0.1;
368 if (myid == 0) { cout <<
"Unknown metric_id: " << metric_id << endl; }
404 #ifdef MFEM_USE_GSLIB
407 MFEM_ABORT(
"MFEM is not built with GSLIB.");
411 size.ProjectCoefficient(ind_coeff);
423 disc.ProjectCoefficient(ind_coeff);
430 #ifdef MFEM_USE_GSLIB
433 MFEM_ABORT(
"MFEM is not built with GSLIB.");
440 disc.GetDerivative(1,0,d_x);
441 disc.GetDerivative(1,1,d_y);
444 for (
int i = 0; i < size.Size(); i++)
446 size(i) = std::pow(d_x(i),2)+std::pow(d_y(i),2);
448 const double max = size.Max();
450 MPI_Allreduce(&max, &max_all, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
452 for (
int i = 0; i < d_x.Size(); i++)
454 d_x(i) = std::abs(d_x(i));
455 d_y(i) = std::abs(d_y(i));
457 const double eps = 0.01;
458 const double aspr_ratio = 20.0;
459 const double size_ratio = 40.0;
461 for (
int i = 0; i < size.Size(); i++)
463 size(i) = (size(i)/max_all);
464 aspr(i) = (d_x(i)+eps)/(d_y(i)+eps);
465 aspr(i) = 0.1 + 0.9*(1-size(i))*(1-size(i));
466 if (aspr(i) > aspr_ratio) {aspr(i) = aspr_ratio;}
467 if (aspr(i) < 1.0/aspr_ratio) {aspr(i) = 1.0/aspr_ratio;}
470 const int NE = pmesh->
GetNE();
471 double volume = 0.0, volume_ind = 0.0;
473 for (
int i = 0; i < NE; i++)
478 size.GetValues(i, ir, vals);
487 double volume_all, volume_ind_all;
488 MPI_Allreduce(&volume, &volume_all, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
489 MPI_Allreduce(&volume_ind, &volume_ind_all, 1, MPI_DOUBLE, MPI_SUM,
493 const double avg_zone_size = volume_all / NE_ALL;
495 const double small_avg_ratio =
496 (volume_ind_all + (volume_all - volume_ind_all) / size_ratio)
499 const double small_zone_size = small_avg_ratio * avg_zone_size;
500 const double big_zone_size = size_ratio * small_zone_size;
502 for (
int i = 0; i < size.Size(); i++)
504 const double val = size(i);
505 const double a = (big_zone_size - small_zone_size) / small_zone_size;
506 size(i) = big_zone_size / (1.0+a*val);
527 #ifdef MFEM_USE_GSLIB
530 MFEM_ABORT(
"MFEM is not built with GSLIB.");
534 aspr3d.ProjectCoefficient(fd_aspr3d);
549 #ifdef MFEM_USE_GSLIB
552 MFEM_ABORT(
"MFEM is not built with GSLIB.");
559 size.ProjectCoefficient(ind_coeff);
566 aspr.ProjectCoefficient(aspr_coeff);
578 if (myid == 0) { cout <<
"Unknown target_id: " << target_id << endl; }
582 if (target_c == NULL)
599 if (myid == 0) { cout <<
"Unknown quad_type: " << quad_type << endl; }
603 if (myid == 0 && dim == 2)
605 cout <<
"Triangle quadrature points: "
607 <<
"\nQuadrilateral quadrature points: "
610 if (myid == 0 && dim == 3)
612 cout <<
"Tetrahedron quadrature points: "
614 <<
"\nHexahedron quadrature points: "
616 <<
"\nPrism quadrature points: "
627 if (normalization) { dist = small_phys_size; }
629 if (lim_const != 0.0) { he_nlf_integ->
EnableLimiting(x0, dist, lim_coeff); }
635 if (adapt_lim_const > 0.0)
640 if (adapt_eval == 0) { adapt_evaluator =
new AdvectorCG; }
641 else if (adapt_eval == 1)
643 #ifdef MFEM_USE_GSLIB
646 MFEM_ABORT(
"MFEM is not built with GSLIB support!");
649 else { MFEM_ABORT(
"Bad interpolation option."); }
700 if (lim_const != 0.0) { combo->
EnableLimiting(x0, dist, lim_coeff); }
712 char title[] =
"Initial metric values";
721 if (move_bnd ==
false)
730 for (
int i = 0; i < pmesh->
GetNBE(); i++)
734 MFEM_VERIFY(!(dim == 2 && attr == 3),
735 "Boundary attribute 3 must be used only for 3D meshes. "
736 "Adjust the attributes (1/2/3/4 for fixed x/y/z/all "
737 "components, rest for free nodes), or use -fix-bnd.");
738 if (attr == 1 || attr == 2 || attr == 3) { n += nd; }
739 if (attr == 4) { n += nd *
dim; }
743 for (
int i = 0; i < pmesh->
GetNBE(); i++)
750 for (
int j = 0; j < nd; j++)
751 { ess_vdofs[n++] = vdofs[j]; }
755 for (
int j = 0; j < nd; j++)
756 { ess_vdofs[n++] = vdofs[j+nd]; }
760 for (
int j = 0; j < nd; j++)
761 { ess_vdofs[n++] = vdofs[j+2*nd]; }
765 for (
int j = 0; j < vdofs.
Size(); j++)
766 { ess_vdofs[n++] = vdofs[j]; }
775 const double linsol_rtol = 1e-12;
780 else if (lin_solver == 1)
801 const int NE = pmesh->
GetNE();
802 for (
int i = 0; i < NE; i++)
814 MPI_Allreduce(&tauval, &minJ0, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
817 { cout <<
"Minimum det(J) of the original mesh is " << tauval << endl; }
818 double h0min = h0.Min(), h0min_all;
819 MPI_Allreduce(&h0min, &h0min_all, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
820 tauval -= 0.01 * h0min_all;
828 if (solver_type == 0)
831 solver.SetPreconditioner(*S);
833 solver.SetMaxIter(solver_iter);
834 solver.SetRelTol(solver_rtol);
835 solver.SetAbsTol(0.0);
836 solver.SetPrintLevel(verbosity_level >= 1 ? 1 : -1);
837 solver.SetOperator(a);
840 if (myid == 0 && solver.GetConverged() ==
false)
842 cout <<
"Nonlinear solver: rtol = " << solver_rtol <<
" not achieved.\n";
848 ostringstream mesh_name;
849 mesh_name <<
"optimized.mesh";
850 ofstream mesh_ofs(mesh_name.str().c_str());
851 mesh_ofs.precision(8);
857 double metric_part = fin_energy;
858 if (lim_const > 0.0 || adapt_lim_const > 0.0)
864 coef_zeta.
constant = adapt_lim_const;
868 cout <<
"Initial strain energy: " << init_energy
869 <<
" = metrics: " << init_energy
870 <<
" + limiting term: " << 0.0 << endl;
871 cout <<
" Final strain energy: " << fin_energy
872 <<
" = metrics: " << metric_part
873 <<
" + limiting term: " << fin_energy - metric_part << endl;
874 cout <<
"The strain energy decreased by: " << setprecision(12)
875 << (init_energy - fin_energy) * 100.0 / init_energy <<
" %." << endl;
881 char title[] =
"Final metric values";
885 if (adapt_lim_const > 0.0 && visualization)
899 sock.
open(
"localhost", 19916);
900 sock <<
"solution\n";
906 sock <<
"window_title 'Displacements'\n"
907 <<
"window_geometry "
908 << 1200 <<
" " << 0 <<
" " << 600 <<
" " << 600 <<
"\n"
909 <<
"keys jRmclA" << endl;
918 delete adapt_evaluator;
int GetNPoints() const
Returns the number of the points in the integration rule.
void vis_tmop_metric_p(int order, TMOP_QualityMetric &qm, const TargetConstructor &tc, ParMesh &pmesh, char *title, int position)
void discrete_aspr_3d(const Vector &x, Vector &v)
virtual void SetParDiscreteTargetSize(const ParGridFunction &tspec_)
int Size() const
Return the 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.
void EnableFiniteDifferences(const GridFunction &x)
Enables FD-based approximation and computes dx.
int DofToVDof(int dof, int vd, int ndofs=-1) const
double discrete_size_2d(const Vector &x)
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.
IntegrationRules IntRulesLo(0, Quadrature1D::GaussLobatto)
void SetIntegrationRules(IntegrationRules &irules, int order)
Prescribe a set of integration rules; relevant for mixed meshes.
void SetFromTrueVector()
Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
A coefficient that is constant across space and time.
long GetGlobalNE() const
Return the total (global) number of elements.
int GetNBE() const
Returns number of boundary elements.
Shape, ideal barrier metric, 3D.
void SetAdaptivityEvaluator(AdaptivityEvaluator *ae)
void DiffuseField(GridFunction &field, int smooth_steps)
void SaveAsOne(std::ostream &out=mfem::out)
Merge the local grid functions.
Container class for integration rules.
Shape, ideal barrier metric, 3D.
void SetVolumeScale(double vol_scale)
Used by target type IDEAL_SHAPE_EQUAL_SIZE. The default volume scale is 1.
Shape, ideal barrier metric, 2D.
void EnableAdaptiveLimiting(const GridFunction &z0, Coefficient &coeff, AdaptivityEvaluator &ae)
Restriction of the node positions to certain regions.
Area, ideal barrier metric, 2D.
void SetIntegrationRules(IntegrationRules &irules, int order)
Prescribe a set of integration rules; relevant for mixed meshes.
int GetNE() const
Returns number of elements.
Abstract parallel finite element space.
virtual void ProjectCoefficient(Coefficient &coeff)
void SetExactActionFlag(bool flag_)
Flag to control if exact action of Integration is effected.
void Randomize(int seed=0)
Set random values in the vector.
int main(int argc, char *argv[])
Shape & area, ideal barrier metric, 2D.
Geometry::Type GetElementBaseGeometry(int i) const
void EnableLimiting(const GridFunction &n0, const GridFunction &dist, Coefficient &w0, TMOP_LimiterFunction *lfunc=NULL)
Adds the limiting term to the first integrator. Disables it for the rest.
Shifted barrier form of metric 2 (shape, ideal barrier metric), 2D.
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)
Limiting of the mesh displacements (general version).
int GetNBE() const
Returns number of boundary elements in the mesh.
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
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 *)
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.
Version of QuadraticFECollection with positive basis functions.
virtual void SetParDiscreteTargetAspectRatio(const ParGridFunction &tspec_)
int GetAttribute() const
Return element's attribute.
double discrete_ori_2d(const Vector &x)
void ParEnableNormalization(const ParGridFunction &x)
void SetNodalFESpace(FiniteElementSpace *nfes)
void PrintUsage(std::ostream &out) const
Print the usage message.
const Vector & GetTrueVector() const
Read only access to the (optional) internal true-dof Vector.
A general vector function coefficient.
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.
double weight_fun(const Vector &x)
Area, ideal barrier metric, 2D.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
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)
Add a boolean option and set 'var' to receive the value. Enable/disable tags are used to set the bool...
double adapt_lim_fun(const Vector &x)
void AddTMOPIntegrator(TMOP_Integrator *ti)
Adds a new TMOP_Integrator to the combination.
double material_indicator_2d(const Vector &x)
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.
double discrete_aspr_2d(const Vector &x)
Class for integration point with weight.
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
IntegrationRules IntRulesCU(0, Quadrature1D::ClosedUniform)
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
void PrintOptions(std::ostream &out) const
Print the options.
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
A general function coefficient.
void VisualizeField(socketstream &sock, const char *vishost, int visport, GridFunction &gf, const char *title, int x, int y, int w, int h, const char *keys, bool vec)
void GetNodes(Vector &node_coord) const
Shape+Size+Orientation metric, 2D.
Arbitrary order H1-conforming (continuous) finite elements.
TargetType
Target-matrix construction algorithms supported by this class.
virtual void SetParDiscreteTargetOrientation(const ParGridFunction &tspec_)
Class for parallel grid function.
const FiniteElement * GetBE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th boundary fac...
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 SetAnalyticTargetSpec(Coefficient *sspec, VectorCoefficient *vspec, TMOPMatrixCoefficient *mspec)
Class for parallel meshes.
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Shape & orientation metric, 2D.
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.
bool Good() const
Return true if the command line options were parsed successfully.
A TMOP integrator class based on any given TMOP_QualityMetric and TargetConstructor.