def _rebuild_operators(self):

        ConstantDensityAcousticTimeScalar_1D._rebuild_operators(self)

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh,
                                           2,
                                           self.spatial_accuracy_order)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dz
            oc.Dz = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='z')

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # Stiffness matrix K doesn't change
            oc.K = spsp.bmat([[-oc.L,    -oc.Dz],
                              [oc.sigmaz*oc.Dz, oc.sigmaz]])

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m = make_diag_mtx((C**-2).reshape(-1,))

        C = spsp.bmat([[oc.sigmaz*oc.m, None],
                       [None, oc.I]]) / self.dt

        M = spsp.bmat([[oc.m,     None],
                       [None, oc.empty]]) / self.dt**2

        Stilde_inv = M+C
        Stilde_inv.data = 1./Stilde_inv.data

        self.A_k = Stilde_inv*(2*M - oc.K + C)
        self.A_km1 = -1*Stilde_inv*(M)
        self.A_f = Stilde_inv
    def _rebuild_operators(self):

        ConstantDensityAcousticTimeScalar_1D._rebuild_operators(self)

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh,
                                           2,
                                           self.spatial_accuracy_order)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dz
            oc.Dz = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='z')

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # Stiffness matrix K doesn't change
            oc.K = spsp.bmat([[          -oc.L,    -oc.Dz],
                              [oc.sigmaz*oc.Dz, oc.sigmaz]])

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m = make_diag_mtx((C**-2).reshape(-1,))

        C = spsp.bmat([[oc.sigmaz*oc.m, None],
                       [          None, oc.I]]) / self.dt

        M = spsp.bmat([[oc.m,     None],
                       [None, oc.empty]]) / self.dt**2

        Stilde_inv = M+C
        Stilde_inv.data = 1./Stilde_inv.data

        self.A_k   = Stilde_inv*(2*M - oc.K + C)
        self.A_km1 = -1*Stilde_inv*(M)
        self.A_f   = Stilde_inv
 def _build_helmholtz_operator(self, nu):
     omega = 2 * np.pi * nu
     # we build the right helmholtz operator compact or not
     if self._local_support_spec['spatial_dimension'] == 1:
         # 1D the compact is not implemented so we raise a warming and use the auxiliary field PML
         return (-(omega**2) * self.M + omega * 1j * self.C +
                 self.K).tocsc()
     elif self.mesh.x.lbc.type == 'pml':
         if self.mesh.x.lbc.domain_bc.compact:
             # building the compact operator
             oc = self.operator_components
             if self._local_support_spec['spatial_dimension'] == 2:
                 dx, dz = self.mesh.deltas
                 length_pml_x = dx * (self.mesh.x.lbc.n - 1)
                 length_pml_z = dz * (self.mesh.z.lbc.n - 1)
                 H1 = -(omega**2) * oc.M
                 H2 = make_diag_mtx(-1j / (omega * length_pml_x) * oc.sxp /
                                    (1 - 1j / omega * oc.sx)**3).dot(oc.Dx)
                 H3 = make_diag_mtx(-1j / (omega * length_pml_z) * oc.szp /
                                    (1 - 1j / omega * oc.sz)**3).dot(oc.Dz)
                 H4 = -make_diag_mtx(1.0 / (1 - 1j / omega * oc.sx)**2).dot(
                     oc.Dxx)
                 H5 = -make_diag_mtx(1.0 / (1 - 1j / omega * oc.sz)**2).dot(
                     oc.Dzz)
                 return (H1 + H2 + H3 + H4 + H5).tocsc(
                 )  # csc is used for the sparse solvers right now
             if self._local_support_spec['spatial_dimension'] == 3:
                 dx, dy, dz = self.mesh.deltas
                 length_pml_x = dx * (self.mesh.x.lbc.n - 1)
                 length_pml_y = dy * (self.mesh.y.lbc.n - 1)
                 length_pml_z = dz * (self.mesh.z.lbc.n - 1)
                 H1 = -(omega**2) * oc.M
                 H2 = make_diag_mtx(-1j / (omega * length_pml_x) * oc.sxp /
                                    (1 - 1j / omega * oc.sx)**3).dot(oc.Dx)
                 H3 = make_diag_mtx(-1j / (omega * length_pml_y) * oc.syp /
                                    (1 - 1j / omega * oc.sy)**3).dot(oc.Dy)
                 H4 = make_diag_mtx(-1j / (omega * length_pml_z) * oc.szp /
                                    (1 - 1j / omega * oc.sz)**3).dot(oc.Dz)
                 H5 = -make_diag_mtx(1.0 / (1 - 1j / omega * oc.sx)**2).dot(
                     oc.Dxx)
                 H6 = -make_diag_mtx(1.0 / (1 - 1j / omega * oc.sy)**2).dot(
                     oc.Dyy)
                 H7 = -make_diag_mtx(1.0 / (1 - 1j / omega * oc.sz)**2).dot(
                     oc.Dzz)
                 return (H1 + H2 + H3 + H4 + H5 + H6 + H7).tocsc()
         else:
             return (-(omega**2) * self.M + omega * 1j * self.C +
                     self.K).tocsc()
     else:
         return (
             -(omega**2) * self.M + omega * 1j * self.C +
             self.K).tocsc()  # csc is used for the sparse solvers right now
Example #4
0
    def _rebuild_operators(self):

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        oc.I = spsp.eye(dof, dof)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh,
                                           2,
                                           self.spatial_accuracy_order,
                                           use_shifted_differences=self.spatial_shifted_differences)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dz
            oc.Dz = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='z',
                                            use_shifted_differences=self.spatial_shifted_differences)

            # build other useful things
            oc.empty = spsp.csr_matrix((dof, dof))

            # Stiffness matrix K doesn't change
            self.K = spsp.bmat([[-oc.L,    -oc.Dz],
                                [oc.sigmaz*oc.Dz, oc.sigmaz]])

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m = make_diag_mtx((C**-2).reshape(-1,))

        self.C = spsp.bmat([[oc.sigmaz*oc.m, None],
                            [None,           oc.I]])

        self.M = spsp.bmat([[oc.m,     None],
                            [None, oc.empty]])

        self.dM = oc.I
        self.dC = oc.sigmaz
        self.dK = 0
    def _rebuild_operators(self):

        ConstantDensityAcousticTimeScalar_2D._rebuild_operators(self)

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            nx = self.mesh.x.n
            nz = self.mesh.z.n

            #We actually don't need to correct the operators for the boundary nodes. But it will make the final matrix a little more sparse and therefore faster. Also, it makes is more clear that something needs to happen to the boundary. Any failure to do so can easily be seen by eye.
            self.left_boundary_nodes = np.arange(
                0, nz)  #includes left corner dirichlet nodes
            self.right_boundary_nodes = np.arange(
                (nx - 1) * nz, nx * nz)  #uncludes right corner dirichlet nodes
            self.top_boundary_nodes = np.arange(
                nz, (nx - 1) * nz,
                nx)  #does not include corner dirichlet nodes
            self.bot_boundary_nodes = np.arange(
                2 * nz - 1, nx * nz - 1,
                nx)  #does not include corner dirichlet nodes
            self.all_boundary_nodes = np.concatenate([
                self.left_boundary_nodes, self.right_boundary_nodes,
                self.top_boundary_nodes, self.bot_boundary_nodes
            ])

            # build laplacian
            oc.L = build_derivative_matrix(self.mesh, 2,
                                           self.spatial_accuracy_order)

            #Set the rows corresponding to the boundary nodes in oc.L to zero (could be any junk value). This is not necessary, but will indicate that I will have to correct the boundary values at the end of the time increment.
            oc.L = self._zero_mat_rows(oc.L, self.all_boundary_nodes)

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            oc._numpy_components_built = True

        C = self.model_parameters.C  #just wavespeed. Don't confuse with the matrix C that used to be here for a while
        oc.m = make_diag_mtx((C**-2).reshape(-1, ))

        K = -oc.L

        M = oc.m / self.dt**2
        M_bc_zero = self._zero_mat_rows(
            M, self.all_boundary_nodes
        )  #put boundary values to zero, not really necessary because boundary values will be overwritten anyway. But easier to see that something must happen when the algorithm will default them to zero so you know you need to correct them.
        Stilde_inv = M
        Stilde_inv.data = 1. / Stilde_inv.data

        self.A_k = Stilde_inv * (2 * M_bc_zero - K)
        self.A_km1 = -1 * Stilde_inv * (M_bc_zero)
        self.A_f = Stilde_inv
Example #6
0
def _turn_sparse_rows_to_identity(A, rows_to_keep, rows_to_change):
    #Convenience function for removing some rows from the sparse laplacian
    #Had some major performance problems by simply slicing in all the matrix formats I tried.

    nr, nc = A.shape
    if nr != nc:
        raise Exception('assuming square matrix')

    #Create diagonal matrix. When we multiply A by this matrix we can remove rows
    rows_to_keep_diag = np.zeros(nr, dtype='int32')
    rows_to_keep_diag[rows_to_keep] = 1
    diag_mat_remove_rows = make_diag_mtx(rows_to_keep_diag)

    #The matrix below has the rows we want to turn into identity turned to 0
    A_with_rows_removed = diag_mat_remove_rows * A

    #Make diag matrix that has diagonal entries in the rows we want to be identity
    rows_to_change_diag = np.zeros(nr, dtype='int32')
    rows_to_change_diag[rows_to_change] = 1
    A_with_identity_rows = make_diag_mtx(rows_to_change_diag)

    A_modified = A_with_rows_removed + A_with_identity_rows
    return A_modified
