!copyright (C) 2001 MSC-RPN COMM %%%RPNPHY%%%
*** S/P SURFACE
SUBROUTINE SURFACE ( 1,16
$ D, DSIZ, F, FSIZ, V, VSIZ,
$ WORK, ESPWORK, SELOC, TRNCH,
$ KOUNT, DT, NI, M, NK, TASK
$ )
*
#include "impnone.cdk"
*
INTEGER DSIZ, FSIZ, VSIZ, ESPWORK
INTEGER TRNCH,KOUNT,NI,M, NK, TASK
*
REAL DT
REAL D(DSIZ), F(FSIZ), V(VSIZ), WORK(ESPWORK), SELOC(M,NK)
*
*Author
* B. Bilodeau (Dec 1998)
*
*Revisions
*
* 001 J. Mailhot (Jul 2000) - Changes to add MOISTKE option (ifluvert=3)
* 002 B. Bilodeau (Mar 2003) - Convert aggregated value of SNODP to cm
* 003 Y. Delage (Aug 2003) - ILMO truncated between -100 and +100
* 004 M. Roch and B. Bilodeau (Jan 2002) - Eliminate unit conversion for snodp
* 005 Y. Delage (Oct 2003) - ILMO truncated between -10 and +10
* 006 B. Bilodeau (Feb 2004) - Move call to fisimp3 from surface to phyexe1
* 007 B. Bilodeau (Feb 2004) - Revised logic to facilitate the
* addition of new types of surface
*
*
*Object
* this is the main interface subroutine
* for the surface processes
*
*Arguments
*
* - Input/Output -
* D dynamic bus
* F permanent variables bus
* V volatile (output) bus
* WORK physics work space
*
* - Input -
* DSIZ dimension of D
* FSIZ dimension of F
* VSIZ dimension of V
* ESPWORK dimension of WORK
*
* - Input -
* TRNCH row number
* KOUNT timestep number
* DT length of timestep
* NI number of elements processed in the horizontal
* (could be a subset of M in future versions)
* M horizontal dimensions of fields
* (not used for the moment)
* NK vertical dimension
* TASK task number
*
*
*Notes
*
*IMPLICITES
*
#include "stk.cdk"
#include "options.cdk"
#include "consphy.cdk"
#include "surfacepar.cdk"
*
*MODULES
*
**
logical do_glaciers, do_ice
*
integer i, icpu, ik, j, jk, k, x, ptr
integer sommet
integer ni_soil, ni_glacier, ni_water, ni_ice
integer siz_soil, siz_glacier, siz_water, siz_ice
*
real lemin, lemax, mask, sc
*
#include "zuzt.cdk"
#include "nbvarsurf.cdk"
#include "dimsurf.cdk"
*
real zun,ztn
pointer (zun_ , zun (1 ))
pointer (ztn_ , ztn (1 ))
*
* les poids
real poids
pointer(poids_ , poids (ni,nsurf+1))
*
* les "rangs" (dans l'espace de la grille complete)
integer rangs
pointer(rangs_ , rangs (ni,nsurf+1))
*
* les "rangs" (dans chacun des 4 espaces
* correspondant aux 4 types de surfaces)
integer rg_soil, rg_glacier, rg_water, rg_ice
pointer (rg_soil_ , rg_soil (1 ))
pointer (rg_glacier_ , rg_glacier (1 ))
pointer (rg_water_ , rg_water (1 ))
pointer (rg_ice_ , rg_ice (1 ))
*
* les bus
real bus_soil, bus_glacier, bus_water, bus_ice
pointer(bus_soil_ , bus_soil (1 ))
pointer(bus_glacier_ , bus_glacier(1 ))
pointer(bus_water_ , bus_water (1 ))
pointer(bus_ice_ , bus_ice (1 ))
*
* les pointeurs
integer ptr_soil, ptr_glacier, ptr_water, ptr_ice
pointer (ptr_soil_ , ptr_soil (1 ))
pointer (ptr_glacier_, ptr_glacier(1 ))
pointer (ptr_water_ , ptr_water (1 ))
pointer (ptr_ice_ , ptr_ice (1 ))
*
*
#include "phy_macros_f.h"
#include "phybus.cdk"
*
* fonction-formule
ik(i,k) = (k-1)*ni + i -1
*
*
* work space initialization
STK_INITA (work, espwork)
*
*VDIR NODEP
do i=1,ni
v(za+i-1) = -rgasd/grav* v(tve+ik(i,nk-1)) *
+ alog(d(sigm+ik(i,nk-1)))
sc = d(sigm+ik(i,nk-1))**(-cappa)
v(thetaa+i-1) = sc*d(tmoins+ik(i,nk-1))
v(fcor +i-1)= 1.45441e-4*sin(f(dlat+i-1))
*
end do
*
* Phase of the precipitation reaching
* the surface.
*
CALL SURF_PRECIP
( d(TMOINS+(nk-2)*ni),
+ f(TLC), f(TLS), f(TSC), f(TSS),
+ v(rainrate), v(snowrate), ni )
*
*
if (ifluvert.ge.2) then ! CLEF OR MOISTKE
*
poids_ = loc(v(sfcwgt))
*
STK_ALLOC (rangs_ , ni*(nsurf+1))
STK_ALLOC (rg_water_ , ni )
STK_ALLOC (rg_soil_ , ni )
STK_ALLOC (rg_ice_ , ni )
STK_ALLOC (rg_glacier_ , ni )
STK_ALLOC (ptr_water_ , nvarsurf )
STK_ALLOC (ptr_soil_ , nvarsurf )
STK_ALLOC (ptr_ice_ , nvarsurf )
STK_ALLOC (ptr_glacier_, nvarsurf )
*
* mg, glsea et glacier doivent etre bornes entre 0 et 1
* pour que les poids soient valides
*VDIR NODEP
do i=1,ni
lemin = min(f(mg+i-1),f(glsea+i-1),f(glacier+i-1))
lemax = max(f(mg+i-1),f(glsea+i-1),f(glacier+i-1))
if (lemin.lt.0. .or. lemax.gt.1.) then
write(6,1000)
call qqexit(1)
endif
end do
*
* calcul des poids
*VDIR NODEP
do i=1,ni
*
mask = f(mg+i-1)
if (mask.gt.(1.-critmask)) then
mask = 1.0
else if (mask.lt. critmask ) then
mask = 0.0
endif
*
* sol
poids(i,indx_soil) = mask * (1.-f(glacier+i-1))
*
* glaciers continentaux
poids(i,indx_glacier) = mask * f(glacier+i-1)
*
* eau
poids(i,indx_water) = (1.-mask) * (1.-f(glsea +i-1))
*
* glace marine
poids(i,indx_ice) = (1.-mask) * f(glsea +i-1)
*
end do
*
do i=1,ni
rg_soil (i) = 0
rg_glacier(i) = 0
rg_water (i) = 0
rg_ice (i) = 0
end do
*
do i=1,ni*(nsurf+1)
rangs(i,1) = 0
end do
*
ni_water = 0
ni_ice = 0
ni_soil = 0
ni_glacier = 0
*
* definition des "rangs"
*
if (agregat) then
*
* agregation
* ----------
*
*VDIR NODEP
do i=1,ni
*
if (poids(i,indx_soil).gt.0.0) then
ni_soil = ni_soil + 1
rangs(i,indx_soil) = ni_soil
rg_soil(ni_soil) = i
endif
*
if (poids(i,indx_glacier).gt.0.0) then
ni_glacier = ni_glacier + 1
rangs(i,indx_glacier) = ni_glacier
rg_glacier(ni_glacier) = i
endif
*
if (poids(i,indx_water).gt.0.0) then
ni_water = ni_water + 1
rangs(i,indx_water) = ni_water
rg_water(ni_water) = i
endif
*
if (poids(i,indx_ice).gt.0.0) then
ni_ice = ni_ice + 1
rangs(i,indx_ice) = ni_ice
rg_ice(ni_ice) = i
endif
*
end do
*
*
else if (.not.agregat) then
*
* pas d'agregation
* ----------------
*
do i=1,ni
*
if (f(mg +i-1).ge.0.5 .and.
$ f(glacier+i-1).lt.0.5) then
*
ni_soil = ni_soil + 1
rg_soil(ni_soil ) = i
poids (i,indx_soil ) = 1.0
poids (i,indx_glacier) = 0.0
poids (i,indx_water ) = 0.0
poids (i,indx_ice ) = 0.0
*
else if (f(mg +i-1).ge.0.5 .and.
$ f(glacier+i-1).ge.0.5) then
*
ni_glacier = ni_glacier + 1
rg_glacier(ni_glacier ) = i
poids (i,indx_soil ) = 0.0
poids (i,indx_glacier ) = 1.0
poids (i,indx_water ) = 0.0
poids (i,indx_ice ) = 0.0
*
else if (f(mg +i-1).lt.0.5 .and.
$ f(glsea+i-1).lt.0.5) then
*
ni_water = ni_water + 1
rg_water(ni_water ) = i
poids (i,indx_soil ) = 0.0
poids (i,indx_glacier) = 0.0
poids (i,indx_water ) = 1.0
poids (i,indx_ice ) = 0.0
*
*
else if (f(mg +i-1).lt.0.5 .and.
$ f(glsea+i-1).ge.0.5) then
*
ni_ice = ni_ice + 1
rg_ice (ni_ice ) = i
poids (i,indx_soil ) = 0.0
poids (i,indx_glacier) = 0.0
poids (i,indx_water ) = 0.0
poids (i,indx_ice ) = 1.0
*
endif
*
end do
*
endif
*
*
*******************************
* *
* SOIL *
* ---- *
* *
*******************************
*
sommet = 1
*VDIR NODEP
do i=1,nvarsurf
ptr_soil(i) = sommet
sommet = sommet + niveaux(i) * mul(i) * ni_soil
end do
*
* Lorsque surfesptot =0, bus_soil ne contient
* qu'un element et il est egal a zero (voir s/p agrege).
siz_soil = max(surfesptot*ni_soil,1)
*
if (siz_soil.eq.1) then
*
STK_ALLOC (bus_soil_ , 1 )
*
bus_soil(1) = 0.
*
else if (siz_soil.gt.1) then
*
STK_ALLOC (bus_soil_ , siz_soil )
*
do i=1,siz_soil
bus_soil(i) = 0.0
end do
*
* transvidage des 3 bus dans bus_soil
call copybus
(bus_soil, d , f , v ,
$ siz_soil, dsiz, fsiz, vsiz,
$ ptr_soil, nvarsurf,
$ rg_soil, ni_soil,
$ ni, indx_soil, agregat, .true.)
*
if (ischmsol.eq.1) then
call force_restore
(
$ bus_soil, siz_soil,
$ ptr_soil, nvarsurf,
$ kount, trnch,
$ ni_soil, ni_soil, nk-1, icpu )
*
* else if (ischmsol.eq.2) then
*
* call class270
*
else if (ischmsol.eq.3) then
*
call isba2
(bus_soil, siz_soil,
$ ptr_soil, nvarsurf,
$ dt, kount, trnch,
$ ni_soil, ni_soil, nk-1)
*
endif
*
call copybus
(bus_soil, d , f , v ,
$ siz_soil, dsiz, fsiz, vsiz,
$ ptr_soil, nvarsurf,
$ rg_soil, ni_soil,
$ ni, indx_soil, agregat, .false.)
*
endif
*
*
*******************************
* *
* WATER *
* ----- *
* *
*******************************
*
sommet = 1
*VDIR NODEP
do i=1,nvarsurf
ptr_water(i) = sommet
sommet = sommet + niveaux(i) * mul(i) * ni_water
end do
*
siz_water = max(surfesptot*ni_water,1)
*
if (siz_water.eq.1) then
*
STK_ALLOC (bus_water_ , 1 )
*
bus_water(1) = 0.
*
else if (siz_water.gt.1) then
*
STK_ALLOC (bus_water_ , siz_water)
*
do i=1,siz_water
bus_water(i) = 0.0
end do
* transvidage des 3 bus dans bus_water
call copybus
(bus_water, d , f , v ,
$ siz_water, dsiz, fsiz, vsiz,
$ ptr_water, nvarsurf,
$ rg_water, ni_water,
$ ni, indx_water, agregat, .true.)
*
call water
( bus_water, siz_water,
$ ptr_water, nvarsurf,
$ trnch, kount,
$ ni_water, ni_water,
$ nk-1)
*
call copybus
(bus_water, d , f , v ,
$ siz_water, dsiz, fsiz, vsiz,
$ ptr_water, nvarsurf,
$ rg_water, ni_water,
$ ni, indx_water, agregat, .false.)
*
endif
*
*
*******************************
* *
* OCEANIC ICE *
* ----------- *
* *
*******************************
*
sommet = 1
*VDIR NODEP
do i=1,nvarsurf
ptr_ice(i) = sommet
sommet = sommet + niveaux(i) * mul(i) * ni_ice
end do
*
siz_ice = max(surfesptot*ni_ice,1)
*
if (siz_ice.eq.1) then
*
do_ice = .false.
*
STK_ALLOC (bus_ice_ , 1 )
*
bus_ice(1) = 0.
*
else if (siz_ice.gt.1) then
*
do_ice = .true.
*
STK_ALLOC (bus_ice_ , siz_ice )
*
do i=1,siz_ice
bus_ice(i) = 0.0
end do
* transvidage des 3 bus dans bus_ice
call copybus
(bus_ice, d , f , v ,
$ siz_ice, dsiz, fsiz, vsiz,
$ ptr_ice, nvarsurf,
$ rg_ice, ni_ice,
$ ni, indx_ice, agregat, .true.)
*
call seaice1
( bus_ice, siz_ice,
$ ptr_ice, nvarsurf,
$ trnch, kount,
$ ni_ice,
$ ni_ice, nk-1)
*
call copybus
(bus_ice, d , f , v ,
$ siz_ice, dsiz, fsiz, vsiz,
$ ptr_ice, nvarsurf,
$ rg_ice, ni_ice,
$ ni, indx_ice, agregat, .false.)
*
endif
*
*
*******************************
* *
* CONTINENTAL ICE *
* --------------- *
* *
*******************************
*
*
sommet = 1
*VDIR NODEP
do i=1,nvarsurf
ptr_glacier(i) = sommet
sommet = sommet + niveaux(i) * mul(i) * ni_glacier
end do
*
siz_glacier = max(surfesptot*ni_glacier,1)
*
if (siz_glacier.eq.1) then
*
do_glaciers = .false.
*
STK_ALLOC (bus_glacier_, 1 )
*
bus_glacier(1) = 0.
*
else if (siz_glacier.gt.1) then
*
do_glaciers = .true.
*
STK_ALLOC (bus_glacier_, siz_glacier)
*
do i=1,siz_glacier
bus_glacier(i) = 0.0
end do
* transvidage des 3 bus dans bus_glacier
call copybus
(bus_glacier, d , f , v ,
$ siz_glacier, dsiz, fsiz, vsiz,
$ ptr_glacier, nvarsurf,
$ rg_glacier, ni_glacier,
$ ni, indx_glacier, agregat, .true.)
*
call glaciers1
( bus_glacier, siz_glacier,
$ ptr_glacier, nvarsurf,
$ trnch, kount,
$ ni_glacier, ni_glacier, nk-1)
*
call copybus
(bus_glacier, d , f , v ,
$ siz_glacier, dsiz, fsiz, vsiz,
$ ptr_glacier, nvarsurf,
$ rg_glacier, ni_glacier,
$ ni, indx_glacier, agregat, .false.)
*
endif
*
*
*
*******************************
* *
* AGREGATION *
* ---------- *
* *
*******************************
*
if (agregat) then
*
call agrege
( d , f , v ,
$ dsiz, fsiz, vsiz,
$ bus_soil, bus_glacier, bus_water, bus_ice,
$ siz_soil, siz_glacier, siz_water, siz_ice,
$ ni_soil, ni_glacier, ni_water, ni_ice,
$ ptr_soil, ptr_glacier, ptr_water, ptr_ice,
$ nvarsurf,
$ rangs, poids, ni,
$ do_glaciers, do_ice)
*
endif
*
endif
*
*
********************************************
* CORRECTIF POUR LA SORTIE *
* ----------------------------------- *
********************************************
*
do i=0,ni-1
v(sfcwgt+(indx_agrege-1)*ni+i) = 1.0
end do
*
do i=0,5*ni-1
* changement d'unites : m vers cm
f(snodp+i) = 100. * f(snodp+i)
f(ilmo+i)=max(-100.,min(100.,f(ilmo+i)))
end do
*
********************************************
* DIAGNOSTICS *
* ----------- *
********************************************
*
* series temporelles et diagnostics zonaux
call diagnosurf
(f,v,fsiz,vsiz,ni,ni,nk,trnch,task)
*
* Relacher l'espace de travail
STK_FREE
*
*
1000 FORMAT (//2(1x,60('*')/),1x,'*',58(' '),'*'/
+ 1x,'*',11(' '),'INVALID WEIGHTS FOR SURFACE',
+ 20(' '),'*'/1x,'*',11(' '),
+ 'PROCESSES IN SUBROUTINE "SURFACE"',
+ 14(' '),'*'/(1x,'*',58(' '),'*'/),
+ ' *',11(' '),'MAKE SURE THAT # LAND-SEA MASK',17(' '),'*'
+ /1x,'*',26(' '),'# SEA ICE FRACTION',14(' '),'*'/,
+ ' *',26(' '),'# FRACTION OF GLACIERS',10(' '),'*'/
+ ' *',11(' '),'ARE BOUNDED BETWEEN 0 AND 1',20(' '),'*'/
+ (1x,'*',58(' '),'*'/),
+ ' *',58(' '),'*'/2(1x,60('*')/))
*
return
end