Replies: 2 comments
-
There are probably 1000 lines of code here. I definitely do not have the time to look at this for you to find a nondescript bug, sorry. |
Beta Was this translation helpful? Give feedback.
0 replies
-
Where 4698 pores comes from? I just find a 4608 with |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Dear professor,
this is my code in which I exctracted a network from porespy and here there the properties of my network. Afterward there are also the properties of a network extracted from the same tomographic image but with a very different number of values. For example it's so weird that in my model there just 4698 disconnected pore instead in the other exctraction there are much much more (63396).
Can you have a look at it?
Thanks a lot for you attention and time.
`import openpnm as op
import numpy as np
import matplotlib.pyplot as plt
import porespy as ps
import pickle as pk
import tifffile
import imageio
import os
import array as arr
import scipy.stats
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
from scipy.stats import norm
import pandas as pd
import math
from statistics import mean
import tqdm
op.visualization.set_mpl_style()
#NETWORK from PORESPY
set tqdm to current version
ps.settings.tqdm = {} # Just set all the settings to the default values
np.set_printoptions(precision=4) # post-decimal digits
np.random.seed(10)
imTot = tifffile.imread("HB-08-03-b2-pre-pores.tif")
path = ''
file_format = '.tif'
file_name = 'HB-08-03-b2-pre-pores'
file = file_name + file_format
fetch_file = os.path.join(path, file)
#im = ~numpy.array(imageio.mimread(fetch_file), dtype=bool)
if the image is bigger than 256MB, set memtest to a higher value:
im = np.array(imageio.mimread(fetch_file, memtest = 500000000), dtype = bool)
b=2
resolution = b*26e-6 # in m
snow = pk.load(open('HB-08-03-b2-pre-pores.dat', 'rb'))
pn= op.io.network_from_porespy(snow.network)
pn1= op.io.network_from_porespy(snow.network) #CLONE NETWORK
print(pn)
#SHOWING THE NUMBER OF THROATS, PORES AND CONNECTED PORES OF THE EXTRACTED NETWORK:
n_thorats=(op.network.Network.num_throats(pn))
print('Number of throats:')
print(n_thorats,'\n')
n_pores=op.network.Network.num_pores(pn)
print('number of pores')
print(n_pores,'\n')
throat_indices=pn.to_indices(pn['throat.all'])
n_conn_pores=pn.find_connected_pores(throats=throat_indices, flatten='false', mode='or')
print('number of connected pores')
print(len(n_conn_pores))
#MEANS OF THE FEATURES OF THE NETWORK:
#PORES:
print('\n','\n','\n','\n','before')
print('\n','Pores volume','\n')
print(mean(pn['pore.volume']))
print('\n','Pores surface_area','\n')
print(mean(pn['pore.surface_area']))
print('\n','Pores region_volume','\n')
print(mean(pn['pore.region_volume']))
print('\n','Pores equivalent_diameter','\n')
print(mean(pn['pore.equivalent_diameter']))
print('\n','Pores inscribed_diameter','\n')
print(mean(pn['pore.inscribed_diameter']))
print('\n','Pores extended_diameter','\n')
print(mean(pn['pore.extended_diameter']))
#THROATS:
print('\n','Throat inscribed diameter','\n')
print(mean(pn['throat.inscribed_diameter']))
print('\n','Throat total_length','\n')
print(mean(pn['throat.total_length']))
print('\n','Throat perimeter','\n')
print(mean(pn['throat.perimeter']))
print('\n','Throat cross_sectional_Area','\n')
print(mean(pn['throat.cross_sectional_area']))
print('\n','Throat equivalent_diamter','\n')
print(mean(pn['throat.equivalent_diameter']))
#ASSIGNING OF A GEOMETRY MODEL TO THE NETWORK
geo = op.models.collections.geometry.spheres_and_cylinders #spheres and cylinders model geometry assigned
pn.add_model_collection(geo)
pn.regenerate_models()
print(pn.models) #it shows the properties of the model that I am applying to my network
geo1 = op.models.collections.geometry.spheres_and_cylinders #spheres and cylinders model geometry assigned
pn1.add_model_collection(geo1)
pn1.regenerate_models()
print(pn1.models)
#DEFINING THE 6 SURFACES OF THE OBJECT:
inlet=pn.pores('xmin') #inlet area of the fluid
outlet=pn.pores('xmax') #outlet area of the fluid
top=pn.pores('zmax') #top of the object
bottom=pn.pores('zmin') # bottom of the object
back=pn.pores('ymax') #back of the object
front=pn.pores('ymin') #front of the object
#CHECKING IF THE NETWORK IS PERCOLATING: it gives TRUE, meaning it's percolating, so actually the fluid can go from inlet to outlet surface
print(op.topotools.ispercolating(pn, inlet, outlet))
#CHECKING IF THE NETWORK IS FULLY CONNECTED: it gives FALSE, meaning some pores are not connected: disconnected
print(op.topotools.is_fully_connected(pn))
#CHECKING THE HEALTH OF THE SYSTEM: it gives the indices of the disconnected and isolated pores
h = op.utils.check_network_health(pn)
print(h)
#GRAPHS (istograms) of the NETOWRK'S FEATURES:
#THROATS:
#THROAT DIAMETER
print(mean(pn['throat.diameter']))
plt.xlabel("Throat diameter [m] ")
counts, bins = np.histogram(pn['throat.diameter'], bins=500)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
#THROAT LENGHT
plt.xlabel("Throat length [m] ")
counts, bins = np.histogram(pn['throat.length'],bins=500)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
#THROAT VOLUME
plt.xlabel("throat volume [m^3] ")
counts, bins = np.histogram(pn['throat.volume'],bins=250)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
#PORES:
#PORE DIAMETER
count=0
for i in range(len(pn['pore.all'])):
if pn['pore.volume'][i]==np.inf:
count=count+1
inf_in_pore_volume=count
count=0
pn['pore.volume'][np.where(pn['pore.volume']==np.inf)[0]]=0.0 #There are some value of pore volume that are 'inf' value, maybe these are biases, I equalled to zero all these values
plt.xlabel("Pore volume [m^3]")
counts, bins = np.histogram(pn['pore.volume'], bins=2000)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
plt.xlim(-0.000000000005, 0.00000000003)
#PORE VOLUME
count=0
for i in range(len(pn['pore.all'])):
if pn['pore.diameter'][i]==np.inf:
count=count+1
inf_in_pore_diamter=count
count=0
pn['pore.diameter'][np.where(pn['pore.diameter']==np.inf)[0]]=0.0 #There are some value of pore diameter that are 'inf' value, maybe these are biases, I equalled to zero all these values
plt.xlabel("Pore diameter [m]")
counts, bins = np.histogram(pn['pore.diameter'], bins=100)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
plt.xlim(-0.00001, 0.0007)
#PORE COORDINATION NUMBER:
count=0
for i in range(len(pn['pore.all'])):
if pn['pore.coordination_number'][i]==np.nan:
count=count+1
nan_in_pore_coord_number=count
count=0
#pn['pore.coordination_number'][np.where(pn['pore.coordination_number']==np.nan)[0]]=0.0 #There are some values of pore coordination number that are 'nan' value, maybe these are biases, I equalled to zero all these values
plt.xlabel("Pore coordination number")
counts, bins = np.histogram(pn['pore.coordination_number'], bins=100)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
plt.xlim(0, 21)
print('\n','Mean coordination number','\n')
mean_coor_n=mean(pn['pore.coordination_number'])
print(mean_coor_n)
#PORE SURFACE AREA:
count=0
for i in range(len(pn['pore.all'])):
if pn['pore.surface_area'][i]==np.nan:
count=count+1
nan_in_pore_surface_area=count
count=0
#pn['pore.surface_area'][np.where(pn['pore.surface_area']==np.nan)[0]]=0.0 #There some value of pore surface area that are 'nan' value, maybe these are biases, I equalled to zero all these values
plt.xlabel("Pore surface area [m^2]")
counts, bins = np.histogram(pn['pore.surface_area'], bins=300)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
plt.xlim(0, 0.0000025)
#plt.show()
#CONNECTING PORES:
Pnb=pn.find_neighbor_pores(h['isolated_pores'], mode='or') #This function return an empty array, meaning that it looks for pores near the input one but to whom they are already connected, and because they are isolated it doesn't find anyone
#r=max(pn['throat.length']) #I chose the maximum length of the all throats in the model as a radius parameter for the connection
#r=op.models.network.distance_to_nearest_pore(pn)h['isolated_pores']
#SHOWING HOW MAY DISCONNECTED AND ISOLATED PORES ARE THERE:
h = op.utils.check_network_health(pn)
print('\n', 'Number of disconnected pores: ','\n', len(h['disconnected_pores'])) #4658 disconnected pores of which 3423 isolated pores
print('\n', 'Number of isolated pores: ','\n', len(h['isolated_pores'])) #3423 isolated pores
#CONNECTING PORES:
#Creating properties related to clusters of the network
pn.add_model(propname='pore.cluster_number',
model=op.models.network.cluster_number) #number that identify each cluster, how each cluster is 'named'
pn.add_model(propname='pore.cluster_size',
model=op.models.network.cluster_size) #size of the cluster, the number of the pores that belongs to each cluster (for example cluster_size=3 means the cluster is formed by just 3 connected pores)
cluster_sizes=pn['pore.cluster_size']
cluster_numbers=pn['pore.cluster_number']
max_cluster_size=max(cluster_sizes) #biggest cluster of the pore network
print('\n', 'Max cluster size:', '\n', max_cluster_size)
clusters_isolated=op.topotools.find_isolated_clusters(pn, pn['pore.all'], inlet) #isolated clusters
big_cluster = cluster_sizes == max_cluster_size
Big_cluster=pn.to_indices(big_cluster) #Array composed by the indices of the pores belonging to the bigger cluster
#ISTOGRAM OF ISOLATED AND DISCONNECTED PORES FEATURES:
plt.xlabel("Pore coordination number isolated pores")
counts, bins = np.histogram(pn['pore.coordination_number'][h['isolated_pores']], bins=100)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
plt.xlim(0, 21)
plt.show()
plt.xlabel("Pore coordination number disconnected pores")
counts, bins = np.histogram(pn['pore.coordination_number'][h['disconnected_pores']], bins=100)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
plt.xlim(0, 21)
plt.show()
plt.xlabel("Pore cluster size")
counts, bins = np.histogram(pn['pore.cluster_size'], bins=100)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
plt.xlim(0, 21)
plt.show()
plt.xlabel("Pore cluster size")
counts, bins = np.histogram(clusters_isolated, bins=100)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
plt.xlim(0, 21)
plt.xlabel("Pore diameter[m]")
counts, bins = np.histogram(pn['pore.equivalent_diameter'][h['isolated_pores']], bins=300)
plt.stairs(counts, bins)
plt.hist(bins[:-1], bins, weights=counts)
plt.xlim(0, 0.0000025)
plt.show()
#DELETING THE DISCONNECTED PORES FROM A NETWORK AND EVERYTHING EXCEPT THE DISCONNECTED PORES FROM THE OTHER ONE
h1 = op.utils.check_network_health(pn1)
disconnected_pores=h1['disconnected_pores']
pores_all=pn1.to_indices(pn1['pore.all'])
c = np.setdiff1d(pores_all, disconnected_pores)
op.topotools.trim(network=pn1, pores=c) #Removing everything but not the disconnected pores
op.topotools.trim(network=pn, pores=h['disconnected_pores']) #Removing the disconnected_pores FROM THE network pn
op.io._vtk.project_to_vtk(pn1.project, filename='network_clone')
pores_pn=pn.to_indices(pn['pore.all'])
pores_pn1=pn1.to_indices(pn1['pore.all'])
op.topotools.stitch(pn, pn1, pores_pn, pores_pn1, method='nearest', len_max='inf', label_suffix='', label_stitches='stitched')
new_conns=pn.to_indices(pn['throat.stitched'])
throat_data_sheet = pd.DataFrame({k: pn[k] for k in pn.props(element='throat') if pn[k].ndim == 1})
print(throat_data_sheet)
pn.regenerate_models()
throat_data_sheet = pd.DataFrame({k: pn[k] for k in pn.props(element='throat') if pn[k].ndim == 1})
print(throat_data_sheet)
for i in tqdm.tqdm(range(len(new_conns))):
first_pore=pn['throat.conns'][new_conns[i]][0]
second_pore=pn['throat.conns'][new_conns[i]][1]
squared_dist = np.sum((pn['pore.coords'][first_pore]-pn['pore.coords'][second_pore])**2, axis=0) #calculate the throat.direct_length
dist = np.sqrt(squared_dist)
pn['throat.direct_length'][new_conns[i]]=dist
throat_data_sheet = pd.DataFrame({k: pn[k] for k in pn.props(element='throat') if pn[k].ndim == 1})
print(throat_data_sheet)
#Check to understand if the network is completely connected: it gives TRUE, meaning it is fully connected now
print(op.topotools.is_fully_connected(pn))
#Checking again the HEALTH of the system:
h = op.utils.check_network_health(pn)
print('\n', h)
print('\n','isolated pores',len(h['isolated_pores'])) #0 isolated
print('\n','disconnected pores',len(h['disconnected_pores'])) #0 disconnected
#THESE NEW THROATS NEED SOME PROPERTIES, BECAUSE FOR NOW THEY JUST EXIST WITHOUT ANY SPECIFIED FEATURES
pn.regenerate_models()
throat_data_sheet = pd.DataFrame({k: pn[k] for k in pn.props(element='throat') if pn[k].ndim == 1})
print(throat_data_sheet)
pn['throat.equivalent_diameter'][pn['throat.stitched']]=0.0000084
throat_data_sheet = pd.DataFrame({k: pn[k] for k in pn.props(element='throat') if pn[k].ndim == 1})
print(throat_data_sheet)
pn.regenerate_models()
throat_data_sheet = pd.DataFrame({k: pn[k] for k in pn.props(element='throat') if pn[k].ndim == 1})
print(throat_data_sheet) #I am regenerating the model that now will be applied also to the new connections
pn['throat.equivalent_diameter'][pn['throat.stitched']]=0.0000084
pn['throat.equivalent_diameter'][pn['throat.stitched']]=0.0000084
throat_data_sheet = pd.DataFrame({k: pn[k] for k in pn.props(element='throat') if pn[k].ndim == 1})
print(throat_data_sheet)
geo = op.models.collections.geometry.spheres_and_cylinders #spheres and cylinders model geometry assigned
pn.add_model_collection(geo)
pn.regenerate_models()
#SHOWING THE PROPERTIES VALUES OF PORES AND THROATS:
print('After regenerate_model','\n')
pore_data_sheet = pd.DataFrame({k: pn[k] for k in pn.props(element='pore') if pn[k].ndim == 1})
print(pore_data_sheet)
throat_data_sheet = pd.DataFrame({k: pn[k] for k in pn.props(element='throat') if pn[k].ndim == 1})
print(throat_data_sheet)
print(pn)
#CREATING THE FLUID PHASE THROUGH WHICH THIS SAMPLE IS BEEN TESTED:
synthetic_saline_water = op.phase.Water(network=pn)
synthetic_saline_water['pore.pressure']= 1000000 #1 Mpa
synthetic_saline_water['pore.density']=1025 #[kg/m^3]
synthetic_saline_water['pore.viscosity']=1.020.001 #[Pas]: dynamic viscosity
synthetic_saline_water['throat.viscosity']=1.020.001 #[Pas]: dynamic viscosity
eta_f= 1.020.001 #[Pas]: dynamic viscosity. qI assume same viscosity for pores and throats because it depends from the temperature and on the type of liquid
density_f=synthetic_saline_water['pore.density']
synthetic_saline_water.add_model(propname='throat.hydraulic_conductance', model=op.models.physics.hydraulic_conductance.hagen_poiseuille)
#Assigning MODELS:
#Size factor:
#size_factor=op.models.geometry.hydraulic_size_factors.spheres_and_cylinders
#pn.add_model(propname='hydraulic_size_factors', model=size_factor)
#Hydraulic conductance:
#hagen_poiseuille=op.models.physics.hydraulic_conductance.hagen_poiseuille
#pn.add_model(propname='throat.hydraulic_conductance', model=hagen_poiseuille)
#Re- Defining the 6 surfaces of my object
inlet=pn.pores('xmin') #inlet area of the fluid
outlet=pn.pores('xmax') #outlet area of the fluid
top=pn.pores('zmax') #top of the object
bottom=pn.pores('zmin') # bottom of the object
back=pn.pores('ymax') #back of the object
front=pn.pores('ymin') #front of the object
#Defining boundary condition for pressure at inlet and outlet:
inlet_P=2000000
outlet_P=1000000
#PERFORMING A FLOW SIMULATION THROUGH THE APPLICATION OF THE STOKES ALGORITHM:
flow = op.algorithms.StokesFlow(network=pn, phase=synthetic_saline_water)
flow.set_value_BC(pores=inlet, values=inlet_P)
flow.set_value_BC(pores=outlet, values=outlet_P)
flow.run()
synthetic_saline_water.update(flow.soln)
#Hagen-Poiseuille formula:
#R=#radius of the connecting throat
#deltaP=#delta pressure between two pores
#Length=#distance between the two pores
#Q_f=deltaP3.14R**4/(8eta_fLength)
#SHOWING OF THE PHASE FEATURES:
pore_data_sheet = pd.DataFrame({k: synthetic_saline_water[k] for k in synthetic_saline_water.props(element='pore') if synthetic_saline_water[k].ndim == 1})
print(pore_data_sheet)
throat_data_sheet = pd.DataFrame({k: synthetic_saline_water[k] for k in synthetic_saline_water.props(element='throat') if synthetic_saline_water[k].ndim == 1})
print(throat_data_sheet)
#PLOTTING OF THE PRESSURE GRADIENT ON THE SAMPLE:
#ax = op.visualization.plot_connections(network=pn, color_by=flow.rate(throats=pn.Ts, mode='single'))
#op.visualization.plot_coordinates(network=pn, color_by=flow.x, ax=ax, markersize=100)
#plt.show()
#EVALUATION OF HYDROMECHANICAL PROPERTIES:
#ABSOLUTE PERMEABILITY:
g=9.81 #[m/s^2]
delta_P=1000000 #[Pa]: 1Mpa #inlet-outlet
#Q_f=flow.rate(pores=inlet, mode='group')[0] #cumulative sum of each fluid flow rate which is flowing through the entire sample
#Calculation of Hagen-Poiseuille formula
Q_f=0
Q_={}
flag=0
for i in tqdm.tqdm(range(len(pn['throat.all']))):
pressure=(flow['pore.pressure'][pn['throat.conns'][i][1]])-(flow['pore.pressure'][pn['throat.conns'][i][0]])
if pressure<=0:
pressure_diff=(-1)(pressure)
flag=flag+1
else :
pressure_diff=pressure
radius=(pn['throat.equivalent_diameter'][i]/2)**4
length=pn['throat.direct_length'][i]
print(pressure_diff3.14radius/(8eta_flength))
Q_f=Q_f+(pressure_diff3.14radius/(8eta_flength))
Q_[i]=(pressure_diff3.14radius/(8eta_f*length))
print('Flow rate',Q_f)
print('Mean flow rate',Q_)
#Input of geometrical properties of the sample:
d=0.025 #[m]: 25 mm
A=d2 #[m]
L=0.076 #[m]: 76 mm
#A = (im.shape[1] * im.shape[2]) * resolution2
#L = im.shape[0] * resolution
#Absolute permeability evaluated through the hydraulic conductance and Darcy's law:
k=(Q_fLeta_f)/(A*delta_P)
print('\n','Absolute permability', k)
op.io._vtk.project_to_vtk(pn.project, filename='network3') #Saving the pore network as a vtk file to visualize it on Paraview
plt.show()
'
Network properties that I obtained:
Network properties obtained from another extraction of the same image (that It's the right one and that I want to replicate):
Beta Was this translation helpful? Give feedback.
All reactions