1
+ """
2
+ # Exports
3
+ $(EXPORTS)
4
+ """
5
+ module XYAdvection
6
+
7
+ export set_2Dgrid, set_Params, set_Vars, set_Problem, set_initialConditions!,
8
+ run_and_save, get_data, updatevars!, stepforward!, saveoutput
9
+
10
+ using DocStringExtensions
11
+
12
+ using FourierFlows, JLD2
13
+ using LinearAlgebra: mul!, ldiv!
14
+
15
+ """
16
+ struct Params{T} <: AbstractParams
17
+
18
+ The parameters for XYAdvection problem:
19
+ $(FIELDS)
20
+ """
21
+ struct Params{T} <: AbstractParams
22
+ " Diffusion coefficient"
23
+ J :: T
24
+ " Advection coefficient"
25
+ A :: T
26
+ " LG coefficient"
27
+ Γ :: T
28
+ " Average order parameter"
29
+ α :: T
30
+ end
31
+
32
+ """
33
+ struct Vars2D{Aphys, Atrans} <: AbstractVars
34
+
35
+ The variables for XYAdvection problem:
36
+
37
+ $(FIELDS)
38
+ """
39
+ struct Vars2D{Aphys, Atrans} <: AbstractVars
40
+ " px and py field and its x and y derivative pxx, pxy, pyx, pyy"
41
+ px :: Aphys
42
+ py :: Aphys
43
+
44
+ pxx :: Aphys
45
+ pxy :: Aphys
46
+ pyx :: Aphys
47
+ pyy :: Aphys
48
+
49
+ " px_hat, py_hat; FFT of px, py and its derivative fields"
50
+ pxh :: Atrans
51
+ pyh :: Atrans
52
+ pxxh :: Atrans
53
+ pxyh :: Atrans
54
+ pyxh :: Atrans
55
+ pyyh :: Atrans
56
+ end
57
+
58
+ """
59
+ Vars2D(grid)
60
+
61
+ Return the variables `vars` for a XYAdvection problem on `grid`.
62
+
63
+ $(TYPEDFIELDS)
64
+ """
65
+ function Vars2D (grid:: TwoDGrid{T} ) where T
66
+ Dev = typeof (grid. device)
67
+
68
+ @devzeros Dev T (grid. nx, grid. ny) px py pxx pxy pyx pyy
69
+ @devzeros Dev Complex{T} (grid. nkr, grid. nl) pxh pyh pxxh pxyh pyxh pyyh
70
+
71
+ return Vars2D (px, py, pxx, pxy, pyx, pyy, pxh, pyh, pxxh, pxyh, pyxh, pyyh)
72
+ end
73
+
74
+ """
75
+ calcN!(N, sol, t, clock, vars, params, grid)
76
+
77
+ Calculate the nonlinear term for the XYAdvection equation.
78
+ """
79
+ function calcN! (N, sol, t, clock, vars, params, grid)
80
+ # multiply p__h with ik to get derivatives
81
+ @. vars. pxxh = im * grid. kr .* sol[:,:,1 ]
82
+ @. vars. pxyh = im * grid. l .* sol[:,:,1 ]
83
+
84
+ @. vars. pyxh = im * grid. kr .* sol[:,:,2 ]
85
+ @. vars. pyyh = im * grid. l .* sol[:,:,2 ]
86
+
87
+ # get ik*p__h in physical space
88
+ ldiv! (vars. pxx, grid. rfftplan, vars. pxxh) # destroys vars.pxxh when using fftw
89
+ ldiv! (vars. pxy, grid. rfftplan, vars. pxyh) # destroys vars.pxyh when using fftw
90
+ ldiv! (vars. pyx, grid. rfftplan, vars. pyxh) # destroys vars.pyxh when using fftw
91
+ ldiv! (vars. pyy, grid. rfftplan, vars. pyyh) # destroys vars.pyyh when using fftw
92
+
93
+ # non-linear term
94
+ @. vars. pxx = params. A * ((vars. px * vars. pxx) + (vars. py * vars. pxy)) + params. Γ * (params. α - (vars. px^ 2 + vars. py^ 2 ))* vars. px
95
+ @. vars. pyx = params. A * ((vars. px * vars. pyx) + (vars. py * vars. pyy)) + params. Γ * (params. α - (vars. px^ 2 + vars. py^ 2 ))* vars. py
96
+
97
+ # go to fourier space and define N
98
+ mul! (vars. pxxh, grid. rfftplan, vars. pxx)
99
+ mul! (vars. pyxh, grid. rfftplan, vars. pyx)
100
+ N[:,:, 1 ] = vars. pxxh
101
+ N[:,:, 2 ] = vars. pyxh
102
+
103
+ dealias! (N[:,:,1 ], grid)
104
+ dealias! (N[:,:,2 ], grid)
105
+ return nothing
106
+ end
107
+
108
+ """
109
+ Equation(params,grid)
110
+ """
111
+ function Equation (params:: Params , grid:: TwoDGrid )
112
+ dev = grid. device
113
+
114
+ # Linear operator
115
+ L = zeros (dev, eltype (grid), (grid. nkr, grid. nl,2 ))
116
+ @. L[:,:,1 ] = - params. J * grid. kr^ 2 - params. J * grid. l^ 2
117
+ @. L[:,:,2 ] = - params. J * grid. kr^ 2 - params. J * grid. l^ 2
118
+
119
+ # full equation
120
+ return FourierFlows. Equation (L, calcN!, grid)
121
+ end
122
+
123
+ # ################################### Exported Functions #################################
124
+ """
125
+ To be called from main
126
+
127
+ set_2Dgrid(nx::Int64,Lx; dev::Device=CPU(),aliased_fraction = 0,kwargs...)
128
+
129
+ setup 2D grid given the parameters
130
+ """
131
+ function set_2Dgrid (nx:: Int64 ,Lx; dev:: Device = CPU (),aliased_fraction = 0 ,kwargs... )
132
+ grid = TwoDGrid (dev; nx, Lx, aliased_fraction,kwargs... )
133
+ return grid
134
+ end
135
+
136
+ """
137
+ To be called from main
138
+
139
+ set_Params(;J::T,A::T,Γ::T,α::T)
140
+
141
+ setup parameter values for the problem
142
+ """
143
+ function set_Params (;J:: T ,A:: T ,Γ:: T ,α:: T ) where {T<: Float64 }
144
+ params = Params (J, A, Γ, α)
145
+ return params
146
+ end
147
+
148
+ """
149
+ To be called from main
150
+
151
+ set_Vars(grid::TwoDGrid)
152
+
153
+ setup variables for the system
154
+ """
155
+ function set_Vars (grid:: TwoDGrid )
156
+ vars = Vars2D (grid)
157
+ return vars
158
+ end
159
+
160
+
161
+ """
162
+ To be called from main
163
+
164
+ set_Problem(grid::TwoDGrid,params::Params,vars::Vars2D,dt::Float64=0.02,stepper = "ForwardEuler";stepperkwargs...)
165
+
166
+ setup the FourierFlows.Problem
167
+ """
168
+ function set_Problem (grid:: TwoDGrid ,params:: Params ,vars:: Vars2D ,dt:: Float64 = 0.02 ,stepper = " ForwardEuler" ;stepperkwargs... )
169
+
170
+ equation = Equation (params,grid)
171
+
172
+ prob = FourierFlows. Problem (equation, stepper, dt, grid, vars, params; stepperkwargs... )
173
+ return prob
174
+ end
175
+
176
+ """
177
+ updatevars!(prob)
178
+ """
179
+ function updatevars! (prob)
180
+ vars, grid, sol = prob. vars, prob. grid, prob. sol
181
+
182
+ @. vars. pxh = sol[:,:, 1 ]
183
+ @. vars. pyh = sol[:,:, 2 ]
184
+
185
+ ldiv! (vars. px, grid. rfftplan, deepcopy (sol[:,:, 1 ])) # use deepcopy() because irfft destroys its input
186
+ ldiv! (vars. py, grid. rfftplan, deepcopy (sol[:,:, 2 ])) # use deepcopy() because irfft destroys its input
187
+ return nothing
188
+ end
189
+
190
+ """
191
+ set_initialConditions!(prob, px, py)
192
+
193
+ Set the solution `sol` as the transform of `px` and `py` and update `vars`.
194
+ """
195
+ function set_initialConditions! (prob, u, v)
196
+ vars, grid, sol = prob. vars, prob. grid, prob. sol
197
+
198
+ cast_type = typeof (vars. px) # determine the type of vars.px
199
+
200
+ # below, e.g., A(px0) converts px0 to the same type as vars expects
201
+ # (useful when px0 is a CPU array but grid.device is GPU)
202
+ mul! (vars. pxh, grid. rfftplan, cast_type (u))
203
+ mul! (vars. pyh, grid. rfftplan, cast_type (v))
204
+
205
+ @. sol[:,:,1 ] = vars. pxh
206
+ @. sol[:,:,2 ] = vars. pyh
207
+
208
+ updatevars! (prob)
209
+
210
+ return nothing
211
+ end
212
+
213
+ """
214
+ To be called from main
215
+
216
+ run_and_save(prob,nsteps::T=10^5,printFreq::T=10^3;filepath::T2 = ".",filename::T2 = "XYAdvection_data.jld2") where {T<:Integer,T2<:String}
217
+
218
+ Run the problem and save output to file.
219
+ """
220
+ function run_and_save (prob,nsteps:: T = 10 ^ 5 ,printFreq:: T = 10 ^ 3 ;filepath:: T2 = " ." ,filename:: T2 = " XYAdvection_data.jld2" ) where {T<: Integer ,T2<: String }
221
+ # assert nsteps/printFreq is an integer
222
+ @assert isinteger (nsteps/ printFreq) " requires nsteps/printFreq == Integer"
223
+
224
+ fname = joinpath (filepath, filename)
225
+ get_sol (prob) = prob. sol
226
+ out = Output (prob, fname, (:sol , get_sol))
227
+ saveproblem (out)
228
+ for i in 0 : Int (nsteps)
229
+ if i % Int (printFreq)== 0
230
+ saveoutput (out)
231
+ end
232
+ stepforward! (prob)
233
+ updatevars! (prob)
234
+ end
235
+ return out
236
+ end
237
+
238
+ """
239
+ To be called from main
240
+
241
+ get_data(titr::Integer,filepath::String,nx::Integer)
242
+
243
+ Read output data from file and convert to physical space for analysis.
244
+ """
245
+ function get_data (titr:: Integer ,filepath:: String ,nx:: Integer )
246
+ file = jldopen (filepath)
247
+ px = irfft (file[string (" snapshots/sol/" , titr)][:,:, 1 ], nx)
248
+ py = irfft (file[string (" snapshots/sol/" , titr)][:,:, 2 ], nx)
249
+ return px,py
250
+ end
251
+ # ###########################################################################################################
252
+ end # end module
0 commit comments