Example #7
0
def _turn_sparse_rows_to_identity(A, rows_to_keep, rows_to_change):
    #Convenience function for removing some rows from the sparse laplacian
    #Had some major performance problems by simply slicing in all the matrix formats I tried.

    nr,nc = A.shape
    if nr != nc:
        raise Exception('assuming square matrix')

    #Create diagonal matrix. When we multiply A by this matrix we can remove rows
    rows_to_keep_diag = np.zeros(nr, dtype='int32')
    rows_to_keep_diag[rows_to_keep] = 1
    diag_mat_remove_rows = make_diag_mtx(rows_to_keep_diag)

    #The matrix below has the rows we want to turn into identity turned to 0
    A_with_rows_removed = diag_mat_remove_rows*A

    #Make diag matrix that has diagonal entries in the rows we want to be identity
    rows_to_change_diag = np.zeros(nr, dtype='int32')
    rows_to_change_diag[rows_to_change] = 1
    A_with_identity_rows = make_diag_mtx(rows_to_change_diag)

    A_modified = A_with_rows_removed + A_with_identity_rows
    return A_modified
    def _rebuild_operators(self):

        dof = self.mesh.dof(include_bc=True)

        # a more readable reference
        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh, 2,
                                           self.spatial_accuracy_order)

            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.minus_sigmax = make_diag_mtx(-sx)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.minus_sigmaz = make_diag_mtx(-sz)

            # build Dx
            oc.Dx = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='x')

            # build Dz
            oc.Dz = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='z')

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_xz = make_diag_mtx(sx * sz)
            oc.minus_sigma_xPz = oc.minus_sigmax + oc.minus_sigmaz
            oc.sigma_zMx_Dx = make_diag_mtx(sz - sx) * oc.Dx
            oc.sigma_xMz_Dz = make_diag_mtx(sx - sz) * oc.Dz

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m_inv = make_diag_mtx((C**2).reshape(-1, ))

        self.A = spsp.bmat(
            [[oc.empty, oc.I, oc.empty, oc.empty],
             [
                 oc.m_inv * oc.L - oc.sigma_xz, oc.minus_sigma_xPz,
                 oc.m_inv * oc.Dx, oc.m_inv * oc.Dz
             ], [oc.sigma_zMx_Dx, oc.empty, oc.minus_sigmax, oc.empty],
             [oc.sigma_xMz_Dz, oc.empty, oc.empty, oc.minus_sigmaz]])
    def _rebuild_operators(self):

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh,
                                           2,
                                           self.spatial_accuracy_order)

            # build sigmaz (stored as -1*sigmaz)
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.minus_sigmaz = make_diag_mtx(-sz)

            # build Dz
            oc.Dz = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='z')

            # build other useful things
            oc.I     = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m_inv = make_diag_mtx((C**2).reshape(-1,))

        self.A = spsp.bmat([[oc.empty,              oc.I,            oc.empty       ],
                            [oc.m_inv*oc.L,         oc.minus_sigmaz, oc.m_inv*oc.Dz ],
                            [oc.minus_sigmaz*oc.Dz, oc.empty,        oc.minus_sigmaz]])
 def _build_helmholtz_operator(self, nu):
     omega = 2*np.pi*nu
     # we build the right helmholtz operator compact or not
     if self._local_support_spec['spatial_dimension']==1:
         # 1D the compact is not implemented so we raise a warming and use the auxiliary field PML
         return (-(omega**2)*self.M + omega*1j*self.C + self.K).tocsc()
     elif self.mesh.x.lbc.type == 'pml':
         if self.mesh.x.lbc.domain_bc.compact:
             # building the compact operator
             oc  = self.operator_components
             if self._local_support_spec['spatial_dimension']==2:
                 dx, dz = self.mesh.deltas
                 length_pml_x = dx * (self.mesh.x.lbc.n -1 )
                 length_pml_z = dz * (self.mesh.z.lbc.n -1 )
                 H1 = -(omega**2)*oc.M
                 H2 = make_diag_mtx(-1j/(omega*length_pml_x) * oc.sxp / (1 - 1j/omega * oc.sx)**3).dot(oc.Dx)
                 H3 = make_diag_mtx(-1j/(omega*length_pml_z) * oc.szp / (1 - 1j/omega * oc.sz)**3).dot(oc.Dz)
                 H4 = - make_diag_mtx(1.0/(1 - 1j/omega * oc.sx)**2).dot(oc.Dxx)
                 H5 = - make_diag_mtx(1.0/(1 - 1j/omega * oc.sz)**2).dot(oc.Dzz)
                 return (H1 + H2 + H3 + H4 + H5).tocsc() # csc is used for the sparse solvers right now
             if self._local_support_spec['spatial_dimension']==3:
                 dx, dy, dz = self.mesh.deltas
                 length_pml_x = dx * (self.mesh.x.lbc.n -1 )
                 length_pml_y = dy * (self.mesh.y.lbc.n -1 )
                 length_pml_z = dz * (self.mesh.z.lbc.n -1 )
                 H1 = -(omega**2)*oc.M
                 H2 = make_diag_mtx(-1j/(omega*length_pml_x) * oc.sxp / (1 - 1j/omega * oc.sx)**3).dot(oc.Dx)
                 H3 = make_diag_mtx(-1j/(omega*length_pml_y) * oc.syp / (1 - 1j/omega * oc.sy)**3).dot(oc.Dy)
                 H4 = make_diag_mtx(-1j/(omega*length_pml_z) * oc.szp / (1 - 1j/omega * oc.sz)**3).dot(oc.Dz)
                 H5 = - make_diag_mtx(1.0/(1 - 1j/omega * oc.sx)**2).dot(oc.Dxx)
                 H6 = - make_diag_mtx(1.0/(1 - 1j/omega * oc.sy)**2).dot(oc.Dyy)
                 H7 = - make_diag_mtx(1.0/(1 - 1j/omega * oc.sz)**2).dot(oc.Dzz)
                 return (H1 + H2 + H3 + H4 + H5 + H6 + H7).tocsc() 
         else:
             return (-(omega**2)*self.M + omega*1j*self.C + self.K).tocsc()
     else:
         return (-(omega**2)*self.M + omega*1j*self.C + self.K).tocsc() # csc is used for the sparse solvers right now
    def _rebuild_operators(self):

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh,
                                           2,
                                           self.spatial_accuracy_order)

            # build sigmaz (stored as -1*sigmaz)
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.minus_sigmaz = make_diag_mtx(-sz)

            # build Dz
            oc.Dz = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='z')

            # build other useful things
            oc.I     = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m_inv = make_diag_mtx((C**2).reshape(-1,))

        self.A = spsp.bmat([[oc.empty,              oc.I,            oc.empty       ],
                            [oc.m_inv*oc.L,         oc.minus_sigmaz, oc.m_inv*oc.Dz ],
                            [oc.minus_sigmaz*oc.Dz, oc.empty,        oc.minus_sigmaz]])
    def _rebuild_operators(self):

        dof = self.mesh.dof(include_bc=True)

        # a more readable reference
        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh,
                                           2,
                                           self.spatial_accuracy_order)

            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.minus_sigmax = make_diag_mtx(-sx)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.minus_sigmaz = make_diag_mtx(-sz)

            # build Dx
            oc.Dx = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='x')

            # build Dz
            oc.Dz = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='z')

            # build other useful things
            oc.I     = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_xz = make_diag_mtx(sx*sz)
            oc.minus_sigma_xPz = oc.minus_sigmax + oc.minus_sigmaz
            oc.sigma_zMx_Dx = make_diag_mtx(sz-sx)*oc.Dx
            oc.sigma_xMz_Dz = make_diag_mtx(sx-sz)*oc.Dz

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m_inv = make_diag_mtx((C**2).reshape(-1,))

        self.A = spsp.bmat([[oc.empty,                  oc.I,               oc.empty,        oc.empty        ],
                            [oc.m_inv*oc.L-oc.sigma_xz, oc.minus_sigma_xPz, oc.m_inv*oc.Dx,  oc.m_inv*oc.Dz  ],
                            [oc.sigma_zMx_Dx,           oc.empty,           oc.minus_sigmax, oc.empty        ],
                            [oc.sigma_xMz_Dz,           oc.empty,           oc.empty,        oc.minus_sigmaz ]])
    def _rebuild_operators(self):
        if self.mesh.x.lbc.type == 'pml' and self.compact:
            # build intermediates for the compact operator
            dof = self.mesh.dof(include_bc=True)

            oc = self.operator_components

            built = oc.get('_numpy_components_built', False)
            oc.M = make_diag_mtx(self.model_parameters.C.squeeze()**-2)
            oc.I = spsp.eye(dof, dof)
            # build the static components
            if not built:
                # build Dxx
                oc.Dxx = build_derivative_matrix(
                    self.mesh,
                    2,
                    self.spatial_accuracy_order,
                    dimension='x',
                    use_shifted_differences=self.spatial_shifted_differences)
                # build Dzz
                oc.Dzz = build_derivative_matrix(
                    self.mesh,
                    2,
                    self.spatial_accuracy_order,
                    dimension='z',
                    use_shifted_differences=self.spatial_shifted_differences)
                # build Dx
                oc.Dx = build_derivative_matrix(
                    self.mesh,
                    1,
                    self.spatial_accuracy_order,
                    dimension='x',
                    use_shifted_differences=self.spatial_shifted_differences)

                # build Dz
                oc.Dz = build_derivative_matrix(
                    self.mesh,
                    1,
                    self.spatial_accuracy_order,
                    dimension='z',
                    use_shifted_differences=self.spatial_shifted_differences)

                # build sigma
                oc.sx, oc.sz, oc.sxp, oc.szp = self._sigma_PML(self.mesh)

                oc._numpy_components_built = True

            self.dK = 0
            self.dC = 0
            self.dM = oc.I
        else:
            # build intermediates for operator with auxiliary fields
            dof = self.mesh.dof(include_bc=True)

            oc = self.operator_components
            oc.I = spsp.eye(dof, dof)

            built = oc.get('_numpy_components_built', False)

            # build the static components
            if not built:
                # build laplacian
                oc.L = build_derivative_matrix(
                    self.mesh,
                    2,
                    self.spatial_accuracy_order,
                    use_shifted_differences=self.spatial_shifted_differences)

                # build sigmax
                sx = build_sigma(self.mesh, self.mesh.x)
                oc.sigmax = make_diag_mtx(sx)

                # build sigmaz
                sz = build_sigma(self.mesh, self.mesh.z)
                oc.sigmaz = make_diag_mtx(sz)

                # build Dx
                oc.minus_Dx = build_derivative_matrix(
                    self.mesh,
                    1,
                    self.spatial_accuracy_order,
                    dimension='x',
                    use_shifted_differences=self.spatial_shifted_differences)
                oc.minus_Dx.data *= -1

                # build Dz
                oc.minus_Dz = build_derivative_matrix(
                    self.mesh,
                    1,
                    self.spatial_accuracy_order,
                    dimension='z',
                    use_shifted_differences=self.spatial_shifted_differences)
                oc.minus_Dz.data *= -1

                # build other useful things
                oc.I = spsp.eye(dof, dof)
                oc.empty = spsp.csr_matrix((dof, dof))

                # useful intermediates
                oc.sigma_xz = make_diag_mtx(sx * sz)
                oc.sigma_xPz = oc.sigmax + oc.sigmaz

                oc.minus_sigma_zMx_Dx = make_diag_mtx((sz - sx)) * oc.minus_Dx
                oc.minus_sigma_xMz_Dz = make_diag_mtx((sx - sz)) * oc.minus_Dz

                oc._numpy_components_built = True

            C = self.model_parameters.C
            oc.m = make_diag_mtx((C**-2).reshape(-1, ))

            self.K = spsp.bmat(
                [[oc.m * oc.sigma_xz - oc.L, oc.minus_Dx, oc.minus_Dz],
                 [oc.minus_sigma_zMx_Dx, oc.sigmax, oc.empty],
                 [oc.minus_sigma_xMz_Dz, oc.empty, oc.sigmaz]])

            self.C = spsp.bmat([[oc.m * oc.sigma_xPz, oc.empty, oc.empty],
                                [oc.empty, oc.I, oc.empty],
                                [oc.empty, oc.empty, oc.I]])

            self.M = spsp.bmat([[oc.m, oc.empty, oc.empty],
                                [oc.empty, oc.empty, oc.empty],
                                [oc.empty, oc.empty, oc.empty]])

            self.dK = oc.sigma_xz
            self.dC = oc.sigma_xPz
            self.dM = oc.I
    def _rebuild_operators(self):

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh,
                                           2,
                                           self.spatial_accuracy_order,
                                           use_shifted_differences=self.spatial_shifted_differences)

            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.sigmax = make_diag_mtx(sx)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dx
            oc.minus_Dx = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='x',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            oc.minus_Dx.data *= -1

            # build Dz
            oc.minus_Dz = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='z',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            oc.minus_Dz.data *= -1

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_xz  = make_diag_mtx(sx*sz)
            oc.sigma_xPz = oc.sigmax + oc.sigmaz

            oc.minus_sigma_zMx_Dx = make_diag_mtx((sz-sx))*oc.minus_Dx
            oc.minus_sigma_xMz_Dz = make_diag_mtx((sx-sz))*oc.minus_Dz

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m = make_diag_mtx((C**-2).reshape(-1,))

        self.K = spsp.bmat([[oc.m*oc.sigma_xz-oc.L, oc.minus_Dx, oc.minus_Dz ],
                            [oc.minus_sigma_zMx_Dx, oc.sigmax,   oc.empty    ],
                            [oc.minus_sigma_xMz_Dz, oc.empty,    oc.sigmaz   ]])

        self.C = spsp.bmat([[oc.m*oc.sigma_xPz, oc.empty, oc.empty],
                            [oc.empty,          oc.I,     oc.empty],
                            [oc.empty,          oc.empty, oc.I    ]])

        self.M = spsp.bmat([[    oc.m, oc.empty, oc.empty],
                            [oc.empty, oc.empty, oc.empty],
                            [oc.empty, oc.empty, oc.empty]])
    def _rebuild_operators(self):
        if self.mesh.x.lbc.type == 'pml' and self.compact:
            # build intermediates for the compact operator
            raise ValidationFunctionError(
                " This solver is in construction and is not yet complete. For variable density and compact PML."
            )
            dof = self.mesh.dof(include_bc=True)

            oc = self.operator_components

            built = oc.get('_numpy_components_built', False)
            oc.M = make_diag_mtx(self.model_parameters.C.squeeze()**-2)
            # build the static components
            if not built:
                # build Dxx
                oc.Dxx = build_derivative_matrix(
                    self.mesh,
                    2,
                    self.spatial_accuracy_order,
                    dimension='x',
                    use_shifted_differences=self.spatial_shifted_differences)
                # build Dzz
                oc.Dzz = build_derivative_matrix(
                    self.mesh,
                    2,
                    self.spatial_accuracy_order,
                    dimension='z',
                    use_shifted_differences=self.spatial_shifted_differences)
                # build Dx
                oc.Dx = build_derivative_matrix(
                    self.mesh,
                    1,
                    self.spatial_accuracy_order,
                    dimension='x',
                    use_shifted_differences=self.spatial_shifted_differences)

                # build Dz
                oc.Dz = build_derivative_matrix(
                    self.mesh,
                    1,
                    self.spatial_accuracy_order,
                    dimension='z',
                    use_shifted_differences=self.spatial_shifted_differences)

                # build sigma
                oc.sx, oc.sz, oc.sxp, oc.szp = self._sigma_PML(self.mesh)

                oc._numpy_components_built = True
        else:
            # build intermediates for operator with auxiliary fields
            dof = self.mesh.dof(include_bc=True)

            oc = self.operator_components

            built = oc.get('_numpy_components_built', False)

            # build the static components
            if not built:
                # build sigmax
                sx = build_sigma(self.mesh, self.mesh.x)
                oc.sigmax = make_diag_mtx(sx)

                # build sigmaz
                sz = build_sigma(self.mesh, self.mesh.z)
                oc.sigmaz = make_diag_mtx(sz)

                # build Dx
                oc.minus_Dx = build_derivative_matrix(
                    self.mesh,
                    1,
                    self.spatial_accuracy_order,
                    dimension='x',
                    use_shifted_differences=self.spatial_shifted_differences)
                oc.minus_Dx.data *= -1

                # build Dz
                oc.minus_Dz = build_derivative_matrix(
                    self.mesh,
                    1,
                    self.spatial_accuracy_order,
                    dimension='z',
                    use_shifted_differences=self.spatial_shifted_differences)
                oc.minus_Dz.data *= -1

                # build other useful things
                oc.I = spsp.eye(dof, dof)
                oc.empty = spsp.csr_matrix((dof, dof))

                # useful intermediates
                oc.sigma_xz = make_diag_mtx(sx * sz)
                oc.sigma_xPz = oc.sigmax + oc.sigmaz

                oc.minus_sigma_zMx_Dx = make_diag_mtx((sz - sx)) * oc.minus_Dx
                oc.minus_sigma_xMz_Dz = make_diag_mtx((sx - sz)) * oc.minus_Dz

                oc._numpy_components_built = True

        kappa = self.model_parameters.kappa
        rho = self.model_parameters.rho
        oc.m1 = make_diag_mtx((kappa**-1).reshape(-1, ))
        oc.m2 = make_diag_mtx((rho**-1).reshape(-1, ))
        # build heterogenous laplacian
        sh = self.mesh.shape(include_bc=True, as_grid=True)
        deltas = [self.mesh.x.delta, self.mesh.z.delta]
        oc.L = build_derivative_matrix_VDA(self.mesh,
                                           2,
                                           self.spatial_accuracy_order,
                                           alpha=rho**-1)

        # oc.L is a heterogenous laplacian operator. It computes div(m2 grad), where m2 = 1/rho.
        # Currently the creation of oc.L is slow. This is because we have implemented a cenetered heterogenous laplacian.
        # To speed up computation, we could compute a div(m2 grad) operator that is not centered by simply multiplying
        # a divergence operator by oc.m2 by a gradient operator.

        self.K = spsp.bmat([[
            oc.m1 * oc.sigma_xz - oc.L, oc.minus_Dx * oc.m2,
            oc.minus_Dz * oc.m2
        ], [oc.minus_sigma_zMx_Dx, oc.sigmax, oc.empty],
                            [oc.minus_sigma_xMz_Dz, oc.empty, oc.sigmaz]])

        self.C = spsp.bmat([[oc.m1 * oc.sigma_xPz, oc.empty, oc.empty],
                            [oc.empty, oc.I, oc.empty],
                            [oc.empty, oc.empty, oc.I]])

        self.M = spsp.bmat([[oc.m1, oc.empty, oc.empty],
                            [oc.empty, oc.empty, oc.empty],
                            [oc.empty, oc.empty, oc.empty]])
