Пример #1
0
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)
Пример #2
0
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.')