Skip to content

Commit 11cb659

Browse files
committed
avoiding duplicates pairs in hessian
1 parent b0c58f1 commit 11cb659

File tree

10 files changed

+196
-43
lines changed

10 files changed

+196
-43
lines changed

apps/NeoHookean/barrier_energy.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,19 @@ void floor_barrier_energy(ProblemT& problem,
5555
});
5656
}
5757

58-
template <typename VAttrT, typename VAttrB, typename T = typename VAttrT::Type>
58+
template <typename VAttrT,
59+
typename VAttrB,
60+
typename PairT,
61+
typename T = typename VAttrT::Type>
5962
void add_contact(RXMeshStatic& rx,
60-
CandidatePairsVV& contact_pairs,
63+
PairT& contact_pairs,
6164
const VertexHandle dbc_vertex,
65+
const VertexHandle dbc_vertex1,
66+
const VertexHandle dbc_vertex2,
6267
const VAttrB& is_dbc,
6368
const VAttrT& x,
6469
const T dhat)
6570
{
66-
if (contact_pairs.num_pairs() > 0) {
67-
return;
68-
}
6971
contact_pairs.reset();
7072

7173
rx.for_each_vertex(DEVICE, [=] __device__(const VertexHandle& vh) mutable {
@@ -79,12 +81,22 @@ void add_contact(RXMeshStatic& rx,
7981
T d = (xi - x_dbc).dot(normal);
8082

8183
if (d < dhat) {
84+
// if (vh.local_id() == 20 || vh.local_id() == 21 || vh.local_id()
85+
// == 22 || vh.local_id() == 23 || vh.local_id() == 24) {
8286
bool inserted = contact_pairs.insert(vh, dbc_vertex);
8387
assert(inserted);
8488

85-
printf("\n addec contact pair between %d, %d",
89+
inserted = contact_pairs.insert(vh, dbc_vertex1);
90+
assert(inserted);
91+
92+
inserted = contact_pairs.insert(vh, dbc_vertex2);
93+
assert(inserted);
94+
95+
printf("\n addec contact pair between %d, (%d, %d, %d)",
8696
vh.local_id(),
87-
dbc_vertex.local_id());
97+
dbc_vertex.local_id(),
98+
dbc_vertex1.local_id(),
99+
dbc_vertex2.local_id());
88100
}
89101
});
90102

apps/NeoHookean/draw.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44

55
using namespace rxmesh;
66

7-
template <typename FunT, typename VAttrT>
7+
template <typename FunT, typename VAttrT, typename DirT>
88
void draw(RXMeshStatic& rx,
99
VAttrT& x,
1010
VAttrT& velocity,
1111
FunT& step_forward,
12+
DirT& dir_mat,
13+
DirT& grad_mat,
1214
int& step)
1315
{
1416
#if USE_POLYSCOPE
@@ -18,13 +20,25 @@ void draw(RXMeshStatic& rx,
1820

1921
bool is_running = false;
2022

23+
auto dir = *rx.add_vertex_attribute<float>("Dir", 3);
24+
auto grad = *rx.add_vertex_attribute<float>("Grad", 3);
25+
2126
auto ps_callback = [&]() mutable {
2227
auto step_and_update = [&]() {
2328
step_forward();
2429
x.move(DEVICE, HOST);
2530
velocity.move(DEVICE, HOST);
2631
auto vel = rx.get_polyscope_mesh()->addVertexVectorQuantity(
2732
"Velocity", velocity);
33+
34+
dir_mat.move(DEVICE, HOST);
35+
dir.from_matrix(&dir_mat);
36+
rx.get_polyscope_mesh()->addVertexVectorQuantity("Direction", dir);
37+
38+
grad_mat.move(DEVICE, HOST);
39+
grad.from_matrix(&grad_mat);
40+
rx.get_polyscope_mesh()->addVertexVectorQuantity("Grad", grad);
41+
2842
rx.get_polyscope_mesh()->updateVertexPositions(x);
2943
};
3044
if (ImGui::Button("Step")) {

apps/NeoHookean/neo_hookean.cu

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ void neo_hookean(RXMeshStatic& rx, T dx)
168168
ceiling_barrier_energy(
169169
problem, contact_area, time_step, ground_n, ground_o, dhat, kappa);
170170

171+
DenseMatrix<T, Eigen::RowMajor> dir(
172+
rx, problem.grad.rows(), problem.grad.cols());
173+
174+
DenseMatrix<T, Eigen::RowMajor> grad(
175+
rx, problem.grad.rows(), problem.grad.cols());
171176

172177
T line_search_init_step = 0;
173178

@@ -193,6 +198,11 @@ void neo_hookean(RXMeshStatic& rx, T dx)
193198
timer.add("LinearSolver");
194199
timer.add("Diff");
195200

201+
//add_contact(
202+
// rx, problem.vv_pairs, v_dbc[0], v_dbc[1], v_dbc[2], is_dbc, x, dhat);
203+
//problem.update_hessian();
204+
//printf("\n");
205+
196206
auto step_forward = [&]() {
197207
// x_tilde = x + v*h
198208
timer.start("Step");
@@ -221,14 +231,22 @@ void neo_hookean(RXMeshStatic& rx, T dx)
221231
rx, is_dbc, x, v_dbc_vel, v_dbc_limit, time_step, dbc_target);
222232

223233
// evaluate energy
224-
add_contact(rx, problem.vv_pairs, v_dbc[0], is_dbc, x, dhat);
234+
add_contact(rx,
235+
problem.vv_pairs,
236+
v_dbc[0],
237+
v_dbc[1],
238+
v_dbc[2],
239+
is_dbc,
240+
x,
241+
dhat);
225242
problem.update_hessian();
226243
problem.eval_terms();
227244
{
228245
CUDA_ERROR(cudaGetLastError());
229246
CUDA_ERROR(cudaDeviceSynchronize());
230247
}
231248

249+
grad.copy_from(problem.grad, DEVICE, DEVICE);
232250
// DBC satisfied
233251
check_dbc_satisfied(
234252
rx, is_dbc_satisfied, x, is_dbc, dbc_target, time_step, tol);
@@ -244,18 +262,25 @@ void neo_hookean(RXMeshStatic& rx, T dx)
244262
// get newton direction
245263
newton_solver.compute_direction();
246264

265+
dir.copy_from(newton_solver.dir, DEVICE, DEVICE);
247266
// residual is abs_max(newton_dir)/ h
248267
T residual = newton_solver.dir.abs_max() / time_step;
249268

250269
T f = problem.get_current_loss();
251270
RXMESH_INFO(
252-
"*******Step: {}, Energy: {}, Residual: {}", steps, f, residual);
271+
"*******Step: {}, Energy: {}, Residual: {}, DBC_satisfied= {}",
272+
steps,
273+
f,
274+
residual,
275+
num_satisfied);
253276

254277
int iter = 0;
255278
while (residual > tol || num_satisfied != num_dbc_vertices) {
256279

257280
if (residual <= tol && num_satisfied != num_dbc_vertices) {
258281
dbc_stiff.multiply(T(2));
282+
problem.eval_terms();
283+
newton_solver.compute_direction();
259284
}
260285

261286
T nh_step = neo_hookean_step_size(rx, x, newton_solver.dir, alpha);
@@ -272,10 +297,22 @@ void neo_hookean(RXMeshStatic& rx, T dx)
272297
line_search_init_step = std::min(nh_step, bar_step);
273298

274299
// TODO: line search should pass the step to the friction energy
275-
newton_solver.line_search(line_search_init_step, 0.5);
300+
bool ls_success =
301+
newton_solver.line_search(line_search_init_step, 0.5, 64, 0.0);
302+
303+
if (!ls_success) {
304+
RXMESH_WARN("Line search failed!");
305+
}
276306

277307
// evaluate energy
278-
add_contact(rx, problem.vv_pairs, v_dbc[0], is_dbc, x, dhat);
308+
add_contact(rx,
309+
problem.vv_pairs,
310+
v_dbc[0],
311+
v_dbc[1],
312+
v_dbc[2],
313+
is_dbc,
314+
x,
315+
dhat);
279316
problem.update_hessian();
280317
problem.eval_terms();
281318
{
@@ -301,9 +338,20 @@ void neo_hookean(RXMeshStatic& rx, T dx)
301338
// residual is abs_max(newton_dir)/ h
302339
residual = newton_solver.dir.abs_max() / time_step;
303340

304-
RXMESH_INFO(" Subsetp: {}, F: {}, R: {}", iter, f, residual);
341+
RXMESH_INFO(
342+
" Subsetp: {}, F: {}, R: {}, line_search_init_step={}, "
343+
"DBC_satisfied= {}",
344+
iter,
345+
f,
346+
residual,
347+
line_search_init_step,
348+
num_satisfied);
305349

306350
iter++;
351+
352+
if (iter > 10) {
353+
break;
354+
}
307355
}
308356

309357
RXMESH_INFO("\n===================\n");
@@ -325,7 +373,7 @@ void neo_hookean(RXMeshStatic& rx, T dx)
325373
};
326374

327375
#if USE_POLYSCOPE
328-
draw(rx, x, velocity, step_forward, steps);
376+
draw(rx, x, velocity, step_forward, dir, grad, steps);
329377
#else
330378
while (steps < 5) {
331379
step_forward();

include/rxmesh/attribute.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,10 @@ class Attribute : public AttributeBase
190190
* rows represent the number of mesh elements of this attribute and number
191191
* of columns is the number of attributes
192192
*/
193-
std::shared_ptr<DenseMatrix<T>> to_matrix() const
193+
template <int Order = Eigen::ColMajor>
194+
std::shared_ptr<DenseMatrix<T, Order>> to_matrix() const
194195
{
195-
std::shared_ptr<DenseMatrix<T>> mat =
196+
std::shared_ptr<DenseMatrix<T, Order>> mat =
196197
std::make_shared<DenseMatrix<T>>(*m_rxmesh, rows(), cols());
197198

198199
if constexpr (std::is_same_v<HandleT, VertexHandle>) {
@@ -230,7 +231,8 @@ class Attribute : public AttributeBase
230231
* attribute on the host side
231232
* @param mat
232233
*/
233-
void from_matrix(DenseMatrix<T>* mat)
234+
template <int Order>
235+
void from_matrix(DenseMatrix<T, Order>* mat)
234236
{
235237
assert(mat->rows() == rows());
236238
assert(mat->cols() == cols());

include/rxmesh/diff/candidate_pairs.h

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ namespace rxmesh {
77
/**
88
* @brief Storing a pair of candidate contact pairs using their handles
99
*/
10-
template <typename HandleT0, typename HandleT1, typename IndexT>
10+
template <typename HandleT0, typename HandleT1, typename HessMatT>
1111
struct CandidatePairs
1212
{
13+
using IndexT = int;
14+
1315
template <typename T, int V, typename O, bool W>
1416
friend struct DiffScalarProblem;
1517

@@ -36,11 +38,12 @@ struct CandidatePairs
3638
* contribute to -- but this is already allocated in the hessian matrix
3739
*/
3840
__host__ CandidatePairs(int max_capacity,
39-
int variable_dim,
41+
HessMatT& hess,
4042
const Context& ctx)
41-
: m_variable_dim(variable_dim),
43+
: m_hess(hess),
44+
m_variable_dim(hess.K_),
4245
m_pairs_id(DenseMatrix<IndexT, Eigen::ColMajor>(
43-
max_capacity * variable_dim * variable_dim * 2,
46+
max_capacity * m_variable_dim * m_variable_dim * 2,
4447
2)),
4548
m_pairs_handle(DenseMatrix<PairT, Eigen::ColMajor>(max_capacity, 1)),
4649
m_current_num_pairs(DenseMatrix<int>(1, 1)),
@@ -53,15 +56,23 @@ struct CandidatePairs
5356

5457
/**
5558
* @brief Insert a candidate pair and return true if it succeeded. Otherwise
56-
* return false, i.e., in case of exceeding the max capacity
59+
* return false, i.e., in case of exceeding the max capacity.
60+
* Here, we insert two things 1) the handles in a buffer to iterate over
61+
* later 2) the corresponding new indices of the local Hessian block in the
62+
* sparse Hessian matrix that these two (possibly) contacting pair
63+
* generates.
64+
* We always insert new handles (so long as the buffer is not overflown).
65+
* For 2) we check if the block is already allocated. If not, we add the
66+
* indices to another buffer which is later used in the update_hessian in
67+
* the Problem
5768
*/
5869
__device__ __host__ bool insert(const HandleT0& c0, const HandleT1& c1)
5970
{
6071

6172
// first check if we have a space
6273
/// if we have a space to insert new pairs
6374

64-
auto add_candidate = [&](int id) {
75+
auto add_candidate_with_indices = [&](int id) {
6576
// add the handles
6677
m_pairs_handle(id).first = c0;
6778
m_pairs_handle(id).second = c1;
@@ -86,12 +97,24 @@ struct CandidatePairs
8697
}
8798
};
8899

100+
101+
auto add_candidate = [&](int id) {
102+
// add the handles
103+
m_pairs_handle(id).first = c0;
104+
m_pairs_handle(id).second = c1;
105+
};
106+
107+
89108
#ifdef __CUDA_ARCH__
90109
int id = ::atomicAdd(m_current_num_pairs.data(DEVICE), 1);
91-
if (id < m_pairs_handle.rows()) {
92-
::atomicAdd(m_current_num_index.data(DEVICE),
93-
m_variable_dim * m_variable_dim * 2);
94-
add_candidate(id);
110+
if (id < m_pairs_handle.rows()) {
111+
if (m_hess.is_non_zero(c0, c1)) {
112+
add_candidate(id);
113+
} else {
114+
::atomicAdd(m_current_num_index.data(DEVICE),
115+
m_variable_dim * m_variable_dim * 2);
116+
add_candidate_with_indices(id);
117+
}
95118
return true;
96119
} else {
97120
::atomicAdd(m_current_num_pairs.data(DEVICE), -1);
@@ -100,9 +123,13 @@ struct CandidatePairs
100123
#else
101124
if (m_current_num_pairs(0) < m_pairs_handle.rows()) {
102125
int id = m_current_num_pairs(0);
103-
m_current_num_pairs(0)++;
104-
m_current_num_index(0) += m_variable_dim * m_variable_dim * 2;
105-
add_candidate(id);
126+
m_current_num_pairs(0)++;
127+
if (m_hess.is_non_zero(c0, c1)) {
128+
add_candidate(id);
129+
} else {
130+
m_current_num_index(0) += m_variable_dim * m_variable_dim * 2;
131+
add_candidate_with_indices(id);
132+
}
106133
return true;
107134
} else {
108135
return false;
@@ -168,7 +195,6 @@ struct CandidatePairs
168195
m_current_num_index(0) = 0;
169196

170197
#ifndef __CUDA_ARCH__
171-
172198
m_current_num_pairs.move(HOST, DEVICE);
173199
m_current_num_index.move(HOST, DEVICE);
174200
#endif
@@ -194,12 +220,16 @@ struct CandidatePairs
194220
// track the number of pairs (not the number of indices)
195221
DenseMatrix<int> m_current_num_pairs;
196222
DenseMatrix<int> m_current_num_index;
197-
int m_variable_dim;
223+
224+
// TODO remove this and use m_hess.k_
225+
int m_variable_dim;
226+
227+
HessMatT m_hess;
198228

199229
Context m_context;
200230
};
201231

202-
203-
using CandidatePairsVV = CandidatePairs<VertexHandle, VertexHandle, int>;
232+
template <typename HessMatT>
233+
using CandidatePairsVV = CandidatePairs<VertexHandle, VertexHandle, HessMatT>;
204234

205235
} // namespace rxmesh

0 commit comments

Comments
 (0)