<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Problem with Domain Area and Length
In order to find network properties such as permeability using Darcy's law, it is necessary to know the domain length and area.  At first glance this might seem as simple as finding the maxima and minima of the pore coordinates in the direction of interest; however it is a bit more subtle than that as will be explained in this notebook.  Consider the simple cubic network
Step1:  Now let's plot the coordinates and connections between them
Step2:  Let's say we'd like to know the length of the domain from left to right.  The pore coordinates for the leftmost pores are
Step3:  Note that the 'minimum' value is 0.5 rather than 0.0.  This is because the pore coordinates point to the center of the region that belongs to the pore.  In the case of the simple cubic with a spacing of 1, pore 0 lies at [0.5, 0.5, 0.5], while the bounding box around the pore goes from [0, 0, 0], to [1, 1, 1].  
Therefore, if we use pore coordinates to find the domain length we'd do
Step4:  While in reality to domain is 4 pore long and the correct answer should be 4.0.  The extra 0.5 of the left and right cells are not included.  
It may seem simple enough to automatically add a full lattice cell to the calculation, but this cannot be assumed since many networks are random.  Consider the Delaunay network
Step5:  Let's first remove the boundary pores to ensure the network is fully random
Step6:  Now it's quite clear that finding the domain size by assuming a bounding box around the pore coordinates does not tell the whole story. How much 'extra' length should be added beyond the extreme pores?  This is not possible to know based only on the pore coordinates, which is the only information OpenPNM has.
The end result of this scenario is that when computing anything that requires length and area, these values must be specified by the user. Consider the permeability coefficient
Step7:  If you do not specify the domain area and length, OpenPNM will attempt to estimate these values using the faulty logic of minima and maxima of boundary pores, but will issue a warning so you know that errors are present.
Step8:  To get correct answers, it is necessary to specify the domain sizes as follows
Step9:  Of course, the most correct way to calculate K is to do it manually using Darcy's law
<ASSISTANT_TASK:>
Python Code:
import matplotlib.pyplot as plt
import openpnm as op
%config InlineBackend.figure_formats = ['svg']
import numpy as np
np.random.seed(10)
pn = op.network.Cubic(shape=[4, 4, 1])
Explanation: Problem with Domain Area and Length
In order to find network properties such as permeability using Darcy's law, it is necessary to know the domain length and area.  At first glance this might seem as simple as finding the maxima and minima of the pore coordinates in the direction of interest; however it is a bit more subtle than that as will be explained in this notebook.  Consider the simple cubic network:
End of explanation
# NBVAL_IGNORE_OUTPUT
fig, ax = plt.subplots()
op.topotools.plot_coordinates(pn, markersize=500, ax=ax)
op.topotools.plot_connections(pn, ax=ax)
Explanation: Now let's plot the coordinates and connections between them:
End of explanation
pn['pore.coords'][pn.pores('left'), :]
Explanation: Let's say we'd like to know the length of the domain from left to right.  The pore coordinates for the leftmost pores are:
End of explanation
L = pn['pore.coords'][:, 0].max() - pn['pore.coords'][:, 0].min()
print(L)
Explanation: Note that the 'minimum' value is 0.5 rather than 0.0.  This is because the pore coordinates point to the center of the region that belongs to the pore.  In the case of the simple cubic with a spacing of 1, pore 0 lies at [0.5, 0.5, 0.5], while the bounding box around the pore goes from [0, 0, 0], to [1, 1, 1].  
Therefore, if we use pore coordinates to find the domain length we'd do:
End of explanation
dn = op.network.Delaunay(points=20, shape=[1, 1, 0])
Explanation: While in reality to domain is 4 pore long and the correct answer should be 4.0.  The extra 0.5 of the left and right cells are not included.  
It may seem simple enough to automatically add a full lattice cell to the calculation, but this cannot be assumed since many networks are random.  Consider the Delaunay network:
End of explanation
op.topotools.trim(network=dn, pores=dn.pores(['left', 'right', 'front', 'back']))
# NBVAL_IGNORE_OUTPUT
fig, ax = plt.subplots()
op.topotools.plot_coordinates(dn, markersize=500, ax=ax)
op.topotools.plot_connections(dn, ax=ax)
Explanation: Let's first remove the boundary pores to ensure the network is fully random:
End of explanation
pn = op.network.Cubic(shape=[4, 4, 4])
geo = op.geometry.SpheresAndCylinders(network=pn, pores=pn.Ps, throats=pn.Ts)
air = op.phases.Air(network=pn)
phys = op.physics.Standard(network=pn, phase=air, geometry=geo)
sf = op.algorithms.StokesFlow(network=pn, phase=air)
sf.set_value_BC(pores=pn.pores('left'), values=200000)
sf.set_value_BC(pores=pn.pores('right'), values=100000)
sf.run()
Explanation: Now it's quite clear that finding the domain size by assuming a bounding box around the pore coordinates does not tell the whole story. How much 'extra' length should be added beyond the extreme pores?  This is not possible to know based only on the pore coordinates, which is the only information OpenPNM has.
The end result of this scenario is that when computing anything that requires length and area, these values must be specified by the user. Consider the permeability coefficient:
End of explanation
perm=op.metrics.AbsolutePermeability(network=pn)
K=perm.run()
print(K)
Explanation: If you do not specify the domain area and length, OpenPNM will attempt to estimate these values using the faulty logic of minima and maxima of boundary pores, but will issue a warning so you know that errors are present.
End of explanation
A = 16
L = 4
perm=op.metrics.AbsolutePermeability(network=pn)
perm.settings._update({
    'area': A,
    'length':L})
K=perm.run()
print(K)
Explanation: To get correct answers, it is necessary to specify the domain sizes as follows:
End of explanation
mu = air['pore.viscosity'].mean()
Q = sf.rate(pores=pn.pores('left'))
dP = 200000 - 100000
K = Q*mu*L/(A * dP)
print(K)
Explanation: Of course, the most correct way to calculate K is to do it manually using Darcy's law:
End of explanation
<END_TASK>