3 !----------------------------------------------------------------------
4 ! Purpose : add updated ensemble mean and perturbations to get analysis
6 ! Arthur P. Mizzi (NCAR/MMM) April 2011
8 !----------------------------------------------------------------------
9 ! xlf90 -C -I${NETCDF}/include -L${NETCDF}/lib -lnetcdf -lnetcdff -o da_run_add_mean.exe da_run_add_mean.f90
15 integer, parameter :: max_num_vars
= 50 ! Maximum number of variables.
16 integer, parameter :: max_num_dims
= 20 ! Maximum number of dimensions.
17 integer, parameter :: unit
= 100 ! Unit number.
19 integer :: num_members
! Ensemble size.
20 integer :: nv
! Number of variables.
21 integer :: length
! Filename length.
22 integer :: rcode
! NETCDF return code.
23 integer :: cdfid_mean
, cdfid_pert
! NETCDF file IDs.
24 integer :: nijkv
, nijkv_mean
, nijkv_pert
! Array counter.
25 integer :: index
! Array index.
26 integer :: member
, v
, o
, i
, j
, k
, ijkv
! Loop counters.
27 integer :: ivtype
! 4=integer, 5=real, 6=d.p.
28 integer :: natts
! Number of field attributes.
29 integer :: istart_mean(1:max_num_vars
) ! Start index.
30 integer :: istart_pert(1:max_num_vars
) ! Start index.
31 integer :: id_var_mean(1:max_num_vars
) ! NETCDF variable ID.
32 integer :: id_var_pert(1:max_num_vars
) ! NETCDF variable ID.
33 integer :: ndims_mean(1:max_num_vars
) ! Number of field dimensions.
34 integer :: ndims_pert(1:max_num_vars
) ! Number of field dimensions.
35 integer :: one(1:max_num_dims
) ! Array of dimension starts.
36 integer :: dimids_mean(1:max_num_dims
) ! Array of dimension IDs.
37 integer :: dimids_pert(1:max_num_dims
) ! Array of dimension IDs.
38 integer :: dims_mean(1:max_num_vars
,1:max_num_dims
) ! Array of dimensions.
39 integer :: dims_pert(1:max_num_vars
,1:max_num_dims
) ! Array of dimensions.
41 real (kind
=4), allocatable
:: data_r_3d(:,:,:) ! 3-D Data array.
42 real (kind
=4), allocatable
:: data_r_4d(:,:,:,:) ! 4-D Data array.
43 real, allocatable
:: xf_mean(:) ! Ensemble mean.
44 real, allocatable
:: xf_pert(:) ! Ensemble perturbations.
46 character (len
=3) :: ce
! Member index -> character.
47 character (len
=10) :: cv(1:max_num_vars
) ! Default array of variable names.
48 character (len
=160) :: path
! Input file path.
49 character (len
=160) :: file_mean
! Input file_mean name.
50 character (len
=160) :: file_pert
! Input file_pert name.
51 character (len
=160) :: input_file_mean
! Input file.
52 character (len
=160) :: input_file_pert
! Input file.
54 namelist / add_mean_nl
/ num_members
, nv
, cv
, path
, file_mean
, file_pert
56 ! OPEN AND READ NAMELIST DATA
57 open(unit
=unit
, file
='add_mean_nl.nl', &
58 form
='formatted', status
='old', action
='read')
59 read(unit
, add_mean_nl
)
62 print *, 'NUM_MEMBERS ', num_members
64 print *, 'CV ', (trim(cv(i
)),i
=1,nv
)
65 print *, 'PATH ', trim(path
)
66 print *, 'FILE_MEAN ', trim(file_mean
)
67 print *, 'FILE_PERT ', trim(file_pert
)
69 ! OPEN THE ENSEMBLE MEAN FILE
70 input_file_mean
= trim(path
)//'/'//trim(file_mean
)
71 ! print *, 'INPUT_FILE_MEAN', trim(input_file_mean)
72 length
= len_trim(input_file_mean
)
73 rcode
= nf_open( input_file_mean(1:length
), NF_WRITE
, cdfid_mean
)
75 ! OPEN THE ENSEMBLE PERT FILE
76 input_file_pert
= trim(path
)//'/'//trim(file_pert
)
77 ! print *, 'INPUT_FILE_PERT', trim(input_file_pert)
78 length
= len_trim(input_file_pert
)
79 rcode
= nf_open( input_file_pert(1:length
), NF_WRITE
, cdfid_pert
)
81 ! LOOP OVER VARIABLES (v) TO GET DIMENSIONS
84 ! GET VARIABLE IDENTIFIER
85 rcode
= nf_inq_varid ( cdfid_mean
, cv(v
), id_var_mean(v
) )
86 if ( rcode
/= 0 ) then
87 write(UNIT
=6,FMT
='(A,A)') &
88 cv(v
), ' variable is not in input file mean'
91 rcode
= nf_inq_varid ( cdfid_pert
, cv(v
), id_var_pert(v
) )
92 if ( rcode
/= 0 ) then
93 write(UNIT
=6,FMT
='(A,A)') &
94 cv(v
), ' variable is not in input file pert'
97 if (id_var_mean(v
) .ne
. id_var_pert(v
)) then
98 print *, 'mean var id not equal pert var id ',v
,id_var_mean(v
),id_var_pert(v
)
102 ! CHECK IF VARIABLE IS TYPE REAL
104 rcode
= nf_inq_var( cdfid_mean
, id_var_mean(v
), cv(v
), ivtype
, ndims_mean(v
), dimids_mean
, natts
)
105 if ( ivtype
/= 5 ) then
106 write(UNIT
=6,FMT
='(A,A)') cv(v
), ' variable is not real type in file_mean'
110 rcode
= nf_inq_var( cdfid_pert
, id_var_pert(v
), cv(v
), ivtype
, ndims_pert(v
), dimids_pert
, natts
)
111 if ( ivtype
/= 5 ) then
112 write(UNIT
=6,FMT
='(A,A)') cv(v
), ' variable is not real type in file_pert'
116 ! GET DIMENSIONS FOR THIS VARIABLE
118 do i
= 1, ndims_mean(v
)
119 rcode
= nf_inq_dimlen( cdfid_mean
, dimids_mean(i
), dims_mean(v
,i
) )
122 do i
= 1, ndims_pert(v
)
123 rcode
= nf_inq_dimlen( cdfid_pert
, dimids_pert(i
), dims_pert(v
,i
) )
127 ! SET COLUMN VECTOR INDEXING ARRAY
131 istart_mean(v
) = istart_mean(v
-1) + product(dims_mean(v
-1,1:ndims_mean(v
-1)-1))
136 istart_pert(v
) = istart_pert(v
-1) + product(dims_pert(v
-1,1:ndims_pert(v
-1)-1))
139 ! CALCULATE SIZE OF COLUMN VECTOR AND ALLOCATE ARRAY
140 nijkv_mean
= istart_mean(nv
) + product(dims_mean(nv
,1:ndims_mean(nv
)-1)) - 1
141 nijkv_pert
= istart_pert(nv
) + product(dims_pert(nv
,1:ndims_pert(nv
)-1)) - 1
143 if(nijkv_mean
.ne
. nijkv_pert
) then
144 print *, 'nijkv_mean not equal nijkv_pert ',nijkv_mean
, nijkv_pert
148 allocate(xf_mean(1:nijkv
))
149 allocate(xf_pert(1:nijkv
))
151 ! LOOP OVER VARIABLES TO BE UPDATED
153 print *, 'process variable ',v
155 ! GET MEAN FIELD VARIABLE IDENTIFIER
156 rcode
= nf_inq_varid ( cdfid_mean
, cv(v
), id_var_mean(v
) )
157 if ( rcode
/= 0 ) then
158 write(UNIT
=6,FMT
='(A,A)') &
159 cv(v
), ' variable is not in input file mean'
162 ! print *, 'save mean field'
163 index
= istart_mean(v
)
164 if(ndims_mean(v
) == 3) then
165 allocate( data_r_3d(dims_mean(v
,1),dims_mean(v
,2),dims_mean(v
,3)))
166 rcode
= nf_get_vara_real( cdfid_mean
, id_var_mean(v
), one
, dims_mean(v
,:), data_r_3d
)
168 print *, 'Error read ',trim(input_file_mean
),' variable ',cv(v
)
169 print *, 'rcode ',rcode
172 do k
= 1, dims_mean(v
,3)
173 do j
= 1, dims_mean(v
,2)
174 do i
= 1, dims_mean(v
,1)
175 xf_mean(index
) = data_r_3d(i
,j
,k
)
180 deallocate( data_r_3d
)
182 if(ndims_mean(v
) == 4) then
183 allocate( data_r_4d(dims_mean(v
,1),dims_mean(v
,2),dims_mean(v
,3),dims_mean(v
,4)))
184 rcode
= nf_get_vara_real( cdfid_mean
, id_var_mean(v
), one
, dims_mean(v
,:), data_r_4d
)
186 print *, 'Error read ',trim(input_file_mean
),' variable ',cv(v
)
187 print *, 'rcode ',rcode
190 do k
= 1, dims_mean(v
,3)
191 do j
= 1, dims_mean(v
,2)
192 do i
= 1, dims_mean(v
,1)
193 xf_mean(index
) = data_r_4d(i
,j
,k
,1)
198 deallocate( data_r_4d
)
201 ! GET PERT FIELD VARIABLE IDENTIFIER
202 rcode
= nf_inq_varid ( cdfid_pert
, cv(v
), id_var_pert(v
) )
203 if ( rcode
/= 0 ) then
204 write(UNIT
=6,FMT
='(A,A)') &
205 cv(v
), ' variable is not in input file pert'
208 ! print *, 'save pert field'
209 index
= istart_pert(v
)
210 if(ndims_pert(v
) == 3) then
211 allocate( data_r_3d(dims_pert(v
,1),dims_pert(v
,2),dims_pert(v
,3)))
212 rcode
= nf_get_vara_real( cdfid_pert
, id_var_pert(v
), one
, dims_pert(v
,:), data_r_3d
)
214 print *, 'Error read ',trim(input_file_pert
),' variable ',cv(v
)
215 print *, 'rcode ',rcode
218 do k
= 1, dims_pert(v
,3)
219 do j
= 1, dims_pert(v
,2)
220 do i
= 1, dims_pert(v
,1)
221 xf_pert(index
) = data_r_3d(i
,j
,k
)
226 deallocate( data_r_3d
)
228 if(ndims_pert(v
) == 4) then
229 allocate( data_r_4d(dims_pert(v
,1),dims_pert(v
,2),dims_pert(v
,3),dims_pert(v
,4)))
230 rcode
= nf_get_vara_real( cdfid_pert
, id_var_pert(v
), one
, dims_pert(v
,:), data_r_4d
)
232 print *, 'Error read ',trim(input_file_pert
),' variable ',cv(v
)
233 print *, 'rcode ',rcode
236 do k
= 1, dims_pert(v
,3)
237 do j
= 1, dims_pert(v
,2)
238 do i
= 1, dims_pert(v
,1)
239 xf_pert(index
) = data_r_4d(i
,j
,k
,1)
244 deallocate( data_r_4d
)
247 ! ADD THE MEAN AND PERT FIELDS
248 ! print *, 'add mean and pert'
250 xf_pert(ijkv
) = xf_mean(ijkv
) + xf_pert(ijkv
)
253 ! WRITE UPDATED FIELD TO FILE_PERT
254 ! print *, 'write total field'
255 index
= istart_pert(v
)
256 if(ndims_pert(v
) == 3) then
257 allocate( data_r_3d(dims_pert(v
,1),dims_pert(v
,2),dims_pert(v
,3)))
258 do k
= 1, dims_pert(v
,3)
259 do j
= 1, dims_pert(v
,2)
260 do i
= 1, dims_pert(v
,1)
261 data_r_3d(i
,j
,k
) = xf_pert(index
)
266 call ncvpt( cdfid_pert
, id_var_pert(v
), one
, dims_pert(v
,:), data_r_3d
, rcode
)
267 deallocate( data_r_3d
)
269 if(ndims_pert(v
) == 4) then
270 allocate( data_r_4d(dims_pert(v
,1),dims_pert(v
,2),dims_pert(v
,3),dims_pert(v
,4)))
271 do k
= 1, dims_pert(v
,3)
272 do j
= 1, dims_pert(v
,2)
273 do i
= 1, dims_pert(v
,1)
274 data_r_4d(i
,j
,k
,1) = xf_pert(index
)
279 call ncvpt( cdfid_pert
, id_var_pert(v
), one
, dims_pert(v
,:), data_r_4d
, rcode
)
280 deallocate( data_r_4d
)
283 rcode
= nf_close( cdfid_mean
)
284 rcode
= nf_close( cdfid_pert
)
287 end program gen_be_addmean