26 #ifndef OOMPH_TUBE_MESH_TEMPLATE_CC
27 #define OOMPH_TUBE_MESH_TEMPLATE_CC
39 template<
class ELEMENT>
44 const unsigned& nlayer,
46 : Volume_pt(volume_pt)
49 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(3);
53 volume_pt, centreline_limits, theta_positions, radius_box, nlayer);
62 unsigned nelem = 5 * nlayer;
66 ELEMENT* dummy_el_pt =
new ELEMENT;
69 unsigned n_p = dummy_el_pt->nnode_1d();
75 unsigned nnodes_total =
76 (n_p * n_p + 4 * (n_p - 1) * (n_p - 1)) * (1 + nlayer * (n_p - 1));
86 for (
unsigned ielem = 0; ielem < nelem; ielem++)
92 for (
unsigned i2 = 0; i2 < n_p; i2++)
95 for (
unsigned i1 = 0; i1 < n_p; i1++)
98 for (
unsigned i0 = 0; i0 < n_p; i0++)
101 unsigned jnod_local = i0 + i1 * n_p + i2 * n_p * n_p;
105 jnod_local, time_stepper_pt);
108 s[0] = -1.0 + 2.0 * double(i0) / double(n_p - 1);
109 s[1] = -1.0 + 2.0 * double(i1) / double(n_p - 1);
110 s[2] = -1.0 + 2.0 * double(i2) / double(n_p - 1);
122 unsigned node_count = 0;
125 double node_kill_tol = 1.0e-12;
134 for (
unsigned ielem = 0; ielem < nelem; ielem++)
137 unsigned ilayer = unsigned(ielem / 5);
147 for (
unsigned i2 = 0; i2 < n_p; i2++)
150 for (
unsigned i1 = 0; i1 < n_p; i1++)
153 for (
unsigned i0 = 0; i0 < n_p; i0++)
156 unsigned jnod_local = i0 + i1 * n_p + i2 * n_p * n_p;
163 if ((i2 == 0) && (ilayer > 0))
166 unsigned ielem_neigh = ielem - 5;
169 unsigned i0_neigh = i0;
170 unsigned i1_neigh = i1;
171 unsigned i2_neigh = n_p - 1;
172 unsigned jnod_local_neigh =
173 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
176 for (
unsigned i = 0;
i < 3;
i++)
178 double error = std::fabs(
183 if (error > node_kill_tol)
185 oomph_info <<
"Error in node killing for i " <<
i <<
" "
186 << error << std::endl;
209 if ((i2 == 0) && (ilayer == 0))
216 if ((i2 == n_p - 1) && (ilayer == nlayer - 1))
238 for (
unsigned i2 = 0; i2 < n_p; i2++)
241 for (
unsigned i1 = 0; i1 < n_p; i1++)
244 for (
unsigned i0 = 0; i0 < n_p; i0++)
247 unsigned jnod_local = i0 + i1 * n_p + i2 * n_p * n_p;
254 if ((i2 == 0) && (ilayer > 0))
257 unsigned ielem_neigh = ielem - 5;
260 unsigned i0_neigh = i0;
261 unsigned i1_neigh = i1;
262 unsigned i2_neigh = n_p - 1;
263 unsigned jnod_local_neigh =
264 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
268 for (
unsigned i = 0;
i < 3;
i++)
270 double error = std::fabs(
275 if (error > node_kill_tol)
277 oomph_info <<
"Error in node killing for i " <<
i <<
" "
278 << error << std::endl;
298 unsigned ielem_neigh = ielem - 1;
301 unsigned i0_neigh = i0;
302 unsigned i1_neigh = 0;
303 unsigned i2_neigh = i2;
304 unsigned jnod_local_neigh =
305 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
308 for (
unsigned i = 0;
i < 3;
i++)
310 double error = std::fabs(
315 if (error > node_kill_tol)
317 oomph_info <<
"Error in node killing for i " <<
i <<
" "
318 << error << std::endl;
342 if ((i2 == 0) && (ilayer == 0))
349 if ((i2 == n_p - 1) && (ilayer == nlayer - 1))
362 zeta[0] = centreline_limits[0] +
363 (double(ilayer) + double(i2) / double(n_p - 1)) *
364 (centreline_limits[1] - centreline_limits[0]) /
368 zeta[1] = theta_positions[0] +
369 double(i1) / double(n_p - 1) * 0.5 *
370 (theta_positions[1] - theta_positions[0]);
372 Node_pt[node_count]->set_coordinates_on_boundary(1, zeta);
389 for (
unsigned i2 = 0; i2 < n_p; i2++)
392 for (
unsigned i1 = 0; i1 < n_p; i1++)
395 for (
unsigned i0 = 0; i0 < n_p; i0++)
398 unsigned jnod_local = i0 + i1 * n_p + i2 * n_p * n_p;
405 if ((i2 == 0) && (ilayer > 0))
408 unsigned ielem_neigh = ielem - 5;
411 unsigned i0_neigh = i0;
412 unsigned i1_neigh = i1;
413 unsigned i2_neigh = n_p - 1;
414 unsigned jnod_local_neigh =
415 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
418 for (
unsigned i = 0;
i < 3;
i++)
420 double error = std::fabs(
425 if (error > node_kill_tol)
427 oomph_info <<
"Error in node killing for i " <<
i <<
" "
428 << error << std::endl;
448 unsigned ielem_neigh = ielem - 1;
451 unsigned i0_neigh = n_p - 1;
452 unsigned i1_neigh = n_p - 1 - i0;
453 unsigned i2_neigh = i2;
454 unsigned jnod_local_neigh =
455 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
458 for (
unsigned i = 0;
i < 3;
i++)
460 double error = std::fabs(
465 if (error > node_kill_tol)
467 oomph_info <<
"Error in node killing for i " <<
i <<
" "
468 << error << std::endl;
484 if ((i0 == 0) && (i1 != 0))
487 unsigned ielem_neigh = ielem - 2;
490 unsigned i0_neigh = n_p - 1;
491 unsigned i1_neigh = i1;
492 unsigned i2_neigh = i2;
493 unsigned jnod_local_neigh =
494 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
497 for (
unsigned i = 0;
i < 3;
i++)
499 double error = std::fabs(
504 if (error > node_kill_tol)
506 oomph_info <<
"Error in node killing for i " <<
i <<
" "
507 << error << std::endl;
530 if ((i2 == 0) && (ilayer == 0))
537 if ((i2 == n_p - 1) && (ilayer == nlayer - 1))
551 centreline_limits[0] +
552 (double(ilayer) + double(i2) / double(n_p - 1)) *
553 (centreline_limits[1] - centreline_limits[0]) /
557 zeta[1] = theta_positions[1] +
558 double(i1) / double(n_p - 1) * 0.5 *
559 (theta_positions[2] - theta_positions[1]);
561 Node_pt[node_count]->set_coordinates_on_boundary(1, zeta);
579 for (
unsigned i2 = 0; i2 < n_p; i2++)
582 for (
unsigned i1 = 0; i1 < n_p; i1++)
585 for (
unsigned i0 = 0; i0 < n_p; i0++)
588 unsigned jnod_local = i0 + i1 * n_p + i2 * n_p * n_p;
595 if ((i2 == 0) && (ilayer > 0))
598 unsigned ielem_neigh = ielem - 5;
601 unsigned i0_neigh = i0;
602 unsigned i1_neigh = i1;
603 unsigned i2_neigh = n_p - 1;
604 unsigned jnod_local_neigh =
605 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
608 for (
unsigned i = 0;
i < 3;
i++)
610 double error = std::fabs(
615 if (error > node_kill_tol)
617 oomph_info <<
"Error in node killing for i " <<
i <<
" "
618 << error << std::endl;
638 unsigned ielem_neigh = ielem - 1;
641 unsigned i0_neigh = i1;
642 unsigned i1_neigh = n_p - 1;
643 unsigned i2_neigh = i2;
644 unsigned jnod_local_neigh =
645 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
648 for (
unsigned i = 0;
i < 3;
i++)
650 double error = std::fabs(
655 if (error > node_kill_tol)
657 oomph_info <<
"Error in node killing for i " <<
i <<
" "
658 << error << std::endl;
673 if ((i1 == 0) && (i0 != n_p - 1))
676 unsigned ielem_neigh = ielem - 3;
679 unsigned i0_neigh = i0;
680 unsigned i1_neigh = n_p - 1;
681 unsigned i2_neigh = i2;
682 unsigned jnod_local_neigh =
683 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
686 for (
unsigned i = 0;
i < 3;
i++)
688 double error = std::fabs(
693 if (error > node_kill_tol)
695 oomph_info <<
"Error in node killing for i " <<
i <<
" "
696 << error << std::endl;
719 if ((i2 == 0) && (ilayer == 0))
726 if ((i2 == n_p - 1) && (ilayer == nlayer - 1))
740 centreline_limits[0] +
741 (double(ilayer) + double(i2) / double(n_p - 1)) *
742 (centreline_limits[1] - centreline_limits[0]) /
746 zeta[1] = theta_positions[3] +
747 double(i0) / double(n_p - 1) * 0.5 *
748 (theta_positions[2] - theta_positions[3]);
750 Node_pt[node_count]->set_coordinates_on_boundary(1, zeta);
768 for (
unsigned i2 = 0; i2 < n_p; i2++)
771 for (
unsigned i1 = 0; i1 < n_p; i1++)
774 for (
unsigned i0 = 0; i0 < n_p; i0++)
777 unsigned jnod_local = i0 + i1 * n_p + i2 * n_p * n_p;
784 if ((i2 == 0) && (ilayer > 0))
787 unsigned ielem_neigh = ielem - 5;
790 unsigned i0_neigh = i0;
791 unsigned i1_neigh = i1;
792 unsigned i2_neigh = n_p - 1;
793 unsigned jnod_local_neigh =
794 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
797 for (
unsigned i = 0;
i < 3;
i++)
799 double error = std::fabs(
804 if (error > node_kill_tol)
806 oomph_info <<
"Error in node killing for i " <<
i <<
" "
807 << error << std::endl;
827 unsigned ielem_neigh = ielem - 1;
830 unsigned i0_neigh = 0;
831 unsigned i1_neigh = n_p - 1 - i0;
832 unsigned i2_neigh = i2;
833 unsigned jnod_local_neigh =
834 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
837 for (
unsigned i = 0;
i < 3;
i++)
839 double error = std::fabs(
844 if (error > node_kill_tol)
846 oomph_info <<
"Error in node killing for i " <<
i <<
" "
847 << error << std::endl;
862 if ((i0 == n_p - 1) && (i1 != n_p - 1))
865 unsigned ielem_neigh = ielem - 4;
868 unsigned i0_neigh = 0;
869 unsigned i1_neigh = i1;
870 unsigned i2_neigh = i2;
871 unsigned jnod_local_neigh =
872 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
875 for (
unsigned i = 0;
i < 3;
i++)
877 double error = std::fabs(
882 if (error > node_kill_tol)
884 oomph_info <<
"Error in node killing for i " <<
i <<
" "
885 << error << std::endl;
900 if ((i1 == 0) && (i0 != n_p - 1))
903 unsigned ielem_neigh = ielem - 3;
906 unsigned i0_neigh = 0;
907 unsigned i1_neigh = i0;
908 unsigned i2_neigh = i2;
909 unsigned jnod_local_neigh =
910 i0_neigh + i1_neigh * n_p + i2_neigh * n_p * n_p;
913 for (
unsigned i = 0;
i < 3;
i++)
915 double error = std::fabs(
920 if (error > node_kill_tol)
922 oomph_info <<
"Error in node killing for i " <<
i <<
" "
923 << error << std::endl;
947 if ((i2 == 0) && (ilayer == 0))
954 if ((i2 == n_p - 1) && (ilayer == nlayer - 1))
968 centreline_limits[0] +
969 (double(ilayer) + double(i2) / double(n_p - 1)) *
970 (centreline_limits[1] - centreline_limits[0]) /
975 theta_positions[0] + 2.0 * pi +
976 double(i1) / double(n_p - 1) * 0.5 *
977 (theta_positions[3] - theta_positions[0] + 2.0 * pi);
979 Node_pt[node_count]->set_coordinates_on_boundary(1, zeta);
996 std::ostringstream error_stream;
997 error_stream <<
"Error in killing nodes\n"
998 <<
"The most probable cause is that the domain is not\n"
999 <<
"compatible with the mesh.\n"
1000 <<
"For the TubeMesh, the domain must be\n"
1001 <<
"topologically consistent with a quarter tube with a\n"
1002 <<
"non-curved centreline.\n";
1004 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
void setup_boundary_element_info()
Setup lookup schemes which establish whic elements are located next to mesh's boundaries (wrapper to ...
MacroElement * macro_element_pt(const unsigned &i)
Access to i-th macro element.
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
/////////////////////////////////////////////////////////////////////
void macro_map(const Vector< double > &s, Vector< double > &r)
The mapping from local to global coordinates at the current time : r(s)
void add_boundary_node(const unsigned &b, Node *const &node_pt)
Add a (pointer to) a node to the b-th boundary.
Vector< Node * > Node_pt
Vector of pointers to nodes.
std::vector< bool > Boundary_coordinate_exists
Vector of boolean data that indicates whether the boundary coordinates have been set for the boundary...
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
void set_nboundary(const unsigned &nbound)
Set the number of boundaries in the mesh.
void convert_to_boundary_node(Node *&node_pt, const Vector< FiniteElement * > &finite_element_pt)
A function that upgrades an ordinary node to a boundary node We shouldn't ever really use this,...
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
An OomphLibError object which should be thrown when an run-time error is encountered....
////////////////////////////////////////////////////////////////////// //////////////////////////////...
Tube as a domain. The entire domain must be defined by a GeomObject with the following convention: ze...
GeomObject *& volume_pt()
Access function to GeomObject representing wall.
TubeMesh(GeomObject *wall_pt, const Vector< double > ¢reline_limits, const Vector< double > &theta_positions, const Vector< double > &radius_box, const unsigned &nlayer, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to geometric object that specifies the volume, start and end coordinates fo...
TubeDomain * Domain_pt
Pointer to domain.
const double Pi
50 digits from maple
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...