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