forked from ESCOMP/CISM
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathglide_vertint.F90
164 lines (135 loc) · 5.43 KB
/
glide_vertint.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
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!
! glide_vertint.F90 - part of the Community Ice Sheet Model (CISM)
!
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!
! Copyright (C) 2005-2018
! CISM contributors - see AUTHORS file for list of contributors
!
! This file is part of CISM.
!
! CISM is free software: you can redistribute it and/or modify it
! under the terms of the Lesser GNU General Public License as published
! by the Free Software Foundation, either version 3 of the License, or
! (at your option) any later version.
!
! CISM is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! Lesser GNU General Public License for more details.
!
! You should have received a copy of the Lesser GNU General Public License
! along with CISM. If not, see <http://www.gnu.org/licenses/>.
!
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!TODO - Remove module glide_vertint? Not currently used.
module glide_vertint
!> This module contains routines to vertically integrate fields
!> All 3d fields are assumed to use the (z,x,y) coordinate system,
!> where the top is the minimum z and the bottom is the maximum z.
use glimmer_global , only: dp
implicit none
contains
!> Performs vertical integration, places the result on a 3d field
!> where each level in the 3d field is the integral of all levels
!> above it
subroutine vertint_output3d(infield, outfield, levels, topdown, initial_value)
real(dp), dimension(:,:,:), intent(in) :: infield
real(dp), dimension(:,:,:), intent(out) :: outfield
real(dp), dimension(:), intent(in) :: levels
logical :: topdown !> Controls the direction of integration. If true,
!> outfield(1,:,:) contains zeros and each level
!> below it accumulates another part of the
!> integral. If false, outfield(upn,:,:) contains
!> zeros and each level above it accumulates
!> another part of the integral
real(dp), dimension(:,:), intent(in), optional :: initial_value
integer :: upn
integer :: i
integer :: lower, upper, step !Loop control, parameterized based on
!value of topdown
real(dp) :: deltax
upn = size(levels)
if (topdown) then
lower = 2
upper = upn
step = 1
else
lower = upn-1
upper = 1
step = -1
end if
if (present(initial_value)) then
outfield(lower - step,:,:) = initial_value
else
outfield(lower - step,:,:) = 0
end if
do i = lower, upper, step
deltax = step*(levels(i) - levels(i - step))
!Apply trapezoid rule
outfield(i,:,:) = outfield(i - step,:,:) + .5 * deltax*(infield(i - step,:,:) + infield(i,:,:))
end do
end subroutine vertint_output3d
subroutine vertint_output2d(infield, outfield, levels, initial_value)
!> Vertically integrates the 3D field and places the result of the
!> integral on a 2D field
real(dp), dimension(:,:,:), intent(in) :: infield
real(dp), dimension(:,:), intent(out) :: outfield
real(dp), dimension(:), intent(in) :: levels
real(dp), dimension(:,:), intent(in), optional :: initial_value
integer :: upn
integer :: i
real(dp) :: deltax
upn = size(levels)
if (present(initial_value)) then
outfield = initial_value
else
outfield = 0
end if
do i = 2, upn
deltax = levels(i) - levels(i - 1)
outfield = outfield + .5 * deltax*(infield(i-1,:,:) + infield(i,:,:))
end do
end subroutine
!Contained unit test cases
!Based around evaluation of the integral of x^2dx from 0 to 1.
subroutine test_vertint()
real(dp), dimension(11) :: levels
real(dp), dimension(11,1,1) :: values
real(dp), dimension(1,1) :: answer
real(dp), dimension(1,1) :: ival
integer :: i
real(dp) :: val
!Test case where we have evenly spaced levels
val = 0
do i = 1,11
levels(i) = val
values(i,1,1) = val ** 2
val = val + .1
write(*,*) levels(i),values(i,1,1)
end do
ival = 0
call vertint_output2d(values, answer, levels, ival)
write(*,*) answer(1,1)
!Test case where we do not have evenly spaced levels
levels(1) = 0
levels(2) = .2
levels(3) = .4
levels(4) = .5
levels(5) = .6
levels(6) = .7
levels(7) = .8
levels(8) = .85
levels(9) = .9
levels(10) = .95
levels(11) = 1
do i = 1,11
values(i,1,1) = levels(i) ** 2
write(*,*) levels(i),values(i,1,1)
end do
ival = 0
call vertint_output2d(values, answer, levels, ival)
write(*,*) answer(1,1)
end subroutine
end module glide_vertint