/c/lcao.c

https://gitlab.com/gkastlun/gpaw · C · 193 lines · 123 code · 27 blank · 43 comment · 21 complexity · ec2e163bcb577c8f6945b5e1f50392cd MD5 · raw file

  1. /* Copyright (C) 2003-2007 CAMP
  2. * Copyright (C) 2007-2009 CAMd
  3. * Please see the accompanying LICENSE file for further information. */
  4. #include "extensions.h"
  5. #include "bmgs/bmgs.h"
  6. #include "spline.h"
  7. #include <complex.h>
  8. // +-----------n
  9. // +----m +----m | +----c+m |
  10. // | | | | | | | |
  11. // | b | = | v | * | | a | |
  12. // | | | | | | | |
  13. // 0----+ 0----+ | c----+ |
  14. // | |
  15. // 0-----------+
  16. void cut(const double* a, const int n[3], const int c[3],
  17. const double* v,
  18. double* b, const int m[3])
  19. {
  20. a += c[2] + (c[1] + c[0] * n[1]) * n[2];
  21. for (int i0 = 0; i0 < m[0]; i0++)
  22. {
  23. for (int i1 = 0; i1 < m[1]; i1++)
  24. {
  25. for (int i2 = 0; i2 < m[2]; i2++)
  26. b[i2] = v[i2] * a[i2];
  27. a += n[2];
  28. b += m[2];
  29. v += m[2];
  30. }
  31. a += n[2] * (n[1] - m[1]);
  32. }
  33. }
  34. PyObject *tci_overlap(PyObject *self, PyObject *args)
  35. {
  36. /*
  37. Calculate two-center integral overlaps:
  38. -- -- l _
  39. X = > s (r) > G r Y (r)
  40. LL' -- l -- LL'L'' L''
  41. l L''
  42. or derivatives
  43. / dX \ ^ -- -- l _
  44. | -- | = R > s'(r) > G r Y (r)
  45. \ dR /LL' -- l -- LL'L'' L''
  46. l L''
  47. l _
  48. -- -- / d r Y(r) \
  49. + > s (r) > G | ----- | ,
  50. -- l -- LL'L'' \ dR /L''
  51. l L''
  52. ^
  53. where dR denotes movement of one of the centers and R is a unit vector
  54. parallel to the displacement vector r.
  55. Without derivatives, Rhat_c_obj, drLYdR_Lc_obj, and dxdR_cmi_obj must still
  56. be numpy arrays but are otherwise ignored (may have size 0).
  57. With derivatives, x_mi_obj can be likewise ignored.
  58. */
  59. int la, lb;
  60. PyArrayObject *G_LLL_obj;
  61. PyObject *spline_l;
  62. double r;
  63. PyArrayObject *rlY_L_obj, *x_mi_obj;
  64. int is_derivative;
  65. PyArrayObject *Rhat_c_obj, *drlYdR_Lc_obj, *dxdR_cmi_obj;
  66. if (!PyArg_ParseTuple(args, "iiOOdOOiOOO", &la, &lb, &G_LLL_obj, &spline_l,
  67. &r, &rlY_L_obj, &x_mi_obj,
  68. &is_derivative,
  69. &Rhat_c_obj, &drlYdR_Lc_obj,
  70. &dxdR_cmi_obj))
  71. return NULL;
  72. SplineObject *spline_obj;
  73. bmgsspline *spline;
  74. double *x_mi = (double *) PyArray_DATA(x_mi_obj);
  75. double *G_LLL = (double *) PyArray_DATA(G_LLL_obj);
  76. double *rlY_L = (double *) PyArray_DATA(rlY_L_obj);
  77. double *Rhat_c = (double *) PyArray_DATA(Rhat_c_obj);
  78. double *drlYdR_Lc = (double *) PyArray_DATA(drlYdR_Lc_obj);
  79. double *dxdR_cmi = (double *) PyArray_DATA(dxdR_cmi_obj);
  80. int Lastart = la * la;
  81. int Lbstart = lb * lb;
  82. int l = (la + lb) % 2;
  83. int nsplines = PyList_Size(spline_l);
  84. int ispline;
  85. int itemsize = PyArray_ITEMSIZE(G_LLL_obj);
  86. npy_intp *strides = PyArray_STRIDES(G_LLL_obj);
  87. npy_intp *xstrides = PyArray_STRIDES(x_mi_obj);
  88. int stride0 = strides[0] / itemsize;
  89. int stride1 = strides[1] / itemsize;
  90. int xstride = xstrides[0] / itemsize;
  91. G_LLL += Lastart * stride0 + Lbstart * stride1;
  92. for(ispline=0; ispline < nsplines; ispline++, l+=2) {
  93. int Lstart = l * l;
  94. spline_obj = (SplineObject*)PyList_GET_ITEM(spline_l, ispline);
  95. spline = &spline_obj->spline;
  96. double s, dsdr;
  97. if(is_derivative) {
  98. bmgs_get_value_and_derivative(spline, r, &s, &dsdr);
  99. } else {
  100. s = bmgs_splinevalue(spline, r);
  101. }
  102. if(fabs(s) < 1e-10) {
  103. continue;
  104. }
  105. int nm1 = 2 * la + 1;
  106. int nm2 = 2 * lb + 1;
  107. int m1, m2, L;
  108. int nL = 2 * l + 1;
  109. double srlY_L[2 * l + 1]; // Variable but very small alloc on stack
  110. for(L=0; L < nL; L++) {
  111. srlY_L[L] = s * rlY_L[Lstart + L];
  112. }
  113. if(!is_derivative) {
  114. for(m1=0; m1 < nm1; m1++) {
  115. for(m2=0; m2 < nm2; m2++) {
  116. double x = 0.0;
  117. for(L=0; L < nL; L++) {
  118. x += G_LLL[stride0 * m1 + stride1 * m2 + Lstart + L] * srlY_L[L];
  119. }
  120. x_mi[m1 * xstride + m2] += x;
  121. }
  122. }
  123. continue;
  124. }
  125. // Derivative only
  126. int c;
  127. npy_intp *dxdRstrides = PyArray_STRIDES(dxdR_cmi_obj);
  128. int dxdRstride0 = dxdRstrides[0] / itemsize;
  129. int dxdRstride1 = dxdRstrides[1] / itemsize;
  130. double dsdr_Rhat_c[3];
  131. for(c=0; c < 3; c++) {
  132. dsdr_Rhat_c[c] = dsdr * Rhat_c[c];
  133. }
  134. double s_drlYdR_Lc[nL * 3];
  135. for(L=0; L < nL; L++) {
  136. for(c=0; c < 3; c++) {
  137. s_drlYdR_Lc[L * 3 + c] = s * drlYdR_Lc[(Lstart + L) * 3 + c];
  138. }
  139. }
  140. // This loop can probably be written a lot better, but it turns out
  141. // it is so fast that we need not worry for a long time.
  142. for(m1=0; m1 < nm1; m1++) {
  143. for(m2=0; m2 < nm2; m2++) {
  144. double GrlY_mi = 0.0;
  145. for(L=0; L < nL; L++) {
  146. GrlY_mi += G_LLL[stride0 * m1 + stride1 * m2 + Lstart + L] * rlY_L[Lstart + L];
  147. }
  148. for(c=0; c < 3; c++) {
  149. double derivative = 0.0;
  150. derivative += dsdr_Rhat_c[c] * GrlY_mi;
  151. for(L=0; L < nL; L++) {
  152. derivative += G_LLL[stride0 * m1 + stride1 * m2 + Lstart + L] * s_drlYdR_Lc[L * 3 + c];
  153. }
  154. dxdR_cmi[dxdRstride0 * c + dxdRstride1 * m1 + m2] += derivative;
  155. }
  156. }
  157. }
  158. }
  159. Py_RETURN_NONE;
  160. }