ESMF_CompConstruct Subroutine

public recursive subroutine ESMF_CompConstruct(compp, compType, name, dirPath, configFile, config, clock, petlist, devlist, contextflag, rc)

Arguments

Type IntentOptional Attributes Name
type(ESMF_CompClass), pointer :: compp
type(ESMF_CompType_Flag), intent(in) :: compType
character(len=*), intent(in), optional :: name
character(len=*), intent(in), optional :: dirPath
character(len=*), intent(in), optional :: configFile
type(ESMF_Config), intent(in), optional :: config
type(ESMF_Clock), intent(in), optional :: clock
integer, intent(in), optional :: petlist(:)
integer, intent(in), optional :: devlist(:)
type(ESMF_Context_Flag), intent(in), optional :: contextflag
integer, intent(out), optional :: rc

Source Code

  recursive subroutine ESMF_CompConstruct(compp, compType, name, &
    dirPath, configFile, config, clock, petlist, devlist, contextflag, rc)
!
! !ARGUMENTS:
    type(ESMF_CompClass),     pointer               :: compp
    type(ESMF_CompType_Flag), intent(in)            :: compType
    character(len=*),         intent(in),  optional :: name
    character(len=*),         intent(in),  optional :: dirPath
    character(len=*),         intent(in),  optional :: configFile
    type(ESMF_Config),        intent(in),  optional :: config
    type(ESMF_Clock),         intent(in),  optional :: clock
    integer,                  intent(in),  optional :: petlist(:)
    integer,                  intent(in),  optional :: devlist(:)
    type(ESMF_Context_Flag),  intent(in),  optional :: contextflag
    integer,                  intent(out), optional :: rc 
