Skip to content

CAM computes enthalpy to send to BLOM#62

Open
mvertens wants to merge 8 commits intoNorESMhub:noresm_developfrom
mvertens:feature/cam_computes_enthalpy
Open

CAM computes enthalpy to send to BLOM#62
mvertens wants to merge 8 commits intoNorESMhub:noresm_developfrom
mvertens:feature/cam_computes_enthalpy

Conversation

@mvertens
Copy link
Contributor

@mvertens mvertens commented Oct 9, 2025

This PR supersedes PR #58

Copy link
Contributor

@gold2718 gold2718 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some questions, some optimization ideas, and at least one code section that does not look right.

Comment on lines +3063 to +3064
ifld = pbuf_get_index('ENTHALPY_PREC_AC', errcode=i)
if (ifld>0) call pbuf_set_field(pbuf, ifld, 0._r8)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why ask for ifld when there is already a module variable for it? Also, if ifld <= 0, isn't that an error since the pbuf field is added using the same logical (computer_enthalpy_flux)?

Suggested change
ifld = pbuf_get_index('ENTHALPY_PREC_AC', errcode=i)
if (ifld>0) call pbuf_set_field(pbuf, ifld, 0._r8)
if (enthalpy_prec_ac_idx > 0) then
call pbuf_set_field(pbuf, ifld, 0._r8)
else
call endrun('pbuf field, ENTHALPY_PREC_AC, not defined')
end if

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need the check for > 0 since the pbuf_add_field for ENTHALPY_PREC_AC is in this module and only occurs if compute_enthalpy_flux is .true.

Comment on lines +80 to +82
integer :: enthalpy_prec_bc_idx = 0
integer :: enthalpy_prec_ac_idx = 0
integer :: enthalpy_evop_idx = 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These variables should be public, protected and used from check_energy.F90 and camsrfexch.F90 instead of calling pbuf_get_index there (or later in this module).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have put these in phys_init.

integer :: enthalpy_evop_idx = 0
integer :: qcsedten_idx=0, qrsedten_idx=0
integer :: qisedten_idx=0, qssedten_idx=0, qgsedten_idx=0
integer :: qrain_mg_idx=0, qsnow_mg_idx=0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These variables should be public, protected and used from check_energy.F90 instead of calling pbuf_get_index there (or later in this module).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have put setting this in phys_init.

call pbuf_get_field(pbuf, qssedten_idx, qssedten)
qsnow_mg_macmic(:ncol,:) = qsnow_mg_macmic(:ncol,:)-qssedten(:ncol,:)
endif
if (qgsedten_idx.gt.0) then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update syntax:

Suggested change
if (qgsedten_idx.gt.0) then
if (qgsedten_idx > 0) then

Comment on lines +2018 to +2019
qrain_mg_idx = pbuf_get_index('qrain_mg' , errcode=i)
qsnow_mg_idx = pbuf_get_index('qsnow_mg' , errcode=i)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should also be moved to phys_init. Also, I think the errcode=i optional input should be dropped since the return code is not being checked. Without that, a failure results in a call to endrun while this version would fail silently.

Comment on lines +2578 to +2579
endif
endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please restore spaces (nit pick):

Suggested change
endif
endif
end if
end if

Comment on lines +2844 to +2846
call cnst_get_ind('Q', ixq)
call cnst_get_ind('CLDLIQ', ixcldliq)
call cnst_get_ind('CLDICE', ixcldice)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bit of potential cleanup:
Move ixq, ixcldliq and ixcldice to be module variables, move the cnst_get_ind calls to phys_init (including from tphysbc), and remove them from the run-time routines.

Comment on lines +3060 to +3062
if (compute_enthalpy_flux) then
! In first time-step tphysac variables need to be zero'd out
if (compute_enthalpy_flux) then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something seems wrong here since the inner if statement is the same as the outer one. The comment mentions "first time-step" but the logic does not reflect that.

@mvertens mvertens marked this pull request as ready for review October 20, 2025 12:20
Copy link
Contributor

