Manually Adding and Removing Pores and Throats#

import openpnm as op
%config InlineBackend.figure_formats = ['svg']
import matplotlib.pyplot as plt
import numpy as np
ws = op.Workspace()
ws.settings['loglevel'] = 50

We’ll start with something simple, by adding a single pore and throat to a 2D network:

pn =[5, 5, 1], spacing=1.0)

Add a Single Pore#

First add a pore and visualize it:

op.topotools.extend(network=pn, pore_coords=[[6, 6, 0.5]])
fig, ax = plt.subplots()
op.topotools.plot_coordinates(network=pn, ax=ax)
op.topotools.plot_connections(network=pn, ax=ax)
<matplotlib.collections.LineCollection at 0x7f08411cc160>

Note that we’ve only added a pore, but not specified any connections to other pores. This requires quite a bit more thought than adding pore coords. The original network had 25 pores, number 0 to 24 (due to python’s 0 indexing), so this new pore is number 25. Specifying connections requires explicitly stating which pores are connected to which according to the pore index.

Add a Single Throat#

Let’s connect this new pore to a the single pore in the top-left corner, which we know to be pore 4. Again we’ll use extend but specify throat_conns instead:

op.topotools.extend(network=pn, throat_conns=[[4, 25]])
fig, ax = plt.subplots()
op.topotools.plot_coordinates(network=pn, ax=ax)
op.topotools.plot_connections(network=pn, ax=ax)
<matplotlib.collections.LineCollection at 0x7f0829e2f6a0>

Find Several Throat and Add Simultaneously#

We can also find the indices of pores that are physicall close to pore 25 , then make connections between those:

Ps = pn.find_nearby_pores(pores=25, r=3)
[array([19, 23, 24])]

The above search yeilded 3 pores that are withing a radius of 3 units of pore 25. In order to connected these to pore 25 y a new throat, we need to create a pair of indices indicating the pore on each the new throat as shown below. This convention for defining network topology is based on the sparse adjacency matrix expressed in COO format, as described here.

[[25, i] for i in Ps[0]]
[[25, 19], [25, 23], [25, 24]]

We can send this list to the extend function to add all three new throats with one call:

op.topotools.extend(network=pn, throat_conns=[[25, i] for i in Ps[0]])
fig, ax = plt.subplots()
op.topotools.plot_coordinates(network=pn, ax=ax)
op.topotools.plot_connections(network=pn, ax=ax)
<matplotlib.collections.LineCollection at 0x7f0829e0ad30>

More Complex Additions#

Now let’s do something more complex, by adding pores inside a for-loop. First create a simple 2D cubic network:

net =[5, 5, 1], spacing=1.0)

We’ll now scan through each pores in the network and add 4 new pores next to each one, at the 4 corners:

Ps = net.Ps
Ts = net.Ts
coords = net['pore.coords']
dist = 0.3
corners = [[-1, -1], [-1, 1], [1, 1], [1, -1]]
for xdir, ydir in corners:
    adj = np.zeros_like(coords)
    adj[:, 0] = dist*xdir
    adj[:, 1] = dist*ydir
    new_coords = coords + adj
    op.topotools.extend(network=net, pore_coords=new_coords)
    new_Ps = net.Ps[-len(Ps):]
    new_conns = np.vstack((Ps, new_Ps)).T
    op.topotools.extend(network=net, throat_conns=new_conns)

After any network manipulation operation, it’s a good idea to check the health of the network, which checks for disconnected pores. All empty lists means nothing was found.

Key                                 Value
headless_throats                    []
looped_throats                      []
isolated_pores                      []
disconnected_pores                  []
duplicate_throats                   []
bidirectional_throats               []
fig, ax = plt.subplots(1, figsize=[6, 6])
op.topotools.plot_connections(network=net, throats=Ts, ax=ax, c='b')
op.topotools.plot_connections(network=net, throats=net.Ts[len(Ts):],
                              ax=ax, c='y')
op.topotools.plot_coordinates(network=net, pores=Ps, c='r', s=500, ax=ax)
op.topotools.plot_coordinates(network=net, pores=net.Ps[len(Ps):],
                              c='g', s=100, ax=ax)