37 throw std::invalid_argument(
"An interface requires two valid patches");
39 throw std::invalid_argument(
"An interface requires two valid sides");
45 Patch &
patch(std::size_t endpoint) {
53 const Patch &
patch(std::size_t endpoint)
const {
61 const std::shared_ptr<Patch> &
patchPtr(std::size_t endpoint)
const {
70 assert(endpoint <
sides_.size());
96 std::array<std::shared_ptr<Patch>, 2>
patches_;
198 std::size_t index =
patches_.size();
207 std::size_t index =
patches_.size();
208 patches_.push_back(std::shared_ptr<Patch>(std::move(
patch)));
220 std::size_t secondPatch,
enum side secondSide) {
221 assert(firstPatch <
patches_.size());
222 assert(secondPatch <
patches_.size());
235 std::shared_ptr<Patch> secondPatch,
236 enum side secondSide) {
241 throw std::invalid_argument(
242 "Interface patches must belong to the MultiPatch");
245 interfaces_.emplace_back(std::move(firstPatch), firstSide,
246 std::move(secondPatch), secondSide);
282 const Patch &
patch(std::size_t index)
const {
293 const std::vector<std::shared_ptr<Patch>> &
patches()
const {
335 auto it = std::find_if(
337 [
patch](
const auto &candidate) { return candidate.get() == patch; });
339 throw std::runtime_error(
"Did not find the patch index");
358 [patchInterface](
const auto &candidate) {
359 return &candidate == patchInterface;
362 throw std::runtime_error(
"Did not find the patch interface index");
373 template <
typename P = Patch>
374 requires requires {
typename P::value_type; }
375 void load(
const std::string &filename,
const std::string &key =
"multipatch",
378 torch::serialize::InputArchive archive;
379 archive.load_from(filename);
380 read(archive, key, options);
389 template <
typename P = Patch>
390 requires requires {
typename P::value_type; }
391 torch::serialize::InputArchive &
read(torch::serialize::InputArchive &archive,
392 const std::string &key =
"multipatch",
396 archive.read(key +
".json", data);
397 data = data.to(torch::kCPU, torch::kUInt8).contiguous();
399 reinterpret_cast<const char *
>(data.data_ptr<uint8_t>());
408 void save(
const std::string &filename,
409 const std::string &key =
"multipatch")
const {
410 torch::serialize::OutputArchive archive;
411 write(archive, key).save_to(filename);
418 torch::serialize::OutputArchive &
419 write(torch::serialize::OutputArchive &archive,
420 const std::string &key =
"multipatch")
const {
421 const std::string serialized =
to_json().dump();
423 torch::from_blob(
const_cast<char *
>(serialized.data()),
424 {static_cast<int64_t>(serialized.size())},
425 torch::TensorOptions{}.dtype(torch::kUInt8))
427 archive.write(key +
".json", data);
437 template <
typename P = Patch>
438 requires requires {
typename P::value_type; }
441 typename P::value_type rtol =
typename P::value_type{1e-5},
442 typename P::value_type atol =
typename P::value_type{1e-8})
const {
461 os <<
"MultiPatch(\nparDim = " << Patch::parDim()
464 for (std::size_t patchIndex = 0; patchIndex <
patches_.size();
466 const auto json =
patches_[patchIndex]->to_json();
467 os <<
"patch[" << patchIndex <<
"] = {geoDim = " << json[
"geoDim"]
468 <<
", degrees = " << json[
"degrees"] <<
"}\n";
470 for (std::size_t interfaceIndex = 0; interfaceIndex <
interfaces_.size();
472 const auto &patchInterface =
interfaces_[interfaceIndex];
473 os <<
"interface[" << interfaceIndex <<
"] = {patch "
475 <<
static_cast<short_t>(patchInterface.side(0)) <<
" <-> patch "
477 <<
static_cast<short_t>(patchInterface.side(1)) <<
"}\n";
484 [[nodiscard]] nlohmann::json
to_json()
const {
486 json[
"parDim"] = Patch::parDim();
487 json[
"patches"] = nlohmann::json::array();
488 json[
"interfaces"] = nlohmann::json::array();
489 json[
"boundaries"] = nlohmann::json::array();
492 json[
"patches"].push_back(
patch->to_json());
495 nlohmann::json interfaceJson;
496 interfaceJson[
"patches"] = {
499 interfaceJson[
"sides"] = {
static_cast<short_t>(patchInterface.side(0)),
500 static_cast<short_t>(patchInterface.side(1))};
503 (
static_cast<short_t>(patchInterface.side(0)) - 1) / 2;
505 (
static_cast<short_t>(patchInterface.side(1)) - 1) / 2;
506 interfaceJson[
"direction"] = nlohmann::json::array();
507 interfaceJson[
"orientation"] = nlohmann::json::array();
508 for (
short_t axis = 0; axis < Patch::parDim(); ++axis) {
510 if (axis == firstAxis)
511 mappedAxis = secondAxis;
512 else if (axis == secondAxis)
513 mappedAxis = firstAxis;
514 interfaceJson[
"direction"].push_back(mappedAxis);
515 interfaceJson[
"orientation"].push_back(1);
517 json[
"interfaces"].push_back(std::move(interfaceJson));
520 for (std::size_t patchIndex = 0; patchIndex <
patches_.size();
522 for (
short_t patchSide = 1; patchSide <= 2 * Patch::parDim();
524 const bool isInterface =
526 [&](
const auto &patchInterface) {
527 return (patchInterface.patchPtr(0).get() ==
528 patches_[patchIndex].get() &&
529 patchInterface.side(0) == patchSide) ||
530 (patchInterface.patchPtr(1).get() ==
531 patches_[patchIndex].get() &&
532 patchInterface.side(1) == patchSide);
535 json[
"boundaries"].push_back(
536 {{
"patch", patchIndex}, {
"side", patchSide}});
547 template <
typename P = Patch>
548 requires requires {
typename P::value_type; }
552 if (json.at(
"parDim").get<
short_t>() != Patch::parDim())
553 throw std::runtime_error(
554 "MultiPatch JSON provides an incompatible parametric dimension");
556 const auto &patchJson = json.at(
"patches");
557 if (!patchJson.is_array() ||
559 throw std::runtime_error(
560 "MultiPatch JSON patch count does not match the patch container");
563 const bool createPatches = parsedPatches.empty();
565 parsedPatches.reserve(patchJson.size());
566 for (
const auto &item : patchJson) {
568 parsedPatches.push_back(
570 Patch::parDim()>(item, options));
571 }
catch (
const std::runtime_error &) {
572 parsedPatches.push_back(
574 Patch::geoDim(), Patch::parDim()>(
580 const auto &interfaceJson =
json.at(
"interfaces");
581 if (!interfaceJson.is_array())
582 throw std::runtime_error(
"MultiPatch JSON interfaces must be an array");
584 std::vector<interface_type> parsedInterfaces;
585 parsedInterfaces.reserve(interfaceJson.size());
586 for (
const auto &item : interfaceJson) {
587 const auto patchIndices = item.at(
"patches").get<std::array<size_t, 2>>();
588 const auto sides = item.at(
"sides").get<std::array<short_t, 2>>();
589 if (patchIndices[0] >= parsedPatches.size() ||
590 patchIndices[1] >= parsedPatches.size() || sides[0] <=
none ||
591 sides[0] > 2 * Patch::parDim() || sides[1] <=
none ||
592 sides[1] > 2 * Patch::parDim())
593 throw std::runtime_error(
"MultiPatch JSON has an invalid interface");
595 if (!item.at(
"direction").is_array() ||
596 item.at(
"direction").size() != Patch::parDim() ||
597 !item.at(
"orientation").is_array() ||
598 item.at(
"orientation").size() != Patch::parDim())
599 throw std::runtime_error(
600 "MultiPatch JSON has invalid interface orientation data");
602 parsedInterfaces.emplace_back(
603 parsedPatches[patchIndices[0]],
static_cast<enum
side>(sides[0]),
604 parsedPatches[patchIndices[1]],
static_cast<enum
side>(sides[1]));
608 for (std::size_t patchIndex = 0; patchIndex < parsedPatches.size();
610 parsedPatches[patchIndex]->
from_json(patchJson[patchIndex]);
612 patches_ = std::move(parsedPatches);
622 [[nodiscard]] pugi::xml_document
623 to_xml(
int id = 0,
const std::string &label =
"",
int index = -1)
const {
624 pugi::xml_document doc;
625 pugi::xml_node root = doc.append_child(
"xml");
626 to_xml(root,
id, label, index);
636 pugi::xml_node &
to_xml(pugi::xml_node &root,
int id = 0,
637 const std::string &label =
"",
int index = -1)
const {
638 for (std::size_t patchIndex = 0; patchIndex <
patches_.size(); ++patchIndex)
641 pugi::xml_node multiPatch = root.append_child(
"MultiPatch");
642 multiPatch.append_attribute(
"parDim") = Patch::parDim();
643 multiPatch.append_attribute(
"id") = id;
645 multiPatch.append_attribute(
"label") = label.c_str();
647 multiPatch.append_attribute(
"index") = index;
649 pugi::xml_node
patches = multiPatch.append_child(
"patches");
650 patches.append_attribute(
"type") =
"id_range";
652 const std::string range =
653 "0 " + std::to_string(
static_cast<int64_t
>(
patches_.size()) - 1);
654 patches.append_child(pugi::node_pcdata).set_value(range.c_str());
657 std::stringstream interfaceData;
659 interfaceData <<
"\n ";
660 const auto firstPatch =
findPatchIndex(patchInterface.patchPtr(0).get());
661 const auto secondPatch =
findPatchIndex(patchInterface.patchPtr(1).get());
663 (
static_cast<short_t>(patchInterface.side(0)) - 1) / 2;
665 (
static_cast<short_t>(patchInterface.side(1)) - 1) / 2;
667 interfaceData << firstPatch <<
' '
668 <<
static_cast<short_t>(patchInterface.side(0)) <<
' '
669 << secondPatch <<
' '
670 <<
static_cast<short_t>(patchInterface.side(1));
672 for (
short_t axis = 0; axis < Patch::parDim(); ++axis) {
674 if (axis == firstAxis)
675 mappedAxis = secondAxis;
676 else if (axis == secondAxis)
677 mappedAxis = firstAxis;
678 interfaceData <<
' ' << mappedAxis;
680 for (
short_t axis = 0; axis < Patch::parDim(); ++axis)
681 interfaceData <<
" 1";
684 interfaceData <<
"\n ";
685 multiPatch.append_child(
"interfaces")
686 .append_child(pugi::node_pcdata)
687 .set_value(interfaceData.str().c_str());
689 std::stringstream boundaryData;
690 for (std::size_t patchIndex = 0; patchIndex <
patches_.size();
692 for (
short_t patchSide = 1; patchSide <= 2 * Patch::parDim();
694 const bool isInterface =
696 [&](
const auto &patchInterface) {
697 return (patchInterface.patchPtr(0).get() ==
698 patches_[patchIndex].get() &&
699 patchInterface.side(0) == patchSide) ||
700 (patchInterface.patchPtr(1).get() ==
701 patches_[patchIndex].get() &&
702 patchInterface.side(1) == patchSide);
705 boundaryData <<
"\n " << patchIndex <<
' ' << patchSide;
708 if (!boundaryData.str().empty())
709 boundaryData <<
"\n ";
710 multiPatch.append_child(
"boundary")
711 .append_child(pugi::node_pcdata)
712 .set_value(boundaryData.str().c_str());
725 template <
typename P = Patch>
726 requires requires {
typename P::value_type; }
728 const std::string &label =
"",
int index = -1,
731 return from_xml(doc.child(
"xml"),
id, label, index, options);
742 template <
typename P = Patch>
743 requires requires {
typename P::value_type; }
745 const std::string &label =
"",
int index = -1,
748 pugi::xml_node multiPatch;
749 for (
const auto &candidate : root.children(
"MultiPatch")) {
750 if ((
id >= 0 ? candidate.attribute(
"id").as_int() ==
id : true) &&
751 (index >= 0 ? candidate.attribute(
"index").as_int() == index
753 (!label.empty() ? candidate.attribute(
"label").value() == label
755 multiPatch = candidate;
760 throw std::runtime_error(
"Did not find the MultiPatch XML node");
762 if (multiPatch.attribute(
"parDim").as_int() != Patch::parDim())
763 throw std::runtime_error(
764 "MultiPatch XML provides an incompatible parametric dimension");
766 const pugi::xml_node patchRange = multiPatch.child(
"patches");
768 std::string_view{patchRange.attribute(
"type").value()} !=
"id_range")
769 throw std::runtime_error(
"MultiPatch XML has no valid patch ID range");
771 std::stringstream rangeData(patchRange.child_value());
772 int64_t firstPatch = 0;
773 int64_t lastPatch = -1;
774 if (!(rangeData >> firstPatch >> lastPatch) || firstPatch != 0 ||
776 lastPatch + 1 !=
static_cast<int64_t
>(
patches_.size())))
777 throw std::runtime_error(
778 "MultiPatch XML patch range does not match the patch container");
781 const bool createPatches = parsedPatches.empty();
783 parsedPatches.reserve(
static_cast<std::size_t
>(lastPatch + 1));
784 for (int64_t patchIndex = 0; patchIndex <= lastPatch; ++patchIndex) {
786 parsedPatches.push_back(
788 Patch::parDim()>(root, patchIndex,
"", -1,
790 }
catch (
const std::runtime_error &) {
791 parsedPatches.push_back(
793 Patch::geoDim(), Patch::parDim()>(
794 root, patchIndex,
"", -1, options));
799 std::vector<interface_type> parsedInterfaces;
800 const pugi::xml_node interfaceNode = multiPatch.child(
"interfaces");
802 throw std::runtime_error(
"MultiPatch XML has no interfaces node");
804 std::stringstream interfaceData(interfaceNode.child_value());
806 while (std::getline(interfaceData, line)) {
807 std::stringstream item(line);
808 std::size_t firstPatchIndex;
809 std::size_t secondPatchIndex;
812 if (!(item >> firstPatchIndex >> firstSide >> secondPatchIndex >>
816 if (firstPatchIndex >= parsedPatches.size() ||
817 secondPatchIndex >= parsedPatches.size() || firstSide <=
none ||
818 firstSide > 2 * Patch::parDim() || secondSide <=
none ||
819 secondSide > 2 * Patch::parDim())
820 throw std::runtime_error(
"MultiPatch XML has an invalid interface");
823 for (
short_t entry = 0; entry < 2 * Patch::parDim(); ++entry) {
824 if (!(item >> topologyEntry))
825 throw std::runtime_error(
826 "MultiPatch XML has incomplete interface orientation data");
828 if (item >> topologyEntry)
829 throw std::runtime_error(
830 "MultiPatch XML has excess interface orientation data");
832 parsedInterfaces.emplace_back(
833 parsedPatches[firstPatchIndex],
static_cast<enum
side>(firstSide),
834 parsedPatches[secondPatchIndex],
static_cast<enum
side>(secondSide));
838 for (std::size_t patchIndex = 0; patchIndex < parsedPatches.size();
840 parsedPatches[patchIndex]->
from_xml(root,
static_cast<int>(patchIndex));
842 patches_ = std::move(parsedPatches);
848 template <
typename real_t>
850 const nlohmann::json &second, real_t rtol,
852 if (first.type() != second.type())
853 return first.is_number() && second.is_number() &&
854 std::abs(first.template get<real_t>() -
855 second.template get<real_t>()) <=
856 atol + rtol * std::abs(second.template get<real_t>());
857 if (first.is_number())
858 return std::abs(first.template get<real_t>() -
859 second.template get<real_t>()) <=
860 atol + rtol * std::abs(second.template get<real_t>());
861 if (first.is_array()) {
862 if (first.size() != second.size())
864 for (std::size_t i = 0; i < first.size(); ++i)
869 if (first.is_object()) {
870 if (first.size() != second.size())
872 for (
const auto &[key, value] : first.items()) {
873 const auto it = second.find(key);
874 if (it == second.end() || !
jsonIsClose(value, *it, rtol, atol))
879 return first == second;
894template <
typename Patch>
905template <
typename Patch>
906torch::serialize::OutputArchive &
907operator<<(torch::serialize::OutputArchive &archive,
909 return obj.
write(archive);
917template <
typename Patch>
918torch::serialize::InputArchive &
920 return obj.
read(archive);
Multi-patch container class.
Definition multipatch.hpp:105
MultiPatch & from_xml(const pugi::xml_node &root, int id=0, const std::string &label="", int index=-1, Options< typename P::value_type > options=Options< typename P::value_type >{})
Updates the multi-patch object from an XML node.
Definition multipatch.hpp:744
void pretty_print(std::ostream &os) const noexcept
Prints a human-readable representation of the multi-patch object.
Definition multipatch.hpp:460
void removeInterface(std::size_t index)
Removes a single interface.
Definition multipatch.hpp:260
MultiPatch(const MultiPatch &other)
Copy constructor.
Definition multipatch.hpp:116
auto rbegin() const
Returns a reverse const-iterator to the patches.
Definition multipatch.hpp:160
std::size_t findPatchIndex(const Patch *patch) const
Provides the findPatchIndex operation.
Definition multipatch.hpp:334
auto rend()
Returns a reverse iterator to the end of the patches.
Definition multipatch.hpp:168
interface_type & interface(std::size_t index)
Returns a non-constant reference to a single interface.
Definition multipatch.hpp:301
void clear()
Removes all patches.
Definition multipatch.hpp:266
std::size_t npatches() const
Returns the number of patches.
Definition multipatch.hpp:182
bool operator!=(const MultiPatch &other) const
Returns true if patches or topology differ.
Definition multipatch.hpp:456
bool operator==(const MultiPatch &other) const
Returns true if patches and topology are exactly equal.
Definition multipatch.hpp:449
auto crbegin() const noexcept
Provides the crbegin operation.
Definition multipatch.hpp:163
pugi::xml_node & to_xml(pugi::xml_node &root, int id=0, const std::string &label="", int index=-1) const
Appends the multi-patch object to an XML node.
Definition multipatch.hpp:636
auto end() const
Returns a const-iterator to the end of the patches.
Definition multipatch.hpp:147
std::vector< interface_type > interfaces_
Vector of patch-interface objects.
Definition multipatch.hpp:886
MultiPatch(MultiPatch &&other) noexcept
Move constructor.
Definition multipatch.hpp:121
std::size_t findPatchIndex(const Patch &patch) const
Returns the index of a given single patch.
Definition multipatch.hpp:327
pugi::xml_document to_xml(int id=0, const std::string &label="", int index=-1) const
Returns the multi-patch object as an XML document.
Definition multipatch.hpp:623
std::size_t addInterface(interface_type patchInterface)
Adds an interface object.
Definition multipatch.hpp:253
MultiPatch & from_xml(const pugi::xml_document &doc, int id=0, const std::string &label="", int index=-1, Options< typename P::value_type > options=Options< typename P::value_type >{})
Updates the multi-patch object from an XML document.
Definition multipatch.hpp:727
const std::vector< std::shared_ptr< Patch > > & patches() const
Provides the patches operation.
Definition multipatch.hpp:293
auto begin()
Returns an iterator to the patches.
Definition multipatch.hpp:129
std::size_t addPatch(std::shared_ptr< Patch > patch)
Adds a single patch.
Definition multipatch.hpp:197
bool isclose(const MultiPatch &other, typename P::value_type rtol=typename P::value_type{1e-5}, typename P::value_type atol=typename P::value_type{1e-8}) const
Returns true if patches and topology are close up to tolerances.
Definition multipatch.hpp:440
void load(const std::string &filename, const std::string &key="multipatch", Options< typename P::value_type > options=Options< typename P::value_type >{})
Loads the multi-patch object from a Torch archive file.
Definition multipatch.hpp:375
const Patch & patch(std::size_t index) const
Returns a constant reference to a single patch.
Definition multipatch.hpp:282
const std::vector< interface_type > & interfaces() const
Provides the interfaces operation.
Definition multipatch.hpp:320
std::size_t ninterfaces() const
Returns the number of interfaces.
Definition multipatch.hpp:186
auto rend() const
Returns a reverse const-iterator to the end of the patches.
Definition multipatch.hpp:173
std::vector< interface_type > & interfaces()
Returns the interfaces for range-based iteration.
Definition multipatch.hpp:317
std::size_t addInterface(std::size_t firstPatch, enum side firstSide, std::size_t secondPatch, enum side secondSide)
Adds an interface between two patches identified by index.
Definition multipatch.hpp:219
std::vector< std::shared_ptr< Patch > > patches_
Vector of single-patch objects.
Definition multipatch.hpp:883
MultiPatch()=default
Default constructor.
void save(const std::string &filename, const std::string &key="multipatch") const
Saves the multi-patch object to a Torch archive file.
Definition multipatch.hpp:408
nlohmann::json to_json() const
Returns the multi-patch object as a JSON object.
Definition multipatch.hpp:484
torch::serialize::OutputArchive & write(torch::serialize::OutputArchive &archive, const std::string &key="multipatch") const
Writes the multi-patch object into a Torch output archive.
Definition multipatch.hpp:419
std::size_t addPatch(std::unique_ptr< Patch > patch)
Provides the addPatch operation.
Definition multipatch.hpp:206
std::size_t findInterfaceIndex(const interface_type &patchInterface) const
Returns the index of a given patch interface.
Definition multipatch.hpp:349
auto rbegin()
Returns a reverse iterator to the patches.
Definition multipatch.hpp:155
std::size_t findInterfaceIndex(const interface_type *patchInterface) const
Provides the findInterfaceIndex operation.
Definition multipatch.hpp:356
std::vector< std::shared_ptr< Patch > > & patches()
Returns a reference to the vector of patches.
Definition multipatch.hpp:290
auto begin() const
Returns a const-iterator to the patches.
Definition multipatch.hpp:134
std::size_t nboundaries() const
Returns the number of outer boundaries.
Definition multipatch.hpp:190
static bool jsonIsClose(const nlohmann::json &first, const nlohmann::json &second, real_t rtol, real_t atol)
Definition multipatch.hpp:849
torch::serialize::InputArchive & read(torch::serialize::InputArchive &archive, const std::string &key="multipatch", Options< typename P::value_type > options=Options< typename P::value_type >{})
Reads the multi-patch object from a Torch input archive.
Definition multipatch.hpp:391
MultiPatch & from_json(const nlohmann::json &json, Options< typename P::value_type > options=Options< typename P::value_type >{})
Updates the multi-patch object from a JSON object.
Definition multipatch.hpp:549
auto cbegin() const noexcept
Provides the cbegin operation.
Definition multipatch.hpp:137
Patch & patch(std::size_t index)
Returns a non-constant reference to a single patch.
Definition multipatch.hpp:274
auto crend() const noexcept
Provides the crend operation.
Definition multipatch.hpp:176
auto cend() const noexcept
Provides the cend operation.
Definition multipatch.hpp:150
const interface_type & interface(std::size_t index) const
Returns a constant reference to a single interface.
Definition multipatch.hpp:309
auto end()
Returns an iterator to the end of the patches.
Definition multipatch.hpp:142
std::size_t addInterface(std::shared_ptr< Patch > firstPatch, enum side firstSide, std::shared_ptr< Patch > secondPatch, enum side secondSide)
Adds an interface between two patches.
Definition multipatch.hpp:233
The Options class handles the automated determination of dtype from the template argument and the sel...
Definition options.hpp:47
Connection between two patch sides.
Definition multipatch.hpp:24
std::array< enum side, 2 > sides_
Definition multipatch.hpp:97
const Patch & firstPatch() const
Provides the firstPatch operation.
Definition multipatch.hpp:80
const Patch & patch(std::size_t endpoint) const
Returns one of the two patches.
Definition multipatch.hpp:53
std::array< std::shared_ptr< Patch >, 2 > patches_
Definition multipatch.hpp:96
Patch & secondPatch()
Provides the secondPatch operation.
Definition multipatch.hpp:83
const std::shared_ptr< Patch > & patchPtr(std::size_t endpoint) const
Returns the shared pointer to one of the two patches.
Definition multipatch.hpp:61
Patch & patch(std::size_t endpoint)
Returns one of the two patches.
Definition multipatch.hpp:45
const Patch & secondPatch() const
Provides the secondPatch operation.
Definition multipatch.hpp:86
PatchInterface(std::shared_ptr< Patch > firstPatch, enum side firstSide, std::shared_ptr< Patch > secondPatch, enum side secondSide)
Constructor.
Definition multipatch.hpp:32
Patch & firstPatch()
Named endpoint accessors.
Definition multipatch.hpp:77
enum side firstSide() const
Provides the firstSide operation.
Definition multipatch.hpp:89
enum side secondSide() const
Provides the secondSide operation.
Definition multipatch.hpp:92
enum side side(std::size_t endpoint) const
Returns the side of one of the two patches.
Definition multipatch.hpp:69
std::shared_ptr< iganet::BSplinePatch< real_t, GeoDim, ParDim > > createUniformBSpline(const std::array< iganet::short_t, ParDim > °rees, const std::array< int64_t, ParDim > &ncoeffs, enum iganet::init init=iganet::init::greville, iganet::Options< real_t > options=iganet::Options< real_t >{})
Create tensor-product uniform B-spline.
Definition bspline.hpp:7729
std::shared_ptr< iganet::BSplinePatch< real_t, GeoDim, ParDim > > createNonUniformBSpline(const std::array< iganet::short_t, ParDim > °rees, const std::array< int64_t, ParDim > &ncoeffs, enum iganet::init init=iganet::init::greville, iganet::Options< real_t > options=iganet::Options< real_t >{})
Create tensor-product non-uniform B-spline.
Definition bspline.hpp:7823
std::ostream & operator<<(std::ostream &os, const MemoryDebugger< id > &obj)
Prints a memory debugger object.
Definition memory.hpp:145
torch::serialize::InputArchive & operator>>(torch::serialize::InputArchive &archive, UniformBSplineCore< real_t, GeoDim, Degrees... > &obj)
Deserializes a B-spline object.
Definition bspline.hpp:3274
side
Identifiers for topological sides.
Definition boundary.hpp:25
@ none
Definition boundary.hpp:38
short int short_t
Signed short integer type used by IgANet's compact enumerations.
Definition core.hpp:76