! ! This work (Common Community Physics Package), identified by NOAA, NCAR, ! CU/CIRES, is free of known copyright restrictions and is placed in the ! public domain. ! ! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ! !> !! @brief Physics suite infrastructure module. ! module ccpp_suite use, intrinsic :: iso_c_binding, & only: c_ptr, c_null_ptr use :: ccpp_types, & only: ccpp_suite_t use :: ccpp_errors, & only: ccpp_error, ccpp_info, ccpp_debug use :: ccpp_strings, & only: ccpp_cstr use :: ccpp_xml use :: ccpp_scheme, & only: ccpp_scheme_init, ccpp_scheme_finalize, & ccpp_scheme_load, ccpp_scheme_unload implicit none private public :: ccpp_suite_init, & ccpp_suite_finalize, & ccpp_suite_load, & ccpp_suite_unload contains !> !! Suite initialization subroutine. !! !! @param[in] filename The file name of the XML scheme file to load. !! @param[in,out] suite The ccpp_suite_t type to initalize from !! the scheme XML file. !! @param[ out] ierr Integer error flag. ! subroutine ccpp_suite_init(filename, suite, ierr) implicit none character(len=*), intent(in) :: filename type(ccpp_suite_t), intent(inout) :: suite integer, intent( out) :: ierr integer :: i integer :: j integer :: k integer :: l type(c_ptr) :: xml type(c_ptr) :: root type(c_ptr) :: group type(c_ptr) :: subcycle type(c_ptr) :: scheme type(c_ptr), target :: tmp character(len=*), parameter :: err_msg = & 'Please validate the suite xml file: ' ierr = 0 tmp = c_null_ptr call ccpp_debug('Called ccpp_suite_init') ! Load the xml document. ierr = ccpp_xml_load(ccpp_cstr(filename), xml, root) if (ierr /= 0) then call ccpp_error('Unable to load suite from: ' // trim(filename)) return end if ! Parse the suite element call ccpp_xml_parse(root, suite, ierr) if (ierr /= 0) then call ccpp_error(err_msg // trim(filename)) return end if call ccpp_info('Parsing suite ' //trim(suite%name)) ! Find the init subroutine call ccpp_xml_ele_find(root, ccpp_cstr(CCPP_XML_ELE_INIT), tmp, ierr) if (ierr == 0) then ! Get the init subroutine name call ccpp_xml_parse(tmp, suite%library, suite%version, & suite%init, ierr) if (ierr /= 0) then call ccpp_error('Unable to load initialization subroutine') call ccpp_error(err_msg // trim(filename)) return end if ! Do not allow empty init constructs < if (trim(suite%init%name) == '') then call ccpp_error('CCPP does not allow empty ' & // ' XML elements; remove if not used') ierr = 1 return end if ! Initialize the scheme call ccpp_scheme_init(suite%init, ierr) end if ! Find the finalize subroutine call ccpp_xml_ele_find(root, ccpp_cstr(CCPP_XML_ELE_FINALIZE), & tmp, ierr) if (ierr == 0) then ! Get the finalize subroutine name call ccpp_xml_parse(tmp, suite%library, suite%version, & suite%finalize, ierr) if (ierr /= 0) then call ccpp_error('Unable to load finalization subroutine') call ccpp_error(err_msg // trim(filename)) return end if ! Do not allow empty init constructs < if (trim(suite%finalize%name) == '') then call ccpp_error('CCPP does not allow empty ' & // 'XML elements; remove if not used') ierr = 1 return end if ! Initialize the scheme call ccpp_scheme_init(suite%finalize, ierr) if (ierr /= 0) return end if ! Find the first group call ccpp_xml_ele_find(root, CCPP_XML_ELE_GROUP, group, ierr) if (ierr /= 0) then call ccpp_error('Unable to find first group') call ccpp_error(err_msg // trim(filename)) return end if ! Loop over all groups do i=1, suite%groups_max ! Parse the group call ccpp_xml_parse(group, suite%groups_max, suite%groups(i), ierr) if (ierr /= 0) then call ccpp_error(err_msg // trim(filename)) return end if ! Find the first subcycle call ccpp_xml_ele_find(group, CCPP_XML_ELE_SUBCYCLE, subcycle, ierr) if (ierr /= 0) then call ccpp_error('Unable to locate element: ' & // CCPP_XML_ELE_SUBCYCLE) call ccpp_error(err_msg // trim(filename)) return end if ! Loop over all subcycles do j=1, suite%groups(i)%subcycles_max ! Parse the subcycle call ccpp_xml_parse(subcycle, & suite%groups(i)%subcycles_max, & suite%groups(i)%subcycles(j), & ierr) if (ierr /= 0) then call ccpp_error(err_msg // trim(filename)) return end if ! Find the first scheme call ccpp_xml_ele_find(subcycle, CCPP_XML_ELE_SCHEME, & scheme, ierr) ! Loop over all scheme do k=1, suite%groups(i)%subcycles(j)%schemes_max ! Parse the scheme call ccpp_xml_parse(scheme, suite%library, suite%version, & suite%groups(i)%subcycles(j)%schemes(k), & ierr) ! Initialize the scheme call ccpp_scheme_init(suite%groups(i)%subcycles(j)%schemes(k), ierr) if (ierr /= 0) return ! Find the next scheme call ccpp_xml_ele_next(scheme, CCPP_XML_ELE_SCHEME, & scheme, ierr) end do ! Find the next subcycle call ccpp_xml_ele_next(subcycle, CCPP_XML_ELE_SUBCYCLE, & subcycle, ierr) end do ! Find the next group call ccpp_xml_ele_next(group, CCPP_XML_ELE_GROUP, group, ierr) end do #ifdef DEBUG write(6, '(A)') '--------------------------------------------------------------------------------' write(6, '(A)') 'CCPP suite configuration parsed from SDF ' // trim(filename) write(6, '(A)') '--------------------------------------------------------------------------------' write(6, '(*(A))') & '' write(6, '(A, I0)') '[suite%groups_max] = ', suite%groups_max do i=1, suite%groups_max write(6, '(A, A, A)') ' ' write(6, '(A, I0)') ' [suite%groups(i)%subcycles_max] = ', suite%groups(i)%subcycles_max do j=1, suite%groups(i)%subcycles_max write(6, '(A, I0, A)') ' ' write(6, '(A, I0)') ' [suite%groups(i)%subcycles(j)%schemes_max] = ', & suite%groups(i)%subcycles(j)%schemes_max do k=1, suite%groups(i)%subcycles(j)%schemes_max write(6, '(*(A))') & ' ' write(6, '(A, I0)') ' [suite%groups(i)%subcycles(j)%schemes(k)%functions_max] = ', & suite%groups(i)%subcycles(j)%schemes(k)%functions_max do l=1, suite%groups(i)%subcycles(j)%schemes(k)%functions_max write(6, '(*(A))') & ' ', & trim(suite%groups(i)%subcycles(j)%schemes(k)%functions(l)%name), & '' end do write(6, '(A)') ' ' end do write(6, '(A)') ' ' end do write(6, '(A)') ' ' end do write(6, '(A)') '' write(6, '(A)') '--------------------------------------------------------------------------------' #endif ierr = ccpp_xml_unload(xml) call ccpp_suite_load(suite, ierr) end subroutine ccpp_suite_init !> !! Suite finalization subroutine. !! !! @param[in,out] suite The suite_t type to finalize. !! @param[ out] ierr Integer error flag. ! subroutine ccpp_suite_finalize(suite, ierr) type(ccpp_suite_t), intent(inout) :: suite integer, intent( out) :: ierr integer :: i integer :: j integer :: k ierr = 0 call ccpp_debug('Called ccpp_suite_finalize') #ifndef STATIC do i=1, suite%groups_max do j=1, suite%groups(i)%subcycles_max do k=1, suite%groups(i)%subcycles(j)%schemes_max call ccpp_scheme_finalize(suite%groups(i)%subcycles(j)%schemes(k), ierr) if (ierr /= 0) return if (allocated(suite%groups(i)%subcycles(j)%schemes(k)%name)) then deallocate(suite%groups(i)%subcycles(j)%schemes(k)%name) end if if (allocated(suite%groups(i)%subcycles(j)%schemes(k)%library)) & then deallocate(suite%groups(i)%subcycles(j)%schemes(k)%library) end if if (allocated(suite%groups(i)%subcycles(j)%schemes(k)%version)) & then deallocate(suite%groups(i)%subcycles(j)%schemes(k)%version) end if end do if (allocated(suite%groups(i)%subcycles(j)%schemes)) then deallocate(suite%groups(i)%subcycles(j)%schemes) end if end do if (allocated(suite%groups(i)%subcycles)) then deallocate(suite%groups(i)%subcycles) end if end do #endif if (allocated(suite%groups)) then deallocate(suite%groups) end if #ifndef STATIC ! Clean up the init scheme call ccpp_scheme_finalize(suite%init, ierr) if (ierr /=0) return #endif if (allocated(suite%init%name)) then deallocate(suite%init%name) end if if (allocated(suite%init%library)) then deallocate(suite%init%library) end if if (allocated(suite%init%version)) then deallocate(suite%init%version) end if #ifndef STATIC ! Clean up the finalize scheme call ccpp_scheme_finalize(suite%finalize, ierr) if (ierr /=0) return #endif if (allocated(suite%finalize%name)) then deallocate(suite%finalize%name) end if if (allocated(suite%finalize%library)) then deallocate(suite%finalize%library) end if if (allocated(suite%finalize%version)) then deallocate(suite%finalize%version) end if ! Clean up ourself if (allocated(suite%name)) then deallocate(suite%name) end if if (allocated(suite%library)) then deallocate(suite%library) end if if (allocated(suite%version)) then deallocate(suite%version) end if suite%groups_max = 0 end subroutine ccpp_suite_finalize !> !! Suite sub-components loading. !! !! @param[in,out] suite The suite_t type to load all sub-components. !! @param[ out] ierr Integer error flag. ! subroutine ccpp_suite_load(suite, ierr) type(ccpp_suite_t), intent(inout) :: suite integer, intent( out) :: ierr integer :: i integer :: j integer :: k ierr = 0 call ccpp_debug('Called ccpp_suite_load') if (allocated(suite%init%name)) then call ccpp_scheme_load(suite%init, ierr) if (ierr /= 0) return end if if (allocated(suite%finalize%name)) then call ccpp_scheme_load(suite%finalize, ierr) if (ierr /= 0) return end if do i=1, suite%groups_max do j=1, suite%groups(i)%subcycles_max do k=1, suite%groups(i)%subcycles(j)%schemes_max call ccpp_scheme_load(suite%groups(i)%subcycles(j)%schemes(k), ierr) if (ierr /= 0) return end do end do end do end subroutine ccpp_suite_load !> !! Suite unload subroutine. !! !! This loops over all defined schemes to close !! the handle to the scheme library !! !! @param[in,out] cdata The CCPP data of type ccpp_t !! @param[ out] ierr Integer error flag ! subroutine ccpp_suite_unload(suite, ierr) type(ccpp_suite_t), intent(inout) :: suite integer , intent( out) :: ierr integer :: i integer :: j integer :: k ierr = 0 call ccpp_debug('Called ccpp_suite_unload') if (allocated(suite%init%name)) then call ccpp_scheme_unload(suite%init, ierr) if (ierr /= 0) return end if if (allocated(suite%finalize%name)) then call ccpp_scheme_unload(suite%finalize, ierr) if (ierr /= 0) return end if do i=1, suite%groups_max do j=1, suite%groups(i)%subcycles_max do k=1, suite%groups(i)%subcycles(j)%schemes_max call ccpp_scheme_unload(suite%groups(i)%subcycles(j)%schemes(k), ierr) if (ierr /= 0) return end do end do end do end subroutine ccpp_suite_unload end module ccpp_suite