00001 /** 00002 * @file vcs_internal.h 00003 * Internal declarations for the VCSnonideal package 00004 */ 00005 /* 00006 * $Id: vcs_internal.h 368 2010-01-04 00:46:26Z hkmoffa $ 00007 */ 00008 00009 /* 00010 * Copywrite (2005) Sandia Corporation. Under the terms of 00011 * Contract DE-AC04-94AL85000 with Sandia Corporation, the 00012 * U.S. Government retains certain rights in this software. 00013 */ 00014 00015 #ifndef _VCS_INTERNAL_H 00016 #define _VCS_INTERNAL_H 00017 00018 #include <cstring> 00019 00020 #include "vcs_defs.h" 00021 #include "vcs_DoubleStarStar.h" 00022 #include "vcs_Exception.h" 00023 00024 #include "global.h" 00025 00026 namespace VCSnonideal { 00027 00028 //! Points to the data in a std::vector<> object 00029 #define VCS_DATA_PTR(vvv) (&(vvv[0])) 00030 00031 //! define this Cantera function to replace printf 00032 /*! 00033 * We can replace this with printf easily 00034 */ 00035 #define plogf Cantera::writelogf 00036 00037 //! define this Cantera function to replace cout << endl; 00038 /*! 00039 * We use this to place an endl in the log file, and 00040 * ensure that the IO buffers are flushed. 00041 */ 00042 #define plogendl() Cantera::writelogendl() 00043 00044 //! Global hook for turning on and off time printing. 00045 /*! 00046 * Default is to allow printing. But, you can assign this to zero 00047 * globally to turn off all time printing. 00048 * This is helpful for test suite purposes where you are interested 00049 * in differences in text files. 00050 */ 00051 extern int vcs_timing_print_lvl; 00052 00053 /* 00054 * Forward references 00055 */ 00056 class VCS_SPECIES_THERMO; 00057 class VCS_PROB; 00058 00059 //! Amount of extra printing that is done while in debug mode. 00060 /*! 00061 * 0 -> none 00062 * 1 -> some 00063 * 2 -> alot (default) 00064 * 3 -> everything 00065 */ 00066 00067 //! Class to keep track of time and iterations 00068 /*! 00069 * class keeps all of the counters together. 00070 */ 00071 class VCS_COUNTERS { 00072 public: 00073 //! Total number of iterations in the main loop 00074 //! of vcs_TP() to solve for thermo equilibrium 00075 int T_Its; 00076 00077 //! Current number of iterations in the main loop 00078 //! of vcs_TP() to solve for thermo equilibrium 00079 int Its; 00080 00081 //! Total number of optimizations of the 00082 //! components basis set done 00083 int T_Basis_Opts; 00084 00085 //! number of optimizations of the components basis set done 00086 int Basis_Opts; 00087 00088 //! Current number of times the initial thermo 00089 //! equilibrium estimator has been called 00090 int T_Calls_Inest; 00091 00092 //! Current number of calls to vcs_TP 00093 int T_Calls_vcs_TP; 00094 00095 //! Current time spent in vcs_TP 00096 double T_Time_vcs_TP; 00097 00098 //! Current time spent in vcs_TP 00099 double Time_vcs_TP; 00100 00101 //! Total Time spent in basopt 00102 double T_Time_basopt; 00103 00104 //! Current Time spent in basopt 00105 double Time_basopt; 00106 00107 //! Time spent in initial estimator 00108 double T_Time_inest; 00109 00110 //! Time spent in the vcs suite of programs 00111 double T_Time_vcs; 00112 }; 00113 00114 //! Returns the value of the gas constant in the units specified by parameter 00115 /*! 00116 * @param mu_units Specifies the units. 00117 * - VCS_UNITS_KCALMOL: kcal gmol-1 K-1 00118 * - VCS_UNITS_UNITLESS: 1.0 K-1 00119 * - VCS_UNITS_KJMOL: kJ gmol-1 K-1 00120 * - VCS_UNITS_KELVIN: 1.0 K-1 00121 * - VCS_UNITS_MKS: joules kmol-1 K-1 = kg m2 s-2 kmol-1 K-1 00122 */ 00123 double vcsUtil_gasConstant(int mu_units); 00124 00125 //! Invert an n x n matrix and solve m rhs's 00126 /*! 00127 * Solve a square matrix with multiple right hand sides 00128 * 00129 * \f[ 00130 * C X + B = 0; 00131 * \f] 00132 * 00133 * This routine uses Gauss elimination and is optimized for the solution 00134 * of lots of rhs's. A crude form of row pivoting is used here. 00135 * The matrix C is destroyed during the solve. 00136 * 00137 * @return The solution x[] is returned in the matrix <I>B</I>. 00138 * Routine returns an integer representing success: 00139 * - 1 : Matrix is singluar 00140 * - 0 : solution is OK 00141 * 00142 * 00143 * @param c Matrix to be inverted. c is in fortran format, i.e., rows 00144 * are the inner loop. Row numbers equal to idem. 00145 * c[i+j*idem] = c_i_j = Matrix to be inverted: 00146 * - i = row number 00147 * - j = column number 00148 * 00149 * @param idem number of row dimensions in c 00150 * @param n Number of rows and columns in c 00151 * @param b Multiple RHS. Note, b is actually the negative of 00152 * most formulations. Row numbers equal to idem. 00153 * b[i+j*idem] = b_i_j = vectors of rhs's: 00154 * - i = row number 00155 * - j = column number 00156 * (each column is a new rhs) 00157 * @param m number of rhs's 00158 */ 00159 int vcsUtil_mlequ(double *c, int idem, int n, double *b, int m); 00160 00161 //! Swap values in vector of doubles 00162 /*! 00163 * Switches the value of x[i1] with x[i2] 00164 * 00165 * @param x Vector of doubles 00166 * @param i1 first index 00167 * @param i2 second index 00168 */ 00169 void vcsUtil_dsw(double x[], int i1, int i2); 00170 00171 //! Swap values in an integer array 00172 /*! 00173 * Switches the value of x[i1] with x[i2] 00174 * 00175 * @param x Vector of integers 00176 * @param i1 first index 00177 * @param i2 second index 00178 */ 00179 void vcsUtil_isw(int x[], int i1, int i2); 00180 00181 //! Swap values in a std vector string 00182 /*! 00183 * Switches the value of vecStrings[i1] with vecStrings[i2] 00184 * 00185 * @param vecStrings Vector of integers 00186 * @param i1 first index 00187 * @param i2 second index 00188 */ 00189 void vcsUtil_stsw(std::vector<std::string> & vecStrings, 00190 int i1, int i2); 00191 00192 //! Definition of the function pointer for the root finder 00193 /*! 00194 * see vcsUtil_root1d for a definition of how to use this. 00195 */ 00196 typedef double (*VCS_FUNC_PTR)(double xval, double Vtarget, 00197 int varID, void *fptrPassthrough, 00198 int *err); 00199 00200 //! One dimensional root finder 00201 /*! 00202 * 00203 * This root finder will find the root of a one dimensional 00204 * equation 00205 * 00206 * \f[ 00207 * f(x) = 0 00208 * \f] 00209 * where x is a bounded quantity: \f$ x_{min} < x < x_max \f$ 00210 * 00211 * The functional to be minimized must have the following call 00212 * structure: 00213 * 00214 * @verbatim 00215 typedef double (*VCS_FUNC_PTR)(double xval, double Vtarget, 00216 int varID, void *fptrPassthrough, 00217 int *err); @endverbatim 00218 * 00219 * xval is the current value of the x variable. Vtarget is the 00220 * requested value of f(x), usually 0. varID is an integer 00221 * that is passed through. fptrPassthrough is a void pointer 00222 * that is passed through. err is a return error indicator. 00223 * err = 0 is the norm. anything else is considered a fatal 00224 * error. 00225 * The return value of the function is the current value of 00226 * f(xval). 00227 * 00228 * @param xmin Minimum permissible value of the x variable 00229 * @param xmax Maximum permissible value of the x paramerer 00230 * @param itmax Maximum number of iterations 00231 * @param func function pointer, pointing to the function to be 00232 * minimized 00233 * @param fptrPassthrough Pointer to void that gets passed through 00234 * the rootfinder, unchanged, to the func. 00235 * @param FuncTargVal Target value of the function. This is usually set 00236 * to zero. 00237 * @param varID Variable ID. This is usually set to zero. 00238 * @param xbest Pointer to the initial value of x on input. On output 00239 * This contains the root value. 00240 * @param printLvl Print level of the routine. 00241 * 00242 * 00243 * Following is a nontrial example for vcs_root1d() in which the position of a 00244 * cylinder floating on the water is calculated. 00245 * 00246 * @verbatim 00247 #include <cmath> 00248 #include <cstdlib> 00249 00250 #include "Cantera.h" 00251 #include "kernel/vcs_internal.h" 00252 using namespace Cantera; 00253 using namespace VCSnonideal; 00254 00255 const double g_cgs = 980.; 00256 const double mass_cyl = 0.066; 00257 const double diam_cyl = 0.048; 00258 const double rad_cyl = diam_cyl / 2.0; 00259 const double len_cyl = 5.46; 00260 const double vol_cyl = Pi * diam_cyl * diam_cyl / 4 * len_cyl; 00261 const double rho_cyl = mass_cyl / vol_cyl; 00262 const double rho_gas = 0.0; 00263 const double rho_liq = 1.0; 00264 const double sigma = 72.88; 00265 // Contact angle in radians 00266 const double alpha1 = 40.0 / 180. * Pi; 00267 00268 double func_vert(double theta1, double h_2, double rho_c) { 00269 double f_grav = - Pi * rad_cyl * rad_cyl * rho_c * g_cgs; 00270 double tmp = rad_cyl * rad_cyl * g_cgs; 00271 double tmp1 = theta1 + sin(theta1) * cos(theta1) - 2.0 * h_2 / rad_cyl * sin(theta1); 00272 double f_buoy = tmp * (Pi * rho_gas + (rho_liq - rho_gas) * tmp1); 00273 double f_sten = 2 * sigma * sin(theta1 + alpha1 - Pi); 00274 double f_net = f_grav + f_buoy + f_sten; 00275 return f_net; 00276 } 00277 double calc_h2_farfield(double theta1) { 00278 double rhs = sigma * (1.0 + cos(alpha1 + theta1)); 00279 rhs *= 2.0; 00280 rhs = rhs / (rho_liq - rho_gas) / g_cgs; 00281 double sign = -1.0; 00282 if (alpha1 + theta1 < Pi) sign = 1.0; 00283 double res = sign * sqrt(rhs); 00284 double h2 = res + rad_cyl * cos(theta1); 00285 return h2; 00286 } 00287 double funcZero(double xval, double Vtarget, int varID, void *fptrPassthrough, int *err) { 00288 double theta = xval; 00289 double h2 = calc_h2_farfield(theta); 00290 double fv = func_vert(theta, h2, rho_cyl); 00291 return fv; 00292 } 00293 int main () { 00294 double thetamax = Pi; 00295 double thetamin = 0.0; 00296 int maxit = 1000; 00297 int iconv; 00298 double thetaR = Pi/2.0; 00299 int printLvl = 4; 00300 00301 iconv = VCSnonideal::vcsUtil_root1d(thetamin, thetamax, maxit, 00302 funcZero, 00303 (void *) 0, 0.0, 0, 00304 &thetaR, printLvl); 00305 printf("theta = %g\n", thetaR); 00306 double h2Final = calc_h2_farfield(thetaR); 00307 printf("h2Final = %g\n", h2Final); 00308 return 0; 00309 } @endverbatim 00310 * 00311 */ 00312 int vcsUtil_root1d(double xmin, double xmax, int itmax, VCS_FUNC_PTR func, 00313 void *fptrPassthrough, 00314 double FuncTargVal, int varID, double *xbest, 00315 int printLvl = 0); 00316 00317 //! Returns the system wall clock time in seconds 00318 /*! 00319 * @return time in seconds. 00320 */ 00321 double vcs_second(); 00322 00323 //! This define turns on using memset and memcpy. I have not run into 00324 //! any systems where this is a problem. It's the fastest way to do 00325 //! low lvl operations where applicable. There are alternative routines 00326 //! available if this ever fails. 00327 #define USE_MEMSET 00328 #ifdef USE_MEMSET 00329 00330 //! Zero a double vector 00331 /*! 00332 * @param vec_to vector of doubles 00333 * @param length length of the vector to zero. 00334 */ 00335 inline void vcs_dzero(double * const vec_to, const int length) { 00336 (void) memset((void *) vec_to, 0, length * sizeof(double)); 00337 } 00338 00339 //! Zero an int vector 00340 /*! 00341 * @param vec_to vector of ints 00342 * @param length length of the vector to zero. 00343 */ 00344 inline void vcs_izero(int * const vec_to, const int length) { 00345 (void) memset((void *) vec_to, 0, length * sizeof(int)); 00346 } 00347 00348 //! Copy a double vector 00349 /*! 00350 * @param vec_to Vector to copy into. This vector must be dimensioned 00351 * at least as large as the vec_from vector. 00352 * @param vec_from Vector to copy from 00353 * @param length Number of doubles to copy. 00354 */ 00355 inline void vcs_dcopy(double * const vec_to, 00356 const double * const vec_from, const int length) { 00357 (void) memcpy((void *) vec_to, (const void *) vec_from, 00358 (length) * sizeof(double)); 00359 } 00360 00361 00362 //! Copy an int vector 00363 /*! 00364 * @param vec_to Vector to copy into. This vector must be dimensioned 00365 * at least as large as the vec_from vector. 00366 * @param vec_from Vector to copy from 00367 * @param length Number of int to copy. 00368 */ 00369 inline void vcs_icopy(int * const vec_to, 00370 const int * const vec_from, const int length) { 00371 (void) memcpy((void *) vec_to, (const void *) vec_from, 00372 (length) * sizeof(int)); 00373 } 00374 00375 //! Zero a std double vector 00376 /*! 00377 * @param vec_to vector of doubles 00378 * @param length length of the vector to zero. 00379 */ 00380 inline void vcs_vdzero(std::vector<double> &vec_to, const int length) { 00381 (void) memset((void *)VCS_DATA_PTR(vec_to), 0, (length) * sizeof(double)); 00382 } 00383 00384 //! Zero a std int vector 00385 /*! 00386 * @param vec_to vector of ints 00387 * @param length length of the vector to zero. 00388 */ 00389 inline void vcs_vizero(std::vector<int> &vec_to, const int length) { 00390 (void) memset((void *)VCS_DATA_PTR(vec_to), 0, (length) * sizeof(int)); 00391 } 00392 00393 //! Copy one std double vector into another 00394 /*! 00395 * This is an inlined function that uses memcpy. memcpy is probably 00396 * the fastest way to do this. This routine requires the vectors to be 00397 * previously dimensioned appropriately. No error checking is done. 00398 * 00399 * @param vec_to Vector to copy into. This vector must be dimensioned 00400 * at least as large as the vec_from vector. 00401 * @param vec_from Vector to copy from 00402 * @param length Number of doubles to copy. 00403 */ 00404 inline void vcs_vdcopy(std::vector<double> & vec_to, 00405 const std::vector<double> & vec_from, int length) { 00406 (void) memcpy((void *)&(vec_to[0]), (const void *) &(vec_from[0]), 00407 (length) * sizeof(double)); 00408 } 00409 00410 //! Copy one std integer vector into another 00411 /*! 00412 * This is an inlined function that uses memcpy. memcpy is probably 00413 * the fastest way to do this. This routine requires the 00414 * 00415 * @param vec_to Vector to copy into. This vector must be dimensioned 00416 * at least as large as the vec_from vector. 00417 * @param vec_from Vector to copy from 00418 * @param length Number of integers to copy. 00419 */ 00420 inline void vcs_vicopy(std::vector<int> & vec_to, 00421 const std::vector<int> & vec_from, const int length) { 00422 (void) memcpy((void *)&(vec_to[0]), (const void *) &(vec_from[0]), 00423 (length) * sizeof(int)); 00424 } 00425 #else 00426 extern void vcs_dzero(double * const, const int); 00427 extern void vcs_izero(int * const , const int); 00428 extern void vcs_dcopy(double * const, const double * const, const int); 00429 extern void vcs_icopy(int * const, const int * const, const int); 00430 extern void vcs_vdzero(std::vector<double> &vvv, const int len = -1); 00431 extern void vcs_vizero(std::vector<double> &vvv, const int len = -1); 00432 void vcs_vdcopy(std::vector<double> &vec_to, 00433 const std::vector<double> vec_from, const int len = -1); 00434 void vcs_vicopy(std::vector<int> &vec_to, 00435 const std::vector<int> vec_from, const int len = -1); 00436 #endif 00437 00438 //! determine the l2 norm of a vector of doubles 00439 /*! 00440 * @param vec vector of doubles 00441 * 00442 * @return Returns the l2 norm of the vector 00443 */ 00444 double vcs_l2norm(const std::vector<double> vec); 00445 00446 //! Finds the location of the maximum component in a double vector 00447 /*! 00448 * @param x pointer to a vector of doubles 00449 * @param xSize pointer to a vector of doubles used as a multiplier 00450 * to x[] 00451 * @param j lowest index to search from 00452 * @param n highest index to search from 00453 * @return Return index of the greatest value on X(i) searched 00454 * j <= i < n 00455 */ 00456 int vcs_optMax(const double *x, const double *xSize, int j, int n); 00457 00458 //! Returns the maximum integer in a list 00459 /*! 00460 * @param vector pointer to a vector of ints 00461 * @param length length of the integer vector 00462 * 00463 * @return returns the max integer value in the list 00464 */ 00465 int vcs_max_int(const int *vector, int length); 00466 00467 //! Prints a line consisting of mutliple occurances of the same string 00468 /*! 00469 * This prints a string num times, and then terminate with a 00470 * end of line character 00471 * 00472 * @param str C string that is null terminated 00473 * @param num number of times the string is to be printed 00474 */ 00475 void vcs_print_line(const char *str, int num); 00476 00477 //! Returns a const char string representing the type of the 00478 //! species given by the first argument 00479 /*! 00480 * @param speciesStatus Species status integer representing the type 00481 * of the species. 00482 * @param length Maximum length of the string to be returned. 00483 * Shorter values will yield abbreviated strings. 00484 * Defaults to a value of 100. 00485 */ 00486 const char *vcs_speciesType_string(int speciesStatus, int length = 100); 00487 00488 //! Print a string within a given space limit 00489 /*! 00490 * This routine limits the amount of the string that will be printed to a 00491 * maximum of "space" characters. Printing is done to 00492 * to Cantera's writelog() function. 00493 * 00494 * @param str String, which must be null terminated. 00495 * @param space space limit for the printing. 00496 * @param alignment Alignment of string within the space: 00497 * - 0 centered 00498 * - 1 right aligned 00499 * - 2 left aligned 00500 */ 00501 void vcs_print_stringTrunc(const char *str, int space, int alignment); 00502 00503 //! Simple routine to check whether two doubles are equal up to 00504 //! roundoff error 00505 /*! 00506 * Currently it's set to check for 10 digits of 00507 * relative accuracy. 00508 * 00509 * @param d1 first double 00510 * @param d2 second double 00511 * 00512 * @return returns true if the doubles are "equal" and false otherwise 00513 */ 00514 bool vcs_doubleEqual(double d1, double d2); 00515 00516 } 00517 00518 #endif