예제 #1
0
def divergenceCell(c, F):
    ret = 0
    for bi in range(c.boundaryCount()):
        b = pg.findBoundary(c.boundaryNodes(bi))
        # print(b.norm(c).dot(F[b.id()]))
        ret += b.norm(c).dot(F[b.id()]) * b.size()

    return ret
예제 #2
0
def divergenceCell(c, F):
    ret = 0
    for bi in range(c.boundaryCount()):
        b = pg.findBoundary(c.boundaryNodes(bi))
        # print(b.norm(c).dot(F[b.id()]))
        ret += b.norm(c).dot(F[b.id()]) * b.size()

    return ret
예제 #3
0
def diffusionConvectionKernel(mesh,
                              a=None,
                              f=None,
                              uBoundaries=None,
                              duBoundaries=None,
                              fn=None,
                              vel=0,
                              u0=0,
                              scheme='CDS',
                              sparse=False,
                              time=0.0,
                              userData=None):
    """
        Peclet Number - ratio between convection/diffusion * Length

        Advection .. forced convection
    """
    if a is None:
        a = pg.Vector(mesh.boundaryCount(), 1.0)

    AScheme = None
    if scheme == 'CDS':
        # CDS - central differences scheme ..
        # .. maybe irregular for Peclet-number |F/D| > 2
        # diffusion dominant
        # Error of order 2
        AScheme = lambda peclet_: 1.0 - 0.5 * abs(peclet_)
    elif scheme == 'UDS':
        # UDS - upwind scheme
        # Convection dominant
        # Error of order 1
        AScheme = lambda peclet_: 1.0
    elif scheme == 'HS':
        # HS - hybrid scheme.
        # Diffusion dominant for Peclet-number |(F/D)| < 2
        # Convection dominant else
        AScheme = lambda peclet_: max(0.0, 1.0 - 0.5 * abs(peclet_))
    elif scheme == 'PS':
        # PS - power-law scheme.
        # Identical to HS for Peclet-number |(F/D)| > 10 and near to ES else
        AScheme = lambda peclet_: max(0.0, (1.0 - 0.1 * abs(peclet_))**5.0)
    elif scheme == 'ES':
        # ES - exponential scheme
        # Only stationary one-dimensional but exact solution
        AScheme = lambda peclet_: (peclet_) / (np.exp(abs(peclet_))-1.0) \
            if peclet_ != 0.0 else 1
    else:
        raise

    useHalfBoundaries = False

    dof = mesh.cellCount()

    if not uBoundaries:
        uBoundaries = []
    if not duBoundaries:
        duBoundaries = []

    if useHalfBoundaries:
        dof = mesh.cellCount() + len(uBoundaries)

    S = None
    if sparse:
        S = pg.matrix.SparseMapMatrix(dof, dof, 0)
    else:
        S = np.zeros((dof, dof))

    rhsBoundaryScales = np.zeros(dof)

    # we need this to fast identify uBoundary and value by boundary
    uBoundaryID = []
    uBoundaryVals = [None] * mesh.boundaryCount()
    for i, [boundary, val] in enumerate(uBoundaries):
        if not isinstance(boundary, pg.core.Boundary):
            raise BaseException("Please give boundary, value list")
        uBoundaryID.append(boundary.id())
        uBoundaryVals[boundary.id()] = val
    duBoundaryID = []
    duBoundaryVals = [None] * mesh.boundaryCount()
    for i, [boundary, val] in enumerate(duBoundaries):
        if not isinstance(boundary, pg.core.Boundary):
            raise BaseException("Please give boundary, value list")
        duBoundaryID.append(boundary.id())
        duBoundaryVals[boundary.id()] = val

    for cell in mesh.cells():

        for bi in range(cell.boundaryCount()):
            boundary = pg.findBoundary(cell.boundaryNodes(bi))

            ncell = boundary.leftCell()
            if ncell == cell:
                ncell = boundary.rightCell()

            v = findVelocity(mesh, vel, boundary, cell, ncell)

            # Convection part
            F = boundary.norm(cell).dot(v) * boundary.size()

            # Diffusion part
            D = findDiffusion(mesh, a, boundary, cell, ncell)

            aB = D * AScheme(F / D) + max(-F, 0.0)

            aB /= cell.size()

            #            print(cell.center(), boundary.center(), boundary.norm(cell), aB)
            if ncell:
                # no boundary
                if sparse:
                    S.addVal(cell.id(), ncell.id(), -aB)
                    S.addVal(cell.id(), cell.id(), +aB)
                else:
                    S[cell.id(), ncell.id()] -= aB
                    S[cell.id(), cell.id()] += aB

            elif not useHalfBoundaries:

                if boundary.id() in uBoundaryID:
                    val = pg.solver.generateBoundaryValue(
                        boundary,
                        uBoundaryVals[boundary.id()],
                        time=time,
                        userData=userData)

                    if sparse:
                        S.addVal(cell.id(), cell.id(), aB)
                    else:
                        S[cell.id(), cell.id()] += aB

                    rhsBoundaryScales[cell.id()] += aB * val

                if boundary.id() in duBoundaryID:
                    # Neumann boundary condition
                    val = pg.solver.generateBoundaryValue(
                        boundary,
                        duBoundaryVals[boundary.id()],
                        time=time,
                        userData=userData)
                    if sparse:
                        # amount of flow through the boundary
                        S.addVal(cell.id(), cell.id(),
                                 val * boundary.size() / cell.size())
                    else:
                        S[cell.id(), cell.id()] += val * boundary.size() / \
                          cell.size()

        if fn is not None:
            if sparse:
                S.addVal(cell.id(), cell.id(), -fn[cell.id()])
                # * cell.shape().domainSize())
            else:
                S[cell.id(), cell.id()] -= fn[cell.id()]
                # * cell.shape().domainSize()

    if useHalfBoundaries:
        for i, [b, val] in enumerate(uDirBounds):  #  not defined!
            bIdx = mesh.cellCount() + i

            c = b.leftCell()
            if not c:
                c = b.rightCell()

            if c:
                n = b.norm(c)
                v = findVelocity(mesh, vel, b, c, nc=None)
                F = n.dot(v) * b.size()

                D = findDiffusion(mesh, a, b, c)
                aB = D * AScheme(F / D) + max(-F, 0.0)

                if useHalfBoundaries:
                    if sparse:
                        S.setVal(c.id(), c.id(), 1.)
                        S.addVal(c.id(), bIdx, -aB)
                    else:
                        S[bIdx, bIdx] = 1.
                        S[c.id(), bIdx] -= aB

                    rhsBoundaryScales[bIdx] = aB

    return S, rhsBoundaryScales
