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