27 #ifndef OOMPH_CHANNEL_WITH_LEAFLET_MESH_TEMPLATE_CC
28 #define OOMPH_CHANNEL_WITH_LEAFLET_MESH_TEMPLATE_CC
47 template<
class ELEMENT>
49 GeomObject* leaflet_pt,
52 const double& hleaflet,
54 const unsigned& nleft,
55 const unsigned& nright,
58 TimeStepper* time_stepper_pt)
60 nright + nleft, ny1 + ny2, lright + lleft, htot, time_stepper_pt)
63 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
71 leaflet_pt, lleft, lright, hleaflet, htot, nleft, nright, ny1, ny2);
75 unsigned nmacro = (ny1 + ny2) * (nleft + nright);
78 for (
unsigned e = 0; e < nmacro; e++)
81 FiniteElement* el_pt = this->finite_element_pt(e);
84 el_pt->set_macro_elem_pt(this->
Domain_pt->macro_element_pt(e));
92 this->set_nboundary(7);
95 this->remove_boundary_nodes(0);
98 unsigned nnode_1d = this->finite_element_pt(0)->nnode_1d();
101 for (
unsigned e = 0; e < nleft; e++)
103 for (
unsigned i = 0; i < nnode_1d; i++)
105 Node* nod_pt = this->finite_element_pt(e)->node_pt(i);
107 if (e != nleft - 1 || i != 2)
109 this->add_boundary_node(0, nod_pt);
114 for (
unsigned e = nleft; e < nleft + nright; e++)
116 for (
unsigned i = 0; i < nnode_1d; i++)
118 Node* nod_pt = this->finite_element_pt(e)->node_pt(i);
119 this->add_boundary_node(6, nod_pt);
124 Vector<double> zeta(1);
127 for (
unsigned k = 0; k < ny1; k++)
129 unsigned e = (nleft + nright) * k + nleft - 1;
130 for (
unsigned i = 0; i < nnode_1d; i++)
133 this->finite_element_pt(e)->node_pt((i + 1) * nnode_1d - 1);
134 this->convert_to_boundary_node(nod_pt);
135 this->add_boundary_node(4, nod_pt);
138 zeta[0] = double(k) * hleaflet / double(ny1) +
139 double(i) * hleaflet / double(ny1) / double(nnode_1d - 1);
140 nod_pt->set_coordinates_on_boundary(4, zeta);
157 unsigned e = nleft - 1;
165 for (
unsigned i = 0; i < nnode_1d; i++)
167 nod_pt = this->finite_element_pt(e)->construct_boundary_node(
168 (i + 1) * nnode_1d - 1, time_stepper_pt);
169 this->add_boundary_node(5, nod_pt);
172 this->add_boundary_node(0, nod_pt);
174 this->add_node_pt(nod_pt);
176 zeta[0] = i * hleaflet / double(ny1) / double(nnode_1d - 1);
177 nod_pt->set_coordinates_on_boundary(5, zeta);
182 for (
unsigned k = 1; k < ny1; k++)
184 e = (nleft + nright) * k + nleft - 1;
187 this->finite_element_pt(e)->node_pt(nnode_1d - 1) = nod_pt;
188 this->add_boundary_node(5, nod_pt);
190 zeta[0] = k * hleaflet / double(ny1);
191 nod_pt->set_coordinates_on_boundary(5, zeta);
194 for (
unsigned i = 1; i < nnode_1d; i++)
197 if ((k == ny1 - 1) && (i == nnode_1d - 1))
200 nod_pt = this->finite_element_pt(e)->node_pt(nnode_1d * nnode_1d - 1);
205 nod_pt = this->finite_element_pt(e)->construct_boundary_node(
206 (i + 1) * nnode_1d - 1, time_stepper_pt);
207 this->add_node_pt(nod_pt);
211 this->add_boundary_node(5, nod_pt);
213 zeta[0] = double(k) * hleaflet / double(ny1) +
214 double(i) * hleaflet / double(ny1) / double(nnode_1d - 1);
215 nod_pt->set_coordinates_on_boundary(5, zeta);
223 this->setup_boundary_element_info();
226 this->Boundary_coordinate_exists[4] =
true;
227 this->Boundary_coordinate_exists[5] =
true;
241 template<
class ELEMENT>
245 double hleaflet = this->domain_pt()->hleaflet();
246 double htot = this->domain_pt()->htot();
247 double lleft = this->domain_pt()->lleft();
248 double lright = this->domain_pt()->lright();
251 unsigned nnod = this->nnode();
252 for (
unsigned j = 0; j < nnod; j++)
255 AlgebraicNode* nod_pt = node_pt(j);
258 double x = nod_pt->x(0);
259 double y = nod_pt->x(1);
263 Vector<double> zeta(1);
266 this->Leaflet_pt->position(zeta, r);
267 if ((r[0] != X_0) || (r[1] != hleaflet))
269 std::ostringstream error_stream;
270 error_stream <<
"Wall must be in its undeformed position when\n"
271 <<
"algebraic node update information is set up!\n "
272 << r[0] <<
" " << X_0 <<
" " << r[1] <<
" " << hleaflet
275 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
280 Vector<double> ref_value(4);
283 if ((x <= X_0) && (y <= hleaflet))
290 Vector<double> zeta(1);
292 ref_value[3] = zeta[0];
295 GeomObject* geom_obj_pt;
297 this->Leaflet_pt->locate_zeta(zeta, geom_obj_pt, s);
300 Vector<GeomObject*> geom_object_pt(1);
301 geom_object_pt[0] = geom_obj_pt;
309 ref_value[2] = (lleft + x - X_0) / lleft;
314 nod_pt->add_node_update_info(1,
320 if ((x >= X_0) && (y <= hleaflet))
327 Vector<double> zeta(1);
329 ref_value[3] = zeta[0];
332 GeomObject* geom_obj_pt;
334 this->Leaflet_pt->locate_zeta(zeta, geom_obj_pt, s);
337 Vector<GeomObject*> geom_object_pt(1);
338 geom_object_pt[0] = geom_obj_pt;
346 ref_value[2] = (x - X_0) / lright;
350 nod_pt->add_node_update_info(2,
356 if ((x <= X_0) && (y >= hleaflet))
362 ref_value[1] = (y - hleaflet) / (htot - hleaflet);
366 ref_value[2] = (lleft + x - X_0) / lleft;
369 Vector<GeomObject*> geom_object_pt(1);
370 geom_object_pt[0] = this->Leaflet_pt;
374 nod_pt->add_node_update_info(3,
380 if ((x >= X_0) && (y >= hleaflet))
386 ref_value[1] = (y - hleaflet) / (htot - hleaflet);
390 ref_value[2] = (x - X_0) / lright;
393 Vector<GeomObject*> geom_object_pt(1);
394 geom_object_pt[0] = this->Leaflet_pt;
398 nod_pt->add_node_update_info(4,
411 template<
class ELEMENT>
413 const unsigned& t, AlgebraicNode*& node_pt)
415 unsigned id = node_pt->node_update_fct_id();
420 node_update_I(t, node_pt);
424 node_update_II(t, node_pt);
428 node_update_III(t, node_pt);
432 node_update_IV(t, node_pt);
436 std::ostringstream error_message;
437 error_message <<
"The node update fct id is " <<
id
438 <<
", but it should only be one of " << 1 <<
", " << 2
439 <<
", " << 3 <<
" or " << 4 << std::endl;
440 std::string function_name =
441 "AlgebraicChannelWithLeafletMesh::algebraic_node_update()";
443 throw OomphLibError(error_message.str(),
444 OOMPH_CURRENT_FUNCTION,
445 OOMPH_EXCEPTION_LOCATION);
454 template<
class ELEMENT>
456 const unsigned& t, AlgebraicNode*& node_pt)
459 double lleft = this->domain_pt()->lleft();
462 Vector<double> ref_value(node_pt->vector_ref_value());
465 Vector<GeomObject*> geom_object_pt(node_pt->vector_geom_object_pt());
468 GeomObject* leaflet_pt = geom_object_pt[0];
472 double y0 = ref_value[0];
473 double x0 = -lleft + X_0;
481 Vector<double> r_wall(2);
482 leaflet_pt->position(t, s, r_wall);
487 double r = ref_value[2];
491 node_pt->x(t, 0) = x0 + r * (r_wall[0] - x0);
492 node_pt->x(t, 1) = y0 + r * (r_wall[1] - y0);
499 template<
class ELEMENT>
501 const unsigned& t, AlgebraicNode*& node_pt)
504 double lright = this->domain_pt()->lright();
507 Vector<double> ref_value(node_pt->vector_ref_value());
510 Vector<GeomObject*> geom_object_pt(node_pt->vector_geom_object_pt());
513 GeomObject* leaflet_pt = geom_object_pt[0];
517 double y0 = ref_value[0];
518 double x0 = X_0 + lright;
525 Vector<double> r_wall(2);
526 leaflet_pt->position(t, s, r_wall);
530 double r = ref_value[2];
533 node_pt->x(t, 0) = r_wall[0] + r * (x0 - r_wall[0]);
534 node_pt->x(t, 1) = r_wall[1] + r * (y0 - r_wall[1]);
541 template<
class ELEMENT>
543 const unsigned& t,
const Vector<double>& zeta, Vector<double>& r)
547 double htot = this->domain_pt()->htot();
549 Vector<double> xi(1);
552 Vector<double> r_join(2);
554 this->Leaflet_pt->position(t, xi, r_join);
556 r[0] = r_join[0] + zeta[0] * (X_0 - r_join[0]);
557 r[1] = r_join[1] + zeta[0] * (htot - r_join[1]);
563 template<
class ELEMENT>
565 const unsigned& t, AlgebraicNode*& node_pt)
568 double lleft = this->domain_pt()->lleft();
571 Vector<double> ref_value(node_pt->vector_ref_value());
575 double y0 = ref_value[0];
576 double x0 = -lleft + X_0;
582 Vector<double> r_line(2);
583 slanted_bound_up(t, s, r_line);
587 double r = ref_value[2];
590 node_pt->x(t, 0) = x0 + r * (r_line[0] - x0);
591 node_pt->x(t, 1) = y0 + r * (r_line[1] - y0);
597 template<
class ELEMENT>
599 const unsigned& t, AlgebraicNode*& node_pt)
602 double lright = this->domain_pt()->lright();
605 Vector<double> ref_value(node_pt->vector_ref_value());
609 double y0 = ref_value[0];
610 double x0 = X_0 + lright;
617 Vector<double> r_line(2);
618 slanted_bound_up(t, s, r_line);
622 double r = ref_value[2];
625 node_pt->x(t, 0) = r_line[0] + r * (x0 - r_line[0]);
626 node_pt->x(t, 1) = r_line[1] + r * (y0 - r_line[1]);
638 template<
class ELEMENT>
640 AlgebraicNode*& node_pt)
643 unsigned id = node_pt->node_update_fct_id();
645 if ((
id == 1) || (
id == 2))
648 Vector<double> ref_value(node_pt->vector_ref_value());
651 Vector<double> zeta_wall(1);
652 zeta_wall[0] = ref_value[3];
656 GeomObject* geom_obj_pt;
657 this->Leaflet_pt->locate_zeta(zeta_wall, geom_obj_pt, s);
660 Vector<GeomObject*> geom_object_pt(node_pt->vector_geom_object_pt());
666 geom_object_pt[0] = geom_obj_pt;
676 node_pt->kill_node_update_info(1);
679 node_pt->add_node_update_info(1,
687 node_pt->kill_node_update_info(2);
690 node_pt->add_node_update_info(2,
void setup_algebraic_node_update()
Function to setup the algebraic node update.
void algebraic_node_update(const unsigned &t, AlgebraicNode *&node_pt)
Update nodal position at time level t (t=0: present; t>0: previous)
void node_update_I(const unsigned &t, AlgebraicNode *&node_pt)
Update function for nodes in lower left region (I)
void node_update_III(const unsigned &t, AlgebraicNode *&node_pt)
Update function for nodes in upper left region (III)
void node_update_II(const unsigned &t, AlgebraicNode *&node_pt)
Update function for nodes in lower right region (II)
void slanted_bound_up(const unsigned &t, const Vector< double > &zeta, Vector< double > &r)
Helper function.
void node_update_IV(const unsigned &t, AlgebraicNode *&node_pt)
Update function for nodes in upper right region (IV)
Rectangular domain with a leaflet blocking the lower half.
ChannelWithLeafletDomain * Domain_pt
Pointer to domain.
GeomObject * Leaflet_pt
Pointer to GeomObject that represents the leaflet.
ChannelWithLeafletMesh(GeomObject *leaflet_pt, const double &lleft, const double &lright, const double &hleaflet, const double &htot, const unsigned &nleft, const unsigned &nright, const unsigned &ny1, const unsigned &ny2, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to GeomObject that represents the leaflet, the length of the domain to left...
void update_node_update(AlgebraicNode *&node_pt)
Update the node update data for specified node following any mesh adapation.
Simple rectangular 2D Quad mesh class. Nx : number of elements in the x direction.
////////////////////////////////////////////////////////////////////// //////////////////////////////...