예제 #4
0
    def _trace_back(self, sensor_idx, source_idx, epsilon=1e-5):
        """
        Traces a ray backwards through the mesh from a particular sensor
        towards the seismic source.
        """
        msh = self.mesh()
        self.poslist = []
        self._jac[source_idx] = np.zeros((msh.cellCount()))

        pos_offset = pg.RVector3(0., epsilon, 0.)

        sensor_pos = self.data().sensorPosition(sensor_idx)
        source_pos = self.data().sensorPosition(source_idx)
        source_node = msh.findNearestNode(source_pos)

        current_cell = msh.findCell(sensor_pos - pos_offset)
        new_cell = current_cell
        ray_origin = sensor_pos - pos_offset
        was_on_edge = False
        while ray_origin.dist(source_pos) > epsilon:
            self.poslist.append(ray_origin)
            if new_cell is None:
                print("Ended up outside mesh!")
                print("Last valid cell: {}".format(current_cell))
                break
#                other_boundary = pg.findBoundary(
#                    current_cell.node((node_idx+2)%nnodes),
#                    current_cell.node((node_idx+1)%nnodes))
#                new_cell = self._get_new_cell(other_boundary, current_cell)
#                gradient = current_cell.node((node_idx+1)%nnodes).pos() -
#                current_cell.node(node_idx).pos()
            else:
                old_cell_id = current_cell.id()  # going to slower cell
                #                if new_cell.attribute() > current_cell.attribute():
                #                    gradient = current_cell.grad(current_cell.center(),
                #                                             self.timefields[source_idx])
                #                else:
                #                    gradient = new_cell.grad(current_cell.center(),
                #                                             self.timefields[source_idx])
                current_cell = new_cell

                if not was_on_edge:
                    gradient = current_cell.grad(current_cell.center(),
                                                 self.timefields[source_idx])
                else:
                    was_on_edge = False
            print("Current cell: {}".format(current_cell.id()))
            #            gradient = current_cell.grad(current_cell.center(),
            #                                         self.timefields[source_idx])
            #            gradient_norm = -gradient / gradient.length()
            gradient_norm = -gradient.norm()
            nnodes = current_cell.nodeCount()
            params = np.zeros((nnodes, 2))
            gradient_line = pg.Line(ray_origin, ray_origin + gradient_norm)
            for i in range(nnodes):
                if current_cell.node(i).id() == source_node:
                    print("cell closest to source")
                    params[i, :] = [ray_origin.dist(source_pos), i]
                    break
                edge = pg.Line(
                    current_cell.node(i).pos(),
                    current_cell.node((i + 1) % nnodes).pos())
                #                print("Grad: {}".format(gradient_line))
                #                print("Edge: {}".format(edge))

                s_t = self._intersect_lines(gradient_line, edge)

                #                print("s_t: {}".format(s_t))
                params[i, :] = [s_t[0], i]

            t, node_idx, stay_on_edge = self._check_param(params)
            print("Stay on edge: {}".format(stay_on_edge))

            boundary = pg.findBoundary(
                current_cell.node(node_idx),
                current_cell.node((node_idx + 1) % nnodes))
            if stay_on_edge:
                # break
                next_node_id, next_cell_id = self._get_next_node(
                    boundary, current_cell.id(), ray_origin, gradient_norm)
                t = ray_origin.dist(msh.node(next_node_id).pos())
                print("Current: {}, next: {}, t: {}".format(
                    current_cell.id(), next_cell_id, t))
                print("")
                self._jac[source_idx][next_cell_id] += t
                temp = msh.node(next_node_id).pos() - ray_origin
                ray_origin = msh.node(next_node_id).pos() + \
                    1e-5 * temp.norm() - pg.RVector3(0.0, 1e-6, 0.0)
                # new_cell = mesh.cell(next_cell_id)
                new_cell = msh.findCell(ray_origin)
                was_on_edge = True


#                print("next_cell_id: {}, findCell: {}".format(
#                    next_cell_id, new_cell.id()))
            else:
                # print("params: {}, t: {}, i: {}".format(params, t, node_idx))
                # Save distance travelled in the cell (t) and update origin
                self._jac[source_idx][current_cell.id()] = t
                ray_origin = gradient_line.lineAt(t)
                #            print("ray origin: {}".format(ray_origin))
                new_cell = self._get_new_cell(boundary, current_cell)
            if new_cell.id() == old_cell_id:
                # If we keep jumping back and forth between two cells.
                print("Jumping back and forth...")
                break

        return self._jac
