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)
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()
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")
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)
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')
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')