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]])
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): 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]])
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