예제 #5
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
예제 #6
0
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
예제 #7
0
def calcSeismics(meshIn, vP):
    """Do seismic computations."""
    meshSeis = meshIn.createH2()
    meshSeis = mt.appendTriangleBoundary(meshSeis,
                                         xbound=25,
                                         ybound=22.0,
                                         marker=1,
                                         quality=32.0,
                                         area=0.3,
                                         smooth=True,
                                         markerBoundary=1,
                                         isSubSurface=False,
                                         verbose=False)
    print(meshSeis)
    meshSeis = meshSeis.createH2()
    meshSeis = meshSeis.createH2()
    # meshSeis = meshSeis.createP2()

    meshSeis.smooth(1, 1, 1, 4)
    vP = pg.interpolate(meshIn, vP, meshSeis.cellCenters())

    mesh = meshSeis
    vP = pg.solver.fillEmptyToCellArray(mesh, vP)

    print(mesh)
    # ax, cbar = pg.show(mesh, data=vP)
    # pg.show(mesh, axes=ax)

    geophPointsX = np.arange(-19, 19.1, 1)
    geophPoints = np.vstack((geophPointsX, np.zeros(len(geophPointsX)))).T
    sourcePos = geophPoints[4]

    c = mesh.findCell(sourcePos)
    h1 = pg.findBoundary(c.boundaryNodes(0)).size()
    h2 = pg.findBoundary(c.boundaryNodes(1)).size()
    h3 = pg.findBoundary(c.boundaryNodes(2)).size()
    print([h1, h2, h3])
    h = pg.math.median([h1, h2, h3])

    # h = pg.math.median(mesh.boundarySizes())
    f0scale = 0.25
    cfl = 0.5
    dt = cfl * h / max(vP)
    print("Courant-Friedrich-Lewy number:", cfl)

    tmax = 40. / min(vP)
    times = np.arange(0.0, tmax, dt)

    solutionName = createCacheName('seis', mesh, times) + "cfl-" + str(cfl)
    try:
        # u = pg.load(solutionName + '.bmat')
        uI = pg.load(solutionName + 'I.bmat')
    except Exception as e:
        print(e)
        f0 = f0scale * 1. / dt
        print("h:", round(h, 2), "dt:", round(dt, 5), "1/dt:",
              round(1 / dt, 1), "f0", round(f0, 2), "Wavelength: ",
              round(max(vP) / f0, 2), " m")

        uSource = ricker(times, f0, t0=1. / f0)

        plt.figure()
        plt.plot(times, uSource, '-*')
        plt.show(block=0)
        plt.pause(0.01)
        u = solvePressureWave(mesh,
                              vP,
                              times,
                              sourcePos=sourcePos,
                              uSource=uSource,
                              verbose=10)

        u.save(solutionName)
        uI = pg.Matrix()
        print("interpolate node to cell data ... ")
        pg.interpolate(mesh, u, mesh.cellCenters(), uI)
        print("... done")
        uI.save(solutionName + 'I')

#    nodes = [mesh.findNearestNode(p) for p in geophPoints]
#    fig = plt.figure()
#    axs = fig.add_subplot(1,1,1)
#    drawSeismogramm(axs, mesh, u, nodes, dt, i=None)
#    plt.show()

    dpi = 92
    scale = 1
    fig = plt.figure(facecolor='white',
                     figsize=(scale * 800 / dpi, scale * 490 / dpi),
                     dpi=dpi)
    ax = fig.add_subplot(1, 1, 1)
    gci = pg.viewer.mpl.drawModel(ax,
                                  mesh,
                                  data=uI[0],
                                  cMin=-1,
                                  cMax=1,
                                  cmap='bwr')
    pg.viewer.mpl.drawMeshBoundaries(ax, meshIn, hideMesh=1)
    ax.set_xlim((-20, 20))
    ax.set_ylim((-15, 0))
    ax.set_ylabel('Depth [m]')
    ax.set_xlabel('$x$ [m]')

    ticks = ax.yaxis.get_majorticklocs()
    tickLabels = []
    for t in ticks:
        tickLabels.append(str(int(abs(t))))

    ax.set_yticklabels(tickLabels)

    plt.tight_layout()

    #    ax, cbar = pg.show(mesh, data=vP)
    #    pg.showNow()
    #    ax = fig.add_subplot(1,1,1)

    def animate(i):
        i = i * 5
        if i > len(uI) - 1:
            return
        print("Frame:", i, "/", len(uI))
        ui = uI[i]
        ui = ui / max(pg.abs(ui))
        ui = pg.logDropTol(ui, 1e-2)
        cMax = max(pg.abs(ui))

        pg.viewer.mpl.setMappableData(gci,
                                      ui,
                                      cMin=-cMax,
                                      cMax=cMax,
                                      logScale=False)
        # plt.pause(0.001)

    anim = animation.FuncAnimation(fig,
                                   animate,
                                   frames=int(len(uI) / 5),
                                   interval=0.001,
                                   repeat=0)  # , blit=True)
    out = 'seis' + str(f0scale) + "cfl-" + str(cfl)
    anim.save(out + ".mp4",
              writer=None,
              fps=20,
              dpi=dpi,
              codec=None,
              bitrate=24 * 1024,
              extra_args=None,
              metadata=None,
              extra_anim=None,
              savefig_kwargs=None)
    try:
        print("create frames ... ")
        os.system('mkdir -p anim-' + out)
        os.system('ffmpeg -i ' + out + '.mp4 anim-' + out + '/movie%d.jpg')
    except:
        pass
