def interp(self, y, eigval=1, same_mesh=False, verbose=False): """Interpolate solution eigenvector and it's derivative onto y """ N = self.N nx, eigval = self.get_eigval(eigval, verbose) phi_hat = np.zeros(N, np.complex) phi_hat[:-4] = np.squeeze(self.eigvectors[:, nx]) if same_mesh: phi = np.zeros_like(phi_hat) dphidy = np.zeros_like(phi_hat) if self.SB is None: self.SB = ShenBiharmonicBasis(N, quad=self.quad, plan=True) self.SD = ShenDirichletBasis(N, quad=self.quad, plan=True) self.CDB = inner_product((self.SD, 0), (self.SB, 1)) phi = self.SB.ifst(phi_hat, phi) dphidy_hat = self.CDB.matvec(phi_hat) dphidy_hat = self.SD.apply_inverse_mass(dphidy_hat) dphidy = self.SD.backward(dphidy_hat, dphidy) else: # Recompute interpolation matrices if necessary if not len(self.P4) == len(y): SB = ShenBiharmonicBasis(N, quad=self.quad) V = self.V = SB.vandermonde(y) P4 = self.P4 = SB.get_vandermonde_basis(V) T4x = self.T4x = SB.get_vandermonde_basis_derivative(V, 1) phi = np.dot(self.P4, phi_hat) dphidy = np.dot(self.T4x, phi_hat) return phi, dphidy
def test_Helmholtz_matvec(quad): M = 2*N SD = ShenDirichletBasis(M, quad=quad) kx = 11 uj = np.random.randn(M) u_hat = np.zeros(M) u_hat = SD.forward(uj, u_hat) uj = SD.backward(u_hat, uj) B = inner_product((SD, 0), (SD, 0)) A = inner_product((SD, 0), (SD, 2)) AB = HelmholtzCoeff(M, 1, kx**2, SD.quad) u1 = np.zeros(M) u1 = SD.forward(uj, u1) c0 = np.zeros_like(u1) c1 = np.zeros_like(u1) c = A.matvec(u1, c0)+kx**2*B.matvec(u1, c1) b = np.zeros(M) #LUsolve.Mult_Helmholtz_1D(M, SD.quad=="GL", 1, kx**2, u1, b) b = AB.matvec(u1, b) #from IPython import embed; embed() assert np.allclose(c, b) b = np.zeros((M, 4, 4), dtype=np.complex) u1 = u1.repeat(16).reshape((M, 4, 4)) +1j*u1.repeat(16).reshape((M, 4, 4)) kx = np.zeros((1, 4, 4))+kx #LUsolve.Mult_Helmholtz_3D_complex(M, SD.quad=="GL", 1.0, kx**2, u1, b) AB = HelmholtzCoeff(M, 1, kx**2, SD.quad) b = AB.matvec(u1, b) assert np.linalg.norm(b[:, 2, 2].real - c)/(M*16) < 1e-12 assert np.linalg.norm(b[:, 2, 2].imag - c)/(M*16) < 1e-12
def test_Mult_CTD(quad): SD = ShenDirichletBasis(N, quad=quad) SD.plan(N, 0, np.complex, {}) C = inner_product((SD.CT, 0), (SD, 1)) B = inner_product((SD.CT, 0), (SD.CT, 0)) vk = np.random.randn((N))+np.random.randn((N))*1j wk = np.random.randn((N))+np.random.randn((N))*1j bv = np.zeros(N, dtype=np.complex) bw = np.zeros(N, dtype=np.complex) vk0 = np.zeros(N, dtype=np.complex) wk0 = np.zeros(N, dtype=np.complex) cv = np.zeros(N, dtype=np.complex) cw = np.zeros(N, dtype=np.complex) vk0 = SD.forward(vk, vk0) vk = SD.backward(vk0, vk) vk0 = SD.forward(vk, vk0) wk0 = SD.forward(wk, wk0) wk = SD.backward(wk0, wk) wk0 = SD.forward(wk, wk0) LUsolve.Mult_CTD_1D(N, vk0, wk0, bv, bw) cv = np.zeros_like(vk0) cw = np.zeros_like(wk0) cv = C.matvec(vk0, cv) cw = C.matvec(wk0, cw) cv /= B[0] cw /= B[0] assert np.allclose(cv, bv) assert np.allclose(cw, bw)
def test_Mult_CTD_3D(quad): SD = ShenDirichletBasis(N, quad=quad) SD.plan((N, 4, 4), 0, np.complex, {}) C = inner_product((SD.CT, 0), (SD, 1)) B = inner_product((SD.CT, 0), (SD.CT, 0)) vk = np.random.random((N, 4, 4))+np.random.random((N, 4, 4))*1j wk = np.random.random((N, 4, 4))+np.random.random((N, 4, 4))*1j bv = np.zeros((N, 4, 4), dtype=np.complex) bw = np.zeros((N, 4, 4), dtype=np.complex) vk0 = np.zeros((N, 4, 4), dtype=np.complex) wk0 = np.zeros((N, 4, 4), dtype=np.complex) cv = np.zeros((N, 4, 4), dtype=np.complex) cw = np.zeros((N, 4, 4), dtype=np.complex) vk0 = SD.forward(vk, vk0) vk = SD.backward(vk0, vk) vk0 = SD.forward(vk, vk0) wk0 = SD.forward(wk, wk0) wk = SD.backward(wk0, wk) wk0 = SD.forward(wk, wk0) LUsolve.Mult_CTD_3D_ptr(N, vk0, wk0, bv, bw, 0) cv = np.zeros_like(vk0) cw = np.zeros_like(wk0) cv = C.matvec(vk0, cv) cw = C.matvec(wk0, cw) cv /= B[0].repeat(np.array(bv.shape[1:]).prod()).reshape(bv.shape) cw /= B[0].repeat(np.array(bv.shape[1:]).prod()).reshape(bv.shape) assert np.allclose(cv, bv) assert np.allclose(cw, bw)
def interp(self, y, eigvals, eigvectors, eigval=1, same_mesh=False, verbose=False): """Interpolate solution eigenvector and it's derivative onto y args: y Interpolation points eigvals All computed eigenvalues eigvectors All computed eigenvectors kwargs: eigval The chosen eigenvalue, ranked with descending imaginary part. The largest imaginary part is 1, the second largest is 2, etc. same_mesh Boolean. Whether or not to interpolate to the same quadrature points as used for computing the eigenvectors verbose Boolean. Print information or not """ N = self.N nx, eigval = self.get_eigval(eigval, eigvals, verbose) phi_hat = np.zeros(N, np.complex) phi_hat[:-4] = np.squeeze(eigvectors[:, nx]) if same_mesh: phi = np.zeros_like(phi_hat) dphidy = np.zeros_like(phi_hat) if self.SB is None: self.SB = ShenBiharmonicBasis(N, quad=self.quad, plan=True) self.SD = ShenDirichletBasis(N, quad=self.quad, plan=True) self.CDB = inner_product((self.SD, 0), (self.SB, 1)) phi = self.SB.ifst(phi_hat, phi) dphidy_hat = self.CDB.matvec(phi_hat) dphidy_hat = self.SD.apply_inverse_mass(dphidy_hat) dphidy = self.SD.backward(dphidy_hat, dphidy) else: # Recompute interpolation matrices if necessary if not len(self.P4) == len(y): SB = ShenBiharmonicBasis(N, quad=self.quad) V = SB.vandermonde(y) self.P4 = SB.get_vandermonde_basis(V) self.T4x = SB.get_vandermonde_basis_derivative(V, 1) phi = np.dot(self.P4, phi_hat) dphidy = np.dot(self.T4x, phi_hat) return eigval, phi, dphidy
def test_Helmholtz2(quad): M = 2 * N SD = ShenDirichletBasis(M, quad=quad, plan=True) kx = 12 points, weights = SD.points_and_weights(M) uj = np.random.randn(M) u_hat = np.zeros(M) u_hat = SD.forward(uj, u_hat) uj = SD.backward(u_hat, uj) #from IPython import embed; embed() A = inner_product((SD, 0), (SD, 2)) B = inner_product((SD, 0), (SD, 0)) s = SD.slice() u1 = np.zeros(M) u1 = SD.forward(uj, u1) c0 = np.zeros_like(u1) c1 = np.zeros_like(u1) c = A.matvec(u1, c0) + kx**2 * B.matvec(u1, c1) b = np.zeros(M) H = Helmholtz(M, kx, SD) b = H.matvec(u1, b) #LUsolve.Mult_Helmholtz_1D(M, SD.quad=="GL", 1, kx**2, u1, b) assert np.allclose(c, b) b = np.zeros((M, 4, 4), dtype=np.complex) u1 = u1.repeat(16).reshape((M, 4, 4)) + 1j * u1.repeat(16).reshape( (M, 4, 4)) kx = np.zeros((4, 4)) + kx H = Helmholtz(M, kx, SD) b = H.matvec(u1, b) #LUsolve.Mult_Helmholtz_3D_complex(M, SD.quad=="GL", 1.0, kx**2, u1, b) assert np.linalg.norm(b[:, 2, 2].real - c) / (M * 16) < 1e-12 assert np.linalg.norm(b[:, 2, 2].imag - c) / (M * 16) < 1e-12
class OrrSommerfeld(object): def __init__(self, **kwargs): self.par = {'alfa': 1., 'Re': 8000., 'N': 80, 'quad': 'GC'} self.par.update(**kwargs) for name, val in six.iteritems(self.par): setattr(self, name, val) self.P4 = np.zeros(0) self.T4x = np.zeros(0) self.SB, self.SD, self.CDB = (None, ) * 3 self.x, self.w = None, None def interp(self, y, eigvals, eigvectors, eigval=1, same_mesh=False, verbose=False): """Interpolate solution eigenvector and it's derivative onto y args: y Interpolation points eigvals All computed eigenvalues eigvectors All computed eigenvectors kwargs: eigval The chosen eigenvalue, ranked with descending imaginary part. The largest imaginary part is 1, the second largest is 2, etc. same_mesh Boolean. Whether or not to interpolate to the same quadrature points as used for computing the eigenvectors verbose Boolean. Print information or not """ N = self.N nx, eigval = self.get_eigval(eigval, eigvals, verbose) phi_hat = np.zeros(N, np.complex) phi_hat[:-4] = np.squeeze(eigvectors[:, nx]) if same_mesh: phi = np.zeros_like(phi_hat) dphidy = np.zeros_like(phi_hat) if self.SB is None: self.SB = ShenBiharmonicBasis(N, quad=self.quad, plan=True) self.SD = ShenDirichletBasis(N, quad=self.quad, plan=True) self.CDB = inner_product((self.SD, 0), (self.SB, 1)) phi = self.SB.ifst(phi_hat, phi) dphidy_hat = self.CDB.matvec(phi_hat) dphidy_hat = self.SD.apply_inverse_mass(dphidy_hat) dphidy = self.SD.backward(dphidy_hat, dphidy) else: # Recompute interpolation matrices if necessary if not len(self.P4) == len(y): SB = ShenBiharmonicBasis(N, quad=self.quad) V = SB.vandermonde(y) self.P4 = SB.get_vandermonde_basis(V) self.T4x = SB.get_vandermonde_basis_derivative(V, 1) phi = np.dot(self.P4, phi_hat) dphidy = np.dot(self.T4x, phi_hat) return eigval, phi, dphidy def assemble(self): N = self.N SB = ShenBiharmonicBasis(N, quad=self.quad) SB.plan((N, N), 0, np.float, {}) x, w = self.x, self.w = SB.points_and_weights(N) V = SB.vandermonde(x) # Trial function P4 = SB.get_vandermonde_basis(V) # Second derivatives T2x = SB.get_vandermonde_basis_derivative(V, 2) # (u'', v) K = np.zeros((N, N)) K[:-4, :-4] = inner_product((SB, 0), (SB, 2)).diags().toarray() # ((1-x**2)u, v) xx = np.broadcast_to((1 - x**2)[:, np.newaxis], (N, N)) #K1 = np.dot(w*P4.T, xx*P4) # Alternative: K1 = np.dot(w*P4.T, ((1-x**2)*P4.T).T) K1 = np.zeros((N, N)) K1 = SB.scalar_product(xx * P4, K1) K1 = extract_diagonal_matrix( K1).diags().toarray() # For improved roundoff # ((1-x**2)u'', v) K2 = np.zeros((N, N)) K2 = SB.scalar_product(xx * T2x, K2) K2 = extract_diagonal_matrix( K2).diags().toarray() # For improved roundoff # (u'''', v) Q = np.zeros((self.N, self.N)) Q[:-4, :-4] = inner_product((SB, 0), (SB, 4)).diags().toarray() # (u, v) M = np.zeros((self.N, self.N)) M[:-4, :-4] = inner_product((SB, 0), (SB, 0)).diags().toarray() Re = self.Re a = self.alfa B = -Re * a * 1j * (K - a**2 * M) A = Q - 2 * a**2 * K + a**4 * M - 2 * a * Re * 1j * M - 1j * a * Re * ( K2 - a**2 * K1) return A, B def solve(self, verbose=False): """Solve the Orr-Sommerfeld eigenvalue problem """ if verbose: print('Solving the Orr-Sommerfeld eigenvalue problem...') print('Re = ' + str(self.par['Re']) + ' and alfa = ' + str(self.par['alfa'])) A, B = self.assemble() return eig(A[:-4, :-4], B[:-4, :-4]) # return eig(np.dot(inv(B[:-4, :-4]), A[:-4, :-4])) @staticmethod def get_eigval(nx, eigvals, verbose=False): """Get the chosen eigenvalue Args: nx The chosen eigenvalue. nx=1 corresponds to the one with the largest imaginary part, nx=2 the second largest etc. eigvals Computed eigenvalues verbose Print the value of the chosen eigenvalue """ indices = np.argsort(np.imag(eigvals)) indi = indices[-1 * np.array(nx)] eigval = eigvals[indi] if verbose: ev = list(eigval) if np.ndim(eigval) else [eigval] indi = list(indi) if np.ndim(indi) else [indi] for i, (e, v) in enumerate(zip(ev, indi)): print('Eigenvalue {} ({}) = {:2.16e}'.format(i + 1, v, e)) return indi, eigval
def get_context(): """Set up context for solver""" # Get points and weights for Chebyshev weighted integrals ST = ShenDirichletBasis(params.N[0], quad=params.Dquad) SB = ShenBiharmonicBasis(params.N[0], quad=params.Bquad) CT = Basis(params.N[0], quad=params.Dquad) ST0 = ShenDirichletBasis(params.N[0], quad=params.Dquad, plan=True) # For 1D problem K0 = C2CBasis(params.N[1], domain=(0, params.L[1])) K1 = R2CBasis(params.N[2], domain=(0, params.L[2])) #CT = ST.CT # Chebyshev transform FST = TensorProductSpace(comm, (ST, K0, K1), **{ 'threads': params.threads, 'planner_effort': params.planner_effort["dct"] }) # Dirichlet FSB = TensorProductSpace(comm, (SB, K0, K1), **{ 'threads': params.threads, 'planner_effort': params.planner_effort["dct"] }) # Biharmonic FCT = TensorProductSpace(comm, (CT, K0, K1), **{ 'threads': params.threads, 'planner_effort': params.planner_effort["dct"] }) # Regular Chebyshev VFS = VectorTensorProductSpace([FSB, FST, FST]) # Padded STp = ShenDirichletBasis(params.N[0], quad=params.Dquad) SBp = ShenBiharmonicBasis(params.N[0], quad=params.Bquad) CTp = Basis(params.N[0], quad=params.Dquad) K0p = C2CBasis(params.N[1], padding_factor=1.5, domain=(0, params.L[1])) K1p = R2CBasis(params.N[2], padding_factor=1.5, domain=(0, params.L[2])) FSTp = TensorProductSpace( comm, (STp, K0p, K1p), **{ 'threads': params.threads, 'planner_effort': params.planner_effort["dct"] }) FSBp = TensorProductSpace( comm, (SBp, K0p, K1p), **{ 'threads': params.threads, 'planner_effort': params.planner_effort["dct"] }) FCTp = TensorProductSpace( comm, (CTp, K0p, K1p), **{ 'threads': params.threads, 'planner_effort': params.planner_effort["dct"] }) VFSp = VectorTensorProductSpace([FSBp, FSTp, FSTp]) VFSp = VFS FCTp = FCT FSTp = FST FSBp = FSB Nu = params.N[0] - 2 # Number of velocity modes in Shen basis Nb = params.N[0] - 4 # Number of velocity modes in Shen biharmonic basis u_slice = slice(0, Nu) v_slice = slice(0, Nb) float, complex, mpitype = datatypes("double") # Mesh variables X = FST.local_mesh(True) x0, x1, x2 = FST.mesh() K = FST.local_wavenumbers(scaled=True) # Solution variables U = Array(VFS, False) U0 = Array(VFS, False) U_hat = Array(VFS) U_hat0 = Array(VFS) g = Array(FST) # primary variable u = (U_hat, g) H_hat = Array(VFS) H_hat0 = Array(VFS) H_hat1 = Array(VFS) dU = Array(VFS) hv = Array(FST) hg = Array(FST) Source = Array(VFS, False) Sk = Array(VFS) K2 = K[1] * K[1] + K[2] * K[2] K_over_K2 = np.zeros((2, ) + g.shape) for i in range(2): K_over_K2[i] = K[i + 1] / np.where(K2 == 0, 1, K2) work = work_arrays() nu, dt, N = params.nu, params.dt, params.N K4 = K2**2 kx = K[0][:, 0, 0] alfa = K2[0] - 2.0 / nu / dt # Collect all matrices mat = config.AttributeDict( dict( CDD=inner_product((ST, 0), (ST, 1)), AB=HelmholtzCoeff(kx, -1.0, -alfa, ST.quad), AC=BiharmonicCoeff(kx, nu * dt / 2., (1. - nu * dt * K2[0]), -(K2[0] - nu * dt / 2. * K4[0]), quad=SB.quad), # Matrices for biharmonic equation CBD=inner_product((SB, 0), (ST, 1)), ABB=inner_product((SB, 0), (SB, 2)), BBB=inner_product((SB, 0), (SB, 0)), SBB=inner_product((SB, 0), (SB, 4)), # Matrices for Helmholtz equation ADD=inner_product((ST, 0), (ST, 2)), BDD=inner_product((ST, 0), (ST, 0)), BBD=inner_product((SB, 0), (ST, 0)), CDB=inner_product((ST, 0), (SB, 1)), ADD0=inner_product((ST0, 0), (ST0, 2)), BDD0=inner_product((ST0, 0), (ST0, 0)), )) # Collect all linear algebra solvers #la = config.AttributeDict(dict( #HelmholtzSolverG = Helmholtz(N[0], np.sqrt(K2[0]+2.0/nu/dt), ST), #BiharmonicSolverU = Biharmonic(N[0], -nu*dt/2., 1.+nu*dt*K2[0], #-(K2[0] + nu*dt/2.*K4[0]), quad=SB.quad, #solver="cython"), #HelmholtzSolverU0 = Helmholtz(N[0], np.sqrt(2./nu/dt), ST), #TDMASolverD = TDMA(inner_product((ST, 0), (ST, 0))) #) #) mat.ADD.axis = 0 mat.BDD.axis = 0 mat.SBB.axis = 0 la = config.AttributeDict( dict(HelmholtzSolverG=Helmholtz(mat.ADD, mat.BDD, -np.ones( (1, 1, 1)), (K2[0] + 2.0 / nu / dt)[np.newaxis, :, :]), BiharmonicSolverU=Biharmonic( mat.SBB, mat.ABB, mat.BBB, -nu * dt / 2. * np.ones( (1, 1, 1)), (1. + nu * dt * K2[0])[np.newaxis, :, :], (-(K2[0] + nu * dt / 2. * K4[0]))[np.newaxis, :, :]), HelmholtzSolverU0=old_Helmholtz(N[0], np.sqrt(2. / nu / dt), ST), TDMASolverD=TDMA(inner_product((ST, 0), (ST, 0))))) hdf5file = KMMWriter({ "U": U[0], "V": U[1], "W": U[2] }, chkpoint={ 'current': { 'U': U }, 'previous': { 'U': U0 } }, filename=params.solver + ".h5", mesh={ "x": x0, "y": x1, "z": x2 }) return config.AttributeDict(locals())
def get_context(): """Set up context for solver""" # Get points and weights for Chebyshev weighted integrals ST = ShenDirichletBasis(params.N[0], quad=params.Dquad, threads=params.threads, planner_effort=params.planner_effort["dct"]) SN = ShenNeumannBasis(params.N[0], quad=params.Nquad, threads=params.threads, planner_effort=params.planner_effort["dct"]) CT = ST.CT Nf = params.N[ 2] / 2 + 1 # Number of independent complex wavenumbers in z-direction Nu = params.N[0] - 2 # Number of velocity modes in Shen basis Nq = params.N[0] - 3 # Number of pressure modes in Shen basis u_slice = slice(0, Nu) p_slice = slice(1, Nu) FST = SlabShen_R2C(params.N, params.L, comm, threads=params.threads, communication=params.communication, planner_effort=params.planner_effort, dealias_cheb=params.dealias_cheb) float, complex, mpitype = datatypes("double") # Get grid for velocity points X = FST.get_local_mesh(ST) x0, x1, x2 = FST.get_mesh_dims(ST) U = zeros((3, ) + FST.real_shape(), dtype=float) U_hat = zeros((3, ) + FST.complex_shape(), dtype=complex) P = zeros(FST.real_shape(), dtype=float) P_hat = zeros(FST.complex_shape(), dtype=complex) Pcorr = zeros(FST.complex_shape(), dtype=complex) U0 = zeros((3, ) + FST.real_shape(), dtype=float) U_hat0 = zeros((3, ) + FST.complex_shape(), dtype=complex) U_hat1 = zeros((3, ) + FST.complex_shape(), dtype=complex) dU = zeros((3, ) + FST.complex_shape(), dtype=complex) H_hat = zeros((3, ) + FST.complex_shape(), dtype=complex) H_hat0 = zeros((3, ) + FST.complex_shape(), dtype=complex) H_hat1 = zeros((3, ) + FST.complex_shape(), dtype=complex) diff0 = zeros((3, ) + FST.complex_shape(), dtype=complex) Source = zeros((3, ) + FST.real_shape(), dtype=float) Sk = zeros((3, ) + FST.complex_shape(), dtype=complex) K = FST.get_local_wavenumbermesh(scaled=True) K2 = K[1] * K[1] + K[2] * K[2] K_over_K2 = zeros((3, ) + FST.complex_shape()) for i in range(3): K_over_K2[i] = K[i] / np.where(K2 == 0, 1, K2) work = work_arrays() # Primary variable u = (U_hat, P_hat) nu, dt, N = params.nu, params.dt, params.N # Collect all linear algebra solvers la = config.AttributeDict( dict(HelmholtzSolverU=Helmholtz(N[0], np.sqrt(K2[0] + 2.0 / nu / dt), ST), HelmholtzSolverP=Helmholtz(N[0], np.sqrt(K2[0]), SN), TDMASolverD=TDMA(inner_product((ST, 0), (ST, 0))), TDMASolverN=TDMA(inner_product((SN, 0), (SN, 0))))) alfa = K2[0] - 2.0 / nu / dt # Collect all matrices kx = K[0][:, 0, 0] mat = config.AttributeDict( dict(CDN=inner_product((ST, 0), (SN, 1)), CND=inner_product((SN, 0), (ST, 1)), BDN=inner_product((ST, 0), (SN, 0)), CDD=inner_product((ST, 0), (ST, 1)), BDD=inner_product((ST, 0), (ST, 0)), BDT=inner_product((ST, 0), (CT, 0)), AB=HelmholtzCoeff(kx, -1.0, -alfa, ST.quad))) hdf5file = IPCSWriter({ "U": U[0], "V": U[1], "W": U[2], "P": P }, chkpoint={ 'current': { 'U': U, 'P': P }, 'previous': { 'U': U0 } }, filename=params.solver + ".h5", mesh={ "x": x0, "xp": FST.get_mesh_dim(SN, 0), "y": x1, "z": x2 }) return config.AttributeDict(locals())
def test_Mult_Div(): SD = ShenDirichletBasis(N, "GC") SN = ShenNeumannBasis(N, "GC") SD.plan(N, 0, np.complex, {}) SN.plan(N, 0, np.complex, {}) Cm = inner_product((SN, 0), (SD, 1)) Bm = inner_product((SN, 0), (SD, 0)) uk = np.random.randn((N))+np.random.randn((N))*1j vk = np.random.randn((N))+np.random.randn((N))*1j wk = np.random.randn((N))+np.random.randn((N))*1j b = np.zeros(N, dtype=np.complex) uk0 = np.zeros(N, dtype=np.complex) vk0 = np.zeros(N, dtype=np.complex) wk0 = np.zeros(N, dtype=np.complex) uk0 = SD.forward(uk, uk0) uk = SD.backward(uk0, uk) uk0 = SD.forward(uk, uk0) vk0 = SD.forward(vk, vk0) vk = SD.backward(vk0, vk) vk0 = SD.forward(vk, vk0) wk0 = SD.forward(wk, wk0) wk = SD.backward(wk0, wk) wk0 = SD.forward(wk, wk0) LUsolve.Mult_Div_1D(N, 7, 7, uk0[:N-2], vk0[:N-2], wk0[:N-2], b[1:N-2]) uu = np.zeros_like(uk0) v0 = np.zeros_like(vk0) w0 = np.zeros_like(wk0) uu = Cm.matvec(uk0, uu) uu += 1j*7*Bm.matvec(vk0, v0) + 1j*7*Bm.matvec(wk0, w0) #from IPython import embed; embed() assert np.allclose(uu, b) uk0 = uk0.repeat(4*4).reshape((N, 4, 4)) + 1j*uk0.repeat(4*4).reshape((N, 4, 4)) vk0 = vk0.repeat(4*4).reshape((N, 4, 4)) + 1j*vk0.repeat(4*4).reshape((N, 4, 4)) wk0 = wk0.repeat(4*4).reshape((N, 4, 4)) + 1j*wk0.repeat(4*4).reshape((N, 4, 4)) b = np.zeros((N, 4, 4), dtype=np.complex) m = np.zeros((4, 4))+7 n = np.zeros((4, 4))+7 LUsolve.Mult_Div_3D(N, m, n, uk0[:N-2], vk0[:N-2], wk0[:N-2], b[1:N-2]) uu = np.zeros_like(uk0) v0 = np.zeros_like(vk0) w0 = np.zeros_like(wk0) uu = Cm.matvec(uk0, uu) uu += 1j*7*Bm.matvec(vk0, v0) + 1j*7*Bm.matvec(wk0, w0) assert np.allclose(uu, b)
def get_context(): """Set up context for solver""" # Get points and weights for Chebyshev weighted integrals ST = ShenDirichletBasis(params.N[0], quad=params.Dquad) SB = ShenBiharmonicBasis(params.N[0], quad=params.Bquad) CT = ST.CT # Chebyshev transform Nu = params.N[0] - 2 # Number of velocity modes in Shen basis Nb = params.N[0] - 4 # Number of velocity modes in Shen biharmonic basis u_slice = slice(0, Nu) v_slice = slice(0, Nb) FST = SlabShen_R2C(params.N, params.L, comm, threads=params.threads, communication=params.communication, planner_effort=params.planner_effort, dealias_cheb=params.dealias_cheb) float, complex, mpitype = datatypes("double") ST.plan(FST.complex_shape(), 0, complex, { 'threads': params.threads, 'planner_effort': params.planner_effort["dct"] }) SB.plan(FST.complex_shape(), 0, complex, { 'threads': params.threads, 'planner_effort': params.planner_effort["dct"] }) # Mesh variables X = FST.get_local_mesh(ST) x0, x1, x2 = FST.get_mesh_dims(ST) K = FST.get_local_wavenumbermesh(scaled=True) K2 = K[1] * K[1] + K[2] * K[2] K_over_K2 = zeros((2, ) + FST.complex_shape()) for i in range(2): K_over_K2[i] = K[i + 1] / np.where(K2 == 0, 1, K2) # Solution variables U = zeros((3, ) + FST.real_shape(), dtype=float) U0 = zeros((3, ) + FST.real_shape(), dtype=float) U_hat = zeros((3, ) + FST.complex_shape(), dtype=complex) U_hat0 = zeros((3, ) + FST.complex_shape(), dtype=complex) g = zeros(FST.complex_shape(), dtype=complex) # primary variable u = (U_hat, g) H_hat = zeros((3, ) + FST.complex_shape(), dtype=complex) H_hat0 = zeros((3, ) + FST.complex_shape(), dtype=complex) H_hat1 = zeros((3, ) + FST.complex_shape(), dtype=complex) dU = zeros((3, ) + FST.complex_shape(), dtype=complex) hv = zeros(FST.complex_shape(), dtype=complex) hg = zeros(FST.complex_shape(), dtype=complex) Source = zeros((3, ) + FST.real_shape(), dtype=float) Sk = zeros((3, ) + FST.complex_shape(), dtype=complex) work = work_arrays() nu, dt, N = params.nu, params.dt, params.N K4 = K2**2 kx = K[0][:, 0, 0] # Collect all linear algebra solvers la = config.AttributeDict( dict(HelmholtzSolverG=Helmholtz(N[0], np.sqrt(K2[0] + 2.0 / nu / dt), ST), BiharmonicSolverU=Biharmonic(N[0], -nu * dt / 2., 1. + nu * dt * K2[0], -(K2[0] + nu * dt / 2. * K4[0]), quad=SB.quad, solver="cython"), HelmholtzSolverU0=Helmholtz(N[0], np.sqrt(2. / nu / dt), ST), TDMASolverD=TDMA(inner_product((ST, 0), (ST, 0))))) alfa = K2[0] - 2.0 / nu / dt # Collect all matrices mat = config.AttributeDict( dict( CDD=inner_product((ST, 0), (ST, 1)), AB=HelmholtzCoeff(N[0], 1.0, -alfa, ST.quad), AC=BiharmonicCoeff(N[0], nu * dt / 2., (1. - nu * dt * K2[0]), -(K2[0] - nu * dt / 2. * K4[0]), quad=SB.quad), # Matrices for biharmonic equation CBD=inner_product((SB, 0), (ST, 1)), ABB=inner_product((SB, 0), (SB, 2)), BBB=inner_product((SB, 0), (SB, 0)), SBB=inner_product((SB, 0), (SB, 4)), # Matrices for Helmholtz equation ADD=inner_product((ST, 0), (ST, 2)), BDD=inner_product((ST, 0), (ST, 0)), BBD=inner_product((SB, 0), (ST, 0)), CDB=inner_product((ST, 0), (SB, 1)))) hdf5file = KMMWriter({ "U": U[0], "V": U[1], "W": U[2] }, chkpoint={ 'current': { 'U': U }, 'previous': { 'U': U0 } }, filename=params.solver + ".h5", mesh={ "x": x0, "y": x1, "z": x2 }) return config.AttributeDict(locals())
from shenfun.chebyshev.bases import ShenDirichletBasis from shenfun.fourier.bases import FourierBasis from shenfun import Function , TensorProductSpace # TensorProductSpace class is used to construct W , # Function is a subclass of numpy.ndarray used to hold solution arrays. from mpi4py import MPI import numpy as np comm = MPI.COMM_WORLD N = (32, 33) K0 = ShenDirichletBasis(N[0]) K1 = FourierBasis(N[1], dtype=np.float) W = TensorProductSpace(comm, (K0, K1)) print(W) # Alternatively, switch order for periodic in first direction instead # W = TensorProductSpace(comm, (K1, K0), axes=(1, 0)) # # w_hat = Function(W, forward_output=True) # to create an array consistent with the output of W.forward (solution in spectral space) # w = Function(W, forward_output=False) # to create an array consistent with the input (solution in real space). # # uh = np.zeros_like(w_hat) # w_hat = Function(W, buffer=uh) # can be used to wrap a Function instance around a regular Numpy array uh. # Note that uh and w_hat now will share the same data, and modifying one will # naturally modify also the other.
from sympy import Symbol, sin, lambdify import numpy as np from shenfun import inner, div, grad, TestFunction, TrialFunction from shenfun.chebyshev.bases import ShenDirichletBasis # Use sympy to compute a rhs, given an analytical solution x = Symbol("x") ue = sin(np.pi * x) * (1 - x**2) fe = ue.diff(x, 2) # Lambdify for faster evaluation ul = lambdify(x, ue, 'numpy') fl = lambdify(x, fe, 'numpy') N = 32 SD = ShenDirichletBasis(N, plan=True) X = SD.mesh(N) u = TrialFunction(SD) v = TestFunction(SD) fj = fl(X) # Compute right hand side of Poisson equation f_hat = inner(v, fj) # array # Get left hand side of Poisson equation and solve A = inner(v, div(grad(u))) # matrix f_hat = A.solve(f_hat) uj = SD.backward(f_hat) # Compare with analytical solution ue = ul(X)