!BOP =========================================================================== ! ! !MODULE: clm_mct_mod -- provides a standard API naming convention for MCT code ! ! !DESCRIPTION: ! This module should be used instead of accessing mct modules directly. ! This module: ! \begin{itemize} ! \item Uses Fortran {\sf use} renaming of MCT routines and data types so that they ! all have an mct\_ prefix and related data types and routines have related names. ! \item Provides easy and uniform access to ! all MCT routines and data types that must be accessed. ! \item Provides a convienient list of ! all MCT routines and data types that can be accessed. ! \item Blocks access to MCT routines that are not used in cpl6. ! \end{itemize} ! This module also includes some MCT-only functions to augment ! the MCT library. ! ! !REVISION HISTORY: ! 2001-Aug-14 - B. Kauffman - first prototype ! 2006-Apr-13 - M. Vertenstein - modified for sequential mode ! ! !INTERFACE: ------------------------------------------------------------------ module clm_mct_mod 7,7 ! !USES: use shr_sys_mod ! share system routines use shr_mpi_mod ! mpi layer use shr_const_mod ! constants use shr_kind_mod ,only: R8 => SHR_KIND_R8 use shr_kind_mod ,only: IN => SHR_KIND_IN use shr_kind_mod ,only: CL => SHR_KIND_CL use clm_varctl ,only: iulog use m_MCTWorld ,only: mct_world_init => init use m_AttrVect ,only: mct_aVect => AttrVect use m_AttrVect ,only: mct_aVect_init => init use m_AttrVect ,only: mct_aVect_clean => clean use m_AttrVect ,only: mct_aVect_zero => zero use m_AttrVect ,only: mct_aVect_lsize => lsize use m_AttrVect ,only: mct_aVect_indexIA => indexIA use m_AttrVect ,only: mct_aVect_indexRA => indexRA use m_AttrVect ,only: mct_aVect_getIList => getIList use m_AttrVect ,only: mct_aVect_getRList => getRList use m_AttrVect ,only: mct_aVect_expIListToChar => exportIListToChar use m_AttrVect ,only: mct_aVect_expRListToChar => exportRListToChar use m_AttrVect ,only: mct_aVect_nIAttr => nIAttr use m_AttrVect ,only: mct_aVect_nRAttr => nRAttr use m_AttrVect ,only: mct_aVect_copy => Copy use m_AttrVect ,only: mct_aVect_exportRattr => exportRattr use m_AttrVect ,only: mct_aVect_importRattr => importRattr use m_AttrVect ,only: mct_aVect_exportIattr => exportIattr use m_AttrVect ,only: mct_aVect_importIattr => importIattr use m_AttrVectComms ,only: mct_aVect_scatter => scatter use m_AttrVectComms ,only: mct_aVect_gather => gather use m_AttrVectComms ,only: mct_aVect_bcast => bcast use m_GeneralGrid ,only: mct_gGrid => GeneralGrid use m_GeneralGrid ,only: mct_gGrid_init => init use m_GeneralGrid ,only: mct_gGrid_clean => clean use m_GeneralGrid ,only: mct_gGrid_lsize => lsize use m_GeneralGrid ,only: mct_ggrid_indexIA => indexIA use m_GeneralGrid ,only: mct_gGrid_indexRA => indexRA use m_GeneralGrid ,only: mct_gGrid_exportRattr => exportRattr use m_GeneralGrid ,only: mct_gGrid_importRattr => importRattr use m_GeneralGrid ,only: mct_gGrid_exportIattr => exportIattr use m_GeneralGrid ,only: mct_gGrid_importIattr => importIattr use m_GeneralGridComms ,only: mct_gGrid_scatter => scatter use m_GeneralGridComms ,only: mct_gGrid_gather => gather use m_GeneralGridComms ,only: mct_gGrid_bcast => bcast use m_GlobalSegMap ,only: mct_gsMap => GlobalSegMap use m_GlobalSegMap ,only: mct_gsMap_init => init use m_GlobalSegMap ,only: mct_gsMap_clean => clean use m_GlobalSegMap ,only: mct_gsMap_lsize => lsize use m_GlobalSegMap ,only: mct_gsMap_gsize => gsize use m_GlobalSegMap ,only: mct_gsMap_ngseg => ngseg use m_GlobalSegMap ,only: mct_gsMap_nlseg => nlseg use m_GlobalSegMap ,only: mct_gsMap_OP => OrderedPoints use m_GlobalSegMap ,only: mct_gsMap_pelocs => pelocs use m_Rearranger ,only: mct_rearr => Rearranger use m_Rearranger ,only: mct_rearr_init => init use m_Rearranger ,only: mct_rearr_clean => clean use m_Rearranger ,only: mct_rearr_rearrange => rearrange use m_SparseMatrixToMaps ,only: mct_sMat_2XgsMap => SparseMatrixToXGlobalSegMap use m_SparseMatrixToMaps ,only: mct_sMat_2YgsMap => SparseMatrixToYGlobalSegMap use m_SparseMatrix ,only: mct_sMat => SparseMatrix use m_SparseMatrix ,only: mct_sMat_Init => init use m_SparseMatrix ,only: mct_sMat_Vecinit => vecinit use m_SparseMatrix ,only: mct_sMat_Clean => clean use m_SparseMatrix ,only: mct_sMat_indexIA => indexIA use m_SparseMatrix ,only: mct_sMat_indexRA => indexRA use m_SparseMatrix ,only: mct_sMat_lsize => lsize use m_SparseMatrix ,only: mct_sMat_nrows => nRows use m_SparseMatrix ,only: mct_sMat_ncols => nCols use m_SparseMatrix ,only: mct_sMat_SortPermute => SortPermute use m_SparseMatrix ,only: mct_sMat_GNumEl => GlobalNumElements use m_SparseMatrixComms ,only: mct_sMat_ScatterByRow => ScatterByRow use m_SparseMatrixComms ,only: mct_sMat_ScatterByCol => ScatterByColumn use m_SparseMatrixPlus ,only: mct_sMatP => SparseMatrixPlus use m_SparseMatrixPlus ,only: mct_sMatP_init => init use m_SparseMatrixPlus ,only: mct_sMatP_Vecinit => vecinit use m_MatAttrVectMul ,only: mct_sMat_avMult => sMatAvMult use m_GlobalToLocal ,only: mct_sMat_g2lMat => GlobalToLocalMatrix use m_List ,only: mct_list => list use m_List ,only: mct_list_init => init use m_List ,only: mct_list_get => get use m_List ,only: mct_list_nitem => nitem use m_List ,only: mct_list_clean => clean use m_string ,only: mct_string => string use m_string ,only: mct_string_clean => clean use m_string ,only: mct_string_toChar => toChar use m_die ,only: mct_perr_die => mp_perr_die use m_MergeSorts ,only: mct_indexset => IndexSet use m_MergeSorts ,only: mct_indexsort => IndexSort implicit none !EOP !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ contains !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: mct_aVect_info - print out aVect info for debugging ! ! !DESCRIPTION: ! Print out information about the input MCT {\it AttributeVector} ! {\tt aVect} to stdout. {\tt flag} sets the level of information: ! \begin{enumerate} ! \item print out names of attributes in {\tt aVect}. ! \item also print out local max and min of data in {\tt aVect}. ! \item also print out global max and min of data in {\tt aVect}. ! \item Same as 3 but include name of this routine. ! \end{enumerate} ! If {\tt flag} is 3 or higher, then optional argument {\tt comm} ! must be provided. ! If optional argument {\tt fld} is present, only information for ! that field will be printed. ! If optional argument {\tt istr} is present, it will be output ! before any of the information. ! ! ! !REVISION HISTORY: ! 2003 Jul 01 - B. Kauffman, T. Craig - first version ! ! !INTERFACE: ------------------------------------------------------------------ subroutine mct_aVect_info(flag,aVect,comm,pe,fld,istr),4 ! !USES: ! !INPUT/OUTPUT PARAMETERS: integer(IN) ,intent(in) :: flag ! info level flag type(mct_aVect),intent(in) :: aVect ! Attribute vector integer(IN) ,intent(in),optional :: comm ! MPI communicator integer(IN) ,intent(in),optional :: pe ! processor number character(*) ,intent(in),optional :: fld ! fld character(*) ,intent(in),optional :: istr ! string for print !EOP !--- local --- integer(IN) :: i,j,k,n ! generic indicies integer(IN) :: ks,ke ! start and stop k indices integer(IN) :: nflds ! number of flds in AV to diagnose integer(IN) :: nsize ! grid point size of AV type(mct_string) :: item ! mct string character(CL) :: itemc ! item converted to char integer(IN) :: comm_loc ! local variable for comm integer(IN) :: pe_loc ! local variable for pe logical :: commOK ! is comm available logical :: peOK ! is pe available real(R8),allocatable :: minl(:) ! local min real(R8),allocatable :: ming(:) ! global min real(R8),allocatable :: maxl(:) ! local max real(R8),allocatable :: maxg(:) ! global max !--- formats --- character(*),parameter :: subName = '(mct_aVect_info) ' character(*),parameter :: F00 = "('(mct_aVect_info) ',8a)" character(*),parameter :: F01 = "('(mct_aVect_info) ',a,i9)" character(*),parameter :: F02 = "('(mct_aVect_info) ',240a)" character(*),parameter :: F03 = "('(mct_aVect_info) ',a,2es11.3,i4,2x,a)" !------------------------------------------------------------------------------- ! NOTE: has hard-coded knowledge/assumptions about mct aVect data type internals !------------------------------------------------------------------------------- commOK = .false. peOK = .false. if (present(pe)) then peOK = .true. pe_loc = pe endif if (present(comm)) then commOK = .true. comm_loc = comm if (.not.PEOK) then call shr_mpi_commrank(comm,pe_loc,subName) peOK = .true. endif endif nsize = mct_aVect_lsize(aVect) if (present(fld)) then nflds = 1 ks = mct_aVect_indexRA(aVect,fld,perrWith=subName) ke = ks else nflds = mct_aVect_nRAttr(aVect) ks = 1 ke = nflds endif if (flag >= 1) then if (present(istr)) write(iulog,*) trim(istr) write(iulog,F01) "local size =",nsize if (associated(aVect%iList%bf)) write(iulog,F02) "iList = ",aVect%iList%bf if (associated(aVect%rList%bf)) write(iulog,F02) "rList = ",aVect%rList%bf endif if (flag >= 2) then allocate(minl(nflds)) allocate(maxl(nflds)) do k=ks,ke minl(k) = minval(aVect%rAttr(k,:)) maxl(k) = maxval(aVect%rAttr(k,:)) enddo if (flag >= 4 .and. commOK) then allocate(ming(nflds)) allocate(maxg(nflds)) ming = 0._R8 maxg = 0._R8 call shr_mpi_min(minl,ming,comm,subName) call shr_mpi_max(maxl,maxg,comm,subName) endif do k=ks,ke call mct_aVect_getRList(item,k,aVect) itemc = mct_string_toChar(item) call mct_string_clean(item) write(iulog,F03) 'l min/max ',minl(k),maxl(k),k,trim(itemc) if (flag >= 3 .and. commOK) then if ((peOK .and. pe_loc == 0) .or. .not.peOK) then write(iulog,F03) 'g min/max ',ming(k),maxg(k),k,trim(itemc) endif endif if (flag >= 4 .and. commOK) then if ((peOK .and. pe_loc == 0) .or. .not.peOK) then write(iulog,*) trim(subName),'g min/max ',ming(k),maxg(k),k,trim(itemc) endif endif enddo deallocate(minl) deallocate(maxl) if (flag >= 4 .and. commOK) then deallocate(ming) deallocate(maxg) endif endif #ifndef UNICOSMP call shr_sys_flush(iulog) #endif end subroutine mct_aVect_info !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: mct_aVect_getRAttr - get real F90 array data out of an aVect ! ! !DESCRIPTION: ! Get the data associated with attribute {\tt str} in ! {\it AttributeVector} {\tt aVect} and return in the ! real F90 array data {\tt data}. ! {\tt rcode} will be 0 if succesful, 1 if size of {\tt data} ! does not match size of {\tt aVect} and 2 if {\tt str} is ! not found. ! ! !REMARKS: ! This is like the MCT routine exportRAttr except the output argument ! is not a pointer. ! ! !REVISION HISTORY: ! 2002 Apr xx - B. Kauffman - first version ! ! !INTERFACE: ------------------------------------------------------------------ subroutine mct_aVect_getRAttr(aVect,str,data,rcode) 2 ! !INPUT/OUTPUT PARAMETERS: type(mct_aVect),intent(in) :: aVect ! an Attribute vector character(*) ,intent(in) :: str ! field name string real(R8) ,intent(out) :: data(:) ! an F90 array integer(IN) ,intent(out) :: rcode ! return code !EOP !--- local --- integer(IN) :: k,n,m integer(IN) :: aVsize !--- formats --- character(*),parameter :: subName = "(mct_aVect_getRAttr) " character(*),parameter :: F00 = "('(mct_aVect_getRAttr) ',8a)" !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- rcode = 0 n = mct_aVect_lsize(aVect) m = size(data) if (n /= m) then write(iulog,*) subName,"ERROR: size aV,data,attr = ",n,m,trim(str) data = SHR_CONST_SPVAL rcode = 1 return end if k = mct_aVect_indexRA(aVect,trim(str) ,perrWith=subName) if ( k < 1) then write(iulog,*) subName,"ERROR: attribute not found, var = ",trim(str),", k=",k data = SHR_CONST_SPVAL rcode = 2 return end if data(:) = aVect%rAttr(k,:) end subroutine mct_aVect_getRAttr !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: mct_aVect_putRAttr - put real F90 array data into an aVect ! ! !DESCRIPTION: ! Put the data in array {\tt data} into the {\it AttributeVector} ! {\tt aVect} under the attribute {\tt str}. ! {\tt rcode} will be 0 if succesful, 1 if size of {\tt data} ! does not match size of {\tt aVect} and 2 if {\tt str} is not ! found. ! ! !REMARKS: ! This is like the MCT routine importRAttr except the output argument ! is not a pointer. ! !REVISION HISTORY: ! 2002 Apr xx - B. Kauffman - first version ! ! !INTERFACE: ------------------------------------------------------------------ subroutine mct_aVect_putRAttr(aVect,str,data,rcode) ! !INPUT/OUTPUT PARAMETERS: type(mct_aVect),intent(out) :: aVect ! Attribute vector character(*) ,intent(in) :: str real(R8) ,intent(in) :: data(:) integer(IN) ,intent(out) :: rcode !EOP !--- local --- integer(IN) :: k,n,m integer(IN) :: aVsize !--- formats --- character(*),parameter :: subName = "(mct_aVect_putRAttr) " character(*),parameter :: F00 = "('(mct_aVect_putRAttr) ',8a)" !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- rcode = 0 n = mct_aVect_lsize(aVect) m = size(data) if (n /= m) then write(iulog,*) subName,"ERROR: size aV,data,attr = ",n,m,trim(str) rcode = 1 return end if k = mct_aVect_indexRA(aVect,trim(str) ,perrWith=subName) if ( k < 1) then write(iulog,*) subName,"ERROR: attribute not found, var = ",trim(str),", k=",k rcode = 2 return end if aVect%rAttr(k,:) = data(:) end subroutine mct_aVect_putRAttr !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: mct_aVect_accum - accumulate attributes from one aVect to another ! ! !DESCRIPTION: ! This routine accumulates from input argment {\tt aVin} into the output ! {\it AttrVect} argument {\tt aVout} the real and integer attributes specified in ! input {\tt CHARACTER} argument {\tt iList} and {\tt rList}. The attributes can ! be listed in any order. If neither {\tt iList} nor {\tt rList} are provided, ! all attributes shared between {\tt aVin} and {\tt aVout} will be copied. ! ! If any attributes in {\tt aVout} have different names but represent the ! the same quantity and should still be copied, you must provide a translation ! argument {\tt TrList} and/or {\tt TiList}. The translation arguments should ! be identical to the {\tt rList} or {\tt iList} but with the correct {\tt aVout} ! name subsititued at the appropriate place. ! ! {\bf N.B.:} This routine will fail if the {\tt aVout} is not initialized or ! if any of the specified attributes are not present in either {\tt aVout} or {\tt aVin}. ! ! !REVISION HISTORY: ! 2002 Sep 15 - ? - initial version. ! ! !INTERFACE: ------------------------------------------------------------------ subroutine mct_aVect_accum(aVin, rList, TrList, iList, TiList, aVout) 3 ! !USES: use m_die , only : die use m_stdio , only : stderr use m_String , only : String_toChar => toChar use m_String , only : String use m_String , only : String_init use m_String , only : String_clean => clean use m_List , only : List use m_List, only : List_get => get use m_List, only : List_nullify => nullify use m_List, only : List_clean => clean use m_List, only : init,nitem use m_AttrVect, only : AttrVect use m_AttrVect, only : lsize use m_AttrVect, only : SharedAttrIndexList implicit none !INPUT/OUTPUT PARAMETERS type(AttrVect) ,intent(in) :: aVin character(*), optional,intent(in) :: iList character(*), optional,intent(in) :: rList character(*), optional,intent(in) :: TiList character(*), optional,intent(in) :: TrList type(AttrVect) ,intent(inout) :: aVout !EOP !--- local --- type(List) :: rcpList ! The list of real attributes to accum type(List) :: icpList ! The list of integer attributes to accum type(List) :: TrcpList ! Names of output attributes corresponding to input type(List) :: TicpList ! Names of output attributes corresponding to input type(String) :: attr ! an individual attribute type(String) :: attr2 ! an individual attribute integer(IN) :: i,j ! generic indicies integer(IN) :: rcode ! return code integer(IN) :: inx,outx integer(IN) :: num_indices ! Overlapping attribute index number !--- Overlapping attribute index storage arrays: --- integer(IN), dimension(:), pointer :: aVinindices, aVoutindices character(7) :: data_flag ! character variable used as data type flag !--- formats --- character(*),parameter :: myname_='mct_accum' !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- call List_nullify(rcpList) call List_nullify(icpList) call List_nullify(TrcpList) call List_nullify(TicpList) if (lsize(aVin) .ne. lsize(aVout)) then write(stderr,'(2a)')myname_, & 'MCTERROR: Input aV and output aV do not have the same size' write(stderr,*)myname_, & 'MCTERROR: ',lsize(aVin),lsize(aVout) call die(myname_,'lsize check',rcode) endif !---------------------------------------------------------------------------- ! Accum the listed real attributes !---------------------------------------------------------------------------- if ( present(rList)) then if( len_trim(rList)>0 ) then call init(rcpList,rList) ! init.List() !--- check translation list --- if ( present(TrList) ) then if(len_trim(TrList)>0 ) then call init(TrcpList,TrList) if ( nitem(rcpList) .ne. nitem(TrcpList)) then write(stderr,'(2a)')myname_, & 'MCTERROR: Input rList and TrList do not have the same size' call die(myname_,'nitem TrList check',rcode) endif endif endif if (nitem(rcpList) .ge. 1) then do i=1,lsize(aVin) do j=1,nitem(rcpList) call List_get(attr,j,rcpList) if (present(TrList)) then call List_get(attr2,j,TrcpList) else call String_init(attr2,attr) endif inx=mct_aVect_indexRA(aVin,String_toChar(attr),dieWith=myname_//'real aVin') outx=mct_aVect_indexRA(aVout,String_toChar(attr2),dieWith=myname_//'real aVout') aVout%rAttr(outx,i)=aVout%rAttr(outx,i)+aVin%rAttr(inx,i) call String_clean(attr) call String_clean(attr2) enddo enddo endif call List_clean(rcpList) if (present(TrList)) call List_clean(TrcpList) endif endif !---------------------------------------------------------------------------- ! Accum the listed integer attributes !---------------------------------------------------------------------------- if ( present(iList) ) then if (len_trim(iList)>0 ) then call init(icpList,iList) ! init.List() !--- check translation list --- if ( present(TiList) ) then if (len_trim(TiList)>0 ) then call init(TicpList,TiList) if ( nitem(icpList) .ne. nitem(TicpList)) then write(stderr,'(2a)')myname_, & 'MCTERROR: Input iList and TiList do not have the same size' call die(myname_,'nitem TiList check',rcode) endif endif endif if (nitem(icpList) .ge. 1) then do i=1,lsize(aVin) do j=1,nitem(icpList) call List_get(attr,j,icpList) if (present(TiList)) then call List_get(attr2,j,TicpList) else call String_init(attr2,attr) endif inx =mct_aVect_indexIA(aVin ,String_toChar(attr) ,dieWith=myname_//'int aVin') outx=mct_aVect_indexIA(aVout,String_toChar(attr2),dieWith=myname_//'int aVout') aVout%iAttr(outx,i)=aVout%iAttr(outx,i)+aVin%iAttr(inx,i) call String_clean(attr) call String_clean(attr2) enddo enddo endif call List_clean(icpList) if (present(TrList)) call List_clean(TicpList) endif endif !---------------------------------------------------------------------------- ! if neither rList nor iList is present, accum shared attibutes from in to out !---------------------------------------------------------------------------- if ( .not.present(rList) .and. .not.present(iList)) then data_flag = 'REAL' call SharedAttrIndexList(aVin, aVout, data_flag, num_indices, & aVinindices, aVoutindices) if (num_indices .gt. 0) then #ifdef CPP_VECTOR do j=1,num_indices !CDIR SELECT(VECTOR) !DIR$ CONCURRENT do i=1,lsize(aVin) #else do i=1,lsize(aVin) do j=1,num_indices #endif aVout%rAttr(aVoutindices(j),i)= & & aVout%rAttr(aVoutindices(j),i)+aVin%rAttr(aVinindices(j),i) enddo enddo endif deallocate(aVinindices, aVoutindices,stat=rcode) if (rcode /= 0) call die(myname_,'deallocate real(Vinindices...',rcode) data_flag = 'INTEGER' call SharedAttrIndexList(aVin, aVout, data_flag, num_indices, & aVinindices, aVoutindices) if (num_indices .gt. 0) then #ifdef CPP_VECTOR do j=1,num_indices !CDIR SELECT(VECTOR) !DIR$ CONCURRENT do i=1,lsize(aVin) #else do i=1,lsize(aVin) do j=1,num_indices #endif aVout%iAttr(aVoutindices(j),i)= & & aVout%iAttr(aVoutindices(j),i)+aVin%iAttr(aVinindices(j),i) enddo enddo endif deallocate(aVinindices, aVoutindices,stat=rcode) if (rcode /= 0) call die(myname_,'deallocate int(Vinindices...',rcode) endif end subroutine mct_aVect_accum !=============================================================================== end module clm_mct_mod