line_mesh.cc
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2023 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 // oomph-lib headers
27 #include "map_matrix.h"
28 #include "line_mesh.h"
29 
30 namespace oomph
31 {
32  //=======================================================================
33  /// Set up lookup schemes which establish which elements are located
34  /// next to which boundaries (doc to outfile if it's open)
35  //=======================================================================
36  void LineMeshBase::setup_boundary_element_info(std::ostream& outfile)
37  {
38  // Initialise documentation flag
39  bool doc = false;
40 
41  // Set this to true if an open file has been passed to the function
42  if (outfile)
43  {
44  doc = true;
45  }
46 
47  // Determine number of boundaries in mesh
48  const unsigned n_bound = nboundary();
49 
50  // Wipe/allocate storage for arrays
51  Boundary_element_pt.clear();
52  Face_index_at_boundary.clear();
53  Boundary_element_pt.resize(n_bound);
54  Face_index_at_boundary.resize(n_bound);
55 
56  // Matrix map for working out the fixed local coord for elements on boundary
58 
59  // Determine number of elements in the mesh
60  const unsigned n_element = nelement();
61 
62  // Loop over elements
63  for (unsigned e = 0; e < n_element; e++)
64  {
65  // Get pointer to element
67 
68  // Output information to output file
69  if (doc)
70  {
71  outfile << "Element: " << e << " " << fe_pt << std::endl;
72  }
73 
74  // Only include 1D elements! Some meshes contain interface elements too.
75  if (fe_pt->dim() == 1)
76  {
77  // Loop over the element's nodes and find out which boundaries they're
78  // on
79  // ----------------------------------------------------------------------
80 
81  // Determine number of nodes in the element
82  const unsigned n_node = fe_pt->nnode_1d();
83 
84  // Loop over nodes in order
85  for (unsigned n = 0; n < n_node; n++)
86  {
87  // Allocate storage for pointer to set of boundaries that node lives
88  // on
89  std::set<unsigned>* boundaries_pt = 0;
90 
91  // Get pointer to vector of boundaries that this node lives on
92  fe_pt->node_pt(n)->get_boundaries_pt(boundaries_pt);
93 
94  // If the node lives on some boundaries....
95  if (boundaries_pt != 0)
96  {
97  // Determine number of boundaries which node lives on
98  const unsigned n_bound_node_lives_on = (*boundaries_pt).size();
99 
100  // Throw an error if the node lives on more than one boundary
101  if (n_bound_node_lives_on > 1)
102  {
103  std::string error_message =
104  "In a 1D mesh a node shouldn't be able to live on more than\n";
105  error_message += "one boundary, yet this node claims to.";
106 
107  throw OomphLibError(error_message,
108  OOMPH_CURRENT_FUNCTION,
109  OOMPH_EXCEPTION_LOCATION);
110  }
111  // If the node lives on just one boundary
112  else if (n_bound_node_lives_on == 1)
113  {
114  // Determine which boundary the node lives on
115  const std::set<unsigned>::iterator boundary =
116  boundaries_pt->begin();
117 
118  // In 1D if an element has any nodes on a boundary then it must
119  // be a boundary element. This means that (unlike in the 2D and
120  // 3D cases) we can immediately add this element to permanent
121  // storage.
122  Boundary_element_pt[*boundary].push_back(fe_pt);
123 
124  // Record information required for FaceElements.
125  // `Face_index_at_boundary' = -/+1 for nodes on the left/right
126  // boundary. This allows us to decide which edge of the element
127  // coincides with the boundary since the line element must have
128  // precisely one vertex node on the boundary.
129 
130  // Are we at the left-hand vertex node? (left face)
131  if (n == 0)
132  {
133  Face_index_at_boundary[*boundary].push_back(-1);
134  }
135 
136  // Are we at the right-hand vertex node? (right face)
137  else if (n == n_node - 1)
138  {
139  Face_index_at_boundary[*boundary].push_back(1);
140  }
141  }
142  } // End of if node lives on some boundaries
143 
144  } // End of loop over nodes
145  }
146  } // End of loop over elements
147 
148 #ifdef PARANOID
149 
150  // Check each boundary only has precisely one element next to it
151  // -------------------------------------------------------------
152  // Only if not distributed
153 #ifdef OOMPH_HAS_MPI
154  if (Comm_pt == 0)
155 #endif
156  {
157  // Loop over boundaries
158  for (unsigned b = 0; b < n_bound; b++)
159  {
160  // Evaluate number of elements adjacent to boundary b
161  const unsigned n_element = Boundary_element_pt[b].size();
162 
163  switch (n_element)
164  {
165  // Boundary b has no adjacent elements
166  case 0:
167  {
168  std::ostringstream error_stream;
169  error_stream << "Boundary " << b
170  << " has no element adjacent to it\n";
171  throw OomphLibError(error_stream.str(),
172  OOMPH_CURRENT_FUNCTION,
173  OOMPH_EXCEPTION_LOCATION);
174  break;
175  }
176  // Boundary b has one adjacent element (this is good!)
177  case 1:
178  break;
179 
180  // Boundary b has more than one adjacent element
181  default:
182  {
183  std::ostringstream error_stream;
184  error_stream << "Boundary " << b << " has " << n_element
185  << " elements adjacent to it.\n"
186  << "This shouldn't occur in a 1D mesh.\n";
187  throw OomphLibError(error_stream.str(),
188  OOMPH_CURRENT_FUNCTION,
189  OOMPH_EXCEPTION_LOCATION);
190  break;
191  }
192  } // End of switch
193 
194  // Because each boundary should only have one element adjacent to it,
195  // each `Face_index_at_boundary[b]' should be of size one.
196 
197  const unsigned face_index_at_boundary_size =
198  Face_index_at_boundary[b].size();
199 
200  if (face_index_at_boundary_size != 1)
201  {
202  std::ostringstream error_stream;
203  error_stream
204  << "Face_index_at_boundary[" << b << "] has size"
205  << face_index_at_boundary_size << " which does not make sense.\n"
206  << "In a 1D mesh its size should always be one since only\n"
207  << "one element can be adjacent to any particular boundary";
208  throw OomphLibError(error_stream.str(),
209  OOMPH_CURRENT_FUNCTION,
210  OOMPH_EXCEPTION_LOCATION);
211  }
212  } // End of loop over boundaries
213  }
214 #endif
215 
216  // Doc?
217  // ----
218  if (doc)
219  {
220  // Loop over boundaries
221  for (unsigned b = 0; b < n_bound; b++)
222  {
223  const unsigned n_element = Boundary_element_pt[b].size();
224  outfile << "Boundary: " << b << " is adjacent to " << n_element
225  << " elements" << std::endl;
226 
227  // Loop over elements on given boundary
228  for (unsigned e = 0; e < n_element; e++)
229  {
230  FiniteElement* fe_pt = Boundary_element_pt[b][e];
231  outfile << "Boundary element:" << fe_pt
232  << " Face index on boundary is "
233  << Face_index_at_boundary[b][e] << std::endl;
234  }
235  }
236  } // End of if(doc)
237 
238 
239  // Lookup scheme has now been set up
241 
242  } // End of setup_boundary_element_info()
243 
244 } // namespace oomph
e
Definition: cfortran.h:571
A general Finite Element class.
Definition: elements.h:1313
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition: elements.h:2611
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
Definition: elements.h:2218
void setup_boundary_element_info()
Set up lookup schemes which establish which elements are located next to mesh's boundaries (wrapper t...
Definition: line_mesh.h:70
MapMatrixMixed is a generalised, STL-map-based, sparse(ish) matrix class with mixed indices.
Definition: map_matrix.h:109
Vector< Vector< FiniteElement * > > Boundary_element_pt
Vector of Vector of pointers to elements on the boundaries: Boundary_element_pt(b,...
Definition: mesh.h:91
bool Lookup_for_elements_next_boundary_is_setup
Flag to indicate that the lookup schemes for elements that are adjacent to the boundaries has been se...
Definition: mesh.h:87
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition: mesh.h:473
Vector< Vector< int > > Face_index_at_boundary
For the e-th finite element on boundary b, this is the index of the face that lies along that boundar...
Definition: mesh.h:95
OomphCommunicator * Comm_pt
Pointer to communicator – set to NULL if mesh is not distributed.
Definition: mesh.h:119
unsigned nboundary() const
Return number of boundaries.
Definition: mesh.h:827
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:590
virtual void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Return a pointer to set of mesh boundaries that this node occupies; this will be overloaded by Bounda...
Definition: nodes.h:1365
An OomphLibError object which should be thrown when an run-time error is encountered....
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...