.. _SuiteGroupCaps: **************************************** Suite and Group *Caps* **************************************** The connection between the :term:`host model` and the physics :term:`schemes` through the :term:`CCPP Framework` is realized with :term:`caps` on both sides as illustrated in :numref:`Figure %s `. The CCPP *capgen* script discussed in :numref:`Chapter %s ` generates the :term:`caps ` that connect the physics schemes to the CCPP Framework. This chapter describes the :term:`suite` and :term:`group caps`, while the host model *caps* are described in :numref:`Chapter %s `. These *caps* autogenerated by ``ccpp_capgen.py`` reside in the directory defined by the ``CAPS_DIR`` variable (see example in :ref:`Listing 8.1 `). Overview ======== When CCPP is built, the CCPP Framework and physics are statically linked to the executable. This allows the best performance and efficient memory use. This build requires metadata provided by the host model and variables requested from the physics scheme. Only the variables required for the specified suites are kept, requiring one or more :term:`SDF`\ s (see left side of :numref:`Figure %s `) as arguments to the ``ccpp_capgen.py`` script. The CCPP *capgen* step performs the tasks below. * Parse Scheme and Host metadata and source files, compare argument list(s) consistency, check for requested vs provided variables by ``standard_name``, and also check for any Suite variables. * Check units, dimensions, type. Add variable transformation if a mismatch of units/type is detected and the required conversion has been implemented (see :numref:`Section %s ` for details). * Filter unused schemes and variables. * Create *caps* for groups and suite(s). * Create Host *caps* * Create CCPP *datatable. * Populate target lists in CMakeLists.txt with scheme files, dependency files, and autogenerated cap files from *datatable* The capgen datatable step will produce the following file lists for any host model. Note that the location of these files varies between the host models and whether an in-source or out-of-source build is used. * List of CCPP Scheme files: .. code-block:: console SCHEME_FORTRAN_FILES * List of CCPP dependency files: .. code-block:: console CAPGEN_DEPENDENCIES * List of autogenerated caps: .. code-block:: console CAPGEN_FILES * List of Host model files: .. code-block:: console HOST_FORTRAN_FILES * One *cap* per physics group (fast_physics, physics, radiation, time_vary, stochastic, …) for each suite: .. code-block:: console ccpp_{suite_name}_{group_name}_cap.F90 * *Cap* for each suite: .. code-block:: console ccpp_{suite_name}_cap.F90 * Autogenerated API (aka CCPP Framework). .. code-block:: console {host_name}_ccpp_cap.F90 ``{host_name}_ccpp_cap.F90`` is an interface, which contains subroutines ``ccpp_register``, ``ccpp_init``, ``ccpp_physics_init``, ``ccpp_physics_timestep_init``, ``ccpp_physics_run``, ``ccpp_physics_timestep_final``, and ``ccpp_physics_final``. Each subroutine uses a ``suite_name`` and an optional argument, ``group_name``, to call the groups of a specified suite (e.g. ``fast_physics``, ``physics``, ``time_vary``, ``radiation``, ``stochastic``, etc.), or to call the entire suite. For example, ``ufs_ccpp_cap.F90`` would contain module ``ufs_ccpp_cap`` with subroutines ``ccpp_physics_{register, init, physics_init, timestep_init, run, timestep_final, final}``. Interested users should run ``ccpp_capgen.py`` as appropriate for their model and inspect these auto-generated files. .. _AutomaticVariableConversions: Automatic variable conversions ========================== The CCPP framework is capable of performing automatic unit conversions if a mismatch of units between the host model and a physics scheme is detected, provided that the required unit conversion has been implemented. Similarly, the framework can also perform type conversions between host and scheme variables. If a mismatch of units is detected and an automatic unit conversion can be performed, the CCPP capgen script will document this with a log message as in the following example: .. code-block:: console DJS: THERE ARE NO MESSAGES MADE BY CAPGEN WHEN REGISTERING VARIABLE CONVERSION. The CCPP framework is performing only the minimum unit conversions necessary, depending on the intent information of the variable in the :term:`parameterization`\'s metadata table. Below are examples for auto-generated code performing automatic unit conversions from ``m`` to ``um`` or back, depending on the intent of the variable. The conversions are performed in the individual Suite caps, before and after calling the Scheme. .. code-block:: fortran module ccpp_suite_name ... subroutine physics_run(lb, ub, ..., errmsg, errflg) ... real(kind=kind_phys), dimension(lb:ub, levs) :: re_cloud_l real(kind=kind_phys), dimension(lb:ub, levs) :: re_cloudice_l real(kind=kind_dbl), dimension(lb:ub, levs) :: re_cloudsnow_1 ... ! re_cloud is intent(in), re_cloudice is intent(inout), re_cloudsnow has intent(out) and is of type R8. re_cloud_l = 1.0E-6_kind_phys*re_cloud re_cloudice_l = 1.0E-6_kind_phys*re_cloud_ice re_cloudsnow_1 = real(re_cloudsnow, type=R8) call mp_thompson_run(...,re_cloud=re_cloud_l,re_cloudice=re_cloudice_l,re_cloudliq=re_cloudliq_l...,errmsg=errmsg,errflg=errflg) re_cloudice = 1.0E+6_kind_phys* re_cloudice_l re_cloudsnow = real(re_cloudsnow_1,type=kind_phys) If a required unit conversion has not been implemented the CCPP capgen script will generate an error message as follows: .. code-block:: console Variable 'prsl' (standard_name='air_pressure'): host units 'Pa' differ from scheme 'mp_thompson' units 'PaPaPa' but no unit conversion is known; add a conversion to metadata/unit_conversion.py or fix the metadata All automatic unit conversions are implemented in ``ccpp-framework/capgen/metadata/unit_conversion.py``, new unit conversions can be added to this file by following the existing examples. .. _OptionalVariables: Optional Scheme variables ========================== For Scheme's with optional arguments, the CCPP framework generates local pointers in the Group cap. These local pointers are associated within the Group cap, just prior to calling the Scheme. .. code-block:: fortran module ccpp_suite_name use ccpp_suite_name_types, only:real_kind_phys_rank1_ptr_type ... subroutine physics_run(lb, ub, ..., errmsg, errflg) ... type(real_kind_phys_rank1_ptr_type) :: nwfa2d_p ... if ((do_thompson) .and. (ltaerosol .or. mraerosol)) then nwfa2d_p%ptr => nwfa2d(lb:ub) else nullify(nwfa2d_p%ptr) end if ! re_cloud is optional in mp_thompson_run call mp_thompson_run(..., nwfa2d=nwfa2d_p%ptr,...,errmsg=errmsg,errflg=errflg)