def _getAddedMeshValues(self, other, resolution=1e-2): """Calculate the parameters to define a concatenation of `other` with `self` Parameters ---------- other : ~fipy.meshes.mesh.Mesh The `Mesh` to concatenate with `self` resolution : float How close vertices have to be (relative to the smallest cell-to-cell distance in either mesh) to be considered the same Returns ------- dict (`vertexCoords`, `faceVertexIDs`, `cellFaceIDs`) for the new mesh. """ selfc = self._concatenableMesh otherc = other._concatenableMesh selfNumFaces = selfc.faceVertexIDs.shape[-1] selfNumVertices = selfc.vertexCoords.shape[-1] otherNumFaces = otherc.faceVertexIDs.shape[-1] otherNumVertices = otherc.vertexCoords.shape[-1] ## check dimensions if(selfc.vertexCoords.shape[0] != otherc.vertexCoords.shape[0]): raise MeshAdditionError("Dimensions do not match") ## compute vertex correlates # from fipy.tools.debug import PRINT # PRINT("selfNumFaces", selfNumFaces) # PRINT("otherNumFaces", otherNumVertices) # PRINT("selfNumVertices", selfNumVertices) # PRINT("otherNumVertices", otherNumVertices) # # from fipy.tools.debug import PRINT # from fipy.tools.debug import PRINT # PRINT("otherExt", otherc.exteriorFaces.value) # raw_input() # PRINT("selfExt", selfc.exteriorFaces.value) # # PRINT("self filled", selfc.faceVertexIDs.filled()) # PRINT("othe filled", otherc.faceVertexIDs.filled()) # raw_input() # # PRINT("selfc.faceVertexIDs.filled()\n",selfc.faceVertexIDs.filled()) # PRINT("flat\n",selfc.faceVertexIDs.filled()[..., # selfc.exteriorFaces.value].flatten()) # PRINT("selfc.exteriorFaces.value\n",selfc.exteriorFaces.value) # PRINT("extfaces type", type(selfc.exteriorFaces)) # PRINT("extfaces mesh", selfc.exteriorFaces.mesh) ## only try to match along the operation manifold if hasattr(self, "opManifold"): self_faces = self.opManifold(selfc) else: self_faces = selfc.exteriorFaces.value if hasattr(other, "opManifold"): other_faces = other.opManifold(otherc) else: other_faces = otherc.exteriorFaces.value ## only try to match exterior (X) vertices self_Xvertices = numerix.unique(selfc.faceVertexIDs.filled()[..., self_faces].flatten()) other_Xvertices = numerix.unique(otherc.faceVertexIDs.filled()[..., other_faces].flatten()) self_XvertexCoords = selfc.vertexCoords[..., self_Xvertices] other_XvertexCoords = otherc.vertexCoords[..., other_Xvertices] closest = numerix.nearest(self_XvertexCoords, other_XvertexCoords) # just because they're closest, doesn't mean they're close tmp = self_XvertexCoords[..., closest] - other_XvertexCoords distance = numerix.sqrtDot(tmp, tmp) # only want vertex pairs that are 100x closer than the smallest # cell-to-cell distance close = distance < resolution * min(selfc._cellToCellDistances.min(), otherc._cellToCellDistances.min()) vertexCorrelates = numerix.array((self_Xvertices[closest[close]], other_Xvertices[close])) # warn if meshes don't touch, but allow it if (selfc._numberOfVertices > 0 and otherc._numberOfVertices > 0 and vertexCorrelates.shape[-1] == 0): import warnings warnings.warn("Vertices are not aligned", UserWarning, stacklevel=4) ## compute face correlates # ensure that both sets of faceVertexIDs have the same maximum number of (masked) elements self_faceVertexIDs = selfc.faceVertexIDs other_faceVertexIDs = otherc.faceVertexIDs diff = self_faceVertexIDs.shape[0] - other_faceVertexIDs.shape[0] if diff > 0: other_faceVertexIDs = numerix.append(other_faceVertexIDs, -1 * numerix.ones((diff,) + other_faceVertexIDs.shape[1:], 'l'), axis=0) other_faceVertexIDs = MA.masked_values(other_faceVertexIDs, -1) elif diff < 0: self_faceVertexIDs = numerix.append(self_faceVertexIDs, -1 * numerix.ones((-diff,) + self_faceVertexIDs.shape[1:], 'l'), axis=0) self_faceVertexIDs = MA.masked_values(self_faceVertexIDs, -1) # want self's Faces for which all faceVertexIDs are in vertexCorrelates self_matchingFaces = numerix.in1d(self_faceVertexIDs, vertexCorrelates[0]).reshape(self_faceVertexIDs.shape).all(axis=0).nonzero()[0] # want other's Faces for which all faceVertexIDs are in vertexCorrelates other_matchingFaces = numerix.in1d(other_faceVertexIDs, vertexCorrelates[1]).reshape(other_faceVertexIDs.shape).all(axis=0).nonzero()[0] # map other's Vertex IDs to new Vertex IDs, # accounting for overlaps with self's Vertex IDs vertex_map = numerix.empty(otherNumVertices, dtype=numerix.INT_DTYPE) verticesToAdd = numerix.delete(numerix.arange(otherNumVertices), vertexCorrelates[1]) vertex_map[verticesToAdd] = numerix.arange(otherNumVertices - len(vertexCorrelates[1])) + selfNumVertices vertex_map[vertexCorrelates[1]] = vertexCorrelates[0] # calculate hashes of faceVertexIDs for comparing Faces if self_matchingFaces.shape[-1] == 0: self_faceHash = numerix.empty(self_matchingFaces.shape[:-1] + (0,), dtype="str") else: # sort each of self's Face's vertexIDs for canonical comparison self_faceHash = numerix.sort(self_faceVertexIDs[..., self_matchingFaces], axis=0) # then hash the Faces for comparison (NumPy set operations are only for 1D arrays) self_faceHash = numerix.apply_along_axis(str, axis=0, arr=self_faceHash) face_sort = numerix.argsort(self_faceHash) self_faceHash = self_faceHash[face_sort] self_matchingFaces = self_matchingFaces[face_sort] if other_matchingFaces.shape[-1] == 0: other_faceHash = numerix.empty(other_matchingFaces.shape[:-1] + (0,), dtype="str") else: # convert each of other's Face's vertexIDs to new IDs other_faceHash = vertex_map[other_faceVertexIDs[..., other_matchingFaces]] # sort each of other's Face's vertexIDs for canonical comparison other_faceHash = numerix.sort(other_faceHash, axis=0) # then hash the Faces for comparison (NumPy set operations are only for 1D arrays) other_faceHash = numerix.apply_along_axis(str, axis=0, arr=other_faceHash) face_sort = numerix.argsort(other_faceHash) other_faceHash = other_faceHash[face_sort] other_matchingFaces = other_matchingFaces[face_sort] self_matchingFaces = self_matchingFaces[numerix.in1d(self_faceHash, other_faceHash)] other_matchingFaces = other_matchingFaces[numerix.in1d(other_faceHash, self_faceHash)] faceCorrelates = numerix.array((self_matchingFaces, other_matchingFaces)) # warn if meshes don't touch, but allow it if (selfc.numberOfFaces > 0 and otherc.numberOfFaces > 0 and faceCorrelates.shape[-1] == 0): import warnings warnings.warn("Faces are not aligned", UserWarning, stacklevel=4) # map other's Face IDs to new Face IDs, # accounting for overlaps with self's Face IDs face_map = numerix.empty(otherNumFaces, dtype=numerix.INT_DTYPE) facesToAdd = numerix.delete(numerix.arange(otherNumFaces), faceCorrelates[1]) face_map[facesToAdd] = numerix.arange(otherNumFaces - len(faceCorrelates[1])) + selfNumFaces face_map[faceCorrelates[1]] = faceCorrelates[0] other_faceVertexIDs = vertex_map[otherc.faceVertexIDs[..., facesToAdd]] # ensure that both sets of cellFaceIDs have the same maximum number of (masked) elements self_cellFaceIDs = selfc.cellFaceIDs other_cellFaceIDs = face_map[otherc.cellFaceIDs] diff = self_cellFaceIDs.shape[0] - other_cellFaceIDs.shape[0] if diff > 0: other_cellFaceIDs = numerix.append(other_cellFaceIDs, -1 * numerix.ones((diff,) + other_cellFaceIDs.shape[1:], 'l'), axis=0) other_cellFaceIDs = MA.masked_values(other_cellFaceIDs, -1) elif diff < 0: self_cellFaceIDs = numerix.append(self_cellFaceIDs, -1 * numerix.ones((-diff,) + self_cellFaceIDs.shape[1:], 'l'), axis=0) self_cellFaceIDs = MA.masked_values(self_cellFaceIDs, -1) # concatenate everything and return return { 'vertexCoords': numerix.concatenate((selfc.vertexCoords, otherc.vertexCoords[..., verticesToAdd]), axis=1), 'faceVertexIDs': numerix.concatenate((self_faceVertexIDs, other_faceVertexIDs), axis=1), 'cellFaceIDs': MA.concatenate((self_cellFaceIDs, other_cellFaceIDs), axis=1) }
#### # # phloem # #### phl.mp2mesh(segs) #creates grid phl.cellsID = [phl.new2oldNodeID[xi] - 1 for xi in phl.mesh.cellFaceIDs[1] ] if(len(phl.phi.value) > len(phiOld)): #place according to index ID CphiOld = phiOld * cellVolumeOld orderedCPhi = np.concatenate((np.array([x for _,x in sorted(zip(cellsIDOld, CphiOld))]), np.full(len(phl.phi.value)-len(phiOld),0.))) orderedCPhiNew = np.take(orderedCPhi, phl.cellsID)/phl.mesh.cellVolumes growthSteps = np.append(growthSteps, [step]) phl.phi = CellVariablemod(mesh = phl.mesh, value= orderedCPhiNew , hasOld =True) phl.phi.updateOld() orderedcumulOut = np.concatenate((np.array([x for _,x in sorted(zip(cellsIDOld, cumulOutOld))]), np.full(len(phl.phi.value)-len(phiOld),0.))) orderedcumulOutNew = np.take(orderedcumulOut, phl.cellsID) cumulOut = CellVariable(mesh = phl.mesh, value= orderedcumulOutNew) orderedcumulGr = np.concatenate((np.array([x for _,x in sorted(zip(cellsIDOld, cumulGrOld))]), np.full(len(phl.phi.value)-len(phiOld),0.))) orderedcumulGrNew = np.take(orderedcumulGr, phl.cellsID) cumulGr = CellVariable(mesh = phl.mesh, value= orderedcumulGrNew) orderedcumulRm = np.concatenate((np.array([x for _,x in sorted(zip(cellsIDOld, cumulRmOld))]), np.full(len(phl.phi.value)-len(phiOld),0.))) orderedcumulRmNew = np.take(orderedcumulRm, phl.cellsID) cumulRm = CellVariable(mesh = phl.mesh, value= orderedcumulRmNew)
rho_sorted_acc_to_theta = index_sorted( xvar, yvar) # calling the index_sorted function rho_sorted_acc_to_theta = np.reshape( rho_sorted_acc_to_theta, (1, len(rho_sorted_acc_to_theta))) # reshaping into a single array theta_sorted = np.sort(theta_at_index) # theta value sorted theta_sorted = theta_sorted[ 0, :] # converting from 1Xn matrix to row array of n elements phi_new = phi_value * numerix.ones(len(theta_sorted)) m_cell_modified_sph_pol = numerix.append( numerix.asarray(r_at_index), [numerix.asarray(theta_sorted), numerix.asarray(phi_new)], axis=0) #print(numerix.shape(m_cell_modified_sph_pol)) m_cell_sph = numerix.append( m_cell_sph, (m_cell_modified_sph_pol), axis=1) #Appending the m values in spherical polar coordinate theta_sz = np.shape(theta_sorted) size = theta_sz[0] total_size = total_size + size # calculate total number of cells being covered during calculation phi_value = phi_value + delta # phi is increased by delta at end of each loop print('Total number of cells covered = ' + str(total_size))
def _getAddedMeshValues(self, other, resolution=1e-2): """Calculate the parameters to define a concatenation of `other` with `self` :Parameters: - `other`: The :class:`~fipy.meshes.numMesh.Mesh` to concatenate with `self` - `resolution`: How close vertices have to be (relative to the smallest cell-to-cell distance in either mesh) to be considered the same :Returns: A `dict` with 3 elements: the new mesh vertexCoords, faceVertexIDs, and cellFaceIDs. """ selfc = self._getConcatenableMesh() other = other._getConcatenableMesh() selfNumFaces = selfc.faceVertexIDs.shape[-1] selfNumVertices = selfc.vertexCoords.shape[-1] otherNumFaces = other.faceVertexIDs.shape[-1] otherNumVertices = other.vertexCoords.shape[-1] ## check dimensions if(selfc.vertexCoords.shape[0] != other.vertexCoords.shape[0]): raise MeshAdditionError, "Dimensions do not match" ## compute vertex correlates ## only try to match exterior (X) vertices self_Xvertices = numerix.unique(selfc._getFaceVertexIDs().filled()[..., selfc.getExteriorFaces().getValue()].flatten()) other_Xvertices = numerix.unique(other._getFaceVertexIDs().filled()[..., other.getExteriorFaces().getValue()].flatten()) self_XvertexCoords = selfc.vertexCoords[..., self_Xvertices] other_XvertexCoords = other.vertexCoords[..., other_Xvertices] # lifted from Mesh._getNearestCellID() other_vertexCoordMap = numerix.resize(other_XvertexCoords, (self_XvertexCoords.shape[-1], other_XvertexCoords.shape[0], other_XvertexCoords.shape[-1])).swapaxes(0,1) tmp = self_XvertexCoords[..., numerix.newaxis] - other_vertexCoordMap closest = numerix.argmin(numerix.dot(tmp, tmp), axis=0) # just because they're closest, doesn't mean they're close tmp = self_XvertexCoords[..., closest] - other_XvertexCoords distance = numerix.sqrtDot(tmp, tmp) # only want vertex pairs that are 100x closer than the smallest # cell-to-cell distance close = distance < resolution * min(selfc._getCellToCellDistances().min(), other._getCellToCellDistances().min()) vertexCorrelates = numerix.array((self_Xvertices[closest[close]], other_Xvertices[close])) # warn if meshes don't touch, but allow it if (selfc._getNumberOfVertices() > 0 and other._getNumberOfVertices() > 0 and vertexCorrelates.shape[-1] == 0): import warnings warnings.warn("Vertices are not aligned", UserWarning, stacklevel=4) ## compute face correlates # ensure that both sets of faceVertexIDs have the same maximum number of (masked) elements self_faceVertexIDs = selfc.faceVertexIDs other_faceVertexIDs = other.faceVertexIDs diff = self_faceVertexIDs.shape[0] - other_faceVertexIDs.shape[0] if diff > 0: other_faceVertexIDs = numerix.append(other_faceVertexIDs, -1 * numerix.ones((diff,) + other_faceVertexIDs.shape[1:]), axis=0) other_faceVertexIDs = MA.masked_values(other_faceVertexIDs, -1) elif diff < 0: self_faceVertexIDs = numerix.append(self_faceVertexIDs, -1 * numerix.ones((-diff,) + self_faceVertexIDs.shape[1:]), axis=0) self_faceVertexIDs = MA.masked_values(self_faceVertexIDs, -1) # want self's Faces for which all faceVertexIDs are in vertexCorrelates self_matchingFaces = numerix.in1d(self_faceVertexIDs, vertexCorrelates[0]).reshape(self_faceVertexIDs.shape).all(axis=0).nonzero()[0] # want other's Faces for which all faceVertexIDs are in vertexCorrelates other_matchingFaces = numerix.in1d(other_faceVertexIDs, vertexCorrelates[1]).reshape(other_faceVertexIDs.shape).all(axis=0).nonzero()[0] # map other's Vertex IDs to new Vertex IDs, # accounting for overlaps with self's Vertex IDs vertex_map = numerix.empty(otherNumVertices, dtype=int) verticesToAdd = numerix.delete(numerix.arange(otherNumVertices), vertexCorrelates[1]) vertex_map[verticesToAdd] = numerix.arange(otherNumVertices - len(vertexCorrelates[1])) + selfNumVertices vertex_map[vertexCorrelates[1]] = vertexCorrelates[0] # calculate hashes of faceVertexIDs for comparing Faces if self_matchingFaces.shape[-1] == 0: self_faceHash = numerix.empty(self_matchingFaces.shape[:-1] + (0,), dtype="str") else: # sort each of self's Face's vertexIDs for canonical comparison self_faceHash = numerix.sort(self_faceVertexIDs[..., self_matchingFaces], axis=0) # then hash the Faces for comparison (NumPy set operations are only for 1D arrays) self_faceHash = numerix.apply_along_axis(str, axis=0, arr=self_faceHash) face_sort = numerix.argsort(self_faceHash) self_faceHash = self_faceHash[face_sort] self_matchingFaces = self_matchingFaces[face_sort] if other_matchingFaces.shape[-1] == 0: other_faceHash = numerix.empty(other_matchingFaces.shape[:-1] + (0,), dtype="str") else: # convert each of other's Face's vertexIDs to new IDs other_faceHash = vertex_map[other_faceVertexIDs[..., other_matchingFaces]] # sort each of other's Face's vertexIDs for canonical comparison other_faceHash = numerix.sort(other_faceHash, axis=0) # then hash the Faces for comparison (NumPy set operations are only for 1D arrays) other_faceHash = numerix.apply_along_axis(str, axis=0, arr=other_faceHash) face_sort = numerix.argsort(other_faceHash) other_faceHash = other_faceHash[face_sort] other_matchingFaces = other_matchingFaces[face_sort] self_matchingFaces = self_matchingFaces[numerix.in1d(self_faceHash, other_faceHash)] other_matchingFaces = other_matchingFaces[numerix.in1d(other_faceHash, self_faceHash)] faceCorrelates = numerix.array((self_matchingFaces, other_matchingFaces)) # warn if meshes don't touch, but allow it if (selfc._getNumberOfFaces() > 0 and other._getNumberOfFaces() > 0 and faceCorrelates.shape[-1] == 0): import warnings warnings.warn("Faces are not aligned", UserWarning, stacklevel=4) # map other's Face IDs to new Face IDs, # accounting for overlaps with self's Face IDs face_map = numerix.empty(otherNumFaces, dtype=int) facesToAdd = numerix.delete(numerix.arange(otherNumFaces), faceCorrelates[1]) face_map[facesToAdd] = numerix.arange(otherNumFaces - len(faceCorrelates[1])) + selfNumFaces face_map[faceCorrelates[1]] = faceCorrelates[0] other_faceVertexIDs = vertex_map[other.faceVertexIDs[..., facesToAdd]] # ensure that both sets of cellFaceIDs have the same maximum number of (masked) elements self_cellFaceIDs = selfc.cellFaceIDs other_cellFaceIDs = face_map[other.cellFaceIDs] diff = self_cellFaceIDs.shape[0] - other_cellFaceIDs.shape[0] if diff > 0: other_cellFaceIDs = numerix.append(other_cellFaceIDs, -1 * numerix.ones((diff,) + other_cellFaceIDs.shape[1:]), axis=0) other_cellFaceIDs = MA.masked_values(other_cellFaceIDs, -1) elif diff < 0: self_cellFaceIDs = numerix.append(self_cellFaceIDs, -1 * numerix.ones((-diff,) + self_cellFaceIDs.shape[1:]), axis=0) self_cellFaceIDs = MA.masked_values(self_cellFaceIDs, -1) # concatenate everything and return return { 'vertexCoords': numerix.concatenate((selfc.vertexCoords, other.vertexCoords[..., verticesToAdd]), axis=1), 'faceVertexIDs': numerix.concatenate((self_faceVertexIDs, other_faceVertexIDs), axis=1), 'cellFaceIDs': MA.concatenate((self_cellFaceIDs, other_cellFaceIDs), axis=1) }
issue = [] issueRes = [] issueLoop = [] for _ in range(steps): res = 1e+10 resOld = 2e+10 loop = 0 print('step ', _) while res > max(1e-10, 1e-5 * max(phl.phi)) and loop < 1000 and resOld != res: resOld = res res = eq1.sweep(dt=dt) loop += 1 if res > max(1e-10, 1e-5 * max(phl.phi)): print('no convergence! res: ', res) issue = np.append(issue, [_]) issueRes = np.append(issueRes, [res]) issueLoop = np.append(issueLoop, [loop]) phl.phi.updateOld() cumulRm.setValue(cumulRm.value + phl.Rm.value * dt * phl.mesh.cellVolumes) cumulAn.setValue(cumulAn.value + phl.Source.value * dt * phl.mesh.cellVolumes) cumulGr.setValue(cumulGr.value + phl.GrSink.value * dt * phl.mesh.cellVolumes) loop = 0 resOld = 2e+10 res = 1e+10 while res > max(1e-10, 1e-5 * max(phl.phi)) and loop < 1000 and resOld != res:
def update_artists(self, tidx): """ Update the data of the line artists for time point Args: tidx (int): The time index """ self.logger.info( 'Updating artist_paths for time step #{}'.format(tidx)) clocktime = self.model.times[tidx] dt = int(np.ceil((clocktime - self._clock).numericValue)) H, M, S = [int(s.value) for s in clocktime.inUnitsOf('h', 'min', 's')] hmstr = self.clockstr.format(H, M, S, dt) self._clock = clocktime self.clock_artist.set_text(hmstr) self.logger.debug('Time: {}'.format(hmstr)) # self.axes_all # all_depth_axes = itertools.chain(self.axes_depth, self.axes_depth_linked.values()) # all_time_axes = itertools.chain(self.axes_time, self.axes_time_linked.values()) for artist, dpath in self.artist_paths.items(): ax = artist.axes self.logger.info('Updating {} artist {} from {}'.format( ax.name, artist, dpath)) # get the data data = self.model.get_data(dpath, tidx=tidx) data_unit = data.unit.name() self.logger.debug('Got data {} {} of unit: {!r}'.format( data.__class__.__name__, data.shape, data_unit)) # cast to units if not getattr(ax, 'data_unit_', None): ax.data_unit_ = data.unit.name() self.logger.debug('Set axes {} to unit: {}'.format( ax.name, ax.data_unit_)) # if ax in all_time_axes: # ax.set_ylabel(ax.data_unit_) ax_unit = ax.data_unit_ try: D = data.inUnitsOf(ax_unit).value self.logger.debug('Got data {} dtype {} --> {}'.format( D.dtype, D.min(), D.max())) except TypeError: self.logger.error( "Error casting {} units from {} to {}".format( dpath, data_unit, ax_unit)) # raise D = data.value # now data D is a numpy array label_base = self._get_label(dpath) # normalize if necessary data_normed = getattr(ax, 'data_normed_', False) if data_normed: Dabs = abs(D) Dabsmax = float(Dabs.max()) Dabsmin = float(Dabs.min()) Drange = Dabsmax - Dabsmin if Drange <= 1e-15: self.logger.debug('abs(data) max = min = {:.2g}'.format( Dabsmax, Dabsmin)) if Dabsmax == 0.0: Drange = 1.0 self.logger.debug( 'all data is zero, normalizing by 1.0') else: Drange = Dabsmax self.logger.debug( 'normalizing by abs(data).max = {:.2g}'.format( Dabsmax)) else: self.logger.debug( 'abs(data) range {:.2g} --> {:.2g}'.format( Dabsmin, Dabsmax)) Drange = Dabsmax D = D / Drange self.logger.info( 'Normalized {} data by {:.3g}: {:.3g} --> {:.3g}'.format( label_base, Drange, D.min(), D.max())) label = label_base + flabel(Drange) if D.max() > 1.01: self.logger.error('data max {} is not <=1.01'.format( D.max())) self.logger.warning(D) self.logger.warning('Drange: {}'.format(Drange)) self.logger.warning('Original data: {}'.format( data.inUnitsOf(ax_unit).value)) raise RuntimeError( 'Data normalization of {} failed!'.format(dpath)) else: label = label_base # now ready to set data and label if ax in self.axes_depth_all: artist.set_xdata(D) artist.set_label(label) elif ax in self.axes_time_all: xdata, ydata = artist.get_data() t = self.model.get_data('/time', tidx=tidx) artist.set_xdata(np.append(xdata, t.inUnitsOf('h').value)) artist.set_ydata(np.append(ydata, D)) artist.set_label(label + ' {}'.format(ax.data_unit_)) self.logger.debug('{} updated'.format(artist)) self.update_legends() for ax in self.axes_depth + self.axes_time: ax.relim() ax.autoscale_view(scalex=True, scaley=True)