SALSA Analysis Modules
|
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 PetscBool 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 PetscBool 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(PetscBool *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,PetscBool *mem,PetscBool *local,PetscBool *global) 00193 { 00194 MPI_Comm comm; const MatType type; int mytid; 00195 PetscBool flg; PetscErrorCode ierr; 00196 PetscFunctionBegin; 00197 00198 ierr = PetscObjectGetComm((PetscObject)A,&comm); CHKERRQ(ierr); 00199 ierr = 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(PetscBool *flg) 00239 { 00240 PetscFunctionBegin; 00241 *flg = expensive; 00242 PetscFunctionReturn(0); 00243 }