Example #16
0
    def _rebuild_operators(self):

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.sigmax = make_diag_mtx(sx)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dx
            oc.minus_Dx = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='x',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            oc.minus_Dx.data *= -1

            # build Dz
            oc.minus_Dz = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='z',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            oc.minus_Dz.data *= -1

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_xz  = make_diag_mtx(sx*sz)
            oc.sigma_xPz = oc.sigmax + oc.sigmaz

            oc.minus_sigma_zMx_Dx = make_diag_mtx((sz-sx))*oc.minus_Dx
            oc.minus_sigma_xMz_Dz = make_diag_mtx((sx-sz))*oc.minus_Dz

            oc._numpy_components_built = True

        kappa = self.model_parameters.kappa
        rho = self.model_parameters.rho
        oc.m1 = make_diag_mtx((kappa**-1).reshape(-1,))
        oc.m2 = make_diag_mtx((rho**-1).reshape(-1,))
        # build heterogenous laplacian
        sh = self.mesh.shape(include_bc=True,as_grid=True)
        deltas = [self.mesh.x.delta,self.mesh.z.delta]
        oc.L = build_heterogenous_laplacian(sh,rho**-1,deltas)

        # oc.L is a heterogenous laplacian operator. It computes div(m2 grad), where m2 = 1/rho. 
        # Currently the creation of oc.L is slow. This is because we have implemented a cenetered heterogenous laplacian.
        # To speed up computation, we could compute a div(m2 grad) operator that is not centered by simply multiplying
        # a divergence operator by oc.m2 by a gradient operator.

        self.K = spsp.bmat([[oc.m1*oc.sigma_xz-oc.L, oc.minus_Dx*oc.m2, oc.minus_Dz*oc.m2 ],
                            [oc.minus_sigma_zMx_Dx, oc.sigmax,   oc.empty    ],
                            [oc.minus_sigma_xMz_Dz, oc.empty,    oc.sigmaz   ]])

        self.C = spsp.bmat([[oc.m1*oc.sigma_xPz, oc.empty, oc.empty],
                            [oc.empty,          oc.I,     oc.empty],
                            [oc.empty,          oc.empty, oc.I    ]])

        self.M = spsp.bmat([[    oc.m1, oc.empty, oc.empty],
                            [oc.empty, oc.empty, oc.empty],
                            [oc.empty, oc.empty, oc.empty]])
    def _rebuild_operators(self):
        if self.mesh.x.lbc.type == 'pml' and self.compact:
          # build intermediates for compact operator 
          dof = self.mesh.dof(include_bc=True)
          oc = self.operator_components
          built = oc.get('_numpy_components_built', False)
          oc.M = make_diag_mtx(self.model_parameters.C.squeeze()**-2)
          # build the static components
          if not built:          
            # build Dxx
            oc.Dxx = build_derivative_matrix(self.mesh,
                                                  2,
                                                  self.spatial_accuracy_order,
                                                  dimension='x',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            # build Dzz
            oc.Dzz = build_derivative_matrix(self.mesh,
                                                  2,
                                                  self.spatial_accuracy_order,
                                                  dimension='z',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            # build Dyy
            oc.Dyy = build_derivative_matrix(self.mesh,
                                                  2,
                                                  self.spatial_accuracy_order,
                                                  dimension='y',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            # build Dx
            oc.Dx = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='x',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            
            # build Dz
            oc.Dz = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='z',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            # build Dz
            oc.Dy = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='y',
                                                  use_shifted_differences=self.spatial_shifted_differences)
                                                  
            # build sigma
            oc.sx, oc.sy, oc.sz, oc.sxp, oc.syp, oc.szp = self._sigma_PML(self.mesh)

            oc._numpy_components_built = True

        else :
          # build intermediates for operator with auxiliary fields
          dof = self.mesh.dof(include_bc=True)

          oc = self.operator_components

          built = oc.get('_numpy_components_built', False)

          # build the static components
          if not built:
              # build laplacian
              oc.L = build_derivative_matrix(self.mesh,
                                             2,
                                             self.spatial_accuracy_order,
                                             use_shifted_differences=self.spatial_shifted_differences)

              # build sigmax
              sx = build_sigma(self.mesh, self.mesh.x)
              oc.sigmax = make_diag_mtx(sx)

              # build sigmay
              sy = build_sigma(self.mesh, self.mesh.y)
              oc.sigmay = make_diag_mtx(sy)

              # build sigmaz
              sz = build_sigma(self.mesh, self.mesh.z)
              oc.sigmaz = make_diag_mtx(sz)

              # build Dx
              oc.minus_Dx = build_derivative_matrix(self.mesh,
                                                    1,
                                                    self.spatial_accuracy_order,
                                                    dimension='x',
                                                    use_shifted_differences=self.spatial_shifted_differences)
              oc.minus_Dx.data *= -1

              # build Dy
              oc.minus_Dy = build_derivative_matrix(self.mesh,
                                                    1,
                                                    self.spatial_accuracy_order,
                                                    dimension='y',
                                                    use_shifted_differences=self.spatial_shifted_differences)
              oc.minus_Dy.data *= -1

              # build Dz
              oc.minus_Dz = build_derivative_matrix(self.mesh,
                                                    1,
                                                    self.spatial_accuracy_order,
                                                    dimension='z',
                                                    use_shifted_differences=self.spatial_shifted_differences)
              oc.minus_Dz.data *= -1

              # build other useful things
              oc.I = spsp.eye(dof, dof)
              oc.minus_I = -1*oc.I
              oc.empty = spsp.csr_matrix((dof, dof))

              # useful intermediates
              oc.sigma_sum_pair_prod  = make_diag_mtx(sx*sy + sx*sz + sy*sz)
              oc.sigma_sum            = make_diag_mtx(sx+sy+sz)
              oc.sigma_prod           = make_diag_mtx(sx*sy*sz)
              oc.minus_sigma_yPzMx_Dx = make_diag_mtx(sy+sz-sx)*oc.minus_Dx
              oc.minus_sigma_xPzMy_Dy = make_diag_mtx(sx+sz-sy)*oc.minus_Dy
              oc.minus_sigma_xPyMz_Dz = make_diag_mtx(sx+sy-sz)*oc.minus_Dz

              oc.minus_sigma_yz_Dx    = make_diag_mtx(sy*sz)*oc.minus_Dx
              oc.minus_sigma_zx_Dy    = make_diag_mtx(sz*sx)*oc.minus_Dy
              oc.minus_sigma_xy_Dz    = make_diag_mtx(sx*sy)*oc.minus_Dz

              oc._numpy_components_built = True

          C = self.model_parameters.C
          oc.m = make_diag_mtx((C**-2).reshape(-1,))

          self.K = spsp.bmat([[oc.m*oc.sigma_sum_pair_prod-oc.L, oc.m*oc.sigma_prod,   oc.minus_Dx, oc.minus_Dy, oc.minus_Dz ],
                              [oc.minus_I,                       oc.empty,             oc.empty,    oc.empty,    oc.empty    ],
                              [oc.minus_sigma_yPzMx_Dx,          oc.minus_sigma_yz_Dx, oc.sigmax,   oc.empty,    oc.empty    ],
                              [oc.minus_sigma_xPzMy_Dy,          oc.minus_sigma_zx_Dy, oc.empty,    oc.sigmay,   oc.empty    ],
                              [oc.minus_sigma_xPyMz_Dz,          oc.minus_sigma_xy_Dz, oc.empty,    oc.empty,    oc.sigmaz   ]])

          self.C = spsp.bmat([[oc.m*oc.sigma_sum, oc.empty, oc.empty, oc.empty, oc.empty],
                              [oc.empty,          oc.I,     oc.empty, oc.empty, oc.empty],
                              [oc.empty,          oc.empty, oc.I,     oc.empty, oc.empty],
                             [oc.empty,          oc.empty, oc.empty, oc.I,     oc.empty],
                             [oc.empty,          oc.empty, oc.empty, oc.empty, oc.I    ]]) / self.dt

          self.M = spsp.bmat([[    oc.m, oc.empty, oc.empty, oc.empty, oc.empty],
                             [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty],
                              [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty],
                             [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty],
                             [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty]])
    def _rebuild_operators(self):

        ConstantDensityAcousticTimeScalar_2D._rebuild_operators(self)

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh,
                                           2,
                                           self.spatial_accuracy_order)

            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.sigmax = make_diag_mtx(sx)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dx
            oc.minus_Dx = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='x')
            oc.minus_Dx.data *= -1

            # build Dz
            oc.minus_Dz = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='z')
            oc.minus_Dz.data *= -1

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_xz = make_diag_mtx(sx*sz)
            oc.sigma_xPz = oc.sigmax + oc.sigmaz

            oc.minus_sigma_zMx_Dx = make_diag_mtx((sz-sx))*oc.minus_Dx
            oc.minus_sigma_xMz_Dz = make_diag_mtx((sx-sz))*oc.minus_Dz

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m = make_diag_mtx((C**-2).reshape(-1,))

        K = spsp.bmat([[oc.m*oc.sigma_xz-oc.L, oc.minus_Dx, oc.minus_Dz],
                       [oc.minus_sigma_zMx_Dx, oc.sigmax,   oc.empty],
                       [oc.minus_sigma_xMz_Dz, oc.empty,    oc.sigmaz]])

        C = spsp.bmat([[oc.m*oc.sigma_xPz, oc.empty, oc.empty],
                       [oc.empty,          oc.I,     oc.empty],
                       [oc.empty,          oc.empty, oc.I]]) / self.dt

        M = spsp.bmat([[oc.m, oc.empty, oc.empty],
                       [oc.empty, oc.empty, oc.empty],
                       [oc.empty, oc.empty, oc.empty]]) / self.dt**2

        Stilde_inv = M+C
        Stilde_inv.data = 1./Stilde_inv.data

        self.A_k = Stilde_inv*(2*M - K + C)
        self.A_km1 = -1*Stilde_inv*(M)
        self.A_f = Stilde_inv
