47 const bool &add_neighbour_data_to_bulk)
65 const unsigned el_dim = this->
dim();
70 const unsigned n_dim = bulk_element_pt->
dim();
78 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
81 for(
unsigned i=0;
i<el_dim;
i++)
90 get_neighbouring_face_and_local_coordinate(this->
face_index(),
94 if(add_neighbour_data_to_bulk)
101 unsigned n_neighbour_data = neighbour_data.size();
106 for(
unsigned n=0;n<n_neighbour_data;n++)
123 const unsigned n_node = this->
nnode();
133 const unsigned el_dim = this->
dim();
140 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
143 for(
unsigned i=0;
i<el_dim;
i++)
154 for(
unsigned i=0;
i<
dim;
i++)
164 for(
unsigned i=0;
i<
dim;
i++)
168 oomph_info << std::setw(5) << std::left << face_x[
i];
183 const unsigned n_node =
nnode();
185 if(n_node==0) {
return;}
196 for(
unsigned i=0;
i<n_flux;
i++)
201 for(
unsigned i=0;
i<n_flux;
i++) {u[
i] = 0.0;}
204 for(
unsigned n=0;n<n_node;n++)
206 const double psi_ = psi[n];
207 for(
unsigned i=0;
i<n_flux;
i++)
223 const unsigned n_node =
nnode();
225 interpolation_data.resize(n_node);
228 if(n_node==0) {
return;}
231 for(
unsigned n=0;n<n_node;n++)
233 interpolation_data[n] = this->
node_pt(n);
250 const unsigned n_node = this->
nnode();
257 for(
unsigned i=0;
i<n_flux;
i++)
266 for(
unsigned l=0;l<n_node;l++)
269 const double psi_ = psi(l);
271 for(
unsigned i=0;
i<n_flux;
i++)
274 interpolated_u[
i] += this->
nodal_value(l,flux_nodal_index[
i])*psi_;
289 neighbour_element_pt->
291 interpolated_u_neigh);
295 interpolated_u_neigh,flux);
298 if(flag && (flag < 3))
301 interpolated_u_neigh,dflux_du_int,
333 for(
unsigned n=0;n<n_flux;n++)
338 double old_var = u_int_local[n];
340 u_int_local[n] += fd_step;
345 u_int_local[n] = old_var;
347 u_int_local[n] -= fd_step;
352 for(
unsigned m=0;m<n_flux;m++)
354 dflux_du_int(m,n) = (flux_plus[m] - flux_minus[m])/(2.0*fd_step);
358 u_int_local[n] = old_var;
363 old_var = u_ext_local[n];
365 u_ext_local[n] += fd_step;
370 u_ext_local[n] = old_var;
372 u_ext_local[n] -= fd_step;
377 for(
unsigned m=0;m<n_flux;m++)
379 dflux_du_ext(m,n) = (flux_plus[m] - flux_minus[m])/(2.0*fd_step);
383 u_ext_local[n] = old_var;
398 if(flag && (flag < 3))
402 std::ostringstream error_stream;
404 "Coupling data between elements not included in jacobian\n" 406 "You should call DGMesh::setup_face_neighbour_info(true) to ensure\n" 408 "that this information is included in the jacobian\n";
411 OOMPH_CURRENT_FUNCTION,
412 OOMPH_EXCEPTION_LOCATION);
419 const unsigned n_node =
nnode();
421 const unsigned el_dim =
dim();
431 for(
unsigned i=0;
i<n_flux;
i++)
445 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
469 for(
unsigned l=0;l<n_node;l++)
472 for(
unsigned i=0;
i<n_flux;
i++)
482 residuals[local_eqn] -= psi(l)*F[
i]*J;
492 for(
unsigned l2=0;l2<n_node;l2++)
494 for(
unsigned i2=0;i2<n_flux;i2++)
497 int local_unknown = bulk_elem_pt
501 if(local_unknown >= 0)
505 jacobian(local_eqn,local_unknown) -=
506 psi(l)*dF_du_int(i,i2)*psi(l2)*J;
512 unsigned neigh_n_node = neighbour_element_pt->
nnode();
516 for(
unsigned i2=0;i2<n_flux;i2++)
518 neigh_flux_index[i2] = neighbour_element_pt->
flux_index(i2);
522 for(
unsigned l2=0;l2<neigh_n_node;l2++)
525 for(
unsigned i2=0;i2<n_flux;i2++)
534 if(local_unknown >= 0)
538 jacobian(local_eqn,local_unknown) -=
539 psi(l)*dF_du_ext(i,i2)*psi(l2)*J;
558 const unsigned n_dof = this->
ndof();
566 M_pt->resize(n_dof,n_dof);
568 M_pt->initialise(0.0);
578 Mass_matrix_has_been_computed=
true;
594 std::ostringstream error_stream;
596 "Cannot use a discontinuous formulation for the mass matrix when\n" 598 "there are external data.\n " <<
599 "Do not call Problem::enable_discontinuous_formulation()\n";
602 OOMPH_CURRENT_FUNCTION,
603 OOMPH_EXCEPTION_LOCATION);
607 const unsigned n_dof = this->
ndof();
612 minv_res.resize(n_dof);
613 for(
unsigned n=0;n<n_dof;n++) {minv_res[n] = 0.0;}
616 if(Mass_matrix_reuse_is_enabled && Mass_matrix_has_been_computed)
625 M_pt->resize(n_dof,n_dof);
627 M_pt->initialise(0.0);
637 Mass_matrix_has_been_computed=
true;
641 M_pt->lubksub(minv_res);
650 DG_mesh_pt->neighbour_finder(
this,face_index,s,face_element_pt,s_face);
658 const unsigned n_dim = this->
dim();
669 required_element_pt[0] =
this;
672 required_element_pt[1] =
dynamic_cast<DGElement*
>(
676 required_element_pt[2] =
dynamic_cast<DGElement*
>(
681 for(
unsigned i=0;
i<n_flux;
i++)
685 slope_limiter_pt->
limit(
i,required_element_pt);
692 std::ostringstream error_stream;
693 error_stream <<
"Slope limiting is not implemented for this dimension: " 696 OOMPH_CURRENT_FUNCTION,
697 OOMPH_EXCEPTION_LOCATION);
710 const unsigned n_arg = args.size();
712 if(n_arg==0) {
return 0.0;}
716 if(args[0] < 0.0) {sign = -1;}
717 else if(args[0] > 0.0) {sign = 1;}
721 double min = std::fabs(args[0]);
724 for(
unsigned i=1;
i<n_arg;
i++)
728 if(args[
i] < 0.0) {
return 0.0;}
729 else if(args[
i] < min) {min = args[
i];}
733 if(args[
i] > 0.0) {
return 0.0;}
734 else if(std::fabs(args[
i]) < min) {min = std::fabs(args[i]);}
746 const unsigned n_arg = args.size();
748 if(n_arg==0) {
return 0.0;}
751 if(std::fabs(args[0]) < this->M*h*h) {
return args[0];}
753 else {
return minmod(args);}
761 const double tol = 1.0e-16;
764 const unsigned n_node = required_element_pt[0]->nnode();
765 const double x_l = required_element_pt[0]->node_pt(0)->x(0);
766 const double x_r = required_element_pt[0]->node_pt(n_node-1)->x(0);
767 const double h = x_r - x_l;
768 const double x0 = 0.5*(x_l + x_r);
770 const double u_av = required_element_pt[0]->average_value(i);
776 arg.push_back(u_av - required_element_pt[0]->
node_pt(0)->value(i));
780 if(required_element_pt[1] != required_element_pt[0])
781 {arg.push_back(u_av - required_element_pt[1]->average_value(i));}
784 if(required_element_pt[2] != required_element_pt[0])
785 {arg.push_back(required_element_pt[2]->average_value(i) - u_av);}
788 const double u_l = u_av - this->minmod(arg);
792 arg.front() = required_element_pt[0]->node_pt(n_node-1)->value(i) - u_av;
795 const double u_r = u_av + this->minmod(arg);
799 if((std::fabs(u_l - required_element_pt[0]->
node_pt(0)->value(i)) > tol) &&
800 (std::fabs(u_r - required_element_pt[0]->
node_pt(n_node-1)->value(i))
805 0.5*(required_element_pt[1]->node_pt(required_element_pt[1]->
nnode()-1)
806 ->x(0) + required_element_pt[1]->node_pt(0)->x(0));
809 0.5*(required_element_pt[2]->node_pt(required_element_pt[2]->
nnode()-1)
810 ->x(0) + required_element_pt[2]->node_pt(0)->x(0));
813 arg.clear(); arg.reserve(3);
816 arg.push_back((required_element_pt[0]->
node_pt(n_node-1)->value(i) -
817 required_element_pt[0]->
node_pt(0)->value(i))/h);
821 double gradient_factor = 0.5;
822 if(MUSCL) {gradient_factor = 1.0;}
825 if(required_element_pt[0]!=required_element_pt[1])
828 (u_av - required_element_pt[1]->average_value(i))/
829 (gradient_factor*(x0 - x0_l)));
833 if(required_element_pt[0]!=required_element_pt[2])
836 (required_element_pt[2]->average_value(i) - u_av)/
837 (gradient_factor*(x0_r - x0)));
841 double limited_gradient = this->minmodB(arg,h);
844 for(
unsigned n=0;n<n_node;n++)
846 double x = required_element_pt[0]->node_pt(n)->x(0) - x0;
847 required_element_pt[0]->node_pt(n)
848 ->set_value(i,u_av + x*limited_gradient);
Class of matrices containing doubles, and stored as a DenseMatrix<double>, but with solving functiona...
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...
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...
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...
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...
Vector< Vector< unsigned > > Neighbour_external_data
static double FaceTolerance
virtual void limit(const unsigned &i, const Vector< DGElement *> &required_element_pt)
Basic function.
void report_info()
Output information about the present element and its neighbour.
Vector< Vector< double > > Neighbour_local_coordinate
Vector of neighbouring local coordinates at the integration points.
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
FaceElement * neighbour_face_pt(const unsigned &i)
Access function for neighbouring face information.
void outer_unit_normal(const Vector< double > &s, Vector< double > &unit_normal) const
Compute outer unit normal at the specified local coordinate.
Vector< FaceElement * > Neighbour_face_pt
Vector of neighbouring face elements at the integration points.
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...
A Base class for DGElements.
double minmodB(Vector< double > &args, const double &h)
The modified minmod function.
unsigned & bulk_node_number(const unsigned &n)
Return the bulk node number that corresponds to the n-th local node number.
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
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...
void pre_compute_mass_matrix()
Function that computes and stores the (inverse) mass matrix.
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
unsigned nexternal_data() const
Return the number of external data objects.
unsigned ndof() const
Return the number of equations/dofs in the element.
unsigned nodal_dimension() const
Return the required Eulerian dimension of the nodes in this element.
Base class for slope limiters.
virtual void interpolated_u(const Vector< double > &s, Vector< double > &f)
Return the interpolated values of the unknown fluxes.
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
void limit(const unsigned &i, const Vector< DGElement *> &required_element_pt)
The limit function.
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...
virtual void shape_at_knot(const unsigned &ipt, Shape &psi) const
Return the geometric shape function at the ipt-th integration point.
virtual double knot(const unsigned &i, const unsigned &j) const =0
Return local coordinate s[j] of i-th integration point.
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_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...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
void setup_neighbour_info(const bool &add_neighbour_data_to_bulk)
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...
double minmod(Vector< double > &args)
The basic minmod function.
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
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. Note that this function should NOT initialise the residuals vector or the mass matrix. It must be called after the residuals vector and jacobian matrix have been initialised to zero. The default is deliberately broken.
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
Base class for Discontinuous Galerkin Faces. These are responsible for calculating the normal fluxes ...
FiniteElement *& bulk_element_pt()
Pointer to higher-dimensional "bulk" element.
virtual unsigned flux_index(const unsigned &i) const
Return the index at which the i-th unknown flux is stored.
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...
unsigned nnode() const
Return the number of nodes.
void add_flux_contributions(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Add the contribution from integrating the numerical flux.
static double Default_fd_jacobian_step
Double used for the default finite difference step in elemental jacobian calculations.
void slope_limit(SlopeLimiter *const &slope_limiter_pt)
Limit the slope within the element.
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...
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation...
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...
virtual unsigned required_nflux()
Set the number of flux components.
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...