Ejemplo n.º 1
0
def sparse_laplacian(nx, ny):

    # Neumann BC Laplacian
    Ix = sp.eye(nx, format='csc')
    Iy = sp.eye(ny, format='csc')
    Ix[0, 0] = 0.5
    Ix[-1, -1] = 0.5
    Iy[0, 0] = 0.5
    Iy[-1, -1] = 0.5

    Dxx = sp.diags([1, -2, 1], [-1, 0, 1], shape=(nx, nx)).toarray()
    Dxx[0, 1] = 2
    Dxx[-1, -2] = 2

    Dyy = sp.diags([1, -2, 1], [-1, 0, 1], shape=(ny, ny)).toarray()
    Dyy[0, 1] = 2
    Dyy[-1, -2] = 2

    # L = sp.kronsum(Dyy,Dxx,format='csc')
    L = sp.kronsum(Dxx, Dyy, format='csc')

    Q = sp.kron(Ix, Iy, format='csc')
    # Q = sp.kron(Ix,Iy,format='csc')

    return L, Q
Ejemplo n.º 2
0
def matrices(shape, operators, combine):
    def parts():
        for i, o in enumerate(operators):
            diagonals = []
            for j, p in enumerate(o):
                index = -(len(o) // 2 - j)
                diagonals.append((p * np.ones(shape[i] - abs(index)), index))

            matrix = sp.diags(*zip(*diagonals))
            if combine:
                yield matrix
            else:
                # The sum of these kronecker product folds is equivalent to the kronecker sum of all the matrices.
                # This identity can be derived from the properties of the kronecker product.
                # This is useful when you need to apply each operator on a different axis,
                # like in the case of finding the divergence of a velocity field using the gradient.
                yield reduce(
                    sp.kron,
                    tuple(matrix if k == i else sp.identity(d)
                          for k, d in enumerate(shape)))

    # Credit to Philip Zucker for figuring out that kronsum's argument order is reversed.
    # Without that bit of wisdom I'd have lost it.
    return reduce(lambda a, b: sp.kronsum(b, a),
                  parts()) if combine else tuple(parts())
Ejemplo n.º 3
0
def operator(shape, *differences):
    # Credit to Philip Zucker for figuring out
    # that kronsum's argument order is reversed.
    # Without that bit of wisdom I'd have lost it.
    differences = zip(shape, cycle(differences))
    factors = (sp.diags(*diff, shape=(dim, ) * 2) for dim, diff in differences)
    return reduce(lambda a, f: sp.kronsum(f, a, format='csc'), factors)
Ejemplo n.º 4
0
 def _get_elem(self):
     a = self.A._get_elem()
     b = self.B._get_elem()
     A = sp.coo_matrix((a[2], (a[0], a[1])))
     B = sp.coo_matrix((b[2], (b[0], b[1])))
     C = sp.kronsum(A, B, format='coo')
     return (C.row, C.col, C.data)
Ejemplo n.º 5
0
def lapl(shape, mul=1, h=1):
    diags = [1, -2, 1] # Values on diagonals for 1d laplacian
    ks = [mul, 0, -mul] # which diagonals to set for above values
    
    # Store 1d laplacians T_j in array Ts
    Ts = [sparse.diags(diags, ks, shape=(j, j), format='csr') for j in shape]
    
    # Calculate kronsum (sum of tensor product of T_a, I_b and tensor product of I_a, T_b) of 1d laplacian matrices
    return reduce(lambda a, b: sparse.kronsum(a, b, format='csr'), Ts[::-1]) / h
Ejemplo n.º 6
0
    def __init__(self, m, n, dx, wn, ws, we, ww, id, neumann=None):
        """

        :param m: int, shape[0] of the room
        :param n: int, shape[1] of the room
        :param dx: float, dicretization distance
        :param wn: float, temperature of north wall
        :param ws: float, temperature of south wall
        :param we: float, temperature of east wall
        :param ww: float, temperature of west wall
        :param id: int, rank of the calling thread
        """

        self.M = m
        self.N = n

        # create the whole array
        self.u = np.zeros((m, n))
        self.dx = dx

        # create references to the walls
        self.wn = self.u[-1, :]
        self.ws = self.u[0, :]
        self.we = self.u[:, -1]
        self.ww = self.u[:, 0]

        # setup a dictionary for shared items
        self.shared = dict()

        # assign values to the walls
        self.wn += wn
        self.ws += ws
        self.we += we
        self.ww += ww

        ub = self.u.copy()
        nan = np.empty((m, n))
        nan[:, :] = np.NaN
        self.ub = np.where(ub != 0, ub, nan)

        # set the id
        self.id = id  # try using some form of broadcast with a class variable?

        # deal with any boundary conditions when we create the A matrix
        Dn = sparse.diags([1, -2, 1], [-1, 0, 1], shape=(n, n))
        Dm = sparse.diags([1, -2, 1], [-1, 0, 1], shape=(m, m))

        if neumann == 'east':
            Dn = Dn.copy().tolil()
            Dn[-1, -1] += 1
            self.ub[1:-1, -1] = np.NaN
        elif neumann == 'west':
            Dn = Dn.copy().tolil()
            Dn[0, 0] += 1
            self.ub[1:-1, 0] = np.NaN

        self.A = sparse.kronsum(Dn, Dm)
Ejemplo n.º 7
0
def kronsum(gen):
    """
    Kronnecker sum

    example:
    """
    res = next(gen)
    for each in gen:
        res = sp.kronsum(res, each)
    return res
Ejemplo n.º 8
0
    def define_laplacian(self):
        """Define the laplacian."""
        L = self.get_1D_laplacian()

        if self.ndim == 2:
            L = sp.kronsum(L, L, format='lil')

        L[0, -1] = 1.
        L[-1, 0] = 1.
        self.L = L / (self.steps**2).prod()
        self.L = sp.block_diag([self.L] * self.nstates)
Ejemplo n.º 9
0
def L_form(h, Nx, Ny):
    Dx = np.zeros((Nx, Nx - 1))
    np.fill_diagonal(Dx, 1)
    np.fill_diagonal(Dx[1:, :], -1)

    Dy = np.zeros((Ny, Ny - 1))
    np.fill_diagonal(Dy, 1)
    np.fill_diagonal(Dy[1:, :], -1)

    Lxx = Dx.T @ Dx
    Lyy = Dy.T @ Dy
    L = sp.kronsum(Lxx, Lyy) / h**2
    return -L
Ejemplo n.º 10
0
def build_laplacian_matrix(nx, ny, g=g,d=d):
    Lx = ss.diags([-2*np.ones(nx), np.ones(nx-1), np.ones(nx-1), 1.0, 1.0],
                  [0, -1, 1, nx-1, -(nx-1)])/d/d

    Ly = ss.diags([-2*np.ones(ny), np.ones(ny-1), np.ones(ny-1), 1.0, 1.0],
                  [0, -1, 1, ny-1, -(ny-1)])/d/d


    L =   ss.kronsum(Ly, Lx).tocsr()
    I = ss.eye(nx*ny).tocsr()
    L[0] = I[0]

    return L
Ejemplo n.º 11
0
def generate_A(ijklevels):
    numLevels = ijklevels.shape[1]
    A = []
    for i in range(numLevels):
        Nx = ijklevels[0][i]
        Ny = ijklevels[1][i]
        Nz = ijklevels[2][i]
        nx = Nx - 2
        ny = Ny - 2
        nz = Nz - 2
        hx = Lx / (Nx - 1)
        hy = Ly / (Ny - 1)
        hz = Lz / (Nz - 1)
        diagonalsx = [(hz**2/hx**2)*np.ones(nx-1), (-2*hz**2/hx**2)*np.ones(nx), \
                      (hz**2/hx**2)*np.ones(nx-1)]
        diagonalsy = [(hz**2/hy**2)*np.ones(ny-1), (-2*hz**2/hy**2)*np.ones(ny), \
                      (hz**2/hy**2)*np.ones(ny-1)]
        diagonalsz = [np.ones(nz - 1), -2 * np.ones(nz), np.ones(nz - 1)]
        Ax = sp.diags(diagonalsx, [-1, 0, 1])
        Ay = sp.diags(diagonalsy, [-1, 0, 1])
        Az = sp.diags(diagonalsz, [-1, 0, 1])
        A.append(sp.kronsum(sp.kronsum(Ax, Ay), Az, format='coo'))
    return A
Ejemplo n.º 12
0
def make_L(Nx, Ny):
    Dx = sp.diags((Nx - 1) * [1.])
    Dx += sp.diags((Nx - 2) * [-1.], -1)
    rowx = sp.csr_matrix((1, Nx - 1))
    rowx[0, -1] = -1
    Dx = sp.vstack((Dx, rowx))
    Lx = Dx.transpose().dot(Dx)

    Dy = sp.diags((Ny - 1) * [1])
    Dy += sp.diags((Ny - 2) * [-1], -1)
    rowy = sp.csr_matrix((1, Ny - 1))
    rowy[0, -1] = -1
    Dy = sp.vstack((Dy, rowy))
    Ly = Dy.transpose().dot(Dy)
    return sp.kronsum(Lx, Ly)
Ejemplo n.º 13
0
def make_L(Nx, Ny):
    Dx = sp.diags((Nx - 1) * [1])
    Dx += sp.diags((Nx - 2) * [-1], -1)
    rowx = sp.csr_matrix((1, Nx - 1))
    rowx[0, -1] = -1
    Dx = sp.vstack((Dx, rowx))
    Lx = Dx.transpose().dot(Dx)

    Dy = sp.diags((Ny - 1) * [1])
    Dy += sp.diags((Ny - 2) * [-1], -1)
    rowy = sp.csr_matrix((1, Ny - 1))
    rowy[0, -1] = -1
    Dy = sp.vstack((Dy, rowy))
    Ly = Dy.transpose().dot(Dy)

    #Kronsum is jsut a cleaner way than creating Identity matrices and stuff
    return sp.kronsum(Lx, Ly)
Ejemplo n.º 14
0
def discrete_hamiltonian(V: np.ndarray):
    """
    Given the potential V, return the discretized Hamiltonian.

    Reference to discretize the Hamiltonian:
    https://wiki.physics.udel.edu/phys824/
    Discretization_of_1D_continuous_Hamiltonian

    Discretizing the Laplacian:
    https://en.wikipedia.org/wiki/Discrete_Laplace_operator#
    Implementation_via_operator_discretization

    Kronecker sum of discrete Laplacians:
    https://en.wikipedia.org/wiki/Kronecker_sum_of_discrete_Laplacians
    """
    diag = HBAR**2 / (2 * M_E * DX**2) * np.ones([N])
    diags = np.array([-diag, 2.0 * diag, -diag])
    kinetic_1d = sparse.spdiags(diags, np.array([1.0, 0.0, -1.0]), N, N)
    T = sparse.kronsum(kinetic_1d, kinetic_1d)
    U = sparse.diags((V.reshape(N * N)), (0))
    return T + U
Ejemplo n.º 15
0
    def __init__(self):
        # list of tuples (solver, symmetric, positive_definite )
        solvers = [cg, cgs, bicg, bicgstab, gmres, qmr, minres, lgmres, gcrotmk, tfqmr]
        sym_solvers = [minres, cg]
        posdef_solvers = [cg]
        real_solvers = [minres]

        self.solvers = solvers

        # list of tuples (A, symmetric, positive_definite )
        self.cases = []

        # Symmetric and Positive Definite
        N = 40
        data = ones((3,N))
        data[0,:] = 2
        data[1,:] = -1
        data[2,:] = -1
        Poisson1D = spdiags(data, [0,-1,1], N, N, format='csr')
        self.Poisson1D = Case("poisson1d", Poisson1D)
        self.cases.append(Case("poisson1d", Poisson1D))
        # note: minres fails for single precision
        self.cases.append(Case("poisson1d", Poisson1D.astype('f'),
                               skip=[minres]))

        # Symmetric and Negative Definite
        self.cases.append(Case("neg-poisson1d", -Poisson1D,
                               skip=posdef_solvers))
        # note: minres fails for single precision
        self.cases.append(Case("neg-poisson1d", (-Poisson1D).astype('f'),
                               skip=posdef_solvers + [minres]))

        # 2-dimensional Poisson equations
        Poisson2D = kronsum(Poisson1D, Poisson1D)
        self.Poisson2D = Case("poisson2d", Poisson2D)
        # note: minres fails for 2-d poisson problem, it will be fixed in the future PR
        self.cases.append(Case("poisson2d", Poisson2D, skip=[minres]))
        # note: minres fails for single precision
        self.cases.append(Case("poisson2d", Poisson2D.astype('f'),
                               skip=[minres]))

        # Symmetric and Indefinite
        data = array([[6, -5, 2, 7, -1, 10, 4, -3, -8, 9]],dtype='d')
        RandDiag = spdiags(data, [0], 10, 10, format='csr')
        self.cases.append(Case("rand-diag", RandDiag, skip=posdef_solvers))
        self.cases.append(Case("rand-diag", RandDiag.astype('f'),
                               skip=posdef_solvers))

        # Random real-valued
        np.random.seed(1234)
        data = np.random.rand(4, 4)
        self.cases.append(Case("rand", data, skip=posdef_solvers+sym_solvers))
        self.cases.append(Case("rand", data.astype('f'),
                               skip=posdef_solvers+sym_solvers))

        # Random symmetric real-valued
        np.random.seed(1234)
        data = np.random.rand(4, 4)
        data = data + data.T
        self.cases.append(Case("rand-sym", data, skip=posdef_solvers))
        self.cases.append(Case("rand-sym", data.astype('f'),
                               skip=posdef_solvers))

        # Random pos-def symmetric real
        np.random.seed(1234)
        data = np.random.rand(9, 9)
        data = np.dot(data.conj(), data.T)
        self.cases.append(Case("rand-sym-pd", data))
        # note: minres fails for single precision
        self.cases.append(Case("rand-sym-pd", data.astype('f'),
                               skip=[minres]))

        # Random complex-valued
        np.random.seed(1234)
        data = np.random.rand(4, 4) + 1j*np.random.rand(4, 4)
        self.cases.append(Case("rand-cmplx", data,
                               skip=posdef_solvers+sym_solvers+real_solvers))
        self.cases.append(Case("rand-cmplx", data.astype('F'),
                               skip=posdef_solvers+sym_solvers+real_solvers))

        # Random hermitian complex-valued
        np.random.seed(1234)
        data = np.random.rand(4, 4) + 1j*np.random.rand(4, 4)
        data = data + data.T.conj()
        self.cases.append(Case("rand-cmplx-herm", data,
                               skip=posdef_solvers+real_solvers))
        self.cases.append(Case("rand-cmplx-herm", data.astype('F'),
                               skip=posdef_solvers+real_solvers))

        # Random pos-def hermitian complex-valued
        np.random.seed(1234)
        data = np.random.rand(9, 9) + 1j*np.random.rand(9, 9)
        data = np.dot(data.conj(), data.T)
        self.cases.append(Case("rand-cmplx-sym-pd", data, skip=real_solvers))
        self.cases.append(Case("rand-cmplx-sym-pd", data.astype('F'),
                               skip=real_solvers))

        # Non-symmetric and Positive Definite
        #
        # cgs, qmr, bicg and tfqmr fail to converge on this one
        #   -- algorithmic limitation apparently
        data = ones((2,10))
        data[0,:] = 2
        data[1,:] = -1
        A = spdiags(data, [0,-1], 10, 10, format='csr')
        self.cases.append(Case("nonsymposdef", A,
                               skip=sym_solvers+[cgs, qmr, bicg, tfqmr]))
        self.cases.append(Case("nonsymposdef", A.astype('F'),
                               skip=sym_solvers+[cgs, qmr, bicg, tfqmr]))

        # Symmetric, non-pd, hitting cgs/bicg/bicgstab/qmr/tfqmr breakdown
        A = np.array([[0, 0, 0, 0, 0, 1, -1, -0, -0, -0, -0],
                      [0, 0, 0, 0, 0, 2, -0, -1, -0, -0, -0],
                      [0, 0, 0, 0, 0, 2, -0, -0, -1, -0, -0],
                      [0, 0, 0, 0, 0, 2, -0, -0, -0, -1, -0],
                      [0, 0, 0, 0, 0, 1, -0, -0, -0, -0, -1],
                      [1, 2, 2, 2, 1, 0, -0, -0, -0, -0, -0],
                      [-1, 0, 0, 0, 0, 0, -1, -0, -0, -0, -0],
                      [0, -1, 0, 0, 0, 0, -0, -1, -0, -0, -0],
                      [0, 0, -1, 0, 0, 0, -0, -0, -1, -0, -0],
                      [0, 0, 0, -1, 0, 0, -0, -0, -0, -1, -0],
                      [0, 0, 0, 0, -1, 0, -0, -0, -0, -0, -1]], dtype=float)
        b = np.array([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], dtype=float)
        assert (A == A.T).all()
        self.cases.append(Case("sym-nonpd", A, b,
                               skip=posdef_solvers,
                               nonconvergence=[cgs,bicg,bicgstab,qmr,tfqmr]))
Ejemplo n.º 16
0
def _build_derivative_matrix_structured_cartesian(mesh,
                                                  derivative, order_accuracy,
                                                  dimension='all',
                                                  use_shifted_differences=False,
                                                  return_1D_matrix=False,
                                                  **kwargs):

    dims = list()
    if type(dimension) is str:
        dimension = [dimension]
    if 'all' in dimension:
        if mesh.dim > 1:
            dims.append('x')
        if mesh.dim > 2:
            dims.append('y')
        dims.append('z')
    else:
        for d in dimension:
            dims.append(d)

    # sh[-1] is always 'z'
    # sh[0] is always 'x' if in 2 or 3d
    # sh[1] is always 'y' if dim > 2
    sh = mesh.shape(include_bc = True, as_grid = True)

    if mesh.dim > 1:
        if 'x' in dims:
            lbc = _set_bc(mesh.x.lbc)
            rbc = _set_bc(mesh.x.rbc)
            delta = mesh.x.delta
            Dx = _build_derivative_matrix_part(sh[0], derivative, order_accuracy, h=delta, lbc=lbc, rbc=rbc, use_shifted_differences=use_shifted_differences)
        else:
            Dx = spsp.csr_matrix((sh[0],sh[0]))
    if mesh.dim > 2:
        if 'y' in dims:
            lbc = _set_bc(mesh.y.lbc)
            rbc = _set_bc(mesh.y.rbc)
            delta = mesh.y.delta
            Dy = _build_derivative_matrix_part(sh[1], derivative, order_accuracy, h=delta, lbc=lbc, rbc=rbc, use_shifted_differences=use_shifted_differences)
        else:
            Dy = spsp.csr_matrix((sh[1],sh[1]))

    if 'z' in dims:
        lbc = _set_bc(mesh.z.lbc)
        rbc = _set_bc(mesh.z.rbc)
        delta = mesh.z.delta
        Dz = _build_derivative_matrix_part(sh[-1], derivative, order_accuracy, h=delta, lbc=lbc, rbc=rbc, use_shifted_differences=use_shifted_differences)
    else:
        Dz = spsp.csr_matrix((sh[-1],sh[-1]))

    if return_1D_matrix and 'all' not in dims:
        if 'z' in dims:
            mtx = Dz
        elif 'y' in dims:
            mtx = Dy
        elif 'x' in dims:
            mtx = Dx
    else:
        if mesh.dim == 1:
            mtx = Dz.tocsr()
        if mesh.dim == 2:
            # kronsum in this order because wavefields are stored with 'z' in row
            # and 'x' in columns, then vectorized in 'C' order
            mtx = spsp.kronsum(Dz, Dx, format='csr')
        if mesh.dim == 3:
            mtx = spsp.kronsum(Dz, spsp.kronsum(Dy,Dx, format='csr'), format='csr')

    return mtx
Ejemplo n.º 17
0
Ix = sp.eye(nx, format='csc')
Iy = sp.eye(ny, format='csc')
Ix[0, 0] = 0.5
Ix[-1, -1] = 0.5
Iy[0, 0] = 0.5
Iy[-1, -1] = 0.5

Dxx = sp.diags([1, -2, 1], [-1, 0, 1], shape=(nx, nx)).toarray()
Dxx[0, 1] = 2
Dxx[-1, -2] = 2  #Riemann boundary condition

Dyy = sp.diags([1, -2, 1], [-1, 0, 1], shape=(ny, ny)).toarray()
Dyy[0, 1] = 2
Dyy[-1, -2] = 2

L = sp.kronsum(Dyy, Dxx, format='csc')

Q = sp.kron(Ix, Iy, format='csc')

A0 = Q @ (I - C / 2.0 * L)
#Aarr = A.toarray()

#pd =is_pos_def(A.toarray())   #check if A matrix is positive definite
# LU decomposition Pr*A*Pc = LU
#lu = la.splu(A0)
#factor = cholesky(A0)

#LU_x = lambda x: factor(x)
#pvec = la.LinearOperator((nv, nv), LU_x)

##====================Initial condition=========================
# converting in CSR format
A1 = A1.tocsr()
 
 # Construct anther matrix  
B1 = lil_matrix((1000, 1000))
B1[0, :100] = rand(100)
B1[1, 100:200] = B1[0, :100]
B1.setdiag(rand(1000))
# converting in CSR forma
B1 = B1.tocsr()
 
 # Sparse kronecker product
C1 = sparse.kron(A1, B1).toarray() 

#sparse kronecker sum 
C2 = sparse.kronsum(A1,B1).toarray()

# Sparse Kronecker product diagonal matrix
def populatematrix1(dim):
    return dia_matrix( (np.array( [np.array([2]*5),np.array([1]*5), np.array([1]*5)] ),np.array([0,1,-1]) ),shape=(5,5))
def populatematrix2(dim):
    return dia_matrix( (np.array( [np.array([2]*5),np.array([1]*5), np.array([1]*5)] ),np.array([0,1,-1]) ),shape=(5,5))

dx = np.linspace(0,1,5)
x = populatematrix1(len(dx))
print (x.shape, type(x))
y = populatematrix2(len(dx))
print (y.shape, type(y))
z = kron(x,y)
print (z.shape)
Ejemplo n.º 19
0
h = 0.002
Nx = int(2 / h)
Ny = int(1 / h)

Dx = np.zeros((Nx, Nx - 1))
np.fill_diagonal(Dx, 1)
np.fill_diagonal(Dx[1:, :], -1)

Dy = np.zeros((Ny, Ny - 1))
np.fill_diagonal(Dy, 1)
np.fill_diagonal(Dy[1:, :], -1)

Lxx = Dx.T @ Dx
Lyy = Dy.T @ Dy
L = sp.kronsum(Lxx, Lyy)
L = L / h**2
print(L)
plt.figure()
plt.spy(L, marker='o', markersize=6, color='green')

gridy = np.arange(0 + h, 1, h)
gridx = np.arange(0 + h, 2, h)

grid = np.mgrid[0 + h:2:h, 0 + h:1:h]
x = grid[0]
y = grid[1]

f = 20 * np.multiply(np.sin(np.pi * y), np.sin(1.5 * np.pi * x + np.pi))
f = np.transpose(f)
Ejemplo n.º 20
0
'''
 $$\left[-\frac{1}{2}(D \oplus D) + m\Delta x^2 V \right] \psi = \left(m \Delta x^2 E\right) \psi$$

'''

# V = np.exp(-(X-0.3)**2/(2*0.1**2))*np.exp(-(Y-0.3)**2/(2*0.1**2))
# V = 1./(1+np.exp(-(X-0.3)**2/(2*0.1**2))*np.exp(-(Y-0.3)**2/(2*0.1**2)))
# V = 1./(1+(X-0.3)**2 + (Y-0.3)**2)
V = (X-0.3)**2 + (Y-0.3)**2
V = 0*V
ones = np.ones(N)
data = np.array([ones, -2*ones, ones])
diags = np.array([-1, 0, 1])
D = sparse.spdiags(data, diags, N, N)
T = -1/2 * sparse.kronsum(D, D)
U = sparse.diags(V.reshape(N**2), (0))
H = T+U

print(data.shape)
print(D.toarray().shape)
print(T.toarray().shape)
print(U.toarray().shape)
print(H.toarray().shape)

E, Psi = eigsh(H, k=10, which='SM')
print(E.shape, Psi.shape)

def Psi_n(n): return Psi.T[n].reshape((N, N))

Ejemplo n.º 21
0
 def test_kronsum(self):
     test = kronsum(sigmax, sigmax, iden)
     exact = sp.kronsum(sp.kronsum(sigmax, sigmax), iden)
     self.assertEqual((test != exact).nnz, 0)
Ejemplo n.º 22
0
import numpy as np
from scipy.sparse import kronsum

dim = 2
a = np.zeros((dim, dim))
b = np.zeros((dim, dim))

for i in range(dim):
    for ip in range(dim):
        if i == ip + 1:
            a[i, ip] = -1
            b[i, ip] = -1
        if i == ip - 1:
            a[i, ip] = +1
            b[i, ip] = +1
        if i == ip:
            a[i, ip] = 1.1
            b[i, ip] = 1.1

full2 = kronsum(a, a).todense()
full3 = kronsum(full2, a).todense()
print(full2)
print(full3)
    def predict(self, tspan, ic):
        """Given initial condition as ``ic``, predicting the trajectory given ``tspan`` as time.

        We direct evaluate time that is far away, not using recursive for each delta t since it is linear system.

        Args:
            tspan (:obj:`numpy.ndarray`): time array

            ic (:obj:`numpy.ndarray`): initial condition :math:`x_0 = x(t=0)`.

        Returns:

            :obj:`numpy.ndarray` : ensemble of trajectory from Monte Carlo sampling, representing a distribution of posteriori.

        """

        # let's share the same IC

        state = ic

        # read in (1,M) state -> to generate (Q,K) Phi_0, but evaluate at many different states

        # duffing: [[0.00673038, 0.03789839, 0.0423713 ]]

        init_phi_state_mc_array = self.model.computePhi(state) # x -> phi

        # get Q realization of K

        self.K = self.model.get_K()

        # get linear lambda

        self.lambda_lin = self.model.get_lambda_lin()

        # get reconstruction noise

        self.noise_rec = self.model.get_noise_rec()

        RANDOM_SAMPLE = np.random.normal(size=(self.model.n_mc_samples, tspan.size,
                                               self.model.n_mc_diff_samples, self.K[0].shape[0]))

        state_total_mc_list = []
        if self.LRAN_T == 1:

            # diff form
            # for each phi state in Q realization, let's evolve the dynamics

            for i in xrange(self.model.n_mc_samples):

                # LAMBDA, P = np.linalg.eig(self.K[i])
                # PINV = np.linalg.inv(P)
                # LAMBDA = np.diag(LAMBDA)

                Q = np.linalg.inv(kronsum(self.K[i].astype('float64'), self.K[i].astype('float64')).toarray())

                # Q = 0.5*np.matmul(np.matmul(P, np.diag(self.lambda_lin[i])), -np.linalg.inv(LAMBDA))

                # for each sample
                print 'monte carlo run index = ', i, ': ', self.model.n_mc_samples # *self.model.n_mc_diff_samples

                state_list = [[state]*self.model.n_mc_diff_samples]

                for index_time in xrange(1, tspan.size):

                    delta_time = tspan[index_time] - tspan[0]

                    # linearly evolving phi to future - for i-th realization
                    # convert to double precision
                    time_evolution_with_K = delta_time * self.K[i]
                    time_evolution_with_K = time_evolution_with_K.astype('float64')
                    phi_state_at_t_mc_array = np.matmul(init_phi_state_mc_array[i].astype('float64'), expm(time_evolution_with_K))

                    # phi with noise
                    Q_true = -1.0 * np.matmul(Q.astype('float64'), np.eye(self.K[i].shape[0]**2) - expm( kronsum(self.K[i].astype('float64'), self.K[i].astype('float64')) * delta_time) )
                    Q_true = np.matmul(Q_true, np.diag(self.lambda_lin[i].astype('float64')).reshape(-1,1, order='F'))
                    Q_true = Q_true.reshape(self.K[i].shape[0],-1, order='F')

                    try:
                        L = np.linalg.cholesky(Q_true)
                    except:
                        print 'L is not positive definite...'
                        print('Q_true = ', Q_true)
                        print("")
                        print('K = ', self.K[i])
                        print('K = ', np.linalg.eig(self.K[i])[0])

                        print('lin = ', self.lambda_lin[i])
                        print('')
                        print(np.linalg.eig(Q_true)[0])
                        L = np.zeros(self.K[i].shape)

                    # the noise is involved via MOU process.
                    # Q_true = np.matmul(np.matmul(Q, np.eye(LAMBDA.shape[0]) - expm(2*LAMBDA*delta_time)), PINV)

                    ## need to modify a bit to make sure the round off error is removed...
                    # Q_true_real = np.real(Q_true)
                    # Q_true_symm = 0.5*(Q_true + np.conj(Q_true))

                    # try:
                    #    L = np.linalg.cholesky(Q_true_symm) # it is important to make it real..

                    #except:
                    #    print np.linalg.eigh(L)
                    #    L = np.zeros(LAMBDA.shape)

                    state_for_current_time_list = []

                    for i_mc_diff in xrange(self.model.n_mc_diff_samples):

                        NOISE_MOU = np.matmul(RANDOM_SAMPLE[i, index_time-1, i_mc_diff,:].reshape(1,-1), L).astype('float64')

                        phi_state_at_t_mc_array_noise_mou = phi_state_at_t_mc_array + NOISE_MOU # np.matmul(self.noise_lin[i], integrate_exp_tK)

                        # reconstruct x from phi state at feature
                        state_future_mc_array_noise_mou = self.model.reconstruct_with_i_realization(phi=phi_state_at_t_mc_array_noise_mou, i=i)

                        # here we will introduce reconstriction error
                        # add reconstruction noise -> it is like the white noise in ARMA model, not interacting with the flow. not a
                        # subscale turublence problem..
                        state_future_mc_array = state_future_mc_array_noise_mou + self.noise_rec[i][:state_future_mc_array_noise_mou.shape[1]]

                        # transform normalized state: eta, to original state
                        state_future_mc_array = self.model.transform_eta_to_x(state_future_mc_array)

                        # state_list.append(state_future_mc_array)
                        state_for_current_time_list.append(state_future_mc_array)

                    state_list.append(state_for_current_time_list)

                # append for each time's the whole realization
                state_total_mc_list.append(np.array(state_list))

            # (800, 4, 10, 1, 2)
            QM_state_array = np.stack(state_total_mc_list, axis=1)

            # (800, 4, 10, 2)
            QM_state_array = np.squeeze(QM_state_array)

            QM_state_array = np.swapaxes(QM_state_array, 0, 1)
            QM_state_array = np.swapaxes(QM_state_array, 1, 2)

            QM_state_future_array = QM_state_array.reshape(-1, tspan.size, state.size)

            # QM_state_future_array = np.squeeze(np.stack(state_total_mc_list, axis=0), axis=2)


        elif self.LRAN_T > 1:

            # recurrent form
            # for each phi state, let's evolve the dynamics.


            for i in xrange(self.model.n_mc_samples):

                # stability test

                eigv,_ = np.linalg.eig(self.K[i].astype('float64'))
                if np.max(np.real(eigv)) > 0:
                    print('=====================')
                    print('unstable!')
                    print(self.K[i])
                    print(eigv)


                # for each sample
                print 'monte carlo run index = ', i, ': ', self.model.n_mc_samples

                state_list = [state]

                # loop over time
                for index_time in xrange(1, tspan.size):

                    # compute ``delta time``
                    delta_time = tspan[index_time] - tspan[0]

                    # linearly evolving phi to future ``delta time`` - for i-th realization
                    time_evolution_with_K = delta_time * self.K[i].astype('float64')

                    # convert to double precision, because sometimes single precision overfloat
                    time_evolution_with_K = time_evolution_with_K.astype('float64')

                    phi_state_at_t_mc_array = np.matmul(init_phi_state_mc_array[i].astype('float64'), expm(time_evolution_with_K)) # phi_0 -> phi_t

                    # reconstruct x from phi state at feature
                    state_future_mc_array = self.model.reconstruct_with_i_realization(phi=phi_state_at_t_mc_array, i=i) # phi_t -> eta_rec_t

                    # here we will introduce reconstriction error
                    # add reconstruction noise -> it is like the white noise in ARMA model, not interacting with the flow. not a
                    # subscale turublence problem..
                    state_future_mc_array = state_future_mc_array + self.noise_rec[i][:state_future_mc_array.shape[1]]

                    # transform normalized state: eta, to original state
                    state_future_mc_array = self.model.transform_eta_to_x(state_future_mc_array) # eta_rec_t -> x_rec_t

                    state_list.append(state_future_mc_array)

                # append for each time's the whole realization
                state_total_mc_list.append(state_list)

            # if self.mode == 'MAP':
            #     QM_state_future_array = np.stack(state_total_mc_list, axis=0)
            # else:
            QM_state_future_array = np.squeeze(np.stack(state_total_mc_list, axis=0), axis=2)

        else:

            raise NotImplementedError('not yet..')




        return QM_state_future_array
from scipy import sparse
from scipy.sparse import linalg


dx = 1 / 20
nbr_points = int(1 / dx + 1)
n = nbr_points
m = 2 * n  # Big room has twice as many rows.

Dn = sparse.diags([1, -2, 1], [-1, 0, 1], shape=(n, n))
Dm = sparse.diags([1, -2, 1], [-1, 0, 1], shape=(m, m))


Dn_east = Dn.copy().tolil()
Dn_east[-1, -1] += 1
A0 = sparse.kronsum(Dn_east, Dn)

A1 = sparse.kronsum(Dn, Dm)

Dn_west = Dn.copy().tolil()
Dn_west[0, 0] += 1
A2 = sparse.kronsum(Dn_west, Dn)


# first room
u0 = np.zeros((n, n))
u0[0, :] += 15
u0[-1, :] += 15
u0[:, 0] += 40
u0[:, -1] += -1
Ejemplo n.º 25
0
def _build_derivative_matrix_structured_cartesian(
        mesh,
        derivative,
        order_accuracy,
        dimension='all',
        use_shifted_differences=False,
        return_1D_matrix=False,
        **kwargs):

    dims = list()
    if type(dimension) is str:
        dimension = [dimension]
    if 'all' in dimension:
        if mesh.dim > 1:
            dims.append('x')
        if mesh.dim > 2:
            dims.append('y')
        dims.append('z')
    else:
        for d in dimension:
            dims.append(d)

    # sh[-1] is always 'z'
    # sh[0] is always 'x' if in 2 or 3d
    # sh[1] is always 'y' if dim > 2
    sh = mesh.shape(include_bc=True, as_grid=True)

    if mesh.dim > 1:
        if 'x' in dims:
            lbc = _set_bc(mesh.x.lbc)
            rbc = _set_bc(mesh.x.rbc)
            delta = mesh.x.delta
            Dx = _build_derivative_matrix_part(
                sh[0],
                derivative,
                order_accuracy,
                h=delta,
                lbc=lbc,
                rbc=rbc,
                use_shifted_differences=use_shifted_differences)
        else:
            Dx = spsp.csr_matrix((sh[0], sh[0]))
    if mesh.dim > 2:
        if 'y' in dims:
            lbc = _set_bc(mesh.y.lbc)
            rbc = _set_bc(mesh.y.rbc)
            delta = mesh.y.delta
            Dy = _build_derivative_matrix_part(
                sh[1],
                derivative,
                order_accuracy,
                h=delta,
                lbc=lbc,
                rbc=rbc,
                use_shifted_differences=use_shifted_differences)
        else:
            Dy = spsp.csr_matrix((sh[1], sh[1]))

    if 'z' in dims:
        lbc = _set_bc(mesh.z.lbc)
        rbc = _set_bc(mesh.z.rbc)
        delta = mesh.z.delta
        Dz = _build_derivative_matrix_part(
            sh[-1],
            derivative,
            order_accuracy,
            h=delta,
            lbc=lbc,
            rbc=rbc,
            use_shifted_differences=use_shifted_differences)
    else:
        Dz = spsp.csr_matrix((sh[-1], sh[-1]))

    if return_1D_matrix and 'all' not in dims:
        if 'z' in dims:
            mtx = Dz
        elif 'y' in dims:
            mtx = Dy
        elif 'x' in dims:
            mtx = Dx
    else:
        if mesh.dim == 1:
            mtx = Dz.tocsr()
        if mesh.dim == 2:
            # kronsum in this order because wavefields are stored with 'z' in row
            # and 'x' in columns, then vectorized in 'C' order
            mtx = spsp.kronsum(Dz, Dx, format='csr')
        if mesh.dim == 3:
            mtx = spsp.kronsum(Dz,
                               spsp.kronsum(Dy, Dx, format='csr'),
                               format='csr')

    return mtx
Ejemplo n.º 26
0
# gradient operators
gradx = sparse.kron(build_grad(Nx), sparse.identity(Ny - 1))
grady = sparse.kron(sparse.identity(Nx - 1), build_grad(Ny))


def build_K(N):
    # builds N-1 x N - 1   K second defivative matrix
    data = np.array([-np.ones(N - 2), 2 * np.ones(N - 1), -np.ones(N - 2)])
    diags = np.array([-1, 0, 1])
    return sparse.diags(data, diags)


# Laplacian operator . Zero dirichlet boundary conditions
# why the hell is this reversed? Sigh.
K = sparse.kronsum(build_K(Ny), build_K(Nx))
Ksolve = linalg.factorized(K)


def build_interp(N):
    data = np.array([np.ones(N) / 2., np.ones(N - 1) / 2.])
    diags = np.array([0, 1])
    return sparse.diags(data, diags, shape=(N - 1, N))


interpy = sparse.kron(sparse.identity(Nx), build_interp(Ny))
interpx = sparse.kron(build_interp(Nx), sparse.identity(Ny))


def projection_pass(vx, vy):
    # alternating projection? Not necessary. In fact stupid. but easy.
Ejemplo n.º 27
0
# sys.exit()

## A3
D3           = np.copy(D)
D3[n-1, n-1] = -3
A3           = ut.sp_bmat_tridiag(I, D3, I, n)
"""


Dn = sparse.diags([1, -2, 1], [-1, 0, 1], shape=(n, n))
Dm = sparse.diags([1, -2, 1], [-1, 0, 1], shape=(m, m))


Dn_east = Dn.copy().tolil()
Dn_east[-1, -1] += 1
A1 = sparse.kronsum(Dn, Dn)

A2 = sparse.kronsum(Dm, Dn)

Dn_west = Dn.copy().tolil()
Dn_west[0, 0] += 1
A3 = sparse.kronsum(Dn, Dn)

# print(A1.toarray())
# print(A2.toarray())
# print(A3.toarray())
# sys.exit()

# Boundaries
gammaH = 40
normal = 15
Ejemplo n.º 28
0

Nx = int(4 / h)
Ny = int(4 / h)

Dx = np.zeros((Nx, Nx - 1))
np.fill_diagonal(Dx, 1)
np.fill_diagonal(Dx[1:, :], -1)

Dy = np.zeros((Ny, Ny - 1))
np.fill_diagonal(Dy, 1)
np.fill_diagonal(Dy[1:, :], -1)

Lxx = Dx.T @ Dx
Lyy = Dy.T @ Dy
A = -1 * sp.kronsum(Lxx, Lyy) / h**2

grid = np.mgrid[h:4:h, h:4:h]
x = grid[0]
y = grid[1]

u = u(x, y)
u = np.reshape(u, ((Nx - 1) * (Ny - 1)), order='F')


def forward(u0, A, dt):
    return (sp.identity(A.shape[0]) + dt * A) @ u0


def backward(u0, A, dt):
    return la.spsolve(sp.identity(A.shape[0]) - dt * A, u0)
Ejemplo n.º 29
0
def _create_sparse_poisson2d(n):
    P1d = _create_sparse_poisson1d(n)
    P2d = sparse.kronsum(P1d, P1d)
    assert_equal(P2d.shape, (n * n, n * n))
    return P2d
Ejemplo n.º 30
0
def _create_sparse_poisson2d(n):
    P1d = _create_sparse_poisson1d(n)
    P2d = sparse.kronsum(P1d, P1d)
    assert_equal(P2d.shape, (n*n, n*n))
    return P2d.tocsr()
Ejemplo n.º 31
0
    def __init__(self, config):
        self.config = config

        self.w = config['width']
        self.h = config['height']
        self.dt = config['delta_t']
        self.viscosity_k = config['viscosity_k']
        self.diffusion_k = config['diffusion_k']
        self.dissipation = config['dissipation']
        self.vorticity = config['vorticity']
        self.solver_iters = config['solver_iters']
        self.fast_advect = config['fast_advect']

        self.out_folder = config['out_folder']
        if not os.path.exists(self.out_folder):
            os.makedirs(self.out_folder)

        self.write_vel = config['write_vel']
        self.out_vel_folder = os.path.join(self.out_folder, 'vel')
        if self.write_vel and not os.path.exists(self.out_vel_folder):
            os.makedirs(self.out_vel_folder)

        color_keys = ('color_r', 'color_g', 'color_b')
        self.color = [config[k] for k in color_keys]
        self.color = np.array(self.color)[np.newaxis, np.newaxis, :]

        # Initialize scalar field(s)
        init_s = config.get('init_s', None)
        if os.path.exists(init_s):
            if init_s.endswith('npy'):
                self.s = np.load(init_s)
                while len(self.s.shape) < 3:
                    self.s = np.expand_dims(self.s, -1)
            else:
                self.s = imageio.imread(init_s) / 255.0
            print('Loaded scalar field from `%s`.' % init_s)
        else:
            self.s = np.zeros((self.h, self.w, 1))
        self.ns = self.s.shape[-1]  # number of scalar fields

        # Initialize velocity field
        init_v = config.get('init_v', None)
        if os.path.exists(init_v):
            self.v = np.load(init_v)
            print('Loaded velocity field from `%s`.' % init_v)
        else:
            self.v = np.zeros((self.h, self.w, 2))  # order: (vx, vy)

        # For warping
        if self.fast_advect:
            xx, yy = np.meshgrid(np.arange(self.w), np.arange(self.h))
            self.base_coords = np.stack((xx, yy), axis=-1)  # (h, w, 2)

        # Set guiding attributes
        self.target_v = None
        self.guiding = config['guiding']
        target_v_path = config['target_v']
        if os.path.exists(target_v_path):
            self.target_v = np.load(target_v_path)
            print('Loaded target velocity field from `%s`.' % target_v_path)

        gauss = utils.gaussian2d(self.config['blur_size'])
        self.blur_kernel = 2.0 * gauss @ gauss
        self.blur_kernel = self.blur_kernel[:, :, np.newaxis]
        self.blur = lambda field: convolve(field, self.blur_kernel, 'same')

        # Blur target
        self.target_v = self.blur(self.target_v)

        # Algorithm-specific guiding setup
        self.guiding_alg = config['guiding_alg']
        self.pd_params = config.get('pd_params', {})
        self.pd_x, self.pd_y, self.pd_z = None, None, None
        self.cw, self.tw, self.lsqr_A = None, None, None
        if self.guiding_alg == 'pd':
            self.pd_params = config['pd_params']
            self.pd_x = np.zeros_like(self.v)
            self.pd_y = np.zeros_like(self.v)
            self.pd_z = np.zeros_like(self.v)
        elif self.guiding_alg == 'lsqr':
            # Current/target weights
            lsqr_params = config.get('lsqr_params', {})
            self.cw = lsqr_params.get('current_w', 0.5)
            self.tw = lsqr_params.get('target_w', 0.5)
            weight_sum = self.cw + self.tw
            self.cw = float(self.cw) / weight_sum
            self.tw = float(self.tw) / weight_sum

            # Define A
            self.define_lsqr_A()

        # Ref: Philip Zucker (https://bit.ly/2Tx2LuE)
        def lapl(N):
            diagonals = np.array(
                [-np.ones(N - 1), 2 * np.ones(N), -np.ones(N - 1)])
            return sparse.diags(diagonals, [-1, 0, 1])

        lapl2 = sparse.kronsum(lapl(self.w), lapl(self.h))
        self.project_solve = sparse.linalg.factorized(lapl2)

        self.frame_no = 0
Ejemplo n.º 32
0
def calc_Ekin(dim_basis, n_part, basis_specs, eigensys_coord):
    """Calculates the kinetic energy matrix.

        1) fill 1-particle matrix for 1 Cartesian dimension
        2) fill the N-particle, D-cart-dim matrix via a double Kronecker sum

    :dim_basis: dvr basis dimension '=' nbr of grid points (for ONE dimension)
    :n_part: nbr of particles
    :basis_specs: type and parameters of the variation basis (includes spatial dimensionality)
    :eigensys_coord: eigenvectors and transformation matrix from variational to discrete basis

    :return: Kinetic energy matrix
    """
    tmp = np.zeros((dim_basis, dim_basis))
    tmp2 = np.zeros((dim_basis, dim_basis))

    # analytic DVR of the kinetic-energy operator from
    # The Journal of Chemical Physics 96, 1982 (1992), Eq. A6a/b
    if basis_specs[0] == 'SINE':
        # infer the constant grid spacing (dx) and the box length (L) from
        # the eigenvalues; as the eigenvalues do not include the edges, 2*dx
        # has to be added;

        if sum(
                np.isclose(np.diff(eigensys_coord[0]),
                           np.roll(np.diff(eigensys_coord[0]),
                                   1))) != len(eigensys_coord[0]) - 1:
            print(
                'Grid points of the SINE basis are not equally spaced! Exiting...'
            )
            exit()

        dx = abs(eigensys_coord[0][1] - eigensys_coord[0][0])
        L = abs(eigensys_coord[0][-1] - eigensys_coord[0][0]) + 2 * dx
        for i in range(dim_basis):
            for ip in range(dim_basis):
                i_idx = i + 1
                ip_idx = ip + 1  # to array indices (i,ip) add 1
                if i == ip:
                    tmp[i,
                        i] = (((2. * (dim_basis + 1)**2 + 1) / 3.) -
                              np.sin(i_idx * (np.pi / (dim_basis + 1)))**(-2))
                else:
                    tmp[i, ip] = ((-1)**(i_idx - ip_idx)) * (
                        np.sin(np.pi / (2. * (dim_basis + 1)) *
                               (i_idx - ip_idx))**(-2) -
                        np.sin(np.pi / (2. * (dim_basis + 1)) *
                               (i_idx + ip_idx))**(-2))
                tmp[i, ip] *= np.pi**2 / (2. * L**2)

        tmp = tmp / (2. * basis_specs[1][3])
        # this factor has to be verified!

    if basis_specs[0] == 'HO':

        for alpha in range(dim_basis):
            for beta in range(dim_basis):
                for k in range(dim_basis):
                    tmp[alpha, beta] += basis_specs[1][3] * eigensys_coord[1][
                        k, alpha] * (k + 0.5) * eigensys_coord[1][k, beta]
                if alpha == beta:
                    tmp[alpha, beta] -= 0.5 * basis_specs[1][2] * basis_specs[
                        1][3]**2 * (eigensys_coord[0][alpha] -
                                    basis_specs[1][1])**2

    mEkin = csr_matrix(0)
    # the two loops represent the Kronecker sums which generate the full matrix
    # for N particles, each in D Cartesian dimensions
    for particle in range(n_part):
        for cart_dim in range(basis_specs[1][0]):
            mEkin = kronsum(mEkin, tmp)
    return mEkin