26 #ifndef OOMPH_TUBE_MESH_TEMPLATE_CC
27 #define OOMPH_TUBE_MESH_TEMPLATE_CC
39 template<
class ELEMENT>
41 const Vector<double>& centreline_limits,
42 const Vector<double>& theta_positions,
43 const Vector<double>& radius_box,
44 const unsigned& nlayer,
45 TimeStepper* time_stepper_pt)
46 : Volume_pt(volume_pt)
49 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(3);
53 volume_pt, centreline_limits, theta_positions, radius_box, nlayer);
59 Boundary_coordinate_exists[1] =
true;
62 unsigned nelem = 5 * nlayer;
63 Element_pt.resize(nelem);
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));
77 Node_pt.resize(nnodes_total);
83 Vector<double> zeta(2);
86 for (
unsigned ielem = 0; ielem < nelem; ielem++)
89 Element_pt[ielem] =
new ELEMENT;
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;
104 Node* node_pt = finite_element_pt(ielem)->construct_node(
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);
111 Domain_pt->macro_element_pt(ielem)->macro_map(s, r);
113 node_pt->x(0) = r[0];
114 node_pt->x(1) = r[1];
115 node_pt->x(2) = r[2];
122 unsigned node_count = 0;
125 double node_kill_tol = 1.0e-12;
131 const double pi = MathematicalConstants::Pi;
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(
179 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
180 finite_element_pt(ielem_neigh)
181 ->node_pt(jnod_local_neigh)
183 if (error > node_kill_tol)
185 oomph_info <<
"Error in node killing for i " << i <<
" "
186 << error << std::endl;
192 delete finite_element_pt(ielem)->node_pt(jnod_local);
196 finite_element_pt(ielem)->node_pt(jnod_local) =
197 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
203 Node_pt[node_count] =
204 finite_element_pt(ielem)->node_pt(jnod_local);
209 if ((i2 == 0) && (ilayer == 0))
211 this->convert_to_boundary_node(Node_pt[node_count]);
212 add_boundary_node(0, Node_pt[node_count]);
216 if ((i2 == n_p - 1) && (ilayer == nlayer - 1))
218 this->convert_to_boundary_node(Node_pt[node_count]);
219 add_boundary_node(2, Node_pt[node_count]);
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(
271 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
272 finite_element_pt(ielem_neigh)
273 ->node_pt(jnod_local_neigh)
275 if (error > node_kill_tol)
277 oomph_info <<
"Error in node killing for i " << i <<
" "
278 << error << std::endl;
284 delete finite_element_pt(ielem)->node_pt(jnod_local);
288 finite_element_pt(ielem)->node_pt(jnod_local) =
289 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
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(
311 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
312 finite_element_pt(ielem_neigh)
313 ->node_pt(jnod_local_neigh)
315 if (error > node_kill_tol)
317 oomph_info <<
"Error in node killing for i " << i <<
" "
318 << error << std::endl;
324 delete finite_element_pt(ielem)->node_pt(jnod_local);
328 finite_element_pt(ielem)->node_pt(jnod_local) =
329 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
336 Node_pt[node_count] =
337 finite_element_pt(ielem)->node_pt(jnod_local);
342 if ((i2 == 0) && (ilayer == 0))
344 this->convert_to_boundary_node(Node_pt[node_count]);
345 add_boundary_node(0, Node_pt[node_count]);
349 if ((i2 == n_p - 1) && (ilayer == nlayer - 1))
351 this->convert_to_boundary_node(Node_pt[node_count]);
352 add_boundary_node(2, Node_pt[node_count]);
358 this->convert_to_boundary_node(Node_pt[node_count]);
359 add_boundary_node(1, Node_pt[node_count]);
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(
421 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
422 finite_element_pt(ielem_neigh)
423 ->node_pt(jnod_local_neigh)
425 if (error > node_kill_tol)
427 oomph_info <<
"Error in node killing for i " << i <<
" "
428 << error << std::endl;
434 delete finite_element_pt(ielem)->node_pt(jnod_local);
438 finite_element_pt(ielem)->node_pt(jnod_local) =
439 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
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(
461 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
462 finite_element_pt(ielem_neigh)
463 ->node_pt(jnod_local_neigh)
465 if (error > node_kill_tol)
467 oomph_info <<
"Error in node killing for i " << i <<
" "
468 << error << std::endl;
474 delete finite_element_pt(ielem)->node_pt(jnod_local);
478 finite_element_pt(ielem)->node_pt(jnod_local) =
479 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
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(
500 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
501 finite_element_pt(ielem_neigh)
502 ->node_pt(jnod_local_neigh)
504 if (error > node_kill_tol)
506 oomph_info <<
"Error in node killing for i " << i <<
" "
507 << error << std::endl;
513 delete finite_element_pt(ielem)->node_pt(jnod_local);
517 finite_element_pt(ielem)->node_pt(jnod_local) =
518 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
524 Node_pt[node_count] =
525 finite_element_pt(ielem)->node_pt(jnod_local);
530 if ((i2 == 0) && (ilayer == 0))
532 this->convert_to_boundary_node(Node_pt[node_count]);
533 add_boundary_node(0, Node_pt[node_count]);
537 if ((i2 == n_p - 1) && (ilayer == nlayer - 1))
539 this->convert_to_boundary_node(Node_pt[node_count]);
540 add_boundary_node(2, Node_pt[node_count]);
546 this->convert_to_boundary_node(Node_pt[node_count]);
547 add_boundary_node(1, Node_pt[node_count]);
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(
611 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
612 finite_element_pt(ielem_neigh)
613 ->node_pt(jnod_local_neigh)
615 if (error > node_kill_tol)
617 oomph_info <<
"Error in node killing for i " << i <<
" "
618 << error << std::endl;
624 delete finite_element_pt(ielem)->node_pt(jnod_local);
628 finite_element_pt(ielem)->node_pt(jnod_local) =
629 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
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(
651 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
652 finite_element_pt(ielem_neigh)
653 ->node_pt(jnod_local_neigh)
655 if (error > node_kill_tol)
657 oomph_info <<
"Error in node killing for i " << i <<
" "
658 << error << std::endl;
664 delete finite_element_pt(ielem)->node_pt(jnod_local);
668 finite_element_pt(ielem)->node_pt(jnod_local) =
669 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
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(
689 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
690 finite_element_pt(ielem_neigh)
691 ->node_pt(jnod_local_neigh)
693 if (error > node_kill_tol)
695 oomph_info <<
"Error in node killing for i " << i <<
" "
696 << error << std::endl;
702 delete finite_element_pt(ielem)->node_pt(jnod_local);
706 finite_element_pt(ielem)->node_pt(jnod_local) =
707 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
713 Node_pt[node_count] =
714 finite_element_pt(ielem)->node_pt(jnod_local);
719 if ((i2 == 0) && (ilayer == 0))
721 this->convert_to_boundary_node(Node_pt[node_count]);
722 add_boundary_node(0, Node_pt[node_count]);
726 if ((i2 == n_p - 1) && (ilayer == nlayer - 1))
728 this->convert_to_boundary_node(Node_pt[node_count]);
729 add_boundary_node(2, Node_pt[node_count]);
735 this->convert_to_boundary_node(Node_pt[node_count]);
736 add_boundary_node(1, Node_pt[node_count]);
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(
800 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
801 finite_element_pt(ielem_neigh)
802 ->node_pt(jnod_local_neigh)
804 if (error > node_kill_tol)
806 oomph_info <<
"Error in node killing for i " << i <<
" "
807 << error << std::endl;
813 delete finite_element_pt(ielem)->node_pt(jnod_local);
817 finite_element_pt(ielem)->node_pt(jnod_local) =
818 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
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(
840 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
841 finite_element_pt(ielem_neigh)
842 ->node_pt(jnod_local_neigh)
844 if (error > node_kill_tol)
846 oomph_info <<
"Error in node killing for i " << i <<
" "
847 << error << std::endl;
853 delete finite_element_pt(ielem)->node_pt(jnod_local);
857 finite_element_pt(ielem)->node_pt(jnod_local) =
858 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
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(
878 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
879 finite_element_pt(ielem_neigh)
880 ->node_pt(jnod_local_neigh)
882 if (error > node_kill_tol)
884 oomph_info <<
"Error in node killing for i " << i <<
" "
885 << error << std::endl;
891 delete finite_element_pt(ielem)->node_pt(jnod_local);
895 finite_element_pt(ielem)->node_pt(jnod_local) =
896 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
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(
916 finite_element_pt(ielem)->node_pt(jnod_local)->x(i) -
917 finite_element_pt(ielem_neigh)
918 ->node_pt(jnod_local_neigh)
920 if (error > node_kill_tol)
922 oomph_info <<
"Error in node killing for i " << i <<
" "
923 << error << std::endl;
929 delete finite_element_pt(ielem)->node_pt(jnod_local);
933 finite_element_pt(ielem)->node_pt(jnod_local) =
934 finite_element_pt(ielem_neigh)->node_pt(jnod_local_neigh);
941 Node_pt[node_count] =
942 finite_element_pt(ielem)->node_pt(jnod_local);
947 if ((i2 == 0) && (ilayer == 0))
949 this->convert_to_boundary_node(Node_pt[node_count]);
950 add_boundary_node(0, Node_pt[node_count]);
954 if ((i2 == n_p - 1) && (ilayer == nlayer - 1))
956 this->convert_to_boundary_node(Node_pt[node_count]);
957 add_boundary_node(2, Node_pt[node_count]);
963 this->convert_to_boundary_node(Node_pt[node_count]);
964 add_boundary_node(1, Node_pt[node_count]);
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";
1003 throw OomphLibError(
1004 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1008 setup_boundary_element_info();
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.
////////////////////////////////////////////////////////////////////// //////////////////////////////...