3 #include <sofa/helper/OptionsGroup.h>
5 #include <SofaCaribou/Forcefield/HyperelasticForcefield.inl>
6 #include <SofaCaribou/Topology/FictitiousGrid.h>
8 #include <Caribou/config.h>
9 #include <Caribou/Geometry/Hexahedron.h>
11 namespace caribou::geometry {
19 struct SubdividedGaussHexahedron;
22 static constexpr INTEGER_TYPE NumberOfGaussNodesAtCompileTime = caribou::Dynamic;
48 namespace SofaCaribou::forcefield {
54 template <
typename Element>
62 using GaussContainer =
typename Base::GaussContainer;
63 using Index = sofa::Index;
65 using typename Base::Mat33;
67 template <
typename ObjectType>
68 using Link = SingleLink<FictitiousGridHyperelasticForcefield<Element>, ObjectType, BaseLink::FLAG_STRONGLINK>;
73 , d_grid(initLink(
"fictitious_grid",
"Fictitious grid containing the elements on which this forcefield will be applied."))
74 , d_integration_method(initData(&d_integration_method,
77 Integration method used to integrate the stiffness matrix.
80 SubdividedVolume: Hexas are recursively subdivided into cubic subcells and these subcells are used to
81 compute the inside volume of the regular hexa's gauss points.
82 SubdividedGauss: Hexas are recursively subdivided into cubic subcells and these subcells are used to
83 add new gauss points. Gauss points outside of the boundary are ignored.
87 d_integration_method.setValue(sofa::helper::OptionsGroup(std::vector<std::string> {
88 "SubdividedVolume",
"SubdividedGauss"
90 sofa::helper::WriteAccessor<Data< sofa::helper::OptionsGroup >> integration_method = d_integration_method;
91 integration_method->setSelectedItem((
unsigned int) 0);
94 void init()
override {
96 msg_warning() <<
"No element found in the grid '" << d_grid->getPathName() <<
"'.";
97 }
else if (not d_grid.get()) {
99 auto containers = this->getContext()->template getObjects<FictitiousGrid>(BaseContext::Local);
100 if (containers.empty()) {
101 msg_warning() <<
"Could not find a fictitious grid in the current context.";
103 std::vector<FictitiousGrid *> suitable_containers;
104 for (
const auto & container : containers) {
105 d_grid.set(container);
107 suitable_containers.push_back(container);
112 if (suitable_containers.empty()) {
113 msg_warning() <<
"Could not find a suitable fictitious grid in the current context, they are all empty.";
114 }
else if (suitable_containers.size() > 1) {
115 d_grid.set(suitable_containers[0]);
117 "Multiple fictitious grid were found in the context node. The first one will be taken ('" << d_grid.get()->getPathName() <<
"'). " <<
118 "If it isn't the correct one, please specify which one contains the elements on which this force field will be applied " <<
119 "by explicitly setting the container's path in the '" << d_grid.getName() <<
"' parameter.";
120 msg_info() <<
"Automatically found the topology '" << d_grid.get()->getPathName() <<
"'.";
122 d_grid.set(suitable_containers[0]);
123 msg_info() <<
"Automatically found the topology '" << d_grid.get()->getPathName() <<
"'.";
139 return d_grid->number_of_cells();
148 auto get_element_nodes_indices(
const std::size_t & element_id)
const ->
const Index *
override {
149 if (not d_grid.get() or d_grid->number_of_cells() == 0) {
153 return &(d_grid->get_node_indices_of(element_id)[0]);
162 static auto mesh_is_compatible(
const sofa::core::topology::BaseMeshTopology *) ->
bool {
167 auto get_gauss_nodes(
const std::size_t & ,
const Element & )
const -> GaussContainer
override {
172 Link<FictitiousGrid> d_grid;
173 Data< sofa::helper::OptionsGroup > d_integration_method;
177 template <>
auto FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedVolumeHexahedron>::templateName(
const FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedVolumeHexahedron> *) -> std::string;
178 template <>
auto FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedVolumeHexahedron>::canCreate(FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedVolumeHexahedron>*, BaseContext*, BaseObjectDescription* arg) -> bool;
179 template <>
auto FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedVolumeHexahedron>::get_gauss_nodes(
const std::size_t & element_id,
const caribou::geometry::SubdividedVolumeHexahedron & e)
const -> GaussContainer;
180 extern template class FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedVolumeHexahedron>;
183 template <>
auto FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedGaussHexahedron>::templateName(
const FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedGaussHexahedron> *) -> std::string;
184 template <>
auto FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedGaussHexahedron>::canCreate(FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedGaussHexahedron>*, BaseContext*, BaseObjectDescription* arg) -> bool;
185 template <>
auto FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedGaussHexahedron>::get_gauss_nodes(
const std::size_t & element_id,
const caribou::geometry::SubdividedGaussHexahedron & e)
const -> GaussContainer;
186 extern template class FictitiousGridHyperelasticForcefield<caribou::geometry::SubdividedGaussHexahedron>;