MADNESS  0.10.1
response_functions.h
Go to the documentation of this file.
1 /* Copyright 2021 Adrian Hurtado
2  * Small class to hold response functions and to interact with KAIN solver.
3  */
4 
5 #ifndef SRC_APPS_MOLRESPONSE_RESPONSE_FUNCTIONS_H_
6 #define SRC_APPS_MOLRESPONSE_RESPONSE_FUNCTIONS_H_
7 
8 #include <madness/mra/mra.h>
9 #include <madness/mra/operator.h>
10 
11 #include <algorithm>
12 #include <cstdint>
13 #include <memory>
14 #include <vector>
15 
16 // real_function_3d == Function<double,3>
17 namespace madness {
18 
19  typedef std::vector<vector_real_function_3d> response_matrix;
20 
21  /* *
22  * @brief response matrix holds response vectors for response state
23  *
24  */
25  struct response_space {
26  // Member variables
27  /**
28  * @brief vector of vector of real 3d functions
29  *
30  */
31 
32  public:
33  size_t num_states; // Num. of resp. states
34  size_t num_orbitals;// Num. of ground states
36  std::list<size_t> active;
37 
38  // Member functions
39  public:
40  /**
41  * @brief default Construct a new response space object
42  * num_states(0)
43  * num_orbitals(0)
44  * x() default constructor of std::vector
45  */
47 
48  void reset_active() {
49  active.resize(num_states);
50  size_t i{0};
51  for (auto &ai: active) { ai = i++; }
52  }
53 
54  // Copy constructor
55  /**
56  * @brief copy construct a new response space object
57  * we are using copying defined by std:vector
58  * we copy madness functions therefore we are copying pointers to function
59  * implementations
60  * @param y
61  */
63  : num_states(y.size()), num_orbitals(y.size_orbitals()), x(y.x), active(y.active) {}
64 
65  // assignment
66  // Copy assignment should copy the members of y and leave y Unchanged
67  // The problem is what happens when we copy two functions
69  //
70  if (this != &y) {// is it the same object?
71  this->num_states = y.size();
72  this->num_orbitals = y.size_orbitals();
73  this->x = y.x;
74  this->active = y.active;
75  if (x.size() != num_states) { x.resize(num_states); }
76  }
77  return *this;//
78  }
79 
81  //
82  this->num_states = y.size();
83  this->num_orbitals = y[0].size();
84  this->x = y;
85  return *this;//
86  }
87  // Initialize functions to zero
88  // m = number of response states
89  // n = number of ground state orbitals
90 
91  // Zero Constructor constructs m vectors
92  /**
93  * @brief Construct a new response space with zero functions
94  *
95  * @param world
96  * @param num_states
97  * @param num_orbitals
98  */
99  response_space(World &world, size_t num_states, size_t num_orbitals)
101  active(num_states) {
102  for (auto &state: x) { state = vector_real_function_3d(num_orbitals); }
103  reset_active();
104  //world.gop.fence();
105  }
106  // Conversion from respones_matrix
107  /**
108  * @brief Construct a new response space object from vector of functions
109  *
110  * @param x
111  */
113  : num_states(x.size()), num_orbitals(x[0].size()), x(x), active(num_states) {
114  reset_active();
115  }
116 
117  // Determines if two ResponseFunctions are the same size
118  friend bool same_size(const response_space &a, const response_space &b) {
119  return ((a.size() == b.size()) && (a.size_orbitals() == b.size_orbitals()));
120  }
121  // Returns a deep copy
122  [[nodiscard]] response_space copy() const {
123  World &world = x[0][0].world();
124  response_space result(*this);
125  std::transform(x.begin(), x.end(), result.x.begin(),
126  [&world](const vector_real_function_3d &xi) { return madness::copy(world, xi, false); });
127  world.gop.fence();
128  return result;
129  }
130  [[nodiscard]] response_space copy(const std::shared_ptr<WorldDCPmapInterface<Key<3>>> &pmap,
131  bool fence = false) const {
132  auto &world = x[0][0].world();
133  response_space result(*this);
134  std::transform(x.begin(), x.end(), result.x.begin(),
135  [&](const auto &xi) { return madness::copy(world, xi, pmap, fence); });
136  world.gop.fence();
137  return result;
138  }
139 
140  vector_real_function_3d &operator[](size_t i) { return x.at(i); }
141  const vector_real_function_3d &operator[](size_t i) const { return x.at(i); }
142 
143  friend auto
145  const std::function<void(vector_real_function_3d &)> &func) {
146  auto &world = A.x[0][0].world();
147  for (auto &i: A.active) { func(A.x[i]); }
148  world.gop.fence();
149  }
150 
151  friend auto oop_unary_apply(
152  const response_space &A,
154  -> response_space {
155  auto result = A.copy();
156  auto &world = result.x[0][0].world();
157  for (auto &i: result.active) { result.x[i] = func(A.x[i]); }
158  world.gop.fence();
159  return result;
160  }
161 
162  friend auto
166  -> response_space {
168 
169  response_space result = A.copy();// create zero_functions
170  auto &world = result.x[0][0].world();
171 
172  for (const auto &i: result.active) {
173  auto ax = result.x[i];
174  auto bx = B.x[i];
175  result.x[i] = func(ax, bx);
176  }
177  world.gop.fence();
178  return result;
179  }
180 
181  template<class T>
182  friend auto binary_inplace(response_space &A, const response_space &B, const T &func) {
184  auto &world = A.x[0][0].world();
185  for (const auto &i: A.active) {
186  auto ax = A.x[i];
187  auto bx = B.x[i];
188  func(ax, bx);
189  }
190  world.gop.fence();
191 
192  return A;
193  }
194 
196 
197  MADNESS_ASSERT(size() > 0);
198  MADNESS_ASSERT(same_size(*this, rhs_y));// assert that same size
199 
200  auto result = binary_apply(*this, rhs_y, [&](auto xi, auto vi) {
201  return gaxpy_oop(1.0, xi, 1.0, vi, false);
202  });
203  return result;
204  }
205 
207  MADNESS_ASSERT(size() > 0);
208  MADNESS_ASSERT(same_size(*this, rhs_y));// assert that same size
209  auto result = binary_apply(*this, rhs_y, [&](auto xi, auto vi) {
210  return gaxpy_oop(1.0, xi, -1.0, vi, false);
211  });
212  return result;
213  }
214 
215  friend response_space operator*(const response_space &y, double a) {
216  World &world = y.x.at(0).at(0).world();
217  auto multiply_scalar = [&](vector_real_function_3d &vi) {
218  madness::scale(world, vi, a, false);
219  };
220  auto result = y.copy();
221  inplace_unary_apply(result, multiply_scalar);
222  return result;
223  }
224 
226  World &world = y.x.at(0).at(0).world();
227  auto multiply_scalar = [&](vector_real_function_3d &vi) {
228  madness::scale(world, vi, a, false);
229  };
230  auto result = y.copy();
231  inplace_unary_apply(result, multiply_scalar);
232  return result;
233  }
234 
236  World &world = this->x[0][0].world();
237  auto multiply_scalar = [&](vector_real_function_3d &vi) {
238  madness::scale(world, vi, a, false);
239  };
240  inplace_unary_apply(*this, multiply_scalar);
241  return *this;
242  }
243 
244  // Scaling all internal functions by an external function
245  // g[i][j] = x[i][j] * f
247  World &world = a.x.at(0).at(0).world();
248  auto multiply_scalar_function = [&](const vector_real_function_3d &vi) {
249  return mul(world, f, vi, false);
250  };
251  return oop_unary_apply(a, multiply_scalar_function);
252  }
253 
254  // Scaling all internal functions by an external function
255  // g[i][j] = x[i][j] * f
257  // commutative property
258  return a * f;
259  }
260 
262  World &world = x[0][0].world();
263 
264  auto multiply_scalar_function = [&](const vector_real_function_3d &vi) {
265  return mul(world, f, vi, false);
266  };
267 
268  return oop_unary_apply(*this, multiply_scalar_function);
269  }
270 
272  MADNESS_ASSERT(a.size() > 0);
273  MADNESS_ASSERT(!a[0].empty());
274  World &world = a[0][0].world();
275 
276  auto response_transform = [&](const vector_real_function_3d &vi) {
277  return transform(world, vi, b, false);
278  };
279  return oop_unary_apply(a, response_transform);
280  }
281 
282  // KAIN must have this
284  MADNESS_ASSERT(same_size(*this, b));
285  auto &world = x[0][0].world();
286 
287  auto a_plus_equal_b = [&](vector_real_function_3d &a,
288  const vector_real_function_3d &g) {
289  gaxpy(world, 1.0, a, 1.0, g, false);
290  };
291  binary_inplace(*this, b, a_plus_equal_b);
292  return *this;
293 
294 
295  return *this;
296  }
297 
298 
299  // Mimicking std::vector with these 4
301  x.push_back(f);
302  num_states++;
303  // print("im calling response_space push back");
304 
305  // Be smart with g_states
306  if (num_orbitals > 0) MADNESS_ASSERT(num_orbitals == f.size());
307  else {// g_states == 0 (empty vector)
308  num_orbitals = f.size();
309  }
310  }
311 
312  void pop_back() {
314  x.pop_back();
315  num_states--;
316 
317  // Be smart with g_states
318  if (num_states == 0) {// removed last item
319  num_orbitals = 0;
320  }
321  }
322 
323  void clear() {
324  x.clear();
325  num_states = 0;
326  num_orbitals = 0;
327  }
328 
329  auto begin() { return x.begin(); }
330 
331  auto end() { return x.end(); }
332 
333  const auto begin() const { return x.begin(); }
334 
335  [[nodiscard]] const auto end() const { return x.end(); }
336 
337  size_t size() const { return num_states; }
338 
339  size_t size_orbitals() const { return num_orbitals; }
340 
341  // Mimicing standard madness calls with these 3
342  void zero() {
343  auto &world = x[0][0].world();
344  std::generate(x.begin(), x.end(),
345  [&]() { return zero_functions<double, 3>(world, num_orbitals, true); });
346 
347  /*
348  for (size_t k = 0; k < num_states; k++) {
349  x[k] = zero_functions<double, 3>(x[0][0].world(), num_orbitals);
350  }
351  */
352  }
353 
354  void compress_rf() {
355  //for (size_t k = 0; k < num_states; k++) { compress(x[0][0].world(), x[k], true); }
356  auto &world = x[0][0].world();
357  std::for_each(x.begin(), x.end(), [&](auto &xi) { compress(world, xi, true); });
358  }
359 
360  void reconstruct_rf() {
361  //for (size_t k = 0; k < num_states; k++) { reconstruct(x[0][0].world(), x[k], true); }
362  auto &world = x[0][0].world();
363  std::for_each(x.begin(), x.end(), [&](auto &xi) { reconstruct(world, xi, true); });
364  }
365 
366  void truncate_rf() {
368  /*
369  for (size_t k = 0; k < num_states; k++) {
370  truncate(x[0][0].world(), x[k], FunctionDefaults<3>::get_thresh(), true);
371  }
372  */
373  }
374 
375  void truncate_rf(double tol) {
376  auto &world = x[0][0].world();
377  std::for_each(x.begin(), x.end(), [&](auto &xi) { truncate(world, xi, tol, true); });
378  /*
379  for (size_t k = 0; k < num_states; k++) { truncate(x[0][0].world(), x[k], tol, true); }
380  */
381  }
382 
383  // Returns norms of each state
385  auto &world = x[0][0].world();
386  Tensor<double> answer(num_states);
387  for (size_t i = 0; i < num_states; i++) { answer(i) = madness::norm2(world, x[i]); }
388 
389  world.gop.fence();
390 
391  return answer;
392  }
393 
394  // Scales each state (read: entire row) by corresponding vector element
395  // new[i] = old[i] * mat[i]
396  void scale(Tensor<double> &mat) {
397  for (size_t i = 0; i < num_states; i++)
398  madness::scale(x[0][0].world(), x[i], mat[i], false);
399  // x[i] = x[i] * mat[i];
400  }
401 
402  friend bool operator==(const response_space &a, const response_space &y) {
403  if (!same_size(a, y)) return false;
404  for (size_t b = 0; b < a.size(); ++b) {
405  for (size_t k = 0; b < a.size_orbitals(); ++k) {
406  if ((a[b][k] - y[b][k]).norm2() >
407  FunctionDefaults<3>::get_thresh())// this may be strict
408  return false;
409  }
410  }
411  return true;
412  }
413 
415  const response_space &b) {
416  MADNESS_ASSERT(a.size() > 0);
417  MADNESS_ASSERT(a.size() == b.size());
418  MADNESS_ASSERT(!a[0].empty());
419  MADNESS_ASSERT(a[0].size() == b[0].size());
420 
421  World &world = a[0][0].world();
422 
423  size_t dim_1 = a.size();
424  size_t dim_2 = b[0].size();
425  // Need to take transpose of each input ResponseFunction
426  response_space aT(world, dim_2, dim_1);
427  response_space bT(world, dim_2, dim_1);
428  for (size_t i = 0; i < dim_1; i++) {
429  for (size_t j = 0; j < dim_2; j++) {
430  aT[j][i] = a[i][j];
431  bT[j][i] = b[i][j];
432  }
433  }
434  // Container for result
435  Tensor<double> result(dim_1, dim_1);
436  for (size_t p = 0; p < dim_2; p++) { result += matrix_inner(world, aT[p], bT[p]); }
437  return result;
438  }
439  };
440 
441  // Final piece for KAIN
442  inline double inner(response_space &a, response_space &b) {
443  MADNESS_ASSERT(a.size() > 0);
444  MADNESS_ASSERT(a.size() == b.size());
445  MADNESS_ASSERT(!a[0].empty());
446  MADNESS_ASSERT(a[0].size() == b[0].size());
447 
448  double value = 0.0;
449 
450  for (unsigned int i = 0; i < a.size(); i++) {
451  // vmra.h function
452  value += inner(a[i], b[i]);
453  }
454 
455  return value;
456  }
457 
459  // Final piece for KAIN
460 
461 }// End namespace madness
462 #endif// SRC_APPS_MOLRESPONSE_RESPONSE_FUNCTIONS_H_
463 
464 // Deuces
real_convolution_3d A(World &world)
Definition: DKops.h:230
Definition: test_ar.cc:118
Definition: test_ar.cc:141
FunctionDefaults holds default paramaters as static class members.
Definition: funcdefaults.h:204
Key is the index for a node of the 2^NDIM-tree.
Definition: key.h:66
Interface to be provided by any process map.
Definition: worlddc.h:82
void fence(bool debug=false)
Synchronizes all processes in communicator AND globally ensures no pending AM or tasks.
Definition: worldgop.cc:161
A parallel world class.
Definition: world.h:132
WorldGopInterface & gop
Global operations.
Definition: world.h:205
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition: derivatives.cc:72
std::vector< Fcwf > transform(World &world, std::vector< Fcwf > &a, Tensor< std::complex< double >> U)
Definition: fcwf.cc:477
static double function(const coord_3d &r)
Normalized gaussian.
Definition: functionio.cc:100
auto T(World &world, response_space &f) -> response_space
Definition: global_functions.cc:34
static const long vi
Definition: he.cc:17
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition: madness_exception.h:134
Main include file for MADNESS and defines Function interface.
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
Function< TENSOR_RESULT_TYPE(Q, T), NDIM > mul(const Q alpha, const Function< T, NDIM > &f, bool fence=true)
Returns new function equal to alpha*f(x) with optional fence.
Definition: mra.h:1701
response_space scale(response_space a, double b)
std::vector< vector_real_function_3d > response_matrix
Definition: response_functions.h:19
double norm2(World &world, const std::vector< Function< T, NDIM > > &v)
Computes the 2-norm of a vector of functions.
Definition: vmra.h:851
std::vector< real_function_3d > vector_real_function_3d
Definition: functypedefs.h:79
Function< TENSOR_RESULT_TYPE(L, R), NDIM > gaxpy_oop(TENSOR_RESULT_TYPE(L, R) alpha, const Function< L, NDIM > &left, TENSOR_RESULT_TYPE(L, R) beta, const Function< R, NDIM > &right, bool fence=true)
Returns new function alpha*left + beta*right optional fence and no automatic compression.
Definition: mra.h:1917
std::shared_ptr< FunctionFunctorInterface< double, 3 > > func(new opT(g))
NDIM & f
Definition: mra.h:2416
NDIM const Function< R, NDIM > & g
Definition: mra.h:2416
double inner(response_space &a, response_space &b)
Definition: response_functions.h:442
std::vector< Function< TENSOR_RESULT_TYPE(T, R), NDIM > > transform(World &world, const std::vector< Function< T, NDIM > > &v, const Tensor< R > &c, bool fence=true)
Transforms a vector of functions according to new[i] = sum[j] old[j]*c[j,i].
Definition: vmra.h:689
void matrix_inner(DistributedMatrix< T > &A, const std::vector< Function< T, NDIM > > &f, const std::vector< Function< T, NDIM > > &g, bool sym=false)
Definition: distpm.cc:46
void gaxpy(const double a, ScalarResult< T > &left, const double b, const T &right, const bool fence=true)
the result type of a macrotask must implement gaxpy
Definition: macrotaskq.h:140
auto transposeResponseMatrix(const response_matrix &x) -> response_matrix
Definition: x_space.cc:145
static const double b
Definition: nonlinschro.cc:119
static const double a
Definition: nonlinschro.cc:118
Implements most functionality of separated operators.
static const long k
Definition: rk.cc:44
const double xi
Exponent for delta function approx.
Definition: siam_example.cc:60
Definition: response_functions.h:25
response_space()
default Construct a new response space object num_states(0) num_orbitals(0) x() default constructor o...
Definition: response_functions.h:46
response_space & operator=(const response_space &y)
Definition: response_functions.h:68
response_space operator-(const response_space &rhs_y) const
Definition: response_functions.h:206
friend bool same_size(const response_space &a, const response_space &b)
Definition: response_functions.h:118
void push_back(const vector_real_function_3d &f)
Definition: response_functions.h:300
response_space(const response_space &y)
copy construct a new response space object we are using copying defined by std:vector we copy madness...
Definition: response_functions.h:62
friend response_space operator*(const response_space &a, const Function< double, 3 > &f)
Definition: response_functions.h:246
response_space(const response_matrix &x)
Construct a new response space object from vector of functions.
Definition: response_functions.h:112
friend auto binary_apply(const response_space &A, const response_space &B, const std::function< vector_real_function_3d(vector_real_function_3d, vector_real_function_3d)> &func) -> response_space
Definition: response_functions.h:163
response_space operator+(const response_space &rhs_y) const
Definition: response_functions.h:195
response_space & operator+=(const response_space &b)
Definition: response_functions.h:283
void reset_active()
Definition: response_functions.h:48
Tensor< double > norm2()
Definition: response_functions.h:384
size_t num_orbitals
Definition: response_functions.h:34
response_space copy(const std::shared_ptr< WorldDCPmapInterface< Key< 3 >>> &pmap, bool fence=false) const
Definition: response_functions.h:130
friend auto inplace_unary_apply(response_space &A, const std::function< void(vector_real_function_3d &)> &func)
Definition: response_functions.h:144
friend auto binary_inplace(response_space &A, const response_space &B, const T &func)
Definition: response_functions.h:182
friend bool operator==(const response_space &a, const response_space &y)
Definition: response_functions.h:402
friend response_space operator*(const response_space &y, double a)
Definition: response_functions.h:215
size_t num_states
vector of vector of real 3d functions
Definition: response_functions.h:33
friend response_space operator*(const response_space &a, const Tensor< double > &b)
Definition: response_functions.h:271
const auto begin() const
Definition: response_functions.h:333
void truncate_rf(double tol)
Definition: response_functions.h:375
void reconstruct_rf()
Definition: response_functions.h:360
friend response_space operator*(double a, response_space &y)
Definition: response_functions.h:225
response_space & operator*=(double a)
Definition: response_functions.h:235
friend Tensor< double > response_space_inner(const response_space &a, const response_space &b)
Definition: response_functions.h:414
friend auto oop_unary_apply(const response_space &A, const std::function< vector_real_function_3d(const vector_real_function_3d &)> &func) -> response_space
Definition: response_functions.h:151
void zero()
Definition: response_functions.h:342
void pop_back()
Definition: response_functions.h:312
response_space(World &world, size_t num_states, size_t num_orbitals)
Construct a new response space with zero functions.
Definition: response_functions.h:99
response_space operator*(const Function< double, 3 > &f)
Definition: response_functions.h:261
size_t size() const
Definition: response_functions.h:337
void compress_rf()
Definition: response_functions.h:354
void truncate_rf()
Definition: response_functions.h:366
vector_real_function_3d & operator[](size_t i)
Definition: response_functions.h:140
response_space copy() const
Definition: response_functions.h:122
auto end()
Definition: response_functions.h:331
friend response_space operator*(const Function< double, 3 > &f, const response_space &a)
Definition: response_functions.h:256
const auto end() const
Definition: response_functions.h:335
void scale(Tensor< double > &mat)
Definition: response_functions.h:396
auto begin()
Definition: response_functions.h:329
size_t size_orbitals() const
Definition: response_functions.h:339
response_matrix x
Definition: response_functions.h:35
std::list< size_t > active
Definition: response_functions.h:36
const vector_real_function_3d & operator[](size_t i) const
Definition: response_functions.h:141
response_space & operator=(const response_matrix &y)
Definition: response_functions.h:80
void clear()
Definition: response_functions.h:323