SALSA Analysis Modules
|
00001 /*! \defgroup categories Files with defined categories */ 00002 /*! \defgroup functions User-accessible functions */ 00003 /*! \defgroup implementation Functions only of use to the implementation */ 00004 00005 /*! \file module_functions.c \ingroup functions \anchor modules 00006 \brief User functions for accessing the analysis modules 00007 00008 Analysis modules need to be defined with RegisterModule(), after which 00009 they can be invoked with ComputeQuantity(). See also HasQuantity(). 00010 The functions AnaModRegisterStandardModules() installs all standard 00011 available modules. 00012 00013 There are utility functions for querying the existence of modules: 00014 GetCategories(), CategoryGetModules(), 00015 HasComputeCategory(), HasComputeModule(). 00016 00017 Utility functions: QuantityAsString(), GetDataType(), GetDataID(), 00018 GetCategoryIndex(), GetModuleIndex(). 00019 */ 00020 00021 /*! \mainpage AnaMod : an Analysis Modules library 00022 \section Introduction 00023 00024 This is a library of modules that can compute various properties of 00025 a matrix. The code heavily uses the Petsc library, and the matrix has to 00026 be stored in Petsc format. 00027 00028 Modules are divided into several categories, each defined in its own file. 00029 Typical categories are for structural information, normlike properties, 00030 spectral estimate. A number of modules have been supplied, but because of 00031 the modular setup, it is easy to add new modules. 00032 00033 This library was written for use in the Salsa project 00034 (http://icl.cs.utk.edu/salsa/), but can be 00035 used independently of it. If the Salsa NMD library 00036 (http://icl.cs.utk.edu/salsa/software/index.html) is present (see the 00037 installation instructions), its data types are used. 00038 00039 \subpage installation 00040 00041 \subpage usage 00042 00043 \subpage list 00044 00045 \subpage customization 00046 00047 \subpage getall 00048 00049 \ref tracing 00050 00051 \author Victor Eijkhout 00052 \version 1.91 00053 \date unreleased 00054 00055 Change log: 00056 - 2.0 : internals revamped, bug fixes in simple:diagonal-dominance 00057 - 1.91 : spectrum modules with ";re" and ";im" have been renamed 00058 to "-re" and "-im" for MySQL sake. 00059 - 1.9 : fixed memory leak in dummy row computation 00060 - 1.8.a : added the stats.c file 00061 - 1.8 : much code cleanup; unit tests to ensure proper operation 00062 - 1.7 : handling of arrays is now completely changed. most routines 00063 have acquired an explicit array length parameter 00064 - 1.6 : handling of the location of slepc and such. Make sure to check 00065 the Make.inc.example file 00066 - 1.5 : 00067 - module-specific options 00068 - \c -anamod_force now has underscore for consistency 00069 - several spectrum imaginary parts were miscomputed 00070 - added SLEPC computation of spectrum 00071 - 1.4 : 00072 - improved trace mode; incompatible change in the prototype 00073 of the trace function 00074 - removed a11 module 00075 - 1.3 : 00076 - trace mode added (see \ref tracing) 00077 - renamed header files: module_functions.h -> anamod.h , 00078 module_types.h -> anamodtypes.h , nmdmodules.h -> anamodsalsamodules.h , 00079 module_utils.h -> anamodutils.h 00080 - 1.2 : 00081 - added runtime options: forced computation of single-processor 00082 modules in parallel context, of expensive modules 00083 - bug fix of aux:a11. 00084 - compatibility with gcc4 (ignoring 'const' used to be a warning, 00085 it's now an error) 00086 - 1.1 : correct handling of parallelism 00087 */ 00088 00089 /*! \page installation Installation and compiling programs 00090 00091 \section Installation 00092 00093 See the README file. The main thing is that you need to have Petsc installed. 00094 00095 \section compilation Compilation of user programs 00096 00097 The easiest way to compile a program that uses the Salsa Analysis Modules 00098 is to have these includes in your makefile: 00099 \verbatim 00100 include $(PETSC_DIR)/bmake/common/variables 00101 include $(SALSA_MODULES_DIR)/Make.inc 00102 \endverbatim 00103 00104 The following flags for your C compiler are 00105 - line 1: Petsc option 00106 - line 2: Analysis Modules options 00107 - line 3: (optionally) options for using the NMD library; HAVE_NMD_DEFINE 00108 has to be "-DHAVE_NMD" if the library is present 00109 \verbatim 00110 CFLAGS = \ 00111 $(PETSC_INCLUDE) $(COPTFLAGS) \ 00112 -I$(SALSA_MODULES_DIR) \ 00113 $(HAVE_NMD_DEFINE) -I$(LIBNMD_INCLUDE_DIR) -I$(LIBXMLSC_INCLUDE_DIR) 00114 \endverbatim 00115 00116 Your program needs to include the following header files: 00117 \verbatim 00118 #include "anamod.h" 00119 #include "anamodsalsamodules.h" 00120 \endverbatim 00121 00122 The following link line brings together all the needed libraries 00123 (add libnmd if required) 00124 \verbatim 00125 yourprog : 00126 $(CLINKER) -o yourprog yourprog.o \ 00127 -L$(SALSA_MODULES_LIB_DIR) -lsalsamodules -lothermodules \ 00128 $(PETSC_LIB) 00129 \endverbatim 00130 */ 00131 00132 /*! \page usage Use of the analysis modules 00133 00134 \section init Library Initialization 00135 00136 There are calls AnaModInitialize() and AnaModFinalize() which do 00137 global allocation. These are necessary. 00138 00139 \section registration Category registration 00140 00141 Every category needs to be registered before use with a call 00142 00143 Register<Category>Modules(); 00144 00145 where the available categores are \ref icmk, \ref iprs, \ref jpl, 00146 \ref normal, \ref simple, 00147 \ref spectrum, \ref structure, \ref variance. 00148 The functions AnaModRegisterStandardModules() installs all standard 00149 available modules. 00150 00151 \section compute Quantity computation 00152 00153 After registring a category, its elements can be computed as 00154 00155 PetscErrorCode ComputeQuantity(char *cat,char *cmp,Mat A,AnalysisItem *res,PetscBool *success); 00156 00157 with 00158 -# the name of the category 00159 -# the name of the element 00160 -# the matrix 00161 -# the result 00162 -# a success indicator 00163 00164 For the main user functions, see \ref modules "the module functions file" 00165 00166 Commandline options are discussed in section \ref options. 00167 00168 \section types Datatypes 00169 00170 The \c AnalysisDataType type is an integer. To get a printable name 00171 of the datatype, use AnaModGetTypeName() or AnaModGetTypeMySQLName(). 00172 */ 00173 00174 /*! \page list List of the available modules 00175 00176 \subpage icmk 00177 00178 \subpage iprs 00179 00180 \subpage jpl 00181 00182 \subpage normal 00183 00184 \subpage simple 00185 00186 \subpage spectrum 00187 00188 \subpage structure 00189 00190 \subpage variance 00191 */ 00192 00193 /*! \page customization Customization 00194 00195 While this library comes with a number of categories supplied, you can 00196 write your own category, taking any of the given ones as example. 00197 00198 Each analysis module has to have the following prototype: 00199 \verbatim 00200 static PetscErrorCode MyModule(Mat A,AnalysisItem *rv,PetscBool *flg) 00201 \endverbatim 00202 where 00203 - \c A is the input matrix 00204 - \c rv is the return value 00205 - \c flg is true if the quantity was succesfully computed, false otherwise 00206 00207 The module return code should be 0 for success, anything else for 00208 (catastrophic) failure. A simple failure (or refusal) to compute should 00209 be indicated through the \c flg variable. 00210 00211 The modules (including the return type of their computed quantities) 00212 are declared to the system by calling routine 00213 \verbatim 00214 PetscErrorCode RegisterMyModules() 00215 { 00216 PetscErrorCode ierr; 00217 PetscFunctionBegin; 00218 00219 ierr = RegisterModule 00220 ("mycategory","mymodule",THERESULTTYPE,&MyModule); CHKERRQ(ierr); 00221 .... 00222 \endverbatim 00223 or you can make the invidual calls to RegisterModule(). 00224 See \ref types and \ref arraytypes. 00225 */ 00226 00227 /*! \page arraytypes Array type handling 00228 00229 The actual types are listed in \ref types ; here are some semantic issues 00230 pertaining to array types. 00231 00232 The uniform calling structure of the modules allows only one parameter 00233 to be returned. This is a problem only for array types: we want both the 00234 array data and the length of the array. Hence we adopt the convention that 00235 every array is longer by one element than necessary, and the zero element 00236 contains the length of the array proper. That is, to store 5 elements, 00237 6 elements are allocated, and the zero element contains the number '5'. 00238 00239 If, in this documentation, we refer to location array[i], we will 00240 take this to mean location `i' after the size element. Zero-based 00241 indexing is used. 00242 */ 00243 00244 /*! \page attached Attached quantities in Petsc 00245 00246 Petsc has a mechanism where quantities can be attached to objects. 00247 For instance, integers can be attached and queried with 00248 PetscObjectComposedDataSetInt() and PetscObjectComposedDataGetInt(). 00249 Such data is attached together with the current state of the object, 00250 which means that it will be properly invalidated if the object is 00251 altered. 00252 00253 This composition mechanism is used in this analysis modules package. 00254 There are many quantities (such as the norms of the symmetric and 00255 anti-symmetric part of the matrix) that can be computed together at 00256 practically the same cost as either one alone. Thus, when one is requested 00257 by calling ComputeQuantity(), the other one will be compute as well, 00258 and attached to the matrix object. A call to ComputeQuantity() 00259 for this second quantity will then just return the attached number, 00260 and not be computed separately. 00261 00262 The routine HasQuantity() can query which quantities are already attached. 00263 00264 As a result of the use of attached quantities, benchmarking the AnaMod 00265 modules is a bit tricky. You can forced computation of the requested 00266 quantities by calling PetscObjectIncreaseState() on the matrix object 00267 after each call to ComputeQuantity(). 00268 */ 00269 #include <stdlib.h> 00270 #include <string.h> 00271 #include "anamod.h" 00272 #include "anamodsalsamodules.h" 00273 00274 static struct{int id; const char *name,*mysqlname;} anamodtypenames[5]; 00275 static int nAnaModTypeNames; 00276 static int AnaModIsInitialized = 0; 00277 00278 int ncategories=0; 00279 categoryobject *categoryobjects = NULL; 00280 00281 #undef __FUNCT__ 00282 #define __FUNCT__ "AnaModInitialize" 00283 /*! Initializatin for AnaMod. See also AnaModFinalize() */ 00284 PetscErrorCode AnaModInitialize() 00285 { 00286 PetscErrorCode ierr; 00287 00288 PetscFunctionBegin; 00289 ierr = AllocCategoryObjects(); CHKERRQ(ierr); 00290 00291 anamodtypenames[0].id = NMDString; 00292 anamodtypenames[0].name="string"; 00293 anamodtypenames[0].mysqlname="VARCHAR(256)"; 00294 00295 anamodtypenames[1].id = NMDInt; 00296 anamodtypenames[1].name="int"; 00297 anamodtypenames[1].mysqlname="INTEGER"; 00298 00299 anamodtypenames[2].id = NMDReal; 00300 anamodtypenames[2].name="real"; 00301 anamodtypenames[2].mysqlname="DOUBLE"; 00302 00303 anamodtypenames[3].id = NMDIntarray; 00304 anamodtypenames[3].name="intarray"; 00305 anamodtypenames[3].mysqlname="VARCHAR(1024)"; 00306 00307 anamodtypenames[4].id = NMDRealarray; 00308 anamodtypenames[4].name="realarray"; 00309 anamodtypenames[4].mysqlname="VARCHAR(1024)"; 00310 00311 AnaModIsInitialized = 1; nAnaModTypeNames = 5; 00312 PetscFunctionReturn(0); 00313 } 00314 00315 #undef __FUNCT__ 00316 #define __FUNCT__ "AnaModFinalize" 00317 /*! Finalization for AnaMod. See also AnaModInitialize() */ 00318 PetscErrorCode AnaModFinalize() 00319 { 00320 PetscErrorCode ierr; 00321 PetscFunctionBegin; 00322 ierr = FreeCategoryObjects(); CHKERRQ(ierr); 00323 PetscFunctionReturn(0); 00324 } 00325 00326 #undef __FUNCT__ 00327 #define __FUNCT__ "AnaModGetTypeName" 00328 PetscErrorCode AnaModGetTypeName(int id,const char **name) 00329 { 00330 int i; 00331 PetscFunctionBegin; 00332 for (i=0; i<nAnaModTypeNames; i++) { 00333 if (id==anamodtypenames[i].id) { 00334 *name = (char*)anamodtypenames[i].name; goto exit; 00335 } 00336 } 00337 SETERRQ1(MPI_COMM_WORLD,1,"Unknown AnaMod datatype %d",id); 00338 exit: 00339 PetscFunctionReturn(0); 00340 } 00341 00342 #undef __FUNCT__ 00343 #define __FUNCT__ "AnaModGetTypeMySQLName" 00344 PetscErrorCode AnaModGetTypeMySQLName(int id,const char **name) 00345 { 00346 int i; 00347 PetscFunctionBegin; 00348 if (AnaModIsInitialized<1) 00349 SETERRQ(MPI_COMM_WORLD,1,"AnaMod has not been not formally initialized.\nInsert a call to AnaModInitialize() in your code"); 00350 for (i=0; i<nAnaModTypeNames; i++) { 00351 if (id==anamodtypenames[i].id) { 00352 *name = (char*)anamodtypenames[i].mysqlname; goto exit; 00353 } 00354 } 00355 SETERRQ1(MPI_COMM_WORLD,1,"Unknown AnaMod datatype %d",id); 00356 exit: 00357 PetscFunctionReturn(0); 00358 } 00359 00360 #undef __FUNCT__ 00361 #define __FUNCT__ "RegisterModule" 00362 /*! 00363 Register a new computational module 00364 00365 This adds a computational routine (the \c f argument) into the modules 00366 database under the given category (\c cat) and module (\c cmp) label. 00367 If the category does not exist yet, it is created. 00368 00369 The available types are defined in \ref types "anamodtypes.h" 00370 00371 If the routine is NULL, only the category and component are created. 00372 00373 Routine prototype: 00374 - problem (input) 00375 - item (output) 00376 - array length (output) 00377 - success (output) 00378 00379 See also HasComputeModule(), ComputeQuantity(). 00380 */ 00381 PetscErrorCode RegisterModule 00382 (const char *cat,const char *cmp,AnalysisDataType type, 00383 PetscErrorCode(*f)(AnaModNumericalProblem,AnalysisItem*,int*,PetscBool*)) 00384 { 00385 int id; PetscErrorCode ierr; 00386 PetscFunctionBegin; 00387 00388 if (!AnaModIsInitialized) 00389 SETERRQ(MPI_COMM_WORLD,1,"AnaMod not initialized: insert call to AnaModInitialize()\n"); 00390 /* 00391 * Check for illegal names 00392 */ 00393 if (strchr(cat,':')) SETERRQ(MPI_COMM_WORLD,1,"Illegal colon in category name"); 00394 if (strchr(cmp,':')) SETERRQ(MPI_COMM_WORLD,1,"Illegal colon in component name"); 00395 00396 #if defined(ANAMODDEBUG) 00397 printf("Defining module <%s:%s>\n",cat,cmp); 00398 #endif 00399 ierr = PetscObjectComposedDataRegister(&id); CHKERRQ(ierr); 00400 ierr = CategoryComponentSetModule(cat,cmp,type,id,f); CHKERRQ(ierr); 00401 00402 PetscFunctionReturn(0); 00403 } 00404 00405 #undef __FUNCT__ 00406 #define __FUNCT__ "DeRegisterCategory" 00407 /*! Deallocate the storage for a particular category of analysis modules. 00408 No longer needed. */ 00409 PetscErrorCode DeRegisterCategory(const char *cat) 00410 { 00411 /* categoryobject catg; */ 00412 /* PetscBool flg; PetscErrorCode ierr; */ 00413 PetscFunctionBegin; 00414 00415 printf("Please remove use of legacy function DeRegisterCategory\n"); 00416 /* ierr = GetCategory(cat,&catg,&flg); CHKERRQ(ierr); */ 00417 /* if (!flg) SETERRQ1(MPI_COMM_WORLD,1,"Invalid category <%s>",cat); */ 00418 /* ierr = DestroyCategoryObject(catg); CHKERRQ(ierr); */ 00419 PetscFunctionReturn(0); 00420 } 00421 00422 #undef __FUNCT__ 00423 #define __FUNCT__ "DeregisterModules" 00424 /*! This function is no longer needed */ 00425 PetscErrorCode DeregisterModules() 00426 { 00427 /* int icat,ncat; const char **cat; */ 00428 /* PetscErrorCode ierr; */ 00429 PetscFunctionBegin; 00430 printf("Please remove use of legacy function DeRegisterModules\n"); 00431 /* ierr = GetCategories(&ncat,&cat); CHKERRQ(ierr); */ 00432 /* for (icat=0; icat<ncat; icat++) { */ 00433 /* ierr = DeRegisterCategory(cat[icat]); CHKERRQ(ierr); */ 00434 /* } */ 00435 PetscFunctionReturn(0); 00436 } 00437 00438 /*! \page getall Bulk computation 00439 After the modules have been installed, the typical user will only 00440 use ComputeQuantity(). However, for purposes of reporting and such 00441 it may be necessary to query systematicaly the available modules. 00442 This can be done with GetCategories() and CategoryGetModules(). 00443 00444 Related: HasComputeCategory(), HasComputeModule(). 00445 00446 Auxiliary routines: GetCategoryIndex(), GetModuleIndex(). 00447 */ 00448 #undef __FUNCT__ 00449 #define __FUNCT__ "HasComputeCategory" 00450 /*! Query whether a specified category has been declared. */ 00451 PetscErrorCode HasComputeCategory(const char *cat,PetscBool *f) 00452 { 00453 PetscErrorCode ierr; 00454 PetscFunctionBegin; 00455 ierr = GetCategory(cat,PETSC_NULL,f); CHKERRQ(ierr); 00456 PetscFunctionReturn(0); 00457 } 00458 00459 #undef __FUNCT__ 00460 #define __FUNCT__ "HasComputeModule" 00461 /*! 00462 Query whether a specified module exists inside a specified category. 00463 The category need not itself have been declared. 00464 */ 00465 PetscErrorCode HasComputeModule(const char *cat,const char *cmp,PetscBool *f) 00466 { 00467 categoryobject catg; PetscErrorCode ierr; 00468 PetscFunctionBegin; 00469 ierr = GetCategory(cat,&catg,f); CHKERRQ(ierr); 00470 if (*f) { 00471 ierr = CategoryGetComponent(catg,cmp,PETSC_NULL,f); CHKERRQ(ierr); 00472 } 00473 PetscFunctionReturn(0); 00474 } 00475 00476 #define MODE_RETRIEVE 1 00477 #define MODE_COMPUTE 0 00478 #undef __FUNCT__ 00479 #define __FUNCT__ "ComputeOrRetrieveQuantity" 00480 static PetscErrorCode ComputeOrRetrieveQuantity 00481 (AnaModNumericalProblem prob,const char *cat,const char *cmp, 00482 AnalysisItem *res,int *rreslen,PetscBool *success,int mode) 00483 { 00484 categoryobject catg; componentobject cmpt; PetscBool flg,trace; 00485 int reslen; PetscErrorCode ierr; 00486 00487 PetscFunctionBegin; 00488 ierr = AnaModHasTrace(&trace); CHKERRQ(ierr); 00489 00490 /* 00491 * Get the module and compute 00492 */ 00493 ierr = GetCategory(cat,&catg,&flg); CHKERRQ(ierr); 00494 if (!flg) SETERRQ1(MPI_COMM_WORLD,1,"Could not find category <%s>",cat); 00495 ierr = CategoryGetComponent(catg,cmp,&cmpt,&flg); CHKERRQ(ierr); 00496 if (!flg) SETERRQ1(MPI_COMM_WORLD,1,"Could not find component <%s>",cmp); 00497 if (mode==MODE_COMPUTE) { 00498 ierr = ComponentCompute(cmpt,prob,res,&reslen,&flg); CHKERRQ(ierr); 00499 } else if (mode==MODE_RETRIEVE) { 00500 ierr = ComponentRetrieve(cmpt,prob,res,&reslen,&flg); CHKERRQ(ierr); 00501 } else SETERRQ(MPI_COMM_WORLD,1,"Invalid mode"); 00502 00503 if (rreslen) *rreslen = reslen; 00504 if (success) *success = flg; 00505 00506 /* 00507 * Tracing 00508 */ 00509 if (trace) { 00510 if (flg) { 00511 char *string; PetscBool trace_arrays; AnalysisDataType t; 00512 00513 ierr = ComponentGetType(cmpt,&t); CHKERRQ(ierr); 00514 ierr = AnaModTraceArrays(&trace_arrays); CHKERRQ(ierr); 00515 if (t<ANALYSISINTARRAY || trace_arrays) { 00516 ierr = QuantityAsString(res,t,(const char**)&string); CHKERRQ(ierr); 00517 ierr = AnaModTraceMessage 00518 ("Anamod computed <%s:%s> = <%s>\n",cat,cmp,string); CHKERRQ(ierr); 00519 ierr = PetscFree(string); CHKERRQ(ierr); 00520 } 00521 } else { 00522 ierr = AnaModTraceMessage 00523 ("Anamod failed to compute <%s:%s>\n",cat,cmp); CHKERRQ(ierr); 00524 } 00525 } 00526 00527 PetscFunctionReturn(0); 00528 } 00529 00530 #undef __FUNCT__ 00531 #define __FUNCT__ "ComputeQuantity" 00532 /*! 00533 Compute a computational module from a certain category. 00534 00535 Argument: 00536 -# the name of the category (see GetCategories()) 00537 -# the name of the module (see CategoryGetModules()) 00538 -# the matrix 00539 -# a pointer to the result. This is given as \c "(AnalysisItem*)&res" ; 00540 see \ref types for the definition of the AnalysisItem data type 00541 -# the length of the result if the result is an array. This 00542 argument can be NULL. 00543 -# a success indicator. Failure can have obvious causes, 00544 such as breakdown of an internal routine, but the routine can also 00545 refuse to compute a quantity if doing so would be too expensive (see 00546 an example in the \ref normal category). 00547 00548 A call to this routine need not 00549 involve actual computation: the requested quantity can already be attached 00550 to the matrix object (see \ref attached "attached quantities" for details). 00551 This mechanism is used in all the standard modules that come with the 00552 AnaMod package. 00553 00554 The workings of this function can be traced by specifying a trace function; 00555 see \ref tracing. 00556 */ 00557 PetscErrorCode ComputeQuantity 00558 (AnaModNumericalProblem prob,const char *cat,const char *cmp, 00559 AnalysisItem *res,int *rreslen,PetscBool *success) 00560 { 00561 PetscErrorCode ierr; 00562 PetscFunctionBegin; 00563 if (!AnaModIsInitialized) 00564 SETERRQ(MPI_COMM_WORLD,1,"AnaMod not initialized: insert call to AnaModInitialize()\n"); 00565 ierr = ComputeOrRetrieveQuantity 00566 (prob,cat,cmp,res,rreslen,success,MODE_COMPUTE); CHKERRQ(ierr); 00567 PetscFunctionReturn(0); 00568 } 00569 00570 #undef __FUNCT__ 00571 #define __FUNCT__ "RetrieveQuantity" 00572 /*! Retrieve an attached quantity. 00573 Note that this does not report the length of arrays; you have to 00574 know under which name this is stored. 00575 */ 00576 PetscErrorCode RetrieveQuantity 00577 (AnaModNumericalProblem prob,const char *cat,const char *cmp, 00578 AnalysisItem *res,int *rreslen,PetscBool *success) 00579 { 00580 PetscErrorCode ierr; 00581 PetscFunctionBegin; 00582 ierr = ComputeOrRetrieveQuantity 00583 (prob,cat,cmp,res,rreslen,success,MODE_RETRIEVE); CHKERRQ(ierr); 00584 PetscFunctionReturn(0); 00585 } 00586 00587 #undef __FUNCT__ 00588 #define __FUNCT__ "GetDataID" 00589 PetscErrorCode GetDataID(const char *cat,const char *cmp,int *id,PetscBool *f) 00590 { 00591 categoryobject catg; componentobject cmpt; PetscBool flg; 00592 PetscErrorCode ierr; 00593 PetscFunctionBegin; 00594 ierr = GetCategory(cat,&catg,&flg); CHKERRQ(ierr); 00595 if (!flg) { 00596 if (!f) SETERRQ(MPI_COMM_WORLD,1,"Could not find cat/cmp, but no flag to report this"); 00597 *f = PETSC_FALSE; PetscFunctionReturn(0); 00598 } 00599 ierr = CategoryGetComponent(catg,cmp,&cmpt,&flg); CHKERRQ(ierr); 00600 if (!flg) { 00601 if (!f) SETERRQ(MPI_COMM_WORLD,1,"Could not find cat/cmp, but no flag to report this"); 00602 *f = PETSC_FALSE; PetscFunctionReturn(0); 00603 } 00604 ierr = ComponentGetId(cmpt,id); CHKERRQ(ierr); 00605 if (f) *f = PETSC_TRUE; 00606 PetscFunctionReturn(0); 00607 } 00608 00609 #undef __FUNCT__ 00610 #define __FUNCT__ "GetDataType" 00611 PetscErrorCode GetDataType 00612 (const char *cat,const char *cmp,AnalysisDataType *t,PetscBool *f) 00613 { 00614 categoryobject catg; componentobject cmpt; PetscBool flg; 00615 PetscErrorCode ierr; 00616 PetscFunctionBegin; 00617 ierr = GetCategory(cat,&catg,&flg); CHKERRQ(ierr); 00618 if (!flg) { 00619 if (!f) SETERRQ(MPI_COMM_WORLD,1,"Could not find cat/cmp, but no flag to report this"); 00620 *f = PETSC_FALSE; PetscFunctionReturn(0); 00621 } 00622 ierr = CategoryGetComponent(catg,cmp,&cmpt,&flg); CHKERRQ(ierr); 00623 if (!flg) { 00624 if (!f) SETERRQ(MPI_COMM_WORLD,1,"Could not find cat/cmp, but no flag to report this"); 00625 *f = PETSC_FALSE; PetscFunctionReturn(0); 00626 } 00627 ierr = ComponentGetType(cmpt,t); CHKERRQ(ierr); 00628 if (f) *f = PETSC_TRUE; 00629 PetscFunctionReturn(0); 00630 } 00631 00632 #undef __FUNCT__ 00633 #define __FUNCT__ "HasQuantity" 00634 /*! 00635 Check if a certain quantity is precomputed, meaning that it can 00636 be retrieved (with a call to ComputeQuantity()) at no computational cost. 00637 00638 The category and module names have to exist. 00639 Use HasComputeModule() to test whether 00640 a category and module is known to the system. 00641 00642 See \ref attached "the page on attached quantities" for an explanation 00643 of the mechanism behind this routine. 00644 */ 00645 PetscErrorCode HasQuantity 00646 (AnaModNumericalProblem prob,const char *cat,const char *cmp,PetscBool *f) 00647 { 00648 categoryobject catg; componentobject cmpt; 00649 AnalysisDataType t; int id; PetscErrorCode ierr; 00650 PetscFunctionBegin; 00651 ierr = GetCategory(cat,&catg,f); CHKERRQ(ierr); 00652 if (!*f) PetscFunctionReturn(0); 00653 ierr = CategoryGetComponent(catg,cmp,&cmpt,f); CHKERRQ(ierr); 00654 if (!*f) PetscFunctionReturn(0); 00655 ierr = ComponentGetId(cmpt,&id); CHKERRQ(ierr); 00656 ierr = ComponentGetType(cmpt,&t); CHKERRQ(ierr); 00657 ierr = HasQuantityByID(prob,id,t,f); CHKERRQ(ierr); 00658 PetscFunctionReturn(0); 00659 } 00660 00661 #undef __FUNCT__ 00662 #define __FUNCT__ "HasQuantityByID" 00663 /*! Auxiliary routine with lookup by ID, which is much faster 00664 than by string indexing. 00665 */ 00666 PetscErrorCode HasQuantityByID 00667 (AnaModNumericalProblem prob,int id,AnalysisDataType type,PetscBool *f) 00668 { 00669 Mat A = (Mat)prob; PetscReal rv,*rsv; int iv,*isv; 00670 PetscErrorCode ierr; 00671 PetscFunctionBegin; 00672 switch (type) { 00673 case ANALYSISINTEGER : 00674 ierr = PetscObjectComposedDataGetInt 00675 ((PetscObject)A,id,iv,*f); CHKERRQ(ierr); 00676 break; 00677 case ANALYSISDOUBLE : 00678 ierr = PetscObjectComposedDataGetReal 00679 ((PetscObject)A,id,rv,*f); CHKERRQ(ierr); 00680 break; 00681 case ANALYSISINTARRAY : 00682 ierr = PetscObjectComposedDataGetIntstar 00683 ((PetscObject)A,id,isv,*f); CHKERRQ(ierr); 00684 break; 00685 case ANALYSISDBLARRAY : 00686 ierr = PetscObjectComposedDataGetRealstar 00687 ((PetscObject)A,id,rsv,*f); CHKERRQ(ierr); 00688 break; 00689 default : SETERRQ1(MPI_COMM_WORLD,1,"Unknown data type %d",type); 00690 } 00691 PetscFunctionReturn(0); 00692 } 00693 00694 #undef __FUNCT__ 00695 #define __FUNCT__ "RetrieveQuantityByID" 00696 /*! See also HasQuantityByID() */ 00697 PetscErrorCode RetrieveQuantityByID 00698 (AnaModNumericalProblem prob,int id,AnalysisDataType type, 00699 AnalysisItem *result,PetscBool *f) 00700 { 00701 Mat A = (Mat)prob; PetscErrorCode ierr; 00702 PetscFunctionBegin; 00703 00704 switch (type) { 00705 case ANALYSISINTEGER : 00706 ierr = PetscObjectComposedDataGetInt 00707 ((PetscObject)A,id,result->i,*f); CHKERRQ(ierr); 00708 break; 00709 case ANALYSISDOUBLE : 00710 ierr = PetscObjectComposedDataGetReal 00711 ((PetscObject)A,id,result->r,*f); CHKERRQ(ierr); 00712 break; 00713 case ANALYSISINTARRAY : 00714 ierr = PetscObjectComposedDataGetIntstar 00715 ((PetscObject)A,id,result->ii,*f); CHKERRQ(ierr); 00716 break; 00717 case ANALYSISDBLARRAY : 00718 ierr = PetscObjectComposedDataGetRealstar 00719 ((PetscObject)A,id,result->rr,*f); CHKERRQ(ierr); 00720 break; 00721 default : SETERRQ1(MPI_COMM_WORLD,1,"Unknown data type %d",type); 00722 } 00723 PetscFunctionReturn(0); 00724 } 00725 00726 #undef __FUNCT__ 00727 #define __FUNCT__ "QuantityAsString" 00728 /*! 00729 Generate a character string for a given quantity. 00730 */ 00731 PetscErrorCode QuantityAsString(AnalysisItem *q,AnalysisDataType t,char **s) 00732 { 00733 PetscErrorCode ierr; size_t l; 00734 00735 PetscFunctionBegin; 00736 switch (t) { 00737 case ANALYSISINTEGER : 00738 ierr = PetscMalloc(12*sizeof(char),s); CHKERRQ(ierr); 00739 ierr = PetscMemzero((void*)*s,12*sizeof(char)); CHKERRQ(ierr); 00740 sprintf((char*)*s,"%d",q->i); 00741 break; 00742 case ANALYSISDOUBLE : 00743 ierr = PetscMalloc(22*sizeof(char),s); CHKERRQ(ierr); 00744 ierr = PetscMemzero((void*)*s,22*sizeof(char)); CHKERRQ(ierr); 00745 sprintf((char*)*s,"%e",q->r); 00746 break; 00747 case ANALYSISSTRING : 00748 ierr = PetscMalloc((strlen(q->c)+1)*sizeof(char),s); CHKERRQ(ierr); 00749 ierr = PetscMemzero((void*)*s,(strlen(q->c)+1)*sizeof(char)); CHKERRQ(ierr); 00750 sprintf((char*)*s,"%s",q->c); 00751 break; 00752 case ANALYSISINTARRAY : 00753 { 00754 int i,n,*iar; 00755 iar = q->ii; 00756 n = q->len; 00757 ierr = PetscMalloc((10*n+1)*sizeof(char),s); CHKERRQ(ierr); 00758 ierr = PetscMemzero((void*)*s,(10*n+1)*sizeof(char)); CHKERRQ(ierr); 00759 for (i=0; i<=n; i++) { 00760 ierr = PetscStrlen(*s,&l); CHKERRQ(ierr); 00761 sprintf((char*)*s+l,"%d,",iar[i]); 00762 } 00763 } 00764 break; 00765 case ANALYSISDBLARRAY : 00766 { 00767 int i,n; PetscReal *rar; 00768 rar = q->rr; 00769 n = q->len; 00770 ierr = PetscMalloc((15*n+1)*sizeof(char),s); CHKERRQ(ierr); 00771 ierr = PetscMemzero((void*)*s,(15*n+1)*sizeof(char)); CHKERRQ(ierr); 00772 for (i=0; i<=n; i++) { 00773 ierr = PetscStrlen(*s,&l); CHKERRQ(ierr); 00774 sprintf((char*)*s+l,"%e,",rar[i]); 00775 } 00776 } 00777 break; 00778 default : SETERRQ1(MPI_COMM_WORLD,1,"Cannot string quantity type %d",t); 00779 } 00780 PetscFunctionReturn(0); 00781 } 00782