SALSA Analysis Modules
category.c
Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <string.h>
00003 #include "anamod.h"
00004 #include "petscmat.h"
00005 
00006 #define CATEGORYCOOKIE 983429
00007 #define CHECKVALIDCATEGORY(x) ANAMODCHECKVALID(x,CATEGORYCOOKIE,"category")
00008 
00009 struct categoryobject_ {
00010   int cookie;
00011   const char *name;
00012   int enabled; /* 1: enable, 0: never compute, -1: skip from loops */
00013   int maxcomponents,ncomponents; 
00014   PetscErrorCode (*optionfunction)(char*);
00015   componentobject *components; const char **componentnames;
00016   AnalysisDataType *types;
00017 } ;
00018 
00019 extern int ncategories;
00020 int maxcategories;
00021 extern categoryobject *categoryobjects;
00022 const char **categorynames; /* pointers to the names in the actual objects */
00023 
00024 #undef __FUNCT__
00025 #define __FUNCT__ "AllocCategoryObjects"
00026 PetscErrorCode AllocCategoryObjects()
00027 {
00028   PetscErrorCode ierr;
00029   PetscFunctionBegin;
00030   maxcategories = MXC; ncategories = 0;
00031   ierr = PetscMalloc
00032     (maxcategories*sizeof(categoryobject),&categoryobjects); CHKERRQ(ierr);
00033   ierr = PetscMalloc
00034     (maxcategories*sizeof(char*),&categorynames); CHKERRQ(ierr);
00035   PetscFunctionReturn(0);
00036 }
00037 
00038 #undef __FUNCT__
00039 #define __FUNCT__ "FreeCategoryObjects"
00040 PetscErrorCode FreeCategoryObjects()
00041 {
00042   int icat; PetscErrorCode ierr;
00043   PetscFunctionBegin;
00044   for (icat=0; icat<ncategories; icat++) {
00045     ierr = DestroyCategoryObject(categoryobjects[icat]); CHKERRQ(ierr);
00046   }
00047   ierr = PetscFree(categoryobjects); CHKERRQ(ierr);
00048   ierr = PetscFree(categorynames); CHKERRQ(ierr);
00049   PetscFunctionReturn(0);
00050 }
00051 
00052 #undef __FUNCT__
00053 #define __FUNCT__ "CreateCategoryObject"
00054 /*! Create a category object with a given name.
00055   See also DestroyCategoryObject(). 
00056 */
00057 PetscErrorCode CreateCategoryObject(const char *cat,categoryobject *obj)
00058 {
00059   categoryobject nnew; PetscErrorCode ierr;
00060 
00061   PetscFunctionBegin;
00062   ierr = PetscMalloc(sizeof(struct categoryobject_),&nnew); CHKERRQ(ierr);
00063   ierr = PetscStrallocpy(cat,(char**)&(nnew->name)); CHKERRQ(ierr);
00064   nnew->cookie = CATEGORYCOOKIE; nnew->enabled = CATCMP_ENABLE;
00065   nnew->maxcomponents = MXC; nnew->ncomponents = 0;
00066   ierr = PetscMalloc
00067     (nnew->maxcomponents*sizeof(componentobject),&(nnew->components)); CHKERRQ(ierr);
00068   ierr = PetscMalloc
00069     (nnew->maxcomponents*sizeof(char*),&(nnew->componentnames)); CHKERRQ(ierr);
00070   ierr = PetscMalloc
00071      (nnew->maxcomponents*sizeof(AnalysisDataType),&(nnew->types)); CHKERRQ(ierr);
00072   *obj = nnew;
00073   PetscFunctionReturn(0);
00074 }
00075 
00076 #undef __FUNCT__
00077 #define __FUNCT__ "DestroyCategoryObject"
00078 /*! Deallocate a category object. See also CreateCategoryObject(). */
00079 PetscErrorCode DestroyCategoryObject(categoryobject obj)
00080 {
00081   int icmp; PetscErrorCode ierr;
00082   PetscFunctionBegin;
00083   CHECKVALIDCATEGORY(obj);
00084   for (icmp=0; icmp<obj->ncomponents; icmp++) {
00085     ierr = DestroyComponentObject(obj->components[icmp]); CHKERRQ(ierr);
00086   }
00087   ierr = PetscFree(obj->components); CHKERRQ(ierr);
00088   ierr = PetscFree(obj->componentnames); CHKERRQ(ierr);
00089   ierr = PetscFree(obj->types); CHKERRQ(ierr);
00090   ierr = PetscFree(obj->name); CHKERRQ(ierr);
00091   ierr = PetscFree(obj); CHKERRQ(ierr);
00092   PetscFunctionReturn(0);
00093 }
00094 
00095 #undef __FUNCT__
00096 #define __FUNCT__ "GetCategoryIndex"
00097 /*! Test for existence of a category, and return its index
00098   if present. Both output parameters can be null.
00099 */
00100 static PetscErrorCode GetCategoryIndex(const char* cat,int *icat,PetscTruth *flag)
00101 {
00102   int i; PetscTruth flg; PetscErrorCode ierr;
00103   PetscFunctionBegin;
00104   flg = PETSC_FALSE;
00105   for (i=0; i<ncategories; i++) {
00106     ierr = PetscStrcmp(cat,categoryobjects[i]->name,&flg); CHKERRQ(ierr);
00107     if (flg) {if (icat) *icat = i; goto found;}
00108   }
00109  found:
00110   if (flag) *flag = flg;
00111   if (!flag && !flg)
00112     SETERRQ(1,"Category not found but no flag provided to report this");
00113   PetscFunctionReturn(0);
00114 }
00115 
00116 #undef __FUNCT__
00117 #define __FUNCT__ "GetOrCreateCategory"
00118 /*! Return a named category, creating it if necessary */
00119 PetscErrorCode GetOrCreateCategory(const char *cat,categoryobject *catg)
00120 {
00121   int icat; PetscTruth flg; PetscErrorCode ierr;
00122   PetscFunctionBegin;
00123   ierr = GetCategoryIndex(cat,&icat,&flg); CHKERRQ(ierr);
00124   if (!flg) {
00125     icat = ncategories++;
00126     if (icat>=maxcategories)
00127       SETERRQ(1,"Category reallocation not implemented");
00128     ierr = CreateCategoryObject(cat,&categoryobjects[icat]); CHKERRQ(ierr);
00129     categorynames[icat] = categoryobjects[icat]->name;
00130   }
00131   *catg = categoryobjects[icat];
00132   PetscFunctionReturn(0);
00133 }
00134 
00135 #undef __FUNCT__
00136 #define __FUNCT__ "GetCategory"
00137 /*! Return a named category */
00138 PetscErrorCode GetCategory(const char *cat,categoryobject *catg,PetscTruth *f)
00139 {
00140   int icat; PetscTruth flg; PetscErrorCode ierr;
00141   PetscFunctionBegin;
00142   ierr = GetCategoryIndex(cat,&icat,&flg); CHKERRQ(ierr);
00143   if (f) *f = flg;
00144   if (flg && catg) *catg = categoryobjects[icat];
00145   PetscFunctionReturn(0);
00146 }
00147 
00148 #undef __FUNCT__
00149 #define __FUNCT__ "GetCategories"
00150 PetscErrorCode GetCategories(int *ncat,const char ***cats)
00151 {
00152   PetscFunctionBegin;
00153   if (ncat) *ncat = ncategories;
00154   if (cats) *cats = categorynames;
00155   PetscFunctionReturn(0);
00156 }
00157 
00158 #undef __FUNCT__
00159 #define __FUNCT__ "CategoryGetComponentIndex"
00160 /*! Test for presence of a component in a category, and return its index
00161   if present. The index parameter can be null.
00162 */
00163 PetscErrorCode CategoryGetComponentIndex
00164 (categoryobject catg,const char *cmp,int *icmp,PetscTruth *flag)
00165 {
00166   int i; PetscTruth flg; PetscErrorCode ierr;
00167   PetscFunctionBegin;
00168   CHECKVALIDCATEGORY(catg);
00169   flg = PETSC_FALSE;
00170   for (i=0; i<catg->ncomponents; i++) {
00171     ierr = PetscStrcmp(cmp,catg->componentnames[i],&flg); CHKERRQ(ierr);
00172     if (flg) {if (icmp) *icmp = i; goto found;}
00173   }
00174  found:
00175   if (flag) *flag = flg;
00176   if (!flg && !flag)
00177     SETERRQ(1,"Component not found but no flag to return this info");
00178   PetscFunctionReturn(0);
00179 }
00180 
00181 #undef __FUNCT__
00182 #define __FUNCT__ "CategoryGetOrCreateComponent"
00183 PetscErrorCode CategoryGetOrCreateComponent
00184 (categoryobject catg,const char *cmp,componentobject *cmpt)
00185 {
00186   int icmp; PetscTruth flg; PetscErrorCode ierr;
00187   PetscFunctionBegin;
00188   CHECKVALIDCATEGORY(catg);
00189   ierr = CategoryGetComponentIndex(catg,cmp,&icmp,&flg); CHKERRQ(ierr);
00190   if (!flg) {
00191     icmp = catg->ncomponents++;
00192     if (icmp>=catg->maxcomponents)
00193       SETERRQ(1,"Component reallocation not implemented");
00194     ierr = CreateComponentObject(cmp,&(catg->components[icmp])); CHKERRQ(ierr);
00195     ierr = ComponentGetName
00196       (catg->components[icmp],&(catg->componentnames[icmp])); CHKERRQ(ierr);
00197   }
00198   *cmpt = catg->components[icmp];
00199   PetscFunctionReturn(0);
00200 }
00201 
00202 #undef __FUNCT__
00203 #define __FUNCT__ "CategoryGetComponent"
00204 /*! Retrieve a component.
00205 
00206   See also CategoryGetOrCreateComponent(), CategoryGetComponentIndex().
00207 */
00208 PetscErrorCode CategoryGetComponent
00209 (categoryobject catg,const char *cmp,componentobject *cmpt,PetscTruth *success)
00210 {
00211   int icmp; PetscTruth flg; PetscErrorCode ierr;
00212   PetscFunctionBegin;
00213   CHECKVALIDCATEGORY(catg);
00214   ierr = CategoryGetComponentIndex(catg,cmp,&icmp,&flg); CHKERRQ(ierr);
00215   if (success) *success = flg;
00216   if (flg) {
00217     if (cmpt) *cmpt = catg->components[icmp];
00218   } else if (!success)
00219     SETERRQ(1,"Component not found but no flag given to report this");
00220   PetscFunctionReturn(0);
00221 }
00222 
00223 #undef __FUNCT__
00224 #define __FUNCT__ "CategoryComponentSetModule"
00225 PetscErrorCode CategoryComponentSetModule
00226 (const char *cat,const char *cmp,AnalysisDataType type,int id,
00227  PetscErrorCode(*f)(AnaModNumericalProblem,AnalysisItem*,int*,PetscTruth*))
00228 {
00229   categoryobject catg; componentobject cmpt; int icmp; PetscErrorCode ierr;
00230   PetscFunctionBegin;
00231   ierr = GetOrCreateCategory(cat,&catg); CHKERRQ(ierr);
00232   ierr = CategoryGetOrCreateComponent(catg,cmp,&cmpt); CHKERRQ(ierr);
00233   ierr = ComponentSetModule(cmpt,type,id,f); CHKERRQ(ierr);
00234   ierr = CategoryGetComponentIndex(catg,cmp,&icmp,PETSC_NULL); CHKERRQ(ierr);
00235   catg->types[icmp] = type;
00236   PetscFunctionReturn(0);
00237 }
00238 
00239 #undef __FUNCT__
00240 #define __FUNCT__ "CategoryGetModules"
00241 /*! Query the modules in a specified category.
00242 
00243   The category name has to exist. The routine will call the Petsc error
00244   handler if the name is invalid.
00245 
00246   Parameters:
00247   - \c cat : the category that is being queried
00248   - \c ms (optional) : the names of the modules in the category
00249   - \c t (optional) : the corresponding list of datatypes
00250   - \c id (optional) : the list of module IDs (see RetrieveQuantityByID())
00251   - \c n (optional) : the number of modules in the category
00252 
00253   See also GetCategories() and HasComputeCategory().
00254 */
00255 PetscErrorCode CategoryGetModules
00256 (const char *cat,const char ***ms,AnalysisDataType **t,int **id,int *n)
00257 {
00258   categoryobject catg; PetscTruth flg; PetscErrorCode ierr;
00259   PetscFunctionBegin;
00260   ierr = GetCategory(cat,&catg,&flg); CHKERRQ(ierr);
00261   if (!flg) SETERRQ1(1,"Unknown category <%s>",cat);
00262   if (ms) *ms = catg->componentnames;
00263   if (t) *t = catg->types;
00264   if (n) *n = catg->ncomponents;
00265   //      if (id) *id = ids[i];
00266   PetscFunctionReturn(0);
00267 }
00268 
00269 /*
00270  * Stuff for category reporting
00271  */
00272 static int categoryreadout=-1;
00273 
00274 #undef __FUNCT__
00275 #define __FUNCT__ "GetFirstCategory"
00276 PetscErrorCode GetFirstCategory(const char **rname,PetscTruth *rfound)
00277 {
00278   PetscTruth found = PETSC_FALSE;
00279   PetscFunctionBegin;
00280   categoryreadout = 0;
00281   while (categoryreadout<ncategories 
00282          && categoryobjects[categoryreadout]->enabled!=CATCMP_ENABLE)
00283     categoryreadout++;
00284   if (categoryreadout<ncategories) {
00285     found = PETSC_TRUE;
00286     if (rname) *rname = categoryobjects[categoryreadout]->name;
00287   }
00288   *rfound = found;
00289   PetscFunctionReturn(0);
00290 }
00291 
00292 #undef __FUNCT__
00293 #define __FUNCT__ "GetNextCategory"
00294 PetscErrorCode GetNextCategory(const char **rname,PetscTruth *rfound)
00295 {
00296   PetscTruth found = PETSC_FALSE;
00297   PetscFunctionBegin;
00298   categoryreadout++;
00299   while (categoryreadout<ncategories 
00300          && categoryobjects[categoryreadout]->enabled!=CATCMP_ENABLE)
00301     categoryreadout++;
00302   if (categoryreadout<ncategories) {
00303     found = PETSC_TRUE;
00304     if (rname) *rname = categoryobjects[categoryreadout]->name;
00305   }
00306   *rfound = found;
00307   PetscFunctionReturn(0);
00308 }
00309 
00310 #undef __FUNCT__
00311 #define __FUNCT__ "CategoryEnableByName"
00312 /*! Mark a category as enabled/disabled. Values (CatCmpEnableMode):
00313   - 0 : enable
00314   - 1 : skip from loops
00315   - 2 : skip altogether
00316 */
00317 PetscErrorCode CategoryEnableByName(const char *cat,int mode)
00318 {
00319   int icat;
00320   PetscFunctionBegin;
00321   for (icat=0; icat<ncategories; icat++) {
00322     if (!strcmp(cat,categoryobjects[icat]->name)) {
00323       categoryobjects[icat]->enabled = mode;
00324     }
00325   }
00326   PetscFunctionReturn(0);
00327 }
00328 
00329 #undef __FUNCT__
00330 #define __FUNCT__ "DeclareCategoryOptionFunction"
00331 /*! This function allows the module developer to give the user
00332   commandline options for control of a module.
00333 
00334   See DeclareCategoryOptionFunction(),GetCategoryOptionFunction(),
00335   AnaModOptionsHandling() and section \ref optionsfile.
00336 */
00337 PetscErrorCode DeclareCategoryOptionFunction
00338   (const char *cat,PetscErrorCode(*f)(char*))
00339 {
00340   PetscTruth flg; categoryobject catg; PetscErrorCode ierr;
00341   PetscFunctionBegin;
00342   ierr = GetCategory(cat,&catg,&flg); CHKERRQ(ierr);
00343   if (flg) {
00344     catg->optionfunction = f;
00345   }
00346   PetscFunctionReturn(0);
00347 }
00348 
00349 #undef __FUNCT__
00350 #define __FUNCT__ "CategoryGetOptionFunction"
00351 /*! This function is called in AnaModOptionsHandling().
00352   There is probably no reason for the user ever to call it.
00353 
00354   See DeclareCategoryOptionFunction(),GetCategoryOptionFunction(),
00355   AnaModOptionsHandling() and section \ref optionsfile.
00356 */
00357 PetscErrorCode CategoryGetOptionFunction
00358 (const char *cat,PetscErrorCode(**f)(char*))
00359 {
00360   PetscTruth flg; categoryobject catg; PetscErrorCode ierr;
00361   PetscFunctionBegin;
00362   ierr = GetCategory(cat,&catg,&flg); CHKERRQ(ierr);
00363   if (flg) {
00364     *f = catg->optionfunction;
00365   } else *f = NULL;
00366   PetscFunctionReturn(0);
00367 }
00368