human
Give me a the Python program you requested given the following:
I am working on the file "Syllabus_in_notebooks/Sec4_1_Capillary_rise.ipynb".
The first task is:
Note that the effective grain diameter is about 10 times the effective pore radius. How to derive this, is another matter. It can be one by comparing Poisseuille flow in a tube with a porous medium by using the hydraulic radius instead of pore radius for both.
A sand of a grain diameter of say 0.2 mm will have a conductivity of around 10 m/d and a capillary rise of about 20 cm. This should correspond with a pore radius of 0.02 mm
Can you write Python program for it?
assistant
#Here is the Python program you requested.

class Straw:
    """Class defining a single straw."""
    def __init__(self, r, x):
        """Return a straw object with r and position given."""
        self.gam = 75e-3 # N/m
        self.rho = 1000. # [kf/m3]
        self.g = 9.81    # [N/kg]
        self.r = r # [m]
        self.x = x # [m]
        self.bbox = Bbox.null()
        
    @property
    def h(self):
        return 2 * self.gam / (self.rho * self.g * self.r)
        
    @property
    def surface(self):
        """Fluid surface in the straw."""
        angle = np.linspace(-180, 0, 36) * np.pi / 180.
        xy = np.vstack((self.x + self.r * np.cos(angle),
                        self.h + self.r * np.sin(angle))).T
        return xy
                       
    def plot(self, ax=None):
        """Generate a strawpatch and add it to ax."""
        MOVETO = 1
        LINETO = 2
        CLOSE = 90
        xys = np.array([[self.x - self.r, 0]])
        xye = np.array([[self.x + self.r, 0]])
        xy  = np.vstack((xys, self.surface, xye, xys))
        
        codes = np.zeros(xy.shape[0], dtype=int)  + LINETO
        codes[ 0] = MOVETO
        codes[-1] = CLOSE
        
        p = Path(xy, codes=codes)
                               
        ax.add_patch(PathPatch(path=p, fc='lightblue', ec='black'))
        self.bbox.update_from_path(p)
        
    def plotz(self, z=None, ax=None, **kw):
        """Plot the sides of the capilarry.
        
        Paramters
        ---------
        z: float
            height to plot the sides of the sraw
        ax: Axes object
            the axes
        kw: dict
            further parameters passed on to ax.plot()        
        """
        xyL = np.array([[self.x - self.r, 0],
                        [self.x - self.r, z]])
        xyR = np.array([[self.x + self.r, 0],
                        [self.x + self.r, z]])
        line1, = ax.plot(*xyL.T, **kw)
        line2, = ax.plot(*xyR.T, **kw)
        return (line1, line2)

class Straw_collection:
    """Class for collection of straws with random width...