Skip to content

Commit bb37534

Browse files
authored
Merge branch 'develop' into development
2 parents fab0758 + 0345a66 commit bb37534

21 files changed

+674
-28
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 3.10)
1+
cmake_minimum_required(VERSION 3.18)
22

33
project(ccpp_framework
44
VERSION 5.0.0

scripts/ccpp_prebuild.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -490,9 +490,12 @@ def compare_metadata(metadata_define, metadata_request):
490490
if not metadata_define[var_name][0].active == 'T':
491491
for var in metadata_request[var_name]:
492492
if var.optional == 'F':
493-
logging.error("Conditionally allocated host-model variable {0} is not optional in {1}".format(
493+
# DH 20241022 - change logging.error to logging.warn, because it is known
494+
# that this strict check is not correct and will be reverted soon
495+
#logging.error(
496+
logging.warn("Conditionally allocated host-model variable {0} is not optional in {1}".format(
494497
var_name, var.container))
495-
success = False
498+
#success = False
496499
# TEMPORARY CHECK - IF THE VARIABLE IS ALWAYS ALLOCATED, THE SCHEME VARIABLE SHOULDN'T BE OPTIONAL
497500
else:
498501
for var in metadata_request[var_name]:

scripts/mkcap.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -299,13 +299,14 @@ def print_def_intent(self, metadata):
299299
# It is an error for host model variables to have the optional attribute in the metadata
300300
if self.optional == 'T':
301301
error_message = "This routine should only be called for host model variables" + \
302-
" that cannot be optional, but got self.optional=T"
302+
" that cannot have the optional metadata attribute, but got self.optional=T"
303303
raise Exception(error_message)
304304
# If the host variable is potentially unallocated, add optional and target to variable declaration
305305
elif not self.active == 'T':
306306
optional = ', optional, target'
307307
else:
308-
optional = ''
308+
# Always declare as target variable so that locally defined pointers can point to it
309+
optional = ', target'
309310
#
310311
if self.type in STANDARD_VARIABLE_TYPES:
311312
if self.kind:
@@ -355,12 +356,16 @@ def print_def_local(self, metadata):
355356
str = "type({s.type}), pointer :: p => null()"
356357
return str.format(s=self)
357358
else:
358-
# If the host variable is potentially unallocated, the active attribute is
359-
# also set accordingly for the local variable; add target to variable declaration
360-
if self.optional == 'T':
361-
target = ', target'
362-
else:
363-
target = ''
359+
# DH* 20241022 WORKAROUND TO ACCOUNT FOR MISSING UPDATES TO CCPP PHYSICS
360+
# W.R.T. DECLARING OPTIONAL VARIABLES IN METADATA AND CODE. ALWAYS USE TARGET
361+
## If the host variable is potentially unallocated, the active attribute is
362+
## also set accordingly for the local variable; add target to variable declaration
363+
#if self.optional == 'T':
364+
# target = ', target'
365+
#else:
366+
# target = ''
367+
target = ', target'
368+
# *DH
364369
if self.type in STANDARD_VARIABLE_TYPES:
365370
if self.kind:
366371
if self.rank:

scripts/mkstatic.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,17 @@ def create_arguments_module_use_var_defs(variable_dictionary, metadata_define, t
211211
kind_var_standard_name = variable_dictionary[standard_name].kind
212212
if not kind_var_standard_name in local_kind_and_type_vars:
213213
if not kind_var_standard_name in metadata_define.keys():
214-
raise Exception("Kind {kind} not defined by host model".format(kind=kind_var_standard_name))
214+
raise Exception("Kind {kind}, required by {std_name}, not defined by host model".format(
215+
kind=kind_var_standard_name, std_name=standard_name))
215216
kind_var = metadata_define[kind_var_standard_name][0]
216217
module_use.append(kind_var.print_module_use())
217218
local_kind_and_type_vars.append(kind_var_standard_name)
218219
elif not variable_dictionary[standard_name].type in STANDARD_VARIABLE_TYPES:
219220
type_var_standard_name = variable_dictionary[standard_name].type
220221
if not type_var_standard_name in local_kind_and_type_vars:
221222
if not type_var_standard_name in metadata_define.keys():
222-
raise Exception("Type {type} not defined by host model".format(type=type_var_standard_name))
223+
raise Exception("Type {type}, required by {std_name}, not defined by host model".format(
224+
type=type_var_standard_name, std_name=standard_name))
223225
type_var = metadata_define[type_var_standard_name][0]
224226
module_use.append(type_var.print_module_use())
225227
local_kind_and_type_vars.append(type_var_standard_name)
@@ -1476,27 +1478,50 @@ def write(self, metadata_request, metadata_define, arguments, debug):
14761478
if len(dimensions_target_name) < len(dim_substrings):
14771479
raise Exception("THIS SHOULD NOT HAPPEN")
14781480
dim_counter = 0
1481+
# We need two different dim strings for the following. The first,
1482+
# called 'dim_string' is used for the incoming variable (host model
1483+
# variable) and must contain all dimensions and indices. The second,
1484+
# called 'dim_string_allocate' is used for the allocation of temporary
1485+
# variables used for unit conversions etc. This 'dim_string_allocate'
1486+
# only contains the dimensions, not the indices of the target variable.
1487+
# Example: a scheme requests a variable foo that is a slice of a host
1488+
# model variable bar: foo(1:n) = bar(1:n,1). If a variable transformation
1489+
# is required, mkstatic creates a temporary variable tmpvar of rank 1.
1490+
# The allocation and assignment of this variable must then be
1491+
# allocate(tmpvar(1:n))
1492+
# tmpvar(1:n) = bar(1:n,1)
1493+
# Likewise, when scheme baz is called, the callstring must be
1494+
# call baz(...,foo=tmpvar(1:n),...)
1495+
# Hence the need for two different dim strings in the following code.
1496+
# See also https://github.com/NCAR/ccpp-framework/issues/598.
14791497
dim_string = '('
1498+
dim_string_allocate = '('
14801499
for dim in dimensions_target_name:
14811500
if ':' in dim:
14821501
dim_string += dim_substrings[dim_counter] + ','
1502+
dim_string_allocate += dim_substrings[dim_counter] + ','
14831503
dim_counter += 1
14841504
else:
14851505
dim_string += dim + ','
1506+
# Don't add to dim_string_allocate!
14861507
dim_string = dim_string.rstrip(',') + ')'
1508+
dim_string_allocate = dim_string_allocate.rstrip(',') + ')'
14871509
# Consistency check to make sure all dimensions from metadata are 'used'
14881510
if dim_counter < len(dim_substrings):
14891511
raise Exception(f"Mismatch of derived dimensions from metadata {dim_substrings} " + \
14901512
f"vs target local name {dimensions_target_name} for {var_standard_name} and " + \
14911513
f"scheme {scheme_name} / phase {ccpp_stage}")
14921514
else:
14931515
dim_string = '({})'.format(','.join(dim_substrings))
1516+
dim_string_allocate = dim_string
14941517
var_size_expected = '({})'.format('*'.join(array_size))
14951518
else:
14961519
if dimensions_target_name:
14971520
dim_string = dim_string_target_name
14981521
else:
14991522
dim_string = ''
1523+
# A scalar variable doesn't get allocated, set to safe value
1524+
dim_string_allocate = ''
15001525
var_size_expected = 1
15011526

15021527
# To assist debugging efforts, check if arrays have the correct size (ignore scalars for now)
@@ -1722,7 +1747,7 @@ def write(self, metadata_request, metadata_define, arguments, debug):
17221747
tmpvars[local_vars[var_standard_name]['name']] = tmpvar
17231748
if tmpvar.rank:
17241749
# Add allocate statement if the variable has a rank > 0 using the dimstring derived above
1725-
actions_in += f' allocate({tmpvar.local_name}{dim_string})\n'
1750+
actions_in += f' allocate({tmpvar.local_name}{dim_string_allocate})\n'
17261751
if var.actions['in']:
17271752
# Add unit conversion before entering the subroutine
17281753
actions_in += ' {t} = {c}{d}\n'.format(t=tmpvar.local_name,
@@ -1732,7 +1757,7 @@ def write(self, metadata_request, metadata_define, arguments, debug):
17321757
# If the variable is conditionally allocated, assign pointer
17331758
if not conditional == '.true.':
17341759
actions_in += ' {p} => {t}{d}\n'.format(p=f"{tmpptr.local_name}_array({CCPP_INTERNAL_VARIABLES[CCPP_THREAD_NUMBER]})%p",
1735-
t=tmpvar.local_name, d=dim_string)
1760+
t=tmpvar.local_name, d=dim_string_allocate)
17361761
if var.actions['out']:
17371762
# Add unit conversion after returning from the subroutine
17381763
actions_out += ' {v}{d} = {c}\n'.format(v=tmpvar.target.replace(dim_string_target_name, ''),
@@ -1763,7 +1788,7 @@ def write(self, metadata_request, metadata_define, arguments, debug):
17631788
# Add to argument list
17641789
if conditional == '.true.':
17651790
arg = '{local_name}={var_name}{dim_string},'.format(local_name=var.local_name,
1766-
var_name=tmpvar.local_name.replace(dim_string_target_name, ''), dim_string=dim_string)
1791+
var_name=tmpvar.local_name.replace(dim_string_target_name, ''), dim_string=dim_string_allocate)
17671792
else:
17681793
arg = '{local_name}={ptr_name},'.format(local_name=var.local_name,
17691794
ptr_name=f"{tmpptr.local_name}_array({CCPP_INTERNAL_VARIABLES[CCPP_THREAD_NUMBER]})%p")

test_prebuild/run_all_tests.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ echo "" && echo "Running unit_tests " && cd unit_tests && ./run_tes
66
echo "" && echo "Running test_opt_arg " && cd test_opt_arg && ./run_test.sh && cd ..
77
echo "" && echo "Running test_blocked_data" && cd test_blocked_data && ./run_test.sh && cd ..
88
echo "" && echo "Running test_chunked_data" && cd test_chunked_data && ./run_test.sh && cd ..
9+
echo "" && echo "Running test_unit_conv" && cd test_unit_conv && ./run_test.sh && cd ..
910

10-
echo "" && echo "Running test_track_variables" && pytest test_track_variables.py
11+
echo "" && echo "Running test_track_variables" && pytest test_track_variables.py

test_prebuild/test_blocked_data/main.F90

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,21 @@ program test_blocked_data
2323
! CCPP init step !
2424
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2525

26-
! For physics running over the entire domain, block and thread
27-
! number are not used; set to safe values
26+
! For physics running over the entire domain,
27+
! ccpp_thread_number and ccpp_chunk_number are
28+
! set to 1, indicating that arrays are to be sent
29+
! following their dimension specification in the
30+
! metadata (must match horizontal_dimension).
2831
ccpp_data_domain%blk_no = 1
2932
ccpp_data_domain%thrd_no = 1
33+
ccpp_data_domain%thrd_cnt = 1
3034

3135
! Loop over all blocks and threads for ccpp_data_blocks
3236
do ib=1,nblks
3337
! Assign the correct block numbers, only one thread
34-
ccpp_data_blocks(ib)%blk_no = ib
35-
ccpp_data_blocks(ib)%thrd_no = 1
38+
ccpp_data_blocks(ib)%blk_no = ib
39+
ccpp_data_blocks(ib)%thrd_no = 1
40+
ccpp_data_blocks(ib)%thrd_cnt = 1
3641
end do
3742

3843
do ib=1,size(blocked_data_instance)
@@ -85,7 +90,7 @@ program test_blocked_data
8590
cdata => ccpp_data_domain
8691
call ccpp_physics_timestep_finalize(cdata, suite_name=trim(ccpp_suite), ierr=ierr)
8792
if (ierr/=0) then
88-
write(error_unit,'(a)') "An error occurred in ccpp_physics_timestep_init:"
93+
write(error_unit,'(a)') "An error occurred in ccpp_physics_timestep_finalize:"
8994
write(error_unit,'(a)') trim(cdata%errmsg)
9095
stop 1
9196
end if
@@ -97,7 +102,7 @@ program test_blocked_data
97102
cdata => ccpp_data_domain
98103
call ccpp_physics_finalize(cdata, suite_name=trim(ccpp_suite), ierr=ierr)
99104
if (ierr/=0) then
100-
write(error_unit,'(a)') "An error occurred in ccpp_physics_timestep_init:"
105+
write(error_unit,'(a)') "An error occurred in ccpp_physics_finalize:"
101106
write(error_unit,'(a)') trim(cdata%errmsg)
102107
stop 1
103108
end if

test_prebuild/test_chunked_data/main.F90

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ program test_chunked_data
2525

2626
! For physics running over the entire domain,
2727
! ccpp_thread_number and ccpp_chunk_number are
28-
! set to 0, indicating that arrays are to be sent
28+
! set to 1, indicating that arrays are to be sent
2929
! following their dimension specification in the
3030
! metadata (must match horizontal_dimension).
31-
ccpp_data_domain%thrd_no = 0
32-
ccpp_data_domain%chunk_no = 0
31+
ccpp_data_domain%thrd_no = 1
32+
ccpp_data_domain%chunk_no = 1
3333
ccpp_data_domain%thrd_cnt = 1
3434

3535
! Loop over all chunks and threads for ccpp_data_chunks
@@ -88,7 +88,7 @@ program test_chunked_data
8888
cdata => ccpp_data_domain
8989
call ccpp_physics_timestep_finalize(cdata, suite_name=trim(ccpp_suite), ierr=ierr)
9090
if (ierr/=0) then
91-
write(error_unit,'(a)') "An error occurred in ccpp_physics_timestep_init:"
91+
write(error_unit,'(a)') "An error occurred in ccpp_physics_timestep_finalize:"
9292
write(error_unit,'(a)') trim(cdata%errmsg)
9393
stop 1
9494
end if
@@ -100,7 +100,7 @@ program test_chunked_data
100100
cdata => ccpp_data_domain
101101
call ccpp_physics_finalize(cdata, suite_name=trim(ccpp_suite), ierr=ierr)
102102
if (ierr/=0) then
103-
write(error_unit,'(a)') "An error occurred in ccpp_physics_timestep_init:"
103+
write(error_unit,'(a)') "An error occurred in ccpp_physics_finalize:"
104104
write(error_unit,'(a)') trim(cdata%errmsg)
105105
stop 1
106106
end if
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#------------------------------------------------------------------------------
2+
cmake_minimum_required(VERSION 3.10)
3+
4+
project(ccpp_unit_conv
5+
VERSION 1.0.0
6+
LANGUAGES Fortran)
7+
8+
#------------------------------------------------------------------------------
9+
# Request a static build
10+
option(BUILD_SHARED_LIBS "Build a shared library" OFF)
11+
12+
#------------------------------------------------------------------------------
13+
# Set MPI flags for C/C++/Fortran with MPI F08 interface
14+
find_package(MPI REQUIRED Fortran)
15+
if(NOT MPI_Fortran_HAVE_F08_MODULE)
16+
message(FATAL_ERROR "MPI implementation does not support the Fortran 2008 mpi_f08 interface")
17+
endif()
18+
19+
#------------------------------------------------------------------------------
20+
# Set the sources: physics type definitions
21+
set(TYPEDEFS $ENV{CCPP_TYPEDEFS})
22+
if(TYPEDEFS)
23+
message(STATUS "Got CCPP TYPEDEFS from environment variable: ${TYPEDEFS}")
24+
else(TYPEDEFS)
25+
include(${CMAKE_CURRENT_BINARY_DIR}/CCPP_TYPEDEFS.cmake)
26+
message(STATUS "Got CCPP TYPEDEFS from cmakefile include file: ${TYPEDEFS}")
27+
endif(TYPEDEFS)
28+
29+
# Generate list of Fortran modules from the CCPP type
30+
# definitions that need need to be installed
31+
foreach(typedef_module ${TYPEDEFS})
32+
list(APPEND MODULES_F90 ${CMAKE_CURRENT_BINARY_DIR}/${typedef_module})
33+
endforeach()
34+
35+
#------------------------------------------------------------------------------
36+
# Set the sources: physics schemes
37+
set(SCHEMES $ENV{CCPP_SCHEMES})
38+
if(SCHEMES)
39+
message(STATUS "Got CCPP SCHEMES from environment variable: ${SCHEMES}")
40+
else(SCHEMES)
41+
include(${CMAKE_CURRENT_BINARY_DIR}/CCPP_SCHEMES.cmake)
42+
message(STATUS "Got CCPP SCHEMES from cmakefile include file: ${SCHEMES}")
43+
endif(SCHEMES)
44+
45+
# Set the sources: physics scheme caps
46+
set(CAPS $ENV{CCPP_CAPS})
47+
if(CAPS)
48+
message(STATUS "Got CCPP CAPS from environment variable: ${CAPS}")
49+
else(CAPS)
50+
include(${CMAKE_CURRENT_BINARY_DIR}/CCPP_CAPS.cmake)
51+
message(STATUS "Got CCPP CAPS from cmakefile include file: ${CAPS}")
52+
endif(CAPS)
53+
54+
# Set the sources: physics scheme caps
55+
set(API $ENV{CCPP_API})
56+
if(API)
57+
message(STATUS "Got CCPP API from environment variable: ${API}")
58+
else(API)
59+
include(${CMAKE_CURRENT_BINARY_DIR}/CCPP_API.cmake)
60+
message(STATUS "Got CCPP API from cmakefile include file: ${API}")
61+
endif(API)
62+
63+
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -O0 -fno-unsafe-math-optimizations -frounding-math -fsignaling-nans -ffpe-trap=invalid,zero,overflow -fbounds-check -ggdb -fbacktrace -ffree-line-length-none")
64+
65+
#------------------------------------------------------------------------------
66+
add_library(ccpp_unit_conv STATIC ${SCHEMES} ${CAPS} ${API})
67+
target_link_libraries(ccpp_unit_conv PRIVATE MPI::MPI_Fortran)
68+
# Generate list of Fortran modules from defined sources
69+
foreach(source_f90 ${CAPS} ${API})
70+
get_filename_component(tmp_source_f90 ${source_f90} NAME)
71+
string(REGEX REPLACE ".F90" ".mod" tmp_module_f90 ${tmp_source_f90})
72+
string(TOLOWER ${tmp_module_f90} module_f90)
73+
list(APPEND MODULES_F90 ${CMAKE_CURRENT_BINARY_DIR}/${module_f90})
74+
endforeach()
75+
76+
set_target_properties(ccpp_unit_conv PROPERTIES VERSION ${PROJECT_VERSION}
77+
SOVERSION ${PROJECT_VERSION_MAJOR})
78+
79+
add_executable(test_unit_conv.x main.F90)
80+
add_dependencies(test_unit_conv.x ccpp_unit_conv)
81+
target_link_libraries(test_unit_conv.x ccpp_unit_conv)
82+
set_target_properties(test_unit_conv.x PROPERTIES LINKER_LANGUAGE Fortran)
83+
84+
# Define where to install the library
85+
install(TARGETS ccpp_unit_conv
86+
EXPORT ccpp_unit_conv-targets
87+
ARCHIVE DESTINATION lib
88+
LIBRARY DESTINATION lib
89+
RUNTIME DESTINATION lib
90+
)
91+
# Export our configuration
92+
install(EXPORT ccpp_unit_conv-targets
93+
FILE ccpp_unit_conv-config.cmake
94+
DESTINATION lib/cmake
95+
)
96+
# Define where to install the C headers and Fortran modules
97+
#install(FILES ${HEADERS_C} DESTINATION include)
98+
install(FILES ${MODULES_F90} DESTINATION include)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# How to build the unit conv test
2+
3+
1. Set compiler environment as appropriate for your system
4+
2. Run the following commands:
5+
```
6+
cd test_prebuild/test_unit_conv/
7+
rm -fr build
8+
mkdir build
9+
../../scripts/ccpp_prebuild.py --config=ccpp_prebuild_config.py --builddir=build
10+
cd build
11+
cmake .. 2>&1 | tee log.cmake
12+
make 2>&1 | tee log.make
13+
./test_unit_conv.x
14+
# On systems where linking against the MPI library requires a parallel launcher,
15+
# use 'mpirun -np 1 ./test_unit_conv.x' or 'srun -n 1 ./test_unit_conv.x' etc.
16+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module ccpp_kinds
2+
3+
!! \section arg_table_ccpp_kinds
4+
!! \htmlinclude ccpp_kinds.html
5+
!!
6+
7+
use iso_fortran_env, only: real64
8+
9+
implicit none
10+
11+
integer, parameter :: kind_phys = real64
12+
13+
end module ccpp_kinds

0 commit comments

Comments
 (0)