def computeTravelTimes(self, slowness, allSensors=True): """Compute the travel times and fill data and time matrix for later use of response and Jacobian, respectively. For response only active sources are needed, for Jacobian we need all. """ # mesh = self.mesh() # better but for now input mesh mesh = self.mesh_ data = self.data_ param_markers = np.unique(mesh.cellMarkers()) param_count = len(param_markers) if len(slowness) == mesh.cellCount(): self.mapModel(slowness) elif len(slowness) == param_count: # map the regions in the mesh to slowness slow_map = pg.stdMapF_F() min_reg_num = min(param_markers) for i, si in enumerate(slowness): slow_map.insert(float(i+min_reg_num), si) mesh.mapCellAttributes(slow_map) else: raise ValueError("Wrong no of parameters. Mesh size: {}, no " "of regions: {}, and number of slowness values:" "{}".format(self.mesh().cellCount(), param_count, len(slowness))) times = pg.RVector(self.nNodes, 0.) upTags = np.zeros(self.nNodes) downTags = np.zeros(mesh.nodeCount()) for iSource in range(self.nSensors): # initial condition (reset vectors) times *= 0.0 upTags *= 0 downwind = set() source = self.data_.sensorPosition(iSource) cell = self.mesh_.findCell(source) # fill in nodes around source using local smoothness for i, n in enumerate(cell.nodes()): times[n.id()] = cell.attribute() * n.pos().distance(source) upTags[n.id()] = 1 for i, n in enumerate(cell.nodes()): tmpNodes = pg.commonNodes(n.cellSet()) for nn in tmpNodes: if not upTags[nn.id()] and not downTags[nn.id()]: downwind.add(nn) downTags[nn.id()] = 1 while len(downwind) > 0: # start fast marching fastMarch(self.mesh_, downwind, times, upTags, downTags) self.dataMatrix[iSource] = pg.interpolate(mesh, times, data.sensorPositions()) self.timeMatrix[iSource] = pg.interpolate(mesh, times, self.midPoints) sensor_idx = data("g")[data("s") == iSource]
def computeTravelTimes(self, slowness, allSensors=True): """Compute the travel times and fill data and time matrix for later use of response and Jacobian, respectively. For response only active sources are needed, for Jacobian we need all. """ # mesh = self.mesh() # better but for now input mesh mesh = self.mesh_ data = self.data_ param_markers = np.unique(mesh.cellMarkers()) param_count = len(param_markers) if len(slowness) == mesh.cellCount(): self.mapModel(slowness) elif len(slowness) == param_count: # map the regions in the mesh to slowness slow_map = pg.stdMapF_F() min_reg_num = min(param_markers) for i, si in enumerate(slowness): slow_map.insert(float(i + min_reg_num), si) mesh.mapCellAttributes(slow_map) else: raise ValueError("Wrong no of parameters. Mesh size: {}, no " "of regions: {}, and number of slowness values:" "{}".format(self.mesh().cellCount(), param_count, len(slowness))) times = pg.RVector(self.nNodes, 0.) upTags = np.zeros(self.nNodes) downTags = np.zeros(mesh.nodeCount()) for iSource in range(self.nSensors): # initial condition (reset vectors) times *= 0.0 upTags *= 0 downwind = set() source = self.data_.sensorPosition(iSource) cell = self.mesh_.findCell(source) # fill in nodes around source using local smoothness for i, n in enumerate(cell.nodes()): times[n.id()] = cell.attribute() * n.pos().distance(source) upTags[n.id()] = 1 for i, n in enumerate(cell.nodes()): tmpNodes = pg.commonNodes(n.cellSet()) for nn in tmpNodes: if not upTags[nn.id()] and not downTags[nn.id()]: downwind.add(nn) downTags[nn.id()] = 1 while len(downwind) > 0: # start fast marching fastMarch(self.mesh_, downwind, times, upTags, downTags) self.dataMatrix[iSource] = pg.interpolate(mesh, times, data.sensorPositions()) self.timeMatrix[iSource] = pg.interpolate(mesh, times, self.midPoints) sensor_idx = data("g")[data("s") == iSource]
# initialize source position and trvel time vector source = pg.RVector3(0., 0.) times = pg.RVector(mesh.nodeCount(), 0.) # initialize sets and tags upwind, downwind = set(), set() upTags, downTags = np.zeros(mesh.nodeCount()), np.zeros(mesh.nodeCount()) # define initial condition cell = mesh.findCell(source) for i, n in enumerate(cell.nodes()): times[n.id()] = cell.attribute() * n.pos().distance(source) upTags[n.id()] = 1 for i, n in enumerate(cell.nodes()): tmpNodes = pg.commonNodes(n.cellSet()) for nn in tmpNodes: if not upTags[nn.id()] and not downTags[nn.id()]: downwind.add(nn) downTags[nn.id()] = 1 # start fast marching tic = time.time() while len(downwind) > 0: fastMarch(mesh, downwind, times, upTags, downTags) print(time.time() - tic, "s") # compare with analytical solution along the x axis x = np.arange(0., 100., 0.5) t = pg.interpolate(mesh, times, pg.asvector(x), x * 0., x * 0.)
def fastMarch( mesh, downwind, times, upTags, downTags ): def findSlowness( edge ): if edge.leftCell() is None: slowness = edge.rightCell().attribute() elif edge.rightCell() is None: slowness = edge.leftCell().attribute() else: slowness = min( edge.leftCell().attribute(), edge.rightCell().attribute() ) return slowness # def findSlowness( ... ) upCandidate = [] for node in downwind: neighNodes = pg.commonNodes( node.cellSet() ) upNodes = [] for n in neighNodes: if upTags[ n.id() ]: upNodes.append( n ) if len( upNodes ) == 1: # this is the dijkstra case edge = pg.findBoundary( upNodes[0], node ) tt = times[ upNodes[0].id() ] + findSlowness( edge ) * edge.shape().domainSize() heapq.heappush( upCandidate, (tt, node) ) else: cells = node.cellSet() for c in cells: for i in range( c.nodeCount() ): edge = pg.findBoundary( c.node( i ), c.node( (i + 1 )%3 ) ) a = edge.node( 0 ) b = edge.node( 1 ) ta = times[ a.id() ] tb = times[ b.id() ] if upTags[ a.id() ] and upTags[ b.id() ]: line = pg.Line( a.pos(), b.pos() ) t = min( 1., max( 0., line.nearest( node.pos() ) ) ) ea = pg.findBoundary( a, node ) eb = pg.findBoundary( b, node ) if t == 0: slowness = findSlowness( ea ) elif t == 1: slowness = findSlowness( eb ) else: slowness = c.attribute() ttimeA = ( ta + slowness * a.pos().distance( node.pos() ) ) ttimeQ = ( ta + t*(tb-ta) ) + slowness * line( t ).distance( node.pos() ) ttimeB = ( tb + slowness * b.pos().distance( node.pos() ) ) heapq.heappush( upCandidate, (min(ttimeA,ttimeQ,ttimeB), node ) ) #for c in upCandidate: #print c[1].id(), c[0] candidate = heapq.heappop( upCandidate ) #print candidate newUpNode = candidate[1] times[ newUpNode.id() ] = candidate[0] upTags[ newUpNode.id() ] = 1 #print newUpNode downwind.remove( newUpNode ) newDownNodes = pg.commonNodes( newUpNode.cellSet() ) for nn in newDownNodes: if not upTags[ nn.id() ] and not downTags[ nn.id() ]: downwind.add( nn ) downTags[ nn.id() ] = 1
def fastMarch(mesh, downwind, times, upT, downT): """Do one front marching.""" upCandidate = [] for node in downwind: neighNodes = pg.commonNodes(node.cellSet()) upNodes = [] for n in neighNodes: if upT[n.id()]: upNodes.append(n) if len(upNodes) == 1: # the Dijkstra case edge = pg.findBoundary(upNodes[0], node) if edge is None: continue raise StandardError("no edge found") tt = times[upNodes[0].id()] + \ findSlowness(edge) * edge.shape().domainSize() # use node id additionally in case of equal travel times heapq.heappush(upCandidate, (tt, node.id(), node)) else: cells = node.cellSet() for c in cells: for i in range(c.nodeCount()): edge = pg.findBoundary(c.node(i), c.node((i + 1) % c.nodeCount())) a = edge.node(0) b = edge.node(1) ta = times[a.id()] tb = times[b.id()] if upT[a.id()] and upT[b.id()]: line = pg.Line(a.pos(), b.pos()) t = min(1., max(0., line.nearest(node.pos()))) ea = pg.findBoundary(a, node) eb = pg.findBoundary(b, node) #if ea is None or eb is None: #print(a, b, node) if t == 0: slowness = findSlowness(ea) elif t == 1: slowness = findSlowness(eb) else: slowness = c.attribute() ttimeA = (ta + slowness * a.pos().distance(node.pos())) ttimeQ = (ta + t * (tb - ta)) + \ slowness * line(t).distance(node.pos()) ttimeB = (tb + slowness * b.pos().distance(node.pos())) tmin = min(ttimeA, ttimeQ, ttimeB) heapq.heappush(upCandidate, (tmin, node.id(), node)) candidate = heapq.heappop(upCandidate) newUpNode = candidate[2] # original times[newUpNode.id()] = candidate[0] upT[newUpNode.id()] = 1 downwind.remove(newUpNode) newDownNodes = pg.commonNodes(newUpNode.cellSet()) # newUpNodeId = candidate[1] # original # times[newUpNodeId] = candidate[0] # upT[newUpNodeId] = 1 # downwind.remove(newUpNodeId) # newDownNodes = pg.commonNodes(mesh.node(newUpNodeId).cellSet()) for nn in newDownNodes: if not upT[nn.id()] and not downT[nn.id()]: downwind.add(nn) downT[nn.id()] = 1
def computeTravelTimes(self, slowness, calcOthers=False): """Compute the travel times and fill data and time matrix for later use of response and Jacobian, respectively. For response only active sources are needed, for Jacobian all. """ mesh = self.mesh() nNodes = mesh.nodeCount() midPoints = self.mesh().cellCenters() param_markers = np.unique(mesh.cellMarkers()) param_count = len(param_markers) data = self.data() if len(slowness) == mesh.cellCount(): mesh.setCellAttributes(slowness) # self.mapModel(slowness) elif len(slowness) == param_count: # map the regions in the mesh to slowness slow_map = pg.stdMapF_F() min_reg_num = min(param_markers) for i, si in enumerate(slowness): slow_map.insert(float(i + min_reg_num), si) mesh.mapCellAttributes(slow_map) else: raise ValueError("Wrong no of parameters. Mesh size: {}, no " "of regions: {}, and number of slowness values:" "{}".format(mesh.cellCount(), param_count, len(slowness))) times = pg.RVector(nNodes, 0.) upTags = np.zeros(nNodes) downTags = np.zeros(nNodes) sourceIndices = np.unique(data("s")) if calcOthers: ns = len(sourceIndices) geophoneIndices = np.setxor1d(np.arange(data.sensorCount()), sourceIndices) sourceIndices = geophoneIndices # geophoneIndices = np.unique(data("g")) if self.debug: print("{:d}-{:d}={:d}".format(data.sensorCount(), ns, len(sourceIndices))) # if self.debug: # resize not working # self.solution().resize(self.mesh().nodeCount(), self.nSensors) # print(self.solution().rows(), self.solution().cols()) for iSource in np.array(sourceIndices, dtype=int): if self.debug: print(iSource) # initial condition (reset vectors) times *= 0.0 upTags *= 0 downTags *= 0 downwind = set() source = data.sensorPosition(int(iSource)) cell = mesh.findCell(source) # fill in nodes around source using local smoothness for i, n in enumerate(cell.nodes()): times[n.id()] = cell.attribute() * n.pos().distance(source) upTags[n.id()] = 1 for i, n in enumerate(cell.nodes()): tmpNodes = pg.commonNodes(n.cellSet()) for nn in tmpNodes: if not upTags[nn.id()] and not downTags[nn.id()]: downwind.add(nn) downTags[nn.id()] = 1 while len(downwind) > 0: # start fast marching fastMarch(mesh, downwind, times, upTags, downTags) self.dataMatrix[iSource] = pg.interpolate( mesh, times, destPos=data.sensorPositions()) self.timeMatrix[iSource] = pg.interpolate(mesh, times, destPos=midPoints) if self.debug: print(self.solution().rows(), self.solution().cols()) print(len(times), self.mesh()) self.solution()[int(iSource)] = times self.solution().setCol(int(iSource), times)
def response(self, slowness): """ Response function. Returns the result of the forward calculation. Uses the shot- and sensor positions specified in the data container. """ mesh = self.mesh() param_markers = np.unique(mesh.cellMarker()) param_count = len(param_markers) if len(slowness) == mesh.cellCount(): self.mapModel(slowness) elif len(slowness) == param_count: # map the regions in the mesh to slowness slow_map = pg.stdMapF_F() min_reg_num = min(param_markers) for i, si in enumerate(slowness): slow_map.insert(float(i+min_reg_num), si) mesh.mapCellAttributes(slow_map) else: raise ValueError("Wrong no of parameters. Mesh size: {}, no " "of regions: {}, and number of slowness values:" "{}".format(self.mesh().cellCount(), param_count, len(slowness))) data = self.data() n_data = data.size() t_fmm = np.zeros(n_data) idx = 0 for source_idx in [0]: # np.unique(data("s")): # initialize source position and trvel time vector n_sensors = np.sum(data("s") == source_idx) # maybe not always same number of sensors source = data.sensorPosition(int(source_idx)) times = pg.RVector(mesh.nodeCount(), 0.) # initialize sets and tags # upwind, downwind = set(), set() downwind = set() upTags = np.zeros(mesh.nodeCount()) downTags = np.zeros(mesh.nodeCount()) # define initial condition cell = mesh.findCell(source) for i, n in enumerate(cell.nodes()): times[n.id()] = cell.attribute() * n.pos().distance(source) upTags[n.id()] = 1 for i, n in enumerate(cell.nodes()): tmpNodes = pg.commonNodes(n.cellSet()) for nn in tmpNodes: if not upTags[nn.id()] and not downTags[nn.id()]: downwind.add(nn) downTags[nn.id()] = 1 # start fast marching while len(downwind) > 0: fastMarch(mesh, downwind, times, upTags, downTags) self.timefields[source_idx] = np.array(times) sensor_idx = data("g")[data("s") == source_idx] t_fmm[idx:idx+n_sensors] = np.array( [times[mesh.findNearestNode(data.sensorPosition(int(i)))] for i in sensor_idx]) idx += n_sensors return t_fmm
def fastMarch(mesh, downwind, times, upT, downT): """WRITEME.""" upCandidate = [] # print('.', end='') for node in downwind: neighNodes = pg.commonNodes(node.cellSet()) upNodes = [] for n in neighNodes: if upT[n.id()]: upNodes.append(n) if len(upNodes) == 1: # the Dijkstra case edge = pg.findBoundary(upNodes[0], node) tt = times[upNodes[0].id()] + \ findSlowness(edge) * edge.shape().domainSize() heapq.heappush(upCandidate, (tt, node)) else: cells = node.cellSet() for c in cells: for i in range(c.nodeCount()): edge = pg.findBoundary(c.node(i), c.node((i + 1) % 3)) a = edge.node(0) b = edge.node(1) ta = times[a.id()] tb = times[b.id()] if upT[a.id()] and upT[b.id()]: line = pg.Line(a.pos(), b.pos()) t = min(1., max(0., line.nearest(node.pos()))) ea = pg.findBoundary(a, node) eb = pg.findBoundary(b, node) if t == 0: slowness = findSlowness(ea) elif t == 1: slowness = findSlowness(eb) else: slowness = c.attribute() ttimeA = (ta + slowness * a.pos().distance(node.pos())) ttimeQ = (ta + t * (tb - ta)) + \ slowness * line(t).distance(node.pos()) ttimeB = (tb + slowness * b.pos().distance(node.pos())) heapq.heappush(upCandidate, (min(ttimeA, ttimeQ, ttimeB), node)) # for c in upCandidate: # print c[1].id(), c[0] candidate = heapq.heappop(upCandidate) # print candidate newUpNode = candidate[1] times[newUpNode.id()] = candidate[0] upT[newUpNode.id()] = 1 # print newUpNode downwind.remove(newUpNode) newDownNodes = pg.commonNodes(newUpNode.cellSet()) for nn in newDownNodes: if not upT[nn.id()] and not downT[nn.id()]: downwind.add(nn) downT[nn.id()] = 1
def test(): """WRITEME.""" mesh = pg.Mesh('mesh/test2d') mesh.createNeighbourInfos() print(mesh) source = pg.RVector3(-80, 0.) times = pg.RVector(mesh.nodeCount(), 0.) for c in mesh.cells(): if c.marker() == 1: c.setAttribute(1.) elif c.marker() == 2: c.setAttribute(0.5) # c.setAttribute(abs(1./c.center()[1])) fig = plt.figure() ax = fig.subplot(1, 1, 1) anaTimes = pg.RVector(mesh.nodeCount(), 0.0) for n in mesh.nodes(): anaTimes[n.id()] = source.distance(n.pos()) # d = pg.DataContainer() # dijk = pg.TravelTimeDijkstraModelling(mesh, d) # upwind = set() downwind = set() upTags = np.zeros(mesh.nodeCount()) downTags = np.zeros(mesh.nodeCount()) # define initial condition cell = mesh.findCell(source) for n in cell.nodes(): times[n.id()] = cell.attribute() * n.pos().distance(source) upTags[n.id()] = 1 for n in cell.nodes(): tmpNodes = pg.commonNodes(n.cellSet()) for nn in tmpNodes: if not upTags[nn.id()] and not downTags[nn.id()]: downwind.add(nn) downTags[nn.id()] = 1 # start fast marching tic = time.time() while len(downwind) > 0: # model = pg.RVector(mesh.cellCount(), 0.0) # for c in upwind: model.setVal(2, c.id()) # for c in downwind: model.setVal(1, c.id()) # drawMesh(a, mesh) # a.plot(source[0], source[1], 'x') # for c in mesh.cells(): # a.text(c.center()[0],c.center()[1], str(c.id())) # for n in mesh.nodes(): # if upTags[n.id()]: # a.plot(n.pos()[0], n.pos()[1], 'o', color='black') # mindist = 9e99 # for n in downwind: # a.plot(n.pos()[0], n.pos()[1], 'o', color='white') # if n.pos().distance(source) < mindist: # mindist = n.pos().distance(source) # nextPredict = n # print "next predicted ", n.id(), mindist # a.plot(nextPredict.pos()[0], nextPredict.pos()[1], # 'o', color='green') # drawField(a, mesh, times) # drawField(a, mesh, anaTimes, colors = 'white') # a.figure.canvas.draw() # a.figure.show() # raw_input('Press Enter...') # a.clear() fastMarch(mesh, downwind, times, upTags, downTags) print(time.time() - tic, "s") drawMesh(ax, mesh) drawField(ax, mesh, times, filled=True)
mesh.mapCellAttributes(slomap) # map values to attributes using map ############################################################################### # We initialize the source position and the travel time vector # initialize sets and tags and define the initial condition. source = pg.RVector3(0., 0.) # does not have to be a node! times = pg.RVector(mesh.nodeCount(), 0.) upwind, downwind = set(), set() upTags, downTags = np.zeros(mesh.nodeCount()), np.zeros(mesh.nodeCount()) cell = mesh.findCell(source) for i, n in enumerate(cell.nodes()): times[n.id()] = cell.attribute() * n.pos().distance(source) upTags[n.id()] = 1 for i, n in enumerate(cell.nodes()): tmpNodes = pg.commonNodes(n.cellSet()) for nn in tmpNodes: if not upTags[nn.id()] and not downTags[nn.id()]: downwind.add(nn) downTags[nn.id()] = 1 ############################################################################### # Then we start marching until all fields are filled. tic = time.time() while len(downwind) > 0: fastMarch(mesh, downwind, times, upTags, downTags) print(time.time() - tic, "s") ############################################################################### # First, we plot the traveltime field and streamlines
def computeTravelTimes(self, slowness, calcOthers=False): """Compute the travel times and fill data and time matrix for later use of response and Jacobian, respectively. For response only active sources are needed, for Jacobian all. """ mesh = self.mesh() nNodes = mesh.nodeCount() midPoints = self.mesh().cellCenters() param_markers = np.unique(mesh.cellMarkers()) param_count = len(param_markers) data = self.data() if len(slowness) == mesh.cellCount(): mesh.setCellAttributes(slowness) # self.mapModel(slowness) elif len(slowness) == param_count: # map the regions in the mesh to slowness slow_map = pg.stdMapF_F() min_reg_num = min(param_markers) for i, si in enumerate(slowness): slow_map.insert(float(i+min_reg_num), si) mesh.mapCellAttributes(slow_map) else: raise ValueError("Wrong no of parameters. Mesh size: {}, no " "of regions: {}, and number of slowness values:" "{}".format(mesh.cellCount(), param_count, len(slowness))) times = pg.RVector(nNodes, 0.) upTags = np.zeros(nNodes) downTags = np.zeros(nNodes) sourceIndices = np.unique(data("s")) if calcOthers: ns = len(sourceIndices) geophoneIndices = np.setxor1d(np.arange(data.sensorCount()), sourceIndices) sourceIndices = geophoneIndices # geophoneIndices = np.unique(data("g")) if self.debug: print("{:d}-{:d}={:d}".format( data.sensorCount(), ns, len(sourceIndices))) # if self.debug: # resize not working # self.solution().resize(self.mesh().nodeCount(), self.nSensors) # print(self.solution().rows(), self.solution().cols()) for iSource in np.array(sourceIndices, dtype=int): if self.debug: print(iSource) # initial condition (reset vectors) times *= 0.0 upTags *= 0 downTags *= 0 downwind = set() source = data.sensorPosition(int(iSource)) cell = mesh.findCell(source) # fill in nodes around source using local smoothness for i, n in enumerate(cell.nodes()): times[n.id()] = cell.attribute() * n.pos().distance(source) upTags[n.id()] = 1 for i, n in enumerate(cell.nodes()): tmpNodes = pg.commonNodes(n.cellSet()) for nn in tmpNodes: if not upTags[nn.id()] and not downTags[nn.id()]: downwind.add(nn) downTags[nn.id()] = 1 while len(downwind) > 0: # start fast marching fastMarch(mesh, downwind, times, upTags, downTags) self.dataMatrix[iSource] = pg.interpolate( mesh, times, destPos=data.sensorPositions()) self.timeMatrix[iSource] = pg.interpolate( mesh, times, destPos=midPoints) if self.debug: print(self.solution().rows(), self.solution().cols()) print(len(times), self.mesh()) self.solution()[int(iSource)] = times self.solution().setCol(int(iSource), times)