template<bool simple> static void add_gradient_helper(RawArray<const Vector<int,4>> bends, RawArray<const CubicHinges<TV3>::Info> info, const T scale, RawArray<const TV3> X, SolidMatrix<TV3>& matrix) { if (!scale) return; for (int b=0;b<bends.size();b++) { const auto& I = info[b]; int i0,i1,i2,i3;bends[b].get(i0,i1,i2,i3); const T quad = -scale*I.dot; matrix.add_entry(i0,quad*sqr(I.c[0])); matrix.add_entry(i1,quad*sqr(I.c[1])); matrix.add_entry(i2,quad*sqr(I.c[2])); matrix.add_entry(i3,quad*sqr(I.c[3])); if (simple) { matrix.add_entry(i0,i1,quad*I.c[0]*I.c[1]); matrix.add_entry(i0,i2,quad*I.c[0]*I.c[2]); matrix.add_entry(i0,i3,quad*I.c[0]*I.c[3]); matrix.add_entry(i1,i2,quad*I.c[1]*I.c[2]); matrix.add_entry(i1,i3,quad*I.c[1]*I.c[3]); matrix.add_entry(i2,i3,quad*I.c[2]*I.c[3]); } else { const T cubic = -scale*I.det; const TV3 x0 = cubic*X[i0], x1 = cubic*X[i1], x2 = cubic*X[i2], x3 = cubic*X[i3]; matrix.add_entry(i0,i1,quad*I.c[0]*I.c[1]+cross_product_matrix(x3-x2)); // e3 matrix.add_entry(i0,i2,quad*I.c[0]*I.c[2]+cross_product_matrix(x1-x3)); // -e1 matrix.add_entry(i0,i3,quad*I.c[0]*I.c[3]+cross_product_matrix(x2-x1)); // e0 matrix.add_entry(i1,i2,quad*I.c[1]*I.c[2]+cross_product_matrix(x3-x0)); matrix.add_entry(i1,i3,quad*I.c[1]*I.c[3]+cross_product_matrix(x0-x2)); // e4 matrix.add_entry(i2,i3,quad*I.c[2]*I.c[3]+cross_product_matrix(x1-x0)); // -e2 } } }
template<bool definite> void SimpleShell::add_elastic_gradient_helper(SolidMatrix<TV>& matrix) const { const int m = 3, d = 2; Matrix<T,m> dGdD[d+1][d+1]; for (const auto& I : info) { for (int i=0;i<d;i++) for (int j=0;j<m;j++) { Matrix<T,m,d> dDs; dDs(j,i) = 1; Matrix<T,m,d> dG = force_differential<definite>(I,dDs); for (int k=0;k<d;k++) dGdD[k+1][i+1].set_column(j,dG.column(k)); } Matrix<T,m> sum; for (int i=0;i<d;i++) { Matrix<T,m> sum_i; for (int j=0;j<d;j++) sum_i -= dGdD[i+1][j+1]; dGdD[i+1][0] = sum_i; sum -= sum_i; } dGdD[0][0] = sum; for (int j=0;j<d+1;j++) for (int i=j;i<d+1;i++) matrix.add_entry(I.nodes[i],I.nodes[j],dGdD[i][j]); } }
template<bool simple> static void add_gradient_helper(RawArray<const Vector<int,3>> bends, RawArray<const CubicHinges<TV2>::Info> info, const T scale, RawArray<const TV2> X, SolidMatrix<TV2>& matrix) { if (!scale) return; for (int b=0;b<bends.size();b++) { const auto& I = info[b]; int i0,i1,i2;bends[b].get(i0,i1,i2); const T quad = -scale*I.dot; matrix.add_entry(i0,quad*sqr(I.c[0])); matrix.add_entry(i1,quad*sqr(I.c[1])); matrix.add_entry(i2,quad*sqr(I.c[2])); if (simple) { matrix.add_entry(i0,i1,quad*I.c[0]*I.c[1]); matrix.add_entry(i0,i2,quad*I.c[0]*I.c[2]); matrix.add_entry(i1,i2,quad*I.c[1]*I.c[2]); } else { const T a = scale*I.det; const Matrix<T,2> anti(0,a,-a,0); // x'Ay = cross(x,y), scaled matrix.add_entry(i0,i1,quad*I.c[0]*I.c[1]-anti); matrix.add_entry(i0,i2,quad*I.c[0]*I.c[2]+anti); matrix.add_entry(i1,i2,quad*I.c[1]*I.c[2]-anti); } } }