// Copyright 2013 - Christian Schüller 2013, schuellc@inf.ethz.ch // Interactive Geometry Lab - ETH Zurich #include "GreenStrain_LIMSolver3D.h" #include "TetrahedronMesh.h" GreenStrain_LIMSolver3D::GreenStrain_LIMSolver3D() { Beta = 100; } GreenStrain_LIMSolver3D::~GreenStrain_LIMSolver3D() { } void GreenStrain_LIMSolver3D::debugOutput(std::stringstream& info) { std::cout << "GS:" << info.str() << "\n"; } void GreenStrain_LIMSolver3D::prepareProblemData(std::vector& hessRowIdx, std::vector& hessColIdx) { const int numNodes = mesh->InitalVertices->rows(); // Compute deformation gradients int numTets = mesh->Tetrahedra->rows(); Ms.resize(4,3*numTets); MMTs.resize(4,4*numTets); Eigen::Matrix SelectorM; SelectorM.block<3,3>(0,0) = Eigen::Matrix3d::Identity(); SelectorM.row(3) = Eigen::Vector3d::Ones()*-1; for(int t=0;tInitalVertices->row(mesh->Tetrahedra->coeff(t,0)).cast(); Eigen::Vector3d B = mesh->InitalVertices->row(mesh->Tetrahedra->coeff(t,1)).cast(); Eigen::Vector3d C = mesh->InitalVertices->row(mesh->Tetrahedra->coeff(t,2)).cast(); Eigen::Vector3d D = mesh->InitalVertices->row(mesh->Tetrahedra->coeff(t,3)).cast(); Eigen::Matrix3d V; V << A-D,B-D,C-D; Eigen::Matrix Mtemp = SelectorM*V.inverse().cast(); Ms.block<4,3>(0,3*t) = Mtemp; MMTs.block<4,4>(0,4*t) = Mtemp*Mtemp.transpose(); } } double GreenStrain_LIMSolver3D::computeFunction(const Eigen::Matrix& x) { // green strain energy double shape = 0; Eigen::Matrix3d I = Eigen::Matrix3d::Identity(); for(int t=0;tTetrahedra->rows();t++) { Eigen::Vector3d A(x[TetrahedronVertexIdx.coeff(0,t)],x[TetrahedronVertexIdx.coeff(1,t)],x[TetrahedronVertexIdx.coeff(2,t)]); Eigen::Vector3d B(x[TetrahedronVertexIdx.coeff(3,t)],x[TetrahedronVertexIdx.coeff(4,t)],x[TetrahedronVertexIdx.coeff(5,t)]); Eigen::Vector3d C(x[TetrahedronVertexIdx.coeff(6,t)],x[TetrahedronVertexIdx.coeff(7,t)],x[TetrahedronVertexIdx.coeff(8,t)]); Eigen::Vector3d D(x[TetrahedronVertexIdx.coeff(9,t)],x[TetrahedronVertexIdx.coeff(10,t)],x[TetrahedronVertexIdx.coeff(11,t)]); Eigen::Matrix V; V.col(0) = A; V.col(1) = B; V.col(2) = C; V.col(3) = D; Eigen::Matrix3d F = V*Ms.block<4,3>(0,3*t); Eigen::Matrix3d E = (F.transpose()*F - I); shape += E.squaredNorm()*Divider; } return shape; } void GreenStrain_LIMSolver3D::computeGradient(const Eigen::Matrix& x, Eigen::Matrix& grad) { // green strain energy for(int t=0;tTetrahedra->rows();t++) { Eigen::Vector3d A(x[TetrahedronVertexIdx.coeff(0,t)],x[TetrahedronVertexIdx.coeff(1,t)],x[TetrahedronVertexIdx.coeff(2,t)]); Eigen::Vector3d B(x[TetrahedronVertexIdx.coeff(3,t)],x[TetrahedronVertexIdx.coeff(4,t)],x[TetrahedronVertexIdx.coeff(5,t)]); Eigen::Vector3d C(x[TetrahedronVertexIdx.coeff(6,t)],x[TetrahedronVertexIdx.coeff(7,t)],x[TetrahedronVertexIdx.coeff(8,t)]); Eigen::Vector3d D(x[TetrahedronVertexIdx.coeff(9,t)],x[TetrahedronVertexIdx.coeff(10,t)],x[TetrahedronVertexIdx.coeff(11,t)]); Eigen::Matrix V; V.col(0) = A; V.col(1) = B; V.col(2) = C; V.col(3) = D; // jacobian(E) = 4(VMM'V'VMM' - VMM') Eigen::Matrix VMMT = V*MMTs.block<4,4>(0,4*t); Eigen::Matrix T = 4*(VMMT*V.transpose()*VMMT - VMMT); for(int i=0;i<12;i++) grad[TetrahedronVertexIdx.coeff(i,t)] += T.coeff(i)*Divider; } } void GreenStrain_LIMSolver3D::computeHessian(const Eigen::Matrix& x, const Eigen::Matrix& hess) { // green strain tensor energy Eigen::Matrix S; for(int t=0;tTetrahedra->rows();t++) { Eigen::Vector3d A(x[TetrahedronVertexIdx.coeff(0,t)],x[TetrahedronVertexIdx.coeff(1,t)],x[TetrahedronVertexIdx.coeff(2,t)]); Eigen::Vector3d B(x[TetrahedronVertexIdx.coeff(3,t)],x[TetrahedronVertexIdx.coeff(4,t)],x[TetrahedronVertexIdx.coeff(5,t)]); Eigen::Vector3d C(x[TetrahedronVertexIdx.coeff(6,t)],x[TetrahedronVertexIdx.coeff(7,t)],x[TetrahedronVertexIdx.coeff(8,t)]); Eigen::Vector3d D(x[TetrahedronVertexIdx.coeff(9,t)],x[TetrahedronVertexIdx.coeff(10,t)],x[TetrahedronVertexIdx.coeff(11,t)]); Eigen::Matrix V; V.col(0) = A; V.col(1) = B; V.col(2) = C; V.col(3) = D; // hessian(E) = 4*r_x'*((SMM'V'V+VMM'*(V'S+SV))*MM' - SMM')*c_x Eigen::Matrix VTV = V.transpose()*V; Eigen::Matrix MMT = MMTs.block<4,4>(0,4*t); Eigen::Matrix VMMT = V*MMT; Eigen::Matrix MMTVTV = MMT*VTV; int numElem = 0; for(int r=0;r<12;r++) { S = Eigen::Matrix::Zero(3,4); S.coeffRef(r) = 1; Eigen::Matrix Temp = 4*((S*MMTVTV + VMMT*(V.transpose()*S+S.transpose()*V))*MMT - S*MMT); for(int c=r;c<12;c++) *denseHessianCoeffs(numElem++,t) += Temp.coeff(c)*Divider; } } }