source: trunk/LMDZ.MARS/libf/phymars/soil_settings.F @ 2932

Last change on this file since 2932 was 2919, checked in by llange, 22 months ago

PCM
Flux_geo is now correctled initialized (wasnot correctly read in the startfi) for the 3D and 1D
Minor fix in the pem (wrong name for a variable)
LL

File size: 16.5 KB
Line 
1      subroutine soil_settings(nid,ngrid,nsoil,tsurf,tsoil,indextime)
2
3!      use netcdf
4      use comsoil_h, only: layer, mlayer, inertiedat, volcapa,flux_geo
5      use iostart, only: inquire_field_ndims, get_var, get_field,
6     &                   inquire_field, inquire_dimension_length
7      USE comslope_mod, ONLY: nslope
8      implicit none
9
10!======================================================================
11!  Author: Ehouarn Millour (07/2006)
12!
13!  Purpose: Read and/or initialise soil depths and properties
14!
15! Modifications: Aug.2010 EM : use NetCDF90 to load variables (enables using
16!                      r4 or r8 restarts independently of having compiled
17!                      the GCM in r4 or r8)
18!                June 2013 TN : Possibility to read files with a time axis
19!
20!
21!  This subroutine reads from a NetCDF file (opened by the caller)
22!  of "startfi.nc" format.
23!  The various actions and variable read/initialized are:
24!  1. Check out the number of soil layers (in datafile); if it isn't equal
25!     to nsoil, then some interpolation will be required
26!     Also check if data in file "startfi.nc" is in older format (ie:
27!     thermal inertia was depth-independent; and there was no "depth"
28!     coordinate.
29!     Read/build layer (and midlayer) depths
30!  2. Read volumetric specific heat (or initialise it to default value)
31!  3. Read Thermal inertia
32!  4. Read soil temperatures
33!  5. Interpolate thermal inertia and temperature on the new grid, if
34!     necessary
35!======================================================================
36
37!======================================================================
38!  arguments
39!  ---------
40!  inputs:
41      integer,intent(in) :: nid ! Input Netcdf file ID
42      integer,intent(in) :: ngrid       ! # of horizontal grid points
43      integer,intent(in) :: nsoil       ! # of soil layers
44      real,intent(in) :: tsurf(ngrid,nslope)   ! surface temperature
45      integer,intent(in) :: indextime   ! position on time axis
46!  output:
47      real,intent(out) :: tsoil(ngrid,nsoil,nslope)     ! soil temperature
48
49!======================================================================
50! local variables:
51      integer ierr      ! status (returned by NetCDF functions)
52      integer nvarid    ! ID of NetCDF variable
53      integer dimid     ! ID of NetCDF dimension
54      integer dimlen    ! length along the "depth" dimension
55      integer ndims     ! # of dimensions of read <inertiedat> data
56      integer ig,iloop  ! loop counters
57      integer islope
58     
59      integer edges(3),corner(3) ! to read a specific time
60
61      logical :: olddepthdef=.false. ! flag
62      logical :: interpol=.false. ! flag: true if interpolation will be requiered
63
64      ! to store "old" values
65      real,dimension(:),allocatable :: surfinertia !surface thermal inertia
66      real,dimension(:),allocatable :: oldmlayer
67      real,dimension(:,:),allocatable :: oldinertiedat
68      real,dimension(:,:,:),allocatable :: oldtsoil
69     
70      ! for interpolation
71      real,dimension(:),allocatable :: oldgrid
72      real,dimension(:),allocatable :: oldval
73      real,dimension(:),allocatable :: newval
74
75      real alpha,lay1 ! coefficients for building layers
76      real xmin,xmax ! to display min and max of a field
77
78      real,parameter :: default_volcapa=1.e6
79
80      logical :: found,ok
81     
82!======================================================================
83
84! 1. Depth coordinate
85! -------------------
86
87! 1.1 Start by reading how many layers of soil there are
88
89!       ierr=nf90_inq_dimid(nid,"subsurface_layers",dimid)
90!       if (ierr.ne.nf90_noerr) then
91!        write(*,*)'soil_settings: Problem reading <subsurface_layers>'
92!         write(*,*)trim(nf90_strerror(ierr))
93!        call abort
94!       endif
95
96!       ierr=nf90_inquire_dimension(nid,dimid,len=dimlen)
97!       if (ierr.ne.nf90_noerr) then
98!        write(*,*)'soil_settings: Problem getting <subsurface_layers>',
99!     &             'length'
100!        write(*,*)trim(nf90_strerror(ierr))
101!         call abort
102!       endif
103        dimlen=inquire_dimension_length("subsurface_layers")
104
105        if (dimlen.ne.nsoil) then
106          write(*,*)'soil_settings: Interpolation of soil temperature ',
107     &              'and thermal inertia will be required!'
108        ! if dimlen doesn't match nsoil, then interpolation of
109        ! soil temperatures and thermal inertia will be requiered
110          interpol=.true.
111        ! allocate oldmlayer
112        if (.not.allocated(oldmlayer)) then
113          allocate(oldmlayer(dimlen),stat=ierr)
114          if (ierr.ne.0) then
115            write(*,*) 'soil_settings: failed allocation of oldmlayer!'
116            call abort_physic("soil_settings",
117     &           "failed oldmlayer allocation",1)
118          endif
119        endif
120        endif
121
122! 1.2 Find out the # of dimensions <inertiedat> was defined as using
123!     (in ye old days, thermal inertia was only given at the "surface")
124      ! Look for thermal inertia data
125!      ierr=nf90_inq_varid(nid,"inertiedat",nvarid)
126!      if (ierr.NE.nf90_noerr) then
127!         write(*,*)'soil_settings: Field <inertiedat> not found!'
128!         write(*,*)trim(nf90_strerror(ierr))
129!         call abort
130!      endif
131!
132!      ! Read the # of dimensions <inertidat> was defined as using
133!      ierr=nf90_inquire_variable(nid,nvarid,ndims=ndims)
134!      ! if (ndims.eq.1) then we have the "old 2D-surface" format
135      ndims=inquire_field_ndims("inertiedat")
136
137! 1.3 Read depths values or set olddepthdef flag and values
138      if (ndims.eq.1) then ! we know that there is none
139        write(*,*)'soil_settings: no <soildepth> field expected'
140        write(*,*)'building one mimicking old definitions'
141        olddepthdef=.true.
142        interpol=.true.
143
144        do iloop=1,dimlen
145          oldmlayer(iloop)=sqrt(887.75/3.14)*((2.**(iloop-0.5))-1.)
146        enddo
147      else ! Look for depth
148!        ierr=nf90_inq_varid(nid,"soildepth",nvarid)
149!        if (ierr.ne.nf90_noerr) then
150!          write(*,*)'soil_settings: Field <soildepth> not found!'
151!          write(*,*)trim(nf90_strerror(ierr))
152!         call abort
153!        endif
154        ! read <depth> coordinate
155        if (interpol) then !put values in oldmlayer
156!          ierr=nf90_get_var(nid,nvarid,oldmlayer)
157!          if (ierr.ne.nf90_noerr) then
158!           write(*,*)'soil_settings: Problem while reading <soildepth>'
159!           write(*,*)trim(nf90_strerror(ierr))
160!           call abort
161!          endif
162          call get_var("soildepth",oldmlayer,found)
163          if (.not.found) then
164            write(*,*)'soil_settings: Problem while reading <soildepth>'
165          endif
166        else ! put values in mlayer
167!          ierr=nf90_get_var(nid,nvarid,mlayer)
168!          if (ierr.ne.nf90_noerr) then
169!           write(*,*)'soil_settings: Problem while reading <soildepth>'
170!           write(*,*)trim(nf90_strerror(ierr))
171!           call abort
172!          endif
173          call get_var("soildepth",mlayer,found)
174          if (.not.found) then
175            write(*,*)'soil_settings: Problem while reading <soildepth>'
176          endif
177        endif !of if (interpol)
178      endif !of if (ndims.eq.1)
179
180! 1.4 Build mlayer(), if necessary
181      if (interpol) then
182      ! default mlayer distribution, following a power law:
183      !  mlayer(k)=lay1*alpha**(k-1/2)
184        lay1=2.e-4
185        alpha=2
186        do iloop=0,nsoil-1
187          mlayer(iloop)=lay1*(alpha**(iloop-0.5))
188        enddo
189      endif
190
191! 1.5 Build layer(); following the same law as mlayer()
192      ! Assuming layer distribution follows mid-layer law:
193      ! layer(k)=lay1*alpha**(k-1)
194      lay1=sqrt(mlayer(0)*mlayer(1))
195      alpha=mlayer(1)/mlayer(0)
196      do iloop=1,nsoil
197        layer(iloop)=lay1*(alpha**(iloop-1))
198      enddo
199
200! 2. Volumetric heat capacity (note: it is declared in comsoil_h)
201! ---------------------------
202! "volcapa" is (so far) 0D and written in "controle" table of startfi file
203! volcapa is read or set when "controle" is read (see tabfi.F)
204! Just in case, we check here that it is not zero. If it is, we
205! set it to "default_volcapa"
206
207      if (volcapa.le.0.0) then
208        write(*,*)'soil_settings: Warning, volcapa = ',volcapa
209        write(*,*)'               That doesn t seem right'
210        write(*,*)'        Initializing Volumetric heat capacity to ',
211     &             default_volcapa
212        volcapa=default_volcapa
213      endif
214! Look for it
215!      ierr=NF_INQ_VARID(nid,"volcapa",nvarid)
216!      if (ierr.NE.nf90_noerr) then
217!         write(*,*)'soil_settings: Field <volcapa> not found!'
218!         write(*,*)'Initializing Volumetric heat capacity to ',
219!     &             default_volcapa
220!         volcapa=default_volcapa
221!      else
222!#ifdef NC_DOUBLE
223!       ierr = NF_GET_VAR_DOUBLE(nid,nvarid,volcapa)
224!#else
225!       ierr = NF_GET_VAR_REAL(nid,nvarid,volcapa)
226!#endif
227!        if (ierr.ne.nf90_noerr) then
228!         write(*,*)'soil_settings: Problem while reading <volcapa>'
229!         call abort
230!       endif
231!      endif
232
233! 3. Thermal inertia (note: it is declared in comsoil_h)
234! ------------------
235
236! 3.1 Look (again) for thermal inertia data (to reset nvarid)
237!      ierr=nf90_inq_varid(nid,"inertiedat",nvarid)
238!      if (ierr.NE.nf90_noerr) then
239!         write(*,*)'soil_settings: Field <inertiedat> not found!'
240!         write(*,*)trim(nf90_strerror(ierr))
241!         call abort
242!      endif
243
244! 3.2 Knowing the # of dimensions <inertidat> was defined as using,
245!     read/build thermal inertia
246
247      if (ndims.eq.1) then ! "old 2D-surface" format
248       write(*,*)'soil_settings: Thermal inertia is only given as surfac
249     &e data!'
250       ! Read Surface thermal inertia
251       allocate(surfinertia(ngrid))
252!       ierr=nf90_get_var(nid,nvarid,surfinertia)
253!        if (ierr.NE.nf90_noerr) then
254!         write(*,*)'soil_settings: Problem while reading <inertiedat>'
255!         write(*,*)trim(nf90_strerror(ierr))
256!         call abort
257!        endif
258       call get_field("inertiedat",surfinertia,found)
259       if (.not.found) then
260         write(*,*) "soil_settings: Failed loading <inertiedat>"
261         call abort_physic("soil_settings",
262     &        "failed loading <inertiedat>",1)
263       endif
264       
265       write(*,*)' => Building soil thermal inertia (using reference sur
266     &face thermal inertia)'
267       do iloop=1,nsoil
268         inertiedat(:,iloop)=surfinertia(:)
269       enddo
270       deallocate(surfinertia)
271
272      else ! "3D surface+depth" format
273       if (interpol) then ! put values in oldinertiedat
274         if (.not.allocated(oldinertiedat)) then
275           allocate(oldinertiedat(ngrid,dimlen),stat=ierr)
276           if (ierr.ne.0) then
277            write(*,*) 'soil_settings: failed allocation of ',
278     &                 'oldinertiedat!'
279            call abort_physic("soil_settings",
280     &        "failed allocation of oldinertiedat",1)
281           endif
282         endif ! of if (.not.allocated(oldinertiedat))
283!         ierr=nf90_get_var(nid,nvarid,oldinertiedat)
284!        if (ierr.NE.nf90_noerr) then
285!         write(*,*)'soil_settings: Problem while reading <inertiedat>'
286!         write(*,*)trim(nf90_strerror(ierr))
287!         call abort
288!        endif
289        call get_field("inertiedat",oldinertiedat,found)
290        if (.not.found) then
291          write(*,*) "soil_settings: Failed loading <inertiedat>"
292         call abort_physic("soil_settings",
293     &        "failed loading <inertiedat>",1)
294        endif
295       else ! put values in therm_i
296!        ierr=nf90_get_var(nid,nvarid,inertiedat)
297!        if (ierr.NE.nf90_noerr) then
298!         write(*,*)'soil_settings: Problem while reading <inertiedat>'
299!         write(*,*)trim(nf90_strerror(ierr))
300!         call abort
301         call get_field("inertiedat",inertiedat,found)
302         if (.not.found) then
303           write(*,*) "soil_settings: Failed loading <inertiedat>"
304           call abort_physic("soil_settings",
305     &        "failed loading <inertiedat>",1)
306         endif
307!        endif
308       endif ! of if (interpol)
309      endif ! of if (ndims.eq.1)
310     
311! 4. Read soil temperatures
312! -------------------------
313
314!      ierr=nf90_inq_varid(nid,"tsoil",nvarid)
315      ok=inquire_field("tsoil")
316!      if (ierr.ne.nf90_noerr) then
317      if (.not.ok) then
318        write(*,*)'soil_settings: Field <tsoil> not found!'
319        write(*,*)' => Building <tsoil> from surface values <tsurf>'
320        do iloop=1,nsoil
321          do islope=1,nslope
322            tsoil(:,iloop,islope)=tsurf(:,islope)
323          enddo
324        enddo
325      else ! <tsoil> found
326       if (interpol) then ! put values in oldtsoil
327         if (.not.allocated(oldtsoil)) then
328           allocate(oldtsoil(ngrid,dimlen,nslope),stat=ierr)
329           if (ierr.ne.0) then
330             write(*,*) 'soil_settings: failed allocation of ',
331     &                  'oldtsoil!'
332             call abort_physic("soil_settings",
333     &        "failed allocation of oldtsoil",1)
334           endif
335         endif
336!        ierr=nf90_get_var(nid,nvarid,oldtsoil)
337!        if (ierr.ne.nf90_noerr) then
338!        write(*,*)'soil_settings: Problem while reading <tsoil>'
339!         write(*,*)trim(nf90_strerror(ierr))
340!        call abort
341!       endif
342         call get_field("tsoil",oldtsoil,found)
343         if (.not.found) then
344           write(*,*) "soil_settings: Failed loading <tsoil>"
345           call abort_physic("soil_settings",
346     &          "failed loading <tsoil>",1)
347         endif
348       else ! put values in tsoil
349!        corner(1)=1
350!        corner(2)=1
351!        corner(3)=indextime
352!        edges(1)=ngrid
353!        edges(2)=nsoil
354!        edges(3)=1
355!        !ierr=nf90_get_var(nid,nvarid,tsoil,corner,edges)
356!        ierr=nf90_get_var(nid,nvarid,tsoil)
357!        if (ierr.ne.nf90_noerr) then
358!        write(*,*)'soil_settings: Problem while reading <tsoil>'
359!         write(*,*)trim(nf90_strerror(ierr))
360!        call abort
361!       endif
362         call get_field("tsoil",tsoil,found,timeindex=indextime)
363         if (.not.found) then
364           write(*,*) "soil_settings: Failed loading <tsoil>"
365           call abort_physic("soil_settings",
366     &          "failed loading <tsoil>",1)
367         endif
368       endif ! of if (interpol)
369      endif! of if (.not.ok)
370
371! 5. If necessary, interpolate soil temperatures and thermal inertias
372! -------------------------------------------------------------------
373
374      if (olddepthdef) then
375      ! tsoil needs to be interpolated, but not therm_i
376        allocate(oldgrid(dimlen+1))
377        allocate(oldval(dimlen+1))
378        allocate(newval(nsoil))
379
380        do ig=1,ngrid
381          ! copy values
382          do islope=1,nslope
383          oldval(1)=tsurf(ig,islope)
384          oldval(2:dimlen+1)=oldtsoil(ig,1:dimlen,islope)
385          ! build vertical coordinate
386          oldgrid(1)=0. ! ground
387          oldgrid(2:dimlen+1)=oldmlayer(1:dimlen)*
388     &                (inertiedat(ig,1)/volcapa)
389          ! interpolate
390          call interp_line(oldgrid,oldval,dimlen+1,mlayer,newval,nsoil)
391          ! copy result in tsoil
392          tsoil(ig,:,islope)=newval(:)
393          enddo
394        enddo
395
396        ! cleanup
397        deallocate(oldgrid)
398        deallocate(oldval)
399        deallocate(newval)
400        interpol=.false. ! no need for interpolation any more     
401      endif !of if (olddepthdef)
402
403      if (interpol) then
404      write(*,*)'soil_settings: Vertical interpolation along new grid'
405      ! interpolate soil temperatures and thermal inertias
406        if (.not.allocated(oldgrid)) then
407          allocate(oldgrid(dimlen+1))
408          allocate(oldval(dimlen+1))
409          allocate(newval(nsoil))
410        endif
411
412      ! thermal inertia
413        do ig=1,ngrid
414          ! copy data
415          oldval(1:dimlen)=oldinertiedat(ig,dimlen)
416          ! interpolate
417          call interp_line(oldmlayer,oldval,dimlen,mlayer,newval,nsoil)
418          !copy result in inertiedat
419          inertiedat(ig,:)=newval(:)
420        enddo
421       
422      ! soil temperature
423        ! vertical coordinate
424        oldgrid(1)=0.0
425        oldgrid(2:dimlen+1)=oldmlayer(1:dimlen)
426        do ig=1,ngrid
427          do islope=1,nslope
428          ! data
429          oldval(1)=tsurf(ig,islope)
430          oldval(2:dimlen+1)=oldtsoil(ig,1:dimlen,islope)
431          ! interpolate
432          call interp_line(oldgrid,oldval,dimlen+1,mlayer,newval,nsoil)
433          ! copy result in inertiedat
434          tsoil(ig,:,islope)=newval(:)
435          enddo
436        enddo
437       
438        !cleanup
439        deallocate(oldgrid)
440        deallocate(oldval)
441        deallocate(newval)
442        deallocate(oldinertiedat)
443        deallocate(oldtsoil)
444      endif ! of if (interpol)
445
446
447     
448! 6. Load Geothermal Flux
449! ----------------------------------------------------------------------
450
451
452      call get_field("flux_geo",flux_geo,found,timeindex=indextime)
453      if (.not.found) then
454           write(*,*) "soil_settings: Failed loading <flux_geo>"
455           write(*,*) "soil_settings: Will put  <flux_geo> to 0."
456           flux_geo(:,:) = 0.
457      endif
458
459
460     
461! 7. Report min and max values of soil temperatures and thermal inertias
462! ----------------------------------------------------------------------
463
464      write(*,*)
465      write(*,*)'Soil volumetric heat capacity:',volcapa
466
467      xmin = MINVAL(inertiedat)
468      xmax = MAXVAL(inertiedat)
469      write(*,*)'Soil thermal inertia <inertiedat>:',xmin,xmax
470
471      xmin = 1.0E+20
472      xmax = -1.0E+20
473      xmin = MINVAL(tsoil)
474      xmax = MAXVAL(tsoil)
475      write(*,*)'Soil temperature <tsoil>:',xmin,xmax
476
477      end
Note: See TracBrowser for help on using the repository browser.