-
Notifications
You must be signed in to change notification settings - Fork 322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix interp. of surfdat soil layers so we can use interp. for 10SL case #771
Changes from 2 commits
d885079
40a5881
9986578
aadb3c5
3cf9ae7
d8f31b3
789554e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -148,7 +148,6 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) | |
type(file_desc_t) :: ncid ! netcdf id | ||
real(r8) ,pointer :: zsoifl (:) ! Output: [real(r8) (:)] original soil midpoint | ||
real(r8) ,pointer :: zisoifl (:) ! Output: [real(r8) (:)] original soil interface depth | ||
real(r8) ,pointer :: dzsoifl (:) ! Output: [real(r8) (:)] original soil thickness | ||
real(r8) ,pointer :: gti (:) ! read in - fmax | ||
real(r8) ,pointer :: sand3d (:,:) ! read in - soil texture: percent sand (needs to be a pointer for use in ncdio) | ||
real(r8) ,pointer :: clay3d (:,:) ! read in - soil texture: percent clay (needs to be a pointer for use in ncdio) | ||
|
@@ -303,22 +302,22 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) | |
! get original soil depths to be used in interpolation of sand and clay | ||
! -------------------------------------------------------------------- | ||
|
||
allocate(zsoifl(1:nlevsoifl), zisoifl(0:nlevsoifl), dzsoifl(1:nlevsoifl)) | ||
do j = 1, nlevsoifl | ||
zsoifl(j) = 0.025*(exp(0.5_r8*(j-0.5_r8))-1._r8) !node depths | ||
enddo | ||
|
||
dzsoifl(1) = 0.5_r8*(zsoifl(1)+zsoifl(2)) !thickness b/n two interfaces | ||
do j = 2,nlevsoifl-1 | ||
dzsoifl(j)= 0.5_r8*(zsoifl(j+1)-zsoifl(j-1)) | ||
! Note that the depths on the file are assumed to be the same as the depths in the | ||
! model when running with 10SL_3.5m. Ideally zsoifl and zisoifl would be read from | ||
! the surface dataset rather than assumed here. | ||
! | ||
! We need to specify zsoifl down to nlevsoifl+1 (rather than just nlevsoifl) so that | ||
! we can get the appropriate zisoifl at level nlevsoifl (i.e., the bottom interface | ||
! depth). | ||
allocate(zsoifl(1:nlevsoifl+1), zisoifl(0:nlevsoifl)) | ||
do j = 1, nlevsoifl+1 | ||
zsoifl(j) = 0.025_r8*(exp(0.5_r8*(j-0.5_r8))-1._r8) !node depths | ||
enddo | ||
dzsoifl(nlevsoifl) = zsoifl(nlevsoifl)-zsoifl(nlevsoifl-1) | ||
|
||
zisoifl(0) = 0._r8 | ||
do j = 1, nlevsoifl-1 | ||
do j = 1, nlevsoifl | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Diff (3) from my main PR comment (and related changes around here): changing definition of zisoifl for lowest level There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Considering zsoifl represents the depths in the soil texture file, we introduce an abstraction here by defining a zsoifl for a soil layer that doesn't really exist, i.e. nlevsoifl + 1. Do you feel comfortable with that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that this feels weird, and certainly I'd feel less comfortable with this if zsoifl were used for anything more than defining zisoifl. But since zsoifl is just used to define zisoifl, I figured that the best thing to do here is to define zsoifl so that the zisoifl values end up as desired - which involves setting an assumed value for zsoifl(nlevsoifl+1). Unless you see a cleaner way to accomplish this goal? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good. To help with the long term development and institutional memory of what is going on here, how about a comment that explains how this code might change if we were reading the depths from the file (a file); and which specific file we are referring to; and the danger of switching to a new file given the current implementation. If such a comment exists somewhere else, I suggest copying it here, too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment added in 40a5881 |
||
zisoifl(j) = 0.5_r8*(zsoifl(j)+zsoifl(j+1)) !interface depths | ||
enddo | ||
zisoifl(nlevsoifl) = zsoifl(nlevsoifl) + 0.5_r8*dzsoifl(nlevsoifl) | ||
|
||
! -------------------------------------------------------------------- | ||
! Set soil hydraulic and thermal properties: non-lake | ||
|
@@ -330,7 +329,6 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) | |
! roof, sunwall and shadewall are prescribed in SoilThermProp.F90 | ||
! in SoilPhysicsMod.F90 | ||
|
||
|
||
do c = begc, endc | ||
g = col%gridcell(c) | ||
l = col%landunit(c) | ||
|
@@ -367,36 +365,32 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) | |
else | ||
|
||
do lev = 1,nlevgrnd | ||
! DML - this if statement could probably be removed and just the | ||
! top part used for all soil layer structures | ||
if (.not. organic_frac_squared) then | ||
if (lev .eq. 1) then | ||
clay = clay3d(g,1) | ||
sand = sand3d(g,1) | ||
om_frac = organic3d(g,1)/organic_max | ||
else if (lev <= nlevsoi) then | ||
do j = 1,nlevsoifl-1 | ||
if (zisoi(lev) >= zisoifl(j) .AND. zisoi(lev) < zisoifl(j+1)) then | ||
clay = clay3d(g,j+1) | ||
sand = sand3d(g,j+1) | ||
om_frac = organic3d(g,j+1)/organic_max | ||
endif | ||
end do | ||
else | ||
clay = clay3d(g,nlevsoifl) | ||
sand = sand3d(g,nlevsoifl) | ||
om_frac = 0._r8 | ||
endif | ||
if (lev .eq. 1) then | ||
clay = clay3d(g,1) | ||
sand = sand3d(g,1) | ||
om_frac = organic3d(g,1)/organic_max | ||
else if (lev <= nlevsoi) then | ||
do j = 1,nlevsoifl-1 | ||
! NOTE(wjs, 2019-08-01) It appears that the code currently doesn't set | ||
! clay, sand and om_frac explicitly under some conditions. It probably | ||
! should. My understanding is that currently things work okay, though, | ||
! because clay, sand and om_frac will remain set at their previous | ||
! values, which is probably reasonable enough. See also | ||
! <https://github.com/ESCOMP/ctsm/pull/771#discussion_r309509596>. | ||
if (zisoi(lev) > zisoifl(j) .AND. zisoi(lev) <= zisoifl(j+1)) then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Diff (2) from my main PR comment: changing the logic for when zisoi == zisoifl There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens here for, let's say, lev = 20 if zisoi(20) happens to be greater than zisoifl(10). I think that clay, sand, and om_frac do not get valid values for lev = 20 in that case. Even if somehow they do get valid values, maybe we need an explicit statement, so that there is no doubt about their values. I'm thinking something like this: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, and what if zisoi(lev) happens to be less than or equal to zisoifl(j). That case is not accounted for, either, I think. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good point. I believe these problems existed before this PR; do you agree? (I'm just trying to distinguish between possible new problems in this PR and pre-existing problems.) For this
I'm thinking you mean: zisoi(lev) is <= zisoifl(1), for lev = 2 or more. Now, that said: I believe the code is actually working in a reasonable way right now, it just isn't as explicit as it could be: if these variables (clay, sand, om_frac) aren't explicitly set, they'll remain at their values from the last iteration of the level loop. So, for the case where zisoi(lev) is <= zisoifl(1), I believe we'll end up using values from level 1 of the file (because these will have been set in the We could fix this to be more explicit; if so, I think this code would become cleaner - and unit testable! - if we extracted this logic for finding the right layer into its own routine, tied in with the parenthetical under "Caveat c" in this comment #759 (comment) . However, it might make the most sense to wait and do this as part of resolving #772 , once we agree on how we want to solve that one - rather than fixing this implementation just to throw it out and replace it with something more correct. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm fine with that. Again though, how about adding a comment in the code with your best understanding of how this works now versus how it should work ideally. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Regarding the parenthetical under caveat c in #759, if there's a chance that some day we will end up with varying soil layer depths, it may not be worth changing. I'm just raising as a potential concern; @swensosc and others may have better insight. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment added in 40a5881 |
||
clay = clay3d(g,j+1) | ||
sand = sand3d(g,j+1) | ||
om_frac = organic3d(g,j+1)/organic_max | ||
endif | ||
end do | ||
else | ||
if (lev <= nlevsoi) then ! duplicate clay and sand values from 10th soil layer | ||
clay = clay3d(g,lev) | ||
sand = sand3d(g,lev) | ||
om_frac = (organic3d(g,lev)/organic_max)**2._r8 | ||
else | ||
clay = clay3d(g,nlevsoi) | ||
sand = sand3d(g,nlevsoi) | ||
om_frac = 0._r8 | ||
endif | ||
clay = clay3d(g,nlevsoifl) | ||
sand = sand3d(g,nlevsoifl) | ||
om_frac = 0._r8 | ||
endif | ||
|
||
if (organic_frac_squared) then | ||
om_frac = om_frac**2._r8 | ||
end if | ||
|
||
if (lun%urbpoi(l)) then | ||
|
@@ -591,7 +585,7 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) | |
! -------------------------------------------------------------------- | ||
|
||
deallocate(sand3d, clay3d, organic3d) | ||
deallocate(zisoifl, zsoifl, dzsoifl) | ||
deallocate(zisoifl, zsoifl) | ||
|
||
end subroutine SoilStateInitTimeConst | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Diff (1) from my main PR comment: addition of _r8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we calculate these depths if they are on the file and could be read? Seems risky to be calculating depths that are assumed to be on a file, when the file may change and we could be calculating the wrong depths at that point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, I completely agree that these should be on the file. But they aren't on there right now. Long-term, the best solution would absolutely be to put these levels on the surface datasets, but I felt that was too much to fold in with #759 or this PR.