From d46b20387c0d947128b34f208dfdc2defada9c78 Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Sat, 21 Mar 2026 23:09:32 +0100 Subject: [PATCH 01/12] Add more break points for long lines --- scripts/fortran_tools/fortran_write.py | 22 ++++++++++--------- .../fortran_files/linebreak_test.F90 | 3 +++ test/unit_tests/test_fortran_write.py | 4 ++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/scripts/fortran_tools/fortran_write.py b/scripts/fortran_tools/fortran_write.py index e147b48c..493a1ee1 100644 --- a/scripts/fortran_tools/fortran_write.py +++ b/scripts/fortran_tools/fortran_write.py @@ -27,6 +27,8 @@ class FortranWriter: __LINE_MAX = 130 # Max line length + __BREAK_CHARS = [',', '+', '*', '/', '(', ')'] + # CCPP copyright statement to be included in all generated Fortran files __COPYRIGHT = '''! ! This work (Common Community Physics Package Framework), identified by @@ -150,8 +152,8 @@ def write(self, statement, indent_level, continue_line=False): line_len = len(outstr) if line_len > self.__line_fill: # Collect pretty break points - spaces = list() - commas = list() + spaces = [] + break_chars = [] sptr = len(istr) in_single_char = False in_double_char = False @@ -180,12 +182,12 @@ def write(self, statement, indent_level, continue_line=False): elif outstr[sptr] == ' ': # Non-quote spaces are where we can break spaces.append(sptr) - elif outstr[sptr] == ',': - # Non-quote commas are where we can break - commas.append(sptr) + elif outstr[sptr] in FortranWriter.__BREAK_CHARS: + # Non-quote syntax are where we can break + break_chars.append(sptr) elif outstr[sptr:sptr+2] == '//': - # Non-quote commas are where we can break - commas.append(sptr + 1) + # Non-quote syntax are where we can break + break_chars.append(sptr + 1) # End if (no else, other characters will be ignored) sptr = sptr + 1 # End while @@ -203,7 +205,7 @@ def write(self, statement, indent_level, continue_line=False): # end if best = self.find_best_break(spaces) if best >= self.__line_fill: - best = min(best, self.find_best_break(commas)) + best = min(best, self.find_best_break(break_chars)) # End if line_continue = False if best >= self.__line_max: @@ -218,8 +220,8 @@ def write(self, statement, indent_level, continue_line=False): if self._in_quote(outstr[0:best+1]): line_continue = '&' elif not outstr[best+1:].lstrip(): - # If the next line is empty, the current line is done - # and is equal to the max line length. Do not use + # If the next line is empty, the current line is done + # and is equal to the max line length. Do not use # continue and set best to line_max (best+1) line_continue = False best = best+1 diff --git a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 index 4f89441f..40039f03 100644 --- a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 @@ -30,6 +30,9 @@ module linebreak_test name088, name089, name090, name091, name092, name093, name094, name095, name096, & name097, name098, name099 /) + allocate(tracer_data_test_dynamic_constituents(0+size(ozone_constituents)+size( & + aerosol_constituents)+size(volcaero_constituents)+size(other_constituents))) + CONTAINS call & endrun('Cannot read columns_on_task from file'// & diff --git a/test/unit_tests/test_fortran_write.py b/test/unit_tests/test_fortran_write.py index c2248896..d82f9fec 100644 --- a/test/unit_tests/test_fortran_write.py +++ b/test/unit_tests/test_fortran_write.py @@ -80,6 +80,10 @@ def test_line_breaking(self): # Test long declaration data_items = ', '.join([f"name{x:03}" for x in range(100)]) gen.write(f"character(len=7) :: data = (/ {data_items} /)", 1) + gen.blank_line() + gen.write("allocate(tracer_data_test_dynamic_constituents(0+" + "size(ozone_constituents)+size(aerosol_constituents)" + "+size(volcaero_constituents)+size(other_constituents)))", 2) gen.end_module_header() # Test long code lines line_items = ["call endrun('Cannot read columns_on_task from ", From 8919657995024ec06032ce22dd42db452edb484e Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Sun, 22 Mar 2026 10:41:12 +0100 Subject: [PATCH 02/12] Try to make Codee happy --- scripts/fortran_tools/fortran_write.py | 2 +- .../unit_tests/sample_files/fortran_files/linebreak_test.F90 | 3 ++- test/unit_tests/test_fortran_write.py | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/fortran_tools/fortran_write.py b/scripts/fortran_tools/fortran_write.py index 493a1ee1..7c11c7a8 100644 --- a/scripts/fortran_tools/fortran_write.py +++ b/scripts/fortran_tools/fortran_write.py @@ -252,7 +252,7 @@ def write(self, statement, indent_level, continue_line=False): # end if self.write(statement, indent_level, continue_line=line_continue) else: - self.__file.write("{}\n".format(outstr)) + self.__file.write(f"{outstr}\n") # End if # End if diff --git a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 index 40039f03..488b853b 100644 --- a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 @@ -30,10 +30,11 @@ module linebreak_test name088, name089, name090, name091, name092, name093, name094, name095, name096, & name097, name098, name099 /) +CONTAINS + allocate(tracer_data_test_dynamic_constituents(0+size(ozone_constituents)+size( & aerosol_constituents)+size(volcaero_constituents)+size(other_constituents))) -CONTAINS call & endrun('Cannot read columns_on_task from file'// & ', columns_on_task has no horizontal dimension; columns_on_task is a protected variable') diff --git a/test/unit_tests/test_fortran_write.py b/test/unit_tests/test_fortran_write.py index d82f9fec..6588a74b 100644 --- a/test/unit_tests/test_fortran_write.py +++ b/test/unit_tests/test_fortran_write.py @@ -80,12 +80,13 @@ def test_line_breaking(self): # Test long declaration data_items = ', '.join([f"name{x:03}" for x in range(100)]) gen.write(f"character(len=7) :: data = (/ {data_items} /)", 1) + gen.end_module_header() + # Test long code lines gen.blank_line() gen.write("allocate(tracer_data_test_dynamic_constituents(0+" "size(ozone_constituents)+size(aerosol_constituents)" "+size(volcaero_constituents)+size(other_constituents)))", 2) - gen.end_module_header() - # Test long code lines + gen.blank_line() line_items = ["call endrun('Cannot read columns_on_task from ", "file'//', columns_on_task has no horizontal ", "dimension; columns_on_task is a ", From f960f1ffcd50f4597c2fa59c7656e674adb19106 Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Sun, 22 Mar 2026 11:02:12 +0100 Subject: [PATCH 03/12] Try harder to make codee happy --- .../fortran_files/linebreak_test.F90 | 39 ++++++++++++------- test/unit_tests/test_fortran_write.py | 18 +++++++-- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 index 488b853b..17a53f44 100644 --- a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 @@ -17,27 +17,36 @@ ! module linebreak_test - character(len=7) :: data = (/ name000, name001, name002, name003, name004, name005, name006, & - name007, name008, name009, name010, name011, name012, name013, name014, name015, & - name016, name017, name018, name019, name020, name021, name022, name023, name024, & - name025, name026, name027, name028, name029, name030, name031, name032, name033, & - name034, name035, name036, name037, name038, name039, name040, name041, name042, & - name043, name044, name045, name046, name047, name048, name049, name050, name051, & - name052, name053, name054, name055, name056, name057, name058, name059, name060, & - name061, name062, name063, name064, name065, name066, name067, name068, name069, & - name070, name071, name072, name073, name074, name075, name076, name077, name078, & - name079, name080, name081, name082, name083, name084, name085, name086, name087, & - name088, name089, name090, name091, name092, name093, name094, name095, name096, & - name097, name098, name099 /) + character(len=7) :: data(100) = (/ 'name000', 'name001', 'name002', 'name003', 'name004', & + 'name005', 'name006', 'name007', 'name008', 'name009', 'name010', 'name011', 'name012', & + 'name013', 'name014', 'name015', 'name016', 'name017', 'name018', 'name019', 'name020', & + 'name021', 'name022', 'name023', 'name024', 'name025', 'name026', 'name027', 'name028', & + 'name029', 'name030', 'name031', 'name032', 'name033', 'name034', 'name035', 'name036', & + 'name037', 'name038', 'name039', 'name040', 'name041', 'name042', 'name043', 'name044', & + 'name045', 'name046', 'name047', 'name048', 'name049', 'name050', 'name051', 'name052', & + 'name053', 'name054', 'name055', 'name056', 'name057', 'name058', 'name059', 'name060', & + 'name061', 'name062', 'name063', 'name064', 'name065', 'name066', 'name067', 'name068', & + 'name069', 'name070', 'name071', 'name072', 'name073', 'name074', 'name075', 'name076', & + 'name077', 'name078', 'name079', 'name080', 'name081', 'name082', 'name083', 'name084', & + 'name085', 'name086', 'name087', 'name088', 'name089', 'name090', 'name091', 'name092', & + 'name093', 'name094', 'name095', 'name096', 'name097', 'name098', 'name099' /) CONTAINS + subroutine foo(ozone_constituents, aerosol_constituents, volcaero_constituents, & + other_constituents) + integer, intent(in) :: ozone_constituents(:) + integer, intent(in) :: aerosol_constituents(:) + integer, intent(in) :: volcaero_constituents(:) + integer, intent(in) :: other_constituents(:) + real, allocatable :: tracer_data_test_dynamic_constituents(:) allocate(tracer_data_test_dynamic_constituents(0+size(ozone_constituents)+size( & aerosol_constituents)+size(volcaero_constituents)+size(other_constituents))) - call & - endrun('Cannot read columns_on_task from file'// & - ', columns_on_task has no horizontal dimension; columns_on_task is a protected variable') + write (6, '(a)') & + 'Cannot read columns_on_task from file'// & + ', columns_on_task has no horizontal dimension; columns_on_task is a protected variable' + end subroutine foo end module linebreak_test diff --git a/test/unit_tests/test_fortran_write.py b/test/unit_tests/test_fortran_write.py index 6588a74b..4e3b418d 100644 --- a/test/unit_tests/test_fortran_write.py +++ b/test/unit_tests/test_fortran_write.py @@ -78,20 +78,30 @@ def test_line_breaking(self): header = "Test of line breaking for FortranWriter" with FortranWriter(generate, 'w', header, f"{testname}") as gen: # Test long declaration - data_items = ', '.join([f"name{x:03}" for x in range(100)]) - gen.write(f"character(len=7) :: data = (/ {data_items} /)", 1) + qchr = "'" + nditems = 100 + data_items = ', '.join([f"{qchr}name{x:03}{qchr}" for x in range(nditems)]) + gen.write(f"character(len=7) :: data({nditems}) = (/ {data_items} /)", 1) gen.end_module_header() # Test long code lines gen.blank_line() + gen.write("subroutine foo(ozone_constituents, aerosol_constituents, " + "volcaero_constituents, other_constituents)", 1) + gen.write("integer, intent(in) :: ozone_constituents(:)", 2) + gen.write("integer, intent(in) :: aerosol_constituents(:)", 2) + gen.write("integer, intent(in) :: volcaero_constituents(:)", 2) + gen.write("integer, intent(in) :: other_constituents(:)", 2) + gen.write("real, allocatable :: tracer_data_test_dynamic_constituents(:)", 2) gen.write("allocate(tracer_data_test_dynamic_constituents(0+" "size(ozone_constituents)+size(aerosol_constituents)" "+size(volcaero_constituents)+size(other_constituents)))", 2) gen.blank_line() - line_items = ["call endrun('Cannot read columns_on_task from ", + line_items = ["write (6, '(a)') 'Cannot read columns_on_task from ", "file'//', columns_on_task has no horizontal ", "dimension; columns_on_task is a ", - "protected variable')"] + "protected variable'"] gen.write(f"{''.join(line_items)}", 2) + gen.write("end subroutine foo", 1) # end with # Check that file was generated From 6c42138c11cbf5edf73fc7905c369654a8fee3c3 Mon Sep 17 00:00:00 2001 From: Steve Goldhaber Date: Mon, 23 Mar 2026 21:37:27 +0100 Subject: [PATCH 04/12] Make Fortran output more Codee compliant Add missing spaces in host cap (for Codee). --- scripts/fortran_tools/fortran_write.py | 20 +-- scripts/host_cap.py | 4 +- .../fortran_files/comments_test.F90 | 20 +-- .../fortran_files/linebreak_test.F90 | 63 ++++---- .../fortran_files/long_string_test.F90 | 136 +++++++++--------- test/unit_tests/test_fortran_write.py | 4 +- 6 files changed, 126 insertions(+), 121 deletions(-) diff --git a/scripts/fortran_tools/fortran_write.py b/scripts/fortran_tools/fortran_write.py index 7c11c7a8..49057e1a 100644 --- a/scripts/fortran_tools/fortran_write.py +++ b/scripts/fortran_tools/fortran_write.py @@ -19,9 +19,9 @@ class FortranWriter: ########################################################################### # Class variables ########################################################################### - __INDENT = 3 # Spaces per indent level + __INDENT = 2 # Spaces per indent level - __CONTINUE_INDENT = 5 # Extra spaces on continuation line + __CONTINUE_INDENT = 4 # Extra spaces on continuation line __LINE_FILL = 97 # Target line length @@ -54,7 +54,7 @@ class FortranWriter: __MOD_PREAMBLE = ["implicit none", "private"] __CONTAINS = ''' -CONTAINS''' +contains''' __MOD_FOOTER = ''' end module {module}''' @@ -182,12 +182,12 @@ def write(self, statement, indent_level, continue_line=False): elif outstr[sptr] == ' ': # Non-quote spaces are where we can break spaces.append(sptr) - elif outstr[sptr] in FortranWriter.__BREAK_CHARS: - # Non-quote syntax are where we can break - break_chars.append(sptr) elif outstr[sptr:sptr+2] == '//': # Non-quote syntax are where we can break break_chars.append(sptr + 1) + elif outstr[sptr] in FortranWriter.__BREAK_CHARS: + # Non-quote syntax are where we can break + break_chars.append(sptr) # End if (no else, other characters will be ignored) sptr = sptr + 1 # End while @@ -235,12 +235,14 @@ def write(self, statement, indent_level, continue_line=False): if in_comment or is_comment_stmt: line_continue = False # end if - if line_continue: - fill = "{}&".format((self.__line_fill - best)*' ') + if line_continue == '&': + fill = '&' + elif line_continue: + fill = ' &' else: fill = "" # End if - outline = f"{outstr[0:best+1]}{fill}".rstrip() + outline = f"{outstr[0:best+1].rstrip()}{fill}" self.__file.write(f"{outline}\n") if best <= 0: imsg = "Internal ERROR: Unable to break line" diff --git a/scripts/host_cap.py b/scripts/host_cap.py index b06906fe..fb2e7012 100644 --- a/scripts/host_cap.py +++ b/scripts/host_cap.py @@ -732,12 +732,12 @@ def write_host_cap(host_model, api, module_name, output_dir, run_env): cap.write("return", 4) cap.write("end if", 3) # Allocate the suite's dynamic constituents array - size_string = "0+" + size_string = "0 +" for var in host_local_vars.variable_list(): vtype = var.get_prop_value('type') if vtype == 'ccpp_constituent_properties_t': local_name = var.get_prop_value('local_name') - size_string += f"size({local_name})+" + size_string += f"size({local_name}) +" # end if # end for if not has_dyn_consts: diff --git a/test/unit_tests/sample_files/fortran_files/comments_test.F90 b/test/unit_tests/sample_files/fortran_files/comments_test.F90 index d4820a36..a3aa6072 100644 --- a/test/unit_tests/sample_files/fortran_files/comments_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/comments_test.F90 @@ -18,16 +18,16 @@ module comments_test ! We can write comments in the module header - ! We can write indented comments in the header - integer :: foo ! Comment at end of line works - integer :: bar ! - ! xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - ! - integer :: baz ! - ! yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - ! yyyyy + ! We can write indented comments in the header + integer :: foo ! Comment at end of line works + integer :: bar ! + ! xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + ! + integer :: baz ! + ! yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + ! yyyy -CONTAINS - ! We can write comments in the module body +contains + ! We can write comments in the module body end module comments_test diff --git a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 index 17a53f44..e2f5a3bc 100644 --- a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 @@ -17,36 +17,37 @@ ! module linebreak_test - character(len=7) :: data(100) = (/ 'name000', 'name001', 'name002', 'name003', 'name004', & - 'name005', 'name006', 'name007', 'name008', 'name009', 'name010', 'name011', 'name012', & - 'name013', 'name014', 'name015', 'name016', 'name017', 'name018', 'name019', 'name020', & - 'name021', 'name022', 'name023', 'name024', 'name025', 'name026', 'name027', 'name028', & - 'name029', 'name030', 'name031', 'name032', 'name033', 'name034', 'name035', 'name036', & - 'name037', 'name038', 'name039', 'name040', 'name041', 'name042', 'name043', 'name044', & - 'name045', 'name046', 'name047', 'name048', 'name049', 'name050', 'name051', 'name052', & - 'name053', 'name054', 'name055', 'name056', 'name057', 'name058', 'name059', 'name060', & - 'name061', 'name062', 'name063', 'name064', 'name065', 'name066', 'name067', 'name068', & - 'name069', 'name070', 'name071', 'name072', 'name073', 'name074', 'name075', 'name076', & - 'name077', 'name078', 'name079', 'name080', 'name081', 'name082', 'name083', 'name084', & - 'name085', 'name086', 'name087', 'name088', 'name089', 'name090', 'name091', 'name092', & - 'name093', 'name094', 'name095', 'name096', 'name097', 'name098', 'name099' /) - -CONTAINS - - subroutine foo(ozone_constituents, aerosol_constituents, volcaero_constituents, & - other_constituents) - integer, intent(in) :: ozone_constituents(:) - integer, intent(in) :: aerosol_constituents(:) - integer, intent(in) :: volcaero_constituents(:) - integer, intent(in) :: other_constituents(:) - real, allocatable :: tracer_data_test_dynamic_constituents(:) - allocate(tracer_data_test_dynamic_constituents(0+size(ozone_constituents)+size( & - aerosol_constituents)+size(volcaero_constituents)+size(other_constituents))) - - write (6, '(a)') & - 'Cannot read columns_on_task from file'// & - ', columns_on_task has no horizontal dimension; columns_on_task is a protected variable' - - end subroutine foo + character(len=7) :: data(100) = (/ 'name000', 'name001', 'name002', 'name003', 'name004', & + 'name005', 'name006', 'name007', 'name008', 'name009', 'name010', 'name011', 'name012', & + 'name013', 'name014', 'name015', 'name016', 'name017', 'name018', 'name019', 'name020', & + 'name021', 'name022', 'name023', 'name024', 'name025', 'name026', 'name027', 'name028', & + 'name029', 'name030', 'name031', 'name032', 'name033', 'name034', 'name035', 'name036', & + 'name037', 'name038', 'name039', 'name040', 'name041', 'name042', 'name043', 'name044', & + 'name045', 'name046', 'name047', 'name048', 'name049', 'name050', 'name051', 'name052', & + 'name053', 'name054', 'name055', 'name056', 'name057', 'name058', 'name059', 'name060', & + 'name061', 'name062', 'name063', 'name064', 'name065', 'name066', 'name067', 'name068', & + 'name069', 'name070', 'name071', 'name072', 'name073', 'name074', 'name075', 'name076', & + 'name077', 'name078', 'name079', 'name080', 'name081', 'name082', 'name083', 'name084', & + 'name085', 'name086', 'name087', 'name088', 'name089', 'name090', 'name091', 'name092', & + 'name093', 'name094', 'name095', 'name096', 'name097', 'name098', 'name099' /) + +contains + + subroutine foo(ozone_constituents, aerosol_constituents, volcaero_constituents, & + other_constituents) + integer, intent(in) :: ozone_constituents(:) + integer, intent(in) :: aerosol_constituents(:) + integer, intent(in) :: volcaero_constituents(:) + integer, intent(in) :: other_constituents(:) + real, allocatable :: tracer_data_test_dynamic_constituents(:) +! codee format off + allocate(tracer_data_test_dynamic_constituents(0+size(ozone_constituents)+size( & + aerosol_constituents)+size(volcaero_constituents)+size(other_constituents))) + + write(6, '(a)') & + 'Cannot read columns_on_task from file'// & + ', columns_on_task has no horizontal dimension; columns_on_task is a protected variable' +! codee format on + end subroutine foo end module linebreak_test diff --git a/test/unit_tests/sample_files/fortran_files/long_string_test.F90 b/test/unit_tests/sample_files/fortran_files/long_string_test.F90 index 2910fe53..46e0c350 100644 --- a/test/unit_tests/sample_files/fortran_files/long_string_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/long_string_test.F90 @@ -17,95 +17,95 @@ ! module long_string_test - foo100 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' + foo100 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' - foo101 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' + foo101 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' - foo102 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' + foo102 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' - foo103 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012' + foo103 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012' - foo104 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123' + foo104 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123' - foo105 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234' + foo105 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234' - foo106 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345' + foo106 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345' - foo107 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456' + foo107 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456' - foo108 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567' + foo108 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567' - foo109 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678' + foo109 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678' - foo110 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' + foo110 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' - foo111 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' + foo111 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' - foo112 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' + foo112 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' - foo113 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012' + foo113 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012' - foo114 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123' + foo114 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123' - foo115 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234' + foo115 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234' - foo116 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345' + foo116 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345' - foo117 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456' + foo117 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456' - foo118 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567' + foo118 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567' - foo119 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678' + foo119 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678' - foo120 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' + foo120 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' - foo121 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890& + foo121 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' + + foo122 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' + + foo123 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& &' - foo122 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890& -&1' - foo123 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890& -&12' - foo124 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890& -&123' - foo125 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890& -&1234' - foo126 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890& -&12345' - foo127 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890& -&123456' - foo128 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890& -&1234567' - foo129 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890& -&12345678' + foo124 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&3' + foo125 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&34' + foo126 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&345' + foo127 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&3456' + foo128 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&34567' + foo129 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&345678' end module long_string_test diff --git a/test/unit_tests/test_fortran_write.py b/test/unit_tests/test_fortran_write.py index 4e3b418d..8466e2ec 100644 --- a/test/unit_tests/test_fortran_write.py +++ b/test/unit_tests/test_fortran_write.py @@ -92,15 +92,17 @@ def test_line_breaking(self): gen.write("integer, intent(in) :: volcaero_constituents(:)", 2) gen.write("integer, intent(in) :: other_constituents(:)", 2) gen.write("real, allocatable :: tracer_data_test_dynamic_constituents(:)", 2) + gen.comment("codee format off", 0) gen.write("allocate(tracer_data_test_dynamic_constituents(0+" "size(ozone_constituents)+size(aerosol_constituents)" "+size(volcaero_constituents)+size(other_constituents)))", 2) gen.blank_line() - line_items = ["write (6, '(a)') 'Cannot read columns_on_task from ", + line_items = ["write(6, '(a)') 'Cannot read columns_on_task from ", "file'//', columns_on_task has no horizontal ", "dimension; columns_on_task is a ", "protected variable'"] gen.write(f"{''.join(line_items)}", 2) + gen.comment("codee format on", 0) gen.write("end subroutine foo", 1) # end with From 18384503c97f5648b8d78a3d85626233b2b86323 Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Fri, 3 Apr 2026 06:11:30 -0700 Subject: [PATCH 05/12] Exclude test files from codee formatting and remove 'codee format off' and 'code format on' blocks (test/unit_tests/sample_files/fortran_files/{linebreak_test.F90,comments_test.F90,long_string_test.F90}) --- test/unit_tests/sample_files/fortran_files/comments_test.F90 | 3 ++- test/unit_tests/sample_files/fortran_files/linebreak_test.F90 | 3 ++- .../unit_tests/sample_files/fortran_files/long_string_test.F90 | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/unit_tests/sample_files/fortran_files/comments_test.F90 b/test/unit_tests/sample_files/fortran_files/comments_test.F90 index a3aa6072..b0183858 100644 --- a/test/unit_tests/sample_files/fortran_files/comments_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/comments_test.F90 @@ -10,13 +10,13 @@ ! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - !> !! @brief Auto-generated Test of comment writing for FortranWriter !! ! module comments_test +! codee format off ! We can write comments in the module header ! We can write indented comments in the header integer :: foo ! Comment at end of line works @@ -29,5 +29,6 @@ module comments_test contains ! We can write comments in the module body +! codee format on end module comments_test diff --git a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 index e2f5a3bc..7facb467 100644 --- a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 @@ -10,13 +10,13 @@ ! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - !> !! @brief Auto-generated Test of line breaking for FortranWriter !! ! module linebreak_test +! codee format off character(len=7) :: data(100) = (/ 'name000', 'name001', 'name002', 'name003', 'name004', & 'name005', 'name006', 'name007', 'name008', 'name009', 'name010', 'name011', 'name012', & 'name013', 'name014', 'name015', 'name016', 'name017', 'name018', 'name019', 'name020', & @@ -30,6 +30,7 @@ module linebreak_test 'name077', 'name078', 'name079', 'name080', 'name081', 'name082', 'name083', 'name084', & 'name085', 'name086', 'name087', 'name088', 'name089', 'name090', 'name091', 'name092', & 'name093', 'name094', 'name095', 'name096', 'name097', 'name098', 'name099' /) +! codee format on contains diff --git a/test/unit_tests/sample_files/fortran_files/long_string_test.F90 b/test/unit_tests/sample_files/fortran_files/long_string_test.F90 index 46e0c350..7484031f 100644 --- a/test/unit_tests/sample_files/fortran_files/long_string_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/long_string_test.F90 @@ -10,13 +10,13 @@ ! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - !> !! @brief Auto-generated Test of long string breaking for FortranWriter !! ! module long_string_test +! codee format off foo100 = & '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' @@ -107,5 +107,6 @@ module long_string_test foo129 = & '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& &345678' +! codee format on end module long_string_test From d4005ee081ba73d3e9009d672c774aa496972015 Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Mon, 23 Mar 2026 10:59:37 -0600 Subject: [PATCH 06/12] Add threading test to `capgen_test`; codee format `test/capgen_test/*.F90` (#722) 1. Add threading test to `capgen_test`. This is exercised with `ctest` without any further changes, and it passes. I added a comparison of all averages to the `compare_data` call, which compares the `omp1` and `omp2` test runs. This is commit https://github.com/NCAR/ccpp-framework/pull/722/changes/900069b975fb7b1b41f94df55e4230eae071e169. While testing this, @peverwhee and I uncovered a bug (uninitialized variable, see https://github.com/NCAR/ccpp-framework/pull/722#issuecomment-4055148707) that I had to fix. 2. Update Codee to 2025.4.8 and simplify `.github/workflows/fortran-formatting.yaml` (there was an actual error using the workflow that needed to be fixed). This is commit https://github.com/NCAR/ccpp-framework/pull/722/changes/a76f82c38c024e3b13564479ed541a5ae34bc0d2 3. Codee format `test/capgen_test/*.F90`. This is commit https://github.com/NCAR/ccpp-framework/pull/722/changes/24223ffe773e98973b48ff4bdc984a72a1ed4b4d User interface changes?: No Issues: Working toward https://github.com/NCAR/ccpp-framework/issues/721 Testing: all pass test removed: n/a unit tests: n/a system tests: existing capgen test now run with `OMP_NUM_THREADS=1` and `OMP_NUM_THREADS=2` manual testing: tested manually on my dev machine with spack-stack-2.1.0 --- .github/workflows/fortran-formatting.yaml | 29 +- test/capgen_test/CMakeLists.txt | 19 +- test/capgen_test/ddt2.F90 | 12 +- test/capgen_test/make_ddt.F90 | 279 +++++----- test/capgen_test/setup_coeffs.F90 | 8 +- test/capgen_test/temp_adjust.F90 | 114 ++-- test/capgen_test/temp_calc_adjust.F90 | 153 ++--- .../test_capgen_host_integration.F90 | 150 ++--- test/capgen_test/test_host.F90 | 527 +++++++++--------- test/capgen_test/test_host_data.F90 | 40 +- test/capgen_test/test_host_mod.F90 | 211 +++---- 11 files changed, 798 insertions(+), 744 deletions(-) diff --git a/.github/workflows/fortran-formatting.yaml b/.github/workflows/fortran-formatting.yaml index 85331777..7ca69e8a 100644 --- a/.github/workflows/fortran-formatting.yaml +++ b/.github/workflows/fortran-formatting.yaml @@ -6,7 +6,7 @@ on: types: [opened, synchronize, labeled, unlabeled] env: - CODEE_VERSION: 2025.4.5 + CODEE_VERSION: 2025.4.8 # Only needed when fixing formatting automatically, but this only # works for pull requests from the same repo, not from a fork @@ -16,7 +16,7 @@ env: jobs: format: - name: Check and fix Fortran formatting + name: Check Fortran formatting runs-on: ubuntu-22.04 steps: @@ -25,32 +25,25 @@ jobs: with: fetch-depth: 0 - - name: Get modified Fortran files + - name: Check formatting of modified Fortran files run: | git remote -v show git fetch origin ${{ github.base_ref }} MODIFIED_FILES=$(git diff --name-only --diff-filter=d origin/${{ github.base_ref }}...HEAD -- '*.f90' '*.F90' '*.f' '*.F') - echo "MODIFIED_FILES=${MODIFIED_FILES}" >> ${GITHUB_ENV} - - - name: Install Codee - if: env.MODIFIED_FILES != '' - run: | + if [[ "${MODIFIED_FILES}" == "" ]]; then + exit 0 + fi + # echo "Installing Codee ${CODEE_VERSION} ..." wget https://codee.com/release/codee-${CODEE_VERSION}-linux-x86_64.tar.gz tar -xf codee-${CODEE_VERSION}-linux-x86_64.tar.gz - - - name: Run `codee format` on modified files - if: env.MODIFIED_FILES != '' - run: | export PATH="${PWD}/codee-${CODEE_VERSION}-linux-x86_64/bin:${PATH}" + # codee format --accept-eula --verbose ${MODIFIED_FILES} REFORMATTED_FILES=$(git diff --name-only --diff-filter=d) - echo "REFORMATTED_FILES=${REFORMATTED_FILES}" >> ${GITHUB_ENV} - - - name: Fail if there are uncommitted changes - if: ${{ env.REFORMATTED_FILES != '' }} - run: | + if [[ "${REFORMATTED_FILES}" == "" ]]; then + exit 0 + fi echo "Formatting issues detected. Run 'codee format' locally or apply the following diff manually:" git diff exit 1 - diff --git a/test/capgen_test/CMakeLists.txt b/test/capgen_test/CMakeLists.txt index 8288569f..3a0e1405 100644 --- a/test/capgen_test/CMakeLists.txt +++ b/test/capgen_test/CMakeLists.txt @@ -72,8 +72,25 @@ add_library(CAPGEN_TESTLIB OBJECT ${SCHEME_FORTRAN_FILES} # Setup test executable with needed dependencies add_executable(capgen_host_integration test_capgen_host_integration.F90 ${HOST}.F90) +if(OPENMP) + target_link_libraries(capgen_host_integration PRIVATE OpenMP::OpenMP_Fortran) +endif() target_link_libraries(capgen_host_integration PRIVATE CAPGEN_TESTLIB test_utils) target_include_directories(capgen_host_integration PRIVATE "$") # Add executable to be called with ctest -add_test(NAME ctest_capgen_host_integration COMMAND capgen_host_integration) +add_test(NAME ctest_capgen_host_integration_omp1 + COMMAND capgen_host_integration) + +add_test(NAME ctest_capgen_host_integration_omp2 + COMMAND capgen_host_integration) + +set_tests_properties(ctest_capgen_host_integration_omp1 + PROPERTIES + ENVIRONMENT "OMP_NUM_THREADS=1" +) + +set_tests_properties(ctest_capgen_host_integration_omp2 + PROPERTIES + ENVIRONMENT "OMP_NUM_THREADS=2" +) diff --git a/test/capgen_test/ddt2.F90 b/test/capgen_test/ddt2.F90 index 69e08a50..ce560846 100644 --- a/test/capgen_test/ddt2.F90 +++ b/test/capgen_test/ddt2.F90 @@ -1,12 +1,12 @@ module ddt2 - USE ccpp_kinds, ONLY: kind_phys + use ccpp_kinds, only: kind_phys - implicit none + implicit none - type ty_ddt2 - integer :: foo - real(kind_phys) :: bar - end type ty_ddt2 + type ty_ddt2 + integer :: foo + real(kind=kind_phys) :: bar + end type ty_ddt2 end module ddt2 diff --git a/test/capgen_test/make_ddt.F90 b/test/capgen_test/make_ddt.F90 index 91ec2e77..429e8939 100644 --- a/test/capgen_test/make_ddt.F90 +++ b/test/capgen_test/make_ddt.F90 @@ -1,143 +1,142 @@ !Hello demonstration parameterization ! -MODULE make_ddt - - USE ccpp_kinds, ONLY: kind_phys - USE ddt2, only: ty_ddt2 - - IMPLICIT NONE - PRIVATE - - PUBLIC :: make_ddt_init - PUBLIC :: make_ddt_run - PUBLIC :: make_ddt_timestep_final - PUBLIC :: vmr_type - - type ty_ddt3 - integer :: dont_lose - integer :: your_head - integer :: to_gain_a_minute - integer :: you_need_your_head - integer :: your_brains_are_in_it - end type ty_ddt3 - - !> \section arg_table_vmr_type Argument Table - !! \htmlinclude arg_table_vmr_type.html - !! - type vmr_type - integer :: nvmr - real(kind_phys), allocatable :: vmr_array(:,:) - type(ty_ddt2) :: error_maybe - type(ty_ddt3) :: burma_shave - end type vmr_type - - -CONTAINS - - !> \section arg_table_make_ddt_run Argument Table - !! \htmlinclude arg_table_make_ddt_run.html - !! - SUBROUTINE make_ddt_run(cols, cole, O3, HNO3, vmr, errmsg, errflg) - !---------------------------------------------------------------- - IMPLICIT NONE - !---------------------------------------------------------------- - - ! Dummy arguments - integer, intent(in) :: cols - integer, intent(in) :: cole - REAL(kind_phys), intent(in) :: O3(:) - REAL(kind_phys), intent(in) :: HNO3(:) - type(vmr_type), intent(inout) :: vmr - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg - ! Local variable - integer :: nbox - !---------------------------------------------------------------- - - errmsg = '' - errflg = 0 - - ! Check for correct threading behavior - nbox = cole - cols + 1 - if (SIZE(O3) /= nbox) then - errflg = 1 - write(errmsg, '(2(a,i0))') 'SIZE(O3) = ', SIZE(O3), ', should be ', nbox - else if (SIZE(HNO3) /= nbox) then - errflg = 1 - write(errmsg, '(2(a,i0))') 'SIZE(HNO3) = ', SIZE(HNO3), & - ', should be ', nbox - else - ! NOTE -- This is prototyping one approach to passing a large number of - ! chemical VMR values and is the predecssor for adding in methods and - ! maybe nesting DDTs (especially for aerosols) - vmr%vmr_array(cols:cole, 1) = O3(:) - vmr%vmr_array(cols:cole, 2) = HNO3(:) - end if - - END SUBROUTINE make_ddt_run - - !> \section arg_table_make_ddt_init Argument Table - !! \htmlinclude arg_table_make_ddt_init.html - !! - subroutine make_ddt_init(nbox, vmr, errmsg, errflg) - - ! Dummy arguments - integer, intent(in) :: nbox - type(vmr_type), intent(out) :: vmr - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg - - ! This routine initializes the vmr array - vmr%nvmr = 2 - allocate(vmr%vmr_array(nbox, vmr%nvmr)) - - errmsg = '' - errflg = 0 - - end subroutine make_ddt_init - - !> \section arg_table_make_ddt_timestep_final Argument Table - !! \htmlinclude arg_table_make_ddt_timestep_final.html - !! - subroutine make_ddt_timestep_final (ncols, vmr, errmsg, errflg) - - ! Dummy arguments - integer, intent(in) :: ncols - type(vmr_type), intent(in) :: vmr - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg - ! Local variables - integer :: index - real(kind_phys) :: rind - - errmsg = '' - errflg = 0 - - ! This routine checks the array values in vmr - if (SIZE(vmr%vmr_array, 1) /= ncols) then - errflg = 1 - write(errmsg, '(2(a,i0))') 'VMR%VMR_ARRAY first dimension size is, ', & - SIZE(vmr%vmr_array, 1), ', should be, ', ncols - else - do index = 1, ncols - rind = real(index, kind_phys) - if (vmr%vmr_array(index, 1) /= rind * 1.e-6_kind_phys) then - errflg = 1 - write(errmsg, '(a,i0,2(a,e12.4))') 'O3(', index, ') = ', & - vmr%vmr_array(index, 1), ', should be, ', & - rind * 1.e-6_kind_phys - exit - else if (vmr%vmr_array(index, 2) /= rind * 1.e-9_kind_phys) then - errflg = 1 - write(errmsg, '(a,i0,2(a,e12.4))') 'HNO3(', index, ') = ', & - vmr%vmr_array(index, 2), ', should be, ', & - rind * 1.e-9_kind_phys - exit - end if - end do - end if - - end subroutine make_ddt_timestep_final - -END MODULE make_ddt +module make_ddt + + use ccpp_kinds, only: kind_phys + use ddt2, only: ty_ddt2 + + implicit none + private + + public :: make_ddt_init + public :: make_ddt_run + public :: make_ddt_timestep_final + public :: vmr_type + + type ty_ddt3 + integer :: dont_lose + integer :: your_head + integer :: to_gain_a_minute + integer :: you_need_your_head + integer :: your_brains_are_in_it + end type ty_ddt3 + + !> \section arg_table_vmr_type Argument Table + !! \htmlinclude arg_table_vmr_type.html + !! + type vmr_type + integer :: nvmr + real(kind=kind_phys), allocatable :: vmr_array(:, :) + type(ty_ddt2) :: error_maybe + type(ty_ddt3) :: burma_shave + end type vmr_type + +contains + + !> \section arg_table_make_ddt_run Argument Table + !! \htmlinclude arg_table_make_ddt_run.html + !! + subroutine make_ddt_run(cols, cole, o3, hno3, vmr, errmsg, errflg) + !---------------------------------------------------------------- + implicit none + !---------------------------------------------------------------- + + ! Dummy arguments + integer, intent(in) :: cols + integer, intent(in) :: cole + real(kind=kind_phys), intent(in) :: o3(:) + real(kind=kind_phys), intent(in) :: hno3(:) + type(vmr_type), intent(inout) :: vmr + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + ! Local variable + integer :: nbox + !---------------------------------------------------------------- + + errmsg = '' + errflg = 0 + + ! Check for correct threading behavior + nbox = cole - cols + 1 + if (size(o3) /= nbox) then + errflg = 1 + write(errmsg, '(2(a,i0))') 'SIZE(O3) = ', size(o3), ', should be ', nbox + else if (size(hno3) /= nbox) then + errflg = 1 + write(errmsg, '(2(a,i0))') 'SIZE(HNO3) = ', size(hno3), & + ', should be ', nbox + else + ! NOTE -- This is prototyping one approach to passing a large number of + ! chemical VMR values and is the predecssor for adding in methods and + ! maybe nesting DDTs (especially for aerosols) + vmr%vmr_array(cols:cole, 1) = o3(:) + vmr%vmr_array(cols:cole, 2) = hno3(:) + end if + + end subroutine make_ddt_run + + !> \section arg_table_make_ddt_init Argument Table + !! \htmlinclude arg_table_make_ddt_init.html + !! + subroutine make_ddt_init(nbox, vmr, errmsg, errflg) + + ! Dummy arguments + integer, intent(in) :: nbox + type(vmr_type), intent(out) :: vmr + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! This routine initializes the vmr array + vmr%nvmr = 2 + allocate(vmr%vmr_array(nbox, vmr%nvmr)) + + errmsg = '' + errflg = 0 + + end subroutine make_ddt_init + + !> \section arg_table_make_ddt_timestep_final Argument Table + !! \htmlinclude arg_table_make_ddt_timestep_final.html + !! + subroutine make_ddt_timestep_final(ncols, vmr, errmsg, errflg) + + ! Dummy arguments + integer, intent(in) :: ncols + type(vmr_type), intent(in) :: vmr + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + ! Local variables + integer :: index + real(kind=kind_phys) :: rind + + errmsg = '' + errflg = 0 + + ! This routine checks the array values in vmr + if (size(vmr%vmr_array, 1) /= ncols) then + errflg = 1 + write(errmsg, '(2(a,i0))') 'VMR%VMR_ARRAY first dimension size is, ', & + size(vmr%vmr_array, 1), ', should be, ', ncols + else + do index = 1, ncols + rind = real(index, kind_phys) + if (vmr%vmr_array(index, 1) /= rind * 1.e-6_kind_phys) then + errflg = 1 + write(errmsg, '(a,i0,2(a,e12.4))') 'O3(', index, ') = ', & + vmr%vmr_array(index, 1), ', should be, ', & + rind * 1.e-6_kind_phys + exit + else if (vmr%vmr_array(index, 2) /= rind * 1.e-9_kind_phys) then + errflg = 1 + write(errmsg, '(a,i0,2(a,e12.4))') 'HNO3(', index, ') = ', & + vmr%vmr_array(index, 2), ', should be, ', & + rind * 1.e-9_kind_phys + exit + end if + end do + end if + + end subroutine make_ddt_timestep_final + +end module make_ddt diff --git a/test/capgen_test/setup_coeffs.F90 b/test/capgen_test/setup_coeffs.F90 index 09452780..09c7fcc1 100644 --- a/test/capgen_test/setup_coeffs.F90 +++ b/test/capgen_test/setup_coeffs.F90 @@ -1,5 +1,5 @@ module setup_coeffs - use ccpp_kinds, ONLY: kind_phys + use ccpp_kinds, only: kind_phys implicit none public :: setup_coeffs_timestep_init @@ -10,9 +10,9 @@ module setup_coeffs !! subroutine setup_coeffs_timestep_init(coeffs, errmsg, errflg) - real(kind_phys), intent(inout) :: coeffs(:) - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg + real(kind=kind_phys), intent(inout) :: coeffs(:) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg errmsg = '' errflg = 0 diff --git a/test/capgen_test/temp_adjust.F90 b/test/capgen_test/temp_adjust.F90 index b39baf61..c25d087b 100644 --- a/test/capgen_test/temp_adjust.F90 +++ b/test/capgen_test/temp_adjust.F90 @@ -1,56 +1,58 @@ ! Test parameterization with no vertical level ! -MODULE temp_adjust +module temp_adjust - USE ccpp_kinds, ONLY: kind_phys, kind_temp + use ccpp_kinds, only: kind_phys, kind_temp - IMPLICIT NONE - PRIVATE + implicit none + private - PUBLIC :: temp_adjust_register - PUBLIC :: temp_adjust_init - PUBLIC :: temp_adjust_run - PUBLIC :: temp_adjust_finalize + public :: temp_adjust_register + public :: temp_adjust_init + public :: temp_adjust_run + public :: temp_adjust_finalize logical :: module_level_config = .false. -CONTAINS +contains !> \section arg_table_temp_adjust_register Argument Table !! \htmlinclude arg_table_temp_adjust_register.hml !! subroutine temp_adjust_register(config_var, errmsg, errflg) - logical, intent(in) :: config_var - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg + logical, intent(in) :: config_var + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg - module_level_config = config_var - errflg = 0 - errmsg = '' + module_level_config = config_var + errflg = 0 + errmsg = '' end subroutine temp_adjust_register !> \section arg_table_temp_adjust_run Argument Table !! \htmlinclude arg_table_temp_adjust_run.html !! - subroutine temp_adjust_run(foo, timestep, interstitial_var, temp_prev, temp_layer, qv, ps, & - to_promote, promote_pcnst, errmsg, errflg, innie, outie, optsie) - - integer, intent(in) :: foo - real(kind_phys), intent(in) :: timestep - real(kind_phys), intent(inout),optional :: qv(:) - real(kind_phys), intent(inout) :: ps(:) - REAL(kind_phys), intent(in) :: temp_prev(:) - REAL(kind_phys), intent(inout) :: temp_layer(foo) - real(kind_temp), intent(in) :: to_promote(:) - real(kind_phys), intent(in) :: promote_pcnst(:) - integer, intent(out) :: interstitial_var(:) - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg - real(kind_phys), optional, intent(in) :: innie - real(kind_phys), optional, intent(out) :: outie - real(kind_phys), optional, intent(inout) :: optsie + subroutine temp_adjust_run(foo, timestep, interstitial_var, temp_prev, temp_layer, qv, ps, & + to_promote, promote_pcnst, errmsg, errflg, innie, outie, optsie) + + integer, intent(in) :: foo + real(kind=kind_phys), intent(in) :: timestep + real(kind=kind_phys), intent(inout), optional :: qv(:) + real(kind=kind_phys), intent(inout) :: ps(:) + ! codee format off + REAL(kind_phys), intent(in) :: temp_prev(:) + REAL(kind_phys), intent(inout) :: temp_layer(foo) + ! codee format on + real(kind=kind_temp), intent(in) :: to_promote(:) + real(kind=kind_phys), intent(in) :: promote_pcnst(:) + integer, intent(out) :: interstitial_var(:) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + real(kind=kind_phys), optional, intent(in) :: innie + real(kind=kind_phys), optional, intent(out) :: outie + real(kind=kind_phys), optional, intent(inout) :: optsie !---------------------------------------------------------------- integer :: col_index @@ -60,34 +62,34 @@ subroutine temp_adjust_run(foo, timestep, interstitial_var, temp_prev, temp_laye interstitial_var = 6 if (size(interstitial_var) /= 3) then - errflg = 1 - errmsg = 'interstitial variable not allocated properly!' - return + errflg = 1 + errmsg = 'interstitial variable not allocated properly!' + return end if - if (.not. module_level_config) then - ! do nothing - return + if (.not.module_level_config) then + ! do nothing + return end if do col_index = 1, foo - temp_layer(col_index) = temp_layer(col_index) + temp_prev(col_index) - if (present(qv)) qv(col_index) = qv(col_index) + 1.0_kind_phys + temp_layer(col_index) = temp_layer(col_index) + temp_prev(col_index) + if (present(qv)) qv(col_index) = qv(col_index) + 1.0_kind_phys end do if (present(innie) .and. present(outie) .and. present(optsie)) then - outie = innie * optsie - optsie = optsie + 1.0_kind_phys + outie = innie * optsie + optsie = optsie + 1.0_kind_phys end if - END SUBROUTINE temp_adjust_run + end subroutine temp_adjust_run !> \section arg_table_temp_adjust_init Argument Table !! \htmlinclude arg_table_temp_adjust_init.html !! - subroutine temp_adjust_init (errmsg, errflg) + subroutine temp_adjust_init(errmsg, errflg) - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg ! This routine currently does nothing @@ -99,26 +101,26 @@ end subroutine temp_adjust_init !> \section arg_table_temp_adjust_finalize Argument Table !! \htmlinclude arg_table_temp_adjust_finalize.html !! - subroutine temp_adjust_finalize (interstitial_var, errmsg, errflg) + subroutine temp_adjust_finalize(interstitial_var, errmsg, errflg) - integer, intent(in) :: interstitial_var(:) - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg + integer, intent(in) :: interstitial_var(:) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg ! This routine currently does nothing errmsg = '' errflg = 0 if (size(interstitial_var) /= 3) then - errflg = 1 - errmsg = 'interstitial variable not allocated properly!' - return + errflg = 1 + errmsg = 'interstitial variable not allocated properly!' + return end if if (interstitial_var(1) /= 6) then - errflg = 1 - errmsg = 'interstitial variable not set properly!' + errflg = 1 + errmsg = 'interstitial variable not set properly!' end if end subroutine temp_adjust_finalize -END MODULE temp_adjust +end module temp_adjust diff --git a/test/capgen_test/temp_calc_adjust.F90 b/test/capgen_test/temp_calc_adjust.F90 index cee03dbf..cee0703f 100644 --- a/test/capgen_test/temp_calc_adjust.F90 +++ b/test/capgen_test/temp_calc_adjust.F90 @@ -1,108 +1,111 @@ !Test parameterization with no vertical level and hanging intent(out) variable ! -MODULE temp_calc_adjust +module temp_calc_adjust - USE ccpp_kinds, ONLY: kind_phys + use ccpp_kinds, only: kind_phys - IMPLICIT NONE - PRIVATE + implicit none + private - PUBLIC :: temp_calc_adjust_register - PUBLIC :: temp_calc_adjust_init - PUBLIC :: temp_calc_adjust_run - PUBLIC :: temp_calc_adjust_finalize + public :: temp_calc_adjust_register + public :: temp_calc_adjust_init + public :: temp_calc_adjust_run + public :: temp_calc_adjust_finalize -CONTAINS +contains - !> \section arg_table_temp_calc_adjust_register Argument Table - !! \htmlinclude arg_table_temp_calc_adjust_register.html - !! - SUBROUTINE temp_calc_adjust_register(dim_inter, errmsg, errflg) - integer, intent(out) :: dim_inter - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg +! codee format off +!> \section arg_table_temp_calc_adjust_register Argument Table +!! \htmlinclude arg_table_temp_calc_adjust_register.html +!! + SUBROUTINE temp_calc_adjust_register(dim_inter, errmsg, errflg) +! codee format on + integer, intent(out) :: dim_inter + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg - errflg = 0 - errmsg = '' - dim_inter = 3 - END SUBROUTINE temp_calc_adjust_register - !> \section arg_table_temp_calc_adjust_run Argument Table - !! \htmlinclude arg_table_temp_calc_adjust_run.html - !! - SUBROUTINE temp_calc_adjust_run(nbox, timestep, temp_level, temp_calc, & - errmsg, errflg) + errflg = 0 + errmsg = '' + dim_inter = 3 + end subroutine temp_calc_adjust_register - integer, intent(in) :: nbox - real(kind_phys), intent(in) :: timestep - real(kind_phys), intent(in) :: temp_level(:,:) - REAL(kind_phys), intent(out) :: temp_calc(:) - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg - !---------------------------------------------------------------- + !> \section arg_table_temp_calc_adjust_run Argument Table + !! \htmlinclude arg_table_temp_calc_adjust_run.html + !! + subroutine temp_calc_adjust_run(nbox, timestep, temp_level, temp_calc, & + errmsg, errflg) - integer :: col_index - real(kind_phys) :: bar = 1.0_kind_phys + integer, intent(in) :: nbox + real(kind=kind_phys), intent(in) :: timestep + real(kind=kind_phys), intent(in) :: temp_level(:, :) + real(kind=kind_phys), intent(out) :: temp_calc(:) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + !---------------------------------------------------------------- - errmsg = '' - errflg = 0 + integer :: col_index + real(kind=kind_phys) :: bar = 1.0_kind_phys - call temp_calc_adjust_nested_subroutine(temp_calc) - if (check_foo()) then - call foo(bar) - end if + errmsg = '' + errflg = 0 - CONTAINS + call temp_calc_adjust_nested_subroutine(temp_calc) + if (check_foo()) then + call foo(bar) + end if - ELEMENTAL SUBROUTINE temp_calc_adjust_nested_subroutine(temp) + contains - REAL(kind_phys), intent(out) :: temp - !------------------------------------------------------------- + elemental subroutine temp_calc_adjust_nested_subroutine(temp) - temp = 1.0_kind_phys + real(kind=kind_phys), intent(out) :: temp + !------------------------------------------------------------- - END SUBROUTINE temp_calc_adjust_nested_subroutine + temp = 1.0_kind_phys - SUBROUTINE foo(bar) - REAL(kind_phys), intent(inout) :: bar - bar = bar + 1.0_kind_phys + end subroutine temp_calc_adjust_nested_subroutine - END SUBROUTINE + subroutine foo(bar) + real(kind=kind_phys), intent(inout) :: bar + bar = bar + 1.0_kind_phys - logical function check_foo() - check_foo = .true. - end function check_foo + end subroutine foo - END SUBROUTINE + logical function check_foo() + check_foo = .true. + end function check_foo - !> \section arg_table_temp_calc_adjust_init Argument Table - !! \htmlinclude arg_table_temp_calc_adjust_init.html - !! - subroutine temp_calc_adjust_init (errmsg, errflg) + end subroutine temp_calc_adjust_run - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg + !> \section arg_table_temp_calc_adjust_init Argument Table + !! \htmlinclude arg_table_temp_calc_adjust_init.html + !! + subroutine temp_calc_adjust_init(errmsg, errflg) - ! This routine currently does nothing + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg - errmsg = '' - errflg = 0 + ! This routine currently does nothing - end subroutine temp_calc_adjust_init + errmsg = '' + errflg = 0 - !> \section arg_table_temp_calc_adjust_finalize Argument Table - !! \htmlinclude arg_table_temp_calc_adjust_finalize.html - !! - subroutine temp_calc_adjust_finalize (errmsg, errflg) + end subroutine temp_calc_adjust_init - character(len=512), intent(out) :: errmsg - integer, intent(out) :: errflg + !> \section arg_table_temp_calc_adjust_finalize Argument Table + !! \htmlinclude arg_table_temp_calc_adjust_finalize.html + !! + subroutine temp_calc_adjust_finalize(errmsg, errflg) - ! This routine currently does nothing + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg - errmsg = '' - errflg = 0 + ! This routine currently does nothing - end subroutine temp_calc_adjust_finalize + errmsg = '' + errflg = 0 -END MODULE temp_calc_adjust + end subroutine temp_calc_adjust_finalize + +end module temp_calc_adjust diff --git a/test/capgen_test/test_capgen_host_integration.F90 b/test/capgen_test/test_capgen_host_integration.F90 index 745e5678..eb11f2f8 100644 --- a/test/capgen_test/test_capgen_host_integration.F90 +++ b/test/capgen_test/test_capgen_host_integration.F90 @@ -1,86 +1,86 @@ program test - use test_prog, only: test_host, suite_info, cm, cs + use test_prog, only: test_host, suite_info, cm, cs - implicit none + implicit none - character(len=cs), target :: test_parts1(2) = (/ 'physics1 ', & - 'physics2 ' /) - character(len=cs), target :: test_parts2(1) = (/ 'data_prep ' /) - character(len=cm), target :: test_invars1(10) = (/ & - 'potential_temperature ', & - 'potential_temperature_at_interface ', & - 'coefficients_for_interpolation ', & - 'surface_air_pressure ', & - 'water_vapor_specific_humidity ', & - 'potential_temperature_increment ', & - 'soil_levels ', & - 'temperature_at_diagnostic_levels ', & - 'time_step_for_physics ', & - 'array_variable_for_testing ' /) - character(len=cm), target :: test_outvars1(10) = (/ & - 'potential_temperature ', & - 'potential_temperature_at_interface ', & - 'coefficients_for_interpolation ', & - 'surface_air_pressure ', & - 'water_vapor_specific_humidity ', & - 'soil_levels ', & - 'temperature_at_diagnostic_levels ', & - 'ccpp_error_code ', & - 'ccpp_error_message ', & - 'array_variable_for_testing ' /) - character(len=cm), target :: test_reqvars1(12) = (/ & - 'potential_temperature ', & - 'potential_temperature_at_interface ', & - 'coefficients_for_interpolation ', & - 'surface_air_pressure ', & - 'water_vapor_specific_humidity ', & - 'potential_temperature_increment ', & - 'time_step_for_physics ', & - 'soil_levels ', & - 'temperature_at_diagnostic_levels ', & - 'ccpp_error_code ', & - 'ccpp_error_message ', & - 'array_variable_for_testing ' /) + character(len=cs), target :: test_parts1(2) = (/ 'physics1 ', & + 'physics2 ' /) + character(len=cs), target :: test_parts2(1) = (/ 'data_prep ' /) + character(len=cm), target :: test_invars1(10) = (/ & + 'potential_temperature ', & + 'potential_temperature_at_interface ', & + 'coefficients_for_interpolation ', & + 'surface_air_pressure ', & + 'water_vapor_specific_humidity ', & + 'potential_temperature_increment ', & + 'soil_levels ', & + 'temperature_at_diagnostic_levels ', & + 'time_step_for_physics ', & + 'array_variable_for_testing ' /) + character(len=cm), target :: test_outvars1(10) = (/ & + 'potential_temperature ', & + 'potential_temperature_at_interface ', & + 'coefficients_for_interpolation ', & + 'surface_air_pressure ', & + 'water_vapor_specific_humidity ', & + 'soil_levels ', & + 'temperature_at_diagnostic_levels ', & + 'ccpp_error_code ', & + 'ccpp_error_message ', & + 'array_variable_for_testing ' /) + character(len=cm), target :: test_reqvars1(12) = (/ & + 'potential_temperature ', & + 'potential_temperature_at_interface ', & + 'coefficients_for_interpolation ', & + 'surface_air_pressure ', & + 'water_vapor_specific_humidity ', & + 'potential_temperature_increment ', & + 'time_step_for_physics ', & + 'soil_levels ', & + 'temperature_at_diagnostic_levels ', & + 'ccpp_error_code ', & + 'ccpp_error_message ', & + 'array_variable_for_testing ' /) - character(len=cm), target :: test_invars2(3) = (/ & - 'model_times ', & - 'number_of_model_times ', & - 'surface_air_pressure ' /) + character(len=cm), target :: test_invars2(3) = (/ & + 'model_times ', & + 'number_of_model_times ', & + 'surface_air_pressure ' /) - character(len=cm), target :: test_outvars2(5) = (/ & - 'ccpp_error_code ', & - 'ccpp_error_message ', & - 'model_times ', & - 'surface_air_pressure ', & - 'number_of_model_times ' /) + character(len=cm), target :: test_outvars2(5) = (/ & + 'ccpp_error_code ', & + 'ccpp_error_message ', & + 'model_times ', & + 'surface_air_pressure ', & + 'number_of_model_times ' /) - character(len=cm), target :: test_reqvars2(5) = (/ & - 'model_times ', & - 'number_of_model_times ', & - 'surface_air_pressure ', & - 'ccpp_error_code ', & - 'ccpp_error_message ' /) - type(suite_info) :: test_suites(2) - logical :: run_okay + character(len=cm), target :: test_reqvars2(5) = (/ & + 'model_times ', & + 'number_of_model_times ', & + 'surface_air_pressure ', & + 'ccpp_error_code ', & + 'ccpp_error_message ' /) + type(suite_info) :: test_suites(2) + logical :: run_okay - ! Setup expected test suite info - test_suites(1)%suite_name = 'temp_suite' - test_suites(1)%suite_parts => test_parts1 - test_suites(1)%suite_input_vars => test_invars1 - test_suites(1)%suite_output_vars => test_outvars1 - test_suites(1)%suite_required_vars => test_reqvars1 - test_suites(2)%suite_name = 'ddt_suite' - test_suites(2)%suite_parts => test_parts2 - test_suites(2)%suite_input_vars => test_invars2 - test_suites(2)%suite_output_vars => test_outvars2 - test_suites(2)%suite_required_vars => test_reqvars2 + ! Setup expected test suite info + test_suites(1)%suite_name = 'temp_suite' + test_suites(1)%suite_parts => test_parts1 + test_suites(1)%suite_input_vars => test_invars1 + test_suites(1)%suite_output_vars => test_outvars1 + test_suites(1)%suite_required_vars => test_reqvars1 + test_suites(2)%suite_name = 'ddt_suite' + test_suites(2)%suite_parts => test_parts2 + test_suites(2)%suite_input_vars => test_invars2 + test_suites(2)%suite_output_vars => test_outvars2 + test_suites(2)%suite_required_vars => test_reqvars2 - call test_host(run_okay, test_suites) + call test_host(run_okay, test_suites) - if (run_okay) then - STOP 0 - else - STOP -1 - end if + if (run_okay) then + stop 0 + else + stop -1 + end if end program test diff --git a/test/capgen_test/test_host.F90 b/test/capgen_test/test_host.F90 index 9ed3f47c..6e39c787 100644 --- a/test/capgen_test/test_host.F90 +++ b/test/capgen_test/test_host.F90 @@ -1,280 +1,303 @@ module test_prog - use ccpp_kinds, only: kind_phys + use ccpp_kinds, only: kind_phys - implicit none - private + implicit none + private - public test_host + public test_host - ! Public data and interfaces - integer, public, parameter :: cs = 16 - integer, public, parameter :: cm = 36 + ! Public data and interfaces + integer, public, parameter :: cs = 16 + integer, public, parameter :: cm = 36 - !> \section arg_table_suite_info Argument Table - !! \htmlinclude arg_table_suite_info.html - !! - type, public :: suite_info - character(len=cs) :: suite_name = '' - character(len=cs), pointer :: suite_parts(:) => NULL() - character(len=cm), pointer :: suite_input_vars(:) => NULL() - character(len=cm), pointer :: suite_output_vars(:) => NULL() - character(len=cm), pointer :: suite_required_vars(:) => NULL() - end type suite_info + !> \section arg_table_suite_info Argument Table + !! \htmlinclude arg_table_suite_info.html + !! + type, public :: suite_info + character(len=cs) :: suite_name = '' + character(len=cs), pointer :: suite_parts(:) => null() + character(len=cm), pointer :: suite_input_vars(:) => null() + character(len=cm), pointer :: suite_output_vars(:) => null() + character(len=cm), pointer :: suite_required_vars(:) => null() + end type suite_info -CONTAINS +contains - logical function check_suite(test_suite) - use test_host_ccpp_cap, only: ccpp_physics_suite_part_list - use test_host_ccpp_cap, only: ccpp_physics_suite_variables - use test_utils, only: check_list + logical function check_suite(test_suite) + use test_host_ccpp_cap, only: ccpp_physics_suite_part_list + use test_host_ccpp_cap, only: ccpp_physics_suite_variables + use test_utils, only: check_list - ! Dummy argument - type(suite_info), intent(in) :: test_suite - ! Local variables - integer :: sind - logical :: check - integer :: errflg - character(len=512) :: errmsg - character(len=128), allocatable :: test_list(:) + ! Dummy argument + type(suite_info), intent(in) :: test_suite + ! Local variables + integer :: sind + logical :: check + integer :: errflg + character(len=512) :: errmsg + character(len=128), allocatable :: test_list(:) - check_suite = .true. - write(6, *) "Checking suite ", trim(test_suite%suite_name) - ! First, check the suite parts - call ccpp_physics_suite_part_list(test_suite%suite_name, test_list, & - errmsg, errflg) - if (errflg == 0) then - check = check_list(test_list, test_suite%suite_parts, 'part names', & - suite_name=test_suite%suite_name) - else - check = .false. - write(6, '(a,i0,2a)') 'ERROR ', errflg, ': ', trim(errmsg) - end if - check_suite = check_suite .and. check - if (allocated(test_list)) then - deallocate(test_list) - end if - ! Check the input variables - call ccpp_physics_suite_variables(test_suite%suite_name, test_list, & - errmsg, errflg, input_vars=.true., output_vars=.false.) - if (errflg == 0) then - check = check_list(test_list, test_suite%suite_input_vars, & - 'input variable names', suite_name=test_suite%suite_name) - else - check = .false. - write(6, '(a,i0,2a)') 'ERROR ', errflg, ': ', trim(errmsg) - end if - check_suite = check_suite .and. check - if (allocated(test_list)) then - deallocate(test_list) - end if - ! Check the output variables - call ccpp_physics_suite_variables(test_suite%suite_name, test_list, & - errmsg, errflg, input_vars=.false., output_vars=.true.) - if (errflg == 0) then - check = check_list(test_list, test_suite%suite_output_vars, & - 'output variable names', suite_name=test_suite%suite_name) - else - check = .false. - write(6, '(a,i0,2a)') 'ERROR ', errflg, ': ', trim(errmsg) - end if - check_suite = check_suite .and. check - if (allocated(test_list)) then - deallocate(test_list) - end if - ! Check all required variables - call ccpp_physics_suite_variables(test_suite%suite_name, test_list, & - errmsg, errflg) - if (errflg == 0) then - check = check_list(test_list, test_suite%suite_required_vars, & - 'required variable names', suite_name=test_suite%suite_name) - else - check = .false. - write(6, '(a,i0,2a)') 'ERROR ', errflg, ': ', trim(errmsg) - end if - check_suite = check_suite .and. check - if (allocated(test_list)) then - deallocate(test_list) - end if - end function check_suite + check_suite = .true. + write(6, *) "Checking suite ", trim(test_suite%suite_name) + ! First, check the suite parts + call ccpp_physics_suite_part_list(test_suite%suite_name, test_list, & + errmsg, errflg) + if (errflg == 0) then + check = check_list(test_list, test_suite%suite_parts, 'part names', & + suite_name=test_suite%suite_name) + else + check = .false. + write(6, '(a,i0,2a)') 'ERROR ', errflg, ': ', trim(errmsg) + end if + check_suite = check_suite .and. check + if (allocated(test_list)) then + deallocate(test_list) + end if + ! Check the input variables + call ccpp_physics_suite_variables(test_suite%suite_name, test_list, & + errmsg, errflg, input_vars=.true., output_vars=.false.) + if (errflg == 0) then + check = check_list(test_list, test_suite%suite_input_vars, & + 'input variable names', suite_name=test_suite%suite_name) + else + check = .false. + write(6, '(a,i0,2a)') 'ERROR ', errflg, ': ', trim(errmsg) + end if + check_suite = check_suite .and. check + if (allocated(test_list)) then + deallocate(test_list) + end if + ! Check the output variables + call ccpp_physics_suite_variables(test_suite%suite_name, test_list, & + errmsg, errflg, input_vars=.false., output_vars=.true.) + if (errflg == 0) then + check = check_list(test_list, test_suite%suite_output_vars, & + 'output variable names', suite_name=test_suite%suite_name) + else + check = .false. + write(6, '(a,i0,2a)') 'ERROR ', errflg, ': ', trim(errmsg) + end if + check_suite = check_suite .and. check + if (allocated(test_list)) then + deallocate(test_list) + end if + ! Check all required variables + call ccpp_physics_suite_variables(test_suite%suite_name, test_list, & + errmsg, errflg) + if (errflg == 0) then + check = check_list(test_list, test_suite%suite_required_vars, & + 'required variable names', suite_name=test_suite%suite_name) + else + check = .false. + write(6, '(a,i0,2a)') 'ERROR ', errflg, ': ', trim(errmsg) + end if + check_suite = check_suite .and. check + if (allocated(test_list)) then + deallocate(test_list) + end if + end function check_suite + !> \section arg_table_test_host Argument Table + !! \htmlinclude arg_table_test_host.html + !! + subroutine test_host(retval, test_suites) - !> \section arg_table_test_host Argument Table - !! \htmlinclude arg_table_test_host.html - !! - subroutine test_host(retval, test_suites) +#ifdef _OPENMP + use omp_lib +#endif + use test_host_mod, only: ncols, num_time_steps + use test_host_ccpp_cap, only: test_host_ccpp_physics_register + use test_host_ccpp_cap, only: test_host_ccpp_physics_initialize + use test_host_ccpp_cap, only: test_host_ccpp_physics_timestep_initial + use test_host_ccpp_cap, only: test_host_ccpp_physics_run + use test_host_ccpp_cap, only: test_host_ccpp_physics_timestep_final + use test_host_ccpp_cap, only: test_host_ccpp_physics_finalize + use test_host_ccpp_cap, only: ccpp_physics_suite_list + use test_host_mod, only: init_data, compare_data, check_model_times + use test_utils, only: check_list - use test_host_mod, only: ncols, num_time_steps - use test_host_ccpp_cap, only: test_host_ccpp_physics_register - use test_host_ccpp_cap, only: test_host_ccpp_physics_initialize - use test_host_ccpp_cap, only: test_host_ccpp_physics_timestep_initial - use test_host_ccpp_cap, only: test_host_ccpp_physics_run - use test_host_ccpp_cap, only: test_host_ccpp_physics_timestep_final - use test_host_ccpp_cap, only: test_host_ccpp_physics_finalize - use test_host_ccpp_cap, only: ccpp_physics_suite_list - use test_host_mod, only: init_data, compare_data, check_model_times - use test_utils, only: check_list + type(suite_info), intent(in) :: test_suites(:) + logical, intent(out) :: retval - type(suite_info), intent(in) :: test_suites(:) - logical, intent(out) :: retval + logical :: check + integer :: col_start, col_end + integer :: thread_num, num_threads + integer :: index, sind + integer :: time_step + integer :: num_suites + character(len=128), allocatable :: suite_names(:) + character(len=512) :: errmsg + integer :: errflg - logical :: check - integer :: col_start, col_end - integer :: index, sind - integer :: time_step - integer :: num_suites - character(len=128), allocatable :: suite_names(:) - character(len=512) :: errmsg - integer :: errflg + ! Initialize our 'data' + call init_data() - ! Initialize our 'data' - call init_data() + ! Gather and test the inspection routines + num_suites = size(test_suites) + call ccpp_physics_suite_list(suite_names) + retval = check_list(suite_names, test_suites(:)%suite_name, & + 'suite names') + write(6, *) 'Available suites are:' + do index = 1, size(suite_names) + do sind = 1, num_suites + if (trim(test_suites(sind)%suite_name) == & + trim(suite_names(index))) then + exit + end if + end do + write(6, '(i0,3a,i0,a)') index, ') ', trim(suite_names(index)), & + ' = test_suites(', sind, ')' + end do + if (retval) then + do sind = 1, num_suites + check = check_suite(test_suites(sind)) + retval = retval .and. check + end do + end if + !!! Return here if any check failed + if (.not.retval) then + return + end if - ! Gather and test the inspection routines - num_suites = size(test_suites) - call ccpp_physics_suite_list(suite_names) - retval = check_list(suite_names, test_suites(:)%suite_name, & - 'suite names') - write(6, *) 'Available suites are:' - do index = 1, size(suite_names) - do sind = 1, num_suites - if (trim(test_suites(sind)%suite_name) == & - trim(suite_names(index))) then - exit - end if - end do - write(6, '(i0,3a,i0,a)') index, ') ', trim(suite_names(index)), & - ' = test_suites(', sind, ')' - end do - if (retval) then - do sind = 1, num_suites - check = check_suite(test_suites(sind)) - retval = retval .and. check - end do - end if - !!! Return here if any check failed - if (.not. retval) then - return - end if + ! Use the suite information to call the register phase + do sind = 1, num_suites + call test_host_ccpp_physics_register(test_suites(sind)%suite_name, & + errmsg, errflg) + if (errflg /= 0) then + write(6, '(4a)') 'ERROR in register of ', & + trim(test_suites(sind)%suite_name), ': ', trim(errmsg) + end if + end do + ! Use the suite information to setup the run + do sind = 1, num_suites + call test_host_ccpp_physics_initialize(test_suites(sind)%suite_name, & + errmsg, errflg) + if (errflg /= 0) then + write(6, '(4a)') 'ERROR in initialize of ', & + trim(test_suites(sind)%suite_name), ': ', trim(errmsg) + end if + end do + ! Loop over time steps + do time_step = 1, num_time_steps + ! Initialize the timestep + do sind = 1, num_suites + if (errflg /= 0) then + exit + end if + if (errflg == 0) then + call test_host_ccpp_physics_timestep_initial( & + test_suites(sind)%suite_name, errmsg, errflg) + end if + if (errflg /= 0) then + write(6, '(3a)') trim(test_suites(sind)%suite_name), ': ', & + trim(errmsg) + exit + end if + if (errflg /= 0) then + exit + end if + end do - ! Use the suite information to call the register phase - do sind = 1, num_suites - call test_host_ccpp_physics_register(test_suites(sind)%suite_name, & - errmsg, errflg) + run_phase_if_no_error: if (errflg == 0) then +#ifdef _OPENMP + num_threads = omp_get_max_threads() +#else + num_threads = 1 +#endif + !$OMP parallel num_threads (num_threads) & + !$OMP default (none) & + !$OMP shared (num_threads, num_suites, test_suites) & + !$OMP private (thread_num, col_start, col_end, errmsg) & + !$OMP reduction (+:errflg) +#ifdef _OPENMP + thread_num = omp_get_thread_num() +#else + thread_num = 0 +#endif + !$OMP do + do col_start = 1, ncols, 5 if (errflg /= 0) then - write(6, '(4a)') 'ERROR in register of ', & - trim(test_suites(sind)%suite_name), ': ', trim(errmsg) + continue end if - end do - ! Use the suite information to setup the run - do sind = 1, num_suites - call test_host_ccpp_physics_initialize(test_suites(sind)%suite_name, & - errmsg, errflg) - if (errflg /= 0) then - write(6, '(4a)') 'ERROR in initialize of ', & - trim(test_suites(sind)%suite_name), ': ', trim(errmsg) - end if - end do - ! Loop over time steps - do time_step = 1, num_time_steps - ! Initialize the timestep + col_end = min(col_start + 4, ncols) do sind = 1, num_suites - if (errflg /= 0) then - exit - end if - if (errflg == 0) then - call test_host_ccpp_physics_timestep_initial( & - test_suites(sind)%suite_name, errmsg, errflg) - end if - if (errflg /= 0) then - write(6, '(3a)') trim(test_suites(sind)%suite_name), ': ', & - trim(errmsg) - exit - end if - if (errflg /= 0) then - exit - end if + if (errflg /= 0) then + continue + end if + do index = 1, size(test_suites(sind)%suite_parts) + if (errflg /= 0) then + continue + end if + write(0, '(a,i0,a,i0,5a,i0,a,i0)') 'Thread ', thread_num, '/', num_threads, & + ': calling run phase for suite ', trim(test_suites(sind)%suite_name), & + ' part ', trim(test_suites(sind)%suite_parts(index)), & + ' columns ', col_start, ':', col_end + call test_host_ccpp_physics_run( & + test_suites(sind)%suite_name, & + test_suites(sind)%suite_parts(index), & + col_start, col_end, errmsg, errflg) + if (errflg /= 0) then + write(6, '(5a)') trim(test_suites(sind)%suite_name), & + '/', trim(test_suites(sind)%suite_parts(index)), & + ': ', trim(errmsg) + end if + end do end do + end do + !$OMP end do + !$OMP end parallel + end if run_phase_if_no_error - do col_start = 1, ncols, 5 - if (errflg /= 0) then - exit - end if - col_end = MIN(col_start + 4, ncols) + do sind = 1, num_suites + if (errflg /= 0) then + exit + end if + if (errflg == 0) then + call test_host_ccpp_physics_timestep_final( & + test_suites(sind)%suite_name, errmsg, errflg) + end if + if (errflg /= 0) then + write(6, '(3a)') trim(test_suites(sind)%suite_name), ': ', & + trim(errmsg) + exit + end if + end do + end do ! End time step loop - do sind = 1, num_suites - if (errflg /= 0) then - exit - end if - do index = 1, size(test_suites(sind)%suite_parts) - if (errflg /= 0) then - exit - end if - if (errflg == 0) then - call test_host_ccpp_physics_run( & - test_suites(sind)%suite_name, & - test_suites(sind)%suite_parts(index), & - col_start, col_end, errmsg, errflg) - end if - if (errflg /= 0) then - write(6, '(5a)') trim(test_suites(sind)%suite_name), & - '/', trim(test_suites(sind)%suite_parts(index)), & - ': ', trim(errmsg) - exit - end if - end do - end do - end do + do sind = 1, num_suites + if (errflg /= 0) then + exit + end if + if (errflg == 0) then + call test_host_ccpp_physics_finalize( & + test_suites(sind)%suite_name, errmsg, errflg) + end if + if (errflg /= 0) then + write(6, '(3a)') test_suites(sind)%suite_parts(index), ': ', & + trim(errmsg) + write(6, '(2a)') 'An error occurred in ccpp_timestep_final, ', & + 'Exiting...' + exit + end if + end do - do sind = 1, num_suites - if (errflg /= 0) then - exit - end if - if (errflg == 0) then - call test_host_ccpp_physics_timestep_final( & - test_suites(sind)%suite_name, errmsg, errflg) - end if - if (errflg /= 0) then - write(6, '(3a)') trim(test_suites(sind)%suite_name), ': ', & - trim(errmsg) - exit - end if - end do - end do ! End time step loop - - do sind = 1, num_suites - if (errflg /= 0) then - exit - end if - if (errflg == 0) then - call test_host_ccpp_physics_finalize( & - test_suites(sind)%suite_name, errmsg, errflg) - end if - if (errflg /= 0) then - write(6, '(3a)') test_suites(sind)%suite_parts(index), ': ', & - trim(errmsg) - write(6,'(2a)') 'An error occurred in ccpp_timestep_final, ', & - 'Exiting...' - exit - end if - end do - - if (errflg == 0) then - ! Run finished without error, check answers - if (.not. check_model_times()) then - write(6, *) 'Model times error!' - errflg = -1 - else if (compare_data()) then - write(6, *) 'Answers are correct!' - errflg = 0 - else - write(6, *) 'Answers are not correct!' - errflg = -1 - end if - end if + if (errflg == 0) then + ! Run finished without error, check answers + if (.not.check_model_times()) then + write(6, *) 'Model times error!' + errflg = -1 + else if (compare_data()) then + write(6, *) 'Answers are correct!' + errflg = 0 + else + write(6, *) 'Answers are not correct!' + errflg = -1 + end if + end if - retval = errflg == 0 + retval = errflg == 0 - end subroutine test_host + end subroutine test_host - end module test_prog +end module test_prog diff --git a/test/capgen_test/test_host_data.F90 b/test/capgen_test/test_host_data.F90 index 1b0a45c1..32c421a4 100644 --- a/test/capgen_test/test_host_data.F90 +++ b/test/capgen_test/test_host_data.F90 @@ -8,15 +8,15 @@ module test_host_data !> \section arg_table_physics_state Argument Table !! \htmlinclude arg_table_physics_state.html type physics_state - real(kind_phys), dimension(:), allocatable :: & - ps, & ! surface pressure - soil_levs ! soil temperature (cm) - real(kind_phys), dimension(:,:), allocatable :: & - u, & ! zonal wind (m/s) - v, & ! meridional wind (m/s) - pmid ! midpoint pressure (Pa) - real(kind_phys), dimension(:,:,:),allocatable :: & - q ! constituent mixing ratio (kg/kg moist or dry air depending on type) + real(kind=kind_phys), dimension(:), allocatable :: & + ps, & ! surface pressure + soil_levs ! soil temperature (cm) + real(kind=kind_phys), dimension(:, :), allocatable :: & + u, & ! zonal wind (m/s) + v, & ! meridional wind (m/s) + pmid ! midpoint pressure (Pa) + real(kind=kind_phys), dimension(:, :, :), allocatable :: & + q ! constituent mixing ratio (kg/kg moist or dry air depending on type) end type physics_state public :: physics_state @@ -25,36 +25,36 @@ module test_host_data contains subroutine allocate_physics_state(cols, levels, constituents, lbnd_slev, ubnd_slev, state) - integer, intent(in) :: cols - integer, intent(in) :: levels - integer, intent(in) :: constituents - integer, intent(in) :: lbnd_slev, ubnd_slev + integer, intent(in) :: cols + integer, intent(in) :: levels + integer, intent(in) :: constituents + integer, intent(in) :: lbnd_slev, ubnd_slev type(physics_state), intent(out) :: state if (allocated(state%ps)) then - deallocate(state%ps) + deallocate(state%ps) end if allocate(state%ps(cols)) if (allocated(state%u)) then - deallocate(state%u) + deallocate(state%u) end if allocate(state%u(cols, levels)) if (allocated(state%v)) then - deallocate(state%v) + deallocate(state%v) end if allocate(state%v(cols, levels)) if (allocated(state%pmid)) then - deallocate(state%pmid) + deallocate(state%pmid) end if allocate(state%pmid(cols, levels)) if (allocated(state%q)) then - deallocate(state%q) + deallocate(state%q) end if allocate(state%q(cols, levels, constituents)) if (allocated(state%soil_levs)) then - deallocate(state%soil_levs) + deallocate(state%soil_levs) end if allocate(state%soil_levs(lbnd_slev:ubnd_slev)) - + end subroutine allocate_physics_state end module test_host_data diff --git a/test/capgen_test/test_host_mod.F90 b/test/capgen_test/test_host_mod.F90 index f2586a77..aecc5f15 100644 --- a/test/capgen_test/test_host_mod.F90 +++ b/test/capgen_test/test_host_mod.F90 @@ -1,45 +1,45 @@ module test_host_mod - use ccpp_kinds, only: kind_phys - use test_host_data, only: physics_state, allocate_physics_state - - implicit none - public - - !> \section arg_table_test_host_mod Argument Table - !! \htmlinclude arg_table_test_host_host.html - !! - integer, parameter :: ncols = 10 - integer, parameter :: pver = 5 - integer, parameter :: pverP = 6 - integer, parameter :: pcnst = 2 - integer, parameter :: slevs = 4 - integer, parameter :: slev_lbound = -3 - integer, parameter :: slev_ubound = 0 - integer, parameter :: DiagDimStart = 2 - integer, parameter :: index_qv = 1 - logical, parameter :: config_var = .true. - real(kind_phys), allocatable :: temp_midpoints(:,:) - real(kind_phys) :: temp_interfaces(ncols, pverP) - real(kind_phys) :: temp_diag(ncols,6) - real(kind_phys) :: coeffs(ncols) - real(kind_phys) :: var_array(ncols,2,4,6) - real(kind_phys), dimension(DiagDimStart:ncols, DiagDimStart:pver) :: & - diag1, & - diag2 - real(kind_phys) :: dt - real(kind_phys), parameter :: temp_inc = 0.05_kind_phys - type(physics_state) :: phys_state - integer :: num_model_times = -1 - integer, allocatable :: model_times(:) - - integer, parameter :: num_time_steps = 2 - real(kind_phys), parameter :: tolerance = 1.0e-13_kind_phys - real(kind_phys) :: tint_save(ncols, pverP) - - public :: init_data - public :: compare_data - public :: check_model_times + use ccpp_kinds, only: kind_phys + use test_host_data, only: physics_state, allocate_physics_state + + implicit none + public + + !> \section arg_table_test_host_mod Argument Table + !! \htmlinclude arg_table_test_host_host.html + !! + integer, parameter :: ncols = 10 + integer, parameter :: pver = 5 + integer, parameter :: pverp = 6 + integer, parameter :: pcnst = 2 + integer, parameter :: slevs = 4 + integer, parameter :: slev_lbound = -3 + integer, parameter :: slev_ubound = 0 + integer, parameter :: diagdimstart = 2 + integer, parameter :: index_qv = 1 + logical, parameter :: config_var = .true. + real(kind=kind_phys), allocatable :: temp_midpoints(:, :) + real(kind=kind_phys) :: temp_interfaces(ncols, pverp) + real(kind=kind_phys) :: temp_diag(ncols, 6) + real(kind=kind_phys) :: coeffs(ncols) + real(kind=kind_phys) :: var_array(ncols, 2, 4, 6) + real(kind=kind_phys), dimension(diagdimstart:ncols, diagdimstart:pver) :: & + diag1, & + diag2 + real(kind=kind_phys) :: dt + real(kind=kind_phys), parameter :: temp_inc = 0.05_kind_phys + type(physics_state) :: phys_state + integer :: num_model_times = -1 + integer, allocatable :: model_times(:) + + integer, parameter :: num_time_steps = 2 + real(kind=kind_phys), parameter :: tolerance = 1.0e-13_kind_phys + real(kind=kind_phys) :: tint_save(ncols, pverp) + + public :: init_data + public :: compare_data + public :: check_model_times contains @@ -53,22 +53,23 @@ subroutine init_data() ! Allocate and initialize temperature allocate(temp_midpoints(ncols, pver)) temp_midpoints = 0.0_kind_phys - do lev = 1, pverP - offsize = ((cind - 1) * (ncols * pver)) + ((lev - 1) * ncols) - do col = 1, ncols - temp_interfaces(col, lev) = real(offsize + col, kind=kind_phys) - tint_save(col, lev) = temp_interfaces(col, lev) - end do + cind = 1 + do lev = 1, pverp + offsize = ((cind - 1) * (ncols * pver)) + ((lev - 1) * ncols) + do col = 1, ncols + temp_interfaces(col, lev) = real(offsize + col, kind=kind_phys) + tint_save(col, lev) = temp_interfaces(col, lev) + end do end do ! Allocate and initialize state call allocate_physics_state(ncols, pver, pcnst, slev_lbound, slev_ubound, phys_state) do cind = 1, pcnst - do lev = 1, pver - offsize = ((cind - 1) * (ncols * pver)) + ((lev - 1) * ncols) - do col = 1, ncols - phys_state%q(col, lev, cind) = real(offsize + col, kind=kind_phys) - end do - end do + do lev = 1, pver + offsize = ((cind - 1) * (ncols * pver)) + ((lev - 1) * ncols) + do col = 1, ncols + phys_state%q(col, lev, cind) = real(offsize + col, kind=kind_phys) + end do + end do end do end subroutine init_data @@ -77,70 +78,86 @@ logical function check_model_times() check_model_times = (num_model_times > 0) if (check_model_times) then - check_model_times = (size(model_times) == num_model_times) - if (.not. check_model_times) then - write(6, '(2(a,i0))') 'model_times size mismatch, ', & - size(model_times), ' should be ', num_model_times - end if + check_model_times = (size(model_times) == num_model_times) + if (.not.check_model_times) then + write(6, '(2(a,i0))') 'model_times size mismatch, ', & + size(model_times), ' should be ', num_model_times + end if else - write(6, '(a,i0,a)') 'num_model_times mismatch, ',num_model_times, & - ' should be greater than zero' + write(6, '(a,i0,a)') 'num_model_times mismatch, ', num_model_times, & + ' should be greater than zero' end if end function check_model_times logical function compare_data() - integer :: col - integer :: lev - integer :: cind - integer :: offsize - logical :: need_header - real(kind_phys) :: avg + integer :: col + integer :: lev + integer :: cind + integer :: offsize + logical :: need_header + real(kind=kind_phys) :: avg integer, parameter :: cincrements(pcnst) = (/ 1, 0 /) + real(kind=kind_phys) :: total_test + real(kind=kind_phys), parameter :: total_ref = 6730.0_kind_phys compare_data = .true. + total_test = 0.0_kind_phys need_header = .true. do lev = 1, pver - do col = 1, ncols - avg = (tint_save(col,lev) + tint_save(col,lev+1)) - avg = 1.0_kind_phys + (avg / 2.0_kind_phys) - avg = avg + (temp_inc * num_time_steps) - if (abs((temp_midpoints(col, lev) - avg) / avg) > tolerance) then - if (need_header) then - write(6, '(" COL LEV T MIDPOINTS EXPECTED")') - need_header = .false. - end if - write(6, '(2i5,2(3x,es15.7))') col, lev, & - temp_midpoints(col, lev), avg - compare_data = .false. + do col = 1, ncols + avg = (tint_save(col, lev) + tint_save(col, lev + 1)) + avg = 1.0_kind_phys + (avg / 2.0_kind_phys) + avg = avg + (temp_inc * num_time_steps) + total_test = total_test + avg + if (abs((temp_midpoints(col, lev) - avg) / avg) > tolerance) then + if (need_header) then + write(6, '(" COL LEV T MIDPOINTS EXPECTED")') + need_header = .false. end if - end do + write(6, '(2i5,2(3x,es15.7))') col, lev, & + temp_midpoints(col, lev), avg + compare_data = .false. + end if + end do end do ! Check constituents need_header = .true. do cind = 1, pcnst - do lev = 1, pver - offsize = ((cind - 1) * (ncols * pver)) + ((lev - 1) * ncols) - do col = 1, ncols - avg = real(offsize + col + (cincrements(cind) * num_time_steps), & - kind=kind_phys) - if (abs((phys_state%q(col, lev, cind) - avg) / avg) > & - tolerance) then - if (need_header) then - write(6, '(2(2x,a),3x,a,10x,a,14x,a)') & - 'COL', 'LEV', 'C#', 'Q', 'EXPECTED' - need_header = .false. - end if - write(6, '(3i5,2(3x,es15.7))') col, lev, cind, & - phys_state%q(col, lev, cind), avg - compare_data = .false. - end if - end do - end do + do lev = 1, pver + offsize = ((cind - 1) * (ncols * pver)) + ((lev - 1) * ncols) + do col = 1, ncols + avg = real(offsize + col + (cincrements(cind) * num_time_steps), & + kind=kind_phys) + total_test = total_test + avg + if (abs((phys_state%q(col, lev, cind) - avg) / avg) > & + tolerance) then + if (need_header) then + write(6, '(2(2x,a),3x,a,10x,a,14x,a)') & + 'COL', 'LEV', 'C#', 'Q', 'EXPECTED' + need_header = .false. + end if + write(6, '(3i5,2(3x,es15.7))') col, lev, cind, & + phys_state%q(col, lev, cind), avg + compare_data = .false. + end if + end do + end do end do - + if (abs((total_test - total_ref) / total_ref) > tolerance) then + write(6, '(a,e12.4)') 'TOTAL REFERENCE: ', total_ref + write(6, '(a,e12.4)') 'TOTAL TEST: ', total_test + write(6, '(2(a,e12.4))') 'REL.DIFF > TOLERANCE:', & + abs((total_test - total_ref) / total_ref), ' >', tolerance + compare_data = .false. + else + write(0, '(a,e12.4)') 'TOTAL REFERENCE: ', total_ref + write(0, '(a,e12.4)') 'TOTAL TEST: ', total_test + write(0, '(2(a,e12.4))') 'REL.DIFF < TOLERANCE:', & + abs((total_test - total_ref) / total_ref), ' <', tolerance + end if end function compare_data end module test_host_mod From 12c375e639f32d82c65c2093078f76f079c76286 Mon Sep 17 00:00:00 2001 From: Haipeng Lin Date: Mon, 23 Mar 2026 13:11:29 -0400 Subject: [PATCH 07/12] Fix TypeError when reporting ParseSyntaxError in parse_fortran_var_decl (#726) Fix TypeError from ParseSyntaxError in parse_fortran_var_decl In `parse_fortran_var_decl()`, when `FortranVar()` raises a `ParseSyntaxError`, the exception object was appended directly to the errors list. `parse_module` expects string elements and calls `'\n'.join(errors)`, which crashes with a `TypeError`. Convert the exception to a string before appending. From the context above `errmsg` is already being appended to `errors` array so I think this is a safe change to make that is consistent with the intended type of `errors[]`. User interface changes?: No Fixes: closes #725 Testing: unit tests: New doctest for parse_fortran_var_decl() covers previous error manual testing: see minimal reproducible example in issue #725 --- scripts/fortran_tools/parse_fortran.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/fortran_tools/parse_fortran.py b/scripts/fortran_tools/parse_fortran.py index 4b3605c1..ab072afd 100644 --- a/scripts/fortran_tools/parse_fortran.py +++ b/scripts/fortran_tools/parse_fortran.py @@ -701,6 +701,8 @@ def parse_fortran_var_decl(line, source, run_env, imports=None): ['8'] >>> parse_fortran_var_decl("character(len=*), intent(out) :: errmsg", ParseSource('foo.F90', 'module', ParseContext()), _DUMMY_RUN_ENV)[1][0] 'Syntax error: Invalid variable declaration, character(len=*), intent(out) :: errmsg, intent not allowed in module variable, in ' + >>> parse_fortran_var_decl("type(banana_t) :: bananas(0:N_FRUITS)", ParseSource('foo.F90', 'module', ParseContext()), _DUMMY_RUN_ENV)[1][0] + "bananas: '0:N_FRUITS' is an invalid dimension name; integer dimension indices not supported, in " ## NB: Expressions (including function calls) not currently supported here #>>> parse_fortran_var_decl("real(kind_phys), intent(out) :: foo(size(bar))", ParseSource('foo.F90', 'scheme', ParseContext()), _DUMMY_RUN_ENV)[0].get_prop_value('dimensions') @@ -814,7 +816,7 @@ def parse_fortran_var_decl(line, source, run_env, imports=None): fortran_imports=imports) newvars.append(var) except ParseSyntaxError as perr: - errors.append(perr) + errors.append(str(perr)) # end try # end for # No else (not a variable declaration) From 118f000eb737a23298753d78376151ee60d61933 Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Fri, 3 Apr 2026 06:37:21 -0700 Subject: [PATCH 08/12] Fix test/unit_tests/test_fortran_write.py --- .../fortran_files/comments_test.F90 | 3 +- .../fortran_files/linebreak_test.F90 | 5 +- .../fortran_files/long_string_test.F90 | 3 +- test/unit_tests/test_fortran_write.py | 2 - .../tmp/fortran_files/comments_test.F90 | 33 ++++++ .../tmp/fortran_files/linebreak_test.F90 | 51 ++++++++ .../tmp/fortran_files/long_string_test.F90 | 111 ++++++++++++++++++ 7 files changed, 198 insertions(+), 10 deletions(-) create mode 100644 test/unit_tests/tmp/fortran_files/comments_test.F90 create mode 100644 test/unit_tests/tmp/fortran_files/linebreak_test.F90 create mode 100644 test/unit_tests/tmp/fortran_files/long_string_test.F90 diff --git a/test/unit_tests/sample_files/fortran_files/comments_test.F90 b/test/unit_tests/sample_files/fortran_files/comments_test.F90 index b0183858..a3aa6072 100644 --- a/test/unit_tests/sample_files/fortran_files/comments_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/comments_test.F90 @@ -10,13 +10,13 @@ ! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + !> !! @brief Auto-generated Test of comment writing for FortranWriter !! ! module comments_test -! codee format off ! We can write comments in the module header ! We can write indented comments in the header integer :: foo ! Comment at end of line works @@ -29,6 +29,5 @@ module comments_test contains ! We can write comments in the module body -! codee format on end module comments_test diff --git a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 index 7facb467..31fb7497 100644 --- a/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/linebreak_test.F90 @@ -10,13 +10,13 @@ ! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + !> !! @brief Auto-generated Test of line breaking for FortranWriter !! ! module linebreak_test -! codee format off character(len=7) :: data(100) = (/ 'name000', 'name001', 'name002', 'name003', 'name004', & 'name005', 'name006', 'name007', 'name008', 'name009', 'name010', 'name011', 'name012', & 'name013', 'name014', 'name015', 'name016', 'name017', 'name018', 'name019', 'name020', & @@ -30,7 +30,6 @@ module linebreak_test 'name077', 'name078', 'name079', 'name080', 'name081', 'name082', 'name083', 'name084', & 'name085', 'name086', 'name087', 'name088', 'name089', 'name090', 'name091', 'name092', & 'name093', 'name094', 'name095', 'name096', 'name097', 'name098', 'name099' /) -! codee format on contains @@ -41,14 +40,12 @@ subroutine foo(ozone_constituents, aerosol_constituents, volcaero_constituents, integer, intent(in) :: volcaero_constituents(:) integer, intent(in) :: other_constituents(:) real, allocatable :: tracer_data_test_dynamic_constituents(:) -! codee format off allocate(tracer_data_test_dynamic_constituents(0+size(ozone_constituents)+size( & aerosol_constituents)+size(volcaero_constituents)+size(other_constituents))) write(6, '(a)') & 'Cannot read columns_on_task from file'// & ', columns_on_task has no horizontal dimension; columns_on_task is a protected variable' -! codee format on end subroutine foo end module linebreak_test diff --git a/test/unit_tests/sample_files/fortran_files/long_string_test.F90 b/test/unit_tests/sample_files/fortran_files/long_string_test.F90 index 7484031f..46e0c350 100644 --- a/test/unit_tests/sample_files/fortran_files/long_string_test.F90 +++ b/test/unit_tests/sample_files/fortran_files/long_string_test.F90 @@ -10,13 +10,13 @@ ! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + !> !! @brief Auto-generated Test of long string breaking for FortranWriter !! ! module long_string_test -! codee format off foo100 = & '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' @@ -107,6 +107,5 @@ module long_string_test foo129 = & '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& &345678' -! codee format on end module long_string_test diff --git a/test/unit_tests/test_fortran_write.py b/test/unit_tests/test_fortran_write.py index 8466e2ec..2a09436c 100644 --- a/test/unit_tests/test_fortran_write.py +++ b/test/unit_tests/test_fortran_write.py @@ -92,7 +92,6 @@ def test_line_breaking(self): gen.write("integer, intent(in) :: volcaero_constituents(:)", 2) gen.write("integer, intent(in) :: other_constituents(:)", 2) gen.write("real, allocatable :: tracer_data_test_dynamic_constituents(:)", 2) - gen.comment("codee format off", 0) gen.write("allocate(tracer_data_test_dynamic_constituents(0+" "size(ozone_constituents)+size(aerosol_constituents)" "+size(volcaero_constituents)+size(other_constituents)))", 2) @@ -102,7 +101,6 @@ def test_line_breaking(self): "dimension; columns_on_task is a ", "protected variable'"] gen.write(f"{''.join(line_items)}", 2) - gen.comment("codee format on", 0) gen.write("end subroutine foo", 1) # end with diff --git a/test/unit_tests/tmp/fortran_files/comments_test.F90 b/test/unit_tests/tmp/fortran_files/comments_test.F90 new file mode 100644 index 00000000..a3aa6072 --- /dev/null +++ b/test/unit_tests/tmp/fortran_files/comments_test.F90 @@ -0,0 +1,33 @@ +! +! This work (Common Community Physics Package Framework), identified by +! NOAA, NCAR, CU/CIRES, is free of known copyright restrictions and is +! placed in the public domain. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +! THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +!> +!! @brief Auto-generated Test of comment writing for FortranWriter +!! +! +module comments_test + +! We can write comments in the module header + ! We can write indented comments in the header + integer :: foo ! Comment at end of line works + integer :: bar ! + ! xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + ! + integer :: baz ! + ! yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + ! yyyy + +contains + ! We can write comments in the module body + +end module comments_test diff --git a/test/unit_tests/tmp/fortran_files/linebreak_test.F90 b/test/unit_tests/tmp/fortran_files/linebreak_test.F90 new file mode 100644 index 00000000..31fb7497 --- /dev/null +++ b/test/unit_tests/tmp/fortran_files/linebreak_test.F90 @@ -0,0 +1,51 @@ +! +! This work (Common Community Physics Package Framework), identified by +! NOAA, NCAR, CU/CIRES, is free of known copyright restrictions and is +! placed in the public domain. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +! THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +!> +!! @brief Auto-generated Test of line breaking for FortranWriter +!! +! +module linebreak_test + + character(len=7) :: data(100) = (/ 'name000', 'name001', 'name002', 'name003', 'name004', & + 'name005', 'name006', 'name007', 'name008', 'name009', 'name010', 'name011', 'name012', & + 'name013', 'name014', 'name015', 'name016', 'name017', 'name018', 'name019', 'name020', & + 'name021', 'name022', 'name023', 'name024', 'name025', 'name026', 'name027', 'name028', & + 'name029', 'name030', 'name031', 'name032', 'name033', 'name034', 'name035', 'name036', & + 'name037', 'name038', 'name039', 'name040', 'name041', 'name042', 'name043', 'name044', & + 'name045', 'name046', 'name047', 'name048', 'name049', 'name050', 'name051', 'name052', & + 'name053', 'name054', 'name055', 'name056', 'name057', 'name058', 'name059', 'name060', & + 'name061', 'name062', 'name063', 'name064', 'name065', 'name066', 'name067', 'name068', & + 'name069', 'name070', 'name071', 'name072', 'name073', 'name074', 'name075', 'name076', & + 'name077', 'name078', 'name079', 'name080', 'name081', 'name082', 'name083', 'name084', & + 'name085', 'name086', 'name087', 'name088', 'name089', 'name090', 'name091', 'name092', & + 'name093', 'name094', 'name095', 'name096', 'name097', 'name098', 'name099' /) + +contains + + subroutine foo(ozone_constituents, aerosol_constituents, volcaero_constituents, & + other_constituents) + integer, intent(in) :: ozone_constituents(:) + integer, intent(in) :: aerosol_constituents(:) + integer, intent(in) :: volcaero_constituents(:) + integer, intent(in) :: other_constituents(:) + real, allocatable :: tracer_data_test_dynamic_constituents(:) + allocate(tracer_data_test_dynamic_constituents(0+size(ozone_constituents)+size( & + aerosol_constituents)+size(volcaero_constituents)+size(other_constituents))) + + write(6, '(a)') & + 'Cannot read columns_on_task from file'// & + ', columns_on_task has no horizontal dimension; columns_on_task is a protected variable' + end subroutine foo + +end module linebreak_test diff --git a/test/unit_tests/tmp/fortran_files/long_string_test.F90 b/test/unit_tests/tmp/fortran_files/long_string_test.F90 new file mode 100644 index 00000000..46e0c350 --- /dev/null +++ b/test/unit_tests/tmp/fortran_files/long_string_test.F90 @@ -0,0 +1,111 @@ +! +! This work (Common Community Physics Package Framework), identified by +! NOAA, NCAR, CU/CIRES, is free of known copyright restrictions and is +! placed in the public domain. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +! THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +!> +!! @brief Auto-generated Test of long string breaking for FortranWriter +!! +! +module long_string_test + + foo100 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' + + foo101 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' + + foo102 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' + + foo103 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012' + + foo104 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123' + + foo105 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234' + + foo106 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345' + + foo107 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456' + + foo108 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567' + + foo109 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678' + + foo110 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' + + foo111 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' + + foo112 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' + + foo113 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012' + + foo114 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123' + + foo115 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234' + + foo116 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345' + + foo117 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456' + + foo118 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567' + + foo119 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678' + + foo120 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' + + foo121 = & + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' + + foo122 = & + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' + + foo123 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&' + foo124 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&3' + foo125 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&34' + foo126 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&345' + foo127 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&3456' + foo128 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&34567' + foo129 = & + '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& +&345678' + +end module long_string_test From 42930e84822ea9866d69db0a32ceeb1933838109 Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Fri, 3 Apr 2026 06:38:06 -0700 Subject: [PATCH 09/12] Exclude certain files from Codee formatting checks --- .github/workflows/fortran-formatting.yaml | 29 ++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/.github/workflows/fortran-formatting.yaml b/.github/workflows/fortran-formatting.yaml index 7ca69e8a..c87ee17a 100644 --- a/.github/workflows/fortran-formatting.yaml +++ b/.github/workflows/fortran-formatting.yaml @@ -33,13 +33,40 @@ jobs: if [[ "${MODIFIED_FILES}" == "" ]]; then exit 0 fi + + # Filter list of modified files to exclude certain files + EXCLUDED_FILES=( + test/unit_tests/sample_files/fortran_files/linebreak_test.F90 + test/unit_tests/sample_files/fortran_files/comments_test.F90 + test/unit_tests/sample_files/fortran_files/long_string_test.F90 + ) + FILTERED_FILES=() + while IFS= read -r file; do + skip=false + for excluded in "${EXCLUDED_FILES[@]}"; do + if [[ "$file" == "$excluded" ]]; then + skip=true + break + fi + done + if [[ "$skip" == false ]]; then + FILTERED_FILES+=("$file") + fi + done <<< "$MODIFIED_FILES" + echo "MODIFIED_FILES: ${MODIFIED_FILES[@]}" + echo "EXCLUDED_FILES: ${EXCLUDED_FILES[@]}" + echo "FILTERED_FILES: ${FILTERED_FILES[@]}" + if [[ "${FILTERED_FILES}" == "" ]]; then + exit 0 + fi + # echo "Installing Codee ${CODEE_VERSION} ..." wget https://codee.com/release/codee-${CODEE_VERSION}-linux-x86_64.tar.gz tar -xf codee-${CODEE_VERSION}-linux-x86_64.tar.gz export PATH="${PWD}/codee-${CODEE_VERSION}-linux-x86_64/bin:${PATH}" # - codee format --accept-eula --verbose ${MODIFIED_FILES} + codee format --accept-eula --verbose ${FILTERED_FILES} REFORMATTED_FILES=$(git diff --name-only --diff-filter=d) if [[ "${REFORMATTED_FILES}" == "" ]]; then exit 0 From c4fcac06f5de03a11771abb9c444b983257c8dd3 Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Fri, 3 Apr 2026 06:40:40 -0700 Subject: [PATCH 10/12] Remove erroneously committed files --- .../tmp/fortran_files/comments_test.F90 | 33 ------ .../tmp/fortran_files/linebreak_test.F90 | 51 -------- .../tmp/fortran_files/long_string_test.F90 | 111 ------------------ 3 files changed, 195 deletions(-) delete mode 100644 test/unit_tests/tmp/fortran_files/comments_test.F90 delete mode 100644 test/unit_tests/tmp/fortran_files/linebreak_test.F90 delete mode 100644 test/unit_tests/tmp/fortran_files/long_string_test.F90 diff --git a/test/unit_tests/tmp/fortran_files/comments_test.F90 b/test/unit_tests/tmp/fortran_files/comments_test.F90 deleted file mode 100644 index a3aa6072..00000000 --- a/test/unit_tests/tmp/fortran_files/comments_test.F90 +++ /dev/null @@ -1,33 +0,0 @@ -! -! This work (Common Community Physics Package Framework), identified by -! NOAA, NCAR, CU/CIRES, is free of known copyright restrictions and is -! placed in the public domain. -! -! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -! THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -!> -!! @brief Auto-generated Test of comment writing for FortranWriter -!! -! -module comments_test - -! We can write comments in the module header - ! We can write indented comments in the header - integer :: foo ! Comment at end of line works - integer :: bar ! - ! xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - ! - integer :: baz ! - ! yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - ! yyyy - -contains - ! We can write comments in the module body - -end module comments_test diff --git a/test/unit_tests/tmp/fortran_files/linebreak_test.F90 b/test/unit_tests/tmp/fortran_files/linebreak_test.F90 deleted file mode 100644 index 31fb7497..00000000 --- a/test/unit_tests/tmp/fortran_files/linebreak_test.F90 +++ /dev/null @@ -1,51 +0,0 @@ -! -! This work (Common Community Physics Package Framework), identified by -! NOAA, NCAR, CU/CIRES, is free of known copyright restrictions and is -! placed in the public domain. -! -! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -! THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -!> -!! @brief Auto-generated Test of line breaking for FortranWriter -!! -! -module linebreak_test - - character(len=7) :: data(100) = (/ 'name000', 'name001', 'name002', 'name003', 'name004', & - 'name005', 'name006', 'name007', 'name008', 'name009', 'name010', 'name011', 'name012', & - 'name013', 'name014', 'name015', 'name016', 'name017', 'name018', 'name019', 'name020', & - 'name021', 'name022', 'name023', 'name024', 'name025', 'name026', 'name027', 'name028', & - 'name029', 'name030', 'name031', 'name032', 'name033', 'name034', 'name035', 'name036', & - 'name037', 'name038', 'name039', 'name040', 'name041', 'name042', 'name043', 'name044', & - 'name045', 'name046', 'name047', 'name048', 'name049', 'name050', 'name051', 'name052', & - 'name053', 'name054', 'name055', 'name056', 'name057', 'name058', 'name059', 'name060', & - 'name061', 'name062', 'name063', 'name064', 'name065', 'name066', 'name067', 'name068', & - 'name069', 'name070', 'name071', 'name072', 'name073', 'name074', 'name075', 'name076', & - 'name077', 'name078', 'name079', 'name080', 'name081', 'name082', 'name083', 'name084', & - 'name085', 'name086', 'name087', 'name088', 'name089', 'name090', 'name091', 'name092', & - 'name093', 'name094', 'name095', 'name096', 'name097', 'name098', 'name099' /) - -contains - - subroutine foo(ozone_constituents, aerosol_constituents, volcaero_constituents, & - other_constituents) - integer, intent(in) :: ozone_constituents(:) - integer, intent(in) :: aerosol_constituents(:) - integer, intent(in) :: volcaero_constituents(:) - integer, intent(in) :: other_constituents(:) - real, allocatable :: tracer_data_test_dynamic_constituents(:) - allocate(tracer_data_test_dynamic_constituents(0+size(ozone_constituents)+size( & - aerosol_constituents)+size(volcaero_constituents)+size(other_constituents))) - - write(6, '(a)') & - 'Cannot read columns_on_task from file'// & - ', columns_on_task has no horizontal dimension; columns_on_task is a protected variable' - end subroutine foo - -end module linebreak_test diff --git a/test/unit_tests/tmp/fortran_files/long_string_test.F90 b/test/unit_tests/tmp/fortran_files/long_string_test.F90 deleted file mode 100644 index 46e0c350..00000000 --- a/test/unit_tests/tmp/fortran_files/long_string_test.F90 +++ /dev/null @@ -1,111 +0,0 @@ -! -! This work (Common Community Physics Package Framework), identified by -! NOAA, NCAR, CU/CIRES, is free of known copyright restrictions and is -! placed in the public domain. -! -! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -! THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -!> -!! @brief Auto-generated Test of long string breaking for FortranWriter -!! -! -module long_string_test - - foo100 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' - - foo101 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' - - foo102 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' - - foo103 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012' - - foo104 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123' - - foo105 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234' - - foo106 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345' - - foo107 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456' - - foo108 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567' - - foo109 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678' - - foo110 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' - - foo111 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' - - foo112 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' - - foo113 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012' - - foo114 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123' - - foo115 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234' - - foo116 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345' - - foo117 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456' - - foo118 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567' - - foo119 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678' - - foo120 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' - - foo121 = & - '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' - - foo122 = & - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' - - foo123 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& -&' - foo124 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& -&3' - foo125 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& -&34' - foo126 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& -&345' - foo127 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& -&3456' - foo128 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& -&34567' - foo129 = & - '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012& -&345678' - -end module long_string_test From b1c57efcf91bc723b891ff4b08e6ce8be5760737 Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Mon, 6 Apr 2026 09:27:34 -0700 Subject: [PATCH 11/12] Remove files from codee exlude list in .github/workflows/fortran-formatting.yaml --- .github/workflows/fortran-formatting.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/fortran-formatting.yaml b/.github/workflows/fortran-formatting.yaml index c87ee17a..968e20fb 100644 --- a/.github/workflows/fortran-formatting.yaml +++ b/.github/workflows/fortran-formatting.yaml @@ -36,9 +36,8 @@ jobs: # Filter list of modified files to exclude certain files EXCLUDED_FILES=( - test/unit_tests/sample_files/fortran_files/linebreak_test.F90 - test/unit_tests/sample_files/fortran_files/comments_test.F90 - test/unit_tests/sample_files/fortran_files/long_string_test.F90 + # file1 + # file2 ) FILTERED_FILES=() while IFS= read -r file; do From ca0163791a83909597ec1a309a31605c630a0807 Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Mon, 6 Apr 2026 11:04:13 -0600 Subject: [PATCH 12/12] Apply suggestion from @climbfuji --- scripts/fortran_tools/fortran_write.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/fortran_tools/fortran_write.py b/scripts/fortran_tools/fortran_write.py index 7cf46fa4..35d403e0 100644 --- a/scripts/fortran_tools/fortran_write.py +++ b/scripts/fortran_tools/fortran_write.py @@ -29,8 +29,6 @@ class FortranWriter: __BREAK_CHARS = [',', '+', '*', '/', '(', ')'] - __BREAK_CHARS = [',', '+', '*', '/', '(', ')'] - # CCPP copyright statement to be included in all generated Fortran files __COPYRIGHT = '''! ! This work (Common Community Physics Package Framework), identified by