324 const double voigtSigmaSq =
getParameter(
"SigmaSquared");
328 double H = 1.0, eta = 0.5;
331 const double eps = std::numeric_limits<double>::epsilon() * 1000.0;
332 const double Hsafe = std::max(H, eps);
333 const double Hsafe2 = Hsafe * Hsafe;
334 const double S = std::max(Hsafe2 / (8.0 * M_LN2), eps);
335 const double beta = 1.0 / beta0;
336 const double beta2 = beta * beta;
338 constexpr double k = 0.05;
339 constexpr double kk = k * k;
340 constexpr double one_minus_k = 1.0 - k;
341 constexpr double one_plus_k = 1.0 + k;
342 const double one_minus_eta = 1.0 - eta;
343 constexpr double twoOverPi = 2.0 / M_PI;
344 const double etaTwoOverPi = eta * twoOverPi;
345 const double halfHsafe = 0.5 * Hsafe;
346 const double halfH2 = halfHsafe * halfHsafe;
348 const double invRoot2S = 1.0 / std::sqrt(2.0 * S);
349 const double rootSOver2 = std::sqrt(S / 2.0);
350 const double twoInvSqrtPi = 2.0 / std::sqrt(M_PI);
351 const double CexpSFactor = invRoot2S / (2.0 * S);
354 const double g2 = std::max(8.0 * M_LN2 * voigtSigmaSq, eps);
355 const double g = std::sqrt(g2);
356 const double g3 = g2 * g;
357 const double g4 = g2 * g2;
359 const double L = voigtGamma;
360 const double L2 = L * L;
361 const double L3 = L2 * L;
362 const double L4 = L2 * L2;
364 constexpr double c1 = 2.69269, c2 = 2.42843, c3 = 4.47163, c4 = 0.07842;
366 const double H4 = Hsafe2 * Hsafe2;
367 const double inv5H4 = 1.0 / (5.0 * std::max(H4, eps));
369 const double dPdg = 5.0 * g4 + 4.0 * c1 * g3 * L + 3.0 * c2 * g2 * L2 + 2.0 * c3 * g * L3 + c4 * L4;
370 const double dPdL = c1 * g4 + 2.0 * c2 * g3 * L + 3.0 * c3 * g2 * L2 + 4.0 * c4 * g * L3 + 5.0 * L4;
372 const double dgdV = (4.0 * M_LN2) / g;
373 const double dHdV = dPdg * dgdV * inv5H4;
374 const double dHdL = dPdL * inv5H4;
376 const double t = L / Hsafe;
377 const double deta_dt = 1.36603 - 0.95438 * t + 0.33348 * t * t;
378 const double invHsafe2 = 1.0 / Hsafe2;
380 const double deta_dV = deta_dt * (-L * dHdV * invHsafe2);
381 const double deta_dL = deta_dt * (1.0 / Hsafe - L * dHdL * invHsafe2);
383 const double inv4Ln2 = 1.0 / (4.0 * M_LN2);
384 const double dSdV = Hsafe * dHdV * inv4Ln2;
385 const double dSdL = Hsafe * dHdL * inv4Ln2;
387 const double kappa2_inv = 1.0 / (kappa * kappa);
391 for (
size_t i = 0; i < nData; ++i) {
394 const double diff = xValues[i] - X0;
395 const double diff2 = diff * diff;
397 const double R = std::exp(-81.799 / (lambda2 * kappa));
398 const double alpha = 1.0 / (alpha0 +
lambda * alpha1);
399 const double alpha2 = alpha * alpha;
401 const double a_minus = alpha * one_minus_k;
402 const double a_plus = alpha * one_plus_k;
404 const double x = a_minus - beta;
405 const double y = alpha - beta;
406 const double z = a_plus - beta;
408 const double inv_x = 1.0 /
x;
409 const double inv_y = 1.0 /
y;
410 const double inv_z = 1.0 /
z;
411 const double inv_x2 = inv_x * inv_x;
412 const double inv_y2 = inv_y * inv_y;
413 const double inv_z2 = inv_z * inv_z;
415 const double Nu = 1.0 - R * a_minus * inv_x;
416 const double Nv = 1.0 - R * a_plus * inv_z;
417 const double Ns = -2.0 * (1.0 - R * alpha * inv_y);
418 const double Nr = 2.0 * R * alpha2 * beta * kk * inv_x * inv_y * inv_z;
421 const double amuS_d = a_minus * S - diff;
422 const double apuS_d = a_plus * S - diff;
423 const double alS_d = alpha * S - diff;
424 const double beS_d = beta * S - diff;
426 const double u = 0.5 * a_minus * (amuS_d - diff);
427 const double v = 0.5 * a_plus * (apuS_d - diff);
428 const double s = 0.5 * alpha * (alS_d - diff);
429 const double r = 0.5 * beta * (beS_d - diff);
431 const double yu = amuS_d * invRoot2S;
432 const double yv = apuS_d * invRoot2S;
433 const double ys = alS_d * invRoot2S;
434 const double yr = beS_d * invRoot2S;
436 const double Ku = std::exp(u + gsl_sf_log_erfc(yu));
437 const double Kv = std::exp(v + gsl_sf_log_erfc(yv));
438 const double Ks = std::exp(s + gsl_sf_log_erfc(ys));
439 const double Kr = std::exp(r + gsl_sf_log_erfc(yr));
442 const std::complex<double> zu(-a_minus * diff, a_minus * halfHsafe);
443 const std::complex<double> zv(-a_plus * diff, a_plus * halfHsafe);
444 const std::complex<double> zs(-alpha * diff, alpha * halfHsafe);
445 const std::complex<double> zr(-beta * diff, beta * halfHsafe);
452 const double Ju = Fu.imag();
453 const double Jv = Fv.imag();
454 const double Js = Fs.imag();
455 const double Jr = Fr.imag();
460 const double inv_d2h2 = 1.0 / (diff2 + halfH2);
461 const double d_term = diff * inv_d2h2;
462 const double h_term = halfHsafe * inv_d2h2;
464 const double Fpu_r = Fu.real() + d_term / a_minus;
465 const double Fpu_i = Fu.imag() + h_term / a_minus;
466 const double Fpv_r = Fv.real() + d_term / a_plus;
467 const double Fpv_i = Fv.imag() + h_term / a_plus;
468 const double Fps_r = Fs.real() + d_term / alpha;
469 const double Fps_i = Fs.imag() + h_term / alpha;
470 const double Fpr_r = Fr.real() + d_term / beta;
471 const double Fpr_i = Fr.imag() + h_term / beta;
474 const double Q = 0.25 * alpha * (1.0 - kk) / kk;
475 const double IQ = I * Q;
477 const double G = Nu * Ku + Nv * Kv + Ns * Ks + Nr * Kr;
478 const double Lmix = Nu * Ju + Nv * Jv + Ns * Js + Nr * Jr;
479 const double modelCore = one_minus_eta * G - etaTwoOverPi * Lmix;
482 const double Cexp = twoInvSqrtPi * std::exp(-diff2 / (2.0 * S));
483 const double CexpRS2 = Cexp * rootSOver2;
487 const double dKu_da = amuS_d * Ku - CexpRS2;
488 const double dKv_da = apuS_d * Kv - CexpRS2;
489 const double dKs_da = alS_d * Ks - CexpRS2;
490 const double dKr_da = beS_d * Kr - CexpRS2;
493 const double dKu_dS = 0.5 * a_minus * a_minus * Ku - Cexp * (a_minus * S + diff) * CexpSFactor;
494 const double dKv_dS = 0.5 * a_plus * a_plus * Kv - Cexp * (a_plus * S + diff) * CexpSFactor;
495 const double dKs_dS = 0.5 * alpha2 * Ks - Cexp * (alpha * S + diff) * CexpSFactor;
496 const double dKr_dS = 0.5 * beta2 * Kr - Cexp * (beta * S + diff) * CexpSFactor;
499 const double CexpIR2S = Cexp * invRoot2S;
500 const double dKu_dd = -a_minus * Ku + CexpIR2S;
501 const double dKv_dd = -a_plus * Kv + CexpIR2S;
502 const double dKs_dd = -alpha * Ks + CexpIR2S;
503 const double dKr_dd = -beta * Kr + CexpIR2S;
507 const double dJu_da = Fpu_r * halfHsafe - Fpu_i * diff;
508 const double dJv_da = Fpv_r * halfHsafe - Fpv_i * diff;
509 const double dJs_da = Fps_r * halfHsafe - Fps_i * diff;
510 const double dJr_da = Fpr_r * halfHsafe - Fpr_i * diff;
513 const double dJu_dH = 0.5 * a_minus * Fpu_r;
514 const double dJv_dH = 0.5 * a_plus * Fpv_r;
515 const double dJs_dH = 0.5 * alpha * Fps_r;
516 const double dJr_dH = 0.5 * beta * Fpr_r;
519 const double dJu_dd = -a_minus * Fpu_i;
520 const double dJv_dd = -a_plus * Fpv_i;
521 const double dJs_dd = -alpha * Fps_i;
522 const double dJr_dd = -beta * Fpr_i;
525 const double Rbeta = R * beta;
526 const double dNu_dalpha = Rbeta * one_minus_k * inv_x2;
527 const double dNv_dalpha = Rbeta * one_plus_k * inv_z2;
528 const double dNs_dalpha = -2.0 * Rbeta * inv_y2;
529 const double dNr_dalpha = Nr * (2.0 / alpha - one_minus_k * inv_x - inv_y - one_plus_k * inv_z);
531 const double dNu_dbeta = -R * a_minus * inv_x2;
532 const double dNv_dbeta = -R * a_plus * inv_z2;
533 const double dNs_dbeta = 2.0 * R * alpha * inv_y2;
534 const double dNr_dbeta = Nr * (1.0 / beta + inv_x + inv_y + inv_z);
536 const double dNu_dR = -a_minus * inv_x;
537 const double dNv_dR = -a_plus * inv_z;
538 const double dNs_dR = 2.0 * alpha * inv_y;
539 const double dNr_dR = 2.0 * alpha2 * beta * kk * inv_x * inv_y * inv_z;
543 const double dG_dalpha = dNu_dalpha * Ku + Nu * one_minus_k * dKu_da + dNv_dalpha * Kv + Nv * one_plus_k * dKv_da +
544 dNs_dalpha * Ks + Ns * dKs_da + dNr_dalpha * Kr;
546 const double dL_dalpha = dNu_dalpha * Ju + Nu * one_minus_k * dJu_da + dNv_dalpha * Jv + Nv * one_plus_k * dJv_da +
547 dNs_dalpha * Js + Ns * dJs_da + dNr_dalpha * Jr;
550 const double dG_dbeta = dNu_dbeta * Ku + dNv_dbeta * Kv + dNs_dbeta * Ks + dNr_dbeta * Kr + Nr * dKr_da;
552 const double dL_dbeta = dNu_dbeta * Ju + dNv_dbeta * Jv + dNs_dbeta * Js + dNr_dbeta * Jr + Nr * dJr_da;
555 const double dG_dR = dNu_dR * Ku + dNv_dR * Kv + dNs_dR * Ks + dNr_dR * Kr;
556 const double dL_dR = dNu_dR * Ju + dNv_dR * Jv + dNs_dR * Js + dNr_dR * Jr;
559 const double dG_dS = Nu * dKu_dS + Nv * dKv_dS + Ns * dKs_dS + Nr * dKr_dS;
562 const double dL_dH = Nu * dJu_dH + Nv * dJv_dH + Ns * dJs_dH + Nr * dJr_dH;
565 const double dG_dd = Nu * dKu_dd + Nv * dKv_dd + Ns * dKs_dd + Nr * dKr_dd;
566 const double dL_dd = Nu * dJu_dd + Nv * dJv_dd + Ns * dJs_dd + Nr * dJr_dd;
569 const double df_dI = Q * modelCore;
570 const double df_dalpha = I * (Q / alpha * modelCore + Q * (one_minus_eta * dG_dalpha - etaTwoOverPi * dL_dalpha));
571 const double df_dbeta = IQ * (one_minus_eta * dG_dbeta - etaTwoOverPi * dL_dbeta);
572 const double df_dR = IQ * (one_minus_eta * dG_dR - etaTwoOverPi * dL_dR);
573 const double df_dS = IQ * one_minus_eta * dG_dS;
574 const double df_dH = -IQ * etaTwoOverPi * dL_dH;
575 const double df_deta = -IQ * (G + twoOverPi * Lmix);
576 const double df_ddiff = IQ * (one_minus_eta * dG_dd - etaTwoOverPi * dL_dd);
579 const double neg_alpha2 = -alpha2;
580 jacobian->
set(i, 0, df_dI);
581 jacobian->
set(i, 1, df_dalpha * neg_alpha2);
582 jacobian->
set(i, 2, df_dalpha * neg_alpha2 *
lambda);
583 jacobian->
set(i, 3, df_dbeta * (-beta2));
584 jacobian->
set(i, 4, df_dR * R * 81.799 * kappa2_inv / lambda2);
585 jacobian->
set(i, 5, df_dS * dSdV + df_dH * dHdV + df_deta * deta_dV);
586 jacobian->
set(i, 6, df_dS * dSdL + df_dH * dHdL + df_deta * deta_dL);
587 jacobian->
set(i, 7, -df_ddiff);