41#define GENERATE_EXPR_SEQ (curl)(div)(grad)(hess)(jac)(lapl)
47#define GENERATE_IEXPR_SEQ (icurl)(idiv)(igrad)(ihess)(ijac)(ilapl)
50using namespace literals;
51using utils::operator+;
182 public BSplinePatch<real_t, GeoDim, sizeof...(Degrees)> {
250 template <
typename other_t>
381 throw std::runtime_error(
"Invalid number of coefficients");
388 .to(
options.requires_grad(
false))
389 .requires_grad_(
options.requires_grad());
422 template <
typename other_t>
435 .to(
options.requires_grad(
false))
436 .requires_grad_(
options.requires_grad());
442 .to(
options.requires_grad(
false))
443 .requires_grad_(
options.requires_grad());
459 inline static constexpr const std::array<short_t, parDim_> &
628 template <std::size_t...
Is>
629 inline torch::Tensor
as_tensor_(std::index_sequence<Is...>)
const noexcept {
638 return as_tensor_(std::make_index_sequence<geoDim_>{});
645 template <std::size_t...
Is>
648 const torch::Tensor &
tensor)
noexcept {
760 torch::IntArrayRef
sizes)
const override {
776 torch::IntArrayRef
sizes)
const override {
796 return torch::matmul(
859 template <deriv deriv = deriv::func,
bool memory_optimized = false>
860 inline auto eval(
const torch::Tensor &
xi)
const {
864 throw std::runtime_error(
"Invalid parametric dimension");
867 template <deriv deriv = deriv::func,
bool memory_optimized = false>
888 template <deriv deriv = deriv::func,
bool memory_optimized = false>
913 template <deriv deriv = deriv::func,
bool memory_optimized = false>
941 throw std::runtime_error(
942 "Memory-optimized evaluation requires single-valued coefficient");
953 return torch::matmul(
959 return torch::matmul(
978 if (
coeffs(0).dim() > 1) {
994 .
view({-1,
xi[0].numel()}))
1022 return torch::zeros_like(
coeffs_[0]).to(torch::kInt64);
1054 template <
bool memory_optimized = false>
1057 return torch::zeros_like(
coeffs_[0]).to(torch::kInt64);
1063 template <
bool memory_optimized = false>
1066 using utils::operator-;
1069 return torch::zeros_like(
coeffs_[0]).to(torch::kInt64);
1070 else if constexpr (
parDim_ == 1)
1074 return utils::VSlice<memory_optimized>(
1076 utils::make_array<int64_t>(-
degrees_),
1077 utils::make_array<int64_t, parDim_>(1),
1092 template <deriv deriv = deriv::func,
bool memory_optimized = false>
1096 return torch::ones_like(
coeffs_[0]);
1098 return torch::zeros_like(
coeffs_[0]);
1103 template <deriv deriv = deriv::func,
bool memory_optimized = false>
1107 return torch::ones_like(
coeffs_[0]);
1109 return torch::zeros_like(
coeffs_[0]);
1127 template <deriv deriv = deriv::func,
bool memory_optimized = false>
1132 return torch::ones_like(
coeffs_[0]);
1134 return torch::zeros_like(
coeffs_[0]);
1140 template <deriv deriv = deriv::func,
bool memory_optimized = false>
1147 return torch::ones_like(
coeffs_[0]);
1149 return torch::zeros_like(
coeffs_[0]);
1163 this]<std::size_t...
Is>(std::index_sequence<
Is...>) {
1175 return basfunc_(std::make_index_sequence<parDim_>{});
1189 auto basfunc_ = [&,
this]<std::size_t...
Is>(
1190 std::index_sequence<
Is...>) {
1200 10>(
xi[
Is].flatten(),
1215 std::array<real_t, geoDim_>(
const std::array<real_t, parDim_> &)>
1217 static_assert(
parDim_ <= 4,
"Unsupported parametric dimension");
1227 else if constexpr (
parDim_ == 1) {
1228#pragma omp parallel for
1231 std::array<real_t, parDim_>{
i / real_t(
ncoeffs_[0] - 1)});
1238 else if constexpr (
parDim_ == 2) {
1239#pragma omp parallel for collapse(2)
1251 else if constexpr (
parDim_ == 3) {
1252#pragma omp parallel for collapse(3)
1268 else if constexpr (
parDim_ == 4) {
1269#pragma omp parallel for collapse(4)
1287 throw std::runtime_error(
"Unsupported parametric dimension");
1293 template <std::
size_t N>
1296 std::array<real_t, N>(
const std::array<real_t, parDim_> &)>
1298 std::array<short_t, N> dims) {
1299 static_assert(
parDim_ <= 4,
"Unsupported parametric dimension");
1304 for (std::size_t
d = 0;
d <
N; ++
d)
1309 else if constexpr (
parDim_ == 1) {
1310#pragma omp parallel for
1313 std::array<real_t, parDim_>{
i / real_t(
ncoeffs_[0] - 1)});
1314 for (std::size_t
d = 0;
d <
N; ++
d)
1320 else if constexpr (
parDim_ == 2) {
1321#pragma omp parallel for collapse(2)
1326 for (std::size_t
d = 0;
d <
N; ++
d)
1333 else if constexpr (
parDim_ == 3) {
1334#pragma omp parallel for collapse(3)
1341 for (std::size_t
d = 0;
d <
N; ++
d)
1350 else if constexpr (
parDim_ == 4) {
1351#pragma omp parallel for collapse(4)
1359 for (std::size_t
d = 0;
d <
N; ++
d)
1369 throw std::runtime_error(
"Unsupported parametric dimension");
1376 nlohmann::json
json;
1390 return ::iganet::utils::to_json<real_t, 1>(
knots_);
1398 utils::to_tensorAccessor<real_t, 1>(
coeffs_[
g], torch::kCPU);
1400 auto json = nlohmann::json::array();
1420 throw std::runtime_error(
1421 "JSON object provides incompatible geometric dimensions");
1424 throw std::runtime_error(
1425 "JSON object provides incompatible parametric dimensions");
1427 if (
json[
"degrees"].get<std::array<short_t, parDim_>>() !=
degrees_)
1428 throw std::runtime_error(
"JSON object provides incompatible degrees");
1430 nknots_ =
json[
"nknots"].get<std::array<int64_t, parDim_>>();
1431 ncoeffs_ =
json[
"ncoeffs"].get<std::array<int64_t, parDim_>>();
1437 auto kv =
json[
"knots"].get<std::array<std::vector<real_t>,
parDim_>>();
1442 auto c =
json[
"coeffs"].get<std::array<std::vector<real_t>,
geoDim_>>();
1452 int index = -1)
const {
1453 pugi::xml_document
doc;
1454 pugi::xml_node
root =
doc.append_child(
"xml");
1462 std::string
label =
"",
int index = -1)
const {
1464 pugi::xml_node
geo =
root.append_child(
"Geometry");
1468 geo.append_attribute(
"type") =
"Point";
1471 geo.append_attribute(
"id") =
id;
1474 geo.append_attribute(
"index") = index;
1477 geo.append_attribute(
"label") =
label.c_str();
1481 else if constexpr (
parDim_ == 1) {
1482 geo.append_attribute(
"type") =
"BSpline";
1485 geo.append_attribute(
"id") =
id;
1488 geo.append_attribute(
"index") = index;
1491 geo.append_attribute(
"label") =
label.c_str();
1494 pugi::xml_node
basis =
geo.append_child(
"Basis");
1495 basis.append_attribute(
"type") =
"BSplineBasis";
1498 pugi::xml_node
knots =
basis.append_child(
"KnotVector");
1501 std::stringstream
ss;
1503 utils::to_tensorAccessor<real_t, 1>(
knots_[0], torch::kCPU);
1506 << (
i <
nknots_[0] - 1 ?
" " :
"");
1507 knots.append_child(pugi::node_pcdata).set_value(
ss.str().c_str());
1512 geo.append_attribute(
"type") =
1513 std::string(
"TensorBSpline").append(std::to_string(
parDim_)).c_str();
1516 geo.append_attribute(
"id") =
id;
1519 geo.append_attribute(
"index") = index;
1522 geo.append_attribute(
"label") =
label.c_str();
1525 pugi::xml_node
bases =
geo.append_child(
"Basis");
1526 bases.append_attribute(
"type") = std::string(
"TensorBSplineBasis")
1527 .append(std::to_string(
parDim_))
1531 pugi::xml_node
basis =
bases.append_child(
"Basis");
1532 basis.append_attribute(
"type") =
"BSplineBasis";
1533 basis.append_attribute(
"index") = index;
1536 pugi::xml_node
knots =
basis.append_child(
"KnotVector");
1539 std::stringstream
ss;
1541 utils::to_tensorAccessor<real_t, 1>(
knots_[index], torch::kCPU);
1544 << (
i <
nknots_[index] - 1 ?
" " :
"");
1545 knots.append_child(pugi::node_pcdata).set_value(
ss.str().c_str());
1551 pugi::xml_node
coefs =
geo.append_child(
"coefs");
1555 utils::to_tensorAccessor<real_t, 1>(
coeffs_, torch::kCPU);
1556 std::stringstream
ss;
1568 coefs.append_child(pugi::node_pcdata).set_value(
ss.str().c_str());
1575 std::string
label =
"",
int index = -1) {
1581 std::string
label =
"",
int index = -1) {
1587 for (pugi::xml_node
geo :
root.children(
"Geometry")) {
1593 if (
geo.attribute(
"type").value() == std::string(
"Point") &&
1594 (
id >= 0 ?
geo.attribute(
"id").as_int() ==
id :
true) &&
1595 (index >= 0 ?
geo.attribute(
"index").as_int() == index :
true) &&
1596 (!
label.empty() ?
geo.attribute(
"label").value() ==
label :
true)) {
1606 else if constexpr (
parDim_ == 1) {
1609 if (
geo.attribute(
"type").value() == std::string(
"BSpline") &&
1610 (
id >= 0 ?
geo.attribute(
"id").as_int() ==
id :
true) &&
1611 (index >= 0 ?
geo.attribute(
"index").as_int() == index :
true) &&
1612 (!
label.empty() ?
geo.attribute(
"label").value() ==
label :
true)) {
1615 if (pugi::xml_node
basis =
geo.child(
"Basis");
1616 basis.attribute(
"type").value() == std::string(
"BSplineBasis")) {
1619 if (pugi::xml_node
knots =
basis.child(
"KnotVector");
1622 std::vector<real_t>
kv;
1623 std::string
values = std::regex_replace(
1624 knots.text().get(), std::regex(
"[\t\r\n\a]+| +"),
" ");
1627 kv.push_back(
static_cast<real_t
>(std::stod(value)));
1649 if (
geo.attribute(
"type").value() ==
1650 std::string(
"TensorBSpline").append(std::to_string(
parDim_)) &&
1651 (
id >= 0 ?
geo.attribute(
"id").as_int() ==
id :
true) &&
1652 (index >= 0 ?
geo.attribute(
"index").as_int() == index :
true) &&
1653 (!
label.empty() ?
geo.attribute(
"label").value() ==
label :
true)) {
1656 if (pugi::xml_node
bases =
geo.child(
"Basis");
1657 bases.attribute(
"type").value() ==
1658 std::string(
"TensorBSplineBasis")
1659 .append(std::to_string(
parDim_))) {
1662 for (pugi::xml_node
basis :
bases.children(
"Basis")) {
1665 if (
basis.attribute(
"type").value() ==
1666 std::string(
"BSplineBasis")) {
1671 if (pugi::xml_node
knots =
basis.child(
"KnotVector");
1674 std::vector<real_t>
kv;
1675 std::string
values = std::regex_replace(
1676 knots.text().get(), std::regex(
"[\t\r\n\a]+| +"),
" ");
1680 kv.push_back(
static_cast<real_t
>(std::stod(value)));
1704 [](
bool i) {
return !
i; }))
1705 throw std::runtime_error(
1706 "XML object is not compatible with B-spline object");
1718 if (pugi::xml_node
coefs =
geo.child(
"coefs")) {
1720 std::string
values = std::regex_replace(
1721 coefs.text().get(), std::regex(
"[\t\r\n\a]+| +"),
" ");
1729 throw std::runtime_error(
1730 "XML object does not provide enough coefficients");
1737 throw std::runtime_error(
1738 "XML object provides too many coefficients");
1746 throw std::runtime_error(
1747 "XML object does not provide enough coefficients");
1754 throw std::runtime_error(
1755 "XML object provides too many coefficients");
1766 [](
bool i) {
return i; }) &&
1769 [](
bool i) {
return i; }))
1773 throw std::runtime_error(
1774 "XML object is not compatible with B-spline object");
1778 throw std::runtime_error(
"XML object does not provide coefficients");
1782 throw std::runtime_error(
"XML object does not provide geometry with given "
1783 "id, index, and/or label");
1789 const std::string &
key =
"bspline") {
1790 torch::serialize::InputArchive
archive;
1796 inline torch::serialize::InputArchive &
1798 const std::string &
key =
"bspline") {
1803 throw std::runtime_error(
"parDim mismatch");
1807 throw std::runtime_error(
"geoDim mismatch");
1812 throw std::runtime_error(
"degrees mismatch");
1836 const std::string &
key =
"bspline")
const {
1837 torch::serialize::OutputArchive
archive;
1842 inline torch::serialize::OutputArchive &
1844 const std::string &
key =
"bspline")
const {
1849 archive.write(
key +
".degree[" + std::to_string(
i) +
"]",
1853 archive.write(
key +
".nknots[" + std::to_string(
i) +
"]",
1860 archive.write(
key +
".ncoeffs[" + std::to_string(
i) +
"]",
1873 real_t
rtol = real_t{1
e-5}, real_t
atol = real_t{1
e-8})
const {
1874 if constexpr (!std::is_same<real_t, other_t>::value)
1906 if constexpr (!std::is_same<real_t, other_t>::value)
1974 std::vector<real_t>
kv;
1978 kv.push_back(
static_cast<real_t
>(0));
1981 kv.push_back(
static_cast<real_t
>(
j) /
1985 kv.push_back(
static_cast<real_t
>(1));
2036 throw std::runtime_error(
2037 "Not enough coefficients to create open knot vector");
2103 coeffs_[
i] = torch::kron(torch::linspace(
static_cast<real_t
>(0),
2104 static_cast<real_t
>(1),
2165 std::pow(10,
i) * 0, std::pow(10,
i) * (size - 1), size,
options_);
2171 throw std::runtime_error(
"Unsupported init option");
2201 auto basfunc_ = [&,
this]<std::size_t...
Is>(std::index_sequence<
Is...>) {
2202 if constexpr (
sizeof...(Is) == 1)
2237 .
view({-1, knot_indices_[0].numel()}))
2238 .view(knot_indices_[0].
sizes());
2347 template <
short_t degree,
short_t dim,
short_t deriv>
2356 torch::Tensor
b = torch::ones({
xi.numel()},
options_);
2381 b = torch::cat({torch::mul(torch::ones_like(
w,
options_) -
w,
b),
2384 torch::cat({torch::zeros_like(
xi,
options_), torch::mul(
w,
b)}, 0);
2408 b = torch::cat({torch::mul(-
w,
b), torch::zeros_like(
xi,
options_)},
2410 torch::cat({torch::zeros_like(
xi,
options_), torch::mul(
w,
b)}, 0);
2413 return b.view({
degree + 1,
xi.numel()});
2423 template <
short_t degree,
short_t dim>
2451 auto w = torch::div(
2452 knots.index({torch::indexing::Slice(k, knot_indices.numel() + k)})
2458 b = torch::cat({torch::mul(torch::ones_like(
w,
options_) -
w,
b),
2474#ifdef IGANET_WITH_GISMO
2480 utils::to_tensorAccessor<real_t, 1>(
coeffs_[
g], torch::kCPU);
2486 std::array<gismo::gsKnotVector<real_t>,
parDim_>
kv;
2490 utils::to_tensorAccessor<real_t, 1>(
knots_[
i], torch::kCPU);
2498 return gismo::gsBSpline<real_t>(gismo::give(
kv[0]), gismo::give(
coefs));
2500 }
else if constexpr (
parDim_ == 2) {
2502 return gismo::gsTensorBSpline<parDim_, real_t>(
2503 gismo::give(
kv[0]), gismo::give(
kv[1]), gismo::give(
coefs));
2505 }
else if constexpr (
parDim_ == 3) {
2507 return gismo::gsTensorBSpline<parDim_, real_t>(
2508 gismo::give(
kv[0]), gismo::give(
kv[1]), gismo::give(
kv[2]),
2509 gismo::give(
coefs));
2511 }
else if constexpr (
parDim_ == 4) {
2513 return gismo::gsTensorBSpline<parDim_, real_t>(
2514 gismo::give(
kv[0]), gismo::give(
kv[1]), gismo::give(
kv[2]),
2515 gismo::give(
kv[3]), gismo::give(
coefs));
2518 throw std::runtime_error(
"Invalid parametric dimension");
2521 throw std::runtime_error(
2522 "This functions must be compiled with -DIGANET_WITH_GISMO turned on");
2526#ifdef IGANET_WITH_GISMO
2538 throw std::runtime_error(
"Degrees mismatch");
2541 utils::to_tensorAccessor<real_t, 1>(
knots_[0], torch::kCPU);
2550 throw std::runtime_error(
"Invalid parametric dimension");
2557 utils::to_tensorAccessor<real_t, 1>(
coeffs_[
g], torch::kCPU);
2568 gismo::gsTensorBSpline<parDim_, real_t> &
2580 utils::to_tensorAccessor<real_t, 1>(
knots_[
i], torch::kCPU);
2593 utils::to_tensorAccessor<real_t, 1>(
coeffs_[
g], torch::kCPU);
2605 template <
typename BSpline>
2607 throw std::runtime_error(
2608 "This functions must be compiled with -DIGANET_WITH_GISMO turned on");
2614#ifdef IGANET_WITH_GISMO
2622 throw std::runtime_error(
2623 "Knot vectors can only be updated for Non-uniform B-splines");
2629 throw std::runtime_error(
"Geometric dimensions mismatch");
2632 throw std::runtime_error(
"Coefficient vector dimensions mismatch");
2637 utils::to_tensorAccessor<real_t, 1>(
coeffs_[
g], torch::kCPU);
2657 throw std::runtime_error(
2658 "Knot vectors can only be updated for Non-uniform B-splines");
2664 throw std::runtime_error(
"Geometric dimensions mismatch");
2667 throw std::runtime_error(
"Coefficient vector dimensions mismatch");
2672 utils::to_tensorAccessor<real_t, 1>(
coeffs_[
g], torch::kCPU);
2689 throw std::runtime_error(
2690 "This functions must be compiled with -DIGANET_WITH_GISMO turned on");
2699inline torch::serialize::OutputArchive &
2707inline torch::serialize::InputArchive &
2753 template <
typename other_t>
2808 .to(
options.requires_grad(
false))
2818 const std::array<std::vector<typename Base::value_type>,
Base::parDim_>
2824 throw std::runtime_error(
"Knot vector is too short for an open knot "
2825 "vector (n+p+1 > 2*(p+1))");
2840 template <deriv deriv = deriv::func,
bool memory_optimized = false>
2841 inline auto eval(
const torch::Tensor &
xi)
const {
2845 template <deriv deriv = deriv::func,
bool memory_optimized = false>
2860 template <deriv deriv = deriv::func,
bool memory_optimized = false>
2876 template <deriv deriv = deriv::func,
bool memory_optimized = false>
2909 return torch::zeros_like(
Base::coeffs_[0]).to(torch::kInt64);
2922 torch::remainder(std::get<1>(((
nnz.cumsum(1) == 1) &
nnz).max(1)) - 1,
2947 utils::to_tensorAccessor<typename Base::value_type, 1>(
2950 std::vector<typename Base::value_type>
kv;
3056 utils::to_tensorAccessor<typename Base::value_type, 1>(
3059 std::vector<typename Base::value_type>
kv;
3105#ifdef IGANET_WITH_GISMO
3116 throw std::runtime_error(
"Degrees mismatch");
3119 throw std::runtime_error(
"Knot vector dimensions mismatch");
3122 utils::to_tensorAccessor<typename Base::value_type, 1>(
3126 bspline.knots(0).asMatrix().data();
3134 throw std::runtime_error(
"Invalid parametric dimension");
3140 throw std::runtime_error(
"Geometric dimensions mismatch");
3143 throw std::runtime_error(
"Coefficient vector dimensions mismatch");
3148 utils::to_tensorAccessor<typename Base::value_type, 1>(
3166 const gismo::gsTensorBSpline<Base::parDim_, typename Base::value_type>
3174 throw std::runtime_error(
"Degrees mismatch");
3177 throw std::runtime_error(
"Knot vector dimensions mismatch");
3180 utils::to_tensorAccessor<typename Base::value_type, 1>(
3184 bspline.knots(
i).asMatrix().data();
3196 throw std::runtime_error(
"Geometric dimensions mismatch");
3199 throw std::runtime_error(
"Coefficient vector dimensions mismatch");
3204 utils::to_tensorAccessor<typename Base::value_type, 1>(
3223 throw std::runtime_error(
3224 "This functions must be compiled with -DIGANET_WITH_GISMO turned on");
3237template <
typename... T>
3239 std::conjunction<std::is_base_of<detail::SplineType, T>...>;
3242template <
typename... T>
3258template <
typename BSplineCore>
3264 using BSplineCore::BSplineCore;
3292 template <
typename other_t>
3297 using Ptr = std::shared_ptr<BSplineCommon>;
3300 using uPtr = std::unique_ptr<BSplineCommon>;
3308 for (
short_t i = 0;
i < BSplineCore::geoDim_; ++
i)
3318 for (
short_t i = 0;
i < BSplineCore::geoDim_; ++
i)
3319 BSplineCore::coeffs_[
i] = coeffs[
i].
clone();
3321 for (
short_t i = 0;
i < BSplineCore::geoDim_; ++
i)
3322 BSplineCore::coeffs_[
i] = coeffs[
i];
3332 for (
short_t i = 0;
i < BSplineCore::geoDim_; ++
i)
3333 BSplineCore::coeffs_[
i] = std::move(coeffs[
i]);
3370 make_unique(
const std::array<std::vector<typename BSplineCore::value_type>,
3371 BSplineCore::parDim_> &
kv,
3379 make_unique(
const std::array<std::vector<typename BSplineCore::value_type>,
3380 BSplineCore::parDim_> &
kv,
3423 make_shared(
const std::array<std::vector<typename BSplineCore::value_type>,
3424 BSplineCore::parDim_> &
kv,
3432 make_shared(
const std::array<std::vector<typename BSplineCore::value_type>,
3433 BSplineCore::parDim_> &
kv,
3449 BSplineCore::uniform_refine(
numRefine, dim);
3457 result.nknots_ = BSplineCore::nknots_;
3458 result.ncoeffs_ = BSplineCore::ncoeffs_;
3459 result.ncoeffs_reverse_ = BSplineCore::ncoeffs_reverse_;
3461 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
3464 for (
short_t i = 0;
i < BSplineCore::geoDim_; ++
i)
3465 result.coeffs_[
i] = BSplineCore::coeffs_[
i].clone();
3475 result.nknots_ = BSplineCore::nknots_;
3476 result.ncoeffs_ = BSplineCore::ncoeffs_;
3477 result.ncoeffs_reverse_ = BSplineCore::ncoeffs_reverse_;
3479 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
3480 result.knots_[
i] = BSplineCore::knots_[
i].to(options);
3482 for (
short_t i = 0;
i < BSplineCore::geoDim_; ++
i)
3483 result.coeffs_[
i] = BSplineCore::coeffs_[
i].to(options);
3489 inline auto to(torch::Device device)
const {
3492 result.nknots_ = BSplineCore::nknots_;
3493 result.ncoeffs_ = BSplineCore::ncoeffs_;
3494 result.ncoeffs_reverse_ = BSplineCore::ncoeffs_reverse_;
3496 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
3497 result.knots_[
i] = BSplineCore::knots_[
i].to(device);
3499 for (
short_t i = 0;
i < BSplineCore::geoDim_; ++
i)
3500 result.coeffs_[
i] = BSplineCore::coeffs_[
i].to(device);
3506 template <
typename real_t>
inline auto to()
const {
3520 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
3523 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
3527 throw std::runtime_error(
"B-splines are not compatible");
3530 for (
short_t i = 0;
i < BSplineCore::geoDim_; ++
i)
3531 BSplineCore::coeffs(
i) -=
other.coeffs(
i);
3533 BSplineCore::coeffs(dim) -=
other.coeffs(dim);
3548 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
3551 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
3555 throw std::runtime_error(
"B-splines are not compatible");
3558 for (
short_t i = 0;
i < BSplineCore::geoDim_; ++
i)
3559 BSplineCore::coeffs(
i) =
3560 torch::abs(BSplineCore::coeffs(
i) -
other.coeffs(
i));
3562 BSplineCore::coeffs(dim) =
3563 torch::abs(BSplineCore::coeffs(dim) -
other.coeffs(dim));
3569 inline auto scale(
typename BSplineCore::value_type
s,
int dim = -1) {
3571 for (
int i = 0;
i < BSplineCore::geoDim(); ++
i)
3572 BSplineCore::coeffs(
i) *=
s;
3574 BSplineCore::coeffs(dim) *=
s;
3580 scale(std::array<
typename BSplineCore::value_type, BSplineCore::geoDim()>
v) {
3581 for (
int i = 0;
i < BSplineCore::geoDim(); ++
i)
3582 BSplineCore::coeffs(
i) *=
v[
i];
3588 std::array<
typename BSplineCore::value_type, BSplineCore::geoDim()>
v) {
3589 for (
int i = 0;
i < BSplineCore::geoDim(); ++
i)
3590 BSplineCore::coeffs(
i) +=
v[
i];
3595 inline auto rotate(
typename BSplineCore::value_type angle) {
3597 static_assert(BSplineCore::geoDim() == 2,
3598 "Rotation about one angle is only available in 2D");
3601 coeffs[0] = std::cos(angle) * BSplineCore::coeffs(0) -
3602 std::sin(angle) * BSplineCore::coeffs(1);
3603 coeffs[1] = std::sin(angle) * BSplineCore::coeffs(0) +
3604 std::cos(angle) * BSplineCore::coeffs(1);
3606 BSplineCore::coeffs().swap(coeffs);
3611 inline auto rotate(std::array<typename BSplineCore::value_type, 3> angle) {
3613 static_assert(BSplineCore::geoDim() == 3,
3614 "Rotation about two angles is only available in 3D");
3618 std::cos(angle[0]) * std::cos(angle[1]) * BSplineCore::coeffs(0) +
3619 (std::sin(angle[0]) * std::sin(angle[1]) * std::cos(angle[2]) -
3620 std::cos(angle[0]) * std::sin(angle[2])) *
3621 BSplineCore::coeffs(1) +
3622 (std::cos(angle[0]) * std::sin(angle[1]) * std::cos(angle[2]) +
3623 std::sin(angle[0]) * std::sin(angle[2])) *
3624 BSplineCore::coeffs(2);
3627 std::cos(angle[1]) * std::sin(angle[2]) * BSplineCore::coeffs(0) +
3628 (std::sin(angle[0]) * std::sin(angle[1]) * std::sin(angle[2]) +
3629 std::cos(angle[0]) * std::cos(angle[2])) *
3630 BSplineCore::coeffs(1) +
3631 (std::cos(angle[0]) * std::sin(angle[1]) * std::sin(angle[2]) -
3632 std::sin(angle[0]) * std::cos(angle[2])) *
3633 BSplineCore::coeffs(2);
3636 -std::sin(angle[1]) * BSplineCore::coeffs(0) +
3637 std::sin(angle[0]) * std::cos(angle[1]) * BSplineCore::coeffs(1) +
3638 std::cos(angle[0]) * std::cos(angle[1]) * BSplineCore::coeffs(2);
3640 BSplineCore::coeffs().swap(coeffs);
3648 auto min_ = [&,
this]<std::size_t...
Is>(std::index_sequence<
Is...>) {
3649 return torch::stack({BSplineCore::coeffs(
Is).min()...});
3653 auto max_ = [&,
this]<std::size_t...
Is>(std::index_sequence<
Is...>) {
3654 return torch::stack({BSplineCore::coeffs(
Is).max()...});
3657 std::pair<torch::Tensor, torch::Tensor>
bbox;
3658 bbox.first =
min_(std::make_index_sequence<BSplineCore::geoDim_>{});
3659 bbox.second =
max_(std::make_index_sequence<BSplineCore::geoDim_>{});
3686 template <
bool memory_optimized = false>
3691 template <
bool memory_optimized = false>
3721 template <
bool memory_optimized = false>
3757 template <
bool memory_optimized = false>
3762 static_assert(BSplineCore::parDim_ == BSplineCore::geoDim_,
3763 "curl(.) requires that parametric and geometric dimension "
3767 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
3769 for (
short_t i = 1;
i < BSplineCore::parDim_; ++
i)
3772 if constexpr (BSplineCore::parDim_ == 2)
3785 else if constexpr (BSplineCore::parDim_ == 3)
3805 throw std::runtime_error(
"Unsupported parametric/geometric dimension");
3831 template <
bool memory_optimized = false,
typename Geometry>
3833 if constexpr (BSplineCore::parDim_ == 0)
3835 torch::zeros_like(BSplineCore::coeffs_[0])};
3840 template <
bool memory_optimized = false,
typename Geometry>
3843 if constexpr (BSplineCore::parDim_ == 0)
3845 torch::zeros_like(BSplineCore::coeffs_[0])};
3848 G,
xi, BSplineCore::find_knot_indices(
xi), G.find_knot_indices(
xi));
3875 template <
bool memory_optimized = false,
typename Geometry>
3880 if constexpr (BSplineCore::parDim_ == 0)
3882 torch::zeros_like(BSplineCore::coeffs_[0])};
3922 template <
bool memory_optimized = false,
typename Geometry>
3930 if constexpr (BSplineCore::parDim_ == 0)
3932 torch::zeros_like(BSplineCore::coeffs_[0])};
3935 det[0] = std::make_shared<torch::Tensor>(torch::reciprocal(
3966 template <
bool memory_optimized = false>
3967 auto div(
const torch::Tensor &
xi)
const {
3968 if constexpr (BSplineCore::parDim_ == 0)
3970 torch::zeros_like(BSplineCore::coeffs_[0])};
3974 template <
bool memory_optimized = false>
3976 if constexpr (BSplineCore::parDim_ == 0)
3978 torch::zeros_like(BSplineCore::coeffs_[0])};
4005 template <
bool memory_optimized = false>
4009 if constexpr (BSplineCore::parDim_ == 0)
4011 torch::zeros_like(BSplineCore::coeffs_[0])};
4043 template <
bool memory_optimized = false>
4048 static_assert(BSplineCore::parDim_ == BSplineCore::geoDim_,
4049 "div(.) requires parDim == geoDim");
4051 if constexpr (BSplineCore::parDim_ == 0)
4053 torch::zeros_like(BSplineCore::coeffs_[0])};
4058 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
4060 for (
short_t i = 1;
i < BSplineCore::parDim_; ++
i)
4064 auto div_ = [&,
this]<std::size_t...
Is>(std::index_sequence<
Is...>) {
4066 (*BSplineCore::template eval<
4072 return div_(std::make_index_sequence<BSplineCore::parDim_>{});
4098 template <
bool memory_optimized = false,
typename Geometry>
4100 if constexpr (BSplineCore::parDim_ == 0)
4102 torch::zeros_like(BSplineCore::coeffs_[0])};
4107 template <
bool memory_optimized = false,
typename Geometry>
4110 if constexpr (BSplineCore::parDim_ == 0)
4112 torch::zeros_like(BSplineCore::coeffs_[0])};
4115 G,
xi, BSplineCore::find_knot_indices(
xi), G.find_knot_indices(
xi));
4144 template <
bool memory_optimized = false,
typename Geometry>
4149 if constexpr (BSplineCore::parDim_ == 0)
4151 torch::zeros_like(BSplineCore::coeffs_[0])};
4192 template <
bool memory_optimized = false,
typename Geometry>
4199 if constexpr (BSplineCore::parDim_ == 0)
4201 torch::zeros_like(BSplineCore::coeffs_[0])};
4229 template <
bool memory_optimized = false>
4230 inline auto grad(
const torch::Tensor &
xi)
const {
4232 static_assert(BSplineCore::geoDim_ == 1,
4233 "grad(.) requires 1D variable, use jac(.) instead");
4235 if constexpr (BSplineCore::parDim_ == 0)
4237 torch::zeros_like(BSplineCore::coeffs_[0])};
4242 template <
bool memory_optimized = false>
4245 static_assert(BSplineCore::geoDim_ == 1,
4246 "grad(.) requires 1D variable, use jac(.) instead");
4248 if constexpr (BSplineCore::parDim_ == 0)
4250 torch::zeros_like(BSplineCore::coeffs_[0])};
4277 template <
bool memory_optimized = false>
4282 static_assert(BSplineCore::geoDim_ == 1,
4283 "grad(.) requires 1D variable, use jac(.) instead");
4285 if constexpr (BSplineCore::parDim_ == 0)
4287 torch::zeros_like(BSplineCore::coeffs_[0])};
4319 template <
bool memory_optimized = false>
4324 static_assert(BSplineCore::geoDim_ == 1,
4325 "grad(.) requires 1D variable, use jac(.) instead");
4327 if constexpr (BSplineCore::parDim_ == 0)
4329 torch::zeros_like(BSplineCore::coeffs_[0])};
4333 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
4335 for (
short_t i = 1;
i < BSplineCore::parDim_; ++
i)
4339 auto grad_ = [&,
this]<std::size_t...
Is>(std::index_sequence<
Is...>) {
4346 return grad_(std::make_index_sequence<BSplineCore::parDim_>{});
4371 template <
bool memory_optimized = false,
typename Geometry>
4373 if constexpr (BSplineCore::parDim_ == 0)
4375 torch::zeros_like(BSplineCore::coeffs_[0])};
4380 template <
bool memory_optimized = false,
typename Geometry>
4383 if constexpr (BSplineCore::parDim_ == 0)
4385 torch::zeros_like(BSplineCore::coeffs_[0])};
4388 G,
xi, BSplineCore::find_knot_indices(
xi), G.find_knot_indices(
xi));
4415 template <
bool memory_optimized = false,
typename Geometry>
4420 if constexpr (BSplineCore::parDim_ == 0)
4422 torch::zeros_like(BSplineCore::coeffs_[0])};
4462 template <
bool memory_optimized = false,
typename Geometry>
4469 if constexpr (BSplineCore::parDim_ == 0)
4471 torch::zeros_like(BSplineCore::coeffs_[0])};
4515 template <
bool memory_optimized = false>
4516 inline auto hess(
const torch::Tensor &
xi)
const {
4517 if constexpr (BSplineCore::parDim_ == 0)
4519 torch::zeros_like(BSplineCore::coeffs_[0])};
4524 template <
bool memory_optimized = false>
4526 if constexpr (BSplineCore::parDim_ == 0)
4528 torch::zeros_like(BSplineCore::coeffs_[0])};
4570 template <
bool memory_optimized = false>
4574 if constexpr (BSplineCore::parDim_ == 0)
4576 torch::zeros_like(BSplineCore::coeffs_[0])};
4622 template <
bool memory_optimized = false>
4627 if constexpr (BSplineCore::parDim_ == 0)
4629 torch::zeros_like(BSplineCore::coeffs_[0])};
4633 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
4635 for (
short_t i = 1;
i < BSplineCore::parDim_; ++
i)
4639 auto hess_ = [&,
this]<std::size_t...
Is>(std::index_sequence<
Is...>) {
4641 BSplineCore::geoDim_, BSplineCore::parDim_>{
4642 BSplineCore::template eval<
4644 Is / BSplineCore::parDim_>::value +
4646 Is % BSplineCore::parDim_>::value,
4651 return hess_(std::make_index_sequence<BSplineCore::parDim_ *
4652 BSplineCore::parDim_>{});
4683 template <
bool memory_optimized = false,
typename Geometry>
4685 if constexpr (BSplineCore::parDim_ == 0)
4687 torch::zeros_like(BSplineCore::coeffs_[0])};
4692 template <
bool memory_optimized = false,
typename Geometry>
4695 if constexpr (BSplineCore::parDim_ == 0)
4697 torch::zeros_like(BSplineCore::coeffs_[0])};
4700 G,
xi, BSplineCore::find_knot_indices(
xi), G.find_knot_indices(
xi));
4733 template <
bool memory_optimized = false,
typename Geometry>
4738 if constexpr (BSplineCore::parDim_ == 0)
4740 torch::zeros_like(BSplineCore::coeffs_[0])};
4785 template <
bool memory_optimized = false,
typename Geometry>
4793 if constexpr (BSplineCore::parDim_ == 0)
4795 torch::zeros_like(BSplineCore::coeffs_[0])};
4814 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
4815 for (
short_t j = 0;
j < BSplineCore::parDim_; ++
j)
4855 template <
bool memory_optimized = false>
4856 inline auto jac(
const torch::Tensor &
xi)
const {
4857 if constexpr (BSplineCore::parDim_ == 0)
4859 torch::zeros_like(BSplineCore::coeffs_[0])};
4864 template <
bool memory_optimized = false>
4866 if constexpr (BSplineCore::parDim_ == 0)
4868 torch::zeros_like(BSplineCore::coeffs_[0])};
4905 template <
bool memory_optimized = false>
4909 if constexpr (BSplineCore::parDim_ == 0)
4911 torch::zeros_like(BSplineCore::coeffs_[0])};
4958 template <
bool memory_optimized = false>
4963 if constexpr (BSplineCore::parDim_ == 0)
4965 torch::zeros_like(BSplineCore::coeffs_[0])};
4969 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
4971 for (
short_t i = 1;
i < BSplineCore::parDim_; ++
i)
4975 auto jac_ = [&,
this]<std::size_t...
Is>(std::index_sequence<
Is...>) {
4977 BSplineCore::geoDim_>{
4984 return jac_(std::make_index_sequence<BSplineCore::parDim_>{});
5009 template <
bool memory_optimized = false,
typename Geometry>
5011 if constexpr (BSplineCore::parDim_ == 0)
5013 torch::zeros_like(BSplineCore::coeffs_[0])};
5018 template <
bool memory_optimized = false,
typename Geometry>
5021 if constexpr (BSplineCore::parDim_ == 0)
5023 torch::zeros_like(BSplineCore::coeffs_[0])};
5026 G,
xi, BSplineCore::find_knot_indices(
xi), G.find_knot_indices(
xi));
5054 template <
bool memory_optimized = false,
typename Geometry>
5059 if constexpr (BSplineCore::parDim_ == 0)
5061 torch::zeros_like(BSplineCore::coeffs_[0])};
5101 template <
bool memory_optimized = false,
typename Geometry>
5108 if constexpr (BSplineCore::parDim_ == 0)
5110 torch::zeros_like(BSplineCore::coeffs_[0])};
5138 template <
bool memory_optimized = false>
5139 inline auto lapl(
const torch::Tensor &
xi)
const {
5140 if constexpr (BSplineCore::parDim_ == 0)
5142 torch::zeros_like(BSplineCore::coeffs_[0])};
5147 template <
bool memory_optimized = false>
5149 if constexpr (BSplineCore::parDim_ == 0)
5151 torch::zeros_like(BSplineCore::coeffs_[0])};
5178 template <
bool memory_optimized = false>
5182 if constexpr (BSplineCore::parDim_ == 0)
5184 torch::zeros_like(BSplineCore::coeffs_[0])};
5216 template <
bool memory_optimized = false>
5221 if constexpr (BSplineCore::parDim_ == 0)
5223 torch::zeros_like(BSplineCore::coeffs_[0])};
5227 for (
short_t i = 0;
i < BSplineCore::parDim_; ++
i)
5229 for (
short_t i = 1;
i < BSplineCore::parDim_; ++
i)
5233 auto lapl_ = [&,
this]<std::size_t...
Is>(std::index_sequence<
Is...>) {
5235 (BSplineCore::template eval<
5242 return lapl_(std::make_index_sequence<BSplineCore::parDim_>{});
5274 template <
bool memory_optimized = false,
typename Geometry>
5276 if constexpr (BSplineCore::parDim_ == 0)
5278 torch::zeros_like(BSplineCore::coeffs_[0])};
5283 template <
bool memory_optimized = false,
typename Geometry>
5286 if constexpr (BSplineCore::parDim_ == 0)
5288 torch::zeros_like(BSplineCore::coeffs_[0])};
5291 G,
xi, BSplineCore::find_knot_indices(
xi), G.find_knot_indices(
xi));
5325 template <
bool memory_optimized = false,
typename Geometry>
5330 if constexpr (BSplineCore::parDim_ == 0)
5332 torch::zeros_like(BSplineCore::coeffs_[0])};
5379 template <
bool memory_optimized = false,
typename Geometry>
5387 if constexpr (BSplineCore::parDim_ == 0)
5389 torch::zeros_like(BSplineCore::coeffs_[0])};
5419#ifdef IGANET_WITH_MATPLOT
5420 template <
typename Backend = matplot::backend::gnuplot>
5422 template <
typename Backend =
void>
5424 inline auto plot(
const nlohmann::json &
json = {})
const {
5435#ifdef IGANET_WITH_MATPLOT
5436 template <
typename Backend = matplot::backend::gnuplot>
5438 template <
typename Backend =
void>
5441 const nlohmann::json &
json = {})
const {
5453#ifdef IGANET_WITH_MATPLOT
5454 template <
typename Backend = matplot::backend::gnuplot>
5456 template <
typename Backend =
void>
5460 const nlohmann::json &
json = {})
const {
5472#ifdef IGANET_WITH_MATPLOT
5473 template <
typename Backend = matplot::backend::gnuplot,
5476 template <
typename Backend =
void,
typename BSplineCoreColor>
5479 const nlohmann::json &
json = {})
const {
5480#ifdef IGANET_WITH_MATPLOT
5481 static_assert(BSplineCore::parDim() == BSplineCoreColor::parDim(),
5482 "Parametric dimensions must match");
5484 if ((
void *)
this != (
void *)&
color && BSplineCoreColor::geoDim() > 1)
5485 throw std::runtime_error(
"BSpline for coloring must have geoDim=1");
5487 if constexpr (BSplineCore::parDim() == 1 && BSplineCore::geoDim() == 1) {
5494 if (
json.contains(
"res0"))
5498 auto f = matplot::figure<Backend>(
true);
5499 auto ax = f->current_axes();
5503 BSplineCore::eval(torch::linspace(0, 1,
res0, BSplineCore::options_));
5506 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5511 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5518#pragma omp parallel for simd
5523 if ((
void *)
this != (
void *)&
color) {
5524 if constexpr (BSplineCoreColor::geoDim_ == 1) {
5528 color.eval(torch::linspace(0, 1,
res0, BSplineCore::options_));
5532 1>(
Color(0), torch::kCPU);
5537 1>(
Color(0), torch::kCPU);
5542#pragma omp parallel for simd
5549 auto Cmap = matplot::colormap();
5555 ax->hold(matplot::on);
5556 for (std::size_t
i = 0;
i <
Xfine.size() - 1; ++
i)
5562 ax->hold(matplot::off);
5563 matplot::colorbar(
ax);
5565 throw std::runtime_error(
"BSpline for coloring must have geoDim=1");
5572 if (
json.contains(
"cnet"))
5579 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5580 BSplineCore::coeffs(0), torch::kCPU);
5584 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5585 BSplineCore::coeffs(0), torch::kCPU);
5587 matplot::vector_1d
X(BSplineCore::ncoeffs(0), 0.0);
5588 matplot::vector_1d
Y(BSplineCore::ncoeffs(0), 0.0);
5590#pragma omp parallel for simd
5591 for (
int64_t i = 0;
i < BSplineCore::ncoeffs(0); ++
i) {
5596 ax->hold(matplot::on);
5597 ax->plot(
X,
Y,
".k-")->line_width(1);
5598 ax->hold(matplot::off);
5602 if (
json.contains(
"title"))
5603 ax->title(
json[
"title"].get<std::string>());
5605 ax->title(
"BSpline: [0,1] -> R");
5608 if (
json.contains(
"xlabel"))
5609 ax->xlabel(
json[
"xlabel"].get<std::string>());
5614 if (
json.contains(
"ylabel"))
5615 ax->ylabel(
json[
"ylabel"].get<std::string>());
5622 else if constexpr (BSplineCore::parDim_ == 1 && BSplineCore::geoDim_ == 2) {
5629 if (
json.contains(
"res0"))
5633 auto f = matplot::figure<Backend>(
true);
5634 auto ax = f->current_axes();
5638 BSplineCore::eval(torch::linspace(0, 1,
res0, BSplineCore::options_));
5641 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5647 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5650 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5657#pragma omp parallel for simd
5664 if ((
void *)
this != (
void *)&
color) {
5665 if constexpr (BSplineCoreColor::geoDim() == 1) {
5669 color.eval(torch::linspace(0, 1,
res0, BSplineCore::options_));
5673 1>(
Color(0), torch::kCPU);
5678 1>(
Color(0), torch::kCPU);
5683#pragma omp parallel for simd
5691 auto Cmap = matplot::colormap();
5697 ax->hold(matplot::on);
5698 for (std::size_t
i = 0;
i <
Xfine.size() - 1; ++
i)
5704 ax->hold(matplot::off);
5705 matplot::colorbar(
ax);
5707 throw std::runtime_error(
"BSpline for coloring must have geoDim=1");
5714 if (
json.contains(
"cnet"))
5721 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5722 BSplineCore::coeffs(), torch::kCPU);
5727 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5728 BSplineCore::coeffs(0), torch::kCPU);
5730 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5731 BSplineCore::coeffs(1), torch::kCPU);
5734 matplot::vector_1d
X(BSplineCore::ncoeffs(0), 0.0);
5735 matplot::vector_1d
Y(BSplineCore::ncoeffs(0), 0.0);
5737#pragma omp parallel for simd
5738 for (
int64_t i = 0;
i < BSplineCore::ncoeffs(0); ++
i) {
5744 ax->hold(matplot::on);
5745 ax->plot(
X,
Y,
".k-")->line_width(1);
5746 ax->hold(matplot::off);
5750 if (
json.contains(
"title"))
5751 ax->title(
json[
"title"].get<std::string>());
5753 ax->title(
"BSpline: [0,1] -> R^2");
5756 if (
json.contains(
"xlabel"))
5757 ax->xlabel(
json[
"xlabel"].get<std::string>());
5762 if (
json.contains(
"ylabel"))
5763 ax->ylabel(
json[
"ylabel"].get<std::string>());
5770 else if constexpr (BSplineCore::parDim() == 1 &&
5771 BSplineCore::geoDim() == 3) {
5778 if (
json.contains(
"res0"))
5782 auto f = matplot::figure<Backend>(
true);
5783 auto ax = f->current_axes();
5786 BSplineCore::eval(torch::linspace(0, 1,
res0, BSplineCore::options_));
5789 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5796 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5799 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5802 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5811#pragma omp parallel for simd
5819 if ((
void *)
this != (
void *)&
color) {
5820 if constexpr (BSplineCoreColor::geoDim() == 1) {
5823 color.eval(torch::linspace(0, 1,
res0, BSplineCore::options_));
5827 1>(
Color(0), torch::kCPU);
5832 1>(
Color(0), torch::kCPU);
5836 matplot::vector_1d
Cfine(matplot::vector_1d(
res0, 0.0));
5838#pragma omp parallel for simd
5846 auto Cmap = matplot::colormap();
5852 ax->hold(matplot::on);
5853 for (std::size_t
i = 0;
i <
Xfine.size() - 1; ++
i)
5860 ax->hold(matplot::off);
5861 matplot::colorbar(
ax);
5863 throw std::runtime_error(
"BSpline for coloring must have geoDim=1");
5870 if (
json.contains(
"cnet"))
5877 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5878 BSplineCore::coeffs(), torch::kCPU);
5884 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5885 BSplineCore::coeffs(0), torch::kCPU);
5887 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5888 BSplineCore::coeffs(1), torch::kCPU);
5890 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
5891 BSplineCore::coeffs(2), torch::kCPU);
5894 matplot::vector_1d
X(BSplineCore::ncoeffs(0), 0.0);
5895 matplot::vector_1d
Y(BSplineCore::ncoeffs(0), 0.0);
5896 matplot::vector_1d
Z(BSplineCore::ncoeffs(0), 0.0);
5898#pragma omp parallel for simd
5899 for (
int64_t i = 0;
i < BSplineCore::ncoeffs(0); ++
i) {
5906 ax->hold(matplot::on);
5907 ax->plot3(
X,
Y,
Z,
".k-")->line_width(1);
5908 ax->hold(matplot::off);
5912 if (
json.contains(
"title"))
5913 ax->title(
json[
"title"].get<std::string>());
5915 ax->title(
"BSpline: [0,1] -> R^3");
5918 if (
json.contains(
"xlabel"))
5919 ax->xlabel(
json[
"xlabel"].get<std::string>());
5924 if (
json.contains(
"ylabel"))
5925 ax->ylabel(
json[
"ylabel"].get<std::string>());
5930 if (
json.contains(
"zlabel"))
5931 ax->zlabel(
json[
"zlabel"].get<std::string>());
5938 else if constexpr (BSplineCore::parDim() == 2 &&
5939 BSplineCore::geoDim() == 2) {
5945 int64_t res0 = BSplineCore::ncoeffs(0);
5946 int64_t res1 = BSplineCore::ncoeffs(1);
5947 if (json.contains(
"res0"))
5948 res0 = json[
"res0"].get<int64_t>();
5949 if (json.contains(
"res1"))
5950 res1 = json[
"res1"].get<int64_t>();
5953 auto f = matplot::figure<Backend>(
true);
5954 auto ax = f->current_axes();
5957 utils::TensorArray<2> meshgrid = utils::to_array<2>(
5958 torch::meshgrid({torch::linspace(0, 1, res0, BSplineCore::options_),
5959 torch::linspace(0, 1, res1, BSplineCore::options_)},
5961 auto Coords = BSplineCore::eval(meshgrid);
5964 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 2>(
5965 Coords, torch::kCPU);
5966 auto XAccessor = std::get<1>(Coords_cpu)[0];
5967 auto YAccessor = std::get<1>(Coords_cpu)[1];
5969 auto [Coords0_cpu, XAccessor] =
5970 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 2>(
5971 Coords(0), torch::kCPU);
5972 auto [Coords1_cpu, YAccessor] =
5973 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 2>(
5974 Coords(1), torch::kCPU);
5977 matplot::vector_2d Xfine(res1, matplot::vector_1d(res0, 0.0));
5978 matplot::vector_2d Yfine(res1, matplot::vector_1d(res0, 0.0));
5979 matplot::vector_2d Zfine(res1, matplot::vector_1d(res0, 0.0));
5981#pragma omp parallel for simd collapse(2)
5982 for (int64_t i = 0; i < res0; ++i)
5983 for (int64_t j = 0; j < res1; ++j) {
5984 Xfine[j][i] = XAccessor[j][i];
5985 Yfine[j][i] = YAccessor[j][i];
5989 if ((
void *)
this != (
void *)&color) {
5990 if constexpr (BSplineCoreColor::geoDim() == 1) {
5993 auto Color = color.eval(meshgrid);
5996 utils::to_tensorAccessor<
typename BSplineCoreColor::value_type,
5997 2>(Color, torch::kCPU);
5998 auto CAccessor = std::get<1>(Color_cpu)[0];
6000 auto [Color0_cpu, CAccessor] =
6001 utils::to_tensorAccessor<
typename BSplineCoreColor::value_type,
6002 2>(Color(0), torch::kCPU);
6005 matplot::vector_2d Cfine(res1, matplot::vector_1d(res0, 0.0));
6007#pragma omp parallel for simd collapse(2)
6008 for (int64_t i = 0; i < res0; ++i)
6009 for (int64_t j = 0; j < res1; ++j)
6010 Cfine[j][i] = CAccessor[j][i];
6014 ax->mesh(Xfine, Yfine, Cfine)->hidden_3d(
false);
6015 matplot::colorbar(ax);
6017 throw std::runtime_error(
"BSpline for coloring must have geoDim=1");
6021 matplot::colormap(std::vector<std::vector<double>>{{ 0.0, 0.0, 1.0 }});
6022 ax->mesh(Xfine, Yfine, Zfine)->hidden_3d(
false).line_width(2);
6026 if (json.contains(
"cnet"))
6027 cnet = json[
"cnet"].get<
bool>();
6033 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6034 BSplineCore::coeffs(), torch::kCPU);
6035 auto xAccessor = std::get<1>(coeffs_cpu)[0];
6036 auto yAccessor = std::get<1>(coeffs_cpu)[1];
6038 auto [coeffs0_cpu, xAccessor] =
6039 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6040 BSplineCore::coeffs(0), torch::kCPU);
6041 auto [coeffs1_cpu, yAccessor] =
6042 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6043 BSplineCore::coeffs(1), torch::kCPU);
6046 matplot::vector_2d X(BSplineCore::ncoeffs(1),
6047 matplot::vector_1d(BSplineCore::ncoeffs(0), 0.0));
6048 matplot::vector_2d Y(BSplineCore::ncoeffs(1),
6049 matplot::vector_1d(BSplineCore::ncoeffs(0), 0.0));
6050 matplot::vector_2d Z(BSplineCore::ncoeffs(1),
6051 matplot::vector_1d(BSplineCore::ncoeffs(0), 0.0));
6053#pragma omp parallel for simd collapse(2)
6054 for (int64_t i = 0; i < BSplineCore::ncoeffs(0); ++i)
6055 for (int64_t j = 0; j < BSplineCore::ncoeffs(1); ++j) {
6056 X[j][i] = xAccessor[j * BSplineCore::ncoeffs(0) + i];
6057 Y[j][i] = yAccessor[j * BSplineCore::ncoeffs(0) + i];
6061 ax->hold(matplot::on);
6063 ->palette_map_at_surface(
true)
6066 for (std::size_t i = 0; i < X.size(); ++i)
6067 ax->scatter3(X[i], Y[i], Z[i],
"k.");
6068 ax->hold(matplot::off);
6072 if (json.contains(
"title"))
6073 ax->title(json[
"title"].get<std::string>());
6075 ax->title(
"BSpline: [0,1]^2 -> R^2");
6078 if (json.contains(
"xlabel"))
6079 ax->xlabel(json[
"xlabel"].get<std::string>());
6084 if (json.contains(
"ylabel"))
6085 ax->ylabel(json[
"ylabel"].get<std::string>());
6090 if (json.contains(
"zlabel"))
6091 ax->zlabel(json[
"zlabel"].get<std::string>());
6098 else if constexpr (BSplineCore::parDim() == 2 &&
6099 BSplineCore::geoDim() == 3) {
6105 int64_t res0 = BSplineCore::ncoeffs(0);
6106 int64_t res1 = BSplineCore::ncoeffs(1);
6107 if (json.contains(
"res0"))
6108 res0 = json[
"res0"].get<int64_t>();
6109 if (json.contains(
"res1"))
6110 res1 = json[
"res1"].get<int64_t>();
6113 auto f = matplot::figure<Backend>(
true);
6114 auto ax = f->current_axes();
6117 utils::TensorArray<2> meshgrid = utils::to_array<2>(
6118 torch::meshgrid({torch::linspace(0, 1, res0, BSplineCore::options_),
6119 torch::linspace(0, 1, res1, BSplineCore::options_)},
6121 auto Coords = BSplineCore::eval(meshgrid);
6124 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 2>(
6125 Coords, torch::kCPU);
6126 auto XAccessor = std::get<1>(Coords_cpu)[0];
6127 auto YAccessor = std::get<1>(Coords_cpu)[1];
6128 auto ZAccessor = std::get<1>(Coords_cpu)[2];
6130 auto [Coords0_cpu, XAccessor] =
6131 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 2>(
6132 Coords(0), torch::kCPU);
6133 auto [Coords1_cpu, YAccessor] =
6134 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 2>(
6135 Coords(1), torch::kCPU);
6136 auto [Coords2_cpu, ZAccessor] =
6137 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 2>(
6138 Coords(2), torch::kCPU);
6141 matplot::vector_2d Xfine(res1, matplot::vector_1d(res0, 0.0));
6142 matplot::vector_2d Yfine(res1, matplot::vector_1d(res0, 0.0));
6143 matplot::vector_2d Zfine(res1, matplot::vector_1d(res0, 0.0));
6145#pragma omp parallel for simd collapse(2)
6146 for (int64_t i = 0; i < res0; ++i)
6147 for (int64_t j = 0; j < res1; ++j) {
6148 Xfine[j][i] = XAccessor[j][i];
6149 Yfine[j][i] = YAccessor[j][i];
6150 Zfine[j][i] = ZAccessor[j][i];
6154 if ((
void *)
this != (
void *)&color) {
6155 if constexpr (BSplineCoreColor::geoDim() == 1) {
6158 auto Color = color.eval(meshgrid);
6161 utils::to_tensorAccessor<
typename BSplineCoreColor::value_type,
6162 2>(Color, torch::kCPU);
6163 auto CAccessor = std::get<1>(Color_cpu)[0];
6165 auto [Color_cpu, CAccessor] =
6166 utils::to_tensorAccessor<
typename BSplineCoreColor::value_type,
6167 2>(Color(0), torch::kCPU);
6170 matplot::vector_2d Cfine(res1, matplot::vector_1d(res0, 0.0));
6172#pragma omp parallel for simd collapse(2)
6173 for (int64_t i = 0; i < res0; ++i)
6174 for (int64_t j = 0; j < res1; ++j) {
6175 Cfine[j][i] = CAccessor[j][i];
6179 ax->mesh(Xfine, Yfine, Zfine, Cfine)->hidden_3d(
false);
6180 matplot::colorbar(ax);
6182 throw std::runtime_error(
"BSpline for coloring must have geoDim=1");
6185 matplot::colormap(std::vector<std::vector<double>>{{ 0.0, 0.0, 1.0 }});
6186 ax->mesh(Xfine, Yfine, Zfine)->hidden_3d(
false).line_width(2);
6190 if (json.contains(
"cnet"))
6191 cnet = json[
"cnet"].get<
bool>();
6197 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6198 BSplineCore::coeffs(), torch::kCPU);
6199 auto xAccessor = std::get<1>(coeffs_cpu)[0];
6200 auto yAccessor = std::get<1>(coeffs_cpu)[1];
6201 auto zAccessor = std::get<1>(coeffs_cpu)[2];
6203 auto [coeffs0_cpu, xAccessor] =
6204 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6205 BSplineCore::coeffs(0), torch::kCPU);
6206 auto [coeffs1_cpu, yAccessor] =
6207 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6208 BSplineCore::coeffs(1), torch::kCPU);
6209 auto [coeffs2_cpu, zAccessor] =
6210 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6211 BSplineCore::coeffs(2), torch::kCPU);
6214 matplot::vector_2d X(BSplineCore::ncoeffs(1),
6215 matplot::vector_1d(BSplineCore::ncoeffs(0), 0.0));
6216 matplot::vector_2d Y(BSplineCore::ncoeffs(1),
6217 matplot::vector_1d(BSplineCore::ncoeffs(0), 0.0));
6218 matplot::vector_2d Z(BSplineCore::ncoeffs(1),
6219 matplot::vector_1d(BSplineCore::ncoeffs(0), 0.0));
6221#pragma omp parallel for simd collapse(2)
6222 for (int64_t i = 0; i < BSplineCore::ncoeffs(0); ++i)
6223 for (int64_t j = 0; j < BSplineCore::ncoeffs(1); ++j) {
6224 X[j][i] = xAccessor[j * BSplineCore::ncoeffs(0) + i];
6225 Y[j][i] = yAccessor[j * BSplineCore::ncoeffs(0) + i];
6226 Z[j][i] = zAccessor[j * BSplineCore::ncoeffs(0) + i];
6230 ax->hold(matplot::on);
6232 ->palette_map_at_surface(
true)
6235 for (std::size_t i = 0; i < X.size(); ++i)
6236 ax->scatter3(X[i], Y[i], Z[i],
"k.");
6237 ax->hold(matplot::off);
6241 if (json.contains(
"title"))
6242 ax->title(json[
"title"].get<std::string>());
6244 ax->title(
"BSpline: [0,1]^2 -> R^3");
6247 if (json.contains(
"xlabel"))
6248 ax->xlabel(json[
"xlabel"].get<std::string>());
6253 if (json.contains(
"ylabel"))
6254 ax->ylabel(json[
"ylabel"].get<std::string>());
6259 if (json.contains(
"zlabel"))
6260 ax->zlabel(json[
"zlabel"].get<std::string>());
6268 throw std::runtime_error(
6269 "Unsupported combination of parametric/geometric dimensions");
6271 throw std::runtime_error(
6272 "This functions must be compiled with -DIGANET_WITH_MATPLOT turned on");
6286#ifdef IGANET_WITH_MATPLOT
6287 template <
typename Backend = matplot::backend::gnuplot,
6288 typename BSplineCoreColor>
6290 template <
typename Backend =
void,
typename BSplineCoreColor>
6294 const nlohmann::json &json = {})
const {
6296#ifdef IGANET_WITH_MATPLOT
6297 auto f = plot<Backend>(color, json);
6298 auto ax = f->current_axes();
6302 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6304 auto xiAccessor = std::get<1>(xi_cpu);
6306 auto [xi_cpu, xiAccessor] =
6307 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6311 if constexpr (BSplineCore::parDim_ == 1) {
6312 matplot::vector_1d X(xi[0].size(0), 0.0);
6313 matplot::vector_1d Y(xi[0].size(0), 0.0);
6315#pragma omp parallel for simd
6316 for (int64_t i = 0; i < xi[0].size(0); ++i) {
6317 X[i] = xiAccessor[0][i];
6320 ax->hold(matplot::on);
6321 ax->scatter(X, Y,
".");
6322 ax->hold(matplot::off);
6323 }
else if constexpr (BSplineCore::parDim_ == 2) {
6324 matplot::vector_1d X(xi[0].size(0), 0.0);
6325 matplot::vector_1d Y(xi[0].size(0), 0.0);
6326 matplot::vector_1d Z(xi[0].size(0), 0.0);
6328#pragma omp parallel for simd
6329 for (int64_t i = 0; i < xi[0].size(0); ++i) {
6330 X[i] = xiAccessor[0][i];
6331 Y[i] = xiAccessor[1][i];
6334 ax->hold(matplot::on);
6335 ax->scatter3(X, Y, Z,
".");
6336 ax->hold(matplot::off);
6337 }
else if constexpr (BSplineCore::parDim_ == 3) {
6338 matplot::vector_1d X(xi[0].size(0), 0.0);
6339 matplot::vector_1d Y(xi[0].size(0), 0.0);
6340 matplot::vector_1d Z(xi[0].size(0), 0.0);
6342#pragma omp parallel for simd
6343 for (int64_t i = 0; i < xi[0].size(0); ++i) {
6344 X[i] = xiAccessor[0][i];
6345 Y[i] = xiAccessor[1][i];
6346 Z[i] = xiAccessor[2][i];
6349 ax->hold(matplot::on);
6350 ax->scatter3(X, Y, Z,
".");
6351 ax->hold(matplot::off);
6353 throw std::runtime_error(
"Invalid parametric dimension");
6357 throw std::runtime_error(
6358 "This functions must be compiled with -DIGANET_WITH_MATPLOT turned on");
6372#ifdef IGANET_WITH_MATPLOT
6373 template <
typename Backend = matplot::backend::gnuplot,
6374 typename BSplineCoreColor>
6376 template <
typename Backend =
void,
typename BSplineCoreColor>
6381 const nlohmann::json &json = {})
const {
6383#ifdef IGANET_WITH_MATPLOT
6384 auto f = plot<Backend>(color, json);
6385 auto ax = f->current_axes();
6387 for (
const auto &xi : xi) {
6390 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6392 auto xiAccessor = std::get<1>(xi_cpu);
6394 auto [xi_cpu, xiAccessor] =
6395 utils::to_tensorAccessor<typename BSplineCoreColor::value_type, 1>(
6399 if constexpr (BSplineCore::parDim_ == 1) {
6400 matplot::vector_1d X(xi[0].size(0), 0.0);
6401 matplot::vector_1d Y(xi[0].size(0), 0.0);
6403#pragma omp parallel for simd
6404 for (int64_t i = 0; i < xi[0].size(0); ++i) {
6405 X[i] = xiAccessor[0][i];
6408 ax->hold(matplot::on);
6409 ax->scatter(X, Y,
".");
6410 ax->hold(matplot::off);
6411 }
else if constexpr (BSplineCore::parDim_ == 2) {
6412 matplot::vector_1d X(xi[0].size(0), 0.0);
6413 matplot::vector_1d Y(xi[0].size(0), 0.0);
6414 matplot::vector_1d Z(xi[0].size(0), 0.0);
6416#pragma omp parallel for simd
6417 for (int64_t i = 0; i < xi[0].size(0); ++i) {
6418 X[i] = xiAccessor[0][i];
6419 Y[i] = xiAccessor[1][i];
6422 ax->hold(matplot::on);
6423 ax->scatter3(X, Y, Z,
".");
6424 ax->hold(matplot::off);
6425 }
else if constexpr (BSplineCore::parDim_ == 3) {
6426 matplot::vector_1d X(xi[0].size(0), 0.0);
6427 matplot::vector_1d Y(xi[0].size(0), 0.0);
6428 matplot::vector_1d Z(xi[0].size(0), 0.0);
6430#pragma omp parallel for simd
6431 for (int64_t i = 0; i < xi[0].size(0); ++i) {
6432 X[i] = xiAccessor[0][i];
6433 Y[i] = xiAccessor[1][i];
6434 Z[i] = xiAccessor[2][i];
6437 ax->hold(matplot::on);
6438 ax->scatter3(X, Y, Z,
".");
6439 ax->hold(matplot::off);
6442 throw std::runtime_error(
"Invalid parametric dimension");
6446 throw std::runtime_error(
6447 "This functions must be compiled with -DIGANET_WITH_MATPLOT turned on");
6454 os << name() <<
"(\nparDim = " << BSplineCore::parDim()
6455 <<
", geoDim = " << BSplineCore::geoDim() <<
", degrees = ";
6457 for (
short_t i = 0; i < BSplineCore::parDim() - 1; ++i)
6458 os << BSplineCore::degree(i) <<
"x";
6459 if (BSplineCore::parDim() > 0)
6460 os << BSplineCore::degree(BSplineCore::parDim() - 1);
6465 for (
short_t i = 0; i < BSplineCore::parDim() - 1; ++i)
6466 os << BSplineCore::nknots(i) <<
"x";
6467 if (BSplineCore::parDim() > 0)
6468 os << BSplineCore::nknots(BSplineCore::parDim() - 1);
6472 os <<
", coeffs = ";
6473 for (
short_t i = 0; i < BSplineCore::parDim() - 1; ++i)
6474 os << BSplineCore::ncoeffs(i) <<
"x";
6475 if (BSplineCore::parDim() > 0)
6476 os << BSplineCore::ncoeffs(BSplineCore::parDim() - 1);
6480 os <<
", options = "
6481 <<
static_cast<torch::TensorOptions
>(BSplineCore::options_);
6485 for (
const torch::Tensor &knots : BSplineCore::knots()) {
6486 os << (knots.is_view() ?
"view/" :
"owns/");
6487 os << (knots.is_contiguous() ?
"cont " :
"non-cont ");
6489 if (BSplineCore::parDim() > 0)
6490 os <<
"] = " << BSplineCore::knots();
6494 os <<
"\ncoeffs [ ";
6495 for (
const torch::Tensor &coeffs : BSplineCore::coeffs()) {
6496 os << (coeffs.is_view() ?
"view/" :
"owns/");
6497 os << (coeffs.is_contiguous() ?
"cont " :
"non-cont ");
6499 if (BSplineCore::ncumcoeffs() > 0)
6500 os <<
"] = " << BSplineCore::coeffs_view();
6519 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6520 result.coeffs(i) += other.coeffs(i);
6537 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6538 result.coeffs(i) -= other.coeffs(i);
6549 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6550 result.coeffs(i) *= s;
6558 std::array<
typename BSplineCore::value_type, BSplineCore::geoDim()> v)
6563 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6564 result.coeffs(i) *= v[i];
6575 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6576 result.coeffs(i) /= s;
6584 std::array<
typename BSplineCore::value_type, BSplineCore::geoDim()> v)
6589 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6590 result.coeffs(i) /= v[i];
6603 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6604 BSplineCore::coeffs(i) += other.coeffs(i);
6617 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6618 BSplineCore::coeffs(i) -= other.coeffs(i);
6626 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6627 BSplineCore::coeffs(i) *= s;
6634 std::array<
typename BSplineCore::value_type, BSplineCore::geoDim()> v) {
6636 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6637 BSplineCore::coeffs(i) *= v[i];
6645 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6646 BSplineCore::coeffs(i) /= s;
6653 std::array<
typename BSplineCore::value_type, BSplineCore::geoDim()> v) {
6655 for (
short_t i = 0; i < BSplineCore::geoDim(); ++i)
6656 BSplineCore::coeffs(i) /= v[i];
6663template <
typename real_t, short_t GeoDim, short_t... Degrees>
6669inline std::ostream &
6677template <
typename real_t, short_t GeoDim, short_t... Degrees>
6683inline std::ostream &
Compile-time block tensor.
B-spline (common high-level functionality)
Definition bspline.hpp:3261
auto ijac(const Geometry G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G) const
Returns a block-tensor with the Jacobian of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:5056
auto scale(typename BSplineCore::value_type s, int dim=-1)
Scales the B-spline object by a scalar.
Definition bspline.hpp:3569
auto translate(std::array< typename BSplineCore::value_type, BSplineCore::geoDim()> v)
Translates the B-spline object by a vector.
Definition bspline.hpp:3587
BSplineCommon operator/(typename BSplineCore::value_type s) const
Returns a new B-spline object whose coefficients are scaled by a scalar.
Definition bspline.hpp:6571
auto diff(const BSplineCommon &other, int dim=-1)
Computes the difference between two compatible B-spline objects.
Definition bspline.hpp:3516
auto scale(std::array< typename BSplineCore::value_type, BSplineCore::geoDim()> v)
Scales the B-spline object by a vector.
Definition bspline.hpp:3580
BSplineCommon & operator*=(typename BSplineCore::value_type s)
Scales the coefficients by a scalar.
Definition bspline.hpp:6624
auto icurl(const Geometry G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G) const
Returns a block-tensor with the curl of the B-spline object in the points xi with respect to the phys...
Definition bspline.hpp:3877
auto ihess(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the Hessian of the B-spline object in the points xi with respect to the p...
Definition bspline.hpp:4693
auto curl(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices) const
Returns a block-tensor with the curl of the B-spline object with respect to the parametric variables.
Definition bspline.hpp:3758
auto curl(const torch::Tensor &xi) const
Returns a block-tensor with the curl of the B-spline object with respect to the parametric variables.
Definition bspline.hpp:3687
auto ihess(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G, const torch::Tensor &coeff_indices_G) const
Returns a block-tensor with the Hessian of the B-spline object in the points xi with respect to the p...
Definition bspline.hpp:4787
auto ilapl(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the Laplacian of the B-spline object in the points xi with respect to the...
Definition bspline.hpp:5284
auto ihess(const Geometry &G, const torch::Tensor &xi) const
Returns a block-tensor with the Hessian of the B-spline object in the points xi with respect to the p...
Definition bspline.hpp:4684
BSplineCommon & operator*=(std::array< typename BSplineCore::value_type, BSplineCore::geoDim()> v)
Scales the coefficients by a vector.
Definition bspline.hpp:6633
auto idiv(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the divergence of the B-spline object with respect to the physical variab...
Definition bspline.hpp:4108
auto grad(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices) const
Returns a block-tensor with the gradient of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4320
auto plot(const BSplineCommon< BSplineCoreColor > &color, const std::initializer_list< utils::TensorArray< BSplineCore::parDim_ > > &xi, const nlohmann::json &json={}) const
Definition bspline.hpp:6378
auto div(const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the divergence of the B-spline object with respect to the parametric vari...
Definition bspline.hpp:3975
auto rotate(std::array< typename BSplineCore::value_type, 3 > angle)
Rotates the B-spline object by three angles in 3d.
Definition bspline.hpp:3611
BSplineCommon operator*(std::array< typename BSplineCore::value_type, BSplineCore::geoDim()> v) const
Returns a new B-spline object whose coefficients are scaled by a vector.
Definition bspline.hpp:6557
auto rotate(typename BSplineCore::value_type angle)
Rotates the B-spline object by an angle in 2d.
Definition bspline.hpp:3595
BSplineCommon & operator/=(std::array< typename BSplineCore::value_type, BSplineCore::geoDim()> v)
Scales the coefficients by a vector.
Definition bspline.hpp:6652
auto lapl(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices) const
Returns a block-tensor with the Laplacian of the B-spline object in the points xi with respect to the...
Definition bspline.hpp:5217
auto ijac(const Geometry &G, const torch::Tensor &xi) const
Returns a block-tensor with the Jacobian of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:5010
auto icurl(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G, const torch::Tensor &coeff_indices_G) const
Returns a block-tensor with the curl of the B-spline object in the points xi with respect to the phys...
Definition bspline.hpp:3924
auto ijac(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G, const torch::Tensor &coeff_indices_G) const
Returns a block-tensor with the Jacobian of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:5102
auto jac(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices) const
Returns a block-tensor with the Jacobian of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4907
auto jac(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices) const
Returns a block-tensor with the Jacobian of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4959
auto hess(const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the Hessian of the B-spline object in the points xi with respect to the p...
Definition bspline.hpp:4525
std::unique_ptr< BSplineCommon > uPtr
Unique pointer for BSplineCommon.
Definition bspline.hpp:3300
BSplineCommon(const BSplineCommon &other, bool clone)
Copy/clone constructor.
Definition bspline.hpp:3306
auto idiv(const Geometry G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G) const
Returns a block-tensor with the divergence of the B-spline object with respect to the physical variab...
Definition bspline.hpp:4146
static Ptr make_unique(const std::array< int64_t, BSplineCore::parDim_ > &ncoeffs, enum init init=init::greville, Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as unique pointer.
Definition bspline.hpp:3345
auto lapl(const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the Laplacian of the B-spline object in the points xi with respect to the...
Definition bspline.hpp:5148
auto ilapl(const Geometry G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G) const
Returns a block-tensor with the Laplacian of the B-spline object in the points xi with respect to the...
Definition bspline.hpp:5327
static Ptr make_shared(const std::array< std::vector< typename BSplineCore::value_type >, BSplineCore::parDim_ > &kv, enum init init=init::greville, Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as shared pointer.
Definition bspline.hpp:3423
auto grad(const torch::Tensor &xi) const
Returns a block-tensor with the gradient of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4230
auto idiv(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G, const torch::Tensor &coeff_indices_G) const
Returns a block-tensor with the divergence of the B-spline object with respect to the physical variab...
Definition bspline.hpp:4193
auto curl(const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the curl of the B-spline object with respect to the parametric variables.
Definition bspline.hpp:3692
auto hess(const torch::Tensor &xi) const
Returns a block-tensor with the Hessian of the B-spline object in the points xi with respect to the p...
Definition bspline.hpp:4516
auto igrad(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the gradient of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4381
static Ptr make_unique(const std::array< int64_t, BSplineCore::parDim_ > &ncoeffs, utils::TensorArray< BSplineCore::geoDim_ > &&coeffs, Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as unique pointer.
Definition bspline.hpp:3362
auto abs_diff(const BSplineCommon &other, int dim=-1)
Computes the absolute difference between two compatible B-spline objects.
Definition bspline.hpp:3544
auto igrad(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G, const torch::Tensor &coeff_indices_G) const
Returns a block-tensor with the gradient of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4464
auto div(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices) const
Returns a block-tensor with the divergence of the B-spline object with respect to the parametric vari...
Definition bspline.hpp:4044
std::shared_ptr< BSplineCommon > Ptr
Shared pointer for BSplineCommon.
Definition bspline.hpp:3297
auto hess(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices) const
Returns a block-tensor with the Hessian of the B-spline object in the points xi with respect to the p...
Definition bspline.hpp:4623
auto plot(const BSplineCommon< BSplineCoreColor > &color, const utils::TensorArray< BSplineCore::parDim_ > &xi, const nlohmann::json &json={}) const
Definition bspline.hpp:6292
static Ptr make_unique(const std::array< int64_t, BSplineCore::parDim_ > &ncoeffs, const utils::TensorArray< BSplineCore::geoDim_ > &coeffs, bool clone=false, Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as unique pointer.
Definition bspline.hpp:3353
static Ptr make_shared(const std::array< int64_t, BSplineCore::parDim_ > &ncoeffs, utils::TensorArray< BSplineCore::geoDim_ > &&coeffs, Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as shared pointer.
Definition bspline.hpp:3415
BSplineCommon(const BSplineCommon &)=default
Copy constructor.
auto hess(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices) const
Returns a block-tensor with the Hessian of the B-spline object in the points xi with respect to the p...
Definition bspline.hpp:4572
auto plot(const utils::TensorArray< BSplineCore::parDim_ > &xi, const nlohmann::json &json={}) const
Definition bspline.hpp:5440
static Ptr make_unique(const std::array< std::vector< typename BSplineCore::value_type >, BSplineCore::parDim_ > &kv, const utils::TensorArray< BSplineCore::geoDim_ > &coeffs, bool clone=false, Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as unique pointer.
Definition bspline.hpp:3379
auto curl(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices) const
Returns a block-tensor with the curl of the B-spline object with respect to the parametric variables.
Definition bspline.hpp:3723
static Ptr make_unique(Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as unique pointer.
Definition bspline.hpp:3339
BSplineCommon(BSplineCommon &&)=default
Move constructor.
auto plot(const nlohmann::json &json={}) const
Definition bspline.hpp:5424
BSplineCommon(BSplineCommon &&other, utils::TensorArray< BSplineCore::geoDim_ > &&coeffs)
Move constructor with external coefficients.
Definition bspline.hpp:3329
BSplineCommon & operator+=(const BSplineCommon &other)
Adds the coefficients of another B-spline object.
Definition bspline.hpp:6601
auto ilapl(const Geometry &G, const torch::Tensor &xi) const
Returns a block-tensor with the Laplacian of the B-spline object in the points xi with respect to the...
Definition bspline.hpp:5275
auto plot(const BSplineCommon< BSplineCoreColor > &color, const nlohmann::json &json={}) const
Definition bspline.hpp:5478
auto to() const
Returns a copy of the B-spline object with real_t type.
Definition bspline.hpp:3506
BSplineCommon operator+(const BSplineCommon &other) const
Returns a new B-spline object whose coefficients are the sum of that of two compatible B-spline objec...
Definition bspline.hpp:6515
auto icurl(const Geometry &G, const torch::Tensor &xi) const
Returns a block-tensor with the curl of the B-spline object in the points xi with respect to the phys...
Definition bspline.hpp:3832
auto ihess(const Geometry G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G) const
Returns a block-tensor with the Hessian of the B-spline object in the points xi with respect to the p...
Definition bspline.hpp:4735
auto idiv(const Geometry &G, const torch::Tensor &xi)
Returns a block-tensor with the divergence of the B-spline object with respect to the physical variab...
Definition bspline.hpp:4099
auto ijac(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the Jacobian of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:5019
auto boundingBox() const
Computes the bounding box of the B-spline object.
Definition bspline.hpp:3645
static Ptr make_shared(const std::array< int64_t, BSplineCore::parDim_ > &ncoeffs, enum init init=init::greville, Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as shared pointer.
Definition bspline.hpp:3398
auto div(const torch::Tensor &xi) const
Returns a block-tensor with the divergence of the B-spline object with respect to the parametric vari...
Definition bspline.hpp:3967
auto icurl(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the curl of the B-spline object in the points xi with respect to the phys...
Definition bspline.hpp:3841
auto grad(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices) const
Returns a block-tensor with the gradient of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4279
auto igrad(const Geometry &G, const torch::Tensor &xi) const
Returns a block-tensor with the gradient of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4372
auto jac(const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the Jacobian of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4865
BSplineCommon & operator/=(typename BSplineCore::value_type s)
Scales the coefficients by a scalar.
Definition bspline.hpp:6643
static Ptr make_shared(const std::array< int64_t, BSplineCore::parDim_ > &ncoeffs, const utils::TensorArray< BSplineCore::geoDim_ > &coeffs, bool clone=false, Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as shared pointer.
Definition bspline.hpp:3406
static Ptr make_unique(const std::array< std::vector< typename BSplineCore::value_type >, BSplineCore::parDim_ > &kv, enum init init=init::greville, Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as unique pointer.
Definition bspline.hpp:3370
BSplineCommon & operator-=(const BSplineCommon &other)
Substracts the coefficients of another B-spline object.
Definition bspline.hpp:6615
BSplineCommon operator-(const BSplineCommon &other) const
Returns a new B-spline object whose coefficients are the difference of that of two compatible B-splin...
Definition bspline.hpp:6533
BSplineCommon(const BSplineCommon &other, const utils::TensorArray< BSplineCore::geoDim_ > &coeffs, bool clone=false)
Copy constructor with external coefficients.
Definition bspline.hpp:3313
auto ilapl(const Geometry &G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const torch::Tensor &coeff_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G, const torch::Tensor &coeff_indices_G) const
Returns a block-tensor with the Laplacian of the B-spline object in the points xi with respect to the...
Definition bspline.hpp:5381
auto grad(const utils::TensorArray< BSplineCore::parDim_ > &xi) const
Returns a block-tensor with the gradient of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4243
auto to(torch::Device device) const
Returns a copy of the B-spline object with settings from device.
Definition bspline.hpp:3489
auto igrad(const Geometry G, const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices, const utils::TensorArray< Geometry::parDim()> &knot_indices_G) const
Returns a block-tensor with the gradient of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4417
auto lapl(const torch::Tensor &xi) const
Returns a block-tensor with the Laplacian of the B-spline object in the points xi with respect to the...
Definition bspline.hpp:5139
auto clone() const
Returns a clone of the B-spline object.
Definition bspline.hpp:3454
BSplineCommon operator/(std::array< typename BSplineCore::value_type, BSplineCore::geoDim()> v) const
Returns a new B-spline object whose coefficients are scaled by a vector.
Definition bspline.hpp:6583
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept override
Returns a string representation of the BSplineCommon object.
Definition bspline.hpp:6453
static Ptr make_shared(Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as shared pointer.
Definition bspline.hpp:3392
auto jac(const torch::Tensor &xi) const
Returns a block-tensor with the Jacobian of the B-spline object in the points xi with respect to the ...
Definition bspline.hpp:4856
static Ptr make_shared(const std::array< std::vector< typename BSplineCore::value_type >, BSplineCore::parDim_ > &kv, const utils::TensorArray< BSplineCore::geoDim_ > &coeffs, bool clone=false, Options< typename BSplineCore::value_type > options=Options< typename BSplineCore::value_type >{})
Creates a new B-spline object as shared pointer.
Definition bspline.hpp:3432
auto lapl(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices) const
Returns a block-tensor with the Laplacian of the B-spline object in the points xi with respect to the...
Definition bspline.hpp:5180
auto div(const utils::TensorArray< BSplineCore::parDim_ > &xi, const utils::TensorArray< BSplineCore::parDim_ > &knot_indices) const
Returns a block-tensor with the divergence of the B-spline object with respect to the parametric vari...
Definition bspline.hpp:4007
BSplineCommon & uniform_refine(int numRefine=1, int dim=-1)
Returns the B-spline object with uniformly refined knot and coefficient vectors.
Definition bspline.hpp:3448
auto plot(const std::initializer_list< utils::TensorArray< BSplineCore::parDim_ > > &xi, const nlohmann::json &json={}) const
Definition bspline.hpp:5458
auto to(Options< real_t > options) const
Returns a copy of the B-spline object with settings from options.
Definition bspline.hpp:3471
BSplineCommon operator*(typename BSplineCore::value_type s) const
Returns a new B-spline object whose coefficients are scaled by a scalar.
Definition bspline.hpp:6545
Abstract patch function base class.
Definition patch.hpp:25
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:90
Spline type.
Definition bspline.hpp:3233
Full qualified name descriptor.
Definition fqn.hpp:26
Container utility functions.
Full qualified name utility functions.
Integer sequence utility function.
Integer power utility function.
Linear algebra utility functions.
auto kron(T0 &&t0, T1 &&t1)
Computes the Kronecker-product between two or more tensors.
Definition linalg.hpp:210
std::array< torch::Tensor, N > TensorArray
Definition tensorarray.hpp:28
auto to_tensor(const std::array< T, N > &array, torch::IntArrayRef sizes=torch::IntArrayRef{-1}, const iganet::Options< T > &options=iganet::Options< T >{})
Converts an std::array to torch::Tensor.
Definition container.hpp:60
auto kronproduct(T0 &&t0, T1 &&t1)
Computes the directional Kronecker-product between two tensors along the given dimension.
Definition linalg.hpp:61
TensorArray< 1 > TensorArray1
Definition tensorarray.hpp:31
auto to_tensorAccessor(const torch::Tensor &tensor)
Converts a torch::Tensor object to a torch::TensorAccessor object.
Definition tensorarray.hpp:80
T prod(std::array< T, N > array, std::size_t start_index=0, std::size_t stop_index=N - 1)
Computes the (partial) product of all std::array entries.
Definition linalg.hpp:221
constexpr std::array< T, N - M > remove_from_back(std::array< T, N > array)
Derives an std::array object from a given std::array object dropping the last M entries.
Definition container.hpp:376
auto VSlice(torch::Tensor index, int64_t start_offset, int64_t stop_offset)
Vectorized version of torch::indexing::Slice (see https://pytorch.org/cppdocs/notes/tensor_indexing....
Definition vslice.hpp:47
auto dotproduct(T0 &&t0, T1 &&t1)
Computes the directional dot-product between two tensors with summation along the given dimension.
Definition linalg.hpp:37
auto to_ArrayRef(const std::array< T, N > &array)
Converts an std::array<int64_t, N> to a at::IntArrayRef object.
Definition container.hpp:192
Forward declaration of BlockTensor.
Definition blocktensor.hpp:46
Definition boundary.hpp:22
deriv
Enumerator for specifying the derivative of B-spline evaluation.
Definition bspline.hpp:74
constexpr auto operator+(deriv lhs, deriv rhs)
Adds two enumerators for specifying the derivative of B-spline evaluation.
Definition bspline.hpp:91
std::conjunction< std::is_base_of< detail::SplineType, T >... > is_SplineType
Type trait to check if T is a valid Spline type.
Definition bspline.hpp:3239
bool is_verbose(std::ostream &os)
Definition core.hpp:831
constexpr bool is_SplineType_v
Alias to the value of is_SplineType.
Definition bspline.hpp:3243
std::ostream & operator<<(std::ostream &os, const Boundary< Spline > &obj)
Print (as string) a Boundary object.
Definition boundary.hpp:1978
constexpr auto operator^(deriv lhs, short_t rhs)
Raises an enumerator for specifying the derivative of B-spline evaluation to a higher exponent.
Definition bspline.hpp:103
struct iganet::@0 Log
Logger.
init
Enumerator for specifying the initialization of B-spline coefficients.
Definition bspline.hpp:55
torch::serialize::InputArchive & operator>>(torch::serialize::InputArchive &archive, UniformBSplineCore< real_t, GeoDim, Degrees... > &obj)
De-serializes a B-spline object.
Definition bspline.hpp:2708
@ none
Definition boundary.hpp:38
short int short_t
Definition core.hpp:74
Serialization utility functions.
Serialization prototype.
Definition serialize.hpp:31
Computes the power of integer E to the N at compile time.
Definition integer_pow.hpp:22
Reverse index sequence.
Definition index_sequence.hpp:37
TensorArray utility functions.
#define TENSORARRAY_FORALL(obj, func,...)
Definition tensorarray.hpp:159
VSlice utility functions.