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)
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." 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);
358 QGauss qrule (mesh_dim, fe_type.default_quadrature_order());
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);
439 QGauss qface(mesh_dim-1, fe_type.default_quadrature_order());
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);
757 QGauss qface(mesh_dim-1, fe_type.default_quadrature_order());
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);
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
std::vector< std::unique_ptr< SparseMatrix< Number > > > _avg_matrices
The "flux average" element boundary matrices.
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
void set_n_time_steps(unsigned int n_time_steps_in)
Set/get the number of time-steps.
std::unique_ptr< SparseMatrix< Number > > _jump_matrix
The "jump" element boundary matrix.
This is the EquationSystems class.
SparseMatrix< Number > & get_boundary_condition_matrix(unsigned int dim)
void assemble_jump_coupling_matrix()
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
TemporalDiscretizationType get_temporal_discretization_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)
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
const EquationSystems & get_equation_systems() const
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.
Real _time
The current time in the conservation law solve.
const Parallel::Communicator & comm() const
Order default_quadrature_order() const
void assemble_all_matrices()
Assemble the matrices we need to solve a conservation law.
void set_time(Real time_in)
Set/get the current time in the conservation law solve.
void assemble_mass_matrix()
Helper functions called by assemble_all_matrices().
The libMesh namespace provides an interface to certain functionality in the library.
dof_id_type n_local_dofs() const
virtual void solve() override
Assembles & solves the linear system A*x=b.
const MeshBase & get_mesh() const
virtual void init_data() override
Initialize the system (e.g.
dof_id_type n_dofs() const
void set_temporal_discretization_type(TemporalDiscretizationType td_in)
Set/get the temporal discretization type.
This is the MeshBase class.
void set_write_interval(unsigned int write_interval_in)
Set/get write_interval.
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 > & get_advection_matrix(unsigned int dim)
TemporalDiscretizationType
Define an enumeration for temporal discretization types ForwardEuler = 1st-order Explicit Euler RK4 =...
This class handles the numbering of degrees of freedom on a mesh.
virtual void init_data() override
Initializes new data members of the system.
virtual void zero()=0
Set all entries to 0.
virtual void process_parameters_file(const std::string ¶meters_filename)
Set parameters for this system (e.g.
Real _delta_t
The time step size.
SparseMatrix< Number > & get_avg_matrix(unsigned int dim)
void assemble_boundary_condition_matrices()
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
ClawSystem(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
static std::string enum_to_string(TemporalDiscretizationType enum_type)
unsigned int get_n_time_steps()
SparseMatrix< Number > & get_jump_matrix()
std::vector< std::unique_ptr< SparseMatrix< Number > > > _boundary_condition_matrices
The "boundary condition" matrices.
virtual void print_info()
Print out some info about the system's configuration.
void solve_conservation_law()
Solve the conservation law.
void set_delta_t(Real delta_t_in)
Set/get the time-step size.
Real _LxF_constant
The constant C in the Lax-Friedrichs flux.
void write_out_discretization_matrices()
Print discretization matrices to file in MATLAB-readable format.
const Elem * neighbor_ptr(unsigned int i) const
virtual void update()
Update the local values to reflect the solution on neighboring processors.
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
virtual ~ClawSystem()
Destructor.
const FEType & variable_type(const unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static TemporalDiscretizationType string_to_enum(std::string string_type)
Convert between string and enum for TemporalDiscretizationType.
unsigned int _write_interval
The time step interval between writing out solutions.
unsigned int _n_time_steps
The number of time steps.
virtual unsigned short dim() const =0
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.
SparseMatrix< Number > * matrix
The system matrix.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
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...
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...
SparseMatrix< Number > & get_mass_matrix()
Get a reference to one of the discretization matrices.
This class implements specific orders of Gauss quadrature.
std::unique_ptr< SparseMatrix< Number > > _mass_matrix
The mass matrix.
void assemble_advection_matrices()
virtual std::string system_type() const override
void assemble_avg_coupling_matrices()
virtual void assemble_claw_rhs(NumericVector< Number > &)=0
Assemble the right-hand side vector.
const std::string & name() const
bool assemble_before_solve
Flag which tells the system to whether or not to call the user assembly function during each call to ...
void set_LxF_constant(Real LxF_constant_in)
Set/get the Lax-Friedrichs constant.
std::unique_ptr< LinearSolver< Number > > linear_solver
This class handles all the details of interfacing with various linear algebra packages like PETSc or ...
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 DofMap & get_dof_map() const
unsigned int get_write_interval()
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
TemporalDiscretizationType _temporal_discretization_type
String that defines the type of temporal discretization that we use.
std::vector< std::unique_ptr< SparseMatrix< Number > > > _advection_matrices
The "advection" matrices.
void constrain_element_matrix(DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
Constrains the element matrix.