56 #error This example requires that MFEM is built with MFEM_USE_HIOP=YES
83 class LinearScaleOperator :
public Operator
95 pfes(space), w(weight), grad(1, width)
98 pfes.Dof_TrueDof_Matrix()->MultTranspose(w, w_glob);
99 for (
int i = 0; i < width; i++) { grad(0, i) = w_glob(i); }
105 pfes.GetProlongationMatrix()->Mult(x, x_loc);
106 const double loc_res = w * x_loc;
107 MPI_Allreduce(&loc_res, &y(0), 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
118 class TanhSumOperator :
public Operator
126 :
Operator(1, space.TrueVSize()), grad(1, width) { }
130 double sum_loc = x.
Sum();
131 MPI_Allreduce(&sum_loc, &y(0), 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
132 y(0) = std::tanh(y(0));
137 double sum_loc = x.
Sum();
139 MPI_Allreduce(&sum_loc, &dtanh, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
140 dtanh = 1.0 - pow(std::tanh(dtanh), 2);
142 for (
int i = 0; i < width; i++) { grad(0, i) = dtanh; }
158 Vector massvec, d_lo, d_hi;
159 const LinearScaleOperator LSoper;
160 const TanhSumOperator TSoper;
167 x_HO(xho), massvec(1), d_lo(1), d_hi(1),
168 LSoper(space, w), TSoper(space)
172 SetEqualityConstraint(massvec);
175 double lsums[2], gsums[2];
176 lsums[0] = xmin.
Sum();
177 lsums[1] = xmax.
Sum();
178 MPI_Allreduce(lsums, gsums, 2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
179 d_lo(0) = std::tanh(gsums[0]);
180 d_hi(0) = std::tanh(gsums[1]);
181 MFEM_ASSERT(d_lo(0) < d_hi(0),
182 "The bounds produce an infeasible optimization problem");
183 SetInequalityConstraint(d_lo, d_hi);
185 SetSolutionBounds(xmin, xmax);
188 virtual double CalcObjective(
const Vector &x)
const
190 double loc_res = 0.0;
191 for (
int i = 0; i < input_size; i++)
193 const double d = x(i) - x_HO(i);
198 MPI_Allreduce(&loc_res, &res, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
202 virtual void CalcObjectiveGrad(
const Vector &x,
Vector &grad)
const
204 for (
int i = 0; i < input_size; i++) { grad(i) = x(i) - x_HO(i); }
240 int main(
int argc,
char *argv[])
244 MPI_Init(&argc, &argv);
245 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
246 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
251 const char *mesh_file =
"../../data/periodic-hexagon.mesh";
252 int ser_ref_levels = 2;
253 int par_ref_levels = 0;
255 int ode_solver_type = 3;
256 double t_final = 1.0;
258 bool visualization =
true;
264 cout.precision(precision);
267 args.
AddOption(&mesh_file,
"-m",
"--mesh",
268 "Mesh file to use.");
270 "Problem setup to use. See options in velocity_function().");
271 args.
AddOption(&ser_ref_levels,
"-rs",
"--refine-serial",
272 "Number of times to refine the mesh uniformly in serial.");
273 args.
AddOption(&par_ref_levels,
"-rp",
"--refine-parallel",
274 "Number of times to refine the mesh uniformly in parallel.");
276 "Order (degree) of the finite elements.");
278 "Nonlinear optimizer: 1 - SLBQP,\n\t"
280 args.
AddOption(&ode_solver_type,
"-s",
"--ode-solver",
281 "ODE solver: 1 - Forward Euler,\n\t"
282 " 2 - RK2 SSP, 3 - RK3 SSP.");
283 args.
AddOption(&t_final,
"-tf",
"--t-final",
284 "Final time; start time is 0.");
285 args.
AddOption(&dt,
"-dt",
"--time-step",
287 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
288 "--no-visualization",
289 "Enable or disable GLVis visualization.");
290 args.
AddOption(&visit,
"-visit",
"--visit-datafiles",
"-no-visit",
291 "--no-visit-datafiles",
292 "Save data files for VisIt (visit.llnl.gov) visualization.");
293 args.
AddOption(&binary,
"-binary",
"--binary-datafiles",
"-ascii",
295 "Use binary (Sidre) or ascii format for VisIt data files.");
296 args.
AddOption(&vis_steps,
"-vs",
"--visualization-steps",
297 "Visualize every n-th timestep.");
309 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
315 switch (ode_solver_type)
318 case 2: ode_solver =
new RK2Solver(1.0);
break;
320 case 4: ode_solver =
new RK4Solver;
break;
321 case 6: ode_solver =
new RK6Solver;
break;
325 cout <<
"Unknown ODE solver type: " << ode_solver_type <<
'\n';
336 for (
int lev = 0; lev < ser_ref_levels; lev++)
351 for (
int lev = 0; lev < par_ref_levels; lev++)
364 cout <<
"Number of unknowns: " << global_vSize << endl;
406 ostringstream mesh_name, sol_name;
407 mesh_name <<
"ex9-mesh." << setfill(
'0') << setw(6) << myid;
408 sol_name <<
"ex9-init." << setfill(
'0') << setw(6) << myid;
409 ofstream omesh(mesh_name.str().c_str());
410 omesh.precision(precision);
412 ofstream osol(sol_name.str().c_str());
413 osol.precision(precision);
424 #ifdef MFEM_USE_SIDRE
427 MFEM_ABORT(
"Must build with MFEM_USE_SIDRE=YES for binary output.");
448 sout.
open(vishost, visport);
452 cout <<
"Unable to connect to GLVis server at "
453 << vishost <<
':' << visport << endl;
454 visualization =
false;
457 cout <<
"GLVis visualization disabled.\n";
462 sout <<
"parallel " << num_procs <<
" " << myid <<
"\n";
463 sout.precision(precision);
464 sout <<
"solution\n" << *pmesh << *
u;
468 cout <<
"GLVis visualization paused."
469 <<
" Press space (in the GLVis window) to resume it.\n";
483 ode_solver->
Init(adv);
488 const double vol0_loc = M_rowsums * (*u);
490 MPI_Allreduce(&vol0_loc, &vol0, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
493 for (
int ti = 0; !done; )
495 double dt_real = min(dt, t_final - t);
497 ode_solver->
Step(*U, t, dt_real);
500 done = (t >= t_final - 1e-8*dt);
502 if (done || ti % vis_steps == 0)
506 cout <<
"time step: " << ti <<
", time: " << t << endl;
515 sout <<
"parallel " << num_procs <<
" " << myid <<
"\n";
516 sout <<
"solution\n" << *pmesh << *u << flush;
529 const double max_error = u->ComputeMaxError(u0),
530 l1_error = u->ComputeL1Error(u0),
531 l2_error = u->ComputeL2Error(u0);
534 std::cout <<
"Linf error = " << max_error << endl
535 <<
"L1 error = " << l1_error << endl
536 <<
"L2 error = " << l2_error << endl;
540 const double vol_loc = M_rowsums * (*u);
542 MPI_Allreduce(&vol_loc, &vol, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
545 std::cout <<
"Vol error = " << vol - vol0 << endl;
552 ostringstream sol_name;
553 sol_name <<
"ex9-final." << setfill(
'0') << setw(6) << myid;
554 ofstream osol(sol_name.str().c_str());
555 osol.precision(precision);
583 M(M_), K(K_),
b(b_), M_solver(M.GetComm()), z(M_.Height()),
584 pbf(pbf_), M_rowsums(M_rs)
586 M_prec.SetType(HypreSmoother::Jacobi);
605 const int ldofs = x_gf.Size();
606 Vector y_min(ldofs), y_max(ldofs);
607 x_gf.ExchangeFaceNbrData();
608 Vector &x_nd = x_gf.FaceNbrData();
610 for (
int i = 0, k = 0; i < ldofs; i++)
614 for (
int end = In[i+1]; k < end; k++)
617 const double x_j = (j < ldofs) ? x(j): x_nd(j-ldofs);
619 if (x_j > x_i_max) { x_i_max = x_j; }
620 if (x_j < x_i_min) { x_i_min = x_j; }
625 for (
int i = 0; i < ldofs; i++)
627 y_min(i) = (y_min(i) - x_gf(i) ) / dt;
628 y_max(i) = (y_max(i) - x_gf(i) ) / dt;
641 const double mass_y = 0.0;
645 const int max_iter = 500;
646 const double rtol = 1.e-7;
654 optsolver = tmp_opt_ptr;
656 MFEM_ABORT(
"MFEM is not built with HiOp support!");
662 slbqp->
SetBounds(y_min_tdofs, y_max_tdofs);
668 OptimizedTransportProblem ot_prob(*pfes, y, M_rowsums, mass_y,
669 y_min_tdofs, y_max_tdofs);
676 optsolver->
Mult(y, y_out);
691 for (
int i = 0; i <
dim; i++)
705 case 2: v(0) = sqrt(2./3.); v(1) = sqrt(1./3.);
break;
706 case 3: v(0) = sqrt(3./6.); v(1) = sqrt(2./6.); v(2) = sqrt(1./6.);
715 const double w = M_PI/2;
718 case 1: v(0) = 1.0;
break;
719 case 2: v(0) = w*X(1); v(1) = -w*X(0);
break;
720 case 3: v(0) = w*X(1); v(1) = -w*X(0); v(2) = 0.0;
break;
727 const double w = M_PI/2;
728 double d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
732 case 1: v(0) = 1.0;
break;
733 case 2: v(0) = d*w*X(1); v(1) = -d*w*X(0);
break;
734 case 3: v(0) = d*w*X(1); v(1) = -d*w*X(0); v(2) = 0.0;
break;
748 for (
int i = 0; i <
dim; i++)
762 return (X(0) > -0.15 && X(0) < 0.15) ? 1.0 : 0.0;
767 double rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
770 const double s = (1. + 0.25*cos(2*M_PI*X(2)));
774 return ( erfc(w*(X(0)-cx-rx))*erfc(-w*(X(0)-cx+rx)) *
775 erfc(w*(X(1)-cy-ry))*erfc(-w*(X(1)-cy+ry)) )/16;
781 double x_ = X(0), y_ = X(1), rho, phi;
784 return pow(sin(M_PI*rho),2)*sin(3*phi);
788 const double f = M_PI;
789 return sin(f*X(0))*sin(f*X(1));
void SetPrecision(int prec)
Set the precision (number of digits) used for the text output of doubles.
Conjugate gradient method.
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
virtual const Operator * GetProlongationMatrix() const
The returned Operator is owned by the FiniteElementSpace.
int TrueVSize() const
Obsolete, kept for backward compatibility.
Base abstract class for first order time dependent operators.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
void GetBoundingBox(Vector &min, Vector &max, int ref=2)
Returns the minimum and maximum corners of the mesh bounding box.
int * GetJ()
Return the array J.
virtual void Step(Vector &x, double &t, double &dt)=0
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in]...
HYPRE_BigInt GlobalTrueVSize() const
Data type dense matrix using column-major storage.
int Size() const
Returns the size of the vector.
Abstract class for solving systems of ODEs: dx/dt = f(x,t)
int * GetI()
Return the array I.
virtual void Save(std::ostream &out) const
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
virtual void SetTime(const double t_)
Set the current time.
Abstract parallel finite element space.
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
Data collection with Sidre routines following the Conduit mesh blueprint specification.
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection.
void SetPrintLevel(int print_lvl)
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
virtual void Save()
Save the collection to disk.
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Data collection with VisIt I/O routines.
void SetMaxIter(int max_it)
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
void SetTimeStep(double dt_)
void SetLinearConstraint(const Vector &w_, double a_)
void SetK(HypreParMatrix &K_)
virtual void Print(std::ostream &out=mfem::out) const
Parallel smoothers in hypre.
void PrintUsage(std::ostream &out) const
Print the usage message.
void SetTime(double t)
Set physical time (for time-dependent simulations)
A general vector function coefficient.
Wrapper for hypre's parallel vector class.
The classical explicit forth-order Runge-Kutta method, RK4.
void SetAbsTol(double atol)
void SetRelTol(double rtol)
void velocity_function(const Vector &x, Vector &v)
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
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...
Third-order, strong stability preserving (SSP) Runge-Kutta method.
Adapts the HiOp functionality to the MFEM OptimizationSolver interface.
virtual void Mult(const Vector &x, Vector &y) const
Perform the action of the operator: y = k = f(x, t), where k solves the algebraic equation F(x...
FE_Evolution(FiniteElementSpace &vfes_, Operator &A_, SparseMatrix &Aflux_)
NURBSExtension * NURBSext
Optional NURBS mesh extension.
Abstract solver for OptimizationProblems.
virtual const SparseMatrix * GetRestrictionMatrix() const
Get the R matrix which restricts a local dof vector to true dof vector.
virtual void Mult(const Vector &xt, Vector &x) const =0
Operator application: y=A(x).
void PrintOptions(std::ostream &out) const
Print the options.
HypreParVector * GetTrueDofs() const
Returns the true dofs in a new HypreParVector.
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'.
double u0_function(const Vector &x)
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
A general function coefficient.
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
double u(const Vector &xvec)
Class for parallel grid function.
The classical forward Euler method.
Wrapper for hypre's ParCSR matrix class.
void SetBounds(const Vector &lo_, const Vector &hi_)
virtual void SetOptimizationProblem(const OptimizationProblem &prob)
Class for parallel meshes.
double Sum() const
Return the sum of the vector entries.
virtual void Init(TimeDependentOperator &f_)
Associate a TimeDependentOperator with the ODE solver.
double inflow_function(const Vector &x)
void GetRowSums(Vector &x) const
For all i compute .
Arbitrary order "L2-conforming" discontinuous finite elements.
double f(const Vector &p)
bool Good() const
Return true if the command line options were parsed successfully.