Skip to content

Commit 57d524e

Browse files
committed
improved fft init
1 parent 549d74f commit 57d524e

File tree

4 files changed

+120
-47
lines changed

4 files changed

+120
-47
lines changed

pySDC/implementations/problem_classes/AllenCahn_2D_FFT.py

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,14 @@ def __init__(self, problem_params, dtype_u=mesh, dtype_f=rhs_imex_mesh):
5858

5959
kx = np.zeros(self.init[0])
6060
ky = np.zeros(self.init[1] // 2 + 1)
61-
for i in range(0, int(self.init[0] / 2) + 1):
62-
kx[i] = 2 * np.pi / self.params.L * i
63-
for i in range(0, int(self.init[1] // 2) + 1):
64-
ky[i] = 2 * np.pi / self.params.L * i
65-
for i in range(int(self.init[0] / 2) + 1, self.init[0]):
66-
kx[i] = 2 * np.pi / self.params.L * (-self.init[0] + i)
67-
68-
self.lap = np.zeros((self.init[0], self.init[1] // 2 + 1))
69-
for i in range(self.init[0]):
70-
for j in range(self.init[1] // 2 + 1):
71-
self.lap[i, j] = -kx[i] ** 2 - ky[j] ** 2
61+
62+
kx[:int(self.init[0] / 2) + 1] = 2 * np.pi / self.params.L * np.arange(0, int(self.init[0] / 2) + 1)
63+
kx[int(self.init[0] / 2) + 1:] = 2 * np.pi / self.params.L * \
64+
np.arange(int(self.init[0] / 2) + 1 - self.init[0], 0)
65+
ky[:] = 2 * np.pi / self.params.L * np.arange(0, self.init[1] // 2 + 1)
66+
67+
xv, yv = np.meshgrid(kx, ky, indexing='ij')
68+
self.lap = -xv ** 2 - yv ** 2
7269

7370
rfft_in = pyfftw.empty_aligned(self.init, dtype='float64')
7471
fft_out = pyfftw.empty_aligned((self.init[0], self.init[1] // 2 + 1), dtype='complex128')
@@ -133,10 +130,9 @@ def u_exact(self, t):
133130
assert t == 0, 'ERROR: u_exact only valid for t=0'
134131
me = self.dtype_u(self.init, val=0.0)
135132
if self.params.init_type == 'circle':
136-
for i in range(self.params.nvars[0]):
137-
for j in range(self.params.nvars[1]):
138-
r2 = self.xvalues[i] ** 2 + self.xvalues[j] ** 2
139-
me.values[i, j] = np.tanh((self.params.radius - np.sqrt(r2)) / (np.sqrt(2) * self.params.eps))
133+
xv, yv = np.meshgrid(self.xvalues, self.xvalues, indexing='ij')
134+
me.values[:, :] = np.tanh((self.params.radius - np.sqrt(xv ** 2 + yv ** 2)) /
135+
(np.sqrt(2) * self.params.eps))
140136
elif self.params.init_type == 'checkerboard':
141137
xv, yv = np.meshgrid(self.xvalues, self.xvalues)
142138
me.values[:, :] = np.sin(2.0 * np.pi * xv) * np.sin(2.0 * np.pi * yv)
@@ -172,19 +168,7 @@ def __init__(self, problem_params, dtype_u=mesh, dtype_f=rhs_imex_mesh):
172168
"""
173169
super(allencahn2d_imex_stab, self).__init__(problem_params=problem_params, dtype_u=dtype_u, dtype_f=dtype_f)
174170

175-
kx = np.zeros(self.init[0])
176-
ky = np.zeros(self.init[1] // 2 + 1)
177-
for i in range(0, int(self.init[0] / 2) + 1):
178-
kx[i] = 2 * np.pi / self.params.L * i
179-
for i in range(0, int(self.init[1] // 2) + 1):
180-
ky[i] = 2 * np.pi / self.params.L * i
181-
for i in range(int(self.init[0] / 2) + 1, self.init[0]):
182-
kx[i] = 2 * np.pi / self.params.L * (-self.init[0] + i)
183-
184-
self.lap = np.zeros((self.init[0], self.init[1] // 2 + 1))
185-
for i in range(self.init[0]):
186-
for j in range(self.init[1] // 2 + 1):
187-
self.lap[i, j] = -kx[i] ** 2 - ky[j] ** 2 - 2.0 / self.params.eps ** 2
171+
self.lap -= 2.0 / self.params.eps ** 2
188172

189173
def eval_f(self, u, t):
190174
"""

pySDC/implementations/problem_classes/AllenCahn_2D_parFFT.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,31 +53,32 @@ def __init__(self, problem_params, dtype_u=mesh, dtype_f=rhs_imex_mesh):
5353
if problem_params['nvars'][0] % 2 != 0:
5454
raise ProblemError('the setup requires nvars = 2^p per dimension')
5555

56-
self.FFT = R2C(np.asarray(problem_params['nvars']), np.asarray((1, 1)), problem_params['comm'], "double")
56+
self.FFT = R2C(np.asarray(problem_params['nvars']),
57+
np.asarray((problem_params['L'], problem_params['L'])),
58+
problem_params['comm'], "double")
5759

5860
# invoke super init, passing number of dofs, dtype_u and dtype_f
5961
super(allencahn2d_imex, self).__init__(init=self.FFT.real_shape(), dtype_u=dtype_u, dtype_f=dtype_f,
6062
params=problem_params)
6163

64+
self.rank = self.params.comm.Get_rank()
65+
6266
self.dx = self.params.L / self.params.nvars[0] # could be useful for hooks, too.
63-
self.xvalues = np.array([i * self.dx - self.params.L / 2.0 for i in range(self.init[0])])
67+
self.xvalues = np.array([i * self.dx - self.params.L / 2.0
68+
for i in range(self.rank * self.init[0], (self.rank + 1) * self.init[0])])
6469
self.yvalues = np.array([i * self.dx - self.params.L / 2.0 for i in range(self.init[1])])
6570

6671
cinit = self.FFT.complex_shape()
6772

6873
kx = np.zeros(cinit[0])
6974
ky = np.zeros(cinit[1])
70-
for i in range(0, int(cinit[0] / 2) + 1):
71-
kx[i] = 2 * np.pi / self.params.L * i
72-
for i in range(0, cinit[1]):
73-
ky[i] = 2 * np.pi / self.params.L * i
74-
for i in range(int(cinit[0] / 2) + 1, cinit[0]):
75-
kx[i] = 2 * np.pi / self.params.L * (-cinit[0] + i)
7675

77-
self.lap = np.zeros((cinit[0], cinit[1]))
78-
for i in range(cinit[0]):
79-
for j in range(cinit[1]):
80-
self.lap[i, j] = -kx[i] ** 2 - ky[j] ** 2
76+
kx[:int(cinit[0] / 2) + 1] = 2 * np.pi / self.params.L * np.arange(0, int(cinit[0] / 2) + 1)
77+
kx[int(cinit[0] / 2) + 1:] = 2 * np.pi / self.params.L * np.arange(int(cinit[0] / 2) + 1 - cinit[0], 0)
78+
ky[:] = 2 * np.pi / self.params.L * np.arange(self.rank * cinit[1], (self.rank + 1) * cinit[1])
79+
80+
xv, yv = np.meshgrid(kx, ky, indexing='ij')
81+
self.lap = -xv ** 2 - yv ** 2
8182

8283
print(self.init, cinit)
8384

@@ -143,12 +144,11 @@ def u_exact(self, t):
143144
assert t == 0, 'ERROR: u_exact only valid for t=0'
144145
me = self.dtype_u(self.init, val=0.0)
145146
if self.params.init_type == 'circle':
146-
for i in range(self.init[0]):
147-
for j in range(self.init[1]):
148-
r2 = self.xvalues[i] ** 2 + self.yvalues[j] ** 2
149-
me.values[i, j] = np.tanh((self.params.radius - np.sqrt(r2)) / (np.sqrt(2) * self.params.eps))
147+
xv, yv = np.meshgrid(self.xvalues, self.yvalues, indexing='ij')
148+
me.values[:, :] = np.tanh((self.params.radius - np.sqrt(xv ** 2 + yv ** 2)) /
149+
(np.sqrt(2) * self.params.eps))
150150
elif self.params.init_type == 'checkerboard':
151-
xv, yv = np.meshgrid(self.xvalues, self.xvalues)
151+
xv, yv = np.meshgrid(self.xvalues, self.yvalues, indexing='ij')
152152
me.values[:, :] = np.sin(2.0 * np.pi * xv) * np.sin(2.0 * np.pi * yv)
153153
elif self.params.init_type == 'random':
154154
me.values[:, :] = np.random.uniform(-1, 1, self.init)

pySDC/playgrounds/parallel/AllenCahn_contracting_circle_FFT.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
from pySDC.implementations.problem_classes.AllenCahn_2D_parFFT import allencahn2d_imex, allencahn2d_imex_stab
1111
from pySDC.implementations.sweeper_classes.imex_1st_order import imex_1st_order
1212
from pySDC.implementations.transfer_classes.TransferMesh_FFT2D import mesh_to_mesh_fft2d
13-
from pySDC.projects.TOMS.AllenCahn_monitor import monitor
13+
from pySDC.playgrounds.parallel.AllenCahn_parallel_monitor import monitor
14+
15+
import pySDC.helpers.plot_helper as plt_helper
1416

1517

1618
# http://www.personal.psu.edu/qud2/Res/Pre/dz09sisc.pdf
@@ -98,7 +100,7 @@ def run_SDC_variant(variant=None):
98100

99101
# setup parameters "in time"
100102
t0 = 0.0
101-
Tend = 0.032
103+
Tend = 0.02
102104

103105
# set MPI communicator
104106
comm = MPI.COMM_WORLD
@@ -128,6 +130,8 @@ def run_SDC_variant(variant=None):
128130
time_rank, time_size))
129131

130132
description['problem_params']['comm'] = space_comm
133+
# set level depending on rank
134+
controller_params['logger_level'] = controller_params['logger_level'] if space_rank == 0 else 99
131135

132136
# instantiate controller
133137
controller = controller_MPI(controller_params=controller_params, description=description, comm=time_comm)
@@ -136,9 +140,19 @@ def run_SDC_variant(variant=None):
136140
P = controller.S.levels[0].prob
137141
uinit = P.u_exact(t0)
138142

143+
# if time_rank == 0:
144+
# plt_helper.plt.imshow(uinit.values)
145+
# plt_helper.savefig(f'uinit_{space_rank}', save_pdf=False, save_pgf=False, save_png=True)
146+
# exit()
147+
139148
# call main function to get things done...
140149
uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend)
141150

151+
if time_rank == 0:
152+
plt_helper.plt.imshow(uend.values)
153+
plt_helper.savefig(f'uend_{space_rank}', save_pdf=False, save_pgf=False, save_png=True)
154+
# exit()
155+
142156
rank = comm.Get_rank()
143157

144158
# filter statistics by variant (number of iterations)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import numpy as np
2+
3+
from pySDC.core.Hooks import hooks
4+
5+
6+
class monitor(hooks):
7+
8+
def __init__(self):
9+
"""
10+
Initialization of Allen-Cahn monitoring
11+
"""
12+
super(monitor, self).__init__()
13+
14+
self.init_radius = None
15+
16+
def pre_run(self, step, level_number):
17+
"""
18+
Overwrite standard pre run hook
19+
20+
Args:
21+
step (pySDC.Step.step): the current step
22+
level_number (int): the current level number
23+
"""
24+
super(monitor, self).pre_run(step, level_number)
25+
L = step.levels[0]
26+
27+
c = np.count_nonzero(L.u[0].values > 0.0)
28+
radius = np.sqrt(c / np.pi) * L.prob.dx
29+
30+
radius1 = 0
31+
rows, cols = np.where(L.u[0].values > 0.0)
32+
for r in rows:
33+
radius1 = max(radius1, abs(L.prob.xvalues[r]))
34+
35+
# rows1 = np.where(L.u[0].values[int((L.prob.init[0]) / 2), :int((L.prob.init[0]) / 2)] > -0.99)
36+
# rows2 = np.where(L.u[0].values[int((L.prob.init[0]) / 2), :int((L.prob.init[0]) / 2)] < 0.99)
37+
# interface_width = (rows2[0][-1] - rows1[0][0]) * L.prob.dx / L.prob.params.eps
38+
39+
self.init_radius = L.prob.params.radius
40+
41+
if L.time == 0.0:
42+
self.add_to_stats(process=step.status.slot, time=L.time, level=-1, iter=step.status.iter,
43+
sweep=L.status.sweep, type='computed_radius', value=radius)
44+
self.add_to_stats(process=step.status.slot, time=L.time, level=-1, iter=step.status.iter,
45+
sweep=L.status.sweep, type='exact_radius', value=self.init_radius)
46+
# self.add_to_stats(process=step.status.slot, time=L.time, level=-1, iter=step.status.iter,
47+
# sweep=L.status.sweep, type='interface_width', value=interface_width)
48+
49+
def post_step(self, step, level_number):
50+
"""
51+
Overwrite standard post step hook
52+
53+
Args:
54+
step (pySDC.Step.step): the current step
55+
level_number (int): the current level number
56+
"""
57+
super(monitor, self).post_step(step, level_number)
58+
59+
# some abbreviations
60+
L = step.levels[0]
61+
62+
c = np.count_nonzero(L.uend.values >= 0.0)
63+
radius = np.sqrt(c / np.pi) * L.prob.dx
64+
65+
exact_radius = np.sqrt(max(self.init_radius ** 2 - 2.0 * (L.time + L.dt), 0))
66+
# rows1 = np.where(L.uend.values[int((L.prob.init[0]) / 2), :int((L.prob.init[0]) / 2)] > -0.99)
67+
# rows2 = np.where(L.uend.values[int((L.prob.init[0]) / 2), :int((L.prob.init[0]) / 2)] < 0.99)
68+
# interface_width = (rows2[0][-1] - rows1[0][0]) * L.prob.dx / L.prob.params.eps
69+
70+
self.add_to_stats(process=step.status.slot, time=L.time + L.dt, level=-1, iter=step.status.iter,
71+
sweep=L.status.sweep, type='computed_radius', value=radius)
72+
self.add_to_stats(process=step.status.slot, time=L.time + L.dt, level=-1, iter=step.status.iter,
73+
sweep=L.status.sweep, type='exact_radius', value=exact_radius)
74+
# self.add_to_stats(process=step.status.slot, time=L.time + L.dt, level=-1, iter=step.status.iter,
75+
# sweep=L.status.sweep, type='interface_width', value=interface_width)

0 commit comments

Comments
 (0)