Esempio n. 1
0
    def __init__(self,
                 shapes,
                 spacings,
                 origins,
                 labels=None,
                 name=None,
                 project=None):

        # If no labels given, then use default
        if labels is None:
            labels = [None for i in shapes]

        # Generate cubic networks of specified properties and store in a list
        nets = []
        for n in range(len(shapes)):
            net = Cubic(shape=shapes[n], spacing=spacings[n], name=labels[n])
            #            label_faces(net)
            net['pore.coords'] += origins[n]
            nets.append(net)

        # Begin the process of merging the networks, but no stitching yet
        main_net = nets.pop(0)
        for net in nets:
            extend(network=main_net,
                   pore_coords=net['pore.coords'],
                   throat_conns=net['throat.conns'] + main_net.Np)

        for net in nets:
            P1 = main_net.pores('surface')
            P1 = net.pores('surface')
            stitch(network=main_net)
Esempio n. 2
0
    def __init__(self, shapes, spacings, origins, labels=None, name=None,
                 project=None):

        # If no labels given, then use default
        if labels is None:
            labels = [None for i in shapes]

        # Generate cubic networks of specified properties and store in a list
        nets = []
        for n in range(len(shapes)):
            net = Cubic(shape=shapes[n], spacing=spacings[n], name=labels[n])
#            label_faces(net)
            net['pore.coords'] += origins[n]
            nets.append(net)

        # Begin the process of merging the networks, but no stitching yet
        main_net = nets.pop(0)
        for net in nets:
            extend(network=main_net, pore_coords=net['pore.coords'],
                   throat_conns=net['throat.conns'] + main_net.Np)

        for net in nets:
            P1 = main_net.pores('surface')
            P1 = net.pores('surface')
            stitch(network=main_net)
Esempio n. 3
0
    def __init__(self, shape, name=None, **kwargs):
        super().__init__(name=name)

        net = Cubic(shape=shape,
                    spacing=1e-4,
                    connectivity=26,
                    project=self,
                    **kwargs)

        geom = GenericGeometry(network=net, pores=net.Ps, throats=net.Ts)

        geom.add_model(propname='pore.seed',
                       model=gm.pore_seed.spatially_correlated,
                       weights=[1, 1, 1])
        geom.add_model(propname='pore.diameter',
                       model=gm.pore_size.weibull,
                       shape=2.2,
                       scale=2e-5,
                       loc=1e-6)
        geom.add_model(propname='pore.volume', model=gm.pore_volume.sphere)
        geom.add_model(propname='throat.length',
                       model=gm.throat_length.spheres_and_cylinders)
        geom.add_model(propname='throat.diameter',
                       model=gm.throat_size.from_neighbor_pores,
                       prop='pore.diameter',
                       mode='min')
        geom.add_model(propname='throat.volume',
                       model=gm.throat_volume.cylinder)

        geom.regenerate_models()
Esempio n. 4
0
 def __init__(self,
              shape,
              spacing=1,
              label_1='primary',
              label_2='secondary',
              **kwargs):
     super().__init__(**kwargs)
     spacing = sp.array(spacing)
     shape = sp.array(shape)
     # Deal with non-3D shape arguments
     shape = sp.pad(shape, [0, 3 - shape.size],
                    mode='constant',
                    constant_values=1)
     net = Cubic(shape=shape, spacing=1)
     net['throat.' + label_1] = True
     net['pore.' + label_1] = True
     single_dim = shape == 1
     shape[single_dim] = 2
     dual = Cubic(shape=shape - 1, spacing=1)
     faces = [['front', 'back'], ['left', 'right'], ['top', 'bottom']]
     faces = [faces[i] for i in sp.where(~single_dim)[0]]
     faces = sp.array(faces).flatten().tolist()
     dual.add_boundary_pores(faces)
     # Add secondary network name as a label
     dual['pore.' + label_2] = True
     dual['throat.' + label_2] = True
     # Shift coordinates prior to stitching
     dual['pore.coords'] += 0.5 * (~single_dim)
     topotools.stitch(net,
                      dual,
                      P_network=net.Ps,
                      P_donor=dual.Ps,
                      len_max=1)
     net['throat.interconnect'] = net['throat.stitched']
     del net['throat.stitched']
     # Clean-up labels
     net['pore.surface'] = False
     net['throat.surface'] = False
     for face in faces:
         # Remove face label from secondary network since it's internal now
         Ps = net.pores(labels=[face, label_2], mode='xnor')
         net['pore.' + face][Ps] = False
         Ps = net.pores(labels=[face + '_boundary'])
         net['pore.' + face][Ps] = True
         Ps = net.pores(face)
         net['pore.surface'][Ps] = True
         Ts = net.find_neighbor_throats(pores=Ps, mode='xnor')
         net['throat.surface'][Ts] = True
         net['throat.' + face] = net.tomask(throats=Ts)
     [net.pop(item) for item in net.labels() if 'boundary' in item]
     # Label non-surface pores and throats as internal
     net['pore.internal'] = True
     net['throat.internal'] = True
     # Transfer all dictionary items from 'net' to 'self'
     [self.update({item: net[item]}) for item in net]
     ws.close_project(net.project)
     # Finally, scale network to requested spacing
     net['pore.coords'] *= spacing
