Skip to content

Commit fe5eece

Browse files
committed
Bugfixes and improvements in plotting of rectangular RVEs
1 parent 82c8434 commit fe5eece

File tree

4 files changed

+45
-17
lines changed

4 files changed

+45
-17
lines changed

src/kanapy/api.py

+21-5
Original file line numberDiff line numberDiff line change
@@ -372,16 +372,24 @@ def plot_ellipsoids(self, cmap='prism', dual_phase=False):
372372
""" Generates plot of particles"""
373373
if self.particles is None:
374374
raise ValueError('No particle to plot. Run pack first.')
375-
plot_ellipsoids_3D(self.particles, cmap=cmap, dual_phase=dual_phase)
375+
hmin = min(self.rve.size)
376+
asp_arr = [int(self.rve.size[0] / hmin),
377+
int(self.rve.size[1] / hmin),
378+
int(self.rve.size[2] / hmin)]
379+
plot_ellipsoids_3D(self.particles, cmap=cmap, dual_phase=dual_phase, asp_arr=asp_arr)
376380

377381
def plot_particles(self, cmap='prism', dual_phase=False, plot_hull=True):
378382
""" Generates plot of particles"""
379383
if self.particles is None:
380384
raise ValueError('No particle to plot. Run pack first.')
381385
if self.particles[0].inner is None:
382386
raise ValueError('Ellipsoids without inner polygon cannot be plotted.')
387+
hmin = min(self.rve.size)
388+
asp_arr = [int(self.rve.size[0] / hmin),
389+
int(self.rve.size[1] / hmin),
390+
int(self.rve.size[2] / hmin)]
383391
plot_particles_3D(self.particles, cmap=cmap,
384-
dual_phase=dual_phase, plot_hull=plot_hull)
392+
dual_phase=dual_phase, plot_hull=plot_hull, asp_arr=asp_arr)
385393

386394
def plot_voxels(self, sliced=False, dual_phase=False, cmap='prism', ori=None,
387395
color_key=0, silent=False):
@@ -420,9 +428,13 @@ def plot_voxels(self, sliced=False, dual_phase=False, cmap='prism', ori=None,
420428
clist = None
421429
else:
422430
clist = None
423-
431+
hmin = min(self.rve.size)
432+
asp_arr = [int(self.rve.size[0] / hmin),
433+
int(self.rve.size[1] / hmin),
434+
int(self.rve.size[2] / hmin)]
424435
fig = plot_voxels_3D(data, Ngr=np.sum(self.ngrains), sliced=sliced,
425-
dual_phase=dual_phase, cmap=cmap, clist=clist, silent=silent)
436+
dual_phase=dual_phase, cmap=cmap, clist=clist,
437+
silent=silent, asp_arr=asp_arr)
426438
if silent:
427439
return fig
428440

@@ -433,8 +445,12 @@ def plot_grains(self, geometry=None, cmap='prism', alpha=0.4,
433445
geometry = self.geometry
434446
if geometry is None:
435447
raise ValueError('No polygons for grains defined. Run generate_grains() first')
448+
hmin = min(self.rve.size)
449+
asp_arr = [int(self.rve.size[0] / hmin),
450+
int(self.rve.size[1] / hmin),
451+
int(self.rve.size[2] / hmin)]
436452
plot_polygons_3D(geometry, cmap=cmap, alpha=alpha, ec=ec,
437-
dual_phase=dual_phase)
453+
dual_phase=dual_phase, asp_arr=asp_arr)
438454

