#ifndef generators_IS_INCLUDED #define generators_IS_INCLUDED #include #include #include "Rnd.h" //Included from Gnu Scientific Library: #include //Provides mathematical constants and elemetary //mathematical functions. #include //Provides evaluation of the error function. using namespace std; /* List of constructor prototypes and short descriptions of parameters: * * ---------------------------------------------------------------------- * Envelope1(unsigned long int s1, unsigned long int s2); * * (two seeds to random number generators) * * ---------------------------------------------------------------------- * Envelope2(unsigned long int s1, unsigned long int s2 * unsigned long int s3); * * (three seeds to random number generators) * * ---------------------------------------------------------------------- * Envelope3(unsigned long int s1, unsigned long int s2 * unsigned long int s3, unsigned long int s4); * * (four seeds to random number generators) * * ---------------------------------------------------------------------- * Envelope4(unsigned long int s1, unsigned long int s2 * unsigned long int s3, unsigned long int s4); * * (four seeds to random number generators) * * ---------------------------------------------------------------------- * InversionMethod(double _error, unsigned long int s1); * * (_error: absolute error for the Newton iteration, * s1: seed to the random number generator) * * ---------------------------------------------------------------------- * BoxEnvelope(double _zLTa, double _zGTa, * unsigned long int s1, unsigned long int s2 ); * * (_zLTa: should be set to min(a - alpha1, -alpha2) * _zGTa: should be set to min(a, alpha2) * where alpha1 = 1 or 2, * alpha2 = 3, * a = V.e/sqrt(2T) (fractional fluid velocity * along surface normal vector) * s1, s2: two seeds to random number generators) * * ---------------------------------------------------------------------- * ReservoirEnvelope(double _zLTa, * unsigned long int s1, unsigned long int s2 ); * * (_zLTa: should be set to min(a - 1, -alphaR) * where alphaR = 3 * a = V.e/sqrt(2T) (fractional fluid velocity * along surface normal vector) * s1, s2: two seeds to random number generators) * */ // List of generator type identyfiers const unsigned int envelope1 = 0x0; const unsigned int envelope2 = 0x1; const unsigned int envelope3 = 0x2; const unsigned int envelope4 = 0x3; const unsigned int inversionMethod = 0x4; const unsigned int boxEnvelope = 0x5; const unsigned int reservoirEnvelope = 0x6; // Base class for generator structs struct Generator { double a; virtual void set(double _a) {}; virtual unsigned int isType() {return 0;} double generate() {return 0;} }; struct Envelope1 : public Generator { //Unique type specifier unsigned int isType() {return envelope1;} //Generator-specific variables double aa; Rnd rnd1, rnd2; //Constructor Envelope1(unsigned long int s1, unsigned long int s2) : rnd1(s1), rnd2(s2) {} void set(double _a) { a = _a; aa = _a*_a; } //The generator inline double generate() { double result; while(true) { result = -sqrt(aa - log(rnd1.getUniform())); if ((result-a)/result > rnd2.getUniform()) return result; } } }; // end struct Envelope1 struct Envelope2 : public Generator { //Unique type specifier unsigned int isType() {return envelope2;} //Generator-specific variables double z_a, beta_a, z_a_2, beta_a_2, aMz_aINV, aMbeta_a, c; Rnd rnd1, rnd2, rnd3; //Constructor Envelope2(unsigned long int s1, unsigned long int s2, unsigned long int s3) : rnd1(s1), rnd2(s2), rnd3(s3) { } void set(double _a) { a = _a; z_a = 0.5*(a - sqrt(a*a + 2)); beta_a = a - (1 - a)*(a - z_a); z_a_2 = z_a*z_a; beta_a_2 = beta_a*beta_a; double aMz_a = a - z_a; aMz_aINV = 1./aMz_a; aMbeta_a = a - beta_a; c = exp(-beta_a_2)/(exp(-beta_a_2) + 2*aMz_a*aMbeta_a*exp(-z_a_2)); } //The generator inline double generate() { double result; while(true) { if (c > rnd1.getUniform()) { result = -sqrt(beta_a_2 - log(rnd2.getUniform())); if ((result-a)/result > rnd3.getUniform()) return result; } else { result = beta_a + aMbeta_a*rnd2.getUniform(); if ((a-result)*aMz_aINV*exp(z_a_2 - result*result) > rnd3.getUniform()) return result; } } } }; // end struct Envelope2 struct Envelope3 : public Generator { //Unique type specifier unsigned int isType() {return envelope3;} //Generator-specific variables double c1, c2; Rnd rnd1, rnd2, rnd3, rnd4; //Constructor Envelope3(unsigned long int s1, unsigned long int s2, unsigned long int s3, unsigned long int s4 ) : rnd1(s1), rnd2(s2), rnd3(s3), rnd4(s4) {} void set(double _a) { a = _a; c1 = a*M_SQRTPI/(a*M_SQRTPI + 1 + a*a); c2 = (a*M_SQRTPI + 1)/(a*M_SQRTPI + 1 + a*a); /* gsl-specific content: * const double M_SQRTPI; (square root of pi) */ } //The generator inline double generate() { double res; while(true) { res = rnd1.getUniform(); if (c1 > res) return -fabs(rnd2.getGaussian(M_SQRT1_2)); /* gsl-specific content: * const double M_SQRT1_2; (square root of 0.5) */ else if (c2 > res) return -sqrt(-log(rnd3.getUniform())); else { res = (1 - sqrt(rnd3.getUniform()))*a; if (exp(-res*res) > rnd4.getUniform()) return res; } } } }; // end struct Envelope3 struct Envelope4 : public Generator { //Unique type specifier unsigned int isType() {return envelope4;} //Generator-specific variables double aINV, c; Rnd rnd1, rnd2, rnd3, rnd4; //Constructor Envelope4(unsigned long int s1, unsigned long int s2, unsigned long int s3, unsigned long int s4 ) : rnd1(s1), rnd2(s2), rnd3(s3), rnd4(s4) {} void set(double _a) { a = _a; aINV = 1./a; c = 1/(2*a*M_SQRTPI + 1); /* gsl-specific content: * const double M_SQRTPI; (square root of pi) */ } //The generator inline double generate() { double result; while(true) { if (c > rnd1.getUniform()) result = -sqrt(-log(rnd2.getUniform())); else result = rnd3.getGaussian(M_SQRT1_2); /* gsl-specific content: * const double M_SQRT1_2; (square root of 0.5) */ if ((a - result)*aINV > rnd4.getUniform()) return result; } } }; // end struct Envelope4 struct InversionMethod : public Generator { //Unique type specifier unsigned int isType() {return inversionMethod;} //Generator-specific variables double error, m_a, m_aINV, c, z0; Rnd rnd1; //Constructor InversionMethod(double _error, unsigned long int s1) : error(_error), rnd1(s1) {} void set(double _a) { a = _a; m_a = exp(-a*a) + a*M_SQRTPI*(1 + gsl_sf_erf(a)); m_aINV = 1./m_a; c = a*M_SQRTPI; z0 = 0.5*(a - sqrt(a*a +2)); /* gsl-specific content: * const double M_SQRTPI; (square root of pi) */ } //The generator inline double generate() { double u = rnd1.getUniform(); //Initial guess double z = z0; double errorCurrent; while ( fabs(errorCurrent = (exp(-z*z) + c*(1 + gsl_sf_erf(z)))*m_aINV - u) >= error) z -= errorCurrent*m_a/(2*(a - z)*exp(-z*z)); /* gsl-specific content: * double gsl_sf_erf(double); (the error function) */ return z; } }; // end struct InversionMethod struct BoxEnvelope : public Generator { //Unique type specifier unsigned int isType() {return boxEnvelope;} //Generator-specific variables double zLTa, zGTa, aMz_aINV, z_a_2, c; Rnd rnd1, rnd2; //Constructor BoxEnvelope(double _zLTa, double _zGTa, unsigned long int s1, unsigned long int s2 ) : zLTa(_zLTa), zGTa(_zGTa), rnd1(s1), rnd2(s2) {} void set(double _a) { double z_a = 0.5*(a - sqrt(a*a +2)); aMz_aINV = 1./(a - z_a); z_a_2 = z_a*z_a; c = zGTa - zLTa; } //The generator inline double generate() { double z; do z = zLTa + c*rnd1.getUniform(); while ((a - z)*aMz_aINV*exp(z_a_2 - z*z) <= rnd2.getUniform()); return z; } }; // end struct BoxEnvelope4 struct ReservoirEnvelope : public Generator { //Unique type specifier unsigned int isType() {return reservoirEnvelope;} //Generator-specific variables double zLTa, c; Rnd rnd1, rnd2; //Constructor ReservoirEnvelope(double _zLTa, unsigned long int s1, unsigned long int s2 ) : zLTa(_zLTa), rnd1(s1), rnd2(s2) {} void set(double _a) { a = _a; c = 1./(a - zLTa); } //The generator inline double generate() { double result; do if (a <= 0) result = -fabs(rnd1.getGaussian(M_SQRT1_2)); else result = rnd1.getGaussian(M_SQRT1_2); while ( (a-result)*c <= rnd2.getUniform() ); /* gsl-specific content: * const double M_SQRT1_2; (square root of 0.5) */ return result; } }; // end struct ReservoirEnvelope #endif