예제 #8
0
    def _trace_back(self, sensor_idx, source_idx, epsilon=1e-5):
        """
        Traces a ray backwards through the mesh from a particular sensor
        towards the seismic source.
        """
        msh = self.mesh()
        self.poslist = []
        self._jac[source_idx] = np.zeros((msh.cellCount()))

        pos_offset = pg.RVector3(0., epsilon, 0.)

        sensor_pos = self.data().sensorPosition(sensor_idx)
        source_pos = self.data().sensorPosition(source_idx)
        source_node = msh.findNearestNode(source_pos)

        current_cell = msh.findCell(sensor_pos - pos_offset)
        new_cell = current_cell
        ray_origin = sensor_pos - pos_offset
        was_on_edge = False
        while ray_origin.dist(source_pos) > epsilon:
            self.poslist.append(ray_origin)
            if new_cell is None:
                print("Ended up outside mesh!")
                print("Last valid cell: {}".format(current_cell))
                break
#                other_boundary = pg.findBoundary(
#                    current_cell.node((node_idx+2)%nnodes),
#                    current_cell.node((node_idx+1)%nnodes))
#                new_cell = self._get_new_cell(other_boundary, current_cell)
#                gradient = current_cell.node((node_idx+1)%nnodes).pos() -
#                current_cell.node(node_idx).pos()
            else:
                old_cell_id = current_cell.id()  # going to slower cell
#                if new_cell.attribute() > current_cell.attribute():
#                    gradient = current_cell.grad(current_cell.center(),
#                                             self.timefields[source_idx])
#                else:
#                    gradient = new_cell.grad(current_cell.center(),
#                                             self.timefields[source_idx])
                current_cell = new_cell

                if not was_on_edge:
                    gradient = current_cell.grad(
                        current_cell.center(), self.timefields[source_idx])
                else:
                    was_on_edge = False
            print("Current cell: {}".format(current_cell.id()))
#            gradient = current_cell.grad(current_cell.center(),
#                                         self.timefields[source_idx])
#            gradient_norm = -gradient / gradient.length()
            gradient_norm = -gradient.norm()
            nnodes = current_cell.nodeCount()
            params = np.zeros((nnodes, 2))
            gradient_line = pg.Line(ray_origin, ray_origin + gradient_norm)
            for i in range(nnodes):
                if current_cell.node(i).id() == source_node:
                    print("cell closest to source")
                    params[i, :] = [ray_origin.dist(source_pos), i]
                    break
                edge = pg.Line(current_cell.node(i).pos(),
                               current_cell.node((i+1) % nnodes).pos())
#                print("Grad: {}".format(gradient_line))
#                print("Edge: {}".format(edge))

                s_t = self._intersect_lines(gradient_line, edge)

#                print("s_t: {}".format(s_t))
                params[i, :] = [s_t[0], i]

            t, node_idx, stay_on_edge = self._check_param(params)
            print("Stay on edge: {}".format(stay_on_edge))

            boundary = pg.findBoundary(
                current_cell.node(node_idx),
                current_cell.node((node_idx+1) % nnodes))
            if stay_on_edge:
                # break
                next_node_id, next_cell_id = self._get_next_node(
                    boundary, current_cell.id(), ray_origin, gradient_norm)
                t = ray_origin.dist(msh.node(next_node_id).pos())
                print("Current: {}, next: {}, t: {}".format(
                    current_cell.id(), next_cell_id, t))
                print("")
                self._jac[source_idx][next_cell_id] += t
                temp = msh.node(next_node_id).pos() - ray_origin
                ray_origin = msh.node(next_node_id).pos() + \
                    1e-5 * temp.norm() - pg.RVector3(0.0, 1e-6, 0.0)
                # new_cell = mesh.cell(next_cell_id)
                new_cell = msh.findCell(ray_origin)
                was_on_edge = True
#                print("next_cell_id: {}, findCell: {}".format(
#                    next_cell_id, new_cell.id()))
            else:
                # print("params: {}, t: {}, i: {}".format(params, t, node_idx))
                # Save distance travelled in the cell (t) and update origin
                self._jac[source_idx][current_cell.id()] = t
                ray_origin = gradient_line.lineAt(t)
#            print("ray origin: {}".format(ray_origin))
                new_cell = self._get_new_cell(boundary, current_cell)
            if new_cell.id() == old_cell_id:
                # If we keep jumping back and forth between two cells.
                print("Jumping back and forth...")
                break

        return self._jac
예제 #9
0
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
예제 #10
0
파일: seismics.py 프로젝트: gimli-org/gimli
def calcSeismics(meshIn, vP):
    """Do seismic computations."""
    meshSeis = meshIn.createH2()
    meshSeis = mt.appendTriangleBoundary(
            meshSeis, xbound=25, ybound=22.0, marker=1, quality=32.0, area=0.3,
            smooth=True, markerBoundary=1, isSubSurface=False, verbose=False)
    print(meshSeis)
    meshSeis = meshSeis.createH2()
    meshSeis = meshSeis.createH2()
    # meshSeis = meshSeis.createP2()

    meshSeis.smooth(1, 1, 1, 4)
    vP = pg.interpolate(meshIn, vP, meshSeis.cellCenters())

    mesh = meshSeis
    vP = pg.solver.fillEmptyToCellArray(mesh, vP)

    print(mesh)
    # ax, cbar = pg.show(mesh, data=vP)
    # pg.show(mesh, axes=ax)

    geophPointsX = np.arange(-19, 19.1, 1)
    geophPoints = np.vstack((geophPointsX, np.zeros(len(geophPointsX)))).T
    sourcePos = geophPoints[4]

    c = mesh.findCell(sourcePos)
    h1 = pg.findBoundary(c.boundaryNodes(0)).size()
    h2 = pg.findBoundary(c.boundaryNodes(1)).size()
    h3 = pg.findBoundary(c.boundaryNodes(2)).size()
    print([h1, h2, h3])
    h = pg.median([h1, h2, h3])

    # h = pg.median(mesh.boundarySizes())
    f0scale = 0.25
    cfl = 0.5
    dt = cfl * h / max(vP)
    print("Courant-Friedrich-Lewy number:", cfl)

    tmax = 40./min(vP)
    times = np.arange(0.0, tmax, dt)

    solutionName = createCacheName('seis', mesh, times) + "cfl-" + str(cfl)
    try:
        # u = pg.load(solutionName + '.bmat')
        uI = pg.load(solutionName + 'I.bmat')
    except Exception as e:
        print(e)
        f0 = f0scale * 1./dt
        print("h:", round(h, 2),
              "dt:", round(dt, 5),
              "1/dt:", round(1/dt, 1),
              "f0", round(f0, 2),
              "Wavelength: ", round(max(vP)/f0, 2), " m")

        uSource = ricker(times, f0, t0=1./f0)

        plt.figure()
        plt.plot(times, uSource, '-*')
        plt.show(block=0)
        plt.pause(0.01)
        u = solvePressureWave(mesh, vP, times, sourcePos=sourcePos,
                              uSource=uSource, verbose=10)

        u.save(solutionName)
        uI = pg.RMatrix()
        print("interpolate node to cell data ... ")
        pg.interpolate(mesh, u, mesh.cellCenters(), uI)
        print("... done")
        uI.save(solutionName+'I')

