geompack_scaffold_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 #include "geompack_scaffold_mesh.h"
27 
28 namespace oomph
29 {
30  //=====================================================================
31  /// Constructor: Pass the filename of the mesh files
32  //=====================================================================
34  const std::string& mesh_file_name, const std::string& curve_file_name)
35  {
36  // Read the output mesh file to find informations about the nodes
37  // and elements of the mesh
38 
39  // Process mesh file
40  //---------------------
41  std::ifstream mesh_file(mesh_file_name.c_str(), std::ios_base::in);
42 
43  // Number of nodes
44  unsigned n_node;
45  mesh_file >> n_node;
46 
47  // Coordinates of nodes and extra information index
48  Vector<double> x_node(n_node);
49  Vector<double> y_node(n_node);
50  Vector<int> vertinfo(n_node);
51  for (unsigned i = 0; i < n_node; i++)
52  {
53  mesh_file >> x_node[i];
54  mesh_file >> y_node[i];
55  mesh_file >> vertinfo[i];
56  }
57 
58  // Extra information (nodes lying on a curve)
59  unsigned n_vx;
60  mesh_file >> n_vx;
61 
62  // Dummy storage for the node code
63  int dummy_node_code;
64 
65  // Storage for the curve indice
66  Vector<int> icurv(n_vx); // it's negative if not used
67 
68  // Dummy storage for the location of the point on the curve
69  double dummy_ucurv;
70 
71  for (unsigned i = 0; i < n_vx; i++)
72  {
73  mesh_file >> dummy_node_code;
74  mesh_file >> icurv[i];
75  mesh_file >> dummy_ucurv;
76  }
77 
78  // Number of local nodes per element
79  unsigned n_local_node;
80  mesh_file >> n_local_node;
81 
82  // Number of elements
83  unsigned n_element;
84  mesh_file >> n_element;
85 
86  // Storage for global node numbers for all elements
87  Vector<unsigned> global_node(n_local_node * n_element);
88 
89  // Storage for edge information
90  // (needed for a possible construction of midside node
91  // in the following build from scaffold function)
92  Vector<int> edgeinfo(n_local_node * n_element);
93 
94  // Initialize counter
95  unsigned k = 0;
96 
97  // Read global node numbers for all elements
98  for (unsigned i = 0; i < n_element; i++)
99  {
100  for (unsigned j = 0; j < n_local_node; j++)
101  {
102  mesh_file >> global_node[k];
103  k++;
104  }
105  }
106 
107  // Initialize counter
108  unsigned l = 0;
109 
110  // Read the edge information
111  for (unsigned i = 0; i < n_element; i++)
112  {
113  for (unsigned j = 0; j < n_local_node; j++)
114  {
115  mesh_file >> edgeinfo[l];
116  l++;
117  }
118  }
119 
120  mesh_file.close();
121 
122  // Create a vector of boolean so as not to create the same node twice
123  std::vector<bool> done(n_node);
124  for (unsigned i = 0; i < n_node; i++)
125  {
126  done[i] = false;
127  }
128 
129  // Resize the Node vector
130  Node_pt.resize(n_node, 0);
131 
132  // Resize the Element vector
133  Element_pt.resize(n_element);
134 
135 
136  // Process curve file to extract information about boundaries
137  // ----------------------------------------------------------
138 
139  // Important: the input file must NOT have NURBS curve
140  std::ifstream curve_file(curve_file_name.c_str(), std::ios_base::in);
141 
142  // Number of curves
143  unsigned n_curv;
144  curve_file >> n_curv;
145 
146  // Storage of several information for each curve
147  Vector<Vector<int>> curv;
148 
149  // Resize to n_curv rows
150  curv.resize(n_curv);
151 
152  // Curve type
153  unsigned type;
154 
155  // Loop over the curves to extract information
156  for (unsigned i = 0; i < n_curv; i++)
157  {
158  curve_file >> type;
159  if (type == 1)
160  {
161  curv[i].resize(4);
162  curv[i][0] = type;
163  for (unsigned j = 1; j < 4; j++)
164  {
165  curve_file >> curv[i][j];
166  }
167  }
168  else if (type == 2)
169  {
170  curv[i].resize(5);
171  curv[i][0] = type;
172  for (unsigned j = 1; j < 5; j++)
173  {
174  curve_file >> curv[i][j];
175  }
176  }
177  else
178  {
179  std::ostringstream error_stream;
180  error_stream << "Current we can only process curves of\n"
181  << "type 1 (straight lines) and 2 (circular arcs\n"
182  << "You've specified: type " << type << std::endl;
183 
184  throw OomphLibError(
185  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
186  }
187  }
188 
189  curve_file.close();
190 
191  // Searching the number of boundaries
192  int d = 0;
193  for (unsigned i = 0; i < n_curv; i++)
194  {
195  if (d < curv[i][1])
196  {
197  d = curv[i][1]; // the boundary code is the 2nd value of each curve
198  }
199  }
200  oomph_info << "The number of boundaries is " << d << std::endl;
201 
202  // Set number of boundaries
203  if (d > 0)
204  {
205  set_nboundary(d);
206  }
207 
208  // Search the boundary number of node located on a boundary
209  // If after this, boundary_of_node[j][0] is -1 then node j
210  // is not located on any boundary.
211  // If boundary_of_node[j][0] is positive, the node is located
212  // on the boundary indicated by that number.
213  // If boundary_of_node[j][1] is also positive, the node is also
214  // located on that boundary. Note: We're ignoring the (remote)
215  // possibility that node is located on 3 or more boundaries
216  // as one of them would have to be an internal boundary which
217  // would be odd...
218  Vector<Vector<int>> boundary_of_node;
219  boundary_of_node.resize(n_node);
220  unsigned n;
221  for (unsigned i = 0; i < n_node; i++)
222  {
223  n = 0;
224  boundary_of_node[i].resize(2);
225  boundary_of_node[i][0] = -1;
226  boundary_of_node[i][1] = -1;
227  if (vertinfo[i] == 2) // it's an endpoint
228  {
229  for (unsigned j = 0; j < n_curv; j++)
230  {
231  for (unsigned m = 2; m < curv[j].size(); m++)
232  {
233  if (curv[j][m] ==
234  static_cast<int>(i + 1)) // node number begins at 1
235  { // in the mesh file !!!
236  boundary_of_node[i][n] = curv[j][1];
237  n++;
238  }
239  }
240  }
241  }
242  if (vertinfo[i] > 20)
243  {
244  int a = 0;
245  a = (vertinfo[i]) / 20;
246  int b;
247  b = icurv[a - 1]; // 1st value of vector at [0] !!
248  boundary_of_node[i][0] =
249  curv[b - 1][1]; // 1st value of vector at [0] !!
250  }
251  }
252 
253 
254  // Create the elements
255  //--------------------
256 
257  unsigned count = 0;
258  unsigned c;
259  for (unsigned e = 0; e < n_element; e++)
260  {
261  // Build simplex four node quad in the scaffold mesh
262  Element_pt[e] = new QElement<2, 2>;
263 
264  // Construction of the two first nodes of the element
265  for (unsigned j = 0; j < 2; j++)
266  {
267  c = global_node[count];
268  if (done[c - 1] == false) // c-1 because node number begins
269  // at 1 in the mesh file
270  {
271  // If the node is located on a boundary construct a boundary node
272  if ((d > 0) && ((boundary_of_node[c - 1][0] > 0) ||
273  (boundary_of_node[c - 1][1] > 0)))
274  {
275  // Construct a boundary node
277  // Add to the look=up schemes
278  if (boundary_of_node[c - 1][0] > 0)
279  {
280  add_boundary_node(boundary_of_node[c - 1][0] - 1, Node_pt[c - 1]);
281  }
282  if (boundary_of_node[c - 1][1] > 0)
283  {
284  add_boundary_node(boundary_of_node[c - 1][1] - 1, Node_pt[c - 1]);
285  }
286  }
287  // Otherwise construct a normal node
288  else
289  {
291  }
292  done[c - 1] = true;
293  Node_pt[c - 1]->x(0) = x_node[c - 1];
294  Node_pt[c - 1]->x(1) = y_node[c - 1];
295  }
296  else
297  {
298  finite_element_pt(e)->node_pt(j) = Node_pt[c - 1];
299  }
300  count++;
301  }
302 
303  // Construction of the third node not in anticlockwise order
304  c = global_node[count + 1];
305  if (done[c - 1] ==
306  false) // c-1 because node number begins at 1 in the mesh file
307  {
308  // If the node is on a boundary, construct a boundary node
309  if ((d > 0) && ((boundary_of_node[c - 1][0] > 0) ||
310  (boundary_of_node[c - 1][1] > 0)))
311  {
312  // Construct the node
314  // Add to the look-up schemes
315  if (boundary_of_node[c - 1][0] > 0)
316  {
317  add_boundary_node(boundary_of_node[c - 1][0] - 1, Node_pt[c - 1]);
318  }
319  if (boundary_of_node[c - 1][1] > 0)
320  {
321  add_boundary_node(boundary_of_node[c - 1][1] - 1, Node_pt[c - 1]);
322  }
323  }
324  // otherwise construct a normal node
325  else
326  {
328  }
329  done[c - 1] = true;
330  Node_pt[c - 1]->x(0) = x_node[c - 1];
331  Node_pt[c - 1]->x(1) = y_node[c - 1];
332  }
333  else
334  {
335  finite_element_pt(e)->node_pt(2) = Node_pt[c - 1];
336  }
337 
338  count++;
339 
340  // Construction of the fourth node
341  c = global_node[count - 1];
342  if (done[c - 1] ==
343  false) // c-1 because node number begins at 1 in the mesh file
344  {
345  // If the node is on a boundary, constuct a boundary node
346  if ((d > 0) && ((boundary_of_node[c - 1][0] > 0) ||
347  (boundary_of_node[c - 1][1] > 0)))
348  {
349  // Construct the boundary node
351  // Add to the look-up schemes
352  if (boundary_of_node[c - 1][0] > 0)
353  {
354  add_boundary_node(boundary_of_node[c - 1][0] - 1, Node_pt[c - 1]);
355  }
356  if (boundary_of_node[c - 1][1] > 0)
357  {
358  add_boundary_node(boundary_of_node[c - 1][1] - 1, Node_pt[c - 1]);
359  }
360  }
361  // Otherwise construct a normal node
362  else
363  {
365  }
366  done[c - 1] = true;
367  Node_pt[c - 1]->x(0) = x_node[c - 1];
368  Node_pt[c - 1]->x(1) = y_node[c - 1];
369  }
370  else
371  {
372  finite_element_pt(e)->node_pt(3) = Node_pt[c - 1];
373  }
374 
375  count++;
376  }
377  }
378 
379 } // namespace oomph
e
Definition: cfortran.h:571
cstr elem_len * i
Definition: cfortran.h:603
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object.
Definition: elements.h:2509
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
virtual Node * construct_boundary_node(const unsigned &n)
Construct the local node n as a boundary node; that is a node that MAY be placed on a mesh boundary a...
Definition: elements.h:2538
GeompackQuadScaffoldMesh()
Empty constructor.
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
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition: mesh.h:473
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
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.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...