cantera/include/cantera/equil/vcs_internal.h
Harry Moffat c6f7abbf2f Fixed a serious error in InterfaceKinetics that had crept into this branch.
Started upgrade/update of equilibrium solver
       - Fixed numerical jacobian calculation of the ln activity coefficients.
2012-11-29 02:18:05 +00:00

543 lines
17 KiB
C++

/**
* @file vcs_internal.h
* Internal declarations for the VCSnonideal package
*/
/*
* Copyright (2005) Sandia Corporation. Under the terms of
* Contract DE-AC04-94AL85000 with Sandia Corporation, the
* U.S. Government retains certain rights in this software.
*/
#ifndef _VCS_INTERNAL_H
#define _VCS_INTERNAL_H
#include <cstring>
#include "cantera/equil/vcs_defs.h"
#include "cantera/base/global.h"
namespace VCSnonideal
{
using Cantera::npos;
//! Points to the data in a std::vector<> object
#define VCS_DATA_PTR(vvv) (&(vvv[0]))
//! define this Cantera function to replace printf
/*!
* We can replace this with printf easily
*/
#define plogf Cantera::writelogf
//! define this Cantera function to replace cout << endl;
/*!
* We use this to place an endl in the log file, and
* ensure that the IO buffers are flushed.
*/
#define plogendl() Cantera::writelogendl()
//! Global hook for turning on and off time printing.
/*!
* Default is to allow printing. But, you can assign this to zero
* globally to turn off all time printing.
* This is helpful for test suite purposes where you are interested
* in differences in text files.
*/
extern int vcs_timing_print_lvl;
/*
* Forward references
*/
class VCS_SPECIES_THERMO;
class VCS_PROB;
//! Amount of extra printing that is done while in debug mode.
/*!
* 0 -> none
* 1 -> some
* 2 -> alot (default)
* 3 -> everything
*/
//! Class to keep track of time and iterations
/*!
* class keeps all of the counters together.
*/
class VCS_COUNTERS
{
public:
//! Total number of iterations in the main loop
//! of vcs_TP() to solve for thermo equilibrium
int T_Its;
//! Current number of iterations in the main loop
//! of vcs_TP() to solve for thermo equilibrium
int Its;
//! Total number of optimizations of the
//! components basis set done
int T_Basis_Opts;
//! number of optimizations of the components basis set done
int Basis_Opts;
//! Current number of times the initial thermo
//! equilibrium estimator has been called
int T_Calls_Inest;
//! Current number of calls to vcs_TP
int T_Calls_vcs_TP;
//! Current time spent in vcs_TP
double T_Time_vcs_TP;
//! Current time spent in vcs_TP
double Time_vcs_TP;
//! Total Time spent in basopt
double T_Time_basopt;
//! Current Time spent in basopt
double Time_basopt;
//! Time spent in initial estimator
double T_Time_inest;
//! Time spent in the vcs suite of programs
double T_Time_vcs;
};
//! Returns the value of the gas constant in the units specified by parameter
/*!
* @param mu_units Specifies the units.
* - VCS_UNITS_KCALMOL: kcal gmol-1 K-1
* - VCS_UNITS_UNITLESS: 1.0 K-1
* - VCS_UNITS_KJMOL: kJ gmol-1 K-1
* - VCS_UNITS_KELVIN: 1.0 K-1
* - VCS_UNITS_MKS: joules kmol-1 K-1 = kg m2 s-2 kmol-1 K-1
*/
double vcsUtil_gasConstant(int mu_units);
//! Invert an n x n matrix and solve m rhs's
/*!
* Solve a square matrix with multiple right hand sides
*
* \f[
* C X + B = 0;
* \f]
*
* This routine uses Gauss elimination and is optimized for the solution
* of lots of rhs's. A crude form of row pivoting is used here.
* The matrix C is destroyed during the solve.
*
* @return The solution x[] is returned in the matrix <I>B</I>.
* Routine returns an integer representing success:
* - 1 : Matrix is singular
* - 0 : solution is OK
*
*
* @param c Matrix to be inverted. c is in fortran format, i.e., rows
* are the inner loop. Row numbers equal to idem.
* c[i+j*idem] = c_i_j = Matrix to be inverted:
* - i = row number
* - j = column number
*
* @param idem number of row dimensions in c
* @param n Number of rows and columns in c
* @param b Multiple RHS. Note, b is actually the negative of
* most formulations. Row numbers equal to idem.
* b[i+j*idem] = b_i_j = vectors of rhs's:
* - i = row number
* - j = column number
* (each column is a new rhs)
* @param m number of rhs's
*/
int vcsUtil_mlequ(double* c, size_t idem, size_t n, double* b, size_t m);
//! Invert an n x n matrix and solve m rhs's
/*!
* Solve a square matrix with multiple right hand sides
*
* \f[
* C X + B = 0;
* \f]
*
* This routine uses Gauss-Jordan elimination and is optimized for the solution
* of lots of rhs's. Full row and column pivoting is used here. It's been
* shown to be necessary in at least one case.
* The matrix C is destroyed during the solve.
*
* @return The solution x[] is returned in the matrix <I>B</I>.
* Routine returns an integer representing success:
* - 1 : Matrix is singular
* - 0 : solution is OK
*
* @param c Matrix to be inverted. c is in fortran format, i.e., rows
* are the inner loop. Row numbers equal to idem.
* c[i+j*idem] = c_i_j = Matrix to be inverted:
* - i = row number
* - j = column number
*
* @param idem number of row dimensions in c
* @param n Number of rows and columns in c
* @param b Multiple RHS. Note, b is actually the negative of
* most formulations. Row numbers equal to idem.
* b[i+j*idem] = b_i_j = vectors of rhs's:
* - i = row number
* - j = column number
* (each column is a new rhs)
* @param m number of rhs's
*/
int vcsUtil_gaussj(double* c, size_t idem, size_t n, double* b, size_t m);
//! Definition of the function pointer for the root finder
/*!
* see vcsUtil_root1d for a definition of how to use this.
*/
typedef double(*VCS_FUNC_PTR)(double xval, double Vtarget,
int varID, void* fptrPassthrough,
int* err);
//! One dimensional root finder
/*!
*
* This root finder will find the root of a one dimensional
* equation
*
* \f[
* f(x) = 0
* \f]
* where x is a bounded quantity: \f$ x_{min} < x < x_max \f$
*
* The functional to be minimized must have the following call
* structure:
*
* @verbatim
typedef double (*VCS_FUNC_PTR)(double xval, double Vtarget,
int varID, void *fptrPassthrough,
int *err); @endverbatim
*
* xval is the current value of the x variable. Vtarget is the
* requested value of f(x), usually 0. varID is an integer
* that is passed through. fptrPassthrough is a void pointer
* that is passed through. err is a return error indicator.
* err = 0 is the norm. anything else is considered a fatal
* error.
* The return value of the function is the current value of
* f(xval).
*
* @param xmin Minimum permissible value of the x variable
* @param xmax Maximum permissible value of the x parameter
* @param itmax Maximum number of iterations
* @param func function pointer, pointing to the function to be
* minimized
* @param fptrPassthrough Pointer to void that gets passed through
* the rootfinder, unchanged, to the func.
* @param FuncTargVal Target value of the function. This is usually set
* to zero.
* @param varID Variable ID. This is usually set to zero.
* @param xbest Pointer to the initial value of x on input. On output
* This contains the root value.
* @param printLvl Print level of the routine.
*
*
* Following is a nontrial example for vcs_root1d() in which the position of a
* cylinder floating on the water is calculated.
*
* @verbatim
#include <cmath>
#include <cstdlib>
#include "equil/vcs_internal.h"
const double g_cgs = 980.;
const double mass_cyl = 0.066;
const double diam_cyl = 0.048;
const double rad_cyl = diam_cyl / 2.0;
const double len_cyl = 5.46;
const double vol_cyl = Pi * diam_cyl * diam_cyl / 4 * len_cyl;
const double rho_cyl = mass_cyl / vol_cyl;
const double rho_gas = 0.0;
const double rho_liq = 1.0;
const double sigma = 72.88;
// Contact angle in radians
const double alpha1 = 40.0 / 180. * Pi;
double func_vert(double theta1, double h_2, double rho_c) {
double f_grav = - Pi * rad_cyl * rad_cyl * rho_c * g_cgs;
double tmp = rad_cyl * rad_cyl * g_cgs;
double tmp1 = theta1 + sin(theta1) * cos(theta1) - 2.0 * h_2 / rad_cyl * sin(theta1);
double f_buoy = tmp * (Pi * rho_gas + (rho_liq - rho_gas) * tmp1);
double f_sten = 2 * sigma * sin(theta1 + alpha1 - Pi);
double f_net = f_grav + f_buoy + f_sten;
return f_net;
}
double calc_h2_farfield(double theta1) {
double rhs = sigma * (1.0 + cos(alpha1 + theta1));
rhs *= 2.0;
rhs = rhs / (rho_liq - rho_gas) / g_cgs;
double sign = -1.0;
if (alpha1 + theta1 < Pi) sign = 1.0;
double res = sign * sqrt(rhs);
double h2 = res + rad_cyl * cos(theta1);
return h2;
}
double funcZero(double xval, double Vtarget, int varID, void *fptrPassthrough, int *err) {
double theta = xval;
double h2 = calc_h2_farfield(theta);
double fv = func_vert(theta, h2, rho_cyl);
return fv;
}
int main () {
double thetamax = Pi;
double thetamin = 0.0;
int maxit = 1000;
int iconv;
double thetaR = Pi/2.0;
int printLvl = 4;
iconv = VCSnonideal::vcsUtil_root1d(thetamin, thetamax, maxit,
funcZero,
(void *) 0, 0.0, 0,
&thetaR, printLvl);
printf("theta = %g\n", thetaR);
double h2Final = calc_h2_farfield(thetaR);
printf("h2Final = %g\n", h2Final);
return 0;
} @endverbatim
*
*/
int vcsUtil_root1d(double xmin, double xmax, size_t itmax, VCS_FUNC_PTR func,
void* fptrPassthrough,
double FuncTargVal, int varID, double* xbest,
int printLvl = 0);
//! Returns the system wall clock time in seconds
/*!
* @return time in seconds.
*/
double vcs_second();
//! This define turns on using memset and memcpy. I have not run into
//! any systems where this is a problem. It's the fastest way to do
//! low lvl operations where applicable. There are alternative routines
//! available if this ever fails.
#define USE_MEMSET
#ifdef USE_MEMSET
//! Zero a double vector
/*!
* @param vec_to vector of doubles
* @param length length of the vector to zero.
*/
inline void vcs_dzero(double* const vec_to, const size_t length)
{
(void) memset((void*) vec_to, 0, length * sizeof(double));
}
//! Zero an int vector
/*!
* @param vec_to vector of ints
* @param length length of the vector to zero.
*/
inline void vcs_izero(int* const vec_to, const size_t length)
{
(void) memset((void*) vec_to, 0, length * sizeof(int));
}
//! Copy a double vector
/*!
* @param vec_to Vector to copy into. This vector must be dimensioned
* at least as large as the vec_from vector.
* @param vec_from Vector to copy from
* @param length Number of doubles to copy.
*/
inline void vcs_dcopy(double* const vec_to,
const double* const vec_from, const size_t length)
{
(void) memcpy((void*) vec_to, (const void*) vec_from,
(length) * sizeof(double));
}
//! Copy an int vector
/*!
* @param vec_to Vector to copy into. This vector must be dimensioned
* at least as large as the vec_from vector.
* @param vec_from Vector to copy from
* @param length Number of int to copy.
*/
inline void vcs_icopy(int* const vec_to,
const int* const vec_from, const size_t length)
{
(void) memcpy((void*) vec_to, (const void*) vec_from,
(length) * sizeof(int));
}
//! Zero a std double vector
/*!
* @param vec_to vector of doubles
* @param length length of the vector to zero.
*/
inline void vcs_vdzero(std::vector<double> &vec_to, const size_t length)
{
(void) memset((void*)VCS_DATA_PTR(vec_to), 0, (length) * sizeof(double));
}
//! Zero a std int vector
/*!
* @param vec_to vector of ints
* @param length length of the vector to zero.
*/
inline void vcs_vizero(std::vector<int> &vec_to, const size_t length)
{
(void) memset((void*)VCS_DATA_PTR(vec_to), 0, (length) * sizeof(int));
}
//! Copy one std double vector into another
/*!
* This is an inlined function that uses memcpy. memcpy is probably
* the fastest way to do this. This routine requires the vectors to be
* previously dimensioned appropriately. No error checking is done.
*
* @param vec_to Vector to copy into. This vector must be dimensioned
* at least as large as the vec_from vector.
* @param vec_from Vector to copy from
* @param length Number of doubles to copy.
*/
inline void vcs_vdcopy(std::vector<double> & vec_to,
const std::vector<double> & vec_from, size_t length)
{
(void) memcpy((void*)&(vec_to[0]), (const void*) &(vec_from[0]),
(length) * sizeof(double));
}
//! Copy one std integer vector into another
/*!
* This is an inlined function that uses memcpy. memcpy is probably
* the fastest way to do this. This routine requires the
*
* @param vec_to Vector to copy into. This vector must be dimensioned
* at least as large as the vec_from vector.
* @param vec_from Vector to copy from
* @param length Number of integers to copy.
*/
inline void vcs_vicopy(std::vector<int> & vec_to,
const std::vector<int> & vec_from, const int length)
{
(void) memcpy((void*)&(vec_to[0]), (const void*) &(vec_from[0]),
(length) * sizeof(int));
}
#else
extern void vcs_dzero(double* const, const int);
extern void vcs_izero(int* const , const int);
extern void vcs_dcopy(double* const, const double* const, const int);
extern void vcs_icopy(int* const, const int* const, const int);
extern void vcs_vdzero(std::vector<double> &vvv, const int len = -1);
extern void vcs_vizero(std::vector<double> &vvv, const int len = -1);
void vcs_vdcopy(std::vector<double> &vec_to,
const std::vector<double> vec_from, const int len = -1);
void vcs_vicopy(std::vector<int> &vec_to,
const std::vector<int> vec_from, const int len = -1);
#endif
//! determine the l2 norm of a vector of doubles
/*!
* @param vec vector of doubles
*
* @return Returns the l2 norm of the vector
*/
double vcs_l2norm(const std::vector<double> vec);
//! Finds the location of the maximum component in a double vector
/*!
* @param x pointer to a vector of doubles
* @param xSize pointer to a vector of doubles used as a multiplier
* to x[]
* @param j lowest index to search from
* @param n highest index to search from
* @return Return index of the greatest value on X(i) searched
* j <= i < n
*/
size_t vcs_optMax(const double* x, const double* xSize, size_t j, size_t n);
//! Returns the maximum integer in a list
/*!
* @param vector pointer to a vector of ints
* @param length length of the integer vector
*
* @return returns the max integer value in the list
*/
int vcs_max_int(const int* vector, int length);
//! Prints a line consisting of multiple occurrences of the same string
/*!
* This prints a string num times, and then terminate with a
* end of line character
*
* @param str C string that is null terminated
* @param num number of times the string is to be printed
*/
void vcs_print_line(const char* str, int num);
//! Returns a const char string representing the type of the
//! species given by the first argument
/*!
* @param speciesStatus Species status integer representing the type
* of the species.
* @param length Maximum length of the string to be returned.
* Shorter values will yield abbreviated strings.
* Defaults to a value of 100.
*/
const char* vcs_speciesType_string(int speciesStatus, int length = 100);
//! Print a string within a given space limit
/*!
* This routine limits the amount of the string that will be printed to a
* maximum of "space" characters. Printing is done to
* to Cantera's writelog() function.
*
* @param str String, which must be null terminated.
* @param space space limit for the printing.
* @param alignment Alignment of string within the space:
* - 0 centered
* - 1 right aligned
* - 2 left aligned
*/
void vcs_print_stringTrunc(const char* str, size_t space, int alignment);
//! Simple routine to check whether two doubles are equal up to
//! roundoff error
/*!
* Currently it's set to check for 10 digits of
* relative accuracy.
*
* @param d1 first double
* @param d2 second double
*
* @return returns true if the doubles are "equal" and false otherwise
*/
bool vcs_doubleEqual(double d1, double d2);
//! Sorts a vector of ints in place from lowest to the highest values
/*!
* The vector is returned sorted from lowest to highest.
*
* @param x Reference to a vector of ints.
*/
void vcs_heapsort(std::vector<int> &x);
//! Sorts a vector of ints and eliminates duplicates from the resulting list
/*!
* @param xOrderedUnique Ordered vector of unique ints that were part of the original list
* @param x Reference to a constant vector of ints.
*/
void vcs_orderedUnique(std::vector<int> & xOrderedUnique, const std::vector<int> & x);
}
#endif