25 k = np.fft.fftfreq(N, 1.0 / N)
26 KX, KY = np.meshgrid(k, k, indexing=
"ij")
28 x = TWO_PI * np.arange(N) / N
29 X, Y = np.meshgrid(x, x, indexing=
"ij")
30 u = U0 + A * np.sin(X) * np.cos(Y)
31 v = -A * np.cos(X) * np.sin(Y)
34 b = bvec.reshape(N, N)
36 bx = np.real(np.fft.ifft2(1j * KX * bh)); by = np.real(np.fft.ifft2(1j * KY * bh))
37 lap = np.real(np.fft.ifft2(-K2 * bh))
38 r = u * bx + v * by - D * lap
39 return (r - r.mean()).ravel() + b.mean()
42 rh = np.fft.fft2(r.reshape(N, N))
43 with np.errstate(divide=
"ignore", invalid=
"ignore"):
44 bh = np.where(K2 > 0, rh / (D * K2), rh)
45 return np.real(np.fft.ifft2(bh)).ravel()
47 op = spla.LinearOperator((N * N, N * N), matvec=L)
48 P = spla.LinearOperator((N * N, N * N), matvec=Pinv)
50 for comp, rhs
in ((
"xx", u.mean() - u), (
"yy", v.mean() - v)):
51 b, info = spla.gmres(op, rhs.ravel(), M=P, rtol=1e-12, restart=200, maxiter=50)
53 bh = np.fft.fft2(b.reshape(N, N))
54 bx = np.real(np.fft.ifft2(1j * KX * bh)); by = np.real(np.fft.ifft2(1j * KY * bh))
56 out.append(D * np.mean((1 + bx) ** 2 + by**2))
58 out.append(D * np.mean(bx**2 + (1 + by) ** 2))
66def simulate(U0, A, D, Np, dt, T, nper_fpt=(1, 4, 16), seed=0, nsave=400):
67 rng = np.random.default_rng(seed)
68 x = rng.random(Np) * TWO_PI; y = rng.random(Np) * TWO_PI
70 nsteps = int(round(T / dt))
71 every = max(1, nsteps // nsave)
74 fpt = {n: np.full(Np, np.nan)
for n
in nper_fpt}
75 s = np.sqrt(2 * D * dt)
76 for it
in range(nsteps):
78 ts.append(it * dt); X.append(x - x0); Y.append(y.copy())
79 U.append(
vel(x, y, U0, A)[0])
80 u1, v1 =
vel(x, y, U0, A)
81 u2, v2 =
vel(x + u1 * dt, y + v1 * dt, U0, A)
82 x = x + 0.5 * (u1 + u2) * dt + s * rng.standard_normal(Np)
83 y = y + 0.5 * (v1 + v2) * dt + s * rng.standard_normal(Np)
86 hit = np.isnan(fpt[n]) & (x - x0 >= n * TWO_PI)
88 return np.array(ts), np.array(X), np.array(U), fpt
92 i1, i2 = np.searchsorted(ts, t1), np.searchsorted(ts, t2)
96 tt = ts[i1:i2 + 1]; vv = v[i1:i2 + 1]
97 return 0.5 * np.polyfit(tt, vv, 1)[0]
99 b = [one(X[:, k::nb])
for k
in range(nb)]
100 return full, np.std(b, ddof=1) / np.sqrt(nb)
109 C = np.array([np.mean(u[: len(u) - l] * u[l:])
for l
in range(nl)])
110 return D + dt * (C.sum() - 0.5 * C[0])
112 b = [one(up[:, k::nb])
for k
in range(nb)]
113 return full, np.std(b, ddof=1) / np.sqrt(nb)
141 for frac
in (0.05, 0.1, 0.25, 0.5, 1.0):
146 for (t1, t2)
in ((0.25 * T, 0.5 * T), (0.5 * T, T)):
simulate(U0, A, D, Np, dt, T, nper_fpt=(1, 4, 16), seed=0, nsave=400)