!
! !DESCRIPTION:
!  Take a new component datatype and fill in the contents.
!
!  The arguments are:
!  \begin{description}
!   \item[compp]
!    Component internal structure to be filled in.
!   \item[compType]
!    Component type, where type is {\tt ESMF\_GRIDCOMP} or {\tt ESMF\_CPLCOMP}.
!   \item[{[name]}]
!    Component name.
!   \item[{[dirPath]}]
!    Directory where component-specfic configuration or data files
!    are located.
!   \item[{[configFile]}]
!    File containing configuration information, either absolute filename
!    or relative to {\tt dirPath}.
!   \item[{[config]}]
!    Already created {\tt config} object.
!   \item[{[clock]}]
!    Private {\tt clock} for this {\tt Component}.
!   \item[{[petlist]}]
!    List of {\tt PET}s for this component. The default is to use all PETs.
!   \item[{[devlist]}]
!    List of {\tt DEV}s for this component. By default no devices are associated.
!   \item[{[contextflag]}]
!    Specify the component's VM context. The default context is
!    {\tt ESMF\_CONTEXT\_OWN\_VM}. See section \ref{const:contextflag} for a
!    complete list of options.
!   \item[{[rc]}] 
!       Return code; equals {\tt ESMF\_SUCCESS} if there are no errors.
!   \end{description}
!
!EOPI
!------------------------------------------------------------------------------
    integer :: localrc                        ! local return code
    integer :: npets, mypet, i, petCount
    integer, pointer :: petlist_loc(:), devlist_loc(:)
    character(len=ESMF_MAXPATHLEN) :: fullpath    ! config file + dirPath
    character(len=ESMF_MAXSTR)     :: msgbuf
    type(ESMF_VM):: vm

    ! Assume not implemented until success
    if (present(rc)) rc = ESMF_RC_NOT_IMPL
    localrc = ESMF_RC_NOT_IMPL

    ! Test incoming compp object
    if (.not.associated(compp)) then
      call ESMF_LogSetError(ESMF_RC_OBJ_BAD, &
        msg="Not a valid pointer to ESMF Component object", &
        ESMF_CONTEXT, rcToReturn=rc)
      return
    endif

    ! Set values for the derived type members
    compp%ftable = ESMF_NULL_POINTER
    compp%base%this = ESMF_NULL_POINTER
    compp%compType = compType
    compp%compTunnel%this = ESMF_NULL_POINTER
    compp%configFile = "uninitialized"
    compp%dirPath = "uninitialized"
    compp%npetlist = 0
    compp%ndevlist = 0
    nullify(compp%compw%compp)
    nullify(compp%petlist)
    nullify(compp%devlist)
    compp%vm_info = ESMF_NULL_POINTER
    compp%vm_cargo = ESMF_NULL_POINTER
    compp%vm_recursionCount = 0
    nullify(compp%is%statep)
    nullify(compp%es%statep)
    compp%vm_released = .false.
    compp%contextflag = ESMF_CONTEXT_OWN_VM
    
    compp%compStatus = ESMF_COMPSTATUS_ALL_NOTPRESENT

    ! parent VM
    call ESMF_VMGetCurrent(vm=compp%vm_parent, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return
    
    ! own VM
    call ESMF_VMSetThis(compp%vm, ESMF_NULL_POINTER, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return
    call ESMF_VMSetInitCreated(compp%vm, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return
 
    ! for config files, store a directory path and subsequent opens can
    ! be relative to this or absolute.
    if (present(dirPath)) then
      compp%dirPath = dirPath
    else
      compp%dirPath = "."
    endif

    ! config handling
    if (present(config)) then
      compp%config = config
      compp%compStatus%configIsPresent = .true.
      if (present(configFile)) then
        ! a config object gets priority over a name if both are specified.
        call ESMF_LogWrite("Ignoring configFile because config object given.", &
          ESMF_LOGMSG_WARNING)
      endif
    else if (present(configFile)) then
      ! name of a specific config file.  open it and store the config object.
      compp%configFile = configFile
      compp%compStatus%configFileIsPresent = .true.
      compp%config = ESMF_ConfigCreate(rc=localrc)
      compp%compStatus%configIsPresent = .true.
      call ESMF_ConfigLoadFile(compp%config, configFile, rc=localrc)
      if (localrc /= ESMF_SUCCESS) then
        ! try again with the dirPath concatinated on front
        fullpath = trim(compp%dirPath) // '/' // trim(configFile)
        call ESMF_ConfigLoadFile(compp%config, fullpath, rc=localrc)
        ! TODO: construct a msg string and then call something here.
        ! if (ESMF_LogFoundError(status, msgstr, rc)) return
        if (localrc /= ESMF_SUCCESS) then
          write(msgbuf, *) &
            "ERROR: loading config file, unable to open either", &
            " name = ", trim(configFile), " or name = ", trim(fullpath)
          call ESMF_LogSetError(ESMF_RC_ARG_VALUE, &
            msg=msgbuf, &
            ESMF_CONTEXT, rcToReturn=rc)
          return
        endif
      endif
    endif

    ! clock
    if (present(clock)) then
      compp%clock = clock
      compp%compStatus%clockIsPresent = .true.
    endif

    ! petlist
    if (present(petlist)) then
      compp%npetlist = size(petlist)
      allocate(petlist_loc(compp%npetlist), stat=localrc)
      if (ESMF_LogFoundAllocError(localrc, msg="local petlist", &
        ESMF_CONTEXT, rcToReturn=rc)) return 
      compp%petlist => petlist_loc
      compp%petlist = petlist     ! copy contents of petlist
    else
      compp%npetlist = 0
      allocate(compp%petlist(1), stat=localrc)
      if (ESMF_LogFoundAllocError(localrc, msg="local petlist", &
        ESMF_CONTEXT, rcToReturn=rc)) return 
    endif

    ! devlist
    if (present(devlist)) then
      compp%ndevlist = size(devlist)
      allocate(devlist_loc(compp%ndevlist), stat=localrc)
      if (ESMF_LogFoundAllocError(localrc, msg="local devlist", &
        ESMF_CONTEXT, rcToReturn=rc)) return 
      compp%devlist => devlist_loc
      compp%devlist = devlist     ! copy contents of devlist
    else
      compp%ndevlist = 0
      allocate(compp%devlist(1), stat=localrc)
      if (ESMF_LogFoundAllocError(localrc, msg="local devlist", &
        ESMF_CONTEXT, rcToReturn=rc)) return 
    endif

    ! check for consistency between contextflag and petlist
    call ESMF_VMGet(vm=compp%vm_parent, localPet=mypet, petCount=npets, &
      rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return
    if (present(contextflag)) then
      if (contextflag==ESMF_CONTEXT_PARENT_VM) then
        if ((compp%npetlist .gt. 0) .and. (compp%npetlist .lt. npets)) then
          ! conflict between contextflag and petlist -> bail out
          deallocate(compp%petlist) ! local garbage collection for bail-on-error
          call ESMF_LogSetError(ESMF_RC_ARG_VALUE, &
            msg="Conflict between contextflag and petlist arguments", &
            ESMF_CONTEXT, rcToReturn=rc) 
          return
        endif
      endif
      compp%contextflag = contextflag
    else
      compp%contextflag = ESMF_CONTEXT_OWN_VM    ! default
    endif
    
    ! check for conflict between petlist and current VM petCount
    if (compp%npetlist .gt. 0) then
      call ESMF_VMGetCurrent(vm, rc=localrc)
      if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
          ESMF_CONTEXT, rcToReturn=rc)) return
      call ESMF_VMGet(vm, petCount=petCount, rc=localrc)
      if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, &
          ESMF_CONTEXT, rcToReturn=rc)) return
      ! see if pets in the petlist are negative or if they exist
      do i=1, compp%npetlist
        if ((compp%petlist(i) .ge. petCount) .or. (compp%petlist(i) .lt. 0)) then
          deallocate(compp%petlist) ! local garbage collection for bail-on-error
          call ESMF_LogSetError(ESMF_RC_ARG_VALUE, &
            msg="Conflict between petlist and global pet count", &
            ESMF_CONTEXT, rcToReturn=rc)
          return
        endif
      enddo
    endif

    ! initialize base class, including component name
    call ESMF_BaseCreate(compp%base, "Component", name, 0, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return

    ! set the participation flag
    compp%iAmParticipant = .false.  ! reset
    if (compp%npetlist .gt. 0) then
      ! see if mypet is in the petlist
      do i=1, compp%npetlist
        if (compp%petlist(i) == mypet) compp%iAmParticipant = .true.  ! set
      enddo
    else
      ! no petlist -> all PETs participate
      compp%iAmParticipant = .true. ! set
    endif

    ! instantiate a default VMPlan
    call ESMF_VMPlanConstruct(vmplan=compp%vmplan, vm=compp%vm_parent, &
      npetlist=compp%npetlist, petlist=compp%petlist, &
      ndevlist=compp%ndevlist, devlist=compp%devlist, &
      contextflag=compp%contextflag, rc=localrc)
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return
                              
    ! initialize the remaining VM members in compp
    compp%vm_info = ESMF_NULL_POINTER
    compp%vm_cargo = ESMF_NULL_POINTER
    compp%vm_released = .false.
                              
    ! Create an empty subroutine/internal state table.
    call c_ESMC_FTableCreate(compp%ftable, localrc) 
    if (ESMF_LogFoundError(localrc, &
      ESMF_ERR_PASSTHRU, &
      ESMF_CONTEXT, rcToReturn=rc)) return
      
    ! create methodTable object
    call c_ESMC_MethodTableCreate(compp%methodTable, localrc)
    if (ESMF_LogFoundError(localrc, &
        ESMF_ERR_PASSTHRU, &
        ESMF_CONTEXT, rcToReturn=rc)) return

    ! Set init code
    ESMF_INIT_SET_CREATED(compp)

    ! Return successfully
    if (present(rc)) rc = ESMF_SUCCESS

  end subroutine ESMF_CompConstruct