26 #ifndef OOMPH_PML_MESH_HEADER
27 #define OOMPH_PML_MESH_HEADER
31 #include <oomph-lib-config.h>
35 #include "../meshes/rectangular_quadmesh.template.h"
36 #include "../meshes/rectangular_quadmesh.template.cc"
46 template<
class ELEMENT>
58 template<
unsigned DIM>
83 for (
unsigned direction = 0; direction < DIM; direction++)
98 const double& interface_border_value,
99 const double& outer_domain_border_value)
145 namespace TwoDimensionalPMLHelper
184 template<
class ELEMENT>
191 const unsigned& n_pml_y,
192 const double& x_pml_start,
193 const double& x_pml_end,
194 const double& y_pml_start,
195 const double& y_pml_end,
232 double tol = 1.0e-12;
237 if ((x[0] <
x_min - tol) || (x[0] >
x_max + tol) ||
241 std::ostringstream error_message_stream;
244 error_message_stream <<
"Point does not lie in the mesh." << std::endl;
248 OOMPH_CURRENT_FUNCTION,
249 OOMPH_EXCEPTION_LOCATION);
256 const unsigned nx = this->
nx();
259 const unsigned ny = this->
ny();
289 bottom_boundary_x_coordinates[0] =
x_min;
292 bottom_boundary_x_coordinates[
nx] =
x_max;
295 right_boundary_y_coordinates[0] =
y_min;
298 right_boundary_y_coordinates[
ny] =
y_max;
306 unsigned lower_boundary_id = 0;
309 unsigned right_boundary_id = 1;
312 for (
unsigned i = 0;
i <
nx;
i++)
318 bottom_boundary_x_coordinates[
i + 1] =
328 for (
unsigned i = 0;
i <
ny;
i++)
334 right_boundary_y_coordinates[
i + 1] = el_pt->
node_pt(
nnode - 1)->
x(1);
343 bool element_x_id_has_been_found =
false;
348 bool element_y_id_has_been_found =
false;
351 unsigned element_x_id = 0;
354 unsigned element_y_id = 0;
357 for (
unsigned i = 0;
i <
nx;
i++)
360 if ((x[0] >= bottom_boundary_x_coordinates[
i]) &&
361 (x[0] <= bottom_boundary_x_coordinates[
i + 1]))
367 element_x_id_has_been_found =
true;
372 if (!element_x_id_has_been_found)
375 std::ostringstream error_message_stream;
378 error_message_stream <<
"The ID of the element in the x-direction "
379 <<
"has not been found." << std::endl;
383 OOMPH_CURRENT_FUNCTION,
384 OOMPH_EXCEPTION_LOCATION);
388 for (
unsigned i = 0;
i <
ny;
i++)
391 if ((x[1] >= right_boundary_y_coordinates[
i]) &&
392 (x[1] <= right_boundary_y_coordinates[
i + 1]))
398 element_y_id_has_been_found =
true;
403 if (!element_y_id_has_been_found)
406 std::ostringstream error_message_stream;
409 error_message_stream <<
"The ID of the element in the y-direction "
410 <<
"has not been found." << std::endl;
414 OOMPH_CURRENT_FUNCTION,
415 OOMPH_EXCEPTION_LOCATION);
419 unsigned el_id = element_y_id *
nx + element_x_id;
429 template<
class ELEMENT>
442 const unsigned& boundary_id,
443 const unsigned& quad_boundary_id,
444 const unsigned& n_pml_x,
445 const unsigned& n_pml_y,
446 const double& x_pml_start,
447 const double& x_pml_end,
448 const double& y_pml_start,
449 const double& y_pml_end,
459 unsigned n_boundary_node = bulk_mesh_pt->
nboundary_node(boundary_id);
465 for (
unsigned n = 0; n < n_boundary_node; n++)
467 ordered_boundary_node_pt[n] =
474 if (quad_boundary_id == 3)
476 std::sort(ordered_boundary_node_pt.begin(),
477 ordered_boundary_node_pt.end(),
482 if (quad_boundary_id == 0)
484 std::sort(ordered_boundary_node_pt.begin(),
485 ordered_boundary_node_pt.end(),
490 if (quad_boundary_id == 1)
492 std::sort(ordered_boundary_node_pt.begin(),
493 ordered_boundary_node_pt.end(),
498 if (quad_boundary_id == 2)
500 std::sort(ordered_boundary_node_pt.begin(),
501 ordered_boundary_node_pt.end(),
511 unsigned interior_node_nr_helper_1 = nnode_1d * (nnode_1d - 1);
513 unsigned interior_node_nr_helper_2 = nnode_1d - 1;
515 unsigned interior_node_nr_helper_3 = nnode_1d * (nnode_1d - 1) - 1;
520 for (
unsigned j = 0; j < nnod; j++)
529 unsigned n_pml_element = this->
nelement();
534 unsigned interior_element_nr_helper_1 = n_pml_element - 1;
543 if (quad_boundary_id == 3)
545 for (
unsigned e = 0;
e < n_pml_element;
e++)
548 if ((
e % n_pml_x) == 0)
551 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
554 unsigned n_node = el_pt->nnode();
555 for (
unsigned inod = 0; inod < n_node; inod++)
557 if (inod % nnode_1d == 0)
560 el_pt->node_pt(inod) = ordered_boundary_node_pt[count];
564 if (inod == interior_node_nr_helper_1)
575 if (quad_boundary_id == 0)
577 for (
unsigned e = 0;
e < n_pml_element;
e++)
580 if ((
int)(
e / n_pml_x) == 0)
583 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
586 unsigned n_node = el_pt->nnode();
587 for (
unsigned inod = 0; inod < n_node; inod++)
589 if ((
int)(inod / nnode_1d) == 0)
592 el_pt->node_pt(inod) = ordered_boundary_node_pt[count];
596 if (inod == interior_node_nr_helper_2)
607 if (quad_boundary_id == 1)
609 for (
unsigned e = interior_element_nr_helper_1;
e < n_pml_element;
e--)
612 if ((
e % n_pml_x) == (n_pml_x - 1))
615 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
618 unsigned n_node = el_pt->nnode();
619 unsigned starter = n_node - 1;
620 for (
unsigned inod = starter; inod <= starter; inod--)
622 if (inod % nnode_1d == interior_node_nr_helper_2)
625 el_pt->node_pt(inod) = ordered_boundary_node_pt[count];
629 if (inod == interior_node_nr_helper_2)
640 if (quad_boundary_id == 2)
642 for (
unsigned e = interior_element_nr_helper_1;
e < n_pml_element;
e--)
645 if (
e >= (n_pml_x * (n_pml_y - 1)))
648 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
651 unsigned n_node = el_pt->nnode();
652 unsigned starter = n_node - 1;
653 for (
unsigned inod = starter; inod <= starter; inod--)
655 if (inod > interior_node_nr_helper_3)
658 el_pt->node_pt(inod) = ordered_boundary_node_pt[count];
662 if (inod == interior_node_nr_helper_1)
680 for (
unsigned e = 0;
e < n_pml_element;
e++)
683 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
684 unsigned n_node = el_pt->nnode();
687 double temp_coordinate = 0.0;
688 for (
unsigned inod = 0; inod < n_node; inod++)
691 if (quad_boundary_id == 3)
694 if (inod % nnode_1d == 0)
697 temp_coordinate = el_pt->node_pt(inod)->x(1);
702 el_pt->node_pt(inod)->x(1) = temp_coordinate;
707 if (quad_boundary_id == 0)
710 if (inod > interior_node_nr_helper_2)
713 el_pt->node_pt(inod)->x(0) =
714 el_pt->node_pt(inod - nnode_1d)->x(0);
721 for (
unsigned e = interior_element_nr_helper_1;
e < n_pml_element;
e--)
724 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
725 unsigned n_node = el_pt->nnode();
728 double temp_coordinate = 0.0;
729 unsigned starter = n_node - 1;
730 for (
unsigned inod = starter; inod <= starter; inod--)
733 if (quad_boundary_id == 1)
736 if (inod % nnode_1d == interior_node_nr_helper_2)
739 temp_coordinate = el_pt->node_pt(inod)->x(1);
744 el_pt->node_pt(inod)->x(1) = temp_coordinate;
749 if (quad_boundary_id == 2)
752 if (inod < interior_node_nr_helper_1)
755 el_pt->node_pt(inod)->x(0) =
756 el_pt->node_pt(inod + nnode_1d)->x(0);
775 template<
class ELEMENT>
784 Mesh* PMLQuad_mesh_y_pt,
786 Node* special_corner_node_pt,
787 const unsigned& parent_boundary_x_id,
788 const unsigned& parent_boundary_y_id,
789 const unsigned& current_boundary_x_id,
790 const unsigned& current_boundary_y_id,
791 const unsigned& n_pml_x,
792 const unsigned& n_pml_y,
793 const double& x_pml_start,
794 const double& x_pml_end,
795 const double& y_pml_start,
796 const double& y_pml_end,
812 unsigned interior_node_nr_helper_1 = nnode_1d * (nnode_1d - 1);
814 unsigned interior_node_nr_helper_2 = nnode_1d - 1;
816 unsigned interior_node_nr_helper_3 = nnode_1d * nnode_1d - 1;
820 if ((parent_boundary_x_id == 2) && (parent_boundary_y_id == 1))
823 unsigned n_boundary_x_node =
830 for (
unsigned n = 0; n < n_boundary_x_node; n++)
832 ordered_boundary_x_node_pt[n] =
837 if (parent_boundary_x_id == 2)
839 std::sort(ordered_boundary_x_node_pt.begin(),
840 ordered_boundary_x_node_pt.end(),
845 unsigned n_boundary_y_node =
852 for (
unsigned n = 0; n < n_boundary_y_node; n++)
854 ordered_boundary_y_node_pt[n] =
859 if (parent_boundary_y_id == 1)
861 std::sort(ordered_boundary_y_node_pt.begin(),
862 ordered_boundary_y_node_pt.end(),
867 for (
unsigned j = 0; j < x_nnod; j++)
873 for (
unsigned j = 0; j < y_nnod; j++)
881 unsigned n_pml_element = this->
nelement();
887 if (parent_boundary_y_id == 1)
889 for (
unsigned e = 0;
e < n_pml_element;
e++)
892 if ((
e % n_pml_x) == 0)
895 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
898 unsigned n_node = el_pt->nnode();
899 for (
unsigned inod = 0; inod < n_node; inod++)
904 if (inod == 0) el_pt->node_pt(inod) = special_corner_node_pt;
905 if ((inod % nnode_1d == 0) && (inod > 0))
908 el_pt->node_pt(inod) = ordered_boundary_y_node_pt[count];
912 if (inod == interior_node_nr_helper_1)
920 if ((inod % nnode_1d) == 0)
923 el_pt->node_pt(inod) = ordered_boundary_y_node_pt[count];
927 if (inod == interior_node_nr_helper_1)
940 if (parent_boundary_x_id == 2)
942 for (
unsigned e = 0;
e < n_pml_element;
e++)
945 if ((
int)(
e / n_pml_x) == 0)
948 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
951 unsigned n_node = el_pt->nnode();
952 for (
unsigned inod = 0; inod < n_node; inod++)
956 if (((
int)(inod / nnode_1d) == 0) && (inod > 0))
959 el_pt->node_pt(inod) = ordered_boundary_x_node_pt[count];
963 if (inod == interior_node_nr_helper_2)
971 if ((
int)(inod / nnode_1d) == 0)
974 el_pt->node_pt(inod) = ordered_boundary_x_node_pt[count];
978 if (inod == interior_node_nr_helper_2)
992 if ((parent_boundary_x_id == 0) && (parent_boundary_y_id == 1))
995 unsigned n_boundary_x_node =
1002 for (
unsigned n = 0; n < n_boundary_x_node; n++)
1004 ordered_boundary_x_node_pt[n] =
1009 if (parent_boundary_x_id == 0)
1011 std::sort(ordered_boundary_x_node_pt.begin(),
1012 ordered_boundary_x_node_pt.end(),
1017 unsigned n_boundary_y_node =
1021 Vector<Node*> ordered_boundary_y_node_pt(n_boundary_y_node);
1024 for (
unsigned n = 0; n < n_boundary_y_node; n++)
1026 ordered_boundary_y_node_pt[n] =
1031 if (parent_boundary_y_id == 1)
1033 std::sort(ordered_boundary_y_node_pt.begin(),
1034 ordered_boundary_y_node_pt.end(),
1039 for (
unsigned j = 0; j < x_nnod; j++)
1045 for (
unsigned j = 0; j < y_nnod; j++)
1054 unsigned n_pml_element = this->
nelement();
1060 if (parent_boundary_y_id == 1)
1062 for (
unsigned e = 0;
e < n_pml_element;
e++)
1065 if ((
e % n_pml_x) == 0)
1068 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
1071 unsigned n_node = el_pt->nnode();
1072 for (
unsigned inod = 0; inod < n_node; inod++)
1074 if (
e == ((n_pml_x) * (n_pml_y - 1)))
1076 if (inod == interior_node_nr_helper_1)
1078 el_pt->node_pt(inod) = special_corner_node_pt;
1080 if ((inod % nnode_1d == 0) &&
1081 (inod < interior_node_nr_helper_1))
1084 el_pt->node_pt(inod) = ordered_boundary_y_node_pt[count];
1088 if (inod == interior_node_nr_helper_1)
1096 if ((inod % nnode_1d) == 0)
1099 el_pt->node_pt(inod) = ordered_boundary_y_node_pt[count];
1103 if (inod == interior_node_nr_helper_1)
1116 if (parent_boundary_x_id == 0)
1118 for (
unsigned e = 0;
e < n_pml_element;
e++)
1121 if (
e >= ((n_pml_x - 0) * (n_pml_y - 1)))
1124 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
1127 unsigned n_node = el_pt->nnode();
1128 for (
unsigned inod = 0; inod < n_node; inod++)
1130 if (
e == ((n_pml_x) * (n_pml_y - 1)))
1132 if (((
unsigned)(inod / nnode_1d) ==
1133 interior_node_nr_helper_2) &&
1134 (inod > interior_node_nr_helper_1))
1137 el_pt->node_pt(inod) = ordered_boundary_x_node_pt[count];
1141 if (inod == interior_node_nr_helper_3)
1149 if ((
unsigned)(inod / nnode_1d) == interior_node_nr_helper_2)
1152 el_pt->node_pt(inod) = ordered_boundary_x_node_pt[count];
1156 if (inod == interior_node_nr_helper_3)
1170 if ((parent_boundary_x_id == 2) && (parent_boundary_y_id == 3))
1173 unsigned n_boundary_x_node =
1177 Vector<Node*> ordered_boundary_x_node_pt(n_boundary_x_node);
1180 for (
unsigned n = 0; n < n_boundary_x_node; n++)
1182 ordered_boundary_x_node_pt[n] =
1187 if (parent_boundary_x_id == 2)
1189 std::sort(ordered_boundary_x_node_pt.begin(),
1190 ordered_boundary_x_node_pt.end(),
1195 unsigned n_boundary_y_node =
1199 Vector<Node*> ordered_boundary_y_node_pt(n_boundary_y_node);
1202 for (
unsigned n = 0; n < n_boundary_y_node; n++)
1204 ordered_boundary_y_node_pt[n] =
1209 if (parent_boundary_y_id == 1)
1211 std::sort(ordered_boundary_y_node_pt.begin(),
1212 ordered_boundary_y_node_pt.end(),
1217 for (
unsigned j = 0; j < x_nnod; j++)
1223 for (
unsigned j = 0; j < y_nnod; j++)
1232 unsigned n_pml_element = this->
nelement();
1238 if (parent_boundary_y_id == 3)
1240 for (
unsigned e = 0;
e < n_pml_element;
e++)
1243 if ((
e % n_pml_x) == (n_pml_x - 1))
1246 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
1249 unsigned n_node = el_pt->nnode();
1250 for (
unsigned inod = 0; inod < n_node; inod++)
1252 if (
e == (n_pml_x - 1))
1254 if (inod == interior_node_nr_helper_2)
1255 el_pt->node_pt(inod) = special_corner_node_pt;
1256 if ((inod % nnode_1d == interior_node_nr_helper_2) &&
1257 (inod > (nnode_1d - 1)))
1260 el_pt->node_pt(inod) = ordered_boundary_y_node_pt[count];
1264 if (inod == interior_node_nr_helper_3)
1272 if ((inod % nnode_1d) == interior_node_nr_helper_2)
1275 el_pt->node_pt(inod) = ordered_boundary_y_node_pt[count];
1279 if (inod == interior_node_nr_helper_3)
1292 if (parent_boundary_x_id == 2)
1294 for (
unsigned e = 0;
e < n_pml_element;
e++)
1297 if ((
int)(
e / n_pml_x) == 0)
1300 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
1303 unsigned n_node = el_pt->nnode();
1304 for (
unsigned inod = 0; inod < n_node; inod++)
1307 if (
e == (n_pml_x - 1))
1309 if (((
int)(inod / nnode_1d) == 0) &&
1310 (inod < interior_node_nr_helper_2))
1313 el_pt->node_pt(inod) = ordered_boundary_x_node_pt[count];
1317 if (inod == (nnode_1d - 1))
1325 if ((
int)(inod / nnode_1d) == 0)
1328 el_pt->node_pt(inod) = ordered_boundary_x_node_pt[count];
1332 if (inod == interior_node_nr_helper_2)
1346 if ((parent_boundary_x_id == 0) && (parent_boundary_y_id == 3))
1349 unsigned n_boundary_x_node =
1353 Vector<Node*> ordered_boundary_x_node_pt(n_boundary_x_node);
1356 for (
unsigned n = 0; n < n_boundary_x_node; n++)
1358 ordered_boundary_x_node_pt[n] =
1363 if (parent_boundary_x_id == 0)
1365 std::sort(ordered_boundary_x_node_pt.begin(),
1366 ordered_boundary_x_node_pt.end(),
1371 unsigned n_boundary_y_node =
1375 Vector<Node*> ordered_boundary_y_node_pt(n_boundary_y_node);
1378 for (
unsigned n = 0; n < n_boundary_y_node; n++)
1380 ordered_boundary_y_node_pt[n] =
1385 if (parent_boundary_y_id == 3)
1387 std::sort(ordered_boundary_y_node_pt.begin(),
1388 ordered_boundary_y_node_pt.end(),
1393 for (
unsigned j = 0; j < x_nnod; j++)
1399 for (
unsigned j = 0; j < y_nnod; j++)
1407 unsigned n_pml_element = this->
nelement();
1413 if (parent_boundary_y_id == 3)
1415 for (
unsigned e = 0;
e < n_pml_element;
e++)
1418 if ((
e % n_pml_x) == (n_pml_x - 1))
1421 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
1424 unsigned n_node = el_pt->nnode();
1425 for (
unsigned inod = 0; inod < n_node; inod++)
1427 if (
e == (n_pml_element - 1))
1429 if (inod == interior_node_nr_helper_3)
1431 el_pt->node_pt(inod) = special_corner_node_pt;
1433 if ((inod % nnode_1d == interior_node_nr_helper_2) &&
1434 (inod < interior_node_nr_helper_3))
1437 el_pt->node_pt(inod) = ordered_boundary_y_node_pt[count];
1441 if (inod == interior_node_nr_helper_3)
1449 if ((inod % nnode_1d) == interior_node_nr_helper_2)
1452 el_pt->node_pt(inod) = ordered_boundary_y_node_pt[count];
1456 if (inod == interior_node_nr_helper_3)
1469 if (parent_boundary_x_id == 0)
1471 for (
unsigned e = 0;
e < n_pml_element;
e++)
1474 if (
e >= ((n_pml_x) * (n_pml_y - 1)))
1477 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(this->
element_pt(
e));
1480 unsigned n_node = el_pt->nnode();
1481 for (
unsigned inod = 0; inod < n_node; inod++)
1483 if (
e == (n_pml_element - 1))
1485 if (((
unsigned)(inod / nnode_1d) ==
1486 interior_node_nr_helper_2) &&
1487 (inod < interior_node_nr_helper_3))
1490 el_pt->node_pt(inod) = ordered_boundary_x_node_pt[count];
1494 if (inod == interior_node_nr_helper_3)
1502 if ((
unsigned)(inod / nnode_1d) == interior_node_nr_helper_2)
1505 el_pt->node_pt(inod) = ordered_boundary_x_node_pt[count];
1509 if (inod == interior_node_nr_helper_3)
1532 namespace TwoDimensionalPMLHelper
1538 template<
class ASSOCIATED_PML_QUAD_ELEMENT>
1541 const unsigned& right_boundary_id,
1542 const unsigned& n_x_right_pml,
1543 const double& width_x_right_pml,
1547 unsigned n_right_boundary_node =
1551 Vector<Node*> ordered_right_boundary_node_pt(n_right_boundary_node);
1554 for (
unsigned n = 0; n < n_right_boundary_node; n++)
1556 ordered_right_boundary_node_pt[n] =
1561 std::sort(ordered_right_boundary_node_pt.begin(),
1562 ordered_right_boundary_node_pt.end(),
1566 unsigned n_y_right_pml =
1570 double l_pml_right_x_start = ordered_right_boundary_node_pt[0]->x(0);
1572 double l_pml_right_x_end =
1573 width_x_right_pml + ordered_right_boundary_node_pt[0]->x(0);
1574 double l_pml_right_y_start = ordered_right_boundary_node_pt[0]->x(1);
1575 double l_pml_right_y_end =
1576 ordered_right_boundary_node_pt[n_right_boundary_node - 1]->x(1);
1579 unsigned right_quadPML_boundary_id = 3;
1582 Mesh* pml_right_mesh_pt = 0;
1588 right_quadPML_boundary_id,
1591 l_pml_right_x_start,
1593 l_pml_right_y_start,
1598 unsigned n_element_pml_right = pml_right_mesh_pt->
nelement();
1599 for (
unsigned e = 0;
e < n_element_pml_right;
e++)
1604 el_pt->
enable_pml(0, l_pml_right_x_start, l_pml_right_x_end);
1613 unsigned npin = values_to_pin.size();
1617 unsigned n_bound_pml_right = pml_right_mesh_pt->
nboundary();
1618 for (
unsigned b = 0; b < n_bound_pml_right; b++)
1621 for (
unsigned n = 0; n < n_node; n++)
1626 for (
unsigned j = 0; j < npin; j++)
1628 unsigned j_val = values_to_pin[j];
1638 return pml_right_mesh_pt;
1645 template<
class ASSOCIATED_PML_QUAD_ELEMENT>
1648 const unsigned& top_boundary_id,
1649 const unsigned& n_y_top_pml,
1650 const double& width_y_top_pml,
1654 unsigned n_top_boundary_node =
1658 Vector<Node*> ordered_top_boundary_node_pt(n_top_boundary_node);
1661 for (
unsigned n = 0; n < n_top_boundary_node; n++)
1663 ordered_top_boundary_node_pt[n] =
1668 std::sort(ordered_top_boundary_node_pt.begin(),
1669 ordered_top_boundary_node_pt.end(),
1676 double l_pml_top_x_start = ordered_top_boundary_node_pt[0]->x(0);
1677 double l_pml_top_x_end =
1678 ordered_top_boundary_node_pt[n_top_boundary_node - 1]->x(0);
1679 double l_pml_top_y_start = ordered_top_boundary_node_pt[0]->x(1);
1681 double l_pml_top_y_end =
1682 width_y_top_pml + ordered_top_boundary_node_pt[0]->x(1);
1684 unsigned top_quadPML_boundary_id = 0;
1687 Mesh* pml_top_mesh_pt = 0;
1693 top_quadPML_boundary_id,
1703 unsigned n_element_pml_top = pml_top_mesh_pt->
nelement();
1704 for (
unsigned e = 0;
e < n_element_pml_top;
e++)
1709 el_pt->
enable_pml(1, l_pml_top_y_start, l_pml_top_y_end);
1718 unsigned npin = values_to_pin.size();
1723 unsigned n_bound_pml_top = pml_top_mesh_pt->
nboundary();
1724 for (
unsigned b = 0; b < n_bound_pml_top; b++)
1727 for (
unsigned n = 0; n < n_node; n++)
1732 for (
unsigned j = 0; j < npin; j++)
1734 unsigned j_val = values_to_pin[j];
1744 return pml_top_mesh_pt;
1751 template<
class ASSOCIATED_PML_QUAD_ELEMENT>
1754 const unsigned& left_boundary_id,
1755 const unsigned& n_x_left_pml,
1756 const double& width_x_left_pml,
1760 unsigned n_left_boundary_node =
1764 Vector<Node*> ordered_left_boundary_node_pt(n_left_boundary_node);
1767 for (
unsigned n = 0; n < n_left_boundary_node; n++)
1769 ordered_left_boundary_node_pt[n] =
1774 std::sort(ordered_left_boundary_node_pt.begin(),
1775 ordered_left_boundary_node_pt.end(),
1783 double l_pml_left_x_start =
1785 ordered_left_boundary_node_pt[n_left_boundary_node - 1]->x(0);
1786 double l_pml_left_x_end =
1787 ordered_left_boundary_node_pt[n_left_boundary_node - 1]->x(0);
1788 double l_pml_left_y_start =
1789 ordered_left_boundary_node_pt[n_left_boundary_node - 1]->x(1);
1790 double l_pml_left_y_end = ordered_left_boundary_node_pt[0]->x(1);
1792 unsigned left_quadPML_boundary_id = 1;
1795 Mesh* pml_left_mesh_pt = 0;
1801 left_quadPML_boundary_id,
1811 unsigned n_element_pml_left = pml_left_mesh_pt->
nelement();
1812 for (
unsigned e = 0;
e < n_element_pml_left;
e++)
1817 el_pt->
enable_pml(0, l_pml_left_x_end, l_pml_left_x_start);
1826 unsigned npin = values_to_pin.size();
1831 unsigned n_bound_pml_left = pml_left_mesh_pt->
nboundary();
1832 for (
unsigned b = 0; b < n_bound_pml_left; b++)
1835 for (
unsigned n = 0; n < n_node; n++)
1840 for (
unsigned j = 0; j < npin; j++)
1842 unsigned j_val = values_to_pin[j];
1852 return pml_left_mesh_pt;
1859 template<
class ASSOCIATED_PML_QUAD_ELEMENT>
1862 const unsigned& bottom_boundary_id,
1863 const unsigned& n_y_bottom_pml,
1864 const double& width_y_bottom_pml,
1868 unsigned n_bottom_boundary_node =
1872 Vector<Node*> ordered_bottom_boundary_node_pt(n_bottom_boundary_node);
1875 for (
unsigned n = 0; n < n_bottom_boundary_node; n++)
1877 ordered_bottom_boundary_node_pt[n] =
1882 std::sort(ordered_bottom_boundary_node_pt.begin(),
1883 ordered_bottom_boundary_node_pt.end(),
1887 unsigned n_x_bottom_pml =
1891 double l_pml_bottom_x_start =
1892 ordered_bottom_boundary_node_pt[n_bottom_boundary_node - 1]->x(0);
1893 double l_pml_bottom_x_end = ordered_bottom_boundary_node_pt[0]->x(0);
1896 double l_pml_bottom_y_start =
1897 -width_y_bottom_pml + ordered_bottom_boundary_node_pt[0]->x(1);
1898 double l_pml_bottom_y_end = ordered_bottom_boundary_node_pt[0]->x(1);
1900 unsigned bottom_quadPML_boundary_id = 2;
1903 Mesh* pml_bottom_mesh_pt = 0;
1906 pml_bottom_mesh_pt =
1909 bottom_quadPML_boundary_id,
1912 l_pml_bottom_x_start,
1914 l_pml_bottom_y_start,
1919 unsigned n_element_pml_bottom = pml_bottom_mesh_pt->
nelement();
1920 for (
unsigned e = 0;
e < n_element_pml_bottom;
e++)
1925 el_pt->
enable_pml(1, l_pml_bottom_y_end, l_pml_bottom_y_start);
1934 unsigned npin = values_to_pin.size();
1939 unsigned n_bound_pml_bottom = pml_bottom_mesh_pt->
nboundary();
1940 for (
unsigned b = 0; b < n_bound_pml_bottom; b++)
1943 for (
unsigned n = 0; n < n_node; n++)
1948 for (
unsigned j = 0; j < npin; j++)
1950 unsigned j_val = values_to_pin[j];
1960 return pml_bottom_mesh_pt;
1967 template<
class ASSOCIATED_PML_QUAD_ELEMENT>
1969 Mesh* pml_right_mesh_pt,
1970 Mesh* pml_top_mesh_pt,
1972 const unsigned& right_boundary_id,
1977 unsigned parent_boundary_x_id = 2;
1978 unsigned parent_boundary_y_id = 1;
1980 unsigned current_boundary_x_id = 0;
1981 unsigned current_boundary_y_id = 3;
1984 unsigned n_right_boundary_node =
1988 Vector<Node*> ordered_right_boundary_node_pt(n_right_boundary_node);
1991 for (
unsigned n = 0; n < n_right_boundary_node; n++)
1993 ordered_right_boundary_node_pt[n] =
1998 std::sort(ordered_right_boundary_node_pt.begin(),
1999 ordered_right_boundary_node_pt.end(),
2004 unsigned n_x_right_pml =
2006 unsigned n_y_top_pml =
2008 unsigned n_x_boundary_nodes =
2010 unsigned n_y_boundary_nodes =
2015 double l_pml_right_x_start =
2016 ordered_right_boundary_node_pt[n_right_boundary_node - 1]->x(0);
2017 double l_pml_right_x_end =
2021 double l_pml_top_y_start =
2022 ordered_right_boundary_node_pt[n_right_boundary_node - 1]->x(1);
2023 double l_pml_top_y_end =
2029 Mesh* pml_top_right_mesh_pt = 0;
2032 pml_top_right_mesh_pt =
2037 ordered_right_boundary_node_pt[n_right_boundary_node - 1],
2038 parent_boundary_x_id,
2039 parent_boundary_y_id,
2040 current_boundary_x_id,
2041 current_boundary_y_id,
2044 l_pml_right_x_start,
2053 unsigned n_element_pml_top_right = pml_top_right_mesh_pt->
nelement();
2054 for (
unsigned e = 0;
e < n_element_pml_top_right;
e++)
2059 el_pt->
enable_pml(0, l_pml_right_x_start, l_pml_right_x_end);
2060 el_pt->
enable_pml(1, l_pml_top_y_start, l_pml_top_y_end);
2069 unsigned npin = values_to_pin.size();
2074 unsigned n_bound_pml_top_right = pml_top_right_mesh_pt->
nboundary();
2075 for (
unsigned b = 0; b < n_bound_pml_top_right; b++)
2078 for (
unsigned n = 0; n < n_node; n++)
2081 if ((b == 1) || (b == 2))
2083 for (
unsigned j = 0; j < npin; j++)
2085 unsigned j_val = values_to_pin[j];
2095 return pml_top_right_mesh_pt;
2102 template<
class ASSOCIATED_PML_QUAD_ELEMENT>
2104 Mesh* pml_right_mesh_pt,
2105 Mesh* pml_bottom_mesh_pt,
2107 const unsigned& right_boundary_id,
2112 unsigned parent_boundary_x_id = 0;
2113 unsigned parent_boundary_y_id = 1;
2115 unsigned current_boundary_x_id = 2;
2116 unsigned current_boundary_y_id = 3;
2119 unsigned n_right_boundary_node =
2123 Vector<Node*> ordered_right_boundary_node_pt(n_right_boundary_node);
2126 for (
unsigned n = 0; n < n_right_boundary_node; n++)
2128 ordered_right_boundary_node_pt[n] =
2133 std::sort(ordered_right_boundary_node_pt.begin(),
2134 ordered_right_boundary_node_pt.end(),
2139 unsigned n_x_right_pml =
2141 unsigned n_y_bottom_pml =
2143 unsigned n_x_boundary_nodes =
2148 double l_pml_right_x_start = ordered_right_boundary_node_pt[0]->x(0);
2149 double l_pml_right_x_end =
2153 double l_pml_bottom_y_start =
2155 double l_pml_bottom_y_end = ordered_right_boundary_node_pt[0]->x(1);
2158 Mesh* pml_bottom_right_mesh_pt = 0;
2161 pml_bottom_right_mesh_pt =
2166 ordered_right_boundary_node_pt[0],
2167 parent_boundary_x_id,
2168 parent_boundary_y_id,
2169 current_boundary_x_id,
2170 current_boundary_y_id,
2173 l_pml_right_x_start,
2175 l_pml_bottom_y_start,
2182 unsigned n_element_pml_bottom_right =
2183 pml_bottom_right_mesh_pt->
nelement();
2185 for (
unsigned e = 0;
e < n_element_pml_bottom_right;
e++)
2190 el_pt->
enable_pml(0, l_pml_right_x_start, l_pml_right_x_end);
2191 el_pt->
enable_pml(1, l_pml_bottom_y_end, l_pml_bottom_y_start);
2200 unsigned npin = values_to_pin.size();
2205 unsigned n_bound_pml_bottom_right = pml_bottom_right_mesh_pt->
nboundary();
2206 for (
unsigned b = 0; b < n_bound_pml_bottom_right; b++)
2209 for (
unsigned n = 0; n < n_node; n++)
2212 if ((b == 0) || (b == 1))
2214 for (
unsigned j = 0; j < npin; j++)
2216 unsigned j_val = values_to_pin[j];
2226 return pml_bottom_right_mesh_pt;
2233 template<
class ASSOCIATED_PML_QUAD_ELEMENT>
2235 Mesh* pml_left_mesh_pt,
2236 Mesh* pml_top_mesh_pt,
2238 const unsigned& left_boundary_id,
2243 unsigned parent_boundary_x_id = 2;
2244 unsigned parent_boundary_y_id = 3;
2246 unsigned current_boundary_x_id = 0;
2247 unsigned current_boundary_y_id = 1;
2250 unsigned n_left_boundary_node =
2254 Vector<Node*> ordered_left_boundary_node_pt(n_left_boundary_node);
2257 for (
unsigned n = 0; n < n_left_boundary_node; n++)
2259 ordered_left_boundary_node_pt[n] =
2266 std::sort(ordered_left_boundary_node_pt.begin(),
2267 ordered_left_boundary_node_pt.end(),
2272 unsigned n_x_left_pml =
2274 unsigned n_y_top_pml =
2276 unsigned n_y_boundary_nodes =
2281 double l_pml_left_x_start =
2283 double l_pml_left_x_end =
2284 ordered_left_boundary_node_pt[n_left_boundary_node - 1]->x(0);
2285 double l_pml_top_y_start =
2286 ordered_left_boundary_node_pt[n_left_boundary_node - 1]->x(1);
2287 double l_pml_top_y_end =
2293 Mesh* pml_top_left_mesh_pt = 0;
2300 ordered_left_boundary_node_pt[n_left_boundary_node - 1],
2301 parent_boundary_x_id,
2302 parent_boundary_y_id,
2303 current_boundary_x_id,
2304 current_boundary_y_id,
2316 unsigned n_element_pml_top_left = pml_top_left_mesh_pt->
nelement();
2318 for (
unsigned e = 0;
e < n_element_pml_top_left;
e++)
2323 el_pt->
enable_pml(0, l_pml_left_x_end, l_pml_left_x_start);
2324 el_pt->
enable_pml(1, l_pml_top_y_start, l_pml_top_y_end);
2333 unsigned npin = values_to_pin.size();
2338 unsigned n_bound_pml_top_left = pml_top_left_mesh_pt->
nboundary();
2339 for (
unsigned b = 0; b < n_bound_pml_top_left; b++)
2342 for (
unsigned n = 0; n < n_node; n++)
2345 if ((b == 2) || (b == 3))
2347 for (
unsigned j = 0; j < npin; j++)
2349 unsigned j_val = values_to_pin[j];
2359 return pml_top_left_mesh_pt;
2366 template<
class ASSOCIATED_PML_QUAD_ELEMENT>
2368 Mesh* pml_left_mesh_pt,
2369 Mesh* pml_bottom_mesh_pt,
2371 const unsigned& left_boundary_id,
2376 unsigned parent_boundary_x_id = 0;
2377 unsigned parent_boundary_y_id = 3;
2379 unsigned current_boundary_x_id = 2;
2380 unsigned current_boundary_y_id = 1;
2383 unsigned n_left_boundary_node =
2387 Vector<Node*> ordered_left_boundary_node_pt(n_left_boundary_node);
2390 for (
unsigned n = 0; n < n_left_boundary_node; n++)
2392 ordered_left_boundary_node_pt[n] =
2399 std::sort(ordered_left_boundary_node_pt.begin(),
2400 ordered_left_boundary_node_pt.end(),
2405 unsigned n_x_left_pml =
2407 unsigned n_y_bottom_pml =
2412 double l_pml_left_x_start =
2414 double l_pml_left_x_end =
2415 ordered_left_boundary_node_pt[n_left_boundary_node - 1]->x(0);
2416 double l_pml_bottom_y_start =
2418 double l_pml_bottom_y_end = ordered_left_boundary_node_pt[0]->x(1);
2421 Mesh* pml_bottom_left_mesh_pt = 0;
2424 pml_bottom_left_mesh_pt =
2429 ordered_left_boundary_node_pt[0],
2430 parent_boundary_x_id,
2431 parent_boundary_y_id,
2432 current_boundary_x_id,
2433 current_boundary_y_id,
2438 l_pml_bottom_y_start,
2445 unsigned n_element_pml_bottom_left = pml_bottom_left_mesh_pt->
nelement();
2446 for (
unsigned e = 0;
e < n_element_pml_bottom_left;
e++)
2451 el_pt->
enable_pml(0, l_pml_left_x_end, l_pml_left_x_start);
2452 el_pt->
enable_pml(1, l_pml_bottom_y_end, l_pml_bottom_y_start);
2461 unsigned npin = values_to_pin.size();
2466 unsigned n_bound_pml_bottom_left = pml_bottom_left_mesh_pt->
nboundary();
2467 for (
unsigned b = 0; b < n_bound_pml_bottom_left; b++)
2470 for (
unsigned n = 0; n < n_node; n++)
2473 if ((b == 0) || (b == 3))
2475 for (
unsigned j = 0; j < npin; j++)
2477 unsigned j_val = values_to_pin[j];
2487 return pml_bottom_left_mesh_pt;
void pin(const unsigned &i)
Pin the i-th stored variable.
void set_value(const unsigned &i, const double &value_)
Set the i-th stored data value to specified value. The only reason that we require an explicit set fu...
A general Finite Element class.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
unsigned nnode() const
Return the number of nodes.
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
static Steady< 0 > Default_TimeStepper
Default Steady Timestepper, to be used in default arguments to Mesh constructors.
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
unsigned nboundary_element(const unsigned &b) const
Return number of finite elements that are adjacent to boundary b.
unsigned nboundary() const
Return number of boundaries.
FiniteElement * boundary_element_pt(const unsigned &b, const unsigned &e) const
Return pointer to e-th finite element on boundary b.
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
unsigned long nnode() const
Return number of nodes in the mesh.
const Vector< GeneralisedElement * > & element_pt() const
Return reference to the Vector of elements.
Vector< Node * > prune_dead_nodes()
Prune nodes. Nodes that have been marked as obsolete are removed from the mesh (and its boundary-node...
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
unsigned long nelement() const
Return number of elements in the mesh.
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.
void set_obsolete()
Mark node as obsolete.
An OomphLibError object which should be thrown when an run-time error is encountered....
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
PMLCornerQuadMesh(Mesh *PMLQuad_mesh_x_pt, Mesh *PMLQuad_mesh_y_pt, Mesh *bulk_mesh_pt, Node *special_corner_node_pt, const unsigned &parent_boundary_x_id, const unsigned &parent_boundary_y_id, const unsigned ¤t_boundary_x_id, const unsigned ¤t_boundary_y_id, const unsigned &n_pml_x, const unsigned &n_pml_y, const double &x_pml_start, const double &x_pml_end, const double &y_pml_start, const double &y_pml_end, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to "bulk" mesh and the two existing PML meshes in order to construct the co...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
bool Pml_is_enabled
Boolean indicating if element is used in pml mode.
virtual ~PMLElementBase()
Virtual destructor.
void enable_pml(const int &direction, const double &interface_border_value, const double &outer_domain_border_value)
Enable pml. Specify the coordinate direction along which pml boundary is constant,...
void disable_pml()
Disable pml. Ensures the PML-ification in all directions has been deactivated.
std::vector< bool > Pml_direction_active
Coordinate direction along which pml boundary is constant; alternatively: coordinate direction in whi...
Vector< double > Pml_outer_boundary
Coordinate of outer pml boundary (Storage is provided for any coordinate direction; only the entries ...
Vector< double > Pml_inner_boundary
Coordinate of inner pml boundary (Storage is provided for any coordinate direction; only the entries ...
PMLElementBase()
Constructor.
virtual void values_to_be_pinned_on_outer_pml_boundary(Vector< unsigned > &values_to_pin)=0
Pure virtual function in which we have to specify the values to be pinned (and set to zero) on the ou...
General definition of policy class defining the elements to be used in the actual PML layers....
/////////////////////////////////////////////////////////////// /////////////////////////////////////...
virtual void pml_locate_zeta(const Vector< double > &x, FiniteElement *&el_pt)=0
Pure virtual function to provide an optimised version of the locate_zeta function for PML meshes....
PML mesh class. Policy class for 2D PML meshes.
void pml_locate_zeta(const Vector< double > &x, FiniteElement *&coarse_mesh_el_pt)
Overloaded function to allow the user to locate an element in mesh given the (Eulerian) position of a...
PMLQuadMeshBase(const unsigned &n_pml_x, const unsigned &n_pml_y, const double &x_pml_start, const double &x_pml_end, const double &y_pml_start, const double &y_pml_end, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Create the underlying rectangular quad mesh.
PML mesh, derived from RectangularQuadMesh.
PMLQuadMesh(Mesh *bulk_mesh_pt, const unsigned &boundary_id, const unsigned &quad_boundary_id, const unsigned &n_pml_x, const unsigned &n_pml_y, const double &x_pml_start, const double &x_pml_end, const double &y_pml_start, const double &y_pml_end, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to "bulk" mesh, the boundary ID of axis aligned boundary to which the mesh ...
RectangularQuadMesh is a two-dimensional mesh of Quad elements with Nx elements in the "x" (horizonal...
const double y_min() const
Return the minimum value of y coordinate.
const double x_max() const
Return the maximum value of x coordinate.
const double y_max() const
Return the maximum value of y coordinate.
const unsigned & ny() const
Return number of elements in y direction.
const double x_min() const
Return the minimum value of x coordinate.
const unsigned & nx() const
Return number of elements in x direction.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
bool sorter_bottom_boundary(Node *nod_i_pt, Node *nod_j_pt)
helper function for sorting the bottom boundary nodes
Mesh * create_bottom_right_pml_mesh(Mesh *pml_right_mesh_pt, Mesh *pml_bottom_mesh_pt, Mesh *bulk_mesh_pt, const unsigned &right_boundary_id, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
"Constructor" for PML bottom right corner mesh, aligned with the existing PML meshes
Mesh * create_top_right_pml_mesh(Mesh *pml_right_mesh_pt, Mesh *pml_top_mesh_pt, Mesh *bulk_mesh_pt, const unsigned &right_boundary_id, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
"Constructor" for PML top right corner mesh, aligned with the existing PML meshes
Mesh * create_top_pml_mesh(Mesh *bulk_mesh_pt, const unsigned &top_boundary_id, const unsigned &n_y_top_pml, const double &width_y_top_pml, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
"Constructor" for PML mesh, aligned with the top physical domain boundary
Mesh * create_top_left_pml_mesh(Mesh *pml_left_mesh_pt, Mesh *pml_top_mesh_pt, Mesh *bulk_mesh_pt, const unsigned &left_boundary_id, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
"Constructor" for PML top left corner mesh, aligned with the existing PML meshes
bool sorter_top_boundary(Node *nod_i_pt, Node *nod_j_pt)
helper function for sorting the top boundary nodes
Mesh * create_bottom_left_pml_mesh(Mesh *pml_left_mesh_pt, Mesh *pml_bottom_mesh_pt, Mesh *bulk_mesh_pt, const unsigned &left_boundary_id, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
"Constructor" for PML bottom left corner mesh, aligned with the existing PML meshes
Mesh * create_bottom_pml_mesh(Mesh *bulk_mesh_pt, const unsigned &bottom_boundary_id, const unsigned &n_y_bottom_pml, const double &width_y_bottom_pml, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
"Constructor" for PML mesh,aligned with the bottom physical domain boundary
Mesh * create_left_pml_mesh(Mesh *bulk_mesh_pt, const unsigned &left_boundary_id, const unsigned &n_x_left_pml, const double &width_x_left_pml, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
"Constructor" for PML mesh, aligned with the left physical domain boundary
bool sorter_right_boundary(Node *nod_i_pt, Node *nod_j_pt)
helper function for sorting the right boundary nodes
bool sorter_left_boundary(Node *nod_i_pt, Node *nod_j_pt)
helper function for sorting the left boundary nodes
Mesh * create_right_pml_mesh(Mesh *bulk_mesh_pt, const unsigned &right_boundary_id, const unsigned &n_x_right_pml, const double &width_x_right_pml, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
"Constructor" for PML mesh,aligned with the right physical domain boundary
//////////////////////////////////////////////////////////////////// ////////////////////////////////...