LCOV - code coverage report
Current view: top level - src/grpp - grpp_fortran.c (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b4bd748) Lines: 16 324 4.9 %
Date: 2025-03-09 07:56:22 Functions: 2 40 5.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             : /*
      16             :  * Wrappers for the LIBGRPP subroutines to be used from Fortran projects.
      17             :  *
      18             :  * C99       Fortran
      19             :  * --------------------
      20             :  * int32_t   integer(4)
      21             :  * double    real(8)
      22             :  */
      23             : 
      24             : #include <math.h>
      25             : #include <stdint.h>
      26             : #include <stdio.h>
      27             : #include <stdlib.h>
      28             : 
      29             : #include "grpp_factorial.h"
      30             : #include "libgrpp.h"
      31             : 
      32             : /*
      33             :  * Fine-tuning of the LIBGRPP internal parameters.
      34             :  */
      35             : 
      36           0 : void libgrpp_set_default_parameters_() { libgrpp_set_default_parameters(); }
      37             : 
      38           0 : void libgrpp_set_radial_tolerance_(const double *tolerance) {
      39           0 :   libgrpp_set_radial_tolerance(*tolerance);
      40           0 : }
      41             : 
      42           0 : void libgrpp_set_angular_screening_tolerance_(const double *tolerance) {
      43           0 :   libgrpp_set_angular_screening_tolerance(*tolerance);
      44           0 : }
      45             : 
      46           0 : void libgrpp_set_modified_bessel_tolerance_(const double *tolerance) {
      47           0 :   libgrpp_set_modified_bessel_tolerance(*tolerance);
      48           0 : }
      49             : 
      50           0 : void libgrpp_set_cartesian_order_(const int32_t *order) {
      51           0 :   libgrpp_set_cartesian_order(*order);
      52           0 : }
      53             : 
      54             : /*
      55             :  * initialization and finalization
      56             :  */
      57       11380 : void libgrpp_init_() { libgrpp_init(); }
      58             : 
      59           0 : void libgrpp_finalize_() { libgrpp_finalize(); }
      60             : 
      61             : /*
      62             :  * Type 1 RPP integrals (local term)
      63             :  */
      64             : 
      65           0 : void libgrpp_type1_integrals_(
      66             :     // contracted Gaussian A
      67             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
      68             :     double *alpha_A,
      69             :     // contracted Gaussian B
      70             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
      71             :     double *alpha_B,
      72             :     // pseudopotential
      73             :     double *rpp_origin, int32_t *rpp_num_primitives, int32_t *rpp_powers,
      74             :     double *rpp_coeffs, double *rpp_alpha,
      75             :     // answer
      76             :     double *matrix) {
      77           0 :   int *pot_powers_int = (int *)calloc(*rpp_num_primitives, sizeof(int));
      78             : 
      79           0 :   for (int i = 0; i < *rpp_num_primitives; i++) {
      80           0 :     pot_powers_int[i] = rpp_powers[i];
      81             :   }
      82             : 
      83           0 :   libgrpp_potential_t *pot = libgrpp_new_potential(
      84             :       0, 0, *rpp_num_primitives, pot_powers_int, rpp_coeffs, rpp_alpha);
      85           0 :   libgrpp_shell_t *shell_A =
      86           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
      87           0 :   libgrpp_shell_t *shell_B =
      88           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
      89             : 
      90           0 :   libgrpp_type1_integrals(shell_A, shell_B, rpp_origin, pot, matrix);
      91             : 
      92           0 :   libgrpp_delete_shell(shell_A);
      93           0 :   libgrpp_delete_shell(shell_B);
      94           0 :   libgrpp_delete_potential(pot);
      95           0 :   free(pot_powers_int);
      96           0 : }
      97             : 
      98             : /*
      99             :  * Type 2 RPP integrals (semilocal terms with projectors)
     100             :  */
     101             : 
     102      149632 : void libgrpp_type2_integrals_(
     103             :     // contracted Gaussian A
     104             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     105             :     double *alpha_A, double *origin_B,
     106             :     // contracted Gaussian B
     107             :     int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B, double *alpha_B,
     108             :     // pseudopotential
     109             :     double *pot_origin, int32_t *pot_L, int32_t *pot_num_primitives,
     110             :     int32_t *pot_powers, double *pot_coeffs, double *pot_alpha,
     111             :     // answer
     112             :     double *matrix) {
     113      149632 :   int *pot_powers_int = (int *)calloc(*pot_num_primitives, sizeof(int));
     114             : 
     115      437153 :   for (int i = 0; i < *pot_num_primitives; i++) {
     116      287521 :     pot_powers_int[i] = pot_powers[i];
     117             :   }
     118             : 
     119      149632 :   libgrpp_potential_t *pot = libgrpp_new_potential(
     120             :       *pot_L, 0, *pot_num_primitives, pot_powers_int, pot_coeffs, pot_alpha);
     121      149632 :   libgrpp_shell_t *shell_A =
     122      149632 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     123      149632 :   libgrpp_shell_t *shell_B =
     124      149632 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     125             : 
     126      149632 :   libgrpp_type2_integrals(shell_A, shell_B, pot_origin, pot, matrix);
     127             : 
     128      149632 :   libgrpp_delete_shell(shell_A);
     129      149632 :   libgrpp_delete_shell(shell_B);
     130      149632 :   libgrpp_delete_potential(pot);
     131      149632 :   free(pot_powers_int);
     132      149632 : }
     133             : 
     134             : /*
     135             :  * Effective spin-orbit operator ("Type 3") RPP integrals (semilocal terms with
     136             :  * projectors)
     137             :  */
     138             : 
     139           0 : void libgrpp_spin_orbit_integrals_(
     140             :     // contracted Gaussian A
     141             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     142             :     double *alpha_A,
     143             :     // contracted Gaussian B
     144             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     145             :     double *alpha_B,
     146             :     // pseudopotential
     147             :     double *pot_origin, int32_t *pot_L, int32_t *pot_num_primitives,
     148             :     int32_t *pot_powers, double *pot_coeffs, double *pot_alpha,
     149             :     // answer
     150             :     double *so_x_matrix, double *so_y_matrix, double *so_z_matrix) {
     151           0 :   int *pot_powers_int = (int *)calloc(*pot_num_primitives, sizeof(int));
     152             : 
     153           0 :   for (int i = 0; i < *pot_num_primitives; i++) {
     154           0 :     pot_powers_int[i] = pot_powers[i];
     155             :   }
     156             : 
     157             :   /*
     158             :    * construct RPP structure
     159             :    */
     160           0 :   libgrpp_potential_t *pot = libgrpp_new_potential(
     161             :       *pot_L, 0, *pot_num_primitives, pot_powers_int, pot_coeffs, pot_alpha);
     162             : 
     163             :   /*
     164             :    * construct shells
     165             :    */
     166           0 :   libgrpp_shell_t *shell_A =
     167           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     168           0 :   libgrpp_shell_t *shell_B =
     169           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     170             : 
     171           0 :   libgrpp_spin_orbit_integrals(shell_A, shell_B, pot_origin, pot, so_x_matrix,
     172             :                                so_y_matrix, so_z_matrix);
     173             : 
     174           0 :   libgrpp_delete_shell(shell_A);
     175           0 :   libgrpp_delete_shell(shell_B);
     176           0 :   libgrpp_delete_potential(pot);
     177           0 :   free(pot_powers_int);
     178           0 : }
     179             : 
     180             : /**
     181             :  * Outercore RPP integrals (non-local terms with projectors onto outercore
     182             :  * spinors)
     183             :  *
     184             :  * Part 1: integration of the first non-local term:
     185             :  * U*|nlj><nlj| + |nlj><nlj|*U
     186             :  */
     187           0 : void libgrpp_outercore_potential_integrals_part_1_(
     188             :     // contracted Gaussian A
     189             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     190             :     double *alpha_A, double *origin_B,
     191             :     // contracted Gaussian B
     192             :     int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B, double *alpha_B,
     193             :     // pseudopotential for the outercore shell LJ
     194             :     double *pot_origin, int32_t *pot_L, int32_t *pot_J,
     195             :     int32_t *pot_num_primitives, int32_t *pot_powers, double *pot_coeffs,
     196             :     double *pot_alpha,
     197             :     // expansion of the outercore shell LJ
     198             :     int32_t *oc_shell_num_primitives, double *oc_shell_coeffs,
     199             :     double *oc_shell_alpha,
     200             :     // answer
     201             :     double *arep_matrix, double *so_x_matrix, double *so_y_matrix,
     202             :     double *so_z_matrix) {
     203           0 :   void libgrpp_outercore_potential_integrals_part_1(
     204             :       libgrpp_shell_t * shell_A, libgrpp_shell_t * shell_B, double *C,
     205             :       libgrpp_potential_t *oc_potential, libgrpp_shell_t *oc_shell,
     206             :       double *arep_matrix, double *so_x_matrix, double *so_y_matrix,
     207             :       double *so_z_matrix);
     208             : 
     209             :   /*
     210             :    * array conversion: Fortran -> C
     211             :    */
     212           0 :   int *pot_powers_int = (int *)calloc(*pot_num_primitives, sizeof(int));
     213           0 :   for (int i = 0; i < *pot_num_primitives; i++) {
     214           0 :     pot_powers_int[i] = pot_powers[i];
     215             :   }
     216             : 
     217             :   /*
     218             :    * construct shells
     219             :    */
     220           0 :   libgrpp_shell_t *shell_A =
     221           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     222           0 :   libgrpp_shell_t *shell_B =
     223           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     224             : 
     225             :   /*
     226             :    * construct pseudopotential for the given L,J numbers
     227             :    */
     228           0 :   libgrpp_potential_t *oc_potential =
     229           0 :       libgrpp_new_potential(*pot_L, *pot_J, *pot_num_primitives, pot_powers_int,
     230             :                             pot_coeffs, pot_alpha);
     231             : 
     232             :   /*
     233             :    * construct outercore shell associated with the pseudopotential
     234             :    */
     235           0 :   libgrpp_shell_t *oc_shell =
     236           0 :       libgrpp_new_shell(pot_origin, *pot_L, *oc_shell_num_primitives,
     237             :                         oc_shell_coeffs, oc_shell_alpha);
     238             : 
     239             :   /*
     240             :    * evaluate RPP integrals
     241             :    */
     242           0 :   libgrpp_outercore_potential_integrals_part_1(
     243             :       shell_A, shell_B, pot_origin, oc_potential, oc_shell, arep_matrix,
     244             :       so_x_matrix, so_y_matrix, so_z_matrix);
     245             : 
     246             :   /*
     247             :    * clean-up
     248             :    */
     249           0 :   libgrpp_delete_shell(shell_A);
     250           0 :   libgrpp_delete_shell(shell_B);
     251           0 :   libgrpp_delete_potential(oc_potential);
     252           0 :   libgrpp_delete_shell(oc_shell);
     253           0 :   free(pot_powers_int);
     254           0 : }
     255             : 
     256             : /**
     257             :  * Outercore RPP integrals (non-local terms with projectors onto outercore
     258             :  * spinors)
     259             :  *
     260             :  * Part 2: integration of the second non-local term:
     261             :  * |nlj><nlj| U |n'lj><n'lj|
     262             :  */
     263           0 : void libgrpp_outercore_potential_integrals_part_2_(
     264             :     // contracted Gaussian A
     265             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     266             :     double *alpha_A,
     267             :     // contracted Gaussian B
     268             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     269             :     double *alpha_B,
     270             :     // origin of the RPP
     271             :     double *pot_origin,
     272             :     // outercore shell 1:
     273             :     int32_t *oc_shell_1_L, int32_t *oc_shell_1_J, int32_t *pot1_num_primitives,
     274             :     int32_t *pot1_powers, double *pot1_coeffs, double *pot1_alpha,
     275             :     int32_t *oc_shell_1_num_primitives, double *oc_shell_1_coeffs,
     276             :     double *oc_shell_1_alpha,
     277             :     // outercore shell 2:
     278             :     int32_t *oc_shell_2_L, int32_t *oc_shell_2_J, int32_t *pot2_num_primitives,
     279             :     int32_t *pot2_powers, double *pot2_coeffs, double *pot2_alpha,
     280             :     int32_t *oc_shell_2_num_primitives, double *oc_shell_2_coeffs,
     281             :     double *oc_shell_2_alpha,
     282             :     // answer:
     283             :     double *arep_matrix, double *so_x_matrix, double *so_y_matrix,
     284             :     double *so_z_matrix) {
     285           0 :   void libgrpp_outercore_potential_integrals_part_2(
     286             :       libgrpp_shell_t * shell_A, libgrpp_shell_t * shell_B, double *C,
     287             :       libgrpp_potential_t *oc_potential_1, libgrpp_shell_t *oc_shell_1,
     288             :       libgrpp_potential_t *oc_potential_2, libgrpp_shell_t *oc_shell_2,
     289             :       double *arep_matrix, double *so_x_matrix, double *so_y_matrix,
     290             :       double *so_z_matrix);
     291             : 
     292             :   /*
     293             :    * array conversion: Fortran -> C
     294             :    */
     295           0 :   int *pot1_powers_int = (int *)calloc(*pot1_num_primitives, sizeof(int));
     296           0 :   int *pot2_powers_int = (int *)calloc(*pot2_num_primitives, sizeof(int));
     297             : 
     298           0 :   for (int i = 0; i < *pot1_num_primitives; i++) {
     299           0 :     pot1_powers_int[i] = pot1_powers[i];
     300             :   }
     301           0 :   for (int i = 0; i < *pot2_num_primitives; i++) {
     302           0 :     pot2_powers_int[i] = pot2_powers[i];
     303             :   }
     304             : 
     305             :   /*
     306             :    * construct shells
     307             :    */
     308           0 :   libgrpp_shell_t *shell_A =
     309           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     310           0 :   libgrpp_shell_t *shell_B =
     311           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     312             : 
     313             :   /*
     314             :    * the first outercore pseudopotential U_{n,L,J} and the corresponding
     315             :    * outercore shell
     316             :    */
     317           0 :   libgrpp_potential_t *oc_potential_1 =
     318           0 :       libgrpp_new_potential(*oc_shell_1_L, *oc_shell_1_J, *pot1_num_primitives,
     319             :                             pot1_powers_int, pot1_coeffs, pot1_alpha);
     320           0 :   libgrpp_shell_t *oc_shell_1 =
     321           0 :       libgrpp_new_shell(pot_origin, *oc_shell_1_L, *oc_shell_1_num_primitives,
     322             :                         oc_shell_1_coeffs, oc_shell_1_alpha);
     323             : 
     324             :   /*
     325             :    * the second outercore pseudopotential U_{n',L',J'} and the corresponding
     326             :    * outercore shell
     327             :    */
     328           0 :   libgrpp_potential_t *oc_potential_2 =
     329           0 :       libgrpp_new_potential(*oc_shell_2_L, *oc_shell_2_J, *pot2_num_primitives,
     330             :                             pot2_powers_int, pot2_coeffs, pot2_alpha);
     331           0 :   libgrpp_shell_t *oc_shell_2 =
     332           0 :       libgrpp_new_shell(pot_origin, *oc_shell_2_L, *oc_shell_2_num_primitives,
     333             :                         oc_shell_2_coeffs, oc_shell_2_alpha);
     334             : 
     335             :   /*
     336             :    * evaluate integrals
     337             :    */
     338           0 :   libgrpp_outercore_potential_integrals_part_2(
     339             :       shell_A, shell_B, pot_origin, oc_potential_1, oc_shell_1, oc_potential_2,
     340             :       oc_shell_2, arep_matrix, so_x_matrix, so_y_matrix, so_z_matrix);
     341             : 
     342             :   /*
     343             :    * clean-up
     344             :    */
     345           0 :   libgrpp_delete_shell(shell_A);
     346           0 :   libgrpp_delete_shell(shell_B);
     347           0 :   libgrpp_delete_potential(oc_potential_1);
     348           0 :   libgrpp_delete_potential(oc_potential_2);
     349           0 :   libgrpp_delete_shell(oc_shell_1);
     350           0 :   libgrpp_delete_shell(oc_shell_2);
     351           0 :   free(pot1_powers_int);
     352           0 :   free(pot2_powers_int);
     353           0 : }
     354             : 
     355             : /**
     356             :  * Analytic calculation of gradients of LOCAL potential integrals for a given
     357             :  * shell pair with respect to the point 'point_3d'.
     358             :  */
     359           0 : void libgrpp_type1_integrals_gradient_(
     360             :     // contracted Gaussian A
     361             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     362             :     double *alpha_A,
     363             :     // contracted Gaussian B
     364             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     365             :     double *alpha_B,
     366             :     // pseudopotential
     367             :     double *rpp_origin, int32_t *rpp_num_primitives, int32_t *rpp_powers,
     368             :     double *rpp_coeffs, double *rpp_alpha,
     369             :     // differentiation wrt the 3d point (x,y,z)
     370             :     double *point_3d,
     371             :     // answer: matrices d<Int>/dx, d<Int>/dy, d<Int>/dZ
     372             :     double *grad_arep_x, double *grad_arep_y, double *grad_arep_z) {
     373           0 :   int *pot_powers_int = (int *)calloc(*rpp_num_primitives, sizeof(int));
     374           0 :   double *grad_array[3];
     375           0 :   grad_array[0] = grad_arep_x;
     376           0 :   grad_array[1] = grad_arep_y;
     377           0 :   grad_array[2] = grad_arep_z;
     378             : 
     379           0 :   for (int i = 0; i < *rpp_num_primitives; i++) {
     380           0 :     pot_powers_int[i] = rpp_powers[i];
     381             :   }
     382             : 
     383           0 :   libgrpp_potential_t *pot = libgrpp_new_potential(
     384             :       0, 0, *rpp_num_primitives, pot_powers_int, rpp_coeffs, rpp_alpha);
     385           0 :   libgrpp_shell_t *shell_A =
     386           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     387           0 :   libgrpp_shell_t *shell_B =
     388           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     389             : 
     390           0 :   libgrpp_type1_integrals_gradient(shell_A, shell_B, rpp_origin, pot, point_3d,
     391             :                                    grad_array);
     392             : 
     393           0 :   libgrpp_delete_shell(shell_A);
     394           0 :   libgrpp_delete_shell(shell_B);
     395           0 :   libgrpp_delete_potential(pot);
     396           0 :   free(pot_powers_int);
     397           0 : }
     398             : 
     399             : /**
     400             :  * Analytic calculation of gradients of SEMI-LOCAL potential integrals for a
     401             :  * given shell pair with respect to the point 'point_3d'.
     402             :  */
     403           0 : void libgrpp_type2_integrals_gradient_(
     404             :     // contracted Gaussian A
     405             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     406             :     double *alpha_A, double *origin_B,
     407             :     // contracted Gaussian B
     408             :     int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B, double *alpha_B,
     409             :     // pseudopotential
     410             :     double *pot_origin, int32_t *pot_L, int32_t *pot_num_primitives,
     411             :     int32_t *pot_powers, double *pot_coeffs, double *pot_alpha,
     412             :     // differentiation wrt the 3d point (x,y,z)
     413             :     double *point_3d,
     414             :     // answer: matrices d<Int>/dx, d<Int>/dy, d<Int>/dZ
     415             :     double *grad_arep_x, double *grad_arep_y, double *grad_arep_z) {
     416           0 :   int *pot_powers_int = (int *)calloc(*pot_num_primitives, sizeof(int));
     417           0 :   for (int i = 0; i < *pot_num_primitives; i++) {
     418           0 :     pot_powers_int[i] = pot_powers[i];
     419             :   }
     420             : 
     421           0 :   double *grad_array[3];
     422           0 :   grad_array[0] = grad_arep_x;
     423           0 :   grad_array[1] = grad_arep_y;
     424           0 :   grad_array[2] = grad_arep_z;
     425             : 
     426           0 :   libgrpp_potential_t *pot = libgrpp_new_potential(
     427             :       *pot_L, 0, *pot_num_primitives, pot_powers_int, pot_coeffs, pot_alpha);
     428           0 :   libgrpp_shell_t *shell_A =
     429           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     430           0 :   libgrpp_shell_t *shell_B =
     431           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     432             : 
     433           0 :   libgrpp_type2_integrals_gradient(shell_A, shell_B, pot_origin, pot, point_3d,
     434             :                                    grad_array);
     435             : 
     436           0 :   libgrpp_delete_shell(shell_A);
     437           0 :   libgrpp_delete_shell(shell_B);
     438           0 :   libgrpp_delete_potential(pot);
     439           0 :   free(pot_powers_int);
     440           0 : }
     441             : 
     442             : /**
     443             :  * Analytic calculation of gradients of integrals over the effective spin-orbit
     444             :  * operator (potential) for a given shell pair (with respect to the point
     445             :  * 'point_3d').
     446             :  */
     447           0 : void libgrpp_spin_orbit_integrals_gradient_(
     448             :     // contracted Gaussian A
     449             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     450             :     double *alpha_A,
     451             :     // contracted Gaussian B
     452             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     453             :     double *alpha_B,
     454             :     // pseudopotential
     455             :     double *pot_origin, int32_t *pot_L, int32_t *pot_num_primitives,
     456             :     int32_t *pot_powers, double *pot_coeffs, double *pot_alpha,
     457             :     // differentiation wrt the 3d point (x,y,z)
     458             :     double *point_3d,
     459             :     // answer: 9 matrices
     460             :     // d<SO-x>/dx, d<SO-x>/dy, d<SO-x>/dZ
     461             :     double *grad_sox_x, double *grad_sox_y, double *grad_sox_z,
     462             :     // d<SO-y>/dx, d<SO-y>/dy, d<SO-y>/dZ
     463             :     double *grad_soy_x, double *grad_soy_y, double *grad_soy_z,
     464             :     // d<SO-z>/dx, d<SO-z>/dy, d<SO-z>/dZ
     465             :     double *grad_soz_x, double *grad_soz_y, double *grad_soz_z) {
     466           0 :   int *pot_powers_int = (int *)calloc(*pot_num_primitives, sizeof(int));
     467             : 
     468           0 :   double *grad_array_SO_x[3];
     469           0 :   grad_array_SO_x[0] = grad_sox_x;
     470           0 :   grad_array_SO_x[1] = grad_sox_y;
     471           0 :   grad_array_SO_x[2] = grad_sox_z;
     472             : 
     473           0 :   double *grad_array_SO_y[3];
     474           0 :   grad_array_SO_y[0] = grad_soy_x;
     475           0 :   grad_array_SO_y[1] = grad_soy_y;
     476           0 :   grad_array_SO_y[2] = grad_soy_z;
     477             : 
     478           0 :   double *grad_array_SO_z[3];
     479           0 :   grad_array_SO_z[0] = grad_soz_x;
     480           0 :   grad_array_SO_z[1] = grad_soz_y;
     481           0 :   grad_array_SO_z[2] = grad_soz_z;
     482             : 
     483           0 :   for (int i = 0; i < *pot_num_primitives; i++) {
     484           0 :     pot_powers_int[i] = pot_powers[i];
     485             :   }
     486             : 
     487             :   /*
     488             :    * construct RPP structure
     489             :    */
     490           0 :   libgrpp_potential_t *pot = libgrpp_new_potential(
     491             :       *pot_L, 0, *pot_num_primitives, pot_powers_int, pot_coeffs, pot_alpha);
     492             : 
     493             :   /*
     494             :    * construct shells
     495             :    */
     496           0 :   libgrpp_shell_t *shell_A =
     497           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     498           0 :   libgrpp_shell_t *shell_B =
     499           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     500             : 
     501           0 :   libgrpp_spin_orbit_integrals_gradient(shell_A, shell_B, pot_origin, pot,
     502             :                                         point_3d, grad_array_SO_x,
     503             :                                         grad_array_SO_y, grad_array_SO_z);
     504             : 
     505           0 :   libgrpp_delete_shell(shell_A);
     506           0 :   libgrpp_delete_shell(shell_B);
     507           0 :   libgrpp_delete_potential(pot);
     508           0 :   free(pot_powers_int);
     509           0 : }
     510             : 
     511             : /**
     512             :  * Overlap integrals between two contracted Gaussians with given cartesian parts
     513             :  * x^n y^l z^m (auxiliary function)
     514             :  */
     515             : 
     516           0 : void evaluate_overlap_integral_contracted_(
     517             :     // contracted Gaussian A
     518             :     double *origin_A, int32_t *n_A, int32_t *l_A, int32_t *m_A,
     519             :     int32_t *num_primitives_A, double *coeffs_A, double *alpha_A,
     520             :     // contracted Gaussian B
     521             :     double *origin_B, int32_t *n_B, int32_t *l_B, int32_t *m_B,
     522             :     int32_t *num_primitives_B, double *coeffs_B, double *alpha_B,
     523             :     // answer
     524             :     double *overlap_integral) {
     525           0 :   void libgrpp_overlap_integrals(libgrpp_shell_t * shell_A,
     526             :                                  libgrpp_shell_t * shell_B,
     527             :                                  double *overlap_matrix);
     528             : 
     529           0 :   libgrpp_shell_t *shell_A = libgrpp_new_shell(
     530           0 :       origin_A, *n_A + *l_A + *m_A, *num_primitives_A, coeffs_A, alpha_A);
     531           0 :   libgrpp_shell_t *shell_B = libgrpp_new_shell(
     532           0 :       origin_B, *n_B + *l_B + *m_B, *num_primitives_B, coeffs_B, alpha_B);
     533             : 
     534           0 :   shell_A->cart_size = 1;
     535           0 :   shell_A->cart_list[0] = *n_A;
     536           0 :   shell_A->cart_list[1] = *l_A;
     537           0 :   shell_A->cart_list[2] = *m_A;
     538             : 
     539           0 :   shell_B->cart_size = 1;
     540           0 :   shell_B->cart_list[0] = *n_B;
     541           0 :   shell_B->cart_list[1] = *l_B;
     542           0 :   shell_B->cart_list[2] = *m_B;
     543             : 
     544           0 :   libgrpp_overlap_integrals(shell_A, shell_B, overlap_integral);
     545             : 
     546           0 :   libgrpp_delete_shell(shell_A);
     547           0 :   libgrpp_delete_shell(shell_B);
     548           0 : }
     549             : 
     550             : /*
     551             :  * calculates normalization factor for the given contracted Gaussians
     552             :  * (auxiliary function)
     553             :  */
     554           0 : void radial_gto_norm_factor_(int32_t *L, int32_t *num_primitives,
     555             :                              double *coeffs, double *alpha, double *norm) {
     556           0 :   *norm = 0.0;
     557           0 :   double S = 0.0;
     558           0 :   double origin[] = {0, 0, 0};
     559           0 :   int zero = 0;
     560             : 
     561           0 :   evaluate_overlap_integral_contracted_(origin, L, &zero, &zero, num_primitives,
     562             :                                         coeffs, alpha, origin, L, &zero, &zero,
     563             :                                         num_primitives, coeffs, alpha, &S);
     564             : 
     565           0 :   *norm = sqrt(libgrpp_double_factorial(2 * (*L) - 1)) / sqrt(S);
     566           0 : }
     567             : 
     568             : /*
     569             :  * overlap integrals (for the shell pair)
     570             :  */
     571             : 
     572           0 : void libgrpp_overlap_integrals_(
     573             :     // contracted Gaussian A
     574             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     575             :     double *alpha_A,
     576             :     // contracted Gaussian B
     577             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     578             :     double *alpha_B,
     579             :     // answer
     580             :     double *matrix) {
     581           0 :   libgrpp_shell_t *shell_A =
     582           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     583           0 :   libgrpp_shell_t *shell_B =
     584           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     585             : 
     586           0 :   libgrpp_overlap_integrals(shell_A, shell_B, matrix);
     587             : 
     588           0 :   libgrpp_delete_shell(shell_A);
     589           0 :   libgrpp_delete_shell(shell_B);
     590           0 : }
     591             : 
     592             : /*
     593             :  * kinetic-energy integrals (for the shell pair)
     594             :  */
     595             : 
     596           0 : void libgrpp_kinetic_energy_integrals_(
     597             :     // contracted Gaussian A
     598             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     599             :     double *alpha_A,
     600             :     // contracted Gaussian B
     601             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     602             :     double *alpha_B,
     603             :     // answer
     604             :     double *matrix) {
     605           0 :   libgrpp_shell_t *shell_A =
     606           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     607           0 :   libgrpp_shell_t *shell_B =
     608           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     609             : 
     610           0 :   libgrpp_kinetic_energy_integrals(shell_A, shell_B, matrix);
     611             : 
     612           0 :   libgrpp_delete_shell(shell_A);
     613           0 :   libgrpp_delete_shell(shell_B);
     614           0 : }
     615             : 
     616             : /*
     617             :  * momentum operator integrals (for the shell pair)
     618             :  */
     619             : 
     620           0 : void libgrpp_momentum_integrals_(
     621             :     // contracted Gaussian A
     622             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     623             :     double *alpha_A,
     624             :     // contracted Gaussian B
     625             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     626             :     double *alpha_B,
     627             :     // answer
     628             :     double *matrix_x, double *matrix_y, double *matrix_z) {
     629           0 :   libgrpp_shell_t *shell_A =
     630           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     631           0 :   libgrpp_shell_t *shell_B =
     632           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     633             : 
     634           0 :   libgrpp_momentum_integrals(shell_A, shell_B, matrix_x, matrix_y, matrix_z);
     635             : 
     636           0 :   libgrpp_delete_shell(shell_A);
     637           0 :   libgrpp_delete_shell(shell_B);
     638           0 : }
     639             : 
     640             : /*
     641             :  * nuclear attraction integrals
     642             :  */
     643             : 
     644           0 : void libgrpp_nuclear_attraction_integrals_(
     645             :     // contracted Gaussian A
     646             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     647             :     double *alpha_A,
     648             :     // contracted Gaussian B
     649             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     650             :     double *alpha_B,
     651             :     // potential definition
     652             :     double *charge_origin, int32_t *charge, int32_t *nuclear_model,
     653             :     double *model_params,
     654             :     // answer
     655             :     double *matrix) {
     656           0 :   libgrpp_shell_t *shell_A =
     657           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     658           0 :   libgrpp_shell_t *shell_B =
     659           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     660             : 
     661           0 :   libgrpp_nuclear_attraction_integrals(shell_A, shell_B, charge_origin, *charge,
     662             :                                        *nuclear_model, model_params, matrix);
     663             : 
     664           0 :   libgrpp_delete_shell(shell_A);
     665           0 :   libgrpp_delete_shell(shell_B);
     666           0 : }
     667             : 
     668           0 : void libgrpp_nuclear_attraction_integrals_point_charge_(
     669             :     // contracted Gaussian A
     670             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     671             :     double *alpha_A,
     672             :     // contracted Gaussian B
     673             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     674             :     double *alpha_B,
     675             :     // potential definition
     676             :     double *charge_origin, int32_t *charge,
     677             :     // answer
     678             :     double *matrix) {
     679           0 :   libgrpp_shell_t *shell_A =
     680           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     681           0 :   libgrpp_shell_t *shell_B =
     682           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     683             : 
     684           0 :   libgrpp_nuclear_attraction_integrals_point_charge(
     685             :       shell_A, shell_B, charge_origin, *charge, matrix);
     686             : 
     687           0 :   libgrpp_delete_shell(shell_A);
     688           0 :   libgrpp_delete_shell(shell_B);
     689           0 : }
     690             : 
     691           0 : void libgrpp_nuclear_attraction_integrals_charged_ball_(
     692             :     // contracted Gaussian A
     693             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     694             :     double *alpha_A,
     695             :     // contracted Gaussian B
     696             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     697             :     double *alpha_B,
     698             :     // potential definition
     699             :     double *charge_origin, int32_t *charge, double *r_rms,
     700             :     // answer
     701             :     double *matrix) {
     702           0 :   libgrpp_shell_t *shell_A =
     703           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     704           0 :   libgrpp_shell_t *shell_B =
     705           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     706             : 
     707           0 :   libgrpp_nuclear_attraction_integrals_charged_ball(
     708             :       shell_A, shell_B, charge_origin, *charge, *r_rms, matrix);
     709             : 
     710           0 :   libgrpp_delete_shell(shell_A);
     711           0 :   libgrpp_delete_shell(shell_B);
     712           0 : }
     713             : 
     714           0 : void libgrpp_nuclear_attraction_integrals_gaussian_model_(
     715             :     // contracted Gaussian A
     716             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     717             :     double *alpha_A,
     718             :     // contracted Gaussian B
     719             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     720             :     double *alpha_B,
     721             :     // potential definition
     722             :     double *charge_origin, int32_t *charge, double *r_rms,
     723             :     // answer
     724             :     double *matrix) {
     725           0 :   libgrpp_shell_t *shell_A =
     726           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     727           0 :   libgrpp_shell_t *shell_B =
     728           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     729             : 
     730           0 :   libgrpp_nuclear_attraction_integrals_gaussian_model(
     731             :       shell_A, shell_B, charge_origin, *charge, *r_rms, matrix);
     732             : 
     733           0 :   libgrpp_delete_shell(shell_A);
     734           0 :   libgrpp_delete_shell(shell_B);
     735           0 : }
     736             : 
     737           0 : void libgrpp_nuclear_attraction_integrals_fermi_model_(
     738             :     // contracted Gaussian A
     739             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     740             :     double *alpha_A,
     741             :     // contracted Gaussian B
     742             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     743             :     double *alpha_B,
     744             :     // potential definition
     745             :     double *charge_origin, int32_t *charge, double *fermi_param_c,
     746             :     double *fermi_param_a,
     747             :     // answer
     748             :     double *matrix) {
     749           0 :   libgrpp_shell_t *shell_A =
     750           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     751           0 :   libgrpp_shell_t *shell_B =
     752           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     753             : 
     754           0 :   libgrpp_nuclear_attraction_integrals_fermi_model(
     755             :       shell_A, shell_B, charge_origin, *charge, *fermi_param_c, *fermi_param_a,
     756             :       matrix);
     757             : 
     758           0 :   libgrpp_delete_shell(shell_A);
     759           0 :   libgrpp_delete_shell(shell_B);
     760           0 : }
     761             : 
     762           0 : void libgrpp_nuclear_attraction_integrals_fermi_bubble_model_(
     763             :     // contracted Gaussian A
     764             :     double *origin_A, int32_t *L_A, int32_t *num_primitives_A, double *coeffs_A,
     765             :     double *alpha_A,
     766             :     // contracted Gaussian B
     767             :     double *origin_B, int32_t *L_B, int32_t *num_primitives_B, double *coeffs_B,
     768             :     double *alpha_B,
     769             :     // potential definition
     770             :     double *charge_origin, int32_t *charge, double *fermi_param_c,
     771             :     double *fermi_param_a, double *param_k,
     772             :     // answer
     773             :     double *matrix) {
     774           0 :   libgrpp_shell_t *shell_A =
     775           0 :       libgrpp_new_shell(origin_A, *L_A, *num_primitives_A, coeffs_A, alpha_A);
     776           0 :   libgrpp_shell_t *shell_B =
     777           0 :       libgrpp_new_shell(origin_B, *L_B, *num_primitives_B, coeffs_B, alpha_B);
     778             : 
     779           0 :   libgrpp_nuclear_attraction_integrals_fermi_bubble_model(
     780             :       shell_A, shell_B, charge_origin, *charge, *fermi_param_c, *fermi_param_a,
     781             :       *param_k, matrix);
     782             : 
     783           0 :   libgrpp_delete_shell(shell_A);
     784           0 :   libgrpp_delete_shell(shell_B);
     785           0 : }
     786             : 
     787             : /*
     788             :  * Fortran interface to the nuclear models
     789             :  */
     790             : 
     791           0 : void libgrpp_estimate_nuclear_rms_radius_johnson_1985_(int32_t *A,
     792             :                                                        double *R_rms) {
     793           0 :   *R_rms = libgrpp_estimate_nuclear_rms_radius_johnson_1985(*A);
     794           0 : }
     795             : 
     796           0 : void libgrpp_estimate_nuclear_rms_radius_golovko_2008_(int32_t *A,
     797             :                                                        double *R_rms) {
     798           0 :   *R_rms = libgrpp_estimate_nuclear_rms_radius_golovko_2008(*A);
     799           0 : }
     800             : 
     801           0 : void libgrpp_estimate_fermi_model_parameters_(double *R_rms, double *c,
     802             :                                               double *a, int32_t *err_code) {
     803           0 :   *err_code = (int32_t)libgrpp_estimate_fermi_model_parameters(*R_rms, c, a);
     804           0 : }
     805             : 
     806           0 : void libgrpp_charge_density_ball_(double *r, double *Z, double *R_rms,
     807             :                                   double *rho) {
     808           0 :   *rho = libgrpp_charge_density_ball(*r, *Z, *R_rms);
     809           0 : }
     810             : 
     811           0 : void libgrpp_charge_density_gaussian_(double *r, double *Z, double *R_rms,
     812             :                                       double *rho) {
     813           0 :   *rho = libgrpp_charge_density_gaussian(*r, *Z, *R_rms);
     814           0 : }
     815             : 
     816           0 : void libgrpp_charge_density_fermi_(double *r, double *Z, double *c, double *a,
     817             :                                    double *rho) {
     818           0 :   *rho = libgrpp_charge_density_fermi(*r, *Z, *c, *a);
     819           0 : }
     820             : 
     821           0 : void libgrpp_charge_density_fermi_bubble_(double *r, double *Z, double *c,
     822             :                                           double *a, double *k, double *rho) {
     823           0 :   *rho = libgrpp_charge_density_fermi_bubble(*r, *Z, *c, *a, *k);
     824           0 : }
     825             : 
     826           0 : void libgrpp_coulomb_potential_point_(double *r, double *Z, double *potential) {
     827           0 :   *potential = libgrpp_coulomb_potential_point(*r, *Z);
     828           0 : }
     829             : 
     830           0 : void libgrpp_coulomb_potential_ball_(double *r, double *Z, double *R_rms,
     831             :                                      double *potential) {
     832           0 :   *potential = libgrpp_coulomb_potential_ball(*r, *Z, *R_rms);
     833           0 : }
     834             : 
     835           0 : void libgrpp_coulomb_potential_gaussian_(double *r, double *Z, double *R_rms,
     836             :                                          double *potential) {
     837           0 :   *potential = libgrpp_coulomb_potential_gaussian(*r, *Z, *R_rms);
     838           0 : }
     839             : 
     840           0 : void libgrpp_coulomb_potential_fermi_(double *r, double *Z, double *c,
     841             :                                       double *a, double *potential) {
     842           0 :   *potential = libgrpp_coulomb_potential_fermi(*r, *Z, *c, *a);
     843           0 : }
     844             : 
     845           0 : void libgrpp_coulomb_potential_fermi_bubble_(double *r, double *Z, double *c,
     846             :                                              double *a, double *k,
     847             :                                              double *potential) {
     848           0 :   *potential = libgrpp_coulomb_potential_fermi_bubble(*r, *Z, *c, *a, *k);
     849           0 : }
     850             : 
     851           0 : void libgrpp_rms_radius_fermi_(int32_t *Z, double *c, double *a,
     852             :                                double *r_rms) {
     853           0 :   *r_rms = libgrpp_rms_radius_fermi(*Z, *c, *a);
     854           0 : }
     855             : 
     856           0 : void libgrpp_rms_radius_fermi_bubble_(int32_t *Z, double *c, double *a,
     857             :                                       double *k, double *r_rms) {
     858           0 :   *r_rms = libgrpp_rms_radius_fermi_bubble(*Z, *c, *a, *k);
     859           0 : }

Generated by: LCOV version 1.15