Example #19
0
def _build_derivative_matrix_staggered_structured_cartesian(mesh,
                                                            derivative, order_accuracy,
                                                            dimension='all',
                                                            alpha = None,
                                                            return_1D_matrix=False,
                                                            **kwargs):

    #Some of the operators could be cached the same way I did to make 'build_permutation_matrix' faster.
    #Could be considered if the current speed is ever considered to be insufficient.

    import time
    tt = time.time()

    if return_1D_matrix:
        raise Exception('Not yet implemented')

    if derivative < 1 or derivative > 2:
        raise ValueError('Only defined for first and second order right now')

    if derivative == 1 and dimension not in ['x', 'y', 'z']:
        raise ValueError('First derivative requires a direciton')

    sh = mesh.shape(include_bc = True, as_grid = True) #Will include PML padding
    if len(sh) != 2: raise Exception('currently hardcoded 2D implementation, relatively straight-forward to change. Look at the function build_derivative_matrix to get a more general function.')
    nx = sh[0]
    nz = sh[-1]

    #Currently I am working with density input on the regular grid.
    #In the derivation of the variable density solver we only require density at the stagger points
    #For now I am just interpolating density defined on regular points towards the stagger points and use that as 'density model'.
    #Later it is probably better to define the density directly on the stagger points (and evaluate density gradient there to update directly at these points?)

    if type(alpha) == None: #If no alpha is given, we set it to a uniform vector. The result should be the homogeneous Laplacian.
        alpha = np.ones(nx*nz)

    alpha = alpha.flatten() #make 1D

    dx = mesh.x.delta
    dz = mesh.z.delta

    #Get 1D linear interpolation matrices
    Jx_1d = build_linear_interpolation_matrix_part(nx)
    Jz_1d = build_linear_interpolation_matrix_part(nz)


    #Get 1D derivative matrix for first spatial derivative using the desired order of accuracy
    lbc_x = _set_bc(mesh.x.lbc)
    rbc_x = _set_bc(mesh.x.rbc)

    lbc_z = _set_bc(mesh.z.lbc)
    rbc_z = _set_bc(mesh.z.rbc)

    Dx_1d = _build_staggered_first_derivative_matrix_part(nx, order_accuracy, h=dx, lbc = lbc_x, rbc = rbc_x)
    Dz_1d = _build_staggered_first_derivative_matrix_part(nz, order_accuracy, h=dz, lbc = lbc_z, rbc = rbc_z)

    #Some empty matrices of the right shape so we can use kronsum to get the proper 2D matrices for the operations we want.
    #The same is used in the homogeneous 'build_derivative_matrix' function.
    Ix = spsp.eye(nx)
    Iz = spsp.eye(nz)



    Dx_2d = spsp.kron(Dx_1d, Iz, format='csr')
    if dimension == 'x' and derivative == 1:
        return Dx_2d

    Dz_2d = spsp.kron(Ix, Dz_1d, format='csr')
    if dimension == 'z' and derivative == 1:
        return Dz_2d

    #If we are evaluating this we want to make the heterogeneous Laplacian
    Jx_2d = spsp.kron(Jx_1d, Iz, format='csr')
    Jz_2d = spsp.kron(Ix, Jz_1d, format='csr')

    #alpha interpolated to x stagger points. Make diag mat
    diag_alpha_x = make_diag_mtx(Jx_2d*alpha)

    #alpha interpolated to z stagger points. Make diag mat
    diag_alpha_z = make_diag_mtx(Jz_2d*alpha)

    #Create laplacian components
    #The negative transpose of Dx and Dz takes care of the divergence term of the heterogeneous laplacian
    Dxx_2d = -Dx_2d.T*diag_alpha_x*Dx_2d
    Dzz_2d = -Dz_2d.T*diag_alpha_z*Dz_2d

    #Correct the Laplacian around the boundary. This is also done in the homogeneous Laplacian
    #I want the heterogeneous Laplacian to be the same as the homogeneous Laplacian when alpha is uniform
    #This is the only part of the Laplacian that deviates from symmetry, just as in the homogeneous case.
    #But because of these conditions on the dirichlet boundary the wavefield will always equal 0 there and this deviation from symmetry is fine.

    #For indexing, get list of all boundary node numbers
    left_node_nrs  = np.arange(nz)
    right_node_nrs = np.arange((nx-1)*nz,nx*nz)
    top_node_nrs   = np.arange(nz,(nx-1)*nz,nz) #does not include left and right top node
    bot_node_nrs   = top_node_nrs + nz - 1    #does not include left and right top node
    all_boundary_node_nrs   = np.concatenate((left_node_nrs, right_node_nrs, top_node_nrs, bot_node_nrs))
    nb             = all_boundary_node_nrs.size
    L = Dxx_2d + Dzz_2d

    all_node_numbers = np.arange(0,(nx*nz), dtype='int32')
    internal_node_numbers = list(set(all_node_numbers) - set(all_boundary_node_nrs))


    L = L.tocsr() #so we can extract rows efficiently

    #Operation below fixes the boundary rows quite efficiently.
    L_fixed = _turn_sparse_rows_to_identity(L, internal_node_numbers, all_boundary_node_nrs)

    return L_fixed.tocsr()
    def _rebuild_operators(self):
    
            VariableDensityAcousticTimeScalar_2D._rebuild_operators(self)
    
            dof = self.mesh.dof(include_bc=True)
    
            oc = self.operator_components
    
            built = oc.get('_numpy_components_built', False)
    
            # build the static components
            if not built:
                # build sigmax
                sx = build_sigma(self.mesh, self.mesh.x)
                oc.sigmax = make_diag_mtx(sx)
    
                # build sigmaz
                sz = build_sigma(self.mesh, self.mesh.z)
                oc.sigmaz = make_diag_mtx(sz)
    
                # build Dx
                oc.Dx = build_derivative_matrix(self.mesh,
                                                        1,
                                                        self.spatial_accuracy_order,
                                                        dimension='x')
                oc.minus_Dx = copy.deepcopy(oc.Dx)      #more storage, but less computations
                oc.minus_Dx.data *= -1                  
    
                # build Dz
                oc.Dz = build_derivative_matrix(self.mesh,
                                                        1,
                                                        self.spatial_accuracy_order,
                                                        dimension='z')
                oc.minus_Dz = copy.deepcopy(oc.Dz)      #more storage, but less computations
                oc.minus_Dz.data *= -1                                  

    
                # build other useful things
                oc.I = spsp.eye(dof, dof)
                oc.empty = spsp.csr_matrix((dof, dof))
    
                # useful intermediates
                oc.sigma_xz  = make_diag_mtx(sx*sz)
                oc.sigma_xPz = oc.sigmax + oc.sigmaz
    
                oc.minus_sigma_zMx_Dx = make_diag_mtx((sz-sx))*oc.minus_Dx
                oc.minus_sigma_xMz_Dz = make_diag_mtx((sx-sz))*oc.minus_Dz
    
                oc._numpy_components_built = True

            kappa = self.model_parameters.kappa
            rho = self.model_parameters.rho
    
            oc.m1 = make_diag_mtx((kappa**-1).reshape(-1,))
            oc.m2 = make_diag_mtx((rho**-1).reshape(-1,))

            oc.L = build_derivative_matrix_VDA(self.mesh,
                                               2,
                                               self.spatial_accuracy_order,
                                               alpha = rho**-1
                                               )
            
    
            # oc.L is a heterogenous laplacian operator. It computes div(m2 grad), where m2 = 1/rho. 
            # Ian's implementation used the regular Dx operators in the PML even though the heterogeneous Laplacian with staggered derivative operators is used in the physical domain.
            # I (Bram) did not change this or investigate if this causes some problems but am noting it here for completeness. 
            
            K = spsp.bmat([[oc.m1*oc.sigma_xz-oc.L, oc.minus_Dx*oc.m2, oc.minus_Dz*oc.m2 ],
                           [oc.minus_sigma_zMx_Dx, oc.sigmax,   oc.empty    ],
                           [oc.minus_sigma_xMz_Dz, oc.empty,    oc.sigmaz   ]])
    
            C = spsp.bmat([[oc.m1*oc.sigma_xPz, oc.empty, oc.empty],
                           [oc.empty,          oc.I,     oc.empty],
                           [oc.empty,          oc.empty, oc.I    ]]) / self.dt
    
            M = spsp.bmat([[    oc.m1, oc.empty, oc.empty],
                           [oc.empty, oc.empty, oc.empty],
                           [oc.empty, oc.empty, oc.empty]]) / self.dt**2
    
            Stilde_inv = M+C
            Stilde_inv.data = 1./Stilde_inv.data
    
            self.A_k   = Stilde_inv*(2*M - K + C)
            self.A_km1 = -1*Stilde_inv*(M)
            self.A_f   = Stilde_inv
    def _rebuild_operators(self):

        VariableDensityAcousticTimeScalar_2D._rebuild_operators(self)

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.sigmax = make_diag_mtx(sx)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dx
            oc.Dx = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='x')
            oc.minus_Dx = copy.deepcopy(
                oc.Dx)  #more storage, but less computations
            oc.minus_Dx.data *= -1

            # build Dz
            oc.Dz = build_derivative_matrix(self.mesh,
                                            1,
                                            self.spatial_accuracy_order,
                                            dimension='z')
            oc.minus_Dz = copy.deepcopy(
                oc.Dz)  #more storage, but less computations
            oc.minus_Dz.data *= -1

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_xz = make_diag_mtx(sx * sz)
            oc.sigma_xPz = oc.sigmax + oc.sigmaz

            oc.minus_sigma_zMx_Dx = make_diag_mtx((sz - sx)) * oc.minus_Dx
            oc.minus_sigma_xMz_Dz = make_diag_mtx((sx - sz)) * oc.minus_Dz

            oc._numpy_components_built = True

        kappa = self.model_parameters.kappa
        rho = self.model_parameters.rho

        oc.m1 = make_diag_mtx((kappa**-1).reshape(-1, ))
        oc.m2 = make_diag_mtx((rho**-1).reshape(-1, ))

        oc.L = build_derivative_matrix_VDA(self.mesh,
                                           2,
                                           self.spatial_accuracy_order,
                                           alpha=rho**-1)

        # oc.L is a heterogenous laplacian operator. It computes div(m2 grad), where m2 = 1/rho.
        # Ian's implementation used the regular Dx operators in the PML even though the heterogeneous Laplacian with staggered derivative operators is used in the physical domain.
        # I (Bram) did not change this or investigate if this causes some problems but am noting it here for completeness.

        K = spsp.bmat([[
            oc.m1 * oc.sigma_xz - oc.L, oc.minus_Dx * oc.m2,
            oc.minus_Dz * oc.m2
        ], [oc.minus_sigma_zMx_Dx, oc.sigmax, oc.empty],
                       [oc.minus_sigma_xMz_Dz, oc.empty, oc.sigmaz]])

        C = spsp.bmat([[oc.m1 * oc.sigma_xPz, oc.empty, oc.empty],
                       [oc.empty, oc.I, oc.empty], [oc.empty, oc.empty, oc.I]
                       ]) / self.dt

        M = spsp.bmat([[oc.m1, oc.empty, oc.empty],
                       [oc.empty, oc.empty, oc.empty],
                       [oc.empty, oc.empty, oc.empty]]) / self.dt**2

        Stilde_inv = M + C
        Stilde_inv.data = 1. / Stilde_inv.data

        self.A_k = Stilde_inv * (2 * M - K + C)
        self.A_km1 = -1 * Stilde_inv * (M)
        self.A_f = Stilde_inv
