tFixed porosity calculator and added porosity tests - sphere - GPU-based 3D dis… | |
git clone git://src.adamsgaard.dk/sphere | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit d6e187230caddd28d3aeac6ebd09175c1067fa40 | |
parent b3a14695511b1c825ed7bd11f7ea0e0f07a3da98 | |
Author: Anders Damsgaard <[email protected]> | |
Date: Wed, 2 Jan 2013 09:57:32 +0100 | |
Fixed porosity calculator and added porosity tests | |
Diffstat: | |
M python/tests.py | 83 ++++++++++++++++++++++++++++-… | |
M src/main.cpp | 15 +++++++++++---- | |
M src/sphere.cpp | 45 +++++++++++++++++++++++------… | |
M src/sphere.h | 3 +++ | |
4 files changed, 123 insertions(+), 23 deletions(-) | |
--- | |
diff --git a/python/tests.py b/python/tests.py | |
t@@ -2,18 +2,36 @@ | |
from sphere import * | |
import subprocess | |
+def passed(): | |
+ return "\tPassed" | |
+ | |
+def failed(): | |
+ return "\tFailed" | |
+ | |
def compare(first, second, string): | |
if (first == second): | |
- print(string + "\tPassed") | |
+ print(string + passed()) | |
else: | |
- print(string + "\tFailed") | |
+ print(string + failed()) | |
+ | |
+def compareFloats(first, second, string, criterion=1e-5): | |
+ if abs(first-second) < criterion: | |
+ print(string + passed()) | |
+ else : | |
+ print(string + failed()) | |
+ | |
+def cleanup(spherebin): | |
+ 'Remove temporary files' | |
+ subprocess.call("rm -f ../input/" + spherebin.sid + ".bin", shell=True) | |
+ subprocess.call("rm -f ../output/" + spherebin.sid + ".*.bin", shell=True) | |
+ print("") | |
#### Input/output tests #### | |
print("### Input/output tests ###") | |
# Generate data in python | |
-orig = Spherebin(np = 100, nw = 1, sid = "test") | |
+orig = Spherebin(np = 100, nw = 1, sid = "test-initgrid") | |
orig.generateRadii(histogram = False) | |
orig.defaultParams() | |
orig.initRandomGridPos(g = numpy.zeros(orig.nd)) | |
t@@ -24,24 +42,73 @@ orig.writebin(verbose=False) | |
# Test Python IO routines | |
py = Spherebin() | |
-py.readbin("../input/test.bin", verbose=False) | |
+py.readbin("../input/" + orig.sid + ".bin", verbose=False) | |
compare(orig, py, "Python IO:") | |
# Test C++ IO routines | |
orig.run(verbose=False, hideinputfile=True) | |
#orig.run() | |
cpp = Spherebin() | |
-cpp.readbin("../output/test.output00000.bin", verbose=False) | |
+cpp.readbin("../output/" + orig.sid + ".output00000.bin", verbose=False) | |
compare(orig, cpp, "C++ IO: ") | |
# Test CUDA IO routines | |
cuda = Spherebin() | |
-cuda.readbin("../output/test.output00001.bin", verbose=False) | |
+cuda.readbin("../output/" + orig.sid + ".output00001.bin", verbose=False) | |
cuda.time_current = orig.time_current | |
cuda.time_step_count = orig.time_step_count | |
compare(orig, cuda, "CUDA IO: ") | |
# Remove temporary files | |
-subprocess.call("rm ../input/" + orig.sid + ".bin", shell=True) | |
-subprocess.call("rm ../output/" + orig.sid + ".*.bin", shell=True) | |
+cleanup(orig) | |
+ | |
+ | |
+#### Porosity tests #### | |
+print("### porosity tests ###") | |
+ | |
+def testPorosities(spherebin): | |
+ | |
+ # Number of vertical slices | |
+ slicevals = [1, 2, 4] | |
+ i = 1 # iterator var | |
+ for slices in slicevals: | |
+ | |
+ # Find correct value of bulk porosity | |
+ n_bulk = spherebin.bulkPorosity() | |
+ #print("Bulk: " + str(n_bulk)) | |
+ | |
+ porosity = spherebin.porosity(slices = slices)[0] | |
+ #print("Avg: " + str(numpy.average(porosity))) | |
+ #print(porosity) | |
+ | |
+ # Check if average of porosity function values matches the bulk porosi… | |
+ compareFloats(n_bulk, numpy.average(porosity), \ | |
+ spherebin.sid + ": Porosity average to bulk porosity ("\ | |
+ + str(i) + "/" + str(len(slicevals)) + "):") | |
+ i += 1 | |
+ | |
+# Test data from previous test | |
+testPorosities(orig) | |
+ | |
+# Simple cubic packing of uniform spheres | |
+# The theoretical porosity is (4/3*pi*r^3)/(2r)^3 = 0.476 | |
+sidelen = 10 | |
+cubic = Spherebin(np = sidelen**3, sid='cubic') | |
+radius = 1.0 | |
+cubic.generateRadii(psd='uni', radius_mean=radius, radius_variance=0.0, histog… | |
+for ix in range(sidelen): | |
+ for iy in range(sidelen): | |
+ for iz in range(sidelen): | |
+ i = ix + sidelen * (iy + sidelen * iz) # linear index | |
+ cubic.x[i,0] = ix*radius*2.0 + radius | |
+ cubic.x[i,1] = iy*radius*2.0 + radius | |
+ cubic.x[i,2] = iz*radius*2.0 + radius | |
+cubic.L[:] = 2.0 * radius * sidelen | |
+ | |
+cubic.initTemporal(0.2) | |
+cubic.initGrid() | |
+ | |
+testPorosities(cubic) | |
+ | |
+cleanup(cubic) | |
diff --git a/src/main.cpp b/src/main.cpp | |
t@@ -53,7 +53,8 @@ int main(const int argc, const char *argv[]) | |
<< "-dc, --dont-check\tdon't check values before running\n" | |
<< "\nRaytracer (-r) specific options:\n" | |
<< "-m <method> <maxval>, --method <method> <maxval>\n\tcolor … | |
- << "\tpres, vel, angvel, xdisp, angpos\n" | |
+ << "\tnormal, pres, vel, angvel, xdisp, angpos\n" | |
+ << "\t'normal' is the default mode\n" | |
<< std::endl; | |
return 0; // Exit with success | |
} | |
t@@ -92,7 +93,9 @@ int main(const int argc, const char *argv[]) | |
else if (argvi == "-m" || argvi == "--method") { | |
// Find out which | |
- if (std::string(argv[i+1]) == "pres") | |
+ if (std::string(argv[i+1]) == "normal") | |
+ method = 0; | |
+ else if (std::string(argv[i+1]) == "pres") | |
method = 1; | |
else if (std::string(argv[i+1]) == "vel") | |
method = 2; | |
t@@ -109,8 +112,12 @@ int main(const int argc, const char *argv[]) | |
} | |
// Read max. value of colorbar as next argument | |
- max_val = atof(argv[i+2]); | |
- i += 2; // skip ahead | |
+ if (method != 0) { | |
+ max_val = atof(argv[i+2]); | |
+ i += 2; // skip ahead | |
+ } else { | |
+ i += 1; | |
+ } | |
} | |
diff --git a/src/sphere.cpp b/src/sphere.cpp | |
t@@ -306,6 +306,19 @@ Float sphericalCap(const Float h, const Float r) | |
return M_PI * h * h / 3.0 * (3.0 * r - h); | |
} | |
+// Returns the max. radius of any particle | |
+Float DEM::r_max() | |
+{ | |
+ Float r_max = 0.0; | |
+ Float r; | |
+ for (unsigned int i=0; i<np; ++i) { | |
+ r = k.x[i].w; | |
+ if (r > r_max) | |
+ r_max = r; | |
+ } | |
+ return r; | |
+} | |
+ | |
// Calculate the porosity with depth, and write to file in output directory | |
void DEM::porosity(const int z_slices) | |
{ | |
t@@ -321,6 +334,15 @@ void DEM::porosity(const int z_slices) | |
// Calculate depth slice thickness | |
Float h_slice = (top - grid.origo[2]) / (Float)z_slices; | |
+ // Check that the vertical slice height does not exceed the | |
+ // max particle diameter, since this function doesn't work | |
+ // if the sphere intersects more than 1 boundary | |
+ if (h_slice <= r_max()*2.0) { | |
+ std::cerr << "Error! The number of z-slices is too high." | |
+ << std::endl; | |
+ exit(1); | |
+ } | |
+ | |
// Calculate slice volume | |
Float V_slice = h_slice * grid.L[0] * grid.L[1]; | |
t@@ -331,7 +353,7 @@ void DEM::porosity(const int z_slices) | |
Float porosity[z_slices]; | |
// Loop over vertical slices | |
-#pragma omp parallel for if(np > 100) | |
+//#pragma omp parallel for if(np > 100) | |
for (int iz = 0; iz<z_slices; ++iz) { | |
// The void volume equals the slice volume, with the | |
t@@ -358,14 +380,14 @@ void DEM::porosity(const int z_slices) | |
// If the sphere is inside the slice and not intersecting the | |
// boundaries, subtract the entire sphere volume | |
- if (z_slice_low < z_sphere_low && z_sphere_high < z_slice_high) { | |
+ if (z_slice_low <= z_sphere_low && z_sphere_high <= z_slice_high) { | |
V_void -= V_sphere; | |
} else { | |
// If the sphere intersects with the lower boundary, | |
// and the centre is below the boundary | |
- if (z_slice_low > z_sphere_centre && z_slice_low < z_sphere_hi… | |
+ if (z_slice_low >= z_sphere_centre && z_slice_low <= z_sphere_… | |
// Subtract the volume of a spherical cap | |
V_void -= sphericalCap(z_sphere_high - z_slice_low, radius… | |
t@@ -381,24 +403,25 @@ void DEM::porosity(const int z_slices) | |
} | |
// If the sphere intersects with the upper boundary, | |
+ // and the centre is above the boundary | |
+ if (z_slice_high <= z_sphere_centre && z_slice_high >= z_spher… | |
+ | |
+ // Subtract the volume of the spherical cap below | |
+ V_void -= sphericalCap(z_slice_high - z_sphere_low, radius… | |
+ } | |
+ // If the sphere intersects with the upper boundary, | |
// and the centre is below the boundary | |
- if (z_slice_high > z_sphere_centre && z_slice_high < z_sphere_… | |
+ else if (z_slice_high > z_sphere_centre && z_slice_high < z_sp… | |
// Subtract the volume of the sphere, | |
// then add the volume of the spherical cap above | |
V_void -= V_sphere + sphericalCap(z_sphere_high - z_slice_… | |
} | |
- // If the sphere intersects with the upper boundary, | |
- // and the centre is above the boundary | |
- else if (z_slice_high < z_sphere_centre && z_slice_high > z_sp… | |
- | |
- // Subtract the volume of the spherical cap below | |
- V_void -= sphericalCap(z_slice_high - z_sphere_low, radius… | |
- } | |
} | |
+ | |
} | |
// Save the mid z-point | |
diff --git a/src/sphere.h b/src/sphere.h | |
t@@ -122,6 +122,9 @@ class DEM { | |
// Find and return the max. position of any particle in each dimension | |
float3 maxPos(void); | |
+ // Find and return the max. radius | |
+ Float r_max(void); | |
+ | |
// Write porosities found in porosity() to text file | |
void writePorosities( | |
const char *target, |