22#include "libmesh/dense_matrix.h"
23#include "libmesh/dof_map.h"
24#include "libmesh/equation_systems.h"
25#include "libmesh/exodusII_io.h"
26#include "libmesh/fe.h"
27#include "libmesh/fe_interface.h"
28#include "libmesh/getpot.h"
29#include "libmesh/libmesh_logging.h"
30#include "libmesh/linear_solver.h"
31#include "libmesh/mesh_base.h"
32#include "libmesh/numeric_vector.h"
33#include "libmesh/quadrature_gauss.h"
34#include "libmesh/sparse_matrix.h"
40 const std::string & name,
41 const unsigned int number)
42 :
Parent(es, name, number),
45 _temporal_discretization_type(ForwardEuler),
69 if (string_type ==
"ForwardEuler")
72 if (string_type ==
"RK4")
76 libmesh_error_msg(
"Error: Invalid temporal discretization");
85 return "ForwardEuler";
91 libmesh_error_msg(
"Error: Invalid temporal discretization");
114 std::vector<std::unique_ptr<NumericVector<Number>>> k(4);
115 std::unique_ptr<NumericVector<Number>> temp;
168 *temp = *old_solution;
175 *temp = *old_solution;
182 *temp = *old_solution;
200 libmesh_error_msg(
"Error: Invalid temporal discretization in ClawSystem::solve_conservation_law");
207#ifdef LIBMESH_HAVE_EXODUS_API
210 libMesh::out << std::endl <<
"plotting time step " << step <<
", time = " <<
_time << std::endl;
212 std::ostringstream file_name;
213 file_name <<
"claw_solution."
223 file_name.str(), this->get_equation_systems(), 1,
_time);
234 GetPot infile(parameters_filename);
236 const std::string temporal_discretization_type_in = infile(
"temporal_discretization_type",
"ForwardEuler");
237 const Real LxF_constant_in = infile(
"LxF_constant", 1.);
238 const Real delta_t_in = infile(
"delta_t", 0.05);
239 const unsigned int n_time_steps_in = infile(
"n_time_steps", 0);
240 const unsigned int write_interval_in = infile(
"write_interval", 1);
252 libMesh::out << std::endl <<
"==== ClawSystem ====" << std::endl;
273 LOG_SCOPE(
"assemble_mass_matrix()",
"ClawSystem");
280 const unsigned int mesh_dim =
mesh.mesh_dimension();
284 std::unique_ptr<FEBase> fe =
FEBase::build(mesh_dim, fe_type);
288 fe->attach_quadrature_rule (&qrule);
291 const std::vector<Real> & JxW = fe->get_JxW();
292 const std::vector<std::vector<Real>> & phi = fe->get_phi();
299 std::vector<dof_id_type> dof_indices;
301 for (
const auto & elem :
mesh.active_local_element_ptr_range())
310 const unsigned int n_q1_dofs = dof_indices.size();
313 Ke.
resize(n_q1_dofs, n_q1_dofs);
316 unsigned int n_qpoints = qrule.
n_points();
323 Ke(i,j) += JxW[qp] * phi[j][qp] * phi[i][qp];
337 LOG_SCOPE(
"assemble_advection_matrices()",
"ClawSystem");
345 const unsigned int mesh_dim =
mesh.mesh_dimension();
349 libmesh_error_msg_if(
351 "Error: Expected number of advection matrices to match mesh dimension.");
355 std::unique_ptr<FEBase> fe =
FEBase::build(mesh_dim, fe_type);
359 fe->attach_quadrature_rule (&qrule);
362 const std::vector<Real> & JxW = fe->get_JxW();
363 const std::vector<std::vector<Real>> & phi = fe->get_phi();
364 const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
367 std::vector<DenseMatrix<Number>> K_vec(mesh_dim);
371 std::vector<dof_id_type> dof_indices;
373 for (
const auto & elem :
mesh.active_local_element_ptr_range())
382 const unsigned int n_q1_dofs = dof_indices.size();
385 for (
auto & Ke : K_vec)
386 Ke.resize(n_q1_dofs, n_q1_dofs);
389 unsigned int n_qpoints = qrule.
n_points();
400 K_vec[
dim](i,j) += JxW[qp] * phi[j][qp] * dphi[i][qp](
dim);
417 LOG_SCOPE(
"assemble_avg_coupling_matrices()",
"ClawSystem");
425 const unsigned int mesh_dim =
mesh.mesh_dimension();
429 libmesh_error_msg_if(
431 "Error: Expected number of average coupling matrices to match mesh dimension.");
435 std::unique_ptr<FEBase> fe_elem_face =
FEBase::build(mesh_dim, fe_type);
436 std::unique_ptr<FEBase> fe_neighbor_face =
FEBase::build(mesh_dim, fe_type);
440 fe_elem_face->attach_quadrature_rule(&qface);
441 fe_neighbor_face->attach_quadrature_rule(&qface);
446 const std::vector<std::vector<Real>> & phi_face = fe_elem_face->get_phi();
447 const std::vector<Real> & JxW_face = fe_elem_face->get_JxW();
448 const std::vector<Point> & qface_normals = fe_elem_face->get_normals();
449 const std::vector<Point> & qface_points = fe_elem_face->get_xyz();
452 const std::vector<std::vector<Real>> & phi_neighbor_face = fe_neighbor_face->get_phi();
456 std::vector<DenseMatrix<Number>> Kne_vec(mesh_dim);
457 std::vector<DenseMatrix<Number>> Ken_vec(mesh_dim);
458 std::vector<DenseMatrix<Number>> Kee_vec(mesh_dim);
459 std::vector<DenseMatrix<Number>> Knn_vec(mesh_dim);
463 std::vector<dof_id_type> dof_indices;
464 std::vector<dof_id_type> neighbor_dof_indices;
466 for (
const auto * elem :
mesh.active_local_element_ptr_range())
469 const unsigned int n_dofs = dof_indices.size();
471 for (
auto side : elem->side_index_range())
474 if (elem->neighbor_ptr(side) !=
nullptr)
479 const unsigned int elem_id = elem->
id();
480 const unsigned int neighbor_id = neighbor->
id();
483 if (elem_id < neighbor_id)
486 std::unique_ptr<const Elem> elem_side = elem->build_side_ptr(side);
489 fe_elem_face->reinit(elem, side);
492 std::vector<Point> qface_neighbor_points;
497 qface_neighbor_points);
500 fe_neighbor_face->reinit(neighbor, &qface_neighbor_points);
505 dof_map.
dof_indices (neighbor, neighbor_dof_indices);
506 const unsigned int n_neighbor_dofs = neighbor_dof_indices.size();
515 Kne_vec[
dim].resize(n_neighbor_dofs,
n_dofs);
516 Ken_vec[
dim].resize(
n_dofs, n_neighbor_dofs);
518 Knn_vec[
dim].resize(n_neighbor_dofs, n_neighbor_dofs);
540 Kee_vec[
dim](i,j) += 0.5 * JxW_face[qp] * phi_face[i][qp] * phi_face[j][qp] * qface_normals[qp](
dim);
548 Knn_vec[
dim](i,j) += -0.5 * JxW_face[qp] * phi_neighbor_face[i][qp] * phi_neighbor_face[j][qp] * qface_normals[qp](
dim);
558 Kne_vec[
dim](i,j) += -0.5 * JxW_face[qp] * phi_neighbor_face[i][qp] * phi_face[j][qp] * qface_normals[qp](
dim);
567 Ken_vec[
dim](i,j) += 0.5 * JxW_face[qp] * phi_face[i][qp] * phi_neighbor_face[j][qp] * qface_normals[qp](
dim);
575 mat->add_matrix(Kne_vec[
dim], neighbor_dof_indices, dof_indices);
576 mat->add_matrix(Ken_vec[
dim], dof_indices, neighbor_dof_indices);
577 mat->add_matrix(Kee_vec[
dim], dof_indices);
578 mat->add_matrix(Knn_vec[
dim], neighbor_dof_indices);
592 LOG_SCOPE(
"assemble_jump_coupling_matrix()",
"ClawSystem");
598 const unsigned int mesh_dim =
mesh.mesh_dimension();
602 std::unique_ptr<FEBase> fe_elem_face =
FEBase::build(mesh_dim, fe_type);
603 std::unique_ptr<FEBase> fe_neighbor_face =
FEBase::build(mesh_dim, fe_type);
607 fe_elem_face->attach_quadrature_rule(&qface);
608 fe_neighbor_face->attach_quadrature_rule(&qface);
613 const std::vector<std::vector<Real>> & phi_face = fe_elem_face->get_phi();
614 const std::vector<Real> & JxW_face = fe_elem_face->get_JxW();
615 const std::vector<Point> & qface_points = fe_elem_face->get_xyz();
618 const std::vector<std::vector<Real>> & phi_neighbor_face = fe_neighbor_face->get_phi();
631 std::vector<dof_id_type> dof_indices;
632 std::vector<dof_id_type> neighbor_dof_indices;
634 for (
const auto & elem :
mesh.active_local_element_ptr_range())
637 const unsigned int n_dofs = dof_indices.size();
639 for (
auto side : elem->side_index_range())
642 if (elem->neighbor_ptr(side) !=
nullptr)
647 const unsigned int elem_id = elem->
id();
648 const unsigned int neighbor_id = neighbor->
id();
651 if (elem_id < neighbor_id)
654 std::unique_ptr<const Elem> elem_side = elem->build_side_ptr(side);
657 fe_elem_face->reinit(elem, side);
660 std::vector<Point> qface_neighbor_points;
665 qface_neighbor_points);
668 fe_neighbor_face->reinit(neighbor, &qface_neighbor_points);
673 dof_map.
dof_indices (neighbor, neighbor_dof_indices);
674 const unsigned int n_neighbor_dofs = neighbor_dof_indices.size();
685 Knn.
resize (n_neighbor_dofs, n_neighbor_dofs);
697 Kee(i,j) += 0.5 * JxW_face[qp] * phi_face[i][qp] * phi_face[j][qp];
703 Knn(i,j) += 0.5 * JxW_face[qp] * phi_neighbor_face[i][qp] * phi_neighbor_face[j][qp];
710 Kne(i,j) -= 0.5 * JxW_face[qp] * phi_neighbor_face[i][qp] * phi_face[j][qp];
717 Ken(i,j) -= 0.5 * JxW_face[qp] * phi_face[i][qp] * phi_neighbor_face[j][qp];
723 _jump_matrix->add_matrix(Kne, neighbor_dof_indices, dof_indices);
724 _jump_matrix->add_matrix(Ken, dof_indices, neighbor_dof_indices);
738 LOG_SCOPE(
"assemble_boundary_condition_matrices()",
"ClawSystem");
746 const unsigned int mesh_dim =
mesh.mesh_dimension();
750 libmesh_error_msg_if(
752 "Error: Expected number of boundary condition matrices to match mesh dimension.");
756 std::unique_ptr<FEBase> fe_elem_face =
FEBase::build(mesh_dim, fe_type);
760 fe_elem_face->attach_quadrature_rule(&qface);
765 const std::vector<std::vector<Real>> & phi_face = fe_elem_face->get_phi();
766 const std::vector<Real> & JxW_face = fe_elem_face->get_JxW();
767 const std::vector<Point> & qface_normals = fe_elem_face->get_normals();
770 std::vector<DenseMatrix<Number>> K_vec(mesh_dim);
774 std::vector<dof_id_type> dof_indices;
776 for (
const auto & elem :
mesh.active_local_element_ptr_range())
779 const unsigned int n_dofs = dof_indices.size();
781 for (
auto side : elem->side_index_range())
784 if (elem->neighbor_ptr(side) ==
nullptr)
787 fe_elem_face->reinit(elem, side);
790 for (
auto & Ke : K_vec)
801 K_vec[
dim](i,j) += JxW_face[qp] * phi_face[i][qp] * phi_face[j][qp] * qface_normals[qp](
dim);
824 libmesh_error_msg_if(
826 "Error: Invalid dimension " <<
dim <<
" requested.");
834 libmesh_error_msg_if(
836 "Error: Invalid dimension " <<
dim <<
" requested.");
850 libmesh_error_msg_if(
852 "Error: Invalid dimension " <<
dim <<
" requested.");
935 _avg_matrices[i]->print_matlab(
"avg_matrix_" + std::to_string(i+1) +
".m");
950 for (
unsigned int i=0; i<2; ++i)
971 prepare_matrix(*mat);
974 prepare_matrix(*mat);
979 prepare_matrix(*mat);
virtual std::string system_type() const override
static TemporalDiscretizationType string_to_enum(std::string string_type)
Convert between string and enum for TemporalDiscretizationType.
void assemble_mass_matrix()
Helper functions called by assemble_all_matrices().
void solve_conservation_law()
Solve the conservation law.
std::vector< std::unique_ptr< SparseMatrix< Number > > > _avg_matrices
The "flux average" element boundary matrices.
void assemble_advection_matrices()
unsigned int get_n_time_steps()
TemporalDiscretizationType
Define an enumeration for temporal discretization types ForwardEuler = 1st-order Explicit Euler RK4 =...
void set_n_time_steps(unsigned int n_time_steps_in)
Set/get the number of time-steps.
Real _time
The current time in the conservation law solve.
unsigned int get_write_interval()
std::vector< std::unique_ptr< SparseMatrix< Number > > > _advection_matrices
The "advection" matrices.
virtual ~ClawSystem()
Destructor.
std::vector< std::unique_ptr< SparseMatrix< Number > > > _boundary_condition_matrices
The "boundary condition" matrices.
void set_temporal_discretization_type(TemporalDiscretizationType td_in)
Set/get the temporal discretization type.
TemporalDiscretizationType _temporal_discretization_type
String that defines the type of temporal discretization that we use.
void assemble_all_matrices()
Assemble the matrices we need to solve a conservation law.
void set_LxF_constant(Real LxF_constant_in)
Set/get the Lax-Friedrichs constant.
SparseMatrix< Number > & get_jump_matrix()
void set_write_interval(unsigned int write_interval_in)
Set/get write_interval.
std::unique_ptr< SparseMatrix< Number > > _mass_matrix
The mass matrix.
SparseMatrix< Number > & get_advection_matrix(unsigned int dim)
void assemble_boundary_condition_matrices()
void write_out_discretization_matrices()
Print discretization matrices to file in MATLAB-readable format.
void set_time(Real time_in)
Set/get the current time in the conservation law solve.
void assemble_avg_coupling_matrices()
SparseMatrix< Number > & get_boundary_condition_matrix(unsigned int dim)
SparseMatrix< Number > & get_mass_matrix()
Get a reference to one of the discretization matrices.
void assemble_jump_coupling_matrix()
Real _delta_t
The time step size.
static std::string enum_to_string(TemporalDiscretizationType enum_type)
unsigned int _n_time_steps
The number of time steps.
void set_delta_t(Real delta_t_in)
Set/get the time-step size.
SparseMatrix< Number > & get_avg_matrix(unsigned int dim)
ClawSystem(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
virtual void process_parameters_file(const std::string ¶meters_filename)
Set parameters for this system (e.g.
unsigned int _write_interval
The time step interval between writing out solutions.
Real _LxF_constant
The constant C in the Lax-Friedrichs flux.
virtual void assemble_claw_rhs(NumericVector< Number > &)=0
Assemble the right-hand side vector.
virtual void init_data() override
Initialize the system (e.g.
virtual void print_info()
Print out some info about the system's configuration.
std::unique_ptr< SparseMatrix< Number > > _jump_matrix
The "jump" element boundary matrix.
TemporalDiscretizationType get_temporal_discretization_type()
Defines a dense matrix for use in Finite Element-type computations.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
This class handles the numbering of degrees of freedom on a mesh.
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
void constrain_element_matrix(DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
Constrains the element matrix.
void attach_matrix(SparseMatrix< Number > &matrix)
Additional matrices may be attached to this DofMap.
This is the base class from which all geometric element types are derived.
virtual unsigned short dim() const =0
const Elem * neighbor_ptr(unsigned int i) const
This is the EquationSystems class.
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
void write_timestep(const std::string &fname, const EquationSystems &es, const int timestep, const Real time, const std::set< std::string > *system_names=nullptr)
Writes out the solution at a specific timestep.
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Order default_quadrature_order() const
SparseMatrix< Number > * matrix
The system matrix.
std::unique_ptr< LinearSolver< Number > > linear_solver
This class handles all the details of interfacing with various linear algebra packages like PETSc or ...
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
virtual void init_data() override
Initializes new data members of the system.
virtual void solve() override
Assembles & solves the linear system A*x=b.
This is the MeshBase class.
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
const Parallel::Communicator & comm() const
unsigned int n_points() const
This class implements specific orders of Gauss quadrature.
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
virtual void zero()=0
Set all entries to 0.
virtual void add(const numeric_index_type i, const numeric_index_type j, const T value)=0
Add value to the element (i,j).
SparseMatrix< Number > & add_matrix(std::string_view mat_name, ParallelType type=PARALLEL, MatrixBuildType mat_build_type=MatrixBuildType::AUTOMATIC)
Adds the additional matrix mat_name to this system.
const std::string & name() const
dof_id_type n_dofs() const
const FEType & variable_type(const unsigned int i) const
bool assemble_before_solve
Flag which tells the system to whether or not to call the user assembly function during each call to ...
dof_id_type n_local_dofs() const
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
virtual void update()
Update the local values to reflect the solution on neighboring processors.
const DofMap & get_dof_map() const
const MeshBase & get_mesh() const
The libMesh namespace provides an interface to certain functionality in the library.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...