@gold2718 gold2718 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this is much better!
There are still some items from the first review plus a few new ones.

Comment on lines +968 to +972
qcsedten_idx = pbuf_get_index('QCSEDTEN', ierr)
qrsedten_idx = pbuf_get_index('QRSEDTEN', ierr)
qisedten_idx = pbuf_get_index('QISEDTEN', ierr)
qssedten_idx = pbuf_get_index('QSSEDTEN', ierr)
qgsedten_idx = pbuf_get_index('QGSEDTEN', ierr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should either check the ierr return values or leave them out (which calls endrun for any field not found).

Suggested change
qcsedten_idx = pbuf_get_index('QCSEDTEN', ierr)
qrsedten_idx = pbuf_get_index('QRSEDTEN', ierr)
qisedten_idx = pbuf_get_index('QISEDTEN', ierr)
qssedten_idx = pbuf_get_index('QSSEDTEN', ierr)
qgsedten_idx = pbuf_get_index('QGSEDTEN', ierr)
qcsedten_idx = pbuf_get_index('QCSEDTEN')
qrsedten_idx = pbuf_get_index('QRSEDTEN')
qisedten_idx = pbuf_get_index('QISEDTEN')
qssedten_idx = pbuf_get_index('QSSEDTEN')
qgsedten_idx = pbuf_get_index('QGSEDTEN')

real(r8), dimension(pcols,pver) :: qrain_mg_macmic , qsnow_mg_macmic
integer :: m_cnst
real(r8):: hflx_iref(pcols)
character(50) :: physparname
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use len= and maybe a standard value:

Suggested change
character(50) :: physparname
character(len=CS) :: physparname

or

Suggested change
character(50) :: physparname
character(len=16) :: physparname

Comment on lines +1988 to +2007
if (qcsedten_idx > 0) then
call pbuf_get_field(pbuf, qcsedten_idx, qcsedten)
qrain_mg_macmic(:ncol,:) = qrain_mg_macmic(:ncol,:) - qcsedten(:ncol,:)
endif
if (qrsedten_idx > 0) then
call pbuf_get_field(pbuf, qrsedten_idx, qrsedten)
qrain_mg_macmic(:ncol,:) = qrain_mg_macmic(:ncol,:) - qrsedten(:ncol,:)
endif
if (qisedten_idx > 0) then
call pbuf_get_field(pbuf, qisedten_idx, qisedten)
qsnow_mg_macmic(:ncol,:) = qsnow_mg_macmic(:ncol,:) - qisedten(:ncol,:)
endif
if (qssedten_idx > 0) then
call pbuf_get_field(pbuf, qssedten_idx, qssedten)
qsnow_mg_macmic(:ncol,:) = qsnow_mg_macmic(:ncol,:) - qssedten(:ncol,:)
endif
if (qgsedten_idx > 0) then
call pbuf_get_field(pbuf, qgsedten_idx, qgsedten)
qsnow_mg_macmic(:ncol,:) = qsnow_mg_macmic(:ncol,:) - qgsedten(:ncol,:)
endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you apply the suggestion back at 968 - 972, you can save a lot of logic here.

Suggested change
if (qcsedten_idx > 0) then
call pbuf_get_field(pbuf, qcsedten_idx, qcsedten)
qrain_mg_macmic(:ncol,:) = qrain_mg_macmic(:ncol,:) - qcsedten(:ncol,:)
endif
if (qrsedten_idx > 0) then
call pbuf_get_field(pbuf, qrsedten_idx, qrsedten)
qrain_mg_macmic(:ncol,:) = qrain_mg_macmic(:ncol,:) - qrsedten(:ncol,:)
endif
if (qisedten_idx > 0) then
call pbuf_get_field(pbuf, qisedten_idx, qisedten)
qsnow_mg_macmic(:ncol,:) = qsnow_mg_macmic(:ncol,:) - qisedten(:ncol,:)
endif
if (qssedten_idx > 0) then
call pbuf_get_field(pbuf, qssedten_idx, qssedten)
qsnow_mg_macmic(:ncol,:) = qsnow_mg_macmic(:ncol,:) - qssedten(:ncol,:)
endif
if (qgsedten_idx > 0) then
call pbuf_get_field(pbuf, qgsedten_idx, qgsedten)
qsnow_mg_macmic(:ncol,:) = qsnow_mg_macmic(:ncol,:) - qgsedten(:ncol,:)
endif
call pbuf_get_field(pbuf, qcsedten_idx, qcsedten)
qrain_mg_macmic(:ncol,:) = qrain_mg_macmic(:ncol,:) - qcsedten(:ncol,:)
call pbuf_get_field(pbuf, qrsedten_idx, qrsedten)
qrain_mg_macmic(:ncol,:) = qrain_mg_macmic(:ncol,:) - qrsedten(:ncol,:)
call pbuf_get_field(pbuf, qisedten_idx, qisedten)
qsnow_mg_macmic(:ncol,:) = qsnow_mg_macmic(:ncol,:) - qisedten(:ncol,:)
call pbuf_get_field(pbuf, qssedten_idx, qssedten)
qsnow_mg_macmic(:ncol,:) = qsnow_mg_macmic(:ncol,:) - qssedten(:ncol,:)
call pbuf_get_field(pbuf, qgsedten_idx, qgsedten)
qsnow_mg_macmic(:ncol,:) = qsnow_mg_macmic(:ncol,:) - qgsedten(:ncol,:)

Comment on lines +2868 to +2872
call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., &
state%pdel(1:ncol,1:pver), cp_or_cv_dycore(:ncol,:,lchnk), &
state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver),&
vc_dycore, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), &
te = te_init(:ncol,1,lchnk), se=te_init(:ncol,2,lchnk), po=te_init(:ncol,3,lchnk), ke=te_init(:ncol,4,lchnk))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think you need to pass the se, p0, or ke arguments as they are never used.
Only te_init(:,1,:) is used and I want to remove that second dimension (also see xxx comments in air_composition.F90). I realize this will not compile without also changing the CAM code but it seems reasonable.

