13 #include "../common/mfem-common.hpp"
29 M(Mbf), K(Kbf), K_mat(NULL),
b(rhs),
30 lo_solver(NULL), lumpedM(NULL)
39 M_Lump.SpMat().GetDiag(*lumpedM);
54 const int NE = pfes.
GetNE();
61 for (
int k = 0; k < NE; k++)
64 if (active_zones[k] ==
false)
73 MFEM_VERIFY(
adv_mode ==
HO,
"Wrong input for advection mode (-dg).");
81 Vector rhs_loc(nd), dx_loc(nd);
82 for (
int k = 0; k < NE; k++)
86 if (active_zones[k] ==
false)
92 rhs.GetSubVector(dofs, rhs_loc);
95 M_loc_inv.
Mult(rhs_loc, dx_loc);
105 for (
int k = 0; k < NE; k++)
110 for (
int i = 0; i < ndof; i++)
112 el_min(k) = min(el_min(k), gf(k*ndof + i));
113 el_max(k) = max(el_max(k), gf(k*ndof + i));
118 void AdvectionOper::ComputeBounds(
const ParFiniteElementSpace &pfes,
119 const Vector &el_min,
const Vector &el_max,
120 Vector &dof_min, Vector &dof_max)
const
122 ParMesh *pmesh = pfes.GetParMesh();
123 L2_FECollection fec_bounds(0, pmesh->Dimension());
124 ParFiniteElementSpace pfes_bounds(pmesh, &fec_bounds);
125 ParGridFunction el_min_gf(&pfes_bounds), el_max_gf(&pfes_bounds);
126 const int NE = pmesh->GetNE(), ndofs = dof_min.Size() / NE;
131 el_min_gf.ExchangeFaceNbrData(); el_max_gf.ExchangeFaceNbrData();
132 const Vector &min_nbr = el_min_gf.FaceNbrData();
133 const Vector &max_nbr = el_max_gf.FaceNbrData();
134 const Table &el_to_el = pmesh->ElementToElementTable();
135 Array<int> face_nbr_el;
136 for (
int k = 0; k < NE; k++)
138 double k_min = el_min_gf(k), k_max = el_max_gf(k);
140 el_to_el.GetRow(k, face_nbr_el);
141 for (
int n = 0; n < face_nbr_el.Size(); n++)
143 if (face_nbr_el[n] < NE)
146 k_min = std::min(k_min, el_min_gf(face_nbr_el[n]));
147 k_max = std::max(k_max, el_max_gf(face_nbr_el[n]));
152 k_min = std::min(k_min, min_nbr(face_nbr_el[n] - NE));
153 k_max = std::max(k_max, max_nbr(face_nbr_el[n] - NE));
157 for (
int j = 0; j < ndofs; j++)
159 dof_min(k*ndofs + j) = k_min;
160 dof_max(k*ndofs + j) = k_max;
167 const double time_period,
198 for (
int k = 0; k < NE; k++)
221 u.ProjectGridFunction(input);
222 for (
int k = 0; k < NE; k++)
226 {
u.SetSubVector(dofs, 0.0); }
233 "Fixed (known) u values",
wsize, 0,
236 "Element markings", 0, 2*
wsize+60,
266 const double alpha = -1.0;
280 for (
int k = 0; k < NE; k++)
284 MPI_Allreduce(MPI_IN_PLACE, &h_min, 1, MPI_DOUBLE, MPI_MIN, pmesh.
GetComm());
286 double dt = 0.25 * h_min / order / 1.0;
287 double half_dt = 0.5 * dt;
298 ode_solver.
Init(adv_oper);
305 TimeLoop(
u, ode_solver, time_period, half_dt,
306 wsize,
"Extrap const u -- LO");
311 std::string mode_text =
"HO";
322 TimeLoop(n_grad_u, ode_solver, time_period, half_dt,
323 2*
wsize,
"Extrap const n.grad(u) -- Aslam -- LO");
328 lhs_bf.Mult(n_grad_u, rhs);
329 TimeLoop(
u, ode_solver, time_period, dt,
330 wsize,
"Extrap linear u -- Aslam -- " + mode_text);
338 TimeLoop(n_grad_n_grad_u, ode_solver, time_period, half_dt,
339 3*
wsize,
"Extrap const n.grad(n.grad(u)) -- Aslam -- LO");
344 lhs_bf.Mult(n_grad_n_grad_u, rhs);
345 TimeLoop(n_grad_u, ode_solver, time_period, dt,
346 2*
wsize,
"Extrap linear n.grad(u) -- Aslam -- " + mode_text);
349 lhs_bf.Mult(n_grad_u, rhs);
350 TimeLoop(
u, ode_solver, time_period, dt,
351 wsize,
"Extrap quadratic u -- Aslam -- " + mode_text);
363 grad_u_0.ProjectCoefficient(grad_u_0_coeff);
365 TimeLoop(grad_u_0, ode_solver, time_period, half_dt,
366 2*
wsize,
"Extrap const du_dx -- Bochkov -- LO");
367 TimeLoop(grad_u_1, ode_solver, time_period, half_dt,
368 3*
wsize,
"Extrap const du_dy -- Bochkov -- LO");
378 TimeLoop(
u, ode_solver, time_period, dt,
379 wsize,
"Extrap linear u -- Bochkov -- " + mode_text);
384 MFEM_ABORT(
"Quadratic Bochkov method is not implemented.");
387 else { MFEM_ABORT(
"Wrong input for extrapolation type (-et)."); }
396 double &err_L1,
double &err_L2,
414 Vector errors_L1(NE), errors_L2(NE), errors_LI(NE);
420 err_L1 = 0.0, err_L2 = 0.0, err_LI = 0.0;
421 double cut_volume = 0.0;
422 for (
int k = 0; k < NE; k++)
426 err_L1 += errors_L1(k);
427 err_L2 += errors_L2(k);
428 err_LI = std::max(err_LI, errors_LI(k));
432 MPI_Comm comm = pmesh.
GetComm();
433 MPI_Allreduce(MPI_IN_PLACE, &err_L1, 1, MPI_DOUBLE, MPI_SUM, comm);
434 MPI_Allreduce(MPI_IN_PLACE, &err_L2, 1, MPI_DOUBLE, MPI_SUM, comm);
435 MPI_Allreduce(MPI_IN_PLACE, &err_LI, 1, MPI_DOUBLE, MPI_MAX, comm);
436 MPI_Allreduce(MPI_IN_PLACE, &cut_volume, 1, MPI_DOUBLE, MPI_SUM, comm);
437 err_L1 /= cut_volume;
438 err_L2 /= cut_volume;
442 double t_final,
double dt,
443 int vis_x_pos, std::string vis_name)
450 for (
int ti = 0; !done;)
452 double dt_real = min(dt, t_final - t);
453 ode_solver.
Step(sltn, t, dt_real);
456 done = (t >= t_final - 1e-8*dt);
461 cout << vis_name+
" / time step: " << ti <<
", time: " << t << endl;
466 vis_name.c_str(), vis_x_pos,
wsize+60,
479 : pfes(space), K(adv), D(adv), K_smap(), M_lumped(Mlump)
484 for (
int row = 0, j = 0; row < n; row++)
486 for (
int end = I[row+1]; j < end; j++)
490 for (
int _j = I[col], _end = I[col+1];
true; _j++)
492 MFEM_VERIFY(_j != _end,
"Can't find the symmetric entry!");
494 if (J[_j] == row) {
K_smap[j] = _j;
break; }
509 const int s = du.
Size();
510 for (
int i = 0; i <
s; i++)
512 du(i) = (du(i) + rhs(i)) /
M_lumped(i);
525 for (
int i = 0, k = 0; i < n; i++)
528 for (
int end = I[i+1]; k < end; k++)
531 double kij = K_data[k];
532 double kji = K_data[
K_smap[k]];
533 double dij = fmax(fmax(0.0,-kij),-kji);
534 D_data[k] = kij + dij;
535 D_data[K_smap[k]] = kji + dij;
536 if (i != j) { rowsum += dij; }
538 D(i,i) =
K(i,i) - rowsum;
545 const int s = u.
Size();
552 for (
int i = 0; i <
s; i++)
555 for (
int k = I[i]; k < I[i + 1]; k++)
558 double u_j = (j <
s) ?
u(j) : u_np[j -
s];
559 double d_ij = D_data[k];
void SetSubVector(const Array< int > &dofs, const double value)
Set the entries listed in dofs to the given value.
Class for domain integration L(v) := (f, v)
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
void ExchangeFaceNbrData()
ParMesh * GetParMesh() const
Base abstract class for first order time dependent operators.
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]...
void ComputeDiscreteUpwindMatrix() const
Coefficient defined by a GridFunction. This coefficient is mesh dependent.
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.
int GetNE() const
Returns number of elements.
virtual void ProjectDiscCoefficient(VectorCoefficient &coeff)
Project a discontinuous vector coefficient as a grid function on a continuous finite element space...
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...
void Factor()
Factor the current DenseMatrix, *a.
DiscreteUpwindLOSolver(ParFiniteElementSpace &space, const SparseMatrix &adv, const Vector &Mlump)
virtual void ComputeElementL2Errors(Coefficient &exsol, Vector &error, const IntegrationRule *irs[]=NULL) const
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm) const
double * HostReadWriteData()
int GetNE() const
Returns number of elements in the mesh.
double GetElementSize(ElementTransformation *T, int type=0)
virtual const FiniteElement * GetFE(int i) const
const double * HostReadData() const
const int * HostReadJ() const
void CalcLOSolution(const Vector &u, const Vector &rhs, Vector &du) const
virtual DofTransformation * GetElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
virtual void ComputeElementL1Errors(Coefficient &exsol, Vector &error, const IntegrationRule *irs[]=NULL) const
virtual void Mult(const Vector &x, Vector &dx) const
Perform the action of the operator: y = k = f(x, t), where k solves the algebraic equation F(x...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
void ProjectGridFunction(const GridFunction &src)
Project the src GridFunction to this GridFunction, both of which must be on the same mesh...
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int GetOrder(int i) const
Returns the polynomial degree of the i'th finite element.
void Mult(const double *x, double *y) const
Matrix vector multiplication with the inverse of dense matrix.
int Size() const
For backward compatibility, define Size() to be synonym of Height().
virtual void ComputeElementMaxErrors(Coefficient &exsol, Vector &error, const IntegrationRule *irs[]=NULL) const
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
enum mfem::AdvectionOper::AdvectionMode adv_mode
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
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)
const int * HostReadI() const
Vector coefficient defined by a vector GridFunction.
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0) const
Computes y = alpha * A * x + beta * y.
Arbitrary order H1-conforming (continuous) finite elements.
double u(const Vector &xvec)
Class for parallel grid function.
Class for parallel meshes.
void MarkElements(const ParGridFunction &ls_func, Array< int > &elem_marker)
void ApplyDiscreteUpwindMatrix(ParGridFunction &u, Vector &du) const
double GetElementVolume(int i)
Arbitrary order "L2-conforming" discontinuous finite elements.
ParFiniteElementSpace * ParFESpace() const