307 const double voigtSigmaSq =
getParameter(
"SigmaSquared");
311 double H = 1.0, eta = 0.5;
314 const double eps = std::numeric_limits<double>::epsilon() * 1000.0;
315 const double Hsafe = std::max(H, eps);
316 const double Hsafe2 = Hsafe * Hsafe;
317 const double S = std::max(Hsafe2 / (8.0 * M_LN2), eps);
318 const double beta = 1.0 / beta0;
319 const double beta2 = beta * beta;
321 constexpr double k = 0.05;
322 constexpr double kk = k * k;
323 constexpr double one_minus_k = 1.0 - k;
324 constexpr double one_plus_k = 1.0 + k;
325 const double one_minus_eta = 1.0 - eta;
326 constexpr double twoOverPi = 2.0 / M_PI;
327 const double etaTwoOverPi = eta * twoOverPi;
328 const double halfHsafe = 0.5 * Hsafe;
329 const double halfH2 = halfHsafe * halfHsafe;
331 const double invRoot2S = 1.0 / std::sqrt(2.0 * S);
332 const double rootSOver2 = std::sqrt(S / 2.0);
333 const double twoInvSqrtPi = 2.0 / std::sqrt(M_PI);
334 const double CexpSFactor = invRoot2S / (2.0 * S);
337 const double g2 = std::max(8.0 * M_LN2 * voigtSigmaSq, eps);
338 const double g = std::sqrt(g2);
339 const double g3 = g2 * g;
340 const double g4 = g2 * g2;
342 const double L = voigtGamma;
343 const double L2 = L * L;
344 const double L3 = L2 * L;
345 const double L4 = L2 * L2;
347 constexpr double c1 = 2.69269, c2 = 2.42843, c3 = 4.47163, c4 = 0.07842;
349 const double H4 = Hsafe2 * Hsafe2;
350 const double inv5H4 = 1.0 / (5.0 * std::max(H4, eps));
352 const double dPdg = 5.0 * g4 + 4.0 * c1 * g3 * L + 3.0 * c2 * g2 * L2 + 2.0 * c3 * g * L3 + c4 * L4;
353 const double dPdL = c1 * g4 + 2.0 * c2 * g3 * L + 3.0 * c3 * g2 * L2 + 4.0 * c4 * g * L3 + 5.0 * L4;
355 const double dgdV = (4.0 * M_LN2) / g;
356 const double dHdV = dPdg * dgdV * inv5H4;
357 const double dHdL = dPdL * inv5H4;
359 const double t = L / Hsafe;
360 const double deta_dt = 1.36603 - 0.95438 * t + 0.33348 * t * t;
361 const double invHsafe2 = 1.0 / Hsafe2;
363 const double deta_dV = deta_dt * (-L * dHdV * invHsafe2);
364 const double deta_dL = deta_dt * (1.0 / Hsafe - L * dHdL * invHsafe2);
366 const double inv4Ln2 = 1.0 / (4.0 * M_LN2);
367 const double dSdV = Hsafe * dHdV * inv4Ln2;
368 const double dSdL = Hsafe * dHdL * inv4Ln2;
370 const double kappa2_inv = 1.0 / (kappa * kappa);
374 for (
size_t i = 0; i < nData; ++i) {
377 const double diff = xValues[i] - X0;
378 const double diff2 = diff * diff;
380 const double R = std::exp(-81.799 / (lambda2 * kappa));
381 const double alpha = 1.0 / (alpha0 +
lambda * alpha1);
382 const double alpha2 = alpha * alpha;
384 const double a_minus = alpha * one_minus_k;
385 const double a_plus = alpha * one_plus_k;
387 const double x = a_minus - beta;
388 const double y = alpha - beta;
389 const double z = a_plus - beta;
391 const double inv_x = 1.0 /
x;
392 const double inv_y = 1.0 /
y;
393 const double inv_z = 1.0 /
z;
394 const double inv_x2 = inv_x * inv_x;
395 const double inv_y2 = inv_y * inv_y;
396 const double inv_z2 = inv_z * inv_z;
398 const double Nu = 1.0 - R * a_minus * inv_x;
399 const double Nv = 1.0 - R * a_plus * inv_z;
400 const double Ns = -2.0 * (1.0 - R * alpha * inv_y);
401 const double Nr = 2.0 * R * alpha2 * beta * kk * inv_x * inv_y * inv_z;
404 const double amuS_d = a_minus * S - diff;
405 const double apuS_d = a_plus * S - diff;
406 const double alS_d = alpha * S - diff;
407 const double beS_d = beta * S - diff;
409 const double u = 0.5 * a_minus * (amuS_d - diff);
410 const double v = 0.5 * a_plus * (apuS_d - diff);
411 const double s = 0.5 * alpha * (alS_d - diff);
412 const double r = 0.5 * beta * (beS_d - diff);
414 const double yu = amuS_d * invRoot2S;
415 const double yv = apuS_d * invRoot2S;
416 const double ys = alS_d * invRoot2S;
417 const double yr = beS_d * invRoot2S;
419 const double Ku = std::exp(u + gsl_sf_log_erfc(yu));
420 const double Kv = std::exp(v + gsl_sf_log_erfc(yv));
421 const double Ks = std::exp(s + gsl_sf_log_erfc(ys));
422 const double Kr = std::exp(r + gsl_sf_log_erfc(yr));
425 const std::complex<double> zu(-a_minus * diff, a_minus * halfHsafe);
426 const std::complex<double> zv(-a_plus * diff, a_plus * halfHsafe);
427 const std::complex<double> zs(-alpha * diff, alpha * halfHsafe);
428 const std::complex<double> zr(-beta * diff, beta * halfHsafe);
435 const double Ju = Fu.imag();
436 const double Jv = Fv.imag();
437 const double Js = Fs.imag();
438 const double Jr = Fr.imag();
443 const double inv_d2h2 = 1.0 / (diff2 + halfH2);
444 const double d_term = diff * inv_d2h2;
445 const double h_term = halfHsafe * inv_d2h2;
447 const double Fpu_r = Fu.real() + d_term / a_minus;
448 const double Fpu_i = Fu.imag() + h_term / a_minus;
449 const double Fpv_r = Fv.real() + d_term / a_plus;
450 const double Fpv_i = Fv.imag() + h_term / a_plus;
451 const double Fps_r = Fs.real() + d_term / alpha;
452 const double Fps_i = Fs.imag() + h_term / alpha;
453 const double Fpr_r = Fr.real() + d_term / beta;
454 const double Fpr_i = Fr.imag() + h_term / beta;
457 const double Q = 0.25 * alpha * (1.0 - kk) / kk;
458 const double IQ = I * Q;
460 const double G = Nu * Ku + Nv * Kv + Ns * Ks + Nr * Kr;
461 const double Lmix = Nu * Ju + Nv * Jv + Ns * Js + Nr * Jr;
462 const double modelCore = one_minus_eta * G - etaTwoOverPi * Lmix;
465 const double Cexp = twoInvSqrtPi * std::exp(-diff2 / (2.0 * S));
466 const double CexpRS2 = Cexp * rootSOver2;
470 const double dKu_da = amuS_d * Ku - CexpRS2;
471 const double dKv_da = apuS_d * Kv - CexpRS2;
472 const double dKs_da = alS_d * Ks - CexpRS2;
473 const double dKr_da = beS_d * Kr - CexpRS2;
476 const double dKu_dS = 0.5 * a_minus * a_minus * Ku - Cexp * (a_minus * S + diff) * CexpSFactor;
477 const double dKv_dS = 0.5 * a_plus * a_plus * Kv - Cexp * (a_plus * S + diff) * CexpSFactor;
478 const double dKs_dS = 0.5 * alpha2 * Ks - Cexp * (alpha * S + diff) * CexpSFactor;
479 const double dKr_dS = 0.5 * beta2 * Kr - Cexp * (beta * S + diff) * CexpSFactor;
482 const double CexpIR2S = Cexp * invRoot2S;
483 const double dKu_dd = -a_minus * Ku + CexpIR2S;
484 const double dKv_dd = -a_plus * Kv + CexpIR2S;
485 const double dKs_dd = -alpha * Ks + CexpIR2S;
486 const double dKr_dd = -beta * Kr + CexpIR2S;
490 const double dJu_da = Fpu_r * halfHsafe - Fpu_i * diff;
491 const double dJv_da = Fpv_r * halfHsafe - Fpv_i * diff;
492 const double dJs_da = Fps_r * halfHsafe - Fps_i * diff;
493 const double dJr_da = Fpr_r * halfHsafe - Fpr_i * diff;
496 const double dJu_dH = 0.5 * a_minus * Fpu_r;
497 const double dJv_dH = 0.5 * a_plus * Fpv_r;
498 const double dJs_dH = 0.5 * alpha * Fps_r;
499 const double dJr_dH = 0.5 * beta * Fpr_r;
502 const double dJu_dd = -a_minus * Fpu_i;
503 const double dJv_dd = -a_plus * Fpv_i;
504 const double dJs_dd = -alpha * Fps_i;
505 const double dJr_dd = -beta * Fpr_i;
508 const double Rbeta = R * beta;
509 const double dNu_dalpha = Rbeta * one_minus_k * inv_x2;
510 const double dNv_dalpha = Rbeta * one_plus_k * inv_z2;
511 const double dNs_dalpha = -2.0 * Rbeta * inv_y2;
512 const double dNr_dalpha = Nr * (2.0 / alpha - one_minus_k * inv_x - inv_y - one_plus_k * inv_z);
514 const double dNu_dbeta = -R * a_minus * inv_x2;
515 const double dNv_dbeta = -R * a_plus * inv_z2;
516 const double dNs_dbeta = 2.0 * R * alpha * inv_y2;
517 const double dNr_dbeta = Nr * (1.0 / beta + inv_x + inv_y + inv_z);
519 const double dNu_dR = -a_minus * inv_x;
520 const double dNv_dR = -a_plus * inv_z;
521 const double dNs_dR = 2.0 * alpha * inv_y;
522 const double dNr_dR = 2.0 * alpha2 * beta * kk * inv_x * inv_y * inv_z;
526 const double dG_dalpha = dNu_dalpha * Ku + Nu * one_minus_k * dKu_da + dNv_dalpha * Kv + Nv * one_plus_k * dKv_da +
527 dNs_dalpha * Ks + Ns * dKs_da + dNr_dalpha * Kr;
529 const double dL_dalpha = dNu_dalpha * Ju + Nu * one_minus_k * dJu_da + dNv_dalpha * Jv + Nv * one_plus_k * dJv_da +
530 dNs_dalpha * Js + Ns * dJs_da + dNr_dalpha * Jr;
533 const double dG_dbeta = dNu_dbeta * Ku + dNv_dbeta * Kv + dNs_dbeta * Ks + dNr_dbeta * Kr + Nr * dKr_da;
535 const double dL_dbeta = dNu_dbeta * Ju + dNv_dbeta * Jv + dNs_dbeta * Js + dNr_dbeta * Jr + Nr * dJr_da;
538 const double dG_dR = dNu_dR * Ku + dNv_dR * Kv + dNs_dR * Ks + dNr_dR * Kr;
539 const double dL_dR = dNu_dR * Ju + dNv_dR * Jv + dNs_dR * Js + dNr_dR * Jr;
542 const double dG_dS = Nu * dKu_dS + Nv * dKv_dS + Ns * dKs_dS + Nr * dKr_dS;
545 const double dL_dH = Nu * dJu_dH + Nv * dJv_dH + Ns * dJs_dH + Nr * dJr_dH;
548 const double dG_dd = Nu * dKu_dd + Nv * dKv_dd + Ns * dKs_dd + Nr * dKr_dd;
549 const double dL_dd = Nu * dJu_dd + Nv * dJv_dd + Ns * dJs_dd + Nr * dJr_dd;
552 const double df_dI = Q * modelCore;
553 const double df_dalpha = I * (Q / alpha * modelCore + Q * (one_minus_eta * dG_dalpha - etaTwoOverPi * dL_dalpha));
554 const double df_dbeta = IQ * (one_minus_eta * dG_dbeta - etaTwoOverPi * dL_dbeta);
555 const double df_dR = IQ * (one_minus_eta * dG_dR - etaTwoOverPi * dL_dR);
556 const double df_dS = IQ * one_minus_eta * dG_dS;
557 const double df_dH = -IQ * etaTwoOverPi * dL_dH;
558 const double df_deta = -IQ * (G + twoOverPi * Lmix);
559 const double df_ddiff = IQ * (one_minus_eta * dG_dd - etaTwoOverPi * dL_dd);
562 const double neg_alpha2 = -alpha2;
563 jacobian->
set(i, 0, df_dI);
564 jacobian->
set(i, 1, df_dalpha * neg_alpha2);
565 jacobian->
set(i, 2, df_dalpha * neg_alpha2 *
lambda);
566 jacobian->
set(i, 3, df_dbeta * (-beta2));
567 jacobian->
set(i, 4, df_dR * R * 81.799 * kappa2_inv / lambda2);
568 jacobian->
set(i, 5, df_dS * dSdV + df_dH * dHdV + df_deta * deta_dV);
569 jacobian->
set(i, 6, df_dS * dSdL + df_dH * dHdL + df_deta * deta_dL);
570 jacobian->
set(i, 7, -df_ddiff);