2 ! WRFVAR generic type macro file
4 ! This file is used to generate a series of simple boiler-plate calls
5 ! to support residual generic types for bitwise-exact testing.
6 ! It contains M4 macros and then
7 ! a series of invocations of the macros to generate the subroutine
8 ! definitions, which are then included in another source file.
11 ! $1 = specific ob name, $2 = specific ob type, $3 = ob counter
14 define( macro_y_type_extract,
17 SUBROUTINE da_y_type_ex_$1( iv, re, slice )
19 !------------------------------------------------------------------------------
20 ! PURPOSE: Eliminate redundant code for many obs types.
22 ! METHOD: Extract all $1 obs from y and place them in generic
24 ! Call da_y_facade_free() to deallocate memory allocated here.
25 !------------------------------------------------------------------------------
28 type (iv_type), INTENT(IN ) :: iv ! Innovation vector
29 type (y_type), INTENT(IN ) :: re ! all residual obs
30 type (y_facade_type), INTENT(INOUT) :: slice ! selected residual obs
34 CALL da_y_facade_create( slice, iv%info($1)%nlocal, iv%info($1)%ntotal )
37 ! CALL da_res_generic_set_info( slice%obs(n), &
38 ! iv%$1(n)%loc%proc_domain, &
39 ! iv%$1(n)%loc%obs_global_index )
40 ! CALL da_res_$2_to_generic( re%$1(n), iv%$1(n)%info%levels, &
44 END SUBROUTINE da_y_type_ex_$1 ' )
49 define( macro_y_type_insert_global,
52 SUBROUTINE da_y_type_ins_$1_global( slice_glob, re_glob )
54 !------------------------------------------------------------------------------
55 ! PURPOSE: Eliminate redundant code for many obs types.
57 ! METHOD: Insert obs from generic object slice_glob into
58 ! globally-scoped y_type re_glob. re_glob is
59 ! allocated minimally. Caller must deallocate.
60 ! Memory for global object slice_glob is deallocated here.
61 ! Do not use slice_glob after this call.
62 !------------------------------------------------------------------------------
65 type (y_facade_type), INTENT(INOUT) :: slice_glob ! generic
66 type (y_type), INTENT(INOUT) :: re_glob ! selected residual obs
70 ! allocate and initialize obs
71 ! deallocation is done in free_global_$1()
72 ALLOCATE( re_glob%$1(slice_glob%num_obs) )
73 DO n=1, slice_glob%num_obs
74 CALL da_res_$2_from_generic( slice_glob%obs(n), re_glob%$1(n) )
76 re_glob%nlocal($1) = slice_glob%num_obs ! duplication!
77 CALL da_y_facade_free( slice_glob )
79 END SUBROUTINE da_y_type_ins_$1_global ')
84 define( macro_iv_type_insert_global,
87 SUBROUTINE da_iv_type_ins_$1_global( slice_glob, iv_glob )
89 !------------------------------------------------------------------------------
90 ! PURPOSE: Eliminate redundant code for many obs types.
92 ! METHOD: Insert meta-data from generic object slice_glob into
93 ! globally-scoped iv_type iv_glob. iv_glob is
94 ! allocated minimally. Caller must deallocate.
95 !------------------------------------------------------------------------------
98 type (y_facade_type), INTENT(IN ) :: slice_glob ! selected residual obs
99 type (iv_type), INTENT(INOUT) :: iv_glob ! partial Innovation vector
103 ! allocate and initialize needed bits of iv_glob (ugly)
104 iv_glob%info($1)%nlocal = slice_glob%num_obs
105 iv_glob%info($1)%ntotal = slice_glob%num_obs_glo
106 ! deallocation is done in free_global_$1()
107 ALLOCATE( iv_glob%$1(iv_glob%info($1)%nlocal) )
108 DO n=1, iv_glob%info($1)%nlocal
110 ! iv_glob%$1(n)%loc%proc_domain = slice_glob%obs(n)%proc_domain
111 ! iv_glob%$1(n)%loc%obs_global_index = &
112 ! slice_glob%obs(n)%obs_global_index
113 ! IF ( da_res_generic_has_vector( slice_glob%obs(n) ) ) THEN
114 ! iv_glob%$1(n)%info%levels = SIZE(slice_glob%obs(n)%values(1)%ptr)
118 END SUBROUTINE da_iv_type_ins_$1_global ' )
121 define( macro_to_global,
124 !------------------------------------------------------------------------------
125 ! PURPOSE: Collect local arrays of residual_$2_type objects into
126 ! global arrays in serial-code storage order. This is used to
127 ! perform bitwise-exact floating-point summations in
128 ! serial-code-order during bitwise-exact testing of
129 ! distributed-memory parallel configurations.
131 ! METHOD: Indices stowed away during Read_Obs() are used to restore serial
132 ! storage order. Memory for global objects is allocated here.
133 ! Global objects are minimally allocated to save memory.
134 ! Memory is deallocated in free_global_$1().
135 !------------------------------------------------------------------------------
136 SUBROUTINE da_to_global_$1( iv, re, jo_grad_y, &
137 iv_glob, re_glob, jo_grad_y_glob )
142 type (iv_type), INTENT( IN) :: iv ! Innovation vector
143 type (y_type), INTENT( IN) :: re ! residual vector
144 type (y_type), INTENT( IN) :: jo_grad_y ! Grad_y(Jo)
145 ! task-global objects
146 type (iv_type), INTENT(OUT) :: iv_glob ! Innovation vector
147 type (y_type), INTENT(OUT) :: re_glob ! residual vector
148 type (y_type), INTENT(OUT) :: jo_grad_y_glob ! Grad_y(Jo)
151 type (y_facade_type) :: re_slice, re_glob_slice
152 type (y_facade_type) :: jo_grad_y_slice, jo_grad_y_glob_slice
153 type (residual_template_type) :: template ! allocation info
155 ! create process-local generic objects from specific objects
156 CALL da_y_type_ex_$1( iv, re, re_slice )
157 CALL da_y_type_ex_$1( iv, jo_grad_y, jo_grad_y_slice )
159 ! create global versions of generic objects from process-local objects
160 ! and destroy process-local generic objects
161 CALL da_res_$2_create_template( template ) ! use template in case
162 ! some tasks have no obs
163 CALL da_y_facade_to_global( re_slice, template, re_glob_slice )
164 CALL da_y_facade_to_global( jo_grad_y_slice, template, jo_grad_y_glob_slice )
166 ! create global versions of specific objects
167 ! and destroy global versions of generic objects
169 CALL da_iv_type_ins_$1_global( re_glob_slice, iv_glob )
171 CALL da_y_type_ins_$1_global( re_glob_slice, re_glob )
172 CALL da_y_type_ins_$1_global( jo_grad_y_glob_slice, jo_grad_y_glob )
173 ! global versions of specific objects are destroyed in
178 END SUBROUTINE da_to_global_$1 ' )
182 macro_y_type_extract(sound,sound,num_sound)
185 macro_y_type_insert_global(sound,sound,num_sound)
188 macro_iv_type_insert_global(sound,sound,num_sound)
191 macro_to_global(sound,sound,num_sound)
194 macro_y_type_extract(sonde_sfc,synop,num_sound)
197 macro_y_type_insert_global(sonde_sfc,synop,num_sound)
200 macro_iv_type_insert_global(sonde_sfc,synop,num_sound)
203 macro_to_global(sonde_sfc,synop,num_sound)
206 macro_y_type_extract(synop,synop,num_synop)
209 macro_y_type_insert_global(synop,synop,num_synop)
212 macro_iv_type_insert_global(synop,synop,num_synop)
215 macro_to_global(synop,synop,num_synop)