xref: /petsc/src/vec/is/utils/isltog.c (revision 549d3d68a6ae470532d58d544870024f02ff2d7c)
1d4bb536fSBarry Smith 
2a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
3*549d3d68SSatish Balay static char vcid[] = "$Id: isltog.c,v 1.27 1999/02/01 21:43:29 curfman Exp balay $";
42362add9SBarry Smith #endif
52362add9SBarry Smith 
62362add9SBarry Smith #include "sys.h"   /*I "sys.h" I*/
783271157SBarry Smith #include "src/vec/is/isimpl.h"    /*I "is.h"  I*/
82362add9SBarry Smith 
95615d1e5SSatish Balay #undef __FUNC__
105a5d4f66SBarry Smith #define __FUNC__ "ISLocalToGlobalMappingView"
115a5d4f66SBarry Smith /*@C
125a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
135a5d4f66SBarry Smith 
14b9cd556bSLois Curfman McInnes     Not Collective
15b9cd556bSLois Curfman McInnes 
165a5d4f66SBarry Smith     Input Parameters:
175a5d4f66SBarry Smith .   ltog - local to global mapping
18b9cd556bSLois Curfman McInnes .   viewer - viewer
195a5d4f66SBarry Smith 
20a997ad1aSLois Curfman McInnes     Level: advanced
21a997ad1aSLois Curfman McInnes 
225a5d4f66SBarry Smith .keywords: IS, local-to-global mapping, create
235a5d4f66SBarry Smith 
245a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
255a5d4f66SBarry Smith @*/
265a5d4f66SBarry Smith int ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,Viewer viewer)
275a5d4f66SBarry Smith {
285a5d4f66SBarry Smith   int      i;
295a5d4f66SBarry Smith 
305a5d4f66SBarry Smith   PetscFunctionBegin;
315a5d4f66SBarry Smith 
325a5d4f66SBarry Smith   for ( i=0; i<mapping->n; i++ ) {
335a5d4f66SBarry Smith     printf("%d %d\n",i,mapping->indices[i]);
345a5d4f66SBarry Smith   }
355a5d4f66SBarry Smith 
365a5d4f66SBarry Smith   PetscFunctionReturn(0);
375a5d4f66SBarry Smith }
385a5d4f66SBarry Smith 
395a5d4f66SBarry Smith #undef __FUNC__
402bdab257SBarry Smith #define __FUNC__ "ISLocalToGlobalMappingCreateIS"
412bdab257SBarry Smith /*@C
422bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
432bdab257SBarry Smith     ordering and a global parallel ordering.
442bdab257SBarry Smith 
45b9cd556bSLois Curfman McInnes     Collective on IS
46b9cd556bSLois Curfman McInnes 
47a997ad1aSLois Curfman McInnes     Input Parameter:
482bdab257SBarry Smith .   is - index set containing the global numbers for each local
492bdab257SBarry Smith 
50a997ad1aSLois Curfman McInnes     Output Parameter:
512bdab257SBarry Smith .   mapping - new mapping data structure
522bdab257SBarry Smith 
53a997ad1aSLois Curfman McInnes     Level: advanced
54a997ad1aSLois Curfman McInnes 
552bdab257SBarry Smith .keywords: IS, local-to-global mapping, create
562bdab257SBarry Smith 
572bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
582bdab257SBarry Smith @*/
592bdab257SBarry Smith int ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
602bdab257SBarry Smith {
612bdab257SBarry Smith   int      n,*indices,ierr;
622bdab257SBarry Smith   MPI_Comm comm;
633a40ed3dSBarry Smith 
643a40ed3dSBarry Smith   PetscFunctionBegin;
652bdab257SBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
662bdab257SBarry Smith 
672bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
682bdab257SBarry Smith   ierr = ISGetSize(is,&n);CHKERRQ(ierr);
692bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
702bdab257SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,mapping);CHKERRQ(ierr);
712bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
722bdab257SBarry Smith 
733a40ed3dSBarry Smith   PetscFunctionReturn(0);
742bdab257SBarry Smith }
755a5d4f66SBarry Smith 
762bdab257SBarry Smith #undef __FUNC__
77d4bb536fSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingCreate"
78dd7157adSSatish Balay /*@C
7990f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
8090f02eecSBarry Smith     ordering and a global parallel ordering.
812362add9SBarry Smith 
82b9cd556bSLois Curfman McInnes     Collective on MPI_Comm
83b9cd556bSLois Curfman McInnes 
842362add9SBarry Smith     Input Parameters:
85b9cd556bSLois Curfman McInnes +   comm - MPI communicator of size 1.
8690f02eecSBarry Smith .   n - the number of local elements
87b9cd556bSLois Curfman McInnes -   indices - the global index for each local element
882362add9SBarry Smith 
89a997ad1aSLois Curfman McInnes     Output Parameter:
9090f02eecSBarry Smith .   mapping - new mapping data structure
912362add9SBarry Smith 
92a997ad1aSLois Curfman McInnes     Level: advanced
93a997ad1aSLois Curfman McInnes 
943acfe500SLois Curfman McInnes .keywords: IS, local-to-global mapping, create
952362add9SBarry Smith 
962bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
972362add9SBarry Smith @*/
98987e4450SSatish Balay int ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
992362add9SBarry Smith {
100*549d3d68SSatish Balay   int ierr;
101*549d3d68SSatish Balay 
1023a40ed3dSBarry Smith   PetscFunctionBegin;
10390f02eecSBarry Smith   PetscValidIntPointer(indices);
10490f02eecSBarry Smith   PetscValidPointer(mapping);
1052362add9SBarry Smith 
1063f1db9ecSBarry Smith   PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping",
1073f1db9ecSBarry Smith                     cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);
108d4bb536fSBarry Smith   PLogObjectCreate(*mapping);
109d4bb536fSBarry Smith   PLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
110d4bb536fSBarry Smith 
111d4bb536fSBarry Smith   (*mapping)->n       = n;
11290f02eecSBarry Smith   (*mapping)->indices = (int *) PetscMalloc((n+1)*sizeof(int));CHKPTRQ((*mapping)->indices);
113*549d3d68SSatish Balay   ierr = PetscMemcpy((*mapping)->indices,indices,n*sizeof(int));CHKERRQ(ierr);
114d4bb536fSBarry Smith 
115d4bb536fSBarry Smith   /*
116d4bb536fSBarry Smith       Do not create the global to local mapping. This is only created if
117d4bb536fSBarry Smith      ISGlobalToLocalMapping() is called
118d4bb536fSBarry Smith   */
119d4bb536fSBarry Smith   (*mapping)->globals = 0;
1203a40ed3dSBarry Smith   PetscFunctionReturn(0);
1212362add9SBarry Smith }
1222362add9SBarry Smith 
1235615d1e5SSatish Balay #undef __FUNC__
124d4bb536fSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingDestroy"
12590f02eecSBarry Smith /*@
12690f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
12790f02eecSBarry Smith    ordering and a global parallel ordering.
12890f02eecSBarry Smith 
129b9cd556bSLois Curfman McInnes    Collective on ISLocalToGlobalMapping
130b9cd556bSLois Curfman McInnes 
13190f02eecSBarry Smith    Input Parameters:
13290f02eecSBarry Smith .  mapping - mapping data structure
13390f02eecSBarry Smith 
134a997ad1aSLois Curfman McInnes    Level: advanced
135a997ad1aSLois Curfman McInnes 
1363acfe500SLois Curfman McInnes .keywords: IS, local-to-global mapping, destroy
13790f02eecSBarry Smith 
1383acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
13990f02eecSBarry Smith @*/
14090f02eecSBarry Smith int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
14190f02eecSBarry Smith {
1423a40ed3dSBarry Smith   PetscFunctionBegin;
14390f02eecSBarry Smith   PetscValidPointer(mapping);
1443a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
14590f02eecSBarry Smith 
14690f02eecSBarry Smith   PetscFree(mapping->indices);
147d4bb536fSBarry Smith   if (mapping->globals) PetscFree(mapping->globals);
148d4bb536fSBarry Smith   PLogObjectDestroy(mapping);
149d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
1503a40ed3dSBarry Smith   PetscFunctionReturn(0);
15190f02eecSBarry Smith }
15290f02eecSBarry Smith 
1535615d1e5SSatish Balay #undef __FUNC__
154d4bb536fSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingApplyIS"
15590f02eecSBarry Smith /*@
1563acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
1573acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
1583acfe500SLois Curfman McInnes     context.
15990f02eecSBarry Smith 
160b9cd556bSLois Curfman McInnes     Not collective
161b9cd556bSLois Curfman McInnes 
16290f02eecSBarry Smith     Input Parameters:
163b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
164b9cd556bSLois Curfman McInnes -   is - index set in local numbering
16590f02eecSBarry Smith 
16690f02eecSBarry Smith     Output Parameters:
16790f02eecSBarry Smith .   newis - index set in global numbering
16890f02eecSBarry Smith 
169a997ad1aSLois Curfman McInnes     Level: advanced
170a997ad1aSLois Curfman McInnes 
1713acfe500SLois Curfman McInnes .keywords: IS, local-to-global mapping, apply
1723acfe500SLois Curfman McInnes 
17390f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
174d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
17590f02eecSBarry Smith @*/
17690f02eecSBarry Smith int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping, IS is, IS *newis)
17790f02eecSBarry Smith {
17890f02eecSBarry Smith   int ierr,n,i,*idxin,*idxmap,*idxout;
1793a40ed3dSBarry Smith 
1803a40ed3dSBarry Smith   PetscFunctionBegin;
18190f02eecSBarry Smith   PetscValidPointer(mapping);
18290f02eecSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
18390f02eecSBarry Smith   PetscValidPointer(newis);
18490f02eecSBarry Smith 
18590f02eecSBarry Smith   ierr   = ISGetSize(is,&n);CHKERRQ(ierr);
18690f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
18790f02eecSBarry Smith   idxmap = mapping->indices;
18890f02eecSBarry Smith 
18990f02eecSBarry Smith   idxout = (int *) PetscMalloc((n+1)*sizeof(int));CHKPTRQ(idxout);
19090f02eecSBarry Smith   for ( i=0; i<n; i++ ) {
19190f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
19290f02eecSBarry Smith   }
193029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
19490f02eecSBarry Smith   PetscFree(idxout);
1953a40ed3dSBarry Smith   PetscFunctionReturn(0);
19690f02eecSBarry Smith }
19790f02eecSBarry Smith 
1985615d1e5SSatish Balay #undef __FUNC__
199d4bb536fSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingApply"
200d4bb536fSBarry Smith /*@C
2013acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
2023acfe500SLois Curfman McInnes    and converts them to the global numbering.
20390f02eecSBarry Smith 
204b9cd556bSLois Curfman McInnes    Not collective
205b9cd556bSLois Curfman McInnes 
206bb25748dSBarry Smith    Input Parameters:
207b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
208bb25748dSBarry Smith .  N - number of integers
209b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
210bb25748dSBarry Smith 
211bb25748dSBarry Smith    Output Parameter:
212bb25748dSBarry Smith .  out - indices in global numbering
213bb25748dSBarry Smith 
214b9cd556bSLois Curfman McInnes    Notes:
215b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
216d4bb536fSBarry Smith 
217a997ad1aSLois Curfman McInnes    Level: advanced
218a997ad1aSLois Curfman McInnes 
219bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
2200752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
221d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
222bb25748dSBarry Smith 
2233acfe500SLois Curfman McInnes .keywords: local-to-global, mapping, apply
224d4bb536fSBarry Smith 
225d4bb536fSBarry Smith @*/
226987e4450SSatish Balay int ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,const int in[],int out[])
227d4bb536fSBarry Smith {
228d4bb536fSBarry Smith   int i,*idx = mapping->indices,Nmax = mapping->n;
2293a40ed3dSBarry Smith 
2303a40ed3dSBarry Smith   PetscFunctionBegin;
231d4bb536fSBarry Smith   for ( i=0; i<N; i++ ) {
232d4bb536fSBarry Smith     if (in[i] < 0) {out[i] = in[i]; continue;}
233596552b5SBarry Smith     if (in[i] >= Nmax) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,1,"Local index %d too large %d (max)",in[i],Nmax);
234d4bb536fSBarry Smith     out[i] = idx[in[i]];
235d4bb536fSBarry Smith   }
2363a40ed3dSBarry Smith   PetscFunctionReturn(0);
237d4bb536fSBarry Smith }
238d4bb536fSBarry Smith 
239d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
240d4bb536fSBarry Smith 
241d4bb536fSBarry Smith #undef __FUNC__
242d4bb536fSBarry Smith #define __FUNC__ "ISGlobalToLocalMappingSetUp_Private"
243d4bb536fSBarry Smith /*
244d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
245d4bb536fSBarry Smith */
246d4bb536fSBarry Smith static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
247d4bb536fSBarry Smith {
248d4bb536fSBarry Smith   int i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
249d4bb536fSBarry Smith 
2503a40ed3dSBarry Smith   PetscFunctionBegin;
251d4bb536fSBarry Smith   end   = 0;
252d4bb536fSBarry Smith   start = 100000000;
253d4bb536fSBarry Smith 
254d4bb536fSBarry Smith   for ( i=0; i<n; i++ ) {
255d4bb536fSBarry Smith     if (idx[i] < 0) continue;
256d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
257d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
258d4bb536fSBarry Smith   }
259d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
260d4bb536fSBarry Smith   mapping->globalstart = start;
261d4bb536fSBarry Smith   mapping->globalend   = end;
262d4bb536fSBarry Smith 
263d4bb536fSBarry Smith   globals = mapping->globals = (int *) PetscMalloc((end-start+2)*sizeof(int));CHKPTRQ(mapping->globals);
264d4bb536fSBarry Smith   for ( i=0; i<end-start+1; i++ ) {
265d4bb536fSBarry Smith     globals[i] = -1;
266d4bb536fSBarry Smith   }
267d4bb536fSBarry Smith   for ( i=0; i<n; i++ ) {
268d4bb536fSBarry Smith     if (idx[i] < 0) continue;
269d4bb536fSBarry Smith     globals[idx[i] - start] = i;
270d4bb536fSBarry Smith   }
271d4bb536fSBarry Smith 
272d4bb536fSBarry Smith   PLogObjectMemory(mapping,(end-start+1)*sizeof(int));
2733a40ed3dSBarry Smith   PetscFunctionReturn(0);
274d4bb536fSBarry Smith }
275d4bb536fSBarry Smith 
276d4bb536fSBarry Smith #undef __FUNC__
277d4bb536fSBarry Smith #define __FUNC__ "ISGlobalToLocalMappingApply"
278d4bb536fSBarry Smith /*@
279a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
280a997ad1aSLois Curfman McInnes     specified with a global numbering.
281d4bb536fSBarry Smith 
282b9cd556bSLois Curfman McInnes     Not collective
283b9cd556bSLois Curfman McInnes 
284d4bb536fSBarry Smith     Input Parameters:
285b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
286d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
287d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
288d4bb536fSBarry Smith .   n - number of global indices to map
289b9cd556bSLois Curfman McInnes -   idx - global indices to map
290d4bb536fSBarry Smith 
291d4bb536fSBarry Smith     Output Parameters:
292b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
293b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
294e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
295e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
296e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
297e182c471SBarry Smith              a second time to set the values.
298d4bb536fSBarry Smith 
299b9cd556bSLois Curfman McInnes     Notes:
300b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
301d4bb536fSBarry Smith 
302a997ad1aSLois Curfman McInnes     Level: advanced
303a997ad1aSLois Curfman McInnes 
304d4bb536fSBarry Smith .keywords: IS, global-to-local mapping, apply
305d4bb536fSBarry Smith 
306d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
307d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
308d4bb536fSBarry Smith @*/
309d4bb536fSBarry Smith int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingType type,
310987e4450SSatish Balay                                   int n, const int idx[],int *nout,int idxout[])
311d4bb536fSBarry Smith {
312d4bb536fSBarry Smith   int i,ierr, *globals,nf = 0,tmp,start,end;
313d4bb536fSBarry Smith 
3143a40ed3dSBarry Smith   PetscFunctionBegin;
315d4bb536fSBarry Smith   if (!mapping->globals) {
316d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
317d4bb536fSBarry Smith   }
318d4bb536fSBarry Smith   globals = mapping->globals;
319d4bb536fSBarry Smith   start   = mapping->globalstart;
320d4bb536fSBarry Smith   end     = mapping->globalend;
321d4bb536fSBarry Smith 
322d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
323d4bb536fSBarry Smith     if (idxout) {
324d4bb536fSBarry Smith       for ( i=0; i<n; i++ ) {
325d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
326d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
327d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
328d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
329d4bb536fSBarry Smith       }
330d4bb536fSBarry Smith     }
331d4bb536fSBarry Smith     if (nout) *nout = n;
332d4bb536fSBarry Smith   } else {
333d4bb536fSBarry Smith     if (idxout) {
334d4bb536fSBarry Smith       for ( i=0; i<n; i++ ) {
335d4bb536fSBarry Smith         if (idx[i] < 0) continue;
336d4bb536fSBarry Smith         if (idx[i] < start) continue;
337d4bb536fSBarry Smith         if (idx[i] > end) continue;
338d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
339d4bb536fSBarry Smith         if (tmp < 0) continue;
340d4bb536fSBarry Smith         idxout[nf++] = tmp;
341d4bb536fSBarry Smith       }
342d4bb536fSBarry Smith     } else {
343d4bb536fSBarry Smith       for ( i=0; i<n; i++ ) {
344d4bb536fSBarry Smith         if (idx[i] < 0) continue;
345d4bb536fSBarry Smith         if (idx[i] < start) continue;
346d4bb536fSBarry Smith         if (idx[i] > end) continue;
347d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
348d4bb536fSBarry Smith         if (tmp < 0) continue;
349d4bb536fSBarry Smith         nf++;
350d4bb536fSBarry Smith       }
351d4bb536fSBarry Smith     }
352d4bb536fSBarry Smith     if (nout) *nout = nf;
353d4bb536fSBarry Smith   }
354d4bb536fSBarry Smith 
3553a40ed3dSBarry Smith   PetscFunctionReturn(0);
356d4bb536fSBarry Smith }
35790f02eecSBarry Smith 
358