1 | subroutine setgrid(nz,z,zmax,zfac) |
---|
2 | ! construct regularly or geometrically spaced 1D grid |
---|
3 | ! z(n)-z(1) = 2*z(1)*(zfac**(n-1)-1)/(zfac-1) |
---|
4 | ! choice of z(1) and z(2) is compatible with conductionQ |
---|
5 | implicit none |
---|
6 | integer, intent(IN) :: nz |
---|
7 | real(8), intent(IN) :: zfac, zmax |
---|
8 | real(8), intent(OUT) :: z(nz) |
---|
9 | integer i |
---|
10 | real(8) dz |
---|
11 | |
---|
12 | dz = zmax/nz |
---|
13 | do i=1,nz |
---|
14 | z(i) = (i-0.5)*dz |
---|
15 | enddo |
---|
16 | |
---|
17 | if (zfac>1.) then |
---|
18 | dz = zmax/(3.+2.*zfac*(zfac**(nz-2)-1.)/(zfac-1.)) |
---|
19 | z(1) = dz |
---|
20 | z(2) = 3*z(1) |
---|
21 | do i=3,nz |
---|
22 | z(i) = (1.+zfac)*z(i-1) - zfac*z(i-2) |
---|
23 | ! z(i) = z(i-1) + zfac*(z(i-1)-z(i-2)) ! equivalent |
---|
24 | enddo |
---|
25 | endif |
---|
26 | |
---|
27 | end subroutine setgrid |
---|
28 | |
---|
29 | |
---|
30 | |
---|
31 | real(8) function smartzfac(nz_max,zmax,nz_delta,delta) |
---|
32 | ! output can be used as input to setgrid |
---|
33 | ! produces zfac with desired number of points within depth delta |
---|
34 | implicit none |
---|
35 | integer, intent(IN) :: nz_max, nz_delta |
---|
36 | real(8), intent(IN) :: zmax, delta |
---|
37 | integer j |
---|
38 | real(8) f, g, gprime |
---|
39 | |
---|
40 | if (nz_max<nz_delta .or. nz_delta<=1) then |
---|
41 | stop 'inappropriate input to smartzfac' |
---|
42 | endif |
---|
43 | f = 1.05 |
---|
44 | do j=1,7 ! Newton iteration |
---|
45 | !print *,j,f |
---|
46 | g = (f-3+2*f**(nz_max-1))/(f-3+2*f**(nz_delta-1))-zmax/delta |
---|
47 | gprime=(1+2*(nz_max-1)*f**(nz_max-2))/(f-3+2*f**(nz_delta-1)) - & |
---|
48 | & (f-3+2*f**(nz_max-1))*(1+2*(nz_delta-1)*f**(nz_delta-2))/ & |
---|
49 | & (f-3+2*f**(nz_delta-1))**2 |
---|
50 | f = f-g/gprime |
---|
51 | enddo |
---|
52 | smartzfac = f |
---|
53 | if (smartzfac<1. .or. smartzfac>2.) then |
---|
54 | print *,'zfac=',smartzfac |
---|
55 | stop 'unwanted result in smartzfac' |
---|
56 | endif |
---|
57 | end function smartzfac |
---|
58 | |
---|
59 | |
---|
60 | |
---|
61 | !-grid-dependent utility functions |
---|
62 | |
---|
63 | function colint(y,z,nz,i1,i2) |
---|
64 | ! column integrates y |
---|
65 | implicit none |
---|
66 | integer, intent(IN) :: nz, i1, i2 |
---|
67 | real(8), intent(IN) :: y(nz), z(nz) |
---|
68 | real(8) colint |
---|
69 | integer i |
---|
70 | real(8) dz(nz) |
---|
71 | |
---|
72 | dz(1) = (z(2)-0.)/2 |
---|
73 | do i=2,nz-1 |
---|
74 | dz(i) = (z(i+1)-z(i-1))/2. |
---|
75 | enddo |
---|
76 | dz(nz) = z(nz)-z(nz-1) |
---|
77 | colint = sum(y(i1:i2)*dz(i1:i2)) |
---|
78 | end function colint |
---|
79 | |
---|
80 | |
---|
81 | |
---|
82 | subroutine heatflux_from_temperature(nz,z,T,k,H) |
---|
83 | ! calculates heat flux from temperature profile |
---|
84 | ! like k, the heat flux H is defined mid-point |
---|
85 | implicit none |
---|
86 | integer, intent(IN) :: nz |
---|
87 | real(8), intent(IN) :: z(nz), T(nz), k(nz) |
---|
88 | real(8), intent(OUT) :: H(nz) |
---|
89 | integer j |
---|
90 | |
---|
91 | ! H(1) = -k(1)*(T(1)-Tsurf)/z(1) |
---|
92 | H(1) = 0. ! to avoid ill-defined value |
---|
93 | do j=2,nz |
---|
94 | H(j) = -k(j)*(T(j)-T(j-1))/(z(j)-z(j-1)) |
---|
95 | enddo |
---|
96 | end subroutine heatflux_from_temperature |
---|