System Preprocessors
transform.c
Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include "petsc.h"
00005 #include "sysprotransform.h"
00006 #include "syspro_impl.h"
00007 
00008 struct SalsaTransformObject_ {
00009   int cookie;
00010   const char *name,*explanation;
00011   SalsaTransform transform;
00012   int n_options,alloc_options,*options; const char *option,**optionexplanation;
00013   int *options_marked; int active_option;
00014   int alloc_annotate_c; const char **annotate_c;
00015   int alloc_annotate_i,*annotate_i;
00016   int marked;
00017   PetscErrorCode(*suitabilityfunction)
00018     (NumericalProblem,void*,SuitabilityValue*);
00019   void *suitabilityctx;
00020 };
00021 
00022 #define TFINC 20
00023 
00024 /*! \page transform Preprocessor definition
00025 
00026   \section preprocessorclass Class definition
00027 
00028   A class of preprocessors (such as scaling, preconditioning) is defined
00029   using the function NewTransform().
00030 
00031   \section preprocessorindividual Individual preprocessor definition
00032 
00033   The individual preprocessors (left scaling, preprocessing by ILU)
00034   are defined in a function that is passed as the \c specific_setup
00035   argument to DeclarePreprocessor(). This function makes calls to 
00036   NewTransformObject(), TransformObjectIntAnnotate() et cetera.
00037   See for instance file \ref pc.c .
00038  */
00039 
00040 #undef __FUNCT__
00041 #define __FUNCT__ "NewTransform"
00042 /*! Define a new class of preprocessors, for instance scaling 
00043   or permutation.
00044 */
00045 PetscErrorCode NewTransform(const char *name,SalsaTransform *tf)
00046 {
00047   SalsaTransform snew; PetscErrorCode ierr;
00048   PetscFunctionBegin;
00049   ierr = PetscNew(struct SalsaTransform_,&snew); CHKERRQ(ierr);
00050   ierr = PetscMemzero(snew,sizeof(struct SalsaTransform_)); CHKERRQ(ierr);
00051   snew->name = strdup(name); snew->cookie = TRANSFORMCOOKIE;
00052 
00053   snew->alloc_objects = TFINC; snew->n_objects = 0;
00054   ierr = PetscMalloc(snew->alloc_objects*sizeof(SalsaTransformObject),&snew->transformobjects); CHKERRQ(ierr);
00055   ierr = PetscMemzero(snew->transformobjects,snew->alloc_objects*sizeof(SalsaTransformObject)); CHKERRQ(ierr);
00056   ierr = PetscMalloc(snew->alloc_objects*sizeof(int),&snew->aprioriselection); CHKERRQ(ierr);
00057   ierr = PetscMemzero(snew->aprioriselection,snew->alloc_objects*sizeof(int)); CHKERRQ(ierr);
00058 
00059   *tf = snew;
00060   PetscFunctionReturn(0);
00061 }
00062 
00063 PetscErrorCode DeregisterTransform(SalsaTransform tf)
00064 {
00065   int i; PetscErrorCode ierr;
00066   PetscFunctionBegin;
00067   CHECKVALIDTRANSFORM(tf);
00068   for (i=0; i<tf->n_objects; i++) {
00069     ierr = FreeTransformObject(tf->transformobjects[i]); CHKERRQ(ierr);
00070   }
00071   ierr = PetscFree(tf->transformobjects); CHKERRQ(ierr);
00072   ierr = PetscFree(tf->aprioriselection); CHKERRQ(ierr);
00073   if (tf->annotations_i) {ierr = PetscFree(tf->annotations_i); CHKERRQ(ierr);}
00074   if (tf->annotations_c) {ierr = PetscFree(tf->annotations_c); CHKERRQ(ierr);}
00075   ierr = PetscFree(tf); CHKERRQ(ierr);
00076   PetscFunctionReturn(0);
00077 }
00078 
00079 #undef __FUNCT__
00080 #define __FUNCT__ "TransformGetName"
00081 PetscErrorCode TransformGetName(SalsaTransform tf,const char **name)
00082 {
00083   PetscFunctionBegin;
00084   CHECKVALIDTRANSFORM(tf);
00085   *name = tf->name;
00086   PetscFunctionReturn(0);
00087 }
00088 
00089 #undef __FUNCT__
00090 #define __FUNCT__ "TransformGetObjects"
00091 PetscErrorCode TransformGetObjects
00092 (SalsaTransform tf,int *n,SalsaTransformObject **objs)
00093 {
00094   PetscFunctionBegin;
00095   CHECKVALIDTRANSFORM(tf);
00096   if (n) *n = tf->n_objects;
00097   if (objs) *objs = tf->transformobjects;
00098   PetscFunctionReturn(0);
00099 }
00100 
00101 #undef __FUNCT__
00102 #define __FUNCT__ "NewTransformObject"
00103 /*! Create a transform object specified by \c name 
00104    for the preprocessor class \c transform.
00105    The \c to parameter can be NULL if no further specifications
00106    of the object are needed, in which case this only registers the name.
00107 */
00108 PetscErrorCode NewTransformObject
00109 (const char *transform,const char *name,SalsaTransformObject *to)
00110 {
00111   SalsaTransform tf; SalsaTransformObject snew; PetscErrorCode ierr;
00112   PetscFunctionBegin;
00113   ierr = TransformGetByName(transform,&tf); CHKERRQ(ierr);
00114   ierr = PetscNew(struct SalsaTransformObject_,&snew); CHKERRQ(ierr);
00115   ierr = PetscMemzero(snew,sizeof(struct SalsaTransformObject_)); CHKERRQ(ierr);
00116   ierr = PetscStrallocpy(name,(char**)&(snew->name)); snew->transform = tf;
00117   snew->cookie = TRANSFORMOBJECTCOOKIE;
00118   if (tf->n_objects>=tf->alloc_objects)
00119     SETERRQ(PETSC_COMM_SELF,1,"Can not realloc transform objects");
00120   tf->transformobjects[tf->n_objects++] = snew;
00121   if (to) *to = snew;
00122   PetscFunctionReturn(0);
00123 }
00124 
00125 #undef __FUNCT__
00126 #define __FUNCT__ "FreeTransformObject"
00127 PetscErrorCode FreeTransformObject(SalsaTransformObject tf)
00128 {
00129   int iopt; PetscErrorCode ierr;
00130   CHECKVALIDTRANSFORMOBJECT(tf);
00131   PetscFunctionBegin;
00132   if (tf->options) {
00133     ierr = PetscFree(tf->options); CHKERRQ(ierr);
00134     ierr = PetscFree(tf->options_marked); CHKERRQ(ierr);
00135     for (iopt=0; iopt<tf->n_options; iopt++)
00136       free((char*)tf->optionexplanation[iopt]);
00137     ierr = PetscFree(tf->optionexplanation); CHKERRQ(ierr);
00138   }
00139   if (tf->annotate_i) {ierr = PetscFree(tf->annotate_i); CHKERRQ(ierr);}
00140   if (tf->annotate_c) {ierr = PetscFree(tf->annotate_c); CHKERRQ(ierr);}
00141   ierr = PetscFree(tf->name); CHKERRQ(ierr); //free(tf->name);
00142   ierr = PetscFree(tf); CHKERRQ(ierr);
00143   PetscFunctionReturn(0);
00144 }
00145 
00146 #undef __FUNCT__
00147 #define __FUNCT__ "TransformObjectGetName"
00148 PetscErrorCode TransformObjectGetName(SalsaTransformObject tf,const char **name)
00149 {
00150   PetscFunctionBegin;
00151   CHECKVALIDTRANSFORMOBJECT(tf);
00152   *name = tf->name;
00153   PetscFunctionReturn(0);
00154 }
00155 
00156 #undef __FUNCT__
00157 #define __FUNCT__ "TransformObjectSetExplanation"
00158 PetscErrorCode TransformObjectSetExplanation
00159 (SalsaTransformObject tf,const char *x)
00160 {
00161   PetscFunctionBegin;
00162   CHECKVALIDTRANSFORMOBJECT(tf);
00163   tf->explanation = x;
00164   PetscFunctionReturn(0);
00165 }
00166 
00167 /*! \page suit Suitability functions
00168 
00169   The general mechanism form choosing between algorithms is that of
00170   `suitability functions'. We associate with each specific preprocessor
00171   (for instance scaling/left) a function that returns either a fuzzy truth
00172   value (0--1) or `unknown' (-1). See TransformObjectSetSuitabilityFunction(),
00173   TransformObjectGetSuitabilityFunction(). See also \ref transform about 
00174   specific preprocessor construction.
00175 
00176   At the start of a preprocessor invocation,
00177   in PreprocessorSpecificSetup(), the suitability functions of all choices are 
00178   evaluated, and the choices are marked as unsuitable (if the evaluate
00179   is zero), or ranked otherwise.
00180 
00181   The only implemented suitability functions are for the linear problem;
00182   see \ref suitc.
00183  */
00184 
00185 #undef __FUNCT__
00186 #define __FUNCT__ "TransformObjectSetSuitabilityFunction"
00187 /*! Set the suitability function; see \ref suit.
00188 
00189   See also TransformObjectGetSuitabilityFunction().
00190 */
00191 PetscErrorCode TransformObjectSetSuitabilityFunction
00192 (SalsaTransformObject tf,void *sctx,
00193  PetscErrorCode(*f)(NumericalProblem,void*,SuitabilityValue*))
00194 {
00195   PetscFunctionBegin;
00196   CHECKVALIDTRANSFORMOBJECT(tf);
00197   tf->suitabilityfunction = f;
00198   tf->suitabilityctx = sctx;
00199   PetscFunctionReturn(0);
00200 }
00201 
00202 #undef __FUNCT__
00203 #define __FUNCT__ "TransformObjectGetSuitabilityFunction"
00204 /*! Retrieve the suitability function and context; see \ref suit. Both
00205   arguments can be null.
00206 
00207   See also TransformObjectSetSuitabilityFunction().
00208  */
00209 PetscErrorCode TransformObjectGetSuitabilityFunction
00210 (SalsaTransformObject tf,void **sctx,
00211  PetscErrorCode(**f)(NumericalProblem,void*,SuitabilityValue*))
00212 {
00213   PetscFunctionBegin;
00214   CHECKVALIDTRANSFORMOBJECT(tf);
00215   if (sctx) *sctx = tf->suitabilityctx;
00216   if (f) *f = tf->suitabilityfunction;
00217   PetscFunctionReturn(0);
00218 }
00219 
00220 #undef __FUNCT__
00221 #define __FUNCT__ "TransformObjectGetTransformName"
00222 PetscErrorCode TransformObjectGetTransformName(SalsaTransformObject tf,char **name)
00223 {
00224   PetscFunctionBegin;
00225   CHECKVALIDTRANSFORMOBJECT(tf);
00226   *name = tf->transform->name;
00227   PetscFunctionReturn(0);
00228 }
00229 
00230 #undef __FUNCT__
00231 #define __FUNCT__ "TransformObjectGetByName"
00232 PetscErrorCode TransformObjectGetByName
00233 (const char *trans,const char *name,SalsaTransformObject *tf)
00234 {
00235   SalsaTransform tt; int i; PetscErrorCode ierr;
00236   PetscFunctionBegin;
00237   ierr = TransformGetByName(trans,&tt); CHKERRQ(ierr);
00238   for (i=0; i<tt->n_objects; i++) {
00239     if (!strcmp(name,tt->transformobjects[i]->name)) {
00240       *tf = tt->transformobjects[i];
00241       CHECKVALIDTRANSFORMOBJECT(*tf);
00242       PetscFunctionReturn(0);
00243     }
00244   }
00245   SETERRQ2(PETSC_COMM_SELF,1,"Could not find transform <%s:%s>",trans,name);
00246   PetscFunctionReturn(0);
00247 }
00248 
00249 #undef __FUNCT__
00250 #define __FUNCT__ "TransformObjectsGetNames"
00251 /*!
00252   Get the names of all declared transformobjects. An array is allocated
00253   for the names, which needs to be PetscFree()'d.
00254 */
00255 PetscErrorCode TransformObjectsGetNames(SalsaTransform tf,const char ***names)
00256 {
00257   int i; const char **thenames; PetscErrorCode ierr;
00258   PetscFunctionBegin;
00259   CHECKVALIDTRANSFORM(tf);
00260   ierr = PetscMalloc(tf->n_objects*sizeof(char*),&thenames); CHKERRQ(ierr);
00261   for (i=0; i<tf->n_objects; i++)
00262     thenames[i] = tf->transformobjects[i]->name;
00263   *names = thenames;
00264   PetscFunctionReturn(0);
00265 }
00266 
00267 /*
00268  * Annotations
00269  */
00270 #undef __FUNCT__
00271 #define __FUNCT__ "SysProDefineCharAnnotation"
00272 /*! Define a character string annotation for a transform. The index of this
00273   annotation can be retrieved with TransformCharAnnotationGetIndex().
00274   The actual annotation can be found with TransformItemGetCharAnnotation().
00275 */
00276 PetscErrorCode SysProDefineCharAnnotation(const char *transform,const char *ann)
00277 {
00278   SalsaTransform tf; int loc; PetscErrorCode ierr;
00279   PetscFunctionBegin;
00280 
00281   ierr = TransformGetByName(transform,&tf); CHKERRQ(ierr);
00282 
00283   /*
00284    * Initial allocation of various arrays
00285    */
00286   if (tf->n_annotate_c==0) {
00287     /* names */
00288     ierr = PetscMalloc
00289       (TFINC*sizeof(char*),&(tf->annotations_c)); CHKERRQ(ierr);
00290     ierr = PetscMemzero
00291       (tf->annotations_c,TFINC*sizeof(char*)); CHKERRQ(ierr);
00292     loc = 0;
00293   } else if (tf->n_annotate_c==TFINC) {
00294     SETERRQ(PETSC_COMM_SELF,1,"Can not realloc annotations yet");
00295   } else {
00296     loc = tf->n_annotate_c;
00297   }
00298 
00299   /*
00300    * now setup this annotation
00301    */
00302   tf->annotations_c[loc] = strdup(ann);
00303 
00304   tf->n_annotate_c++;
00305   PetscFunctionReturn(0);
00306 }
00307 
00308 #undef __FUNCT__
00309 #define __FUNCT__ "TransformCharAnnotationGetIndex"
00310 PetscErrorCode TransformCharAnnotationGetIndex
00311 (SalsaTransform tf,const char *ann,int *idx,PetscBool *flg)
00312 {
00313   int i; PetscBool f; PetscErrorCode ierr;
00314   PetscFunctionBegin;
00315   CHECKVALIDTRANSFORM(tf);
00316   *idx = -1;
00317   for (i=0; i<tf->n_annotate_c; i++) {
00318     ierr = PetscStrcmp(ann,tf->annotations_c[i],&f); CHKERRQ(ierr);
00319     if (f) {
00320       *idx = i; if (flg) *flg = f; break;
00321     }
00322   }
00323   PetscFunctionReturn(0);
00324 }
00325 
00326 #undef __FUNCT__
00327 #define __FUNCT__ "SysProDefineIntAnnotation"
00328 /*! Define a integer string annotation for a transform. The index of this
00329   annotation can be retrieved with TransformIntAnnotationGetIndex().
00330   The actual annotation can be found with TransformItemGetIntAnnotation().
00331 */
00332 PetscErrorCode SysProDefineIntAnnotation(const char *transform,const char *ann)
00333 {
00334   SalsaTransform tf; int loc; PetscErrorCode ierr;
00335   PetscFunctionBegin;
00336   ierr = TransformGetByName(transform,&tf); CHKERRQ(ierr);
00337   /*
00338    * Initial allocation of various arrays
00339    */
00340   if (tf->n_annotate_i==0) {
00341     /* names */
00342     ierr = PetscMalloc
00343       (TFINC*sizeof(char*),&(tf->annotations_i)); CHKERRQ(ierr);
00344     ierr = PetscMemzero
00345       (tf->annotations_i,TFINC*sizeof(char*)); CHKERRQ(ierr);
00346     loc = 0;
00347   } else if (tf->n_annotate_i==TFINC) {
00348     SETERRQ(PETSC_COMM_SELF,1,"Can not realloc annotations yet");
00349   } else {
00350     loc = tf->n_annotate_i;
00351   }
00352 
00353   /*
00354    * now setup this annotation
00355    */
00356   tf->annotations_i[loc] = strdup(ann);
00357 
00358   tf->n_annotate_i++;
00359   PetscFunctionReturn(0);
00360 }
00361 
00362 #undef __FUNCT__
00363 #define __FUNCT__ "TransformIntAnnotationGetIndex"
00364 PetscErrorCode TransformIntAnnotationGetIndex
00365 (SalsaTransform tf,const char *ann,int *idx,PetscBool *flg)
00366 {
00367   int i; PetscBool f; PetscErrorCode ierr;
00368   PetscFunctionBegin;
00369   CHECKVALIDTRANSFORM(tf);
00370   *idx = -1;
00371   for (i=0; i<tf->n_annotate_i; i++) {
00372     ierr = PetscStrcmp(ann,tf->annotations_i[i],&f); CHKERRQ(ierr);
00373     if (f) {
00374       *idx = i; if (flg) *flg = f; break;
00375     }
00376   }
00377   PetscFunctionReturn(0);
00378 }
00379 
00380 #undef __FUNCT__
00381 #define __FUNCT__ "TransformObjectMark"
00382 PetscErrorCode TransformObjectMark(SalsaTransformObject tf)
00383 {
00384   int j;
00385   PetscFunctionBegin;
00386   CHECKVALIDTRANSFORMOBJECT(tf);
00387   for (j=0; j<tf->n_options; j++)
00388     tf->options_marked[j] = 1;
00389   tf->marked = 1;
00390   PetscFunctionReturn(0);
00391 }
00392 
00393 #undef __FUNCT__
00394 #define __FUNCT__ "TransformObjectUnmark"
00395 PetscErrorCode TransformObjectUnmark(SalsaTransformObject tf)
00396 {
00397   int j;
00398   PetscFunctionBegin;
00399   CHECKVALIDTRANSFORMOBJECT(tf);
00400   for (j=0; j<tf->n_options; j++)
00401     tf->options_marked[j] = 0;
00402   tf->marked = 0;
00403   PetscFunctionReturn(0);
00404 }
00405 
00406 #undef __FUNCT__
00407 #define __FUNCT__ "TransformObjectsMarkAll"
00408 PetscErrorCode TransformObjectsMarkAll(SalsaTransform tf)
00409 {
00410   int i; PetscErrorCode ierr;
00411   PetscFunctionBegin;
00412   CHECKVALIDTRANSFORM(tf);
00413   for (i=0; i<tf->n_objects; i++) {
00414     SalsaTransformObject to = tf->transformobjects[i];
00415     CHECKVALIDTRANSFORMOBJECT(to);
00416     ierr = TransformObjectMark(to); CHKERRQ(ierr);
00417   }
00418   PetscFunctionReturn(0);
00419 }
00420 
00421 #undef __FUNCT__
00422 #define __FUNCT__ "TransformObjectsUnmarkAll"
00423 PetscErrorCode TransformObjectsUnmarkAll(SalsaTransform tf)
00424 {
00425   int i; PetscErrorCode ierr;
00426   PetscFunctionBegin;
00427   CHECKVALIDTRANSFORM(tf);
00428   for (i=0; i<tf->n_objects; i++) {
00429     SalsaTransformObject to = tf->transformobjects[i];
00430     CHECKVALIDTRANSFORMOBJECT(to);
00431     ierr = TransformObjectUnmark(to); CHKERRQ(ierr);
00432   }
00433   PetscFunctionReturn(0);
00434 }
00435 
00436 #undef __FUNCT__
00437 #define __FUNCT__ "TransformObjectGetMark"
00438 PetscErrorCode TransformObjectGetMark(SalsaTransformObject tf,int *m)
00439 {
00440   PetscFunctionBegin;
00441   CHECKVALIDTRANSFORMOBJECT(tf);
00442   *m = tf->marked;
00443   PetscFunctionReturn(0);
00444 }
00445 
00446 #undef __FUNCT__
00447 #define __FUNCT__ "TransformGetNUnmarked"
00448 PetscErrorCode TransformGetNUnmarked(SalsaTransform tf,int *n)
00449 {
00450   int i;
00451   PetscFunctionBegin;
00452   CHECKVALIDTRANSFORM(tf);
00453   *n = 0;
00454   for (i=0; i<tf->n_objects; i++)
00455     if (!tf->transformobjects[i]->marked) (*n)++;
00456   PetscFunctionReturn(0);
00457 }
00458 
00459 #undef __FUNCT__
00460 #define __FUNCT__ "PreprocessorSaveAprioriSelection"
00461 PetscErrorCode PreprocessorSaveAprioriSelection(SystemPreprocessor pp)
00462 {
00463   SalsaTransform tf = pp->transform; int ipp;
00464   PetscFunctionBegin;
00465   for (ipp=0; ipp<tf->n_objects; ipp++) {
00466     SalsaTransformObject to = tf->transformobjects[ipp];
00467     CHECKVALIDTRANSFORMOBJECT(to);
00468     tf->aprioriselection[ipp] = to->marked;
00469   }
00470   PetscFunctionReturn(0);
00471 }
00472 
00473 #undef __FUNCT__
00474 #define __FUNCT__ "PreprocessorApplyAprioriSelection"
00475 PetscErrorCode PreprocessorApplyAprioriSelection(SystemPreprocessor pp)
00476 {
00477   SalsaTransform tf = pp->transform; int ipp;
00478   PetscFunctionBegin;
00479   for (ipp=0; ipp<tf->n_objects; ipp++) {
00480     tf->transformobjects[ipp]->marked = tf->aprioriselection[ipp];
00481   }
00482   PetscFunctionReturn(0);
00483 }
00484 
00485 #undef __FUNCT__
00486 #define __FUNCT__ "TransformObjectsUseOnly"
00487 /*! Mark a list of names as to be used.
00488 
00489   Cases:
00490   - \c "name1,name2,name3" : all other names are marked as not to be used
00491   - \c "not,name1,name2" : all names will be used, except for the
00492   ones listed
00493 */
00494 PetscErrorCode TransformObjectsUseOnly(SalsaTransform tf,const char *list)
00495 {
00496   char *c; PetscErrorCode ierr; PetscBool eliminate;
00497   PetscFunctionBegin;
00498   CHECKVALIDTRANSFORM(tf);
00499   c = strtok((char*)list,",");
00500   eliminate = (PetscBool)(c && (PetscBool)!strcmp(c,"not"));
00501   if (eliminate) {
00502     ierr = TransformObjectsUnmarkAll(tf); CHKERRQ(ierr);
00503     c = strtok(NULL,",");
00504   } else {
00505     ierr = TransformObjectsMarkAll(tf); CHKERRQ(ierr);
00506   }
00507   while (c) {
00508     SalsaTransformObject to;
00509     ierr = TransformObjectGetByName(tf->name,c,&to); CHKERRQ(ierr);
00510     if (eliminate) {
00511       ierr = TransformObjectMark(to); CHKERRQ(ierr);
00512     } else {
00513       ierr = TransformObjectUnmark(to); CHKERRQ(ierr);
00514     }
00515     c = strtok(NULL,",");
00516   }
00517   PetscFunctionReturn(0);
00518 }
00519 
00520 #undef __FUNCT__
00521 #define __FUNCT__ "TransformGetNextUnmarkedItem"
00522 /*! Find the next unmarked value; if \c old is NULL, the first
00523   first unmarked value is given, otherwise the first one after
00524   a match with \c old.
00525 */
00526 PetscErrorCode TransformGetNextUnmarkedItem
00527 (SalsaTransform tf,const char *old,SalsaTransformObject *snew,PetscBool *f)
00528 {
00529   int idx; PetscBool foundtheoldone,found;
00530   PetscFunctionBegin;
00531   CHECKVALIDTRANSFORM(tf);
00532   found = PETSC_FALSE;
00533   foundtheoldone = TRUTH(old==NULL);
00534   for (idx=0; idx<tf->n_objects; idx++) {
00535     SalsaTransformObject to = tf->transformobjects[idx];
00536     CHECKVALIDTRANSFORMOBJECT(to);
00537     if (!foundtheoldone) {
00538       /* skip iterations until we have a match with the old name;
00539          then we take the next iteration
00540       */
00541       foundtheoldone = (PetscBool)!strcmp(old,to->name);
00542       continue;
00543     }
00544     found = (PetscBool)(!to->marked);
00545     if (found) {
00546       *snew = to; 
00547       if (f) *f = PETSC_TRUE;
00548       PetscFunctionReturn(0);
00549     }
00550   }
00551   if (f) *f = found;
00552   else SETERRQ(PETSC_COMM_SELF,1,"Could not find, but no flag given to report");
00553   PetscFunctionReturn(0);
00554 }
00555 
00556 #define STRDUP(a) ( (a) ? strdup(a) : NULL)
00557 
00558 #undef __FUNCT__
00559 #define __FUNCT__ "TransformObjectDefineOption"
00560 PetscErrorCode TransformObjectDefineOption
00561 (SalsaTransformObject tf,const char *opt)
00562 {
00563   PetscFunctionBegin;
00564   CHECKVALIDTRANSFORMOBJECT(tf);
00565   tf->option = strdup(opt);
00566   PetscFunctionReturn(0);
00567 }
00568 
00569 #undef __FUNCT__
00570 #define __FUNCT__ "TransformObjectAddOption"
00571 PetscErrorCode TransformObjectAddOption(SalsaTransformObject tf,int v)
00572 {
00573   PetscErrorCode ierr;
00574   PetscFunctionBegin;
00575   CHECKVALIDTRANSFORMOBJECT(tf);
00576   if (!tf->options) {
00577     ierr = PetscMalloc(TFINC*sizeof(int),&tf->options); CHKERRQ(ierr);
00578     ierr = PetscMemzero(tf->options,TFINC*sizeof(int)); CHKERRQ(ierr);
00579     ierr = PetscMalloc(TFINC*sizeof(int),&(tf->options_marked)); CHKERRQ(ierr);
00580     ierr = PetscMemzero(tf->options_marked,TFINC*sizeof(int)); CHKERRQ(ierr);
00581     ierr = PetscMalloc(TFINC*sizeof(char*),&(tf->optionexplanation)); CHKERRQ(ierr);
00582     ierr = PetscMemzero(tf->optionexplanation,TFINC*sizeof(char*)); CHKERRQ(ierr);
00583     tf->n_options = 0; tf->alloc_options = TFINC;
00584   }
00585   if (tf->n_options>=tf->alloc_options)
00586     SETERRQ1(PETSC_COMM_SELF,1,"No space for further options in tranform %s",tf->name);
00587   tf->options[tf->n_options++] = v;
00588   PetscFunctionReturn(0);
00589 }
00590 
00591 #undef __FUNCT__
00592 #define __FUNCT__ "TransformObjectAddOptionExplanation"
00593 PetscErrorCode TransformObjectAddOptionExplanation
00594 (SalsaTransformObject tf,int opt,const char *ex)
00595 {
00596   int i;
00597   PetscFunctionBegin;
00598   CHECKVALIDTRANSFORMOBJECT(tf);
00599   for (i=0; i<tf->n_options; i++) {
00600     if (tf->options[i]==opt) {
00601       tf->optionexplanation[i] = strdup(ex);
00602       goto out;
00603     }
00604   }
00605  out:
00606   PetscFunctionReturn(0);
00607 }
00608 
00609 #undef __FUNCT__
00610 #define __FUNCT__ "TransformItemOptionsUseOnly"
00611 PetscErrorCode TransformItemOptionsUseOnly(SalsaTransformObject tf,const char *opt)
00612 {
00613   char *c; PetscErrorCode ierr;
00614   PetscFunctionBegin;
00615   CHECKVALIDTRANSFORMOBJECT(tf);
00616   c = strtok((char*)opt,",");
00617   tf->n_options = 0;
00618   while (c) {
00619     int cv;
00620     sscanf(c,"%d",&cv);
00621     ierr = TransformObjectAddOption(tf,cv); CHKERRQ(ierr);
00622     c = strtok(NULL,",");
00623   }
00624   PetscFunctionReturn(0);
00625 }
00626 
00627 #undef __FUNCT__
00628 #define __FUNCT__ "TransformItemGetFirstOption"
00629 PetscErrorCode TransformItemGetFirstOption
00630 (const char* tf,const char *it,int *v,PetscBool *f)
00631 {
00632   SalsaTransformObject to; PetscBool found,flg;
00633   int i; PetscErrorCode ierr;
00634 
00635   PetscFunctionBegin;
00636   ierr = TransformObjectGetByName(tf,it,&to); CHKERRQ(ierr);
00637   found = PETSC_FALSE; flg = PETSC_FALSE;
00638   for (i=0; i<to->n_options; i++) {
00639     if (!to->options_marked[i]) {
00640       flg = PETSC_TRUE;
00641       *v = to->options[i];
00642       goto out;
00643     }
00644   }
00645 
00646  out:
00647   if (f) *f = flg;
00648   PetscFunctionReturn(0);
00649 }
00650 
00651 #undef __FUNCT__
00652 #define __FUNCT__ "TransformItemGetNextOption"
00653 PetscErrorCode TransformItemGetNextOption
00654 (const char* tf,const char *it,int *v,PetscBool *f)
00655 {
00656   SalsaTransformObject to; PetscBool found,flg;
00657   int i; PetscErrorCode ierr;
00658 
00659   PetscFunctionBegin;
00660   ierr = TransformObjectGetByName(tf,it,&to); CHKERRQ(ierr);
00661   found = PETSC_FALSE; flg = PETSC_FALSE;
00662   for (i=0; i<to->n_options; i++) {
00663     if (found && !to->options_marked[i]) {
00664       flg = PETSC_TRUE;
00665       *v = to->options[i];
00666       goto out;
00667     }
00668     if (to->options[i]==*v) found = PETSC_TRUE;
00669  }
00670 
00671  out:
00672   if (f) *f = flg;
00673   PetscFunctionReturn(0);
00674 }
00675 
00676 #undef __FUNCT__
00677 #define __FUNCT__ "TransformItemOptionMark"
00678 PetscErrorCode TransformItemOptionMark(SalsaTransform tf,const char *it,int o)
00679 {
00680   SalsaTransformObject to; int i; PetscErrorCode ierr;
00681   PetscFunctionBegin;
00682   CHECKVALIDTRANSFORM(tf);
00683   ierr = TransformObjectGetByName(tf->name,it,&to); CHKERRQ(ierr);
00684   to->marked = 0;
00685   for (i=0; i<to->n_options; i++) 
00686     if (to->options[i]==o) to->options_marked[i] = 1;
00687 
00688   PetscFunctionReturn(0);
00689 }
00690 
00691 #undef __FUNCT__
00692 #define __FUNCT__ "TransformObjectCharAnnotate"
00693 PetscErrorCode TransformObjectCharAnnotate
00694 (SalsaTransformObject tf,const char *an,const char *v)
00695 {
00696   int idx; PetscBool f; PetscErrorCode ierr;
00697   PetscFunctionBegin;
00698   CHECKVALIDTRANSFORMOBJECT(tf);
00699   if (!tf->annotate_c) {
00700     ierr = PetscMalloc(TFINC*sizeof(char*),&tf->annotate_c); CHKERRQ(ierr);
00701     ierr = PetscMemzero(tf->annotate_c,TFINC*sizeof(char*)); CHKERRQ(ierr);
00702     tf->alloc_annotate_c = TFINC;
00703   }
00704   ierr = TransformCharAnnotationGetIndex
00705     (tf->transform,an,&idx,&f); CHKERRQ(ierr);
00706   if (!f) SETERRQ1(PETSC_COMM_SELF,1,"Could not find annotation %s",an);
00707   if (idx>=tf->alloc_annotate_c)
00708     SETERRQ1(PETSC_COMM_SELF,1,"Char annotate index too large: %d.",idx);
00709   tf->annotate_c[idx] = v;
00710   PetscFunctionReturn(0);
00711 }
00712 
00713 #undef __FUNCT__
00714 #define __FUNCT__ "TransformObjectIntAnnotate"
00715 PetscErrorCode TransformObjectIntAnnotate
00716 (SalsaTransformObject tf,const char *an,int v)
00717 {
00718   int idx; PetscBool f; PetscErrorCode ierr;
00719   PetscFunctionBegin;
00720   CHECKVALIDTRANSFORMOBJECT(tf);
00721   if (!tf->annotate_i) {
00722     ierr = PetscMalloc(TFINC*sizeof(int),&tf->annotate_i); CHKERRQ(ierr);
00723     ierr = PetscMemzero(tf->annotate_i,TFINC*sizeof(int)); CHKERRQ(ierr);
00724     tf->alloc_annotate_i = TFINC;
00725   }
00726   ierr = TransformIntAnnotationGetIndex
00727     (tf->transform,an,&idx,&f); CHKERRQ(ierr);
00728   if (!f) SETERRQ1(PETSC_COMM_SELF,1,"Could not find annotation %s",an);
00729   if (idx>=tf->alloc_annotate_i)
00730     SETERRQ1(PETSC_COMM_SELF,1,"Int annotate index too large: %d.",idx);
00731   tf->annotate_i[idx] = v;
00732   PetscFunctionReturn(0);
00733 }
00734 
00735 #undef __FUNCT__
00736 #define __FUNCT__ "TransformObjectGetIntAnnotation"
00737 PetscErrorCode TransformObjectGetIntAnnotation
00738 (SalsaTransformObject tf,const char *an,int *v,PetscBool *f)
00739 {
00740   SalsaTransform tt = tf->transform; int ian;
00741   PetscFunctionBegin;
00742   CHECKVALIDTRANSFORMOBJECT(tf);
00743   *f = PETSC_FALSE;
00744   for (ian=0; ian<tt->n_annotate_i; ian++) {
00745     if (!strcmp(tt->annotations_i[ian],an)) {
00746       *f = TRUTH(tf->annotate_i!=NULL);
00747       if (*f) *v = tf->annotate_i[ian];
00748       PetscFunctionReturn(0);
00749     }
00750   }
00751   PetscFunctionReturn(0);
00752 }
00753 
00754 #undef __FUNCT__
00755 #define __FUNCT__ "TransformReportTeXTable"
00756 PetscErrorCode TransformReportTeXTable(SalsaTransform tf,FILE *f)
00757 {
00758   int i,j;
00759   PetscFunctionBegin;
00760 
00761   for (i=0; i<tf->n_objects; i++) {
00762     SalsaTransformObject to = tf->transformobjects[i];
00763     fprintf(f,"%s&%s",to->name,to->explanation);
00764     if (to->n_options>0) {
00765       /*
00766       fprintf(f,"&%s&",to->optionexplanation);
00767       */
00768       for (j=0; j<to->n_options; j++) {
00769         fprintf(f,"%d,",to->options[j]);        
00770       }
00771     } else fprintf(f,"&&");
00772     fprintf(f,"\\\\\n");
00773   }
00774   PetscFunctionReturn(0);
00775 }
00776 
00777 #undef __FUNCT__
00778 #define __FUNCT__ "TransformReportEnabled"
00779 PetscErrorCode TransformReportEnabled(SalsaTransform tf,const char **rs)
00780 {
00781   const char *s,**names; int i; size_t l; PetscErrorCode ierr;
00782   PetscFunctionBegin;
00783 
00784   ierr = PetscMalloc(1000*sizeof(char),&s); CHKERRQ(ierr);
00785   ierr = PetscMemzero((char*)s,1000*sizeof(char)); CHKERRQ(ierr);
00786   ierr = TransformObjectsGetNames(tf,&names); CHKERRQ(ierr);
00787   for (i=0; i<tf->n_objects; i++) {
00788     int mark;
00789     ierr = TransformObjectGetMark(tf->transformobjects[i],&mark); CHKERRQ(ierr);
00790     if (!mark) {
00791       ierr = PetscStrlen(s,&l); CHKERRQ(ierr);
00792       if (l) {sprintf((char*)s+l," "); l++;} sprintf((char*)s+l,"%s",names[i]);
00793     }
00794   }
00795   ierr = PetscFree(names); CHKERRQ(ierr);
00796   *rs = s;
00797   PetscFunctionReturn(0);
00798 }
00799 
00800 #undef __FUNCT__
00801 #define __FUNCT__ "TransformItemDescribeShort"
00802 PetscErrorCode TransformItemDescribeShort(SalsaTransform tf,char *it,int opt,char **s)
00803 {
00804   SalsaTransformObject to; char *ss; size_t l; PetscErrorCode ierr;
00805   PetscFunctionBegin;
00806 
00807   ierr = TransformObjectGetByName(tf->name,it,&to); CHKERRQ(ierr);
00808   ierr = PetscMalloc(200*sizeof(char),&ss); CHKERRQ(ierr);
00809   sprintf(ss,"%s",to->name); CHKERRQ(ierr);
00810   ierr = PetscStrlen(ss,&l); CHKERRQ(ierr);
00811   if (to->n_options) {
00812     sprintf(ss+l,"(%d)",opt);
00813     ierr = PetscStrlen(ss,&l); CHKERRQ(ierr);
00814   }
00815   *s = ss;
00816   PetscFunctionReturn(0);
00817 }
00818 
00819 #undef __FUNCT__
00820 #define __FUNCT__ "TransformItemDescribeLong"
00821 PetscErrorCode TransformItemDescribeLong(SalsaTransform tf,char *it,int opt,char **s)
00822 {
00823   SalsaTransformObject to;
00824   char *ss; size_t l; PetscErrorCode ierr;
00825 
00826   PetscFunctionBegin;
00827   CHECKVALIDTRANSFORM(tf);
00828   ierr = TransformObjectGetByName(tf->name,it,&to); CHKERRQ(ierr);
00829   ierr = PetscMalloc(200*sizeof(char),&ss); CHKERRQ(ierr);
00830   sprintf(ss,"%s",to->explanation); CHKERRQ(ierr);
00831   ierr = PetscStrlen(ss,&l); CHKERRQ(ierr);
00832 #if 0
00833   if (to->options[idx]) {
00834     sprintf(ss+l,"; %s",tf->options[idx]);
00835     ierr = PetscStrlen(ss,&l); CHKERRQ(ierr);
00836   }
00837   if (tf->noptions[idx]) {
00838     ierr = TransformItemGetOptionIndex(tf,idx,opt,&odx); CHKERRQ(ierr);
00839     if (odx>=0)
00840       sprintf(ss+l," %s",tf->options_texts[idx][odx]);
00841     else
00842       sprintf(ss+l,"(%d)",opt);
00843     ierr = PetscStrlen(ss,&l); CHKERRQ(ierr);
00844   }
00845 #endif
00846   *s = ss;
00847   PetscFunctionReturn(0);
00848 }
00849 
00850 #undef __FUNCT__
00851 #define __FUNCT__ "TransformSetUserChoices"
00852 /*! Declare that the user has ordained which choice(s) to take for a 
00853   specific transform. The values of these choices are implicitly given
00854   by disabling some transforms.
00855 
00856   See also TransformGetUserChoices(), TransformObjectsUseOnly().
00857 */
00858 PetscErrorCode TransformSetUserChoices(SalsaTransform tf,PetscBool ch)
00859 {
00860   PetscFunctionBegin;
00861   CHECKVALIDTRANSFORM(tf);
00862   tf->userchoices = ch;
00863   PetscFunctionReturn(0);
00864 }
00865 
00866 #undef __FUNCT__
00867 #define __FUNCT__ "TransformGetUserChoices"
00868 /*! Query whether the user has ordained which choice(s) to take for a 
00869   specific transform. The values of these choices are implicitly given
00870   by disabling some transforms.
00871 
00872   See also TransformSetUserChoices(), TransformObjectsUseOnly(). 
00873 */
00874 PetscErrorCode TransformGetUserChoices(SalsaTransform tf,PetscBool *ch)
00875 {
00876   PetscFunctionBegin;
00877   CHECKVALIDTRANSFORM(tf);
00878   *ch = tf->userchoices;
00879   PetscFunctionReturn(0);
00880 }
00881 
00882 #undef __FUNCT__
00883 #define __FUNCT__ "SetSuitabilityContextTester"
00884 PetscErrorCode SetSuitabilityContextTester(SalsaTransform tf,PetscErrorCode(*f)(void*))
00885 {
00886   PetscFunctionBegin;
00887   CHECKVALIDTRANSFORM(tf);
00888   tf->suitabilityctxtester = f;
00889   PetscFunctionReturn(0);
00890 }
00891 
00892 #undef __FUNCT__
00893 #define __FUNCT__ "TestSuitabilityContext"
00894 PetscErrorCode TestSuitabilityContext(SalsaTransform tf,void *ctx)
00895 {
00896   PetscErrorCode ierr;
00897   PetscFunctionBegin;
00898   CHECKVALIDTRANSFORM0(tf);
00899   if (tf->suitabilityctxtester) {
00900     ierr = (tf->suitabilityctxtester)(ctx); CHKERRQ(ierr);
00901   }
00902   PetscFunctionReturn(0);
00903 }
00904 
00905 #undef __FUNCT__
00906 #define __FUNCT__ "SalsaTransformIntegrityTest"
00907 PetscErrorCode SalsaTransformIntegrityTest(SalsaTransform tf)
00908 {
00909   int i; PetscErrorCode ierr;
00910   PetscFunctionBegin;
00911   if (!tf || !tf->suitabilityctxtester) PetscFunctionReturn(0);
00912   for (i=0; i<tf->n_objects; i++) {
00913     SalsaTransformObject to = tf->transformobjects[i]; void *sctx;
00914     ierr = TransformObjectGetSuitabilityFunction
00915       (to,&sctx,PETSC_NULL); CHKERRQ(ierr);
00916     if (sctx) {
00917       ierr = TestSuitabilityContext(tf,sctx); CHKERRQ(ierr);
00918     }
00919   }
00920   PetscFunctionReturn(0);
00921 }