rectangular_quadmesh.template.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-2025 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#ifndef OOMPH_RECTANGULAR_QUADMESH_TEMPLATE_HEADER
27#define OOMPH_RECTANGULAR_QUADMESH_TEMPLATE_HEADER
28
29#ifndef OOMPH_RECTANGULAR_QUADMESH_HEADER
30#error __FILE__ should only be included from rectangular_quadmesh.h.
31#endif // OOMPH_RECTANGULAR_QUADMESH_HEADER
32
33// OOMPH-LIB Headers
34
35namespace oomph
36{
37 //===========================================================================
38 /// Generic mesh construction. This function contains the "guts" of the
39 /// mesh generation process, including all the tedious loops, counting
40 /// and spacing functions. The function should be called in all constuctors
41 /// of any derived classes.
42 //===========================================================================
43 template<class ELEMENT>
45 {
46 // Mesh can only be built with 2D Qelements.
47 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
48
49 // Set the number of boundaries
50 set_nboundary(4);
51
52 // Allocate the store for the elements
53 Element_pt.resize(Nx * Ny);
54 // Allocate the memory for the first element
55 Element_pt[0] = new ELEMENT;
56
57 // Read out the number of linear points in the element
58 Np = dynamic_cast<ELEMENT*>(finite_element_pt(0))->nnode_1d();
59
60 // Can now allocate the store for the nodes
61 Node_pt.resize((1 + (Np - 1) * Nx) * (1 + (Np - 1) * Ny));
62
63 // Set up geometrical data
64 unsigned long node_count = 0;
65
66 // Now assign the topology
67 // Boundaries are numbered 0 1 2 3 from the bottom proceeding anticlockwise
68 // Pinned value are denoted by an integer value 1
69 // Thus if a node is on two boundaries, ORing the values of the
70 // boundary conditions will give the most restrictive case (pinning)
71
72 // FIRST ELEMENT (lower left corner)
73
74 // Set the corner node
75 // Allocate memory for the node
77 finite_element_pt(0)->construct_boundary_node(0, time_stepper_pt);
78
79 // Set the position of the node
80 Node_pt[node_count]->x(0) = x_spacing_function(0, 0, 0, 0);
81 Node_pt[node_count]->x(1) = y_spacing_function(0, 0, 0, 0);
82
83 // Push the node back onto boundaries
84 add_boundary_node(0, Node_pt[node_count]);
85 add_boundary_node(3, Node_pt[node_count]);
86
87 // Increment the node number
88 node_count++;
89
90 // Loop over the other nodes in the first row
91 for (unsigned l2 = 1; l2 < Np; l2++)
92 {
93 // Allocate memory for the nodes
95 finite_element_pt(0)->construct_boundary_node(l2, time_stepper_pt);
96
97 // Set the position of the node
98 Node_pt[node_count]->x(0) = x_spacing_function(0, l2, 0, 0);
99 Node_pt[node_count]->x(1) = y_spacing_function(0, l2, 0, 0);
100
101 // Push the node back onto boundaries
102 add_boundary_node(0, Node_pt[node_count]);
103
104 // If we only have one column then the RHS node is on the right boundary
105 if ((Nx == 1) && (l2 == (Np - 1)))
106 {
107 add_boundary_node(1, Node_pt[node_count]);
108 }
109
110 // Increment the node number
111 node_count++;
112 }
113
114 // Loop over the other node columns
115 for (unsigned l1 = 1; l1 < Np; l1++)
116 {
117 // Allocate memory for the nodes
119 finite_element_pt(0)->construct_boundary_node(l1 * Np, time_stepper_pt);
120
121 // Set the position of the node
122 Node_pt[node_count]->x(0) = x_spacing_function(0, 0, 0, l1);
123 Node_pt[node_count]->x(1) = y_spacing_function(0, 0, 0, l1);
124
125 // Push the node back onto boundaries
126 add_boundary_node(3, Node_pt[node_count]);
127
128 // If we only have one row, then the top node is on the top boundary
129 if ((Ny == 1) && (l1 == (Np - 1)))
130 {
131 add_boundary_node(2, Node_pt[node_count]);
132 }
133
134 // Increment the node number
135 node_count++;
136
137 // Loop over the other nodes in the row
138 for (unsigned l2 = 1; l2 < Np; l2++)
139 {
140 // Allocate the memory for the node
141 // If it lies on a boundary make a boundary node
142 if (((Nx == 1) && (l2 == (Np - 1))) || ((Ny == 1) && (l1 == (Np - 1))))
143 {
144 Node_pt[node_count] = finite_element_pt(0)->construct_boundary_node(
145 l1 * Np + l2, time_stepper_pt);
146 }
147 // Otherwise its a normal node
148 else
149 {
151 finite_element_pt(0)->construct_node(l1 * Np + l2, time_stepper_pt);
152 }
153
154 // Set the position of the node
155 Node_pt[node_count]->x(0) = x_spacing_function(0, l2, 0, l1);
156 Node_pt[node_count]->x(1) = y_spacing_function(0, l2, 0, l1);
157
158 // If we only have one column then the RHS node is on the right boundary
159 if ((Nx == 1) && l2 == (Np - 1))
160 {
161 add_boundary_node(1, Node_pt[node_count]);
162 }
163 // If we only have one row, then the top node is on the top boundary
164 if ((Ny == 1) && (l1 == (Np - 1)))
165 {
166 add_boundary_node(2, Node_pt[node_count]);
167 }
168
169 // Increment the node number
170 node_count++;
171 }
172 }
173 // END OF FIRST ELEMENT
174
175 // CENTRE OF FIRST ROW OF ELEMENTS
176 // Now loop over the first row of elements, apart from final element
177 for (unsigned j = 1; j < (Nx - 1); j++)
178 {
179 // Allocate memory for new element
180 Element_pt[j] = new ELEMENT;
181 // Do first row of nodes
182 // First column of nodes is same as neighbouring element
183 finite_element_pt(j)->node_pt(0) =
184 finite_element_pt(j - 1)->node_pt((Np - 1));
185 // New nodes for other columns
186 for (unsigned l2 = 1; l2 < Np; l2++)
187 {
188 // Allocate memory for the nodes
190 finite_element_pt(j)->construct_boundary_node(l2, time_stepper_pt);
191
192 // Set the position of the node
193 Node_pt[node_count]->x(0) = x_spacing_function(j, l2, 0, 0);
194 Node_pt[node_count]->x(1) = y_spacing_function(j, l2, 0, 0);
195
196 // Push the node back onto boundaries
197 add_boundary_node(0, Node_pt[node_count]);
198
199 // Increment the node number
200 node_count++;
201 }
202
203 // Do the rest of the nodes
204 for (unsigned l1 = 1; l1 < Np; l1++)
205 {
206 // First column of nodes is same as neighbouring element
207 finite_element_pt(j)->node_pt(l1 * Np) =
208 finite_element_pt(j - 1)->node_pt(l1 * Np + (Np - 1));
209 // New nodes for other columns
210 for (unsigned l2 = 1; l2 < Np; l2++)
211 {
212 // Allocate memory for the nodes
213 // If we only have one row, this node could be on the boundary
214 if ((Ny == 1) && (l1 == (Np - 1)))
215 {
216 Node_pt[node_count] = finite_element_pt(j)->construct_boundary_node(
217 l1 * Np + l2, time_stepper_pt);
218 }
219 // Otherwise create a normal node
220 else
221 {
222 Node_pt[node_count] = finite_element_pt(j)->construct_node(
223 l1 * Np + l2, time_stepper_pt);
224 }
225
226 // Set the position of the node
227 Node_pt[node_count]->x(0) = x_spacing_function(j, l2, 0, l1);
228 Node_pt[node_count]->x(1) = y_spacing_function(j, l2, 0, l1);
229
230 // If we only have one row, then the top node is on the top boundary
231 if ((Ny == 1) && (l1 == (Np - 1)))
232 {
233 add_boundary_node(2, Node_pt[node_count]);
234 }
235
236 // Increment the node number
237 node_count++;
238 }
239 }
240 }
241 // END OF CENTRE OF FIRST ROW OF ELEMENTS
242
243 // FINAL ELEMENT IN FIRST ROW (lower right corner)
244 // Only allocate if there is more than one element in the row
245 if (Nx > 1)
246 {
247 // Allocate memory for element
248 Element_pt[Nx - 1] = new ELEMENT;
249
250 // First column of nodes is same as neighbouring element
251 finite_element_pt(Nx - 1)->node_pt(0) =
252 finite_element_pt(Nx - 2)->node_pt(Np - 1);
253
254 // New middle nodes
255 for (unsigned l2 = 1; l2 < (Np - 1); l2++)
256 {
257 // Allocate memory for node
259 finite_element_pt(Nx - 1)->construct_boundary_node(l2,
261
262 // Set the position of the node
263 Node_pt[node_count]->x(0) = x_spacing_function(Nx - 1, l2, 0, 0);
264 Node_pt[node_count]->x(1) = y_spacing_function(Nx - 1, l2, 0, 0);
265
266 // Push the node back onto boundaries
267 add_boundary_node(0, Node_pt[node_count]);
268
269 // Increment the node number
270 node_count++;
271 }
272
273 // Allocate memory for a new boundary node
274 Node_pt[node_count] = finite_element_pt(Nx - 1)->construct_boundary_node(
275 Np - 1, time_stepper_pt);
276
277 // If required make it periodic from the node on the other side
278 if (Xperiodic == true)
279 {
280 Node_pt[node_count]->make_periodic(finite_element_pt(0)->node_pt(0));
281 }
282
283 // Set the position of the node
284 Node_pt[node_count]->x(0) = x_spacing_function(Nx - 1, Np - 1, 0, 0);
285 Node_pt[node_count]->x(1) = y_spacing_function(Nx - 1, Np - 1, 0, 0);
286
287 // Push the node back onto boundaries
288 add_boundary_node(0, Node_pt[node_count]);
289 add_boundary_node(1, Node_pt[node_count]);
290
291 // Increment the node number
292 node_count++;
293
294 // Do the rest of the nodes
295 for (unsigned l1 = 1; l1 < Np; l1++)
296 {
297 // First column of nodes is same as neighbouring element
298 finite_element_pt(Nx - 1)->node_pt(l1 * Np) =
299 finite_element_pt(Nx - 2)->node_pt(l1 * Np + (Np - 1));
300
301 // New node for middle column
302 for (unsigned l2 = 1; l2 < (Np - 1); l2++)
303 {
304 // Allocate memory for node
305 // If it lies on the boundary, create a boundary node
306 if ((Ny == 1) && (l1 == (Np - 1)))
307 {
309 finite_element_pt(Nx - 1)->construct_boundary_node(
310 l1 * Np + l2, time_stepper_pt);
311 }
312 // Otherwise create a normal node
313 else
314 {
315 Node_pt[node_count] = finite_element_pt(Nx - 1)->construct_node(
316 l1 * Np + l2, time_stepper_pt);
317 }
318
319 // Set the position of the node
320 Node_pt[node_count]->x(0) = x_spacing_function(Nx - 1, l2, 0, l1);
321 Node_pt[node_count]->x(1) = y_spacing_function(Nx - 1, l2, 0, l1);
322
323 // If we only have one row, then the top node is on the top boundary
324 if ((Ny == 1) && (l1 == (Np - 1)))
325 {
326 add_boundary_node(2, Node_pt[node_count]);
327 }
328
329 // Increment the node number
330 node_count++;
331 }
332
333 // Allocate memory for a new boundary node
335 finite_element_pt(Nx - 1)->construct_boundary_node(l1 * Np + (Np - 1),
337
338 // If required make it periodic from the corresponding node on the other
339 // side
340 if (Xperiodic == true)
341 {
343 finite_element_pt(0)->node_pt(l1 * Np));
344 }
345
346 // Set the position of the node
347 Node_pt[node_count]->x(0) = x_spacing_function(Nx - 1, Np - 1, 0, l1);
348 Node_pt[node_count]->x(1) = y_spacing_function(Nx - 1, Np - 1, 0, l1);
349
350 // Push the node back onto boundaries
351 add_boundary_node(1, Node_pt[node_count]);
352
353 // If we only have one row, then the top node is on the top boundary
354 if ((Ny == 1) && (l1 == (Np - 1)))
355 {
356 add_boundary_node(2, Node_pt[node_count]);
357 }
358
359 // Increment the node number
360 node_count++;
361 }
362 }
363 // END OF FIRST ROW OF ELEMENTS
364
365 // ALL CENTRAL ELEMENT ROWS
366 // Loop over remaining element rows
367 for (unsigned i = 1; i < (Ny - 1); i++)
368 {
369 // Set the first element in the row
370 // Allocate memory for element
371 Element_pt[Nx * i] = new ELEMENT;
372
373 // The first row of nodes is copied from the element below
374 for (unsigned l2 = 0; l2 < Np; l2++)
375 {
376 finite_element_pt(Nx * i)->node_pt(l2) =
377 finite_element_pt(Nx * (i - 1))->node_pt((Np - 1) * Np + l2);
378 }
379
380 // Other rows are new nodes
381 for (unsigned l1 = 1; l1 < Np; l1++)
382 {
383 // First column of nodes
384 // Allocate memory for node
386 finite_element_pt(Nx * i)->construct_boundary_node(l1 * Np,
388
389 // Set the position of the node
390 Node_pt[node_count]->x(0) = x_spacing_function(0, 0, i, l1);
391 Node_pt[node_count]->x(1) = y_spacing_function(0, 0, i, l1);
392
393 // Push the node back onto boundaries
394 add_boundary_node(3, Node_pt[node_count]);
395
396 // Increment the node number
397 node_count++;
398
399 // Now do the other columns
400 for (unsigned l2 = 1; l2 < Np; l2++)
401 {
402 // Allocate memory for node
403 // If we only have one column, the node could be on the boundary
404 if ((Nx == 1) && (l2 == (Np - 1)))
405 {
407 finite_element_pt(Nx * i)->construct_boundary_node(
408 l1 * Np + l2, time_stepper_pt);
409 }
410 else
411 {
412 Node_pt[node_count] = finite_element_pt(Nx * i)->construct_node(
413 l1 * Np + l2, time_stepper_pt);
414 }
415
416 // Set the position of the node
417 Node_pt[node_count]->x(0) = x_spacing_function(0, l2, i, l1);
418 Node_pt[node_count]->x(1) = y_spacing_function(0, l2, i, l1);
419
420 // If we only have one column then the RHS node is on the
421 // right boundary
422 if ((Nx == 1) && (l2 == (Np - 1)))
423 {
424 add_boundary_node(1, Node_pt[node_count]);
425 }
426
427 // Increment the node number
428 node_count++;
429 }
430 }
431
432 // Now loop over the rest of the elements in the row, apart from the last
433 for (unsigned j = 1; j < (Nx - 1); j++)
434 {
435 // Allocate memory for new element
436 Element_pt[Nx * i + j] = new ELEMENT;
437 // The first row is copied from the lower element
438 for (unsigned l2 = 0; l2 < Np; l2++)
439 {
440 finite_element_pt(Nx * i + j)->node_pt(l2) =
441 finite_element_pt(Nx * (i - 1) + j)->node_pt((Np - 1) * Np + l2);
442 }
443
444 for (unsigned l1 = 1; l1 < Np; l1++)
445 {
446 // First column is same as neighbouring element
447 finite_element_pt(Nx * i + j)->node_pt(l1 * Np) =
448 finite_element_pt(Nx * i + (j - 1))->node_pt(l1 * Np + (Np - 1));
449 // New nodes for other columns
450 for (unsigned l2 = 1; l2 < Np; l2++)
451 {
452 // Allocate memory for the nodes
454 finite_element_pt(Nx * i + j)
455 ->construct_node(l1 * Np + l2, time_stepper_pt);
456
457 // Set the position of the node
458 Node_pt[node_count]->x(0) = x_spacing_function(j, l2, i, l1);
459 Node_pt[node_count]->x(1) = y_spacing_function(j, l2, i, l1);
460
461 // Increment the node number
462 node_count++;
463 }
464 }
465 } // End of loop over elements in row
466
467 // Do final element in row
468 // Only if there is more than one column
469 if (Nx > 1)
470 {
471 // Allocate memory for element
472 Element_pt[Nx * i + Nx - 1] = new ELEMENT;
473 // The first row is copied from the lower element
474 for (unsigned l2 = 0; l2 < Np; l2++)
475 {
476 finite_element_pt(Nx * i + Nx - 1)->node_pt(l2) =
477 finite_element_pt(Nx * (i - 1) + Nx - 1)
478 ->node_pt((Np - 1) * Np + l2);
479 }
480
481 for (unsigned l1 = 1; l1 < Np; l1++)
482 {
483 // First column is same as neighbouring element
484 finite_element_pt(Nx * i + Nx - 1)->node_pt(l1 * Np) =
485 finite_element_pt(Nx * i + Nx - 2)->node_pt(l1 * Np + (Np - 1));
486
487 // Middle nodes
488 for (unsigned l2 = 1; l2 < (Np - 1); l2++)
489 {
490 // Allocate memory for node
492 finite_element_pt(Nx * i + Nx - 1)
493 ->construct_node(l1 * Np + l2, time_stepper_pt);
494
495 // Set the position of the node
496 Node_pt[node_count]->x(0) = x_spacing_function(Nx - 1, l2, i, l1);
497 Node_pt[node_count]->x(1) = y_spacing_function(Nx - 1, l2, i, l1);
498
499 // Increment the node number
500 node_count++;
501 }
502
503 // Allocate memory for a new boundary node
505 finite_element_pt(Nx * i + Nx - 1)
506 ->construct_boundary_node(l1 * Np + (Np - 1), time_stepper_pt);
507
508 // If required make it periodic from the corresponding node on
509 // the other side
510 if (Xperiodic == true)
511 {
513 finite_element_pt(Nx * i)->node_pt(l1 * Np));
514 }
515
516 // Set the position of the node
517 Node_pt[node_count]->x(0) = x_spacing_function(Nx - 1, Np - 1, i, l1);
518 Node_pt[node_count]->x(1) = y_spacing_function(Nx - 1, Np - 1, i, l1);
519
520 // Push the node back onto boundaries
521 add_boundary_node(1, Node_pt[node_count]);
522
523 // Increment the node number
524 node_count++;
525 } // End of loop over rows of nodes in the element
526 } // End of if more than one column
527 } // End of loop over rows of elements
528
529 // END OF LOOP OVER CENTRAL ELEMENT ROWS
530
531 // FINAL ELEMENT ROW
532 // ONLY NECESSARY IF THERE IS MORE THAN ONE ROW
533 if (Ny > 1)
534 {
535 // FIRST ELEMENT IN UPPER ROW (upper left corner)
536 // Allocate memory for element
537 Element_pt[Nx * (Ny - 1)] = new ELEMENT;
538 // The first row of nodes is copied from the element below
539 for (unsigned l2 = 0; l2 < Np; l2++)
540 {
541 finite_element_pt(Nx * (Ny - 1))->node_pt(l2) =
542 finite_element_pt(Nx * (Ny - 2))->node_pt((Np - 1) * Np + l2);
543 }
544
545 // Second row of nodes
546 // First column of nodes
547 for (unsigned l1 = 1; l1 < (Np - 1); l1++)
548 {
549 // Allocate memory for node
551 finite_element_pt(Nx * (Ny - 1))
552 ->construct_boundary_node(Np * l1, time_stepper_pt);
553
554 // Set the position of the node
555 Node_pt[node_count]->x(0) = x_spacing_function(0, 0, Ny - 1, l1);
556 Node_pt[node_count]->x(1) = y_spacing_function(0, 0, Ny - 1, l1);
557
558 // Push the node back onto boundaries
559 add_boundary_node(3, Node_pt[node_count]);
560
561 // Increment the node number
562 node_count++;
563
564 // Now do the other columns
565 for (unsigned l2 = 1; l2 < Np; l2++)
566 {
567 // Allocate memory for node
568 if ((Nx == 1) && (l2 == Np - 1))
569 {
571 finite_element_pt(Nx * (Ny - 1))
572 ->construct_boundary_node(Np * l1 + l2, time_stepper_pt);
573 }
574 else
575 {
577 finite_element_pt(Nx * (Ny - 1))
578 ->construct_node(Np * l1 + l2, time_stepper_pt);
579 }
580
581 // Set the position of the node
582 Node_pt[node_count]->x(0) = x_spacing_function(0, l2, Ny - 1, l1);
583 Node_pt[node_count]->x(1) = y_spacing_function(0, l2, Ny - 1, l1);
584
585 // Push the node back onto boundaries
586 if ((Nx == 1) && (l2 == Np - 1))
587 {
588 add_boundary_node(1, Node_pt[node_count]);
589 }
590
591 // Increment the node number
592 node_count++;
593 }
594 }
595
596 // Final row of nodes
597 // First column of nodes
598 // Top left node
599 // Allocate memory for node
601 finite_element_pt(Nx * (Ny - 1))
602 ->construct_boundary_node(Np * (Np - 1), time_stepper_pt);
603
604 // Set the position of the node
605 Node_pt[node_count]->x(0) = x_spacing_function(0, 0, Ny - 1, Np - 1);
606 Node_pt[node_count]->x(1) = y_spacing_function(0, 0, Ny - 1, Np - 1);
607
608 // Push the node back onto boundaries
609 add_boundary_node(2, Node_pt[node_count]);
610 add_boundary_node(3, Node_pt[node_count]);
611
612 // Increment the node number
613 node_count++;
614
615 // Now do the other columns
616 for (unsigned l2 = 1; l2 < Np; l2++)
617 {
618 // Allocate memory for the node
620 finite_element_pt(Nx * (Ny - 1))
621 ->construct_boundary_node(Np * (Np - 1) + l2, time_stepper_pt);
622
623 // Set the position of the node
624 Node_pt[node_count]->x(0) = x_spacing_function(0, l2, Ny - 1, Np - 1);
625 Node_pt[node_count]->x(1) = y_spacing_function(0, l2, Ny - 1, Np - 1);
626
627 // Push the node back onto boundaries
628 add_boundary_node(2, Node_pt[node_count]);
629
630 // Push the node back onto boundaries
631 if ((Nx == 1) && (l2 == Np - 1))
632 {
633 add_boundary_node(1, Node_pt[node_count]);
634 }
635
636 // Increment the node number
637 node_count++;
638 }
639
640 // Now loop over the rest of the elements in the row, apart from the last
641 for (unsigned j = 1; j < (Nx - 1); j++)
642 {
643 // Allocate memory for element
644 Element_pt[Nx * (Ny - 1) + j] = new ELEMENT;
645 // The first row is copied from the lower element
646 for (unsigned l2 = 0; l2 < Np; l2++)
647 {
648 finite_element_pt(Nx * (Ny - 1) + j)->node_pt(l2) =
649 finite_element_pt(Nx * (Ny - 2) + j)->node_pt((Np - 1) * Np + l2);
650 }
651
652 // Second rows
653 for (unsigned l1 = 1; l1 < (Np - 1); l1++)
654 {
655 // First column is same as neighbouring element
656 finite_element_pt(Nx * (Ny - 1) + j)->node_pt(Np * l1) =
657 finite_element_pt(Nx * (Ny - 1) + (j - 1))
658 ->node_pt(Np * l1 + (Np - 1));
659
660 // New nodes for other columns
661 for (unsigned l2 = 1; l2 < Np; l2++)
662 {
663 // Allocate memory for the node
665 finite_element_pt(Nx * (Ny - 1) + j)
666 ->construct_node(Np * l1 + l2, time_stepper_pt);
667
668 // Set the position of the node
669 Node_pt[node_count]->x(0) = x_spacing_function(j, l2, Ny - 1, l1);
670 Node_pt[node_count]->x(1) = y_spacing_function(j, l2, Ny - 1, l1);
671
672 // Increment the node number
673 node_count++;
674 }
675 }
676
677 // Top row
678 // First column is same as neighbouring element
679 finite_element_pt(Nx * (Ny - 1) + j)->node_pt(Np * (Np - 1)) =
680 finite_element_pt(Nx * (Ny - 1) + (j - 1))
681 ->node_pt(Np * (Np - 1) + (Np - 1));
682 // New nodes for other columns
683 for (unsigned l2 = 1; l2 < Np; l2++)
684 {
685 // Allocate memory for node
687 finite_element_pt(Nx * (Ny - 1) + j)
688 ->construct_boundary_node(Np * (Np - 1) + l2, time_stepper_pt);
689
690 // Set the position of the node
691 Node_pt[node_count]->x(0) = x_spacing_function(j, l2, Ny - 1, Np - 1);
692 Node_pt[node_count]->x(1) = y_spacing_function(j, l2, Ny - 1, Np - 1);
693
694 // Push the node back onto boundaries
695 add_boundary_node(2, Node_pt[node_count]);
696
697 // Increment the node number
698 node_count++;
699 }
700 } // End of loop over central elements in row
701
702 // FINAL ELEMENT IN ROW (upper right corner)
703 // Only if there is more than one column
704 if (Nx > 1)
705 {
706 // Allocate memory for element
707 Element_pt[Nx * (Ny - 1) + Nx - 1] = new ELEMENT;
708 // The first row is copied from the lower element
709 for (unsigned l2 = 0; l2 < Np; l2++)
710 {
711 finite_element_pt(Nx * (Ny - 1) + Nx - 1)->node_pt(l2) =
712 finite_element_pt(Nx * (Ny - 2) + Nx - 1)
713 ->node_pt((Np - 1) * Np + l2);
714 }
715
716 // Second rows
717 for (unsigned l1 = 1; l1 < (Np - 1); l1++)
718 {
719 // First column is same as neighbouring element
720 finite_element_pt(Nx * (Ny - 1) + Nx - 1)->node_pt(Np * l1) =
721 finite_element_pt(Nx * (Ny - 1) + Nx - 2)
722 ->node_pt(Np * l1 + (Np - 1));
723
724 // Middle nodes
725 for (unsigned l2 = 1; l2 < (Np - 1); l2++)
726 {
727 // Allocate memory for node
729 finite_element_pt(Nx * (Ny - 1) + Nx - 1)
730 ->construct_node(Np * l1 + l2, time_stepper_pt);
731
732 // Set the position of the node
733 Node_pt[node_count]->x(0) =
734 x_spacing_function(Nx - 1, l2, Ny - 1, l1);
735 Node_pt[node_count]->x(1) =
736 y_spacing_function(Nx - 1, l2, Ny - 1, l1);
737
738 // Increment the node number
739 node_count++;
740 }
741
742 // Final node
743 // Allocate new memory for a boundary node
745 finite_element_pt(Nx * (Ny - 1) + Nx - 1)
746 ->construct_boundary_node(Np * l1 + (Np - 1), time_stepper_pt);
747
748 // If required make it periodic
749 if (Xperiodic == true)
750 {
752 finite_element_pt(Nx * (Ny - 1))->node_pt(Np * l1));
753 }
754
755 // Set the position of the node
756 Node_pt[node_count]->x(0) =
757 x_spacing_function(Nx - 1, Np - 1, Ny - 1, l1);
758 Node_pt[node_count]->x(1) =
759 y_spacing_function(Nx - 1, Np - 1, Ny - 1, l1);
760
761 // Push the node back onto boundaries
762 add_boundary_node(1, Node_pt[node_count]);
763
764 // Increment the node number
765 node_count++;
766
767 } // End of loop over middle rows
768
769 // Final row
770 // First column is same as neighbouring element
771 finite_element_pt(Nx * (Ny - 1) + Nx - 1)->node_pt(Np * (Np - 1)) =
772 finite_element_pt(Nx * (Ny - 1) + Nx - 2)
773 ->node_pt(Np * (Np - 1) + (Np - 1));
774
775 // Middle nodes
776 for (unsigned l2 = 1; l2 < (Np - 1); l2++)
777 {
778 // Allocate memory for node
780 finite_element_pt(Nx * (Ny - 1) + Nx - 1)
781 ->construct_boundary_node(Np * (Np - 1) + l2, time_stepper_pt);
782
783 // Set the position of the node
784 Node_pt[node_count]->x(0) =
785 x_spacing_function(Nx - 1, l2, Ny - 1, Np - 1);
786 Node_pt[node_count]->x(1) =
787 y_spacing_function(Nx - 1, l2, Ny - 1, Np - 1);
788
789 // Push the node back onto boundaries
790 add_boundary_node(2, Node_pt[node_count]);
791
792 // Increment the node number
793 node_count++;
794 }
795
796 // Final node
797 // Allocate new memory for a periodic node
798 Node_pt[node_count] = finite_element_pt(Nx * (Ny - 1) + Nx - 1)
799 ->construct_boundary_node(
800 Np * (Np - 1) + (Np - 1), time_stepper_pt);
801
802 // If required make it periodic
803 if (Xperiodic == true)
804 {
806 finite_element_pt(Nx * (Ny - 1))->node_pt(Np * (Np - 1)));
807 }
808
809 // Set the position of the node
810 Node_pt[node_count]->x(0) =
811 x_spacing_function(Nx - 1, Np - 1, Ny - 1, Np - 1);
812 Node_pt[node_count]->x(1) =
813 y_spacing_function(Nx - 1, Np - 1, Ny - 1, Np - 1);
814
815 // Push the node back onto boundaries
816 add_boundary_node(1, Node_pt[node_count]);
817 add_boundary_node(2, Node_pt[node_count]);
818
819 // Increment the node number
820 node_count++;
821 }
822 // END OF FINAL ELEMENT IN MESH
823 }
824
825 // Setup boundary element lookup schemes
826 setup_boundary_element_info();
827 }
828
829 //============================================================================
830 /// Reorder the elements so they are listed in vertical slices
831 /// (more efficient during the frontal solution if the domain
832 /// is long in the x-direction.
833 //============================================================================
834 template<class ELEMENT>
836 {
837 // Find out how many elements there are
838 unsigned long Nelement = nelement();
839 // Create a dummy array of elements
841
842 // Loop over the elements in horizontal order
843 for (unsigned long j = 0; j < Nx; j++)
844 {
845 // Loop over the elements vertically
846 for (unsigned long i = 0; i < Ny; i++)
847 {
848 // Push back onto the new stack
849 dummy.push_back(finite_element_pt(Nx * i + j));
850 }
851 }
852
853 // Now copy the reordered elements into the element_pt
854 for (unsigned long e = 0; e < Nelement; e++)
855 {
856 Element_pt[e] = dummy[e];
857 }
858 }
859
860} // namespace oomph
861#endif
e
Definition cfortran.h:571
cstr elem_len * i
Definition cfortran.h:603
Node ** Node_pt
Storage for pointers to the nodes in the element.
Definition elements.h:1323
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
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:2222
TimeStepper *& time_stepper_pt()
Access function for pointer to time stepper: Null if object is not time-dependent.
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition nodes.h:1060
void resize(const unsigned &n_value)
Resize the number of equations.
Definition nodes.cc:2167
virtual void make_periodic(Node *const &node_pt)
Make the node periodic by copying the values from node_pt. Note that the coordinates will always rema...
Definition nodes.cc:2257
virtual void element_reorder()
Reorder the elements: By default they are ordered in "horizontal" layers (increasing in x,...
void build_mesh(TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Generic mesh construction function: contains all the hard work.
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).