Example #22
0
def _build_derivative_matrix_staggered_structured_cartesian(
        mesh,
        derivative,
        order_accuracy,
        dimension='all',
        alpha=None,
        return_1D_matrix=False,
        **kwargs):

    #Some of the operators could be cached the same way I did to make 'build_permutation_matrix' faster.
    #Could be considered if the current speed is ever considered to be insufficient.

    import time
    tt = time.time()

    if return_1D_matrix:
        raise Exception('Not yet implemented')

    if derivative < 1 or derivative > 2:
        raise ValueError('Only defined for first and second order right now')

    if derivative == 1 and dimension not in ['x', 'y', 'z']:
        raise ValueError('First derivative requires a direciton')

    sh = mesh.shape(include_bc=True, as_grid=True)  #Will include PML padding
    if len(sh) != 2:
        raise Exception(
            'currently hardcoded 2D implementation, relatively straight-forward to change. Look at the function build_derivative_matrix to get a more general function.'
        )
    nx = sh[0]
    nz = sh[-1]

    #Currently I am working with density input on the regular grid.
    #In the derivation of the variable density solver we only require density at the stagger points
    #For now I am just interpolating density defined on regular points towards the stagger points and use that as 'density model'.
    #Later it is probably better to define the density directly on the stagger points (and evaluate density gradient there to update directly at these points?)

    if type(
            alpha
    ) == None:  #If no alpha is given, we set it to a uniform vector. The result should be the homogeneous Laplacian.
        alpha = np.ones(nx * nz)

    alpha = alpha.flatten()  #make 1D

    dx = mesh.x.delta
    dz = mesh.z.delta

    #Get 1D linear interpolation matrices
    Jx_1d = build_linear_interpolation_matrix_part(nx)
    Jz_1d = build_linear_interpolation_matrix_part(nz)

    #Get 1D derivative matrix for first spatial derivative using the desired order of accuracy
    lbc_x = _set_bc(mesh.x.lbc)
    rbc_x = _set_bc(mesh.x.rbc)

    lbc_z = _set_bc(mesh.z.lbc)
    rbc_z = _set_bc(mesh.z.rbc)

    Dx_1d = _build_staggered_first_derivative_matrix_part(nx,
                                                          order_accuracy,
                                                          h=dx,
                                                          lbc=lbc_x,
                                                          rbc=rbc_x)
    Dz_1d = _build_staggered_first_derivative_matrix_part(nz,
                                                          order_accuracy,
                                                          h=dz,
                                                          lbc=lbc_z,
                                                          rbc=rbc_z)

    #Some empty matrices of the right shape so we can use kronsum to get the proper 2D matrices for the operations we want.
    #The same is used in the homogeneous 'build_derivative_matrix' function.
    Ix = spsp.eye(nx)
    Iz = spsp.eye(nz)

    Dx_2d = spsp.kron(Dx_1d, Iz, format='csr')
    if dimension == 'x' and derivative == 1:
        return Dx_2d

    Dz_2d = spsp.kron(Ix, Dz_1d, format='csr')
    if dimension == 'z' and derivative == 1:
        return Dz_2d

    #If we are evaluating this we want to make the heterogeneous Laplacian
    Jx_2d = spsp.kron(Jx_1d, Iz, format='csr')
    Jz_2d = spsp.kron(Ix, Jz_1d, format='csr')

    #alpha interpolated to x stagger points. Make diag mat
    diag_alpha_x = make_diag_mtx(Jx_2d * alpha)

    #alpha interpolated to z stagger points. Make diag mat
    diag_alpha_z = make_diag_mtx(Jz_2d * alpha)

    #Create laplacian components
    #The negative transpose of Dx and Dz takes care of the divergence term of the heterogeneous laplacian
    Dxx_2d = -Dx_2d.T * diag_alpha_x * Dx_2d
    Dzz_2d = -Dz_2d.T * diag_alpha_z * Dz_2d

    #Correct the Laplacian around the boundary. This is also done in the homogeneous Laplacian
    #I want the heterogeneous Laplacian to be the same as the homogeneous Laplacian when alpha is uniform
    #This is the only part of the Laplacian that deviates from symmetry, just as in the homogeneous case.
    #But because of these conditions on the dirichlet boundary the wavefield will always equal 0 there and this deviation from symmetry is fine.

    #For indexing, get list of all boundary node numbers
    left_node_nrs = np.arange(nz)
    right_node_nrs = np.arange((nx - 1) * nz, nx * nz)
    top_node_nrs = np.arange(nz, (nx - 1) * nz,
                             nz)  #does not include left and right top node
    bot_node_nrs = top_node_nrs + nz - 1  #does not include left and right top node
    all_boundary_node_nrs = np.concatenate(
        (left_node_nrs, right_node_nrs, top_node_nrs, bot_node_nrs))
    nb = all_boundary_node_nrs.size
    L = Dxx_2d + Dzz_2d

    all_node_numbers = np.arange(0, (nx * nz), dtype='int32')
    internal_node_numbers = list(
        set(all_node_numbers) - set(all_boundary_node_nrs))

    L = L.tocsr()  #so we can extract rows efficiently

    #Operation below fixes the boundary rows quite efficiently.
    L_fixed = _turn_sparse_rows_to_identity(L, internal_node_numbers,
                                            all_boundary_node_nrs)

    return L_fixed.tocsr()
    def _rebuild_operators(self):

        VariableDensityAcousticTimeScalar_2D._rebuild_operators(self)

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.sigmax = make_diag_mtx(sx)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dx
            oc.minus_Dx = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='x')
            oc.minus_Dx.data *= -1

            # build Dz
            oc.minus_Dz = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='z')
            oc.minus_Dz.data *= -1

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_xz  = make_diag_mtx(sx*sz)
            oc.sigma_xPz = oc.sigmax + oc.sigmaz

            oc.minus_sigma_zMx_Dx = make_diag_mtx((sz-sx))*oc.minus_Dx
            oc.minus_sigma_xMz_Dz = make_diag_mtx((sx-sz))*oc.minus_Dz

            oc._numpy_components_built = True

        kappa = self.model_parameters.kappa
        rho = self.model_parameters.rho

        oc.m1 = make_diag_mtx((kappa**-1).reshape(-1,))
        oc.m2 = make_diag_mtx((rho**-1).reshape(-1,))
        
        # build heterogenous laplacian
        sh = self.mesh.shape(include_bc=True,as_grid=True)
        deltas = [self.mesh.x.delta,self.mesh.z.delta]
        oc.L = build_heterogenous_laplacian(sh,rho**-1,deltas)

        # oc.L is a heterogenous laplacian operator. It computes div(m2 grad), where m2 = 1/rho. 
        # Currently the creation of oc.L is slow. This is because we have implemented a cenetered heterogenous laplacian.
        # To speed up computation, we could compute a div(m2 grad) operator that is not centered by simply multiplying
        # a divergence operator by oc.m2 by a gradient operator.

        K = spsp.bmat([[oc.m1*oc.sigma_xz-oc.L, oc.minus_Dx*oc.m2, oc.minus_Dz*oc.m2 ],
                       [oc.minus_sigma_zMx_Dx, oc.sigmax,   oc.empty    ],
                       [oc.minus_sigma_xMz_Dz, oc.empty,    oc.sigmaz   ]])

        C = spsp.bmat([[oc.m1*oc.sigma_xPz, oc.empty, oc.empty],
                       [oc.empty,          oc.I,     oc.empty],
                       [oc.empty,          oc.empty, oc.I    ]]) / self.dt

        M = spsp.bmat([[    oc.m1, oc.empty, oc.empty],
                       [oc.empty, oc.empty, oc.empty],
                       [oc.empty, oc.empty, oc.empty]]) / self.dt**2

        Stilde_inv = M+C
        Stilde_inv.data = 1./Stilde_inv.data

        self.A_k   = Stilde_inv*(2*M - K + C)
        self.A_km1 = -1*Stilde_inv*(M)
        self.A_f   = Stilde_inv
    def _rebuild_operators(self):

        ConstantDensityAcousticTimeScalar_3D._rebuild_operators(self)

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get("_numpy_components_built", False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh, 2, self.spatial_accuracy_order)

            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.sigmax = make_diag_mtx(sx)

            # build sigmay
            sy = build_sigma(self.mesh, self.mesh.y)
            oc.sigmay = make_diag_mtx(sy)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dx
            oc.minus_Dx = build_derivative_matrix(self.mesh, 1, self.spatial_accuracy_order, dimension="x")
            oc.minus_Dx.data *= -1

            # build Dy
            oc.minus_Dy = build_derivative_matrix(self.mesh, 1, self.spatial_accuracy_order, dimension="y")
            oc.minus_Dy.data *= -1

            # build Dz
            oc.minus_Dz = build_derivative_matrix(self.mesh, 1, self.spatial_accuracy_order, dimension="z")
            oc.minus_Dz.data *= -1

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.minus_I = -1 * oc.I
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_sum_pair_prod = make_diag_mtx(sx * sy + sx * sz + sy * sz)
            oc.sigma_sum = make_diag_mtx(sx + sy + sz)
            oc.sigma_prod = make_diag_mtx(sx * sy * sz)
            oc.minus_sigma_yPzMx_Dx = make_diag_mtx(sy + sz - sx) * oc.minus_Dx
            oc.minus_sigma_xPzMy_Dy = make_diag_mtx(sx + sz - sy) * oc.minus_Dy
            oc.minus_sigma_xPyMz_Dz = make_diag_mtx(sx + sy - sz) * oc.minus_Dz

            oc.minus_sigma_yz_Dx = make_diag_mtx(sy * sz) * oc.minus_Dx
            oc.minus_sigma_zx_Dy = make_diag_mtx(sz * sx) * oc.minus_Dy
            oc.minus_sigma_xy_Dz = make_diag_mtx(sx * sy) * oc.minus_Dz

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m = make_diag_mtx((C ** -2).reshape(-1))

        K = spsp.bmat(
            [
                [oc.m * oc.sigma_sum_pair_prod - oc.L, oc.m * oc.sigma_prod, oc.minus_Dx, oc.minus_Dy, oc.minus_Dz],
                [oc.minus_I, oc.empty, oc.empty, oc.empty, oc.empty],
                [oc.minus_sigma_yPzMx_Dx, oc.minus_sigma_yz_Dx, oc.sigmax, oc.empty, oc.empty],
                [oc.minus_sigma_xPzMy_Dy, oc.minus_sigma_zx_Dy, oc.empty, oc.sigmay, oc.empty],
                [oc.minus_sigma_xPyMz_Dz, oc.minus_sigma_xy_Dz, oc.empty, oc.empty, oc.sigmaz],
            ]
        )

        C = (
            spsp.bmat(
                [
                    [oc.m * oc.sigma_sum, oc.empty, oc.empty, oc.empty, oc.empty],
                    [oc.empty, oc.I, oc.empty, oc.empty, oc.empty],
                    [oc.empty, oc.empty, oc.I, oc.empty, oc.empty],
                    [oc.empty, oc.empty, oc.empty, oc.I, oc.empty],
                    [oc.empty, oc.empty, oc.empty, oc.empty, oc.I],
                ]
            )
            / self.dt
        )

        M = (
            spsp.bmat(
                [
                    [oc.m, oc.empty, oc.empty, oc.empty, oc.empty],
                    [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty],
                    [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty],
                    [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty],
                    [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty],
                ]
            )
            / self.dt ** 2
        )

        Stilde_inv = M + C
        Stilde_inv.data = 1.0 / Stilde_inv.data

        self.A_k = Stilde_inv * (2 * M - K + C)
        self.A_km1 = -1 * Stilde_inv * (M)
        self.A_f = Stilde_inv
    def _rebuild_operators(self):

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh,
                                           2,
                                           self.spatial_accuracy_order,
                                           use_shifted_differences=self.spatial_shifted_differences)

            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.sigmax = make_diag_mtx(sx)

            # build sigmay
            sy = build_sigma(self.mesh, self.mesh.y)
            oc.sigmay = make_diag_mtx(sy)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dx
            oc.minus_Dx = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='x',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            oc.minus_Dx.data *= -1

            # build Dy
            oc.minus_Dy = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='y',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            oc.minus_Dy.data *= -1

            # build Dz
            oc.minus_Dz = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='z',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            oc.minus_Dz.data *= -1

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.minus_I = -1*oc.I
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_sum_pair_prod  = make_diag_mtx(sx*sy + sx*sz + sy*sz)
            oc.sigma_sum            = make_diag_mtx(sx+sy+sz)
            oc.sigma_prod           = make_diag_mtx(sx*sy*sz)
            oc.minus_sigma_yPzMx_Dx = make_diag_mtx(sy+sz-sx)*oc.minus_Dx
            oc.minus_sigma_xPzMy_Dy = make_diag_mtx(sx+sz-sy)*oc.minus_Dy
            oc.minus_sigma_xPyMz_Dz = make_diag_mtx(sx+sy-sz)*oc.minus_Dz

            oc.minus_sigma_yz_Dx    = make_diag_mtx(sy*sz)*oc.minus_Dx
            oc.minus_sigma_zx_Dy    = make_diag_mtx(sz*sx)*oc.minus_Dy
            oc.minus_sigma_xy_Dz    = make_diag_mtx(sx*sy)*oc.minus_Dz

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m = make_diag_mtx((C**-2).reshape(-1,))

        self.K = spsp.bmat([[oc.m*oc.sigma_sum_pair_prod-oc.L, oc.m*oc.sigma_prod,   oc.minus_Dx, oc.minus_Dy, oc.minus_Dz ],
                            [oc.minus_I,                       oc.empty,             oc.empty,    oc.empty,    oc.empty    ],
                            [oc.minus_sigma_yPzMx_Dx,          oc.minus_sigma_yz_Dx, oc.sigmax,   oc.empty,    oc.empty    ],
                            [oc.minus_sigma_xPzMy_Dy,          oc.minus_sigma_zx_Dy, oc.empty,    oc.sigmay,   oc.empty    ],
                            [oc.minus_sigma_xPyMz_Dz,          oc.minus_sigma_xy_Dz, oc.empty,    oc.empty,    oc.sigmaz   ]])

        self.C = spsp.bmat([[oc.m*oc.sigma_sum, oc.empty, oc.empty, oc.empty, oc.empty],
                            [oc.empty,          oc.I,     oc.empty, oc.empty, oc.empty],
                            [oc.empty,          oc.empty, oc.I,     oc.empty, oc.empty],
                           [oc.empty,          oc.empty, oc.empty, oc.I,     oc.empty],
                           [oc.empty,          oc.empty, oc.empty, oc.empty, oc.I    ]]) / self.dt

        self.M = spsp.bmat([[    oc.m, oc.empty, oc.empty, oc.empty, oc.empty],
                           [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty],
                            [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty],
                           [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty],
                           [oc.empty, oc.empty, oc.empty, oc.empty, oc.empty]])
    def _rebuild_operators(self):
        if self.mesh.x.lbc.type == 'pml' and self.compact:
          # build intermediates for the compact operator
          raise ValidationFunctionError(" This solver is in construction and is not yet complete. For variable density and compact PML.")
          dof = self.mesh.dof(include_bc=True)

          oc = self.operator_components

          built = oc.get('_numpy_components_built', False)
          oc.M = make_diag_mtx(self.model_parameters.C.squeeze()**-2)
          # build the static components
          if not built:          
            # build Dxx
            oc.Dxx = build_derivative_matrix(self.mesh,
                                                  2,
                                                  self.spatial_accuracy_order,
                                                  dimension='x',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            # build Dzz
            oc.Dzz = build_derivative_matrix(self.mesh,
                                                  2,
                                                  self.spatial_accuracy_order,
                                                  dimension='z',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            # build Dx
            oc.Dx = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='x',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            
            # build Dz
            oc.Dz = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='z',
                                                  use_shifted_differences=self.spatial_shifted_differences)
                                                  
            # build sigma
            oc.sx, oc.sz, oc.sxp, oc.szp = self._sigma_PML(self.mesh)

            oc._numpy_components_built = True
        else:
          # build intermediates for operator with auxiliary fields
          dof = self.mesh.dof(include_bc=True)

          oc = self.operator_components

          built = oc.get('_numpy_components_built', False)

          # build the static components
          if not built:
            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.sigmax = make_diag_mtx(sx)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dx
            oc.minus_Dx = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='x',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            oc.minus_Dx.data *= -1

            # build Dz
            oc.minus_Dz = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='z',
                                                  use_shifted_differences=self.spatial_shifted_differences)
            oc.minus_Dz.data *= -1

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_xz  = make_diag_mtx(sx*sz)
            oc.sigma_xPz = oc.sigmax + oc.sigmaz

            oc.minus_sigma_zMx_Dx = make_diag_mtx((sz-sx))*oc.minus_Dx
            oc.minus_sigma_xMz_Dz = make_diag_mtx((sx-sz))*oc.minus_Dz

            oc._numpy_components_built = True

        kappa = self.model_parameters.kappa
        rho = self.model_parameters.rho
        oc.m1 = make_diag_mtx((kappa**-1).reshape(-1,))
        oc.m2 = make_diag_mtx((rho**-1).reshape(-1,))
        # build heterogenous laplacian
        sh = self.mesh.shape(include_bc=True,as_grid=True)
        deltas = [self.mesh.x.delta,self.mesh.z.delta]
        oc.L = build_heterogenous_laplacian(sh,rho**-1,deltas)

        # oc.L is a heterogenous laplacian operator. It computes div(m2 grad), where m2 = 1/rho. 
        # Currently the creation of oc.L is slow. This is because we have implemented a cenetered heterogenous laplacian.
        # To speed up computation, we could compute a div(m2 grad) operator that is not centered by simply multiplying
        # a divergence operator by oc.m2 by a gradient operator.

        self.K = spsp.bmat([[oc.m1*oc.sigma_xz-oc.L, oc.minus_Dx*oc.m2, oc.minus_Dz*oc.m2 ],
                            [oc.minus_sigma_zMx_Dx, oc.sigmax,   oc.empty    ],
                            [oc.minus_sigma_xMz_Dz, oc.empty,    oc.sigmaz   ]])

        self.C = spsp.bmat([[oc.m1*oc.sigma_xPz, oc.empty, oc.empty],
                            [oc.empty,          oc.I,     oc.empty],
                            [oc.empty,          oc.empty, oc.I    ]])

        self.M = spsp.bmat([[    oc.m1, oc.empty, oc.empty],
                            [oc.empty, oc.empty, oc.empty],
                            [oc.empty, oc.empty, oc.empty]])