#    nodes = [mesh.findNearestNode(p) for p in geophPoints]
#    fig = plt.figure()
#    axs = fig.add_subplot(1,1,1)
#    drawSeismogramm(axs, mesh, u, nodes, dt, i=None)
#    plt.show()

    dpi = 92
    scale = 1
    fig = plt.figure(facecolor='white',
                     figsize=(scale*800/dpi, scale*490/dpi), dpi=dpi)
    ax = fig.add_subplot(1, 1, 1)
    gci = pg.mplviewer.drawModel(ax, mesh, data=uI[0],
                                 cMin=-1, cMax=1, cmap='bwr')
    pg.mplviewer.drawMeshBoundaries(ax, meshIn, hideMesh=1)
    ax.set_xlim((-20, 20))
    ax.set_ylim((-15, 0))
    ax.set_ylabel('Depth [m]')
    ax.set_xlabel('$x$ [m]')

    ticks = ax.yaxis.get_majorticklocs()
    tickLabels = []
    for t in ticks:
        tickLabels.append(str(int(abs(t))))

    ax.set_yticklabels(tickLabels)

    plt.tight_layout()
#    ax, cbar = pg.show(mesh, data=vP)
#    pg.showNow()
#    ax = fig.add_subplot(1,1,1)

    def animate(i):
        i = i*5
        if i > len(uI)-1:
            return
        print("Frame:", i, "/", len(uI))
        ui = uI[i]
        ui = ui / max(pg.abs(ui))
        ui = pg.logDropTol(ui, 1e-2)
        cMax = max(pg.abs(ui))

        pg.mplviewer.setMappableData(gci, ui,
                                     cMin=-cMax, cMax=cMax,
                                     logScale=False)
        # plt.pause(0.001)

    anim = animation.FuncAnimation(fig, animate,
                                   frames=int(len(uI)/5),
                                   interval=0.001, repeat=0)  # , blit=True)
    out = 'seis' + str(f0scale) + "cfl-" + str(cfl)
    anim.save(out + ".mp4", writer=None, fps=20, dpi=dpi, codec=None,
              bitrate=24*1024, extra_args=None, metadata=None,
              extra_anim=None, savefig_kwargs=None)
    try:
        print("create frames ... ")
        os.system('mkdir -p anim-' + out)
        os.system('ffmpeg -i ' + out + '.mp4 anim-' + out + '/movie%d.jpg')
    except:
        pass
