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)