18 double south,
double north,
20 bool flag, std::set<int> faces) {
22 std::cout <<
"DEBUG: Constructing a TwoD_TVDLF_Elt object over ["
23 << west <<
", " << east <<
"] X [" << south <<
", " << north <<
"]\n";
28 this -> SOUTH = south;
30 this -> DX = east - west;
31 this -> DY = north - south;
35 EXTERNAL_FACES = faces;
37 p_ELTS = std::vector<TwoD_TVDLF_Elt*>(4,
this);
46 FLUX_FACE_DONE = std::vector<bool>(4,
false);
54 if(EXTERNAL_FACES.find(index) == EXTERNAL_FACES.end()) {
65 p_ELTS[ index ] = ptr;
69 return p_ELTS[ index ];
75 if(!FLUX_FACE_DONE[ 0 ]) {
78 if(!FLUX_FACE_DONE[ 1 ]) {
81 if(!FLUX_FACE_DONE[ 2 ]) {
84 if(!FLUX_FACE_DONE[ 3 ]) {
88 DELTA_Q *= dt / (DX * DY);
96 FLUX_FACE_DONE = std::vector<bool>(4,
false);
102 std::set< int > indices) {
104 std::set< int > internal_indices;
105 set_difference(indices.begin(), indices.end(),
106 EXTERNAL_FACES.begin(), EXTERNAL_FACES.end(),
107 inserter(internal_indices, internal_indices.begin()));
109 std::list< contribution >::iterator c = CONT_LIST.begin();
111 while(c != CONT_LIST.end()) {
112 if(c -> elt_ptr == ptr) {
121 c -> face_indices.insert(internal_indices.begin(), internal_indices.end());
128 cont.face_indices.insert(internal_indices.begin(), internal_indices.end());
130 CONT_LIST.push_back(cont);
136 std::cout << WEST + DX / 2 <<
" " << SOUTH + DY / 2 <<
" " <<
get_Q(s)[0] <<
"\n";
137 if(EXTERNAL_FACES.find(1) != EXTERNAL_FACES.end()) {
147 std::list< contribution >::const_iterator c = CONT_LIST.begin();
151 while(c != CONT_LIST.end()) {
153 sum += c -> elt_ptr ->
get_int_Q(c -> sw, c -> ne);
162 std::list< contribution >::iterator c = CONT_LIST.begin();
165 while(c != CONT_LIST.end()) {
167 if(c -> face_indices.find(3) != c -> face_indices.end()) {
171 s_half[ 0 ] = c -> sw[ 0 ];
172 s_half[ 1 ] = (c -> sw[1] + c -> ne[1]) * 0.5;
176 c -> elt_ptr ->
p_system -> flux_fn_x(c -> elt_ptr ->
get_x(s_half), q_half_step, flux);
178 const double sub_dy((c -> elt_ptr ->
get_x(c -> ne) - c -> elt_ptr ->
get_x(c -> sw))[1]);
179 flux_in_west += flux * sub_dy;
184 p_ELTS[ 3 ] -> add_to_delta_Q(1, -flux_in_west);
189 std::list< contribution >::iterator c = CONT_LIST.begin();
191 while(c != CONT_LIST.end()) {
197 s_half[ 0 ] = c -> sw[ 0 ];
198 s_half[ 1 ] = (c -> sw[1] + c -> ne[1]) * 0.5;
206 p_system -> edge_values(3, x, q_half_step);
208 c -> elt_ptr ->
p_system -> flux_fn_x(x, q_half_step, flux);
210 const double sub_dy((c -> elt_ptr ->
get_x(c -> ne) - c -> elt_ptr ->
get_x(c -> sw))[1]);
211 flux_in_west += flux * sub_dy;
216 FLUX_FACE_DONE[ 3 ] =
true;
217 DELTA_Q += flux_in_west;
223 std::list< contribution >::iterator c = CONT_LIST.begin();
226 while(c != CONT_LIST.end()) {
228 if(c -> face_indices.find(0) != c -> face_indices.end()) {
232 s_half[ 0 ] = (c -> sw[ 0 ] + c -> ne[ 0 ]) * 0.5;
233 s_half[ 1 ] = c -> sw[ 1 ];
237 c -> elt_ptr ->
p_system -> flux_fn_y(c -> elt_ptr ->
get_x(s_half), q_half_step, flux);
239 const double sub_dx((c -> elt_ptr ->
get_x(c -> ne) - c -> elt_ptr ->
get_x(c -> sw))[0]);
240 flux_in_south += flux * sub_dx;
245 p_ELTS[ 0 ] -> add_to_delta_Q(2, -flux_in_south);
250 std::list< contribution >::iterator c = CONT_LIST.begin();
252 while(c != CONT_LIST.end()) {
258 s_half[ 0 ] = (c -> sw[ 0 ] + c -> ne[ 0 ]) * 0.5;
259 s_half[ 1 ] = c -> sw[ 1 ];
267 p_system -> edge_values(0, x, q_half_step);
269 c -> elt_ptr ->
p_system -> flux_fn_y(x, q_half_step, flux);
271 const double sub_dx((c -> elt_ptr ->
get_x(c -> ne) - c -> elt_ptr ->
get_x(c -> sw))[0]);
272 flux_in_south += flux * sub_dx;
277 FLUX_FACE_DONE[ 0 ] =
true;
278 DELTA_Q += flux_in_south;
284 std::list< contribution >::iterator c = CONT_LIST.begin();
287 while(c != CONT_LIST.end()) {
289 if(c -> face_indices.find(1) != c -> face_indices.end()) {
293 s_half[ 0 ] = c -> ne[ 0 ];
294 s_half[ 1 ] = (c -> sw[1] + c -> ne[1]) * 0.5;
298 c -> elt_ptr ->
p_system -> flux_fn_x(c -> elt_ptr ->
get_x(s_half), q_half_step, flux);
300 const double sub_dy((c -> elt_ptr ->
get_x(c -> ne) - c -> elt_ptr ->
get_x(c -> sw))[1]);
301 flux_out_east += flux * sub_dy;
306 p_ELTS[ 1 ] -> add_to_delta_Q(3, flux_out_east);
311 std::list< contribution >::iterator c = CONT_LIST.begin();
313 while(c != CONT_LIST.end()) {
319 s_half[ 0 ] = c -> ne[ 0 ];
320 s_half[ 1 ] = (c -> sw[1] + c -> ne[1]) * 0.5;
328 p_system -> edge_values(1, x, q_half_step);
330 c -> elt_ptr ->
p_system -> flux_fn_x(x, q_half_step, flux);
332 const double sub_dy((c -> elt_ptr ->
get_x(c -> ne) - c -> elt_ptr ->
get_x(c -> sw))[1]);
333 flux_out_east += flux * sub_dy;
338 FLUX_FACE_DONE[ 1 ] =
true;
339 DELTA_Q -= flux_out_east;
345 std::list< contribution >::iterator c = CONT_LIST.begin();
348 while(c != CONT_LIST.end()) {
350 if(c -> face_indices.find(2) != c -> face_indices.end()) {
354 s_half[ 0 ] = (c -> sw[ 0 ] + c -> ne[ 0 ]) * 0.5;
355 s_half[ 1 ] = c -> ne[ 1 ];
359 c -> elt_ptr ->
p_system -> flux_fn_y(c -> elt_ptr ->
get_x(s_half), q_half_step, flux);
361 const double sub_dx((c -> elt_ptr ->
get_x(c -> ne) - c -> elt_ptr ->
get_x(c -> sw))[0]);
362 flux_out_north += flux * sub_dx;
367 p_ELTS[ 2 ] -> add_to_delta_Q(0, flux_out_north);
372 std::list< contribution >::iterator c = CONT_LIST.begin();
374 while(c != CONT_LIST.end()) {
380 s_half[ 0 ] = (c -> sw[ 0 ] + c -> ne[ 0 ]) * 0.5;
381 s_half[ 1 ] = c -> ne[ 1 ];
389 p_system -> edge_values(2, x, q_half_step);
391 c -> elt_ptr ->
p_system -> flux_fn_y(x, q_half_step, flux);
393 const double sub_dx((c -> elt_ptr ->
get_x(c -> ne) - c -> elt_ptr ->
get_x(c -> sw))[0]);
394 flux_out_north += flux * sub_dx;
399 FLUX_FACE_DONE[ 2 ] =
true;
400 DELTA_Q -= flux_out_north;
403 void TwoD_TVDLF_Elt::add_to_delta_Q(
const int& face_index,
const DenseVector<double>& dq) {
404 FLUX_FACE_DONE[ face_index ] =
true;
410 if((x[0] < WEST) || (x[0] > WEST + DX) || (x[1] > SOUTH + DY) || (x[1] < SOUTH)) {
412 problem =
" The TwoD_TVDLF_Elt::get_s method has been called for an element \n";
413 problem +=
" whose range does not bracket the given global coordinate.\n";
418 s[0] = -1 + 2 * (x[0] - WEST) / DX;
419 s[1] = -1 + 2 * (x[1] - SOUTH) / DY;
425 x[ 0 ] = WEST + (s[ 0 ] + 1) * DX / 2;
426 x[ 1 ] = SOUTH + (s[ 1 ] + 1) * DY / 2;
432 x[ 0 ] = WEST + DX / 2;
433 x[ 1 ] = SOUTH + DY / 2;
457 return EXTERNAL_FACES;
461 EXTERNAL_FACES.insert(i);
465 EXTERNAL_FACES.erase(i);
480 p_system -> Jac_flux_fn_x(x, q, jac);
483 p_system -> Jac_flux_fn_y(x, q, jac);
Specification of a two dimensional linear element for use in a TVD Lax-Friedrichs scheme.
A matrix class that constructs a DENSE matrix as a row major std::vector of DenseVectors.
DenseVector< _Type > multiply(const DenseVector< _Type > &x) const
Right multiply the matrix by a DENSE vector.
An DenseVector class – a dense vector object.
A generic runtime exception.
A class to represent a two-dimensional hyperbolic system of equations.
void set_external_flag(bool flag)
Set the external flag.
void clear_contributions()
Reset the contributions to this element.
void set_ptrs(const int &index, TwoD_TVDLF_Elt *ptr)
Each element stores pointers to any adjacent elements in the four compass directions 0,...
void dump() const
Dump the details of this element.
TwoD_TVDLF_Elt(double west, double east, double south, double north, TwoD_Hyperbolic_System *ptr, bool flag=false, std::set< int > faces=std::set< int >())
Construct a linear rectangular element.
DenseVector< double > get_x(DenseVector< double > s) const
Get the global position of a local coordinate in this element.
double get_dA() const
Get the area of the element.
void add_external_face(const int &i)
Add an external face to the stored stl::set.
DenseVector< double > get_Q(const DenseVector< double > &s) const
Get the value of the 'concentration' stored in this element.
bool get_external_flag() const
Get the external flag.
bool face_is_external(const int &index) const
Test to see if a face index of an element is external to the mesh.
TwoD_Hyperbolic_System * p_system
bool face_is_internal(const int &index) const
Test to see if a face index of an element is internal to the mesh.
void contributed_flux_out_north(const double &dt, DenseVector< double > &flux_out_north)
Compute the flux out of this element across the northern face.
void add_contribution(TwoD_TVDLF_Elt *ptr, const DenseVector< double > &sw, const DenseVector< double > &ne, std::set< int > indices)
Add a contribution to this element from another element.
DenseVector< double > get_dx() const
Get the size of the element as a vector (delta_x, delta_y).
void contributed_flux_in_west(const double &dt, DenseVector< double > &flux_in_west)
Compute the flux into this element across the western face.
DenseVector< double > get_x_mid() const
Get the global position of a central node in this element.
void add_flux_contributions(const double &dt)
Adds the contribution of each face's flux to the correction for this element unless it has already be...
DenseVector< double > get_source_contribution(const double &dt) const
Evaluate the contribution to this element by the hyperbolic system's source function over a given tim...
void contributed_flux_out_east(const double &dt, DenseVector< double > &flux_out_east)
Compute the flux out of this element across the eastern face.
std::set< int > get_external_faces() const
Get a set of indices of faces that are external.
void remove_external_face(const int &i)
Remove an external face to the stored stl::set.
DenseVector< double > get_s(const DenseVector< double > &x) const
Get the local coordinate that corresponds to a given global coordinate.
~TwoD_TVDLF_Elt()
An empty destructor.
void contributed_flux_in_south(const double &dt, DenseVector< double > &flux_in_south)
Compute the flux into this element across the southern face.
DenseVector< double > get_int_Q(const DenseVector< double > &sw, const DenseVector< double > &ne) const
Get the integral of Q over a sub-element.
DenseVector< double > contributed_Q() const
Find the integral contributions to this black/red element from the corresponding contributing red/bla...
DenseVector< double > get_Q_Taylor_series(const DenseVector< double > &s, const double &dt) const
Get the Taylor series expansion of the concentration for a given time step and local coordinate for t...
TwoD_TVDLF_Elt * get_ptrs(const int &index) const
Return a pointer to an element in the given compass direction.
A collection of OO numerical routines aimed at simple (typical) applied problems in continuum mechani...