def check_geometry_health(self): r""" Perform a check to find pores with overlapping or undefined Geometries Returns ------- A HealthDict """ health = HealthDict() health['overlapping_pores'] = [] health['undefined_pores'] = [] health['overlapping_throats'] = [] health['undefined_throats'] = [] geoms = self.geometries().keys() if len(geoms): net = self.network Ptemp = np.zeros((net.Np, )) Ttemp = np.zeros((net.Nt, )) for item in geoms: Pind = net['pore.' + item] Tind = net['throat.' + item] Ptemp[Pind] = Ptemp[Pind] + 1 Ttemp[Tind] = Ttemp[Tind] + 1 health['overlapping_pores'] = np.where(Ptemp > 1)[0].tolist() health['undefined_pores'] = np.where(Ptemp == 0)[0].tolist() health['overlapping_throats'] = np.where(Ttemp > 1)[0].tolist() health['undefined_throats'] = np.where(Ttemp == 0)[0].tolist() return health
def check_data_health(self, obj): r""" Check the health of pore and throat data arrays. Parameters ---------- obj : OpenPNM object A handle of the object to be checked Returns ------- health : dict Returns a HealthDict object which a basic dictionary with an added ``health`` attribute that is True is all entries in the dict are deemed healthy (empty lists), or False otherwise. """ health = HealthDict() for item in obj.props(): health[item] = [] if obj[item].dtype == 'O': health[item] = 'No checks on object' elif np.sum(np.isnan(obj[item])) > 0: health[item] = 'Has NaNs' elif np.shape(obj[item])[0] != obj._count(item.split('.')[0]): health[item] = 'Wrong Length' return health
def check_mixture_health(self): r""" Checks the "health" of the mixture Calculates the mole fraction of all species in each pore and returns an list of where values are too low or too high Returns ------- health : dict A HealtDict object containing lists of locations where the mole fractions are not unity. One value indiates locations that are too high, and another where they are too low. """ h = HealthDict() h['mole_fraction_too_low'] = [] h['mole_fraction_too_high'] = [] self._update_total_molfrac() lo = np.where(self['pore.mole_fraction.all'] < 1.0)[0] hi = np.where(self['pore.mole_fraction.all'] > 1.0)[0] if len(lo) > 0: h['mole_fraction_too_low'] = lo if len(hi) > 0: h['mole_fraction_too_high'] = hi return h
def check_network_health(self): r""" This method checks the topological health of the network The following aspects are checked for: (1) Isolated pores (2) Disconnected clusters of pores (3) Duplicate throats (4) Headless throats (5) Bidirectional throats Returns ------- health : dict A dictionary containing the offending pores or throat numbers under each named key. Notes ----- It also returns a list of which pores and throats should be trimmed from the network to restore health. This list is a suggestion only, and is based on keeping the largest cluster and trimming the others. - Does not yet check for duplicate pores - Does not yet suggest which throats to remove - This is just a 'check' and does not 'fix' the problems it finds """ import openpnm.models.network as mods health = HealthDict() net = self.network # Check for headless throats headless = mods.headless_throats(net) health['headless_throats'] = np.where(headless)[0].tolist() # Check for throats that loop back onto the same pore looped = mods.looped_throats(net) health['looped_throats'] = np.where(looped)[0].tolist() # Check for individual isolated pores isolated = mods.isolated_pores(net) health['isolated_pores'] = np.where(isolated)[0].tolist() # Check for separated clusters of pores size = mods.cluster_size(net) mx = np.max(size) health['disconnected_pores'] = np.where(size < mx)[0].tolist() # Check for duplicate throats dupes = mods.duplicate_throats(net) health['duplicate_throats'] = np.where(dupes)[0].tolist() # Check for bidirectional throats bidir = mods.bidirectional_throats(net) health['bidirectional_throats'] = np.where(bidir)[0].tolist() return health
def check_physics_health(self, phase): r""" Performs a check to find pores which have overlapping or missing Physics. Parameters ---------- phase : GenericPhase The Phase whose Physics should be checked Returns ------- HealthDict """ health = HealthDict() health['overlapping_pores'] = [] health['undefined_pores'] = [] health['overlapping_throats'] = [] health['undefined_throats'] = [] geoms = self.geometries().keys() if len(geoms) > 0: phys = self.find_physics(phase=phase) if len(phys) == 0: raise Exception( str(len(geoms)) + ' geometries were found, but' + ' no physics') if None in phys: raise Exception('Undefined physics found, check the grid') Ptemp = np.zeros((phase.Np, )) Ttemp = np.zeros((phase.Nt, )) for item in phys: Pind = phase['pore.' + item.name] Tind = phase['throat.' + item.name] Ptemp[Pind] = Ptemp[Pind] + 1 Ttemp[Tind] = Ttemp[Tind] + 1 health['overlapping_pores'] = np.where(Ptemp > 1)[0].tolist() health['undefined_pores'] = np.where(Ptemp == 0)[0].tolist() health['overlapping_throats'] = np.where(Ttemp > 1)[0].tolist() health['undefined_throats'] = np.where(Ttemp == 0)[0].tolist() return health
def check_network_health(self): r""" This method check the network topological health by checking for: (1) Isolated pores (2) Islands or isolated clusters of pores (3) Duplicate throats (4) Bidirectional throats (ie. symmetrical adjacency matrix) (5) Headless throats Returns ------- A dictionary containing the offending pores or throat numbers under each named key. It also returns a list of which pores and throats should be trimmed from the network to restore health. This list is a suggestion only, and is based on keeping the largest cluster and trimming the others. Notes ----- - Does not yet check for duplicate pores - Does not yet suggest which throats to remove - This is just a 'check' and does not 'fix' the problems it finds """ health = HealthDict() health['disconnected_clusters'] = [] health['isolated_pores'] = [] health['trim_pores'] = [] health['duplicate_throats'] = [] health['bidirectional_throats'] = [] health['headless_throats'] = [] health['looped_throats'] = [] # Check for headless throats hits = sp.where(self['throat.conns'] > self.Np - 1)[0] if sp.size(hits) > 0: health['headless_throats'] = sp.unique(hits) return health # Check for throats that loop back onto the same pore P12 = self['throat.conns'] hits = sp.where(P12[:, 0] == P12[:, 1])[0] if sp.size(hits) > 0: health['looped_throats'] = hits # Check for individual isolated pores Ps = self.num_neighbors(self.pores()) if sp.sum(Ps == 0) > 0: health['isolated_pores'] = sp.where(Ps == 0)[0] # Check for separated clusters of pores temp = [] am = self.create_adjacency_matrix(fmt='coo', triu=True) Cs = csg.connected_components(am, directed=False)[1] if sp.unique(Cs).size > 1: for i in sp.unique(Cs): temp.append(sp.where(Cs == i)[0]) b = sp.array([len(item) for item in temp]) c = sp.argsort(b)[::-1] for i in range(0, len(c)): health['disconnected_clusters'].append(temp[c[i]]) if i > 0: health['trim_pores'].extend(temp[c[i]]) # Check for duplicate throats am = self.create_adjacency_matrix(fmt='csr', triu=True).tocoo() hits = sp.where(am.data > 1)[0] if len(hits): mergeTs = [] hits = sp.vstack((am.row[hits], am.col[hits])).T ihits = hits[:, 0] + 1j * hits[:, 1] conns = self['throat.conns'] iconns = conns[:, 0] + 1j * conns[:, 1] # Convert to imaginary for item in ihits: mergeTs.append(sp.where(iconns == item)[0]) health['duplicate_throats'] = mergeTs # Check for bidirectional throats adjmat = self.create_adjacency_matrix(fmt='coo') num_full = adjmat.sum() temp = sprs.triu(adjmat, k=1) num_upper = temp.sum() if num_full > num_upper: biTs = sp.where( self['throat.conns'][:, 0] > self['throat.conns'][:, 1])[0] health['bidirectional_throats'] = biTs.tolist() return health