FV3 Bundle
CRTM_Cloud_Define.f90
Go to the documentation of this file.
1 !
2 ! CRTM_Cloud_Define
3 !
4 ! Module defining the CRTM Cloud structure and containing routines to
5 ! manipulate it.
6 !
7 !
8 ! CREATION HISTORY:
9 ! Written by: Yong Han, yong.han@noaa.gov
10 ! Quanhua Liu, quanhua.liu@noaa.gov
11 ! Paul van Delst, paul.vandelst@noaa.gov
12 ! 20-Feb-2004
13 !
14 
16 
17 
18  ! -----------------
19  ! Environment setup
20  ! -----------------
21  ! Intrinsic modules
22  USE iso_fortran_env , ONLY: output_unit
23  ! Module use
24  USE type_kinds , ONLY: fp
27  OPERATOR(.equalto.), &
33  ! Disable implicit typing
34  IMPLICIT NONE
35 
36 
37  ! ------------
38  ! Visibilities
39  ! ------------
40  ! Everything private by default
41  PRIVATE
42  ! Cloud Parameters
43  PUBLIC :: n_valid_cloud_categories
44  PUBLIC :: invalid_cloud
45  PUBLIC :: water_cloud
46  PUBLIC :: ice_cloud
47  PUBLIC :: rain_cloud
48  PUBLIC :: snow_cloud
49  PUBLIC :: graupel_cloud
50  PUBLIC :: hail_cloud
51  PUBLIC :: cloud_category_name
52  ! Datatypes
53  PUBLIC :: crtm_cloud_type
54  ! Operators
55  PUBLIC :: OPERATOR(==)
56  PUBLIC :: OPERATOR(+)
57  PUBLIC :: OPERATOR(-)
58  ! Procedures
59  PUBLIC :: crtm_cloud_categoryname
60  PUBLIC :: crtm_cloud_categoryid
61  PUBLIC :: crtm_cloud_categorylist
62  PUBLIC :: crtm_cloud_associated
63  PUBLIC :: crtm_cloud_destroy
64  PUBLIC :: crtm_cloud_create
65  PUBLIC :: crtm_cloud_addlayercopy
66  PUBLIC :: crtm_cloud_zero
67  PUBLIC :: crtm_cloud_isvalid
68  PUBLIC :: crtm_cloud_inspect
69  PUBLIC :: crtm_cloud_defineversion
70  PUBLIC :: crtm_cloud_compare
71  PUBLIC :: crtm_cloud_setlayers
72  PUBLIC :: crtm_cloud_inquirefile
73  PUBLIC :: crtm_cloud_readfile
74  PUBLIC :: crtm_cloud_writefile
75 
76 
77  ! ---------------------
78  ! Procedure overloading
79  ! ---------------------
80  INTERFACE OPERATOR(==)
81  MODULE PROCEDURE crtm_cloud_equal
82  END INTERFACE OPERATOR(==)
83 
84  INTERFACE OPERATOR(+)
85  MODULE PROCEDURE crtm_cloud_add
86  END INTERFACE OPERATOR(+)
87 
88  INTERFACE OPERATOR(-)
89  MODULE PROCEDURE crtm_cloud_subtract
90  END INTERFACE OPERATOR(-)
91 
93  MODULE PROCEDURE scalar_inspect
94  MODULE PROCEDURE rank1_inspect
95  MODULE PROCEDURE rank2_inspect
96  END INTERFACE crtm_cloud_inspect
97 
98 
99  ! -----------------
100  ! Module parameters
101  ! -----------------
102  CHARACTER(*), PARAMETER :: module_version_id = &
103  '$Id: CRTM_Cloud_Define.f90 60152 2015-08-13 19:19:13Z paul.vandelst@noaa.gov $'
104  ! The valid cloud categories and names
105  INTEGER, PARAMETER :: n_valid_cloud_categories = 6
106  INTEGER, PARAMETER :: invalid_cloud = 0
107  INTEGER, PARAMETER :: water_cloud = 1
108  INTEGER, PARAMETER :: ice_cloud = 2
109  INTEGER, PARAMETER :: rain_cloud = 3
110  INTEGER, PARAMETER :: snow_cloud = 4
111  INTEGER, PARAMETER :: graupel_cloud = 5
112  INTEGER, PARAMETER :: hail_cloud = 6
113  INTEGER, PARAMETER :: cloud_category_list(0:n_valid_cloud_categories) = &
114  [ invalid_cloud, &
115  water_cloud, &
116  ice_cloud, &
117  rain_cloud, &
118  snow_cloud, &
119  graupel_cloud, &
120  hail_cloud ]
121  CHARACTER(*), PARAMETER :: cloud_category_name(0:n_valid_cloud_categories) = &
122  [ 'Invalid', &
123  'Water ', &
124  'Ice ', &
125  'Rain ', &
126  'Snow ', &
127  'Graupel', &
128  'Hail ' ]
129  ! Literal constants
130  REAL(fp), PARAMETER :: zero = 0.0_fp
131  REAL(fp), PARAMETER :: one = 1.0_fp
132  ! Message string length
133  INTEGER, PARAMETER :: ml = 256
134  ! File status on close after write error
135  CHARACTER(*), PARAMETER :: write_error_status = 'DELETE'
136 
137 
138  ! --------------------------
139  ! Cloud data type definition
140  ! --------------------------
141  !:tdoc+:
143  ! Allocation indicator
144  LOGICAL :: is_allocated = .false.
145  ! Dimension values
146  INTEGER :: max_layers = 0 ! K dimension.
147  INTEGER :: n_layers = 0 ! Kuse dimension.
148  ! Number of added layers
149  INTEGER :: n_added_layers = 0
150  ! Cloud type
151  INTEGER :: Type = invalid_cloud
152  ! Cloud state variables
153  REAL(fp), ALLOCATABLE :: effective_radius(:) ! K. Units are microns
154  REAL(fp), ALLOCATABLE :: effective_variance(:) ! K. Units are microns^2
155  REAL(fp), ALLOCATABLE :: water_content(:) ! K. Units are kg/m^2
156  END TYPE crtm_cloud_type
157  !:tdoc-:
158 
159 
160 CONTAINS
161 
162 
163 !################################################################################
164 !################################################################################
165 !## ##
166 !## ## PUBLIC MODULE ROUTINES ## ##
167 !## ##
168 !################################################################################
169 !################################################################################
170 
171  PURE FUNCTION crtm_cloud_categoryid(cloud) RESULT(id)
172  TYPE(crtm_cloud_type), INTENT(IN) :: cloud
173  INTEGER :: id
174  id = cloud%type
175  IF ( id < 1 .OR. id > n_valid_cloud_categories ) id = invalid_cloud
176  END FUNCTION crtm_cloud_categoryid
177 
178  PURE FUNCTION crtm_cloud_categoryname(cloud) RESULT(name)
179  TYPE(crtm_cloud_type), INTENT(IN) :: cloud
180  CHARACTER(LEN(CLOUD_CATEGORY_NAME(1))) :: name
181  INTEGER :: id
183  name = cloud_category_name(id)
184  END FUNCTION crtm_cloud_categoryname
185 
186  FUNCTION crtm_cloud_categorylist(list) RESULT(err_stat)
187  INTEGER, ALLOCATABLE, INTENT(OUT) :: list(:)
188  INTEGER :: err_stat
189  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_Cloud_CategoryList'
190  CHARACTER(ML) :: alloc_msg, msg
191  INTEGER :: alloc_stat
192  err_stat = success
193  ALLOCATE( list(0:n_valid_cloud_categories), stat=alloc_stat, errmsg=alloc_msg )
194  IF ( alloc_stat /= 0 ) THEN
195  err_stat = failure
196  msg = 'Cloud category list result not allocated -'//trim(alloc_msg)
197  CALL display_message( routine_name, msg, err_stat )
198  RETURN
199  END IF
200  list = cloud_category_list
201  END FUNCTION crtm_cloud_categorylist
202 
203 
204 !--------------------------------------------------------------------------------
205 !:sdoc+:
206 !
207 ! NAME:
208 ! CRTM_Cloud_Associated
209 !
210 ! PURPOSE:
211 ! Elemental function to test the status of the allocatable components
212 ! of a CRTM Cloud object.
213 !
214 ! CALLING SEQUENCE:
215 ! Status = CRTM_Cloud_Associated( Cloud )
216 !
217 ! OBJECTS:
218 ! Cloud: Cloud structure which is to have its member's
219 ! status tested.
220 ! UNITS: N/A
221 ! TYPE: CRTM_Cloud_type
222 ! DIMENSION: Scalar or any rank
223 ! ATTRIBUTES: INTENT(IN)
224 !
225 ! FUNCTION RESULT:
226 ! Status: The return value is a logical value indicating the
227 ! status of the Cloud members.
228 ! .TRUE. - if the array components are allocated.
229 ! .FALSE. - if the array components are not allocated.
230 ! UNITS: N/A
231 ! TYPE: LOGICAL
232 ! DIMENSION: Same as input Cloud argument
233 !
234 !:sdoc-:
235 !--------------------------------------------------------------------------------
236 
237  ELEMENTAL FUNCTION crtm_cloud_associated( Cloud ) RESULT( Status )
238  TYPE(crtm_cloud_type), INTENT(IN) :: cloud
239  LOGICAL :: status
240  status = cloud%Is_Allocated
241  END FUNCTION crtm_cloud_associated
242 
243 
244 !--------------------------------------------------------------------------------
245 !:sdoc+:
246 !
247 ! NAME:
248 ! CRTM_Cloud_Destroy
249 !
250 ! PURPOSE:
251 ! Elemental subroutine to re-initialize CRTM Cloud objects.
252 !
253 ! CALLING SEQUENCE:
254 ! CALL CRTM_Cloud_Destroy( Cloud )
255 !
256 ! OBJECTS:
257 ! Cloud: Re-initialized Cloud structure.
258 ! UNITS: N/A
259 ! TYPE: CRTM_Cloud_type
260 ! DIMENSION: Scalar OR any rank
261 ! ATTRIBUTES: INTENT(OUT)
262 !
263 !:sdoc-:
264 !--------------------------------------------------------------------------------
265 
266  ELEMENTAL SUBROUTINE crtm_cloud_destroy( Cloud )
267  TYPE(crtm_cloud_type), INTENT(OUT) :: cloud
268  cloud%Is_Allocated = .false.
269  END SUBROUTINE crtm_cloud_destroy
270 
271 
272 !--------------------------------------------------------------------------------
273 !:sdoc+:
274 !
275 ! NAME:
276 ! CRTM_Cloud_Create
277 !
278 ! PURPOSE:
279 ! Elemental subroutine to create an instance of the CRTM Cloud object.
280 !
281 ! CALLING SEQUENCE:
282 ! CALL CRTM_Cloud_Create( Cloud, n_Layers )
283 !
284 ! OBJECTS:
285 ! Cloud: Cloud structure.
286 ! UNITS: N/A
287 ! TYPE: CRTM_Cloud_type
288 ! DIMENSION: Scalar or any rank
289 ! ATTRIBUTES: INTENT(OUT)
290 !
291 ! INPUTS:
292 ! n_Layers: Number of layers for which there is cloud data.
293 ! Must be > 0.
294 ! UNITS: N/A
295 ! TYPE: INTEGER
296 ! DIMENSION: Same as Cloud object
297 ! ATTRIBUTES: INTENT(IN)
298 !
299 !:sdoc-:
300 !--------------------------------------------------------------------------------
301 
302  ELEMENTAL SUBROUTINE crtm_cloud_create( Cloud, n_Layers )
303  ! Arguments
304  TYPE(crtm_cloud_type), INTENT(OUT) :: cloud
305  INTEGER, INTENT(IN) :: n_layers
306  ! Local variables
307  INTEGER :: alloc_stat
308 
309  ! Check input
310  IF ( n_layers < 1 ) RETURN
311 
312  ! Perform the allocation
313  ALLOCATE( cloud%Effective_Radius( n_layers ), &
314  cloud%Effective_Variance( n_layers ), &
315  cloud%Water_Content( n_layers ), &
316  stat = alloc_stat )
317  IF ( alloc_stat /= 0 ) RETURN
318 
319  ! Initialise
320  ! ...Dimensions
321  cloud%Max_Layers = n_layers
322  cloud%n_Layers = n_layers
323  ! ...Arrays
324  cloud%Effective_Radius = zero
325  cloud%Effective_Variance = zero
326  cloud%Water_Content = zero
327 
328  ! Set allocation indicator
329  cloud%Is_Allocated = .true.
330 
331  END SUBROUTINE crtm_cloud_create
332 
333 
334 !--------------------------------------------------------------------------------
335 !:sdoc+:
336 !
337 ! NAME:
338 ! CRTM_Cloud_AddLayerCopy
339 !
340 ! PURPOSE:
341 ! Elemental function to copy an instance of the CRTM Cloud object
342 ! with additional layers added to the TOA of the input.
343 !
344 ! CALLING SEQUENCE:
345 ! cld_out = CRTM_Cloud_AddLayerCopy( cld, n_Added_Layers )
346 !
347 ! OBJECTS:
348 ! cld: Cloud structure to copy.
349 ! UNITS: N/A
350 ! TYPE: CRTM_Cloud_type
351 ! DIMENSION: Scalar or any rank
352 ! ATTRIBUTES: INTENT(OUT)
353 !
354 ! INPUTS:
355 ! n_Added_Layers: Number of layers to add to the function result.
356 ! UNITS: N/A
357 ! TYPE: INTEGER
358 ! DIMENSION: Same as Cloud object
359 ! ATTRIBUTES: INTENT(IN)
360 !
361 ! FUNCTION RESULT:
362 ! cld_out: Copy of the input Cloud structure with space for
363 ! extra layers added to TOA.
364 ! UNITS: N/A
365 ! TYPE: CRTM_Cloud_type
366 ! DIMENSION: Same as input.
367 ! ATTRIBUTES: INTENT(OUT)
368 !
369 !
370 !:sdoc-:
371 !--------------------------------------------------------------------------------
372 
373  ELEMENTAL FUNCTION crtm_cloud_addlayercopy( &
374  cld, &
375  n_Added_Layers ) &
376  result( cld_out )
377  ! Arguments
378  TYPE(crtm_cloud_type), INTENT(IN) :: cld
379  INTEGER, INTENT(IN) :: n_added_layers
380  ! Function result
381  TYPE(crtm_cloud_type) :: cld_out
382  ! Local variables
383  INTEGER :: na, no, nt
384 
385  ! Set the number of extra layers
386  na = max(n_added_layers,0)
387 
388  ! Create the output structure
389  CALL crtm_cloud_create( cld_out, &
390  cld%n_Layers+na )
391  IF ( .NOT. crtm_cloud_associated(cld_out) ) RETURN
392 
393  ! Assign data
394  cld_out%n_Added_Layers = cld%n_Added_Layers+na
395  ! ...Layer independent data
396  cld_out%Type = cld%Type
397  ! ...Layer dependent data
398  no = cld%n_Layers
399  nt = cld_out%n_Layers
400  cld_out%Effective_Radius(na+1:nt) = cld%Effective_Radius(1:no)
401  cld_out%Effective_Variance(na+1:nt) = cld%Effective_Variance(1:no)
402  cld_out%Water_Content(na+1:nt) = cld%Water_Content(1:no)
403 
404  END FUNCTION crtm_cloud_addlayercopy
405 
406 
407 !--------------------------------------------------------------------------------
408 !:sdoc+:
409 !
410 ! NAME:
411 ! CRTM_Cloud_Zero
412 !
413 ! PURPOSE:
414 ! Elemental subroutine to zero out the data arrays in a CRTM Cloud object.
415 !
416 ! CALLING SEQUENCE:
417 ! CALL CRTM_Cloud_Zero( Cloud )
418 !
419 ! OBJECTS:
420 ! Cloud: CRTM Cloud structure in which the data arrays are
421 ! to be zeroed out.
422 ! UNITS: N/A
423 ! TYPE: CRTM_Cloud_type
424 ! DIMENSION: Scalar or any rank
425 ! ATTRIBUTES: INTENT(IN OUT)
426 !
427 ! COMMENTS:
428 ! - The dimension components of the structure are *NOT* set to zero.
429 ! - The cloud type component is *NOT* reset.
430 !
431 !:sdoc-:
432 !--------------------------------------------------------------------------------
433 
434  ELEMENTAL SUBROUTINE crtm_cloud_zero( Cloud )
435  TYPE(crtm_cloud_type), INTENT(IN OUT) :: cloud
436  ! Do nothing if structure is unused
437  IF ( .NOT. crtm_cloud_associated(cloud) ) RETURN
438  ! Only zero out the data arrays
439  cloud%Effective_Radius = zero
440  cloud%Effective_Variance = zero
441  cloud%Water_Content = zero
442  END SUBROUTINE crtm_cloud_zero
443 
444 
445 !--------------------------------------------------------------------------------
446 !:sdoc+:
447 !
448 ! NAME:
449 ! CRTM_Cloud_IsValid
450 !
451 ! PURPOSE:
452 ! Non-pure function to perform some simple validity checks on a
453 ! CRTM Cloud object.
454 !
455 ! If invalid data is found, a message is printed to stdout.
456 !
457 ! CALLING SEQUENCE:
458 ! result = CRTM_Cloud_IsValid( cloud )
459 !
460 ! or
461 !
462 ! IF ( CRTM_Cloud_IsValid( cloud ) ) THEN....
463 !
464 ! OBJECTS:
465 ! cloud: CRTM Cloud object which is to have its
466 ! contents checked.
467 ! UNITS: N/A
468 ! TYPE: CRTM_Cloud_type
469 ! DIMENSION: Scalar
470 ! ATTRIBUTES: INTENT(IN)
471 !
472 ! FUNCTION RESULT:
473 ! result: Logical variable indicating whether or not the input
474 ! passed the check.
475 ! If == .FALSE., Cloud object is unused or contains
476 ! invalid data.
477 ! == .TRUE., Cloud object can be used in CRTM.
478 ! UNITS: N/A
479 ! TYPE: LOGICAL
480 ! DIMENSION: Scalar
481 !
482 !:sdoc-:
483 !--------------------------------------------------------------------------------
484 
485  FUNCTION crtm_cloud_isvalid( Cloud ) RESULT( IsValid )
486  TYPE(crtm_cloud_type), INTENT(IN) :: cloud
487  LOGICAL :: isvalid
488  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_Cloud_IsValid'
489  CHARACTER(ML) :: msg
490 
491  ! Setup
492  isvalid = .false.
493  ! ...Check if structure is used
494  IF ( .NOT. crtm_cloud_associated(cloud) ) THEN
495  msg = 'Cloud structure not allocated'
496  CALL display_message( routine_name, trim(msg), information )
497  RETURN
498  ENDIF
499  IF ( cloud%n_Layers < 1 ) THEN
500  msg = 'Cloud structure dimension invalid'
501  CALL display_message( routine_name, trim(msg), information )
502  RETURN
503  ENDIF
504 
505  ! Check data
506  ! ...Change default so all entries can be checked
507  isvalid = .true.
508  ! ...The type of cloud
509  IF ( cloud%Type < 1 .OR. cloud%Type > n_valid_cloud_categories ) THEN
510  msg = 'Invalid cloud type'
511  CALL display_message( routine_name, trim(msg), information )
512  isvalid = .false.
513  ENDIF
514  ! ...Data limits. Only checking negative values
515  IF ( any(cloud%Effective_Radius < zero ) ) THEN
516  msg = 'Negative cloud effective radius found'
517  CALL display_message( routine_name, trim(msg), information )
518  isvalid = .false.
519  ENDIF
520  IF ( any(cloud%Effective_Variance < zero ) ) THEN
521  msg = 'Negative cloud effective variance found'
522  CALL display_message( routine_name, trim(msg), information )
523  isvalid = .false.
524  ENDIF
525  IF ( any(cloud%Water_Content < zero ) ) THEN
526  msg = 'Negative cloud water content found'
527  CALL display_message( routine_name, trim(msg), information )
528  isvalid = .false.
529  ENDIF
530 
531  END FUNCTION crtm_cloud_isvalid
532 
533 
534 !--------------------------------------------------------------------------------
535 !:sdoc+:
536 !
537 ! NAME:
538 ! CRTM_Cloud_Inspect
539 !
540 ! PURPOSE:
541 ! Subroutine to print the contents of a CRTM Cloud object to stdout.
542 !
543 ! CALLING SEQUENCE:
544 ! CALL CRTM_Cloud_Inspect( Cloud, Unit=unit )
545 !
546 ! INPUTS:
547 ! Cloud: CRTM Cloud object to display.
548 ! UNITS: N/A
549 ! TYPE: CRTM_Cloud_type
550 ! DIMENSION: Scalar, Rank-1, or Rank-2 array
551 ! ATTRIBUTES: INTENT(IN)
552 !
553 ! OPTIONAL INPUTS:
554 ! Unit: Unit number for an already open file to which the output
555 ! will be written.
556 ! If the argument is specified and the file unit is not
557 ! connected, the output goes to stdout.
558 ! UNITS: N/A
559 ! TYPE: INTEGER
560 ! DIMENSION: Scalar
561 ! ATTRIBUTES: INTENT(IN), OPTIONAL
562 !
563 !:sdoc-:
564 !--------------------------------------------------------------------------------
565 
566  SUBROUTINE scalar_inspect( Cloud, Unit )
567  TYPE(CRTM_Cloud_type), INTENT(IN) :: Cloud
568  INTEGER, OPTIONAL, INTENT(IN) :: Unit
569  ! Local variables
570  INTEGER :: fid
571 
572  ! Setup
573  fid = output_unit
574  IF ( PRESENT(unit) ) THEN
575  IF ( file_open(unit) ) fid = unit
576  END IF
577 
578 
579  WRITE(fid,'(1x,"CLOUD OBJECT")')
580  WRITE(fid,'(3x,"n_Layers :",1x,i0)') cloud%n_Layers
581  WRITE(fid,'(3x,"Category :",1x,a)') crtm_cloud_categoryname(cloud)
582  IF ( .NOT. crtm_cloud_associated(cloud) ) RETURN
583  WRITE(fid,'(3x,"Effective radius:")')
584  WRITE(fid,'(5(1x,es13.6,:))') cloud%Effective_Radius
585  WRITE(fid,'(3x,"Water content:")')
586  WRITE(fid,'(5(1x,es13.6,:))') cloud%Water_Content
587  END SUBROUTINE scalar_inspect
588 
589  SUBROUTINE rank1_inspect( Cloud, Unit )
590  TYPE(CRTM_Cloud_type), INTENT(IN) :: Cloud(:)
591  INTEGER, OPTIONAL, INTENT(IN) :: Unit
592  INTEGER :: fid
593  INTEGER :: i
594  fid = output_unit
595  IF ( PRESENT(unit) ) THEN
596  IF ( file_open(unit) ) fid = unit
597  END IF
598  DO i = 1, SIZE(cloud)
599  WRITE(fid, fmt='(1x,"RANK-1 INDEX:",i0," - ")', advance='NO') i
600  CALL scalar_inspect(cloud(i), unit=unit)
601  END DO
602  END SUBROUTINE rank1_inspect
603 
604  SUBROUTINE rank2_inspect( Cloud, Unit )
605  TYPE(CRTM_Cloud_type), INTENT(IN) :: Cloud(:,:)
606  INTEGER, OPTIONAL, INTENT(IN) :: Unit
607  INTEGER :: fid
608  INTEGER :: i, j
609  fid = output_unit
610  IF ( PRESENT(unit) ) THEN
611  IF ( file_open(unit) ) fid = unit
612  END IF
613  DO j = 1, SIZE(cloud,2)
614  DO i = 1, SIZE(cloud,1)
615  WRITE(fid, fmt='(1x,"RANK-2 INDEX:",i0,",",i0," - ")', advance='NO') i,j
616  CALL scalar_inspect(cloud(i,j), unit=unit)
617  END DO
618  END DO
619  END SUBROUTINE rank2_inspect
620 
621 
622 !--------------------------------------------------------------------------------
623 !:sdoc+:
624 !
625 ! NAME:
626 ! CRTM_Cloud_DefineVersion
627 !
628 ! PURPOSE:
629 ! Subroutine to return the module version information.
630 !
631 ! CALLING SEQUENCE:
632 ! CALL CRTM_Cloud_DefineVersion( Id )
633 !
634 ! OUTPUTS:
635 ! Id: Character string containing the version Id information
636 ! for the module.
637 ! UNITS: N/A
638 ! TYPE: CHARACTER(*)
639 ! DIMENSION: Scalar
640 ! ATTRIBUTES: INTENT(OUT)
641 !
642 !:sdoc-:
643 !--------------------------------------------------------------------------------
644 
645  SUBROUTINE crtm_cloud_defineversion( Id )
646  CHARACTER(*), INTENT(OUT) :: id
647  id = module_version_id
648  END SUBROUTINE crtm_cloud_defineversion
649 
650 
651 !------------------------------------------------------------------------------
652 !:sdoc+:
653 ! NAME:
654 ! CRTM_Cloud_Compare
655 !
656 ! PURPOSE:
657 ! Elemental function to compare two CRTM_Cloud objects to within
658 ! a user specified number of significant figures.
659 !
660 ! CALLING SEQUENCE:
661 ! is_comparable = CRTM_Cloud_Compare( x, y, n_SigFig=n_SigFig )
662 !
663 ! OBJECTS:
664 ! x, y: Two CRTM Cloud objects to be compared.
665 ! UNITS: N/A
666 ! TYPE: CRTM_Cloud_type
667 ! DIMENSION: Scalar or any rank
668 ! ATTRIBUTES: INTENT(IN)
669 !
670 ! OPTIONAL INPUTS:
671 ! n_SigFig: Number of significant figure to compare floating point
672 ! components.
673 ! UNITS: N/A
674 ! TYPE: INTEGER
675 ! DIMENSION: Scalar or same as input
676 ! ATTRIBUTES: INTENT(IN), OPTIONAL
677 !
678 ! FUNCTION RESULT:
679 ! is_equal: Logical value indicating whether the inputs are equal.
680 ! UNITS: N/A
681 ! TYPE: LOGICAL
682 ! DIMENSION: Same as inputs.
683 !:sdoc-:
684 !------------------------------------------------------------------------------
685 
686  ELEMENTAL FUNCTION crtm_cloud_compare( &
687  x, &
688  y, &
689  n_SigFig ) &
690  result( is_comparable )
691  TYPE(crtm_cloud_type), INTENT(IN) :: x, y
692  INTEGER, OPTIONAL, INTENT(IN) :: n_sigfig
693  LOGICAL :: is_comparable
694  ! Variables
695  INTEGER :: n
696 
697  ! Set up
698  is_comparable = .false.
699  IF ( PRESENT(n_sigfig) ) THEN
700  n = abs(n_sigfig)
701  ELSE
702  n = default_n_sigfig
703  END IF
704 
705  ! Check the structure association status
706  IF ( (.NOT. crtm_cloud_associated(x)) .OR. &
707  (.NOT. crtm_cloud_associated(y)) ) RETURN
708 
709  ! Check scalars
710  IF ( (x%n_Layers /= y%n_Layers) .OR. &
711  (x%Type /= y%Type ) ) RETURN
712 
713  ! Check arrays
714  IF ( (.NOT. all(compares_within_tolerance(x%Effective_Radius ,y%Effective_Radius ,n))) .OR. &
715  (.NOT. all(compares_within_tolerance(x%Effective_Variance,y%Effective_Variance,n))) .OR. &
716  (.NOT. all(compares_within_tolerance(x%Water_Content ,y%Water_Content ,n))) ) RETURN
717 
718  ! If we get here, the structures are comparable
719  is_comparable = .true.
720 
721  END FUNCTION crtm_cloud_compare
722 
723 
724 !--------------------------------------------------------------------------------
725 !:sdoc+:
726 !
727 ! NAME:
728 ! CRTM_Cloud_SetLayers
729 !
730 ! PURPOSE:
731 ! Elemental subroutine to set the working number of layers to use
732 ! in a CRTM Cloud object.
733 !
734 ! CALLING SEQUENCE:
735 ! CALL CRTM_Cloud_SetLayers( Cloud, n_Layers )
736 !
737 ! OBJECT:
738 ! Cloud: CRTM Cloud object which is to have its working number
739 ! of layers updated.
740 ! UNITS: N/A
741 ! TYPE: CRTM_Cloud_type
742 ! DIMENSION: Scalar or any rank
743 ! ATTRIBUTES: INTENT(IN OUT)
744 !
745 ! INPUTS:
746 ! n_Layers: The value to set the n_Layers component of the
747 ! Cloud object.
748 ! UNITS: N/A
749 ! TYPE: CRTM_Cloud_type
750 ! DIMENSION: Conformable with the Cloud object argument
751 ! ATTRIBUTES: INTENT(IN)
752 !
753 ! COMMENTS:
754 ! - The object is zeroed upon output.
755 !
756 ! - If n_Layers <= Cloud%Max_Layers, then only the dimension value
757 ! of the object is changed.
758 !
759 ! - If n_Layers > Cloud%Max_Layers, then the object is reallocated
760 ! to the required number of layers.
761 !
762 !:sdoc-:
763 !--------------------------------------------------------------------------------
764 
765  ELEMENTAL SUBROUTINE crtm_cloud_setlayers( Cloud, n_Layers )
766  TYPE(crtm_cloud_type), INTENT(IN OUT) :: cloud
767  INTEGER, INTENT(IN) :: n_layers
768  IF ( n_layers < cloud%Max_Layers ) THEN
769  cloud%n_Layers = n_layers
770  CALL crtm_cloud_zero(cloud)
771  ELSE
772  CALL crtm_cloud_create( cloud, n_layers )
773  END IF
774  END SUBROUTINE crtm_cloud_setlayers
775 
776 
777 !------------------------------------------------------------------------------
778 !:sdoc+:
779 !
780 ! NAME:
781 ! CRTM_Cloud_InquireFile
782 !
783 ! PURPOSE:
784 ! Function to inquire CRTM Cloud object files.
785 !
786 ! CALLING SEQUENCE:
787 ! Error_Status = CRTM_Cloud_InquireFile( Filename , &
788 ! n_Clouds = n_Clouds )
789 !
790 ! INPUTS:
791 ! Filename: Character string specifying the name of a
792 ! CRTM Cloud data file to read.
793 ! UNITS: N/A
794 ! TYPE: CHARACTER(*)
795 ! DIMENSION: Scalar
796 ! ATTRIBUTES: INTENT(IN)
797 !
798 ! OPTIONAL OUTPUTS:
799 ! n_Clouds: The number of Cloud profiles in the data file.
800 ! UNITS: N/A
801 ! TYPE: INTEGER
802 ! DIMENSION: Scalar
803 ! ATTRIBUTES: OPTIONAL, INTENT(OUT)
804 !
805 ! FUNCTION RESULT:
806 ! Error_Status: The return value is an integer defining the error status.
807 ! The error codes are defined in the Message_Handler module.
808 ! If == SUCCESS, the file inquire was successful
809 ! == FAILURE, an unrecoverable error occurred.
810 ! UNITS: N/A
811 ! TYPE: INTEGER
812 ! DIMENSION: Scalar
813 !
814 !:sdoc-:
815 !------------------------------------------------------------------------------
816 
817  FUNCTION crtm_cloud_inquirefile( &
818  Filename, & ! Input
819  n_Clouds) & ! Optional output
820  result( err_stat )
821  ! Arguments
822  CHARACTER(*), INTENT(IN) :: filename
823  INTEGER , OPTIONAL, INTENT(OUT) :: n_clouds
824  ! Function result
825  INTEGER :: err_stat
826  ! Function parameters
827  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_Cloud_InquireFile'
828  ! Function variables
829  CHARACTER(ML) :: msg
830  CHARACTER(ML) :: io_msg
831  INTEGER :: io_stat
832  INTEGER :: fid
833  INTEGER :: nc
834 
835  ! Setup
836  err_stat = success
837 
838 
839  ! Open the cloud data file
840  err_stat = open_binary_file( filename, fid )
841  IF ( err_stat /= success ) THEN
842  msg = 'Error opening '//trim(filename)
843  CALL inquire_cleanup(); RETURN
844  END IF
845 
846 
847  ! Read the number of clouds dimension
848  READ( fid,iostat=io_stat,iomsg=io_msg ) nc
849  IF ( io_stat /= 0 ) THEN
850  msg = 'Error reading n_Clouds dimension from '//trim(filename)//' - '//trim(io_msg)
851  CALL inquire_cleanup(); RETURN
852  END IF
853 
854 
855  ! Close the file
856  CLOSE( fid,iostat=io_stat,iomsg=io_msg )
857  IF ( io_stat /= 0 ) THEN
858  msg = 'Error closing '//trim(filename)//' - '//trim(io_msg)
859  CALL inquire_cleanup(); RETURN
860  END IF
861 
862 
863  ! Set the return arguments
864  IF ( PRESENT(n_clouds) ) n_clouds = nc
865 
866  CONTAINS
867 
868  SUBROUTINE inquire_cleanup()
869  IF ( file_open(fid) ) THEN
870  CLOSE( fid,iostat=io_stat,iomsg=io_msg )
871  IF ( io_stat /= success ) &
872  msg = trim(msg)//'; Error closing input file during error cleanup - '//trim(io_msg)
873  END IF
874  err_stat = failure
875  CALL display_message( routine_name, msg, err_stat )
876  END SUBROUTINE inquire_cleanup
877 
878  END FUNCTION crtm_cloud_inquirefile
879 
880 
881 !------------------------------------------------------------------------------
882 !:sdoc+:
883 !
884 ! NAME:
885 ! CRTM_Cloud_ReadFile
886 !
887 ! PURPOSE:
888 ! Function to read CRTM Cloud object files.
889 !
890 ! CALLING SEQUENCE:
891 ! Error_Status = CRTM_Cloud_ReadFile( Filename , &
892 ! Cloud , &
893 ! Quiet = Quiet , &
894 ! No_Close = No_Close, &
895 ! n_Clouds = n_Clouds )
896 !
897 ! INPUTS:
898 ! Filename: Character string specifying the name of a
899 ! Cloud format data file to read.
900 ! UNITS: N/A
901 ! TYPE: CHARACTER(*)
902 ! DIMENSION: Scalar
903 ! ATTRIBUTES: INTENT(IN)
904 !
905 ! OUTPUTS:
906 ! Cloud: CRTM Cloud object array containing the Cloud data.
907 ! UNITS: N/A
908 ! TYPE: CRTM_Cloud_type
909 ! DIMENSION: Rank-1
910 ! ATTRIBUTES: INTENT(OUT), ALLOCATABLE
911 !
912 ! OPTIONAL INPUTS:
913 ! Quiet: Set this logical argument to suppress INFORMATION
914 ! messages being printed to stdout
915 ! If == .FALSE., INFORMATION messages are OUTPUT [DEFAULT].
916 ! == .TRUE., INFORMATION messages are SUPPRESSED.
917 ! If not specified, default is .FALSE.
918 ! UNITS: N/A
919 ! TYPE: LOGICAL
920 ! DIMENSION: Scalar
921 ! ATTRIBUTES: INTENT(IN), OPTIONAL
922 !
923 ! No_Close: Set this logical argument to NOT close the file upon exit.
924 ! If == .FALSE., the input file is closed upon exit [DEFAULT]
925 ! == .TRUE., the input file is NOT closed upon exit.
926 ! If not specified, default is .FALSE.
927 ! UNITS: N/A
928 ! TYPE: LOGICAL
929 ! DIMENSION: Scalar
930 ! ATTRIBUTES: INTENT(IN), OPTIONAL
931 !
932 ! OPTIONAL OUTPUTS:
933 ! n_Clouds: The actual number of cloud profiles read in.
934 ! UNITS: N/A
935 ! TYPE: INTEGER
936 ! DIMENSION: Scalar
937 ! ATTRIBUTES: OPTIONAL, INTENT(OUT)
938 !
939 ! FUNCTION RESULT:
940 ! Error_Status: The return value is an integer defining the error status.
941 ! The error codes are defined in the Message_Handler module.
942 ! If == SUCCESS, the file read was successful
943 ! == FAILURE, an unrecoverable error occurred.
944 ! UNITS: N/A
945 ! TYPE: INTEGER
946 ! DIMENSION: Scalar
947 !
948 !:sdoc-:
949 !------------------------------------------------------------------------------
950 
951  FUNCTION crtm_cloud_readfile( &
952  Filename, & ! Input
953  Cloud , & ! Output
954  Quiet , & ! Optional input
955  No_Close, & ! Optional input
956  n_Clouds, & ! Optional output
957  Debug ) & ! Optional input (Debug output control)
958  result( err_stat )
959  ! Arguments
960  CHARACTER(*), INTENT(IN) :: filename
961  TYPE(crtm_cloud_type) , ALLOCATABLE, INTENT(OUT) :: cloud(:)
962  LOGICAL, OPTIONAL, INTENT(IN) :: quiet
963  LOGICAL, OPTIONAL, INTENT(IN) :: no_close
964  INTEGER, OPTIONAL, INTENT(OUT) :: n_clouds
965  LOGICAL, OPTIONAL, INTENT(IN) :: debug
966  ! Function result
967  INTEGER :: err_stat
968  ! Function parameters
969  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_Cloud_ReadFile'
970  ! Function variables
971  CHARACTER(ML) :: msg
972  CHARACTER(ML) :: io_msg
973  CHARACTER(ML) :: alloc_msg
974  INTEGER :: io_stat
975  INTEGER :: alloc_stat
976  LOGICAL :: noisy
977  LOGICAL :: yes_close
978  INTEGER :: fid
979  INTEGER :: m
980  INTEGER :: nc
981 
982  ! Setup
983  err_stat = success
984  ! ...Check Quiet argument
985  noisy = .true.
986  IF ( PRESENT(quiet) ) noisy = .NOT. quiet
987  ! ...Check file close argument
988  yes_close = .true.
989  IF ( PRESENT(no_close) ) yes_close = .NOT. no_close
990  ! ...Override Quiet settings if debug set.
991  IF ( PRESENT(debug) ) noisy = debug
992 
993 
994  ! Check if the file is open
995  IF ( file_open( filename ) ) THEN
996  ! Yes, the file is already open
997  ! ...Get the file id
998  INQUIRE( file=filename,number=fid )
999  IF ( fid == -1 ) THEN
1000  msg = 'Error inquiring '//trim(filename)//' for its unit number'
1001  CALL read_cleanup(); RETURN
1002  END IF
1003  ELSE
1004  ! No, the file is not open
1005  ! ...Open the file
1006  err_stat = open_binary_file( filename, fid )
1007  IF ( err_stat /= success ) THEN
1008  msg = 'Error opening '//trim(filename)
1009  CALL read_cleanup(); RETURN
1010  END IF
1011  END IF
1012 
1013 
1014  ! Read the number of clouds dimension
1015  READ( fid,iostat=io_stat,iomsg=io_msg ) nc
1016  IF ( io_stat /= 0 ) THEN
1017  msg = 'Error reading n_Clouds data dimension from '//trim(filename)//' - '//trim(io_msg)
1018  CALL read_cleanup(); RETURN
1019  END IF
1020  ! ...Allocate the return structure array
1021  ALLOCATE(cloud(nc), stat=alloc_stat, errmsg=alloc_msg)
1022  IF ( alloc_stat /= 0 ) THEN
1023  msg = 'Error allocating Cloud array - '//trim(alloc_msg)
1024  CALL read_cleanup(); RETURN
1025  END IF
1026 
1027 
1028  ! Read the cloud data
1029  cloud_loop: DO m = 1, nc
1030  err_stat = read_record( fid, cloud(m) )
1031  IF ( err_stat /= success ) THEN
1032  WRITE( msg,'("Error reading Cloud element #",i0," from ",a)' ) m, trim(filename)
1033  CALL read_cleanup(); RETURN
1034  END IF
1035  END DO cloud_loop
1036 
1037 
1038  ! Close the file
1039  IF ( yes_close ) THEN
1040  CLOSE( fid,iostat=io_stat,iomsg=io_msg )
1041  IF ( io_stat /= 0 ) THEN
1042  msg = 'Error closing '//trim(filename)//' - '//trim(io_msg)
1043  CALL read_cleanup(); RETURN
1044  END IF
1045  END IF
1046 
1047 
1048  ! Set the optional return values
1049  IF ( PRESENT(n_clouds) ) n_clouds = nc
1050 
1051 
1052  ! Output an info message
1053  IF ( noisy ) THEN
1054  WRITE( msg,'("Number of clouds read from ",a,": ",i0)' ) trim(filename), nc
1055  CALL display_message( routine_name, msg, information )
1056  END IF
1057 
1058  CONTAINS
1059 
1060  SUBROUTINE read_cleanup()
1061  IF ( file_open(fid) ) THEN
1062  CLOSE( fid,iostat=io_stat,iomsg=io_msg )
1063  IF ( io_stat /= 0 ) &
1064  msg = trim(msg)//'; Error closing input file during error cleanup - '//trim(io_msg)
1065  END IF
1066  IF ( ALLOCATED(cloud) ) THEN
1067  DEALLOCATE(cloud, stat=alloc_stat, errmsg=alloc_msg)
1068  IF ( alloc_stat /= 0 ) &
1069  msg = trim(msg)//'; Error deallocating Cloud array during error cleanup - '//&
1070  trim(alloc_msg)
1071  END IF
1072  err_stat = failure
1073  CALL display_message( routine_name, msg, err_stat )
1074  END SUBROUTINE read_cleanup
1075 
1076  END FUNCTION crtm_cloud_readfile
1077 
1078 
1079 !------------------------------------------------------------------------------
1080 !:sdoc+:
1081 !
1082 ! NAME:
1083 ! CRTM_Cloud_WriteFile
1084 !
1085 ! PURPOSE:
1086 ! Function to write CRTM Cloud object files.
1087 !
1088 ! CALLING SEQUENCE:
1089 ! Error_Status = CRTM_Cloud_WriteFile( Filename , &
1090 ! Cloud , &
1091 ! Quiet = Quiet , &
1092 ! No_Close = No_Close )
1093 !
1094 ! INPUTS:
1095 ! Filename: Character string specifying the name of the
1096 ! Cloud format data file to write.
1097 ! UNITS: N/A
1098 ! TYPE: CHARACTER(*)
1099 ! DIMENSION: Scalar
1100 ! ATTRIBUTES: INTENT(IN)
1101 !
1102 ! Cloud: CRTM Cloud object array containing the Cloud data.
1103 ! UNITS: N/A
1104 ! TYPE: CRTM_Cloud_type
1105 ! DIMENSION: Rank-1
1106 ! ATTRIBUTES: INTENT(IN)
1107 !
1108 ! OPTIONAL INPUTS:
1109 ! Quiet: Set this logical argument to suppress INFORMATION
1110 ! messages being printed to stdout
1111 ! If == .FALSE., INFORMATION messages are OUTPUT [DEFAULT].
1112 ! == .TRUE., INFORMATION messages are SUPPRESSED.
1113 ! If not specified, default is .FALSE.
1114 ! UNITS: N/A
1115 ! TYPE: LOGICAL
1116 ! DIMENSION: Scalar
1117 ! ATTRIBUTES: INTENT(IN), OPTIONAL
1118 !
1119 ! No_Close: Set this logical argument to NOT close the file upon exit.
1120 ! If == .FALSE., the input file is closed upon exit [DEFAULT]
1121 ! == .TRUE., the input file is NOT closed upon exit.
1122 ! If not specified, default is .FALSE.
1123 ! UNITS: N/A
1124 ! TYPE: LOGICAL
1125 ! DIMENSION: Scalar
1126 ! ATTRIBUTES: INTENT(IN), OPTIONAL
1127 !
1128 ! FUNCTION RESULT:
1129 ! Error_Status: The return value is an integer defining the error status.
1130 ! The error codes are defined in the Message_Handler module.
1131 ! If == SUCCESS, the file write was successful
1132 ! == FAILURE, an unrecoverable error occurred.
1133 ! UNITS: N/A
1134 ! TYPE: INTEGER
1135 ! DIMENSION: Scalar
1136 !
1137 ! SIDE EFFECTS:
1138 ! - If the output file already exists, it is overwritten.
1139 ! - If an error occurs during *writing*, the output file is deleted before
1140 ! returning to the calling routine.
1141 !
1142 !:sdoc-:
1143 !------------------------------------------------------------------------------
1144 
1145  FUNCTION crtm_cloud_writefile( &
1146  Filename, & ! Input
1147  Cloud , & ! Input
1148  Quiet , & ! Optional input
1149  No_Close, & ! Optional input
1150  Debug ) & ! Optional input (Debug output control)
1151  result( err_stat )
1152  ! Arguments
1153  CHARACTER(*), INTENT(IN) :: filename
1154  TYPE(crtm_cloud_type) , INTENT(IN) :: cloud(:)
1155  LOGICAL, OPTIONAL, INTENT(IN) :: quiet
1156  LOGICAL, OPTIONAL, INTENT(IN) :: no_close
1157  LOGICAL, OPTIONAL, INTENT(IN) :: debug
1158  ! Function result
1159  INTEGER :: err_stat
1160  ! Function parameters
1161  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_Cloud_WriteFile'
1162  ! Function variables
1163  CHARACTER(ML) :: msg
1164  CHARACTER(ML) :: io_msg
1165  INTEGER :: io_stat
1166  LOGICAL :: noisy
1167  LOGICAL :: yes_close
1168  INTEGER :: fid
1169  INTEGER :: m, nc
1170 
1171  ! Setup
1172  err_stat = success
1173  ! ...Check Quiet argument
1174  noisy = .true.
1175  IF ( PRESENT(quiet) ) noisy = .NOT. quiet
1176  ! ...Check file close argument
1177  yes_close = .true.
1178  IF ( PRESENT(no_close) ) yes_close = .NOT. no_close
1179  ! ...Override Quiet settings if debug set.
1180  IF ( PRESENT(debug) ) noisy = debug
1181 
1182 
1183  ! Check the Cloud structure dimensions
1184  IF ( any(cloud%n_Layers < 1) ) THEN
1185  msg = 'Dimensions of Cloud structures are < or = 0.'
1186  CALL write_cleanup(); RETURN
1187  END IF
1188 
1189 
1190  ! Check if the file is open
1191  IF ( file_open( filename ) ) THEN
1192  ! Yes, the file is already open
1193  INQUIRE( file=filename,number=fid )
1194  IF ( fid == -1 ) THEN
1195  msg = 'Error inquiring '//trim(filename)//' for its unit number'
1196  CALL write_cleanup(); RETURN
1197  END IF
1198  ELSE
1199  ! No, the file is not open
1200  err_stat = open_binary_file( filename, fid, for_output = .true. )
1201  IF ( err_stat /= success ) THEN
1202  msg = 'Error opening '//trim(filename)
1203  CALL write_cleanup(); RETURN
1204  END IF
1205  END IF
1206 
1207 
1208  ! Write the number of clouds dimension
1209  nc = SIZE(cloud)
1210  WRITE( fid,iostat=io_stat,iomsg=io_msg ) nc
1211  IF ( io_stat /= 0 ) THEN
1212  msg = 'Error writing n_Clouds data dimension to '//trim(filename)//'- '//trim(io_msg)
1213  CALL write_cleanup(); RETURN
1214  END IF
1215 
1216 
1217  ! Write the cloud data
1218  cloud_loop: DO m = 1, nc
1219  err_stat = write_record( fid, cloud(m) )
1220  IF ( err_stat /= success ) THEN
1221  WRITE( msg,'("Error writing Cloud element #",i0," to ",a)' ) m, trim(filename)
1222  CALL write_cleanup(); RETURN
1223  END IF
1224  END DO cloud_loop
1225 
1226 
1227  ! Close the file (if error, no delete)
1228  IF ( yes_close ) THEN
1229  CLOSE( fid,status='KEEP',iostat=io_stat,iomsg=io_msg )
1230  IF ( io_stat /= 0 ) THEN
1231  msg = 'Error closing '//trim(filename)//'- '//trim(io_msg)
1232  CALL write_cleanup(); RETURN
1233  END IF
1234  END IF
1235 
1236 
1237  ! Output an info message
1238  IF ( noisy ) THEN
1239  WRITE( msg,'("Number of clouds written to ",a,": ",i0)' ) trim(filename), nc
1240  CALL display_message( routine_name, msg, information )
1241  END IF
1242 
1243  CONTAINS
1244 
1245  SUBROUTINE write_cleanup()
1246  IF ( file_open(fid) ) THEN
1247  CLOSE( fid,status=write_error_status,iostat=io_stat,iomsg=io_msg )
1248  IF ( io_stat /= 0 ) &
1249  msg = trim(msg)//'; Error deleting output file during error cleanup - '//trim(io_msg)
1250  END IF
1251  err_stat = failure
1252  CALL display_message( routine_name, msg, err_stat )
1253  END SUBROUTINE write_cleanup
1254 
1255  END FUNCTION crtm_cloud_writefile
1256 
1257 
1258 
1259 !##################################################################################
1260 !##################################################################################
1261 !## ##
1262 !## ## PRIVATE MODULE ROUTINES ## ##
1263 !## ##
1264 !##################################################################################
1265 !##################################################################################
1266 
1267 !------------------------------------------------------------------------------
1268 !
1269 ! NAME:
1270 ! CRTM_Cloud_Equal
1271 !
1272 ! PURPOSE:
1273 ! Elemental function to test the equality of two CRTM_Cloud objects.
1274 ! Used in OPERATOR(==) interface block.
1275 !
1276 ! CALLING SEQUENCE:
1277 ! is_equal = CRTM_Cloud_Equal( x, y )
1278 !
1279 ! or
1280 !
1281 ! IF ( x == y ) THEN
1282 ! ...
1283 ! END IF
1284 !
1285 ! OBJECTS:
1286 ! x, y: Two CRTM Cloud objects to be compared.
1287 ! UNITS: N/A
1288 ! TYPE: CRTM_Cloud_type
1289 ! DIMENSION: Scalar or any rank
1290 ! ATTRIBUTES: INTENT(IN)
1291 !
1292 ! FUNCTION RESULT:
1293 ! is_equal: Logical value indicating whether the inputs are equal.
1294 ! UNITS: N/A
1295 ! TYPE: LOGICAL
1296 ! DIMENSION: Same as inputs.
1297 !
1298 !------------------------------------------------------------------------------
1299 
1300  ELEMENTAL FUNCTION crtm_cloud_equal( x, y ) RESULT( is_equal )
1301  TYPE(crtm_cloud_type) , INTENT(IN) :: x, y
1302  LOGICAL :: is_equal
1303  ! Variables
1304  INTEGER :: n
1305 
1306  ! Set up
1307  is_equal = .false.
1308 
1309  ! Check the structure association status
1310  IF ( (.NOT. crtm_cloud_associated(x)) .OR. &
1311  (.NOT. crtm_cloud_associated(y)) ) RETURN
1312 
1313  ! Check contents
1314  ! ...Scalars
1315  IF ( (x%n_Layers /= y%n_Layers) .OR. (x%Type /= y%Type) ) RETURN
1316  ! ...Arrays
1317  n = x%n_Layers
1318  IF ( all(x%Effective_Radius(1:n) .equalto. y%Effective_Radius(1:n) ) .AND. &
1319  all(x%Effective_Variance(1:n) .equalto. y%Effective_Variance(1:n)) .AND. &
1320  all(x%Water_Content(1:n) .equalto. y%Water_Content(1:n) ) ) &
1321  is_equal = .true.
1322 
1323  END FUNCTION crtm_cloud_equal
1324 
1325 
1326 !--------------------------------------------------------------------------------
1327 !
1328 ! NAME:
1329 ! CRTM_Cloud_Add
1330 !
1331 ! PURPOSE:
1332 ! Pure function to add two CRTM Cloud objects.
1333 ! Used in OPERATOR(+) interface block.
1334 !
1335 ! CALLING SEQUENCE:
1336 ! cldsum = CRTM_Cloud_Add( cld1, cld2 )
1337 !
1338 ! or
1339 !
1340 ! cldsum = cld1 + cld2
1341 !
1342 !
1343 ! INPUTS:
1344 ! cld1, cld2: The Cloud objects to add.
1345 ! UNITS: N/A
1346 ! TYPE: CRTM_Cloud_type
1347 ! DIMENSION: Scalar or any rank
1348 ! ATTRIBUTES: INTENT(IN OUT)
1349 !
1350 ! RESULT:
1351 ! cldsum: Cloud structure containing the added components.
1352 ! UNITS: N/A
1353 ! TYPE: CRTM_Cloud_type
1354 ! DIMENSION: Same as input
1355 !
1356 !--------------------------------------------------------------------------------
1357 
1358  ELEMENTAL FUNCTION crtm_cloud_add( cld1, cld2 ) RESULT( cldsum )
1359  TYPE(crtm_cloud_type), INTENT(IN) :: cld1, cld2
1360  TYPE(crtm_cloud_type) :: cldsum
1361  ! Variables
1362  INTEGER :: n
1363 
1364  ! Check input
1365  ! ...If input structures not used, do nothing
1366  IF ( .NOT. crtm_cloud_associated( cld1 ) .OR. &
1367  .NOT. crtm_cloud_associated( cld2 ) ) RETURN
1368  ! ...If input structure for different clouds, or sizes, do nothing
1369  IF ( cld1%Type /= cld2%Type .OR. &
1370  cld1%n_Layers /= cld2%n_Layers .OR. &
1371  cld1%n_Added_Layers /= cld2%n_Added_Layers ) RETURN
1372 
1373  ! Copy the first structure
1374  cldsum = cld1
1375 
1376  ! And add its components to the second one
1377  n = cld1%n_Layers
1378  cldsum%Effective_Radius(1:n) = cldsum%Effective_Radius(1:n) + cld2%Effective_Radius(1:n)
1379  cldsum%Effective_Variance(1:n) = cldsum%Effective_Variance(1:n) + cld2%Effective_Variance(1:n)
1380  cldsum%Water_Content(1:n) = cldsum%Water_Content(1:n) + cld2%Water_Content(1:n)
1381 
1382  END FUNCTION crtm_cloud_add
1383 
1384 
1385 !--------------------------------------------------------------------------------
1386 !
1387 ! NAME:
1388 ! CRTM_Cloud_Subtract
1389 !
1390 ! PURPOSE:
1391 ! Pure function to subtract two CRTM Cloud objects.
1392 ! Used in OPERATOR(-) interface block.
1393 !
1394 ! CALLING SEQUENCE:
1395 ! clddiff = CRTM_Cloud_Subtract( cld1, cld2 )
1396 !
1397 ! or
1398 !
1399 ! clddiff = cld1 - cld2
1400 !
1401 !
1402 ! INPUTS:
1403 ! cld1, cld2: The Cloud objects to difference.
1404 ! UNITS: N/A
1405 ! TYPE: CRTM_Cloud_type
1406 ! DIMENSION: Scalar or any rank
1407 ! ATTRIBUTES: INTENT(IN OUT)
1408 !
1409 ! RESULT:
1410 ! clddiff: Cloud structure containing the differenced components.
1411 ! UNITS: N/A
1412 ! TYPE: CRTM_Cloud_type
1413 ! DIMENSION: Same as input
1414 !
1415 !--------------------------------------------------------------------------------
1416 
1417  ELEMENTAL FUNCTION crtm_cloud_subtract( cld1, cld2 ) RESULT( clddiff )
1418  TYPE(crtm_cloud_type), INTENT(IN) :: cld1, cld2
1419  TYPE(crtm_cloud_type) :: clddiff
1420  ! Variables
1421  INTEGER :: n
1422 
1423  ! Check input
1424  ! ...If input structures not used, do nothing
1425  IF ( .NOT. crtm_cloud_associated( cld1 ) .OR. &
1426  .NOT. crtm_cloud_associated( cld2 ) ) RETURN
1427  ! ...If input structure for different clouds, or sizes, do nothing
1428  IF ( cld1%Type /= cld2%Type .OR. &
1429  cld1%n_Layers /= cld2%n_Layers .OR. &
1430  cld1%n_Added_Layers /= cld2%n_Added_Layers ) RETURN
1431 
1432  ! Copy the first structure
1433  clddiff = cld1
1434 
1435  ! And subtract the second one's components from it
1436  n = cld1%n_Layers
1437  clddiff%Effective_Radius(1:n) = clddiff%Effective_Radius(1:n) - cld2%Effective_Radius(1:n)
1438  clddiff%Effective_Variance(1:n) = clddiff%Effective_Variance(1:n) - cld2%Effective_Variance(1:n)
1439  clddiff%Water_Content(1:n) = clddiff%Water_Content(1:n) - cld2%Water_Content(1:n)
1440 
1441  END FUNCTION crtm_cloud_subtract
1442 
1443 
1444 !
1445 ! NAME:
1446 ! Read_Record
1447 !
1448 ! PURPOSE:
1449 ! Utility function to read a single CRTM Cloud object in binary format
1450 !
1451 
1452  FUNCTION read_record( &
1453  fid , & ! Input
1454  cloud) & ! Output
1455  result( err_stat )
1456  ! Arguments
1457  INTEGER , INTENT(IN) :: fid
1458  TYPE(crtm_cloud_type) , INTENT(OUT) :: cloud
1459  ! Function result
1460  INTEGER :: err_stat
1461  ! Function parameters
1462  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_Cloud_ReadFile(Record)'
1463  ! Function variables
1464  CHARACTER(ML) :: msg
1465  CHARACTER(ML) :: io_msg
1466  INTEGER :: io_stat
1467  INTEGER :: n_layers
1468 
1469  ! Set up
1470  err_stat = success
1471 
1472 
1473  ! Read the dimensions
1474  READ( fid,iostat=io_stat,iomsg=io_msg ) n_layers
1475  IF ( io_stat /= 0 ) THEN
1476  msg = 'Error reading n_Layers dimension - '//trim(io_msg)
1477  CALL read_record_cleanup(); RETURN
1478  END IF
1479 
1480 
1481  ! Allocate the structure
1482  CALL crtm_cloud_create( cloud, n_layers )
1483  IF ( .NOT. crtm_cloud_associated( cloud ) ) THEN
1484  msg = 'Cloud object allocation failed.'
1485  CALL read_record_cleanup(); RETURN
1486  END IF
1487 
1488 
1489  ! Read the cloud data
1490  READ( fid,iostat=io_stat,iomsg=io_msg ) &
1491  cloud%Type, &
1492  cloud%Effective_Radius, &
1493  cloud%Effective_Variance, &
1494  cloud%Water_Content
1495  IF ( io_stat /= 0 ) THEN
1496  msg = 'Error reading Cloud data - '//trim(io_msg)
1497  CALL read_record_cleanup(); RETURN
1498  END IF
1499 
1500  CONTAINS
1501 
1502  SUBROUTINE read_record_cleanup()
1504  CLOSE( fid,iostat=io_stat,iomsg=io_msg )
1505  IF ( io_stat /= success ) &
1506  msg = trim(msg)//'; Error closing file during error cleanup - '//trim(io_msg)
1507  err_stat = failure
1508  CALL display_message( routine_name, msg, err_stat )
1509  END SUBROUTINE read_record_cleanup
1510 
1511  END FUNCTION read_record
1512 
1513 
1514 !
1515 ! NAME:
1516 ! Write_Record
1517 !
1518 ! PURPOSE:
1519 ! Function to write a single CRTM Cloud object in binary format
1520 !
1521 
1522  FUNCTION write_record( &
1523  fid , & ! Input
1524  cloud ) & ! Input
1525  result( err_stat )
1526  ! Arguments
1527  INTEGER , INTENT(IN) :: fid
1528  TYPE(crtm_cloud_type) , INTENT(IN) :: cloud
1529  ! Function result
1530  INTEGER :: err_stat
1531  ! Function parameters
1532  CHARACTER(*), PARAMETER :: routine_name = 'CRTM_Cloud_WriteFile(Record)'
1533  ! Function variables
1534  CHARACTER(ML) :: msg
1535  CHARACTER(ML) :: io_msg
1536  INTEGER :: io_stat
1537 
1538  ! Setup
1539  err_stat = success
1540  IF ( .NOT. crtm_cloud_associated( cloud ) ) THEN
1541  msg = 'Input Cloud object is not used.'
1542  CALL write_record_cleanup(); RETURN
1543  END IF
1544 
1545 
1546  ! Write the dimensions
1547  WRITE( fid,iostat=io_stat,iomsg=io_msg ) cloud%n_Layers
1548  IF ( io_stat /= 0 ) THEN
1549  msg = 'Error writing dimensions - '//trim(io_msg)
1550  CALL write_record_cleanup(); RETURN
1551  END IF
1552 
1553 
1554  ! Write the data
1555  WRITE( fid,iostat=io_stat,iomsg=io_msg ) &
1556  cloud%Type, &
1557  cloud%Effective_Radius(1:cloud%n_Layers), &
1558  cloud%Effective_Variance(1:cloud%n_Layers), &
1559  cloud%Water_Content(1:cloud%n_Layers)
1560  IF ( io_stat /= 0 ) THEN
1561  msg = 'Error writing Cloud data - '//trim(io_msg)
1562  CALL write_record_cleanup(); RETURN
1563  END IF
1564 
1565  CONTAINS
1566 
1567  SUBROUTINE write_record_cleanup()
1568  CLOSE( fid,status=write_error_status,iostat=io_stat,iomsg=io_msg )
1569  IF ( io_stat /= success ) &
1570  msg = trim(msg)//'; Error closing file during error cleanup'
1571  err_stat = failure
1572  CALL display_message( routine_name, trim(msg), err_stat )
1573  END SUBROUTINE write_record_cleanup
1574 
1575  END FUNCTION write_record
1576 
1577 END MODULE crtm_cloud_define
integer, parameter, public ice_cloud
integer, parameter, public n_valid_cloud_categories
real(fp), parameter one
integer, parameter ml
integer, parameter, public failure
pure integer function, public crtm_cloud_categoryid(cloud)
elemental type(crtm_cloud_type) function, public crtm_cloud_addlayercopy(cld, n_Added_Layers)
integer, parameter, public warning
integer function, public crtm_cloud_inquirefile(Filename, n_Clouds)
integer, parameter, public fp
Definition: Type_Kinds.f90:124
integer function, public crtm_cloud_readfile(Filename, Cloud, Quiet, No_Close, n_Clouds, Debug)
integer function, public readgatts_binary_file(fid, Write_Module, Created_On, Title, History, Comment)
integer, parameter, public rain_cloud
elemental subroutine, public crtm_cloud_create(Cloud, n_Layers)
integer function, public crtm_cloud_writefile(Filename, Cloud, Quiet, No_Close, Debug)
elemental logical function, public crtm_cloud_compare(x, y, n_SigFig)
integer, dimension(0:n_valid_cloud_categories), parameter cloud_category_list
subroutine scalar_inspect(Cloud, Unit)
subroutine inquire_cleanup()
integer, parameter, public invalid_cloud
Definition: cloud.F90:1
character(*), dimension(0:n_valid_cloud_categories), parameter, public cloud_category_name
character(*), parameter write_error_status
elemental type(crtm_cloud_type) function crtm_cloud_subtract(cld1, cld2)
elemental subroutine, public crtm_cloud_setlayers(Cloud, n_Layers)
integer function read_record(fid, cloud)
subroutine read_cleanup()
subroutine write_cleanup()
subroutine rank1_inspect(Cloud, Unit)
elemental subroutine, public crtm_cloud_zero(Cloud)
subroutine read_record_cleanup()
integer function, public open_binary_file(Filename, FileID, For_Output, No_Check)
recursive subroutine, public display_message(Routine_Name, Message, Error_State, Message_Log)
elemental type(crtm_cloud_type) function crtm_cloud_add(cld1, cld2)
integer, parameter, public snow_cloud
integer, parameter, public default_n_sigfig
integer function, public crtm_cloud_categorylist(list)
integer, parameter, public hail_cloud
character(*), parameter module_version_id
integer function, public writegatts_binary_file(fid, Write_Module, Created_On, Title, History, Comment)
integer, parameter, public graupel_cloud
subroutine write_record_cleanup()
#define max(a, b)
Definition: mosaic_util.h:33
elemental logical function crtm_cloud_equal(x, y)
subroutine, public crtm_cloud_defineversion(Id)
elemental subroutine, public crtm_cloud_destroy(Cloud)
logical function, public crtm_cloud_isvalid(Cloud)
pure character(len(cloud_category_name(1))) function, public crtm_cloud_categoryname(cloud)
integer, parameter, public water_cloud
subroutine rank2_inspect(Cloud, Unit)
integer, parameter, public success
real(fp), parameter zero
elemental logical function, public crtm_cloud_associated(Cloud)
integer, parameter, public information