21 std::cout <<
"DEBUG: Starting construction of a TwoD_TVDLF_Mesh object. \n";
26 if(std::min(
NX - 1,
NY - 1) <= 1) {
28 problem =
" The TwoD_TVDLF_Mesh object is trying to construct itself \n";
29 problem +=
" with just one element in one of the directions! \n";
34 std::cout <<
"DEBUG: configuration of the black mesh \n";
49 std::set<int> faces_s;
51 std::set<int> faces_e;
53 std::set<int> faces_n;
55 std::set<int> faces_w;
58 std::set<int> faces_se(faces_s);
60 std::set<int> faces_ne(faces_n);
62 std::set<int> faces_nw(faces_n);
64 std::set<int> faces_sw(faces_s);
70 for(std::size_t i = 1; i <=
NX - 3; ++i) {
75 for(std::size_t j = 1; j <=
NY - 3; ++j) {
77 for(std::size_t i = 1; i <=
NX - 3; ++i) {
84 for(std::size_t i = 1; i <=
NX - 3; ++i) {
91 std::cout <<
"DEBUG: configuration of the red mesh \n";
98 for(std::size_t i = 1; i <=
NX - 2; ++i) {
99 RED_ELTS.push_back(
TwoD_TVDLF_Elt((X[i-1] + X[i]) / 2, (X[i] + X[i+1]) / 2, Y[0], (Y[0] + Y[1]) / 2, ptr,
true, faces_s));
103 for(std::size_t j = 1; j <=
NY - 2; ++j) {
104 RED_ELTS.push_back(
TwoD_TVDLF_Elt(X[0], (X[1] + X[0]) / 2, (Y[j-1] + Y[j]) / 2, (Y[j] + Y[j+1]) / 2, ptr,
true, faces_w));
105 for(std::size_t i = 1; i <=
NX - 2; ++i) {
106 RED_ELTS.push_back(
TwoD_TVDLF_Elt((X[i-1] + X[i]) / 2, (X[i] + X[i+1]) / 2, (Y[j-1] + Y[j]) / 2, (Y[j] + Y[j+1]) / 2, ptr));
112 for(std::size_t i = 1; i <=
NX - 2; ++i) {
119 std::cout <<
"DEBUG: computing black to red projection \n";
157 eb -> add_contribution(&(*er), s1, s2, faces_nw);
170 eb -> add_contribution(&(*er), s1, s2, faces_sw);
183 eb -> add_contribution(&(*er), s1, s2, faces_ne);
196 eb -> add_contribution(&(*er), s1, s2, faces_se);
202 std::cout <<
"DEBUG: computing red to black projection \n";
221 std::set<int> external = er -> get_external_faces();
222 if((external.find(2) == external.end()) &&
223 (external.find(3) == external.end())) {
234 er -> add_contribution(&(*eb), s1, s2, faces_nw);
236 if((external.find(0) == external.end()) &&
237 (external.find(3) == external.end())) {
248 er -> add_contribution(&(*eb), s1, s2, faces_sw);
250 if((external.find(1) == external.end()) &&
251 (external.find(2) == external.end())) {
262 er -> add_contribution(&(*eb), s1, s2, faces_ne);
264 if((external.find(0) == external.end()) &&
265 (external.find(1) == external.end())) {
276 er -> add_contribution(&(*eb), s1, s2, faces_se);
282 std::cout <<
"DEBUG: setting up pointers to NESW elts in black mesh\n";
289 const std::size_t offset(
NX - 1);
291 std::set< int > faces(eb -> get_external_faces());
292 if(eb -> face_is_internal(0)) {
294 eb -> set_ptrs(0, &(*eb) - offset);
296 if(eb -> face_is_internal(1)) {
298 eb -> set_ptrs(1, &(*eb) + 1);
300 if(eb -> face_is_internal(2)) {
302 eb -> set_ptrs(2, &(*eb) + offset);
304 if(eb -> face_is_internal(3)) {
306 eb -> set_ptrs(3, &(*eb) - 1);
312 std::cout <<
"DEBUG: setting up pointers to NESW elts in red mesh\n";
320 const std::size_t offset(
NX);
322 std::set< int > faces(er -> get_external_faces());
323 if(er -> face_is_internal(0)) {
325 er -> set_ptrs(0, &(*er) - offset);
327 if(er -> face_is_internal(1)) {
329 er -> set_ptrs(1, &(*er) + 1);
331 if(er -> face_is_internal(2)) {
333 er -> set_ptrs(2, &(*er) + offset);
335 if(er -> face_is_internal(3)) {
337 er -> set_ptrs(3, &(*er) - 1);
343 std::cout <<
"DEBUG: initialising the black mesh \n";
375 eb -> set_slope_x((Qe - Qw) / (xe[0] - xw[0]));
376 eb -> set_slope_y((Qn - Qs) / (xn[1] - xs[1]));
378 eb -> set_Q_mid((Qe + Qw + Qn + Qs) / 4);
383 std::cout <<
"DEBUG: mesh constructor complete \n";
407 dump.open(filename.c_str());
413 dump << e -> get_x(s)[0] <<
" " << e -> get_x(s)[1] <<
" ";
415 dump << e -> get_Q(s)[i] <<
" ";
417 dump << e -> get_max_dt();
425 if(e -> face_is_external(1))
435 dump.open(filename.c_str());
441 for(
unsigned i = 0; i <
NX - 1; ++i) {
442 dump << e -> get_x(s)[0] <<
"\n";
451 dump.open(filename.c_str());
457 for(
unsigned i = 0; i <
NY - 1; ++i) {
458 dump << e -> get_x(s)[1] <<
"\n";
467 dump.open(filename.c_str());
475 dump << e -> get_Q(s)[i] <<
" ";
477 dump << e -> get_max_dt() <<
" ";
494 return e -> get_Q(s);
503 std::cout <<
"[DEBUG] in update with MESH_TIME = " <<
MESH_TIME <<
"\n";
504 std::cout <<
"[DEBUG] in update with max_dt = " << max_dt <<
"\n";
509 e -> set_Q_mid(e -> contributed_Q() / e -> get_dA());
519 first_dt = e -> get_max_dt();
522 first_dt = std::min(first_dt, e -> get_max_dt());
525 std::cout <<
"[DEBUG] in update with first_dt = " << first_dt <<
"\n";
527 std::cout <<
"[DEBUG] in update with first_dt*CFL = " << first_dt <<
"\n";
529 if(first_dt > max_dt / 2) {
530 first_dt = max_dt / 2;
532 std::cout <<
"[DEBUG] in update with final first_dt = " << first_dt <<
"\n";
540 e -> add_flux_contributions(first_dt);
546 std::cout <<
"[DEBUG] in update with MESH_TIME = " <<
MESH_TIME <<
"\n";
552 e -> set_Q_mid(e -> contributed_Q() / e -> get_dA());
562 second_dt = e -> get_max_dt();
565 second_dt = std::min(second_dt, e -> get_max_dt());
568 std::cout <<
"[DEBUG] in update with second_dt = " << second_dt <<
"\n";
570 std::cout <<
"[DEBUG] in update with second_dt*CFL = " << second_dt <<
"\n";
572 if(first_dt + second_dt > max_dt) {
573 second_dt = max_dt - first_dt;
575 std::cout <<
"[DEBUG] in update with final second_dt = " << second_dt <<
"\n";
583 e -> add_flux_contributions(second_dt);
589 std::cout <<
"[DEBUG] in update with MESH_TIME = " <<
MESH_TIME <<
"\n";
591 return first_dt + second_dt;
596 std::cout <<
" computing to " << t_end <<
"\n";
609 while(e != elts -> end()) {
612 I += e -> get_int_Q(sw, ne);
624 while(e != elts -> end()) {
628 double west = e -> get_x(sw)[ 0 ];
629 double east = e -> get_x(ne)[ 0 ];
630 if((x[ 0 ] >= west) && (x[ 0 ] <= east)) {
640 double south = e -> get_x(sw)[ 1 ];
641 double north = e -> get_x(ne)[ 1 ];
642 if((x[ 1 ] >= south) && (x[ 1 ] <= north)) {
645 if(e + Mx < elts -> end()) {
650 problem =
"The TwoD_TVDLF_Mesh::get_elt_iter_from_x method has been called\n";
651 problem +=
"for a position that is outside the boundaries of the mesh.\n";
662 if(mesh_colour ==
"black") {
664 }
else if(mesh_colour ==
"red") {
668 problem =
" The TwoD_TVDLF_Mesh object has been passed an unrecognised mesh identifier. \n";
669 problem +=
" valid options are 'black' or 'red'.\n";
677 if(mesh_colour ==
"black") {
679 }
else if(mesh_colour ==
"red") {
683 problem =
" The TwoD_TVDLF_Mesh object has been passed an unrecognised mesh identifier. \n";
684 problem +=
" valid options are 'black' or 'red'.\n";
700 while(e != elt_vector -> end()) {
705 e -> set_slope_x(
minmod(slope_east, slope_west));
706 e -> set_slope_y(
minmod(slope_north, slope_south));
712 while(e != elt_vector -> end()) {
723 e -> set_slope_x(slope_x);
724 e -> set_slope_y(slope_y);
729 while(e != elt_vector -> end()) {
735 minmod(slope_east, slope_west * 2.),
736 minmod(slope_east * 2., slope_west)
738 e -> set_slope_x(slope_x);
740 minmod(slope_north, slope_south * 2.),
741 minmod(slope_north * 2., slope_south)
743 e -> set_slope_y(slope_y);
749 problem =
" The TwoD_TVDLF_Mesh object has an unrecognised 'LIMITER' identifier. \n";
756 std::set< int > faces(e -> get_external_faces());
757 const int face_index(1);
758 if(e -> face_is_external(face_index)) {
764 elt_iter j(e -> get_ptrs(face_index));
765 diff = (j -> get_Q_mid() - e -> get_Q_mid())
766 / (j -> get_x_mid()[0] - e -> get_x_mid()[0]);
773 std::set< int > faces(e -> get_external_faces());
774 const int face_index(3);
775 if(e -> face_is_external(face_index)) {
781 elt_iter j(e -> get_ptrs(face_index));
782 diff = (e -> get_Q_mid() - j -> get_Q_mid())
783 / (e -> get_x_mid()[0] - j -> get_x_mid()[0]);
790 std::set< int > faces(e -> get_external_faces());
791 const int face_index(2);
792 if(e -> face_is_external(face_index)) {
798 elt_iter j(e -> get_ptrs(face_index));
799 diff = (j -> get_Q_mid() - e -> get_Q_mid())
800 / (j -> get_x_mid()[1] - e -> get_x_mid()[1]);
807 std::set< int > faces(e -> get_external_faces());
808 const int face_index(0);
809 if(e -> face_is_external(face_index)) {
815 elt_iter j(e -> get_ptrs(face_index));
816 diff = (e -> get_Q_mid() - j -> get_Q_mid())
817 / (e -> get_x_mid()[1] - j -> get_x_mid()[1]);
824 std::set< int > faces(e -> get_external_faces());
825 if(e -> face_is_external(0)) {
829 }
else if(e -> face_is_external(2)) {
837 diff = (jN -> get_Q_mid() - jS -> get_Q_mid())
838 / (jN -> get_x_mid()[1] - jS -> get_x_mid()[1]);
845 std::set< int > faces(e -> get_external_faces());
846 if(e -> face_is_external(1)) {
850 }
else if(e -> face_is_external(3)) {
858 diff = (jE -> get_Q_mid() - jW -> get_Q_mid())
859 / (jE -> get_x_mid()[0] - jW -> get_x_mid()[0]);
876 for(std::size_t i = 0; i < A.size(); ++i) {
878 * std::min(std::abs(A[i]), std::abs(B[i])));
885 for(std::size_t i = 0; i < A.size(); ++i) {
887 * std::max(std::abs(A[i]), std::abs(B[i])));
920 std::vector<bool> inflow = e -> p_system -> edge_values(face_index, e -> get_x(se), Q);
924 e -> p_system -> edge_slopes(face_index, e -> get_x(se), sigma_n);
927 if(inflow[ i ] ==
true) {
929 diff[ i ] = sigma_n[ i ];
Specification of a two dimensional linear element for use in a TVD Lax-Friedrichs scheme.
Specification of an object that represents a two dimensional mesh for TVD LF methods.
An DenseVector class – a dense vector object.
void push_back(const _Type &fill)
A pass-thru definition of push_back.
std::size_t size() const
A pass-thru definition to get the size of the vector.
A generic runtime exception.
A class to represent a two-dimensional hyperbolic system of equations.
vector_of_elts * get_elts_from_colour(std::string mesh_colour)
Given a choice of black or red mesh, return a pointer to the appropriate vector of elements.
vector_of_elts RED_ELTS
An STL vector of linear elements – the red mesh.
virtual void actions_before_time_step1(const double &time_step)
A virtual method that is run before the first time update.
DenseVector< double > get_point_values(const DenseVector< double > &x)
Get the vector of unknowns at a point in the 2D mesh.
std::size_t get_number_elts_in_x(std::string mesh_colour)
Given a choice of black or red mesh, return the number of elements in the x-direction.
void dump_gnu(std::string filename)
Dump the data to a given filename in a gnuplot format.
DenseVector< double > minmod(DenseVector< double > A, DenseVector< double > B) const
A vector version of the minmod operator.
void calc_slopes(vector_of_elts *elt_vector)
Use the appropriate limiter to approximate the slope in each element in the mesh.
DenseVector< double > integrate(std::string mesh_colour="black")
Integrate the concentration values across the entire mesh.
void update_to(const double &CFL, const double &t_end)
Update the mesh object to a set time level.
unsigned LIMITER
Slope limiter method.
DenseVector< double > EW_diff(elt_iter e)
Compute a finite difference approximation of the derivative in the compass direction.
DenseVector< double > west_diff(elt_iter e) const
Compute a finite difference approximation of the derivative in the compass direction.
DenseVector< double > east_diff(elt_iter e) const
Compute a finite difference approximation of the derivative in the compass direction.
DenseVector< double > south_diff(elt_iter e) const
Compute a finite difference approximation of the derivative in the compass direction.
TwoD_TVDLF_Mesh(const DenseVector< double > &X, const DenseVector< double > &Y, TwoD_Hyperbolic_System *ptr, fn_ptr init_ptr)
Constructor for the Finite Volume Mesh using linear elements.
void dump_data(std::string filename)
Dump the data over the nodal positions to a given filename.
void boundary_diff(elt_iter e, const int &face_index, DenseVector< double > &diff) const
Given an element iterator and the local coordinate this will return zero for any components specified...
vector_of_elts BLACK_ELTS
An STL vector of linear elements – the black mesh.
elt_iter get_elt_iter_from_elt_iter(elt_iter e, std::string target_colour, int corner_index)
Given an element in the INITIAL STRUCTURED MESH, this method will return an iterator to an element in...
fn_ptr p_Q_INIT
function pointer to a funnction that defines the initial distribution
std::size_t ORDER_OF_SYSTEM
order of the conservative system
int sgn(double a) const
Sign of a double.
void set_boundary_Q(vector_of_elts *elts)
Loops over all boundary elements and sets the Q values in each one to be the value specified by the e...
const double & get_time() const
Get a const reference to the time value for the current mesh.
vector_of_elts::const_iterator celt_iter
void dump_nodes_y(std::string filename) const
Dump the y-nodal positions to a given filename.
double update(const double &CFL, const double &max_dt=std::numeric_limits< long double >::max())
Update the mesh object.
DenseVector< double > NS_diff(elt_iter e)
Compute a finite difference approximation of the derivative in the compass direction.
DenseVector< double > maxmod(DenseVector< double > A, DenseVector< double > B) const
A vector version of the maxmod operator.
void dump_nodes_x(std::string filename) const
Dump the x-nodal positions to a given filename.
std::size_t NX
number of faces in the x & y directions
DenseVector< double > north_diff(elt_iter e) const
Compute a finite difference approximation of the derivative in the compass direction.
virtual ~TwoD_TVDLF_Mesh()
Empty desctructor.
void set_limiter(const unsigned &id)
Set the limiter type to be applied in the slope values.
double MESH_TIME
the time level of the mesh
virtual void actions_before_time_step2(const double &time_step)
A virtual method that is run before the second time update.
vector_of_elts::iterator elt_iter
std::vector< TwoD_TVDLF_Elt > vector_of_elts
iterators for the vector of elements
elt_iter get_elt_iter_from_x(const DenseVector< double > &x, std::string mesh_colour="black")
Given a global coordinate, return a pointer to the elt that contains that point.
A collection of OO numerical routines aimed at simple (typical) applied problems in continuum mechani...