"""
import openpnm as op
from openpnm.network import Cubic
from openpnm.phases import Air, Water, MultiPhase
from openpnm.geometry import SpheresAndCylinders
from openpnm.physics import Standard
from openpnm.models.misc import constant
from openpnm.models.physics.source_terms import linear
import matplotlib.pyplot as plt
import numpy as np

np.random.seed(10)

# Define network, geometry and constituent phases
shape = np.array([100, 100, 1])
net = Cubic(shape=shape)
geom = StickAndBall(network=net, pores=net.Ps, throats=net.Ts)
air = Air(network=net, name="air")
water = Water(network=net, name="water")
water["pore.diffusivity"] = air["pore.diffusivity"] * 0.05

# Define the regions to be occupied by the two phases (air and water)
x, y, z = net["pore.coords"].T
ps_water = net.Ps[(y >= 75) + (y <= 25)]
ps_air = np.setdiff1d(net.Ps, ps_water)
ts_water = net.find_neighbor_throats(pores=ps_water, mode="xnor")
ts_air = net.find_neighbor_throats(pores=ps_air, mode="xnor")
ts_interface = net.find_neighbor_throats(pores=ps_water, mode="xor")

# Define multiphase and set phase occupancy
mphase = MultiPhase(network=net, phases=[air, water], name="mphase")
Esempio n. 6
0
    def __init__(self, shape, mode='sc', spacing=1, **kwargs):
        super().__init__(**kwargs)
        shape = np.array(shape)
        if np.any(shape < 2):
            raise Exception('Bravais lattice networks must have at least 2 '
                            'pores in all directions')
        if mode == 'bcc':
            # Make a basic cubic for the coner pores
            net1 = Cubic(shape=shape)
            net1['pore.net1'] = True
            # Create a smaller cubic for the body pores, and shift it
            net2 = Cubic(shape=shape - 1)
            net2['pore.net2'] = True
            net2['pore.coords'] += 0.5
            # Stitch them together
            topotools.stitch(net1, net2, net1.Ps, net2.Ps, len_max=0.99)
            self.update(net1)
            ws.close_project(net1.project)

            # Deal with labels
            Ps1 = self['pore.net2']
            self.clear(mode='labels')
            self['pore.corner_sites'] = ~Ps1
            self['pore.body_sites'] = Ps1
            Ts = self.find_neighbor_throats(pores=self.pores('body_sites'),
                                            mode='exclusive_or')
            self['throat.corner_to_body'] = False
            self['throat.corner_to_body'][Ts] = True
            Ts = self.find_neighbor_throats(pores=self.pores('corner_sites'),
                                            mode='xnor')
            self['throat.corner_to_corner'] = False
            self['throat.corner_to_corner'][Ts] = True
            Ts = self.find_neighbor_throats(pores=self.pores('body_sites'),
                                            mode='xnor')
            self['throat.body_to_body'] = False
            self['throat.body_to_body'][Ts] = True

        elif mode == 'fcc':
            shape = np.array(shape)
            # Create base cubic network of corner sites
            net1 = Cubic(shape=shape)
            # Create 3 networks to become face sites
            net2 = Cubic(shape=shape - [1, 1, 0])
            net3 = Cubic(shape=shape - [1, 0, 1])
            net4 = Cubic(shape=shape - [0, 1, 1])
            net2['pore.coords'] += np.array([0.5, 0.5, 0])
            net3['pore.coords'] += np.array([0.5, 0, 0.5])
            net4['pore.coords'] += np.array([0, 0.5, 0.5])
            # Remove throats from net2 (trim doesn't work when removing ALL)
            for n in [net2, net3, net4]:
                n.clear(element='throat', mode='all')
                n.update({'throat.all': np.array([], dtype=bool)})
                n.update({'throat.conns': np.ndarray([0, 2], dtype=bool)})
            # Join networks 2, 3 and 4 into one with all face sites
            topotools.stitch(net2,
                             net3,
                             net2.Ps,
                             net3.Ps,
                             method='radius',
                             len_max=0.75)
            topotools.stitch(net2,
                             net4,
                             net2.Ps,
                             net4.Ps,
                             method='radius',
                             len_max=0.75)
            # Join face sites network with the corner sites network
            topotools.stitch(net1,
                             net2,
                             net1.Ps,
                             net2.Ps,
                             method='radius',
                             len_max=0.75)
            self.update(net1)
            ws.close_project(net1.project)
            # Deal with labels
            self.clear(mode='labels')
            Ps = np.any(np.mod(self['pore.coords'], 1) == 0, axis=1)
            self['pore.face_sites'] = Ps
            self['pore.corner_sites'] = ~Ps
            Ts = self.find_neighbor_throats(pores=self.pores('corner_sites'),
                                            mode='xnor')
            self['throat.corner_to_corner'] = False
            self['throat.corner_to_corner'][Ts] = True
            Ts = self.find_neighbor_throats(pores=self.pores('face_sites'))
            self['throat.corner_to_face'] = False
            self['throat.corner_to_face'][Ts] = True

        elif mode == 'hcp':
            raise NotImplementedError('hcp is not implemented yet')

        elif mode == 'sc':
            net = Cubic(shape=shape, spacing=1)
            self.update(net)
            ws.close_project(net.project)
            self.clear(mode='labels')
            self['pore.corner_sites'] = True
            self['throat.corner_to_corner'] = True

        else:
            raise Exception('Unrecognized lattice type: ' + mode)

        # Finally scale network to specified spacing
        topotools.label_faces(self)
        Ps = self.pores(['left', 'right', 'top', 'bottom', 'front', 'back'])
        Ps = self.to_mask(pores=Ps)
        self['pore.surface'] = Ps
        self['pore.coords'] *= np.array(spacing)
Esempio n. 7
0
    def __init__(self,
                 shape,
                 spacing=1.0,
                 length=1.0,
                 psd_params={'distribution': 'norm',
                             'loc': None,
                             'scale': None},
                 name=None,
                 settings={},
                 **kwargs):
        super().__init__(name=name)
        self.settings.update(defsets)
        self.settings.update(settings)

        if isinstance(shape, int):
            shape = sp.array([shape, shape, 2])
        elif len(shape) == 2:
            shape = sp.concatenate((sp.array(shape), [2]))
        else:
            raise Exception('shape not understood, must be int ' +
                            ' or list of 2 ints')

        if isinstance(spacing, float) or isinstance(spacing, int):
            spacing = float(spacing)
            self.settings['spacing'] = spacing
            spacing = sp.array([spacing, spacing, length])
        else:
            raise Exception('spacing not understood, must be float')

        net = Cubic(shape=shape, spacing=spacing, project=self, **kwargs)
        Ps_top = net.pores('top')
        Ps_bot = net.pores('bottom')
        Ts = net.find_connecting_throat(P1=Ps_top, P2=Ps_bot)
        Ts = net.tomask(throats=Ts)
        trim(network=net, throats=~Ts)

        geom = GenericGeometry(network=net, pores=net.Ps, throats=net.Ts)

        geom.add_model(propname='throat.seed',
                       model=mods.geometry.throat_seed.random)
        if psd_params['loc'] is None:
            psd_params['loc'] = spacing[0]/2
        if psd_params['scale'] is None:
            psd_params['scale'] = spacing[0]/10
        if psd_params['distribution'] in ['norm', 'normal', 'gaussian']:
            geom.add_model(propname='throat.size_distribution',
                           seeds='throat.seed',
                           model=mods.geometry.throat_size.normal,
                           loc=psd_params['loc'], scale=psd_params['scale'])
        elif psd_params['distribution'] in ['weibull']:
            geom.add_model(propname='throat.size_distribution',
                           seeds='throat.seed',
                           model=mods.geometry.throat_size.weibull,
                           loc=psd_params['loc'],
                           scale=psd_params['scale'],
                           shape=psd_params['shape'])
        else:
            temp = psd_params.copy()
            func = getattr(spst, temp.pop('distribution'))
            psd = func.freeze(**temp)
            geom.add_model(propname='throat.size_distribution',
                           seeds='throat.seed',
                           model=mods.geometry.throat_size.generic_distribution,
                           func=psd)

        if sp.any(geom['throat.size_distribution'] < 0):
            logger.warning('Given size distribution produced negative ' +
                           'throat diameters...these will be set to 0')
        geom.add_model(propname='throat.diameter',
                       model=mods.misc.clip,
                       prop='throat.size_distribution',
                       xmin=1e-12, xmax=sp.inf)

        if self.settings['adjust_psd'] is None:
            if geom['throat.size_distribution'].max() > spacing[0]:
                logger.warning('Given size distribution produced throats ' +
                               'larger than the spacing.')

        elif self.settings['adjust_psd'] == 'clip':
            geom.add_model(propname='throat.diameter',
                           model=mods.misc.clip,
                           prop='throat.size_distribution',
                           xmin=1e-12, xmax=spacing[0])
            if geom['throat.size_distribution'].max() > spacing[0]:
                logger.warning('Given size distribution produced throats ' +
                               'larger than the spacing...tube diameters ' +
                               'will be clipped between 0 and given spacing')

        elif self.settings['adjust_psd'] == 'normalize':
            tmin = max(1e-12, geom['throat.size_distribution'].min())
            geom.add_model(propname='throat.diameter',
                           model=mods.misc.normalize,
                           prop='throat.size_distribution',
                           xmin=tmin, xmax=spacing[0])
            if geom['throat.size_distribution'].max() > spacing[0]:
                logger.warning('Given size distribution produced throats ' +
                               'larger than the spacing...tube diameters ' +
                               'will be normalized to fit given spacing')
        else:
            logger.warning('Settings not understood, ignoring')

        geom.add_model(propname='pore.diameter',
                       model=mods.geometry.pore_size.from_neighbor_throats,
                       throat_prop='throat.diameter', mode='max')
        geom.add_model(propname='pore.diameter',
                       model=mods.misc.constant, value=0.0)
        geom.add_model(propname='throat.length',
                       model=mods.geometry.throat_length.ctc)
        geom.add_model(propname='throat.area',
                       model=mods.geometry.throat_area.cylinder)
        geom.add_model(propname='pore.area',
                       model=mods.misc.from_neighbor_throats,
                       throat_prop='throat.area')
        geom.add_model(propname='pore.volume',
                       model=mods.misc.constant, value=0.0)
        geom.add_model(propname='throat.volume',
                       model=mods.geometry.throat_volume.cylinder)

        geom.regenerate_models()

        # Now create a generic phase with physics models on it
        phase = GenericPhase(network=net)
        m = mods.physics.hydraulic_conductance.classic_hagen_poiseuille
        phase.add_model(propname='throat.hydraulic_conductance',
                        model=m, regen_mode='deferred')
        m = mods.physics.diffusive_conductance.classic_ordinary_diffusion
        phase.add_model(propname='throat.diffusive_conductance',
                        model=m, regen_mode='deferred')
        m = mods.physics.diffusive_conductance.classic_ordinary_diffusion
        phase.add_model(propname='throat.entry_pressure',
                        model=m, regen_mode='deferred')
Esempio n. 8
0
    def __init__(self,
                 shape,
                 spacing=1.0,
                 length=1.0,
                 psd_params={
                     'distribution': 'norm',
                     'loc': None,
                     'scale': None
                 },
                 name=None,
                 settings={},
                 **kwargs):
        super().__init__(name=name)
        self.settings.update(defsets)
        self.settings.update(settings)

        if isinstance(shape, int):
            shape = sp.array([shape, shape, 2])
        elif len(shape) == 2:
            shape = sp.concatenate((sp.array(shape), [2]))
        else:
            raise Exception('shape not understood, must be int ' +
                            ' or list of 2 ints')

        if isinstance(spacing, float) or isinstance(spacing, int):
            spacing = float(spacing)
            self.settings['spacing'] = spacing
            spacing = sp.array([spacing, spacing, length])
        else:
            raise Exception('spacing not understood, must be float')

        net = Cubic(shape=shape, spacing=spacing, project=self, **kwargs)
        Ps_top = net.pores('top')
        Ps_bot = net.pores('bottom')
        Ts = net.find_connecting_throat(P1=Ps_top, P2=Ps_bot)
        Ts = net.tomask(throats=Ts)
        trim(network=net, throats=~Ts)

        geom = GenericGeometry(network=net, pores=net.Ps, throats=net.Ts)

        geom.add_model(propname='throat.seed',
                       model=mods.geometry.throat_seed.random)
        if psd_params['loc'] is None:
            psd_params['loc'] = spacing[0] / 2
        if psd_params['scale'] is None:
            psd_params['scale'] = spacing[0] / 10
        if psd_params['distribution'] in ['norm', 'normal', 'gaussian']:
            geom.add_model(propname='throat.size_distribution',
                           seeds='throat.seed',
                           model=mods.geometry.throat_size.normal,
                           loc=psd_params['loc'],
                           scale=psd_params['scale'])
        elif psd_params['distribution'] in ['weibull']:
            geom.add_model(propname='throat.size_distribution',
                           seeds='throat.seed',
                           model=mods.geometry.throat_size.weibull,
                           loc=psd_params['loc'],
                           scale=psd_params['scale'],
                           shape=psd_params['shape'])
        else:
            temp = psd_params.copy()
            func = getattr(spst, temp.pop('distribution'))
            psd = func.freeze(**temp)
            geom.add_model(
                propname='throat.size_distribution',
                seeds='throat.seed',
                model=mods.geometry.throat_size.generic_distribution,
                func=psd)

        if sp.any(geom['throat.size_distribution'] < 0):
            logger.warning('Given size distribution produced negative ' +
                           'throat diameters...these will be set to 0')
        geom.add_model(propname='throat.diameter',
                       model=mods.misc.clip,
                       prop='throat.size_distribution',
                       xmin=1e-12,
                       xmax=sp.inf)

        if self.settings['adjust_psd'] is None:
            if geom['throat.size_distribution'].max() > spacing[0]:
                logger.warning('Given size distribution produced throats ' +
                               'larger than the spacing.')

        elif self.settings['adjust_psd'] == 'clip':
            geom.add_model(propname='throat.diameter',
                           model=mods.misc.clip,
                           prop='throat.size_distribution',
                           xmin=1e-12,
                           xmax=spacing[0])
            if geom['throat.size_distribution'].max() > spacing[0]:
                logger.warning('Given size distribution produced throats ' +
                               'larger than the spacing...tube diameters ' +
                               'will be clipped between 0 and given spacing')

        elif self.settings['adjust_psd'] == 'normalize':
            tmin = max(1e-12, geom['throat.size_distribution'].min())
            geom.add_model(propname='throat.diameter',
                           model=mods.misc.normalize,
                           prop='throat.size_distribution',
                           xmin=tmin,
                           xmax=spacing[0])
            if geom['throat.size_distribution'].max() > spacing[0]:
                logger.warning('Given size distribution produced throats ' +
                               'larger than the spacing...tube diameters ' +
                               'will be normalized to fit given spacing')
        else:
            logger.warning('Settings not understood, ignoring')

        geom.add_model(propname='pore.diameter',
                       model=mods.geometry.pore_size.from_neighbor_throats,
                       throat_prop='throat.diameter',
                       mode='max')
        geom.add_model(propname='pore.diameter',
                       model=mods.misc.constant,
                       value=0.0)
        geom.add_model(propname='throat.length',
                       model=mods.geometry.throat_length.ctc)
        geom.add_model(propname='throat.area',
                       model=mods.geometry.throat_area.cylinder)
        geom.add_model(propname='pore.area',
                       model=mods.misc.from_neighbor_throats,
                       throat_prop='throat.area')
        geom.add_model(propname='pore.volume',
                       model=mods.misc.constant,
                       value=0.0)
        geom.add_model(propname='throat.volume',
                       model=mods.geometry.throat_volume.cylinder)

        geom.regenerate_models()

        # Now create a generic phase with physics models on it
        phase = GenericPhase(network=net)
        m = mods.physics.hydraulic_conductance.classic_hagen_poiseuille
        phase.add_model(propname='throat.hydraulic_conductance',
                        model=m,
                        regen_mode='deferred')
        m = mods.physics.diffusive_conductance.classic_ordinary_diffusion
        phase.add_model(propname='throat.diffusive_conductance',
                        model=m,
                        regen_mode='deferred')
        m = mods.physics.diffusive_conductance.classic_ordinary_diffusion
        phase.add_model(propname='throat.entry_pressure',
                        model=m,
                        regen_mode='deferred')