-
Notifications
You must be signed in to change notification settings - Fork 26
/
gradient.f90
385 lines (315 loc) · 15.6 KB
/
gradient.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
submodule (calculus) gradient
implicit none (type, external)
contains
module procedure grad3D1_curv_3
! grad3D1_curv_3(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 1-DIMENSION. IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE - EXCEPT FOR THE GRID.
!-------STRUCTURE.
!-------
!-------FOR THIS AND FOLLOWING CURV DERIVATIVE PROCEDURES THE UPPER
!-------AND LOWER BOUNDS FOR DIFFERENTIATION CANNOT BE DETERMINED
!-------WITHOUT ADDITIONAL ARGUMENTS SINCE STRUCTURE X CANNOT BE
!-------BE TRIMMED IN THE SAME WAY AS A NORMAL ARRAY. ESSENTIALLY
!-------THE INPUT ARRAY "F" AND GRID NEED TO BE INDEXED DIFFERENTLY, LEADING
!-------TO TWO SEPARATE SETS ON INDICES THROUGHOUT THIS AND SIMILAR ROUTINES.
!-------
!-------ONE ISSUE ADDRESSED HERE IS THAT THE METRIC FACTORS NEED TO KNOW
!-------WHAT PART OF THE GRID THAT THEY ARE BEING USED OVER... IE
!-------IF ANY OF THESE IS FULL GRID THEN THE HALL VERSIONS SHOUDL
!-------SHOULD BE USED FOR THE METRIC FACTORS...
!------------------------------------------------------------
integer :: ix2,ix3,lx1,lx2,lx3
! real(wp), dimension(1:size(f,1),1:size(f,2),1:size(f,3)) :: h1,h2,h3
!! local references to the metric factors to be used in the derivative
! real(wp), dimension(1:size(f,1)) :: dx1
!! local reference to the backward difference
real(wp), dimension(:,:,:), pointer :: h1
!! local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx1
!! local reference to the backward difference
lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)
!! ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
error stop '!!! Inconsistent array and mesh sizes in grad3D1 gradient function.'
!! just bail on it and let the user figure it out
end if
!CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
!INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
!Can avoid wasting memory and copying of metric factor arrays by recoding with pointers
!Unfortunately a pointer is not gauranteed to be contiguous in memory so I'm not sure this is the way to go
if (lx3<=x%lx3+4) then
h1=>x%h1(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
else if (lx3<=x%lx3all+4) then
h1=>x%h1all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
print *, '! Accessing root-only grid information'
else
error stop '!!! Array size is larger full mesh.'
end if
dx1=>x%dx1(lbnd1:ubnd1)
!! NOW EXECUTE THE FINITE DIFFERENCES -
!! NOTE THAT LOOP INDICES ARE MEANT TO INDEX ARRAY BEING DIFFERENCED AND NOT THE MESH STRUCTURE,
!! WHICH USES INPUT BOUNDS. TO KEEP THE CODE CLEAN I'VE ALIASED THE GRID VARS SO THAT THEY MAY BE ACCESSED BY LOOP INDEX.
do ix3=1,lx3
do ix2=1,lx2
grad3D1_curv_3(1,ix2,ix3) = (f(2,ix2,ix3)-f(1,ix2,ix3))/dx1(1)/h1(1,ix2,ix3)
!! fwd diff. at beginning, note that h1 is cell-centered
grad3D1_curv_3(2:lx1-1,ix2,ix3) = (f(3:lx1,ix2,ix3)-f(1:lx1-2,ix2,ix3)) &
/(dx1(3:lx1)+dx1(2:lx1-1))/h1(2:lx1-1,ix2,ix3)
!! centered diff. in the middleq
grad3D1_curv_3(lx1,ix2,ix3) = (f(lx1,ix2,ix3)-f(lx1-1,ix2,ix3))/dx1(lx1)/h1(lx1,ix2,ix3)
!! backward diff. at end
end do
end do
end procedure grad3D1_curv_3
module procedure grad3D1_curv_23
! grad3D1_curv_23(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 1-DIMENSION. IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE - EXCEPT FOR THE GRID.
!-------STRUCTURE.
!-------
!-------FOR THIS AND FOLLOWING CURV DERIVATIVE PROCEDURES THE UPPER
!-------AND LOWER BOUNDS FOR DIFFERENTIATION CANNOT BE DETERMINED
!-------WITHOUT ADDITIONAL ARGUMENTS SINCE STRUCTURE X CANNOT BE
!-------BE TRIMMED IN THE SAME WAY AS A NORMAL ARRAY. ESSENTIALLY
!-------THE INPUT ARRAY "F" AND GRID NEED TO BE INDEXED DIFFERENTLY, LEADING
!-------TO TWO SEPARATE SETS ON INDICES THROUGHOUT THIS AND SIMILAR ROUTINES.
!-------
!-------ONE ISSUE ADDRESSED HERE IS THAT THE METRIC FACTORS NEED TO KNOW
!-------WHAT PART OF THE GRID THAT THEY ARE BEING USED OVER... IE
!-------IF ANY OF THESE IS FULL GRID THEN THE HALL VERSIONS SHOUDL
!-------SHOULD BE USED FOR THE METRIC FACTORS...
!------------------------------------------------------------
integer :: ix2,ix3,lx1,lx2,lx3
! real(wp), dimension(1:size(f,1),1:size(f,2),1:size(f,3)) :: h1,h2,h3
!! local references to the metric factors to be used in the derivative
! real(wp), dimension(1:size(f,1)) :: dx1
!! local reference to the backward difference
real(wp), dimension(:,:,:), pointer :: h1
!! local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx1
!! local reference to the backward difference
lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)
!ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
error stop '!!! Inconsistent array and mesh sizes in grad3D1 gradient function.'
!! just bail on it and let the user figure it out
end if
!CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
!INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
!Can avoid wasting memory and copying of metric factor arrays by recoding with pointers
!Unfortunately a pointer is not gauranteed to be contiguous in memory so I'm not sure this is the way to go
if (lx3<=x%lx3+4) then
h1=>x%h1(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
else if (lx3<=x%lx3all+4) then
h1=>x%h1all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
print *, '! Accessing root-only grid information'
else
error stop '!!! Array size is larger full mesh.'
end if
dx1=>x%dx1(lbnd1:ubnd1)
!! NOW EXECUTE THE FINITE DIFFERENCES
!! NOTE THAT LOOP INDICES ARE MEANT TO INDEX ARRAY BEING DIFFERENCED AND NOT THE MESH STRUCTURE,
!! WHICH USES INPUT BOUNDS. TO KEEP THE CODE CLEAN I'VE ALIASED THE GRID VARS SO THAT THEY MAY BE ACCESSED BY LOOP INDEX.
do ix3=1,lx3
do ix2=1,lx2
grad3D1_curv_23(1,ix2,ix3) = (f(2,ix2,ix3)-f(1,ix2,ix3))/dx1(1)/h1(1,ix2,ix3)
!! fwd diff. at beginning, note that h1 is cell-centered
grad3D1_curv_23(2:lx1-1,ix2,ix3) = (f(3:lx1,ix2,ix3)-f(1:lx1-2,ix2,ix3)) &
/(dx1(3:lx1)+dx1(2:lx1-1))/h1(2:lx1-1,ix2,ix3)
!! centered diff. in the middleq
grad3D1_curv_23(lx1,ix2,ix3) = (f(lx1,ix2,ix3)-f(lx1-1,ix2,ix3))/dx1(lx1)/h1(lx1,ix2,ix3)
!! backward diff. at end
end do
end do
end procedure grad3D1_curv_23
module procedure grad3D2_curv_3
! grad3D2_curv_3(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 2-DIMENSION. IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE
!------------------------------------------------------------
integer :: ix1,ix3,lx1,lx2,lx3
real(wp), dimension(:,:,:), pointer :: h2 !local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx2 !local reference to the backward difference
lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)
if (lx2>1) then !if we have a singleton dimension then we are doing a 2D run and the derivatives in this direction are zero
!ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
error stop '!!! Inconsistent array and mesh sizes in gradient function.' !just bail on it and let the user figure it out
end if
!CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
!INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
if (lx3<=x%lx3+4) then
h2=>x%h2(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
else if (lx3<=x%lx3all+4) then
h2=>x%h2all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
print *, '! Accessing root-only grid information'
else
error stop '!!! Array size is larger full mesh.'
end if
dx2=>x%dx2(lbnd2:ubnd2)
!DIFFERENCING
do ix3=1,lx3
do ix1=1,lx1
grad3D2_curv_3(ix1,1,ix3)=(f(ix1,2,ix3)-f(ix1,1,ix3))/dx2(2)/h2(ix1,1,ix3)
grad3D2_curv_3(ix1,2:lx2-1,ix3)=(f(ix1,3:lx2,ix3)-f(ix1,1:lx2-2,ix3)) &
/(dx2(3:lx2)+dx2(2:lx2-1))/h2(ix1,2:lx2-1,ix3)
grad3D2_curv_3(ix1,lx2,ix3)=(f(ix1,lx2,ix3)-f(ix1,lx2-1,ix3))/dx2(lx2)/h2(ix1,lx2,lx3)
end do
end do
else
grad3D2_curv_3=0._wp
end if
end procedure grad3D2_curv_3
module procedure grad3D2_curv_23
! grad3D2_curv_23(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 2-DIMENSION. IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE
!------------------------------------------------------------
integer :: ix1,ix3,lx1,lx2,lx3
real(wp), dimension(:,:,:), pointer :: h2 !local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx2 !local reference to the backward difference
lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)
if (x%lx2>1) then !if we have a singleton dimension then we are doing a 2D run and the derivatives in this direction are zero
!ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
error stop '!!! Inconsistent array and mesh sizes in gradient function.'
!! just bail on it and let the user figure it out
end if
!CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
!INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
if (lx3<=x%lx3+4) then !this is a derivative over a slab region (subgrid)
h2=>x%h2(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
dx2=>x%dx2(lbnd2:ubnd2)
else if (lx3<=x%lx3all+4) then
!! if a larger dimension was specified for x3 then assume that we are differentiating over x2all and x3all
h2=>x%h2all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
dx2=>x%dx2all(lbnd2:ubnd2)
print *, '! Accessing root-only grid information, while taking derivative in 2-direction'
else
error stop '!!! Array size is larger full mesh.'
end if
!DIFFERENCING
do ix3=1,lx3
do ix1=1,lx1
grad3D2_curv_23(ix1,1,ix3)=(f(ix1,2,ix3)-f(ix1,1,ix3))/dx2(2)/h2(ix1,1,ix3)
grad3D2_curv_23(ix1,2:lx2-1,ix3)=(f(ix1,3:lx2,ix3)-f(ix1,1:lx2-2,ix3)) &
/(dx2(3:lx2)+dx2(2:lx2-1))/h2(ix1,2:lx2-1,ix3)
grad3D2_curv_23(ix1,lx2,ix3)=(f(ix1,lx2,ix3)-f(ix1,lx2-1,ix3))/dx2(lx2)/h2(ix1,lx2,lx3)
end do
end do
else
grad3D2_curv_23=0._wp
end if
end procedure grad3D2_curv_23
module procedure grad3D3_curv_3
! grad3D3_curv_3(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 3-DIMENSION. IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE
!-------
!-------AN EXTRA STEP IS NEEDED IN THIS ROUTINE SINCE WE HAVE
!-------TO DETERMINE WHETHER THIS IS A FULL-GRID OR SUBGRID
!-------DERIVATIVE.
!------------------------------------------------------------
integer :: ix1,ix2,lx1,lx2,lx3
real(wp), dimension(:,:,:), pointer :: h3 !local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx3 !local reference to the backward difference
lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)
!ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
error stop '!!! Inconsistent array and mesh sizes in gradient function.' !just bail on it and let the user figure it out
end if
!CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
!INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
!Can avoid wasting memory and copying of metric factor arrays by recoding with pointers
!Unfortunately a pointer is not gauranteed to be contiguous in memory so I'm not sure this is the way to go
if (lx3<=x%lx3+4) then
h3=>x%h3(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
dx3=>x%dx3(lbnd3:ubnd3)
else if (lx3<=x%lx3all+4) then
h3=>x%h3all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
dx3=>x%dx3all(lbnd3:ubnd3)
print *, '! Accessing root-only grid information'
else
error stop '!!! Array size is larger than full mesh.'
end if
!FINITE DIFFERENCING
do ix2=1,lx2
do ix1=1,lx1
grad3D3_curv_3(ix1,ix2,1)=(f(ix1,ix2,2)-f(ix1,ix2,1))/dx3(2)/h3(ix1,ix2,1)
grad3D3_curv_3(ix1,ix2,2:lx3-1)=(f(ix1,ix2,3:lx3)-f(ix1,ix2,1:lx3-2)) &
/(dx3(3:lx3)+dx3(2:lx3-1))/h3(ix1,ix2,2:lx3-1)
grad3D3_curv_3(ix1,ix2,lx3)=(f(ix1,ix2,lx3)-f(ix1,ix2,lx3-1))/dx3(lx3)/h3(ix1,ix2,lx3)
end do
end do
end procedure grad3D3_curv_3
module procedure grad3D3_curv_23
! grad3D3_curv_23(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 3-DIMENSION. IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE
!-------
!-------AN EXTRA STEP IS NEEDED IN THIS ROUTINE SINCE WE HAVE
!-------TO DETERMINE WHETHER THIS IS A FULL-GRID OR SUBGRID
!-------DERIVATIVE.
!------------------------------------------------------------
integer :: ix1,ix2,lx1,lx2,lx3
real(wp), dimension(:,:,:), pointer :: h3 !local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx3 !local reference to the backward difference
lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)
if (x%lx3>1) then !only differentiate if we have non-singleton dimension, otherwise set to zero
!ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
error stop '!!! Inconsistent array and mesh sizes in gradient function.' !just bail on it and let the user figure it out
end if
!CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
!INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
!Can avoid wasting memory and copying of metric factor arrays by recoding with pointers
!Unfortunately a pointer is not gauranteed to be contiguous in memory so I'm not sure this is the way to go
if (lx3<=x%lx3+4) then
h3=>x%h3(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
dx3=>x%dx3(lbnd3:ubnd3)
else if (lx3<=x%lx3all+4) then
h3=>x%h3all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
dx3=>x%dx3all(lbnd3:ubnd3)
print *, '! Accessing root-only grid information while differentiating in x3'
else
error stop '!!! Array size is larger than full mesh.'
end if
!FINITE DIFFERENCING
do ix2=1,lx2
do ix1=1,lx1
grad3D3_curv_23(ix1,ix2,1)=(f(ix1,ix2,2)-f(ix1,ix2,1))/dx3(2)/h3(ix1,ix2,1)
grad3D3_curv_23(ix1,ix2,2:lx3-1)=(f(ix1,ix2,3:lx3)-f(ix1,ix2,1:lx3-2)) &
/(dx3(3:lx3)+dx3(2:lx3-1))/h3(ix1,ix2,2:lx3-1)
grad3D3_curv_23(ix1,ix2,lx3)=(f(ix1,ix2,lx3)-f(ix1,ix2,lx3-1))/dx3(lx3)/h3(ix1,ix2,lx3)
end do
end do
else
grad3D3_curv_23=0._wp
end if
end procedure grad3D3_curv_23
end submodule gradient