tm5_climat.F90 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #define TRACEBACK write (gol,'("in ",a," (",a,i6,")")') rname, __FILE__, __LINE__ ; call goErr
  2. #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
  3. #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if
  4. !
  5. #include "tm5.inc"
  6. !
  7. !
  8. ! Tools for climatologies
  9. !
  10. module Climat
  11. use GO, only : TDate
  12. implicit none
  13. ! --- in/out -------------------------
  14. private
  15. public :: TClimat
  16. public :: Init, Done
  17. public :: Set, Setup
  18. ! --- const -----------------------------
  19. character(len=*), parameter :: mname = 'Climat'
  20. ! --- types --------------------------
  21. type TClimat
  22. character(len=16) :: name, unit
  23. ! actual climatology:
  24. real, pointer :: data(:,:,:)
  25. ! current data can be used to interpolate to this interval:
  26. type(TDate) :: tr(2)
  27. ! fields used for temporal interpolation:
  28. character(len=10) :: tinterp
  29. integer :: nt
  30. type(TDate), pointer :: t_in(:)
  31. real, pointer :: data_in(:,:,:,:)
  32. end type TClimat
  33. ! --- interfaces ------------------------
  34. interface Init
  35. module procedure climat_Init
  36. end interface
  37. interface Done
  38. module procedure climat_Done
  39. end interface
  40. interface Setup
  41. module procedure climat_Setup
  42. end interface
  43. interface Set
  44. module procedure climat_Set
  45. end interface
  46. contains
  47. ! =========================================================
  48. subroutine climat_Init( climat, name, unit, tinterp, im, jm, lm, status )
  49. use GO, only : gol, goErr
  50. use GO, only : AnyDate
  51. ! --- in/out --------------------------------
  52. type(TClimat), intent(out) :: climat
  53. character(len=*), intent(in) :: name, unit
  54. character(len=*), intent(in) :: tinterp
  55. integer, intent(in) :: im, jm, lm
  56. integer, intent(inout) :: status
  57. ! --- const ------------------------------
  58. character(len=*), parameter :: rname = mname//'/climat_Init'
  59. ! --- local -------------------------------
  60. integer :: it
  61. ! --- begin --------------------------------
  62. ! trap previous errors:
  63. if (status>0) return
  64. ! store info:
  65. climat%name = name
  66. climat%unit = unit
  67. climat%tinterp = tinterp
  68. ! setup target data:
  69. allocate( climat%data (im,jm,lm) )
  70. ! data not valid yet:
  71. climat%tr(1) = AnyDate()
  72. climat%tr(2) = AnyDate()
  73. ! setup interpolation data if necessary:
  74. select case ( climat%tinterp )
  75. case ( 'linear' )
  76. climat%nt = 2
  77. allocate( climat%data_in(im,jm,lm,climat%nt) )
  78. allocate( climat%t_in(climat%nt) )
  79. do it = 1, climat%nt
  80. climat%t_in(it) = AnyDate()
  81. end do
  82. case ( 'constant' )
  83. climat%nt = 0
  84. nullify( climat%data_in )
  85. case default
  86. write (gol,'("unsupported time interpolation : ",a)') trim(climat%tinterp); call goErr
  87. write (gol,'("in ",a)') rname; call goErr; status=1; return
  88. end select
  89. ! ok
  90. status = 0
  91. end subroutine climat_Init
  92. ! ***
  93. subroutine climat_Done( climat, status )
  94. use GO, only : gol, goErr
  95. ! --- in/out --------------------------------
  96. type(TClimat), intent(inout) :: climat
  97. integer, intent(inout) :: status
  98. ! --- const ------------------------------
  99. character(len=*), parameter :: rname = mname//'/climat_Done'
  100. ! --- begin --------------------------------
  101. ! trap previous errors:
  102. if (status>0) return
  103. ! clear arrays:
  104. deallocate( climat%data )
  105. select case ( climat%tinterp )
  106. case ( 'linear' )
  107. deallocate( climat%data_in )
  108. deallocate( climat%t_in )
  109. case ( 'constant' )
  110. ! nothing to clear
  111. case default
  112. write (gol,'("unsupported time interpolation : ",a)') trim(climat%tinterp); call goErr
  113. write (gol,'("in ",a)') rname; call goErr; status=1; return
  114. end select
  115. ! ok
  116. status = 0
  117. end subroutine climat_Done
  118. ! ***
  119. subroutine climat_Set( climat, status, data, tr, t_in, data_in, it_in )
  120. use GO, only : gol, goErr
  121. ! --- in/out --------------------------------
  122. type(TClimat), intent(inout) :: climat
  123. integer, intent(inout) :: status
  124. real, intent(in), optional :: data(:,:,:)
  125. type(TDate), intent(in), optional :: tr(2)
  126. type(TDate), intent(in), optional :: t_in
  127. real, intent(in), optional :: data_in(:,:,:)
  128. integer, optional :: it_in
  129. ! --- const ------------------------------
  130. character(len=*), parameter :: rname = mname//'/climat_Set'
  131. ! --- begin --------------------------------
  132. ! trap previous errors:
  133. if (status>0) return
  134. ! store data ?
  135. if ( present(data) ) climat%data = data
  136. ! store time range within which data is valid:
  137. if ( present(tr) ) climat%tr = tr
  138. ! input fields for time interpolation ?
  139. if ( present(t_in) .or. present(data_in) .or. present(it_in) ) then
  140. ! all should be present ...
  141. if ( .not. ( present(t_in) .and. present(data_in) .and. present(it_in) ) ) then
  142. write (gol,'("all or none input arguments should be present:")'); call goErr
  143. write (gol,'(" t_in : ",l1)') present(t_in)
  144. write (gol,'(" data_in : ",l1)') present(data_in)
  145. write (gol,'(" it_in : ",l1)') present(it_in)
  146. write (gol,'("in ",a)') rname; call goErr; status=1; return
  147. end if
  148. ! check it_inex ...
  149. if ( (it_in < 1) .or. (it_in > climat%nt) ) then
  150. write (gol,'("it_in not valid:")'); call goErr
  151. write (gol,'(" it_in : ",i2)') it_in
  152. write (gol,'(" nt : ",i2)') climat%nt
  153. write (gol,'(" tinterp : ",a)') trim(climat%tinterp)
  154. write (gol,'("in ",a)') rname; call goErr; status=1; return
  155. end if
  156. ! store:
  157. climat%t_in(it_in) = t_in
  158. climat%data_in(:,:,:,it_in) = data_in
  159. end if
  160. ! ok
  161. status = 0
  162. end subroutine climat_Set
  163. ! ***
  164. subroutine climat_Setup( climat, t, status )
  165. use GO, only : gol, goErr
  166. use GO, only : TDate, IsAnyDate, operator(<), InterpolFractions
  167. ! --- in/out --------------------------------
  168. type(TClimat), intent(inout) :: climat
  169. type(TDate), intent(in) :: t
  170. integer, intent(inout) :: status
  171. ! --- const ------------------------------
  172. character(len=*), parameter :: rname = mname//'/climat_Setup'
  173. ! --- local -------------------------------
  174. real :: alfa(2)
  175. integer :: it
  176. ! --- begin --------------------------------
  177. ! trap previous errors:
  178. if (status>0) return
  179. ! not filled yet ?
  180. if ( IsAnyDate(climat%tr(1)) .or. IsAnyDate(climat%tr(2)) ) then
  181. ! return as a warning; calling program should fill data ...
  182. status=-1; return
  183. end if
  184. ! t outside time range for which current data is valid ?
  185. if ( (t < climat%tr(1)) .or. (climat%tr(2) < t) ) then
  186. ! return as a warning; calling program should fill data ...
  187. status=-1; return
  188. end if
  189. ! apply time interpolation:
  190. select case ( climat%tinterp )
  191. case ( 'linear' )
  192. ! determine fractions to be applied to data1 and data2:
  193. call InterpolFractions( t, climat%t_in(1), climat%t_in(2), alfa(1), alfa(2), status )
  194. if (status/=0) then; write (gol,'("in ",a)') rname; call goErr; status=1; return; end if
  195. ! interpolate and store :
  196. climat%data = alfa(1) * climat%data_in(:,:,:,1) + alfa(2) * climat%data_in(:,:,:,2)
  197. case ( 'constant' )
  198. ! nothing to be done
  199. case default
  200. write (gol,'("unsupported time interpolation : ",a)') trim(climat%tinterp); call goErr
  201. write (gol,'("in ",a)') rname; call goErr; status=1; return
  202. end select
  203. ! ok
  204. status = 0
  205. end subroutine climat_Setup
  206. end module Climat