!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !----------------------------------------------------------------------- ! CVS m_AttrVect.F90,v 1.86 2012-04-27 20:01:04 jacob Exp ! CVS MCT_2_8_0 !BOP ------------------------------------------------------------------- ! ! !MODULE: m_AttrVect - Multi-field Storage ! ! !DESCRIPTION: ! ! An {\em attribute vector} is a scheme for storing bundles of integer ! and real data vectors, indexed by the names of the fields stored in ! {\tt List} format (see the mpeu module {\tt m\_List} for more ! information about the {\tt List} datatype). The ordering of the ! fieldnames in the integer and real attribute {\tt List} components ! ({\tt AttrVect\%iList} and {\tt AttrVect\%rList}, respectively) ! corresponds to the storage order of the attributes in their respective ! data buffers (the components {\tt AttrVect\%iAttr(:,:)} and ! {\tt AttrVect\%rAttr(:,:)}, respectively). The organization of ! the fieldnames in {\tt List} format, along with the direct mapping ! between {\tt List} items and locations in the data buffer, allows ! the user to have {\em random access} to the field data. This ! approach also allows the user to set the number and the names of fields ! stored in an {\tt AttrVect} at run-time. ! ! The {\tt AttrVect} stores field data in a {\em pointwise} fashion ! (that is, the data are grouped so that all the integer or real data ! associated with an individual point are adjacent to each other in memory. ! This amounts to the having the integer and real field data arrays in ! the {\tt AttrVect} (the components {\tt AttrVect\%iAttr(:,:)} and ! {\tt AttrVect\%rAttr(:,:)}, respectively) having the attribute index ! as the major (or fastest-varying) index. A prime example of this is ! observational data input to a data assimilation system. In the Model ! Coupling Toolkit, this datatype is the fundamental type for storing ! field data exchanged by component models, and forms a basis for other ! MCT datatypes that encapsulate time accumulation/averaging buffers (the ! {\tt Accumulator} datatype defined in the module {\tt m\_Accumulator}), ! coordinate grid information (the {\tt GeneralGrid} datatype defined in ! the module {\tt m\_GeneralGrid}), and sparse interpolation matrices ! (the {\tt SparseMatrix} datatype defined in the module ! {\tt m\_SparseMatrix}). ! ! The attribute vector is implemented in Fortran 90 using the ! {\tt AttrVect} derived type. This module contains the definition ! of the {\tt AttrVect}, and the numerous methods that service it. There ! are a number of initialization (creation) schemes, and a routine for ! zeroing out the elements of an {\tt AttrVect}. There is a method ! to {\em clean} up allocated memory used by an {\tt AttrVect} ! (destruction). There are numerous query methods that return: the ! number of datapoints (or {\em length}; the numbers of integer and ! real attributes; the data buffer index of a given real or integer ! attribute; and return the lists of real and integer attributes. There ! also exist methods for exporting a given attribute as a one-dimensional ! array and importing a given attribute from a one-dimensional array. ! There is a method for copying attributes from one {\tt AttrVect} to ! another. There is also a method for cross-indexing the attributes in ! two {\tt AttrVect} variables. In addition, there are methods that ! return those cross-indexed attributes along with some auxiliary data ! in a {\tt AVSharedIndicesOneType} or {\tt AVSharedIndices} structure. ! Finally, there are methods for sorting and permuting {\tt AttrVect} ! entries using a MergeSort scheme keyed by the attributes of the {\tt ! AttrVect}. ! ! !INTERFACE: module m_AttrVect ! ! !USES: ! use m_realkinds,only : SP,DP,FP ! Real types definitions use m_List, only : List ! Support for rList and iList components. implicit none private ! except ! !PUBLIC TYPES: public :: AttrVect ! The class data structure public :: AVSharedIndicesOneType ! Data structure recording shared indices between ! two attribute vectors, for a single data type ! (e.g., shared real attributes) public :: AVSharedIndices ! Data structure recording shared indices between two ! attribute vectors, for all data types type AttrVect #ifdef SEQUENCE sequence #endif type(List) :: iList type(List) :: rList integer,dimension(:,:),pointer :: iAttr real(FP) ,dimension(:,:),pointer :: rAttr end type AttrVect type AVSharedIndicesOneType integer :: num_indices ! number of shared items logical :: contiguous ! true if index segments are contiguous in memory character*7 :: data_flag ! data type flag (e.g., 'REAL' or 'INTEGER') ! arrays of indices to storage locations of shared attributes between the two ! attribute vectors: integer, dimension(:), pointer :: aVindices1 integer, dimension(:), pointer :: aVindices2 end type AVSharedIndicesOneType type AVSharedIndices type(AVSharedIndicesOneType) :: shared_real ! shared indices of type REAL type(AVSharedIndicesOneType) :: shared_integer ! shared indices of type INTEGER end type AVSharedIndices ! !PUBLIC MEMBER FUNCTIONS: public :: init ! create a local vector public :: clean ! clean the local vector public :: zero ! zero the local vector public :: lsize ! size of the local vector public :: nIAttr ! number of integer attributes on local public :: nRAttr ! number of real attributes on local public :: indexIA ! index the integer attributes public :: indexRA ! index the real attributes public :: getIList ! return list of integer attributes public :: getRList ! return list of real attributes public :: exportIList ! export INTEGER attibute List public :: exportRList ! export REAL attibute List public :: exportIListToChar ! export INTEGER attibute List as Char public :: exportRListToChar ! export REAL attibute List as Char public :: appendIAttr ! append INTEGER attribute List public :: appendRAttr ! append REAL attribute List public :: exportIAttr ! export INTEGER attribute to vector public :: exportRAttr ! export REAL attribute to vector public :: importIAttr ! import INTEGER attribute from vector public :: importRAttr ! import REAL attribute from vector public :: Copy ! copy attributes from one Av to another public :: RCopy ! copy real attributes from one Av to another public :: ICopy ! copy integer attributes from one Av to another public :: Sort ! sort entries, and return permutation public :: Permute ! permute entries public :: Unpermute ! Unpermute entries public :: SortPermute ! sort and permute entries public :: SharedAttrIndexList ! Cross-indices of shared ! attributes of two AttrVects public :: SharedIndices ! Given two AttrVects, create an AVSharedIndices structure public :: SharedIndicesOneType ! Given two AttrVects, create an ! AVSharedIndicesOneType structure for a single type public :: cleanSharedIndices ! clean a AVSharedIndices structure public :: cleanSharedIndicesOneType ! clean a AVSharedIndicesOneType structure interface init ; module procedure & init_, & initv_, & initl_ end interface interface clean ; module procedure clean_ ; end interface interface zero ; module procedure zero_ ; end interface interface lsize ; module procedure lsize_ ; end interface interface nIAttr ; module procedure nIAttr_ ; end interface interface nRAttr ; module procedure nRAttr_ ; end interface interface indexIA; module procedure indexIA_; end interface interface indexRA; module procedure indexRA_; end interface interface getIList; module procedure getIList_; end interface interface getRList; module procedure getRList_; end interface interface exportIList; module procedure exportIList_; end interface interface exportRList; module procedure exportRList_; end interface interface exportIListToChar module procedure exportIListToChar_ end interface interface exportRListToChar module procedure exportRListToChar_ end interface interface appendIAttr ; module procedure appendIAttr_ ; end interface interface appendRAttr ; module procedure appendRAttr_ ; end interface interface exportIAttr; module procedure exportIAttr_; end interface interface exportRAttr; module procedure & exportRAttrSP_, & exportRAttrDP_ end interface interface importIAttr; module procedure importIAttr_; end interface interface importRAttr; module procedure & importRAttrSP_, & importRAttrDP_ end interface interface Copy ; module procedure Copy_ ; end interface interface RCopy ; module procedure & RCopy_, & RCopyL_ end interface interface ICopy ; module procedure & ICopy_, & ICopyL_ end interface interface Sort ; module procedure Sort_ ; end interface interface Permute ; module procedure Permute_ ; end interface interface Unpermute ; module procedure Unpermute_ ; end interface interface SortPermute ; module procedure SortPermute_ ; end interface interface SharedAttrIndexList ; module procedure & aVaVSharedAttrIndexList_ end interface interface SharedIndices ; module procedure SharedIndices_ ; end interface interface SharedIndicesOneType ; module procedure SharedIndicesOneType_ ; end interface interface cleanSharedIndices ; module procedure cleanSharedIndices_ ; end interface interface cleanSharedIndicesOneType ; module procedure cleanSharedIndicesOneType_ ; end interface ! !REVISION HISTORY: ! 10Apr98 - Jing Guo - initial prototype/prolog/code ! 10Oct00 - J.W. Larson - made getIList ! and getRList functions public and added appropriate ! interface definitions ! 20Oct00 - J.W. Larson - added Sort, ! Permute, and SortPermute functions. ! 09May01 - J.W. Larson - added initl_(). ! 19Oct01 - J.W. Larson - added routines ! exportIattr(), exportRAttr(), importIAttr(), ! and importRAttr(). Also cleaned up module and ! routine prologues. ! 13Dec01 - J.W. Larson - made importIAttr() ! and importRAttr() public (bug fix). ! 14Dec01 - J.W. Larson - added exportIList() ! and exportRList(). ! 14Feb02 - J.W. Larson - added CHARCTER ! functions exportIListToChar() and exportRListToChar() ! 26Feb02 - J.W. Larson - corrected of usage ! of m_die routines throughout this module. ! 16Apr02 - J.W. Larson - added the method ! LocalReduce(), and the public data members AttrVectSUM, ! AttrVectMIN, and AttrVectMAX. ! 7May02 - J.W. Larson - Refactoring. Moved ! LocalReduce() and the public data members AttrVectSUM, ! AttrVectMIN, and AttrVectMAX to a new module named ! m_AttrVectReduce. ! 12Jun02 - R.L. Jacob - add Copy function ! 13Jun02 - R.L. Jacob - move aVavSharedAttrIndexList ! to this module from old m_SharedAttrIndicies ! 28Apr11 - W.J. Sacks - added AVSharedIndices and ! AVSharedIndicesOneType derived types, and associated ! subroutines ! 10Apr12 - W.J. Sacks - modified AVSharedIndices code ! to be Fortran-90 compliant !EOP ___________________________________________________________________ character(len=*),parameter :: myname='MCT::m_AttrVect' contains !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: init_ - Initialize an AttrVect Given Attribute Lists and Length ! ! !DESCRIPTION: ! This routine creates an {\tt AttrVect} (the output argument {\tt aV}) ! using the optional input {\tt CHARACTER} arguments {\tt iList}, and ! {\tt rList} to define its integer and real attributes, respectively. ! The optional input {\tt INTEGER} argument {\tt lsize} defines the ! number of points for which we are storing attributes, or the ! {\em length} of {\tt aV}. The expected form for the arguments ! {\tt iList} and {\tt rList} are colon-delimited strings where each ! substring defines an attribute. Suppose we wish to store {\tt N} ! observations that have the real attributes {\tt 'latitude'}, ! {\tt 'longitude'}, {\tt pressure}, {\tt 'u-wind'}, and ! {\tt 'v-wind'}. Suppose we also wish to store the integer ! attributes {\tt 'hour'}, {\tt 'day'}, {\tt 'month'}, {\tt 'year'}, ! and {\tt 'data source'}. This can be accomplished by invoking ! {\tt init\_()} as follows: ! \begin{verbatim} ! call init_(aV, 'hour:day:month:year:data source', & ! 'latitude:longitude:pressure:u-wind:v-wind', N) ! \end{verbatim} ! The resulting {\tt AttrVect} {\tt aV} will have five integer ! attributes, five real attributes, and length {\tt N}. ! ! !INTERFACE: subroutine init_(aV, iList, rList, lsize) ! ! !USES: ! use m_List, only : List use m_List, only : init,nitem use m_List, only : List_nullify => nullify use m_mall use m_die implicit none ! !INPUT PARAMETERS: ! character(len=*), optional, intent(in) :: iList character(len=*), optional, intent(in) :: rList integer, optional, intent(in) :: lsize ! !OUTPUT PARAMETERS: ! type(AttrVect), intent(out) :: aV ! !REVISION HISTORY: ! 09Apr98 - Jing Guo - initial prototype/prolog/code ! 09Oct01 - J.W. Larson - added feature to ! nullify all pointers before usage. This was done to ! accomodate behavior of the f90 ASSOCIATED intrinsic ! function on the AIX platform. ! 07Dec01 - E.T. Ong - added support for ! intialization with blank character strings for iList ! and rList !EOP ___________________________________________________________________ ! character(len=*),parameter :: myname_=myname//'::init_' integer :: nIA,nRA,n,ier ! Initially, nullify all pointers in the AttrVect aV: nullify(aV%iAttr) nullify(aV%rAttr) call List_nullify(aV%iList) call List_nullify(aV%rList) if(present(rList)) then if(len_trim(rList) > 0) then call init(aV%rList,rList) ! init.List() endif endif if(present(iList)) then if(len_trim(iList) > 0) then call init(aV%iList,iList) ! init.List() endif endif nIA=nitem(aV%iList) ! nitem.List() nRA=nitem(aV%rList) ! nitem.List() n=0 if(present(lsize)) n=lsize allocate( aV%iAttr(nIA,n),aV%rAttr(nRA,n), stat=ier) if(ier /= 0) call die(myname_,'allocate()',ier) #ifdef MALL_ON call mall_ci(size(transfer(aV%iAttr,(/1/)),myname_) call mall_ci(size(transfer(aV%rAttr,(/1/)),myname_) #endif end subroutine init_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: initv_ - Initialize One AttrVect from Another ! ! !DESCRIPTION: This routine takes an input {\tt AttrVect} argument ! {\tt bV}, and uses its attribute list information to create an output ! {\tt AttrVect} variable {\tt aV}. The length of {\tt aV} is defined ! by the input {\tt INTEGER} argument {\tt lsize}. ! ! !INTERFACE: subroutine initv_(aV, bV, lsize) ! ! !USES: ! use m_String, only : String,char use m_String, only : String_clean => clean use m_List, only : get use m_List, only : List_nullify => nullify use m_die use m_stdio implicit none ! !INPUT PARAMETERS: ! type(AttrVect),intent(in) :: bV integer, intent(in) :: lsize ! !OUTPUT PARAMETERS: ! type(AttrVect),intent(out) :: aV ! !REVISION HISTORY: ! 22Apr98 - Jing Guo - initial prototype/prolog/code ! 17May01 - R. Jacob - add a check to see if ! input argument has been defined. SGI will dump ! core if its not. ! 10Oct01 - J. Larson - Nullify all pointers ! in ouput AttrVect aV before initializing aV. ! 19Sep08 - J. Wolfe - plug memory leak from not deallocating ! strings. !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::initv_' type(String) :: iLStr,rLStr ! Step One: Nullify all pointers in aV. We will set ! only the pointers we really need for aV based on those ! currently ASSOCIATED in bV. call List_nullify(aV%iList) call List_nullify(aV%rList) nullify(aV%iAttr) nullify(aV%rAttr) ! Convert the two Lists to two Strings if(.not.associated(bv%iList%bf) .and. & .not.associated(bv%rList%bf)) then write(stderr,'(2a)')myname_, & 'MCTERROR: Trying to initialize a new AttrVect off an undefined AttrVect' call die(myname_,'undefined input argument',0) endif if(associated(bv%iList%bf)) then call get(iLStr,bv%iList) endif if(associated(bv%rList%bf)) then call get(rLStr,bv%rList) endif ! Initialize the AttrVect aV depending on which parts of ! the input bV are valid: if(associated(bv%iList%bf) .and. associated(bv%rList%bf)) then call init_(aV,iList=char(iLStr),rList=char(rLStr),lsize=lsize) endif if(.not.associated(bv%iList%bf) .and. associated(bv%rList%bf)) then call init_(aV,rList=char(rLStr),lsize=lsize) endif if(associated(bv%iList%bf) .and. .not.associated(bv%rList%bf)) then call init_(aV,iList=char(iLStr),lsize=lsize) endif if(associated(bv%iList%bf)) then call String_clean(iLStr) endif if(associated(bv%rList%bf)) then call String_clean(rLStr) endif end subroutine initv_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: initl_ - Initialize an AttrVect Using the List Type ! ! !DESCRIPTION: This routine initializes an {\tt AttrVect} directly ! from input {\tt List} data type arguments {\tt iList} and {\tt rList} ! (see the module {\tt m\_List} in mpeu for further details), and an ! input length {\tt lsize}. The resulting {\tt AttrVect} is returned in ! the argument {\tt aV}. ! ! {\bf N.B.}: If the user supplies an empty list for the arguments ! {\tt iList} ({\tt rList}), then {\tt aV} will be created only with ! {\tt REAL} ({\tt INTEGER}) attributes. If both arguments {\tt iList} ! and {\tt rList} are empty, the routine will terminate execution and ! report an error. ! ! {\bf N.B.}: The outcome of this routine, {\tt aV} represents ! allocated memory. When this {\tt AttrVect} is no longer needed, ! it must be deallocated by invoking the routine {\tt AttrVect\_clean()}. ! Failure to do so will spawn a memory leak. ! ! !INTERFACE: subroutine initl_(aV, iList, rList, lsize) ! ! !USES: ! use m_die use m_stdio use m_String, only : String use m_String, only : String_clean => clean use m_String, only : String_toChar => toChar use m_List, only : List use m_List, only : List_nitem => nitem use m_List, only : List_exportToChar => exportToChar implicit none ! !INPUT PARAMETERS: ! type(List), intent(in) :: iList type(List), intent(in) :: rList integer, intent(in) :: lsize ! !OUTPUT PARAMETERS: ! type(AttrVect), intent(out) :: aV ! !REVISION HISTORY: ! 09May98 - J.W. Larson - initial version. ! 08Aug01 - E.T. Ong - change list assignment(=) ! to list copy to avoid compiler errors with pgf90. ! 10Oct01 - J. Larson - Nullify all pointers ! in ouput AttrVect aV before initializing aV. Also, ! greater caution taken regarding validity of input ! arguments iList and rList. ! 15May08 - J. Larson - Simplify to use ! the init_ routine. Better argument checking. !EOP ___________________________________________________________________ ! character(len=*),parameter :: myname_=myname//'::initl_' ! Basic argument sanity checks: if (List_nitem(iList) < 0) then write(stderr,'(2a,i8,a)') myname_, & ':: FATAL: List argument iList has a negative number ( ',List_nitem(iList), & ' ) of attributes!' call die(myname_) endif if (List_nitem(rList) < 0) then write(stderr,'(2a,i8,a)') myname_, & ':: FATAL: List argument rList has a negative number ( ',List_nitem(rList), & ' ) of attributes!' call die(myname_) endif if ((List_nitem(iList) > 0) .and. (List_nitem(rList) > 0)) then call init_(aV, List_exportToChar(iList), List_exportToChar(rList), lsize) else ! Then solely REAL or solely INTEGER attributes: if (List_nitem(iList) > 0) then ! solely INTEGER attributes call init_(aV, iList=List_exportToChar(iList), lsize=lsize) endif ! if (List_nitem(iList) > 0) then... if (List_nitem(rList) > 0) then ! solely REAL attributes call init_(aV, rList=List_exportToChar(rList), lsize=lsize) endif ! if (List_nitem(rList) > 0) then... endif ! if ((List_nitem(iList) > 0) .and. (List_nitem(rList) > 0)) then... end subroutine initl_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: clean_ - Deallocate Allocated Memory Structures of an AttrVect ! ! !DESCRIPTION: ! This routine deallocates the allocated memory structures of the ! input/output {\tt AttrVect} argument {\tt aV}. This amounts to ! cleaning the {\tt List} structures {\tt aV\%iList} and {\tt av\%rList}, ! and deallocating the arrays {\tt aV\%iAttr(:,:)} and ! {\tt aV\%rAttr(:,:)}. The success (failure) of this operation is ! signified by a zero (non-zero) value of the optional {\tt INTEGER} ! output argument {\tt stat}. If {\tt clean\_()} is invoked without ! supplying {\tt stat}, and any of the deallocation operations fail, ! the routine will terminate with an error message. ! ! !INTERFACE: subroutine clean_(aV, stat) ! ! !USES: ! use m_mall use m_stdio use m_die use m_List, only : List_clean => clean implicit none ! !INPUT/OUTPUT PARAMETERS: ! type(AttrVect), intent(inout) :: aV ! !OUTPUT PARAMETERS: ! integer, optional, intent(out) :: stat ! !REVISION HISTORY: ! 09Apr98 - Jing Guo - initial prototype/prolog/code ! 10Oct01 - J. Larson - various fixes to ! prevent deallocation of UNASSOCIATED pointers. ! 01Mar01 - E.T. Ong - removed dies to prevent ! crashes when cleaning uninitialized attrvects. Added ! optional stat argument. !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::clean_' integer :: ier ! Note that an undefined pointer may either crash the process ! or return either .true. or .false. to the associated() test. ! One should therefore avoid using the function on an ! undefined pointer. ! Clean up INTEGER attribute list: if(present(stat)) stat=0 if(associated(aV%iList%bf)) then if(present(stat)) then call List_clean(aV%iList,ier) if(ier/=0) stat=ier else call List_clean(aV%iList) endif endif ! Clean up REAL attribute list: if(associated(aV%rList%bf)) then if(present(stat)) then call List_clean(aV%rList,ier) if(ier/=0) stat=ier else call List_clean(aV%rList) endif endif ! Clean up INTEGER attributes: if(associated(aV%iAttr)) then #ifdef MALL_ON call mall_co(size(transfer(aV%iAttr,(/1/)),myname_) #endif deallocate(aV%iAttr,stat=ier) if(ier /= 0) then if(present(stat)) then stat=ier else call warn(myname_,'deallocate(aV%iAttr)',ier) endif endif endif ! if(associated(aV%iAttr))... ! Clean up REAL attributes: if(associated(aV%rAttr)) then #ifdef MALL_ON call mall_co(size(transfer(aV%rAttr,(/1/)),myname_) #endif deallocate(aV%rAttr,stat=ier) if(ier /= 0) then if(present(stat)) then stat=ier else call warn(myname_,'deallocate(aV%rAttr)',ier) endif endif endif ! if(associated(aV%rAttr))... end subroutine clean_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: lsize_ - Length of an AttrVect ! ! !DESCRIPTION: ! This function returns the number of elements, or {\em length} of the ! input {\tt AttrVect} argument {\tt aV}. This function examines the ! length of the second dimension of the arrays {\tt aV\%iAttr(:,:)} ! and {\tt aV\%rAttr(:,:)}. If neither {\tt aV\%iAttr(:,:)} nor ! {\tt aV\%rAttr(:,:)} are associated, then ${\tt lsize\_(aV)} = 0$. ! If {\tt aV\%iAttr(:,:)} is associated, but {\tt aV\%rAttr(:,:)} is ! not, then ${\tt lsize\_(aV)} = {\tt size(aV\%iAttr,2)}$. If ! {\tt aV\%iAttr(:,:)} is not associated, but {\tt aV\%rAttr(:,:)} is, ! then ${\tt lsize\_(aV)} = {\tt size(aV\%rAttr,2)}$. If both ! {\tt aV\%iAttr(:,:)} and {\tt aV\%rAttr(:,:)} are associated, the ! function {\tt lsize\_()} will do one of two things: If ! ${\tt size(aV\%iAttr,2)} = {\tt size(aV\%rAttr,2)}$, this equal value ! will be returned. If ${\tt size(aV\%iAttr,2)} \neq ! {\tt size(aV\%rAttr,2)}$, termination with an error message will occur. ! ! !INTERFACE: integer function lsize_(aV) ! !USES: use m_List, only : List use m_List, only : List_allocated => allocated use m_stdio, only : stderr use m_die implicit none ! !INPUT PARAMETERS: ! type(AttrVect), intent(in) :: aV ! !REVISION HISTORY: ! 09Apr98 - Jing Guo - initial prototype/prolog/code ! 10Oct01 - J. Larson - made code more robust ! to handle cases where the length of either aV%iAttr or ! aV%rAttr is zero, but the other is positive. !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::lsize_' integer :: iLength, rLength ! One should try to avoid using this function on an undefined ! or disassocated pointer. However, it is understandable ! that an undefined or disassocated pointer has a size 0, if ! the associated() test sucesses. lsize_=0 if(List_allocated(aV%iList) .and. associated(aV%iAttr)) then iLength = size(aV%iAttr,2) else iLength = 0 endif if(List_allocated(aV%rList) .and. associated(aV%rAttr)) then rLength = size(aV%rAttr,2) else rLength = 0 endif if(iLength /= rLength) then if((rLength > 0) .and. (iLength > 0)) then call die(myname_,'attribute array length mismatch', & iLength-rLength) endif if((rLength > 0) .and. (iLength == 0)) then lsize_ = rLength endif if((iLength > 0) .and. (rLength == 0)) then lsize_ = iLength endif endif if(iLength == rLength) lsize_ = iLength end function lsize_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory !BOP ------------------------------------------------------------------- ! ! !IROUTINE: zero_ - Set AttrVect Field Data to Zero ! ! !DESCRIPTION: ! This routine sets all of the point values of the integer and real ! attributes of an the input/output {\tt AttrVect} argument {\tt aV} ! to zero. The default action is to set the values of all the real and ! integer attributes to zero. The user may prevent the zeroing of the ! real (integer) attributes invoking {\tt zero\_()} with the optional ! {\tt LOGICAL} argument {\tt zeroReals} ({\tt zeroInts}) set with value ! {\tt .FALSE.} ! ! !INTERFACE: subroutine zero_(aV, zeroReals, zeroInts) ! !USES: use m_die,only : die use m_stdio,only : stderr use m_List, only : List use m_List, only : List_allocated => allocated implicit none ! !INPUT PARAMETERS: logical, optional, intent(IN) :: zeroReals logical, optional, intent(IN) :: zeroInts ! !INPUT/OUTPUT PARAMETERS: ! type(AttrVect), intent(INOUT) :: aV ! !REVISION HISTORY: ! 17May01 - R. Jacob - initial prototype/code ! 15Oct01 - J. Larson - switched loop order ! for cache optimization. ! 03Dec01 - E.T. Ong - eliminated looping method of ! of zeroing. "Compiler assignment" of attrvect performs faster ! on the IBM SP with mpxlf90 compiler. ! 05Jan10 - R. Jacob - zeroing an uninitialized aV is no ! longer a fatal error. !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::zero_' logical myZeroReals, myZeroInts if(present(zeroReals)) then myZeroReals = zeroReals else myZeroReals = .TRUE. endif if(present(zeroInts)) then myZeroInts = zeroInts else myZeroInts = .TRUE. endif ! if((.not. List_allocated(aV%iList)) .and. (.not. List_allocated(aV%rList))) then ! write(stderr,'(2a)')myname_, & ! 'MCTERROR: Trying to zero an uninitialized AttrVect' ! call die(myname_) ! endif if(myZeroInts) then ! zero out INTEGER attributes if(List_allocated(aV%iList)) then !CDIR COLLAPSE if(associated(aV%iAttr) .and. (nIAttr_(aV)>0)) aV%iAttr=0 endif endif if(myZeroReals) then ! zero out REAL attributes if(List_allocated(aV%rList)) then !CDIR COLLAPSE if(associated(aV%rAttr) .and. (nRAttr_(aV)>0)) aV%rAttr=0._FP endif endif end subroutine zero_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: nIAttr_ - Return the Number of Integer Attributes ! ! !DESCRIPTION: ! This integer function returns the number of integer attributes ! present in the input {\tt AttrVect} argument {\tt aV}. ! ! !INTERFACE: integer function nIAttr_(aV) ! ! !USES: ! use m_List, only : nitem implicit none ! !INPUT PARAMETERS: ! type(AttrVect),intent(in) :: aV ! !REVISION HISTORY: ! 22Apr98 - Jing Guo - initial prototype/prolog/code ! 10Oct01 - J. Larson - made code more robust ! by checking status of pointers in aV%iList !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::nIAttr_' if(associated(aV%iList%bf)) then nIAttr_ = nitem(aV%iList) else nIAttr_ = 0 endif end function nIAttr_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: nRAttr_ - Return the Number of Real Attributes ! ! !DESCRIPTION: ! This integer function returns the number of real attributes ! present in the input {\tt AttrVect} argument {\tt aV}. ! !INTERFACE: integer function nRAttr_(aV) ! ! !USES: ! use m_List, only : nitem implicit none ! !INPUT PARAMETERS: ! type(AttrVect),intent(in) :: aV ! !REVISION HISTORY: ! 22Apr98 - Jing Guo - initial prototype/prolog/code ! 10Oct01 - J. Larson - made code more robust ! by checking status of pointers in aV%iList !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::nRAttr_' if(associated(aV%rList%bf)) then nRAttr_ = nitem(aV%rList) else nRAttr_ = 0 endif end function nRAttr_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: getIList_ - Retrieve the Name of a Numbered Integer Attribute ! ! !DESCRIPTION: ! This routine returns the name of the {\tt ith} integer attribute of ! the input {\tt AttrVect} argument {\tt aVect}. The name is returned ! in the output {\tt String} argument {\tt item} (see the mpeu module ! {\tt m\_String} for more information regarding the {\tt String} type). ! ! !INTERFACE: subroutine getIList_(item, ith, aVect) ! ! !USES: ! use m_String, only : String use m_List, only : get implicit none ! !INPUT PARAMETERS: ! integer, intent(in) :: ith type(AttrVect),intent(in) :: aVect ! !OUTPUT PARAMETERS: ! type(String),intent(out) :: item ! !REVISION HISTORY: ! 24Apr98 - Jing Guo - initial prototype/prolog/code !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::getIList_' call get(item, ith, aVect%iList) end subroutine getIList_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: getRList_ - Retrieve the Name of a Numbered Real Attribute ! ! !DESCRIPTION: ! This routine returns the name of the {\tt ith} real attribute of ! the input {\tt AttrVect} argument {\tt aVect}. The name is returned ! in the output {\tt String} argument {\tt item} (see the mpeu module ! {\tt m\_String} for more information regarding the {\tt String} type). ! ! !INTERFACE: subroutine getRList_(item, ith, aVect) ! ! !USES: ! use m_String, only : String use m_List, only : get implicit none ! !INPUT PARAMETERS: ! integer, intent(in) :: ith type(AttrVect), intent(in) :: aVect ! !OUTPUT PARAMETERS: ! type(String), intent(out) :: item ! !REVISION HISTORY: ! 24Apr98 - Jing Guo - initial prototype/prolog/code !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::getRList_' call get(item,ith,aVect%rList) end subroutine getRList_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: indexIA_ - Index an Integer Attribute ! ! !DESCRIPTION: ! This function returns an {\tt INTEGER}, corresponding to the location ! of an integer attribute within the input {\tt AttrVect} argument ! {\tt aV}. For example, suppose {\tt aV} has the following attributes ! {\tt 'month'}, {\tt 'day'}, and {\tt 'year'}. The array of integer ! values for the attribute {\tt 'day'} is stored in !% \begin{verbatim} ! {\tt aV\%iAttr(indexIA\_(aV,'day'),:)}. !% \end{verbatim} ! If {\tt indexIA\_()} is unable to match {\tt item} to any of the integer ! attributes in {\tt aV}, the resulting value is zero which is equivalent ! to an error. The optional input {\tt CHARACTER} arguments {\tt perrWith} ! and {\tt dieWith} control how such errors are handled. ! \begin{enumerate} ! \item if neither {\tt perrWith} nor {\tt dieWith} are present, ! {\tt indexIA\_()} terminates execution with an internally generated ! error message; ! \item if {\tt perrWith} is present, but {\tt dieWith} is not, an error ! message is written to {\tt stderr} incorporating user-supplied traceback ! information stored in the argument {\tt perrWith}; ! \item if {\tt perrWith} is present, but {\tt dieWith} is not, and ! {\tt perrWith} is equal to ``quiet'', no error message is written. ! \item if {\tt dieWith} is present, execution terminates with an error ! message written to {\tt stderr} that incorporates user-supplied traceback ! information stored in the argument {\tt dieWith}; and ! \item if both {\tt perrWith} and {\tt dieWith} are present, execution ! terminates with an error message using {\tt dieWith}, and the argument ! {\tt perrWith} is ignored. ! \end{enumerate} ! ! !INTERFACE: integer function indexIA_(aV, item, perrWith, dieWith) ! ! !USES: ! use m_die, only : die use m_stdio,only : stderr use m_String, only : String use m_String, only : String_init => init use m_String, only : String_clean => clean use m_String, only : String_ToChar => ToChar use m_List, only : index use m_TraceBack, only : GenTraceBackString implicit none ! !INPUT PARAMETERS: ! type(AttrVect), intent(in) :: aV character(len=*), intent(in) :: item character(len=*), optional, intent(in) :: perrWith character(len=*), optional, intent(in) :: dieWith ! !REVISION HISTORY: ! 27Apr98 - Jing Guo - initial prototype/prolog/code ! 2Aug02 - J. Larson - Solidified error handling using perrWith/dieWith ! 1Jan05 - R. Jacob - add quiet option for error handling !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::indexIA_' type(String) :: myTrace if(present(dieWith)) then call GenTraceBackString(myTrace, dieWith, myname_) else if(present(perrWith)) then call GenTraceBackString(myTrace, perrWith, myname_) else call GenTraceBackString(myTrace, myname_) endif endif indexIA_=index(aV%iList,item) if(indexIA_==0) then ! The attribute was not found! ! As per the prologue, decide how to handle this error if(present(perrWith) .and. (.not. present(dieWith))) then if (trim(perrWith).eq.'quiet') then ! do nothing else write(stderr,'(5a)') myname_, & ':: ERROR--attribute not found: "',trim(item),'" ', & 'Traceback: ',String_ToChar(myTrace) endif else ! Shutdown write(stderr,'(5a)') myname_, & ':: FATAL--attribute not found: "',trim(item),'" ', & 'Traceback: ',String_ToChar(myTrace) call die(myname_) endif endif call String_clean(myTrace) end function indexIA_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: indexRA_ - Index a Real Attribute ! ! !DESCRIPTION: ! This function returns an {\tt INTEGER}, corresponding to the location ! of a real attribute within the input {\tt AttrVect} argument ! {\tt aV}. For example, suppose {\tt aV} has the following attributes ! {\tt 'latitude'}, {\tt 'longitude'}, and {\tt 'pressure'}. The array ! of real values for the attribute {\tt 'longitude'} is stored in !% \begin{verbatim} ! {\tt aV\%iAttr(indexRA\_(aV,'longitude'),:)}. !% \end{verbatim} ! If {\tt indexRA\_()} is unable to match {\tt item} to any of the real ! attributes in {\tt aV}, the resulting value is zero which is equivalent ! to an error. The optional input {\tt CHARACTER} arguments {\tt perrWith} ! and {\tt dieWith} control how such errors are handled. ! \begin{enumerate} ! \item if neither {\tt perrWith} nor {\tt dieWith} are present, ! {\tt indexRA\_()} terminates execution with an internally generated ! error message; ! \item if {\tt perrWith} is present, but {\tt dieWith} is not, an error ! message is written to {\tt stderr} incorporating user-supplied traceback ! information stored in the argument {\tt perrWith}; ! \item if {\tt perrWith} is present, but {\tt dieWith} is not, and ! {\tt perrWith} is equal to ``quiet'', no error message is written. ! \item if {\tt dieWith} is present, execution terminates with an error ! message written to {\tt stderr} that incorporates user-supplied traceback ! information stored in the argument {\tt dieWith}; and ! \item if both {\tt perrWith} and {\tt dieWith} are present, execution ! terminates with an error message using {\tt dieWith}, and the argument ! {\tt perrWith} is ignored. ! \end{enumerate} ! ! !INTERFACE: integer function indexRA_(aV, item, perrWith, dieWith) ! ! !USES: ! use m_die, only : die use m_stdio,only : stderr use m_List, only : index use m_String, only : String use m_String, only : String_init => init use m_String, only : String_clean => clean use m_String, only : String_ToChar => ToChar use m_TraceBack, only : GenTraceBackString implicit none ! !INPUT PARAMETERS: ! type(AttrVect), intent(in) :: aV character(len=*), intent(in) :: item character(len=*), optional, intent(in) :: perrWith character(len=*), optional, intent(in) :: dieWith ! !REVISION HISTORY: ! 27Apr98 - Jing Guo - initial prototype/prolog/code ! 2Aug02 - J. Larson - Solidified error handling using perrWith/dieWith ! 18Jan05 - R. Jacob - add quiet option for error handling !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::indexRA_' type(String) :: myTrace if(present(dieWith)) then ! Append onto TraceBack call GenTraceBackString(myTrace, dieWith, myname_) else if(present(perrWith)) then ! Append onto TraceBack call GenTraceBackString(myTrace, perrWith, myname_) else ! Start a TraceBackString call GenTraceBackString(myTrace, myname_) endif endif indexRA_=index(aV%rList,item) if(indexRA_==0) then ! The attribute was not found! ! As per the prologue, decide how to handle this error if(present(perrWith) .and. (.not. present(dieWith))) then if (trim(perrWith).eq.'quiet') then ! do nothing else write(stderr,'(5a)') myname_, & ':: ERROR--attribute not found: "',trim(item),'" ', & 'Traceback: ',String_ToChar(myTrace) endif else ! Shutdown if dieWith or no arguments present write(stderr,'(5a)') myname_, & ':: FATAL--attribute not found: "',trim(item),'" ', & 'Traceback: ',String_ToChar(myTrace) call die(myname_) endif endif call String_clean(myTrace) end function indexRA_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! DOE/ANL Mathematics and Computer Science Division ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: appendIAttr_ - Append one or more attributes onto the INTEGER part of an AttrVect. ! ! !DESCRIPTION: This routine takes an input {\tt AttrVect} argument ! {\tt aV}, and an input character string {\tt rList} and Appends {\tt rList} ! to the INTEGER part of {\tt aV}. The success (failure) of this operation is ! signified by a zero (nonzero) value for the optional {\tt INTEGER} ! output argument {\tt status}. ! ! !INTERFACE: subroutine appendIAttr_(aV, iList, status) ! ! !USES: ! use m_List, only : List_init => init use m_List, only : List_append => append use m_List, only : List_clean => clean use m_List, only : List_nullify => nullify use m_List, only : List_allocated => allocated use m_List, only : List_copy => copy use m_List, only : List use m_die use m_stdio implicit none ! !INPUT/OUTPUT PARAMETERS: ! type(AttrVect),intent(inout) :: aV ! !INPUT PARAMETERS: ! character(len=*), intent(in) :: iList ! !OUTPUT PARAMETERS: ! integer,optional,intent(out) :: status ! !REVISION HISTORY: ! 08Jul03 - R. Jacob - initial version !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::appendIAttr_' type(List) :: avRList,avIList ! placeholders for the aV attributes type(List) :: addIlist ! for the input string type(AttrVect) :: tempaV ! placeholder for aV data. integer :: locsize ! size of aV integer :: rlstatus,cstatus ! status flags integer :: ilstatus if(present(status)) status = 0 call List_nullify(avIList) call List_nullify(avRList) ! save the local size and current int and real attributes locsize = lsize_(aV) call exportRList_(aV,avRList,rlstatus) call exportIList_(aV,avIList,ilstatus) ! create and fill a temporary AttrVect to hold any data currently in the aV call initv_(tempaV,aV,lsize=locsize) call Copy_(aV,tempaV) ! create a List with the new attributes call List_init(addIlist,iList) ! append addIlist to current avIList if it has attributes. if(List_allocated(avIList)) then call List_append(avIList,addIlist) ! copy addIlist to avIList else call List_copy(avIList,addIlist) endif ! now delete the input aV and recreate it call clean_(aV,cstatus) call initl_(aV,avIList,avRList,locsize) ! copy back the data call Copy_(tempaV,aV) ! clean up. call List_clean(avRList,cstatus) call clean_(tempaV,cstatus) call List_clean(addIlist,cstatus) call List_clean(avIList,cstatus) if(present(status)) status = cstatus end subroutine appendIAttr_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! DOE/ANL Mathematics and Computer Science Division ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: appendRAttr_ - Append one or more attributes onto the REAL part of an AttrVect. ! ! !DESCRIPTION: This routine takes an input {\tt AttrVect} argument ! {\tt aV}, and an input character string {\tt rList} and Appends {\tt rList} ! to the REAL part of {\tt aV}. The success (failure) of this operation is ! signified by a zero (nonzero) value for the optional {\tt INTEGER} ! output argument {\tt status}. ! ! !INTERFACE: subroutine appendRAttr_(aV, rList, status) ! ! !USES: ! use m_List, only : List_init => init use m_List, only : List_append => append use m_List, only : List_clean => clean use m_List, only : List_nullify => nullify use m_List, only : List_allocated => allocated use m_List, only : List_copy => copy use m_List, only : List use m_die use m_stdio implicit none ! !INPUT/OUTPUT PARAMETERS: ! type(AttrVect),intent(inout) :: aV ! !INPUT PARAMETERS: ! character(len=*), intent(in) :: rList ! !OUTPUT PARAMETERS: ! integer,optional,intent(out) :: status ! !REVISION HISTORY: ! 04Jun03 - R. Jacob - initial version !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::appendRAttr_' type(List) :: avRList,avIList ! placeholders for the aV attributes type(List) :: addRlist ! for the input string type(AttrVect) :: tempaV ! placeholder for aV data. integer :: locsize ! size of aV integer :: rlstatus,cstatus ! status flags integer :: ilstatus if(present(status)) status = 0 call List_nullify(avIList) call List_nullify(avRList) ! save the local size and current int and real attributes locsize = lsize_(aV) call exportRList_(aV,avRList,rlstatus) call exportIList_(aV,avIList,ilstatus) ! create and fill a temporary AttrVect to hold any data currently in the aV call initv_(tempaV,aV,lsize=locsize) call Copy_(aV,tempaV) ! create a List with the new attributes call List_init(addRlist,rList) ! append addRlist to current avRList if it has attributes. if(List_allocated(avRList)) then call List_append(avRList,addRlist) ! copy addRlist to avRList else call List_copy(avRList,addRlist) endif ! now delete the input aV and recreate it call clean_(aV,cstatus) call initl_(aV,avIList,avRList,locsize) ! copy back the data call Copy_(tempaV,aV) ! clean up. call List_clean(avIList,cstatus) call clean_(tempaV,cstatus) call List_clean(addRlist,cstatus) call List_clean(avRList,cstatus) if(present(status)) status = cstatus end subroutine appendRAttr_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: exportIList_ - Return INTEGER Attribute List ! ! !DESCRIPTION: ! This routine extracts from the input {\tt AttrVect} argument {\tt aV} ! the integer attribute list, and returns it as the {\tt List} output ! argument {\tt outIList}. The success (failure) of this operation is ! signified by a zero (nonzero) value for the optional {\tt INTEGER} ! output argument {\tt status}. ! ! {\bf N.B.:} This routine returns an allocated {\tt List} data ! structure ({\tt outIList}). The user is responsible for deallocating ! this structure by invoking {\tt List\_clean()} (see the module ! {\tt m\_List} for details) once it is no longer needed. Failure to ! do so will result in a memory leak. ! ! !INTERFACE: subroutine exportIList_(aV, outIList, status) ! ! !USES: ! use m_die , only : die use m_stdio, only : stderr use m_List, only : List use m_List, only : List_allocated => allocated use m_List, only : List_copy => copy use m_List, only : List_nullify => nullify implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aV ! !OUTPUT PARAMETERS: type(List), intent(out) :: outIList integer, optional, intent(out) :: status ! !REVISION HISTORY: ! 14Dec01 - J.W. Larson - initial prototype. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::exportIList_' ! Initialize status flag (if present) to success value of zero. if(present(status)) status = 0 if(List_allocated(aV%iList)) then call List_copy(outIList, aV%iList) else call List_nullify(outIList) if(present(status)) then status = 1 else call die(myname_) endif endif end subroutine exportIList_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: exportRList_ - Return REAL attribute List ! ! !DESCRIPTION: ! This routine extracts from the input {\tt AttrVect} argument {\tt aV} ! the real attribute list, and returns it as the {\tt List} output ! argument {\tt outRList}. The success (failure) of this operation is ! signified by a zero (nonzero) value for the optional {\tt INTEGER} ! output argument {\tt status}. ! ! {\bf N.B.:} This routine returns an allocated {\tt List} data ! structure ({\tt outRList}). The user is responsible for deallocating ! this structure by invoking {\tt List\_clean()} (see the module ! {\tt m\_List} for details) once it is no longer needed. Failure to ! do so will result in a memory leak. ! ! !INTERFACE: subroutine exportRList_(aV, outRList, status) ! ! !USES: ! use m_die , only : die use m_stdio, only : stderr use m_List, only : List use m_List, only : List_allocated => allocated use m_List, only : List_copy => copy use m_List, only : List_nullify => nullify implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aV ! !OUTPUT PARAMETERS: type(List), intent(out) :: outRList integer, optional, intent(out) :: status ! !REVISION HISTORY: ! 14Dec01 - J.W. Larson - initial prototype. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::exportRList_' ! Initialize status flag (if present) to success value of zero. if(present(status)) status = 0 if(List_allocated(aV%rList)) then call List_copy(outRList, aV%rList) else call List_nullify(outRList) if(present(status)) then status = 1 else call die(myname_) endif endif end subroutine exportRList_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: exportIListToChar_ - Return AttrVect\%iList as CHARACTER ! ! !DESCRIPTION: ! This routine extracts from the input {\tt AttrVect} argument {\tt aV} ! the integer attribute list (see the mpeu module {\tt m\_List} for more ! information regarding the {\tt List} type), and returns it as a ! {\tt CHARACTER} suitable for printing. An example of its usage is ! \begin{verbatim} ! write(stdout,'(1a)') exportIListToChar_(aV) ! \end{verbatim} ! which writes the contents of {\tt aV\%iList\%bf} to the Fortran device ! {\tt stdout}. ! ! !INTERFACE: function exportIListToChar_(aV) ! ! !USES: ! use m_die , only : die use m_stdio, only : stderr use m_List, only : List use m_List, only : List_allocated => allocated use m_List, only : List_copy => copy use m_List, only : List_exportToChar => exportToChar use m_List, only : List_clean => clean implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aV ! !OUTPUT PARAMETERS: character(len=size(aV%iList%bf,1)) :: exportIListToChar_ ! !REVISION HISTORY: ! 13Feb02 - J.W. Larson - initial prototype. ! 05Jun03 - R. Jacob - return a blank instead of dying ! to avoid I/O errors when this function is used in a write statement. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::exportIListToChar_' ! The following extraneous list copy avoids a bug in the ! SGI MIPSpro Fortran 90 compiler version 7.30. and the ! Sun Fortran 90 Workshop compiler 5.0. If this line is removed, ! the following error will occur during compile time: ! Signal: Segmentation fault in IR->WHIRL Conversion phase. ! "m_AttrVect.F90": Error: Signal Segmentation fault in phase IR->WHIRL ! Conversion -- processing aborted ! f90 ERROR: /opt/MIPSpro/73/usr/lib32/cmplrs/mfef90 died due to signal 4 ! f90 ERROR: core dumped ! *** Error code 32 (bu21) type(List) :: iListCopy ! Extract the INTEGER attribute list to a character: if(List_allocated(aV%iList)) then call List_copy(iListCopy,aV%iList) exportIListToChar_ = List_exportToChar(iListCopy) call List_clean(iListCopy) else exportIListToChar_ = '' endif end function exportIListToChar_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: exportRListToChar_ - Return AttrVect\%rList as CHARACTER ! ! !DESCRIPTION: ! This routine extracts from the input {\tt AttrVect} argument {\tt aV} ! the real attribute list (see the mpeu module {\tt m\_List} for more ! information regarding the {\tt List} type), and returns it as a ! {\tt CHARACTER} suitable for printing. An example of its usage is ! \begin{verbatim} ! write(stdout,'(1a)') exportRListToChar_(aV) ! \end{verbatim} ! which writes the contents of {\tt aV\%rList\%bf} to the Fortran device ! {\tt stdout}. ! ! !INTERFACE: function exportRListToChar_(aV) ! ! !USES: ! use m_die , only : die use m_stdio, only : stderr use m_List, only : List use m_List, only : List_allocated => allocated use m_List, only : List_copy => copy use m_List, only : List_exportToChar => exportToChar use m_List, only : List_clean => clean implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aV ! !OUTPUT PARAMETERS: character(len=size(aV%rList%bf,1)) :: exportRListToChar_ ! !REVISION HISTORY: ! 13Feb02 - J.W. Larson - initial prototype. ! 05Jun03 - R. Jacob - return a blank instead of dying ! to avoid I/O errors when this function is used in a write statement. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::exportRListToChar_' ! The following extraneous list copy avoids a bug in the ! SGI MIPSpro Fortran 90 compiler version 7.30. and the ! Sun Fortran 90 Workshop compiler 5.0. If this line is removed, ! the following error will occur during compile time: ! Signal: Segmentation fault in IR->WHIRL Conversion phase. ! "m_AttrVect.F90": Error: Signal Segmentation fault in phase IR->WHIRL ! Conversion -- processing aborted ! f90 ERROR: /opt/MIPSpro/73/usr/lib32/cmplrs/mfef90 died due to signal 4 ! f90 ERROR: core dumped ! *** Error code 32 (bu21) type(List) :: rListCopy ! Extract the REAL attribute list to a character: if(List_allocated(aV%rList)) then call List_copy(rListCopy,aV%rList) exportRListToChar_ = List_exportToChar(rListCopy) call List_clean(rListCopy) else exportRListToChar_ = '' endif end function exportRListToChar_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: exportIAttr_ - Return INTEGER Attribute as a Vector ! ! !DESCRIPTION: ! This routine extracts from the input {\tt AttrVect} argument {\tt aV} ! the integer attribute corresponding to the tag defined in the input ! {\tt CHARACTER} argument {\tt AttrTag}, and returns it in the ! {\tt INTEGER} output array {\tt outVect}, and its length in the output ! {\tt INTEGER} argument {\tt lsize}. The optional input {\tt CHARACTER} ! arguments {\tt perrWith} and {\tt dieWith} control how errors are ! handled. ! \begin{enumerate} ! \item if neither {\tt perrWith} nor {\tt dieWith} are present, ! {\tt exportIAttr\_()} terminates execution with an internally generated ! error message; ! \item if {\tt perrWith} is present, but {\tt dieWith} is not, an error ! message is written to {\tt stderr} incorporating user-supplied traceback ! information stored in the argument {\tt perrWith}; ! \item if {\tt dieWith} is present, execution terminates with an error ! message written to {\tt stderr} that incorporates user-supplied traceback ! information stored in the argument {\tt dieWith}; and ! \item if both {\tt perrWith} and {\tt dieWith} are present, execution ! terminates with an error message using {\tt dieWith}, and the argument ! {\tt perrWith} is ignored. ! \end{enumerate} ! ! {\bf N.B.:} This routine will fail if the {\tt AttrTag} is not in ! the {\tt AttrVect} {\tt List} component {\tt aV\%iList}. ! ! {\bf N.B.:} The flexibility of this routine regarding the pointer ! association status of the output argument {\tt outVect} means the ! user must invoke this routine with care. If the user wishes this ! routine to fill a pre-allocated array, then obviously this array ! must be allocated prior to calling this routine. If the user wishes ! that the routine {\em create} the output argument array {\tt outVect}, ! then the user must ensure this pointer is not allocated (i.e. the user ! must nullify this pointer) before this routine is invoked. ! ! {\bf N.B.:} If the user has relied on this routine to allocate memory ! associated with the pointer {\tt outVect}, then the user is responsible ! for deallocating this array once it is no longer needed. Failure to ! do so will result in a memory leak. ! ! !INTERFACE: subroutine exportIAttr_(aV, AttrTag, outVect, lsize, perrWith, dieWith) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr use m_String, only : String use m_String, only : String_init => init use m_String, only : String_clean => clean use m_String, only : String_ToChar => ToChar use m_TraceBack, only : GenTraceBackString implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aV character(len=*), intent(in) :: AttrTag character(len=*), optional, intent(in) :: perrWith character(len=*), optional, intent(in) :: dieWith ! !OUTPUT PARAMETERS: integer, dimension(:), pointer :: outVect integer, optional, intent(out) :: lsize ! !REVISION HISTORY: ! 19Oct01 - J.W. Larson - initial (slow) ! prototype. ! 6May02 - J.W. Larson - added capability ! to work with pre-allocated outVect. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::exportIAttr_' integer :: index, ierr, n, myLsize type(String) :: myTrace if(present(dieWith)) then ! Append onto TraceBack call GenTraceBackString(myTrace, dieWith, myname_) else if(present(perrWith)) then ! Append onto TraceBack call GenTraceBackString(myTrace, perrWith, myname_) else ! Start a TraceBackString call GenTraceBackString(myTrace, myname_) endif endif ! Index the attribute we wish to extract: index = indexIA_(aV, attrTag, dieWith=String_ToChar(myTrace)) ! Determine the number of data points: myLsize = lsize_(aV) ! Allocate space for outVect (if it is not already dimensioned) if(associated(outVect)) then ! check the size of outVect if(size(outVect) < myLsize) then write(stderr,'(3a,i8,a,i8)') myname_, & ':: ERROR length of output array outVect ', & ' less than length of aV. size(outVect)=',size(outVect), & ', length of aV=',myLsize write(stderr,'(2a)') 'Traceback: ',String_ToChar(myTrace) call die(myname_) endif else ! allocate space for outVect allocate(outVect(myLsize), stat=ierr) if(ierr /= 0) then write(stderr,'(2a,i8)') myname_, & ':: Error - allocate(outVect(...) failed. ierr = ',ierr write(stderr,'(2a)') 'Traceback: ',String_ToChar(myTrace) call die(myname_) endif endif ! Copy the attribute data into outVect !$OMP PARALLEL DO PRIVATE(n) do n=1,myLsize outVect(n) = aV%iAttr(index,n) end do ! return optional output argument lsize: if(present(lsize)) lsize = myLsize call String_clean(myTrace) end subroutine exportIAttr_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: exportRAttrSP_ - Return REAL Attribute as a Pointer to Array ! ! !DESCRIPTION: ! This routine extracts from the input {\tt AttrVect} argument {\tt aV} ! the real attribute corresponding to the tag defined in the input ! {\tt CHARACTER} argument {\tt AttrTag}, and returns it in the ! {\tt REAL} output array {\tt outVect}, and its length in the output ! {\tt INTEGER} argument {\tt lsize}. The optional input {\tt CHARACTER} ! arguments {\tt perrWith} and {\tt dieWith} control how errors are ! handled. ! \begin{enumerate} ! \item if neither {\tt perrWith} nor {\tt dieWith} are present, ! {\tt exportRAttr\_()} terminates execution with an internally generated ! error message; ! \item if {\tt perrWith} is present, but {\tt dieWith} is not, an error ! message is written to {\tt stderr} incorporating user-supplied traceback ! information stored in the argument {\tt perrWith}; ! \item if {\tt dieWith} is present, execution terminates with an error ! message written to {\tt stderr} that incorporates user-supplied traceback ! information stored in the argument {\tt dieWith}; and ! \item if both {\tt perrWith} and {\tt dieWith} are present, execution ! terminates with an error message using {\tt dieWith}, and the argument ! {\tt perrWith} is ignored. ! \end{enumerate} ! ! {\bf N.B.:} This routine will fail if the {\tt AttrTag} is not in ! the {\tt AttrVect} {\tt List} component {\tt aV\%iList}. ! ! {\bf N.B.:} The flexibility of this routine regarding the pointer ! association status of the output argument {\tt outVect} means the ! user must invoke this routine with care. If the user wishes this ! routine to fill a pre-allocated array, then obviously this array ! must be allocated prior to calling this routine. If the user wishes ! that the routine {\em create} the output argument array {\tt outVect}, ! then the user must ensure this pointer is not allocated (i.e. the user ! must nullify this pointer) before this routine is invoked. ! ! {\bf N.B.:} If the user has relied on this routine to allocate memory ! associated with the pointer {\tt outVect}, then the user is responsible ! for deallocating this array once it is no longer needed. Failure to ! do so will result in a memory leak. ! ! !INTERFACE: subroutine exportRAttrSP_(aV, AttrTag, outVect, lsize, perrWith, dieWith) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr use m_String, only : String use m_String, only : String_init => init use m_String, only : String_clean => clean use m_String, only : String_ToChar => ToChar use m_TraceBack, only : GenTraceBackString implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aV character(len=*), intent(in) :: AttrTag character(len=*), optional, intent(in) :: perrWith character(len=*), optional, intent(in) :: dieWith ! !OUTPUT PARAMETERS: real(SP), dimension(:), pointer :: outVect integer, optional, intent(out) :: lsize ! !REVISION HISTORY: ! 19Oct01 - J.W. Larson - initial (slow) ! prototype. ! 6May02 - J.W. Larson - added capability ! to work with pre-allocated outVect. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::exportRAttrSP_' integer :: index, ierr, n, myLsize type(String) :: myTrace if(present(dieWith)) then ! Append onto TraceBack call GenTraceBackString(myTrace, dieWith, myname_) else if(present(perrWith)) then ! Append onto TraceBack call GenTraceBackString(myTrace, perrWith, myname_) else ! Start a TraceBackString call GenTraceBackString(myTrace, myname_) endif endif ! Index the attribute we wish to extract: index = indexRA_(aV, attrTag, dieWith=String_ToChar(myTrace)) ! Determine the number of data points: myLsize = lsize_(aV) ! Allocate space for outVect (if it is not already dimensioned) if(associated(outVect)) then ! check the size of outVect if(size(outVect) < myLsize) then write(stderr,'(3a,i8,a,i8)') myname_, & ':: ERROR length of output array outVect ', & ' less than length of aV. size(outVect)=',size(outVect), & ', length of aV=',myLsize write(stderr,'(2a)') 'Traceback: ',String_ToChar(myTrace) call die(myname_) endif else ! allocate space for outVect allocate(outVect(myLsize), stat=ierr) if(ierr /= 0) then write(stderr,'(2a,i8)') myname_, & ':: Error - allocate(outVect(...) failed. ierr = ',ierr write(stderr,'(2a)') 'Traceback: ',String_ToChar(myTrace) call die(myname_) endif endif ! Copy the attribute data into outVect !$OMP PARALLEL DO PRIVATE(n) do n=1,myLsize outVect(n) = aV%rAttr(index,n) end do call String_clean(myTrace) ! return optional argument lsize if(present(lsize)) lsize = myLsize end subroutine exportRAttrSP_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! ! ---------------------------------------------------------------------- ! ! !IROUTINE: exportRAttrDP_ - Return REAL Attribute as a Pointer to Array ! ! !DESCRIPTION: ! Double precision version of exportRAttrSP_ ! ! !INTERFACE: subroutine exportRAttrDP_(aV, AttrTag, outVect, lsize, perrWith, dieWith) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr use m_String, only : String use m_String, only : String_init => init use m_String, only : String_clean => clean use m_String, only : String_ToChar => ToChar use m_TraceBack, only : GenTraceBackString implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aV character(len=*), intent(in) :: AttrTag character(len=*), optional, intent(in) :: perrWith character(len=*), optional, intent(in) :: dieWith ! !OUTPUT PARAMETERS: real(DP), dimension(:), pointer :: outVect integer, optional, intent(out) :: lsize ! !REVISION HISTORY: ! 19Oct01 - J.W. Larson - initial (slow) ! prototype. ! 6May02 - J.W. Larson - added capability ! to work with pre-allocated outVect. ! ! ______________________________________________________________________ character(len=*),parameter :: myname_=myname//'::exportRAttrDP_' integer :: index, ierr, n, myLsize type(String) :: myTrace if(present(dieWith)) then ! Append onto TraceBack call GenTraceBackString(myTrace, dieWith, myname_) else if(present(perrWith)) then ! Append onto TraceBack call GenTraceBackString(myTrace, perrWith, myname_) else ! Start a TraceBackString call GenTraceBackString(myTrace, myname_) endif endif ! Index the attribute we wish to extract: index = indexRA_(aV, attrTag, dieWith=String_ToChar(myTrace)) ! Determine the number of data points: myLsize = lsize_(aV) ! Allocate space for outVect (if it is not already dimensioned) if(associated(outVect)) then ! check the size of outVect if(size(outVect) < myLsize) then write(stderr,'(3a,i8,a,i8)') myname_, & ':: ERROR length of output array outVect ', & ' less than length of aV. size(outVect)=',size(outVect), & ', length of aV=',myLsize write(stderr,'(2a)') 'Traceback: ',String_ToChar(myTrace) call die(myname_) endif else ! allocate space for outVect allocate(outVect(myLsize), stat=ierr) if(ierr /= 0) then write(stderr,'(2a,i8)') myname_, & ':: Error - allocate(outVect(...) failed. ierr = ',ierr write(stderr,'(2a)') 'Traceback: ',String_ToChar(myTrace) call die(myname_) endif endif ! Copy the attribute data into outVect !$OMP PARALLEL DO PRIVATE(n) do n=1,myLsize outVect(n) = aV%rAttr(index,n) end do call String_clean(myTrace) ! return optional argument lsize if(present(lsize)) lsize = myLsize end subroutine exportRAttrDP_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: importIAttr_ - Import INTEGER Vector as an Attribute ! ! !DESCRIPTION: ! This routine imports into the input/output {\tt AttrVect} argument ! {\tt aV} the integer attribute corresponding to the tag defined in the ! input {\tt CHARACTER} argument {\tt AttrTag}. The data to be imported ! is provided in the {\tt INTEGER} input array {\tt inVect}, and the ! number of entries to be imported in the optional input {\tt INTEGER} ! argument {\tt lsize}. ! ! {\bf N.B.:} This routine will fail if the {\tt AttrTag} is not in ! the {\tt AttrVect} {\tt List} component {\tt aV\%iList}. ! ! !INTERFACE: subroutine importIAttr_(aV, AttrTag, inVect, lsize) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr implicit none ! !INPUT PARAMETERS: character(len=*), intent(in) :: AttrTag integer, dimension(:), pointer :: inVect integer, optional, intent(in) :: lsize ! !INPUT/OUTPUT PARAMETERS: type(AttrVect), intent(inout) :: aV ! !REVISION HISTORY: ! 19Oct01 - J.W. Larson - initial (slow) ! prototype. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::importIAttr_' integer :: index, aVsize, ierr, n, mysize ! Index the attribute we wish to extract: index = indexIA_(aV, attrTag) ! Determine the number of data points: aVsize = lsize_(aV) ! Check input array size vs. lsize_(aV): if(present(lsize)) then if(aVsize < lsize) then write(stderr,'(3a,i8,a,i8)') myname_, & ':: ERROR--attempt to import too many entries ', & 'into AttrVect aV. AttrVect_lsize(aV)=',aVsize, & ', number of entries to be imported=',lsize call die(myname_) endif mysize=lsize else if(aVsize < size(inVect)) then write(stderr,'(3a,i8,a,i8)') myname_, & ':: ERROR--attempt to import too many entries ', & 'into AttrVect aV. AttrVect_lsize(aV)=',aVsize, & ' , number of entries to be imported=',size(inVect) call die(myname_) endif mysize = aVsize endif ! Copy the data from inVect to its attribute slot: !$OMP PARALLEL DO PRIVATE(n) do n=1,mysize aV%iAttr(index,n) = inVect(n) end do end subroutine importIAttr_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: importRAttrSP_ - Import REAL Vector as an Attribute ! ! !DESCRIPTION: ! This routine imports into the input/output {\tt AttrVect} argument ! {\tt aV} the real attribute corresponding to the tag defined in the ! input {\tt CHARACTER} argument {\tt AttrTag}. The data to be imported ! is provided in the {\tt REAL} input array {\tt inVect}, and its ! length in the optional input {\tt INTEGER} argument {\tt lsize}. ! ! {\bf N.B.:} This routine will fail if the {\tt AttrTag} is not in ! the {\tt AttrVect} {\tt List} component {\tt aV\%rList}. ! ! !INTERFACE: subroutine importRAttrSP_(aV, AttrTag, inVect, lsize) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr implicit none ! !INPUT PARAMETERS: character(len=*), intent(in) :: AttrTag real(SP), dimension(:), pointer :: inVect integer, optional, intent(in) :: lsize ! !INPUT/OUTPUT PARAMETERS: type(AttrVect), intent(inout) :: aV ! !REVISION HISTORY: ! 19Oct01 - J.W. Larson - initial (slow) ! prototype. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::importRAttrSP_' integer :: index, aVsize, ierr, n, mysize ! Index the attribute we wish to extract: index = indexRA_(aV, attrTag) ! Determine the number of data points: aVsize = lsize_(aV) ! Check input array size vs. lsize_(aV): if(present(lsize)) then if(aVsize < lsize) then write(stderr,'(3a,i8,a,i8)') myname_, & ':: ERROR--attempt to import too many entries ', & 'into AttrVect aV. AttrVect_lsize(aV)=',aVsize, & ', number of entries to be imported=',lsize call die(myname_) endif mysize=lsize else if(aVsize < size(inVect)) then write(stderr,'(3a,i8,a,i8)') myname_, & ':: ERROR--attempt to import too many entries ', & 'into AttrVect aV. AttrVect_lsize(aV)=',aVsize, & ' , number of entries to be imported=',size(inVect) call die(myname_) endif mysize=aVsize endif ! Copy the attribute data into outVect !$OMP PARALLEL DO PRIVATE(n) do n=1,mysize aV%rAttr(index,n) = inVect(n) end do end subroutine importRAttrSP_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! ! ---------------------------------------------------------------------- ! ! !IROUTINE: importRAttrDP_ - Import REAL Vector as an Attribute ! ! !DESCRIPTION: ! Double precision version of importRAttrSP_ ! ! !INTERFACE: subroutine importRAttrDP_(aV, AttrTag, inVect, lsize) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr implicit none ! !INPUT PARAMETERS: character(len=*), intent(in) :: AttrTag real(DP), dimension(:), pointer :: inVect integer, optional, intent(in) :: lsize ! !INPUT/OUTPUT PARAMETERS: type(AttrVect), intent(inout) :: aV ! !REVISION HISTORY: ! 19Oct01 - J.W. Larson - initial (slow) ! prototype. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::importRAttrDP_' integer :: index, aVsize, ierr, n, mysize ! Index the attribute we wish to extract: index = indexRA_(aV, attrTag) ! Determine the number of data points: aVsize = lsize_(aV) ! Check input array size vs. lsize_(aV): if(present(lsize)) then if(aVsize < lsize) then write(stderr,'(3a,i8,a,i8)') myname_, & ':: ERROR--attempt to import too many entries ', & 'into AttrVect aV. AttrVect_lsize(aV)=',aVsize, & ', number of entries to be imported=',lsize call die(myname_) endif mysize=lsize else if(aVsize < size(inVect)) then write(stderr,'(3a,i8,a,i8)') myname_, & ':: ERROR--attempt to import too many entries ', & 'into AttrVect aV. AttrVect_lsize(aV)=',aVsize, & ' , number of entries to be imported=',size(inVect) call die(myname_) endif mysize=aVsize endif ! Copy the attribute data into outVect !$OMP PARALLEL DO PRIVATE(n) do n=1,mysize aV%rAttr(index,n) = inVect(n) end do end subroutine importRAttrDP_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: RCopy_ - Copy Real Attributes from One AttrVect to Another ! ! !DESCRIPTION: ! This routine copies from input argment {\tt aVin} into the output ! {\tt AttrVect} argument {\tt aVout} the shared real attributes. ! ! If the optional argument {\tt Vector} is present and true, the vector ! architecture-friendly portions of this routine will be invoked. ! ! If the optional argument {\tt sharedIndices} is present, it should be ! the result of the call {\tt SharedIndicesOneType\_(aVin, aVout, 'REAL', ! sharedIndices)}. Providing this argument speeds up this routine ! substantially. For example, you can compute a {\tt sharedIndices} ! structure once for a given pair of {\tt AttrVect}s, then use that same ! structure for all copies between those two {\tt AttrVect}s (although ! note that a different {\tt sharedIndices} variable would be needed if ! {\tt aVin} and {\tt aVout} were reversed). ! ! {\bf N.B.:} This routine will fail if the {\tt aVout} is not initialized. ! ! !INTERFACE: subroutine RCopy_(aVin, aVout, vector, sharedIndices) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr use m_List, only : GetSharedListIndices use m_List, only : GetIndices => get_indices implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aVin logical, optional, intent(in) :: vector type(AVSharedIndicesOneType), optional, intent(in) :: sharedIndices ! !OUTPUT PARAMETERS: type(AttrVect), intent(inout) :: aVout ! !REVISION HISTORY: ! 18Aug06 - R. Jacob - initial version. ! 28Apr11 - W.J. Sacks - added sharedIndices argument !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::RCopy_' integer :: i,j,ier ! dummy variables integer :: aVsize ! The lsize of aVin and aVout integer :: num_inindices, num_outindices ! Number of matching indices in aV integer :: inxmin, outxmin, inx, outx ! Index variables logical :: usevector ! true if vector flag is present and true. character*7 :: data_flag ! character variable used as data type flag type(AVSharedIndicesOneType) :: mySharedIndices ! copied from sharedIndices, or ! computed if sharedIndices is not ! present logical :: clean_mySharedIndices ! true if we need to clean mySharedIndices before ! returning (will be true if we did allocation in this ! subroutine) ! Check the arguments aVsize = lsize_(aVin) if(lsize_(aVin) /= lsize_(aVout)) then write(stderr,'(2a)') myname_, & 'MCTERROR: Input aV and output aV do not have the same size' call die(myname_,'MCTERROR: Input aV and output aV & &do not have the same size',2) endif data_flag = 'REAL' if (present(sharedIndices)) then ! do some error checking on sharedIndices if (.not. (associated(sharedIndices%aVindices1) .and. associated(sharedIndices%aVindices2))) then call die(myname_,'MCTERROR: provided sharedIndices structure is uninitialized',3) endif if (trim(sharedIndices%data_flag) /= data_flag) then call die(myname_,'MCTERROR: provided sharedIndices structure has incorrect data_flag',4) endif ! copy into local variable mySharedIndices = sharedIndices clean_mySharedIndices = .false. else ! Check REAL attributes for matching indices call SharedIndicesOneType_(aVin, aVout, data_flag, mySharedIndices) clean_mySharedIndices = .true. endif if(mySharedIndices%num_indices <= 0) then if (clean_mySharedIndices) then call cleanSharedIndicesOneType_(mySharedIndices,stat=ier) if(ier /= 0) call die(myname_,'MCTERROR: in cleanSharedIndicesOneType_',ier) endif return endif ! check vector flag. usevector = .false. if (present(vector)) then if(vector) usevector = .true. endif ! Start copying if(mySharedIndices%contiguous) then if(usevector) then outxmin=mySharedIndices%aVindices2(1)-1 inxmin=mySharedIndices%aVindices1(1)-1 !$OMP PARALLEL DO PRIVATE(i,j) do i=1,mySharedIndices%num_indices !CDIR SELECT(VECTOR) !DIR$ CONCURRENT do j=1,aVsize aVout%rAttr(outxmin+i,j) = aVin%rAttr(inxmin+i,j) enddo enddo else outxmin=mySharedIndices%aVindices2(1)-1 inxmin=mySharedIndices%aVindices1(1)-1 !$OMP PARALLEL DO PRIVAtE(j,i) do j=1,aVsize !DIR$ CONCURRENT do i=1,mySharedIndices%num_indices aVout%rAttr(outxmin+i,j) = aVin%rAttr(inxmin+i,j) enddo enddo endif else !$OMP PARALLEL DO PRIVATE(j,i,outx,inx) do j=1,aVsize !DIR$ CONCURRENT do i=1,mySharedIndices%num_indices outx=mySharedIndices%aVindices2(i) inx=mySharedIndices%aVindices1(i) aVout%rAttr(outx,j) = aVin%rAttr(inx,j) enddo enddo endif if (clean_mySharedIndices) then call cleanSharedIndicesOneType_(mySharedIndices,stat=ier) if(ier /= 0) call die(myname_,'MCTERROR: in cleanSharedIndicesOneType_',ier) endif end subroutine RCopy_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: RCopyL_ - Copy Specific Real Attributes from One AttrVect to Another ! ! !DESCRIPTION: ! This routine copies from input argment {\tt aVin} into the output ! {\tt AttrVect} argument {\tt aVout} the real attributes specified in ! input {\tt CHARACTER} argument {\tt rList}. The attributes can ! be listed in any order. ! ! 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}. The translation arguments should ! be identical in length to the {\tt rList} but with the correct {\tt aVout} ! name subsititued at the appropriate place. ! ! If the optional argument {\tt Vector} is present and true, the vector ! architecture-friendly portions of this routine will be invoked. ! ! {\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}. ! ! !INTERFACE: subroutine RCopyL_(aVin, aVout, rList, TrList, vector) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr use m_List, only : GetSharedListIndices use m_List, only : GetIndices => get_indices implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aVin character(len=*), intent(in) :: rList character(len=*), optional, intent(in) :: TrList logical, optional, intent(in) :: vector ! !OUTPUT PARAMETERS: type(AttrVect), intent(inout) :: aVout ! !REVISION HISTORY: ! 16Aug06 - R. Jacob - initial version from breakup ! of Copy_. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::RCopyL_' integer :: i,j,ier ! dummy variables integer :: num_indices ! Overlapping attribute index number integer :: aVsize ! The lsize of aVin and aVout integer :: num_inindices, num_outindices ! Number of matching indices in aV integer :: inxmin, outxmin, inx, outx ! Index variables logical :: TrListIsPresent ! true if list argument is present logical :: contiguous ! true if index segments are contiguous in memory logical :: usevector ! true if vector flag is present and true. character*7 :: data_flag ! character variable used as data type flag ! Overlapping attribute index storage arrays: integer, dimension(:), pointer :: aVinindices, aVoutindices ! Check the arguments aVsize = lsize_(aVin) if(lsize_(aVin) /= lsize_(aVout)) then write(stderr,'(2a)') myname_, & 'MCTERROR: Input aV and output aV do not have the same size' call die(myname_,'MCTERROR: Input aV and output aV & &do not have the same size',2) endif if(len_trim(rList) <= 0) return ! Copy the listed real attributes ! Index rList with the AttrVects call GetIndices(aVinindices,aVin%rList,trim(rList)) ! TrList is present if it is provided and its length>0 TrListIsPresent = .false. if(present(TrList)) then if(len_trim(TrList) > 0) then TrListIsPresent = .true. endif endif if(TrListIsPresent) then call GetIndices(aVoutindices,aVout%rList,trim(TrList)) if(size(aVinindices) /= size(aVoutindices)) then call die(myname_,"Arguments rList and TrList do not& &contain the same number of items") endif else call GetIndices(aVoutindices,aVout%rList,trim(rList)) endif num_indices=size(aVoutindices) ! nothing to do if num_indices <=0 if (num_indices <= 0) then deallocate(aVinindices, aVoutindices, stat=ier) if(ier/=0) call die(myname_,"deallocate(aVinindices...)",ier) return endif ! check vector flag. usevector = .false. if (present(vector)) then if(vector) usevector = .true. endif ! Check if the indices are contiguous in memory for faster copy contiguous=.true. do i=2,num_indices if(aVinindices(i) /= aVinindices(i-1)+1) contiguous = .false. enddo if(contiguous) then do i=2,num_indices if(aVoutindices(i) /= aVoutindices(i-1)+1) contiguous=.false. enddo endif ! Start copying (arranged loop order optimized for xlf90) if(contiguous) then if(usevector) then outxmin=aVoutindices(1)-1 inxmin=aVinindices(1)-1 !$OMP PARALLEL DO PRIVATE(i,j) do i=1,num_indices !DIR$ CONCURRENT do j=1,aVsize aVout%rAttr(outxmin+i,j) = aVin%rAttr(inxmin+i,j) enddo enddo else outxmin=aVoutindices(1)-1 inxmin=aVinindices(1)-1 !$OMP PARALLEL DO PRIVATE(j,i) do j=1,aVsize !DIR$ CONCURRENT do i=1,num_indices aVout%rAttr(outxmin+i,j) = aVin%rAttr(inxmin+i,j) enddo enddo endif else !$OMP PARALLEL DO PRIVATE(j,i,outx,inx) do j=1,aVsize !DIR$ CONCURRENT do i=1,num_indices outx=aVoutindices(i) inx=aVinindices(i) aVout%rAttr(outx,j) = aVin%rAttr(inx,j) enddo enddo endif deallocate(aVinindices, aVoutindices, stat=ier) if(ier/=0) call die(myname_,"deallocate(aVinindices...)",ier) end subroutine RCopyL_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: ICopy_ - Copy Integer Attributes from One AttrVect to Another ! ! !DESCRIPTION: ! This routine copies from input argment {\tt aVin} into the output ! {\tt AttrVect} argument {\tt aVout} the shared integer attributes. ! ! If the optional argument {\tt Vector} is present and true, the vector ! architecture-friendly portions of this routine will be invoked. ! ! If the optional argument {\tt sharedIndices} is present, it should be ! the result of the call {\tt SharedIndicesOneType\_(aVin, aVout, 'INTEGER', ! sharedIndices)}. Providing this argument speeds up this routine ! substantially. For example, you can compute a {\tt sharedIndices} ! structure once for a given pair of {\tt AttrVect}s, then use that same ! structure for all copies between those two {\tt AttrVect}s (although ! note that a different {\tt sharedIndices} variable would be needed if ! {\tt aVin} and {\tt aVout} were reversed). ! ! {\bf N.B.:} This routine will fail if the {\tt aVout} is not initialized. ! ! !INTERFACE: subroutine ICopy_(aVin, aVout, vector, sharedIndices) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr use m_List, only : GetSharedListIndices use m_List, only : GetIndices => get_indices implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aVin logical, optional, intent(in) :: vector type(AVSharedIndicesOneType), optional, intent(in) :: sharedIndices ! !OUTPUT PARAMETERS: type(AttrVect), intent(inout) :: aVout ! !REVISION HISTORY: ! 16Aug06 - R. Jacob - initial version. ! 28Apr11 - W.J. Sacks - added sharedIndices argument ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::ICopy_' integer :: i,j,ier ! dummy variables integer :: aVsize ! The lsize of aVin and aVout integer :: num_inindices, num_outindices ! Number of matching indices in aV integer :: inxmin, outxmin, inx, outx ! Index variables logical :: usevector ! true if vector flag is present and true. character*7 :: data_flag ! character variable used as data type flag type(AVSharedIndicesOneType) :: mySharedIndices ! copied from sharedIndices, or ! computed if sharedIndices is not ! present logical :: clean_mySharedIndices ! true if we need to clean mySharedIndices before ! returning (will be true if we did allocation in this ! subroutine) ! Check the arguments aVsize = lsize_(aVin) if(lsize_(aVin) /= lsize_(aVout)) then write(stderr,'(2a)') myname_, & 'MCTERROR: Input aV and output aV do not have the same size' call die(myname_,'MCTERROR: Input aV and output aV & &do not have the same size',2) endif data_flag = 'INTEGER' if (present(sharedIndices)) then ! do some error checking on sharedIndices if (.not. (associated(sharedIndices%aVindices1) .and. associated(sharedIndices%aVindices2))) then call die(myname_,'MCTERROR: provided sharedIndices structure is uninitialized',3) endif if (trim(sharedIndices%data_flag) /= data_flag) then call die(myname_,'MCTERROR: provided sharedIndices structure has incorrect data_flag',4) endif ! copy into local variable mySharedIndices = sharedIndices clean_mySharedIndices = .false. else ! Check INTEGER attributes for matching indices call SharedIndicesOneType_(aVin, aVout, data_flag, mySharedIndices) clean_mySharedIndices = .true. endif if(mySharedIndices%num_indices <= 0) then if (clean_mySharedIndices) then call cleanSharedIndicesOneType_(mySharedIndices,stat=ier) if(ier /= 0) call die(myname_,'MCTERROR: in cleanSharedIndicesOneType_',ier) endif return endif ! check vector flag. usevector = .false. if (present(vector)) then if(vector) usevector = .true. endif if(mySharedIndices%contiguous) then if(usevector) then outxmin=mySharedIndices%aVindices2(1)-1 inxmin=mySharedIndices%aVindices1(1)-1 !$OMP PARALLEL DO PRIVATE(i,j) do i=1,mySharedIndices%num_indices !CDIR SELECT(VECTOR) !DIR$ CONCURRENT do j=1,aVsize aVout%iAttr(outxmin+i,j) = aVin%iAttr(inxmin+i,j) enddo enddo else outxmin=mySharedIndices%aVindices2(1)-1 inxmin=mySharedIndices%aVindices1(1)-1 !$OMP PARALLEL DO PRIVATE(j,i) do j=1,aVsize !DIR$ CONCURRENT do i=1,mySharedIndices%num_indices aVout%iAttr(outxmin+i,j) = aVin%iAttr(inxmin+i,j) enddo enddo endif else !$OMP PARALLEL DO PRIVATE(j,i,outx,inx) do j=1,aVsize !DIR$ CONCURRENT do i=1,mySharedIndices%num_indices outx=mySharedIndices%aVindices2(i) inx=mySharedIndices%aVindices1(i) aVout%iAttr(outx,j) = aVin%iAttr(inx,j) enddo enddo endif if (clean_mySharedIndices) then call cleanSharedIndicesOneType_(mySharedIndices,stat=ier) if(ier /= 0) call die(myname_,'MCTERROR: in cleanSharedIndicesOneType_',ier) endif end subroutine ICopy_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: ICopyL_ - Copy Specific Integer Attributes from One AttrVect to Another ! ! !DESCRIPTION: ! This routine copies from input argment {\tt aVin} into the output ! {\tt AttrVect} argument {\tt aVout} the integer attributes specified in ! input {\tt CHARACTER} argument {\tt iList}. The attributes can ! be listed in any order. ! ! 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 TiList}. The translation arguments should ! be identical in length to the {\tt iList} but with the correct {\tt aVout} ! name subsititued at the appropriate place. ! ! If the optional argument {\tt Vector} is present and true, the vector ! architecture-friendly portions of this routine will be invoked. ! ! {\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}. ! ! !INTERFACE: subroutine ICopyL_(aVin, aVout, iList, TiList, vector) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr use m_List, only : GetIndices => get_indices implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aVin character(len=*) , intent(in) :: iList character(len=*), optional, intent(in) :: TiList logical, optional, intent(in) :: vector ! !OUTPUT PARAMETERS: type(AttrVect), intent(inout) :: aVout ! !REVISION HISTORY: ! 16Aug06 - R. Jacob - initial version from breakup ! of Copy_. ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::ICopyL_' integer :: i,j,ier ! dummy variables integer :: num_indices ! Overlapping attribute index number integer :: aVsize ! The lsize of aVin and aVout integer :: num_inindices, num_outindices ! Number of matching indices in aV integer :: inxmin, outxmin, inx, outx ! Index variables logical :: TiListIsPresent ! true if list argument is present logical :: contiguous ! true if index segments are contiguous in memory logical :: usevector ! true if vector flag is present and true. character*7 :: data_flag ! character variable used as data type flag ! Overlapping attribute index storage arrays: integer, dimension(:), pointer :: aVinindices, aVoutindices ! Check the arguments aVsize = lsize_(aVin) if(lsize_(aVin) /= lsize_(aVout)) then write(stderr,'(2a)') myname_, & 'MCTERROR: Input aV and output aV do not have the same size' call die(myname_,'MCTERROR: Input aV and output aV & &do not have the same size',2) endif if(len_trim(iList) <= 0) return ! Copy the listed real attributes ! Index rList with the AttrVects call GetIndices(aVinindices,aVin%iList,trim(iList)) ! TiList is present if its provided and its length>0 TiListIsPresent = .false. if(present(TiList)) then if(len_trim(TiList) > 0) then TiListIsPresent = .true. endif endif if(TiListIsPresent) then call GetIndices(aVoutindices,aVout%iList,trim(TiList)) if(size(aVinindices) /= size(aVoutindices)) then call die(myname_,"Arguments iList and TiList do not& &contain the same number of items") endif else call GetIndices(aVoutindices,aVout%iList,trim(iList)) endif num_indices=size(aVoutindices) ! nothing to do if num_indices <=0 if (num_indices <= 0) then deallocate(aVinindices, aVoutindices, stat=ier) if(ier/=0) call die(myname_,"deallocate(aVinindices...)",ier) return endif ! check vector flag. usevector = .false. if (present(vector)) then if(vector) usevector = .true. endif ! Check if the indices are contiguous in memory for faster copy contiguous=.true. do i=2,num_indices if(aVinindices(i) /= aVinindices(i-1)+1) contiguous = .false. enddo if(contiguous) then do i=2,num_indices if(aVoutindices(i) /= aVoutindices(i-1)+1) contiguous=.false. enddo endif ! Start copying (arranged loop order optimized for xlf90) if(contiguous) then if(usevector) then outxmin=aVoutindices(1)-1 inxmin=aVinindices(1)-1 !$OMP PARALLEL DO PRIVAtE(i,j) do i=1,num_indices !CDIR SELECT(VECTOR) !DIR$ CONCURRENT do j=1,aVsize aVout%iAttr(outxmin+i,j) = aVin%iAttr(inxmin+i,j) enddo enddo else outxmin=aVoutindices(1)-1 inxmin=aVinindices(1)-1 !$OMP PARALLEL DO PRIVATE(j,i) do j=1,aVsize !DIR$ CONCURRENT do i=1,num_indices aVout%iAttr(outxmin+i,j) = aVin%iAttr(inxmin+i,j) enddo enddo endif else !$OMP PARALLEL DO PRIVATE(j,i,outx,inx) do j=1,aVsize !DIR$ CONCURRENT do i=1,num_indices outx=aVoutindices(i) inx=aVinindices(i) aVout%iAttr(outx,j) = aVin%iAttr(inx,j) enddo enddo endif deallocate(aVinindices, aVoutindices, stat=ier) if(ier/=0) call die(myname_,"deallocate(aVinindices...)",ier) end subroutine ICopyL_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: Copy_ - Copy Real and Integer Attributes from One AttrVect to Another ! ! !DESCRIPTION: ! This routine copies from input argment {\tt aVin} into the output ! {\tt 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. ! ! This routines combines the functions of {\tt RCopy\_}, {\tt RCopyL\_}, ! {\tt ICopy\_} and {\tt ICopyL\_}. If you know you only want to copy real ! attributes, use the {\tt RCopy} functions. If you know you only want to ! copy integer attributes, use the {\tt ICopy} functions. ! ! If the optional argument {\tt Vector} is present and true, the vector ! architecture-friendly portions of this routine will be invoked. ! ! If the optional argument {\tt sharedIndices} is present, it should be ! the result of the call {\tt SharedIndices\_(aVin, aVout, ! sharedIndices)}. Providing this argument speeds up this routine ! substantially. For example, you can compute a {\tt sharedIndices} ! structure once for a given pair of {\tt AttrVect}s, then use that same ! structure for all copies between those two {\tt AttrVect}s (although ! note that a different {\tt sharedIndices} variable would be needed if ! {\tt aVin} and {\tt aVout} were reversed). Note, however, that {\tt ! sharedIndices} is ignored if either {\tt rList} or {\tt iList} are ! given. ! ! {\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}. ! ! !INTERFACE: subroutine Copy_(aVin, aVout, rList, TrList, iList, TiList, vector, sharedIndices) ! ! !USES: ! use m_die , only : die, warn use m_stdio , only : stderr use m_List, only : GetSharedListIndices use m_List, only : GetIndices => get_indices implicit none ! !INPUT PARAMETERS: type(AttrVect), intent(in) :: aVin character(len=*), optional, intent(in) :: iList character(len=*), optional, intent(in) :: rList character(len=*), optional, intent(in) :: TiList character(len=*), optional, intent(in) :: TrList logical, optional, intent(in) :: vector type(AVSharedIndices), optional, intent(in) :: sharedIndices ! !OUTPUT PARAMETERS: type(AttrVect), intent(inout) :: aVout ! !REVISION HISTORY: ! 12Jun02 - R. Jacob - initial version. ! 13Jun02 - R. Jacob - copy shared attributes ! if no attribute lists are specified. ! 30Sep02 - R. Jacob - new argument order with all ! optional arguments last ! 19Feb02 - E. Ong - new implementation using ! new list function get_indices and faster memory copy ! 28Oct03 - R. Jacob - add optional vector ! argument to use vector-friendly code provided by Fujitsu ! 16Aug06 - R. Jacob - split into 4 routines: ! RCopy_,RCopyL_,ICopy_,ICopyL_ ! 28Apr11 - W.J. Sacks - added sharedIndices argument ! !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::Copy_' integer :: i,j,ier ! dummy variables integer :: num_indices ! Overlapping attribute index number integer :: aVsize ! The lsize of aVin and aVout integer :: num_inindices, num_outindices ! Number of matching indices in aV integer :: inxmin, outxmin, inx, outx ! Index variables logical :: TiListIsPresent, TrListIsPresent! true if list argument is present logical :: contiguous ! true if index segments are contiguous in memory logical :: usevector ! true if vector flag is present and true. character*7 :: data_flag ! character variable used as data type flag ! Overlapping attribute index storage arrays: integer, dimension(:), pointer :: aVinindices, aVoutindices ! Check the arguments aVsize = lsize_(aVin) if(lsize_(aVin) /= lsize_(aVout)) then write(stderr,'(2a)') myname_, & 'MCTERROR: Input aV and output aV do not have the same size' call die(myname_,'MCTERROR: Input aV and output aV & &do not have the same size',2) endif ! check vector flag. usevector = .false. if (present(vector)) then if(vector) usevector = .true. endif ! Copy the listed real attributes if(present(rList)) then ! TrList is present if it is provided and its length>0 TrListIsPresent = .false. if(present(TrList)) then if(len_trim(TrList) > 0) then TrListIsPresent = .true. endif endif if(present(sharedIndices)) then call warn(myname_,'Use of sharedIndices not implemented in RCopyL; & &ignoring sharedIndices',1) end if if(TrListIsPresent) then call RCopyL_(aVin,aVout,rList,TrList,vector=usevector) else call RCopyL_(aVin,aVout,rList,vector=usevector) endif endif ! if(present(rList) ! Copy the listed integer attributes if(present(iList)) then ! TiList is present if its provided and its length>0 TiListIsPresent = .false. if(present(TiList)) then if(len_trim(TiList) > 0) then TiListIsPresent = .true. endif endif if(present(sharedIndices)) then call warn(myname_,'Use of sharedIndices not implemented in ICopyL; & &ignoring sharedIndices',1) end if if(TiListIsPresent) then call ICopyL_(aVin,aVout,iList,TiList,vector=usevector) else call ICopyL_(aVin,aVout,iList,vector=usevector) endif endif ! if(present(iList)) ! If neither rList nor iList is present, copy shared attibutes ! from in to out. if( .not.present(rList) .and. .not.present(iList)) then if (present(sharedIndices)) then call RCopy_(aVin, Avout, vector=usevector, sharedIndices=sharedIndices%shared_real) call ICopy_(aVin, Avout, vector=usevector, sharedIndices=sharedIndices%shared_integer) else call RCopy_(aVin, Avout, vector=usevector) call ICopy_(aVin, Avout, vector=usevector) endif endif end subroutine Copy_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: Sort_ - Use Attributes as Keys to Generate an Index Permutation ! ! !DESCRIPTION: ! The subroutine {\tt Sort\_()} uses a list of keys defined by the {\tt List} ! {\tt key\_list}, searches for the appropriate integer or real attributes ! referenced by the items in {\tt key\_list} ( that is, it identifies the ! appropriate entries in {aV\%iList} and {\tt aV\%rList}), and then ! uses these keys to generate a permutation {\tt perm} that will put ! the entries of the attribute vector {\tt aV} in lexicographic order ! as defined by {\tt key\_list} (the ordering in {\tt key\_list} being from ! left to right. ! ! {\bf N.B.:} This routine will fail if {\tt aV\%iList} and ! {\tt aV\%rList} share one or more common entries. ! ! {\bf N.B.:} This routine will fail if one of the sorting keys presented is ! not present in {\tt aV\%iList} nor {\tt aV\%rList}. ! ! !INTERFACE: subroutine Sort_(aV, key_list, perm, descend, perrWith, dieWith) ! ! !USES: ! use m_String, only : String use m_String, only : String_tochar => tochar use m_String, only : String_clean => clean use m_List , only : List_allocated => allocated use m_List , only : List_index => index use m_List , only : List_nitem => nitem use m_List , only : List_get => get use m_die , only : die use m_stdio , only : stderr use m_SortingTools , only : IndexSet use m_SortingTools , only : IndexSort implicit none ! !INPUT PARAMETERS: ! type(AttrVect), intent(in) :: aV type(List), intent(in) :: key_list logical, dimension(:), optional, intent(in) :: descend character(len=*), optional, intent(in) :: perrWith character(len=*), optional, intent(in) :: dieWith ! !OUTPUT PARAMETERS: ! integer, dimension(:), pointer :: perm ! !REVISION HISTORY: ! 20Oct00 - J.W. Larson - initial prototype ! 25Apr01 - R.L. Jacob - add -1 to make a ! backwards loop go backwards ! 14Jun01 - J. Larson / E. Ong -- Fixed logic bug in REAL attribute ! sort (discovered by E. Ong), and cleaned up error / ! shutdown logic. !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::Sort_' ! local variables ! storage for key extracted from key_list: type(String) :: key ! number of keys, loop index, error flag, and length: integer :: nkeys, n, ierr, length ! key indices for av%rAttr and av%iAttr, respectively: integer, dimension(:), allocatable :: rIndex, iIndex ! copy of descend argument logical, dimension(:), allocatable :: descend_copy ! count the sorting keys: nkeys = List_nitem(key_list) ! Check the descend argument. Note: the unnecessary copy ! circumvents an optimization bug in the compaq compiler if(present(descend)) then if(size(descend)/=nkeys) then call die(myname_,"Size of descend argument is not equal & &to the number of keys") endif allocate(descend_copy(nkeys),stat=ierr) if(ierr/=0) call die(myname_,"allocate(descend_copy)",ierr) descend_copy=descend endif ! allocate and initialize rIndex and iIndex to ! zero (the null return values from the functions ! indexRA_() and indexIA_() ). allocate(rIndex(nkeys), iIndex(nkeys), stat=ierr) if(ierr/=0) call die(myname_,"allocate(rindex,iIndex)",ierr) rIndex = 0 iIndex = 0 ! Loop over the keys in the list, and identify the ! appropriate integer or real attribute, storing the ! attribute index in iIndex(:) or rIndex(:), respectively. do n = 1, nkeys ! grab the next key call List_get(key, n, key_list) ! determine wheter this key refers to an ! integer or real attribute: ! jwl commented out in favor of below code block unitl an error ! handling strategy is settled upon for indexIA_() and indexRA_(). ! rIndex(n) = indexRA_(aV, String_tochar(key), dieWith=myname_) ! iIndex(n) = indexIA_(aV, String_tochar(key), dieWith=myname_) if(List_allocated(aV%rList)) then rIndex(n) = List_index(aV%rList, String_tochar(key)) else rIndex(n) = 0 endif if(List_allocated(aV%iList)) then iIndex(n) = List_index(aV%iList, String_tochar(key)) else iIndex(n) = 0 endif ! If both rIndex(n) and iIndex(n) are greater than ! zero, then we have an integer attribute sharing ! the same name as a real attribute, and there is ! no clear path as to which one is the sort key. ! This is a fatal error that triggers shutdown. if ((rIndex(n) > 0) .and. (iIndex(n) > 0)) then if(.not.present(dieWith)) then if(present(perrWith)) write(stderr,'(4a)') myname, & ":: ambiguous key, ", perrWith, & " both iIndex(n) and rIndex(n) positive." call die(myname_,":: both iIndex(n) and rIndex(n) > 0.") else if(present(perrWith)) then write(stderr,'(4a)') myname_,":: ", perrWith, & " both iIndex(n) and rIndex(n) positive." endif call die(myname_,dieWith) endif endif ! If both rIndex(n) and iIndex(n) are nonpositive, ! then the requested sort key is not present in either ! aV%rList or aV%iList, and we cannot perform the sort. ! This is a fatal error that triggers shutdown. if ((rIndex(n) <= 0) .and. (iIndex(n) <= 0)) then if(.not.present(dieWith)) then if(present(perrWith)) write(stderr,'(4a)') myname,":: ", & perrWith, & " both iIndex(n) and rIndex(n) nonpositive" call die(myname_,":: both iIndex(n) and rIndex(n) <= 0.") else if(present(perrWith)) then write(stderr,'(4a)') myname_,":: ", perrWith, & " both iIndex(n) and rIndex(n) nonpositive" endif call die(myname_,dieWith) endif endif ! If only one of rIndex(n) or iIndex(n) is positive, ! set the other value to zero. if (iIndex(n) > 0) rIndex(n) = 0 if (rIndex(n) > 0) iIndex(n) = 0 ! Clean up temporary string -key- call String_clean(key) enddo ! do n=1,nkeys ! Now we have the locations of the keys in the integer and ! real attribute storage areas aV%iAttr and aV%rAttr, respectively. ! our next step is to construct and initialize the permutation ! array perm. First step--determine the length of aV using ! lsize_(): length = lsize_(aV) allocate(perm(length), stat=ierr) if(ierr/=0) call die(myname_,"allocate(perm)",ierr) ! Initialize perm(i)=i, for i=1,length call IndexSet(perm) ! Now we can perform the stable successive keyed sorts to ! transform perm into the permutation that will place the ! entries of the attribute arrays in the lexicographic order ! defined by key_list. This is achieved by successive calls to ! IndexSort(), but in reverse order to the order of the keys ! as they appear in key_list. do n=nkeys, 1, -1 if(iIndex(n) > 0) then if(present(descend)) then call IndexSort(length, perm, aV%iAttr(iIndex(n),:), & descend_copy(n)) else call IndexSort(length, perm, aV%iAttr(iIndex(n),:), & descend=.false.) endif ! if(present(descend)... else if(rIndex(n) > 0) then if(present(descend)) then call IndexSort(length, perm, aV%rAttr(rIndex(n),:), & descend_copy(n)) else call IndexSort(length, perm, aV%rAttr(rIndex(n),:), & descend=.false.) endif ! if(present(descend)... endif ! if (rIndex(n) > 0)... endif ! if (iIndex(n) > 0)... enddo ! Now perm(1:length) is the transformation we seek--we are ! finished. deallocate(iIndex, rIndex, stat=ierr) ! clean up allocated arrays. if(ierr/=0) call die(myname_,"deallocate(iIndex,rIndex)",ierr) if(present(descend)) deallocate(descend_copy,stat=ierr) if(ierr/=0) call die(myname_,"deallocate(descend_copy)",ierr) end subroutine Sort_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: Permute_ - Permute AttrVect Elements ! ! !DESCRIPTION: ! The subroutine {\tt Permute\_()} uses a a permutation {\tt perm} (which can ! be generated by the routine {\tt Sort\_()} in this module) to rearrange ! the entries in the attribute integer and real storage areas of the ! input attribute vector {\tt aV}--{\tt aV\%iAttr} and {\tt aV\%rAttr}, ! respectively. ! ! !INTERFACE: subroutine Permute_(aV, perm, perrWith, dieWith) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr use m_SortingTools , only : Permute implicit none ! !INPUT PARAMETERS: ! integer, dimension(:), intent(in) :: perm character(len=*), optional, intent(in) :: perrWith character(len=*), optional, intent(in) :: dieWith ! !INPUT/OUTPUT PARAMETERS: ! type(AttrVect), intent(inout) :: aV ! !REVISION HISTORY: ! 23Oct00 - J.W. Larson - initial prototype !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::Permute_' ! local variables integer :: i ! Check input arguments for compatibility--assure ! lsize_(aV) = size(perm); that is, make sure the ! index permutation is the same length as the vectors ! it will re-arrange. if (size(perm) /= lsize_(aV)) then if(.not.present(dieWith)) then if(present(perrWith)) write(stderr,'(4a,i8,a,i8)') myname, & ":: size mismatch, ", perrWith, & "size(perm)=",size(perm)," lsize_(aV)=",lsize_(aV) else write(stderr,'(4a,i8,a,i8)') myname, & ":: size mismatch, ", dieWith, & "size(perm)=",size(perm)," lsize_(aV)=",lsize_(aV) call die(dieWith) endif endif if(size(perm) == lsize_(aV)) then ! Permute integer attributes: if(nIAttr_(aV) /= 0) then do i=1,nIAttr_(aV) call Permute(aV%iAttr(i,:),perm,lsize_(aV)) end do endif ! Permute real attributes: if(nRAttr_(aV) /= 0) then do i=1,nRAttr_(aV) call Permute(aV%rAttr(i,:),perm,lsize_(aV)) end do endif endif end subroutine Permute_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: Unpermute_ - Unpermute AttrVect Elements ! ! !DESCRIPTION: ! The subroutine {\tt Unpermute\_()} uses a a permutation {\tt perm} (which can ! be generated by the routine {\tt Sort\_()} in this module) to rearrange ! the entries in the attribute integer and real storage areas of the ! input attribute vector {\tt aV}--{\tt aV\%iAttr} and {\tt aV\%rAttr}, ! respectively. This is meant to be called on an {\tt aV} that has already ! been permuted but it could also be used to perform the inverse operation ! implied by {\tt perm} on an unpermuted {\tt aV}. ! ! !INTERFACE: subroutine Unpermute_(aV, perm, perrWith, dieWith) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr use m_SortingTools , only : Unpermute implicit none ! !INPUT PARAMETERS: ! integer, dimension(:), intent(in) :: perm character(len=*), optional, intent(in) :: perrWith character(len=*), optional, intent(in) :: dieWith ! !INPUT/OUTPUT PARAMETERS: ! type(AttrVect), intent(inout) :: aV ! !REVISION HISTORY: ! 23Nov05 - R. Jacob - based on Permute !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::Unpermute_' ! local variables integer :: i ! Check input arguments for compatibility--assure ! lsize_(aV) = size(perm); that is, make sure the ! index permutation is the same length as the vectors ! it will re-arrange. if (size(perm) /= lsize_(aV)) then if(.not.present(dieWith)) then if(present(perrWith)) write(stderr,'(4a,i8,a,i8)') myname, & ":: size mismatch, ", perrWith, & "size(perm)=",size(perm)," lsize_(aV)=",lsize_(aV) else write(stderr,'(4a,i8,a,i8)') myname, & ":: size mismatch, ", dieWith, & "size(perm)=",size(perm)," lsize_(aV)=",lsize_(aV) call die(dieWith) endif endif if(size(perm) == lsize_(aV)) then ! Unpermute integer attributes: if(nIAttr_(aV) /= 0) then do i=1,nIAttr_(aV) call Unpermute(aV%iAttr(i,:),perm,lsize_(aV)) end do endif ! Permute real attributes: if(nRAttr_(aV) /= 0) then do i=1,nRAttr_(aV) call Unpermute(aV%rAttr(i,:),perm,lsize_(aV)) end do endif endif end subroutine Unpermute_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: SortPermute_ - In-place Lexicographic Sort of an AttrVect ! ! !DESCRIPTION: ! ! The subroutine {\tt SortPermute\_()} uses the routine {\tt Sort\_()} ! to create an index permutation {\tt perm} that will place the AttrVect ! entries in the lexicographic order defined by the keys in the List ! variable {\tt key\_list}. This permutation is then used by the routine ! {\tt Permute\_()} to place the AttreVect entries in lexicographic order. ! ! !INTERFACE: subroutine SortPermute_(aV, key_list, descend, perrWith, dieWith) ! ! !USES: ! use m_die , only : die use m_stdio , only : stderr implicit none ! !INPUT PARAMETERS: ! type(List), intent(in) :: key_list logical , dimension(:), optional, intent(in) :: descend character(len=*), optional, intent(in) :: perrWith character(len=*), optional, intent(in) :: dieWith ! !INPUT/OUTPUT PARAMETERS: ! type(AttrVect), intent(inout) :: aV ! !REVISION HISTORY: ! 24Oct00 - J.W. Larson - initial prototype !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::Permute_' ! local variables ! Permutation array pointer perm(:) integer, dimension(:), pointer :: perm ! Error flag ierr integer :: ierr ! Step One: Generate the index permutation perm(:) if(present(descend)) then call Sort_(aV, key_list, perm, descend, perrWith, dieWith) else call Sort_(aV, key_list, perm, perrWith=perrWith, & dieWith=dieWith) endif ! Step Two: Apply the index permutation perm(:) call Permute_(aV, perm, perrWith, dieWith) ! Step Three: deallocate temporary array used to ! store the index permutation (this was allocated ! in the routine Sort_() deallocate(perm, stat=ierr) end subroutine SortPermute_ ! Sorting: ! ! aV%iVect(:,:) = & ! aV%iVect((/(indx(i),i=1,lsize(aV))/),:) ! ! aV%iVect((/(indx(i),i=1,lsize(aV))/),:) = & ! aV%iVect(:,:) ! ! aV%iVect(:,ikx),aV%iVect(:,iks) ! ! !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Math and Computer Science Division, Argonne National Laboratory ! !BOP ------------------------------------------------------------------- ! ! !IROUTINE: aVaVSharedAttrIndexList_ - AttrVect shared attributes. ! ! !DESCRIPTION: {\tt aVaVSharedAttrIndexList\_()} takes a pair of ! user-supplied {\tt AttrVect} variables {\tt aV1} and {\tt aV2}, ! and for choice of either {\tt REAL} or {\tt INTEGER} attributes (as ! specified literally in the input {\tt CHARACTER} argument {\tt attrib}) ! returns the number of shared attributes {\tt NumShared}, and arrays of ! indices {\tt Indices1} and {\tt Indices2} to their storage locations ! in {\tt aV1} and {\tt aV2}, respectively. ! ! {\bf N.B.:} This routine returns two allocated arrays---{\tt Indices1(:)} ! and {\tt Indices2(:)}---which must be deallocated once the user no longer ! needs them. Failure to do this will create a memory leak. ! ! !INTERFACE: subroutine aVaVSharedAttrIndexList_(aV1, aV2, attrib, NumShared, & Indices1, Indices2) ! ! !USES: ! use m_stdio use m_die, only : MP_perr_die, die, warn use m_List, only : GetSharedListIndices implicit none ! !INPUT PARAMETERS: ! type(AttrVect), intent(in) :: aV1 type(AttrVect), intent(in) :: aV2 character(len=*), intent(in) :: attrib ! !OUTPUT PARAMETERS: ! integer, intent(out) :: NumShared integer, dimension(:), pointer :: Indices1 integer, dimension(:), pointer :: Indices2 ! !REVISION HISTORY: ! 07Feb01 - J.W. Larson - initial version !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::aVaVSharedAttrIndexList_' integer :: ierr ! Based on the value of the argument attrib, pass the ! appropriate pair of Lists for comparison... select case(trim(attrib)) case('REAL','real') call GetSharedListIndices(aV1%rList, aV2%rList, NumShared, & Indices1, Indices2) case('INTEGER','integer') call GetSharedListIndices(aV1%iList, aV2%iList, NumShared, & Indices1, Indices2) case default write(stderr,'(4a)') myname_,":: value of argument attrib=",attrib, & " not recognized. Allowed values: REAL, real, INTEGER, integer" ierr = 1 call die(myname_, 'invalid value for attrib', ierr) end select end subroutine aVaVSharedAttrIndexList_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Climate and Global Dynamics Division, National Center for Atmospheric Research ! !BOP ----------------------------------------------------------------------------- ! ! !IROUTINE: SharedIndices_ - AttrVect shared attributes and auxiliary information ! ! !DESCRIPTION: {\tt SharedIndices\_()} takes a pair of user-supplied ! {\tt AttrVect} variables {\tt aV1} and {\tt aV2}, and returns a ! structure of type {\tt AVSharedIndices} ({\tt sharedIndices}). This ! structure contains arrays of indices to the locations of the shared ! attributes, as well as auxiliary information. The structure contains ! information on both the {\tt REAL} and {\tt INTEGER} attributes. See ! documentation for the {\tt SharedIndicesOneType\_} subroutine for some ! additional details, as much of the work is done there. ! ! {\bf N.B.:} The returned structure, {\tt sharedIndices}, contains ! allocated arrays that must be deallocated once the user no longer ! needs them. This should be done through a call to {\tt ! cleanSharedIndices\_}. ! ! !INTERFACE: subroutine SharedIndices_(aV1, aV2, sharedIndices) implicit none ! !INPUT PARAMETERS: ! type(AttrVect), intent(in) :: aV1 type(AttrVect), intent(in) :: aV2 ! !INPUT/OUTPUT PARAMETERS: ! type(AVSharedIndices), intent(inout) :: sharedIndices ! !REVISION HISTORY: ! 28Apr11 - W.J. Sacks - initial version !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::SharedIndices_' call SharedIndicesOneType_(aV1, aV2, 'REAL', sharedIndices%shared_real) call SharedIndicesOneType_(aV1, aV2, 'INTEGER', sharedIndices%shared_integer) end subroutine SharedIndices_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Climate and Global Dynamics Division, National Center for Atmospheric Research ! !BOP ----------------------------------------------------------------------------- ! ! !IROUTINE: SharedIndicesOneType_ - AttrVect shared attributes and auxiliary information, for one data type ! ! !DESCRIPTION: {\tt SharedIndicesOneType\_()} takes a pair of ! user-supplied {\tt AttrVect} variables {\tt aV1} and {\tt aV2}, and ! for choice of either {\tt REAL} or {\tt INTEGER} attributes (as ! specified literally in the input {\tt CHARACTER} argument {\tt ! attrib}) returns a structure of type {\tt AVSharedIndicesOneType} ({\tt ! sharedIndices}). This structure contains arrays of indices to the ! locations of the shared attributes of the given type, as well as ! auxiliary information. ! ! The {\tt aVindices1} and {\tt aVindices2} components of {\tt ! sharedIndices} will be indices into {\tt aV1} and {\tt aV2}, ! respectively. ! ! {\bf N.B.:} The returned structure, {\tt sharedIndices}, contains ! allocated arrays that must be deallocated once the user no longer ! needs them. This should be done through a call to {\tt ! cleanSharedIndicesOneType\_}. Even if there are no attributes in ! common between {\tt aV1} and {\tt aV2}, {\tt sharedIndices} will still ! be initialized, and memory will still be allocated. Furthermore, if an ! already-initialized {\tt sharedIndices} variable is to be given new ! values, {\tt cleanSharedIndicesOneType\_} must be called before {\tt ! SharedIndicesOneType\_} is called a second time, in order to prevent a ! memory leak. ! ! !INTERFACE: subroutine SharedIndicesOneType_(aV1, aV2, attrib, sharedIndices) implicit none ! !INPUT PARAMETERS: ! type(AttrVect), intent(in) :: aV1 type(AttrVect), intent(in) :: aV2 character(len=*), intent(in) :: attrib ! !INPUT/OUTPUT PARAMETERS: ! type(AVSharedIndicesOneType), intent(inout) :: sharedIndices ! !REVISION HISTORY: ! 28Apr11 - W.J. Sacks - initial version !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::SharedIndicesOneType_' integer :: i ! Check appropriate attributes (real or integer) for matching indices call aVaVSharedAttrIndexList_(aV1, aV2, attrib, sharedIndices%num_indices, & sharedIndices%aVindices1, sharedIndices%aVindices2) sharedIndices%data_flag = attrib ! Check indices for contiguous segments in memory sharedIndices%contiguous=.true. do i=2,sharedIndices%num_indices if(sharedIndices%aVindices1(i) /= sharedIndices%aVindices1(i-1)+1) then sharedIndices%contiguous = .false. endif enddo if(sharedIndices%contiguous) then do i=2,sharedIndices%num_indices if(sharedIndices%aVindices2(i) /= sharedIndices%aVindices2(i-1)+1) then sharedIndices%contiguous=.false. endif enddo endif end subroutine SharedIndicesOneType_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Climate and Global Dynamics Division, National Center for Atmospheric Research ! !BOP ----------------------------------------------------------------------------- ! ! !IROUTINE: cleanSharedIndices_ - Deallocate allocated memory structures of an AVSharedIndices structure ! ! !DESCRIPTION: This routine deallocates the allocated memory structures ! of the input/output {\tt AVSharedIndicesOneType} argument {\tt ! sharedIndices}, if they are currently associated. It also resets ! other components of this structure to a default state. The success ! (failure) of this operation is signified by a zero (non-zero) value of ! the optional {\tt INTEGER} output argument {\tt stat}. If {\tt ! clean\_()} is invoked without supplying {\tt stat}, and any of the ! deallocation operations fail, the routine will terminate with an error ! message. If multiple errors occur, {\tt stat} will give the error ! condition for the last error. ! ! !INTERFACE: subroutine cleanSharedIndices_(sharedIndices, stat) implicit none ! !INPUT/OUTPUT PARAMETERS: ! type(AVSharedIndices), intent(inout) :: sharedIndices ! !OUTPUT PARAMETERS: ! integer, optional, intent(out) :: stat ! !REVISION HISTORY: ! 28Apr11 - W.J. Sacks - initial version !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::cleanSharedIndices_' integer :: ier if(present(stat)) stat=0 call cleanSharedIndicesOneType_(sharedIndices%shared_real, stat=ier) if(present(stat) .and. ier /= 0) then stat = ier end if call cleanSharedIndicesOneType_(sharedIndices%shared_integer, stat=ier) if(present(stat) .and. ier /= 0) then stat = ier end if end subroutine cleanSharedIndices_ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Climate and Global Dynamics Division, National Center for Atmospheric Research ! !BOP ----------------------------------------------------------------------------- ! ! !IROUTINE: cleanSharedIndicesOneType_ - Deallocate allocated memory structures of an AVSharedIndicesOneType structure ! ! !DESCRIPTION: This routine deallocates the allocated memory structures ! of the input/output {\tt AVSharedIndices} argument {\tt ! sharedIndices}, if they are currently associated. It also resets ! other components of this structure to a default state. The success ! (failure) of this operation is signified by a zero (non-zero) value of ! the optional {\tt INTEGER} output argument {\tt stat}. If {\tt ! clean\_()} is invoked without supplying {\tt stat}, and any of the ! deallocation operations fail, the routine will terminate with an error ! message. If multiple errors occur, {\tt stat} will give the error ! condition for the last error. ! ! !INTERFACE: subroutine cleanSharedIndicesOneType_(sharedIndices, stat) ! ! !USES: ! use m_die, only : die implicit none ! !INPUT/OUTPUT PARAMETERS: ! type(AVSharedIndicesOneType), intent(inout) :: sharedIndices ! !OUTPUT PARAMETERS: ! integer, optional, intent(out) :: stat ! !REVISION HISTORY: ! 28Apr11 - W.J. Sacks - initial version !EOP ___________________________________________________________________ character(len=*),parameter :: myname_=myname//'::cleanSharedIndicesOneType_' integer :: ier if(present(stat)) stat=0 if(associated(sharedIndices%aVindices1)) then deallocate(sharedIndices%aVindices1,stat=ier) if (ier /= 0) then if(present(stat)) then stat=ier else call die(myname_,'deallocate(sharedIndices%aVindices1)',ier) endif endif endif if(associated(sharedIndices%aVindices2)) then deallocate(sharedIndices%aVindices2,stat=ier) if (ier /= 0) then if(present(stat)) then stat=ier else call die(myname_,'deallocate(sharedIndices%aVindices2)',ier) endif endif endif ! Reset other components to default values sharedIndices%num_indices = 0 sharedIndices%contiguous = .false. sharedIndices%data_flag = ' ' end subroutine cleanSharedIndicesOneType_ end module m_AttrVect !.