def test_project_2dirichlet(quad): x, y = symbols("x,y") ue = (cos(4*y)*sin(2*x))*(1-x**2)*(1-y**2) sizes = (18, 17) D0 = lbases.ShenDirichlet(sizes[0], quad=quad) D1 = lbases.ShenDirichlet(sizes[1], quad=quad) B0 = lbases.Orthogonal(sizes[0], quad=quad) B1 = lbases.Orthogonal(sizes[1], quad=quad) DD = TensorProductSpace(comm, (D0, D1)) BD = TensorProductSpace(comm, (B0, D1)) DB = TensorProductSpace(comm, (D0, B1)) BB = TensorProductSpace(comm, (B0, B1)) X = DD.local_mesh(True) uh = Function(DD, buffer=ue) dudx_hat = project(Dx(uh, 0, 1), BD) dx = Function(BD, buffer=ue.diff(x, 1)) assert np.allclose(dx, dudx_hat, 0, 1e-5) dudy = project(Dx(uh, 1, 1), DB).backward() duedy = Array(DB, buffer=ue.diff(y, 1)) assert np.allclose(duedy, dudy, 0, 1e-5) us_hat = Function(BB) uq = uh.backward() us = project(uq, BB, output_array=us_hat).backward() assert np.allclose(us, uq, 0, 1e-5) dudxy = project(Dx(us_hat, 0, 1) + Dx(us_hat, 1, 1), BB).backward() dxy = Array(BB, buffer=ue.diff(x, 1) + ue.diff(y, 1)) assert np.allclose(dxy, dudxy, 0, 1e-5), np.linalg.norm(dxy-dudxy)
def standardConvection(rhs, u_dealias, u_hat, K, VFSp, FSTp, FCTp, work, mat, la): rhs[:] = 0 U = u_dealias Uc = work[(U, 1, True)] Uc2 = work[(U, 2, True)] # dudx = 0 on walls from continuity equation. Use Shen Dirichlet basis # Use regular Chebyshev basis for dvdx and dwdx dudx = project(Dx(u_hat[0], 0, 1), FSTp).backward() dvdx = project(Dx(u_hat[1], 0, 1), FCTp).backward() dwdx = project(Dx(u_hat[2], 0, 1), FCTp).backward() dudy = Uc2[0] = FSTp.backward(1j * K[1] * u_hat[0], Uc2[0]) dudz = Uc2[1] = FSTp.backward(1j * K[2] * u_hat[0], Uc2[1]) rhs[0] = FSTp.forward(U[0] * dudx + U[1] * dudy + U[2] * dudz, rhs[0]) Uc2[:] = 0 dvdy = Uc2[0] = FSTp.backward(1j * K[1] * u_hat[1], Uc2[0]) dvdz = Uc2[1] = FSTp.backward(1j * K[2] * u_hat[1], Uc2[1]) rhs[1] = FSTp.forward(U[0] * dvdx + U[1] * dvdy + U[2] * dvdz, rhs[1]) Uc2[:] = 0 dwdy = Uc2[0] = FSTp.backward(1j * K[1] * u_hat[2], Uc2[0]) dwdz = Uc2[1] = FSTp.backward(1j * K[2] * u_hat[2], Uc2[1]) rhs[2] = FSTp.forward(U[0] * dwdx + U[1] * dwdy + U[2] * dwdz, rhs[2]) return rhs
def test_project(typecode, dim, ST, quad): # Using sympy to compute an analytical solution x, y, z = symbols("x,y,z") sizes = (25, 24) funcs = { (1, 0): (cos(4 * y) * sin(2 * np.pi * x)) * (1 - x**2), (1, 1): (cos(4 * x) * sin(2 * np.pi * y)) * (1 - y**2), (2, 0): (sin(6 * z) * cos(4 * y) * sin(2 * np.pi * x)) * (1 - x**2), (2, 1): (sin(2 * z) * cos(4 * x) * sin(2 * np.pi * y)) * (1 - y**2), (2, 2): (sin(2 * x) * cos(4 * y) * sin(2 * np.pi * z)) * (1 - z**2) } syms = {1: (x, y), 2: (x, y, z)} xs = {0: x, 1: y, 2: z} for shape in product(*([sizes] * dim)): bases = [] for n in shape[:-1]: bases.append(Basis(n, 'F', dtype=typecode.upper())) bases.append(Basis(shape[-1], 'F', dtype=typecode)) if dim < 3: n = min(shape) if typecode in 'fdg': n //= 2 n += 1 if n < comm.size: continue for axis in range(dim + 1): ST0 = ST(shape[-1], quad=quad) bases.insert(axis, ST0) fft = TensorProductSpace(comm, bases, dtype=typecode, axes=axes[dim][axis]) X = fft.local_mesh(True) ue = funcs[(dim, axis)] ul = lambdify(syms[dim], ue, 'numpy') uq = ul(*X).astype(typecode) uh = Function(fft) uh = fft.forward(uq, uh) due = ue.diff(xs[axis], 1) dul = lambdify(syms[dim], due, 'numpy') duq = dul(*X).astype(typecode) uf = project(Dx(uh, axis, 1), fft) uy = Array(fft) uy = fft.backward(uf, uy) assert np.allclose(uy, duq, 0, 1e-6) for ax in (x for x in range(dim + 1) if x is not axis): due = ue.diff(xs[axis], 1, xs[ax], 1) dul = lambdify(syms[dim], due, 'numpy') duq = dul(*X).astype(typecode) uf = project(Dx(Dx(uh, axis, 1), ax, 1), fft) uy = Array(fft) uy = fft.backward(uf, uy) assert np.allclose(uy, duq, 0, 1e-6) bases.pop(axis) fft.destroy()
def test_project2(typecode, dim, ST, quad): # Using sympy to compute an analytical solution x, y, z = symbols("x,y,z") sizes = (18, 17) funcx = ((2*np.pi**2*(x**2 - 1) - 1)* cos(2*np.pi*x) - 2*np.pi*x*sin(2*np.pi*x))/(4*np.pi**3) funcy = ((2*np.pi**2*(y**2 - 1) - 1)* cos(2*np.pi*y) - 2*np.pi*y*sin(2*np.pi*y))/(4*np.pi**3) funcz = ((2*np.pi**2*(z**2 - 1) - 1)* cos(2*np.pi*z) - 2*np.pi*z*sin(2*np.pi*z))/(4*np.pi**3) funcs = { (1, 0): cos(4*y)*funcx, (1, 1): cos(4*x)*funcy, (2, 0): sin(3*z)*cos(4*y)*funcx, (2, 1): sin(2*z)*cos(4*x)*funcy, (2, 2): sin(2*x)*cos(4*y)*funcz } syms = {1: (x, y), 2:(x, y, z)} xs = {0:x, 1:y, 2:z} for shape in product(*([sizes]*dim)): bases = [] for n in shape[:-1]: bases.append(Basis(n, 'F', dtype=typecode.upper())) bases.append(Basis(shape[-1], 'F', dtype=typecode)) for axis in range(dim+1): ST0 = ST(shape[-1], quad=quad) bases.insert(axis, ST0) # Spectral space must be aligned in nonperiodic direction, hence axes fft = TensorProductSpace(comm, bases, dtype=typecode, axes=axes[dim][axis]) X = fft.local_mesh(True) ue = funcs[(dim, axis)] ul = lambdify(syms[dim], ue, 'numpy') uq = ul(*X).astype(typecode) uh = Function(fft) uh = fft.forward(uq, uh) due = ue.diff(xs[axis], 1) dul = lambdify(syms[dim], due, 'numpy') duq = dul(*X).astype(typecode) uf = project(Dx(uh, axis, 1), fft) uy = Array(fft) uy = fft.backward(uf, uy) assert np.allclose(uy, duq, 0, 1e-3) # Test also several derivatives for ax in (x for x in range(dim+1) if x is not axis): due = ue.diff(xs[ax], 1, xs[axis], 1) dul = lambdify(syms[dim], due, 'numpy') duq = dul(*X).astype(typecode) uf = project(Dx(Dx(uh, ax, 1), axis, 1), fft) uy = Array(fft) uy = fft.backward(uf, uy) assert np.allclose(uy, duq, 0, 1e-3) bases.pop(axis) fft.destroy()
def test_curl2(): # Test projection of curl K0 = FunctionSpace(N[0], 'C', bc=(0, 0)) K1 = FunctionSpace(N[1], 'F', dtype='D') K2 = FunctionSpace(N[2], 'F', dtype='d') K3 = FunctionSpace(N[0], 'C') T = TensorProductSpace(comm, (K0, K1, K2)) TT = TensorProductSpace(comm, (K3, K1, K2)) X = T.local_mesh(True) K = T.local_wavenumbers(False) Tk = VectorSpace(T) TTk = VectorSpace([T, T, TT]) U = Array(Tk) U_hat = Function(Tk) curl_hat = Function(TTk) curl_ = Array(TTk) # Initialize a Taylor Green vortex U[0] = np.sin(X[0]) * np.cos(X[1]) * np.cos(X[2]) * (1 - X[0]**2) U[1] = -np.cos(X[0]) * np.sin(X[1]) * np.cos(X[2]) * (1 - X[0]**2) U[2] = 0 U_hat = Tk.forward(U, U_hat) Uc = U_hat.copy() U = Tk.backward(U_hat, U) U_hat = Tk.forward(U, U_hat) assert allclose(U_hat, Uc) # Compute curl first by computing each term individually curl_hat[0] = 1j * (K[1] * U_hat[2] - K[2] * U_hat[1]) curl_[0] = T.backward( curl_hat[0], curl_[0]) # No x-derivatives, still in Dirichlet space dwdx_hat = project(Dx(U_hat[2], 0, 1), TT) # Need to use space without bc dvdx_hat = project(Dx(U_hat[1], 0, 1), TT) # Need to use space without bc dwdx = Array(TT) dvdx = Array(TT) dwdx = TT.backward(dwdx_hat, dwdx) dvdx = TT.backward(dvdx_hat, dvdx) curl_hat[1] = 1j * K[2] * U_hat[0] curl_hat[2] = -1j * K[1] * U_hat[0] curl_[1] = T.backward(curl_hat[1], curl_[1]) curl_[2] = T.backward(curl_hat[2], curl_[2]) curl_[1] -= dwdx curl_[2] += dvdx # Now do it with project w_hat = project(curl(U_hat), TTk) w = Array(TTk) w = TTk.backward(w_hat, w) assert allclose(w, curl_)
def test_project_2dirichlet(quad): x, y = symbols("x,y") ue = (cos(4 * y) * sin(2 * x)) * (1 - x**2) * (1 - y**2) sizes = (25, 24) D0 = lbases.ShenDirichletBasis(sizes[0], quad=quad) D1 = lbases.ShenDirichletBasis(sizes[1], quad=quad) B0 = lbases.Basis(sizes[0], quad=quad) B1 = lbases.Basis(sizes[1], quad=quad) DD = TensorProductSpace(comm, (D0, D1)) BD = TensorProductSpace(comm, (B0, D1)) DB = TensorProductSpace(comm, (D0, B1)) BB = TensorProductSpace(comm, (B0, B1)) X = DD.local_mesh(True) ul = lambdify((x, y), ue, 'numpy') uq = Array(DD) uq[:] = ul(*X) uh = Function(DD) uh = DD.forward(uq, uh) dudx_hat = project(Dx(uh, 0, 1), BD) dudx = Array(BD) dudx = BD.backward(dudx_hat, dudx) duedx = ue.diff(x, 1) duxl = lambdify((x, y), duedx, 'numpy') dx = duxl(*X) assert np.allclose(dx, dudx) dudy_hat = project(Dx(uh, 1, 1), DB) dudy = Array(DB) dudy = DB.backward(dudy_hat, dudy) duedy = ue.diff(y, 1) duyl = lambdify((x, y), duedy, 'numpy') dy = duyl(*X) assert np.allclose(dy, dudy) us_hat = Function(BB) us_hat = project(uq, BB, output_array=us_hat) us = Array(BB) us = BB.backward(us_hat, us) assert np.allclose(us, uq) dudxy_hat = project(Dx(us_hat, 0, 1) + Dx(us_hat, 1, 1), BB) dudxy = Array(BB) dudxy = BB.backward(dudxy_hat, dudxy) duedxy = ue.diff(x, 1) + ue.diff(y, 1) duxyl = lambdify((x, y), duedxy, 'numpy') dxy = duxyl(*X) assert np.allclose(dxy, dudxy)
def dw_int(self, u, v): assert isinstance(u, sf.TrialFunction) assert isinstance(v, sf.TestFunction) assert hasattr(self, "_material_parameters") assert len(self._material_parameters) == self._n_material_parameters self.dim = u.dimensions lmbda, mu, c1, c2, c3, c4, c5 = self._material_parameters dw_int = [] if c1 != 0.0: dw_int += inner(c1 * div(grad(u)), div(grad(v))) if c2 != 0.0: dw_int += inner(c2 * div(grad(u)), grad(div(v))) if c3 != 0.0: dw_int += inner(c3 * grad(div(u)), grad(div(v))) if c4 != 0.0: for i in range(self.dim): for j in range(self.dim): for k in range(self.dim): mat = inner(c4 * Dx(Dx(u[i], j), k), Dx(Dx(v[i], j), k)) if isinstance(mat, list): dw_int += mat else: dw_int += [mat] if c5 != 0.0: for i in range(self.dim): for j in range(self.dim): for k in range(self.dim): mat = inner(c5 * Dx(Dx(u[j], i), k), Dx(Dx(v[i], j), k)) if isinstance(mat, list): dw_int += mat else: dw_int += [mat] # add the classical cauchy-terms dw_int += inner(mu * grad(u), grad(v)) for i in range(self.dim): for j in range(self.dim): mat = inner(mu * Dx(u[i], j), Dx(v[j], i)) if isinstance(mat, list): dw_int += mat else: dw_int += [mat] dw_int += inner(lmbda * div(u), div(v)) return dw_int
def test_project_hermite(typecode, dim): # Using sympy to compute an analytical solution x, y, z = symbols("x,y,z") sizes = (20, 19) funcs = { (1, 0): (cos(4*y)*sin(2*x))*exp(-x**2/2), (1, 1): (cos(4*x)*sin(2*y))*exp(-y**2/2), (2, 0): (sin(3*z)*cos(4*y)*sin(2*x))*exp(-x**2/2), (2, 1): (sin(2*z)*cos(4*x)*sin(2*y))*exp(-y**2/2), (2, 2): (sin(2*x)*cos(4*y)*sin(2*z))*exp(-z**2/2) } xs = {0:x, 1:y, 2:z} for shape in product(*([sizes]*dim)): bases = [] for n in shape[:-1]: bases.append(FunctionSpace(n, 'F', dtype=typecode.upper())) bases.append(FunctionSpace(shape[-1], 'F', dtype=typecode)) for axis in range(dim+1): ST0 = hBasis[0](3*shape[-1]) bases.insert(axis, ST0) fft = TensorProductSpace(comm, bases, dtype=typecode, axes=axes[dim][axis]) X = fft.local_mesh(True) ue = funcs[(dim, axis)] due = ue.diff(xs[0], 1) u_h = project(ue, fft) du_h = project(due, fft) du2 = project(Dx(u_h, 0, 1), fft) assert np.linalg.norm(du_h-du2) < 1e-5 bases.pop(axis) fft.destroy()
def interp(self, y, eigvals, eigvectors, eigval=1, verbose=False): """Interpolate solution eigenvector and it's derivative onto y Parameters ---------- y : array Interpolation points eigvals : array All computed eigenvalues eigvectors : array All computed eigenvectors eigval : int, optional The chosen eigenvalue, ranked with descending imaginary part. The largest imaginary part is 1, the second largest is 2, etc. verbose : bool, optional Print information or not """ nx, eigval = self.get_eigval(eigval, eigvals, verbose) SB = Basis(self.N, 'C', bc='Biharmonic', quad=self.quad, dtype='D') phi_hat = Function(SB) phi_hat[:-4] = np.squeeze(eigvectors[:, nx]) phi = phi_hat.eval(y) dphidy = Dx(phi_hat, 0, 1).eval(y) return eigval, phi, dphidy
def divergenceConvection(rhs, u_dealias, u_hat, K, VFSp, FSTp, FSBp, FCTp, work, mat, la, add=False): """c_i = div(u_i u_j)""" if not add: rhs.fill(0) F_tmp = Function(VFSp, buffer=work[(rhs, 0, True)]) F_tmp2 = Function(VFSp, buffer=work[(rhs, 1, True)]) U = u_dealias F_tmp[0] = FSTp.forward(U[0]*U[0], F_tmp[0]) F_tmp[1] = FSTp.forward(U[0]*U[1], F_tmp[1]) F_tmp[2] = FSTp.forward(U[0]*U[2], F_tmp[2]) F_tmp2 = project(Dx(F_tmp, 0, 1), VFSp, output_array=F_tmp2) rhs += F_tmp2 F_tmp2[0] = FSTp.forward(U[0]*U[1], F_tmp2[0]) F_tmp2[1] = FSTp.forward(U[0]*U[2], F_tmp2[1]) rhs[0] += 1j*K[1]*F_tmp2[0] # duvdy rhs[0] += 1j*K[2]*F_tmp2[1] # duwdz F_tmp[0] = FSTp.forward(U[1]*U[1], F_tmp[0]) F_tmp[1] = FSTp.forward(U[1]*U[2], F_tmp[1]) F_tmp[2] = FSTp.forward(U[2]*U[2], F_tmp[2]) rhs[1] += 1j*K[1]*F_tmp[0] # dvvdy rhs[1] += 1j*K[2]*F_tmp[1] # dvwdz rhs[2] += 1j*K[1]*F_tmp[1] # dvwdy rhs[2] += 1j*K[2]*F_tmp[2] # dwwdz return rhs
def compute_cauchy_stresses(self, u_hat): assert isinstance(u_hat, sf.Function) space = u_hat[0].function_space().get_orthogonal() dim = len(space.bases) # number of dofs for each component N = [u_hat.function_space().spaces[0].bases[i].N for i in range(dim)] lmbda, mu = self._material_parameters # displacement gradient H = np.empty(shape=(dim, dim, *N)) for i in range(dim): for j in range(dim): H[i, j] = sf.project(Dx(u_hat[i], j), space).backward() # linear strain tensor E = 0.5 * (H + np.swapaxes(H, 0, 1)) # trace of linear strain tensor trE = np.trace(E) # create block with identity matrices on diagonal identity = np.zeros_like(H) for i in range(dim): identity[i, i] = np.ones(N) # Cauchy stress tensor T = 2.0 * mu * E + lmbda * trE * identity return T, space
def test_project(typecode, dim, ST, quad): # Using sympy to compute an analytical solution x, y, z = symbols("x,y,z") sizes = (20, 19) funcs = { (1, 0): (cos(1*y)*sin(1*np.pi*x))*(1-x**2), (1, 1): (cos(1*x)*sin(1*np.pi*y))*(1-y**2), (2, 0): (sin(1*z)*cos(1*y)*sin(1*np.pi*x))*(1-x**2), (2, 1): (sin(1*z)*cos(1*x)*sin(1*np.pi*y))*(1-y**2), (2, 2): (sin(1*x)*cos(1*y)*sin(1*np.pi*z))*(1-z**2) } xs = {0:x, 1:y, 2:z} for shape in product(*([sizes]*dim)): bases = [] for n in shape[:-1]: bases.append(FunctionSpace(n, 'F', dtype=typecode.upper())) bases.append(FunctionSpace(shape[-1], 'F', dtype=typecode)) for axis in range(dim+1): ST0 = ST(shape[-1], quad=quad) bases.insert(axis, ST0) fft = TensorProductSpace(comm, bases, dtype=typecode, axes=axes[dim][axis]) dfft = fft.get_orthogonal() X = fft.local_mesh(True) ue = funcs[(dim, axis)] uq = Array(fft, buffer=ue) uh = Function(fft) uh = fft.forward(uq, uh) due = ue.diff(xs[axis], 1) duq = Array(fft, buffer=due) uf = project(Dx(uh, axis, 1), dfft).backward() assert np.linalg.norm(uf-duq) < 1e-5 for ax in (x for x in range(dim+1) if x is not axis): due = ue.diff(xs[axis], 1, xs[ax], 1) duq = Array(fft, buffer=due) uf = project(Dx(Dx(uh, axis, 1), ax, 1), dfft).backward() assert np.linalg.norm(uf-duq) < 1e-5 bases.pop(axis) fft.destroy() dfft.destroy()
def compute_hyper_stresses(self, u_hat): assert isinstance(u_hat, sf.Function) space = u_hat[0].function_space() dim = len(space.bases) c1, c2, c3, c4, c5 = self._material_parameters[2:] N = [u_hat.function_space().spaces[0].bases[i].N for i in range(dim)] Laplace = np.zeros(shape=(dim, *N)) for i in range(dim): for j in range(dim): Laplace[i] += sf.project(Dx(u_hat[i], j, 2), space).backward() GradDiv = np.zeros(shape=(dim, *N)) for i in range(dim): for j in range(dim): GradDiv[i] += sf.project( Dx(Dx(u_hat[j], j), i), space ).backward() GradGrad = np.empty(shape=(dim, dim, dim, *N)) for i in range(dim): for j in range(dim): for k in range(dim): GradGrad[i, j, k] = sf.project( Dx(Dx(u_hat[i], j), k), space ).backward() identity = np.identity(dim) # hyper stresses T = c1 * np.swapaxes(np.tensordot(identity, Laplace, axes=0), 0, 2) \ + c2 / 2.0 * (np.tensordot(identity, Laplace, axes=0) + np.swapaxes(np.tensordot(identity, Laplace, axes=0), 1, 2) ) \ + c3 / 2.0 * (np.tensordot(identity, GradDiv, axes=0) + np.swapaxes(np.tensordot(identity, GradDiv, axes=0), 1, 2) ) \ + c4 * GradGrad \ + c5 / 2.0 * (np.swapaxes(GradGrad, 0, 1) + np.swapaxes(GradGrad, 0, 2)) return T, space
def dw_int(self, u, v): assert isinstance(u, sf.TrialFunction) assert isinstance(v, sf.TestFunction) assert hasattr(self, "_material_parameters") assert len(self._material_parameters) == self._n_material_parameters self.dim = u.dimensions lmbda, mu = self._material_parameters A = inner(mu * grad(u), grad(v)) B = [] for i in range(self.dim): for j in range(self.dim): mat = inner(mu * Dx(u[i], j), Dx(v[j], i)) if isinstance(mat, list): B += mat else: B += [mat] C = inner(lmbda * div(u), div(v)) dw_int = A + B + C return dw_int
def standardConvection(rhs, u_dealias, u_hat, K, VFSp, FSTp, FSBp, FCTp, work, mat, la): rhs[:] = 0 U = u_dealias Uc = work[(U, 1, True)] Uc2 = work[(U, 2, True)] F_tmp = work[(rhs, 0, True)] # dudx = 0 from continuity equation. Use Shen Dirichlet basis # Use regular Chebyshev basis for dvdx and dwdx #F_tmp[0] = mat.CDB.matvec(u_hat[0], F_tmp[0]) #F_tmp[0] = la.TDMASolverD(F_tmp[0]) #dudx = Uc[0] = FSTp.backward(F_tmp[0], Uc[0]) #LUsolve.Mult_CTD_3D(params.N[0], u_hat[1], u_hat[2], F_tmp[1], F_tmp[2]) #dvdx = Uc[1] = FCTp.backward(F_tmp[1], Uc[1]) #dwdx = Uc[2] = FCTp.backward(F_tmp[2], Uc[2]) dudx = project(Dx(u_hat[0], 0, 1), FSTp).backward() dvdx = project(Dx(u_hat[1], 0, 1), FCTp).backward() dwdx = project(Dx(u_hat[2], 0, 1), FCTp).backward() dudy = Uc2[0] = FSBp.backward(1j*K[1]*u_hat[0], Uc2[0]) dudz = Uc2[1] = FSBp.backward(1j*K[2]*u_hat[0], Uc2[1]) rhs[0] = FSTp.forward(U[0]*dudx + U[1]*dudy + U[2]*dudz, rhs[0]) Uc2[:] = 0 dvdy = Uc2[0] = FSTp.backward(1j*K[1]*u_hat[1], Uc2[0]) dvdz = Uc2[1] = FSTp.backward(1j*K[2]*u_hat[1], Uc2[1]) rhs[1] = FSTp.forward(U[0]*dvdx + U[1]*dvdy + U[2]*dvdz, rhs[1]) Uc2[:] = 0 dwdy = Uc2[0] = FSTp.backward(1j*K[1]*u_hat[2], Uc2[0]) dwdz = Uc2[1] = FSTp.backward(1j*K[2]*u_hat[2], Uc2[1]) rhs[2] = FSTp.forward(U[0]*dwdx + U[1]*dwdy + U[2]*dwdz, rhs[2]) return rhs
def get_pressure(context, solver): FCT = context.FCT FST = context.FST U_hat = context.U_hat U_hat0 = context.U_hat0 Um = Function(context.FST) Um[:] = 0.5*(U_hat[0] + U_hat0[0]) U = U_hat.backward(context.U) U0 = U_hat0.backward(context.U0) dt = solver.params.dt Hx = Function(context.FST) Hx[:] = solver.get_convection(**context)[0] v = TestFunction(FCT) p = TrialFunction(FCT) rhs_hat = inner(context.nu*div(grad(Um)), v) Hx -= 1./dt*(U_hat[0]-U_hat0[0]) rhs_hat += inner(Hx, v) CT = inner(Dx(p, 0, 1), v) # Should implement fast solver. Just a backwards substitution # Apply integral constraint A = CT.mats[0] N = A.shape[0] A[-(N-1)] = 1 p_hat = Function(context.FCT) p_hat = CT.solve(rhs_hat, p_hat) p = Array(FCT) p = FCT.backward(p_hat, p) uu = 0. if params.convection == 'Vortex': uu = np.sum((0.5*(U+U0))**2, 0) uu *= 0.5 return p-uu
def get_pressure(context, solver): FCT = context.FCT FST = context.FST U = solver.get_velocity(**context) U0 = context.VFS.backward(context.U_hat0, context.U0) dt = solver.params.dt H_hat = solver.get_convection(**context) Hx = Array(FST) Hx = FST.backward(H_hat[0], Hx) v = TestFunction(FCT) p = TrialFunction(FCT) U = U.as_function() U0 = U0.as_function() rhs_hat = inner((0.5 * context.nu) * div(grad(U[0] + U0[0])), v) Hx -= 1. / dt * (U[0] - U0[0]) rhs_hat += inner(Hx, v) CT = inner(Dx(p, 0), v) # Should implement fast solver. Just a backwards substitution A = CT.diags().toarray() * CT.scale[0] A[-1, 0] = 1 a_i = np.linalg.inv(A) p_hat = Function(context.FCT) for j in range(p_hat.shape[1]): for k in range(p_hat.shape[2]): p_hat[:, j, k] = np.dot(a_i, rhs_hat[:, j, k]) p = Array(FCT) p = FCT.backward(p_hat, p) uu = np.sum((0.5 * (U + U0))**2, 0) uu *= 0.5 return p - uu + 3. / 16.
def test_project_lag(typecode, dim): # Using sympy to compute an analytical solution x, y, z = symbols("x,y,z") sizes = (20, 17) funcs = { (1, 0): (cos(4*y)*sin(2*x))*exp(-x), (1, 1): (cos(4*x)*sin(2*y))*exp(-y), (2, 0): (sin(3*z)*cos(4*y)*sin(2*x))*exp(-x), (2, 1): (sin(2*z)*cos(4*x)*sin(2*y))*exp(-y), (2, 2): (sin(2*x)*cos(4*y)*sin(2*z))*exp(-z) } xs = {0:x, 1:y, 2:z} for shape in product(*([sizes]*dim)): bases = [] for n in shape[:-1]: bases.append(Basis(n, 'F', dtype=typecode.upper())) bases.append(Basis(shape[-1], 'F', dtype=typecode)) for axis in range(dim+1): ST1 = lagBasis[1](3*shape[-1]) bases.insert(axis, ST1) fft = TensorProductSpace(comm, bases, dtype=typecode, axes=axes[dim][axis]) dfft = fft.get_orthogonal() X = fft.local_mesh(True) ue = funcs[(dim, axis)] due = ue.diff(xs[0], 1) u_h = project(ue, fft) du_h = project(due, dfft) du2 = project(Dx(u_h, 0, 1), dfft) uf = u_h.backward() assert np.linalg.norm(du2-du_h) < 1e-3 bases.pop(axis) fft.destroy() dfft.destroy()
# Size of discretization N = int(sys.argv[-2]) SD = Basis(N, family=family, bc='Biharmonic', domain=domain, plan=True) X = SD.mesh(N) u = TrialFunction(SD) v = TestFunction(SD) # Get f on quad points fj = Array(SD, buffer=fl(X)) # Compute right hand side of biharmonic equation f_hat = inner(v, fj) # Get left hand side of biharmonic equation (no integration by parts) S = inner(v, a * Dx(u, 0, 4)) A = inner(v, b * Dx(u, 0, 2)) B = inner(v, c * u) # Create linear algebra solver H = Solver(S, A, B, S.scale, A.scale, B.scale) # Solve and transform to real space u_hat = Function(SD) # Solution spectral space u_hat = H(u_hat, f_hat) # Solve u = SD.backward(u_hat) # Compare with analytical solution uj = ul(X) print("Error=%2.16e" % (np.linalg.norm(uj - u))) assert np.allclose(uj, u)
comm = MPI.COMM_WORLD N = (32, 33, 34) K0 = ShenBiharmonicBasis(N[0]) K1 = C2CBasis(N[1]) K2 = R2CBasis(N[2]) W = TensorProductSpace(comm, (K0, K1, K2)) u = TrialFunction(W) v = TestFunction(W) matrices = inner(v, div(grad(div(grad(u))))) fj = Function(W, False) fj[:] = np.random.random(fj.shape) f_hat = inner(v, fj) # Some right hand side B = Solver(**matrices) # Solve and transform to real space u_hat = Function(W) # Solution spectral space u_hat = B(u_hat, f_hat) # Solve u = Function(W, False) u = W.backward(u_hat, u) # compute dudx of the solution K0 = Basis(N[0]) W0 = TensorProductSpace(comm, (K0, K1, K2)) du_hat = project(Dx(u, 0, 1), W0, uh_hat=u_hat) du = Function(W0, False) du = W0.backward(du_hat, du)
# Size of discretization N = int(sys.argv[-2]) SD = Basis(N, family=family, bc=(a, b, 0, 0), domain=domain) X = SD.mesh() u = TrialFunction(SD) v = TestFunction(SD) # Get f on quad points fj = Array(SD, buffer=fe) # Compute right hand side of biharmonic equation f_hat = inner(v, fj) # Get left hand side of biharmonic equation (no integration by parts) matrices = inner(v, aa * Dx(u, 0, 4) + bb * Dx(u, 0, 2) + cc * u) # Function to hold the solution u_hat = Function(SD) # Some work required for inhomogeneous boundary conditions only if SD.has_nonhomogeneous_bcs: bc_mats = extract_bc_matrices([matrices]) # Add boundary terms to the known right hand side SD.bc.set_boundary_dofs(u_hat, final=True) # Fixes boundary dofs in u_hat w0 = np.zeros_like(u_hat) for m in bc_mats: f_hat -= m.matvec(u_hat, w0) # Create linear algebra solver
def Dh(self, dvar, dim): ''' Wrapper around Dx ''' dvar[:] = self.T.backward(project(Dx(self.hf, dim, 1), self.T)) return dvar
# Size of discretization N = eval(sys.argv[-2]) SD = Basis(N, plan=True) X = SD.mesh(N) u = TrialFunction(SD) v = TestFunction(SD) # Get f on quad points fj = fl(X) # Compute right hand side of biharmonic equation f_hat = inner(v, fj) # Get left hand side of biharmonic equation (no integration by parts) S = inner(v, Dx(u, 0, 4)) A = inner(v, Dx(u, 0, 2)) B = inner(v, u) # Create linear algebra solver H = Solver(S, A, B, a, b, c) # Solve and transform to real space u_hat = np.zeros(N) # Solution spectral space u_hat = H(u_hat, f_hat) # Solve u = SD.backward(u_hat) # Compare with analytical solution uj = ul(X) print("Error=%2.16e" %(np.linalg.norm(uj-u))) #assert np.allclose(uj, u)