LCOV - code coverage report
Current view: top level - src/grpp - grpp_nuclear_models.c (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b4bd748) Lines: 0 133 0.0 %
Date: 2025-03-09 07:56:22 Functions: 0 16 0.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 1.15