source: CPL/oasis3-mct/branches/OASIS3-MCT_2.0_branch/lib/mct/mct/m_GeneralGrid.F90 @ 4775

Last change on this file since 4775 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: 109.3 KB
Line 
1!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2!    Math and Computer Science Division, Argonne National Laboratory   !
3!-----------------------------------------------------------------------
4! CVS m_GeneralGrid.F90,v 1.36 2008-05-12 01:57:21 jacob Exp
5! CVS MCT_2_8_0
6!BOP -------------------------------------------------------------------
7!
8! !MODULE: m_GeneralGrid -- Physical Coordinate Grid Information Storage
9!
10! !DESCRIPTION:
11! The {\tt GeneralGrid} data type is a flexible, generic structure for
12! storing physical coordinate grid information.  The {\tt GeneralGrid}
13! may be employed to store coordinate grids of arbitrary dimension, and
14! is also capable of supporting unstructured grids such as meteorological
15! observation data streams.  The grid is representated by a literal
16! listing of the gridpoint coordinates, along with other integer and real
17! {\em attributes} associated with each location.  Examples of real
18! non-coordinate attributes are grid cell length, cross-sectional area, and
19! volume elements, projections of local directional unit vectors onto
20! {\em et cetera}  A {\tt GeneralGrid} as at minimum one integer
21! attribute---{\em the global grid point number}, or {\tt GlobGridNum},
22! which serves as a unique identifier for each physical grid location.
23!
24! The real attributes of of the {\tt GeneralGrid} are grouped as {\tt List}
25! components:
26! \begin{itemize}
27! \item {\tt GGrid\%coordinate\_list} contains the list of the physical
28! dimension names of the grid.  The user initializes a {\tt List} by
29! supplying the items in it as a string with the items delimitted by
30! colons.  For example, setting the coordinates for Euclidean 3-space
31! is accomplished by a choice of {\tt 'x:y:z'}, cylindrical coordinates
32! by {\tt 'rho:theta:z'}, spherical coordinates by {\tt 'r:theta:phi'},
33! {\em et cetera}.
34! \item {\tt GGrid\%weight\_list} contains the names of the spatial
35! cell length, area, and volume weights associated with the grid.  These
36! are also stored in {\tt List} form, and are set by the user in the same
37! fashion as described above for coordinates.  For example, one might
38! wish create cell weight attributes for a cylindrical grid by defining
39! a weight list of {\tt 'drho:dphi:rhodphi:dz}.
40! \item {\tt GGrid\%other\_list} is space for the user to define other
41! real attributes.  For example, one might wish to do vector calculus
42! operatons in spherical coordinates.  Since the spherical coordinate
43! unit vectors ${\hat r}$, ${\hat \theta}$, and ${\hat \phi}$
44! vary in space, it is sometimes useful to store their projections on
45! the fixed Euclidean unit vectors ${\bf \hat x}$, ${\bf \hat y}$, and
46! ${\bf \hat z}$.  To do this one might set up a list of attributes
47! using the string
48! \begin{verbatim}
49! 'rx:ry:rz:thetax:thetay:thetaz:phix:phiy:phyz'
50! \end{verbatim}
51! \item {\tt GGrid\%index\_list} provides space for the user to define
52! integer attributes such as alternative indexing schemes, indices for
53! defining spatial regions, {\em et cetera}.  This attribute list contains
54! all the integer attributes for the {\tt GeneralGrid} save one:  the
55! with the ever-present {\em global gridpoint number attribute}
56! {\tt GlobGridNum}, which is set automatically by MCT.
57! \end{itemize}
58!
59! This module contains the definition of the {\tt GeneralGrid} datatype,
60! various methods for creating and destroying it, query methods, and tools
61! for multiple-key sorting of gridpoints.
62!
63! !INTERFACE:
64
65 module m_GeneralGrid
66
67!
68! !USES:
69!
70      use m_List, only : List   ! Support for List components.
71
72      use m_AttrVect, only : AttrVect ! Support for AttrVect component.
73
74      implicit none
75
76      private   ! except
77
78! !PUBLIC TYPES:
79
80      public :: GeneralGrid      ! The class data structure
81
82    Type GeneralGrid
83#ifdef SEQUENCE
84      sequence
85#endif
86      type(List)                     :: coordinate_list
87      type(List)                     :: coordinate_sort_order
88      logical, dimension(:), pointer :: descend
89      type(List)                     :: weight_list
90      type(List)                     :: other_list
91      type(List)                     :: index_list
92      type(AttrVect)                 :: data
93    End Type GeneralGrid
94
95! !PUBLIC MEMBER FUNCTIONS:
96
97      public :: init             ! Create a GeneralGrid
98      public :: initCartesian    !
99      public :: initUnstructured !
100      public :: clean            ! Destroy a GeneralGrid
101      public :: zero             ! Zero data in a GeneralGrid
102
103                             ! Query functions-----------------
104      public :: dims         ! Return dimensionality of the GeneralGrid
105      public :: indexIA      ! Index integer attribute (indices)
106      public :: indexRA      ! Index integer attribute (coords/weights)
107      public :: lsize        ! Return local number of points
108      public :: exportIAttr  ! Return INTEGER attribute as a vector
109      public :: exportRAttr  ! Return REAL attribute as a vector
110
111                             ! Manipulation--------------------
112      public :: importIAttr  ! Insert INTEGER vector as attribute
113      public :: importRAttr  ! Insert REAL vector as attribute
114      public :: Sort         ! Sort point data by coordinates -> permutation
115      public :: Permute      ! Rearrange point data using input permutation
116      public :: SortPermute  ! Sort and Permute point data
117
118    interface init  ; module procedure &
119        init_, &
120        initl_, &
121        initgg_
122    end interface
123    interface initCartesian ; module procedure &
124        initCartesianSP_, &
125        initCartesianDP_
126    end interface
127    interface initUnstructured ; module procedure &
128        initUnstructuredSP_, &
129        initUnstructuredDP_
130    end interface
131    interface clean ; module procedure clean_ ; end interface
132    interface zero ; module procedure zero_ ; end interface
133
134    interface dims ; module procedure dims_ ; end interface
135    interface indexIA ; module procedure indexIA_ ; end interface
136    interface indexRA ; module procedure indexRA_ ; end interface
137    interface lsize   ; module procedure lsize_   ; end interface
138
139    interface exportIAttr ; module procedure exportIAttr_ ; end interface
140    interface exportRAttr ; module procedure &
141       exportRAttrSP_, &
142       exportRAttrDP_
143    end interface
144    interface importIAttr ; module procedure importIAttr_ ; end interface
145    interface importRAttr ; module procedure &
146       importRAttrSP_, &
147       importRAttrDP_
148    end interface
149
150    interface Sort    ; module procedure Sort_    ; end interface
151    interface Permute ; module procedure Permute_ ; end interface
152    interface SortPermute ; module procedure SortPermute_ ; end interface
153
154! !PUBLIC DATA MEMBERS:
155
156! CHARACTER Tag for GeneralGrid Global Grid Point Identification Number
157
158  character(len=*), parameter :: GlobGridNum='GlobGridNum'
159
160! !SEE ALSO:
161! The MCT module m_AttrVect and the mpeu module m_List.
162
163! !REVISION HISTORY:
164! 25Sep00 - J.W. Larson <larson@mcs.anl.gov> - initial prototype
165! 31Oct00 - J.W. Larson <larson@mcs.anl.gov> - modified the
166!           GeneralGrid type to allow inclusion of grid cell
167!           dimensions (lengths) and area/volume weights.
168! 15Jan01 - J.W. Larson implemented new GeneralGrid type
169!           definition and added numerous APIs.
170! 17Jan01 - J.W. Larson fixed minor bug in module header use
171!           statement.
172! 19Jan01 - J.W. Larson added other_list and coordinate_sort_order
173!           components to the GeneralGrid type.
174! 21Mar01 - J.W. Larson - deleted the initv_ API (more study
175!           needed before implementation.
176!  2May01 - J.W. Larson - added initgg_ API (replaces old initv_).
177! 13Dec01 - J.W. Larson - added import and export methods.
178! 27Mar02 - J.W. Larson <larson@mcs.anl.gov> - Corrected usage of
179!           m_die routines throughout this module.
180!  5Aug02 - E. Ong <eong@mcs.anl.gov> - Modified GeneralGrid usage
181!           to allow user-defined grid numbering schemes.
182!EOP ___________________________________________________________________
183
184  character(len=*),parameter :: myname='MCT::m_GeneralGrid'
185
186 contains
187
188!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
189!    Math and Computer Science Division, Argonne National Laboratory   !
190!BOP -------------------------------------------------------------------
191!
192! !IROUTINE: init_ - Create an Empty GeneralGrid
193!
194! !DESCRIPTION:
195! The routine {\tt init\_()} creates the storage space for grid point
196! coordinates, area/volume weights, and other coordinate data ({\em e.g.},
197! local cell dimensions).  These data are referenced by {\tt List}
198! components that are also created by this routine (see the documentation
199! of the declaration section of this module for more details about setting
200! list information).  Each of the input {\tt CHARACTER} arguments is a
201! colon-delimited string of attribute names, each corrsponding to a
202! {\tt List} element of the output {\tt GeneralGrid} argument {\tt GGrid},
203! and are summarized in the table below:
204!
205!\begin{table}[htbp]
206!\begin{center}
207!\begin{tabular}{|l|l|l|l|}
208!\hline
209!{\bf Argument} & {\bf Component of {\tt GGrid}} & {\bf Significance} & {\bf Required?} \\
210!\hline
211!{\tt CoordChars} & {\tt GGrid\%coordinate\_list} & Dimension Names & Yes \\
212!\hline
213!{\tt CoordSortOrder} & {\tt GGrid\%coordinate\_sort\_order} & Grid Point & No \\
214! & & Sorting Keys & \\
215!\hline
216!{\tt WeightChars} & {\tt GGrid\%weight\_list} & Grid Cell & No \\
217! & & Length, Area, and & \\
218! & & Volume Weights & \\
219!\hline
220!{\tt OtherChars} & {\tt GGrid\%other\_list} & All Other & No \\
221! & & Real Attributes & \\
222!\hline
223!{\tt IndexChars} & {\tt GGrid\%index\_list} & All Other & No \\
224! & & Integer Attributes & \\
225!\hline
226!\end{tabular}
227!\end{center}
228!\end{table}
229!
230! The input {\tt INTEGER} argument {\tt lsize} defines the number of grid points
231! to be stored in {\tt GGrid}.
232!
233! If a set of sorting keys is supplied in the argument {\tt CoordSortOrder},
234! the user can control whether the sorting by each key is in descending or
235! ascending order by supplying the input {\tt LOGICAL} array {\tt descend(:)}. 
236! By default, all sorting is in {\em ascending} order for each key if the
237! argument {\tt descend} is not provided.
238!
239! {\bf N.B.}:  The output {\tt GeneralGrid} {\tt GGrid} is dynamically
240! allocated memory.  When one no longer needs {\tt GGrid}, one should
241! release this space by invoking {\tt clean()} for the {\tt GeneralGrid}.
242!
243! !INTERFACE:
244
245 subroutine init_(GGrid, CoordChars, CoordSortOrder, descend, WeightChars, &
246                  OtherChars, IndexChars, lsize )
247!
248! !USES:
249!
250      use m_stdio
251      use m_die
252
253      use m_List,     only : List
254      use m_List,     only : List_init => init
255      use m_List,     only : List_nitem => nitem
256      use m_List,     only : List_shared => GetSharedListIndices
257      use m_List,     only : List_append => append
258      use m_List,     only : List_copy => copy
259      use m_List,     only : List_nullify => nullify
260      use m_List,     only : List_clean => clean
261
262      use m_AttrVect, only : AttrVect
263      use m_AttrVect, only : AttrVect_init => init
264
265      implicit none
266
267! !INPUT PARAMETERS:
268!
269      character(len=*),                intent(in) :: CoordChars
270      character(len=*),      optional, intent(in) :: CoordSortOrder
271      character(len=*),      optional, intent(in) :: WeightChars
272      logical, dimension(:), optional, pointer    :: descend
273      character(len=*),      optional, intent(in) :: OtherChars
274      character(len=*),      optional, intent(in) :: IndexChars
275      integer,               optional, intent(in) :: lsize
276
277! !OUTPUT PARAMETERS:
278!
279      type(GeneralGrid), intent(out)   :: GGrid
280
281! !REVISION HISTORY:
282! 25Sep00 - Jay Larson <larson@mcs.anl.gov> - initial prototype
283! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - modified to fit
284!           new GeneralGrid definition. 
285! 19Mar01 - Jay Larson <larson@mcs.anl.gov> - added OtherChars
286! 25Apr01 - Jay Larson <larson@mcs.anl.gov> - added GlobGridNum
287!           as a mandatory integer attribute.
288! 13Jun01 - Jay Larson <larson@mcs.anl.gov> - No longer define
289!           blank List attributes of the GeneralGrid.  Previous
290!           versions of this routine had this feature, and this
291!           caused problems with the GeneralGrid Send and Receive
292!           operations on the AIX platform.
293! 13Jun01 - R. Jacob <jacob@mcs.anl.gov> - nullify any pointers
294!           for lists not declared.
295! 15Feb02 - Jay Larson <larson@mcs.anl.gov> - made the input
296!           argument CoordSortOrder mandatory (rather than
297!           optional).
298! 18Jul02 - E. Ong <eong@mcs.anl.gov> - replaced this version of
299!           init with one that calls initl_.
300!  5Aug02 - E. Ong <eong@mcs.anl.gov> - made the input argument
301!           CoordSortOrder optional to allow user-defined grid
302!           numbering schemes.
303!EOP ___________________________________________________________________
304!
305  character(len=*),parameter :: myname_=myname//'::init_'
306
307  ! List to store real and integer attributes
308  type(List) :: RAList, IAList
309
310  ! Overlapping index storage arrays:
311  integer, dimension(:), pointer :: &
312       CoordListIndices, CoordSortOrderIndices
313
314  ! Temporary vars
315  integer :: NumShared, nitems, i, l, ierr
316
317       ! Let's begin by nullifying everything:
318
319  call List_nullify(GGrid%coordinate_list)
320  call List_nullify(GGrid%coordinate_sort_order)
321  call List_nullify(GGrid%weight_list)
322  call List_nullify(GGrid%other_list)
323  call List_nullify(GGrid%index_list)
324  nullify(GGrid%descend)
325
326        ! Convert the Character arguments to the appropriate
327        ! GeneralGrid components.
328
329        ! Set up the integer and real attribute lists.
330
331  call List_init(GGrid%coordinate_list,trim(CoordChars))
332  call List_copy(RAList,GGrid%coordinate_list)
333
334  if(present(CoordSortOrder)) then
335     call List_init(GGrid%coordinate_sort_order,trim(CoordSortOrder))
336  endif
337
338  if(present(WeightChars)) then
339     call List_init(GGrid%weight_list,trim(WeightChars))
340     call List_append(RAList, GGrid%weight_list)
341  endif
342
343  if(present(OtherChars)) then
344     call List_init(GGrid%other_list,trim(OtherChars))
345     call List_append(RAList, GGrid%other_list)
346  endif
347
348  call List_init(IAList,GlobGridNum)
349
350  if(present(IndexChars)) then
351     call List_init(GGrid%index_list,trim(IndexChars))
352     call List_append(IAList, GGrid%index_list)
353  endif
354
355        ! Check the lists that we've initialized :
356
357  nitems = List_nitem(GGrid%coordinate_list)
358
359        ! Check the number of coordinates
360
361  if(nitems <= 0) then
362     write(stderr,*) myname_, &
363          ':: ERROR CoordList is empty!'
364     call die(myname_,'List_nitem(CoordList) <= 0',nitems)
365  endif
366
367        ! Check the items in the coordinate list and the
368        ! coordinate grid sort keys...they should contain
369        ! the same items.
370
371  if(present(CoordSortOrder)) then
372
373     call List_shared(GGrid%coordinate_list,GGrid%coordinate_sort_order, &
374                      NumShared,CoordListIndices,CoordSortOrderIndices)
375
376     deallocate(CoordListIndices,CoordSortOrderIndices,stat=ierr)
377     if(ierr/=0) call die(myname_,'deallocate(CoordListIndices..)',ierr)
378     
379     if(NumShared /= nitems) then
380        call die(myname_,'CoordSortOrder must have the same items &
381                 & as CoordList',abs(nitems-NumShared))
382     endif
383
384  endif
385
386        ! If the LOGICAL argument descend is present, check the
387        ! number of entries to ensure they match the grid dimensionality.
388        ! If descend is not present, assume all coordinate grid point
389        ! sortings will be in ascending order.
390
391  if(present(descend)) then
392
393     if( ( (.not.associated(descend)) .or. &
394           (.not.present(CoordSortOrder)) ) .or. &
395           (size(descend) /= nitems) ) then
396       
397        write(stderr,*) myname_, &
398             ':: ERROR using descend argument, &
399             &associated(descend) = ', associated(descend), &
400             ' present(CoordSortOrder) = ', present(CoordSortOrder), &
401             ' size(descend) = ', size(descend), &
402             ' List_nitem(CoordSortOrder) = ', &
403             List_nitem(GGrid%coordinate_sort_order)
404        call die(myname_, 'ERROR using -descend- argument; &
405             & see stderr file for details')
406     endif
407
408  endif
409
410       ! Finally, Initialize GGrid%descend from descend(:).
411       ! If descend argument is not present, set it to the default .false.
412
413  if(present(CoordSortOrder)) then
414
415     allocate(GGrid%descend(nitems), stat=ierr)
416     if(ierr /= 0) call die(myname_,"allocate GGrid%descend...",ierr)
417
418     if(present(descend)) then
419
420        do i=1,nitems
421           GGrid%descend(i) = descend(i)
422        enddo
423
424     else
425
426        do i=1,nitems
427           GGrid%descend(i) = .FALSE.
428        enddo
429
430     endif
431       
432  endif
433 
434       ! Initialize GGrid%data using IAList, RAList, and lsize (if
435       ! present).
436
437  l = 0
438  if(present(lsize)) l=lsize
439
440  call AttrVect_init(GGrid%data, IAList, RAList, l)
441
442
443       ! Deallocate the temporary variables
444
445  call List_clean(IAList)
446  call List_clean(RAList)
447 
448 end subroutine init_
449
450!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
451!    Math and Computer Science Division, Argonne National Laboratory   !
452!BOP -------------------------------------------------------------------
453!
454! !IROUTINE: initl_ - Create an Empty GeneralGrid from Lists
455!
456! !DESCRIPTION:
457! The routine {\tt initl\_()} creates the storage space for grid point
458! coordinates, area/volume weights, and other coordinate data ({\em e.g.},
459! local cell dimensions).  These data are referenced by {\tt List}
460! components that are also created by this routine (see the documentation
461! of the declaration section of this module for more details about setting
462! list information).  Each of the input {\tt List} arguments is used
463! directly to create the corresponding
464! {\tt List} element of the output {\tt GeneralGrid} argument {\tt GGrid},
465! and are summarized in the table below:
466!
467!\begin{table}[htbp]
468!\begin{center}
469!\begin{tabular}{|l|l|l|l|}
470!\hline
471!{\bf Argument} & {\bf Component of {\tt GGrid}} & {\bf Significance} & {\bf Required?} \\
472!\hline
473!{\tt CoordList} & {\tt GGrid\%coordinate\_list} & Dimension Names & Yes \\
474!\hline
475!{\tt CoordSortOrder} & {\tt GGrid\%coordinate\_sort\_order} & Grid Point & No \\
476! & & Sorting Keys & \\
477!\hline
478!{\tt WeightList} & {\tt GGrid\%weight\_list} & Grid Cell & No \\
479! & & Length, Area, and & \\
480! & & Volume Weights & \\
481!\hline
482!{\tt OtherList} & {\tt GGrid\%other\_list} & All Other & No \\
483! & & Real Attributes & \\
484!\hline
485!{\tt IndexList} & {\tt GGrid\%index\_list} & All Other & No \\
486! & & Integer Attributes & \\
487!\hline
488!\end{tabular}
489!\end{center}
490!\end{table}
491!
492! The input {\tt INTEGER} argument {\tt lsize} defines the number of grid points
493! to be stored in {\tt GGrid}.
494!
495! If a set of sorting keys is supplied in the argument {\tt CoordSortOrder},
496! the user can control whether the sorting by each key is in descending or
497! ascending order by supplying the input {\tt LOGICAL} array {\tt descend(:)}. 
498! By default, all sorting is in {\em ascending} order for each key if the
499! argument {\tt descend} is not provided.
500!
501! {\bf N.B.}:  The output {\tt GeneralGrid} {\tt GGrid} is dynamically
502! allocated memory.  When one no longer needs {\tt GGrid}, one should
503! release this space by invoking {\tt clean()} for the {\tt GeneralGrid}.
504!
505! !INTERFACE:
506
507 subroutine initl_(GGrid, CoordList, CoordSortOrder, descend, WeightList, &
508                   OtherList, IndexList, lsize )
509!
510! !USES:
511!
512
513      use m_stdio
514      use m_die
515
516      use m_List,     only : List
517      use m_List,     only : List_init => init
518      use m_List,     only : List_allocated => allocated
519      use m_List,     only : List_nitem => nitem
520      use m_List,     only : List_shared => GetSharedListIndices
521      use m_List,     only : List_append => append
522      use m_List,     only : List_copy => copy
523      use m_List,     only : List_nullify => nullify
524      use m_List,     only : List_clean => clean
525
526      use m_AttrVect, only : AttrVect
527      use m_AttrVect, only : AttrVect_init => init
528
529      implicit none
530
531! !INPUT PARAMETERS:
532!
533      Type(List),                      intent(in)  :: CoordList
534      Type(List),            optional, intent(in)  :: CoordSortOrder
535      Type(List),            optional, intent(in)  :: WeightList
536      logical, dimension(:), optional, pointer     :: descend
537      Type(List),            optional, intent(in)  :: OtherList
538      Type(List),            optional, intent(in)  :: IndexList
539      integer,               optional, intent(in)  :: lsize
540
541! !OUTPUT PARAMETERS:
542!
543      type(GeneralGrid),               intent(out) :: GGrid
544
545! !REVISION HISTORY:
546! 10May01 - Jay Larson <larson@mcs.anl.gov> - initial version
547!  8Aug01 - E.T. Ong <eong@mcs.anl.gov> - changed list assignment(=)
548!           to list copy to avoid compiler bugs with pgf90
549! 17Jul02 - E. Ong <eong@mcs.anl.gov> - general revision;
550!           added error checks
551!  5Aug02 - E. Ong <eong@mcs.anl.gov> - made input argument
552!           CoordSortOrder optional to allow for user-defined
553!           grid numbering schemes
554!EOP ___________________________________________________________________
555!
556  character(len=*),parameter :: myname_=myname//'::initl_'
557
558  ! List to store real and integer attributes
559  type(List) :: RAList, IAList
560
561  ! Overlapping attribute index storage arrays:
562  integer, dimension(:), pointer :: &
563       CoordListIndices, CoordSortOrderIndices
564
565  ! Temporary vars
566  integer :: NumShared, nitems, i, l, ierr
567
568       ! Let's begin by nullifying everything:
569
570  call List_nullify(GGrid%coordinate_list)
571  call List_nullify(GGrid%coordinate_sort_order)
572  call List_nullify(GGrid%weight_list)
573  call List_nullify(GGrid%other_list)
574  call List_nullify(GGrid%index_list)
575  nullify(GGrid%descend)
576
577        ! Check the arguments:
578
579  nitems = List_nitem(CoordList)
580
581        ! Check the number of coordinates
582
583  if(nitems <= 0) then
584     write(stderr,*) myname_, &
585          ':: ERROR CoordList is empty!'
586     call die(myname_,'List_nitem(CoordList) <= 0',nitems)
587  endif
588
589        ! Check the items in the coordinate list and the
590        ! coordinate grid sort keys...they should contain
591        ! the same items.
592
593  if(present(CoordSortOrder)) then
594
595     call List_shared(CoordList,CoordSortOrder,NumShared, &
596                      CoordListIndices,CoordSortOrderIndices)
597
598     deallocate(CoordListIndices,CoordSortOrderIndices,stat=ierr)
599     if(ierr/=0) call die(myname_,'deallocate(CoordListIndices..)',ierr)
600     
601     if(NumShared /= nitems) then
602        call die(myname_,'CoordSortOrder must have the same items &
603                 & as CoordList',abs(nitems-NumShared))
604     endif
605
606  endif
607
608        ! If the LOGICAL argument descend is present, check the
609        ! number of entries to ensure they match the grid dimensionality.
610        ! If descend is not present, assume all coordinate grid point
611        ! sortings will be in ascending order.
612
613  if(present(descend)) then
614
615     if( ( (.not.associated(descend)) .or. &
616           (.not.present(CoordSortOrder)) ) .or. &
617           (size(descend) /= nitems) ) then
618       
619        write(stderr,*) myname_, &
620             ':: ERROR using descend argument, &
621             &associated(descend) = ', associated(descend), &
622             ' present(CoordSortOrder) = ', present(CoordSortOrder), &
623             ' size(descend) = ', size(descend), &
624             ' List_nitem(CoordSortOrder) = ', &
625             List_nitem(CoordSortOrder)
626        call die(myname_, 'ERROR using -descend- argument; &
627             &stderr file for details')
628     endif
629
630  endif
631
632       ! Initialize GGrid%descend from descend(:), if present.  If
633       ! the argument descend(:) was not passed, set GGrid%descend
634       ! to the default .false.
635
636  if(present(CoordSortOrder)) then
637
638     allocate(GGrid%descend(nitems), stat=ierr)
639     if(ierr /= 0) call die(myname_,"allocate GGrid%descend...",ierr)
640
641     if(present(descend)) then
642
643        do i=1,nitems
644           GGrid%descend(i) = descend(i)
645        enddo
646
647     else
648
649        do i=1,nitems
650           GGrid%descend(i) = .FALSE.
651        enddo
652
653     endif
654
655  endif
656 
657       ! Process input lists and create the appropriate GeneralGrid
658       ! List components
659
660  call List_copy(GGrid%coordinate_list,CoordList)
661  call List_copy(RAList,CoordList)
662
663  if(present(CoordSortOrder)) then
664     if(List_allocated(CoordSortOrder)) then
665        call List_copy(GGrid%coordinate_sort_order,CoordSortOrder)
666     else
667        call die(myname_,"Argument CoortSortOrder not allocated")
668     endif
669  endif
670
671       ! Concatenate present input Lists to create RAList, and
672       ! at the same time assign the List components of GGrid
673
674  if(present(WeightList)) then
675     if(List_allocated(WeightList)) then
676        call List_copy(GGrid%weight_list,WeightList)
677        call List_append(RAList, WeightList)
678     else
679        call die(myname_,"Argument WeightList not allocated")
680     endif
681  endif
682
683  if(present(OtherList)) then
684     if(List_allocated(OtherList)) then
685        call List_copy(GGrid%other_list,OtherList)
686        call List_append(RAList, OtherList)
687     else
688        call die(myname_,"Argument OtherList not allocated")
689     endif
690  endif
691
692       ! Concatenate present input Lists to create IAList
693
694  call List_init(IAList,GlobGridNum)
695
696  if(present(IndexList)) then
697     call List_copy(GGrid%index_list,IndexList)
698     call List_append(IAList, IndexList)
699  endif
700
701       ! Initialize GGrid%data using IAList, RAList, and lsize (if
702       ! present).
703
704  l = 0
705  if(present(lsize)) l = lsize
706
707  call AttrVect_init(GGrid%data, IAList, RAList, l)
708
709       ! Deallocate the temporary variables
710
711  call List_clean(IAList)
712  call List_clean(RAList)
713
714 end subroutine initl_
715
716!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
717!    Math and Computer Science Division, Argonne National Laboratory   !
718!BOP -------------------------------------------------------------------
719!
720! !IROUTINE: initgg_ - Create a GeneralGrid from Another
721!
722! !DESCRIPTION:
723! The routine {\tt initgg\_()} creates the storage space for grid point
724! coordinates, area/volume weights, and other coordinate data ({\em e.g.},
725! nearest-neighbor coordinates).  These data are all copied from the
726! already initialized input {\tt GeneralGrid} argument {\tt iGGrid}.  This
727! routine initializes the output {\tt GeneralGrid} argument {\tt oGGrid}
728! with the same {\tt List} data as {\tt iGGrid}, but with storage space
729! for {\tt lsize} gridpoints.
730!
731! {\bf N.B.}:  Though the attribute lists and gridpoint sorting strategy
732! of {\tt iGGrid} is copied to {\tt oGGrid}, the actual values of the
733! attributes are not.
734!
735! {\bf N.B.}:  It is assumed that {\tt iGGrid} has been initialized.
736!
737! {\bf N.B.}:  The output {\tt GeneralGrid} {\tt oGGrid} is dynamically
738! allocated memory.  When one no longer needs {\tt oGGrid}, one should
739! release this space by invoking {\tt GeneralGrid\_clean()}.
740!
741! !INTERFACE:
742
743 subroutine initgg_(oGGrid, iGGrid, lsize)
744!
745! !USES:
746!
747      use m_stdio
748      use m_die
749
750      use m_List, only : List
751      use m_List, only : List_allocated => allocated
752      use m_List, only : List_copy => copy
753      use m_List, only : List_nitems => nitem
754      use m_List, only : List_nullify => nullify
755
756      use m_AttrVect, only:  AttrVect
757      use m_AttrVect, only:  AttrVect_init => init
758
759      implicit none
760
761! !INPUT PARAMETERS:
762!
763      type(GeneralGrid), intent(in)  :: iGGrid
764      integer, optional, intent(in)  :: lsize
765
766! !OUTPUT PARAMETERS:
767!
768      type(GeneralGrid), intent(out) :: oGGrid
769
770! !REVISION HISTORY:
771!  2May01 - Jay Larson <larson@mcs.anl.gov> - Initial version.
772! 13Jun01 - Jay Larson <larson@mcs.anl.gov> - Now, undefined List
773!           components of the GeneralGrid iGGrid are no longer
774!           copied to oGGrid.
775!  8Aug01 - E.T. Ong <eong@mcs.anl.gov> - changed list assignment(=)
776!           to list copy to avoid compiler bugs with pgf90
777! 24Jul02 - E.T. Ong <eong@mcs.anl.gov> - updated this init version
778!           to correspond with initl_
779!  5Aug02 - E. Ong <eong@mcs.anl.gov> - made input argument
780!           CoordSortOrder optional to allow for user-defined
781!           grid numbering schemes
782!EOP ___________________________________________________________________
783!
784  character(len=*),parameter :: myname_=myname//'::initgg_'
785! Number of grid points, number of grid dimensions
786  integer :: n, ncoord, norder
787! Loop index and Error Flag
788  integer :: i, ierr
789
790       ! Start by nullifying everything:
791
792  call List_nullify(oGGrid%coordinate_list)
793  call List_nullify(oGGrid%coordinate_sort_order)
794  call List_nullify(oGGrid%weight_list)
795  call List_nullify(oGGrid%other_list)
796  call List_nullify(oGGrid%index_list)
797  nullify(oGGrid%descend)
798
799        ! Brief argument check:
800       
801  ncoord = dims_(iGGrid)    ! dimensionality of the GeneralGrid
802 
803  if(associated(iGGrid%descend)) then
804
805     if(size(iGGrid%descend) /= ncoord) then ! size mismatch
806        call die(myname_,"size(iGGrid%descend) must equal ncoord, &
807                 & size(iGGrid%descend) = ", size(iGGrid%descend), &
808                 "ncoord = ", ncoord )
809     endif
810
811  endif
812
813        ! If iGGrid%descend has been allocated, copy its contents;
814        ! allocate and fill oGGrid%descend
815
816  if(associated(iGGrid%descend)) then
817
818     allocate(oGGrid%descend(ncoord), stat=ierr)
819     if(ierr /= 0) then
820        call die(myname_,"allocate(oGGrid%descend...", ierr)
821     endif
822
823     do i=1,ncoord
824        oGGrid%descend(i) = iGGrid%descend(i)
825     end do
826
827  endif
828
829       ! Copy list data from iGGrid to oGGrid.
830
831  call List_copy(oGGrid%coordinate_list,iGGrid%coordinate_list)
832  if(List_allocated(iGGrid%coordinate_sort_order)) then
833     call List_copy(oGGrid%coordinate_sort_order,iGGrid%coordinate_sort_order)
834  endif
835  if(List_allocated(iGGrid%weight_list)) then
836     call List_copy(oGGrid%weight_list,iGGrid%weight_list)
837  endif
838  if(List_allocated(iGGrid%other_list)) then
839     call List_copy(oGGrid%other_list,iGGrid%other_list)
840  endif
841  if(List_allocated(iGGrid%index_list)) then
842     call List_copy(oGGrid%index_list,iGGrid%index_list)
843  endif
844
845        ! if lsize is present, use it to set n; if not, set n=0
846
847  n = 0
848  if(present(lsize)) n=lsize
849
850       ! Now, initialize oGGrid%data from iGGrid%data, but
851       ! with length n.
852
853  call AttrVect_init(oGGrid%data, iGGrid%data, n)
854
855 end subroutine initgg_
856
857!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
858!    Math and Computer Science Division, Argonne National Laboratory   !
859!BOP -------------------------------------------------------------------
860!
861! !IROUTINE: initCartesianSP_ - Initialize a Cartesian GeneralGrid
862!
863! !DESCRIPTION:
864! The routine {\tt initCartesian\_()} creates the storage space for grid point
865! coordinates, area and volume weights, and other coordinate data ({\em e.g.},
866! cell area and volume weights).  The names of the Cartesian axes are supplied
867! by the user as a colon-delimitted string in the input {\tt CHARACTER}
868! argument {\tt CoordChars}.  For example, a Cartesian grid for Euclidian
869! 3-space would have ${\tt CoordChars} = {\tt 'x:y:z'}$.  The user can
870! define named real attributes for spatial weighting data in the input
871! {\tt CHARACTER} argument {\tt WeightChars}.  For example, one could
872! define attributes for Euclidean 3-space length elements by setting
873! ${\tt WeightChars} = {\tt 'dx:dy:dz'}$.  The input {\tt CHARCTER}
874! argument {\tt OtherChars} provides space for defining other real
875! attributes (again as a colon-delimited string of attribute names).
876! One can define integer attributes by supplying a colon-delimitted
877! string of names in the input {\tt CHARACTER} argument
878! {\tt IndexChars}.  For example, on could set aside storage space
879! for the {\tt x}-, {\tt y}-, and {\tt z}-indices by setting
880! ${\tt IndexChars} = {\tt 'xIndex:yIndex:zIndex'}$.
881!
882! Once the storage space in {\tt GGrid} is initialized, The gridpoint
883! coordinates are evaluated using the input arguments {\tt Dims} (the
884! number of points on each coordinate axis) and {\tt AxisData} (the
885! coordinate values on all of the points of all of the axes).  The user
886! presents the axes with each axis stored in a column of {\tt AxisData},
887! and the axes are laid out in the same order as the ordering of the
888! axis names in {\tt CoordChars}.  The number of points on each axis
889! is defined by the entries of the input {\tt INTEGER} array
890! {\tt Dims(:)}.  Continuing with the Euclidean 3-space example given
891! above, setting ${\tt Dims(1:3)} = {\tt (256, 256, 128)}$ will result
892! in a Cartesian grid with 256 points in the {\tt x}- and {\tt y}-directions,
893! and 128 points in the {\tt z}-direction.  Thus the appropriate dimensions
894! of {\tt AxisData} are 256 rows (the maximum number of axis points among
895! all the axes) by 3 columns (the number of physical dimensions).  The
896! {\tt x}-axis points are stored in {\tt AxisData(1:256,1)}, the
897! {\tt y}-axis points are stored in {\tt AxisData(1:256,2)}, and the
898! {\tt z}-axis points are stored in {\tt AxisData(1:128,3)}.
899!
900! The sorting order of the gridpoints can be either user-defined, or
901! set automatically by MCT.  If the latter is desired, the user must
902! supply the argument {\tt CoordSortOrder}, which defines the
903! lexicographic ordering (by coordinate).  The entries optional input
904! {\tt LOGICAL} array {\tt descend(:)} stipulates whether the ordering
905! with respect to the corresponding key in {\tt CoordChars} is to be
906! {\em descending}.  If {\tt CoordChars} is supplied, but {\tt descend(:)}
907! is not, the gridpoint information is placed in {\em ascending} order
908! for each key.  Returning to our Euclidian 3-space example, a choice of 
909! ${\tt CoordSortOrder} = {\tt y:x:z}$ and ${\tt descend(1:3)} =
910! ({\tt .TRUE.}, {\tt .FALSE.}, {\tt .FALSE.})$ will result in the entries of
911! {\tt GGrid} being orderd lexicographically by {\tt y} (in descending
912! order), {\tt x} (in ascending order), and {\tt z} (in ascending order).
913! Regardless of the gridpoint sorting strategy, MCT will number each of
914! the gridpoints in {\tt GGrid}, storing this information in the integer
915! attribute named {\tt 'GlobGridNum'}.
916!
917! !INTERFACE:
918
919 subroutine initCartesianSP_(GGrid, CoordChars, CoordSortOrder, descend, &
920                           WeightChars, OtherChars, IndexChars, Dims, &
921                           AxisData)
922!
923! !USES:
924!
925      use m_stdio
926      use m_die
927      use m_realkinds,  only : SP
928
929      use m_String,     only : String
930      use m_String,     only : String_ToChar => ToChar
931      use m_String,     only : String_clean => clean
932
933      use m_List,     only : List
934      use m_List,     only : List_init => init
935      use m_List,     only : List_clean => clean
936      use m_List,     only : List_nullify => nullify
937      use m_List,     only : List_append => append
938      use m_List,     only : List_nitem => nitem
939      use m_List,     only : List_get => get
940      use m_List,     only : List_shared => GetSharedListIndices
941
942      use m_AttrVect, only : AttrVect
943      use m_AttrVect, only : AttrVect_init => init
944      use m_AttrVect, only : AttrVect_zero => zero
945
946      implicit none
947
948! !INPUT PARAMETERS:
949!
950      character(len=*),                  intent(in)  :: CoordChars
951      character(len=*),        optional, intent(in)  :: CoordSortOrder
952      character(len=*),        optional, intent(in)  :: WeightChars
953      logical, dimension(:),   optional, pointer     :: descend
954      character(len=*),        optional, intent(in)  :: OtherChars
955      character(len=*),        optional, intent(in)  :: IndexChars
956      integer, dimension(:),             pointer     :: Dims
957      real(SP), dimension(:,:),          pointer     :: AxisData
958
959! !OUTPUT PARAMETERS:
960!
961      type(GeneralGrid),                 intent(out) :: GGrid
962
963! !REVISION HISTORY:
964!  7Jun01 - Jay Larson <larson@mcs.anl.gov> - API Specification.
965! 12Aug02 - Jay Larson <larson@mcs.anl.gov> - Implementation.
966!EOP ___________________________________________________________________
967!
968  character(len=*),parameter :: myname_=myname//'::initCartesianSP_'
969
970  type(List) :: IAList, RAList
971  type(String) :: AxisName
972  integer, dimension(:), pointer :: &
973       CoordListIndices, CoordSortOrderIndices
974  integer :: DimMax, NumDims, NumGridPoints, NumShared
975  integer :: ierr, iAxis, i, j, k, n, nCycles, nRepeat
976  integer :: index
977
978       ! Nullify GeneralGrid components
979
980  call List_nullify(GGrid%coordinate_list)
981  call List_nullify(GGrid%coordinate_sort_order)
982  call List_nullify(GGrid%weight_list)
983  call List_nullify(GGrid%other_list)
984  call List_nullify(GGrid%index_list)
985  nullify(GGrid%descend)
986
987       ! Sanity check on axis definition arguments:
988
989       ! Ensure each axis has a positive number of points, and
990       ! determine DimMax, the maximum entry in Dims(:).
991
992  DimMax = 1
993  do i=1,size(Dims)
994     if(Dims(i) > DimMax) DimMax = Dims(i)
995     if(Dims(i) <= 0) then
996        write(stderr,'(2a,i8,a,i8)') myname_, &
997             ':: FATAL--illegal number of axis points in Dims(',i,') = ', &
998             Dims(i)
999        call die(myname_)
1000     endif
1001  end do
1002
1003       ! Are the definitions of Dims(:) and AxisData(:,:) compatible?
1004       ! The number of elements in Dims(:) should match the number of
1005       ! columns in AxisData(:,:), and the maximum value stored in Dims(:)
1006       ! (DimMax determined above in this routine) must not exceed the
1007       ! number of rows in AxisData(:,:).
1008
1009  if(size(AxisData,2) /= size(Dims)) then
1010     write(stderr,'(4a,i8,a,i8)') myname_, &
1011          ':: FATAL-- The number of axes (elements) referenced in Dims(:) ', &
1012          'does not equal the number of columns in AxisData(:,:).  ', &
1013          'size(Dims) = ',size(Dims),' size(AxisData,2) = ',size(AxisData,2)
1014     call die(myname_)
1015  endif
1016
1017  if(size(AxisData,1) < DimMax) then
1018     write(stderr,'(4a,i8,a,i8)') myname_, &
1019          ':: FATAL-- Maximum number of axis points max(Dims) is ', &
1020          'greater than the number of rows in AxisData(:,:).  ', &
1021          'max(Dims) = ',DimMax,' size(AxisData,1) = ',size(AxisData,1)
1022     call die(myname_)
1023  endif
1024
1025       ! If the LOGICAL descend(:) flags for sorting are present,
1026       ! make sure that (1) descend is associated, and
1027       ! (2) CoordSortOrder is also present, and
1028       ! (3) The size of descend(:) matches the size of Dims(:),
1029       ! both of which correspond to the number of axes on the
1030       ! Cartesian Grid.
1031
1032  if(present(descend)) then
1033
1034     if(.not.associated(descend)) then
1035        call die(myname_,'descend argument must be associated')
1036     endif
1037
1038     if(.not. present(CoordSortOrder)) then
1039        write(stderr,'(4a)') myname_, &
1040             ':: FATAL -- Invocation with the argument descend(:) present ', &
1041             'requires the presence of the argument CoordSortOrder, ', &
1042             'which was not provided.'
1043        call die(myname_, 'Argument CoordSortOrder was not provided')
1044     endif
1045
1046     if(size(descend) /= size(Dims)) then
1047        write(stderr,'(4a,i8,a,i8)') myname_, &
1048             ':: FATAL-- The sizes of the arrays descend(:) and Dims(:) ', &
1049             'must match (they both must equal the number of dimensions ', &
1050             'of the Cartesian Grid).  size(Dims) = ',size(Dims), &
1051             ' size(descend) = ',size(descend)
1052        call die(myname_,'size of <descend> and <Dims> arguments must match')
1053     endif
1054
1055  endif
1056
1057       ! Initialize GGrid%coordinate_list and use the number of items
1058       ! in it to set the number of dimensions of the Cartesian
1059       ! Grid (NumDims):
1060
1061  call List_init(GGrid%coordinate_list, CoordChars)
1062 
1063  NumDims = List_nitem(GGrid%coordinate_list)
1064
1065       ! Check the number of arguments
1066
1067  if(NumDims <= 0) then
1068     write(stderr,*) myname_, &
1069          ':: ERROR CoordList is empty!'
1070     call die(myname_,'List_nitem(CoordList) <= 0',NumDims)
1071  endif
1072
1073       ! Do the number of coordinate names specified match the number
1074       ! of coordinate axes (i.e., the number of columns in AxisData(:,:))?
1075
1076  if(NumDims /= size(AxisData,2)) then
1077     write(stderr,'(6a,i8,a,i8)') myname_, &
1078          ':: FATAL-- Number of axes specified in argument CoordChars ', &
1079          'does not equal the number of axes stored in AxisData(:,:).  ', &
1080          'CoordChars = ', CoordChars, &
1081          'Number of axes = ',NumDims, &
1082          ' size(AxisData,2) = ',size(AxisData,2)
1083     call die(myname_)
1084  endif
1085
1086       ! End of argument sanity checks.
1087
1088       ! Create other List components of GGrid and build REAL
1089       ! and INTEGER attribute lists for the AttrVect GGrid%data
1090
1091       ! Start off with things *guaranteed* to be in IAList and RAList.
1092       ! The variable GlobGridNum is a CHARACTER parameter inherited
1093       ! from the declaration section of this module.
1094
1095  call List_init(IAList, GlobGridNum)
1096  call List_init(RAList, CoordChars)
1097
1098  if(present(CoordSortOrder)) then
1099
1100     call List_init(GGrid%coordinate_sort_order, CoordSortOrder)
1101
1102        ! Check the items in the coordinate list and the
1103        ! coordinate grid sort keys...they should contain
1104        ! the same items.
1105
1106     call List_shared(GGrid%coordinate_list,GGrid%coordinate_sort_order, &
1107                      NumShared,CoordListIndices,CoordSortOrderIndices)
1108
1109     deallocate(CoordListIndices,CoordSortOrderIndices,stat=ierr)
1110     if(ierr/=0) call die(myname_,'deallocate(CoordListIndices..)',ierr)
1111     
1112     if(NumShared /= NumDims) then
1113        call die(myname_,'CoordSortOrder must have the same items &
1114                 & as CoordList',abs(NumDims-NumShared))
1115     endif
1116
1117  endif
1118
1119  if(present(WeightChars)) then
1120     call List_init(GGrid%weight_list, WeightChars)
1121     call List_append(RAList, GGrid%weight_list)
1122  endif
1123
1124  if(present(OtherChars)) then
1125     call List_init(GGrid%other_list, OtherChars)
1126     call List_append(RAList, GGrid%other_list)
1127  endif
1128
1129  if(present(IndexChars)) then
1130     call List_init(GGrid%index_list, IndexChars)
1131     call List_append(IAList, GGrid%index_list)
1132  endif
1133
1134       ! Finally, Initialize GGrid%descend from descend(:).
1135       ! If descend argument is not present, set it to the default .false.
1136
1137  if(present(CoordSortOrder)) then
1138
1139     allocate(GGrid%descend(NumDims), stat=ierr)
1140     if(ierr /= 0) call die(myname_,"allocate GGrid%descend...",ierr)
1141
1142     if(present(descend)) then
1143        do n=1,NumDims
1144           GGrid%descend(n) = descend(n)
1145        end do
1146     else
1147        do n=1,NumDims
1148           GGrid%descend(n) = .FALSE.
1149        end do
1150     endif
1151       
1152  endif ! if(present(CoordSortOrder))...
1153 
1154       ! Compute the total number of grid points in the GeneralGrid.
1155       ! This is merely the product of the elements of Dims(:)
1156
1157  NumGridPoints = 1
1158  do i=1,NumDims
1159     NumGridPoints = NumGridPoints * Dims(i)
1160  end do
1161
1162       ! Now we are prepared to create GGrid%data:
1163
1164  call AttrVect_init(GGrid%data, IAList, RAList, NumGridPoints)
1165  call AttrVect_zero(GGrid%data)
1166
1167       ! Now, store Cartesian gridpoint data, in the order
1168       ! defined by how the user laid out AxisData(:,:)
1169
1170  do n=1,NumDims
1171
1172       ! Retrieve first coordinate axis name from GGrid%coordinate_list
1173       ! (as a String)
1174     call List_get(AxisName, n, GGrid%coordinate_list)
1175
1176       ! Index this real attribute of GGrid
1177     iAxis = indexRA_(GGrid, String_ToChar(AxisName))
1178
1179     if(iAxis <= 0) then
1180        write(stderr,'(4a)') myname_, &
1181             ':: REAL Attribute "',String_ToChar(AxisName),'" not found.'
1182        call die(myname_)
1183     endif
1184
1185       ! Now, clear the String AxisName for use in the next
1186       ! cycle of this loop:
1187
1188     call String_clean(AxisName)
1189
1190       ! Compute the number of times we cycle through the axis
1191       ! values (nCycles), and the number of times each axis
1192       ! value is repeated in each cycle (nRepeat)
1193
1194     nCycles = 1
1195     if(n > 1) then
1196        do i=1,n-1
1197           nCycles = nCycles * Dims(i)
1198        end do
1199     endif
1200
1201     nRepeat = 1
1202     if(n < NumDims) then
1203        do i=n+1,NumDims
1204           nRepeat = nRepeat * Dims(i)
1205        end do
1206     endif
1207
1208       ! Loop over the number of cycles for which we run through
1209       ! all the axis points.  Within each cycle, loop over all
1210       ! of the axis points, repeating each value nRepeat times.
1211       ! This produces a set of grid entries that are in
1212       ! lexicographic order with respect to how the axes are
1213       ! presented to this routine.
1214
1215     index = 1
1216     do i=1,nCycles
1217        do j=1,Dims(n)
1218           do k=1,nRepeat
1219              GGrid%data%rAttr(iAxis,index) = AxisData(j,n)
1220              index = index+1
1221           end do ! do k=1,nRepeat
1222        end do ! do j=1,Dims(n)
1223     end do ! do i=1,nCycles
1224
1225  end do ! do n=1,NumDims...
1226
1227       ! If the argument CoordSortOrder was supplied, the entries
1228       ! of GGrid will be sorted/permuted with this lexicographic
1229       ! ordering, and the values of the GGrid INTEGER attribute
1230       ! GlobGridNum will be numbered to reflect this new ordering
1231       ! scheme.
1232
1233  index = indexIA_(GGrid, GlobGridNum)
1234
1235  if(present(CoordSortOrder)) then ! Sort permute entries before
1236                                   ! numbering them
1237
1238     call SortPermute_(GGrid) ! Sort / permute
1239
1240  endif ! if(present(CoordSortOrder))...
1241
1242       ! Number the gridpoints based on the AttrVect point index
1243       ! (i.e., the second index in GGrid%data%iAttr)
1244
1245  do i=1, lsize_(GGrid)
1246     GGrid%data%iAttr(index,i) = i
1247  end do
1248
1249       ! Finally, clean up intermediate Lists
1250
1251  call List_clean(IAList)
1252  call List_clean(RAList)
1253
1254 end subroutine initCartesianSP_
1255
1256!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1257!    Math and Computer Science Division, Argonne National Laboratory   !
1258! ----------------------------------------------------------------------
1259!
1260! !IROUTINE: initCartesianDP_ - Initialize a Cartesian GeneralGrid
1261!
1262! !DESCRIPTION:
1263! Double Precision version of initCartesianSP_
1264!
1265! !INTERFACE:
1266
1267 subroutine initCartesianDP_(GGrid, CoordChars, CoordSortOrder, descend, &
1268                           WeightChars, OtherChars, IndexChars, Dims, &
1269                           AxisData)
1270!
1271! !USES:
1272!
1273      use m_stdio
1274      use m_die
1275      use m_realkinds,  only : DP
1276
1277      use m_String,     only : String
1278      use m_String,     only : String_ToChar => ToChar
1279      use m_String,     only : String_clean => clean
1280
1281      use m_List,     only : List
1282      use m_List,     only : List_init => init
1283      use m_List,     only : List_clean => clean
1284      use m_List,     only : List_nullify => nullify
1285      use m_List,     only : List_append => append
1286      use m_List,     only : List_nitem => nitem
1287      use m_List,     only : List_get => get
1288      use m_List,     only : List_shared => GetSharedListIndices
1289
1290      use m_AttrVect, only : AttrVect
1291      use m_AttrVect, only : AttrVect_init => init
1292      use m_AttrVect, only : AttrVect_zero => zero
1293
1294      implicit none
1295
1296! !INPUT PARAMETERS:
1297!
1298      character(len=*),                  intent(in)  :: CoordChars
1299      character(len=*),        optional, intent(in)  :: CoordSortOrder
1300      character(len=*),        optional, intent(in)  :: WeightChars
1301      logical, dimension(:),   optional, pointer     :: descend
1302      character(len=*),        optional, intent(in)  :: OtherChars
1303      character(len=*),        optional, intent(in)  :: IndexChars
1304      integer, dimension(:),             pointer     :: Dims
1305      real(DP), dimension(:,:),          pointer     :: AxisData
1306
1307! !OUTPUT PARAMETERS:
1308!
1309      type(GeneralGrid),                 intent(out) :: GGrid
1310
1311! !REVISION HISTORY:
1312!  7Jun01 - Jay Larson <larson@mcs.anl.gov> - API Specification.
1313! 12Aug02 - Jay Larson <larson@mcs.anl.gov> - Implementation.
1314! ______________________________________________________________________
1315!
1316  character(len=*),parameter :: myname_=myname//'::initCartesianDP_'
1317
1318  type(List) :: IAList, RAList
1319  type(String) :: AxisName
1320  integer, dimension(:), pointer :: &
1321       CoordListIndices, CoordSortOrderIndices
1322  integer :: DimMax, NumDims, NumGridPoints, NumShared
1323  integer :: ierr, iAxis, i, j, k, n, nCycles, nRepeat
1324  integer :: index
1325
1326       ! Nullify GeneralGrid components
1327
1328  call List_nullify(GGrid%coordinate_list)
1329  call List_nullify(GGrid%coordinate_sort_order)
1330  call List_nullify(GGrid%weight_list)
1331  call List_nullify(GGrid%other_list)
1332  call List_nullify(GGrid%index_list)
1333  nullify(GGrid%descend)
1334
1335       ! Sanity check on axis definition arguments:
1336
1337       ! Ensure each axis has a positive number of points, and
1338       ! determine DimMax, the maximum entry in Dims(:).
1339
1340  DimMax = 1
1341  do i=1,size(Dims)
1342     if(Dims(i) > DimMax) DimMax = Dims(i)
1343     if(Dims(i) <= 0) then
1344        write(stderr,'(2a,i8,a,i8)') myname_, &
1345             ':: FATAL--illegal number of axis points in Dims(',i,') = ', &
1346             Dims(i)
1347        call die(myname_)
1348     endif
1349  end do
1350
1351       ! Are the definitions of Dims(:) and AxisData(:,:) compatible?
1352       ! The number of elements in Dims(:) should match the number of
1353       ! columns in AxisData(:,:), and the maximum value stored in Dims(:)
1354       ! (DimMax determined above in this routine) must not exceed the
1355       ! number of rows in AxisData(:,:).
1356
1357  if(size(AxisData,2) /= size(Dims)) then
1358     write(stderr,'(4a,i8,a,i8)') myname_, &
1359          ':: FATAL-- The number of axes (elements) referenced in Dims(:) ', &
1360          'does not equal the number of columns in AxisData(:,:).  ', &
1361          'size(Dims) = ',size(Dims),' size(AxisData,2) = ',size(AxisData,2)
1362     call die(myname_)
1363  endif
1364
1365  if(size(AxisData,1) < DimMax) then
1366     write(stderr,'(4a,i8,a,i8)') myname_, &
1367          ':: FATAL-- Maximum number of axis points max(Dims) is ', &
1368          'greater than the number of rows in AxisData(:,:).  ', &
1369          'max(Dims) = ',DimMax,' size(AxisData,1) = ',size(AxisData,1)
1370     call die(myname_)
1371  endif
1372
1373       ! If the LOGICAL descend(:) flags for sorting are present,
1374       ! make sure that (1) descend is associated, and
1375       ! (2) CoordSortOrder is also present, and
1376       ! (3) The size of descend(:) matches the size of Dims(:),
1377       ! both of which correspond to the number of axes on the
1378       ! Cartesian Grid.
1379
1380  if(present(descend)) then
1381
1382     if(.not.associated(descend)) then
1383        call die(myname_,'descend argument must be associated')
1384     endif
1385
1386     if(.not. present(CoordSortOrder)) then
1387        write(stderr,'(4a)') myname_, &
1388             ':: FATAL -- Invocation with the argument descend(:) present ', &
1389             'requires the presence of the argument CoordSortOrder, ', &
1390             'which was not provided.'
1391        call die(myname_, 'Argument CoordSortOrder was not provided')
1392     endif
1393
1394     if(size(descend) /= size(Dims)) then
1395        write(stderr,'(4a,i8,a,i8)') myname_, &
1396             ':: FATAL-- The sizes of the arrays descend(:) and Dims(:) ', &
1397             'must match (they both must equal the number of dimensions ', &
1398             'of the Cartesian Grid).  size(Dims) = ',size(Dims), &
1399             ' size(descend) = ',size(descend)
1400        call die(myname_,'size of <descend> and <Dims> arguments must match')
1401     endif
1402
1403  endif
1404
1405       ! Initialize GGrid%coordinate_list and use the number of items
1406       ! in it to set the number of dimensions of the Cartesian
1407       ! Grid (NumDims):
1408
1409  call List_init(GGrid%coordinate_list, CoordChars)
1410 
1411  NumDims = List_nitem(GGrid%coordinate_list)
1412
1413       ! Check the number of arguments
1414
1415  if(NumDims <= 0) then
1416     write(stderr,*) myname_, &
1417          ':: ERROR CoordList is empty!'
1418     call die(myname_,'List_nitem(CoordList) <= 0',NumDims)
1419  endif
1420
1421       ! Do the number of coordinate names specified match the number
1422       ! of coordinate axes (i.e., the number of columns in AxisData(:,:))?
1423
1424  if(NumDims /= size(AxisData,2)) then
1425     write(stderr,'(6a,i8,a,i8)') myname_, &
1426          ':: FATAL-- Number of axes specified in argument CoordChars ', &
1427          'does not equal the number of axes stored in AxisData(:,:).  ', &
1428          'CoordChars = ', CoordChars, &
1429          'Number of axes = ',NumDims, &
1430          ' size(AxisData,2) = ',size(AxisData,2)
1431     call die(myname_)
1432  endif
1433
1434       ! End of argument sanity checks.
1435
1436       ! Create other List components of GGrid and build REAL
1437       ! and INTEGER attribute lists for the AttrVect GGrid%data
1438
1439       ! Start off with things *guaranteed* to be in IAList and RAList.
1440       ! The variable GlobGridNum is a CHARACTER parameter inherited
1441       ! from the declaration section of this module.
1442
1443  call List_init(IAList, GlobGridNum)
1444  call List_init(RAList, CoordChars)
1445
1446  if(present(CoordSortOrder)) then
1447
1448     call List_init(GGrid%coordinate_sort_order, CoordSortOrder)
1449
1450        ! Check the items in the coordinate list and the
1451        ! coordinate grid sort keys...they should contain
1452        ! the same items.
1453
1454     call List_shared(GGrid%coordinate_list,GGrid%coordinate_sort_order, &
1455                      NumShared,CoordListIndices,CoordSortOrderIndices)
1456
1457     deallocate(CoordListIndices,CoordSortOrderIndices,stat=ierr)
1458     if(ierr/=0) call die(myname_,'deallocate(CoordListIndices..)',ierr)
1459     
1460     if(NumShared /= NumDims) then
1461        call die(myname_,'CoordSortOrder must have the same items &
1462                 & as CoordList',abs(NumDims-NumShared))
1463     endif
1464
1465  endif
1466
1467  if(present(WeightChars)) then
1468     call List_init(GGrid%weight_list, WeightChars)
1469     call List_append(RAList, GGrid%weight_list)
1470  endif
1471
1472  if(present(OtherChars)) then
1473     call List_init(GGrid%other_list, OtherChars)
1474     call List_append(RAList, GGrid%other_list)
1475  endif
1476
1477  if(present(IndexChars)) then
1478     call List_init(GGrid%index_list, IndexChars)
1479     call List_append(IAList, GGrid%index_list)
1480  endif
1481
1482       ! Finally, Initialize GGrid%descend from descend(:).
1483       ! If descend argument is not present, set it to the default .false.
1484
1485  if(present(CoordSortOrder)) then
1486
1487     allocate(GGrid%descend(NumDims), stat=ierr)
1488     if(ierr /= 0) call die(myname_,"allocate GGrid%descend...",ierr)
1489
1490     if(present(descend)) then
1491        do n=1,NumDims
1492           GGrid%descend(n) = descend(n)
1493        end do
1494     else
1495        do n=1,NumDims
1496           GGrid%descend(n) = .FALSE.
1497        end do
1498     endif
1499       
1500  endif ! if(present(CoordSortOrder))...
1501 
1502       ! Compute the total number of grid points in the GeneralGrid.
1503       ! This is merely the product of the elements of Dims(:)
1504
1505  NumGridPoints = 1
1506  do i=1,NumDims
1507     NumGridPoints = NumGridPoints * Dims(i)
1508  end do
1509
1510       ! Now we are prepared to create GGrid%data:
1511
1512  call AttrVect_init(GGrid%data, IAList, RAList, NumGridPoints)
1513  call AttrVect_zero(GGrid%data)
1514
1515       ! Now, store Cartesian gridpoint data, in the order
1516       ! defined by how the user laid out AxisData(:,:)
1517
1518  do n=1,NumDims
1519
1520       ! Retrieve first coordinate axis name from GGrid%coordinate_list
1521       ! (as a String)
1522     call List_get(AxisName, n, GGrid%coordinate_list)
1523
1524       ! Index this real attribute of GGrid
1525     iAxis = indexRA_(GGrid, String_ToChar(AxisName))
1526
1527     if(iAxis <= 0) then
1528        write(stderr,'(4a)') myname_, &
1529             ':: REAL Attribute "',String_ToChar(AxisName),'" not found.'
1530        call die(myname_)
1531     endif
1532
1533       ! Now, clear the String AxisName for use in the next
1534       ! cycle of this loop:
1535
1536     call String_clean(AxisName)
1537
1538       ! Compute the number of times we cycle through the axis
1539       ! values (nCycles), and the number of times each axis
1540       ! value is repeated in each cycle (nRepeat)
1541
1542     nCycles = 1
1543     if(n > 1) then
1544        do i=1,n-1
1545           nCycles = nCycles * Dims(i)
1546        end do
1547     endif
1548
1549     nRepeat = 1
1550     if(n < NumDims) then
1551        do i=n+1,NumDims
1552           nRepeat = nRepeat * Dims(i)
1553        end do
1554     endif
1555
1556       ! Loop over the number of cycles for which we run through
1557       ! all the axis points.  Within each cycle, loop over all
1558       ! of the axis points, repeating each value nRepeat times.
1559       ! This produces a set of grid entries that are in
1560       ! lexicographic order with respect to how the axes are
1561       ! presented to this routine.
1562
1563     index = 1
1564     do i=1,nCycles
1565        do j=1,Dims(n)
1566           do k=1,nRepeat
1567              GGrid%data%rAttr(iAxis,index) = AxisData(j,n)
1568              index = index+1
1569           end do ! do k=1,nRepeat
1570        end do ! do j=1,Dims(n)
1571     end do ! do i=1,nCycles
1572
1573  end do ! do n=1,NumDims...
1574
1575       ! If the argument CoordSortOrder was supplied, the entries
1576       ! of GGrid will be sorted/permuted with this lexicographic
1577       ! ordering, and the values of the GGrid INTEGER attribute
1578       ! GlobGridNum will be numbered to reflect this new ordering
1579       ! scheme.
1580
1581  index = indexIA_(GGrid, GlobGridNum)
1582
1583  if(present(CoordSortOrder)) then ! Sort permute entries before
1584                                   ! numbering them
1585
1586     call SortPermute_(GGrid) ! Sort / permute
1587
1588  endif ! if(present(CoordSortOrder))...
1589
1590       ! Number the gridpoints based on the AttrVect point index
1591       ! (i.e., the second index in GGrid%data%iAttr)
1592
1593  do i=1, lsize_(GGrid)
1594     GGrid%data%iAttr(index,i) = i
1595  end do
1596
1597       ! Finally, clean up intermediate Lists
1598
1599  call List_clean(IAList)
1600  call List_clean(RAList)
1601
1602 end subroutine initCartesianDP_
1603
1604!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1605!    Math and Computer Science Division, Argonne National Laboratory   !
1606!BOP -------------------------------------------------------------------
1607!
1608! !IROUTINE: initUnstructuredSP_ - Initialize an Unstructured GeneralGrid
1609!
1610! !DESCRIPTION:
1611! This routine creates the storage space for grid point
1612! coordinates, area/volume weights, and other coordinate data ({\em e.g.},
1613! local cell dimensions), and fills in user-supplied values for the grid
1614! point coordinates.  These data are referenced by {\tt List}
1615! components that are also created by this routine (see the documentation
1616! of the declaration section of this module for more details about setting
1617! list information).  Each of the input {\tt CHARACTER} arguments is a
1618! colon-delimited string of attribute names, each corrsponding to a
1619! {\tt List} element of the output {\tt GeneralGrid} argument {\tt GGrid},
1620! and are summarized in the table below:
1621!
1622!\begin{table}[htbp]
1623!\begin{center}
1624!\begin{tabular}{|l|l|l|l|}
1625!\hline
1626!{\bf Argument} & {\bf Component of {\tt GGrid}} & {\bf Significance} & {\bf Required?} \\
1627!\hline
1628!{\tt CoordChars} & {\tt GGrid\%coordinate\_list} & Dimension Names & Yes \\
1629!\hline
1630!{\tt CoordSortOrder} & {\tt GGrid\%coordinate\_sort\_order} & Grid Point & No \\
1631! & & Sorting Keys & \\
1632!\hline
1633!{\tt WeightChars} & {\tt GGrid\%weight\_list} & Grid Cell & No \\
1634! & & Length, Area, and & \\
1635! & & Volume Weights & \\
1636!\hline
1637!{\tt OtherChars} & {\tt GGrid\%other\_list} & All Other & No \\
1638! & & Real Attributes & \\
1639!\hline
1640!{\tt IndexChars} & {\tt GGrid\%index\_list} & All Other & No \\
1641! & & Integer Attributes & \\
1642!\hline
1643!\end{tabular}
1644!\end{center}
1645!\end{table}
1646!
1647! The number of physical dimensions of the grid is set by the user in
1648! the input {\tt INTEGER} argument {\tt nDims}, and the number of grid
1649! points stored in {\tt GGrid} is set using the input {\tt INTEGER}
1650! argument {\tt nPoints}.  The grid point coordinates are input via the
1651! {\tt REAL} array {\tt PointData(:)}.  The number of entries in
1652! {\tt PointData} must equal the product of {\tt nDims} and {\tt nPoints}.
1653! The grid points are grouped in {\tt nPoints} consecutive groups of
1654! {\tt nDims} entries, with the coordinate values for each point set in
1655! the same order as the dimensions are named in the list {\tt CoordChars}.
1656!
1657! If a set of sorting keys is supplied in the argument {\tt CoordSortOrder},
1658! the user can control whether the sorting by each key is in descending or
1659! ascending order by supplying the input {\tt LOGICAL} array {\tt descend(:)}. 
1660! By default, all sorting is in {\em ascending} order for each key if the
1661! argument {\tt descend} is not provided.
1662!
1663! {\bf N.B.}:  The output {\tt GeneralGrid} {\tt GGrid} is dynamically
1664! allocated memory.  When one no longer needs {\tt GGrid}, one should
1665! release this space by invoking {\tt clean()} for the {\tt GeneralGrid}.
1666!
1667! !INTERFACE:
1668
1669 subroutine initUnstructuredSP_(GGrid, CoordChars, CoordSortOrder, descend, &
1670                              WeightChars, OtherChars, IndexChars, nDims, &
1671                              nPoints, PointData)
1672!
1673! !USES:
1674!
1675      use m_stdio
1676      use m_die
1677      use m_realkinds,only : SP
1678
1679      use m_String,   only : String, char
1680      use m_List,     only : List
1681      use m_List,     only : List_init => init
1682      use m_List,     only : List_clean => clean
1683      use m_List,     only : List_nitem => nitem
1684      use m_List,     only : List_nullify => nullify
1685      use m_List,     only : List_copy => copy
1686      use m_List,     only : List_append => append
1687      use m_List,     only : List_shared => GetSharedListIndices
1688      use m_AttrVect, only : AttrVect
1689      use m_AttrVect, only : AttrVect_init => init
1690      use m_AttrVect, only : AttrVect_zero => zero
1691
1692      implicit none
1693
1694! !INPUT PARAMETERS:
1695!
1696      character(len=*),             intent(in) :: CoordChars
1697      character(len=*), optional,   intent(in) :: CoordSortOrder
1698      character(len=*), optional,   intent(in) :: WeightChars
1699      logical, dimension(:), optional, pointer :: descend
1700      character(len=*), optional,   intent(in) :: OtherChars
1701      character(len=*), optional,   intent(in) :: IndexChars
1702      integer,                      intent(in) :: nDims
1703      integer,                      intent(in) :: nPoints
1704      real(SP), dimension(:),       pointer    :: PointData
1705
1706! !OUTPUT PARAMETERS:
1707!
1708      type(GeneralGrid), intent(out)   :: GGrid
1709
1710! !REVISION HISTORY:
1711!  7Jun01 - Jay Larson <larson@mcs.anl.gov> - API specification.
1712! 22Aug02 - J. Larson <larson@mcs.anl.gov> - Implementation.
1713!EOP ___________________________________________________________________
1714!
1715  character(len=*),parameter :: myname_=myname//'::initUnstructuredSP_'
1716
1717  integer :: i, ierr, index, n, nOffSet, NumShared
1718  integer, dimension(:), pointer :: &
1719       CoordListIndices, CoordSortOrderIndices
1720  type(List) :: IAList, RAList
1721
1722       ! Nullify all GeneralGrid components
1723
1724  call List_nullify(GGrid%coordinate_list)
1725  call List_nullify(GGrid%coordinate_sort_order)
1726  call List_nullify(GGrid%weight_list)
1727  call List_nullify(GGrid%other_list)
1728  call List_nullify(GGrid%index_list)
1729  nullify(GGrid%descend)
1730
1731       ! Sanity checks on input arguments:
1732
1733       ! If the LOGICAL descend(:) flags for sorting are present,
1734       ! make sure that (1) it is associated,
1735       ! (2) CoordSortOrder is also present, and
1736       ! (3) The size of descend(:) matches the size of Dims(:),
1737       ! both of which correspond to the number of axes on the
1738       ! Cartesian Grid.
1739
1740  if(present(descend)) then
1741
1742     if(.not.associated(descend)) then
1743        call die(myname_,'descend argument must be associated')
1744     endif
1745
1746     if(.not. present(CoordSortOrder)) then
1747        write(stderr,'(4a)') myname_, &
1748             ':: FATAL -- Invocation with the argument descend(:) present ', &
1749             'requires the presence of the argument CoordSortOrder, ', &
1750             'which was not provided.'
1751        call die(myname_,'Argument CoordSortOrder was not provided')
1752     endif
1753
1754     if(present(descend)) then
1755        if(size(descend) /= nDims) then
1756           write(stderr,'(4a,i8,a,i8)') myname_, &
1757                ':: FATAL-- The size of the array descend(:) and nDims ', &
1758                'must be equal (they both must equal the number of dimensions ', &
1759                'of the unstructured Grid).  nDims = ',nDims, &
1760             ' size(descend) = ',size(descend)
1761           call die(myname_,'size(descend)/=nDims')
1762        endif
1763     endif
1764
1765  endif
1766
1767       ! Initialize GGrid%coordinate_list and comparethe number of items
1768       ! to the number of dimensions of the unstructured nDims:
1769
1770  call List_init(GGrid%coordinate_list, CoordChars)
1771
1772       ! Check the coordinate_list
1773
1774  if(nDims /= List_nitem(GGrid%coordinate_list)) then
1775     write(stderr,'(4a,i8,3a,i8)') myname_, &
1776          ':: FATAL-- The number of coordinate names supplied in the ', &
1777          'argument CoordChars must equal the number of dimensions ', &
1778          'specified by the argument nDims.  nDims = ',nDims, &
1779          ' CoordChars = ',CoordChars, ' number of dimensions in CoordChars = ', &
1780          List_nitem(GGrid%coordinate_list) 
1781     call die(myname_)
1782  endif
1783
1784  if(nDims <= 0) then
1785     write(stderr,*) myname_, ':: ERROR nDims=0!'
1786     call die(myname_,'nDims <= 0',nDims)
1787  endif
1788
1789       ! PointData is a one-dimensional array containing all the gridpoint
1790       ! coordinates.  As such, its size must equal nDims * nPoints.  True?
1791
1792  if(size(PointData) /= nDims * nPoints) then
1793     write(stderr,'(3a,3(a,i8))') myname_, &
1794          ':: FATAL-- The length of the array PointData(:) must match ', &
1795          'the product of the input arguments nDims and nPoints.  ', &
1796          'nDims = ',nDims, ' nPoints = ',nPoints,&
1797          ' size(PointData) = ',size(PointData)
1798     call die(myname_)
1799  endif
1800     
1801       ! End of input argument sanity checks.
1802
1803       ! Create other List components of GGrid and build REAL
1804       ! and INTEGER attribute lists for the AttrVect GGrid%data
1805
1806       ! Start off with things *guaranteed* to be in IAList and RAList.
1807       ! The variable GlobGridNum is a CHARACTER parameter inherited
1808       ! from the declaration section of this module.
1809
1810  call List_init(IAList, GlobGridNum)
1811  call List_init(RAList, CoordChars)
1812
1813  if(present(CoordSortOrder)) then
1814
1815     call List_init(GGrid%coordinate_sort_order, CoordSortOrder)
1816
1817     call List_shared(GGrid%coordinate_list,GGrid%coordinate_sort_order, &
1818                      NumShared,CoordListIndices,CoordSortOrderIndices)
1819
1820     deallocate(CoordListIndices,CoordSortOrderIndices,stat=ierr)
1821     if(ierr/=0) call die(myname_,'deallocate(CoordListIndices..)',ierr)
1822     
1823     if(NumShared /= nDims) then
1824        call die(myname_,'CoordSortOrder must have the same items &
1825                 & as CoordList',abs(nDims-NumShared))
1826     endif
1827
1828  endif
1829
1830  if(present(WeightChars)) then
1831     call List_init(GGrid%weight_list, WeightChars)
1832     call List_append(RAList, GGrid%weight_list)
1833  endif
1834
1835  if(present(OtherChars)) then
1836     call List_init(GGrid%other_list, OtherChars)
1837     call List_append(RAList, GGrid%other_list)
1838  endif
1839
1840  if(present(IndexChars)) then
1841     call List_init(GGrid%index_list, IndexChars)
1842     call List_append(IAList, GGrid%index_list)
1843  endif
1844
1845       ! Initialize GGrid%descend from descend(:).
1846       ! If descend argument is not present, set it to the default .false.
1847
1848  if(present(CoordSortOrder)) then
1849
1850     allocate(GGrid%descend(nDims), stat=ierr)
1851     if(ierr /= 0) call die(myname_,"allocate GGrid%descend...",ierr)
1852
1853     if(present(descend)) then
1854        do n=1,nDims
1855           GGrid%descend(n) = descend(n)
1856        end do
1857     else
1858        do n=1,nDims
1859           GGrid%descend(n) = .FALSE.
1860        end do
1861     endif
1862       
1863  endif ! if(present(CoordSortOrder))...
1864 
1865       ! Create Grid attribute data storage AttrVect GGrid%data:
1866
1867  call AttrVect_init(GGrid%data, IAList, RAList, nPoints)
1868  call AttrVect_zero(GGrid%data)
1869
1870       ! Load up gridpoint coordinate data into GGrid%data.
1871       ! Given how we've set up the real attributes of GGrid%data,
1872       ! we have guaranteed the first nDims real attributes are
1873       ! the gridpoint coordinates.
1874
1875  do n=1,nPoints
1876     nOffSet = (n-1) * nDims
1877     do i=1,nDims
1878        GGrid%data%rAttr(i,n) = PointData(nOffset + i)
1879     end do
1880  end do
1881
1882       ! If the argument CoordSortOrder was supplied, the entries
1883       ! of GGrid will be sorted/permuted with this lexicographic
1884       ! ordering, and the values of the GGrid INTEGER attribute
1885       ! GlobGridNum will be numbered to reflect this new ordering
1886       ! scheme.
1887
1888  index = indexIA_(GGrid, GlobGridNum)
1889
1890  if(present(CoordSortOrder)) then ! Sort permute entries before
1891                                   ! numbering them
1892
1893     call SortPermute_(GGrid) ! Sort / permute
1894
1895  endif ! if(present(CoordSortOrder))...
1896
1897       ! Number the gridpoints based on the AttrVect point index
1898       ! (i.e., the second index in GGrid%data%iAttr)
1899
1900  do i=1, lsize_(GGrid)
1901     GGrid%data%iAttr(index,i) = i
1902  end do
1903
1904       ! Clean up temporary allocated structures:
1905
1906  call List_clean(IAList)
1907  call List_clean(RAList)
1908
1909 end subroutine initUnstructuredSP_
1910
1911!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1912!    Math and Computer Science Division, Argonne National Laboratory   !
1913! ----------------------------------------------------------------------
1914!
1915! !IROUTINE: initUnstructuredDP_ - Initialize an Unstructured GeneralGrid
1916!
1917! !DESCRIPTION:
1918! Double precision version of initUnstructuredSP_
1919!
1920! !INTERFACE:
1921
1922 subroutine initUnstructuredDP_(GGrid, CoordChars, CoordSortOrder, descend, &
1923                              WeightChars, OtherChars, IndexChars, nDims, &
1924                              nPoints, PointData)
1925!
1926! !USES:
1927!
1928      use m_stdio
1929      use m_die
1930      use m_realkinds,only : DP
1931
1932      use m_String,   only : String, char
1933      use m_List,     only : List
1934      use m_List,     only : List_init => init
1935      use m_List,     only : List_clean => clean
1936      use m_List,     only : List_nitem => nitem
1937      use m_List,     only : List_nullify => nullify
1938      use m_List,     only : List_copy => copy
1939      use m_List,     only : List_append => append
1940      use m_List,     only : List_shared => GetSharedListIndices
1941      use m_AttrVect, only : AttrVect
1942      use m_AttrVect, only : AttrVect_init => init
1943      use m_AttrVect, only : AttrVect_zero => zero
1944
1945      implicit none
1946
1947! !INPUT PARAMETERS:
1948!
1949      character(len=*),             intent(in) :: CoordChars
1950      character(len=*), optional,   intent(in) :: CoordSortOrder
1951      character(len=*), optional,   intent(in) :: WeightChars
1952      logical, dimension(:), optional, pointer :: descend
1953      character(len=*), optional,   intent(in) :: OtherChars
1954      character(len=*), optional,   intent(in) :: IndexChars
1955      integer,                      intent(in) :: nDims
1956      integer,                      intent(in) :: nPoints
1957      real(DP), dimension(:),       pointer    :: PointData
1958
1959! !OUTPUT PARAMETERS:
1960!
1961      type(GeneralGrid), intent(out)   :: GGrid
1962
1963! !REVISION HISTORY:
1964!  7Jun01 - Jay Larson <larson@mcs.anl.gov> - API specification.
1965! 22Aug02 - J. Larson <larson@mcs.anl.gov> - Implementation.
1966! ______________________________________________________________________
1967!
1968  character(len=*),parameter :: myname_=myname//'::initUnstructuredDP_'
1969
1970  integer :: i, ierr, index, n, nOffSet, NumShared
1971  integer, dimension(:), pointer :: &
1972       CoordListIndices, CoordSortOrderIndices
1973  type(List) :: IAList, RAList
1974
1975       ! Nullify all GeneralGrid components
1976
1977  call List_nullify(GGrid%coordinate_list)
1978  call List_nullify(GGrid%coordinate_sort_order)
1979  call List_nullify(GGrid%weight_list)
1980  call List_nullify(GGrid%other_list)
1981  call List_nullify(GGrid%index_list)
1982  nullify(GGrid%descend)
1983
1984       ! Sanity checks on input arguments:
1985
1986       ! If the LOGICAL descend(:) flags for sorting are present,
1987       ! make sure that (1) it is associated,
1988       ! (2) CoordSortOrder is also present, and
1989       ! (3) The size of descend(:) matches the size of Dims(:),
1990       ! both of which correspond to the number of axes on the
1991       ! Cartesian Grid.
1992
1993  if(present(descend)) then
1994
1995     if(.not.associated(descend)) then
1996        call die(myname_,'descend argument must be associated')
1997     endif
1998
1999     if(.not. present(CoordSortOrder)) then
2000        write(stderr,'(4a)') myname_, &
2001             ':: FATAL -- Invocation with the argument descend(:) present ', &
2002             'requires the presence of the argument CoordSortOrder, ', &
2003             'which was not provided.'
2004        call die(myname_,'Argument CoordSortOrder was not provided')
2005     endif
2006
2007     if(present(descend)) then
2008        if(size(descend) /= nDims) then
2009           write(stderr,'(4a,i8,a,i8)') myname_, &
2010                ':: FATAL-- The size of the array descend(:) and nDims ', &
2011                'must be equal (they both must equal the number of dimensions ', &
2012                'of the unstructured Grid).  nDims = ',nDims, &
2013             ' size(descend) = ',size(descend)
2014           call die(myname_,'size(descend)/=nDims')
2015        endif
2016     endif
2017
2018  endif
2019
2020       ! Initialize GGrid%coordinate_list and comparethe number of items
2021       ! to the number of dimensions of the unstructured nDims:
2022
2023  call List_init(GGrid%coordinate_list, CoordChars)
2024
2025       ! Check the coordinate_list
2026
2027  if(nDims /= List_nitem(GGrid%coordinate_list)) then
2028     write(stderr,'(4a,i8,3a,i8)') myname_, &
2029          ':: FATAL-- The number of coordinate names supplied in the ', &
2030          'argument CoordChars must equal the number of dimensions ', &
2031          'specified by the argument nDims.  nDims = ',nDims, &
2032          ' CoordChars = ',CoordChars, ' number of dimensions in CoordChars = ', &
2033          List_nitem(GGrid%coordinate_list) 
2034     call die(myname_)
2035  endif
2036
2037  if(nDims <= 0) then
2038     write(stderr,*) myname_, ':: ERROR nDims=0!'
2039     call die(myname_,'nDims <= 0',nDims)
2040  endif
2041
2042       ! PointData is a one-dimensional array containing all the gridpoint
2043       ! coordinates.  As such, its size must equal nDims * nPoints.  True?
2044
2045  if(size(PointData) /= nDims * nPoints) then
2046     write(stderr,'(3a,3(a,i8))') myname_, &
2047          ':: FATAL-- The length of the array PointData(:) must match ', &
2048          'the product of the input arguments nDims and nPoints.  ', &
2049          'nDims = ',nDims, ' nPoints = ',nPoints,&
2050          ' size(PointData) = ',size(PointData)
2051     call die(myname_)
2052  endif
2053     
2054       ! End of input argument sanity checks.
2055
2056       ! Create other List components of GGrid and build REAL
2057       ! and INTEGER attribute lists for the AttrVect GGrid%data
2058
2059       ! Start off with things *guaranteed* to be in IAList and RAList.
2060       ! The variable GlobGridNum is a CHARACTER parameter inherited
2061       ! from the declaration section of this module.
2062
2063  call List_init(IAList, GlobGridNum)
2064  call List_init(RAList, CoordChars)
2065
2066  if(present(CoordSortOrder)) then
2067
2068     call List_init(GGrid%coordinate_sort_order, CoordSortOrder)
2069
2070     call List_shared(GGrid%coordinate_list,GGrid%coordinate_sort_order, &
2071                      NumShared,CoordListIndices,CoordSortOrderIndices)
2072
2073     deallocate(CoordListIndices,CoordSortOrderIndices,stat=ierr)
2074     if(ierr/=0) call die(myname_,'deallocate(CoordListIndices..)',ierr)
2075     
2076     if(NumShared /= nDims) then
2077        call die(myname_,'CoordSortOrder must have the same items &
2078                 & as CoordList',abs(nDims-NumShared))
2079     endif
2080
2081  endif
2082
2083  if(present(WeightChars)) then
2084     call List_init(GGrid%weight_list, WeightChars)
2085     call List_append(RAList, GGrid%weight_list)
2086  endif
2087
2088  if(present(OtherChars)) then
2089     call List_init(GGrid%other_list, OtherChars)
2090     call List_append(RAList, GGrid%other_list)
2091  endif
2092
2093  if(present(IndexChars)) then
2094     call List_init(GGrid%index_list, IndexChars)
2095     call List_append(IAList, GGrid%index_list)
2096  endif
2097
2098       ! Initialize GGrid%descend from descend(:).
2099       ! If descend argument is not present, set it to the default .false.
2100
2101  if(present(CoordSortOrder)) then
2102
2103     allocate(GGrid%descend(nDims), stat=ierr)
2104     if(ierr /= 0) call die(myname_,"allocate GGrid%descend...",ierr)
2105
2106     if(present(descend)) then
2107        do n=1,nDims
2108           GGrid%descend(n) = descend(n)
2109        end do
2110     else
2111        do n=1,nDims
2112           GGrid%descend(n) = .FALSE.
2113        end do
2114     endif
2115       
2116  endif ! if(present(CoordSortOrder))...
2117 
2118       ! Create Grid attribute data storage AttrVect GGrid%data:
2119
2120  call AttrVect_init(GGrid%data, IAList, RAList, nPoints)
2121  call AttrVect_zero(GGrid%data)
2122
2123       ! Load up gridpoint coordinate data into GGrid%data.
2124       ! Given how we've set up the real attributes of GGrid%data,
2125       ! we have guaranteed the first nDims real attributes are
2126       ! the gridpoint coordinates.
2127
2128  do n=1,nPoints
2129     nOffSet = (n-1) * nDims
2130     do i=1,nDims
2131        GGrid%data%rAttr(i,n) = PointData(nOffset + i)
2132     end do
2133  end do
2134
2135       ! If the argument CoordSortOrder was supplied, the entries
2136       ! of GGrid will be sorted/permuted with this lexicographic
2137       ! ordering, and the values of the GGrid INTEGER attribute
2138       ! GlobGridNum will be numbered to reflect this new ordering
2139       ! scheme.
2140
2141  index = indexIA_(GGrid, GlobGridNum)
2142
2143  if(present(CoordSortOrder)) then ! Sort permute entries before
2144                                   ! numbering them
2145
2146     call SortPermute_(GGrid) ! Sort / permute
2147
2148  endif ! if(present(CoordSortOrder))...
2149
2150       ! Number the gridpoints based on the AttrVect point index
2151       ! (i.e., the second index in GGrid%data%iAttr)
2152
2153  do i=1, lsize_(GGrid)
2154     GGrid%data%iAttr(index,i) = i
2155  end do
2156
2157       ! Clean up temporary allocated structures:
2158
2159  call List_clean(IAList)
2160  call List_clean(RAList)
2161
2162 end subroutine initUnstructuredDP_
2163
2164!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2165!    Math and Computer Science Division, Argonne National Laboratory   !
2166!BOP -------------------------------------------------------------------
2167!
2168! !IROUTINE: clean_ - Destroy a GeneralGrid
2169!
2170! !DESCRIPTION:
2171! This routine deallocates all attribute storage space for the input/output
2172! {\tt GeneralGrid} argument {\tt GGrid}, and destroys all of its {\tt List}
2173! components and sorting flags.  The success (failure) of this operation is
2174! signified by the zero (non-zero) value of the optional {\tt INTEGER}
2175! output argument {\tt stat}.
2176!
2177! !INTERFACE:
2178
2179    subroutine clean_(GGrid, stat)
2180!
2181! !USES:
2182!
2183      use m_stdio
2184      use m_die
2185
2186      use m_List,     only : List_clean => clean
2187      use m_List,     only : List_allocated => allocated
2188      use m_AttrVect, only : AttrVect_clean => clean
2189
2190      implicit none
2191
2192! !INPUT/OUTPUT PARAMETERS:
2193!
2194      type(GeneralGrid), intent(inout) :: GGrid
2195      integer, optional, intent(out)   :: stat
2196
2197! !REVISION HISTORY:
2198! 25Sep00 - J.W. Larson <larson@mcs.anl.gov> - initial prototype
2199! 20Mar01 - J.W. Larson <larson@mcs.anl.gov> - complete version.
2200!  1Mar01 - E.T. Ong <eong@mcs.anl.gov> - removed dies to prevent
2201!           crashes when cleaning uninitialized attrvects. Added
2202!           optional stat argument.
2203!  5Aug02 - E. Ong <eong@mcs.anl.gov> - a more rigorous revision
2204!EOP ___________________________________________________________________
2205
2206  character(len=*),parameter :: myname_=myname//'::clean_'
2207  integer :: ierr
2208
2209  if(present(stat)) then
2210
2211     stat=0
2212     call AttrVect_clean(GGrid%data,ierr)
2213     if(ierr/=0) stat=ierr
2214
2215     call List_clean(GGrid%coordinate_list,ierr)
2216     if(ierr/=0) stat=ierr
2217
2218     if(List_allocated(GGrid%coordinate_sort_order)) then
2219        call List_clean(GGrid%coordinate_sort_order,ierr)
2220        if(ierr/=0) stat=ierr
2221     endif
2222
2223     if(List_allocated(GGrid%weight_list)) then
2224        call List_clean(GGrid%weight_list,ierr)
2225        if(ierr/=0) stat=ierr
2226     endif
2227
2228     if(List_allocated(GGrid%other_list)) then
2229        call List_clean(GGrid%other_list,ierr)
2230        if(ierr/=0) stat=ierr
2231     endif
2232
2233     if(List_allocated(GGrid%index_list)) then
2234        call List_clean(GGrid%index_list,ierr)
2235        if(ierr/=0) stat=ierr
2236     endif
2237
2238     if(associated(GGrid%descend)) then
2239        deallocate(GGrid%descend, stat=ierr)
2240        if(ierr/=0) stat=ierr
2241     endif
2242
2243  else
2244
2245     call AttrVect_clean(GGrid%data)
2246
2247     call List_clean(GGrid%coordinate_list)
2248
2249     if(List_allocated(GGrid%coordinate_sort_order)) then
2250        call List_clean(GGrid%coordinate_sort_order)
2251     endif
2252
2253     if(List_allocated(GGrid%weight_list)) then
2254        call List_clean(GGrid%weight_list)
2255     endif
2256
2257     if(List_allocated(GGrid%other_list)) then
2258        call List_clean(GGrid%other_list)
2259     endif
2260
2261     if(List_allocated(GGrid%index_list)) then
2262        call List_clean(GGrid%index_list)
2263     endif
2264
2265     if(associated(GGrid%descend)) then
2266        deallocate(GGrid%descend, stat=ierr)
2267        if(ierr/=0) call die(myname_,'deallocate(GGrid%descend)',ierr) 
2268     endif
2269
2270  endif
2271
2272 end subroutine clean_
2273
2274!BOP -------------------------------------------------------------------
2275!
2276! !IROUTINE: zero_ - Set GeneralGrid Data to Zero
2277!
2278! !DESCRIPTION:
2279! This routine sets all of the point values of the integer and real
2280! attributes of an the input/output {\tt GeneralGrid} argument {\tt GGrid}
2281! to zero.  The default action is to set the values of all the real and 
2282! integer attributes to zero.
2283!
2284! !INTERFACE:
2285
2286 subroutine zero_(GGrid, zeroReals, zeroInts)
2287
2288! !USES:
2289
2290
2291     use m_die,only     : die
2292     use m_stdio,only   : stderr
2293
2294     use m_AttrVect, only : AttrVect_zero => zero
2295
2296     implicit none
2297! !INPUT/OUTPUT PARAMETERS:
2298!
2299     type(GeneralGrid),    intent(INOUT) :: GGrid
2300
2301! !INPUT PARAMETERS:
2302
2303     logical, optional, intent(IN)    :: zeroReals
2304     logical, optional, intent(IN)    :: zeroInts
2305
2306
2307! !REVISION HISTORY:
2308! 11May08 - R. Jacob <jacob@mcs.anl.gov> - initial prototype/code
2309!EOP ___________________________________________________________________
2310
2311  character(len=*),parameter :: myname_=myname//'::zero_'
2312
2313  logical myZeroReals, myZeroInts
2314
2315  if(present(zeroReals)) then
2316     myZeroReals = zeroReals
2317  else
2318     myZeroReals = .TRUE.
2319  endif
2320
2321  if(present(zeroInts)) then
2322     myZeroInts = zeroInts
2323  else
2324     myZeroInts = .TRUE.
2325  endif
2326
2327  call AttrVect_zero(GGrid%data,myZeroReals,myZeroInts)
2328
2329 end subroutine zero_
2330
2331
2332!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2333!    Math and Computer Science Division, Argonne National Laboratory   !
2334!BOP -------------------------------------------------------------------
2335!
2336! !IROUTINE: dims_ - Return the Dimensionality of a GeneralGrid
2337!
2338! !DESCRIPTION:
2339! This {\tt INTEGER} function returns the number of physical dimensions
2340! of the input {\tt GeneralGrid} argument {\tt GGrid}.
2341!
2342! !INTERFACE:
2343
2344 integer function dims_(GGrid)
2345!
2346! !USES:
2347!
2348      use m_stdio
2349      use m_die
2350
2351      use m_List,     only : List_nitem => nitem
2352
2353      implicit none
2354
2355! !INPUT PARAMETERS:
2356!
2357      type(GeneralGrid), intent(in)  :: GGrid
2358
2359! !REVISION HISTORY:
2360! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - initial version
2361!EOP ___________________________________________________________________
2362!
2363  character(len=*),parameter :: myname_=myname//'::dims_'
2364
2365
2366 dims_ = List_nitem(GGrid%coordinate_list)
2367
2368 if(dims_<=0) then
2369    call die(myname_,"GGrid has zero dimensions",dims_)
2370 endif
2371
2372 end function dims_
2373
2374!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2375!    Math and Computer Science Division, Argonne National Laboratory   !
2376!BOP -------------------------------------------------------------------
2377!
2378! !IROUTINE: indexIA - Index an Integer Attribute
2379!
2380! !DESCRIPTION:
2381! This function returns an {\tt INTEGER}, corresponding to the location
2382! of an integer attribute within the input {\tt GeneralGrid} argument
2383! {\tt GGrid}.  For example, every {\tt GGrid} has at least one integer
2384! attribute (namely the global gridpoint index {\tt 'GlobGridNum'}).
2385! The array of integer values for the attribute {\tt 'GlobGridNum'} is
2386! stored in
2387! \begin{verbatim}
2388! {\tt GGrid%data%iAttr(indexIA_(GGrid,'GlobGridNum'),:)}.
2389! \end{verbatim}
2390! If {\tt indexIA\_()} is unable to match {\tt item} to any of the integer
2391! attributes present in {\tt GGrid}, the resulting value is zero which is
2392! equivalent to an error.  The optional input {\tt CHARACTER} arguments
2393! {\tt perrWith} and {\tt dieWith} control how such errors are handled. 
2394! Below are the rules how error handling is controlled by using
2395! {\tt perrWith} and {\tt dieWith}:
2396! \begin{enumerate}
2397! \item if neither {\tt perrWith} nor {\tt dieWith} are present,
2398! {\tt indexIA\_()} terminates execution with an internally generated
2399! error message;
2400! \item if {\tt perrWith} is present, but {\tt dieWith} is not, an error
2401! message is written to {\tt stderr} incorporating user-supplied
2402! traceback information stored in the argument {\tt perrWith};
2403! \item if {\tt dieWith} is present, execution terminates with an error
2404! message written to {\tt stderr} that incorporates user-supplied
2405! traceback information stored in the argument {\tt dieWith}; and
2406! \item if both {\tt perrWith} and {\tt dieWith} are present, execution
2407! terminates with an error message using {\tt dieWith}, and the argument
2408! {\tt perrWith} is ignored.
2409! \end{enumerate}
2410!
2411! !INTERFACE:
2412
2413 integer function indexIA_(GGrid, item, perrWith, dieWith)
2414
2415!
2416! !USES:
2417!
2418      use m_die
2419      use m_stdio
2420
2421      use m_String, only : String
2422      use m_String, only : String_init => init
2423      use m_String, only : String_clean => clean
2424      use m_String, only : String_ToChar => ToChar
2425
2426      use m_TraceBack, only : GenTraceBackString
2427
2428      use m_AttrVect,     only : AttrVect_indexIA => indexIA
2429
2430      implicit none
2431
2432! !INPUT PARAMETERS:
2433!
2434      type(GeneralGrid),          intent(in) :: GGrid
2435      character(len=*),           intent(in) :: item
2436      character(len=*), optional, intent(in) :: perrWith
2437      character(len=*), optional, intent(in) :: dieWith
2438
2439! !REVISION HISTORY:
2440! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - Initial version.
2441! 27Mar02 - Jay Larson <larson@mcs.anl.gov> - Cleaned up error
2442!           handling logic.
2443!  2Aug02 - Jay Larson <larson@mcs.anl.gov> - Further refinement
2444!           of error handling.
2445!EOP ___________________________________________________________________
2446!
2447
2448 character(len=*), parameter :: myname_=myname//'::indexIA_'
2449
2450 type(String) :: myTrace
2451
2452       ! Generate a traceback String
2453
2454  if(present(dieWith)) then
2455     call GenTraceBackString(myTrace, dieWith, myname_)
2456  else
2457     if(present(perrWith)) then
2458        call GenTraceBackString(myTrace, perrWith, myname_)
2459     else
2460        call GenTraceBackString(myTrace, myname_)
2461     endif
2462  endif
2463
2464       ! Call AttrVect_indexIA() accordingly:
2465
2466  if( present(dieWith) .or. &
2467     ((.not. present(dieWith)) .and. (.not. present(perrWith))) ) then
2468     indexIA_ = AttrVect_indexIA(GGrid%data, item, &
2469                                 dieWith=String_ToChar(myTrace))
2470  else  ! perrWith but no dieWith case
2471     indexIA_ = AttrVect_indexIA(GGrid%data, item, &
2472                   perrWith=String_ToChar(myTrace))
2473  endif
2474
2475  call String_clean(myTrace)
2476
2477 end function indexIA_
2478
2479
2480!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2481!    Math and Computer Science Division, Argonne National Laboratory   !
2482!BOP -------------------------------------------------------------------
2483!
2484! !IROUTINE: indexRA - Index a Real Attribute
2485!
2486! !DESCRIPTION:
2487
2488! This function returns an {\tt INTEGER}, corresponding to the location
2489! of an integer attribute within the input {\tt GeneralGrid} argument
2490! {\tt GGrid}.  For example, every {\tt GGrid} has at least one integer
2491! attribute (namely the global gridpoint index {\tt 'GlobGridNum'}).
2492! The array of integer values for the attribute {\tt 'GlobGridNum'} is
2493! stored in
2494! \begin{verbatim}
2495! {\tt GGrid%data%iAttr(indexRA_(GGrid,'GlobGridNum'),:)}.
2496! \end{verbatim}
2497! If {\tt indexRA\_()} is unable to match {\tt item} to any of the integer
2498! attributes present in {\tt GGrid}, the resulting value is zero which is
2499! equivalent to an error.  The optional input {\tt CHARACTER} arguments
2500! {\tt perrWith} and {\tt dieWith} control how such errors are handled. 
2501! Below are the rules how error handling is controlled by using
2502! {\tt perrWith} and {\tt dieWith}:
2503! \begin{enumerate}
2504! \item if neither {\tt perrWith} nor {\tt dieWith} are present,
2505! {\tt indexRA\_()} terminates execution with an internally generated
2506! error message;
2507! \item if {\tt perrWith} is present, but {\tt dieWith} is not, an error
2508! message is written to {\tt stderr} incorporating user-supplied
2509! traceback information stored in the argument {\tt perrWith};
2510! \item if {\tt dieWith} is present, execution terminates with an error
2511! message written to {\tt stderr} that incorporates user-supplied
2512! traceback information stored in the argument {\tt dieWith}; and
2513! \item if both {\tt perrWith} and {\tt dieWith} are present, execution
2514! terminates with an error message using {\tt dieWith}, and the argument
2515! {\tt perrWith} is ignored.
2516! \end{enumerate}
2517!
2518! !INTERFACE:
2519
2520 integer function indexRA_(GGrid, item, perrWith, dieWith)
2521!
2522! !USES:
2523!
2524      use m_stdio
2525      use m_die
2526
2527      use m_String, only : String
2528      use m_String, only : String_init => init
2529      use m_String, only : String_clean => clean
2530      use m_String, only : String_ToChar => ToChar
2531
2532      use m_TraceBack, only : GenTraceBackString
2533
2534      use m_AttrVect,     only : AttrVect_indexRA => indexRA
2535
2536      implicit none
2537
2538! !INPUT PARAMETERS:
2539!
2540      type(GeneralGrid),          intent(in)  :: GGrid
2541      character(len=*),           intent(in)  :: item
2542      character(len=*), optional, intent(in) :: perrWith
2543      character(len=*), optional, intent(in) :: dieWith
2544
2545! !REVISION HISTORY:
2546! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - Initial version.
2547! 27Mar02 - Jay Larson <larson@mcs.anl.gov> - Cleaned up error
2548!           handling logic.
2549!EOP ___________________________________________________________________
2550!
2551 character(len=*),parameter :: myname_=myname//'::indexRA_'
2552
2553
2554 type(String) :: myTrace
2555
2556       ! Generate a traceback String
2557
2558  if(present(dieWith)) then ! append myname_ onto dieWith
2559     call GenTraceBackString(myTrace, dieWith, myname_)
2560  else
2561     if(present(perrWith)) then ! append myname_ onto perrwith
2562        call GenTraceBackString(myTrace, perrWith, myname_)
2563     else ! Start a TraceBack String
2564        call GenTraceBackString(myTrace, myname_)
2565     endif
2566  endif
2567
2568       ! Call AttrVect_indexRA() accordingly:
2569
2570  if( present(dieWith) .or. &
2571     ((.not. present(dieWith)) .and. (.not. present(perrWith))) ) then
2572     indexRA_ = AttrVect_indexRA(GGrid%data, item, &
2573                                 dieWith=String_ToChar(myTrace))
2574  else  ! perrWith but no dieWith case
2575     indexRA_ = AttrVect_indexRA(GGrid%data, item, &
2576                   perrWith=String_ToChar(myTrace))
2577  endif
2578
2579  call String_clean(myTrace)
2580
2581 end function indexRA_
2582
2583!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2584!    Math and Computer Science Division, Argonne National Laboratory   !
2585!BOP -------------------------------------------------------------------
2586!
2587! !IROUTINE: lsize - Number of Grid Points
2588!
2589! !DESCRIPTION:
2590! This {\tt INTEGER} function returns the number of grid points stored
2591! in the input {\tt GeneralGrid} argument {\tt GGrid}.  Note that the
2592! value returned will be the number of points stored on a local process
2593! in the case of a distributed {\tt GeneralGrid}.
2594!
2595! !INTERFACE:
2596
2597 integer function lsize_(GGrid)
2598!
2599! !USES:
2600!
2601      use m_List,     only : List
2602      use m_List,     only : List_allocated => allocated
2603      use m_AttrVect, only : AttrVect_lsize => lsize
2604      use m_die,      only : die   
2605     
2606
2607      implicit none
2608
2609! !INPUT PARAMETERS:
2610!
2611      type(GeneralGrid), intent(in)  :: GGrid
2612
2613! !REVISION HISTORY:
2614! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - Initial version.
2615! 27Mar02 - Jay Larson <larson@mcs.anl.gov> - slight logic change.
2616! 27Mar02 - Jay Larson <larson@mcs.anl.gov> - Bug fix and use of
2617!           List_allocated() function to check for existence of
2618!           attributes.
2619!  5Aug02 - E. Ong <eong@mcs.anl.gov> - more rigorous revision
2620!EOP ___________________________________________________________________
2621!
2622 character(len=*),parameter :: myname_=myname//'::lsize_'
2623
2624 if(List_allocated(GGrid%data%rList) .and. &
2625      List_allocated(GGrid%data%iList)) then
2626
2627    lsize_ = AttrVect_lsize( GGrid%data )
2628
2629 else
2630
2631    call die(myname_,"Argument GGrid%data is not associated!")
2632
2633 endif
2634
2635 end function lsize_
2636
2637!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2638!    Math and Computer Science Division, Argonne National Laboratory   !
2639!BOP -------------------------------------------------------------------
2640!
2641! !IROUTINE: exportIAttr_ - Return GeneralGrid INTEGER Attribute as a Vector
2642!
2643! !DESCRIPTION:
2644! This routine extracts from the input {\tt GeneralGrid} argument
2645! {\tt GGrid} the integer attribute corresponding to the tag defined in
2646! the input {\tt CHARACTER} argument {\tt AttrTag}, and returns it in
2647! the {\tt INTEGER} output array {\tt outVect}, and its length in the
2648! output {\tt INTEGER} argument {\tt lsize}.
2649!
2650! {\bf N.B.:}  This routine will fail if the {\tt AttrTag} is not in
2651! the {\tt GeneralGrid} {\tt List} component {\tt GGrid\%data\%iList}.
2652!
2653! {\bf N.B.:}  The flexibility of this routine regarding the pointer
2654! association status of the output argument {\tt outVect} means the
2655! user must invoke this routine with care.  If the user wishes this
2656! routine to fill a pre-allocated array, then obviously this array
2657! must be allocated prior to calling this routine.  If the user wishes
2658! that the routine {\em create} the output argument array {\tt outVect},
2659! then the user must ensure this pointer is not allocated (i.e. the user
2660! must nullify this pointer) before this routine is invoked.
2661!
2662! {\bf N.B.:}  If the user has relied on this routine to allocate memory
2663! associated with the pointer {\tt outVect}, then the user is responsible
2664! for deallocating this array once it is no longer needed.  Failure to
2665! do so will result in a memory leak.
2666!
2667! !INTERFACE:
2668
2669 subroutine exportIAttr_(GGrid, AttrTag, outVect, lsize)
2670!
2671! !USES:
2672!
2673      use m_die 
2674      use m_stdio
2675
2676      use m_AttrVect,      only : AttrVect_exportIAttr => exportIAttr
2677
2678      implicit none
2679
2680! !INPUT PARAMETERS:
2681
2682      type(GeneralGrid),      intent(in)  :: GGrid
2683      character(len=*),       intent(in)  :: AttrTag
2684
2685! !OUTPUT PARAMETERS:
2686
2687      integer,  dimension(:), pointer     :: outVect
2688      integer,  optional,     intent(out) :: lsize
2689
2690! !REVISION HISTORY:
2691! 13Dec01 - J.W. Larson <larson@mcs.anl.gov> - initial prototype.
2692!EOP ___________________________________________________________________
2693
2694  character(len=*),parameter :: myname_=myname//'::exportIAttr_'
2695
2696       ! Export the data (inheritance from AttrVect)
2697  if(present(lsize)) then
2698     call AttrVect_exportIAttr(GGrid%data, AttrTag, outVect, lsize)
2699  else
2700     call AttrVect_exportIAttr(GGrid%data, AttrTag, outVect)
2701  endif
2702
2703 end subroutine exportIAttr_
2704
2705!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2706!    Math and Computer Science Division, Argonne National Laboratory   !
2707!BOP -------------------------------------------------------------------
2708!
2709! !IROUTINE: exportRAttrSP_ - Return GeneralGrid REAL Attribute as a Vector
2710!
2711! !DESCRIPTION:
2712! This routine extracts from the input {\tt GeneralGrid} argument
2713! {\tt GGrid} the real attribute corresponding to the tag defined in
2714! the input {\tt CHARACTER} argument {\tt AttrTag}, and returns it in
2715! the {\tt REAL} output array {\tt outVect}, and its length in the
2716! output {\tt INTEGER} argument {\tt lsize}.
2717!
2718! {\bf N.B.:}  This routine will fail if the {\tt AttrTag} is not in
2719! the {\tt GeneralGrid} {\tt List} component {\tt GGrid\%data\%rList}.
2720!
2721! {\bf N.B.:}  The flexibility of this routine regarding the pointer
2722! association status of the output argument {\tt outVect} means the
2723! user must invoke this routine with care.  If the user wishes this
2724! routine to fill a pre-allocated array, then obviously this array
2725! must be allocated prior to calling this routine.  If the user wishes
2726! that the routine {\em create} the output argument array {\tt outVect},
2727! then the user must ensure this pointer is not allocated (i.e. the user
2728! must nullify this pointer) before this routine is invoked.
2729!
2730! {\bf N.B.:}  If the user has relied on this routine to allocate memory
2731! associated with the pointer {\tt outVect}, then the user is responsible
2732! for deallocating this array once it is no longer needed.  Failure to
2733! do so will result in a memory leak.
2734!
2735! !INTERFACE:
2736
2737 subroutine exportRAttrSP_(GGrid, AttrTag, outVect, lsize)
2738!
2739! !USES:
2740!
2741      use m_die
2742      use m_stdio
2743
2744      use m_realkinds,  only : SP
2745
2746      use m_AttrVect,   only : AttrVect_exportRAttr => exportRAttr
2747
2748      implicit none
2749
2750! !INPUT PARAMETERS:
2751
2752      type(GeneralGrid),          intent(in)  :: GGrid
2753      character(len=*),           intent(in)  :: AttrTag
2754
2755! !OUTPUT PARAMETERS:
2756
2757      real(SP),  dimension(:),    pointer     :: outVect
2758      integer,   optional,        intent(out) :: lsize
2759
2760! !REVISION HISTORY:
2761! 13Dec01 - J.W. Larson <larson@mcs.anl.gov> - initial prototype.
2762!
2763!EOP ___________________________________________________________________
2764
2765  character(len=*),parameter :: myname_=myname//'::exportRAttrSP_'
2766
2767       ! Export the data (inheritance from AttrVect)
2768
2769  if(present(lsize)) then
2770     call AttrVect_exportRAttr(GGrid%data, AttrTag, outVect, lsize)
2771  else
2772     call AttrVect_exportRAttr(GGrid%data, AttrTag, outVect)
2773  endif
2774
2775 end subroutine exportRAttrSP_
2776
2777!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2778!    Math and Computer Science Division, Argonne National Laboratory   !
2779! ---------------------------------------------------------------------
2780!
2781! !IROUTINE: exportRAttrDP_ - Return GeneralGrid REAL Attribute as a Vector
2782!
2783! !DESCRIPTION:
2784! double precision version of exportRAttrSP_
2785!
2786! !INTERFACE:
2787
2788 subroutine exportRAttrDP_(GGrid, AttrTag, outVect, lsize)
2789!
2790! !USES:
2791!
2792      use m_die
2793      use m_stdio
2794
2795      use m_realkinds,  only : DP
2796
2797      use m_AttrVect,   only : AttrVect_exportRAttr => exportRAttr
2798
2799      implicit none
2800
2801! !INPUT PARAMETERS:
2802
2803      type(GeneralGrid),          intent(in)  :: GGrid
2804      character(len=*),           intent(in)  :: AttrTag
2805
2806! !OUTPUT PARAMETERS:
2807
2808      real(DP),  dimension(:),    pointer     :: outVect
2809      integer,   optional,        intent(out) :: lsize
2810
2811! !REVISION HISTORY:
2812! 13Dec01 - J.W. Larson <larson@mcs.anl.gov> - initial prototype.
2813!
2814!_______________________________________________________________________
2815
2816  character(len=*),parameter :: myname_=myname//'::exportRAttrDP_'
2817
2818       ! Export the data (inheritance from AttrVect)
2819  if(present(lsize)) then
2820     call AttrVect_exportRAttr(GGrid%data, AttrTag, outVect, lsize)
2821  else
2822     call AttrVect_exportRAttr(GGrid%data, AttrTag, outVect)
2823  endif
2824
2825 end subroutine exportRAttrDP_
2826
2827!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2828!    Math and Computer Science Division, Argonne National Laboratory   !
2829!BOP -------------------------------------------------------------------
2830!
2831! !IROUTINE: importIAttr_ - Import GeneralGrid INTEGER Attribute
2832!
2833! !DESCRIPTION:
2834! This routine imports data provided in the input {\tt INTEGER} vector
2835! {\tt inVect} into the {\tt GeneralGrid} argument {\tt GGrid}, storing
2836! it as the integer attribute corresponding to the tag defined in
2837! the input {\tt CHARACTER} argument {\tt AttrTag}.  The input
2838! {\tt INTEGER} argument {\tt lsize} is used to ensure there is
2839! sufficient space in the {\tt GeneralGrid} to store the data.
2840!
2841! {\bf N.B.:}  This routine will fail if the {\tt AttrTag} is not in
2842! the {\tt GeneralGrid} {\tt List} component {\tt GGrid\%data\%iList}.
2843!
2844! !INTERFACE:
2845
2846 subroutine importIAttr_(GGrid, AttrTag, inVect, lsize)
2847!
2848! !USES:
2849!
2850      use m_die
2851      use m_stdio
2852
2853      use m_AttrVect,      only : AttrVect_importIAttr => importIAttr
2854
2855      implicit none
2856
2857! !INPUT PARAMETERS:
2858
2859      character(len=*),       intent(in)    :: AttrTag
2860      integer,  dimension(:), pointer       :: inVect
2861      integer,                intent(in)    :: lsize
2862
2863! !INPUT/OUTPUT PARAMETERS:
2864
2865      type(GeneralGrid),      intent(inout) :: GGrid
2866
2867! !REVISION HISTORY:
2868! 13Dec01 - J.W. Larson <larson@mcs.anl.gov> - initial prototype.
2869! 27Mar02 - Jay Larson <larson@mcs.anl.gov> - improved error handling.
2870!EOP ___________________________________________________________________
2871
2872  character(len=*),parameter :: myname_=myname//'::importIAttr_'
2873
2874       ! Argument Check:
2875
2876  if(lsize > lsize_(GGrid)) then
2877     write(stderr,*) myname_,':: ERROR, lsize > lsize_(GGrid).', &
2878          'lsize = ',lsize,'lsize_(GGrid) = ',lsize_(GGrid)
2879     call die(myname_)
2880  endif
2881
2882       ! Import the data (inheritance from AttrVect)
2883
2884  call AttrVect_importIAttr(GGrid%data, AttrTag, inVect, lsize)
2885
2886 end subroutine importIAttr_
2887
2888!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2889!    Math and Computer Science Division, Argonne National Laboratory   !
2890!BOP -------------------------------------------------------------------
2891!
2892! !IROUTINE: importRAttrSP_ - Import GeneralGrid REAL Attribute
2893!
2894! !DESCRIPTION:
2895! This routine imports data provided in the input {\tt REAL} vector
2896! {\tt inVect} into the {\tt GeneralGrid} argument {\tt GGrid}, storing
2897! it as the real attribute corresponding to the tag defined in
2898! the input {\tt CHARACTER} argument {\tt AttrTag}.  The input
2899! {\tt INTEGER} argument {\tt lsize} is used to ensure there is
2900! sufficient space in the {\tt GeneralGrid} to store the data.
2901!
2902! {\bf N.B.:}  This routine will fail if the {\tt AttrTag} is not in
2903! the {\tt GeneralGrid} {\tt List} component {\tt GGrid\%data\%rList}.
2904!
2905! !INTERFACE:
2906
2907 subroutine importRAttrSP_(GGrid, AttrTag, inVect, lsize)
2908!
2909! !USES:
2910!
2911      use m_die ,          only : die
2912      use m_die ,          only : MP_perr_die
2913      use m_stdio ,        only : stderr
2914
2915      use m_realkinds,     only : SP
2916
2917      use m_AttrVect,      only : AttrVect_importRAttr => importRAttr
2918
2919      implicit none
2920
2921! !INPUT PARAMETERS:
2922
2923      character(len=*),           intent(in)    :: AttrTag
2924      real(SP), dimension(:),     pointer       :: inVect
2925      integer,                    intent(in)    :: lsize
2926
2927! !INPUT/OUTPUT PARAMETERS:
2928
2929      type(GeneralGrid),          intent(inout) :: GGrid
2930
2931! !REVISION HISTORY:
2932! 13Dec01 - J.W. Larson <larson@mcs.anl.gov> - initial prototype.
2933! 27Mar02 - Jay Larson <larson@mcs.anl.gov> - improved error handling.
2934!EOP ___________________________________________________________________
2935
2936  character(len=*),parameter :: myname_=myname//'::importRAttrSP_'
2937
2938       ! Argument Check:
2939
2940  if(lsize > lsize_(GGrid)) then
2941     write(stderr,*) myname_,':: ERROR, lsize > lsize_(GGrid).', &
2942          'lsize = ',lsize,'lsize_(GGrid) = ',lsize_(GGrid)
2943     call die(myname_)
2944  endif
2945
2946       ! Import the data (inheritance from AttrVect)
2947
2948  call AttrVect_importRAttr(GGrid%data, AttrTag, inVect, lsize)
2949
2950 end subroutine importRAttrSP_
2951
2952!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2953!    Math and Computer Science Division, Argonne National Laboratory   !
2954!-----------------------------------------------------------------------
2955!
2956! !IROUTINE: importRAttrDP_ - Import GeneralGrid REAL Attribute
2957!
2958! !DESCRIPTION:
2959! Double precision version of importRAttrSP_
2960!
2961! !INTERFACE:
2962
2963 subroutine importRAttrDP_(GGrid, AttrTag, inVect, lsize)
2964!
2965! !USES:
2966!
2967      use m_die ,          only : die
2968      use m_die ,          only : MP_perr_die
2969      use m_stdio ,        only : stderr
2970
2971      use m_realkinds,     only : DP
2972
2973      use m_AttrVect,      only : AttrVect_importRAttr => importRAttr
2974
2975      implicit none
2976
2977! !INPUT PARAMETERS:
2978
2979      character(len=*),           intent(in)    :: AttrTag
2980      real(DP), dimension(:),     pointer       :: inVect
2981      integer,                    intent(in)    :: lsize
2982
2983! !INPUT/OUTPUT PARAMETERS:
2984
2985      type(GeneralGrid),          intent(inout) :: GGrid
2986
2987! !REVISION HISTORY:
2988! 13Dec01 - J.W. Larson <larson@mcs.anl.gov> - initial prototype.
2989! 27Mar02 - Jay Larson <larson@mcs.anl.gov> - improved error handling.
2990!_______________________________________________________________________
2991
2992  character(len=*),parameter :: myname_=myname//'::importRAttrDP_'
2993
2994       ! Argument Check:
2995
2996  if(lsize > lsize_(GGrid)) then
2997     write(stderr,*) myname_,':: ERROR, lsize > lsize_(GGrid).', &
2998          'lsize = ',lsize,'lsize_(GGrid) = ',lsize_(GGrid)
2999     call die(myname_)
3000  endif
3001
3002       ! Import the data (inheritance from AttrVect)
3003
3004  call AttrVect_importRAttr(GGrid%data, AttrTag, inVect, lsize)
3005
3006 end subroutine importRAttrDP_
3007
3008!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3009!    Math and Computer Science Division, Argonne National Laboratory   !
3010!BOP -------------------------------------------------------------------
3011!
3012! !IROUTINE: Sort_ - Generate Sort Permutation Defined by Arbitrary Keys.
3013!
3014! !DESCRIPTION:
3015! The subroutine {\tt Sort\_()} uses the list of keys present in the
3016! input  {\tt List} variable {\tt key\_List}.  This list of keys is
3017! checked to ensure that {\em only} coordinate attributes are present
3018! in the sorting keys, and that there are no redundant keys.  Once
3019! checked, this list is used to find the appropriate real attributes
3020! referenced by the items in {\tt key\_list} ( that is, it identifies the
3021! appropriate entries in {\tt GGrid\%data\%rList}), and then uses these
3022! keys to generate a an output permutation {\tt perm} that will put
3023! the entries of the attribute vector {\tt GGrid\%data} in lexicographic
3024! order as defined by {\tt key\_list} (the ordering in {\tt key\_list}
3025! being from left to right.
3026!
3027! !INTERFACE:
3028
3029 subroutine Sort_(GGrid, key_List, perm, descend)
3030
3031!
3032! !USES:
3033!
3034      use m_stdio
3035      use m_die
3036
3037      use m_AttrVect,     only : AttrVect_Sort => Sort
3038      use m_List,        only : List_nitem => nitem
3039
3040      implicit none
3041
3042! !INPUT PARAMETERS:
3043!
3044      type(GeneralGrid),               intent(in) :: GGrid
3045      type(List),                      intent(in) :: key_list
3046      logical, dimension(:), optional, intent(in) :: descend
3047
3048! !OUTPUT PARAMETERS:
3049!
3050      integer, dimension(:), pointer              :: perm
3051
3052
3053! !REVISION HISTORY:
3054! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - Initial version.
3055! 20Mar01 - Jay Larson <larson@mcs.anl.gov> - Final working version.
3056!EOP ___________________________________________________________________
3057!
3058 character(len=*),parameter :: myname_=myname//'::Sort_'
3059 logical, dimension(:), allocatable :: descending
3060 integer :: n, ierr
3061
3062        ! Here is how we transmit the sort order keys stored
3063        ! in descending (if present):
3064
3065  n = List_nitem(key_list)
3066  allocate(descending(n), stat=ierr)
3067  if(ierr /= 0) then
3068     call die(myname_,"allocate(descending...",ierr)
3069  endif
3070
3071  if(present(descend)) then
3072     descending = descend
3073  else
3074     descending = .false.
3075  endif
3076
3077        ! This is a straightforward call to AttrVect_Sort().
3078 
3079  call AttrVect_Sort(GGrid%data, key_list, perm, descending) 
3080
3081        ! Clean up...
3082
3083  deallocate(descending, stat=ierr)
3084  if(ierr /= 0) then
3085     call die(myname_,"deallocate(descending...",ierr)
3086  endif
3087
3088 end subroutine Sort_
3089
3090!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3091!    Math and Computer Science Division, Argonne National Laboratory   !
3092!BOP -------------------------------------------------------------------
3093!
3094! !IROUTINE: Sortg_ - Generate Sort Permutation Based on GeneralGrid Keys.
3095!
3096! !DESCRIPTION:
3097! The subroutine {\tt Sortg\_()} uses the list of sorting keys present in
3098! the input  {\tt GeneralGrid} variable {\tt GGrid\%coordinate\_sort\_order}
3099! to create a sort permutation {\tt perm(:)}.  Sorting is either in ascending
3100! or descending order based on the entries of {\tt GGrid\%descend(:)}.
3101! The output index permutation is stored in the array {\tt perm(:)} that
3102! will put the entries of the attribute vector {\tt GGrid\%data} in
3103! lexicographic order as defined by {\tt GGrid\%coordinate\_sort\_order}. The
3104! ordering in {\tt GGrid\%coordinate\_sort\_order} being from left to right.
3105!
3106! {\bf N.B.:}  This routine returnss an allocatable array perm(:).  This
3107! allocated array must be deallocated when the user no longer needs it. 
3108! Failure to do so will cause a memory leak.
3109!
3110! {\bf N.B.:}  This routine will fail if {\tt GGrid} has not been initialized
3111! with sort keys in the {\tt List} component {\tt GGrid\%coordinate\_sort\_order}.
3112!
3113! !INTERFACE:
3114
3115 subroutine Sortg_(GGrid, perm)
3116
3117!
3118! !USES:
3119!
3120      use m_List, only : List_allocated => allocated
3121      use m_die,  only : die
3122   
3123      implicit none
3124
3125! !INPUT PARAMETERS:
3126!
3127      type(GeneralGrid),     intent(in) :: GGrid
3128
3129! !OUTPUT PARAMETERS:
3130!
3131      integer, dimension(:), pointer    :: perm
3132
3133! !REVISION HISTORY:
3134! 22Mar01 - Jay Larson <larson@mcs.anl.gov> - Initial version.
3135!  5Aug02 - E. Ong <eong@mcs.anl.gov> - revise with more error checking.
3136!EOP ___________________________________________________________________
3137!
3138 character(len=*),parameter :: myname_=myname//'::Sortg_'
3139
3140     if(.not.List_allocated(GGrid%coordinate_sort_order)) then
3141        call die(myname_, "GGrid%coordinate_aort_order must be &
3142                 &allocated for use in any sort function")
3143     endif
3144
3145     if(associated(GGrid%descend)) then
3146        call Sort_(GGrid, GGrid%coordinate_sort_order, &
3147                       perm, GGrid%descend)
3148     else
3149        call Sort_(GGrid=GGrid, key_list=GGrid%coordinate_sort_order, &
3150                       perm=perm)
3151     endif
3152
3153 end subroutine Sortg_
3154
3155!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3156!    Math and Computer Science Division, Argonne National Laboratory   !
3157!BOP -------------------------------------------------------------------
3158!
3159! !IROUTINE: Permute_ - Permute GeneralGrid Attributes Using Supplied Index Permutation
3160!
3161! !DESCRIPTION:
3162! The subroutine {\tt Permute\_()} uses an input index permutation {\tt perm}
3163! to re-order the coordinate data stored in the {\tt GeneralGrid} argument
3164! {\tt GGrid}.  This permutation can be generated by either of the routines
3165! {\tt Sort\_()} or {\tt Sortg\_()} contained in this module.
3166!
3167! !INTERFACE:
3168
3169 subroutine Permute_(GGrid, perm)
3170
3171!
3172! !USES:
3173!
3174
3175      use m_stdio
3176      use m_die
3177
3178      use m_AttrVect,     only : AttrVect
3179      use m_AttrVect, only : AttrVect_Permute => Permute
3180
3181      implicit none
3182
3183! !INPUT PARAMETERS:
3184!
3185      integer, dimension(:), intent(in)    :: perm
3186
3187! !INPUT/OUTPUT PARAMETERS:
3188!
3189      type(GeneralGrid),     intent(inout) :: GGrid
3190
3191
3192! !REVISION HISTORY:
3193! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - API specification.
3194! 10Apr01 - Jay Larson <larson@mcs.anl.gov> - API modified, working
3195!           code.
3196!EOP ___________________________________________________________________
3197!
3198 character(len=*),parameter :: myname_=myname//'::Permute_'
3199
3200        ! This is a straightforward call to AttrVect_Permute:
3201
3202  call AttrVect_Permute(GGrid%data, perm)
3203
3204 end subroutine Permute_
3205
3206!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3207!    Math and Computer Science Division, Argonne National Laboratory   !
3208!BOP -------------------------------------------------------------------
3209!
3210! !IROUTINE: SortPermute_ - Sort and Permute GeneralGrid Attributes
3211!
3212! !DESCRIPTION:
3213! The subroutine {\tt SortPermute\_()} uses the list of keys defined in
3214! {\tt GGrid\%coordinate\_sort\_order} to create an index permutation
3215! {\tt perm}, which is then applied to re-order the coordinate data stored
3216! in the {\tt GeneralGrid} argument {\tt GGrid} (more specifically, the
3217! gridpoint data stored in {\tt GGrid\%data}.  This permutation is generated 
3218! by the routine {\tt Sortg\_()} contained in this module.  The permutation
3219! is carried out by the routine {\tt Permute\_()} contained in this module.
3220!
3221! {\bf N.B.:}  This routine will fail if {\tt GGrid} has not been initialized
3222! with sort keys in the {\tt List} component {\tt GGrid\%coordinate\_sort\_order}.
3223!
3224! !INTERFACE:
3225
3226 subroutine SortPermute_(GGrid)
3227
3228!
3229! !USES:
3230!
3231      use m_stdio
3232      use m_die
3233
3234      implicit none
3235
3236! !INPUT/OUTPUT PARAMETERS:
3237!
3238      type(GeneralGrid),     intent(inout)   :: GGrid
3239
3240! !REVISION HISTORY:
3241! 15Jan01 - Jay Larson <larson@mcs.anl.gov> - API specification.
3242! 10Apr01 - Jay Larson <larson@mcs.anl.gov> - API modified, working
3243!           code.
3244! 13Apr01 - Jay Larson <larson@mcs.anl.gov> - Simplified API and
3245!           code (Thanks to Tony Craig of NCAR for detecting the
3246!           bug that inspired these changes).
3247!EOP ___________________________________________________________________
3248!
3249 character(len=*),parameter :: myname_=myname//'::SortPermute_'
3250
3251 integer, dimension(:), pointer :: perm
3252 integer :: ierr
3253
3254  call Sortg_(GGrid, perm)
3255
3256  call Permute_(GGrid, perm)
3257
3258! Clean up--deallocate temporary permutation array:
3259
3260  deallocate(perm, stat=ierr)
3261  if(ierr /= 0) then
3262     call die(myname_,"deallocate(perm)",ierr)
3263  endif
3264
3265 end subroutine SortPermute_
3266
3267 end module m_GeneralGrid
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
Note: See TracBrowser for help on using the repository browser.