56#error This example requires that MFEM is built with MFEM_USE_HIOP=YES 
   83class LinearScaleOperator : 
public Operator 
  100      for (
int i = 0; i < 
width; i++) { grad(0, i) = w_glob(i); }
 
  107      const double loc_res = w * x_loc;
 
  108      MPI_Allreduce(&loc_res, &y(0), 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
 
  119class TanhSumOperator : 
public Operator 
  131      double sum_loc = x.
Sum();
 
  132      MPI_Allreduce(&sum_loc, &y(0), 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
 
  133      y(0) = std::tanh(y(0));
 
  138      double sum_loc = x.
Sum();
 
  140      MPI_Allreduce(&sum_loc, &dtanh, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
 
  141      dtanh = 1.0 - pow(std::tanh(dtanh), 2);
 
  143      for (
int i = 0; i < 
width; i++) { grad(0, i) = dtanh; }
 
  159   Vector massvec, d_lo, d_hi;
 
  160   const LinearScaleOperator LSoper;
 
  161   const TanhSumOperator TSoper;
 
  168        x_HO(xho), massvec(1), d_lo(1), d_hi(1),
 
  176      double lsums[2], gsums[2];
 
  177      lsums[0] = xmin.
Sum();
 
  178      lsums[1] = xmax.
Sum();
 
  179      MPI_Allreduce(lsums, gsums, 2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
 
  180      d_lo(0) = std::tanh(gsums[0]);
 
  181      d_hi(0) = std::tanh(gsums[1]);
 
  182      MFEM_ASSERT(d_lo(0) < d_hi(0),
 
  183                  "The bounds produce an infeasible optimization problem");
 
  189   virtual double CalcObjective(
const Vector &x)
 const 
  191      double loc_res = 0.0;
 
  194         const double d = x(i) - x_HO(i);
 
  199      MPI_Allreduce(&loc_res, &res, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
 
  203   virtual void CalcObjectiveGrad(
const Vector &x, 
Vector &grad)
 const 
  205      for (
int i = 0; i < 
input_size; i++) { grad(i) = x(i) - x_HO(i); }
 
  233   void SetTimeStep(
double dt_) { dt = dt_; }
 
  237   virtual ~FE_Evolution() { }
 
  241int main(
int argc, 
char *argv[])
 
  252   const char *mesh_file = 
"../../data/periodic-hexagon.mesh";
 
  253   int ser_ref_levels = 2;
 
  254   int par_ref_levels = 0;
 
  256   int ode_solver_type = 3;
 
  257   double t_final = 1.0;
 
  259   bool visualization = 
true;
 
  265   cout.precision(precision);
 
  268   args.
AddOption(&mesh_file, 
"-m", 
"--mesh",
 
  269                  "Mesh file to use.");
 
  271                  "Problem setup to use. See options in velocity_function().");
 
  272   args.
AddOption(&ser_ref_levels, 
"-rs", 
"--refine-serial",
 
  273                  "Number of times to refine the mesh uniformly in serial.");
 
  274   args.
AddOption(&par_ref_levels, 
"-rp", 
"--refine-parallel",
 
  275                  "Number of times to refine the mesh uniformly in parallel.");
 
  277                  "Order (degree) of the finite elements.");
 
  279                  "Nonlinear optimizer: 1 - SLBQP,\n\t" 
  281   args.
AddOption(&ode_solver_type, 
"-s", 
"--ode-solver",
 
  282                  "ODE solver: 1 - Forward Euler,\n\t" 
  283                  "            2 - RK2 SSP, 3 - RK3 SSP.");
 
  284   args.
AddOption(&t_final, 
"-tf", 
"--t-final",
 
  285                  "Final time; start time is 0.");
 
  286   args.
AddOption(&dt, 
"-dt", 
"--time-step",
 
  288   args.
AddOption(&visualization, 
"-vis", 
"--visualization", 
"-no-vis",
 
  289                  "--no-visualization",
 
  290                  "Enable or disable GLVis visualization.");
 
  291   args.
AddOption(&visit, 
"-visit", 
"--visit-datafiles", 
"-no-visit",
 
  292                  "--no-visit-datafiles",
 
  293                  "Save data files for VisIt (visit.llnl.gov) visualization.");
 
  294   args.
AddOption(&binary, 
"-binary", 
"--binary-datafiles", 
"-ascii",
 
  296                  "Use binary (Sidre) or ascii format for VisIt data files.");
 
  297   args.
AddOption(&vis_steps, 
"-vs", 
"--visualization-steps",
 
  298                  "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';
 
  335   for (
int lev = 0; lev < ser_ref_levels; lev++)
 
  350   for (
int lev = 0; lev < par_ref_levels; lev++)
 
  363      cout << 
"Number of unknowns: " << global_vSize << endl;
 
  383   b->AddBdrFaceIntegrator(
 
  401   u->ProjectCoefficient(u0);
 
  405      ostringstream mesh_name, sol_name;
 
  406      mesh_name << 
"ex9-mesh." << setfill(
'0') << setw(6) << myid;
 
  407      sol_name << 
"ex9-init." << setfill(
'0') << setw(6) << myid;
 
  408      ofstream omesh(mesh_name.str().c_str());
 
  409      omesh.precision(precision);
 
  411      ofstream osol(sol_name.str().c_str());
 
  412      osol.precision(precision);
 
  426         MFEM_ABORT(
"Must build with MFEM_USE_SIDRE=YES for binary output.");
 
  451            cout << 
"Unable to connect to GLVis server at " 
  452                 << 
vishost << 
':' << visport << endl;
 
  453         visualization = 
false;
 
  456            cout << 
"GLVis visualization disabled.\n";
 
  461         sout << 
"parallel " << num_procs << 
" " << myid << 
"\n";
 
  462         sout.precision(precision);
 
  463         sout << 
"solution\n" << *pmesh << *
u;
 
  467            cout << 
"GLVis visualization paused." 
  468                 << 
" Press space (in the GLVis window) to resume it.\n";
 
  478   FE_Evolution adv(*M, *K, *B, *k, M_rowsums);
 
  482   ode_solver->
Init(adv);
 
  487   const double vol0_loc = M_rowsums * (*u);
 
  489   MPI_Allreduce(&vol0_loc, &vol0, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
 
  492   for (
int ti = 0; !done; )
 
  494      double dt_real = min(dt, t_final - t);
 
  495      adv.SetTimeStep(dt_real);
 
  496      ode_solver->
Step(*U, t, dt_real);
 
  499      done = (t >= t_final - 1e-8*dt);
 
  501      if (done || ti % vis_steps == 0)
 
  505            cout << 
"time step: " << ti << 
", time: " << t << endl;
 
  514            sout << 
"parallel " << num_procs << 
" " << myid << 
"\n";
 
  515            sout << 
"solution\n" << *pmesh << *
u << flush;
 
  528   const double max_error = 
u->ComputeMaxError(u0),
 
  529                l1_error  = 
u->ComputeL1Error(u0),
 
  530                l2_error  = 
u->ComputeL2Error(u0);
 
  533      std::cout << 
"Linf error = " << max_error << endl
 
  534                << 
"L1   error = " << l1_error << endl
 
  535                << 
"L2   error = " << l2_error << endl;
 
  539   const double vol_loc = M_rowsums * (*u);
 
  541   MPI_Allreduce(&vol_loc, &vol, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
 
  544      std::cout << 
"Vol  error = " << vol - vol0 << endl;
 
  551      ostringstream sol_name;
 
  552      sol_name << 
"ex9-final." << setfill(
'0') << setw(6) << myid;
 
  553      ofstream osol(sol_name.str().c_str());
 
  554      osol.precision(precision);
 
 
  581     M(M_), K(K_), 
b(b_), M_solver(M.GetComm()), z(M_.Height()),
 
  582     pbf(pbf_), M_rowsums(M_rs)
 
  585   M_solver.SetPreconditioner(M_prec);
 
  586   M_solver.SetOperator(M);
 
  588   M_solver.iterative_mode = 
false;
 
  589   M_solver.SetRelTol(1e-9);
 
  590   M_solver.SetAbsTol(0.0);
 
  591   M_solver.SetMaxIter(100);
 
  592   M_solver.SetPrintLevel(0);
 
  595void FE_Evolution::Mult(
const Vector &x, 
Vector &y)
 const 
  603   const int ldofs = x_gf.Size();
 
  604   Vector y_min(ldofs), y_max(ldofs);
 
  605   x_gf.ExchangeFaceNbrData();
 
  606   Vector &x_nd = x_gf.FaceNbrData();
 
  608   for (
int i = 0, k = 0; i < ldofs; i++)
 
  610      double x_i_min = +std::numeric_limits<double>::infinity();
 
  611      double x_i_max = -std::numeric_limits<double>::infinity();
 
  612      for (
int end = In[i+1]; k < end; k++)
 
  615         const double x_j = (j < ldofs) ? x(j): x_nd(j-ldofs);
 
  617         if (x_j > x_i_max) { x_i_max = x_j; }
 
  618         if (x_j < x_i_min) { x_i_min = x_j; }
 
  623   for (
int i = 0; i < ldofs; i++)
 
  625      y_min(i) = (y_min(i) - x_gf(i) ) / dt;
 
  626      y_max(i) = (y_max(i) - x_gf(i) ) / dt;
 
  639   const double mass_y = 0.0;
 
  643   const int max_iter = 500;
 
  644   const double rtol = 1.e-7;
 
  652      optsolver = tmp_opt_ptr;
 
  654      MFEM_ABORT(
"MFEM is not built with HiOp support!");
 
  660      slbqp->
SetBounds(y_min_tdofs, y_max_tdofs);
 
  666   OptimizedTransportProblem ot_prob(*pfes, y, M_rowsums, mass_y,
 
  667                                     y_min_tdofs, y_max_tdofs);
 
  674   optsolver->
Mult(y, y_out);
 
  689   for (
int i = 0; i < 
dim; i++)
 
  703            case 2: v(0) = sqrt(2./3.); v(1) = sqrt(1./3.); 
break;
 
  704            case 3: v(0) = sqrt(3./6.); v(1) = sqrt(2./6.); v(2) = sqrt(1./6.);
 
  713         const double w = M_PI/2;
 
  716            case 1: v(0) = 1.0; 
break;
 
  717            case 2: v(0) = w*X(1); v(1) = -w*X(0); 
break;
 
  718            case 3: v(0) = w*X(1); v(1) = -w*X(0); v(2) = 0.0; 
break;
 
  725         const double w = M_PI/2;
 
  726         double d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
 
  730            case 1: v(0) = 1.0; 
break;
 
  731            case 2: v(0) = d*w*X(1); v(1) = -d*w*X(0); 
break;
 
  732            case 3: v(0) = d*w*X(1); v(1) = -d*w*X(0); v(2) = 0.0; 
break;
 
 
  746   for (
int i = 0; i < 
dim; i++)
 
  760               return (X(0) > -0.15 && X(0) < 0.15) ? 1.0 : 0.0;
 
  765               double rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
 
  768                  const double s = (1. + 0.25*cos(2*M_PI*X(2)));
 
  772               return ( erfc(w*(X(0)-cx-rx))*erfc(-w*(X(0)-cx+rx)) *
 
  773                        erfc(w*(X(1)-cy-ry))*erfc(-w*(X(1)-cy+ry)) )/16;
 
  779         double x_ = X(0), y_ = X(1), rho, phi;
 
  782         return pow(sin(M_PI*rho),2)*sin(3*phi);
 
  786         const double f = M_PI;
 
  787         return sin(
f*X(0))*sin(
f*X(1));
 
 
@ Positive
Bernstein polynomials.
 
Conjugate gradient method.
 
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the Conjugate Gradient method.
 
void SetPrecision(int prec)
Set the precision (number of digits) used for the text output of doubles.
 
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection.
 
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
 
void SetTime(real_t t)
Set physical time (for time-dependent simulations)
 
virtual void Save()
Save the collection to disk.
 
Data type dense matrix using column-major storage.
 
The classical forward Euler method.
 
A general function coefficient.
 
Adapts the HiOp functionality to the MFEM OptimizationSolver interface.
 
Wrapper for hypre's ParCSR matrix class.
 
HYPRE_Int MultTranspose(HypreParVector &x, HypreParVector &y, real_t alpha=1.0, real_t beta=0.0) const
Computes y = alpha * A^t * x + beta * y.
 
Wrapper for hypre's parallel vector class.
 
Parallel smoothers in hypre.
 
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
 
void SetRelTol(real_t rtol)
 
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
 
void SetMaxIter(int max_it)
 
void SetAbsTol(real_t atol)
 
Arbitrary order "L2-conforming" discontinuous finite elements.
 
NURBSExtension * NURBSext
Optional NURBS mesh extension.
 
void GetBoundingBox(Vector &min, Vector &max, int ref=2)
Returns the minimum and maximum corners of the mesh bounding box.
 
int Dimension() const
Dimension of the reference space used within the elements.
 
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Set the curvature of the mesh nodes using the given polynomial degree.
 
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
 
static int WorldRank()
Return the MPI rank in MPI_COMM_WORLD.
 
static int WorldSize()
Return the size of MPI_COMM_WORLD.
 
static void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
 
Abstract class for solving systems of ODEs: dx/dt = f(x,t)
 
virtual void Init(TimeDependentOperator &f_)
Associate a TimeDependentOperator with the ODE solver.
 
virtual void Step(Vector &x, real_t &t, real_t &dt)=0
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
 
int width
Dimension of the input / number of columns in the matrix.
 
Operator(int s=0)
Construct a square Operator with given size s (default 0).
 
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
 
const Operator * C
Not owned, some can remain unused (NULL).
 
void SetSolutionBounds(const Vector &xl, const Vector &xh)
 
void SetEqualityConstraint(const Vector &c)
 
void SetInequalityConstraint(const Vector &dl, const Vector &dh)
 
Abstract solver for OptimizationProblems.
 
void Mult(const Vector &xt, Vector &x) const override=0
Operator application: y=A(x).
 
virtual void SetOptimizationProblem(const OptimizationProblem &prob)
 
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
 
void PrintUsage(std::ostream &out) const
Print the usage message.
 
void PrintOptions(std::ostream &out) const
Print the options.
 
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...
 
bool Good() const
Return true if the command line options were parsed successfully.
 
Abstract parallel finite element space.
 
HYPRE_BigInt GlobalTrueVSize() const
 
const Operator * GetProlongationMatrix() const override
 
HypreParMatrix * Dof_TrueDof_Matrix() const
The true dof-to-dof interpolation matrix.
 
const SparseMatrix * GetRestrictionMatrix() const override
Get the R matrix which restricts a local dof vector to true dof vector.
 
Class for parallel grid function.
 
Class for parallel meshes.
 
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
 
Third-order, strong stability preserving (SSP) Runge-Kutta method.
 
The classical explicit forth-order Runge-Kutta method, RK4.
 
void SetBounds(const Vector &lo_, const Vector &hi_)
 
void SetLinearConstraint(const Vector &w_, real_t a_)
 
Data collection with Sidre routines following the Conduit mesh blueprint specification.
 
void GetRowSums(Vector &x) const
For all i compute .
 
void Mult(const Vector &x, Vector &y) const override
Matrix vector multiplication.
 
int * GetJ()
Return the array J.
 
int * GetI()
Return the array I.
 
Base abstract class for first order time dependent operators.
 
virtual void SetTime(const real_t t_)
Set the current time.
 
A general vector function coefficient.
 
int Size() const
Returns the size of the vector.
 
real_t Sum() const
Return the sum of the vector entries.
 
virtual real_t * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
 
Data collection with VisIt I/O routines.
 
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
 
void velocity_function(const Vector &x, Vector &v)
 
double u0_function(const Vector &x)
 
double inflow_function(const Vector &x)
 
real_t u(const Vector &xvec)
 
std::function< real_t(const Vector &)> f(real_t mass_coeff)