xref: /petsc/src/sys/classes/viewer/impls/ascii/vcreatea.c (revision ef19f93092e352e3913c051be7ff665cb50f0bd9)
15c6c1daeSBarry Smith 
25c6c1daeSBarry Smith #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>  /*I     "petscsys.h"   I*/
35c6c1daeSBarry Smith 
45c6c1daeSBarry Smith /* ---------------------------------------------------------------------*/
55c6c1daeSBarry Smith 
65c6c1daeSBarry Smith #undef __FUNCT__
75c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerASCIIGetStdout"
85c6c1daeSBarry Smith /*@C
95c6c1daeSBarry Smith    PetscViewerASCIIGetStdout - Creates a ASCII PetscViewer shared by all processors
105c6c1daeSBarry Smith                     in a communicator. Error returning version of PETSC_VIEWER_STDOUT_()
115c6c1daeSBarry Smith 
125c6c1daeSBarry Smith    Collective on MPI_Comm
135c6c1daeSBarry Smith 
145c6c1daeSBarry Smith    Input Parameter:
155c6c1daeSBarry Smith .  comm - the MPI communicator to share the PetscViewer
165c6c1daeSBarry Smith 
175c6c1daeSBarry Smith    Level: beginner
185c6c1daeSBarry Smith 
195c6c1daeSBarry Smith    Notes:
205c6c1daeSBarry Smith      This should be used in all PETSc source code instead of PETSC_VIEWER_STDOUT_()
215c6c1daeSBarry Smith 
225c6c1daeSBarry Smith .seealso: PETSC_VIEWER_DRAW_(), PetscViewerASCIIOpen(), PETSC_VIEWER_STDERR_, PETSC_VIEWER_STDOUT_WORLD,
235c6c1daeSBarry Smith           PETSC_VIEWER_STDOUT_SELF
245c6c1daeSBarry Smith 
255c6c1daeSBarry Smith @*/
265c6c1daeSBarry Smith PetscErrorCode  PetscViewerASCIIGetStdout(MPI_Comm comm,PetscViewer *viewer)
275c6c1daeSBarry Smith {
285c6c1daeSBarry Smith   PetscErrorCode ierr;
295c6c1daeSBarry Smith 
305c6c1daeSBarry Smith   PetscFunctionBegin;
31*ef19f930SBarry Smith   ierr = PetscViewerASCIIOpen(comm,"stdout",viewer);CHKERRQ(ierr);
325c6c1daeSBarry Smith   PetscFunctionReturn(0);
335c6c1daeSBarry Smith }
345c6c1daeSBarry Smith 
355c6c1daeSBarry Smith #undef __FUNCT__
365c6c1daeSBarry Smith #define __FUNCT__ "PETSC_VIEWER_STDOUT_"
375c6c1daeSBarry Smith /*@C
385c6c1daeSBarry Smith    PETSC_VIEWER_STDOUT_ - Creates a ASCII PetscViewer shared by all processors
395c6c1daeSBarry Smith                     in a communicator.
405c6c1daeSBarry Smith 
415c6c1daeSBarry Smith    Collective on MPI_Comm
425c6c1daeSBarry Smith 
435c6c1daeSBarry Smith    Input Parameter:
445c6c1daeSBarry Smith .  comm - the MPI communicator to share the PetscViewer
455c6c1daeSBarry Smith 
465c6c1daeSBarry Smith    Level: beginner
475c6c1daeSBarry Smith 
485c6c1daeSBarry Smith    Notes:
495c6c1daeSBarry Smith    Unlike almost all other PETSc routines, this does not return
505c6c1daeSBarry Smith    an error code. Usually used in the form
515c6c1daeSBarry Smith $      XXXView(XXX object,PETSC_VIEWER_STDOUT_(comm));
525c6c1daeSBarry Smith 
535c6c1daeSBarry Smith .seealso: PETSC_VIEWER_DRAW_(), PetscViewerASCIIOpen(), PETSC_VIEWER_STDERR_, PETSC_VIEWER_STDOUT_WORLD,
545c6c1daeSBarry Smith           PETSC_VIEWER_STDOUT_SELF
555c6c1daeSBarry Smith 
565c6c1daeSBarry Smith @*/
575c6c1daeSBarry Smith PetscViewer  PETSC_VIEWER_STDOUT_(MPI_Comm comm)
585c6c1daeSBarry Smith {
595c6c1daeSBarry Smith   PetscErrorCode ierr;
605c6c1daeSBarry Smith   PetscViewer    viewer;
615c6c1daeSBarry Smith 
625c6c1daeSBarry Smith   PetscFunctionBegin;
635c6c1daeSBarry Smith   ierr = PetscViewerASCIIGetStdout(comm,&viewer);
64efca3c55SSatish Balay   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_STDOUT_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); PetscFunctionReturn(0);}
655c6c1daeSBarry Smith   PetscFunctionReturn(viewer);
665c6c1daeSBarry Smith }
675c6c1daeSBarry Smith 
685c6c1daeSBarry Smith /* ---------------------------------------------------------------------*/
695c6c1daeSBarry Smith 
705c6c1daeSBarry Smith #undef __FUNCT__
715c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerASCIIGetStderr"
725c6c1daeSBarry Smith /*@C
735c6c1daeSBarry Smith    PetscViewerASCIIGetStderr - Creates a ASCII PetscViewer shared by all processors
745c6c1daeSBarry Smith                     in a communicator. Error returning version of PETSC_VIEWER_STDERR_()
755c6c1daeSBarry Smith 
765c6c1daeSBarry Smith    Collective on MPI_Comm
775c6c1daeSBarry Smith 
785c6c1daeSBarry Smith    Input Parameter:
795c6c1daeSBarry Smith .  comm - the MPI communicator to share the PetscViewer
805c6c1daeSBarry Smith 
815c6c1daeSBarry Smith    Level: beginner
825c6c1daeSBarry Smith 
835c6c1daeSBarry Smith    Notes:
845c6c1daeSBarry Smith      This should be used in all PETSc source code instead of PETSC_VIEWER_STDERR_()
855c6c1daeSBarry Smith 
865c6c1daeSBarry Smith .seealso: PETSC_VIEWER_DRAW_(), PetscViewerASCIIOpen(), PETSC_VIEWER_STDERR_, PETSC_VIEWER_STDERR_WORLD,
875c6c1daeSBarry Smith           PETSC_VIEWER_STDERR_SELF
885c6c1daeSBarry Smith 
895c6c1daeSBarry Smith @*/
905c6c1daeSBarry Smith PetscErrorCode  PetscViewerASCIIGetStderr(MPI_Comm comm,PetscViewer *viewer)
915c6c1daeSBarry Smith {
925c6c1daeSBarry Smith   PetscErrorCode ierr;
935c6c1daeSBarry Smith 
945c6c1daeSBarry Smith   PetscFunctionBegin;
95*ef19f930SBarry Smith   ierr = PetscViewerASCIIOpen(comm,"stderr",viewer);CHKERRQ(ierr);
965c6c1daeSBarry Smith   PetscFunctionReturn(0);
975c6c1daeSBarry Smith }
985c6c1daeSBarry Smith 
995c6c1daeSBarry Smith #undef __FUNCT__
1005c6c1daeSBarry Smith #define __FUNCT__ "PETSC_VIEWER_STDERR_"
1015c6c1daeSBarry Smith /*@C
1025c6c1daeSBarry Smith    PETSC_VIEWER_STDERR_ - Creates a ASCII PetscViewer shared by all processors
1035c6c1daeSBarry Smith                     in a communicator.
1045c6c1daeSBarry Smith 
1055c6c1daeSBarry Smith    Collective on MPI_Comm
1065c6c1daeSBarry Smith 
1075c6c1daeSBarry Smith    Input Parameter:
1085c6c1daeSBarry Smith .  comm - the MPI communicator to share the PetscViewer
1095c6c1daeSBarry Smith 
1105c6c1daeSBarry Smith    Level: beginner
1115c6c1daeSBarry Smith 
1125c6c1daeSBarry Smith    Note:
1135c6c1daeSBarry Smith    Unlike almost all other PETSc routines, this does not return
1145c6c1daeSBarry Smith    an error code. Usually used in the form
1155c6c1daeSBarry Smith $      XXXView(XXX object,PETSC_VIEWER_STDERR_(comm));
1165c6c1daeSBarry Smith 
1175c6c1daeSBarry Smith .seealso: PETSC_VIEWER_DRAW_, PetscViewerASCIIOpen(), PETSC_VIEWER_STDOUT_, PETSC_VIEWER_STDOUT_WORLD,
1185c6c1daeSBarry Smith           PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDERR_WORLD, PETSC_VIEWER_STDERR_SELF
1195c6c1daeSBarry Smith @*/
1205c6c1daeSBarry Smith PetscViewer  PETSC_VIEWER_STDERR_(MPI_Comm comm)
1215c6c1daeSBarry Smith {
1225c6c1daeSBarry Smith   PetscErrorCode ierr;
1235c6c1daeSBarry Smith   PetscViewer    viewer;
1245c6c1daeSBarry Smith 
1255c6c1daeSBarry Smith   PetscFunctionBegin;
1265c6c1daeSBarry Smith   ierr = PetscViewerASCIIGetStderr(comm,&viewer);
127efca3c55SSatish Balay   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_STDERR_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); PetscFunctionReturn(0);}
1285c6c1daeSBarry Smith   PetscFunctionReturn(viewer);
1295c6c1daeSBarry Smith }
1305c6c1daeSBarry Smith 
1315c6c1daeSBarry Smith 
1325c6c1daeSBarry Smith PetscMPIInt Petsc_Viewer_keyval = MPI_KEYVAL_INVALID;
1335c6c1daeSBarry Smith #undef __FUNCT__
1345c6c1daeSBarry Smith #define __FUNCT__ "Petsc_DelViewer"
1355c6c1daeSBarry Smith /*
1365c6c1daeSBarry Smith    Called with MPI_Comm_free() is called on a communicator that has a viewer as an attribute. The viewer is not actually destroyed because that is managed by
1375c6c1daeSBarry Smith    PetscObjectDestroyRegisterAll(). PetscViewerASCIIGetStdout() registers the viewer with PetscObjectDestroyRegister() to be destroyed when PetscFinalize() is called.
1385c6c1daeSBarry Smith 
1395c6c1daeSBarry Smith   This is called by MPI, not by users.
1405c6c1daeSBarry Smith 
1415c6c1daeSBarry Smith */
1428cc058d9SJed Brown PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelViewer(MPI_Comm comm,PetscMPIInt keyval,void *attr_val,void *extra_state)
1435c6c1daeSBarry Smith {
1445c6c1daeSBarry Smith   PetscErrorCode ierr;
1455c6c1daeSBarry Smith 
1465c6c1daeSBarry Smith   PetscFunctionBegin;
1475c6c1daeSBarry Smith   ierr = PetscInfo1(0,"Removing viewer data attribute in an MPI_Comm %ld\n",(long)comm);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr);
1485c6c1daeSBarry Smith   PetscFunctionReturn(MPI_SUCCESS);
1495c6c1daeSBarry Smith }
1505c6c1daeSBarry Smith 
1515c6c1daeSBarry Smith #undef __FUNCT__
1525c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerASCIIOpen"
1535c6c1daeSBarry Smith /*@C
1545c6c1daeSBarry Smith    PetscViewerASCIIOpen - Opens an ASCII file as a PetscViewer.
1555c6c1daeSBarry Smith 
1565c6c1daeSBarry Smith    Collective on MPI_Comm
1575c6c1daeSBarry Smith 
1585c6c1daeSBarry Smith    Input Parameters:
1595c6c1daeSBarry Smith +  comm - the communicator
1605c6c1daeSBarry Smith -  name - the file name
1615c6c1daeSBarry Smith 
1625c6c1daeSBarry Smith    Output Parameter:
1635c6c1daeSBarry Smith .  lab - the PetscViewer to use with the specified file
1645c6c1daeSBarry Smith 
1655c6c1daeSBarry Smith    Level: beginner
1665c6c1daeSBarry Smith 
1675c6c1daeSBarry Smith    Notes:
1685c6c1daeSBarry Smith    This PetscViewer can be destroyed with PetscViewerDestroy().
1695c6c1daeSBarry Smith 
1702ea3bc1cSBarry Smith    The MPI communicator used here must match that used by the object one is viewing. For example if the
1712ea3bc1cSBarry Smith    Mat was created with a PETSC_COMM_WORLD, then the Viewer must be created with PETSC_COMM_WORLD
1725c6c1daeSBarry Smith 
1735c6c1daeSBarry Smith    As shown below, PetscViewerASCIIOpen() is useful in conjunction with
1745c6c1daeSBarry Smith    MatView() and VecView()
1755c6c1daeSBarry Smith .vb
1765c6c1daeSBarry Smith      PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer);
1775c6c1daeSBarry Smith      MatView(matrix,viewer);
1785c6c1daeSBarry Smith .ve
1795c6c1daeSBarry Smith 
1805c6c1daeSBarry Smith   Concepts: PetscViewerASCII^creating
1815c6c1daeSBarry Smith   Concepts: printf
1825c6c1daeSBarry Smith   Concepts: printing
1835c6c1daeSBarry Smith   Concepts: accessing remote file
1845c6c1daeSBarry Smith   Concepts: remote file
1855c6c1daeSBarry Smith 
1865c6c1daeSBarry Smith .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerBinaryOpen(),
1875c6c1daeSBarry Smith           PetscViewerASCIIGetPointer(), PetscViewerSetFormat(), PETSC_VIEWER_STDOUT_, PETSC_VIEWER_STDERR_,
1885c6c1daeSBarry Smith           PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF,
1895c6c1daeSBarry Smith @*/
1905c6c1daeSBarry Smith PetscErrorCode  PetscViewerASCIIOpen(MPI_Comm comm,const char name[],PetscViewer *lab)
1915c6c1daeSBarry Smith {
1925c6c1daeSBarry Smith   PetscErrorCode  ierr;
1935c6c1daeSBarry Smith   PetscViewerLink *vlink,*nv;
1945c6c1daeSBarry Smith   PetscBool       flg,eq;
1955c6c1daeSBarry Smith   size_t          len;
1965c6c1daeSBarry Smith 
1975c6c1daeSBarry Smith   PetscFunctionBegin;
1985c6c1daeSBarry Smith   ierr = PetscStrlen(name,&len);CHKERRQ(ierr);
1995c6c1daeSBarry Smith   if (!len) {
2005c6c1daeSBarry Smith     ierr = PetscViewerASCIIGetStdout(comm,lab);CHKERRQ(ierr);
2015c6c1daeSBarry Smith     ierr = PetscObjectReference((PetscObject)*lab);CHKERRQ(ierr);
2025c6c1daeSBarry Smith     PetscFunctionReturn(0);
2035c6c1daeSBarry Smith   }
204*ef19f930SBarry Smith   ierr = PetscSpinlockLock(&PetscViewerASCIISpinLock);CHKERRQ(ierr);
2055c6c1daeSBarry Smith   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) {
2065c6c1daeSBarry Smith     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelViewer,&Petsc_Viewer_keyval,(void*)0);CHKERRQ(ierr);
2075c6c1daeSBarry Smith   }
2082bf49c77SBarry Smith   /*
2092bf49c77SBarry Smith        It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator
2102bf49c77SBarry Smith      we cannot do that, since PetscFileSetName() takes a communicator that already exists.
2112bf49c77SBarry Smith 
2122bf49c77SBarry Smith       Plus if the original communicator that created the file has since been close this will not detect the old
2132bf49c77SBarry Smith       communictor and hence will overwrite the old data. It may be better to simply remove all this code
2142bf49c77SBarry Smith   */
2155c6c1daeSBarry Smith   /* make sure communicator is a PETSc communicator */
2160298fd71SBarry Smith   ierr = PetscCommDuplicate(comm,&comm,NULL);CHKERRQ(ierr);
2175c6c1daeSBarry Smith   /* has file already been opened into a viewer */
2185c6c1daeSBarry Smith   ierr = MPI_Attr_get(comm,Petsc_Viewer_keyval,(void**)&vlink,(PetscMPIInt*)&flg);CHKERRQ(ierr);
2195c6c1daeSBarry Smith   if (flg) {
2205c6c1daeSBarry Smith     while (vlink) {
2215c6c1daeSBarry Smith       ierr = PetscStrcmp(name,((PetscViewer_ASCII*)(vlink->viewer->data))->filename,&eq);CHKERRQ(ierr);
2225c6c1daeSBarry Smith       if (eq) {
2235c6c1daeSBarry Smith         ierr = PetscObjectReference((PetscObject)vlink->viewer);CHKERRQ(ierr);
2245c6c1daeSBarry Smith         *lab = vlink->viewer;
2255c6c1daeSBarry Smith         ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
226*ef19f930SBarry Smith         ierr = PetscSpinlockUnlock(&PetscViewerASCIISpinLock);CHKERRQ(ierr);
2275c6c1daeSBarry Smith         PetscFunctionReturn(0);
2285c6c1daeSBarry Smith       }
2295c6c1daeSBarry Smith       vlink = vlink->next;
2305c6c1daeSBarry Smith     }
2315c6c1daeSBarry Smith   }
2325c6c1daeSBarry Smith   ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr);
2335c6c1daeSBarry Smith   ierr = PetscViewerSetType(*lab,PETSCVIEWERASCII);CHKERRQ(ierr);
2345c6c1daeSBarry Smith   if (name) {
2355c6c1daeSBarry Smith     ierr = PetscViewerFileSetName(*lab,name);CHKERRQ(ierr);
2365c6c1daeSBarry Smith   }
2375c6c1daeSBarry Smith   /* save viewer into communicator if needed later */
238b00a9115SJed Brown   ierr       = PetscNew(&nv);CHKERRQ(ierr);
2395c6c1daeSBarry Smith   nv->viewer = *lab;
2405c6c1daeSBarry Smith   if (!flg) {
2415c6c1daeSBarry Smith     ierr = MPI_Attr_put(comm,Petsc_Viewer_keyval,nv);CHKERRQ(ierr);
2425c6c1daeSBarry Smith   } else {
2435c6c1daeSBarry Smith     ierr = MPI_Attr_get(comm,Petsc_Viewer_keyval,(void**)&vlink,(PetscMPIInt*)&flg);CHKERRQ(ierr);
2445c6c1daeSBarry Smith     if (vlink) {
2455c6c1daeSBarry Smith       while (vlink->next) vlink = vlink->next;
2465c6c1daeSBarry Smith       vlink->next = nv;
2475c6c1daeSBarry Smith     } else {
2485c6c1daeSBarry Smith       ierr = MPI_Attr_put(comm,Petsc_Viewer_keyval,nv);CHKERRQ(ierr);
2495c6c1daeSBarry Smith     }
2505c6c1daeSBarry Smith   }
2515c6c1daeSBarry Smith   ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
252*ef19f930SBarry Smith   ierr = PetscSpinlockUnlock(&PetscViewerASCIISpinLock);CHKERRQ(ierr);
2535c6c1daeSBarry Smith   PetscFunctionReturn(0);
2545c6c1daeSBarry Smith }
2555c6c1daeSBarry Smith 
2565c6c1daeSBarry Smith #undef __FUNCT__
2575c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerASCIIOpenWithFILE"
2585c6c1daeSBarry Smith /*@C
2595c6c1daeSBarry Smith    PetscViewerASCIIOpenWithFILE - Given an open file creates an ASCII viewer that prints to it.
2605c6c1daeSBarry Smith 
2615c6c1daeSBarry Smith    Collective on MPI_Comm
2625c6c1daeSBarry Smith 
2635c6c1daeSBarry Smith    Input Parameters:
2645c6c1daeSBarry Smith +  comm - the communicator
2655c6c1daeSBarry Smith -  fd - the FILE pointer
2665c6c1daeSBarry Smith 
2675c6c1daeSBarry Smith    Output Parameter:
2685c6c1daeSBarry Smith .  lab - the PetscViewer to use with the specified file
2695c6c1daeSBarry Smith 
2705c6c1daeSBarry Smith    Level: beginner
2715c6c1daeSBarry Smith 
2725c6c1daeSBarry Smith    Notes:
2735c6c1daeSBarry Smith    This PetscViewer can be destroyed with PetscViewerDestroy(), but the fd will NOT be closed.
2745c6c1daeSBarry Smith 
2755c6c1daeSBarry Smith    If a multiprocessor communicator is used (such as PETSC_COMM_WORLD),
2765c6c1daeSBarry Smith    then only the first processor in the group uses the file.  All other
2775c6c1daeSBarry Smith    processors send their data to the first processor to print.
2785c6c1daeSBarry Smith 
2795c6c1daeSBarry Smith   Concepts: PetscViewerASCII^creating
2805c6c1daeSBarry Smith   Concepts: printf
2815c6c1daeSBarry Smith   Concepts: printing
2825c6c1daeSBarry Smith   Concepts: accessing remote file
2835c6c1daeSBarry Smith   Concepts: remote file
2845c6c1daeSBarry Smith 
2855c6c1daeSBarry Smith .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerBinaryOpen(),
2865c6c1daeSBarry Smith           PetscViewerASCIIGetPointer(), PetscViewerSetFormat(), PETSC_VIEWER_STDOUT_, PETSC_VIEWER_STDERR_,
2875c6c1daeSBarry Smith           PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF, PetscViewerASCIIOpen()
2885c6c1daeSBarry Smith @*/
2895c6c1daeSBarry Smith PetscErrorCode  PetscViewerASCIIOpenWithFILE(MPI_Comm comm,FILE *fd,PetscViewer *lab)
2905c6c1daeSBarry Smith {
2915c6c1daeSBarry Smith   PetscErrorCode ierr;
2925c6c1daeSBarry Smith 
2935c6c1daeSBarry Smith   PetscFunctionBegin;
2945c6c1daeSBarry Smith   ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr);
2955c6c1daeSBarry Smith   ierr = PetscViewerSetType(*lab,PETSCVIEWERASCII);CHKERRQ(ierr);
2965c6c1daeSBarry Smith   ierr = PetscViewerASCIISetFILE(*lab,fd);CHKERRQ(ierr);
2975c6c1daeSBarry Smith   PetscFunctionReturn(0);
2985c6c1daeSBarry Smith }
2995c6c1daeSBarry Smith 
3005c6c1daeSBarry Smith #undef __FUNCT__
3015c6c1daeSBarry Smith #define __FUNCT__ "PetscViewerASCIISetFILE"
3025c6c1daeSBarry Smith PetscErrorCode  PetscViewerASCIISetFILE(PetscViewer viewer,FILE *fd)
3035c6c1daeSBarry Smith {
3045c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
3055c6c1daeSBarry Smith 
3065c6c1daeSBarry Smith   PetscFunctionBegin;
3075c6c1daeSBarry Smith   vascii->fd        = fd;
3085c6c1daeSBarry Smith   vascii->closefile = PETSC_FALSE;
3095c6c1daeSBarry Smith   PetscFunctionReturn(0);
3105c6c1daeSBarry Smith }
3115c6c1daeSBarry Smith 
3125c6c1daeSBarry Smith 
3135c6c1daeSBarry Smith 
314