1#include "SemiImplicitHyperelasticitySolver.h"
3#include "Matrix/MatrixFunc.h"
4#include "ParticleSystem/Module/Kernel.h"
5#include "curand_kernel.h"
6#include "Algorithm/CudaRand.h"
10 IMPLEMENT_TCLASS(SemiImplicitHyperelasticitySolver, TDataType);
12 __constant__ EnergyModels<Real> ENERGY_FUNC;
14 template<typename Real>
15 __device__ Real constantWeight(Real r, Real h)
21 template<typename Real>
22 __device__ Real D_Weight(Real r, Real h)
24 CorrectedKernel<Real> kernSmooth;
25 return kernSmooth.WeightRR(r, 4 * h);
28 template<typename TDataType>
29 SemiImplicitHyperelasticitySolver<TDataType>::SemiImplicitHyperelasticitySolver()
30 : LinearElasticitySolver<TDataType>()
32 this->varIterationNumber()->setValue(5);
35 template<typename TDataType>
36 SemiImplicitHyperelasticitySolver<TDataType>::~SemiImplicitHyperelasticitySolver()
38 this->mWeights.clear();
39 this->mDisplacement.clear();
42 this->mPosBuf.clear();
45 template <typename Real, typename Coord, typename Matrix>
46 __global__ void HM_ComputeEnergy(
51 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
52 if (pId >= energy.size()) return;
54 Coord eigen_i = eigens[pId];
57 energy[pId] = ENERGY_FUNC.stvkModel.getEnergy(eigen_i[0], eigen_i[1], eigen_i[2]);
59 else if (type == NeoHooekean) {
60 energy[pId] = ENERGY_FUNC.neohookeanModel.getEnergy(eigen_i[0], eigen_i[1], eigen_i[2]);
62 else if (type == Linear) {
63 energy[pId] = ENERGY_FUNC.linearModel.getEnergy(eigen_i[0], eigen_i[1], eigen_i[2]);
65 else if (type == Xuetal) {
66 energy[pId] = ENERGY_FUNC.xuModel.getEnergy(eigen_i[0], eigen_i[1], eigen_i[2]);
68 else if (type == MooneyRivlin) {
69 energy[pId] = ENERGY_FUNC.mrModel.getEnergy(eigen_i[0], eigen_i[1], eigen_i[2]);
71 else if (type == Fung) {
72 energy[pId] = ENERGY_FUNC.fungModel.getEnergy(eigen_i[0], eigen_i[1], eigen_i[2]);
74 else if (type == Ogden) {
75 energy[pId] = ENERGY_FUNC.ogdenModel.getEnergy(eigen_i[0], eigen_i[1], eigen_i[2]);
77 else if (type == Yeoh) {
78 energy[pId] = ENERGY_FUNC.yeohModel.getEnergy(eigen_i[0], eigen_i[1], eigen_i[2]);
80 else if (type == ArrudaBoyce) {
81 energy[pId] = ENERGY_FUNC.abModel.getEnergy(eigen_i[0], eigen_i[1], eigen_i[2]);
86 template<typename TDataType>
87 void SemiImplicitHyperelasticitySolver<TDataType>::solveElasticity()
89 cudaMemcpyToSymbol(ENERGY_FUNC, this->inEnergyModels()->constDataPtr().get(), sizeof(EnergyModels<Real>));
91 enforceHyperelasticity();
94 template <typename Coord>
95 __global__ void HM_ComputeGradient(
100 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
101 if (pId >= y_next.size()) return;
103 grad[pId] = y_next[pId] - y_pre[pId];
106 template <typename Real, typename Coord>
107 __global__ void HM_ComputeCurrentPosition(
109 DArray<Coord> y_current,
110 DArray<Coord> y_next,
111 DArray<Attribute> attribute,
114 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
115 if (pId >= y_next.size()) return;
117 y_next[pId] = attribute[pId].isDynamic() ? y_current[pId] + alpha[pId] * grad[pId] : y_current[pId];
120 template <typename Real, typename Coord>
121 __global__ void HM_ComputeCurrentPosition(
123 DArray<Coord> y_current,
124 DArray<Coord> y_next,
127 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
128 if (pId >= y_next.size()) return;
130 y_next[pId] = y_current[pId] + alpha * grad[pId];
133 template <typename Real, typename Coord, typename Matrix, typename Bond>
134 __global__ void HM_Compute1DEnergy(
136 DArray<Coord> energyGradient,
141 DArray<bool> validOfK,
142 DArray<Coord> eigenValues,
143 DArrayList<Bond> bonds,
146 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
147 if (pId >= energy.size()) return;
151 Real totalEnergy = 0.0f;
152 Coord totalEnergyGradient = Coord(0);
153 Real V_i = volume[pId];
155 int size_i = bonds[pId].size();
158 Coord eigen_value_i = eigenValues[pId];
159 bool valid_i = validOfK[pId];
163 for (int ne = 1; ne < size_i; ne++)
165 Bond bond_ij = bonds[pId][ne];
168 Real r = bond_ij.xi.norm();
170 Real V_j = volume[j];
174 Real norm_ij = (y_j - y_i).norm();
175 Real lambda_ij = norm_ij / r;
178 Coord deltaEnergyGradient;
179 Coord dir_ij = norm_ij < EPSILON ? Coord(0) : (y_i - y_j) / (r);
182 deltaEnergy = V_j * ENERGY_FUNC.stvkModel.getEnergy(lambda_ij, lambda_ij, lambda_ij);
183 deltaEnergyGradient = V_j * (ENERGY_FUNC.stvkModel.getStressTensorPositive(lambda_ij, lambda_ij, lambda_ij) - ENERGY_FUNC.stvkModel.getStressTensorNegative(lambda_ij, lambda_ij, lambda_ij)) * dir_ij;
185 else if (type == NeoHooekean) {
186 deltaEnergy = V_j * ENERGY_FUNC.neohookeanModel.getEnergy(lambda_ij, lambda_ij, lambda_ij);
187 deltaEnergyGradient = V_j * (ENERGY_FUNC.neohookeanModel.getStressTensorPositive(lambda_ij, lambda_ij, lambda_ij) - ENERGY_FUNC.neohookeanModel.getStressTensorNegative(lambda_ij, lambda_ij, lambda_ij)) * dir_ij;
189 else if (type == Linear) {
190 deltaEnergy = V_j * ENERGY_FUNC.linearModel.getEnergy(lambda_ij, lambda_ij, lambda_ij);
191 deltaEnergyGradient = V_j * (ENERGY_FUNC.linearModel.getStressTensorPositive(lambda_ij, lambda_ij, lambda_ij) - ENERGY_FUNC.linearModel.getStressTensorNegative(lambda_ij, lambda_ij, lambda_ij)) * dir_ij;
193 else if (type == Xuetal) {
194 deltaEnergy = V_j * ENERGY_FUNC.xuModel.getEnergy(lambda_ij, lambda_ij, lambda_ij);
195 deltaEnergyGradient = V_j * (ENERGY_FUNC.xuModel.getStressTensorPositive(lambda_ij, lambda_ij, lambda_ij) - ENERGY_FUNC.xuModel.getStressTensorNegative(lambda_ij, lambda_ij, lambda_ij)) * dir_ij;
197 else if (type == MooneyRivlin) {
198 deltaEnergy = V_j * ENERGY_FUNC.mrModel.getEnergy(lambda_ij, lambda_ij, lambda_ij);
199 deltaEnergyGradient = V_j * (ENERGY_FUNC.mrModel.getStressTensorPositive(lambda_ij, lambda_ij, lambda_ij) - ENERGY_FUNC.xuModel.getStressTensorNegative(lambda_ij, lambda_ij, lambda_ij)) * dir_ij;
201 else if (type == Fung) {
202 deltaEnergy = V_j * ENERGY_FUNC.fungModel.getEnergy(lambda_ij, lambda_ij, lambda_ij);
203 deltaEnergyGradient = V_j * (ENERGY_FUNC.fungModel.getStressTensorPositive(lambda_ij, lambda_ij, lambda_ij) - ENERGY_FUNC.xuModel.getStressTensorNegative(lambda_ij, lambda_ij, lambda_ij)) * dir_ij;
205 else if (type == Ogden) {
206 deltaEnergy = V_j * ENERGY_FUNC.ogdenModel.getEnergy(lambda_ij, lambda_ij, lambda_ij);
207 deltaEnergyGradient = V_j * (ENERGY_FUNC.ogdenModel.getStressTensorPositive(lambda_ij, lambda_ij, lambda_ij) - ENERGY_FUNC.xuModel.getStressTensorNegative(lambda_ij, lambda_ij, lambda_ij)) * dir_ij;
209 else if (type == Yeoh) {
210 deltaEnergy = V_j * ENERGY_FUNC.yeohModel.getEnergy(lambda_ij, lambda_ij, lambda_ij);
211 deltaEnergyGradient = V_j * (ENERGY_FUNC.yeohModel.getStressTensorPositive(lambda_ij, lambda_ij, lambda_ij) - ENERGY_FUNC.xuModel.getStressTensorNegative(lambda_ij, lambda_ij, lambda_ij)) * dir_ij;
213 else if (type == ArrudaBoyce) {
214 deltaEnergy = V_j * ENERGY_FUNC.abModel.getEnergy(lambda_ij, lambda_ij, lambda_ij);
215 deltaEnergyGradient = V_j * (ENERGY_FUNC.abModel.getStressTensorPositive(lambda_ij, lambda_ij, lambda_ij) - ENERGY_FUNC.xuModel.getStressTensorNegative(lambda_ij, lambda_ij, lambda_ij)) * dir_ij;
218 totalEnergy += deltaEnergy;
219 totalEnergyGradient += deltaEnergyGradient;
223 energy[pId] = totalEnergy * V_i;
224 energyGradient[pId] = totalEnergyGradient * V_i;
227 template <typename Coord>
228 __global__ void HM_Chebyshev_Acceleration(DArray<Coord> next_X, DArray<Coord> X, DArray<Coord> prev_X, float omega)
230 int pId = blockDim.x * blockIdx.x + threadIdx.x;
231 if (pId >= prev_X.size()) return;
233 next_X[pId] = (next_X[pId] - X[pId]) * 0.666 + X[pId];
235 next_X[pId] = omega * (next_X[pId] - prev_X[pId]) + prev_X[pId];
238 template <typename Real, typename Coord, typename Matrix, typename Bond>
239 __global__ void HM_ComputeStepLength(
240 DArray<Real> stepLength,
241 DArray<Coord> gradient,
242 DArray<Coord> energyGradient,
246 DArrayList<Bond> restShapes)
248 int pId = blockDim.x * blockIdx.x + threadIdx.x;
249 if (pId >= stepLength.size()) return;
251 //TODO: replace 1000 with an input
252 Real mass_i = volume[pId] * 1000.0;
253 Real energy_i = energy[pId];
255 Real deltaE_i = abs(energyGradient[pId].dot(gradient[pId]));
257 Real alpha = deltaE_i < EPSILON || deltaE_i < energy_i ? Real(1) : energy_i / deltaE_i;
259 alpha /= Real(1 + restShapes[pId].size());
261 stepLength[pId] = alpha;
264 template <typename Coord>
265 __global__ void HM_FixCoM(
266 DArray<Coord> positions,
267 DArray<Attribute> atts,
270 int pId = blockDim.x * blockIdx.x + threadIdx.x;
271 if (pId >= positions.size()) return;
272 if ((positions[pId] - CoM).norm() < 0.05)
273 atts[pId].setFixed();
276 template <typename Coord, typename Bond>
277 __global__ void K_UpdateRestShape(
278 DArrayList<Bond> shape,
282 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
283 if (pId >= pos.size()) return;
287 List<Bond>& rest_shape_i = shape[pId];
288 List<int>& list_id_i = nbr[pId];
289 int nbSize = list_id_i.size();
290 for (int ne = 0; ne < nbSize; ne++)
292 int j = list_id_i[ne];
297 rest_shape_i.insert(np);
300 Bond np_0 = rest_shape_i[0];
301 rest_shape_i[0] = np;
302 rest_shape_i[ne] = np_0;
307 template <typename Coord>
308 __global__ void test_HM_UpdatePosition(
309 DArray<Coord> position,
310 DArray<Coord> velocity,
311 DArray<Coord> y_next,
312 DArray<Coord> position_old,
313 DArray<Attribute> att,
316 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
317 if (pId >= position.size()) return;
319 if (att[pId].isDynamic()) {
320 position[pId] = y_next[pId];
321 velocity[pId] += (position[pId] - position_old[pId]) / dt;
325 template<typename Real>
326 __device__ Real LimitStrain(Real s, Real slimit)
331 // ret = 0;// s + 0.05 * (slimit - s);
333 // // else if (s > 1.1 / slimit)
335 // // ret = s - 0.05 * (s - 1 / slimit);
339 ret = clamp(s, Real(0.2), 1 / slimit);
345 template <typename Real, typename Coord, typename Matrix, typename Bond>
346 __global__ void HM_ComputeF(
348 DArray<Coord> eigens,
350 DArray<bool> validOfK,
356 DArrayList<Bond> bonds,
360 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
361 if (pId >= Y.size()) return;
362 /*if (pId % 100 == 0)
363 printf("%d %d \n", pId, pId);*/
367 Real total_weight = Real(0);
374 printf("Position in HM_ComputeF %d: %f %f %f \n", pId, Y[pId][0], Y[pId][1], Y[pId][2]);
378 List<Bond>& bonds_i = bonds[pId];
380 Real maxDist = Real(0);
381 for (int ne = 0; ne < bonds_i.size(); ne++)
383 maxDist = max(maxDist, bonds_i[ne].xi.norm());
385 maxDist = maxDist < EPSILON ? Real(1) : maxDist;
387 //printf("maxdist %d: %f; \n\n", pId, maxDist);
390 printf("Max distance %d: %f \n", pId, maxDist);
393 for (int ne = 0; ne < bonds_i.size(); ne++)
395 Bond bond_ij = bonds[pId][ne];
398 Real r = (x_i - x_j).norm();
402 Coord p = (Y[j] - Y[pId]) / maxDist;
403 Coord q = (x_j - x_i) / maxDist;
404 //Real weight = D_Weight(r, horizon);
407 matL_i(0, 0) += p[0] * q[0] * weight; matL_i(0, 1) += p[0] * q[1] * weight; matL_i(0, 2) += p[0] * q[2] * weight;
408 matL_i(1, 0) += p[1] * q[0] * weight; matL_i(1, 1) += p[1] * q[1] * weight; matL_i(1, 2) += p[1] * q[2] * weight;
409 matL_i(2, 0) += p[2] * q[0] * weight; matL_i(2, 1) += p[2] * q[1] * weight; matL_i(2, 2) += p[2] * q[2] * weight;
411 matK_i(0, 0) += q[0] * q[0] * weight; matK_i(0, 1) += q[0] * q[1] * weight; matK_i(0, 2) += q[0] * q[2] * weight;
412 matK_i(1, 0) += q[1] * q[0] * weight; matK_i(1, 1) += q[1] * q[1] * weight; matK_i(1, 2) += q[1] * q[2] * weight;
413 matK_i(2, 0) += q[2] * q[0] * weight; matK_i(2, 1) += q[2] * q[1] * weight; matK_i(2, 2) += q[2] * q[2] * weight;
415 total_weight += weight;
420 printf("%d Neighbor %d: %f %f %f \n", pId, j, Y[j][0], Y[j][1], Y[j][2]);
426 if (total_weight > EPSILON)
428 matL_i *= (1.0f / total_weight);
429 matK_i *= (1.0f / total_weight);
433 polarDecomposition(matK_i, R, U, D, V);
438 Matrix mat_out = matK_i;
439 printf("matK_i: \n %f %f %f \n %f %f %f \n %f %f %f \n\n",
440 mat_out(0, 0), mat_out(0, 1), mat_out(0, 2),
441 mat_out(1, 0), mat_out(1, 1), mat_out(1, 2),
442 mat_out(2, 0), mat_out(2, 1), mat_out(2, 2));
445 printf("matL_i: \n %f %f %f \n %f %f %f \n %f %f %f \n\n",
446 mat_out(0, 0), mat_out(0, 1), mat_out(0, 2),
447 mat_out(1, 0), mat_out(1, 1), mat_out(1, 2),
448 mat_out(2, 0), mat_out(2, 1), mat_out(2, 2));
450 mat_out = U * D * V.transpose();
451 printf("matK polar: \n %f %f %f \n %f %f %f \n %f %f %f \n\n",
452 mat_out(0, 0), mat_out(0, 1), mat_out(0, 2),
453 mat_out(1, 0), mat_out(1, 1), mat_out(1, 2),
454 mat_out(2, 0), mat_out(2, 1), mat_out(2, 2));
456 printf("Horizon: %f; Det: %f \n", horizon, matK_i.determinant());
460 Real maxK = maximum(abs(D(0, 0)), maximum(abs(D(1, 1)), abs(D(2, 2))));
461 Real minK = minimum(abs(D(0, 0)), minimum(abs(D(1, 1)), abs(D(2, 2))));
463 bool valid_K = (minK < EPSILON) ? false : true;
465 validOfK[pId] = valid_K;
470 invK[pId] = matK_i.inverse();
471 F_i = matL_i * matK_i.inverse();
475 Real threshold = 0.0001f * horizon;
476 D(0, 0) = D(0, 0) > threshold ? 1.0 / D(0, 0) : 1.0;
477 D(1, 1) = D(1, 1) > threshold ? 1.0 / D(1, 1) : 1.0;
478 D(2, 2) = D(2, 2) > threshold ? 1.0 / D(2, 2) : 1.0;
479 invK[pId] = V * D * U.transpose();
480 F_i = matL_i * V * D * U.transpose();
483 polarDecomposition(F_i, R, U, D, V);
485 // Real minDist = Real(1000.0f);
486 // for (int ne = 0; ne < size_i; ne++)
488 // Bond np_j = restShapes[pId][ne];
489 // int j = np_j.index;
490 // Coord rest_pos_j = np_j.pos;
491 // Real r = (rest_pos_i - rest_pos_j).norm();
494 // minDist = min(minDist, r);
497 // printf("ID %d: min value %f \n", pId, minDist);
499 if (F_i.determinant() < maxDist * EPSILON)
508 // Coord n0 = Coord(1, 0, 0);
509 // Coord n1 = Coord(0, 1, 0);
510 // Coord n2 = Coord(0, 0, 1);
512 // Coord n0_rot = R * n0;
513 // Coord n1_rot = R * n1;
514 // Coord n2_rot = R * n2;
520 const Real slimit = strainLimiting;
522 l0 = clamp(l0, slimit, 1 / slimit);
523 l1 = clamp(l1, slimit, 1 / slimit);
524 l2 = clamp(l2, slimit, 1 / slimit);
530 eigens[pId] = Coord(l0, l1, l2);
532 F[pId] = U * D * V.transpose();
534 // if (F_i.determinant() < maxDist*EPSILON)
543 // Coord n0 = Coord(1, 0, 0);
544 // Coord n1 = Coord(0, 1, 0);
545 // Coord n2 = Coord(0, 0, 1);
547 // Coord n0_rot = R * n0;
548 // Coord n1_rot = R * n1;
549 // Coord n2_rot = R * n2;
551 // Real l0 = n0_rot.dot(F_i*n0);
552 // Real l1 = n1_rot.dot(F_i*n1);
553 // Real l2 = n2_rot.dot(F_i*n2);
556 // matV[pId] = Matrix::identityMatrix();
558 // const Real slimit = strainLimiting;
560 // l0 = clamp(l0, slimit, 1 / slimit);
561 // l1 = clamp(l1, slimit, 1 / slimit);
562 // l2 = clamp(l2, slimit, 1 / slimit);
568 // eigens[pId] = Coord(l0, l1, l2);
573 template <typename Real, typename Coord, typename Matrix, typename Bond>
574 __global__ void HM_JacobiStepNonsymmetric(
575 DArray<Coord> source,
582 DArray<bool> validOfK,
585 DArrayList<Bond> bonds,
588 DArrayList<Real> volumePair,
592 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
593 if (pId >= y_pre.size()) return;
596 int size_i = bonds[pId].size();
598 Real kappa = 4 / (3 * M_PI * horizon * horizon * horizon);
599 Real lambda_i1 = eigen[pId][0];
600 Real lambda_i2 = eigen[pId][1];
601 Real lambda_i3 = eigen[pId][2];
603 Matrix U_i = matU[pId];
604 Matrix V_i = matV[pId];
609 S1_i = ENERGY_FUNC.stvkModel.getStressTensorPositive(lambda_i1, lambda_i2, lambda_i3);
610 S2_i = ENERGY_FUNC.stvkModel.getStressTensorNegative(lambda_i1, lambda_i2, lambda_i3);
612 else if (type == NeoHooekean) {
613 S1_i = ENERGY_FUNC.neohookeanModel.getStressTensorPositive(lambda_i1, lambda_i2, lambda_i3);
614 S2_i = ENERGY_FUNC.neohookeanModel.getStressTensorNegative(lambda_i1, lambda_i2, lambda_i3);
616 else if (type == Linear) {
617 S1_i = ENERGY_FUNC.linearModel.getStressTensorPositive(lambda_i1, lambda_i2, lambda_i3);
618 S2_i = ENERGY_FUNC.linearModel.getStressTensorNegative(lambda_i1, lambda_i2, lambda_i3);
620 else if (type == Xuetal) {
621 S1_i = ENERGY_FUNC.xuModel.getStressTensorPositive(lambda_i1, lambda_i2, lambda_i3);
622 S2_i = ENERGY_FUNC.xuModel.getStressTensorNegative(lambda_i1, lambda_i2, lambda_i3);
624 else if (type == MooneyRivlin) {
625 S1_i = ENERGY_FUNC.mrModel.getStressTensorPositive(lambda_i1, lambda_i2, lambda_i3);
626 S2_i = ENERGY_FUNC.mrModel.getStressTensorNegative(lambda_i1, lambda_i2, lambda_i3);
628 else if (type == Fung) {
629 S1_i = ENERGY_FUNC.fungModel.getStressTensorPositive(lambda_i1, lambda_i2, lambda_i3);
630 S2_i = ENERGY_FUNC.fungModel.getStressTensorNegative(lambda_i1, lambda_i2, lambda_i3);
632 else if (type == Ogden) {
633 S1_i = ENERGY_FUNC.ogdenModel.getStressTensorPositive(lambda_i1, lambda_i2, lambda_i3);
634 S2_i = ENERGY_FUNC.ogdenModel.getStressTensorNegative(lambda_i1, lambda_i2, lambda_i3);
636 else if (type == Yeoh) {
637 S1_i = ENERGY_FUNC.yeohModel.getStressTensorPositive(lambda_i1, lambda_i2, lambda_i3);
638 S2_i = ENERGY_FUNC.yeohModel.getStressTensorNegative(lambda_i1, lambda_i2, lambda_i3);
640 else if (type == ArrudaBoyce) {
641 S1_i = ENERGY_FUNC.abModel.getStressTensorPositive(lambda_i1, lambda_i2, lambda_i3);
642 S2_i = ENERGY_FUNC.abModel.getStressTensorNegative(lambda_i1, lambda_i2, lambda_i3);
645 Matrix PK1_i = U_i * S1_i * U_i.transpose();
646 Matrix PK2_i = U_i * S2_i * V_i.transpose();
648 //Real Vol_i = volume[pId];
652 Coord y_pre_i = y_pre[pId];
654 bool K_valid = validOfK[pId];
659 for (int ne = 0; ne < size_i; ne++)
661 Bond bond_ij = bonds[pId][ne];
664 Coord y_pre_j = y_pre[j];
665 Real r = bond_ij.xi.norm();
670 //Real Vol_j = volume[j];
671 Real V_ij = volumePair[pId][ne];
673 Coord y_ij = y_pre_i - y_pre_j;
675 Real lambda = y_ij.norm() / r;
677 //const Real scale = Vol_i * Vol_j*kappa;
678 const Real scale = V_ij * V_ij * kappa;
679 const Real sw_ij = dt * dt * scale * weight_ij / (r * r);
681 bool K_valid_ij = K_valid & validOfK[j];
686 S1_ij = ENERGY_FUNC.stvkModel.getStressTensorPositive(lambda, lambda, lambda);
687 S2_ij = ENERGY_FUNC.stvkModel.getStressTensorNegative(lambda, lambda, lambda);
689 else if (type == NeoHooekean) {
690 S1_ij = ENERGY_FUNC.neohookeanModel.getStressTensorPositive(lambda, lambda, lambda);
691 S2_ij = ENERGY_FUNC.neohookeanModel.getStressTensorNegative(lambda, lambda, lambda);
693 else if (type == Linear) {
694 S1_ij = ENERGY_FUNC.linearModel.getStressTensorPositive(lambda, lambda, lambda);
695 S2_ij = ENERGY_FUNC.linearModel.getStressTensorNegative(lambda, lambda, lambda);
697 else if (type == Xuetal) {
698 S1_ij = ENERGY_FUNC.xuModel.getStressTensorPositive(lambda, lambda, lambda);
699 S2_ij = ENERGY_FUNC.xuModel.getStressTensorNegative(lambda, lambda, lambda);
701 else if (type == MooneyRivlin) {
702 S1_ij = ENERGY_FUNC.mrModel.getStressTensorPositive(lambda, lambda, lambda);
703 S2_ij = ENERGY_FUNC.mrModel.getStressTensorNegative(lambda, lambda, lambda);
705 else if (type == Fung) {
706 S1_ij = ENERGY_FUNC.fungModel.getStressTensorPositive(lambda, lambda, lambda);
707 S2_ij = ENERGY_FUNC.fungModel.getStressTensorNegative(lambda, lambda, lambda);
709 else if (type == Ogden) {
710 S1_ij = ENERGY_FUNC.ogdenModel.getStressTensorPositive(lambda, lambda, lambda);
711 S2_ij = ENERGY_FUNC.ogdenModel.getStressTensorNegative(lambda, lambda, lambda);
713 else if (type == Yeoh) {
714 S1_ij = ENERGY_FUNC.yeohModel.getStressTensorPositive(lambda, lambda, lambda);
715 S2_ij = ENERGY_FUNC.yeohModel.getStressTensorNegative(lambda, lambda, lambda);
717 else if (type == ArrudaBoyce) {
718 S1_ij = ENERGY_FUNC.abModel.getStressTensorPositive(lambda, lambda, lambda);
719 S2_ij = ENERGY_FUNC.abModel.getStressTensorNegative(lambda, lambda, lambda);
722 Matrix PK1_ij = K_valid_ij ? PK1_i : S1_ij;
723 Matrix PK2_ij = K_valid_ij ? PK2_i : S2_ij;
725 Coord dir_ij = lambda > EPSILON ? y_ij.normalize() : Coord(1, 0, 0);
727 Coord x_ij = K_valid_ij ? x_i - x_j : dir_ij * (x_i - x_j).norm();
729 Coord ds_ij = sw_ij * PK1_ij * y_pre_j + sw_ij * PK2_ij * x_ij;
730 Coord ds_ji = sw_ij * PK1_ij * y_pre_i - sw_ij * PK2_ij * x_ij;
732 Matrix mat_ij = sw_ij * PK1_ij;
737 atomicAdd(&source[j][0], ds_ji[0]);
738 atomicAdd(&source[j][1], ds_ji[1]);
739 atomicAdd(&source[j][2], ds_ji[2]);
741 atomicAdd(&A[j](0, 0), mat_ij(0, 0));
742 atomicAdd(&A[j](0, 1), mat_ij(0, 1));
743 atomicAdd(&A[j](0, 2), mat_ij(0, 2));
744 atomicAdd(&A[j](1, 0), mat_ij(1, 0));
745 atomicAdd(&A[j](1, 1), mat_ij(1, 1));
746 atomicAdd(&A[j](1, 2), mat_ij(1, 2));
747 atomicAdd(&A[j](2, 0), mat_ij(2, 0));
748 atomicAdd(&A[j](2, 1), mat_ij(2, 1));
749 atomicAdd(&A[j](2, 2), mat_ij(2, 2));
753 atomicAdd(&source[pId][0], source_i[0]);
754 atomicAdd(&source[pId][1], source_i[1]);
755 atomicAdd(&source[pId][2], source_i[2]);
757 atomicAdd(&A[pId](0, 0), mat_i(0, 0));
758 atomicAdd(&A[pId](0, 1), mat_i(0, 1));
759 atomicAdd(&A[pId](0, 2), mat_i(0, 2));
760 atomicAdd(&A[pId](1, 0), mat_i(1, 0));
761 atomicAdd(&A[pId](1, 1), mat_i(1, 1));
762 atomicAdd(&A[pId](1, 2), mat_i(1, 2));
763 atomicAdd(&A[pId](2, 0), mat_i(2, 0));
764 atomicAdd(&A[pId](2, 1), mat_i(2, 1));
765 atomicAdd(&A[pId](2, 2), mat_i(2, 2));
768 template <typename Real, typename Coord, typename Matrix>
769 __global__ void HM_ComputeNextPosition(
770 DArray<Coord> y_next,
773 DArray<Coord> source,
776 DArray<Attribute> attribute,
779 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
780 if (pId >= y_next.size()) return;
782 //TODO: replace 1000 with an input
783 Real mass_i = volume[pId] * 1000;
785 Matrix mat_i = A[pId] + mass_i * Matrix::identityMatrix();
786 Coord src_i = source[pId] + mass_i * y_old[pId];
788 y_next[pId] = attribute[pId].isDynamic() ? mat_i.inverse() * src_i : y_pre[pId];
791 template <typename Matrix>
792 __global__ void HM_InitRotation(
797 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
798 if (pId >= U.size()) return;
800 U[pId] = Matrix::identityMatrix();
801 V[pId] = Matrix::identityMatrix();
802 R[pId] = Matrix::identityMatrix();
805 template<typename TDataType>
806 void SemiImplicitHyperelasticitySolver<TDataType>::resizeAllFields()
808 uint num = this->inY()->size();
810 if (m_F.size() == num)
816 m_validOfK.resize(num);
817 m_validOfF.resize(num);
819 m_eigenValues.resize(num);
824 m_energy.resize(num);
826 m_gradient.resize(num);
827 mEnergyGradient.resize(num);
831 y_current.resize(num);
832 y_residual.resize(num);
835 m_source.resize(num);
838 this->mPosBuf.resize(num);
840 m_fraction.resize(num);
842 cuExecute(m_matU.size(),
848 m_reduce = Reduction<Real>::Create(num);
851 template<typename TDataType>
852 void SemiImplicitHyperelasticitySolver<TDataType>::enforceHyperelasticity()
854 //std::cout << "enforceElasticity\n";
858 int numOfParticles = this->inY()->size();
859 uint pDims = cudaGridSize(numOfParticles, BLOCK_SIZE);
861 std::cout << "enforceElasticity " << numOfParticles << std::endl;
863 this->mWeights.reset();
865 Log::sendMessage(Log::User, "\n \n \n \n *************solver start!!!***************");
867 /**************************** Jacobi method ************************************************/
868 // initialize y_now, y_next_iter
869 y_current.assign(this->inY()->getData());
870 y_next.assign(this->inY()->getData());
871 this->mPosBuf.assign(this->inY()->getData());
873 // do Jacobi method Loop
874 bool convergeFlag = false; // converge or not
879 std::cout << "enforceElasticity 2 " << numOfParticles << std::endl;
881 while (iterCount < this->varIterationNumber()->getData()) {
882 //printf("%.3lf\n", inHorizon()->getData());
887 HM_ComputeF << <pDims, BLOCK_SIZE >> > (
895 this->inX()->getData(),
897 this->inBonds()->getData(),
898 this->varStrainLimiting()->getData(),
899 this->inHorizon()->getData());
902 HM_JacobiStepNonsymmetric << <pDims, BLOCK_SIZE >> > (
912 this->inX()->getData(),
913 this->inBonds()->getData(),
914 this->inHorizon()->getData(),
915 this->inVolume()->getData(),
916 this->inVolumePair()->getData(),
917 this->inTimeStep()->getData(),
918 this->inEnergyType()->getData());
921 cuExecute(y_next.size(),
922 HM_ComputeNextPosition,
928 this->inVolume()->getData(),
929 this->inAttribute()->getData(),
930 this->inEnergyType()->getData());
933 cuExecute(m_gradient.size(),
940 cuExecute(m_energy.size(),
944 this->inX()->getData(),
947 this->inVolume()->getData(),
950 this->inBonds()->getData(),
951 this->inEnergyType()->getData());
953 m_alphaCompute = this->varIsAlphaComputed()->getData();
954 if (this->m_alphaCompute) {
955 cuExecute(m_alpha.size(),
956 HM_ComputeStepLength,
960 this->inVolume()->getData(),
963 this->inBonds()->getData());
965 cuExecute(m_gradient.size(),
966 HM_ComputeCurrentPosition,
970 this->inAttribute()->getData(),
976 cuExecute(m_gradient.size(),
977 HM_ComputeCurrentPosition,
984 y_current.assign(y_next);
989 cuExecute(this->inY()->getDataPtr()->size(),
990 test_HM_UpdatePosition,
991 this->inY()->getData(),
992 this->inVelocity()->getData(),
995 this->inAttribute()->getData(),
996 this->inTimeStep()->getData());
1000 DEFINE_CLASS(SemiImplicitHyperelasticitySolver);