oomph::SimpleRectangularTriMesh< ELEMENT > Class Template Reference

Simple 2D triangular mesh for TElements. More...

#include <simple_rectangular_tri_mesh.template.h>

+ Inheritance diagram for oomph::SimpleRectangularTriMesh< ELEMENT >:

Public Member Functions

 SimpleRectangularTriMesh (const unsigned &n_x, const unsigned &n_y, const double &l_x, const double &l_y, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
 
const unsignednx () const
 Access function for number of elements in x directions. More...
 
const unsignedny () const
 Access function for number of elements in y directions. More...
 
- Public Member Functions inherited from oomph::TriangleMeshBase
 TriangleMeshBase ()
 Constructor. More...
 
 TriangleMeshBase (const TriangleMeshBase &node)=delete
 Broken copy constructor. More...
 
virtual ~TriangleMeshBase ()
 Broken assignment operator. More...
 
void setup_boundary_element_info ()
 
void setup_boundary_element_info (std::ostream &outfile)
 
virtual void load_balance (const Vector< unsigned > &target_domain_for_local_non_halo_element)
 Virtual function to perform the load balance rutines. More...
 
virtual void reset_boundary_element_info (Vector< unsigned > &ntmp_boundary_elements, Vector< Vector< unsigned >> &ntmp_boundary_elements_in_region, Vector< FiniteElement * > &deleted_elements)
 Virtual function to perform the reset boundary elements info rutines. More...
 
- Public Member Functions inherited from oomph::UnstructuredTwoDMeshGeometryBase
 UnstructuredTwoDMeshGeometryBase ()
 Empty constructor. More...
 
 UnstructuredTwoDMeshGeometryBase (const UnstructuredTwoDMeshGeometryBase &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const UnstructuredTwoDMeshGeometryBase &)=delete
 Broken assignment operator. More...
 
 ~UnstructuredTwoDMeshGeometryBase ()
 Empty destructor. More...
 
unsigned nregion ()
 Return the number of regions specified by attributes. More...
 
unsigned nregion_element (const unsigned &i)
 Return the number of elements in the i-th region. More...
 
FiniteElementregion_element_pt (const unsigned &i, const unsigned &e)
 Return the e-th element in the i-th region. More...
 
unsigned nregion_attribute ()
 Return the number of attributes used in the mesh. More...
 
double region_attribute (const unsigned &i)
 Return the attribute associated with region i. More...
 
GeomObjectboundary_geom_object_pt (const unsigned &b)
 
std::map< unsigned, GeomObject * > & boundary_geom_object_pt ()
 Return direct access to the geometric object storage. More...
 
std::map< unsigned, Vector< double > > & boundary_coordinate_limits ()
 
Vector< double > & boundary_coordinate_limits (const unsigned &b)
 
unsigned nboundary_element_in_region (const unsigned &b, const unsigned &r) const
 Return the number of elements adjacent to boundary b in region r. More...
 
FiniteElementboundary_element_in_region_pt (const unsigned &b, const unsigned &r, const unsigned &e) const
 Return pointer to the e-th element adjacent to boundary b in region r. More...
 
int face_index_at_boundary_in_region (const unsigned &b, const unsigned &r, const unsigned &e) const
 Return face index of the e-th element adjacent to boundary b in region r. More...
 
TriangleMeshPolyLineboundary_polyline_pt (const unsigned &b)
 
std::map< unsigned, std::set< Node * > > & nodes_on_boundary_pt ()
 
const bool get_connected_vertex_number_on_destination_polyline (TriangleMeshPolyLine *dst_polyline_pt, Vector< double > &vertex_coordinates, unsigned &vertex_number)
 
void check_contiguousness_on_polylines_helper (Vector< TriangleMeshPolyLine * > &polylines_pt, unsigned &index)
 
void check_contiguousness_on_polylines_helper (Vector< TriangleMeshPolyLine * > &polylines_pt, unsigned &index_halo_start, unsigned &index_halo_end)
 
bool is_point_inside_polygon_helper (Vector< Vector< double >> polygon_vertices, Vector< double > point)
 Helper function that checks if a given point is inside a polygon. More...
 
void enable_automatic_creation_of_vertices_on_boundaries ()
 
void disable_automatic_creation_of_vertices_on_boundaries ()
 
bool is_automatic_creation_of_vertices_on_boundaries_allowed ()
 
template<class ELEMENT >
void setup_boundary_coordinates (const unsigned &b)
 
template<class ELEMENT >
void setup_boundary_coordinates (const unsigned &b, std::ofstream &outfile)
 
- Public Member Functions inherited from oomph::Mesh
 Mesh ()
 Default constructor. More...
 
 Mesh (const Vector< Mesh * > &sub_mesh_pt)
 
void merge_meshes (const Vector< Mesh * > &sub_mesh_pt)
 
template<class BULK_ELEMENT >
void doc_boundary_coordinates (const unsigned &b, std::ofstream &the_file)
 
virtual void scale_mesh (const double &factor)
 
 Mesh (const Mesh &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const Mesh &)=delete
 Broken assignment operator. More...
 
virtual ~Mesh ()
 Virtual Destructor to clean up all memory. More...
 
void flush_element_and_node_storage ()
 
void flush_element_storage ()
 
void flush_node_storage ()
 
Node *& node_pt (const unsigned long &n)
 Return pointer to global node n. More...
 
Nodenode_pt (const unsigned long &n) const
 Return pointer to global node n (const version) More...
 
GeneralisedElement *& element_pt (const unsigned long &e)
 Return pointer to element e. More...
 
GeneralisedElementelement_pt (const unsigned long &e) const
 Return pointer to element e (const version) More...
 
const Vector< GeneralisedElement * > & element_pt () const
 Return reference to the Vector of elements. More...
 
Vector< GeneralisedElement * > & element_pt ()
 Return reference to the Vector of elements. More...
 
FiniteElementfinite_element_pt (const unsigned &e) const
 
Node *& boundary_node_pt (const unsigned &b, const unsigned &n)
 Return pointer to node n on boundary b. More...
 
Nodeboundary_node_pt (const unsigned &b, const unsigned &n) const
 Return pointer to node n on boundary b. More...
 
void set_nboundary (const unsigned &nbound)
 Set the number of boundaries in the mesh. More...
 
void remove_boundary_nodes ()
 Clear all pointers to boundary nodes. More...
 
void remove_boundary_nodes (const unsigned &b)
 
void remove_boundary_node (const unsigned &b, Node *const &node_pt)
 Remove a node from the boundary b. More...
 
void add_boundary_node (const unsigned &b, Node *const &node_pt)
 Add a (pointer to) a node to the b-th boundary. More...
 
void copy_boundary_node_data_from_nodes ()
 
bool boundary_coordinate_exists (const unsigned &i) const
 Indicate whether the i-th boundary has an intrinsic coordinate. More...
 
unsigned long nelement () const
 Return number of elements in the mesh. More...
 
unsigned long nnode () const
 Return number of nodes in the mesh. More...
 
unsigned ndof_types () const
 Return number of dof types in mesh. More...
 
unsigned elemental_dimension () const
 Return number of elemental dimension in mesh. More...
 
unsigned nodal_dimension () const
 Return number of nodal dimension in mesh. More...
 
void add_node_pt (Node *const &node_pt)
 Add a (pointer to a) node to the mesh. More...
 
void add_element_pt (GeneralisedElement *const &element_pt)
 Add a (pointer to) an element to the mesh. More...
 
virtual void node_update (const bool &update_all_solid_nodes=false)
 
virtual void reorder_nodes (const bool &use_old_ordering=true)
 
virtual void get_node_reordering (Vector< Node * > &reordering, const bool &use_old_ordering=true) const
 
template<class BULK_ELEMENT , template< class > class FACE_ELEMENT>
void build_face_mesh (const unsigned &b, Mesh *const &face_mesh_pt)
 
unsigned self_test ()
 Self-test: Check elements and nodes. Return 0 for OK. More...
 
void max_and_min_element_size (double &max_size, double &min_size)
 
double total_size ()
 
void check_inverted_elements (bool &mesh_has_inverted_elements, std::ofstream &inverted_element_file)
 
void check_inverted_elements (bool &mesh_has_inverted_elements)
 
unsigned check_for_repeated_nodes (const double &epsilon=1.0e-12)
 
Vector< Node * > prune_dead_nodes ()
 
unsigned nboundary () const
 Return number of boundaries. More...
 
unsigned long nboundary_node (const unsigned &ibound) const
 Return number of nodes on a particular boundary. More...
 
FiniteElementboundary_element_pt (const unsigned &b, const unsigned &e) const
 Return pointer to e-th finite element on boundary b. More...
 
Nodeget_some_non_boundary_node () const
 
unsigned nboundary_element (const unsigned &b) const
 Return number of finite elements that are adjacent to boundary b. More...
 
int face_index_at_boundary (const unsigned &b, const unsigned &e) const
 
virtual void dump (std::ofstream &dump_file, const bool &use_old_ordering=true) const
 Dump the data in the mesh into a file for restart. More...
 
void dump (const std::string &dump_file_name, const bool &use_old_ordering=true) const
 Dump the data in the mesh into a file for restart. More...
 
virtual void read (std::ifstream &restart_file)
 Read solution from restart file. More...
 
void output_paraview (std::ofstream &file_out, const unsigned &nplot) const
 
void output_fct_paraview (std::ofstream &file_out, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt) const
 
void output_fct_paraview (std::ofstream &file_out, const unsigned &nplot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt) const
 
void output (std::ostream &outfile)
 Output for all elements. More...
 
void output (std::ostream &outfile, const unsigned &n_plot)
 Output at f(n_plot) points in each element. More...
 
void output (FILE *file_pt)
 Output for all elements (C-style output) More...
 
void output (FILE *file_pt, const unsigned &nplot)
 Output at f(n_plot) points in each element (C-style output) More...
 
void output (const std::string &output_filename)
 Output for all elements. More...
 
void output (const std::string &output_filename, const unsigned &n_plot)
 Output at f(n_plot) points in each element. More...
 
void output_fct (std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt)
 Output a given Vector function at f(n_plot) points in each element. More...
 
void output_fct (std::ostream &outfile, const unsigned &n_plot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt)
 
void output_boundaries (std::ostream &outfile)
 Output the nodes on the boundaries (into separate tecplot zones) More...
 
void output_boundaries (const std::string &output_filename)
 
void assign_initial_values_impulsive ()
 Assign initial values for an impulsive start. More...
 
void shift_time_values ()
 
void calculate_predictions ()
 
void set_nodal_and_elemental_time_stepper (TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
 
virtual void set_mesh_level_time_stepper (TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
 
void set_consistent_pinned_values_for_continuation (ContinuationStorageScheme *const &continuation_stepper_pt)
 Set consistent values for pinned data in continuation. More...
 
bool does_pointer_correspond_to_mesh_data (double *const &parameter_pt)
 Does the double pointer correspond to any mesh data. More...
 
void set_nodal_time_stepper (TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
 Set the timestepper associated with the nodal data in the mesh. More...
 
void set_elemental_internal_time_stepper (TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
 
virtual void compute_norm (double &norm)
 
virtual void compute_norm (Vector< double > &norm)
 
virtual void compute_error (std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
 
virtual void compute_error (std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
 
virtual void compute_error (FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
 
virtual void compute_error (FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, Vector< double > &error, Vector< double > &norm)
 
virtual void compute_error (std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, Vector< double > &error, Vector< double > &norm)
 
virtual void compute_error (std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, Vector< double > &error, Vector< double > &norm)
 
virtual void compute_error (FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
 Returns the norm of the error and that of the exact solution. More...
 
virtual void compute_error (FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, Vector< double > &error, Vector< double > &norm)
 
bool is_mesh_distributed () const
 Boolean to indicate if Mesh has been distributed. More...
 
OomphCommunicatorcommunicator_pt () const
 
void delete_all_external_storage ()
 Wipe the storage for all externally-based elements. More...
 

Private Attributes

unsigned Nx
 Number of elements in x direction. More...
 
unsigned Ny
 Number of elements in y directions. More...
 
double Lx
 Length of mesh in x-direction. More...
 
double Ly
 Length of mesh in y-direction. More...
 

Additional Inherited Members

- Public Types inherited from oomph::Mesh
typedef void(FiniteElement::* SteadyExactSolutionFctPt) (const Vector< double > &x, Vector< double > &soln)
 
typedef void(FiniteElement::* UnsteadyExactSolutionFctPt) (const double &time, const Vector< double > &x, Vector< double > &soln)
 
- Static Public Attributes inherited from oomph::UnstructuredTwoDMeshGeometryBase
static bool Suppress_warning_about_regions_and_boundaries
 Public static flag to suppress warning; defaults to false. More...
 
- Static Public Attributes inherited from oomph::Mesh
static Steady< 0 > Default_TimeStepper
 The Steady Timestepper. More...
 
static bool Suppress_warning_about_empty_mesh_level_time_stepper_function
 Static boolean flag to control warning about mesh level timesteppers. More...
 
- Protected Member Functions inherited from oomph::UnstructuredTwoDMeshGeometryBase
void snap_nodes_onto_geometric_objects ()
 
void copy_connection_information (TriangleMeshCurveSection *input_curve_pt, TriangleMeshCurveSection *output_curve_pt)
 
void copy_connection_information_to_sub_polylines (TriangleMeshCurveSection *input_curve_pt, TriangleMeshCurveSection *output_curve_pt)
 
- Protected Member Functions inherited from oomph::Mesh
unsigned long assign_global_eqn_numbers (Vector< double * > &Dof_pt)
 Assign (global) equation numbers to the nodes. More...
 
void describe_dofs (std::ostream &out, const std::string &current_string) const
 
void describe_local_dofs (std::ostream &out, const std::string &current_string) const
 
void assign_local_eqn_numbers (const bool &store_local_dof_pt)
 Assign local equation numbers in all elements. More...
 
void convert_to_boundary_node (Node *&node_pt, const Vector< FiniteElement * > &finite_element_pt)
 
void convert_to_boundary_node (Node *&node_pt)
 
- Protected Attributes inherited from oomph::UnstructuredTwoDMeshGeometryBase
bool Allow_automatic_creation_of_vertices_on_boundaries
 
std::map< unsigned, Vector< FiniteElement * > > Region_element_pt
 
Vector< doubleRegion_attribute
 Vector of attributes associated with the elements in each region. More...
 
std::map< unsigned, GeomObject * > Boundary_geom_object_pt
 Storage for the geometric objects associated with any boundaries. More...
 
std::map< unsigned, Vector< double > > Boundary_coordinate_limits
 
Vector< TriangleMeshPolygon * > Outer_boundary_pt
 Polygon that defines outer boundaries. More...
 
Vector< TriangleMeshPolygon * > Internal_polygon_pt
 Vector of polygons that define internal polygons. More...
 
Vector< TriangleMeshOpenCurve * > Internal_open_curve_pt
 Vector of open polylines that define internal curves. More...
 
Vector< Vector< double > > Extra_holes_coordinates
 Storage for extra coordinates for holes. More...
 
std::map< unsigned, Vector< double > > Regions_coordinates
 
std::map< unsigned, TriangleMeshCurveSection * > Boundary_curve_section_pt
 
Vector< std::map< unsigned, Vector< FiniteElement * > > > Boundary_region_element_pt
 Storage for elements adjacent to a boundary in a particular region. More...
 
Vector< std::map< unsigned, Vector< int > > > Face_index_region_at_boundary
 Storage for the face index adjacent to a boundary in a particular region. More...
 
std::map< unsigned, Vector< std::pair< double, double > > > Polygonal_vertex_arclength_info
 
std::map< unsigned, std::set< Node * > > Nodes_on_boundary_pt
 
std::set< TriangleMeshCurveSection * > Free_curve_section_pt
 
std::set< TriangleMeshPolygon * > Free_polygon_pt
 
std::set< TriangleMeshOpenCurve * > Free_open_curve_pt
 
- Protected Attributes inherited from oomph::Mesh
Vector< Vector< Node * > > Boundary_node_pt
 
bool Lookup_for_elements_next_boundary_is_setup
 
Vector< Vector< FiniteElement * > > Boundary_element_pt
 
Vector< Vector< int > > Face_index_at_boundary
 
Vector< Node * > Node_pt
 Vector of pointers to nodes. More...
 
Vector< GeneralisedElement * > Element_pt
 Vector of pointers to generalised elements. More...
 
std::vector< boolBoundary_coordinate_exists
 

Detailed Description

template<class ELEMENT>
class oomph::SimpleRectangularTriMesh< ELEMENT >

Simple 2D triangular mesh for TElements.

Constructor & Destructor Documentation

◆ SimpleRectangularTriMesh()

template<class ELEMENT >
oomph::SimpleRectangularTriMesh< ELEMENT >::SimpleRectangularTriMesh ( const unsigned n_x,
const unsigned n_y,
const double l_x,
const double l_y,
TimeStepper time_stepper_pt = &Mesh::Default_TimeStepper 
)

Constructor n_x : number of elements in the x direction; n_y : number of elements in the y direction; l_x : length in the x direction l_y : length in the y direction Ordering of elements: 'lower left' to 'lower right' then 'upwards'

Constructor for simple 2D triangular mesh class:

n_x : number of elements in the x direction

n_y : number of elements in the y direction

l_x : length in the x direction

l_y : length in the y direction

Ordering of elements: 'lower left' to 'lower right' then 'upwards'

60  : Nx(n_x), Ny(n_y), Lx(l_x), Ly(l_y)
61  {
62  using namespace MathematicalConstants;
63 
64  // Mesh can only be built with 2D Telements.
65  MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(2);
66 
67  // Set number of boundaries
68  this->set_nboundary(4);
69 
70  // Allocate the store for the elements
71  unsigned n_element = (Nx) * (Ny)*2;
72  Element_pt.resize(n_element, 0);
73 
74  // Create first element
75  Element_pt[0] = new ELEMENT;
76 
77  // Currently this mesh only works for 3 and 6 noded triangles
78  if ((finite_element_pt(0)->nnode_1d() != 2) &&
79  (finite_element_pt(0)->nnode_1d() != 3) &&
80  (finite_element_pt(0)->nnode_1d() != 4))
81  {
82  throw OomphLibError(
83  "Currently this mesh only works for 3, 6 & 10-noded triangles",
86  }
87 
88  unsigned n_node = 0;
89  // Unless nnode_1d returned as !=2 default no extra nodes
90  unsigned additional_nnode = 0;
91 
92  // Allocate storage if no extra nodes
93  if (finite_element_pt(0)->nnode_1d() == 2)
94  {
95  n_node = (Nx + 1) * (Ny + 1);
96  }
97 
98  if (finite_element_pt(0)->nnode_1d() == 3)
99  {
100  additional_nnode = 3;
101  // Allocate storage for nodes (including extra)
102  n_node = (2 * Nx + 1) * (2 * Ny + 1);
103  }
104 
105  if (finite_element_pt(0)->nnode_1d() == 4)
106  {
107  additional_nnode = 7;
108  // Allocate storage for notes (including extra)
109  n_node = (3 * Nx + 1) * (3 * Ny + 1);
110  }
111 
112  Node_pt.resize(n_node);
113 
114  // Set up geometrical data
115  //------------------------
116  unsigned long node_count = 0;
117  unsigned long element_count = 0;
118  double xinit = 0.0, yinit = 0.0;
119  // Set the values of the increments
120  double xstep = Lx / (Nx);
121  double ystep = Ly / (Ny);
122 
123 
124  // FIRST NODE (lower left corner)
125  //-------------------------------
126 
127  // Set the corner node
128 
129  // Allocate memory for the corner node of the first element
130  //(which is not created loop as all subsequent bottom corners already exist)
131  Node_pt[node_count] =
132  finite_element_pt(0)->construct_node(1, time_stepper_pt);
133 
134  // Set the pointer from the element
135  finite_element_pt(0)->node_pt(1) = Node_pt[node_count];
136 
137  // Don't increment node_count yet as we still need its containing box
138  //(position and boundaries for first node are allocated in the main loop)
139 
140  // CREATE THE ELEMENTS (each has 3 local nodes)
141  //--------------------------------------------------
142  // Elements are created two at a time, the first being lower triangular
143  // and the second upper triangular, so that they form a containing box.
144  // Local nodes are numbered anti-clockwise with node_pt(1) being the
145  // right-angle corner of the triangle.
146  // The global node number, node_count, is considered to define
147  // a containing box, with node_count defined as the node number
148  // of the bottom left corner of the box.
149  for (unsigned j = 0; j < Ny + 1; ++j)
150  {
151  for (unsigned i = 0; i < Nx + 1; ++i)
152  {
153  // CURRENT BOX
154  //(nodes on RHS or top edge of domain do not define a box)
155  if (j < Ny && i < Nx)
156  {
157  // Create two elements
158  //------------------------------
159  if (element_count != 0) // 0th element already exists
160  {
161  Element_pt[element_count] = new ELEMENT;
162  }
163 
164  Element_pt[element_count + 1] = new ELEMENT;
165 
166 
167  // Allocate memory for nodes in the current box
168  //--------------------------------------------
169  // If node on LHS of domain, allocate the top left corner node
170  if (i == 0)
171  {
172  Node_pt[node_count + Nx + 1] =
173  finite_element_pt(element_count)
174  ->construct_node(0, time_stepper_pt);
175  }
176 
177  // If on bottom row, allocate the bottom right corner node
178  if (j == 0)
179  {
180  Node_pt[node_count + 1] = finite_element_pt(element_count)
181  ->construct_node(2, time_stepper_pt);
182  }
183 
184  // Always need to allocate top right corner node
185  Node_pt[node_count + Nx + 2] = finite_element_pt(element_count + 1)
186  ->construct_node(1, time_stepper_pt);
187 
188  // Bottom left corner node is already allocated
189 
190 
191  // Set the pointers from the elements
192  //----------------------------------
193  finite_element_pt(element_count)->node_pt(0) =
194  Node_pt[node_count + Nx + 1];
195  finite_element_pt(element_count)->node_pt(1) = Node_pt[node_count];
196  finite_element_pt(element_count)->node_pt(2) =
197  Node_pt[node_count + 1];
198  finite_element_pt(element_count + 1)->node_pt(0) =
199  Node_pt[node_count + 1];
200  finite_element_pt(element_count + 1)->node_pt(1) =
201  Node_pt[node_count + Nx + 2];
202  finite_element_pt(element_count + 1)->node_pt(2) =
203  Node_pt[node_count + Nx + 1];
204 
205  element_count += 2;
206  }
207 
208  // CURRENT (GLOBAL) NODE
209  // Set the position
210  Node_pt[node_count]->x(0) = xinit + i * xstep;
211  Node_pt[node_count]->x(1) = yinit + j * ystep;
212 
213  // Add node to any relevant boundaries
214  if (j == 0)
215  {
216  this->convert_to_boundary_node(Node_pt[node_count]);
217  add_boundary_node(0, Node_pt[node_count]);
218  }
219  if (j == Ny)
220  {
221  this->convert_to_boundary_node(Node_pt[node_count]);
222  add_boundary_node(2, Node_pt[node_count]);
223  }
224  if (i == 0)
225  {
226  this->convert_to_boundary_node(Node_pt[node_count]);
227  add_boundary_node(3, Node_pt[node_count]);
228  }
229  if (i == Nx)
230  {
231  this->convert_to_boundary_node(Node_pt[node_count]);
232  add_boundary_node(1, Node_pt[node_count]);
233  }
234 
235  // Increment counter
236  node_count++;
237  }
238  }
239 
240 
241  if (additional_nnode == 3)
242  {
243  // Reset element counter to allow looping over existing elements
244  // to add extra nodes.
245  // Note that the node_count is not reset so no entries are overwritten
246  element_count = 0;
247  for (unsigned j = 0; j < Ny + 1; ++j)
248  {
249  // Note: i counter reduced by 1 since i axis runs through middle of
250  // elements on x-axis
251  for (unsigned i = 0; i < Nx; ++i)
252  {
253  // The additional nodes will be added in stages for ease of
254  // application. Note: local numbering follows the anti-clockwise
255  // pattern, node 3 halfway between nodes 0-1, 4 between 1-2 and the
256  // 5th local node between 2-0.
257 
258  // Restricted to stop creation of additional nodes outside the mesh
259  if (j < Ny)
260  {
261  // If on the bottom row middle-node at bottom needs allocating
262  if (j == 0)
263  {
264  Node_pt[node_count] = finite_element_pt(element_count)
265  ->construct_node(4, time_stepper_pt);
266  }
267 
268  // Due to directions of iteration node at middle of top box edge
269  // (in next element) always needs allocating
270  Node_pt[node_count + Nx] = finite_element_pt(element_count + 1)
271  ->construct_node(4, time_stepper_pt);
272 
273  // Set pointers to the top/bottom middle nodes
274  // Bottom node
275  finite_element_pt(element_count)->node_pt(4) = Node_pt[node_count];
276  // Top node
277  finite_element_pt(element_count + 1)->node_pt(4) =
278  Node_pt[node_count + Nx];
279 
280  // Increase the element counter to add top/bottom nodes to
281  // next pair of element on next pass
282  element_count += 2;
283  } // End extra top/bottom node construction
284 
285  // Set position of current (Global) Node
286  Node_pt[node_count]->x(0) = xinit + double(i + 0.5) * xstep;
287  Node_pt[node_count]->x(1) = yinit + j * ystep;
288 
289  // Add node to any applicable boundaries (node 4's can only be top
290  // or bottom boundaries)
291  if (j == 0)
292  {
293  this->convert_to_boundary_node(Node_pt[node_count]);
294  add_boundary_node(0, Node_pt[node_count]);
295  }
296  if (j == Ny)
297  {
298  this->convert_to_boundary_node(Node_pt[node_count]);
299  add_boundary_node(2, Node_pt[node_count]);
300  }
301 
302  // Update node_count
303  node_count++;
304  }
305  }
306 
307  // Next stage of additional node implementation involes the middle left
308  // and right nodes (local number 3 on each triangle)
309 
310  // Element counter reset for second loop over existing elements
311  element_count = 0;
312  // Note: j counter reduced by 1 since j axis runs through middle of
313  // elements on y-axis
314  for (unsigned j = 0; j < Ny; ++j)
315  {
316  for (unsigned i = 0; i < Nx + 1; ++i)
317  {
318  if (j < Ny && i < Nx)
319  {
320  // If on the left hand boundary the node at middle of the left
321  // side needs allocating
322  if (i == 0)
323  {
324  Node_pt[node_count] = finite_element_pt(element_count)
325  ->construct_node(3, time_stepper_pt);
326  }
327 
328  // The mid node on the right hand side always needs constructing
329  // within the bounds of the mesh
330  Node_pt[node_count + 1] = finite_element_pt(element_count + 1)
331  ->construct_node(3, time_stepper_pt);
332 
333  // Set pointers from the elements to new nodes
334  finite_element_pt(element_count)->node_pt(3) = Node_pt[node_count];
335  finite_element_pt(element_count + 1)->node_pt(3) =
336  Node_pt[node_count + 1];
337 
338  // Increase element_count by 2
339  element_count += 2;
340  } // End extra left/right node construction
341 
342  // Set position of current (Global) Node
343  Node_pt[node_count]->x(0) = xinit + i * xstep;
344  Node_pt[node_count]->x(1) = yinit + double(j + 0.5) * ystep;
345 
346  // Add node to any applicable boundaries again - only be left/right
347  if (i == 0)
348  {
349  this->convert_to_boundary_node(Node_pt[node_count]);
350  add_boundary_node(3, Node_pt[node_count]);
351  }
352  if (i == Nx)
353  {
354  this->convert_to_boundary_node(Node_pt[node_count]);
355  add_boundary_node(1, Node_pt[node_count]);
356  }
357 
358  // Update node_count
359  node_count++;
360  }
361  }
362 
363  // Final stage of inserting extra nodes - inclusion of the local
364  // number 5 (middle of hypot. edge)
365 
366  element_count = 0;
367  // Note: both i,j counters reduced by 1 since j axis runs through middle
368  // of elements in both x,y
369  for (unsigned j = 0; j < Ny; ++j)
370  {
371  for (unsigned i = 0; i < Nx; ++i)
372  {
373  // The middle node always needs constructing
374  Node_pt[node_count] = finite_element_pt(element_count)
375  ->construct_node(5, time_stepper_pt);
376 
377  // Set pointers from the elements to new nodes
378  finite_element_pt(element_count)->node_pt(5) = Node_pt[node_count];
379  finite_element_pt(element_count + 1)->node_pt(5) =
380  Node_pt[node_count];
381 
382  // Increase element_count by 2
383  element_count += 2;
384  // End extra left/right node construction
385 
386  // Set position of current (Global) Node
387  Node_pt[node_count]->x(0) = xinit + double(i + 0.5) * xstep;
388  Node_pt[node_count]->x(1) = yinit + double(j + 0.5) * ystep;
389 
390  // All nodes are internal in this structure so no boundaries
391  // applicable
392 
393  // Update node_count
394  node_count++;
395  }
396  }
397  }
398  // End of extra nodes for 6 noded trianglur elements
399 
400 
401  if (additional_nnode == 7)
402  {
403  // Reset element counter to allow looping over existing elements
404  // to add extra nodes.
405  // Note that the node_count is not reset so no entries are overwritten
406  element_count = 0;
407  for (unsigned j = 0; j < Ny + 1; ++j)
408  {
409  // Note: i counter reduced by 1 for implementation of lower element
410  // node 5 and upper element node 6's.
411  for (unsigned i = 0; i < Nx; ++i)
412  {
413  // The additional nodes will be added in stages for ease of
414  // application. Note: local numbering follows the anti-clockwise
415  // pattern, nodes 3 and 4 equidistant between nodes 0-1, 5 and 6
416  // between 1-2, 7 and 8 between 2-0 and last node 9 located
417  // (internally) at the centroid of the triangle.
418 
419  // Restricted to stop creation of additional nodes outside the mesh
420  if (j < Ny)
421  {
422  // If on the bottom row middle-left-node at bottom needs allocating
423  if (j == 0)
424  {
425  Node_pt[node_count] = finite_element_pt(element_count)
426  ->construct_node(5, time_stepper_pt);
427  }
428 
429  // Due to directions of iteration node at middle left of top box
430  // edge (in next element) always needs allocating
431  Node_pt[node_count + Nx] = finite_element_pt(element_count + 1)
432  ->construct_node(6, time_stepper_pt);
433 
434  // Set pointers to the top/bottom middle nodes
435  // Bottom node
436  finite_element_pt(element_count)->node_pt(5) = Node_pt[node_count];
437  // Top node
438  finite_element_pt(element_count + 1)->node_pt(6) =
439  Node_pt[node_count + Nx];
440 
441  // Increase the element counter to add top/bottom nodes to
442  // next pair of element on next pass
443  element_count += 2;
444  } // End extra top/bottom node construction
445 
446  // Set position of current (Global) Node
447  Node_pt[node_count]->x(0) = xinit + double(i + 1.0 / 3.0) * xstep;
448  Node_pt[node_count]->x(1) = yinit + j * ystep;
449 
450  // Add node to any applicable boundaries (exactly as previous)
451  if (j == 0)
452  {
453  this->convert_to_boundary_node(Node_pt[node_count]);
454  add_boundary_node(0, Node_pt[node_count]);
455  }
456  if (j == Ny)
457  {
458  this->convert_to_boundary_node(Node_pt[node_count]);
459  add_boundary_node(2, Node_pt[node_count]);
460  }
461 
462  // Update node_count
463  node_count++;
464  }
465  }
466 
467 
468  // Next stage: bottom-middle-right node (node 6 in lower tri.el.)
469  // and top-middle-right node (node 5 in upper tri.el.)
470 
471  element_count = 0;
472  for (unsigned j = 0; j < Ny + 1; ++j)
473  {
474  // Note: i counter as for above 5/6's
475  for (unsigned i = 0; i < Nx; ++i)
476  {
477  // Restricted to stop creation of additional nodes outside the mesh
478  if (j < Ny)
479  {
480  // If on the bottom row middle-right-node at bottom needs allocating
481  if (j == 0)
482  {
483  Node_pt[node_count] = finite_element_pt(element_count)
484  ->construct_node(6, time_stepper_pt);
485  }
486 
487  // Due to directions of iteration node at middle left of top box
488  // edge (in next element) always needs allocating
489  Node_pt[node_count + Nx] = finite_element_pt(element_count + 1)
490  ->construct_node(5, time_stepper_pt);
491 
492  // Set pointers to the top/bottom middle nodes
493  // Bottom node
494  finite_element_pt(element_count)->node_pt(6) = Node_pt[node_count];
495  // Top node
496  finite_element_pt(element_count + 1)->node_pt(5) =
497  Node_pt[node_count + Nx];
498 
499  // Increase the element counter to add top/bottom nodes to
500  // next pair of element on next pass
501  element_count += 2;
502  } // End extra top/bottom node construction
503 
504  // Set position of current (Global) Node
505  Node_pt[node_count]->x(0) = xinit + double(i + 2.0 / 3.0) * xstep;
506  Node_pt[node_count]->x(1) = yinit + j * ystep;
507 
508  // Add node to any applicable boundaries (exactly as previous)
509  if (j == 0)
510  {
511  this->convert_to_boundary_node(Node_pt[node_count]);
512  add_boundary_node(0, Node_pt[node_count]);
513  }
514  if (j == Ny)
515  {
516  this->convert_to_boundary_node(Node_pt[node_count]);
517  add_boundary_node(2, Node_pt[node_count]);
518  }
519 
520  // Update node_count
521  node_count++;
522  }
523  }
524 
525 
526  // Next stage of additional node implementation involes node 4 on lower
527  // tri. el. and node 3 on upper tri. el.
528 
529  // Element counter reset for next loop over existing elements
530  element_count = 0;
531  // Note: j counter reduced by 1 similar to others above
532  for (unsigned j = 0; j < Ny; ++j)
533  {
534  for (unsigned i = 0; i < Nx + 1; ++i)
535  {
536  if (j < Ny && i < Nx)
537  {
538  // If on the left hand boundary the lower middle node of the left
539  // side needs allocating
540  if (i == 0)
541  {
542  Node_pt[node_count] = finite_element_pt(element_count)
543  ->construct_node(4, time_stepper_pt);
544  }
545 
546  // The mid node on the right hand side always needs constructing
547  // within the bounds of the mesh
548  Node_pt[node_count + 1] = finite_element_pt(element_count + 1)
549  ->construct_node(3, time_stepper_pt);
550 
551  // Set pointers from the elements to new nodes
552  finite_element_pt(element_count)->node_pt(4) = Node_pt[node_count];
553  finite_element_pt(element_count + 1)->node_pt(3) =
554  Node_pt[node_count + 1];
555 
556  // Increase element_count by 2
557  element_count += 2;
558  } // End extra left/right node construction
559 
560  // Set position of current (Global) Node
561  Node_pt[node_count]->x(0) = xinit + i * xstep;
562  Node_pt[node_count]->x(1) = yinit + double(j + 1.0 / 3.0) * ystep;
563 
564  // Add node to any applicable boundaries again - only be left/right
565  if (i == 0)
566  {
567  this->convert_to_boundary_node(Node_pt[node_count]);
568  add_boundary_node(3, Node_pt[node_count]);
569  }
570  if (i == Nx)
571  {
572  this->convert_to_boundary_node(Node_pt[node_count]);
573  add_boundary_node(1, Node_pt[node_count]);
574  }
575 
576  // Update node_count
577  node_count++;
578  }
579  }
580 
581 
582  // Next stage of additional node implementation involes node 3 on lower
583  // tri. el. and node 4 on upper tri. el.
584 
585  // Element counter reset for next loop over existing elements
586  element_count = 0;
587  // Note: j counter reduced by 1 similar to others above
588  for (unsigned j = 0; j < Ny; ++j)
589  {
590  for (unsigned i = 0; i < Nx + 1; ++i)
591  {
592  if (j < Ny && i < Nx)
593  {
594  // If on the left hand boundary the lower middle node of the left
595  // side needs allocating
596  if (i == 0)
597  {
598  Node_pt[node_count] = finite_element_pt(element_count)
599  ->construct_node(3, time_stepper_pt);
600  }
601 
602  // The mid node on the right hand side always needs constructing
603  // within the bounds of the mesh
604  Node_pt[node_count + 1] = finite_element_pt(element_count + 1)
605  ->construct_node(4, time_stepper_pt);
606 
607  // Set pointers from the elements to new nodes
608  finite_element_pt(element_count)->node_pt(3) = Node_pt[node_count];
609  finite_element_pt(element_count + 1)->node_pt(4) =
610  Node_pt[node_count + 1];
611 
612  // Increase element_count by 2
613  element_count += 2;
614  } // End extra left/right node construction
615 
616  // Set position of current (Global) Node
617  Node_pt[node_count]->x(0) = xinit + i * xstep;
618  Node_pt[node_count]->x(1) = yinit + double(j + 2.0 / 3.0) * ystep;
619 
620  // Add node to any applicable boundaries again - only be left/right
621  if (i == 0)
622  {
623  this->convert_to_boundary_node(Node_pt[node_count]);
624  add_boundary_node(3, Node_pt[node_count]);
625  }
626  if (i == Nx)
627  {
628  this->convert_to_boundary_node(Node_pt[node_count]);
629  add_boundary_node(1, Node_pt[node_count]);
630  }
631 
632  // Update node_count
633  node_count++;
634  }
635  }
636 
637 
638  // Next is the lower tri. el. totally internal node with local number 9
639  element_count = 0;
640  // Note: both i,j counters reduced by 1
641  for (unsigned j = 0; j < Ny; ++j)
642  {
643  for (unsigned i = 0; i < Nx; ++i)
644  {
645  // The middle node always needs constructing
646  Node_pt[node_count] = finite_element_pt(element_count)
647  ->construct_node(9, time_stepper_pt);
648 
649  // Set pointers from the elements to new nodes
650  finite_element_pt(element_count)->node_pt(9) = Node_pt[node_count];
651 
652  // Increase element_count by 2
653  element_count += 2;
654 
655  // Set position of current (Global) Node
656  Node_pt[node_count]->x(0) = xinit + double(i + 1.0 / 3.0) * xstep;
657  Node_pt[node_count]->x(1) = yinit + double(j + 1.0 / 3.0) * ystep;
658 
659  // All nodes are internal in this structure so no boundaries
660  // applicable
661 
662  // Update node_count
663  node_count++;
664  }
665  }
666 
667 
668  // Next is the bottom hyp. node -
669  // lower tri. el. number 7, upper tri. el. number 8
670  element_count = 0;
671  // Note: both i,j counters reduced by 1
672  for (unsigned j = 0; j < Ny; ++j)
673  {
674  for (unsigned i = 0; i < Nx; ++i)
675  {
676  // The node always needs constructing
677  Node_pt[node_count] = finite_element_pt(element_count)
678  ->construct_node(7, time_stepper_pt);
679 
680  // Set pointers from the elements to new nodes
681  finite_element_pt(element_count)->node_pt(7) = Node_pt[node_count];
682  finite_element_pt(element_count + 1)->node_pt(8) =
683  Node_pt[node_count];
684 
685  // Increase element_count by 2
686  element_count += 2;
687 
688  // Set position of current (Global) Node
689  Node_pt[node_count]->x(0) = xinit + double(i + 2.0 / 3.0) * xstep;
690  Node_pt[node_count]->x(1) = yinit + double(j + 1.0 / 3.0) * ystep;
691 
692  // All nodes are internal in this structure so no boundaries
693  // applicable
694 
695  // Update node_count
696  node_count++;
697  }
698  }
699 
700 
701  // Next is the upper hyp. node -
702  // lower tri. el. number 8, upper tri. el. number 7
703  element_count = 0;
704  // Note: both i,j counters reduced by 1
705  for (unsigned j = 0; j < Ny; ++j)
706  {
707  for (unsigned i = 0; i < Nx; ++i)
708  {
709  // The node always needs constructing
710  Node_pt[node_count] = finite_element_pt(element_count)
711  ->construct_node(8, time_stepper_pt);
712 
713  // Set pointers from the elements to new nodes
714  finite_element_pt(element_count)->node_pt(8) = Node_pt[node_count];
715  finite_element_pt(element_count + 1)->node_pt(7) =
716  Node_pt[node_count];
717 
718  // Increase element_count by 2
719  element_count += 2;
720 
721  // Set position of current (Global) Node
722  Node_pt[node_count]->x(0) = xinit + double(i + 1.0 / 3.0) * xstep;
723  Node_pt[node_count]->x(1) = yinit + double(j + 2.0 / 3.0) * ystep;
724 
725  // All nodes are internal in this structure so no boundaries
726  // applicable
727 
728  // Update node_count
729  node_count++;
730  }
731  }
732 
733 
734  // Next is the upper tri. el. totally internal node with local number 9
735  element_count = 0;
736  // Note: both i,j counters reduced by 1
737  for (unsigned j = 0; j < Ny; ++j)
738  {
739  for (unsigned i = 0; i < Nx; ++i)
740  {
741  // The middle node always needs constructing
742  Node_pt[node_count] = finite_element_pt(element_count + 1)
743  ->construct_node(9, time_stepper_pt);
744 
745  // Set pointers from the elements to new nodes
746  finite_element_pt(element_count + 1)->node_pt(9) =
747  Node_pt[node_count];
748 
749  // Increase element_count by 2
750  element_count += 2;
751 
752  // Set position of current (Global) Node
753  Node_pt[node_count]->x(0) = xinit + double(i + 2.0 / 3.0) * xstep;
754  Node_pt[node_count]->x(1) = yinit + double(j + 2.0 / 3.0) * ystep;
755 
756  // All nodes are internal in this structure so no boundaries
757  // applicable
758 
759  // Update node_count
760  node_count++;
761  }
762  }
763  }
764  }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
virtual Node * construct_node(const unsigned &n)
Definition: elements.h:2509
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
virtual unsigned nnode_1d() const
Definition: elements.h:2218
void add_boundary_node(const unsigned &b, Node *const &node_pt)
Add a (pointer to) a node to the b-th boundary.
Definition: mesh.cc:243
Vector< Node * > Node_pt
Vector of pointers to nodes.
Definition: mesh.h:183
FiniteElement * finite_element_pt(const unsigned &e) const
Definition: mesh.h:473
void set_nboundary(const unsigned &nbound)
Set the number of boundaries in the mesh.
Definition: mesh.h:505
void convert_to_boundary_node(Node *&node_pt, const Vector< FiniteElement * > &finite_element_pt)
Definition: mesh.cc:2590
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
Definition: mesh.h:186
double Lx
Length of mesh in x-direction.
Definition: simple_rectangular_tri_mesh.template.h:84
unsigned Ny
Number of elements in y directions.
Definition: simple_rectangular_tri_mesh.template.h:81
unsigned Nx
Number of elements in x direction.
Definition: simple_rectangular_tri_mesh.template.h:78
double Ly
Length of mesh in y-direction.
Definition: simple_rectangular_tri_mesh.template.h:87
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References oomph::Mesh::add_boundary_node(), oomph::FiniteElement::construct_node(), oomph::Mesh::convert_to_boundary_node(), oomph::Mesh::Element_pt, oomph::Mesh::finite_element_pt(), i, j, oomph::SimpleRectangularTriMesh< ELEMENT >::Lx, oomph::SimpleRectangularTriMesh< ELEMENT >::Ly, oomph::FiniteElement::nnode_1d(), oomph::FiniteElement::node_pt(), oomph::Mesh::Node_pt, oomph::SimpleRectangularTriMesh< ELEMENT >::Nx, oomph::SimpleRectangularTriMesh< ELEMENT >::Ny, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, and oomph::Mesh::set_nboundary().

Member Function Documentation

◆ nx()

template<class ELEMENT >
const unsigned& oomph::SimpleRectangularTriMesh< ELEMENT >::nx ( ) const
inline

Access function for number of elements in x directions.

66  {
67  return Nx;
68  }

References oomph::SimpleRectangularTriMesh< ELEMENT >::Nx.

◆ ny()

template<class ELEMENT >
const unsigned& oomph::SimpleRectangularTriMesh< ELEMENT >::ny ( ) const
inline

Access function for number of elements in y directions.

72  {
73  return Ny;
74  }

References oomph::SimpleRectangularTriMesh< ELEMENT >::Ny.

Member Data Documentation

◆ Lx

template<class ELEMENT >
double oomph::SimpleRectangularTriMesh< ELEMENT >::Lx
private

Length of mesh in x-direction.

Referenced by oomph::SimpleRectangularTriMesh< ELEMENT >::SimpleRectangularTriMesh().

◆ Ly

template<class ELEMENT >
double oomph::SimpleRectangularTriMesh< ELEMENT >::Ly
private

Length of mesh in y-direction.

Referenced by oomph::SimpleRectangularTriMesh< ELEMENT >::SimpleRectangularTriMesh().

◆ Nx

template<class ELEMENT >
unsigned oomph::SimpleRectangularTriMesh< ELEMENT >::Nx
private

◆ Ny

template<class ELEMENT >
unsigned oomph::SimpleRectangularTriMesh< ELEMENT >::Ny
private

The documentation for this class was generated from the following files: