10#ifndef GOOSEFEM_MESHQUAD4_H
11#define GOOSEFEM_MESHQUAD4_H
54 m_nnode = (m_nelx + 1) * (m_nely + 1);
55 m_nelem = m_nelx * m_nely;
65 return xt::arange<size_t>(m_nelem).reshape({m_nely, m_nelx});
72 size_t nelx_impl()
const
77 size_t nely_impl()
const
87 array_type::tensor<double, 2> coor_impl()
const
89 array_type::tensor<double, 2>
ret = xt::empty<double>({m_nnode, m_ndim});
91 array_type::tensor<double, 1>
x =
92 xt::linspace<double>(0.0, m_h *
static_cast<double>(m_nelx), m_nelx + 1);
93 array_type::tensor<double, 1>
y =
94 xt::linspace<double>(0.0, m_h *
static_cast<double>(m_nely), m_nely + 1);
98 for (
size_t iy = 0;
iy < m_nely + 1; ++
iy) {
99 for (
size_t ix = 0;
ix < m_nelx + 1; ++
ix) {
109 array_type::tensor<size_t, 2> conn_impl()
const
111 array_type::tensor<size_t, 2>
ret = xt::empty<size_t>({m_nelem, m_nne});
115 for (
size_t iy = 0;
iy < m_nely; ++
iy) {
116 for (
size_t ix = 0;
ix < m_nelx; ++
ix) {
128 array_type::tensor<size_t, 1> nodesBottomEdge_impl()
const
130 return xt::arange<size_t>(m_nelx + 1);
133 array_type::tensor<size_t, 1> nodesTopEdge_impl()
const
135 return xt::arange<size_t>(m_nelx + 1) + m_nely * (m_nelx + 1);
138 array_type::tensor<size_t, 1> nodesLeftEdge_impl()
const
140 return xt::arange<size_t>(m_nely + 1) * (m_nelx + 1);
143 array_type::tensor<size_t, 1> nodesRightEdge_impl()
const
145 return xt::arange<size_t>(m_nely + 1) * (m_nelx + 1) + m_nelx;
148 array_type::tensor<size_t, 1> nodesBottomOpenEdge_impl()
const
150 return xt::arange<size_t>(1, m_nelx);
153 array_type::tensor<size_t, 1> nodesTopOpenEdge_impl()
const
155 return xt::arange<size_t>(1, m_nelx) + m_nely * (m_nelx + 1);
158 array_type::tensor<size_t, 1> nodesLeftOpenEdge_impl()
const
160 return xt::arange<size_t>(1, m_nely) * (m_nelx + 1);
163 array_type::tensor<size_t, 1> nodesRightOpenEdge_impl()
const
165 return xt::arange<size_t>(1, m_nely) * (m_nelx + 1) + m_nelx;
168 size_t nodesBottomLeftCorner_impl()
const
173 size_t nodesBottomRightCorner_impl()
const
178 size_t nodesTopLeftCorner_impl()
const
180 return m_nely * (m_nelx + 1);
183 size_t nodesTopRightCorner_impl()
const
185 return m_nely * (m_nelx + 1) + m_nelx;
289 size_t nely = m_nhy.size();
290 size_t iy = (
nely - 1) / 2;
291 return m_startElem(
iy) + xt::arange<size_t>(m_layer_nelx(
iy));
302 size_t n = m_layer_nelx(
layer);
303 if (m_refine(
layer) != -1) {
306 return m_startElem(
layer) + xt::arange<size_t>(
n);
322 std::array<size_t, 2>
rows;
323 std::array<size_t, 2>
cols;
335 if (start_stop_cols.size() == 2) {
352 auto H = xt::cumsum(m_nhy);
355 yl = xt::argmax(
H >
rows[0])();
357 size_t yu = xt::argmax(
H >=
rows[1])();
358 size_t hx = std::max(m_nhx(
yl), m_nhx(
yu));
366 for (
size_t i =
yl;
i <=
yu; ++
i) {
368 size_t n = (
xu -
xl) *
hx / m_nhx(
i);
370 if (m_refine(
i) != -1) {
382 for (
size_t i =
yl;
i <=
yu; ++
i) {
384 size_t n = (
xu -
xl) *
hx / m_nhx(
i);
387 if (m_refine(
i) != -1) {
392 m_startElem(
i) +
xl *
h / m_nhx(
i) + xt::arange<size_t>(
n);
393 xt::view(
ret, xt::range(
N,
N +
n)) =
e;
414 size_t iy = xt::argmin(m_startElem <=
e)() - 1;
415 size_t nel = m_layer_nelx(
iy);
419 auto H = xt::cumsum(m_nhy);
421 if (2 *
size >=
H(
H.size() - 1)) {
422 return xt::arange<size_t>(this->
nelem());
426 size_t l = xt::argmax(
H > (
hy -
size - 1))();
427 size_t u = xt::argmax(
H >= (
hy +
size))();
434 size_t step = xt::amax(m_nhx)();
438 size_t dx = m_nhx(
u);
467 auto map = this->
roll(nroll);
468 return xt::view(map, xt::keep(
ret));
487 size_t iy = xt::argmin(m_startElem <=
e)() - 1;
488 size_t nel = m_layer_nelx(
iy);
492 size_t step = xt::amax(m_nhx)();
496 size_t dx = m_nhx(
iy);
524 auto H = xt::cumsum(m_nhy);
530 auto map = this->
roll(nroll);
531 return xt::view(map, xt::keep(
ret));
542 size_t nely =
static_cast<size_t>(m_nhy.size());
549 size_t shift =
n * (m_layer_nelx(
iy) / m_layer_nelx(0));
550 size_t nel = m_layer_nelx(
iy);
553 if (m_refine(
iy) != -1) {
554 shift =
n * (m_layer_nelx(
iy) / m_layer_nelx(0)) * 4;
555 nel = m_layer_nelx(
iy) * 4;
559 auto e = m_startElem(
iy) + xt::arange<size_t>(
nel);
560 xt::view(
ret, xt::range(m_startElem(
iy), m_startElem(
iy) +
nel)) = xt::roll(
e,
shift);
571 size_t nelx_impl()
const
573 return xt::amax(m_layer_nelx)();
576 size_t nely_impl()
const
578 return xt::sum(m_nhy)();
586 array_type::tensor<double, 2> coor_impl()
const
589 array_type::tensor<double, 2>
ret = xt::empty<double>({m_nnode, m_ndim});
593 size_t nely =
static_cast<size_t>(m_nhy.size());
597 array_type::tensor<double, 1>
y = xt::empty<double>({
nely + 1});
602 y(
iy) =
y(
iy - 1) + m_nhy(
iy - 1) * m_h;
608 for (
size_t iy = 0;; ++
iy) {
610 array_type::tensor<double, 1>
x = xt::linspace<double>(0.0, m_Lx, m_layer_nelx(
iy) + 1);
613 for (
size_t ix = 0;
ix < m_layer_nelx(
iy) + 1; ++
ix) {
620 if (
iy == (
nely - 1) / 2) {
625 if (m_refine(
iy) == 0) {
627 double dx = m_h *
static_cast<double>(m_nhx(
iy) / 3);
628 double dy = m_h *
static_cast<double>(m_nhy(
iy) / 2);
630 for (
size_t ix = 0;
ix < m_layer_nelx(
iy); ++
ix) {
631 for (
size_t j = 0;
j < 2; ++
j) {
644 array_type::tensor<double, 1>
x = xt::linspace<double>(0.0, m_Lx, m_layer_nelx(
iy) + 1);
647 if (m_refine(
iy) == 0) {
649 double dx = m_h *
static_cast<double>(m_nhx(
iy) / 3);
650 double dy = m_h *
static_cast<double>(m_nhy(
iy) / 2);
652 for (
size_t ix = 0;
ix < m_layer_nelx(
iy); ++
ix) {
653 for (
size_t j = 0;
j < 2; ++
j) {
662 for (
size_t ix = 0;
ix < m_layer_nelx(
iy) + 1; ++
ix) {
672 array_type::tensor<size_t, 2> conn_impl()
const
675 array_type::tensor<size_t, 2>
ret = xt::empty<size_t>({m_nelem, m_nne});
679 size_t nely =
static_cast<size_t>(m_nhy.size());
685 bot = m_startNode(
iy);
686 mid = m_startNode(
iy) + m_nnd(
iy);
687 top = m_startNode(
iy + 1);
690 if (m_refine(
iy) == -1) {
691 for (
size_t ix = 0;
ix < m_layer_nelx(
iy); ++
ix) {
701 else if (m_refine(
iy) == 0 &&
iy <= (
nely - 1) / 2) {
702 for (
size_t ix = 0;
ix < m_layer_nelx(
iy); ++
ix) {
731 else if (m_refine(
iy) == 0 &&
iy > (
nely - 1) / 2) {
732 for (
size_t ix = 0;
ix < m_layer_nelx(
iy); ++
ix) {
764 array_type::tensor<size_t, 1> nodesBottomEdge_impl()
const
766 return m_startNode(0) + xt::arange<size_t>(m_layer_nelx(0) + 1);
769 array_type::tensor<size_t, 1> nodesTopEdge_impl()
const
771 size_t nely = m_nhy.size();
772 return m_startNode(
nely) + xt::arange<size_t>(m_layer_nelx(
nely - 1) + 1);
775 array_type::tensor<size_t, 1> nodesLeftEdge_impl()
const
777 size_t nely = m_nhy.size();
779 array_type::tensor<size_t, 1>
ret = xt::empty<size_t>({
nely + 1});
782 size_t j = (
nely + 1) / 2;
783 size_t k = (
nely - 1) / 2;
786 xt::view(
ret, xt::range(
i,
j)) = xt::view(m_startNode, xt::range(
i,
j));
787 xt::view(
ret, xt::range(
k + 1,
l + 1)) = xt::view(m_startNode, xt::range(
k + 1,
l + 1));
792 array_type::tensor<size_t, 1> nodesRightEdge_impl()
const
794 size_t nely = m_nhy.size();
796 array_type::tensor<size_t, 1>
ret = xt::empty<size_t>({
nely + 1});
799 size_t j = (
nely + 1) / 2;
800 size_t k = (
nely - 1) / 2;
803 xt::view(
ret, xt::range(
i,
j)) =
804 xt::view(m_startNode, xt::range(
i,
j)) + xt::view(m_layer_nelx, xt::range(
i,
j));
806 xt::view(
ret, xt::range(
k + 1,
l + 1)) = xt::view(m_startNode, xt::range(
k + 1,
l + 1)) +
807 xt::view(m_layer_nelx, xt::range(
k,
l));
812 array_type::tensor<size_t, 1> nodesBottomOpenEdge_impl()
const
814 return m_startNode(0) + xt::arange<size_t>(1, m_layer_nelx(0));
817 array_type::tensor<size_t, 1> nodesTopOpenEdge_impl()
const
819 size_t nely = m_nhy.size();
821 return m_startNode(
nely) + xt::arange<size_t>(1, m_layer_nelx(
nely - 1));
824 array_type::tensor<size_t, 1> nodesLeftOpenEdge_impl()
const
826 size_t nely = m_nhy.size();
828 array_type::tensor<size_t, 1>
ret = xt::empty<size_t>({
nely - 1});
831 size_t j = (
nely + 1) / 2;
832 size_t k = (
nely - 1) / 2;
835 xt::view(
ret, xt::range(
i,
j - 1)) = xt::view(m_startNode, xt::range(
i + 1,
j));
836 xt::view(
ret, xt::range(
k,
l - 1)) = xt::view(m_startNode, xt::range(
k + 1,
l));
841 array_type::tensor<size_t, 1> nodesRightOpenEdge_impl()
const
843 size_t nely = m_nhy.size();
845 array_type::tensor<size_t, 1>
ret = xt::empty<size_t>({
nely - 1});
848 size_t j = (
nely + 1) / 2;
849 size_t k = (
nely - 1) / 2;
852 xt::view(
ret, xt::range(
i,
j - 1)) = xt::view(m_startNode, xt::range(
i + 1,
j)) +
853 xt::view(m_layer_nelx, xt::range(
i + 1,
j));
855 xt::view(
ret, xt::range(
k,
l - 1)) = xt::view(m_startNode, xt::range(
k + 1,
l)) +
856 xt::view(m_layer_nelx, xt::range(
k,
l - 1));
861 size_t nodesBottomLeftCorner_impl()
const
863 return m_startNode(0);
866 size_t nodesBottomRightCorner_impl()
const
868 return m_startNode(0) + m_layer_nelx(0);
871 size_t nodesTopLeftCorner_impl()
const
873 size_t nely = m_nhy.size();
874 return m_startNode(
nely);
877 size_t nodesTopRightCorner_impl()
const
879 size_t nely = m_nhy.size();
880 return m_startNode(
nely) + m_layer_nelx(
nely - 1);
889 array_type::tensor<size_t, 1> m_layer_nelx;
890 array_type::tensor<size_t, 1> m_nhx;
891 array_type::tensor<size_t, 1> m_nhy;
892 array_type::tensor<size_t, 1> m_nnd;
893 array_type::tensor<int, 1> m_refine;
894 array_type::tensor<size_t, 1> m_startElem;
895 array_type::tensor<size_t, 1> m_startNode;
908 m_Lx = m_h *
static_cast<double>(
nelx);
914 array_type::tensor<size_t, 1>
nhx = xt::ones<size_t>({
nely});
915 array_type::tensor<size_t, 1>
nhy = xt::ones<size_t>({
nely});
916 array_type::tensor<int, 1>
refine = -1 * xt::ones<int>({
nely});
927 if (
nfine % 2 == 0) {
961 auto vnhy = xt::view(
nhy, xt::range(
iy + 1,
_));
981 m_nhx = xt::empty<size_t>({
nely * 2 - 1});
982 m_nhy = xt::empty<size_t>({
nely * 2 - 1});
983 m_refine = xt::empty<int>({
nely * 2 - 1});
984 m_layer_nelx = xt::empty<size_t>({
nely * 2 - 1});
985 m_nnd = xt::empty<size_t>({
nely * 2});
986 m_startElem = xt::empty<size_t>({
nely * 2 - 1});
987 m_startNode = xt::empty<size_t>({
nely * 2});
1004 nely = m_nhx.size();
1008 m_layer_nelx(
iy) =
nelx / m_nhx(
iy);
1012 for (
size_t iy = 0;
iy < (
nely + 1) / 2; ++
iy) {
1013 m_nnd(
iy) = m_layer_nelx(
iy) + 1;
1016 m_nnd(
iy + 1) = m_layer_nelx(
iy) + 1;
1027 for (
size_t i = 0;
i < (
nely - 1) / 2; ++
i) {
1029 m_startElem(
i) = m_nelem;
1031 if (m_refine(
i) == 0) {
1032 m_nnode += (3 * m_layer_nelx(
i) + 1);
1035 m_nnode += (m_layer_nelx(
i) + 1);
1038 if (m_refine(
i) == 0) {
1039 m_nelem += (4 * m_layer_nelx(
i));
1042 m_nelem += (m_layer_nelx(
i));
1045 m_startNode(
i + 1) = m_nnode;
1051 m_startElem(
i) = m_nelem;
1053 if (m_refine(
i) == 0) {
1054 m_nnode += (5 * m_layer_nelx(
i) + 1);
1057 m_nnode += (m_layer_nelx(
i) + 1);
1060 if (m_refine(
i) == 0) {
1061 m_nelem += (4 * m_layer_nelx(
i));
1064 m_nelem += (m_layer_nelx(
i));
1067 m_startNode(
i + 1) = m_nnode;
1070 m_nnode += m_layer_nelx(
nely - 1) + 1;
1076 template <
class C,
class E>
1077 void init_by_mapping(
const C&
coor,
const E&
conn)
1087 if (
conn.shape(0) == 1) {
1115 auto dx = xt::view(
coor, xt::keep(
n1), 0) - xt::view(
coor, xt::keep(
n0), 0);
1116 auto dy = xt::view(
coor, xt::keep(
n2), 1) - xt::view(
coor, xt::keep(
n1), 1);
1117 auto hx = xt::amin(
dx)();
1118 auto hy = xt::amin(
dy)();
1157 : m_coarse(
mesh), m_nx(
nx), m_ny(
ny)
1164 m_coarse2fine = xt::empty<size_t>({m_coarse.
nelem(),
nx *
ny});
1168 xt::view(m_coarse2fine,
elmat_coarse(
i,
j), xt::all()) = xt::flatten(xt::view(
1219 return m_coarse2fine;
1249 return m_coarse2fine;
1260 template <
class T,
size_t rank>
1265 std::array<size_t, rank>
shape;
1266 std::copy(data.shape().cbegin(), data.shape().cend(), &
shape[0]);
1267 shape[0] = m_coarse2fine.shape(0);
1271 for (
size_t i = 0;
i < m_coarse2fine.shape(0); ++
i) {
1272 auto e = xt::view(m_coarse2fine,
i, xt::all());
1273 auto d = xt::view(data, xt::keep(
e));
1274 xt::view(
ret,
i) = xt::mean(
d, 0);
1290 template <
class T,
size_t rank,
class S>
1298 std::array<size_t, rank>
shape;
1299 std::copy(data.shape().cbegin(), data.shape().cend(), &
shape[0]);
1300 shape[0] = m_coarse2fine.shape(0);
1304 for (
size_t i = 0;
i < m_coarse2fine.shape(0); ++
i) {
1305 auto e = xt::view(m_coarse2fine,
i, xt::all());
1308 xt::view(
ret,
i) = xt::average(
d, w, {0});
1326 template <
class T,
size_t rank>
1331 std::array<size_t, rank>
shape;
1332 std::copy(data.shape().cbegin(), data.shape().cend(), &
shape[0]);
1333 shape[0] = m_coarse2fine.size();
1337 for (
size_t e = 0;
e < m_coarse2fine.shape(0); ++
e) {
1338 for (
size_t i = 0;
i < m_coarse2fine.shape(1); ++
i) {
1339 xt::view(
ret, m_coarse2fine(
e,
i)) = xt::view(data,
e);
1375 xt::amax(m_finelayer.m_layer_nelx)(), xt::sum(m_finelayer.m_nhy)(), m_finelayer.m_h
1383 m_elem_regular.resize(m_finelayer.m_nelem);
1384 m_frac_regular.resize(m_finelayer.m_nelem);
1397 xt::concatenate(xt::xtuple(xt::zeros<size_t>({1}), xt::cumsum(
nhy)));
1400 size_t nely =
nhy.size();
1403 for (
size_t iy = 0;
iy < nely; ++
iy) {
1410 if (m_finelayer.m_refine(
iy) == -1) {
1415 for (
size_t ix = 0;
ix < nelx(
iy); ++
ix) {
1423 m_elem_regular[
el_old(
ix)].push_back(
i);
1424 m_frac_regular[
el_old(
ix)].push_back(1.0);
1432 else if (m_finelayer.m_refine(
iy) == 0 &&
iy <= (nely - 1) / 2) {
1436 start(
iy) + xt::arange<size_t>(nelx(
iy) * 4ul).reshape({-1, 4});
1439 for (
size_t ix = 0;
ix < nelx(
iy); ++
ix) {
1447 for (
size_t j = 0;
j <
nhy(
iy) / 2; ++
j) {
1450 m_elem_regular[
el_old(
ix, 0)].push_back(
e(0));
1451 m_frac_regular[
el_old(
ix, 0)].push_back(0.5);
1453 for (
size_t k = 1;
k <
e.size() - 1; ++
k) {
1454 m_elem_regular[
el_old(
ix, 0)].push_back(
e(
k));
1455 m_frac_regular[
el_old(
ix, 0)].push_back(1.0);
1458 m_elem_regular[
el_old(
ix, 0)].push_back(
e(
e.size() - 1));
1459 m_frac_regular[
el_old(
ix, 0)].push_back(0.5);
1472 m_elem_regular[
el_old(
ix, 2)].push_back(
i);
1473 m_frac_regular[
el_old(
ix, 2)].push_back(1.0);
1480 for (
size_t j = 0;
j <
nhy(
iy) / 2; ++
j) {
1481 auto e = xt::view(
block,
j, xt::range(0,
j + 1));
1483 for (
size_t k = 0;
k <
e.size() - 1; ++
k) {
1484 m_elem_regular[
el_old(
ix, 3)].push_back(
e(
k));
1485 m_frac_regular[
el_old(
ix, 3)].push_back(1.0);
1488 m_elem_regular[
el_old(
ix, 3)].push_back(
e(
e.size() - 1));
1489 m_frac_regular[
el_old(
ix, 3)].push_back(0.5);
1501 m_elem_regular[
el_old(
ix, 3)].push_back(
i);
1502 m_frac_regular[
el_old(
ix, 3)].push_back(1.0);
1510 for (
size_t j = 0;
j <
nhy(
iy) / 2; ++
j) {
1513 m_elem_regular[
el_old(
ix, 1)].push_back(
e(0));
1514 m_frac_regular[
el_old(
ix, 1)].push_back(0.5);
1516 for (
size_t k = 1;
k <
e.size(); ++
k) {
1517 m_elem_regular[
el_old(
ix, 1)].push_back(
e(
k));
1518 m_frac_regular[
el_old(
ix, 1)].push_back(1.0);
1531 m_elem_regular[
el_old(
ix, 1)].push_back(
i);
1532 m_frac_regular[
el_old(
ix, 1)].push_back(1.0);
1540 else if (m_finelayer.m_refine(
iy) == 0 &&
iy > (nely - 1) / 2) {
1544 start(
iy) + xt::arange<size_t>(nelx(
iy) * 4ul).reshape({-1, 4});
1547 for (
size_t ix = 0;
ix < nelx(
iy); ++
ix) {
1555 for (
size_t j = 0;
j <
nhy(
iy) / 2; ++
j) {
1559 xt::range(1 *
nhx(
iy) / 3 -
j - 1, 2 *
nhx(
iy) / 3 +
j + 1)
1562 m_elem_regular[
el_old(
ix, 3)].push_back(
e(0));
1563 m_frac_regular[
el_old(
ix, 3)].push_back(0.5);
1565 for (
size_t k = 1;
k <
e.size() - 1; ++
k) {
1566 m_elem_regular[
el_old(
ix, 3)].push_back(
e(
k));
1567 m_frac_regular[
el_old(
ix, 3)].push_back(1.0);
1570 m_elem_regular[
el_old(
ix, 3)].push_back(
e(
e.size() - 1));
1571 m_frac_regular[
el_old(
ix, 3)].push_back(0.5);
1579 xt::range(0,
nhy(
iy) / 2),
1584 m_elem_regular[
el_old(
ix, 1)].push_back(
i);
1585 m_frac_regular[
el_old(
ix, 1)].push_back(1.0);
1595 xt::range(0,
nhy(
iy) / 2),
1600 m_elem_regular[
el_old(
ix, 0)].push_back(
i);
1601 m_frac_regular[
el_old(
ix, 0)].push_back(1.0);
1606 for (
size_t j = 0;
j <
nhy(
iy) / 2; ++
j) {
1610 for (
size_t k = 0;
k <
e.size() - 1; ++
k) {
1611 m_elem_regular[
el_old(
ix, 0)].push_back(
e(
k));
1612 m_frac_regular[
el_old(
ix, 0)].push_back(1.0);
1615 m_elem_regular[
el_old(
ix, 0)].push_back(
e(
e.size() - 1));
1616 m_frac_regular[
el_old(
ix, 0)].push_back(0.5);
1626 xt::range(0,
nhy(
iy) / 2),
1631 m_elem_regular[
el_old(
ix, 2)].push_back(
i);
1632 m_frac_regular[
el_old(
ix, 2)].push_back(1.0);
1637 for (
size_t j = 0;
j <
nhy(
iy) / 2; ++
j) {
1642 m_elem_regular[
el_old(
ix, 2)].push_back(
e(0));
1643 m_frac_regular[
el_old(
ix, 2)].push_back(0.5);
1645 for (
size_t k = 1;
k <
e.size(); ++
k) {
1646 m_elem_regular[
el_old(
ix, 2)].push_back(
e(
k));
1647 m_frac_regular[
el_old(
ix, 2)].push_back(1.0);
1685 std::vector<std::vector<size_t>>
map()
const
1687 return m_elem_regular;
1697 return m_frac_regular;
1732 std::vector<std::vector<size_t>>
getMap()
const
1734 return m_elem_regular;
1745 return m_frac_regular;
1761 template <
class T,
size_t rank>
1766 std::array<size_t, rank>
shape;
1767 std::copy(data.shape().cbegin(), data.shape().cend(), &
shape[0]);
1772 for (
size_t e = 0;
e < m_finelayer.
nelem(); ++
e) {
1773 for (
size_t i = 0;
i < m_elem_regular[
e].size(); ++
i) {
1774 xt::view(
ret, m_elem_regular[
e][
i]) += m_frac_regular[
e][
i] * xt::view(data,
e);
1784 std::vector<std::vector<size_t>> m_elem_regular;
1785 std::vector<std::vector<double>> m_frac_regular;
Mesh with fine middle layer, and coarser elements towards the top and bottom.
const array_type::tensor< size_t, 1 > & elemrow_nhy() const
Edge size in y-direction of a block, in units of h, per row of blocks.
array_type::tensor< size_t, 1 > roll(size_t n)
Mapping to 'roll' periodically in the x-direction,.
array_type::tensor< size_t, 1 > elementsLayer(size_t layer) const
Elements along a layer.
array_type::tensor< size_t, 1 > elementgrid_leftright(size_t e, size_t left, size_t right, bool periodic=true)
Select region of elements from 'matrix' of element numbers around an element: left/right from element...
array_type::tensor< size_t, 1 > elementgrid_around_ravel(size_t e, size_t size, bool periodic=true)
Select region of elements from 'matrix' of element numbers around an element: square box with edge-si...
FineLayer(const C &coor, const E &conn)
Reconstruct class for given coordinates / connectivity.
FineLayer(size_t nelx, size_t nely, double h=1.0, size_t nfine=1)
Constructor.
const array_type::tensor< int, 1 > & elemrow_type() const
Per row of blocks: -1: normal layer 0: transition layer to match coarse and finer element on the prev...
const array_type::tensor< size_t, 1 > & elemrow_nhx() const
Edge size in x-direction of a block, in units of h, per row of blocks.
array_type::tensor< size_t, 1 > elementgrid_ravel(std::vector< size_t > start_stop_rows, std::vector< size_t > start_stop_cols) const
Select region of elements from 'matrix' of element numbers.
const array_type::tensor< size_t, 1 > & elemrow_nelem() const
Number of elements per row of blocks.
array_type::tensor< size_t, 1 > elementsMiddleLayer() const
Elements in the middle (fine) layer.
Map a FineLayer mesh to a Regular mesh.
array_type::tensor< T, rank > mapToRegular(const array_type::tensor< T, rank > &data) const
Map element quantities to Regular.
std::vector< std::vector< double > > getMapFraction() const
To overlap fraction for each item in the mapping in getMap().
GooseFEM::Mesh::Quad4::FineLayer fineLayerMesh() const
Obtain the FineLayer mesh (copy of the mesh passed to the constructor).
std::vector< std::vector< size_t > > map() const
Get element-mapping: elements of the Regular mesh per element of the FineLayer mesh.
GooseFEM::Mesh::Quad4::Regular regularMesh() const
Obtain the Regular mesh.
GooseFEM::Mesh::Quad4::FineLayer getFineLayerMesh() const
Obtain the FineLayer mesh (copy of the mesh passed to the constructor).
GooseFEM::Mesh::Quad4::Regular getRegularMesh() const
Obtain the Regular mesh.
std::vector< std::vector< double > > mapFraction() const
To overlap fraction for each item in the mapping in map().
std::vector< std::vector< size_t > > getMap() const
Get element-mapping: elements of the Regular mesh per element of the FineLayer mesh.
FineLayer2Regular(const GooseFEM::Mesh::Quad4::FineLayer &mesh)
Constructors.
Refine a Regular mesh: subdivide elements in several smaller elements.
GooseFEM::Mesh::Quad4::Regular getCoarseMesh() const
Obtain the coarse mesh (copy of the mesh passed to the constructor).
const array_type::tensor< size_t, 2 > & getMap() const
Get element-mapping: elements of the fine mesh per element of the coarse mesh.
array_type::tensor< T, rank > mapToFine(const array_type::tensor< T, rank > &data) const
Map element quantities to the fine mesh.
GooseFEM::Mesh::Quad4::Regular fineMesh() const
Obtain the fine mesh.
GooseFEM::Mesh::Quad4::Regular coarseMesh() const
Obtain the coarse mesh (copy of the mesh passed to the constructor).
size_t ny() const
For each coarse element: number of fine elements in y-direction.
array_type::tensor< T, rank > meanToCoarse(const array_type::tensor< T, rank > &data) const
Compute the mean of the quantity define on the fine mesh when mapped on the coarse mesh.
RefineRegular(const GooseFEM::Mesh::Quad4::Regular &mesh, size_t nx, size_t ny)
Constructor.
size_t nx() const
For each coarse element: number of fine elements in x-direction.
array_type::tensor< T, rank > averageToCoarse(const array_type::tensor< T, rank > &data, const array_type::tensor< S, rank > &weights) const
Compute the average of the quantity define on the fine mesh when mapped on the coarse mesh.
GooseFEM::Mesh::Quad4::Regular getFineMesh() const
Obtain the fine mesh.
const array_type::tensor< size_t, 2 > & map() const
Get element-mapping: elements of the fine mesh per element of the coarse mesh.
Regular mesh: equi-sized elements.
Regular(size_t nelx, size_t nely, double h=1.0)
Constructor.
array_type::tensor< size_t, 2 > elementgrid() const
Element numbers as 'matrix'.
CRTP base class for regular meshes in 2d.
CRTP base class for regular meshes.
auto nely() const
Number of elements in y-direction == height of the mesh, in units of h,.
auto coor() const
Nodal coordinates [nnode, ndim].
auto h() const
Linear edge size of one 'block'.
auto nelx() const
Number of elements in x-direction == width of the mesh in units of h.
auto nelem() const
Number of elements.
auto conn() const
Connectivity [nelem, nne].
#define GOOSEFEM_ASSERT(expr)
All assertions are implementation as::
#define GOOSEFEM_WIP_ASSERT(expr)
Assertion that concerns temporary implementation limitations.
#define GOOSEFEM_CHECK(expr)
Assertion that cannot be switched off.
ElementType
Enumerator for element-types.
@ Quad4
Quadrilateral: 4-noded element in 2-d.
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Toolbox to perform finite element computations.
auto AsTensor(const T &arg, const S &shape)
"Broadcast" a scalar stored in an array (e.g.