(git:ed6f26b)
Loading...
Searching...
No Matches
grpp_lmatrix.c
Go to the documentation of this file.
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 * Functions for construction of matrices of the angular momentum operator L
17 * in the bases of either real or complex spherical harmonics.
18 */
19
20#include "grpp_lmatrix.h"
21
22#include <complex.h>
23#include <math.h>
24#include <stdlib.h>
25#include <string.h>
26
27static void get_transformation_coeffs_csh_to_rsh(int m, double complex *a,
28 double complex *b);
29
30/**
31 * Constructs matrices of the Lx, Ly, Lz operators for the given angular
32 * momentum L in the basis of real spherical harmonics (rsh).
33 */
35 double *ly_matrix,
36 double *lz_matrix) {
37 int dim = 2 * L + 1;
38
39 // set all matrices to zero
40 memset(lx_matrix, 0, dim * dim * sizeof(double));
41 memset(ly_matrix, 0, dim * dim * sizeof(double));
42 memset(lz_matrix, 0, dim * dim * sizeof(double));
43
44 double *lx_matrix_csh = calloc(dim * dim, sizeof(double));
45 double *ly_matrix_csh = calloc(dim * dim, sizeof(double));
46 double *lz_matrix_csh = calloc(dim * dim, sizeof(double));
47
49 ly_matrix_csh, lz_matrix_csh);
50
51 for (int m1 = -L; m1 <= L; m1++) {
52 for (int m2 = -L; m2 <= L; m2++) {
53
54 // coefficients: S_lm = a * Y_{l,-m} + b * Y_{l,m}
55 double complex a1, b1;
56 double complex a2, b2;
57 get_transformation_coeffs_csh_to_rsh(m1, &a1, &b1); // bra
58 get_transformation_coeffs_csh_to_rsh(m2, &a2, &b2); // ket
59
60 int m1m = -abs(m1);
61 int m1p = +abs(m1);
62 int m2m = -abs(m2);
63 int m2p = +abs(m2);
64
65 double complex lx = 0.0 + 0.0 * I;
66 lx += conj(a1) * a2 * lx_matrix_csh[dim * (m1m + L) + (m2m + L)];
67 lx += conj(a1) * b2 * lx_matrix_csh[dim * (m1m + L) + (m2p + L)];
68 lx += conj(b1) * a2 * lx_matrix_csh[dim * (m1p + L) + (m2m + L)];
69 lx += conj(b1) * b2 * lx_matrix_csh[dim * (m1p + L) + (m2p + L)];
70
71 double complex ly = 0.0 + 0.0 * I;
72 ly += conj(a1) * a2 * ly_matrix_csh[dim * (m1m + L) + (m2m + L)];
73 ly += conj(a1) * b2 * ly_matrix_csh[dim * (m1m + L) + (m2p + L)];
74 ly += conj(b1) * a2 * ly_matrix_csh[dim * (m1p + L) + (m2m + L)];
75 ly += conj(b1) * b2 * ly_matrix_csh[dim * (m1p + L) + (m2p + L)];
76
77 double complex lz = 0.0 + 0.0 * I;
78 lz += conj(a1) * a2 * lz_matrix_csh[dim * (m1m + L) + (m2m + L)];
79 lz += conj(a1) * b2 * lz_matrix_csh[dim * (m1m + L) + (m2p + L)];
80 lz += conj(b1) * a2 * lz_matrix_csh[dim * (m1p + L) + (m2m + L)];
81 lz += conj(b1) * b2 * lz_matrix_csh[dim * (m1p + L) + (m2p + L)];
82
83 lx_matrix[(m1 + L) * dim + (m2 + L)] = cimag(lx);
84 ly_matrix[(m1 + L) * dim + (m2 + L)] = -creal(ly);
85 lz_matrix[(m1 + L) * dim + (m2 + L)] = cimag(lz);
86 }
87 }
88
89 free(lx_matrix_csh);
90 free(ly_matrix_csh);
91 free(lz_matrix_csh);
92}
93
94/**
95 * Constructs matrices of the Lx, Ly, Lz operators in the basis of
96 * complex spherical harmonics (csh) |Y_lm> for angular momentum l=L.
97 * Matrices of size (2*L+1) x (2*L+1) must be pre-allocated.
98 */
100 double *ly_matrix,
101 double *lz_matrix) {
102 int dim = 2 * L + 1;
103
104 // set all matrices to zero
105 memset(lx_matrix, 0, dim * dim * sizeof(double));
106 memset(ly_matrix, 0, dim * dim * sizeof(double));
107 memset(lz_matrix, 0, dim * dim * sizeof(double));
108
109 for (int m1 = -L; m1 <= L; m1++) {
110 for (int m2 = -L; m2 <= L; m2++) {
111
112 double lz = m2 * (m1 == m2);
113 double lp = sqrt((L - m2) * (L + m2 + 1)) * (m1 == m2 + 1); // L+
114 double lm = sqrt((L + m2) * (L - m2 + 1)) * (m1 == m2 - 1); // L-
115 double lx = 0.5 * (lp + lm);
116 double ly = 0.5 * (lp - lm);
117
118 lx_matrix[(m1 + L) * dim + (m2 + L)] = lx;
119 ly_matrix[(m1 + L) * dim + (m2 + L)] = ly;
120 lz_matrix[(m1 + L) * dim + (m2 + L)] = lz;
121 }
122 }
123}
124
125/**
126 * Real spherical harmonic S_{l,m} can be represented as a linear combination
127 * of two complex spherical harmonics:
128 * S_{l,m} = a * Y_{l,-m} + b * Y_{l,m}
129 * (except for the case m=0, where S_{l,0} = Y_{l,0})
130 *
131 * coefficients can be found elsewhere, see, for example,
132 * https://en.wikipedia.org/wiki/Table_of_spherical_harmonics
133 */
134static void get_transformation_coeffs_csh_to_rsh(int m, double complex *a,
135 double complex *b) {
136 if (m == 0) {
137 *a = 0.5;
138 *b = 0.5;
139 } else if (m < 0) {
140 *a = +1.0 * I / sqrt(2);
141 *b = -1.0 * I / sqrt(2) * pow(-1, abs(m));
142 } else { // m > 0
143 *a = +1.0 / sqrt(2);
144 *b = +1.0 / sqrt(2) * pow(-1, m);
145 }
146}
void libgrpp_construct_angular_momentum_matrices_rsh(int L, double *lx_matrix, double *ly_matrix, double *lz_matrix)
static void get_transformation_coeffs_csh_to_rsh(int m, double complex *a, double complex *b)
void libgrpp_construct_angular_momentum_matrices_csh(int L, double *lx_matrix, double *ly_matrix, double *lz_matrix)