void BackToBackExponential::function1D(double* out, const double* xValues, const size_t nData)const { /* const double& I = getParameter("I"); const double& a = getParameter("A"); const double& b = getParameter("B"); const double& x0 = getParameter("X0"); const double& s = getParameter("S"); */ const double I = getParameter(0); const double a = getParameter(1); const double b = getParameter(2); const double x0 = getParameter(3); const double s = getParameter(4); // find the reasonable extent of the peak ~100 fwhm double extent = expWidth(); if ( s > extent ) extent = s; extent *= 100; double s2 = s*s; double normFactor = a * b / (a + b) / 2; //Needed for IntegratePeaksMD for cylinder profile fitted with b=0 if (normFactor == 0.0) normFactor = 1.0; for (size_t i = 0; i < nData; i++) { double diff=xValues[i]-x0; if ( fabs(diff) < extent ) { double val = 0.0; double arg1 = a/2*(a*s2+2*diff); val += exp( arg1 + gsl_sf_log_erfc((a*s2+diff)/sqrt(2*s2)) ); //prevent overflow double arg2 = b/2*(b*s2-2*diff); val += exp( arg2 + gsl_sf_log_erfc((b*s2-diff)/sqrt(2*s2)) ); //prevent overflow out[i] = I*val*normFactor; } else out[i] = 0.0; } }
void IkedaCarpenterPV::functionLocal(double *out, const double *xValues, const size_t nData) const { const double I = getParameter("I"); const double alpha0 = getParameter("Alpha0"); const double alpha1 = getParameter("Alpha1"); const double beta0 = getParameter("Beta0"); const double kappa = getParameter("Kappa"); const double voigtsigmaSquared = getParameter("SigmaSquared"); const double voigtgamma = getParameter("Gamma"); const double X0 = getParameter("X0"); // cal pseudo voigt sigmaSq and gamma and eta double gamma = 1.0; // dummy initialization double eta = 0.5; // dummy initialization convertVoigtToPseudo(voigtsigmaSquared, voigtgamma, gamma, eta); double sigmaSquared = gamma * gamma / (8.0 * M_LN2); // pseudo voigt sigma^2 const double beta = 1 / beta0; // equations taken from Fullprof manual const double k = 0.05; // Not entirely sure what to do if sigmaSquared ever negative // for now just post a warning double someConst = std::numeric_limits<double>::max() / 100.0; if (sigmaSquared > 0) someConst = 1 / sqrt(2.0 * sigmaSquared); else if (sigmaSquared < 0) { g_log.warning() << "sigmaSquared negative in functionLocal.\n"; } // update wavelength vector calWavelengthAtEachDataPoint(xValues, nData); for (size_t i = 0; i < nData; i++) { double diff = xValues[i] - X0; double R = exp(-81.799 / (m_waveLength[i] * m_waveLength[i] * kappa)); double alpha = 1.0 / (alpha0 + m_waveLength[i] * alpha1); double a_minus = alpha * (1 - k); double a_plus = alpha * (1 + k); double x = a_minus - beta; double y = alpha - beta; double z = a_plus - beta; double Nu = 1 - R * a_minus / x; double Nv = 1 - R * a_plus / z; double Ns = -2 * (1 - R * alpha / y); double Nr = 2 * R * alpha * alpha * beta * k * k / (x * y * z); double u = a_minus * (a_minus * sigmaSquared - 2 * diff) / 2.0; double v = a_plus * (a_plus * sigmaSquared - 2 * diff) / 2.0; double s = alpha * (alpha * sigmaSquared - 2 * diff) / 2.0; double r = beta * (beta * sigmaSquared - 2 * diff) / 2.0; double yu = (a_minus * sigmaSquared - diff) * someConst; double yv = (a_plus * sigmaSquared - diff) * someConst; double ys = (alpha * sigmaSquared - diff) * someConst; double yr = (beta * sigmaSquared - diff) * someConst; std::complex<double> zs = std::complex<double>(-alpha * diff, 0.5 * alpha * gamma); std::complex<double> zu = (1 - k) * zs; std::complex<double> zv = (1 - k) * zs; std::complex<double> zr = std::complex<double>(-beta * diff, 0.5 * beta * gamma); double N = 0.25 * alpha * (1 - k * k) / (k * k); out[i] = I * N * ((1 - eta) * (Nu * exp(u + gsl_sf_log_erfc(yu)) + Nv * exp(v + gsl_sf_log_erfc(yv)) + Ns * exp(s + gsl_sf_log_erfc(ys)) + Nr * exp(r + gsl_sf_log_erfc(yr))) - eta * 2.0 / M_PI * (Nu * exponentialIntegral(zu).imag() + Nv * exponentialIntegral(zv).imag() + Ns * exponentialIntegral(zs).imag() + Nr * exponentialIntegral(zr).imag())); } }
static VALUE Error_log_erfc(VALUE self, VALUE x) { return rb_float_new(gsl_sf_log_erfc(NUM2DBL(x))); }