@@ -739,14 +739,21 @@ def get_dimension_info(hvar):
739
739
- The local variable name of the vertical dimension (or None)
740
740
- True if <hvar> has one dimension which is a horizontal dimension or
741
741
if <hvar> has two dimensions (horizontal and vertical)
742
+ - Flag if any dimensions are number_of_ccpp_constituents and needs
743
+ reading separate variables by constituent and reassembled into
744
+ host model indices.
742
745
"""
743
746
vdim_name = None
744
747
legal_dims = False
745
748
fail_reason = ""
749
+
746
750
dims = hvar .get_dimensions ()
747
751
levnm = hvar .has_vertical_dimension ()
752
+ has_constituent_dim = any ('number_of_ccpp_constituents' in dim for dim in dims )
753
+
748
754
# <hvar> is only 'legal' for 2 or 3 dimensional fields (i.e., 1 or 2
749
- # dimensional variables). The second dimension must be vertical.
755
+ # dimensional variables).
756
+ # The second dimension must either be vertical or number of constituents.
750
757
# XXgoldyXX: If we ever need to read scalars, it would have to be
751
758
# done using global attributes, not 'infld'.
752
759
ldims = len (dims )
@@ -758,7 +765,17 @@ def get_dimension_info(hvar):
758
765
fail_reason += f"{ suff } { lname } has no horizontal dimension"
759
766
suff = "; "
760
767
# end if
761
- if (ldims > 2 ) or ((ldims > 1 ) and (not levnm )):
768
+
769
+ if has_constituent_dim :
770
+ # A special case where any dimensions include number_of_ccpp_constituents,
771
+ # in this case the variable needs to be suffixed by an underscore plus the constituent name
772
+ # and read and reassembled separately into host model constituent indices
773
+ # based on constituent name.
774
+ # This case will be handled separately.
775
+ legal_dims = True
776
+ elif (ldims > 2 ) or ((ldims > 1 ) and (not levnm )):
777
+ # The regular case where the second dimension must be vertical,
778
+ # and higher dimensions are unsupported.
762
779
legal_dims = False
763
780
unsupp = []
764
781
for dim in dims :
@@ -785,6 +802,7 @@ def get_dimension_info(hvar):
785
802
# end if
786
803
suff = "; "
787
804
# end if
805
+
788
806
if legal_dims and levnm :
789
807
# <hvar> should be legal, find the correct local name for the
790
808
# vertical dimension
@@ -808,7 +826,8 @@ def get_dimension_info(hvar):
808
826
raise ValueError (f"Vertical dimension, '{ levnm } ', not found" )
809
827
# end if
810
828
# end if
811
- return vdim_name , legal_dims , fail_reason
829
+
830
+ return vdim_name , legal_dims , fail_reason , has_constituent_dim
812
831
813
832
def write_phys_read_subroutine (outfile , host_dict , host_vars , host_imports ,
814
833
phys_check_fname_str , constituent_set ,
@@ -850,7 +869,7 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
850
869
call_string_key = f"case ('{ var_stdname } ')"
851
870
852
871
# Extract vertical level variable:
853
- levnm , call_read_field , reason = get_dimension_info (hvar )
872
+ levnm , call_read_field , reason , has_constituent_read = get_dimension_info (hvar )
854
873
if hvar .get_prop_value ('protected' ):
855
874
call_read_field = False
856
875
if reason :
@@ -860,14 +879,23 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
860
879
# end if
861
880
lvar = hvar .get_prop_value ('local_name' )
862
881
reason += f"{ suff } { lvar } is a protected variable"
882
+ # end if
883
+
863
884
# Set "read_field" call string:
864
885
if call_read_field :
865
- # Replace vertical dimension with local name
866
- call_str = "call read_field(file, " + \
867
- f"'{ var_stdname } ', input_var_names(:,name_idx), "
886
+ if has_constituent_read :
887
+ # Special case for constituent-dimension variables.
888
+ call_str = f"call read_constituent_dimensioned_field(const_props, file, '{ var_stdname } ', input_var_names(:,name_idx), "
889
+ else :
890
+ # Replace vertical dimension with local name
891
+ call_str = "call read_field(file, " + \
892
+ f"'{ var_stdname } ', input_var_names(:,name_idx), "
893
+ # end if
894
+
868
895
if levnm is not None :
869
896
call_str += f"'{ levnm } ', "
870
897
# end if
898
+
871
899
err_on_not_found_string = ""
872
900
if var_stdname in vars_init_value :
873
901
# if initial value is available, do not throw error when not found in initial condition file.
@@ -903,7 +931,8 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
903
931
["shr_kind_mod" , ["SHR_KIND_CS, SHR_KIND_CL, SHR_KIND_CX" ]],
904
932
["physics_data" , ["read_field" , "find_input_name_idx" ,
905
933
"no_exist_idx" , "init_mark_idx" ,
906
- "prot_no_init_idx" , "const_idx" ]],
934
+ "prot_no_init_idx" , "const_idx" ,
935
+ "read_constituent_dimensioned_field" ]],
907
936
["cam_ccpp_cap" , ["ccpp_physics_suite_variables" ,
908
937
"cam_constituents_array" ,
909
938
"cam_model_const_properties" ]],
@@ -967,8 +996,13 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
967
996
outfile .write ("logical :: use_init_variables" , 2 )
968
997
outfile .blank_line ()
969
998
999
+ # Prepare constituent properties pointer for later usage:
1000
+ outfile .comment ("Get constituent properties pointer:" , 2 )
1001
+ outfile .write ("const_props => cam_model_const_properties()" , 2 )
1002
+ outfile .blank_line ()
1003
+
970
1004
# Initialize variables:
971
- outfile .comment ("Initalize missing and non-initialized variables strings:" ,
1005
+ outfile .comment ("Initialize missing and non-initialized variables strings:" ,
972
1006
2 )
973
1007
outfile .write ("missing_required_vars = ' '" , 2 )
974
1008
outfile .write ("protected_non_init_vars = ' '" , 2 )
@@ -1103,7 +1137,6 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
1103
1137
# Read in constituent data
1104
1138
outfile .comment ("Read in constituent variables if not using init variables" , 2 )
1105
1139
outfile .write ("field_data_ptr => cam_constituents_array()" , 2 )
1106
- outfile .write ("const_props => cam_model_const_properties()" , 2 )
1107
1140
outfile .blank_line ()
1108
1141
outfile .comment ("Iterate over all registered constituents" , 2 )
1109
1142
outfile .write ("do constituent_idx = 1, size(const_props)" , 2 )
@@ -1138,7 +1171,7 @@ def write_phys_read_subroutine(outfile, host_dict, host_vars, host_imports,
1138
1171
outfile .write ("call const_props(constituent_idx)%minimum(constituent_min_value, constituent_errflg, constituent_errmsg)" , 5 )
1139
1172
outfile .write ("field_data_ptr(:,:,constituent_idx) = constituent_min_value" , 5 )
1140
1173
outfile .write ("if (masterproc) then" , 5 )
1141
- outfile .write ("write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to 0.' " , 6 )
1174
+ outfile .write ("write(iulog,*) 'Constituent ', trim(std_name), ' default value not configured. Setting to min value of ', constituent_min_value " , 6 )
1142
1175
outfile .write ("end if" , 5 )
1143
1176
outfile .write ("end if" , 4 )
1144
1177
outfile .write ("end if" , 3 )
@@ -1191,7 +1224,12 @@ def write_phys_check_subroutine(outfile, host_dict, host_vars, host_imports,
1191
1224
call_string_key = f"case ('{ var_stdname } ')"
1192
1225
1193
1226
# Extract vertical level variable:
1194
- levnm , call_check_field , reason = get_dimension_info (hvar )
1227
+ levnm , call_check_field , reason , has_constituent_read = get_dimension_info (hvar )
1228
+
1229
+ # If this is a constituent-indexed field, do not check it for now.
1230
+ if has_constituent_read :
1231
+ continue
1232
+ # end if
1195
1233
1196
1234
# Set "check_field" call string:
1197
1235
if call_check_field :
0 commit comments