oomph::QuadFromTriangleMesh< ELEMENT > Class Template Reference

#include <quad_from_triangle_mesh.template.h>

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

Public Member Functions

 QuadFromTriangleMesh ()
 Empty constructor. More...
 
 QuadFromTriangleMesh (const std::string &node_file_name, const std::string &element_file_name, const std::string &poly_file_name, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper, const bool &use_attributes=false, const bool &allow_automatic_creation_of_vertices_on_boundaries=true)
 Constructor with the input files. More...
 
 QuadFromTriangleMesh (const QuadFromTriangleMesh &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const QuadFromTriangleMesh &)=delete
 Broken assignment operator. More...
 
 ~QuadFromTriangleMesh ()
 Empty destructor. More...
 
void build_from_scaffold (TriangleScaffoldMesh *tmp_mesh_pt, TimeStepper *time_stepper_pt, const bool &use_attributes)
 Build the quad mesh from the given scaffold mesh. 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)
 
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...
 
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...
 
- Public Member Functions inherited from oomph::QuadMeshBase
 QuadMeshBase ()
 Constructor (empty) More...
 
 QuadMeshBase (const QuadMeshBase &node)=delete
 Broken copy constructor. More...
 
void operator= (const QuadMeshBase &)=delete
 Broken assignment operator. More...
 
virtual ~QuadMeshBase ()
 Destructor (empty) More...
 
void setup_boundary_element_info ()
 
void setup_boundary_element_info (std::ostream &outfile)
 

Public Attributes

TimeStepperTime_stepper_pt
 Timestepper used to build elements. More...
 
bool Use_attributes
 

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::QuadFromTriangleMesh< ELEMENT >

Quad mesh built on top of triangle scaffold mesh coming from the triangle mesh generator Triangle. http://www.cs.cmu.edu/~quake/triangle.html

Constructor & Destructor Documentation

◆ QuadFromTriangleMesh() [1/3]

template<class ELEMENT >
oomph::QuadFromTriangleMesh< ELEMENT >::QuadFromTriangleMesh ( )
inline

Empty constructor.

76  {
77 #ifdef OOMPH_HAS_TRIANGLE_LIB
78  // By default allow the automatic creation of vertices along the
79  // boundaries by Triangle
81 #endif
82 
83  // Mesh can only be built with 2D Qelements.
84  MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
85  }
bool Allow_automatic_creation_of_vertices_on_boundaries
Definition: unstructured_two_d_mesh_geometry_base.h:2575

References oomph::UnstructuredTwoDMeshGeometryBase::Allow_automatic_creation_of_vertices_on_boundaries.

◆ QuadFromTriangleMesh() [2/3]

template<class ELEMENT >
oomph::QuadFromTriangleMesh< ELEMENT >::QuadFromTriangleMesh ( const std::string &  node_file_name,
const std::string &  element_file_name,
const std::string &  poly_file_name,
TimeStepper time_stepper_pt = &Mesh::Default_TimeStepper,
const bool use_attributes = false,
const bool allow_automatic_creation_of_vertices_on_boundaries = true 
)
inline

Constructor with the input files.

95  {
96  // Mesh can only be built with 2D Qelements.
97  MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
98 
99  // Initialize the value for allowing creation of points on boundaries
101  allow_automatic_creation_of_vertices_on_boundaries;
102 
103  // Store Timestepper used to build elements
104  this->Time_stepper_pt = time_stepper_pt;
105 
106  // Store the attributes
107  this->Use_attributes = use_attributes;
108 
109  // Build scaffold
110  TriangleScaffoldMesh* tmp_mesh_pt = new TriangleScaffoldMesh(
111  node_file_name, element_file_name, poly_file_name);
112 
113  // Convert mesh from scaffold to actual mesh
114  this->build_from_scaffold(tmp_mesh_pt, time_stepper_pt, use_attributes);
115 
116  // Kill the scaffold
117  delete tmp_mesh_pt;
118  tmp_mesh_pt = 0;
119 
120  // Setup boundary coordinates for boundaries
121  unsigned nbound = nboundary();
122  for (unsigned ibound = 0; ibound < nbound; ibound++)
123  {
124  this->template setup_boundary_coordinates<ELEMENT>(ibound);
125  }
126  }
unsigned nboundary() const
Return number of boundaries.
Definition: mesh.h:827
TimeStepper * Time_stepper_pt
Timestepper used to build elements.
Definition: quad_from_triangle_mesh.template.h:558
bool Use_attributes
Definition: quad_from_triangle_mesh.template.h:562
void build_from_scaffold(TriangleScaffoldMesh *tmp_mesh_pt, TimeStepper *time_stepper_pt, const bool &use_attributes)
Build the quad mesh from the given scaffold mesh.
Definition: quad_from_triangle_mesh.template.cc:71

References oomph::UnstructuredTwoDMeshGeometryBase::Allow_automatic_creation_of_vertices_on_boundaries, oomph::QuadFromTriangleMesh< ELEMENT >::build_from_scaffold(), oomph::Mesh::nboundary(), oomph::QuadFromTriangleMesh< ELEMENT >::Time_stepper_pt, and oomph::QuadFromTriangleMesh< ELEMENT >::Use_attributes.

◆ QuadFromTriangleMesh() [3/3]

template<class ELEMENT >
oomph::QuadFromTriangleMesh< ELEMENT >::QuadFromTriangleMesh ( const QuadFromTriangleMesh< ELEMENT > &  dummy)
delete

Broken copy constructor.

◆ ~QuadFromTriangleMesh()

template<class ELEMENT >
oomph::QuadFromTriangleMesh< ELEMENT >::~QuadFromTriangleMesh ( )
inline

Empty destructor.