Example #27
0
    def _rebuild_operators(self):

        ConstantDensityAcousticTimeScalar_2D._rebuild_operators(self)

        dof = self.mesh.dof(include_bc=True)

        oc = self.operator_components

        built = oc.get('_numpy_components_built', False)

        # build the static components
        if not built:
            # build laplacian
            oc.L = build_derivative_matrix(self.mesh, 2,
                                           self.spatial_accuracy_order)

            # build sigmax
            sx = build_sigma(self.mesh, self.mesh.x)
            oc.sigmax = make_diag_mtx(sx)

            # build sigmaz
            sz = build_sigma(self.mesh, self.mesh.z)
            oc.sigmaz = make_diag_mtx(sz)

            # build Dx
            oc.minus_Dx = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='x')
            oc.minus_Dx.data *= -1

            # build Dz
            oc.minus_Dz = build_derivative_matrix(self.mesh,
                                                  1,
                                                  self.spatial_accuracy_order,
                                                  dimension='z')
            oc.minus_Dz.data *= -1

            # build other useful things
            oc.I = spsp.eye(dof, dof)
            oc.empty = spsp.csr_matrix((dof, dof))

            # useful intermediates
            oc.sigma_xz = make_diag_mtx(sx * sz)
            oc.sigma_xPz = oc.sigmax + oc.sigmaz

            oc.minus_sigma_zMx_Dx = make_diag_mtx((sz - sx)) * oc.minus_Dx
            oc.minus_sigma_xMz_Dz = make_diag_mtx((sx - sz)) * oc.minus_Dz

            oc._numpy_components_built = True

        C = self.model_parameters.C
        oc.m = make_diag_mtx((C**-2).reshape(-1, ))

        K = spsp.bmat([[oc.m * oc.sigma_xz - oc.L, oc.minus_Dx, oc.minus_Dz],
                       [oc.minus_sigma_zMx_Dx, oc.sigmax, oc.empty],
                       [oc.minus_sigma_xMz_Dz, oc.empty, oc.sigmaz]])

        C = spsp.bmat([[oc.m * oc.sigma_xPz, oc.empty, oc.empty],
                       [oc.empty, oc.I, oc.empty], [oc.empty, oc.empty, oc.I]
                       ]) / self.dt

        M = spsp.bmat([[oc.m, oc.empty, oc.empty],
                       [oc.empty, oc.empty, oc.empty],
                       [oc.empty, oc.empty, oc.empty]]) / self.dt**2

        Stilde_inv = M + C
        Stilde_inv.data = 1. / Stilde_inv.data

        self.A_k = Stilde_inv * (2 * M - K + C)
        self.A_km1 = -1 * Stilde_inv * (M)
        self.A_f = Stilde_inv
    def _rebuild_operators(self):
        if self.mesh.x.lbc.type == 'pml' and self.compact:
            # build intermediates for the compact operator
            dof = self.mesh.dof(include_bc=True)

            oc = self.operator_components

            built = oc.get('_numpy_components_built', False)
            oc.M = make_diag_mtx(self.model_parameters.C.squeeze()**-2)
            oc.I = spsp.eye(dof, dof)
            # build the static components
            if not built:
                # build Dxx
                oc.Dxx = build_derivative_matrix(self.mesh,
                                                 2,
                                                 self.spatial_accuracy_order,
                                                 dimension='x',
                                                 use_shifted_differences=self.spatial_shifted_differences)
                # build Dzz
                oc.Dzz = build_derivative_matrix(self.mesh,
                                                 2,
                                                 self.spatial_accuracy_order,
                                                 dimension='z',
                                                 use_shifted_differences=self.spatial_shifted_differences)
                # build Dx
                oc.Dx = build_derivative_matrix(self.mesh,
                                                1,
                                                self.spatial_accuracy_order,
                                                dimension='x',
                                                use_shifted_differences=self.spatial_shifted_differences)

                # build Dz
                oc.Dz = build_derivative_matrix(self.mesh,
                                                1,
                                                self.spatial_accuracy_order,
                                                dimension='z',
                                                use_shifted_differences=self.spatial_shifted_differences)

                # build sigma
                oc.sx, oc.sz, oc.sxp, oc.szp = self._sigma_PML(self.mesh)

                oc._numpy_components_built = True

            self.dK = 0
            self.dC = 0
            self.dM = oc.I
        else:
            # build intermediates for operator with auxiliary fields
            dof = self.mesh.dof(include_bc=True)

            oc = self.operator_components
            oc.I = spsp.eye(dof, dof)

            built = oc.get('_numpy_components_built', False)

            # build the static components
            if not built:
                # build laplacian
                oc.L = build_derivative_matrix(self.mesh,
                                               2,
                                               self.spatial_accuracy_order,
                                               use_shifted_differences=self.spatial_shifted_differences)

                # build sigmax
                sx = build_sigma(self.mesh, self.mesh.x)
                oc.sigmax = make_diag_mtx(sx)

                # build sigmaz
                sz = build_sigma(self.mesh, self.mesh.z)
                oc.sigmaz = make_diag_mtx(sz)

                # build Dx
                oc.minus_Dx = build_derivative_matrix(self.mesh,
                                                      1,
                                                      self.spatial_accuracy_order,
                                                      dimension='x',
                                                      use_shifted_differences=self.spatial_shifted_differences)
                oc.minus_Dx.data *= -1

                # build Dz
                oc.minus_Dz = build_derivative_matrix(self.mesh,
                                                      1,
                                                      self.spatial_accuracy_order,
                                                      dimension='z',
                                                      use_shifted_differences=self.spatial_shifted_differences)
                oc.minus_Dz.data *= -1

                # build other useful things
                oc.I = spsp.eye(dof, dof)
                oc.empty = spsp.csr_matrix((dof, dof))

                # useful intermediates
                oc.sigma_xz = make_diag_mtx(sx*sz)
                oc.sigma_xPz = oc.sigmax + oc.sigmaz

                oc.minus_sigma_zMx_Dx = make_diag_mtx((sz-sx))*oc.minus_Dx
                oc.minus_sigma_xMz_Dz = make_diag_mtx((sx-sz))*oc.minus_Dz

                oc._numpy_components_built = True

            C = self.model_parameters.C
            oc.m = make_diag_mtx((C**-2).reshape(-1,))

            self.K = spsp.bmat([[oc.m*oc.sigma_xz-oc.L, oc.minus_Dx, oc.minus_Dz],
                                [oc.minus_sigma_zMx_Dx, oc.sigmax,   oc.empty],
                                [oc.minus_sigma_xMz_Dz, oc.empty,    oc.sigmaz]])

            self.C = spsp.bmat([[oc.m*oc.sigma_xPz, oc.empty, oc.empty],
                                [oc.empty,          oc.I,     oc.empty],
                                [oc.empty,          oc.empty, oc.I]])

            self.M = spsp.bmat([[oc.m,     oc.empty, oc.empty],
                                [oc.empty, oc.empty, oc.empty],
                                [oc.empty, oc.empty, oc.empty]])

            self.dK = oc.sigma_xz
            self.dC = oc.sigma_xPz
            self.dM = oc.I