source: trunk/LMDZ.COMMON/libf/evolution/conductionQ.f90 @ 3470

Last change on this file since 3470 was 3470, checked in by evos, 4 weeks ago

we added the option to use NS dynamical subsurface ice in the model to more realisticly calculate the amount of ice in the subsurface and therfore the subsurface thermal inertia

File size: 4.2 KB
Line 
1subroutine conductionQ(nz,z,dt,Qn,Qnp1,T,ti,rhoc,emiss,Tsurf, &
2     &     Fgeotherm,Fsurf)
3!***********************************************************************
4!   conductionQ:  program to calculate the diffusion of temperature
5!                 into the ground and thermal emission at the surface
6!                 with variable thermal properties on irregular grid
7!   Crank-Nicolson scheme, flux conservative
8!                          uses Samar's radiation formula
9!   Eqn: rhoc*T_t = (k*T_z)_z
10!   BC (z=0): Q(t) + kT_z = em*sig*T^4
11!   BC (z=L): heat flux = Fgeotherm
12!
13!   nz = number of grid points
14!   dt = time step
15!   Qn,Qnp1 = net solar insolation at time steps n and n+1 [W/m^2]
16!   T = vertical temperature profile [K]  (in- and output) 
17!   ti = thermal inertia [J m^-2 K^-1 s^-1/2]  VECTOR
18!   rhoc = rho*c  VECTOR where rho=density [kg/m^3] and
19!                              c=specific heat [J K^-1 kg^-1]
20!   ti and rhoc are not allowed to vary in the layers immediately
21!               adjacent to the surface or the bottom
22!   emiss = emissivity
23!   Tsurf = surface temperature [K]  (in- and output)
24!   Fgeotherm = geothermal heat flux at bottom boundary [W/m^2]
25!   Fsurf = heat flux at surface [W/m^2]  (output)
26!
27!   Grid: surface is at z=0
28!         z(0)=0, z(2)=3*z(1), i.e., the top layer has half the width
29!         T(1) is at z(1); ...; T(i) is at z(i)
30!         k(i), rhoc(i), ti(i) are midway between z(i-1) and z(i)
31!     
32!   originally written by Samar Khatiwala, 2001
33!   extended to variable thermal properties
34!         and irregular grid by Norbert Schorghofer
35!   added predictor-corrector 9/2019 
36!***********************************************************************
37
38  implicit none
39  real*8, parameter :: sigSB=5.6704d-8
40 
41  integer, intent(IN) :: nz
42  real*8, intent(IN) :: z(nz), dt, Qn, Qnp1, ti(nz),rhoc(nz)
43  real*8, intent(IN) :: emiss, Fgeotherm
44  real*8, intent(INOUT) :: T(nz), Tsurf
45  real*8, intent(OUT) :: Fsurf
46  integer i, iter
47  real*8 k(nz), k1, alpha(nz), gamma(nz), Tr
48  real*8 a(nz), b(nz), c(nz), r(nz), Told(nz)
49  real*8 arad, brad, ann, annp1, bn, buf, dz, beta
50 
51  ! set some constants
52  k(:) = ti(:)**2/rhoc(:) ! thermal conductivity
53  dz = 2.*z(1)
54  beta = dt/rhoc(1)/(2.*dz**2)   ! assumes rhoc(0)=rhoc(1)
55  alpha(1) = beta*k(2)
56  gamma(1) = beta*k(1)
57  do i=2,nz-1
58     buf = dt/(z(i+1)-z(i-1))
59     alpha(i) = 2.*k(i+1)*buf/(rhoc(i)+rhoc(i+1))/(z(i+1)-z(i))
60     gamma(i) = 2.*k(i)*buf/(rhoc(i)+rhoc(i+1))/(z(i)-z(i-1))
61  enddo
62  buf = dt/(z(nz)-z(nz-1))**2
63  gamma(nz) = k(nz)*buf/(2*rhoc(nz)) ! assumes rhoc(nz+1)=rhoc(nz)
64 
65  k1 = k(1)/dz
66 
67  ! elements of tridiagonal matrix
68  a(:) = -gamma(:)   !  a(1) is not used
69  b(:) = 1. + alpha(:) + gamma(:) !  b(1) has to be reset at every timestep
70  c(:) = -alpha(:)   !  c(nz) is not used
71  b(nz) = 1. + gamma(nz)
72
73  Tr = Tsurf            ! 'reference' temperature
74  iter = 0
75  Told(:) = T(:)
7630 continue  ! in rare case of iterative correction
77
78  ! Emission
79  arad = -3.*emiss*sigSB*Tr**4
80  brad = 2.*emiss*sigSB*Tr**3
81  ann = (Qn-arad)/(k1+brad)
82  annp1 = (Qnp1-arad)/(k1+brad)
83  bn = (k1-brad)/(k1+brad)
84  b(1) = 1. + alpha(1) + gamma(1) - gamma(1)*bn
85 
86  ! Set RHS         
87  r(1) = gamma(1)*(annp1+ann) + &
88       &     (1.-alpha(1)-gamma(1)+gamma(1)*bn)*T(1) + alpha(1)*T(2)
89  do concurrent (i=2:nz-1)
90     r(i) = gamma(i)*T(i-1) + (1.-alpha(i)-gamma(i))*T(i)+ alpha(i)*T(i+1)
91  enddo
92  r(nz) = gamma(nz)*T(nz-1) + (1.-gamma(nz))*T(nz) &
93       &     + dt/rhoc(nz)*Fgeotherm/(z(nz)-z(nz-1)) ! assumes rhoc(nz+1)=rhoc(nz)
94
95  ! Solve for T at n+1
96  call tridag(a,b,c,r,T,nz) ! update by tridiagonal inversion
97 
98  Tsurf = 0.5*(annp1 + bn*T(1) + T(1)) ! (T0+T1)/2
99
100  ! iterative predictor-corrector
101  if ((Tsurf > 1.2*Tr .or. Tsurf < 0.8*Tr) .and. iter<10) then  ! linearization error expected
102     ! redo until Tr is within 20% of new surface temperature
103     ! (under most circumstances, the 20% threshold is never exceeded)
104     iter = iter+1
105     Tr = sqrt(Tr*Tsurf)  ! linearize around an intermediate temperature
106     T(:) = Told(:)
107     goto 30
108  endif
109  !if (iter>=5) print *,'consider taking shorter time steps',iter
110  !if (iter>=10) print *,'warning: too many iterations'
111 
112  Fsurf = - k(1)*(T(1)-Tsurf)/z(1) ! heat flux into surface
113end subroutine conductionQ
Note: See TracBrowser for help on using the repository browser.