522  {
523 #ifdef OOMPH_HAS_TRIANGLE_LIB
524 
525  std::set<TriangleMeshCurveSection*>::iterator it_polyline;
526  for (it_polyline = Free_curve_section_pt.begin();
527  it_polyline != Free_curve_section_pt.end();
528  it_polyline++)
529  {
530  delete (*it_polyline);
531  }
532 
533  std::set<TriangleMeshPolygon*>::iterator it_polygon;
534  for (it_polygon = Free_polygon_pt.begin();
535  it_polygon != Free_polygon_pt.end();
536  it_polygon++)
537  {
538  delete (*it_polygon);
539  }
540 
541  std::set<TriangleMeshOpenCurve*>::iterator it_open_polyline;
542  for (it_open_polyline = Free_open_curve_pt.begin();
543  it_open_polyline != Free_open_curve_pt.end();
544  it_open_polyline++)
545  {
546  delete (*it_open_polyline);
547  }
548 
549 #endif
550  }
std::set< TriangleMeshOpenCurve * > Free_open_curve_pt
Definition: unstructured_two_d_mesh_geometry_base.h:2646
std::set< TriangleMeshCurveSection * > Free_curve_section_pt
Definition: unstructured_two_d_mesh_geometry_base.h:2638
std::set< TriangleMeshPolygon * > Free_polygon_pt
Definition: unstructured_two_d_mesh_geometry_base.h:2642

References oomph::UnstructuredTwoDMeshGeometryBase::Free_curve_section_pt, oomph::UnstructuredTwoDMeshGeometryBase::Free_open_curve_pt, and oomph::UnstructuredTwoDMeshGeometryBase::Free_polygon_pt.

Member Function Documentation

◆ build_from_scaffold()

template<class ELEMENT >
void oomph::QuadFromTriangleMesh< ELEMENT >::build_from_scaffold ( TriangleScaffoldMesh tmp_mesh_pt,
TimeStepper time_stepper_pt,
const bool use_attributes 
)

Build the quad mesh from the given scaffold mesh.

Build the full mesh with the help of the scaffold mesh coming from the triangle mesh generator, Triangle. To build this quad element based mesh we make use of the fact that a triangle element can be split as shown in the diagram below:

             N2
            | |                 N0 : 1st scaffold element node
           |   |                N1 : 2nd scaffold element node
          |     |               N2 : 3rd scaffold element node
         |       |
      C |   Q_2   | B           Edge 0 : N0 --> N1
       | |       | |            Edge 1 : N1 --> N2
      |   |     |   |           Edge 2 : N2 --> N0
     |     |   |     |
    |       | |       |         A : Midpoint of edge 0
   |   Q_0   |   Q_1   |        B : Midpoint of edge 1
  |          |          |       C : Midpoint of edge 2
 |           |           |
N0 __________|__________ N1
             A

The intersection of all three quad elements is the centroid. Using this splitting, the subsequent mesh will consist of quadrilaterals whose shape which depend on the structure of the underlying mesh.