439455
def plot_stats(self, data=None,
440456
gs_data=None, gs_param=None,

src/kanapy/initializations.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def __init__(self, stats_dicts, nsteps=1000, from_voxels=False, poly=None):
101101
Number of alloy in ICAMS CP-UMAT
102102
"""
103103

104-
def init_particles():
104+
def init_particles(ip):
105105
"""
106106
Extract statistical microstructure information from data dictionary
107107
and initalize particles for packing accordingly
@@ -135,7 +135,8 @@ def gen_data_basic(pdict):
135135
K = individualK / np.sum(individualK)
136136

137137
# Total number of ellipsoids for packing density given by volume fraction
138-
num_f = np.divide(K * phase_vf[-1] * np.prod(self.size), volume_array)
138+
ip = pdict['Phase']
139+
num_f = np.divide(K * phase_vf[ip] * np.prod(self.size), volume_array)
139140
"""print(f'Particle numbers: {num_f}')
140141
print(f'Total volume of particles: {np.sum(np.multiply(num_f, volume_array))}')"""
141142
# Rounding particle numbers to integer values keeping total volume constant
@@ -151,7 +152,7 @@ def gen_data_basic(pdict):
151152
num[i] = v1
152153
"""print(f'Volume after rounding: {np.sum(np.multiply(num, volume_array))}')
153154
print(f'Particle numbers: {num}')
154-
print(f'Phase volume fraction: {phase_vf[-1]}')"""
155+
print(f'Phase volume fraction: {phase_vf[ip]}')"""
155156
totalEllipsoids = int(np.sum(num))
156157

157158
# Duplicate the diameter values
@@ -389,7 +390,7 @@ def gen_data_elong(pdict):
389390
if not from_voxels:
390391
if stats["Grain type"] not in ["Elongated", "Equiaxed", "Free"]:
391392
raise ValueError('The value for "Grain type" must be either "Equiaxed" or "Elongated".')
392-
part_dict = init_particles()
393+
part_dict = init_particles(ip)
393394
self.particle_data.append(part_dict)
394395
self.nparticles.append(part_dict['Number'])
395396
print(' RVE characteristics:')

src/kanapy/plotting.py

+17-6
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
def plot_voxels_3D(data, Ngr=1, sliced=False, dual_phase=False,
3939
mask=None, cmap='prism', alpha=1.0, silent=False,
40-
clist=None):
40+
clist=None, asp_arr=None):
4141
"""
4242
Plot voxels in microstructure, each grain with a different color. Sliced
4343
indicates whether one eighth of the box should be removed to see internal
@@ -75,7 +75,8 @@ def plot_voxels_3D(data, Ngr=1, sliced=False, dual_phase=False,
7575
Nx = data.shape[0]
7676
Ny = data.shape[1]
7777
Nz = data.shape[2]
78-
78+
if asp_arr is None:
79+
asp_arr = [1, 1, 1]
7980
if mask is None:
8081
vox_b = np.full(data.shape, True, dtype=bool)
8182
else:
@@ -116,14 +117,15 @@ def plot_voxels_3D(data, Ngr=1, sliced=False, dual_phase=False,
116117
ax.set_xlim(right=Nx)
117118
ax.set_ylim(top=Ny)
118119
ax.set_zlim(top=Nz)
120+
ax.set_box_aspect(asp_arr)
119121
if silent:
120122
return fig
121123
else:
122124
plt.show(block=True)
123125

124126

125127
def plot_polygons_3D(geometry, cmap='prism', alpha=0.4, ec=[0.5, 0.5, 0.5, 0.1],
126-
dual_phase=False, silent=False):
128+
dual_phase=False, silent=False, asp_arr=None):
127129
"""
128130
Plot triangularized convex hulls of grains, based on vertices, i.e.
129131
connection points of 4 up to 8 grains or the end points of triple or quadruple
@@ -148,6 +150,8 @@ def plot_polygons_3D(geometry, cmap='prism', alpha=0.4, ec=[0.5, 0.5, 0.5, 0.1],
148150
None.
149151
150152
"""
153+
if asp_arr is None:
154+
asp_arr = [1, 1, 1]
151155
grains = geometry['Grains']
152156
pts = geometry['Points']
153157
Ng = np.amax(list(grains.keys()))
@@ -171,14 +175,15 @@ def plot_polygons_3D(geometry, cmap='prism', alpha=0.4, ec=[0.5, 0.5, 0.5, 0.1],
171175
ax.set(xlabel='x', ylabel='y', zlabel='z')
172176
ax.set_title('Polygonized microstructure')
173177
ax.view_init(30, 30)
178+
ax.set_box_aspect(asp_arr)
174179
if silent:
175180
return fig
176181
else:
177182
plt.show(block=True)
178183

179184

180185

181-
def plot_ellipsoids_3D(particles, cmap='prism', dual_phase=False, silent=False):
186+
def plot_ellipsoids_3D(particles, cmap='prism', dual_phase=False, silent=False, asp_arr=None):
182187
"""
183188
Display ellipsoids after packing procedure
184189
Parameters
@@ -190,7 +195,8 @@ def plot_ellipsoids_3D(particles, cmap='prism', dual_phase=False, silent=False):
190195
dual_phase : bool, optional
191196
Whether to display the ellipsoids in red/green contrast or in colors
192197
"""
193-
198+
if asp_arr is None:
199+
asp_arr = [1, 1, 1]
194200
fig = plt.figure(figsize=(6, 6))
195201
ax = fig.add_subplot(111, projection='3d')
196202
ax.set(xlabel='x', ylabel='y', zlabel='z')
@@ -211,14 +217,16 @@ def plot_ellipsoids_3D(particles, cmap='prism', dual_phase=False, silent=False):
211217
y = (pts[:, 1] + ctr[1]).reshape((100, 100))
212218
z = (pts[:, 2] + ctr[2]).reshape((100, 100))
213219
ax.plot_surface(x, y, z, rstride=4, cstride=4, color=color, linewidth=0, antialiased=False)
220+
ax.set_box_aspect(asp_arr)
214221
if silent:
215222
return fig
216223
else:
217224
plt.show(block=True)
218225

219226

220227

221-
def plot_particles_3D(particles, cmap='prism', dual_phase=False, plot_hull=True, silent=False):
228+
def plot_particles_3D(particles, cmap='prism', dual_phase=False, plot_hull=True,
229+
silent=False, asp_arr=None):
222230
"""
223231
Display inner polyhedra of ellipsoids after packing procedure
224232
@@ -238,6 +246,8 @@ def plot_particles_3D(particles, cmap='prism', dual_phase=False, plot_hull=True,
238246
None.
239247
240248
"""
249+
if asp_arr is None:
250+
asp_arr = [1, 1, 1]
241251
fig = plt.figure(figsize=plt.figaspect(1))
242252
ax = fig.add_subplot(111, projection='3d')
243253
ax.set(xlabel='x', ylabel='y', zlabel='z')
@@ -272,6 +282,7 @@ def plot_particles_3D(particles, cmap='prism', dual_phase=False, plot_hull=True,
272282
y = (pts[:, 1] + ctr[None, 1]).reshape((100, 100))
273283
z = (pts[:, 2] + ctr[None, 2]).reshape((100, 100))
274284
ax.plot_surface(x, y, z, rstride=4, cstride=4, color=col, linewidth=0)
285+
ax.set_box_aspect(asp_arr)
275286
if silent:
276287
return fig
277288
else:

tests/test_packing.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def par_sim(mocker):
1616
'Minor_diameter1': np.array([2.15, 3.6, 1.15]),
1717
'Minor_diameter2': np.array([2.15, 3.6, 1.15]),
1818
'Tilt angle': np.array([92, 89.3, 85]),
19-
'Phase': [0, 0, 0]}
19+
'Phase': 0}
2020

2121
sb = mocker.MagicMock()
2222
# Define attributes to mocker object
@@ -119,7 +119,7 @@ def test_packingRoutine():
119119
'Minor_diameter1': [1.5, 1.5],
120120
'Minor_diameter2': [1.5, 1.5],
121121
'Tilt angle': [86, 92],
122-
'Phase': [0, 0]}
122+
'Phase': 0}
123123
sb = Simulation_Box((3, 3, 3))
124124

125125
# Test if the 'particle_generator' function is called once

0 commit comments

Comments
 (0)