source: CPL/oasis3-mct/branches/OASIS3-MCT_2.0_branch/lib/mct/mct/m_AttrVect.F90

Last change on this file was 4775, checked in by aclsce, 5 years ago
  • Imported oasis3-mct from Cerfacs svn server (not suppotred anymore).

The version has been extracted from https://oasis3mct.cerfacs.fr/svn/branches/OASIS3-MCT_2.0_branch/oasis3-mct@1818

File size: 133.6 KB
Line 
1!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2!     Math and Computer Science Division, Argonne National Laboratory  !
3!-----------------------------------------------------------------------
4! CVS m_AttrVect.F90,v 1.86 2012-04-27 20:01:04 jacob Exp
5! CVS MCT_2_8_0
6!BOP -------------------------------------------------------------------
7!
8! !MODULE: m_AttrVect - Multi-field Storage
9!
10! !DESCRIPTION:
11!
12! An {\em attribute vector} is a scheme for storing bundles of integer
13! and real data vectors, indexed by the names of the fields stored in
14! {\tt List} format (see the mpeu module {\tt m\_List} for more
15! information about the {\tt List} datatype).  The ordering of the
16! fieldnames in the integer and real attribute {\tt List} components
17! ({\tt AttrVect\%iList} and {\tt AttrVect\%rList}, respectively)
18! corresponds to the storage order of the attributes in their respective
19! data buffers (the components {\tt AttrVect\%iAttr(:,:)} and
20! {\tt AttrVect\%rAttr(:,:)}, respectively).   The organization of
21! the fieldnames in {\tt List} format, along with the direct mapping
22! between {\tt List} items and locations in the data buffer, allows
23! the user to have {\em random access} to the field data.  This
24! approach also allows the user to set the number and the names of fields
25! stored in an {\tt AttrVect} at run-time. 
26!
27! The {\tt AttrVect} stores field data in a {\em pointwise} fashion
28! (that is, the data are grouped so that all the integer or real data
29! associated with an individual point are adjacent to each other in memory.
30! This amounts to the having the integer and real field data arrays in
31! the {\tt AttrVect} (the components {\tt AttrVect\%iAttr(:,:)} and
32! {\tt AttrVect\%rAttr(:,:)}, respectively) having the attribute index
33! as the major (or fastest-varying) index.  A prime example of this is
34! observational data input to a data assimilation system.  In the Model
35! Coupling Toolkit, this datatype is the fundamental type for storing
36! field data exchanged by component models, and forms a basis for other
37! MCT datatypes that encapsulate time accumulation/averaging buffers (the
38! {\tt Accumulator} datatype defined in the module {\tt m\_Accumulator}),
39! coordinate grid information (the {\tt GeneralGrid} datatype defined in
40! the module {\tt m\_GeneralGrid}), and sparse interpolation matrices
41! (the {\tt SparseMatrix} datatype defined in the module
42! {\tt m\_SparseMatrix}).
43!
44! The attribute vector is implemented in Fortran 90 using the
45! {\tt AttrVect} derived type.  This module contains the definition
46! of the {\tt AttrVect}, and the numerous methods that service it.  There
47! are a number of initialization (creation) schemes, and a routine for
48! zeroing out the elements of an {\tt AttrVect}.  There is a method
49! to {\em clean} up allocated memory used by an {\tt AttrVect}
50! (destruction).  There are numerous query methods that return:  the
51! number of datapoints (or {\em length}; the numbers of integer and
52! real attributes; the data buffer index of a given real or integer
53! attribute; and return the lists of real and integer attributes.  There
54! also exist methods for exporting a given attribute as a one-dimensional
55! array and importing a given attribute from a one-dimensional array. 
56! There is a method for copying attributes from one {\tt AttrVect} to
57! another.  There is also a method for cross-indexing the attributes in
58! two {\tt AttrVect} variables.  In addition, there are methods that
59! return those cross-indexed attributes along with some auxiliary data
60! in a {\tt AVSharedIndicesOneType} or {\tt AVSharedIndices} structure.
61! Finally, there are methods for sorting and permuting {\tt AttrVect}
62! entries using a MergeSort scheme keyed by the attributes of the {\tt
63! AttrVect}.
64!
65! !INTERFACE:
66
67 module m_AttrVect
68!
69! !USES:
70!
71      use m_realkinds,only : SP,DP,FP          ! Real types definitions
72
73      use m_List, only : List   ! Support for rList and iList components.
74
75      implicit none
76
77      private   ! except
78
79! !PUBLIC TYPES:
80
81      public :: AttrVect        ! The class data structure
82      public :: AVSharedIndicesOneType ! Data structure recording shared indices between
83                                       ! two attribute vectors, for a single data type
84                                       ! (e.g., shared real attributes)
85      public :: AVSharedIndices ! Data structure recording shared indices between two
86                                ! attribute vectors, for all data types
87
88    type AttrVect
89#ifdef SEQUENCE
90      sequence
91#endif
92      type(List) :: iList
93      type(List) :: rList
94      integer,dimension(:,:),pointer :: iAttr
95      real(FP) ,dimension(:,:),pointer :: rAttr
96    end type AttrVect
97
98    type AVSharedIndicesOneType
99       integer :: num_indices           ! number of shared items
100       logical :: contiguous            ! true if index segments are contiguous in memory
101       character*7 :: data_flag         ! data type flag (e.g., 'REAL' or 'INTEGER')
102
103       ! arrays of indices to storage locations of shared attributes between the two
104       ! attribute vectors:
105       integer, dimension(:), pointer :: aVindices1
106       integer, dimension(:), pointer :: aVindices2
107    end type AVSharedIndicesOneType
108
109    type AVSharedIndices
110       type(AVSharedIndicesOneType) :: shared_real     ! shared indices of type REAL
111       type(AVSharedIndicesOneType) :: shared_integer  ! shared indices of type INTEGER
112    end type AVSharedIndices
113       
114
115! !PUBLIC MEMBER FUNCTIONS:
116
117      public :: init            ! create a local vector
118      public :: clean           ! clean the local vector
119      public :: zero            ! zero the local vector
120      public :: lsize           ! size of the local vector
121      public :: nIAttr          ! number of integer attributes on local
122      public :: nRAttr          ! number of real attributes on local
123      public :: indexIA         ! index the integer attributes
124      public :: indexRA         ! index the real attributes
125      public :: getIList        ! return list of integer attributes
126      public :: getRList        ! return list of real attributes
127      public :: exportIList     ! export INTEGER attibute List
128      public :: exportRList     ! export REAL attibute List
129      public :: exportIListToChar ! export INTEGER attibute List as Char
130      public :: exportRListToChar ! export REAL attibute List as Char
131      public :: appendIAttr     ! append INTEGER attribute List
132      public :: appendRAttr     ! append REAL attribute List
133      public :: exportIAttr     ! export INTEGER attribute to vector
134      public :: exportRAttr     ! export REAL attribute to vector
135      public :: importIAttr     ! import INTEGER attribute from vector
136      public :: importRAttr     ! import REAL attribute from vector
137      public :: Copy            ! copy attributes from one Av to another
138      public :: RCopy           ! copy real attributes from one Av to another
139      public :: ICopy           ! copy integer attributes from one Av to another
140      public :: Sort            ! sort entries, and return permutation
141      public :: Permute         ! permute entries
142      public :: Unpermute       ! Unpermute entries
143      public :: SortPermute     ! sort and permute entries
144      public :: SharedAttrIndexList  ! Cross-indices of shared
145                                     ! attributes of two AttrVects
146      public :: SharedIndices        ! Given two AttrVects, create an AVSharedIndices structure
147      public :: SharedIndicesOneType ! Given two AttrVects, create an
148                                     ! AVSharedIndicesOneType structure for a single type
149      public :: cleanSharedIndices   ! clean a AVSharedIndices structure
150      public :: cleanSharedIndicesOneType  ! clean a AVSharedIndicesOneType structure
151
152
153    interface init   ; module procedure &
154       init_,  &
155       initv_, &
156       initl_
157    end interface
158    interface clean  ; module procedure clean_  ; end interface
159    interface zero  ; module procedure zero_  ; end interface
160    interface lsize  ; module procedure lsize_  ; end interface
161    interface nIAttr ; module procedure nIAttr_ ; end interface
162    interface nRAttr ; module procedure nRAttr_ ; end interface
163    interface indexIA; module procedure indexIA_; end interface
164    interface indexRA; module procedure indexRA_; end interface
165    interface getIList; module procedure getIList_; end interface
166    interface getRList; module procedure getRList_; end interface
167    interface exportIList; module procedure exportIList_; end interface
168    interface exportRList; module procedure exportRList_; end interface
169    interface exportIListToChar
170       module procedure exportIListToChar_
171    end interface
172    interface exportRListToChar
173       module procedure exportRListToChar_
174    end interface
175    interface appendIAttr  ; module procedure appendIAttr_  ; end interface
176    interface appendRAttr  ; module procedure appendRAttr_  ; end interface
177    interface exportIAttr; module procedure exportIAttr_; end interface
178    interface exportRAttr; module procedure &
179       exportRAttrSP_, &
180       exportRAttrDP_
181    end interface
182    interface importIAttr; module procedure importIAttr_; end interface
183    interface importRAttr; module procedure &
184         importRAttrSP_, &
185         importRAttrDP_
186    end interface
187    interface Copy    ; module procedure Copy_    ; end interface
188    interface RCopy   ; module procedure  &
189         RCopy_, &
190         RCopyL_
191    end interface
192    interface ICopy   ; module procedure  &
193          ICopy_, &
194          ICopyL_
195    end interface
196    interface Sort    ; module procedure Sort_    ; end interface
197    interface Permute ; module procedure Permute_ ; end interface
198    interface Unpermute ; module procedure Unpermute_ ; end interface
199    interface SortPermute ; module procedure SortPermute_ ; end interface
200    interface SharedAttrIndexList ; module procedure &
201        aVaVSharedAttrIndexList_ 
202    end interface
203    interface SharedIndices ; module procedure SharedIndices_ ; end interface
204    interface SharedIndicesOneType ; module procedure SharedIndicesOneType_ ; end interface
205    interface cleanSharedIndices ; module procedure cleanSharedIndices_ ; end interface
206    interface cleanSharedIndicesOneType ; module procedure cleanSharedIndicesOneType_ ; end interface
207
208! !REVISION HISTORY:
209! 10Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
210! 10Oct00 - J.W. Larson <larson@mcs.anl.gov> - made getIList
211!           and getRList functions public and added appropriate
212!           interface definitions
213! 20Oct00 - J.W. Larson <larson@mcs.anl.gov> - added Sort,
214!           Permute, and SortPermute functions.
215! 09May01 - J.W. Larson <larson@mcs.anl.gov> - added initl_().
216! 19Oct01 - J.W. Larson <larson@mcs.anl.gov> - added routines
217!           exportIattr(), exportRAttr(), importIAttr(),
218!           and importRAttr().  Also cleaned up module and
219!           routine prologues.
220! 13Dec01 - J.W. Larson <larson@mcs.anl.gov> - made importIAttr()
221!           and importRAttr() public (bug fix).
222! 14Dec01 - J.W. Larson <larson@mcs.anl.gov> - added exportIList()
223!           and exportRList().
224! 14Feb02 - J.W. Larson <larson@mcs.anl.gov> - added CHARCTER
225!           functions exportIListToChar() and exportRListToChar()
226! 26Feb02 - J.W. Larson <larson@mcs.anl.gov> - corrected of usage
227!           of m_die routines throughout this module.
228! 16Apr02 - J.W. Larson <larson@mcs.anl.gov> - added the method
229!           LocalReduce(), and the public data members AttrVectSUM,
230!           AttrVectMIN, and AttrVectMAX.
231! 7May02 - J.W. Larson <larson@mcs.anl.gov> - Refactoring.  Moved
232!          LocalReduce() and the public data members AttrVectSUM,
233!           AttrVectMIN, and AttrVectMAX to a new module named
234!           m_AttrVectReduce.
235! 12Jun02 - R.L. Jacob <jacob@mcs.anl.gov> - add Copy function
236! 13Jun02 - R.L. Jacob <jacob@mcs.anl.gov> - move aVavSharedAttrIndexList
237!           to this module from old m_SharedAttrIndicies
238! 28Apr11 - W.J. Sacks <sacks@ucar.edu> - added AVSharedIndices and
239!           AVSharedIndicesOneType derived types, and associated
240!           subroutines
241! 10Apr12 - W.J. Sacks <sacks@ucar.edu> - modified AVSharedIndices code
242!           to be Fortran-90 compliant
243!EOP ___________________________________________________________________
244
245  character(len=*),parameter :: myname='MCT::m_AttrVect'
246
247 contains
248
249!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
250!     Math and Computer Science Division, Argonne National Laboratory  !
251!BOP -------------------------------------------------------------------
252!
253! !IROUTINE: init_ - Initialize an AttrVect Given Attribute Lists and Length
254!
255! !DESCRIPTION:
256! This routine creates an {\tt AttrVect} (the output argument {\tt aV})
257! using the optional input {\tt CHARACTER} arguments {\tt iList}, and
258! {\tt rList} to define its integer and real attributes, respectively.
259! The optional input {\tt INTEGER} argument {\tt lsize} defines the
260! number of points for which we are storing attributes, or the
261! {\em length} of {\tt aV}.  The expected form for the arguments
262! {\tt iList} and {\tt rList} are colon-delimited strings where each
263! substring defines an attribute.  Suppose we wish to store {\tt N}
264! observations that have the real attributes {\tt 'latitude'},
265! {\tt 'longitude'}, {\tt pressure}, {\tt 'u-wind'}, and
266! {\tt 'v-wind'}.  Suppose we also wish to store the integer
267! attributes {\tt 'hour'}, {\tt 'day'}, {\tt 'month'}, {\tt 'year'},
268! and {\tt 'data source'}.  This can be accomplished by invoking
269! {\tt init\_()} as follows:
270! \begin{verbatim}
271! call init_(aV, 'hour:day:month:year:data source', &
272!            'latitude:longitude:pressure:u-wind:v-wind', N)
273! \end{verbatim}
274! The resulting {\tt AttrVect} {\tt aV} will have five integer
275! attributes, five real attributes, and length {\tt N}.
276!
277! !INTERFACE:
278
279 subroutine init_(aV, iList, rList, lsize)
280!
281! !USES:
282!
283      use m_List, only : List
284      use m_List, only : init,nitem
285      use m_List, only : List_nullify => nullify
286      use m_mall
287      use m_die
288
289      implicit none
290
291! !INPUT PARAMETERS:
292!
293      character(len=*), optional, intent(in)  :: iList
294      character(len=*), optional, intent(in)  :: rList
295      integer,          optional, intent(in)  :: lsize
296
297! !OUTPUT PARAMETERS:
298!
299      type(AttrVect),             intent(out) :: aV
300
301! !REVISION HISTORY:
302! 09Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
303! 09Oct01 - J.W. Larson <larson@mcs.anl.gov> - added feature to
304!           nullify all pointers before usage.  This was done to
305!           accomodate behavior of the f90 ASSOCIATED intrinsic
306!           function on the AIX platform.
307! 07Dec01 - E.T. Ong <eong@mcs.anl.gov> - added support for
308!           intialization with blank character strings for iList
309!           and rList
310!EOP ___________________________________________________________________
311!
312  character(len=*),parameter :: myname_=myname//'::init_'
313  integer :: nIA,nRA,n,ier
314
315       ! Initially, nullify all pointers in the AttrVect aV:
316
317  nullify(aV%iAttr)
318  nullify(aV%rAttr)
319  call List_nullify(aV%iList)
320  call List_nullify(aV%rList)
321
322  if(present(rList)) then
323     if(len_trim(rList) > 0) then
324        call init(aV%rList,rList)       ! init.List()
325     endif
326  endif
327
328  if(present(iList)) then
329     if(len_trim(iList) > 0) then
330        call init(aV%iList,iList)       ! init.List()
331     endif
332  endif
333
334  nIA=nitem(aV%iList)           ! nitem.List()
335  nRA=nitem(aV%rList)           ! nitem.List()
336
337  n=0
338  if(present(lsize)) n=lsize
339
340  allocate( aV%iAttr(nIA,n),aV%rAttr(nRA,n),    stat=ier)
341  if(ier /= 0) call die(myname_,'allocate()',ier)
342
343#ifdef MALL_ON
344        call mall_ci(size(transfer(aV%iAttr,(/1/)),myname_)
345        call mall_ci(size(transfer(aV%rAttr,(/1/)),myname_)
346#endif
347
348 end subroutine init_
349
350!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
351!     Math and Computer Science Division, Argonne National Laboratory  !
352!BOP -------------------------------------------------------------------
353!
354! !IROUTINE: initv_ - Initialize One AttrVect from Another
355!
356! !DESCRIPTION:  This routine takes an input {\tt AttrVect} argument
357! {\tt bV}, and uses its attribute list information to create an output
358! {\tt AttrVect} variable {\tt aV}.  The length of {\tt aV} is defined
359! by the input {\tt INTEGER} argument {\tt lsize}. 
360!
361! !INTERFACE:
362
363 subroutine initv_(aV, bV, lsize)
364!
365! !USES:
366!
367      use m_String, only : String,char
368      use m_String, only : String_clean => clean   
369      use m_List,   only : get
370      use m_List,   only : List_nullify => nullify
371      use m_die
372      use m_stdio
373
374      implicit none
375
376! !INPUT PARAMETERS:
377!
378      type(AttrVect),intent(in)  :: bV
379      integer,       intent(in)  :: lsize
380
381! !OUTPUT PARAMETERS:
382!
383      type(AttrVect),intent(out) :: aV
384
385! !REVISION HISTORY:
386! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
387! 17May01 - R. Jacob <jacob@mcs.anl.gov> - add a check to see if
388!           input argument has been defined.  SGI will dump
389!           core if its not.
390! 10Oct01 - J. Larson <larson@mcs.anl.gov> - Nullify all pointers
391!           in ouput AttrVect aV before initializing aV.
392! 19Sep08 - J. Wolfe <jwolfe@ucar.edu> - plug memory leak from not deallocating
393!           strings.
394!EOP ___________________________________________________________________
395
396  character(len=*),parameter :: myname_=myname//'::initv_'
397  type(String) :: iLStr,rLStr
398
399        ! Step One:  Nullify all pointers in aV.  We will set
400        ! only the pointers we really need for aV based on those
401        ! currently ASSOCIATED in bV.
402
403  call List_nullify(aV%iList)
404  call List_nullify(aV%rList)
405  nullify(aV%iAttr)
406  nullify(aV%rAttr)
407
408        ! Convert the two Lists to two Strings
409
410  if(.not.associated(bv%iList%bf) .and. & 
411       .not.associated(bv%rList%bf)) then
412     write(stderr,'(2a)')myname_, &
413      'MCTERROR:  Trying to initialize a new AttrVect off an undefined AttrVect'
414      call die(myname_,'undefined input argument',0)
415  endif
416
417  if(associated(bv%iList%bf)) then
418     call get(iLStr,bv%iList)
419  endif
420
421  if(associated(bv%rList%bf)) then
422     call get(rLStr,bv%rList)
423  endif
424
425       ! Initialize the AttrVect aV depending on which parts of
426       ! the input bV are valid:
427
428  if(associated(bv%iList%bf) .and. associated(bv%rList%bf)) then
429     call init_(aV,iList=char(iLStr),rList=char(rLStr),lsize=lsize)
430  endif
431  if(.not.associated(bv%iList%bf) .and. associated(bv%rList%bf)) then
432     call init_(aV,rList=char(rLStr),lsize=lsize)
433  endif
434  if(associated(bv%iList%bf) .and. .not.associated(bv%rList%bf)) then
435     call init_(aV,iList=char(iLStr),lsize=lsize)
436  endif
437
438  if(associated(bv%iList%bf)) then 
439     call String_clean(iLStr)       
440  endif                             
441  if(associated(bv%rList%bf)) then 
442     call String_clean(rLStr)       
443  endif                             
444
445 end subroutine initv_
446
447!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
448!     Math and Computer Science Division, Argonne National Laboratory  !
449!BOP -------------------------------------------------------------------
450!
451! !IROUTINE: initl_ - Initialize an AttrVect Using the List Type
452!
453! !DESCRIPTION:  This routine initializes an {\tt AttrVect} directly
454! from input {\tt List} data type arguments {\tt iList} and {\tt rList}
455! (see the module {\tt m\_List} in mpeu for further details), and an
456! input length {\tt lsize}.  The resulting {\tt AttrVect} is returned in
457! the argument {\tt aV}.
458!
459! {\bf N.B.}:  If the user supplies an empty list for the arguments
460! {\tt iList} ({\tt rList}), then {\tt aV} will be created only with
461! {\tt REAL} ({\tt INTEGER}) attributes.  If both arguments {\tt iList}
462! and {\tt rList} are empty, the routine will terminate execution and
463! report an error.
464!
465! {\bf N.B.}:  The outcome of this routine, {\tt aV} represents
466! allocated memory.  When this {\tt AttrVect} is no longer needed,
467! it must be deallocated by invoking the routine {\tt AttrVect\_clean()}. 
468! Failure to do so will spawn a memory leak.
469!
470! !INTERFACE:
471
472 subroutine initl_(aV, iList, rList, lsize)
473
474!
475! !USES:
476!
477      use m_die
478      use m_stdio
479
480      use m_String, only : String
481      use m_String, only : String_clean => clean
482      use m_String, only : String_toChar => toChar
483
484      use m_List, only : List
485      use m_List, only : List_nitem => nitem
486      use m_List, only : List_exportToChar => exportToChar
487
488      implicit none
489
490! !INPUT PARAMETERS:
491!
492      type(List),  intent(in)  :: iList
493      type(List),  intent(in)  :: rList
494      integer,     intent(in)  :: lsize
495
496! !OUTPUT PARAMETERS:
497!
498      type(AttrVect), intent(out) :: aV
499
500! !REVISION HISTORY:
501! 09May98 - J.W. Larson <larson@mcs.anl.gov> - initial version.
502! 08Aug01 - E.T. Ong <eong@mcs.anl.gov> - change list assignment(=)
503!           to list copy to avoid compiler errors with pgf90.
504! 10Oct01 - J. Larson <larson@mcs.anl.gov> - Nullify all pointers
505!           in ouput AttrVect aV before initializing aV.  Also,
506!           greater caution taken regarding validity of input
507!           arguments iList and rList.
508! 15May08 - J. Larson <larson@mcs.anl.gov> - Simplify to use
509!           the init_ routine.  Better argument checking.
510!EOP ___________________________________________________________________
511!
512  character(len=*),parameter :: myname_=myname//'::initl_'
513
514  ! Basic argument sanity checks:
515
516  if (List_nitem(iList) < 0) then
517     write(stderr,'(2a,i8,a)') myname_, &
518          ':: FATAL:  List argument iList has a negative number ( ',List_nitem(iList), &
519          ' ) of attributes!'
520     call die(myname_)
521  endif
522
523  if (List_nitem(rList) < 0) then
524     write(stderr,'(2a,i8,a)') myname_, &
525          ':: FATAL:  List argument rList has a negative number ( ',List_nitem(rList), &
526          ' ) of attributes!'
527     call die(myname_)
528  endif
529
530  if ((List_nitem(iList) > 0) .and. (List_nitem(rList) > 0)) then
531
532     call init_(aV, List_exportToChar(iList), List_exportToChar(rList), lsize)
533
534  else ! Then solely REAL or solely INTEGER attributes:
535
536     if (List_nitem(iList) > 0) then ! solely INTEGER attributes
537               
538        call init_(aV, iList=List_exportToChar(iList), lsize=lsize)
539
540     endif ! if (List_nitem(iList) > 0) then...
541
542     if (List_nitem(rList) > 0) then ! solely REAL attributes
543               
544        call init_(aV, rList=List_exportToChar(rList), lsize=lsize)
545
546     endif ! if (List_nitem(rList) > 0) then...
547
548  endif ! if ((List_nitem(iList) > 0) .and. (List_nitem(rList) > 0)) then...
549
550 end subroutine initl_
551
552!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
553!     Math and Computer Science Division, Argonne National Laboratory  !
554!BOP -------------------------------------------------------------------
555!
556! !IROUTINE: clean_ - Deallocate Allocated Memory Structures of an AttrVect
557!
558! !DESCRIPTION:
559! This routine deallocates the allocated memory structures of the
560! input/output {\tt AttrVect} argument {\tt aV}.  This amounts to
561! cleaning the {\tt List} structures {\tt aV\%iList} and {\tt av\%rList},
562! and deallocating the arrays {\tt aV\%iAttr(:,:)} and
563! {\tt aV\%rAttr(:,:)}.  The success (failure) of this operation is
564! signified by a zero (non-zero) value of the optional {\tt INTEGER}
565! output argument {\tt stat}.  If {\tt clean\_()} is invoked without
566! supplying {\tt stat}, and any of the deallocation operations fail,
567! the routine will terminate with an error message.
568!
569! !INTERFACE:
570
571 subroutine clean_(aV, stat)
572!
573! !USES:
574!
575      use m_mall
576      use m_stdio
577      use m_die
578      use m_List, only : List_clean => clean
579
580      implicit none
581
582! !INPUT/OUTPUT PARAMETERS:
583!
584      type(AttrVect),    intent(inout) :: aV
585
586! !OUTPUT PARAMETERS:
587!
588      integer, optional, intent(out)   :: stat
589
590! !REVISION HISTORY:
591! 09Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
592! 10Oct01 - J. Larson <larson@mcs.anl.gov> - various fixes to
593!           prevent deallocation of UNASSOCIATED pointers.
594! 01Mar01 - E.T. Ong <eong@mcs.anl.gov> - removed dies to prevent
595!           crashes when cleaning uninitialized attrvects. Added
596!           optional stat argument.
597!EOP ___________________________________________________________________
598
599  character(len=*),parameter :: myname_=myname//'::clean_'
600  integer :: ier
601
602        ! Note that an undefined pointer may either crash the process
603        ! or return either .true. or .false. to the associated() test.
604        ! One should therefore avoid using the function on an
605        ! undefined pointer.
606
607        ! Clean up INTEGER attribute list:
608
609  if(present(stat)) stat=0
610 
611  if(associated(aV%iList%bf)) then
612
613     if(present(stat)) then
614        call List_clean(aV%iList,ier)
615        if(ier/=0) stat=ier
616     else
617        call List_clean(aV%iList)
618     endif
619
620  endif
621
622        ! Clean up REAL attribute list:
623
624  if(associated(aV%rList%bf)) then
625
626     if(present(stat)) then
627        call List_clean(aV%rList,ier)
628        if(ier/=0) stat=ier
629     else
630        call List_clean(aV%rList)
631     endif
632
633  endif
634
635        ! Clean up INTEGER attributes:
636
637  if(associated(aV%iAttr)) then
638
639#ifdef MALL_ON
640     call mall_co(size(transfer(aV%iAttr,(/1/)),myname_)
641#endif
642
643     deallocate(aV%iAttr,stat=ier)
644
645     if(ier /= 0) then
646        if(present(stat)) then
647           stat=ier
648        else
649           call warn(myname_,'deallocate(aV%iAttr)',ier)
650        endif
651     endif
652
653  endif ! if(associated(aV%iAttr))...
654 
655        ! Clean up REAL attributes:
656
657  if(associated(aV%rAttr)) then
658
659#ifdef MALL_ON
660     call mall_co(size(transfer(aV%rAttr,(/1/)),myname_)
661#endif
662
663     deallocate(aV%rAttr,stat=ier)
664
665     if(ier /= 0) then
666        if(present(stat)) then
667           stat=ier
668        else
669           call warn(myname_,'deallocate(aV%rAttr)',ier)
670        endif
671     endif
672
673  endif ! if(associated(aV%rAttr))...
674
675
676 end subroutine clean_
677
678!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
679!     Math and Computer Science Division, Argonne National Laboratory  !
680!BOP -------------------------------------------------------------------
681!
682! !IROUTINE: lsize_ - Length of an AttrVect
683!
684! !DESCRIPTION:
685! This function returns the number of elements, or {\em length} of the
686! input {\tt AttrVect} argument {\tt aV}.  This function examines the
687! length of the second dimension of the arrays {\tt aV\%iAttr(:,:)}
688! and {\tt aV\%rAttr(:,:)}.  If neither {\tt aV\%iAttr(:,:)} nor
689! {\tt aV\%rAttr(:,:)} are associated, then ${\tt lsize\_(aV)} = 0$.
690! If {\tt aV\%iAttr(:,:)} is associated, but {\tt aV\%rAttr(:,:)} is
691! not, then ${\tt lsize\_(aV)} = {\tt size(aV\%iAttr,2)}$. If
692! {\tt aV\%iAttr(:,:)} is not associated, but {\tt aV\%rAttr(:,:)} is,
693! then ${\tt lsize\_(aV)} = {\tt size(aV\%rAttr,2)}$. If both
694! {\tt aV\%iAttr(:,:)} and {\tt aV\%rAttr(:,:)} are associated, the
695! function {\tt lsize\_()} will do one of two things:  If
696! ${\tt size(aV\%iAttr,2)} = {\tt size(aV\%rAttr,2)}$, this equal value
697! will be returned.  If ${\tt size(aV\%iAttr,2)} \neq
698! {\tt size(aV\%rAttr,2)}$, termination with an error message will occur.
699!
700! !INTERFACE:
701
702 integer function lsize_(aV)
703
704! !USES:
705
706     use m_List,  only : List
707     use m_List,  only : List_allocated => allocated
708
709     use m_stdio, only : stderr
710     use m_die
711 
712     implicit none
713
714! !INPUT PARAMETERS:
715!
716      type(AttrVect), intent(in) :: aV
717
718! !REVISION HISTORY:
719! 09Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
720! 10Oct01 - J. Larson <larson@mcs.anl.gov> - made code more robust
721!           to handle cases where the length of either aV%iAttr or
722!           aV%rAttr is zero, but the other is positive.
723!EOP ___________________________________________________________________
724
725  character(len=*),parameter :: myname_=myname//'::lsize_'
726  integer :: iLength, rLength
727
728        ! One should try to avoid using this function on an undefined
729        ! or disassocated pointer.  However, it is understandable
730        ! that an undefined or disassocated pointer has a size 0, if
731        ! the associated() test sucesses.
732
733  lsize_=0
734
735  if(List_allocated(aV%iList) .and. associated(aV%iAttr)) then
736     iLength = size(aV%iAttr,2)
737  else
738     iLength = 0
739  endif
740
741  if(List_allocated(aV%rList) .and. associated(aV%rAttr)) then
742     rLength = size(aV%rAttr,2)
743  else
744     rLength = 0
745  endif
746
747  if(iLength /= rLength) then
748
749     if((rLength > 0) .and. (iLength > 0)) then
750        call die(myname_,'attribute array length mismatch', &
751             iLength-rLength)
752     endif
753
754     if((rLength > 0) .and. (iLength == 0)) then
755        lsize_ = rLength
756     endif
757
758     if((iLength > 0) .and. (rLength == 0)) then
759        lsize_ = iLength
760     endif
761
762  endif
763
764  if(iLength == rLength) lsize_ = iLength
765
766 end function lsize_
767
768!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
769!        Math and Computer Science Division, Argonne National Laboratory
770!BOP -------------------------------------------------------------------
771!
772! !IROUTINE: zero_ - Set AttrVect Field Data to Zero
773!
774! !DESCRIPTION:
775! This routine sets all of the point values of the integer and real
776! attributes of an the input/output {\tt AttrVect} argument {\tt aV}
777! to zero.  The default action is to set the values of all the real and
778! integer attributes to zero.  The user may prevent the zeroing of the
779! real (integer) attributes invoking {\tt zero\_()} with the optional
780! {\tt LOGICAL} argument {\tt zeroReals} ({\tt zeroInts}) set with value
781! {\tt .FALSE.}
782!
783! !INTERFACE:
784
785 subroutine zero_(aV, zeroReals, zeroInts)
786
787! !USES:
788
789
790     use m_die,only     : die
791     use m_stdio,only   : stderr
792
793     use m_List, only : List
794     use m_List, only : List_allocated => allocated
795 
796     implicit none
797
798! !INPUT PARAMETERS:
799
800     logical, optional, intent(IN)    :: zeroReals
801     logical, optional, intent(IN)    :: zeroInts
802
803! !INPUT/OUTPUT PARAMETERS:
804!
805     type(AttrVect),    intent(INOUT) :: aV
806
807! !REVISION HISTORY:
808! 17May01 - R. Jacob <jacob@mcs.anl.gov> - initial prototype/code
809! 15Oct01 - J. Larson <larson@mcs.anl.gov> - switched loop order
810!           for cache optimization.
811! 03Dec01 - E.T. Ong <eong@mcs.anl.gov> - eliminated looping method of
812!           of zeroing. "Compiler assignment" of attrvect performs faster
813!           on the IBM SP with mpxlf90 compiler.
814! 05Jan10 - R. Jacob <jacob@mcs.anl.gov> - zeroing an uninitialized aV is no
815!           longer a fatal error.
816!EOP ___________________________________________________________________
817
818  character(len=*),parameter :: myname_=myname//'::zero_'
819
820  logical myZeroReals, myZeroInts
821
822  if(present(zeroReals)) then
823     myZeroReals = zeroReals
824  else
825     myZeroReals = .TRUE.
826  endif
827
828  if(present(zeroInts)) then
829     myZeroInts = zeroInts
830  else
831     myZeroInts = .TRUE.
832  endif
833
834!  if((.not. List_allocated(aV%iList)) .and. (.not. List_allocated(aV%rList))) then
835!    write(stderr,'(2a)')myname_, &
836!      'MCTERROR:  Trying to zero an uninitialized AttrVect'
837!      call die(myname_)
838!  endif
839
840  if(myZeroInts) then ! zero out INTEGER attributes
841     if(List_allocated(aV%iList)) then
842!CDIR COLLAPSE
843        if(associated(aV%iAttr) .and. (nIAttr_(aV)>0)) aV%iAttr=0
844     endif
845  endif
846
847  if(myZeroReals) then ! zero out REAL attributes
848     if(List_allocated(aV%rList)) then
849!CDIR COLLAPSE
850        if(associated(aV%rAttr) .and. (nRAttr_(aV)>0)) aV%rAttr=0._FP
851     endif
852  endif
853
854 end subroutine zero_
855
856!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
857!     Math and Computer Science Division, Argonne National Laboratory  !
858!BOP -------------------------------------------------------------------
859!
860! !IROUTINE: nIAttr_ - Return the Number of Integer Attributes
861!
862! !DESCRIPTION:
863! This integer function returns the number of integer attributes
864! present in the input {\tt AttrVect} argument {\tt aV}.
865!
866! !INTERFACE:
867
868 integer function nIAttr_(aV)
869!
870! !USES:
871!
872      use m_List, only : nitem
873
874      implicit none
875
876! !INPUT PARAMETERS:
877!
878      type(AttrVect),intent(in) :: aV
879
880! !REVISION HISTORY:
881! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
882! 10Oct01 - J. Larson <larson@mcs.anl.gov> - made code more robust
883!           by checking status of pointers in aV%iList
884!EOP ___________________________________________________________________
885
886  character(len=*),parameter :: myname_=myname//'::nIAttr_'
887
888  if(associated(aV%iList%bf)) then
889     nIAttr_ = nitem(aV%iList)
890  else
891     nIAttr_ = 0
892  endif
893
894 end function nIAttr_
895
896!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
897!     Math and Computer Science Division, Argonne National Laboratory  !
898!BOP -------------------------------------------------------------------
899!
900! !IROUTINE: nRAttr_ - Return the Number of Real Attributes
901!
902! !DESCRIPTION:
903! This integer function returns the number of real attributes
904! present in the input {\tt AttrVect} argument {\tt aV}.
905
906! !INTERFACE:
907
908 integer function nRAttr_(aV)
909!
910! !USES:
911!
912      use m_List, only : nitem
913
914      implicit none
915
916! !INPUT PARAMETERS:
917!
918      type(AttrVect),intent(in) :: aV
919
920! !REVISION HISTORY:
921! 22Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
922! 10Oct01 - J. Larson <larson@mcs.anl.gov> - made code more robust
923!           by checking status of pointers in aV%iList
924!EOP ___________________________________________________________________
925
926  character(len=*),parameter :: myname_=myname//'::nRAttr_'
927
928  if(associated(aV%rList%bf)) then
929     nRAttr_ = nitem(aV%rList)
930  else
931     nRAttr_ = 0
932  endif
933
934 end function nRAttr_
935
936!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
937!     Math and Computer Science Division, Argonne National Laboratory  !
938!BOP -------------------------------------------------------------------
939!
940! !IROUTINE: getIList_ - Retrieve the Name of a Numbered Integer Attribute
941!
942! !DESCRIPTION:
943! This routine returns the name of the {\tt ith} integer attribute of
944! the input {\tt AttrVect} argument {\tt aVect}.  The name is returned
945! in the output {\tt String} argument {\tt item} (see the mpeu module
946! {\tt m\_String} for more information regarding the {\tt String} type).
947!
948! !INTERFACE:
949
950 subroutine getIList_(item, ith, aVect)
951!
952! !USES:
953!
954      use m_String, only : String
955      use m_List,   only : get
956
957      implicit none
958
959! !INPUT PARAMETERS:
960!
961      integer,     intent(in)  :: ith
962      type(AttrVect),intent(in) :: aVect
963
964! !OUTPUT PARAMETERS:
965!
966      type(String),intent(out) :: item
967
968! !REVISION HISTORY:
969! 24Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
970!EOP ___________________________________________________________________
971
972  character(len=*),parameter :: myname_=myname//'::getIList_'
973
974  call get(item, ith, aVect%iList)
975
976 end subroutine getIList_
977
978!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
979!     Math and Computer Science Division, Argonne National Laboratory  !
980!BOP -------------------------------------------------------------------
981!
982! !IROUTINE: getRList_ - Retrieve the Name of a Numbered Real Attribute
983!
984! !DESCRIPTION:
985! This routine returns the name of the {\tt ith} real attribute of
986! the input {\tt AttrVect} argument {\tt aVect}.  The name is returned
987! in the output {\tt String} argument {\tt item} (see the mpeu module
988! {\tt m\_String} for more information regarding the {\tt String} type).
989!
990! !INTERFACE:
991
992 subroutine getRList_(item, ith, aVect)
993!
994! !USES:
995!
996      use m_String, only : String
997      use m_List,   only : get
998
999      implicit none
1000
1001! !INPUT PARAMETERS:
1002!
1003      integer,        intent(in)  :: ith
1004      type(AttrVect), intent(in)  :: aVect
1005
1006! !OUTPUT PARAMETERS:
1007!
1008      type(String),   intent(out) :: item
1009
1010! !REVISION HISTORY:
1011! 24Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
1012!EOP ___________________________________________________________________
1013
1014  character(len=*),parameter :: myname_=myname//'::getRList_'
1015
1016  call get(item,ith,aVect%rList)
1017
1018 end subroutine getRList_
1019
1020!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1021!     Math and Computer Science Division, Argonne National Laboratory  !
1022!BOP -------------------------------------------------------------------
1023!
1024! !IROUTINE: indexIA_ - Index an Integer Attribute
1025!
1026! !DESCRIPTION:
1027! This function returns an {\tt INTEGER}, corresponding to the location
1028! of an integer attribute within the input {\tt AttrVect} argument
1029! {\tt aV}.  For example, suppose {\tt aV} has the following attributes
1030! {\tt 'month'}, {\tt 'day'}, and {\tt 'year'}.  The array of integer
1031! values for the attribute {\tt 'day'}  is stored in
1032!% \begin{verbatim}
1033! {\tt aV\%iAttr(indexIA\_(aV,'day'),:)}.
1034!% \end{verbatim}
1035! If {\tt indexIA\_()} is unable to match {\tt item} to any of the integer
1036! attributes in {\tt aV}, the resulting value is zero which is equivalent
1037! to an error.  The optional input {\tt CHARACTER} arguments {\tt perrWith}
1038! and {\tt dieWith} control how such errors are handled. 
1039! \begin{enumerate}
1040! \item if neither {\tt perrWith} nor {\tt dieWith} are present,
1041! {\tt indexIA\_()} terminates execution with an internally generated
1042! error message;
1043! \item if {\tt perrWith} is present, but {\tt dieWith} is not, an error
1044! message is written to {\tt stderr} incorporating user-supplied traceback
1045! information stored in the argument {\tt perrWith};
1046! \item if {\tt perrWith} is present, but {\tt dieWith} is not, and
1047! {\tt perrWith} is equal to ``quiet'', no error message is written.
1048! \item if {\tt dieWith} is present, execution terminates with an error
1049! message written to {\tt stderr} that incorporates user-supplied traceback
1050! information stored in the argument {\tt dieWith}; and
1051! \item if both {\tt perrWith} and {\tt dieWith} are present, execution
1052! terminates with an error message using {\tt dieWith}, and the argument
1053! {\tt perrWith} is ignored.
1054! \end{enumerate}
1055!
1056! !INTERFACE:
1057
1058 integer function indexIA_(aV, item, perrWith, dieWith)
1059!
1060! !USES:
1061!
1062      use m_die,  only : die
1063      use m_stdio,only : stderr
1064
1065      use m_String, only : String
1066      use m_String, only : String_init => init
1067      use m_String, only : String_clean => clean
1068      use m_String, only : String_ToChar => ToChar
1069
1070      use m_List, only : index
1071
1072      use m_TraceBack, only : GenTraceBackString
1073
1074      implicit none
1075
1076! !INPUT PARAMETERS:
1077!
1078      type(AttrVect),             intent(in) :: aV
1079      character(len=*),           intent(in) :: item
1080      character(len=*), optional, intent(in) :: perrWith
1081      character(len=*), optional, intent(in) :: dieWith
1082
1083! !REVISION HISTORY:
1084! 27Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
1085!  2Aug02 - J. Larson - Solidified error handling using perrWith/dieWith
1086!  1Jan05 - R. Jacob - add quiet option for error handling
1087!EOP ___________________________________________________________________
1088
1089  character(len=*),parameter :: myname_=myname//'::indexIA_'
1090
1091  type(String) :: myTrace
1092
1093  if(present(dieWith)) then
1094     call GenTraceBackString(myTrace, dieWith, myname_)
1095  else
1096     if(present(perrWith)) then
1097        call GenTraceBackString(myTrace, perrWith, myname_)
1098     else
1099        call GenTraceBackString(myTrace, myname_)
1100     endif
1101  endif
1102
1103  indexIA_=index(aV%iList,item)
1104
1105  if(indexIA_==0) then ! The attribute was not found!
1106       ! As per the prologue, decide how to handle this error
1107     if(present(perrWith) .and. (.not. present(dieWith))) then
1108       if (trim(perrWith).eq.'quiet') then
1109        ! do nothing
1110       else
1111        write(stderr,'(5a)') myname_, &
1112             ':: ERROR--attribute not found: "',trim(item),'" ', &
1113             'Traceback:  ',String_ToChar(myTrace)
1114       endif
1115     else ! Shutdown
1116        write(stderr,'(5a)') myname_, &
1117             ':: FATAL--attribute not found: "',trim(item),'" ', &
1118             'Traceback:  ',String_ToChar(myTrace)
1119        call die(myname_)
1120     endif
1121  endif
1122
1123  call String_clean(myTrace)
1124
1125 end function indexIA_
1126
1127!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1128!     Math and Computer Science Division, Argonne National Laboratory  !
1129!BOP -------------------------------------------------------------------
1130!
1131! !IROUTINE: indexRA_ - Index a Real Attribute
1132!
1133! !DESCRIPTION:
1134! This function returns an {\tt INTEGER}, corresponding to the location
1135! of a real attribute within the input {\tt AttrVect} argument
1136! {\tt aV}.  For example, suppose {\tt aV} has the following attributes
1137! {\tt 'latitude'}, {\tt 'longitude'}, and {\tt 'pressure'}.  The array
1138! of real values for the attribute {\tt 'longitude'}  is stored in
1139!% \begin{verbatim}
1140! {\tt aV\%iAttr(indexRA\_(aV,'longitude'),:)}.
1141!% \end{verbatim}
1142! If {\tt indexRA\_()} is unable to match {\tt item} to any of the real
1143! attributes in {\tt aV}, the resulting value is zero which is equivalent
1144! to an error.  The optional input {\tt CHARACTER} arguments {\tt perrWith}
1145! and {\tt dieWith} control how such errors are handled. 
1146! \begin{enumerate}
1147! \item if neither {\tt perrWith} nor {\tt dieWith} are present,
1148! {\tt indexRA\_()} terminates execution with an internally generated
1149! error message;
1150! \item if {\tt perrWith} is present, but {\tt dieWith} is not, an error
1151! message is written to {\tt stderr} incorporating user-supplied traceback
1152! information stored in the argument {\tt perrWith};
1153! \item if {\tt perrWith} is present, but {\tt dieWith} is not, and
1154! {\tt perrWith} is equal to ``quiet'', no error message is written.
1155! \item if {\tt dieWith} is present, execution terminates with an error
1156! message written to {\tt stderr} that incorporates user-supplied traceback
1157! information stored in the argument {\tt dieWith}; and
1158! \item if both {\tt perrWith} and {\tt dieWith} are present, execution
1159! terminates with an error message using {\tt dieWith}, and the argument
1160! {\tt perrWith} is ignored.
1161! \end{enumerate}
1162!
1163! !INTERFACE:
1164
1165 integer function indexRA_(aV, item, perrWith, dieWith)
1166!
1167! !USES:
1168!
1169      use m_die,  only : die
1170      use m_stdio,only : stderr
1171
1172      use m_List, only : index
1173
1174      use m_String, only : String
1175      use m_String, only : String_init => init
1176      use m_String, only : String_clean => clean
1177      use m_String, only : String_ToChar => ToChar
1178
1179      use m_TraceBack, only : GenTraceBackString
1180
1181      implicit none
1182
1183! !INPUT PARAMETERS:
1184!
1185      type(AttrVect),             intent(in) :: aV
1186      character(len=*),           intent(in) :: item
1187      character(len=*), optional, intent(in) :: perrWith
1188      character(len=*), optional, intent(in) :: dieWith
1189
1190! !REVISION HISTORY:
1191! 27Apr98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
1192!  2Aug02 - J. Larson - Solidified error handling using perrWith/dieWith
1193! 18Jan05 - R. Jacob - add quiet option for error handling
1194!EOP ___________________________________________________________________
1195
1196  character(len=*),parameter :: myname_=myname//'::indexRA_'
1197
1198  type(String) :: myTrace
1199
1200  if(present(dieWith)) then ! Append onto TraceBack
1201     call GenTraceBackString(myTrace, dieWith, myname_)
1202  else
1203     if(present(perrWith)) then ! Append onto TraceBack
1204        call GenTraceBackString(myTrace, perrWith, myname_)
1205     else ! Start a TraceBackString
1206        call GenTraceBackString(myTrace, myname_)
1207     endif
1208  endif
1209
1210  indexRA_=index(aV%rList,item)
1211
1212  if(indexRA_==0) then ! The attribute was not found!
1213       ! As per the prologue, decide how to handle this error
1214     if(present(perrWith) .and. (.not. present(dieWith))) then
1215       if (trim(perrWith).eq.'quiet') then
1216        ! do nothing
1217       else
1218        write(stderr,'(5a)') myname_, &
1219             ':: ERROR--attribute not found: "',trim(item),'" ', &
1220             'Traceback:  ',String_ToChar(myTrace)
1221       endif
1222     else ! Shutdown if dieWith or no arguments present
1223        write(stderr,'(5a)') myname_, &
1224             ':: FATAL--attribute not found: "',trim(item),'" ', &
1225             'Traceback:  ',String_ToChar(myTrace)
1226        call die(myname_)
1227     endif
1228  endif
1229
1230  call String_clean(myTrace)
1231
1232 end function indexRA_
1233
1234!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1235!       DOE/ANL Mathematics and Computer Science Division              !
1236!BOP -------------------------------------------------------------------
1237!
1238! !IROUTINE: appendIAttr_ - Append one or more attributes onto the INTEGER part of an AttrVect.
1239!
1240! !DESCRIPTION:  This routine takes an input {\tt AttrVect} argument
1241! {\tt aV}, and an input character string {\tt rList} and Appends {\tt rList}
1242! to the INTEGER part of {\tt aV}. The success (failure) of this operation is
1243! signified by a zero (nonzero) value for the optional {\tt INTEGER}
1244! output argument {\tt status}. 
1245!
1246! !INTERFACE:
1247
1248 subroutine appendIAttr_(aV, iList, status)
1249!
1250! !USES:
1251!
1252      use m_List,   only : List_init => init
1253      use m_List,   only : List_append => append
1254      use m_List,   only : List_clean => clean
1255      use m_List,   only : List_nullify => nullify
1256      use m_List,   only : List_allocated => allocated
1257      use m_List,   only : List_copy => copy
1258      use m_List,   only : List
1259      use m_die
1260      use m_stdio
1261
1262      implicit none
1263
1264! !INPUT/OUTPUT PARAMETERS:
1265!
1266      type(AttrVect),intent(inout)  :: aV
1267
1268! !INPUT PARAMETERS:
1269!
1270      character(len=*), intent(in)  :: iList
1271
1272! !OUTPUT PARAMETERS:
1273!
1274      integer,optional,intent(out)  :: status
1275
1276! !REVISION HISTORY:
1277! 08Jul03 - R. Jacob <jacob@mcs.anl.gov> - initial version
1278!EOP ___________________________________________________________________
1279
1280  character(len=*),parameter :: myname_=myname//'::appendIAttr_'
1281
1282  type(List) :: avRList,avIList        ! placeholders for the aV attributes
1283  type(List) :: addIlist               ! for the input string
1284  type(AttrVect) :: tempaV             ! placeholder for aV data.
1285  integer :: locsize                   ! size of aV
1286  integer :: rlstatus,cstatus           ! status flags
1287  integer :: ilstatus
1288
1289  if(present(status)) status = 0
1290
1291  call List_nullify(avIList)
1292  call List_nullify(avRList)
1293
1294! save the local size and current int and real attributes
1295  locsize = lsize_(aV)
1296  call exportRList_(aV,avRList,rlstatus)
1297  call exportIList_(aV,avIList,ilstatus)
1298
1299! create and fill a temporary AttrVect to hold any data currently in the aV
1300  call initv_(tempaV,aV,lsize=locsize)
1301  call Copy_(aV,tempaV)
1302
1303! create a List with the new attributes
1304  call List_init(addIlist,iList)
1305
1306! append addIlist to current avIList if it has attributes.
1307  if(List_allocated(avIList)) then
1308    call List_append(avIList,addIlist)
1309! copy addIlist to avIList
1310  else
1311    call List_copy(avIList,addIlist)
1312  endif
1313
1314! now delete the input aV and recreate it
1315  call clean_(aV,cstatus)
1316  call initl_(aV,avIList,avRList,locsize)
1317
1318! copy back the data
1319  call Copy_(tempaV,aV)
1320
1321! clean up.
1322  call List_clean(avRList,cstatus)
1323
1324  call clean_(tempaV,cstatus)
1325  call List_clean(addIlist,cstatus)
1326  call List_clean(avIList,cstatus)
1327
1328  if(present(status)) status = cstatus
1329
1330 end subroutine appendIAttr_
1331
1332!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1333!       DOE/ANL Mathematics and Computer Science Division              !
1334!BOP -------------------------------------------------------------------
1335!
1336! !IROUTINE: appendRAttr_ - Append one or more attributes onto the REAL part of an AttrVect.
1337!
1338! !DESCRIPTION:  This routine takes an input {\tt AttrVect} argument
1339! {\tt aV}, and an input character string {\tt rList} and Appends {\tt rList}
1340! to the REAL part of {\tt aV}. The success (failure) of this operation is
1341! signified by a zero (nonzero) value for the optional {\tt INTEGER}
1342! output argument {\tt status}. 
1343!
1344! !INTERFACE:
1345
1346 subroutine appendRAttr_(aV, rList, status)
1347!
1348! !USES:
1349!
1350      use m_List,   only : List_init => init
1351      use m_List,   only : List_append => append
1352      use m_List,   only : List_clean => clean
1353      use m_List,   only : List_nullify => nullify
1354      use m_List,   only : List_allocated => allocated
1355      use m_List,   only : List_copy => copy
1356      use m_List,   only : List
1357      use m_die
1358      use m_stdio
1359
1360      implicit none
1361
1362! !INPUT/OUTPUT PARAMETERS:
1363!
1364      type(AttrVect),intent(inout)  :: aV
1365
1366! !INPUT PARAMETERS:
1367!
1368      character(len=*), intent(in)  :: rList
1369
1370! !OUTPUT PARAMETERS:
1371!
1372      integer,optional,intent(out)  :: status
1373
1374! !REVISION HISTORY:
1375! 04Jun03 - R. Jacob <jacob@mcs.anl.gov> - initial version
1376!EOP ___________________________________________________________________
1377
1378  character(len=*),parameter :: myname_=myname//'::appendRAttr_'
1379
1380  type(List) :: avRList,avIList        ! placeholders for the aV attributes
1381  type(List) :: addRlist               ! for the input string
1382  type(AttrVect) :: tempaV             ! placeholder for aV data.
1383  integer :: locsize                   ! size of aV
1384  integer :: rlstatus,cstatus           ! status flags
1385  integer :: ilstatus
1386
1387  if(present(status)) status = 0
1388
1389  call List_nullify(avIList)
1390  call List_nullify(avRList)
1391
1392! save the local size and current int and real attributes
1393  locsize = lsize_(aV)
1394  call exportRList_(aV,avRList,rlstatus)
1395  call exportIList_(aV,avIList,ilstatus)
1396
1397! create and fill a temporary AttrVect to hold any data currently in the aV
1398  call initv_(tempaV,aV,lsize=locsize)
1399  call Copy_(aV,tempaV)
1400
1401! create a List with the new attributes
1402  call List_init(addRlist,rList)
1403
1404! append addRlist to current avRList if it has attributes.
1405  if(List_allocated(avRList)) then
1406    call List_append(avRList,addRlist)
1407! copy addRlist to avRList
1408  else
1409    call List_copy(avRList,addRlist)
1410  endif
1411
1412! now delete the input aV and recreate it
1413  call clean_(aV,cstatus)
1414  call initl_(aV,avIList,avRList,locsize)
1415
1416! copy back the data
1417  call Copy_(tempaV,aV)
1418
1419! clean up.
1420  call List_clean(avIList,cstatus)
1421
1422  call clean_(tempaV,cstatus)
1423  call List_clean(addRlist,cstatus)
1424  call List_clean(avRList,cstatus)
1425
1426  if(present(status)) status = cstatus
1427
1428 end subroutine appendRAttr_
1429
1430!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1431!    Math and Computer Science Division, Argonne National Laboratory   !
1432!BOP -------------------------------------------------------------------
1433!
1434! !IROUTINE: exportIList_ - Return INTEGER Attribute List
1435!
1436! !DESCRIPTION:
1437! This routine extracts from the input {\tt AttrVect} argument {\tt aV}
1438! the integer attribute list, and returns it as the {\tt List} output
1439! argument {\tt outIList}.  The success (failure) of this operation is
1440! signified by a zero (nonzero) value for the optional {\tt INTEGER}
1441! output argument {\tt status}. 
1442!
1443! {\bf N.B.:}  This routine returns an allocated {\tt List} data
1444! structure ({\tt outIList}).  The user is responsible for deallocating
1445! this structure by invoking {\tt List\_clean()} (see the module
1446! {\tt m\_List} for details) once it is no longer needed.  Failure to
1447! do so will result in a memory leak.
1448!
1449! !INTERFACE:
1450
1451 subroutine exportIList_(aV, outIList, status)
1452
1453!
1454! !USES:
1455!
1456      use m_die ,  only : die
1457      use m_stdio, only : stderr
1458
1459      use m_List,  only : List
1460      use m_List,  only : List_allocated => allocated
1461      use m_List,  only : List_copy => copy
1462      use m_List,  only : List_nullify => nullify
1463
1464      implicit none
1465
1466! !INPUT PARAMETERS:
1467
1468      type(AttrVect),             intent(in)  :: aV
1469
1470! !OUTPUT PARAMETERS:
1471
1472      type(List),                 intent(out) :: outIList
1473      integer,          optional, intent(out) :: status
1474
1475! !REVISION HISTORY:
1476! 14Dec01 - J.W. Larson <larson@mcs.anl.gov> - initial prototype.
1477!
1478!EOP ___________________________________________________________________
1479
1480  character(len=*),parameter :: myname_=myname//'::exportIList_'
1481
1482       ! Initialize status flag (if present) to success value of zero.
1483
1484  if(present(status)) status = 0
1485
1486  if(List_allocated(aV%iList)) then
1487     call List_copy(outIList, aV%iList)
1488  else
1489     call List_nullify(outIList)
1490     if(present(status)) then
1491        status = 1
1492     else
1493        call die(myname_)
1494     endif
1495  endif
1496
1497 end subroutine exportIList_
1498
1499!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1500!    Math and Computer Science Division, Argonne National Laboratory   !
1501!BOP -------------------------------------------------------------------
1502!
1503! !IROUTINE: exportRList_ - Return REAL attribute List
1504!
1505! !DESCRIPTION:
1506! This routine extracts from the input {\tt AttrVect} argument {\tt aV}
1507! the real attribute list, and returns it as the {\tt List} output
1508! argument {\tt outRList}.  The success (failure) of this operation is
1509! signified by a zero (nonzero) value for the optional {\tt INTEGER}
1510! output argument {\tt status}.
1511!
1512! {\bf N.B.:}  This routine returns an allocated {\tt List} data
1513! structure ({\tt outRList}).  The user is responsible for deallocating
1514! this structure by invoking {\tt List\_clean()} (see the module
1515! {\tt m\_List} for details) once it is no longer needed.  Failure to
1516! do so will result in a memory leak.
1517!
1518! !INTERFACE:
1519
1520 subroutine exportRList_(aV, outRList, status)
1521
1522!
1523! !USES:
1524!
1525      use m_die ,  only : die
1526      use m_stdio, only : stderr
1527
1528      use m_List,  only : List
1529      use m_List,  only : List_allocated => allocated
1530      use m_List,  only : List_copy => copy
1531      use m_List,  only : List_nullify => nullify
1532
1533      implicit none
1534
1535! !INPUT PARAMETERS:
1536
1537      type(AttrVect),           intent(in)  :: aV
1538
1539! !OUTPUT PARAMETERS:
1540
1541      type(List),               intent(out) :: outRList
1542      integer,        optional, intent(out) :: status
1543
1544! !REVISION HISTORY:
1545! 14Dec01 - J.W. Larson <larson@mcs.anl.gov> - initial prototype.
1546!
1547!EOP ___________________________________________________________________
1548
1549  character(len=*),parameter :: myname_=myname//'::exportRList_'
1550
1551       ! Initialize status flag (if present) to success value of zero.
1552
1553  if(present(status)) status = 0
1554
1555  if(List_allocated(aV%rList)) then
1556     call List_copy(outRList, aV%rList)
1557  else
1558     call List_nullify(outRList)
1559     if(present(status)) then
1560        status = 1
1561     else
1562        call die(myname_)
1563     endif
1564  endif
1565
1566 end subroutine exportRList_
1567
1568!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1569!    Math and Computer Science Division, Argonne National Laboratory   !
1570!BOP -------------------------------------------------------------------
1571!
1572! !IROUTINE: exportIListToChar_ - Return AttrVect\%iList as CHARACTER
1573!
1574! !DESCRIPTION:
1575! This routine extracts from the input {\tt AttrVect} argument {\tt aV}
1576! the integer attribute list (see the mpeu module {\tt m\_List} for more
1577! information regarding the {\tt List} type), and returns it as a
1578! {\tt CHARACTER} suitable for printing.  An example of its usage is
1579! \begin{verbatim}
1580!           write(stdout,'(1a)') exportIListToChar_(aV)
1581! \end{verbatim}
1582! which writes the contents of {\tt aV\%iList\%bf} to the Fortran device
1583! {\tt stdout}.
1584!
1585! !INTERFACE:
1586
1587 function exportIListToChar_(aV)
1588
1589!
1590! !USES:
1591!
1592      use m_die ,  only : die
1593      use m_stdio, only : stderr
1594
1595      use m_List,  only : List
1596      use m_List,  only : List_allocated => allocated
1597      use m_List,  only : List_copy => copy
1598      use m_List,  only : List_exportToChar => exportToChar
1599      use m_List,  only : List_clean => clean
1600
1601      implicit none
1602
1603! !INPUT PARAMETERS:
1604
1605      type(AttrVect),       intent(in) :: aV
1606
1607! !OUTPUT PARAMETERS:
1608
1609      character(len=size(aV%iList%bf,1)) :: exportIListToChar_
1610
1611! !REVISION HISTORY:
1612! 13Feb02 - J.W. Larson <larson@mcs.anl.gov> - initial prototype.
1613! 05Jun03 - R. Jacob <jacob@mcs.anl.gov> - return a blank instead of dying
1614!           to avoid I/O errors when this function is used in a write statement.
1615!
1616!EOP ___________________________________________________________________
1617
1618  character(len=*),parameter :: myname_=myname//'::exportIListToChar_'
1619
1620  ! The following extraneous list copy avoids a bug in the
1621  ! SGI MIPSpro Fortran 90 compiler version 7.30. and the
1622  ! Sun Fortran 90 Workshop compiler 5.0. If this line is removed,
1623  ! the following error will occur during compile time:
1624
1625  ! Signal: Segmentation fault in IR->WHIRL Conversion phase.
1626  ! "m_AttrVect.F90": Error: Signal Segmentation fault in phase IR->WHIRL
1627  ! Conversion -- processing aborted
1628  ! f90 ERROR:  /opt/MIPSpro/73/usr/lib32/cmplrs/mfef90 died due to signal 4
1629  ! f90 ERROR:  core dumped
1630  ! *** Error code 32 (bu21)
1631
1632  type(List) :: iListCopy
1633
1634       ! Extract the INTEGER attribute list to a character:
1635
1636  if(List_allocated(aV%iList)) then
1637     call List_copy(iListCopy,aV%iList)
1638     exportIListToChar_ = List_exportToChar(iListCopy)
1639     call List_clean(iListCopy)
1640  else
1641     exportIListToChar_ = ''
1642  endif
1643
1644 end function exportIListToChar_
1645
1646!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1647!    Math and Computer Science Division, Argonne National Laboratory   !
1648!BOP -------------------------------------------------------------------
1649!
1650! !IROUTINE: exportRListToChar_ - Return AttrVect\%rList as CHARACTER
1651!
1652! !DESCRIPTION:
1653! This routine extracts from the input {\tt AttrVect} argument {\tt aV}
1654! the real attribute list (see the mpeu module {\tt m\_List} for more
1655! information regarding the {\tt List} type), and returns it as a
1656! {\tt CHARACTER} suitable for printing.  An example of its usage is
1657! \begin{verbatim}
1658!           write(stdout,'(1a)') exportRListToChar_(aV)
1659! \end{verbatim}
1660! which writes the contents of {\tt aV\%rList\%bf} to the Fortran device
1661! {\tt stdout}.
1662!
1663! !INTERFACE:
1664
1665 function exportRListToChar_(aV)
1666
1667!
1668! !USES:
1669!
1670      use m_die ,  only : die
1671      use m_stdio, only : stderr
1672
1673      use m_List,  only : List
1674      use m_List,  only : List_allocated => allocated
1675      use m_List,  only : List_copy => copy
1676      use m_List,  only : List_exportToChar => exportToChar
1677      use m_List,  only : List_clean => clean
1678
1679      implicit none
1680
1681! !INPUT PARAMETERS:
1682
1683      type(AttrVect),       intent(in) :: aV
1684
1685! !OUTPUT PARAMETERS:
1686
1687      character(len=size(aV%rList%bf,1)) :: exportRListToChar_
1688
1689! !REVISION HISTORY:
1690! 13Feb02 - J.W. Larson <larson@mcs.anl.gov> - initial prototype.
1691! 05Jun03 - R. Jacob <jacob@mcs.anl.gov> - return a blank instead of dying
1692!           to avoid I/O errors when this function is used in a write statement.
1693!
1694!EOP ___________________________________________________________________
1695
1696  character(len=*),parameter :: myname_=myname//'::exportRListToChar_'
1697
1698  ! The following extraneous list copy avoids a bug in the
1699  ! SGI MIPSpro Fortran 90 compiler version 7.30. and the
1700  ! Sun Fortran 90 Workshop compiler 5.0. If this line is removed,
1701  ! the following error will occur during compile time:
1702
1703  ! Signal: Segmentation fault in IR->WHIRL Conversion phase.
1704  ! "m_AttrVect.F90": Error: Signal Segmentation fault in phase IR->WHIRL
1705  ! Conversion -- processing aborted
1706  ! f90 ERROR:  /opt/MIPSpro/73/usr/lib32/cmplrs/mfef90 died due to signal 4
1707  ! f90 ERROR:  core dumped
1708  ! *** Error code 32 (bu21)
1709
1710  type(List) :: rListCopy
1711
1712       ! Extract the REAL attribute list to a character:
1713
1714  if(List_allocated(aV%rList)) then
1715     call List_copy(rListCopy,aV%rList)
1716     exportRListToChar_ = List_exportToChar(rListCopy)
1717     call List_clean(rListCopy)
1718  else
1719     exportRListToChar_ = ''
1720  endif
1721
1722 end function exportRListToChar_
1723
1724!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1725!    Math and Computer Science Division, Argonne National Laboratory   !
1726!BOP -------------------------------------------------------------------
1727!
1728! !IROUTINE: exportIAttr_ - Return INTEGER Attribute as a Vector
1729!
1730! !DESCRIPTION:
1731! This routine extracts from the input {\tt AttrVect} argument {\tt aV}
1732! the integer attribute corresponding to the tag defined in the input
1733! {\tt CHARACTER} argument {\tt AttrTag}, and returns it in the
1734! {\tt INTEGER} output array {\tt outVect}, and its length in the output
1735! {\tt INTEGER} argument {\tt lsize}.  The optional input {\tt CHARACTER}
1736! arguments {\tt perrWith} and {\tt dieWith} control how errors are
1737! handled. 
1738! \begin{enumerate}
1739! \item if neither {\tt perrWith} nor {\tt dieWith} are present,
1740! {\tt exportIAttr\_()} terminates execution with an internally generated
1741! error message;
1742! \item if {\tt perrWith} is present, but {\tt dieWith} is not, an error
1743! message is written to {\tt stderr} incorporating user-supplied traceback
1744! information stored in the argument {\tt perrWith};
1745! \item if {\tt dieWith} is present, execution terminates with an error
1746! message written to {\tt stderr} that incorporates user-supplied traceback
1747! information stored in the argument {\tt dieWith}; and
1748! \item if both {\tt perrWith} and {\tt dieWith} are present, execution
1749! terminates with an error message using {\tt dieWith}, and the argument
1750! {\tt perrWith} is ignored.
1751! \end{enumerate}
1752!
1753! {\bf N.B.:}  This routine will fail if the {\tt AttrTag} is not in
1754! the {\tt AttrVect} {\tt List} component {\tt aV\%iList}.
1755!
1756! {\bf N.B.:}  The flexibility of this routine regarding the pointer
1757! association status of the output argument {\tt outVect} means the
1758! user must invoke this routine with care.  If the user wishes this
1759! routine to fill a pre-allocated array, then obviously this array
1760! must be allocated prior to calling this routine.  If the user wishes
1761! that the routine {\em create} the output argument array {\tt outVect},
1762! then the user must ensure this pointer is not allocated (i.e. the user
1763! must nullify this pointer) before this routine is invoked.
1764!
1765! {\bf N.B.:}  If the user has relied on this routine to allocate memory
1766! associated with the pointer {\tt outVect}, then the user is responsible
1767! for deallocating this array once it is no longer needed.  Failure to
1768! do so will result in a memory leak.
1769!
1770! !INTERFACE:
1771
1772 subroutine exportIAttr_(aV, AttrTag, outVect, lsize, perrWith, dieWith)
1773
1774!
1775! !USES:
1776!
1777      use m_die ,          only : die
1778      use m_stdio ,        only : stderr
1779
1780      use m_String, only : String
1781      use m_String, only : String_init => init
1782      use m_String, only : String_clean => clean
1783      use m_String, only : String_ToChar => ToChar
1784
1785      use m_TraceBack, only : GenTraceBackString
1786
1787      implicit none
1788
1789! !INPUT PARAMETERS:
1790
1791      type(AttrVect),             intent(in) :: aV
1792      character(len=*),           intent(in) :: AttrTag
1793      character(len=*), optional, intent(in) :: perrWith
1794      character(len=*), optional, intent(in) :: dieWith
1795
1796! !OUTPUT PARAMETERS:
1797
1798      integer,      dimension(:), pointer     :: outVect
1799      integer,          optional, intent(out) :: lsize
1800
1801! !REVISION HISTORY:
1802! 19Oct01 - J.W. Larson <larson@mcs.anl.gov> - initial (slow)
1803!           prototype.
1804!  6May02 - J.W. Larson <larson@mcs.anl.gov> - added capability
1805!           to work with pre-allocated outVect.
1806!
1807!EOP ___________________________________________________________________
1808
1809  character(len=*),parameter :: myname_=myname//'::exportIAttr_'
1810
1811  integer :: index, ierr, n, myLsize
1812  type(String) :: myTrace
1813
1814  if(present(dieWith)) then ! Append onto TraceBack
1815     call GenTraceBackString(myTrace, dieWith, myname_)
1816  else
1817     if(present(perrWith)) then ! Append onto TraceBack
1818        call GenTraceBackString(myTrace, perrWith, myname_)
1819     else ! Start a TraceBackString
1820        call GenTraceBackString(myTrace, myname_)
1821     endif
1822  endif
1823
1824       ! Index the attribute we wish to extract:
1825
1826  index = indexIA_(aV, attrTag, dieWith=String_ToChar(myTrace))
1827
1828       ! Determine the number of data points:
1829
1830  myLsize = lsize_(aV)
1831
1832       ! Allocate space for outVect (if it is not already dimensioned)
1833
1834  if(associated(outVect)) then ! check the size of outVect
1835     if(size(outVect) < myLsize) then
1836        write(stderr,'(3a,i8,a,i8)') myname_, &
1837            ':: ERROR length of output array outVect ', &
1838            ' less than length of aV.  size(outVect)=',size(outVect), &
1839            ', length of aV=',myLsize
1840        write(stderr,'(2a)') 'Traceback:  ',String_ToChar(myTrace)
1841        call die(myname_)
1842     endif
1843  else ! allocate space for outVect
1844     allocate(outVect(myLsize), stat=ierr)
1845     if(ierr /= 0) then
1846        write(stderr,'(2a,i8)') myname_, &
1847             ':: Error - allocate(outVect(...) failed. ierr = ',ierr
1848        write(stderr,'(2a)') 'Traceback:  ',String_ToChar(myTrace)     
1849        call die(myname_)
1850     endif
1851  endif
1852
1853       ! Copy the attribute data into outVect
1854
1855!$OMP PARALLEL DO PRIVATE(n)
1856  do n=1,myLsize
1857     outVect(n) = aV%iAttr(index,n)
1858  end do
1859
1860  ! return optional output argument lsize:
1861  if(present(lsize)) lsize = myLsize
1862
1863  call String_clean(myTrace)
1864
1865 end subroutine exportIAttr_
1866
1867!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1868!    Math and Computer Science Division, Argonne National Laboratory   !
1869!BOP -------------------------------------------------------------------
1870!
1871! !IROUTINE: exportRAttrSP_ - Return REAL Attribute as a Pointer to Array
1872!
1873! !DESCRIPTION:
1874! This routine extracts from the input {\tt AttrVect} argument {\tt aV}
1875! the real attribute corresponding to the tag defined in the input
1876! {\tt CHARACTER} argument {\tt AttrTag}, and returns it in the
1877! {\tt REAL} output array {\tt outVect}, and its length in the output
1878! {\tt INTEGER} argument {\tt lsize}.  The optional input {\tt CHARACTER}
1879! arguments {\tt perrWith} and {\tt dieWith} control how errors are
1880! handled. 
1881! \begin{enumerate}
1882! \item if neither {\tt perrWith} nor {\tt dieWith} are present,
1883! {\tt exportRAttr\_()} terminates execution with an internally generated
1884! error message;
1885! \item if {\tt perrWith} is present, but {\tt dieWith} is not, an error
1886! message is written to {\tt stderr} incorporating user-supplied traceback
1887! information stored in the argument {\tt perrWith};
1888! \item if {\tt dieWith} is present, execution terminates with an error
1889! message written to {\tt stderr} that incorporates user-supplied traceback
1890! information stored in the argument {\tt dieWith}; and
1891! \item if both {\tt perrWith} and {\tt dieWith} are present, execution
1892! terminates with an error message using {\tt dieWith}, and the argument
1893! {\tt perrWith} is ignored.
1894! \end{enumerate}
1895!
1896! {\bf N.B.:}  This routine will fail if the {\tt AttrTag} is not in
1897! the {\tt AttrVect} {\tt List} component {\tt aV\%iList}.
1898!
1899! {\bf N.B.:}  The flexibility of this routine regarding the pointer
1900! association status of the output argument {\tt outVect} means the
1901! user must invoke this routine with care.  If the user wishes this
1902! routine to fill a pre-allocated array, then obviously this array
1903! must be allocated prior to calling this routine.  If the user wishes
1904! that the routine {\em create} the output argument array {\tt outVect},
1905! then the user must ensure this pointer is not allocated (i.e. the user
1906! must nullify this pointer) before this routine is invoked.
1907!
1908! {\bf N.B.:}  If the user has relied on this routine to allocate memory
1909! associated with the pointer {\tt outVect}, then the user is responsible
1910! for deallocating this array once it is no longer needed.  Failure to
1911! do so will result in a memory leak.
1912!
1913! !INTERFACE:
1914
1915 subroutine exportRAttrSP_(aV, AttrTag, outVect, lsize, perrWith, dieWith)
1916
1917!
1918! !USES:
1919!
1920      use m_die ,          only : die
1921      use m_stdio ,        only : stderr
1922
1923
1924      use m_String, only : String
1925      use m_String, only : String_init => init
1926      use m_String, only : String_clean => clean
1927      use m_String, only : String_ToChar => ToChar
1928
1929      use m_TraceBack, only : GenTraceBackString
1930
1931      implicit none
1932
1933! !INPUT PARAMETERS:
1934
1935      type(AttrVect),             intent(in) :: aV
1936      character(len=*),           intent(in) :: AttrTag
1937      character(len=*), optional, intent(in) :: perrWith
1938      character(len=*), optional, intent(in) :: dieWith
1939
1940! !OUTPUT PARAMETERS:
1941
1942      real(SP),        dimension(:),  pointer     :: outVect
1943      integer,          optional,     intent(out) :: lsize
1944
1945! !REVISION HISTORY:
1946! 19Oct01 - J.W. Larson <larson@mcs.anl.gov> - initial (slow)
1947!           prototype.
1948!  6May02 - J.W. Larson <larson@mcs.anl.gov> - added capability
1949!           to work with pre-allocated outVect.
1950!
1951!EOP ___________________________________________________________________
1952
1953  character(len=*),parameter :: myname_=myname//'::exportRAttrSP_'
1954
1955  integer :: index, ierr, n, myLsize
1956  type(String) :: myTrace
1957
1958  if(present(dieWith)) then ! Append onto TraceBack
1959     call GenTraceBackString(myTrace, dieWith, myname_)
1960  else
1961     if(present(perrWith)) then ! Append onto TraceBack
1962        call GenTraceBackString(myTrace, perrWith, myname_)
1963     else ! Start a TraceBackString
1964        call GenTraceBackString(myTrace, myname_)
1965     endif
1966  endif
1967
1968       ! Index the attribute we wish to extract:
1969
1970  index = indexRA_(aV, attrTag, dieWith=String_ToChar(myTrace))
1971
1972       ! Determine the number of data points:
1973
1974  myLsize = lsize_(aV)
1975
1976       ! Allocate space for outVect (if it is not already dimensioned)
1977
1978  if(associated(outVect)) then ! check the size of outVect
1979     if(size(outVect) < myLsize) then
1980        write(stderr,'(3a,i8,a,i8)') myname_, &
1981            ':: ERROR length of output array outVect ', &
1982            ' less than length of aV.  size(outVect)=',size(outVect), &
1983            ', length of aV=',myLsize
1984        write(stderr,'(2a)') 'Traceback:  ',String_ToChar(myTrace)
1985        call die(myname_)
1986     endif
1987  else ! allocate space for outVect
1988     allocate(outVect(myLsize), stat=ierr)
1989     if(ierr /= 0) then
1990        write(stderr,'(2a,i8)') myname_, &
1991             ':: Error - allocate(outVect(...) failed. ierr = ',ierr
1992        write(stderr,'(2a)') 'Traceback:  ',String_ToChar(myTrace)     
1993        call die(myname_)
1994     endif
1995  endif
1996
1997       ! Copy the attribute data into outVect
1998
1999!$OMP PARALLEL DO PRIVATE(n)
2000  do n=1,myLsize
2001     outVect(n) = aV%rAttr(index,n)
2002  end do
2003
2004  call String_clean(myTrace)
2005
2006  ! return optional argument lsize
2007  if(present(lsize)) lsize = myLsize
2008
2009 end subroutine exportRAttrSP_
2010
2011!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2012!    Math and Computer Science Division, Argonne National Laboratory   !
2013! ----------------------------------------------------------------------
2014!
2015! !IROUTINE: exportRAttrDP_ - Return REAL Attribute as a Pointer to Array
2016!
2017! !DESCRIPTION:
2018! Double precision version of exportRAttrSP_
2019!
2020! !INTERFACE:
2021
2022 subroutine exportRAttrDP_(aV, AttrTag, outVect, lsize, perrWith, dieWith)
2023
2024!
2025! !USES:
2026!
2027      use m_die ,          only : die
2028      use m_stdio ,        only : stderr
2029
2030
2031      use m_String, only : String
2032      use m_String, only : String_init => init
2033      use m_String, only : String_clean => clean
2034      use m_String, only : String_ToChar => ToChar
2035
2036      use m_TraceBack, only : GenTraceBackString
2037
2038      implicit none
2039
2040! !INPUT PARAMETERS:
2041
2042      type(AttrVect),             intent(in) :: aV
2043      character(len=*),           intent(in) :: AttrTag
2044      character(len=*), optional, intent(in) :: perrWith
2045      character(len=*), optional, intent(in) :: dieWith
2046
2047! !OUTPUT PARAMETERS:
2048
2049      real(DP),    dimension(:),  pointer     :: outVect
2050      integer,          optional, intent(out) :: lsize
2051
2052! !REVISION HISTORY:
2053! 19Oct01 - J.W. Larson <larson@mcs.anl.gov> - initial (slow)
2054!           prototype.
2055!  6May02 - J.W. Larson <larson@mcs.anl.gov> - added capability
2056!           to work with pre-allocated outVect.
2057!
2058! ______________________________________________________________________
2059
2060  character(len=*),parameter :: myname_=myname//'::exportRAttrDP_'
2061
2062  integer :: index, ierr, n, myLsize
2063  type(String) :: myTrace
2064
2065  if(present(dieWith)) then ! Append onto TraceBack
2066     call GenTraceBackString(myTrace, dieWith, myname_)
2067  else
2068     if(present(perrWith)) then ! Append onto TraceBack
2069        call GenTraceBackString(myTrace, perrWith, myname_)
2070     else ! Start a TraceBackString
2071        call GenTraceBackString(myTrace, myname_)
2072     endif
2073  endif
2074
2075       ! Index the attribute we wish to extract:
2076
2077  index = indexRA_(aV, attrTag, dieWith=String_ToChar(myTrace))
2078
2079       ! Determine the number of data points:
2080
2081  myLsize = lsize_(aV)
2082
2083       ! Allocate space for outVect (if it is not already dimensioned)
2084
2085  if(associated(outVect)) then ! check the size of outVect
2086     if(size(outVect) < myLsize) then
2087        write(stderr,'(3a,i8,a,i8)') myname_, &
2088            ':: ERROR length of output array outVect ', &
2089            ' less than length of aV.  size(outVect)=',size(outVect), &
2090            ', length of aV=',myLsize
2091        write(stderr,'(2a)') 'Traceback:  ',String_ToChar(myTrace)
2092        call die(myname_)
2093     endif
2094  else ! allocate space for outVect
2095     allocate(outVect(myLsize), stat=ierr)
2096     if(ierr /= 0) then
2097        write(stderr,'(2a,i8)') myname_, &
2098             ':: Error - allocate(outVect(...) failed. ierr = ',ierr
2099        write(stderr,'(2a)') 'Traceback:  ',String_ToChar(myTrace)     
2100        call die(myname_)
2101     endif
2102  endif
2103
2104       ! Copy the attribute data into outVect
2105
2106!$OMP PARALLEL DO PRIVATE(n)
2107  do n=1,myLsize
2108     outVect(n) = aV%rAttr(index,n)
2109  end do
2110
2111  call String_clean(myTrace)
2112
2113  ! return optional argument lsize
2114  if(present(lsize)) lsize = myLsize
2115
2116 end subroutine exportRAttrDP_
2117
2118!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2119!    Math and Computer Science Division, Argonne National Laboratory   !
2120!BOP -------------------------------------------------------------------
2121!
2122! !IROUTINE: importIAttr_ - Import INTEGER Vector as an Attribute
2123!
2124! !DESCRIPTION:
2125! This routine imports into the input/output {\tt AttrVect} argument
2126! {\tt aV} the integer attribute corresponding to the tag defined in the
2127! input {\tt CHARACTER} argument {\tt AttrTag}.  The data to be imported
2128! is provided in the {\tt INTEGER} input array {\tt inVect}, and the
2129! number of entries to be imported in the optional input {\tt INTEGER}
2130! argument {\tt lsize}.
2131!
2132! {\bf N.B.:}  This routine will fail if the {\tt AttrTag} is not in
2133! the {\tt AttrVect} {\tt List} component {\tt aV\%iList}.
2134!
2135! !INTERFACE:
2136
2137 subroutine importIAttr_(aV, AttrTag, inVect, lsize)
2138!
2139! !USES:
2140!
2141      use m_die ,          only : die
2142      use m_stdio ,        only : stderr
2143
2144      implicit none
2145
2146! !INPUT PARAMETERS:
2147
2148      character(len=*),       intent(in)    :: AttrTag
2149      integer,  dimension(:), pointer       :: inVect
2150      integer,  optional,     intent(in)    :: lsize
2151
2152! !INPUT/OUTPUT PARAMETERS:
2153
2154      type(AttrVect),         intent(inout) :: aV
2155
2156! !REVISION HISTORY:
2157! 19Oct01 - J.W. Larson <larson@mcs.anl.gov> - initial (slow)
2158!           prototype.
2159!
2160!EOP ___________________________________________________________________
2161
2162  character(len=*),parameter :: myname_=myname//'::importIAttr_'
2163
2164  integer :: index, aVsize, ierr, n, mysize
2165
2166       ! Index the attribute we wish to extract:
2167
2168  index = indexIA_(aV, attrTag)
2169
2170       ! Determine the number of data points:
2171
2172  aVsize = lsize_(aV)
2173
2174       ! Check input array size vs. lsize_(aV):
2175
2176  if(present(lsize)) then
2177     if(aVsize < lsize) then
2178        write(stderr,'(3a,i8,a,i8)') myname_, &
2179                       ':: ERROR--attempt to import too many entries ', &
2180                       'into AttrVect aV.  AttrVect_lsize(aV)=',aVsize, &
2181                       ', number of entries to be imported=',lsize
2182        call die(myname_)
2183     endif
2184     mysize=lsize
2185  else
2186     if(aVsize < size(inVect)) then
2187        write(stderr,'(3a,i8,a,i8)') myname_, &
2188                       ':: ERROR--attempt to import too many entries ', &
2189                       'into AttrVect aV.  AttrVect_lsize(aV)=',aVsize, &
2190                       ' , number of entries to be imported=',size(inVect)
2191        call die(myname_)
2192     endif
2193     mysize = aVsize
2194  endif
2195
2196       ! Copy the data from inVect to its attribute slot:
2197
2198!$OMP PARALLEL DO PRIVATE(n)
2199  do n=1,mysize
2200     aV%iAttr(index,n) = inVect(n)
2201  end do
2202
2203 end subroutine importIAttr_
2204
2205!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2206!    Math and Computer Science Division, Argonne National Laboratory   !
2207!BOP -------------------------------------------------------------------
2208!
2209! !IROUTINE: importRAttrSP_ - Import REAL Vector as an Attribute
2210!
2211! !DESCRIPTION:
2212! This routine imports into the input/output {\tt AttrVect} argument
2213! {\tt aV} the real attribute corresponding to the tag defined in the
2214! input {\tt CHARACTER} argument {\tt AttrTag}.  The data to be imported
2215! is provided in the {\tt REAL} input array {\tt inVect}, and its
2216! length in the optional input {\tt INTEGER} argument {\tt lsize}.
2217!
2218! {\bf N.B.:}  This routine will fail if the {\tt AttrTag} is not in
2219! the {\tt AttrVect} {\tt List} component {\tt aV\%rList}.
2220!
2221! !INTERFACE:
2222
2223 subroutine importRAttrSP_(aV, AttrTag, inVect, lsize)
2224!
2225! !USES:
2226!
2227      use m_die ,          only : die
2228      use m_stdio ,        only : stderr
2229
2230      implicit none
2231
2232! !INPUT PARAMETERS:
2233
2234      character(len=*),   intent(in)    :: AttrTag
2235      real(SP), dimension(:), pointer   :: inVect
2236      integer, optional,  intent(in)    :: lsize
2237
2238! !INPUT/OUTPUT PARAMETERS:
2239
2240      type(AttrVect),     intent(inout) :: aV
2241
2242
2243
2244! !REVISION HISTORY:
2245! 19Oct01 - J.W. Larson <larson@mcs.anl.gov> - initial (slow)
2246!           prototype.
2247!
2248!EOP ___________________________________________________________________
2249
2250  character(len=*),parameter :: myname_=myname//'::importRAttrSP_'
2251
2252  integer :: index, aVsize, ierr, n, mysize
2253
2254       ! Index the attribute we wish to extract:
2255
2256  index = indexRA_(aV, attrTag)
2257
2258       ! Determine the number of data points:
2259
2260  aVsize = lsize_(aV)
2261
2262       ! Check input array size vs. lsize_(aV):
2263
2264  if(present(lsize)) then
2265     if(aVsize < lsize) then
2266        write(stderr,'(3a,i8,a,i8)') myname_, &
2267                       ':: ERROR--attempt to import too many entries ', &
2268                       'into AttrVect aV.  AttrVect_lsize(aV)=',aVsize, &
2269                       ', number of entries to be imported=',lsize
2270        call die(myname_)
2271     endif
2272     mysize=lsize
2273  else
2274     if(aVsize < size(inVect)) then
2275        write(stderr,'(3a,i8,a,i8)') myname_, &
2276                       ':: ERROR--attempt to import too many entries ', &
2277                       'into AttrVect aV.  AttrVect_lsize(aV)=',aVsize, &
2278                       ' , number of entries to be imported=',size(inVect)
2279        call die(myname_)
2280     endif
2281     mysize=aVsize
2282  endif
2283
2284       ! Copy the attribute data into outVect
2285
2286!$OMP PARALLEL DO PRIVATE(n)
2287  do n=1,mysize
2288     aV%rAttr(index,n) = inVect(n)
2289  end do
2290
2291 end subroutine importRAttrSP_
2292
2293!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2294!    Math and Computer Science Division, Argonne National Laboratory   !
2295! ----------------------------------------------------------------------
2296!
2297! !IROUTINE: importRAttrDP_ - Import REAL Vector as an Attribute
2298!
2299! !DESCRIPTION:
2300! Double precision version of importRAttrSP_
2301!
2302! !INTERFACE:
2303
2304 subroutine importRAttrDP_(aV, AttrTag, inVect, lsize)
2305!
2306! !USES:
2307!
2308      use m_die ,          only : die
2309      use m_stdio ,        only : stderr
2310
2311      implicit none
2312
2313! !INPUT PARAMETERS:
2314
2315      character(len=*),   intent(in)    :: AttrTag
2316      real(DP), dimension(:), pointer   :: inVect
2317      integer, optional,  intent(in)    :: lsize
2318
2319! !INPUT/OUTPUT PARAMETERS:
2320
2321      type(AttrVect),     intent(inout) :: aV
2322
2323
2324
2325! !REVISION HISTORY:
2326! 19Oct01 - J.W. Larson <larson@mcs.anl.gov> - initial (slow)
2327!           prototype.
2328!
2329!EOP ___________________________________________________________________
2330
2331  character(len=*),parameter :: myname_=myname//'::importRAttrDP_'
2332
2333  integer :: index, aVsize, ierr, n, mysize
2334
2335       ! Index the attribute we wish to extract:
2336
2337  index = indexRA_(aV, attrTag)
2338
2339       ! Determine the number of data points:
2340
2341  aVsize = lsize_(aV)
2342
2343       ! Check input array size vs. lsize_(aV):
2344
2345  if(present(lsize)) then
2346     if(aVsize < lsize) then
2347        write(stderr,'(3a,i8,a,i8)') myname_, &
2348                       ':: ERROR--attempt to import too many entries ', &
2349                       'into AttrVect aV.  AttrVect_lsize(aV)=',aVsize, &
2350                       ', number of entries to be imported=',lsize
2351        call die(myname_)
2352     endif
2353     mysize=lsize
2354  else
2355     if(aVsize < size(inVect)) then
2356        write(stderr,'(3a,i8,a,i8)') myname_, &
2357                       ':: ERROR--attempt to import too many entries ', &
2358                       'into AttrVect aV.  AttrVect_lsize(aV)=',aVsize, &
2359                       ' , number of entries to be imported=',size(inVect)
2360        call die(myname_)
2361     endif
2362     mysize=aVsize
2363  endif
2364
2365       ! Copy the attribute data into outVect
2366
2367!$OMP PARALLEL DO PRIVATE(n)
2368  do n=1,mysize
2369     aV%rAttr(index,n) = inVect(n)
2370  end do
2371
2372 end subroutine importRAttrDP_
2373
2374!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2375!    Math and Computer Science Division, Argonne National Laboratory   !
2376!BOP -------------------------------------------------------------------
2377!
2378! !IROUTINE: RCopy_ - Copy Real Attributes from One AttrVect to Another
2379!
2380! !DESCRIPTION:
2381! This routine copies from input argment {\tt aVin} into the output
2382! {\tt AttrVect} argument {\tt aVout} the shared real attributes.
2383!
2384! If the optional argument {\tt Vector} is present and true, the vector
2385! architecture-friendly portions of this routine will be invoked.
2386!
2387! If the optional argument {\tt sharedIndices} is present, it should be
2388! the result of the call {\tt SharedIndicesOneType\_(aVin, aVout, 'REAL',
2389! sharedIndices)}. Providing this argument speeds up this routine
2390! substantially. For example, you can compute a {\tt sharedIndices}
2391! structure once for a given pair of {\tt AttrVect}s, then use that same
2392! structure for all copies between those two {\tt AttrVect}s (although
2393! note that a different {\tt sharedIndices} variable would be needed if
2394! {\tt aVin} and {\tt aVout} were reversed).
2395!
2396! {\bf N.B.:}  This routine will fail if the {\tt aVout} is not initialized.
2397!
2398! !INTERFACE:
2399
2400 subroutine RCopy_(aVin, aVout, vector, sharedIndices)
2401
2402!
2403! !USES:
2404!
2405      use m_die ,          only : die
2406      use m_stdio ,        only : stderr
2407
2408      use m_List,          only : GetSharedListIndices
2409      use m_List,          only : GetIndices => get_indices
2410
2411      implicit none
2412
2413! !INPUT PARAMETERS:
2414
2415      type(AttrVect),             intent(in)    :: aVin
2416      logical, optional,          intent(in)    :: vector 
2417      type(AVSharedIndicesOneType), optional, intent(in) :: sharedIndices
2418
2419! !OUTPUT PARAMETERS:
2420
2421      type(AttrVect),             intent(inout) :: aVout
2422
2423
2424! !REVISION HISTORY:
2425! 18Aug06 - R. Jacob <jacob@mcs.anl.gov> - initial version.
2426! 28Apr11 - W.J. Sacks <sacks@ucar.edu> - added sharedIndices argument
2427!EOP ___________________________________________________________________
2428
2429  character(len=*),parameter :: myname_=myname//'::RCopy_'
2430
2431  integer :: i,j,ier       ! dummy variables
2432  integer :: aVsize        ! The lsize of aVin and aVout
2433  integer :: num_inindices, num_outindices   ! Number of matching indices in aV
2434  integer :: inxmin, outxmin, inx, outx      ! Index variables
2435  logical :: usevector    ! true if vector flag is present and true.
2436  character*7 :: data_flag ! character variable used as data type flag
2437  type(AVSharedIndicesOneType) :: mySharedIndices  ! copied from sharedIndices, or
2438                                                   ! computed if sharedIndices is not
2439                                                   ! present
2440  logical :: clean_mySharedIndices ! true if we need to clean mySharedIndices before
2441                                   ! returning (will be true if we did allocation in this
2442                                   ! subroutine)
2443
2444
2445  ! Check the arguments
2446  aVsize = lsize_(aVin)
2447  if(lsize_(aVin) /= lsize_(aVout)) then
2448     write(stderr,'(2a)') myname_, &
2449      'MCTERROR: Input aV and output aV do not have the same size'
2450     call die(myname_,'MCTERROR: Input aV and output aV &
2451                       &do not have the same size',2)
2452  endif
2453
2454  data_flag = 'REAL'
2455
2456  if (present(sharedIndices)) then
2457     ! do some error checking on sharedIndices
2458     if (.not. (associated(sharedIndices%aVindices1) .and. associated(sharedIndices%aVindices2))) then
2459        call die(myname_,'MCTERROR: provided sharedIndices structure is uninitialized',3)
2460     endif
2461     if (trim(sharedIndices%data_flag) /= data_flag) then
2462        call die(myname_,'MCTERROR: provided sharedIndices structure has incorrect data_flag',4)
2463     endif
2464
2465     ! copy into local variable
2466     mySharedIndices = sharedIndices
2467     clean_mySharedIndices = .false.
2468  else
2469     ! Check REAL attributes for matching indices
2470     call SharedIndicesOneType_(aVin, aVout, data_flag, mySharedIndices)
2471     clean_mySharedIndices = .true.
2472  endif
2473
2474  if(mySharedIndices%num_indices <= 0) then
2475    if (clean_mySharedIndices) then
2476       call cleanSharedIndicesOneType_(mySharedIndices,stat=ier)
2477       if(ier /= 0) call die(myname_,'MCTERROR: in cleanSharedIndicesOneType_',ier)
2478    endif
2479    return
2480  endif
2481
2482  ! check vector flag.
2483  usevector = .false.
2484  if (present(vector)) then
2485   if(vector) usevector = .true.
2486  endif
2487
2488  ! Start copying
2489
2490  if(mySharedIndices%contiguous) then
2491
2492     if(usevector) then
2493        outxmin=mySharedIndices%aVindices2(1)-1
2494        inxmin=mySharedIndices%aVindices1(1)-1
2495!$OMP PARALLEL DO PRIVATE(i,j)
2496        do i=1,mySharedIndices%num_indices
2497!CDIR SELECT(VECTOR)
2498!DIR$ CONCURRENT
2499           do j=1,aVsize
2500              aVout%rAttr(outxmin+i,j) = aVin%rAttr(inxmin+i,j)
2501           enddo
2502        enddo
2503     else
2504        outxmin=mySharedIndices%aVindices2(1)-1
2505        inxmin=mySharedIndices%aVindices1(1)-1
2506!$OMP PARALLEL DO PRIVAtE(j,i)
2507        do j=1,aVsize
2508!DIR$ CONCURRENT
2509           do i=1,mySharedIndices%num_indices
2510              aVout%rAttr(outxmin+i,j) = aVin%rAttr(inxmin+i,j)
2511           enddo
2512        enddo
2513     endif
2514
2515  else
2516         
2517!$OMP PARALLEL DO PRIVATE(j,i,outx,inx)
2518     do j=1,aVsize
2519!DIR$ CONCURRENT
2520        do i=1,mySharedIndices%num_indices
2521           outx=mySharedIndices%aVindices2(i)
2522           inx=mySharedIndices%aVindices1(i)     
2523           aVout%rAttr(outx,j) = aVin%rAttr(inx,j)
2524        enddo
2525     enddo
2526       
2527  endif
2528
2529
2530  if (clean_mySharedIndices) then
2531     call cleanSharedIndicesOneType_(mySharedIndices,stat=ier)
2532     if(ier /= 0) call die(myname_,'MCTERROR: in cleanSharedIndicesOneType_',ier)
2533  endif
2534
2535 end subroutine RCopy_
2536
2537!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2538!    Math and Computer Science Division, Argonne National Laboratory   !
2539!BOP -------------------------------------------------------------------
2540!
2541! !IROUTINE: RCopyL_ - Copy Specific Real Attributes from One AttrVect to Another
2542!
2543! !DESCRIPTION:
2544! This routine copies from input argment {\tt aVin} into the output
2545! {\tt AttrVect} argument {\tt aVout} the real attributes specified in
2546! input {\tt CHARACTER} argument {\tt rList}. The attributes can
2547! be listed in any order. 
2548!
2549! If any attributes in {\tt aVout} have different names but represent the
2550! the same quantity and should still be copied, you must provide a translation
2551! argument {\tt TrList}.  The translation arguments should
2552! be identical in length to the {\tt rList} but with the correct {\tt aVout}
2553! name subsititued at the appropriate place.
2554!
2555! If the optional argument {\tt Vector} is present and true, the vector
2556! architecture-friendly portions of this routine will be invoked.
2557!
2558! {\bf N.B.:}  This routine will fail if the {\tt aVout} is not initialized or
2559! if any of the specified attributes are not present in either {\tt aVout} or {\tt aVin}.
2560!
2561! !INTERFACE:
2562
2563 subroutine RCopyL_(aVin, aVout, rList, TrList,  vector)
2564
2565!
2566! !USES:
2567!
2568      use m_die ,          only : die
2569      use m_stdio ,        only : stderr
2570
2571      use m_List,          only : GetSharedListIndices
2572      use m_List,          only : GetIndices => get_indices
2573
2574      implicit none
2575
2576! !INPUT PARAMETERS:
2577
2578      type(AttrVect),             intent(in)    :: aVin
2579      character(len=*),           intent(in)    :: rList
2580      character(len=*), optional, intent(in)    :: TrList
2581      logical, optional,          intent(in)    :: vector 
2582
2583! !OUTPUT PARAMETERS:
2584
2585      type(AttrVect),             intent(inout) :: aVout
2586
2587
2588! !REVISION HISTORY:
2589! 16Aug06 - R. Jacob <jacob@mcs.anl.gov> - initial version from breakup
2590!           of Copy_.
2591!
2592!EOP ___________________________________________________________________
2593
2594  character(len=*),parameter :: myname_=myname//'::RCopyL_'
2595
2596  integer :: i,j,ier       ! dummy variables
2597  integer :: num_indices   ! Overlapping attribute index number
2598  integer :: aVsize        ! The lsize of aVin and aVout
2599  integer :: num_inindices, num_outindices   ! Number of matching indices in aV
2600  integer :: inxmin, outxmin, inx, outx      ! Index variables
2601  logical :: TrListIsPresent   ! true if list argument is present
2602  logical :: contiguous    ! true if index segments are contiguous in memory 
2603  logical :: usevector    ! true if vector flag is present and true.
2604  character*7 :: data_flag ! character variable used as data type flag
2605
2606  ! Overlapping attribute index storage arrays:
2607  integer, dimension(:), pointer :: aVinindices, aVoutindices
2608
2609
2610  ! Check the arguments
2611  aVsize = lsize_(aVin)
2612  if(lsize_(aVin) /= lsize_(aVout)) then
2613     write(stderr,'(2a)') myname_, &
2614      'MCTERROR: Input aV and output aV do not have the same size'
2615     call die(myname_,'MCTERROR: Input aV and output aV &
2616                       &do not have the same size',2)
2617  endif
2618
2619  if(len_trim(rList) <= 0) return
2620  ! Copy the listed real attributes
2621
2622  ! Index rList with the AttrVects
2623  call GetIndices(aVinindices,aVin%rList,trim(rList))
2624       
2625!  TrList is present if it is provided and its length>0
2626  TrListIsPresent = .false.
2627  if(present(TrList)) then
2628     if(len_trim(TrList) > 0) then
2629       TrListIsPresent = .true.
2630     endif
2631  endif
2632
2633  if(TrListIsPresent) then
2634     call GetIndices(aVoutindices,aVout%rList,trim(TrList))
2635
2636     if(size(aVinindices) /= size(aVoutindices)) then
2637       call die(myname_,"Arguments rList and TrList do not&
2638             &contain the same number of items")
2639     endif
2640  else
2641       call GetIndices(aVoutindices,aVout%rList,trim(rList))
2642  endif
2643
2644  num_indices=size(aVoutindices)
2645
2646  ! nothing to do if num_indices <=0
2647  if (num_indices <= 0) then
2648    deallocate(aVinindices, aVoutindices, stat=ier)
2649    if(ier/=0) call die(myname_,"deallocate(aVinindices...)",ier)
2650    return
2651  endif
2652 
2653  ! check vector flag.
2654  usevector = .false.
2655  if (present(vector)) then
2656   if(vector) usevector = .true.
2657  endif
2658
2659! Check if the indices are contiguous in memory for faster copy
2660  contiguous=.true.
2661  do i=2,num_indices
2662     if(aVinindices(i) /= aVinindices(i-1)+1) contiguous = .false.
2663  enddo
2664  if(contiguous) then
2665     do i=2,num_indices
2666         if(aVoutindices(i) /= aVoutindices(i-1)+1) contiguous=.false.
2667     enddo
2668  endif
2669
2670! Start copying (arranged loop order optimized for xlf90)
2671  if(contiguous) then
2672
2673     if(usevector) then
2674        outxmin=aVoutindices(1)-1
2675        inxmin=aVinindices(1)-1
2676!$OMP PARALLEL DO PRIVATE(i,j)
2677        do i=1,num_indices
2678!DIR$ CONCURRENT
2679           do j=1,aVsize
2680             aVout%rAttr(outxmin+i,j) = aVin%rAttr(inxmin+i,j)       
2681           enddo
2682        enddo
2683     else
2684        outxmin=aVoutindices(1)-1
2685        inxmin=aVinindices(1)-1
2686!$OMP PARALLEL DO PRIVATE(j,i)
2687        do j=1,aVsize
2688!DIR$ CONCURRENT
2689           do i=1,num_indices
2690              aVout%rAttr(outxmin+i,j) = aVin%rAttr(inxmin+i,j)       
2691           enddo
2692        enddo
2693     endif
2694
2695  else
2696
2697!$OMP PARALLEL DO PRIVATE(j,i,outx,inx)
2698    do j=1,aVsize
2699!DIR$ CONCURRENT
2700       do i=1,num_indices
2701          outx=aVoutindices(i)
2702          inx=aVinindices(i)     
2703          aVout%rAttr(outx,j) = aVin%rAttr(inx,j)
2704       enddo
2705    enddo
2706
2707  endif
2708
2709  deallocate(aVinindices, aVoutindices, stat=ier)
2710  if(ier/=0) call die(myname_,"deallocate(aVinindices...)",ier)
2711
2712 end subroutine RCopyL_
2713
2714!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2715!    Math and Computer Science Division, Argonne National Laboratory   !
2716!BOP -------------------------------------------------------------------
2717!
2718! !IROUTINE: ICopy_ - Copy Integer Attributes from One AttrVect to Another
2719!
2720! !DESCRIPTION:
2721! This routine copies from input argment {\tt aVin} into the output
2722! {\tt AttrVect} argument {\tt aVout} the shared integer attributes.
2723!
2724! If the optional argument {\tt Vector} is present and true, the vector
2725! architecture-friendly portions of this routine will be invoked.
2726!
2727! If the optional argument {\tt sharedIndices} is present, it should be
2728! the result of the call {\tt SharedIndicesOneType\_(aVin, aVout, 'INTEGER',
2729! sharedIndices)}. Providing this argument speeds up this routine
2730! substantially. For example, you can compute a {\tt sharedIndices}
2731! structure once for a given pair of {\tt AttrVect}s, then use that same
2732! structure for all copies between those two {\tt AttrVect}s (although
2733! note that a different {\tt sharedIndices} variable would be needed if
2734! {\tt aVin} and {\tt aVout} were reversed).
2735!
2736! {\bf N.B.:}  This routine will fail if the {\tt aVout} is not initialized.
2737!
2738! !INTERFACE:
2739
2740 subroutine ICopy_(aVin, aVout, vector, sharedIndices)
2741
2742!
2743! !USES:
2744!
2745      use m_die ,          only : die
2746      use m_stdio ,        only : stderr
2747
2748      use m_List,          only : GetSharedListIndices
2749      use m_List,          only : GetIndices => get_indices
2750
2751      implicit none
2752
2753! !INPUT PARAMETERS:
2754
2755      type(AttrVect),             intent(in)    :: aVin
2756      logical, optional,          intent(in)    :: vector 
2757      type(AVSharedIndicesOneType), optional, intent(in) :: sharedIndices
2758
2759! !OUTPUT PARAMETERS:
2760
2761      type(AttrVect),             intent(inout) :: aVout
2762
2763
2764! !REVISION HISTORY:
2765! 16Aug06 - R. Jacob <jacob@mcs.anl.gov> - initial version.
2766! 28Apr11 - W.J. Sacks <sacks@ucar.edu> - added sharedIndices argument
2767!
2768!EOP ___________________________________________________________________
2769
2770  character(len=*),parameter :: myname_=myname//'::ICopy_'
2771
2772  integer :: i,j,ier       ! dummy variables
2773  integer :: aVsize        ! The lsize of aVin and aVout
2774  integer :: num_inindices, num_outindices   ! Number of matching indices in aV
2775  integer :: inxmin, outxmin, inx, outx      ! Index variables
2776  logical :: usevector    ! true if vector flag is present and true.
2777  character*7 :: data_flag ! character variable used as data type flag
2778  type(AVSharedIndicesOneType) :: mySharedIndices  ! copied from sharedIndices, or
2779                                                   ! computed if sharedIndices is not
2780                                                   ! present
2781  logical :: clean_mySharedIndices ! true if we need to clean mySharedIndices before
2782                                   ! returning (will be true if we did allocation in this
2783                                   ! subroutine)
2784
2785
2786  ! Check the arguments
2787  aVsize = lsize_(aVin)
2788  if(lsize_(aVin) /= lsize_(aVout)) then
2789     write(stderr,'(2a)') myname_, &
2790      'MCTERROR: Input aV and output aV do not have the same size'
2791     call die(myname_,'MCTERROR: Input aV and output aV &
2792                       &do not have the same size',2)
2793  endif
2794
2795  data_flag = 'INTEGER'
2796 
2797  if (present(sharedIndices)) then
2798     ! do some error checking on sharedIndices
2799     if (.not. (associated(sharedIndices%aVindices1) .and. associated(sharedIndices%aVindices2))) then
2800        call die(myname_,'MCTERROR: provided sharedIndices structure is uninitialized',3)
2801     endif
2802     if (trim(sharedIndices%data_flag) /= data_flag) then
2803        call die(myname_,'MCTERROR: provided sharedIndices structure has incorrect data_flag',4)
2804     endif
2805
2806     ! copy into local variable
2807     mySharedIndices = sharedIndices
2808     clean_mySharedIndices = .false.
2809  else
2810     ! Check INTEGER attributes for matching indices
2811     call SharedIndicesOneType_(aVin, aVout, data_flag, mySharedIndices)
2812     clean_mySharedIndices = .true.
2813  endif
2814
2815  if(mySharedIndices%num_indices <= 0) then
2816    if (clean_mySharedIndices) then
2817       call cleanSharedIndicesOneType_(mySharedIndices,stat=ier)
2818       if(ier /= 0) call die(myname_,'MCTERROR: in cleanSharedIndicesOneType_',ier)
2819    endif
2820    return
2821  endif
2822
2823  ! check vector flag.
2824  usevector = .false.
2825  if (present(vector)) then
2826   if(vector) usevector = .true.
2827  endif
2828
2829
2830  if(mySharedIndices%contiguous) then
2831     
2832     if(usevector) then
2833        outxmin=mySharedIndices%aVindices2(1)-1
2834        inxmin=mySharedIndices%aVindices1(1)-1
2835!$OMP PARALLEL DO PRIVATE(i,j)
2836        do i=1,mySharedIndices%num_indices
2837!CDIR SELECT(VECTOR)
2838!DIR$ CONCURRENT
2839           do j=1,aVsize
2840              aVout%iAttr(outxmin+i,j) = aVin%iAttr(inxmin+i,j)
2841           enddo
2842        enddo
2843     else
2844        outxmin=mySharedIndices%aVindices2(1)-1
2845        inxmin=mySharedIndices%aVindices1(1)-1
2846!$OMP PARALLEL DO PRIVATE(j,i)
2847        do j=1,aVsize
2848!DIR$ CONCURRENT
2849           do i=1,mySharedIndices%num_indices
2850              aVout%iAttr(outxmin+i,j) = aVin%iAttr(inxmin+i,j)
2851           enddo
2852        enddo
2853     endif
2854
2855  else
2856
2857!$OMP PARALLEL DO PRIVATE(j,i,outx,inx)
2858     do j=1,aVsize
2859!DIR$ CONCURRENT
2860        do i=1,mySharedIndices%num_indices
2861           outx=mySharedIndices%aVindices2(i)
2862           inx=mySharedIndices%aVindices1(i)     
2863           aVout%iAttr(outx,j) = aVin%iAttr(inx,j)
2864        enddo
2865     enddo
2866     
2867  endif
2868
2869  if (clean_mySharedIndices) then
2870     call cleanSharedIndicesOneType_(mySharedIndices,stat=ier)
2871     if(ier /= 0) call die(myname_,'MCTERROR: in cleanSharedIndicesOneType_',ier)
2872  endif
2873
2874 end subroutine ICopy_
2875
2876!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2877!    Math and Computer Science Division, Argonne National Laboratory   !
2878!BOP -------------------------------------------------------------------
2879!
2880! !IROUTINE: ICopyL_ - Copy Specific Integer Attributes from One AttrVect to Another
2881!
2882! !DESCRIPTION:
2883! This routine copies from input argment {\tt aVin} into the output
2884! {\tt AttrVect} argument {\tt aVout} the integer attributes specified in
2885! input {\tt CHARACTER} argument {\tt iList}. The attributes can
2886! be listed in any order.
2887!
2888! If any attributes in {\tt aVout} have different names but represent the
2889! the same quantity and should still be copied, you must provide a translation
2890! argument {\tt TiList}.  The translation arguments should
2891! be identical in length to the {\tt iList} but with the correct {\tt aVout}
2892! name subsititued at the appropriate place.
2893!
2894! If the optional argument {\tt Vector} is present and true, the vector
2895! architecture-friendly portions of this routine will be invoked.
2896!
2897! {\bf N.B.:}  This routine will fail if the {\tt aVout} is not initialized or
2898! if any of the specified attributes are not present in either {\tt aVout} or {\tt aVin}.
2899!
2900! !INTERFACE:
2901
2902 subroutine ICopyL_(aVin, aVout, iList, TiList, vector)
2903
2904!
2905! !USES:
2906!
2907      use m_die ,          only : die
2908      use m_stdio ,        only : stderr
2909
2910      use m_List,          only : GetIndices => get_indices
2911
2912      implicit none
2913
2914! !INPUT PARAMETERS:
2915
2916      type(AttrVect),             intent(in)    :: aVin
2917      character(len=*)          , intent(in)    :: iList
2918      character(len=*), optional, intent(in)    :: TiList
2919      logical, optional,          intent(in)    :: vector 
2920
2921! !OUTPUT PARAMETERS:
2922
2923      type(AttrVect),             intent(inout) :: aVout
2924
2925
2926! !REVISION HISTORY:
2927! 16Aug06 - R. Jacob <jacob@mcs.anl.gov> - initial version from breakup
2928!           of Copy_.
2929!
2930!EOP ___________________________________________________________________
2931
2932  character(len=*),parameter :: myname_=myname//'::ICopyL_'
2933
2934  integer :: i,j,ier       ! dummy variables
2935  integer :: num_indices   ! Overlapping attribute index number
2936  integer :: aVsize        ! The lsize of aVin and aVout
2937  integer :: num_inindices, num_outindices   ! Number of matching indices in aV
2938  integer :: inxmin, outxmin, inx, outx      ! Index variables
2939  logical :: TiListIsPresent     ! true if list argument is present
2940  logical :: contiguous    ! true if index segments are contiguous in memory 
2941  logical :: usevector    ! true if vector flag is present and true.
2942  character*7 :: data_flag ! character variable used as data type flag
2943
2944  ! Overlapping attribute index storage arrays:
2945  integer, dimension(:), pointer :: aVinindices, aVoutindices
2946
2947
2948  ! Check the arguments
2949  aVsize = lsize_(aVin)
2950  if(lsize_(aVin) /= lsize_(aVout)) then
2951     write(stderr,'(2a)') myname_, &
2952      'MCTERROR: Input aV and output aV do not have the same size'
2953     call die(myname_,'MCTERROR: Input aV and output aV &
2954                       &do not have the same size',2)
2955  endif
2956
2957  if(len_trim(iList) <= 0) return
2958  ! Copy the listed real attributes
2959
2960
2961! Index rList with the AttrVects
2962  call GetIndices(aVinindices,aVin%iList,trim(iList))
2963
2964! TiList is present if its provided and its length>0
2965  TiListIsPresent = .false.
2966  if(present(TiList)) then
2967    if(len_trim(TiList) > 0) then
2968      TiListIsPresent = .true.
2969    endif
2970  endif
2971
2972  if(TiListIsPresent) then
2973     call GetIndices(aVoutindices,aVout%iList,trim(TiList))
2974     if(size(aVinindices) /= size(aVoutindices)) then
2975        call die(myname_,"Arguments iList and TiList do not&
2976               &contain the same number of items")
2977     endif
2978  else
2979     call GetIndices(aVoutindices,aVout%iList,trim(iList))
2980  endif
2981
2982  num_indices=size(aVoutindices)
2983
2984  ! nothing to do if num_indices <=0
2985  if (num_indices <= 0) then
2986    deallocate(aVinindices, aVoutindices, stat=ier)
2987    if(ier/=0) call die(myname_,"deallocate(aVinindices...)",ier)
2988    return
2989  endif
2990
2991  ! check vector flag.
2992  usevector = .false.
2993  if (present(vector)) then
2994   if(vector) usevector = .true.
2995  endif
2996
2997! Check if the indices are contiguous in memory for faster copy
2998  contiguous=.true.
2999  do i=2,num_indices
3000    if(aVinindices(i) /= aVinindices(i-1)+1) contiguous = .false.
3001  enddo
3002  if(contiguous) then
3003    do i=2,num_indices
3004      if(aVoutindices(i) /= aVoutindices(i-1)+1) contiguous=.false.
3005    enddo
3006  endif
3007       
3008! Start copying (arranged loop order optimized for xlf90)
3009  if(contiguous) then
3010
3011    if(usevector) then
3012      outxmin=aVoutindices(1)-1
3013      inxmin=aVinindices(1)-1
3014!$OMP PARALLEL DO PRIVAtE(i,j)
3015      do i=1,num_indices
3016!CDIR SELECT(VECTOR)
3017!DIR$ CONCURRENT
3018         do j=1,aVsize
3019            aVout%iAttr(outxmin+i,j) = aVin%iAttr(inxmin+i,j)       
3020         enddo
3021      enddo
3022    else
3023      outxmin=aVoutindices(1)-1
3024      inxmin=aVinindices(1)-1
3025!$OMP PARALLEL DO PRIVATE(j,i)
3026      do j=1,aVsize
3027!DIR$ CONCURRENT
3028         do i=1,num_indices
3029            aVout%iAttr(outxmin+i,j) = aVin%iAttr(inxmin+i,j)       
3030         enddo
3031      enddo
3032    endif
3033
3034  else
3035
3036!$OMP PARALLEL DO PRIVATE(j,i,outx,inx)
3037     do j=1,aVsize
3038!DIR$ CONCURRENT
3039       do i=1,num_indices
3040          outx=aVoutindices(i)
3041          inx=aVinindices(i)     
3042          aVout%iAttr(outx,j) = aVin%iAttr(inx,j)
3043       enddo
3044     enddo
3045
3046  endif
3047               
3048  deallocate(aVinindices, aVoutindices, stat=ier)
3049  if(ier/=0) call die(myname_,"deallocate(aVinindices...)",ier)
3050
3051 end subroutine ICopyL_
3052
3053!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3054!    Math and Computer Science Division, Argonne National Laboratory   !
3055!BOP -------------------------------------------------------------------
3056!
3057! !IROUTINE: Copy_ - Copy Real and Integer Attributes from One AttrVect to Another
3058!
3059! !DESCRIPTION:
3060! This routine copies from input argment {\tt aVin} into the output
3061! {\tt AttrVect} argument {\tt aVout} the real and integer attributes specified in
3062! input {\tt CHARACTER} argument {\tt iList} and {\tt rList}. The attributes can
3063! be listed in any order.  If neither {\tt iList} nor {\tt rList} are provided,
3064! all attributes shared between {\tt aVin} and {\tt aVout} will be copied.
3065!
3066! If any attributes in {\tt aVout} have different names but represent the
3067! the same quantity and should still be copied, you must provide a translation
3068! argument {\tt TrList} and/or {\tt TiList}.  The translation arguments should
3069! be identical to the {\tt rList} or {\tt iList} but with the correct {\tt aVout}
3070! name subsititued at the appropriate place.
3071!
3072! This routines combines the functions of {\tt RCopy\_}, {\tt RCopyL\_},
3073! {\tt ICopy\_} and {\tt ICopyL\_}.  If you know you only want to copy real
3074! attributes, use the {\tt RCopy} functions.  If you know you only want to
3075! copy integer attributes, use the {\tt ICopy} functions.
3076!
3077! If the optional argument {\tt Vector} is present and true, the vector
3078! architecture-friendly portions of this routine will be invoked.
3079!
3080! If the optional argument {\tt sharedIndices} is present, it should be
3081! the result of the call {\tt SharedIndices\_(aVin, aVout,
3082! sharedIndices)}. Providing this argument speeds up this routine
3083! substantially. For example, you can compute a {\tt sharedIndices}
3084! structure once for a given pair of {\tt AttrVect}s, then use that same
3085! structure for all copies between those two {\tt AttrVect}s (although
3086! note that a different {\tt sharedIndices} variable would be needed if
3087! {\tt aVin} and {\tt aVout} were reversed). Note, however, that {\tt
3088! sharedIndices} is ignored if either {\tt rList} or {\tt iList} are
3089! given.
3090!
3091! {\bf N.B.:}  This routine will fail if the {\tt aVout} is not initialized or
3092! if any of the specified attributes are not present in either {\tt aVout} or {\tt aVin}.
3093!
3094! !INTERFACE:
3095
3096 subroutine Copy_(aVin, aVout, rList, TrList, iList, TiList, vector, sharedIndices)
3097
3098!
3099! !USES:
3100!
3101      use m_die ,          only : die, warn
3102      use m_stdio ,        only : stderr
3103
3104      use m_List,          only : GetSharedListIndices
3105      use m_List,          only : GetIndices => get_indices
3106
3107      implicit none
3108
3109! !INPUT PARAMETERS:
3110
3111      type(AttrVect),             intent(in)    :: aVin
3112      character(len=*), optional, intent(in)    :: iList
3113      character(len=*), optional, intent(in)    :: rList
3114      character(len=*), optional, intent(in)    :: TiList
3115      character(len=*), optional, intent(in)    :: TrList
3116      logical, optional,          intent(in)    :: vector 
3117      type(AVSharedIndices), optional, intent(in) :: sharedIndices
3118
3119! !OUTPUT PARAMETERS:
3120
3121      type(AttrVect),             intent(inout) :: aVout
3122
3123
3124! !REVISION HISTORY:
3125! 12Jun02 - R. Jacob <jacob@mcs.anl.gov> - initial version.
3126! 13Jun02 - R. Jacob <jacob@mcs.anl.gov> - copy shared attributes
3127!           if no attribute lists are specified.
3128! 30Sep02 - R. Jacob <jacob@mcs.anl.gov> - new argument order with all
3129!           optional arguments last
3130! 19Feb02 - E. Ong <eong@mcs.anl.gov> - new implementation using
3131!           new list function get_indices and faster memory copy 
3132! 28Oct03 - R. Jacob <jacob@mcs.anl.gov> - add optional vector
3133!           argument to use vector-friendly code provided by Fujitsu
3134! 16Aug06 - R. Jacob <jacob@mcs.anl.gov> - split into 4 routines:
3135!           RCopy_,RCopyL_,ICopy_,ICopyL_
3136! 28Apr11 - W.J. Sacks <sacks@ucar.edu> - added sharedIndices argument
3137!
3138!EOP ___________________________________________________________________
3139
3140  character(len=*),parameter :: myname_=myname//'::Copy_'
3141
3142  integer :: i,j,ier       ! dummy variables
3143  integer :: num_indices   ! Overlapping attribute index number
3144  integer :: aVsize        ! The lsize of aVin and aVout
3145  integer :: num_inindices, num_outindices   ! Number of matching indices in aV
3146  integer :: inxmin, outxmin, inx, outx      ! Index variables
3147  logical :: TiListIsPresent, TrListIsPresent! true if list argument is present
3148  logical :: contiguous    ! true if index segments are contiguous in memory 
3149  logical :: usevector    ! true if vector flag is present and true.
3150  character*7 :: data_flag ! character variable used as data type flag
3151
3152  ! Overlapping attribute index storage arrays:
3153  integer, dimension(:), pointer :: aVinindices, aVoutindices
3154
3155
3156  ! Check the arguments
3157  aVsize = lsize_(aVin)
3158  if(lsize_(aVin) /= lsize_(aVout)) then
3159     write(stderr,'(2a)') myname_, &
3160      'MCTERROR: Input aV and output aV do not have the same size'
3161     call die(myname_,'MCTERROR: Input aV and output aV &
3162                       &do not have the same size',2)
3163  endif
3164
3165  ! check vector flag.
3166  usevector = .false.
3167  if (present(vector)) then
3168   if(vector) usevector = .true.
3169  endif
3170
3171  ! Copy the listed real attributes
3172  if(present(rList)) then
3173        ! TrList is present if it is provided and its length>0
3174        TrListIsPresent = .false.
3175        if(present(TrList)) then
3176           if(len_trim(TrList) > 0) then
3177              TrListIsPresent = .true.
3178           endif
3179        endif
3180
3181        if(present(sharedIndices)) then
3182           call warn(myname_,'Use of sharedIndices not implemented in RCopyL; &
3183                     &ignoring sharedIndices',1)
3184        end if
3185
3186        if(TrListIsPresent) then
3187           call RCopyL_(aVin,aVout,rList,TrList,vector=usevector)
3188        else
3189           call RCopyL_(aVin,aVout,rList,vector=usevector)
3190        endif
3191
3192  endif   ! if(present(rList)
3193
3194  !  Copy the listed integer attributes
3195  if(present(iList)) then
3196
3197        ! TiList is present if its provided and its length>0
3198        TiListIsPresent = .false.
3199        if(present(TiList)) then
3200           if(len_trim(TiList) > 0) then
3201              TiListIsPresent = .true.
3202           endif
3203        endif
3204
3205        if(present(sharedIndices)) then
3206           call warn(myname_,'Use of sharedIndices not implemented in ICopyL; &
3207                     &ignoring sharedIndices',1)
3208        end if
3209
3210        if(TiListIsPresent) then
3211           call ICopyL_(aVin,aVout,iList,TiList,vector=usevector)
3212        else
3213           call ICopyL_(aVin,aVout,iList,vector=usevector)
3214        endif
3215
3216  endif   ! if(present(iList))
3217
3218  ! If neither rList nor iList is present, copy shared attibutes
3219  ! from in to out.
3220  if( .not.present(rList) .and. .not.present(iList)) then
3221
3222     if (present(sharedIndices)) then
3223        call RCopy_(aVin, Avout, vector=usevector, sharedIndices=sharedIndices%shared_real)
3224        call ICopy_(aVin, Avout, vector=usevector, sharedIndices=sharedIndices%shared_integer)
3225     else
3226        call RCopy_(aVin, Avout, vector=usevector)
3227        call ICopy_(aVin, Avout, vector=usevector)
3228     endif
3229
3230  endif
3231
3232 end subroutine Copy_
3233
3234!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3235!    Math and Computer Science Division, Argonne National Laboratory   !
3236!BOP -------------------------------------------------------------------
3237!
3238! !IROUTINE: Sort_ - Use Attributes as Keys to Generate an Index Permutation
3239!
3240! !DESCRIPTION:
3241! The subroutine {\tt Sort\_()} uses a list of keys defined by the {\tt List}
3242! {\tt key\_list}, searches for the appropriate integer or real attributes
3243! referenced by the items in {\tt key\_list} ( that is, it identifies the
3244! appropriate entries in {aV\%iList} and {\tt aV\%rList}), and then
3245! uses these keys to generate a permutation {\tt perm} that will put
3246! the entries of the attribute vector {\tt aV} in lexicographic order
3247! as defined by {\tt key\_list} (the ordering in {\tt key\_list} being from
3248! left to right.
3249!
3250! {\bf N.B.:}  This routine will fail if {\tt aV\%iList} and
3251! {\tt aV\%rList} share one or more common entries.
3252!
3253! {\bf N.B.:}  This routine will fail if one of the sorting keys presented is
3254! not present in {\tt aV\%iList} nor {\tt aV\%rList}.
3255!
3256! !INTERFACE:
3257
3258 subroutine Sort_(aV, key_list, perm, descend, perrWith, dieWith)
3259!
3260! !USES:
3261!
3262      use m_String,        only : String
3263      use m_String,        only : String_tochar => tochar
3264      use m_String,        only : String_clean => clean
3265      use m_List ,         only : List_allocated => allocated
3266      use m_List ,         only : List_index => index
3267      use m_List ,         only : List_nitem => nitem
3268      use m_List ,         only : List_get   => get
3269      use m_die ,          only : die
3270      use m_stdio ,        only : stderr
3271      use m_SortingTools , only : IndexSet
3272      use m_SortingTools , only : IndexSort
3273
3274      implicit none
3275
3276! !INPUT PARAMETERS:
3277!
3278      type(AttrVect),                  intent(in) :: aV
3279      type(List),                      intent(in) :: key_list
3280      logical, dimension(:), optional, intent(in) :: descend
3281      character(len=*),      optional, intent(in) :: perrWith
3282      character(len=*),      optional, intent(in) :: dieWith
3283
3284! !OUTPUT PARAMETERS:
3285!
3286      integer, dimension(:),           pointer    :: perm
3287
3288
3289! !REVISION HISTORY:
3290! 20Oct00 - J.W. Larson <larson@mcs.anl.gov> - initial prototype
3291! 25Apr01 - R.L. Jacob <jacob@mcs.anl.gov> - add -1 to make a
3292!           backwards loop go backwards
3293! 14Jun01 - J. Larson / E. Ong -- Fixed logic bug in REAL attribute
3294!           sort (discovered by E. Ong), and cleaned up error /
3295!           shutdown logic.
3296!EOP ___________________________________________________________________
3297
3298  character(len=*),parameter :: myname_=myname//'::Sort_'
3299
3300! local variables
3301
3302        ! storage for key extracted from key_list:
3303
3304  type(String) :: key
3305
3306        ! number of keys, loop index, error flag, and length:
3307
3308  integer :: nkeys, n, ierr, length
3309
3310        ! key indices for av%rAttr and av%iAttr, respectively:
3311
3312  integer, dimension(:), allocatable :: rIndex, iIndex 
3313
3314        ! copy of descend argument
3315
3316  logical, dimension(:), allocatable :: descend_copy
3317
3318        ! count the sorting keys:
3319
3320  nkeys = List_nitem(key_list)
3321
3322        ! Check the descend argument. Note: the unnecessary copy
3323        ! circumvents an optimization bug in the compaq compiler
3324
3325  if(present(descend)) then
3326     if(size(descend)/=nkeys) then
3327        call die(myname_,"Size of descend argument is not equal &
3328                  &to the number of keys")
3329     endif
3330     allocate(descend_copy(nkeys),stat=ierr)
3331     if(ierr/=0) call die(myname_,"allocate(descend_copy)",ierr)
3332     descend_copy=descend
3333  endif
3334     
3335
3336        ! allocate and initialize rIndex and iIndex to
3337        ! zero (the null return values from the functions
3338        ! indexRA_() and indexIA_() ).
3339
3340  allocate(rIndex(nkeys), iIndex(nkeys), stat=ierr)
3341  if(ierr/=0) call die(myname_,"allocate(rindex,iIndex)",ierr)
3342
3343  rIndex = 0
3344  iIndex = 0
3345
3346        ! Loop over the keys in the list, and identify the
3347        ! appropriate integer or real attribute, storing the
3348        ! attribute index in iIndex(:) or rIndex(:), respectively.
3349
3350  do n = 1, nkeys
3351
3352        ! grab the next key
3353
3354     call List_get(key, n, key_list)
3355
3356        ! determine wheter this key refers to an
3357        ! integer or real attribute:
3358! jwl commented out in favor of below code block unitl an error
3359! handling strategy is settled upon for indexIA_() and indexRA_().
3360!     rIndex(n) = indexRA_(aV, String_tochar(key), dieWith=myname_)
3361!     iIndex(n) = indexIA_(aV, String_tochar(key), dieWith=myname_)
3362
3363     if(List_allocated(aV%rList)) then
3364        rIndex(n) = List_index(aV%rList, String_tochar(key))
3365     else
3366        rIndex(n) = 0
3367     endif
3368     if(List_allocated(aV%iList)) then
3369        iIndex(n) = List_index(aV%iList, String_tochar(key))
3370     else
3371        iIndex(n) = 0
3372     endif
3373
3374        ! If both rIndex(n) and iIndex(n) are greater than
3375        ! zero, then we have an integer attribute sharing
3376        ! the same name as a real attribute, and there is
3377        ! no clear path as to which one is the sort key.
3378        ! This is a fatal error that triggers shutdown.
3379
3380     if ((rIndex(n) > 0) .and. (iIndex(n) > 0)) then
3381        if(.not.present(dieWith)) then
3382           if(present(perrWith)) write(stderr,'(4a)') myname, &
3383                ":: ambiguous key, ", perrWith, &
3384                " both iIndex(n) and rIndex(n) positive."
3385            call die(myname_,":: both iIndex(n) and rIndex(n) > 0.")
3386        else
3387           if(present(perrWith)) then
3388               write(stderr,'(4a)') myname_,":: ", perrWith, &
3389                       " both iIndex(n) and rIndex(n) positive."
3390           endif
3391           call die(myname_,dieWith)
3392        endif
3393     endif
3394
3395        ! If both rIndex(n) and iIndex(n) are nonpositive,
3396        ! then the requested sort key is not present in either
3397        ! aV%rList or aV%iList, and we cannot perform the sort.
3398        ! This is a fatal error that triggers shutdown.
3399
3400     if ((rIndex(n) <= 0) .and. (iIndex(n) <= 0)) then
3401        if(.not.present(dieWith)) then
3402           if(present(perrWith)) write(stderr,'(4a)') myname,":: ", &
3403                perrWith, &
3404                " both iIndex(n) and rIndex(n) nonpositive"
3405           call die(myname_,":: both iIndex(n) and rIndex(n) <= 0.")
3406        else
3407           if(present(perrWith)) then
3408              write(stderr,'(4a)') myname_,":: ", perrWith,     &
3409                   " both iIndex(n) and rIndex(n) nonpositive"
3410           endif
3411           call die(myname_,dieWith)
3412        endif
3413     endif
3414
3415        ! If only one of rIndex(n) or iIndex(n) is positive,
3416        ! set the other value to zero.
3417
3418     if (iIndex(n) > 0) rIndex(n) = 0
3419     if (rIndex(n) > 0) iIndex(n) = 0
3420
3421        ! Clean up temporary string -key-
3422
3423     call String_clean(key)
3424
3425  enddo ! do n=1,nkeys
3426
3427        ! Now we have the locations of the keys in the integer and
3428        ! real attribute storage areas aV%iAttr and aV%rAttr, respectively.
3429        ! our next step is to construct and initialize the permutation
3430        ! array perm.  First step--determine the length of aV using
3431        ! lsize_():
3432
3433  length = lsize_(aV)
3434
3435  allocate(perm(length), stat=ierr)
3436  if(ierr/=0) call die(myname_,"allocate(perm)",ierr)
3437
3438        ! Initialize perm(i)=i, for i=1,length
3439
3440  call IndexSet(perm)
3441
3442        ! Now we can perform the stable successive keyed sorts to
3443        ! transform perm into the permutation that will place the
3444        ! entries of the attribute arrays in the lexicographic order
3445        ! defined by key_list.  This is achieved by successive calls to
3446        ! IndexSort(), but in reverse order to the order of the keys
3447        ! as they appear in key_list.
3448
3449  do n=nkeys, 1, -1
3450     if(iIndex(n) > 0) then
3451        if(present(descend)) then
3452           call IndexSort(length, perm, aV%iAttr(iIndex(n),:), &
3453                          descend_copy(n))
3454        else
3455           call IndexSort(length, perm, aV%iAttr(iIndex(n),:), &
3456                          descend=.false.)
3457        endif ! if(present(descend)...
3458     else
3459        if(rIndex(n) > 0) then
3460           if(present(descend)) then
3461              call IndexSort(length, perm, aV%rAttr(rIndex(n),:), &
3462                             descend_copy(n))
3463           else
3464              call IndexSort(length, perm, aV%rAttr(rIndex(n),:), &
3465                             descend=.false.)
3466           endif ! if(present(descend)...
3467        endif ! if (rIndex(n) > 0)...
3468     endif ! if (iIndex(n) > 0)...
3469  enddo
3470
3471        ! Now perm(1:length) is the transformation we seek--we are
3472        ! finished.
3473
3474  deallocate(iIndex, rIndex, stat=ierr)  ! clean up allocated arrays.
3475  if(ierr/=0) call die(myname_,"deallocate(iIndex,rIndex)",ierr)
3476
3477  if(present(descend)) deallocate(descend_copy,stat=ierr)
3478  if(ierr/=0) call die(myname_,"deallocate(descend_copy)",ierr)
3479
3480 end subroutine Sort_
3481
3482!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3483!    Math and Computer Science Division, Argonne National Laboratory   !
3484!BOP -------------------------------------------------------------------
3485!
3486! !IROUTINE: Permute_ - Permute AttrVect Elements
3487!
3488! !DESCRIPTION:
3489! The subroutine {\tt Permute\_()} uses a a permutation {\tt perm} (which can
3490! be generated by the routine {\tt Sort\_()} in this module) to rearrange
3491! the entries in the attribute integer and real storage areas of the
3492! input attribute vector {\tt aV}--{\tt aV\%iAttr} and {\tt aV\%rAttr},
3493! respectively.
3494!
3495! !INTERFACE:
3496
3497 subroutine Permute_(aV, perm, perrWith, dieWith)
3498!
3499! !USES:
3500!
3501      use m_die ,          only : die
3502      use m_stdio ,        only : stderr
3503      use m_SortingTools , only : Permute
3504
3505      implicit none
3506
3507! !INPUT PARAMETERS:
3508!
3509      integer, dimension(:),           intent(in)    :: perm
3510      character(len=*),      optional, intent(in)    :: perrWith
3511      character(len=*),      optional, intent(in)    :: dieWith
3512
3513! !INPUT/OUTPUT PARAMETERS:
3514!
3515      type(AttrVect),                  intent(inout) :: aV
3516
3517! !REVISION HISTORY:
3518! 23Oct00 - J.W. Larson <larson@mcs.anl.gov> - initial prototype
3519!EOP ___________________________________________________________________
3520
3521  character(len=*),parameter :: myname_=myname//'::Permute_'
3522
3523! local variables
3524
3525  integer :: i
3526
3527        ! Check input arguments for compatibility--assure
3528        ! lsize_(aV) = size(perm); that is, make sure the
3529        ! index permutation is the same length as the vectors
3530        ! it will re-arrange.
3531
3532  if (size(perm) /= lsize_(aV)) then
3533     if(.not.present(dieWith)) then
3534        if(present(perrWith)) write(stderr,'(4a,i8,a,i8)') myname, &
3535          ":: size mismatch, ", perrWith, &
3536          "size(perm)=",size(perm)," lsize_(aV)=",lsize_(aV)
3537     else
3538        write(stderr,'(4a,i8,a,i8)') myname, &
3539         ":: size mismatch, ", dieWith, &
3540         "size(perm)=",size(perm)," lsize_(aV)=",lsize_(aV)
3541        call die(dieWith)
3542     endif
3543  endif
3544
3545  if(size(perm) == lsize_(aV)) then
3546
3547        ! Permute integer attributes:
3548     if(nIAttr_(aV) /= 0) then
3549        do i=1,nIAttr_(aV)
3550           call Permute(aV%iAttr(i,:),perm,lsize_(aV))
3551        end do
3552     endif
3553
3554        ! Permute real attributes:
3555     if(nRAttr_(aV) /= 0) then
3556        do i=1,nRAttr_(aV)
3557           call Permute(aV%rAttr(i,:),perm,lsize_(aV))
3558        end do
3559     endif
3560
3561  endif
3562
3563 end subroutine Permute_
3564
3565!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3566!    Math and Computer Science Division, Argonne National Laboratory   !
3567!BOP -------------------------------------------------------------------
3568!
3569! !IROUTINE: Unpermute_ - Unpermute AttrVect Elements
3570!
3571! !DESCRIPTION:
3572! The subroutine {\tt Unpermute\_()} uses a a permutation {\tt perm} (which can
3573! be generated by the routine {\tt Sort\_()} in this module) to rearrange
3574! the entries in the attribute integer and real storage areas of the
3575! input attribute vector {\tt aV}--{\tt aV\%iAttr} and {\tt aV\%rAttr},
3576! respectively.  This is meant to be called on an {\tt aV} that has already
3577! been permuted but it could also be used to perform the inverse operation
3578! implied by {\tt perm} on an unpermuted {\tt aV}.
3579!
3580! !INTERFACE:
3581
3582 subroutine Unpermute_(aV, perm, perrWith, dieWith)
3583!
3584! !USES:
3585!
3586      use m_die ,          only : die
3587      use m_stdio ,        only : stderr
3588      use m_SortingTools , only : Unpermute
3589
3590      implicit none
3591
3592! !INPUT PARAMETERS:
3593!
3594      integer, dimension(:),           intent(in)    :: perm
3595      character(len=*),      optional, intent(in)    :: perrWith
3596      character(len=*),      optional, intent(in)    :: dieWith
3597
3598! !INPUT/OUTPUT PARAMETERS:
3599!
3600      type(AttrVect),                  intent(inout) :: aV
3601
3602! !REVISION HISTORY:
3603! 23Nov05 - R. Jacob <jacob@mcs.anl.gov> - based on Permute
3604!EOP ___________________________________________________________________
3605
3606  character(len=*),parameter :: myname_=myname//'::Unpermute_'
3607
3608! local variables
3609
3610  integer :: i
3611
3612        ! Check input arguments for compatibility--assure
3613        ! lsize_(aV) = size(perm); that is, make sure the
3614        ! index permutation is the same length as the vectors
3615        ! it will re-arrange.
3616
3617  if (size(perm) /= lsize_(aV)) then
3618     if(.not.present(dieWith)) then
3619        if(present(perrWith)) write(stderr,'(4a,i8,a,i8)') myname, &
3620          ":: size mismatch, ", perrWith, &
3621          "size(perm)=",size(perm)," lsize_(aV)=",lsize_(aV)
3622     else
3623        write(stderr,'(4a,i8,a,i8)') myname, &
3624         ":: size mismatch, ", dieWith, &
3625         "size(perm)=",size(perm)," lsize_(aV)=",lsize_(aV)
3626        call die(dieWith)
3627     endif
3628  endif
3629
3630  if(size(perm) == lsize_(aV)) then
3631
3632        ! Unpermute integer attributes:
3633     if(nIAttr_(aV) /= 0) then
3634        do i=1,nIAttr_(aV)
3635           call Unpermute(aV%iAttr(i,:),perm,lsize_(aV))
3636        end do
3637     endif
3638
3639        ! Permute real attributes:
3640     if(nRAttr_(aV) /= 0) then
3641        do i=1,nRAttr_(aV)
3642           call Unpermute(aV%rAttr(i,:),perm,lsize_(aV))
3643        end do
3644     endif
3645
3646  endif
3647
3648 end subroutine Unpermute_
3649
3650!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3651!    Math and Computer Science Division, Argonne National Laboratory   !
3652!BOP -------------------------------------------------------------------
3653!
3654! !IROUTINE: SortPermute_ - In-place Lexicographic Sort of an AttrVect
3655!
3656! !DESCRIPTION:
3657!
3658! The subroutine {\tt SortPermute\_()} uses the routine {\tt Sort\_()}
3659! to create an index permutation {\tt perm} that will place the AttrVect
3660! entries in the lexicographic order defined by the keys in the List
3661! variable {\tt key\_list}.  This permutation is then used by the routine
3662! {\tt Permute\_()} to place the AttreVect entries in lexicographic order.
3663!
3664! !INTERFACE:
3665
3666 subroutine SortPermute_(aV, key_list, descend, perrWith, dieWith)
3667!
3668! !USES:
3669!
3670      use m_die ,          only : die
3671      use m_stdio ,        only : stderr
3672
3673      implicit none
3674
3675! !INPUT PARAMETERS:
3676!
3677      type(List),                       intent(in)    :: key_list
3678      logical , dimension(:), optional, intent(in)    :: descend
3679      character(len=*),       optional, intent(in)    :: perrWith
3680      character(len=*),       optional, intent(in)    :: dieWith
3681
3682! !INPUT/OUTPUT PARAMETERS:
3683!
3684      type(AttrVect),                   intent(inout) :: aV
3685
3686! !REVISION HISTORY:
3687! 24Oct00 - J.W. Larson <larson@mcs.anl.gov> - initial prototype
3688!EOP ___________________________________________________________________
3689
3690  character(len=*),parameter :: myname_=myname//'::Permute_'
3691
3692! local variables
3693
3694       ! Permutation array pointer perm(:)
3695  integer, dimension(:), pointer :: perm
3696       ! Error flag ierr
3697  integer :: ierr
3698
3699       ! Step One: Generate the index permutation perm(:)
3700
3701  if(present(descend)) then
3702     call Sort_(aV, key_list, perm, descend, perrWith, dieWith)
3703  else
3704     call Sort_(aV, key_list, perm, perrWith=perrWith, &
3705                dieWith=dieWith)
3706  endif
3707
3708       ! Step Two:  Apply the index permutation perm(:)
3709
3710  call Permute_(aV, perm, perrWith, dieWith)
3711
3712       ! Step Three:  deallocate temporary array used to
3713       ! store the index permutation (this was allocated
3714       ! in the routine Sort_()
3715
3716  deallocate(perm, stat=ierr)
3717
3718  end subroutine SortPermute_
3719
3720! Sorting:
3721!
3722!       aV%iVect(:,:) =         &
3723!               aV%iVect((/(indx(i),i=1,lsize(aV))/),:)
3724!
3725!       aV%iVect((/(indx(i),i=1,lsize(aV))/),:) =       &
3726!               aV%iVect(:,:)
3727!
3728!       aV%iVect(:,ikx),aV%iVect(:,iks)
3729!
3730!
3731
3732!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3733!    Math and Computer Science Division, Argonne National Laboratory   !
3734!BOP -------------------------------------------------------------------
3735!
3736! !IROUTINE: aVaVSharedAttrIndexList_ - AttrVect shared attributes.
3737!
3738! !DESCRIPTION:  {\tt aVaVSharedAttrIndexList\_()} takes a pair of
3739! user-supplied {\tt AttrVect} variables {\tt aV1} and {\tt aV2},
3740! and for choice of either {\tt REAL} or {\tt INTEGER} attributes (as
3741! specified literally in the input {\tt CHARACTER} argument {\tt attrib})
3742! returns the number of shared attributes {\tt NumShared}, and arrays of
3743! indices {\tt Indices1} and {\tt Indices2} to their storage locations
3744! in {\tt aV1} and {\tt aV2}, respectively.
3745!
3746! {\bf N.B.:}  This routine returns two allocated arrays---{\tt Indices1(:)}
3747! and {\tt Indices2(:)}---which must be deallocated once the user no longer
3748! needs them.  Failure to do this will create a memory leak.
3749!
3750! !INTERFACE:
3751
3752 subroutine aVaVSharedAttrIndexList_(aV1, aV2, attrib, NumShared, &
3753                                     Indices1, Indices2)
3754
3755!
3756! !USES:
3757!
3758      use m_stdio
3759      use m_die,      only : MP_perr_die, die, warn
3760
3761      use m_List,     only : GetSharedListIndices
3762
3763      implicit none
3764
3765! !INPUT PARAMETERS:
3766!
3767      type(AttrVect),        intent(in)  :: aV1   
3768      type(AttrVect),        intent(in)  :: aV2
3769      character(len=*),      intent(in)  :: attrib
3770
3771! !OUTPUT PARAMETERS:   
3772!
3773      integer,               intent(out) :: NumShared
3774      integer, dimension(:), pointer     :: Indices1
3775      integer, dimension(:), pointer     :: Indices2
3776
3777! !REVISION HISTORY:
3778! 07Feb01 - J.W. Larson <larson@mcs.anl.gov> - initial version
3779!EOP ___________________________________________________________________
3780
3781  character(len=*),parameter :: myname_=myname//'::aVaVSharedAttrIndexList_'
3782
3783  integer :: ierr
3784
3785       ! Based on the value of the argument attrib, pass the
3786       ! appropriate pair of Lists for comparison...
3787
3788  select case(trim(attrib))
3789  case('REAL','real')
3790     call GetSharedListIndices(aV1%rList, aV2%rList, NumShared, &
3791                                 Indices1, Indices2)
3792  case('INTEGER','integer')
3793     call GetSharedListIndices(aV1%iList, aV2%iList, NumShared, &
3794                                 Indices1, Indices2)
3795  case default
3796     write(stderr,'(4a)') myname_,":: value of argument attrib=",attrib, &
3797          " not recognized.  Allowed values: REAL, real, INTEGER, integer"
3798     ierr = 1
3799     call die(myname_, 'invalid value for attrib', ierr)
3800  end select
3801
3802 end subroutine aVaVSharedAttrIndexList_
3803
3804
3805!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3806! Climate and Global Dynamics Division, National Center for Atmospheric Research !
3807!BOP -----------------------------------------------------------------------------
3808!
3809! !IROUTINE: SharedIndices_ - AttrVect shared attributes and auxiliary information
3810!
3811! !DESCRIPTION:  {\tt SharedIndices\_()} takes a pair of user-supplied
3812! {\tt AttrVect} variables {\tt aV1} and {\tt aV2}, and returns a
3813! structure of type {\tt AVSharedIndices} ({\tt sharedIndices}).  This
3814! structure contains arrays of indices to the locations of the shared
3815! attributes, as well as auxiliary information.  The structure contains
3816! information on both the {\tt REAL} and {\tt INTEGER} attributes.  See
3817! documentation for the {\tt SharedIndicesOneType\_} subroutine for some
3818! additional details, as much of the work is done there.
3819!
3820! {\bf N.B.:} The returned structure, {\tt sharedIndices}, contains
3821! allocated arrays that must be deallocated once the user no longer
3822! needs them.  This should be done through a call to {\tt
3823! cleanSharedIndices\_}.
3824!
3825! !INTERFACE:
3826
3827 subroutine SharedIndices_(aV1, aV2, sharedIndices)
3828
3829    implicit none
3830
3831! !INPUT PARAMETERS:
3832!
3833      type(AttrVect),        intent(in)  :: aV1   
3834      type(AttrVect),        intent(in)  :: aV2
3835
3836! !INPUT/OUTPUT PARAMETERS:   
3837!
3838      type(AVSharedIndices), intent(inout) :: sharedIndices
3839
3840! !REVISION HISTORY:
3841! 28Apr11 - W.J. Sacks <sacks@ucar.edu> - initial version
3842!EOP ___________________________________________________________________
3843
3844  character(len=*),parameter :: myname_=myname//'::SharedIndices_'
3845
3846  call SharedIndicesOneType_(aV1, aV2, 'REAL', sharedIndices%shared_real)
3847  call SharedIndicesOneType_(aV1, aV2, 'INTEGER', sharedIndices%shared_integer)
3848
3849 end subroutine SharedIndices_
3850
3851!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3852! Climate and Global Dynamics Division, National Center for Atmospheric Research !
3853!BOP -----------------------------------------------------------------------------
3854!
3855! !IROUTINE: SharedIndicesOneType_ - AttrVect shared attributes and auxiliary information, for one data type
3856!
3857! !DESCRIPTION:  {\tt SharedIndicesOneType\_()} takes a pair of
3858! user-supplied {\tt AttrVect} variables {\tt aV1} and {\tt aV2}, and
3859! for choice of either {\tt REAL} or {\tt INTEGER} attributes (as
3860! specified literally in the input {\tt CHARACTER} argument {\tt
3861! attrib}) returns a structure of type {\tt AVSharedIndicesOneType} ({\tt
3862! sharedIndices}).  This structure contains arrays of indices to the
3863! locations of the shared attributes of the given type, as well as
3864! auxiliary information.
3865!
3866! The {\tt aVindices1} and {\tt aVindices2} components of {\tt
3867! sharedIndices} will be indices into {\tt aV1} and {\tt aV2},
3868! respectively.
3869!
3870! {\bf N.B.:} The returned structure, {\tt sharedIndices}, contains
3871! allocated arrays that must be deallocated once the user no longer
3872! needs them.  This should be done through a call to {\tt
3873! cleanSharedIndicesOneType\_}.  Even if there are no attributes in
3874! common between {\tt aV1} and {\tt aV2}, {\tt sharedIndices} will still
3875! be initialized, and memory will still be allocated. Furthermore, if an
3876! already-initialized {\tt sharedIndices} variable is to be given new
3877! values, {\tt cleanSharedIndicesOneType\_} must be called before {\tt
3878! SharedIndicesOneType\_} is called a second time, in order to prevent a
3879! memory leak.
3880!
3881! !INTERFACE:
3882
3883 subroutine SharedIndicesOneType_(aV1, aV2, attrib, sharedIndices)
3884
3885    implicit none
3886
3887! !INPUT PARAMETERS:
3888!
3889      type(AttrVect),        intent(in)  :: aV1   
3890      type(AttrVect),        intent(in)  :: aV2
3891      character(len=*),      intent(in)  :: attrib
3892
3893! !INPUT/OUTPUT PARAMETERS:   
3894!
3895      type(AVSharedIndicesOneType), intent(inout) :: sharedIndices
3896
3897! !REVISION HISTORY:
3898! 28Apr11 - W.J. Sacks <sacks@ucar.edu> - initial version
3899!EOP ___________________________________________________________________
3900
3901  character(len=*),parameter :: myname_=myname//'::SharedIndicesOneType_'
3902  integer :: i
3903
3904  ! Check appropriate attributes (real or integer) for matching indices
3905  call aVaVSharedAttrIndexList_(aV1, aV2, attrib, sharedIndices%num_indices, &
3906                                   sharedIndices%aVindices1, sharedIndices%aVindices2)
3907
3908  sharedIndices%data_flag = attrib
3909
3910  ! Check indices for contiguous segments in memory
3911  sharedIndices%contiguous=.true.
3912  do i=2,sharedIndices%num_indices
3913     if(sharedIndices%aVindices1(i) /= sharedIndices%aVindices1(i-1)+1) then
3914        sharedIndices%contiguous = .false.
3915     endif
3916  enddo
3917  if(sharedIndices%contiguous) then
3918     do i=2,sharedIndices%num_indices
3919        if(sharedIndices%aVindices2(i) /= sharedIndices%aVindices2(i-1)+1) then
3920           sharedIndices%contiguous=.false.
3921        endif
3922     enddo
3923  endif
3924
3925 end subroutine SharedIndicesOneType_
3926
3927
3928!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3929! Climate and Global Dynamics Division, National Center for Atmospheric Research !
3930!BOP -----------------------------------------------------------------------------
3931!
3932! !IROUTINE: cleanSharedIndices_ - Deallocate allocated memory structures of an AVSharedIndices structure
3933!
3934! !DESCRIPTION: This routine deallocates the allocated memory structures
3935! of the input/output {\tt AVSharedIndicesOneType} argument {\tt
3936! sharedIndices}, if they are currently associated.  It also resets
3937! other components of this structure to a default state.  The success
3938! (failure) of this operation is signified by a zero (non-zero) value of
3939! the optional {\tt INTEGER} output argument {\tt stat}.  If {\tt
3940! clean\_()} is invoked without supplying {\tt stat}, and any of the
3941! deallocation operations fail, the routine will terminate with an error
3942! message.  If multiple errors occur, {\tt stat} will give the error
3943! condition for the last error.
3944!
3945! !INTERFACE:
3946
3947 subroutine cleanSharedIndices_(sharedIndices, stat)
3948
3949    implicit none
3950
3951! !INPUT/OUTPUT PARAMETERS:   
3952!
3953      type(AVSharedIndices), intent(inout) :: sharedIndices
3954
3955! !OUTPUT PARAMETERS:
3956!
3957      integer, optional, intent(out)       :: stat
3958
3959! !REVISION HISTORY:
3960! 28Apr11 - W.J. Sacks <sacks@ucar.edu> - initial version
3961!EOP ___________________________________________________________________
3962
3963  character(len=*),parameter :: myname_=myname//'::cleanSharedIndices_'
3964  integer :: ier
3965
3966  if(present(stat)) stat=0
3967
3968  call cleanSharedIndicesOneType_(sharedIndices%shared_real, stat=ier)
3969  if(present(stat) .and. ier /= 0) then
3970     stat = ier
3971  end if
3972
3973  call cleanSharedIndicesOneType_(sharedIndices%shared_integer, stat=ier)
3974  if(present(stat) .and. ier /= 0) then
3975     stat = ier
3976  end if
3977
3978 end subroutine cleanSharedIndices_
3979
3980!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3981! Climate and Global Dynamics Division, National Center for Atmospheric Research !
3982!BOP -----------------------------------------------------------------------------
3983!
3984! !IROUTINE: cleanSharedIndicesOneType_ - Deallocate allocated memory structures of an AVSharedIndicesOneType structure
3985!
3986! !DESCRIPTION: This routine deallocates the allocated memory structures
3987! of the input/output {\tt AVSharedIndices} argument {\tt
3988! sharedIndices}, if they are currently associated.  It also resets
3989! other components of this structure to a default state.  The success
3990! (failure) of this operation is signified by a zero (non-zero) value of
3991! the optional {\tt INTEGER} output argument {\tt stat}.  If {\tt
3992! clean\_()} is invoked without supplying {\tt stat}, and any of the
3993! deallocation operations fail, the routine will terminate with an error
3994! message.  If multiple errors occur, {\tt stat} will give the error
3995! condition for the last error.
3996!
3997! !INTERFACE:
3998
3999 subroutine cleanSharedIndicesOneType_(sharedIndices, stat)
4000!
4001! !USES:
4002!
4003      use m_die,      only : die
4004
4005    implicit none
4006
4007! !INPUT/OUTPUT PARAMETERS:   
4008!
4009      type(AVSharedIndicesOneType), intent(inout) :: sharedIndices
4010
4011! !OUTPUT PARAMETERS:
4012!
4013      integer, optional, intent(out)       :: stat
4014
4015! !REVISION HISTORY:
4016! 28Apr11 - W.J. Sacks <sacks@ucar.edu> - initial version
4017!EOP ___________________________________________________________________
4018
4019  character(len=*),parameter :: myname_=myname//'::cleanSharedIndicesOneType_'
4020  integer :: ier
4021
4022  if(present(stat)) stat=0
4023
4024  if(associated(sharedIndices%aVindices1)) then
4025     
4026     deallocate(sharedIndices%aVindices1,stat=ier)
4027
4028     if (ier /= 0) then
4029        if(present(stat)) then
4030           stat=ier
4031        else
4032           call die(myname_,'deallocate(sharedIndices%aVindices1)',ier)
4033        endif
4034     endif
4035
4036  endif
4037
4038  if(associated(sharedIndices%aVindices2)) then
4039     
4040     deallocate(sharedIndices%aVindices2,stat=ier)
4041
4042     if (ier /= 0) then
4043        if(present(stat)) then
4044           stat=ier
4045        else
4046           call die(myname_,'deallocate(sharedIndices%aVindices2)',ier)
4047        endif
4048     endif
4049
4050  endif 
4051       
4052  ! Reset other components to default values
4053  sharedIndices%num_indices = 0
4054  sharedIndices%contiguous = .false.
4055  sharedIndices%data_flag = ' '
4056
4057  end subroutine cleanSharedIndicesOneType_
4058
4059 end module m_AttrVect
4060!.
4061
4062
4063
4064
Note: See TracBrowser for help on using the repository browser.