예제 #11
0
def diffusionConvectionKernel(
        mesh,
        a=None,
        b=0.0,
        uB=None,
        duB=None,
        vel=0,
        # u0=0,
        fn=None,
        scheme='CDS',
        sparse=False,
        time=0.0,
        userData=None):
    """
    Generate system matrix for diffusion and convection in a velocity field.

    Particle concentration u inside a velocity field.

    Peclet Number - ratio between convection/diffusion = F/D
        F = velocity flow trough volume boundary,
        D = diffusion coefficient

    Parameters
    ----------
    mesh : :gimliapi:`GIMLI::Mesh`
        Mesh represents spatial discretization of the calculation domain

    a   : value | array | callable(cell, userData)
        Diffusion coefficient per cell

    b   : value | array | callable(cell, userData)
        TODO What is b

    fn   : iterable(cell)
        TODO What is fn

    vel : ndarray (N,dim) | RMatrix(N,dim)
        velocity field [[v_i,]_j,] with i=[1..3] for the mesh dimension
        and j = [0 .. N-1] per Cell or per Node so N is either
        mesh.cellCount() or mesh.nodeCount()

    scheme : str [CDS]
        Finite volume scheme

        * CDS -- Central Difference Scheme.
            maybe irregular for Peclet no. |F/D| > 2
            Diffusion dominant. Error of order 2
        * UDS -- Upwind Scheme.
            Convection dominant. Error of order 1
        * HS -- Hybrid Scheme.
            Diffusion dominant for Peclet-number |(F/D)| < 2
            Convection dominant else.
        * PS -- Power Law Scheme.
            Identical to HS for Peclet-number |(F/D)| > 10 and near to ES else
            Convection dominant.
        * ES -- Exponential scheme
            Only stationary one-dimensional but exact solution

    Returns
    -------

    S : :gimliapi:`GIMLI::SparseMatrix` | numpy.ndarray(nCells, nCells)
        Kernel matrix, depends on vel, a, b, scheme, uB, duB .. if some of this
        has been changed you cannot cache these matrix

    rhsBoundaryScales : ndarray(nCells)
        RHS offset vector
    """
    if a is None:
        a = pg.RVector(mesh.boundaryCount(), 1.0)

    AScheme = None
    if scheme == 'CDS':
        AScheme = lambda peclet_: 1.0 - 0.5 * abs(peclet_)
    elif scheme == 'UDS':
        AScheme = lambda peclet_: 1.0
    elif scheme == 'HS':
        AScheme = lambda peclet_: max(0.0, 1.0 - 0.5 * abs(peclet_))
    elif scheme == 'PS':
        AScheme = lambda peclet_: max(0.0, (1.0 - 0.1 * abs(peclet_))**5.0)
    elif scheme == 'ES':
        AScheme = lambda peclet_: (peclet_) / (np.exp(abs(peclet_)) - 1.0) \
            if peclet_ != 0.0 else 1
    else:
        raise BaseException("Scheme unknwon:" + scheme)

    useHalfBoundaries = False

    dof = mesh.cellCount()

    if not uB:
        uB = []
    if not duB:
        duB = []

    if useHalfBoundaries:
        dof = mesh.cellCount() + len(uB)

    S = None
    if sparse:
        S = pg.RSparseMapMatrix(dof, dof, stype=0) + identity(dof, scale=b)
    else:
        S = np.zeros((dof, dof))

    rhsBoundaryScales = np.zeros(dof)

    #    swatch = pg.Stopwatch(True)

    # we need this to fast identify uBoundary and value by boundary
    uBoundaryID = []
    uBoundaryVals = [None] * mesh.boundaryCount()
    for [boundary, val] in uB:

        if not isinstance(boundary, pg.Boundary):
            raise BaseException("Please give boundary, value list")

        uBoundaryID.append(boundary.id())
        uBoundaryVals[boundary.id()] = val

    duBoundaryID = []
    duBoundaryVals = [None] * mesh.boundaryCount()

    for [boundary, val] in duB:
        if not isinstance(boundary, pg.Boundary):
            raise BaseException("Please give boundary, value list")

        duBoundaryID.append(boundary.id())
        duBoundaryVals[boundary.id()] = val

    # iterate over all cells
    for cell in mesh.cells():
        cID = cell.id()
        for bi in range(cell.boundaryCount()):
            boundary = pg.findBoundary(cell.boundaryNodes(bi))

            ncell = boundary.leftCell()
            if ncell == cell:
                ncell = boundary.rightCell()

            v = findVelocity(mesh, vel, boundary, cell, ncell)

            # Convection part
            F = boundary.norm(cell).dot(v) * boundary.size()
            # print(F, boundary.size(), v, vel)
            # Diffusion part
            D = findDiffusion(mesh, a, boundary, cell, ncell)

            # print(F, D, F/D)
            # print((1.0 - 0.1 * abs(F/D))**5.0)
            aB = D * AScheme(F / D) + max(-F, 0.0)

            aB /= cell.size()

            # print(cell.center(), boundary.center(), boundary.norm(cell), aB)
            if ncell:
                # no boundary
                if sparse:
                    S.addVal(cID, ncell.id(), -aB)
                    S.addVal(cID, cID, +aB)
                else:
                    S[cID, ncell.id()] -= aB
                    S[cID, cID] += aB

            elif not useHalfBoundaries:

                if boundary.id() in uBoundaryID:
                    val = pg.solver.generateBoundaryValue(
                        boundary,
                        uBoundaryVals[boundary.id()],
                        time=time,
                        userData=userData)

                    if sparse:
                        S.addVal(cID, cID, aB)
                    else:
                        S[cID, cID] += aB

                    rhsBoundaryScales[cID] += aB * val

                if boundary.id() in duBoundaryID:
                    # Neumann boundary condition
                    val = pg.solver.generateBoundaryValue(
                        boundary,
                        duBoundaryVals[boundary.id()],
                        time=time,
                        userData=userData)

                    # amount of flow through the boundary
                    outflow = val * boundary.size() / cell.size()
                    if sparse:
                        S.addVal(cID, cID, outflow)
                    else:
                        S[cID, cID] += outflow

        if fn is not None:
            if sparse:
                # * cell.shape().domainSize())
                S.addVal(cell.id(), cell.id(), -fn[cell.id()])
            else:
                # * cell.shape().domainSize()
                S[cell.id(), cell.id()] -= fn[cell.id()]

    return S, rhsBoundaryScales
예제 #12
0
def diffusionConvectionKernel(mesh, a=None, b=0.0, f=None,
                              uB=None, duB=None,
                              fn=None, vel=0, u0=0,
                              scheme='CDS', sparse=False, time=0.0,
                              userData=None):
    """
    Peclet Number - ratio between convection/diffusion * Length

    Advection .. forced convection
    """
    if a is None:
        a = pg.RVector(mesh.boundaryCount(), 1.0)

    AScheme = None
    if scheme == 'CDS':
        # CDS - central diff. scheme .. maybe irregular for Peclet no. |F/D|>2
        # diffusion dominant
        # Error of order 2
        AScheme = lambda peclet_: 1.0 - 0.5 * abs(peclet_)
    elif scheme == 'UDS':
        # UDS - upwind scheme
        # Convection dominant
        # Error of order 1
        AScheme = lambda peclet_: 1.0
    elif scheme == 'HS':
        # HS - hybrid scheme.
        # Diffusion dominant for Peclet-number |(F/D)| < 2
        # Convection dominant else
        AScheme = lambda peclet_: max(0.0, 1.0 - 0.5 * abs(peclet_))
    elif scheme == 'PS':
        # PS - power-law scheme.
        # Identical to HS for Peclet-number |(F/D)| > 10 and near to ES else
        AScheme = lambda peclet_: max(0.0, (1.0 - 0.1 * abs(peclet_))**5.0)
    elif scheme == 'ES':
        # ES - exponential scheme
        # Only stationary one-dimensional but exact solution
        AScheme = lambda peclet_: (peclet_) / (np.exp(abs(peclet_)) - 1.0) \
            if peclet_ != 0.0 else 1
    else:
        raise

    useHalfBoundaries = False

    dof = mesh.cellCount()

    if not uB:
        uB = []
    if not duB:
        duB = []

    if useHalfBoundaries:
        dof = mesh.cellCount() + len(uB)

    S = None
    if sparse:
        S = pg.RSparseMapMatrix(dof, dof, 0) + identity(dof) * b
    else:
        S = np.zeros((dof, dof))

    rhsBoundaryScales = np.zeros(dof)

