-
Notifications
You must be signed in to change notification settings - Fork 0
/
NASATileFile.F90
276 lines (215 loc) · 10.1 KB
/
NASATileFile.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
!==============================================================================
! Earth System Modeling Framework
! Copyright 2002-2019, University Corporation for Atmospheric Research,
! Massachusetts Institute of Technology, Geophysical Fluid Dynamics
! Laboratory, University of Michigan, National Centers for Environmental
! Prediction, Los Alamos National Laboratory, Argonne National Laboratory,
! NASA Goddard Space Flight Center.
! Licensed under the University of Illinois-NCSA License.
!==============================================================================
! This is a module that provides some basic functionality for doing things
! with ESMF and the NASA tile file
module NASATileFile
use ESMF
use NetCDF
implicit none
#define NTF_SRCLINE __FILE__,__LINE__
#define NTF_CONTEXT file=__FILE__,line=__LINE__
#define NTF_PASSTHRU msg="Internal subroutine call returned Error"
! Public interfaces available from this module
public NTF_Write
! Make things private, except that which is explicitly make public
private
!-----------------------------------------------------------------------------
contains
!-----------------------------------------------------------------------------
! Given an ESMF XGrid output a NASA tile file
subroutine NTF_Write(xgrid, fileName, rc)
#undef NTF_METHOD
#define NTF_METHOD "NTF_Write()"
!
! !ARGUMENTS:
type(ESMF_XGrid), intent(in) :: xgrid
character (len=*), intent(in) :: fileName
integer, intent(out), optional :: rc
! Local variables
integer, parameter :: unitNum=14
integer :: localrc
type(ESMF_Field) :: sideBIndField
type(ESMF_Field) :: areaField
type(ESMF_Field) :: centroidLonField, centroidLatField
type(ESMF_Array) :: sideBIndArray
integer, pointer :: sideBIndPtr(:)
real(ESMF_KIND_R8), pointer :: areaPtr(:)
integer :: i, clbnd(1), cubnd(1)
integer :: lDE, localDECount
type(ESMF_VM) :: vm
integer :: localPet
real(ESMF_KIND_R8), pointer :: centroidLonPtr(:) , centroidLatPtr(:)
integer :: numElements
! Get VM
call ESMF_VMGetCurrent(vm, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Get VM info
call ESMF_VMGet(vm, localPet=localPet, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Create a Field to hold sideBInd on the Xgrid
sideBIndField=ESMF_FieldCreate(xgrid, typekind=ESMF_TYPEKIND_I4, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Get Array
call ESMF_FieldGet(sideBIndField, array=sideBIndArray, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Get Info from XGrid
call ESMF_XGridGet(xgrid, &
sideBGeomIndArray=sideBIndArray, &
rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Create a Field to hold Area on the Xgrid
areaField=ESMF_FieldCreate(xgrid, typekind=ESMF_TYPEKIND_R8, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Get area
call ESMF_FieldRegridGetArea(areaField, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Create Fields to hold centroid coordinates
centroidLonField=ESMF_FieldCreate(xgrid, typekind=ESMF_TYPEKIND_R8, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
centroidLatField=ESMF_FieldCreate(xgrid, typekind=ESMF_TYPEKIND_R8, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Get coordinates for XGrid centroids
call getCentroidIntoFields(xgrid, centroidlonField, centroidLatField, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Get localDECount
call ESMF_FieldGet(sideBIndField, localDECount=localDECount, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Open file
open(unit=unitNum, file=fileName)
! Loop over Field
do lDE=0,localDECount-1
! Get tile type
call ESMF_FieldGet(sideBIndField, lDE, &
farrayPtr=sideBIndPtr, computationalLBound=clbnd, computationalUBound=cubnd, &
rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Get area
call ESMF_FieldGet(areaField, lDE, farrayPtr=areaPtr, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Get centroid
call ESMF_FieldGet(centroidLonField, lDE, farrayPtr=centroidLonPtr, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
call ESMF_FieldGet(centroidLatField, lDE, farrayPtr=centroidLatPtr, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Loop writing data to file
do i=clbnd(1), cubnd(1)
! Write cell types
if (sideBIndPtr(i) == 1) then
! Write land type
! TODO: need to add lake and landice when we have them coming out
write(unitNum,'(i)',advance="no") 100
else if (sideBIndPtr(i) == 2) then
! Write ocean type
write(unitNum,'(i)',advance="no") 0
endif
! Write cell area
write(unitNum,'(f)',advance="no") areaPtr(i)
! Write centroids
write(unitNum,'(f f)',advance="no") centroidLonPtr(i), centroidLatPtr(i)
! TODO: fill in second set of info specifc to grid types
if (sideBIndPtr(i) == 1) then
! Write land info
else if (sideBIndPtr(i) == 2) then
! Write ocean info
endif
! End line
write(unitNum,'(A)',advance="yes") " "
enddo
enddo
! Close file
close(unit=unitNum)
! Destroy tmp Fields
call ESMF_FieldDestroy(sideBIndField, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
call ESMF_FieldDestroy(areaField, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
call ESMF_FieldDestroy(centroidLonField, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
call ESMF_FieldDestroy(centroidLatField, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Return successfully
if (present(rc)) rc = ESMF_SUCCESS
end subroutine NTF_Write
! Get centroids into Fields
! Right now this is just a wrapper to go from XGrids output of a fortran array to
! to an ESMF Field, eventually I'm going to add an option to get ESMF Fields/Arrays
! directly out of XGridGet, so this will go away.
! Putting these into Fields (vs just a Fotran array) is
! future proofing to allow to to redist, etc. as necessary to output in parallel.
! Also, I think that it gives a more consistent view of the data to have it all
! in Fields on the XGrid DistGrid.
subroutine getCentroidIntoFields(xgrid, centroidlonField, centroidLatField, rc)
type(ESMF_XGrid), intent(in) :: xgrid
type(ESMF_Field), intent(inout) :: centroidLonField
type(ESMF_Field), intent(inout) :: centroidLatField
integer, intent(out), optional :: rc
real(ESMF_KIND_R8), allocatable :: centroids(:,:)
real(ESMF_KIND_R8), pointer :: lonPtr(:)
real(ESMF_KIND_R8), pointer :: latPtr(:)
integer :: i, clbnd(1), cubnd(1)
integer :: lDE, localDECount
integer :: localrc
integer :: dimCount, elementCount
integer :: pos
! Get localDECount
call ESMF_FieldGet(centroidLonField, localDECount=localDECount, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Get element info
call ESMF_XGridGet(xgrid, elementCount=elementCount, dimCount=dimCount, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Allocate space for centroids
allocate(centroids(elementCount,dimCount))
! Get centroids
call ESMF_XGridGet(xgrid, centroid=centroids, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Loop over Field putting centroids into Field
pos=1
do lDE=0,localDECount-1
! Get Lon pointer
call ESMF_FieldGet(centroidLonField, localDE=lDE, &
farrayPtr=lonPtr, computationalLBound=clbnd, computationalUBound=cubnd, &
rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Get Lat pointere
call ESMF_FieldGet(centroidLatField, localDE=lDE, farrayPtr=latPtr, rc=localrc)
if (ESMF_LogFoundError(localrc, NTF_PASSTHRU, &
NTF_CONTEXT, rcToReturn=rc)) return
! Loop copying coords to Fields
do i=clbnd(1), cubnd(1)
lonPtr(i)=centroids(pos,1)
latPtr(i)=centroids(pos,2)
pos=pos+1
enddo
enddo
end subroutine getCentroidIntoFields
end module