MAmfRead.F90 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. ! First include the set of model-wide compiler flags
  2. #include "tm5.inc"
  3. ! Macro
  4. #define TRACEBACK write (gol,'("in ",a," (",a,i6,")")') rname, __FILE__, __LINE__ ; call goErr
  5. #define IF_NOTOK_RETURN if (status/=0) then; TRACEBACK; return; end if
  6. #define IF_ERROR_RETURN if (status> 0) then; TRACEBACK; return; end if
  7. module MAmfRead
  8. !
  9. ! Module to load the height-dependent air-mass factor lookup table
  10. !
  11. ! subroutine ReadAmfLut
  12. !
  13. ! Henk Eskes, KNMI, Sept 2015
  14. use GO, only : gol, goErr
  15. implicit none
  16. private
  17. public :: ReadAmfLut
  18. ! The LUT netcdf file contains:
  19. !
  20. ! float mu(mu) ; long_name = "Cosine of viewing zenith angle" ; units = "1"
  21. ! float mu0(mu0) ; long_name = "Cosine of solar zenith angle" ; units = "1"
  22. ! int dphi(dphi) ; long_name = "Relative azimuth angle" ; units = "degree"
  23. ! float vza(mu) ; long_name = "Viewing zenith angle" ; units = "degree" (not used)
  24. ! float sza(mu0) ; long_name = "Solar zenith angle" ; units = "degree" (not used)
  25. ! float p(p) ; longname = "Pressure Levels" ; units = "hPa"
  26. ! int p_surface(p_surface) ; long_name = "Surface pressure levels" ; units = "hPa"
  27. ! float albedo(albedo) ; long_name = "Surface Albedo" ; units = "1"
  28. !
  29. ! float amf(albedo, p_surface, p, dphi, mu0, mu) ;
  30. ! (note: indices in reverse order as in F90)
  31. ! long_name = "Box air mass factor" ; units = "1"
  32. !
  33. ! Note:
  34. ! albedo, dphi, mu, mu0 : increasing
  35. ! p, p_surface : decreasing
  36. character(len=*), parameter :: mname = 'MAmfRead'
  37. contains
  38. subroutine ReadAmfLut ( amf_filename, divideByAMFGeo, amfLut, status )
  39. !=======================================================================
  40. !
  41. ! ReadAmfLut: read lookup table for AMF calculations
  42. ! updated netcdf format lookup table, 7 Sept 2015
  43. ! from Alba Lorente, Folkert Boersma
  44. !
  45. ! input:
  46. ! amf_filename = path+name of the file containing the AMF lookup table
  47. ! divideByAMFGeo = provide inital division by AMF_geo ? (t/f)
  48. ! (The latest AMF files contain AMF / AMF_geo, and the flag should be put to .false.)
  49. ! output:
  50. ! amfLut = structure with AMF lookup table
  51. ! status = status ( 0 means OK )
  52. !
  53. ! The routine will allocate the arrays in "anfLut",
  54. ! using the dimensions in the file
  55. ! Henk Eskes, KNMI, sept 2015
  56. !=======================================================================
  57. use MDF, only : MDF_Open, MDF_NETCDF, MDF_READ
  58. use MDF, only : MDF_Inq_VarID, MDF_Get_Var, MDF_Close
  59. use MDF, only : MDF_Inquire_Dimension, MDF_Inq_DimID
  60. use MTAmf, only : TAmfLut, AllocateAmfLut
  61. use MAmfGet, only : GetAmfGeo
  62. implicit none
  63. ! in/out
  64. character(*), intent(in) :: amf_filename
  65. logical, intent(in) :: divideByAMFGeo
  66. type(TAmfLut), intent(inout) :: amfLut
  67. integer, intent(out) :: status
  68. ! local
  69. character(len=*), parameter :: rname = mname//'/ReadAmfLut'
  70. integer :: fid
  71. integer :: dimid, id_mu, id_mu0, id_dphi, id_p, id_psurf, id_alb, id_amf
  72. integer :: nmu_file, nmu0_file, ndphi_file, np_file, npsurf_file, nalbedo_file
  73. integer :: imu, imu0
  74. integer, dimension(:), allocatable :: dphi_int, psurf_int
  75. real :: amfGeo
  76. ! start code
  77. call MDF_Open( trim(amf_filename), MDF_NETCDF, MDF_READ, fid, status )
  78. IF_NOTOK_RETURN
  79. ! get the 6 dimensions
  80. call MDF_Inq_DimID( fid, 'mu', dimid, status )
  81. IF_NOTOK_RETURN
  82. call MDF_Inquire_Dimension( fid, dimid, status, length=nmu_file )
  83. IF_NOTOK_RETURN
  84. call MDF_Inq_DimID( fid, 'mu0', dimid, status )
  85. IF_NOTOK_RETURN
  86. call MDF_Inquire_Dimension( fid, dimid, status, length=nmu0_file )
  87. IF_NOTOK_RETURN
  88. call MDF_Inq_DimID( fid, 'dphi', dimid, status )
  89. IF_NOTOK_RETURN
  90. call MDF_Inquire_Dimension( fid, dimid, status, length=ndphi_file )
  91. IF_NOTOK_RETURN
  92. call MDF_Inq_DimID( fid, 'p', dimid, status )
  93. IF_NOTOK_RETURN
  94. call MDF_Inquire_Dimension( fid, dimid, status, length=np_file )
  95. IF_NOTOK_RETURN
  96. call MDF_Inq_DimID( fid, 'p_surface', dimid, status )
  97. IF_NOTOK_RETURN
  98. call MDF_Inquire_Dimension( fid, dimid, status, length=npsurf_file )
  99. IF_NOTOK_RETURN
  100. call MDF_Inq_DimID( fid, 'albedo', dimid, status )
  101. IF_NOTOK_RETURN
  102. call MDF_Inquire_Dimension( fid, dimid, status, length=nalbedo_file )
  103. IF_NOTOK_RETURN
  104. ! Allocate storage space
  105. call AllocateAmfLut ( nmu_file, nmu0_file, ndphi_file, np_file, npsurf_file, nalbedo_file, amfLut )
  106. ! Define variables
  107. CALL MDF_Inq_VarID( fid, 'mu', id_mu, status )
  108. IF_ERROR_RETURN
  109. CALL MDF_Inq_VarID( fid, 'mu0', id_mu0, status )
  110. IF_ERROR_RETURN
  111. CALL MDF_Inq_VarID( fid, 'dphi', id_dphi, status )
  112. IF_ERROR_RETURN
  113. CALL MDF_Inq_VarID( fid, 'p', id_p, status )
  114. IF_ERROR_RETURN
  115. CALL MDF_Inq_VarID( fid, 'p_surface', id_psurf, status )
  116. IF_ERROR_RETURN
  117. CALL MDF_Inq_VarID( fid, 'albedo' , id_alb, status )
  118. IF_ERROR_RETURN
  119. CALL MDF_Inq_VarID( fid, 'amf', id_amf, status )
  120. IF_ERROR_RETURN
  121. ! Read variables
  122. CALL MDF_Get_Var( fid, id_mu, amfLut%mu, status ) ! cos(vza)
  123. IF_NOTOK_RETURN
  124. CALL MDF_Get_Var( fid, id_mu0, amfLut%mu0, status ) ! cos(sza)
  125. IF_NOTOK_RETURN
  126. allocate ( dphi_int(ndphi_file) )
  127. CALL MDF_Get_Var( fid, id_dphi, dphi_int, status )
  128. IF_NOTOK_RETURN
  129. amfLut%azi(:) = real ( dphi_int(:) ) ! azi/dphi in degree
  130. deallocate ( dphi_int )
  131. CALL MDF_Get_Var( fid, id_p, amfLut%pres, status ) ! layer pressures
  132. IF_NOTOK_RETURN
  133. allocate ( psurf_int(npsurf_file) )
  134. CALL MDF_Get_Var( fid, id_psurf, psurf_int, status )
  135. IF_NOTOK_RETURN
  136. amfLut%spres(:) = real ( psurf_int(:) ) ! surface pressures
  137. deallocate ( psurf_int )
  138. CALL MDF_Get_Var( fid, id_alb, amfLut%albedo, status ) ! albedo values
  139. IF_NOTOK_RETURN
  140. CALL MDF_Get_Var( fid, id_amf, amfLut%amf, status ) ! the AMF lookup table
  141. IF_NOTOK_RETURN
  142. ! Close file
  143. CALL MDF_Close( fid, status )
  144. IF_NOTOK_RETURN
  145. ! The LUT file contains either AMF or AMF/AMFgeo
  146. if ( divideByAMFGeo ) then
  147. ! The AMF is pre-divided by the geometrical AMF, which makes it more smooth
  148. ! in order to reduce interpolation errors
  149. do imu = 1, amfLut%mmu
  150. do imu0 = 1, amfLut%mmu0
  151. call GetAmfGeo ( amfLut%mu(imu), amfLut%mu0(imu0), amfGeo )
  152. amfLut%amf(imu,imu0,:,:,:,:) = amfLut%amf(imu,imu0,:,:,:,:) / amfGeo
  153. ! print*,' mu, mu0, amfgeo ',amfLut%mu(imu), amfLut%mu0(imu0), amfGeo, amfLut%amf(imu,imu0,4,150,1,7)
  154. end do
  155. end do
  156. end if
  157. end subroutine ReadAmfLut
  158. end module MAmfRead