// Calculates the probability density of finding the particle at location z at // timepoint t, given that the particle is still in the domain. const Real FirstPassageGreensFunction1DRad::calcpcum (const Real r, const Real t) const { // BEWARE: HERE THERE IS SCALING OF R! const Real r_corr(r/this->l_scale); // p_survival is unscaled! return prob_r (r_corr, t)/p_survival (t); }
const Real GreensFunction2DAbs::drawR(const Real rnd, const Real t) const { THROW_UNLESS(std::invalid_argument, 0.0<=rnd && rnd <= 1.0); if(a == r0) throw std::invalid_argument("a equal r0"); if(t == 0e0 || D == 0e0) return r0; if(rnd == 1e0) return a;//!? Real p_surv(p_survival(t)); assert(p_surv > 0e0); p_r_params params = {this, t, rnd * p_surv}; gsl_function F = { reinterpret_cast<double (*)(double, void*)>(&p_r_F), ¶ms }; const Real low(0e0); const Real high(a); const gsl_root_fsolver_type* solverType(gsl_root_fsolver_brent); gsl_root_fsolver* solver(gsl_root_fsolver_alloc(solverType)); const Real r(findRoot(F, solver, low, high, 1e-18, 1e-12, "GreensFunction2DAbsSym::drawR")); gsl_root_fsolver_free(solver); return r; }
// Draws the position of the particle at a given time from p(r,t), assuming // that the particle is still in the domain Real GreensFunction1DAbsAbs::drawR (Real rnd, Real t) const { THROW_UNLESS( std::invalid_argument, 0.0 <= rnd && rnd < 1.0 ); THROW_UNLESS( std::invalid_argument, t >= 0.0 ); const Real a(this->geta()); const Real sigma(this->getsigma()); const Real L(this->geta() - this->getsigma()); const Real r0(this->getr0()); const Real D(this->getD()); const Real v(this->getv()); // the trivial case: if there was no movement or the domain was zero if ( (D==0.0 && v==0.0) || L<0.0 || t==0.0) { return r0; } else { // if the initial condition is at the boundary, raise an error // The particle can only be at the boundary in the ABOVE cases THROW_UNLESS( std::invalid_argument, (r0-sigma) >= L*EPSILON && (r0-sigma) <= L*(1.0-EPSILON) ); } // else the normal case // From here on the problem is well defined // structure to store the numbers to calculate numbers for 1-S(t) struct drawR_params parameters; Real S_Cn_An; Real nPI; const Real expo (-D*t/(L*L)); const Real r0s_L((r0-sigma)/L); const Real v2D(v/2.0/D); const Real Lv2D(L*v/2.0/D); const Real vexpo(-v*v*t/4.0/D - v*r0/2.0/D); // exponent of the drift-prefactor, same as in survival prob. const Real S = 2.0*exp(vexpo)/p_survival(t); // This is a prefactor to every term, so it also contains there // exponential drift-prefactor. // Construct the coefficients and the terms in the exponent and put them // in the params structure int n=0; do { nPI = ((Real)(n+1))*M_PI; // note: summation starting with n=1, indexing with n=0, therefore we need n+1 here if(v==0.0) S_Cn_An = S * exp(nPI*nPI*expo) * sin(nPI*r0s_L) / nPI; else S_Cn_An = S * exp(nPI*nPI*expo) * sin(nPI*r0s_L) * nPI/(nPI*nPI + Lv2D*Lv2D); // The rest is the z-dependent part, which has to be defined directly in drawR_f(z). // Of course also the summation happens there because the terms now are z-dependent. // The last term originates from the integrated prob. density including drift. // // In case of zero drift this expression becomes: 2.0/p_survival(t) * exp(nPI*nPI*expo) * sin(nPI*r0s_L) / nPI // also store the values for the exponent, so they don't have to be recalculated in drawR_f parameters.S_Cn_An[n]= S_Cn_An; parameters.n_L[n] = nPI/L; n++; } while (n<MAX_TERMS); // store the random number for the probability parameters.rnd = rnd ; // store the number of terms used parameters.terms = MAX_TERMS; // store needed constants parameters.H[0] = sigma; parameters.H[1] = v2D; // find the intersection on the y-axis between the random number and // the function gsl_function F; F.function = &drawR_f; F.params = ¶meters; // define a new solver type brent const gsl_root_fsolver_type* solverType( gsl_root_fsolver_brent ); // make a new solver instance // TODO: incl typecast? gsl_root_fsolver* solver( gsl_root_fsolver_alloc( solverType ) ); const Real r( findRoot( F, solver, sigma, a, L*EPSILON, EPSILON, "GreensFunction1DAbsAbs::drawR" ) ); // return the drawn time return r; }
// Calculates the probability density of finding the particle at location r at // timepoint t, given that the particle is still in the domain. Real GreensFunction1DAbsAbs::calcpcum (Real r, Real t) const { return prob_r(r, t) / p_survival(t); }
const Real GreensFunction2DAbsSym::drawR( const Real rnd, const Real t ) const { THROW_UNLESS( std::invalid_argument, rnd <= 1.0 && rnd >= 0.0 ); THROW_UNLESS( std::invalid_argument, t >= 0.0 ); const Real a( geta() ); const Real D( getD() ); if( a == 0.0 || t == 0.0 || D == 0.0 ) { return 0.0; } //const Real thresholdDistance( this->CUTOFF_H * sqrt( 4.0 * D * t ) ); gsl_function F; Real psurv; // if( a <= thresholdDistance ) // if the domain is not so big, the boundaries are felt // { psurv = p_survival( t ); //psurv = p_int_r( a, t ); //printf("dr %g %g\n",psurv, p_survival( t )); //assert( fabs(psurv - p_int_r( a, t )) < psurv * 1e-8 ); assert( psurv > 0.0 ); F.function = reinterpret_cast<double (*)(double, void*)>( &p_r_F ); /* } else // if the domain is very big, just use the free solution { // p_int_r < p_int_r_free if( p_int_r_free( a, t ) < rnd ) // if the particle is outside the domain? { std::cerr << "p_int_r_free( a, t ) < rnd, returning a." << std::endl; return a; } psurv = 1.0; F.function = reinterpret_cast<double (*)(double, void*)>( &p_r_free_F ); } */ const Real target( psurv * rnd ); p_r_params params = { this, t, target }; F.params = ¶ms; const Real low( 0.0 ); const Real high( a ); //const Real high( std::min( thresholdDistance, a ) ); const gsl_root_fsolver_type* solverType( gsl_root_fsolver_brent ); gsl_root_fsolver* solver( gsl_root_fsolver_alloc( solverType ) ); const Real r( findRoot( F, solver, low, high, 1e-18, 1e-12, "GreensFunction2DAbsSym::drawR" ) ); gsl_root_fsolver_free( solver ); return r; }
Real GreensFunction1DRadAbs::drawR (Real rnd, Real t) const { THROW_UNLESS( std::invalid_argument, 0.0 <= rnd && rnd < 1.0 ); THROW_UNLESS( std::invalid_argument, t >= 0.0 ); const Real sigma(this->getsigma()); const Real a(this->geta()); const Real L(this->geta()-this->getsigma()); const Real r0(this->getr0()); const Real D(this->getD()); const Real v(this->getv()); const Real k(this->getk()); const Real h((this->getk()+this->getv()/2.0)/this->getD()); if (t==0.0 || (D==0.0 && v==0.0) ) { // the trivial case //return r0*this->l_scale; // renormalized version, discontinued return r0; } if ( a<0.0 ) { // if the domain had zero size return 0.0; } // the structure to store the numbers to calculate the numbers for 1-S struct drawR_params parameters; double root_n = 0; double S_Cn_root_n; double root_n2, root_n_r0_s; const Real vexpo(-v*v*t/4.0/D - v*r0/2.0/D); // exponent of the drift-prefactor, same as in survival prob. const Real v2D(v/2.0/D); const Real v2Dv2D(v2D*v2D); const Real S = 2.0*exp(vexpo)/p_survival(t); // This is a prefactor to every term, so it also contains // the exponential drift-prefactor. // produce the coefficients and the terms in the exponent and put them // in the params structure for (int n=0; n<MAX_TERMS; n++) { root_n = this->root_n(n+1); // get the n-th root of tan(alfa*a)=alfa/-k root_n2 = root_n * root_n; root_n_r0_s = root_n * (r0-sigma); S_Cn_root_n = S * exp(-D*root_n2*t) * (root_n*cos(root_n_r0_s) + h*sin(root_n_r0_s)) / (L*(root_n2 + h*h) + h) * root_n / (root_n2 + v2Dv2D); // store the coefficients in the structure parameters.root_n[n] = root_n; // also store the values for the exponent parameters.S_Cn_root_n[n] = S_Cn_root_n; } // store the random number for the probability parameters.rnd = rnd; // store the number of terms used parameters.terms = MAX_TERMS; // also store constant prefactors that appear in the calculation of the // r-dependent terms parameters.H[0] = v2D; // appears together with z in one of the prefactors parameters.H[1] = k/D; // further constant terms of the cosine prefactor parameters.H[2] = h*v2D; // further constant terms of the sine prefactor parameters.H[3] = sigma; // find the intersection on the y-axis between the random number and // the function gsl_function F; F.function = &GreensFunction1DRadAbs::drawR_f; F.params = ¶meters; // define a new solver type brent const gsl_root_fsolver_type* solverType( gsl_root_fsolver_brent ); // make a new solver instance // TODO: incl typecast? gsl_root_fsolver* solver( gsl_root_fsolver_alloc( solverType ) ); Real r( findRoot( F, solver, sigma, a, EPSILON*L, EPSILON, "GreensFunction1DRadAbs::drawR" ) ); // return the drawn position return r; }
const Real FirstPassageGreensFunction1DRad::drawR (const Real rnd, const Real t) const { const Real L(this->getL()); const Real D(this->getD()); const Real r0(this->getr0()); THROW_UNLESS( std::invalid_argument, 0.0 <= rnd && rnd < 1.0 ); THROW_UNLESS( std::invalid_argument, t >= 0.0 ); if (t == 0.0 || D == 0) { // the trivial case return r0*this->l_scale; } if ( L < 0.0 ) { // if the domain had zero size return 0.0; } // the structure to store the numbers to calculate the numbers for 1-S struct drawR_params parameters; double An = 0; double S_Cn_An; double tmp0, tmp1; const Real h(this->getk()/D); const Real S = 2.0/p_survival(t); // produce the coefficients and the terms in the exponent and put them // in the params structure for (int n=0; n<MAX_TERMEN; n++) { An = a_n (n+1); // get the n-th root of tan(alfa*L)=alfa/-k tmp0 = An * An; // An^2 tmp1 = An * r0; // An * z' S_Cn_An = S * exp(-D*tmp0*t) * (An*cos(tmp1) + h*sin(tmp1)) / (L*(tmp0 + h*h) + h); // store the coefficients in the structure parameters.An[n] = An; // also store the values for the exponent parameters.S_Cn_An[n]= S_Cn_An; parameters.b_An[n] = h/An; } // store the random number for the probability parameters.rnd = rnd; // store the number of terms used parameters.terms = MAX_TERMEN; // find the intersection on the y-axis between the random number and // the function gsl_function F; F.function = &FirstPassageGreensFunction1DRad::drawR_f; F.params = ¶meters; // define a new solver type brent const gsl_root_fsolver_type* solverType( gsl_root_fsolver_brent ); // make a new solver instance // incl typecast? gsl_root_fsolver* solver( gsl_root_fsolver_alloc( solverType ) ); const Real z( findRoot( F, solver, 0.0, L, EPSILON*L, EPSILON, "FirstPassageGreensFunction1DRad::drawR" ) ); // return the drawn place return z*this->l_scale; }