Skip to content
Snippets Groups Projects
Commit ba50e221 authored by Giovanni La Mura's avatar Giovanni La Mura
Browse files

Use HPC lattice for compact random cluster generation

parent 73f2154a
No related merge requests found
...@@ -385,17 +385,25 @@ def load_model(model_file): ...@@ -385,17 +385,25 @@ def load_model(model_file):
rnd_engine = "COMPACT" rnd_engine = "COMPACT"
if (rnd_engine == "COMPACT"): if (rnd_engine == "COMPACT"):
check = random_compact(sconf, gconf, rnd_seed, max_rad) check = random_compact(sconf, gconf, rnd_seed, max_rad)
if (check == 1): if (check == -1):
print("ERROR: compact random generator works only when all sphere types have the same radius.") print("ERROR: compact random generator works only when all sphere types have the same radius.")
return (None, None) return (None, None)
elif (check == -2):
print("ERROR: sub-particle radius larger than particle radius.")
return (None, None)
elif (check == -3):
print("ERROR: requested number of spheres cannot fit in allowed volume.")
return (None, None)
elif (rnd_engine == "LOOSE"): elif (rnd_engine == "LOOSE"):
# random_aggregate() checks internally whether application is INCLUSION # random_aggregate() checks internally whether application is INCLUSION
check = random_aggregate(sconf, gconf, rnd_seed, max_rad) check = random_aggregate(sconf, gconf, rnd_seed, max_rad)
else: else:
print("ERROR: unrecognized random generator engine.") print("ERROR: unrecognized random generator engine.")
return (None, None) return (None, None)
if (check != 0): if (check != sconf['nsph']):
print("WARNING: %d sphere(s) could not be placed."%check) print("WARNING: placed only %d out of %d requested spheres."%(check, sconf['nsph']))
sconf['nsph'] = check
gconf['nsph'] = check
else: else:
if (len(model['geometry_settings']['x_coords']) != gconf['nsph']): if (len(model['geometry_settings']['x_coords']) != gconf['nsph']):
print("ERROR: coordinate vectors do not match the number of spheres!") print("ERROR: coordinate vectors do not match the number of spheres!")
...@@ -588,15 +596,19 @@ def random_aggregate(scatterer, geometry, seed, max_rad, max_attempts=100): ...@@ -588,15 +596,19 @@ def random_aggregate(scatterer, geometry, seed, max_rad, max_attempts=100):
vec_thetas = [0.0 for i in range(nsph)] vec_thetas = [0.0 for i in range(nsph)]
vec_phis = [0.0 for i in range(nsph)] vec_phis = [0.0 for i in range(nsph)]
vec_rads = [0.0 for i in range(nsph)] vec_rads = [0.0 for i in range(nsph)]
vec_types = []
n_types = scatterer['configurations'] n_types = scatterer['configurations']
if (0 in scatterer['vec_types']): if (0 in scatterer['vec_types']):
tincrement = 1 if scatterer['application'] != "INCLUSION" else 2 tincrement = 1 if scatterer['application'] != "INCLUSION" else 2
for ti in range(nsph): for ti in range(nsph):
itype = tincrement + int(n_types * random.random()) itype = tincrement + int(n_types * random.random())
scatterer['vec_types'][ti] = itype scatterer['vec_types'][ti] = itype
if (scatterer['application'] == "INCLUSION"):
scatterer['vec_types'][0] = 1
sph_type_index = scatterer['vec_types'][0] - 1 sph_type_index = scatterer['vec_types'][0] - 1
vec_spheres = [{'itype': sph_type_index + 1, 'x': 0.0, 'y': 0.0, 'z': 0.0}] vec_spheres = [{'itype': sph_type_index + 1, 'x': 0.0, 'y': 0.0, 'z': 0.0}]
vec_rads[0] = scatterer['ros'][sph_type_index] vec_rads[0] = scatterer['ros'][sph_type_index]
vec_types.append(sph_type_index + 1)
placed_spheres = 1 placed_spheres = 1
attempts = 0 attempts = 0
for i in range(1, nsph): for i in range(1, nsph):
...@@ -670,7 +682,9 @@ def random_aggregate(scatterer, geometry, seed, max_rad, max_attempts=100): ...@@ -670,7 +682,9 @@ def random_aggregate(scatterer, geometry, seed, max_rad, max_attempts=100):
}) })
is_placed = True is_placed = True
placed_spheres += 1 placed_spheres += 1
vec_types.append(sph_type_index + 1)
attempts = 0 attempts = 0
scatterer['vec_types'] = vec_types
sph_index = 0 sph_index = 0
for sphere in sorted(vec_spheres, key=lambda item: item['itype']): for sphere in sorted(vec_spheres, key=lambda item: item['itype']):
scatterer['vec_types'][sph_index] = sphere['itype'] scatterer['vec_types'][sph_index] = sphere['itype']
...@@ -678,6 +692,7 @@ def random_aggregate(scatterer, geometry, seed, max_rad, max_attempts=100): ...@@ -678,6 +692,7 @@ def random_aggregate(scatterer, geometry, seed, max_rad, max_attempts=100):
geometry['vec_sph_y'][sph_index] = sphere['y'] geometry['vec_sph_y'][sph_index] = sphere['y']
geometry['vec_sph_z'][sph_index] = sphere['z'] geometry['vec_sph_z'][sph_index] = sphere['z']
sph_index += 1 sph_index += 1
result = placed_spheres
return result return result
## \brief Generate a random compact cluster from YAML configuration options. ## \brief Generate a random compact cluster from YAML configuration options.
...@@ -700,45 +715,30 @@ def random_compact(scatterer, geometry, seed, max_rad): ...@@ -700,45 +715,30 @@ def random_compact(scatterer, geometry, seed, max_rad):
random.seed(seed) random.seed(seed)
nsph = scatterer['nsph'] nsph = scatterer['nsph']
n_types = scatterer['configurations'] n_types = scatterer['configurations']
if (0 in scatterer['vec_types']): radius = scatterer['ros'][0]
tincrement = 1 if scatterer['application'] != "INCLUSION" else 2 # Return an error code if types have different radii
for ti in range(nsph):
itype = tincrement + int(n_types * random.random())
scatterer['vec_types'][ti] = itype
if (max(scatterer['ros']) != min(scatterer['ros'])): if (max(scatterer['ros']) != min(scatterer['ros'])):
result = 1 result = -1
elif (radius > max_rad):
# Requested spheres are larger than the maximum allowed volume.
# End function with error code -2.
result = -2
else: else:
radius = scatterer['ros'][0] x_centers = np.arange(-1.0 * max_rad + 2.0 * radius, max_rad, 2.0 * radius)
x_centers = np.arange(-1.0 * max_rad + radius, max_rad, 2.0 * radius) x_size = len(x_centers)
y_centers = np.arange(-1.0 * max_rad + radius, max_rad, math.sqrt(3.0) * radius) y_size = int(2.0 * max_rad / ((1.0 + math.sqrt(3.0) / 3.0) * radius))
z_centers = np.arange(-1.0 * max_rad + radius, max_rad, math.sqrt(3.0) * radius) z_size = int(2.0 * max_rad / ((1.0 + 2.0 * math.sqrt(6.0) / 3.0) * radius))
x_offset = radius
y_offset = radius
x_layer_offset = radius
y_layer_offset = radius / math.sqrt(3.0)
tmp_spheres = [] tmp_spheres = []
n_cells = len(x_centers) * len(y_centers) * len(z_centers) n_cells = x_size * y_size * z_size
print("INFO: the cubic space would contain %d spheres."%n_cells) print("INFO: the cubic space would contain %d spheres."%n_cells)
n_max_spheres = int((max_rad / radius) * (max_rad / radius) * (max_rad / radius) * 0.74) k = 0
print("INFO: the maximum radius allows for %d spheres."%n_max_spheres) z = -max_rad + radius
for zi in range(len(z_centers)): while (z < max_rad - radius):
if (x_layer_offset == 0.0): j = 0
x_layer_offset = radius y = -max_rad + radius
else: while (y < max_rad - radius):
x_layer_offset = 0.0 for i in range(len(x_centers)):
if (y_offset == 0.0): x = (2 * (i + 1) + (j + k) % 2) * radius - max_rad
y_offset = radius
else:
y_offset = 0.0
for yi in range(len(y_centers)):
if (x_offset == 0.0):
x_offset = radius
else:
x_offset = 0.0
for xi in range(len(x_centers)):
x = x_centers[xi] + x_offset + x_layer_offset
y = y_centers[yi] + y_offset
z = z_centers[zi]
extent = radius + math.sqrt(x * x + y * y + z * z) extent = radius + math.sqrt(x * x + y * y + z * z)
if (extent < max_rad): if (extent < max_rad):
tmp_spheres.append({ tmp_spheres.append({
...@@ -747,6 +747,11 @@ def random_compact(scatterer, geometry, seed, max_rad): ...@@ -747,6 +747,11 @@ def random_compact(scatterer, geometry, seed, max_rad):
'y': y, 'y': y,
'z': z 'z': z
}) })
#
j += 1
y = math.sqrt(3.0) * (j + (k % 2) / 3.0) * radius - max_rad + radius
k += 1
z = 2.0 / 3.0 * math.sqrt(6.0) * k * radius - max_rad + radius
#tmp_spheres = [{'itype': 1, 'x': 0.0, 'y': 0.0, 'z': 0.0}] #tmp_spheres = [{'itype': 1, 'x': 0.0, 'y': 0.0, 'z': 0.0}]
current_n = len(tmp_spheres) current_n = len(tmp_spheres)
print("INFO: before erosion there are %d spheres in use."%current_n) print("INFO: before erosion there are %d spheres in use."%current_n)
...@@ -778,20 +783,20 @@ def random_compact(scatterer, geometry, seed, max_rad): ...@@ -778,20 +783,20 @@ def random_compact(scatterer, geometry, seed, max_rad):
current_n -= 1 current_n -= 1
vec_spheres = [] vec_spheres = []
sph_index = 0 sph_index = 0
# Generate a vector of types if none is given
if (0 in scatterer['vec_types']):
tincrement = 1 if scatterer['application'] != "INCLUSION" else 2
for ti in range(current_n):
itype = tincrement + int(n_types * random.random())
scatterer['vec_types'][ti] = itype
if (scatterer['application'] == "INCLUSION"):
scatterer['vec_types'][0] = 1
for ti in range(len(tmp_spheres)): for ti in range(len(tmp_spheres)):
sphere = tmp_spheres[ti] sphere = tmp_spheres[ti]
if (sphere['x'] < max_rad): if (sphere['x'] < max_rad):
sphere['itype'] = scatterer['vec_types'][sph_index] sphere['itype'] = scatterer['vec_types'][sph_index]
sph_index += 1 sph_index += 1
vec_spheres.append(sphere) vec_spheres.append(sphere)
#pl = pv.Plotter()
#for si in range(len(vec_spheres)):
# x = vec_spheres[si]['x'] / max_rad
# y = vec_spheres[si]['y'] / max_rad
# z = vec_spheres[si]['z'] / max_rad
# mesh = pv.Sphere(radius / max_rad, (x, y, z))
# pl.add_mesh(mesh)
#pl.export_obj("scene.obj")
sph_index = 0 sph_index = 0
for sphere in sorted(vec_spheres, key=lambda item: item['itype']): for sphere in sorted(vec_spheres, key=lambda item: item['itype']):
scatterer['vec_types'][sph_index] = sphere['itype'] scatterer['vec_types'][sph_index] = sphere['itype']
...@@ -799,7 +804,7 @@ def random_compact(scatterer, geometry, seed, max_rad): ...@@ -799,7 +804,7 @@ def random_compact(scatterer, geometry, seed, max_rad):
geometry['vec_sph_y'][sph_index] = sphere['y'] geometry['vec_sph_y'][sph_index] = sphere['y']
geometry['vec_sph_z'][sph_index] = sphere['z'] geometry['vec_sph_z'][sph_index] = sphere['z']
sph_index += 1 sph_index += 1
return result return current_n
## \brief Write the geometry configuration dictionary to legacy format. ## \brief Write the geometry configuration dictionary to legacy format.
# #
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment