tBond model passes stability, normal, shear, and bend tests, but not twist - sp… | |
git clone git://src.adamsgaard.dk/sphere | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit c2a5b8e5819c09eea3dba1b97fcade073e984bd9 | |
parent 11c8ccc15c6f107407771020cf27c7bd34233df4 | |
Author: Anders Damsgaard <[email protected]> | |
Date: Thu, 7 Mar 2013 18:36:25 +0100 | |
Bond model passes stability, normal, shear, and bend tests, but not twist | |
Diffstat: | |
M src/cohesion.cuh | 44 ++++++++++++++++++++---------… | |
M tests/CMakeLists.txt | 3 +++ | |
A tests/bond_tests.py | 187 +++++++++++++++++++++++++++++… | |
3 files changed, 219 insertions(+), 15 deletions(-) | |
--- | |
diff --git a/src/cohesion.cuh b/src/cohesion.cuh | |
t@@ -53,15 +53,18 @@ __global__ void bondsLinear( | |
const Float4 x_j = dev_x[bond.y]; | |
const Float4 vel_i = dev_vel[bond.x]; | |
const Float4 vel_j = dev_vel[bond.y]; | |
- const Float4 angvel_i = dev_angvel[bond.x]; | |
- const Float4 angvel_j = dev_angvel[bond.y]; | |
+ const Float4 angvel4_i = dev_angvel[bond.x]; | |
+ const Float4 angvel4_j = dev_angvel[bond.y]; | |
+ | |
+ const Float3 angvel_i = MAKE_FLOAT3(angvel4_i.x, angvel4_i.y, angvel4_i.z); | |
+ const Float3 angvel_j = MAKE_FLOAT3(angvel4_j.x, angvel4_j.y, angvel4_j.z); | |
// Initialize force- and torque vectors | |
Float3 f, t, f_n, f_t, t_n, t_t; | |
//// Bond geometry and inertia | |
- | |
+ | |
// Parallel-bond radius (Potyondy and Cundall 2004, eq. 12) | |
const Float R_bar = devC_params.lambda_bar * fmin(x_i.w, x_j.w); | |
t@@ -72,7 +75,8 @@ __global__ void bondsLinear( | |
const Float I = 0.25 * PI * R_bar*R_bar*R_bar*R_bar; | |
// Bond polar moment of inertia (Potyondy and Cundall 2004, eq. 15) | |
- const Float J = 0.50 * PI * R_bar*R_bar*R_bar*R_bar; | |
+ //const Float J = 0.50 * PI * R_bar*R_bar*R_bar*R_bar; | |
+ const Float J = I*2.0; | |
// Inter-particle vector | |
const Float3 x = MAKE_FLOAT3( | |
t@@ -80,6 +84,9 @@ __global__ void bondsLinear( | |
x_i.y - x_j.y, | |
x_i.z - x_j.z); | |
const Float x_length = length(x); | |
+ | |
+ // Find overlap (negative value if overlapping) | |
+ const Float overlap = fmin(0.0, x_length - (x_i.w + x_j.w)); | |
// Normal vector of contact (points from i to j) | |
const Float3 n = x/x_length; | |
t@@ -91,11 +98,15 @@ __global__ void bondsLinear( | |
//const Float3 delta_t0 = delta_t0_uncor - dot(delta_t0_uncor, n); | |
const Float3 delta_t0 = delta_t0_uncor - (n * dot(n, delta_t0_uncor)); | |
- // Contact displacement (should this include rolling?) | |
- const Float3 ddelta = MAKE_FLOAT3( | |
- vel_i.x - vel_j.x, | |
- vel_i.y - vel_j.y, | |
- vel_i.z - vel_j.z) * devC_dt; | |
+ // Contact displacement | |
+ const Float3 ddelta = ( | |
+ MAKE_FLOAT3( | |
+ vel_i.x - vel_j.x, | |
+ vel_i.y - vel_j.y, | |
+ vel_i.z - vel_j.z) | |
+ + (x_i.w + overlap/2.0) * cross(n, angvel_i) | |
+ + (x_j.w + overlap/2.0) * cross(n, angvel_j) | |
+ ) * devC_dt; | |
// Normal component of the displacement increment | |
//const Float ddelta_n = dot(ddelta, n); | |
t@@ -111,11 +122,14 @@ __global__ void bondsLinear( | |
// Tangential component of the total displacement | |
const Float3 delta_t = delta_t0 + ddelta_t; | |
- // Normal force: Elastic contact model | |
+ // Normal force: Visco-elastic contact model | |
+ // The elastic component caused by the overlap is subtracted. | |
//f_n = devC_params.k_n * A * delta_n * n; | |
f_n = (devC_params.k_n * A * delta_n + devC_params.gamma_n * ddelta_n/devC… | |
+ //f_n += devC_params.k_n * overlap * n; | |
+ | |
- // Tangential force: Elastic contact model | |
+ // Tangential force: Visco-elastic contact model | |
//f_t = -devC_params.k_t * A * delta_t; | |
f_t = -devC_params.k_t * A * delta_t - devC_params.gamma_t * ddelta_t/devC… | |
t@@ -149,11 +163,11 @@ __global__ void bondsLinear( | |
// Tangential component of the total displacement | |
const Float3 omega_t = omega_t0 + domega_t; | |
- // Twisting torque: Elastic contact model | |
- //t_n = -devC_params.k_t * J * omega_n * n; | |
- t_n = (devC_params.k_t * J * omega_n + devC_params.gamma_t * domega_n/devC… | |
+ // Twisting torque: Visco-elastic contact model | |
+ t_n = -devC_params.k_t * J * omega_n * n; | |
+ //t_n = (devC_params.k_t * J * omega_n + devC_params.gamma_t * domega_n/de… | |
- // Bending torque: Elastic contact model | |
+ // Bending torque: Visco-elastic contact model | |
//t_t = -devC_params.k_n * I * omega_t; | |
//t_t = -devC_params.k_n * I * omega_t - devC_params.gamma_n * domega_t/de… | |
t_t = devC_params.k_n * I * omega_t - devC_params.gamma_n * domega_t/devC_… | |
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt | |
t@@ -9,3 +9,6 @@ add_test(porosity_tests ${PYTHON_EXECUTABLE} | |
add_test(memory_tests ${PYTHON_EXECUTABLE} | |
${CMAKE_CURRENT_BINARY_DIR}/memcheck_tests.py) | |
+ | |
+add_test(bond_tests ${PYTHON_EXECUTABLE} | |
+ ${CMAKE_CURRENT_BINARY_DIR}/bond_tests.py) | |
diff --git a/tests/bond_tests.py b/tests/bond_tests.py | |
t@@ -0,0 +1,187 @@ | |
+#!/usr/bin/env python | |
+from pytestutils import * | |
+from sphere import * | |
+ | |
+def printKinematics(sb): | |
+ print('bonds_delta_n'); print(sb.bonds_delta_n) | |
+ print('bonds_delta_t'); print(sb.bonds_delta_t) | |
+ print('bonds_omega_n'); print(sb.bonds_omega_n) | |
+ print('bonds_omega_t'); print(sb.bonds_omega_t) | |
+ print('force'); print(sb.force) | |
+ print('torque'); print(sb.torque) | |
+ print('vel'); print(sb.vel) | |
+ print('angvel'); print(sb.angvel) | |
+ | |
+#### Bond tests #### | |
+print("### Bond tests ###") | |
+ | |
+# Zero arrays | |
+z2_1 = numpy.zeros((2,1)) | |
+z2_2 = numpy.zeros((2,2)) | |
+z1_3 = numpy.zeros((1,3)) | |
+z2_3 = numpy.zeros((2,3)) | |
+ | |
+# Small value arrays | |
+smallval = 1e-8 | |
+s2_1 = numpy.ones((2,1))*smallval | |
+ | |
+# Inter-particle distances to try (neg. for overlap) | |
+distances = [0.2, 0.0, -0.2] | |
+#distances = [-0.2] | |
+ | |
+for d in distances: | |
+ | |
+ radii = 0.5 | |
+ print("## Inter-particle distance: " + str(d/radii) + " radii") | |
+ | |
+ sb = Spherebin(np=2, sid='bondtest') | |
+ cleanup(sb) | |
+ | |
+ # setup particles, bond, and simulation | |
+ sb.x[0,:] = numpy.array((2.0, 2.0, 2.0)) | |
+ #sb.x[1,:] = numpy.array((2.2, 2.0, 2.0)) | |
+ sb.x[1,:] = numpy.array((2.0+2.0*radii+d, 2.0, 2.0)) | |
+ sb.radius = numpy.ones(sb.np)*radii | |
+ sb.initGridAndWorldsize(margin = 10, periodic = 1, contactmodel = 2, g = n… | |
+ sb.bond(0, 1) | |
+ sb.defaultParams(gamma_n = 0.0, gamma_t = 0.0) | |
+ #sb.initTemporal(total=0.5, file_dt=0.01) | |
+ | |
+ #sb.render(verbose=False) | |
+ #visualize(sb.sid, "energy") | |
+ | |
+ print("# Stability test") | |
+ sb.zeroKinematics() | |
+ sb.initTemporal(total=0.2, file_dt=0.01) | |
+ #sb.initTemporal(total=0.01, file_dt=0.0001) | |
+ sb.writebin(verbose=False) | |
+ sb.run(verbose=False) | |
+ #sb.run() | |
+ sb.readlast(verbose=False) | |
+ compareFloats(0.0, sb.energy("kin") + sb.energy("rot") + sb.energy("bondpo… | |
+ compareNumpyArrays(sb.vel, z2_3, "vel\t") | |
+ compareNumpyArrays(sb.angvel, z2_3, "angvel\t") | |
+ #printKinematics(sb) | |
+ #visualize(sb.sid, "energy") | |
+ #sb.readbin('../output/' + sb.sid + '.output00001.bin') | |
+ #printKinematics(sb) | |
+ | |
+ print("# Normal expansion") | |
+ sb.zeroKinematics() | |
+ #sb.initTemporal(total=0.2, file_dt=0.01) | |
+ sb.initTemporal(total=0.2, file_dt=0.001) | |
+ sb.vel[1,0] = 1e-4 | |
+ Ekinrot0 = sb.energy("kin") + sb.energy("rot") | |
+ sb.writebin(verbose=False) | |
+ sb.run(verbose=False) | |
+ sb.readlast(verbose=False) | |
+ compareFloats(Ekinrot0, sb.energy("kin") + sb.energy("rot") + sb.energy("b… | |
+ print("vel[:,0]"), | |
+ if ((sb.vel[0,0] <= 0.0) or (sb.vel[1,0] <= 0.0)): | |
+ print(failed()) | |
+ else : | |
+ print(passed()) | |
+ compareNumpyArrays(sb.vel[:,1:2], z2_2, "vel[:,1:2]") | |
+ compareNumpyArrays(sb.angvel, z2_3, "angvel\t") | |
+ #printKinematics(sb) | |
+ #visualize(sb.sid, "energy") | |
+ | |
+ print("# Normal contraction") | |
+ sb.zeroKinematics() | |
+ sb.initTemporal(total=0.2, file_dt=0.01) | |
+ sb.vel[1,0] = -1e-4 | |
+ Ekinrot0 = sb.energy("kin") + sb.energy("rot") | |
+ sb.writebin(verbose=False) | |
+ sb.run(verbose=False) | |
+ sb.readlast(verbose=False) | |
+ compareFloats(Ekinrot0, sb.energy("kin") + sb.energy("rot") + sb.energy("b… | |
+ print("vel[:,0]"), | |
+ if ((sb.vel[0,0] >= 0.0) or (sb.vel[1,0] >= 0.0)): | |
+ print(failed()) | |
+ else : | |
+ print(passed()) | |
+ compareNumpyArrays(sb.vel[:,1:2], z2_2, "vel[:,1:2]") | |
+ compareNumpyArrays(sb.angvel, z2_3, "angvel\t") | |
+ #printKinematics(sb) | |
+ | |
+ print("# Shear") | |
+ sb.zeroKinematics() | |
+ sb.initTemporal(total=0.2, file_dt=0.01) | |
+ sb.vel[1,2] = 1e-4 | |
+ Ekinrot0 = sb.energy("kin") + sb.energy("rot") | |
+ sb.writebin(verbose=False) | |
+ sb.run(verbose=False) | |
+ sb.readlast(verbose=False) | |
+ compareFloats(Ekinrot0, sb.energy("kin") + sb.energy("rot") + sb.energy("b… | |
+ #print("vel[:,0]"), | |
+ #if ((sb.vel[0,0] <= 0.0) or (sb.vel[1,0] >= 0.0)): | |
+ # print(failed()) | |
+ #else : | |
+ # print(passed()) | |
+ compareNumpyArrays(sb.vel[:,1], z2_1, "vel[:,1]") | |
+ print("vel[:,2]"), | |
+ if ((sb.vel[0,2] <= 0.0) or (sb.vel[1,2] <= 0.0)): | |
+ print(failed()) | |
+ else : | |
+ print(passed()) | |
+ #compareNumpyArrays(sb.angvel[:,0:2:2], z2_2, "angvel[:,0:2:2]") | |
+ #print("angvel[:,1]"), | |
+ #if ((sb.angvel[0,1] >= 0.0) or (sb.angvel[1,1] >= 0.0)): | |
+ # print(failed()) | |
+ #else : | |
+ # print(passed()) | |
+ compareNumpyArrays(sb.angvel, z2_3, "angvel\t") | |
+ #printKinematics(sb) | |
+ #visualize(sb.sid, "energy") | |
+ | |
+ | |
+ print("# Bend") | |
+ sb.zeroKinematics() | |
+ sb.initTemporal(total=0.2, file_dt=0.01) | |
+ sb.angvel[1,1] = 1e-4 | |
+ Ekinrot0 = sb.energy("kin") + sb.energy("rot") | |
+ sb.writebin(verbose=False) | |
+ sb.run(verbose=False) | |
+ sb.readlast(verbose=False) | |
+ compareFloats(Ekinrot0, sb.energy("kin") + sb.energy("rot") + sb.energy("b… | |
+ print("vel[:,0]"), | |
+ if (sb.vel[0,0] <= 0.0) or (sb.vel[1,0] >= 0.0): | |
+ print(failed()) | |
+ else : | |
+ print(passed()) | |
+ compareNumpyArrays(sb.vel[:,1], z2_1, "vel[:,1]") | |
+ print("vel[:,2]"), | |
+ if ((sb.vel[0,2] <= 0.0) or (sb.vel[1,2] >= 0.0)): | |
+ print(failed()) | |
+ else : | |
+ print(passed()) | |
+ compareNumpyArrays(sb.angvel[:,0:2:2], z2_2, "angvel[:,0:2:2]") | |
+ print("angvel[:,1]"), | |
+ if ((sb.angvel[0,1] <= 0.0) or (sb.angvel[1,1] <= 0.0)): | |
+ print(failed()) | |
+ else : | |
+ print(passed()) | |
+ #printKinematics(sb) | |
+ #visualize(sb.sid, "energy") | |
+ | |
+ | |
+ print("# Twist") | |
+ sb.zeroKinematics() | |
+ sb.initTemporal(total=0.2, file_dt=0.01) | |
+ sb.angvel[1,0] = 1e-4 | |
+ Ekinrot0 = sb.energy("kin") + sb.energy("rot") | |
+ sb.writebin(verbose=False) | |
+ sb.run(verbose=False) | |
+ sb.readlast(verbose=False) | |
+ compareFloats(Ekinrot0, sb.energy("kin") + sb.energy("rot") + sb.energy("b… | |
+ compareNumpyArrays(sb.vel, z2_3, "vel\t") | |
+ print("angvel[:,1]"), | |
+ if ((sb.angvel[0,1] <= 0.0) or (sb.angvel[0,1] <= 0.0)): | |
+ print(failed()) | |
+ else : | |
+ print(passed()) | |
+ compareNumpyArrays(sb.angvel[:,0:2:2], z2_2, "angvel[:,0:2:2]") | |
+ printKinematics(sb) | |
+ visualize(sb.sid, "energy") | |
+ | |
+#cleanup(sb) |