LCOV - code coverage report
Current view: top level - src/grpp - grpp_nuclear_models.c (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 0.0 % 133 0
Test Date: 2025-12-04 06:27:48 Functions: 0.0 % 16 0

            Line data    Source code
       1              : /*----------------------------------------------------------------------------*/
       2              : /*  CP2K: A general program to perform molecular dynamics simulations         */
       3              : /*  Copyright 2000-2025 CP2K developers group <https://cp2k.org>              */
       4              : /*                                                                            */
       5              : /*  SPDX-License-Identifier: MIT                                              */
       6              : /*----------------------------------------------------------------------------*/
       7              : 
       8              : /*
       9              :  *  libgrpp - a library for the evaluation of integrals over
      10              :  *            generalized relativistic pseudopotentials.
      11              :  *
      12              :  *  Copyright (C) 2021-2023 Alexander Oleynichenko
      13              :  */
      14              : 
      15              : #include "grpp_nuclear_models.h"
      16              : #include "grpp_specfunc.h"
      17              : #include <math.h>
      18              : 
      19              : #ifndef M_PI
      20              : #define M_PI 3.14159265358979323846
      21              : #endif
      22              : 
      23              : extern double libgrpp_fermi_model_Sk(int k, double x);
      24              : 
      25              : extern double libgrpp_fermi_model_norm_factor(double c, double a);
      26              : 
      27              : extern double libgrpp_fermi_bubble_model_norm_factor(double c, double a,
      28              :                                                      double k);
      29              : 
      30              : /*
      31              :  * estimates for root mean square radius of nuclear charge distribution
      32              :  */
      33              : 
      34              : /**
      35              :  * estimate for R(rms) from:
      36              :  * W. R. Johnson, G. Soff. The Lamb shift in hydrogen-like atoms, 1 <= Z <=>
      37              :  * 110. At. Data Nucl. Data Tables, 33(3), 405 (1985).
      38              :  *
      39              :  * A = mass number
      40              :  * returns R(rms) in [fm] units
      41              :  */
      42            0 : double libgrpp_estimate_nuclear_rms_radius_johnson_1985(int A) {
      43            0 :   return 0.836 * pow(A, 1.0 / 3.0) + 0.570;
      44              : }
      45              : 
      46              : /**
      47              :  * estimate for R(rms) from:
      48              :  * O. A. Golovko, I. A. Goidenko, I. I. Tupitsyn.
      49              :  * Quantum electrodynamic corrections for valence electrons in Eka-Hg.
      50              :  * Opt. Spectrosc. 104(5), 662 (2008).
      51              :  *
      52              :  * A = mass number
      53              :  * returns R(rms) in [fm] units
      54              :  */
      55            0 : double libgrpp_estimate_nuclear_rms_radius_golovko_2008(int A) {
      56            0 :   return 0.77 * pow(A, 1.0 / 3.0) + 0.98;
      57              : }
      58              : 
      59              : /**
      60              :  * estimate parameters of the Fermi model using default formulas for 'c' and
      61              :  * 'a'. return -1 if such estimate cannot be performed, 1 otherwise.
      62              :  *
      63              :  * units: Fermi for R_rms, c, a.
      64              :  */
      65            0 : int libgrpp_estimate_fermi_model_parameters(double R_rms, double *c,
      66              :                                             double *a) {
      67            0 :   const double t = 2.3;
      68            0 :   *a = t / (4 * log(3));
      69              : 
      70            0 :   const double c2 =
      71            0 :       5.0 / 3.0 * R_rms * R_rms - 7.0 / 3.0 * M_PI * M_PI * (*a) * (*a);
      72            0 :   if (c2 < 0) {
      73              :     return -1;
      74              :   }
      75              : 
      76            0 :   *c = sqrt(c2);
      77            0 :   return 1;
      78              : }
      79              : 
      80              : /*
      81              :  * radially-local electrostatic potentials and density functions
      82              :  * for different nuclear finite charge distribution models
      83              :  */
      84              : 
      85              : /**
      86              :  * point charge
      87              :  */
      88            0 : double libgrpp_coulomb_potential_point(double r, double Z) { return -Z / r; }
      89              : 
      90              : /**
      91              :  * uniformly charged ball: density
      92              :  */
      93            0 : double libgrpp_charge_density_ball(double r, double Z, double R_rms) {
      94            0 :   const double R0 = sqrt(5.0 / 3.0) * R_rms;
      95              : 
      96            0 :   if (r <= R0) {
      97            0 :     return 3.0 * Z / (4.0 * M_PI * R0 * R0 * R0);
      98              :   } else {
      99              :     return 0.0;
     100              :   }
     101              : }
     102              : 
     103              : /**
     104              :  * uniformly charged ball: potential
     105              :  *
     106              :  * formula from:
     107              :  * L. Visscher, K. G. Dyall,
     108              :  * Dirac-Fock atomic electronic structure calculations using different nuclear
     109              :  * charge distributions. Atomic Data and Nuclear Data Tables, 67, 207–224 (1997)
     110              :  */
     111            0 : double libgrpp_coulomb_potential_ball(double r, double Z, double R_rms) {
     112            0 :   const double R0 = sqrt(5.0 / 3.0) * R_rms;
     113              : 
     114            0 :   if (r <= R0) {
     115            0 :     return -Z / (2.0 * R0) * (3.0 - r * r / (R0 * R0));
     116              :   } else {
     117            0 :     return -Z / r;
     118              :   }
     119              : }
     120              : 
     121              : /**
     122              :  * Gaussian charge distribution: density
     123              :  */
     124            0 : double libgrpp_charge_density_gaussian(double r, double Z, double R_rms) {
     125            0 :   const double xi = 3.0 / (2.0 * R_rms * R_rms);
     126            0 :   const double rho0 = Z * pow(xi / M_PI, 1.5);
     127              : 
     128            0 :   return rho0 * exp(-xi * r * r);
     129              : }
     130              : 
     131              : /**
     132              :  * Gaussian charge distribution: potential
     133              :  *
     134              :  * formula from:
     135              :  * L. Visscher, K. G. Dyall,
     136              :  * Dirac-Fock atomic electronic structure calculations using different nuclear
     137              :  * charge distributions. Atomic Data and Nuclear Data Tables, 67, 207–224 (1997)
     138              :  */
     139            0 : double libgrpp_coulomb_potential_gaussian(double r, double Z, double R_rms) {
     140            0 :   const double xi = 3.0 / (2.0 * R_rms * R_rms);
     141              : 
     142            0 :   return -Z / r * erf(sqrt(xi) * r);
     143              : }
     144              : 
     145              : /**
     146              :  * Fermi charge distribution: density
     147              :  */
     148            0 : double libgrpp_charge_density_fermi(double r, double Z, double c, double a) {
     149            0 :   const double N = libgrpp_fermi_model_norm_factor(c, a);
     150            0 :   const double c3 = c * c * c;
     151            0 :   const double rho0 = 3.0 * Z / (4 * M_PI * c3 * N);
     152              : 
     153            0 :   return rho0 / (1.0 + exp((r - c) / a));
     154              : }
     155              : 
     156              : /**
     157              :  * Fermi charge distribution: rms radius
     158              :  */
     159            0 : double libgrpp_rms_radius_fermi(int Z, double c, double a) {
     160            0 :   const double N = libgrpp_fermi_model_norm_factor(c, a);
     161            0 :   const double c3 = c * c * c;
     162            0 :   const double rho0 = 3.0 * Z / (4 * M_PI * c3 * N);
     163              : 
     164            0 :   const double r2 =
     165            0 :       4 * M_PI * rho0 / Z * pow(c, 5) / 5.0 *
     166            0 :       (1.0 + 10.0 / 3.0 * a * a * M_PI * M_PI / (c * c) +
     167            0 :        7.0 / 3.0 * pow(M_PI, 4) * pow(a, 4) / pow(c, 4) -
     168            0 :        120.0 * pow(a, 5) / pow(c, 5) * libgrpp_specfunc_fermi_sk(5, -c / a));
     169              : 
     170            0 :   return sqrt(r2);
     171              : }
     172              : 
     173              : /**
     174              :  * Fermi charge distribution: potential
     175              :  *
     176              :  * formula from:
     177              :  * N. S. Mosyagin, A. V. Zaitsevskii, A. V. Titov
     178              :  * Generalized relativistic effective core potentials for superheavy elements
     179              :  * Int. J. Quantum Chem. e26076 (2019)
     180              :  * doi: https://doi.org/10.1002/qua.26076
     181              :  */
     182            0 : double libgrpp_coulomb_potential_fermi(double r, double Z, double c, double a) {
     183            0 :   const double a2 = a * a;
     184            0 :   const double a3 = a * a * a;
     185            0 :   const double c3 = c * c * c;
     186            0 :   const double N = libgrpp_fermi_model_norm_factor(c, a);
     187              : 
     188            0 :   if (r > c) {
     189            0 :     const double S2 = libgrpp_specfunc_fermi_sk(2, (c - r) / a);
     190            0 :     const double S3 = libgrpp_specfunc_fermi_sk(3, (c - r) / a);
     191              : 
     192            0 :     return -Z / (N * r) * (N + 3 * a2 * r / c3 * S2 + 6 * a3 / c3 * S3);
     193              :   } else {
     194            0 :     const double P2 = libgrpp_specfunc_fermi_sk(2, (r - c) / a);
     195            0 :     const double P3 = libgrpp_specfunc_fermi_sk(3, (r - c) / a);
     196            0 :     const double S3 = libgrpp_specfunc_fermi_sk(3, -c / a);
     197            0 :     const double r3 = r * r * r;
     198              : 
     199            0 :     return -Z / (N * r) *
     200            0 :            (1.5 * r / c - r3 / (2 * c3) + M_PI * M_PI * a2 * r / (2 * c3) -
     201            0 :             3 * a2 * r / c3 * P2 + 6 * a3 / c3 * (P3 - S3));
     202              :   }
     203              : }
     204              : 
     205              : /**
     206              :  * normalization factor for the Fermi nuclear charge distribution
     207              :  */
     208            0 : double libgrpp_fermi_model_norm_factor(double c, double a) {
     209            0 :   const double a2 = a * a;
     210            0 :   const double a3 = a * a * a;
     211            0 :   const double c2 = c * c;
     212            0 :   const double c3 = c * c * c;
     213              : 
     214            0 :   return 1.0 + M_PI * M_PI * a2 / c2 -
     215            0 :          6.0 * a3 / c3 * libgrpp_specfunc_fermi_sk(3, -c / a);
     216              : }
     217              : 
     218              : /**
     219              :  * "Fermi bubble" charge distribution: density
     220              :  */
     221            0 : double libgrpp_charge_density_fermi_bubble(double r, double Z, double c,
     222              :                                            double a, double k) {
     223            0 :   const double Nk = libgrpp_fermi_bubble_model_norm_factor(c, a, k);
     224            0 :   const double c3 = c * c * c;
     225            0 :   const double rho0 = 3.0 * Z / (4 * M_PI * c3 * Nk);
     226              : 
     227            0 :   return rho0 * (1 + k * pow(r / c, 2)) / (1.0 + exp((r - c) / a));
     228              : }
     229              : 
     230              : /**
     231              :  * "Fermi bubble" charge distribution: rms radius
     232              :  */
     233            0 : double libgrpp_rms_radius_fermi_bubble(int Z, double c, double a, double k) {
     234            0 :   const double Nk = libgrpp_fermi_bubble_model_norm_factor(c, a, k);
     235            0 :   const double c3 = c * c * c;
     236            0 :   const double rho0 = 3.0 * Z / (4 * M_PI * c3 * Nk);
     237              : 
     238            0 :   const double part_r4 =
     239            0 :       pow(c, 5) / 5.0 *
     240            0 :       (1.0 + 10.0 / 3.0 * a * a * M_PI * M_PI / (c * c) +
     241            0 :        7.0 / 3.0 * pow(M_PI, 4) * pow(a, 4) / pow(c, 4) -
     242            0 :        120.0 * pow(a, 5) / pow(c, 5) * libgrpp_specfunc_fermi_sk(5, -c / a));
     243              : 
     244            0 :   const double part_r6 =
     245            0 :       pow(c, 7) / 7.0 *
     246            0 :       (1.0 + 7.0 * a * a * M_PI * M_PI / (c * c) +
     247            0 :        49.0 / 3.0 * pow(M_PI, 4) * pow(a, 4) / pow(c, 4) +
     248            0 :        31.0 / 3.0 * pow(M_PI, 6) * pow(a, 6) / pow(c, 6) -
     249            0 :        5040.0 * pow(a, 7) / pow(c, 7) * libgrpp_specfunc_fermi_sk(7, -c / a));
     250              : 
     251            0 :   const double r2 = 4 * M_PI * rho0 / Z * (part_r4 + k / (c * c) * part_r6);
     252              : 
     253            0 :   return sqrt(r2);
     254              : }
     255              : 
     256              : /**
     257              :  * "Fermi bubble" charge distribution: potential.
     258              :  *
     259              :  * derivation of the formula is based on:
     260              :  *
     261              :  * F. A. Parpia and A. K. Mohanty,
     262              :  * Relativistic basis-set calculations for atoms with Fermi nuclei.
     263              :  * Phys. Rev. A 46, 3735 (1992)
     264              :  * doi: 10.1103/PhysRevA.46.3735
     265              :  *
     266              :  */
     267            0 : double libgrpp_coulomb_potential_fermi_bubble(double r, double Z, double c,
     268              :                                               double a, double k) {
     269              :   // const double a2 = a * a;
     270              :   // const double a3 = a * a * a;
     271              :   // const double c2 = c * c;
     272              :   // const double c3 = c * c * c;
     273              : 
     274            0 :   const double Nk = libgrpp_fermi_bubble_model_norm_factor(c, a, k);
     275              :   // const double rho0 = 3 * Z / (4 * M_PI * M_PI * c * c * c * Nk);
     276              : 
     277            0 :   double F0 = 0.0;
     278            0 :   double F2 = 0.0;
     279              : 
     280            0 :   if (r < c) {
     281            0 :     const double S2 = libgrpp_specfunc_fermi_sk(2, (r - c) / a);
     282            0 :     const double S3 = libgrpp_specfunc_fermi_sk(3, (r - c) / a);
     283            0 :     const double S4 = libgrpp_specfunc_fermi_sk(4, (r - c) / a);
     284            0 :     const double S5 = libgrpp_specfunc_fermi_sk(5, (r - c) / a);
     285              : 
     286              :     // contribution from the "classical" Fermi term
     287            0 :     F0 = -pow(r, 3) / 6.0 - r * a * a * S2 + 2.0 * pow(a, 3) * S3 +
     288            0 :          r * c * c / 2.0 + M_PI * M_PI / 6.0 * r * a * a -
     289            0 :          2.0 * pow(a, 3) * libgrpp_specfunc_fermi_sk(3, -c / a);
     290              : 
     291              :     // contribution from the quadratic, "hole" term
     292            0 :     F2 = -pow(r, 5) / 20.0 - pow(r, 3) * pow(a, 2) * S2 +
     293            0 :          6.0 * pow(r, 2) * pow(a, 3) * S3 - 18.0 * r * pow(a, 4) * S4 +
     294            0 :          24.0 * pow(a, 5) * S5 + r * pow(c, 4) / 4.0 +
     295            0 :          r * M_PI * M_PI * c * c * a * a / 2.0 +
     296            0 :          r * pow(a, 4) * pow(M_PI, 4) * 7.0 / 60.0 -
     297            0 :          24.0 * pow(a, 5) * libgrpp_specfunc_fermi_sk(5, -c / a);
     298              :   } else {
     299            0 :     const double S2 = libgrpp_specfunc_fermi_sk(2, (c - r) / a);
     300            0 :     const double S3 = libgrpp_specfunc_fermi_sk(3, (c - r) / a);
     301            0 :     const double S4 = libgrpp_specfunc_fermi_sk(4, (c - r) / a);
     302            0 :     const double S5 = libgrpp_specfunc_fermi_sk(5, (c - r) / a);
     303              : 
     304              :     // contribution from the "classical" Fermi term
     305            0 :     F0 = pow(c, 3) / 3.0 + M_PI * M_PI / 3.0 * c * a * a -
     306            0 :          2.0 * pow(a, 3) * libgrpp_specfunc_fermi_sk(3, -c / a) +
     307            0 :          r * a * a * S2 + 2.0 * pow(a, 3) * S3;
     308              : 
     309              :     // contribution from the quadratic, "hole" term
     310            0 :     F2 = pow(c, 5) / 5.0 + 2.0 * pow(c, 3) * a * a * M_PI * M_PI / 3.0 +
     311            0 :          7.0 * pow(a, 4) * c * pow(M_PI, 4) / 15.0 -
     312            0 :          24.0 * pow(a, 5) * libgrpp_specfunc_fermi_sk(5, -c / a) +
     313            0 :          pow(a, 2) * pow(r, 3) * S2 + 6.0 * pow(a, 3) * pow(r, 2) * S3 +
     314            0 :          18.0 * r * pow(a, 4) * S4 + 24.0 * pow(a, 5) * S5;
     315              :   }
     316              : 
     317            0 :   return -Z / (Nk * r) * 3.0 / pow(c, 3) * (F0 + k / (c * c) * F2);
     318              : }
     319              : 
     320              : /**
     321              :  * normalization factor for the "Fermi bubble" nuclear charge distribution
     322              :  */
     323            0 : double libgrpp_fermi_bubble_model_norm_factor(double c, double a, double k) {
     324            0 :   const double a2 = a * a;
     325            0 :   const double a3 = a * a2;
     326            0 :   const double a4 = a * a3;
     327            0 :   const double a5 = a * a4;
     328            0 :   const double c2 = c * c;
     329            0 :   const double c3 = c * c2;
     330            0 :   const double c4 = c * c3;
     331            0 :   const double c5 = c * c4;
     332              : 
     333            0 :   return libgrpp_fermi_model_norm_factor(c, a) + 3.0 / 5.0 * k +
     334            0 :          2.0 * M_PI * M_PI * a2 * k / c2 +
     335            0 :          7.0 * M_PI * M_PI * M_PI * M_PI * a4 * k / (5.0 * c4) -
     336            0 :          72.0 * a5 * k / c5 * libgrpp_specfunc_fermi_sk(5, -c / a);
     337              : }
        

Generated by: LCOV version 2.0-1