SALSA Analysis Modules
options.c
Go to the documentation of this file.
00001 /*! \file options.c \ingroup implementation
00002 
00003   \brief Commandline options handling
00004 
00005 */
00006 /*!  \page options Commandline options
00007 
00008   The runtime behaviour of AnaMod can be influenced by commandline options,
00009   specified at the start of the calling application.
00010 
00011   All options start with \c "-anamod" and they can have a sequence of
00012   comma-separated values separated from the option by a 
00013   blank: \c "-anamod_option value1,value2". Note the single dash, which is Petsc
00014   style, as opposed to the double dash of GNU style.
00015 
00016   - \c -anamod_force : Certain operations can be very expensive, 
00017   for instance because
00018   they need to be performed on a single processor. AnaMod will be default 
00019   refuse to compute these quantities, but their computation can be forced
00020   by \c "-anamod_force <option>" where \c option is
00021     - \c "expensive" : certain modules are very expensive to compute in
00022     certain circumstances, so AnaMod will normally refuse to compute them.
00023     (See \ref normal.) This option forces their computation, no matter how
00024     much time they may take.
00025     - \c "sequential" : certain modules are only implemented as single
00026     processor code, so they will normally not be computed in a parallel
00027     run. This option will force processor zero to gather the full matrix,
00028     and perform the computation locally. I hope I do not have to point out
00029     the potential pitfalls of this option. Sequential modules are the norms
00030     of the symmetric/anti-symmetric part in the \ref simple category.
00031   - Each module can have options \c "-anamod_<module name> <option>".
00032   If the module has declared a function to handle such options, that
00033   function is called here. This implies that the AnaModOptionsHandling()
00034   function needs to be called after all modules have been declared.
00035   - \c "-anamod_use_only <mod>" : prevent other categories from
00036   being computed
00037   - \c -anamod_compute : (not implemented yet)
00038 
00039  */
00040 
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include "anamod.h"
00044 #include "petsc.h"
00045 
00046 static PetscTruth single_proc = PETSC_FALSE, expensive = PETSC_FALSE;
00047 
00048 #undef __FUNCT__
00049 #define __FUNCT__ "AnaModOptionsHandling"
00050 /*!
00051   Process any commandline options that were given for AnaMod.
00052   These use the regular Petsc commandline options database.
00053 
00054   This routine handles general options and module-specific options,
00055   so it has to be called after all modules have been declared.
00056 
00057   See DeclareCategoryOptionFunction(),CategoryGetOptionFunction(),
00058   AnaModOptionsHandling() and section \ref options.
00059 */
00060 PetscErrorCode AnaModOptionsHandling()
00061 {
00062   PetscTruth flg; PetscErrorCode ierr;
00063   char *value;
00064   PetscFunctionBegin;
00065 
00066 #define VALUELEN 150
00067   ierr = PetscMalloc(VALUELEN*sizeof(char),&value); CHKERRQ(ierr);
00068 
00069   {
00070     ierr = PetscOptionsHasName(PETSC_NULL,"-anamod_force",&flg); CHKERRQ(ierr);
00071     if (flg) {
00072       ierr = PetscOptionsGetString
00073         (PETSC_NULL,"-anamod_force",value,VALUELEN,&flg); CHKERRQ(ierr);
00074       if (flg) {
00075         char *c;
00076         c = strtok(value,",");
00077         while (c) {
00078           ierr = PetscStrcmp(c,"sequential",&flg); CHKERRQ(ierr);
00079           if (flg) single_proc = PETSC_TRUE;
00080           ierr = PetscStrcmp(c,"expensive",&flg); CHKERRQ(ierr);
00081           if (flg) expensive = PETSC_TRUE;
00082           c = strtok(NULL,",");
00083         }
00084       }
00085     }
00086   }
00087 
00088   {
00089     const char **categories; char *option; int icat,ncats;
00090     ierr = PetscMalloc(30*sizeof(char),&option); CHKERRQ(ierr);
00091     ierr = GetCategories(&ncats,&categories); CHKERRQ(ierr);
00092     for (icat=0; icat<ncats; icat++) {
00093       ierr = PetscMemzero(value,VALUELEN*sizeof(char)); CHKERRQ(ierr);      
00094       ierr = PetscMemzero(option,30*sizeof(char)); CHKERRQ(ierr);
00095       sprintf(option,"-anamod_%s",categories[icat]);
00096       ierr = PetscOptionsGetString
00097         (PETSC_NULL,option,value,VALUELEN,&flg); CHKERRQ(ierr);
00098       if (flg) {
00099         PetscErrorCode (*f)(char*);
00100         ierr = CategoryGetOptionFunction(categories[icat],&f); CHKERRQ(ierr);
00101         if (f) {
00102           ierr = (*f)(value); CHKERRQ(ierr);
00103         }
00104       }
00105     }
00106     ierr = PetscFree(option); CHKERRQ(ierr);
00107   }
00108 
00109   {
00110     ierr = PetscOptionsGetString
00111       (PETSC_NULL,"-anamod_use_only",value,VALUELEN,&flg); CHKERRQ(ierr);
00112     if (flg) {
00113       int ncats,icat; const char **cats;
00114       ierr = GetCategories(&ncats,&cats); CHKERRQ(ierr);
00115       for (icat=0; icat<ncats; icat++) {
00116         if (strcmp(value,cats[icat])) {
00117           ierr = CategoryEnableByName
00118             (cats[icat],CATCMP_SKIP_FROM_LOOPS); CHKERRQ(ierr);
00119         }
00120       }
00121     }
00122   }
00123 
00124   ierr = PetscFree(value); CHKERRQ(ierr);
00125 
00126   PetscFunctionReturn(0);
00127 }
00128 
00129 #undef __FUNCT__
00130 #define __FUNCT__ "AnaModShowOptions"
00131 /*! Display all available options. This depends on the installed modules,
00132   so you need to do the various register calls first. See \ref usage.
00133 
00134   For options see \ref options.
00135 */
00136 PetscErrorCode AnaModShowOptions(MPI_Comm comm)
00137 {
00138   PetscErrorCode ierr;
00139   PetscFunctionBegin;
00140   PetscPrintf(comm,"Available AnaMod options\n  Global:\n");
00141   PetscPrintf(comm,"  -anamod_use_only mod : use only the specified module\n");
00142   PetscPrintf(comm,"  -anamod_force sequential : do sequential computations\n  even in parallel runs\n");
00143   PetscPrintf(comm,"  -anamod_force expensive : do certain calculations no matter how expensive\n");
00144   PetscPrintf(comm,"\n  Categories and modules:\n");
00145   {
00146     const char **categories; char *option; int icat,ncats;
00147     ierr = PetscMalloc(30*sizeof(char),&option); CHKERRQ(ierr);
00148     ierr = GetCategories(&ncats,&categories); CHKERRQ(ierr);
00149     for (icat=0; icat<ncats; icat++) {
00150       ierr = PetscMemzero(option,30*sizeof(char)); CHKERRQ(ierr);
00151       PetscPrintf
00152         (comm,"  -anamod_%s : options for category %s\n",
00153          categories[icat],categories[icat]);
00154     }
00155     ierr = PetscFree(option); CHKERRQ(ierr);
00156   }
00157   PetscFunctionReturn(0);
00158 }
00159 
00160 #undef __FUNCT__
00161 #define __FUNCT__ "AnaModHasForcedSequentialComputation"
00162 /*!
00163   Query whether parallel modules should be done on processor zero.
00164 */
00165 PetscErrorCode AnaModHasForcedSequentialComputation(PetscTruth *flg)
00166 {
00167   PetscFunctionBegin;
00168   *flg = single_proc;
00169   PetscFunctionReturn(0);
00170 }
00171 
00172 #undef __FUNCT__
00173 #define __FUNCT__ "AnaModGetSequentialMatrix"
00174 /*!
00175   Collect the matrix on processor zero.
00176 
00177   There is an implicit assumption here that processor zero is the one
00178   that will do the actual work.
00179 
00180   Argument:
00181   - \c A : input matrix
00182   - \c Awork : pointer to the sequential matrix, this can be a pointer
00183   to the original matrix if it was already sequential; it is NULL
00184   if no forced sequential computation is asked (see \ref options)
00185   - \c mem : true if \c Awork is newly allocated
00186   - \c local : true if this processor needs to do the work
00187   - \c global : true if any processor does work; this condition is false
00188   in the case of a distributed matrix and no forced sequential operation
00189 
00190 */
00191 PetscErrorCode AnaModGetSequentialMatrix
00192 (Mat A,Mat *Awork,PetscTruth *mem,PetscTruth *local,PetscTruth *global)
00193 {
00194   MPI_Comm comm; const MatType type; int mytid;
00195   PetscTruth flg; PetscErrorCode ierr;
00196   PetscFunctionBegin;
00197 
00198   ierr = PetscObjectGetComm((PetscObject)A,&comm); CHKERRQ(ierr);
00199   MPI_Comm_rank(comm,&mytid);
00200   ierr = MatGetType(A,&type); CHKERRQ(ierr);
00201   ierr = PetscStrcmp(type,MATSEQAIJ,&flg); CHKERRQ(ierr);
00202   if (flg) {
00203     *Awork = A; *mem = PETSC_FALSE;
00204     *local = PETSC_TRUE; *global = PETSC_TRUE;
00205   } else {
00206     ierr = AnaModHasForcedSequentialComputation(&flg); CHKERRQ(ierr);
00207     if (!flg) {
00208       *Awork = NULL;
00209       *mem = PETSC_FALSE; *local = PETSC_FALSE; *global = PETSC_FALSE;
00210       PetscFunctionReturn(0);
00211     }
00212     *global = PETSC_TRUE;
00213     {
00214       Mat *Arow; IS is[1]; int N,M;
00215       ierr = MatGetSize(A,&M,&N); CHKERRQ(ierr);
00216       if (mytid==0) {
00217         ierr = ISCreateStride(MPI_COMM_SELF,M,0,1,is); CHKERRQ(ierr);
00218         *local = PETSC_TRUE;
00219       } else {
00220         ierr = ISCreateStride(MPI_COMM_SELF,0,0,1,is); CHKERRQ(ierr);
00221         *local = PETSC_FALSE;
00222       }
00223       ierr = MatGetSubMatrices
00224         (A,1,is,is,MAT_INITIAL_MATRIX,&Arow); CHKERRQ(ierr);
00225       ierr = ISDestroy(is[0]); CHKERRQ(ierr);
00226       *Awork = Arow[0]; *mem = PETSC_TRUE;
00227     }
00228   }
00229   PetscFunctionReturn(0);
00230 }
00231 
00232 #undef __FUNCT__
00233 #define __FUNCT__ "AnaModHasForcedExpensiveComputation"
00234 /*!
00235   Query whether certain expensive operations should be done 
00236   regardless the cost.
00237 */
00238 PetscErrorCode AnaModHasForcedExpensiveComputation(PetscTruth *flg)
00239 {
00240   PetscFunctionBegin;
00241   *flg = expensive;
00242   PetscFunctionReturn(0);
00243 }