FV3 Bundle
NLTECoeff_Define.f90
Go to the documentation of this file.
1 !
2 ! NLTECoeff_Define
3 !
4 ! Module defining the NLTECoeff structure and containing routines to
5 ! manipulate it.
6 !
7 !
8 ! CREATION HISTORY:
9 ! Written by: Yong Han, 08-05-2010
10 ! yong.han@noaa.gov
11 !
12 ! Refactored by: Paul van Delst, 19-Jan-2011
13 ! paul.vandelst@noaa.gov
14 !
15 
17 
18  ! -----------------
19  ! Environment setup
20  ! -----------------
21  ! Module use
22  USE type_kinds, ONLY: long, double
24  USE compare_float_numbers, ONLY: OPERATOR(.equalto.)
25  USE subset_define , ONLY: subset_type , &
27  subset_getvalue , &
31  ! Disable implicit typing
32  IMPLICIT NONE
33 
34 
35  ! ------------
36  ! Visibilities
37  ! ------------
38  ! Everything private by default
39  PRIVATE
40  ! Datatypes
41  PUBLIC :: nltecoeff_type
42  ! Operators
43  PUBLIC :: OPERATOR(==)
44  ! Procedures
45  PUBLIC :: nltecoeff_associated
46  PUBLIC :: nltecoeff_destroy
47  PUBLIC :: nltecoeff_create
48  PUBLIC :: nltecoeff_inspect
49  PUBLIC :: nltecoeff_validrelease
50  PUBLIC :: nltecoeff_info
51  PUBLIC :: nltecoeff_defineversion
52  PUBLIC :: nltecoeff_subset
53  PUBLIC :: nltecoeff_concat
54  PUBLIC :: nltecoeff_channelreindex
55 
56 
57  ! ---------------------
58  ! Procedure overloading
59  ! ---------------------
60  INTERFACE OPERATOR(==)
61  MODULE PROCEDURE nltecoeff_equal
62  END INTERFACE OPERATOR(==)
63 
64 
65  ! -----------------
66  ! Module parameters
67  ! -----------------
68  ! Version Id for the module
69  CHARACTER(*), PARAMETER :: module_version_id = &
70  '$Id: NLTECoeff_Define.f90 60152 2015-08-13 19:19:13Z paul.vandelst@noaa.gov $'
71  ! Literal constants
72  REAL(Double), PARAMETER :: zero = 0.0_double
73  REAL(Double), PARAMETER :: one = 1.0_double
74  ! Default message string length
75  INTEGER, PARAMETER :: ml = 512
76  ! Sensor id string length
77  INTEGER, PARAMETER :: sl = 20
78  ! Current valid release and version numbers
79  INTEGER, PARAMETER :: nltecoeff_release = 2 ! This determines structure and file formats.
80  INTEGER, PARAMETER :: nltecoeff_version = 1 ! This is just the data version.
81  ! Number of layers for which mean temperatures are computed
82  INTEGER, PARAMETER :: n_layers = 2
83  ! Integer flags corresponding to logical false/true
84  INTEGER, PARAMETER :: false = 0
85  INTEGER, PARAMETER :: true = 1
86 
87 
88  ! -----------------------
89  ! Derived type definition
90  ! -----------------------
92  ! Allocation indicator
93  LOGICAL :: is_allocated = .false.
94  ! Release and version information
95  INTEGER(Long) :: release = nltecoeff_release
96  INTEGER(Long) :: version = nltecoeff_version
97  ! Dimensions
98  INTEGER(Long) :: n_predictors = 0 ! n1 dimension
99  INTEGER(Long) :: n_sensor_angles = 0 ! n2 dimension
100  INTEGER(Long) :: n_solar_angles = 0 ! n3 dimension
101  INTEGER(Long) :: n_nlte_channels = 0 ! n4 dimension
102  INTEGER(Long) :: n_channels = 0 ! n5 dimension
103  ! ..."Internal" dimension
104  INTEGER(Long) :: n_layers = n_layers
105  ! Sensor info
106  CHARACTER(SL) :: sensor_id = ''
107  INTEGER(Long) :: wmo_satellite_id = invalid_wmo_satellite_id
108  INTEGER(Long) :: wmo_sensor_id = invalid_wmo_sensor_id
109  INTEGER(Long), ALLOCATABLE :: sensor_channel(:) ! n5
110  ! Pressure levels used for computing mean temperatures in the two layers
111  REAL(Double) :: upper_plevel(n_layers) = zero
112  REAL(Double) :: lower_plevel(n_layers) = zero
113  ! Min., max. and mean layer temperatures used as the temperature predictor limits
114  REAL(Double) :: min_tm(n_layers) = zero
115  REAL(Double) :: max_tm(n_layers) = zero
116  REAL(Double) :: mean_tm(n_layers) = zero
117  ! Coefficient table dimension vectors
118  REAL(Double) , ALLOCATABLE :: secant_sensor_zenith(:) ! n2
119  REAL(Double) , ALLOCATABLE :: secant_solar_zenith(:) ! n3
120  INTEGER(Long), ALLOCATABLE :: nlte_channel(:) ! n4
121  LOGICAL , ALLOCATABLE :: is_nlte_channel(:) ! n5
122  ! Coefficients for NLTE corrections
123  INTEGER(Long), ALLOCATABLE :: c_index(:) ! n5
124  REAL(Double) , ALLOCATABLE :: c(:,:,:,:) ! n1 x n2 x n3 x n4
125  END TYPE nltecoeff_type
126 
127 CONTAINS
128 
129 
130 !################################################################################
131 !################################################################################
132 !## ##
133 !## ## PUBLIC MODULE ROUTINES ## ##
134 !## ##
135 !################################################################################
136 !################################################################################
137 
138 !--------------------------------------------------------------------------------
139 !:sdoc+:
140 !
141 ! NAME:
142 ! NLTECoeff_Associated
143 !
144 ! PURPOSE:
145 ! Elemental function to test the status of the allocatable components
146 ! of the NLTECoeff structure.
147 !
148 ! CALLING SEQUENCE:
149 ! Status = NLTECoeff_Associated( NLTECoeff )
150 !
151 ! OBJECTS:
152 ! NLTECoeff: Structure which is to have its member's
153 ! status tested.
154 ! UNITS: N/A
155 ! TYPE: NLTECoeff_type
156 ! DIMENSION: Scalar or any rank
157 ! ATTRIBUTES: INTENT(IN)
158 !
159 ! FUNCTION RESULT:
160 ! Status: The return value is a logical value indicating the
161 ! status of the NLTE members.
162 ! .TRUE. - if ANY of the NLTECoeff allocatable members
163 ! are in use.
164 ! .FALSE. - if ALL of the NLTECoeff allocatable members
165 ! are not in use.
166 ! UNITS: N/A
167 ! TYPE: LOGICAL
168 ! DIMENSION: Same as input
169 !
170 !:sdoc-:
171 !--------------------------------------------------------------------------------
172 
173  ELEMENTAL FUNCTION nltecoeff_associated( NLTECoeff ) RESULT( Status )
174  TYPE(nltecoeff_type), INTENT(IN) :: nltecoeff
175  LOGICAL :: status
176  status = nltecoeff%Is_Allocated
177  END FUNCTION nltecoeff_associated
178 
179 
180 !--------------------------------------------------------------------------------
181 !:sdoc+:
182 !
183 ! NAME:
184 ! NLTECoeff_Destroy
185 !
186 ! PURPOSE:
187 ! Elemental subroutine to re-initialize NLTECoeff objects.
188 !
189 ! CALLING SEQUENCE:
190 ! CALL NLTECoeff_Destroy( NLTECoeff )
191 !
192 ! OBJECTS:
193 ! NLTECoeff: Re-initialized NLTECoeff structure.
194 ! UNITS: N/A
195 ! TYPE: NLTECoeff_type
196 ! DIMENSION: Scalar or any rank
197 ! ATTRIBUTES: INTENT(OUT)
198 !
199 !:sdoc-:
200 !--------------------------------------------------------------------------------
201 
202  ELEMENTAL SUBROUTINE nltecoeff_destroy( NLTECoeff )
203  TYPE(nltecoeff_type), INTENT(OUT) :: nltecoeff
204  nltecoeff%Is_Allocated = .false.
205  nltecoeff%n_Predictors = 0
206  nltecoeff%n_Sensor_Angles = 0
207  nltecoeff%n_Solar_Angles = 0
208  nltecoeff%n_NLTE_Channels = 0
209  nltecoeff%n_Channels = 0
210  nltecoeff%Sensor_Id = ''
211  nltecoeff%WMO_Satellite_ID = invalid_wmo_satellite_id
212  nltecoeff%WMO_Sensor_ID = invalid_wmo_sensor_id
213  END SUBROUTINE nltecoeff_destroy
214 
215 
216 !--------------------------------------------------------------------------------
217 !:sdoc+:
218 !
219 ! NAME:
220 ! NLTECoeff_Create
221 !
222 ! PURPOSE:
223 ! Elemental subroutine to create an instance of an NLTECoeff object.
224 !
225 ! CALLING SEQUENCE:
226 ! CALL NLTECoeff_Create( NLTECoeff , &
227 ! n_Predictors , &
228 ! n_Sensor_Angles , &
229 ! n_Solar_Angles , &
230 ! n_NLTE_Channels , &
231 ! n_Channels )
232 !
233 ! OBJECTS:
234 ! NLTECoeff: NLTECoeff object structure.
235 ! UNITS: N/A
236 ! TYPE: NLTECoeff_type
237 ! DIMENSION: Scalar or any rank
238 ! ATTRIBUTES: INTENT(OUT)
239 !
240 ! INPUTS:
241 ! n_Predictors: Number of predictors used in NLTE correction algorithm.
242 ! Must be > 0.
243 ! UNITS: N/A
244 ! TYPE: INTEGER
245 ! DIMENSION: Same as the NLTECoeff object
246 ! ATTRIBUTES: INTENT(IN)
247 !
248 ! n_Sensor_Angles: Number of sensor zenith angles.
249 ! Must be > 0.
250 ! UNITS: N/A
251 ! TYPE: INTEGER
252 ! DIMENSION: Same as the NLTECoeff object
253 ! ATTRIBUTES: INTENT(IN)
254 !
255 ! n_Solar_Angles: Number of solar zenith angles.
256 ! Must be > 0.
257 ! UNITS: N/A
258 ! TYPE: INTEGER
259 ! DIMENSION: Same as the NLTECoeff object
260 ! ATTRIBUTES: INTENT(IN)
261 !
262 ! n_NLTE_Channels: Number of NLTE channels for the sensor.
263 ! Must be > 0.
264 ! UNITS: N/A
265 ! TYPE: INTEGER
266 ! DIMENSION: Same as the NLTECoeff object
267 ! ATTRIBUTES: INTENT(IN)
268 !
269 ! n_Channels: Total number of channels for the sensor.
270 ! Must be >= n_NLTE_Channels.
271 ! UNITS: N/A
272 ! TYPE: INTEGER
273 ! DIMENSION: Same as NLTECoeff object
274 ! ATTRIBUTES: INTENT(IN)
275 !
276 !:sdoc-:
277 !--------------------------------------------------------------------------------
278 
279  ELEMENTAL SUBROUTINE nltecoeff_create( &
280  NLTECoeff , & ! Output
281  n_Predictors , & ! Input
282  n_Sensor_Angles , & ! Input
283  n_Solar_Angles , & ! Input
284  n_NLTE_Channels , & ! Input
285  n_Channels ) ! Input
286  ! Arguments
287  TYPE(nltecoeff_type), INTENT(OUT) :: nltecoeff
288  INTEGER , INTENT(IN) :: n_predictors
289  INTEGER , INTENT(IN) :: n_sensor_angles
290  INTEGER , INTENT(IN) :: n_solar_angles
291  INTEGER , INTENT(IN) :: n_nlte_channels
292  INTEGER , INTENT(IN) :: n_channels
293  ! Local variables
294  INTEGER :: alloc_stat
295 
296  ! Check input
297  IF ( n_predictors < 1 .OR. &
298  n_sensor_angles < 1 .OR. &
299  n_solar_angles < 1 .OR. &
300  n_nlte_channels < 1 .OR. &
301  n_channels < n_nlte_channels ) RETURN
302 
303  ! Perform the allocation
304  ALLOCATE( nltecoeff%Sensor_Channel( n_channels ), &
305  nltecoeff%Secant_Sensor_Zenith( n_sensor_angles ), &
306  nltecoeff%Secant_Solar_Zenith( n_solar_angles ), &
307  nltecoeff%NLTE_Channel( n_nlte_channels ), &
308  nltecoeff%Is_NLTE_Channel( n_channels ), &
309  nltecoeff%C_Index( n_channels ), &
310  nltecoeff%C( n_predictors, n_sensor_angles, n_solar_angles, n_nlte_channels ), &
311  stat = alloc_stat )
312  IF ( alloc_stat /= 0 ) RETURN
313 
314 
315  ! Initialise
316  ! ...Dimensions
317  nltecoeff%n_Predictors = n_predictors
318  nltecoeff%n_Sensor_Angles = n_sensor_angles
319  nltecoeff%n_Solar_Angles = n_solar_angles
320  nltecoeff%n_NLTE_Channels = n_nlte_channels
321  nltecoeff%n_Channels = n_channels
322  ! ...Arrays
323  nltecoeff%Sensor_Channel = 0
324  nltecoeff%Secant_Sensor_Zenith = zero
325  nltecoeff%Secant_Solar_Zenith = zero
326  nltecoeff%NLTE_Channel = 0
327  nltecoeff%Is_NLTE_Channel = .false.
328  nltecoeff%C_Index = 0
329  nltecoeff%C = zero
330 
331  ! Set allocation indicator
332  nltecoeff%Is_Allocated = .true.
333 
334  END SUBROUTINE nltecoeff_create
335 
336 
337 !--------------------------------------------------------------------------------
338 !:sdoc+:
339 !
340 ! NAME:
341 ! NLTECoeff_Inspect
342 !
343 ! PURPOSE:
344 ! Subroutine to print the contents of a NLTECoeff object to stdout.
345 !
346 ! CALLING SEQUENCE:
347 ! CALL NLTECoeff_Inspect( NLTECoeff )
348 !
349 ! OBJECTS:
350 ! NLTECoeff: NLTECoeff object to display.
351 ! UNITS: N/A
352 ! TYPE: NLTECoeff_type
353 ! DIMENSION: Scalar
354 ! ATTRIBUTES: INTENT(IN)
355 !
356 !:sdoc-:
357 !--------------------------------------------------------------------------------
358 
359  SUBROUTINE nltecoeff_inspect( NLTECoeff )
360  TYPE(nltecoeff_type), INTENT(IN) :: nltecoeff
361  INTEGER :: i
362  CHARACTER(3) :: maybe
363  WRITE(*,'(1x,"NLTECoeff OBJECT")')
364  ! Release/version info
365  WRITE(*,'(3x,"Release.Version :",1x,i0,".",i0)') nltecoeff%Release, nltecoeff%Version
366  ! Dimensions
367  WRITE(*,'(3x,"n_Predictors :",1x,i0)') nltecoeff%n_Predictors
368  WRITE(*,'(3x,"n_Sensor_Angles :",1x,i0)') nltecoeff%n_Sensor_Angles
369  WRITE(*,'(3x,"n_Solar_Angles :",1x,i0)') nltecoeff%n_Solar_Angles
370  WRITE(*,'(3x,"n_NLTE_Channels :",1x,i0)') nltecoeff%n_NLTE_Channels
371  WRITE(*,'(3x,"n_Channels :",1x,i0)') nltecoeff%n_Channels
372  IF ( .NOT. nltecoeff_associated(nltecoeff) ) RETURN
373  ! Sensor info
374  WRITE(*,'(3x,"Sensor_Id :",1x,a )') trim(nltecoeff%Sensor_Id)
375  WRITE(*,'(3x,"WMO_Satellite_ID :",1x,i0)') nltecoeff%WMO_Satellite_ID
376  WRITE(*,'(3x,"WMO_Sensor_ID :",1x,i0)') nltecoeff%WMO_Sensor_ID
377  WRITE(*,'(3x,"Sensor_Channel :")')
378  WRITE(*,'(10(1x,i5,:))') nltecoeff%Sensor_Channel
379  ! Pressure arrays
380  WRITE(*,'(3x,"Upper_Plevel :")')
381  WRITE(*,'(5(1x,es13.6,:))') nltecoeff%Upper_Plevel
382  WRITE(*,'(3x,"Lower_Plevel :")')
383  WRITE(*,'(5(1x,es13.6,:))') nltecoeff%Lower_Plevel
384  ! Temperature arrays
385  WRITE(*,'(3x,"Min_Tm :")')
386  WRITE(*,'(5(1x,es13.6,:))') nltecoeff%Min_Tm
387  WRITE(*,'(3x,"Max_Tm :")')
388  WRITE(*,'(5(1x,es13.6,:))') nltecoeff%Max_Tm
389  WRITE(*,'(3x,"Mean_Tm :")')
390  WRITE(*,'(5(1x,es13.6,:))') nltecoeff%Mean_Tm
391  ! Coefficient table dimension vectors
392  WRITE(*,'(3x,"Secant_Sensor_Zenith :")')
393  WRITE(*,'(5(1x,es13.6,:))') nltecoeff%Secant_Sensor_Zenith
394  WRITE(*,'(3x,"Secant_Solar_Zenith :")')
395  WRITE(*,'(5(1x,es13.6,:))') nltecoeff%Secant_Solar_Zenith
396  WRITE(*,'(3x,"NLTE_Channel :")')
397  WRITE(*,'(10(1x,i5,:))') nltecoeff%NLTE_Channel
398  ! NLTE channel flag
399  WRITE(*,'(3x,"NLTE_Channel_Flag :")')
400  DO i = 1, nltecoeff%n_Channels
401  IF ( mod(i,5) == 0 .OR. i == nltecoeff%n_Channels ) THEN
402  maybe = 'yes'
403  ELSE
404  maybe = 'no'
405  END IF
406  WRITE(*,fmt='(1x,i5,":",l1,", c-index: ",i0)',advance=maybe) nltecoeff%Sensor_Channel(i), &
407  nltecoeff%Is_NLTE_Channel(i), &
408  nltecoeff%C_Index(i)
409  END DO
410  ! Coefficient data
411  WRITE(*,'(3x,"NLTE correction coefficients :")')
412  WRITE(*,'(5(1x,es13.6,:))') nltecoeff%C
413  END SUBROUTINE nltecoeff_inspect
414 
415 
416 !----------------------------------------------------------------------------------
417 !:sdoc+:
418 !
419 ! NAME:
420 ! NLTECoeff_ValidRelease
421 !
422 ! PURPOSE:
423 ! Function to check the NLTECoeff Release value.
424 !
425 ! CALLING SEQUENCE:
426 ! IsValid = NLTECoeff_ValidRelease( NLTECoeff )
427 !
428 ! INPUTS:
429 ! NLTECoeff: NLTECoeff object for which the Release component
430 ! is to be checked.
431 ! UNITS: N/A
432 ! TYPE: NLTECoeff_type
433 ! DIMENSION: Scalar
434 ! ATTRIBUTES: INTENT(IN)
435 !
436 ! FUNCTION RESULT:
437 ! IsValid: Logical value defining the release validity.
438 ! UNITS: N/A
439 ! TYPE: LOGICAL
440 ! DIMENSION: Scalar
441 !
442 !:sdoc-:
443 !----------------------------------------------------------------------------------
444 
445  FUNCTION nltecoeff_validrelease( NLTECoeff ) RESULT( IsValid )
446  ! Arguments
447  TYPE(nltecoeff_type), INTENT(IN) :: nltecoeff
448  ! Function result
449  LOGICAL :: isvalid
450  ! Local parameters
451  CHARACTER(*), PARAMETER :: routine_name = 'NLTECoeff_ValidRelease'
452  ! Local variables
453  CHARACTER(ML) :: msg
454 
455  ! Set up
456  isvalid = .true.
457 
458 
459  ! Check release is not too old
460  IF ( nltecoeff%Release < nltecoeff_release ) THEN
461  isvalid = .false.
462  WRITE( msg,'("A NLTECoeff data update is needed. ", &
463  &"NLTECoeff release is ",i0,". Valid release is ",i0,"." )' ) &
464  nltecoeff%Release, nltecoeff_release
465  CALL display_message( routine_name, msg, information )
466  RETURN
467  END IF
468 
469 
470  ! Check release is not too new
471  IF ( nltecoeff%Release > nltecoeff_release ) THEN
472  isvalid = .false.
473  WRITE( msg,'("A NLTECoeff software update is needed. ", &
474  &"NLTECoeff release is ",i0,". Valid release is ",i0,"." )' ) &
475  nltecoeff%Release, nltecoeff_release
476  CALL display_message( routine_name, msg, information )
477  RETURN
478  END IF
479 
480  END FUNCTION nltecoeff_validrelease
481 
482 
483 !--------------------------------------------------------------------------------
484 !:sdoc+:
485 !
486 ! NAME:
487 ! NLTECoeff_Info
488 !
489 ! PURPOSE:
490 ! Subroutine to return a string containing version and dimension
491 ! information about a NLTECoeff object.
492 !
493 ! CALLING SEQUENCE:
494 ! CALL NLTECoeff_Info( NLTECoeff, Info )
495 !
496 ! OBJECTS:
497 ! NLTECoeff: NLTECoeff object about which info is required.
498 ! UNITS: N/A
499 ! TYPE: NLTECoeff_type
500 ! DIMENSION: Scalar
501 ! ATTRIBUTES: INTENT(IN)
502 !
503 ! OUTPUTS:
504 ! Info: String containing version and dimension information
505 ! about the NLTECoeff object.
506 ! UNITS: N/A
507 ! TYPE: CHARACTER(*)
508 ! DIMENSION: Scalar
509 ! ATTRIBUTES: INTENT(OUT)
510 !
511 !:sdoc-:
512 !--------------------------------------------------------------------------------
513 
514  SUBROUTINE nltecoeff_info( NLTECoeff, Info )
515  ! Arguments
516  TYPE(nltecoeff_type), INTENT(IN) :: nltecoeff
517  CHARACTER(*), INTENT(OUT) :: info
518  ! Parameters
519  INTEGER, PARAMETER :: carriage_return = 13
520  INTEGER, PARAMETER :: linefeed = 10
521  ! Local variables
522  CHARACTER(2000) :: long_string
523 
524  ! Write the required data to the local string
525  WRITE( long_string, &
526  '(a,1x,"NLTECoeff RELEASE.VERSION: ",i2,".",i2.2,a,3x, &
527  &"N_PREDICTORS=",i0,2x,&
528  &"N_SENSOR_ANGLES=",i0,2x,&
529  &"N_SOLAR_ANGLES=",i0,2x,&
530  &"N_NLTE_CHANNELS=",i0,2x,&
531  &"N_CHANNELS=",i0 )' ) &
532  achar(carriage_return)//achar(linefeed), &
533  nltecoeff%Release, nltecoeff%Version, &
534  achar(carriage_return)//achar(linefeed), &
535  nltecoeff%n_Predictors , &
536  nltecoeff%n_Sensor_Angles , &
537  nltecoeff%n_Solar_Angles , &
538  nltecoeff%n_NLTE_Channels , &
539  nltecoeff%n_Channels
540 
541  ! Trim the output based on the
542  ! dummy argument string length
543  info = long_string(1:min(len(info), len_trim(long_string)))
544 
545  END SUBROUTINE nltecoeff_info
546 
547 
548 !--------------------------------------------------------------------------------
549 !:sdoc+:
550 !
551 ! NAME:
552 ! NLTECoeff_DefineVersion
553 !
554 ! PURPOSE:
555 ! Subroutine to return the module version information.
556 !
557 ! CALLING SEQUENCE:
558 ! CALL NLTECoeff_DefineVersion( Id )
559 !
560 ! OUTPUTS:
561 ! Id: Character string containing the version Id information
562 ! for the module.
563 ! UNITS: N/A
564 ! TYPE: CHARACTER(*)
565 ! DIMENSION: Scalar
566 ! ATTRIBUTES: INTENT(OUT)
567 !
568 !:sdoc-:
569 !--------------------------------------------------------------------------------
570 
571  SUBROUTINE nltecoeff_defineversion( Id )
572  CHARACTER(*), INTENT(OUT) :: id
573  id = module_version_id
574  END SUBROUTINE nltecoeff_defineversion
575 
576 
577 !--------------------------------------------------------------------------------
578 !:sdoc+:
579 !
580 ! NAME:
581 ! NLTECoeff_Subset
582 !
583 ! PURPOSE:
584 ! Subroutine to return a channel subset of the input NLTECoeff object.
585 !
586 ! CALLING SEQUENCE:
587 ! CALL NLTECoeff_Subset( NLTECoeff, Subset, NC_Subset )
588 !
589 ! OBJECTS:
590 ! NLTECoeff: NLTECoeff object which is to be subsetted.
591 ! UNITS: N/A
592 ! TYPE: NLTECoeff_type
593 ! DIMENSION: Scalar
594 ! ATTRIBUTES: INTENT(IN)
595 !
596 ! INPUTS:
597 ! Subset: Subset object containing the list of indices
598 ! corresponding the channels to be extracted.
599 ! UNITS: N/A
600 ! TYPE: Subset_type
601 ! DIMENSION: Scalar
602 ! ATTRIBUTES: INTENT(IN)
603 !
604 ! OUTPUTS:
605 ! NC_Subset: NLTECoeff object containing the requested channel subset
606 ! of the input NLTECoeff data.
607 ! UNITS: N/A
608 ! TYPE: NLTECoeff_type
609 ! DIMENSION: Scalar
610 ! ATTRIBUTES: INTENT(OUT)
611 !
612 !:sdoc-:
613 !--------------------------------------------------------------------------------
614 
615  SUBROUTINE nltecoeff_subset( &
616  NLTECoeff , & ! Input
617  Sensor_Channel, & ! Input
618  NC_Subset ) ! Output
619  ! Arguments
620  TYPE(nltecoeff_type), INTENT(IN) :: nltecoeff
621  INTEGER , INTENT(IN) :: sensor_channel(:)
622  TYPE(nltecoeff_type), INTENT(OUT) :: nc_subset
623  ! Local variables
624  TYPE(subset_type) :: subset, nlte_subset
625  INTEGER :: n_subset_channels, n_nlte_subset_channels
626  INTEGER, ALLOCATABLE :: idx(:), nlte_idx(:)
627 
628  ! Check input is valid
629  IF ( .NOT. nltecoeff_associated(nltecoeff) ) RETURN
630 
631 
632  ! Generate the channel subset list
633  CALL subset_generate( &
634  subset, &
635  nltecoeff%Sensor_Channel, &
636  sensor_channel )
637  IF ( .NOT. subset_associated( subset ) ) RETURN
638  ! ...Generate the NLTE channel subset list
639  ! ...(which is itself a subset of the sensor channel list)
640  CALL subset_generate( &
641  nlte_subset, &
642  nltecoeff%NLTE_Channel, &
643  sensor_channel )
644  IF ( .NOT. subset_associated( nlte_subset ) ) RETURN
645 
646 
647  ! Allocate the output subset NLTECoeff object
648  CALL subset_getvalue( subset , n_values = n_subset_channels , index = idx )
649  CALL subset_getvalue( nlte_subset, n_values = n_nlte_subset_channels, index = nlte_idx )
650  CALL nltecoeff_create( &
651  nc_subset , &
652  nltecoeff%n_Predictors , &
653  nltecoeff%n_Sensor_Angles, &
654  nltecoeff%n_Solar_Angles , &
655  n_nlte_subset_channels , &
656  n_subset_channels )
657  IF ( .NOT. nltecoeff_associated(nc_subset) ) RETURN
658 
659 
660  ! Extract out the subset channels
661  ! ...First assign the non-channel dependent data
662  nc_subset%Version = nltecoeff%Version
663  nc_subset%Sensor_Id = nltecoeff%Sensor_Id
664  nc_subset%WMO_Satellite_ID = nltecoeff%WMO_Satellite_ID
665  nc_subset%WMO_Sensor_ID = nltecoeff%WMO_Sensor_ID
666  nc_subset%Upper_Plevel = nltecoeff%Upper_Plevel
667  nc_subset%Lower_Plevel = nltecoeff%Lower_Plevel
668  nc_subset%Min_Tm = nltecoeff%Min_Tm
669  nc_subset%Max_Tm = nltecoeff%Max_Tm
670  nc_subset%Mean_Tm = nltecoeff%Mean_Tm
671  nc_subset%Secant_Sensor_Zenith = nltecoeff%Secant_Sensor_Zenith
672  nc_subset%Secant_Solar_Zenith = nltecoeff%Secant_Solar_Zenith
673  ! ...and now extract the subset
674  nc_subset%Sensor_Channel = nltecoeff%Sensor_Channel(idx)
675  nc_subset%NLTE_Channel = nltecoeff%NLTE_Channel(nlte_idx)
676  nc_subset%Is_NLTE_Channel = nltecoeff%Is_NLTE_Channel(idx)
677  nc_subset%C_Index = nltecoeff%C_Index(idx)
678  nc_subset%C = nltecoeff%C(:,:,:,nlte_idx)
679  ! ...Reindex the correction coefficient index array
680  CALL nltecoeff_reindex( nc_subset )
681 
682  END SUBROUTINE nltecoeff_subset
683 
684 
685 !--------------------------------------------------------------------------------
686 !:sdoc+:
687 !
688 ! NAME:
689 ! NLTECoeff_Concat
690 !
691 ! PURPOSE:
692 ! Subroutine to concatenate multiple NLTECoeff objects along the channel
693 ! dimension into a single NLTECoeff object.
694 !
695 ! CALLING SEQUENCE:
696 ! CALL NLTECoeff_Concat( NLTECoeff, NC_Array, Sensor_Id=Sensor_Id )
697 !
698 ! OBJECTS:
699 ! NLTECoeff: NLTECoeff object containing the concatenated result.
700 ! UNITS: N/A
701 ! TYPE: NLTECoeff_type
702 ! DIMENSION: Scalar
703 ! ATTRIBUTES: INTENT(OUT)
704 !
705 ! INPUTS:
706 ! NC_Array: Array of NLTECoeff objects to be concatenated.
707 ! UNITS: N/A
708 ! TYPE: NLTECoeff_type
709 ! DIMENSION: Rank-1
710 ! ATTRIBUTES: INTENT(IN)
711 !
712 ! OPTIONAL INPUTS:
713 ! Sensor_Id: Sensor id character to string to use for the concatenated
714 ! result. If not specified, the sensor id of the first valid
715 ! element of NC_Array is used.
716 ! UNITS: N/A
717 ! TYPE: CHARACTER(*)
718 ! DIMENSION: Scalar
719 ! ATTRIBUTES: INTENT(IN), OPTIONAL
720 !
721 !:sdoc-:
722 !--------------------------------------------------------------------------------
723 
724  SUBROUTINE nltecoeff_concat( &
725  NLTECoeff, & ! Output
726  NC_Array , & ! Input
727  Sensor_Id ) ! Optional input
728  ! Arguments
729  TYPE(nltecoeff_type) , INTENT(OUT) :: nltecoeff
730  TYPE(nltecoeff_type) , INTENT(IN) :: nc_array(:)
731  CHARACTER(*), OPTIONAL, INTENT(IN) :: sensor_id
732  ! Local variables
733  INTEGER, ALLOCATABLE :: valid_index(:)
734  INTEGER :: i, j, n_nc, n_valid, n_channels, n_nlte_channels
735  INTEGER :: ch1, ch2, nlte_ch1, nlte_ch2
736 
737  ! Set up
738  ! ...Check input is valid
739  n_nc = SIZE(nc_array)
740  IF ( n_nc < 1 ) RETURN
741  ! ...Count valid input
742  n_valid = count(nltecoeff_associated(nc_array))
743  IF ( n_valid == 0 ) RETURN
744  ! ...Index the valid input
745  ALLOCATE( valid_index(n_valid) )
746  valid_index = pack( (/(i,i=1,n_nc)/), mask=nltecoeff_associated(nc_array) )
747  ! ...Check non-channel dimensions and ids
748  DO j = 1, n_valid
749  i = valid_index(j)
750  IF ( nc_array(i)%n_Predictors /= nc_array(valid_index(1))%n_Predictors .OR. &
751  nc_array(i)%n_Sensor_Angles /= nc_array(valid_index(1))%n_Sensor_Angles .OR. &
752  nc_array(i)%n_Solar_Angles /= nc_array(valid_index(1))%n_Solar_Angles .OR. &
753  nc_array(i)%WMO_Satellite_ID /= nc_array(valid_index(1))%WMO_Satellite_ID .OR. &
754  nc_array(i)%WMO_Sensor_ID /= nc_array(valid_index(1))%WMO_Sensor_ID ) THEN
755  RETURN
756  END IF
757  END DO
758 
759 
760  ! Sum channel dimensions
761  n_nlte_channels = sum(nc_array(valid_index)%n_NLTE_Channels)
762  n_channels = sum(nc_array(valid_index)%n_Channels)
763 
764 
765  ! Allocate the output concatenated NLTECoeff object
766  CALL nltecoeff_create( &
767  nltecoeff , &
768  nc_array(valid_index(1))%n_Predictors , &
769  nc_array(valid_index(1))%n_Sensor_Angles, &
770  nc_array(valid_index(1))%n_Solar_Angles , &
771  n_nlte_channels , &
772  n_channels )
773  IF ( .NOT. nltecoeff_associated(nltecoeff) ) RETURN
774 
775 
776  ! Concatenate the channel data
777  ! ...First assign the non-channel dependent data
778  nltecoeff%Version = nc_array(valid_index(1))%Version
779  IF ( PRESENT(sensor_id) ) THEN
780  nltecoeff%Sensor_Id = adjustl(sensor_id)
781  ELSE
782  nltecoeff%Sensor_Id = nc_array(valid_index(1))%Sensor_Id
783  END IF
784  nltecoeff%WMO_Satellite_ID = nc_array(valid_index(1))%WMO_Satellite_ID
785  nltecoeff%WMO_Sensor_ID = nc_array(valid_index(1))%WMO_Sensor_ID
786  nltecoeff%Upper_Plevel = nc_array(valid_index(1))%Upper_Plevel
787  nltecoeff%Lower_Plevel = nc_array(valid_index(1))%Lower_Plevel
788  nltecoeff%Min_Tm = nc_array(valid_index(1))%Min_Tm
789  nltecoeff%Max_Tm = nc_array(valid_index(1))%Max_Tm
790  nltecoeff%Mean_Tm = nc_array(valid_index(1))%Mean_Tm
791  nltecoeff%Secant_Sensor_Zenith = nc_array(valid_index(1))%Secant_Sensor_Zenith
792  nltecoeff%Secant_Solar_Zenith = nc_array(valid_index(1))%Secant_Solar_Zenith
793  ! ...and now concatenate the channel data
794  ch1 = 1
795  nlte_ch1 = 1
796  DO j = 1, n_valid
797  i = valid_index(j)
798 
799  nlte_ch2 = nlte_ch1 + nc_array(i)%n_NLTE_Channels - 1
800  ch2 = ch1 + nc_array(i)%n_Channels - 1
801 
802  nltecoeff%Sensor_Channel(ch1:ch2) = nc_array(i)%Sensor_Channel
803  nltecoeff%NLTE_Channel(nlte_ch1:nlte_ch2) = nc_array(i)%NLTE_Channel
804  nltecoeff%Is_NLTE_Channel(ch1:ch2) = nc_array(i)%Is_NLTE_Channel
805  nltecoeff%C_Index(ch1:ch2) = nc_array(i)%C_Index
806  nltecoeff%C(:,:,:,nlte_ch1:nlte_ch2) = nc_array(i)%C
807 
808  nlte_ch1 = nlte_ch2 + 1
809  ch1 = ch2 + 1
810  END DO
811  ! ...Reindex the correction coefficient index array
812  CALL nltecoeff_reindex( nltecoeff )
813 
814 
815  ! Cleanup
816  DEALLOCATE( valid_index )
817 
818  END SUBROUTINE nltecoeff_concat
819 
820 
821 !--------------------------------------------------------------------------------
822 !:sdoc+:
823 !
824 ! NAME:
825 ! NLTECoeff_ChannelReindex
826 !
827 ! PURPOSE:
828 ! Subroutine to re-index an NLTECoeff object for a different complete
829 ! channel set.
830 !
831 ! CALLING SEQUENCE:
832 ! CALL NLTECoeff_ChannelReindex( NLTECoeff, Sensor_Channels )
833 !
834 ! OBJECTS:
835 ! NLTECoeff: NLTECoeff object to have its channel information reindexed.
836 ! UNITS: N/A
837 ! TYPE: NLTECoeff_type
838 ! DIMENSION: Scalar
839 ! ATTRIBUTES: INTENT(IN OUT)
840 !
841 ! INPUTS:
842 ! Sensor_Channel: Array of channel numbers for which the NLTECoeff object
843 ! is to be re-indexed against.
844 ! UNITS: N/A
845 ! TYPE: INTEGER
846 ! DIMENSION: Rank-1
847 ! ATTRIBUTES: INTENT(IN)
848 !
849 ! COMMENTS:
850 ! If there is a mismatch between the channel sets, e.g. total number of
851 ! sensor channels is less than the number of NLTE channels, or if ANY of
852 ! the NLTE channels are NOT in the sensor channel list, no reindexing is
853 ! performed and the input structure is returned with no changes.
854 !
855 !:sdoc-:
856 !--------------------------------------------------------------------------------
857 
858  SUBROUTINE nltecoeff_channelreindex( NLTECoeff, Sensor_Channel )
859  ! Arguments
860  TYPE(nltecoeff_type), INTENT(IN OUT) :: nltecoeff
861  INTEGER , INTENT(IN) :: sensor_channel(:)
862  ! Local variables
863  TYPE(nltecoeff_type) :: nc_copy
864  INTEGER :: i, i_nlte
865  INTEGER :: n_channels, n_nlte_channels
866 
867  ! Setup
868  IF ( .NOT. nltecoeff_associated(nltecoeff) ) RETURN
869  n_channels = SIZE(sensor_channel)
870  IF ( n_channels < 1 ) RETURN
871  IF ( n_channels < nltecoeff%n_NLTE_Channels ) RETURN
872 
873 
874  ! Copy the input structure
875  nc_copy = nltecoeff
876 
877 
878  ! Allocate the reindexed NLTECoeff object
879  CALL nltecoeff_create( &
880  nltecoeff , &
881  nc_copy%n_Predictors , &
882  nc_copy%n_Sensor_Angles, &
883  nc_copy%n_Solar_Angles , &
884  nc_copy%n_NLTE_Channels, &
885  n_channels )
886  IF ( .NOT. nltecoeff_associated(nltecoeff) ) RETURN
887 
888 
889  ! Fill the new structure
890  ! ...Copy over the non-channel related information
891  nltecoeff%Version = nc_copy%Version
892  nltecoeff%Sensor_Id = nc_copy%Sensor_Id
893  nltecoeff%WMO_Satellite_ID = nc_copy%WMO_Satellite_ID
894  nltecoeff%WMO_Sensor_ID = nc_copy%WMO_Sensor_ID
895  nltecoeff%Upper_Plevel = nc_copy%Upper_Plevel
896  nltecoeff%Lower_Plevel = nc_copy%Lower_Plevel
897  nltecoeff%Min_Tm = nc_copy%Min_Tm
898  nltecoeff%Max_Tm = nc_copy%Max_Tm
899  nltecoeff%Mean_Tm = nc_copy%Mean_Tm
900  nltecoeff%Secant_Sensor_Zenith = nc_copy%Secant_Sensor_Zenith
901  nltecoeff%Secant_Solar_Zenith = nc_copy%Secant_Solar_Zenith
902  ! ...Copy over the NLTE channel related information
903  nltecoeff%NLTE_Channel = nc_copy%NLTE_Channel
904  nltecoeff%C = nc_copy%C
905  ! ...Copy over the all-channel related information
906  nltecoeff%Sensor_Channel = sensor_channel
907 
908 
909  ! Perform the channel reindexing
910  i_nlte = 1
911  reindex_loop: DO i = 1, n_channels
912  IF ( nltecoeff%Sensor_Channel(i) == nltecoeff%NLTE_Channel(i_nlte) ) THEN
913  nltecoeff%Is_NLTE_Channel(i) = .true.
914  nltecoeff%C_Index(i) = i_nlte
915  i_nlte = i_nlte + 1
916  IF (i_nlte > nltecoeff%n_NLTE_Channels) EXIT reindex_loop
917  END IF
918  END DO reindex_loop
919  ! ...Unless ALL the NLTE channel were reindexed, restore the original structure
920  n_nlte_channels = i_nlte - 1
921  IF ( n_nlte_channels /= nltecoeff%n_NLTE_Channels ) nltecoeff = nc_copy
922 
923 
924  ! Clean up
925  CALL nltecoeff_destroy(nc_copy)
926 
927  END SUBROUTINE nltecoeff_channelreindex
928 
929 
930 
931 !##################################################################################
932 !##################################################################################
933 !## ##
934 !## ## PRIVATE MODULE ROUTINES ## ##
935 !## ##
936 !##################################################################################
937 !##################################################################################
938 
939 !------------------------------------------------------------------------------
940 !
941 ! NAME:
942 ! NLTECoeff_Equal
943 !
944 ! PURPOSE:
945 ! Elemental function to test the equality of two NLTECoeff objects.
946 ! Used in OPERATOR(==) interface block.
947 !
948 ! CALLING SEQUENCE:
949 ! is_equal = NLTECoeff_Equal( x, y )
950 !
951 ! or
952 !
953 ! IF ( x == y ) THEN
954 ! ...
955 ! END IF
956 !
957 ! OBJECTS:
958 ! x, y: Two NLTECoeff objects to be compared.
959 ! UNITS: N/A
960 ! TYPE: NLTECoeff_type
961 ! DIMENSION: Scalar or any rank
962 ! ATTRIBUTES: INTENT(IN)
963 !
964 ! FUNCTION RESULT:
965 ! is_equal: Logical value indicating whether the inputs are equal.
966 ! UNITS: N/A
967 ! TYPE: LOGICAL
968 ! DIMENSION: Same as inputs.
969 !
970 !------------------------------------------------------------------------------
971 
972  ELEMENTAL FUNCTION nltecoeff_equal( x, y ) RESULT( is_equal )
973  TYPE(nltecoeff_type), INTENT(IN) :: x, y
974  LOGICAL :: is_equal
975 
976  ! Set up
977  is_equal = .false.
978 
979  ! Check the object association status
980  IF ( (.NOT. nltecoeff_associated(x)) .OR. &
981  (.NOT. nltecoeff_associated(y)) ) RETURN
982 
983  ! Check contents
984  ! ...Release/version info
985  IF ( (x%Release /= y%Release) .OR. &
986  (x%Version /= y%Version) ) RETURN
987  ! ...Dimensions
988  IF ( (x%n_Predictors /= y%n_Predictors ) .OR. &
989  (x%n_Sensor_Angles /= y%n_Sensor_Angles ) .OR. &
990  (x%n_Solar_Angles /= y%n_Solar_Angles ) .OR. &
991  (x%n_NLTE_Channels /= y%n_NLTE_Channels ) .OR. &
992  (x%n_Channels /= y%n_Channels ) ) RETURN
993  ! ...Scalars
994  IF ( (x%Sensor_Id /= y%Sensor_Id ) .OR. &
995  (x%WMO_Satellite_ID /= y%WMO_Satellite_ID) .OR. &
996  (x%WMO_Sensor_ID /= y%WMO_Sensor_ID ) ) RETURN
997  ! ...Arrays
998  IF ( all(x%Sensor_Channel == y%Sensor_Channel ) .AND. &
999  all(x%Upper_Plevel .equalto. y%Upper_Plevel ) .AND. &
1000  all(x%Lower_Plevel .equalto. y%Lower_Plevel ) .AND. &
1001  all(x%Min_Tm .equalto. y%Min_Tm ) .AND. &
1002  all(x%Max_Tm .equalto. y%Max_Tm ) .AND. &
1003  all(x%Mean_Tm .equalto. y%Mean_Tm ) .AND. &
1004  all(x%Secant_Sensor_Zenith .equalto. y%Secant_Sensor_Zenith) .AND. &
1005  all(x%Secant_Solar_Zenith .equalto. y%Secant_Solar_Zenith ) .AND. &
1006  all(x%NLTE_Channel == y%NLTE_Channel ) .AND. &
1007  all(x%Is_NLTE_Channel .EQV. y%Is_NLTE_Channel ) .AND. &
1008  all(x%C_Index == y%C_Index ) .AND. &
1009  all(x%C .equalto. y%C ) ) &
1010  is_equal = .true.
1011 
1012  END FUNCTION nltecoeff_equal
1013 
1014 
1015 !--------------------------------------------------------------------------------
1016 !
1017 ! NAME:
1018 ! NLTECoeff_Reindex
1019 !
1020 ! PURPOSE:
1021 ! Subroutine to reindex the C_Index component of an NLTECoeff object after,
1022 ! for example, subsetting or concatenation.
1023 !
1024 ! CALLING SEQUENCE:
1025 ! CALL NLTECoeff_Reindex( NLTECoeff )
1026 !
1027 ! OBJECTS:
1028 ! NLTECoeff: NLTECoeff object which is to have its C_Index
1029 ! component reindexed.
1030 ! UNITS: N/A
1031 ! TYPE: NLTECoeff_type
1032 ! DIMENSION: Scalar
1033 ! ATTRIBUTES: INTENT(IN OUT)
1034 !
1035 !--------------------------------------------------------------------------------
1036 
1037  SUBROUTINE nltecoeff_reindex( NLTECoeff )
1038  TYPE(NLTECoeff_type), INTENT(IN OUT) :: NLTECoeff
1039  INTEGER :: i, j
1040  j = 1
1041  DO i = 1, nltecoeff%n_Channels
1042  IF ( nltecoeff%C_Index(i) > 0 ) THEN
1043  nltecoeff%C_Index(i) = j
1044  j = j + 1
1045  END IF
1046  END DO
1047  END SUBROUTINE nltecoeff_reindex
1048 
1049 END MODULE nltecoeff_define
integer, parameter, public failure
integer, parameter, public invalid_wmo_sensor_id
elemental subroutine, public nltecoeff_create(NLTECoeff, n_Predictors, n_Sensor_Angles, n_Solar_Angles, n_NLTE_Channels, n_Channels)
integer, parameter nltecoeff_release
real(fp), parameter, public zero
integer, parameter false
integer, parameter, public long
Definition: Type_Kinds.f90:76
elemental logical function nltecoeff_equal(x, y)
integer, parameter, public double
Definition: Type_Kinds.f90:106
logical function, public nltecoeff_validrelease(NLTECoeff)
integer, parameter ml
integer, parameter, public invalid_wmo_satellite_id
elemental logical function, public subset_associated(Subset)
integer, parameter nltecoeff_version
subroutine, public nltecoeff_subset(NLTECoeff, Sensor_Channel, NC_Subset)
integer, parameter sl
real(fp), parameter, public one
recursive subroutine, public display_message(Routine_Name, Message, Error_State, Message_Log)
subroutine, public nltecoeff_channelreindex(NLTECoeff, Sensor_Channel)
subroutine nltecoeff_reindex(NLTECoeff)
integer, parameter true
subroutine, public nltecoeff_inspect(NLTECoeff)
subroutine, public subset_getvalue(Subset, n_Values, Number, Index)
subroutine, public nltecoeff_info(NLTECoeff, Info)
subroutine, public nltecoeff_defineversion(Id)
elemental subroutine, public nltecoeff_destroy(NLTECoeff)
#define min(a, b)
Definition: mosaic_util.h:32
subroutine, public subset_generate(Subset, List, Subset_List)
character(*), parameter module_version_id
integer, parameter, public success
subroutine, public nltecoeff_concat(NLTECoeff, NC_Array, Sensor_Id)
integer, parameter n_layers
integer, parameter, public information
elemental logical function, public nltecoeff_associated(NLTECoeff)