def parse_suites(suites_dir, sdfs): """Parse suite definition files for prebuild""" logging.info('Parsing suite definition files ...') suites = [] for sdf in sdfs: logging.info('Parsing suite definition file {0} ...'.format(os.path.join(suites_dir, sdf))) suite = Suite(sdf_name=os.path.join(suites_dir, sdf)) success = suite.parse() if not success: logging.error('Parsing suite definition file {0} failed.'.format(sdf)) break suites.append(suite) return (success, suites)
def main(): """Main routine that handles the CCPP prebuild for different host models.""" # Parse command line arguments (success, configfile, debug, static, sdf) = parse_arguments() if not success: raise Exception('Call to parse_arguments failed.') success = setup_logging(debug) if not success: raise Exception('Call to setup_logging failed.') (success, config) = import_config(configfile) if not success: raise Exception('Call to import_config failed.') if static: # Parse suite definition file for static build suite = Suite(sdf_name=sdf) success = suite.parse() if not success: raise Exception( 'Parsing suite definition file {0} failed.'.format(sdf)) # Check that each scheme only belongs to one set of physics # this is required for using the optimized version of ccpp_field_get # that supplies the build-time derived index in the array success = check_unique_pset_per_scheme(config['scheme_files']) if not success: raise Exception('Call to check_unique_pset_per_scheme failed.') # Variables defined by the host model (success, metadata_define) = gather_variable_definitions( config['variable_definition_files']) if not success: raise Exception('Call to gather_variable_definitions failed.') # Create an HTML table with all variables provided by the model success = metadata_to_html(metadata_define, config['host_model'], config['html_vartable_file']) if not success: raise Exception('Call to metadata_to_html failed.') # Variables requested by the CCPP physics schemes (success, metadata_request, pset_request, arguments_request, pset_schemes) = collect_physics_subroutines(config['scheme_files']) if not success: raise Exception('Call to collect_physics_subroutines failed.') # For static build, also check that each group only contains scheme that # belong to one set of physics; this is required for using the optimized # version of ccpp_field_get that supplies the build-time derived index # of the variable in the cdata structure if static: success = check_unique_pset_per_group(suite, pset_schemes) if not success: raise Exception('Call to check_unique_pset_per_group failed.') # Filter metadata/pset/arguments for static build - remove whatever is not included in suite definition file if static: (success, metadata_request, pset_request, arguments_request) = filter_metadata(metadata_request, pset_request, arguments_request, suite) if not success: raise Exception('Call to filter_metadata failed.') # Process optional arguments based on configuration in above dictionary optional_arguments (success, metadata_request, arguments_request) = check_optional_arguments( metadata_request, arguments_request, config['optional_arguments']) if not success: raise Exception('Call to check_optional_arguments failed.') # Create a LaTeX table with all variables requested by the pool of physics and/or provided by the host model success = metadata_to_latex(metadata_define, metadata_request, pset_request, config['host_model'], config['latex_vartable_file']) if not success: raise Exception('Call to metadata_to_latex failed.') # Flatten list of list of psets for all variables psets_merged = list(set(itertools.chain(*pset_request.values()))) # Check requested against defined arguments to generate metadata (list/dict of variables for CCPP) (success, modules, metadata) = compare_metadata(metadata_define, metadata_request, pset_request, psets_merged) if not success: raise Exception('Call to compare_metadata failed.') # Dictionary of indices of variables in the cdata structure, per pset ccpp_field_maps = {} for pset in psets_merged: # Create module use statements to inject into the host model cap (success, module_use_statements) = create_module_use_statements( modules[pset], pset, config['module_use_template_host_cap']) if not success: raise Exception('Call to create_module_use_statements failed.') # Only process variables that fall into this pset metadata_filtered = { key: value for (key, value) in metadata.items() if pset in pset_request[key] } # Create ccpp_fiels_add statements to inject into the host model cap; # this returns a ccpp_field_map that contains indices of variables in # the cdata structure for the given pset (success, ccpp_field_add_statements, ccpp_field_map) = create_ccpp_field_add_statements( metadata_filtered, pset, config['ccpp_data_structure']) if not success: raise Exception('Call to create_ccpp_field_add_statements failed.') ccpp_field_maps[pset] = ccpp_field_map # Generate include files for module_use_statements and ccpp_field_add_statements success = generate_include_files( module_use_statements, ccpp_field_add_statements, config['target_files'], config['module_include_file'].format(set=pset), config['fields_include_file'].format(set=pset)) if not success: raise Exception('Call to generate_include_files failed.') # Static build: generate caps for entire suite and groups in the specified suite; generate API if static: (success, suite_and_group_caps) = generate_suite_and_group_caps( suite, metadata_request, metadata_define, arguments_request, ccpp_field_maps, config['caps_dir'], config['module_use_template_scheme_cap']) if not success: raise Exception('Call to generate_suite_and_group_caps failed.') (success, api) = generate_static_api(suite, config['caps_dir']) if not success: raise Exception('Call to generate_static_api failed.') # Generate scheme caps (success, scheme_caps) = generate_scheme_caps( metadata_request, arguments_request, pset_schemes, ccpp_field_maps, config['caps_dir'], config['module_use_template_scheme_cap']) if not success: raise Exception('Call to generate_scheme_caps failed.') # Add filenames of schemes to makefile - add dependencies for schemes success = generate_schemes_makefile( config['scheme_files_dependencies'] + config['scheme_files'].keys(), config['schemes_makefile'], config['schemes_cmakefile']) if not success: raise Exception('Call to generate_schemes_makefile failed.') # DH* NOT FOR STATIC BUILD - add static code (group and suite drivers) instead? # Add filenames of scheme caps to makefile if static: all_caps = scheme_caps + suite_and_group_caps + [api.filename] else: all_caps = scheme_caps success = generate_caps_makefile(all_caps, config['caps_makefile'], config['caps_cmakefile'], config['caps_dir']) if not success: raise Exception('Call to generate_caps_makefile failed.') logging.info('CCPP prebuild step completed successfully.')