Skip to content

Instantly share code, notes, and snippets.

@ma-sadeghi
Created October 2, 2020 23:18
Show Gist options
  • Save ma-sadeghi/e85a7fdac3a9ecc6afb0300988517e0c to your computer and use it in GitHub Desktop.
Save ma-sadeghi/e85a7fdac3a9ecc6afb0300988517e0c to your computer and use it in GitHub Desktop.
How to handle extra boundary pores added by SNOW extraction method from porespy?
def generate_network(shape, radius, ncyl, phimax, thetamax):
ws = op.Workspace()
ws.clear()
proj = ws.new_project(name='proj1')
im = psp.generators.cylinders(shape=shape, radius=radius, ncylinders=ncyl, phi_max=phimax, theta_max=thetamax)
im = psp.filters.fill_blind_pores(im)
im = psp.filters.trim_floating_solid(im)
# extract network
net = psp.networks.snow(im=im, voxel_size=1e-6)
pn = op.network.GenericNetwork(name='net1', project=proj)
pn.update(net)
op.utils.Workspace.save_workspace(ws, filename='pnm_networks/testws.pnm')
def add_boundary_pores(pn):
op.topotools.add_boundary_pores(pn, pores=pn.pores('top'), offset=[0, 0, max(pn['pore.diameter'])],
apply_label='top_inlet')
op.topotools.add_boundary_pores(pn, pores=pn.pores('bottom'), offset=[0, 0, -max(pn['pore.diameter'])],
apply_label='bottom_inlet')
op.topotools.add_boundary_pores(pn, pores=pn.pores('front'), offset=[0, -max(pn['pore.diameter']), 0],
apply_label='front_inlet')
op.topotools.add_boundary_pores(pn, pores=pn.pores('back'), offset=[0, max(pn['pore.diameter']), 0],
apply_label='back_inlet')
op.topotools.add_boundary_pores(pn, pores=pn.pores('top'), offset=[-max(pn['pore.diameter']), 0, 0],
apply_label='left_inlet')
op.topotools.add_boundary_pores(pn, pores=pn.pores('right'), offset=[max(pn['pore.diameter']), 0, 0],
apply_label='right_inlet')
# make geometry obect for inlet pores
PsB = pn.pores('*inlet')
TsB = pn.find_neighbor_throats(pores=PsB, mode='xor', flatten=True)
geom_b = op.geometry.GenericGeometry(network=pn, pores=PsB, throats=TsB, name='boun1')
# add properties to boundary pores and throats
geom_b['pore.volume'] = 0.0
geom_b['pore.inscribed_diameter'] = max(pn['pore.inscribed_diameter'])
geom_b['pore.diameter'] = max(pn['pore.diameter'])
geom_b['pore.equivalent_diameter'] = max(pn['pore.equivalent_diameter'])
geom_b['pore.extended_diameter'] = max(pn['pore.extended_diameter'])
geom_b['pore.surface_area'] = max(pn['pore.surface_area'])
geom_b['pore.area'] = max(pn['pore.area'])
geom_b['throat.volume'] = 0.0
geom_b['throat.diameter'] = np.nanmax(pn['throat.diameter'])
geom_b['throat.inscribed_diameter'] = max(pn['throat.inscribed_diameter'])
geom_b['throat.area'] = max(pn['throat.area'])
geom_b['throat.perimeter'] = max(pn['throat.perimeter'])
geom_b['throat.equivalent_diameter'] = max(pn['throat.equivalent_diameter'])
geom_b['throat.total_length'] = max(pn['throat.total_length'])
geom_b['throat.length'] = max(pn['throat.length'])
geom_b['throat.direct_length'] = max(pn['throat.direct_length'])
geom_b['throat.conduit_lengths.pore1'] = max(pn['throat.conduit_lengths.pore1'])
geom_b['throat.conduit_lengths.pore2'] = max(pn['throat.conduit_lengths.pore2'])
geom_b['throat.conduit_lengths.throat'] = max(pn['throat.conduit_lengths.throat'])
return geom_b
if __name__ == '__main__':
if not os.path.isfile('pnm_networks/testws.pnm'): # check if a file is present
generate_network([1000, 1000, 250], 5, 200, 90, 90) # if no then generate a network
ws = op.Workspace()
ws.clear()
ws.load_project('pnm_networks/testws.pnm')
pn = ws['proj1']['net1'] # load project
geom = op.geometry.Imported(network=pn, name='geo1')
geomb = add_boundary_pores(pn) # <------------------------------ adds boundary pores to network
dis_pore = pn.check_network_health()
if dis_pore['trim_pores'] is not None:
op.topotools.trim(pn, pores=dis_pore['trim_pores'])
dis_pore = pn.check_network_health()
# phases
air = op.phases.Air(network=pn, name='air')
water = op.phases.Water(network=pn, name='water')
water['pore.contact_angle'] = 110
# physicss
phys_water = op.physics.Standard(network=pn, phase=water, geometry=geom)
phys_air = op.physics.Standard(network=pn, phase=air, geometry=geom)
phys_water_b = op.physics.Standard(network=pn, phase=water, geometry=geomb)
phys_air_b = op.physics.Standard(network=pn, phase=air, geometry=geomb)
# run ordinary percolation
OP1 = op.algorithms.OrdinaryPercolation(network=pn)
OP1.set_inlets(pores=pn.pores('top_inlet'))
OP1.set_outlets(pores=pn.pores('bottom'))
OP1.settings['trapping'] = True
OP1.setup(phase=water, pore_volume='pore.volume', throat_volume='throat.volume', access_limited=True)
OP1.run(points=100)
# plt.figure()
OP1.plot_intrusion_curve()
data = OP1.get_intrusion_data()
sat = data.Snwp
def update_phys_phase(results):
water['pore.occupancy'] = results['pore.occupancy']
air['pore.occupancy'] = 1 - results['pore.occupancy']
water['throat.occupancy'] = results['throat.occupancy']
air['throat.occupancy'] = 1 - results['throat.occupancy']
# internal physics
phys_air.add_model(model=pm.multiphase.conduit_conductance,
propname='throat.conduit_hydraulic_conductance',
throat_conductance='throat.hydraulic_conductance',
mode='strict')
phys_water.add_model(model=pm.multiphase.conduit_conductance,
propname='throat.conduit_hydraulic_conductance',
throat_conductance='throat.hydraulic_conductance',
mode='strict')
phys_air.add_model(model=pm.multiphase.conduit_conductance,
propname='throat.conduit_diffusive_conductance',
throat_conductance='throat.diffusive_conductance',
mode='strict')
phys_water.add_model(model=pm.multiphase.conduit_conductance,
propname='throat.conduit_diffusive_conductance',
throat_conductance='throat.diffusive_conductance',
mode='strict')
# boundary physics
phys_air_b.add_model(model=pm.multiphase.conduit_conductance,
propname='throat.conduit_hydraulic_conductance',
throat_conductance='throat.diffusive_conductance',
mode='strict')
phys_water_b.add_model(model=pm.multiphase.conduit_conductance,
propname='throat.conduit_hydraulic_conductance',
throat_conductance='throat.diffusive_conductance',
mode='strict')
phys_air_b.add_model(model=pm.multiphase.conduit_conductance,
propname='throat.conduit_diffusive_conductance',
throat_conductance='throat.diffusive_conductance',
mode='strict')
phys_water_b.add_model(model=pm.multiphase.conduit_conductance,
propname='throat.conduit_diffusive_conductance',
throat_conductance='throat.diffusive_conductance',
mode='strict')
bounds = [['front', 'back'], ['left', 'right'], ['top', 'bottom']]
diff_air = {'0': [], '1': [], '2': []}
diff_water = {'0': [], '1': [], '2': []}
perm_air = {'0': [], '1': [], '2': []}
perm_water = {'0': [], '1': [], '2': []}
max_Pc = max(OP1['throat.invasion_pressure'])
pore_volumes = pn['pore.volume']
throat_volumes = pn['throat.volume']
tot_vol = np.sum(pore_volumes) + np.sum(throat_volumes)
SPP_air = [None, None, None]
SPP_water = [None, None, None]
SPD_air = [None, None, None]
SPD_water = [None, None, None]
atm1 = 1
atm2 = 0
for bound_increment in range(len(bounds)):
BC1_pores = pn.pores(labels=bounds[bound_increment][0])
BC2_pores = pn.pores(labels=bounds[bound_increment][1])
# setup and run stokes and fickian diffusion
SPST_air = op.algorithms.StokesFlow(network=pn, phase=air)
SPST_air.setup(conductance='throat.hydraulic_conductance')
SPST_air.set_value_BC(values=atm1, pores=BC1_pores)
SPST_air.set_value_BC(values=atm2, pores=BC2_pores)
SPST_air.run()
SPST_water = op.algorithms.StokesFlow(network=pn, phase=water)
SPST_water.setup(conductance='throat.hydraulic_conductance')
SPST_water.set_value_BC(values=atm1, pores=BC1_pores)
SPST_water.set_value_BC(values=atm2, pores=BC2_pores)
SPST_water.run()
SPFD_air = op.algorithms.FickianDiffusion(network=pn, phase=air)
SPFD_air.setup(conductance='throat.diffusive_conductance')
SPFD_air.set_value_BC(values=atm1, pores=BC1_pores)
SPFD_air.set_value_BC(values=atm2, pores=BC2_pores)
SPFD_air.run()
SPFD_water = op.algorithms.FickianDiffusion(network=pn, phase=water)
SPFD_water.setup(conductance='throat.diffusive_conductance')
SPFD_water.set_value_BC(values=atm1, pores=BC1_pores)
SPFD_water.set_value_BC(values=atm2, pores=BC2_pores)
SPFD_water.run()
# multiplying the one length by 1e-6 has the same impact as multiplying all lengths by the scale factor
SPP_air[bound_increment] = SPST_air.calc_effective_permeability(
domain_area=1000*1000*1e-6, domain_length=250
)
SPP_water[bound_increment] = SPST_water.calc_effective_permeability(
domain_area=1000*1000*1e-6, domain_length=250
)
SPD_air[bound_increment] = SPFD_air.calc_effective_diffusivity(
domain_area=1000*1000*1e-6, domain_length=250
)
SPD_water[bound_increment] = SPFD_water.calc_effective_diffusivity(
domain_area=1000*1000*1e-6, domain_length=250
)
pn.project.purge_object(obj=SPST_air)
pn.project.purge_object(obj=SPST_water)
pn.project.purge_object(obj=SPFD_air)
pn.project.purge_object(obj=SPFD_water)
for Pc in data.Pcap:
update_phys_phase(OP1.results(Pc=Pc))
for bound_increment in range(len(bounds)):
BC1_pores = pn.pores(labels=bounds[bound_increment][0])
BC2_pores = pn.pores(labels=bounds[bound_increment][1])
# setup and run multiphase stokes flow and fickian diffusion
MPST_air = op.algorithms.StokesFlow(network=pn, phase=air)
MPST_air.setup(conductance='throat.conduit_hydraulic_conductance')
MPST_air.set_value_BC(values=atm1, pores=BC1_pores)
MPST_air.set_value_BC(values=atm2, pores=BC2_pores)
MPST_air.run()
MPST_water = op.algorithms.StokesFlow(network=pn, phase=water)
MPST_water.setup(conductance='throat.conduit_hydraulic_conductance')
MPST_water.set_value_BC(values=atm1, pores=BC1_pores)
MPST_water.set_value_BC(values=atm2, pores=BC2_pores)
MPST_water.run()
MPFD_air = op.algorithms.FickianDiffusion(network=pn, phase=air)
MPFD_air.setup(conductance='throat.conduit_diffusive_conductance')
MPFD_air.set_value_BC(values=atm1, pores=BC1_pores)
MPFD_air.set_value_BC(values=atm2, pores=BC2_pores)
MPFD_air.run()
MPFD_water = op.algorithms.FickianDiffusion(network=pn, phase=water)
MPFD_water.setup(conductance='throat.conduit_diffusive_conductance')
MPFD_water.set_value_BC(values=atm1, pores=BC1_pores)
MPFD_water.set_value_BC(values=atm2, pores=BC2_pores)
MPFD_water.run()
MPair_eff_perm = MPST_air.calc_effective_permeability(
domain_area=1000*1000*1e-6, domain_length=250
)
MPwater_eff_perm = MPST_water.calc_effective_permeability(
domain_area=1000*1000*1e-6, domain_length=250
)
MPair_eff_dif = MPFD_air.calc_effective_diffusivity(
domain_area=1000*1000*1e-6, domain_length=250
)
MPwater_eff_dif = MPFD_water.calc_effective_diffusivity(
domain_area=1000*1000*1e-6, domain_length=250
)
rel_eff_perm_air = MPair_eff_perm / SPP_air[bound_increment]
rel_eff_perm_water = MPwater_eff_perm / SPP_water[bound_increment]
rel_eff_dif_air = MPair_eff_dif / SPD_air[bound_increment]
rel_eff_dif_water = MPwater_eff_dif / SPD_water[bound_increment]
perm_air[str(bound_increment)].append(rel_eff_perm_air)
perm_water[str(bound_increment)].append(rel_eff_perm_water)
diff_air[str(bound_increment)].append(rel_eff_dif_air)
diff_water[str(bound_increment)].append(rel_eff_dif_water)
pn.project.purge_object(obj=MPFD_air)
pn.project.purge_object(obj=MPFD_water)
pn.project.purge_object(obj=MPST_air)
pn.project.purge_object(obj=MPST_water)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment