def initialize(solver, context): c = context # Create mask with ones where |k| < Kf2 and zeros elsewhere kf = config.params.Kf2 c.k2_mask = np.where(c.K2 <= kf**2, 1, 0) np.random.seed(solver.rank) k = np.sqrt(c.K2) k = np.where(k == 0, 1, k) kk = c.K2.copy() kk = np.where(kk == 0, 1, kk) k1, k2, k3 = c.K[0], c.K[1], c.K[2] ksq = np.sqrt(k1**2 + k2**2) ksq = np.where(ksq == 0, 1, ksq) E0 = np.sqrt(9. / 11. / kf * c.K2 / kf**2) * c.k2_mask E1 = np.sqrt(9. / 11. / kf * (k / kf)**(-5. / 3.)) * (1 - c.k2_mask) Ek = E0 + E1 # theta1, theta2, phi, alpha and beta from [1] theta1, theta2, phi = np.random.sample(c.U_hat.shape) * 2j * np.pi alpha = np.sqrt(Ek / 4. / np.pi / kk) * np.exp(1j * theta1) * np.cos(phi) beta = np.sqrt(Ek / 4. / np.pi / kk) * np.exp(1j * theta2) * np.sin(phi) c.U_hat[0] = (alpha * k * k2 + beta * k1 * k3) / (k * ksq) c.U_hat[1] = (beta * k2 * k3 - alpha * k * k1) / (k * ksq) c.U_hat[2] = beta * ksq / k c.mask = c.T.get_mask_nyquist() c.T.mask_nyquist(c.U_hat, c.mask) solver.get_velocity(**c) U_hat = solver.set_velocity(**c) K = c.K # project to zero divergence U_hat[:] -= (K[0] * U_hat[0] + K[1] * U_hat[1] + K[2] * U_hat[2]) * c.K_over_K2 if solver.rank == 0: c.U_hat[:, 0, 0, 0] = 0.0 # Scale to get correct kinetic energy. Target from [2] energy = 0.5 * energy_fourier(c.U_hat, c.T) target = config.params.Re_lam * (config.params.nu * config.params.kd)**2 / np.sqrt(20. / 3.) c.U_hat *= np.sqrt(target / energy) if 'VV' in config.params.solver: c.W_hat = solver.cross2(c.W_hat, c.K, c.U_hat) config.params.t = 0.0 config.params.tstep = 0 c.target_energy = energy_fourier(c.U_hat, c.T)
def init_from_file(filename, solver, context): f = h5py.File(filename, driver="mpio", comm=solver.comm) assert "0" in f["U/3D"] U_hat = context.U_hat s = context.T.local_slice(True) U_hat[:] = f["U/3D/0"][:, s[0], s[1], s[2]] if solver.rank == 0: U_hat[:, 0, 0, 0] = 0.0 if 'VV' in config.params.solver: context.W_hat = solver.cross2(context.W_hat, context.K, context.U_hat) context.target_energy = energy_fourier(U_hat, context.T) f.close()
def test_energy_fourier(N): B0 = FunctionSpace(N[0], 'F', dtype='D') B1 = FunctionSpace(N[1], 'F', dtype='D') B2 = FunctionSpace(N[2], 'F', dtype='d') for bases, axes in zip(((B0, B1, B2), (B0, B2, B1)), ((0, 1, 2), (2, 0, 1))): T = TensorProductSpace(comm, bases, axes=axes) u_hat = Function(T) u_hat[:] = np.random.random( u_hat.shape) + 1j * np.random.random(u_hat.shape) u = u_hat.backward() u_hat = u.forward(u_hat) u = u_hat.backward(u) e0 = comm.allreduce(np.sum(u.v * u.v) / np.prod(N)) e1 = fourier.energy_fourier(u_hat, T) assert abs(e0 - e1) < 1e-10
def update(context): global k, w, im1 c = context params = config.params solver = config.solver if (params.tstep % params.compute_energy == 0 or params.tstep % params.plot_step == 0 and params.plot_step > 0): U = solver.get_velocity(**c) curl = solver.get_curl(**c) if 'NS' in params.solver: solver.get_pressure(**c) if plt is not None: if params.tstep % params.plot_step == 0 and solver.rank == 0 and params.plot_step > 0: if im1 is None: plt.figure() im1 = plt.contourf(c.X[1][:, :, 0], c.X[0][:, :, 0], U[0, :, :, 10], 100) plt.colorbar(im1) plt.draw() globals().update(im1=im1) else: im1.ax.clear() im1.ax.contourf(c.X[1][:, :, 0], c.X[0][:, :, 0], U[0, :, :, 10], 100) im1.autoscale() plt.pause(1e-6) if params.tstep == 1: from spectralDNS.utilities import reset_profile try: reset_profile(profile) print("Reset profile") except: pass if params.tstep % params.compute_energy == 0: #dx, L = params.dx, params.L #if 'NS' in params.solver: #ww = comm.reduce(sum(curl*curl)/prod(params.N)/2) #duidxj = work[(((3,3)+FFT.real_shape()), FFT.float, 0)] #for i in range(3): #for j in range(3): #duidxj[i,j] = FFT.ifftn(1j*K[j]*U_hat[i], duidxj[i,j]) #ww2 = comm.reduce(sum(duidxj*duidxj)/prod(params.N)/2) #ddU = work[(((3,)+FFT.real_shape()), FFT.float, 0)] #dU = ComputeRHS(dU, U_hat) #for i in range(3): #ddU[i] = FFT.ifftn(dU[i], ddU[i]) #ww3 = comm.reduce(sum(ddU*U)/prod(params.N)/2) #if rank == 0: #print ww, params.nu*ww2, ww3, ww-ww2 ww = solver.comm.reduce( sum(curl.astype(float64) * curl.astype(float64)) / prod(params.N) / 2) kk = solver.comm.reduce( sum(U.astype(float64) * U.astype(float64)) / prod(params.N) / 2) # Compute energy with double precision if not 'NS' in params.solver: c.U_hat = c.U.forward(c.U_hat) ww2 = energy_fourier(c.U_hat, c.T) / 2 divu = solver.get_divergence(**context) divu = solver.comm.reduce( sum(divu.astype(float64) * divu.astype(float64)) / prod(params.N) / 2) kold[0] = kk if solver.rank == 0: k.append(kk) w.append(ww) print("%2.2f %2.8f %2.8e %2.8e" % (params.t, float(kk), float(ww2 - kk), float(divu)))
def update(context): global k, w, im1, energy_new c = context params = config.params solver = config.solver curl_hat = Function(c.VT, buffer=c.work[(c.U_hat, 2, True)]) if solver.rank == 0: c.U_hat[:, 0, 0, 0] = 0 if params.solver == 'VV': c.U_hat = solver.cross2(c.U_hat, c.K_over_K2, c.W_hat) energy_new = energy_fourier(c.U_hat, c.T) energy_lower = energy_fourier(c.U_hat * c.k2_mask, c.T) energy_upper = energy_new - energy_lower alpha2 = (c.target_energy - energy_upper) / energy_lower alpha = np.sqrt(alpha2) #du = c.U_hat*c.k2_mask*(alpha) #dus = energy_fourier(du*c.U_hat, c.T) energy_old = energy_new #c.dU[:] = alpha*c.k2_mask*c.U_hat c.U_hat *= (alpha * c.k2_mask + (1 - c.k2_mask)) energy_new = energy_fourier(c.U_hat, c.T) assert np.sqrt((energy_new - c.target_energy)**2) < 1e-7, np.sqrt( (energy_new - c.target_energy)**2) if params.solver == 'VV': c.W_hat = solver.cross2(c.W_hat, c.K, c.U_hat) if (params.tstep % params.compute_energy == 0 or params.tstep % params.plot_step == 0 and params.plot_step > 0): solver.get_velocity(**c) solver.get_curl(**c) if 'NS' in params.solver: solver.get_pressure(**c) K = c.K if plt is not None: if params.tstep % params.plot_step == 0 and solver.rank == 0 and params.plot_step > 0: #div_u = solver.get_divergence(**c) if not plt.fignum_exists(1): plt.figure(1) #im1 = plt.contourf(c.X[1][:,:,0], c.X[0][:,:,0], div_u[:,:,10], 100) im1 = plt.contourf(c.X[1][..., 0], c.X[0][..., 0], c.U[0, ..., 10], 100) plt.colorbar(im1) plt.draw() else: im1.ax.clear() #im1.ax.contourf(c.X[1][:,:,0], c.X[0][:,:,0], div_u[:,:,10], 100) im1.ax.contourf(c.X[1][..., 0], c.X[0][..., 0], c.U[0, ..., 10], 100) im1.autoscale() plt.pause(1e-6) if params.tstep % params.compute_spectrum == 0: Ek, _, _, _, _ = spectrum(solver, context) f = h5py.File(context.spectrumname, driver='mpio', comm=solver.comm) f['Turbulence/Ek'].create_dataset(str(params.tstep), data=Ek) f.close() if params.tstep % params.compute_energy == 0: dx, L = params.dx, params.L #ww = solver.comm.reduce(sum(curl*curl)/np.prod(params.N)/2) duidxj = np.zeros(((3, 3) + c.U[0].shape), dtype=c.float) for i in range(3): for j in range(3): duidxj[i, j] = c.T.backward(1j * K[j] * c.U_hat[i], duidxj[i, j]) ww2 = L2_norm(solver.comm, duidxj) * params.nu #ww2 = solver.comm.reduce(sum(duidxj*duidxj)) ddU = np.zeros(((3, ) + c.U[0].shape), dtype=c.float) dU = solver.ComputeRHS(c.dU, c.U_hat, solver, **c) for i in range(3): ddU[i] = c.T.backward(dU[i], ddU[i]) ww3 = solver.comm.allreduce(sum(ddU * c.U)) / np.prod(params.N) ##if solver.rank == 0: ##print('W ', params.nu*ww, params.nu*ww2, ww3, ww-ww2) curl_hat = solver.cross2(curl_hat, K, c.U_hat) dissipation = energy_fourier(curl_hat, c.T) div_u = solver.get_divergence(**c) #du = 1j*(c.K[0]*c.U_hat[0]+c.K[1]*c.U_hat[1]+c.K[2]*c.U_hat[2]) div_u = L2_norm(solver.comm, div_u) #div_u2 = energy_fourier(solver.comm, 1j*(K[0]*c.U_hat[0]+K[1]*c.U_hat[1]+K[2]*c.U_hat[2])) kk = 0.5 * energy_new eps = dissipation * params.nu Re_lam = np.sqrt(20 * kk**2 / (3 * params.nu * eps)) Re_lam2 = kk * np.sqrt(20. / 3.) / (params.nu * params.kd)**2 kold[0] = energy_new e0, e1 = energy_new, L2_norm(solver.comm, c.U) ww4 = (energy_new - energy_old) / 2 / params.dt if solver.rank == 0: k.append(energy_new) w.append(dissipation) print('%2.4f %2.6e %2.6e %2.6e %2.6e %2.6e %2.6e %2.6e %2.6e' % (params.t, e0, e1, eps, ww2, ww3, ww4, Re_lam, Re_lam2))