1
+ #include " Integrator.h"
2
+
3
+ #include " Kernels.h"
4
+ #include " pbat/math/linalg/mini/Mini.h"
5
+ #include " pbat/physics/StableNeoHookeanEnergy.h"
6
+
7
+ #include < tbb/parallel_for.h>
8
+ #include < type_traits>
9
+
10
+ namespace pbat {
11
+ namespace sim {
12
+ namespace vbd {
13
+
14
+ Integrator::Integrator (Data&& dataIn) : data(dataIn) {}
15
+
16
+ void Integrator::Step (Scalar dt, Index iterations, Index substeps, Scalar rho)
17
+ {
18
+ Scalar sdt = dt / (static_cast <Scalar>(substeps));
19
+ Scalar sdt2 = sdt * sdt;
20
+ auto const nVertices = data.x .cols ();
21
+ using IndexType = std::remove_const_t <decltype (nVertices)>;
22
+ bool const bUseChebyshevAcceleration = rho > Scalar (0 ) and rho < Scalar (1 );
23
+ using namespace math ::linalg;
24
+ using mini::FromEigen;
25
+ using mini::ToEigen;
26
+ for (auto s = 0 ; s < substeps; ++s)
27
+ {
28
+ // Store previous positions
29
+ data.xt = data.x ;
30
+ // Compute inertial target positions
31
+ tbb::parallel_for (IndexType (0 ), nVertices, [&](auto i) {
32
+ auto xtilde = kernels::InertialTarget (
33
+ FromEigen (data.xt .col (i).head <3 >()),
34
+ FromEigen (data.vt .col (i).head <3 >()),
35
+ FromEigen (data.aext .col (i).head <3 >()),
36
+ sdt,
37
+ sdt2);
38
+ data.xtilde .col (i) = ToEigen (xtilde);
39
+ });
40
+ // Initialize block coordinate descent's, i.e. BCD's, solution
41
+ tbb::parallel_for (IndexType (0 ), nVertices, [&](auto i) {
42
+ auto x = kernels::InitialPositionsForSolve (
43
+ FromEigen (data.xt .col (i).head <3 >()),
44
+ FromEigen (data.vt .col (i).head <3 >()),
45
+ FromEigen (data.v .col (i).head <3 >()),
46
+ FromEigen (data.aext .col (i).head <3 >()),
47
+ sdt,
48
+ sdt2,
49
+ data.initializationStrategy );
50
+ data.x .col (i) = ToEigen (x);
51
+ });
52
+ // Initialize Chebyshev semi-iterative method
53
+ Scalar omega{};
54
+ Scalar rho2 = rho * rho;
55
+ // Minimize Backward Euler, i.e. BDF1, objective
56
+ for (auto k = 0 ; k < iterations; ++k)
57
+ {
58
+ if (bUseChebyshevAcceleration)
59
+ omega = kernels::ChebyshevOmega (k, rho2, omega);
60
+
61
+ for (auto const & partition : data.partitions )
62
+ {
63
+ auto const nVerticesInPartition = static_cast <std::size_t >(partition.size ());
64
+ tbb::parallel_for (std::size_t (0 ), nVerticesInPartition, [&](auto v) {
65
+ auto i = partition[v];
66
+ auto begin = data.GVGp [i];
67
+ auto end = data.GVGp [i + 1 ];
68
+ // Compute vertex elastic hessian
69
+ mini::SMatrix<Scalar, 3 , 3 > Hi = mini::Zeros<Scalar, 3 , 3 >();
70
+ mini::SVector<Scalar, 3 > gi = mini::Zeros<Scalar, 3 , 1 >();
71
+ for (auto n = begin; n < end; ++n)
72
+ {
73
+ auto ilocal = data.GVGilocal [n];
74
+ auto e = data.GVGe [n];
75
+ auto g = data.GVGn [n];
76
+ auto lamee = data.lame .col (g);
77
+ auto wg = data.wg [g];
78
+ auto Te = data.T .col (e);
79
+ mini::SMatrix<Scalar, 4 , 3 > GPe = FromEigen (data.GP .block <4 , 3 >(0 , e * 3 ));
80
+ mini::SMatrix<Scalar, 3 , 4 > xe =
81
+ FromEigen (data.x (Eigen::all, Te).block <3 , 4 >(0 , 0 ));
82
+ mini::SMatrix<Scalar, 3 , 3 > Fe = xe * GPe;
83
+ physics::StableNeoHookeanEnergy<3 > Psi{};
84
+ mini::SVector<Scalar, 9 > gF ;
85
+ mini::SMatrix<Scalar, 9 , 9 > HF;
86
+ Psi.gradAndHessian (Fe, lamee (0 ), lamee (1 ), gF , HF);
87
+ kernels::AccumulateElasticHessian (ilocal, wg, GPe, HF, Hi);
88
+ kernels::AccumulateElasticGradient (ilocal, wg, GPe, gF , gi);
89
+ }
90
+ // Update vertex position
91
+ Scalar m = data.m [i];
92
+ mini::SVector<Scalar, 3 > xti = FromEigen (data.xt .col (i).head <3 >());
93
+ mini::SVector<Scalar, 3 > xtildei = FromEigen (data.xtilde .col (i).head <3 >());
94
+ mini::SVector<Scalar, 3 > xi = FromEigen (data.x .col (i).head <3 >());
95
+ kernels::AddDamping (sdt, xti, xi, data.kD , gi, Hi);
96
+ kernels::AddInertiaDerivatives (sdt2, m, xtildei, xi, gi, Hi);
97
+ kernels::IntegratePositions (gi, Hi, xi, data.detHZero );
98
+ data.x .col (i) = ToEigen (xi);
99
+ });
100
+ }
101
+
102
+ if (bUseChebyshevAcceleration)
103
+ {
104
+ tbb::parallel_for (IndexType (0 ), nVertices, [&](auto i) {
105
+ auto xkm2eig = data.xchebm2 .col (i).head <3 >();
106
+ auto xkm1eig = data.xchebm1 .col (i).head <3 >();
107
+ auto xkeig = data.x .col (i).head <3 >();
108
+ auto xkm2 = FromEigen (xkm2eig);
109
+ auto xkm1 = FromEigen (xkm1eig);
110
+ auto xk = FromEigen (xkeig);
111
+ kernels::ChebyshevUpdate (k, omega, xkm2, xkm1, xk);
112
+ });
113
+ }
114
+ }
115
+ // Update velocity
116
+ tbb::parallel_for (IndexType (0 ), nVertices, [&](auto i) {
117
+ kernels::IntegrateVelocity (
118
+ FromEigen (data.xt .col (i).head <3 >()),
119
+ FromEigen (data.x .col (i).head <3 >()),
120
+ sdt);
121
+ });
122
+ }
123
+ }
124
+
125
+ } // namespace vbd
126
+ } // namespace sim
127
+ } // namespace pbat
0 commit comments