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