File: multipole_prep.cc

package info (click to toggle)
ergo 3.8.2-1.1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 17,568 kB
  • sloc: cpp: 94,763; ansic: 17,785; sh: 10,701; makefile: 1,403; yacc: 127; lex: 116; awk: 23
file content (121 lines) | stat: -rw-r--r-- 3,699 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* Ergo, version 3.8.2, a program for linear scaling electronic structure
 * calculations.
 * Copyright (C) 2023 Elias Rudberg, Emanuel H. Rubensson, Pawel Salek,
 * and Anastasia Kruchinina.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Primary academic reference:
 * Ergo: An open-source program for linear-scaling electronic structure
 * calculations,
 * Elias Rudberg, Emanuel H. Rubensson, Pawel Salek, and Anastasia
 * Kruchinina,
 * SoftwareX 7, 107 (2018),
 * <http://dx.doi.org/10.1016/j.softx.2018.03.005>
 * 
 * For further information about Ergo, see <http://www.ergoscf.org>.
 */

/** @file multipole_prep.cc

    @brief This file contains preparatory stuff for computing
    multipole moments and related things.

    @author: Elias Rudberg <em>responsible</em>
*/

#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdexcept>

#include "multipole_prep.h"
#include "output.h"
#include "template_blas_common.h"

static ergo_real
slow_factorial(int n) {
  if(n == 0)
    return 1;
  return n * slow_factorial(n-1);
}

static ergo_real
get_lm_factor_slow(int l, int m) {
  return 1.0 / template_blas_sqrt(slow_factorial(l-m)*slow_factorial(l+m));
}

static void
get_l_m_from_index(int index, int* result_l, int* result_m) {
  int l = 0;
  int count = 0;
  while(count < index) {
    l++;
    count += 2 * l + 1;
  }
  int m = l + index - count;
  *result_l = l;
  *result_m = m;
}

MultipolePrepManager::MultipolePrepManager() {
  initialized_flag = 0;
  memset(prepared_lm_factor_list, 0x00, sizeof(prepared_lm_factor_list));
  memset(prepared_l_m_list, 0x00, sizeof(prepared_l_m_list));
}

void MultipolePrepManager::init() {
  if(initialized_flag)
    return;
  for(int l = 0; l <= MAX_MULTIPOLE_DEGREE; l++)
    for(int m = 0; m <= l; m++)
      prepared_lm_factor_list[l][m] = get_lm_factor_slow(l, m);
  // initialize prepared_l_m_list
  for(int A = 0; A < MAX_NO_OF_MOMENTS_PER_MULTIPOLE; A++)
    get_l_m_from_index(A, &prepared_l_m_list[A].l, &prepared_l_m_list[A].m);
  initialized_flag = 1;
}

bool MultipolePrepManager::is_initialized() const {
  if(initialized_flag == 1)
    return true;
  else
    return false;
}

ergo_real MultipolePrepManager::get_lm_factor(int l, int m) const {
  if(m >= 0)
    return prepared_lm_factor_list[l][m];
  else
    return prepared_lm_factor_list[l][-m];
}

void MultipolePrepManager::write_to_buffer ( char * dataBuffer, size_t const bufferSize ) const {
  char* p = dataBuffer;
  if(bufferSize < get_size())
    throw std::runtime_error("Error in MultipolePrepManager::write_to_buffer: bufferSize too small.");
  memcpy(p, this, sizeof(MultipolePrepManager));
}

size_t MultipolePrepManager::get_size() const {
  return sizeof(MultipolePrepManager);
}

void MultipolePrepManager::assign_from_buffer ( char const * dataBuffer, size_t const bufferSize) {
  const char* p = dataBuffer;
  if(bufferSize < sizeof(MultipolePrepManager))
    throw std::runtime_error("Error in MultipolePrepManager::assign_from_buffer: bufferSize too small.");
  memcpy(this, p, sizeof(MultipolePrepManager));
}