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();
549 u.ExchangeFaceNbrData();
550 const Vector &u_np =
u.FaceNbrData();
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];
const double * HostReadData() const
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 Size() const
For backward compatibility, define Size() to be synonym of Height().
void ExchangeFaceNbrData()
int Dimension() const
Dimension of the reference space used within the elements.
void Mult(const double *x, double *y) const
Matrix vector multiplication with the inverse of dense matrix.
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]...
int Size() const
Returns the size of the vector.
Coefficient defined by a GridFunction. This coefficient is mesh dependent.
Data type dense matrix using column-major storage.
Abstract class for solving systems of ODEs: dx/dt = f(x,t)
int * GetI()
Return the array I.
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.
virtual void ComputeElementMaxErrors(Coefficient &exsol, Vector &error, const IntegrationRule *irs[]=NULL) const
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm) const
DiscreteUpwindLOSolver(ParFiniteElementSpace &space, const SparseMatrix &adv, const Vector &Mlump)
double * HostReadWriteData()
double GetElementSize(ElementTransformation *T, int type=0)
void CalcLOSolution(const Vector &u, const Vector &rhs, Vector &du) const
const int * HostReadJ() const
ParMesh * GetParMesh() const
int GetNE() const
Returns number of elements in the mesh.
void ComputeDiscreteUpwindMatrix() const
virtual DofTransformation * GetElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
virtual const FiniteElement * GetFE(int i) const
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...
ParFiniteElementSpace * ParFESpace() const
int GetOrder(int i) const
Returns the polynomial degree of the i'th finite element.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int GetDof() const
Returns the number of degrees of freedom in the finite element.
virtual void ComputeElementL2Errors(Coefficient &exsol, Vector &error, const IntegrationRule *irs[]=NULL) const
const int * HostReadI() const
int GetNE() const
Returns number of elements.
void Init(TimeDependentOperator &f_) override
Associate a TimeDependentOperator with the ODE solver.
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 GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
enum mfem::AdvectionOper::AdvectionMode adv_mode
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
void ApplyDiscreteUpwindMatrix(ParGridFunction &u, Vector &du) const
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)
Vector coefficient defined by a vector GridFunction.
ParFiniteElementSpace & pfes
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)
double GetElementVolume(int i)
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 "L2-conforming" discontinuous finite elements.