Caribou
FictitiousGridElasticForce.h
1 #pragma once
2 
3 #include <sofa/core/behavior/ForceField.h>
4 #include <sofa/core/behavior/MechanicalState.h>
5 #include <sofa/helper/OptionsGroup.h>
6 
7 #include <SofaCaribou/Topology/FictitiousGrid.h>
8 
9 #include <Eigen/Sparse>
10 
11 #include <Caribou/Geometry/Hexahedron.h>
12 #include <Caribou/Geometry/RectangularHexahedron.h>
13 
14 namespace SofaCaribou::forcefield {
15 
16 using namespace sofa::core;
17 using namespace sofa::core::objectmodel;
18 using namespace sofa::core::behavior;
19 using namespace sofa::core::topology;
20 using sofa::defaulttype::Vec3Types;
21 
22 class FictitiousGridElasticForce : public ForceField<Vec3Types>
23 {
24 public:
25  SOFA_CLASS(FictitiousGridElasticForce, SOFA_TEMPLATE(ForceField, Vec3Types));
26 
27  // Type definitions
28  using DataTypes = Vec3Types;
29  using Inherit = ForceField<DataTypes>;
30  using VecCoord = typename DataTypes::VecCoord;
31  using VecDeriv = typename DataTypes::VecDeriv;
32  using Coord = typename DataTypes::Coord;
33  using Deriv = typename DataTypes::Deriv;
34  using Real = typename Coord::value_type;
35 
37 
40  static constexpr INTEGER_TYPE NumberOfNodes = caribou::geometry::traits<Hexahedron>::NumberOfNodesAtCompileTime;
41 
42 
43  template<int nRows, int nColumns, int Options=Eigen::RowMajor>
44  using Matrix = Eigen::Matrix<Real, nRows, nColumns, Options>;
45 
46  template<int nRows, int nColumns>
47  using Map = Eigen::Map<const Matrix<nRows, nColumns, Eigen::RowMajor>>;
48 
49  template<int nRows, int Options=0>
50  using Vector = Eigen::Matrix<Real, nRows, 1, Options>;
51 
52  template<int nRows>
53  using MapVector = Eigen::Map<const Vector<nRows, Eigen::ColMajor>>;
54 
55  using Mat33 = Matrix<3, 3, Eigen::RowMajor>;
56  using Vec3 = Vector<3>;
57  using Mat2424 = Matrix<24, 24, Eigen::RowMajor>;
58  using Vec24 = Vector<24>;
59 
60  template <typename ObjectType>
61  using Link = SingleLink<FictitiousGridElasticForce, ObjectType, BaseLink::FLAG_STRONGLINK>;
62 
63  // Data structures
64 
65  struct GaussNode {
66  Real weight = 0;
67  Matrix<NumberOfNodes, 3> dN_dx = Matrix<NumberOfNodes, 3, Eigen::RowMajor>::Zero();
68  Mat33 F = Mat33::Identity();
69  };
70 
72  enum class IntegrationMethod : unsigned int {
74  Regular = 0,
75 
79  SubdividedVolume = 1,
80 
84  SubdividedGauss = 2
85  };
86 
87  // Public methods
88 
90 
91  void init() override;
92  void reinit() override;
93 
94  void addForce(
95  const MechanicalParams* mparams,
96  Data<VecDeriv>& d_f,
97  const Data<VecCoord>& d_x,
98  const Data<VecDeriv>& d_v) override;
99 
100  void addDForce(
101  const MechanicalParams* /*mparams*/,
102  Data<VecDeriv>& /*d_df*/,
103  const Data<VecDeriv>& /*d_dx*/) override;
104 
105  void draw(const sofa::core::visual::VisualParams* vparams) override;
106 
107  SReal getPotentialEnergy(
108  const MechanicalParams* /* mparams */,
109  const Data<VecCoord>& /* d_x */) const override
110  {return 0;}
111 
112  void addKToMatrix(sofa::defaulttype::BaseMatrix * /*matrix*/, SReal /*kFact*/, unsigned int & /*offset*/) override;
113 
114  void computeBBox(const sofa::core::ExecParams* params, bool onlyVisible) override;
115 
116  template <typename T>
117  inline
118  Hexahedron hexahedron(std::size_t hexa_id, const T & x) const
119  {
120  auto * grid = d_grid_container.get();
121  const auto &node_indices = grid->get_node_indices_of(hexa_id);
122 
123  Matrix<8, 3> m;
124  for (std::size_t j = 0; j < 8; ++j) {
125  const auto &node_id = node_indices[j];
126  m.row(j) = MapVector<3>(&x[node_id][0]);
127  }
128 
129  return Hexahedron(m);
130  }
131 
132  inline
133  IntegrationMethod integration_method() const
134  {
135  const auto m = static_cast<IntegrationMethod> (d_integration_method.getValue().getSelectedId());
136  switch (m) {
137  case IntegrationMethod::Regular:
138  return IntegrationMethod::Regular;
139  case IntegrationMethod::SubdividedVolume:
140  return IntegrationMethod::SubdividedVolume;
141  case IntegrationMethod::SubdividedGauss:
142  return IntegrationMethod::SubdividedGauss;
143  default:
144  return IntegrationMethod::Regular;
145  }
146  }
147 
148  inline
149  std::string integration_method_as_string() const
150  {
151  return d_integration_method.getValue().getSelectedItem();
152  }
153 
154  inline
155  void set_integration_method(const IntegrationMethod & m) {
156  auto index = static_cast<unsigned int > (m);
157  sofa::helper::WriteAccessor<Data< sofa::helper::OptionsGroup >> d = d_integration_method;
158  d->setSelectedItem(index);
159  }
160 
161  const std::vector<GaussNode> & gauss_nodes_of(std::size_t hexahedron_id) const {
162  return p_quadrature_nodes[hexahedron_id];
163  }
164 
165  const Matrix<24, 24> & stiffness_matrix_of(std::size_t hexahedron_id) const {
166  return p_stiffness_matrices[hexahedron_id];
167  }
168 
170  const Eigen::SparseMatrix<Real> & K();
171 
173  const Vector<Eigen::Dynamic> & eigenvalues();
174 
176  Real cond();
177 
178 private:
180  virtual void compute_K();
181 
182 protected:
183  Data< Real > d_youngModulus;
184  Data< Real > d_poissonRatio;
185  Data< bool > d_linear_strain;
186  Data< bool > d_corotated;
187  Data< sofa::helper::OptionsGroup > d_integration_method;
188  Link<FictitiousGrid> d_grid_container;
189 
190 private:
191  bool recompute_compute_tangent_stiffness = false;
192  std::vector<Matrix<24, 24>> p_stiffness_matrices;
193  std::vector<std::vector<GaussNode>> p_quadrature_nodes;
194  std::vector<Mat33> p_initial_rotation;
195  std::vector<Mat33> p_current_rotation;
196  Eigen::SparseMatrix<Real> p_K;
197  Vector<Eigen::Dynamic> p_eigenvalues;
198  bool K_is_up_to_date;
199  bool eigenvalues_are_up_to_date;
200 
201 };
202 
203 } // namespace SofaCaribou::forcefield
caribou::geometry::Hexahedron< caribou::Linear >
SofaCaribou::topology::FictitiousGrid
Definition: FictitiousGrid.h:35
caribou::geometry::traits
Definition: Element.h:14
SofaCaribou::forcefield::FictitiousGridElasticForce::GaussNode
Definition: FictitiousGridElasticForce.h:65
SofaCaribou::forcefield::FictitiousGridElasticForce
Definition: FictitiousGridElasticForce.h:23
caribou::geometry::RectangularHexahedron
Definition: RectangularHexahedron.h:12
SofaCaribou::forcefield::FictitiousGridElasticForce::IntegrationMethod
IntegrationMethod
Integration method used to integrate the stiffness matrix.
Definition: FictitiousGridElasticForce.h:72