Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorover0219 <over0219@umn.edu>2020-06-03 03:53:14 +0300
committerover0219 <over0219@umn.edu>2020-06-03 03:53:14 +0300
commit9ba5c8b90aa6245c569f7e66b0cd472beb59b5a5 (patch)
treedf2c36e90a6f5003b6e02e45b0612cf250575983 /extern/softbody/src/admmpd_energy.cpp
parent2deb6c51778701135a54c05043a123a715cde938 (diff)
first commit. interfaced to very basic admmpd solver, but requires restart to begin sim as caching not working for velocity. lattice is simply a packed 5-tet cube around mesh.
Diffstat (limited to 'extern/softbody/src/admmpd_energy.cpp')
-rw-r--r--extern/softbody/src/admmpd_energy.cpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/extern/softbody/src/admmpd_energy.cpp b/extern/softbody/src/admmpd_energy.cpp
new file mode 100644
index 00000000000..978fd565aa4
--- /dev/null
+++ b/extern/softbody/src/admmpd_energy.cpp
@@ -0,0 +1,112 @@
+
+
+
+#include "admmpd_energy.h"
+
+namespace admmpd {
+using namespace Eigen;
+
+Lame::Lame() : m_model(0)
+{
+ set_from_youngs_poisson(10000000,0.299);
+}
+
+void Lame::set_from_youngs_poisson(double youngs, double poisson)
+{
+ m_mu = youngs/(2.0*(1.0+poisson));
+ m_lambda = youngs*poisson/((1.0+poisson)*(1.0-2.0*poisson));
+ m_bulk_mod = m_lambda + (2.0/3.0)*m_mu;
+}
+
+void EnergyTerm::signed_svd(
+ const Eigen::Matrix<double,3,3>& A,
+ Eigen::Matrix<double,3,3> &U,
+ Eigen::Matrix<double,3,1> &S,
+ Eigen::Matrix<double,3,3> &V)
+{
+ JacobiSVD<Matrix3d> svd(A, ComputeFullU | ComputeFullV);
+ S = svd.singularValues();
+ U = svd.matrixU();
+ V = svd.matrixV();
+ Matrix3d J = Matrix3d::Identity();
+ J(2,2) = -1.0;
+ if( U.determinant() < 0.0 )
+ {
+ U = U * J;
+ S[2] = -S[2];
+ }
+ if( V.determinant() < 0.0 )
+ {
+ Matrix3d Vt = V.transpose();
+ Vt = J * Vt;
+ V = Vt.transpose();
+ S[2] = -S[2];
+ }
+}
+
+void EnergyTerm::update(
+ int index,
+ const Lame &lame,
+ double rest_volume,
+ double weight,
+ const Eigen::MatrixXd *x,
+ const Eigen::MatrixXd *Dx,
+ Eigen::MatrixXd *z,
+ Eigen::MatrixXd *u)
+{
+ Matrix3d Dix = Dx->block<3,3>(index,0);
+ Matrix3d ui = u->block<3,3>(index,0);
+ Matrix3d zi = Dix + ui;
+
+ Matrix3d U, V;
+ Vector3d S;
+ signed_svd(zi, U, S, V);
+ S = Vector3d::Ones();
+
+ Matrix3d p = U * S.asDiagonal() * V.transpose();
+ double k = lame.m_bulk_mod;
+ double kv = k * rest_volume;
+ double w2 = weight*weight;
+ zi = (kv*p + w2*zi) / (w2 + kv);
+ ui += (Dix - zi);
+
+ u->block<3,3>(index,0) = ui;
+ z->block<3,3>(index,0) = zi;
+
+} // end EnergyTerm::update
+
+int EnergyTerm::init_tet(
+ int index,
+ const Lame &lame,
+ const Eigen::Matrix<int,1,4> &prim,
+ const Eigen::MatrixXd *x,
+ double &volume,
+ double &weight,
+ std::vector< Eigen::Triplet<double> > &triplets )
+{
+ Matrix<double,3,3> edges;
+ edges.col(0) = x->row(prim[1]) - x->row(prim[0]);
+ edges.col(1) = x->row(prim[2]) - x->row(prim[0]);
+ edges.col(2) = x->row(prim[3]) - x->row(prim[0]);
+ Matrix<double,3,3> edges_inv = edges.inverse();
+ volume = edges.determinant() / 6.0f;
+ if( volume < 0 )
+ throw std::runtime_error("**Solver::energy_init: Inverted initial tet");
+ double k = lame.m_bulk_mod;
+ weight = std::sqrt(k*volume);
+ Matrix<double,4,3> S = Matrix<double,4,3>::Zero();
+ S(0,0) = -1; S(0,1) = -1; S(0,2) = -1;
+ S(1,0) = 1; S(2,1) = 1; S(3,2) = 1;
+ Eigen::Matrix<double,4,3> D = S * edges_inv;
+ Eigen::Matrix<double,3,4> Dt = D.transpose();
+ int rows[3] = { index+0, index+1, index+2 };
+ int cols[4] = { prim[0], prim[1], prim[2], prim[3] };
+ for( int r=0; r<3; ++r ){
+ for( int c=0; c<4; ++c ){
+ triplets.emplace_back(rows[r], cols[c], Dt(r,c));
+ }
+ }
+ return 3;
+}
+
+} // end namespace mcl