gbasis icon indicating copy to clipboard operation
gbasis copied to clipboard

[REQUEST] Allow Gbasis to use normalized primitive contraction coefficients

Open leila-pujal opened this issue 1 year ago • 1 comments

Is your feature request related to a problem? Please describe.

Currently Gbasis works with Cartesian primitives defined as:

$g_i(\mathbf{r} | \mathbf{R}_A, \mathbf{a}) = N(\alpha_i, \mathbf{a}) (x - X_A)^{a_x} (y - Y_A)^{a_y} (z - Z_A)^{a_z} \exp \left(-\alpha_i |\mathbf{r} - \mathbf{R}_A|^2 \right)$

Where $N(\alpha_i, \mathbf{a})$ is the normalization constant of the Cartesian primitive defined as:

$N(\alpha_i, \mathbf{a}) = \sqrt { \left(\frac{2\alpha_i}{\pi}\right)^\frac{3}{2} \frac{(4\alpha_i)^{a_x + a_y + a_z}}{(2a_x - 1)!! (2a_y - 1)!! (2a_z - 1)!!}} $

Gbasis assumes for each set of contraction primitives, contraction coefficients do not include $N(\alpha_i, \mathbf{a})$. There could be packages though where generated basis sets already include primitive normalization constants in the contraction coefficients for each primitive as shown in #194 . This issue suggests an enhancement to Gbasis code to allow for basis sets with primitive normalization constants already included in the contraction coefficients.

Is there a specific integral/formula that you would like implemented?

Is there a change to the code or algorithm you would like to see?

The normalization constant for each cartesian primitive is calculated at the contractions module in norm_prim_cart. Primitive normalization is used for all the integrals and density evaluations usually when the a lower level function is called. In the case of overlap for example when the Overlap class calls _compute_multipole_moment_integrals in construct_array_contraction the norm_prim_cart information is passed. There would be two ways to include this option into Gbasis.

  • As an argument to contractions and can be specified also when using parsers or wrappers. Then internally norm_prim_cart could read that flag and generate ones instead of the normalization constants
  • As an argument to the methods they use the normalization constants (most of them).

Additional info: Gbasis works at the low level only with cartesian primitives. Spherical primitives are converted to Cartesian here in generate_transformation. There the normalization applied is a factor combining Cartesian and Spherical normalizations:

$ \frac{N_s(\alpha_i, \ell)}{N(\alpha_i, \mathbf{a})} = \frac{ \sqrt{ \left(\frac{2 \alpha_i}{\pi} \right)^{\frac{3}{2}} \frac{(4 \alpha_i)^{\ell}}{(2\ell - 1)!!} } }{ \sqrt{ \left(\frac{2 \alpha_i}{\pi} \right)^{\frac{3}{2}} (4 \alpha_i)^{\ell} } \sqrt{ \frac{1}{(2 a_x -1)!! (2 a_y -1)!! (2 a_z -1)!!} } }\\ = \sqrt{\frac{(2 a_x -1)!! (2 a_y -1)!! (2 a_z -1)!!}{(2\ell - 1)!!}}$

generate_transformation uses the last simplification here but I think we could refactor that part to only use the spherical normalization if the contraction coefficients already include the cartesian primitive normalization.

Additional context

leila-pujal avatar Aug 02 '24 15:08 leila-pujal

I like the idea of handling this as a preprocessing step (parser/wrapper level). Just a pre-processor-function that just converts any user-specified basis set to a gbasis-format basis set by "undoing" the primitive normalization and adjusting the contraction coefficients accordingly. We have to expect that the user knows what convention the given basis set uses because, if they do not, then there is no (robust and general) way to detect it.

PaulWAyers avatar Aug 02 '24 17:08 PaulWAyers

Hey @PaulWAyers

I would like to work on this issue. can you please tell me about your view on the topic if we should handle the normalized primitives with a flag and return ones as per the suggestion of @leila-pujal or if we ought to wrap/parse the basis set to a gbasis-format basis set?

My remarks on this are:

  • The implementation of the first approach (returning ones for the normalization constant by providing an optional? argument in the contraction class) would be easier from the coding side, and also the user side as doesn't require additional imports for the preprocessing.
  • If we can avoid the computation and mathematical formula, it would be better. This is the case I think with the first approach, because we don't need to undo the normalization.

I have done some search across the repo and found these to be the distinct references to norm (maybe there are more indirectly referenced such as generate_transformation?). Please have a look to see if returning ones for the norm constant would be correct.

construct_array_contraction

cleanup_intermediate_integrals

_eval_first_second_order_deriv_contractions

On your approval, I can work on this issue and implement the approach you suggest.

3laaHisham avatar Mar 15 '25 09:03 3laaHisham

I would defer to @leila-pujal and @FarnazH as to the ultimate decision on which is the better approach. My preference is the "flag" approach at the parser/wrapper stage.

PaulWAyers avatar Mar 16 '25 19:03 PaulWAyers

Hi @PaulWAyers and @3laaHisham, sorry for the late reply to this. @PaulWAyers, my preferred approach is the flag to the parser/wrapper functions too. This approach I believe is less prone to user errors. Then for the actual implementation of the feature, the easy fix is to make the normalization function return ones or go through the code and use the flag to avid the explicit normalization. With this last option, we would have a more efficient code, as @3laaHisham pointed out in his comment. I am happy to provide code support if is needed just let me know.

leila-pujal avatar Mar 27 '25 00:03 leila-pujal