8 #include "element-families.h"
10 #include "precompute.h"
16 #include <xtensor/xtensor.hpp>
17 #include <xtensor/xview.hpp>
18 #include <xtl/xspan.hpp>
39 std::tuple<std::array<std::vector<xt::xtensor<double, 2>>, 4>,
40 std::array<std::vector<xt::xtensor<double, 3>>, 4>>
42 const std::array<std::vector<xt::xtensor<double, 3>>, 4>& M,
43 int tdim,
int value_size);
224 const xt::xtensor<double, 2>&
wcoeffs,
225 const std::array<std::vector<xt::xtensor<double, 2>>, 4>&
x,
226 const std::array<std::vector<xt::xtensor<double, 3>>, 4>&
M,
230 std::vector<std::tuple<std::vector<FiniteElement>, std::vector<int>>>
238 const xt::xtensor<double, 2>&
wcoeffs,
239 const std::array<std::vector<xt::xtensor<double, 2>>, 4>&
x,
240 const std::array<std::vector<xt::xtensor<double, 3>>, 4>&
M,
243 std::vector<std::tuple<std::vector<FiniteElement>, std::vector<int>>>
251 const xt::xtensor<double, 2>&
wcoeffs,
252 const std::array<std::vector<xt::xtensor<double, 2>>, 4>&
x,
253 const std::array<std::vector<xt::xtensor<double, 3>>, 4>&
M,
256 std::vector<std::tuple<std::vector<FiniteElement>, std::vector<int>>>
264 const xt::xtensor<double, 2>&
wcoeffs,
265 const std::array<std::vector<xt::xtensor<double, 2>>, 4>&
x,
266 const std::array<std::vector<xt::xtensor<double, 3>>, 4>&
M,
269 std::vector<std::tuple<std::vector<FiniteElement>, std::vector<int>>>
304 std::size_t num_points)
const;
327 xt::xtensor<double, 4>
tabulate(
int nd,
328 const xt::xtensor<double, 2>&
x)
const;
355 void tabulate(
int nd,
const xt::xtensor<double, 2>&
x,
356 xt::xtensor<double, 4>& basis)
const;
429 xt::xtensor<double, 3>
push_forward(
const xt::xtensor<double, 3>& U,
430 const xt::xtensor<double, 3>& J,
431 const xtl::span<const double>& detJ,
432 const xt::xtensor<double, 3>& K)
const;
440 xt::xtensor<double, 3>
pull_back(
const xt::xtensor<double, 3>& u,
441 const xt::xtensor<double, 3>& J,
442 const xtl::span<const double>& detJ,
443 const xt::xtensor<double, 3>& K)
const;
476 template <
typename O,
typename P,
typename Q,
typename R>
477 std::function<void(O&,
const P&,
const Q&,
double,
const R&)>
map_fn()
const
481 case maps::type::identity:
482 return [](O& u,
const P& U,
const Q&, double,
const R&) { u.assign(U); };
483 case maps::type::L2Piola:
484 return [](O& u,
const P& U,
const Q& J,
double detJ,
const R& K)
486 case maps::type::covariantPiola:
487 return [](O& u,
const P& U,
const Q& J,
double detJ,
const R& K)
489 case maps::type::contravariantPiola:
490 return [](O& u,
const P& U,
const Q& J,
double detJ,
const R& K)
492 case maps::type::doubleCovariantPiola:
493 return [](O& u,
const P& U,
const Q& J,
double detJ,
const R& K)
495 case maps::type::doubleContravariantPiola:
496 return [](O& u,
const P& U,
const Q& J,
double detJ,
const R& K)
499 throw std::runtime_error(
"Map not implemented");
530 const std::vector<std::vector<std::vector<int>>>&
entity_dofs()
const;
633 std::uint32_t cell_info)
const;
643 std::uint32_t cell_info)
const;
653 template <
typename T>
655 std::uint32_t cell_info)
const;
665 template <
typename T>
668 std::uint32_t cell_info)
const;
678 template <
typename T>
680 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const;
690 template <
typename T>
693 std::uint32_t cell_info)
const;
703 template <
typename T>
706 std::uint32_t cell_info)
const;
716 template <
typename T>
718 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const;
728 template <
typename T>
730 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const;
740 template <
typename T>
742 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const;
748 const xt::xtensor<double, 2>&
points()
const;
839 const xt::xtensor<double, 2>&
wcoeffs()
const;
844 const std::array<std::vector<xt::xtensor<double, 2>>, 4>&
x()
const;
878 const std::array<std::vector<xt::xtensor<double, 3>>, 4>&
M()
const;
903 std::vector<std::tuple<std::vector<FiniteElement>, std::vector<int>>>
915 std::size_t _cell_tdim;
918 std::vector<std::vector<cell::type>> _cell_subentity_types;
936 int _highest_complete_degree;
939 std::vector<int> _value_shape;
949 xt::xtensor<double, 2> _coeffs;
957 std::vector<std::vector<int>> _num_edofs;
961 std::vector<std::vector<int>> _num_e_closure_dofs;
964 std::vector<std::vector<std::vector<int>>> _edofs;
967 std::vector<std::vector<std::vector<int>>> _e_closure_dofs;
970 std::map<cell::type, xt::xtensor<double, 3>> _entity_transformations;
977 xt::xtensor<double, 2> _points;
981 std::array<std::vector<xt::xtensor<double, 2>>, 4> _x;
984 xt::xtensor<double, 2> _matM;
988 bool _dof_transformations_are_permutations;
991 bool _dof_transformations_are_identity;
996 std::map<cell::type, std::vector<std::vector<std::size_t>>> _eperm;
1001 std::map<cell::type, std::vector<std::vector<std::size_t>>> _eperm_rev;
1005 std::vector<std::tuple<std::vector<std::size_t>, std::vector<double>,
1006 xt::xtensor<double, 2>>>>
1011 std::vector<std::tuple<std::vector<std::size_t>, std::vector<double>,
1012 xt::xtensor<double, 2>>>>
1017 std::vector<std::tuple<std::vector<std::size_t>, std::vector<double>,
1018 xt::xtensor<double, 2>>>>
1023 std::vector<std::tuple<std::vector<std::size_t>, std::vector<double>,
1024 xt::xtensor<double, 2>>>>
1029 bool _discontinuous;
1032 xt::xtensor<double, 2> _dual_matrix;
1039 std::vector<std::tuple<std::vector<FiniteElement>, std::vector<int>>>
1043 bool _interpolation_is_identity;
1047 xt::xtensor<double, 2> _wcoeffs;
1050 std::array<std::vector<xt::xtensor<double, 3>>, 4> _M;
1074 cell::type cell_type,
const std::vector<std::size_t>& value_shape,
1075 const xt::xtensor<double, 2>& wcoeffs,
1076 const std::array<std::vector<xt::xtensor<double, 2>>, 4>& x,
1077 const std::array<std::vector<xt::xtensor<double, 3>>, 4>& M,
1078 maps::type map_type,
bool discontinuous,
int highest_complete_degree,
1079 int highest_degree);
1092 bool discontinuous);
1119 bool discontinuous);
1132 int degree,
bool discontinuous);
1181 template <
typename T>
1184 std::uint32_t cell_info)
const
1186 if (_dof_transformations_are_identity)
1189 if (_cell_tdim >= 2)
1193 int face_start = _cell_tdim == 3 ? 3 * _num_edofs[2].size() : 0;
1195 = std::accumulate(_num_edofs[0].cbegin(), _num_edofs[0].cend(), 0);
1198 for (std::size_t e = 0; e < _num_edofs[1].size(); ++e)
1201 if (cell_info >> (face_start + e) & 1)
1203 dofstart, block_size);
1204 dofstart += _num_edofs[1][e];
1207 if (_cell_tdim == 3)
1210 for (std::size_t f = 0; f < _num_edofs[2].size(); ++f)
1213 if (cell_info >> (3 * f) & 1)
1215 data, dofstart, block_size);
1218 for (std::uint32_t r = 0; r < (cell_info >> (3 * f + 1) & 3); ++r)
1220 data, dofstart, block_size);
1221 dofstart += _num_edofs[2][f];
1227 template <
typename T>
1229 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const
1231 if (_dof_transformations_are_identity)
1234 if (_cell_tdim >= 2)
1238 int face_start = _cell_tdim == 3 ? 3 * _num_edofs[2].size() : 0;
1240 = std::accumulate(_num_edofs[0].cbegin(), _num_edofs[0].cend(), 0);
1243 for (std::size_t e = 0; e < _num_edofs[1].size(); ++e)
1246 if (cell_info >> (face_start + e) & 1)
1248 dofstart, block_size);
1249 dofstart += _num_edofs[1][e];
1252 if (_cell_tdim == 3)
1255 for (std::size_t f = 0; f < _num_edofs[2].size(); ++f)
1258 for (std::uint32_t r = 0; r < (cell_info >> (3 * f + 1) & 3); ++r)
1260 data, dofstart, block_size);
1262 if (cell_info >> (3 * f) & 1)
1264 data, dofstart, block_size);
1265 dofstart += _num_edofs[2][f];
1271 template <
typename T>
1273 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const
1275 if (_dof_transformations_are_identity)
1278 if (_cell_tdim >= 2)
1282 int face_start = _cell_tdim == 3 ? 3 * _num_edofs[2].size() : 0;
1284 = std::accumulate(_num_edofs[0].cbegin(), _num_edofs[0].cend(), 0);
1287 for (std::size_t e = 0; e < _num_edofs[1].size(); ++e)
1290 if (cell_info >> (face_start + e) & 1)
1292 dofstart, block_size);
1293 dofstart += _num_edofs[1][e];
1296 if (_cell_tdim == 3)
1299 for (std::size_t f = 0; f < _num_edofs[2].size(); ++f)
1302 if (cell_info >> (3 * f) & 1)
1304 _etrans_invT.at(_cell_subentity_types[2][f])[1], data, dofstart,
1308 for (std::uint32_t r = 0; r < (cell_info >> (3 * f + 1) & 3); ++r)
1310 _etrans_invT.at(_cell_subentity_types[2][f])[0], data, dofstart,
1312 dofstart += _num_edofs[2][f];
1318 template <
typename T>
1320 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const
1322 if (_dof_transformations_are_identity)
1325 if (_cell_tdim >= 2)
1329 int face_start = _cell_tdim == 3 ? 3 * _num_edofs[2].size() : 0;
1331 = std::accumulate(_num_edofs[0].cbegin(), _num_edofs[0].cend(), 0);
1334 for (std::size_t e = 0; e < _num_edofs[1].size(); ++e)
1337 if (cell_info >> (face_start + e) & 1)
1339 dofstart, block_size);
1340 dofstart += _num_edofs[1][e];
1343 if (_cell_tdim == 3)
1346 for (std::size_t f = 0; f < _num_edofs[2].size(); ++f)
1349 for (std::uint32_t r = 0; r < (cell_info >> (3 * f + 1) & 3); ++r)
1351 _etrans_inv.at(_cell_subentity_types[2][f])[0], data, dofstart,
1354 if (cell_info >> (3 * f) & 1)
1356 _etrans_inv.at(_cell_subentity_types[2][f])[1], data, dofstart,
1358 dofstart += _num_edofs[2][f];
1364 template <
typename T>
1366 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const
1368 if (_dof_transformations_are_identity)
1371 if (_cell_tdim >= 2)
1375 int face_start = _cell_tdim == 3 ? 3 * _num_edofs[2].size() : 0;
1377 = std::accumulate(_num_edofs[0].cbegin(), _num_edofs[0].cend(), 0);
1380 for (std::size_t e = 0; e < _num_edofs[1].size(); ++e)
1383 if (cell_info >> (face_start + e) & 1)
1385 _etrans.at(cell::type::interval)[0], data, dofstart, block_size);
1386 dofstart += _num_edofs[1][e];
1389 if (_cell_tdim == 3)
1392 for (std::size_t f = 0; f < _num_edofs[2].size(); ++f)
1395 if (cell_info >> (3 * f) & 1)
1397 _etrans.at(_cell_subentity_types[2][f])[1], data, dofstart,
1401 for (std::uint32_t r = 0; r < (cell_info >> (3 * f + 1) & 3); ++r)
1403 _etrans.at(_cell_subentity_types[2][f])[0], data, dofstart,
1405 dofstart += _num_edofs[2][f];
1411 template <
typename T>
1413 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const
1415 if (_dof_transformations_are_identity)
1418 if (_cell_tdim >= 2)
1422 int face_start = _cell_tdim == 3 ? 3 * _num_edofs[2].size() : 0;
1424 = std::accumulate(_num_edofs[0].cbegin(), _num_edofs[0].cend(), 0);
1427 for (std::size_t e = 0; e < _num_edofs[1].size(); ++e)
1430 if (cell_info >> (face_start + e) & 1)
1432 _etrans_invT.at(cell::type::interval)[0], data, dofstart,
1434 dofstart += _num_edofs[1][e];
1437 if (_cell_tdim == 3)
1440 for (std::size_t f = 0; f < _num_edofs[2].size(); ++f)
1443 if (cell_info >> (3 * f) & 1)
1445 _etrans_invT.at(_cell_subentity_types[2][f])[1], data, dofstart,
1449 for (std::uint32_t r = 0; r < (cell_info >> (3 * f + 1) & 3); ++r)
1451 _etrans_invT.at(_cell_subentity_types[2][f])[0], data, dofstart,
1453 dofstart += _num_edofs[2][f];
1459 template <
typename T>
1461 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const
1463 if (_dof_transformations_are_identity)
1466 if (_cell_tdim >= 2)
1470 int face_start = _cell_tdim == 3 ? 3 * _num_edofs[2].size() : 0;
1472 = std::accumulate(_num_edofs[0].cbegin(), _num_edofs[0].cend(), 0);
1475 for (std::size_t e = 0; e < _num_edofs[1].size(); ++e)
1478 if (cell_info >> (face_start + e) & 1)
1480 _etransT.at(cell::type::interval)[0], data, dofstart, block_size);
1481 dofstart += _num_edofs[1][e];
1484 if (_cell_tdim == 3)
1487 for (std::size_t f = 0; f < _num_edofs[2].size(); ++f)
1490 for (std::uint32_t r = 0; r < (cell_info >> (3 * f + 1) & 3); ++r)
1492 _etransT.at(_cell_subentity_types[2][f])[0], data, dofstart,
1496 if (cell_info >> (3 * f) & 1)
1498 _etransT.at(_cell_subentity_types[2][f])[1], data, dofstart,
1501 dofstart += _num_edofs[2][f];
1507 template <
typename T>
1509 const xtl::span<T>& data,
int block_size, std::uint32_t cell_info)
const
1511 if (_dof_transformations_are_identity)
1514 if (_cell_tdim >= 2)
1518 int face_start = _cell_tdim == 3 ? 3 * _num_edofs[2].size() : 0;
1520 = std::accumulate(_num_edofs[0].cbegin(), _num_edofs[0].cend(), 0);
1523 for (std::size_t e = 0; e < _num_edofs[1].size(); ++e)
1526 if (cell_info >> (face_start + e) & 1)
1528 _etrans_inv.at(cell::type::interval)[0], data, dofstart,
1530 dofstart += _num_edofs[1][e];
1533 if (_cell_tdim == 3)
1536 for (std::size_t f = 0; f < _num_edofs[2].size(); ++f)
1539 for (std::uint32_t r = 0; r < (cell_info >> (3 * f + 1) & 3); ++r)
1541 _etrans_inv.at(_cell_subentity_types[2][f])[0], data, dofstart,
1545 if (cell_info >> (3 * f) & 1)
1547 _etrans_inv.at(_cell_subentity_types[2][f])[1], data, dofstart,
1550 dofstart += _num_edofs[2][f];