75  {
76  // Create space for elements
77  unsigned nelem = tmp_mesh_pt->nelement();
78 
79  // We will have 3 quad elements per scaffold element
80  Element_pt.resize(3 * nelem);
81 
82  // Set number of boundaries
83  unsigned nbound = tmp_mesh_pt->nboundary();
84 
85  // Resize the boundary information (the number of boundaries doesn't
86  // change)
87  set_nboundary(nbound);
88 
89  // Stores each element attached to a boundary and the index of the
90  // face of the given element attached to the boundary
91  Boundary_element_pt.resize(nbound);
92  Face_index_at_boundary.resize(nbound);
93 
94  // Create a quad element for nodal data
95  ELEMENT* temp_el_pt = new ELEMENT;
96 
97  // Get the number of nodes in a quad element
98  unsigned nnode_el = temp_el_pt->nnode();
99 
100  // Find the number of nodes along one edge of a quad element
101  unsigned nnode_1d = temp_el_pt->nnode_1d();
102 
103  // Calculate the number of nodes that will lie along an edge of a
104  // triangle element in the scaffold mesh
105  unsigned nnode_edge = 2 * nnode_1d - 1;
106 
107  // Delete the element pointer
108  delete temp_el_pt;
109 
110  // Make it a null pointer
111  temp_el_pt = 0;
112 
113  // Create dummy linear quad for geometry
114  QElement<2, 2> dummy_element;
115 
116  // The dimension of the element
117  unsigned n_dim = 2;
118 
119  // The position type
120  unsigned n_position_type = 1;
121 
122  // Don't assign memory for any values
123  unsigned initial_n_value = 0;
124 
125  // Loop over the nodes of the element and make them
126  for (unsigned j = 0; j < 4; j++)
127  {
128  dummy_element.node_pt(j) =
129  new Node(n_dim, n_position_type, initial_n_value);
130  }
131 
132  // Local node number of each quad element corner
133  unsigned corner_0 = 0;
134  unsigned corner_1 = nnode_1d - 1;
135  unsigned corner_2 = nnode_el - nnode_1d;
136  unsigned corner_3 = nnode_el - 1;
137 
138  // Create a map to return a vector of pointers to nnode_1d nodes where
139  // the input is an edge. If the edge hasn't been set up then this will
140  // return a null pointer. Note: all node pointers on an edge will be
141  // stored in clockwise ordering. Therefore, to copy the data of an
142  // edge into the adjoining element we must proceed through the vector
143  // backwards (as progressing through an edge of an element in a clockwise
144  // manner is equivalent to proceeding through the edge of the neighbouring
145  // element in an anti-clockwise manner)
146  std::map<Edge, Vector<Node*>> edge_nodes_map;
147 
148  // Set up a map to check if the scaffold mesh node has been set up in the
149  // quad mesh. If the node has been set up this map will return a pointer
150  // to it otherwise it will return a null pointer
151  std::map<Node*, Node*> scaffold_to_quad_mesh_node;
152 
153  // Loop over elements in scaffold mesh
154  unsigned new_el_count = 0;
155 
156  // Create storage for the coordinates of the centroid
157  Vector<double> centroid(2);
158 
159  // Create storage for the coordinates of the vertices of the triangle
160  Vector<Vector<double>> triangle_vertex(3);
161 
162  // Loop over all of the elements in the scaffold mesh
163  for (unsigned e = 0; e < nelem; e++)
164  {
165  // Initialise centroid values for the e-th triangle element
166  centroid[0] = 0.0;
167  centroid[1] = 0.0;
168 
169  // Loop over the scaffold element nodes
170  for (unsigned j = 0; j < 3; j++)
171  {
172  // Resize the j-th triangle_vertex entry to contain the x and
173  // y-coordinate
174  triangle_vertex[j].resize(2);
175 
176  // Get the coordinates
177  double x = tmp_mesh_pt->finite_element_pt(e)->node_pt(j)->x(0);
178  double y = tmp_mesh_pt->finite_element_pt(e)->node_pt(j)->x(1);
179 
180  // Increment the centroid coordinates
181  centroid[0] += x;
182  centroid[1] += y;
183 
184  // Assign the triangle_vertex coordinates
185  triangle_vertex[j][0] = x;
186  triangle_vertex[j][1] = y;
187  }
188 
189  // Divide the centroid entries by 3 to get the centroid coordinates
190  centroid[0] /= 3.0;
191  centroid[1] /= 3.0;
192 
193  // Create element pointers and assign them to a vector
194  //----------------------------------------------------
195  // Make new quad elements of the type specified by the template parameter
196  ELEMENT* el0_pt = new ELEMENT;
197  ELEMENT* el1_pt = new ELEMENT;
198  ELEMENT* el2_pt = new ELEMENT;
199 
200  // Create a vector of ELEMENTs to store el0_pt, el1_pt and el2_pt
201  Vector<ELEMENT*> el_vector_pt(3, 0);
202 
203  // Assign the entries to el_vector_pt
204  el_vector_pt[0] = el0_pt;
205  el_vector_pt[1] = el1_pt;
206  el_vector_pt[2] = el2_pt;
207 
208 
209  // Create the first node in each quad element and store in Node_pt.
210  // These correspond to the nodes of the simplex triangle stored in
211  // Tmp_mesh_pt. If they have already been set up then we do nothing:
212  //------------------------------------------------------------------
213  // Loop over the scaffold element nodes and check to see if they have
214  // been set up
215  for (unsigned j = 0; j < 3; j++)
216  {
217  // Pointer to node in the scaffold mesh
218  Node* scaffold_node_pt = tmp_mesh_pt->finite_element_pt(e)->node_pt(j);
219 
220  // Check if the node has been set up yet
221  Node* qmesh_node_pt = scaffold_to_quad_mesh_node[scaffold_node_pt];
222 
223  // Haven't done this one yet
224  if (qmesh_node_pt == 0)
225  {
226  // Get pointer to set of mesh boundaries that this
227  // scaffold node occupies; NULL if the node is not on any boundary
228  std::set<unsigned>* boundaries_pt;
229  scaffold_node_pt->get_boundaries_pt(boundaries_pt);
230 
231  // Check to see if it's on any boundaries
232  if (boundaries_pt != 0)
233  {
234  // Create new boundary node. The scaffold element nodes are the
235  // corners of a simplex triangle and thus always correspond to the
236  // first node in each quad element
237  qmesh_node_pt = el_vector_pt[j]->construct_boundary_node(
238  corner_0, time_stepper_pt);
239 
240  // Add to boundaries
241  for (std::set<unsigned>::iterator it = boundaries_pt->begin();
242  it != boundaries_pt->end();
243  ++it)
244  {
245  add_boundary_node(*it, qmesh_node_pt);
246  }
247  }
248  // Build normal node
249  else
250  {
251  // Create new normal node
252  qmesh_node_pt =
253  el_vector_pt[j]->construct_node(corner_0, time_stepper_pt);
254  }
255 
256  // Add the mapping from the scaffold mesh node to the quad mesh node
257  scaffold_to_quad_mesh_node[scaffold_node_pt] = qmesh_node_pt;
258 
259  // Copy new node, created using the NEW element's construct_node
260  // function into global storage, using the same global
261  // node number that we've just associated with the
262  // corresponding node in the scaffold mesh
263  Node_pt.push_back(qmesh_node_pt);
264  }
265  // If this node has already been done we need to copy the data across
266  else
267  {
268  el_vector_pt[j]->node_pt(corner_0) = qmesh_node_pt;
269  }
270 
271 
272  // Set global coordinate
273  el_vector_pt[j]->node_pt(corner_0)->x(0) = triangle_vertex[j][0];
274  el_vector_pt[j]->node_pt(corner_0)->x(1) = triangle_vertex[j][1];
275  }
276 
277 
278  // Create the edges of the scaffold element and check to see if
279  // they've been set up yet or not. If they haven't:
280  //--------------------------------------------------------------
281  // Make the three edges of the triangle
282  Edge edge0(tmp_mesh_pt->finite_element_pt(e)->node_pt(0),
283  tmp_mesh_pt->finite_element_pt(e)->node_pt(1));
284  Edge edge1(tmp_mesh_pt->finite_element_pt(e)->node_pt(1),
285  tmp_mesh_pt->finite_element_pt(e)->node_pt(2));
286  Edge edge2(tmp_mesh_pt->finite_element_pt(e)->node_pt(2),
287  tmp_mesh_pt->finite_element_pt(e)->node_pt(0));
288 
289  // Check if the edges have been set up (each will have size nnode_1d).
290  // If they have not been set up yet, this will
291  Vector<Node*> edge0_vector_pt = edge_nodes_map[edge0];
292  Vector<Node*> edge1_vector_pt = edge_nodes_map[edge1];
293  Vector<Node*> edge2_vector_pt = edge_nodes_map[edge2];
294 
295  // Bools to indicate whether or not the edges have been set up
296  bool edge0_setup = (edge0_vector_pt.size() != 0);
297  bool edge1_setup = (edge1_vector_pt.size() != 0);
298  bool edge2_setup = (edge2_vector_pt.size() != 0);
299 
300  // If edge 0 hasn't been set up (node 0 to node 1)
301  if (!edge0_setup)
302  {
303  // Resize the vector to have length nnode_1d
304  edge0_vector_pt.resize(nnode_edge, 0);
305 
306  // First node along edge 0 is the first node of element 0
307  edge0_vector_pt[0] = el_vector_pt[0]->node_pt(0);
308 
309  // Last node along edge 0 is the first node of element 1
310  edge0_vector_pt[nnode_edge - 1] = el_vector_pt[1]->node_pt(0);
311  }
312 
313  // If edge 1 hasn't been set up (node 1 to node 2)
314  if (!edge1_setup)
315  {
316  // Resize the vector to have length nnode_1d
317  edge1_vector_pt.resize(nnode_edge, 0);
318 
319  // First node along edge 1 is the first node of element 1
320  edge1_vector_pt[0] = el_vector_pt[1]->node_pt(0);
321 
322  // Last node along edge 1 is the first node of element 2
323  edge1_vector_pt[nnode_edge - 1] = el_vector_pt[2]->node_pt(0);
324  }
325 
326  // If edge 2 hasn't been set up (node 2 to node 0)
327  if (!edge2_setup)
328  {
329  // Resize the vector to have length nnode_1d
330  edge2_vector_pt.resize(nnode_edge, 0);
331 
332  // First node along edge 2 is the first node of element 2
333  edge2_vector_pt[0] = el_vector_pt[2]->node_pt(0);
334 
335  // Last node along edge 2 is the first node of element 0
336  edge2_vector_pt[nnode_edge - 1] = el_vector_pt[0]->node_pt(0);
337  }
338 
339 
340 #ifdef PARANOID
341  // If any of the edges have been set up, make sure that that the endpoints
342  // in the returned vectors have the same address as those on the vertices
343 
344  // Come back and finish this off.
345  // To check:
346  // - If two edges which have been set up have the same node in the
347  // middle
348  // - If an edge has already been set up then the map will return the
349  // same node as in the vector
350 #endif
351 
352  // Boundary IDs for bottom and left edge of quad
353  // from scaffold mesh (if these remain zero the edges
354  // are not on a boundary)
355  unsigned q0_lower_boundary_id = 0;
356  unsigned q0_left_boundary_id = 0;
357  unsigned q1_lower_boundary_id = 0;
358  unsigned q1_left_boundary_id = 0;
359  unsigned q2_lower_boundary_id = 0;
360  unsigned q2_left_boundary_id = 0;
361 
362  // Lower/left boundary IDs for quad 0; the lower edge in quad 0 is on
363  // edge 0 of the scaffold triangle and the left edge in quad is on edge
364  // 2 in scaffold triangle
365  q0_lower_boundary_id = tmp_mesh_pt->edge_boundary(e, 0);
366  q0_left_boundary_id = tmp_mesh_pt->edge_boundary(e, 2);
367 
368  // Lower/left boundary IDs for quad 1; the lower edge in quad 1 is on
369  // edge 1 of the scaffold triangle and the left edge in quad is on edge
370  // 0 of the scaffold triangle
371  q1_lower_boundary_id = tmp_mesh_pt->edge_boundary(e, 1);
372  q1_left_boundary_id = tmp_mesh_pt->edge_boundary(e, 0);
373 
374  // Lower/left boundary IDs for quad 2; the lower edge in quad 2 is on
375  // edge 2 of the scaffold triangle and the left edge in quad is on edge
376  // 1 of the scaffold triangle
377  q2_lower_boundary_id = tmp_mesh_pt->edge_boundary(e, 2);
378  q2_left_boundary_id = tmp_mesh_pt->edge_boundary(e, 1);
379 
380  // Store the boundary IDs as a vector; allows us to loop over them easily
381  Vector<unsigned> boundary_id_vector(6, 0);
382  boundary_id_vector[0] = q0_lower_boundary_id;
383  boundary_id_vector[1] = q0_left_boundary_id;
384  boundary_id_vector[2] = q1_lower_boundary_id;
385  boundary_id_vector[3] = q1_left_boundary_id;
386  boundary_id_vector[4] = q2_lower_boundary_id;
387  boundary_id_vector[5] = q2_left_boundary_id;
388 
389  // Loop over the quad elements and store the boundary elements in the
390  // vector Boundary_element_pt
391  for (unsigned j = 0; j < 3; j++)
392  {
393  // Loop over the lower and the left boundary ID in the j'th element
394  for (unsigned k = 0; k < 2; k++)
395  {
396  // The quad element lies on a boundary of the mesh
397  if (boundary_id_vector[2 * j + k] > 0)
398  {
399  // Since the j'th quad element lies on a boundary of the mesh we add
400  // a pointer to the element to the appropriate entry of
401  // Boundary_element_pt
402  Boundary_element_pt[boundary_id_vector[2 * j + k] - 1].push_back(
403  el_vector_pt[j]);
404 
405  // If k=0 then the lower boundary of the quad element lies on
406  // the boundary of the mesh and if k=1 then the left boundary
407  // of the quad element lies on the mesh boundary. For quad elements
408  // the indices are as follows:
409  // North face: 2
410  // East face: 1
411  // South face: -2
412  // West face: -1
413  if (k == 0)
414  {
415  Face_index_at_boundary[boundary_id_vector[2 * j + k] - 1]
416  .push_back(-2);
417  }
418  else
419  {
420  Face_index_at_boundary[boundary_id_vector[2 * j + k] - 1]
421  .push_back(-1);
422  } // if (k==0)
423  } // if (boundary_id_vector[2*j+k]>0)
424  } // for (unsigned k=0;k<2;k++)
425  } // for (unsigned j=0;j<3;j++)
426 
427 
428  // The upper right node is always the centroid. Note: The 'corner_3' node
429  // lies within each of the three quad elements so we simply share the
430  // pointer to it with each element:
431  //---------------------------------------------------------------------------
432  // Construct the centroid node
433  Node* nod_pt = el0_pt->construct_node(corner_3, time_stepper_pt);
434 
435  // Add the pointer to the vector of nodal pointers
436  Node_pt.push_back(nod_pt);
437 
438  // Quad 0
439  el0_pt->node_pt(corner_3)->x(0) = centroid[0];
440  el0_pt->node_pt(corner_3)->x(1) = centroid[1];
441 
442  // Quad 1
443  el1_pt->node_pt(corner_3) = el0_pt->node_pt(corner_3);
444 
445  // Quad 2
446  el2_pt->node_pt(corner_3) = el0_pt->node_pt(corner_3);
447 
448 
449  // Set the nodal positions of the dummy element to emulate the FIRST
450  // quad element (this allows for simple linear interpolation later):
451  //------------------------------------------------------------------
452  // Bottom-left corner
453  dummy_element.node_pt(0)->x(0) = triangle_vertex[0][0];
454  dummy_element.node_pt(0)->x(1) = triangle_vertex[0][1];
455 
456  // Bottom-right corner
457  dummy_element.node_pt(1)->x(0) =
458  0.5 * (triangle_vertex[0][0] + triangle_vertex[1][0]);
459  dummy_element.node_pt(1)->x(1) =
460  0.5 * (triangle_vertex[0][1] + triangle_vertex[1][1]);
461 
462  // Top-left corner
463  dummy_element.node_pt(2)->x(0) =
464  0.5 * (triangle_vertex[0][0] + triangle_vertex[2][0]);
465  dummy_element.node_pt(2)->x(1) =
466  0.5 * (triangle_vertex[0][1] + triangle_vertex[2][1]);
467 
468  // Top-right corner
469  dummy_element.node_pt(3)->x(0) = centroid[0];
470  dummy_element.node_pt(3)->x(1) = centroid[1];
471 
472 
473  // Set up all of the nodes in the first quad element (Q0):
474  //--------------------------------------------------------
475  // Local and global coordinate vectors for the nodes
476  Vector<double> s(2);
477  Vector<double> x(2);
478 
479  // Loop over all of nodes in Q0 noting that the lower left corner node
480  // (node 0) and the upper right corner node (centroid) have already
481  // been set up
482  for (unsigned j = 1; j < corner_3; j++)
483  {
484  // Indicates whether or not the node has been set up yet
485  bool done = false;
486 
487  // On the lower edge
488  if (j < nnode_1d)
489  {
490  // If the lower edge has already been set up then we already know the
491  // nodes along this edge
492  if (edge0_setup)
493  {
494  // The j'th node along this edge is the (nnode_1d-j)'th node in the
495  // vector (remembering that the ordering is backwards since it has
496  // already been set up)
497  el0_pt->node_pt(j) = edge0_vector_pt[(nnode_edge - 1) - j];
498 
499  // Since the node has already been set up we do not need to sort
500  // out its global coordinate data so skip to the next node
501  continue;
502  }
503  // If the edge hasn't been set up yet
504  else
505  {
506  // If the node lies on a boundary too then we need to construct a
507  // boundary node
508  if (q0_lower_boundary_id > 0)
509  {
510  // Construct a boundary node
511  Node* nod_pt =
512  el0_pt->construct_boundary_node(j, time_stepper_pt);
513 
514  // Add it to the list of boundary nodes
515  add_boundary_node(q0_lower_boundary_id - 1, nod_pt);
516 
517  // Add the node into the vector of nodes on edge 0
518  edge0_vector_pt[j] = nod_pt;
519 
520  // Add it to the list of nodes in the mesh
521  Node_pt.push_back(nod_pt);
522 
523  // Indicate the j'th node has been set up
524  done = true;
525  }
526  }
527 
528  // Node is not on a mesh boundary but on the lower edge
529  if (!done)
530  {
531  // Construct a normal node
532  Node* nod_pt = el0_pt->construct_node(j, time_stepper_pt);
533 
534  // Add the node into the vector of nodes on edge 0
535  edge0_vector_pt[j] = nod_pt;
536 
537  // Add it to the list of nodes in the mesh
538  Node_pt.push_back(nod_pt);
539 
540  // Indicate the j'th node has been set up
541  done = true;
542  }
543  }
544  // On the left edge
545  else if (j % nnode_1d == 0)
546  {
547  // If the left edge has already been set up then we already know the
548  // nodes along this edge
549  if (edge2_setup)
550  {
551  // The j'th node is the (j/nnode_1d)'th node along this edge and
552  // thus the (j/nnode_1d)'th entry in the edge vector
553  el0_pt->node_pt(j) = edge2_vector_pt[j / nnode_1d];
554 
555  // Since the node has already been set up we do not need to sort
556  // out its global coordinate data
557  continue;
558  }
559  // If the edge hasn't been set up yet
560  else
561  {
562  if (q0_left_boundary_id > 0)
563  {
564  // Construct a boundary node
565  Node* nod_pt =
566  el0_pt->construct_boundary_node(j, time_stepper_pt);
567 
568  // Add it to the list of boundary nodes
569  add_boundary_node(q0_left_boundary_id - 1, nod_pt);
570 
571  // Add the node into the vector of nodes on edge 2 in clockwise
572  // order
573  edge2_vector_pt[(nnode_edge - 1) - (j / nnode_1d)] = nod_pt;
574 
575  // Add it to the list of nodes in the mesh
576  Node_pt.push_back(nod_pt);
577 
578  // Indicate that the j'th node has been set up
579  done = true;
580  }
581  }
582 
583  // Node is not on a mesh boundary but on the left edge
584  if (!done)
585  {
586  // Construct a normal node
587  Node* nod_pt = el0_pt->construct_node(j, time_stepper_pt);
588 
589  // Add the node into the vector of nodes on edge 2 in clockwise
590  // order
591  edge2_vector_pt[(nnode_edge - 1) - (j / nnode_1d)] = nod_pt;
592 
593  // Add it to the list of nodes in the mesh
594  Node_pt.push_back(nod_pt);
595 
596  // Indicate the j'th node has been set up
597  done = true;
598  }
599  }
600 
601  // Node is not on a mesh boundary or on the edge of the scaffold element
602  if (!done)
603  {
604  // Construct a normal node
605  Node* nod_pt = el0_pt->construct_node(j, time_stepper_pt);
606 
607  // Add it to the list of nodes in the mesh
608  Node_pt.push_back(nod_pt);
609  }
610 
611  // Get local coordinate
612  el0_pt->local_coordinate_of_node(j, s);
613 
614  // Interpolate position linearly between vertex nodes
615  dummy_element.interpolated_x(s, x);
616  el0_pt->node_pt(j)->x(0) = x[0];
617  el0_pt->node_pt(j)->x(1) = x[1];
618  }
619 
620 
621  // Set the nodal positions of the dummy element to now emulate the
622  // SECOND quad element:
623  //------------------------------------------------------------------
624  // Note: we do not need to change the top-right corner since it always
625  // coincides with the centroid of the triangle element
626 
627  // Bottom-left corner
628  dummy_element.node_pt(0)->x(0) = triangle_vertex[1][0];
629  dummy_element.node_pt(0)->x(1) = triangle_vertex[1][1];
630 
631  // Bottom-right corner
632  dummy_element.node_pt(1)->x(0) =
633  0.5 * (triangle_vertex[1][0] + triangle_vertex[2][0]);
634  dummy_element.node_pt(1)->x(1) =
635  0.5 * (triangle_vertex[1][1] + triangle_vertex[2][1]);
636 
637  // Top-left corner
638  dummy_element.node_pt(2)->x(0) =
639  0.5 * (triangle_vertex[0][0] + triangle_vertex[1][0]);
640  dummy_element.node_pt(2)->x(1) =
641  0.5 * (triangle_vertex[0][1] + triangle_vertex[1][1]);
642 
643 
644  // Set up all of the nodes in the second quad element (Q1):
645  //--------------------------------------------------------
646  // Here we need to notice that we have already set up the final nnode_1d
647  // nodes (the upper edge of Q1 coincides with the right edge of Q0)
648 
649  // Loop over nodes 1 to (corner_2-1) in Q1 noting that the lower left
650  // corner node (node 0) and the upper edge of Q1 contains nodes
651  // corner_2 to corner_3
652  for (unsigned j = 1; j < corner_2; j++)
653  {
654  // Indicates whether or not the node has been set up yet
655  bool done = false;
656 
657  // On the lower edge
658  if (j < nnode_1d)
659  {
660  // If the lower edge has already been set up then we already know the
661  // nodes along this edge
662  if (edge1_setup)
663  {
664  // The j'th node along this edge is the (nnode_1d-j)'th node in the
665  // vector (remembering that the ordering is backwards if it has
666  // already been set up)
667  el1_pt->node_pt(j) = edge1_vector_pt[(nnode_edge - 1) - j];
668 
669  // Since the node has already been set up we do not need to sort
670  // out its global coordinate data
671  continue;
672  }
673  // If the edge hasn't been set up yet
674  else
675  {
676  // If the node lies on a boundary too then we need to construct a
677  // boundary node
678  if (q1_lower_boundary_id > 0)
679  {
680  // Construct a boundary node
681  Node* nod_pt =
682  el1_pt->construct_boundary_node(j, time_stepper_pt);
683 
684  // Add it to the list of boundary nodes
685  add_boundary_node(q1_lower_boundary_id - 1, nod_pt);
686 
687  // Add the node into the vector of nodes on edge 1
688  edge1_vector_pt[j] = nod_pt;
689 
690  // Add it to the list of nodes in the mesh
691  Node_pt.push_back(nod_pt);
692 
693  // Indicate the j'th node has been set up
694  done = true;
695  }
696  }
697 
698  // Node is not on a mesh boundary but on the lower edge
699  if (!done)
700  {
701  // Construct a normal node
702  Node* nod_pt = el1_pt->construct_node(j, time_stepper_pt);
703 
704  // Add the node into the vector of nodes on edge 1
705  edge1_vector_pt[j] = nod_pt;
706 
707  // Add it to the list of nodes in the mesh
708  Node_pt.push_back(nod_pt);
709 
710  // Indicate the j'th node has been set up
711  done = true;
712  }
713  }
714  // On the left edge
715  else if (j % nnode_1d == 0)
716  {
717  // If the left edge has already been set up then we already know the
718  // nodes along this edge
719  if (edge0_setup)
720  {
721  // The j'th node along this edge is the (j/nnode_1d)'th node in the
722  // vector
723  el1_pt->node_pt(j) = edge0_vector_pt[j / nnode_1d];
724 
725  // Since the node has already been set up we do not need to sort
726  // out its global coordinate data
727  continue;
728  }
729  // If the edge hasn't been set up yet
730  else
731  {
732  if (q1_left_boundary_id > 0)
733  {
734  // Construct a boundary node
735  Node* nod_pt =
736  el1_pt->construct_boundary_node(j, time_stepper_pt);
737 
738  // Add it to the list of boundary nodes
739  add_boundary_node(q1_left_boundary_id - 1, nod_pt);
740 
741  // Add the node into the vector of nodes on edge 0 in clockwise
742  // order
743  edge0_vector_pt[(nnode_edge - 1) - (j / nnode_1d)] = nod_pt;
744 
745  // Add it to the list of nodes in the mesh
746  Node_pt.push_back(nod_pt);
747 
748  // Indicate that the j'th node has been set up
749  done = true;
750  }
751  }
752 
753  // Node is not on a mesh boundary but on the left edge
754  if (!done)
755  {
756  // Construct a normal node
757  Node* nod_pt = el1_pt->construct_node(j, time_stepper_pt);
758 
759  // Add the node into the vector of nodes on edge 0 in clockwise
760  // order
761  edge0_vector_pt[(nnode_edge - 1) - (j / nnode_1d)] = nod_pt;
762 
763  // Add it to the list of nodes in the mesh
764  Node_pt.push_back(nod_pt);
765 
766  // Indicate the j'th node has been set up
767  done = true;
768  }
769  }
770 
771  // Node is not on a mesh boundary or the scaffold element boundary
772  if (!done)
773  {
774  // Construct a normal node
775  Node* nod_pt = el1_pt->construct_node(j, time_stepper_pt);
776 
777  // Add it to the list of nodes in the mesh
778  Node_pt.push_back(nod_pt);
779  }
780 
781  // Get local coordinate
782  el1_pt->local_coordinate_of_node(j, s);
783 
784  // Interpolate position linearly between vertex nodes
785  dummy_element.interpolated_x(s, x);
786  el1_pt->node_pt(j)->x(0) = x[0];
787  el1_pt->node_pt(j)->x(1) = x[1];
788  }
789 
790 
791  // We now need to loop over nodes corner_2 to (corner_3-1) and copy the
792  // given information from Q0. We do not need to set up the (corner_3)'th
793  // node since it coincides with the centroid which has already been set up
794  for (unsigned j = corner_2; j < corner_3; j++)
795  {
796  // The nodes along the upper edge of Q1 go from corner_2 to corner_3-1
797  // while the nodes along the right edge of Q0 go from corner_1 to
798  // (corner_3-nnode_1d) in increments of nnode_1d
799  el1_pt->node_pt(j) =
800  el0_pt->node_pt(corner_1 + (j - corner_2) * nnode_1d);
801  }
802 
803 
804  // Set the nodal positions of the dummy element to now emulate the
805  // THIRD quad element:
806  //------------------------------------------------------------------
807  // Note: we do not need to change the top-right corner since it always
808  // coincides with the centroid of the triangle element
809 
810  // Bottom-left corner
811  dummy_element.node_pt(0)->x(0) = triangle_vertex[2][0];
812  dummy_element.node_pt(0)->x(1) = triangle_vertex[2][1];
813 
814  // Bottom-right corner
815  dummy_element.node_pt(1)->x(0) =
816  0.5 * (triangle_vertex[0][0] + triangle_vertex[2][0]);
817  dummy_element.node_pt(1)->x(1) =
818  0.5 * (triangle_vertex[0][1] + triangle_vertex[2][1]);
819 
820  // Top-left corner
821  dummy_element.node_pt(2)->x(0) =
822  0.5 * (triangle_vertex[1][0] + triangle_vertex[2][0]);
823  dummy_element.node_pt(2)->x(1) =
824  0.5 * (triangle_vertex[1][1] + triangle_vertex[2][1]);
825 
826 
827  // Set up all of the nodes in the third quad element (Q2):
828  //--------------------------------------------------------
829  // Here we need to notice that we have already set up the final nnode_1d
830  // nodes (the upper edge of Q2 coincides with the right edge of Q1).
831  // We have also already set up the nodes on the right edge of Q2 (the
832  // right edge of Q2 coincides with the upper edge of Q0)
833 
834  // Loop over nodes 1 to (corner_2-1)
835  for (unsigned j = 1; j < corner_2; j++)
836  {
837  // Indicates whether or not the node has been set up yet
838  bool done = false;
839 
840  // On the lower edge
841  if (j < nnode_1d - 1)
842  {
843  // If the lower edge has already been set up then we already know the
844  // nodes along this edge
845  if (edge2_setup)
846  {
847  // The j'th node along this edge is the (nnode_1d-j)'th node in the
848  // vector (remembering that the ordering is backwards if it has
849  // already been set up)
850  el2_pt->node_pt(j) = edge2_vector_pt[(nnode_edge - 1) - j];
851 
852  // Since the node has already been set up we do not need to sort
853  // out its global coordinate data
854  continue;
855  }
856  // If the edge hasn't been set up yet
857  else
858  {
859  // If the node lies on a boundary too then we need to construct a
860  // boundary node
861  if (q2_lower_boundary_id > 0)
862  {
863  // Construct a boundary node
864  Node* nod_pt =
865  el2_pt->construct_boundary_node(j, time_stepper_pt);
866 
867  // Add it to the list of boundary nodes
868  add_boundary_node(q2_lower_boundary_id - 1, nod_pt);
869 
870  // Add the node into the vector of nodes on edge 2
871  edge2_vector_pt[j] = nod_pt;
872 
873  // Add it to the list of nodes in the mesh
874  Node_pt.push_back(nod_pt);
875 
876  // Indicate the j'th node has been set up
877  done = true;
878  }
879  }
880 
881  // Node is not on a mesh boundary but on the lower edge
882  if (!done)
883  {
884  // Construct a normal node
885  Node* nod_pt = el2_pt->construct_node(j, time_stepper_pt);
886 
887  // Add the node into the vector of nodes on edge 2
888  edge2_vector_pt[j] = nod_pt;
889 
890  // Add it to the list of nodes in the mesh
891  Node_pt.push_back(nod_pt);
892 
893  // Indicate the j'th node has been set up
894  done = true;
895  }
896  }
897  // On the right edge
898  else if ((j + 1) % nnode_1d == 0)
899  {
900  // Copy the data from the top edge of element 0 to element 2
901  el2_pt->node_pt(j) =
902  el0_pt->node_pt((corner_2 - 1) + (j + 1) / nnode_1d);
903 
904  // We don't need to set up the global coordinate data so just
905  // skip to the next node in the element
906  continue;
907  }
908  // On the left edge
909  else if (j % nnode_1d == 0)
910  {
911  // If the left edge has already been set up then we already know the
912  // nodes along this edge
913  if (edge1_setup)
914  {
915  // The j'th node along this edge is the (j/nnode_1d)'th node in the
916  // vector
917  el2_pt->node_pt(j) = edge1_vector_pt[j / nnode_1d];
918 
919  // Since the node has already been set up we do not need to sort
920  // out its global coordinate data
921  continue;
922  }
923  // If the edge hasn't been set up yet
924  else
925  {
926  if (q2_left_boundary_id > 0)
927  {
928  // Construct a boundary node
929  Node* nod_pt =
930  el2_pt->construct_boundary_node(j, time_stepper_pt);
931 
932  // Add it to the list of boundary nodes
933  add_boundary_node(q2_left_boundary_id - 1, nod_pt);
934 
935  // Add the node into the vector of nodes on edge 1 in clockwise
936  // order
937  edge1_vector_pt[(nnode_edge - 1) - (j / nnode_1d)] = nod_pt;
938 
939  // Add it to the list of nodes in the mesh
940  Node_pt.push_back(nod_pt);
941 
942  // Indicate that the j'th node has been set up
943  done = true;
944  }
945  }
946 
947  // Node is not on a mesh boundary but on the left edge
948  if (!done)
949  {
950  // Construct a normal node
951  Node* nod_pt = el2_pt->construct_node(j, time_stepper_pt);
952 
953  // Add the node into the vector of nodes on edge 1 in clockwise
954  // order
955  edge1_vector_pt[(nnode_edge - 1) - (j / nnode_1d)] = nod_pt;
956 
957  // Add it to the list of nodes in the mesh
958  Node_pt.push_back(nod_pt);
959 
960  // Indicate the j'th node has been set up
961  done = true;
962  }
963  }
964 
965  // Node is not on a mesh boundary
966  if (!done)
967  {
968  // Construct a normal node
969  Node* nod_pt = el2_pt->construct_node(j, time_stepper_pt);
970 
971  // Add it to the list of nodes in the mesh
972  Node_pt.push_back(nod_pt);
973  }
974 
975  // Get local coordinate
976  el2_pt->local_coordinate_of_node(j, s);
977 
978  // Interpolate position linearly between vertex nodes
979  dummy_element.interpolated_x(s, x);
980  el2_pt->node_pt(j)->x(0) = x[0];
981  el2_pt->node_pt(j)->x(1) = x[1];
982  }
983 
984  // We now need to loop over nodes corner_2 to (corner_3-1) and copy the
985  // given information from Q1. We do not need to set up the (corner_3)'th
986  // node since it coincides with the centroid which has already been set up
987  for (unsigned j = corner_2; j < corner_3; j++)
988  {
989  // The nodes along the upper edge of Q2 go from corner_2 to corner_3-1
990  // while the nodes along the right edge of Q1 go from corner_1 to
991  // (corner_3-nnode_1d) in increments of nnode_1d
992  el2_pt->node_pt(j) =
993  el1_pt->node_pt(corner_1 + (j - corner_2) * nnode_1d);
994  }
995 
996  // Add the element pointers to Element_pt and then increment the counter
997  Element_pt[new_el_count] = el0_pt;
998  Element_pt[new_el_count + 1] = el1_pt;
999  Element_pt[new_el_count + 2] = el2_pt;
1000  new_el_count += 3;
1001 
1002  // Assign the edges to the edge map
1003  edge_nodes_map[edge0] = edge0_vector_pt;
1004  edge_nodes_map[edge1] = edge1_vector_pt;
1005  edge_nodes_map[edge2] = edge2_vector_pt;
1006  }
1007 
1008  // Indicate that the look up scheme has been set up
1010 
1011  // Clean the dummy element nodes
1012  for (unsigned j = 0; j < 4; j++)
1013  {
1014  // Delete the j-th dummy element node
1015  delete dummy_element.node_pt(j);
1016 
1017  // Make it a null pointer
1018  dummy_element.node_pt(j) = 0;
1019  }
1020  }
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Edge class.
Definition: mesh.h:2692
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
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
Vector< Vector< FiniteElement * > > Boundary_element_pt
Definition: mesh.h:91
bool Lookup_for_elements_next_boundary_is_setup
Definition: mesh.h:87
FiniteElement * finite_element_pt(const unsigned &e) const
Definition: mesh.h:473
Vector< Vector< int > > Face_index_at_boundary
Definition: mesh.h:95
void set_nboundary(const unsigned &nbound)
Set the number of boundaries in the mesh.
Definition: mesh.h:505
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
Definition: mesh.h:186
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:590
Definition: nodes.h:906
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
virtual void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Definition: nodes.h:1365
unsigned edge_boundary(const unsigned &e, const unsigned &i) const
Definition: triangle_scaffold_mesh.h:89
Scalar * y
Definition: level1_cplx_impl.h:128
RealScalar s
Definition: level1_cplx_impl.h:130
char char char int int * k
Definition: level2_impl.h:374
list x
Definition: plotDoE.py:28
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References e(), oomph::TriangleScaffoldMesh::edge_boundary(), oomph::Mesh::finite_element_pt(), oomph::Node::get_boundaries_pt(), j, k, oomph::Mesh::nboundary(), oomph::Mesh::nelement(), oomph::FiniteElement::node_pt(), s, plotDoE::x, oomph::Node::x(), and y.

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

◆ operator=()

template<class ELEMENT >
void oomph::QuadFromTriangleMesh< ELEMENT >::operator= ( const QuadFromTriangleMesh< ELEMENT > &  )
delete

Broken assignment operator.

Member Data Documentation

◆ Time_stepper_pt

template<class ELEMENT >
TimeStepper* oomph::QuadFromTriangleMesh< ELEMENT >::Time_stepper_pt

Timestepper used to build elements.

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

◆ Use_attributes

template<class ELEMENT >
bool oomph::QuadFromTriangleMesh< ELEMENT >::Use_attributes

Boolean flag to indicate whether to use attributes or not (required for multidomain meshes)

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


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