Also, the lower bounds on some of these array references is not needed, can the use be made consistent?

Suggested change
call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., &
state%pdel(1:ncol,1:pver), cp_or_cv_dycore(:ncol,:,lchnk), &
state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver),&
vc_dycore, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), &
te = te_init(:ncol,1,lchnk), se=te_init(:ncol,2,lchnk), po=te_init(:ncol,3,lchnk), ke=te_init(:ncol,4,lchnk))
call get_hydrostatic_energy(state%q(:ncol,:pver,:pcnst),.true., &
state%pdel(:ncol,1:pver), cp_or_cv_dycore(:ncol,:,lchnk), &
state%u(:ncol,:pver), state%v(:ncol,:pver), state%T(:ncol,:pver),&
vc_dycore, ptop=state%pintdry(:ncol,1), phis = state%phis(:ncol), &
te = te_init(:ncol,lchnk))


if (compute_enthalpy_flux) then
! In first time-step tphysac variables need to be zero'd out
call pbuf_set_field(pbuf, ifld, 0._r8)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is ifld supposed to be here? ifld is set to the index of different pbuf fields above, which is this? Should it be an enthalpy-specific pbuf? All of them? Right now, it is probably FRACIS but who knows for sure?

Comment on lines +3095 to +3099
if (compute_enthalpy_flux) then
call cam_export(state, cam_out, pbuf, cam_in=cam_in)
else
call cam_export(state, cam_out, pbuf)
end if
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a fan of this method of communicating the enthalpy flag to cam_export. Instead of using the passing of cam_in, can you make cam_in a required (not optional) input to cam_export and use compute_enthalpy_flux in place of present(cam_in)?

Suggested change
if (compute_enthalpy_flux) then
call cam_export(state, cam_out, pbuf, cam_in=cam_in)
else
call cam_export(state, cam_out, pbuf)
end if
call cam_export(state, cam_out, pbuf, cam_in)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants