[Bf-blender-cvs] [c2cffc2f8e2] soc-2020-soft-body: settings updates
mattoverby
noreply at git.blender.org
Tue Jul 28 23:43:18 CEST 2020
Commit: c2cffc2f8e21207765162bea561caa2395dd2164
Author: mattoverby
Date: Tue Jul 28 16:43:10 2020 -0500
Branches: soc-2020-soft-body
https://developer.blender.org/rBc2cffc2f8e21207765162bea561caa2395dd2164
settings updates
===================================================================
M extern/softbody/src/admmpd_energy.cpp
M extern/softbody/src/admmpd_energy.h
M extern/softbody/src/admmpd_geom.cpp
M extern/softbody/src/admmpd_geom.h
M extern/softbody/src/admmpd_linsolve.cpp
M extern/softbody/src/admmpd_linsolve.h
M extern/softbody/src/admmpd_mesh.cpp
M extern/softbody/src/admmpd_solver.cpp
M extern/softbody/src/admmpd_solver.h
M extern/softbody/src/admmpd_types.h
M intern/softbody/admmpd_api.cpp
M intern/softbody/admmpd_api.h
M release/scripts/startup/bl_ui/properties_physics_softbody.py
M source/blender/blenkernel/intern/softbody.c
M source/blender/makesdna/DNA_object_force_types.h
M source/blender/makesrna/intern/rna_object_force.c
===================================================================
diff --git a/extern/softbody/src/admmpd_energy.cpp b/extern/softbody/src/admmpd_energy.cpp
index 4271b182ac3..d7ca504fa37 100644
--- a/extern/softbody/src/admmpd_energy.cpp
+++ b/extern/softbody/src/admmpd_energy.cpp
@@ -10,7 +10,7 @@
namespace admmpd {
using namespace Eigen;
-Lame::Lame() : m_model(ELASTIC_ARAP)
+Lame::Lame() : m_material(ELASTIC_ARAP)
{
set_from_youngs_poisson(10000000,0.399);
}
@@ -90,7 +90,7 @@ void EnergyTerm::update_tet(
signed_svd(zi, U, S, V);
Vector3d s0 = S;
- switch (lame.m_model)
+ switch (lame.m_material)
{
default:
case ELASTIC_ARAP:
@@ -161,7 +161,7 @@ void EnergyTerm::solve_prox(
const Eigen::Vector3d &s0,
Eigen::Vector3d &s)
{
-
+ (void)(index);
Vector3d g; // gradient
Vector3d p; // descent
Vector3d s_prev;
@@ -235,7 +235,7 @@ double EnergyTerm::energy_density(
// Compute energy and gradient
// https://github.com/mattoverby/admm-elastic/blob/master/src/TetEnergyTerm.cpp
// I suppose I should add ARAP for completeness even though it's not used
- switch (lame.m_model)
+ switch (lame.m_material)
{
default: {
if (g != nullptr) g->setZero();
@@ -282,11 +282,11 @@ void EnergyTerm::hessian_spd(
static const Matrix3d I = Matrix3d::Identity();
// Compute specific Hessian
- switch (lame.m_model)
+ switch (lame.m_material)
{
default:
{
- H.setIdentity();
+ H.setIdentity(); // We don't use ARAP hessian
} break;
case ELASTIC_NH:
diff --git a/extern/softbody/src/admmpd_energy.h b/extern/softbody/src/admmpd_energy.h
index 953f1a7d81d..bc3886e9f25 100644
--- a/extern/softbody/src/admmpd_energy.h
+++ b/extern/softbody/src/admmpd_energy.h
@@ -7,18 +7,13 @@
#include <Eigen/Sparse>
#include <Eigen/Geometry>
#include <vector>
+#include "admmpd_types.h"
namespace admmpd {
-enum ELASTIC_ENERGY
-{
- ELASTIC_ARAP, // As-rigid-as-possible
- ELASTIC_NH // NeoHookean
-};
-
class Lame {
public:
- ELASTIC_ENERGY m_model;
+ int m_material;
double m_mu;
double m_lambda;
double m_bulk_mod;
diff --git a/extern/softbody/src/admmpd_geom.cpp b/extern/softbody/src/admmpd_geom.cpp
index f6a545276a6..e9fa2d65fbd 100644
--- a/extern/softbody/src/admmpd_geom.cpp
+++ b/extern/softbody/src/admmpd_geom.cpp
@@ -419,6 +419,29 @@ void geom::merge_close_vertices(
}
}
+template<typename T>
+void geom::make_n3(
+ const Eigen::SparseMatrix<T> &A,
+ Eigen::SparseMatrix<T> &A3)
+{
+ int na = A.rows();
+ A3.resize(na*3, na*3);
+ A3.reserve(A.nonZeros()*3);
+ int cols = A.rows();
+ for(int c=0; c<cols; ++c)
+ {
+ for(int dim=0; dim<3; ++dim)
+ {
+ int col = c*3+dim;
+ A3.startVec(col);
+ for(typename SparseMatrix<T>::InnerIterator itA(A,c); itA; ++itA)
+ A3.insertBack((itA.row()*3+dim), col) = itA.value();
+ }
+ }
+ A3.finalize();
+ A3.makeCompressed();
+}
+
//
// Compile template types
//
@@ -474,5 +497,11 @@ template bool admmpd::geom::ray_triangle<float>(
const Eigen::Vector3f&, const Eigen::Vector3f&,
const Eigen::Vector3f&, const Eigen::Vector3f&,
const Eigen::Vector3f&, float, float&, Eigen::Vector3f*);
+template void admmpd::geom::make_n3<float>(
+ const Eigen::SparseMatrix<float>&,
+ Eigen::SparseMatrix<float>&);
+template void admmpd::geom::make_n3<double>(
+ const Eigen::SparseMatrix<double>&,
+ Eigen::SparseMatrix<double>&);
} // namespace admmpd
diff --git a/extern/softbody/src/admmpd_geom.h b/extern/softbody/src/admmpd_geom.h
index 46da52e683c..3ef2fc8b882 100644
--- a/extern/softbody/src/admmpd_geom.h
+++ b/extern/softbody/src/admmpd_geom.h
@@ -5,6 +5,7 @@
#define ADMMPD_GEOM_H_
#include <Eigen/Geometry>
+#include <Eigen/Sparse>
#include <vector>
// Common geometry kernels
@@ -84,6 +85,12 @@ static void merge_close_vertices(
std::vector<Eigen::RowVector4i> &tets,
double eps = 1e-12);
+// Replicates a matrix along the diagonal
+template<typename T>
+static void make_n3(
+ const Eigen::SparseMatrix<T> &A,
+ Eigen::SparseMatrix<T> &A3);
+
}; // class geom
} // namespace admmpd
diff --git a/extern/softbody/src/admmpd_linsolve.cpp b/extern/softbody/src/admmpd_linsolve.cpp
index a4ff75ab77e..95751957a39 100644
--- a/extern/softbody/src/admmpd_linsolve.cpp
+++ b/extern/softbody/src/admmpd_linsolve.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT License.
#include "admmpd_linsolve.h"
+#include "admmpd_geom.h"
#include <numeric>
#include <iostream>
#include <set>
@@ -13,30 +14,26 @@
namespace admmpd {
using namespace Eigen;
-// Makes full n3 x n3 matrix
-static inline void make_n3(
- const RowSparseMatrix<double> &A,
- RowSparseMatrix<double> &A3)
+void ConjugateGradients::init_solve(
+ const Options *options,
+ SolverData *data)
{
- int na = A.rows();
- SparseMatrix<double> A_cm = A; // A to CM
- SparseMatrix<double> A3_cm(na*3, na*3);
- A3_cm.reserve(A_cm.nonZeros()*3);
- int cols = A_cm.rows();
- for(int c=0; c<cols; ++c)
- {
- for(int dim=0; dim<3; ++dim)
- {
- int col = c*3+dim;
- A3_cm.startVec(col);
- for(SparseMatrix<double>::InnerIterator itA(A_cm,c); itA; ++itA)
- A3_cm.insertBack((itA.row()*3+dim), col) = itA.value();
- }
- }
- A3_cm.finalize();
- A3_cm.makeCompressed();
- A3 = A3_cm; // to RowMajor
-} // end make_n3
+ int nx3 = 3*data->x.rows();
+ if (nx3==0)
+ return;
+
+ A3_PtP_CtC.resize(nx3,nx3);
+ CtC.resize(nx3,nx3);
+ Ctd.resize(nx3);
+ Ptq.resize(nx3);
+ b3_Ptq_Ctd.resize(nx3);
+ r.resize(nx3);
+ z.resize(nx3);
+ p.resize(nx3);
+ Ap.resize(nx3);
+ double pk = options->mult_pk * data->A_diag_max;
+ Ptq = pk * data->P.transpose()*data->q;
+}
void ConjugateGradients::solve(
const Options *options,
@@ -48,75 +45,65 @@ void ConjugateGradients::solve(
BLI_assert(options != NULL);
int nx = data->x.rows();
BLI_assert(nx > 0);
- BLI_assert(data->A.rows() == nx);
- BLI_assert(data->A.cols() == nx);
BLI_assert(data->b.rows() == nx);
BLI_assert(data->C.cols() == nx*3);
BLI_assert(data->d.rows() > 0);
BLI_assert(data->C.rows() == data->d.rows());
- BLI_assert(data->PtP.cols() == nx*3);
- BLI_assert(data->PtP.rows() == nx*3);
- // If we don't have any constraints, we don't need to perform CG
- data->b.noalias() = data->M_xbar + data->DtW2*(data->z-data->u);
- if (data->C.nonZeros()==0 && data->PtP.nonZeros()==0)
+ // Update A matrix with collision constraints
+ double ck = options->mult_ck * data->A_diag_max;
+ RowSparseMatrix<double> *A;
+ if (data->C.nonZeros()>0)
{
- data->x = data->ldltA.solve(data->b);
- return;
+ Ctd = ck * data->C.transpose()*data->d;
+ CtC = ck * data->C.transpose()*data->C;
+ A3_PtP_CtC = data->A3_plus_PtP + CtC;
+ A = &A3_PtP_CtC;
}
-
- // Resize data associated with Conjugate-Gradient
- admmpd::SolverData::GlobalStepData *gsdata = &data->gsdata;
- if (gsdata->r.rows() != nx*3)
+ else
{
- gsdata->r.resize(nx*3);
- gsdata->z.resize(nx*3);
- gsdata->p.resize(nx*3);
- gsdata->A3p.resize(nx*3);
- gsdata->b3_Ctd_Ptx.resize(nx*3);
- make_n3(data->A, gsdata->A3);
+ Ctd.setZero();
+ A = &data->A3_plus_PtP;
}
- double col_k = options->mult_ck * data->A_diag_max;
- gsdata->CtC = col_k * data->C.transpose()*data->C;
- gsdata->Ctd = col_k * data->C.transpose()*data->d;
- gsdata->A3_CtC_PtP = gsdata->A3 + gsdata->CtC + data->PtP;
+ // Compute RHS
VectorXd x3(nx*3);
+ data->b.noalias() = data->M_xbar + data->DtW2*(data->z-data->u);
for (int i=0; i<nx; ++i)
{
- gsdata->b3_Ctd_Ptx.segment<3>(i*3) =
+ b3_Ptq_Ctd.segment<3>(i*3) =
data->b.row(i).transpose() +
- gsdata->Ctd.segment<3>(i*3) +
- data->Ptq.segment<3>(i*3);
+ Ptq.segment<3>(i*3) +
+ Ctd.segment<3>(i*3);
x3.segment<3>(i*3) = data->x.row(i);
}
- gsdata->r.noalias() = gsdata->b3_Ctd_Ptx - gsdata->A3_CtC_PtP*x3;
- solve_Ax_b(data,&gsdata->z,&gsdata->r);
- gsdata->p = gsdata->z;
+ r.noalias() = b3_Ptq_Ctd - *A*x3; // b-Ax
+ z = data->ldlt_A3.solve(r);
+ p = z;
for (int iter=0; iter<options->max_cg_iters; ++iter)
{
- gsdata->A3p.noalias() = gsdata->A3_CtC_PtP*gsdata->p;
- double p_dot_Ap = gsdata->p.dot(gsdata->A3p);
+ Ap.noalias() = *A*p;
+ double p_dot_Ap = p.dot(Ap);
if (p_dot_Ap==0.0)
break;
- double zk_dot_rk = gsdata->z.dot(gsdata->r);
+ double zk_dot_rk = z.dot(r);
if (zk_dot_rk==0.0)
break;
double alpha = zk_dot_rk / p_dot_Ap;
- x3.noalias() += alpha * gsdata->p;
- gsdata->r.noalias() -= alpha * gsdata->A3p;
- double r_norm = gsdata->r.lpNorm<Infinity>();
+ x3.noalias() += alpha * p;
+ r.noalias() -= alpha * Ap;
+ double r_norm = r.lpNorm<Infinity>();
if (r_norm < options->min_res)
break;
- solve_Ax_b(data,&gsdata->z,&gsdata->r);
- double zk1_dot_rk1 = gsdata->z.dot(gsdata->r);
+ z = data->ldlt_A3.solve(r);
+ double zk1_dot_rk1 = z.dot(r);
double beta = zk1_dot_rk1 / zk_dot_rk;
- gsdata->p = gsdata->z + beta*gsdata->p;
+ p = z + beta*p;
}
for (int i=0; i<nx; ++i)
@@ -124,42 +111,7 @@ void ConjugateGradients::solve(
} // end ConjugateGradients solve
-// Solve Ax = b in parallel and apply
-// dimensionality mapping with temporaries
-void ConjugateGradients::solve_Ax_b(
- SolverData *data_,
- VectorXd *x_,
- VectorXd *b_)
-{
- struct LinSolveThreadData {
- SolverData *data;
- VectorXd *ls_x;
- VectorXd *ls_b;
- };
-
- auto parallel_lin_solve = [](
- void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict tls)->void
- {
- (void)(tls);
- LinSolveThreadData *td = (LinSolveThreadData*)userdata;
- int nx = td->ls_x->rows()/3;
- VectorXd b(nx);
- for (int j=0; j<nx; ++j)
- b[j] = td->ls_b->operator[](j*3+i);
- VectorXd x = td->data->ldltA.solve(b);
- for (int j=0; j<nx; ++j)
- td->ls_x->operator[](j*3+i) = x[j];
- };
-
- LinSolveThreadData thread_data = {.data=data_, .ls_x=x_, .ls_b=b_};
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- BLI_task_parallel_range(0, 3, &thread_data, parallel_lin_solve, &settings);
-
-} // end solve Ax=b
-
+#if 0
void GaussSeidel::solve(
const Options *options,
SolverData *data,
@@ -312,7 +264,11 @@ void GaussSeidel::init_solve(
// Create large A if we haven't already.
if (data->gsdata.A3.nonZeros()==0)
- make_n3(data->A, data->gsdata.A3);
+ {
+ SparseMatrix<double> A3;
+ geom::make_n3<double>(data->A, A3);
+ data->gsdata.A3 = A3;
+ }
// TODO
// Eventually we
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list