diff --git a/Get_CRTM_Binary_Files.sh b/Get_CRTM_Binary_Files.sh index c772343..3a559f2 100755 --- a/Get_CRTM_Binary_Files.sh +++ b/Get_CRTM_Binary_Files.sh @@ -1,5 +1,4 @@ -#foldername="fix_REL-2.4.0" #rel 2.4.0 files -foldername="fix_REL-2.4.1_latest" +foldername="fix_REL-3.0.0_20230303" filename="${foldername}.tgz" if test -f "$filename"; then @@ -14,7 +13,7 @@ if test -f "$filename"; then else #download, untar, move echo "downloading $filename, please wait about 5 minutes (3.3 GB tar file)" - wget -q ftp://ftp.ssec.wisc.edu/pub/s4/CRTM/$filename # CRTM binary files + wget ftp://ftp.ssec.wisc.edu/pub/s4/CRTM/$filename # CRTM binary files, add "-q" to suppress output. tar -zxvf $filename mv $foldername fix echo "fix/ directory created from downloaded $filename." diff --git a/README.md b/README.md index 56f4079..f30f7ae 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -CRTM REL-2.4.1-alpha +CRTM REL-3.0.0 ==================== [![Build Status](https://app.travis-ci.com/JCSDA-internal/crtm.svg?token=r6aaq9P13fHcTi8yBgdM&branch=develop)](https://app.travis-ci.com/JCSDA-internal/crtm) @@ -6,12 +6,14 @@ CRTM REL-2.4.1-alpha Preamble -------- -CRTM v2.4.1-alpha release (`REL-2.4.1-alpha`) +CRTM v3.0.0 release (`REL-3.0.0`) -v2.4.1-alpha Released on April 1, 2021 +v3.0.0 Released March, 2023 +v2.4.1-alpha Released on April 1, 2021 (internal realease only) v2.4.0 Released on October 23, 2020 -This is an alpha release of CRTM v2.4.1, some features may not be fully functional. Contact crtm-support@googlegroups.com. +This is an experimental/early release of CRTM v3.0.0, some features may not be fully functional. Contact crtm-support@googlegroups.com. +v3.x features will be rolled out in incremental updates. Basic requirements: (1) A Fortran 2003 compatible compiler @@ -53,7 +55,7 @@ Contents Configuration, building, and testing the library ================================================ -JCSDA CRTM v2.4.x Build Instructions +JCSDA CRTM v3.0.x Build Instructions - Development Repository Build - Note: the development repository build differs from a release build. @@ -67,7 +69,7 @@ The CRTM **development** repository directory structure looks like: ├── NOTES ├── README.md ├── Set_CRTM_Environment.sh - ├── Uncompress_Binary_Files.sh (manually gunzip files in the fix/ directory after cloning) + ├── Get_CRTM_Binary_Files.sh ├── configuration/ ├── documentation/ ├── fix/ @@ -121,8 +123,9 @@ But after a clean clone of the development repository, none of the links to sour Configuration ------------- -Unlike version 2.4.0, the "`fix/`" directory is now provided in the CRTM via git-LFS. The files therein are gzipped (*.gz extension). -Uncompress_Binary_Files.sh script will traverse and gunzip all of the files. +At present, the 'fix/' directory is provided through ftp, rather than git-LFS. We're working on a way to make the process of getting binary data equitable and easy for all users. + +The files therein are gzipped (*.gz extension). Use the Get_CRTM_Binary_Files.sh script to obtain and unpack the dataset. At the top level (`crtm/`), the `configuration` directory contains the various compiler-specific configuration files.
@@ -244,10 +247,10 @@ make install Linking to the library ---------------------- -Let's assume the above install was moved into "/home/username/CRTM/crtm_v2.4.1/", to use the library in this structure in your own application, the usual environment variables would need to be be modified something like: +Let's assume the above install was moved into "/home/username/CRTM/crtm_v3.0.0/", to use the library in this structure in your own application, the usual environment variables would need to be be modified something like:-libroot="/home/username/CRTM/crtm_v2.4.1" +libroot="/home/username/CRTM/crtm_v3.0.0" FCFLAGS="-I${libroot}/include ${FCFLAGS}" LDFLAGS="-L${libroot}/lib ${LDFLAGS}" LIBS="-lcrtm ${LIBS}" @@ -260,11 +263,11 @@ To uninstall the library (assuming you haven't moved the installation directory make uninstall -This will DELETE the created installation directory. So, for a library version, say, v2.4.1, if your configure script invocation was something like +This will DELETE the created installation directory. So, for a library version, say, v3.0.0, if your configure script invocation was something like ./configure --prefix=${PWD} ...other command line arguments... -then the "uninstall" target will delete the "${PWD}/crtm_v2.4.1" directory. +then the "uninstall" target will delete the "${PWD}/crtm_v3.0.0" directory. Cleaning Up @@ -311,13 +314,13 @@ make install **Additional options for `configure`** -`configure` sets an install path environment variable, among other things. This, by default, will set the `lib/` and `include/` directory paths in the `/usr/local/crtm_v2.4.1/` (or whatever string in in `src/CRTM_Version.inc`). +`configure` sets an install path environment variable, among other things. This, by default, will set the `lib/` and `include/` directory paths in the `/usr/local/crtm_v3.0.0/` (or whatever string in in `src/CRTM_Version.inc`). The `--prefix` switch sets the installation directory, make sure you have write access to that directory. You can override this by setting a different install directory as follows: ` ./configure --prefix=` -For example, `./configure --prefix=${PWD}` will create the library in the directory in which you're currently in (e.g., crtm/src/Build/crtm_v2.4.1/). +For example, `./configure --prefix=${PWD}` will create the library in the directory in which you're currently in (e.g., crtm/src/Build/crtm_v3.0.0y/). By default, the CRTM is built for big-endian I/O. The --disable-big-endian switch builds the library and test programs for little-endian I/O: diff --git a/README_JEDI.md b/README_JEDI.md index 29c45dc..4d4e47b 100644 --- a/README_JEDI.md +++ b/README_JEDI.md @@ -1,21 +1,21 @@ README_JEDI.md -CRTM REL-2.4.1-alpha +CRTM REL-3.0.0 Released April 1, 2021 The README.md file contains a lot of general information about this repository and the legacy build system based on autotools. -CRTM REL-2.4.1-alpha JEDI environment build instructions +CRTM REL-3.0.0 JEDI environment build instructions ========================================================= Preamble -------- -CRTM v2.4.1-alpha release (`REL-2.4.1-alpha`) +CRTM v3.0.0-alpha release (`REL-3.0.0`) -This is a fully functional release of CRTM v2.4.1-alpha. +This is a fully functional release of CRTM v3.0.0-alpha. Basic requirements: (1) A Fortran 2003 compatible compiler. @@ -50,7 +50,7 @@ Contents Configuration, building, and testing the library ================================================ -JCSDA CRTM v2.4.x Build Instructions +JCSDA CRTM v3.0.0 Build Instructions The CRTM **development** repository directory structure looks like: @@ -61,7 +61,7 @@ The CRTM **development** repository directory structure looks like: ├── NOTES ├── README.md ├── Set_CRTM_Environment.sh - ├── Uncompress_Binary_Files.sh (uncompresses files in the fix/ directory "manually") + ├── Get_CRTM_Binary_Files.sh (downloads the "fix" directory binary data from ftp, this is useful if you're doing out-of-jedi tests or if you want to override the default binary datasets. ) ├── CMakeLists.txt (top-level configuration file for ecbuild) ├── configuration/ ├── documentation/ @@ -109,7 +109,8 @@ In the above list, the directories highlighted in bold (bold in markdown), are t JEDI Configuration ------------------ -As of v2.4.1-alpha, the "`fix/`" directory is provided in the CRTM by git LFS. It needs to be uncompressed by running the Uncompress_Binary_Files.sh +As of v3.0.0, binary data is obtained during the ecbuild step, it downloads a tarball from UCAR's GDEX service and unpacks it. see `test/CMakeLists.txt`. + **Configuration** git clone https://github.com/JCSDA/crtm (you've probably done this already) diff --git a/Uncompress_Binary_Files.sh b/Uncompress_Binary_Files.sh deleted file mode 100644 index a557ef8..0000000 --- a/Uncompress_Binary_Files.sh +++ /dev/null @@ -1,5 +0,0 @@ -# after a new clone of the repository, the binary LFS-stored files are in gzip format (*.gz) -# this script traverses the fix/ directory and uncompresses all of the binary and netCDF files. -# If you're making change to binary files, please add them to LFS in gzipped format. - -find ./fix/ -name "*.gz" -type f -exec gunzip -fv {} \; diff --git a/src/Atmosphere/CRTM_Atmosphere_Define.f90 b/src/Atmosphere/CRTM_Atmosphere_Define.f90 index c119a39..ccf7042 100644 --- a/src/Atmosphere/CRTM_Atmosphere_Define.f90 +++ b/src/Atmosphere/CRTM_Atmosphere_Define.f90 @@ -11,8 +11,10 @@ ! Modified by Yingtao Ma, 2020/6/11 ! yingtao.ma@noaa.gov ! Implemented CMAQ aerosol +! Modified by: Cheng Dang, 17-Aug-2022 +! dangch@ucar.edu +! Add relative humidity calculation ! - MODULE CRTM_Atmosphere_Define ! ----------------- @@ -80,6 +82,8 @@ MODULE CRTM_Atmosphere_Define CRTM_Aerosol_SetLayers, & CRTM_Aerosol_ReadFile, & CRTM_Aerosol_WriteFile + USE CRTM_Relative_Humidity, ONLY: PPMV_to_MR, MR_to_RH + ! Disable implicit typing IMPLICIT NONE @@ -342,7 +346,6 @@ MODULE CRTM_Atmosphere_Define ! File status on close after write error CHARACTER(*), PARAMETER :: WRITE_ERROR_STATUS = 'DELETE' - ! ------------------------------- ! Atmosphere structure definition ! ------------------------------- @@ -794,12 +797,12 @@ ELEMENTAL SUBROUTINE CRTM_Atmosphere_Zero( Atmosphere ) IF ( .NOT. CRTM_Atmosphere_Associated(Atmosphere) ) RETURN ! Zero out the data - Atmosphere%Level_Pressure = ZERO - Atmosphere%Pressure = ZERO - Atmosphere%Temperature = ZERO + Atmosphere%Level_Pressure = ZERO + Atmosphere%Pressure = ZERO + Atmosphere%Temperature = ZERO Atmosphere%Relative_Humidity = ZERO - Atmosphere%Absorber = ZERO - Atmosphere%Cloud_Fraction = ZERO + Atmosphere%Absorber = ZERO + Atmosphere%Cloud_Fraction = ZERO ! Reset the structure components IF ( Atmosphere%n_Clouds > 0 ) CALL CRTM_Cloud_Zero( Atmosphere%Cloud ) @@ -925,8 +928,8 @@ FUNCTION CRTM_Atmosphere_IsValid( Atm ) RESULT( IsValid ) CALL Display_Message( ROUTINE_NAME, msg, INFORMATION ) IsValid = .FALSE. ENDIF - IF ( ANY(Atm%Relative_Humidity < ZERO ) ) THEN - msg = 'Negative layer relative humidity found' + IF ( ANY(Atm%Relative_Humidity < ZERO ) .OR. ANY(Atm%Relative_Humidity > 1.2_fp ) ) THEN + msg = 'Invalid layer relative humidity found' CALL Display_Message( ROUTINE_NAME, msg, INFORMATION ) IsValid = .FALSE. ENDIF @@ -1030,7 +1033,7 @@ SUBROUTINE Scalar_Inspect( Atm, Unit ) WRITE(fid, '(3x,"Layer pressure:")') WRITE(fid, '(5(1x,es22.15,:))') Atm%Pressure(1:k) WRITE(fid, '(3x,"Layer temperature:")') - WRITE(fid, '(5(1x,es22.15,:))') Atm%Temperature(1:k) + WRITE(fid, '(5(1x,es22.15,:))') Atm%Temperature(1:k) WRITE(fid, '(3x,"Layer relative humidity:")') WRITE(fid, '(5(1x,es22.15,:))') Atm%Relative_Humidity(1:k) WRITE(fid, '(3x,"Layer absorber:")') @@ -1115,7 +1118,6 @@ END SUBROUTINE Rank2_Inspect !-------------------------------------------------------------------------------- ELEMENTAL FUNCTION CRTM_Atmosphere_Compare( & -! FUNCTION CRTM_Atmosphere_Compare( & x, & y, & n_SigFig ) & @@ -1153,31 +1155,27 @@ ELEMENTAL FUNCTION CRTM_Atmosphere_Compare( & j = x%n_Absorbers IF ( ANY(x%Absorber_ID(1:j) /= y%Absorber_ID(1:j) ) .OR. & ANY(x%Absorber_Units(1:j) /= y%Absorber_Units(1:j)) ) RETURN - ! ...Floating point arrays - IF ( (.NOT. ALL(Compares_Within_Tolerance(x%Level_Pressure,y%Level_Pressure,n))) .OR. & - (.NOT. ALL(Compares_Within_Tolerance(x%Pressure ,y%Pressure ,n))) .OR. & - (.NOT. ALL(Compares_Within_Tolerance(x%Temperature ,y%Temperature ,n))) .OR. & - (.NOT. ALL(Compares_Within_Tolerance(x%Relative_Humidity ,y%Relative_Humidity ,n))) .OR. & - (.NOT. ALL(Compares_Within_Tolerance(x%Absorber ,y%Absorber ,n))) .OR. & - (.NOT. ALL(Compares_Within_Tolerance(x%Cloud_Fraction,y%Cloud_Fraction,n)))) RETURN + IF ( (.NOT. ALL(Compares_Within_Tolerance(x%Level_Pressure ,y%Level_Pressure ,n))) .OR. & + (.NOT. ALL(Compares_Within_Tolerance(x%Pressure ,y%Pressure ,n))) .OR. & + (.NOT. ALL(Compares_Within_Tolerance(x%Temperature ,y%Temperature ,n))) .OR. & + (.NOT. ALL(Compares_Within_Tolerance(x%Relative_Humidity ,y%Relative_Humidity ,n))) .OR. & + (.NOT. ALL(Compares_Within_Tolerance(x%Absorber ,y%Absorber ,n))) .OR. & + (.NOT. ALL(Compares_Within_Tolerance(x%Cloud_Fraction ,y%Cloud_Fraction ,n)))) RETURN ! ...Clouds - IF ( x%n_Clouds > 0 ) THEN IF ( .NOT. ALL(CRTM_Cloud_Compare(x%Cloud,y%Cloud,n_SigFig=n)) ) RETURN - END IF ! ...Aerosols IF ( x%n_Aerosols > 0 ) THEN IF ( .NOT. ALL(CRTM_Aerosol_Compare(x%Aerosol,y%Aerosol,n_SigFig=n)) ) RETURN - END IF END IF ! If we get here, the objects are comparable is_comparable = .TRUE. + END FUNCTION CRTM_Atmosphere_Compare -! END FUNCTION CRTM_Atmosphere_Compare !-------------------------------------------------------------------------------- @@ -2146,14 +2144,14 @@ ELEMENTAL FUNCTION CRTM_Atmosphere_Equal( x, y ) RESULT( is_equal ) IF ( CRTM_Atmosphere_Associated(x) .AND. CRTM_Atmosphere_Associated(y) ) THEN k = x%n_Layers j = x%n_Absorbers - IF ( .NOT. (ALL(x%Absorber_ID(1:j) == y%Absorber_ID(1:j) ) .AND. & - ALL(x%Absorber_Units(1:j) == y%Absorber_Units(1:j)) .AND. & - ALL(x%Level_Pressure(0:k) .EqualTo. y%Level_Pressure(0:k)) .AND. & - ALL(x%Pressure(1:k) .EqualTo. y%Pressure(1:k) ) .AND. & - ALL(x%Temperature(1:k) .EqualTo. y%Temperature(1:k) ) .AND. & - ALL(x%Relative_Humidity(1:k) .EqualTo. y%Relative_Humidity(1:k) ) .AND. & - ALL(x%Absorber(1:k,1:j) .EqualTo. y%Absorber(1:k,1:j) ) .AND. & - ALL(x%Cloud_Fraction(1:k) .EqualTo. y%Cloud_Fraction(1:k))) ) RETURN + IF ( .NOT. (ALL(x%Absorber_ID(1:j) == y%Absorber_ID(1:j) ) .AND. & + ALL(x%Absorber_Units(1:j) == y%Absorber_Units(1:j)) .AND. & + ALL(x%Level_Pressure(0:k) .EqualTo. y%Level_Pressure(0:k)) .AND. & + ALL(x%Pressure(1:k) .EqualTo. y%Pressure(1:k) ) .AND. & + ALL(x%Temperature(1:k) .EqualTo. y%Temperature(1:k) ) .AND. & + ALL(x%Relative_Humidity(1:k) .EqualTo. y%Relative_Humidity(1:k)) .AND. & + ALL(x%Absorber(1:k,1:j) .EqualTo. y%Absorber(1:k,1:j) ) .AND. & + ALL(x%Cloud_Fraction(1:k) .EqualTo. y%Cloud_Fraction(1:k))) ) RETURN ! ...Clouds IF ( x%n_Clouds > 0 ) THEN IF ( .NOT. ALL(x%Cloud == y%Cloud) ) RETURN @@ -2272,12 +2270,12 @@ ELEMENTAL FUNCTION CRTM_Atmosphere_Add( atm1, atm2 ) RESULT( atmsum ) ! And add its components to the second one k = atm1%n_Layers j = atm1%n_Absorbers - atmsum%Level_Pressure(0:k) = atmsum%Level_Pressure(0:k) + atm2%Level_Pressure(0:k) - atmsum%Pressure(1:k) = atmsum%Pressure(1:k) + atm2%Pressure(1:k) - atmsum%Temperature(1:k) = atmsum%Temperature(1:k) + atm2%Temperature(1:k) - atmsum%Relative_Humidity(1:k) = atmsum%Relative_Humidity(1:k) + atm2%Relative_Humidity(1:k) - atmsum%Absorber(1:k,1:j) = atmsum%Absorber(1:k,1:j) + atm2%Absorber(1:k,1:j) - atmsum%Cloud_Fraction(1:k) = atmsum%Cloud_Fraction(1:k) + atm2%Cloud_Fraction(1:k) + atmsum%Level_Pressure(0:k) = atmsum%Level_Pressure(0:k) + atm2%Level_Pressure(0:k) + atmsum%Pressure(1:k) = atmsum%Pressure(1:k) + atm2%Pressure(1:k) + atmsum%Temperature(1:k) = atmsum%Temperature(1:k) + atm2%Temperature(1:k) + atmsum%Relative_Humidity(1:k) = atmsum%Relative_Humidity(1:k) + atm2%Relative_Humidity(1:k) + atmsum%Absorber(1:k,1:j) = atmsum%Absorber(1:k,1:j) + atm2%Absorber(1:k,1:j) + atmsum%Cloud_Fraction(1:k) = atmsum%Cloud_Fraction(1:k) + atm2%Cloud_Fraction(1:k) ! ...Cloud component IF ( atm1%n_Clouds > 0 ) THEN DO i = 1, atm1%n_Clouds @@ -2354,12 +2352,12 @@ ELEMENTAL FUNCTION CRTM_Atmosphere_Subtract( atm1, atm2 ) RESULT( atmdiff ) ! And subtract the second one's components from it k = atm1%n_Layers j = atm1%n_Absorbers - atmdiff%Level_Pressure(0:k) = atmdiff%Level_Pressure(0:k) - atm2%Level_Pressure(0:k) - atmdiff%Pressure(1:k) = atmdiff%Pressure(1:k) - atm2%Pressure(1:k) - atmdiff%Temperature(1:k) = atmdiff%Temperature(1:k) - atm2%Temperature(1:k) - atmdiff%Relative_Humidity(1:k) = atmdiff%Relative_Humidity(1:k) - atm2%Relative_Humidity(1:k) - atmdiff%Absorber(1:k,1:j) = atmdiff%Absorber(1:k,1:j) - atm2%Absorber(1:k,1:j) - atmdiff%Cloud_Fraction(1:k) = atmdiff%Cloud_Fraction(1:k) - atm2%Cloud_Fraction(1:k) + atmdiff%Level_Pressure(0:k) = atmdiff%Level_Pressure(0:k) - atm2%Level_Pressure(0:k) + atmdiff%Pressure(1:k) = atmdiff%Pressure(1:k) - atm2%Pressure(1:k) + atmdiff%Temperature(1:k) = atmdiff%Temperature(1:k) - atm2%Temperature(1:k) + atmdiff%Relative_Humidity(1:k) = atmdiff%Relative_Humidity(1:k) - atm2%Relative_Humidity(1:k) + atmdiff%Absorber(1:k,1:j) = atmdiff%Absorber(1:k,1:j) - atm2%Absorber(1:k,1:j) + atmdiff%Cloud_Fraction(1:k) = atmdiff%Cloud_Fraction(1:k) - atm2%Cloud_Fraction(1:k) ! ...Cloud component IF ( atm1%n_Clouds > 0 ) THEN DO i = 1, atm1%n_Clouds @@ -2409,6 +2407,7 @@ FUNCTION Read_Record( & INTEGER :: n_clouds INTEGER :: n_aerosols + ! Set up err_stat = SUCCESS @@ -2453,8 +2452,7 @@ FUNCTION Read_Record( & atm%Level_Pressure, & atm%Pressure, & atm%Temperature, & -!qliu atm%Relative_Humidity, & - atm%Relative_Humidity, & + !atm%Relative_Humidity, & ! RH APPROACH #1 atm%Absorber, & atm%Cloud_Fraction IF ( io_stat /= 0 ) THEN @@ -2462,6 +2460,9 @@ FUNCTION Read_Record( & CALL Read_Record_Cleanup(); RETURN END IF + ! RH APPROACH #2 + ! Compute the relative humidity + CALL Compute_Relative_Humidity( atm ) ! Read the cloud data IF ( n_clouds > 0 ) THEN @@ -2491,7 +2492,7 @@ FUNCTION Read_Record( & CALL Read_Record_Cleanup(); RETURN END IF END IF - + CONTAINS SUBROUTINE Read_Record_Cleanup() @@ -2621,4 +2622,78 @@ END SUBROUTINE Write_Record_Cleanup END FUNCTION Write_Record + !-------------------------------------------------------------------------------- + !:sdoc+: + ! + ! NAME: + ! Compute_Relative_Humidity + ! + ! PURPOSE: + ! Subroutine to compute and set the relative humidity of layers + ! given water vapor concentration + ! + ! CALLING SEQUENCE: + ! CALL Compute_Relative_Humidity( Atmosphere ) + ! + ! OBJECT: + ! Atmosphere: CRTM Atmosphere object which is to have its working number + ! of layers updated. + ! UNITS: N/A + ! TYPE: CRTM_Atmosphere_type + ! DIMENSION: Scalar or any rank + ! ATTRIBUTES: INTENT(IN OUT) + !:sdoc-: + !-------------------------------------------------------------------------------- + + SUBROUTINE Compute_Relative_Humidity( Atmosphere ) + ! Arguments + TYPE(CRTM_Atmosphere_type), INTENT(IN OUT) :: Atmosphere + ! Local parameters + CHARACTER( * ), PARAMETER :: ROUTINE_NAME = 'Compute_Relative_Humidity' + ! Local variables + INTEGER :: H2O_Index + REAL(fp), ALLOCATABLE :: H2O_MR(:) + REAL(fp), ALLOCATABLE :: RH(:) + CHARACTER(256) :: msg + INTEGER :: Error_Status + + ! Allocate local variables + ALLOCATE( H2O_MR(Atmosphere%n_Layers) ) + ALLOCATE( RH(Atmosphere%n_Layers) ) + + ! Find the index of absorber water vapor + H2O_Index = CRTM_Get_AbsorberIdx(Atmosphere, H2O_ID) + + ! Obtain water vapor concentration in unit g/kg + IF ( Atmosphere%Absorber_Units(H2O_Index) == VOLUME_MIXING_RATIO_UNITS ) THEN + CALL PPMV_to_MR( Atmosphere%Absorber(:, H2O_Index) , & + H2O_MR, & + Molecule_ID = H2O_ID ) + ELSE IF ( Atmosphere%Absorber_Units(H2O_Index) == MASS_MIXING_RATIO_UNITS ) THEN + H2O_MR = Atmosphere%Absorber(:, H2O_Index) + ELSE + Error_Status = FAILURE + WRITE( msg, '( "The water vapor units type ", i4, " is currently not supported")') & + Atmosphere%Absorber_Units(H2O_Index) + CALL Display_Message( ROUTINE_NAME, TRIM( msg ), Error_Status ) + RETURN + ENDIF + + ! Compute relative humidity + CALL MR_to_RH( Atmosphere%Pressure, & + Atmosphere%Temperature, & + H2O_MR, & + Atmosphere%Relative_Humidity) ! replace with RH for discussion below + + ! Test: are RH approaches 1 and 2 equivalent? + ! Remove after discussion. + ! IF ( .NOT. (ALL(Atmosphere%Relative_Humidity .EqualTo. RH)) ) THEN + ! Error_Status = FAILURE + ! WRITE(msg, '("Atmosphere%Relative_Humidity and RH are different")') + ! CALL Display_Message(ROUTINE_NAME, msg, Error_Status ) + ! RETURN + ! END IF + + END SUBROUTINE Compute_Relative_Humidity + END MODULE CRTM_Atmosphere_Define diff --git a/src/Atmosphere/CRTM_Relative_Humidity.f90 b/src/Atmosphere/CRTM_Relative_Humidity.f90 new file mode 100644 index 0000000..02afdcb --- /dev/null +++ b/src/Atmosphere/CRTM_Relative_Humidity.f90 @@ -0,0 +1,661 @@ +! +! CRTM_RH_Calculation +! +! Compute relative humidity based on CRTM Atmosphere sturctures +! +! CREATION HISTORY: +! Written by: Cheng Dang, 17-Aug-2022 +! dangch@ucar.edu +! +! Contains submodules from Profile_Utility package: +! MR_PPMV.f90 : PPMV_to_MR +! RH_MR.f90 : MR_to_RH [RH unit in one not %] +! Atmospheric_Properties.f90: Saturation_Mixing_Ratio, SVP_Water, SVP_Ice +! + +MODULE CRTM_Relative_Humidity + ! ----------------- + ! Environment setup + ! ----------------- + ! Module use + USE Type_Kinds , ONLY: fp + USE Message_Handler , ONLY: SUCCESS, FAILURE, WARNING, INFORMATION, Display_Message + USE CRTM_Parameters , ONLY: ZERO + + + ! Disable implicit typing + IMPLICIT NONE + + + ! ------------ + ! Visibilities + ! ------------ + ! Everything private by default + PRIVATE + ! Module procedures + PUBLIC :: PPMV_to_MR, MR_to_RH + + ! ----------------- + ! Module parameters + ! ----------------- + ! Parameters for unit conversion + REAL(fp), PARAMETER :: CELSIUS_TO_KELVIN = 273.15_fp + REAL(fp), PARAMETER :: KG_TO_G = 1.0e+03_fp + REAL(fp), PARAMETER :: TO_PERCENT = 1.0e+02_fp + REAL(fp), PARAMETER :: PPMV_TO_PPV = 1.0e-06_fp + REAL(fp), PARAMETER :: PPMV_TO_MR_SCALE_FACTOR = KG_TO_G * PPMV_TO_PPV + ! + ! Maximum number of molecular species (for MW_H2O only in this module) + INTEGER, PARAMETER :: MAX_N_MOLECULAR_SPECIES = 32 + ! Molecular weights of first seven HITRAN molecular species + REAL(fp), PUBLIC, PARAMETER :: MW_H2O = 18.01528_fp + REAL(fp), PARAMETER :: MW_CO2 = 44.00950_fp + REAL(fp), PARAMETER :: MW_O3 = 47.99820_fp + REAL(fp), PARAMETER :: MW_N2O = 44.01288_fp + REAL(fp), PARAMETER :: MW_CO = 28.01010_fp + REAL(fp), PARAMETER :: MW_CH4 = 16.04246_fp + REAL(fp), PARAMETER :: MW_O2 = 31.99880_fp + REAL(fp), PARAMETER :: MW_N2 = 28.01348_fp + ! Weights of all 32 HITRAN molecular species + REAL(fp), PARAMETER :: MOLECULAR_WEIGHT(MAX_N_MOLECULAR_SPECIES) = & + (/ MW_H2O, MW_CO2, MW_O3, MW_N2O, & + MW_CO , MW_CH4, MW_O2, 30.00614_fp, & + 64.06480_fp, 46.00554_fp, 17.03056_fp, 63.01288_fp, & + 17.00734_fp, 20.00634_fp, 36.46064_fp, 80.91194_fp, & + 127.91241_fp, 51.45210_fp, 60.07610_fp, 30.02598_fp, & + 52.46004_fp, MW_N2 , 27.02538_fp, 50.48722_fp, & + 34.01468_fp, 26.03728_fp, 30.06904_fp, 33.99758_fp, & + 66.00690_fp, 146.05643_fp, 34.08188_fp, 46.02538_fp /) + + ! Average molecular weight of dry air + REAL(fp), PARAMETER :: MW_DRYAIR = 28.9648_fp + ! Ratio of water vapor and dry air weights for conversion routines + REAL(fp), PARAMETER :: EPS = MW_H2O / MW_DRYAIR + ! Minimum pressure for saturation mixing ratio calculation + REAL(fp), PARAMETER :: MIN_SMR_PRESSURE = 50.0_fp + + ! Coefficients for saturation vapor pressure over water + INTEGER, PARAMETER :: N_SVPW_COEFFICIENTS = 8 + REAL(fp), PARAMETER :: SVPW_COEFFICIENTS(0:N_SVPW_COEFFICIENTS) = & + (/-3.21582393e-16_fp, 3.79534310e-14_fp, 7.02620698e-11_fp, & + 2.03154182e-08_fp, 2.99291081e-06_fp, 2.64224321e-04_fp, & + 1.43177157e-02_fp, 4.44606896e-01_fp, 6.11583699e+00_fp /) + ! ...Valid temperature range + REAL(fp), PARAMETER :: MIN_SVPW_TEMPERATURE = 188.15_fp + REAL(fp), PARAMETER :: MAX_SVPW_TEMPERATURE = 343.15_fp + + ! Coefficients for saturation vapor pressure over ice + INTEGER, PARAMETER :: N_SVPI_COEFFICIENTS = 8 + REAL(fp), PARAMETER :: SVPI_COEFFICIENTS(0:N_SVPI_COEFFICIENTS) = & + (/ 1.61444444e-15_fp, 1.05785160e-12_fp, 3.07839583e-10_fp, & + 5.21693933e-08_fp, 5.65392987e-06_fp, 4.02737184e-04_fp, & + 1.84672631e-02_fp, 4.99320233e-01_fp, 6.09868993e+00_fp /) + ! ...Valid temperature range + REAL(fp), PARAMETER :: MIN_SVPI_TEMPERATURE = 183.15_fp + REAL(fp), PARAMETER :: MAX_SVPI_TEMPERATURE = 273.15_fp + + +CONTAINS + + + +!################################################################################ +!################################################################################ +!## ## +!## ## PUBLIC MODULE ROUTINES ## ## +!## ## +!################################################################################ +!################################################################################ +!------------------------------------------------------------------------------ +!:sdoc+: +! NAME: +! PPMV_to_MR +! +! PURPOSE: +! Subroutine to convert gas concentrations from volume mixing +! ratio in ppmv to mass mixing ratio in g/kg. +! +! CALLING SEQUENCE: +! CALL PPMV_to_MR( ppmv , & ! Input +! Mixing_Ratio , & ! Output +! Molecule_ID = Molecule_ID ) ! Optional input +! +! INPUTS: +! ppmv: Volume mixing ratio of gas. +! Must be > or = 0.0 +! UNITS: ppmv +! TYPE: REAL(fp) +! DIMENSION: Scalar or any rank +! ATTRIBUTES: INTENT(IN) +! +! OUTPUTS: +! Mixing_Ratio: Mass mixing ratio of gas. +! Set to 0.0 if input < 0.0 +! UNITS: g/kg +! TYPE: REAL(fp) +! DIMENSION: Same as ppmv argument +! ATTRIBUTES: INTENT(IN) +! +! OPTIONAL INPUT ARGUMENTS: +! Molecule_ID: HITRAN molecular designation identifying the +! molecule for which the concentration units +! conversion is required. If not specified, the +! default value is that for water vapor. +! Valid values are: +! 1: H2O 9: SO2 17: HI 25: H2O2 +! 2: CO2 10: NO2 18: ClO 26: C2H2 +! 3: O3 11: NH3 19: OCS 27: C2H6 +! 4: N2O 12: HNO3 20: H2CO 28: PH3 +! 5: CO 13: OH 21: HOCl 29: COF2 +! 6: CH4 14: HF 22: N2 30: SF6 +! 7: O2 15: HCl 23: HCN 31: H2S +! 8: NO 16: HBr 24: CH3Cl 32: HCOOH +! Output is set to zero if an invalid Molecule_Id +! is supplied. +! UNITS: N/A +! TYPE: INTEGER +! DIMENSION: Scalar +! ATTRIBUTES: OPTIONAL, INTENT(IN) +! +! PROCEDURE: +! To convert ppmv to mixing ratio, the following is used: +! +! MW(MOL) +! mr(MOL) = 0.001 . ppmv(MOL) . ------------- +! MW(Dry Air) +! +! where MW(Dry Air) = Average molecular weight of dry air +! MW(MOL) = Molecular weight of the gas in question. +! +! The factor of 0.001 derives from the product of the g/g to g/kg +! scale factor (1000) and the "parts-per-million" to "parts-per" +! scale factor (1.0e-06) +! +! CREATION HISTORY: +! Written by: Paul van Delst, 03-May-2000 +! paul.vandelst@noaa.gov +!:sdoc-: +!------------------------------------------------------------------------------ + + ELEMENTAL SUBROUTINE PPMV_to_MR( & + ppmv , & ! Input + Mixing_Ratio, & ! Output + Molecule_ID ) ! Optional input + ! Arguments + REAL(fp), INTENT(IN) :: ppmv + REAL(fp), INTENT(OUT) :: Mixing_Ratio + INTEGER, OPTIONAL, INTENT(IN) :: Molecule_ID + ! Local variables + INTEGER :: Id + + ! Error checks + ! ...Zero output for -ve input + IF ( ppmv < ZERO ) THEN + Mixing_Ratio = ZERO + RETURN + ENDIF + ! ...Zero output for invalid id + IF ( PRESENT(Molecule_ID) ) THEN + IF ( Molecule_ID < 1 .OR. Molecule_ID > MAX_N_MOLECULAR_SPECIES ) THEN + Mixing_Ratio = ZERO + RETURN + END IF + Id = Molecule_ID + ELSE + Id = 1 ! Default value is for water vapor + END IF + + ! Convert volume to mass mixing ratio + Mixing_Ratio = ppmv * PPMV_TO_MR_SCALE_FACTOR * MOLECULAR_WEIGHT(Id) / MW_DRYAIR + + END SUBROUTINE PPMV_to_MR + +!------------------------------------------------------------------------------ +!:sdoc+: +! NAME: +! MR_to_RH +! +! PURPOSE: +! Subroutine to convert water vapor mass mixing ratio +! to relative humidity +! +! CALLING SEQUENCE: +! CALL MR_to_RH( Pressure , & ! Input +! Temperature , & ! Input +! Mixing_Ratio , & ! Input +! Relative_Humidity , & ! Output +! Ice_Temperature = Ice_Temperature, & ! Optional input +! Min_Pressure = Min_Pressure ) ! Optional input +! +! INPUTS: +! Pressure: Total atmospheric pressure. +! Must be > 0. +! UNITS: hectoPascals, hPa +! TYPE: REAL(fp) +! DIMENSION: Scalar or Rank-1 (K x 1) +! ATTRIBUTES: INTENT(IN) +! +! Temperature: Atmospheric temperature. +! Must be > 0. +! UNITS: Kelvin, K +! TYPE: REAL(fp) +! DIMENSION: Same as Pressure +! ATTRIBUTES: INTENT(IN) +! +! Mixing_Ratio: Water vapor mixing ratio. +! Must be > 0. +! UNITS: g/kg +! TYPE: REAL(fp) +! DIMENSION: Same as Pressure +! ATTRIBUTES: INTENT(IN) +! +! OUTPUTS: +! Relative_Humidity: Relative humidity. +! Set to zero for invalid input. +! UNITS: % +! TYPE: REAL(fp) +! DIMENSION: Same as Pressure +! ATTRIBUTES: INTENT(OUT) +! +! OPTIONAL INPUT ARGUMENTS: +! Ice_Temperature: Temperature below which the saturation vapor +! pressure over ice is used in the conversion. +! By default, only the saturation vapor pressure +! over water is used. +! UNITS: Kelvin, K +! TYPE: REAL(fp) +! DIMENSION: Scalar +! ATTRIBUTES: OPTIONAL, INTENT(IN) +! +! Min_Pressure: Pressure value below which the saturation +! mixing ratio is not calculated. The default +! is 50mb. Saturation mixing ratios below the +! minimum pressure are set to zero. This is +! because at pressures less than 50mb, the +! saturation vapour Pressure, which is based +! only on temperature, can exceed the total +! air Pressure. +! UNITS: hectoPascals, hPa +! TYPE: REAL(fp) +! DIMENSION: Scalar +! ATTRIBUTES: OPTIONAL, INTENT(IN) +! +! PROCEDURE: +! Once the saturation mixing ratio is calculated the relative humidity +! corresponding to the input mixing ratio is determined using: +! +! Mixing_Ratio +! Relative_Humidity = 100.0 * ------------------------- +! Saturation_Mixing_Ratio +! +! CREATION HISTORY: +! Written by: Paul van Delst, 02-Mar-1999 +! paul.vandelst@noaa.gov +!:sdoc-: +!------------------------------------------------------------------------------ + + ELEMENTAL SUBROUTINE MR_to_RH( & + P , & ! Input + T , & ! Input + mr , & ! Input + rh , & ! Output + Ice_Temperature, & ! Optional Input + Min_Pressure ) ! Optional Input + ! Arguments + REAL(fp), INTENT(IN) :: P + REAL(fp), INTENT(IN) :: T + REAL(fp), INTENT(IN) :: mr + REAL(fp), INTENT(OUT) :: rh + REAL(fp), OPTIONAL, INTENT(IN) :: Ice_Temperature + REAL(fp), OPTIONAL, INTENT(IN) :: Min_Pressure + ! Local variables + REAL(fp) :: smr + + ! Setup + IF ( P < ZERO .OR. T < ZERO .OR. mr < ZERO ) THEN + rh = ZERO + RETURN + ENDIF + + + ! Calculate saturation mixing ratio in g/kg + CALL Saturation_Mixing_Ratio( P, & + T, & + smr, & + Ice_Temperature=Ice_Temperature, & + Min_Pressure =Min_Pressure ) + + ! Calculate relative humidity from 0 to 1 + IF ( smr > ZERO ) THEN + rh = mr / smr + ELSE + rh = ZERO + END IF + + END SUBROUTINE MR_to_RH + +!-------------------------------------------------------------------------------- +!:sdoc+: +! NAME: +! Saturation_Mixing_Ratio +! +! PURPOSE: +! Subroutine to calculate the saturation mixing ratio for +! a given pressure and temperature +! +! CALLING SEQUENCE: +! CALL Saturation_Mixing_Ratio( Pressure , & ! Input +! Temperature , & ! Input +! Mixing_Ratio , & ! Output +! Ice_Temperature = Ice_Temperature, & ! Optional input +! Min_Pressure = Min_Pressure ) ! Optional input +! +! INPUTS: +! Pressure: Total atmospheric pressure. +! Valid pressures are > 50hPa. +! UNITS: hectoPascals, hPa +! TYPE: REAL(fp) +! DIMENSION: Scalar or any rank. +! ATTRIBUTES: INTENT(IN) +! +! Temperature: Atmospheric Temperature. +! Valid temperature ranges for saturation vapor +! pressure calculation are: +! Over ice: 183K - 273K (-90C - 0C). +! Over water: 188K - 343K (-85C - +70C). +! UNITS: Kelvin, K +! TYPE: REAL(fp) +! DIMENSION: Same as Pressure +! ATTRIBUTES: INTENT(IN) +! +! OUTPUTS: +! Mixing_Ratio: The saturation mixing ratio for the supplied +! pressure and temperature. +! Value is set to zero for invalid input. +! UNITS: g/kg +! TYPE: REAL(fp) +! DIMENSION: Same as Pressure +! ATTRIBUTES: INTENT(OUT) +! +! OPTIONAL INPUTS: +! Ice_Temperature: Temperature below which the saturation vapor +! pressure over ice is used in the conversion. +! By default, only the saturation vapor pressure +! over water is used. +! UNITS: Kelvin, K +! TYPE: REAL(fp) +! DIMENSION: Scalar +! ATTRIBUTES: OPTIONAL, INTENT(IN) +! +! Min_Pressure: Pressure value below which the saturation +! mixing ratio is not calculated. The default, and +! absolute, minimum value used in this routine is +! 50hPa. Saturation mixing ratios at pressures +! less than the minimum pressure are set to zero. +! This is because at pressures less than 50mb, the +! saturation vapour pressure, which is based only on +! temperature, can exceed the total air pressure. +! UNITS: hectoPascals, hPa +! TYPE: REAL(fp) +! DIMENSION: Scalar +! ATTRIBUTES: OPTIONAL, INTENT(IN) +! +! PROCEDURE: +! The saturation mixing ratio can be defined as: +! +! rho_ws +! ws = -------- .....(1) +! rho_d +! +! where rho_ws = the partial density of water vapour required to +! saturate air with respect to water at a Temperature, T +! rho_d = the partial density of dry air. +! +! Equation (1) can be rewritten as: +! +! es +! --------- +! R_w . T +! ws = ------------ +! p - es +! --------- +! R_d . T +! +! R_d es +! = ----- . -------- +! R_w p - es +! +! M_w es +! = ----- . -------- .....(2) +! M_d p - es +! +! where M_w = molecular weight of water +! M_d = molecular weight of dry air +! es = water vapor partial pressure +! p = total air pressure +! R_d = gas constant for dry air +! R_w = gas constant for water vapor +! +! The units of equation (2) are: +! +! g hPa +! ws = --- . ----- +! g hPa +! +! g +! = 1000.0 ---- +! kg +! +! A factor of 1000 is used to return values in units of g/kg. +! +!:sdoc-: +!-------------------------------------------------------------------------------- + + ELEMENTAL SUBROUTINE Saturation_Mixing_Ratio( & + Pressure , & ! Input + Temperature , & ! Input + Mixing_Ratio , & ! Output + Ice_Temperature, & ! Optional Input + Min_Pressure ) ! Optional Input + ! Arguments + REAL(fp), INTENT(IN) :: Pressure + REAL(fp), INTENT(IN) :: Temperature + REAL(fp), INTENT(OUT) :: Mixing_Ratio + REAL(fp), OPTIONAL, INTENT(IN) :: Ice_Temperature + REAL(fp), OPTIONAL, INTENT(IN) :: Min_Pressure + ! Local variables + REAL(fp) :: Pmin, Tmin, Tice + REAL(fp) :: svp + REAL(fp) :: dp + + ! Setup + ! ...Check optional arguments + IF ( PRESENT(Min_Pressure) ) THEN + Pmin = MAX(Min_Pressure, MIN_SMR_PRESSURE) + ELSE + Pmin = MIN_SMR_PRESSURE + END IF + IF ( PRESENT(Ice_Temperature) ) THEN + Tice = Ice_Temperature + Tmin = MIN_SVPI_TEMPERATURE + ELSE + Tice = ZERO + Tmin = MIN_SVPW_TEMPERATURE + END IF + ! ...Check input + IF ( Pressure < Pmin .OR. Temperature < Tmin ) THEN + Mixing_Ratio = ZERO + RETURN + ENDIF + + + ! Calculate saturation vapor pressure + IF ( Temperature > Tice ) THEN + CALL SVP_Water( Temperature, svp ) + ELSE + CALL SVP_Ice( Temperature, svp ) + END IF + + + ! Calculate saturation mixing ratio only if the + ! total pressure is greater than the saturation + ! vapor pressure. + dp = Pressure - svp + IF ( dp > ZERO ) THEN + Mixing_Ratio = KG_TO_G * EPS * svp / dp + ELSE + Mixing_Ratio = ZERO + END IF + + END SUBROUTINE Saturation_Mixing_Ratio + + +!-------------------------------------------------------------------------------- +!:sdoc+: +! NAME: +! SVP_Water +! +! PURPOSE: +! Subroutine to calculate the saturation vapor pressure +! over water. +! +! CALLING SEQUENCE: +! CALL SVP_Water( Temperature , & ! Input +! Vapor_Pressure ) ! Output +! +! INPUTS: +! Temperature: Temperatures for which the saturation vapor +! pressure is required. +! Valid temperature range is 188K - 343K (-85C - +70C). +! UNITS: Kelvin, K +! TYPE: REAL(fp) +! DIMENSION: Scalar or any rank. +! ATTRIBUTES: INTENT(IN) +! +! OUTPUTS: +! Vapor_Pressure: The saturation vapor pressure over water. +! Value is set to zero if input temperatures are +! outside the valid range. +! UNITS: hectoPascals, hPa +! TYPE: REAL(fp) +! DIMENSION: Same as input Temperature +! ATTRIBUTES: INTENT(OUT) +! +! PROCEDURE: +! Flatau,P.J., R.L.Walko, and W.R.Cotton, 1992: "Polynomial fits to +! saturation vapor pressure", J.Appl.Met., v31, pp1507-1513 +! +! __ N +! \ i +! SVP_Water = c0 + > c(i) . T +! /__ +! i=1 +! +! where the c(i) are the relative error norm coefficients obtained +! from the reference above. +! +! Horner's method is used to evaluate the above polynomial. +! +!:sdoc-: +!-------------------------------------------------------------------------------- + + ELEMENTAL SUBROUTINE SVP_Water( & + Temperature, & ! Input + Vapor_Pressure ) ! Output + ! Arguments + REAL(fp), INTENT(IN) :: Temperature + REAL(fp), INTENT(OUT) :: Vapor_Pressure + ! Local variables + INTEGER :: i + REAL(fp) :: T + + ! Setup + IF ( Temperature < MIN_SVPW_TEMPERATURE .OR. Temperature > MAX_SVPW_TEMPERATURE ) THEN + Vapor_Pressure = ZERO + RETURN + END IF + + ! Calculate saturation vapor pressure + T = Temperature - CELSIUS_TO_KELVIN + Vapor_Pressure = SVPW_COEFFICIENTS(0) + DO i = 1, N_SVPW_COEFFICIENTS + Vapor_Pressure = (Vapor_Pressure * T) + SVPW_COEFFICIENTS(i) + END DO + + END SUBROUTINE SVP_Water + +!-------------------------------------------------------------------------------- +!:sdoc+: +! NAME: +! SVP_Ice +! +! PURPOSE: +! Subroutine to calculate the saturation vapor pressure +! over ice. +! +! CALLING SEQUENCE: +! CALL SVP_Ice( Temperature , & ! Input +! Vapor_Pressure ) ! Output +! +! INPUTS: +! Temperature: Temperatures for which the saturation vapor +! pressure is required. +! Valid temperature range is 183K - 273K (-90C - 0C). +! UNITS: Kelvin, K +! TYPE: REAL(fp) +! DIMENSION: Scalar or any rank. +! ATTRIBUTES: INTENT(IN) +! +! OUTPUTS: +! Vapor_Pressure: The saturation vapor pressure over ice. +! Value is set to zero if input temperatures are +! outside the valid range. +! UNITS: hectoPascals, hPa +! TYPE: REAL(fp) +! DIMENSION: Same as input Temperature +! ATTRIBUTES: INTENT(OUT) +! +! PROCEDURE: +! Flatau,P.J., R.L.Walko, and W.R.Cotton, 1992: "Polynomial fits to +! saturation vapor pressure", J.Appl.Met., v31, pp1507-1513 +! +! __ N +! \ i +! SVP_Ice = c0 + > c(i) . T +! /__ +! i=1 +! +! where the c(i) are the relative error norm coefficients obtained +! from the reference above. +! +! Horner's method is used to evaluate the above polynomial. +! +!:sdoc-: +!-------------------------------------------------------------------------------- + + ELEMENTAL SUBROUTINE SVP_Ice( & + Temperature, & ! Input + Vapor_Pressure ) ! Output + ! Arguments + REAL(fp), INTENT(IN) :: Temperature + REAL(fp), INTENT(OUT) :: Vapor_Pressure + ! Local variables + INTEGER :: i + REAL(fp) :: T + + ! Setup + IF ( Temperature < MIN_SVPI_TEMPERATURE .OR. Temperature > MAX_SVPI_TEMPERATURE ) THEN + Vapor_Pressure = ZERO + RETURN + END IF + + ! Calculate saturation vapor pressure + T = Temperature - CELSIUS_TO_KELVIN + Vapor_Pressure = SVPI_COEFFICIENTS(0) + DO i = 1, N_SVPI_COEFFICIENTS + Vapor_Pressure = (Vapor_Pressure * T) + SVPI_COEFFICIENTS(i) + END DO + + END SUBROUTINE SVP_Ice + +END MODULE CRTM_Relative_Humidity diff --git a/src/Build/libsrc/make.dependencies b/src/Build/libsrc/make.dependencies index a278c85..42027f7 100644 --- a/src/Build/libsrc/make.dependencies +++ b/src/Build/libsrc/make.dependencies @@ -4,7 +4,6 @@ ACCoeff_Define.o : ACCoeff_Define.f90 SensorInfo_Parameters.o Subset_Define.o Co ADA_Module.o : ADA_Module.f90 CRTM_Utility.o Message_Handler.o Type_Kinds.o CRTM_Parameters.o RTV_Define.o AerosolCoeff_Binary_IO.o : AerosolCoeff_Binary_IO.f90 AerosolCoeff_Define.o Binary_File_Utility.o Message_Handler.o File_Utility.o AerosolCoeff_netCDF_IO.o : AerosolCoeff_netCDF_IO.f90 AerosolCoeff_Define.o Message_Handler.o File_Utility.o -AerosolCoeff_IO.o : AerosolCoeff_IO.f90 AerosolCoeff_Binary_IO.o AerosolCoeff_netCDF_IO.o Message_Handler.o File_Utility.o AerosolCoeff_Define.o : AerosolCoeff_Define.f90 Spectral_Units_Conversion.o String_Utility.o Compare_Float_Numbers.o Message_Handler.o Type_Kinds.o AOvar_Define.o : AOvar_Define.f90 Binary_File_Utility.o File_Utility.o Compare_Float_Numbers.o Message_Handler.o Type_Kinds.o ASvar_Define.o : ASvar_Define.f90 CRTM_Interpolation.o Binary_File_Utility.o File_Utility.o Compare_Float_Numbers.o Message_Handler.o Type_Kinds.o @@ -17,7 +16,7 @@ CloudCoeff_Define.o : CloudCoeff_Define.f90 Compare_Float_Numbers.o Message_Hand Common_RTSolution.o : Common_RTSolution.f90 CRTM_RTSolution_Define.o CRTM_Utility.o CRTM_SfcOptics_Define.o CRTM_SfcOptics.o RTV_Define.o CRTM_AtmOptics.o CRTM_AtmOptics_Define.o CRTM_SpcCoeff.o CRTM_Planck_Functions.o CRTM_GeometryInfo_Define.o CRTM_Surface_Define.o CRTM_Atmosphere_Define.o Message_Handler.o CRTM_Parameters.o Type_Kinds.o Compare_Float_Numbers.o : Compare_Float_Numbers.f90 Type_Kinds.o CRTM_Adjoint_Module.o : CRTM_Adjoint_Module.f90 RTV_Define.o ASvar_Define.o CSvar_Define.o AOvar_Define.o CRTM_CloudCover_Define.o CRTM_Planck_Functions.o NLTECoeff_Define.o ACCoeff_Define.o CRTM_NLTECorrection.o CRTM_AerosolCoeff.o CRTM_CloudCoeff.o CRTM_AncillaryInput_Define.o CRTM_MoleculeScatter.o CRTM_AntennaCorrection.o CRTM_RTSolution.o CRTM_SfcOptics.o CRTM_SfcOptics_Define.o CRTM_AtmOptics.o CRTM_CloudScatter.o CRTM_AerosolScatter.o CRTM_AtmOptics_Define.o CRTM_AtmAbsorption.o CRTM_Predictor.o CRTM_Predictor_Define.o CRTM_GeometryInfo.o CRTM_GeometryInfo_Define.o CRTM_Atmosphere.o CRTM_Options_Define.o CRTM_RTSolution_Define.o CRTM_ChannelInfo_Define.o CRTM_Geometry_Define.o CRTM_Surface_Define.o CRTM_Atmosphere_Define.o CRTM_SpcCoeff.o CRTM_Parameters.o Message_Handler.o Type_Kinds.o -CRTM_AerosolCoeff.o : CRTM_AerosolCoeff.f90 AerosolCoeff_IO.o AerosolCoeff_Define.o Message_Handler.o +CRTM_AerosolCoeff.o : CRTM_AerosolCoeff.f90 AerosolCoeff_Define.o Message_Handler.o CRTM_Aerosol_Define.o : CRTM_Aerosol_Define.f90 CRTM_AerosolCoeff.o AerosolCoeff_Define.o Binary_File_Utility.o File_Utility.o Compare_Float_Numbers.o Message_Handler.o Type_Kinds.o CRTM_AerosolScatter.o : CRTM_AerosolScatter.f90 ASvar_Define.o CRTM_AtmOptics_Define.o CRTM_Interpolation.o CRTM_GeometryInfo_Define.o CRTM_Atmosphere_Define.o CRTM_AerosolCoeff.o CRTM_SpcCoeff.o CRTM_Parameters.o String_Utility.o Message_Handler.o Type_Kinds.o CRTM_AncillaryInput_Define.o : CRTM_AncillaryInput_Define.f90 Zeeman_Input_Define.o SSU_Input_Define.o @@ -26,7 +25,7 @@ CRTM_AOD_Module.o : CRTM_AOD_Module.f90 ASvar_Define.o CRTM_AerosolCoeff.o CRTM_ CRTM_AtmAbsorption.o : CRTM_AtmAbsorption.f90 ODZeeman_AtmAbsorption.o ODSSU_AtmAbsorption.o ODPS_AtmAbsorption.o ODAS_AtmAbsorption.o CRTM_Predictor_Define.o CRTM_AtmOptics_Define.o CRTM_GeometryInfo_Define.o CRTM_AncillaryInput_Define.o CRTM_TauCoeff.o CRTM_Atmosphere_Define.o CRTM_Parameters.o Message_Handler.o Type_Kinds.o CRTM_AtmOptics_Define.o : CRTM_AtmOptics_Define.f90 Binary_File_Utility.o File_Utility.o Compare_Float_Numbers.o Message_Handler.o Type_Kinds.o CRTM_AtmOptics.o : CRTM_AtmOptics.f90 AOvar_Define.o CRTM_AtmOptics_Define.o CRTM_Parameters.o Message_Handler.o Type_Kinds.o -CRTM_Atmosphere_Define.o : CRTM_Atmosphere_Define.f90 CRTM_Aerosol_Define.o CRTM_Cloud_Define.o CRTM_Parameters.o Binary_File_Utility.o File_Utility.o Compare_Float_Numbers.o Message_Handler.o Type_Kinds.o +CRTM_Atmosphere_Define.o : CRTM_Atmosphere_Define.f90 CRTM_Relative_Humidity.o CRTM_Aerosol_Define.o CRTM_Cloud_Define.o CRTM_Parameters.o Binary_File_Utility.o File_Utility.o Compare_Float_Numbers.o Message_Handler.o Type_Kinds.o CRTM_Atmosphere.o : CRTM_Atmosphere.f90 iAtm_Define.o CRTM_Model_Profiles.o CRTM_Atmosphere_Define.o CRTM_Parameters.o Message_Handler.o Type_Kinds.o CRTM_Hypsometric.o CRTM_ChannelInfo_Define.o : CRTM_ChannelInfo_Define.f90 Sort_Utility.o SensorInfo_Parameters.o CRTM_Parameters.o File_Utility.o Message_Handler.o CRTM_CloudCoeff.o : CRTM_CloudCoeff.f90 CloudCoeff_netCDF_IO.o CloudCoeff_Binary_IO.o CloudCoeff_Define.o Message_Handler.o @@ -36,6 +35,7 @@ CRTM_CloudScatter.o : CRTM_CloudScatter.f90 CSvar_Define.o CRTM_AtmOptics_Define CRTM_Fastem1.o : CRTM_Fastem1.f90 CRTM_Parameters.o Type_Kinds.o CRTM_FastemX.o : CRTM_FastemX.f90 Azimuth_Emissivity_F6_Module.o Azimuth_Emissivity_Module.o Reflection_Correction_Module.o Large_Scale_Correction_Module.o Small_Scale_Correction_Module.o Foam_Utility_Module.o Liu.o Fresnel.o CRTM_Parameters.o MWwaterCoeff_Define.o Type_Kinds.o CRTM_Forward_Module.o : CRTM_Forward_Module.f90 RTV_Define.o ASvar_Define.o CSvar_Define.o AOvar_Define.o CRTM_CloudCover_Define.o CRTM_Planck_Functions.o NLTECoeff_Define.o ACCoeff_Define.o CRTM_NLTECorrection.o CRTM_AerosolCoeff.o CRTM_CloudCoeff.o CRTM_AncillaryInput_Define.o CRTM_MoleculeScatter.o CRTM_AntennaCorrection.o CRTM_RTSolution.o CRTM_SfcOptics.o CRTM_SfcOptics_Define.o CRTM_AtmOptics.o CRTM_CloudScatter.o CRTM_AerosolScatter.o CRTM_AtmOptics_Define.o CRTM_AtmAbsorption.o CRTM_Predictor.o CRTM_Predictor_Define.o CRTM_GeometryInfo.o CRTM_GeometryInfo_Define.o CRTM_Atmosphere.o CRTM_Options_Define.o CRTM_RTSolution_Define.o CRTM_ChannelInfo_Define.o CRTM_Geometry_Define.o CRTM_Surface_Define.o CRTM_Atmosphere_Define.o CRTM_SpcCoeff.o CRTM_Parameters.o Message_Handler.o Type_Kinds.o +CRTM_Relative_Humidity.o : CRTM_Relative_Humidity.f90 Message_Handler.o Type_Kinds.o CRTM_Parameters.o CRTM_Geometry_Define.o : CRTM_Geometry_Define.f90 CRTM_Parameters.o Date_Utility.o Binary_File_Utility.o File_Utility.o Compare_Float_Numbers.o Message_Handler.o Type_Kinds.o CRTM_GeometryInfo_Define.o : CRTM_GeometryInfo_Define.f90 CRTM_Geometry_Define.o CRTM_Parameters.o Binary_File_Utility.o File_Utility.o Compare_Float_Numbers.o Message_Handler.o Type_Kinds.o CRTM_GeometryInfo.o : CRTM_GeometryInfo.f90 CRTM_GeometryInfo_Define.o CRTM_Parameters.o Date_Utility.o Message_Handler.o Type_Kinds.o diff --git a/src/Build/libsrc/make.filelist b/src/Build/libsrc/make.filelist index 92fc2f2..f4f38cc 100644 --- a/src/Build/libsrc/make.filelist +++ b/src/Build/libsrc/make.filelist @@ -30,7 +30,7 @@ FSRC_FILES = \ SpcCoeff_Define.f90 ACCoeff_Define.f90 NLTECoeff_Define.f90 \ SpcCoeff_Binary_IO.f90 ACCoeff_Binary_IO.f90 NLTECoeff_Binary_IO.f90 \ CloudCoeff_Define.f90 CloudCoeff_Binary_IO.f90 CloudCoeff_netCDF_IO.f90 \ - AerosolCoeff_Define.f90 AerosolCoeff_Binary_IO.f90 AerosolCoeff_netCDF_IO.f90 AerosolCoeff_IO.f90 \ + AerosolCoeff_Define.f90 AerosolCoeff_Binary_IO.f90 AerosolCoeff_netCDF_IO.f90 \ CRTM_Options_Define.f90 \ CRTM_AOD_Module.f90 \ IRwaterCoeff_Define.f90 \ @@ -78,6 +78,7 @@ FSRC_FILES = \ CRTM_GeometryInfo_Define.f90 CRTM_GeometryInfo.f90 \ CRTM_Atmosphere.f90 iAtm_Define.f90 \ CRTM_Hypsometric.f90 \ + CRTM_Relative_Humidity.f90 \ CRTM_CloudCover_Define.f90 \ CRTM_Model_Profiles.f90 \ CRTM_AerosolScatter.f90 ASvar_Define.f90 \ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e8a2ed8..8f50b79 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,6 +29,7 @@ list( APPEND crtm_src_files Atmosphere/Cloud/CRTM_Cloud_Define.f90 Atmosphere/CRTM_Atmosphere_Define.f90 Atmosphere/CRTM_Hypsometric.f90 + Atmosphere/CRTM_Relative_Humidity.f90 Atmosphere/CRTM_Atmosphere.f90 Atmosphere/CRTM_Model_Profiles.f90 Atmosphere/iAtm_Define.f90 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index df7cfe5..ccbbb2a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -38,25 +38,26 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/results/forward) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/results/unit) CREATE_SYMLINK( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${crtm_test_input} ) - -if( DEFINED ENV{LOCAL_PATH_JEDI_TESTFILES}) - set(LOCAL_PATH_JEDI_TESTFILES "$ENV{LOCAL_PATH_JEDI_TESTFILES}") -endif() - -set( REPO_VERSION crtm/2.4.0 ) +set( REPO_VERSION crtm/3.0.0 ) # If local path to testfiles is defined don't download -if( DEFINED LOCAL_PATH_JEDI_TESTFILES ) - set( CRTM_COEFFS_PATH ${LOCAL_PATH_JEDI_TESTFILES}/${REPO_VERSION} ) - message(STATUS "use LOCAL_PATH_JEDI_TESTFILES: ${LOCAL_PATH_JEDI_TESTFILES}") + +# IF the fix/ directory already exists locally, don't download the tarball from gdex +# this supports non-jedi users. +IF(EXISTS ${CMAKE_SOURCE_DIR}/fix) + set( CRTM_COEFFS_PATH ${CMAKE_SOURCE_DIR}/fix ) + message(STATUS "use LOCAL_PATH_JEDI_TESTFILES: ${CRTM_COEFFS_PATH}") + message("Using existing local fix directory instead of downloading.") # Download CRTM coefficients else() - set( CRTM_COEFFS_BRANCH "jedi_release_2.4.0" ) - set( CRTM_COEFFS_PATH ${CMAKE_BINARY_DIR}/test_data/${REPO_VERSION}) - file(MAKE_DIRECTORY ${CRTM_COEFFS_PATH}) - set( ECBUILD_DOWNLOAD_BASE_URL https://gdex.ucar.edu/dataset/jedi-skylab ) + set( CRTM_COEFFS_BRANCH_PREFIX "crtm" ) #preserves the structure of the paths that have been used in jedi previously vs the local path above + set( CRTM_COEFFS_BRANCH "jedi_release_3.0.0" ) #this version is the CRTM version, not the jedi / skylab version (again, following prior installations -- I'm not tied to this in any way) + # it is my intention is to not have any difference between jedi/ufo versions of CRTM and stand-alond versions of CRTM -- they should both work "out of the box" + set( CRTM_COEFFS_PATH ${CMAKE_BINARY_DIR}/test_data/${REPO_VERSION}) #this is where the symlinks point to binary files for the testinput/* directory after ecbuild. + file(MAKE_DIRECTORY ${CRTM_COEFFS_PATH}) + set( ECBUILD_DOWNLOAD_BASE_URL https://gdex.ucar.edu/dataset/jedi-skylab ) message(STATUS "download CRTM coeffs files from: ${ECBUILD_DOWNLOAD_BASE_URL}/file to ${CRTM_COEFFS_PATH}") ecbuild_get_test_multidata( TARGET get_crtm_coeffs - NAMES crtm_coefficients_${CRTM_COEFFS_BRANCH}.tar.gz:7e35d27179b2f62e54fdf257751f29bf + NAMES crtm_coefficients_${CRTM_COEFFS_BRANCH}.tar.gz:9941a3c099704108830e33e49792478 #i'm assuming these are md5sums, this is the md5sum for crtm_coefficients_3.0.0_skylab_4.0.tar.gz as of March 8, 2023 that was sent to gdex DIRNAME file DIRLOCAL ${CRTM_COEFFS_PATH} EXTRACT ) @@ -70,30 +71,30 @@ ecbuild_add_resources( TARGET crtm_test_scripts # Create list of sensor ids for testing list( APPEND Simple_Sensor_Ids - atms_npp - cris399_npp - v.abi_gr + atms_n21 + cris-fsr_n21 + v.abi_g18 modis_aqua ) list( APPEND ScatteringSwitch_Sensor_Ids - atms_npp - cris399_npp - v.abi_gr + atms_n21 + cris-fsr_n21 + v.abi_g18 modis_aqua ) list( APPEND SOI_Sensor_Ids - atms_npp - cris399_npp - v.abi_gr + atms_n21 + cris-fsr_n21 + v.abi_g18 modis_aqua ) list( APPEND VerticalCoordinates_Sensor_Ids - atms_npp - cris399_npp - v.abi_gr + atms_n21 + cris-fsr_n21 + v.abi_g18 modis_aqua ) @@ -103,16 +104,16 @@ list( APPEND SSU_Sensor_Ids ) list( APPEND ClearSky_Sensor_Ids - atms_npp - cris399_npp - v.abi_gr + atms_n21 + cris-fsr_n21 + v.abi_g18 modis_aqua ) # Create list of sensor ids for testing list( APPEND AOD_Sensor_Ids - cris399_npp - v.abi_gr + cris-fsr_n21 + v.abi_g18 airs_aqua ) @@ -131,7 +132,7 @@ list( APPEND ChannelSubset_Sensor_Ids ) list( APPEND Aircraft_Sensor_Ids - crisB1_npp + cris-fsr_n21 ) list (APPEND common_tests @@ -254,9 +255,6 @@ endforeach() ##################################################################### list( APPEND crtm_test_input -Test_Input/ECMWF_5K/Big_Endian/ecmwf_5k_atmosphereccol.bin -Test_Input/ECMWF_5K/Big_Endian/ecmwf_5k_surfaceccol.bin -Test_Input/ECMWF_5K/Big_Endian/ecmwf_5k_geometryccol.bin AerosolCoeff/Little_Endian/AerosolCoeff.bin CloudCoeff/Little_Endian/CloudCoeff.bin EmisCoeff/MW_Water/Little_Endian/FASTEM6.MWwater.EmisCoeff.bin @@ -280,8 +278,8 @@ SpcCoeff/Little_Endian/gmi_gpm.SpcCoeff.bin TauCoeff/ODPS/Little_Endian/gmi_gpm.TauCoeff.bin SpcCoeff/Little_Endian/seviri_m08.SpcCoeff.bin TauCoeff/ODAS/Little_Endian/seviri_m08.TauCoeff.bin -SpcCoeff/Little_Endian/cris-fsr_npp.SpcCoeff.bin -TauCoeff/ODPS/Little_Endian/cris-fsr_npp.TauCoeff.bin +SpcCoeff/Little_Endian/cris-fsr_n21.SpcCoeff.bin +TauCoeff/ODPS/Little_Endian/cris-fsr_n21.TauCoeff.bin SpcCoeff/Little_Endian/iasi_metop-a.SpcCoeff.bin TauCoeff/ODPS/Little_Endian/iasi_metop-a.TauCoeff.bin SpcCoeff/Little_Endian/iasi_metop-b.SpcCoeff.bin @@ -300,16 +298,14 @@ SpcCoeff/Little_Endian/airs_aqua.SpcCoeff.bin TauCoeff/ODPS/Little_Endian/airs_aqua.TauCoeff.bin SpcCoeff/Little_Endian/modis_aqua.SpcCoeff.bin TauCoeff/ODPS/Little_Endian/modis_aqua.TauCoeff.bin -SpcCoeff/Little_Endian/cris399_npp.SpcCoeff.bin -TauCoeff/ODPS/Little_Endian/cris399_npp.TauCoeff.bin -SpcCoeff/Little_Endian/crisB1_npp.SpcCoeff.bin -TauCoeff/ODPS/Little_Endian/crisB1_npp.TauCoeff.bin -SpcCoeff/Little_Endian/atms_npp.SpcCoeff.bin -TauCoeff/ODPS/Little_Endian/atms_npp.TauCoeff.bin -SpcCoeff/Little_Endian/v.viirs-m_npp.SpcCoeff.bin -TauCoeff/ODAS/Little_Endian/v.viirs-m_npp.TauCoeff.bin -SpcCoeff/Little_Endian/v.abi_gr.SpcCoeff.bin -TauCoeff/ODAS/Little_Endian/v.abi_gr.TauCoeff.bin +SpcCoeff/Little_Endian/cris-fsr_n21.SpcCoeff.bin +TauCoeff/ODPS/Little_Endian/cris-fsr_n21.TauCoeff.bin +SpcCoeff/Little_Endian/atms_n21.SpcCoeff.bin +TauCoeff/ODPS/Little_Endian/atms_n21.TauCoeff.bin +SpcCoeff/Little_Endian/v.viirs-m_j2.SpcCoeff.bin +TauCoeff/ODPS/Little_Endian/v.viirs-m_j2.TauCoeff.bin +SpcCoeff/Little_Endian/v.abi_g18.SpcCoeff.bin +TauCoeff/ODAS/Little_Endian/v.abi_g18.TauCoeff.bin TauCoeff/ODPS/Little_Endian/zssmis_f20.TauCoeff.bin TauCoeff/ODPS/Little_Endian/zssmis_f19.TauCoeff.bin TauCoeff/ODPS/Little_Endian/zssmis_f18.TauCoeff.bin @@ -341,6 +337,6 @@ SpcCoeff/Little_Endian/ssu_n14.SpcCoeff.bin # Symlink all CRTM files -CREATE_SYMLINK_FILENAME( ${CRTM_COEFFS_PATH}/crtm/${CRTM_COEFFS_BRANCH} +CREATE_SYMLINK_FILENAME( ${CRTM_COEFFS_PATH}/${CRTM_COEFFS_BRANCH_PREFIX}/${CRTM_COEFFS_BRANCH} ${CMAKE_CURRENT_BINARY_DIR}/testinput ${crtm_test_input} )