Module PostProcessing
@author: Alexandre Sac–Morane alexandre.sac-morane@enpc.fr
This is the file to post-proccess the data.
Expand source code
#-------------------------------------------------------------------------------
# Librairies
#-------------------------------------------------------------------------------
import numpy as np
import matplotlib.pyplot as plt
import pyvista as pv
import pickle, porespy, skimage, time
# Own
from main import index_to_str
#-------------------------------------------------------------------------------
# Functions
#-------------------------------------------------------------------------------
def pp(dict_user):
'''
Main function for the post-processing.
'''
# compute performances
tic = time.perf_counter()
# initialize the dict
dict_tempo = {
'L_M_Neck': [],
'L_freeSurface': [],
'L_M0': [],
'L_M1': [],
'L_M2': [],
'L_M3': [],
'map': None
}
# read and plot the .csv data.
ReadCSV(dict_user, dict_tempo)
print('\nread pvtu')
# determine the zone of interest for the porosity
# a box is generated from the lastest configuration (more dense)
# read the .pvtu
ReadPVTU(dict_user, dict_tempo, 'output/vtk/PF_Sintering_other_'+dict_user['last_j_str']+'.pvtu')
# compute the zone of interest
RebuildMap_ZoneInterest(dict_user, dict_tempo)
# iterate on the .pvtu files
for i in range(dict_user['last_j']+1):
# flag the initial map (for plot)
if i == 0 :
dict_tempo['ic_flag'] = True
else:
dict_tempo['ic_flag'] = False
# read the .pvtu
ReadPVTU(dict_user, dict_tempo, 'output/vtk/PF_Sintering_other_'+index_to_str(i)+'.pvtu')
# Biswas, 2018
# compute the neck area
ComputeNeck(dict_tempo)
# compute the free surface area
ComputeFreeSurface(dict_tempo)
# Guevel, 2022
RebuildMap(dict_user, dict_tempo)
ComputeMorphometers(dict_tempo)
# plot final map
PlotMap(dict_user, dict_tempo)
# Biswas, 2018
# plot the neck area
PlotNeck(dict_tempo)
# plot the free surface area
PlotFreeSurface(dict_tempo)
# Guevel, 2022
PlotMorphometers(dict_tempo)
# compute performances
tac = time.perf_counter()
hours = (tac-tic)//(60*60)
minutes = (tac-tic - hours*60*60)//(60)
seconds = int(tac-tic - hours*60*60 - minutes*60)
print("\nPost-processing time : "+str(hours)+" hours "+str(minutes)+" minutes "+str(seconds)+" seconds")
print('Post-processing ends')
#-------------------------------------------------------------------------------
def ReadCSV(dict_user, dict_tempo):
'''
Read the csv file generated with Moose (made by postprocessors).
'''
print('\nread csv')
# read file
f = open('output/PF_Sintering_csv.csv', "r")
lines = f.readlines()
f.close()
# init data
time_pp = []
c_pp = []
L_eta_pp = []
for i_grain in range(dict_user['n_eta']):
L_eta_pp.append([])
# iterate on lines
for line in lines[1:]:
line = line.replace("\n", "")
data = line.split(',')
# read data
time_pp.append(float(data[0]))
c_pp.append(float(data[1]))
for i_grain in range(dict_user['n_eta']):
L_eta_pp[i_grain].append(float(data[2+i_grain]))
# plot time-mass
fig, ax1 = plt.subplots(1,1,figsize=(16,9))
ax1.plot(time_pp, c_pp, linewidth=6)
ax1.set_xlabel('time (-)', fontsize=25)
ax1.set_ylabel('mean mass concentration (-)', fontsize=25)
ax1.tick_params(axis='both', labelsize=20, width=3, length=3)
fig.tight_layout()
fig.savefig('output/evol_time_mass.png')
plt.close(fig)
# output
print('conservation of the mass:')
print('mass min:', round(min(c_pp),3), '(delta', int(100*(np.mean(c_pp)-min(c_pp))/np.mean(c_pp)),'% of mean value)')
print('mass max:', round(max(c_pp),3), '(delta', int(100*(max(c_pp)-np.mean(c_pp))/np.mean(c_pp)),'% of mean value)')
# plot time-etas
fig, ax1 = plt.subplots(1,1,figsize=(16,9))
for i_grain in range(dict_user['n_eta']):
ax1.plot(time_pp, L_eta_pp[i_grain], linewidth=6)
ax1.set_xlabel('time (-)', fontsize=25)
ax1.set_ylabel('mean grain concentration (-)', fontsize=25)
ax1.tick_params(axis='both', labelsize=20, width=3, length=3)
fig.tight_layout()
fig.savefig('output/evol_time_etas.png')
plt.close(fig)
# extract time from the iterations saved
L_time_extracted = []
for ite in dict_user['L_ite_saved']:
L_time_extracted.append(time_pp[ite])
# save
dict_tempo['L_time_extracted'] = L_time_extracted
#-------------------------------------------------------------------------------
def ReadPVTU(dict_user, dict_tempo, filename):
'''
Read the PVTU file generated with Moose.
'''
# read the .pvtu file
dataset = pv.read(filename)
# extract the points
L_points = dataset.points
# extract the concentration
L_c = dataset['c']
# extract the etas
L_L_eta = []
for i_grain in range(dict_user['n_eta']):
L_L_eta.append(dataset['eta'+str(i_grain)])
# save
dict_tempo['L_points'] = L_points
dict_tempo['L_c'] = L_c
dict_tempo['L_L_eta'] = L_L_eta
#-------------------------------------------------------------------------------
def ComputeNeck(dict_tempo):
'''
Compute the neck area.
Defined as the integral of the function eta_i*eta_j.
'''
# initialization
M_Neck = np.zeros((len(dict_tempo['L_L_eta']), len(dict_tempo['L_L_eta'])))
# iterate on the pairs
for i_grain in range(len(dict_tempo['L_L_eta'])-1):
for j_grain in range(i_grain+1,len(dict_tempo['L_L_eta'])):
L_eta_i_j = np.array(dict_tempo['L_L_eta'][i_grain])*np.array(dict_tempo['L_L_eta'][j_grain])
M_Neck[i_grain, j_grain] = np.mean(L_eta_i_j)
# save
dict_tempo['L_M_Neck'].append(M_Neck)
#-------------------------------------------------------------------------------
def PlotNeck(dict_tempo):
'''
Plot the neck area.
Defined as the integral of the function eta_i*eta_j.
'''
# open figure
fig, (ax1) = plt.subplots(1,1,figsize=(16,9))
# iterate on the pairs
for i_grain in range(len(dict_tempo['L_L_eta'])-1):
for j_grain in range(i_grain+1,len(dict_tempo['L_L_eta'])):
L_Neck_i_j = []
# extract the pair with time
for ite in range(len(dict_tempo['L_M_Neck'])):
L_Neck_i_j.append(dict_tempo['L_M_Neck'][ite][i_grain, j_grain])
# plot
ax1.plot(dict_tempo['L_time_extracted'], L_Neck_i_j, linewidth=6)
# close figure
ax1.set_xlabel('time (-)', fontsize=25)
ax1.set_ylabel('neck area (-)', fontsize=25)
ax1.tick_params(axis='both', labelsize=20, width=3, length=3)
fig.tight_layout()
fig.savefig('output/evol_time_neck.png')
plt.close(fig)
#-------------------------------------------------------------------------------
def ComputeFreeSurface(dict_tempo):
'''
Compute the free surface area.
Defined as the integral of the function c_int (=1 for c in [0.45, 0.55]).
'''
# pp data
L_c_int = []
for c in dict_tempo['L_c']:
if 0.45 <= c and c <= 0.55:
L_c_int.append(1)
else :
L_c_int.append(0)
# save
dict_tempo['L_freeSurface'].append(np.mean(L_c_int))
#-------------------------------------------------------------------------------
def PlotFreeSurface(dict_tempo):
'''
Plot the free surface area.
Defined as the integral of the function c_int (=1 for c in [0.45, 0.55]).
'''
# open figure
fig, (ax1) = plt.subplots(1,1,figsize=(16,9))
ax1.plot(dict_tempo['L_time_extracted'], dict_tempo['L_freeSurface'], linewidth=6)
ax1.set_xlabel('time (-)', fontsize=25)
ax1.set_ylabel('free surface (-)', fontsize=25)
ax1.tick_params(axis='both', labelsize=20, width=3, length=3)
fig.tight_layout()
fig.savefig('output/evol_time_freesurface.png')
plt.close(fig)
#-------------------------------------------------------------------------------
def RebuildMap(dict_user, dict_tempo):
'''
Rebuild the map from the output of the pyvista.
'''
# initialization
M_void = np.zeros((len(dict_user['L_y']), len(dict_user['L_x'])))
M_solid = np.zeros((len(dict_user['L_y']), len(dict_user['L_x'])))
# the map is not know
if dict_tempo['map'] == None:
# init map
map = []
# iterate on the points
for i_point in range(len(dict_tempo['L_points'])):
# search node in the mesh
L_search = list(abs(np.array(dict_user['L_x']-list(dict_tempo['L_points'][i_point])[0])))
i_x = L_search.index(min(L_search))
L_search = list(abs(np.array(dict_user['L_y']-list(dict_tempo['L_points'][i_point])[1])))
i_y = L_search.index(min(L_search))
# save map
map.append([i_x, i_y])
# rebuild maps
if dict_tempo['L_c'][i_point] < 0.5:
M_void[-1-i_y, i_x] = 1
else:
M_solid[-1-i_y, i_x] = 1
# save map
dict_tempo['map'] = map
# the map is know
else:
# iterate on the points
for i_point in range(len(dict_tempo['L_points'])):
# read the map
i_x = dict_tempo['map'][i_point][0]
i_y = dict_tempo['map'][i_point][1]
# rebuild maps
if dict_tempo['L_c'][i_point] < 0.5:
M_void[-1-i_y, i_x] = 1
else:
M_solid[-1-i_y, i_x] = 1
# extract maps (exclude void on the sides)
i_x_min = dict_tempo['zoneInterest'][0]
i_x_max = dict_tempo['zoneInterest'][1]
i_y_min = dict_tempo['zoneInterest'][2]
i_y_max = dict_tempo['zoneInterest'][3]
# save
dict_tempo['M_void'] = M_void.copy()
dict_tempo['M_void_extracted'] = M_void.copy()[i_y_min: i_y_max+1, i_x_min: i_x_max+1]
dict_tempo['M_solid'] = M_solid.copy()
dict_tempo['M_solid_extracted'] = M_solid.copy()[i_y_min: i_y_max+1, i_x_min: i_x_max+1]
# save ic
if dict_tempo['ic_flag']:
dict_tempo['M_solid_ic'] = M_solid.copy()
#-------------------------------------------------------------------------------
def RebuildMap_ZoneInterest(dict_user, dict_tempo):
'''
Rebuild the map from the output of the pyvista. And determine the zone of interest for the porosity estimation.
'''
# initialization
M_solid = np.zeros((len(dict_user['L_y']), len(dict_user['L_x'])))
# the map is not know
if dict_tempo['map'] == None:
# init map
map = []
# iterate on the points
for i_point in range(len(dict_tempo['L_points'])):
# search node in the mesh
L_search = list(abs(np.array(dict_user['L_x']-list(dict_tempo['L_points'][i_point])[0])))
i_x = L_search.index(min(L_search))
L_search = list(abs(np.array(dict_user['L_y']-list(dict_tempo['L_points'][i_point])[1])))
i_y = L_search.index(min(L_search))
# save map
map.append([i_x, i_y])
# rebuild maps
if dict_tempo['L_c'][i_point] > 0.5:
M_solid[-1-i_y, i_x] = 1
# save map
dict_tempo['map'] = map
# the map is know
else:
# iterate on the points
for i_point in range(len(dict_tempo['L_points'])):
# read the map
i_x = dict_tempo['map'][i_point][0]
i_y = dict_tempo['map'][i_point][1]
# rebuild maps
if dict_tempo['L_c'][i_point] > 0.5:
M_solid[-1-i_y, i_x] = 1
# extract maps (exclude void on the sides)
# find i_x_min
#i_x_min = 0
#while np.max(M_solid[:, i_x_min]) == 0:
# i_x_min = i_x_min + 1
i_x_min = int(0.25*M_solid.shape[0])
# find i_x_max
#i_x_max = M_solid.shape[1]-1
#while np.max(M_solid[:, i_x_max]) == 0:
# i_x_max = i_x_max - 1
i_x_max = int(0.75*M_solid.shape[0])
# find i_y_min
#i_y_min = 0
#while np.max(M_solid[i_y_min, :]) == 0:
# i_y_min = i_y_min + 1
i_y_min = int(0.25*M_solid.shape[1])
# find i_y_max
#i_y_max = M_solid.shape[0]-1
#while np.max(M_solid[i_y_max, :]) == 0:
# i_y_max = i_y_max - 1
i_y_max = int(0.75*M_solid.shape[1])
# save
dict_tempo['zoneInterest'] = [i_x_min, i_x_max, i_y_min, i_y_max]
#-------------------------------------------------------------------------------
def PlotMap(dict_user, dict_tempo):
'''
plot the current configuration.
'''
# Plot maps
fig, (ax1, ax2) = plt.subplots(1,2,figsize=(16,9))
# parameters
ax1.imshow(dict_tempo['M_solid_ic'], interpolation = 'nearest', extent=(dict_user['L_x'][0],dict_user['L_x'][-1],dict_user['L_y'][0],dict_user['L_x'][-1]))
ax1.set_title('ic', fontsize=30)
ax2.imshow(dict_tempo['M_solid'], interpolation = 'nearest', extent=(dict_user['L_x'][0],dict_user['L_x'][-1],dict_user['L_y'][0],dict_user['L_x'][-1]))
ax2.set_title('final', fontsize=30)
fig.tight_layout()
fig.savefig('output/map_c.png')
plt.close(fig)
# Plot delta
fig, ax1 = plt.subplots(1,1,figsize=(16,9))
# parameters
cax = ax1.imshow(dict_tempo['M_solid']-dict_tempo['M_solid_ic'], interpolation = 'nearest', extent=(dict_user['L_x'][0],dict_user['L_x'][-1],dict_user['L_y'][0],dict_user['L_x'][-1]), cmap='bwr')
cbar = fig.colorbar(cax, ticks=[1, -1])
cbar.ax.set_yticklabels(['precipitation', 'dissolution'])
cbar.ax.tick_params(labelsize=20)
ax1.set_title('final-ic', fontsize=30)
fig.tight_layout()
fig.savefig('output/map_deltac.png')
plt.close(fig)
#-------------------------------------------------------------------------------
def ComputeMorphometers(dict_tempo):
'''
Compute the morphometers.
see Guével, 2022
'''
# M0 porosity
M0 = porespy.metrics.porosity(dict_tempo['M_void_extracted'])
# M1 perimeter
M1 = skimage.measure.perimeter(dict_tempo['M_solid'])
# M2 grain size
# this morphometer requires more lines
# an algorithm is called to determine the size of the grains
sizes = porespy.filters.local_thickness(dict_tempo['M_solid'])
# then a size distribution is called
data = porespy.metrics.pore_size_distribution(sizes, log=False, bins=20)
# finally the mean (weighted by the probability) is computed
M2 = 0
counter = 0
for i_bin in range(len(data.bin_centers)):
M2 = M2 + data.pdf[i_bin]*data.bin_centers[i_bin]
counter = counter + data.pdf[i_bin]
M2 = M2 / counter
# M3 Euler
M3 = skimage.measure.euler_number(dict_tempo['M_solid'])
# save
dict_tempo['L_M0'].append(M0)
dict_tempo['L_M1'].append(M1)
dict_tempo['L_M2'].append(M2)
dict_tempo['L_M3'].append(M3)
#-------------------------------------------------------------------------------
def PlotMorphometers(dict_tempo):
'''
Plot the morphometers.
see Guevel, 2022.
'''
# open figure
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2,2,figsize=(2*16,2*9))
# M0
ax1.plot(dict_tempo['L_time_extracted'], dict_tempo['L_M0'], linewidth=6)
ax1.set_xlabel('time (-)', fontsize=25)
ax1.set_ylabel('M0 porosity (-)', fontsize=25)
ax1.tick_params(axis='both', labelsize=20, width=3, length=3)
# M1
ax2.plot(dict_tempo['L_time_extracted'], dict_tempo['L_M1'], linewidth=6)
ax2.set_xlabel('time (-)', fontsize=25)
ax2.set_ylabel('M1 perimeter (-)', fontsize=25)
ax2.tick_params(axis='both', labelsize=20, width=3, length=3)
# M2
ax3.plot(dict_tempo['L_time_extracted'], dict_tempo['L_M2'], linewidth=6)
ax3.set_xlabel('time (-)', fontsize=25)
ax3.set_ylabel('M2 grain size (-)', fontsize=25)
ax3.tick_params(axis='both', labelsize=20, width=3, length=3)
# M3
ax4.plot(dict_tempo['L_time_extracted'], dict_tempo['L_M3'], linewidth=6)
ax4.set_xlabel('time (-)', fontsize=25)
ax4.set_ylabel('M3 euler (-)', fontsize=25)
ax4.tick_params(axis='both', labelsize=20, width=3, length=3)
# close
fig.tight_layout()
fig.savefig('output/evol_time_morphometers.png')
plt.close(fig)
#-------------------------------------------------------------------------------
# MAIN code
#-------------------------------------------------------------------------------
if __name__ == '__main__':
# load dict_user
with open('output/dict_user', 'rb') as handle:
dict_user = pickle.load(handle)
# call pp function
pp(dict_user)
Functions
def pp()-
Main function for the post-processing.
Expand source code
def pp(dict_user): ''' Main function for the post-processing. ''' # compute performances tic = time.perf_counter() # initialize the dict dict_tempo = { 'L_M_Neck': [], 'L_freeSurface': [], 'L_M0': [], 'L_M1': [], 'L_M2': [], 'L_M3': [], 'map': None } # read and plot the .csv data. ReadCSV(dict_user, dict_tempo) print('\nread pvtu') # determine the zone of interest for the porosity # a box is generated from the lastest configuration (more dense) # read the .pvtu ReadPVTU(dict_user, dict_tempo, 'output/vtk/PF_Sintering_other_'+dict_user['last_j_str']+'.pvtu') # compute the zone of interest RebuildMap_ZoneInterest(dict_user, dict_tempo) # iterate on the .pvtu files for i in range(dict_user['last_j']+1): # flag the initial map (for plot) if i == 0 : dict_tempo['ic_flag'] = True else: dict_tempo['ic_flag'] = False # read the .pvtu ReadPVTU(dict_user, dict_tempo, 'output/vtk/PF_Sintering_other_'+index_to_str(i)+'.pvtu') # Biswas, 2018 # compute the neck area ComputeNeck(dict_tempo) # compute the free surface area ComputeFreeSurface(dict_tempo) # Guevel, 2022 RebuildMap(dict_user, dict_tempo) ComputeMorphometers(dict_tempo) # plot final map PlotMap(dict_user, dict_tempo) # Biswas, 2018 # plot the neck area PlotNeck(dict_tempo) # plot the free surface area PlotFreeSurface(dict_tempo) # Guevel, 2022 PlotMorphometers(dict_tempo) # compute performances tac = time.perf_counter() hours = (tac-tic)//(60*60) minutes = (tac-tic - hours*60*60)//(60) seconds = int(tac-tic - hours*60*60 - minutes*60) print("\nPost-processing time : "+str(hours)+" hours "+str(minutes)+" minutes "+str(seconds)+" seconds") print('Post-processing ends') def ReadCSV()-
Read the csv file generated with Moose (made by postprocessors).
Expand source code
def ReadCSV(dict_user, dict_tempo): ''' Read the csv file generated with Moose (made by postprocessors). ''' print('\nread csv') # read file f = open('output/PF_Sintering_csv.csv', "r") lines = f.readlines() f.close() # init data time_pp = [] c_pp = [] L_eta_pp = [] for i_grain in range(dict_user['n_eta']): L_eta_pp.append([]) # iterate on lines for line in lines[1:]: line = line.replace("\n", "") data = line.split(',') # read data time_pp.append(float(data[0])) c_pp.append(float(data[1])) for i_grain in range(dict_user['n_eta']): L_eta_pp[i_grain].append(float(data[2+i_grain])) # plot time-mass fig, ax1 = plt.subplots(1,1,figsize=(16,9)) ax1.plot(time_pp, c_pp, linewidth=6) ax1.set_xlabel('time (-)', fontsize=25) ax1.set_ylabel('mean mass concentration (-)', fontsize=25) ax1.tick_params(axis='both', labelsize=20, width=3, length=3) fig.tight_layout() fig.savefig('output/evol_time_mass.png') plt.close(fig) # output print('conservation of the mass:') print('mass min:', round(min(c_pp),3), '(delta', int(100*(np.mean(c_pp)-min(c_pp))/np.mean(c_pp)),'% of mean value)') print('mass max:', round(max(c_pp),3), '(delta', int(100*(max(c_pp)-np.mean(c_pp))/np.mean(c_pp)),'% of mean value)') # plot time-etas fig, ax1 = plt.subplots(1,1,figsize=(16,9)) for i_grain in range(dict_user['n_eta']): ax1.plot(time_pp, L_eta_pp[i_grain], linewidth=6) ax1.set_xlabel('time (-)', fontsize=25) ax1.set_ylabel('mean grain concentration (-)', fontsize=25) ax1.tick_params(axis='both', labelsize=20, width=3, length=3) fig.tight_layout() fig.savefig('output/evol_time_etas.png') plt.close(fig) # extract time from the iterations saved L_time_extracted = [] for ite in dict_user['L_ite_saved']: L_time_extracted.append(time_pp[ite]) # save dict_tempo['L_time_extracted'] = L_time_extracted def ReadPVTU()-
Read the PVTU file generated with Moose.
Expand source code
def ReadPVTU(dict_user, dict_tempo, filename): ''' Read the PVTU file generated with Moose. ''' # read the .pvtu file dataset = pv.read(filename) # extract the points L_points = dataset.points # extract the concentration L_c = dataset['c'] # extract the etas L_L_eta = [] for i_grain in range(dict_user['n_eta']): L_L_eta.append(dataset['eta'+str(i_grain)]) # save dict_tempo['L_points'] = L_points dict_tempo['L_c'] = L_c dict_tempo['L_L_eta'] = L_L_eta def ComputeNeck()-
Compute the neck area.
Expand source code
def ComputeNeck(dict_tempo): ''' Compute the neck area. Defined as the integral of the function eta_i*eta_j. ''' # initialization M_Neck = np.zeros((len(dict_tempo['L_L_eta']), len(dict_tempo['L_L_eta']))) # iterate on the pairs for i_grain in range(len(dict_tempo['L_L_eta'])-1): for j_grain in range(i_grain+1,len(dict_tempo['L_L_eta'])): L_eta_i_j = np.array(dict_tempo['L_L_eta'][i_grain])*np.array(dict_tempo['L_L_eta'][j_grain]) M_Neck[i_grain, j_grain] = np.mean(L_eta_i_j) # save dict_tempo['L_M_Neck'].append(M_Neck) def PlotNeck()-
Plot the neck area.
Expand source code
def PlotNeck(dict_tempo): ''' Plot the neck area. Defined as the integral of the function eta_i*eta_j. ''' # open figure fig, (ax1) = plt.subplots(1,1,figsize=(16,9)) # iterate on the pairs for i_grain in range(len(dict_tempo['L_L_eta'])-1): for j_grain in range(i_grain+1,len(dict_tempo['L_L_eta'])): L_Neck_i_j = [] # extract the pair with time for ite in range(len(dict_tempo['L_M_Neck'])): L_Neck_i_j.append(dict_tempo['L_M_Neck'][ite][i_grain, j_grain]) # plot ax1.plot(dict_tempo['L_time_extracted'], L_Neck_i_j, linewidth=6) # close figure ax1.set_xlabel('time (-)', fontsize=25) ax1.set_ylabel('neck area (-)', fontsize=25) ax1.tick_params(axis='both', labelsize=20, width=3, length=3) fig.tight_layout() fig.savefig('output/evol_time_neck.png') plt.close(fig) def ComputeFreeSurface()-
Compute the free surface area.
Expand source code
def ComputeFreeSurface(dict_tempo): ''' Compute the free surface area. Defined as the integral of the function c_int (=1 for c in [0.45, 0.55]). ''' # pp data L_c_int = [] for c in dict_tempo['L_c']: if 0.45 <= c and c <= 0.55: L_c_int.append(1) else : L_c_int.append(0) # save dict_tempo['L_freeSurface'].append(np.mean(L_c_int)) def PlotFreeSurface()-
Plot the free surface area.
Expand source code
def PlotFreeSurface(dict_tempo): ''' Plot the free surface area. Defined as the integral of the function c_int (=1 for c in [0.45, 0.55]). ''' # open figure fig, (ax1) = plt.subplots(1,1,figsize=(16,9)) ax1.plot(dict_tempo['L_time_extracted'], dict_tempo['L_freeSurface'], linewidth=6) ax1.set_xlabel('time (-)', fontsize=25) ax1.set_ylabel('free surface (-)', fontsize=25) ax1.tick_params(axis='both', labelsize=20, width=3, length=3) fig.tight_layout() fig.savefig('output/evol_time_freesurface.png') plt.close(fig) def RebuildMap()-
Rebuild the map from the output of the pyvista.
Expand source code
def RebuildMap(dict_user, dict_tempo): ''' Rebuild the map from the output of the pyvista. ''' # initialization M_void = np.zeros((len(dict_user['L_y']), len(dict_user['L_x']))) M_solid = np.zeros((len(dict_user['L_y']), len(dict_user['L_x']))) # the map is not know if dict_tempo['map'] == None: # init map map = [] # iterate on the points for i_point in range(len(dict_tempo['L_points'])): # search node in the mesh L_search = list(abs(np.array(dict_user['L_x']-list(dict_tempo['L_points'][i_point])[0]))) i_x = L_search.index(min(L_search)) L_search = list(abs(np.array(dict_user['L_y']-list(dict_tempo['L_points'][i_point])[1]))) i_y = L_search.index(min(L_search)) # save map map.append([i_x, i_y]) # rebuild maps if dict_tempo['L_c'][i_point] < 0.5: M_void[-1-i_y, i_x] = 1 else: M_solid[-1-i_y, i_x] = 1 # save map dict_tempo['map'] = map # the map is know else: # iterate on the points for i_point in range(len(dict_tempo['L_points'])): # read the map i_x = dict_tempo['map'][i_point][0] i_y = dict_tempo['map'][i_point][1] # rebuild maps if dict_tempo['L_c'][i_point] < 0.5: M_void[-1-i_y, i_x] = 1 else: M_solid[-1-i_y, i_x] = 1 # extract maps (exclude void on the sides) i_x_min = dict_tempo['zoneInterest'][0] i_x_max = dict_tempo['zoneInterest'][1] i_y_min = dict_tempo['zoneInterest'][2] i_y_max = dict_tempo['zoneInterest'][3] # save dict_tempo['M_void'] = M_void.copy() dict_tempo['M_void_extracted'] = M_void.copy()[i_y_min: i_y_max+1, i_x_min: i_x_max+1] dict_tempo['M_solid'] = M_solid.copy() dict_tempo['M_solid_extracted'] = M_solid.copy()[i_y_min: i_y_max+1, i_x_min: i_x_max+1] # save ic if dict_tempo['ic_flag']: dict_tempo['M_solid_ic'] = M_solid.copy() def RebuildMap_ZoneInterest()-
Rebuild the map from the output of the pyvista. And determine the zone of interest for the porosity estimation.
Expand source code
def RebuildMap_ZoneInterest(dict_user, dict_tempo): ''' Rebuild the map from the output of the pyvista. And determine the zone of interest for the porosity estimation. ''' # initialization M_solid = np.zeros((len(dict_user['L_y']), len(dict_user['L_x']))) # the map is not know if dict_tempo['map'] == None: # init map map = [] # iterate on the points for i_point in range(len(dict_tempo['L_points'])): # search node in the mesh L_search = list(abs(np.array(dict_user['L_x']-list(dict_tempo['L_points'][i_point])[0]))) i_x = L_search.index(min(L_search)) L_search = list(abs(np.array(dict_user['L_y']-list(dict_tempo['L_points'][i_point])[1]))) i_y = L_search.index(min(L_search)) # save map map.append([i_x, i_y]) # rebuild maps if dict_tempo['L_c'][i_point] > 0.5: M_solid[-1-i_y, i_x] = 1 # save map dict_tempo['map'] = map # the map is know else: # iterate on the points for i_point in range(len(dict_tempo['L_points'])): # read the map i_x = dict_tempo['map'][i_point][0] i_y = dict_tempo['map'][i_point][1] # rebuild maps if dict_tempo['L_c'][i_point] > 0.5: M_solid[-1-i_y, i_x] = 1 # extract maps (exclude void on the sides) # find i_x_min #i_x_min = 0 #while np.max(M_solid[:, i_x_min]) == 0: # i_x_min = i_x_min + 1 i_x_min = int(0.25*M_solid.shape[0]) # find i_x_max #i_x_max = M_solid.shape[1]-1 #while np.max(M_solid[:, i_x_max]) == 0: # i_x_max = i_x_max - 1 i_x_max = int(0.75*M_solid.shape[0]) # find i_y_min #i_y_min = 0 #while np.max(M_solid[i_y_min, :]) == 0: # i_y_min = i_y_min + 1 i_y_min = int(0.25*M_solid.shape[1]) # find i_y_max #i_y_max = M_solid.shape[0]-1 #while np.max(M_solid[i_y_max, :]) == 0: # i_y_max = i_y_max - 1 i_y_max = int(0.75*M_solid.shape[1]) # save dict_tempo['zoneInterest'] = [i_x_min, i_x_max, i_y_min, i_y_max] def PlotMap()-
plot the current configuration.
Expand source code
def PlotMap(dict_user, dict_tempo): ''' plot the current configuration. ''' # Plot maps fig, (ax1, ax2) = plt.subplots(1,2,figsize=(16,9)) # parameters ax1.imshow(dict_tempo['M_solid_ic'], interpolation = 'nearest', extent=(dict_user['L_x'][0],dict_user['L_x'][-1],dict_user['L_y'][0],dict_user['L_x'][-1])) ax1.set_title('ic', fontsize=30) ax2.imshow(dict_tempo['M_solid'], interpolation = 'nearest', extent=(dict_user['L_x'][0],dict_user['L_x'][-1],dict_user['L_y'][0],dict_user['L_x'][-1])) ax2.set_title('final', fontsize=30) fig.tight_layout() fig.savefig('output/map_c.png') plt.close(fig) # Plot delta fig, ax1 = plt.subplots(1,1,figsize=(16,9)) # parameters cax = ax1.imshow(dict_tempo['M_solid']-dict_tempo['M_solid_ic'], interpolation = 'nearest', extent=(dict_user['L_x'][0],dict_user['L_x'][-1],dict_user['L_y'][0],dict_user['L_x'][-1]), cmap='bwr') cbar = fig.colorbar(cax, ticks=[1, -1]) cbar.ax.set_yticklabels(['precipitation', 'dissolution']) cbar.ax.tick_params(labelsize=20) ax1.set_title('final-ic', fontsize=30) fig.tight_layout() fig.savefig('output/map_deltac.png') plt.close(fig) def ComputeMorphometers()-
Compute the morphometers.
Expand source code
def ComputeMorphometers(dict_tempo): ''' Compute the morphometers. see Guével, 2022 ''' # M0 porosity M0 = porespy.metrics.porosity(dict_tempo['M_void_extracted']) # M1 perimeter M1 = skimage.measure.perimeter(dict_tempo['M_solid']) # M2 grain size # this morphometer requires more lines # an algorithm is called to determine the size of the grains sizes = porespy.filters.local_thickness(dict_tempo['M_solid']) # then a size distribution is called data = porespy.metrics.pore_size_distribution(sizes, log=False, bins=20) # finally the mean (weighted by the probability) is computed M2 = 0 counter = 0 for i_bin in range(len(data.bin_centers)): M2 = M2 + data.pdf[i_bin]*data.bin_centers[i_bin] counter = counter + data.pdf[i_bin] M2 = M2 / counter # M3 Euler M3 = skimage.measure.euler_number(dict_tempo['M_solid']) # save dict_tempo['L_M0'].append(M0) dict_tempo['L_M1'].append(M1) dict_tempo['L_M2'].append(M2) dict_tempo['L_M3'].append(M3) def PlotMorphometers()-
Plot the morphometers.
Expand source code
def PlotMorphometers(dict_tempo): ''' Plot the morphometers. see Guevel, 2022. ''' # open figure fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2,2,figsize=(2*16,2*9)) # M0 ax1.plot(dict_tempo['L_time_extracted'], dict_tempo['L_M0'], linewidth=6) ax1.set_xlabel('time (-)', fontsize=25) ax1.set_ylabel('M0 porosity (-)', fontsize=25) ax1.tick_params(axis='both', labelsize=20, width=3, length=3) # M1 ax2.plot(dict_tempo['L_time_extracted'], dict_tempo['L_M1'], linewidth=6) ax2.set_xlabel('time (-)', fontsize=25) ax2.set_ylabel('M1 perimeter (-)', fontsize=25) ax2.tick_params(axis='both', labelsize=20, width=3, length=3) # M2 ax3.plot(dict_tempo['L_time_extracted'], dict_tempo['L_M2'], linewidth=6) ax3.set_xlabel('time (-)', fontsize=25) ax3.set_ylabel('M2 grain size (-)', fontsize=25) ax3.tick_params(axis='both', labelsize=20, width=3, length=3) # M3 ax4.plot(dict_tempo['L_time_extracted'], dict_tempo['L_M3'], linewidth=6) ax4.set_xlabel('time (-)', fontsize=25) ax4.set_ylabel('M3 euler (-)', fontsize=25) ax4.tick_params(axis='both', labelsize=20, width=3, length=3) # close fig.tight_layout() fig.savefig('output/evol_time_morphometers.png') plt.close(fig)