43 const bool& add_neighbour_data_to_bulk)
57 if (add_neighbour_data_to_bulk)
64 const unsigned el_dim = this->
dim();
77 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
80 for (
unsigned i = 0;
i < el_dim;
i++)
97 if (add_neighbour_data_to_bulk)
104 unsigned n_neighbour_data = neighbour_data.size();
109 for (
unsigned n = 0; n < n_neighbour_data; n++)
126 const unsigned n_node = this->
nnode();
136 const unsigned el_dim = this->
dim();
143 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
146 for (
unsigned i = 0;
i < el_dim;
i++)
159 for (
unsigned i = 0;
i <
dim;
i++)
175 for (
unsigned i = 0;
i <
dim;
i++)
185 oomph_info << std::setw(5) << std::left << face_x[
i];
199 const unsigned n_node =
nnode();
215 for (
unsigned i = 0;
i < n_flux;
i++)
220 for (
unsigned i = 0;
i < n_flux;
i++)
226 for (
unsigned n = 0; n < n_node; n++)
228 const double psi_ = psi[n];
229 for (
unsigned i = 0;
i < n_flux;
i++)
244 const unsigned n_node =
nnode();
246 interpolation_data.resize(n_node);
255 for (
unsigned n = 0; n < n_node; n++)
257 interpolation_data[n] = this->
node_pt(n);
274 const unsigned n_node = this->
nnode();
281 for (
unsigned i = 0;
i < n_flux;
i++)
290 for (
unsigned l = 0; l < n_node; l++)
293 const double psi_ = psi(l);
295 for (
unsigned i = 0;
i < n_flux;
i++)
314 interpolated_u_neigh);
321 if (flag && (flag < 3))
325 interpolated_u_neigh,
357 for (
unsigned n = 0; n < n_flux; n++)
362 double old_var = u_int_local[n];
364 u_int_local[n] += fd_step;
369 u_int_local[n] = old_var;
371 u_int_local[n] -= fd_step;
373 this->
numerical_flux(n_out, u_int_local, u_ext_local, flux_minus);
376 for (
unsigned m = 0; m < n_flux; m++)
378 dflux_du_int(m, n) = (flux_plus[m] - flux_minus[m]) / (2.0 * fd_step);
382 u_int_local[n] = old_var;
387 old_var = u_ext_local[n];
389 u_ext_local[n] += fd_step;
394 u_ext_local[n] = old_var;
396 u_ext_local[n] -= fd_step;
398 this->
numerical_flux(n_out, u_int_local, u_ext_local, flux_minus);
401 for (
unsigned m = 0; m < n_flux; m++)
403 dflux_du_ext(m, n) = (flux_plus[m] - flux_minus[m]) / (2.0 * fd_step);
407 u_ext_local[n] = old_var;
422 if (flag && (flag < 3))
426 std::ostringstream error_stream;
428 <<
"Coupling data between elements not included in jacobian\n"
429 <<
"You should call DGMesh::setup_face_neighbour_info(true) to "
431 <<
"that this information is included in the jacobian\n";
434 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
441 const unsigned n_node =
nnode();
443 const unsigned el_dim =
dim();
453 for (
unsigned i = 0;
i < n_flux;
i++)
467 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
494 for (
unsigned l = 0; l < n_node; l++)
497 for (
unsigned i = 0;
i < n_flux;
i++)
501 flux_nodal_index[
i]);
507 residuals[local_eqn] -= psi(l) *
F[
i] * J;
516 for (
unsigned l2 = 0; l2 < n_node; l2++)
518 for (
unsigned i2 = 0; i2 < n_flux; i2++)
525 if (local_unknown >= 0)
529 jacobian(local_eqn, local_unknown) -=
530 psi(l) * dF_du_int(
i, i2) * psi(l2) * J;
536 unsigned neigh_n_node = neighbour_element_pt->
nnode();
540 for (
unsigned i2 = 0; i2 < n_flux; i2++)
542 neigh_flux_index[i2] = neighbour_element_pt->
flux_index(i2);
546 for (
unsigned l2 = 0; l2 < neigh_n_node; l2++)
549 for (
unsigned i2 = 0; i2 < n_flux; i2++)
555 flux_nodal_index[i2]);
558 if (local_unknown >= 0)
562 jacobian(local_eqn, local_unknown) -=
563 psi(l) * dF_du_ext(
i, i2) * psi(l2) * J;
581 const unsigned n_dof = this->
ndof();
620 std::ostringstream error_stream;
622 <<
"Cannot use a discontinuous formulation for the mass matrix when\n"
623 <<
"there are external data.\n "
624 <<
"Do not call Problem::enable_discontinuous_formulation()\n";
627 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
631 const unsigned n_dof = this->
ndof();
639 minv_res.resize(n_dof);
640 for (
unsigned n = 0; n < n_dof; n++)
676 const int& face_index,
689 const unsigned n_dim = this->
dim();
700 required_element_pt[0] =
this;
703 required_element_pt[1] =
dynamic_cast<DGElement*
>(
705 ->neighbour_face_pt(0)
708 required_element_pt[2] =
dynamic_cast<DGElement*
>(
710 ->neighbour_face_pt(0)
714 for (
unsigned i = 0;
i < n_flux;
i++)
718 slope_limiter_pt->
limit(
i, required_element_pt);
725 std::ostringstream error_stream;
726 error_stream <<
"Slope limiting is not implemented for this dimension: "
729 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
742 const unsigned n_arg = args.size();
755 else if (args[0] > 0.0)
765 double min = std::fabs(args[0]);
768 for (
unsigned i = 1;
i < n_arg;
i++)
776 else if (args[
i] < min)
787 else if (std::fabs(args[
i]) < min)
789 min = std::fabs(args[
i]);
802 const unsigned n_arg = args.size();
810 if (std::fabs(args[0]) < this->
M * h * h)
826 const double tol = 1.0e-16;
829 const unsigned n_node = required_element_pt[0]->nnode();
830 const double x_l = required_element_pt[0]->node_pt(0)->x(0);
831 const double x_r = required_element_pt[0]->node_pt(n_node - 1)->x(0);
832 const double h = x_r - x_l;
833 const double x0 = 0.5 * (x_l + x_r);
835 const double u_av = required_element_pt[0]->average_value(
i);
842 arg.push_back(u_av - required_element_pt[0]->node_pt(0)->value(
i));
846 if (required_element_pt[1] != required_element_pt[0])
848 arg.push_back(u_av - required_element_pt[1]->average_value(
i));
852 if (required_element_pt[2] != required_element_pt[0])
854 arg.push_back(required_element_pt[2]->average_value(
i) - u_av);
858 const double u_l = u_av - this->
minmod(arg);
862 arg.front() = required_element_pt[0]->node_pt(n_node - 1)->value(
i) - u_av;
865 const double u_r = u_av + this->
minmod(arg);
869 if ((std::fabs(u_l - required_element_pt[0]->node_pt(0)->value(
i)) > tol) &&
871 u_r - required_element_pt[0]->node_pt(n_node - 1)->value(
i)) > tol))
875 0.5 * (required_element_pt[1]
876 ->node_pt(required_element_pt[1]->nnode() - 1)
878 required_element_pt[1]->node_pt(0)->x(0));
881 0.5 * (required_element_pt[2]
882 ->node_pt(required_element_pt[2]->nnode() - 1)
884 required_element_pt[2]->node_pt(0)->x(0));
891 arg.push_back((required_element_pt[0]->node_pt(n_node - 1)->value(
i) -
892 required_element_pt[0]->node_pt(0)->value(
i)) /
897 double gradient_factor = 0.5;
900 gradient_factor = 1.0;
904 if (required_element_pt[0] != required_element_pt[1])
906 arg.push_back((u_av - required_element_pt[1]->average_value(
i)) /
907 (gradient_factor * (x0 - x0_l)));
911 if (required_element_pt[0] != required_element_pt[2])
913 arg.push_back((required_element_pt[2]->average_value(
i) - u_av) /
914 (gradient_factor * (x0_r - x0)));
918 double limited_gradient = this->
minmodB(arg, h);
921 for (
unsigned n = 0; n < n_node; n++)
923 double x = required_element_pt[0]->node_pt(n)->x(0) - x0;
924 required_element_pt[0]->node_pt(n)->set_value(
925 i, u_av + x * limited_gradient);
A Base class for DGElements.
DGMesh * DG_mesh_pt
Pointer to Mesh, which will be responsible for the neighbour finding.
void pre_compute_mass_matrix()
Function that computes and stores the (inverse) mass matrix.
void slope_limit(SlopeLimiter *const &slope_limiter_pt)
Limit the slope within the element.
virtual unsigned required_nflux()
Set the number of flux components.
bool Mass_matrix_has_been_computed
Boolean flag to indicate whether the mass matrix has been computed.
bool Mass_matrix_reuse_is_enabled
Boolean flag to indicate whether to reuse the mass matrix.
DGFaceElement * face_element_pt(const unsigned &i)
Access function for the faces.
void get_neighbouring_face_and_local_coordinate(const int &face_index, const Vector< double > &s, FaceElement *&face_element_pt, Vector< double > &s_face)
Return the neighbour info.
virtual void get_inverse_mass_matrix_times_residuals(Vector< double > &minv_res)
Function that returns the current value of the residuals multiplied by the inverse mass matrix (virtu...
DenseDoubleMatrix * M_pt
Pointer to storage for a mass matrix that can be recycled if desired.
Base class for Discontinuous Galerkin Faces. These are responsible for calculating the normal fluxes ...
virtual void numerical_flux(const Vector< double > &n_out, const Vector< double > &u_int, const Vector< double > &u_ext, Vector< double > &flux)
Calculate the normal flux, which is the dot product of our approximation to the flux with the outer u...
virtual void get_interpolation_data(Vector< Data * > &interpolation_data)
Get the data that are used to interpolate the unkowns in the element. These must be returned in order...
void setup_neighbour_info(const bool &add_neighbour_data_to_bulk)
Setup information from the neighbouring face, return a set of nodes (as data) in the neighour....
void report_info()
Output information about the present element and its neighbour.
Vector< FaceElement * > Neighbour_face_pt
Vector of neighbouring face elements at the integration points.
void add_flux_contributions(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Add the contribution from integrating the numerical flux.
Vector< Vector< unsigned > > Neighbour_external_data
Vector of the vectors that will store the number of the bulk external data that correspond to the dof...
virtual void dnumerical_flux_du(const Vector< double > &n_out, const Vector< double > &u_int, const Vector< double > &u_ext, DenseMatrix< double > &dflux_du_int, DenseMatrix< double > &dflux_du_ext)
Calculate the derivative of the normal flux, which is the dot product of our approximation to the flu...
virtual void interpolated_u(const Vector< double > &s, Vector< double > &f)
Return the interpolated values of the unknown fluxes.
virtual void numerical_flux_at_knot(const unsigned &ipt, const Shape &psi, Vector< double > &flux, DenseMatrix< double > &dflux_du_int, DenseMatrix< double > &dflux_du_ext, unsigned flag)
Calculate the normal numerical flux at the integration point. This is the most general interface that...
Vector< Vector< double > > Neighbour_local_coordinate
Vector of neighbouring local coordinates at the integration points.
virtual unsigned flux_index(const unsigned &i) const
Return the index at which the i-th unknown flux is stored.
virtual unsigned required_nflux()
Set the number of flux components.
virtual void neighbour_finder(FiniteElement *const &bulk_element_pt, const int &face_index, const Vector< double > &s_bulk, FaceElement *&face_element_pt, Vector< double > &s_face)
static double FaceTolerance
Class of matrices containing doubles, and stored as a DenseMatrix<double>, but with solving functiona...
virtual void lubksub(DoubleVector &rhs)
LU backsubstitution.
virtual void ludecompose()
LU decomposition using DenseLU (default linea solver)
void initialise(const T &val)
Initialize all values in the matrix to val.
void resize(const unsigned long &n)
Resize to a square nxn matrix; any values already present will be transfered.
FaceElements are elements that coincide with the faces of higher-dimensional "bulk" elements....
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
void outer_unit_normal(const Vector< double > &s, Vector< double > &unit_normal) const
Compute outer unit normal at the specified local coordinate.
FiniteElement *& bulk_element_pt()
Pointer to higher-dimensional "bulk" element.
double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s. Overloaded to get information from bulk...
double J_eulerian_at_knot(const unsigned &ipt) const
Return the Jacobian of the mapping from local to global coordinates at the ipt-th integration point O...
void get_local_coordinate_in_bulk(const Vector< double > &s, Vector< double > &s_bulk) const
Calculate the vector of local coordinate in the bulk element given the local coordinates in this Face...
unsigned & bulk_node_number(const unsigned &n)
Return the bulk node number that corresponds to the n-th local node number.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
double nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n. Produces suitably interpolated values for hanging nodes...
virtual void shape(const Vector< double > &s, Shape &psi) const =0
Calculate the geometric shape functions at local coordinate s. This function must be overloaded for e...
int nodal_local_eqn(const unsigned &n, const unsigned &i) const
Return the local equation number corresponding to the i-th value at the n-th local node.
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
unsigned nnode() const
Return the number of nodes.
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
unsigned nodal_dimension() const
Return the required Eulerian dimension of the nodes in this element.
virtual void shape_at_knot(const unsigned &ipt, Shape &psi) const
Return the geometric shape function at the ipt-th integration point.
unsigned nexternal_data() const
Return the number of external data objects.
virtual void fill_in_contribution_to_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &mass_matrix)
Add the elemental contribution to the mass matrix matrix. and the residuals vector....
static double Default_fd_jacobian_step
Double used for the default finite difference step in elemental jacobian calculations.
virtual void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the elemental contribution to the residuals vector. Note that this function will NOT initialise t...
unsigned ndof() const
Return the number of equations/dofs in the element.
int external_local_eqn(const unsigned &i, const unsigned &j)
Return the local equation number corresponding to the j-th value stored at the i-th external data.
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
Add a (pointer to an) external data object to the element and return its index (i....
virtual double knot(const unsigned &i, const unsigned &j) const =0
Return local coordinate s[j] of i-th integration point.
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
double minmod(Vector< double > &args)
The basic minmod function.
bool MUSCL
Boolean flag to indicate a MUSCL or straight min-mod limiter.
double minmodB(Vector< double > &args, const double &h)
The modified minmod function.
void limit(const unsigned &i, const Vector< DGElement * > &required_element_pt)
The limit function.
double M
Constant that is used in the modified min-mod function to provide better properties at extrema.
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation....
An OomphLibError object which should be thrown when an run-time error is encountered....
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
Base class for slope limiters.
virtual void limit(const unsigned &i, const Vector< DGElement * > &required_element_pt)
Basic function.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...