From 4c96ed55664e48d2288e6981bad710a7ebffcd3b Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Wed, 2 Oct 2024 22:35:50 -0600 Subject: [PATCH 01/82] return all indices and check for duplicates --- .../cam/outfrq24h_port/user_nl_cam | 2 +- src/control/cam_history.F90 | 74 +++++++++++-------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq24h_port/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/outfrq24h_port/user_nl_cam index e385809756..2d18788e39 100644 --- a/cime_config/testdefs/testmods_dirs/cam/outfrq24h_port/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/outfrq24h_port/user_nl_cam @@ -2,7 +2,7 @@ rad_data_fdh = .true. empty_htapes = .true. avgflag_pertape = 'A','I' - fincl1 = 'SOLIN', 'QRS', 'FSNS', 'FSNT','FSNSC', 'FSDSC','FSNR','FLNR', + fincl1 = 'SOLIN', 'QRS', 'FSNS', 'FSNT','FSNSC', 'FSNR','FLNR', 'FSNTOA', 'FSUTOA', 'FSNTOAC', 'FSNTC', 'FSDSC', 'FSDS', 'SWCF', 'QRL', 'FLNS', 'FLDS', 'FLNT', 'LWCF', 'FLUT' ,'FLUTC', 'FLNTC', 'FLNSC', 'FLDSC' diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index 39222fc536..602280baf3 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -486,10 +486,6 @@ subroutine intht (model_doi_url_in) ! do t=1,ptapes do fld=1,nflds(t) - if (nhtfrq(t) == 1) then - ! Override any non-I flags if nhtfrq equals 1 - tape(t)%hlist(fld)%avgflag = 'I' - end if if (tape(t)%hlist(fld)%avgflag .ne. 'I') then hfile_accum(t) = .true. end if @@ -2570,7 +2566,10 @@ subroutine fldlst () ! integer t, fld ! tape, field indices integer ffld ! index into include, exclude and fprec list + integer :: ffld_array(pflds, ptapes) integer :: i + integer :: duplicate_index ! iterator for multiple occurrences of the same field + integer :: num_fields ! Number of times field appears in field list character(len=fieldname_len) :: name ! field name portion of fincl (i.e. no avgflag separator) character(len=max_fieldname_len) :: mastername ! name from masterlist field character(len=max_chars) :: errormsg ! error output field @@ -2645,8 +2644,8 @@ subroutine fldlst () add_fincl_idx = fld if (fld > 1 .and. interpolate_output(t)) then do i = 1, n_vec_comp - call list_index(fincl(:,t), vec_comp_names(i), ffld) - if (ffld == 0) then + call list_index(fincl(:,t), vec_comp_names(i), ffld_array(:,t)) + if (.not. any(ffld_array(:,t) > 0)) then ! Add vector component to fincl. Don't need to check whether its in the master ! list since this was done at the time of registering the vector components. @@ -2744,21 +2743,23 @@ subroutine fldlst () listentry => masterlinkedlist do while(associated(listentry)) mastername = listentry%field%name - call list_index (fincl(1,t), mastername, ffld) + call list_index (fincl(1,t), mastername, ffld_array(:,t)) fieldontape = .false. - if (ffld > 0) then + if (any(ffld_array(:,t) > 0)) then fieldontape = .true. + num_fields = count(ffld_array(:,t) > 0) else if ((.not. empty_htapes) .or. (is_initfile(file_index=t))) then - call list_index (fexcl(1,t), mastername, ffld) - if (ffld == 0 .and. listentry%actflag(t)) then + call list_index (fexcl(1,t), mastername, ffld_array(:,t)) + if ((.not. any(ffld_array(:,t) > 0)) .and. listentry%actflag(t)) then fieldontape = .true. + num_fields = 1 end if end if if (fieldontape) then - ! The field is active so increment the number fo fields and add + ! The field is active so increment the number of fields and add ! its decomp type to the list of decomp types on this tape - nflds(t) = nflds(t) + 1 + nflds(t) = nflds(t) + num_fields do ffld = 1, size(gridsontape, 1) if (listentry%field%decomp_type == gridsontape(ffld, t)) then exit @@ -2821,21 +2822,23 @@ subroutine fldlst () do while(associated(listentry)) mastername = listentry%field%name - call list_index (fwrtpr(1,t), mastername, ffld) - if (ffld > 0) then - prec_wrt = getflag(fwrtpr(ffld,t)) + call list_index (fwrtpr(1,t), mastername, ffld_array(:,t)) + if (ffld_array(1,t) > 0) then + prec_wrt = getflag(fwrtpr(ffld_array(1,t), t)) else - prec_wrt = ' ' + prec_wrt = ' ' end if - call list_index (fincl(1,t), mastername, ffld) + call list_index (fincl(1,t), mastername, ffld_array(:,t)) - if (ffld > 0) then - avgflag = getflag (fincl(ffld,t)) - call inifld (t, listentry, avgflag, prec_wrt) + if (any(ffld_array(:,t) > 0)) then + do duplicate_index = 1, count(ffld_array(:,t) > 0) + avgflag = getflag (fincl(ffld_array(duplicate_index,t),t)) + call inifld (t, listentry, avgflag, prec_wrt) + end do else if ((.not. empty_htapes) .or. (is_initfile(file_index=t))) then - call list_index (fexcl(1,t), mastername, ffld) - if (ffld == 0 .and. listentry%actflag(t)) then + call list_index (fexcl(1,t), mastername, ffld_array(:,t)) + if (.not. any(ffld_array(:,t) > 0) .and. listentry%actflag(t)) then call inifld (t, listentry, ' ', prec_wrt) else listentry%actflag(t) = .false. @@ -2882,9 +2885,18 @@ subroutine fldlst () tape(t)%hlist(ffld+1) = tmp else if (tape(t)%hlist(ffld)%field%name == tape(t)%hlist(ffld+1)%field%name) then - - write(errormsg,'(2a,2(a,i3))') 'FLDLST: Duplicate field: ', & - trim(tape(t)%hlist(ffld)%field%name),', tape = ', t, ', ffld = ', ffld + if (tape(t)%hlist(ffld)%avgflag == tape(t)%hlist(ffld+1)%avgflag) then + write(errormsg,'(2a,2(a,i3),2a)') & + 'FLDLST: Duplicate field with the same averaging flag. Check your fincl list: ', & + trim(tape(t)%hlist(ffld)%field%name),', tape = ', t, ', ffld = ', ffld, & + ', flag = ', trim(tape(t)%hlist(ffld)%avgflag) + else + write(errormsg,'(2a,2(a,i3),4a)') & + 'FLDLST: Duplicate field with different averaging flags. Place on separate tapes: ', & + trim(tape(t)%hlist(ffld)%field%name),', tape = ', t, ', ffld = ', ffld, & + ', flag1 = ', trim(tape(t)%hlist(ffld)%avgflag), ', flag2 = ', & + trim(tape(t)%hlist(ffld+1)%avgflag) + end if call endrun(errormsg) end if @@ -3507,18 +3519,20 @@ subroutine list_index (list, name, index) ! Input arguments ! character(len=*), intent(in) :: list(pflds) ! input list of names, possibly ":" delimited - character(len=max_fieldname_len), intent(in) :: name ! name to be searched for + character(len=*), intent(in) :: name ! name to be searched for ! ! Output arguments ! - integer, intent(out) :: index ! index of "name" in "list" + integer, intent(out) :: index(:) ! indices of "name" in "list" ! ! Local workspace ! character(len=fieldname_len) :: listname ! input name with ":" stripped off. - integer f ! field index + integer :: f ! field index + integer :: num_found ! number of time field appears in list index = 0 + num_found = 1 do f=1,pflds ! ! Only list items @@ -3526,8 +3540,8 @@ subroutine list_index (list, name, index) listname = getname (list(f)) if (listname == ' ') exit if (listname == name) then - index = f - exit + index(num_found) = f + num_found = num_found + 1 end if end do From 3acb4b239775a7afa736fc1c74f4146eaaf9283e Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Wed, 2 Oct 2024 23:40:24 -0600 Subject: [PATCH 02/82] update to git-fleximod 0.9.2 --- .lib/git-fleximod/git_fleximod/cli.py | 2 +- .../git-fleximod/git_fleximod/git_fleximod.py | 6 +- .../git-fleximod/git_fleximod/gitinterface.py | 7 +- .lib/git-fleximod/git_fleximod/submodule.py | 101 ++++++++++-------- .lib/git-fleximod/git_fleximod/utils.py | 10 +- .lib/git-fleximod/pyproject.toml | 2 +- .lib/git-fleximod/tbump.toml | 2 +- 7 files changed, 72 insertions(+), 58 deletions(-) diff --git a/.lib/git-fleximod/git_fleximod/cli.py b/.lib/git-fleximod/git_fleximod/cli.py index b6f728f881..208bc04684 100644 --- a/.lib/git-fleximod/git_fleximod/cli.py +++ b/.lib/git-fleximod/git_fleximod/cli.py @@ -2,7 +2,7 @@ import argparse from git_fleximod import utils -__version__ = "0.8.4" +__version__ = "0.9.2" def find_root_dir(filename=".gitmodules"): """ finds the highest directory in tree diff --git a/.lib/git-fleximod/git_fleximod/git_fleximod.py b/.lib/git-fleximod/git_fleximod/git_fleximod.py index 50e0ef83df..0851e9d095 100755 --- a/.lib/git-fleximod/git_fleximod/git_fleximod.py +++ b/.lib/git-fleximod/git_fleximod/git_fleximod.py @@ -124,8 +124,8 @@ def submodule_sparse_checkout(root_dir, name, url, path, sparsefile, tag="master # set the repository remote logger.info("Setting remote origin in {}/{}".format(root_dir, path)) - status = sprepo_git.git_operation("remote", "-v") - if url not in status: + _, remotelist = sprepo_git.git_operation("remote", "-v") + if url not in remotelist: sprepo_git.git_operation("remote", "add", "origin", url) topgit = os.path.join(gitroot, ".git") @@ -213,7 +213,7 @@ def submodules_status(gitmodules, root_dir, toplevel=False, depth=0): def git_toplevelroot(root_dir, logger): rgit = GitInterface(root_dir, logger) - superroot = rgit.git_operation("rev-parse", "--show-superproject-working-tree") + _, superroot = rgit.git_operation("rev-parse", "--show-superproject-working-tree") return superroot def submodules_update(gitmodules, root_dir, requiredlist, force): diff --git a/.lib/git-fleximod/git_fleximod/gitinterface.py b/.lib/git-fleximod/git_fleximod/gitinterface.py index 5831201446..fb20883cd0 100644 --- a/.lib/git-fleximod/git_fleximod/gitinterface.py +++ b/.lib/git-fleximod/git_fleximod/gitinterface.py @@ -59,11 +59,12 @@ def git_operation(self, operation, *args, **kwargs): command = self._git_command(operation, *newargs) if isinstance(command, list): try: - return utils.execute_subprocess(command, output_to_caller=True) + status, output = utils.execute_subprocess(command, status_to_caller=True, output_to_caller=True) + return status, output.rstrip() except Exception as e: sys.exit(e) else: - return command + return 0, command def config_get_value(self, section, name): if self._use_module: @@ -81,6 +82,8 @@ def config_get_value(self, section, name): def config_set_value(self, section, name, value): if self._use_module: with self.repo.config_writer() as writer: + if "." in section: + section = section.replace("."," \"")+'"' writer.set_value(section, name, value) writer.release() # Ensure changes are saved else: diff --git a/.lib/git-fleximod/git_fleximod/submodule.py b/.lib/git-fleximod/git_fleximod/submodule.py index 70a3018a42..c939d54bc9 100644 --- a/.lib/git-fleximod/git_fleximod/submodule.py +++ b/.lib/git-fleximod/git_fleximod/submodule.py @@ -60,8 +60,9 @@ def status(self): if not os.path.exists(os.path.join(smpath, ".git")): rootgit = GitInterface(self.root_dir, self.logger) # submodule commands use path, not name - tags = rootgit.git_operation("ls-remote", "--tags", self.url) - result = rootgit.git_operation("submodule","status",smpath).split() + status, tags = rootgit.git_operation("ls-remote", "--tags", self.url) + status, result = rootgit.git_operation("submodule","status",smpath) + result = result.split() if result: ahash = result[0][1:] @@ -80,9 +81,9 @@ def status(self): result = f"e {self.name:>20} not checked out, aligned at tag {self.fxtag}{optional}" needsupdate = True elif self.fxtag: - ahash = rootgit.git_operation( + status, ahash = rootgit.git_operation( "submodule", "status", "{}".format(self.path) - ).rstrip() + ) ahash = ahash[1 : len(self.fxtag) + 1] if self.fxtag == ahash: result = f"e {self.name:>20} not checked out, aligned at hash {ahash}{optional}" @@ -96,14 +97,15 @@ def status(self): else: with utils.pushd(smpath): git = GitInterface(smpath, self.logger) - remote = git.git_operation("remote").rstrip() + status, remote = git.git_operation("remote") if remote == '': result = f"e {self.name:>20} has no associated remote" testfails = True needsupdate = True return result, needsupdate, localmods, testfails - rurl = git.git_operation("ls-remote","--get-url").rstrip() - line = git.git_operation("log", "--pretty=format:\"%h %d\"").partition('\n')[0] + status, rurl = git.git_operation("ls-remote","--get-url") + status, lines = git.git_operation("log", "--pretty=format:\"%h %d\"") + line = lines.partition('\n')[0] parts = line.split() ahash = parts[0][1:] atag = None @@ -120,7 +122,7 @@ def status(self): #print(f"line is {line} ahash is {ahash} atag is {atag} {parts}") - # atag = git.git_operation("describe", "--tags", "--always").rstrip() + # atag = git.git_operation("describe", "--tags", "--always") # ahash = git.git_operation("rev-list", "HEAD").partition("\n")[0] recurse = False @@ -149,10 +151,10 @@ def status(self): result = f"e {self.name:>20} has no fxtag defined in .gitmodules, module at {ahash}" testfails = False - status = git.git_operation("status", "--ignore-submodules", "-uno") - if "nothing to commit" not in status: + status, output = git.git_operation("status", "--ignore-submodules", "-uno") + if "nothing to commit" not in output: localmods = True - result = "M" + textwrap.indent(status, " ") + result = "M" + textwrap.indent(output, " ") # print(f"result {result} needsupdate {needsupdate} localmods {localmods} testfails {testfails}") return result, needsupdate, localmods, testfails @@ -171,10 +173,11 @@ def _add_remote(self, git): Returns: str: The name of the new remote if added, or the name of the existing remote that matches the submodule's URL. """ - remotes = git.git_operation("remote", "-v").splitlines() + status, remotes = git.git_operation("remote", "-v") + remotes = remotes.splitlines() upstream = None if remotes: - upstream = git.git_operation("ls-remote", "--get-url").rstrip() + status, upstream = git.git_operation("ls-remote", "--get-url") newremote = "newremote.00" tmpurl = self.url.replace("git@github.com:", "https://github.com/") line = next((s for s in remotes if self.url in s or tmpurl in s), None) @@ -183,7 +186,7 @@ def _add_remote(self, git): return newremote else: i = 0 - while "newremote" in remotes: + while newremote in remotes: i = i + 1 newremote = f"newremote.{i:02d}" else: @@ -214,12 +217,19 @@ def sparse_checkout(self): """ self.logger.info("Called sparse_checkout for {}".format(self.name)) rgit = GitInterface(self.root_dir, self.logger) - superroot = rgit.git_operation("rev-parse", "--show-superproject-working-tree") + status, superroot = rgit.git_operation("rev-parse", "--show-superproject-working-tree") if superroot: gitroot = superroot.strip() else: gitroot = self.root_dir.strip() - assert os.path.isdir(os.path.join(gitroot, ".git")) + # Now need to move the .git dir to the submodule location + rootdotgit = os.path.join(self.root_dir, ".git") + while os.path.isfile(rootdotgit): + with open(rootdotgit) as f: + line = f.readline().rstrip() + if line.startswith("gitdir: "): + rootdotgit = os.path.abspath(os.path.join(self.root_dir,line[8:])) + assert os.path.isdir(rootdotgit) # first create the module directory if not os.path.isdir(os.path.join(self.root_dir, self.path)): os.makedirs(os.path.join(self.root_dir, self.path)) @@ -244,8 +254,8 @@ def sparse_checkout(self): # set the repository remote self.logger.info("Setting remote origin in {}/{}".format(self.root_dir, self.path)) - status = sprepo_git.git_operation("remote", "-v") - if self.url not in status: + status, remotes = sprepo_git.git_operation("remote", "-v") + if self.url not in remotes: sprepo_git.git_operation("remote", "add", "origin", self.url) topgit = os.path.join(gitroot, ".git") @@ -256,46 +266,46 @@ def sparse_checkout(self): os.path.join(self.root_dir, f.read().split()[1]), start=os.path.join(self.root_dir, self.path), ) - topgit = os.path.join(gitpath, "modules") + rootdotgit = os.path.join(gitpath, "modules", self.name) else: - topgit = os.path.relpath( - os.path.join(self.root_dir, ".git", "modules"), + rootdotgit = os.path.relpath( + os.path.join(self.root_dir, ".git", "modules", self.name), start=os.path.join(self.root_dir, self.path), ) - with utils.pushd(sprep_repo): - if not os.path.isdir(topgit): - os.makedirs(topgit) - topgit += os.sep + self.name - if os.path.isdir(os.path.join(self.root_dir, self.path, ".git")): with utils.pushd(sprep_repo): - if os.path.isdir(os.path.join(topgit,".git")): - shutil.rmtree(os.path.join(topgit,".git")) - shutil.move(".git", topgit) + if os.path.isdir(os.path.join(rootdotgit,".git")): + shutil.rmtree(os.path.join(rootdotgit,".git")) + shutil.move(".git", rootdotgit) with open(".git", "w") as f: - f.write("gitdir: " + os.path.relpath(topgit)) - # assert(os.path.isdir(os.path.relpath(topgit, start=sprep_repo))) - gitsparse = os.path.abspath(os.path.join(topgit, "info", "sparse-checkout")) + f.write("gitdir: " + os.path.relpath(rootdotgit)) + infodir = os.path.join(rootdotgit, "info") + if not os.path.isdir(infodir): + os.makedirs(infodir) + gitsparse = os.path.abspath(os.path.join(infodir, "sparse-checkout")) if os.path.isfile(gitsparse): self.logger.warning( - "submodule {} is already initialized {}".format(self.name, topgit) + "submodule {} is already initialized {}".format(self.name, rootdotgit) ) return with utils.pushd(sprep_repo): if os.path.isfile(self.fxsparse): + shutil.copy(self.fxsparse, gitsparse) # Finally checkout the repo sprepo_git.git_operation("fetch", "origin", "--tags") - sprepo_git.git_operation("checkout", self.fxtag) - - print(f"Successfully checked out {self.name:>20} at {self.fxtag}") - rgit.config_set_value(f'submodule "{self.name}"', "active", "true") - rgit.config_set_value(f'submodule "{self.name}"', "url", self.url) - rgit.config_set_value(f'submodule "{self.name}"', "path", self.path) + status,_ = sprepo_git.git_operation("checkout", self.fxtag) + if status: + print(f"Error checking out {self.name:>20} at {self.fxtag}") + else: + print(f"Successfully checked out {self.name:>20} at {self.fxtag}") + rgit.config_set_value('submodule.' + self.name, "active", "true") + rgit.config_set_value('submodule.' + self.name, "url", self.url) + rgit.config_set_value('submodule.' + self.name, "path", self.path) def update(self): """ @@ -342,7 +352,7 @@ def update(self): git.git_operation("clone", self.url, self.path) smgit = GitInterface(repodir, self.logger) if not tag: - tag = smgit.git_operation("describe", "--tags", "--always").rstrip() + status, tag = smgit.git_operation("describe", "--tags", "--always") smgit.git_operation("checkout", tag) # Now need to move the .git dir to the submodule location rootdotgit = os.path.join(self.root_dir, ".git") @@ -350,7 +360,7 @@ def update(self): with open(rootdotgit) as f: line = f.readline() if line.startswith("gitdir: "): - rootdotgit = line[8:].rstrip() + rootdotgit = line[8:] newpath = os.path.abspath(os.path.join(self.root_dir, rootdotgit, "modules", self.name)) if os.path.exists(newpath): @@ -393,15 +403,16 @@ def update(self): git = GitInterface(submoddir, self.logger) # first make sure the url is correct newremote = self._add_remote(git) - tags = git.git_operation("tag", "-l") + status, tags = git.git_operation("tag", "-l") fxtag = self.fxtag if fxtag and fxtag not in tags: git.git_operation("fetch", newremote, "--tags") - atag = git.git_operation("describe", "--tags", "--always").rstrip() + status, atag = git.git_operation("describe", "--tags", "--always") if fxtag and fxtag != atag: try: - git.git_operation("checkout", fxtag) - print(f"{self.name:>20} updated to {fxtag}") + status, _ = git.git_operation("checkout", fxtag) + if not status: + print(f"{self.name:>20} updated to {fxtag}") except Exception as error: print(error) diff --git a/.lib/git-fleximod/git_fleximod/utils.py b/.lib/git-fleximod/git_fleximod/utils.py index 1a2d5ccf2f..c4f43d5238 100644 --- a/.lib/git-fleximod/git_fleximod/utils.py +++ b/.lib/git-fleximod/git_fleximod/utils.py @@ -307,12 +307,12 @@ def execute_subprocess(commands, status_to_caller=False, output_to_caller=False) # simple status check. If returning, it is the callers # responsibility determine if an error occurred and handle it # appropriately. + msg_context = ( + "Process did not run successfully; " + "returned status {0}".format(error.returncode) + ) + msg = failed_command_msg(msg_context, commands, output=error.output) if not return_to_caller: - msg_context = ( - "Process did not run successfully; " - "returned status {0}".format(error.returncode) - ) - msg = failed_command_msg(msg_context, commands, output=error.output) logging.error(error) logging.error(msg) log_process_output(error.output) diff --git a/.lib/git-fleximod/pyproject.toml b/.lib/git-fleximod/pyproject.toml index 850e57d59d..619cdabe3b 100644 --- a/.lib/git-fleximod/pyproject.toml +++ b/.lib/git-fleximod/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "git-fleximod" -version = "0.8.4" +version = "0.9.2" description = "Extended support for git-submodule and git-sparse-checkout" authors = ["Jim Edwards "] maintainers = ["Jim Edwards "] diff --git a/.lib/git-fleximod/tbump.toml b/.lib/git-fleximod/tbump.toml index bd82c557ad..920ff0591c 100644 --- a/.lib/git-fleximod/tbump.toml +++ b/.lib/git-fleximod/tbump.toml @@ -2,7 +2,7 @@ github_url = "https://github.com/jedwards4b/git-fleximod/" [version] -current = "0.8.4" +current = "0.9.2" # Example of a semver regexp. # Make sure this matches current_version before From 5c343d9b35e86bf162360f576a1f4cf23f51cc3f Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Wed, 2 Oct 2024 23:55:57 -0600 Subject: [PATCH 03/82] remove duplicate fields from use cases --- .../use_cases/1950-2010_ccmi_refc1_waccmx_ma.xml | 2 +- bld/namelist_files/use_cases/sd_waccm_ma_cam6.xml | 2 +- bld/namelist_files/use_cases/sd_waccm_sulfur.xml | 2 +- bld/namelist_files/use_cases/sd_waccmx_ma_cam4.xml | 2 +- bld/namelist_files/use_cases/sd_waccmx_ma_cam6.xml | 2 +- bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml | 2 +- bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml | 2 +- bld/namelist_files/use_cases/waccm_ma_2000_cam6.xml | 2 +- bld/namelist_files/use_cases/waccm_ma_hist_cam4.xml | 2 +- bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml | 2 +- bld/namelist_files/use_cases/waccmx_ma_2000_cam4.xml | 4 ++-- bld/namelist_files/use_cases/waccmx_ma_2000_cam6.xml | 2 +- bld/namelist_files/use_cases/waccmx_ma_hist_cam6.xml | 2 +- bld/namelist_files/use_cases/waccmxie_ma_2000_cam4.xml | 2 +- 14 files changed, 15 insertions(+), 15 deletions(-) diff --git a/bld/namelist_files/use_cases/1950-2010_ccmi_refc1_waccmx_ma.xml b/bld/namelist_files/use_cases/1950-2010_ccmi_refc1_waccmx_ma.xml index 15306d5711..4141549d60 100644 --- a/bld/namelist_files/use_cases/1950-2010_ccmi_refc1_waccmx_ma.xml +++ b/bld/namelist_files/use_cases/1950-2010_ccmi_refc1_waccmx_ma.xml @@ -80,7 +80,7 @@ 'Z3', 'T', 'TIon', 'TElec', 'e', 'U', 'V', 'OMEGA', 'UI', 'VI', 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2' 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', - 'QNO', 'QO3P', 'QHC2S', 'QJOULE', 'EKGW', 'TTGW', 'UTGW_TOTAL', + 'QNO', 'QO3P', 'QHC2S', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'V_08_COS', 'V_08_SIN', diff --git a/bld/namelist_files/use_cases/sd_waccm_ma_cam6.xml b/bld/namelist_files/use_cases/sd_waccm_ma_cam6.xml index 753c2e0035..5888b56ff9 100644 --- a/bld/namelist_files/use_cases/sd_waccm_ma_cam6.xml +++ b/bld/namelist_files/use_cases/sd_waccm_ma_cam6.xml @@ -76,7 +76,7 @@ 'FSDS', 'FSNS', 'FSNSC', 'FSNT', 'FSNTC', 'HORZ', 'LANDFRAC', 'LHFLX', 'OCNFRAC', 'OH', 'OMEGA', 'PHIS', 'PRECC', 'PRECL', 'PS', 'QFLX', 'QRL', 'QRLNLTE', 'QRS', 'RELHUM', 'SHFLX', 'SOLIN', 'SWCF', 'QCP', 'QTHERMAL', 'QRL_TOT', 'QRS_TOT', - 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', + 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'TREFHT', 'TTGW', 'UTGWORO', 'UTGWSPEC', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'HOX', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', diff --git a/bld/namelist_files/use_cases/sd_waccm_sulfur.xml b/bld/namelist_files/use_cases/sd_waccm_sulfur.xml index 7a02c11544..6d1055cd1f 100644 --- a/bld/namelist_files/use_cases/sd_waccm_sulfur.xml +++ b/bld/namelist_files/use_cases/sd_waccm_sulfur.xml @@ -76,7 +76,7 @@ 'N', 'N2O', 'N2O5', 'NO', 'NO2', 'NO3', 'O', 'O1D', 'O2', 'O3', 'OCLO', 'OCNFRAC', 'OH', 'OMEGA', 'PHIS', 'PRECC', 'PRECL', 'PS', 'Q', 'QFLX', 'QPERT', 'QRL', 'QRLNLTE', 'QRS', 'RELHUM', 'SHFLX', 'SOLIN', 'SWCF', 'QCP', - 'QTHERMAL', 'QRL_TOT', 'QRS_TOT', 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', + 'QTHERMAL', 'QRL_TOT', 'QRS_TOT', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Aircraft', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'T', 'TREFHT', 'TTGW', 'U', 'UTGWORO', 'UTGWSPEC', 'V', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'O2_1S', diff --git a/bld/namelist_files/use_cases/sd_waccmx_ma_cam4.xml b/bld/namelist_files/use_cases/sd_waccmx_ma_cam4.xml index 6ec178700a..f50160948e 100644 --- a/bld/namelist_files/use_cases/sd_waccmx_ma_cam4.xml +++ b/bld/namelist_files/use_cases/sd_waccmx_ma_cam4.xml @@ -80,7 +80,7 @@ 'Z3', 'T', 'TIon', 'TElec', 'e', 'U', 'V', 'OMEGA', 'UI', 'VI', 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2' 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', - 'QNO', 'QO3P', 'QHC2S', 'QJOULE', 'EKGW', 'TTGW', 'UTGW_TOTAL', + 'QNO', 'QO3P', 'QHC2S', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'V_08_COS', 'V_08_SIN', diff --git a/bld/namelist_files/use_cases/sd_waccmx_ma_cam6.xml b/bld/namelist_files/use_cases/sd_waccmx_ma_cam6.xml index 6493ed584b..984ab0b002 100644 --- a/bld/namelist_files/use_cases/sd_waccmx_ma_cam6.xml +++ b/bld/namelist_files/use_cases/sd_waccmx_ma_cam6.xml @@ -67,7 +67,7 @@ 'Z3', 'T', 'TIon', 'TElec', 'e', 'U', 'V', 'OMEGA', 'UI', 'VI', 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2' 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', - 'QNO', 'QO3P', 'QHC2S', 'QJOULE', 'EKGW', 'TTGW', 'UTGW_TOTAL', + 'QNO', 'QO3P', 'QHC2S', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'V_08_COS', 'V_08_SIN', diff --git a/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml b/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml index 1429770e8e..c04967bace 100644 --- a/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml +++ b/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml @@ -90,7 +90,7 @@ 'HNO3_GAS', 'NO_Aircraft', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'T', 'TREFHT', 'TTGW', 'U', 'UTGWORO', 'UTGWSPEC', 'V', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'O2_1S', - 'O2_1D', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', + 'O2_1D', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI', 'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', diff --git a/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml b/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml index 24b55facc2..d978796e4a 100644 --- a/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml @@ -63,7 +63,7 @@ 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'TREFHT', 'TTGW', 'UTGWORO', 'UTGWSPEC', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'HOX', 'NOX', 'NOY', 'CLOX', - 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', + 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI', 'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'PS_24_COS', 'PS_24_SIN', 'PS_12_COS', diff --git a/bld/namelist_files/use_cases/waccm_ma_2000_cam6.xml b/bld/namelist_files/use_cases/waccm_ma_2000_cam6.xml index 9ccac8892f..5443a10f83 100644 --- a/bld/namelist_files/use_cases/waccm_ma_2000_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_ma_2000_cam6.xml @@ -158,7 +158,7 @@ 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'TREFHT', 'TTGW', 'UTGWORO', 'UTGWSPEC', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'HOX', 'NOX', 'NOY', 'CLOX', - 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', + 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI', 'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'PS_24_COS', 'PS_24_SIN', 'PS_12_COS', diff --git a/bld/namelist_files/use_cases/waccm_ma_hist_cam4.xml b/bld/namelist_files/use_cases/waccm_ma_hist_cam4.xml index e2376e4a70..6526502ba5 100644 --- a/bld/namelist_files/use_cases/waccm_ma_hist_cam4.xml +++ b/bld/namelist_files/use_cases/waccm_ma_hist_cam4.xml @@ -86,7 +86,7 @@ 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'TREFHT', 'TTGW', 'UTGWORO', 'UTGWSPEC', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'HOX', 'NOX', 'NOY', 'CLOX', - 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', + 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI', 'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'PS_24_COS', 'PS_24_SIN', 'PS_12_COS', diff --git a/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml b/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml index 042a153fe4..30deb2b74d 100644 --- a/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml @@ -57,7 +57,7 @@ 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'TREFHT', 'TTGW', 'UTGWORO', 'UTGWSPEC', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'HOX', 'NOX', 'NOY', 'CLOX', - 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', + 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI', 'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'PS_24_COS', 'PS_24_SIN', 'PS_12_COS', diff --git a/bld/namelist_files/use_cases/waccmx_ma_2000_cam4.xml b/bld/namelist_files/use_cases/waccmx_ma_2000_cam4.xml index 017cc3362e..c5bc7e2f57 100644 --- a/bld/namelist_files/use_cases/waccmx_ma_2000_cam4.xml +++ b/bld/namelist_files/use_cases/waccmx_ma_2000_cam4.xml @@ -87,7 +87,7 @@ 'HNO3_GAS', 'NO_Aircraft', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'T', 'TREFHT', 'TTGW', 'U', 'UTGWORO', 'UTGWSPEC', 'V', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'O2_1S', - 'O2_1D', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE','UI','VI','WI', + 'O2_1D', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI','VI','WI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', @@ -134,7 +134,7 @@ 'Qbkgndtot','Qbkgnd_o1','Qbkgnd_o2','Qbkgnd_n2','Qbkgnd_n1','Qbkgnd_no', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'T', 'TREFHT', 'TTGW', 'U', 'UTGWORO', 'UTGWSPEC', 'V', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'O2_1S', 'O2_1D', 'NOX', 'NOY', - 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UIONTEND', 'VIONTEND', + 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UIONTEND', 'VIONTEND', 'DTCORE', 'CLDLIQ', 'CLDICE', 'CONCLD', 'FRONTGF:I', 'BUTGWSPEC', 'BTAUE', 'BTAUW', 'BTAUN', 'BTAUS', 'TAUE', 'TAUW', 'TAUN', 'TAUS', 'TAUGWX', 'TAUGWY', 'TAUX', 'TAUY', 'SNOWHLND', 'SNOWHICE', 'ICEFRAC', 'FSDSC', 'SFNO', 'SFCO', 'SFCH2O', 'CFC11STAR', 'TROPP_FD', 'Op', 'O2p', 'Np', 'NOp', diff --git a/bld/namelist_files/use_cases/waccmx_ma_2000_cam6.xml b/bld/namelist_files/use_cases/waccmx_ma_2000_cam6.xml index 06520cc3fb..713ad27c86 100644 --- a/bld/namelist_files/use_cases/waccmx_ma_2000_cam6.xml +++ b/bld/namelist_files/use_cases/waccmx_ma_2000_cam6.xml @@ -48,7 +48,7 @@ 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2', 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', 'QNO', - 'QO3P', 'QHC2S', 'QJOULE', 'QEN', 'QIN', 'QEI', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', + 'QO3P', 'QHC2S', 'QEN', 'QIN', 'QEI', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'V_08_COS', 'V_08_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', diff --git a/bld/namelist_files/use_cases/waccmx_ma_hist_cam6.xml b/bld/namelist_files/use_cases/waccmx_ma_hist_cam6.xml index 37ca427cd2..02d3b04009 100644 --- a/bld/namelist_files/use_cases/waccmx_ma_hist_cam6.xml +++ b/bld/namelist_files/use_cases/waccmx_ma_hist_cam6.xml @@ -46,7 +46,7 @@ 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2', 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', 'QNO', - 'QO3P', 'QHC2S', 'QJOULE', 'QEN', 'QIN', 'QEI', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', + 'QO3P', 'QHC2S', 'QEN', 'QIN', 'QEI', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'V_08_COS', 'V_08_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', diff --git a/bld/namelist_files/use_cases/waccmxie_ma_2000_cam4.xml b/bld/namelist_files/use_cases/waccmxie_ma_2000_cam4.xml index 5fe9c654dd..ae18c1113c 100644 --- a/bld/namelist_files/use_cases/waccmxie_ma_2000_cam4.xml +++ b/bld/namelist_files/use_cases/waccmxie_ma_2000_cam4.xml @@ -98,7 +98,7 @@ 'Z3', 'T', 'TIon', 'TElec', 'e', 'U', 'V', 'OMEGA', 'UI', 'VI', 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2' 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', - 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', + 'Np', 'N2p', 'O2p', 'NOp', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', 'QNO', 'QO3P', 'QHC2S', 'QJOULE', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', From 8abd7cf89cc365f4320465a6dfa66440cc57a3da Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Thu, 3 Oct 2024 14:23:20 -0600 Subject: [PATCH 04/82] change methodology to allow for duplicate fields with the same flag --- src/control/cam_history.F90 | 80 ++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index 602280baf3..c91287899b 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -2566,10 +2566,8 @@ subroutine fldlst () ! integer t, fld ! tape, field indices integer ffld ! index into include, exclude and fprec list - integer :: ffld_array(pflds, ptapes) integer :: i - integer :: duplicate_index ! iterator for multiple occurrences of the same field - integer :: num_fields ! Number of times field appears in field list + logical :: duplicate_error ! flag for whether there is an incompatible duplicate found character(len=fieldname_len) :: name ! field name portion of fincl (i.e. no avgflag separator) character(len=max_fieldname_len) :: mastername ! name from masterlist field character(len=max_chars) :: errormsg ! error output field @@ -2644,8 +2642,8 @@ subroutine fldlst () add_fincl_idx = fld if (fld > 1 .and. interpolate_output(t)) then do i = 1, n_vec_comp - call list_index(fincl(:,t), vec_comp_names(i), ffld_array(:,t)) - if (.not. any(ffld_array(:,t) > 0)) then + call list_index(fincl(:,t), vec_comp_names(i), ffld) + if (ffld == 0) then ! Add vector component to fincl. Don't need to check whether its in the master ! list since this was done at the time of registering the vector components. @@ -2743,23 +2741,27 @@ subroutine fldlst () listentry => masterlinkedlist do while(associated(listentry)) mastername = listentry%field%name - call list_index (fincl(1,t), mastername, ffld_array(:,t)) + call list_index (fincl(1,t), mastername, ffld, duplicate_error=duplicate_error) + if (duplicate_error) then + write(errormsg,'(2a,2(a,i3))') & + 'FLDLST: Duplicate field with different averaging flags. Place on separate tapes: ', & + trim(mastername),', tape = ', t, ', ffld = ', ffld + call endrun(trim(errormsg)) + end if fieldontape = .false. - if (any(ffld_array(:,t) > 0)) then + if (ffld > 0) then fieldontape = .true. - num_fields = count(ffld_array(:,t) > 0) else if ((.not. empty_htapes) .or. (is_initfile(file_index=t))) then - call list_index (fexcl(1,t), mastername, ffld_array(:,t)) - if ((.not. any(ffld_array(:,t) > 0)) .and. listentry%actflag(t)) then + call list_index (fexcl(1,t), mastername, ffld) + if (ffld == 0 .and. listentry%actflag(t)) then fieldontape = .true. - num_fields = 1 end if end if if (fieldontape) then ! The field is active so increment the number of fields and add ! its decomp type to the list of decomp types on this tape - nflds(t) = nflds(t) + num_fields + nflds(t) = nflds(t) + 1 do ffld = 1, size(gridsontape, 1) if (listentry%field%decomp_type == gridsontape(ffld, t)) then exit @@ -2822,23 +2824,21 @@ subroutine fldlst () do while(associated(listentry)) mastername = listentry%field%name - call list_index (fwrtpr(1,t), mastername, ffld_array(:,t)) - if (ffld_array(1,t) > 0) then - prec_wrt = getflag(fwrtpr(ffld_array(1,t), t)) + call list_index (fwrtpr(1,t), mastername, ffld) + if (ffld > 0) then + prec_wrt = getflag(fwrtpr(ffld,t)) else - prec_wrt = ' ' + prec_wrt = ' ' end if - call list_index (fincl(1,t), mastername, ffld_array(:,t)) + call list_index (fincl(1,t), mastername, ffld) - if (any(ffld_array(:,t) > 0)) then - do duplicate_index = 1, count(ffld_array(:,t) > 0) - avgflag = getflag (fincl(ffld_array(duplicate_index,t),t)) - call inifld (t, listentry, avgflag, prec_wrt) - end do + if (ffld > 0) then + avgflag = getflag (fincl(ffld,t)) + call inifld (t, listentry, avgflag, prec_wrt) else if ((.not. empty_htapes) .or. (is_initfile(file_index=t))) then - call list_index (fexcl(1,t), mastername, ffld_array(:,t)) - if (.not. any(ffld_array(:,t) > 0) .and. listentry%actflag(t)) then + call list_index (fexcl(1,t), mastername, ffld) + if (ffld == 0 .and. listentry%actflag(t)) then call inifld (t, listentry, ' ', prec_wrt) else listentry%actflag(t) = .false. @@ -3514,25 +3514,30 @@ end function getflag !####################################################################### - subroutine list_index (list, name, index) + subroutine list_index (list, name, index, duplicate_error) ! ! Input arguments ! - character(len=*), intent(in) :: list(pflds) ! input list of names, possibly ":" delimited - character(len=*), intent(in) :: name ! name to be searched for + character(len=*), intent(in) :: list(pflds) ! input list of names, possibly ":" delimited + character(len=*), intent(in) :: name ! name to be searched for + logical, optional, intent(out) :: duplicate_error ! .true. if a duplicate field was found with different flags ! ! Output arguments ! - integer, intent(out) :: index(:) ! indices of "name" in "list" + integer, intent(out) :: index ! index of "name" in "list" ! ! Local workspace ! character(len=fieldname_len) :: listname ! input name with ":" stripped off. + character(len=fieldname_len) :: flag ! accumulate flag for field + character(len=fieldname_len) :: flag_comp ! accumulate flag to compare with previous entry integer :: f ! field index - integer :: num_found ! number of time field appears in list index = 0 - num_found = 1 + if (present(duplicate_error)) then + duplicate_error = .false. + end if + do f=1,pflds ! ! Only list items @@ -3540,8 +3545,19 @@ subroutine list_index (list, name, index) listname = getname (list(f)) if (listname == ' ') exit if (listname == name) then - index(num_found) = f - num_found = num_found + 1 + if (index /= 0 .and. present(duplicate_error)) then + ! This already exists in the field list - check the flag + flag_comp = getflag(list(f)) + if (trim(flag_comp) /= trim(flag)) then + duplicate_error = .true. + return + ! No else - if the flags are identical, we're ok to return the first + ! instance + end if + else + index = f + flag = getflag(list(f)) + end if end if end do From 33b6ffbd92da49a720ee409cc197c89204fcd466 Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Thu, 3 Oct 2024 14:29:18 -0600 Subject: [PATCH 05/82] code cleanup; fix bad comment --- bld/namelist_files/use_cases/sd_waccm_sulfur.xml | 2 +- src/control/cam_history.F90 | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/bld/namelist_files/use_cases/sd_waccm_sulfur.xml b/bld/namelist_files/use_cases/sd_waccm_sulfur.xml index 6d1055cd1f..4c2d827633 100644 --- a/bld/namelist_files/use_cases/sd_waccm_sulfur.xml +++ b/bld/namelist_files/use_cases/sd_waccm_sulfur.xml @@ -133,7 +133,7 @@ atm/cam/met/GEOS5 atm/cam/met/GEOS5_filenames_list_c120516.txt - + atm/cam/met/USGS-gtopo30_1.9x2.5_phys_geos5_c100929.nc diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index c91287899b..0d3a4dc823 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -2885,18 +2885,8 @@ subroutine fldlst () tape(t)%hlist(ffld+1) = tmp else if (tape(t)%hlist(ffld)%field%name == tape(t)%hlist(ffld+1)%field%name) then - if (tape(t)%hlist(ffld)%avgflag == tape(t)%hlist(ffld+1)%avgflag) then - write(errormsg,'(2a,2(a,i3),2a)') & - 'FLDLST: Duplicate field with the same averaging flag. Check your fincl list: ', & - trim(tape(t)%hlist(ffld)%field%name),', tape = ', t, ', ffld = ', ffld, & - ', flag = ', trim(tape(t)%hlist(ffld)%avgflag) - else - write(errormsg,'(2a,2(a,i3),4a)') & - 'FLDLST: Duplicate field with different averaging flags. Place on separate tapes: ', & - trim(tape(t)%hlist(ffld)%field%name),', tape = ', t, ', ffld = ', ffld, & - ', flag1 = ', trim(tape(t)%hlist(ffld)%avgflag), ', flag2 = ', & - trim(tape(t)%hlist(ffld+1)%avgflag) - end if + write(errormsg,'(2a,2(a,i3))') 'FLDLST: Duplicate field: ', & + trim(tape(t)%hlist(ffld)%field%name),', tape = ', t, ', ffld = ', ffld call endrun(errormsg) end if From b29a8dea9954ee1584bcc63a6b8c15cc5e7c8ed3 Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Thu, 3 Oct 2024 14:37:13 -0600 Subject: [PATCH 06/82] revert duplicate removal --- .../use_cases/1950-2010_ccmi_refc1_waccmx_ma.xml | 2 +- bld/namelist_files/use_cases/sd_waccm_ma_cam6.xml | 2 +- bld/namelist_files/use_cases/sd_waccm_sulfur.xml | 2 +- bld/namelist_files/use_cases/sd_waccmx_ma_cam4.xml | 2 +- bld/namelist_files/use_cases/sd_waccmx_ma_cam6.xml | 2 +- bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml | 2 +- bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml | 2 +- bld/namelist_files/use_cases/waccm_ma_2000_cam6.xml | 2 +- bld/namelist_files/use_cases/waccm_ma_hist_cam4.xml | 2 +- bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml | 2 +- bld/namelist_files/use_cases/waccmx_ma_2000_cam4.xml | 4 ++-- bld/namelist_files/use_cases/waccmx_ma_2000_cam6.xml | 2 +- bld/namelist_files/use_cases/waccmx_ma_hist_cam6.xml | 2 +- bld/namelist_files/use_cases/waccmxie_ma_2000_cam4.xml | 2 +- .../testdefs/testmods_dirs/cam/outfrq24h_port/user_nl_cam | 2 +- 15 files changed, 16 insertions(+), 16 deletions(-) diff --git a/bld/namelist_files/use_cases/1950-2010_ccmi_refc1_waccmx_ma.xml b/bld/namelist_files/use_cases/1950-2010_ccmi_refc1_waccmx_ma.xml index 4141549d60..15306d5711 100644 --- a/bld/namelist_files/use_cases/1950-2010_ccmi_refc1_waccmx_ma.xml +++ b/bld/namelist_files/use_cases/1950-2010_ccmi_refc1_waccmx_ma.xml @@ -80,7 +80,7 @@ 'Z3', 'T', 'TIon', 'TElec', 'e', 'U', 'V', 'OMEGA', 'UI', 'VI', 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2' 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', - 'QNO', 'QO3P', 'QHC2S', 'EKGW', 'TTGW', 'UTGW_TOTAL', + 'QNO', 'QO3P', 'QHC2S', 'QJOULE', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'V_08_COS', 'V_08_SIN', diff --git a/bld/namelist_files/use_cases/sd_waccm_ma_cam6.xml b/bld/namelist_files/use_cases/sd_waccm_ma_cam6.xml index 5888b56ff9..753c2e0035 100644 --- a/bld/namelist_files/use_cases/sd_waccm_ma_cam6.xml +++ b/bld/namelist_files/use_cases/sd_waccm_ma_cam6.xml @@ -76,7 +76,7 @@ 'FSDS', 'FSNS', 'FSNSC', 'FSNT', 'FSNTC', 'HORZ', 'LANDFRAC', 'LHFLX', 'OCNFRAC', 'OH', 'OMEGA', 'PHIS', 'PRECC', 'PRECL', 'PS', 'QFLX', 'QRL', 'QRLNLTE', 'QRS', 'RELHUM', 'SHFLX', 'SOLIN', 'SWCF', 'QCP', 'QTHERMAL', 'QRL_TOT', 'QRS_TOT', - 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', + 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'TREFHT', 'TTGW', 'UTGWORO', 'UTGWSPEC', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'HOX', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', diff --git a/bld/namelist_files/use_cases/sd_waccm_sulfur.xml b/bld/namelist_files/use_cases/sd_waccm_sulfur.xml index 4c2d827633..d035ea8b79 100644 --- a/bld/namelist_files/use_cases/sd_waccm_sulfur.xml +++ b/bld/namelist_files/use_cases/sd_waccm_sulfur.xml @@ -76,7 +76,7 @@ 'N', 'N2O', 'N2O5', 'NO', 'NO2', 'NO3', 'O', 'O1D', 'O2', 'O3', 'OCLO', 'OCNFRAC', 'OH', 'OMEGA', 'PHIS', 'PRECC', 'PRECL', 'PS', 'Q', 'QFLX', 'QPERT', 'QRL', 'QRLNLTE', 'QRS', 'RELHUM', 'SHFLX', 'SOLIN', 'SWCF', 'QCP', - 'QTHERMAL', 'QRL_TOT', 'QRS_TOT', 'PSL', 'HNO3_STS', 'HNO3_NAT', + 'QTHERMAL', 'QRL_TOT', 'QRS_TOT', 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Aircraft', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'T', 'TREFHT', 'TTGW', 'U', 'UTGWORO', 'UTGWSPEC', 'V', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'O2_1S', diff --git a/bld/namelist_files/use_cases/sd_waccmx_ma_cam4.xml b/bld/namelist_files/use_cases/sd_waccmx_ma_cam4.xml index f50160948e..6ec178700a 100644 --- a/bld/namelist_files/use_cases/sd_waccmx_ma_cam4.xml +++ b/bld/namelist_files/use_cases/sd_waccmx_ma_cam4.xml @@ -80,7 +80,7 @@ 'Z3', 'T', 'TIon', 'TElec', 'e', 'U', 'V', 'OMEGA', 'UI', 'VI', 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2' 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', - 'QNO', 'QO3P', 'QHC2S', 'EKGW', 'TTGW', 'UTGW_TOTAL', + 'QNO', 'QO3P', 'QHC2S', 'QJOULE', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'V_08_COS', 'V_08_SIN', diff --git a/bld/namelist_files/use_cases/sd_waccmx_ma_cam6.xml b/bld/namelist_files/use_cases/sd_waccmx_ma_cam6.xml index 984ab0b002..6493ed584b 100644 --- a/bld/namelist_files/use_cases/sd_waccmx_ma_cam6.xml +++ b/bld/namelist_files/use_cases/sd_waccmx_ma_cam6.xml @@ -67,7 +67,7 @@ 'Z3', 'T', 'TIon', 'TElec', 'e', 'U', 'V', 'OMEGA', 'UI', 'VI', 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2' 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', - 'QNO', 'QO3P', 'QHC2S', 'EKGW', 'TTGW', 'UTGW_TOTAL', + 'QNO', 'QO3P', 'QHC2S', 'QJOULE', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'V_08_COS', 'V_08_SIN', diff --git a/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml b/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml index c04967bace..1429770e8e 100644 --- a/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml +++ b/bld/namelist_files/use_cases/waccm_carma_bc_2013_cam4.xml @@ -90,7 +90,7 @@ 'HNO3_GAS', 'NO_Aircraft', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'T', 'TREFHT', 'TTGW', 'U', 'UTGWORO', 'UTGWSPEC', 'V', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'O2_1S', - 'O2_1D', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI', + 'O2_1D', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', diff --git a/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml b/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml index d978796e4a..24b55facc2 100644 --- a/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_ma_1850_cam6.xml @@ -63,7 +63,7 @@ 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'TREFHT', 'TTGW', 'UTGWORO', 'UTGWSPEC', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'HOX', 'NOX', 'NOY', 'CLOX', - 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI', 'VI', 'UIONTEND', 'VIONTEND', + 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'PS_24_COS', 'PS_24_SIN', 'PS_12_COS', diff --git a/bld/namelist_files/use_cases/waccm_ma_2000_cam6.xml b/bld/namelist_files/use_cases/waccm_ma_2000_cam6.xml index 5443a10f83..9ccac8892f 100644 --- a/bld/namelist_files/use_cases/waccm_ma_2000_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_ma_2000_cam6.xml @@ -158,7 +158,7 @@ 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'TREFHT', 'TTGW', 'UTGWORO', 'UTGWSPEC', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'HOX', 'NOX', 'NOY', 'CLOX', - 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI', 'VI', 'UIONTEND', 'VIONTEND', + 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'PS_24_COS', 'PS_24_SIN', 'PS_12_COS', diff --git a/bld/namelist_files/use_cases/waccm_ma_hist_cam4.xml b/bld/namelist_files/use_cases/waccm_ma_hist_cam4.xml index 6526502ba5..e2376e4a70 100644 --- a/bld/namelist_files/use_cases/waccm_ma_hist_cam4.xml +++ b/bld/namelist_files/use_cases/waccm_ma_hist_cam4.xml @@ -86,7 +86,7 @@ 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'TREFHT', 'TTGW', 'UTGWORO', 'UTGWSPEC', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'HOX', 'NOX', 'NOY', 'CLOX', - 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI', 'VI', 'UIONTEND', 'VIONTEND', + 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'PS_24_COS', 'PS_24_SIN', 'PS_12_COS', diff --git a/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml b/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml index 30deb2b74d..042a153fe4 100644 --- a/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml +++ b/bld/namelist_files/use_cases/waccm_ma_hist_cam6.xml @@ -57,7 +57,7 @@ 'QJOULE', 'PSL', 'HNO3_STS', 'HNO3_NAT', 'HNO3_GAS', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'TREFHT', 'TTGW', 'UTGWORO', 'UTGWSPEC', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'HOX', 'NOX', 'NOY', 'CLOX', - 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI', 'VI', 'UIONTEND', 'VIONTEND', + 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UI', 'VI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'PS_24_COS', 'PS_24_SIN', 'PS_12_COS', diff --git a/bld/namelist_files/use_cases/waccmx_ma_2000_cam4.xml b/bld/namelist_files/use_cases/waccmx_ma_2000_cam4.xml index c5bc7e2f57..017cc3362e 100644 --- a/bld/namelist_files/use_cases/waccmx_ma_2000_cam4.xml +++ b/bld/namelist_files/use_cases/waccmx_ma_2000_cam4.xml @@ -87,7 +87,7 @@ 'HNO3_GAS', 'NO_Aircraft', 'NO_Lightning', 'QNO', 'QRS_AUR', 'QRS_CO2NIR', 'QRS_EUV', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'T', 'TREFHT', 'TTGW', 'U', 'UTGWORO', 'UTGWSPEC', 'V', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'O2_1S', - 'O2_1D', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UI','VI','WI', + 'O2_1D', 'NOX', 'NOY', 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE','UI','VI','WI', 'UIONTEND', 'VIONTEND', 'DTCORE', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', 'OMEGA_12_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', @@ -134,7 +134,7 @@ 'Qbkgndtot','Qbkgnd_o1','Qbkgnd_o2','Qbkgnd_n2','Qbkgnd_n1','Qbkgnd_no', 'SAD_ICE', 'SAD_LNAT', 'SAD_SULFC', 'T', 'TREFHT', 'TTGW', 'U', 'UTGWORO', 'UTGWSPEC', 'V', 'VERT', 'VTGWORO', 'VTGWSPEC', 'Z3', 'O2_1S', 'O2_1D', 'NOX', 'NOY', - 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'UIONTEND', 'VIONTEND', + 'CLOX', 'CLOY', 'BROX', 'BROY', 'TCLY', 'TOTH', 'QJOULE', 'UIONTEND', 'VIONTEND', 'DTCORE', 'CLDLIQ', 'CLDICE', 'CONCLD', 'FRONTGF:I', 'BUTGWSPEC', 'BTAUE', 'BTAUW', 'BTAUN', 'BTAUS', 'TAUE', 'TAUW', 'TAUN', 'TAUS', 'TAUGWX', 'TAUGWY', 'TAUX', 'TAUY', 'SNOWHLND', 'SNOWHICE', 'ICEFRAC', 'FSDSC', 'SFNO', 'SFCO', 'SFCH2O', 'CFC11STAR', 'TROPP_FD', 'Op', 'O2p', 'Np', 'NOp', diff --git a/bld/namelist_files/use_cases/waccmx_ma_2000_cam6.xml b/bld/namelist_files/use_cases/waccmx_ma_2000_cam6.xml index 713ad27c86..06520cc3fb 100644 --- a/bld/namelist_files/use_cases/waccmx_ma_2000_cam6.xml +++ b/bld/namelist_files/use_cases/waccmx_ma_2000_cam6.xml @@ -48,7 +48,7 @@ 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2', 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', 'QNO', - 'QO3P', 'QHC2S', 'QEN', 'QIN', 'QEI', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', + 'QO3P', 'QHC2S', 'QJOULE', 'QEN', 'QIN', 'QEI', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'V_08_COS', 'V_08_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', diff --git a/bld/namelist_files/use_cases/waccmx_ma_hist_cam6.xml b/bld/namelist_files/use_cases/waccmx_ma_hist_cam6.xml index 02d3b04009..37ca427cd2 100644 --- a/bld/namelist_files/use_cases/waccmx_ma_hist_cam6.xml +++ b/bld/namelist_files/use_cases/waccmx_ma_hist_cam6.xml @@ -46,7 +46,7 @@ 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2', 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', 'QNO', - 'QO3P', 'QHC2S', 'QEN', 'QIN', 'QEI', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', + 'QO3P', 'QHC2S', 'QJOULE', 'QEN', 'QIN', 'QEI', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', 'V_24_COS', 'V_24_SIN', 'V_12_COS', 'V_12_SIN', 'V_08_COS', 'V_08_SIN', 'OMEGA_24_COS', 'OMEGA_24_SIN', 'OMEGA_12_COS', diff --git a/bld/namelist_files/use_cases/waccmxie_ma_2000_cam4.xml b/bld/namelist_files/use_cases/waccmxie_ma_2000_cam4.xml index ae18c1113c..5fe9c654dd 100644 --- a/bld/namelist_files/use_cases/waccmxie_ma_2000_cam4.xml +++ b/bld/namelist_files/use_cases/waccmxie_ma_2000_cam4.xml @@ -98,7 +98,7 @@ 'Z3', 'T', 'TIon', 'TElec', 'e', 'U', 'V', 'OMEGA', 'UI', 'VI', 'WI', 'ElecColDens', 'PHIM2D', 'PS', 'PED_CONDUCTANCE', 'HALL_CONDUCTANCE', 'ED1', 'ED2' 'O', 'O2', 'H', 'NO', 'CO2', 'N', 'O1D', 'Op2P', 'Op2D', 'Op', - 'Np', 'N2p', 'O2p', 'NOp', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', + 'Np', 'N2p', 'O2p', 'NOp', 'QJOULE', 'SIGMAHAL', 'SIGMAPED', 'SolIonRate_Tot', 'QRS_TOT', 'QO3', 'QCO2', 'QNO', 'QO3P', 'QHC2S', 'QJOULE', 'EKGW', 'TTGW', 'UTGW_TOTAL', 'T_24_COS', 'T_24_SIN', 'T_12_COS', 'T_12_SIN', 'T_08_COS', 'T_08_SIN', 'U_24_COS', 'U_24_SIN', 'U_12_COS', 'U_12_SIN', 'U_08_COS', 'U_08_SIN', diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq24h_port/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/outfrq24h_port/user_nl_cam index 2d18788e39..e385809756 100644 --- a/cime_config/testdefs/testmods_dirs/cam/outfrq24h_port/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/outfrq24h_port/user_nl_cam @@ -2,7 +2,7 @@ rad_data_fdh = .true. empty_htapes = .true. avgflag_pertape = 'A','I' - fincl1 = 'SOLIN', 'QRS', 'FSNS', 'FSNT','FSNSC', 'FSNR','FLNR', + fincl1 = 'SOLIN', 'QRS', 'FSNS', 'FSNT','FSNSC', 'FSDSC','FSNR','FLNR', 'FSNTOA', 'FSUTOA', 'FSNTOAC', 'FSNTC', 'FSDSC', 'FSDS', 'SWCF', 'QRL', 'FLNS', 'FLDS', 'FLNT', 'LWCF', 'FLUT' ,'FLUTC', 'FLNTC', 'FLNSC', 'FLDSC' From 31e7e6b73a07454b3e56684d3d266bba087e5008 Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Thu, 3 Oct 2024 16:17:53 -0600 Subject: [PATCH 07/82] improve error handling --- src/control/cam_history.F90 | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index 0d3a4dc823..acbcbd266d 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -2552,6 +2552,7 @@ subroutine fldlst () use cam_grid_support, only: cam_grid_num_grids use spmd_utils, only: mpicom use dycore, only: dycore_is + use shr_kind_mod, only: cm => shr_kind_cm !----------------------------------------------------------------------- ! @@ -2567,7 +2568,8 @@ subroutine fldlst () integer t, fld ! tape, field indices integer ffld ! index into include, exclude and fprec list integer :: i - logical :: duplicate_error ! flag for whether there is an incompatible duplicate found + character(len=cm) :: duplicate_error ! string to be populated if an incompatible duplicate is found + character(len=cm) :: tempmsg ! string to be populated if an incompatible duplicate is found character(len=fieldname_len) :: name ! field name portion of fincl (i.e. no avgflag separator) character(len=max_fieldname_len) :: mastername ! name from masterlist field character(len=max_chars) :: errormsg ! error output field @@ -2730,6 +2732,7 @@ subroutine fldlst () allocate(gridsontape(cam_grid_num_grids() + 1, ptapes)) gridsontape = -1 + errormsg = '' do t=1,ptapes ! ! Add the field to the tape if specified via namelist (FINCL[1-ptapes]), or if @@ -2742,11 +2745,13 @@ subroutine fldlst () do while(associated(listentry)) mastername = listentry%field%name call list_index (fincl(1,t), mastername, ffld, duplicate_error=duplicate_error) - if (duplicate_error) then - write(errormsg,'(2a,2(a,i3))') & - 'FLDLST: Duplicate field with different averaging flags. Place on separate tapes: ', & - trim(mastername),', tape = ', t, ', ffld = ', ffld - call endrun(trim(errormsg)) + if (len(trim(duplicate_error)) > 0) then + if (len_trim(errormsg) == 0) then + write(errormsg,*) & + 'FLDLST: Found duplicate field(s) with different averaging flags. Place on separate tapes: ' + end if + write(tempmsg, '(2a, i0, a)') trim(duplicate_error), ' (tape ', t, '). ' + errormsg = trim(errormsg) // trim(tempmsg) end if fieldontape = .false. @@ -2774,6 +2779,9 @@ subroutine fldlst () listentry=>listentry%next_entry end do end do + if (len(errormsg) > 0) then + call endrun(trim(errormsg)) + end if ! ! Determine total number of active history tapes ! @@ -3510,7 +3518,7 @@ subroutine list_index (list, name, index, duplicate_error) ! character(len=*), intent(in) :: list(pflds) ! input list of names, possibly ":" delimited character(len=*), intent(in) :: name ! name to be searched for - logical, optional, intent(out) :: duplicate_error ! .true. if a duplicate field was found with different flags + character(len=*), optional, intent(out) :: duplicate_error ! if present, check the flags and return an error if incompatible ! ! Output arguments ! @@ -3525,7 +3533,7 @@ subroutine list_index (list, name, index, duplicate_error) index = 0 if (present(duplicate_error)) then - duplicate_error = .false. + duplicate_error = '' end if do f=1,pflds @@ -3539,7 +3547,9 @@ subroutine list_index (list, name, index, duplicate_error) ! This already exists in the field list - check the flag flag_comp = getflag(list(f)) if (trim(flag_comp) /= trim(flag)) then - duplicate_error = .true. + write(duplicate_error,*) & + '"', trim(list(f)), '", "', trim(name), & + ':', trim(flag), '"' return ! No else - if the flags are identical, we're ok to return the first ! instance From ca138950be0819fe86f870c618201afd1f346681 Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Thu, 3 Oct 2024 16:32:09 -0600 Subject: [PATCH 08/82] remove reference to tapes --- src/control/cam_history.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index acbcbd266d..156d70f573 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -2748,9 +2748,9 @@ subroutine fldlst () if (len(trim(duplicate_error)) > 0) then if (len_trim(errormsg) == 0) then write(errormsg,*) & - 'FLDLST: Found duplicate field(s) with different averaging flags. Place on separate tapes: ' + 'FLDLST: Found duplicate field(s) with different averaging flags. Place in separate fincl lists: ' end if - write(tempmsg, '(2a, i0, a)') trim(duplicate_error), ' (tape ', t, '). ' + write(tempmsg, '(2a, i0, a)') trim(duplicate_error), ' (fincl', t, '). ' errormsg = trim(errormsg) // trim(tempmsg) end if From b960ffb79a952f7cab6ce1e2671a566d80e92fc5 Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Thu, 3 Oct 2024 17:05:44 -0600 Subject: [PATCH 09/82] don't error all the time perhaps --- src/control/cam_history.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index 156d70f573..0b7ce50944 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -2779,7 +2779,7 @@ subroutine fldlst () listentry=>listentry%next_entry end do end do - if (len(errormsg) > 0) then + if (len_trim(errormsg) > 0) then call endrun(trim(errormsg)) end if ! From 225f7e3a5e836688ec1168f5b0369051fd34cd2c Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Fri, 11 Oct 2024 14:47:49 -0600 Subject: [PATCH 10/82] add sampled_on_subcycle flag and remove time_bounds field from instantaneous files --- src/control/cam_history.F90 | 53 ++- src/control/cam_history_support.F90 | 3 + src/physics/cam/cam_diagnostics.F90 | 6 +- src/physics/cam/check_energy.F90 | 12 +- src/physics/cam/clubb_intr.F90 | 170 ++++---- src/physics/cam/macrop_driver.F90 | 70 ++-- src/physics/cam/micro_pumas_cam.F90 | 336 +++++++-------- src/physics/cam/microp_aero.F90 | 6 +- src/physics/cam7/micro_pumas_cam.F90 | 410 +++++++++---------- src/physics/cam7/stochastic_emulated_cam.F90 | 72 ++-- src/physics/cam7/stochastic_tau_cam.F90 | 72 ++-- 11 files changed, 618 insertions(+), 592 deletions(-) diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index 0b7ce50944..e86f885f0e 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -486,6 +486,12 @@ subroutine intht (model_doi_url_in) ! do t=1,ptapes do fld=1,nflds(t) + if ((.not. tape(t)%hlist(fld)%field%sampled_on_subcycle) .and. nhtfrq(t) == 1) then + ! Override accumulate flag to "I" if nhtfrq equals 1 and subcycle + ! averaging is not enabled + tape(t)%hlist(fld)%avgflag = 'I' + end if + if (tape(t)%hlist(fld)%avgflag .ne. 'I') then hfile_accum(t) = .true. end if @@ -4022,7 +4028,9 @@ subroutine h_inquire (t) ierr=pio_inq_varid (tape(t)%Files(f),'nscur ', tape(t)%nscurid) ierr=pio_inq_varid (tape(t)%Files(f),'nsteph ', tape(t)%nstephid) end if - ierr=pio_inq_varid (tape(t)%Files(f),'time_bounds', tape(t)%tbndid) + if (f == accumulated_file_index) then + ierr=pio_inq_varid (tape(t)%Files(f),'time_bounds', tape(t)%tbndid) + end if ierr=pio_inq_varid (tape(t)%Files(f),'date_written', tape(t)%date_writtenid) ierr=pio_inq_varid (tape(t)%Files(f),'time_written', tape(t)%time_writtenid) #if ( defined BFB_CAM_SCAM_IOP ) @@ -4321,6 +4329,7 @@ subroutine h_define (t, restart) cam_snapshot_before_num_out = cam_snapshot_before_num, & cam_snapshot_after_num_out = cam_snapshot_after_num) + if(restart) then tape => restarthistory_tape if(masterproc) write(iulog,*)'Opening netcdf history restart file ', trim(hrestpath(t)) @@ -4500,13 +4509,14 @@ subroutine h_define (t, restart) if(.not. is_satfile(t)) then - ierr=pio_put_att (tape(t)%Files(f), tape(t)%timeid, 'bounds', 'time_bounds') - - ierr=pio_def_var (tape(t)%Files(f),'time_bounds',pio_double,(/bnddim,timdim/),tape(t)%tbndid) - ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'long_name', 'time interval endpoints') - str = 'days since ' // date2yyyymmdd(nbdate) // ' ' // sec2hms(nbsec) - ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'units', trim(str)) - ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'calendar', trim(calendar)) + if (f == accumulated_file_index) then + ierr=pio_put_att (tape(t)%Files(f), tape(t)%timeid, 'bounds', 'time_bounds') + ierr=pio_def_var (tape(t)%Files(f),'time_bounds',pio_double,(/bnddim,timdim/),tape(t)%tbndid) + ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'long_name', 'time interval endpoints') + str = 'days since ' // date2yyyymmdd(nbdate) // ' ' // sec2hms(nbsec) + ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'units', trim(str)) + ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'calendar', trim(calendar)) + end if ! ! Character ! @@ -5843,14 +5853,16 @@ subroutine wshist (rgnht_in) cycle end if ! We have two files - one for accumulated and one for instantaneous fields - if (f == accumulated_file_index .and. .not. restart .and. .not. is_initfile(t)) then - ! accumulated tape - time is midpoint of time_bounds - ierr=pio_put_var (tape(t)%Files(f), tape(t)%timeid, (/start/),(/count1/),(/(tdata(1) + tdata(2)) / 2._r8/)) + if (f == accumulated_file_index) then + ierr=pio_put_var (tape(t)%Files(f), tape(t)%tbndid, startc, countc, tdata) + if (.not. restart .and. .not. is_initfile(t)) then + ! accumulated tape - time is midpoint of time_bounds + ierr=pio_put_var (tape(t)%Files(f), tape(t)%timeid, (/start/),(/count1/),(/(tdata(1) + tdata(2)) / 2._r8/)) + end if else ! not an accumulated history tape - time is current time ierr=pio_put_var (tape(t)%Files(f), tape(t)%timeid, (/start/),(/count1/),(/time/)) end if - ierr=pio_put_var (tape(t)%Files(f), tape(t)%tbndid, startc, countc, tdata) end do if(.not.restart) beg_time(t) = time ! update beginning time of next interval startc(1) = 1 @@ -5938,7 +5950,7 @@ end subroutine wshist subroutine addfld_1d(fname, vdim_name, avgflag, units, long_name, & gridname, flag_xyfill, sampling_seq, standard_name, fill_value, & - optype, op_f1name, op_f2name) + optype, op_f1name, op_f2name, sampled_on_subcycle) ! !----------------------------------------------------------------------- @@ -5970,6 +5982,7 @@ subroutine addfld_1d(fname, vdim_name, avgflag, units, long_name, & character(len=*), intent(in), optional :: optype ! currently 'dif' or 'sum' is supported character(len=*), intent(in), optional :: op_f1name ! first field to be operated on character(len=*), intent(in), optional :: op_f2name ! second field which is subtracted from or added to first field + logical, intent(in), optional :: sampled_on_subcycle ! If .true., subcycle averaging is enabled ! ! Local workspace ! @@ -5988,13 +6001,13 @@ subroutine addfld_1d(fname, vdim_name, avgflag, units, long_name, & end if call addfld(fname, dimnames, avgflag, units, long_name, gridname, & flag_xyfill, sampling_seq, standard_name, fill_value, optype, op_f1name, & - op_f2name) + op_f2name, sampled_on_subcycle) end subroutine addfld_1d subroutine addfld_nd(fname, dimnames, avgflag, units, long_name, & gridname, flag_xyfill, sampling_seq, standard_name, fill_value, optype, & - op_f1name, op_f2name) + op_f1name, op_f2name, sampled_on_subcycle) ! !----------------------------------------------------------------------- @@ -6030,6 +6043,7 @@ subroutine addfld_nd(fname, dimnames, avgflag, units, long_name, & character(len=*), intent(in), optional :: optype ! currently 'dif' or 'sum' supported character(len=*), intent(in), optional :: op_f1name ! first field to be operated on character(len=*), intent(in), optional :: op_f2name ! second field which is subtracted from or added to first field + logical, intent(in), optional :: sampled_on_subcycle ! If .true., subcycle averaging is enabled ! ! Local workspace @@ -6154,6 +6168,15 @@ subroutine addfld_nd(fname, dimnames, avgflag, units, long_name, & listentry%field%fillvalue = fillvalue endif + ! + ! Whether to allow subcycle averages; default is false + ! + if (present(sampled_on_subcycle)) then + listentry%field%sampled_on_subcycle = sampled_on_subcycle + else + listentry%field%sampled_on_subcycle = .false. + end if + ! ! Process shape ! diff --git a/src/control/cam_history_support.F90 b/src/control/cam_history_support.F90 index 940dc8c177..5e5983e784 100644 --- a/src/control/cam_history_support.F90 +++ b/src/control/cam_history_support.F90 @@ -118,6 +118,9 @@ module cam_history_support integer :: meridional_complement ! meridional field id or -1 integer :: zonal_complement ! zonal field id or -1 + ! Logical to determine if subcycle averages are allowed + logical :: sampled_on_subcycle = .false. + character(len=field_op_len) :: field_op = '' ! 'sum' or 'dif' integer :: op_field1_id ! first field id or -1 integer :: op_field2_id ! second field id or -1 diff --git a/src/physics/cam/cam_diagnostics.F90 b/src/physics/cam/cam_diagnostics.F90 index 97dad2ba01..082a2df9d8 100644 --- a/src/physics/cam/cam_diagnostics.F90 +++ b/src/physics/cam/cam_diagnostics.F90 @@ -232,9 +232,9 @@ subroutine diag_init_dry(pbuf2d) call register_vector_field('UTEND_TOT','VTEND_TOT') ! Debugging negative water output fields - call addfld ('INEGCLPTEND ', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud ice tendency due to clipping neg values after microp') - call addfld ('LNEGCLPTEND ', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud liq tendency due to clipping neg values after microp') - call addfld ('VNEGCLPTEND ', (/ 'lev' /), 'A', 'kg/kg/s', 'Vapor tendency due to clipping neg values after microp') + call addfld ('INEGCLPTEND ', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud ice tendency due to clipping neg values after microp', sampled_on_subcycle=.true.) + call addfld ('LNEGCLPTEND ', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud liq tendency due to clipping neg values after microp', sampled_on_subcycle=.true.) + call addfld ('VNEGCLPTEND ', (/ 'lev' /), 'A', 'kg/kg/s', 'Vapor tendency due to clipping neg values after microp', sampled_on_subcycle=.true.) call addfld ('Z3', (/ 'lev' /), 'A', 'm', 'Geopotential Height (above sea level)') call addfld ('Z1000', horiz_only, 'A', 'm', 'Geopotential Z at 1000 mbar pressure surface') diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 9c569387e0..94ef9a05e1 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -201,12 +201,12 @@ subroutine check_energy_init() history_waccm_out = history_waccm ) ! register history variables - call addfld('TEINP', horiz_only, 'A', 'J/m2', 'Total energy of physics input') - call addfld('TEOUT', horiz_only, 'A', 'J/m2', 'Total energy of physics output') - call addfld('TEFIX', horiz_only, 'A', 'J/m2', 'Total energy after fixer') - call addfld('EFIX', horiz_only, 'A', 'W/m2', 'Effective sensible heat flux due to energy fixer') - call addfld('DTCORE', (/ 'lev' /), 'A', 'K/s' , 'T tendency due to dynamical core') - call addfld('DQCORE', (/ 'lev' /), 'A', 'kg/kg/s' , 'Water vapor tendency due to dynamical core') + call addfld('TEINP', horiz_only, 'A', 'J/m2', 'Total energy of physics input', sampled_on_subcycle=.true.) + call addfld('TEOUT', horiz_only, 'A', 'J/m2', 'Total energy of physics output', sampled_on_subcycle=.true.) + call addfld('TEFIX', horiz_only, 'A', 'J/m2', 'Total energy after fixer', sampled_on_subcycle=.true.) + call addfld('EFIX', horiz_only, 'A', 'W/m2', 'Effective sensible heat flux due to energy fixer', sampled_on_subcycle=.true.) + call addfld('DTCORE', (/ 'lev' /), 'A', 'K/s' , 'T tendency due to dynamical core', sampled_on_subcycle=.true.) + call addfld('DQCORE', (/ 'lev' /), 'A', 'kg/kg/s' , 'Water vapor tendency due to dynamical core', sampled_on_subcycle=.true.) if ( history_budget ) then call add_default ('DTCORE', history_budget_histfile_num, ' ') diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 9bbf211fba..872bbc4963 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -1777,96 +1777,96 @@ subroutine clubb_ini_cam(pbuf2d) ! ----------------------------------------------------------------- ! ! These are default CLUBB output. Not the higher order history budgets - call addfld ('RHO_CLUBB', (/ 'lev' /), 'A', 'kg/m3', 'Air Density') - call addfld ('UP2_CLUBB', (/ 'ilev' /), 'A', 'm2/s2', 'Zonal Velocity Variance') - call addfld ('VP2_CLUBB', (/ 'ilev' /), 'A', 'm2/s2', 'Meridional Velocity Variance') - call addfld ('WP2_CLUBB', (/ 'ilev' /), 'A', 'm2/s2', 'Vertical Velocity Variance') - call addfld ('WP2_ZT_CLUBB', (/ 'lev' /), 'A', 'm2/s2', 'Vert Vel Variance on zt grid') - call addfld ('UPWP_CLUBB', (/ 'ilev' /), 'A', 'm2/s2', 'Zonal Momentum Flux') - call addfld ('VPWP_CLUBB', (/ 'ilev' /), 'A', 'm2/s2', 'Meridional Momentum Flux') - call addfld ('WP3_CLUBB', (/ 'lev' /), 'A', 'm3/s3', 'Third Moment Vertical Velocity') - call addfld ('WPTHLP_CLUBB', (/ 'ilev' /), 'A', 'W/m2', 'Heat Flux') - call addfld ('WPRTP_CLUBB', (/ 'ilev' /), 'A', 'W/m2', 'Moisture Flux') - call addfld ('RTP2_CLUBB', (/ 'ilev' /), 'A', 'kg^2/kg^2', 'Moisture Variance') - call addfld ('RTP2_ZT_CLUBB', (/ 'lev' /), 'A', 'kg^2/kg^2','Moisture Variance on zt grid') - call addfld ('PDFP_RTP2_CLUBB', (/ 'ilev' /), 'A', 'kg^2/kg^2','PDF Rtot Variance') - call addfld ('THLP2_CLUBB', (/ 'ilev' /), 'A', 'K^2', 'Temperature Variance') - call addfld ('THLP2_ZT_CLUBB', (/ 'lev' /), 'A', 'K^2', 'Temperature Variance on zt grid') - call addfld ('RTPTHLP_CLUBB', (/ 'ilev' /), 'A', 'K kg/kg', 'Temp. Moist. Covariance') - call addfld ('RCM_CLUBB', (/ 'lev' /), 'A', 'kg/kg', 'Cloud Water Mixing Ratio') - call addfld ('RTM_CLUBB', (/ 'lev' /), 'A', 'kg/kg', 'Total Water Mixing Ratio') - call addfld ('THLM_CLUBB', (/ 'lev' /), 'A', 'K', 'Liquid Water Potential Temperature') - call addfld ('WPRCP_CLUBB', (/ 'ilev' /), 'A', 'W/m2', 'Liquid Water Flux') - call addfld ('CLOUDFRAC_CLUBB', (/ 'lev' /), 'A', 'fraction', 'Cloud Fraction') - call addfld ('RCMINLAYER_CLUBB', (/ 'lev' /), 'A', 'kg/kg', 'Cloud Water in Layer') - call addfld ('CLOUDCOVER_CLUBB', (/ 'lev' /), 'A', 'fraction', 'Cloud Cover') - call addfld ('WPTHVP_CLUBB', (/ 'ilev' /), 'A', 'W/m2', 'Buoyancy Flux') - call addfld ('RVMTEND_CLUBB', (/ 'lev' /), 'A', 'kg/kg /s', 'Water vapor tendency') - call addfld ('STEND_CLUBB', (/ 'lev' /), 'A', 'J/(kg s)', 'Static energy tendency') - call addfld ('RCMTEND_CLUBB', (/ 'lev' /), 'A', 'kg/kg /s', 'Cloud Liquid Water Tendency') - call addfld ('RIMTEND_CLUBB', (/ 'lev' /), 'A', 'kg/kg /s', 'Cloud Ice Tendency') - call addfld ('UTEND_CLUBB', (/ 'lev' /), 'A', 'm/s /s', 'U-wind Tendency') - call addfld ('VTEND_CLUBB', (/ 'lev' /), 'A', 'm/s /s', 'V-wind Tendency') - call addfld ('ZT_CLUBB', (/ 'lev' /), 'A', 'm', 'Thermodynamic Heights') - call addfld ('ZM_CLUBB', (/ 'ilev' /), 'A', 'm', 'Momentum Heights') - call addfld ('UM_CLUBB', (/ 'lev' /), 'A', 'm/s', 'Zonal Wind') - call addfld ('VM_CLUBB', (/ 'lev' /), 'A', 'm/s', 'Meridional Wind') - call addfld ('WM_ZT_CLUBB', (/ 'lev' /), 'A', 'm/s', 'Vertical Velocity') - call addfld ('PBLH', horiz_only, 'A', 'm', 'PBL height') - call addfld ('CLDST', (/ 'lev' /), 'A', 'fraction', 'Stratus cloud fraction') - call addfld ('ZMDLF', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from ZM convection') - call addfld ('TTENDICE', (/ 'lev' /), 'A', 'K/s', 'T tendency from Ice Saturation Adjustment') - call addfld ('QVTENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Q tendency from Ice Saturation Adjustment') - call addfld ('QITENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency from Ice Saturation Adjustment') - call addfld ('NITENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'NUMICE tendency from Ice Saturation Adjustment') - - - call addfld ('QCTENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency from Ice Saturation Adjustment') - call addfld ('NCTENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'NUMICE tendency from Ice Saturation Adjustment') - call addfld ('FQTENDICE', (/ 'lev' /), 'A', 'fraction', 'Frequency of Ice Saturation Adjustment') - - call addfld ('DPDLFLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from deep convection') - call addfld ('DPDLFICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained ice from deep convection') - call addfld ('DPDLFT', (/ 'lev' /), 'A', 'K/s', 'T-tendency due to deep convective detrainment') - call addfld ('RELVAR', (/ 'lev' /), 'A', '-', 'Relative cloud water variance') - call addfld ('CLUBB_GRID_SIZE', horiz_only, 'A', 'm', 'Horizontal grid box size seen by CLUBB') - - - call addfld ('ZMDLFI', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained ice water from ZM convection') - call addfld ('CONCLD', (/ 'lev' /), 'A', 'fraction', 'Convective cloud cover') - call addfld ('CMELIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of cond-evap of liq within the cloud') - call addfld ('DETNLIQTND', (/ 'lev' /), 'A', '1/kg/s', 'CLDNUM tendency in detrained water') - - call addfld ('QSATFAC', (/ 'lev' /), 'A', '-', 'Subgrid cloud water saturation scaling factor') - call addfld ('KVH_CLUBB', (/ 'ilev' /), 'A', 'm2/s', 'CLUBB vertical diffusivity of heat/moisture on interface levels') - call addfld ('ELEAK_CLUBB', horiz_only, 'A', 'W/m2', 'CLUBB energy leak') - call addfld ('TFIX_CLUBB', horiz_only, 'A', 'K', 'Temperature increment to conserve energy') + call addfld ('RHO_CLUBB', (/ 'lev' /), 'A', 'kg/m3', 'Air Density', sampled_on_subcycle=.true.) + call addfld ('UP2_CLUBB', (/ 'ilev' /), 'A', 'm2/s2', 'Zonal Velocity Variance', sampled_on_subcycle=.true.) + call addfld ('VP2_CLUBB', (/ 'ilev' /), 'A', 'm2/s2', 'Meridional Velocity Variance', sampled_on_subcycle=.true.) + call addfld ('WP2_CLUBB', (/ 'ilev' /), 'A', 'm2/s2', 'Vertical Velocity Variance', sampled_on_subcycle=.true.) + call addfld ('WP2_ZT_CLUBB', (/ 'lev' /), 'A', 'm2/s2', 'Vert Vel Variance on zt grid', sampled_on_subcycle=.true.) + call addfld ('UPWP_CLUBB', (/ 'ilev' /), 'A', 'm2/s2', 'Zonal Momentum Flux', sampled_on_subcycle=.true.) + call addfld ('VPWP_CLUBB', (/ 'ilev' /), 'A', 'm2/s2', 'Meridional Momentum Flux', sampled_on_subcycle=.true.) + call addfld ('WP3_CLUBB', (/ 'lev' /), 'A', 'm3/s3', 'Third Moment Vertical Velocity', sampled_on_subcycle=.true.) + call addfld ('WPTHLP_CLUBB', (/ 'ilev' /), 'A', 'W/m2', 'Heat Flux', sampled_on_subcycle=.true.) + call addfld ('WPRTP_CLUBB', (/ 'ilev' /), 'A', 'W/m2', 'Moisture Flux', sampled_on_subcycle=.true.) + call addfld ('RTP2_CLUBB', (/ 'ilev' /), 'A', 'kg^2/kg^2', 'Moisture Variance', sampled_on_subcycle=.true.) + call addfld ('RTP2_ZT_CLUBB', (/ 'lev' /), 'A', 'kg^2/kg^2','Moisture Variance on zt grid', sampled_on_subcycle=.true.) + call addfld ('PDFP_RTP2_CLUBB', (/ 'ilev' /), 'A', 'kg^2/kg^2','PDF Rtot Variance', sampled_on_subcycle=.true.) + call addfld ('THLP2_CLUBB', (/ 'ilev' /), 'A', 'K^2', 'Temperature Variance', sampled_on_subcycle=.true.) + call addfld ('THLP2_ZT_CLUBB', (/ 'lev' /), 'A', 'K^2', 'Temperature Variance on zt grid', sampled_on_subcycle=.true.) + call addfld ('RTPTHLP_CLUBB', (/ 'ilev' /), 'A', 'K kg/kg', 'Temp. Moist. Covariance', sampled_on_subcycle=.true.) + call addfld ('RCM_CLUBB', (/ 'lev' /), 'A', 'kg/kg', 'Cloud Water Mixing Ratio', sampled_on_subcycle=.true.) + call addfld ('RTM_CLUBB', (/ 'lev' /), 'A', 'kg/kg', 'Total Water Mixing Ratio', sampled_on_subcycle=.true.) + call addfld ('THLM_CLUBB', (/ 'lev' /), 'A', 'K', 'Liquid Water Potential Temperature', sampled_on_subcycle=.true.) + call addfld ('WPRCP_CLUBB', (/ 'ilev' /), 'A', 'W/m2', 'Liquid Water Flux', sampled_on_subcycle=.true.) + call addfld ('CLOUDFRAC_CLUBB', (/ 'lev' /), 'A', 'fraction', 'Cloud Fraction', sampled_on_subcycle=.true.) + call addfld ('RCMINLAYER_CLUBB', (/ 'lev' /), 'A', 'kg/kg', 'Cloud Water in Layer', sampled_on_subcycle=.true.) + call addfld ('CLOUDCOVER_CLUBB', (/ 'lev' /), 'A', 'fraction', 'Cloud Cover', sampled_on_subcycle=.true.) + call addfld ('WPTHVP_CLUBB', (/ 'ilev' /), 'A', 'W/m2', 'Buoyancy Flux', sampled_on_subcycle=.true.) + call addfld ('RVMTEND_CLUBB', (/ 'lev' /), 'A', 'kg/kg /s', 'Water vapor tendency', sampled_on_subcycle=.true.) + call addfld ('STEND_CLUBB', (/ 'lev' /), 'A', 'J/(kg s)', 'Static energy tendency', sampled_on_subcycle=.true.) + call addfld ('RCMTEND_CLUBB', (/ 'lev' /), 'A', 'kg/kg /s', 'Cloud Liquid Water Tendency', sampled_on_subcycle=.true.) + call addfld ('RIMTEND_CLUBB', (/ 'lev' /), 'A', 'kg/kg /s', 'Cloud Ice Tendency', sampled_on_subcycle=.true.) + call addfld ('UTEND_CLUBB', (/ 'lev' /), 'A', 'm/s /s', 'U-wind Tendency', sampled_on_subcycle=.true.) + call addfld ('VTEND_CLUBB', (/ 'lev' /), 'A', 'm/s /s', 'V-wind Tendency', sampled_on_subcycle=.true.) + call addfld ('ZT_CLUBB', (/ 'lev' /), 'A', 'm', 'Thermodynamic Heights', sampled_on_subcycle=.true.) + call addfld ('ZM_CLUBB', (/ 'ilev' /), 'A', 'm', 'Momentum Heights', sampled_on_subcycle=.true.) + call addfld ('UM_CLUBB', (/ 'lev' /), 'A', 'm/s', 'Zonal Wind', sampled_on_subcycle=.true.) + call addfld ('VM_CLUBB', (/ 'lev' /), 'A', 'm/s', 'Meridional Wind', sampled_on_subcycle=.true.) + call addfld ('WM_ZT_CLUBB', (/ 'lev' /), 'A', 'm/s', 'Vertical Velocity', sampled_on_subcycle=.true.) + call addfld ('PBLH', horiz_only, 'A', 'm', 'PBL height', sampled_on_subcycle=.true.) + call addfld ('CLDST', (/ 'lev' /), 'A', 'fraction', 'Stratus cloud fraction', sampled_on_subcycle=.true.) + call addfld ('ZMDLF', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from ZM convection', sampled_on_subcycle=.true.) + call addfld ('TTENDICE', (/ 'lev' /), 'A', 'K/s', 'T tendency from Ice Saturation Adjustment', sampled_on_subcycle=.true.) + call addfld ('QVTENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Q tendency from Ice Saturation Adjustment', sampled_on_subcycle=.true.) + call addfld ('QITENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency from Ice Saturation Adjustment', sampled_on_subcycle=.true.) + call addfld ('NITENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'NUMICE tendency from Ice Saturation Adjustment', sampled_on_subcycle=.true.) + + + call addfld ('QCTENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency from Ice Saturation Adjustment', sampled_on_subcycle=.true.) + call addfld ('NCTENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'NUMICE tendency from Ice Saturation Adjustment', sampled_on_subcycle=.true.) + call addfld ('FQTENDICE', (/ 'lev' /), 'A', 'fraction', 'Frequency of Ice Saturation Adjustment', sampled_on_subcycle=.true.) + + call addfld ('DPDLFLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from deep convection', sampled_on_subcycle=.true.) + call addfld ('DPDLFICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained ice from deep convection', sampled_on_subcycle=.true.) + call addfld ('DPDLFT', (/ 'lev' /), 'A', 'K/s', 'T-tendency due to deep convective detrainment', sampled_on_subcycle=.true.) + call addfld ('RELVAR', (/ 'lev' /), 'A', '-', 'Relative cloud water variance', sampled_on_subcycle=.true.) + call addfld ('CLUBB_GRID_SIZE', horiz_only, 'A', 'm', 'Horizontal grid box size seen by CLUBB', sampled_on_subcycle=.true.) + + + call addfld ('ZMDLFI', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained ice water from ZM convection', sampled_on_subcycle=.true.) + call addfld ('CONCLD', (/ 'lev' /), 'A', 'fraction', 'Convective cloud cover', sampled_on_subcycle=.true.) + call addfld ('CMELIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of cond-evap of liq within the cloud', sampled_on_subcycle=.true.) + call addfld ('DETNLIQTND', (/ 'lev' /), 'A', '1/kg/s', 'CLDNUM tendency in detrained water', sampled_on_subcycle=.true.) + + call addfld ('QSATFAC', (/ 'lev' /), 'A', '-', 'Subgrid cloud water saturation scaling factor', sampled_on_subcycle=.true.) + call addfld ('KVH_CLUBB', (/ 'ilev' /), 'A', 'm2/s', 'CLUBB vertical diffusivity of heat/moisture on interface levels', sampled_on_subcycle=.true.) + call addfld ('ELEAK_CLUBB', horiz_only, 'A', 'W/m2', 'CLUBB energy leak', sampled_on_subcycle=.true.) + call addfld ('TFIX_CLUBB', horiz_only, 'A', 'K', 'Temperature increment to conserve energy', sampled_on_subcycle=.true.) ! ---------------------------------------------------------------------------- ! ! Below are for detailed analysis of EDMF Scheme ! ! ---------------------------------------------------------------------------- ! if (do_clubb_mf) then - call addfld ( 'edmf_DRY_A' , (/ 'ilev' /), 'A', 'fraction', 'Dry updraft area fraction (EDMF)' ) - call addfld ( 'edmf_MOIST_A' , (/ 'ilev' /), 'A', 'fraction', 'Moist updraft area fraction (EDMF)' ) - call addfld ( 'edmf_DRY_W' , (/ 'ilev' /), 'A', 'm/s' , 'Dry updraft vertical velocity (EDMF)' ) - call addfld ( 'edmf_MOIST_W' , (/ 'ilev' /), 'A', 'm/s' , 'Moist updraft vertical velocity (EDMF)' ) - call addfld ( 'edmf_DRY_QT' , (/ 'ilev' /), 'A', 'kg/kg' , 'Dry updraft total water mixing ratio (EDMF)' ) - call addfld ( 'edmf_MOIST_QT' , (/ 'ilev' /), 'A', 'kg/kg' , 'Moist updraft total water mixing ratio (EDMF)' ) - call addfld ( 'edmf_DRY_THL' , (/ 'ilev' /), 'A', 'K' , 'Dry updraft liquid-ice potential temperature (EDMF)' ) - call addfld ( 'edmf_MOIST_THL', (/ 'ilev' /), 'A', 'K' , 'Moist updraft liquid-ice potential temperature (EDMF)' ) - call addfld ( 'edmf_DRY_U' , (/ 'ilev' /), 'A', 'm/s' , 'Dry updraft zonal velocity (EDMF)' ) - call addfld ( 'edmf_MOIST_U' , (/ 'ilev' /), 'A', 'm/s' , 'Moist updraft zonal velocity (EDMF)' ) - call addfld ( 'edmf_DRY_V' , (/ 'ilev' /), 'A', 'm/s' , 'Dry updraft meridional velocity (EDMF)' ) - call addfld ( 'edmf_MOIST_V' , (/ 'ilev' /), 'A', 'm/s' , 'Moist updraft meridional velocity (EDMF)' ) - call addfld ( 'edmf_MOIST_QC' , (/ 'ilev' /), 'A', 'kg/kg' , 'Moist updraft condensate mixing ratio (EDMF)' ) - call addfld ( 'edmf_S_AE' , (/ 'ilev' /), 'A', 'fraction', '1 minus sum of a_i*w_i (EDMF)' ) - call addfld ( 'edmf_S_AW' , (/ 'ilev' /), 'A', 'm/s' , 'Sum of a_i*w_i (EDMF)' ) - call addfld ( 'edmf_S_AWTHL' , (/ 'ilev' /), 'A', 'K m/s' , 'Sum of a_i*w_i*thl_i (EDMF)' ) - call addfld ( 'edmf_S_AWQT' , (/ 'ilev' /), 'A', 'kgm/kgs' , 'Sum of a_i*w_i*q_ti (EDMF)' ) - call addfld ( 'edmf_S_AWU' , (/ 'ilev' /), 'A', 'm2/s2' , 'Sum of a_i*w_i*u_i (EDMF)' ) - call addfld ( 'edmf_S_AWV' , (/ 'ilev' /), 'A', 'm2/s2' , 'Sum of a_i*w_i*v_i (EDMF)' ) - call addfld ( 'edmf_thlflx' , (/ 'ilev' /), 'A', 'W/m2' , 'thl flux (EDMF)' ) - call addfld ( 'edmf_qtflx' , (/ 'ilev' /), 'A', 'W/m2' , 'qt flux (EDMF)' ) + call addfld ( 'edmf_DRY_A' , (/ 'ilev' /), 'A', 'fraction', 'Dry updraft area fraction (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_MOIST_A' , (/ 'ilev' /), 'A', 'fraction', 'Moist updraft area fraction (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_DRY_W' , (/ 'ilev' /), 'A', 'm/s' , 'Dry updraft vertical velocity (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_MOIST_W' , (/ 'ilev' /), 'A', 'm/s' , 'Moist updraft vertical velocity (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_DRY_QT' , (/ 'ilev' /), 'A', 'kg/kg' , 'Dry updraft total water mixing ratio (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_MOIST_QT' , (/ 'ilev' /), 'A', 'kg/kg' , 'Moist updraft total water mixing ratio (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_DRY_THL' , (/ 'ilev' /), 'A', 'K' , 'Dry updraft liquid-ice potential temperature (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_MOIST_THL', (/ 'ilev' /), 'A', 'K' , 'Moist updraft liquid-ice potential temperature (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_DRY_U' , (/ 'ilev' /), 'A', 'm/s' , 'Dry updraft zonal velocity (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_MOIST_U' , (/ 'ilev' /), 'A', 'm/s' , 'Moist updraft zonal velocity (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_DRY_V' , (/ 'ilev' /), 'A', 'm/s' , 'Dry updraft meridional velocity (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_MOIST_V' , (/ 'ilev' /), 'A', 'm/s' , 'Moist updraft meridional velocity (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_MOIST_QC' , (/ 'ilev' /), 'A', 'kg/kg' , 'Moist updraft condensate mixing ratio (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_S_AE' , (/ 'ilev' /), 'A', 'fraction', '1 minus sum of a_i*w_i (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_S_AW' , (/ 'ilev' /), 'A', 'm/s' , 'Sum of a_i*w_i (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_S_AWTHL' , (/ 'ilev' /), 'A', 'K m/s' , 'Sum of a_i*w_i*thl_i (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_S_AWQT' , (/ 'ilev' /), 'A', 'kgm/kgs' , 'Sum of a_i*w_i*q_ti (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_S_AWU' , (/ 'ilev' /), 'A', 'm2/s2' , 'Sum of a_i*w_i*u_i (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_S_AWV' , (/ 'ilev' /), 'A', 'm2/s2' , 'Sum of a_i*w_i*v_i (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_thlflx' , (/ 'ilev' /), 'A', 'W/m2' , 'thl flux (EDMF)', sampled_on_subcycle=.true.) + call addfld ( 'edmf_qtflx' , (/ 'ilev' /), 'A', 'W/m2' , 'qt flux (EDMF)', sampled_on_subcycle=.true.) end if if ( trim(subcol_scheme) /= 'SILHS' ) then diff --git a/src/physics/cam/macrop_driver.F90 b/src/physics/cam/macrop_driver.F90 index 92d52fff8c..d381387bfc 100644 --- a/src/physics/cam/macrop_driver.F90 +++ b/src/physics/cam/macrop_driver.F90 @@ -237,53 +237,53 @@ subroutine macrop_driver_init(pbuf2d) use_shfrc = .false. endif - call addfld ('DPDLFLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from deep convection' ) - call addfld ('DPDLFICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained ice from deep convection' ) - call addfld ('SHDLFLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from shallow convection' ) - call addfld ('SHDLFICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained ice from shallow convection' ) - call addfld ('DPDLFT', (/ 'lev' /), 'A', 'K/s', 'T-tendency due to deep convective detrainment' ) - call addfld ('SHDLFT', (/ 'lev' /), 'A', 'K/s', 'T-tendency due to shallow convective detrainment' ) + call addfld ('DPDLFLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from deep convection', sampled_on_subcycle=.true.) + call addfld ('DPDLFICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained ice from deep convection', sampled_on_subcycle=.true.) + call addfld ('SHDLFLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from shallow convection', sampled_on_subcycle=.true.) + call addfld ('SHDLFICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained ice from shallow convection', sampled_on_subcycle=.true.) + call addfld ('DPDLFT', (/ 'lev' /), 'A', 'K/s', 'T-tendency due to deep convective detrainment', sampled_on_subcycle=.true.) + call addfld ('SHDLFT', (/ 'lev' /), 'A', 'K/s', 'T-tendency due to shallow convective detrainment', sampled_on_subcycle=.true.) - call addfld ('ZMDLF', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from ZM convection' ) + call addfld ('ZMDLF', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from ZM convection', sampled_on_subcycle=.true.) - call addfld ('MACPDT', (/ 'lev' /), 'A', 'W/kg', 'Heating tendency - Revised macrophysics' ) - call addfld ('MACPDQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Q tendency - Revised macrophysics' ) - call addfld ('MACPDLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDLIQ tendency - Revised macrophysics' ) - call addfld ('MACPDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency - Revised macrophysics' ) + call addfld ('MACPDT', (/ 'lev' /), 'A', 'W/kg', 'Heating tendency - Revised macrophysics', sampled_on_subcycle=.true.) + call addfld ('MACPDQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Q tendency - Revised macrophysics', sampled_on_subcycle=.true.) + call addfld ('MACPDLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDLIQ tendency - Revised macrophysics', sampled_on_subcycle=.true.) + call addfld ('MACPDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency - Revised macrophysics', sampled_on_subcycle=.true.) call addfld ('CLDVAPADJ', (/ 'lev' /), 'A', 'kg/kg/s', & - 'Q tendency associated with liq/ice adjustment - Revised macrophysics' ) - call addfld ('CLDLIQADJ', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDLIQ adjustment tendency - Revised macrophysics' ) - call addfld ('CLDICEADJ', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE adjustment tendency - Revised macrophysics' ) + 'Q tendency associated with liq/ice adjustment - Revised macrophysics', sampled_on_subcycle=.true.) + call addfld ('CLDLIQADJ', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDLIQ adjustment tendency - Revised macrophysics', sampled_on_subcycle=.true.) + call addfld ('CLDICEADJ', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE adjustment tendency - Revised macrophysics', sampled_on_subcycle=.true.) call addfld ('CLDLIQDET', (/ 'lev' /), 'A', 'kg/kg/s', & - 'Detrainment of conv cld liq into envrionment - Revised macrophysics' ) + 'Detrainment of conv cld liq into envrionment - Revised macrophysics', sampled_on_subcycle=.true.) call addfld ('CLDICEDET', (/ 'lev' /), 'A', 'kg/kg/s', & - 'Detrainment of conv cld ice into envrionment - Revised macrophysics' ) - call addfld ('CLDLIQLIM', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDLIQ limiting tendency - Revised macrophysics' ) - call addfld ('CLDICELIM', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE limiting tendency - Revised macrophysics' ) + 'Detrainment of conv cld ice into envrionment - Revised macrophysics', sampled_on_subcycle=.true.) + call addfld ('CLDLIQLIM', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDLIQ limiting tendency - Revised macrophysics', sampled_on_subcycle=.true.) + call addfld ('CLDICELIM', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE limiting tendency - Revised macrophysics', sampled_on_subcycle=.true.) - call addfld ('AST', (/ 'lev' /), 'A', '1', 'Stratus cloud fraction' ) - call addfld ('LIQCLDF', (/ 'lev' /), 'A', '1', 'Stratus Liquid cloud fraction' ) - call addfld ('ICECLDF', (/ 'lev' /), 'A', '1', 'Stratus ICE cloud fraction' ) + call addfld ('AST', (/ 'lev' /), 'A', '1', 'Stratus cloud fraction', sampled_on_subcycle=.true.) + call addfld ('LIQCLDF', (/ 'lev' /), 'A', '1', 'Stratus Liquid cloud fraction', sampled_on_subcycle=.true.) + call addfld ('ICECLDF', (/ 'lev' /), 'A', '1', 'Stratus ICE cloud fraction', sampled_on_subcycle=.true.) - call addfld ('CLDST', (/ 'lev' /), 'A', 'fraction', 'Stratus cloud fraction' ) - call addfld ('CONCLD', (/ 'lev' /), 'A', 'fraction', 'Convective cloud cover' ) + call addfld ('CLDST', (/ 'lev' /), 'A', 'fraction', 'Stratus cloud fraction', sampled_on_subcycle=.true.) + call addfld ('CONCLD', (/ 'lev' /), 'A', 'fraction', 'Convective cloud cover', sampled_on_subcycle=.true.) - call addfld ('CLR_LIQ', (/ 'lev' /), 'A', 'fraction', 'Clear sky fraction for liquid stratus' ) - call addfld ('CLR_ICE', (/ 'lev' /), 'A', 'fraction', 'Clear sky fraction for ice stratus' ) + call addfld ('CLR_LIQ', (/ 'lev' /), 'A', 'fraction', 'Clear sky fraction for liquid stratus', sampled_on_subcycle=.true.) + call addfld ('CLR_ICE', (/ 'lev' /), 'A', 'fraction', 'Clear sky fraction for ice stratus', sampled_on_subcycle=.true.) - call addfld ('CLDLIQSTR', (/ 'lev' /), 'A', 'kg/kg', 'Stratiform CLDLIQ' ) - call addfld ('CLDICESTR', (/ 'lev' /), 'A', 'kg/kg', 'Stratiform CLDICE' ) - call addfld ('CLDLIQCON', (/ 'lev' /), 'A', 'kg/kg', 'Convective CLDLIQ' ) - call addfld ('CLDICECON', (/ 'lev' /), 'A', 'kg/kg', 'Convective CLDICE' ) + call addfld ('CLDLIQSTR', (/ 'lev' /), 'A', 'kg/kg', 'Stratiform CLDLIQ', sampled_on_subcycle=.true.) + call addfld ('CLDICESTR', (/ 'lev' /), 'A', 'kg/kg', 'Stratiform CLDICE', sampled_on_subcycle=.true.) + call addfld ('CLDLIQCON', (/ 'lev' /), 'A', 'kg/kg', 'Convective CLDLIQ', sampled_on_subcycle=.true.) + call addfld ('CLDICECON', (/ 'lev' /), 'A', 'kg/kg', 'Convective CLDICE', sampled_on_subcycle=.true.) - call addfld ('CLDSICE', (/ 'lev' /), 'A', 'kg/kg', 'CloudSat equivalent ice mass mixing ratio' ) - call addfld ('CMELIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of cond-evap of liq within the cloud' ) + call addfld ('CLDSICE', (/ 'lev' /), 'A', 'kg/kg', 'CloudSat equivalent ice mass mixing ratio', sampled_on_subcycle=.true.) + call addfld ('CMELIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of cond-evap of liq within the cloud', sampled_on_subcycle=.true.) - call addfld ('TTENDICE', (/ 'lev' /), 'A', 'K/s', 'T tendency from Ice Saturation Adjustment' ) - call addfld ('QVTENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Q tendency from Ice Saturation Adjustment' ) - call addfld ('QITENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency from Ice Saturation Adjustment' ) - call addfld ('NITENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'NUMICE tendency from Ice Saturation Adjustment' ) + call addfld ('TTENDICE', (/ 'lev' /), 'A', 'K/s', 'T tendency from Ice Saturation Adjustment', sampled_on_subcycle=.true.) + call addfld ('QVTENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Q tendency from Ice Saturation Adjustment', sampled_on_subcycle=.true.) + call addfld ('QITENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency from Ice Saturation Adjustment', sampled_on_subcycle=.true.) + call addfld ('NITENDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'NUMICE tendency from Ice Saturation Adjustment', sampled_on_subcycle=.true.) if ( history_budget ) then call add_default ('DPDLFLIQ ', history_budget_histfile_num, ' ') diff --git a/src/physics/cam/micro_pumas_cam.F90 b/src/physics/cam/micro_pumas_cam.F90 index a0c66eb7f1..d5f98c9813 100644 --- a/src/physics/cam/micro_pumas_cam.F90 +++ b/src/physics/cam/micro_pumas_cam.F90 @@ -925,251 +925,251 @@ subroutine micro_pumas_cam_init(pbuf2d) call cnst_get_ind(cnst_names(m), mm) if ( any(mm == (/ ixcldliq, ixcldice, ixrain, ixsnow, ixgraupel /)) ) then ! mass mixing ratios - call addfld(cnst_name(mm), (/ 'lev' /), 'A', 'kg/kg', cnst_longname(mm) ) - call addfld(sflxnam(mm), horiz_only, 'A', 'kg/m2/s', trim(cnst_name(mm))//' surface flux') + call addfld(cnst_name(mm), (/ 'lev' /), 'A', 'kg/kg', cnst_longname(mm), sampled_on_subcycle=.true.) + call addfld(sflxnam(mm), horiz_only, 'A', 'kg/m2/s', trim(cnst_name(mm))//' surface flux', sampled_on_subcycle=.true.) else if ( any(mm == (/ ixnumliq, ixnumice, ixnumrain, ixnumsnow, ixnumgraupel /)) ) then ! number concentrations - call addfld(cnst_name(mm), (/ 'lev' /), 'A', '1/kg', cnst_longname(mm) ) - call addfld(sflxnam(mm), horiz_only, 'A', '1/m2/s', trim(cnst_name(mm))//' surface flux') + call addfld(cnst_name(mm), (/ 'lev' /), 'A', '1/kg', cnst_longname(mm), sampled_on_subcycle=.true.) + call addfld(sflxnam(mm), horiz_only, 'A', '1/m2/s', trim(cnst_name(mm))//' surface flux', sampled_on_subcycle=.true.) else call endrun( "micro_pumas_cam_init: & &Could not call addfld for constituent with unknown units.") endif end do - call addfld(apcnst(ixcldliq), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldliq))//' after physics' ) - call addfld(apcnst(ixcldice), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldice))//' after physics' ) - call addfld(bpcnst(ixcldliq), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldliq))//' before physics' ) - call addfld(bpcnst(ixcldice), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldice))//' before physics' ) + call addfld(apcnst(ixcldliq), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldliq))//' after physics', sampled_on_subcycle=.true.) + call addfld(apcnst(ixcldice), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldice))//' after physics', sampled_on_subcycle=.true.) + call addfld(bpcnst(ixcldliq), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldliq))//' before physics', sampled_on_subcycle=.true.) + call addfld(bpcnst(ixcldice), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldice))//' before physics', sampled_on_subcycle=.true.) if (micro_mg_version > 1) then - call addfld(apcnst(ixrain), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixrain))//' after physics' ) - call addfld(apcnst(ixsnow), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixsnow))//' after physics' ) - call addfld(bpcnst(ixrain), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixrain))//' before physics' ) - call addfld(bpcnst(ixsnow), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixsnow))//' before physics' ) + call addfld(apcnst(ixrain), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixrain))//' after physics', sampled_on_subcycle=.true.) + call addfld(apcnst(ixsnow), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixsnow))//' after physics', sampled_on_subcycle=.true.) + call addfld(bpcnst(ixrain), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixrain))//' before physics', sampled_on_subcycle=.true.) + call addfld(bpcnst(ixsnow), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixsnow))//' before physics', sampled_on_subcycle=.true.) end if if (micro_mg_version > 2) then - call addfld(apcnst(ixgraupel), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixgraupel))//' after physics' ) - call addfld(bpcnst(ixgraupel), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixgraupel))//' before physics' ) + call addfld(apcnst(ixgraupel), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixgraupel))//' after physics', sampled_on_subcycle=.true.) + call addfld(bpcnst(ixgraupel), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixgraupel))//' before physics', sampled_on_subcycle=.true.) end if - call addfld ('CME', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of cond-evap within the cloud' ) - call addfld ('PRODPREC', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of conversion of condensate to precip' ) - call addfld ('EVAPPREC', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling precip' ) - call addfld ('EVAPSNOW', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling snow' ) - call addfld ('HPROGCLD', (/ 'lev' /), 'A', 'W/kg' , 'Heating from prognostic clouds' ) - call addfld ('FICE', (/ 'lev' /), 'A', 'fraction', 'Fractional ice content within cloud' ) - call addfld ('CLDFSNOW', (/ 'lev' /), 'A', '1', 'Cloud fraction adjusted for snow' ) - call addfld ('ICWMRST', (/ 'lev' /), 'A', 'kg/kg', 'Prognostic in-stratus water mixing ratio' ) - call addfld ('ICIMRST', (/ 'lev' /), 'A', 'kg/kg', 'Prognostic in-stratus ice mixing ratio' ) + call addfld ('CME', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of cond-evap within the cloud', sampled_on_subcycle=.true.) + call addfld ('PRODPREC', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of conversion of condensate to precip', sampled_on_subcycle=.true.) + call addfld ('EVAPPREC', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling precip', sampled_on_subcycle=.true.) + call addfld ('EVAPSNOW', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling snow', sampled_on_subcycle=.true.) + call addfld ('HPROGCLD', (/ 'lev' /), 'A', 'W/kg' , 'Heating from prognostic clouds', sampled_on_subcycle=.true.) + call addfld ('FICE', (/ 'lev' /), 'A', 'fraction', 'Fractional ice content within cloud', sampled_on_subcycle=.true.) + call addfld ('CLDFSNOW', (/ 'lev' /), 'A', '1', 'Cloud fraction adjusted for snow', sampled_on_subcycle=.true.) + call addfld ('ICWMRST', (/ 'lev' /), 'A', 'kg/kg', 'Prognostic in-stratus water mixing ratio', sampled_on_subcycle=.true.) + call addfld ('ICIMRST', (/ 'lev' /), 'A', 'kg/kg', 'Prognostic in-stratus ice mixing ratio', sampled_on_subcycle=.true.) ! MG microphysics diagnostics - call addfld ('QCSEVAP', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling cloud water' ) - call addfld ('QISEVAP', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of sublimation of falling cloud ice' ) - call addfld ('QVRES', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of residual condensation term' ) - call addfld ('CMEIOUT', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of deposition/sublimation of cloud ice' ) - call addfld ('VTRMC', (/ 'lev' /), 'A', 'm/s', 'Mass-weighted cloud water fallspeed' ) - call addfld ('VTRMI', (/ 'lev' /), 'A', 'm/s', 'Mass-weighted cloud ice fallspeed' ) - call addfld ('QCSEDTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud water mixing ratio tendency from sedimentation' ) - call addfld ('QISEDTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud ice mixing ratio tendency from sedimentation' ) - call addfld ('PRAO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud water by rain' ) - call addfld ('PRCO', (/ 'lev' /), 'A', 'kg/kg/s', 'Autoconversion of cloud water' ) - call addfld ('MNUCCCO', (/ 'lev' /), 'A', 'kg/kg/s', 'Immersion freezing of cloud water' ) - call addfld ('MNUCCTO', (/ 'lev' /), 'A', 'kg/kg/s', 'Contact freezing of cloud water' ) - call addfld ('MNUCCDO', (/ 'lev' /), 'A', 'kg/kg/s', 'Homogeneous and heterogeneous nucleation from vapor' ) - call addfld ('MNUCCDOhet', (/ 'lev' /), 'A', 'kg/kg/s', 'Heterogeneous nucleation from vapor' ) - call addfld ('MSACWIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water from rime-splintering' ) - call addfld ('PSACWSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud water by snow' ) - call addfld ('BERGSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water to snow from bergeron' ) - call addfld ('BERGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water to cloud ice from bergeron' ) - call addfld ('MELTO', (/ 'lev' /), 'A', 'kg/kg/s', 'Melting of cloud ice' ) - call addfld ('MELTSTOT', (/ 'lev' /), 'A', 'kg/kg/s', 'Melting of snow' ) - call addfld ('MNUDEPO', (/ 'lev' /), 'A', 'kg/kg/s', 'Deposition Nucleation' ) - call addfld ('HOMOO', (/ 'lev' /), 'A', 'kg/kg/s', 'Homogeneous freezing of cloud water' ) - call addfld ('QCRESO', (/ 'lev' /), 'A', 'kg/kg/s', 'Residual condensation term for cloud water' ) - call addfld ('PRCIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Autoconversion of cloud ice to snow' ) - call addfld ('PRAIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud ice to snow' ) - call addfld ('QIRESO', (/ 'lev' /), 'A', 'kg/kg/s', 'Residual deposition term for cloud ice' ) - call addfld ('MNUCCRO', (/ 'lev' /), 'A', 'kg/kg/s', 'Heterogeneous freezing of rain to snow' ) - call addfld ('MNUCCRIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Heterogeneous freezing of rain to ice' ) - call addfld ('PRACSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of rain by snow' ) - call addfld ('MELTSDT', (/ 'lev' /), 'A', 'W/kg', 'Latent heating rate due to melting of snow' ) - call addfld ('FRZRDT', (/ 'lev' /), 'A', 'W/kg', 'Latent heating rate due to homogeneous freezing of rain' ) + call addfld ('QCSEVAP', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling cloud water', sampled_on_subcycle=.true.) + call addfld ('QISEVAP', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of sublimation of falling cloud ice', sampled_on_subcycle=.true.) + call addfld ('QVRES', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of residual condensation term', sampled_on_subcycle=.true.) + call addfld ('CMEIOUT', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of deposition/sublimation of cloud ice',sampled_on_subcycle=.true.) + call addfld ('VTRMC', (/ 'lev' /), 'A', 'm/s', 'Mass-weighted cloud water fallspeed', sampled_on_subcycle=.true.) + call addfld ('VTRMI', (/ 'lev' /), 'A', 'm/s', 'Mass-weighted cloud ice fallspeed', sampled_on_subcycle=.true.) + call addfld ('QCSEDTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud water mixing ratio tendency from sedimentation', sampled_on_subcycle=.true.) + call addfld ('QISEDTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud ice mixing ratio tendency from sedimentation', sampled_on_subcycle=.true.) + call addfld ('PRAO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud water by rain', sampled_on_subcycle=.true.) + call addfld ('PRCO', (/ 'lev' /), 'A', 'kg/kg/s', 'Autoconversion of cloud water', sampled_on_subcycle=.true.) + call addfld ('MNUCCCO', (/ 'lev' /), 'A', 'kg/kg/s', 'Immersion freezing of cloud water', sampled_on_subcycle=.true.) + call addfld ('MNUCCTO', (/ 'lev' /), 'A', 'kg/kg/s', 'Contact freezing of cloud water', sampled_on_subcycle=.true.) + call addfld ('MNUCCDO', (/ 'lev' /), 'A', 'kg/kg/s', 'Homogeneous and heterogeneous nucleation from vapor', sampled_on_subcycle=.true.) + call addfld ('MNUCCDOhet', (/ 'lev' /), 'A', 'kg/kg/s', 'Heterogeneous nucleation from vapor', sampled_on_subcycle=.true.) + call addfld ('MSACWIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water from rime-splintering', sampled_on_subcycle=.true.) + call addfld ('PSACWSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud water by snow', sampled_on_subcycle=.true.) + call addfld ('BERGSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water to snow from bergeron', sampled_on_subcycle=.true.) + call addfld ('BERGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water to cloud ice from bergeron', sampled_on_subcycle=.true.) + call addfld ('MELTO', (/ 'lev' /), 'A', 'kg/kg/s', 'Melting of cloud ice', sampled_on_subcycle=.true.) + call addfld ('MELTSTOT', (/ 'lev' /), 'A', 'kg/kg/s', 'Melting of snow', sampled_on_subcycle=.true.) + call addfld ('MNUDEPO', (/ 'lev' /), 'A', 'kg/kg/s', 'Deposition Nucleation', sampled_on_subcycle=.true.) + call addfld ('HOMOO', (/ 'lev' /), 'A', 'kg/kg/s', 'Homogeneous freezing of cloud water', sampled_on_subcycle=.true.) + call addfld ('QCRESO', (/ 'lev' /), 'A', 'kg/kg/s', 'Residual condensation term for cloud water', sampled_on_subcycle=.true.) + call addfld ('PRCIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Autoconversion of cloud ice to snow', sampled_on_subcycle=.true.) + call addfld ('PRAIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud ice to snow', sampled_on_subcycle=.true.) + call addfld ('QIRESO', (/ 'lev' /), 'A', 'kg/kg/s', 'Residual deposition term for cloud ice', sampled_on_subcycle=.true.) + call addfld ('MNUCCRO', (/ 'lev' /), 'A', 'kg/kg/s', 'Heterogeneous freezing of rain to snow', sampled_on_subcycle=.true.) + call addfld ('MNUCCRIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Heterogeneous freezing of rain to ice', sampled_on_subcycle=.true.) + call addfld ('PRACSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of rain by snow', sampled_on_subcycle=.true.) + call addfld ('MELTSDT', (/ 'lev' /), 'A', 'W/kg', 'Latent heating rate due to melting of snow', sampled_on_subcycle=.true.) + call addfld ('FRZRDT', (/ 'lev' /), 'A', 'W/kg', 'Latent heating rate due to homogeneous freezing of rain', sampled_on_subcycle=.true.) if (micro_mg_version > 1) then - call addfld ('QRSEDTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Rain mixing ratio tendency from sedimentation' ) - call addfld ('QSSEDTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Snow mixing ratio tendency from sedimentation' ) + call addfld ('QRSEDTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Rain mixing ratio tendency from sedimentation', sampled_on_subcycle=.true.) + call addfld ('QSSEDTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Snow mixing ratio tendency from sedimentation', sampled_on_subcycle=.true.) end if if (micro_mg_version > 2) then - call addfld ('PSACRO', (/ 'lev' /), 'A', 'kg/kg/s', 'Collisions between rain & snow (Graupel collecting snow)') - call addfld ('PRACGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change in q collection rain by graupel' ) - call addfld ('PSACWGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change in q collection droplets by graupel' ) - call addfld ('PGSACWO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q conversion to graupel due to collection droplets by snow') - call addfld ('PGRACSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q conversion to graupel due to collection rain by snow') - call addfld ('PRDGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Deposition of graupel') - call addfld ('QMULTGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q change due to ice mult droplets/graupel') - call addfld ('QMULTRGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q change due to ice mult rain/graupel') - call addfld ('QGSEDTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Graupel/Hail mixing ratio tendency from sedimentation') - call addfld ('NPRACGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change N collection rain by graupel') - call addfld ('NSCNGO', (/'lev'/),'A','kg/kg/s','Change N conversion to graupel due to collection droplets by snow') - call addfld ('NGRACSO',(/'lev'/),'A','kg/kg/s','Change N conversion to graupel due to collection rain by snow') - call addfld ('NMULTGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice mult due to acc droplets by graupel ') - call addfld ('NMULTRGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice mult due to acc rain by graupel') - call addfld ('NPSACWGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change N collection droplets by graupel') - call addfld ('CLDFGRAU', (/ 'lev' /), 'A', '1', 'Cloud fraction adjusted for graupel' ) - call addfld ('MELTGTOT', (/ 'lev' /), 'A', 'kg/kg/s', 'Melting of graupel' ) + call addfld ('PSACRO', (/ 'lev' /), 'A', 'kg/kg/s', 'Collisions between rain & snow (Graupel collecting snow)', sampled_on_subcycle=.true.) + call addfld ('PRACGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change in q collection rain by graupel', sampled_on_subcycle=.true.) + call addfld ('PSACWGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change in q collection droplets by graupel', sampled_on_subcycle=.true.) + call addfld ('PGSACWO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q conversion to graupel due to collection droplets by snow', sampled_on_subcycle=.true.) + call addfld ('PGRACSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q conversion to graupel due to collection rain by snow', sampled_on_subcycle=.true.) + call addfld ('PRDGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Deposition of graupel', sampled_on_subcycle=.true.) + call addfld ('QMULTGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q change due to ice mult droplets/graupel', sampled_on_subcycle=.true.) + call addfld ('QMULTRGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q change due to ice mult rain/graupel', sampled_on_subcycle=.true.) + call addfld ('QGSEDTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Graupel/Hail mixing ratio tendency from sedimentation', sampled_on_subcycle=.true.) + call addfld ('NPRACGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change N collection rain by graupel', sampled_on_subcycle=.true.) + call addfld ('NSCNGO', (/'lev'/),'A','kg/kg/s','Change N conversion to graupel due to collection droplets by snow', sampled_on_subcycle=.true.) + call addfld ('NGRACSO',(/'lev'/),'A','kg/kg/s','Change N conversion to graupel due to collection rain by snow', sampled_on_subcycle=.true.) + call addfld ('NMULTGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice mult due to acc droplets by graupel', sampled_on_subcycle=.true.) + call addfld ('NMULTRGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice mult due to acc rain by graupel', sampled_on_subcycle=.true.) + call addfld ('NPSACWGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change N collection droplets by graupel', sampled_on_subcycle=.true.) + call addfld ('CLDFGRAU', (/ 'lev' /), 'A', '1', 'Cloud fraction adjusted for graupel', sampled_on_subcycle=.true.) + call addfld ('MELTGTOT', (/ 'lev' /), 'A', 'kg/kg/s', 'Melting of graupel', sampled_on_subcycle=.true.) end if - call addfld ('RBFRAC', horiz_only, 'A', 'Fraction', 'Fraction of sky covered by a potential rainbow' ) - call addfld ('RBFREQ', horiz_only, 'A', 'Frequency', 'Potential rainbow frequency' ) - call addfld( 'rbSZA', horiz_only, 'I', 'degrees', 'solar zenith angle' ) + call addfld ('RBFRAC', horiz_only, 'A', 'Fraction', 'Fraction of sky covered by a potential rainbow', sampled_on_subcycle=.true.) + call addfld ('RBFREQ', horiz_only, 'A', 'Frequency', 'Potential rainbow frequency', sampled_on_subcycle=.true.) + call addfld( 'rbSZA', horiz_only, 'I', 'degrees', 'solar zenith angle', sampled_on_subcycle=.true.) ! History variables for CAM5 microphysics - call addfld ('MPDT', (/ 'lev' /), 'A', 'W/kg', 'Heating tendency - Morrison microphysics' ) - call addfld ('MPDQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Q tendency - Morrison microphysics' ) - call addfld ('MPDLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDLIQ tendency - Morrison microphysics' ) - call addfld ('MPDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency - Morrison microphysics' ) - call addfld ('MPDNLIQ', (/ 'lev' /), 'A', '1/kg/s', 'NUMLIQ tendency - Morrison microphysics' ) - call addfld ('MPDNICE', (/ 'lev' /), 'A', '1/kg/s', 'NUMICE tendency - Morrison microphysics' ) - call addfld ('MPDW2V', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Vapor tendency - Morrison microphysics' ) - call addfld ('MPDW2I', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Ice tendency - Morrison microphysics' ) - call addfld ('MPDW2P', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Precip tendency - Morrison microphysics' ) - call addfld ('MPDI2V', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Vapor tendency - Morrison microphysics' ) - call addfld ('MPDI2W', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Water tendency - Morrison microphysics' ) - call addfld ('MPDI2P', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Precip tendency - Morrison microphysics' ) - call addfld ('ICWNC', (/ 'lev' /), 'A', 'm-3', 'Prognostic in-cloud water number conc' ) - call addfld ('ICINC', (/ 'lev' /), 'A', 'm-3', 'Prognostic in-cloud ice number conc' ) - call addfld ('EFFLIQ_IND', (/ 'lev' /), 'A','Micron', 'Prognostic droplet effective radius (indirect effect)' ) - call addfld ('CDNUMC', horiz_only, 'A', '1/m2', 'Vertically-integrated droplet concentration' ) + call addfld ('MPDT', (/ 'lev' /), 'A', 'W/kg', 'Heating tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Q tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDLIQ tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDNLIQ', (/ 'lev' /), 'A', '1/kg/s', 'NUMLIQ tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDNICE', (/ 'lev' /), 'A', '1/kg/s', 'NUMICE tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDW2V', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Vapor tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDW2I', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Ice tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDW2P', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Precip tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDI2V', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Vapor tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDI2W', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Water tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDI2P', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Precip tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('ICWNC', (/ 'lev' /), 'A', 'm-3', 'Prognostic in-cloud water number conc', sampled_on_subcycle=.true.) + call addfld ('ICINC', (/ 'lev' /), 'A', 'm-3', 'Prognostic in-cloud ice number conc', sampled_on_subcycle=.true.) + call addfld ('EFFLIQ_IND', (/ 'lev' /), 'A','Micron', 'Prognostic droplet effective radius (indirect effect)', sampled_on_subcycle=.true.) + call addfld ('CDNUMC', horiz_only, 'A', '1/m2', 'Vertically-integrated droplet concentration', sampled_on_subcycle=.true.) call addfld ('MPICLWPI', horiz_only, 'A', 'kg/m2', 'Vertically-integrated & - &in-cloud Initial Liquid WP (Before Micro)' ) + &in-cloud Initial Liquid WP (Before Micro)', sampled_on_subcycle=.true.) call addfld ('MPICIWPI', horiz_only, 'A', 'kg/m2', 'Vertically-integrated & - &in-cloud Initial Ice WP (Before Micro)' ) + &in-cloud Initial Ice WP (Before Micro)', sampled_on_subcycle=.true.) ! This is provided as an example on how to write out subcolumn output ! NOTE -- only 'I' should be used for sub-column fields as subc-columns could shift from time-step to time-step if (use_subcol_microp) then call addfld('FICE_SCOL', (/'psubcols','lev '/), 'I', 'fraction', & - 'Sub-column fractional ice content within cloud', flag_xyfill=.true., fill_value=1.e30_r8) + 'Sub-column fractional ice content within cloud', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('MPDICE_SCOL', (/'psubcols','lev '/), 'I', 'kg/kg/s', & - 'Sub-column CLDICE tendency - Morrison microphysics', flag_xyfill=.true., fill_value=1.e30_r8) + 'Sub-column CLDICE tendency - Morrison microphysics', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('MPDLIQ_SCOL', (/'psubcols','lev '/), 'I', 'kg/kg/s', & - 'Sub-column CLDLIQ tendency - Morrison microphysics', flag_xyfill=.true., fill_value=1.e30_r8) + 'Sub-column CLDLIQ tendency - Morrison microphysics', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) end if ! This is only if the coldpoint temperatures are being adjusted. ! NOTE: Some fields related to these and output later are added in tropopause.F90. if (micro_mg_adjust_cpt) then - call addfld ('TROPF_TADJ', (/ 'lev' /), 'A', 'K', 'Temperatures after cold point adjustment' ) - call addfld ('TROPF_RHADJ', (/ 'lev' /), 'A', 'K', 'Relative Hunidity after cold point adjustment' ) - call addfld ('TROPF_CDT', horiz_only, 'A', 'K', 'Cold point temperature adjustment' ) - call addfld ('TROPF_CDZ', horiz_only, 'A', 'm', 'Distance of coldpoint from coldest model level' ) + call addfld ('TROPF_TADJ', (/ 'lev' /), 'A', 'K', 'Temperatures after cold point adjustment', sampled_on_subcycle=.true.) + call addfld ('TROPF_RHADJ', (/ 'lev' /), 'A', 'K', 'Relative Hunidity after cold point adjustment', sampled_on_subcycle=.true.) + call addfld ('TROPF_CDT', horiz_only, 'A', 'K', 'Cold point temperature adjustment', sampled_on_subcycle=.true.) + call addfld ('TROPF_CDZ', horiz_only, 'A', 'm', 'Distance of coldpoint from coldest model level', sampled_on_subcycle=.true.) end if ! Averaging for cloud particle number and size - call addfld ('AWNC', (/ 'lev' /), 'A', 'm-3', 'Average cloud water number conc' ) - call addfld ('AWNI', (/ 'lev' /), 'A', 'm-3', 'Average cloud ice number conc' ) - call addfld ('AREL', (/ 'lev' /), 'A', 'Micron', 'Average droplet effective radius' ) - call addfld ('AREI', (/ 'lev' /), 'A', 'Micron', 'Average ice effective radius' ) + call addfld ('AWNC', (/ 'lev' /), 'A', 'm-3', 'Average cloud water number conc', sampled_on_subcycle=.true.) + call addfld ('AWNI', (/ 'lev' /), 'A', 'm-3', 'Average cloud ice number conc', sampled_on_subcycle=.true.) + call addfld ('AREL', (/ 'lev' /), 'A', 'Micron', 'Average droplet effective radius', sampled_on_subcycle=.true.) + call addfld ('AREI', (/ 'lev' /), 'A', 'Micron', 'Average ice effective radius', sampled_on_subcycle=.true.) ! Frequency arrays for above - call addfld ('FREQL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of liquid' ) - call addfld ('FREQI', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of ice' ) + call addfld ('FREQL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of liquid', sampled_on_subcycle=.true.) + call addfld ('FREQI', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of ice', sampled_on_subcycle=.true.) ! Average cloud top particle size and number (liq, ice) and frequency - call addfld ('ACTREL', horiz_only, 'A', 'Micron', 'Average Cloud Top droplet effective radius' ) - call addfld ('ACTREI', horiz_only, 'A', 'Micron', 'Average Cloud Top ice effective radius' ) - call addfld ('ACTNL', horiz_only, 'A', 'm-3', 'Average Cloud Top droplet number' ) - call addfld ('ACTNI', horiz_only, 'A', 'm-3', 'Average Cloud Top ice number' ) + call addfld ('ACTREL', horiz_only, 'A', 'Micron', 'Average Cloud Top droplet effective radius', sampled_on_subcycle=.true.) + call addfld ('ACTREI', horiz_only, 'A', 'Micron', 'Average Cloud Top ice effective radius', sampled_on_subcycle=.true.) + call addfld ('ACTNL', horiz_only, 'A', 'm-3', 'Average Cloud Top droplet number', sampled_on_subcycle=.true.) + call addfld ('ACTNI', horiz_only, 'A', 'm-3', 'Average Cloud Top ice number', sampled_on_subcycle=.true.) - call addfld ('FCTL', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top liquid' ) - call addfld ('FCTI', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top ice' ) + call addfld ('FCTL', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top liquid', sampled_on_subcycle=.true.) + call addfld ('FCTI', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top ice', sampled_on_subcycle=.true.) ! New frequency arrays for mixed phase and supercooled liquid (only and mixed) for (a) Cloud Top and (b) everywhere.. - call addfld ('FREQM', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of mixed phase' ) - call addfld ('FREQSL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of only supercooled liquid' ) - call addfld ('FREQSLM', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of super cooled liquid with ice' ) - call addfld ('FCTM', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top mixed phase' ) - call addfld ('FCTSL', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top only supercooled liquid' ) - call addfld ('FCTSLM', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top super cooled liquid with ice' ) - - call addfld ('LS_FLXPRC', (/ 'ilev' /), 'A', 'kg/m2/s', 'ls stratiform gbm interface rain+snow flux' ) - call addfld ('LS_FLXSNW', (/ 'ilev' /), 'A', 'kg/m2/s', 'ls stratiform gbm interface snow flux' ) - - call addfld ('REL', (/ 'lev' /), 'A', 'micron', 'MG REL stratiform cloud effective radius liquid' ) - call addfld ('REI', (/ 'lev' /), 'A', 'micron', 'MG REI stratiform cloud effective radius ice' ) - call addfld ('LS_REFFRAIN', (/ 'lev' /), 'A', 'micron', 'ls stratiform rain effective radius' ) - call addfld ('LS_REFFSNOW', (/ 'lev' /), 'A', 'micron', 'ls stratiform snow effective radius' ) - call addfld ('CV_REFFLIQ', (/ 'lev' /), 'A', 'micron', 'convective cloud liq effective radius' ) - call addfld ('CV_REFFICE', (/ 'lev' /), 'A', 'micron', 'convective cloud ice effective radius' ) - call addfld ('MG_SADICE', (/ 'lev' /), 'A', 'cm2/cm3', 'MG surface area density ice' ) - call addfld ('MG_SADSNOW', (/ 'lev' /), 'A', 'cm2/cm3', 'MG surface area density snow' ) + call addfld ('FREQM', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of mixed phase', sampled_on_subcycle=.true.) + call addfld ('FREQSL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of only supercooled liquid', sampled_on_subcycle=.true.) + call addfld ('FREQSLM', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of super cooled liquid with ice', sampled_on_subcycle=.true.) + call addfld ('FCTM', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top mixed phase', sampled_on_subcycle=.true.) + call addfld ('FCTSL', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top only supercooled liquid', sampled_on_subcycle=.true.) + call addfld ('FCTSLM', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top super cooled liquid with ice', sampled_on_subcycle=.true.) + + call addfld ('LS_FLXPRC', (/ 'ilev' /), 'A', 'kg/m2/s', 'ls stratiform gbm interface rain+snow flux', sampled_on_subcycle=.true.) + call addfld ('LS_FLXSNW', (/ 'ilev' /), 'A', 'kg/m2/s', 'ls stratiform gbm interface snow flux', sampled_on_subcycle=.true.) + + call addfld ('REL', (/ 'lev' /), 'A', 'micron', 'MG REL stratiform cloud effective radius liquid', sampled_on_subcycle=.true.) + call addfld ('REI', (/ 'lev' /), 'A', 'micron', 'MG REI stratiform cloud effective radius ice', sampled_on_subcycle=.true.) + call addfld ('LS_REFFRAIN', (/ 'lev' /), 'A', 'micron', 'ls stratiform rain effective radius', sampled_on_subcycle=.true.) + call addfld ('LS_REFFSNOW', (/ 'lev' /), 'A', 'micron', 'ls stratiform snow effective radius', sampled_on_subcycle=.true.) + call addfld ('CV_REFFLIQ', (/ 'lev' /), 'A', 'micron', 'convective cloud liq effective radius', sampled_on_subcycle=.true.) + call addfld ('CV_REFFICE', (/ 'lev' /), 'A', 'micron', 'convective cloud ice effective radius', sampled_on_subcycle=.true.) + call addfld ('MG_SADICE', (/ 'lev' /), 'A', 'cm2/cm3', 'MG surface area density ice', sampled_on_subcycle=.true.) + call addfld ('MG_SADSNOW', (/ 'lev' /), 'A', 'cm2/cm3', 'MG surface area density snow', sampled_on_subcycle=.true.) ! diagnostic precip - call addfld ('QRAIN', (/ 'lev' /), 'A', 'kg/kg', 'Diagnostic grid-mean rain mixing ratio' ) - call addfld ('QSNOW', (/ 'lev' /), 'A', 'kg/kg', 'Diagnostic grid-mean snow mixing ratio' ) - call addfld ('NRAIN', (/ 'lev' /), 'A', 'm-3', 'Diagnostic grid-mean rain number conc' ) - call addfld ('NSNOW', (/ 'lev' /), 'A', 'm-3', 'Diagnostic grid-mean snow number conc' ) + call addfld ('QRAIN', (/ 'lev' /), 'A', 'kg/kg', 'Diagnostic grid-mean rain mixing ratio', sampled_on_subcycle=.true.) + call addfld ('QSNOW', (/ 'lev' /), 'A', 'kg/kg', 'Diagnostic grid-mean snow mixing ratio', sampled_on_subcycle=.true.) + call addfld ('NRAIN', (/ 'lev' /), 'A', 'm-3', 'Diagnostic grid-mean rain number conc', sampled_on_subcycle=.true.) + call addfld ('NSNOW', (/ 'lev' /), 'A', 'm-3', 'Diagnostic grid-mean snow number conc', sampled_on_subcycle=.true.) ! size of precip - call addfld ('RERCLD', (/ 'lev' /), 'A', 'm', 'Diagnostic effective radius of Liquid Cloud and Rain' ) - call addfld ('DSNOW', (/ 'lev' /), 'A', 'm', 'Diagnostic grid-mean snow diameter' ) + call addfld ('RERCLD', (/ 'lev' /), 'A', 'm', 'Diagnostic effective radius of Liquid Cloud and Rain', sampled_on_subcycle=.true.) + call addfld ('DSNOW', (/ 'lev' /), 'A', 'm', 'Diagnostic grid-mean snow diameter', sampled_on_subcycle=.true.) ! diagnostic radar reflectivity, cloud-averaged - call addfld ('REFL', (/ 'lev' /), 'A', 'DBz', '94 GHz radar reflectivity' ) - call addfld ('AREFL', (/ 'lev' /), 'A', 'DBz', 'Average 94 GHz radar reflectivity' ) - call addfld ('FREFL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of radar reflectivity' ) + call addfld ('REFL', (/ 'lev' /), 'A', 'DBz', '94 GHz radar reflectivity', sampled_on_subcycle=.true.) + call addfld ('AREFL', (/ 'lev' /), 'A', 'DBz', 'Average 94 GHz radar reflectivity', sampled_on_subcycle=.true.) + call addfld ('FREFL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of radar reflectivity', sampled_on_subcycle=.true.) - call addfld ('CSRFL', (/ 'lev' /), 'A', 'DBz', '94 GHz radar reflectivity (CloudSat thresholds)' ) - call addfld ('ACSRFL', (/ 'lev' /), 'A', 'DBz', 'Average 94 GHz radar reflectivity (CloudSat thresholds)' ) - call addfld ('FCSRFL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of radar reflectivity (CloudSat thresholds)' ) + call addfld ('CSRFL', (/ 'lev' /), 'A', 'DBz', '94 GHz radar reflectivity (CloudSat thresholds)', sampled_on_subcycle=.true.) + call addfld ('ACSRFL', (/ 'lev' /), 'A', 'DBz', 'Average 94 GHz radar reflectivity (CloudSat thresholds)', sampled_on_subcycle=.true.) + call addfld ('FCSRFL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of radar reflectivity (CloudSat thresholds)', sampled_on_subcycle=.true.) - call addfld ('AREFLZ', (/ 'lev' /), 'A', 'mm^6/m^3', 'Average 94 GHz radar reflectivity' ) + call addfld ('AREFLZ', (/ 'lev' /), 'A', 'mm^6/m^3', 'Average 94 GHz radar reflectivity', sampled_on_subcycle=.true.) ! Aerosol information - call addfld ('NCAL', (/ 'lev' /), 'A', '1/m3', 'Number Concentation Activated for Liquid' ) - call addfld ('NCAI', (/ 'lev' /), 'A', '1/m3', 'Number Concentation Activated for Ice' ) + call addfld ('NCAL', (/ 'lev' /), 'A', '1/m3', 'Number Concentation Activated for Liquid', sampled_on_subcycle=.true.) + call addfld ('NCAI', (/ 'lev' /), 'A', '1/m3', 'Number Concentation Activated for Ice', sampled_on_subcycle=.true.) ! Average rain and snow mixing ratio (Q), number (N) and diameter (D), with frequency - call addfld ('AQRAIN', (/ 'lev' /), 'A', 'kg/kg', 'Average rain mixing ratio' ) - call addfld ('AQSNOW', (/ 'lev' /), 'A', 'kg/kg', 'Average snow mixing ratio' ) - call addfld ('ANRAIN', (/ 'lev' /), 'A', 'm-3', 'Average rain number conc' ) - call addfld ('ANSNOW', (/ 'lev' /), 'A', 'm-3', 'Average snow number conc' ) - call addfld ('ADRAIN', (/ 'lev' /), 'A', 'm', 'Average rain effective Diameter' ) - call addfld ('ADSNOW', (/ 'lev' /), 'A', 'm', 'Average snow effective Diameter' ) - call addfld ('FREQR', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of rain' ) - call addfld ('FREQS', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of snow' ) + call addfld ('AQRAIN', (/ 'lev' /), 'A', 'kg/kg', 'Average rain mixing ratio', sampled_on_subcycle=.true.) + call addfld ('AQSNOW', (/ 'lev' /), 'A', 'kg/kg', 'Average snow mixing ratio', sampled_on_subcycle=.true.) + call addfld ('ANRAIN', (/ 'lev' /), 'A', 'm-3', 'Average rain number conc', sampled_on_subcycle=.true.) + call addfld ('ANSNOW', (/ 'lev' /), 'A', 'm-3', 'Average snow number conc', sampled_on_subcycle=.true.) + call addfld ('ADRAIN', (/ 'lev' /), 'A', 'm', 'Average rain effective Diameter', sampled_on_subcycle=.true.) + call addfld ('ADSNOW', (/ 'lev' /), 'A', 'm', 'Average snow effective Diameter', sampled_on_subcycle=.true.) + call addfld ('FREQR', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of rain', sampled_on_subcycle=.true.) + call addfld ('FREQS', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of snow', sampled_on_subcycle=.true.) ! precipitation efficiency & other diagnostic fields - call addfld('PE' , horiz_only, 'A', '1', 'Stratiform Precipitation Efficiency (precip/cmeliq)' ) - call addfld('APRL' , horiz_only, 'A', 'm/s', 'Average Stratiform Precip Rate over efficiency calculation' ) - call addfld('PEFRAC', horiz_only, 'A', '1', 'Fraction of timesteps precip efficiency reported' ) - call addfld('VPRCO' , horiz_only, 'A', 'kg/kg/s', 'Vertical average of autoconversion rate' ) - call addfld('VPRAO' , horiz_only, 'A', 'kg/kg/s', 'Vertical average of accretion rate' ) - call addfld('RACAU' , horiz_only, 'A', 'kg/kg/s', 'Accretion/autoconversion ratio from vertical average' ) + call addfld('PE' , horiz_only, 'A', '1', 'Stratiform Precipitation Efficiency (precip/cmeliq)', sampled_on_subcycle=.true.) + call addfld('APRL' , horiz_only, 'A', 'm/s', 'Average Stratiform Precip Rate over efficiency calculation', sampled_on_subcycle=.true.) + call addfld('PEFRAC', horiz_only, 'A', '1', 'Fraction of timesteps precip efficiency reported', sampled_on_subcycle=.true.) + call addfld('VPRCO' , horiz_only, 'A', 'kg/kg/s', 'Vertical average of autoconversion rate', sampled_on_subcycle=.true.) + call addfld('VPRAO' , horiz_only, 'A', 'kg/kg/s', 'Vertical average of accretion rate', sampled_on_subcycle=.true.) + call addfld('RACAU' , horiz_only, 'A', 'kg/kg/s', 'Accretion/autoconversion ratio from vertical average', sampled_on_subcycle=.true.) if (micro_mg_version > 1) then - call addfld('UMR', (/ 'lev' /), 'A', 'm/s', 'Mass-weighted rain fallspeed' ) - call addfld('UMS', (/ 'lev' /), 'A', 'm/s', 'Mass-weighted snow fallspeed' ) + call addfld('UMR', (/ 'lev' /), 'A', 'm/s', 'Mass-weighted rain fallspeed', sampled_on_subcycle=.true.) + call addfld('UMS', (/ 'lev' /), 'A', 'm/s', 'Mass-weighted snow fallspeed', sampled_on_subcycle=.true.) end if if (micro_mg_version > 2) then - call addfld('UMG', (/ 'lev' /), 'A', 'm/s', 'Mass-weighted graupel/hail fallspeed' ) - call addfld ('FREQG', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of Graupel' ) - call addfld ('LS_REFFGRAU', (/ 'lev' /), 'A', 'micron', 'ls stratiform graupel/hail effective radius' ) - call addfld ('AQGRAU', (/ 'lev' /), 'A', 'kg/kg', 'Average graupel/hail mixing ratio' ) - call addfld ('ANGRAU', (/ 'lev' /), 'A', 'm-3', 'Average graupel/hail number conc' ) + call addfld('UMG', (/ 'lev' /), 'A', 'm/s', 'Mass-weighted graupel/hail fallspeed', sampled_on_subcycle=.true.) + call addfld ('FREQG', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of Graupel', sampled_on_subcycle=.true.) + call addfld ('LS_REFFGRAU', (/ 'lev' /), 'A', 'micron', 'ls stratiform graupel/hail effective radius', sampled_on_subcycle=.true.) + call addfld ('AQGRAU', (/ 'lev' /), 'A', 'kg/kg', 'Average graupel/hail mixing ratio', sampled_on_subcycle=.true.) + call addfld ('ANGRAU', (/ 'lev' /), 'A', 'm-3', 'Average graupel/hail number conc', sampled_on_subcycle=.true.) end if ! qc limiter (only output in versions 1.5 and later) if (.not. (micro_mg_version == 1 .and. micro_mg_sub_version == 0)) then - call addfld('QCRAT', (/ 'lev' /), 'A', 'fraction', 'Qc Limiter: Fraction of qc tendency applied') + call addfld('QCRAT', (/ 'lev' /), 'A', 'fraction', 'Qc Limiter: Fraction of qc tendency applied', sampled_on_subcycle=.true.) end if ! determine the add_default fields diff --git a/src/physics/cam/microp_aero.F90 b/src/physics/cam/microp_aero.F90 index 4961a139a8..51303e1830 100644 --- a/src/physics/cam/microp_aero.F90 +++ b/src/physics/cam/microp_aero.F90 @@ -334,10 +334,10 @@ subroutine microp_aero_init(phys_state,pbuf2d) end if - call addfld('LCLOUD', (/ 'lev' /), 'A', ' ', 'Liquid cloud fraction used in stratus activation') + call addfld('LCLOUD', (/ 'lev' /), 'A', ' ', 'Liquid cloud fraction used in stratus activation', sampled_on_subcycle=.true.) - call addfld('WSUB', (/ 'lev' /), 'A', 'm/s', 'Diagnostic sub-grid vertical velocity' ) - call addfld('WSUBI', (/ 'lev' /), 'A', 'm/s', 'Diagnostic sub-grid vertical velocity for ice' ) + call addfld('WSUB', (/ 'lev' /), 'A', 'm/s', 'Diagnostic sub-grid vertical velocity', sampled_on_subcycle=.true.) + call addfld('WSUBI', (/ 'lev' /), 'A', 'm/s', 'Diagnostic sub-grid vertical velocity for ice', sampled_on_subcycle=.true.) if (history_amwg) then call add_default ('WSUB ', 1, ' ') diff --git a/src/physics/cam7/micro_pumas_cam.F90 b/src/physics/cam7/micro_pumas_cam.F90 index 0d9f448e2f..5d76f36be5 100644 --- a/src/physics/cam7/micro_pumas_cam.F90 +++ b/src/physics/cam7/micro_pumas_cam.F90 @@ -958,286 +958,286 @@ subroutine micro_pumas_cam_init(pbuf2d) call cnst_get_ind(cnst_names(m), mm) if ( any(mm == (/ ixcldliq, ixcldice, ixrain, ixsnow, ixgraupel /)) ) then ! mass mixing ratios - call addfld(cnst_name(mm), (/ 'lev' /), 'A', 'kg/kg', cnst_longname(mm) ) - call addfld(sflxnam(mm), horiz_only, 'A', 'kg/m2/s', trim(cnst_name(mm))//' surface flux') + call addfld(cnst_name(mm), (/ 'lev' /), 'A', 'kg/kg', cnst_longname(mm), sampled_on_subcycle=.true.) + call addfld(sflxnam(mm), horiz_only, 'A', 'kg/m2/s', trim(cnst_name(mm))//' surface flux', sampled_on_subcycle=.true.) else if ( any(mm == (/ ixnumliq, ixnumice, ixnumrain, ixnumsnow, ixnumgraupel /)) ) then ! number concentrations - call addfld(cnst_name(mm), (/ 'lev' /), 'A', '1/kg', cnst_longname(mm) ) - call addfld(sflxnam(mm), horiz_only, 'A', '1/m2/s', trim(cnst_name(mm))//' surface flux') + call addfld(cnst_name(mm), (/ 'lev' /), 'A', '1/kg', cnst_longname(mm), sampled_on_subcycle=.true.) + call addfld(sflxnam(mm), horiz_only, 'A', '1/m2/s', trim(cnst_name(mm))//' surface flux', sampled_on_subcycle=.true.) else call endrun( "micro_pumas_cam_init: & &Could not call addfld for constituent with unknown units.") endif end do - call addfld(apcnst(ixcldliq), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldliq))//' after physics' ) - call addfld(apcnst(ixcldice), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldice))//' after physics' ) - call addfld(bpcnst(ixcldliq), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldliq))//' before physics' ) - call addfld(bpcnst(ixcldice), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldice))//' before physics' ) + call addfld(apcnst(ixcldliq), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldliq))//' after physics', sampled_on_subcycle=.true.) + call addfld(apcnst(ixcldice), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldice))//' after physics', sampled_on_subcycle=.true.) + call addfld(bpcnst(ixcldliq), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldliq))//' before physics', sampled_on_subcycle=.true.) + call addfld(bpcnst(ixcldice), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixcldice))//' before physics', sampled_on_subcycle=.true.) - call addfld(apcnst(ixrain), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixrain))//' after physics' ) - call addfld(apcnst(ixsnow), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixsnow))//' after physics' ) - call addfld(bpcnst(ixrain), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixrain))//' before physics' ) - call addfld(bpcnst(ixsnow), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixsnow))//' before physics' ) + call addfld(apcnst(ixrain), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixrain))//' after physics', sampled_on_subcycle=.true.) + call addfld(apcnst(ixsnow), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixsnow))//' after physics', sampled_on_subcycle=.true.) + call addfld(bpcnst(ixrain), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixrain))//' before physics', sampled_on_subcycle=.true.) + call addfld(bpcnst(ixsnow), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixsnow))//' before physics', sampled_on_subcycle=.true.) if (micro_mg_version > 2) then - call addfld(apcnst(ixgraupel), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixgraupel))//' after physics' ) - call addfld(bpcnst(ixgraupel), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixgraupel))//' before physics' ) + call addfld(apcnst(ixgraupel), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixgraupel))//' after physics', sampled_on_subcycle=.true.) + call addfld(bpcnst(ixgraupel), (/ 'lev' /), 'A', 'kg/kg', trim(cnst_name(ixgraupel))//' before physics', sampled_on_subcycle=.true.) end if - call addfld ('CME', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of cond-evap within the cloud' ) - call addfld ('PRODPREC', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of conversion of condensate to precip' ) - call addfld ('EVAPPREC', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling precip' ) - call addfld ('EVAPSNOW', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling snow' ) - call addfld ('HPROGCLD', (/ 'lev' /), 'A', 'W/kg' , 'Heating from prognostic clouds' ) - call addfld ('FICE', (/ 'lev' /), 'A', 'fraction', 'Fractional ice content within cloud' ) - call addfld ('CLDFSNOW', (/ 'lev' /), 'A', '1', 'Cloud fraction adjusted for snow' ) - call addfld ('ICWMRST', (/ 'lev' /), 'A', 'kg/kg', 'Prognostic in-stratus water mixing ratio' ) - call addfld ('ICIMRST', (/ 'lev' /), 'A', 'kg/kg', 'Prognostic in-stratus ice mixing ratio' ) + call addfld ('CME', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of cond-evap within the cloud', sampled_on_subcycle=.true.) + call addfld ('PRODPREC', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of conversion of condensate to precip', sampled_on_subcycle=.true.) + call addfld ('EVAPPREC', (/ 'lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling precip', sampled_on_subcycle=.true.) + call addfld ('EVAPSNOW', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling snow', sampled_on_subcycle=.true.) + call addfld ('HPROGCLD', (/ 'lev' /), 'A', 'W/kg' , 'Heating from prognostic clouds', sampled_on_subcycle=.true.) + call addfld ('FICE', (/ 'lev' /), 'A', 'fraction', 'Fractional ice content within cloud', sampled_on_subcycle=.true.) + call addfld ('CLDFSNOW', (/ 'lev' /), 'A', '1', 'Cloud fraction adjusted for snow', sampled_on_subcycle=.true.) + call addfld ('ICWMRST', (/ 'lev' /), 'A', 'kg/kg', 'Prognostic in-stratus water mixing ratio', sampled_on_subcycle=.true.) + call addfld ('ICIMRST', (/ 'lev' /), 'A', 'kg/kg', 'Prognostic in-stratus ice mixing ratio', sampled_on_subcycle=.true.) ! MG microphysics diagnostics - call addfld ('QCSEVAP', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling cloud water' ) - call addfld ('QISEVAP', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rate of sublimation of falling cloud ice' ) - call addfld ('QVRES', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rate of residual condensation term' ) - call addfld ('CMEIOUT', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rate of deposition/sublimation of cloud ice' ) - call addfld ('VTRMC', (/ 'trop_cld_lev' /), 'A', 'm/s', 'Mass-weighted cloud water fallspeed' ) - call addfld ('VTRMI', (/ 'trop_cld_lev' /), 'A', 'm/s', 'Mass-weighted cloud ice fallspeed' ) - call addfld ('QCSEDTEN', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Cloud water mixing ratio tendency from sedimentation' ) - call addfld ('QISEDTEN', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Cloud ice mixing ratio tendency from sedimentation' ) - call addfld ('PRAO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud water by rain' ) - call addfld ('PRCO', (/ 'lev' /), 'A', 'kg/kg/s', 'Autoconversion of cloud water' ) - call addfld ('MNUCCCO', (/ 'lev' /), 'A', 'kg/kg/s', 'Immersion freezing of cloud water' ) - call addfld ('MNUCCTO', (/ 'lev' /), 'A', 'kg/kg/s', 'Contact freezing of cloud water' ) - call addfld ('MNUCCDO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Homogeneous and heterogeneous nucleation from vapor' ) - call addfld ('MNUCCDOhet', (/ 'lev' /), 'A', 'kg/kg/s', 'Heterogeneous nucleation from vapor' ) - call addfld ('MSACWIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water from rime-splintering' ) - call addfld ('PSACWSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud water by snow' ) - call addfld ('BERGSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water to snow from bergeron' ) - call addfld ('BERGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water to cloud ice from bergeron' ) - call addfld ('MELTO', (/ 'lev' /), 'A', 'kg/kg/s', 'Melting of cloud ice' ) - call addfld ('MELTSTOT', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Melting of snow' ) - call addfld ('MNUDEPO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Deposition Nucleation' ) - call addfld ('HOMOO', (/ 'lev' /), 'A', 'kg/kg/s', 'Homogeneous freezing of cloud water' ) - call addfld ('QCRESO', (/ 'lev' /), 'A', 'kg/kg/s', 'Residual condensation term for cloud water' ) - call addfld ('PRCIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Autoconversion of cloud ice to snow' ) - call addfld ('PRAIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud ice to snow' ) - call addfld ('QIRESO', (/ 'lev' /), 'A', 'kg/kg/s', 'Residual deposition term for cloud ice' ) - call addfld ('MNUCCRO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Heterogeneous freezing of rain to snow' ) - call addfld ('MNUCCRIO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Heterogeneous freezing of rain to ice' ) - call addfld ('PRACSO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Accretion of rain by snow' ) - call addfld ('VAPDEPSO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Vapor deposition onto snow' ) - call addfld ('MELTSDT', (/ 'trop_cld_lev' /), 'A', 'W/kg', 'Latent heating rate due to melting of snow' ) - call addfld ('FRZRDT', (/ 'trop_cld_lev' /), 'A', 'W/kg', 'Latent heating rate due to homogeneous freezing of rain' ) - call addfld ('QRSEDTEN', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rain mixing ratio tendency from sedimentation' ) - call addfld ('QSSEDTEN', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Snow mixing ratio tendency from sedimentation' ) - call addfld ('NNUCCCO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Immersion freezing of cloud water') - call addfld ('NNUCCTO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Contact freezing of cloud water') - call addfld ('NNUCCDO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Ice nucleation') - call addfld ('NNUDEPO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Deposition Nucleation') - call addfld ('NHOMO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Homogeneous freezing of cloud water') - call addfld ('NNUCCRO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to heterogeneous freezing of rain to snow') - call addfld ('NNUCCRIO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Heterogeneous freezing of rain to ice') - call addfld ('NSACWIO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Ice Multiplication- Rime-splintering') - call addfld ('NPRAO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Accretion of cloud water by rain') - call addfld ('NPSACWSO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Accretion of cloud water by snow') - call addfld ('NPRAIO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Accretion of cloud ice to snow') - call addfld ('NPRACSO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Accretion of rain by snow') - call addfld ('NPRCO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Autoconversion of cloud water [to rain]') - call addfld ('NPRCIO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Autoconversion of cloud ice to snow') - call addfld ('NCSEDTEN', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to cloud liquid sedimentation') - call addfld ('NISEDTEN', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to cloud ice sedimentation') - call addfld ('NRSEDTEN', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to rain sedimentation') - call addfld ('NSSEDTEN', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to snow sedimentation') - call addfld ('NMELTO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Melting of cloud ice ') - call addfld ('NMELTS', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Melting of snow') + call addfld ('QCSEVAP', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rate of evaporation of falling cloud water', sampled_on_subcycle=.true.) + call addfld ('QISEVAP', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rate of sublimation of falling cloud ice', sampled_on_subcycle=.true.) + call addfld ('QVRES', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rate of residual condensation term', sampled_on_subcycle=.true.) + call addfld ('CMEIOUT', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rate of deposition/sublimation of cloud ice',sampled_on_subcycle=.true.) + call addfld ('VTRMC', (/ 'trop_cld_lev' /), 'A', 'm/s', 'Mass-weighted cloud water fallspeed', sampled_on_subcycle=.true.) + call addfld ('VTRMI', (/ 'trop_cld_lev' /), 'A', 'm/s', 'Mass-weighted cloud ice fallspeed', sampled_on_subcycle=.true.) + call addfld ('QCSEDTEN', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Cloud water mixing ratio tendency from sedimentation', sampled_on_subcycle=.true.) + call addfld ('QISEDTEN', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Cloud ice mixing ratio tendency from sedimentation', sampled_on_subcycle=.true.) + call addfld ('PRAO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud water by rain', sampled_on_subcycle=.true.) + call addfld ('PRCO', (/ 'lev' /), 'A', 'kg/kg/s', 'Autoconversion of cloud water', sampled_on_subcycle=.true.) + call addfld ('MNUCCCO', (/ 'lev' /), 'A', 'kg/kg/s', 'Immersion freezing of cloud water', sampled_on_subcycle=.true.) + call addfld ('MNUCCTO', (/ 'lev' /), 'A', 'kg/kg/s', 'Contact freezing of cloud water', sampled_on_subcycle=.true.) + call addfld ('MNUCCDO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Homogeneous and heterogeneous nucleation from vapor', sampled_on_subcycle=.true.) + call addfld ('MNUCCDOhet', (/ 'lev' /), 'A', 'kg/kg/s', 'Heterogeneous nucleation from vapor', sampled_on_subcycle=.true.) + call addfld ('MSACWIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water from rime-splintering', sampled_on_subcycle=.true.) + call addfld ('PSACWSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud water by snow', sampled_on_subcycle=.true.) + call addfld ('BERGSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water to snow from bergeron', sampled_on_subcycle=.true.) + call addfld ('BERGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Conversion of cloud water to cloud ice from bergeron',sampled_on_subcycle=.true.) + call addfld ('MELTO', (/ 'lev' /), 'A', 'kg/kg/s', 'Melting of cloud ice', sampled_on_subcycle=.true.) + call addfld ('MELTSTOT', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Melting of snow', sampled_on_subcycle=.true.) + call addfld ('MNUDEPO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Deposition Nucleation', sampled_on_subcycle=.true.) + call addfld ('HOMOO', (/ 'lev' /), 'A', 'kg/kg/s', 'Homogeneous freezing of cloud water', sampled_on_subcycle=.true.) + call addfld ('QCRESO', (/ 'lev' /), 'A', 'kg/kg/s', 'Residual condensation term for cloud water', sampled_on_subcycle=.true.) + call addfld ('PRCIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Autoconversion of cloud ice to snow', sampled_on_subcycle=.true.) + call addfld ('PRAIO', (/ 'lev' /), 'A', 'kg/kg/s', 'Accretion of cloud ice to snow', sampled_on_subcycle=.true.) + call addfld ('QIRESO', (/ 'lev' /), 'A', 'kg/kg/s', 'Residual deposition term for cloud ice', sampled_on_subcycle=.true.) + call addfld ('MNUCCRO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Heterogeneous freezing of rain to snow', sampled_on_subcycle=.true.) + call addfld ('MNUCCRIO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Heterogeneous freezing of rain to ice', sampled_on_subcycle=.true.) + call addfld ('PRACSO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Accretion of rain by snow', sampled_on_subcycle=.true.) + call addfld ('VAPDEPSO', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Vapor deposition onto snow', sampled_on_subcycle=.true.) + call addfld ('MELTSDT', (/ 'trop_cld_lev' /), 'A', 'W/kg', 'Latent heating rate due to melting of snow', sampled_on_subcycle=.true.) + call addfld ('FRZRDT', (/ 'trop_cld_lev' /), 'A', 'W/kg', 'Latent heating rate due to homogeneous freezing of rain', sampled_on_subcycle=.true.) + call addfld ('QRSEDTEN', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Rain mixing ratio tendency from sedimentation', sampled_on_subcycle=.true.) + call addfld ('QSSEDTEN', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Snow mixing ratio tendency from sedimentation', sampled_on_subcycle=.true.) + call addfld ('NNUCCCO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Immersion freezing of cloud water', sampled_on_subcycle=.true.) + call addfld ('NNUCCTO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Contact freezing of cloud water', sampled_on_subcycle=.true.) + call addfld ('NNUCCDO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Ice nucleation', sampled_on_subcycle=.true.) + call addfld ('NNUDEPO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Deposition Nucleation', sampled_on_subcycle=.true.) + call addfld ('NHOMO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Homogeneous freezing of cloud water', sampled_on_subcycle=.true.) + call addfld ('NNUCCRO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to heterogeneous freezing of rain to snow', sampled_on_subcycle=.true.) + call addfld ('NNUCCRIO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Heterogeneous freezing of rain to ice', sampled_on_subcycle=.true.) + call addfld ('NSACWIO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Ice Multiplication- Rime-splintering', sampled_on_subcycle=.true.) + call addfld ('NPRAO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Accretion of cloud water by rain', sampled_on_subcycle=.true.) + call addfld ('NPSACWSO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Accretion of cloud water by snow', sampled_on_subcycle=.true.) + call addfld ('NPRAIO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Accretion of cloud ice to snow', sampled_on_subcycle=.true.) + call addfld ('NPRACSO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Accretion of rain by snow', sampled_on_subcycle=.true.) + call addfld ('NPRCO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Autoconversion of cloud water [to rain]', sampled_on_subcycle=.true.) + call addfld ('NPRCIO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Autoconversion of cloud ice to snow', sampled_on_subcycle=.true.) + call addfld ('NCSEDTEN', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to cloud liquid sedimentation', sampled_on_subcycle=.true.) + call addfld ('NISEDTEN', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to cloud ice sedimentation', sampled_on_subcycle=.true.) + call addfld ('NRSEDTEN', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to rain sedimentation', sampled_on_subcycle=.true.) + call addfld ('NSSEDTEN', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to snow sedimentation', sampled_on_subcycle=.true.) + call addfld ('NMELTO', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Melting of cloud ice', sampled_on_subcycle=.true.) + call addfld ('NMELTS', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Melting of snow', sampled_on_subcycle=.true.) if (trim(micro_mg_warm_rain) == 'kk2000') then - call addfld ('qctend_KK2000', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'cloud liquid mass tendency due to autoconversion & accretion from KK2000') - call addfld ('nctend_KK2000', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'cloud number mass tendency due to autoconversion & accretion from KK2000') - call addfld ('qrtend_KK2000', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'rain mass tendency due to autoconversion & accretion from KK2000') - call addfld ('nrtend_KK2000', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'rain number tendency due to autoconversion & accretion from KK2000') + call addfld ('qctend_KK2000', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'cloud liquid mass tendency due to autoconversion & accretion from KK2000', sampled_on_subcycle=.true.) + call addfld ('nctend_KK2000', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'cloud number mass tendency due to autoconversion & accretion from KK2000', sampled_on_subcycle=.true.) + call addfld ('qrtend_KK2000', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'rain mass tendency due to autoconversion & accretion from KK2000', sampled_on_subcycle=.true.) + call addfld ('nrtend_KK2000', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'rain number tendency due to autoconversion & accretion from KK2000', sampled_on_subcycle=.true.) end if if (trim(micro_mg_warm_rain) == 'sb2001') then - call addfld ('qctend_SB2001', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'cloud liquid mass tendency due to autoconversion & accretion from SB2001') - call addfld ('nctend_SB2001', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'cloud liquid number tendency due to autoconversion & accretion from SB2001') - call addfld ('qrtend_SB2001', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'rain mass tendency due to autoconversion & accretion from SB2001') - call addfld ('nrtend_SB2001', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'rain number tendency due to autoconversion & accretion from SB2001') + call addfld ('qctend_SB2001', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'cloud liquid mass tendency due to autoconversion & accretion from SB2001', sampled_on_subcycle=.true.) + call addfld ('nctend_SB2001', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'cloud liquid number tendency due to autoconversion & accretion from SB2001',sampled_on_subcycle=.true.) + call addfld ('qrtend_SB2001', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'rain mass tendency due to autoconversion & accretion from SB2001', sampled_on_subcycle=.true.) + call addfld ('nrtend_SB2001', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'rain number tendency due to autoconversion & accretion from SB2001', sampled_on_subcycle=.true.) end if - call addfld ('LAMC', (/ 'trop_cld_lev' /), 'A', 'unitless', 'Size distribution parameter lambda for liquid' ) - call addfld ('LAMR', (/ 'trop_cld_lev' /), 'A', 'unitless', 'Size distribution parameter lambda for rain' ) - call addfld ('PGAM', (/ 'trop_cld_lev' /), 'A', 'unitless', 'Size distribution parameter mu (pgam) for liquid' ) - call addfld ('N0R', (/ 'trop_cld_lev' /), 'A', 'unitless', 'Size distribution parameter n0 for rain' ) + call addfld ('LAMC', (/ 'trop_cld_lev' /), 'A', 'unitless', 'Size distribution parameter lambda for liquid', sampled_on_subcycle=.true. ) + call addfld ('LAMR', (/ 'trop_cld_lev' /), 'A', 'unitless', 'Size distribution parameter lambda for rain', sampled_on_subcycle=.true.) + call addfld ('PGAM', (/ 'trop_cld_lev' /), 'A', 'unitless', 'Size distribution parameter mu (pgam) for liquid', sampled_on_subcycle=.true.) + call addfld ('N0R', (/ 'trop_cld_lev' /), 'A', 'unitless', 'Size distribution parameter n0 for rain', sampled_on_subcycle=.true.) if (micro_mg_version > 2) then - call addfld ('NMELTG', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Melting of graupel') - call addfld ('NGSEDTEN', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to graupel sedimentation') - call addfld ('PSACRO', (/ 'lev' /), 'A', 'kg/kg/s', 'Collisions between rain & snow (Graupel collecting snow)') - call addfld ('PRACGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change in q collection rain by graupel' ) - call addfld ('PSACWGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change in q collection droplets by graupel' ) - call addfld ('PGSACWO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q conversion to graupel due to collection droplets by snow') - call addfld ('PGRACSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q conversion to graupel due to collection rain by snow') - call addfld ('PRDGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Deposition of graupel') - call addfld ('QMULTGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q change due to ice mult droplets/graupel') - call addfld ('QMULTRGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q change due to ice mult rain/graupel') - call addfld ('QGSEDTEN', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Graupel/Hail mixing ratio tendency from sedimentation') - call addfld ('NPRACGO', (/ 'lev' /), 'A', '#/kg/s', 'Change N collection rain by graupel') - call addfld ('NSCNGO', (/ 'lev' /), 'A', '#/kg/s', 'Change N conversion to graupel due to collection droplets by snow') - call addfld ('NGRACSO', (/ 'lev' /), 'A', '#/kg/s', 'Change N conversion to graupel due to collection rain by snow') - call addfld ('NMULTGO', (/ 'lev' /), 'A', '#/kg/s', 'Ice mult due to acc droplets by graupel ') - call addfld ('NMULTRGO', (/ 'lev' /), 'A', '#/kg/s', 'Ice mult due to acc rain by graupel') - call addfld ('NPSACWGO', (/ 'lev' /), 'A', '#/kg/s', 'Change N collection droplets by graupel') - call addfld ('CLDFGRAU', (/ 'lev' /), 'A', '1', 'Cloud fraction adjusted for graupel' ) - call addfld ('MELTGTOT', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Melting of graupel' ) + call addfld ('NMELTG', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to Melting of graupel', sampled_on_subcycle=.true.) + call addfld ('NGSEDTEN', (/ 'trop_cld_lev' /), 'A', '#/kg/s', 'Number Tendency due to graupel sedimentation', sampled_on_subcycle=.true.) + call addfld ('PSACRO', (/ 'lev' /), 'A', 'kg/kg/s', 'Collisions between rain & snow (Graupel collecting snow)',sampled_on_subcycle=.true.) + call addfld ('PRACGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change in q collection rain by graupel', sampled_on_subcycle=.true.) + call addfld ('PSACWGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Change in q collection droplets by graupel', sampled_on_subcycle=.true.) + call addfld ('PGSACWO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q conversion to graupel due to collection droplets by snow', sampled_on_subcycle=.true.) + call addfld ('PGRACSO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q conversion to graupel due to collection rain by snow', sampled_on_subcycle=.true.) + call addfld ('PRDGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Deposition of graupel', sampled_on_subcycle=.true.) + call addfld ('QMULTGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q change due to ice mult droplets/graupel', sampled_on_subcycle=.true.) + call addfld ('QMULTRGO', (/ 'lev' /), 'A', 'kg/kg/s', 'Q change due to ice mult rain/graupel', sampled_on_subcycle=.true.) + call addfld ('QGSEDTEN', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Graupel/Hail mixing ratio tendency from sedimentation', sampled_on_subcycle=.true.) + call addfld ('NPRACGO', (/ 'lev' /), 'A', '#/kg/s', 'Change N collection rain by graupel', sampled_on_subcycle=.true.) + call addfld ('NSCNGO', (/ 'lev' /), 'A', '#/kg/s', 'Change N conversion to graupel due to collection droplets by snow', sampled_on_subcycle=.true.) + call addfld ('NGRACSO', (/ 'lev' /), 'A', '#/kg/s', 'Change N conversion to graupel due to collection rain by snow', sampled_on_subcycle=.true.) + call addfld ('NMULTGO', (/ 'lev' /), 'A', '#/kg/s', 'Ice mult due to acc droplets by graupel', sampled_on_subcycle=.true.) + call addfld ('NMULTRGO', (/ 'lev' /), 'A', '#/kg/s', 'Ice mult due to acc rain by graupel', sampled_on_subcycle=.true.) + call addfld ('NPSACWGO', (/ 'lev' /), 'A', '#/kg/s', 'Change N collection droplets by graupel', sampled_on_subcycle=.true.) + call addfld ('CLDFGRAU', (/ 'lev' /), 'A', '1', 'Cloud fraction adjusted for graupel', sampled_on_subcycle=.true.) + call addfld ('MELTGTOT', (/ 'trop_cld_lev' /), 'A', 'kg/kg/s', 'Melting of graupel', sampled_on_subcycle=.true.) end if - call addfld ('RBFRAC', horiz_only, 'A', 'Fraction', 'Fraction of sky covered by a potential rainbow' ) - call addfld ('RBFREQ', horiz_only, 'A', 'Frequency', 'Potential rainbow frequency' ) - call addfld( 'rbSZA', horiz_only, 'I', 'degrees', 'solar zenith angle' ) + call addfld ('RBFRAC', horiz_only, 'A', 'Fraction', 'Fraction of sky covered by a potential rainbow', sampled_on_subcycle=.true.) + call addfld ('RBFREQ', horiz_only, 'A', 'Frequency', 'Potential rainbow frequency', sampled_on_subcycle=.true.) + call addfld( 'rbSZA', horiz_only, 'I', 'degrees', 'solar zenith angle', sampled_on_subcycle=.true.) ! History variables for CAM5 microphysics - call addfld ('MPDT', (/ 'lev' /), 'A', 'W/kg', 'Heating tendency - Morrison microphysics' ) - call addfld ('MPDQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Q tendency - Morrison microphysics' ) - call addfld ('MPDLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDLIQ tendency - Morrison microphysics' ) - call addfld ('MPDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency - Morrison microphysics' ) - call addfld ('MPDNLIQ', (/ 'lev' /), 'A', '1/kg/s', 'NUMLIQ tendency - Morrison microphysics' ) - call addfld ('MPDNICE', (/ 'lev' /), 'A', '1/kg/s', 'NUMICE tendency - Morrison microphysics' ) - call addfld ('MPDW2V', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Vapor tendency - Morrison microphysics' ) - call addfld ('MPDW2I', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Ice tendency - Morrison microphysics' ) - call addfld ('MPDW2P', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Precip tendency - Morrison microphysics' ) - call addfld ('MPDI2V', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Vapor tendency - Morrison microphysics' ) - call addfld ('MPDI2W', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Water tendency - Morrison microphysics' ) - call addfld ('MPDI2P', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Precip tendency - Morrison microphysics' ) - call addfld ('ICWNC', (/ 'lev' /), 'A', 'm-3', 'Prognostic in-cloud water number conc' ) - call addfld ('ICINC', (/ 'lev' /), 'A', 'm-3', 'Prognostic in-cloud ice number conc' ) - call addfld ('EFFLIQ_IND', (/ 'lev' /), 'A','Micron', 'Prognostic droplet effective radius (indirect effect)' ) - call addfld ('CDNUMC', horiz_only, 'A', '1/m2', 'Vertically-integrated droplet concentration' ) + call addfld ('MPDT', (/ 'lev' /), 'A', 'W/kg', 'Heating tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Q tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDLIQ tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDICE', (/ 'lev' /), 'A', 'kg/kg/s', 'CLDICE tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDNLIQ', (/ 'lev' /), 'A', '1/kg/s', 'NUMLIQ tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDNICE', (/ 'lev' /), 'A', '1/kg/s', 'NUMICE tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDW2V', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Vapor tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDW2I', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Ice tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDW2P', (/ 'lev' /), 'A', 'kg/kg/s', 'Water <--> Precip tendency - Morrison microphysics',sampled_on_subcycle=.true.) + call addfld ('MPDI2V', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Vapor tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDI2W', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Water tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('MPDI2P', (/ 'lev' /), 'A', 'kg/kg/s', 'Ice <--> Precip tendency - Morrison microphysics', sampled_on_subcycle=.true.) + call addfld ('ICWNC', (/ 'lev' /), 'A', 'm-3', 'Prognostic in-cloud water number conc', sampled_on_subcycle=.true.) + call addfld ('ICINC', (/ 'lev' /), 'A', 'm-3', 'Prognostic in-cloud ice number conc', sampled_on_subcycle=.true.) + call addfld ('EFFLIQ_IND', (/ 'lev' /), 'A','Micron', 'Prognostic droplet effective radius (indirect effect)', sampled_on_subcycle=.true.) + call addfld ('CDNUMC', horiz_only, 'A', '1/m2', 'Vertically-integrated droplet concentration', sampled_on_subcycle=.true.) call addfld ('MPICLWPI', horiz_only, 'A', 'kg/m2', 'Vertically-integrated & - &in-cloud Initial Liquid WP (Before Micro)' ) + &in-cloud Initial Liquid WP (Before Micro)', sampled_on_subcycle=.true.) call addfld ('MPICIWPI', horiz_only, 'A', 'kg/m2', 'Vertically-integrated & - &in-cloud Initial Ice WP (Before Micro)' ) + &in-cloud Initial Ice WP (Before Micro)', sampled_on_subcycle=.true.) ! This is provided as an example on how to write out subcolumn output ! NOTE -- only 'I' should be used for sub-column fields as subc-columns could shift from time-step to time-step if (use_subcol_microp) then call addfld('FICE_SCOL', (/'psubcols','lev '/), 'I', 'fraction', & - 'Sub-column fractional ice content within cloud', flag_xyfill=.true., fill_value=1.e30_r8) + 'Sub-column fractional ice content within cloud', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('MPDICE_SCOL', (/'psubcols','lev '/), 'I', 'kg/kg/s', & - 'Sub-column CLDICE tendency - Morrison microphysics', flag_xyfill=.true., fill_value=1.e30_r8) + 'Sub-column CLDICE tendency - Morrison microphysics', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('MPDLIQ_SCOL', (/'psubcols','lev '/), 'I', 'kg/kg/s', & - 'Sub-column CLDLIQ tendency - Morrison microphysics', flag_xyfill=.true., fill_value=1.e30_r8) + 'Sub-column CLDLIQ tendency - Morrison microphysics', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) end if ! This is only if the coldpoint temperatures are being adjusted. ! NOTE: Some fields related to these and output later are added in tropopause.F90. if (micro_mg_adjust_cpt) then - call addfld ('TROPF_TADJ', (/ 'lev' /), 'A', 'K', 'Temperatures after cold point adjustment' ) - call addfld ('TROPF_RHADJ', (/ 'lev' /), 'A', 'K', 'Relative Hunidity after cold point adjustment' ) - call addfld ('TROPF_CDT', horiz_only, 'A', 'K', 'Cold point temperature adjustment' ) - call addfld ('TROPF_CDZ', horiz_only, 'A', 'm', 'Distance of coldpoint from coldest model level' ) + call addfld ('TROPF_TADJ', (/ 'lev' /), 'A', 'K', 'Temperatures after cold point adjustment', sampled_on_subcycle=.true.) + call addfld ('TROPF_RHADJ', (/ 'lev' /), 'A', 'K', 'Relative Hunidity after cold point adjustment', sampled_on_subcycle=.true.) + call addfld ('TROPF_CDT', horiz_only, 'A', 'K', 'Cold point temperature adjustment', sampled_on_subcycle=.true.) + call addfld ('TROPF_CDZ', horiz_only, 'A', 'm', 'Distance of coldpoint from coldest model level',sampled_on_subcycle=.true.) end if ! Averaging for cloud particle number and size - call addfld ('AWNC', (/ 'lev' /), 'A', 'm-3', 'Average cloud water number conc' ) - call addfld ('AWNI', (/ 'lev' /), 'A', 'm-3', 'Average cloud ice number conc' ) - call addfld ('AREL', (/ 'lev' /), 'A', 'Micron', 'Average droplet effective radius' ) - call addfld ('AREI', (/ 'lev' /), 'A', 'Micron', 'Average ice effective radius' ) + call addfld ('AWNC', (/ 'lev' /), 'A', 'm-3', 'Average cloud water number conc', sampled_on_subcycle=.true.) + call addfld ('AWNI', (/ 'lev' /), 'A', 'm-3', 'Average cloud ice number conc', sampled_on_subcycle=.true.) + call addfld ('AREL', (/ 'lev' /), 'A', 'Micron', 'Average droplet effective radius', sampled_on_subcycle=.true.) + call addfld ('AREI', (/ 'lev' /), 'A', 'Micron', 'Average ice effective radius', sampled_on_subcycle=.true.) ! Frequency arrays for above - call addfld ('FREQL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of liquid' ) - call addfld ('FREQI', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of ice' ) + call addfld ('FREQL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of liquid', sampled_on_subcycle=.true.) + call addfld ('FREQI', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of ice', sampled_on_subcycle=.true.) ! Average cloud top particle size and number (liq, ice) and frequency - call addfld ('ACTREL', horiz_only, 'A', 'Micron', 'Average Cloud Top droplet effective radius' ) - call addfld ('ACTREI', horiz_only, 'A', 'Micron', 'Average Cloud Top ice effective radius' ) - call addfld ('ACTNL', horiz_only, 'A', 'm-3', 'Average Cloud Top droplet number' ) - call addfld ('ACTNI', horiz_only, 'A', 'm-3', 'Average Cloud Top ice number' ) + call addfld ('ACTREL', horiz_only, 'A', 'Micron', 'Average Cloud Top droplet effective radius', sampled_on_subcycle=.true.) + call addfld ('ACTREI', horiz_only, 'A', 'Micron', 'Average Cloud Top ice effective radius', sampled_on_subcycle=.true.) + call addfld ('ACTNL', horiz_only, 'A', 'm-3', 'Average Cloud Top droplet number', sampled_on_subcycle=.true.) + call addfld ('ACTNI', horiz_only, 'A', 'm-3', 'Average Cloud Top ice number', sampled_on_subcycle=.true.) - call addfld ('FCTL', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top liquid' ) - call addfld ('FCTI', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top ice' ) + call addfld ('FCTL', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top liquid', sampled_on_subcycle=.true.) + call addfld ('FCTI', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top ice', sampled_on_subcycle=.true.) ! New frequency arrays for mixed phase and supercooled liquid (only and mixed) for (a) Cloud Top and (b) everywhere.. - call addfld ('FREQM', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of mixed phase' ) - call addfld ('FREQSL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of only supercooled liquid' ) - call addfld ('FREQSLM', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of super cooled liquid with ice' ) - call addfld ('FCTM', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top mixed phase' ) - call addfld ('FCTSL', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top only supercooled liquid' ) - call addfld ('FCTSLM', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top super cooled liquid with ice' ) - - call addfld ('LS_FLXPRC', (/ 'ilev' /), 'A', 'kg/m2/s', 'ls stratiform gbm interface rain+snow flux' ) - call addfld ('LS_FLXSNW', (/ 'ilev' /), 'A', 'kg/m2/s', 'ls stratiform gbm interface snow flux' ) - - call addfld ('REL', (/ 'lev' /), 'A', 'micron', 'MG REL stratiform cloud effective radius liquid' ) - call addfld ('REI', (/ 'lev' /), 'A', 'micron', 'MG REI stratiform cloud effective radius ice' ) - call addfld ('LS_REFFRAIN', (/ 'lev' /), 'A', 'micron', 'ls stratiform rain effective radius' ) - call addfld ('LS_REFFSNOW', (/ 'lev' /), 'A', 'micron', 'ls stratiform snow effective radius' ) - call addfld ('CV_REFFLIQ', (/ 'lev' /), 'A', 'micron', 'convective cloud liq effective radius' ) - call addfld ('CV_REFFICE', (/ 'lev' /), 'A', 'micron', 'convective cloud ice effective radius' ) - call addfld ('MG_SADICE', (/ 'lev' /), 'A', 'cm2/cm3', 'MG surface area density ice' ) - call addfld ('MG_SADSNOW', (/ 'lev' /), 'A', 'cm2/cm3', 'MG surface area density snow' ) + call addfld ('FREQM', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of mixed phase', sampled_on_subcycle=.true.) + call addfld ('FREQSL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of only supercooled liquid', sampled_on_subcycle=.true.) + call addfld ('FREQSLM', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of super cooled liquid with ice', sampled_on_subcycle=.true.) + call addfld ('FCTM', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top mixed phase', sampled_on_subcycle=.true.) + call addfld ('FCTSL', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top only supercooled liquid', sampled_on_subcycle=.true.) + call addfld ('FCTSLM', horiz_only, 'A', 'fraction', 'Fractional occurrence of cloud top super cooled liquid with ice', sampled_on_subcycle=.true.) + + call addfld ('LS_FLXPRC', (/ 'ilev' /), 'A', 'kg/m2/s', 'ls stratiform gbm interface rain+snow flux', sampled_on_subcycle=.true.) + call addfld ('LS_FLXSNW', (/ 'ilev' /), 'A', 'kg/m2/s', 'ls stratiform gbm interface snow flux', sampled_on_subcycle=.true.) + + call addfld ('REL', (/ 'lev' /), 'A', 'micron', 'MG REL stratiform cloud effective radius liquid', sampled_on_subcycle=.true.) + call addfld ('REI', (/ 'lev' /), 'A', 'micron', 'MG REI stratiform cloud effective radius ice', sampled_on_subcycle=.true.) + call addfld ('LS_REFFRAIN', (/ 'lev' /), 'A', 'micron', 'ls stratiform rain effective radius', sampled_on_subcycle=.true.) + call addfld ('LS_REFFSNOW', (/ 'lev' /), 'A', 'micron', 'ls stratiform snow effective radius', sampled_on_subcycle=.true.) + call addfld ('CV_REFFLIQ', (/ 'lev' /), 'A', 'micron', 'convective cloud liq effective radius', sampled_on_subcycle=.true.) + call addfld ('CV_REFFICE', (/ 'lev' /), 'A', 'micron', 'convective cloud ice effective radius', sampled_on_subcycle=.true.) + call addfld ('MG_SADICE', (/ 'lev' /), 'A', 'cm2/cm3', 'MG surface area density ice', sampled_on_subcycle=.true.) + call addfld ('MG_SADSNOW', (/ 'lev' /), 'A', 'cm2/cm3', 'MG surface area density snow', sampled_on_subcycle=.true.) ! diagnostic precip - call addfld ('QRAIN', (/ 'lev' /), 'A', 'kg/kg', 'Diagnostic grid-mean rain mixing ratio' ) - call addfld ('QSNOW', (/ 'lev' /), 'A', 'kg/kg', 'Diagnostic grid-mean snow mixing ratio' ) - call addfld ('NRAIN', (/ 'lev' /), 'A', 'm-3', 'Diagnostic grid-mean rain number conc' ) - call addfld ('NSNOW', (/ 'lev' /), 'A', 'm-3', 'Diagnostic grid-mean snow number conc' ) + call addfld ('QRAIN', (/ 'lev' /), 'A', 'kg/kg', 'Diagnostic grid-mean rain mixing ratio', sampled_on_subcycle=.true.) + call addfld ('QSNOW', (/ 'lev' /), 'A', 'kg/kg', 'Diagnostic grid-mean snow mixing ratio', sampled_on_subcycle=.true.) + call addfld ('NRAIN', (/ 'lev' /), 'A', 'm-3', 'Diagnostic grid-mean rain number conc', sampled_on_subcycle=.true.) + call addfld ('NSNOW', (/ 'lev' /), 'A', 'm-3', 'Diagnostic grid-mean snow number conc', sampled_on_subcycle=.true.) ! size of precip - call addfld ('RERCLD', (/ 'lev' /), 'A', 'm', 'Diagnostic effective radius of Liquid Cloud and Rain' ) - call addfld ('DSNOW', (/ 'lev' /), 'A', 'm', 'Diagnostic grid-mean snow diameter' ) + call addfld ('RERCLD', (/ 'lev' /), 'A', 'm', 'Diagnostic effective radius of Liquid Cloud and Rain', sampled_on_subcycle=.true.) + call addfld ('DSNOW', (/ 'lev' /), 'A', 'm', 'Diagnostic grid-mean snow diameter', sampled_on_subcycle=.true.) ! diagnostic radar reflectivity, cloud-averaged - call addfld ('REFL', (/ 'lev' /), 'A', 'DBz', '94 GHz radar reflectivity' ) - call addfld ('AREFL', (/ 'lev' /), 'A', 'DBz', 'Average 94 GHz radar reflectivity' ) - call addfld ('FREFL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of radar reflectivity' ) + call addfld ('REFL', (/ 'lev' /), 'A', 'DBz', '94 GHz radar reflectivity', sampled_on_subcycle=.true.) + call addfld ('AREFL', (/ 'lev' /), 'A', 'DBz', 'Average 94 GHz radar reflectivity', sampled_on_subcycle=.true.) + call addfld ('FREFL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of radar reflectivity', sampled_on_subcycle=.true.) - call addfld ('CSRFL', (/ 'lev' /), 'A', 'DBz', '94 GHz radar reflectivity (CloudSat thresholds)' ) - call addfld ('ACSRFL', (/ 'lev' /), 'A', 'DBz', 'Average 94 GHz radar reflectivity (CloudSat thresholds)' ) - call addfld ('FCSRFL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of radar reflectivity (CloudSat thresholds)' ) + call addfld ('CSRFL', (/ 'lev' /), 'A', 'DBz', '94 GHz radar reflectivity (CloudSat thresholds)', sampled_on_subcycle=.true.) + call addfld ('ACSRFL', (/ 'lev' /), 'A', 'DBz', 'Average 94 GHz radar reflectivity (CloudSat thresholds)', sampled_on_subcycle=.true.) + call addfld ('FCSRFL', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of radar reflectivity (CloudSat thresholds)', sampled_on_subcycle=.true.) - call addfld ('AREFLZ', (/ 'lev' /), 'A', 'mm^6/m^3', 'Average 94 GHz radar reflectivity' ) + call addfld ('AREFLZ', (/ 'lev' /), 'A', 'mm^6/m^3', 'Average 94 GHz radar reflectivity', sampled_on_subcycle=.true.) ! 10cm (rain) radar reflectivity - call addfld ('REFL10CM', (/ 'lev' /), 'A', 'DBz', '10cm (Rain) radar reflectivity (Dbz)' ) - call addfld ('REFLZ10CM', (/ 'lev' /), 'A', 'mm^6/m^3', '10cm (Rain) radar reflectivity (Z units)' ) + call addfld ('REFL10CM', (/ 'lev' /), 'A', 'DBz', '10cm (Rain) radar reflectivity (Dbz)', sampled_on_subcycle=.true.) + call addfld ('REFLZ10CM', (/ 'lev' /), 'A', 'mm^6/m^3', '10cm (Rain) radar reflectivity (Z units)', sampled_on_subcycle=.true.) ! Aerosol information - call addfld ('NCAL', (/ 'lev' /), 'A', '1/m3', 'Number Concentation Activated for Liquid' ) - call addfld ('NCAI', (/ 'lev' /), 'A', '1/m3', 'Number Concentation Activated for Ice' ) + call addfld ('NCAL', (/ 'lev' /), 'A', '1/m3', 'Number Concentation Activated for Liquid', sampled_on_subcycle=.true.) + call addfld ('NCAI', (/ 'lev' /), 'A', '1/m3', 'Number Concentation Activated for Ice', sampled_on_subcycle=.true.) ! Average rain and snow mixing ratio (Q), number (N) and diameter (D), with frequency - call addfld ('AQRAIN', (/ 'lev' /), 'A', 'kg/kg', 'Average rain mixing ratio' ) - call addfld ('AQSNOW', (/ 'lev' /), 'A', 'kg/kg', 'Average snow mixing ratio' ) - call addfld ('ANRAIN', (/ 'lev' /), 'A', 'm-3', 'Average rain number conc' ) - call addfld ('ANSNOW', (/ 'lev' /), 'A', 'm-3', 'Average snow number conc' ) - call addfld ('ADRAIN', (/ 'lev' /), 'A', 'm', 'Average rain effective Diameter' ) - call addfld ('ADSNOW', (/ 'lev' /), 'A', 'm', 'Average snow effective Diameter' ) - call addfld ('FREQR', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of rain' ) - call addfld ('FREQS', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of snow' ) + call addfld ('AQRAIN', (/ 'lev' /), 'A', 'kg/kg', 'Average rain mixing ratio', sampled_on_subcycle=.true.) + call addfld ('AQSNOW', (/ 'lev' /), 'A', 'kg/kg', 'Average snow mixing ratio', sampled_on_subcycle=.true.) + call addfld ('ANRAIN', (/ 'lev' /), 'A', 'm-3', 'Average rain number conc', sampled_on_subcycle=.true.) + call addfld ('ANSNOW', (/ 'lev' /), 'A', 'm-3', 'Average snow number conc', sampled_on_subcycle=.true.) + call addfld ('ADRAIN', (/ 'lev' /), 'A', 'm', 'Average rain effective Diameter', sampled_on_subcycle=.true.) + call addfld ('ADSNOW', (/ 'lev' /), 'A', 'm', 'Average snow effective Diameter', sampled_on_subcycle=.true.) + call addfld ('FREQR', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of rain', sampled_on_subcycle=.true.) + call addfld ('FREQS', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of snow', sampled_on_subcycle=.true.) ! precipitation efficiency & other diagnostic fields - call addfld('PE' , horiz_only, 'A', '1', 'Stratiform Precipitation Efficiency (precip/cmeliq)' ) - call addfld('APRL' , horiz_only, 'A', 'm/s', 'Average Stratiform Precip Rate over efficiency calculation' ) - call addfld('PEFRAC', horiz_only, 'A', '1', 'Fraction of timesteps precip efficiency reported' ) - call addfld('VPRCO' , horiz_only, 'A', 'kg/kg/s', 'Vertical average of autoconversion rate' ) - call addfld('VPRAO' , horiz_only, 'A', 'kg/kg/s', 'Vertical average of accretion rate' ) - call addfld('RACAU' , horiz_only, 'A', 'kg/kg/s', 'Accretion/autoconversion ratio from vertical average' ) + call addfld('PE' , horiz_only, 'A', '1', 'Stratiform Precipitation Efficiency (precip/cmeliq)', sampled_on_subcycle=.true.) + call addfld('APRL' , horiz_only, 'A', 'm/s', 'Average Stratiform Precip Rate over efficiency calculation', sampled_on_subcycle=.true.) + call addfld('PEFRAC', horiz_only, 'A', '1', 'Fraction of timesteps precip efficiency reported', sampled_on_subcycle=.true.) + call addfld('VPRCO' , horiz_only, 'A', 'kg/kg/s', 'Vertical average of autoconversion rate', sampled_on_subcycle=.true.) + call addfld('VPRAO' , horiz_only, 'A', 'kg/kg/s', 'Vertical average of accretion rate', sampled_on_subcycle=.true.) + call addfld('RACAU' , horiz_only, 'A', 'kg/kg/s', 'Accretion/autoconversion ratio from vertical average', sampled_on_subcycle=.true.) - call addfld('UMR', (/ 'trop_cld_lev' /), 'A', 'm/s', 'Mass-weighted rain fallspeed' ) - call addfld('UMS', (/ 'trop_cld_lev' /), 'A', 'm/s', 'Mass-weighted snow fallspeed' ) + call addfld('UMR', (/ 'trop_cld_lev' /), 'A', 'm/s', 'Mass-weighted rain fallspeed', sampled_on_subcycle=.true.) + call addfld('UMS', (/ 'trop_cld_lev' /), 'A', 'm/s', 'Mass-weighted snow fallspeed', sampled_on_subcycle=.true.) if (micro_mg_version > 2) then - call addfld('UMG', (/ 'trop_cld_lev' /), 'A', 'm/s', 'Mass-weighted graupel/hail fallspeed' ) - call addfld ('FREQG', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of Graupel' ) - call addfld ('LS_REFFGRAU', (/ 'lev' /), 'A', 'micron', 'ls stratiform graupel/hail effective radius' ) - call addfld ('AQGRAU', (/ 'lev' /), 'A', 'kg/kg', 'Average graupel/hail mixing ratio' ) - call addfld ('ANGRAU', (/ 'lev' /), 'A', 'm-3', 'Average graupel/hail number conc' ) + call addfld('UMG', (/ 'trop_cld_lev' /), 'A', 'm/s', 'Mass-weighted graupel/hail fallspeed', sampled_on_subcycle=.true.) + call addfld ('FREQG', (/ 'lev' /), 'A', 'fraction', 'Fractional occurrence of Graupel', sampled_on_subcycle=.true.) + call addfld ('LS_REFFGRAU', (/ 'lev' /), 'A', 'micron', 'ls stratiform graupel/hail effective radius', sampled_on_subcycle=.true.) + call addfld ('AQGRAU', (/ 'lev' /), 'A', 'kg/kg', 'Average graupel/hail mixing ratio', sampled_on_subcycle=.true.) + call addfld ('ANGRAU', (/ 'lev' /), 'A', 'm-3', 'Average graupel/hail number conc', sampled_on_subcycle=.true.) end if ! qc limiter (only output in versions 1.5 and later) - call addfld('QCRAT', (/ 'lev' /), 'A', 'fraction', 'Qc Limiter: Fraction of qc tendency applied') + call addfld('QCRAT', (/ 'lev' /), 'A', 'fraction', 'Qc Limiter: Fraction of qc tendency applied', sampled_on_subcycle=.true.) ! determine the add_default fields call phys_getopts(history_amwg_out = history_amwg , & diff --git a/src/physics/cam7/stochastic_emulated_cam.F90 b/src/physics/cam7/stochastic_emulated_cam.F90 index 8fbc9e44a1..1433c940e3 100644 --- a/src/physics/cam7/stochastic_emulated_cam.F90 +++ b/src/physics/cam7/stochastic_emulated_cam.F90 @@ -85,44 +85,44 @@ subroutine stochastic_emulated_init_cam(stochastic_emulated_filename_quantile_ou call add_hist_coord('bins_ncd', ncd, 'bins for TAU microphysics') - call addfld('amk_c',(/'trop_cld_lev','bins_ncd '/),'A','kg','cloud liquid mass from bins') - call addfld('ank_c',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','cloud liquid number concentration from bins') - call addfld('amk_r',(/'trop_cld_lev','bins_ncd '/),'A','kg','rain mass from bins') - call addfld('ank_r',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','rain number concentration from bins') - call addfld('amk',(/'trop_cld_lev','bins_ncd '/),'A','kg','all liquid mass from bins') - call addfld('ank',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','all liquid number concentration from bins') - call addfld('amk_out',(/'trop_cld_lev','bins_ncd '/),'A','kg','all liquid mass from bins') - call addfld('ank_out',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','all liquid number concentration from bins') - - call addfld('scale_nc',(/'trop_cld_lev'/),'A','1','scaling factor for nc') - call addfld('scale_nr',(/'trop_cld_lev'/),'A','1','scaling factor for nr') - call addfld('scale_qc',(/'trop_cld_lev'/),'A','1','scaling factor for qc') - call addfld('scale_qr',(/'trop_cld_lev'/),'A','1','scaling factor for qr') + call addfld('amk_c',(/'trop_cld_lev','bins_ncd '/),'A','kg','cloud liquid mass from bins', sampled_on_subcycle=.true.) + call addfld('ank_c',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','cloud liquid number concentration from bins',sampled_on_subcycle=.true.) + call addfld('amk_r',(/'trop_cld_lev','bins_ncd '/),'A','kg','rain mass from bins', sampled_on_subcycle=.true.) + call addfld('ank_r',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','rain number concentration from bins', sampled_on_subcycle=.true.) + call addfld('amk',(/'trop_cld_lev','bins_ncd '/),'A','kg','all liquid mass from bins', sampled_on_subcycle=.true.) + call addfld('ank',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','all liquid number concentration from bins', sampled_on_subcycle=.true.) + call addfld('amk_out',(/'trop_cld_lev','bins_ncd '/),'A','kg','all liquid mass from bins', sampled_on_subcycle=.true.) + call addfld('ank_out',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','all liquid number concentration from bins',sampled_on_subcycle=.true.) + + call addfld('scale_nc',(/'trop_cld_lev'/),'A','1','scaling factor for nc', sampled_on_subcycle=.true.) + call addfld('scale_nr',(/'trop_cld_lev'/),'A','1','scaling factor for nr', sampled_on_subcycle=.true.) + call addfld('scale_qc',(/'trop_cld_lev'/),'A','1','scaling factor for qc', sampled_on_subcycle=.true.) + call addfld('scale_qr',(/'trop_cld_lev'/),'A','1','scaling factor for qr', sampled_on_subcycle=.true.) - call addfld('QC_TAU_in',(/'trop_cld_lev'/),'A','kg/kg','qc in TAU') - call addfld('NC_TAU_in',(/'trop_cld_lev'/),'A','1/kg','nc in TAU') - call addfld('QR_TAU_in',(/'trop_cld_lev'/),'A','kg/kg','qr in TAU') - call addfld('NR_TAU_in',(/'trop_cld_lev'/),'A','1/kg','nr in TAU') - call addfld('QC_TAU_out',(/'trop_cld_lev'/),'A','kg/kg','qc out TAU') - call addfld('NC_TAU_out',(/'trop_cld_lev'/),'A','1/kg','nc out TAU') - call addfld('QR_TAU_out',(/'trop_cld_lev'/),'A','kg/kg','qr out TAU') - call addfld('NR_TAU_out',(/'trop_cld_lev'/),'A','1/kg','nr out TAU') + call addfld('QC_TAU_in',(/'trop_cld_lev'/),'A','kg/kg','qc in TAU', sampled_on_subcycle=.true.) + call addfld('NC_TAU_in',(/'trop_cld_lev'/),'A','1/kg','nc in TAU', sampled_on_subcycle=.true.) + call addfld('QR_TAU_in',(/'trop_cld_lev'/),'A','kg/kg','qr in TAU', sampled_on_subcycle=.true.) + call addfld('NR_TAU_in',(/'trop_cld_lev'/),'A','1/kg','nr in TAU', sampled_on_subcycle=.true.) + call addfld('QC_TAU_out',(/'trop_cld_lev'/),'A','kg/kg','qc out TAU', sampled_on_subcycle=.true.) + call addfld('NC_TAU_out',(/'trop_cld_lev'/),'A','1/kg','nc out TAU', sampled_on_subcycle=.true.) + call addfld('QR_TAU_out',(/'trop_cld_lev'/),'A','kg/kg','qr out TAU', sampled_on_subcycle=.true.) + call addfld('NR_TAU_out',(/'trop_cld_lev'/),'A','1/kg','nr out TAU', sampled_on_subcycle=.true.) - call addfld('qctend_TAU',(/'trop_cld_lev'/),'A','kg/kg/s','qc tendency due to TAU bin code') - call addfld('nctend_TAU',(/'trop_cld_lev'/),'A','1/kg/s','nc tendency due to TAU bin code') - call addfld('qrtend_TAU',(/'trop_cld_lev'/),'A','kg/kg/s','qr tendency due to TAU bin code') - call addfld('nrtend_TAU',(/'trop_cld_lev'/),'A','1/kg/s','nr tendency due to TAU bin code') - call addfld('qctend_TAU_diag',(/'trop_cld_lev'/),'A','kg/kg/s','qc tendency due to TAU bin code') - call addfld('nctend_TAU_diag',(/'trop_cld_lev'/),'A','1/kg/s','nc tendency due to TAU bin code') - call addfld('qrtend_TAU_diag',(/'trop_cld_lev'/),'A','kg/kg/s','qr tendency due to TAU bin code') - call addfld('nrtend_TAU_diag',(/'trop_cld_lev'/),'A','1/kg/s','nr tendency due to TAU bin code') - - call addfld('gmnnn_lmnnn_TAU',(/'trop_cld_lev'/),'A','1','sum of mass gain and loss from bin code') - call addfld('ML_fixer',(/'trop_cld_lev'/),'A','1','frequency that ML fixer is activated') - call addfld('qc_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta qc due to ML fixer') - call addfld('nc_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta nc due to ML fixer') - call addfld('qr_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta qr due to ML fixer') - call addfld('nr_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta nr due to ML fixer') + call addfld('qctend_TAU',(/'trop_cld_lev'/),'A','kg/kg/s','qc tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('nctend_TAU',(/'trop_cld_lev'/),'A','1/kg/s','nc tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('qrtend_TAU',(/'trop_cld_lev'/),'A','kg/kg/s','qr tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('nrtend_TAU',(/'trop_cld_lev'/),'A','1/kg/s','nr tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('qctend_TAU_diag',(/'trop_cld_lev'/),'A','kg/kg/s','qc tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('nctend_TAU_diag',(/'trop_cld_lev'/),'A','1/kg/s','nc tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('qrtend_TAU_diag',(/'trop_cld_lev'/),'A','kg/kg/s','qr tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('nrtend_TAU_diag',(/'trop_cld_lev'/),'A','1/kg/s','nr tendency due to TAU bin code', sampled_on_subcycle=.true.) + + call addfld('gmnnn_lmnnn_TAU',(/'trop_cld_lev'/),'A','1','sum of mass gain and loss from bin code', sampled_on_subcycle=.true.) + call addfld('ML_fixer',(/'trop_cld_lev'/),'A','1','frequency that ML fixer is activated', sampled_on_subcycle=.true.) + call addfld('qc_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta qc due to ML fixer', sampled_on_subcycle=.true.) + call addfld('nc_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta nc due to ML fixer', sampled_on_subcycle=.true.) + call addfld('qr_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta qr due to ML fixer', sampled_on_subcycle=.true.) + call addfld('nr_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta nr due to ML fixer', sampled_on_subcycle=.true.) stochastic_emulated_filename_quantile_out = stochastic_emulated_filename_quantile stochastic_emulated_filename_input_scale_out = stochastic_emulated_filename_input_scale diff --git a/src/physics/cam7/stochastic_tau_cam.F90 b/src/physics/cam7/stochastic_tau_cam.F90 index b305201e7c..0cea0201a0 100644 --- a/src/physics/cam7/stochastic_tau_cam.F90 +++ b/src/physics/cam7/stochastic_tau_cam.F90 @@ -72,44 +72,44 @@ subroutine stochastic_tau_init_cam call add_hist_coord('bins_ncd', ncd, 'bins for TAU microphysics') !Note: lev needs to be trop_cld_lev for proc_rates.... - call addfld('amk_c',(/'trop_cld_lev','bins_ncd '/),'A','kg','cloud liquid mass from bins') - call addfld('ank_c',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','cloud liquid number concentration from bins') - call addfld('amk_r',(/'trop_cld_lev','bins_ncd '/),'A','kg','rain mass from bins') - call addfld('ank_r',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','rain number concentration from bins') - call addfld('amk',(/'trop_cld_lev','bins_ncd '/),'A','kg','all liquid mass from bins') - call addfld('ank',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','all liquid number concentration from bins') - call addfld('amk_out',(/'trop_cld_lev','bins_ncd '/),'A','kg','all liquid mass from bins') - call addfld('ank_out',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','all liquid number concentration from bins') - - call addfld('scale_nc',(/'trop_cld_lev'/),'A','1','scaling factor for nc') - call addfld('scale_nr',(/'trop_cld_lev'/),'A','1','scaling factor for nr') - call addfld('scale_qc',(/'trop_cld_lev'/),'A','1','scaling factor for qc') - call addfld('scale_qr',(/'trop_cld_lev'/),'A','1','scaling factor for qr') + call addfld('amk_c',(/'trop_cld_lev','bins_ncd '/),'A','kg','cloud liquid mass from bins', sampled_on_subcycle=.true.) + call addfld('ank_c',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','cloud liquid number concentration from bins', sampled_on_subcycle=.true.) + call addfld('amk_r',(/'trop_cld_lev','bins_ncd '/),'A','kg','rain mass from bins', sampled_on_subcycle=.true.) + call addfld('ank_r',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','rain number concentration from bins', sampled_on_subcycle=.true.) + call addfld('amk',(/'trop_cld_lev','bins_ncd '/),'A','kg','all liquid mass from bins', sampled_on_subcycle=.true.) + call addfld('ank',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','all liquid number concentration from bins', sampled_on_subcycle=.true.) + call addfld('amk_out',(/'trop_cld_lev','bins_ncd '/),'A','kg','all liquid mass from bins', sampled_on_subcycle=.true.) + call addfld('ank_out',(/'trop_cld_lev','bins_ncd '/),'A','1/kg','all liquid number concentration from bins', sampled_on_subcycle=.true.) + + call addfld('scale_nc',(/'trop_cld_lev'/),'A','1','scaling factor for nc', sampled_on_subcycle=.true.) + call addfld('scale_nr',(/'trop_cld_lev'/),'A','1','scaling factor for nr', sampled_on_subcycle=.true.) + call addfld('scale_qc',(/'trop_cld_lev'/),'A','1','scaling factor for qc', sampled_on_subcycle=.true.) + call addfld('scale_qr',(/'trop_cld_lev'/),'A','1','scaling factor for qr', sampled_on_subcycle=.true.) - call addfld('QC_TAU_in',(/'trop_cld_lev'/),'A','kg/kg','qc in TAU') - call addfld('NC_TAU_in',(/'trop_cld_lev'/),'A','1/kg','nc in TAU') - call addfld('QR_TAU_in',(/'trop_cld_lev'/),'A','kg/kg','qr in TAU') - call addfld('NR_TAU_in',(/'trop_cld_lev'/),'A','1/kg','nr in TAU') - call addfld('QC_TAU_out',(/'trop_cld_lev'/),'A','kg/kg','qc out TAU') - call addfld('NC_TAU_out',(/'trop_cld_lev'/),'A','1/kg','nc out TAU') - call addfld('QR_TAU_out',(/'trop_cld_lev'/),'A','kg/kg','qr out TAU') - call addfld('NR_TAU_out',(/'trop_cld_lev'/),'A','1/kg','nr out TAU') + call addfld('QC_TAU_in',(/'trop_cld_lev'/),'A','kg/kg','qc in TAU', sampled_on_subcycle=.true.) + call addfld('NC_TAU_in',(/'trop_cld_lev'/),'A','1/kg','nc in TAU', sampled_on_subcycle=.true.) + call addfld('QR_TAU_in',(/'trop_cld_lev'/),'A','kg/kg','qr in TAU', sampled_on_subcycle=.true.) + call addfld('NR_TAU_in',(/'trop_cld_lev'/),'A','1/kg','nr in TAU', sampled_on_subcycle=.true.) + call addfld('QC_TAU_out',(/'trop_cld_lev'/),'A','kg/kg','qc out TAU', sampled_on_subcycle=.true.) + call addfld('NC_TAU_out',(/'trop_cld_lev'/),'A','1/kg','nc out TAU', sampled_on_subcycle=.true.) + call addfld('QR_TAU_out',(/'trop_cld_lev'/),'A','kg/kg','qr out TAU', sampled_on_subcycle=.true.) + call addfld('NR_TAU_out',(/'trop_cld_lev'/),'A','1/kg','nr out TAU', sampled_on_subcycle=.true.) - call addfld('qctend_TAU',(/'trop_cld_lev'/),'A','kg/kg/s','qc tendency due to TAU bin code') - call addfld('nctend_TAU',(/'trop_cld_lev'/),'A','1/kg/s','nc tendency due to TAU bin code') - call addfld('qrtend_TAU',(/'trop_cld_lev'/),'A','kg/kg/s','qr tendency due to TAU bin code') - call addfld('nrtend_TAU',(/'trop_cld_lev'/),'A','1/kg/s','nr tendency due to TAU bin code') - call addfld('qctend_TAU_diag',(/'trop_cld_lev'/),'A','kg/kg/s','qc tendency due to TAU bin code') - call addfld('nctend_TAU_diag',(/'trop_cld_lev'/),'A','1/kg/s','nc tendency due to TAU bin code') - call addfld('qrtend_TAU_diag',(/'trop_cld_lev'/),'A','kg/kg/s','qr tendency due to TAU bin code') - call addfld('nrtend_TAU_diag',(/'trop_cld_lev'/),'A','1/kg/s','nr tendency due to TAU bin code') - - call addfld('gmnnn_lmnnn_TAU',(/'trop_cld_lev'/),'A','1','sum of mass gain and loss from bin code') - call addfld('ML_fixer',(/'trop_cld_lev'/),'A','1','frequency that ML fixer is activated') - call addfld('qc_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta qc due to ML fixer') - call addfld('nc_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta nc due to ML fixer') - call addfld('qr_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta qr due to ML fixer') - call addfld('nr_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta nr due to ML fixer') + call addfld('qctend_TAU',(/'trop_cld_lev'/),'A','kg/kg/s','qc tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('nctend_TAU',(/'trop_cld_lev'/),'A','1/kg/s','nc tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('qrtend_TAU',(/'trop_cld_lev'/),'A','kg/kg/s','qr tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('nrtend_TAU',(/'trop_cld_lev'/),'A','1/kg/s','nr tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('qctend_TAU_diag',(/'trop_cld_lev'/),'A','kg/kg/s','qc tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('nctend_TAU_diag',(/'trop_cld_lev'/),'A','1/kg/s','nc tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('qrtend_TAU_diag',(/'trop_cld_lev'/),'A','kg/kg/s','qr tendency due to TAU bin code', sampled_on_subcycle=.true.) + call addfld('nrtend_TAU_diag',(/'trop_cld_lev'/),'A','1/kg/s','nr tendency due to TAU bin code', sampled_on_subcycle=.true.) + + call addfld('gmnnn_lmnnn_TAU',(/'trop_cld_lev'/),'A','1','sum of mass gain and loss from bin code', sampled_on_subcycle=.true.) + call addfld('ML_fixer',(/'trop_cld_lev'/),'A','1','frequency that ML fixer is activated', sampled_on_subcycle=.true.) + call addfld('qc_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta qc due to ML fixer', sampled_on_subcycle=.true.) + call addfld('nc_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta nc due to ML fixer', sampled_on_subcycle=.true.) + call addfld('qr_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta qr due to ML fixer', sampled_on_subcycle=.true.) + call addfld('nr_fixer',(/'trop_cld_lev'/),'A','kg/kg','delta nr due to ML fixer', sampled_on_subcycle=.true.) end subroutine stochastic_tau_init_cam end module stochastic_tau_cam From 37430e150d1d820e993fa7f306a20c4221fa7c2e Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Fri, 11 Oct 2024 22:28:41 -0600 Subject: [PATCH 11/82] Manually merging in changes from ew-develop --- src/physics/cam/clubb_intr.F90 | 37 +++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 9bbf211fba..6b22d53953 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2602,10 +2602,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! MAIN COMPUTATION BEGINS HERE ! !-----------------------------------------------------------------------------------! - call t_startf("clubb_tend_cam") nlev = pver + 1 - top_lev + call t_startf('clubb_tend_cam:NAR') rtp2_zt_out = 0._r8 thl2_zt_out = 0._r8 wp2_zt_out = 0._r8 @@ -2781,6 +2781,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call grid_size(state1, grid_dx, grid_dy) + call t_stopf('clubb_tend_cam:NAR') + if (clubb_do_icesuper) then ! -------------------------------------- ! @@ -2801,11 +2803,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & qitend(:ncol,:)=0._r8 initend(:ncol,:)=0._r8 + call t_startf('clubb_tend_cam:ice_macro_tend') call ice_macro_tend(naai(1:ncol,top_lev:pver), state1%t(1:ncol,top_lev:pver), & state1%pmid(1:ncol,top_lev:pver), state1%q(1:ncol,top_lev:pver,1), & state1%q(1:ncol,top_lev:pver,ixcldice), state1%q(1:ncol,top_lev:pver,ixnumice), & latsub, hdtime, stend(1:ncol,top_lev:pver), qvtend(1:ncol,top_lev:pver), & qitend(1:ncol,top_lev:pver), initend(1:ncol,top_lev:pver), ncol*(pver-top_lev+1)) + call t_stopf('clubb_tend_cam:ice_macro_tend') ! update local copy of state with the tendencies ptend_loc%q(:ncol,top_lev:pver,1)=qvtend(:ncol,top_lev:pver) @@ -2827,6 +2831,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'NITENDICE', initend, pcols, lchnk ) endif + call t_startf('clubb_tend_cam:NAR') ! Determine CLUBB time step and make it sub-step friendly @@ -2991,7 +2996,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & mf_qtflx_output(:,:) = 0._r8 end if - call t_startf("clubb_tend_cam_i_loop") ! Determine Coriolis force at given latitude. This is never used ! when CLUBB is implemented in a host model, therefore just set @@ -3234,7 +3238,9 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Perturbed winds are not used in CAM upwp_sfc_pert = 0.0_r8 vpwp_sfc_pert = 0.0_r8 + call t_stopf('clubb_tend_cam:NAR') + call t_startf('clubb_tend_cam:flip-index') ! Need to flip arrays around for CLUBB core do k=1,nlev+1 do i=1,ncol @@ -3448,6 +3454,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (macmic_it==1) vpwp_clubb_gw_mc(:ncol,:) = 0._r8 if (macmic_it==1) thlp2_clubb_gw_mc(:ncol,:) = 0._r8 if (macmic_it==1) wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 + call t_stopf('clubb_tend_cam:flip-index') do t=1,nadv ! do needed number of "sub" timesteps for each CAM step @@ -3461,6 +3468,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !###################### CALL MF DIAGNOSTIC PLUMES ###################### !####################################################################### if (do_clubb_mf) then + call t_startf('clubb_tend_cam:do_clubb_mf') do k=2,pverp do i=1, ncol @@ -3511,10 +3519,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ((rho_ds_zm(i,k) * mf_thlflx(i,k)) - (rho_ds_zm(i,k-1) * mf_thlflx(i,k-1))) end do end do + call t_stopf('clubb_tend_cam:do_clubb_mf') end if ! Advance CLUBB CORE one timestep in the future + call t_startf('clubb_tend_cam:advance_clubb_core_api') call advance_clubb_core_api( gr, pverp+1-top_lev, ncol, & l_implemented, dtime, fcor, sfc_elevation, & hydromet_dim, & @@ -3559,6 +3569,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wprcp_out, w_up_in_cloud_out, w_down_in_cloud_out, & cloudy_updraft_frac_out, cloudy_downdraft_frac_out, & rcm_in_layer_out, cloud_cover_out, invrs_tau_zm_out ) + call t_stopf('clubb_tend_cam:advance_clubb_core_api') ! Note that CLUBB does not produce an error code specific to any column, and ! one value only for the entire chunk @@ -3582,12 +3593,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + call t_startf('clubb_tend_cam:update_xp2_mc_api') call update_xp2_mc_api( gr, nlev+1, ncol, dtime, cloud_frac_inout, & rcm_inout, rvm_in, thlm_in, wm_zt, & exner, pre_in, pdf_params_chnk(lchnk), & rtp2_mc_out, thlp2_mc_out, & wprtp_mc_out, wpthlp_mc_out, & rtpthlp_mc_out) + call t_stopf('clubb_tend_cam:update_xp2_mc_api') do k=1,nlev+1 do i=1,ncol @@ -3605,6 +3618,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (do_cldcool) then + call t_startf('clubb_tend_cam:do_cldcool') rcm_out_zm = zt2zm_api(pverp+1-top_lev, ncol, gr, rcm_inout ) qrl_zm = zt2zm_api(pverp+1-top_lev, ncol, gr, qrl_clubb ) @@ -3619,19 +3633,23 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & thlp2_in(i,:) = thlp2_in(i,:) + thlp2_rad_out(i,:) * dtime thlp2_in(i,:) = max(thl_tol**2,thlp2_in(i,:)) end do + call t_stopf('clubb_tend_cam:do_cldcool') end if ! Check to see if stats should be output, here stats are read into ! output arrays to make them conformable to CAM output if (stats_metadata%l_stats) then + call t_startf('clubb_tend_cam:stats_end_timestep_clubb') do i=1, ncol call stats_end_timestep_clubb(i, stats_zt(i), stats_zm(i), stats_rad_zt(i), stats_rad_zm(i), stats_sfc(i), & out_zt, out_zm, out_radzt, out_radzm, out_sfc) end do + call t_stopf('clubb_tend_cam:stats_end_timestep_clubb') end if enddo ! end time loop + call t_startf('clubb_tend_cam:NAR') if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then @@ -3657,12 +3675,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end if + call t_stopf('clubb_tend_cam:NAR') ! Convert RTP2 and THLP2 to thermo grid for output + call t_startf('clubb_tend_cam:NAR') rtp2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, rtp2_in ) thl2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, thlp2_in ) wp2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, wp2_in ) + call t_stopf('clubb_tend_cam:NAR') + call t_startf('clubb_tend_cam:flip-index') ! Arrays need to be "flipped" to CAM grid do k=1, nlev+1 do i=1, ncol @@ -3722,6 +3744,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + call t_stopf('clubb_tend_cam:flip-index') + call t_startf('clubb_tend_cam:NAR') ! Accumulate vars through macmic subcycle upwp_clubb_gw_mc(:ncol,:) = upwp_clubb_gw_mc(:ncol,:) + upwp(:ncol,:) @@ -4021,7 +4045,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end do - call t_stopf("clubb_tend_cam_i_loop") call outfld('KVH_CLUBB', khzm, pcols, lchnk) @@ -4068,9 +4091,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! then advances it's predictive equations second, this can lead to ! RHliq > 1 directly before microphysics is called. Therefore, we use ! ice_macro_tend to enforce RHliq <= 1 everywhere before microphysics is called. + call t_stopf('clubb_tend_cam:NAR') if (clubb_do_liqsupersat) then + call t_startf('clubb_cam_tend:do_liqsupersat') ! -------------------------------------- ! ! Ice Saturation Adjustment Computation ! ! -------------------------------------- ! @@ -4122,7 +4147,9 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end where call outfld( 'FQTENDICE', fqtend, pcols, lchnk ) + call t_stopf('clubb_cam_tend:do_liqsupersat') end if + call t_startf('clubb_tend_cam:NAR') ! ------------------------------------------------------------ ! ! The rest of the code deals with diagnosing variables ! @@ -4547,8 +4574,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo endif - - call t_stopf("clubb_tend_cam") + call t_stopf('clubb_tend_cam:NAR') + return #endif From 94275055d5275b8ea2f1d6a8ea06242992dd3b66 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Sat, 12 Oct 2024 10:40:58 -0600 Subject: [PATCH 12/82] Adding acc data statement outside substepping loop and preventing some options from running when compiled with OpenACC --- src/physics/cam/clubb_intr.F90 | 102 +++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 6b22d53953..4b30e503ac 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2598,6 +2598,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & #ifdef CLUBB_SGS +#ifdef _OPENACC + ! These options have not been GPUized + if ( do_clubb_mf ) call endrun(subr//': do_clubb_mf=.true. not available when compiling with OpenACC') + if ( do_rainturb ) call endrun(subr//': do_rainturb=.true. not available when compiling with OpenACC') + if ( do_cldcool ) call endrun(subr//': do_cldcool=.true. not available when compiling with OpenACC') +#endif + !-----------------------------------------------------------------------------------! ! MAIN COMPUTATION BEGINS HERE ! !-----------------------------------------------------------------------------------! @@ -3456,6 +3463,94 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (macmic_it==1) wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 call t_stopf('clubb_tend_cam:flip-index') + + call t_startf('clubb_tend_cam:acc_copyin') + !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & + !$acc gr%weights_zt2zm, gr%weights_zm2zt, & + !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & + !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & + !$acc nu_vert_res_dep%nu6, & + !$acc sclr_idx, clubb_params, & + !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & + !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & + !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & + !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & + !$acc radf, wpthlp_sfc, & + !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & + !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & + !$acc vm_ref, ug, vg, grid_dx, grid_dy, & + !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk) ) & + !$acc copy( um_in, upwp_in, vm_in, vpwp_in, up2_in, vp2_in, up3_in, vp3_in, rtm_in, & + !$acc wprtp_in, thlm_in, wpthlp_in, rtp2_in, & + !$acc rtp3_in, thlp2_in, thlp3_in, rtpthlp_in, wp2_in, wp3_in, & + !$acc p_in_Pa, exner, rcm_inout, cloud_frac_inout, wpthvp_in, wp2thvp_in, & + !$acc rtpthvp_in, thlpthvp_in, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & + !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & + !$acc ice_supersat_frac_inout, um_pert_inout, & + !$acc vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & + !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & + !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & + !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & + !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & + !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & + !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & + !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & + !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & + !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) & + !$acc copyout( rcm_in_layer_out, cloud_cover_out, wprcp_out, w_up_in_cloud_out, w_down_in_cloud_out, & + !$acc cloudy_updraft_frac_out, cloudy_downdraft_frac_out, invrs_tau_zm_out, khzt_out, & + !$acc khzm_out, thlprcp_out, qclvar_out ) + + !$acc data if( sclr_dim > 0 ) & + !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & + !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) + + !$acc data if( edsclr_dim > 0 ) & + !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & + !$acc copy( edsclr_in ) + + !$acc data if( hydromet_dim > 0 ) & + !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & + !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) + call t_stopf('clubb_tend_cam:acc_copyin') + do t=1,nadv ! do needed number of "sub" timesteps for each CAM step ! Increment the statistics then begin stats timestep @@ -3651,6 +3746,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo ! end time loop call t_startf('clubb_tend_cam:NAR') + call t_startf('clubb_tend_cam:acc_copyout') + !$acc end data + !$acc end data + !$acc end data + !$acc end data + call t_stopf('clubb_tend_cam:acc_copyout') + if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then From 6a38ec26aa8548ed86a63e03a59aef02f1148126 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Sat, 12 Oct 2024 15:29:46 -0600 Subject: [PATCH 13/82] Replacing vector notation with loops, rearranging some things, general cleanup. --- src/physics/cam/clubb_intr.F90 | 763 ++++++++++++++++++--------------- 1 file changed, 420 insertions(+), 343 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 4b30e503ac..c1d2008ba2 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -1477,7 +1477,7 @@ subroutine clubb_ini_cam(pbuf2d) logical, parameter :: l_input_fields = .false. ! Always false for CAM-CLUBB. logical, parameter :: l_update_pressure = .false. ! Always false for CAM-CLUBB. - integer :: nlev, ierr=0 + integer :: ierr=0 real(r8) :: & C1, C1b, C1c, C2rt, C2thl, C2rtthl, & @@ -1505,8 +1505,6 @@ subroutine clubb_ini_cam(pbuf2d) !----- Begin Code ----- - nlev = pver + 1 - top_lev - if (core_rknd /= r8) then call endrun('clubb_ini_cam: CLUBB library core_rknd must match CAM r8 and it does not') end if @@ -1748,7 +1746,7 @@ subroutine clubb_ini_cam(pbuf2d) ! at each time step, which is why dummy arrays are read in here for heights ! as they are immediately overwrote. !$OMP PARALLEL - call check_clubb_settings_api( nlev+1, clubb_params_single_col, & ! Intent(in) + call check_clubb_settings_api( pverp+1-top_lev, clubb_params_single_col, & ! Intent(in) l_implemented, & ! Intent(in) l_input_fields, & ! Intent(in) clubb_config_flags, & ! intent(in) @@ -1887,7 +1885,7 @@ subroutine clubb_ini_cam(pbuf2d) if (stats_metadata%l_stats) then call stats_init_clubb( .true., dum1, dum2, & - nlev+1, nlev+1, nlev+1, dum3, & + pverp+1-top_lev, pverp+1-top_lev, pverp+1-top_lev, dum3, & stats_zt(:), stats_zm(:), stats_sfc(:), & stats_rad_zt(:), stats_rad_zm(:)) @@ -2346,10 +2344,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & sclrp3, & ! sclr'^3 (thermo. levels) [{units vary}^3] sclrprtp, & ! sclr'rt' (momentum levels) [{units vary} (kg/kg)] sclrpthlp, & ! sclr'thlp' (momentum levels) [{units vary} (K)] - wpsclrp ! w'sclr' (momentum levels) [{units vary} m/s] - - real(r8), dimension(state%ncol,pverp,sclr_dim) :: & - sclrpthvp_inout ! sclr'th_v' (momentum levels) [{units vary} (K)] + wpsclrp, & ! w'sclr' (momentum levels) [{units vary} m/s] + sclrpthvp_inout ! sclr'th_v' (momentum levels) [{units vary} (K)] real(r8), dimension(state%ncol,pverp+1-top_lev,edsclr_dim) :: & edsclrm_forcing, & ! Eddy passive scalar forcing [{units vary}/s] @@ -2576,8 +2572,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8) :: temp2d(pcols,pver), temp2dp(pcols,pverp) ! temporary array for holding scaled outputs - integer :: nlev - intrinsic :: max character(len=*), parameter :: subr='clubb_tend_cam' @@ -2591,10 +2585,19 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8), dimension(state%ncol,nparams) :: & clubb_params ! Adjustable CLUBB parameters (C1, C2 ...) + + integer :: & + nzm_clubb, & + nzt_clubb, & + sclr, & + edsclr #endif - det_s(:) = 0.0_r8 - det_ice(:) = 0.0_r8 + + do i = 1, pcols + det_s(i) = 0.0_r8 + det_ice(i) = 0.0_r8 + end do #ifdef CLUBB_SGS @@ -2609,33 +2612,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! MAIN COMPUTATION BEGINS HERE ! !-----------------------------------------------------------------------------------! - - nlev = pver + 1 - top_lev - - call t_startf('clubb_tend_cam:NAR') - rtp2_zt_out = 0._r8 - thl2_zt_out = 0._r8 - wp2_zt_out = 0._r8 - pdfp_rtp2 = 0._r8 - wm_zt_out = 0._r8 - - temp2d = 0._r8 - temp2dp = 0._r8 - - dl_rad = clubb_detliq_rad - di_rad = clubb_detice_rad - dt_low = clubb_detphase_lowtemp - - frac_limit = 0.01_r8 - ic_limit = 1.e-12_r8 - inv_rh2o = 1._r8/rh2o - - if (clubb_do_adv) then - apply_const = 1._r8 ! Initialize to one, only if CLUBB's moments are advected - else - apply_const = 0._r8 ! Never want this if CLUBB's moments are not advected - endif - ! Get indicees for cloud and ice mass and cloud and ice number call cnst_get_ind('Q',ixq) call cnst_get_ind('CLDLIQ',ixcldliq) @@ -2643,28 +2619,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call cnst_get_ind('NUMLIQ',ixnumliq) call cnst_get_ind('NUMICE',ixnumice) - if (clubb_do_icesuper) then - call pbuf_get_field(pbuf, naai_idx, naai) - end if - - ! Initialize physics tendency arrays, copy the state to state1 array to use in this routine - call physics_ptend_init(ptend_all, state%psetcols, 'clubb') - - ! Copy the state to state1 array to use in this routine - call physics_state_copy(state, state1) - - ! Constituents are all treated as dry mmr by clubb. Convert the water species to - ! a dry basis. - call set_wet_to_dry(state1, convert_cnst_type='wet') - - if (clubb_do_liqsupersat) then - call pbuf_get_field(pbuf, npccn_idx, npccn) - endif - - ! Determine number of columns and which chunk computation is to be performed on - ncol = state%ncol - lchnk = state%lchnk - ! Determine time step of physics buffer itim_old = pbuf_old_tim_idx() @@ -2761,17 +2715,110 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call pbuf_get_field(pbuf, vpwp_clubb_gw_mc_idx, vpwp_clubb_gw_mc ) call pbuf_get_field(pbuf, wpthlp_clubb_gw_mc_idx, wpthlp_clubb_gw_mc ) + if (clubb_do_icesuper) then + call pbuf_get_field(pbuf, naai_idx, naai) + end if + + ! Initialize physics tendency arrays, copy the state to state1 array to use in this routine + call physics_ptend_init(ptend_all, state%psetcols, 'clubb') + + ! Copy the state to state1 array to use in this routine + call physics_state_copy(state, state1) + + ! Constituents are all treated as dry mmr by clubb. Convert the water species to + ! a dry basis. + call set_wet_to_dry(state1, convert_cnst_type='wet') + + if (clubb_do_liqsupersat) then + call pbuf_get_field(pbuf, npccn_idx, npccn) + endif + + + + ! Determine number of columns and which chunk computation is to be performed on + ncol = state%ncol + lchnk = state%lchnk + + nzt_clubb = pver + 1 - top_lev + nzm_clubb = pverp + 1 - top_lev + + ! Allocate pdf_params only if they aren't allocated already. if ( .not. allocated(pdf_params_chnk(lchnk)%mixt_frac) ) then - call init_pdf_params_api( pverp+1-top_lev, ncol, pdf_params_chnk(lchnk) ) - call init_pdf_params_api( pverp+1-top_lev, ncol, pdf_params_zm_chnk(lchnk) ) + call init_pdf_params_api( nzm_clubb, ncol, pdf_params_chnk(lchnk) ) + call init_pdf_params_api( nzm_clubb, ncol, pdf_params_zm_chnk(lchnk) ) end if - if ( .not. allocated(pdf_implicit_coefs_terms_chnk(lchnk)%coef_wp4_implicit) ) then - call init_pdf_implicit_coefs_terms_api( pverp+1-top_lev, ncol, sclr_dim, & - pdf_implicit_coefs_terms_chnk(lchnk) ) - end if + if ( .not. allocated(pdf_implicit_coefs_terms_chnk(lchnk)%coef_wp4_implicit) ) then + call init_pdf_implicit_coefs_terms_api( nzm_clubb, ncol, sclr_dim, & + pdf_implicit_coefs_terms_chnk(lchnk) ) + end if + + + !--------------------- Scalar Setting -------------------- + + dl_rad = clubb_detliq_rad + di_rad = clubb_detice_rad + dt_low = clubb_detphase_lowtemp + + frac_limit = 0.01_r8 + ic_limit = 1.e-12_r8 + inv_rh2o = 1._r8/rh2o + + ! Determine CLUBB time step and make it sub-step friendly + ! For now we want CLUBB time step to be 5 min since that is + ! what has been scientifically validated. However, there are certain + ! instances when a 5 min time step will not be possible (based on + ! host model time step or on macro-micro sub-stepping + dtime = clubb_timestep + + ! Now check to see if dtime is greater than the host model + ! (or sub stepped) time step. If it is, then simply + ! set it equal to the host (or sub step) time step. + ! This section is mostly to deal with small host model + ! time steps (or small sub-steps) + if (dtime > hdtime) then + dtime = hdtime + endif + + ! Now check to see if CLUBB time step divides evenly into + ! the host model time step. If not, force it to divide evenly. + ! We also want it to be 5 minutes or less. This section is + ! mainly for host model time steps that are not evenly divisible + ! by 5 minutes + if (mod(hdtime,dtime) .ne. 0) then + dtime = hdtime/2._r8 + do while (dtime > clubb_timestep) + dtime = dtime/2._r8 + end do + endif + + ! If resulting host model time step and CLUBB time step do not divide evenly + ! into each other, have model throw a fit. + if (mod(hdtime,dtime) .ne. 0) then + call endrun(subr//': CLUBB time step and HOST time step NOT compatible') + endif + + ! determine number of timesteps CLUBB core should be advanced, + ! host time step divided by CLUBB time step + nadv = max(hdtime/dtime,1._r8) + + + ! Set stats output and increment equal to CLUBB and host dt + stats_metadata%stats_tsamp = dtime + stats_metadata%stats_tout = hdtime + + stats_nsamp = nint(stats_metadata%stats_tsamp/dtime) + stats_nout = nint(stats_metadata%stats_tout/dtime) + + + if (clubb_do_adv) then + apply_const = 1._r8 ! Initialize to one, only if CLUBB's moments are advected + else + apply_const = 0._r8 ! Never want this if CLUBB's moments are not advected + endif + ! Initialize the apply_const variable (note special logic is due to eularian backstepping) if (clubb_do_adv .and. (is_first_step() .or. all(wpthlp(1:ncol,1:pver) == 0._r8))) then @@ -2779,15 +2826,188 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! from moments since it has not been added yet endif + + !--------------------- Initializations -------------------- + + ! Set the ztodt timestep in pbuf for SILHS ztodtptr(:) = 1.0_r8*hdtime + + ! Determine Coriolis force at given latitude. This is never used + ! when CLUBB is implemented in a host model, therefore just set + ! to zero. + fcor(:) = 0._r8 + + call t_startf('clubb_tend_cam:NAR') + + do i = 1, pcols + do k = 1, pverp + rtp2_zt_out(i,k) = 0._r8 + thl2_zt_out(i,k) = 0._r8 + wp2_zt_out(i,k) = 0._r8 + pdfp_rtp2(i,k) = 0._r8 + wm_zt_out(i,k) = 0._r8 + temp2dp(i,k) = 0._r8 + end do + end do + + + do i = 1, pcols + do k = 1, pver + temp2d(i,k) = 0._r8 + end do + end do + + ! Initialize forcings for transported scalars to zero + do sclr = 1, sclr_dim + do i = 1, pcols + do k = 1, nzm_clubb + sclrm_forcing(i,k,sclr) = 0._r8 + sclrm(i,k,sclr) = 0._r8 + end do + end do + end do + + do edsclr = 1, edsclr_dim + do i = 1, pcols + do k = 1, nzm_clubb + edsclrm_forcing(i,k,edsclr) = 0._r8 + edsclr_in(i,k,edsclr) = 0._r8 + end do + end do + end do + + + ! Initialize EDMF outputs + if (do_clubb_mf) then + do k = 1, pverp + do i = 1, pcols + mf_dry_a_output(i,k) = 0._r8 + mf_moist_a_output(i,k) = 0._r8 + mf_dry_w_output(i,k) = 0._r8 + mf_moist_w_output(i,k) = 0._r8 + mf_dry_qt_output(i,k) = 0._r8 + mf_moist_qt_output(i,k) = 0._r8 + mf_dry_thl_output(i,k) = 0._r8 + mf_moist_thl_output(i,k) = 0._r8 + mf_dry_u_output(i,k) = 0._r8 + mf_moist_u_output(i,k) = 0._r8 + mf_dry_v_output(i,k) = 0._r8 + mf_moist_v_output(i,k) = 0._r8 + mf_moist_qc_output(i,k) = 0._r8 + s_ae_output(i,k) = 0._r8 + s_aw_output(i,k) = 0._r8 + s_awthl_output(i,k) = 0._r8 + s_awqt_output(i,k) = 0._r8 + s_awql_output(i,k) = 0._r8 + s_awqi_output(i,k) = 0._r8 + s_awu_output(i,k) = 0._r8 + s_awv_output(i,k) = 0._r8 + mf_thlflx_output(i,k) = 0._r8 + mf_qtflx_output(i,k) = 0._r8 + end do + end do + end if + + ! Define surface sources for transported variables for diffusion, will + ! be zero as these tendencies are done in vertical_diffusion + do edsclr = 1, edsclr_dim + do i = 1, ncol + wpedsclrp_sfc(i,edsclr) = 0._r8 + end do + end do + + + ! Define forcings from CAM to CLUBB as zero for momentum and thermo, + ! forcings already applied through CAM + do k = 1, nzm_clubb + do i = 1, ncol + thlm_forcing(i,k) = 0._r8 + rtm_forcing(i,k) = 0._r8 + um_forcing(i,k) = 0._r8 + vm_forcing(i,k) = 0._r8 + + + rtm_ref(i,k) = 0.0_r8 + thlm_ref(i,k) = 0.0_r8 + um_ref(i,k) = 0.0_r8 + vm_ref(i,k) = 0.0_r8 + ug(i,k) = 0.0_r8 + vg(i,k) = 0.0_r8 + + ! Perturbed winds are not used in CAM + um_pert_inout(i,k) = 0.0_r8 + vm_pert_inout(i,k) = 0.0_r8 + upwp_pert_inout(i,k) = 0.0_r8 + vpwp_pert_inout(i,k) = 0.0_r8 + end do + end do + + do i = 1, ncol + ! Perturbed winds are not used in CAM + upwp_sfc_pert(i) = 0.0_r8 + vpwp_sfc_pert(i) = 0.0_r8 + + ! higher order scalar stuff, put to zero + wpsclrp_sfc(i,sclr) = 0._r8 + end do + + ! Initialize these to prevent crashing behavior + do k=1,nzm_clubb + do i=1,ncol + wprcp_out(i,k) = 0._r8 + rcm_in_layer_out(i,k) = 0._r8 + cloud_cover_out(i,k) = 0._r8 + khzm_out(i,k) = 0._r8 + khzt_out(i,k) = 0._r8 + end do + end do + + ! higher order scalar stuff, put to zero + do sclr = 1, sclr_dim + do k = 1, nzm_clubb + do i=1, ncol + sclrm(i,k,sclr) = 0._r8 + wpsclrp(i,k,sclr) = 0._r8 + sclrp2(i,k,sclr) = 0._r8 + sclrp3(i,k,sclr) = 0._r8 + sclrprtp(i,k,sclr) = 0._r8 + sclrpthlp(i,k,sclr) = 0._r8 + sclrpthvp_inout(i,k,sclr) = 0._r8 + end do + end do + end do + + do ixind=1, hydromet_dim + do k=1, nzm_clubb + do i=1, ncol + hydromet(i,k,ixind) = 0._r8 + wphydrometp(i,k,ixind) = 0._r8 + wp2hmp(i,k,ixind) = 0._r8 + rtphmp_zt(i,k,ixind) = 0._r8 + thlphmp_zt(i,k,ixind) = 0._r8 + end do + end do + end do + + ! need to initialize macmic coupling to zero + if (macmic_it==1) then + ttend_clubb_mc(:ncol,:) = 0._r8 + upwp_clubb_gw_mc(:ncol,:) = 0._r8 + vpwp_clubb_gw_mc(:ncol,:) = 0._r8 + thlp2_clubb_gw_mc(:ncol,:) = 0._r8 + wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 + end if + + + ! Define the grid box size. CLUBB needs this information to determine what ! the maximum length scale should be. This depends on the column for ! variable mesh grids and lat-lon grids call grid_size(state1, grid_dx, grid_dy) - + call t_stopf('clubb_tend_cam:NAR') if (clubb_do_icesuper) then @@ -2805,10 +3025,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call physics_ptend_init(ptend_loc, state%psetcols, 'iceadj', ls=.true., lq=lq2 ) - stend(:ncol,:)=0._r8 - qvtend(:ncol,:)=0._r8 - qitend(:ncol,:)=0._r8 - initend(:ncol,:)=0._r8 + do i = 1, ncol + do k = 1, pver + stend(i,k) = 0._r8 + qvtend(i,k) = 0._r8 + qitend(i,k) = 0._r8 + initend(i,k) = 0._r8 + end do + end do call t_startf('clubb_tend_cam:ice_macro_tend') call ice_macro_tend(naai(1:ncol,top_lev:pver), state1%t(1:ncol,top_lev:pver), & @@ -2819,10 +3043,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:ice_macro_tend') ! update local copy of state with the tendencies - ptend_loc%q(:ncol,top_lev:pver,1)=qvtend(:ncol,top_lev:pver) - ptend_loc%q(:ncol,top_lev:pver,ixcldice)=qitend(:ncol,top_lev:pver) - ptend_loc%q(:ncol,top_lev:pver,ixnumice)=initend(:ncol,top_lev:pver) - ptend_loc%s(:ncol,top_lev:pver)=stend(:ncol,top_lev:pver) + do i = 1, ncol + do k = top_lev, pver + ptend_loc%q(i,k,1) = qvtend(i,k) + ptend_loc%q(i,k,ixcldice) = qitend(i,k) + ptend_loc%q(i,k,ixnumice) = initend(i,k) + ptend_loc%s(i,k) = stend(i,k) + end do + end do ! Add the ice tendency to the output tendency call physics_ptend_sum(ptend_loc, ptend_all, ncol) @@ -2830,8 +3058,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! ptend_loc is reset to zero by this call call physics_update(state1, ptend_loc, hdtime) - !Write output for tendencies: - temp2d(:ncol,:pver) = stend(:ncol,:pver)/cpairv(:ncol,:pver,lchnk) + ! Write output for tendencies: + do i = 1, ncol + do k = 1, pver + temp2d(i,k) = stend(i,k) / cpairv(i,k,lchnk) + end do + end do + call outfld( 'TTENDICE', temp2d, pcols, lchnk ) call outfld( 'QVTENDICE', qvtend, pcols, lchnk ) call outfld( 'QITENDICE', qitend, pcols, lchnk ) @@ -2841,49 +3074,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_startf('clubb_tend_cam:NAR') - ! Determine CLUBB time step and make it sub-step friendly - ! For now we want CLUBB time step to be 5 min since that is - ! what has been scientifically validated. However, there are certain - ! instances when a 5 min time step will not be possible (based on - ! host model time step or on macro-micro sub-stepping - dtime = clubb_timestep - - ! Now check to see if dtime is greater than the host model - ! (or sub stepped) time step. If it is, then simply - ! set it equal to the host (or sub step) time step. - ! This section is mostly to deal with small host model - ! time steps (or small sub-steps) - if (dtime > hdtime) then - dtime = hdtime - endif - - ! Now check to see if CLUBB time step divides evenly into - ! the host model time step. If not, force it to divide evenly. - ! We also want it to be 5 minutes or less. This section is - ! mainly for host model time steps that are not evenly divisible - ! by 5 minutes - if (mod(hdtime,dtime) .ne. 0) then - dtime = hdtime/2._r8 - do while (dtime > clubb_timestep) - dtime = dtime/2._r8 - end do - endif - - ! If resulting host model time step and CLUBB time step do not divide evenly - ! into each other, have model throw a fit. - if (mod(hdtime,dtime) .ne. 0) then - call endrun(subr//': CLUBB time step and HOST time step NOT compatible') - endif - - ! determine number of timesteps CLUBB core should be advanced, - ! host time step divided by CLUBB time step - nadv = max(hdtime/dtime,1._r8) - - ! Initialize forcings for transported scalars to zero - sclrm_forcing(:,:,:) = 0._r8 - edsclrm_forcing(:,:,:) = 0._r8 - sclrm(:,:,:) = 0._r8 - ! Compute inverse exner function consistent with CLUBB's definition, which uses a constant ! surface pressure. CAM's exner (in state) does not. Therefore, for consistent ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables @@ -2902,8 +3092,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! At each CLUBB call, initialize mean momentum and thermo CLUBB state ! from the CAM state - do k=1,pver ! loop over levels - do i=1,ncol ! loop over columns + do k = 1, pver + do i = 1, ncol rtm(i,k) = state1%q(i,k,ixq)+state1%q(i,k,ixcldliq) rvm(i,k) = state1%q(i,k,ixq) @@ -2913,12 +3103,18 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & - (latvap/cpairv(i,k,lchnk))*state1%q(i,k,ixcldliq) ) & * inv_exner_clubb(i,k) - if (clubb_do_adv) then - if (macmic_it == 1) then + enddo + enddo + + if (clubb_do_adv) then - ! Note that some of the moments below can be positive or negative. - ! Remove a constant that was added to prevent dynamics from clipping - ! them to prevent dynamics from making them positive. + if (macmic_it == 1) then + + ! Note that some of the moments below can be positive or negative. + ! Remove a constant that was added to prevent dynamics from clipping + ! them to prevent dynamics from making them positive. + do k = 1, pver + do i = 1, ncol thlp2(i,k) = state1%q(i,k,ixthlp2) rtp2(i,k) = state1%q(i,k,ixrtp2) rtpthlp(i,k) = state1%q(i,k,ixrtpthlp) - (rtpthlp_const*apply_const) @@ -2928,13 +3124,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wp3(i,k) = state1%q(i,k,ixwp3) - (wp3_const*apply_const) up2(i,k) = state1%q(i,k,ixup2) vp2(i,k) = state1%q(i,k,ixvp2) - endif - endif + enddo + enddo - enddo - enddo + endif - if (clubb_do_adv) then ! If not last step of macmic loop then set apply_const back to ! zero to prevent output from being corrupted. if (macmic_it == cld_macmic_num_steps) then @@ -2942,98 +3136,71 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & else apply_const = 0._r8 endif - endif - rtm(1:ncol,pverp) = rtm(1:ncol,pver) - um(1:ncol,pverp) = state1%u(1:ncol,pver) - vm(1:ncol,pverp) = state1%v(1:ncol,pver) - thlm(1:ncol,pverp) = thlm(1:ncol,pver) + do i = 1, ncol + thlp2(i,pverp) = thlp2(i,pver) + rtp2(i,pverp) = rtp2(i,pver) + rtpthlp(i,pverp) = rtpthlp(i,pver) + wpthlp(i,pverp) = wpthlp(i,pver) + wprtp(i,pverp) = wprtp(i,pver) + wp2(i,pverp) = wp2(i,pver) + wp3(i,pverp) = wp3(i,pver) + up2(i,pverp) = up2(i,pver) + vp2(i,pverp) = vp2(i,pver) + end do - if (clubb_do_adv) then - thlp2(1:ncol,pverp) = thlp2(1:ncol,pver) - rtp2(1:ncol,pverp) = rtp2(1:ncol,pver) - rtpthlp(1:ncol,pverp) = rtpthlp(1:ncol,pver) - wpthlp(1:ncol,pverp) = wpthlp(1:ncol,pver) - wprtp(1:ncol,pverp) = wprtp(1:ncol,pver) - wp2(1:ncol,pverp) = wp2(1:ncol,pver) - wp3(1:ncol,pverp) = wp3(1:ncol,pver) - up2(1:ncol,pverp) = up2(1:ncol,pver) - vp2(1:ncol,pverp) = vp2(1:ncol,pver) endif + + do i = 1, ncol + rtm(i,pverp) = rtm(i,pver) + um(i,pverp) = state1%u(i,pver) + vm(i,pverp) = state1%v(i,pver) + thlm(i,pverp) = thlm(i,pver) + end do + ! Compute virtual potential temperature, which is needed for CLUBB - do k=1,pver - do i=1,ncol + do k = 1, pver + do i = 1, ncol thv(i,k) = state1%t(i,k)*inv_exner_clubb(i,k)*(1._r8+zvir*state1%q(i,k,ixq)& -state1%q(i,k,ixcldliq)) enddo enddo - call physics_ptend_init(ptend_loc,state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq) + call physics_ptend_init( ptend_loc, state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq ) !REMOVECAM - no longer need this when CAM is retired and pcols no longer exists troplev(:) = 0 !REMOVECAM_END - call tropopause_findChemTrop(state, troplev) - - ! Initialize EDMF outputs - if (do_clubb_mf) then - mf_dry_a_output(:,:) = 0._r8 - mf_moist_a_output(:,:) = 0._r8 - mf_dry_w_output(:,:) = 0._r8 - mf_moist_w_output(:,:) = 0._r8 - mf_dry_qt_output(:,:) = 0._r8 - mf_moist_qt_output(:,:) = 0._r8 - mf_dry_thl_output(:,:) = 0._r8 - mf_moist_thl_output(:,:) = 0._r8 - mf_dry_u_output(:,:) = 0._r8 - mf_moist_u_output(:,:) = 0._r8 - mf_dry_v_output(:,:) = 0._r8 - mf_moist_v_output(:,:) = 0._r8 - mf_moist_qc_output(:,:) = 0._r8 - s_ae_output(:,:) = 0._r8 - s_aw_output(:,:) = 0._r8 - s_awthl_output(:,:) = 0._r8 - s_awqt_output(:,:) = 0._r8 - s_awql_output(:,:) = 0._r8 - s_awqi_output(:,:) = 0._r8 - s_awu_output(:,:) = 0._r8 - s_awv_output(:,:) = 0._r8 - mf_thlflx_output(:,:) = 0._r8 - mf_qtflx_output(:,:) = 0._r8 - end if + call tropopause_findChemTrop( state, troplev ) - ! Determine Coriolis force at given latitude. This is never used - ! when CLUBB is implemented in a host model, therefore just set - ! to zero. - fcor(:) = 0._r8 ! Define the CLUBB momentum grid (in height, units of m) - do k=1, nlev+1 + do k=1, nzm_clubb do i=1, ncol zi_g(i,k) = state1%zi(i,pverp-k+1)-state1%zi(i,pver+1) end do end do ! Define the CLUBB thermodynamic grid (in units of m) - do k=1, nlev + do k=1, nzt_clubb do i=1, ncol zt_g(i,k+1) = state1%zm(i,pver-k+1)-state1%zi(i,pver+1) end do end do + ! Thermodynamic ghost point is below surface + do i=1, ncol + zt_g(i,1) = -1._r8*zt_g(i,2) + end do + do k=1, pver do i=1, ncol dz_g(i,k) = state1%zi(i,k)-state1%zi(i,k+1) ! compute thickness end do end do - ! Thermodynamic ghost point is below surface - do i=1, ncol - zt_g(i,1) = -1._r8*zt_g(i,2) - end do - do i=1, ncol ! Set the elevation of the surface sfc_elevation(i) = state1%zi(i,pver+1) @@ -3041,8 +3208,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute thermodynamic stuff needed for CLUBB on thermo levels. ! Inputs for the momentum levels are set below setup_clubb core - do k=1,nlev - do i=1, ncol + do k = 1, nzt_clubb + do i = 1, ncol ! base state (dry) variables rho_ds_zt(i,k+1) = rga*(state1%pdeldry(i,pver-k+1)/dz_g(i,pver-k+1)) invrs_rho_ds_zt(i,k+1) = 1._r8/(rho_ds_zt(i,k+1)) @@ -3060,19 +3227,15 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rfrzm(i,k+1) = state1%q(i,pver-k+1,ixcldice) radf(i,k+1) = radf_clubb(i,pver-k+1) qrl_clubb(i,k+1) = qrl(i,pver-k+1)/(cpairv(i,k,lchnk)*state1%pdeldry(i,pver-k+1)) - end do - end do - ! Compute mean w wind on thermo grid, convert from omega to w - do k=1,nlev - do i=1,ncol + ! Compute mean w wind on thermo grid, convert from omega to w wm_zt(i,k+1) = -1._r8*(state1%omega(i,pver-k+1)-state1%omega(i,pver))/(rho_zt(i,k+1)*gravit) end do end do ! Below computes the same stuff for the ghost point. May or may ! not be needed, just to be safe to avoid NaN's - do i=1, ncol + do i = 1, ncol thv_ds_zt(i,1) = thv_ds_zt(i,2) rho_ds_zt(i,1) = rho_ds_zt(i,2) invrs_rho_ds_zt(i,1) = invrs_rho_ds_zt(i,2) @@ -3137,20 +3300,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if - ! Define surface sources for transported variables for diffusion, will - ! be zero as these tendencies are done in vertical_diffusion - do ixind=1,edsclr_dim - do i=1,ncol - wpedsclrp_sfc(i,ixind) = 0._r8 - end do - end do - - ! Set stats output and increment equal to CLUBB and host dt - stats_metadata%stats_tsamp = dtime - stats_metadata%stats_tout = hdtime - - stats_nsamp = nint(stats_metadata%stats_tsamp/dtime) - stats_nout = nint(stats_metadata%stats_tout/dtime) ! Heights need to be set at each timestep. Therefore, recall ! setup_grid and setup_parameters for this. @@ -3159,8 +3308,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Important note: do not make any calls that use CLUBB grid-height ! operators (such as zt2zm_api, etc.) until AFTER the ! call to setup_grid_heights_api. - call setup_grid_api( nlev+1, ncol, sfc_elevation, l_implemented, & ! intent(in) - grid_type, zi_g(:,2), zi_g(:,1), zi_g(:,nlev+1), & ! intent(in) + call setup_grid_api( nzm_clubb, ncol, sfc_elevation, l_implemented, & ! intent(in) + grid_type, zi_g(:,2), zi_g(:,1), zi_g(:,nzm_clubb), & ! intent(in) zi_g, zt_g, & ! intent(in) gr ) ! intent(out) @@ -3171,32 +3320,17 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call setup_parameters_api( zi_g(:,2), clubb_params, gr, ncol, grid_type, & ! intent(in) clubb_config_flags%l_prescribed_avg_deltaz, & ! intent(in) lmin, nu_vert_res_dep, err_code ) ! intent(out) + if ( err_code == clubb_fatal_error ) then call endrun(subr//': Fatal error in CLUBB setup_parameters') end if - - ! Define forcings from CAM to CLUBB as zero for momentum and thermo, - ! forcings already applied through CAM - thlm_forcing(:,:) = 0._r8 - rtm_forcing(:,:) = 0._r8 - um_forcing(:,:) = 0._r8 - vm_forcing(:,:) = 0._r8 - - - rtm_ref(:,:) = 0.0_r8 - thlm_ref(:,:) = 0.0_r8 - um_ref(:,:) = 0.0_r8 - vm_ref(:,:) = 0.0_r8 - ug(:,:) = 0.0_r8 - vg(:,:) = 0.0_r8 - ! Add forcings for SILHS covariance contributions - rtp2_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, rtp2_mc_zt(1:ncol,:) ) - thlp2_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, thlp2_mc_zt(1:ncol,:) ) - wprtp_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, wprtp_mc_zt(1:ncol,:) ) - wpthlp_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, wpthlp_mc_zt(1:ncol,:) ) - rtpthlp_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, rtpthlp_mc_zt(1:ncol,:) ) + rtp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtp2_mc_zt(1:ncol,:) ) + thlp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, thlp2_mc_zt(1:ncol,:) ) + wprtp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wprtp_mc_zt(1:ncol,:) ) + wpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wpthlp_mc_zt(1:ncol,:) ) + rtpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtpthlp_mc_zt(1:ncol,:) ) ! Zero out SILHS covariance contribution terms rtp2_mc_zt(:,:) = 0.0_r8 @@ -3208,11 +3342,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute some inputs from the thermodynamic grid ! to the momentum grid - rho_ds_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, rho_ds_zt ) - rho_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, rho_zt ) - invrs_rho_ds_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, invrs_rho_ds_zt ) - thv_ds_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, thv_ds_zt ) - wm_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, wm_zt ) + rho_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, rho_ds_zt ) + rho_zm = zt2zm_api( nzm_clubb, ncol, gr, rho_zt ) + invrs_rho_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, invrs_rho_ds_zt ) + thv_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, thv_ds_zt ) + wm_zm = zt2zm_api( nzm_clubb, ncol, gr, wm_zt ) ! Surface fluxes provided by host model do i=1,ncol @@ -3241,16 +3375,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vpwp_sfc(i) = cam_in%wsy(i)/rho_ds_zm(i,1) ! Surface zonal momentum flux end do endif - - ! Perturbed winds are not used in CAM - upwp_sfc_pert = 0.0_r8 - vpwp_sfc_pert = 0.0_r8 call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:flip-index') + ! Need to flip arrays around for CLUBB core - do k=1,nlev+1 - do i=1,ncol + do k = 1, nzm_clubb + do i = 1, ncol + um_in(i,k) = um(i,pverp-k+1) vm_in(i,k) = vm(i,pverp-k+1) upwp_in(i,k) = upwp(i,pverp-k+1) @@ -3291,7 +3423,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & pdf_params_zm_chnk(lchnk)%mixt_frac(i,k) = pdf_zm_mixt_frac(i,pverp-k+1) end if - sclrpthvp_inout(i,k,:) = 0._r8 wp2rtp_inout(i,k) = wp2rtp(i,pverp-k+1) wp2thlp_inout(i,k) = wp2thlp(i,pverp-k+1) uprcp_inout(i,k) = uprcp(i,pverp-k+1) @@ -3306,63 +3437,15 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - ! Perturbed winds are not used in CAM - um_pert_inout = 0.0_r8 - vm_pert_inout = 0.0_r8 - upwp_pert_inout = 0.0_r8 - vpwp_pert_inout = 0.0_r8 - - do k=2,nlev+1 + do k=2, nzm_clubb do i=1,ncol pre_in(i,k) = prer_evap(i,pverp-k+1) end do end do do i=1,ncol - pre_in(i,1) = pre_in(i,2) - end do - - do i=1,ncol - rcm_inout(i,1) = rcm_inout(i,2) - end do - - ! Initialize these to prevent crashing behavior - do k=1,nlev+1 - do i=1,ncol - wprcp_out(i,k) = 0._r8 - rcm_in_layer_out(i,k) = 0._r8 - cloud_cover_out(i,k) = 0._r8 - edsclr_in(i,k,:) = 0._r8 - khzm_out(i,k) = 0._r8 - khzt_out(i,k) = 0._r8 - end do - end do - - ! higher order scalar stuff, put to zero - do ixind=1, sclr_dim - do k=1, nlev+1 - do i=1, ncol - sclrm(i,k,ixind) = 0._r8 - wpsclrp(i,k,ixind) = 0._r8 - sclrp2(i,k,ixind) = 0._r8 - sclrp3(i,k,ixind) = 0._r8 - sclrprtp(i,k,ixind) = 0._r8 - sclrpthlp(i,k,ixind) = 0._r8 - wpsclrp_sfc(i,ixind) = 0._r8 - end do - end do - end do - - do ixind=1, hydromet_dim - do k=1, nlev+1 - do i=1, ncol - hydromet(i,k,ixind) = 0._r8 - wphydrometp(i,k,ixind) = 0._r8 - wp2hmp(i,k,ixind) = 0._r8 - rtphmp_zt(i,k,ixind) = 0._r8 - thlphmp_zt(i,k,ixind) = 0._r8 - end do - end do + pre_in(i,1) = pre_in(i,2) + rcm_inout(i,1) = rcm_inout(i,2) end do ! pressure,exner on momentum grid needed for mass flux calc. @@ -3382,7 +3465,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & invrs_exner_zt(i,1) = invrs_exner_zt(i,2) end do - kappa_zm(1:ncol,:) = zt2zm_api(pverp+1-top_lev, ncol, gr, kappa_zt(1:ncol,:)) + kappa_zm(1:ncol,:) = zt2zm_api(nzm_clubb, ncol, gr, kappa_zt(1:ncol,:)) do k=1,pverp do i=1,ncol @@ -3397,17 +3480,17 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_do_adv) then if (macmic_it == 1) then - wp2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, wp2_in ) - wpthlp_in = zt2zm_api(pverp+1-top_lev, ncol, gr, wpthlp_in ) - wprtp_in = zt2zm_api(pverp+1-top_lev, ncol, gr, wprtp_in ) - up2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, up2_in ) - vp2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, vp2_in ) - thlp2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, thlp2_in ) - rtp2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, rtp2_in ) - rtpthlp_in = zt2zm_api(pverp+1-top_lev, ncol, gr, rtpthlp_in ) + wp2_in = zt2zm_api(nzm_clubb, ncol, gr, wp2_in ) + wpthlp_in = zt2zm_api(nzm_clubb, ncol, gr, wpthlp_in ) + wprtp_in = zt2zm_api(nzm_clubb, ncol, gr, wprtp_in ) + up2_in = zt2zm_api(nzm_clubb, ncol, gr, up2_in ) + vp2_in = zt2zm_api(nzm_clubb, ncol, gr, vp2_in ) + thlp2_in = zt2zm_api(nzm_clubb, ncol, gr, thlp2_in ) + rtp2_in = zt2zm_api(nzm_clubb, ncol, gr, rtp2_in ) + rtpthlp_in = zt2zm_api(nzm_clubb, ncol, gr, rtpthlp_in ) - do k=1,nlev+1 - do i=1,ncol + do k = 1, nzm_clubb + do i = 1, ncol thlp2_in(i,k) = max(thl_tol**2,thlp2_in(i,k)) rtp2_in(i,k) = max(rt_tol**2,rtp2_in(i,k)) wp2_in(i,k) = max(w_tol_sqd,wp2_in(i,k)) @@ -3426,7 +3509,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & icnt = icnt+1 - do k=1,nlev + do k=1,nzt_clubb do i=1,ncol edsclr_in(i,k+1,icnt) = state1%q(i,pver-k+1,ixind) end do @@ -3441,7 +3524,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_l_do_expldiff_rtm_thlm) then - do k=1,nlev + do k=1,nzt_clubb do i=1, ncol edsclr_in(i,k+1,icnt+1) = thlm(i,pver-k+1) edsclr_in(i,k+1,icnt+2) = rtm(i,pver-k+1) @@ -3455,12 +3538,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - ! need to initialize macmic coupling to zero - if (macmic_it==1) ttend_clubb_mc(:ncol,:) = 0._r8 - if (macmic_it==1) upwp_clubb_gw_mc(:ncol,:) = 0._r8 - if (macmic_it==1) vpwp_clubb_gw_mc(:ncol,:) = 0._r8 - if (macmic_it==1) thlp2_clubb_gw_mc(:ncol,:) = 0._r8 - if (macmic_it==1) wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 call t_stopf('clubb_tend_cam:flip-index') @@ -3576,8 +3653,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & invrs_dzt(i,:) = 1._r8/dzt(i,:) end do - rtm_zm_in(1:ncol,:) = zt2zm_api( pverp+1-top_lev, ncol, gr, rtm_in(1:ncol,:) ) - thlm_zm_in(1:ncol,:) = zt2zm_api( pverp+1-top_lev, ncol, gr, thlm_in(1:ncol,:) ) + rtm_zm_in(1:ncol,:) = zt2zm_api( nzm_clubb, ncol, gr, rtm_in(1:ncol,:) ) + thlm_zm_in(1:ncol,:) = zt2zm_api( nzm_clubb, ncol, gr, thlm_in(1:ncol,:) ) do i=1, ncol call integrate_mf( pverp, dzt(i,:), zi_g(i,:), p_in_Pa_zm(i,:), invrs_exner_zm(i,:), & ! input @@ -3620,7 +3697,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Advance CLUBB CORE one timestep in the future call t_startf('clubb_tend_cam:advance_clubb_core_api') - call advance_clubb_core_api( gr, pverp+1-top_lev, ncol, & + call advance_clubb_core_api( gr, nzm_clubb, ncol, & l_implemented, dtime, fcor, sfc_elevation, & hydromet_dim, & sclr_dim, sclr_tol, edsclr_dim, sclr_idx, & @@ -3682,14 +3759,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (do_rainturb) then - do k=1,nlev+1 + do k=1,nzm_clubb do i=1,ncol rvm_in(i,k) = rtm_in(i,k) - rcm_inout(i,k) end do end do call t_startf('clubb_tend_cam:update_xp2_mc_api') - call update_xp2_mc_api( gr, nlev+1, ncol, dtime, cloud_frac_inout, & + call update_xp2_mc_api( gr, nzm_clubb, ncol, dtime, cloud_frac_inout, & rcm_inout, rvm_in, thlm_in, wm_zt, & exner, pre_in, pdf_params_chnk(lchnk), & rtp2_mc_out, thlp2_mc_out, & @@ -3697,7 +3774,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rtpthlp_mc_out) call t_stopf('clubb_tend_cam:update_xp2_mc_api') - do k=1,nlev+1 + do k=1,nzm_clubb do i=1,ncol dum1 = (1._r8 - cam_in%landfrac(i)) @@ -3715,12 +3792,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (do_cldcool) then call t_startf('clubb_tend_cam:do_cldcool') - rcm_out_zm = zt2zm_api(pverp+1-top_lev, ncol, gr, rcm_inout ) - qrl_zm = zt2zm_api(pverp+1-top_lev, ncol, gr, qrl_clubb ) + rcm_out_zm = zt2zm_api(nzm_clubb, ncol, gr, rcm_inout ) + qrl_zm = zt2zm_api(nzm_clubb, ncol, gr, qrl_clubb ) thlp2_rad_out(:,:) = 0._r8 do i=1, ncol - call calculate_thlp2_rad_api(nlev+1, rcm_out_zm(i,:), thlprcp_out(i,:), qrl_zm(i,:), clubb_params(i,:), & + call calculate_thlp2_rad_api(nzm_clubb, rcm_out_zm(i,:), thlprcp_out(i,:), qrl_zm(i,:), clubb_params(i,:), & thlp2_rad_out(i,:)) end do @@ -3756,16 +3833,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then - wp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, wp2_in ) - wpthlp_in = zm2zt_api( pverp+1-top_lev, ncol, gr, wpthlp_in ) - wprtp_in = zm2zt_api( pverp+1-top_lev, ncol, gr, wprtp_in ) - up2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, up2_in ) - vp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, vp2_in ) - thlp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, thlp2_in ) - rtp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, rtp2_in ) - rtpthlp_in = zm2zt_api( pverp+1-top_lev, ncol, gr, rtpthlp_in ) + wp2_in = zm2zt_api( nzm_clubb, ncol, gr, wp2_in ) + wpthlp_in = zm2zt_api( nzm_clubb, ncol, gr, wpthlp_in ) + wprtp_in = zm2zt_api( nzm_clubb, ncol, gr, wprtp_in ) + up2_in = zm2zt_api( nzm_clubb, ncol, gr, up2_in ) + vp2_in = zm2zt_api( nzm_clubb, ncol, gr, vp2_in ) + thlp2_in = zm2zt_api( nzm_clubb, ncol, gr, thlp2_in ) + rtp2_in = zm2zt_api( nzm_clubb, ncol, gr, rtp2_in ) + rtpthlp_in = zm2zt_api( nzm_clubb, ncol, gr, rtpthlp_in ) - do k=1,nlev+1 + do k=1,nzm_clubb do i=1, ncol thlp2_in(i,k) = max(thl_tol**2, thlp2_in(i,k)) rtp2_in(i,k) = max(rt_tol**2, rtp2_in(i,k)) @@ -3781,14 +3858,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Convert RTP2 and THLP2 to thermo grid for output call t_startf('clubb_tend_cam:NAR') - rtp2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, rtp2_in ) - thl2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, thlp2_in ) - wp2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, wp2_in ) + rtp2_zt = zm2zt_api( nzm_clubb, ncol, gr, rtp2_in ) + thl2_zt = zm2zt_api( nzm_clubb, ncol, gr, thlp2_in ) + wp2_zt = zm2zt_api( nzm_clubb, ncol, gr, wp2_in ) call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:flip-index') ! Arrays need to be "flipped" to CAM grid - do k=1, nlev+1 + do k=1, nzm_clubb do i=1, ncol um(i,pverp-k+1) = um_in(i,k) vm(i,pverp-k+1) = vm_in(i,k) @@ -3863,7 +3940,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wpthlp_clubb_gw(:ncol,:) = wpthlp_clubb_gw_mc(:ncol,:)/REAL(cld_macmic_num_steps,r8) end if - do k=1, nlev+1 + do k=1, nzm_clubb do i=1, ncol mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & @@ -3881,7 +3958,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do do ixind=1,edsclr_dim - do k=1, nlev+1 + do k=1, nzm_clubb do i=1, ncol edsclr_out(i,pverp-k+1,ixind) = edsclr_in(i,k,ixind) end do @@ -3889,7 +3966,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do if (do_clubb_mf) then - do k=1, nlev+1 + do k=1, nzm_clubb do i=1, ncol mf_dry_a_output(i,pverp-k+1) = mf_dry_a(i,k) mf_moist_a_output(i,pverp-k+1) = mf_moist_a(i,k) From 94ba629400decfc87493c241db8d223916b9eee5 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Sun, 13 Oct 2024 22:43:21 -0600 Subject: [PATCH 14/82] More small changes --- src/physics/cam/clubb_intr.F90 | 451 +++++++++++++++++---------------- 1 file changed, 229 insertions(+), 222 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index c1d2008ba2..42e41c6e35 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2841,8 +2841,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_startf('clubb_tend_cam:NAR') - do i = 1, pcols - do k = 1, pverp + do k = 1, pverp + do i = 1, pcols rtp2_zt_out(i,k) = 0._r8 thl2_zt_out(i,k) = 0._r8 wp2_zt_out(i,k) = 0._r8 @@ -2853,82 +2853,23 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do - do i = 1, pcols - do k = 1, pver - temp2d(i,k) = 0._r8 - end do - end do - - ! Initialize forcings for transported scalars to zero - do sclr = 1, sclr_dim - do i = 1, pcols - do k = 1, nzm_clubb - sclrm_forcing(i,k,sclr) = 0._r8 - sclrm(i,k,sclr) = 0._r8 - end do - end do - end do - - do edsclr = 1, edsclr_dim + do k = 1, pver do i = 1, pcols - do k = 1, nzm_clubb - edsclrm_forcing(i,k,edsclr) = 0._r8 - edsclr_in(i,k,edsclr) = 0._r8 - end do - end do - end do - - - ! Initialize EDMF outputs - if (do_clubb_mf) then - do k = 1, pverp - do i = 1, pcols - mf_dry_a_output(i,k) = 0._r8 - mf_moist_a_output(i,k) = 0._r8 - mf_dry_w_output(i,k) = 0._r8 - mf_moist_w_output(i,k) = 0._r8 - mf_dry_qt_output(i,k) = 0._r8 - mf_moist_qt_output(i,k) = 0._r8 - mf_dry_thl_output(i,k) = 0._r8 - mf_moist_thl_output(i,k) = 0._r8 - mf_dry_u_output(i,k) = 0._r8 - mf_moist_u_output(i,k) = 0._r8 - mf_dry_v_output(i,k) = 0._r8 - mf_moist_v_output(i,k) = 0._r8 - mf_moist_qc_output(i,k) = 0._r8 - s_ae_output(i,k) = 0._r8 - s_aw_output(i,k) = 0._r8 - s_awthl_output(i,k) = 0._r8 - s_awqt_output(i,k) = 0._r8 - s_awql_output(i,k) = 0._r8 - s_awqi_output(i,k) = 0._r8 - s_awu_output(i,k) = 0._r8 - s_awv_output(i,k) = 0._r8 - mf_thlflx_output(i,k) = 0._r8 - mf_qtflx_output(i,k) = 0._r8 - end do - end do - end if - - ! Define surface sources for transported variables for diffusion, will - ! be zero as these tendencies are done in vertical_diffusion - do edsclr = 1, edsclr_dim - do i = 1, ncol - wpedsclrp_sfc(i,edsclr) = 0._r8 + temp2d(i,k) = 0._r8 end do end do - ! Define forcings from CAM to CLUBB as zero for momentum and thermo, - ! forcings already applied through CAM do k = 1, nzm_clubb do i = 1, ncol + + ! Define forcings from CAM to CLUBB as zero for momentum and thermo, + ! forcings already applied through CAM thlm_forcing(i,k) = 0._r8 rtm_forcing(i,k) = 0._r8 um_forcing(i,k) = 0._r8 vm_forcing(i,k) = 0._r8 - rtm_ref(i,k) = 0.0_r8 thlm_ref(i,k) = 0.0_r8 um_ref(i,k) = 0.0_r8 @@ -2941,6 +2882,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vm_pert_inout(i,k) = 0.0_r8 upwp_pert_inout(i,k) = 0.0_r8 vpwp_pert_inout(i,k) = 0.0_r8 + + + ! Initialize these to prevent crashing behavior + wprcp_out(i,k) = 0._r8 + rcm_in_layer_out(i,k) = 0._r8 + cloud_cover_out(i,k) = 0._r8 + khzm_out(i,k) = 0._r8 + khzt_out(i,k) = 0._r8 end do end do @@ -2953,17 +2902,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wpsclrp_sfc(i,sclr) = 0._r8 end do - ! Initialize these to prevent crashing behavior - do k=1,nzm_clubb - do i=1,ncol - wprcp_out(i,k) = 0._r8 - rcm_in_layer_out(i,k) = 0._r8 - cloud_cover_out(i,k) = 0._r8 - khzm_out(i,k) = 0._r8 - khzt_out(i,k) = 0._r8 - end do - end do - ! higher order scalar stuff, put to zero do sclr = 1, sclr_dim do k = 1, nzm_clubb @@ -2991,6 +2929,33 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + ! Initialize forcings for transported scalars to zero + do sclr = 1, sclr_dim + do i = 1, pcols + do k = 1, nzm_clubb + sclrm_forcing(i,k,sclr) = 0._r8 + sclrm(i,k,sclr) = 0._r8 + end do + end do + end do + + do edsclr = 1, edsclr_dim + do i = 1, pcols + do k = 1, nzm_clubb + edsclrm_forcing(i,k,edsclr) = 0._r8 + edsclr_in(i,k,edsclr) = 0._r8 + end do + end do + end do + + ! Define surface sources for transported variables for diffusion, will + ! be zero as these tendencies are done in vertical_diffusion + do edsclr = 1, edsclr_dim + do i = 1, ncol + wpedsclrp_sfc(i,edsclr) = 0._r8 + end do + end do + ! need to initialize macmic coupling to zero if (macmic_it==1) then ttend_clubb_mc(:ncol,:) = 0._r8 @@ -2999,9 +2964,40 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & thlp2_clubb_gw_mc(:ncol,:) = 0._r8 wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 end if - + ! Initialize EDMF outputs + if (do_clubb_mf) then + do k = 1, pverp + do i = 1, pcols + mf_dry_a_output(i,k) = 0._r8 + mf_moist_a_output(i,k) = 0._r8 + mf_dry_w_output(i,k) = 0._r8 + mf_moist_w_output(i,k) = 0._r8 + mf_dry_qt_output(i,k) = 0._r8 + mf_moist_qt_output(i,k) = 0._r8 + mf_dry_thl_output(i,k) = 0._r8 + mf_moist_thl_output(i,k) = 0._r8 + mf_dry_u_output(i,k) = 0._r8 + mf_moist_u_output(i,k) = 0._r8 + mf_dry_v_output(i,k) = 0._r8 + mf_moist_v_output(i,k) = 0._r8 + mf_moist_qc_output(i,k) = 0._r8 + s_ae_output(i,k) = 0._r8 + s_aw_output(i,k) = 0._r8 + s_awthl_output(i,k) = 0._r8 + s_awqt_output(i,k) = 0._r8 + s_awql_output(i,k) = 0._r8 + s_awqi_output(i,k) = 0._r8 + s_awu_output(i,k) = 0._r8 + s_awv_output(i,k) = 0._r8 + mf_thlflx_output(i,k) = 0._r8 + mf_qtflx_output(i,k) = 0._r8 + end do + end do + end if + + ! Define the grid box size. CLUBB needs this information to determine what ! the maximum length scale should be. This depends on the column for ! variable mesh grids and lat-lon grids @@ -3090,22 +3086,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & inv_exner_clubb_surf(i) = 1._r8/((state1%pmid(i,pver)/p0_clubb)**(rairv(i,pver,lchnk)/cpairv(i,pver,lchnk))) enddo - ! At each CLUBB call, initialize mean momentum and thermo CLUBB state - ! from the CAM state - do k = 1, pver - do i = 1, ncol - - rtm(i,k) = state1%q(i,k,ixq)+state1%q(i,k,ixcldliq) - rvm(i,k) = state1%q(i,k,ixq) - um(i,k) = state1%u(i,k) - vm(i,k) = state1%v(i,k) - thlm(i,k) = ( state1%t(i,k) & - - (latvap/cpairv(i,k,lchnk))*state1%q(i,k,ixcldliq) ) & - * inv_exner_clubb(i,k) - - enddo - enddo - if (clubb_do_adv) then if (macmic_it == 1) then @@ -3151,21 +3131,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - - do i = 1, ncol - rtm(i,pverp) = rtm(i,pver) - um(i,pverp) = state1%u(i,pver) - vm(i,pverp) = state1%v(i,pver) - thlm(i,pverp) = thlm(i,pver) - end do - - ! Compute virtual potential temperature, which is needed for CLUBB - do k = 1, pver - do i = 1, ncol - thv(i,k) = state1%t(i,k)*inv_exner_clubb(i,k)*(1._r8+zvir*state1%q(i,k,ixq)& - -state1%q(i,k,ixcldliq)) - enddo - enddo call physics_ptend_init( ptend_loc, state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq ) @@ -3175,7 +3140,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call tropopause_findChemTrop( state, troplev ) - ! Define the CLUBB momentum grid (in height, units of m) do k=1, nzm_clubb do i=1, ncol @@ -3183,33 +3147,43 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - ! Define the CLUBB thermodynamic grid (in units of m) - do k=1, nzt_clubb - do i=1, ncol - zt_g(i,k+1) = state1%zm(i,pver-k+1)-state1%zi(i,pver+1) - end do - end do - - ! Thermodynamic ghost point is below surface - do i=1, ncol - zt_g(i,1) = -1._r8*zt_g(i,2) - end do - do k=1, pver do i=1, ncol + + ! Compute virtual potential temperature, which is needed for CLUBB + thv(i,k) = state1%t(i,k)*inv_exner_clubb(i,k)*(1._r8+zvir*state1%q(i,k,ixq)& + -state1%q(i,k,ixcldliq)) + dz_g(i,k) = state1%zi(i,k)-state1%zi(i,k+1) ! compute thickness - end do - end do - do i=1, ncol - ! Set the elevation of the surface - sfc_elevation(i) = state1%zi(i,pver+1) + ! At each CLUBB call, initialize mean momentum and thermo CLUBB state + ! from the CAM state + rtm(i,k) = state1%q(i,k,ixq)+state1%q(i,k,ixcldliq) + rvm(i,k) = state1%q(i,k,ixq) + um(i,k) = state1%u(i,k) + vm(i,k) = state1%v(i,k) + thlm(i,k) = ( state1%t(i,k) & + - (latvap/cpairv(i,k,lchnk))*state1%q(i,k,ixcldliq) ) & + * inv_exner_clubb(i,k) + + enddo + enddo + + do i = 1, ncol + rtm(i,pverp) = rtm(i,pver) + um(i,pverp) = state1%u(i,pver) + vm(i,pverp) = state1%v(i,pver) + thlm(i,pverp) = thlm(i,pver) end do ! Compute thermodynamic stuff needed for CLUBB on thermo levels. ! Inputs for the momentum levels are set below setup_clubb core do k = 1, nzt_clubb do i = 1, ncol + + ! Define the CLUBB thermodynamic grid (in units of m) + zt_g(i,k+1) = state1%zm(i,pver-k+1)-state1%zi(i,pver+1) + ! base state (dry) variables rho_ds_zt(i,k+1) = rga*(state1%pdeldry(i,pver-k+1)/dz_g(i,pver-k+1)) invrs_rho_ds_zt(i,k+1) = 1._r8/(rho_ds_zt(i,k+1)) @@ -3247,6 +3221,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & radf(i,1) = radf(i,2) qrl_clubb(i,1) = qrl_clubb(i,2) wm_zt(i,1) = wm_zt(i,2) + zt_g(i,1) = -1._r8*zt_g(i,2) + + ! Set the elevation of the surface + sfc_elevation(i) = state1%zi(i,pverp) end do @@ -3333,11 +3311,15 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rtpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtpthlp_mc_zt(1:ncol,:) ) ! Zero out SILHS covariance contribution terms - rtp2_mc_zt(:,:) = 0.0_r8 - thlp2_mc_zt(:,:) = 0.0_r8 - wprtp_mc_zt(:,:) = 0.0_r8 - wpthlp_mc_zt(:,:) = 0.0_r8 - rtpthlp_mc_zt(:,:) = 0.0_r8 + do k = 1, pverp + do i = 1, pcols + rtp2_mc_zt(i,k) = 0.0_r8 + thlp2_mc_zt(i,k) = 0.0_r8 + wprtp_mc_zt(i,k) = 0.0_r8 + wpthlp_mc_zt(i,k) = 0.0_r8 + rtpthlp_mc_zt(i,k) = 0.0_r8 + end do + end do ! Compute some inputs from the thermodynamic grid @@ -3358,6 +3340,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Implementation after Thomas Toniazzo (NorESM) and Colin Zarzycki (PSU) ! Other Surface fluxes provided by host model if( (cld_macmic_num_steps > 1) .and. clubb_l_intr_sfc_flux_smooth ) then + ! Adjust surface stresses using winds from the prior macmic iteration do i=1,ncol ubar = sqrt(state1%u(i,pver)**2+state1%v(i,pver)**2) @@ -3524,6 +3507,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_l_do_expldiff_rtm_thlm) then + do k=1,nzt_clubb do i=1, ncol edsclr_in(i,k+1,icnt+1) = thlm(i,pver-k+1) @@ -3757,7 +3741,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call endrun(subr//': Fatal error in CLUBB library') end if - if (do_rainturb) then + if ( do_rainturb ) then do k=1,nzm_clubb do i=1,ncol @@ -3923,39 +3907,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - call t_stopf('clubb_tend_cam:flip-index') - call t_startf('clubb_tend_cam:NAR') - - ! Accumulate vars through macmic subcycle - upwp_clubb_gw_mc(:ncol,:) = upwp_clubb_gw_mc(:ncol,:) + upwp(:ncol,:) - vpwp_clubb_gw_mc(:ncol,:) = vpwp_clubb_gw_mc(:ncol,:) + vpwp(:ncol,:) - thlp2_clubb_gw_mc(:ncol,:) = thlp2_clubb_gw_mc(:ncol,:) + thlp2(:ncol,:) - wpthlp_clubb_gw_mc(:ncol,:) = wpthlp_clubb_gw_mc(:ncol,:) + wpthlp(:ncol,:) - - ! And average at last macmic step - if (macmic_it == cld_macmic_num_steps) then - upwp_clubb_gw(:ncol,:) = upwp_clubb_gw_mc(:ncol,:)/REAL(cld_macmic_num_steps,r8) - vpwp_clubb_gw(:ncol,:) = vpwp_clubb_gw_mc(:ncol,:)/REAL(cld_macmic_num_steps,r8) - thlp2_clubb_gw(:ncol,:) = thlp2_clubb_gw_mc(:ncol,:)/REAL(cld_macmic_num_steps,r8) - wpthlp_clubb_gw(:ncol,:) = wpthlp_clubb_gw_mc(:ncol,:)/REAL(cld_macmic_num_steps,r8) - end if - - do k=1, nzm_clubb - do i=1, ncol - - mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & - * pdf_params_chnk(lchnk)%rt_1(i,k) & - + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & - * pdf_params_chnk(lchnk)%rt_2(i,k) - - pdfp_rtp2(i,pverp-k+1) = pdf_params_chnk(lchnk)%mixt_frac(i,k) & - * ( ( pdf_params_chnk(lchnk)%rt_1(i,k) - mean_rt )**2 & - + pdf_params_chnk(lchnk)%varnce_rt_1(i,k) ) & - + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & - * ( ( pdf_params_chnk(lchnk)%rt_2(i,k) - mean_rt )**2 & - + pdf_params_chnk(lchnk)%varnce_rt_2(i,k) ) - end do - end do do ixind=1,edsclr_dim do k=1, nzm_clubb @@ -3997,9 +3948,50 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end if - ! Values to use above top_lev, for variables that have not already been - ! set up there. These are mostly fill values that should not actually be - ! used in the run, but may end up in diagnostic output. + call t_stopf('clubb_tend_cam:flip-index') + + + call t_startf('clubb_tend_cam:NAR') + do k=1, pverp + do i=1, ncol + + ! Accumulate vars through macmic subcycle + upwp_clubb_gw_mc(i,k) = upwp_clubb_gw_mc(i,k) + upwp(i,k) + vpwp_clubb_gw_mc(i,k) = vpwp_clubb_gw_mc(i,k) + vpwp(i,k) + thlp2_clubb_gw_mc(i,k) = thlp2_clubb_gw_mc(i,k) + thlp2(i,k) + wpthlp_clubb_gw_mc(i,k) = wpthlp_clubb_gw_mc(i,k) + wpthlp(i,k) + + ! And average at last macmic step + if (macmic_it == cld_macmic_num_steps) then + upwp_clubb_gw(i,k) = upwp_clubb_gw_mc(i,k)/REAL(cld_macmic_num_steps,r8) + vpwp_clubb_gw(i,k) = vpwp_clubb_gw_mc(i,k)/REAL(cld_macmic_num_steps,r8) + thlp2_clubb_gw(i,k) = thlp2_clubb_gw_mc(i,k)/REAL(cld_macmic_num_steps,r8) + wpthlp_clubb_gw(i,k) = wpthlp_clubb_gw_mc(i,k)/REAL(cld_macmic_num_steps,r8) + end if + + end do + end do + + do k=1, nzm_clubb + do i=1, ncol + + mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & + * pdf_params_chnk(lchnk)%rt_1(i,k) & + + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & + * pdf_params_chnk(lchnk)%rt_2(i,k) + + pdfp_rtp2(i,pverp-k+1) = pdf_params_chnk(lchnk)%mixt_frac(i,k) & + * ( ( pdf_params_chnk(lchnk)%rt_1(i,k) - mean_rt )**2 & + + pdf_params_chnk(lchnk)%varnce_rt_1(i,k) ) & + + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & + * ( ( pdf_params_chnk(lchnk)%rt_2(i,k) - mean_rt )**2 & + + pdf_params_chnk(lchnk)%varnce_rt_2(i,k) ) + end do + end do + + ! Values to use above top_lev, for variables that have not already been + ! set up there. These are mostly fill values that should not actually be + ! used in the run, but may end up in diagnostic output. do k=1, top_lev-1 do i=1, ncol upwp(i,k) = 0._r8 @@ -4015,23 +4007,27 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + ! Fill up arrays needed for McICA. Note we do not want the ghost point, + ! thus why the second loop is needed. + do i=1, pcols + zi_out(i,1) = 0._r8 + end do + ! enforce zero tracer tendencies above the top_lev level -- no change icnt=0 do ixind=1,pcnst if (lq(ixind)) then icnt=icnt+1 - do i=1, ncol - edsclr_out(i,:top_lev-1,icnt) = state1%q(i,:top_lev-1,ixind) + do k=1, top_lev-1 + do i=1, ncol + edsclr_out(i,k,icnt) = state1%q(i,k,ixind) + end do end do end if end do - ! Fill up arrays needed for McICA. Note we do not want the ghost point, - ! thus why the second loop is needed. - zi_out(:,1) = 0._r8 - ! Compute static energy using CLUBB's variables do k=1,pver do i=1, ncol @@ -4059,16 +4055,23 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call pbuf_set_field(pbuf, clubbtop_idx, clubbtop) endif + do i=1, ncol + se_a(i) = 0._r8 + ke_a(i) = 0._r8 + wv_a(i) = 0._r8 + wl_a(i) = 0._r8 + + se_b(i) = 0._r8 + ke_b(i) = 0._r8 + wv_b(i) = 0._r8 + wl_b(i) = 0._r8 + end do - ! Compute integrals for static energy, kinetic energy, water vapor, and liquid water - ! after CLUBB is called. This is for energy conservation purposes. - se_a(:) = 0._r8 - ke_a(:) = 0._r8 - wv_a(:) = 0._r8 - wl_a(:) = 0._r8 - - do k=1,pver - do i=1, ncol + ! NO COLLAPSE(2) + do i=1, ncol + do k=1,pver + ! Compute integrals for static energy, kinetic energy, water vapor, and liquid water + ! after CLUBB is called. This is for energy conservation purposes. se_a(i) = se_a(i) + clubb_s(i,k)*state1%pdel(i,k)*rga ke_a(i) = ke_a(i) + 0.5_r8*(um(i,k)**2+vm(i,k)**2)*state1%pdel(i,k)*rga wv_a(i) = wv_a(i) + (rtm(i,k)-rcm(i,k))*state1%pdeldry(i,k)*rga @@ -4076,14 +4079,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - ! Do the same as above, but for before CLUBB was called. - se_b(:) = 0._r8 - ke_b(:) = 0._r8 - wv_b(:) = 0._r8 - wl_b(:) = 0._r8 - - do k=1, pver - do i=1, ncol + ! NO COLLAPSE(2) + do i=1, ncol + do k=1, pver + ! Do the same as above, but for before CLUBB was called. se_b(i) = se_b(i) + state1%s(i,k)*state1%pdel(i,k)*rga ke_b(i) = ke_b(i) + 0.5_r8*(state1%u(i,k)**2+state1%v(i,k)**2)*state1%pdel(i,k)*rga wv_b(i) = wv_b(i) + state1%q(i,k,ixq)*state1%pdeldry(i,k)*rga @@ -4125,34 +4124,45 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Now compute the tendencies of CLUBB to CAM, note that pverp is the ghost point ! for all variables and therefore is never called in this loop - rtm_integral_vtend(:) = 0._r8 - rtm_integral_ltend(:) = 0._r8 + do i=1, ncol + end do - do k=1, pver - do i=1, ncol + ! NO COLLAPSE(2) + do i=1, ncol - ptend_loc%u(i,k) = (um(i,k) - state1%u(i,k)) / hdtime ! east-west wind - ptend_loc%v(i,k) = (vm(i,k) - state1%v(i,k)) / hdtime ! north-south wind - ptend_loc%q(i,k,ixq) = (rtm(i,k) - rcm(i,k)-state1%q(i,k,ixq)) / hdtime ! water vapor - ptend_loc%q(i,k,ixcldliq) = (rcm(i,k) - state1%q(i,k,ixcldliq)) / hdtime ! Tendency of liquid water - ptend_loc%s(i,k) = (clubb_s(i,k) - state1%s(i,k)) / hdtime ! Tendency of static energy + rtm_integral_vtend(i) = 0._r8 + rtm_integral_ltend(i) = 0._r8 - rtm_integral_ltend(i) = rtm_integral_ltend(i) + ptend_loc%q(i,k,ixcldliq)*state1%pdel(i,k) - rtm_integral_vtend(i) = rtm_integral_vtend(i) + ptend_loc%q(i,k,ixq)*state1%pdel(i,k) + do k=1, pver - end do - end do + ptend_loc%u(i,k) = (um(i,k) - state1%u(i,k)) / hdtime ! east-west wind + ptend_loc%v(i,k) = (vm(i,k) - state1%v(i,k)) / hdtime ! north-south wind + ptend_loc%q(i,k,ixq) = (rtm(i,k) - rcm(i,k)-state1%q(i,k,ixq)) / hdtime ! water vapor + ptend_loc%q(i,k,ixcldliq) = (rcm(i,k) - state1%q(i,k,ixcldliq)) / hdtime ! Tendency of liquid water + ptend_loc%s(i,k) = (clubb_s(i,k) - state1%s(i,k)) / hdtime ! Tendency of static energy + + rtm_integral_ltend(i) = rtm_integral_ltend(i) + ptend_loc%q(i,k,ixcldliq)*state1%pdel(i,k) + rtm_integral_vtend(i) = rtm_integral_vtend(i) + ptend_loc%q(i,k,ixq)*state1%pdel(i,k) + + end do - rtm_integral_ltend(:) = rtm_integral_ltend(:)/gravit - rtm_integral_vtend(:) = rtm_integral_vtend(:)/gravit + rtm_integral_ltend(i) = rtm_integral_ltend(i)/gravit + rtm_integral_vtend(i) = rtm_integral_vtend(i)/gravit + + end do ! Accumulate Air Temperature Tendency (TTEND) for Gravity Wave parameterization - ttend_clubb_mc(:ncol,:pver) = ttend_clubb_mc(:ncol,:pver) + ptend_loc%s(:ncol,:pver)/cpair + do k=1, pver + do i=1, ncol + ttend_clubb_mc(i,k) = ttend_clubb_mc(i,k) + ptend_loc%s(i,k)/cpair - ! Average at last macmic step - if (macmic_it == cld_macmic_num_steps) then - ttend_clubb(:ncol,:) = ttend_clubb_mc(:ncol,:pver)/REAL(cld_macmic_num_steps,r8) - end if + ! Average at last macmic step + if (macmic_it == cld_macmic_num_steps) then + ttend_clubb(i,k) = ttend_clubb_mc(i,k) / REAL(cld_macmic_num_steps,r8) + end if + + end do + end do if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then @@ -4181,6 +4191,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + ! Add constant to ghost point so that output is not corrupted + wp3(:,pverp) = wp3(:,pverp) + wp3_const + rtpthlp(:,pverp) = rtpthlp(:,pverp) + rtpthlp_const + wpthlp(:,pverp) = wpthlp(:,pverp) + wpthlp_const + wprtp(:,pverp) = wprtp(:,pverp) + wprtp_const + else do k=1, pver @@ -4231,16 +4247,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld('ELEAK_CLUBB', eleak, pcols, lchnk) call outfld('TFIX_CLUBB', se_dis, pcols, lchnk) - ! Add constant to ghost point so that output is not corrupted - if (clubb_do_adv) then - if (macmic_it == cld_macmic_num_steps) then - wp3(:,pverp) = wp3(:,pverp) + wp3_const - rtpthlp(:,pverp) = rtpthlp(:,pverp) + rtpthlp_const - wpthlp(:,pverp) = wpthlp(:,pverp) + wpthlp_const - wprtp(:,pverp) = wprtp(:,pverp) + wprtp_const - end if - end if - ! ------------------------------------------------- ! ! End column computation of CLUBB, begin to apply ! ! and compute output, etc ! @@ -4392,6 +4398,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & det_ice(:ncol) = det_ice(:ncol)/1000._r8 ! divide by density of water + ! output moist basis to be consistent with history variable definition temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) call outfld( 'DPDLFLIQ', temp2d, pcols, lchnk) From 7b94963d8eb455e4f36cd93b68c5a622b34f16e8 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Mon, 14 Oct 2024 12:13:22 -0600 Subject: [PATCH 15/82] Some GPUization. --- src/physics/cam/clubb_intr.F90 | 274 ++++++++++++++++++--------------- 1 file changed, 150 insertions(+), 124 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 42e41c6e35..ca1aa2b215 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -3360,9 +3360,108 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif call t_stopf('clubb_tend_cam:NAR') + + call t_startf('clubb_tend_cam:acc_copyin') + + + !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & + !$acc gr%weights_zt2zm, gr%weights_zm2zt, & + !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & + !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & + !$acc nu_vert_res_dep%nu6, & + !$acc sclr_idx, clubb_params, & + !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & + !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & + !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & + !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & + !$acc radf, wpthlp_sfc, & + !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & + !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & + !$acc vm_ref, ug, vg, grid_dx, grid_dy, & + !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & + !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & + !$acc state1, state1%q, state1%pint ) & + !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & + !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & + !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & + !$acc rcm_inout, pdf_params_zm_chnk, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & + !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & + !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & + !$acc invrs_exner_zm, edsclr_in, rcm_in_layer_out, cloud_cover_out, zt_g, zi_g, khzm_out, & + !$acc qclvar_out, wm_zt, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & + !$acc w_down_in_cloud_out, invrs_tau_zm_out, khzt_out, thlprcp_out, & + !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & + !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & + !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & + !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & + !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & + !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & + !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & + !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & + !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) & + !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & + !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & + !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & + !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & + !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & + !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & + !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, edsclr_out, pdfp_rtp2, wprcp_out ) + + !$acc data if( sclr_dim > 0 ) & + !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & + !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) + + !$acc data if( edsclr_dim > 0 ) & + !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & + !$acc copy( edsclr_in ) + + !$acc data if( hydromet_dim > 0 ) & + !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & + !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) + call t_stopf('clubb_tend_cam:acc_copyin') + + call t_startf('clubb_tend_cam:flip-index') ! Need to flip arrays around for CLUBB core + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb do i = 1, ncol @@ -3395,17 +3494,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rcm_inout(i,k) = state1%q(i,pverp-k+1,ixcldliq) end if - ! We only need to copy pdf_params from pbuf if this is a restart and - ! we're calling pdf_closure at the end of advance_clubb_core - if ( is_first_restart_step() & - .and. clubb_config_flags%ipdf_call_placement .eq. ipdf_post_advance_fields ) then - pdf_params_zm_chnk(lchnk)%w_1(i,k) = pdf_zm_w_1(i,pverp-k+1) - pdf_params_zm_chnk(lchnk)%w_2(i,k) = pdf_zm_w_2(i,pverp-k+1) - pdf_params_zm_chnk(lchnk)%varnce_w_1(i,k) = pdf_zm_varnce_w_1(i,pverp-k+1) - pdf_params_zm_chnk(lchnk)%varnce_w_2(i,k) = pdf_zm_varnce_w_2(i,pverp-k+1) - pdf_params_zm_chnk(lchnk)%mixt_frac(i,k) = pdf_zm_mixt_frac(i,pverp-k+1) - end if - wp2rtp_inout(i,k) = wp2rtp(i,pverp-k+1) wp2thlp_inout(i,k) = wp2thlp(i,pverp-k+1) uprcp_inout(i,k) = uprcp(i,pverp-k+1) @@ -3420,12 +3508,30 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + ! We only need to copy pdf_params from pbuf if this is a restart and + ! we're calling pdf_closure at the end of advance_clubb_core + if ( is_first_restart_step() & + .and. clubb_config_flags%ipdf_call_placement .eq. ipdf_post_advance_fields ) then + !$acc parallel loop gang vector collapse(2) default(present) + do k = 1, nzm_clubb + do i = 1, ncol + pdf_params_zm_chnk(lchnk)%w_1(i,k) = pdf_zm_w_1(i,pverp-k+1) + pdf_params_zm_chnk(lchnk)%w_2(i,k) = pdf_zm_w_2(i,pverp-k+1) + pdf_params_zm_chnk(lchnk)%varnce_w_1(i,k) = pdf_zm_varnce_w_1(i,pverp-k+1) + pdf_params_zm_chnk(lchnk)%varnce_w_2(i,k) = pdf_zm_varnce_w_2(i,pverp-k+1) + pdf_params_zm_chnk(lchnk)%mixt_frac(i,k) = pdf_zm_mixt_frac(i,pverp-k+1) + end do + end do + end if + + !$acc parallel loop gang vector collapse(2) default(present) do k=2, nzm_clubb do i=1,ncol pre_in(i,k) = prer_evap(i,pverp-k+1) end do end do + !$acc parallel loop gang vector default(present) do i=1,ncol pre_in(i,1) = pre_in(i,2) rcm_inout(i,1) = rcm_inout(i,2) @@ -3492,12 +3598,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & icnt = icnt+1 + !$acc parallel loop gang vector collapse(2) default(present) do k=1,nzt_clubb do i=1,ncol edsclr_in(i,k+1,icnt) = state1%q(i,pver-k+1,ixind) end do end do + !$acc parallel loop gang vector default(present) do i=1,ncol edsclr_in(i,1,icnt) = edsclr_in(i,2,icnt) end do @@ -3508,6 +3616,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_l_do_expldiff_rtm_thlm) then + !$acc parallel loop gang vector collapse(2) default(present) do k=1,nzt_clubb do i=1, ncol edsclr_in(i,k+1,icnt+1) = thlm(i,pver-k+1) @@ -3515,6 +3624,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + !$acc parallel loop gang vector default(present) do i=1, ncol edsclr_in(i,1,icnt+1) = edsclr_in(i,2,icnt+1) edsclr_in(i,1,icnt+2) = edsclr_in(i,2,icnt+2) @@ -3524,94 +3634,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:flip-index') - - call t_startf('clubb_tend_cam:acc_copyin') - !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & - !$acc gr%weights_zt2zm, gr%weights_zm2zt, & - !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & - !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & - !$acc nu_vert_res_dep%nu6, & - !$acc sclr_idx, clubb_params, & - !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & - !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & - !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & - !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & - !$acc radf, wpthlp_sfc, & - !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & - !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & - !$acc vm_ref, ug, vg, grid_dx, grid_dy, & - !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk) ) & - !$acc copy( um_in, upwp_in, vm_in, vpwp_in, up2_in, vp2_in, up3_in, vp3_in, rtm_in, & - !$acc wprtp_in, thlm_in, wpthlp_in, rtp2_in, & - !$acc rtp3_in, thlp2_in, thlp3_in, rtpthlp_in, wp2_in, wp3_in, & - !$acc p_in_Pa, exner, rcm_inout, cloud_frac_inout, wpthvp_in, wp2thvp_in, & - !$acc rtpthvp_in, thlpthvp_in, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & - !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & - !$acc ice_supersat_frac_inout, um_pert_inout, & - !$acc vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & - !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & - !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & - !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & - !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & - !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & - !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & - !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & - !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & - !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) & - !$acc copyout( rcm_in_layer_out, cloud_cover_out, wprcp_out, w_up_in_cloud_out, w_down_in_cloud_out, & - !$acc cloudy_updraft_frac_out, cloudy_downdraft_frac_out, invrs_tau_zm_out, khzt_out, & - !$acc khzm_out, thlprcp_out, qclvar_out ) - - !$acc data if( sclr_dim > 0 ) & - !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & - !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) - - !$acc data if( edsclr_dim > 0 ) & - !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & - !$acc copy( edsclr_in ) - - !$acc data if( hydromet_dim > 0 ) & - !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & - !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) - call t_stopf('clubb_tend_cam:acc_copyin') - do t=1,nadv ! do needed number of "sub" timesteps for each CAM step ! Increment the statistics then begin stats timestep @@ -3807,13 +3829,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo ! end time loop call t_startf('clubb_tend_cam:NAR') - call t_startf('clubb_tend_cam:acc_copyout') - !$acc end data - !$acc end data - !$acc end data - !$acc end data - call t_stopf('clubb_tend_cam:acc_copyout') - if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then @@ -3848,7 +3863,9 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:flip-index') + ! Arrays need to be "flipped" to CAM grid + !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb do i=1, ncol um(i,pverp-k+1) = um_in(i,k) @@ -3909,6 +3926,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do do ixind=1,edsclr_dim + !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb do i=1, ncol edsclr_out(i,pverp-k+1,ixind) = edsclr_in(i,k,ixind) @@ -3948,9 +3966,35 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end if + !$acc parallel loop gang vector collapse(2) default(present) + do k=1, nzm_clubb + do i=1, ncol + + mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & + * pdf_params_chnk(lchnk)%rt_1(i,k) & + + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & + * pdf_params_chnk(lchnk)%rt_2(i,k) + + pdfp_rtp2(i,pverp-k+1) = pdf_params_chnk(lchnk)%mixt_frac(i,k) & + * ( ( pdf_params_chnk(lchnk)%rt_1(i,k) - mean_rt )**2 & + + pdf_params_chnk(lchnk)%varnce_rt_1(i,k) ) & + + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & + * ( ( pdf_params_chnk(lchnk)%rt_2(i,k) - mean_rt )**2 & + + pdf_params_chnk(lchnk)%varnce_rt_2(i,k) ) + end do + end do + call t_stopf('clubb_tend_cam:flip-index') + call t_startf('clubb_tend_cam:acc_copyout') + !$acc end data + !$acc end data + !$acc end data + !$acc end data + call t_stopf('clubb_tend_cam:acc_copyout') + + call t_startf('clubb_tend_cam:NAR') do k=1, pverp do i=1, ncol @@ -3972,23 +4016,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - do k=1, nzm_clubb - do i=1, ncol - - mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & - * pdf_params_chnk(lchnk)%rt_1(i,k) & - + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & - * pdf_params_chnk(lchnk)%rt_2(i,k) - - pdfp_rtp2(i,pverp-k+1) = pdf_params_chnk(lchnk)%mixt_frac(i,k) & - * ( ( pdf_params_chnk(lchnk)%rt_1(i,k) - mean_rt )**2 & - + pdf_params_chnk(lchnk)%varnce_rt_1(i,k) ) & - + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & - * ( ( pdf_params_chnk(lchnk)%rt_2(i,k) - mean_rt )**2 & - + pdf_params_chnk(lchnk)%varnce_rt_2(i,k) ) - end do - end do - ! Values to use above top_lev, for variables that have not already been ! set up there. These are mostly fill values that should not actually be ! used in the run, but may end up in diagnostic output. @@ -4398,7 +4425,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & det_ice(:ncol) = det_ice(:ncol)/1000._r8 ! divide by density of water - ! output moist basis to be consistent with history variable definition temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) call outfld( 'DPDLFLIQ', temp2d, pcols, lchnk) From 7786ccaad5104b528bd0a26871c3d9772c4f0ec9 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Tue, 15 Oct 2024 14:13:59 -0600 Subject: [PATCH 16/82] Small bug fixes --- src/physics/cam/clubb_intr.F90 | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index ca1aa2b215..1c8498a2a7 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2897,9 +2897,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Perturbed winds are not used in CAM upwp_sfc_pert(i) = 0.0_r8 vpwp_sfc_pert(i) = 0.0_r8 - - ! higher order scalar stuff, put to zero - wpsclrp_sfc(i,sclr) = 0._r8 end do ! higher order scalar stuff, put to zero @@ -2917,6 +2914,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + do sclr = 1, sclr_dim + do i=1, ncol + wpsclrp_sfc(i,sclr) = 0._r8 + end do + end do + do ixind=1, hydromet_dim do k=1, nzm_clubb do i=1, ncol @@ -2931,7 +2934,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Initialize forcings for transported scalars to zero do sclr = 1, sclr_dim - do i = 1, pcols + do i = 1, ncol do k = 1, nzm_clubb sclrm_forcing(i,k,sclr) = 0._r8 sclrm(i,k,sclr) = 0._r8 @@ -2940,7 +2943,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do do edsclr = 1, edsclr_dim - do i = 1, pcols + do i = 1, ncol do k = 1, nzm_clubb edsclrm_forcing(i,k,edsclr) = 0._r8 edsclr_in(i,k,edsclr) = 0._r8 @@ -3380,11 +3383,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc vm_ref, ug, vg, grid_dx, grid_dy, & !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & - !$acc state1, state1%q, state1%pint ) & + !$acc state1, state1%q, state1%pint, prer_evap ) & !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & - !$acc rcm_inout, pdf_params_zm_chnk, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & + !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & !$acc invrs_exner_zm, edsclr_in, rcm_in_layer_out, cloud_cover_out, zt_g, zi_g, khzm_out, & From 0d391b1b0a59dd80a5dfaff8a67b804b01b6d0ed Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Tue, 15 Oct 2024 15:40:48 -0600 Subject: [PATCH 17/82] Tweaks to acc data statement. This version passed the GPU ect test. --- src/physics/cam/clubb_intr.F90 | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 1c8498a2a7..e1c6d506cb 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -3383,16 +3383,25 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc vm_ref, ug, vg, grid_dx, grid_dy, & !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & - !$acc state1, state1%q, state1%pint, prer_evap ) & + !$acc state1, state1%q, prer_evap ) & !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & - !$acc invrs_exner_zm, edsclr_in, rcm_in_layer_out, cloud_cover_out, zt_g, zi_g, khzm_out, & - !$acc qclvar_out, wm_zt, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & - !$acc w_down_in_cloud_out, invrs_tau_zm_out, khzt_out, thlprcp_out, & + !$acc invrs_exner_zm, & + !$acc qclvar_out, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & + !$acc w_down_in_cloud_out, invrs_tau_zm_out ) & + !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & + !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & + !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & + !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & + !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & + !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & + !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wprcp_out, & + !$acc khzt_out, khzm_out, thlprcp_out, rcm_in_layer_out, cloud_cover_out, & + !$acc zi_g, zt_g, & !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & @@ -3438,14 +3447,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) & - !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & - !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & - !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & - !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & - !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & - !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & - !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, edsclr_out, pdfp_rtp2, wprcp_out ) + !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) !$acc data if( sclr_dim > 0 ) & !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & @@ -3453,7 +3455,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc data if( edsclr_dim > 0 ) & !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & - !$acc copy( edsclr_in ) + !$acc copy( edsclr_in, edsclr_out ) !$acc data if( hydromet_dim > 0 ) & !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & @@ -3817,7 +3819,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:do_cldcool') end if - + ! Check to see if stats should be output, here stats are read into ! output arrays to make them conformable to CAM output if (stats_metadata%l_stats) then From cf5883468a10760b7e33e377e75fbb73b9c4b78a Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Tue, 15 Oct 2024 22:42:06 -0600 Subject: [PATCH 18/82] More GPUization and small changes. ECT passed on CPU and GPU. --- src/physics/cam/clubb_intr.F90 | 391 +++++++++++++++++---------------- 1 file changed, 206 insertions(+), 185 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index e1c6d506cb..c7c5ad80b2 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2590,7 +2590,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & nzm_clubb, & nzt_clubb, & sclr, & - edsclr + edsclr, & + n #endif @@ -2606,6 +2607,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if ( do_clubb_mf ) call endrun(subr//': do_clubb_mf=.true. not available when compiling with OpenACC') if ( do_rainturb ) call endrun(subr//': do_rainturb=.true. not available when compiling with OpenACC') if ( do_cldcool ) call endrun(subr//': do_cldcool=.true. not available when compiling with OpenACC') + if ( clubb_do_icesuper ) call endrun(subr//': clubb_do_icesuper=.true. not available when compiling with OpenACC') + if ( single_column .and. .not. scm_cambfb_mode ) then + call endrun(subr//': (single_column && !scm_cambfb_mode)=.true. not available when compiling with OpenACC') + end if #endif !-----------------------------------------------------------------------------------! @@ -2732,6 +2737,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_do_liqsupersat) then call pbuf_get_field(pbuf, npccn_idx, npccn) endif + + ! Define the grid box size. CLUBB needs this information to determine what + ! the maximum length scale should be. This depends on the column for + ! variable mesh grids and lat-lon grids + call grid_size(state1, grid_dx, grid_dy) @@ -2834,11 +2844,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ztodtptr(:) = 1.0_r8*hdtime - ! Determine Coriolis force at given latitude. This is never used - ! when CLUBB is implemented in a host model, therefore just set - ! to zero. - fcor(:) = 0._r8 - call t_startf('clubb_tend_cam:NAR') do k = 1, pverp @@ -2897,6 +2902,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Perturbed winds are not used in CAM upwp_sfc_pert(i) = 0.0_r8 vpwp_sfc_pert(i) = 0.0_r8 + + ! Determine Coriolis force at given latitude. This is never used + ! when CLUBB is implemented in a host model, therefore just set + ! to zero. + fcor(i) = 0._r8 end do ! higher order scalar stuff, put to zero @@ -2910,10 +2920,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & sclrprtp(i,k,sclr) = 0._r8 sclrpthlp(i,k,sclr) = 0._r8 sclrpthvp_inout(i,k,sclr) = 0._r8 + sclrm_forcing(i,k,sclr) = 0._r8 end do end do end do - + do sclr = 1, sclr_dim do i=1, ncol wpsclrp_sfc(i,sclr) = 0._r8 @@ -2932,16 +2943,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - ! Initialize forcings for transported scalars to zero - do sclr = 1, sclr_dim - do i = 1, ncol - do k = 1, nzm_clubb - sclrm_forcing(i,k,sclr) = 0._r8 - sclrm(i,k,sclr) = 0._r8 - end do - end do - end do - do edsclr = 1, edsclr_dim do i = 1, ncol do k = 1, nzm_clubb @@ -3000,13 +3001,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end if - - ! Define the grid box size. CLUBB needs this information to determine what - ! the maximum length scale should be. This depends on the column for - ! variable mesh grids and lat-lon grids - - call grid_size(state1, grid_dx, grid_dy) - call t_stopf('clubb_tend_cam:NAR') if (clubb_do_icesuper) then @@ -3073,22 +3067,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_startf('clubb_tend_cam:NAR') - ! Compute inverse exner function consistent with CLUBB's definition, which uses a constant - ! surface pressure. CAM's exner (in state) does not. Therefore, for consistent - ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables - ! (such as thlm), use "inv_exner_clubb" otherwise use the exner in state - do k=1,pver - do i=1,ncol - inv_exner_clubb(i,k) = 1._r8/((state1%pmid(i,k)/p0_clubb)**(rairv(i,k,lchnk)/cpairv(i,k,lchnk))) - enddo - enddo - - ! Compute exner at the surface for converting the sensible heat fluxes - ! to a flux of potential temperature for use as clubb's boundary conditions - do i=1,ncol - inv_exner_clubb_surf(i) = 1._r8/((state1%pmid(i,pver)/p0_clubb)**(rairv(i,pver,lchnk)/cpairv(i,pver,lchnk))) - enddo - if (clubb_do_adv) then if (macmic_it == 1) then @@ -3135,102 +3113,213 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - call physics_ptend_init( ptend_loc, state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq ) + call t_startf('clubb_tend_cam:acc_copyin') + !$acc data copyin( sclr_idx, clubb_params, & + !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & + !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & + !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & + !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & + !$acc radf, wpthlp_sfc, clubb_params_single_col, & + !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & + !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & + !$acc vm_ref, ug, vg, grid_dx, grid_dy, & + !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & + !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & + !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, & + !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, & + !$acc cam_in, cam_in%shf, cam_in%wsx, cam_in%wsy, cam_in%cflx, & + !$acc rrho, prer_evap, inv_exner_clubb_surf, & + !$acc rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & + !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & + !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & + !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & + !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & + !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & + !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & + !$acc invrs_exner_zm, & + !$acc qclvar_out, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & + !$acc w_down_in_cloud_out, invrs_tau_zm_out ) & + !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & + !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & + !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & + !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & + !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & + !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & + !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wprcp_out, & + !$acc khzt_out, khzm_out, thlprcp_out, rcm_in_layer_out, cloud_cover_out, & + !$acc zi_g, zt_g, qrl_clubb, qrl, thv, dz_g, radf_clubb, & + !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & + !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & + !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & + !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & + !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & + !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & + !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & + !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & + !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) - !REMOVECAM - no longer need this when CAM is retired and pcols no longer exists - troplev(:) = 0 - !REMOVECAM_END - call tropopause_findChemTrop( state, troplev ) + !$acc data if( sclr_dim > 0 ) & + !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & + !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) + + !$acc data if( edsclr_dim > 0 ) & + !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & + !$acc copy( edsclr_in, edsclr_out ) + + !$acc data if( hydromet_dim > 0 ) & + !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & + !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) + call t_stopf('clubb_tend_cam:acc_copyin') ! Define the CLUBB momentum grid (in height, units of m) + !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb do i=1, ncol - zi_g(i,k) = state1%zi(i,pverp-k+1)-state1%zi(i,pver+1) + zi_g(i,k) = state1%zi(i,pverp-k+1) - state1%zi(i,pver+1) end do end do + !$acc parallel loop gang vector collapse(2) default(present) do k=1, pver do i=1, ncol + + ! Compute inverse exner function consistent with CLUBB's definition, which uses a constant + ! surface pressure. CAM's exner (in state) does not. Therefore, for consistent + ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables + ! (such as thlm), use "inv_exner_clubb" otherwise use the exner in state + inv_exner_clubb(i,k) = 1._r8/((state1%pmid(i,k)/p0_clubb)**(rairv(i,k,lchnk)/cpairv(i,k,lchnk))) ! Compute virtual potential temperature, which is needed for CLUBB - thv(i,k) = state1%t(i,k)*inv_exner_clubb(i,k)*(1._r8+zvir*state1%q(i,k,ixq)& - -state1%q(i,k,ixcldliq)) + thv(i,k) = state1%t(i,k) * inv_exner_clubb(i,k) & + * ( 1._r8 + zvir * state1%q(i,k,ixq) - state1%q(i,k,ixcldliq) ) - dz_g(i,k) = state1%zi(i,k)-state1%zi(i,k+1) ! compute thickness + dz_g(i,k) = state1%zi(i,k) - state1%zi(i,k+1) ! compute thickness ! At each CLUBB call, initialize mean momentum and thermo CLUBB state ! from the CAM state - rtm(i,k) = state1%q(i,k,ixq)+state1%q(i,k,ixcldliq) + rtm(i,k) = state1%q(i,k,ixq) + state1%q(i,k,ixcldliq) rvm(i,k) = state1%q(i,k,ixq) um(i,k) = state1%u(i,k) vm(i,k) = state1%v(i,k) - thlm(i,k) = ( state1%t(i,k) & - - (latvap/cpairv(i,k,lchnk))*state1%q(i,k,ixcldliq) ) & + thlm(i,k) = ( state1%t(i,k) - ( latvap / cpairv(i,k,lchnk) ) * state1%q(i,k,ixcldliq) ) & * inv_exner_clubb(i,k) enddo enddo + !$acc parallel loop gang vector default(present) do i = 1, ncol rtm(i,pverp) = rtm(i,pver) um(i,pverp) = state1%u(i,pver) vm(i,pverp) = state1%v(i,pver) thlm(i,pverp) = thlm(i,pver) + + ! Compute exner at the surface for converting the sensible heat fluxes + ! to a flux of potential temperature for use as clubb's boundary conditions + inv_exner_clubb_surf(i) = 1._r8/((state1%pmid(i,pver)/p0_clubb)**(rairv(i,pver,lchnk)/cpairv(i,pver,lchnk))) end do ! Compute thermodynamic stuff needed for CLUBB on thermo levels. ! Inputs for the momentum levels are set below setup_clubb core + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzt_clubb do i = 1, ncol ! Define the CLUBB thermodynamic grid (in units of m) - zt_g(i,k+1) = state1%zm(i,pver-k+1)-state1%zi(i,pver+1) + zt_g(i,k+1) = state1%zm(i,pver-k+1) - state1%zi(i,pver+1) ! base state (dry) variables - rho_ds_zt(i,k+1) = rga*(state1%pdeldry(i,pver-k+1)/dz_g(i,pver-k+1)) - invrs_rho_ds_zt(i,k+1) = 1._r8/(rho_ds_zt(i,k+1)) + rho_ds_zt(i,k+1) = rga * ( state1%pdeldry(i,pver-k+1) / dz_g(i,pver-k+1) ) + invrs_rho_ds_zt(i,k+1) = 1._r8 / rho_ds_zt(i,k+1) ! full state (moist) variables p_in_Pa(i,k+1) = state1%pmid(i,pver-k+1) - exner(i,k+1) = 1._r8/inv_exner_clubb(i,pver-k+1) - thv(i,k+1) = state1%t(i,pver-k+1)*inv_exner_clubb(i,pver-k+1)*(1._r8+zvir*state1%q(i,pver-k+1,ixq) & - -state1%q(i,pver-k+1,ixcldliq)) - rho_zt(i,k+1) = rga*state1%pdel(i,pver-k+1)/dz_g(i,pver-k+1) + exner(i,k+1) = 1._r8 / inv_exner_clubb(i,pver-k+1) + thv(i,k+1) = state1%t(i,pver-k+1) * inv_exner_clubb(i,pver-k+1) & + * ( 1._r8 + zvir * state1%q(i,pver-k+1,ixq) - state1%q(i,pver-k+1,ixcldliq) ) + rho_zt(i,k+1) = rga * state1%pdel(i,pver-k+1) / dz_g(i,pver-k+1) ! exception - setting this to moist thv thv_ds_zt(i,k+1) = thv(i,k+1) rfrzm(i,k+1) = state1%q(i,pver-k+1,ixcldice) radf(i,k+1) = radf_clubb(i,pver-k+1) - qrl_clubb(i,k+1) = qrl(i,pver-k+1)/(cpairv(i,k,lchnk)*state1%pdeldry(i,pver-k+1)) + qrl_clubb(i,k+1) = qrl(i,pver-k+1) / ( cpairv(i,k,lchnk) * state1%pdeldry(i,pver-k+1) ) ! Compute mean w wind on thermo grid, convert from omega to w - wm_zt(i,k+1) = -1._r8*(state1%omega(i,pver-k+1)-state1%omega(i,pver))/(rho_zt(i,k+1)*gravit) + wm_zt(i,k+1) = -1._r8 * ( state1%omega(i,pver-k+1) - state1%omega(i,pver) ) & + / (rho_zt(i,k+1) * gravit) end do end do ! Below computes the same stuff for the ghost point. May or may ! not be needed, just to be safe to avoid NaN's + !$acc parallel loop gang vector default(present) do i = 1, ncol - thv_ds_zt(i,1) = thv_ds_zt(i,2) + zt_g(i,1) = -1._r8 * zt_g(i,2) rho_ds_zt(i,1) = rho_ds_zt(i,2) invrs_rho_ds_zt(i,1) = invrs_rho_ds_zt(i,2) p_in_Pa(i,1) = p_in_Pa(i,2) exner(i,1) = exner(i,2) thv(i,1) = thv(i,2) rho_zt(i,1) = rho_zt(i,2) + thv_ds_zt(i,1) = thv_ds_zt(i,2) rfrzm(i,1) = rfrzm(i,2) radf(i,1) = radf(i,2) qrl_clubb(i,1) = qrl_clubb(i,2) wm_zt(i,1) = wm_zt(i,2) - zt_g(i,1) = -1._r8*zt_g(i,2) ! Set the elevation of the surface sfc_elevation(i) = state1%zi(i,pverp) end do + !$acc parallel loop gang vector collapse(2) default(present) + do i = 1, ncol + do n = 1, nparams + clubb_params(i,n) = clubb_params_single_col(n) + end do + end do + + ! ------------------------------------------------- ! ! Begin case specific code for SCAM cases. ! ! This section of code block is NOT called in ! @@ -3289,31 +3378,49 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Important note: do not make any calls that use CLUBB grid-height ! operators (such as zt2zm_api, etc.) until AFTER the ! call to setup_grid_heights_api. + + !$acc update host( zi_g, zt_g, clubb_params, sfc_elevation ) + call setup_grid_api( nzm_clubb, ncol, sfc_elevation, l_implemented, & ! intent(in) grid_type, zi_g(:,2), zi_g(:,1), zi_g(:,nzm_clubb), & ! intent(in) zi_g, zt_g, & ! intent(in) gr ) ! intent(out) - do i = 1, ncol - clubb_params(i,:) = clubb_params_single_col(:) - end do call setup_parameters_api( zi_g(:,2), clubb_params, gr, ncol, grid_type, & ! intent(in) clubb_config_flags%l_prescribed_avg_deltaz, & ! intent(in) lmin, nu_vert_res_dep, err_code ) ! intent(out) + !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & + !$acc gr%weights_zt2zm, gr%weights_zm2zt, & + !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & + !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & + !$acc nu_vert_res_dep%nu6) + if ( err_code == clubb_fatal_error ) then call endrun(subr//': Fatal error in CLUBB setup_parameters') end if + !$acc parallel loop gang vector collapse(2) default(present) + do k = 1, nzm_clubb + do i = 1, ncol + rtp2_forcing = rtp2_mc_zt(i,k) + thlp2_forcing = thlp2_mc_zt(i,k) + wprtp_forcing = wprtp_mc_zt(i,k) + wpthlp_forcing = wpthlp_mc_zt(i,k) + rtpthlp_forcing = rtpthlp_mc_zt(i,k) + end do + end do + ! Add forcings for SILHS covariance contributions - rtp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtp2_mc_zt(1:ncol,:) ) - thlp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, thlp2_mc_zt(1:ncol,:) ) - wprtp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wprtp_mc_zt(1:ncol,:) ) - wpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wpthlp_mc_zt(1:ncol,:) ) - rtpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtpthlp_mc_zt(1:ncol,:) ) + rtp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtp2_forcing ) + thlp2_forcing = zt2zm_api( nzm_clubb, ncol, gr, thlp2_forcing ) + wprtp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wprtp_forcing ) + wpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, wpthlp_forcing ) + rtpthlp_forcing = zt2zm_api( nzm_clubb, ncol, gr, rtpthlp_forcing ) ! Zero out SILHS covariance contribution terms + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, pverp do i = 1, pcols rtp2_mc_zt(i,k) = 0.0_r8 @@ -3334,6 +3441,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wm_zm = zt2zm_api( nzm_clubb, ncol, gr, wm_zt ) ! Surface fluxes provided by host model + !$acc parallel loop gang vector default(present) do i=1,ncol wpthlp_sfc(i) = cam_in%shf(i)/(cpairv(i,pver,lchnk)*rho_ds_zm(i,1)) ! Sensible heat flux wpthlp_sfc(i) = wpthlp_sfc(i)*inv_exner_clubb_surf(i) ! Potential temperature flux @@ -3344,123 +3452,32 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Other Surface fluxes provided by host model if( (cld_macmic_num_steps > 1) .and. clubb_l_intr_sfc_flux_smooth ) then - ! Adjust surface stresses using winds from the prior macmic iteration - do i=1,ncol - ubar = sqrt(state1%u(i,pver)**2+state1%v(i,pver)**2) - if (ubar < 0.25_r8) ubar = 0.25_r8 - - call calc_ustar( state1%t(i,pver), state1%pmid(i,pver), cam_in%wsx(i), cam_in%wsy(i), & - rrho(i), ustar ) - - upwp_sfc(i) = -state1%u(i,pver)*ustar**2/ubar - vpwp_sfc(i) = -state1%v(i,pver)*ustar**2/ubar - end do - else - do i=1,ncol - upwp_sfc(i) = cam_in%wsx(i)/rho_ds_zm(i,1) ! Surface meridional momentum flux - vpwp_sfc(i) = cam_in%wsy(i)/rho_ds_zm(i,1) ! Surface zonal momentum flux - end do - endif - call t_stopf('clubb_tend_cam:NAR') + !$acc update host( state1%u, state1%v, state1%t, state1%pmid, cam_in%wsx, cam_in%wsy, rrho ) + ! Adjust surface stresses using winds from the prior macmic iteration + do i=1,ncol + ubar = sqrt(state1%u(i,pver)**2+state1%v(i,pver)**2) + if (ubar < 0.25_r8) ubar = 0.25_r8 - call t_startf('clubb_tend_cam:acc_copyin') + call calc_ustar( state1%t(i,pver), state1%pmid(i,pver), cam_in%wsx(i), cam_in%wsy(i), & + rrho(i), ustar ) + upwp_sfc(i) = -state1%u(i,pver)*ustar**2/ubar + vpwp_sfc(i) = -state1%v(i,pver)*ustar**2/ubar + end do - !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & - !$acc gr%weights_zt2zm, gr%weights_zm2zt, & - !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & - !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & - !$acc nu_vert_res_dep%nu6, & - !$acc sclr_idx, clubb_params, & - !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & - !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & - !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & - !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & - !$acc radf, wpthlp_sfc, & - !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & - !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & - !$acc vm_ref, ug, vg, grid_dx, grid_dy, & - !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & - !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & - !$acc state1, state1%q, prer_evap ) & - !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & - !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & - !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & - !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & - !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & - !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & - !$acc invrs_exner_zm, & - !$acc qclvar_out, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & - !$acc w_down_in_cloud_out, invrs_tau_zm_out ) & - !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & - !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & - !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & - !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & - !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & - !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & - !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wprcp_out, & - !$acc khzt_out, khzm_out, thlprcp_out, rcm_in_layer_out, cloud_cover_out, & - !$acc zi_g, zt_g, & - !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & - !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & - !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & - !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & - !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & - !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & - !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & - !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & - !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) + !$acc update device( upwp_sfc, vpwp_sfc ) - !$acc data if( sclr_dim > 0 ) & - !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & - !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) + else - !$acc data if( edsclr_dim > 0 ) & - !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & - !$acc copy( edsclr_in, edsclr_out ) + !$acc parallel loop gang vector default(present) + do i=1,ncol + upwp_sfc(i) = cam_in%wsx(i)/rho_ds_zm(i,1) ! Surface meridional momentum flux + vpwp_sfc(i) = cam_in%wsy(i)/rho_ds_zm(i,1) ! Surface zonal momentum flux + end do - !$acc data if( hydromet_dim > 0 ) & - !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & - !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) - call t_stopf('clubb_tend_cam:acc_copyin') + endif + call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:flip-index') @@ -3997,6 +4014,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc end data !$acc end data !$acc end data + !$acc end data call t_stopf('clubb_tend_cam:acc_copyout') @@ -4154,12 +4172,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif + call physics_ptend_init( ptend_loc, state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq ) + ! Now compute the tendencies of CLUBB to CAM, note that pverp is the ghost point ! for all variables and therefore is never called in this loop - do i=1, ncol - end do - - ! NO COLLAPSE(2) do i=1, ncol rtm_integral_vtend(i) = 0._r8 @@ -4585,6 +4601,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! use the aist_vector function to compute the ice cloud fraction ! ! --------------------------------------------------------------------------------- ! + !REMOVECAM - no longer need this when CAM is retired and pcols no longer exists + troplev(:) = 0 + !REMOVECAM_END + call tropopause_findChemTrop( state, troplev ) + aist(:,:top_lev-1) = 0._r8 qsatfac(:, :) = 0._r8 ! Zero out entire profile in case qsatfac is left undefined in aist_vector below From e39e8a37f17ad0c3de2beb188ed51ccb5caaa3a1 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Tue, 15 Oct 2024 23:57:23 -0600 Subject: [PATCH 19/82] Bug fix that scarily did not break the CPU ECT test, but was detected by breaking BFBness. All these values are ~0 but not always exactly. --- src/physics/cam/clubb_intr.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index c7c5ad80b2..a5523211cb 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -3404,11 +3404,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb do i = 1, ncol - rtp2_forcing = rtp2_mc_zt(i,k) - thlp2_forcing = thlp2_mc_zt(i,k) - wprtp_forcing = wprtp_mc_zt(i,k) - wpthlp_forcing = wpthlp_mc_zt(i,k) - rtpthlp_forcing = rtpthlp_mc_zt(i,k) + rtp2_forcing(i,k) = rtp2_mc_zt(i,k) + thlp2_forcing(i,k) = thlp2_mc_zt(i,k) + wprtp_forcing(i,k) = wprtp_mc_zt(i,k) + wpthlp_forcing(i,k) = wpthlp_mc_zt(i,k) + rtpthlp_forcing(i,k) = rtpthlp_mc_zt(i,k) end do end do From e5e81fb630581140b73edad8d4bab39cceffcee1 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Wed, 16 Oct 2024 01:56:03 -0600 Subject: [PATCH 20/82] More GPUization. ECT passes for CPU and GPU, CPU is BFB. --- src/physics/cam/clubb_intr.F90 | 326 +++++++++++++++++---------------- 1 file changed, 170 insertions(+), 156 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index a5523211cb..a12002e51b 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2844,8 +2844,101 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ztodtptr(:) = 1.0_r8*hdtime + call t_startf('clubb_tend_cam:acc_copyin') + !$acc data copyin( sclr_idx, clubb_params_single_col, grid_dx, grid_dy, rairv, cpairv, radf_clubb, qrl, & + !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & + !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, & + !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, & + !$acc cam_in, cam_in%shf, cam_in%wsx, cam_in%wsy, cam_in%cflx, & + !$acc rrho, prer_evap, rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & + !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & + !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & + !$acc cloud_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & + !$acc wp2up2, wp2vp2, ice_supersat_frac ) & + !$acc copyout( temp2d, temp2dp, rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wm_zt_out, inv_exner_clubb, & + !$acc rcm, wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, thv, dz_g ) & + !$acc create( upwp_sfc_pert, vpwp_sfc_pert, khzt_out, khzm_out, & + !$acc fcor, um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & + !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & + !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & + !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & + !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & + !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & + !$acc invrs_exner_zm, cloud_cover_out, rcm_in_layer_out, wprcp_out, & + !$acc qclvar_out, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & + !$acc w_down_in_cloud_out, invrs_tau_zm_out, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & + !$acc thlm_forcing, rtm_forcing, um_forcing, vm_forcing, & + !$acc wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & + !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & + !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & + !$acc radf, wpthlp_sfc, clubb_params, sfc_elevation, wprtp_sfc, upwp_sfc, vpwp_sfc, & + !$acc rtm_ref, thlm_ref, um_ref, vm_ref, ug, vg, p_in_Pa, exner, um_pert_inout, & + !$acc inv_exner_clubb_surf, thlprcp_out, zi_g, zt_g, qrl_clubb, & + !$acc pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, pdf_zm_mixt_frac, & + !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & + !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & + !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & + !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & + !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & + !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & + !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & + !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & + !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& + !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & + !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & + !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & + !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & + !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & + !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & + !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & + !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) + + !$acc data if( sclr_dim > 0 ) & + !$acc create( wpsclrp_sfc, sclrm_forcing, sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout) & + !$acc copyin( sclr_tol ) + + !$acc data if( edsclr_dim > 0 ) & + !$acc create( wpedsclrp_sfc, edsclrm_forcing, edsclr_in ) & + !$acc copyout( edsclr_out ) + + !$acc data if( hydromet_dim > 0 ) & + !$acc create( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt ) & + !$acc copyin( hm_metadata, hm_metadata%l_mix_rat_hm ) + call t_stopf('clubb_tend_cam:acc_copyin') + + call t_startf('clubb_tend_cam:NAR') + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, pverp do i = 1, pcols rtp2_zt_out(i,k) = 0._r8 @@ -2858,6 +2951,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, pver do i = 1, pcols temp2d(i,k) = 0._r8 @@ -2865,6 +2959,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do + !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb do i = 1, ncol @@ -2898,6 +2993,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + !$acc parallel loop gang vector default(present) do i = 1, ncol ! Perturbed winds are not used in CAM upwp_sfc_pert(i) = 0.0_r8 @@ -2909,64 +3005,66 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & fcor(i) = 0._r8 end do - ! higher order scalar stuff, put to zero - do sclr = 1, sclr_dim - do k = 1, nzm_clubb - do i=1, ncol - sclrm(i,k,sclr) = 0._r8 - wpsclrp(i,k,sclr) = 0._r8 - sclrp2(i,k,sclr) = 0._r8 - sclrp3(i,k,sclr) = 0._r8 - sclrprtp(i,k,sclr) = 0._r8 - sclrpthlp(i,k,sclr) = 0._r8 - sclrpthvp_inout(i,k,sclr) = 0._r8 - sclrm_forcing(i,k,sclr) = 0._r8 + if ( sclr_dim > 0 ) then + ! higher order scalar stuff, put to zero + !$acc parallel loop gang vector collapse(3) default(present) + do sclr = 1, sclr_dim + do k = 1, nzm_clubb + do i=1, ncol + sclrm(i,k,sclr) = 0._r8 + wpsclrp(i,k,sclr) = 0._r8 + sclrp2(i,k,sclr) = 0._r8 + sclrp3(i,k,sclr) = 0._r8 + sclrprtp(i,k,sclr) = 0._r8 + sclrpthlp(i,k,sclr) = 0._r8 + sclrpthvp_inout(i,k,sclr) = 0._r8 + sclrm_forcing(i,k,sclr) = 0._r8 + end do end do end do - end do - - do sclr = 1, sclr_dim - do i=1, ncol - wpsclrp_sfc(i,sclr) = 0._r8 - end do - end do - - do ixind=1, hydromet_dim - do k=1, nzm_clubb + + !$acc parallel loop gang vector collapse(2) default(present) + do sclr = 1, sclr_dim do i=1, ncol - hydromet(i,k,ixind) = 0._r8 - wphydrometp(i,k,ixind) = 0._r8 - wp2hmp(i,k,ixind) = 0._r8 - rtphmp_zt(i,k,ixind) = 0._r8 - thlphmp_zt(i,k,ixind) = 0._r8 + wpsclrp_sfc(i,sclr) = 0._r8 end do end do - end do + end if - do edsclr = 1, edsclr_dim - do i = 1, ncol - do k = 1, nzm_clubb - edsclrm_forcing(i,k,edsclr) = 0._r8 - edsclr_in(i,k,edsclr) = 0._r8 + if ( hydromet_dim > 0 ) then + !$acc parallel loop gang vector collapse(3) default(present) + do ixind=1, hydromet_dim + do k=1, nzm_clubb + do i=1, ncol + hydromet(i,k,ixind) = 0._r8 + wphydrometp(i,k,ixind) = 0._r8 + wp2hmp(i,k,ixind) = 0._r8 + rtphmp_zt(i,k,ixind) = 0._r8 + thlphmp_zt(i,k,ixind) = 0._r8 + end do end do end do - end do + end if - ! Define surface sources for transported variables for diffusion, will - ! be zero as these tendencies are done in vertical_diffusion - do edsclr = 1, edsclr_dim - do i = 1, ncol - wpedsclrp_sfc(i,edsclr) = 0._r8 + if ( edsclr_dim > 0 ) then + !$acc parallel loop gang vector collapse(3) default(present) + do edsclr = 1, edsclr_dim + do i = 1, ncol + do k = 1, nzm_clubb + edsclrm_forcing(i,k,edsclr) = 0._r8 + edsclr_in(i,k,edsclr) = 0._r8 + end do + end do end do - end do - ! need to initialize macmic coupling to zero - if (macmic_it==1) then - ttend_clubb_mc(:ncol,:) = 0._r8 - upwp_clubb_gw_mc(:ncol,:) = 0._r8 - vpwp_clubb_gw_mc(:ncol,:) = 0._r8 - thlp2_clubb_gw_mc(:ncol,:) = 0._r8 - wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 + ! Define surface sources for transported variables for diffusion, will + ! be zero as these tendencies are done in vertical_diffusion + !$acc parallel loop gang vector collapse(2) default(present) + do edsclr = 1, edsclr_dim + do i = 1, ncol + wpedsclrp_sfc(i,edsclr) = 0._r8 + end do + end do end if @@ -3078,11 +3176,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & do i = 1, ncol thlp2(i,k) = state1%q(i,k,ixthlp2) rtp2(i,k) = state1%q(i,k,ixrtp2) - rtpthlp(i,k) = state1%q(i,k,ixrtpthlp) - (rtpthlp_const*apply_const) - wpthlp(i,k) = state1%q(i,k,ixwpthlp) - (wpthlp_const*apply_const) - wprtp(i,k) = state1%q(i,k,ixwprtp) - (wprtp_const*apply_const) + rtpthlp(i,k) = state1%q(i,k,ixrtpthlp) - ( rtpthlp_const * apply_const ) + wpthlp(i,k) = state1%q(i,k,ixwpthlp) - ( wpthlp_const * apply_const ) + wprtp(i,k) = state1%q(i,k,ixwprtp) - ( wprtp_const * apply_const ) wp2(i,k) = state1%q(i,k,ixwp2) - wp3(i,k) = state1%q(i,k,ixwp3) - (wp3_const*apply_const) + wp3(i,k) = state1%q(i,k,ixwp3) - ( wp3_const * apply_const ) up2(i,k) = state1%q(i,k,ixup2) vp2(i,k) = state1%q(i,k,ixvp2) enddo @@ -3113,102 +3211,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - call t_startf('clubb_tend_cam:acc_copyin') - !$acc data copyin( sclr_idx, clubb_params, & - !$acc fcor, sfc_elevation, thlm_forcing, rtm_forcing, um_forcing, & - !$acc vm_forcing, wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & - !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & - !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & - !$acc radf, wpthlp_sfc, clubb_params_single_col, & - !$acc wprtp_sfc, upwp_sfc, vpwp_sfc, & - !$acc upwp_sfc_pert, vpwp_sfc_pert, rtm_ref, thlm_ref, um_ref, & - !$acc vm_ref, ug, vg, grid_dx, grid_dy, & - !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & - !$acc p_in_Pa, exner, um_pert_inout, vm_pert_inout, upwp_pert_inout, vpwp_pert_inout, & - !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, & - !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, & - !$acc cam_in, cam_in%shf, cam_in%wsx, cam_in%wsy, cam_in%cflx, & - !$acc rrho, prer_evap, inv_exner_clubb_surf, & - !$acc rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & - !$acc create( um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & - !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & - !$acc thlp3_in, thlm_in, rtm_in, rvm_in, wprtp_in, wpthlp_in, rtpthlp_in, cloud_frac_inout, & - !$acc rcm_inout, wp2rtp_inout, wp2thlp_inout, uprcp_inout, vprcp_inout, & - !$acc rc_coef_inout, wp4_inout, wpup2_inout, wpvp2_inout, wp2up2_inout, wp2vp2_inout, & - !$acc ice_supersat_frac_inout, pre_in, kappa_zt, qc_zt, invrs_exner_zt, kappa_zm, p_in_Pa_zm, & - !$acc invrs_exner_zm, & - !$acc qclvar_out, rtp2_zt, thl2_zt, wp2_zt, w_up_in_cloud_out, cloudy_downdraft_frac_out, & - !$acc w_down_in_cloud_out, invrs_tau_zm_out ) & - !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & - !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & - !$acc cloud_frac, pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, & - !$acc pdf_zm_mixt_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & - !$acc wp2up2, wp2vp2, ice_supersat_frac, rairv, cpairv, inv_exner_clubb, rcm, & - !$acc wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, wm_zt_out, & - !$acc rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wprcp_out, & - !$acc khzt_out, khzm_out, thlprcp_out, rcm_in_layer_out, cloud_cover_out, & - !$acc zi_g, zt_g, qrl_clubb, qrl, thv, dz_g, radf_clubb, & - !$acc pdf_params_chnk(lchnk)%w_1, pdf_params_chnk(lchnk)%w_2, & - !$acc pdf_params_chnk(lchnk)%varnce_w_1, pdf_params_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_chnk(lchnk)%rt_1, pdf_params_chnk(lchnk)%rt_2, & - !$acc pdf_params_chnk(lchnk)%varnce_rt_1, pdf_params_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_chnk(lchnk)%thl_1, pdf_params_chnk(lchnk)%thl_2, & - !$acc pdf_params_chnk(lchnk)%varnce_thl_1, pdf_params_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_rt_1, pdf_params_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_chnk(lchnk)%corr_w_thl_1, pdf_params_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_chnk(lchnk)%corr_rt_thl_1, pdf_params_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_chnk(lchnk)%alpha_thl, pdf_params_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_chnk(lchnk)%crt_1, pdf_params_chnk(lchnk)%crt_2, pdf_params_chnk(lchnk)%cthl_1, & - !$acc pdf_params_chnk(lchnk)%cthl_2, pdf_params_chnk(lchnk)%chi_1, & - !$acc pdf_params_chnk(lchnk)%chi_2, pdf_params_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_chnk(lchnk)%stdev_chi_2, pdf_params_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_chnk(lchnk)%stdev_eta_2, pdf_params_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%covar_chi_eta_2, pdf_params_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_chi_2, pdf_params_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_w_eta_2, pdf_params_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_chnk(lchnk)%corr_chi_eta_2, pdf_params_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_chnk(lchnk)%rsatl_2, pdf_params_chnk(lchnk)%rc_1, pdf_params_chnk(lchnk)%rc_2, & - !$acc pdf_params_chnk(lchnk)%cloud_frac_1, pdf_params_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_chnk(lchnk)%mixt_frac, pdf_params_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_chnk(lchnk)%ice_supersat_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%w_1, pdf_params_zm_chnk(lchnk)%w_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_w_1, pdf_params_zm_chnk(lchnk)%varnce_w_2, & - !$acc pdf_params_zm_chnk(lchnk)%rt_1, pdf_params_zm_chnk(lchnk)%rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_rt_1, pdf_params_zm_chnk(lchnk)%varnce_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%thl_1, pdf_params_zm_chnk(lchnk)%thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%varnce_thl_1, pdf_params_zm_chnk(lchnk)%varnce_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_rt_1, pdf_params_zm_chnk(lchnk)%corr_w_rt_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_thl_1, pdf_params_zm_chnk(lchnk)%corr_w_thl_2, & - !$acc pdf_params_zm_chnk(lchnk)%corr_rt_thl_1, pdf_params_zm_chnk(lchnk)%corr_rt_thl_2,& - !$acc pdf_params_zm_chnk(lchnk)%alpha_thl, pdf_params_zm_chnk(lchnk)%alpha_rt, & - !$acc pdf_params_zm_chnk(lchnk)%crt_1, pdf_params_zm_chnk(lchnk)%crt_2, pdf_params_zm_chnk(lchnk)%cthl_1, & - !$acc pdf_params_zm_chnk(lchnk)%cthl_2, pdf_params_zm_chnk(lchnk)%chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%chi_2, pdf_params_zm_chnk(lchnk)%stdev_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_chi_2, pdf_params_zm_chnk(lchnk)%stdev_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%stdev_eta_2, pdf_params_zm_chnk(lchnk)%covar_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%covar_chi_eta_2, pdf_params_zm_chnk(lchnk)%corr_w_chi_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_chi_2, pdf_params_zm_chnk(lchnk)%corr_w_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_w_eta_2, pdf_params_zm_chnk(lchnk)%corr_chi_eta_1, & - !$acc pdf_params_zm_chnk(lchnk)%corr_chi_eta_2, pdf_params_zm_chnk(lchnk)%rsatl_1, & - !$acc pdf_params_zm_chnk(lchnk)%rsatl_2, pdf_params_zm_chnk(lchnk)%rc_1, pdf_params_zm_chnk(lchnk)%rc_2, & - !$acc pdf_params_zm_chnk(lchnk)%cloud_frac_1, pdf_params_zm_chnk(lchnk)%cloud_frac_2, & - !$acc pdf_params_zm_chnk(lchnk)%mixt_frac, pdf_params_zm_chnk(lchnk)%ice_supersat_frac_1, & - !$acc pdf_params_zm_chnk(lchnk)%ice_supersat_frac_2 ) - - !$acc data if( sclr_dim > 0 ) & - !$acc copyin( sclr_tol, sclrm_forcing, wpsclrp_sfc ) & - !$acc copy( sclrm, wpsclrp, sclrp2, sclrp3, sclrprtp, sclrpthlp, sclrpthvp_inout ) - - !$acc data if( edsclr_dim > 0 ) & - !$acc copyin( wpedsclrp_sfc, edsclrm_forcing ) & - !$acc copy( edsclr_in, edsclr_out ) - - !$acc data if( hydromet_dim > 0 ) & - !$acc copyin( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt, & - !$acc hm_metadata, hm_metadata%l_mix_rat_hm ) - call t_stopf('clubb_tend_cam:acc_copyin') - - ! Define the CLUBB momentum grid (in height, units of m) !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb @@ -3225,7 +3227,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! surface pressure. CAM's exner (in state) does not. Therefore, for consistent ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables ! (such as thlm), use "inv_exner_clubb" otherwise use the exner in state - inv_exner_clubb(i,k) = 1._r8/((state1%pmid(i,k)/p0_clubb)**(rairv(i,k,lchnk)/cpairv(i,k,lchnk))) + inv_exner_clubb(i,k) = 1._r8 / ( ( state1%pmid(i,k) / p0_clubb )**( rairv(i,k,lchnk) / cpairv(i,k,lchnk) ) ) ! Compute virtual potential temperature, which is needed for CLUBB thv(i,k) = state1%t(i,k) * inv_exner_clubb(i,k) & @@ -3254,7 +3256,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute exner at the surface for converting the sensible heat fluxes ! to a flux of potential temperature for use as clubb's boundary conditions - inv_exner_clubb_surf(i) = 1._r8/((state1%pmid(i,pver)/p0_clubb)**(rairv(i,pver,lchnk)/cpairv(i,pver,lchnk))) + inv_exner_clubb_surf(i) = 1._r8 / ( ( state1%pmid(i,pver) / p0_clubb )**( rairv(i,pver,lchnk) / cpairv(i,pver,lchnk) ) ) end do ! Compute thermodynamic stuff needed for CLUBB on thermo levels. @@ -3286,7 +3288,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute mean w wind on thermo grid, convert from omega to w wm_zt(i,k+1) = -1._r8 * ( state1%omega(i,pver-k+1) - state1%omega(i,pver) ) & - / (rho_zt(i,k+1) * gravit) + / ( rho_zt(i,k+1) * gravit ) end do end do @@ -3947,14 +3949,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - do ixind=1,edsclr_dim - !$acc parallel loop gang vector collapse(2) default(present) - do k=1, nzm_clubb - do i=1, ncol - edsclr_out(i,pverp-k+1,ixind) = edsclr_in(i,k,ixind) + if ( edsclr_dim > 0 ) then + do ixind=1,edsclr_dim + !$acc parallel loop gang vector collapse(2) default(present) + do k=1, nzm_clubb + do i=1, ncol + edsclr_out(i,pverp-k+1,ixind) = edsclr_in(i,k,ixind) + end do end do end do - end do + end if if (do_clubb_mf) then do k=1, nzm_clubb @@ -4019,6 +4023,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_startf('clubb_tend_cam:NAR') + + ! need to initialize macmic coupling to zero + if (macmic_it==1) then + ttend_clubb_mc(:ncol,:) = 0._r8 + upwp_clubb_gw_mc(:ncol,:) = 0._r8 + vpwp_clubb_gw_mc(:ncol,:) = 0._r8 + thlp2_clubb_gw_mc(:ncol,:) = 0._r8 + wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 + end if + do k=1, pverp do i=1, ncol From 87af3301afd846312ad3a8ffe133486a1a88295f Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Wed, 16 Oct 2024 23:14:30 -0600 Subject: [PATCH 21/82] Adding/moving timing statements --- src/physics/cam/clubb_intr.F90 | 54 ++++++++++++++++------------------ 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index a12002e51b..bf0826f007 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2595,6 +2595,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & #endif + call t_startf('clubb_tend_cam') + do i = 1, pcols det_s(i) = 0.0_r8 det_ice(i) = 0.0_r8 @@ -2936,7 +2938,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:acc_copyin') - call t_startf('clubb_tend_cam:NAR') + call t_startf('clubb_tend_cam:ACCR') !$acc parallel loop gang vector collapse(2) default(present) do k = 1, pverp @@ -3067,7 +3069,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end if - ! Initialize EDMF outputs if (do_clubb_mf) then do k = 1, pverp @@ -3098,8 +3099,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do end if - - call t_stopf('clubb_tend_cam:NAR') if (clubb_do_icesuper) then @@ -3162,8 +3161,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'NITENDICE', initend, pcols, lchnk ) endif - call t_startf('clubb_tend_cam:NAR') - if (clubb_do_adv) then @@ -3210,7 +3207,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - ! Define the CLUBB momentum grid (in height, units of m) !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb @@ -3321,7 +3317,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - ! ------------------------------------------------- ! ! Begin case specific code for SCAM cases. ! ! This section of code block is NOT called in ! @@ -3381,6 +3376,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! operators (such as zt2zm_api, etc.) until AFTER the ! call to setup_grid_heights_api. + call t_stopf('clubb_tend_cam:ACCR') + call t_startf('clubb_tend_cam:NAR') !$acc update host( zi_g, zt_g, clubb_params, sfc_elevation ) call setup_grid_api( nzm_clubb, ncol, sfc_elevation, l_implemented, & ! intent(in) @@ -3393,15 +3390,21 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & clubb_config_flags%l_prescribed_avg_deltaz, & ! intent(in) lmin, nu_vert_res_dep, err_code ) ! intent(out) + if ( err_code == clubb_fatal_error ) then + call endrun(subr//': Fatal error in CLUBB setup_parameters') + end if + + call t_stopf('clubb_tend_cam:NAR') + + call t_startf('clubb_tend_cam:acc_copyin') !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & !$acc gr%weights_zt2zm, gr%weights_zm2zt, & !$acc nu_vert_res_dep, nu_vert_res_dep%nu2, nu_vert_res_dep%nu9, & !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & !$acc nu_vert_res_dep%nu6) + call t_stopf('clubb_tend_cam:acc_copyin') - if ( err_code == clubb_fatal_error ) then - call endrun(subr//': Fatal error in CLUBB setup_parameters') - end if + call t_startf('clubb_tend_cam:ACCR') !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb @@ -3454,6 +3457,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Other Surface fluxes provided by host model if( (cld_macmic_num_steps > 1) .and. clubb_l_intr_sfc_flux_smooth ) then + call t_stopf('clubb_tend_cam:ACCR') + call t_startf('clubb_tend_cam:NAR') !$acc update host( state1%u, state1%v, state1%t, state1%pmid, cam_in%wsx, cam_in%wsy, rrho ) ! Adjust surface stresses using winds from the prior macmic iteration @@ -3469,6 +3474,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do !$acc update device( upwp_sfc, vpwp_sfc ) + call t_stopf('clubb_tend_cam:NAR') + call t_startf('clubb_tend_cam:ACCR') else @@ -3479,9 +3486,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do endif - call t_stopf('clubb_tend_cam:NAR') - - + call t_startf('clubb_tend_cam:flip-index') ! Need to flip arrays around for CLUBB core @@ -3561,6 +3566,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rcm_inout(i,1) = rcm_inout(i,2) end do + call t_stopf('clubb_tend_cam:flip-index') + ! pressure,exner on momentum grid needed for mass flux calc. if (do_clubb_mf) then @@ -3589,7 +3596,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if - if (clubb_do_adv) then if (macmic_it == 1) then @@ -3637,7 +3643,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end do - if (clubb_l_do_expldiff_rtm_thlm) then !$acc parallel loop gang vector collapse(2) default(present) @@ -3656,8 +3661,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif - call t_stopf('clubb_tend_cam:flip-index') - do t=1,nadv ! do needed number of "sub" timesteps for each CAM step ! Increment the statistics then begin stats timestep @@ -3851,7 +3854,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if enddo ! end time loop - call t_startf('clubb_tend_cam:NAR') if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then @@ -3877,14 +3879,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end if - call t_stopf('clubb_tend_cam:NAR') ! Convert RTP2 and THLP2 to thermo grid for output - call t_startf('clubb_tend_cam:NAR') rtp2_zt = zm2zt_api( nzm_clubb, ncol, gr, rtp2_in ) thl2_zt = zm2zt_api( nzm_clubb, ncol, gr, thlp2_in ) wp2_zt = zm2zt_api( nzm_clubb, ncol, gr, wp2_in ) - call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:flip-index') @@ -4011,7 +4010,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do call t_stopf('clubb_tend_cam:flip-index') - + call t_stopf('clubb_tend_cam:ACCR') call t_startf('clubb_tend_cam:acc_copyout') !$acc end data @@ -4021,7 +4020,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc end data call t_stopf('clubb_tend_cam:acc_copyout') - call t_startf('clubb_tend_cam:NAR') ! need to initialize macmic coupling to zero @@ -4338,7 +4336,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! then advances it's predictive equations second, this can lead to ! RHliq > 1 directly before microphysics is called. Therefore, we use ! ice_macro_tend to enforce RHliq <= 1 everywhere before microphysics is called. - call t_stopf('clubb_tend_cam:NAR') if (clubb_do_liqsupersat) then @@ -4396,7 +4393,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'FQTENDICE', fqtend, pcols, lchnk ) call t_stopf('clubb_cam_tend:do_liqsupersat') end if - call t_startf('clubb_tend_cam:NAR') ! ------------------------------------------------------------ ! ! The rest of the code deals with diagnosing variables ! @@ -4827,10 +4823,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif call t_stopf('clubb_tend_cam:NAR') - +#endif + + call t_stopf('clubb_tend_cam') return -#endif + end subroutine clubb_tend_cam subroutine clubb_emissions_cam (state, cam_in, ptend) From c85778ed06afcbe59f39568c7c3e416d9a3a1212 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Fri, 18 Oct 2024 13:41:14 -0600 Subject: [PATCH 22/82] Small cleanup and a little more GPUization. Passes ECT CPU vs GPU test and BFB on CPUs. --- src/physics/cam/clubb_intr.F90 | 310 ++++++++++++++++++--------------- 1 file changed, 170 insertions(+), 140 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index bf0826f007..aedfa22fbd 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2362,10 +2362,9 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Variables below are needed to compute energy integrals for conservation ! NOTE: Arrays of size PCOLS (all possible columns) can be used to access State, PBuf and History Subroutines - real(r8) :: ke_a(pcols), ke_b(pcols), te_a(pcols), te_b(pcols) - real(r8) :: wv_a(pcols), wv_b(pcols), wl_b(pcols), wl_a(pcols) - real(r8) :: se_dis(pcols), se_a(pcols), se_b(pcols), clubb_s(pcols,pver) - real(r8) :: eleak(pcols) + real(r8) :: te_a, se_a, ke_a, wv_a, wl_a + real(r8) :: te_b, se_b, ke_b, wv_b, wl_b + real(r8) :: se_dis(pcols), clubb_s(pcols,pver), eleak(pcols) real(r8) :: inv_exner_clubb(pcols,pverp) ! Inverse exner function consistent with CLUBB [-] real(r8) :: inv_exner_clubb_surf(pcols) ! Inverse exner function at the surface @@ -2572,6 +2571,22 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8) :: temp2d(pcols,pver), temp2dp(pcols,pverp) ! temporary array for holding scaled outputs + real(r8), dimension(pcols,pver) :: & + rvmtend_clubb, & + rcmtend_clubb, & + rimtend_clubb, & + stend_clubb, & + utend_clubb, & + vtend_clubb, & + dpdlfliq, & + dpdlfice, & + dpdlft, & + detnliquid + + real(r8), dimension(pcols,pverp) :: & + wprcp_clubb, & + wpthvp_clubb + intrinsic :: max character(len=*), parameter :: subr='clubb_tend_cam' @@ -2619,6 +2634,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! MAIN COMPUTATION BEGINS HERE ! !-----------------------------------------------------------------------------------! + call t_startf('clubb_tend_cam:NAR') + ! Get indicees for cloud and ice mass and cloud and ice number call cnst_get_ind('Q',ixq) call cnst_get_ind('CLDLIQ',ixcldliq) @@ -2745,17 +2762,15 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! variable mesh grids and lat-lon grids call grid_size(state1, grid_dx, grid_dy) - - - ! Determine number of columns and which chunk computation is to be performed on + ! Determine number of columns and which chunk computation is to be performed on ncol = state%ncol lchnk = state%lchnk + ! Determine number of vertical levels used in clubb, thermo variables are nzt_clubb + ! and momentum variables are nzm_clubb nzt_clubb = pver + 1 - top_lev nzm_clubb = pverp + 1 - top_lev - - ! Allocate pdf_params only if they aren't allocated already. if ( .not. allocated(pdf_params_chnk(lchnk)%mixt_frac) ) then call init_pdf_params_api( nzm_clubb, ncol, pdf_params_chnk(lchnk) ) @@ -2767,7 +2782,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & pdf_implicit_coefs_terms_chnk(lchnk) ) end if - !--------------------- Scalar Setting -------------------- dl_rad = clubb_detliq_rad @@ -2831,34 +2845,34 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & apply_const = 0._r8 ! Never want this if CLUBB's moments are not advected endif - ! Initialize the apply_const variable (note special logic is due to eularian backstepping) if (clubb_do_adv .and. (is_first_step() .or. all(wpthlp(1:ncol,1:pver) == 0._r8))) then apply_const = 0._r8 ! On first time through do not remove constant ! from moments since it has not been added yet endif - !--------------------- Initializations -------------------- - ! Set the ztodt timestep in pbuf for SILHS ztodtptr(:) = 1.0_r8*hdtime - + call t_stopf('clubb_tend_cam:NAR') call t_startf('clubb_tend_cam:acc_copyin') !$acc data copyin( sclr_idx, clubb_params_single_col, grid_dx, grid_dy, rairv, cpairv, radf_clubb, qrl, & !$acc pdf_params_chnk(lchnk), pdf_params_zm_chnk(lchnk), & - !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, & - !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, & + !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, state1%s, state1%pint, & + !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, state1%phis, & !$acc cam_in, cam_in%shf, cam_in%wsx, cam_in%wsy, cam_in%cflx, & !$acc rrho, prer_evap, rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & !$acc cloud_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & + !$acc ttend_clubb_mc, upwp_clubb_gw_mc, vpwp_clubb_gw_mc, thlp2_clubb_gw_mc, wpthlp_clubb_gw_mc, & + !$acc ttend_clubb, upwp_clubb_gw, vpwp_clubb_gw, thlp2_clubb_gw, wpthlp_clubb_gw, & !$acc wp2up2, wp2vp2, ice_supersat_frac ) & !$acc copyout( temp2d, temp2dp, rtp2_zt_out, thl2_zt_out, wp2_zt_out, pdfp_rtp2, wm_zt_out, inv_exner_clubb, & - !$acc rcm, wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, thv, dz_g ) & + !$acc rcm, wprcp, rcm_in_layer, cloud_cover, zt_out, zi_out, khzm, qclvar, thv, dz_g, & + !$acc clubbtop, se_dis, eleak, clubb_s, wpthvp_clubb, wprcp_clubb ) & !$acc create( upwp_sfc_pert, vpwp_sfc_pert, khzt_out, khzm_out, & !$acc fcor, um_in, vm_in, upwp_in, vpwp_in, wpthvp_in, wp2thvp_in, rtpthvp_in, thlpthvp_in, & !$acc up2_in, vp2_in, up3_in, vp3_in, wp2_in, wp3_in, rtp2_in, thlp2_in, rtp3_in, & @@ -2936,8 +2950,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc create( hydromet, wphydrometp, wp2hmp, rtphmp_zt, thlphmp_zt ) & !$acc copyin( hm_metadata, hm_metadata%l_mix_rat_hm ) call t_stopf('clubb_tend_cam:acc_copyin') - - call t_startf('clubb_tend_cam:ACCR') !$acc parallel loop gang vector collapse(2) default(present) @@ -2952,7 +2964,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - !$acc parallel loop gang vector collapse(2) default(present) do k = 1, pver do i = 1, pcols @@ -2960,7 +2971,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb do i = 1, ncol @@ -2985,7 +2995,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & upwp_pert_inout(i,k) = 0.0_r8 vpwp_pert_inout(i,k) = 0.0_r8 - ! Initialize these to prevent crashing behavior wprcp_out(i,k) = 0._r8 rcm_in_layer_out(i,k) = 0._r8 @@ -2993,7 +3002,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & khzm_out(i,k) = 0._r8 khzt_out(i,k) = 0._r8 end do - end do + end do !$acc parallel loop gang vector default(present) do i = 1, ncol @@ -3069,6 +3078,20 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end if + ! need to initialize macmic coupling to zero + if ( macmic_it == 1 ) then + !$acc parallel loop gang vector collapse(2) default(present) + do i = 1, ncol + do k = 1, pverp + ttend_clubb_mc(i,k) = 0._r8 + upwp_clubb_gw_mc(i,k) = 0._r8 + vpwp_clubb_gw_mc(i,k) = 0._r8 + thlp2_clubb_gw_mc(i,k) = 0._r8 + wpthlp_clubb_gw_mc(i,k) = 0._r8 + end do + end do + end if + ! Initialize EDMF outputs if (do_clubb_mf) then do k = 1, pverp @@ -3379,7 +3402,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:ACCR') call t_startf('clubb_tend_cam:NAR') !$acc update host( zi_g, zt_g, clubb_params, sfc_elevation ) - + call setup_grid_api( nzm_clubb, ncol, sfc_elevation, l_implemented, & ! intent(in) grid_type, zi_g(:,2), zi_g(:,1), zi_g(:,nzm_clubb), & ! intent(in) zi_g, zt_g, & ! intent(in) @@ -3395,7 +3418,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if call t_stopf('clubb_tend_cam:NAR') - call t_startf('clubb_tend_cam:acc_copyin') !$acc data copyin( gr, gr%zm, gr%zt, gr%dzm, gr%dzt, gr%invrs_dzt, gr%invrs_dzm, & !$acc gr%weights_zt2zm, gr%weights_zm2zt, & @@ -3403,7 +3425,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc nu_vert_res_dep%nu1, nu_vert_res_dep%nu8, nu_vert_res_dep%nu10, & !$acc nu_vert_res_dep%nu6) call t_stopf('clubb_tend_cam:acc_copyin') - call t_startf('clubb_tend_cam:ACCR') !$acc parallel loop gang vector collapse(2) default(present) @@ -3436,16 +3457,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - - ! Compute some inputs from the thermodynamic grid - ! to the momentum grid + ! Compute some inputs from the thermodynamic grid to the momentum grid rho_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, rho_ds_zt ) rho_zm = zt2zm_api( nzm_clubb, ncol, gr, rho_zt ) invrs_rho_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, invrs_rho_ds_zt ) thv_ds_zm = zt2zm_api( nzm_clubb, ncol, gr, thv_ds_zt ) wm_zm = zt2zm_api( nzm_clubb, ncol, gr, wm_zt ) - ! Surface fluxes provided by host model + ! Surface fluxes provided by host model !$acc parallel loop gang vector default(present) do i=1,ncol wpthlp_sfc(i) = cam_in%shf(i)/(cpairv(i,pver,lchnk)*rho_ds_zm(i,1)) ! Sensible heat flux @@ -3566,8 +3585,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rcm_inout(i,1) = rcm_inout(i,2) end do - call t_stopf('clubb_tend_cam:flip-index') - ! pressure,exner on momentum grid needed for mass flux calc. if (do_clubb_mf) then @@ -3661,6 +3678,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & endif + call t_stopf('clubb_tend_cam:flip-index') + do t=1,nadv ! do needed number of "sub" timesteps for each CAM step ! Increment the statistics then begin stats timestep @@ -3821,7 +3840,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if - if (do_cldcool) then call t_startf('clubb_tend_cam:do_cldcool') @@ -3949,8 +3967,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do if ( edsclr_dim > 0 ) then + !$acc parallel loop gang vector collapse(3) default(present) do ixind=1,edsclr_dim - !$acc parallel loop gang vector collapse(2) default(present) do k=1, nzm_clubb do i=1, ncol edsclr_out(i,pverp-k+1,ixind) = edsclr_in(i,k,ixind) @@ -4010,27 +4028,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do call t_stopf('clubb_tend_cam:flip-index') - call t_stopf('clubb_tend_cam:ACCR') - - call t_startf('clubb_tend_cam:acc_copyout') - !$acc end data - !$acc end data - !$acc end data - !$acc end data - !$acc end data - call t_stopf('clubb_tend_cam:acc_copyout') - - call t_startf('clubb_tend_cam:NAR') - - ! need to initialize macmic coupling to zero - if (macmic_it==1) then - ttend_clubb_mc(:ncol,:) = 0._r8 - upwp_clubb_gw_mc(:ncol,:) = 0._r8 - vpwp_clubb_gw_mc(:ncol,:) = 0._r8 - thlp2_clubb_gw_mc(:ncol,:) = 0._r8 - wpthlp_clubb_gw_mc(:ncol,:) = 0._r8 - end if + !$acc parallel loop gang vector collapse(2) default(present) do k=1, pverp do i=1, ncol @@ -4054,6 +4053,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Values to use above top_lev, for variables that have not already been ! set up there. These are mostly fill values that should not actually be ! used in the run, but may end up in diagnostic output. + !$acc parallel loop gang vector collapse(2) default(present) do k=1, top_lev-1 do i=1, ncol upwp(i,k) = 0._r8 @@ -4071,6 +4071,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Fill up arrays needed for McICA. Note we do not want the ghost point, ! thus why the second loop is needed. + !$acc parallel loop gang vector default(present) do i=1, pcols zi_out(i,1) = 0._r8 end do @@ -4081,6 +4082,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (lq(ixind)) then icnt=icnt+1 + !$acc parallel loop gang vector collapse(2) default(present) do k=1, top_lev-1 do i=1, ncol edsclr_out(i,k,icnt) = state1%q(i,k,ixind) @@ -4091,6 +4093,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do ! Compute static energy using CLUBB's variables + !$acc parallel loop gang vector collapse(2) default(present) do k=1,pver do i=1, ncol clubb_s(i,k) = cpairv(i,k,lchnk) * thlm(i,k) / inv_exner_clubb(i,k) & @@ -4104,66 +4107,59 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Initialize clubbtop to top_lev, for finding the highlest level CLUBB is ! active for informing where to apply the energy fixer. + !$acc parallel loop gang vector default(present) do i=1, ncol clubbtop(i) = top_lev do while ((rtp2(i,clubbtop(i)) <= 1.e-15_r8 .and. rcm(i,clubbtop(i)) == 0._r8) .and. clubbtop(i) < pver) - clubbtop(i) = clubbtop(i) + 1 + clubbtop(i) = clubbtop(i) + 1 end do end do - ! - ! set pbuf field so that HB scheme is only applied above CLUBB top - ! - if (do_hb_above_clubb) then - call pbuf_set_field(pbuf, clubbtop_idx, clubbtop) - endif + !$acc parallel loop gang vector default(present) do i=1, ncol - se_a(i) = 0._r8 - ke_a(i) = 0._r8 - wv_a(i) = 0._r8 - wl_a(i) = 0._r8 - - se_b(i) = 0._r8 - ke_b(i) = 0._r8 - wv_b(i) = 0._r8 - wl_b(i) = 0._r8 - end do - ! NO COLLAPSE(2) - do i=1, ncol + se_a = 0._r8 + ke_a = 0._r8 + wv_a = 0._r8 + wl_a = 0._r8 + + se_b = 0._r8 + ke_b = 0._r8 + wv_b = 0._r8 + wl_b = 0._r8 + do k=1,pver ! Compute integrals for static energy, kinetic energy, water vapor, and liquid water ! after CLUBB is called. This is for energy conservation purposes. - se_a(i) = se_a(i) + clubb_s(i,k)*state1%pdel(i,k)*rga - ke_a(i) = ke_a(i) + 0.5_r8*(um(i,k)**2+vm(i,k)**2)*state1%pdel(i,k)*rga - wv_a(i) = wv_a(i) + (rtm(i,k)-rcm(i,k))*state1%pdeldry(i,k)*rga - wl_a(i) = wl_a(i) + (rcm(i,k))*state1%pdeldry(i,k)*rga + se_a = se_a + clubb_s(i,k)*state1%pdel(i,k)*rga + ke_a = ke_a + 0.5_r8*(um(i,k)**2+vm(i,k)**2)*state1%pdel(i,k)*rga + wv_a = wv_a + (rtm(i,k)-rcm(i,k))*state1%pdeldry(i,k)*rga + wl_a = wl_a + (rcm(i,k))*state1%pdeldry(i,k)*rga end do - end do - ! NO COLLAPSE(2) - do i=1, ncol + ! Based on these integrals, compute the total energy after CLUBB call + te_a = se_a + ke_a + (latvap+latice) * wv_a + latice * wl_a + do k=1, pver ! Do the same as above, but for before CLUBB was called. - se_b(i) = se_b(i) + state1%s(i,k)*state1%pdel(i,k)*rga - ke_b(i) = ke_b(i) + 0.5_r8*(state1%u(i,k)**2+state1%v(i,k)**2)*state1%pdel(i,k)*rga - wv_b(i) = wv_b(i) + state1%q(i,k,ixq)*state1%pdeldry(i,k)*rga - wl_b(i) = wl_b(i) + state1%q(i,k,ixcldliq)*state1%pdeldry(i,k)*rga + se_b = se_b + state1%s(i,k)*state1%pdel(i,k)*rga + ke_b = ke_b + 0.5_r8*(state1%u(i,k)**2+state1%v(i,k)**2)*state1%pdel(i,k)*rga + wv_b = wv_b + state1%q(i,k,ixq)*state1%pdeldry(i,k)*rga + wl_b = wl_b + state1%q(i,k,ixcldliq)*state1%pdeldry(i,k)*rga end do - end do - - do i=1, ncol - ! Based on these integrals, compute the total energy before and after CLUBB call - te_a(i) = se_a(i) + ke_a(i) + (latvap+latice) * wv_a(i) + latice * wl_a(i) - te_b(i) = se_b(i) + ke_b(i) + (latvap+latice) * wv_b(i) + latice * wl_b(i) + ! Based on these integrals, compute the total energy before CLUBB call + te_b = se_b + ke_b + (latvap+latice) * wv_b + latice * wl_b ! Take into account the surface fluxes of heat and moisture ! Use correct qflux from cam_in, not lhf/latvap as was done previously - te_b(i) = te_b(i) + (cam_in%shf(i)+cam_in%cflx(i,1)*(latvap+latice)) * hdtime + te_b = te_b + (cam_in%shf(i)+cam_in%cflx(i,1)*(latvap+latice)) * hdtime ! Compute the disbalance of total energy, over depth where CLUBB is active - se_dis(i) = (te_a(i) - te_b(i))/(state1%pint(i,pverp)-state1%pint(i,clubbtop(i))) + se_dis(i) = ( te_a - te_b ) / ( state1%pint(i,pverp) - state1%pint(i,clubbtop(i)) ) + + eleak(i) = ( te_a - te_b ) / hdtime + end do ! Fix the total energy coming out of CLUBB so it achieves energy conservation. @@ -4174,14 +4170,39 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! when using specified dynamics, so allow this to be turned off via a namelist ! variable. if (clubb_do_energyfix) then + + !$acc parallel loop gang vector default(present) do i=1, ncol + do k=clubbtop(i),pver clubb_s(i,k) = clubb_s(i,k) - se_dis(i)*gravit end do ! convert to units of +ve [K] se_dis(i) = -1._r8*se_dis(i)*gravit/cpairv(i,pver,lchnk) + end do + endif + + !$acc parallel loop gang vector collapse(2) default(present) + do k=1, pverp + do i=1, ncol + wpthvp_clubb(i,k) = wpthvp(i,k) * cpair + wprcp_clubb(i,k) = wprcp(i,k) * latvap + end do + end do + + call t_stopf('clubb_tend_cam:ACCR') + + call t_startf('clubb_tend_cam:acc_copyout') + !$acc end data + !$acc end data + !$acc end data + !$acc end data + !$acc end data + call t_stopf('clubb_tend_cam:acc_copyout') + + call t_startf('clubb_tend_cam:NAR') call physics_ptend_init( ptend_loc, state%psetcols, 'clubb', ls=.true., lu=.true., lv=.true., lq=lq ) @@ -4299,36 +4320,27 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end if end do + + rvmtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + rcmtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + rimtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + stend_clubb(:ncol,:pver) = ptend_loc%s(:ncol,:pver) + utend_clubb(:ncol,:pver) = ptend_loc%u(:ncol,:pver) + vtend_clubb(:ncol,:pver) = ptend_loc%v(:ncol,:pver) + cmeliq(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - - call outfld('KVH_CLUBB', khzm, pcols, lchnk) - - eleak(:ncol) = (te_a(:ncol) - te_b(:ncol))/hdtime - call outfld('ELEAK_CLUBB', eleak, pcols, lchnk) - call outfld('TFIX_CLUBB', se_dis, pcols, lchnk) + ! + ! set pbuf field so that HB scheme is only applied above CLUBB top + ! + if (do_hb_above_clubb) then + call pbuf_set_field(pbuf, clubbtop_idx, clubbtop) + endif ! ------------------------------------------------- ! ! End column computation of CLUBB, begin to apply ! ! and compute output, etc ! ! ------------------------------------------------- ! - ! Output CLUBB tendencies (convert dry basis to wet for consistency with history variable definition) - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'RVMTEND_CLUBB', temp2d, pcols, lchnk) - - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'RCMTEND_CLUBB', temp2d, pcols, lchnk) - - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'RIMTEND_CLUBB', temp2d, pcols, lchnk) - - call outfld( 'STEND_CLUBB', ptend_loc%s,pcols, lchnk) - call outfld( 'UTEND_CLUBB', ptend_loc%u,pcols, lchnk) - call outfld( 'VTEND_CLUBB', ptend_loc%v,pcols, lchnk) - - cmeliq(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'CMELIQ', cmeliq, pcols, lchnk) - call physics_ptend_sum(ptend_loc,ptend_all,ncol) call physics_update(state1,ptend_loc,hdtime) @@ -4419,6 +4431,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & do k=1,pver do i=1,ncol + if( state1%t(i,k) > meltpt_temp ) then dum1 = 0.0_r8 elseif ( state1%t(i,k) < dt_low ) then @@ -4455,19 +4468,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo det_ice(:ncol) = det_ice(:ncol)/1000._r8 ! divide by density of water - - ! output moist basis to be consistent with history variable definition - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'DPDLFLIQ', temp2d, pcols, lchnk) - - ! output moist basis to be consistent with history variable definition - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) - call outfld( 'DPDLFICE', temp2d, pcols, lchnk) - - temp2d(:ncol,:pver) = ptend_loc%s(:ncol,:pver)/cpairv(:ncol,:pver, lchnk) - call outfld( 'DPDLFT', temp2d, pcols, lchnk) - - call outfld( 'DETNLIQTND', ptend_loc%q(:,:,ixnumliq),pcols, lchnk ) + dpdlfliq(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + dpdlfice(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + dpdlft(:ncol,:pver) = ptend_loc%s(:ncol,:pver)/cpairv(:ncol,:pver, lchnk) + detnliquid(:ncol,:pver) = ptend_loc%q(:,:,ixnumliq) call physics_ptend_sum(ptend_loc,ptend_all,ncol) call physics_update(state1,ptend_loc,hdtime) @@ -4494,11 +4498,20 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & relvarmax = 10.0_r8 endif - relvar(:,:) = relvarmax ! default + do i = 1, ncol + do k = 1, pver + relvar(i,k) = relvarmax ! default + end do + end do if (deep_scheme .ne. 'CLUBB_SGS') then - where (rcm(:ncol,:pver) /= 0 .and. qclvar(:ncol,:pver) /= 0) & - relvar(:ncol,:pver) = min(relvarmax,max(0.001_r8,rcm(:ncol,:pver)**2/qclvar(:ncol,:pver))) + do i = 1, ncol + do k = 1, pver + if ( rcm(i,k) /= 0 .and. qclvar(i,k) /= 0 ) then + relvar(i,k) = min( relvarmax, max(0.001_r8, rcm(i,k)**2 / qclvar(i,k) ) ) + end if + end do + end do endif ! ------------------------------------------------- ! @@ -4705,8 +4718,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ustar2, obklen, kbfs, pblh, dummy2, & state1%zi, cloud_frac(:,1:pver), 1._r8-cam_in%landfrac, dummy3) - ! Output the PBL depth - call outfld('PBLH', pblh, pcols, lchnk) ! Assign the first pver levels of cloud_frac back to cld cld(:,1:pver) = cloud_frac(:,1:pver) @@ -4715,6 +4726,30 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! END CLOUD FRACTION DIAGNOSIS, begin to store variables back into buffer ! ! --------------------------------------------------------------------------------- ! + call outfld( 'DETNLIQTND', detnliquid,pcols, lchnk ) + + ! Output CLUBB tendencies (convert dry basis to wet for consistency with history variable definition) + call outfld( 'RVMTEND_CLUBB', rvmtend_clubb, pcols, lchnk) + call outfld( 'RCMTEND_CLUBB', rcmtend_clubb, pcols, lchnk) + call outfld( 'RIMTEND_CLUBB', rimtend_clubb, pcols, lchnk) + call outfld( 'STEND_CLUBB', stend_clubb, pcols, lchnk) + call outfld( 'UTEND_CLUBB', utend_clubb, pcols, lchnk) + call outfld( 'VTEND_CLUBB', vtend_clubb, pcols, lchnk) + + call outfld( 'CMELIQ', cmeliq, pcols, lchnk) + + ! output moist basis to be consistent with history variable definition + call outfld( 'DPDLFLIQ', dpdlfliq, pcols, lchnk) + call outfld( 'DPDLFICE', dpdlfice, pcols, lchnk) + call outfld( 'DPDLFT', dpdlft, pcols, lchnk) + + ! Output the PBL depth + call outfld('PBLH', pblh, pcols, lchnk) + + call outfld('KVH_CLUBB', khzm, pcols, lchnk) + call outfld('ELEAK_CLUBB', eleak, pcols, lchnk) + call outfld('TFIX_CLUBB', se_dis, pcols, lchnk) + ! Output calls of variables goes here call outfld( 'RELVAR', relvar, pcols, lchnk ) call outfld( 'RHO_CLUBB', rho(:,1:pver), pcols, lchnk ) @@ -4731,13 +4766,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'RCM_CLUBB', rcm(:,1:pver), pcols, lchnk ) call outfld( 'RTM_CLUBB', rtm(:,1:pver), pcols, lchnk ) call outfld( 'THLM_CLUBB', thlm(:,1:pver), pcols, lchnk ) - - temp2dp(:ncol,:) = wprcp(:ncol,:) * latvap - call outfld( 'WPRCP_CLUBB', temp2dp, pcols, lchnk ) - - temp2dp(:ncol,:) = wpthvp(:ncol,:) * cpair - call outfld( 'WPTHVP_CLUBB', temp2dp, pcols, lchnk ) - + call outfld( 'WPRCP_CLUBB', wprcp_clubb, pcols, lchnk ) + call outfld( 'WPTHVP_CLUBB', wpthvp_clubb, pcols, lchnk ) call outfld( 'RTP2_ZT_CLUBB', rtp2_zt_out(:,1:pver), pcols, lchnk ) call outfld( 'THLP2_ZT_CLUBB', thl2_zt_out(:,1:pver), pcols, lchnk ) call outfld( 'WP2_ZT_CLUBB', wp2_zt_out(:,1:pver), pcols, lchnk ) From 34e981615a9fc8e1320555df38f14f12f1884336 Mon Sep 17 00:00:00 2001 From: peverwhee Date: Tue, 22 Oct 2024 13:57:21 -0600 Subject: [PATCH 23/82] move file-dependent fields to end of if block --- src/control/cam_history.F90 | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index e86f885f0e..867c84eaea 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -4329,7 +4329,6 @@ subroutine h_define (t, restart) cam_snapshot_before_num_out = cam_snapshot_before_num, & cam_snapshot_after_num_out = cam_snapshot_after_num) - if(restart) then tape => restarthistory_tape if(masterproc) write(iulog,*)'Opening netcdf history restart file ', trim(hrestpath(t)) @@ -4509,14 +4508,6 @@ subroutine h_define (t, restart) if(.not. is_satfile(t)) then - if (f == accumulated_file_index) then - ierr=pio_put_att (tape(t)%Files(f), tape(t)%timeid, 'bounds', 'time_bounds') - ierr=pio_def_var (tape(t)%Files(f),'time_bounds',pio_double,(/bnddim,timdim/),tape(t)%tbndid) - ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'long_name', 'time interval endpoints') - str = 'days since ' // date2yyyymmdd(nbdate) // ' ' // sec2hms(nbsec) - ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'units', trim(str)) - ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'calendar', trim(calendar)) - end if ! ! Character ! @@ -4565,7 +4556,6 @@ subroutine h_define (t, restart) ierr=pio_put_att (tape(t)%Files(f), tape(t)%nscurid, 'long_name', trim(str)) end if - if (.not. is_initfile(file_index=t) .and. f == instantaneous_file_index) then ! Don't write the GHG/Solar forcing data to the IC file. ! Only write the GHG/Solar forcing data to the instantaneous file @@ -4668,6 +4658,13 @@ subroutine h_define (t, restart) ierr=pio_def_var (tape(t)%Files(f),'nsteph ',pio_int,(/timdim/),tape(t)%nstephid) str = 'current timestep' ierr=pio_put_att (tape(t)%Files(f), tape(t)%nstephid, 'long_name', trim(str)) + else if (f == accumulated_file_index) then + ierr=pio_def_var (tape(t)%Files(f),'time_bounds',pio_double,(/bnddim,timdim/),tape(t)%tbndid) + ierr=pio_put_att (tape(t)%Files(f), tape(t)%timeid, 'bounds', 'time_bounds') + ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'long_name', 'time interval endpoints') + str = 'days since ' // date2yyyymmdd(nbdate) // ' ' // sec2hms(nbsec) + ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'units', trim(str)) + ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'calendar', trim(calendar)) end if end if ! .not. is_satfile @@ -5031,6 +5028,7 @@ subroutine h_define (t, restart) deallocate(header_info) end if + ! Write the mdim variable data do f = 1, maxsplitfiles if (pio_file_is_open(tape(t)%Files(f))) then @@ -5854,11 +5852,14 @@ subroutine wshist (rgnht_in) end if ! We have two files - one for accumulated and one for instantaneous fields if (f == accumulated_file_index) then - ierr=pio_put_var (tape(t)%Files(f), tape(t)%tbndid, startc, countc, tdata) if (.not. restart .and. .not. is_initfile(t)) then ! accumulated tape - time is midpoint of time_bounds ierr=pio_put_var (tape(t)%Files(f), tape(t)%timeid, (/start/),(/count1/),(/(tdata(1) + tdata(2)) / 2._r8/)) + else + ! restart or initfile - time is current time + ierr=pio_put_var (tape(t)%Files(f), tape(t)%timeid, (/start/),(/count1/),(/time/)) end if + ierr=pio_put_var (tape(t)%Files(f), tape(t)%tbndid, startc, countc, tdata) else ! not an accumulated history tape - time is current time ierr=pio_put_var (tape(t)%Files(f), tape(t)%timeid, (/start/),(/count1/),(/time/)) From 2772bb4aa280d4c4dc4d5253fa2fc672dde09b48 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 9 Sep 2024 20:04:06 -0400 Subject: [PATCH 24/82] Port check_energy_chng, check_energy_timestep_init to CCPP-ized subroutines --- bld/configure | 1 + src/dynamics/eul/dp_coupling.F90 | 4 +- src/dynamics/fv/dp_coupling.F90 | 4 +- src/dynamics/mpas/dp_coupling.F90 | 4 +- src/dynamics/se/dp_coupling.F90 | 4 +- src/physics/cam/check_energy.F90 | 302 +-------------------------- src/physics/cam/check_energy_cam.F90 | 211 +++++++++++++++++++ src/physics/cam/physpkg.F90 | 5 +- src/physics/cam/zm_conv_intr.F90 | 1 - src/physics/cam7/physpkg.F90 | 6 +- 10 files changed, 232 insertions(+), 310 deletions(-) create mode 100644 src/physics/cam/check_energy_cam.F90 diff --git a/bld/configure b/bld/configure index 86c6c4e65b..4b898b9d88 100755 --- a/bld/configure +++ b/bld/configure @@ -2340,6 +2340,7 @@ sub write_filepath print $fh "$camsrcdir/src/atmos_phys/schemes/tropopause_find\n"; print $fh "$camsrcdir/src/atmos_phys/schemes/zhang_mcfarlane\n"; print $fh "$camsrcdir/src/atmos_phys/schemes/dry_adiabatic_adjust\n"; + print $fh "$camsrcdir/src/atmos_phys/schemes/check_energy\n"; print $fh "$camsrcdir/src/atmos_phys/schemes/utilities\n"; # Dynamics package and test utilities diff --git a/src/dynamics/eul/dp_coupling.F90 b/src/dynamics/eul/dp_coupling.F90 index bc900e2d0e..8e3eb64a21 100644 --- a/src/dynamics/eul/dp_coupling.F90 +++ b/src/dynamics/eul/dp_coupling.F90 @@ -14,7 +14,7 @@ module dp_coupling use physconst, only: cpair, gravit, rair, zvir use air_composition, only: rairv use geopotential, only: geopotential_t - use check_energy, only: check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_timestep_init #if (defined SPMD) use spmd_dyn, only: buf1, buf1win, buf2, buf2win, & spmdbuf_siz, local_dp_map, & @@ -291,7 +291,7 @@ subroutine d_p_coupling(ps, t3, u3, v3, q3, & ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk ) + call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk ) end do diff --git a/src/dynamics/fv/dp_coupling.F90 b/src/dynamics/fv/dp_coupling.F90 index fc02821471..af2d13b12e 100644 --- a/src/dynamics/fv/dp_coupling.F90 +++ b/src/dynamics/fv/dp_coupling.F90 @@ -12,7 +12,7 @@ module dp_coupling use physconst, only: gravit, zvir use air_composition, only: cpairv, rairv use geopotential, only: geopotential_t - use check_energy, only: check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_timestep_init use dynamics_vars, only: T_FVDYCORE_GRID, t_fvdycore_state use dyn_internal_state,only: get_dyn_state use dyn_comp, only: dyn_import_t, dyn_export_t, fv_print_dpcoup_warn @@ -621,7 +621,7 @@ subroutine d_p_coupling(grid, phys_state, phys_tend, pbuf2d, dyn_out) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do call t_stopf('derived_fields') diff --git a/src/dynamics/mpas/dp_coupling.F90 b/src/dynamics/mpas/dp_coupling.F90 index 10d75b4b8c..c312f1e2f9 100644 --- a/src/dynamics/mpas/dp_coupling.F90 +++ b/src/dynamics/mpas/dp_coupling.F90 @@ -413,7 +413,7 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d) ! MPAS prognostic fields. use geopotential, only: geopotential_t - use check_energy, only: check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_timestep_init use shr_vmath_mod, only: shr_vmath_log use phys_control, only: waccmx_is use cam_thermo, only: cam_thermo_dry_air_update, cam_thermo_water_update @@ -564,7 +564,7 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do diff --git a/src/dynamics/se/dp_coupling.F90 b/src/dynamics/se/dp_coupling.F90 index 919b7f3510..9de31132a2 100644 --- a/src/dynamics/se/dp_coupling.F90 +++ b/src/dynamics/se/dp_coupling.F90 @@ -546,7 +546,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d) use phys_control, only: waccmx_is use geopotential, only: geopotential_t use static_energy, only: update_dry_static_energy_run - use check_energy, only: check_energy_timestep_init + use check_energy_cam,only: check_energy_cam_timestep_init use hycoef, only: hyai, ps0 use shr_vmath_mod, only: shr_vmath_log use qneg_module, only: qneg3 @@ -707,7 +707,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d) cpairv(1:ncol,:,lchnk), errflg, errmsg) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do ! lchnk diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 9c569387e0..5e1df3a967 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -26,10 +26,9 @@ module check_energy use gmean_mod, only: gmean use physconst, only: gravit, rga, latvap, latice, cpair, rair - use air_composition, only: cpairv, rairv, cp_or_cv_dycore + use air_composition, only: cpairv, cp_or_cv_dycore use physics_types, only: physics_state, physics_tend, physics_ptend, physics_ptend_init use constituents, only: cnst_get_ind, pcnst, cnst_name, cnst_get_type_byind - use time_manager, only: is_first_step use cam_logfile, only: iulog use scamMod, only: single_column, use_camiop, heat_glob_scm use cam_history, only: outfld, write_camiop @@ -45,8 +44,6 @@ module check_energy public :: check_energy_register ! register fields in physics buffer public :: check_energy_get_integrals ! get energy integrals computed in check_energy_gmean public :: check_energy_init ! initialization of module - public :: check_energy_timestep_init ! timestep initialization of energy integrals and cumulative boundary fluxes - public :: check_energy_chng ! check changes in integrals against cumulative boundary fluxes public :: check_energy_gmean ! global means of physics input and output total energy public :: check_energy_fix ! add global mean energy difference as a heating public :: check_tracers_init ! initialize tracer integrals and cumulative boundary fluxes @@ -67,11 +64,11 @@ module check_energy ! Physics buffer indices - integer :: teout_idx = 0 ! teout index in physics buffer - integer :: dtcore_idx = 0 ! dtcore index in physics buffer - integer :: dqcore_idx = 0 ! dqcore index in physics buffer - integer :: ducore_idx = 0 ! ducore index in physics buffer - integer :: dvcore_idx = 0 ! dvcore index in physics buffer + integer, public :: teout_idx = 0 ! teout index in physics buffer + integer, public :: dtcore_idx = 0 ! dtcore index in physics buffer + integer, public :: dqcore_idx = 0 ! dqcore index in physics buffer + integer, public :: ducore_idx = 0 ! ducore index in physics buffer + integer, public :: dvcore_idx = 0 ! dvcore index in physics buffer type check_tracers_data real(r8) :: tracer(pcols,pcnst) ! initial vertically integrated total (kinetic + static) energy @@ -219,293 +216,6 @@ end subroutine check_energy_init !=============================================================================== - subroutine check_energy_timestep_init(state, tend, pbuf, col_type) - use cam_thermo, only: get_hydrostatic_energy - use physics_buffer, only: physics_buffer_desc, pbuf_set_field - use cam_abortutils, only: endrun - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure - use physics_types, only: phys_te_idx, dyn_te_idx -!----------------------------------------------------------------------- -! Compute initial values of energy and water integrals, -! zero cumulative tendencies -!----------------------------------------------------------------------- -!------------------------------Arguments-------------------------------- - - type(physics_state), intent(inout) :: state - type(physics_tend ), intent(inout) :: tend - type(physics_buffer_desc), pointer :: pbuf(:) - integer, optional :: col_type ! Flag inidicating whether using grid or subcolumns -!---------------------------Local storage------------------------------- - real(r8) :: cp_or_cv(state%psetcols,pver) - integer lchnk ! chunk identifier - integer ncol ! number of atmospheric columns -!----------------------------------------------------------------------- - - lchnk = state%lchnk - ncol = state%ncol - - ! cp_or_cv needs to be allocated to a size which matches state and ptend - ! If psetcols == pcols, cpairv is the correct size and just copy into cp_or_cv - ! If psetcols > pcols and all cpairv match cpair, then assign the constant cpair - - if (state%psetcols == pcols) then - cp_or_cv(:,:) = cpairv(:,:,lchnk) - else if (state%psetcols > pcols .and. all(cpairv(:,:,lchnk) == cpair)) then - cp_or_cv(1:ncol,:) = cpair - else - call endrun('check_energy_timestep_init: cpairv is not allowed to vary when subcolumns are turned on') - end if - ! - ! CAM physics total energy - ! - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), & - vc_physics, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol),& - te = state%te_ini(1:ncol,phys_te_idx), H2O = state%tw_ini(1:ncol)) - ! - ! Dynamical core total energy - ! - state%temp_ini(:ncol,:) = state%T(:ncol,:) - state%z_ini(:ncol,:) = state%zm(:ncol,:) - if (vc_dycore == vc_height) then - ! - ! MPAS specific hydrostatic energy computation (internal energy) - ! - if (state%psetcols == pcols) then - cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - else - cp_or_cv(:ncol,:) = cpair-rair - endif - - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - 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), & - z_mid = state%z_ini(1:ncol,:), & - te = state%te_ini(1:ncol,dyn_te_idx), H2O = state%tw_ini(1:ncol)) - else if (vc_dycore == vc_dry_pressure) then - ! - ! SE specific hydrostatic energy (enthalpy) - ! - if (state%psetcols == pcols) then - cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - else - cp_or_cv(:ncol,:) = cpair - endif - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), & - vc_dry_pressure, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), & - te = state%te_ini(1:ncol,dyn_te_idx), H2O = state%tw_ini(1:ncol)) - else - ! - ! dycore energy is the same as physics - ! - state%te_ini(1:ncol,dyn_te_idx) = state%te_ini(1:ncol,phys_te_idx) - end if - state%te_cur(:ncol,:) = state%te_ini(:ncol,:) - state%tw_cur(:ncol) = state%tw_ini(:ncol) - -! zero cummulative boundary fluxes - tend%te_tnd(:ncol) = 0._r8 - tend%tw_tnd(:ncol) = 0._r8 - - state%count = 0 - -! initialize physics buffer - if (is_first_step()) then - call pbuf_set_field(pbuf, teout_idx, state%te_ini(:,dyn_te_idx), col_type=col_type) - end if - - end subroutine check_energy_timestep_init - -!=============================================================================== - - subroutine check_energy_chng(state, tend, name, nstep, ztodt, & - flx_vap, flx_cnd, flx_ice, flx_sen) - use cam_thermo, only: get_hydrostatic_energy - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure - use cam_abortutils, only: endrun - use physics_types, only: phys_te_idx, dyn_te_idx -!----------------------------------------------------------------------- -! Check that the energy and water change matches the boundary fluxes -!----------------------------------------------------------------------- -!------------------------------Arguments-------------------------------- - - type(physics_state) , intent(inout) :: state - type(physics_tend ) , intent(inout) :: tend - character*(*),intent(in) :: name ! parameterization name for fluxes - integer , intent(in ) :: nstep ! current timestep number - real(r8), intent(in ) :: ztodt ! 2 delta t (model time increment) - real(r8), intent(in ) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) - real(r8), intent(in ) :: flx_cnd(:) ! (pcols) -boundary flux of liquid+ice (m/s) (precip?) - real(r8), intent(in ) :: flx_ice(:) ! (pcols) -boundary flux of ice (m/s) (snow?) - real(r8), intent(in ) :: flx_sen(:) ! (pcols) -boundary flux of sensible heat (w/m2) - -!******************** BAB ****************************************************** -!******* Note that the precip and ice fluxes are in precip units (m/s). ******** -!******* I would prefer to have kg/m2/s. ******** -!******* I would also prefer liquid (not total) and ice fluxes ******** -!******************************************************************************* - -!---------------------------Local storage------------------------------- - - real(r8) :: te_xpd(state%ncol) ! expected value (f0 + dt*boundary_flux) - real(r8) :: te_dif(state%ncol) ! energy of input state - original energy - real(r8) :: te_tnd(state%ncol) ! tendency from last process - real(r8) :: te_rer(state%ncol) ! relative error in energy column - - real(r8) :: tw_xpd(state%ncol) ! expected value (w0 + dt*boundary_flux) - real(r8) :: tw_dif(state%ncol) ! tw_inp - original water - real(r8) :: tw_tnd(state%ncol) ! tendency from last process - real(r8) :: tw_rer(state%ncol) ! relative error in water column - - real(r8) :: te(state%ncol) ! vertical integral of total energy - real(r8) :: tw(state%ncol) ! vertical integral of total water - real(r8) :: cp_or_cv(state%psetcols,pver) ! cp or cv depending on vcoord - real(r8) :: scaling(state%psetcols,pver) ! scaling for conversion of temperature increment - real(r8) :: temp(state%ncol,pver) ! temperature - - real(r8) :: se(state%ncol) ! enthalpy or internal energy (J/m2) - real(r8) :: po(state%ncol) ! surface potential or potential energy (J/m2) - real(r8) :: ke(state%ncol) ! kinetic energy (J/m2) - real(r8) :: wv(state%ncol) ! column integrated vapor (kg/m2) - real(r8) :: liq(state%ncol) ! column integrated liquid (kg/m2) - real(r8) :: ice(state%ncol) ! column integrated ice (kg/m2) - - integer lchnk ! chunk identifier - integer ncol ! number of atmospheric columns - integer i ! column index -!----------------------------------------------------------------------- - - lchnk = state%lchnk - ncol = state%ncol - - ! If psetcols == pcols, cpairv is the correct size and just copy into cp_or_cv - ! If psetcols > pcols and all cpairv match cpair, then assign the constant cpair - - if (state%psetcols == pcols) then - cp_or_cv(:,:) = cpairv(:,:,lchnk) - else if (state%psetcols > pcols .and. all(cpairv(:,:,:) == cpair)) then - cp_or_cv(:,:) = cpair - else - call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on') - end if - - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), state%T(1:ncol,1:pver), & - vc_physics, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), & - te = te(1:ncol), H2O = tw(1:ncol), se=se(1:ncol),po=po(1:ncol), & - ke=ke(1:ncol),wv=wv(1:ncol),liq=liq(1:ncol),ice=ice(1:ncol)) - ! compute expected values and tendencies - do i = 1, ncol - ! change in static energy and total water - te_dif(i) = te(i) - state%te_cur(i,phys_te_idx) - tw_dif(i) = tw(i) - state%tw_cur(i) - - ! expected tendencies from boundary fluxes for last process - te_tnd(i) = flx_vap(i)*(latvap+latice) - (flx_cnd(i) - flx_ice(i))*1000._r8*latice + flx_sen(i) - tw_tnd(i) = flx_vap(i) - flx_cnd(i) *1000._r8 - - ! cummulative tendencies from boundary fluxes - tend%te_tnd(i) = tend%te_tnd(i) + te_tnd(i) - tend%tw_tnd(i) = tend%tw_tnd(i) + tw_tnd(i) - - ! expected new values from previous state plus boundary fluxes - te_xpd(i) = state%te_cur(i,phys_te_idx) + te_tnd(i)*ztodt - tw_xpd(i) = state%tw_cur(i) + tw_tnd(i)*ztodt - - ! relative error, expected value - input state / previous state - te_rer(i) = (te_xpd(i) - te(i)) / state%te_cur(i,phys_te_idx) - end do - - ! relative error for total water (allow for dry atmosphere) - tw_rer = 0._r8 - where (state%tw_cur(:ncol) > 0._r8) - tw_rer(:ncol) = (tw_xpd(:ncol) - tw(:ncol)) / state%tw_cur(:ncol) - end where - - ! error checking - if (print_energy_errors) then - if (any(abs(te_rer(1:ncol)) > 1.E-14_r8 .or. abs(tw_rer(1:ncol)) > 1.E-10_r8)) then - do i = 1, ncol - ! the relative error threshold for the water budget has been reduced to 1.e-10 - ! to avoid messages generated by QNEG3 calls - ! PJR- change to identify if error in energy or water - if (abs(te_rer(i)) > 1.E-14_r8 ) then - state%count = state%count + 1 - write(iulog,*) "significant energy conservation error after ", name, & - " count", state%count, " nstep", nstep, "chunk", lchnk, "col", i - write(iulog,*) te(i),te_xpd(i),te_dif(i),tend%te_tnd(i)*ztodt, & - te_tnd(i)*ztodt,te_rer(i) - endif - if ( abs(tw_rer(i)) > 1.E-10_r8) then - state%count = state%count + 1 - write(iulog,*) "significant water conservation error after ", name, & - " count", state%count, " nstep", nstep, "chunk", lchnk, "col", i - write(iulog,*) tw(i),tw_xpd(i),tw_dif(i),tend%tw_tnd(i)*ztodt, & - tw_tnd(i)*ztodt,tw_rer(i) - end if - end do - end if - end if - - ! copy new value to state - - do i = 1, ncol - state%te_cur(i,phys_te_idx) = te(i) - state%tw_cur(i) = tw(i) - end do - - ! - ! Dynamical core total energy - ! - if (vc_dycore == vc_height) then - ! - ! compute cv if vertical coordinate is height: cv = cp - R - ! - ! Note: cp_or_cv set above for pressure coordinate - if (state%psetcols == pcols) then - cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - else - cp_or_cv(:ncol,:) = cpair-rair - endif - scaling(:,:) = cpairv(:,:,lchnk)/cp_or_cv(:,:) !cp/cv scaling - temp(1:ncol,:) = state%temp_ini(1:ncol,:)+scaling(1:ncol,:)*(state%T(1:ncol,:)-state%temp_ini(1:ncol,:)) - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), temp(1:ncol,1:pver), & - vc_dycore, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), & - z_mid = state%z_ini(1:ncol,:), & - te = state%te_cur(1:ncol,dyn_te_idx), H2O = state%tw_cur(1:ncol)) - else if (vc_dycore == vc_dry_pressure) then - ! - ! SE specific hydrostatic energy - ! - if (state%psetcols == pcols) then - cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - scaling(:ncol,:) = cpairv(:ncol,:,lchnk)/cp_or_cv_dycore(:ncol,:,lchnk) - else - cp_or_cv(:ncol,:) = cpair - scaling(:ncol,:) = 1.0_r8 - endif - ! - ! enthalpy scaling for energy consistency - ! - temp(1:ncol,:) = state%temp_ini(1:ncol,:)+scaling(1:ncol,:)*(state%T(1:ncol,:)-state%temp_ini(1:ncol,:)) - call get_hydrostatic_energy(state%q(1:ncol,1:pver,1:pcnst),.true., & - state%pdel(1:ncol,1:pver), cp_or_cv(1:ncol,1:pver), & - state%u(1:ncol,1:pver), state%v(1:ncol,1:pver), temp(1:ncol,1:pver), & - vc_dry_pressure, ptop=state%pintdry(1:ncol,1), phis = state%phis(1:ncol), & - te = state%te_cur(1:ncol,dyn_te_idx), H2O = state%tw_cur(1:ncol)) - else - state%te_cur(1:ncol,dyn_te_idx) = te(1:ncol) - end if - end subroutine check_energy_chng - - subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) use physics_buffer, only : physics_buffer_desc, pbuf_get_field, pbuf_get_chunk diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 new file mode 100644 index 0000000000..2bc48d5327 --- /dev/null +++ b/src/physics/cam/check_energy_cam.F90 @@ -0,0 +1,211 @@ +! Shim for CCPP-ized check_energy routines in CAM +module check_energy_cam + use shr_kind_mod, only: r8 => shr_kind_r8 + use ppgrid, only: pcols, pver + use constituents, only: pcnst + use physics_types, only: physics_state, physics_tend + + implicit none + private + + public :: check_energy_cam_chng ! check changes in integrals against cumulative boundary fluxes + public :: check_energy_cam_timestep_init ! timestep initialization of energy integrals and cumulative boundary fluxes + +contains + ! Compute initial values of energy and water integrals, + ! zero cumulative tendencies + subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) + use physics_buffer, only: physics_buffer_desc, pbuf_set_field + use cam_abortutils, only: endrun + use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure + use physics_types, only: phys_te_idx, dyn_te_idx + use time_manager, only: is_first_step + use physconst, only: cpair, rair + use air_composition, only: cpairv, cp_or_cv_dycore + + ! To remove, pbuf indices in check_energy + use check_energy, only: teout_idx + + ! CCPP-ized subroutine + use check_energy_chng, only: check_energy_chng_timestep_init + + type(physics_state), intent(inout) :: state + type(physics_tend ), intent(inout) :: tend + type(physics_buffer_desc), pointer :: pbuf(:) + integer, optional :: col_type ! Flag indicating whether using grid or subcolumns + + real(r8) :: local_cp_phys(state%psetcols,pver) + real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) + integer :: lchnk ! chunk identifier + integer :: ncol ! number of atmospheric columns + character(len=512) :: errmsg + integer :: errflg + + lchnk = state%lchnk + ncol = state%ncol + + ! The code below is split into not-subcolumns and subcolumns code, as there is different handling of the + ! cp passed into the hydrostatic energy call. CAM-SIMA does not support subcolumns, so we keep this special + ! handling inside this shim module. (hplin, 9/9/24) + if(state%psetcols == pcols) then + ! No subcolumns + local_cp_phys(:,:) = cpairv(:,:,lchnk) + local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) + else if (state%psetcols > pcols) then + ! Subcolumns code + ! Subcolumns specific error handling + if(.not. all(cpairv(:,:,lchnk) == cpair)) then + call endrun('check_energy_timestep_init: cpairv is not allowed to vary when subcolumns are turned on') + endif + + local_cp_phys(1:ncol,:) = cpair + + if (vc_dycore == vc_height) then + ! MPAS specific hydrostatic energy computation (internal energy) + local_cp_or_cv_dycore(:ncol,:) = cpair-rair + else if(vc_dycore == vc_dry_pressure) then + ! SE specific hydrostatic energy (enthalpy) + local_cp_or_cv_dycore(:ncol,:) = cpair + else + ! cp_or_cv is not used in the underlying subroutine, zero it out to be sure + local_cp_or_cv_dycore(:ncol,:) = 0.0_r8 + endif + end if + + ! Call CCPP-ized underlying subroutine. + call check_energy_chng_timestep_init( & + ncol = ncol, & + pver = pver, & + pcnst = pcnst, & + q = state%q(1:ncol,1:pver,1:pcnst), & + pdel = state%pdel(1:ncol,1:pver), & + u = state%u(1:ncol,1:pver), & + v = state%v(1:ncol,1:pver), & + T = state%T(1:ncol,1:pver), & + pintdry = state%pintdry(1:ncol,1:pver), & + phis = state%phis(1:ncol), & + zm = state%zm(1:ncol,:), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & + cp_phys = local_cp_phys(1:ncol,:), & + cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & + te_ini_phys = state%te_ini(1:ncol,phys_te_idx), & + te_ini_dyn = state%te_ini(1:ncol,dyn_te_idx), & + tw_ini = state%tw_ini(1:ncol), & + te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & + te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & + tw_cur = state%tw_cur(1:ncol), & + tend_te_tnd = tend%te_tnd(1:ncol), & + tend_tw_tnd = tend%tw_tnd(1:ncol), & + count = state%count, & + vc_physics = vc_physics, & + vc_dycore = vc_dycore, & + errmsg = errmsg, & + errflg = errflg & + ) + + ! initialize physics buffer + if (is_first_step()) then + call pbuf_set_field(pbuf, teout_idx, state%te_ini(:,dyn_te_idx), col_type=col_type) + end if + + end subroutine check_energy_cam_timestep_init + + ! Check that the energy and water change matches the boundary fluxes + subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & + flx_vap, flx_cnd, flx_ice, flx_sen) + use cam_thermo, only: get_hydrostatic_energy + use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure + use cam_abortutils, only: endrun + use physics_types, only: phys_te_idx, dyn_te_idx + use physconst, only: cpair, rair + use air_composition, only: cpairv, cp_or_cv_dycore + + ! CCPP-ized subroutine + use check_energy_chng, only: check_energy_chng_run + + type(physics_state), intent(inout) :: state + type(physics_tend ), intent(inout) :: tend + character*(*),intent(in) :: name ! parameterization name for fluxes + integer , intent(in) :: nstep ! current timestep number + real(r8), intent(in) :: ztodt ! 2 delta t (model time increment) + real(r8), intent(in) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) + real(r8), intent(in) :: flx_cnd(:) ! (pcols) -boundary flux of liquid+ice (m/s) (precip?) + real(r8), intent(in) :: flx_ice(:) ! (pcols) -boundary flux of ice (m/s) (snow?) + real(r8), intent(in) :: flx_sen(:) ! (pcols) -boundary flux of sensible heat (w/m2) + + integer :: lchnk ! chunk identifier + integer :: ncol ! number of atmospheric columns + integer :: i ! column index + real(r8) :: local_cp_phys(state%psetcols,pver) + real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) + real(r8) :: scaling_dycore(state%ncol,pver) + character(len=512) :: errmsg + integer :: errflg + + lchnk = state%lchnk + ncol = state%ncol + + if(state%psetcols == pcols) then + ! No subcolumns + local_cp_phys(:,:) = cpairv(:,:,lchnk) + local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) + + scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + elseif(state%psetcols > pcols) then + ! Subcolumns + if(.not. all(cpairv(:,:,:) == cpair)) then + call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on') + endif + + local_cp_phys(:,:) = cpair + + ! Note: cp_or_cv set above for pressure coordinate + if (vc_dycore == vc_height) then + ! compute cv if vertical coordinate is height: cv = cp - R + local_cp_or_cv_dycore(:ncol,:) = cpair-rair + scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + else if (vc_dycore == vc_dry_pressure) then + ! SE specific hydrostatic energy + local_cp_or_cv_dycore(:ncol,:) = cpair + scaling_dycore(:ncol,:) = 1.0_r8 + else + ! Moist pressure... use phys formula + local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:,lchnk) + scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + end if + endif + + ! Call CCPP-ized underlying subroutine. + call check_energy_chng_run( & + ncol = ncol, & + pver = pver, & + pcnst = pcnst, & + q = state%q(1:ncol,1:pver,1:pcnst), & + pdel = state%pdel(1:ncol,1:pver), & + u = state%u(1:ncol,1:pver), & + v = state%v(1:ncol,1:pver), & + T = state%T(1:ncol,1:pver), & + pintdry = state%pintdry(1:ncol,1:pver), & + phis = state%phis(1:ncol), & + zm = state%zm(1:ncol,:), & + cp_phys = local_cp_phys(1:ncol,:), & + cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & + scaling_dycore = scaling_dycore(1:ncol,:), & + te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & + te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & + tw_cur = state%tw_cur(1:ncol), & + tend_te_tnd = tend%te_tnd(1:ncol), & + tend_tw_tnd = tend%tw_tnd(1:ncol), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & + count = state%count, & + ztodt = ztodt, & + vc_physics = vc_physics, & + vc_dycore = vc_dycore, & + errmsg = errmsg, & + errflg = errflg & + ) + + end subroutine check_energy_cam_chng +end module check_energy_cam \ No newline at end of file diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index ba36670ce8..227274355e 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -2044,7 +2044,8 @@ subroutine tphysbc (ztodt, state, & use convect_deep, only: convect_deep_tend, convect_deep_tend_2, deep_scheme_does_scav_trans use time_manager, only: is_first_step, get_nstep use convect_shallow, only: convect_shallow_tend - use check_energy, only: check_energy_chng, check_energy_fix, check_energy_timestep_init + use check_energy_cam,only: check_energy_cam_timestep_init, check_energy_cam_chng + use check_energy, only: check_energy_fix use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use dycore, only: dycore_is @@ -2630,7 +2631,7 @@ subroutine tphysbc (ztodt, state, & call subcol_gen(state, tend, state_sc, tend_sc, pbuf) !Initialize check energy for subcolumns - call check_energy_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) + call check_energy_cam_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) end if if (trim(cam_take_snapshot_before) == "microp_section") then diff --git a/src/physics/cam/zm_conv_intr.F90 b/src/physics/cam/zm_conv_intr.F90 index 4113c33a4b..5db6d1bc03 100644 --- a/src/physics/cam/zm_conv_intr.F90 +++ b/src/physics/cam/zm_conv_intr.F90 @@ -393,7 +393,6 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & use time_manager, only: get_nstep, is_first_step use physics_buffer, only : pbuf_get_field, physics_buffer_desc, pbuf_old_tim_idx use constituents, only: pcnst, cnst_get_ind, cnst_is_convtran1 - use check_energy, only: check_energy_chng use physconst, only: gravit, latice, latvap, tmelt, cpwv, cpliq, rh2o use phys_control, only: cam_physpkg_is diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index 83d03c46d1..ad5bc9913e 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -1366,7 +1366,8 @@ subroutine tphysac (ztodt, cam_in, & use aoa_tracers, only: aoa_tracers_timestep_tend use physconst, only: rhoh2o use aero_model, only: aero_model_drydep - use check_energy, only: check_energy_chng, tot_energy_phys + use check_energy_cam, only: check_energy_cam_timestep_init, check_energy_cam_chng + use check_energy, only: tot_energy_phys use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use time_manager, only: get_nstep use cam_abortutils, only: endrun @@ -1405,7 +1406,6 @@ subroutine tphysac (ztodt, cam_in, & use aero_model, only: aero_model_wetdep use aero_wetdep_cam, only: wetdep_lq use physics_buffer, only: col_type_subcol - use check_energy, only: check_energy_timestep_init use carma_intr, only: carma_wetdep_tend, carma_timestep_tend, carma_emission_tend use carma_flags_mod, only: carma_do_aerosol, carma_do_emission, carma_do_detrain use carma_flags_mod, only: carma_do_cldice, carma_do_cldliq, carma_do_wetdep @@ -1775,7 +1775,7 @@ subroutine tphysac (ztodt, cam_in, & call subcol_gen(state, tend, state_sc, tend_sc, pbuf) !Initialize check energy for subcolumns - call check_energy_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) + call check_energy_cam_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) end if if (trim(cam_take_snapshot_before) == "microp_section") then From 50afaa6917eb7a40f4f344a8943be30a71c0240f Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 9 Sep 2024 23:56:53 -0400 Subject: [PATCH 25/82] Update physical constants to pass into subroutine --- src/physics/cam/check_energy_cam.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 index 2bc48d5327..4f686b598d 100644 --- a/src/physics/cam/check_energy_cam.F90 +++ b/src/physics/cam/check_energy_cam.F90 @@ -118,7 +118,7 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure use cam_abortutils, only: endrun use physics_types, only: phys_te_idx, dyn_te_idx - use physconst, only: cpair, rair + use physconst, only: cpair, rair, latice, latvap use air_composition, only: cpairv, cp_or_cv_dycore ! CCPP-ized subroutine @@ -201,6 +201,8 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & z_ini = state%z_ini(:ncol,:), & count = state%count, & ztodt = ztodt, & + latice = latice, & + latvap = latvap, & vc_physics = vc_physics, & vc_dycore = vc_dycore, & errmsg = errmsg, & From 80d5b86fb3d2018c978642c21902b31af6c56716 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 10 Sep 2024 00:11:10 -0400 Subject: [PATCH 26/82] Build updates; now use check_energy_cam_chng --- src/physics/cam/check_energy_cam.F90 | 7 ++++- src/physics/cam/physpkg.F90 | 42 ++++++++++++++-------------- src/physics/cam7/physpkg.F90 | 39 +++++++++++++------------- src/physics/simple/physpkg.F90 | 11 ++++---- src/physics/spcam/crm_physics.F90 | 4 +-- src/physics/spcam/spcam_drivers.F90 | 7 +++-- 6 files changed, 59 insertions(+), 51 deletions(-) diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 index 4f686b598d..d5ae76ca48 100644 --- a/src/physics/cam/check_energy_cam.F90 +++ b/src/physics/cam/check_energy_cam.F90 @@ -171,7 +171,7 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & scaling_dycore(:ncol,:) = 1.0_r8 else ! Moist pressure... use phys formula - local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:,lchnk) + local_cp_or_cv_dycore(:,:) = local_cp_phys(:,:) scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling end if endif @@ -205,6 +205,11 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & latvap = latvap, & vc_physics = vc_physics, & vc_dycore = vc_dycore, & + name = name, & + flx_vap = flx_vap, & + flx_cnd = flx_cnd, & + flx_ice = flx_ice, & + flx_sen = flx_sen, & errmsg = errmsg, & errflg = errflg & ) diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index 227274355e..21e693fa17 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -1390,7 +1390,7 @@ subroutine tphysac (ztodt, cam_in, & use aero_model, only: aero_model_drydep use carma_intr, only: carma_emission_tend, carma_timestep_tend use carma_flags_mod, only: carma_do_aerosol, carma_do_emission - use check_energy, only: check_energy_chng, tot_energy_phys + use check_energy, only: tot_energy_phys use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use time_manager, only: get_nstep use cam_abortutils, only: endrun @@ -1615,7 +1615,7 @@ subroutine tphysac (ztodt, cam_in, & call cam_snapshot_all_outfld_tphysac(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf,& fh2o, surfric, obklen, flx_heat) end if - call check_energy_chng(state, tend, "chem", nstep, ztodt, fh2o, zero, zero, zero) + call check_energy_cam_chng(state, tend, "chem", nstep, ztodt, fh2o, zero, zero, zero) call check_tracers_chng(state, tracerint, "chem_timestep_tend", nstep, ztodt, & cam_in%cflx) end if @@ -1677,9 +1677,9 @@ subroutine tphysac (ztodt, cam_in, & call t_stopf('rayleigh_friction') if (do_clubb_sgs) then - call check_energy_chng(state, tend, "vdiff", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "vdiff", nstep, ztodt, zero, zero, zero, zero) else - call check_energy_chng(state, tend, "vdiff", nstep, ztodt, cam_in%cflx(:,1), zero, & + call check_energy_cam_chng(state, tend, "vdiff", nstep, ztodt, cam_in%cflx(:,1), zero, & zero, cam_in%shf) endif @@ -1719,7 +1719,7 @@ subroutine tphysac (ztodt, cam_in, & call carma_timestep_tend(state, cam_in, cam_out, ptend, ztodt, pbuf, obklen=obklen, ustar=surfric) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, zero, zero, zero) call t_stopf('carma_timestep_tend') end if @@ -1759,7 +1759,7 @@ subroutine tphysac (ztodt, cam_in, & end if ! Check energy integrals - call check_energy_chng(state, tend, "gwdrag", nstep, ztodt, zero, & + call check_energy_cam_chng(state, tend, "gwdrag", nstep, ztodt, zero, & zero, zero, flx_heat) call t_stopf('gw_tend') @@ -1789,7 +1789,7 @@ subroutine tphysac (ztodt, cam_in, & end if ! Check energy integrals - call check_energy_chng(state, tend, "qborelax", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "qborelax", nstep, ztodt, zero, zero, zero, zero) ! Lunar tides call lunar_tides_tend( state, ptend ) @@ -1801,7 +1801,7 @@ subroutine tphysac (ztodt, cam_in, & end if call physics_update(state, ptend, ztodt, tend) ! Check energy integrals - call check_energy_chng(state, tend, "lunar_tides", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "lunar_tides", nstep, ztodt, zero, zero, zero, zero) ! Ion drag calculation call t_startf ( 'iondrag' ) @@ -1851,7 +1851,7 @@ subroutine tphysac (ztodt, cam_in, & endif ! Check energy integrals - call check_energy_chng(state, tend, "iondrag", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "iondrag", nstep, ztodt, zero, zero, zero, zero) call t_stopf ( 'iondrag' ) @@ -1866,7 +1866,7 @@ subroutine tphysac (ztodt, cam_in, & call outfld( 'VTEND_NDG', ptend%v, pcols, lchnk) end if call physics_update(state,ptend,ztodt,tend) - call check_energy_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) endif !-------------- Energy budget checks vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv @@ -2257,7 +2257,7 @@ subroutine tphysbc (ztodt, state, & if (.not.dycore_is('EUL')) then call check_energy_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) + call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) end if call tot_energy_phys(state, 'phBP') @@ -2385,7 +2385,7 @@ subroutine tphysbc (ztodt, state, & ! Check energy integrals, including "reserved liquid" flx_cnd(:ncol) = prec_dp(:ncol) + rliq(:ncol) snow_dp(:ncol) = snow_dp(:ncol) + rice(:ncol) - call check_energy_chng(state, tend, "convect_deep", nstep, ztodt, zero, flx_cnd, snow_dp, zero) + call check_energy_cam_chng(state, tend, "convect_deep", nstep, ztodt, zero, flx_cnd, snow_dp, zero) snow_dp(:ncol) = snow_dp(:ncol) - rice(:ncol) ! @@ -2428,7 +2428,7 @@ subroutine tphysbc (ztodt, state, & end if flx_cnd(:ncol) = prec_sh(:ncol) + rliq2(:ncol) - call check_energy_chng(state, tend, "convect_shallow", nstep, ztodt, zero, flx_cnd, snow_sh, zero) + call check_energy_cam_chng(state, tend, "convect_shallow", nstep, ztodt, zero, flx_cnd, snow_sh, zero) call check_tracers_chng(state, tracerint, "convect_shallow", nstep, ztodt, zero_tracers) @@ -2460,9 +2460,9 @@ subroutine tphysbc (ztodt, state, & ! Before the detrainment, the reserved condensate is all liquid, but if CARMA is doing ! detrainment, then the reserved condensate is snow. if (carma_do_detrain) then - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str+rliq, snow_str+rliq, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str+rliq, snow_str+rliq, zero) else - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str, snow_str, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str, snow_str, zero) end if end if @@ -2484,7 +2484,7 @@ subroutine tphysbc (ztodt, state, & cam_in%ts, cam_in%sst, zdu) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "cldwat_tend", nstep, ztodt, zero, prec_str, snow_str, zero) + call check_energy_cam_chng(state, tend, "cldwat_tend", nstep, ztodt, zero, prec_str, snow_str, zero) call t_stopf('rk_stratiform_tend') @@ -2556,7 +2556,7 @@ subroutine tphysbc (ztodt, state, & flx_heat, cmfmc, cmfcme, zdu, rliq, rice, dlf, dlf2, rliq2, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "macrop_tend", nstep, ztodt, & + call check_energy_cam_chng(state, tend, "macrop_tend", nstep, ztodt, & zero, flx_cnd(:ncol)/cld_macmic_num_steps, & det_ice(:ncol)/cld_macmic_num_steps, & flx_heat(:ncol)/cld_macmic_num_steps) @@ -2603,7 +2603,7 @@ subroutine tphysbc (ztodt, state, & end if ! Use actual qflux (not lhf/latvap) for consistency with surface fluxes and revised code - call check_energy_chng(state, tend, "clubb_tend", nstep, ztodt, & + call check_energy_cam_chng(state, tend, "clubb_tend", nstep, ztodt, & cam_in%cflx(:ncol,1)/cld_macmic_num_steps, & flx_cnd(:ncol)/cld_macmic_num_steps, & det_ice(:ncol)/cld_macmic_num_steps, & @@ -2704,7 +2704,7 @@ subroutine tphysbc (ztodt, state, & flx_heat, cmfmc, cmfcme, zdu, rliq, rice, dlf, dlf2, rliq2, det_s, det_ice, net_flx) end if - call check_energy_chng(state_sc, tend_sc, "microp_tend_subcol", & + call check_energy_cam_chng(state_sc, tend_sc, "microp_tend_subcol", & nstep, ztodt, zero_sc, & prec_str_sc(:state_sc%ncol)/cld_macmic_num_steps, & snow_str_sc(:state_sc%ncol)/cld_macmic_num_steps, zero_sc) @@ -2736,7 +2736,7 @@ subroutine tphysbc (ztodt, state, & flx_heat, cmfmc, cmfcme, zdu, rliq, rice, dlf, dlf2, rliq2, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "microp_tend", nstep, ztodt, & + call check_energy_cam_chng(state, tend, "microp_tend", nstep, ztodt, & zero, prec_str(:ncol)/cld_macmic_num_steps, & snow_str(:ncol)/cld_macmic_num_steps, zero) @@ -2889,7 +2889,7 @@ subroutine tphysbc (ztodt, state, & flx_heat, cmfmc, cmfcme, zdu, rliq, rice, dlf, dlf2, rliq2, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "radheat", nstep, ztodt, zero, zero, zero, net_flx) + call check_energy_cam_chng(state, tend, "radheat", nstep, ztodt, zero, zero, zero, net_flx) call t_stopf('radiation') diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index ad5bc9913e..b31a3fcd04 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -1644,7 +1644,7 @@ subroutine tphysac (ztodt, cam_in, & call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "clubb_emissions_tend", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "clubb_emissions_tend", nstep, ztodt, zero, zero, zero, zero) call t_stopf('clubb_emissions_tend') @@ -1672,9 +1672,9 @@ subroutine tphysac (ztodt, cam_in, & ! CARMA is doing ! detrainment, then the reserved condensate is snow. if (carma_do_detrain) then - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str+rliq, snow_str+rliq, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str+rliq, snow_str+rliq, zero) else - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str, snow_str, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, prec_str, snow_str, zero) end if end if @@ -1749,7 +1749,7 @@ subroutine tphysac (ztodt, cam_in, & end if ! Use actual qflux (not lhf/latvap) for consistency with surface fluxes and revised code - call check_energy_chng(state, tend, "clubb_tend", nstep, ztodt, & + call check_energy_cam_chng(state, tend, "clubb_tend", nstep, ztodt, & cam_in%cflx(:ncol,1)/cld_macmic_num_steps, & flx_cnd(:ncol)/cld_macmic_num_steps, & det_ice(:ncol)/cld_macmic_num_steps, & @@ -1848,7 +1848,7 @@ subroutine tphysac (ztodt, cam_in, & fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx) end if - call check_energy_chng(state_sc, tend_sc, "microp_tend_subcol", & + call check_energy_cam_chng(state_sc, tend_sc, "microp_tend_subcol", & nstep, ztodt, zero_sc, & prec_str_sc(:state_sc%ncol)/cld_macmic_num_steps, & snow_str_sc(:state_sc%ncol)/cld_macmic_num_steps, zero_sc) @@ -1880,7 +1880,7 @@ subroutine tphysac (ztodt, cam_in, & fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "microp_tend", nstep, ztodt, & + call check_energy_cam_chng(state, tend, "microp_tend", nstep, ztodt, & zero, prec_str(:ncol)/cld_macmic_num_steps, & snow_str(:ncol)/cld_macmic_num_steps, zero) @@ -2036,7 +2036,7 @@ subroutine tphysac (ztodt, cam_in, & fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "radheat", nstep, ztodt, zero, zero, zero, net_flx) + call check_energy_cam_chng(state, tend, "radheat", nstep, ztodt, zero, zero, zero, net_flx) call t_stopf('radiation') @@ -2113,7 +2113,7 @@ subroutine tphysac (ztodt, cam_in, & call cam_snapshot_all_outfld_tphysac(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf,& fh2o, surfric, obklen, flx_heat, cmfmc, dlf, det_s, det_ice, net_flx) end if - call check_energy_chng(state, tend, "chem", nstep, ztodt, fh2o, zero, zero, zero) + call check_energy_cam_chng(state, tend, "chem", nstep, ztodt, fh2o, zero, zero, zero) call check_tracers_chng(state, tracerint, "chem_timestep_tend", nstep, ztodt, & cam_in%cflx) end if @@ -2175,9 +2175,9 @@ subroutine tphysac (ztodt, cam_in, & call t_stopf('rayleigh_friction') if (do_clubb_sgs) then - call check_energy_chng(state, tend, "vdiff", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "vdiff", nstep, ztodt, zero, zero, zero, zero) else - call check_energy_chng(state, tend, "vdiff", nstep, ztodt, cam_in%cflx(:,1), zero, & + call check_energy_cam_chng(state, tend, "vdiff", nstep, ztodt, cam_in%cflx(:,1), zero, & zero, cam_in%shf) endif @@ -2221,7 +2221,7 @@ subroutine tphysac (ztodt, cam_in, & call carma_timestep_tend(state, cam_in, cam_out, ptend, ztodt, pbuf, obklen=obklen, ustar=surfric) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "carma_tend", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "carma_tend", nstep, ztodt, zero, zero, zero, zero) call t_stopf('carma_timestep_tend') end if @@ -2260,7 +2260,7 @@ subroutine tphysac (ztodt, cam_in, & end if ! Check energy integrals - call check_energy_chng(state, tend, "gwdrag", nstep, ztodt, zero, & + call check_energy_cam_chng(state, tend, "gwdrag", nstep, ztodt, zero, & zero, zero, flx_heat) call t_stopf('gw_tend') @@ -2290,7 +2290,7 @@ subroutine tphysac (ztodt, cam_in, & end if ! Check energy integrals - call check_energy_chng(state, tend, "qborelax", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "qborelax", nstep, ztodt, zero, zero, zero, zero) ! Lunar tides call lunar_tides_tend( state, ptend ) @@ -2302,7 +2302,7 @@ subroutine tphysac (ztodt, cam_in, & end if call physics_update(state, ptend, ztodt, tend) ! Check energy integrals - call check_energy_chng(state, tend, "lunar_tides", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "lunar_tides", nstep, ztodt, zero, zero, zero, zero) ! Ion drag calculation call t_startf ( 'iondrag' ) @@ -2351,7 +2351,7 @@ subroutine tphysac (ztodt, cam_in, & endif ! Check energy integrals - call check_energy_chng(state, tend, "iondrag", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "iondrag", nstep, ztodt, zero, zero, zero, zero) call t_stopf ( 'iondrag' ) @@ -2366,7 +2366,7 @@ subroutine tphysac (ztodt, cam_in, & call outfld( 'VTEND_NDG', ptend%v, pcols, lchnk) end if call physics_update(state,ptend,ztodt,tend) - call check_energy_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) endif !-------------- Energy budget checks vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv @@ -2517,7 +2517,8 @@ subroutine tphysbc (ztodt, state, & use convect_deep, only: convect_deep_tend use time_manager, only: is_first_step, get_nstep use convect_diagnostics,only: convect_diagnostics_calc - use check_energy, only: check_energy_chng, check_energy_fix + use check_energy_cam,only: check_energy_cam_chng + use check_energy, only: check_energy_fix use check_energy, only: check_tracers_data, check_tracers_init use check_energy, only: tot_energy_phys use dycore, only: dycore_is @@ -2701,7 +2702,7 @@ subroutine tphysbc (ztodt, state, & if (.not.dycore_is('EUL')) then call check_energy_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) + call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) end if @@ -2831,7 +2832,7 @@ subroutine tphysbc (ztodt, state, & ! Check energy integrals, including "reserved liquid" flx_cnd(:ncol) = prec_dp(:ncol) + rliq(:ncol) snow_dp(:ncol) = snow_dp(:ncol) + rice(:ncol) - call check_energy_chng(state, tend, "convect_deep", nstep, ztodt, zero, flx_cnd, snow_dp, zero) + call check_energy_cam_chng(state, tend, "convect_deep", nstep, ztodt, zero, flx_cnd, snow_dp, zero) snow_dp(:ncol) = snow_dp(:ncol) - rice(:ncol) !=================================================== diff --git a/src/physics/simple/physpkg.F90 b/src/physics/simple/physpkg.F90 index 8c9c1586ef..22f1171351 100644 --- a/src/physics/simple/physpkg.F90 +++ b/src/physics/simple/physpkg.F90 @@ -503,7 +503,7 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf) use air_composition, only: cpairv, cp_or_cv_dycore use time_manager, only: get_nstep use nudging, only: Nudge_Model, Nudge_ON, nudging_timestep_tend - use check_energy, only: check_energy_chng + use check_energy_cam,only: check_energy_cam_chng ! Arguments ! @@ -595,7 +595,7 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf) if (Nudge_Model .and. Nudge_ON) then call nudging_timestep_tend(state,ptend) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "nudging", nstep, ztodt, zero, zero, zero, zero) endif call tot_energy_phys(state, 'phAP') @@ -728,7 +728,8 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) use cam_diagnostics, only: diag_conv_tend_ini, diag_conv, diag_export use cam_history, only: outfld use time_manager, only: get_nstep - use check_energy, only: check_energy_chng, check_energy_fix, check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_chng + use check_energy, only: check_energy_fix, check_energy_timestep_init use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use chemistry, only: chem_is_active, chem_timestep_tend @@ -833,7 +834,7 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) if (adiabatic .and. (.not. dycore_is('EUL'))) then call check_energy_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) + call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) end if @@ -968,7 +969,7 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) ! surface flux is computed and supplied as an argument to ! check_energy_chng to account for how the simplified physics forcings are ! changing the total exnergy. - call check_energy_chng(state, tend, "tphysidl", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "tphysidl", nstep, ztodt, zero, zero, zero, zero) if (chem_is_active()) then call t_startf('simple_chem') diff --git a/src/physics/spcam/crm_physics.F90 b/src/physics/spcam/crm_physics.F90 index a1d9d2560d..735d6c3630 100644 --- a/src/physics/spcam/crm_physics.F90 +++ b/src/physics/spcam/crm_physics.F90 @@ -750,7 +750,7 @@ subroutine crm_physics_tend(ztodt, state, tend, ptend, pbuf, cam_in) use crmx_crm_module, only: crm use crmx_microphysics, only: nmicro_fields use physconst, only: latvap - use check_energy, only: check_energy_chng + use check_energy_cam, only: check_energy_cam_chng use phys_grid, only: get_rlat_all_p, get_rlon_all_p, get_lon_all_p, get_lat_all_p use modal_aero_calcsize, only: modal_aero_calcsize_sub use micro_pumas_utils, only: size_dist_param_liq, mg_liq_props, mincld, qsmall @@ -2152,7 +2152,7 @@ subroutine crm_physics_tend(ztodt, state, tend, ptend, pbuf, cam_in) end if ! check water and energy conservation - call check_energy_chng(state_loc, tend_loc, "crm_tend", nstep, ztodt, zero, & + call check_energy_cam_chng(state_loc, tend_loc, "crm_tend", nstep, ztodt, zero, & prec_dp(:ncol)+(qli_hydro(:ncol,2)-qli_hydro(:ncol,1))/ztodt/1000._r8, & snow_dp(:ncol)+(qi_hydro(:ncol,2)-qi_hydro(:ncol,1))/ztodt/1000._r8, radflux) diff --git a/src/physics/spcam/spcam_drivers.F90 b/src/physics/spcam/spcam_drivers.F90 index ebe6507607..00ab2448bd 100644 --- a/src/physics/spcam/spcam_drivers.F90 +++ b/src/physics/spcam/spcam_drivers.F90 @@ -300,7 +300,8 @@ subroutine tphysbc_spcam (ztodt, state, & use cam_history, only: outfld use constituents, only: pcnst, qmin, cnst_get_ind use time_manager, only: get_nstep - use check_energy, only: check_energy_chng, check_energy_fix + use check_energy_cam,only: check_energy_cam_chng + use check_energy, only: check_energy_fix use check_energy, only: check_tracers_data, check_tracers_init use dycore, only: dycore_is use radiation, only: radiation_tend @@ -443,7 +444,7 @@ subroutine tphysbc_spcam (ztodt, state, & if (dycore_is('LR') .or. dycore_is('SE')) then call check_energy_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) + call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld('EFIX', flx_heat, pcols,lchnk) end if ! Save state for convective tendency calculations. @@ -557,7 +558,7 @@ subroutine tphysbc_spcam (ztodt, state, & call physics_update(state, ptend, ztodt, tend) - call check_energy_chng(state, tend, "spradheat", nstep, ztodt, zero, zero, zero, zero) + call check_energy_cam_chng(state, tend, "spradheat", nstep, ztodt, zero, zero, zero, zero) call t_stopf('radiation') From 03209f0918ce253ea326963a9ee56eab1e2bd89c Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 10 Sep 2024 00:16:43 -0400 Subject: [PATCH 27/82] Add missing USE in physbc --- src/physics/cam/physpkg.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index 21e693fa17..bab29327b2 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -1392,6 +1392,7 @@ subroutine tphysac (ztodt, cam_in, & use carma_flags_mod, only: carma_do_aerosol, carma_do_emission use check_energy, only: tot_energy_phys use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng + use check_energy_cam, only: check_energy_cam_chng use time_manager, only: get_nstep use cam_abortutils, only: endrun use dycore, only: dycore_is From 3cc3c3e33cc026cf3148a29a988b59a6d868cf81 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 10 Sep 2024 19:34:41 -0400 Subject: [PATCH 28/82] Fix array oob pcols --- src/physics/cam/check_energy_cam.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 index d5ae76ca48..7e1c289b96 100644 --- a/src/physics/cam/check_energy_cam.F90 +++ b/src/physics/cam/check_energy_cam.F90 @@ -49,7 +49,7 @@ subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) ! handling inside this shim module. (hplin, 9/9/24) if(state%psetcols == pcols) then ! No subcolumns - local_cp_phys(:,:) = cpairv(:,:,lchnk) + local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) else if (state%psetcols > pcols) then ! Subcolumns code @@ -148,10 +148,10 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & if(state%psetcols == pcols) then ! No subcolumns - local_cp_phys(:,:) = cpairv(:,:,lchnk) + local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling elseif(state%psetcols > pcols) then ! Subcolumns if(.not. all(cpairv(:,:,:) == cpair)) then @@ -164,14 +164,14 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & if (vc_dycore == vc_height) then ! compute cv if vertical coordinate is height: cv = cp - R local_cp_or_cv_dycore(:ncol,:) = cpair-rair - scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling else if (vc_dycore == vc_dry_pressure) then ! SE specific hydrostatic energy local_cp_or_cv_dycore(:ncol,:) = cpair scaling_dycore(:ncol,:) = 1.0_r8 else ! Moist pressure... use phys formula - local_cp_or_cv_dycore(:,:) = local_cp_phys(:,:) + local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:) scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling end if endif From f7f4139a6f1333eb80375d6adcfb8a34247b22e3 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 7 Oct 2024 10:56:11 -0600 Subject: [PATCH 29/82] Update atmos_phys to check_energy version --- .gitmodules | 4 +- src/atmos_phys | 2 +- src/physics/cam/cam_diagnostics.F90 | 2 +- src/physics/cam/check_energy.F90 | 164 ++------------------------- src/physics/cam/check_energy_cam.F90 | 164 ++++++++++++++++++++++++++- src/physics/cam/physpkg.F90 | 6 +- src/physics/cam7/physpkg.F90 | 7 +- src/physics/simple/physpkg.F90 | 8 +- src/physics/spcam/spcam_drivers.F90 | 5 +- 9 files changed, 184 insertions(+), 178 deletions(-) diff --git a/.gitmodules b/.gitmodules index 224ee10052..e295d8fec1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -35,8 +35,8 @@ [submodule "atmos_phys"] path = src/atmos_phys - url = https://github.com/ESCOMP/atmospheric_physics - fxtag = atmos_phys0_05_001 + url = https://github.com/jimmielin/atmospheric_physics + fxtag = df80b9c1 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index f8ce60bf40..df80b9c1e7 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit f8ce60bf40f800623f8eb3065021ec5dfa9e6b45 +Subproject commit df80b9c1e73064f9a0196282a92b66a2041f6a57 diff --git a/src/physics/cam/cam_diagnostics.F90 b/src/physics/cam/cam_diagnostics.F90 index 97dad2ba01..00d6859a84 100644 --- a/src/physics/cam/cam_diagnostics.F90 +++ b/src/physics/cam/cam_diagnostics.F90 @@ -2019,7 +2019,7 @@ subroutine diag_phys_tend_writeout_dry(state, pbuf, tend, ztodt) ! !--------------------------------------------------------------- - use check_energy, only: check_energy_get_integrals + use check_energy_cam,only: check_energy_get_integrals use physconst, only: cpair ! Arguments diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 5e1df3a967..d71f3df8f6 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -24,13 +24,11 @@ module check_energy use ppgrid, only: pcols, pver, begchunk, endchunk use spmd_utils, only: masterproc - use gmean_mod, only: gmean use physconst, only: gravit, rga, latvap, latice, cpair, rair use air_composition, only: cpairv, cp_or_cv_dycore - use physics_types, only: physics_state, physics_tend, physics_ptend, physics_ptend_init + use physics_types, only: physics_state use constituents, only: cnst_get_ind, pcnst, cnst_name, cnst_get_type_byind use cam_logfile, only: iulog - use scamMod, only: single_column, use_camiop, heat_glob_scm use cam_history, only: outfld, write_camiop implicit none @@ -42,10 +40,7 @@ module check_energy ! Public methods public :: check_energy_readnl ! read namelist values public :: check_energy_register ! register fields in physics buffer - public :: check_energy_get_integrals ! get energy integrals computed in check_energy_gmean public :: check_energy_init ! initialization of module - public :: check_energy_gmean ! global means of physics input and output total energy - public :: check_energy_fix ! add global mean energy difference as a heating public :: check_tracers_init ! initialize tracer integrals and cumulative boundary fluxes public :: check_tracers_chng ! check changes in integrals against cumulative boundary fluxes @@ -55,13 +50,6 @@ module check_energy logical :: print_energy_errors = .false. - real(r8) :: teout_glob ! global mean energy of output state - real(r8) :: teinp_glob ! global mean energy of input state - real(r8) :: tedif_glob ! global mean energy difference - real(r8) :: psurf_glob ! global mean surface pressure - real(r8) :: ptopb_glob ! global mean top boundary pressure - real(r8) :: heat_glob ! global mean heating rate - ! Physics buffer indices integer, public :: teout_idx = 0 ! teout index in physics buffer @@ -88,6 +76,9 @@ subroutine check_energy_readnl(nlfile) use spmd_utils, only: mpicom, mstrid=>masterprocid, mpi_logical use cam_abortutils, only: endrun + ! update the CCPP-ized namelist option + use check_energy_chng, only: check_energy_chng_init + character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input ! Local variables @@ -120,6 +111,9 @@ subroutine check_energy_readnl(nlfile) write(iulog,*) ' print_energy_errors =', print_energy_errors end if + ! update the CCPP-ized namelist option + call check_energy_chng_init(print_energy_errors_in=print_energy_errors) + end subroutine check_energy_readnl !=============================================================================== @@ -154,28 +148,6 @@ subroutine check_energy_register() end subroutine check_energy_register -!=============================================================================== - -subroutine check_energy_get_integrals( tedif_glob_out, heat_glob_out ) - -!----------------------------------------------------------------------- -! Purpose: Return energy integrals -!----------------------------------------------------------------------- - - real(r8), intent(out), optional :: tedif_glob_out - real(r8), intent(out), optional :: heat_glob_out - -!----------------------------------------------------------------------- - - if ( present(tedif_glob_out) ) then - tedif_glob_out = tedif_glob - endif - if ( present(heat_glob_out) ) then - heat_glob_out = heat_glob - endif - -end subroutine check_energy_get_integrals - !================================================================================================ subroutine check_energy_init() @@ -214,128 +186,6 @@ subroutine check_energy_init() end subroutine check_energy_init -!=============================================================================== - - subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) - - use physics_buffer, only : physics_buffer_desc, pbuf_get_field, pbuf_get_chunk - use physics_types, only: dyn_te_idx - use cam_history, only: write_camiop -!----------------------------------------------------------------------- -! Compute global mean total energy of physics input and output states -! computed consistently with dynamical core vertical coordinate -! (under hydrostatic assumption) -!----------------------------------------------------------------------- -!------------------------------Arguments-------------------------------- - - type(physics_state), intent(in ), dimension(begchunk:endchunk) :: state - type(physics_buffer_desc), pointer :: pbuf2d(:,:) - - real(r8), intent(in) :: dtime ! physics time step - integer , intent(in) :: nstep ! current timestep number - -!---------------------------Local storage------------------------------- - integer :: ncol ! number of active columns - integer :: lchnk ! chunk index - - real(r8) :: te(pcols,begchunk:endchunk,4) - ! total energy of input/output states (copy) - real(r8) :: te_glob(4) ! global means of total energy - real(r8), pointer :: teout(:) -!----------------------------------------------------------------------- - - ! Copy total energy out of input and output states - do lchnk = begchunk, endchunk - ncol = state(lchnk)%ncol - ! input energy using dynamical core energy formula - te(:ncol,lchnk,1) = state(lchnk)%te_ini(:ncol,dyn_te_idx) - ! output energy - call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk),teout_idx, teout) - - te(:ncol,lchnk,2) = teout(1:ncol) - ! surface pressure for heating rate - te(:ncol,lchnk,3) = state(lchnk)%pint(:ncol,pver+1) - ! model top pressure for heating rate (not constant for z-based vertical coordinate!) - te(:ncol,lchnk,4) = state(lchnk)%pint(:ncol,1) - end do - - ! Compute global means of input and output energies and of - ! surface pressure for heating rate (assume uniform ptop) - call gmean(te, te_glob, 4) - - if (begchunk .le. endchunk) then - teinp_glob = te_glob(1) - teout_glob = te_glob(2) - psurf_glob = te_glob(3) - ptopb_glob = te_glob(4) - - ! Global mean total energy difference - tedif_glob = teinp_glob - teout_glob - heat_glob = -tedif_glob/dtime * gravit / (psurf_glob - ptopb_glob) - if (masterproc) then - write(iulog,'(1x,a9,1x,i8,5(1x,e25.17))') "nstep, te", nstep, teinp_glob, teout_glob, & - heat_glob, psurf_glob, ptopb_glob - end if - else - heat_glob = 0._r8 - end if ! (begchunk .le. endchunk) - - end subroutine check_energy_gmean - -!=============================================================================== - subroutine check_energy_fix(state, ptend, nstep, eshflx) - -!----------------------------------------------------------------------- -! Add heating rate required for global mean total energy conservation -!----------------------------------------------------------------------- -!------------------------------Arguments-------------------------------- - - type(physics_state), intent(in ) :: state - type(physics_ptend), intent(out) :: ptend - - integer , intent(in ) :: nstep ! time step number - real(r8), intent(out ) :: eshflx(pcols) ! effective sensible heat flux - -!---------------------------Local storage------------------------------- - integer :: i ! column - integer :: ncol ! number of atmospheric columns in chunk - integer :: lchnk ! chunk number - real(r8) :: heat_out(pcols) -!----------------------------------------------------------------------- - lchnk = state%lchnk - ncol = state%ncol - - call physics_ptend_init(ptend, state%psetcols, 'chkenergyfix', ls=.true.) - -#if ( defined OFFLINE_DYN ) - ! disable the energy fix for offline driver - heat_glob = 0._r8 -#endif - - ! Special handling of energy fix for SCAM - supplied via CAMIOP - zero's for normal IOPs - if (single_column) then - if ( use_camiop) then - heat_glob = heat_glob_scm(1) - else - heat_glob = 0._r8 - endif - endif - ptend%s(:ncol,:pver) = heat_glob - - if (nstep > 0 .and. write_camiop) then - heat_out(:ncol) = heat_glob - call outfld('heat_glob', heat_out(:ncol), pcols, lchnk) - endif - -! compute effective sensible heat flux - do i = 1, ncol - eshflx(i) = heat_glob * (state%pint(i,pver+1) - state%pint(i,1)) * rga - end do - - return - end subroutine check_energy_fix - - !=============================================================================== subroutine check_tracers_init(state, tracerint) diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 index 7e1c289b96..6931cfb3ee 100644 --- a/src/physics/cam/check_energy_cam.F90 +++ b/src/physics/cam/check_energy_cam.F90 @@ -1,4 +1,4 @@ -! Shim for CCPP-ized check_energy routines in CAM +! CAM interface for CCPP-ized check_energy routines in CAM module check_energy_cam use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver @@ -8,9 +8,23 @@ module check_energy_cam implicit none private - public :: check_energy_cam_chng ! check changes in integrals against cumulative boundary fluxes + public :: check_energy_cam_chng ! check changes in integrals against cumulative boundary fluxes public :: check_energy_cam_timestep_init ! timestep initialization of energy integrals and cumulative boundary fluxes + public :: check_energy_cam_fix ! add heating rate required for global mean total energy conservation + + ! These subroutines cannot be CCPP-ized and replicated from check_energy + public :: check_energy_gmean ! global means of physics input and output total energy + public :: check_energy_get_integrals ! get energy integrals computed in check_energy_gmean + + ! Module variables used for check_energy_gmean + real(r8) :: teout_glob ! global mean energy of output state + real(r8) :: teinp_glob ! global mean energy of input state + real(r8) :: tedif_glob ! global mean energy difference + real(r8) :: psurf_glob ! global mean surface pressure + real(r8) :: ptopb_glob ! global mean top boundary pressure + real(r8) :: heat_glob ! global mean heating rate + contains ! Compute initial values of energy and water integrals, ! zero cumulative tendencies @@ -215,4 +229,148 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & ) end subroutine check_energy_cam_chng -end module check_energy_cam \ No newline at end of file + + ! Add heating rate required for global mean total energy conservation + subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) + use physics_types, only: physics_ptend, physics_ptend_init + use physconst, only: rga + + ! SCAM support + use scamMod, only: single_column, use_camiop, heat_glob_scm + + ! CCPP-ized subroutine + use check_energy_fix, only: check_energy_fix_run + + type(physics_state), intent(in) :: state + type(physics_ptend), intent(out) :: ptend + + integer , intent(in) :: nstep ! time step number + real(r8), intent(out) :: eshflx(pcols) ! effective sensible heat flux + + integer :: ncol ! number of atmospheric columns in chunk + integer :: lchnk ! chunk number + real(r8) :: heat_out(pcols) + + lchnk = state%lchnk + ncol = state%ncol + + call physics_ptend_init(ptend, state%psetcols, 'chkenergyfix', ls=.true.) + +#if ( defined OFFLINE_DYN ) + ! disable the energy fix for offline driver + heat_glob = 0._r8 +#endif + + ! Special handling of energy fix for SCAM - supplied via CAMIOP - zero's for normal IOPs + if (single_column) then + if (use_camiop) then + heat_glob = heat_glob_scm(1) + else + heat_glob = 0._r8 + endif + endif + + if (nstep > 0 .and. write_camiop) then + heat_out(:ncol) = heat_glob + call outfld('heat_glob', heat_out(:ncol), pcols, lchnk) + endif + + ! Call the CCPP-ized subroutine (for non-SCAM) + ! to compute the effective sensible heat flux and save to ptend%s + call check_energy_fix_run( & + ncol = ncol, & + pver = pver, & + pint = state%pint(:ncol,:), & + rga = rga, & + heat_glob = heat_glob. & + ptend_s = ptend%s(:ncol,:), & + eshflx = eshflx(:ncol) & + ) + + end subroutine check_energy_cam_fix + + ! Compute global mean total energy of physics input and output states + ! computed consistently with dynamical core vertical coordinate + ! (under hydrostatic assumption) + ! + ! This subroutine cannot use the CCPP-ized equivalent because + ! it is dependent on chunks. + subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) + use physics_buffer, only: physics_buffer_desc, pbuf_get_field, pbuf_get_chunk + use physics_types, only: dyn_te_idx + use cam_history, only: write_camiop + use ppgrid, only: begchunk, endchunk + use spmd_utils, only: masterproc + use cam_logfile, only: iulog + use gmean_mod, only: gmean + use physconst, only: gravit + + ! To remove, pbuf indices in check_energy + use check_energy, only: teout_idx + + type(physics_state), intent(in), dimension(begchunk:endchunk) :: state + type(physics_buffer_desc), pointer :: pbuf2d(:,:) + + real(r8), intent(in) :: dtime ! physics time step + integer , intent(in) :: nstep ! current timestep number + + integer :: ncol ! number of active columns + integer :: lchnk ! chunk index + + real(r8) :: te(pcols,begchunk:endchunk,4) + ! total energy of input/output states (copy) + real(r8) :: te_glob(4) ! global means of total energy + real(r8), pointer :: teout(:) + + ! Copy total energy out of input and output states + do lchnk = begchunk, endchunk + ncol = state(lchnk)%ncol + ! input energy using dynamical core energy formula + te(:ncol,lchnk,1) = state(lchnk)%te_ini(:ncol,dyn_te_idx) + ! output energy + call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk),teout_idx, teout) + + te(:ncol,lchnk,2) = teout(1:ncol) + ! surface pressure for heating rate + te(:ncol,lchnk,3) = state(lchnk)%pint(:ncol,pver+1) + ! model top pressure for heating rate (not constant for z-based vertical coordinate!) + te(:ncol,lchnk,4) = state(lchnk)%pint(:ncol,1) + end do + + ! Compute global means of input and output energies and of + ! surface pressure for heating rate (assume uniform ptop) + call gmean(te, te_glob, 4) + + if (begchunk .le. endchunk) then + teinp_glob = te_glob(1) + teout_glob = te_glob(2) + psurf_glob = te_glob(3) + ptopb_glob = te_glob(4) + + ! Global mean total energy difference + tedif_glob = teinp_glob - teout_glob + heat_glob = -tedif_glob/dtime * gravit / (psurf_glob - ptopb_glob) + if (masterproc) then + write(iulog,'(1x,a9,1x,i8,5(1x,e25.17))') "nstep, te", nstep, teinp_glob, teout_glob, & + heat_glob, psurf_glob, ptopb_glob + end if + else + heat_glob = 0._r8 + end if ! (begchunk .le. endchunk) + + end subroutine check_energy_gmean + + ! Return energy integrals (module variables) + subroutine check_energy_get_integrals(tedif_glob_out, heat_glob_out) + real(r8), intent(out), optional :: tedif_glob_out + real(r8), intent(out), optional :: heat_glob_out + + if ( present(tedif_glob_out) ) then + tedif_glob_out = tedif_glob + endif + + if ( present(heat_glob_out) ) then + heat_glob_out = heat_glob + endif + end subroutine check_energy_get_integrals +end module check_energy_cam diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index bab29327b2..25f46c3a45 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -1065,7 +1065,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics,only: diag_allocate, diag_physvar_ic - use check_energy, only: check_energy_gmean + use check_energy_cam, only: check_energy_gmean use phys_control, only: phys_getopts use spcam_drivers, only: tphysbc_spcam use spmd_utils, only: mpicom @@ -2046,7 +2046,7 @@ subroutine tphysbc (ztodt, state, & use time_manager, only: is_first_step, get_nstep use convect_shallow, only: convect_shallow_tend use check_energy_cam,only: check_energy_cam_timestep_init, check_energy_cam_chng - use check_energy, only: check_energy_fix + use check_energy_cam,only: check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use dycore, only: dycore_is @@ -2256,7 +2256,7 @@ subroutine tphysbc (ztodt, state, & call tot_energy_phys(state, 'phBF') call tot_energy_phys(state, 'dyBF',vc=vc_dycore) if (.not.dycore_is('EUL')) then - call check_energy_fix(state, ptend, nstep, flx_heat) + call check_energy_cam_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index b31a3fcd04..1ce28d3a93 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -1056,7 +1056,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics,only: diag_allocate, diag_physvar_ic - use check_energy, only: check_energy_gmean + use check_energy_cam, only: check_energy_gmean use spmd_utils, only: mpicom use physics_buffer, only: physics_buffer_desc, pbuf_get_chunk, pbuf_allocate use cam_history, only: outfld, write_camiop @@ -2517,8 +2517,7 @@ subroutine tphysbc (ztodt, state, & use convect_deep, only: convect_deep_tend use time_manager, only: is_first_step, get_nstep use convect_diagnostics,only: convect_diagnostics_calc - use check_energy_cam,only: check_energy_cam_chng - use check_energy, only: check_energy_fix + use check_energy_cam,only: check_energy_cam_chng, check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init use check_energy, only: tot_energy_phys use dycore, only: dycore_is @@ -2700,7 +2699,7 @@ subroutine tphysbc (ztodt, state, & call tot_energy_phys(state, 'dyBF',vc=vc_dycore) if (.not.dycore_is('EUL')) then - call check_energy_fix(state, ptend, nstep, flx_heat) + call check_energy_cam_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) diff --git a/src/physics/simple/physpkg.F90 b/src/physics/simple/physpkg.F90 index 22f1171351..3e594d9073 100644 --- a/src/physics/simple/physpkg.F90 +++ b/src/physics/simple/physpkg.F90 @@ -305,7 +305,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics, only: diag_allocate, diag_physvar_ic - use check_energy, only: check_energy_gmean + use check_energy_cam, only: check_energy_gmean use physics_buffer, only: physics_buffer_desc, pbuf_get_chunk, pbuf_allocate ! @@ -728,8 +728,8 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) use cam_diagnostics, only: diag_conv_tend_ini, diag_conv, diag_export use cam_history, only: outfld use time_manager, only: get_nstep - use check_energy_cam, only: check_energy_cam_chng - use check_energy, only: check_energy_fix, check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_chng, check_energy_cam_fix + use check_energy, only: check_energy_timestep_init use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use chemistry, only: chem_is_active, chem_timestep_tend @@ -832,7 +832,7 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) call t_startf('energy_fixer') if (adiabatic .and. (.not. dycore_is('EUL'))) then - call check_energy_fix(state, ptend, nstep, flx_heat) + call check_energy_cam_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) diff --git a/src/physics/spcam/spcam_drivers.F90 b/src/physics/spcam/spcam_drivers.F90 index 00ab2448bd..cd7d3f6370 100644 --- a/src/physics/spcam/spcam_drivers.F90 +++ b/src/physics/spcam/spcam_drivers.F90 @@ -300,8 +300,7 @@ subroutine tphysbc_spcam (ztodt, state, & use cam_history, only: outfld use constituents, only: pcnst, qmin, cnst_get_ind use time_manager, only: get_nstep - use check_energy_cam,only: check_energy_cam_chng - use check_energy, only: check_energy_fix + use check_energy_cam,only: check_energy_cam_chng, check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init use dycore, only: dycore_is use radiation, only: radiation_tend @@ -442,7 +441,7 @@ subroutine tphysbc_spcam (ztodt, state, & call t_startf('energy_fixer') if (dycore_is('LR') .or. dycore_is('SE')) then - call check_energy_fix(state, ptend, nstep, flx_heat) + call check_energy_cam_fix(state, ptend, nstep, flx_heat) call physics_update(state, ptend, ztodt, tend) call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld('EFIX', flx_heat, pcols,lchnk) From f6f464bb6b73aa52c2850cdb4595ab4148774fc4 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Thu, 10 Oct 2024 16:26:34 -0600 Subject: [PATCH 30/82] Fix build errors -- does not include bld/configure atmos_phys path updates --- src/physics/cam/check_energy.F90 | 2 +- src/physics/cam/check_energy_cam.F90 | 12 ++++++++---- src/physics/simple/physpkg.F90 | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index d71f3df8f6..9f9faa10fe 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -29,7 +29,7 @@ module check_energy use physics_types, only: physics_state use constituents, only: cnst_get_ind, pcnst, cnst_name, cnst_get_type_byind use cam_logfile, only: iulog - use cam_history, only: outfld, write_camiop + use cam_history, only: outfld implicit none private diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 index 6931cfb3ee..e1f143c0c2 100644 --- a/src/physics/cam/check_energy_cam.F90 +++ b/src/physics/cam/check_energy_cam.F90 @@ -50,6 +50,7 @@ subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) real(r8) :: local_cp_phys(state%psetcols,pver) real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) + real(r8) :: teout(state%ncol) ! dummy teout argument integer :: lchnk ! chunk identifier integer :: ncol ! number of atmospheric columns character(len=512) :: errmsg @@ -91,6 +92,7 @@ subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) ncol = ncol, & pver = pver, & pcnst = pcnst, & + is_first_timestep = is_first_step(), & q = state%q(1:ncol,1:pver,1:pcnst), & pdel = state%pdel(1:ncol,1:pver), & u = state%u(1:ncol,1:pver), & @@ -99,8 +101,6 @@ subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) pintdry = state%pintdry(1:ncol,1:pver), & phis = state%phis(1:ncol), & zm = state%zm(1:ncol,:), & - temp_ini = state%temp_ini(:ncol,:), & - z_ini = state%z_ini(:ncol,:), & cp_phys = local_cp_phys(1:ncol,:), & cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & te_ini_phys = state%te_ini(1:ncol,phys_te_idx), & @@ -111,7 +111,10 @@ subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) tw_cur = state%tw_cur(1:ncol), & tend_te_tnd = tend%te_tnd(1:ncol), & tend_tw_tnd = tend%tw_tnd(1:ncol), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & count = state%count, & + teout = teout(1:ncol), & ! dummy argument - actual teout written to pbuf directly below vc_physics = vc_physics, & vc_dycore = vc_dycore, & errmsg = errmsg, & @@ -237,6 +240,8 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) ! SCAM support use scamMod, only: single_column, use_camiop, heat_glob_scm + use cam_history, only: write_camiop + use cam_history, only: outfld ! CCPP-ized subroutine use check_energy_fix, only: check_energy_fix_run @@ -282,7 +287,7 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) pver = pver, & pint = state%pint(:ncol,:), & rga = rga, & - heat_glob = heat_glob. & + heat_glob = heat_glob, & ptend_s = ptend%s(:ncol,:), & eshflx = eshflx(:ncol) & ) @@ -298,7 +303,6 @@ end subroutine check_energy_cam_fix subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) use physics_buffer, only: physics_buffer_desc, pbuf_get_field, pbuf_get_chunk use physics_types, only: dyn_te_idx - use cam_history, only: write_camiop use ppgrid, only: begchunk, endchunk use spmd_utils, only: masterproc use cam_logfile, only: iulog diff --git a/src/physics/simple/physpkg.F90 b/src/physics/simple/physpkg.F90 index 3e594d9073..eaea0ff1dd 100644 --- a/src/physics/simple/physpkg.F90 +++ b/src/physics/simple/physpkg.F90 @@ -729,7 +729,7 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) use cam_history, only: outfld use time_manager, only: get_nstep use check_energy_cam, only: check_energy_cam_chng, check_energy_cam_fix - use check_energy, only: check_energy_timestep_init + use check_energy_cam, only: check_energy_cam_timestep_init use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use chemistry, only: chem_is_active, chem_timestep_tend From 2ffa522d8403f73aba0f306a2c35dd50319c33a5 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 14 Oct 2024 12:16:26 -0400 Subject: [PATCH 31/82] Move back to check_energy.F90 for FV3 external compatibility --- src/dynamics/eul/dp_coupling.F90 | 4 +- src/dynamics/fv/dp_coupling.F90 | 4 +- src/dynamics/mpas/dp_coupling.F90 | 4 +- src/dynamics/se/dp_coupling.F90 | 4 +- src/physics/cam/cam_diagnostics.F90 | 2 +- src/physics/cam/check_energy.F90 | 390 ++++++++++++++++++++++++++- src/physics/cam/check_energy_cam.F90 | 380 -------------------------- src/physics/cam/physpkg.F90 | 12 +- src/physics/cam7/physpkg.F90 | 8 +- src/physics/simple/physpkg.F90 | 8 +- src/physics/spcam/crm_physics.F90 | 2 +- src/physics/spcam/spcam_drivers.F90 | 2 +- 12 files changed, 403 insertions(+), 417 deletions(-) delete mode 100644 src/physics/cam/check_energy_cam.F90 diff --git a/src/dynamics/eul/dp_coupling.F90 b/src/dynamics/eul/dp_coupling.F90 index 8e3eb64a21..bc900e2d0e 100644 --- a/src/dynamics/eul/dp_coupling.F90 +++ b/src/dynamics/eul/dp_coupling.F90 @@ -14,7 +14,7 @@ module dp_coupling use physconst, only: cpair, gravit, rair, zvir use air_composition, only: rairv use geopotential, only: geopotential_t - use check_energy_cam, only: check_energy_cam_timestep_init + use check_energy, only: check_energy_timestep_init #if (defined SPMD) use spmd_dyn, only: buf1, buf1win, buf2, buf2win, & spmdbuf_siz, local_dp_map, & @@ -291,7 +291,7 @@ subroutine d_p_coupling(ps, t3, u3, v3, q3, & ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk ) + call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk ) end do diff --git a/src/dynamics/fv/dp_coupling.F90 b/src/dynamics/fv/dp_coupling.F90 index af2d13b12e..fc02821471 100644 --- a/src/dynamics/fv/dp_coupling.F90 +++ b/src/dynamics/fv/dp_coupling.F90 @@ -12,7 +12,7 @@ module dp_coupling use physconst, only: gravit, zvir use air_composition, only: cpairv, rairv use geopotential, only: geopotential_t - use check_energy_cam, only: check_energy_cam_timestep_init + use check_energy, only: check_energy_timestep_init use dynamics_vars, only: T_FVDYCORE_GRID, t_fvdycore_state use dyn_internal_state,only: get_dyn_state use dyn_comp, only: dyn_import_t, dyn_export_t, fv_print_dpcoup_warn @@ -621,7 +621,7 @@ subroutine d_p_coupling(grid, phys_state, phys_tend, pbuf2d, dyn_out) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do call t_stopf('derived_fields') diff --git a/src/dynamics/mpas/dp_coupling.F90 b/src/dynamics/mpas/dp_coupling.F90 index c312f1e2f9..10d75b4b8c 100644 --- a/src/dynamics/mpas/dp_coupling.F90 +++ b/src/dynamics/mpas/dp_coupling.F90 @@ -413,7 +413,7 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d) ! MPAS prognostic fields. use geopotential, only: geopotential_t - use check_energy_cam, only: check_energy_cam_timestep_init + use check_energy, only: check_energy_timestep_init use shr_vmath_mod, only: shr_vmath_log use phys_control, only: waccmx_is use cam_thermo, only: cam_thermo_dry_air_update, cam_thermo_water_update @@ -564,7 +564,7 @@ subroutine derived_phys(phys_state, phys_tend, pbuf2d) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do diff --git a/src/dynamics/se/dp_coupling.F90 b/src/dynamics/se/dp_coupling.F90 index 9de31132a2..919b7f3510 100644 --- a/src/dynamics/se/dp_coupling.F90 +++ b/src/dynamics/se/dp_coupling.F90 @@ -546,7 +546,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d) use phys_control, only: waccmx_is use geopotential, only: geopotential_t use static_energy, only: update_dry_static_energy_run - use check_energy_cam,only: check_energy_cam_timestep_init + use check_energy, only: check_energy_timestep_init use hycoef, only: hyai, ps0 use shr_vmath_mod, only: shr_vmath_log use qneg_module, only: qneg3 @@ -707,7 +707,7 @@ subroutine derived_phys_dry(phys_state, phys_tend, pbuf2d) cpairv(1:ncol,:,lchnk), errflg, errmsg) ! Compute energy and water integrals of input state pbuf_chnk => pbuf_get_chunk(pbuf2d, lchnk) - call check_energy_cam_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) + call check_energy_timestep_init(phys_state(lchnk), phys_tend(lchnk), pbuf_chnk) end do ! lchnk diff --git a/src/physics/cam/cam_diagnostics.F90 b/src/physics/cam/cam_diagnostics.F90 index 00d6859a84..97dad2ba01 100644 --- a/src/physics/cam/cam_diagnostics.F90 +++ b/src/physics/cam/cam_diagnostics.F90 @@ -2019,7 +2019,7 @@ subroutine diag_phys_tend_writeout_dry(state, pbuf, tend, ztodt) ! !--------------------------------------------------------------- - use check_energy_cam,only: check_energy_get_integrals + use check_energy, only: check_energy_get_integrals use physconst, only: cpair ! Arguments diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 9f9faa10fe..f318cb51e1 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -21,37 +21,52 @@ module check_energy !--------------------------------------------------------------------------------- use shr_kind_mod, only: r8 => shr_kind_r8 - use ppgrid, only: pcols, pver, begchunk, endchunk + use ppgrid, only: pcols, pver use spmd_utils, only: masterproc - use physconst, only: gravit, rga, latvap, latice, cpair, rair + use physconst, only: rga use air_composition, only: cpairv, cp_or_cv_dycore use physics_types, only: physics_state use constituents, only: cnst_get_ind, pcnst, cnst_name, cnst_get_type_byind use cam_logfile, only: iulog - use cam_history, only: outfld implicit none private -! Public types: + ! Public types: public check_tracers_data -! Public methods - public :: check_energy_readnl ! read namelist values - public :: check_energy_register ! register fields in physics buffer - public :: check_energy_init ! initialization of module - public :: check_tracers_init ! initialize tracer integrals and cumulative boundary fluxes - public :: check_tracers_chng ! check changes in integrals against cumulative boundary fluxes + ! Public methods - not CCPP-ized + public :: check_tracers_init ! initialize tracer integrals and cumulative boundary fluxes + public :: check_tracers_chng ! check changes in integrals against cumulative boundary fluxes + public :: tot_energy_phys ! calculate and output total energy and axial angular momentum diagnostics - public :: tot_energy_phys ! calculate and output total energy and axial angular momentum diagnostics + ! These subroutines cannot be CCPP-ized + public :: check_energy_readnl ! read namelist values + public :: check_energy_register ! register fields in physics buffer + public :: check_energy_init ! initialization of module + public :: check_energy_gmean ! global means of physics input and output total energy + public :: check_energy_get_integrals ! get energy integrals computed in check_energy_gmean -! Private module data + ! Public methods - CAM interfaces to CCPP version: + public :: check_energy_cam_chng ! check changes in integrals against cumulative boundary fluxes + public :: check_energy_timestep_init ! timestep initialization of energy integrals and cumulative boundary fluxes + ! name is retained for FV3 compatibility + public :: check_energy_cam_fix ! add heating rate required for global mean total energy conservation + + ! Private module data logical :: print_energy_errors = .false. -! Physics buffer indices + ! used for check_energy_gmean + real(r8) :: teout_glob ! global mean energy of output state + real(r8) :: teinp_glob ! global mean energy of input state + real(r8) :: tedif_glob ! global mean energy difference + real(r8) :: psurf_glob ! global mean surface pressure + real(r8) :: ptopb_glob ! global mean top boundary pressure + real(r8) :: heat_glob ! global mean heating rate + ! Physics buffer indices integer, public :: teout_idx = 0 ! teout index in physics buffer integer, public :: dtcore_idx = 0 ! dtcore index in physics buffer integer, public :: dqcore_idx = 0 ! dqcore index in physics buffer @@ -542,5 +557,354 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) end subroutine tot_energy_phys + ! Compute global mean total energy of physics input and output states + ! computed consistently with dynamical core vertical coordinate + ! (under hydrostatic assumption) + ! + ! This subroutine cannot use the CCPP-ized equivalent because + ! it is dependent on chunks. + subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) + use physics_buffer, only: physics_buffer_desc, pbuf_get_field, pbuf_get_chunk + use physics_types, only: dyn_te_idx + use ppgrid, only: begchunk, endchunk + use spmd_utils, only: masterproc + use cam_logfile, only: iulog + use gmean_mod, only: gmean + use physconst, only: gravit + + type(physics_state), intent(in), dimension(begchunk:endchunk) :: state + type(physics_buffer_desc), pointer :: pbuf2d(:,:) + + real(r8), intent(in) :: dtime ! physics time step + integer , intent(in) :: nstep ! current timestep number + + integer :: ncol ! number of active columns + integer :: lchnk ! chunk index + + real(r8) :: te(pcols,begchunk:endchunk,4) + ! total energy of input/output states (copy) + real(r8) :: te_glob(4) ! global means of total energy + real(r8), pointer :: teout(:) + + ! Copy total energy out of input and output states + do lchnk = begchunk, endchunk + ncol = state(lchnk)%ncol + ! input energy using dynamical core energy formula + te(:ncol,lchnk,1) = state(lchnk)%te_ini(:ncol,dyn_te_idx) + ! output energy + call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk),teout_idx, teout) + + te(:ncol,lchnk,2) = teout(1:ncol) + ! surface pressure for heating rate + te(:ncol,lchnk,3) = state(lchnk)%pint(:ncol,pver+1) + ! model top pressure for heating rate (not constant for z-based vertical coordinate!) + te(:ncol,lchnk,4) = state(lchnk)%pint(:ncol,1) + end do + + ! Compute global means of input and output energies and of + ! surface pressure for heating rate (assume uniform ptop) + call gmean(te, te_glob, 4) + + if (begchunk .le. endchunk) then + teinp_glob = te_glob(1) + teout_glob = te_glob(2) + psurf_glob = te_glob(3) + ptopb_glob = te_glob(4) + + ! Global mean total energy difference + tedif_glob = teinp_glob - teout_glob + heat_glob = -tedif_glob/dtime * gravit / (psurf_glob - ptopb_glob) + if (masterproc) then + write(iulog,'(1x,a9,1x,i8,5(1x,e25.17))') "nstep, te", nstep, teinp_glob, teout_glob, & + heat_glob, psurf_glob, ptopb_glob + end if + else + heat_glob = 0._r8 + end if ! (begchunk .le. endchunk) + + end subroutine check_energy_gmean + + ! Return energy integrals (module variables) + subroutine check_energy_get_integrals(tedif_glob_out, heat_glob_out) + real(r8), intent(out), optional :: tedif_glob_out + real(r8), intent(out), optional :: heat_glob_out + + if ( present(tedif_glob_out) ) then + tedif_glob_out = tedif_glob + endif + + if ( present(heat_glob_out) ) then + heat_glob_out = heat_glob + endif + end subroutine check_energy_get_integrals + + ! Compute initial values of energy and water integrals, + ! zero cumulative tendencies + subroutine check_energy_timestep_init(state, tend, pbuf, col_type) + use physics_buffer, only: physics_buffer_desc, pbuf_set_field + use cam_abortutils, only: endrun + use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure + use physics_types, only: physics_tend + use physics_types, only: phys_te_idx, dyn_te_idx + use time_manager, only: is_first_step + use physconst, only: cpair, rair + use air_composition, only: cpairv, cp_or_cv_dycore + + ! CCPP-ized subroutine + use check_energy_chng, only: check_energy_chng_timestep_init + + type(physics_state), intent(inout) :: state + type(physics_tend ), intent(inout) :: tend + type(physics_buffer_desc), pointer :: pbuf(:) + integer, optional :: col_type ! Flag indicating whether using grid or subcolumns + + real(r8) :: local_cp_phys(state%psetcols,pver) + real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) + real(r8) :: teout(state%ncol) ! dummy teout argument + integer :: lchnk ! chunk identifier + integer :: ncol ! number of atmospheric columns + character(len=512) :: errmsg + integer :: errflg + + lchnk = state%lchnk + ncol = state%ncol + + ! The code below is split into not-subcolumns and subcolumns code, as there is different handling of the + ! cp passed into the hydrostatic energy call. CAM-SIMA does not support subcolumns, so we keep this special + ! handling inside this shim module. (hplin, 9/9/24) + if(state%psetcols == pcols) then + ! No subcolumns + local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) + local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) + else if (state%psetcols > pcols) then + ! Subcolumns code + ! Subcolumns specific error handling + if(.not. all(cpairv(:,:,lchnk) == cpair)) then + call endrun('check_energy_timestep_init: cpairv is not allowed to vary when subcolumns are turned on') + endif + + local_cp_phys(1:ncol,:) = cpair + + if (vc_dycore == vc_height) then + ! MPAS specific hydrostatic energy computation (internal energy) + local_cp_or_cv_dycore(:ncol,:) = cpair-rair + else if(vc_dycore == vc_dry_pressure) then + ! SE specific hydrostatic energy (enthalpy) + local_cp_or_cv_dycore(:ncol,:) = cpair + else + ! cp_or_cv is not used in the underlying subroutine, zero it out to be sure + local_cp_or_cv_dycore(:ncol,:) = 0.0_r8 + endif + end if + + ! Call CCPP-ized underlying subroutine. + call check_energy_chng_timestep_init( & + ncol = ncol, & + pver = pver, & + pcnst = pcnst, & + is_first_timestep = is_first_step(), & + q = state%q(1:ncol,1:pver,1:pcnst), & + pdel = state%pdel(1:ncol,1:pver), & + u = state%u(1:ncol,1:pver), & + v = state%v(1:ncol,1:pver), & + T = state%T(1:ncol,1:pver), & + pintdry = state%pintdry(1:ncol,1:pver), & + phis = state%phis(1:ncol), & + zm = state%zm(1:ncol,:), & + cp_phys = local_cp_phys(1:ncol,:), & + cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & + te_ini_phys = state%te_ini(1:ncol,phys_te_idx), & + te_ini_dyn = state%te_ini(1:ncol,dyn_te_idx), & + tw_ini = state%tw_ini(1:ncol), & + te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & + te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & + tw_cur = state%tw_cur(1:ncol), & + tend_te_tnd = tend%te_tnd(1:ncol), & + tend_tw_tnd = tend%tw_tnd(1:ncol), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & + count = state%count, & + teout = teout(1:ncol), & ! dummy argument - actual teout written to pbuf directly below + vc_physics = vc_physics, & + vc_dycore = vc_dycore, & + errmsg = errmsg, & + errflg = errflg & + ) + + ! initialize physics buffer + if (is_first_step()) then + call pbuf_set_field(pbuf, teout_idx, state%te_ini(:,dyn_te_idx), col_type=col_type) + end if + + end subroutine check_energy_timestep_init + + ! Check that the energy and water change matches the boundary fluxes + subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & + flx_vap, flx_cnd, flx_ice, flx_sen) + use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure + use cam_abortutils, only: endrun + use physics_types, only: phys_te_idx, dyn_te_idx + use physics_types, only: physics_tend + use physconst, only: cpair, rair, latice, latvap + use air_composition, only: cpairv, cp_or_cv_dycore + + ! CCPP-ized subroutine + use check_energy_chng, only: check_energy_chng_run + + type(physics_state), intent(inout) :: state + type(physics_tend ), intent(inout) :: tend + character*(*),intent(in) :: name ! parameterization name for fluxes + integer , intent(in) :: nstep ! current timestep number + real(r8), intent(in) :: ztodt ! 2 delta t (model time increment) + real(r8), intent(in) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) + real(r8), intent(in) :: flx_cnd(:) ! (pcols) -boundary flux of liquid+ice (m/s) (precip?) + real(r8), intent(in) :: flx_ice(:) ! (pcols) -boundary flux of ice (m/s) (snow?) + real(r8), intent(in) :: flx_sen(:) ! (pcols) -boundary flux of sensible heat (w/m2) + integer :: lchnk ! chunk identifier + integer :: ncol ! number of atmospheric columns + real(r8) :: local_cp_phys(state%psetcols,pver) + real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) + real(r8) :: scaling_dycore(state%ncol,pver) + character(len=512) :: errmsg + integer :: errflg + + lchnk = state%lchnk + ncol = state%ncol + + if(state%psetcols == pcols) then + ! No subcolumns + local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) + + ! Only if vertical coordinate is vc_height or vc_dry_pressure, cp_or_cv_dycore + ! is nonzero. + if(vc_dycore == vc_height .or. vc_dycore == vc_dry_pressure) then + local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) + + scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + endif + elseif(state%psetcols > pcols) then + ! Subcolumns + if(.not. all(cpairv(:,:,:) == cpair)) then + call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on') + endif + + local_cp_phys(:,:) = cpair + + ! Note: cp_or_cv set above for pressure coordinate + if (vc_dycore == vc_height) then + ! compute cv if vertical coordinate is height: cv = cp - R + local_cp_or_cv_dycore(:ncol,:) = cpair-rair + scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + else if (vc_dycore == vc_dry_pressure) then + ! SE specific hydrostatic energy + local_cp_or_cv_dycore(:ncol,:) = cpair + scaling_dycore(:ncol,:) = 1.0_r8 + else + ! Moist pressure... use phys formula + local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:) + scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + end if + endif + + ! Call CCPP-ized underlying subroutine. + call check_energy_chng_run( & + ncol = ncol, & + pver = pver, & + pcnst = pcnst, & + q = state%q(1:ncol,1:pver,1:pcnst), & + pdel = state%pdel(1:ncol,1:pver), & + u = state%u(1:ncol,1:pver), & + v = state%v(1:ncol,1:pver), & + T = state%T(1:ncol,1:pver), & + pintdry = state%pintdry(1:ncol,1:pver), & + phis = state%phis(1:ncol), & + zm = state%zm(1:ncol,:), & + cp_phys = local_cp_phys(1:ncol,:), & + cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & + scaling_dycore = scaling_dycore(1:ncol,:), & + te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & + te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & + tw_cur = state%tw_cur(1:ncol), & + tend_te_tnd = tend%te_tnd(1:ncol), & + tend_tw_tnd = tend%tw_tnd(1:ncol), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & + count = state%count, & + ztodt = ztodt, & + latice = latice, & + latvap = latvap, & + vc_physics = vc_physics, & + vc_dycore = vc_dycore, & + name = name, & + flx_vap = flx_vap, & + flx_cnd = flx_cnd, & + flx_ice = flx_ice, & + flx_sen = flx_sen, & + errmsg = errmsg, & + errflg = errflg & + ) + + end subroutine check_energy_cam_chng + + ! Add heating rate required for global mean total energy conservation + subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) + use physics_types, only: physics_ptend, physics_ptend_init + use physconst, only: rga + + ! SCAM support + use scamMod, only: single_column, use_camiop, heat_glob_scm + use cam_history, only: write_camiop + use cam_history, only: outfld + + ! CCPP-ized subroutine + use check_energy_fix, only: check_energy_fix_run + + type(physics_state), intent(in) :: state + type(physics_ptend), intent(out) :: ptend + + integer , intent(in) :: nstep ! time step number + real(r8), intent(out) :: eshflx(pcols) ! effective sensible heat flux + + integer :: ncol ! number of atmospheric columns in chunk + integer :: lchnk ! chunk number + real(r8) :: heat_out(pcols) + + lchnk = state%lchnk + ncol = state%ncol + + call physics_ptend_init(ptend, state%psetcols, 'chkenergyfix', ls=.true.) + +#if ( defined OFFLINE_DYN ) + ! disable the energy fix for offline driver + heat_glob = 0._r8 +#endif + + ! Special handling of energy fix for SCAM - supplied via CAMIOP - zero's for normal IOPs + if (single_column) then + if (use_camiop) then + heat_glob = heat_glob_scm(1) + else + heat_glob = 0._r8 + endif + endif + + if (nstep > 0 .and. write_camiop) then + heat_out(:ncol) = heat_glob + call outfld('heat_glob', heat_out(:ncol), pcols, lchnk) + endif + + ! Call the CCPP-ized subroutine (for non-SCAM) + ! to compute the effective sensible heat flux and save to ptend%s + call check_energy_fix_run( & + ncol = ncol, & + pver = pver, & + pint = state%pint(:ncol,:), & + rga = rga, & + heat_glob = heat_glob, & + ptend_s = ptend%s(:ncol,:), & + eshflx = eshflx(:ncol) & + ) + + end subroutine check_energy_cam_fix end module check_energy diff --git a/src/physics/cam/check_energy_cam.F90 b/src/physics/cam/check_energy_cam.F90 deleted file mode 100644 index e1f143c0c2..0000000000 --- a/src/physics/cam/check_energy_cam.F90 +++ /dev/null @@ -1,380 +0,0 @@ -! CAM interface for CCPP-ized check_energy routines in CAM -module check_energy_cam - use shr_kind_mod, only: r8 => shr_kind_r8 - use ppgrid, only: pcols, pver - use constituents, only: pcnst - use physics_types, only: physics_state, physics_tend - - implicit none - private - - public :: check_energy_cam_chng ! check changes in integrals against cumulative boundary fluxes - public :: check_energy_cam_timestep_init ! timestep initialization of energy integrals and cumulative boundary fluxes - - public :: check_energy_cam_fix ! add heating rate required for global mean total energy conservation - - ! These subroutines cannot be CCPP-ized and replicated from check_energy - public :: check_energy_gmean ! global means of physics input and output total energy - public :: check_energy_get_integrals ! get energy integrals computed in check_energy_gmean - - ! Module variables used for check_energy_gmean - real(r8) :: teout_glob ! global mean energy of output state - real(r8) :: teinp_glob ! global mean energy of input state - real(r8) :: tedif_glob ! global mean energy difference - real(r8) :: psurf_glob ! global mean surface pressure - real(r8) :: ptopb_glob ! global mean top boundary pressure - real(r8) :: heat_glob ! global mean heating rate - -contains - ! Compute initial values of energy and water integrals, - ! zero cumulative tendencies - subroutine check_energy_cam_timestep_init(state, tend, pbuf, col_type) - use physics_buffer, only: physics_buffer_desc, pbuf_set_field - use cam_abortutils, only: endrun - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure - use physics_types, only: phys_te_idx, dyn_te_idx - use time_manager, only: is_first_step - use physconst, only: cpair, rair - use air_composition, only: cpairv, cp_or_cv_dycore - - ! To remove, pbuf indices in check_energy - use check_energy, only: teout_idx - - ! CCPP-ized subroutine - use check_energy_chng, only: check_energy_chng_timestep_init - - type(physics_state), intent(inout) :: state - type(physics_tend ), intent(inout) :: tend - type(physics_buffer_desc), pointer :: pbuf(:) - integer, optional :: col_type ! Flag indicating whether using grid or subcolumns - - real(r8) :: local_cp_phys(state%psetcols,pver) - real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) - real(r8) :: teout(state%ncol) ! dummy teout argument - integer :: lchnk ! chunk identifier - integer :: ncol ! number of atmospheric columns - character(len=512) :: errmsg - integer :: errflg - - lchnk = state%lchnk - ncol = state%ncol - - ! The code below is split into not-subcolumns and subcolumns code, as there is different handling of the - ! cp passed into the hydrostatic energy call. CAM-SIMA does not support subcolumns, so we keep this special - ! handling inside this shim module. (hplin, 9/9/24) - if(state%psetcols == pcols) then - ! No subcolumns - local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) - local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - else if (state%psetcols > pcols) then - ! Subcolumns code - ! Subcolumns specific error handling - if(.not. all(cpairv(:,:,lchnk) == cpair)) then - call endrun('check_energy_timestep_init: cpairv is not allowed to vary when subcolumns are turned on') - endif - - local_cp_phys(1:ncol,:) = cpair - - if (vc_dycore == vc_height) then - ! MPAS specific hydrostatic energy computation (internal energy) - local_cp_or_cv_dycore(:ncol,:) = cpair-rair - else if(vc_dycore == vc_dry_pressure) then - ! SE specific hydrostatic energy (enthalpy) - local_cp_or_cv_dycore(:ncol,:) = cpair - else - ! cp_or_cv is not used in the underlying subroutine, zero it out to be sure - local_cp_or_cv_dycore(:ncol,:) = 0.0_r8 - endif - end if - - ! Call CCPP-ized underlying subroutine. - call check_energy_chng_timestep_init( & - ncol = ncol, & - pver = pver, & - pcnst = pcnst, & - is_first_timestep = is_first_step(), & - q = state%q(1:ncol,1:pver,1:pcnst), & - pdel = state%pdel(1:ncol,1:pver), & - u = state%u(1:ncol,1:pver), & - v = state%v(1:ncol,1:pver), & - T = state%T(1:ncol,1:pver), & - pintdry = state%pintdry(1:ncol,1:pver), & - phis = state%phis(1:ncol), & - zm = state%zm(1:ncol,:), & - cp_phys = local_cp_phys(1:ncol,:), & - cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & - te_ini_phys = state%te_ini(1:ncol,phys_te_idx), & - te_ini_dyn = state%te_ini(1:ncol,dyn_te_idx), & - tw_ini = state%tw_ini(1:ncol), & - te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & - te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & - tw_cur = state%tw_cur(1:ncol), & - tend_te_tnd = tend%te_tnd(1:ncol), & - tend_tw_tnd = tend%tw_tnd(1:ncol), & - temp_ini = state%temp_ini(:ncol,:), & - z_ini = state%z_ini(:ncol,:), & - count = state%count, & - teout = teout(1:ncol), & ! dummy argument - actual teout written to pbuf directly below - vc_physics = vc_physics, & - vc_dycore = vc_dycore, & - errmsg = errmsg, & - errflg = errflg & - ) - - ! initialize physics buffer - if (is_first_step()) then - call pbuf_set_field(pbuf, teout_idx, state%te_ini(:,dyn_te_idx), col_type=col_type) - end if - - end subroutine check_energy_cam_timestep_init - - ! Check that the energy and water change matches the boundary fluxes - subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & - flx_vap, flx_cnd, flx_ice, flx_sen) - use cam_thermo, only: get_hydrostatic_energy - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure - use cam_abortutils, only: endrun - use physics_types, only: phys_te_idx, dyn_te_idx - use physconst, only: cpair, rair, latice, latvap - use air_composition, only: cpairv, cp_or_cv_dycore - - ! CCPP-ized subroutine - use check_energy_chng, only: check_energy_chng_run - - type(physics_state), intent(inout) :: state - type(physics_tend ), intent(inout) :: tend - character*(*),intent(in) :: name ! parameterization name for fluxes - integer , intent(in) :: nstep ! current timestep number - real(r8), intent(in) :: ztodt ! 2 delta t (model time increment) - real(r8), intent(in) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) - real(r8), intent(in) :: flx_cnd(:) ! (pcols) -boundary flux of liquid+ice (m/s) (precip?) - real(r8), intent(in) :: flx_ice(:) ! (pcols) -boundary flux of ice (m/s) (snow?) - real(r8), intent(in) :: flx_sen(:) ! (pcols) -boundary flux of sensible heat (w/m2) - - integer :: lchnk ! chunk identifier - integer :: ncol ! number of atmospheric columns - integer :: i ! column index - real(r8) :: local_cp_phys(state%psetcols,pver) - real(r8) :: local_cp_or_cv_dycore(state%psetcols,pver) - real(r8) :: scaling_dycore(state%ncol,pver) - character(len=512) :: errmsg - integer :: errflg - - lchnk = state%lchnk - ncol = state%ncol - - if(state%psetcols == pcols) then - ! No subcolumns - local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) - local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) - - scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling - elseif(state%psetcols > pcols) then - ! Subcolumns - if(.not. all(cpairv(:,:,:) == cpair)) then - call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on') - endif - - local_cp_phys(:,:) = cpair - - ! Note: cp_or_cv set above for pressure coordinate - if (vc_dycore == vc_height) then - ! compute cv if vertical coordinate is height: cv = cp - R - local_cp_or_cv_dycore(:ncol,:) = cpair-rair - scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling - else if (vc_dycore == vc_dry_pressure) then - ! SE specific hydrostatic energy - local_cp_or_cv_dycore(:ncol,:) = cpair - scaling_dycore(:ncol,:) = 1.0_r8 - else - ! Moist pressure... use phys formula - local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:) - scaling_dycore(:ncol,:) = cpairv(:,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling - end if - endif - - ! Call CCPP-ized underlying subroutine. - call check_energy_chng_run( & - ncol = ncol, & - pver = pver, & - pcnst = pcnst, & - q = state%q(1:ncol,1:pver,1:pcnst), & - pdel = state%pdel(1:ncol,1:pver), & - u = state%u(1:ncol,1:pver), & - v = state%v(1:ncol,1:pver), & - T = state%T(1:ncol,1:pver), & - pintdry = state%pintdry(1:ncol,1:pver), & - phis = state%phis(1:ncol), & - zm = state%zm(1:ncol,:), & - cp_phys = local_cp_phys(1:ncol,:), & - cp_or_cv_dycore = local_cp_or_cv_dycore(1:ncol,:), & - scaling_dycore = scaling_dycore(1:ncol,:), & - te_cur_phys = state%te_cur(1:ncol,phys_te_idx), & - te_cur_dyn = state%te_cur(1:ncol,dyn_te_idx), & - tw_cur = state%tw_cur(1:ncol), & - tend_te_tnd = tend%te_tnd(1:ncol), & - tend_tw_tnd = tend%tw_tnd(1:ncol), & - temp_ini = state%temp_ini(:ncol,:), & - z_ini = state%z_ini(:ncol,:), & - count = state%count, & - ztodt = ztodt, & - latice = latice, & - latvap = latvap, & - vc_physics = vc_physics, & - vc_dycore = vc_dycore, & - name = name, & - flx_vap = flx_vap, & - flx_cnd = flx_cnd, & - flx_ice = flx_ice, & - flx_sen = flx_sen, & - errmsg = errmsg, & - errflg = errflg & - ) - - end subroutine check_energy_cam_chng - - ! Add heating rate required for global mean total energy conservation - subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) - use physics_types, only: physics_ptend, physics_ptend_init - use physconst, only: rga - - ! SCAM support - use scamMod, only: single_column, use_camiop, heat_glob_scm - use cam_history, only: write_camiop - use cam_history, only: outfld - - ! CCPP-ized subroutine - use check_energy_fix, only: check_energy_fix_run - - type(physics_state), intent(in) :: state - type(physics_ptend), intent(out) :: ptend - - integer , intent(in) :: nstep ! time step number - real(r8), intent(out) :: eshflx(pcols) ! effective sensible heat flux - - integer :: ncol ! number of atmospheric columns in chunk - integer :: lchnk ! chunk number - real(r8) :: heat_out(pcols) - - lchnk = state%lchnk - ncol = state%ncol - - call physics_ptend_init(ptend, state%psetcols, 'chkenergyfix', ls=.true.) - -#if ( defined OFFLINE_DYN ) - ! disable the energy fix for offline driver - heat_glob = 0._r8 -#endif - - ! Special handling of energy fix for SCAM - supplied via CAMIOP - zero's for normal IOPs - if (single_column) then - if (use_camiop) then - heat_glob = heat_glob_scm(1) - else - heat_glob = 0._r8 - endif - endif - - if (nstep > 0 .and. write_camiop) then - heat_out(:ncol) = heat_glob - call outfld('heat_glob', heat_out(:ncol), pcols, lchnk) - endif - - ! Call the CCPP-ized subroutine (for non-SCAM) - ! to compute the effective sensible heat flux and save to ptend%s - call check_energy_fix_run( & - ncol = ncol, & - pver = pver, & - pint = state%pint(:ncol,:), & - rga = rga, & - heat_glob = heat_glob, & - ptend_s = ptend%s(:ncol,:), & - eshflx = eshflx(:ncol) & - ) - - end subroutine check_energy_cam_fix - - ! Compute global mean total energy of physics input and output states - ! computed consistently with dynamical core vertical coordinate - ! (under hydrostatic assumption) - ! - ! This subroutine cannot use the CCPP-ized equivalent because - ! it is dependent on chunks. - subroutine check_energy_gmean(state, pbuf2d, dtime, nstep) - use physics_buffer, only: physics_buffer_desc, pbuf_get_field, pbuf_get_chunk - use physics_types, only: dyn_te_idx - use ppgrid, only: begchunk, endchunk - use spmd_utils, only: masterproc - use cam_logfile, only: iulog - use gmean_mod, only: gmean - use physconst, only: gravit - - ! To remove, pbuf indices in check_energy - use check_energy, only: teout_idx - - type(physics_state), intent(in), dimension(begchunk:endchunk) :: state - type(physics_buffer_desc), pointer :: pbuf2d(:,:) - - real(r8), intent(in) :: dtime ! physics time step - integer , intent(in) :: nstep ! current timestep number - - integer :: ncol ! number of active columns - integer :: lchnk ! chunk index - - real(r8) :: te(pcols,begchunk:endchunk,4) - ! total energy of input/output states (copy) - real(r8) :: te_glob(4) ! global means of total energy - real(r8), pointer :: teout(:) - - ! Copy total energy out of input and output states - do lchnk = begchunk, endchunk - ncol = state(lchnk)%ncol - ! input energy using dynamical core energy formula - te(:ncol,lchnk,1) = state(lchnk)%te_ini(:ncol,dyn_te_idx) - ! output energy - call pbuf_get_field(pbuf_get_chunk(pbuf2d,lchnk),teout_idx, teout) - - te(:ncol,lchnk,2) = teout(1:ncol) - ! surface pressure for heating rate - te(:ncol,lchnk,3) = state(lchnk)%pint(:ncol,pver+1) - ! model top pressure for heating rate (not constant for z-based vertical coordinate!) - te(:ncol,lchnk,4) = state(lchnk)%pint(:ncol,1) - end do - - ! Compute global means of input and output energies and of - ! surface pressure for heating rate (assume uniform ptop) - call gmean(te, te_glob, 4) - - if (begchunk .le. endchunk) then - teinp_glob = te_glob(1) - teout_glob = te_glob(2) - psurf_glob = te_glob(3) - ptopb_glob = te_glob(4) - - ! Global mean total energy difference - tedif_glob = teinp_glob - teout_glob - heat_glob = -tedif_glob/dtime * gravit / (psurf_glob - ptopb_glob) - if (masterproc) then - write(iulog,'(1x,a9,1x,i8,5(1x,e25.17))') "nstep, te", nstep, teinp_glob, teout_glob, & - heat_glob, psurf_glob, ptopb_glob - end if - else - heat_glob = 0._r8 - end if ! (begchunk .le. endchunk) - - end subroutine check_energy_gmean - - ! Return energy integrals (module variables) - subroutine check_energy_get_integrals(tedif_glob_out, heat_glob_out) - real(r8), intent(out), optional :: tedif_glob_out - real(r8), intent(out), optional :: heat_glob_out - - if ( present(tedif_glob_out) ) then - tedif_glob_out = tedif_glob - endif - - if ( present(heat_glob_out) ) then - heat_glob_out = heat_glob - endif - end subroutine check_energy_get_integrals -end module check_energy_cam diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index 25f46c3a45..1d431b2dbb 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -1065,7 +1065,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics,only: diag_allocate, diag_physvar_ic - use check_energy_cam, only: check_energy_gmean + use check_energy, only: check_energy_gmean use phys_control, only: phys_getopts use spcam_drivers, only: tphysbc_spcam use spmd_utils, only: mpicom @@ -1392,7 +1392,7 @@ subroutine tphysac (ztodt, cam_in, & use carma_flags_mod, only: carma_do_aerosol, carma_do_emission use check_energy, only: tot_energy_phys use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng - use check_energy_cam, only: check_energy_cam_chng + use check_energy, only: check_energy_cam_chng use time_manager, only: get_nstep use cam_abortutils, only: endrun use dycore, only: dycore_is @@ -2045,8 +2045,8 @@ subroutine tphysbc (ztodt, state, & use convect_deep, only: convect_deep_tend, convect_deep_tend_2, deep_scheme_does_scav_trans use time_manager, only: is_first_step, get_nstep use convect_shallow, only: convect_shallow_tend - use check_energy_cam,only: check_energy_cam_timestep_init, check_energy_cam_chng - use check_energy_cam,only: check_energy_cam_fix + use check_energy, only: check_energy_timestep_init, check_energy_cam_chng + use check_energy, only: check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use dycore, only: dycore_is @@ -2257,7 +2257,9 @@ subroutine tphysbc (ztodt, state, & call tot_energy_phys(state, 'dyBF',vc=vc_dycore) if (.not.dycore_is('EUL')) then call check_energy_cam_fix(state, ptend, nstep, flx_heat) + call physics_update(state, ptend, ztodt, tend) + call check_energy_cam_chng(state, tend, "chkengyfix", nstep, ztodt, zero, zero, zero, flx_heat) call outfld( 'EFIX', flx_heat , pcols, lchnk ) end if @@ -2632,7 +2634,7 @@ subroutine tphysbc (ztodt, state, & call subcol_gen(state, tend, state_sc, tend_sc, pbuf) !Initialize check energy for subcolumns - call check_energy_cam_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) + call check_energy_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) end if if (trim(cam_take_snapshot_before) == "microp_section") then diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index 1ce28d3a93..ead4935939 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -1056,7 +1056,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics,only: diag_allocate, diag_physvar_ic - use check_energy_cam, only: check_energy_gmean + use check_energy, only: check_energy_gmean use spmd_utils, only: mpicom use physics_buffer, only: physics_buffer_desc, pbuf_get_chunk, pbuf_allocate use cam_history, only: outfld, write_camiop @@ -1366,7 +1366,7 @@ subroutine tphysac (ztodt, cam_in, & use aoa_tracers, only: aoa_tracers_timestep_tend use physconst, only: rhoh2o use aero_model, only: aero_model_drydep - use check_energy_cam, only: check_energy_cam_timestep_init, check_energy_cam_chng + use check_energy, only: check_energy_timestep_init, check_energy_cam_chng use check_energy, only: tot_energy_phys use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use time_manager, only: get_nstep @@ -1775,7 +1775,7 @@ subroutine tphysac (ztodt, cam_in, & call subcol_gen(state, tend, state_sc, tend_sc, pbuf) !Initialize check energy for subcolumns - call check_energy_cam_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) + call check_energy_timestep_init(state_sc, tend_sc, pbuf, col_type_subcol) end if if (trim(cam_take_snapshot_before) == "microp_section") then @@ -2517,7 +2517,7 @@ subroutine tphysbc (ztodt, state, & use convect_deep, only: convect_deep_tend use time_manager, only: is_first_step, get_nstep use convect_diagnostics,only: convect_diagnostics_calc - use check_energy_cam,only: check_energy_cam_chng, check_energy_cam_fix + use check_energy, only: check_energy_cam_chng, check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init use check_energy, only: tot_energy_phys use dycore, only: dycore_is diff --git a/src/physics/simple/physpkg.F90 b/src/physics/simple/physpkg.F90 index eaea0ff1dd..c236f7f021 100644 --- a/src/physics/simple/physpkg.F90 +++ b/src/physics/simple/physpkg.F90 @@ -305,7 +305,7 @@ subroutine phys_run1(phys_state, ztodt, phys_tend, pbuf2d, cam_in, cam_out) !----------------------------------------------------------------------- use time_manager, only: get_nstep use cam_diagnostics, only: diag_allocate, diag_physvar_ic - use check_energy_cam, only: check_energy_gmean + use check_energy, only: check_energy_gmean use physics_buffer, only: physics_buffer_desc, pbuf_get_chunk, pbuf_allocate ! @@ -503,7 +503,7 @@ subroutine tphysac (ztodt, cam_in, cam_out, state, tend, pbuf) use air_composition, only: cpairv, cp_or_cv_dycore use time_manager, only: get_nstep use nudging, only: Nudge_Model, Nudge_ON, nudging_timestep_tend - use check_energy_cam,only: check_energy_cam_chng + use check_energy, only: check_energy_cam_chng ! Arguments ! @@ -728,8 +728,8 @@ subroutine tphysbc (ztodt, state, tend, pbuf, cam_out, cam_in ) use cam_diagnostics, only: diag_conv_tend_ini, diag_conv, diag_export use cam_history, only: outfld use time_manager, only: get_nstep - use check_energy_cam, only: check_energy_cam_chng, check_energy_cam_fix - use check_energy_cam, only: check_energy_cam_timestep_init + use check_energy, only: check_energy_cam_chng, check_energy_cam_fix + use check_energy, only: check_energy_timestep_init use check_energy, only: check_tracers_data, check_tracers_init, check_tracers_chng use check_energy, only: tot_energy_phys use chemistry, only: chem_is_active, chem_timestep_tend diff --git a/src/physics/spcam/crm_physics.F90 b/src/physics/spcam/crm_physics.F90 index 735d6c3630..8812d2be72 100644 --- a/src/physics/spcam/crm_physics.F90 +++ b/src/physics/spcam/crm_physics.F90 @@ -750,7 +750,7 @@ subroutine crm_physics_tend(ztodt, state, tend, ptend, pbuf, cam_in) use crmx_crm_module, only: crm use crmx_microphysics, only: nmicro_fields use physconst, only: latvap - use check_energy_cam, only: check_energy_cam_chng + use check_energy, only: check_energy_cam_chng use phys_grid, only: get_rlat_all_p, get_rlon_all_p, get_lon_all_p, get_lat_all_p use modal_aero_calcsize, only: modal_aero_calcsize_sub use micro_pumas_utils, only: size_dist_param_liq, mg_liq_props, mincld, qsmall diff --git a/src/physics/spcam/spcam_drivers.F90 b/src/physics/spcam/spcam_drivers.F90 index cd7d3f6370..b9f7a596cc 100644 --- a/src/physics/spcam/spcam_drivers.F90 +++ b/src/physics/spcam/spcam_drivers.F90 @@ -300,7 +300,7 @@ subroutine tphysbc_spcam (ztodt, state, & use cam_history, only: outfld use constituents, only: pcnst, qmin, cnst_get_ind use time_manager, only: get_nstep - use check_energy_cam,only: check_energy_cam_chng, check_energy_cam_fix + use check_energy, only: check_energy_cam_chng, check_energy_cam_fix use check_energy, only: check_tracers_data, check_tracers_init use dycore, only: dycore_is use radiation, only: radiation_tend From 4b6de4306cce342c6eab46333004e63d4afcb989 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 15 Oct 2024 12:47:16 -0400 Subject: [PATCH 32/82] Fix subcol test with FV dycore --- src/physics/cam/check_energy.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index f318cb51e1..998fbb9e18 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -801,9 +801,9 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & local_cp_or_cv_dycore(:ncol,:) = cpair scaling_dycore(:ncol,:) = 1.0_r8 else - ! Moist pressure... use phys formula - local_cp_or_cv_dycore(:ncol,:) = local_cp_phys(:ncol,:) - scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling + ! Moist pressure... use phys formula, cp_or_cv_dycore is unused. Reset for safety + local_cp_or_cv_dycore(:ncol,:) = 0.0_r8 + scaling_dycore(:ncol,:) = 0.0_r8 end if endif From cfd28249446085affc8674beccfe642a771559a7 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Fri, 25 Oct 2024 12:23:38 -0600 Subject: [PATCH 33/82] Small updates to comments and indenting --- src/physics/cam/clubb_intr.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index aedfa22fbd..7beb445b37 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2743,7 +2743,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call pbuf_get_field(pbuf, naai_idx, naai) end if - ! Initialize physics tendency arrays, copy the state to state1 array to use in this routine + ! Initialize physics tendency arrays call physics_ptend_init(ptend_all, state%psetcols, 'clubb') ! Copy the state to state1 array to use in this routine @@ -2845,7 +2845,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & apply_const = 0._r8 ! Never want this if CLUBB's moments are not advected endif - ! Initialize the apply_const variable (note special logic is due to eularian backstepping) + ! Initialize the apply_const variable (note special logic is due to eulerian backstepping) if (clubb_do_adv .and. (is_first_step() .or. all(wpthlp(1:ncol,1:pver) == 0._r8))) then apply_const = 0._r8 ! On first time through do not remove constant ! from moments since it has not been added yet @@ -4111,7 +4111,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & do i=1, ncol clubbtop(i) = top_lev do while ((rtp2(i,clubbtop(i)) <= 1.e-15_r8 .and. rcm(i,clubbtop(i)) == 0._r8) .and. clubbtop(i) < pver) - clubbtop(i) = clubbtop(i) + 1 + clubbtop(i) = clubbtop(i) + 1 end do end do From d924e4e434929aa47a89d875e80b7974ce1cdee5 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Wed, 23 Oct 2024 13:19:24 -0400 Subject: [PATCH 34/82] Update atmos_phys; move energy formula to cam_thermo_formula; write cp_or_cv_dycore to snapshot --- .gitmodules | 2 +- src/atmos_phys | 2 +- src/control/cam_snapshot_common.F90 | 9 ++++- src/physics/cam/check_energy.F90 | 56 +++++++++++++++-------------- src/utils/cam_thermo_formula.F90 | 14 ++++++++ 5 files changed, 53 insertions(+), 30 deletions(-) create mode 100644 src/utils/cam_thermo_formula.F90 diff --git a/.gitmodules b/.gitmodules index e295d8fec1..0edbb78972 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,7 +36,7 @@ [submodule "atmos_phys"] path = src/atmos_phys url = https://github.com/jimmielin/atmospheric_physics - fxtag = df80b9c1 + fxtag = 952ebdd fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index df80b9c1e7..952ebddfa2 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit df80b9c1e73064f9a0196282a92b66a2041f6a57 +Subproject commit 952ebddfa22dd796578fba8d73db6128c8db88c1 diff --git a/src/control/cam_snapshot_common.F90 b/src/control/cam_snapshot_common.F90 index ffae561370..fa558b3ad2 100644 --- a/src/control/cam_snapshot_common.F90 +++ b/src/control/cam_snapshot_common.F90 @@ -81,7 +81,7 @@ module cam_snapshot_common integer :: cam_snapshot_before_num, cam_snapshot_after_num ! Note the maximum number of variables for each type -type (snapshot_type) :: state_snapshot(29) +type (snapshot_type) :: state_snapshot(30) type (snapshot_type) :: cnst_snapshot(pcnst) type (snapshot_type) :: tend_snapshot(6) type (snapshot_type) :: cam_in_snapshot(30) @@ -283,6 +283,9 @@ subroutine cam_state_snapshot_init(cam_snapshot_before_num_in, cam_snapshot_afte call snapshot_addfld( nstate_var, state_snapshot, cam_snapshot_before_num, cam_snapshot_after_num, & 'state%te_cur_dyn', 'state_te_cur_dyn', 'unset', horiz_only) + call snapshot_addfld( nstate_var, state_snapshot, cam_snapshot_before_num, cam_snapshot_after_num, & + 'air_composition_cp_or_cv_dycore', 'cp_or_cv_dycore', 'J kg-1 K-1', 'lev') + end subroutine cam_state_snapshot_init subroutine cam_cnst_snapshot_init(cam_snapshot_before_num, cam_snapshot_after_num) @@ -741,6 +744,7 @@ end subroutine snapshot_addfld subroutine state_snapshot_all_outfld(lchnk, file_num, state) use physics_types, only: phys_te_idx, dyn_te_idx + use air_composition, only: cp_or_cv_dycore integer, intent(in) :: lchnk integer, intent(in) :: file_num @@ -843,6 +847,9 @@ subroutine state_snapshot_all_outfld(lchnk, file_num, state) case ('state%te_cur_dyn') call outfld(state_snapshot(i)%standard_name, state%te_cur(:, dyn_te_idx), pcols, lchnk) + case ('air_composition_cp_or_cv_dycore') + call outfld(state_snapshot(i)%standard_name, cp_or_cv_dycore(:,:,lchnk), pcols, lchnk) + case default call endrun('ERROR in state_snapshot_all_outfld: no match found for '//trim(state_snapshot(i)%ddt_string)) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 998fbb9e18..774764c563 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -415,7 +415,8 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) use cam_thermo, only: get_hydrostatic_energy,thermo_budget_num_vars,thermo_budget_vars, & wvidx,wlidx,wiidx,seidx,poidx,keidx,moidx,mridx,ttidx,teidx use cam_history, only: outfld - use dyn_tests_utils, only: vc_physics, vc_height, vc_dry_pressure + use dyn_tests_utils, only: vc_physics + use cam_thermo_formula, only: ENERGY_FORMULA_DYCORE_SE, ENERGY_FORMULA_DYCORE_MPAS use cam_abortutils, only: endrun use cam_history_support, only: max_fieldname_len @@ -467,7 +468,7 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) end if if (state%psetcols == pcols) then - if (vc_loc == vc_height .or. vc_loc == vc_dry_pressure) then + if (vc_loc == ENERGY_FORMULA_DYCORE_MPAS .or. vc_loc == ENERGY_FORMULA_DYCORE_SE) then cp_or_cv(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) else cp_or_cv(:ncol,:) = cpairv(:ncol,:,lchnk) @@ -476,7 +477,7 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) call endrun('tot_energy_phys: energy diagnostics not implemented/tested for subcolumns') end if - if (vc_loc == vc_height .or. vc_loc == vc_dry_pressure) then + if (vc_loc == ENERGY_FORMULA_DYCORE_MPAS .or. vc_loc == ENERGY_FORMULA_DYCORE_SE) then scaling(:ncol,:) = cpairv(:ncol,:,lchnk)/cp_or_cv(:ncol,:)!scaling for energy consistency else scaling(:ncol,:) = 1.0_r8 !internal energy / enthalpy same as CAM physics @@ -643,7 +644,8 @@ end subroutine check_energy_get_integrals subroutine check_energy_timestep_init(state, tend, pbuf, col_type) use physics_buffer, only: physics_buffer_desc, pbuf_set_field use cam_abortutils, only: endrun - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure + use dyn_tests_utils, only: vc_physics, vc_dycore + use cam_thermo_formula, only: ENERGY_FORMULA_DYCORE_SE, ENERGY_FORMULA_DYCORE_MPAS use physics_types, only: physics_tend use physics_types, only: phys_te_idx, dyn_te_idx use time_manager, only: is_first_step @@ -671,7 +673,7 @@ subroutine check_energy_timestep_init(state, tend, pbuf, col_type) ! The code below is split into not-subcolumns and subcolumns code, as there is different handling of the ! cp passed into the hydrostatic energy call. CAM-SIMA does not support subcolumns, so we keep this special - ! handling inside this shim module. (hplin, 9/9/24) + ! handling inside this CAM interface. (hplin, 9/9/24) if(state%psetcols == pcols) then ! No subcolumns local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) @@ -685,10 +687,10 @@ subroutine check_energy_timestep_init(state, tend, pbuf, col_type) local_cp_phys(1:ncol,:) = cpair - if (vc_dycore == vc_height) then + if (vc_dycore == ENERGY_FORMULA_DYCORE_MPAS) then ! MPAS specific hydrostatic energy computation (internal energy) local_cp_or_cv_dycore(:ncol,:) = cpair-rair - else if(vc_dycore == vc_dry_pressure) then + else if(vc_dycore == ENERGY_FORMULA_DYCORE_SE) then ! SE specific hydrostatic energy (enthalpy) local_cp_or_cv_dycore(:ncol,:) = cpair else @@ -721,12 +723,12 @@ subroutine check_energy_timestep_init(state, tend, pbuf, col_type) tw_cur = state%tw_cur(1:ncol), & tend_te_tnd = tend%te_tnd(1:ncol), & tend_tw_tnd = tend%tw_tnd(1:ncol), & - temp_ini = state%temp_ini(:ncol,:), & - z_ini = state%z_ini(:ncol,:), & + temp_ini = state%temp_ini(:ncol,:), & + z_ini = state%z_ini(:ncol,:), & count = state%count, & teout = teout(1:ncol), & ! dummy argument - actual teout written to pbuf directly below - vc_physics = vc_physics, & - vc_dycore = vc_dycore, & + energy_formula_physics = vc_physics, & + energy_formula_dycore = vc_dycore, & errmsg = errmsg, & errflg = errflg & ) @@ -741,15 +743,16 @@ end subroutine check_energy_timestep_init ! Check that the energy and water change matches the boundary fluxes subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & flx_vap, flx_cnd, flx_ice, flx_sen) - use dyn_tests_utils, only: vc_physics, vc_dycore, vc_height, vc_dry_pressure - use cam_abortutils, only: endrun - use physics_types, only: phys_te_idx, dyn_te_idx - use physics_types, only: physics_tend - use physconst, only: cpair, rair, latice, latvap - use air_composition, only: cpairv, cp_or_cv_dycore + use dyn_tests_utils, only: vc_physics, vc_dycore + use cam_thermo_formula, only: ENERGY_FORMULA_DYCORE_SE, ENERGY_FORMULA_DYCORE_MPAS + use cam_abortutils, only: endrun + use physics_types, only: phys_te_idx, dyn_te_idx + use physics_types, only: physics_tend + use physconst, only: cpair, rair, latice, latvap + use air_composition, only: cpairv, cp_or_cv_dycore ! CCPP-ized subroutine - use check_energy_chng, only: check_energy_chng_run + use check_energy_chng, only: check_energy_chng_run type(physics_state), intent(inout) :: state type(physics_tend ), intent(inout) :: tend @@ -776,9 +779,8 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & ! No subcolumns local_cp_phys(:ncol,:) = cpairv(:ncol,:,lchnk) - ! Only if vertical coordinate is vc_height or vc_dry_pressure, cp_or_cv_dycore - ! is nonzero. - if(vc_dycore == vc_height .or. vc_dycore == vc_dry_pressure) then + ! Only if using MPAS or SE energy formula cp_or_cv_dycore is nonzero. + if(vc_dycore == ENERGY_FORMULA_DYCORE_MPAS .or. vc_dycore == ENERGY_FORMULA_DYCORE_SE) then local_cp_or_cv_dycore(:ncol,:) = cp_or_cv_dycore(:ncol,:,lchnk) scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling @@ -792,11 +794,11 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & local_cp_phys(:,:) = cpair ! Note: cp_or_cv set above for pressure coordinate - if (vc_dycore == vc_height) then + if (vc_dycore == ENERGY_FORMULA_DYCORE_MPAS) then ! compute cv if vertical coordinate is height: cv = cp - R local_cp_or_cv_dycore(:ncol,:) = cpair-rair scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling - else if (vc_dycore == vc_dry_pressure) then + else if (vc_dycore == ENERGY_FORMULA_DYCORE_SE) then ! SE specific hydrostatic energy local_cp_or_cv_dycore(:ncol,:) = cpair scaling_dycore(:ncol,:) = 1.0_r8 @@ -832,10 +834,10 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & z_ini = state%z_ini(:ncol,:), & count = state%count, & ztodt = ztodt, & - latice = latice, & - latvap = latvap, & - vc_physics = vc_physics, & - vc_dycore = vc_dycore, & + latice = latice, & + latvap = latvap, & + energy_formula_physics = vc_physics, & + energy_formula_dycore = vc_dycore, & name = name, & flx_vap = flx_vap, & flx_cnd = flx_cnd, & diff --git a/src/utils/cam_thermo_formula.F90 b/src/utils/cam_thermo_formula.F90 new file mode 100644 index 0000000000..7781e9da9c --- /dev/null +++ b/src/utils/cam_thermo_formula.F90 @@ -0,0 +1,14 @@ +module cam_thermo_formula + + implicit none + private + save + + ! energy_formula options for use by CCPPized check_energy + integer, public, parameter :: ENERGY_FORMULA_DYCORE_FV = 0 ! vc_moist_pressure + integer, public, parameter :: ENERGY_FORMULA_DYCORE_SE = 1 ! vc_dry_pressure + integer, public, parameter :: ENERGY_FORMULA_DYCORE_MPAS = 2 ! vc_height + + !REMOVECAM: in CAM, energy_formula_physics and energy_formula_dycore still uses vc_physics + ! and vc_dycore in dyn_tests_utils. The values are the same. +end module cam_thermo_formula From 46b82279c76644b410979b327dabb813afee01a7 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 28 Oct 2024 11:09:15 -0400 Subject: [PATCH 35/82] Update external to fix bug; ChangeLog draft --- .gitmodules | 2 +- doc/ChangeLog | 72 +++++++++++++++++++++++++++++++++++++++++++++++--- src/atmos_phys | 2 +- 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index 0edbb78972..e74baf681e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,7 +36,7 @@ [submodule "atmos_phys"] path = src/atmos_phys url = https://github.com/jimmielin/atmospheric_physics - fxtag = 952ebdd + fxtag = 44d724d fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/doc/ChangeLog b/doc/ChangeLog index 8294c223f2..f9aded72d5 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,71 @@ =============================================================== +Tag name: +Originator(s): jimmielin +Date: 25 Oct 2024 +One-line Summary: Implement CCPPized check_energy_chng and check_energy_fix +Github PR URL: https://github.com/ESCOMP/CAM/pull/1180 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): +- CCPPize check_energy_chng and check_energy_fix (https://github.com/ESCOMP/CAM/issues/1138) + CAM interfaces have been kept in check_energy.F90 instead of a new module because check_tracers is not yet CCPPized, there are other non-CCPPized routines in module, and for compatibility with FV3 external calls +- Save air_composition cp_or_cv_dycore into state snapshot +- Separate out "energy_formula_physics"/"energy_formula_dycore" definitions used in get_hydrostatic_energy from dyn_tests_utils "vcoord" for an eventual change in SIMA. + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: N/A + +List any changes to the defaults for the boundary datasets: N/A + +Describe any substantial timing or memory changes: N/A + +Code reviewed by: + +List all files eliminated: N/A + +List all files added and what they do: +- separate out energy formula definitions used in get_hydrostatic_energy from dyn_tests_utils "vcoord" +A src/utils/cam_thermo_formula.F90 + +List all existing files that have been modified, and describe the changes: + +Update atmos_phys external with CCPPized check_energy +M .gitmodules +M bld/configure +M src/atmos_phys + +Save cp_or_cv_dycore in state snapshot +M src/control/cam_snapshot_common.F90 + +New CAM interfaces to CCPPized routines, when avaialble +M src/physics/cam/check_energy.F90 + +Update calls to CCPPized routines, when available +M src/physics/cam/physpkg.F90 +M src/physics/cam/zm_conv_intr.F90 +M src/physics/cam7/physpkg.F90 +M src/physics/simple/physpkg.F90 +M src/physics/spcam/crm_physics.F90 +M src/physics/spcam/spcam_drivers.F90 + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + +derecho/nvhpc/aux_cam: + +izumi/nag/aux_cam: + +izumi/gnu/aux_cam: + +Summarize any changes to answers: B4B + +=============================================================== + Tag name: cam6_4_043 Originator(s): eaton Date: 25 Oct 2024 @@ -31,12 +97,12 @@ Describe any changes made to the namelist: . change default value of seasalt_emis_scale to 0.75 for cam7 (both lt and mt) This is a cam7 tuning mod from issue #1143 -. update ubc_file_path for cam7 (lt only) to +. update ubc_file_path for cam7 (lt only) to atm/cam/chem/ubc/b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensAvg123.cam.h0zm.H2O.1849-2014_c240604.nc List any changes to the defaults for the boundary datasets: -. update ubc_file_path for cam7 (lt only) to +. update ubc_file_path for cam7 (lt only) to atm/cam/chem/ubc/b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensAvg123.cam.h0zm.H2O.1849-2014_c240604.nc Describe any substantial timing or memory changes: none @@ -64,7 +130,7 @@ bld/namelist_files/namelist_defaults_cam.xml This is a cam7 tuning mod from issue #1143 bld/namelist_files/use_cases/1850_cam_lt.xml -. update ubc_file_path to +. update ubc_file_path to atm/cam/chem/ubc/b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensAvg123.cam.h0zm.H2O.1849-2014_c240604.nc cime_config/testdefs/testlist_cam.xml diff --git a/src/atmos_phys b/src/atmos_phys index 952ebddfa2..44d724d8e8 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit 952ebddfa22dd796578fba8d73db6128c8db88c1 +Subproject commit 44d724d8e88ab0b910543a9fdecd24fea9ca62f7 From ba1e652c92e1127ea3cdc3a61654c38959062ef9 Mon Sep 17 00:00:00 2001 From: peverwhee Date: Mon, 28 Oct 2024 15:01:44 -0600 Subject: [PATCH 36/82] fix filename for instantaneous monthly files --- src/control/cam_history.F90 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index 867c84eaea..d8346ec22f 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -309,6 +309,7 @@ module cam_history ! character(len=max_string_len) :: rhfilename_spec = '%c.cam.rh%t.%y-%m-%d-%s.nc' ! history restart character(len=max_string_len) :: hfilename_spec(ptapes) = (/ (' ', idx=1, ptapes) /) ! filename specifyer + logical :: default_monthly_filename(ptapes) = .false. ! Flag for if there are accumulated fields specified for a given tape logical :: hfile_accum(ptapes) = .false. @@ -812,6 +813,7 @@ subroutine history_readnl(nlfile) if ( nhtfrq(t) == 0 )then ! Monthly files hfilename_spec(t) = '%c.cam' // trim(inst_suffix) // '.h%t%f.%y-%m.nc' + default_monthly_filename(t) = .true. else hfilename_spec(t) = '%c.cam' // trim(inst_suffix) // '.h%t%f.%y-%m-%d-%s.nc' end if @@ -880,6 +882,7 @@ subroutine history_readnl(nlfile) call mpi_bcast(write_nstep0,1, mpi_logical, masterprocid, mpicom, ierr) call mpi_bcast(avgflag_pertape, ptapes, mpi_character, masterprocid, mpicom, ierr) call mpi_bcast(hfilename_spec, len(hfilename_spec(1))*ptapes, mpi_character, masterprocid, mpicom, ierr) + call mpi_bcast(default_monthly_filename, ptapes, mpi_logical, masterprocid, mpicom, ierr) call mpi_bcast(fincl, len(fincl (1,1))*pflds*ptapes, mpi_character, masterprocid, mpicom, ierr) call mpi_bcast(fexcl, len(fexcl (1,1))*pflds*ptapes, mpi_character, masterprocid, mpicom, ierr) @@ -5613,6 +5616,7 @@ subroutine wshist (rgnht_in) character(len=max_string_len) :: fname ! Filename character(len=max_string_len) :: fname_inst ! Filename for instantaneous tape character(len=max_string_len) :: fname_acc ! Filename for accumulated tape + character(len=max_string_len) :: inst_filename_spec ! Filename specifier override for monthly inst. files logical :: prev ! Label file with previous date rather than current logical :: duplicate ! Flag for duplicate file name integer :: ierr @@ -5726,7 +5730,14 @@ subroutine wshist (rgnht_in) else fname_acc = interpret_filename_spec( hfilename_spec(t), number=(t-1), & prev=prev, flag_spec='a' ) - fname_inst = interpret_filename_spec( hfilename_spec(t), number=(t-1), & + ! If this is a monthly instantaneous file, override to default timestamp + ! unless the user input a filename specifier + if (default_monthly_filename(t)) then + inst_filename_spec = '%c.cam' // trim(inst_suffix) // '.h%t%f.%y-%m-%d-%s.nc' + else + inst_filename_spec = hfilename_spec(t) + end if + fname_inst = interpret_filename_spec( inst_filename_spec, number=(t-1), & prev=prev, flag_spec='i' ) end if ! From 75f51d1331238b00228c2f0d5ea1086ddb2ebfa8 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Mon, 28 Oct 2024 15:21:02 -0600 Subject: [PATCH 37/82] Making nzm_clubb and nzt_clubb module parameters that are initialized in clubb_ini_cam. Reusing inv_exner_clubb(:,pver) to set inv_exner_clubb_surf. Splitting up array initialization loop to slightly improve CPU performance. --- src/physics/cam/clubb_intr.F90 | 45 ++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 7beb445b37..6fa4fa2936 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -58,6 +58,10 @@ module clubb_intr type (sclr_idx_type) :: & sclr_idx + + integer :: & + nzm_clubb, & + nzt_clubb #endif private @@ -1509,6 +1513,11 @@ subroutine clubb_ini_cam(pbuf2d) call endrun('clubb_ini_cam: CLUBB library core_rknd must match CAM r8 and it does not') end if + ! Determine number of vertical levels used in clubb, thermo variables are nzt_clubb + ! and momentum variables are nzm_clubb + nzt_clubb = pver + 1 - top_lev + nzm_clubb = pverp + 1 - top_lev + ! Allocate PDF parameters across columns and chunks allocate( & pdf_params_chnk(begchunk:endchunk), & @@ -1746,11 +1755,11 @@ subroutine clubb_ini_cam(pbuf2d) ! at each time step, which is why dummy arrays are read in here for heights ! as they are immediately overwrote. !$OMP PARALLEL - call check_clubb_settings_api( pverp+1-top_lev, clubb_params_single_col, & ! Intent(in) - l_implemented, & ! Intent(in) - l_input_fields, & ! Intent(in) - clubb_config_flags, & ! intent(in) - err_code ) ! Intent(out) + call check_clubb_settings_api( nzm_clubb, clubb_params_single_col, & ! Intent(in) + l_implemented, & ! Intent(in) + l_input_fields, & ! Intent(in) + clubb_config_flags, & ! intent(in) + err_code ) ! Intent(out) if ( err_code == clubb_fatal_error ) then call endrun('clubb_ini_cam: FATAL ERROR CALLING SETUP_CLUBB_CORE') @@ -1885,7 +1894,7 @@ subroutine clubb_ini_cam(pbuf2d) if (stats_metadata%l_stats) then call stats_init_clubb( .true., dum1, dum2, & - pverp+1-top_lev, pverp+1-top_lev, pverp+1-top_lev, dum3, & + nzm_clubb, nzm_clubb, nzm_clubb, dum3, & stats_zt(:), stats_zm(:), stats_sfc(:), & stats_rad_zt(:), stats_rad_zm(:)) @@ -2237,7 +2246,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Local CLUBB variables dimensioned as NCOL (only useful columns) to be sent into the clubb run api ! NOTE: THESE VARIABLS SHOULD NOT BE USED IN PBUF OR OUTFLD (HISTORY) SUBROUTINES - real(r8), dimension(state%ncol,pverp+1-top_lev) :: & + real(r8), dimension(state%ncol,nzm_clubb) :: & thlm_forcing, & ! theta_l forcing (thermodynamic levels) [K/s] rtm_forcing, & ! r_t forcing (thermodynamic levels) [(kg/kg)/s] um_forcing, & ! u wind forcing (thermodynamic levels) [m/s/s] @@ -2337,7 +2346,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Local CLUBB variables dimensioned as NCOL (only useful columns) to be sent into the clubb run api ! NOTE: THESE VARIABLS SHOULD NOT BE USED IN PBUF OR OUTFLD (HISTORY) SUBROUTINES - real(r8), dimension(state%ncol,pverp+1-top_lev,sclr_dim) :: & + real(r8), dimension(state%ncol,nzm_clubb,sclr_dim) :: & sclrm_forcing, & ! Passive scalar forcing [{units vary}/s] sclrm, & ! Passive scalar mean (thermo. levels) [units vary] sclrp2, & ! sclr'^2 (momentum levels) [{units vary}^2] @@ -2347,13 +2356,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wpsclrp, & ! w'sclr' (momentum levels) [{units vary} m/s] sclrpthvp_inout ! sclr'th_v' (momentum levels) [{units vary} (K)] - real(r8), dimension(state%ncol,pverp+1-top_lev,edsclr_dim) :: & + real(r8), dimension(state%ncol,nzm_clubb,edsclr_dim) :: & edsclrm_forcing, & ! Eddy passive scalar forcing [{units vary}/s] edsclr_in ! Scalars to be diffused through CLUBB [units vary] ! Local CLUBB variables dimensioned as NCOL (only useful columns) to be sent into the clubb run api ! NOTE: THESE VARIABLS SHOULD NOT BE USED IN PBUF OR OUTFLD (HISTORY) SUBROUTINES - real(r8), dimension(state%ncol,pverp+1-top_lev,hydromet_dim) :: & + real(r8), dimension(state%ncol,nzm_clubb,hydromet_dim) :: & hydromet, & wphydrometp, & wp2hmp, & @@ -2404,7 +2413,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8) :: rrho(pcols) ! Inverse of air density [1/kg/m^3] real(r8) :: kinwat(pcols) ! Kinematic water vapor flux [m/s] real(r8) :: latsub - real(r8) :: thlp2_rad_out(pcols,pverp+1-top_lev) + real(r8) :: thlp2_rad_out(pcols,nzm_clubb) real(r8) :: apply_const, rtm_test real(r8) :: dl_rad, di_rad, dt_low @@ -2602,8 +2611,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & clubb_params ! Adjustable CLUBB parameters (C1, C2 ...) integer :: & - nzm_clubb, & - nzt_clubb, & sclr, & edsclr, & n @@ -2766,11 +2773,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ncol = state%ncol lchnk = state%lchnk - ! Determine number of vertical levels used in clubb, thermo variables are nzt_clubb - ! and momentum variables are nzm_clubb - nzt_clubb = pver + 1 - top_lev - nzm_clubb = pverp + 1 - top_lev - ! Allocate pdf_params only if they aren't allocated already. if ( .not. allocated(pdf_params_chnk(lchnk)%mixt_frac) ) then call init_pdf_params_api( nzm_clubb, ncol, pdf_params_chnk(lchnk) ) @@ -2988,7 +2990,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vm_ref(i,k) = 0.0_r8 ug(i,k) = 0.0_r8 vg(i,k) = 0.0_r8 + end do + end do + !$acc parallel loop gang vector collapse(2) default(present) + do k = 1, nzm_clubb + do i = 1, ncol ! Perturbed winds are not used in CAM um_pert_inout(i,k) = 0.0_r8 vm_pert_inout(i,k) = 0.0_r8 @@ -3275,7 +3282,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute exner at the surface for converting the sensible heat fluxes ! to a flux of potential temperature for use as clubb's boundary conditions - inv_exner_clubb_surf(i) = 1._r8 / ( ( state1%pmid(i,pver) / p0_clubb )**( rairv(i,pver,lchnk) / cpairv(i,pver,lchnk) ) ) + inv_exner_clubb_surf(i) = inv_exner_clubb(i,pver) end do ! Compute thermodynamic stuff needed for CLUBB on thermo levels. From 2ec915a42c5fa25f3a9fc2815db14e64bbb08be4 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Tue, 10 Sep 2024 08:31:19 -0600 Subject: [PATCH 38/82] add timestamp to rpointer files --- src/control/cam_comp.F90 | 14 +++++++++++--- src/control/cam_initfiles.F90 | 27 +++++++++++++++++---------- src/control/cam_restart.F90 | 32 +++++++++++++++++++------------- src/control/runtime_opts.F90 | 6 +++--- src/cpl/nuopc/atm_comp_nuopc.F90 | 3 +++ 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/control/cam_comp.F90 b/src/control/cam_comp.F90 index a040762067..561129c3db 100644 --- a/src/control/cam_comp.F90 +++ b/src/control/cam_comp.F90 @@ -16,7 +16,7 @@ module cam_comp use spmd_utils, only: masterproc, mpicom use cam_control_mod, only: cam_ctrl_init, cam_ctrl_set_orbit use runtime_opts, only: read_namelist -use time_manager, only: timemgr_init, get_nstep +use time_manager, only: timemgr_init, get_nstep, get_curr_date use camsrfexch, only: cam_out_t, cam_in_t use ppgrid, only: begchunk, endchunk use physics_types, only: physics_state, physics_tend @@ -122,11 +122,11 @@ subroutine cam_init( & integer, intent(in) :: stop_tod ! Stop time of day (sec) integer, intent(in) :: ref_ymd ! Reference date (YYYYMMDD) integer, intent(in) :: ref_tod ! Reference time of day (sec) - type(cam_out_t), pointer :: cam_out(:) ! Output from CAM to surface type(cam_in_t) , pointer :: cam_in(:) ! Merged input state to CAM ! Local variables + integer :: yr, mon, day, tod character(len=cs) :: filein ! Input namelist filename !----------------------------------------------------------------------- @@ -152,7 +152,15 @@ subroutine cam_init( & ! Read CAM namelists. filein = "atm_in" // trim(inst_suffix) - call read_namelist(filein, single_column, scmlat, scmlon) + call get_curr_date(yr, mon, day, tod) + if(len_trim(inst_suffix) > 0) then + restart_pointer_file = interpret_filename_spec("rpointer.cam."//trim(inst_suffix)//".%y-%m-%d-%s", & + yr=yr_spec, mon=mon_spec, day=day_spec, tod= sec_spec ) + else + restart_pointer_file = interpret_filename_spec("rpointer.cam.%y-%m-%d-%s", & + yr=yr_spec, mon=mon_spec, day=day_spec, tod= sec_spec ) + endif + call read_namelist(filein, single_column, scmlat, scmlon, restart_pointer_file=restart_pointer_file) ! Open initial or restart file, and topo file if specified. call cam_initfiles_open() diff --git a/src/control/cam_initfiles.F90 b/src/control/cam_initfiles.F90 index 3b48f1ab0e..6c67125c8d 100644 --- a/src/control/cam_initfiles.F90 +++ b/src/control/cam_initfiles.F90 @@ -42,10 +42,6 @@ module cam_initfiles real(r8), public, protected :: scale_dry_air_mass = 0.0_r8 ! Toggle and target avg air mass for MPAS dycore -! The restart pointer file contains name of most recently written primary restart file. -! The contents of this file are updated by cam_write_restart as new restart files are written. -character(len=cl), public, protected :: rest_pfile - ! Filename for initial restart file. character(len=cl) :: restart_file = ' ' @@ -61,7 +57,7 @@ module cam_initfiles contains !======================================================================================== -subroutine cam_initfiles_readnl(nlfile) +subroutine cam_initfiles_readnl(nlfile, restart_pointer_file) use namelist_utils, only: find_group_name use units, only: getunit, freeunit @@ -70,7 +66,7 @@ subroutine cam_initfiles_readnl(nlfile) use cam_instance, only: inst_suffix character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input - + character(len=*), optional, intent(in) :: restart_pointer_file ! Local variables integer :: unitn, ierr @@ -78,6 +74,10 @@ subroutine cam_initfiles_readnl(nlfile) logical :: filefound integer :: xtype integer(pio_offset_kind) :: slen + logical :: found + + ! The restart pointer file contains name of most recently written primary restart file. + character(len=cl) :: rest_pfile character(len=*), parameter :: sub = 'cam_initfiles_readnl' @@ -112,18 +112,25 @@ subroutine cam_initfiles_readnl(nlfile) call mpi_bcast(scale_dry_air_mass, 1, mpir8, mstrid, mpicom, ierr) if (ierr /= 0) call endrun(sub//": ERROR: mpi_bcast: scale_dry_air_mass") - ! Set pointer file name based on instance suffix - rest_pfile = './rpointer.atm' // trim(inst_suffix) - + if(present(restart_pointer_file)) then + rest_pfile = restart_pointer_file + else + ! Set pointer file name based on instance suffix + rest_pfile = './rpointer.atm' // trim(inst_suffix) + endif ! Set name of primary restart file if (restart_run) then ! Read name of restart file from pointer file if (masterproc) then + inquire(file=trim(rest_pfile),exist=found) + if(.not. found) then + call endrun(sub // ': ERROR: rpointer file: '//trim(rest_pfile) // ' not found') + endif unitn = getunit() call opnfil(rest_pfile, unitn, 'f', status="old") read (unitn, '(a)', iostat=ierr) restart_file if (ierr /= 0) then - call endrun(sub // ': ERROR: reading rpointer file') + call endrun(sub // ': ERROR: reading rpointer file: '//trim(rest_pfile)) end if close(unitn) call freeunit(unitn) diff --git a/src/control/cam_restart.F90 b/src/control/cam_restart.F90 index 124cf3b4b5..41463c71f9 100644 --- a/src/control/cam_restart.F90 +++ b/src/control/cam_restart.F90 @@ -132,38 +132,44 @@ subroutine cam_write_restart(cam_in, cam_out, dyn_out, pbuf2d, & call ionosphere_write_restart(fh) call write_restart_physics(fh, cam_in, cam_out, pbuf2d) - if (present(yr_spec).and.present(mon_spec).and.& - present(day_spec).and.present(sec_spec)) then - call write_restart_history(fh, yr_spec=yr_spec, mon_spec=mon_spec, & - day_spec=day_spec, sec_spec= sec_spec ) - else - call write_restart_history(fh) - end if + call write_restart_history(fh, yr_spec=yr_spec, mon_spec=mon_spec, & + day_spec=day_spec, sec_spec= sec_spec ) ! Close the primary restart file call pio_closefile(fh) ! Update the restart pointer file - call write_rest_pfile(fname) + call write_rest_pfile(fname, yr_spec=yr_spec, mon_spec=mon_spec, & + day_spec=day_spec, sec_spec= sec_spec ) end subroutine cam_write_restart !======================================================================================== -subroutine write_rest_pfile(restart_file) +subroutine write_rest_pfile(restart_file, yr_spec, mon_spec, day_spec, sec_spec) ! Write the restart pointer file - - use cam_initfiles, only: rest_pfile - + use cam_instance, only: inst_suffix + use filenames, only: interpret_filename_spec character(len=*), intent(in) :: restart_file + integer, optional, intent(in) :: yr_spec ! Simulation year + integer, optional, intent(in) :: mon_spec ! Simulation month + integer, optional, intent(in) :: day_spec ! Simulation day + integer, optional, intent(in) :: sec_spec ! Seconds into current simulation day integer :: nsds, ierr + character(len=CL) :: rest_pfile character(len=*), parameter :: sub='write_rest_pfile' !--------------------------------------------------------------------------- if (masterproc) then - + if(inst_suffix .ne. "") then + rest_pfile = interpret_filename_spec('rpointer.cpl.%y-%m-%d-%s',& + yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) + else + rest_pfile = interpret_filename_spec('rpointer.cpl.'//trim(inst_suffix)//'.'//'%y-%m-%d-%s',& + yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) + endif nsds = getunit() call opnfil(rest_pfile, nsds, 'f') rewind nsds diff --git a/src/control/runtime_opts.F90 b/src/control/runtime_opts.F90 index 915664cdb9..0a8c48b509 100644 --- a/src/control/runtime_opts.F90 +++ b/src/control/runtime_opts.F90 @@ -19,7 +19,7 @@ module runtime_opts contains !======================================================================= -subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) +subroutine read_namelist(nlfilename, single_column, scmlat, scmlon, restart_pointer_file) use cam_initfiles, only: cam_initfiles_readnl use constituents, only: cnst_readnl @@ -109,7 +109,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) logical, intent(in) :: single_column real(r8), intent(in) :: scmlat real(r8), intent(in) :: scmlon - + character(len=*), optional, intent(in) :: restart_pointer_file !---------------------------Local variables----------------------------- character(len=*), parameter :: subname = "read_namelist" @@ -133,7 +133,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) !++bee 13 Oct 2015, need to fix the pbuf_global_allocate functionality, then ! can uncomment the pbuf_readnl line ! call pbuf_readnl(nlfilename) - call cam_initfiles_readnl(nlfilename) + call cam_initfiles_readnl(nlfilename, restart_pointer_file=restart_pointer_file) call cnst_readnl(nlfilename) call history_readnl(nlfilename) call chem_surfvals_readnl(nlfilename) diff --git a/src/cpl/nuopc/atm_comp_nuopc.F90 b/src/cpl/nuopc/atm_comp_nuopc.F90 index 8b2ba903d0..927a300bae 100644 --- a/src/cpl/nuopc/atm_comp_nuopc.F90 +++ b/src/cpl/nuopc/atm_comp_nuopc.F90 @@ -1976,6 +1976,9 @@ subroutine cam_write_clockrest( clock, yr_spec, mon_spec, day_spec, sec_spec, rc yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) if (masterproc) then + restart_pfile = interpret_filename_spec('rpointer.cpl.%y-%m-%d-%s',& + yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) + write(iulog,*) " In this configuration, there is no mediator" write(iulog,*) " Normally, the mediator restart file provides the restart time info" write(iulog,*) " In this case, CAM will create the rpointer.cpl and cpl restart file" From 230a84a552e7c4add07ec21f32e4d68ff109b61e Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Tue, 10 Sep 2024 15:23:27 -0600 Subject: [PATCH 39/82] add rpointer timestamp to cam --- src/control/cam_comp.F90 | 13 ++++++++----- src/control/cam_restart.F90 | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/control/cam_comp.F90 b/src/control/cam_comp.F90 index 561129c3db..66adf3b614 100644 --- a/src/control/cam_comp.F90 +++ b/src/control/cam_comp.F90 @@ -16,7 +16,7 @@ module cam_comp use spmd_utils, only: masterproc, mpicom use cam_control_mod, only: cam_ctrl_init, cam_ctrl_set_orbit use runtime_opts, only: read_namelist -use time_manager, only: timemgr_init, get_nstep, get_curr_date +use time_manager, only: timemgr_init, get_nstep, get_prev_date use camsrfexch, only: cam_out_t, cam_in_t use ppgrid, only: begchunk, endchunk use physics_types, only: physics_state, physics_tend @@ -87,7 +87,7 @@ subroutine cam_init( & use cam_snapshot_common, only: cam_snapshot_deactivate use air_composition, only: air_composition_init use phys_grid_ctem, only: phys_grid_ctem_reg - + use filenames, only: interpret_filename_spec ! Arguments character(len=cl), intent(in) :: caseid ! case ID character(len=cl), intent(in) :: ctitle ! case title @@ -126,6 +126,7 @@ subroutine cam_init( & type(cam_in_t) , pointer :: cam_in(:) ! Merged input state to CAM ! Local variables + character(len=cl) :: restart_pointer_file integer :: yr, mon, day, tod character(len=cs) :: filein ! Input namelist filename !----------------------------------------------------------------------- @@ -152,14 +153,16 @@ subroutine cam_init( & ! Read CAM namelists. filein = "atm_in" // trim(inst_suffix) - call get_curr_date(yr, mon, day, tod) + call get_prev_date(yr, mon, day, tod) if(len_trim(inst_suffix) > 0) then restart_pointer_file = interpret_filename_spec("rpointer.cam."//trim(inst_suffix)//".%y-%m-%d-%s", & - yr=yr_spec, mon=mon_spec, day=day_spec, tod= sec_spec ) + yr_spec=yr, mon_spec=mon, day_spec=day, sec_spec=tod ) else restart_pointer_file = interpret_filename_spec("rpointer.cam.%y-%m-%d-%s", & - yr=yr_spec, mon=mon_spec, day=day_spec, tod= sec_spec ) + yr_spec=yr, mon_spec=mon, day_spec=day, sec_spec=tod ) + endif + print *,__FILE__,__LINE__,trim(restart_pointer_file) call read_namelist(filein, single_column, scmlat, scmlon, restart_pointer_file=restart_pointer_file) ! Open initial or restart file, and topo file if specified. diff --git a/src/control/cam_restart.F90 b/src/control/cam_restart.F90 index 41463c71f9..02cb97b8c5 100644 --- a/src/control/cam_restart.F90 +++ b/src/control/cam_restart.F90 @@ -163,11 +163,11 @@ subroutine write_rest_pfile(restart_file, yr_spec, mon_spec, day_spec, sec_spec) !--------------------------------------------------------------------------- if (masterproc) then - if(inst_suffix .ne. "") then - rest_pfile = interpret_filename_spec('rpointer.cpl.%y-%m-%d-%s',& + if(len_trim(inst_suffix) > 0) then + rest_pfile = interpret_filename_spec('rpointer.cam.'//trim(inst_suffix)//'.'//'%y-%m-%d-%s',& yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) else - rest_pfile = interpret_filename_spec('rpointer.cpl.'//trim(inst_suffix)//'.'//'%y-%m-%d-%s',& + rest_pfile = interpret_filename_spec('rpointer.cam.%y-%m-%d-%s',& yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) endif nsds = getunit() From e00353cf02df9e0957b0a515fef024454ab5773d Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Thu, 12 Sep 2024 07:27:50 -0600 Subject: [PATCH 40/82] simplify rpointer naming --- src/control/cam_comp.F90 | 15 ++------------- src/control/cam_initfiles.F90 | 22 +++++++++++----------- src/control/cam_restart.F90 | 17 ++++------------- src/control/runtime_opts.F90 | 5 ++--- 4 files changed, 19 insertions(+), 40 deletions(-) diff --git a/src/control/cam_comp.F90 b/src/control/cam_comp.F90 index 66adf3b614..3eb94f041a 100644 --- a/src/control/cam_comp.F90 +++ b/src/control/cam_comp.F90 @@ -16,7 +16,7 @@ module cam_comp use spmd_utils, only: masterproc, mpicom use cam_control_mod, only: cam_ctrl_init, cam_ctrl_set_orbit use runtime_opts, only: read_namelist -use time_manager, only: timemgr_init, get_nstep, get_prev_date +use time_manager, only: timemgr_init, get_nstep use camsrfexch, only: cam_out_t, cam_in_t use ppgrid, only: begchunk, endchunk use physics_types, only: physics_state, physics_tend @@ -126,8 +126,6 @@ subroutine cam_init( & type(cam_in_t) , pointer :: cam_in(:) ! Merged input state to CAM ! Local variables - character(len=cl) :: restart_pointer_file - integer :: yr, mon, day, tod character(len=cs) :: filein ! Input namelist filename !----------------------------------------------------------------------- @@ -153,17 +151,8 @@ subroutine cam_init( & ! Read CAM namelists. filein = "atm_in" // trim(inst_suffix) - call get_prev_date(yr, mon, day, tod) - if(len_trim(inst_suffix) > 0) then - restart_pointer_file = interpret_filename_spec("rpointer.cam."//trim(inst_suffix)//".%y-%m-%d-%s", & - yr_spec=yr, mon_spec=mon, day_spec=day, sec_spec=tod ) - else - restart_pointer_file = interpret_filename_spec("rpointer.cam.%y-%m-%d-%s", & - yr_spec=yr, mon_spec=mon, day_spec=day, sec_spec=tod ) - endif - print *,__FILE__,__LINE__,trim(restart_pointer_file) - call read_namelist(filein, single_column, scmlat, scmlon, restart_pointer_file=restart_pointer_file) + call read_namelist(filein, single_column, scmlat, scmlon) ! Open initial or restart file, and topo file if specified. call cam_initfiles_open() diff --git a/src/control/cam_initfiles.F90 b/src/control/cam_initfiles.F90 index 6c67125c8d..d44d5030e1 100644 --- a/src/control/cam_initfiles.F90 +++ b/src/control/cam_initfiles.F90 @@ -57,19 +57,19 @@ module cam_initfiles contains !======================================================================================== -subroutine cam_initfiles_readnl(nlfile, restart_pointer_file) +subroutine cam_initfiles_readnl(nlfile) use namelist_utils, only: find_group_name use units, only: getunit, freeunit use spmd_utils, only: mpicom, mstrid=>masterprocid, mpir8=>mpi_real8, & mpichar=>mpi_character, mpi_logical use cam_instance, only: inst_suffix - + use filenames, only: interpret_filename_spec + character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input - character(len=*), optional, intent(in) :: restart_pointer_file + ! Local variables integer :: unitn, ierr - character(len=cl) :: locfn logical :: filefound integer :: xtype @@ -112,19 +112,19 @@ subroutine cam_initfiles_readnl(nlfile, restart_pointer_file) call mpi_bcast(scale_dry_air_mass, 1, mpir8, mstrid, mpicom, ierr) if (ierr /= 0) call endrun(sub//": ERROR: mpi_bcast: scale_dry_air_mass") - if(present(restart_pointer_file)) then - rest_pfile = restart_pointer_file - else - ! Set pointer file name based on instance suffix - rest_pfile = './rpointer.atm' // trim(inst_suffix) - endif ! Set name of primary restart file if (restart_run) then ! Read name of restart file from pointer file if (masterproc) then + rest_pfile = interpret_filename_spec("rpointer.cam"//trim(inst_suffix)//".%y-%m-%d-%s", prev=.true.) inquire(file=trim(rest_pfile),exist=found) if(.not. found) then - call endrun(sub // ': ERROR: rpointer file: '//trim(rest_pfile) // ' not found') + write(iulog, "Warning : rpointer file "//trim(rest_pfile)//" not found.") + rest_pfile = "rpointer.cam"//trim(inst_suffix) + inquire(file=trim(rest_pfile),exist=found) + if(.not. found) then + call endrun(sub // ': ERROR: rpointer file: '//trim(rest_pfile) // ' not found') + endif endif unitn = getunit() call opnfil(rest_pfile, unitn, 'f', status="old") diff --git a/src/control/cam_restart.F90 b/src/control/cam_restart.F90 index 02cb97b8c5..35087aa89b 100644 --- a/src/control/cam_restart.F90 +++ b/src/control/cam_restart.F90 @@ -106,12 +106,8 @@ subroutine cam_write_restart(cam_in, cam_out, dyn_out, pbuf2d, & ! (%c = caseid, $y = year, $m = month, $d = day, $s = seconds in day, %t = number) rfilename_spec = '%c.cam' // trim(inst_suffix) //'.r.%y-%m-%d-%s.nc' - if (present(yr_spec).and.present(mon_spec).and.present(day_spec).and.present(sec_spec)) then - fname = interpret_filename_spec( rfilename_spec, & - yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) - else - fname = interpret_filename_spec( rfilename_spec ) - end if + fname = interpret_filename_spec( rfilename_spec, & + yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) call cam_pio_createfile(fh, trim(fname), 0) ierr = cam_pio_set_fill(fh) @@ -163,13 +159,8 @@ subroutine write_rest_pfile(restart_file, yr_spec, mon_spec, day_spec, sec_spec) !--------------------------------------------------------------------------- if (masterproc) then - if(len_trim(inst_suffix) > 0) then - rest_pfile = interpret_filename_spec('rpointer.cam.'//trim(inst_suffix)//'.'//'%y-%m-%d-%s',& - yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) - else - rest_pfile = interpret_filename_spec('rpointer.cam.%y-%m-%d-%s',& - yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) - endif + rest_pfile = interpret_filename_spec('rpointer.cam'//trim(inst_suffix)//'.'//'%y-%m-%d-%s',& + yr_spec=yr_spec, mon_spec=mon_spec, day_spec=day_spec, sec_spec= sec_spec ) nsds = getunit() call opnfil(rest_pfile, nsds, 'f') rewind nsds diff --git a/src/control/runtime_opts.F90 b/src/control/runtime_opts.F90 index 0a8c48b509..19cff5c884 100644 --- a/src/control/runtime_opts.F90 +++ b/src/control/runtime_opts.F90 @@ -19,7 +19,7 @@ module runtime_opts contains !======================================================================= -subroutine read_namelist(nlfilename, single_column, scmlat, scmlon, restart_pointer_file) +subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) use cam_initfiles, only: cam_initfiles_readnl use constituents, only: cnst_readnl @@ -109,7 +109,6 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon, restart_poin logical, intent(in) :: single_column real(r8), intent(in) :: scmlat real(r8), intent(in) :: scmlon - character(len=*), optional, intent(in) :: restart_pointer_file !---------------------------Local variables----------------------------- character(len=*), parameter :: subname = "read_namelist" @@ -133,7 +132,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon, restart_poin !++bee 13 Oct 2015, need to fix the pbuf_global_allocate functionality, then ! can uncomment the pbuf_readnl line ! call pbuf_readnl(nlfilename) - call cam_initfiles_readnl(nlfilename, restart_pointer_file=restart_pointer_file) + call cam_initfiles_readnl(nlfilename) call cnst_readnl(nlfilename) call history_readnl(nlfilename) call chem_surfvals_readnl(nlfilename) From e67008e34f1d9aa5789b38975fda7f8ad4a80bb7 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Mon, 30 Sep 2024 15:51:08 -0600 Subject: [PATCH 41/82] update from utils to status for newer cime versions --- src/cpl/nuopc/atm_comp_nuopc.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpl/nuopc/atm_comp_nuopc.F90 b/src/cpl/nuopc/atm_comp_nuopc.F90 index 927a300bae..5b16968c44 100644 --- a/src/cpl/nuopc/atm_comp_nuopc.F90 +++ b/src/cpl/nuopc/atm_comp_nuopc.F90 @@ -1967,8 +1967,8 @@ subroutine cam_write_clockrest( clock, yr_spec, mon_spec, day_spec, sec_spec, rc call shr_cal_ymd2date(yy,mm,dd,start_ymd) call ESMF_TimeGet( nextTime, yy=yy, mm=mm, dd=dd, s=curr_tod, rc=rc ) - !call ESMF_TimeGet( currTime, yy=yy, mm=mm, dd=dd, s=curr_tod, rc=rc ) if (ChkErr(rc,__LINE__,u_FILE_u)) return + call shr_cal_ymd2date(yy,mm,dd,curr_ymd) ! Open clock info restart dataset From 880dd3e70c35905414412dc9ebbed07263c4be46 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Thu, 3 Oct 2024 11:48:28 -0600 Subject: [PATCH 42/82] remove whitespace changes, correct issue in atm_comp_nuopc --- src/control/cam_comp.F90 | 4 ++-- src/control/cam_initfiles.F90 | 3 ++- src/control/runtime_opts.F90 | 1 + src/cpl/nuopc/atm_comp_nuopc.F90 | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/control/cam_comp.F90 b/src/control/cam_comp.F90 index 3eb94f041a..a040762067 100644 --- a/src/control/cam_comp.F90 +++ b/src/control/cam_comp.F90 @@ -87,7 +87,7 @@ subroutine cam_init( & use cam_snapshot_common, only: cam_snapshot_deactivate use air_composition, only: air_composition_init use phys_grid_ctem, only: phys_grid_ctem_reg - use filenames, only: interpret_filename_spec + ! Arguments character(len=cl), intent(in) :: caseid ! case ID character(len=cl), intent(in) :: ctitle ! case title @@ -122,6 +122,7 @@ subroutine cam_init( & integer, intent(in) :: stop_tod ! Stop time of day (sec) integer, intent(in) :: ref_ymd ! Reference date (YYYYMMDD) integer, intent(in) :: ref_tod ! Reference time of day (sec) + type(cam_out_t), pointer :: cam_out(:) ! Output from CAM to surface type(cam_in_t) , pointer :: cam_in(:) ! Merged input state to CAM @@ -151,7 +152,6 @@ subroutine cam_init( & ! Read CAM namelists. filein = "atm_in" // trim(inst_suffix) - call read_namelist(filein, single_column, scmlat, scmlon) ! Open initial or restart file, and topo file if specified. diff --git a/src/control/cam_initfiles.F90 b/src/control/cam_initfiles.F90 index d44d5030e1..08de6340ad 100644 --- a/src/control/cam_initfiles.F90 +++ b/src/control/cam_initfiles.F90 @@ -119,8 +119,9 @@ subroutine cam_initfiles_readnl(nlfile) rest_pfile = interpret_filename_spec("rpointer.cam"//trim(inst_suffix)//".%y-%m-%d-%s", prev=.true.) inquire(file=trim(rest_pfile),exist=found) if(.not. found) then - write(iulog, "Warning : rpointer file "//trim(rest_pfile)//" not found.") + write(iulog, "INFO : rpointer file "//trim(rest_pfile)//" not found.") rest_pfile = "rpointer.cam"//trim(inst_suffix) + write(iulog, " Try looking for "//trim(rest_pfile)//" ...") inquire(file=trim(rest_pfile),exist=found) if(.not. found) then call endrun(sub // ': ERROR: rpointer file: '//trim(rest_pfile) // ' not found') diff --git a/src/control/runtime_opts.F90 b/src/control/runtime_opts.F90 index 19cff5c884..915664cdb9 100644 --- a/src/control/runtime_opts.F90 +++ b/src/control/runtime_opts.F90 @@ -109,6 +109,7 @@ subroutine read_namelist(nlfilename, single_column, scmlat, scmlon) logical, intent(in) :: single_column real(r8), intent(in) :: scmlat real(r8), intent(in) :: scmlon + !---------------------------Local variables----------------------------- character(len=*), parameter :: subname = "read_namelist" diff --git a/src/cpl/nuopc/atm_comp_nuopc.F90 b/src/cpl/nuopc/atm_comp_nuopc.F90 index 5b16968c44..8faf60fc79 100644 --- a/src/cpl/nuopc/atm_comp_nuopc.F90 +++ b/src/cpl/nuopc/atm_comp_nuopc.F90 @@ -1985,7 +1985,7 @@ subroutine cam_write_clockrest( clock, yr_spec, mon_spec, day_spec, sec_spec, rc write(iulog,*) " containing this information" write(iulog,*) " writing rpointer file for driver clock info, rpointer.cpl" write(iulog,*) " writing restart clock info for driver= "//trim(restart_file) - open(newunit=unitn, file='rpointer.cpl', form='FORMATTED') + open(newunit=unitn, file=trim(restart_pfile), form='FORMATTED') write(unitn,'(a)') trim(restart_file) close(unitn) endif From 0007c77f803399c58080c4b4b640c528ab6f5b75 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Thu, 17 Oct 2024 12:53:00 -0600 Subject: [PATCH 43/82] reverse alarm initialization to support alarm_restart at end of run --- src/cpl/nuopc/atm_comp_nuopc.F90 | 44 ++++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/cpl/nuopc/atm_comp_nuopc.F90 b/src/cpl/nuopc/atm_comp_nuopc.F90 index 8faf60fc79..bfde73912d 100644 --- a/src/cpl/nuopc/atm_comp_nuopc.F90 +++ b/src/cpl/nuopc/atm_comp_nuopc.F90 @@ -1296,51 +1296,51 @@ subroutine ModelSetRunClock(gcomp, rc) call ESMF_LogWrite(subname//'setting alarms for' // trim(name), ESMF_LOGMSG_INFO) !---------------- - ! Restart alarm + ! Stop alarm !---------------- - call NUOPC_CompAttributeGet(gcomp, name="restart_option", value=restart_option, rc=rc) + call NUOPC_CompAttributeGet(gcomp, name="stop_option", value=stop_option, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call NUOPC_CompAttributeGet(gcomp, name="restart_n", value=cvalue, rc=rc) + call NUOPC_CompAttributeGet(gcomp, name="stop_n", value=cvalue, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - read(cvalue,*) restart_n + read(cvalue,*) stop_n - call NUOPC_CompAttributeGet(gcomp, name="restart_ymd", value=cvalue, rc=rc) + call NUOPC_CompAttributeGet(gcomp, name="stop_ymd", value=cvalue, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - read(cvalue,*) restart_ymd + read(cvalue,*) stop_ymd - call alarmInit(mclock, restart_alarm, restart_option, & - opt_n = restart_n, & - opt_ymd = restart_ymd, & + call alarmInit(mclock, stop_alarm, stop_option, & + opt_n = stop_n, & + opt_ymd = stop_ymd, & RefTime = mcurrTime, & - alarmname = 'alarm_restart', rc=rc) + alarmname = 'alarm_stop', rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_AlarmSet(restart_alarm, clock=mclock, rc=rc) + call ESMF_AlarmSet(stop_alarm, clock=mclock, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return !---------------- - ! Stop alarm + ! Restart alarm !---------------- - call NUOPC_CompAttributeGet(gcomp, name="stop_option", value=stop_option, rc=rc) + call NUOPC_CompAttributeGet(gcomp, name="restart_option", value=restart_option, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call NUOPC_CompAttributeGet(gcomp, name="stop_n", value=cvalue, rc=rc) + call NUOPC_CompAttributeGet(gcomp, name="restart_n", value=cvalue, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - read(cvalue,*) stop_n + read(cvalue,*) restart_n - call NUOPC_CompAttributeGet(gcomp, name="stop_ymd", value=cvalue, rc=rc) + call NUOPC_CompAttributeGet(gcomp, name="restart_ymd", value=cvalue, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - read(cvalue,*) stop_ymd + read(cvalue,*) restart_ymd - call alarmInit(mclock, stop_alarm, stop_option, & - opt_n = stop_n, & - opt_ymd = stop_ymd, & + call alarmInit(mclock, restart_alarm, restart_option, & + opt_n = restart_n, & + opt_ymd = restart_ymd, & RefTime = mcurrTime, & - alarmname = 'alarm_stop', rc=rc) + alarmname = 'alarm_restart', rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_AlarmSet(stop_alarm, clock=mclock, rc=rc) + call ESMF_AlarmSet(restart_alarm, clock=mclock, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if From 2f59d18a1604dc761ea42d5f8d1f87084bd7d464 Mon Sep 17 00:00:00 2001 From: peverwhee Date: Tue, 29 Oct 2024 17:01:21 -0600 Subject: [PATCH 44/82] add sampled_on_subcycle argument for missing subcycle fields --- src/physics/cam/check_energy.F90 | 12 ++-- src/physics/cam/clubb_intr.F90 | 15 +++-- src/physics/cam/hetfrz_classnuc_cam.F90 | 68 +++++++++++----------- src/physics/cam/ndrop.F90 | 26 ++++----- src/physics/cam/ndrop_bam.F90 | 14 ++--- src/physics/cam/nucleate_ice_cam.F90 | 56 +++++++++--------- src/physics/cam/subcol_SILHS.F90 | 76 ++++++++++++------------- 7 files changed, 136 insertions(+), 131 deletions(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 94ef9a05e1..9c569387e0 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -201,12 +201,12 @@ subroutine check_energy_init() history_waccm_out = history_waccm ) ! register history variables - call addfld('TEINP', horiz_only, 'A', 'J/m2', 'Total energy of physics input', sampled_on_subcycle=.true.) - call addfld('TEOUT', horiz_only, 'A', 'J/m2', 'Total energy of physics output', sampled_on_subcycle=.true.) - call addfld('TEFIX', horiz_only, 'A', 'J/m2', 'Total energy after fixer', sampled_on_subcycle=.true.) - call addfld('EFIX', horiz_only, 'A', 'W/m2', 'Effective sensible heat flux due to energy fixer', sampled_on_subcycle=.true.) - call addfld('DTCORE', (/ 'lev' /), 'A', 'K/s' , 'T tendency due to dynamical core', sampled_on_subcycle=.true.) - call addfld('DQCORE', (/ 'lev' /), 'A', 'kg/kg/s' , 'Water vapor tendency due to dynamical core', sampled_on_subcycle=.true.) + call addfld('TEINP', horiz_only, 'A', 'J/m2', 'Total energy of physics input') + call addfld('TEOUT', horiz_only, 'A', 'J/m2', 'Total energy of physics output') + call addfld('TEFIX', horiz_only, 'A', 'J/m2', 'Total energy after fixer') + call addfld('EFIX', horiz_only, 'A', 'W/m2', 'Effective sensible heat flux due to energy fixer') + call addfld('DTCORE', (/ 'lev' /), 'A', 'K/s' , 'T tendency due to dynamical core') + call addfld('DQCORE', (/ 'lev' /), 'A', 'kg/kg/s' , 'Water vapor tendency due to dynamical core') if ( history_budget ) then call add_default ('DTCORE', history_budget_histfile_num, ' ') diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 872bbc4963..41580cc2c7 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -5115,7 +5115,8 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & call addfld( trim(sub), (/ 'ilev' /), 'A', & trim(stats_zt(1)%file%grid_avg_var(i)%units), & - trim(stats_zt(1)%file%grid_avg_var(i)%description) ) + trim(stats_zt(1)%file%grid_avg_var(i)%description), & + sampled_on_subcycle=.true. ) enddo do i = 1, stats_zm(1)%num_output_fields @@ -5126,7 +5127,8 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & call addfld( trim(sub), (/ 'ilev' /), 'A', & trim(stats_zm(1)%file%grid_avg_var(i)%units), & - trim(stats_zm(1)%file%grid_avg_var(i)%description) ) + trim(stats_zm(1)%file%grid_avg_var(i)%description), & + sampled_on_subcycle=.true. ) enddo if (stats_metadata%l_output_rad_files) then @@ -5137,7 +5139,8 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len) call addfld( trim(sub), (/ 'ilev' /), 'A', & trim(stats_rad_zt(1)%file%grid_avg_var(i)%units), & - trim(stats_rad_zt(1)%file%grid_avg_var(i)%description) ) + trim(stats_rad_zt(1)%file%grid_avg_var(i)%description), & + sampled_on_subcycle=.true. ) enddo do i = 1, stats_rad_zm(1)%num_output_fields @@ -5146,7 +5149,8 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len) call addfld( trim(sub), (/ 'ilev' /), 'A', & trim(stats_rad_zm(1)%file%grid_avg_var(i)%units), & - trim(stats_rad_zm(1)%file%grid_avg_var(i)%description) ) + trim(stats_rad_zm(1)%file%grid_avg_var(i)%description), & + sampled_on_subcycle=.true. ) enddo endif @@ -5156,7 +5160,8 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len) call addfld( trim(sub), horiz_only, 'A', & trim(stats_sfc(1)%file%grid_avg_var(i)%units), & - trim(stats_sfc(1)%file%grid_avg_var(i)%description) ) + trim(stats_sfc(1)%file%grid_avg_var(i)%description), & + sampled_on_subcycle=.true. ) enddo diff --git a/src/physics/cam/hetfrz_classnuc_cam.F90 b/src/physics/cam/hetfrz_classnuc_cam.F90 index 2f6d11787b..175ba8cfbb 100644 --- a/src/physics/cam/hetfrz_classnuc_cam.F90 +++ b/src/physics/cam/hetfrz_classnuc_cam.F90 @@ -228,23 +228,23 @@ subroutine hetfrz_classnuc_cam_init(mincld_in, aero_props) wactfac_hnames(cnt) = trim(tmpstr)//'_wactfac' call addfld(tot_dens_hnames(cnt),(/ 'lev' /), 'A', '#/cm3', & - 'total '//trim(tmpstr)//' number density' ) + 'total '//trim(tmpstr)//' number density', sampled_on_subcycle=.true.) call addfld(cld_dens_hnames(cnt),(/ 'lev' /), 'A', '#/cm3', & - 'cloud borne '//trim(tmpstr)//' number density' ) + 'cloud borne '//trim(tmpstr)//' number density', sampled_on_subcycle=.true.) call addfld(cldfn_dens_hnames(cnt),(/ 'lev' /), 'A', '#/cm3', & - 'cloud borne '//trim(tmpstr)//' number density derived from fn' ) + 'cloud borne '//trim(tmpstr)//' number density derived from fn', sampled_on_subcycle=.true.) call addfld(amb_dens_hnames(cnt),(/ 'lev' /), 'A', '#/cm3', & - 'ambient '//trim(tmpstr)//' number density' ) + 'ambient '//trim(tmpstr)//' number density', sampled_on_subcycle=.true.) call addfld(coated_dens_hnames(cnt),(/ 'lev' /), 'A', '#/cm3', & - 'coated '//trim(tmpstr)//' number density' ) + 'coated '//trim(tmpstr)//' number density', sampled_on_subcycle=.true.) call addfld(uncoated_dens_hnames(cnt),(/ 'lev' /), 'A', '#/cm3', & - 'uncoated '//trim(tmpstr)//' number density' ) + 'uncoated '//trim(tmpstr)//' number density', sampled_on_subcycle=.true.) call addfld(coated_frac_hnames(cnt),(/ 'lev' /), 'A', '#/cm3', & - 'coated '//trim(tmpstr)//' fraction' ) + 'coated '//trim(tmpstr)//' fraction', sampled_on_subcycle=.true.) call addfld(radius_hnames(cnt),(/ 'lev' /), 'A', 'm', & - 'ambient '//trim(tmpstr)//' radius' ) + 'ambient '//trim(tmpstr)//' radius', sampled_on_subcycle=.true.) call addfld(wactfac_hnames(cnt),(/ 'lev' /), 'A', ' ', & - trim(tmpstr)//' water activity mass factor' ) + trim(tmpstr)//' water activity mass factor', sampled_on_subcycle=.true.) end if end do @@ -261,49 +261,49 @@ subroutine hetfrz_classnuc_cam_init(mincld_in, aero_props) ! pbuf fields used by hetfrz_classnuc ast_idx = pbuf_get_index('AST') - call addfld('FRZIMM', (/ 'lev' /), 'A', ' ', 'immersion freezing') - call addfld('FRZCNT', (/ 'lev' /), 'A', ' ', 'contact freezing') - call addfld('FRZDEP', (/ 'lev' /), 'A', ' ', 'deposition freezing') - call addfld('FREQIMM', (/ 'lev' /), 'A', 'fraction', 'Fractional occurance of immersion freezing') - call addfld('FREQCNT', (/ 'lev' /), 'A', 'fraction', 'Fractional occurance of contact freezing') - call addfld('FREQDEP', (/ 'lev' /), 'A', 'fraction', 'Fractional occurance of deposition freezing') - call addfld('FREQMIX', (/ 'lev' /), 'A', 'fraction', 'Fractional occurance of mixed-phase clouds' ) + call addfld('FRZIMM', (/ 'lev' /), 'A', ' ', 'immersion freezing', sampled_on_subcycle=.true.) + call addfld('FRZCNT', (/ 'lev' /), 'A', ' ', 'contact freezing', sampled_on_subcycle=.true.) + call addfld('FRZDEP', (/ 'lev' /), 'A', ' ', 'deposition freezing', sampled_on_subcycle=.true.) + call addfld('FREQIMM', (/ 'lev' /), 'A', 'fraction', 'Fractional occurance of immersion freezing', sampled_on_subcycle=.true.) + call addfld('FREQCNT', (/ 'lev' /), 'A', 'fraction', 'Fractional occurance of contact freezing', sampled_on_subcycle=.true.) + call addfld('FREQDEP', (/ 'lev' /), 'A', 'fraction', 'Fractional occurance of deposition freezing', sampled_on_subcycle=.true.) + call addfld('FREQMIX', (/ 'lev' /), 'A', 'fraction', 'Fractional occurance of mixed-phase clouds' , sampled_on_subcycle=.true.) - call addfld('DSTFREZIMM', (/ 'lev' /), 'A', 'm-3s-1', 'dust immersion freezing rate') - call addfld('DSTFREZCNT', (/ 'lev' /), 'A', 'm-3s-1', 'dust contact freezing rate') - call addfld('DSTFREZDEP', (/ 'lev' /), 'A', 'm-3s-1', 'dust deposition freezing rate') + call addfld('DSTFREZIMM', (/ 'lev' /), 'A', 'm-3s-1', 'dust immersion freezing rate', sampled_on_subcycle=.true.) + call addfld('DSTFREZCNT', (/ 'lev' /), 'A', 'm-3s-1', 'dust contact freezing rate', sampled_on_subcycle=.true.) + call addfld('DSTFREZDEP', (/ 'lev' /), 'A', 'm-3s-1', 'dust deposition freezing rate', sampled_on_subcycle=.true.) - call addfld('BCFREZIMM', (/ 'lev' /), 'A', 'm-3s-1', 'bc immersion freezing rate') - call addfld('BCFREZCNT', (/ 'lev' /), 'A', 'm-3s-1', 'bc contact freezing rate') - call addfld('BCFREZDEP', (/ 'lev' /), 'A', 'm-3s-1', 'bc deposition freezing rate') + call addfld('BCFREZIMM', (/ 'lev' /), 'A', 'm-3s-1', 'bc immersion freezing rate', sampled_on_subcycle=.true.) + call addfld('BCFREZCNT', (/ 'lev' /), 'A', 'm-3s-1', 'bc contact freezing rate', sampled_on_subcycle=.true.) + call addfld('BCFREZDEP', (/ 'lev' /), 'A', 'm-3s-1', 'bc deposition freezing rate', sampled_on_subcycle=.true.) call addfld('NIMIX_IMM', (/ 'lev' /), 'A', '#/m3', & - 'Activated Ice Number Concentration due to het immersion freezing in Mixed Clouds') + 'Activated Ice Number Concentration due to het immersion freezing in Mixed Clouds', sampled_on_subcycle=.true.) call addfld('NIMIX_CNT', (/ 'lev' /), 'A', '#/m3', & - 'Activated Ice Number Concentration due to het contact freezing in Mixed Clouds') + 'Activated Ice Number Concentration due to het contact freezing in Mixed Clouds', sampled_on_subcycle=.true.) call addfld('NIMIX_DEP', (/ 'lev' /), 'A', '#/m3', & - 'Activated Ice Number Concentration due to het deposition freezing in Mixed Clouds') + 'Activated Ice Number Concentration due to het deposition freezing in Mixed Clouds', sampled_on_subcycle=.true.) call addfld('DSTNIDEP', (/ 'lev' /), 'A', '#/m3', & - 'Activated Ice Number Concentration due to dst dep freezing in Mixed Clouds') + 'Activated Ice Number Concentration due to dst dep freezing in Mixed Clouds', sampled_on_subcycle=.true.) call addfld('DSTNICNT', (/ 'lev' /), 'A', '#/m3', & - 'Activated Ice Number Concentration due to dst cnt freezing in Mixed Clouds') + 'Activated Ice Number Concentration due to dst cnt freezing in Mixed Clouds', sampled_on_subcycle=.true.) call addfld('DSTNIIMM', (/ 'lev' /), 'A', '#/m3', & - 'Activated Ice Number Concentration due to dst imm freezing in Mixed Clouds') + 'Activated Ice Number Concentration due to dst imm freezing in Mixed Clouds', sampled_on_subcycle=.true.) call addfld('BCNIDEP', (/ 'lev' /), 'A', '#/m3', & - 'Activated Ice Number Concentration due to bc dep freezing in Mixed Clouds') + 'Activated Ice Number Concentration due to bc dep freezing in Mixed Clouds', sampled_on_subcycle=.true.) call addfld('BCNICNT', (/ 'lev' /), 'A', '#/m3', & - 'Activated Ice Number Concentration due to bc cnt freezing in Mixed Clouds') + 'Activated Ice Number Concentration due to bc cnt freezing in Mixed Clouds', sampled_on_subcycle=.true.) call addfld('BCNIIMM', (/ 'lev' /), 'A', '#/m3', & - 'Activated Ice Number Concentration due to bc imm freezing in Mixed Clouds') + 'Activated Ice Number Concentration due to bc imm freezing in Mixed Clouds', sampled_on_subcycle=.true.) call addfld('NUMICE10s', (/ 'lev' /), 'A', '#/m3', & - 'Ice Number Concentration due to het freezing in Mixed Clouds during 10-s period') + 'Ice Number Concentration due to het freezing in Mixed Clouds during 10-s period', sampled_on_subcycle=.true.) call addfld('NUMIMM10sDST', (/ 'lev' /), 'A', '#/m3', & - 'Ice Number Concentration due to imm freezing by dst in Mixed Clouds during 10-s period') + 'Ice Number Concentration due to imm freezing by dst in Mixed Clouds during 10-s period', sampled_on_subcycle=.true.) call addfld('NUMIMM10sBC', (/ 'lev' /), 'A', '#/m3', & - 'Ice Number Concentration due to imm freezing by bc in Mixed Clouds during 10-s period') + 'Ice Number Concentration due to imm freezing by bc in Mixed Clouds during 10-s period', sampled_on_subcycle=.true.) if (hist_hetfrz_classnuc) then diff --git a/src/physics/cam/ndrop.F90 b/src/physics/cam/ndrop.F90 index 9eea87d218..ea3d7522da 100644 --- a/src/physics/cam/ndrop.F90 +++ b/src/physics/cam/ndrop.F90 @@ -135,10 +135,10 @@ subroutine ndrop_init(aero_props) ! Add tendency fields to the history only when prognostic MAM is enabled. long_name = trim(tmpname) // ' dropmixnuc mixnuc column tendency' - call addfld(fieldname(mm), horiz_only, 'A', unit, long_name) + call addfld(fieldname(mm), horiz_only, 'A', unit, long_name, sampled_on_subcycle=.true.) long_name = trim(tmpname_cw) // ' dropmixnuc mixnuc column tendency' - call addfld(fieldname_cw(mm), horiz_only, 'A', unit, long_name) + call addfld(fieldname_cw(mm), horiz_only, 'A', unit, long_name, sampled_on_subcycle=.true.) if (history_aerosol) then call add_default(fieldname(mm), 1, ' ') @@ -148,19 +148,19 @@ subroutine ndrop_init(aero_props) end do end do - call addfld('CCN1',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.02%') - call addfld('CCN2',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.05%') - call addfld('CCN3',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.1%') - call addfld('CCN4',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.2%') - call addfld('CCN5',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.5%') - call addfld('CCN6',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=1.0%') + call addfld('CCN1',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.02%', sampled_on_subcycle=.true.) + call addfld('CCN2',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.05%', sampled_on_subcycle=.true.) + call addfld('CCN3',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.1%', sampled_on_subcycle=.true.) + call addfld('CCN4',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.2%', sampled_on_subcycle=.true.) + call addfld('CCN5',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.5%', sampled_on_subcycle=.true.) + call addfld('CCN6',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=1.0%', sampled_on_subcycle=.true.) - call addfld('WTKE', (/ 'lev' /), 'A', 'm/s', 'Standard deviation of updraft velocity') - call addfld('NDROPMIX', (/ 'lev' /), 'A', '#/kg/s', 'Droplet number mixing') - call addfld('NDROPSRC', (/ 'lev' /), 'A', '#/kg/s', 'Droplet number source') - call addfld('NDROPSNK', (/ 'lev' /), 'A', '#/kg/s', 'Droplet number loss by microphysics') - call addfld('NDROPCOL', horiz_only, 'A', '#/m2', 'Column droplet number') + call addfld('WTKE', (/ 'lev' /), 'A', 'm/s', 'Standard deviation of updraft velocity', sampled_on_subcycle=.true.) + call addfld('NDROPMIX', (/ 'lev' /), 'A', '#/kg/s', 'Droplet number mixing', sampled_on_subcycle=.true.) + call addfld('NDROPSRC', (/ 'lev' /), 'A', '#/kg/s', 'Droplet number source', sampled_on_subcycle=.true.) + call addfld('NDROPSNK', (/ 'lev' /), 'A', '#/kg/s', 'Droplet number loss by microphysics', sampled_on_subcycle=.true.) + call addfld('NDROPCOL', horiz_only, 'A', '#/m2', 'Column droplet number', sampled_on_subcycle=.true.) ! set the add_default fields if (history_amwg) then diff --git a/src/physics/cam/ndrop_bam.F90 b/src/physics/cam/ndrop_bam.F90 index 6cd8231356..01ab3b5856 100644 --- a/src/physics/cam/ndrop_bam.F90 +++ b/src/physics/cam/ndrop_bam.F90 @@ -112,7 +112,7 @@ subroutine ndrop_bam_init if (trim(aername(iaer)) == 'SULFATE') idxsul = iaer ! aerosol number concentration - call addfld(trim(aername(iaer))//'_m3', (/ 'lev' /), 'A', 'm-3', 'aerosol number concentration') + call addfld(trim(aername(iaer))//'_m3', (/ 'lev' /), 'A', 'm-3', 'aerosol number concentration', sampled_on_subcycle=.true.) end do @@ -129,12 +129,12 @@ subroutine ndrop_bam_init end if end if - call addfld ('CCN1',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.02%') - call addfld ('CCN2',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.05%') - call addfld ('CCN3',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.1%') - call addfld ('CCN4',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.2%') - call addfld ('CCN5',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.5%') - call addfld ('CCN6',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=1.0%') + call addfld ('CCN1',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.02%', sampled_on_subcycle=.true.) + call addfld ('CCN2',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.05%', sampled_on_subcycle=.true.) + call addfld ('CCN3',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.1%', sampled_on_subcycle=.true.) + call addfld ('CCN4',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.2%', sampled_on_subcycle=.true.) + call addfld ('CCN5',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=0.5%', sampled_on_subcycle=.true.) + call addfld ('CCN6',(/ 'lev' /), 'A','#/cm3','CCN concentration at S=1.0%', sampled_on_subcycle=.true.) if (history_amwg) then call add_default('CCN3', 1, ' ') diff --git a/src/physics/cam/nucleate_ice_cam.F90 b/src/physics/cam/nucleate_ice_cam.F90 index 7dff84f529..41cea58b38 100644 --- a/src/physics/cam/nucleate_ice_cam.F90 +++ b/src/physics/cam/nucleate_ice_cam.F90 @@ -263,52 +263,52 @@ subroutine nucleate_ice_cam_init(mincld_in, bulk_scale_in, pbuf2d, aero_props) if (cam_physpkg_is("cam7")) then ! Updates for PUMAS v1.21+ - call addfld('NIHFTEN', (/ 'lev' /), 'A', '1/m3/s', 'Activated Ice Number Concentration tendency due to homogenous freezing') - call addfld('NIDEPTEN', (/ 'lev' /), 'A', '1/m3/s', 'Activated Ice Number Concentration tendency due to deposition nucleation') - call addfld('NIIMMTEN', (/ 'lev' /), 'A', '1/m3/s', 'Activated Ice Number Concentration tendency due to immersion freezing') - call addfld('NIMEYTEN', (/ 'lev' /), 'A', '1/m3/s', 'Activated Ice Number Concentration tendency due to meyers deposition') + call addfld('NIHFTEN', (/ 'lev' /), 'A', '1/m3/s', 'Activated Ice Number Concentration tendency due to homogenous freezing', sampled_on_subcycle=.true.) + call addfld('NIDEPTEN', (/ 'lev' /), 'A', '1/m3/s', 'Activated Ice Number Concentration tendency due to deposition nucleation', sampled_on_subcycle=.true.) + call addfld('NIIMMTEN', (/ 'lev' /), 'A', '1/m3/s', 'Activated Ice Number Concentration tendency due to immersion freezing', sampled_on_subcycle=.true.) + call addfld('NIMEYTEN', (/ 'lev' /), 'A', '1/m3/s', 'Activated Ice Number Concentration tendency due to meyers deposition', sampled_on_subcycle=.true.) else - call addfld('NIHF', (/ 'lev' /), 'A', '1/m3', 'Activated Ice Number Concentration due to homogenous freezing') - call addfld('NIDEP', (/ 'lev' /), 'A', '1/m3', 'Activated Ice Number Concentration due to deposition nucleation') - call addfld('NIIMM', (/ 'lev' /), 'A', '1/m3', 'Activated Ice Number Concentration due to immersion freezing') - call addfld('NIMEY', (/ 'lev' /), 'A', '1/m3', 'Activated Ice Number Concentration due to meyers deposition') + call addfld('NIHF', (/ 'lev' /), 'A', '1/m3', 'Activated Ice Number Concentration due to homogenous freezing', sampled_on_subcycle=.true.) + call addfld('NIDEP', (/ 'lev' /), 'A', '1/m3', 'Activated Ice Number Concentration due to deposition nucleation', sampled_on_subcycle=.true.) + call addfld('NIIMM', (/ 'lev' /), 'A', '1/m3', 'Activated Ice Number Concentration due to immersion freezing', sampled_on_subcycle=.true.) + call addfld('NIMEY', (/ 'lev' /), 'A', '1/m3', 'Activated Ice Number Concentration due to meyers deposition', sampled_on_subcycle=.true.) endif - call addfld('NIREGM',(/ 'lev' /), 'A', 'C', 'Ice Nucleation Temperature Threshold for Regime') - call addfld('NISUBGRID',(/ 'lev' /), 'A', '', 'Ice Nucleation subgrid saturation factor') - call addfld('NITROP_PD',(/ 'lev' /), 'A', '', 'Chemical Tropopause probability') + call addfld('NIREGM',(/ 'lev' /), 'A', 'C', 'Ice Nucleation Temperature Threshold for Regime', sampled_on_subcycle=.true.) + call addfld('NISUBGRID',(/ 'lev' /), 'A', '', 'Ice Nucleation subgrid saturation factor', sampled_on_subcycle=.true.) + call addfld('NITROP_PD',(/ 'lev' /), 'A', '', 'Chemical Tropopause probability', sampled_on_subcycle=.true.) if ( history_cesm_forcing ) then call add_default('NITROP_PD',8,' ') endif if (use_preexisting_ice) then - call addfld('fhom', (/ 'lev' /), 'A','fraction', 'Fraction of cirrus where homogeneous freezing occur' ) - call addfld ('WICE', (/ 'lev' /), 'A','m/s','Vertical velocity Reduction caused by preexisting ice' ) - call addfld ('WEFF', (/ 'lev' /), 'A','m/s','Effective Vertical velocity for ice nucleation' ) + call addfld('fhom', (/ 'lev' /), 'A','fraction', 'Fraction of cirrus where homogeneous freezing occur', sampled_on_subcycle=.true.) + call addfld ('WICE', (/ 'lev' /), 'A','m/s','Vertical velocity Reduction caused by preexisting ice', sampled_on_subcycle=.true.) + call addfld ('WEFF', (/ 'lev' /), 'A','m/s','Effective Vertical velocity for ice nucleation', sampled_on_subcycle=.true.) if (cam_physpkg_is("cam7")) then ! Updates for PUMAS v1.21+ - call addfld ('INnso4TEN', (/ 'lev' /), 'A','1/m3/s','Number Concentration tendency so4 (in) to ice_nucleation') - call addfld ('INnbcTEN', (/ 'lev' /), 'A','1/m3/s','Number Concentration tendency bc (in) to ice_nucleation') - call addfld ('INndustTEN', (/ 'lev' /), 'A','1/m3/s','Number Concentration tendency dust (in) ice_nucleation') - call addfld ('INondustTEN', (/ 'lev' /), 'A','1/m3/s','Number Concentration tendency dust (out) from ice_nucleation') + call addfld ('INnso4TEN', (/ 'lev' /), 'A','1/m3/s','Number Concentration tendency so4 (in) to ice_nucleation', sampled_on_subcycle=.true.) + call addfld ('INnbcTEN', (/ 'lev' /), 'A','1/m3/s','Number Concentration tendency bc (in) to ice_nucleation', sampled_on_subcycle=.true.) + call addfld ('INndustTEN', (/ 'lev' /), 'A','1/m3/s','Number Concentration tendency dust (in) ice_nucleation', sampled_on_subcycle=.true.) + call addfld ('INondustTEN', (/ 'lev' /), 'A','1/m3/s','Number Concentration tendency dust (out) from ice_nucleation', sampled_on_subcycle=.true.) call addfld ('INhetTEN', (/ 'lev' /), 'A','1/m3/s', & - 'Tendency for contribution for in-cloud ice number density increase by het nucleation in ice cloud') + 'Tendency for contribution for in-cloud ice number density increase by het nucleation in ice cloud', sampled_on_subcycle=.true.) call addfld ('INhomTEN', (/ 'lev' /), 'A','1/m3/s', & - 'Tendency for contribution for in-cloud ice number density increase by hom nucleation in ice cloud') + 'Tendency for contribution for in-cloud ice number density increase by hom nucleation in ice cloud', sampled_on_subcycle=.true.) else - call addfld ('INnso4', (/ 'lev' /), 'A','1/m3','Number Concentration so4 (in) to ice_nucleation') - call addfld ('INnbc', (/ 'lev' /), 'A','1/m3','Number Concentration bc (in) to ice_nucleation') - call addfld ('INndust', (/ 'lev' /), 'A','1/m3','Number Concentration dust (in) ice_nucleation') - call addfld ('INondust', (/ 'lev' /), 'A','1/m3','Number Concentration dust (out) from ice_nucleation') + call addfld ('INnso4', (/ 'lev' /), 'A','1/m3','Number Concentration so4 (in) to ice_nucleation', sampled_on_subcycle=.true.) + call addfld ('INnbc', (/ 'lev' /), 'A','1/m3','Number Concentration bc (in) to ice_nucleation', sampled_on_subcycle=.true.) + call addfld ('INndust', (/ 'lev' /), 'A','1/m3','Number Concentration dust (in) ice_nucleation', sampled_on_subcycle=.true.) + call addfld ('INondust', (/ 'lev' /), 'A','1/m3','Number Concentration dust (out) from ice_nucleation', sampled_on_subcycle=.true.) call addfld ('INhet', (/ 'lev' /), 'A','1/m3', & - 'contribution for in-cloud ice number density increase by het nucleation in ice cloud') + 'contribution for in-cloud ice number density increase by het nucleation in ice cloud', sampled_on_subcycle=.true.) call addfld ('INhom', (/ 'lev' /), 'A','1/m3', & - 'contribution for in-cloud ice number density increase by hom nucleation in ice cloud') + 'contribution for in-cloud ice number density increase by hom nucleation in ice cloud', sampled_on_subcycle=.true.) endif - call addfld ('INFrehom', (/ 'lev' /), 'A','frequency','hom IN frequency ice cloud') - call addfld ('INFreIN', (/ 'lev' /), 'A','frequency','frequency of ice nucleation occur') + call addfld ('INFrehom', (/ 'lev' /), 'A','frequency','hom IN frequency ice cloud', sampled_on_subcycle=.true.) + call addfld ('INFreIN', (/ 'lev' /), 'A','frequency','frequency of ice nucleation occur', sampled_on_subcycle=.true.) if (hist_preexisting_ice) then call add_default ('WSUBI ', 1, ' ') ! addfld/outfld calls are in microp_aero diff --git a/src/physics/cam/subcol_SILHS.F90 b/src/physics/cam/subcol_SILHS.F90 index c373ed6b3e..05653b9f03 100644 --- a/src/physics/cam/subcol_SILHS.F90 +++ b/src/physics/cam/subcol_SILHS.F90 @@ -489,80 +489,80 @@ subroutine subcol_init_SILHS(pbuf2d) ! Register output fields from SILHS !------------------------------- call addfld('SILHS_NCLD_SCOL', (/'psubcols', 'ilev '/), 'I', 'm^-3', & - 'Subcolumn Cloud Number Concentration', flag_xyfill=.true., fill_value=1.e30_r8) + 'Subcolumn Cloud Number Concentration', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('SILHS_NRAIN_SCOL', (/'psubcols', 'ilev '/), 'I', 'm^-3', & - 'Subcolumn Number Concentration of Rain from SILHS', flag_xyfill=.true., fill_value=1.e30_r8) + 'Subcolumn Number Concentration of Rain from SILHS', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('SILHS_OMEGA_SCOL', (/'psubcols', 'ilev '/), 'I', 'Pa/s', & - 'Subcolumn vertical pressure velocity', flag_xyfill=.true., fill_value=1.e30_r8) + 'Subcolumn vertical pressure velocity', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('SILHS_RCM_SCOL', (/'psubcols', 'ilev '/), 'I', 'kg/kg', & - 'Subcolumn Cloud Liquid Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8) + 'Subcolumn Cloud Liquid Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('SILHS_RICLD_SCOL', (/'psubcols', 'ilev '/), 'I', 'kg/kg', & - 'Subcolumn Cloud Ice Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8) + 'Subcolumn Cloud Ice Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('SILHS_NICLD_SCOL', (/'psubcols', 'ilev '/), 'I', 'kg/kg', & - 'Subcolumn Cloud Ice Number Conc from SILHS', flag_xyfill=.true., fill_value=1.e30_r8) + 'Subcolumn Cloud Ice Number Conc from SILHS', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('SILHS_RRAIN_SCOL', (/'psubcols', 'ilev '/), 'I', 'kg/kg', & - 'Subcolumn Precipitating Liquid Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8) + 'Subcolumn Precipitating Liquid Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('SILHS_RT_SCOL', (/'psubcols', 'ilev '/), 'I', 'kg/kg ', & - 'Subcolumn Total Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8) + 'Subcolumn Total Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('SILHS_THLM_SCOL', (/'psubcols', 'ilev '/), 'I', 'K', & - 'Subcolumn liquid water pot temperature', flag_xyfill=.true., fill_value=1.e30_r8) + 'Subcolumn liquid water pot temperature', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('SILHS_WEIGHT_SCOL', (/'psubcols'/), 'I', 'frac', & - 'Weights for each subcolumn', flag_xyfill=.true., fill_value=1.e30_r8) + 'Weights for each subcolumn', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('SILHS_WM_SCOL', (/'psubcols', 'ilev '/), 'I', 'm/s', & - 'Subcolumn vertical velocity from SILHS', flag_xyfill=.true., fill_value=1.e30_r8) + 'Subcolumn vertical velocity from SILHS', flag_xyfill=.true., fill_value=1.e30_r8, sampled_on_subcycle=.true.) call addfld('NR_IN_LH', (/ 'lev' /), 'I', 'm^-3', & - 'Num Rain Conc as input to SILHS') + 'Num Rain Conc as input to SILHS', sampled_on_subcycle=.true.) call addfld('SILHS_RTM', (/ 'ilev' /), 'I', 'kg/kg', & - 'Input total water mixing ratio') + 'Input total water mixing ratio', sampled_on_subcycle=.true.) call addfld('SILHS_THLM', (/ 'ilev' /), 'I', 'K', & - 'Input liquid water potential temperature') + 'Input liquid water potential temperature', sampled_on_subcycle=.true.) call addfld('SILHS_QC_IN', (/ 'lev' /), 'I', 'kg/kg', & - 'Input cloud water mixing ratio') + 'Input cloud water mixing ratio', sampled_on_subcycle=.true.) call addfld('SILHS_QI_IN', (/ 'lev' /), 'I', 'kg/kg', & - 'Input cloud ice mixing ratio') + 'Input cloud ice mixing ratio', sampled_on_subcycle=.true.) call addfld('SILHS_NC_IN', (/ 'lev' /), 'I', '#/kg', & - 'Input cloud water number concentration') + 'Input cloud water number concentration', sampled_on_subcycle=.true.) call addfld('SILHS_NI_IN', (/ 'lev' /), 'I', '#/kg', & - 'Input cloud ice number concentration') + 'Input cloud ice number concentration', sampled_on_subcycle=.true.) call addfld('AKM_CLUBB', (/ 'ilev' /), 'I', '(kg/kg)/s', & - 'Exact Kessler autoconversion') + 'Exact Kessler autoconversion', sampled_on_subcycle=.true.) call addfld('AKM_LH_CLUBB', (/ 'ilev' /), 'I', '(kg/kg)/s', & - 'Monte Carlo estimate of Kessler autoconversion') + 'Monte Carlo estimate of Kessler autoconversion', sampled_on_subcycle=.true.) call addfld('INVS_EXNER', (/ 'lev' /), 'I', 'none', & - 'inverse EXNER function from state in subcol_SILHS') + 'inverse EXNER function from state in subcol_SILHS', sampled_on_subcycle=.true.) call addfld('SILHS_ZTODT', horiz_only, 'I', 's', & - 'Length of Physics timestep (for debugging)') + 'Length of Physics timestep (for debugging)', sampled_on_subcycle=.true.) if ( subcol_SILHS_constrainmn ) then call addfld('SILHS_MSC_CLDICE', (/ 'lev' /), 'A', 'kg/kg', & - 'Mean Cloud Ice across subcolumns') + 'Mean Cloud Ice across subcolumns', sampled_on_subcycle=.true.) call addfld('SILHS_STDSC_CLDICE', (/ 'lev' /), 'A', 'kg/kg', & - 'Standard deviation of Ice across subcolumns') + 'Standard deviation of Ice across subcolumns', sampled_on_subcycle=.true.) if ( ixsnow > 0 ) then call addfld('SILHS_MSC_CLDLIQ', (/ 'lev' /), 'A', 'kg/kg', & - 'Mean Cloud Liquid across subcolumns') + 'Mean Cloud Liquid across subcolumns', sampled_on_subcycle=.true.) call addfld('SILHS_STDSC_CLDLIQ', (/ 'lev' /), 'A', 'kg/kg', & - 'Standard deviation of Liquid across subcolumns') + 'Standard deviation of Liquid across subcolumns', sampled_on_subcycle=.true.) call addfld('SILHS_MSC_Q', (/ 'lev' /), 'A', 'kg/kg', & - 'Mean water vapor across subcolumns') + 'Mean water vapor across subcolumns', sampled_on_subcycle=.true.) call addfld('SILHS_STDSC_Q', (/ 'lev' /), 'A', 'kg/kg', & - 'Standard deviation of water vapor across subcolumns') + 'Standard deviation of water vapor across subcolumns', sampled_on_subcycle=.true.) endif ! ixsnow > 0 endif ! subcol_SILHS_constrainmn call addfld('SILHS_EFF_CLDFRAC', (/ 'lev' /), 'A', 'frac', & - 'Calculated cloud fraction from subcolumn liq or ice') + 'Calculated cloud fraction from subcolumn liq or ice', sampled_on_subcycle=.true.) call addfld('SILHS_CLUBB_PRECIP_FRAC', (/ 'lev' /), 'A', 'frac', & - 'Precipitation fraction from CLUBB (set_up_pdf_params_incl_hydromet)') + 'Precipitation fraction from CLUBB (set_up_pdf_params_incl_hydromet)', sampled_on_subcycle=.true.) call addfld('SILHS_CLUBB_ICE_SS_FRAC', (/ 'lev' /), 'A', 'frac', & - 'Ice supersaturation fraction from CLUBB') - - call addfld ('QVHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Water vapor mixing ratio tendency from hole filling') - call addfld ('QCHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud water mixing ratio tendency from hole filling') - call addfld ('QRHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Rain water mixing ratio tendency from hole filling') - call addfld ('QIHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud ice mixing ratio tendency from hole filling') - call addfld ('QSHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Snow mixing ratio tendency from hole filling') - call addfld ('THFTEN', (/ 'lev' /), 'A', 'K/s', 'Temperature tendency from hole filling') + 'Ice supersaturation fraction from CLUBB', sampled_on_subcycle=.true.) + + call addfld ('QVHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Water vapor mixing ratio tendency from hole filling', sampled_on_subcycle=.true.) + call addfld ('QCHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud water mixing ratio tendency from hole filling', sampled_on_subcycle=.true.) + call addfld ('QRHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Rain water mixing ratio tendency from hole filling', sampled_on_subcycle=.true.) + call addfld ('QIHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud ice mixing ratio tendency from hole filling', sampled_on_subcycle=.true.) + call addfld ('QSHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Snow mixing ratio tendency from hole filling', sampled_on_subcycle=.true.) + call addfld ('THFTEN', (/ 'lev' /), 'A', 'K/s', 'Temperature tendency from hole filling', sampled_on_subcycle=.true.) #endif #endif From f820ab62a28ba9b9e39633e6a480af52d86c0776 Mon Sep 17 00:00:00 2001 From: peverwhee Date: Mon, 4 Nov 2024 15:30:33 -0700 Subject: [PATCH 45/82] remove "prev" argument for inst files; move open file logging to before pio call --- src/control/cam_history.F90 | 2 +- src/utils/cam_pio_utils.F90 | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/control/cam_history.F90 b/src/control/cam_history.F90 index d8346ec22f..81659ec12a 100644 --- a/src/control/cam_history.F90 +++ b/src/control/cam_history.F90 @@ -5738,7 +5738,7 @@ subroutine wshist (rgnht_in) inst_filename_spec = hfilename_spec(t) end if fname_inst = interpret_filename_spec( inst_filename_spec, number=(t-1), & - prev=prev, flag_spec='i' ) + flag_spec='i' ) end if ! ! Check that this new filename isn't the same as a previous or current filename diff --git a/src/utils/cam_pio_utils.F90 b/src/utils/cam_pio_utils.F90 index 350c421539..7fd58b13cd 100644 --- a/src/utils/cam_pio_utils.F90 +++ b/src/utils/cam_pio_utils.F90 @@ -1133,12 +1133,14 @@ subroutine cam_pio_openfile(file, fname, mode) integer :: ierr + if(pio_iotask_rank(pio_subsystem) == 0) then + write(iulog,*) 'Opening existing file ', trim(fname), file%fh + end if + ierr = pio_openfile(pio_subsystem, file, pio_iotype, fname, mode) if(ierr/= PIO_NOERR) then call endrun('Failed to open '//trim(fname)//' to read') - else if(pio_iotask_rank(pio_subsystem) == 0) then - write(iulog,*) 'Opened existing file ', trim(fname), file%fh end if end subroutine cam_pio_openfile From 03c0a0f8798ec46a439d8fccaec84774208dec0c Mon Sep 17 00:00:00 2001 From: peverwhee Date: Mon, 11 Nov 2024 13:44:43 -0700 Subject: [PATCH 46/82] initial changelog --- doc/ChangeLog | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index fdc0c4aa65..aad083f035 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,102 @@ =============================================================== +Tag name: cam6_4_047 +Originator(s): peverwhee +Date: 12 November 2024 +One-line Summary: History bugfixes +Github PR URL: https://github.com/ESCOMP/CAM/pull/1163 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): +- Issue #1149: cam history always chooses first averaging flag when using duplicate fields +- Issue #1150: CAM history erroneously overrides averaging flags for nhtfrq=1 +- Issue #1166: time_bounds array should not be present in history files containing instantaneous output +- Issue #1167: Time shown in history file names is incorrect for instantaneous data +- Issue #1183: Suggested improvement for openfile +- Updates git-fleximod to v0.9.2 + +Describe any changes made to build system: +M bld/namelist_files/use_cases/sd_waccm_sulfur.xml + - Remove bad XML comment line + +Describe any changes made to the namelist: none + +List any changes to the defaults for the boundary datasets: none + +Describe any substantial timing or memory changes: none + +Code reviewed by: brian-eaton + +List all files eliminated: none + +List all files added and what they do: none + +List all existing files that have been modified, and describe the changes: + +M .lib/git-fleximod/* + - updates to move git-fleximod to v0.9.2 + +M src/control/cam_history.F90 + - remove nhtfrq=1 accumulation flag override if sampled_on_subcyle=.true. + - modify list_index routine to optionally check for duplicates/compatibility + - endrun with message including all duplicates found (if flags differ) + - remove time_bounds from instantaneous history files + - override instantaneous file name for monthly files to include full timestep + - also report correct timestamp on inst. files (don't use prev timestamp as + in accumulated files) + +M src/control/cam_history_support.F90 + - add sampled_on_subcycle to field_info object + +M src/physics/cam/cam_diagnostics.F90 +M src/physics/cam/clubb_intr.F90 +M src/physics/cam/hetfrz_classnuc_cam.F90 +M src/physics/cam/macrop_driver.F90 +M src/physics/cam/micro_pumas_cam.F90 +M src/physics/cam/microp_aero.F90 +M src/physics/cam/ndrop.F90 +M src/physics/cam/ndrop_bam.F90 +M src/physics/cam/nucleate_ice_cam.F90 +M src/physics/cam/subcol_SILHS.F90 +M src/physics/cam7/micro_pumas_cam.F90 +M src/physics/cam7/stochastic_emulated_cam.F90 +M src/physics/cam7/stochastic_tau_cam.F90 + - add sampled_on_subcycle=.true. argument to addflds calls for history fields + that are outfld-ed in the macmic loop + +M src/utils/cam_pio_utils.F90 + - move filename logging to before pio call + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + +SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie (Overall: FAIL) +SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s (Overall: FAIL) + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + +ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s (Overall: FAIL) +SMS_Ld1.f09_f09_mg17.FCHIST_GC.derecho_intel.cam-outfrq1d (Overall: DIFF) + - pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 + +derecho/nvhpc/aux_cam: + +izumi/nag/aux_cam: + +DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) + - pre-existing failure -- issue #670 + +izumi/gnu/aux_cam: + +CAM tag used for the baseline comparison tests if different than previous +tag: + +Summarize any changes to answers: none + +=============================================================== + Tag name: cam6_4_046 Originator(s): sjsprecious Date: 06 November 2024 From b1a243ce649a5061d6f7d3c8b1d54092fc02f924 Mon Sep 17 00:00:00 2001 From: huebleruwm Date: Mon, 11 Nov 2024 16:18:28 -0700 Subject: [PATCH 47/82] Adding timer around all code in the do_rainturb option rather than just the function call. --- src/physics/cam/clubb_intr.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 6fa4fa2936..585dd328d6 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -3817,6 +3817,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if if ( do_rainturb ) then + call t_startf('clubb_tend_cam:do_rainturb') do k=1,nzm_clubb do i=1,ncol @@ -3824,14 +3825,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - call t_startf('clubb_tend_cam:update_xp2_mc_api') call update_xp2_mc_api( gr, nzm_clubb, ncol, dtime, cloud_frac_inout, & rcm_inout, rvm_in, thlm_in, wm_zt, & exner, pre_in, pdf_params_chnk(lchnk), & rtp2_mc_out, thlp2_mc_out, & wprtp_mc_out, wpthlp_mc_out, & rtpthlp_mc_out) - call t_stopf('clubb_tend_cam:update_xp2_mc_api') do k=1,nzm_clubb do i=1,ncol @@ -3845,6 +3844,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do + call t_stopf('clubb_tend_cam:do_rainturb') end if if (do_cldcool) then From cdcbea521b4d1319fa9ae116c1d3d3fa051c0e90 Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Tue, 12 Nov 2024 13:39:18 -0700 Subject: [PATCH 48/82] update archive_baseline script to modify read permissions on izumi --- test/system/archive_baseline.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/system/archive_baseline.sh b/test/system/archive_baseline.sh index f64561dc4d..ef836a8131 100755 --- a/test/system/archive_baseline.sh +++ b/test/system/archive_baseline.sh @@ -68,6 +68,7 @@ case $hostname in test_file_list="tests_pretag_izumi_${CAM_FC,,}" cam_tag=$1_${CAM_FC,,} baselinedir="/fs/cgd/csm/models/atm/cam/pretag_bl/$cam_tag" + chmod_cmd="chmod -R a+r ${baselinedir}" ;; de*) @@ -78,6 +79,7 @@ case $hostname in test_file_list="tests_pretag_derecho_${CAM_FC,,}" cam_tag=$1_${CAM_FC,,} baselinedir="/glade/campaign/cesm/community/amwg/cam_baselines/$cam_tag" + chmod_cmd="" ;; * ) echo "ERROR: machine $hostname not currently supported"; exit 1 ;; @@ -97,6 +99,7 @@ if [ -n "$CESM_TESTDIR" ]; then if [ -d $CESM_TESTDIR/baselines ]; then echo "Using cp to archive baselines." cp -r $CESM_TESTDIR/baselines/. $root_baselinedir/$cam_tag + eval ${chmod_cmd} else echo "Using bless_test_results to archive baselines." ../../cime/CIME/Tools/bless_test_results -p -t '' -c '' -r $CESM_TESTDIR --baseline-root $root_baselinedir -b $cam_tag -f -s From 7244285a9702f8ec99478bc5dc9d6991a634826a Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 18 Nov 2024 11:26:46 -0500 Subject: [PATCH 49/82] Update build issues; atmos_phys external to head of PR --- .gitmodules | 2 +- src/atmos_phys | 2 +- src/physics/cam/check_energy.F90 | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index 195d003bc2..c478c0c686 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,7 +36,7 @@ [submodule "atmos_phys"] path = src/atmos_phys url = https://github.com/jimmielin/atmospheric_physics - fxtag = 7b188e35 + fxtag = b1e2c2a9 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index 7b188e35fe..b1e2c2a9d1 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit 7b188e35fe26247289d3bdbbbdd902cde382765a +Subproject commit b1e2c2a9d188172f888b0b5c903c5a12a741f30e diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 774764c563..9fbc2d592c 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -814,6 +814,7 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & ncol = ncol, & pver = pver, & pcnst = pcnst, & + iulog = iulog, & q = state%q(1:ncol,1:pver,1:pcnst), & pdel = state%pdel(1:ncol,1:pver), & u = state%u(1:ncol,1:pver), & @@ -852,7 +853,7 @@ end subroutine check_energy_cam_chng ! Add heating rate required for global mean total energy conservation subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) use physics_types, only: physics_ptend, physics_ptend_init - use physconst, only: rga + use physconst, only: gravit ! SCAM support use scamMod, only: single_column, use_camiop, heat_glob_scm @@ -902,7 +903,7 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) ncol = ncol, & pver = pver, & pint = state%pint(:ncol,:), & - rga = rga, & + gravit = gravit, & heat_glob = heat_glob, & ptend_s = ptend%s(:ncol,:), & eshflx = eshflx(:ncol) & From e3e6a131208feaf72360d5fa5767ddf638ecc3c9 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 18 Nov 2024 11:52:16 -0500 Subject: [PATCH 50/82] Update check_energy_cam_fix interface --- src/physics/cam/check_energy.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 9fbc2d592c..592faeab00 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -872,6 +872,7 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) integer :: ncol ! number of atmospheric columns in chunk integer :: lchnk ! chunk number real(r8) :: heat_out(pcols) + character(len=64) :: dummy_scheme_name ! dumy scheme name for CCPP-ized scheme lchnk = state%lchnk ncol = state%ncol @@ -906,7 +907,8 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) gravit = gravit, & heat_glob = heat_glob, & ptend_s = ptend%s(:ncol,:), & - eshflx = eshflx(:ncol) & + eshflx = eshflx(:ncol), & + scheme_name = dummy_scheme_name ) end subroutine check_energy_cam_fix From a10a9557acc06679839e64682c9c3f5f4b96663b Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 18 Nov 2024 13:15:13 -0500 Subject: [PATCH 51/82] Update check_energy_cam_fix interface (2) --- src/physics/cam/check_energy.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 592faeab00..3f203bae2c 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -872,7 +872,7 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) integer :: ncol ! number of atmospheric columns in chunk integer :: lchnk ! chunk number real(r8) :: heat_out(pcols) - character(len=64) :: dummy_scheme_name ! dumy scheme name for CCPP-ized scheme + character(len=64) :: dummy_scheme_name ! dummy scheme name for CCPP-ized scheme lchnk = state%lchnk ncol = state%ncol @@ -908,7 +908,7 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) heat_glob = heat_glob, & ptend_s = ptend%s(:ncol,:), & eshflx = eshflx(:ncol), & - scheme_name = dummy_scheme_name + scheme_name = dummy_scheme_name & ) end subroutine check_energy_cam_fix From 902c495ebb7ec85b107ed7cba8bf003136b9ca04 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 19 Nov 2024 12:26:51 -0500 Subject: [PATCH 52/82] Update atmos_phys to atmos_phys0_07_000 --- .gitmodules | 4 ++-- src/atmos_phys | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index c478c0c686..40e189dab5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -35,8 +35,8 @@ [submodule "atmos_phys"] path = src/atmos_phys - url = https://github.com/jimmielin/atmospheric_physics - fxtag = b1e2c2a9 + url = https://github.com/ESCOMP/atmospheric_physics + fxtag = atmos_phys0_07_000 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index b1e2c2a9d1..e10f81151e 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit b1e2c2a9d188172f888b0b5c903c5a12a741f30e +Subproject commit e10f81151ecef5416462472ef0e52810dc82e412 From a9441a893bbaa2db6eb15087c13edc4ec7ff2348 Mon Sep 17 00:00:00 2001 From: peverwhee Date: Wed, 20 Nov 2024 09:37:50 -0700 Subject: [PATCH 53/82] update git-fleximod to 0.9.3 --- .lib/git-fleximod/git_fleximod/cli.py | 38 ++++++++++--------- .../git-fleximod/git_fleximod/git_fleximod.py | 2 +- .lib/git-fleximod/git_fleximod/submodule.py | 2 +- .lib/git-fleximod/poetry.lock | 6 +-- .lib/git-fleximod/pyproject.toml | 2 +- .lib/git-fleximod/tbump.toml | 2 +- .lib/git-fleximod/tests/conftest.py | 4 +- doc/ChangeLog | 10 +++-- test/system/archive_baseline.sh | 4 +- 9 files changed, 38 insertions(+), 32 deletions(-) diff --git a/.lib/git-fleximod/git_fleximod/cli.py b/.lib/git-fleximod/git_fleximod/cli.py index 208bc04684..ac9493cfc3 100644 --- a/.lib/git-fleximod/git_fleximod/cli.py +++ b/.lib/git-fleximod/git_fleximod/cli.py @@ -2,27 +2,31 @@ import argparse from git_fleximod import utils -__version__ = "0.9.2" +__version__ = "0.9.3" def find_root_dir(filename=".gitmodules"): """ finds the highest directory in tree which contains a file called filename """ - d = Path.cwd() - root = Path(d.root) - dirlist = [] - dl = d - while dl != root: - dirlist.append(dl) - dl = dl.parent - dirlist.append(root) - dirlist.reverse() - - for dl in dirlist: - attempt = dl / filename - if attempt.is_file(): - return str(dl) - return None - + try: + root = utils.execute_subprocess(["git","rev-parse", "--show-toplevel"], + output_to_caller=True ).rstrip() + except: + d = Path.cwd() + root = Path(d.root) + dirlist = [] + dl = d + while dl != root: + dirlist.append(dl) + dl = dl.parent + dirlist.append(root) + dirlist.reverse() + + for dl in dirlist: + attempt = dl / filename + if attempt.is_file(): + return str(dl) + return None + return Path(root) def get_parser(): description = """ diff --git a/.lib/git-fleximod/git_fleximod/git_fleximod.py b/.lib/git-fleximod/git_fleximod/git_fleximod.py index 0851e9d095..13f35df959 100755 --- a/.lib/git-fleximod/git_fleximod/git_fleximod.py +++ b/.lib/git-fleximod/git_fleximod/git_fleximod.py @@ -342,7 +342,7 @@ def main(): excludelist=excludelist, ) if not gitmodules.sections(): - sys.exit("No submodule components found") + sys.exit(f"No submodule components found, root_dir={root_dir}") retval = 0 if action == "update": submodules_update(gitmodules, root_dir, fxrequired, force) diff --git a/.lib/git-fleximod/git_fleximod/submodule.py b/.lib/git-fleximod/git_fleximod/submodule.py index c939d54bc9..75d9dd4eb9 100644 --- a/.lib/git-fleximod/git_fleximod/submodule.py +++ b/.lib/git-fleximod/git_fleximod/submodule.py @@ -221,7 +221,7 @@ def sparse_checkout(self): if superroot: gitroot = superroot.strip() else: - gitroot = self.root_dir.strip() + gitroot = self.root_dir # Now need to move the .git dir to the submodule location rootdotgit = os.path.join(self.root_dir, ".git") while os.path.isfile(rootdotgit): diff --git a/.lib/git-fleximod/poetry.lock b/.lib/git-fleximod/poetry.lock index 3a74effcd1..ac82fb0d97 100644 --- a/.lib/git-fleximod/poetry.lock +++ b/.lib/git-fleximod/poetry.lock @@ -30,13 +30,13 @@ dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] [[package]] name = "certifi" -version = "2024.6.2" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, - {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] [[package]] diff --git a/.lib/git-fleximod/pyproject.toml b/.lib/git-fleximod/pyproject.toml index 619cdabe3b..1d0419ad20 100644 --- a/.lib/git-fleximod/pyproject.toml +++ b/.lib/git-fleximod/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "git-fleximod" -version = "0.9.2" +version = "0.9.3" description = "Extended support for git-submodule and git-sparse-checkout" authors = ["Jim Edwards "] maintainers = ["Jim Edwards "] diff --git a/.lib/git-fleximod/tbump.toml b/.lib/git-fleximod/tbump.toml index 920ff0591c..b432206a54 100644 --- a/.lib/git-fleximod/tbump.toml +++ b/.lib/git-fleximod/tbump.toml @@ -2,7 +2,7 @@ github_url = "https://github.com/jedwards4b/git-fleximod/" [version] -current = "0.9.2" +current = "0.9.3" # Example of a semver regexp. # Make sure this matches current_version before diff --git a/.lib/git-fleximod/tests/conftest.py b/.lib/git-fleximod/tests/conftest.py index 81edbe713e..1dd1b86f34 100644 --- a/.lib/git-fleximod/tests/conftest.py +++ b/.lib/git-fleximod/tests/conftest.py @@ -32,7 +32,7 @@ def logger(): "submodule_name": "test_optional", "status1" : "test_optional MPIserial_2.5.0-3-gd82ce7c is out of sync with .gitmodules MPIserial_2.4.0", "status2" : "test_optional at tag MPIserial_2.4.0", - "status3" : "test_optional not checked out, out of sync at tag None, expected tag is MPIserial_2.4.0 (optional)", + "status3" : "test_optional not checked out, out of sync at tag MPIserial_2.5.1, expected tag is MPIserial_2.4.0 (optional)", "status4" : "test_optional at tag MPIserial_2.4.0", "gitmodules_content": """ [submodule "test_optional"] @@ -46,7 +46,7 @@ def logger(): "submodule_name": "test_alwaysoptional", "status1" : "test_alwaysoptional MPIserial_2.3.0 is out of sync with .gitmodules e5cf35c", "status2" : "test_alwaysoptional at hash e5cf35c", - "status3" : "out of sync at tag None, expected tag is e5cf35c", + "status3" : "out of sync at tag MPIserial_2.5.1, expected tag is e5cf35c", "status4" : "test_alwaysoptional at hash e5cf35c", "gitmodules_content": """ [submodule "test_alwaysoptional"] diff --git a/doc/ChangeLog b/doc/ChangeLog index aad083f035..ef811a5bc6 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,8 +1,8 @@ =============================================================== -Tag name: cam6_4_047 +Tag name: cam6_4_049 Originator(s): peverwhee -Date: 12 November 2024 +Date: November 2024 One-line Summary: History bugfixes Github PR URL: https://github.com/ESCOMP/CAM/pull/1163 @@ -12,7 +12,8 @@ Purpose of changes (include the issue number and title text for each relevant Gi - Issue #1166: time_bounds array should not be present in history files containing instantaneous output - Issue #1167: Time shown in history file names is incorrect for instantaneous data - Issue #1183: Suggested improvement for openfile -- Updates git-fleximod to v0.9.2 +- Update git-fleximod to v0.9.3 +- Update archive_baseline.sh modify read permissions on izumi Describe any changes made to build system: M bld/namelist_files/use_cases/sd_waccm_sulfur.xml @@ -66,6 +67,9 @@ M src/physics/cam7/stochastic_tau_cam.F90 M src/utils/cam_pio_utils.F90 - move filename logging to before pio call +M test/system/archive_baseline.sh + - make all baseline files globally readable on izumi + If there were any failures reported from running test_driver.sh on any test platform, and checkin with these failures has been OK'd by the gatekeeper, then copy the lines from the td.*.status files for the failed tests to the diff --git a/test/system/archive_baseline.sh b/test/system/archive_baseline.sh index ef836a8131..99a1003fb0 100755 --- a/test/system/archive_baseline.sh +++ b/test/system/archive_baseline.sh @@ -68,7 +68,6 @@ case $hostname in test_file_list="tests_pretag_izumi_${CAM_FC,,}" cam_tag=$1_${CAM_FC,,} baselinedir="/fs/cgd/csm/models/atm/cam/pretag_bl/$cam_tag" - chmod_cmd="chmod -R a+r ${baselinedir}" ;; de*) @@ -79,7 +78,6 @@ case $hostname in test_file_list="tests_pretag_derecho_${CAM_FC,,}" cam_tag=$1_${CAM_FC,,} baselinedir="/glade/campaign/cesm/community/amwg/cam_baselines/$cam_tag" - chmod_cmd="" ;; * ) echo "ERROR: machine $hostname not currently supported"; exit 1 ;; @@ -99,7 +97,7 @@ if [ -n "$CESM_TESTDIR" ]; then if [ -d $CESM_TESTDIR/baselines ]; then echo "Using cp to archive baselines." cp -r $CESM_TESTDIR/baselines/. $root_baselinedir/$cam_tag - eval ${chmod_cmd} + chmod -R a+r ${baselinedir} else echo "Using bless_test_results to archive baselines." ../../cime/CIME/Tools/bless_test_results -p -t '' -c '' -r $CESM_TESTDIR --baseline-root $root_baselinedir -b $cam_tag -f -s From bc5428f4eaaf55641176b61034a1a71363a943cd Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Wed, 20 Nov 2024 21:41:42 -0500 Subject: [PATCH 54/82] Address review comments --- src/control/cam_snapshot_common.F90 | 2 ++ src/physics/cam/check_energy.F90 | 15 +++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/control/cam_snapshot_common.F90 b/src/control/cam_snapshot_common.F90 index fa558b3ad2..0f49d27a02 100644 --- a/src/control/cam_snapshot_common.F90 +++ b/src/control/cam_snapshot_common.F90 @@ -848,6 +848,8 @@ subroutine state_snapshot_all_outfld(lchnk, file_num, state) call outfld(state_snapshot(i)%standard_name, state%te_cur(:, dyn_te_idx), pcols, lchnk) case ('air_composition_cp_or_cv_dycore') + ! this field is not part of physics state (it is in air_composition) + ! but describes the atmospheric thermodynamic state and thus saved within the snapshot call outfld(state_snapshot(i)%standard_name, cp_or_cv_dycore(:,:,lchnk), pcols, lchnk) case default diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 3f203bae2c..5350371cef 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -461,6 +461,9 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) lchnk = state%lchnk ncol = state%ncol + ! The "vertical coordinate" parameter is equivalent to the dynamical core + ! energy formula parameter, which controls the dycore energy formula used + ! by get_hydrostatic_energy. if (present(vc)) then vc_loc = vc else @@ -758,11 +761,11 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & type(physics_tend ), intent(inout) :: tend character*(*),intent(in) :: name ! parameterization name for fluxes integer , intent(in) :: nstep ! current timestep number - real(r8), intent(in) :: ztodt ! 2 delta t (model time increment) - real(r8), intent(in) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) - real(r8), intent(in) :: flx_cnd(:) ! (pcols) -boundary flux of liquid+ice (m/s) (precip?) - real(r8), intent(in) :: flx_ice(:) ! (pcols) -boundary flux of ice (m/s) (snow?) - real(r8), intent(in) :: flx_sen(:) ! (pcols) -boundary flux of sensible heat (w/m2) + real(r8), intent(in) :: ztodt ! physics timestep (s) + real(r8), intent(in) :: flx_vap(:) ! (pcols) - boundary flux of vapor (kg/m2/s) + real(r8), intent(in) :: flx_cnd(:) ! (pcols) - boundary flux of lwe liquid+ice (m/s) + real(r8), intent(in) :: flx_ice(:) ! (pcols) - boundary flux of lwe ice (m/s) + real(r8), intent(in) :: flx_sen(:) ! (pcols) - boundary flux of sensible heat (W/m2) integer :: lchnk ! chunk identifier integer :: ncol ! number of atmospheric columns @@ -785,7 +788,7 @@ subroutine check_energy_cam_chng(state, tend, name, nstep, ztodt, & scaling_dycore(:ncol,:) = cpairv(:ncol,:,lchnk)/local_cp_or_cv_dycore(:ncol,:) ! cp/cv scaling endif - elseif(state%psetcols > pcols) then + else if(state%psetcols > pcols) then ! Subcolumns if(.not. all(cpairv(:,:,:) == cpair)) then call endrun('check_energy_chng: cpairv is not allowed to vary when subcolumns are turned on') From c0b9d8bc47d2a7b658d1b45a31e723f5ca7055a3 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Thu, 21 Nov 2024 08:51:05 -0500 Subject: [PATCH 55/82] Update comment for tot_energy_phys vc parameter --- src/physics/cam/check_energy.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 5350371cef..7af3a32bda 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -425,7 +425,7 @@ subroutine tot_energy_phys(state, outfld_name_suffix,vc) type(physics_state), intent(inout) :: state character(len=*), intent(in) :: outfld_name_suffix ! suffix for "outfld" - integer, optional, intent(in) :: vc ! vertical coordinate + integer, optional, intent(in) :: vc ! vertical coordinate (controls energy formula to use) !---------------------------Local storage------------------------------- real(r8) :: se(pcols) ! Dry Static energy (J/m2) From 99db7405c90e422df5049c5ee8364c43b7071884 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Tue, 3 Dec 2024 14:20:34 -0700 Subject: [PATCH 56/82] Rename AOAMF as AOA1 and output updated MMR in _tend routine M src/physics/cam/aoa_tracers.F90 --- src/physics/cam/aoa_tracers.F90 | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/physics/cam/aoa_tracers.F90 b/src/physics/cam/aoa_tracers.F90 index f0c272b69d..fc656ad618 100644 --- a/src/physics/cam/aoa_tracers.F90 +++ b/src/physics/cam/aoa_tracers.F90 @@ -31,7 +31,7 @@ module aoa_tracers integer, parameter :: ncnst=3 ! number of constituents implemented by this module ! constituent names - character(len=6), parameter :: c_names(ncnst) = (/'AOAMF ', 'HORZ ', 'VERT '/) + character(len=4), parameter :: c_names(ncnst) = (/'AOA1', 'HORZ', 'VERT'/) ! constituent source/sink names character(len=8), parameter :: src_names(ncnst) = (/'AOAMFSRC', 'HORZSRC ', 'VERTSRC '/) @@ -132,12 +132,12 @@ subroutine aoa_tracers_register if (.not. aoa_tracers_flag) return call cnst_add(c_names(1), mwdry, cpair, 0._r8, ixaoa, readiv=aoa_read_from_ic_file, & - longname='mixing ratio LB tracer') + longname='mixing ratio LB tracer', cam_outfld=.false.) call cnst_add(c_names(2), mwdry, cpair, 1._r8, ixht, readiv=aoa_read_from_ic_file, & - longname='horizontal tracer') + longname='horizontal tracer', cam_outfld=.false.) call cnst_add(c_names(3), mwdry, cpair, 0._r8, ixvt, readiv=aoa_read_from_ic_file, & - longname='vertical tracer') + longname='vertical tracer', cam_outfld=.false.) ifirst = ixaoa @@ -324,6 +324,8 @@ subroutine aoa_tracers_timestep_tend(state, ptend, dt) real(r8), parameter :: mmr0 = 1.0e-6_r8 ! initial lower boundary mmr real(r8), parameter :: per_yr = 0.02_r8 ! fractional increase per year + real(r8) :: mmr_out(pcols,pver,ncnst) + !------------------------------------------------------------------ teul = .5_r8*dt/(86400._r8 * treldays) ! 1/2 for the semi-implicit scheme if dt=time step @@ -371,6 +373,15 @@ subroutine aoa_tracers_timestep_tend(state, ptend, dt) call outfld (src_names(2), ptend%q(:,:,ixht), pcols, lchnk) call outfld (src_names(3), ptend%q(:,:,ixvt), pcols, lchnk) + ! output mixing ratios to history + mmr_out(:ncol,:,1) = state%q(:ncol,:,ixaoa) + dt*ptend%q(1:ncol,:,ixaoa) + mmr_out(:ncol,:,2) = state%q(:ncol,:,ixht) + dt*ptend%q(1:ncol,:,ixht) + mmr_out(:ncol,:,3) = state%q(:ncol,:,ixvt) + dt*ptend%q(1:ncol,:,ixvt) + + call outfld (c_names(1), mmr_out(:,:,1), pcols, lchnk) + call outfld (c_names(2), mmr_out(:,:,2), pcols, lchnk) + call outfld (c_names(3), mmr_out(:,:,3), pcols, lchnk) + end subroutine aoa_tracers_timestep_tend !=========================================================================== From 0624476ba64efc98aa54789d9b1bb23d8be831ae Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Wed, 4 Dec 2024 10:53:28 -0700 Subject: [PATCH 57/82] changes to use carma4_09 base --- .gitmodules | 2 +- cime_config/config_pes.xml | 16 +- cime_config/testdefs/testlist_cam.xml | 20 +- .../testmods_dirs/cam/carma_dust/user_nl_cam | 1 - .../cam/carma_meteor_impact/user_nl_cam | 1 - .../cam/carma_meteor_smoke/user_nl_cam | 1 - .../cam/carma_mixed_sulfate/user_nl_cam | 1 - .../testmods_dirs/cam/carma_pmc/user_nl_cam | 1 - .../cam/carma_sea_salt/user_nl_cam | 1 - .../cam/carma_sulfate/user_nl_cam | 1 - .../cam/carma_test_growth/user_nl_cam | 1 - .../cam/carma_test_passive/user_nl_cam | 1 - .../cam/carma_test_radiative/user_nl_cam | 1 - .../cam/carma_test_swelling/user_nl_cam | 1 - .../cam/carma_test_tracers/user_nl_cam | 1 - .../cam/carma_test_tracers2/user_nl_cam | 1 - src/physics/cam/carma_flags_mod.F90 | 236 +-- src/physics/cam/carma_intr.F90 | 48 +- src/physics/cam/physpkg.F90 | 4 +- src/physics/cam7/physpkg.F90 | 4 +- src/physics/carma/base | 2 +- src/physics/carma/cam/carma_constants_mod.F90 | 9 +- src/physics/carma/cam/carma_intr.F90 | 1417 +++++++++++------ src/physics/carma/cam/carma_precision_mod.F90 | 2 +- .../carma/models/bc_strat/carma_model_mod.F90 | 2 +- .../carma/models/cirrus/carma_model_mod.F90 | 10 +- src/physics/carma/models/cirrus/growevapl.F90 | 2 +- .../carma/models/cirrus_dust/carma_mod.F90 | 2 +- .../models/cirrus_dust/carma_model_mod.F90 | 14 +- .../carma/models/cirrus_dust/growevapl.F90 | 2 +- .../carma/models/dust/carma_model_mod.F90 | 231 ++- .../meteor_impact/carma_model_flags_mod.F90 | 20 +- .../models/meteor_impact/carma_model_mod.F90 | 275 +++- .../models/meteor_smoke/carma_model_mod.F90 | 237 ++- .../models/mixed_sulfate/carma_model_mod.F90 | 257 ++- .../carma/models/pmc/carma_model_mod.F90 | 263 ++- .../models/pmc_sulfate/carma_model_mod.F90 | 10 +- .../carma/models/sea_salt/carma_model_mod.F90 | 235 ++- .../carma/models/sulfate/carma_model_mod.F90 | 192 ++- .../models/test_detrain/carma_model_mod.F90 | 2 +- .../models/test_growth/carma_model_mod.F90 | 235 ++- .../models/test_passive/carma_model_mod.F90 | 196 ++- .../models/test_radiative/carma_model_mod.F90 | 203 ++- .../models/test_swelling/carma_model_mod.F90 | 202 ++- .../models/test_tracers/carma_model_mod.F90 | 215 ++- .../models/test_tracers2/carma_model_mod.F90 | 219 ++- .../carma/models/tholin/carma_model_mod.F90 | 8 +- test/system/TR8.sh | 4 + 48 files changed, 3620 insertions(+), 1189 deletions(-) diff --git a/.gitmodules b/.gitmodules index 817bb1ff6b..9e0fa05361 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,7 +9,7 @@ path = src/physics/carma/base url = https://github.com/ESCOMP/CARMA_base.git fxrequired = AlwaysRequired - fxtag = carma4_01 + fxtag = carma4_09 fxDONOTUSEurl = https://github.com/ESCOMP/CARMA_base.git [submodule "pumas"] diff --git a/cime_config/config_pes.xml b/cime_config/config_pes.xml index f488c21b27..47bbcc4af3 100644 --- a/cime_config/config_pes.xml +++ b/cime_config/config_pes.xml @@ -1678,14 +1678,14 @@ none - 36 - 36 - 36 - 36 - 36 - 36 - 36 - 36 + 32 + 32 + 32 + 32 + 32 + 32 + 32 + 32 1 diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index c95f004d25..2801e231f7 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -582,6 +582,7 @@ + @@ -602,6 +603,7 @@ + @@ -625,6 +627,7 @@ + @@ -636,6 +639,7 @@ + @@ -691,6 +695,7 @@ + @@ -767,18 +772,10 @@ - - - - - - - - - + @@ -799,6 +796,7 @@ + @@ -809,6 +807,7 @@ + @@ -829,6 +828,7 @@ + @@ -839,6 +839,7 @@ + @@ -859,6 +860,7 @@ + diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam index cfac3a4818..9893ae9a9e 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam @@ -6,4 +6,3 @@ pbuf_global_allocate=.false. history_carma=.true. fincl2 = 'CRSLERFC' carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam index 36487d1f35..ca4ea707ef 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam @@ -5,7 +5,6 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" solar_data_type='FIXED' solar_data_ymd=20000101 carma_emis_maxlat = 40. diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam index f69245ce24..2a81a976e2 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam @@ -5,7 +5,6 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" solar_data_type='FIXED' solar_data_ymd=20000101 diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam index 52b192f861..d292329b4c 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam @@ -5,7 +5,6 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" flbc_list = 'CCL4', 'CF2CLBR', 'CF3BR', 'CFC11', 'CFC113', 'CFC12', 'CH3BR', 'CH3CCL3', 'CH3CL', 'CH4', 'CO2', 'H2', 'HCFC22', 'N2O', 'OCS' solar_data_type='FIXED' diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam index b40ad17f97..3ec29d7308 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam @@ -6,4 +6,3 @@ pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. carma_do_partialinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam index cfc4580f54..e3a93951a0 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam @@ -5,7 +5,6 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" flbc_list = 'CCL4', 'CF2CLBR', 'CF3BR', 'CFC11', 'CFC113', 'CFC12', 'CH3BR', 'CH3CCL3', 'CH3CL', 'CH4', 'CO2', 'H2', 'HCFC22', 'N2O', 'OCS' solar_data_type='FIXED' diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam index 377cbb2295..bb1512a995 100644 --- a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam +++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam @@ -5,4 +5,3 @@ inithist='ENDOFRUN' pbuf_global_allocate=.false. history_carma=.true. carma_do_fixedinit=.false. -carma_reftfile="camrun.cam.r.carma_reft.nc" diff --git a/src/physics/cam/carma_flags_mod.F90 b/src/physics/cam/carma_flags_mod.F90 index 59fee48bf3..e583b43d90 100644 --- a/src/physics/cam/carma_flags_mod.F90 +++ b/src/physics/cam/carma_flags_mod.F90 @@ -11,8 +11,13 @@ module carma_flags_mod use spmd_utils, only: masterproc ! Flags for integration with CAM Microphysics - public carma_readnl ! read the carma namelist - + + implicit none + public + + integer, parameter :: carma_maxdiags = 100 + integer, protected :: carma_ndiagpkgs ! Number of diags_packages listed + integer, protected :: carma_ndebugpkgs ! Number of diags_packages listed ! Namelist flags ! @@ -20,45 +25,53 @@ module carma_flags_mod ! calculations, but it will still initialize itself. This allows the same build and ! namelist to be used, but the CARMA processing diabled. Use the configure option ! -carma none to totally disable CARMA and prevent even the register from happening. - logical, public :: carma_flag = .false. ! If .true. then turn on CARMA microphysics in CAM - logical, public :: carma_do_aerosol = .true. ! If .true. then CARMA is processed after surface coupling - logical, public :: carma_do_cldice = .false. ! If .true. then do cloud ice - logical, public :: carma_do_cldliq = .false. ! If .true. then do cloud liquid - logical, public :: carma_do_clearsky = .false. ! If .true. then do clear sky particle calculations - logical, public :: carma_do_coag = .false. ! If .true. then do coagulation - logical, public :: carma_do_detrain = .false. ! If .true. then do detrain - logical, public :: carma_do_drydep = .false. ! If .true. then do dry deposition - logical, public :: carma_do_emission = .false. ! If .true. then do emission - logical, public :: carma_do_fixedinit= .false. ! If .true. then do fixed initialization to a reference state - logical, public :: carma_hetchem_feedback= .false.! If .true. then CARMA sulfate surface area density used in heterogeneous chemistry - logical, public :: carma_rad_feedback= .false. ! If .true. then CARMA sulfate mass mixing ratio & effective radius used in radiation - logical, public :: carma_do_explised = .false. ! If .true. then do sedimentation with substepping - logical, public :: carma_do_incloud = .false. ! If .true. then do incloud particle calculations - logical, public :: carma_do_grow = .false. ! If .true. then do growth - logical, public :: carma_do_optics = .false. ! If .true. then do optical properties file - logical, public :: carma_do_partialinit= .false. ! If .true. then do initialization of coagulation to a reference state (requires fixedinit) - logical, public :: carma_do_pheat = .false. ! If .true. then do particle heating - logical, public :: carma_do_pheatatm = .false. ! If .true. then do particle heating of atmosphere - logical, public :: carma_do_substep = .false. ! If .true. then do substeping - logical, public :: carma_do_thermo = .false. ! If .true. then do solve thermodynamics equation - logical, public :: carma_do_wetdep = .false. ! If .true. then do wet deposition - logical, public :: carma_do_vdiff = .false. ! If .true. then do vertical brownian diffusion - logical, public :: carma_do_vtran = .false. ! If .true. then do vertical transport - integer, public :: carma_maxsubsteps = 1 ! Maximum number of time substeps allowed - integer, public :: carma_minsubsteps = 1 ! Minimum number of time substeps allowed - integer, public :: carma_maxretries = 8 ! Maximum number of time substeps allowed - real(r8), public :: carma_conmax = 0.1_r8 ! Minumum relative concentration to consider in substep - real(r8), public :: carma_dgc_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas concentration allowed per substep. - real(r8), public :: carma_ds_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas saturation allowed per substep. - real(r8), public :: carma_dt_threshold = 0.0_r8 ! When non-zero, the largest change in temperature (K) allowed per substep. - real(r8), public :: carma_tstick = 1.0_r8 ! Thermal accommodation coefficient - real(r8), public :: carma_gsticki = 0.93_r8 ! Growth accommodation coefficient for ice - real(r8), public :: carma_gstickl = 1.0_r8 ! Growth accommodation coefficient for liquid - real(r8), public :: carma_cstick = 1.0_r8 ! Coagulation accommodation coefficient - real(r8), public :: carma_rhcrit = 1.0_r8 ! Critical relative humidity for liquid clouds - real(r8), public :: carma_vf_const = 0.0_r8 ! If specified and non-zero, constant fall velocity for all particles [cm/s] - character(len=256), public :: carma_reftfile = 'carma_reft.nc' ! path to the file containing the reference temperature profile - character(len=32), public :: carma_model = "none" ! String (no spaces) that identifies the model + logical, protected :: carma_flag = .false. ! If .true. then turn on CARMA microphysics in CAM + logical, protected :: carma_do_aerosol = .true. ! If .true. then CARMA is processed after surface coupling + logical, protected :: carma_do_coremasscheck = .false. ! If .true. then do coremasscheck and abort model after certain subroutines + logical, protected :: carma_do_cldice = .false. ! If .true. then do cloud ice + logical, protected :: carma_do_cldliq = .false. ! If .true. then do cloud liquid + logical, protected :: carma_do_clearsky = .false. ! If .true. then do clear sky particle calculations + logical, protected :: carma_do_cloudborne = .false. ! If .true. then do then the carma groups can be cloudborne + logical, protected :: carma_do_coag = .false. ! If .true. then do coagulation + logical, protected :: carma_do_detrain = .false. ! If .true. then do detrain + logical, protected :: carma_do_drydep = .false. ! If .true. then do dry deposition + logical, protected :: carma_do_emission = .false. ! If .true. then do emission + logical, protected :: carma_do_fixedinit= .false. ! If .true. then do fixed initialization to a reference state + logical, protected :: carma_hetchem_feedback=.false.! If .true. then CARMA sulfate surface area density used in heterogeneous chemistry + logical, protected :: carma_rad_feedback= .false. ! If .true. then CARMA sulfate mass mixing ratio & effective radius used in radiation + logical, protected :: carma_do_explised = .false. ! If .true. then do sedimentation with substepping + logical, protected :: carma_do_incloud = .false. ! If .true. then do incloud particle calculations + logical, protected :: carma_do_budget_diags = .false. ! If .true. then do budget diagnostics + logical, protected :: carma_do_package_diags = .false. ! If .true. then do package diagnostics + logical, protected :: carma_do_grow = .false. ! If .true. then do growth + logical, protected :: carma_do_optics = .false. ! If .true. then do optical properties file + logical, protected :: carma_do_partialinit= .false. ! If .true. then do initialization of coagulation to a reference state (requires fixedinit) + logical, protected :: carma_do_pheat = .false. ! If .true. then do particle heating + logical, protected :: carma_do_pheatatm = .false. ! If .true. then do particle heating of atmosphere + logical, protected :: carma_do_substep = .false. ! If .true. then do substeping + logical, protected :: carma_do_thermo = .false. ! If .true. then do solve thermodynamics equation + logical, protected :: carma_do_wetdep = .false. ! If .true. then do wet deposition + logical, protected :: carma_do_vdiff = .false. ! If .true. then do vertical brownian diffusion + logical, protected :: carma_do_vtran = .false. ! If .true. then do vertical transport + integer, protected :: carma_diags_file = 0 ! Default file for diagnostic output + integer, protected :: carma_maxsubsteps = 1 ! Maximum number of time substeps allowed + integer, protected :: carma_minsubsteps = 1 ! Minimum number of time substeps allowed + integer, protected :: carma_maxretries = 8 ! Maximum number of time substeps allowed + real(r8), protected :: carma_conmax = 0.1_r8 ! Minumum relative concentration to consider in substep + real(r8), protected :: carma_dgc_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas concentration allowed per substep. + real(r8), protected :: carma_ds_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas saturation allowed per substep. + real(r8), protected :: carma_dt_threshold = 0.0_r8 ! When non-zero, the largest change in temperature (K) allowed per substep. + real(r8), protected :: carma_tstick = 1.0_r8 ! Thermal accommodation coefficient + real(r8), protected :: carma_gsticki = 0.93_r8 ! Growth accommodation coefficient for ice + real(r8), protected :: carma_gstickl = 1.0_r8 ! Growth accommodation coefficient for liquid + real(r8), protected :: carma_cstick = 1.0_r8 ! Coagulation accommodation coefficient + real(r8), protected :: carma_rhcrit = 1.0_r8 ! Critical relative humidity for liquid clouds + real(r8), protected :: carma_vf_const = 0.0_r8 ! If specified and non-zero, constant fall velocity for all particles [cm/s] + character(len=32), protected :: carma_model = "none" ! String (no spaces) that identifies the model + character(len=10), protected :: carma_sulfnuc_method = "none" ! Sulfate Nucleation method + character(len=32), protected :: carma_diags_packages(carma_maxdiags) = " " ! Names of physics packages for which diagnostic output is desired + character(len=12), protected :: carma_debug_packages(carma_maxdiags) = " " ! Names of physics packages for which debug output is desired + contains @@ -68,30 +81,31 @@ module carma_flags_mod !! @author Chuck Bardeen !! @version Aug-2010 subroutine carma_readnl(nlfile) - + ! Read carma namelist group. - + use cam_abortutils, only: endrun use namelist_utils, only: find_group_name - use units, only: getunit, freeunit - use mpishorthand + use spmd_utils, only: mpicom, masterprocid, mpi_real8, mpi_integer, mpi_logical, mpi_character use carma_model_flags_mod, only: carma_model_readnl - + ! args - + character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input - + ! local vars - - integer :: unitn, ierr - + + integer :: unitn, ierr, i + ! read namelist for CARMA namelist /carma_nl/ & carma_flag, & carma_do_aerosol, & + carma_do_coremasscheck, & carma_do_cldliq, & carma_do_cldice, & carma_do_clearsky, & + carma_do_cloudborne, & carma_do_coag, & carma_do_detrain, & carma_do_drydep, & @@ -115,7 +129,6 @@ subroutine carma_readnl(nlfile) carma_minsubsteps, & carma_maxretries, & carma_model, & - carma_reftfile, & carma_conmax, & carma_dgc_threshold, & carma_ds_threshold, & @@ -125,11 +138,16 @@ subroutine carma_readnl(nlfile) carma_gstickl, & carma_cstick, & carma_rhcrit, & - carma_vf_const - + carma_vf_const, & + carma_sulfnuc_method, & + carma_do_budget_diags, & + carma_do_package_diags, & + carma_diags_packages, & + carma_debug_packages, & + carma_diags_file + if (masterproc) then - unitn = getunit() - open( unitn, file=trim(nlfile), status='old' ) + open( newunit=unitn, file=trim(nlfile), status='old' ) call find_group_name(unitn, 'carma_nl', status=ierr) if (ierr == 0) then read(unitn, carma_nl, iostat=ierr) @@ -138,54 +156,72 @@ subroutine carma_readnl(nlfile) end if end if close(unitn) - call freeunit(unitn) end if - -#ifdef SPMD - call mpibcast (carma_flag, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_aerosol, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_cldliq, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_cldice, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_clearsky, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_coag, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_detrain, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_drydep, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_emission, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_fixedinit, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_hetchem_feedback,1 ,mpilog, 0,mpicom) - call mpibcast (carma_rad_feedback, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_explised, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_incloud, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_grow, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_optics, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_partialinit, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_pheat, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_pheatatm, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_substep, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_thermo, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_wetdep, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_vdiff, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_do_vtran, 1 ,mpilog, 0,mpicom) - call mpibcast (carma_maxsubsteps, 1 ,mpiint, 0,mpicom) - call mpibcast (carma_minsubsteps, 1 ,mpiint, 0,mpicom) - call mpibcast (carma_maxretries, 1 ,mpiint, 0,mpicom) - call mpibcast (carma_conmax, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_dgc_threshold, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_ds_threshold, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_dt_threshold, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_tstick, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_gsticki, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_gstickl, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_cstick, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_rhcrit, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_vf_const, 1 ,mpir8, 0,mpicom) - call mpibcast (carma_model, len(carma_model), mpichar, 0, mpicom) - call mpibcast (carma_reftfile, len(carma_reftfile), mpichar, 0, mpicom) -#endif + + call mpi_bcast (carma_flag, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_aerosol, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_coremasscheck,1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_cldliq, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_cldice, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_clearsky, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_cloudborne, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_coag, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_detrain, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_drydep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_emission, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_fixedinit, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_hetchem_feedback,1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_rad_feedback, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_explised, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_budget_diags, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_package_diags,1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_incloud, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_grow, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_optics, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_partialinit, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_pheat, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_pheatatm, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_substep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_thermo, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_wetdep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_vdiff, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_do_vtran, 1 ,mpi_logical, masterprocid, mpicom, ierr) + call mpi_bcast (carma_diags_file, 1 ,mpi_integer, masterprocid, mpicom, ierr) + call mpi_bcast (carma_maxsubsteps, 1 ,mpi_integer, masterprocid, mpicom, ierr) + call mpi_bcast (carma_minsubsteps, 1 ,mpi_integer, masterprocid, mpicom, ierr) + call mpi_bcast (carma_maxretries, 1 ,mpi_integer, masterprocid, mpicom, ierr) + call mpi_bcast (carma_conmax, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_dgc_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_ds_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_dt_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_tstick, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_gsticki, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_gstickl, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_cstick, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_rhcrit, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_vf_const, 1 ,mpi_real8, masterprocid, mpicom, ierr) + call mpi_bcast (carma_model, len(carma_model), mpi_character, masterprocid, mpicom, ierr) + call mpi_bcast (carma_sulfnuc_method, len(carma_sulfnuc_method), mpi_character, masterprocid, mpicom, ierr) + call mpibcast (carma_diags_packages, len(carma_diags_packages(1))*carma_maxdiags, mpi_character, 0, mpicom) + call mpibcast (carma_debug_packages, len(carma_debug_packages(1))*carma_maxdiags, mpi_character, 0, mpicom) + + carma_ndiagpkgs = 0 + do i = 1, carma_maxdiags + if (len_trim(carma_diags_packages(i)) > 0) then + carma_ndiagpkgs = carma_ndiagpkgs + 1 + endif + enddo + + carma_ndebugpkgs = 0 + do i = 1, carma_maxdiags + if (len_trim(carma_debug_packages(i)) > 0) then + carma_ndebugpkgs = carma_ndebugpkgs + 1 + endif + enddo ! Also cause the CARMA model flags to be read in. call carma_model_readnl(nlfile) - + end subroutine carma_readnl end module carma_flags_mod diff --git a/src/physics/cam/carma_intr.F90 b/src/physics/cam/carma_intr.F90 index fc09de5246..b555aaf68a 100644 --- a/src/physics/cam/carma_intr.F90 +++ b/src/physics/cam/carma_intr.F90 @@ -22,12 +22,12 @@ module carma_intr implicit none - + private save ! Public interfaces - + ! CAM Physics Interface public carma_register ! register consituents public carma_is_active ! retrns true if this package is active (microphysics = .true.) @@ -38,11 +38,11 @@ module carma_intr public carma_timestep_init ! initialize timestep dependent variables public carma_timestep_tend ! interface to tendency computation public carma_accumulate_stats ! collect stats from all MPI tasks - + ! Other Microphysics public carma_emission_tend ! calculate tendency from emission source function public carma_wetdep_tend ! calculate tendency from wet deposition - + contains @@ -55,40 +55,41 @@ end subroutine carma_register function carma_is_active() implicit none - + logical :: carma_is_active - + carma_is_active = .false. - + return end function carma_is_active function carma_implements_cnst(name) implicit none - + character(len=*), intent(in) :: name !! constituent name logical :: carma_implements_cnst ! return value carma_implements_cnst = .false. - + return end function carma_implements_cnst - - subroutine carma_init + + subroutine carma_init(pbuf2d) implicit none - + type(physics_buffer_desc), pointer :: pbuf2d(:,:) + return end subroutine carma_init subroutine carma_final implicit none - + return end subroutine carma_final - + subroutine carma_timestep_init implicit none @@ -103,7 +104,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli use time_manager, only: get_nstep, get_step_size, is_first_step use camsrfexch, only: cam_in_t, cam_out_t use scamMod, only: single_column - + implicit none type(physics_state), intent(inout) :: state !! physics state variables @@ -114,13 +115,13 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer real(r8), intent(in), optional :: dlf(pcols,pver) !! Detraining cld H20 from convection (kg/kg/s) real(r8), intent(inout), optional :: rliq(pcols) !! vertical integral of liquid not yet in q(ixcldliq) - real(r8), intent(out), optional :: prec_str(pcols) !! [Total] sfc flux of precip from stratiform (m/s) + real(r8), intent(out), optional :: prec_str(pcols) !! [Total] sfc flux of precip from stratiform (m/s) real(r8), intent(out), optional :: snow_str(pcols) !! [Total] sfc flux of snow from stratiform (m/s) real(r8), intent(out), optional :: prec_sed(pcols) !! total precip from cloud sedimentation (m/s) real(r8), intent(out), optional :: snow_sed(pcols) !! snow from cloud ice sedimentation (m/s) real(r8), intent(in), optional :: ustar(pcols) !! friction velocity (m/s) real(r8), intent(in), optional :: obklen(pcols) !! Obukhov length [ m ] - + call physics_ptend_init(ptend,state%psetcols,'none') !Initialize an empty ptend for use with physics_update if (present(prec_str)) prec_str(:) = 0._r8 @@ -140,27 +141,28 @@ subroutine carma_init_cnst(name, latvals, lonvals, mask, q) real(r8), intent(in) :: lonvals(:) !! lon in degrees (ncol) logical, intent(in) :: mask(:) !! Only initialize where .true. real(r8), intent(out) :: q(:,:) !! mass mixing ratio - + if (name == "carma") then q = 0._r8 - end if - + end if + return end subroutine carma_init_cnst - subroutine carma_emission_tend(state, ptend, cam_in, dt) + subroutine carma_emission_tend(state, ptend, cam_in, dt, pbuf) use camsrfexch, only: cam_in_t implicit none - + type(physics_state), intent(in ) :: state !! physics state type(physics_ptend), intent(inout) :: ptend !! physics state tendencies type(cam_in_t), intent(inout) :: cam_in !! surface inputs real(r8), intent(in) :: dt !! time step (s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer return - end subroutine carma_emission_tend + end subroutine carma_emission_tend subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index ba36670ce8..a387c0adca 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -855,7 +855,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) call aer_rad_props_init() ! initialize carma - call carma_init() + call carma_init(pbuf2d) ! Prognostic chemistry. call chem_init(phys_state,pbuf2d) @@ -1530,7 +1530,7 @@ subroutine tphysac (ztodt, cam_in, & if (carma_do_emission) then ! carma emissions - call carma_emission_tend (state, ptend, cam_in, ztodt) + call carma_emission_tend (state, ptend, cam_in, ztodt, pbuf) call physics_update(state, ptend, ztodt, tend) end if diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index 83d03c46d1..57cb9d8d21 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -853,7 +853,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) call aer_rad_props_init() ! initialize carma - call carma_init() + call carma_init(pbuf2d) ! Prognostic chemistry. call chem_init(phys_state,pbuf2d) @@ -1615,7 +1615,7 @@ subroutine tphysac (ztodt, cam_in, & if (carma_do_emission) then ! carma emissions - call carma_emission_tend (state, ptend, cam_in, ztodt) + call carma_emission_tend (state, ptend, cam_in, ztodt, pbuf) call physics_update(state, ptend, ztodt, tend) end if diff --git a/src/physics/carma/base b/src/physics/carma/base index bf165cd84e..67418505b4 160000 --- a/src/physics/carma/base +++ b/src/physics/carma/base @@ -1 +1 @@ -Subproject commit bf165cd84ef94087d9a5669a5ad47838ab24c0ef +Subproject commit 67418505b48787bd305a50ffb581f98f0b466cba diff --git a/src/physics/carma/cam/carma_constants_mod.F90 b/src/physics/carma/cam/carma_constants_mod.F90 index e7392cc6a5..c29820d382 100644 --- a/src/physics/carma/cam/carma_constants_mod.F90 +++ b/src/physics/carma/cam/carma_constants_mod.F90 @@ -119,9 +119,9 @@ module carma_constants_mod !! NWAVE should be the total number of bands CAM supports. integer, public, parameter :: NWAVE = nlwbands+nswbands ! Number of wavelength bands - - - + !! The maximum number of diagnostic values that can be returned by + !! CARMA_CalculateCloudborneDiagnostics + integer, public, parameter :: MAXCLDAERDIAG = 16 !! These are constants per CARMA's definition, but are set dynamically in CAM and thus !! can not be set as constants. They must be initialized as variables in carma_init. @@ -147,5 +147,4 @@ module carma_constants_mod !! Define ratio of gas constant for dry air and specific heat real(kind=f) :: RKAPPA - -end module +end module carma_constants_mod diff --git a/src/physics/carma/cam/carma_intr.F90 b/src/physics/carma/cam/carma_intr.F90 index e726c296c9..9e86637b0c 100644 --- a/src/physics/carma/cam/carma_intr.F90 +++ b/src/physics/carma/cam/carma_intr.F90 @@ -11,7 +11,7 @@ module carma_intr use carma_precision_mod use carma_enums_mod - use carma_constants_mod + use carma_constants_mod, only : GRAV, REARTH, WTMOL_AIR, WTMOL_H2O, R_AIR, CP, RKAPPA use carma_types_mod use carma_flags_mod use carma_model_mod @@ -23,25 +23,18 @@ module carma_intr use carma_mod use shr_kind_mod, only: r8 => shr_kind_r8 - use spmd_utils, only: masterproc - use pmgrid, only: plat, plev, plevp, plon + use spmd_utils, only: masterproc, mpicom use ppgrid, only: pcols, pver, pverp use ref_pres, only: pref_mid, pref_edge, pref_mid_norm, psurf_ref use physics_types, only: physics_state, physics_ptend, physics_ptend_init, & set_dry_to_wet, physics_state_copy - use phys_grid, only: get_lat_all_p - use physconst, only: avogad, cpair + use physconst, only: cpair use constituents, only: pcnst, cnst_add, cnst_get_ind, & - cnst_name, cnst_longname, cnst_type - use chem_surfvals, only: chem_surfvals_get + cnst_name, cnst_longname use cam_abortutils, only: endrun use physics_buffer, only: physics_buffer_desc, pbuf_add_field, pbuf_old_tim_idx, & - pbuf_get_index, pbuf_get_field, dtype_r8 - - -#if ( defined SPMD ) - use mpishorthand -#endif + pbuf_get_index, pbuf_get_field, dtype_r8, pbuf_set_field + use pio, only: var_desc_t implicit none @@ -61,17 +54,20 @@ module carma_intr public carma_timestep_tend ! interface to tendency computation public carma_accumulate_stats ! collect stats from all MPI tasks + ! Other Microphysics public carma_emission_tend ! calculate tendency from emission source function public carma_wetdep_tend ! calculate tendency from wet deposition - + public :: carma_restart_init + public :: carma_restart_write + public :: carma_restart_read ! Private data ! Particle Group Statistics ! Gridbox average - integer, parameter :: NGPDIAGS = 12 ! Number of particle diagnostics ... + integer, parameter :: NGPDIAGS = 13 ! Number of particle diagnostics ... integer, parameter :: GPDIAGS_ND = 1 ! Number density integer, parameter :: GPDIAGS_AD = 2 ! Surface area density integer, parameter :: GPDIAGS_MD = 3 ! Mass density @@ -84,10 +80,15 @@ module carma_intr integer, parameter :: GPDIAGS_VM = 10 ! Mass Weighted Fall Velocity integer, parameter :: GPDIAGS_PA = 11 ! Projected Area integer, parameter :: GPDIAGS_AR = 12 ! Area Ratio + integer, parameter :: GPDIAGS_VR = 13 ! Volatile Mixing Ratio ! Particle Bin (Element) Statistics - integer, parameter :: NBNDIAGS = 1 ! Number of bin surface diagnostics ... + integer, parameter :: NBNDIAGS = 5 ! Number of bin surface diagnostics ... integer, parameter :: BNDIAGS_TP = 1 ! Delta Particle Temperature [K] + integer, parameter :: BNDIAGS_WETR = 2 ! wet radius + integer, parameter :: BNDIAGS_ND = 3 ! Number density + integer, parameter :: BNDIAGS_RO = 4 ! particle density + integer, parameter :: BNDIAGS_VR = 5 ! Volatile Mixing Ratio ! Surface integer, parameter :: NSBDIAGS = 2 ! Number of bin surface diagnostics ... @@ -134,16 +135,19 @@ module carma_intr ! Physics Buffer Indicies - integer :: ipbuf4gas(NGAS) ! physics buffer index for a carma gas - integer :: ipbuf4t ! physics buffer index for a carma temperature - integer :: ipbuf4sati(NGAS) ! physics buffer index for a carma saturation over ice - integer :: ipbuf4satl(NGAS) ! physics buffer index for a carma saturation over liquid + integer :: ipbuf4gas(NGAS)=-1 ! physics buffer index for a carma gas + integer :: ipbuf4t=-1 ! physics buffer index for a carma temperature + integer :: ipbuf4sati(NGAS)=-1 ! physics buffer index for a carma saturation over ice + integer :: ipbuf4satl(NGAS)=-1 ! physics buffer index for a carma saturation over liquid ! Globals used for a reference atmosphere. - real(kind=f) :: carma_t_ref(pver) ! midpoint temperature (Pa) - real(kind=f) :: carma_h2o_ref(pver) ! h2o mmmr (kg/kg) - real(kind=f) :: carma_h2so4_ref(pver) ! h2so4 mmr (kg/kg) + real(kind=f) :: carma_t_ref(pver) = -huge(1._f) ! midpoint temperature (Pa) + real(kind=f) :: carma_h2o_ref(pver) = -huge(1._f) ! h2o mmmr (kg/kg) + real(kind=f) :: carma_h2so4_ref(pver) = -huge(1._f) ! h2so4 mmr (kg/kg) + type(var_desc_t) :: t_ref_desc + type(var_desc_t) :: h2o_ref_desc + type(var_desc_t) :: h2so4_ref_desc ! Globals used for total statistics real(kind=f) :: glob_max_nsubstep = 0._f @@ -158,7 +162,6 @@ module carma_intr real(kind=f) :: step_nsubstep = 0._f real(kind=f) :: step_nretry = 0._f - contains @@ -177,8 +180,7 @@ module carma_intr !! @author Chuck Bardeen !! @version May-2009 subroutine carma_register - use radconstants, only : nswbands, nlwbands, & - get_sw_spectral_boundaries, get_lw_spectral_boundaries + use radconstants, only : nlwbands, get_sw_spectral_boundaries, get_lw_spectral_boundaries use cam_logfile, only : iulog use cam_control_mod, only : initial_run use physconst, only: gravit, p_rearth=>rearth, mwdry, mwh2o @@ -251,19 +253,19 @@ subroutine carma_register ! Create the CARMA object that will contain all the information about the ! how CARMA is configured. - call CARMA_Create(carma, NBIN, NELEM, NGROUP, NSOLUTE, NGAS, NWAVE, rc, & - LUNOPRT=LUNOPRT, wave=wave, dwave=dwave, do_wave_emit=do_wave_emit) + LUNOPRT=LUNOPRT, wave=wave, dwave=dwave, do_wave_emit=do_wave_emit, NREFIDX=NREFIDX) if (rc < 0) call endrun('carma_register::CARMA_Create failed.') ! Define the microphysical model. - call CARMA_DefineModel(carma, rc) + call CARMAMODEL_DefineModel(carma, rc) if (rc < 0) call endrun('carma_register::CARMA_DefineModel failed.') if (masterproc) then write(LUNOPRT,*) '' write(LUNOPRT,*) 'CARMA general settings for ', trim(carma_model), ' model : ' write(LUNOPRT,*) ' carma_do_aerosol = ', carma_do_aerosol + write(LUNOPRT,*) ' carma_do_coremasscheck = ',carma_do_coremasscheck write(LUNOPRT,*) ' carma_do_cldice = ', carma_do_cldice write(LUNOPRT,*) ' carma_do_cldliq = ', carma_do_cldliq write(LUNOPRT,*) ' carma_do_clearsky = ', carma_do_clearsky @@ -297,8 +299,8 @@ subroutine carma_register write(LUNOPRT,*) ' carma_maxretries = ', carma_maxretries write(LUNOPRT,*) ' carma_vf_const = ', carma_vf_const write(LUNOPRT,*) ' cldfrc_incloud = ', CLDFRC_INCLOUD - write(LUNOPRT,*) ' carma_reftfile = ', trim(carma_reftfile) write(LUNOPRT,*) ' carma_rad_feedback = ', carma_rad_feedback + write(LUNOPRT,*) ' carma_sulfnuc_method = ', carma_sulfnuc_method write(LUNOPRT,*) '' endif @@ -309,6 +311,8 @@ subroutine carma_register ! assumptions made in the CAM energy checking and microphysics code. call CARMA_Initialize(carma, & rc, & + sulfnucl_method = carma_sulfnuc_method, & + do_coremasscheck = carma_do_coremasscheck, & do_clearsky = carma_do_clearsky, & do_cnst_rlh = .true., & do_coag = carma_do_coag, & @@ -338,7 +342,6 @@ subroutine carma_register tstick = carma_tstick) if (rc < 0) call endrun('carma_register::CARMA_Initialize failed.') - ! The elements and gases from CARMA need to be added as constituents in ! CAM (if they don't already exist). For the elements, each radius bin ! needs to be its own constiuent in CAM. @@ -362,16 +365,14 @@ subroutine carma_register ! For prognostic groups, all of the bins need to be represented as actual CAM ! constituents. Diagnostic groups are determined from state information that ! is already present in CAM, and thus their bins only exist in CARMA. - if (cnsttype == I_CNSTTYPE_PROGNOSTIC) then - - do ibin = 1, NBIN + do ibin = 1, NBIN + write(btndname(igroup, ibin), '(A, I2.2)') trim(grp_short), ibin + if (cnsttype == I_CNSTTYPE_PROGNOSTIC) then ! Bins past maxbin are treated as diagnostic even if the group ! is prognostic and thus are not advected in the paerent model. if (ibin <= maxbin) then - write(btndname(igroup, ibin), '(A, I2.2)') trim(grp_short), ibin - write(c_name, '(A, I2.2)') trim(shortname), ibin write(c_longname, '(A, e11.4, A)') trim(name) // ', ', r(ibin)*1.e4_r8, ' um' @@ -381,8 +382,8 @@ subroutine carma_register call cnst_add(c_name, WTMOL_AIR, cpair, 0._r8, icnst4elem(ielem, ibin), & longname=c_longname, mixtype=carma_mixtype, is_convtran1=is_convtran1(igroup)) end if - end do - end if + end if + end do end do ! Find the constituent for the gas or add it if not found. @@ -508,16 +509,14 @@ end function carma_implements_cnst !! !! @author Chuck Bardeen !! @version May 2009 - subroutine carma_init + subroutine carma_init(pbuf2d) use cam_history, only: addfld, add_default, horiz_only - use ioFileMod, only : getfil use wrap_nf use time_manager, only: is_first_step use phys_control, only: phys_getopts - implicit none + type(physics_buffer_desc), pointer :: pbuf2d(:,:) - integer :: iz ! vertical index integer :: ielem ! element index integer :: ibin ! bin index integer :: igas ! gas index @@ -529,15 +528,10 @@ subroutine carma_init integer :: maxbin ! last prognostic bin logical :: is_cloud ! is the group a cloud? logical :: do_drydep ! is dry deposition enabled? + integer :: ncore ! number of core elements in the group - integer :: ier - integer :: ncid, dimid_lev, vid_T - logical :: lexist - character(len=256) :: locfn - integer :: nlev - integer :: LUNOPRT ! logical unit number for output - logical :: do_print ! do print output? logical :: history_carma + logical :: history_carma_srf_flx 1 format(a6,4x,a11,4x,a11,4x,a11) 2 format(i6,4x,3(1pe11.3,4x)) @@ -546,6 +540,7 @@ subroutine carma_init rc = 0 call phys_getopts(history_carma_out=history_carma) + history_carma_srf_flx = .false. ! Set names of constituent sources and declare them as history variables; howver, ! only prognostic variables have. @@ -589,9 +584,18 @@ subroutine carma_init call addfld(trim(etndname(ielem, ibin))//'SW', horiz_only, 'A', 'kg/m2/s', & trim(cnst_name(icnst)) // ' wet deposition flux at surface') + if (history_carma_srf_flx) then + call add_default(trim(etndname(ielem, ibin))//'EM', 1, ' ') + call add_default(trim(etndname(ielem, ibin))//'SF', 1, ' ') + call add_default(trim(etndname(ielem, ibin))//'SW', 1, ' ') + end if + if (do_drydep) then - call addfld(trim(etndname(ielem, ibin))//'DD', horiz_only, 'A', 'kg/m2/s ', & - trim(cnst_name(icnst)) // ' dry deposition') + call addfld(trim(etndname(ielem, ibin))//'DD', horiz_only, 'A', 'kg/m2/s ', & + trim(cnst_name(icnst)) // ' dry deposition') + if (history_carma_srf_flx) then + call add_default(trim(etndname(ielem, ibin))//'DD', 1, ' ') + end if end if if (carma_do_pheat) then @@ -604,7 +608,7 @@ subroutine carma_init end do do igroup = 1, NGROUP - call CARMAGROUP_Get(carma, igroup, rc, shortname=sname, is_cloud=is_cloud, do_drydep=do_drydep) + call CARMAGROUP_Get(carma, igroup, rc, shortname=sname, is_cloud=is_cloud, do_drydep=do_drydep, ncore=ncore) if (rc < 0) call endrun('carma_init::CARMAGROUP_GetGroup failed.') ! Gridbox average @@ -623,6 +627,7 @@ subroutine carma_init call addfld(trim(sname)//'PA', (/ 'lev' /), 'A', 'cm2', trim(sname) // ' projected area') call addfld(trim(sname)//'AR', (/ 'lev' /), 'A', ' ', trim(sname) // ' area ratio') call addfld(trim(sname)//'VM', (/ 'lev' /), 'A', 'm/s', trim(sname) // ' fall velocity') + call addfld(trim(sname)//'VR', (/ 'lev' /), 'A', 'kg/kg', trim(sname) // ' volatile mass mixing ratio') if (history_carma) then call add_default(trim(sname)//'ND', 1, ' ') @@ -636,6 +641,7 @@ subroutine carma_init call add_default(trim(sname)//'PA', 1, ' ') call add_default(trim(sname)//'AR', 1, ' ') call add_default(trim(sname)//'VM', 1, ' ') + call add_default(trim(sname)//'VR', 1, ' ') if (carma_do_grow) then call add_default(trim(sname)//'JN', 1, ' ') @@ -644,12 +650,39 @@ subroutine carma_init ! Per bin stats .. if (do_drydep) then - do ibin = 1, NBIN - call addfld(trim(btndname(igroup, ibin))//'VD', horiz_only, 'A', 'm/s', & - trim(btndname(igroup, ibin))//' dry deposition velocity') - end do + do ibin = 1, NBIN + call addfld(trim(btndname(igroup, ibin))//'VD', horiz_only, 'A', 'm/s', & + trim(btndname(igroup, ibin)) // ' dry deposition velocity') + end do end if + do ibin = 1, NBIN + call addfld(trim(btndname(igroup, ibin))//'ND', (/ 'lev' /), 'A', '#/cm3', & + trim(btndname(igroup, ibin)) // ' number density') + call addfld(trim(btndname(igroup, ibin))//'WR', (/ 'lev' /), 'A', 'um', & + trim(btndname(igroup, ibin)) // ' wet radius') + call addfld(trim(btndname(igroup, ibin))//'RO', (/ 'lev' /), 'A', 'g/cm3', & + trim(btndname(igroup, ibin)) // ' wet particle density') + call addfld(trim(btndname(igroup, ibin))//'VR', (/ 'lev' /), 'A', 'um', & + trim(btndname(igroup, ibin)) // ' volatile mixing ratio') + + + if ((carma_ndebugpkgs > 0) .and. (ncore > 0)) then + call addfld(trim(btndname(igroup, ibin))//'LCFM', horiz_only, 'A', 'kg/m2', trim(btndname(igroup, ibin)) // ' CARMA local mass fixer fail mass ') + call addfld(trim(btndname(igroup, ibin))//'LCFP', horiz_only, 'A', 'probability', trim(btndname(igroup, ibin)) // ' CARMA mass local fail PDF') + call addfld(trim(btndname(igroup, ibin))//'LCR', (/ 'lev' /), 'A', 'kg/kg', trim(btndname(igroup, ibin)) // ' CARMA local mass fix MMR') + call addfld(trim(btndname(igroup, ibin))//'LCP', (/ 'lev' /), 'A', 'probability', trim(btndname(igroup, ibin)) // ' CARMA local fix PDF') + + if (carma_diags_file > 0) then + call add_default(trim(btndname(igroup, ibin))//'LCFM', carma_diags_file, ' ') + call add_default(trim(btndname(igroup, ibin))//'LCFP', carma_diags_file, ' ') + call add_default(trim(btndname(igroup, ibin))//'LCR', carma_diags_file, ' ') + call add_default(trim(btndname(igroup, ibin))//'LCP', carma_diags_file, ' ') + end if + end if + + end do + end do do igas = 1, NGAS @@ -708,105 +741,20 @@ subroutine carma_init if (carma%f_igash2o /= 0) call carma_getH2O(carma_h2o_ref) if (carma%f_igash2So4 /= 0) call carma_getH2SO4(carma_h2so4_ref) end if - - if (masterproc) then - call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun('carma_init::CARMA_Get failed.') - - if (do_print) write(LUNOPRT,*) "" - if (do_print) write(LUNOPRT,*) "CARMA initializing to fixed reference state." - if (do_print) write(LUNOPRT,*) "" - - ! For temperature, get the average temperature from reference temperature file - ! if it exists or from the initial condition file if the reference temperature file - ! doesn't exist. - ! - ! NOTE: The reference temperature file will only be created for an inital run. It - ! must already exist for a restart run. - - ! Does reference temperature file already exist? - call getfil(carma_reftfile, locfn, iflag=1) - - inquire(file=locfn, exist=lexist) - - ! Read the reference temperature from the file. - if (lexist) then - - ! Open the netcdf file. - call wrap_open(trim(locfn), NF90_NOWRITE, ncid) - - ! Inquire about dimensions - call wrap_inq_dimid(ncid, 'lev', dimid_lev) - call wrap_inq_dimlen(ncid, dimid_lev, nlev) - - ! Does the number of levels match? - if (nlev /= pver) then - call endrun("carma_init::ERROR - Incompatible number of levels & - &in the CARMA reference temperature file ... " // trim(locfn)) - end if - - ! Get variable ID for reference temperature - call wrap_inq_varid(ncid, 'T', vid_T) - - ! Read in the temperature data. - call wrap_get_var_realx(ncid, vid_T, carma_T_ref) - - if (carma%f_igash2o /= 0) then - ! Get variable ID for reference temperature - call wrap_inq_varid(ncid, 'Q', vid_T) - - ! Read in the temperature data. - call wrap_get_var_realx(ncid, vid_T, carma_h2o_ref) - end if - - if (carma%f_igash2so4 /= 0) then - ! Get variable ID for reference temperature - call wrap_inq_varid(ncid, 'H2SO4', vid_T) - - ! Read in the temperature data. - call wrap_get_var_realx(ncid, vid_T, carma_h2so4_ref) - end if - - ! Close the file - call wrap_close(ncid) - - ! Is this an initial or restart run? - else if (is_first_step()) then - - if (do_print) write(LUNOPRT,*) "" - if (do_print) write(LUNOPRT,*) 'Creating CARMA reference temperature file ... ', trim(locfn) - - ! Save the average into a file to be used for restarts. - call CARMA_CreateRefTFile(carma, locfn, pref_mid(:) / 100._r8, & - carma_t_ref(:), rc, refh2o=carma_h2o_ref(:), refh2so4=carma_h2so4_ref(:)) - else - - ! The file must already exist for a restart run. - call endrun("carma_init::ERROR - Can't find the CARMA reference temperature file ... " // trim(carma_reftfile)) - - end if - - ! Write out the values that are being used. - if (do_print) write(LUNOPRT,*) "" - if (do_print) write(LUNOPRT,1) "Level","Int P (Pa)","Mid P (Pa)","Mid T (K)" - - do iz = 1, pver - if (do_print) write(LUNOPRT,2) iz, pref_edge(iz), pref_mid(iz), carma_t_ref(iz) - end do - if (do_print) write(LUNOPRT,2) iz, pref_edge(iz), 0.0_r8, 0.0_r8 - if (do_print) write(LUNOPRT,*) "" - end if - -#ifdef SPMD - - ! Communicate the settings to the other MPI tasks. - call mpi_bcast(carma_t_ref, pver, MPI_REAL8, 0, mpicom, ier) -#endif end if + if (is_first_step()) then + ! initialize physics buffer fields + do igas = 1, NGAS + call pbuf_set_field(pbuf2d, ipbuf4gas(igas), 0.0_r8) + call pbuf_set_field(pbuf2d, ipbuf4sati(igas), 0.0_r8) + call pbuf_set_field(pbuf2d, ipbuf4satl(igas), 0.0_r8) + end do + call pbuf_set_field(pbuf2d, ipbuf4t, 0.0_r8) + endif ! Do a model specific initialization. - call CARMA_InitializeModel(carma, lq_carma, rc) + call CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) if (rc < 0) call endrun('carma_init::CARMA_InitializeModel failed.') return @@ -846,9 +794,9 @@ subroutine carma_final glob_nretry / glob_nstep else if (do_print) write(LUNOPRT,2) glob_max_nsubstep, & - 0., & + 0._r8, & glob_max_nretry, & - 0. + 0._r8 end if end if end if @@ -902,7 +850,7 @@ end subroutine carma_timestep_init !! @version May-2009 subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rliq, prec_str, snow_str, & prec_sed, snow_sed, ustar, obklen) - use time_manager, only: get_nstep, get_step_size, is_first_step + use time_manager, only: get_nstep, is_first_step use camsrfexch, only: cam_in_t, cam_out_t use planck, only: planckIntensity @@ -968,9 +916,12 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli real(r8) :: ar(pver) ! Area Ratio real(r8) :: vm(pver) ! Massweighted fall velocity (cm2) real(r8) :: jn(pver) ! nucleation (cm-3) + real(r8) :: totalmmr(pver) ! total particle mmr (kg/kg) real(r8) :: numberDensity(pver) ! number density (cm-3) real(r8) :: nucleationRate(pver) ! nucleation rate (cm-3 s-1) real(r8) :: extinctionCoefficient(pver) ! extinction coefficient (cm2) + real(r8) :: r_wet(pver) ! wet radius (um) + real(r8) :: rhop_wet(pver) ! wet particle density (g/cm3) real(r8) :: dd ! dry deposition (kg/m2) real(r8) :: vd ! dry deposition velocity (cm/s) real(r8) :: vf(pverp) ! fall velocity (cm/s) @@ -986,7 +937,6 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli real(r8), pointer, dimension(:,:) :: tnd_qsnow ! external tendency on snow mass (kg/kg/s) real(r8), pointer, dimension(:,:) :: tnd_nsnow ! external tendency on snow number(#/kg/s) real(r8), pointer, dimension(:,:) :: re_ice ! ice effective radius (m) - integer :: lchnk ! chunk identifier integer :: iz real(r8) :: cldfrc(pver) ! cloud fraction [fraction] real(r8) :: rhcrit(pver) ! relative humidity for onset of liquid clouds [fraction] @@ -1010,7 +960,6 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli logical :: is_ice ! is the group ice? logical :: grp_do_drydep ! is dry depostion enabled for group? logical :: do_drydep ! is dry depostion enabled? - logical :: do_fixedinit ! do initialization from reference atm? logical :: do_detrain ! do convective detrainment? integer :: iwvl real(r8), parameter :: zzocen = 0.0001_r8 ! Ocean aerodynamic roughness length [m] @@ -1048,8 +997,6 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli call cnst_get_ind('Q', icnst_q) ! Get pointers into pbuf ... - lchnk = state_loc%lchnk - call pbuf_get_field(pbuf, ipbuf4t, t_ptr) ! If doing particle heating, then get pointers to the spectral flux data provided @@ -1080,11 +1027,10 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli ! If initializing CARMASTATE from a reference state, do it before entering the main ! loop. ! - call CARMA_Get(carma, rc, do_fixedinit=do_fixedinit, do_drydep=do_drydep) + call CARMA_Get(carma, rc, do_drydep=do_drydep) if (rc < 0) call endrun('carma_timestep_tend::CARMA_Get failed.') - if (do_fixedinit) then - + if (carma_do_fixedinit) then call CARMASTATE_CreateFromReference(cstate, & carma_ptr, & time, & @@ -1101,7 +1047,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli rc, & qh2o=carma_h2o_ref, & qh2so4=carma_h2so4_ref) - if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_CreateFromReference failed.') + if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_CreateFromReference failed.') end if @@ -1227,7 +1173,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli end do - call CARMA_DiagnoseBins(carma, cstate, state_loc, pbuf, icol, dt, rc, rliq=rliq, prec_str=prec_str, snow_str=snow_str) + call CARMAMODEL_DiagnoseBins(carma, cstate, state_loc, pbuf, icol, dt, rc, rliq=rliq, prec_str=prec_str, snow_str=snow_str) if (rc < 0) call endrun('carma_timestep_tend::CARMA_DiagnoseBins failed.') @@ -1237,7 +1183,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli if (rc < 0) call endrun('CARMA_Detrain::CARMA_Get failed.') if (do_detrain) then - call CARMA_Detrain(carma, cstate, cam_in, dlf, state_loc, icol, dt, rc, rliq=rliq, prec_str=prec_str, & + call CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state_loc, icol, dt, rc, rliq=rliq, prec_str=prec_str, & snow_str=snow_str, tnd_qsnow=tnd_qsnow, tnd_nsnow=tnd_nsnow) if (rc < 0) call endrun('carma_timestep_tend::CARMA_Detrain failed.') end if @@ -1312,11 +1258,11 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli ! NOTE: To work around an XL Fortran compiler bug, the optional arguments can only ! be passed when defined. if (present(rliq)) then - call CARMA_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc, & + call CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc, & rliq=rliq, prec_str=prec_str, snow_str=snow_str, prec_sed=prec_sed, & snow_sed=snow_sed, tnd_qsnow=tnd_qsnow, tnd_nsnow=tnd_nsnow, re_ice=re_ice) else - call CARMA_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc) + call CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc) end if if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_DiagnoseBulk failed.') @@ -1351,7 +1297,8 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli do ibin = 1, NBIN call CARMASTATE_GetBin(cstate, ielem, ibin, newstate(:), rc, & - numberDensity=numberDensity, nucleationRate=nucleationRate, surface=dd, vd=vd, vf=vf, dtpart=dtpart) + numberDensity=numberDensity, nucleationRate=nucleationRate, r_wet=r_wet, & + rhop_wet=rhop_wet, sedimentationflux=dd, vd=vd, vf=vf, dtpart=dtpart, totalmmr=totalmmr) if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_GetBin failed.') ! For prognostic groups, set the tendency from the corresponding constituents. @@ -1367,7 +1314,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli ptend%q(icol, :, icnst) = (newstate(:) - state_loc%q(icol, :, icnst)) / dt if (grp_do_drydep) then - sbdiags(icol, ibin, ielem, SBDIAGS_DD) = dd / dt + sbdiags(icol, ibin, ielem, SBDIAGS_DD) = dd sbdiags(icol, ibin, ielem, SBDIAGS_VD) = - vd / 100._r8 end if end if @@ -1382,7 +1329,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli re3(:) = re3(:) + numberDensity(:) * ((r(ibin)*rrat(ibin))**3) ad(:) = ad(:) + numberDensity(:) * 4.0_r8 * PI * (r(ibin)**2) * 1.0e8_r8 md(:) = md(:) + numberDensity(:) * rmass(ibin) - mr(:) = mr(:) + newstate(:) + mr(:) = mr(:) + totalmmr(:) pa(:) = pa(:) + numberDensity(:) * PI * ((r(ibin) * rrat(ibin))**2) * arat(ibin) vm(:) = vm(:) + numberDensity(:) * rmass(ibin) * vf(2:) / 100._f @@ -1397,6 +1344,9 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli od(:) = od(:) + numberDensity(:) * extinctionCoefficient(:) * dz(:) * 100._r8 end if + bndiags(icol,:,ibin,ielem,BNDIAGS_VR) = bndiags(icol,:,ibin,ielem,BNDIAGS_VR) + totalmmr(:) + gpdiags(icol, :, igroup, GPDIAGS_VR) = gpdiags(icol, :, igroup, GPDIAGS_VR) + totalmmr(:) + ! Particle temperatures from particle heating. if (carma_do_pheat) then bndiags(icol, :, ibin, ielem, BNDIAGS_TP) = dtpart(:) @@ -1405,6 +1355,12 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli if (nucleationRate(1) /= CAM_FILL) then jn(:) = jn(:) + nucleationRate(:) end if + + ! Output nd and wet radius for each bin. + r_wet = r_wet * 1e4_r8 ! cm to um + bndiags(icol,:,ibin,ielem,BNDIAGS_WETR) = r_wet(:) + bndiags(icol,:,ibin,ielem,BNDIAGS_ND) = numberDensity(:) + bndiags(icol,:,ibin,ielem,BNDIAGS_RO) = rhop_wet(:) end do ! If this is the number element for the group, then write out the @@ -1454,7 +1410,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli call pbuf_get_field(pbuf, ipbuf4satl(igas), satl_ptr) call CARMASTATE_GetGas(cstate, igas, newstate(:), rc, satice=satice, satliq=satliq, & - eqice=eqice, eqliq=eqliq, wtpct=wtpct) + eqice=eqice, eqliq=eqliq, wtpct=wtpct) if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_GetGas failed.') icnst = icnst4gas(igas) @@ -1492,7 +1448,9 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_Get failed.') spdiags(icol, :, SPDIAGS_NSTEP) = zsubsteps(:) - spdiags(icol, :, SPDIAGS_LNSTEP) = log(zsubsteps(:)) + where (zsubsteps/=0.0_r8) + spdiags(icol, :, SPDIAGS_LNSTEP) = log(zsubsteps(:)) + end where end if end do @@ -1517,14 +1475,35 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli call CARMASTATE_Destroy(cstate, rc) if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_Destroy failed.') - ! Output diagnostic fields. - call carma_output_diagnostics(state_loc, ptend, gpdiags, sbdiags, gsdiags, spdiags, bndiags) + call carma_output_diagnostics(state_loc, ptend, pbuf, cam_in, gpdiags, sbdiags, gsdiags, spdiags, bndiags) end subroutine carma_timestep_tend + !! Get the index for the constituents array for the specified bin + !! of the specified element. + !! + !! @author Yunqian Zhu, Francis Vitt + !! @version September-2022 + subroutine carma_getcnstforbin(ielem, ibin, icnst) + implicit none + + integer, intent(in) :: ielem, ibin + integer, intent(out) :: icnst + + icnst = icnst4elem(ielem,ibin) + return + end subroutine carma_getcnstforbin + + !! Collect CARMA substep statistics from all MPI tasks. + !! + !! @author Chuck Bardeen + !! @version May-2009 subroutine carma_accumulate_stats() +#if ( defined SPMD ) + use mpishorthand +#endif implicit none integer :: istat @@ -1600,9 +1579,9 @@ subroutine carma_accumulate_stats() step_nretry / step_nstep else if (do_print) write(LUNOPRT,1) step_max_nsubstep, & - 0., & + 0._r8, & step_max_nretry, & - 0. + 0._r8 end if end if end if @@ -1665,7 +1644,7 @@ subroutine carma_init_cnst(name, latvals, lonvals, mask, q) end where end do - call CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + call CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) if (rc < 0) call endrun('carma_init_cnst::CARMA_InitializeParticle failed.') end if end if @@ -1679,19 +1658,21 @@ subroutine carma_init_cnst(name, latvals, lonvals, mask, q) return end subroutine carma_init_cnst - !! Outputs tracer tendencies and diagnositc fields to the history files. !! All the columns in the chunk should be output at the same time. !! !! @author Chuck Bardeen !! @version May-2009 - subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spdiags, bndiags) + subroutine carma_output_diagnostics(state, ptend, pbuf, cam_in, gpdiags, sbdiags, gsdiags, spdiags, bndiags) use cam_history, only: outfld + use camsrfexch, only: cam_in_t implicit none type(physics_state), intent(in) :: state !! Physics state variables - before CARMA type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(in), dimension(pcols, pver, NGROUP, NGPDIAGS) :: gpdiags !! CARMA group diagnostic output real(r8), intent(in), dimension(pcols, NBIN, NELEM, NSBDIAGS) :: sbdiags !! CARMA surface bin diagnostic output real(r8), intent(in), dimension(pcols, pver, NGAS, NGSDIAGS) :: gsdiags !! CARMA gas diagnostic output @@ -1706,7 +1687,6 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd integer :: ienconc ! element index for group's concentration element integer :: icnst ! constituent index integer :: lchnk ! chunk identifier - integer :: ncol ! number of columns integer :: rc ! CARMA return code character(len=8) :: sname ! short (CAM) name integer :: cnsttype ! constituent type @@ -1714,12 +1694,13 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd logical :: is_cloud ! is the group a cloud? logical :: do_drydep ! is dry deposition enabled? + character(len=*), parameter :: subname = 'carma_output_diagnostics' + ! Initialize the return code. rc = 0 ! Check each column int the chunk. lchnk = state%lchnk - ncol = state%ncol ! Output step diagnostics. if (carma_do_substep) then @@ -1732,10 +1713,10 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd do ibin = 1, NBIN call CARMAELEMENT_Get(carma, ielem, rc, igroup=igroup) - if (rc < 0) call endrun('carma_timestep_tend::CARMAELEMENT_Get failed.') + if (rc < 0) call endrun(subname//'::CARMAELEMENT_Get failed.') call CARMAGROUP_Get(carma, igroup, rc, cnsttype=cnsttype, maxbin=maxbin, do_drydep=do_drydep) - if (rc < 0) call endrun('carma_timestep_tend::CARMAGROUP_Get failed.') + if (rc < 0) call endrun(subname//'::CARMAGROUP_Get failed.') if (cnsttype == I_CNSTTYPE_PROGNOSTIC) then @@ -1766,7 +1747,7 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd ! Output the particle diagnostics. do igroup = 1, NGROUP call CARMAGROUP_Get(carma, igroup, rc, shortname=sname, is_cloud=is_cloud, do_drydep=do_drydep, ienconc=ienconc) - if (rc < 0) call endrun('carma_output_diagnostics::CARMAGROUP_Get failed.') + if (rc < 0) call endrun(subname//'::CARMAGROUP_Get failed.') ! Gridbox average call outfld(trim(sname)//'ND', gpdiags(:, :, igroup, GPDIAGS_ND), pcols, lchnk) @@ -1781,12 +1762,20 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd call outfld(trim(sname)//'PA', gpdiags(:, :, igroup, GPDIAGS_PA), pcols, lchnk) call outfld(trim(sname)//'AR', gpdiags(:, :, igroup, GPDIAGS_AR), pcols, lchnk) call outfld(trim(sname)//'VM', gpdiags(:, :, igroup, GPDIAGS_VM), pcols, lchnk) + call outfld(trim(sname)//'VR', gpdiags(:, :, igroup, GPDIAGS_VR), pcols, lchnk) if (do_drydep) then do ibin = 1, NBIN call outfld(trim(btndname(igroup, ibin))//'VD', sbdiags(:, ibin, ienconc, SBDIAGS_VD), pcols, lchnk) end do end if + + do ibin = 1,NBIN + call outfld(trim(btndname(igroup, ibin))//'ND',bndiags(:, :, ibin, ienconc, BNDIAGS_ND), pcols, lchnk) + call outfld(trim(btndname(igroup, ibin))//'WR',bndiags(:, :, ibin, ienconc, BNDIAGS_WETR), pcols, lchnk) + call outfld(trim(btndname(igroup, ibin))//'RO',bndiags(:, :, ibin, ienconc, BNDIAGS_RO), pcols, lchnk) + call outfld(trim(btndname(igroup, ibin))//'VR',bndiags(:, :, ibin, ienconc, BNDIAGS_VR), pcols, lchnk) + end do end do ! Output the gas tendencies. @@ -1808,19 +1797,21 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd call outfld('CRTT', ptend%s(:, :) / cpair, pcols, lchnk) end if + ! Allow models to output their own diagnostics + call CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + return end subroutine carma_output_diagnostics - !! Calculate the emissions for CARMA aerosols. This is taken from !! the routine aerosol_emis_intr in aerosol_intr.F90 and dust_emis_intr in !! dust_intr.F90 by Phil Rasch. !! !! @author Chuck Bardeen !! @version May-2009 - subroutine carma_emission_tend (state, ptend, cam_in, dt) - use cam_history, only: outfld - use camsrfexch, only: cam_in_t + subroutine carma_emission_tend (state, ptend, cam_in, dt, pbuf) + use cam_history, only: outfld + use camsrfexch, only: cam_in_t implicit none @@ -1828,6 +1819,7 @@ subroutine carma_emission_tend (state, ptend, cam_in, dt) type(physics_ptend), intent(inout) :: ptend !! physics state tendencies type(cam_in_t), intent(inout) :: cam_in !! surface inputs real(r8), intent(in) :: dt !! time step (s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer :: lchnk ! chunk identifier integer :: ncol ! number of columns in chunk @@ -1873,7 +1865,7 @@ subroutine carma_emission_tend (state, ptend, cam_in, dt) icnst = icnst4elem(ielem, ibin) - call CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + call CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) if (rc < 0) call endrun('carma_emission_tend::CARMA_EmitParticle failed.') ! Add any surface flux here. @@ -1908,7 +1900,6 @@ end subroutine carma_emission_tend subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) use cam_history, only: outfld use phys_control, only: cam_physpkg_is - use phys_grid, only: get_lat_all_p, get_lon_all_p, get_rlat_all_p use wetdep, only: clddiag, wetdepa_v1, wetdepa_v2 use camsrfexch, only: cam_out_t use physconst, only: gravit @@ -1942,7 +1933,7 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) integer :: ixcldice real(r8) :: totcond(pcols, pver) ! total condensate real(r8) :: solfac(pcols, pver) ! solubility factor - real(r8) :: solfactor + real(r8) :: solfac_in ! solubility factor real(r8) :: scavcoef ! scavenging Coefficient logical :: do_wetdep integer :: ncol ! number of columns @@ -2030,11 +2021,11 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) if (rc < 0) call endrun('carma_wetdep_tend::CARMAELEMENT_Get failed.') call CARMAGROUP_Get(carma, igroup, rc, cnsttype=cnsttype, do_wetdep=do_wetdep, & - solfac=solfactor, scavcoef=scavcoef, maxbin=maxbin) - solfac(:ncol,:) = solfactor - + solfac=solfac_in, scavcoef=scavcoef, maxbin=maxbin) if (rc < 0) call endrun('carma_wetdep_tend::CARMAGROUP_Get failed.') + solfac(:,:) = solfac_in + if ((do_wetdep) .and. (cnsttype == I_CNSTTYPE_PROGNOSTIC)) then do ibin = 1, NBIN @@ -2099,7 +2090,7 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) iscavt, & cldv, & fracis(:, :, icnst), & - solfactor, & + solfac_in, & ncol, & z_scavcoef) else @@ -2122,7 +2113,7 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out) call outfld(trim(cnst_name(icnst))//'SW', sflx, pcols, lchnk) ! Add this to the surface amount of the constituent - call CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + call CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) end if end do @@ -2138,10 +2129,114 @@ end subroutine carma_wetdep_tend !! code to include the impact of CARMA particles in the radiative transfer !! calculation. !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. + !! + !! The I_OPTICS_MIXED_YU2105 and I_OPTICS_SULFATE_YU2015 optics methods are + !! designed to trop_strat models as define in the Yu et al. (2015) paper. The + !! other optics types can be applied more generically to a number of different + !! aerosol/cloud models. + !! !! NOTE: The format of this file is determined by the needs of the radiative tranfer !! code, so ideally a routine would exist in that module that could create a file !! with the proper format. Since that doesn't exist, we do it all here. subroutine CARMA_CreateOpticsFile(carma, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + integer :: igroup + logical :: do_mie + integer :: cnsttype ! constituent type + integer :: opticsType + + ! Assume success. + rc = 0 + + ! Process each group that is defined in the model. + do igroup = 1, NGROUP + + ! Get the necessary group properties. + call CARMAGROUP_Get(carma, igroup, rc, do_mie=do_mie, cnsttype=cnsttype, iopticstype=opticsType) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.') + + ! Are we supposed to do the mie calculation for this group? + if ((do_mie) .and. (cnsttype == I_CNSTTYPE_PROGNOSTIC)) then + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + ! This is for fixed composition, but the particle may swell in response + ! to changes in RH. Only one refractive index specified at the group level. + ! + ! NOTE: This is what was used by the first CARMA models that were radiatively + ! active. + case (I_OPTICS_FIXED) + call CARMA_CreateOpticsFile_Fixed(carma, igroup, rc) + if (rc < 0) call endrun('carma_CreateOpticsFile::CreateOpticsFile_Fixed failed.') + + ! This is similar to Yu (2015) in that handles mixed particles treated as + ! core shell particles; however the dimensions of the lookup table are the + ! the radii and the refractive indicies, so it can be used with various + ! aerosol configurations (not just as in the Yu(2015)). + case(I_OPTICS_MIXED_CORESHELL) + call endrun('carma_CreateOpticsFile mixed_coreshell has not been implemented.') + + ! This is similar to MAM4, in that a volume mixing approach is used to + ! mixed both the core and the shell together and thus only one radius and + ! one refractive index are needed in the lookup table. + case(I_OPTICS_MIXED_VOLUME) + call endrun('carma_CreateOpticsFile mixed_volume has not been implemented.') + + ! This is similar to "mixed_volume", except that Maxwell-Garnett mixing + ! is used instead of volume mixing. + case(I_OPTICS_MIXED_MAXWELL) + call endrun('carma_CreateOpticsFile mixed_maxwell has not been implemented.') + + ! This is for a pure sulfate group where the table is based upon weight + ! percent; however, unlike sulfate_Yu, the refractive index of the sulfate + ! changes with the weight percent of H2SO4. + case(I_OPTICS_SULFATE) + call CARMA_CreateOpticsFile_Sulfate(carma, igroup, rc) + if (rc < 0) call endrun('carma_CreateOpticsFile::CreateOpticsFile_Sulfate failed.') + + ! Other types are not generically useful are are particular to the + ! specific model, so thos are handled by model specific code. These + ! include: + ! I_OPTICS_MIXED_YU2015 + ! I_OPTICS_MIXED_YU_H2O + ! I_OPTICS_SULFATE_YU2015 + case default + call CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + end select + end if + end do + + return + end subroutine CARMA_CreateOpticsFile + + + !! This routine creates files containing optical properties for each radiatively + !! active particle type. These optical properties are used by the RRTMG radiation + !! code to include the impact of CARMA particles in the radiative transfer + !! calculation. + !! + !! NOTE: The format of this file is determined by the needs of the radiative tranfer + !! code, so ideally a routine would exist in that module that could create a file + !! with the proper format. Since that doesn't exist, we do it all here. + subroutine CARMA_CreateOpticsFile_Fixed(carma, igroup, rc) use radconstants, only : nswbands, nlwbands use wrap_nf use wetr, only : getwetr @@ -2149,16 +2244,17 @@ subroutine CARMA_CreateOpticsFile(carma, rc) implicit none type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group index integer, intent(out) :: rc !! return code, negative indicates failure ! Local variables - integer :: igroup, ibin, iwave, irh + integer :: ibin, iwave, irh integer :: irhswell integer :: ienconc real(kind=f) :: rho(NBIN), rhopwet real(kind=f) :: r(NBIN), rmass(NBIN), rlow(NBIN), rup(NBIN) real(kind=f) :: wave(NWAVE) - complex(kind=f) :: refidx(NWAVE) + complex(kind=f) :: refidx(NWAVE, NREFIDX) character(len=CARMA_NAME_LEN) :: name character(len=CARMA_SHORT_NAME_LEN) :: shortname logical :: do_mie @@ -2199,381 +2295,661 @@ subroutine CARMA_CreateOpticsFile(carma, rc) call CARMA_GET(carma, rc, wave=wave, do_print=do_print, LUNOPRT=LUNOPRT) if (rc < 0) call endrun('carma_CreateOpticsFile::CARMA_Get failed.') - ! Process each group that is defined in the model. - do igroup = 1, NGROUP + ! Get the necessary group properties. + call CARMAGROUP_Get(carma, igroup, rc, do_mie=do_mie, name=name, shortname=shortname, r=r, & + rlow=rlow, rup=rup, rmass=rmass, irhswell=irhswell, & + ienconc=ienconc, cnsttype=cnsttype, maxbin=maxbin) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.') - ! Get the necessary group properties. - call CARMAGROUP_Get(carma, igroup, rc, do_mie=do_mie, name=name, shortname=shortname, r=r, & - rlow=rlow, rup=rup, rmass=rmass, refidx=refidx, irhswell=irhswell, & - ienconc=ienconc, cnsttype=cnsttype, maxbin=maxbin) - if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.') + call CARMAELEMENT_Get(carma, ienconc, rc, rho=rho, refidx=refidx) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAELEMENT_Get failed.') - ! Are we supposed to do the mie calculation for this group? - if ((do_mie) .and. (cnsttype == I_CNSTTYPE_PROGNOSTIC)) then + ! A file needs to be created for each bin. + do ibin = 1, NBIN - call CARMAELEMENT_Get(carma, ienconc, rc, rho=rho) - if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAELEMENT_Get failed.') + ! Bins past maxbin are treated as diagnostic even if the group + ! is prognostic and thus are not advected in the paerent model. + if (ibin <= maxbin) then - ! A file needs to be created for each bin. - do ibin = 1, NBIN + write(c_name, '(A, I2.2)') trim(shortname), ibin - ! Bins past maxbin are treated as diagnostic even if the group - ! is prognostic and thus are not advected in the paerent model. - if (ibin <= maxbin) then + ! Construct the path to the file. Each model will have its own subdirectory + ! where the optical property files are stored. + filepath = trim(carma_model) // '_' // trim(c_name) // '_rrtmg.nc' - write(c_name, '(A, I2.2)') trim(shortname), ibin + if (do_print) write(LUNOPRT,*) 'Creating CARMA optics file ... ', trim(filepath) - ! Construct the path to the file. Each model will have its own subdirectory - ! where the optical property files are stored. - filepath = trim(carma_model) // '_' // trim(c_name) // '_rrtmg.nc' + ! Create the file. + call wrap_create(filepath, NF90_CLOBBER, fid) - if (do_print) write(LUNOPRT,*) 'Creating CARMA optics file ... ', trim(filepath) + ! For non-hygroscopic, only use 1 RH value. + if (irhswell /= 0) then + nrh = NMIE_RH + else + nrh = min(NMIE_RH, 1) + end if - ! Create the file. - call wrap_create(filepath, NF90_CLOBBER, fid) + ! Define the dimensions: rh, lwbands, swbands + call wrap_def_dim(fid, 'rh_idx', nrh, rhdim) + call wrap_def_dim(fid, 'lw_band', nlwbands, lwdim) + call wrap_def_dim(fid, 'sw_band', nswbands, swdim) - ! For non-hygroscopic, only use 1 RH value. - if (irhswell /= 0) then - nrh = NMIE_RH - else - nrh = min(NMIE_RH, 1) - end if + write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band dims." - ! Define the dimensions: rh, lwbands, swbands - call wrap_def_dim(fid, 'rh_idx', nrh, rhdim) - call wrap_def_dim(fid, 'lw_band', nlwbands, lwdim) - call wrap_def_dim(fid, 'sw_band', nswbands, swdim) + dimids(1) = rhdim + call wrap_def_var(fid, 'rh', NF90_DOUBLE, 1, dimids(1:1), rhvar) - write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band dims." + dimids(1) = lwdim + call wrap_def_var(fid, 'lw_band', NF90_DOUBLE, 1, dimids(1:1), lwvar) - dimids(1) = rhdim - call wrap_def_var(fid, 'rh', NF90_DOUBLE, 1, dimids(1:1), rhvar) + dimids(1) = swdim + call wrap_def_var(fid, 'sw_band', NF90_DOUBLE, 1, dimids(1:1), swvar) - dimids(1) = lwdim - call wrap_def_var(fid, 'lw_band', NF90_DOUBLE, 1, dimids(1:1), lwvar) + write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band vars." - dimids(1) = swdim - call wrap_def_var(fid, 'sw_band', NF90_DOUBLE, 1, dimids(1:1), swvar) + call wrap_put_att_text(fid, rhvar, 'units', 'fraction') + call wrap_put_att_text(fid, lwvar, 'units', 'm') + call wrap_put_att_text(fid, swvar, 'units', 'm') - write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band vars." + call wrap_put_att_text(fid, rhvar, 'long_name', 'relative humidity') + call wrap_put_att_text(fid, lwvar, 'long_name', 'longwave bands') + call wrap_put_att_text(fid, swvar, 'long_name', 'shortwave bands') - call wrap_put_att_text(fid, rhvar, 'units', 'fraction') - call wrap_put_att_text(fid, lwvar, 'units', 'm') - call wrap_put_att_text(fid, swvar, 'units', 'm') + ! Define the variables: abs_lw, ext_sw, ssa_sw, asm_sw + dimids(1) = rhdim + dimids(2) = lwdim + call wrap_def_var(fid, 'abs_lw', NF90_DOUBLE, 2, dimids, abs_lw_var) - call wrap_put_att_text(fid, rhvar, 'long_name', 'relative humidity') - call wrap_put_att_text(fid, lwvar, 'long_name', 'longwave bands') - call wrap_put_att_text(fid, swvar, 'long_name', 'shortwave bands') + write(LUNOPRT,*) "Defined abs_lw." - ! Define the variables: abs_lw, ext_sw, ssa_sw, asm_sw - dimids(1) = rhdim - dimids(2) = lwdim - call wrap_def_var(fid, 'abs_lw', NF90_DOUBLE, 2, dimids, abs_lw_var) + call wrap_put_att_text(fid, abs_lw_var, 'units', 'meter^2 kilogram^-1') - write(LUNOPRT,*) "Defined abs_lw." + dimids(1) = rhdim + dimids(2) = swdim + call wrap_def_var(fid, 'ext_sw', NF90_DOUBLE, 2, dimids, ext_sw_var) + call wrap_def_var(fid, 'ssa_sw', NF90_DOUBLE, 2, dimids, ssa_sw_var) + call wrap_def_var(fid, 'asm_sw', NF90_DOUBLE, 2, dimids, asm_sw_var) - call wrap_put_att_text(fid, abs_lw_var, 'units', 'meter^2 kilogram^-1') + write(LUNOPRT,*) "Defined ext_sw, ssa_sw, and asm_sw." - dimids(1) = rhdim - dimids(2) = swdim - call wrap_def_var(fid, 'ext_sw', NF90_DOUBLE, 2, dimids, ext_sw_var) - call wrap_def_var(fid, 'ssa_sw', NF90_DOUBLE, 2, dimids, ssa_sw_var) - call wrap_def_var(fid, 'asm_sw', NF90_DOUBLE, 2, dimids, asm_sw_var) + call wrap_put_att_text(fid, ssa_sw_var, 'units', 'fraction') + call wrap_put_att_text(fid, ext_sw_var, 'units', 'meter^2 kilogram^-1') + call wrap_put_att_text(fid, asm_sw_var, 'units', '-') - write(LUNOPRT,*) "Defined ext_sw, ssa_sw, and asm_sw." + ! Define the variables for the refractive indicies. + dimids(1) = swdim + call wrap_def_var(fid, 'refindex_real_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_r_refidx_var) + call wrap_def_var(fid, 'refindex_im_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_i_refidx_var) - call wrap_put_att_text(fid, ssa_sw_var, 'units', 'fraction') - call wrap_put_att_text(fid, ext_sw_var, 'units', 'meter^2 kilogram^-1') - call wrap_put_att_text(fid, asm_sw_var, 'units', '-') + write(LUNOPRT,*) "Defined lw refindex." - ! Define the variables for the refractive indicies. - dimids(1) = swdim - call wrap_def_var(fid, 'refindex_real_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_r_refidx_var) - call wrap_def_var(fid, 'refindex_im_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_i_refidx_var) + dimids(1) = lwdim + call wrap_def_var(fid, 'refindex_real_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_r_refidx_var) + call wrap_def_var(fid, 'refindex_im_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_i_refidx_var) - write(LUNOPRT,*) "Defined lw refindex." + write(LUNOPRT,*) "Defined sw refindex." - dimids(1) = lwdim - call wrap_def_var(fid, 'refindex_real_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_r_refidx_var) - call wrap_def_var(fid, 'refindex_im_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_i_refidx_var) + call wrap_put_att_text(fid, sw_r_refidx_var, 'units', '-') + call wrap_put_att_text(fid, sw_i_refidx_var, 'units', '-') + call wrap_put_att_text(fid, lw_r_refidx_var, 'units', '-') + call wrap_put_att_text(fid, lw_i_refidx_var, 'units', '-') - write(LUNOPRT,*) "Defined sw refindex." + call wrap_put_att_text(fid, sw_r_refidx_var, 'long_name', 'real refractive index of aerosol - shortwave') + call wrap_put_att_text(fid, sw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - shortwave') + call wrap_put_att_text(fid, lw_r_refidx_var, 'long_name', 'real refractive index of aerosol - longwave') + call wrap_put_att_text(fid, lw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - longwave') - call wrap_put_att_text(fid, sw_r_refidx_var, 'units', '-') - call wrap_put_att_text(fid, sw_i_refidx_var, 'units', '-') - call wrap_put_att_text(fid, lw_r_refidx_var, 'units', '-') - call wrap_put_att_text(fid, lw_i_refidx_var, 'units', '-') - call wrap_put_att_text(fid, sw_r_refidx_var, 'long_name', 'real refractive index of aerosol - shortwave') - call wrap_put_att_text(fid, sw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - shortwave') - call wrap_put_att_text(fid, lw_r_refidx_var, 'long_name', 'real refractive index of aerosol - longwave') - call wrap_put_att_text(fid, lw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - longwave') + ! Define fields that define the aerosol properties. + call wrap_def_dim(fid, 'opticsmethod_len', 32, omdim) + dimids(1) = omdim + call wrap_def_var(fid, 'opticsmethod', NF90_CHAR, 1, dimids(1:1), omvar) + write(LUNOPRT,*) "Defined omdim." - ! Define fields that define the aerosol properties. - call wrap_def_dim(fid, 'opticsmethod_len', 32, omdim) - dimids(1) = omdim - call wrap_def_var(fid, 'opticsmethod', NF90_CHAR, 1, dimids(1:1), omvar) + call wrap_def_dim(fid, 'namelength', 20, andim) + dimids(1) = andim + call wrap_def_var(fid, 'aername', NF90_CHAR, 1, dimids(1:1), anvar) - write(LUNOPRT,*) "Defined omdim." + write(LUNOPRT,*) "Defined aername." - call wrap_def_dim(fid, 'namelength', 20, andim) - dimids(1) = andim - call wrap_def_var(fid, 'aername', NF90_CHAR, 1, dimids(1:1), anvar) + call wrap_def_dim(fid, 'name_len', 32, namedim) + dimids(1) = namedim + call wrap_def_var(fid, 'name', NF90_CHAR, 1, dimids(1:1), namevar) - write(LUNOPRT,*) "Defined aername." + write(LUNOPRT,*) "Defined name." - call wrap_def_dim(fid, 'name_len', 32, namedim) - dimids(1) = namedim - call wrap_def_var(fid, 'name', NF90_CHAR, 1, dimids(1:1), namevar) + call wrap_def_var(fid, 'density', NF90_DOUBLE, 0, dimids(1:0), denvar) + call wrap_def_var(fid, 'sigma_logr', NF90_DOUBLE, 0, dimids(1:0), slogvar) + call wrap_def_var(fid, 'dryrad', NF90_DOUBLE, 0, dimids(1:0), dryrvar) + call wrap_def_var(fid, 'radmin_aer', NF90_DOUBLE, 0, dimids(1:0), rminvar) + call wrap_def_var(fid, 'radmax_aer', NF90_DOUBLE, 0, dimids(1:0), rmaxvar) + call wrap_def_var(fid, 'hygroscopicity', NF90_DOUBLE, 0, dimids(1:0), hygrovar) + call wrap_def_var(fid, 'num_to_mass_ratio', NF90_DOUBLE, 0, dimids(1:0), ntmvar) - write(LUNOPRT,*) "Defined name." + call wrap_put_att_text(fid, denvar, 'units', 'kg m^-3') + call wrap_put_att_text(fid, slogvar, 'units', '-') + call wrap_put_att_text(fid, dryrvar, 'units', 'm') + call wrap_put_att_text(fid, rminvar, 'units', 'm') + call wrap_put_att_text(fid, rmaxvar, 'units', 'm') + call wrap_put_att_text(fid, hygrovar, 'units', '-') + call wrap_put_att_text(fid, ntmvar, 'units', 'kg^-1') - call wrap_def_var(fid, 'density', NF90_DOUBLE, 0, dimids(1:0), denvar) - call wrap_def_var(fid, 'sigma_logr', NF90_DOUBLE, 0, dimids(1:0), slogvar) - call wrap_def_var(fid, 'dryrad', NF90_DOUBLE, 0, dimids(1:0), dryrvar) - call wrap_def_var(fid, 'radmin_aer', NF90_DOUBLE, 0, dimids(1:0), rminvar) - call wrap_def_var(fid, 'radmax_aer', NF90_DOUBLE, 0, dimids(1:0), rmaxvar) - call wrap_def_var(fid, 'hygroscopicity', NF90_DOUBLE, 0, dimids(1:0), hygrovar) - call wrap_def_var(fid, 'num_to_mass_ratio', NF90_DOUBLE, 0, dimids(1:0), ntmvar) + call wrap_put_att_text(fid, denvar, 'long_name', 'aerosol material density') + call wrap_put_att_text(fid, slogvar, 'long_name', 'geometric standard deviation of aerosol') + call wrap_put_att_text(fid, dryrvar, 'long_name', 'dry number mode radius of aerosol') + call wrap_put_att_text(fid, rminvar, 'long_name', 'minimum dry radius of aerosol for bin') + call wrap_put_att_text(fid, rmaxvar, 'long_name', 'maximum dry radius of aerosol for bin') + call wrap_put_att_text(fid, hygrovar, 'long_name', 'hygroscopicity of aerosol') + call wrap_put_att_text(fid, ntmvar, 'long_name', 'ratio of number to mass of aerosol') - call wrap_put_att_text(fid, denvar, 'units', 'kg m^-3') - call wrap_put_att_text(fid, slogvar, 'units', '-') - call wrap_put_att_text(fid, dryrvar, 'units', 'm') - call wrap_put_att_text(fid, rminvar, 'units', 'm') - call wrap_put_att_text(fid, rmaxvar, 'units', 'm') - call wrap_put_att_text(fid, hygrovar, 'units', '-') - call wrap_put_att_text(fid, ntmvar, 'units', 'kg^-1') - call wrap_put_att_text(fid, denvar, 'long_name', 'aerosol material density') - call wrap_put_att_text(fid, slogvar, 'long_name', 'geometric standard deviation of aerosol') - call wrap_put_att_text(fid, dryrvar, 'long_name', 'dry number mode radius of aerosol') - call wrap_put_att_text(fid, rminvar, 'long_name', 'minimum dry radius of aerosol for bin') - call wrap_put_att_text(fid, rmaxvar, 'long_name', 'maximum dry radius of aerosol for bin') - call wrap_put_att_text(fid, hygrovar, 'long_name', 'hygroscopicity of aerosol') - call wrap_put_att_text(fid, ntmvar, 'long_name', 'ratio of number to mass of aerosol') + write(LUNOPRT,*) "Defined all variables." + ! End the defintion phase of the netcdf file. + call wrap_enddef(fid) - write(LUNOPRT,*) "Defined all variables." + ! Write out the dimensions. + call wrap_put_var_realx(fid, rhvar, mie_rh(:nrh)) + call wrap_put_var_realx(fid, lwvar, wave(:nlwbands) * 1e-2_f) + call wrap_put_var_realx(fid, swvar, wave(nlwbands+1:) * 1e-2_f) - ! End the defintion phase of the netcdf file. - call wrap_enddef(fid) + ! Write out the refractive indicies. + call wrap_put_var_realx(fid, sw_r_refidx_var, real(refidx(nlwbands+1:, 1))) + call wrap_put_var_realx(fid, sw_i_refidx_var, aimag(refidx(nlwbands+1:, 1))) + call wrap_put_var_realx(fid, lw_r_refidx_var, real(refidx(:nlwbands, 1))) + call wrap_put_var_realx(fid, lw_i_refidx_var, aimag(refidx(:nlwbands, 1))) - ! Write out the dimensions. - call wrap_put_var_realx(fid, rhvar, mie_rh(:nrh)) - call wrap_put_var_realx(fid, lwvar, wave(:nlwbands) * 1e-2_f) - call wrap_put_var_realx(fid, swvar, wave(nlwbands+1:) * 1e-2_f) + ! Pad the names out with spaces. + aer_name = ' ' + aer_name(1:len(trim(c_name))) = c_name + + start_text(1) = 1 + count_text(1) = 32 + call wrap_put_vara_text(fid, namevar, start_text, count_text, (/ aer_name /)) + count_text(1) = 20 + call wrap_put_vara_text(fid, anvar, start_text, count_text, (/ aer_name /)) - ! Write out the refractive indicies. - call wrap_put_var_realx(fid, sw_r_refidx_var, real(refidx(nlwbands+1:))) - call wrap_put_var_realx(fid, sw_i_refidx_var, aimag(refidx(nlwbands+1:))) - call wrap_put_var_realx(fid, lw_r_refidx_var, real(refidx(:nlwbands))) - call wrap_put_var_realx(fid, lw_i_refidx_var, aimag(refidx(:nlwbands))) + ! These fields control whether the particle is treated as a CCN. For now, + ! set these so that CARMA particles are not considered as CCN by the + ! CAM microphysics. + if (irhswell /= 0) then + count_text(1) = len('hygroscopic ') + call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'hygroscopic ' /)) + else + count_text(1) = len('insoluble ') + call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'insoluble ' /)) + end if + call wrap_put_var_realx(fid, denvar, (/ rho(ibin) * 1e-3_f / 1e-6_f /)) + call wrap_put_var_realx(fid, slogvar, (/ 0._f /)) + call wrap_put_var_realx(fid, dryrvar, (/ r(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, rminvar, (/ rlow(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, rmaxvar, (/ rup(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, hygrovar, (/ 0._f /)) + call wrap_put_var_realx(fid, ntmvar, (/ 1._f / rmass(ibin) / 1e-3_f /)) - ! Pad the names out with spaces. - aer_name = ' ' - aer_name(1:len(trim(c_name))) = c_name + ! Iterate over a range of relative humidities, since the particle may swell + ! with relative humidity which will change its optical properties. + do irh = 1, nrh - start_text(1) = 1 - count_text(1) = 32 - call wrap_put_vara_text(fid, namevar, start_text, count_text, (/ aer_name /)) - count_text(1) = 20 - call wrap_put_vara_text(fid, anvar, start_text, count_text, (/ aer_name /)) + ! Determine the wet radius. + call getwetr(carma, igroup, mie_rh(irh), r(ibin), rwet, rho(ibin), rhopwet, rc) + if (rc < 0) call endrun('carma_CreateOpticsFile::wetr failed.') - ! These fields control whether the particle is treated as a CCN. For now, - ! set these so that CARMA particles are not considered as CCN by the - ! CAM microphysics. - if (irhswell /= 0) then - count_text(1) = len('hygroscopic ') - call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'hygroscopic ' /)) - else - count_text(1) = len('insoluble ') - call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'insoluble ' /)) - end if + ! Calculate at each wavelength. + do iwave = 1, NWAVE - call wrap_put_var_realx(fid, denvar, (/ rho(ibin) * 1e-3_f / 1e-6_f /)) - call wrap_put_var_realx(fid, slogvar, (/ 0._f /)) - call wrap_put_var_realx(fid, dryrvar, (/ r(ibin) * 1e-2_f /)) - call wrap_put_var_realx(fid, rminvar, (/ rlow(ibin) * 1e-2_f /)) - call wrap_put_var_realx(fid, rmaxvar, (/ rup(ibin) * 1e-2_f /)) - call wrap_put_var_realx(fid, hygrovar, (/ 0._f /)) - call wrap_put_var_realx(fid, ntmvar, (/ 1._f / rmass(ibin) / 1e-3_f /)) - - ! Iterate over a range of relative humidities, since the particle may swell - ! with relative humidity which will change its optical properties. - do irh = 1, nrh - - ! Determine the wet radius. - call getwetr(carma, igroup, mie_rh(irh), r(ibin), rwet, rho(ibin), rhopwet, rc) - if (rc < 0) call endrun('carma_CreateOpticsFile::wetr failed.') - - ! Calculate at each wavelength. - do iwave = 1, NWAVE -write(carma%f_LUNOPRT,*) "CARMA mie calc: start ", igroup, ibin, iwave, carma%f_wave(iwave), carma%f_group(igroup)%f_nmon(ibin) - - - ! Using Mie code, calculate the optical properties: extinction coefficient, - ! single scattering albedo and asymmetry factor. - ! Assume the particle is homogeneous (no core). - ! - ! NOTE: nmon, df, rmon and falpha are only used for fractal particles. - call mie(carma, & - carma%f_group(igroup)%f_imiertn, & - rwet, & - carma%f_wave(iwave), & - carma%f_group(igroup)%f_nmon(ibin), & - carma%f_group(igroup)%f_df(ibin), & - carma%f_group(igroup)%f_rmon, & - carma%f_group(igroup)%f_falpha, & - carma%f_group(igroup)%f_refidx(iwave), & - Qext, & - Qsca, & - asym, & - rc) - if (rc < 0) call endrun('carma_CreateOpticsFile::mie failed.') -write(carma%f_LUNOPRT,*) "CARMA mie calc: done ", Qext, Qsca, asym - - - ! Calculate the shortwave and longwave properties? - ! - ! NOTE: miess is in cgs units, but the optics file needs to be in mks - ! units, so perform the necessary conversions. - if (iwave <= nlwbands) then - - ! Longwave just needs absorption: abs_lw. - abs_lw(irh, iwave) = (Qext - Qsca) * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) - else - - ! Shortwave needs extinction, single scattering albedo and asymmetry factor: - ! ext_sw, ssa_sw and asm_sw. - ext_sw(irh, iwave - nlwbands) = Qext * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) - ssa_sw(irh, iwave - nlwbands) = Qsca / Qext - asm_sw(irh, iwave - nlwbands) = asym - end if - end do - end do + ! Using Mie code, calculate the optical properties: extinction coefficient, + ! single scattering albedo and asymmetry factor. + ! Assume the particle is homogeneous (no core). + ! + ! NOTE: nmon, df, rmon and falpha are only used for fractal particles. + call mie(carma, & + carma%f_group(igroup)%f_imiertn, & + rwet, & + carma%f_wave(iwave), & + real(carma%f_group(igroup)%f_nmon(ibin),kind=f), & + carma%f_group(igroup)%f_df(ibin), & + carma%f_group(igroup)%f_rmon, & + carma%f_group(igroup)%f_falpha, & + refidx(iwave, 1), & + 0.0_f, & + refidx(iwave, 1), & + Qext, & + Qsca, & + asym, & + rc) + if (rc < 0) call endrun('carma_CreateOpticsFile::mie failed.') + + ! Calculate the shortwave and longwave properties? + ! + ! NOTE: miess is in cgs units, but the optics file needs to be in mks + ! units, so perform the necessary conversions. + if (iwave <= nlwbands) then - ! Write out the longwave fields. - ret = nf90_put_var (fid, abs_lw_var, abs_lw(:nrh, :)) - if (ret/=NF90_NOERR) then - write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', abs_lw_var - call handle_error (ret) - end if + ! Longwave just needs absorption: abs_lw. + abs_lw(irh, iwave) = (Qext - Qsca) * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) + else - ! Write out the shortwave fields. - ret = nf90_put_var (fid, ext_sw_var, ext_sw(:nrh, :)) - if (ret/=NF90_NOERR) then - write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ext_sw_var - call handle_error (ret) - end if - ret = nf90_put_var (fid, ssa_sw_var, ssa_sw(:nrh, :)) - if (ret/=NF90_NOERR) then - write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ssa_sw_var - call handle_error (ret) + ! Shortwave needs extinction, single scattering albedo and asymmetry factor: + ! ext_sw, ssa_sw and asm_sw. + ext_sw(irh, iwave - nlwbands) = Qext * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) + ssa_sw(irh, iwave - nlwbands) = Qsca / Qext + asm_sw(irh, iwave - nlwbands) = asym end if - ret = nf90_put_var (fid, asm_sw_var, asm_sw(:nrh, :)) - if (ret/=NF90_NOERR) then - write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', asm_sw_var - call handle_error (ret) - end if - - ! Close the file. - call wrap_close(fid) - end if + end do end do + + ! Write out the longwave fields. + ret = nf90_put_var (fid, abs_lw_var, abs_lw(:nrh, :)) + if (ret/=NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', abs_lw_var + call handle_error (ret) + end if + + ! Write out the shortwave fields. + ret = nf90_put_var (fid, ext_sw_var, ext_sw(:nrh, :)) + if (ret/=NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ext_sw_var + call handle_error (ret) + end if + ret = nf90_put_var (fid, ssa_sw_var, ssa_sw(:nrh, :)) + if (ret/=NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ssa_sw_var + call handle_error (ret) + end if + ret = nf90_put_var (fid, asm_sw_var, asm_sw(:nrh, :)) + if (ret/=NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', asm_sw_var + call handle_error (ret) + end if + + ! Close the file. + call wrap_close(fid) end if end do return - end subroutine CARMA_CreateOpticsFile + end subroutine CARMA_CreateOpticsFile_Fixed - !! This routine creates a file containing a reference temperature profile - !! for use with fixed initialization. - subroutine CARMA_CreateRefTFile(carma, filepath, lev, reft, rc, refh2o, refh2so4) + + !! This routine creates files containing optical properties for the pure sulfate group + !! following Yu et al. (2015). These optical properties are used by the RRTMG radiation + !! code to include the impact of CARMA particles in the radiative transfer + !! calculation. + subroutine CARMA_CreateOpticsFile_Sulfate(carma, igroup, rc) + use radconstants, only : nswbands, nlwbands use wrap_nf + use wetr, only : getwetr implicit none - type(carma_type), intent(inout) :: carma !! the carma object - character(len=*), intent(in) :: filepath !! the file path - real(kind=f), intent(in) :: lev(pver) !! pressure levels - real(kind=f), intent(in) :: reft(pver) !! reference temperature - integer, intent(out) :: rc !! return code, negative indicates failure - real(kind=f), optional, intent(in) :: refh2o(pver) !! reference water vapor - real(kind=f), optional, intent(in) :: refh2so4(pver) !! reference sulfuric acid + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group index + integer, intent(out) :: rc !! return code, negative indicates failure ! Local variables + integer :: ibin, iwave, iwtp + integer :: irhswell + integer :: imiertn + integer :: ienconc + real(kind=f) :: rho(NBIN), rhopwet + real(kind=f) :: r(NBIN), rmass(NBIN), rlow(NBIN), rup(NBIN) + real(kind=f) :: wave(NWAVE) + complex(kind=f) :: refidx(NWAVE) + complex(kind=f) :: refidxS(NWAVE, NREFIDX) + complex(kind=f) :: refidxW(NWAVE) + character(len=CARMA_NAME_LEN) :: name + character(len=CARMA_SHORT_NAME_LEN) :: shortname integer :: fid - integer :: levdim - integer :: levvar, tvar, h2ovar, h2so4var + integer :: rhdim, lwdim, swdim, wtpdim + integer :: rhvar, lwvar, swvar, wtp_var + integer :: rwetvar + integer :: abs_lw_wtp_var, qabs_lw_wtp_var + integer :: ext_sw_wtp_var, ssa_sw_wtp_var, asm_sw_wtp_var, qext_sw_wtp_var + integer :: omdim, andim, namedim + integer :: omvar, anvar, namevar integer :: dimids(2) + integer :: denvar, slogvar, dryrvar, rminvar, rmaxvar, hygrovar, ntmvar + real(kind=f) :: abs_lw_wtp(NMIE_WTP, nlwbands) + real(kind=f) :: qabs_lw_wtp(NMIE_WTP, nlwbands) + real(kind=f) :: ext_sw_wtp(NMIE_WTP, nswbands) + real(kind=f) :: qext_sw_wtp(NMIE_WTP, nswbands) + real(kind=f) :: ssa_sw_wtp(NMIE_WTP, nswbands) + real(kind=f) :: asm_sw_wtp(NMIE_WTP, nswbands) + character(len=8) :: c_name ! constituent name + character(len=32) :: aer_name ! long enough for both aername and name + character(len=255) :: filepath + real(kind=f) :: rwet + real(kind=f) :: Qext + real(kind=f) :: Qsca + real(kind=f) :: asym + integer :: start_text(2), count_text(2) + integer :: sw_r_refidx_var, sw_i_refidx_var, lw_r_refidx_var, lw_i_refidx_var + integer :: cnsttype ! constituent type + integer :: maxbin ! last prognostic bin + integer :: LUNOPRT ! logical unit number for output + logical :: do_print ! do print output? + integer :: ret + real(kind=f) :: volwater + real(kind=f) :: volsulfate + real(kind=f) :: volshell + integer :: igash2o ! Assume success. rc = 0 - ! Create the file. - call wrap_create(filepath, NF90_CLOBBER, fid) + ! Get the wavelength structure. + call CARMA_GET(carma, rc, wave=wave, do_print=do_print, LUNOPRT=LUNOPRT, igash2o=igash2o) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMA_Get failed.') + ! Get the necessary group properties. + call CARMAGROUP_Get(carma, igroup, rc, name=name, shortname=shortname, r=r, & + rlow=rlow, rup=rup, rmass=rmass, irhswell=irhswell, & + ienconc=ienconc, cnsttype=cnsttype, maxbin=maxbin, imiertn=imiertn) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.') - ! Define the dimensions: lev - call wrap_def_dim(fid, 'lev', pver, levdim) + ! Get the necessary element properties. + call CARMAELEMENT_Get(carma, ienconc, rc, rho=rho, refidx=refidxS) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAELEMENT_Get failed.') - dimids(1) = levdim - call wrap_def_var(fid, 'lev', NF90_DOUBLE, 1, dimids(1:1), levvar) + ! Get the refractive index for water. + call CARMAGAS_Get(carma, igash2o, rc, refidx=refidxW) + if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGAS_Get failed.') - call wrap_put_att_text(fid, levvar, 'units', 'level') - call wrap_put_att_text(fid, levvar, 'long_name', 'hybrid level at midpoints (1000*(A+B))') - call wrap_put_att_text(fid, levvar, 'positive', 'down') - call wrap_put_att_text(fid, levvar, 'standard_name', 'atmosphere_hybrid_sigma_pressure_coordinate') - call wrap_put_att_text(fid, levvar, 'formula_terms', 'a: hyam b: hybm p0: P0 ps: PS') + ! A file needs to be created for each bin. + do ibin = 1, NBIN - ! Define the variables: T - call wrap_def_var(fid, 'T', NF90_DOUBLE, 1, dimids(1:1), tvar) + ! Bins past maxbin are treated as diagnostic even if the group + ! is prognostic and thus are not advected in the paerent model. + if (ibin <= maxbin) then - call wrap_put_att_text(fid, tvar, 'units', 'K') - call wrap_put_att_text(fid, tvar, 'long_name', 'Temperature') + write(c_name, '(A, I2.2)') trim(shortname), ibin - if ((carma%f_igash2o /= 0) .and. present(refh2o)) then - call wrap_def_var(fid, 'Q', NF90_DOUBLE, 1, dimids(1:1), h2ovar) + ! Construct the path to the file. Each model will have its own subdirectory + ! where the optical property files are stored. + filepath = trim(carma_model) // '_' // trim(c_name) // '_rrtmg.nc' + + if (do_print) write(LUNOPRT,*) 'Creating CARMA optics file ... ', trim(filepath) - call wrap_put_att_text(fid, h2ovar, 'units', 'kg/kg') - call wrap_put_att_text(fid, h2ovar, 'long_name', 'Specific Humidity') - end if + ! Create the file. + call wrap_create(filepath, NF90_CLOBBER, fid) + + ! Define the dimensions: rh, lwbands, swbands + call wrap_def_dim(fid, 'rh_idx', NMIE_RH, rhdim) + call wrap_def_dim(fid, 'lw_band', nlwbands, lwdim) + call wrap_def_dim(fid, 'sw_band', nswbands, swdim) + + call wrap_def_dim(fid, 'wgtpct', NMIE_WTP, wtpdim) + + dimids(1) = rhdim + call wrap_def_var(fid, 'rh', NF90_DOUBLE, 1, dimids(1), rhvar) + call wrap_def_var(fid, 'rwet',NF90_DOUBLE, 1, dimids(1), rwetvar) + + dimids(1) = lwdim + call wrap_def_var(fid, 'lw_band', NF90_DOUBLE, 1, dimids(1), lwvar) + + dimids(1) = swdim + call wrap_def_var(fid, 'sw_band', NF90_DOUBLE, 1, dimids(1), swvar) + + dimids(1) = wtpdim + call wrap_def_var(fid, 'wgtpct', NF90_DOUBLE, 1, dimids(1), wtp_var) + + call wrap_put_att_text(fid, rhvar, 'units', 'fraction') + call wrap_put_att_text(fid, rwetvar, 'units', 'cm') + call wrap_put_att_text(fid, lwvar, 'units', 'm') + call wrap_put_att_text(fid, swvar, 'units', 'm') + + call wrap_put_att_text(fid, wtp_var,'units', 'unitless') + call wrap_put_att_text(fid, wtp_var,'long_name', 'weight percent') + + call wrap_put_att_text(fid, rhvar, 'long_name', 'relative humidity') + call wrap_put_att_text(fid, rwetvar, 'long_name', 'wet radius') + call wrap_put_att_text(fid, lwvar, 'long_name', 'longwave bands') + call wrap_put_att_text(fid, swvar, 'long_name', 'shortwave bands') + + ! Define the variables: abs_lw, ext_sw, ssa_sw, asm_sw + ! Define 2-dimension (:nrh,:nswbands) LW optics properties: abs_lw, qabs_lw + dimids(1) = wtpdim + dimids(2) = lwdim + call wrap_def_var(fid, 'abs_lw_wtp', NF90_DOUBLE, 2, dimids(1:2), abs_lw_wtp_var) + call wrap_def_var(fid, 'qabs_lw_wtp',NF90_DOUBLE, 2, dimids(1:2), qabs_lw_wtp_var) + + call wrap_put_att_text(fid, abs_lw_wtp_var, 'units', 'meter^2 kilogram^-1') + call wrap_put_att_text(fid, qabs_lw_wtp_var,'units', '-') + + ! Define 2-dimension (:nrh,:nswbands) optics properties: ext_sw, qext_sw, ssa_sw, asm_sw + dimids(1) = wtpdim + dimids(2) = swdim + call wrap_def_var(fid, 'ext_sw_wtp', NF90_DOUBLE, 2, dimids(1:2), ext_sw_wtp_var) + call wrap_def_var(fid, 'qext_sw_wtp',NF90_DOUBLE, 2, dimids(1:2), qext_sw_wtp_var) + call wrap_def_var(fid, 'ssa_sw_wtp', NF90_DOUBLE, 2, dimids(1:2), ssa_sw_wtp_var) + call wrap_def_var(fid, 'asm_sw_wtp', NF90_DOUBLE, 2, dimids(1:2), asm_sw_wtp_var) + + call wrap_put_att_text(fid, ssa_sw_wtp_var, 'units', 'fraction') + call wrap_put_att_text(fid, qext_sw_wtp_var,'units', '-') + call wrap_put_att_text(fid, ext_sw_wtp_var, 'units', 'meter^2 kilogram^-1') + call wrap_put_att_text(fid, asm_sw_wtp_var, 'units', '-') + + ! Define the variables for the refractive indicies. + dimids(1) = swdim + call wrap_def_var(fid, 'refindex_real_aer_sw', NF90_DOUBLE, 1, dimids(1), sw_r_refidx_var) + call wrap_def_var(fid, 'refindex_im_aer_sw', NF90_DOUBLE, 1, dimids(1), sw_i_refidx_var) + + dimids(1) = lwdim + call wrap_def_var(fid, 'refindex_real_aer_lw', NF90_DOUBLE, 1, dimids(1), lw_r_refidx_var) + call wrap_def_var(fid, 'refindex_im_aer_lw', NF90_DOUBLE, 1, dimids(1), lw_i_refidx_var) + + call wrap_put_att_text(fid, sw_r_refidx_var, 'units', '-') + call wrap_put_att_text(fid, sw_i_refidx_var, 'units', '-') + call wrap_put_att_text(fid, lw_r_refidx_var, 'units', '-') + call wrap_put_att_text(fid, lw_i_refidx_var, 'units', '-') + + call wrap_put_att_text(fid, sw_r_refidx_var, 'long_name', 'real refractive index of aerosol - shortwave') + call wrap_put_att_text(fid, sw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - shortwave') + call wrap_put_att_text(fid, lw_r_refidx_var, 'long_name', 'real refractive index of aerosol - longwave') + call wrap_put_att_text(fid, lw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - longwave') + + + ! Define fields that define the aerosol properties. + call wrap_def_dim(fid, 'opticsmethod_len', 32, omdim) + dimids(1) = omdim + call wrap_def_var(fid, 'opticsmethod', NF90_CHAR, 1, dimids(1), omvar) + + call wrap_def_dim(fid, 'namelength', 20, andim) + dimids(1) = andim + call wrap_def_var(fid, 'aername', NF90_CHAR, 1, dimids(1), anvar) + + call wrap_def_dim(fid, 'name_len', 32, namedim) + dimids(1) = namedim + call wrap_def_var(fid, 'name', NF90_CHAR, 1, dimids, namevar) + + call wrap_def_var(fid, 'density', NF90_DOUBLE, 0, dimids(1), denvar) + call wrap_def_var(fid, 'sigma_logr', NF90_DOUBLE, 0, dimids(1), slogvar) + call wrap_def_var(fid, 'dryrad', NF90_DOUBLE, 0, dimids(1), dryrvar) + call wrap_def_var(fid, 'radmin_aer', NF90_DOUBLE, 0, dimids(1), rminvar) + call wrap_def_var(fid, 'radmax_aer', NF90_DOUBLE, 0, dimids(1), rmaxvar) + call wrap_def_var(fid, 'hygroscopicity', NF90_DOUBLE, 0, dimids(1), hygrovar) + call wrap_def_var(fid, 'num_to_mass_ratio', NF90_DOUBLE, 0, dimids(1), ntmvar) + + call wrap_put_att_text(fid, denvar, 'units', 'kg m^-3') + call wrap_put_att_text(fid, slogvar, 'units', '-') + call wrap_put_att_text(fid, dryrvar, 'units', 'm') + call wrap_put_att_text(fid, rminvar, 'units', 'm') + call wrap_put_att_text(fid, rmaxvar, 'units', 'm') + call wrap_put_att_text(fid, hygrovar, 'units', '-') + call wrap_put_att_text(fid, ntmvar, 'units', 'kg^-1') + + call wrap_put_att_text(fid, denvar, 'long_name', 'aerosol material density') + call wrap_put_att_text(fid, slogvar, 'long_name', 'geometric standard deviation of aerosol') + call wrap_put_att_text(fid, dryrvar, 'long_name', 'dry number mode radius of aerosol') + call wrap_put_att_text(fid, rminvar, 'long_name', 'minimum dry radius of aerosol for bin') + call wrap_put_att_text(fid, rmaxvar, 'long_name', 'maximum dry radius of aerosol for bin') + call wrap_put_att_text(fid, hygrovar, 'long_name', 'hygroscopicity of aerosol') + call wrap_put_att_text(fid, ntmvar, 'long_name', 'ratio of number to mass of aerosol') + + ! End the defintion phase of the netcdf file. + call wrap_enddef(fid) + + ! Write out the dimensions. + call wrap_put_var_realx(fid, rhvar, mie_rh(:)) + call wrap_put_var_realx(fid, lwvar, wave(:nlwbands) * 1e-2_f) + call wrap_put_var_realx(fid, swvar, wave(nlwbands+1:) * 1e-2_f) + + call wrap_put_var_realx(fid, wtp_var, mie_wtp(:)*100._f) + + ! Write out the refractive indicies. + call wrap_put_var_realx(fid, sw_r_refidx_var, real(refidxS(nlwbands+1:, 1))) + call wrap_put_var_realx(fid, sw_i_refidx_var, aimag(refidxS(nlwbands+1:, 1))) + call wrap_put_var_realx(fid, lw_r_refidx_var, real(refidxS(:nlwbands, 1))) + call wrap_put_var_realx(fid, lw_i_refidx_var, aimag(refidxS(:nlwbands, 1))) + + ! Pad the names out with spaces. + aer_name = ' ' + aer_name(1:len(trim(c_name))) = c_name + + start_text(1) = 1 + count_text(1) = 32 + call wrap_put_vara_text(fid, namevar, start_text, count_text, (/ aer_name /)) + count_text(1) = 20 + call wrap_put_vara_text(fid, anvar, start_text, count_text, (/ aer_name /)) + + count_text(1) = len('hygroscopic_wtp ') + call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'hygroscopic_wtp ' /)) + + call wrap_put_var_realx(fid, denvar, (/ rho(ibin) * 1e-3_f / 1e-6_f /)) + call wrap_put_var_realx(fid, slogvar, (/ 0._f /)) + call wrap_put_var_realx(fid, dryrvar, (/ r(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, rminvar, (/ rlow(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, rmaxvar, (/ rup(ibin) * 1e-2_f /)) + call wrap_put_var_realx(fid, hygrovar, (/ 0.6_f /)) + call wrap_put_var_realx(fid, ntmvar, (/ 1._f / rmass(ibin) / 1e-3_f /)) + + ! For now, ext_sw(:nrh, :nswbands) and ext_sw_coreshell(:nrh, :nswbands, :ncoreshellratio) both are calculated + ! Since other aerosols in CAM may use ext_sw rather than ext_sw_coreshell + ! Modified by Pengfei Yu + ! April.1, 2012 + + ! calculate qext and ext for pure sulfate dependent on weight percent + ! ideally qext is based on (wgt,temp,wave), however Beyer et al. (1996) Figure 5 + ! shows sulfate density is roughly 0.006 g/cm3/k, I negelet temp dimension, assuming temp = 270 K + ! In code, sulfate density is precisely calculated to determine wet raidus + do iwtp = 1, NMIE_WTP + + ! NOTE: Weight percent is normal a result of the getwetr calculation. To build the + ! table based upon weight percent, we need to pass in the desired value and a + ! reference temperature. In that case, the RH is ignored. + call getwetr(carma, igroup, mie_rh(1), r(ibin), rwet, rho(ibin), rhopwet, rc, wgtpct=mie_wtp(iwtp)*100._f, temp=270._f) + if (rc < 0) call endrun('carma_CreateOpticsFile::wetr failed.') + + ! This is not in Yu (2015), but rather than using the refractive + ! index of H2SO4 for the shell, do a volume mix of water and H2SO4 + ! for the refractive index of the shell. + volwater = rwet**3._f - r(ibin)**3._f + volsulfate = r(ibin)**3._f + volshell = volwater + volsulfate + if (volshell > 0._f) then + refidx(:) = (volwater / volshell) * refidxW(:) + (volsulfate / volshell) * refidxS(:, 1) + else + refidx(:) = refidxS(:, 1) + end if - if ((carma%f_igash2so4 /= 0) .and. present(refh2so4)) then - call wrap_def_var(fid, 'H2SO4', NF90_DOUBLE, 1, dimids(1:1), h2so4var) + ! Calculate at each wavelength. + do iwave = 1, NWAVE - call wrap_put_att_text(fid, h2so4var, 'units', 'kg/kg') - call wrap_put_att_text(fid, h2so4var, 'long_name', 'H2SO4') - end if + ! Using Mie code, calculate the optical properties: extinction coefficient, + ! single scattering albedo and asymmetry factor. + ! Assume the particle is homogeneous (no core). + ! + ! NOTE: The refractive index for sulfate changes with RH/weight percent, which + ! is not reflected in this code. + call mie(carma, & + imiertn, & + rwet, & + wave(iwave), & + 0._f, & + 3.0_f, & + 0.0_f, & + 1.0_f, & + refidx(iwave), & + 0.0_f, & + refidx(iwave), & + Qext, & + Qsca, & + asym, & + rc) + if (rc < 0) call endrun('carma_CreateOpticsFile::mie failed.') + + ! Calculate the shortwave and longwave properties? + ! + ! NOTE: miess is in cgs units, but the optics file needs to be in mks + ! units, so perform the necessary conversions. + if (iwave <= nlwbands) then - ! End the defintion phase of the netcdf file. - call wrap_enddef(fid) + ! Longwave just needs absorption: abs_lw. + qabs_lw_wtp(iwtp, iwave) = (Qext - Qsca) ! absorption per particle + abs_lw_wtp (iwtp, iwave) = (Qext - Qsca) * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) + else + ! Shortwave needs extinction, single scattering albedo and asymmetry factor: + ! ext_sw, ssa_sw and asm_sw. + qext_sw_wtp(iwtp, iwave - nlwbands) = Qext ! extinction per particle + ext_sw_wtp (iwtp, iwave - nlwbands) = Qext * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f) + ssa_sw_wtp (iwtp, iwave - nlwbands) = Qsca / Qext + asm_sw_wtp (iwtp, iwave - nlwbands) = asym + end if + end do ! iwave + end do ! iwtp + + ! Write out the longwave fields. + ret = nf90_put_var(fid, abs_lw_wtp_var, abs_lw_wtp (:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', fid, abs_lw_wtp_var + call handle_error(ret) + end if - ! Write out the dimensions. - call wrap_put_var_realx(fid, levvar, lev) + ret = nf90_put_var(fid, qabs_lw_wtp_var, qabs_lw_wtp(:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', qabs_lw_wtp_var + call handle_error(ret) + end if - ! Write out the variables. - call wrap_put_var_realx(fid, tvar, reft) + ! Write out the shortwave fields. + ret = nf90_put_var(fid, ext_sw_wtp_var, ext_sw_wtp (:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', ext_sw_wtp_var + call handle_error(ret) + end if - if ((carma%f_igash2o /= 0) .and. present(refh2o)) then - call wrap_put_var_realx(fid, h2ovar, refh2o(:)) - end if + ret = nf90_put_var(fid, qext_sw_wtp_var,qext_sw_wtp(:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', qext_sw_wtp_var + call handle_error(ret) + end if - if ((carma%f_igash2so4 /= 0) .and. present(refh2so4)) then - call wrap_put_var_realx(fid, h2so4var, refh2so4(:)) - end if + ret = nf90_put_var(fid, ssa_sw_wtp_var, ssa_sw_wtp (:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', ssa_sw_wtp_var + call handle_error(ret) + end if + + ret = nf90_put_var(fid, asm_sw_wtp_var, asm_sw_wtp (:, :)) + if (ret /= NF90_NOERR) then + write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', asm_sw_wtp_var + call handle_error(ret) + end if - ! Close the file. - call wrap_close(fid) + ! Close the file. + call wrap_close(fid) + end if + end do return - end subroutine CARMA_CreateRefTFile + end subroutine CARMA_CreateOpticsFile_Sulfate !! Calculate the aerodynamic resistance for dry deposition. @@ -2645,4 +3021,87 @@ subroutine CARMA_calcram(ustar, z0, pdel, pmid, tmid, obklen, ram) return end subroutine CARMA_calcram + + !--------------------------------------------------------------------------- + ! define fields for reference profiles in cam restart file + !--------------------------------------------------------------------------- + subroutine CARMA_restart_init( File ) + use cam_pio_utils, only: cam_pio_def_dim + use pio, only: file_desc_t, pio_def_var, pio_double + + ! arguments + type(file_desc_t),intent(inout) :: File ! pio File pointer + + ! local variables + integer :: levid, ierr + + if (carma_do_fixedinit) then + call cam_pio_def_dim(File, 'lev', pver, levid, existOK=.true.) + ierr = pio_def_var(File, 'CARMA_REF_T', pio_double, (/ levid /), t_ref_desc) + ierr = pio_def_var(File, 'CARMA_REF_H2O', pio_double, (/ levid /), h2o_ref_desc) + ierr = pio_def_var(File, 'CARMA_REF_H2SO4', pio_double, (/ levid /), h2so4_ref_desc) + endif + + end subroutine CARMA_restart_init + + !--------------------------------------------------------------------------- + ! write reference profiles to restart file + !--------------------------------------------------------------------------- + subroutine CARMA_restart_write(File) + use pio, only: file_desc_t, pio_put_var + + ! arguments + type(file_desc_t), intent(inout) :: File + + ! local variables + integer ::ierr + + if (carma_do_fixedinit) then + ierr = pio_put_var(File, t_ref_desc, carma_t_ref) + if (carma%f_igash2o /= 0) then + ierr = pio_put_var(File, h2o_ref_desc, carma_h2o_ref) + endif + if (carma%f_igash2So4 /= 0) then + ierr = pio_put_var(File, h2so4_ref_desc, carma_h2so4_ref) + endif + endif + + end subroutine CARMA_restart_write + + !--------------------------------------------------------------------------- + ! read reference profiles from restart file + !--------------------------------------------------------------------------- + subroutine CARMA_restart_read(File) + use pio, only: file_desc_t, pio_inq_varid, pio_get_var + + ! arguments + type(file_desc_t),intent(inout) :: File ! pio File pointer + + ! local variables + integer :: ierr, varid + character(len=*), parameter :: subname = 'CARMA_restart_read: ' + + if (carma_do_fixedinit) then + ierr = pio_inq_varid(File, 'CARMA_REF_T', varid) + if (varid>0) then + ierr = pio_get_var(File, varid, carma_t_ref) + else + call endrun(subname//'restart file must include CARMA_REF_T') + endif + ierr = pio_inq_varid(File, 'CARMA_REF_H2O', varid) + if (varid>0) then + ierr = pio_get_var(File, varid, carma_h2o_ref) + else if (carma%f_igash2o /= 0) then + call endrun(subname//'restart file must include CARMA_REF_H2O') + endif + ierr = pio_inq_varid(File, 'CARMA_REF_H2SO4', varid) + if (varid>0) then + ierr = pio_get_var(File, varid, carma_h2so4_ref) + else if (carma%f_igash2So4 /= 0) then + call endrun(subname//'restart file must include CARMA_REF_H2SO4') + endif + endif + + end subroutine CARMA_restart_read + end module carma_intr diff --git a/src/physics/carma/cam/carma_precision_mod.F90 b/src/physics/carma/cam/carma_precision_mod.F90 index db76f798c6..ae22471312 100644 --- a/src/physics/carma/cam/carma_precision_mod.F90 +++ b/src/physics/carma/cam/carma_precision_mod.F90 @@ -35,4 +35,4 @@ module carma_precision_mod !! Define smallest possible number such that ONE + ALMOST_ZERO > ONE real(kind=f), parameter :: ALMOST_ZERO = epsilon( ONE ) real(kind=f), parameter :: ALMOST_ONE = ONE - ALMOST_ZERO -end module +end module carma_precision_mod diff --git a/src/physics/carma/models/bc_strat/carma_model_mod.F90 b/src/physics/carma/models/bc_strat/carma_model_mod.F90 index 42dc276a01..e4a933dd67 100644 --- a/src/physics/carma/models/bc_strat/carma_model_mod.F90 +++ b/src/physics/carma/models/bc_strat/carma_model_mod.F90 @@ -417,4 +417,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) return end subroutine CARMA_WetDeposition -end module +end module carma_model_mod diff --git a/src/physics/carma/models/cirrus/carma_model_mod.F90 b/src/physics/carma/models/cirrus/carma_model_mod.F90 index 446a17cdd8..b751221964 100644 --- a/src/physics/carma/models/cirrus/carma_model_mod.F90 +++ b/src/physics/carma/models/cirrus/carma_model_mod.F90 @@ -315,7 +315,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Read in the tables. call wrap_inq_varid(fid, 'wavelength', wave_vid) call wrap_get_var_realx(fid, wave_vid, warren_wave) - warren_wave = warren_wave * 1e-4 ! um -> cm + warren_wave = warren_wave * 1e-4_r8 ! um -> cm call wrap_inq_varid(fid, 'm_real', real_vid) call wrap_get_var_realx(fid, real_vid, warren_real) @@ -1344,7 +1344,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Now integrate the snow distribution. We know the snow amount, but need an effective radius ! to determine the snow number. sub_d = 2._f * (r(NBIN) + (dr(NBIN) / 2._f)) * shapeFactor - sub_dd = (snow_max_d * 1e-4 - sub_d) / NINTS_SNOW + sub_dd = (snow_max_d * 1e-4_r8 - sub_d) / NINTS_SNOW sub_d = sub_d + sub_dd / 2._f remainder = 0._f @@ -1361,7 +1361,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! m = aD^2.1 ! ! NOTE: This needs to match the density assumption made in the detrained ice bins. - remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1) + remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1_r8) sub_d = sub_d + sub_dd end do @@ -1374,7 +1374,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Now integrate the snow distribution. We know the snow amount, but need an effective radius ! to determine the snow number. snow_d = 2._f * ((r(NBIN) + dr(NBIN) / 2._f)) - sub_dd = (snow_max_d * 1e-4 - snow_d) / NINTS_SNOW + sub_dd = (snow_max_d * 1e-4_r8 - snow_d) / NINTS_SNOW sub_d = snow_d + (sub_dd / 2._f) snow_r3 = 0._f @@ -2064,4 +2064,4 @@ subroutine CARMA_CheckMassAndEnergy(carma, cstate, madeSnow, name, state, & return end subroutine CARMA_CheckMassAndEnergy -end module +end module carma_model_mod diff --git a/src/physics/carma/models/cirrus/growevapl.F90 b/src/physics/carma/models/cirrus/growevapl.F90 index e1020eb802..c6659bdbb4 100644 --- a/src/physics/carma/models/cirrus/growevapl.F90 +++ b/src/physics/carma/models/cirrus/growevapl.F90 @@ -216,7 +216,7 @@ subroutine growevapl(carma, cstate, iz, rc) if( x .lt. 1._f )then growlg(ibin,igroup) = dmdt(ibin)/pc(iz,ibin,iepart) & - * ( ar(ibin) - 0.5*dela(ibin)*x + & + * ( ar(ibin) - 0.5_r8*dela(ibin)*x + & (x/2._f - x**2/3._f)*a6(ibin) ) else growlg(ibin,igroup) = dmdt(ibin) / dm(ibin,igroup) diff --git a/src/physics/carma/models/cirrus_dust/carma_mod.F90 b/src/physics/carma/models/cirrus_dust/carma_mod.F90 index ab89065690..f6ac6945ae 100644 --- a/src/physics/carma/models/cirrus_dust/carma_mod.F90 +++ b/src/physics/carma/models/cirrus_dust/carma_mod.F90 @@ -1475,4 +1475,4 @@ subroutine CARMA_Get(carma, rc, LUNOPRT, NBIN, NELEM, NGAS, NGROUP, NSOLUTE, NWA return end subroutine CARMA_Get -end module +end module carma_mod diff --git a/src/physics/carma/models/cirrus_dust/carma_model_mod.F90 b/src/physics/carma/models/cirrus_dust/carma_model_mod.F90 index 036e1ea977..0ff512539e 100644 --- a/src/physics/carma/models/cirrus_dust/carma_model_mod.F90 +++ b/src/physics/carma/models/cirrus_dust/carma_model_mod.F90 @@ -335,7 +335,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Read in the tables. call wrap_inq_varid(fid, 'wavelength', wave_vid) call wrap_get_var_realx(fid, wave_vid, warren_wave) - warren_wave = warren_wave * 1e-4 ! um -> cm + warren_wave = warren_wave * 1e-4_r8 ! um -> cm call wrap_inq_varid(fid, 'm_real', real_vid) call wrap_get_var_realx(fid, real_vid, warren_real) @@ -1386,7 +1386,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Now integrate the snow distribution. We know the snow amount, but need an effective radius ! to determine the snow number. sub_d = 2._f * (r(NBIN) + (dr(NBIN) / 2._f)) * shapeFactor - sub_dd = (snow_max_d * 1e-4 - sub_d) / NINTS_SNOW + sub_dd = (snow_max_d * 1e-4_r8 - sub_d) / NINTS_SNOW sub_d = sub_d + sub_dd / 2._f remainder = 0._f @@ -1403,7 +1403,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! m = aD^2.1 ! ! NOTE: This needs to match the density assumption made in the detrained ice bins. - remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1) + remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1_r8) sub_d = sub_d + sub_dd end do @@ -1416,7 +1416,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Now integrate the snow distribution. We know the snow amount, but need an effective radius ! to determine the snow number. snow_d = 2._f * ((r(NBIN) + dr(NBIN) / 2._f)) - sub_dd = (snow_max_d * 1e-4 - snow_d) / NINTS_SNOW + sub_dd = (snow_max_d * 1e-4_r8 - snow_d) / NINTS_SNOW sub_d = snow_d + (sub_dd / 2._f) snow_r3 = 0._f @@ -2570,7 +2570,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, ilat, ilon, ielem, igroup, ibin * sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/(r(ibin)*2._r8)**2.5_r8) & / sqrt(1.928_r8*(1331._r8*(r(ibin)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8) else - uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2./rhoa) & + uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2._r8/rhoa) & * sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/((.75e-4_r8)*2._r8)**2.5_r8) & / sqrt(1.928_r8*(1331._r8*((.75e-4_r8)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8) endif @@ -2703,7 +2703,7 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) if (present(wbk)) then k = wbk else - k = 0.94*u**0.5_r8 ! follow Grini and Zender, 2004JGR + k = 0.94_r8*u**0.5_r8 ! follow Grini and Zender, 2004JGR ! k = 2.5_r8 ! Lansing's estimate end if @@ -2718,4 +2718,4 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) end subroutine WeibullWind -end module +end module carma_model_mod diff --git a/src/physics/carma/models/cirrus_dust/growevapl.F90 b/src/physics/carma/models/cirrus_dust/growevapl.F90 index e1020eb802..c6659bdbb4 100644 --- a/src/physics/carma/models/cirrus_dust/growevapl.F90 +++ b/src/physics/carma/models/cirrus_dust/growevapl.F90 @@ -216,7 +216,7 @@ subroutine growevapl(carma, cstate, iz, rc) if( x .lt. 1._f )then growlg(ibin,igroup) = dmdt(ibin)/pc(iz,ibin,iepart) & - * ( ar(ibin) - 0.5*dela(ibin)*x + & + * ( ar(ibin) - 0.5_r8*dela(ibin)*x + & (x/2._f - x**2/3._f)*a6(ibin) ) else growlg(ibin,igroup) = dmdt(ibin) / dm(ibin,igroup) diff --git a/src/physics/carma/models/dust/carma_model_mod.F90 b/src/physics/carma/models/dust/carma_model_mod.F90 index 22ba9b69d2..09c96b2bf0 100644 --- a/src/physics/carma/models/dust/carma_model_mod.F90 +++ b/src/physics/carma/models/dust/carma_model_mod.F90 @@ -46,14 +46,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -66,6 +71,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -90,7 +99,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -107,7 +116,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Report model specific namelist configuration parameters. if (masterproc) then call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_DefineModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_DefineModel: CARMA_Get failed.") if (do_print) write(LUNOPRT,*) '' if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :' @@ -122,7 +131,7 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, 1, "dust", rmin, vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="CRDUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -130,7 +139,7 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="CRDUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -143,7 +152,7 @@ subroutine CARMA_DefineModel(carma, rc) return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -153,7 +162,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -178,14 +187,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -211,14 +220,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -249,7 +258,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -258,7 +267,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Lin Su, Pengfei Yu, Chuck Bardeen !! @version Dec-2010 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -276,10 +285,9 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure - integer :: ilat(pcols) ! latitude index - integer :: ilon(pcols) ! longitude index integer :: lchnk ! chunk identifier integer :: ncol ! number of columns in chunk integer :: icol ! column index @@ -341,7 +349,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend ! Process each column. do icol = 1,ncol - call CARMA_SurfaceWind(carma, state, icol, ielem, igroup, idustbin, cam_in, uv10, wwd, uth, rc) + call CARMAMODEL_SurfaceWind(carma, state, icol, ielem, igroup, idustbin, cam_in, uv10, wwd, uth, rc) ! Is the wind above the threshold for dust production? if (uv10 > uth) then @@ -351,16 +359,15 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend ! Scale the clay bins based upon the smallest silt bin. surfaceFlux(icol) = clay_mf(ibin) * surfaceFlux(icol) - end do ! For debug purposes, output the soil erosion factor. call outfld('CRSLERFC', soil_factor(:ncol, lchnk), ncol, lchnk) - end if + end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -368,16 +375,17 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use cam_history, only: addfld, add_default, horiz_only use constituents, only: pcnst implicit none - type(carma_type), intent(in) :: carma !! the carma object - logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent + type(carma_type), intent(in) :: carma !! the carma object + logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency - integer, intent(out) :: rc !! return code, negative indicates failure + type(physics_buffer_desc), pointer :: pbuf2d(:,:) + integer, intent(out) :: rc !! return code, negative indicates failure ! -------- local variables ---------- integer :: ibin ! CARMA bin index @@ -421,7 +429,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do ! Read in the soil factors. - call CARMA_ReadSoilErosionFactor(carma, rc) + call CARMAMODEL_ReadSoilErosionFactor(carma, rc) if (RC < RC_ERROR) return ! To determine Clay Mass Fraction @@ -431,7 +439,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) if (RC < RC_ERROR) return if (shortname .eq. "CRDUST") then - call CARMA_ClayMassFraction(carma, igroup, rc) + call CARMAMODEL_ClayMassFraction(carma, igroup, rc) end if end do @@ -452,7 +460,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) call addfld('CRSLERFC', horiz_only, 'A', 'fraction', 'CARMA soil erosion factor') return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -464,7 +472,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use pmgrid, only: plev @@ -487,15 +495,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -514,7 +562,7 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition !! Determines the mass fraction for the clay (submicron) bins based upon @@ -529,7 +577,7 @@ end subroutine CARMA_WetDeposition !! !! @version July-2012 !! @author Lin Su, Pengfei Yu, Chuck Bardeen - subroutine CARMA_ClayMassFraction(carma, igroup, rc) + subroutine CARMAMODEL_ClayMassFraction(carma, igroup, rc) implicit none type(carma_type), intent(in) :: carma !! the carma object @@ -610,7 +658,7 @@ subroutine CARMA_ClayMassFraction(carma, igroup, rc) clay_mf(ind_low(IABOVE):) = 1._r8 return - end subroutine CARMA_ClayMassFraction + end subroutine CARMAMODEL_ClayMassFraction !! Calculate the sea surface wind with a Weibull distribution. @@ -621,7 +669,7 @@ end subroutine CARMA_ClayMassFraction !! !! @author Lin Su, Pengfei Yu, Chuck Bardeen !! @version July-2012 - subroutine CARMA_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv10, wwd, uth, rc) + subroutine CARMAMODEL_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv10, wwd, uth, rc) use ppgrid, only: pcols, pver use physics_types, only: physics_state use camsrfexch, only: cam_in_t @@ -669,7 +717,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv * sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/(r(ibin)*2._r8)**2.5_r8) & / sqrt(1.928_r8*(1331._r8*(r(ibin)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8) else - uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2./rhoa) & + uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2._r8/rhoa) & * sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/((.75e-4_r8)*2._r8)**2.5_r8) & / sqrt(1.928_r8*(1331._r8*((.75e-4_r8)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8) endif @@ -681,7 +729,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv call WeibullWind(uv10, uth, 2._r8, wwd) return - end subroutine CARMA_SurfaceWind + end subroutine CARMAMODEL_SurfaceWind !! Read in the dust source (soil) erodibility factor from a NETCDF file. In this @@ -693,7 +741,7 @@ end subroutine CARMA_SurfaceWind !! !! @author Pengfei Yu !! @version July-2012 - subroutine CARMA_ReadSoilErosionFactor(carma, rc) + subroutine CARMAMODEL_ReadSoilErosionFactor(carma, rc) use ppgrid, only: begchunk, endchunk, pcols use ioFileMod, only: getfil use wrap_nf @@ -742,7 +790,7 @@ subroutine CARMA_ReadSoilErosionFactor(carma, rc) call wrap_inq_varid(fid, 'new_source', idvar) i = nf90_get_var (fid, idvar, ero_factor) if (i/=NF90_NOERR) then - write(iulog,*)'CARMA_ReadSoilErosionFactor: error reading varid =', idvar + write(iulog,*)'CARMAMODEL_ReadSoilErosionFactor: error reading varid =', idvar call handle_error (i) end if call wrap_inq_varid(fid, 'plat', idlat) @@ -775,7 +823,8 @@ subroutine CARMA_ReadSoilErosionFactor(carma, rc) deallocate(ero_lon) deallocate(ero_factor) - end subroutine CARMA_ReadSoilErosionFactor + return + end subroutine CARMAMODEL_ReadSoilErosionFactor !! Calculate the nth mean of u using Weibull wind distribution @@ -804,7 +853,7 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) if (present(wbk)) then k = wbk else - k = 0.94*u**0.5_r8 ! follow Grini and Zender, 2004JGR + k = 0.94_r8*u**0.5_r8 ! follow Grini and Zender, 2004JGR ! k = 2.5_r8 ! Lansing's estimate end if @@ -819,4 +868,92 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) end subroutine WeibullWind -end module + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics + +end module carma_model_mod diff --git a/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 b/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 index 360ddb9499..efe43af66d 100644 --- a/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 +++ b/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 @@ -24,16 +24,16 @@ module carma_model_flags_mod ! ! Create a public definition of any new namelist variables that you wish to have, ! and default them to an inital value. - real(r8), public :: carma_emis_dust = 0._r8 !! Total dust emission for the event (kg) - real(r8), public :: carma_emis_soot = 0._r8 !! Total soot emission for the event (kg) - integer, public :: carma_emis_startdate = 1 !! start year and day of year (yyyyddd) - integer, public :: carma_emis_stopdate = 1 !! stop year and day of year (yyyyddd) - integer, public :: carma_emis_starttime = 0 !! start time of day (s) - integer, public :: carma_emis_stoptime = 0 !! stop time of day (s) - real(r8), public :: carma_emis_minlat = -90. !! minimum latitude - real(r8), public :: carma_emis_maxlat = 90. !! maximum latitude - real(r8), public :: carma_emis_minlon = 0. !! minimum longitude - real(r8), public :: carma_emis_maxlon = 360. !! maximum longitude + real(r8), public :: carma_emis_dust = 0._r8 !! Total dust emission for the event (kg) + real(r8), public :: carma_emis_soot = 0._r8 !! Total soot emission for the event (kg) + integer, public :: carma_emis_startdate = 1 !! start year and day of year (yyyyddd) + integer, public :: carma_emis_stopdate = 1 !! stop year and day of year (yyyyddd) + integer, public :: carma_emis_starttime = 0 !! start time of day (s) + integer, public :: carma_emis_stoptime = 0 !! stop time of day (s) + real(r8), public :: carma_emis_minlat = -90._r8 !! minimum latitude + real(r8), public :: carma_emis_maxlat = 90._r8 !! maximum latitude + real(r8), public :: carma_emis_minlon = 0._r8 !! minimum longitude + real(r8), public :: carma_emis_maxlon = 360._r8 !! maximum longitude logical, public :: carma_fractal_soot = .false. !! fractal Soot contains diff --git a/src/physics/carma/models/meteor_impact/carma_model_mod.F90 b/src/physics/carma/models/meteor_impact/carma_model_mod.F90 index f8ebec713d..ecc131f0cf 100755 --- a/src/physics/carma/models/meteor_impact/carma_model_mod.F90 +++ b/src/physics/carma/models/meteor_impact/carma_model_mod.F90 @@ -42,14 +42,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 2 !! Number of particle groups @@ -65,6 +70,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) = (/ 0._f, 0.5_f, 0.7_f, 0.8_f, 0.9_f, 0.95_f, 0.98_f, 0.99_f /) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -96,7 +105,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -107,7 +116,7 @@ subroutine CARMA_DefineModel(carma, rc) real(kind=f), parameter :: dust_vmrat = 2.49_f ! dust volume ratio real(kind=f), parameter :: soot_rmin = 20.e-7_f ! dust minimum radius (cm) real(kind=f), parameter :: soot_vmrat = 2.49_f ! dust volume ratio - complex(kind=f) :: refidx(NWAVE) ! refractice indices + complex(kind=f) :: refidx(NWAVE,NREFIDX) ! refractice indices integer :: LUNOPRT ! logical unit number for output logical :: do_print ! do print output? @@ -123,13 +132,13 @@ subroutine CARMA_DefineModel(carma, rc) if (carma_emis_maxlon < 0._f) carma_emis_maxlon = 360._f + carma_emis_maxlon if (carma_emis_minlat > carma_emis_maxlat) then - if (do_print) write(LUNOPRT,*) 'CARMA_DefineModel::ERROR - carma_emis_minlat greater than carma_emis_maxlat' + if (do_print) write(LUNOPRT,*) 'CARMAMODEL_DefineModel::ERROR - carma_emis_minlat greater than carma_emis_maxlat' end if ! Report model specific namelist configuration parameters. if (masterproc) then call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_DefineModel: CARMA_Get failed.") if (do_print) write(LUNOPRT,*) '' if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :' @@ -154,19 +163,10 @@ subroutine CARMA_DefineModel(carma, rc) ! defined. If wetdep is defined, then the optional solubility factor ! should also be defined. - ! Use the same refractive index at all wavelengths. This value is typical of soot and - ! is recommended by Toon et al. 2012. TBD Wagner et al. 2011 shows variability in the - ! real part (0.003 (IR) to 0.05 (UV)). - refidx(:) = (1.53_f, 0.008_f) - call CARMAGROUP_Create(carma, I_GRP_DUST, "Dust", dust_rmin, dust_vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & - scavcoef=0.1_f, shortname="CRDUST", refidx=refidx, do_mie=.true.) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') - - ! Use the same refractive index at all wavelengths. This value is typical of soot and - ! is recommended by Toon et al. 2012. - refidx(:) = (1.8_f, 0.67_f) + scavcoef=0.1_f, shortname="CRDUST", do_mie=.true.) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') if (carma_fractal_soot) then RHO_SOOT = 1.8_f @@ -178,27 +178,37 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, I_GRP_SOOT, "Soot", soot_rmin, soot_vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.1_f, & - scavcoef=0.1_f, shortname="CRSOOT", refidx=refidx, do_mie=.true., & + scavcoef=0.1_f, shortname="CRSOOT", do_mie=.true., & is_fractal=.true., rmon=soot_rmon, df=soot_df, falpha=soot_falpha, & imiertn=I_MIERTN_BOTET1997) else RHO_SOOT = 1.0_f call CARMAGROUP_Create(carma, I_GRP_SOOT, "Soot", soot_rmin, soot_vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.1_f, & - scavcoef=0.1_f, shortname="CRSOOT", refidx=refidx, do_mie=.true.) + scavcoef=0.1_f, shortname="CRSOOT", do_mie=.true.) end if - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements ! ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. - call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="CRDUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') - call CARMAELEMENT_Create(carma, I_ELEM_SOOT, I_GRP_SOOT, "Soot", RHO_SOOT, I_INVOLATILE, I_SOOT, rc, shortname="CRSOOT") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + ! Use the same refractive index at all wavelengths. This value is typical of dust and + ! is recommended by Toon et al. 2012. TBD Wagner et al. 2011 shows variability in the + ! real part (0.003 (IR) to 0.05 (UV)). + refidx(:,1) = CMPLX(1.53_f, 0.008_f, kind=f) + + call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="CRDUST", refidx=refidx) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') + + ! Use the same refractive index at all wavelengths. This value is typical of soot and + ! is recommended by Toon et al. 2012. + refidx(:,1) = CMPLX(1.8_f, 0.67_f, kind=f) + + call CARMAELEMENT_Create(carma, I_ELEM_SOOT, I_GRP_SOOT, "Soot", RHO_SOOT, I_INVOLATILE, I_SOOT, rc, shortname="CRSOOT", refidx=refidx) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -209,13 +219,13 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') call CARMA_AddCoagulation(carma, I_GRP_SOOT, I_GRP_SOOT, I_GRP_SOOT, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -225,7 +235,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -250,14 +260,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -283,14 +293,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -329,7 +339,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, do ibin = 1, NBIN call CARMASTATE_GetBin(cstate, ielem, ibin, mmr, rc, sedimentationFlux=sflx) - if (rc < 0) call endrun('CARMA_DiagnoseBulk::CARMA_GetBin failed.') + if (rc < 0) call endrun('CARMAMODEL_DiagnoseBulk::CARMA_GetBin failed.') cam_out%bcphidry(icol) = cam_out%bcphidry(icol) + max(sflx, 0._r8) end do @@ -338,7 +348,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, do ibin = 1, NBIN call CARMASTATE_GetBin(cstate, ielem, ibin, mmr, rc, sedimentationFlux=sflx) - if (rc < 0) call endrun('CARMA_DiagnoseBulk::CARMA_GetBin failed.') + if (rc < 0) call endrun('CARMAMODEL_DiagnoseBulk::CARMA_GetBin failed.') if (carma_dustmap(ibin) == 1) then cam_out%dstdry1(icol) = cam_out%dstdry1(icol) + max(sflx, 0._r8) @@ -352,7 +362,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, end do return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -361,7 +371,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -382,6 +392,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure real(r8), parameter :: mu_dust_gnd = 1._r8 ! width parameter, dust, ground (km) @@ -563,7 +574,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -574,7 +585,7 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only: pcnst use phys_grid, only: get_rlat_all_p, get_rlon_all_p, get_area_all_p, get_ncols_p use shr_reprosum_mod, only: shr_reprosum_calc @@ -586,14 +597,15 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! NOTE: The dust distribution has not been specified yet, but it should be different ! from the soot. - real(kind=f), parameter :: rm_dust = 0.11 ! dust mean radius (um) - real(kind=f), parameter :: sigma_dust = 1.6 ! dust variance - real(kind=f), parameter :: rm_soot = 0.11 ! soot mean radius (um) - real(kind=f), parameter :: sigma_soot = 1.6 ! soot variance + real(kind=f), parameter :: rm_dust = 0.11_r8 ! dust mean radius (um) + real(kind=f), parameter :: sigma_dust = 1.6_r8 ! dust variance + real(kind=f), parameter :: rm_soot = 0.11_r8 ! soot mean radius (um) + real(kind=f), parameter :: sigma_soot = 1.6_r8 ! soot variance integer :: i real(kind=f) :: r(NBIN) @@ -735,7 +747,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end if return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -747,7 +759,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 implicit none @@ -767,15 +779,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! Add initial condition here. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -817,6 +869,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) end if return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + integer :: icol !! column index + integer :: ibin !! bin index + real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s + real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s + character(len=16) :: binname !! names bins + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer :: i + integer :: icnst !! constituent index + integer :: ienconc !! concentration element index + integer :: ncore !! number of cores + integer :: icorelem(NELEM) !! core element index + real(r8) :: mair(pver) !! Mass of air column (kg/m2) + real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2) + real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2) + real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s) + real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s) + real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2) + real(r8) :: so2(pcols) !! SO2 gas (kg/m2) + real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2) + real(r8) :: bddust(pcols) !! Burden dust (kg/m2) + real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2) + real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2) + real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2) + character(len=16) :: shortname + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/meteor_smoke/carma_model_mod.F90 b/src/physics/carma/models/meteor_smoke/carma_model_mod.F90 index 0b6d83aba1..4ec2910f44 100644 --- a/src/physics/carma/models/meteor_smoke/carma_model_mod.F90 +++ b/src/physics/carma/models/meteor_smoke/carma_model_mod.F90 @@ -42,14 +42,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -62,6 +67,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -102,7 +111,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -120,7 +129,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Report model specific namelist configuration parameters. if (masterproc) then call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_DefineModel: CARMA_Get failed.") if (do_print) write(LUNOPRT,*) '' if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :' @@ -139,7 +148,7 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, I_GRP_DUST, "meteor smoke", rmin, vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -148,7 +157,7 @@ subroutine CARMA_DefineModel(carma, rc) ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "meteor smoke", RHO_METEOR_SMOKE, & I_INVOLATILE, I_METEOR_SMOKE, rc, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -159,10 +168,10 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -172,7 +181,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -197,14 +206,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -230,14 +239,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -268,7 +277,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -277,7 +286,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version Jan-2011 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -296,6 +305,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilat ! latitude index @@ -435,7 +445,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if end do - if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then + if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy) end if @@ -481,7 +491,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -489,7 +499,7 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use ioFileMod, only: getfil use constituents, only: pcnst use wrap_nf @@ -499,6 +509,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilev ! level index @@ -524,7 +535,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_InitializeModel: CARMA_Get failed.") ! Initialize the emissions rate table. if (carma_do_emission) then @@ -565,7 +576,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) carma_emis_ilev_max = carma_emis_nLevs do ilev = 1, carma_emis_nLevs - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_min = ilev + 1 else exit @@ -573,7 +584,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do do ilev = carma_emis_nLevs, 1, -1 - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_max = ilev - 1 else exit @@ -642,7 +653,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! There should be one time for each day of the year, so ! quit if it isn't correct. if (carma_escale_nTimes .ne. 365) then - call endrun("CARMA_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") + call endrun("CARMAMODEL_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") endif call wrap_inq_dimid(fid, "ltime", ltime_did) @@ -665,7 +676,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) call wrap_inq_varid(fid, 'SGRF', grf_vid) tmp = nf90_get_var (fid, grf_vid, carma_escale_grf) if (tmp/=NF90_NOERR) then - write(iulog,*) 'CARMA_InitializeModel: error reading varid =', grf_vid + write(iulog,*) 'CARMAMODEL_InitializeModel: error reading varid =', grf_vid call handle_error (tmp) end if @@ -701,7 +712,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) endif return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -713,8 +724,9 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 + use pmgrid, only: plat, plev, plon implicit none @@ -735,15 +747,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -762,6 +814,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + integer :: icol !! column index + integer :: ibin !! bin index + real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s + real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s + character(len=16) :: binname !! names bins + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer :: i + integer :: icnst !! constituent index + integer :: ienconc !! concentration element index + integer :: ncore !! number of cores + integer :: icorelem(NELEM) !! core element index + real(r8) :: mair(pver) !! Mass of air column (kg/m2) + real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2) + real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2) + real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s) + real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s) + real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2) + real(r8) :: so2(pcols) !! SO2 gas (kg/m2) + real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2) + real(r8) :: bddust(pcols) !! Burden dust (kg/m2) + real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2) + real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2) + real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2) + character(len=16) :: shortname + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 b/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 index 36ee1be358..5f21fbf4d9 100644 --- a/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 +++ b/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 @@ -50,14 +50,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 2 !! Number of particle groups @@ -70,6 +75,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -121,7 +130,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) use ioFileMod, only: getfil use wrap_nf @@ -144,7 +153,7 @@ subroutine CARMA_DefineModel(carma, rc) rc = RC_OK call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.') ! Report model specific configuration parameters. if (masterproc) then @@ -167,7 +176,7 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, I_GRP_DUST, "meteor smoke", rmin, 2.0_f, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! NOTE: For CAM, the optional do_wetdep and do_drydep flags should be @@ -180,7 +189,7 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, I_GRP_SULFATE, "sulfate", rmin_sulfate, vmrat_sulfate, I_SPHERE, 1._f, .false., & rc, irhswell=I_WTPCT_H2SO4, do_wetdep=.true., do_drydep=.true., solfac=1.0_f, & scavcoef=0.1_f, is_sulfate=.true., shortname="SULF") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -189,15 +198,15 @@ subroutine CARMA_DefineModel(carma, rc) ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "meteor smoke", RHO_METEOR_SMOKE, & I_INVOLATILE, I_METEOR_SMOKE, rc, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, I_ELEM_SULFATE, I_GRP_SULFATE, "sulfate", RHO_SULFATE, & I_VOLATILE, I_H2SO4, rc, shortname="SULF") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, I_ELEM_SULCORE, I_GRP_SULFATE, "sulfate core", RHO_METEOR_SMOKE, & I_COREMASS, I_METEOR_SMOKE, rc, shortname="SFCORE") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes ! @@ -208,40 +217,40 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGAS_Create(carma, I_GAS_H2O, "Water Vapor", WTMOL_H2O, & I_VAPRTN_H2O_MURPHY2005, I_GCOMP_H2O, rc, shortname="Q", & ds_threshold=0.2_f) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.') call CARMAGAS_Create(carma, I_GAS_H2SO4, "Sulfuric Acid", WTMOL_H2SO4, & I_VAPRTN_H2SO4_AYERS1980, I_GCOMP_H2SO4, rc, shortname = "H2SO4", & ds_threshold=-0.2_f) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.') ! Define the Processes call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') ! Set H2SO4 to be the condensing gas, water vapor is assumed to be in equilibrium ! and will be used to define the wet particle radius. call CARMA_AddGrowth(carma, I_ELEM_SULFATE, I_GAS_H2SO4, rc) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddGrowth failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddGrowth failed.') call CARMA_AddNucleation(carma, I_ELEM_SULFATE, I_ELEM_SULFATE, I_HOMNUC, 0._f, rc, igas=I_GAS_H2SO4) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.') ! Also need nucleation with meteor smoke. call CARMA_AddNucleation(carma, I_ELEM_DUST, I_ELEM_SULCORE, I_HETNUCSULF, 0._f, rc, igas=I_GAS_H2SO4, ievp2elem=I_ELEM_DUST) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.') call CARMA_AddCoagulation(carma, I_GRP_SULFATE, I_GRP_SULFATE, I_GRP_SULFATE, I_COLLEC_FUCHS, rc) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') ! Dust-Sulfate Coagulation? call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_SULFATE, I_GRP_SULFATE, I_COLLEC_FUCHS, rc) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -251,7 +260,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -276,14 +285,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -309,14 +318,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -347,10 +356,10 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -369,6 +378,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilat ! latitude index @@ -508,7 +518,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if end do - if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then + if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy) end if @@ -560,7 +570,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -568,7 +578,7 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only: pcnst use ioFileMod, only: getfil use wrap_nf @@ -578,6 +588,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilev ! level index @@ -603,7 +614,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_InitializeModel: CARMA_Get failed.") ! Initialize the emissions rate table. if (carma_do_emission) then @@ -644,7 +655,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) carma_emis_ilev_max = carma_emis_nLevs do ilev = 1, carma_emis_nLevs - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_min = ilev + 1 else exit @@ -652,7 +663,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do do ilev = carma_emis_nLevs, 1, -1 - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_max = ilev - 1 else exit @@ -721,7 +732,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! There should be one time for each day of the year, so ! quit if it isn't correct. if (carma_escale_nTimes .ne. 365) then - call endrun("CARMA_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") + call endrun("CARMAMODEL_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") endif call wrap_inq_dimid(fid, "ltime", ltime_did) @@ -744,7 +755,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) call wrap_inq_varid(fid, 'SGRF', grf_vid) tmp = nf90_get_var (fid, grf_vid, carma_escale_grf) if (tmp/=NF90_NOERR) then - write(iulog,*) 'CARMA_InitializeModel: error reading varid =', grf_vid + write(iulog,*) 'CARMAMODEL_InitializeModel: error reading varid =', grf_vid call handle_error (tmp) end if @@ -780,7 +791,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) endif return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -792,8 +803,9 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 + use pmgrid, only: plat, plev, plon implicit none @@ -814,15 +826,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -841,6 +893,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + integer :: icol !! column index + integer :: ibin !! bin index + real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s + real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s + character(len=16) :: binname !! names bins + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer :: i + integer :: icnst !! constituent index + integer :: ienconc !! concentration element index + integer :: ncore !! number of cores + integer :: icorelem(NELEM) !! core element index + real(r8) :: mair(pver) !! Mass of air column (kg/m2) + real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2) + real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2) + real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s) + real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s) + real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2) + real(r8) :: so2(pcols) !! SO2 gas (kg/m2) + real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2) + real(r8) :: bddust(pcols) !! Burden dust (kg/m2) + real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2) + real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2) + real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2) + character(len=16) :: shortname + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/pmc/carma_model_mod.F90 b/src/physics/carma/models/pmc/carma_model_mod.F90 index eb8c6e6667..41ac20fffe 100644 --- a/src/physics/carma/models/pmc/carma_model_mod.F90 +++ b/src/physics/carma/models/pmc/carma_model_mod.F90 @@ -45,14 +45,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 2 !! Number of particle groups @@ -65,6 +70,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -117,7 +126,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) use ioFileMod, only: getfil use wrap_nf @@ -137,7 +146,7 @@ subroutine CARMA_DefineModel(carma, rc) integer :: imag_vid character(len=256) :: efile ! refractive index file name real(kind=f) :: interp - complex(kind=f) :: refidx_ice(NWAVE) ! the refractive index at each CAM wavelength + complex(kind=f) :: refidx_ice(NWAVE,NREFIDX) ! the refractive index at each CAM wavelength integer :: LUNOPRT logical :: do_print @@ -145,7 +154,7 @@ subroutine CARMA_DefineModel(carma, rc) rc = RC_OK call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT, wave=wave) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.') ! Report model specific configuration parameters. if (masterproc) then @@ -203,7 +212,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Read in the tables. call wrap_inq_varid(fid, 'wavelength', wave_vid) call wrap_get_var_realx(fid, wave_vid, warren_wave) - warren_wave = warren_wave * 1e-4 ! um -> cm + warren_wave = warren_wave * 1e-4_r8 ! um -> cm call wrap_inq_varid(fid, 'm_real', real_vid) call wrap_get_var_realx(fid, real_vid, warren_real) @@ -227,10 +236,10 @@ subroutine CARMA_DefineModel(carma, rc) if (wave(i) > warren_wave(j)) then if (j > 1) then interp = (wave(i) - warren_wave(j-1)) / (warren_wave(j) - warren_wave(j-1)) - refidx_ice(i) = cmplx(warren_real(j-1) + interp*(warren_real(j) - warren_real(j-1)), & - warren_imag(j-1) + interp*(warren_imag(j) - warren_imag(j-1))) + refidx_ice(i,1) = cmplx(warren_real(j-1) + interp*(warren_real(j) - warren_real(j-1)), & + warren_imag(j-1) + interp*(warren_imag(j) - warren_imag(j-1)), kind=f) else - refidx_ice(i) = cmplx(warren_real(j), warren_imag(j)) + refidx_ice(i,1) = cmplx(warren_real(j), warren_imag(j), kind=f) endif exit @@ -240,8 +249,8 @@ subroutine CARMA_DefineModel(carma, rc) end if call CARMAGROUP_Create(carma, I_GRP_CRICE, "ice crystal", rmin, 2.2_f, I_SPHERE, 1._f, .true., & - rc, do_mie=carma_do_pheat, refidx=refidx_ice, shortname="CRICE") - if (rc < 0) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + rc, do_mie=carma_do_pheat, shortname="CRICE") + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') ! Define the Elements @@ -250,15 +259,15 @@ subroutine CARMA_DefineModel(carma, rc) ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "meteor smoke", RHO_METEOR_SMOKE, & I_INVOLATILE, I_METEOR_SMOKE, rc, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, I_ELEM_CRICE, I_GRP_CRICE, "ice crystal", RHO_I, & - I_VOLATILE, I_ICE, rc, shortname="CRICE") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + I_VOLATILE, I_ICE, rc, shortname="CRICE", refidx=refidx_ice) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, I_ELEM_CRCORE, I_GRP_CRICE, "ice core", RHO_METEOR_SMOKE, & I_COREMASS, I_METEOR_SMOKE, rc, shortname="CRCORE") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -267,25 +276,25 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Gases call CARMAGAS_Create(carma, I_GAS_H2O, "Water Vapor", WTMOL_H2O, & I_VAPRTN_H2O_MURPHY2005, I_GCOMP_H2O, rc, shortname="Q", ds_threshold=0.2_f) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.') ! Define the Processes call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') call CARMA_AddNucleation(carma, I_ELEM_DUST, I_ELEM_CRCORE, I_HETNUC, 0._f, rc, & igas=I_GAS_H2O, ievp2elem=I_ELEM_DUST) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.') call CARMA_AddGrowth(carma, I_ELEM_CRICE, I_GAS_H2O, rc) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddGrowth failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddGrowth failed.') call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_CRICE, I_GRP_CRICE, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -295,7 +304,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -320,14 +329,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -353,14 +362,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -391,10 +400,10 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -413,6 +422,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilat ! latitude index @@ -552,7 +562,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if end do - if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then + if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy) end if @@ -598,7 +608,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -606,7 +616,7 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use ioFileMod, only: getfil use constituents, only: pcnst use wrap_nf @@ -616,6 +626,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure integer :: ilev ! level index @@ -641,7 +652,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.") + if (rc < 0) call endrun("CARMAMODEL_InitializeModel: CARMA_Get failed.") ! Initialize the emissions rate table. if (carma_do_emission) then @@ -682,7 +693,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) carma_emis_ilev_max = carma_emis_nLevs do ilev = 1, carma_emis_nLevs - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_min = ilev + 1 else exit @@ -690,7 +701,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do do ilev = carma_emis_nLevs, 1, -1 - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_max = ilev - 1 else exit @@ -759,7 +770,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! There should be one time for each day of the year, so ! quit if it isn't correct. if (carma_escale_nTimes .ne. 365) then - call endrun("CARMA_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") + call endrun("CARMAMODEL_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.") endif call wrap_inq_dimid(fid, "ltime", ltime_did) @@ -782,7 +793,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) call wrap_inq_varid(fid, 'SGRF', grf_vid) tmp = nf90_get_var (fid, grf_vid, carma_escale_grf) if (tmp/=NF90_NOERR) then - write(iulog,*) 'CARMA_InitializeModel: error reading varid =', grf_vid + write(iulog,*) 'CARMAMODEL_InitializeModel: error reading varid =', grf_vid call handle_error (tmp) end if @@ -818,7 +829,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) endif return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -830,8 +841,9 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 + use pmgrid, only: plat, plev, plon implicit none @@ -852,15 +864,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -879,6 +931,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + integer :: icol !! column index + integer :: ibin !! bin index + real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s + real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s + character(len=16) :: binname !! names bins + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer :: i + integer :: icnst !! constituent index + integer :: ienconc !! concentration element index + integer :: ncore !! number of cores + integer :: icorelem(NELEM) !! core element index + real(r8) :: mair(pver) !! Mass of air column (kg/m2) + real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2) + real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2) + real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s) + real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s) + real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2) + real(r8) :: so2(pcols) !! SO2 gas (kg/m2) + real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2) + real(r8) :: bddust(pcols) !! Burden dust (kg/m2) + real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2) + real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2) + real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2) + character(len=16) :: shortname + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 b/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 index 4a9e08d5be..166bb66f3d 100644 --- a/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 +++ b/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 @@ -223,7 +223,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Read in the tables. call wrap_inq_varid(fid, 'wavelength', wave_vid) call wrap_get_var_realx(fid, wave_vid, warren_wave) - warren_wave = warren_wave * 1e-4 ! um -> cm + warren_wave = warren_wave * 1e-4_r8 ! um -> cm call wrap_inq_varid(fid, 'm_real', real_vid) call wrap_get_var_realx(fid, real_vid, warren_real) @@ -617,7 +617,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if end do - if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then + if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy) end if @@ -753,7 +753,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) carma_emis_ilev_max = carma_emis_nLevs do ilev = 1, carma_emis_nLevs - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_min = ilev + 1 else exit @@ -761,7 +761,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do do ilev = carma_emis_nLevs, 1, -1 - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_max = ilev - 1 else exit @@ -953,4 +953,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) return end subroutine CARMA_WetDeposition -end module +end module carma_model_mod diff --git a/src/physics/carma/models/sea_salt/carma_model_mod.F90 b/src/physics/carma/models/sea_salt/carma_model_mod.F90 index db01fb4b00..0f1aa889dd 100644 --- a/src/physics/carma/models/sea_salt/carma_model_mod.F90 +++ b/src/physics/carma/models/sea_salt/carma_model_mod.F90 @@ -44,14 +44,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -64,6 +69,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -83,7 +92,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -100,7 +109,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Report model specific configuration parameters. if (masterproc) then call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_Get failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.') if (do_print) write(LUNOPRT,*) '' if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :' @@ -117,7 +126,7 @@ subroutine CARMA_DefineModel(carma, rc) rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="SALT", irhswell=I_GERBER, & irhswcomp=I_SWG_SEA_SALT) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -125,7 +134,7 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "sea salt", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALT") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -137,7 +146,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -147,7 +156,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -172,14 +181,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -205,14 +214,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -243,7 +252,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -252,7 +261,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Tianyi Fan, Chuck Bardeen !! @version Dec-2010 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -270,6 +279,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: lchnk ! chunk identifier @@ -439,7 +449,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend !********************************** ! wet sea salt radius at RH = 80% !********************************** - r80cm = (c1 * (r(ibin)) ** c2 / (c3 * r(ibin) ** c4 - log10(0.8)) + (r(ibin))**3) ** (1./3.) ! [cm] + r80cm = (c1 * (r(ibin)) ** c2 / (c3 * r(ibin) ** c4 - log10(0.8_r8)) + (r(ibin))**3) ** (1._r8/3._r8) ! [cm] rdrycm = r(ibin) ! [cm] r80 = r80cm *1.e4_r8 ! [um] rdry = rdrycm*1.e4_r8 ! [um] @@ -452,7 +462,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend !********************************** ! WIND for seasalt production !********************************** - call CARMA_SurfaceWind(carma, state, icol, cam_in, u10in, rc) + call CARMAMODEL_SurfaceWind(carma, state, icol, cam_in, u10in, rc) ! Add any surface flux here. ncflx = 0.0_r8 @@ -542,7 +552,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend !Monahan B_mona = (0.38_r8 - log10(r80)) / 0.65_r8 Monahan = 1.373_r8 * (u10in**3.41_r8) * r80**(-3._r8) * & - (1._r8 + 0.057 *r80**1.05_r8) * 10._r8 ** (1.19_r8 * exp(-1. * B_mona**2)) ! dF/dr + (1._r8 + 0.057_r8 *r80**1.05_r8) * 10._r8 ** (1.19_r8 * exp(-1._r8 * B_mona**2)) ! dF/dr !Smith u14 = u10in * (1._r8 + cd_smith**0.5_r8 / xkar * log(14._r8 / 10._r8)) ! 14 meter wind @@ -641,7 +651,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -649,13 +659,14 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only: pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -664,7 +675,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -676,8 +687,9 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 + use pmgrid, only: plat, plev, plon implicit none @@ -698,15 +710,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -725,14 +777,14 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition !! Calculate the sea surface wind with a Weibull distribution. !! !! @author Tianyi Fan !! @version August-2010 - subroutine CARMA_SurfaceWind(carma, state, icol, cam_in, u10in, rc) + subroutine CARMAMODEL_SurfaceWind(carma, state, icol, cam_in, u10in, rc) use ppgrid, only: pcols, pver use physics_types, only: physics_state use camsrfexch, only: cam_in_t @@ -765,7 +817,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, cam_in, u10in, rc) u10in = uWB341 ** (1._r8 / 3.41_r8) return - end subroutine CARMA_SurfaceWind + end subroutine CARMAMODEL_SurfaceWind !! Calculate the nth mean of u using Weibull wind distribution @@ -794,7 +846,7 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) if (present(wbk)) then k = wbk else - k = 0.94*u**0.5_r8 ! follow Grini and Zender, 2004JGR + k = 0.94_r8*u**0.5_r8 ! follow Grini and Zender, 2004JGR ! k = 2.5_r8 ! Lansing's estimate end if @@ -809,4 +861,119 @@ subroutine WeibullWind(u, uth, n, uwb, wbk) end subroutine WeibullWind -end module + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + integer :: icol !! column index + integer :: ibin !! bin index + real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s + real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s + character(len=16) :: binname !! names bins + real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer :: i + integer :: icnst !! constituent index + integer :: ienconc !! concentration element index + integer :: ncore !! number of cores + integer :: icorelem(NELEM) !! core element index + real(r8) :: mair(pver) !! Mass of air column (kg/m2) + real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2) + real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2) + real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s) + real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s) + real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2) + real(r8) :: so2(pcols) !! SO2 gas (kg/m2) + real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2) + real(r8) :: bddust(pcols) !! Burden dust (kg/m2) + real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2) + real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2) + real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2) + character(len=16) :: shortname + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics + +end module carma_model_mod diff --git a/src/physics/carma/models/sulfate/carma_model_mod.F90 b/src/physics/carma/models/sulfate/carma_model_mod.F90 index abf98d1820..c19e013891 100644 --- a/src/physics/carma/models/sulfate/carma_model_mod.F90 +++ b/src/physics/carma/models/sulfate/carma_model_mod.F90 @@ -38,15 +38,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition - + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -59,6 +63,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -90,7 +98,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) use physics_buffer, only: pbuf_add_field, dtype_r8 type(carma_type), intent(inout) :: carma !! the carma object @@ -172,7 +180,7 @@ subroutine CARMA_DefineModel(carma, rc) call pbuf_add_field('VOLC_MMR', 'global', dtype_r8, (/pcols, pver/), ipbuf4so4mmr) endif - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -182,7 +190,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -207,14 +215,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -240,14 +248,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t use physics_buffer, only: pbuf_get_field @@ -325,7 +333,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, end if - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -334,7 +342,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Tianyi Fan, Chuck Bardeen !! @version Dec-2010 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -353,6 +361,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -365,7 +374,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend tendency = 0._r8 return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -373,20 +382,21 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. rc = RC_OK return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -398,7 +408,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 implicit none @@ -420,7 +430,49 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! NOTE: Initialized to 0. by the caller, so nothing needs to be done. return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add @@ -428,7 +480,7 @@ end subroutine CARMA_InitializeParticle !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -447,6 +499,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_detrain/carma_model_mod.F90 b/src/physics/carma/models/test_detrain/carma_model_mod.F90 index 16e6cb431f..fde34f8b20 100644 --- a/src/physics/carma/models/test_detrain/carma_model_mod.F90 +++ b/src/physics/carma/models/test_detrain/carma_model_mod.F90 @@ -472,4 +472,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) return end subroutine CARMA_WetDeposition -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_growth/carma_model_mod.F90 b/src/physics/carma/models/test_growth/carma_model_mod.F90 index ad57aed469..5b4a2b6ac7 100644 --- a/src/physics/carma/models/test_growth/carma_model_mod.F90 +++ b/src/physics/carma/models/test_growth/carma_model_mod.F90 @@ -10,10 +10,10 @@ !! the initial conditions of the particles. Each realization of CARMA !! microphysics has its own version of this file. !! -!! This file is a simple test case involving one group of dust particles and -!! 8 size bins. Optical properties are calculated, assuming a constant refractive -!! index of (1.55, 4e-3). The particles are not subject to particle swelling, but -!! do coagulate. +!! This file is a simple test case involving two groups: sulfate condensation nuclei +!! and ice particles. The sulfates are prescribed and the ice is prognostics. This +!! test exercises the nucleation and growth code. THe particles are sedimented, but +!! do not coagulate. !! !! @version May-2009 !! @author Chuck Bardeen @@ -43,14 +43,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 2 !! Number of particle groups @@ -63,6 +68,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -93,7 +102,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -118,11 +127,11 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, I_GRP_CRCN, "Sulfate CN", rmin_cn, 4.0_f, I_SPHERE, 1._f, .false., & rc, shortname="CRCN", cnsttype=I_CNSTTYPE_DIAGNOSTIC, & do_vtran=.false.) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, I_GRP_CRICE, "Ice", rmin_ice, 2.8_f, I_HEXAGON, 1._f / 6._f, .true., & rc, shortname="CRICE", ifallrtn=I_FALLRTN_STD_SHAPE) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') @@ -132,30 +141,30 @@ subroutine CARMA_DefineModel(carma, rc) ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, I_ELEM_CRCN, I_GRP_CRCN, "Sulfate CN", RHO_CN, & I_INVOLATILE, I_H2SO4, rc, shortname="CRCN", isolute=I_SOL_CRH2SO4) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, I_ELEM_CRICE, I_GRP_CRICE, "Ice", RHO_I, & I_VOLATILE, I_ICE, rc, shortname="CRICE") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, I_ELEM_CRCORE, I_GRP_CRICE, "Core Mass", RHO_CN, & I_COREMASS, I_H2SO4, rc, shortname="CRCORE", isolute=1) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') ! Define the Solutes call CARMASOLUTE_Create(carma, I_SOL_CRH2SO4, "Sulfuric Acid", 2, 98._f, 1.38_f, rc, shortname="CRH2SO4") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMASOLUTE_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMASOLUTE_Create failed.') ! Define the Gases call CARMAGAS_Create(carma, I_GAS_H2O, "Water Vapor", WTMOL_H2O, I_VAPRTN_H2O_MURPHY2005, I_GCOMP_H2O, rc, shortname="Q") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.') ! Define the Processes call CARMA_AddGrowth(carma, I_ELEM_CRICE, I_GAS_H2O, rc) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddGrowth failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddGrowth failed.') ! NOTE: For now, assume the latent heat for nucleation is the latent of of fusion of ! water, using the CAM constant (scaled from J/kg to erg/g). @@ -165,10 +174,10 @@ subroutine CARMA_DefineModel(carma, rc) ! the gas associated with nucleation is accounted for. call CARMA_AddNucleation(carma, I_ELEM_CRCN, I_ELEM_CRCORE, & I_AERFREEZE + I_AF_KOOP_2000, 0._f, rc, igas=I_GAS_H2O, ievp2elem=I_ELEM_CRCN) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -178,7 +187,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -203,14 +212,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -249,7 +258,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! Get the air density. call CARMASTATE_GetState(cstate, rc, rhoa_wet=rhoa_wet) - if (rc < RC_OK) call endrun('CARMA_DiagnoseBins::CARMASTATE_GetState failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DiagnoseBins::CARMASTATE_GetState failed.') ! Use a fixed sulfate size distribution. By doing this as a diagnostic group, ! the constituents for the sulfate bins do not need to be advected, which @@ -258,7 +267,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ielem = 1 call CARMAGROUP_Get(carma, igroup, rc, r=r, dr=dr, rmass=rmass) - if (rc < RC_OK) call endrun('CARMA_DiagnoseBins::CARMAGROUP_Get failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DiagnoseBins::CARMAGROUP_Get failed.') arg1(:) = n * dr(:) / (sqrt(2._f*PI) * r(:) * log(rsig)) arg2(:) = -((log(r(:)) - log(r0))**2) / (2._f*(log(rsig))**2) @@ -268,18 +277,18 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr do ibin = 1, NBIN mmr(ibin, :) = rhop(ibin) / rhoa_wet(:) call CARMASTATE_SetBin(cstate, ielem, ibin, mmr(ibin, :), rc) - if (rc < RC_OK) call endrun('CARMA_DiagnoseBins::CARMAGROUP_SetBin failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DiagnoseBins::CARMAGROUP_SetBin failed.') end do return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -310,7 +319,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -319,7 +328,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -338,6 +347,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ncol ! number of columns in chunk @@ -370,7 +380,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend tendency(:ncol, :pver) = 0.0_r8 return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -381,13 +391,14 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -396,7 +407,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -408,7 +419,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use pmgrid, only: plev @@ -431,31 +442,65 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, ! Put a horizontally uniform layer of the smallest bin size ! in the model. if (ibin == 1) then - if (ielem == I_ELEM_CRICE) then - where(mask) - q(:, plev/4) = 100e-7_r8 ! 1/4 - end where - end if - if (ielem == I_ELEM_CRCORE) then - where(mask) - q(:, plev/4) = 100e-9_r8 ! 1/4 - end where - end if + where(mask) +! q(:, 1) = 100e-9_r8 ! top + q(:, plev/4) = 100e-9_r8 ! 1/4 ! q(:, plev/2) = 100e-9_r8 ! middle ! q(:, 3*plev/4) = 100e-9_r8 ! 3/4 ! q(:, plev-1) = 100e-9_r8 ! bottom + end where end if return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -474,6 +519,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_passive/carma_model_mod.F90 b/src/physics/carma/models/test_passive/carma_model_mod.F90 index 12f4a6168e..150f1d8a5f 100644 --- a/src/physics/carma/models/test_passive/carma_model_mod.F90 +++ b/src/physics/carma/models/test_passive/carma_model_mod.F90 @@ -42,14 +42,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -62,6 +67,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -79,7 +88,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -101,7 +110,7 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, 1, "Dust", rmin, vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.15_f, & scavcoef=0.1_f, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -109,7 +118,7 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -120,10 +129,10 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes call CARMA_AddCoagulation(carma, 1, 1, 1, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -133,7 +142,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -158,14 +167,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -191,14 +200,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -229,7 +238,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -238,7 +247,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -257,6 +266,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ncol ! number of columns in chunk @@ -289,7 +299,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend tendency(:ncol, :pver) = 0.0_r8 return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -300,13 +310,14 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -315,7 +326,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -327,7 +338,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use pmgrid, only: plev @@ -360,15 +371,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, end if return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -387,6 +438,95 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_radiative/carma_model_mod.F90 b/src/physics/carma/models/test_radiative/carma_model_mod.F90 index 8acff28edb..d1b248df5a 100644 --- a/src/physics/carma/models/test_radiative/carma_model_mod.F90 +++ b/src/physics/carma/models/test_radiative/carma_model_mod.F90 @@ -42,14 +42,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 1 !! Number of particle groups @@ -65,6 +70,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) = (/ 0._f, 0.5_f, 0.7_f, 0.8_f, 0.9_f, 0.95_f, 0.98_f, 0.99_f /) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -82,7 +91,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -90,14 +99,14 @@ subroutine CARMA_DefineModel(carma, rc) real(kind=f), parameter :: RHO_DUST = 2.0_f ! density of dust particles (g/cm) real(kind=f), parameter :: rmin = 1e-5_f ! minimum radius (cm) real(kind=f), parameter :: vmrat = 2.0_f ! volume ratio - complex(kind=f) :: refidx(NWAVE) ! refractice indices + complex(kind=f) :: refidx(NWAVE, NREFIDX) ! refractice indices ! Default return code. rc = RC_OK ! Use the same refractive index at all wavelengths. This value is typical of dust in ! the visible. - refidx(:) = (1.55_f, 4e-3_f) + refidx(:,1) = (1.55_f, 4e-3_f) ! Define the Groups ! @@ -108,16 +117,16 @@ subroutine CARMA_DefineModel(carma, rc) ! should also be defined. call CARMAGROUP_Create(carma, 1, "Dust", rmin, vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.15_f, & - scavcoef=0.1_f, shortname="DUST", refidx=refidx, do_mie=.true.) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + scavcoef=0.1_f, shortname="DUST", do_mie=.true.) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements ! ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. - call CARMAELEMENT_Create(carma, 1, 1, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="DUST") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + call CARMAELEMENT_Create(carma, 1, 1, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="DUST", refidx=refidx) + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -128,10 +137,10 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes call CARMA_AddCoagulation(carma, 1, 1, 1, I_COLLEC_DATA, rc) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.') return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -141,7 +150,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -166,14 +175,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -199,14 +208,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -237,7 +246,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -246,7 +255,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -265,6 +274,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ncol ! number of columns in chunk @@ -297,7 +307,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend tendency(:ncol, :pver) = 0.0_r8 return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -308,13 +318,14 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -323,7 +334,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -335,7 +346,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use pmgrid, only: plev @@ -368,15 +379,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, end if return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -395,6 +446,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_swelling/carma_model_mod.F90 b/src/physics/carma/models/test_swelling/carma_model_mod.F90 index ce55401475..4e98bb5cd1 100644 --- a/src/physics/carma/models/test_swelling/carma_model_mod.F90 +++ b/src/physics/carma/models/test_swelling/carma_model_mod.F90 @@ -43,14 +43,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 3 !! Number of particle groups @@ -63,6 +68,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -80,7 +89,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -100,19 +109,19 @@ subroutine CARMA_DefineModel(carma, rc) call CARMAGROUP_Create(carma, 1, "None", rmin, vmrat, I_SPHERE, 1._f, .false., & rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="SALT") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') call CARMAGROUP_Create(carma, 2, "Fitzgerald", rmin, vmrat, I_SPHERE, 1._f, & .false., rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="SALTFZ", irhswell=I_FITZGERALD, & irhswcomp=I_SWF_NACL) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') call CARMAGROUP_Create(carma, 3, "Gerber", rmin, vmrat, I_SPHERE, 1._f, & .false., rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, & scavcoef=0.1_f, shortname="SALTGB", irhswell=I_GERBER, & irhswcomp=I_SWG_SEA_SALT) - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.') ! Define the Elements @@ -120,13 +129,13 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "None", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALT") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, 2, 2, "Fitz", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALTFZ") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') call CARMAELEMENT_Create(carma, 3, 3, "Gerb", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALTGB") - if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.') + if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.') ! Define the Solutes @@ -138,7 +147,7 @@ subroutine CARMA_DefineModel(carma, rc) ! Define the Processes return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -148,7 +157,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair @@ -173,14 +182,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -206,14 +215,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use camsrfexch, only: cam_out_t @@ -244,7 +253,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, ! code to determine the bulk mass from the CARMA state. return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. By default, there is no @@ -253,7 +262,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -272,6 +281,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure integer :: ncol ! number of columns in chunk @@ -304,7 +314,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend tendency(:ncol, :pver) = 0.0_r8 return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -312,13 +322,14 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(in) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. @@ -327,7 +338,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) ! Add initialization here. return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -339,7 +350,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use pmgrid, only: plev @@ -369,15 +380,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, end where return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -396,6 +447,95 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_tracers/carma_model_mod.F90 b/src/physics/carma/models/test_tracers/carma_model_mod.F90 index 9ed84a9471..40aa2b911c 100644 --- a/src/physics/carma/models/test_tracers/carma_model_mod.F90 +++ b/src/physics/carma/models/test_tracers/carma_model_mod.F90 @@ -49,14 +49,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 6 !! Number of particle groups @@ -69,6 +74,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -98,7 +107,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -112,7 +121,7 @@ subroutine CARMA_DefineModel(carma, rc) rc = RC_OK call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.') ! Report model specific configuration parameters. if (masterproc) then @@ -132,22 +141,22 @@ subroutine CARMA_DefineModel(carma, rc) ! defined. If wetdep is defined, then the optional solubility factor ! should also be defined. call CARMAGROUP_Create(carma, 1, "Region 1", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG1") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 2, "Region 2", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG2") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 3, "Region 3", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG3") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 4, "Region 4", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG4") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 5, "Region 5", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG5") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 6, "Rest of World", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG6") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') ! Define the Elements @@ -155,22 +164,22 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "Region 1", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG1") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 2, 2, "Region 2", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG2") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 3, 3, "Region 3", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG3") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 4, 4, "Region 4", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG4") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 5, 5, "Region 5", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG5") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 6, 6, "Rest of World", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG6") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') ! Define the Solutes @@ -183,7 +192,7 @@ subroutine CARMA_DefineModel(carma, rc) return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -193,7 +202,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair, cappa @@ -219,14 +228,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -252,7 +261,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. @@ -262,7 +271,7 @@ end subroutine CARMA_DiagnoseBins !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver @@ -325,7 +334,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, end if return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. @@ -352,7 +361,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -372,6 +381,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure real(r8) :: lat(state%ncol) ! latitude (degrees) @@ -489,7 +499,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -500,20 +510,22 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst + implicit none type(carma_type), intent(inout) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. rc = RC_OK return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -525,7 +537,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 implicit none @@ -552,15 +564,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, end do return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -579,6 +631,93 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/test_tracers2/carma_model_mod.F90 b/src/physics/carma/models/test_tracers2/carma_model_mod.F90 index ecb3324ed8..d6a74c4d12 100644 --- a/src/physics/carma/models/test_tracers2/carma_model_mod.F90 +++ b/src/physics/carma/models/test_tracers2/carma_model_mod.F90 @@ -49,14 +49,19 @@ module carma_model_mod private ! Declare the public methods. - public CARMA_DefineModel - public CARMA_Detrain - public CARMA_DiagnoseBins - public CARMA_DiagnoseBulk - public CARMA_EmitParticle - public CARMA_InitializeModel - public CARMA_InitializeParticle - public CARMA_WetDeposition + public CARMAMODEL_CalculateCloudborneDiagnostics + public CARMAMODEL_CreateOpticsFile + public CARMAMODEL_DefineModel + public CARMAMODEL_Detrain + public CARMAMODEL_DiagnoseBins + public CARMAMODEL_DiagnoseBulk + public CARMAMODEL_EmitParticle + public CARMAMODEL_InitializeModel + public CARMAMODEL_InitializeParticle + public CARMAMODEL_OutputBudgetDiagnostics + public CARMAMODEL_OutputCloudborneDiagnostics + public CARMAMODEL_OutputDiagnostics + public CARMAMODEL_WetDeposition ! Declare public constants integer, public, parameter :: NGROUP = 7 !! Number of particle groups @@ -69,6 +74,10 @@ module carma_model_mod integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations real(kind=f), public :: mie_rh(NMIE_RH) + integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations + real(kind=f), public :: mie_wtp(NMIE_WTP) + integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element + ! Defines whether the groups should undergo deep convection in phase 1 or phase 2. ! Water vapor and cloud particles are convected in phase 1, while all other constituents ! are done in phase 2. @@ -99,7 +108,7 @@ module carma_model_mod !! !! @version May-2009 !! @author Chuck Bardeen - subroutine CARMA_DefineModel(carma, rc) + subroutine CARMAMODEL_DefineModel(carma, rc) type(carma_type), intent(inout) :: carma !! the carma object integer, intent(out) :: rc !! return code, negative indicates failure @@ -113,7 +122,7 @@ subroutine CARMA_DefineModel(carma, rc) rc = RC_OK call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT) - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.') ! Report model specific configuration parameters. if (masterproc) then @@ -133,25 +142,25 @@ subroutine CARMA_DefineModel(carma, rc) ! defined. If wetdep is defined, then the optional solubility factor ! should also be defined. call CARMAGROUP_Create(carma, 1, "Region 1", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG1") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 2, "Region 2", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG2") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 3, "Region 3", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG3") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 4, "Region 4", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG4") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 5, "Region 5", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG5") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 6, "Region 6", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG6") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') call CARMAGROUP_Create(carma, 7, "Rest of World", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG7") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.') ! Define the Elements @@ -159,25 +168,25 @@ subroutine CARMA_DefineModel(carma, rc) ! NOTE: For CAM, the optional shortname needs to be provided for the group. These names ! should be 6 characters or less and without spaces. call CARMAELEMENT_Create(carma, 1, 1, "Region 1", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG1") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 2, 2, "Region 2", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG2") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 3, 3, "Region 3", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG3") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 4, 4, "Region 4", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG4") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 5, 5, "Region 5", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG5") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 6, 6, "Region 6", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG6") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') call CARMAELEMENT_Create(carma, 7, 7, "Rest of World", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG7") - if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.') + if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.') ! Define the Solutes @@ -190,7 +199,7 @@ subroutine CARMA_DefineModel(carma, rc) return - end subroutine CARMA_DefineModel + end subroutine CARMAMODEL_DefineModel !! Defines all the CARMA components (groups, elements, solutes and gases) and process @@ -200,7 +209,7 @@ end subroutine CARMA_DefineModel !! @author Chuck Bardeen !! !! @see CARMASTATE_SetDetrain - subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, & tnd_qsnow, tnd_nsnow) use camsrfexch, only: cam_in_t use physconst, only: latice, latvap, cpair, cappa @@ -226,14 +235,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, rc = RC_OK return - end subroutine CARMA_Detrain + end subroutine CARMAMODEL_Detrain !! For diagnostic groups, sets up up the CARMA bins based upon the CAM state. !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) + subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str) use time_manager, only: is_first_step implicit none @@ -259,7 +268,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr ! code to determine the mass in each bin from the CAM state. return - end subroutine CARMA_DiagnoseBins + end subroutine CARMAMODEL_DiagnoseBins !! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins. @@ -269,7 +278,7 @@ end subroutine CARMA_DiagnoseBins !! !! @version July-2009 !! @author Chuck Bardeen - subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & + subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, & prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver @@ -332,7 +341,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, end if return - end subroutine CARMA_DiagnoseBulk + end subroutine CARMAMODEL_DiagnoseBulk !! Calculates the emissions for CARMA aerosol particles. @@ -359,7 +368,7 @@ end subroutine CARMA_DiagnoseBulk !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc) + subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc) use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver use physics_types, only: physics_state @@ -379,6 +388,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend type(cam_in_t), intent(in) :: cam_in !! surface inputs real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s) real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s) + type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer integer, intent(out) :: rc !! return code, negative indicates failure real(r8) :: lat(state%ncol) ! latitude (degrees) @@ -497,7 +507,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend end if return - end subroutine CARMA_EmitParticle + end subroutine CARMAMODEL_EmitParticle !! Allows the model to perform its own initialization in addition to what is done @@ -508,20 +518,21 @@ end subroutine CARMA_EmitParticle !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeModel(carma, lq_carma, rc) + subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc) use constituents, only : pcnst implicit none type(carma_type), intent(inout) :: carma !! the carma object logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent !! could have a CARMA tendency + type(physics_buffer_desc), pointer :: pbuf2d(:,:) integer, intent(out) :: rc !! return code, negative indicates failure ! Default return code. rc = RC_OK return - end subroutine CARMA_InitializeModel + end subroutine CARMAMODEL_InitializeModel !! Sets the initial condition for CARMA aerosol particles. By default, there are no @@ -533,7 +544,7 @@ end subroutine CARMA_InitializeModel !! !! @author Chuck Bardeen !! @version May-2009 - subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) + subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc) use shr_kind_mod, only: r8 => shr_kind_r8 implicit none @@ -560,15 +571,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, end do return - end subroutine CARMA_InitializeParticle + end subroutine CARMAMODEL_InitializeParticle + + !! This routine is an extension of CARMA_CreateOpticsFile() that allows for + !! model specific tables to be created in addition to the model independent + !! methods that are in carma_intr.F90. + !! + !! The opticsType that is specified for the group determines how the optical + !! properties will be generated for that group. Each group can use a different + !! optics method if needed. Refractive indices need for these calculation are + !! are specified in the group's elements rather than at the group level. This + !! allows various mixing approaches to be used to determine the refractive index + !! for the particle as a whole. If the refractive index for water is needed, + !! it is specific the the CARMAGAS object for H2O. + subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc) + + implicit none + + type(carma_type), intent(inout) :: carma !! the carma object + integer, intent(in) :: igroup !! group identifier + integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90) + integer, intent(out) :: rc !! return code, negative indicates failure + ! Local variables + logical :: do_mie + integer :: cnsttype ! constituent type + + ! Assume success. + rc = 0 + + ! What type of calculation is needed for this group? + ! + ! NOTE: Some of these calculations generate optical properties as single mass + ! coefficients, while others are lookup tables designed around multiple + ! dimensions. + select case (opticsType) + + case default + call endrun('carma_CreateOpticsFile:: Unknown optics type.') + end select + + return + end subroutine CARMAMODEL_CreateOpticsFile !! Called after wet deposition has been performed. Allows the specific model to add !! wet deposition of CARMA aerosols to the aerosols being communicated to the surface. !! !! @version July-2011 !! @author Chuck Bardeen - subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) + subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) use camsrfexch, only: cam_out_t implicit none @@ -587,6 +638,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) rc = RC_OK return - end subroutine CARMA_WetDeposition + end subroutine CARMAMODEL_WetDeposition + + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc) + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_CalculateCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc) + use cam_history, only: outfld + use constituents, only: pcnst, cnst_get_ind + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas + type(physics_state), intent(in) :: state !! Physics state variables - before pname + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend + real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputBudgetDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc) + use cam_history, only: outfld + + type(carma_type), intent(in) :: carma !! the carma object + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + real(r8), intent(in) :: dt !! timestep (s) + character(*), intent(in) :: pname !! short name of the physics package + real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputCloudborneDiagnostics + + !! Called at the end of the timestep after all the columns have been processed to + !! to allow additional diagnostics that have been stored in pbuf to be output. + !! + !! Stub version + subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc) + use cam_history, only: outfld + use constituents, only: cnst_get_ind + use camsrfexch, only: cam_in_t + + type(carma_type), intent(in) :: carma !! the carma object + integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element + type(physics_state), intent(in) :: state !! Physics state variables - before CARMA + type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies + type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer + type(cam_in_t), intent(in) :: cam_in !! surface inputs + integer, intent(out) :: rc !! return code, negative indicates failure + + ! Default return code. + rc = RC_OK + + return + end subroutine CARMAMODEL_OutputDiagnostics -end module +end module carma_model_mod diff --git a/src/physics/carma/models/tholin/carma_model_mod.F90 b/src/physics/carma/models/tholin/carma_model_mod.F90 index 460971db9d..ac5216f130 100755 --- a/src/physics/carma/models/tholin/carma_model_mod.F90 +++ b/src/physics/carma/models/tholin/carma_model_mod.F90 @@ -102,7 +102,7 @@ subroutine CARMA_DefineModel(carma, rc) integer, intent(out) :: rc !! return code, negative indicates failure ! Local variables - real(kind=f) :: RHO_THOLIN = 0.64 ! density of tholin particles (g/cm) + real(kind=f) :: RHO_THOLIN = 0.64_f ! density of tholin particles (g/cm) real(kind=f), parameter :: tholin_rmin = 1.e-7_f ! dust minimum radius (cm) real(kind=f), parameter :: tholin_vmrat = 2.5_f ! dust volume ratio @@ -509,7 +509,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) carma_emis_ilev_max = carma_emis_nLevs do ilev = 1, carma_emis_nLevs - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_min = ilev + 1 else exit @@ -517,7 +517,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc) end do do ilev = carma_emis_nLevs, 1, -1 - if (carma_emis_rate(ilev) <= 0.0) then + if (carma_emis_rate(ilev) <= 0.0_r8) then carma_emis_ilev_max = ilev - 1 else exit @@ -639,4 +639,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc) return end subroutine CARMA_WetDeposition -end module +end module carma_model_mod diff --git a/test/system/TR8.sh b/test/system/TR8.sh index cbdb400463..22ec597f5d 100755 --- a/test/system/TR8.sh +++ b/test/system/TR8.sh @@ -10,6 +10,8 @@ ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/cam rc=$? ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/camrt rc=`expr $? + $rc` +ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/carma +rc=`expr $? + $rc` ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/rrtmg -s aer_src rc=`expr $? + $rc` ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/rrtmgp -s data,ext @@ -27,6 +29,8 @@ ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/cam rc=$? ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/camrt rc=`expr $? + $rc` +ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/carma +rc=$? ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/rrtmg -s aer_src rc=`expr $? + $rc` ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/rrtmgp -s data,ext From ee4a28bd6562e773e8d69dddc79eefce3575ee40 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Wed, 4 Dec 2024 11:14:37 -0700 Subject: [PATCH 58/82] correct the AOASRC name modified: src/physics/cam/aoa_tracers.F90 --- src/physics/cam/aoa_tracers.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/physics/cam/aoa_tracers.F90 b/src/physics/cam/aoa_tracers.F90 index fc656ad618..2d42853756 100644 --- a/src/physics/cam/aoa_tracers.F90 +++ b/src/physics/cam/aoa_tracers.F90 @@ -34,10 +34,10 @@ module aoa_tracers character(len=4), parameter :: c_names(ncnst) = (/'AOA1', 'HORZ', 'VERT'/) ! constituent source/sink names - character(len=8), parameter :: src_names(ncnst) = (/'AOAMFSRC', 'HORZSRC ', 'VERTSRC '/) + character(len=7), parameter :: src_names(ncnst) = (/'AOA1SRC', 'HORZSRC', 'VERTSRC'/) integer :: ifirst = -1 ! global index of first constituent - integer :: ixaoa = -1 ! global index for AOAMFSRC tracer + integer :: ixaoa = -1 ! global index for AOA1SRC tracer integer :: ixht = -1 ! global index for HORZ tracer integer :: ixvt = -1 ! global index for VERT tracer @@ -347,7 +347,7 @@ subroutine aoa_tracers_timestep_tend(state, ptend, dt) lchnk = state%lchnk ncol = state%ncol - ! AOAMF + ! AOA1 xmmr = mmr0*(1._r8 + per_yr*years) ptend%q(1:ncol,pver,ixaoa) = (xmmr - state%q(1:ncol,pver,ixaoa)) / dt @@ -403,7 +403,7 @@ subroutine init_cnst_3d(m, latvals, lonvals, mask, q) if (m == ixaoa) then - ! AOAMF + ! AOA1 q(:,:) = 0.0_r8 else if (m == ixht) then From 3aa74633894adc742e7e0590a9786d5c8f9be6a4 Mon Sep 17 00:00:00 2001 From: peverwhee Date: Wed, 4 Dec 2024 14:01:54 -0700 Subject: [PATCH 59/82] update to head of cam_development; update cime and share externals --- .gitmodules | 4 ++-- cime | 2 +- share | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index 817bb1ff6b..7fed08dbb7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -151,7 +151,7 @@ fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git [submodule "cime"] path = cime url = https://github.com/ESMCI/cime -fxtag = cime6.1.41 +fxtag = cime6.1.47 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESMCI/cime @@ -172,7 +172,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git [submodule "share"] path = share url = https://github.com/ESCOMP/CESM_share -fxtag = share1.1.2 +fxtag = share1.1.4 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESCOMP/CESM_share diff --git a/cime b/cime index 1236c0fede..f28506021f 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit 1236c0feded460aef3e5bdba18e4b850f1997346 +Subproject commit f28506021f122fbfab8fea741da35ac48ab875b2 diff --git a/share b/share index f6f31fd61c..63ae6cc216 160000 --- a/share +++ b/share @@ -1 +1 @@ -Subproject commit f6f31fd61cb8f80aee97311fcca64b3e26b0202c +Subproject commit 63ae6cc216c517d3ced4d3466d3616b4c24107b5 From 398d956452e78ea36e1101cf18b9a5069ce21ca0 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Wed, 4 Dec 2024 16:16:47 -0700 Subject: [PATCH 60/82] set carma_sulfnuc_method namelist option modified: bld/build-namelist modified: bld/namelist_files/namelist_definition.xml --- bld/build-namelist | 3 ++- bld/namelist_files/namelist_definition.xml | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/bld/build-namelist b/bld/build-namelist index 66c3574a62..29c7d6b316 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -1268,6 +1268,7 @@ if ($carma ne 'none') { add_default($nl, 'carma_model', 'val'=>$carma); add_default($nl, 'carma_flag', 'val'=>'.true.'); add_default($nl, 'history_carma', 'val'=>'.true.'); + add_default($nl, 'carma_sulfnuc_method','val'=>'ZhaoTurco'); } if ($carma eq 'bc_strat') { add_default($nl, 'carma_do_drydep', 'val'=>'.true.'); @@ -1587,7 +1588,7 @@ if (defined $nl->get_value('prescribed_strataero_3modes')) { # determine if prescribed stratospheric aerosol data is needed if ( ($het_chem) || ($nl->get_value('prescribed_strataero_feedback') =~ /$TRUE/io ) ){ - if ( ($carma ne 'sulfate') && !($nl->get_value('modal_strat_sulfate') =~ /$TRUE/io) ) { # if no prognostic stratospheric aerosols + if ( !($nl->get_value('modal_strat_sulfate') =~ /$TRUE/io) ) { # if no prognostic stratospheric aerosols unless (defined $nl->get_value('prescribed_strataero_type')) { add_default($nl, 'prescribed_strataero_type','val'=>'CYCLICAL'); diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index bd003c779a..d216f837f1 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -4476,6 +4476,20 @@ is not active. Default: none + + Nucleation methods: + ZhaoTurco + Zhao and Turco, JAS, V.26, No.5, 1995. + Vehkamaki + Vehkamaki, H., M. Kulmala, I. Napari, K.E.J. Lehtinen, + C. Timmreck, M. Noppel and A. Laaksonen, 2002, + An improved parameterization for sulfuric acid-water nucleation + rates for tropospheric and stratospheric conditions, + J. Geophys. Res., 107, 4622, doi:10.1029/2002jd002184 +Default: none + + A fraction that scales how tight the convergence criteria are to From ea7b2484f69a9c3aece4ba318c15e04c550854f4 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 5 Dec 2024 08:51:33 -0700 Subject: [PATCH 61/82] change derecho 10x15 res tests to 4x5 modified: cime_config/testdefs/testlist_cam.xml modified: cime_config/config_pes.xml --- cime_config/config_pes.xml | 16 ++-- cime_config/testdefs/testlist_cam.xml | 110 +++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 11 deletions(-) diff --git a/cime_config/config_pes.xml b/cime_config/config_pes.xml index 47bbcc4af3..f488c21b27 100644 --- a/cime_config/config_pes.xml +++ b/cime_config/config_pes.xml @@ -1678,14 +1678,14 @@ none - 32 - 32 - 32 - 32 - 32 - 32 - 32 - 32 + 36 + 36 + 36 + 36 + 36 + 36 + 36 + 36 1 diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index 2801e231f7..d4fc9d40a8 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -583,6 +583,14 @@ + + + + + + + + @@ -605,6 +613,14 @@ + + + + + + + + @@ -616,7 +632,15 @@ - + + + + + + + + + @@ -628,6 +652,14 @@ + + + + + + + + @@ -640,6 +672,14 @@ + + + + + + + + @@ -651,6 +691,14 @@ + + + + + + + + @@ -659,9 +707,17 @@ - + + + + + + + + + @@ -673,6 +729,14 @@ + + + + + + + + @@ -684,6 +748,14 @@ + + + + + + + + @@ -696,6 +768,14 @@ + + + + + + + + @@ -743,6 +823,14 @@ + + + + + + + + @@ -754,6 +842,14 @@ + + + + + + + + @@ -762,9 +858,17 @@ - + + + + + + + + + From 5865cd8aed0fb0e6f2ac784ea9f9fe9564fd56bc Mon Sep 17 00:00:00 2001 From: peverwhee Date: Tue, 17 Dec 2024 10:04:00 -0700 Subject: [PATCH 62/82] update externals; use temp ctsm tag --- .gitmodules | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index 7fed08dbb7..f72ec58ae7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -151,14 +151,14 @@ fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git [submodule "cime"] path = cime url = https://github.com/ESMCI/cime -fxtag = cime6.1.47 +fxtag = cime6.1.49 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESMCI/cime [submodule "cmeps"] path = components/cmeps url = https://github.com/ESCOMP/CMEPS.git -fxtag = cmeps1.0.22 +fxtag = cmeps1.0.32 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git @@ -172,7 +172,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git [submodule "share"] path = share url = https://github.com/ESCOMP/CESM_share -fxtag = share1.1.4 +fxtag = share1.1.6 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESCOMP/CESM_share @@ -192,8 +192,8 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CESM_CICE [submodule "clm"] path = components/clm -url = https://github.com/ESCOMP/CTSM -fxtag = ctsm5.3.002 +url = https://github.com/jedwards4b/CTSM +fxtag = 14aad99fea41c4bef32205494290a675200d3058 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESCOMP/CTSM From f040c7cf8df27df25950c6c529a16cf273bb4d67 Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Tue, 17 Dec 2024 13:57:40 -0700 Subject: [PATCH 63/82] update cdeps external --- .gitmodules | 2 +- cime | 2 +- components/cdeps | 2 +- components/clm | 2 +- components/cmeps | 2 +- share | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitmodules b/.gitmodules index f72ec58ae7..c1e9973a6a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -165,7 +165,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git [submodule "cdeps"] path = components/cdeps url = https://github.com/ESCOMP/CDEPS.git -fxtag = cdeps1.0.53 +fxtag = cdeps1.0.61 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git diff --git a/cime b/cime index f28506021f..b2f271b174 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit f28506021f122fbfab8fea741da35ac48ab875b2 +Subproject commit b2f271b1742533715a05701b1bdd80a24bb2ad77 diff --git a/components/cdeps b/components/cdeps index f6bc97483a..0750c91753 160000 --- a/components/cdeps +++ b/components/cdeps @@ -1 +1 @@ -Subproject commit f6bc97483a1bfb7352c6c5610a13ed898a86990b +Subproject commit 0750c9175395d3ba3bf8eba65703dee230d08572 diff --git a/components/clm b/components/clm index 16cf4ac469..14aad99fea 160000 --- a/components/clm +++ b/components/clm @@ -1 +1 @@ -Subproject commit 16cf4ac469614f4b329c7da206c3d6b9b773bb03 +Subproject commit 14aad99fea41c4bef32205494290a675200d3058 diff --git a/components/cmeps b/components/cmeps index 1355710f04..a91cedfe58 160000 --- a/components/cmeps +++ b/components/cmeps @@ -1 +1 @@ -Subproject commit 1355710f04fa6286a13e8056e35c6736e7250e3d +Subproject commit a91cedfe58658a9fc391195481137a2d83372c25 diff --git a/share b/share index 63ae6cc216..a48ff8790a 160000 --- a/share +++ b/share @@ -1 +1 @@ -Subproject commit 63ae6cc216c517d3ced4d3466d3616b4c24107b5 +Subproject commit a48ff8790a21d3831873ed9f023a43c606a1ef03 From 2120003618a88ea7642e981a0c1b780b69be60b9 Mon Sep 17 00:00:00 2001 From: peverwhee Date: Thu, 19 Dec 2024 16:39:35 -0700 Subject: [PATCH 64/82] update clm tag --- .gitmodules | 4 ++-- components/clm | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index c1e9973a6a..0176e8431c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -192,8 +192,8 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CESM_CICE [submodule "clm"] path = components/clm -url = https://github.com/jedwards4b/CTSM -fxtag = 14aad99fea41c4bef32205494290a675200d3058 +url = https://github.com/ESCOMP/CTSM +fxtag = ctsm5.3.016 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESCOMP/CTSM diff --git a/components/clm b/components/clm index 14aad99fea..f437651ee4 160000 --- a/components/clm +++ b/components/clm @@ -1 +1 @@ -Subproject commit 14aad99fea41c4bef32205494290a675200d3058 +Subproject commit f437651ee449789af9325882bb0acc09576c9411 From ee5b5400f28814297bf80a3428bdac30a91d237a Mon Sep 17 00:00:00 2001 From: peverwhee Date: Thu, 19 Dec 2024 17:18:05 -0700 Subject: [PATCH 65/82] initial changelog --- doc/ChangeLog | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 746fead140..7fb8dacc70 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,74 @@ =============================================================== +Tag name: cam6_4_048 +Originator(s): jedwards4b, peverwhee +Date: 20 December 2024 +One-line Summary: Timestamp in rpointer name +Github PR URL: https://github.com/ESCOMP/CAM/pull/1147 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): +#1146 - Add timestep to rpointer file name +- Updates to externals, nuopc cap, and cam control code to handle timestamp in +rpointer file + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: N/A + +List any changes to the defaults for the boundary datasets: N/A + +Describe any substantial timing or memory changes: N/A + +Code reviewed by: brian-eaton + +List all files eliminated: N/A + +List all files added and what they do: N/A + +List all existing files that have been modified, and describe the changes: +M .gitmodules +- update cmeps, cdeps, cime, share, clm externals + +M src/control/cam_initfiles.F90 +- look for new timestamped rpointer file + +M src/control/cam_restart.F90 +- remove unnecessary conditionals for optional variables + +M src/cpl/nuopc/atm_comp_nuopc.F90 +- update variable names coming from coupler + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + +SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie (Overall: FAIL) +SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s (Overall: FAIL) + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + +ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s (Overall: FAIL) +SMS_Ld1.f09_f09_mg17.FCHIST_GC.derecho_intel.cam-outfrq1d (Overall: DIFF) + - pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 + +derecho/nvhpc/aux_cam: + +izumi/nag/aux_cam: + +DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) + - pre-existing failure -- issue #670 + +izumi/gnu/aux_cam: + +CAM tag used for the baseline comparison tests if different than previous +tag: + +Summarize any changes to answers: + +=============================================================== + Tag name: cam6_4_047 Originator(s): jedwards4b, fvitt Date: 19 November 2024 From 19f0d962144bfc9d8cd41a0fe98d6db79aa67ec1 Mon Sep 17 00:00:00 2001 From: peverwhee Date: Fri, 20 Dec 2024 16:17:21 -0700 Subject: [PATCH 66/82] updated changelog --- doc/ChangeLog | 82 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 7fb8dacc70..cf2aa2517d 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -27,7 +27,12 @@ List all files added and what they do: N/A List all existing files that have been modified, and describe the changes: M .gitmodules -- update cmeps, cdeps, cime, share, clm externals +- update externals for rpointer mods + - cime6.1.49 + - cmeps1.0.32 + - cdeps1.0.61 + - share1.1.6 + - ctsm5.3.016 M src/control/cam_initfiles.F90 - look for new timestamped rpointer file @@ -45,6 +50,64 @@ appropriate machine below. All failed tests must be justified. derecho/intel/aux_cam: +ERC_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq3s_cosp (Overall: NLFAIL) details: +ERC_D_Ln9.f19_f19_mg17.QPMOZ.derecho_intel.cam-outfrq3s (Overall: NLFAIL) details: +ERC_D_Ln9.f19_f19_mg17.QPX2000.derecho_intel.cam-outfrq3s (Overall: NLFAIL) details: +ERC_D_Ln9.ne16_ne16_mg17.FADIAB.derecho_intel.cam-terminator (Overall: NLFAIL) details: +ERC_D_Ln9.ne16_ne16_mg17.QPC5HIST.derecho_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details: +ERC_D_Ln9_P144x1.ne16pg3_ne16pg3_mg17.QPC6HIST.derecho_intel.cam-outfrq3s_ttrac_usecase (Overall: NLFAIL) details: +ERC_D_Ln9.T42_T42_mg17.FDABIP04.derecho_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details: +ERC_D_Ln9.T42_T42_mg17.FHS94.derecho_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details: +ERI_D_Ln18.f45_f45_mg37.QPC41850.derecho_intel.cam-co2rmp_usecase (Overall: NLFAIL) details: +ERP_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq9s (Overall: NLFAIL) details: +ERP_D_Ln9_P64x2.f09_f09_mg17.QSC6.derecho_intel.cam-outfrq9s (Overall: NLFAIL) details: +ERP_Ld3.f09_f09_mg17.FWHIST.derecho_intel.cam-reduced_hist1d (Overall: NLFAIL) details: +ERS_Ln9.ne0TESTONLYne5x4_ne0TESTONLYne5x4_mg37.FADIAB.derecho_intel.cam-outfrq3s_refined (Overall: NLFAIL) details: +SCT_D_Ln7.ne3_ne3_mg37.QPC5.derecho_intel.cam-scm_prep (Overall: NLFAIL) details: +SCT_D_Ln7.T42_T42_mg17.QPC5.derecho_intel.cam-scm_prep (Overall: NLFAIL) details: +SMS_D_Ld2.f19_f19_mg17.QPC5HIST.derecho_intel.cam-volc_usecase (Overall: NLFAIL) details: +SMS_D_Ld5.f19_f19_mg17.PC4.derecho_intel.cam-cam4_port5d (Overall: NLFAIL) details: +SMS_D_Ln9.f19_f19_mg17.QPC2000climo.derecho_intel.cam-outfrq3s_usecase (Overall: NLFAIL) details: +SMS_D_Ln9.f19_f19_mg17.QPC5M7.derecho_intel.cam-outfrq9s (Overall: NLFAIL) details: +SMS_D_Ln9.ne16_ne16_mg17.QPX2000.derecho_intel.cam-outfrq9s (Overall: NLFAIL) details: +SMS_Ld5.f09_f09_mg17.PC6.derecho_intel.cam-cam6_port_f09 (Overall: NLFAIL) details: +SMS_Ln9.f09_f09_mg17.F2010climo.derecho_intel.cam-nudging (Overall: NLFAIL) details: +SMS_Ln9.f09_f09_mg17.FW1850.derecho_intel.cam-reduced_hist3s (Overall: NLFAIL) details: +SMS_Ln9.f19_f19.F2000climo.derecho_intel.cam-silhs (Overall: NLFAIL) details: + - NL diffs due to CMEPS & CTSM external updates + +ERP_D_Ln9.ne30pg3_ne30pg3_mg17.FLTHIST.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERP_Ld3.ne30pg3_ne30pg3_mg17.FHISTC_MTt4s.derecho_intel.cam-outfrq1d_aoa (Overall: DIFF) details: +ERP_Lh12.f19_f19_mg17.FW4madSD.derecho_intel.cam-outfrq3h (Overall: DIFF) details: +ERP_Ln9.C96_C96_mg17.F2000climo.derecho_intel.cam-outfrq9s_mg3 (Overall: DIFF) details: +ERP_Ln9.f09_f09_mg17.F1850.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERP_Ln9.f09_f09_mg17.F2000climo.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERP_Ln9.f09_f09_mg17.F2010climo.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERP_Ln9.f09_f09_mg17.FHIST_BDRD.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERP_Ln9.f19_f19_mg17.FWsc1850.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERP_Ln9.ne30pg3_ne30pg3_mg17.FCnudged.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERP_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERS_Ln9.f09_f09_mg17.FX2000.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERS_Ln9.f19_f19_mg17.FSPCAMS.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERS_Ln9.f19_f19_mg17.FXSD.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +ERS_Ln9_P288x1.mpasa120_mpasa120.F2000climo.derecho_intel.cam-outfrq9s_mpasa120 (Overall: DIFF) details: +SMS_D_Ln9.f09_f09_mg17.FCts2nudged.derecho_intel.cam-outfrq9s_leapday (Overall: DIFF) details: +SMS_D_Ln9.f09_f09_mg17.FCvbsxHIST.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +SMS_D_Ln9.f09_f09_mg17.FSD.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s_waccm_ma_mam4 (Overall: DIFF) details: +SMS_D_Ln9.ne16pg3_ne16pg3_mg17.FX2000.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +SMS_D_Ln9.ne30pg3_ne30pg3_mg17.FMTHIST.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +SMS_D_Ln9_P1280x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +SMS_D_Ln9_P1280x1.ne30pg3_ne30pg3_mg17.FHISTC_MTt1s.derecho_intel.cam-outfrq9s_Leung_dust (Overall: DIFF) details: +SMS_D_Ln9.T42_T42.FSCAMARM97.derecho_intel.cam-outfrq9s (Overall: DIFF) details: +SMS_Ld1.f09_f09_mg17.FW2000climo.derecho_intel.cam-outfrq1d (Overall: DIFF) details: +SMS_Ld1.ne30pg3_ne30pg3_mg17.FC2010climo.derecho_intel.cam-outfrq1d (Overall: DIFF) details: +SMS_Lh12.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq3h (Overall: DIFF) details: +SMS_Ln9.f19_f19_mg17.FHIST.derecho_intel.cam-outfrq9s_nochem (Overall: DIFF) details: +SMS_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s_rrtmgp (Overall: DIFF) details: + - Diffs due to updated CTSM external + SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie (Overall: FAIL) SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s (Overall: FAIL) - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. @@ -54,18 +117,23 @@ SMS_Ld1.f09_f09_mg17.FCHIST_GC.derecho_intel.cam-outfrq1d (Overall: DIFF) - pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 derecho/nvhpc/aux_cam: +ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default (Overall: DIFF) details: + - Diffs due to updated CTSM external -izumi/nag/aux_cam: +izumi/nag/aux_cam: !!due to izumi being down and the desire to make a CESM alpha +tag, the izumi tests were not run!! this changelog entry will be updated once +the tests are run -DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) - - pre-existing failure -- issue #670 - -izumi/gnu/aux_cam: +izumi/gnu/aux_cam: !!due to izumi being down and the desire to make a CESM alpha +tag, the izumi tests were not run!! this changelog entry will be updated once +the tests are run CAM tag used for the baseline comparison tests if different than previous tag: -Summarize any changes to answers: +Summarize any changes to answers: answer changes thanks to updated CTSM tag +- ran derecho intel & nvhpc tests on head of cam_development with ctsm5.3.015 vs baselines for +this tag and confirmed that there were no DIFFs =============================================================== From 3548dcfb3925d57026391c9aedb72611414606c8 Mon Sep 17 00:00:00 2001 From: peverwhee Date: Sat, 21 Dec 2024 21:05:44 -0700 Subject: [PATCH 67/82] update submodules --- cime | 2 +- components/cdeps | 2 +- components/clm | 2 +- components/cmeps | 2 +- share | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cime b/cime index 1236c0fede..b2f271b174 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit 1236c0feded460aef3e5bdba18e4b850f1997346 +Subproject commit b2f271b1742533715a05701b1bdd80a24bb2ad77 diff --git a/components/cdeps b/components/cdeps index f6bc97483a..0750c91753 160000 --- a/components/cdeps +++ b/components/cdeps @@ -1 +1 @@ -Subproject commit f6bc97483a1bfb7352c6c5610a13ed898a86990b +Subproject commit 0750c9175395d3ba3bf8eba65703dee230d08572 diff --git a/components/clm b/components/clm index 16cf4ac469..f437651ee4 160000 --- a/components/clm +++ b/components/clm @@ -1 +1 @@ -Subproject commit 16cf4ac469614f4b329c7da206c3d6b9b773bb03 +Subproject commit f437651ee449789af9325882bb0acc09576c9411 diff --git a/components/cmeps b/components/cmeps index 1355710f04..a91cedfe58 160000 --- a/components/cmeps +++ b/components/cmeps @@ -1 +1 @@ -Subproject commit 1355710f04fa6286a13e8056e35c6736e7250e3d +Subproject commit a91cedfe58658a9fc391195481137a2d83372c25 diff --git a/share b/share index f6f31fd61c..a48ff8790a 160000 --- a/share +++ b/share @@ -1 +1 @@ -Subproject commit f6f31fd61cb8f80aee97311fcca64b3e26b0202c +Subproject commit a48ff8790a21d3831873ed9f023a43c606a1ef03 From d60dbc20f4cfe039657b766b641f311296b988cc Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Fri, 27 Dec 2024 10:11:31 -0700 Subject: [PATCH 68/82] update cime tag to fix restarts issue --- .gitmodules | 2 +- cime | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 0176e8431c..305d3c828a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -151,7 +151,7 @@ fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git [submodule "cime"] path = cime url = https://github.com/ESMCI/cime -fxtag = cime6.1.49 +fxtag = cime6.1.55 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESMCI/cime diff --git a/cime b/cime index b2f271b174..85922c028f 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit b2f271b1742533715a05701b1bdd80a24bb2ad77 +Subproject commit 85922c028ff8a5b9f5573888f4240cdc4b8104a3 From 2d12f78b9b7e261d5b4da13f9c50dbd7c92b65b8 Mon Sep 17 00:00:00 2001 From: Courtney Peverley Date: Mon, 30 Dec 2024 14:04:25 -0700 Subject: [PATCH 69/82] update cime --- .gitmodules | 2 +- cime | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 305d3c828a..d8c01f79d2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -151,7 +151,7 @@ fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git [submodule "cime"] path = cime url = https://github.com/ESMCI/cime -fxtag = cime6.1.55 +fxtag = cime6.1.56 fxrequired = ToplevelRequired fxDONOTUSEurl = https://github.com/ESMCI/cime diff --git a/cime b/cime index 85922c028f..ac8e583108 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit 85922c028ff8a5b9f5573888f4240cdc4b8104a3 +Subproject commit ac8e583108b1ce1f592a6f6436c71d6dc087f447 From c3c9ed2ed02afd4338d0e0aa4865583a930b6d83 Mon Sep 17 00:00:00 2001 From: peverwhee Date: Mon, 30 Dec 2024 17:23:02 -0700 Subject: [PATCH 70/82] final changelog --- doc/ChangeLog | 223 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 215 insertions(+), 8 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 5c8757c219..43712d490b 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -2,7 +2,7 @@ Tag name: cam6_4_049 Originator(s): peverwhee -Date: 23 December 2024 +Date: 30 December 2024 One-line Summary: History bugfixes Github PR URL: https://github.com/ESCOMP/CAM/pull/1163 @@ -14,6 +14,7 @@ Purpose of changes (include the issue number and title text for each relevant Gi - Issue #1183: Suggested improvement for openfile - Update git-fleximod to v0.9.3 - Update archive_baseline.sh modify read permissions on izumi +- Update CIME tag to cime6.1.56 to fix restart issue in CAM Describe any changes made to build system: M bld/namelist_files/use_cases/sd_waccm_sulfur.xml @@ -33,8 +34,11 @@ List all files added and what they do: none List all existing files that have been modified, and describe the changes: +M .gitmodules + - update CIME tag to cime6.1.56 + M .lib/git-fleximod/* - - updates to move git-fleximod to v0.9.2 + - updates to move git-fleximod to v0.9.3 M src/control/cam_history.F90 - remove nhtfrq=1 accumulation flag override if sampled_on_subcyle=.true. @@ -77,6 +81,63 @@ appropriate machine below. All failed tests must be justified. derecho/intel/aux_cam: +ERC_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq3s_cosp (Overall: DIFF) +ERC_D_Ln9.f19_f19_mg17.QPMOZ.derecho_intel.cam-outfrq3s (Overall: DIFF) +ERC_D_Ln9.f19_f19_mg17.QPX2000.derecho_intel.cam-outfrq3s (Overall: DIFF) +ERC_D_Ln9.ne16_ne16_mg17.FADIAB.derecho_intel.cam-terminator (Overall: DIFF) +ERC_D_Ln9.ne16_ne16_mg17.QPC5HIST.derecho_intel.cam-outfrq3s_usecase (Overall: DIFF) +ERC_D_Ln9_P144x1.ne16pg3_ne16pg3_mg17.QPC6HIST.derecho_intel.cam-outfrq3s_ttrac_usecase (Overall: DIFF) +ERC_D_Ln9.T42_T42_mg17.FDABIP04.derecho_intel.cam-outfrq3s_usecase (Overall: DIFF) +ERC_D_Ln9.T42_T42_mg17.FHS94.derecho_intel.cam-outfrq3s_usecase (Overall: DIFF) +ERI_D_Ln18.f45_f45_mg37.QPC41850.derecho_intel.cam-co2rmp_usecase (Overall: DIFF) +ERP_D_Ln9.f19_f19_mg17.QPC6.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERP_D_Ln9.ne30pg3_ne30pg3_mg17.FLTHIST.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERP_D_Ln9_P64x2.f09_f09_mg17.QSC6.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERP_Ld3.f09_f09_mg17.FWHIST.derecho_intel.cam-reduced_hist1d (Overall: DIFF) +ERP_Ld3.ne30pg3_ne30pg3_mg17.FHISTC_MTt4s.derecho_intel.cam-outfrq1d_aoa (Overall: DIFF) +ERP_Lh12.f19_f19_mg17.FW4madSD.derecho_intel.cam-outfrq3h (Overall: DIFF) +ERP_Ln9.C96_C96_mg17.F2000climo.derecho_intel.cam-outfrq9s_mg3 (Overall: DIFF) +ERP_Ln9.f09_f09_mg17.F1850.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERP_Ln9.f09_f09_mg17.F2000climo.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERP_Ln9.f09_f09_mg17.F2010climo.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERP_Ln9.f09_f09_mg17.FHIST_BDRD.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERP_Ln9.f19_f19_mg17.FWsc1850.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERP_Ln9.ne30pg3_ne30pg3_mg17.FCnudged.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERP_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERS_Ln9.f09_f09_mg17.FX2000.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERS_Ln9.f19_f19_mg17.FSPCAMS.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERS_Ln9.f19_f19_mg17.FXSD.derecho_intel.cam-outfrq9s (Overall: DIFF) +ERS_Ln9.ne0TESTONLYne5x4_ne0TESTONLYne5x4_mg37.FADIAB.derecho_intel.cam-outfrq3s_refined (Overall: DIFF) +ERS_Ln9_P288x1.mpasa120_mpasa120.F2000climo.derecho_intel.cam-outfrq9s_mpasa120 (Overall: DIFF) +SCT_D_Ln7.ne3_ne3_mg37.QPC5.derecho_intel.cam-scm_prep (Overall: DIFF) +SCT_D_Ln7.T42_T42_mg17.QPC5.derecho_intel.cam-scm_prep (Overall: DIFF) +SMS_D_Ld2.f19_f19_mg17.QPC5HIST.derecho_intel.cam-volc_usecase (Overall: DIFF) +SMS_D_Ld5.f19_f19_mg17.PC4.derecho_intel.cam-cam4_port5d (Overall: DIFF) +SMS_D_Ln9.f09_f09_mg17.FCts2nudged.derecho_intel.cam-outfrq9s_leapday (Overall: DIFF) +SMS_D_Ln9.f09_f09_mg17.FCvbsxHIST.derecho_intel.cam-outfrq9s (Overall: DIFF) +SMS_D_Ln9.f09_f09_mg17.FSD.derecho_intel.cam-outfrq9s (Overall: DIFF) +SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s (Overall: DIFF) +SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s_waccm_ma_mam4 (Overall: DIFF) +SMS_D_Ln9.f19_f19_mg17.QPC2000climo.derecho_intel.cam-outfrq3s_usecase (Overall: DIFF) +SMS_D_Ln9.f19_f19_mg17.QPC5M7.derecho_intel.cam-outfrq9s (Overall: DIFF) +SMS_D_Ln9.ne16_ne16_mg17.QPX2000.derecho_intel.cam-outfrq9s (Overall: DIFF) +SMS_D_Ln9.ne16pg3_ne16pg3_mg17.FX2000.derecho_intel.cam-outfrq9s (Overall: DIFF) +SMS_D_Ln9.ne30pg3_ne30pg3_mg17.FMTHIST.derecho_intel.cam-outfrq9s (Overall: DIFF) +SMS_D_Ln9_P1280x1.ne0ARCTICne30x4_ne0ARCTICne30x4_mt12.FHIST.derecho_intel.cam-outfrq9s (Overall: DIFF) +SMS_D_Ln9_P1280x1.ne30pg3_ne30pg3_mg17.FHISTC_MTt1s.derecho_intel.cam-outfrq9s_Leung_dust (Overall: DIFF) +SMS_D_Ln9.T42_T42.FSCAMARM97.derecho_intel.cam-outfrq9s (Overall: DIFF) +SMS_Ld1.f09_f09_mg17.FCHIST_GC.derecho_intel.cam-outfrq1d (Overall: DIFF) +SMS_Ld1.f09_f09_mg17.FW2000climo.derecho_intel.cam-outfrq1d (Overall: DIFF) +SMS_Ld1.ne30pg3_ne30pg3_mg17.FC2010climo.derecho_intel.cam-outfrq1d (Overall: DIFF) +SMS_Ld5.f09_f09_mg17.PC6.derecho_intel.cam-cam6_port_f09 (Overall: DIFF) +SMS_Lh12.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq3h (Overall: DIFF) +SMS_Ln9.f09_f09_mg17.F2010climo.derecho_intel.cam-nudging (Overall: DIFF) +SMS_Ln9.f09_f09_mg17.FW1850.derecho_intel.cam-reduced_hist3s (Overall: DIFF) +SMS_Ln9.f19_f19.F2000climo.derecho_intel.cam-silhs (Overall: DIFF) details: +SMS_Ln9.f19_f19_mg17.FHIST.derecho_intel.cam-outfrq9s_nochem (Overall: DIFF) +SMS_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s_rrtmgp (Overall: DIFF) + - fieldlist differences due to removal of time_bounds field from instantaneous file + SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie (Overall: FAIL) SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s (Overall: FAIL) - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. @@ -87,13 +148,87 @@ SMS_Ld1.f09_f09_mg17.FCHIST_GC.derecho_intel.cam-outfrq1d (Overall: DIFF) derecho/nvhpc/aux_cam: +ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default (Overall: DIFF) + - fieldlist differences due to removal of time_bounds field from instantaneous file + izumi/nag/aux_cam: +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_subcol (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QSPCAMS.izumi_nag.cam-outfrq3s (Overall: DIFF) details: +ERC_D_Ln9.mpasa480z32_mpasa480.FHS94.izumi_nag.cam-outfrq3s_usecase (Overall: DIFF) details: +ERC_D_Ln9.ne16_ne16_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: DIFF) details: +ERC_D_Ln9.ne16pg3_ne16pg3_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: DIFF) details: +ERC_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac (Overall: DIFF) details: +ERC_D_Ln9.T5_T5_mg37.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: DIFF) details: +ERI_D_Ln18.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: DIFF) details: +ERI_D_Ln18.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 (Overall: DIFF) details: +ERI_D_Ln18.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: DIFF) details: +ERI_D_Ln18.ne5pg3_ne5pg3_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: DIFF) details: +ERP_Ln9.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: DIFF) details: +ERS_Ln27.ne5pg3_ne5pg3_mg37.FKESSLER.izumi_nag.cam-outfrq9s (Overall: DIFF) details: +ERS_Ln9.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq9s (Overall: DIFF) details: +PEM_D_Ln9.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: DIFF) details: +PLB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: DIFF) details: +PLB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: DIFF) details: +PLB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: DIFF) details: +PLB_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: DIFF) details: +PLB_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: DIFF) details: +PLB_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: DIFF) details: +SMS_D_Ld2.f45_f45_mg37.PC5.izumi_nag.cam-outfrq24h_port (Overall: DIFF) details: +SMS_D_Ln3.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s (Overall: DIFF) details: +SMS_D_Ln6.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem (Overall: DIFF) details: +SMS_D_Ln7.T42_T42_mg17.QPSCAMC5.izumi_nag.cam-scmarm (Overall: DIFF) details: +SMS_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-rad_diag_mam (Overall: DIFF) details: +SMS_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_ba (Overall: DIFF) details: +SMS_D_Ln9_P1x1.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: DIFF) details: +SMS_P48x1_D_Ln3.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase (Overall: DIFF) details: +SUB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s (Overall: DIFF) details: +TMC_D.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: DIFF) details: +TMC_D.T5_T5_mg37.QPC5.izumi_nag.cam-ghgrmp_e8 (Overall: DIFF) details: + - fieldlist differences due to removal of time_bounds field from instantaneous file + DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) - pre-existing failure -- issue #670 izumi/gnu/aux_cam: +ERC_D_Ln9.f10_f10_mg37.FADIAB.izumi_gnu.cam-terminator (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QPC4.izumi_gnu.cam-outfrq3s_diags (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_gnu.cam-outfrq3s_unicon (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_gnu.cam-rad_diag (Overall: DIFF) details: +ERC_D_Ln9.f10_f10_mg37.QPSPCAMM.izumi_gnu.cam-outfrq3s (Overall: DIFF) details: +ERC_D_Ln9.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 (Overall: DIFF) details: +ERC_D_Ln9.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq3s_ba (Overall: DIFF) details: +ERC_D_Ln9.ne5pg2_ne5pg2_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: DIFF) details: +ERC_D_Ln9.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: DIFF) details: +ERI_D_Ln18.T5_T5_mg37.QPC4.izumi_gnu.cam-co2rmp (Overall: DIFF) details: +ERP_D_Ln9.C48_C48_mg17.QPC6.izumi_gnu.cam-outfrq9s (Overall: DIFF) details: +ERP_D_Ln9.ne3pg3_ne3pg3_mg37.FLTHIST.izumi_gnu.cam-outfrq9s (Overall: DIFF) details: +ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPC6.izumi_gnu.cam-outfrq9s_rrtmgp (Overall: DIFF) details: +ERP_Ln9.ne5_ne5_mg37.FHS94.izumi_gnu.cam-outfrq9s (Overall: DIFF) details: +ERP_Ln9.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s (Overall: DIFF) details: +ERP_Ln9_P24x2.f45_f45_mg37.QPWmaC6.izumi_gnu.cam-outfrq9s_mee_fluxes (Overall: DIFF) details: +ERS_Ln9_P24x1.mpasa480_mpasa480.F2000climo.izumi_gnu.cam-outfrq9s_mpasa480 (Overall: DIFF) details: +PEM_D_Ln9.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: DIFF) details: +PLB_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 (Overall: DIFF) details: +PLB_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 (Overall: DIFF) details: +PLB_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 (Overall: DIFF) details: +SCT_D_Ln7.ne3_ne3_mg37.QPC6.izumi_gnu.cam-scm_prep_c6 (Overall: DIFF) details: +SCT_D_Ln7.T42_T42_mg17.QPC4.izumi_gnu.cam-scm_prep (Overall: DIFF) details: +SCT_D_Ln7.T42_T42_mg17.QPC6.izumi_gnu.cam-scm_prep_c6 (Overall: DIFF) details: +SMS_D_Ln3.f10_f10_mg37.QPMOZ.izumi_gnu.cam-outfrq3s_chemproc (Overall: DIFF) details: +SMS_D_Ln9.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee (Overall: DIFF) details: +SMS_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac (Overall: DIFF) details: +SMS_Ld5.f09_f09_mg17.PC6.izumi_gnu.cam-cam6_port_f09_rrtmgp (Overall: DIFF) details: +SMS_P48x1_D_Ln9.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s (Overall: DIFF) details: + - fieldlist differences due to removal of time_bounds field from instantaneous file + CAM tag used for the baseline comparison tests if different than previous tag: @@ -221,13 +356,85 @@ derecho/nvhpc/aux_cam: ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default (Overall: DIFF) details: - Diffs due to updated CTSM external -izumi/nag/aux_cam: !!due to izumi being down and the desire to make a CESM alpha -tag, the izumi tests were not run!! this changelog entry will be updated once -the tests are run +izumi/nag/aux_cam: izumi tests run 12/21/2024 + +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_cosp (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_subcol (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_am (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_cospsathist (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QSPCAMS.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details: +ERC_D_Ln9.mpasa480z32_mpasa480.FHS94.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details: +ERC_D_Ln9.ne16_ne16_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details: +ERC_D_Ln9.ne16pg3_ne16pg3_mg17.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details: +ERC_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-outfrq3s_ttrac (Overall: NLFAIL) details: +ERC_D_Ln9.T5_T5_mg37.QPC4.izumi_nag.cam-outfrq3s_usecase (Overall: NLFAIL) details: +ERI_D_Ln18.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: NLFAIL) details: +ERI_D_Ln18.f19_f19_mg17.QPC6.izumi_nag.cam-ghgrmp_e8 (Overall: NLFAIL) details: +ERI_D_Ln18.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: NLFAIL) details: +ERI_D_Ln18.ne5pg3_ne5pg3_mg37.FADIAB.izumi_nag.cam-outfrq3s_bwic (Overall: NLFAIL) details: +ERP_Ln9.ne5pg3_ne5pg3_mg37.QPC6.izumi_nag.cam-outfrq9s_clubbmf (Overall: NLFAIL) details: +ERS_Ln27.ne5pg3_ne5pg3_mg37.FKESSLER.izumi_nag.cam-outfrq9s (Overall: NLFAIL) details: +ERS_Ln9.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq9s (Overall: NLFAIL) details: +PEM_D_Ln9.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details: +PLB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: NLFAIL) details: +PLB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: NLFAIL) details: +PLB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: NLFAIL) details: +PLB_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal0 (Overall: NLFAIL) details: +PLB_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal1 (Overall: NLFAIL) details: +PLB_D_Ln9.ne5_ne5_mg37.QPC5.izumi_nag.cam-ttrac_loadbal3 (Overall: NLFAIL) details: +SMS_D_Ld2.f45_f45_mg37.PC5.izumi_nag.cam-outfrq24h_port (Overall: NLFAIL) details: +SMS_D_Ln3.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details: +SMS_D_Ln6.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem (Overall: NLFAIL) details: +SMS_D_Ln7.T42_T42_mg17.QPSCAMC5.izumi_nag.cam-scmarm (Overall: NLFAIL) details: +SMS_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-rad_diag_mam (Overall: NLFAIL) details: +SMS_D_Ln9.f10_f10_mg37.QPC6.izumi_nag.cam-outfrq3s_ba (Overall: NLFAIL) details: +MS_D_Ln9_P1x1.ne5_ne5_mg37.FADIAB.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details: +SMS_P48x1_D_Ln3.f09_f09_mg17.QPC6HIST.izumi_nag.cam-outfrq3s_co2cycle_usecase (Overall: NLFAIL) details: +SUB_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s (Overall: NLFAIL) details: +TMC_D.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_eoyttrac (Overall: NLFAIL) details: +TMC_D.T5_T5_mg37.QPC5.izumi_nag.cam-ghgrmp_e8 (Overall: NLFAIL) details: + - NL diffs due to CMEPS & CTSM external updates + +DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) + - pre-existing failure -- issue #670 + +izumi/gnu/aux_cam: izumi tests run 12/21/2024 + +ERC_D_Ln9.f10_f10_mg37.FADIAB.izumi_gnu.cam-terminator (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QPC4.izumi_gnu.cam-outfrq3s_diags (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_gnu.cam-outfrq3s_unicon (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_gnu.cam-rad_diag (Overall: NLFAIL) details: +ERC_D_Ln9.f10_f10_mg37.QPSPCAMM.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details: +ERC_D_Ln9.ne5_ne5_mg37.QPC4.izumi_gnu.cam-outfrq3s_nudging_ne5_L26 (Overall: NLFAIL) details: +ERC_D_Ln9.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq3s_ba (Overall: NLFAIL) details: +ERC_D_Ln9.ne5pg2_ne5pg2_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details: +ERC_D_Ln9.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details: +ERI_D_Ln18.T5_T5_mg37.QPC4.izumi_gnu.cam-co2rmp (Overall: NLFAIL) details: +ERP_D_Ln9.C48_C48_mg17.QPC6.izumi_gnu.cam-outfrq9s (Overall: NLFAIL) details: +ERP_D_Ln9.ne3pg3_ne3pg3_mg37.QPC6.izumi_gnu.cam-outfrq9s_rrtmgp (Overall: NLFAIL) details: +ERP_Ln9.ne5_ne5_mg37.FHS94.izumi_gnu.cam-outfrq9s (Overall: NLFAIL) details: +ERP_Ln9.ne5_ne5_mg37.QPC5.izumi_gnu.cam-outfrq9s (Overall: NLFAIL) details: +ERP_Ln9_P24x2.f45_f45_mg37.QPWmaC6.izumi_gnu.cam-outfrq9s_mee_fluxes (Overall: NLFAIL) details: +PEM_D_Ln9.ne5pg3_ne5pg3_mg37.FADIAB.izumi_gnu.cam-outfrq3s (Overall: NLFAIL) details: +PLB_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal0 (Overall: NLFAIL) details: +PLB_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal1 (Overall: NLFAIL) details: +PLB_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-ttrac_loadbal3 (Overall: NLFAIL) details: +SCT_D_Ln7.ne3_ne3_mg37.QPC6.izumi_gnu.cam-scm_prep_c6 (Overall: NLFAIL) details: +SCT_D_Ln7.T42_T42_mg17.QPC4.izumi_gnu.cam-scm_prep (Overall: NLFAIL) details: +SCT_D_Ln7.T42_T42_mg17.QPC6.izumi_gnu.cam-scm_prep_c6 (Overall: NLFAIL) details: +SMS_D_Ln3.f10_f10_mg37.QPMOZ.izumi_gnu.cam-outfrq3s_chemproc (Overall: NLFAIL) details: +SMS_D_Ln9.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee (Overall: NLFAIL) details: +SMS_D_Ln9.ne5pg3_ne5pg3_mg37.QPC5.izumi_gnu.cam-outfrq3s_ttrac (Overall: NLFAIL) details: +SMS_Ld5.f09_f09_mg17.PC6.izumi_gnu.cam-cam6_port_f09_rrtmgp (Overall: NLFAIL) details: + - NL diffs due to CMEPS & CTSM external updates -izumi/gnu/aux_cam: !!due to izumi being down and the desire to make a CESM alpha -tag, the izumi tests were not run!! this changelog entry will be updated once -the tests are run +ERP_D_Ln9.ne3pg3_ne3pg3_mg37.FLTHIST.izumi_gnu.cam-outfrq9s (Overall: DIFF) details: +ERS_Ln9_P24x1.mpasa480_mpasa480.F2000climo.izumi_gnu.cam-outfrq9s_mpasa480 (Overall: DIFF) details: +SMS_P48x1_D_Ln9.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s (Overall: DIFF) details: + - Diffs due to updated CTSM external CAM tag used for the baseline comparison tests if different than previous tag: From bdb3b768da79bebb4154a8e1a4597883de700261 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 30 Dec 2024 23:54:15 -0500 Subject: [PATCH 71/82] Update to head of atmos_phys with check_energy_fix_run arguments --- .gitmodules | 2 +- src/atmos_phys | 2 +- src/physics/cam/check_energy.F90 | 21 +++++++++++++-------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.gitmodules b/.gitmodules index 91690771e1..d07d5f8ac5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,7 +36,7 @@ [submodule "atmos_phys"] path = src/atmos_phys url = https://github.com/ESCOMP/atmospheric_physics - fxtag = atmos_phys0_07_000 + fxtag = 8e3d0bdff98ff70a4e815160ebd13a150c662a12 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index e10f81151e..8e3d0bdff9 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit e10f81151ecef5416462472ef0e52810dc82e412 +Subproject commit 8e3d0bdff98ff70a4e815160ebd13a150c662a12 diff --git a/src/physics/cam/check_energy.F90 b/src/physics/cam/check_energy.F90 index 7af3a32bda..d1d59e173f 100644 --- a/src/physics/cam/check_energy.F90 +++ b/src/physics/cam/check_energy.F90 @@ -877,6 +877,9 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) real(r8) :: heat_out(pcols) character(len=64) :: dummy_scheme_name ! dummy scheme name for CCPP-ized scheme + integer :: errflg + character(len=512) :: errmsg + lchnk = state%lchnk ncol = state%ncol @@ -904,14 +907,16 @@ subroutine check_energy_cam_fix(state, ptend, nstep, eshflx) ! Call the CCPP-ized subroutine (for non-SCAM) ! to compute the effective sensible heat flux and save to ptend%s call check_energy_fix_run( & - ncol = ncol, & - pver = pver, & - pint = state%pint(:ncol,:), & - gravit = gravit, & - heat_glob = heat_glob, & - ptend_s = ptend%s(:ncol,:), & - eshflx = eshflx(:ncol), & - scheme_name = dummy_scheme_name & + ncol = ncol, & + pver = pver, & + pint = state%pint(:ncol,:), & + gravit = gravit, & + heat_glob = heat_glob, & + ptend_s = ptend%s(:ncol,:), & + eshflx = eshflx(:ncol), & + scheme_name = dummy_scheme_name, & + errmsg = errmsg, & + errflg = errflg & ) end subroutine check_energy_cam_fix From 0881a22bde02cf059f3d383f0de13cf35a492108 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 31 Dec 2024 09:57:33 -0500 Subject: [PATCH 72/82] Update to atmos_phys0_07_001 --- .gitmodules | 2 +- src/atmos_phys | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 29c2e7bdac..1809a94e55 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,7 +36,7 @@ [submodule "atmos_phys"] path = src/atmos_phys url = https://github.com/ESCOMP/atmospheric_physics - fxtag = 8e3d0bdff98ff70a4e815160ebd13a150c662a12 + fxtag = atmos_phys0_07_001 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics diff --git a/src/atmos_phys b/src/atmos_phys index 8e3d0bdff9..c3de8468f7 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit 8e3d0bdff98ff70a4e815160ebd13a150c662a12 +Subproject commit c3de8468f7b245a939448f4ca6d3ef386584e92d From b7b4c3cfad202facbb6064e33f607c26f1988f03 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Tue, 31 Dec 2024 14:02:57 -0500 Subject: [PATCH 73/82] Finalize ChangeLog for cam6_4_050. --- doc/ChangeLog | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index dcc4560393..8ae657fda9 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,7 +1,7 @@ =============================================================== -Tag name: +Tag name: cam6_4_050 Originator(s): jimmielin -Date: 30 Dec 2024 +Date: 31 Dec 2024 One-line Summary: Implement CCPPized check_energy_chng and check_energy_fix Github PR URL: https://github.com/ESCOMP/CAM/pull/1180 @@ -37,7 +37,7 @@ M src/atmos_phys Save cp_or_cv_dycore in state snapshot M src/control/cam_snapshot_common.F90 -New CAM interfaces to CCPPized routines, when avaialble +New CAM interfaces to CCPPized routines, when available M src/physics/cam/check_energy.F90 Update calls to CCPPized routines, when available @@ -55,11 +55,22 @@ appropriate machine below. All failed tests must be justified. derecho/intel/aux_cam: -derecho/nvhpc/aux_cam: +SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie (Overall: FAIL) +SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s (Overall: FAIL) + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + +ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s (Overall: FAIL) +SMS_Ld1.f09_f09_mg17.FCHIST_GC.derecho_intel.cam-outfrq1d (Overall: PASS) + - pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 + +derecho/nvhpc/aux_cam: All PASS izumi/nag/aux_cam: -izumi/gnu/aux_cam: +DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) + - pre-existing failure -- issue #670 + +izumi/gnu/aux_cam: All PASS Summarize any changes to answers: B4B From 88bf77850d4dafccf037a0bba46477873baeb4b7 Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Tue, 31 Dec 2024 13:23:48 -0700 Subject: [PATCH 74/82] Add comments describing new vertical level variables. --- src/physics/cam/clubb_intr.F90 | 58 +++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 6374a3dc2d..a9878bc474 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -31,7 +31,7 @@ module clubb_intr #ifdef CLUBB_SGS use clubb_api_module, only: pdf_parameter, implicit_coefs_terms - use clubb_api_module, only: clubb_config_flags_type, grid, stats, & + use clubb_api_module, only: clubb_config_flags_type, grid, stats, & nu_vertical_res_dep, stats_metadata_type, & hm_metadata_type, sclr_idx_type @@ -52,7 +52,7 @@ module clubb_intr stats_sfc(pcols) ! stats_sfc type (hm_metadata_type) :: & hm_metadata - + type (stats_metadata_type) :: & stats_metadata @@ -60,8 +60,8 @@ module clubb_intr sclr_idx integer :: & - nzm_clubb, & - nzt_clubb + nzm_clubb, & !Number of vertical levels used by CLUBB momentum variables + nzt_clubb !Number of vertical levels used by CLUBB thermodynamic variables #endif private @@ -99,7 +99,7 @@ module clubb_intr ! These are zero by default, but will be set by SILHS before they are used by subcolumns integer :: & - hydromet_dim = 0, & + hydromet_dim = 0, & pdf_dim = 0 @@ -121,7 +121,7 @@ module clubb_intr hm_metadata #endif #endif - + ! ------------ ! ! Private data ! ! ------------ ! @@ -344,7 +344,7 @@ module clubb_intr clubb_l_mono_flux_lim_um, & ! Flag to turn on monotonic flux limiter for um clubb_l_mono_flux_lim_vm, & ! Flag to turn on monotonic flux limiter for vm clubb_l_mono_flux_lim_spikefix, & ! Flag to implement monotonic flux limiter code that - ! eliminates spurious drying tendencies at model top + ! eliminates spurious drying tendencies at model top clubb_l_host_applies_sfc_fluxes ! Whether the host model applies the surface fluxes logical :: & @@ -353,7 +353,7 @@ module clubb_intr ! Constant parameters logical, parameter, private :: & l_implemented = .true. ! Implemented in a host model (always true) - + logical, parameter, private :: & apply_to_heat = .false. ! Apply WACCM energy fixer to heat or not (.true. = yes (duh)) @@ -1740,7 +1740,7 @@ subroutine clubb_ini_cam(pbuf2d) clubb_params_single_col(iwpxp_Ri_exp) = clubb_wpxp_Ri_exp clubb_params_single_col(iz_displace) = clubb_z_displace - ! Override clubb default + ! Override clubb default if ( trim(subcol_scheme) == 'SILHS' ) then clubb_config_flags%saturation_formula = saturation_flatau else @@ -1749,7 +1749,7 @@ subroutine clubb_ini_cam(pbuf2d) ! Define model constant parameters call setup_parameters_model_api( theta0, ts_nudge, clubb_params_single_col(iSkw_max_mag) ) - + ! Set up CLUBB core. Note that some of these inputs are overwritten ! when clubb_tend_cam is called. The reason is that heights can change ! at each time step, which is why dummy arrays are read in here for heights @@ -1892,7 +1892,7 @@ subroutine clubb_ini_cam(pbuf2d) dum3 = 300._r8 if (stats_metadata%l_stats) then - + call stats_init_clubb( .true., dum1, dum2, & nzm_clubb, nzm_clubb, nzm_clubb, dum3, & stats_zt(:), stats_zm(:), stats_sfc(:), & @@ -2591,7 +2591,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & dpdlfice, & dpdlft, & detnliquid - + real(r8), dimension(pcols,pverp) :: & wprcp_clubb, & wpthvp_clubb @@ -2614,7 +2614,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & sclr, & edsclr, & n - + #endif call t_startf('clubb_tend_cam') @@ -2763,7 +2763,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if (clubb_do_liqsupersat) then call pbuf_get_field(pbuf, npccn_idx, npccn) endif - + ! Define the grid box size. CLUBB needs this information to determine what ! the maximum length scale should be. This depends on the column for ! variable mesh grids and lat-lon grids @@ -2865,7 +2865,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc state1, state1%q, state1%u, state1%v, state1%t, state1%pmid, state1%s, state1%pint, & !$acc state1%zm, state1%zi, state1%pdeldry, state1%pdel, state1%omega, state1%phis, & !$acc cam_in, cam_in%shf, cam_in%wsx, cam_in%wsy, cam_in%cflx, & - !$acc rrho, prer_evap, rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & + !$acc rrho, prer_evap, rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, wpthlp_mc_zt, rtpthlp_mc_zt ) & !$acc copy( um, vm, upwp, vpwp, wpthvp, wp2thvp, rtpthvp, thlpthvp, up2, vp2, up3, vp3, & !$acc wp2, wp3, rtp2, thlp2, rtp3, thlp3, thlm, rtm, rvm, wprtp, wpthlp, rtpthlp, & !$acc cloud_frac, wp2rtp, wp2thlp, uprcp, vprcp, rc_coef, wp4, wpup2, wpvp2, & @@ -2889,7 +2889,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !$acc wprtp_forcing, wpthlp_forcing, rtp2_forcing, thlp2_forcing, & !$acc rtpthlp_forcing, wm_zm, wm_zt, rho_zm, rho_zt, rho_ds_zm, rho_ds_zt, & !$acc invrs_rho_ds_zm, invrs_rho_ds_zt, thv_ds_zm, thv_ds_zt, rfrzm, & - !$acc radf, wpthlp_sfc, clubb_params, sfc_elevation, wprtp_sfc, upwp_sfc, vpwp_sfc, & + !$acc radf, wpthlp_sfc, clubb_params, sfc_elevation, wprtp_sfc, upwp_sfc, vpwp_sfc, & !$acc rtm_ref, thlm_ref, um_ref, vm_ref, ug, vg, p_in_Pa, exner, um_pert_inout, & !$acc inv_exner_clubb_surf, thlprcp_out, zi_g, zt_g, qrl_clubb, & !$acc pdf_zm_w_1, pdf_zm_w_2, pdf_zm_varnce_w_1, pdf_zm_varnce_w_2, pdf_zm_mixt_frac, & @@ -3001,7 +3001,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vm_pert_inout(i,k) = 0.0_r8 upwp_pert_inout(i,k) = 0.0_r8 vpwp_pert_inout(i,k) = 0.0_r8 - + ! Initialize these to prevent crashing behavior wprcp_out(i,k) = 0._r8 rcm_in_layer_out(i,k) = 0._r8 @@ -3040,7 +3040,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do end do - + !$acc parallel loop gang vector collapse(2) default(present) do sclr = 1, sclr_dim do i=1, ncol @@ -3126,7 +3126,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & s_awv_output(i,k) = 0._r8 mf_thlflx_output(i,k) = 0._r8 mf_qtflx_output(i,k) = 0._r8 - end do + end do end do end if @@ -3254,7 +3254,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables ! (such as thlm), use "inv_exner_clubb" otherwise use the exner in state inv_exner_clubb(i,k) = 1._r8 / ( ( state1%pmid(i,k) / p0_clubb )**( rairv(i,k,lchnk) / cpairv(i,k,lchnk) ) ) - + ! Compute virtual potential temperature, which is needed for CLUBB thv(i,k) = state1%t(i,k) * inv_exner_clubb(i,k) & * ( 1._r8 + zvir * state1%q(i,k,ixq) - state1%q(i,k,ixcldliq) ) @@ -3272,7 +3272,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo enddo - + !$acc parallel loop gang vector default(present) do i = 1, ncol rtm(i,pverp) = rtm(i,pver) @@ -3409,7 +3409,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:ACCR') call t_startf('clubb_tend_cam:NAR') !$acc update host( zi_g, zt_g, clubb_params, sfc_elevation ) - + call setup_grid_api( nzm_clubb, ncol, sfc_elevation, l_implemented, & ! intent(in) grid_type, zi_g(:,2), zi_g(:,1), zi_g(:,nzm_clubb), & ! intent(in) zi_g, zt_g, & ! intent(in) @@ -3512,14 +3512,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do endif - + call t_startf('clubb_tend_cam:flip-index') ! Need to flip arrays around for CLUBB core !$acc parallel loop gang vector collapse(2) default(present) do k = 1, nzm_clubb do i = 1, ncol - + um_in(i,k) = um(i,pverp-k+1) vm_in(i,k) = vm(i,pverp-k+1) upwp_in(i,k) = upwp(i,pverp-k+1) @@ -3866,7 +3866,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call t_stopf('clubb_tend_cam:do_cldcool') end if - + ! Check to see if stats should be output, here stats are read into ! output arrays to make them conformable to CAM output if (stats_metadata%l_stats) then @@ -4035,7 +4035,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do call t_stopf('clubb_tend_cam:flip-index') - + !$acc parallel loop gang vector collapse(2) default(present) do k=1, pverp do i=1, ncol @@ -4190,7 +4190,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do endif - + !$acc parallel loop gang vector collapse(2) default(present) do k=1, pverp do i=1, ncol @@ -4327,7 +4327,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if end if end do - + rvmtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) rcmtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) rimtend_clubb(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) @@ -5147,7 +5147,7 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & ! Set stats_variables variables with inputs from calling subroutine stats_metadata%l_stats = l_stats_in - + stats_metadata%stats_tsamp = stats_tsamp_in stats_metadata%stats_tout = stats_tout_in From 244142f423276fa10b74520ac5dedbb572565c59 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 2 Jan 2025 11:37:48 -0700 Subject: [PATCH 75/82] ChangeLog draft --- doc/ChangeLog | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 8ae657fda9..fac2f9ea5c 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,59 @@ =============================================================== + +Tag name: cam6_4_051 +Originator(s): fvitt +Date: 2 Jan 2025 +One-line Summary: Updates to age of air tracers history output +Github PR URL: https://github.com/ESCOMP/CAM/pull/1198 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + + Changes to age of air output #1197 + . Output age of air tracers mix ratios to history as soon as the tendencies are update, + before the tracers are transported in the time loop + . Rename history field 'AOAMF' as 'AOA1' + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: + +List any changes to the defaults for the boundary datasets: + +Describe any substantial timing or memory changes: + +Code reviewed by: cacraigucar + +List all files eliminated: N/A + +List all files added and what they do: N/A + +List all existing files that have been modified, and describe the changes: +M src/physics/cam/aoa_tracers.F90 + - add outfld calls for AOA tracers + - rename 'AOAMF' as 'AOA1' + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + +derecho/nvhpc/aux_cam: All PASS + +izumi/nag/aux_cam: + +izumi/gnu/aux_cam: + DIFF ERP_Ln9_P24x2.f45_f45_mg37.QPWmaC6.izumi_gnu.cam-outfrq9s_mee_fluxes + DIFF SMS_D_Ln9.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee + DIFF SMS_P48x1_D_Ln9.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s + - expected difference in AOA history fields , otherwise bit-for-bit unchanged + +Summarize any changes to answers: + Differences in AOA history fields, otherwise bit-for-bit unchanged + +=============================================================== +=============================================================== Tag name: cam6_4_050 Originator(s): jimmielin Date: 31 Dec 2024 From 7e9ce4b3057e6410e72231826e77f54256d9337b Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 2 Jan 2025 13:57:20 -0700 Subject: [PATCH 76/82] ChangeLog update --- doc/ChangeLog | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index fac2f9ea5c..9e8a61063c 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -39,15 +39,52 @@ appropriate machine below. All failed tests must be justified. derecho/intel/aux_cam: + PEND SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie + FAIL SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + + DIFF SMS_Lh12.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq3h + FAIL ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s + - pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 + + DIFF ERC_D_Ln9.f19_f19_mg17.QPX2000.derecho_intel.cam-outfrq3s + DIFF ERP_Ld3.f09_f09_mg17.FWHIST.derecho_intel.cam-reduced_hist1d + DIFF ERP_Ld3.ne30pg3_ne30pg3_mg17.FHISTC_MTt4s.derecho_intel.cam-outfrq1d_aoa + DIFF ERP_Lh12.f19_f19_mg17.FW4madSD.derecho_intel.cam-outfrq3h + DIFF ERP_Ln9.f19_f19_mg17.FWsc1850.derecho_intel.cam-outfrq9s + DIFF ERP_Ln9.ne30pg3_ne30pg3_mg17.FCnudged.derecho_intel.cam-outfrq9s + DIFF ERP_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s + DIFF ERS_Ln9.f09_f09_mg17.FX2000.derecho_intel.cam-outfrq9s + DIFF ERS_Ln9.f19_f19_mg17.FXSD.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.f09_f09_mg17.FCts2nudged.derecho_intel.cam-outfrq9s_leapday + DIFF SMS_D_Ln9.f09_f09_mg17.FCvbsxHIST.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.f19_f19_mg17.FWma2000climo.derecho_intel.cam-outfrq9s_waccm_ma_mam4 + DIFF SMS_D_Ln9.f19_f19_mg17.QPC2000climo.derecho_intel.cam-outfrq3s_usecase + DIFF SMS_D_Ln9.ne16_ne16_mg17.QPX2000.derecho_intel.cam-outfrq9s + DIFF SMS_D_Ln9.ne16pg3_ne16pg3_mg17.FX2000.derecho_intel.cam-outfrq9s + DIFF SMS_Ld1.f09_f09_mg17.FW2000climo.derecho_intel.cam-outfrq1d + DIFF SMS_Ld1.ne30pg3_ne30pg3_mg17.FC2010climo.derecho_intel.cam-outfrq1d + DIFF SMS_Ln9.f09_f09_mg17.FW1850.derecho_intel.cam-reduced_hist3s + DIFF SMS_Ln9.ne30pg3_ne30pg3_mg17.FW2000climo.derecho_intel.cam-outfrq9s_rrtmgp + - expected differences in AOA history fields, otherwise bit-for-bit unchanged + derecho/nvhpc/aux_cam: All PASS izumi/nag/aux_cam: + FAIL DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae + - pre-existing failure -- issue #670 + + DIFF ERC_D_Ln9.f10_f10_mg37.QPWmaC6.izumi_nag.cam-outfrq3s + DIFF SMS_D_Ln3.ne5pg3_ne5pg3_mg37.QPX2000.izumi_nag.cam-outfrq3s + DIFF SMS_D_Ln6.ne5_ne5_mg37.QPWmaC4.izumi_nag.cam-outfrq3s_physgrid_tem + - expected differences in AOA history fields, otherwise bit-for-bit unchanged izumi/gnu/aux_cam: DIFF ERP_Ln9_P24x2.f45_f45_mg37.QPWmaC6.izumi_gnu.cam-outfrq9s_mee_fluxes DIFF SMS_D_Ln9.f10_f10_mg37.QPWmaC4.izumi_gnu.cam-outfrq9s_apmee DIFF SMS_P48x1_D_Ln9.f19_f19_mg17.FW4madSD.izumi_gnu.cam-outfrq9s - - expected difference in AOA history fields , otherwise bit-for-bit unchanged + - expected differences in AOA history fields, otherwise bit-for-bit unchanged Summarize any changes to answers: Differences in AOA history fields, otherwise bit-for-bit unchanged From 286df594345331c7ffb64ac6376154b15923fe2f Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 2 Jan 2025 14:00:06 -0700 Subject: [PATCH 77/82] ChangeLog update --- doc/ChangeLog | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 9e8a61063c..9822c0361f 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -15,11 +15,11 @@ Purpose of changes (include the issue number and title text for each relevant Gi Describe any changes made to build system: N/A -Describe any changes made to the namelist: +Describe any changes made to the namelist: N/A -List any changes to the defaults for the boundary datasets: +List any changes to the defaults for the boundary datasets: N/A -Describe any substantial timing or memory changes: +Describe any substantial timing or memory changes: N/A Code reviewed by: cacraigucar From 189151b244f7af4595d08274d58b9fa07b2b807c Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Thu, 2 Jan 2025 20:29:55 -0700 Subject: [PATCH 78/82] code review changes modified: bld/namelist_files/namelist_definition.xml modified: src/physics/cam/carma_flags_mod.F90 modified: src/physics/carma/cam/carma_intr.F90 --- bld/namelist_files/namelist_definition.xml | 5 ++- src/physics/cam/carma_flags_mod.F90 | 51 +++++++++++++++++++++- src/physics/carma/cam/carma_intr.F90 | 41 +++++++++++------ 3 files changed, 80 insertions(+), 17 deletions(-) diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index d216f837f1..013d8eecfc 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -4480,7 +4480,10 @@ Default: none group="carma_nl" valid_values="ZhaoTurco,Vehkamaki" > Nucleation methods: ZhaoTurco - Zhao and Turco, JAS, V.26, No.5, 1995. + Zhao, J. and Turco, R., + Nucleation simulations in the wake of a jet aircraft in stratospheric flight, + J. Aerosol Sci., 26, 779-795, 1995, + https://doi.org/10.1016/0021-8502(95)00010-A Vehkamaki Vehkamaki, H., M. Kulmala, I. Napari, K.E.J. Lehtinen, C. Timmreck, M. Noppel and A. Laaksonen, 2002, diff --git a/src/physics/cam/carma_flags_mod.F90 b/src/physics/cam/carma_flags_mod.F90 index e583b43d90..2ed1fcc531 100644 --- a/src/physics/cam/carma_flags_mod.F90 +++ b/src/physics/cam/carma_flags_mod.F90 @@ -86,7 +86,7 @@ subroutine carma_readnl(nlfile) use cam_abortutils, only: endrun use namelist_utils, only: find_group_name - use spmd_utils, only: mpicom, masterprocid, mpi_real8, mpi_integer, mpi_logical, mpi_character + use spmd_utils, only: mpicom, masterprocid, mpi_real8, mpi_integer, mpi_logical, mpi_character, mpi_success use carma_model_flags_mod, only: carma_model_readnl ! args @@ -96,6 +96,7 @@ subroutine carma_readnl(nlfile) ! local vars integer :: unitn, ierr, i + character(len=*), parameter :: prefix = 'carma_readnl: ' ! read namelist for CARMA namelist /carma_nl/ & @@ -152,58 +153,104 @@ subroutine carma_readnl(nlfile) if (ierr == 0) then read(unitn, carma_nl, iostat=ierr) if (ierr /= 0) then - call endrun('carma_readnl: ERROR reading namelist') + call endrun(prefix//'ERROR reading namelist') end if end if close(unitn) end if call mpi_bcast (carma_flag, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_flag') call mpi_bcast (carma_do_aerosol, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_aerosol') call mpi_bcast (carma_do_coremasscheck,1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_coremasscheck') call mpi_bcast (carma_do_cldliq, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_cldliq') call mpi_bcast (carma_do_cldice, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_cldice') call mpi_bcast (carma_do_clearsky, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_clearsky') call mpi_bcast (carma_do_cloudborne, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_cloudborne') call mpi_bcast (carma_do_coag, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_coag') call mpi_bcast (carma_do_detrain, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_detrain') call mpi_bcast (carma_do_drydep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_drydep') call mpi_bcast (carma_do_emission, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_emission') call mpi_bcast (carma_do_fixedinit, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_fixedinit') call mpi_bcast (carma_hetchem_feedback,1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_hetchem_feedback') call mpi_bcast (carma_rad_feedback, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_rad_feedback') call mpi_bcast (carma_do_explised, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_explised') call mpi_bcast (carma_do_budget_diags, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_budget_diags') call mpi_bcast (carma_do_package_diags,1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_package_diags') call mpi_bcast (carma_do_incloud, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_incloud') call mpi_bcast (carma_do_grow, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_grow') call mpi_bcast (carma_do_optics, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_optics') call mpi_bcast (carma_do_partialinit, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_partialinit') call mpi_bcast (carma_do_pheat, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_pheat') call mpi_bcast (carma_do_pheatatm, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_pheatatm') call mpi_bcast (carma_do_substep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_substep') call mpi_bcast (carma_do_thermo, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_thermo') call mpi_bcast (carma_do_wetdep, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_wetdep') call mpi_bcast (carma_do_vdiff, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_vdiff') call mpi_bcast (carma_do_vtran, 1 ,mpi_logical, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_vtran') call mpi_bcast (carma_diags_file, 1 ,mpi_integer, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_diags_file') call mpi_bcast (carma_maxsubsteps, 1 ,mpi_integer, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_maxsubsteps') call mpi_bcast (carma_minsubsteps, 1 ,mpi_integer, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_minsubsteps') call mpi_bcast (carma_maxretries, 1 ,mpi_integer, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_maxretries') call mpi_bcast (carma_conmax, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_conmax') call mpi_bcast (carma_dgc_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_dgc_threshold') call mpi_bcast (carma_ds_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_ds_threshold') call mpi_bcast (carma_dt_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_dt_threshold') call mpi_bcast (carma_tstick, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_tstick') call mpi_bcast (carma_gsticki, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_gsticki') call mpi_bcast (carma_gstickl, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_gstickl') call mpi_bcast (carma_cstick, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_cstick') call mpi_bcast (carma_rhcrit, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_rhcrit') call mpi_bcast (carma_vf_const, 1 ,mpi_real8, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_vf_const') call mpi_bcast (carma_model, len(carma_model), mpi_character, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_model') call mpi_bcast (carma_sulfnuc_method, len(carma_sulfnuc_method), mpi_character, masterprocid, mpicom, ierr) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_sulfnuc_method') call mpibcast (carma_diags_packages, len(carma_diags_packages(1))*carma_maxdiags, mpi_character, 0, mpicom) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_diags_packages') call mpibcast (carma_debug_packages, len(carma_debug_packages(1))*carma_maxdiags, mpi_character, 0, mpicom) + if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_debug_packages') carma_ndiagpkgs = 0 do i = 1, carma_maxdiags diff --git a/src/physics/carma/cam/carma_intr.F90 b/src/physics/carma/cam/carma_intr.F90 index 9e86637b0c..89f7f415d6 100644 --- a/src/physics/carma/cam/carma_intr.F90 +++ b/src/physics/carma/cam/carma_intr.F90 @@ -9,18 +9,30 @@ !! @version July 2009 module carma_intr - use carma_precision_mod - use carma_enums_mod - use carma_constants_mod, only : GRAV, REARTH, WTMOL_AIR, WTMOL_H2O, R_AIR, CP, RKAPPA - use carma_types_mod - use carma_flags_mod - use carma_model_mod - use carmaelement_mod - use carmagas_mod - use carmagroup_mod - use carmasolute_mod - use carmastate_mod - use carma_mod + use carma_precision_mod, only: f + use carma_enums_mod, only: I_OPTICS_FIXED, I_OPTICS_MIXED_CORESHELL, I_OPTICS_MIXED_VOLUME, & + I_OPTICS_MIXED_MAXWELL, I_OPTICS_SULFATE, I_CNSTTYPE_PROGNOSTIC, I_HYBRID + use carma_constants_mod, only : GRAV, REARTH, WTMOL_AIR, WTMOL_H2O, R_AIR, CP, RKAPPA, NWAVE, & + CARMA_NAME_LEN, CARMA_SHORT_NAME_LEN, PI, CAM_FILL, RGAS, RM2CGS, RAD2DEG, CLDFRC_INCLOUD + use carma_types_mod, only : carma_type, carmastate_type + use carma_flags_mod, only : carma_flag, carma_do_fixedinit, carma_model, carma_do_wetdep, carma_do_emission, & + carma_do_pheat, carma_do_substep, carma_do_thermo, carma_do_cldice, carma_diags_file, & + carma_do_grow, carma_ndebugpkgs, carma_conmax, carma_cstick, carma_tstick, carma_vf_const, carma_sulfnuc_method, & + carma_rhcrit, carma_rad_feedback, carma_minsubsteps, carma_maxsubsteps, carma_gstickl, carma_gsticki, & + carma_maxretries, carma_dt_threshold, carma_ds_threshold, carma_do_vtran, carma_do_vdiff, carma_do_pheatatm, & + carma_do_partialinit, carma_do_optics, carma_do_incloud, carma_do_explised, carma_do_drydep, carma_do_detrain, & + carma_do_coremasscheck, carma_do_coag, carma_do_clearsky, carma_do_cldliq, carma_do_aerosol, carma_dgc_threshold + + use carma_model_mod, only : NGAS, NBIN, NELEM, NGROUP, NMIE_WTP, NREFIDX, MIE_RH, NMIE_RH, NSOLUTE + use carma_model_mod, only : mie_rh, mie_wtp, is_convtran1, CARMAMODEL_DiagnoseBulk, CARMAMODEL_DiagnoseBins, & + CARMAMODEL_Detrain, CARMAMODEL_OutputDiagnostics, CARMAMODEL_CreateOpticsFile, CARMAMODEL_WetDeposition, & + CARMAMODEL_EmitParticle, CARMAMODEL_InitializeParticle, CARMAMODEL_DefineModel, CARMAMODEL_InitializeModel + use carmaelement_mod, only : CARMAELEMENT_Get + use carmagas_mod, only : CARMAGAS_Get + use carmagroup_mod, only : CARMAGROUP_Get + use carmastate_mod, only : CARMASTATE_CreateFromReference, CARMASTATE_SetGas, CARMASTATE_Step, CARMASTATE_GetBin, & + CARMASTATE_GetGas, CARMASTATE_GetState, CARMASTATE_Get, CARMASTATE_Create, CARMASTATE_SetBin, CARMASTATE_Destroy + use carma_mod, only : CARMA_Get, CARMA_Create, CARMA_Initialize, CARMA_Destroy use shr_kind_mod, only: r8 => shr_kind_r8 use spmd_utils, only: masterproc, mpicom @@ -35,6 +47,7 @@ module carma_intr use physics_buffer, only: physics_buffer_desc, pbuf_add_field, pbuf_old_tim_idx, & pbuf_get_index, pbuf_get_field, dtype_r8, pbuf_set_field use pio, only: var_desc_t + use radconstants, only: nlwbands, nswbands implicit none @@ -180,7 +193,7 @@ module carma_intr !! @author Chuck Bardeen !! @version May-2009 subroutine carma_register - use radconstants, only : nlwbands, get_sw_spectral_boundaries, get_lw_spectral_boundaries + use radconstants, only : get_sw_spectral_boundaries, get_lw_spectral_boundaries use cam_logfile, only : iulog use cam_control_mod, only : initial_run use physconst, only: gravit, p_rearth=>rearth, mwdry, mwh2o @@ -2608,7 +2621,7 @@ subroutine CARMA_CreateOpticsFile_Sulfate(carma, igroup, rc) integer :: rhdim, lwdim, swdim, wtpdim integer :: rhvar, lwvar, swvar, wtp_var integer :: rwetvar - integer :: abs_lw_wtp_var, qabs_lw_wtp_var + integer :: abs_lw_wtp_var, qabs_lw_wtp_var integer :: ext_sw_wtp_var, ssa_sw_wtp_var, asm_sw_wtp_var, qext_sw_wtp_var integer :: omdim, andim, namedim integer :: omvar, anvar, namevar From 8582fd591a4f312332161a406d5089fa59b81919 Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Sat, 4 Jan 2025 21:53:35 -0700 Subject: [PATCH 79/82] Fix bugs found with GNU regression tests. --- src/physics/cam/clubb_intr.F90 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index a9878bc474..a9f25f0256 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -2118,6 +2118,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & use cam_logfile, only: iulog use tropopause, only: tropopause_findChemTrop use time_manager, only: get_nstep, is_first_restart_step + use perf_mod, only: t_startf, t_stopf #ifdef CLUBB_SGS use hb_diff, only: pblintd @@ -2153,8 +2154,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & use macrop_driver, only: liquid_macro_tend use clubb_mf, only: integrate_mf - use perf_mod - #endif implicit none @@ -2192,12 +2191,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Local Variables ! ! ---------------------------------------------------- ! + integer :: i !Must be delcared outside "CLUBB_SGS" ifdef for det_s and det_ice zero-ing loops + #ifdef CLUBB_SGS type(physics_state) :: state1 ! Local copy of state variable type(physics_ptend) :: ptend_loc ! Local tendency from processes, added up to return as ptend_all - integer :: i, j, k, t, ixind, nadv + integer :: j, k, t, ixind, nadv integer :: ixcldice, ixcldliq, ixnumliq, ixnumice, ixq integer :: itim_old integer :: ncol, lchnk ! # of columns, and chunk identifier @@ -4478,7 +4479,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & dpdlfliq(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) dpdlfice(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) dpdlft(:ncol,:pver) = ptend_loc%s(:ncol,:pver)/cpairv(:ncol,:pver, lchnk) - detnliquid(:ncol,:pver) = ptend_loc%q(:,:,ixnumliq) + detnliquid(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixnumliq) call physics_ptend_sum(ptend_loc,ptend_all,ncol) call physics_update(state1,ptend_loc,hdtime) From 87cb0064d0a9deace7833f74ea4886a1824beecd Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Mon, 6 Jan 2025 10:15:23 -0700 Subject: [PATCH 80/82] Update ChangeLog. --- doc/ChangeLog | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 9822c0361f..fb46dbae7a 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,64 @@ =============================================================== +Tag name: cam6_4_052 +Originator(s): huebleruwm, nusbaume +Date: 6 Jan 2025 +One-line Summary: clubb_intr GPUization +Github PR URL: https://github.com/ESCOMP/CAM/pull/1175 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + +Adds OpenACC directives to clubb_intr.F90 to enable GPU offloading of CLUBB. +BFB on CPUs, answer changing (but passes ECT) on GPUs. + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: N/A + +List any changes to the defaults for the boundary datasets: N/A + +Describe any substantial timing or memory changes: N/A + +Code reviewed by: nusbaume, katetc, cacraigucar + +List all files eliminated: N/A + +List all files added and what they do: N/A + +List all existing files that have been modified, and describe the changes: +M src/physics/cam/clubb_intr.F90 + - add OpenACC directives for GPU offloading + - add timer calls to evaulate performance + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + + DIFF SMS_Lh12.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq3h + FAIL ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s + - pre-existing failure due to HEMCO not having reproducible results issues #1018 and #856 + + PEND SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie + FAIL SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + +derecho/nvhpc/aux_cam: + +ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default (Overall: FAIL) + - Expected baseline failures due to non-BFB answer changes with new CLUBB GPU-offloading. + +izumi/nag/aux_cam: + FAIL DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae + - pre-existing failure -- issue #670 + +izumi/gnu/aux_cam: ALL PASS + +=============================================================== +=============================================================== + Tag name: cam6_4_051 Originator(s): fvitt Date: 2 Jan 2025 From 76ea3a47ff72ff6a9417c00f2b2d5054dba66fb2 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Tue, 7 Jan 2025 08:02:37 -0700 Subject: [PATCH 81/82] update ChangeLog --- doc/ChangeLog | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index fb46dbae7a..e105de2e94 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,138 @@ =============================================================== +Tag name: cam6_4_053 +Originator(s): fvitt +Date: 7 Jan 2025 +One-line Summary: Update CARMA base external tag +Github PR URL: https://github.com/ESCOMP/CAM/pull/1201 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + + Update CARMA sectional aerosol model base external to tag carma4_09 and update existing CARMA models accordingly + (Update CARMA base external #1181) + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: + - new carma_sulfnuc_method option + +List any changes to the defaults for the boundary datasets: N/A + +Describe any substantial timing or memory changes: N/A + +Code reviewed by: cacraigucar + +List all files eliminated: N/A + +List all files added and what they do: N/A + +List all existing files that have been modified, and describe the changes: +M .gitmodules + - update carma base tag + +M bld/build-namelist +M bld/namelist_files/namelist_definition.xml + - new carma_sulfnuc_method namelist option + +M cime_config/testdefs/testlist_cam.xml + - adjustments to carma tests + +M cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam +M cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam + - remove carma_reftfile namelist setting + +M src/physics/cam/carma_flags_mod.F90 + - updates to carma runtime options + +M src/physics/cam/carma_intr.F90 +M src/physics/cam/physpkg.F90 +M src/physics/cam7/physpkg.F90 + - interface changes for including pbuf + +M src/physics/carma/cam/carma_constants_mod.F90 + +M src/physics/carma/cam/carma_intr.F90 + - add "only" to use statements + - add restart routines + - new diags flags + - many other updates needed for the development of trop_strat carma models + +M src/physics/carma/cam/carma_precision_mod.F90 +M src/physics/carma/models/bc_strat/carma_model_mod.F90 +M src/physics/carma/models/cirrus/carma_model_mod.F90 +M src/physics/carma/models/cirrus/growevapl.F90 +M src/physics/carma/models/cirrus_dust/carma_mod.F90 +M src/physics/carma/models/cirrus_dust/carma_model_mod.F90 +M src/physics/carma/models/cirrus_dust/growevapl.F90 +M src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 + - fix end module statements + - include missing real kind specifiers + +M src/physics/carma/models/dust/carma_model_mod.F90 +M src/physics/carma/models/meteor_impact/carma_model_mod.F90 +M src/physics/carma/models/meteor_smoke/carma_model_mod.F90 +M src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 +M src/physics/carma/models/pmc/carma_model_mod.F90 +M src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 +M src/physics/carma/models/sea_salt/carma_model_mod.F90 +M src/physics/carma/models/sulfate/carma_model_mod.F90 +M src/physics/carma/models/test_detrain/carma_model_mod.F90 +M src/physics/carma/models/test_growth/carma_model_mod.F90 +M src/physics/carma/models/test_passive/carma_model_mod.F90 +M src/physics/carma/models/test_radiative/carma_model_mod.F90 +M src/physics/carma/models/test_swelling/carma_model_mod.F90 +M src/physics/carma/models/test_tracers/carma_model_mod.F90 +M src/physics/carma/models/test_tracers2/carma_model_mod.F90 +M src/physics/carma/models/tholin/carma_model_mod.F90 + - update interfaces including optics calculations + - include missing real kind specifiers + +M test/system/TR8.sh + - include physics/carma and subdirectories in the r8 checks + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: + FAIL ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s COMPARE_base_rest + - pre-existing failure -- issue #856 + + FAIL SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie SETUP + FAIL SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s SETUP + - pre-existing failures due to build-namelist error requiring CLM/CTSM external update. + +derecho/nvhpc/aux_cam: + FAIL ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default COMPARE_base_rest + - pre-existing failure -- issue #1220 + +izumi/nag/aux_cam: + FAIL DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae + - pre-existing failure -- issue #670 + + DIFF ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt + - expected differences due to updates to carma base code + +izumi/gnu/aux_cam: All PASS + +Summarize any changes to answers: + CARAM configurations change answers, otherwise bit-for-bit unchanged + +=============================================================== +=============================================================== + Tag name: cam6_4_052 Originator(s): huebleruwm, nusbaume Date: 6 Jan 2025 From 56ccdb0f56c2f8a0aeb7d9e6343d888b943738d5 Mon Sep 17 00:00:00 2001 From: Francis Vitt Date: Tue, 7 Jan 2025 08:58:25 -0700 Subject: [PATCH 82/82] update ChangeLog --- doc/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index e105de2e94..830edb9a3f 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -61,6 +61,7 @@ M src/physics/cam7/physpkg.F90 - interface changes for including pbuf M src/physics/carma/cam/carma_constants_mod.F90 + - add MAXCLDAERDIAG M src/physics/carma/cam/carma_intr.F90 - add "only" to use statements