#    swatch = pg.Stopwatch(True)

    # we need this to fast identify uBoundary and value by boundary
    uBoundaryID = []
    uBoundaryVals = [None] * mesh.boundaryCount()
    for i, [boundary, val] in enumerate(uB):
        if not isinstance(boundary, pg.Boundary):
            raise BaseException("Please give boundary, value list")
        uBoundaryID.append(boundary.id())
        uBoundaryVals[boundary.id()] = val
    duBoundaryID = []
    duBoundaryVals = [None] * mesh.boundaryCount()
    for i, [boundary, val] in enumerate(duB):
        if not isinstance(boundary, pg.Boundary):
            raise BaseException("Please give boundary, value list")
        duBoundaryID.append(boundary.id())
        duBoundaryVals[boundary.id()] = val

    for cell in mesh.cells():

        for bi in range(cell.boundaryCount()):
            boundary = pg.findBoundary(cell.boundaryNodes(bi))

            ncell = boundary.leftCell()
            if ncell == cell:
                ncell = boundary.rightCell()

            v = findVelocity(mesh, vel, boundary, cell, ncell)

            # Convection part
            F = boundary.norm(cell).dot(v) * boundary.size()

            # Diffusion part
            D = findDiffusion(mesh, a, boundary, cell, ncell)

            aB = D * AScheme(F / D) + max(-F, 0.0)

            aB /= cell.size()

            # print(cell.center(), boundary.center(), boundary.norm(cell), aB)
            if ncell:
                # no boundary
                if sparse:
                    S.addVal(cell.id(), ncell.id(), -aB)
                    S.addVal(cell.id(), cell.id(), +aB)
                else:
                    S[cell.id(), ncell.id()] -= aB
                    S[cell.id(), cell.id()] += aB

            elif not useHalfBoundaries:

                if boundary.id() in uBoundaryID:
                    val = pg.solver.generateBoundaryValue(boundary,
                                                          uBoundaryVals[
                                                              boundary.id()],
                                                          time=time,
                                                          userData=userData)

                    if sparse:
                        S.addVal(cell.id(), cell.id(), aB)
                    else:
                        S[cell.id(), cell.id()] += aB

                    rhsBoundaryScales[cell.id()] += aB * val

                if boundary.id() in duBoundaryID:
                    # Neumann boundary condition
                    val = pg.solver.generateBoundaryValue(
                        boundary, duBoundaryVals[boundary.id()], time=time,
                        userData=userData)
                    if sparse:
                        # amount of flow through the boundary
                        S.addVal(cell.id(), cell.id(), val *
                                 boundary.size() / cell.size())
                    else:
                        S[cell.id(), cell.id()] += val * \
                            boundary.size() / cell.size()

        if fn is not None:
            if sparse:
                # * cell.shape().domainSize())
                S.addVal(cell.id(), cell.id(), -fn[cell.id()])
            else:
                # * cell.shape().domainSize()
                S[cell.id(), cell.id()] -= fn[cell.id()]

    if useHalfBoundaries:
        for i, [b, val] in enumerate(duB):  # not defined!!!
            bIdx = mesh.cellCount() + i

            c = b.leftCell()
            if not c:
                c = b.rightCell()

            if c:
                n = b.norm(c)
                v = findVelocity(mesh, vel, b, c, nc=None)
                F = n.dot(v) * b.size()

                D = findDiffusion(mesh, a, b, c)
                aB = D * AScheme(F / D) + max(-F, 0.0)

                if useHalfBoundaries:
                    if sparse:
                        S.setVal(c.id(), c.id(), 1.)
                        S.addVal(c.id(), bIdx, -aB)
                    else:
                        S[bIdx, bIdx] = 1.
                        S[c.id(), bIdx] -= aB

                    rhsBoundaryScales[bIdx] = aB

    return S, rhsBoundaryScales
예제 #13
0
def diffusionConvectionKernel(mesh, a=None, b=0.0,
                              uB=None, duB=None,
                              vel=0,
                              # u0=0,
                              fn=None,
                              scheme='CDS', sparse=False, time=0.0,
                              userData=None):
    """
    Generate system matrix for diffusion and convection in a velocity field.

    Particle concentration u inside a velocity field.

    Peclet Number - ratio between convection/diffusion = F/D
        F = velocity flow trough volume boundary,
        D = diffusion coefficient

    Parameters
    ----------
    mesh : :gimliapi:`GIMLI::Mesh`
        Mesh represents spatial discretization of the calculation domain

    a   : value | array | callable(cell, userData)
        Diffusion coefficient per cell

    b   : value | array | callable(cell, userData)
        TODO What is b

    fn   : iterable(cell)
        TODO What is fn

    vel : ndarray (N,dim) | RMatrix(N,dim)
        velocity field [[v_i,]_j,] with i=[1..3] for the mesh dimension
        and j = [0 .. N-1] per Cell or per Node so N is either
        mesh.cellCount() or mesh.nodeCount()

    scheme : str [CDS]
        Finite volume scheme

        * CDS -- Central Difference Scheme.
            maybe irregular for Peclet no. |F/D| > 2
            Diffusion dominant. Error of order 2
        * UDS -- Upwind Scheme.
            Convection dominant. Error of order 1
        * HS -- Hybrid Scheme.
            Diffusion dominant for Peclet-number |(F/D)| < 2
            Convection dominant else.
        * PS -- Power Law Scheme.
            Identical to HS for Peclet-number |(F/D)| > 10 and near to ES else
            Convection dominant.
        * ES -- Exponential scheme
            Only stationary one-dimensional but exact solution

    Returns
    -------

    S : :gimliapi:`GIMLI::SparseMatrix` | numpy.ndarray(nCells, nCells)
        Kernel matrix, depends on vel, a, b, scheme, uB, duB .. if some of this
        has been changed you cannot cache these matrix

    rhsBoundaryScales : ndarray(nCells)
        RHS offset vector
    """
    if a is None:
        a = pg.RVector(mesh.boundaryCount(), 1.0)

    AScheme = None
    if scheme == 'CDS':
        AScheme = lambda peclet_: 1.0 - 0.5 * abs(peclet_)
    elif scheme == 'UDS':
        AScheme = lambda peclet_: 1.0
    elif scheme == 'HS':
        AScheme = lambda peclet_: max(0.0, 1.0 - 0.5 * abs(peclet_))
    elif scheme == 'PS':
        AScheme = lambda peclet_: max(0.0, (1.0 - 0.1 * abs(peclet_))**5.0)
    elif scheme == 'ES':
        AScheme = lambda peclet_: (peclet_) / (np.exp(abs(peclet_)) - 1.0) \
            if peclet_ != 0.0 else 1
    else:
        raise BaseException("Scheme unknwon:" + scheme)

    useHalfBoundaries = False

    dof = mesh.cellCount()

    if not uB:
        uB = []
    if not duB:
        duB = []

    if useHalfBoundaries:
        dof = mesh.cellCount() + len(uB)

    S = None
    if sparse:
        S = pg.RSparseMapMatrix(dof, dof, stype=0) + identity(dof, scale=b)
    else:
        S = np.zeros((dof, dof))

    rhsBoundaryScales = np.zeros(dof)

#    swatch = pg.Stopwatch(True)

    # we need this to fast identify uBoundary and value by boundary
    uBoundaryID = []
    uBoundaryVals = [None] * mesh.boundaryCount()
    for [boundary, val] in uB:

        if not isinstance(boundary, pg.Boundary):
            raise BaseException("Please give boundary, value list")

        uBoundaryID.append(boundary.id())
        uBoundaryVals[boundary.id()] = val

    duBoundaryID = []
    duBoundaryVals = [None] * mesh.boundaryCount()

    for [boundary, val] in duB:
        if not isinstance(boundary, pg.Boundary):
            raise BaseException("Please give boundary, value list")

        duBoundaryID.append(boundary.id())
        duBoundaryVals[boundary.id()] = val

    # iterate over all cells
    for cell in mesh.cells():
        cID = cell.id()
        for bi in range(cell.boundaryCount()):
            boundary = pg.findBoundary(cell.boundaryNodes(bi))

            ncell = boundary.leftCell()
            if ncell == cell:
                ncell = boundary.rightCell()

            v = findVelocity(mesh, vel, boundary, cell, ncell)

            # Convection part
            F = boundary.norm(cell).dot(v) * boundary.size()
            # print(F, boundary.size(), v, vel)
            # Diffusion part
            D = findDiffusion(mesh, a, boundary, cell, ncell)

            # print(F, D, F/D)
            # print((1.0 - 0.1 * abs(F/D))**5.0)
            aB = D * AScheme(F / D) + max(-F, 0.0)

            aB /= cell.size()

            # print(cell.center(), boundary.center(), boundary.norm(cell), aB)
            if ncell:
                # no boundary
                if sparse:
                    S.addVal(cID, ncell.id(), -aB)
                    S.addVal(cID, cID, +aB)
                else:
                    S[cID, ncell.id()] -= aB
                    S[cID, cID] += aB

            elif not useHalfBoundaries:

                if boundary.id() in uBoundaryID:
                    val = pg.solver.generateBoundaryValue(
                        boundary,
                        uBoundaryVals[boundary.id()],
                        time=time,
                        userData=userData)

                    if sparse:
                        S.addVal(cID, cID, aB)
                    else:
                        S[cID, cID] += aB

                    rhsBoundaryScales[cID] += aB * val

                if boundary.id() in duBoundaryID:
                    # Neumann boundary condition
                    val = pg.solver.generateBoundaryValue(
                        boundary,
                        duBoundaryVals[boundary.id()],
                        time=time,
                        userData=userData)

                    # amount of flow through the boundary
                    outflow = val * boundary.size() / cell.size()
                    if sparse:
                        S.addVal(cID, cID, outflow)
                    else:
                        S[cID, cID] += outflow

        if fn is not None:
            if sparse:
                # * cell.shape().domainSize())
                S.addVal(cell.id(), cell.id(), -fn[cell.id()])
            else:
                # * cell.shape().domainSize()
                S[cell.id(), cell.id()] -= fn[cell.id()]

    return S, rhsBoundaryScales
예제 #14
0
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