MADNESS  0.10.1
x_space.h
Go to the documentation of this file.
1 // Copyright 2021 Adrian Hurtado
2 #ifndef SRC_APPS_MOLRESPONSE_X_SPACE_H_
3 #define SRC_APPS_MOLRESPONSE_X_SPACE_H_
4 
5 #include <madness/mra/mra.h>
7 
8 #include <algorithm>
9 #include <cstdint>
10 #include <memory>
11 #include <numeric>
12 #include <vector>
13 
15 
16 
17 namespace madness {
18 
19  typedef std::vector<vector_real_function_3d> response_matrix;
20 
21  struct X_space;
22 
25  auto create_response_matrix(const size_t &num_state,
26  const size_t &num_orbitals) -> response_matrix;
27  auto to_response_matrix(const X_space &x) -> response_matrix;
28  auto to_conjugate_response_matrix(const X_space &x) -> response_matrix;
29  auto to_flattened_vector(const X_space &x) -> vector_real_function_3d;
30  auto to_X_space(const response_matrix &x) -> X_space;
31  auto to_conjugate_X_space(const response_matrix &x) -> X_space;
32  struct X_space {
33  private:
34  size_t n_states; // Num. of resp. states
35  size_t n_orbitals;// Num. of ground states
36 
37  public:
39  std::list<size_t> active;
40 
41  public:
42  [[nodiscard]] size_t num_states() const { return n_states; }
43  [[nodiscard]] size_t num_orbitals() const { return n_orbitals; }
44  // default constructor
45  X_space() : n_states(0), n_orbitals(0), x(), y(), active(0) {}
46  // Copy constructor
47  void reset_active() {
48  active.resize(n_states);
49  size_t i{0};
50  for (auto &ai: active) { ai = i++; }
51  }
52  void set_active(const std::list<size_t> &new_active) {
53  active = new_active;
54  x.active = new_active;
55  y.active = new_active;
56  }
57  X_space(const X_space &A)
59  y(A.y), active(A.active) {}
60  [[nodiscard]] X_space copy() const {
61  auto &world = x[0][0].world();
62  auto new_x = X_space(*this);// copy
63  for (const auto &i: active) {
64  new_x.x[i] = madness::copy(world, x[i], false);
65  new_x.y[i] = madness::copy(world, y[i], false);
66  }
67  world.gop.fence();
68 
69  return new_x;
70  }
71  /// Create a new copy of the function with different distribution and optional
72  /// fence
73 
74  /// Works in either basis. Different distributions imply
75  /// asynchronous communication and the optional fence is
76  /// collective.
77  [[nodiscard]] auto
78  copy(const std::shared_ptr<WorldDCPmapInterface<Key<3>>> &p_map,
79  bool fence = false) const -> X_space {
80  auto &world = x[0][0].world();
81  auto new_x = X_space(*this);// copy
82  for (int i = 0; i < new_x.num_states(); i++) {
83  new_x.x[i] = madness::copy(world, x[i], p_map, false);
84  new_x.y[i] = madness::copy(world, y[i], p_map, false);
85  }
86  world.gop.fence();
87  return new_x;
88  }
89  // assignment
90  auto operator=(const X_space &B) -> X_space & {
91  if (this != &B) {// is it the same object?
92 
93  this->n_states = B.num_states();
94  this->n_orbitals = B.num_orbitals();
95  this->x = B.x;
96  this->y = B.y;
97  this->active = B.active;
98  }
99  return *this;// NO SHALLOW COPIES
100  }
101  // Zero Constructor
102  X_space(World &world, size_t n_states, size_t n_orbitals)
104  x(world, n_states, n_orbitals), y(world, n_states, n_orbitals),
105  active(n_states) {
106  reset_active();
107  }
108  void clear() {
109  x.clear();
110  y.clear();
111  active.clear();
112  }
114  const vector_real_function_3d &vy) {
115  if (n_orbitals > 0) {
118  MADNESS_ASSERT(x.size() == y.size());
119  } else {// g_states == 0 (empty vector)
120  n_orbitals = x.size();
121  }
124  active.push_back(active.back() + 1);
125  n_states++;
126  x.push_back(vx);
127  y.push_back(vy);
128  // Be smart with g_states
129  }
130  void pop_back() {
131  x.pop_back();
132  y.pop_back();
133  active.pop_back();
134  n_states--;
135  if (n_states == 0) { n_orbitals = 0; }
136  }
137 
138 
139  friend auto inplace_apply(
140  X_space &A,
142  -> void {
143  auto &world = A.x[0][0].world();
144  for (auto &i: A.active) {
145  func(A.x[i]);
146  func(A.y[i]);
147  }
148  world.gop.fence();
149  }
150 
151  /**
152  * @brief Apply a function to the X_space
153  * @param A
154  * @param func
155  * @return
156  */
157  friend auto oop_apply(const X_space &A,
159  const vector_real_function_3d &)> &func)
160  -> X_space {
161  auto &world = A.x[0][0].world();
162  auto result = X_space::zero_functions(world, A.num_states(),
163  A.num_orbitals());
164  // if (world.rank() == 0) { print("oop_apply"); }
165  for (auto &i: result.active) {
166  // if (world.rank() == 0) { print("oop_apply", i); }
167  result.x[i] = func(A.x[i]);
168  result.y[i] = func(A.y[i]);
169  }
170  world.gop.fence();
171  return result;
172  }
173 
174  template<typename T>
175  friend auto binary_apply(const X_space &A, const X_space &B, T &func)
176  -> X_space {
178 
179  auto &world = A.x[0][0].world();
180  X_space result = X_space::zero_functions(world, A.num_states(),
181  A.num_orbitals());
182 
183  for (const auto &i: result.active) {
184  auto ax = A.x[i];
185  auto bx = B.x[i];
186 
187  auto ay = A.y[i];
188  auto by = B.y[i];
189 
190  result.x[i] = func(ax, bx);
191  result.y[i] = func(ay, by);
192  }
193  world.gop.fence();
194  return result;
195  }
196 
197  template<class T>
198  friend auto binary_inplace(X_space &A, const X_space &B,
199  const T &func) {
201  auto &world = A.x[0][0].world();
202  for (const auto &i: A.active) {
203  auto ax = A.x[i];
204  auto ay = A.y[i];
205 
206  auto bx = B.x[i];
207  auto by = B.y[i];
208 
209  func(ax, bx);
210  func(ay, by);
211  }
212  world.gop.fence();
213 
214  return A;
215  }
216 
217  static X_space zero_functions(World &world, size_t n_states,
218  size_t n_orbitals) {
219  auto zeros = X_space(world, n_states, n_orbitals);
220  for (int i = 0; i < zeros.num_states(); i++) {
221  zeros.x[i] = ::madness::zero_functions<double, 3>(
222  world, n_orbitals, false);
223  zeros.y[i] = ::madness::zero_functions<double, 3>(
224  world, n_orbitals, false);
225  }
226  world.gop.fence();
227  return zeros;
228  }
229 
230  auto operator+=(const X_space &B) -> X_space & {
231  MADNESS_ASSERT(same_size(*this, B));
232  auto &world = this->x[0][0].world();
233  auto add_inplace = [&](auto &a, const auto &b) {
234  gaxpy(world, 1.0, a, 1.0, b, false);
235  };
236  binary_inplace(*this, B, add_inplace);
237  return *this;
238  }
239 
240 
241  friend auto operator+(const X_space &A, const X_space &B) -> X_space {
243  auto add_ab = [&](const auto &a, const auto &b) {
244  return gaxpy_oop(1.0, a, 1.0, b, false);
245  };
246  return binary_apply(A, B, add_ab);
247  }
248 
249 
250  friend X_space operator-(const X_space &A, const X_space &B) {
252  auto sub_ab = [&](const auto &a, const auto &b) {
253  return gaxpy_oop(1.0, a, -1.0, b, false);
254  };
255  return binary_apply(A, B, sub_ab);
256  }
257 
258  friend X_space operator*(const X_space &A, const double &b) {
259  World &world = A.x[0][0].world();
260  auto result = A.copy();
261  auto scale_a = [&](vector_real_function_3d &vec_ai) {
262  scale(world, vec_ai, b, false);
263  };
264  inplace_apply(result, scale_a);
265  return result;
266  }
267  friend X_space operator*(const double &b, const X_space &A) {
268  World &world = A.x[0][0].world();
269  auto result = A.copy();
270  auto scale_a = [&](vector_real_function_3d &vec_ai) {
271  scale(world, vec_ai, b, false);
272  };
273  inplace_apply(result, scale_a);
274  return result;
275  }
276 
277  friend X_space operator*(const X_space &A,
278  const Function<double, 3> &f) {
279  World &world = A.x[0][0].world();
280  auto mul_f = [&](const vector_real_function_3d &vec_ai) {
281  return mul(world, f, vec_ai, false);
282  };
283  return oop_apply(A, mul_f);
284  }
285  friend auto operator*(const Function<double, 3> &f, const X_space &A)
286  -> X_space {
287  World &world = A.x[0][0].world();
288  auto mul_f = [&](const vector_real_function_3d &vec_ai) {
289  return mul(world, f, vec_ai, false);
290  };
291  return oop_apply(A, mul_f);
292  }
293 
294  friend auto operator*(const X_space &A, const Tensor<double> &b)
295  -> X_space {
298 
299  World &world = A.x[0][0].world();
300  auto transform_ai = [&](auto &ai) {
301  return transform(world, ai, b, false);
302  };
303  return oop_apply(A, transform_ai);
304  }
305  /***
306  *
307  * @param A
308  * @param B
309  * @return
310  */
311  friend auto inner(const X_space &A, const X_space &B) -> Tensor<double>;
312 
313  void truncate() {
314  auto rx = to_response_matrix(*this);
315  auto &world = rx[0][0].world();
316  auto truncate_i = [&](auto &fi) {
318  false);
319  };
320  inplace_apply(*this, truncate_i);
321  }
322 
323  void truncate(double thresh) {
324  auto rx = to_response_matrix(*this);
325  auto &world = rx[0][0].world();
326  auto truncate_i = [&](auto &fi) {
327  madness::truncate(world, fi, thresh, false);
328  };
329  inplace_apply(*this, truncate_i);
330  }
331 
332  auto norm2s() const -> Tensor<double> {
333  World &world = x[0][0].world();
334  Tensor<double> norms(num_states());
335 
336  auto x = to_response_matrix(*this);
337  int b = 0;
338  for (const auto &xb: x) { norms[b++] = norm2(world, xb); }
339  world.gop.fence();
340  return norms;
341  }
342 
343  [[nodiscard]] auto component_norm2s() const -> Tensor<double> {
344  World &world = x[0][0].world();
345  auto rx = to_flattened_vector(*this);
346  auto norms = norm2s_T(world, rx);
347  return norms.reshape(n_states, 2 * n_orbitals);
348  }
349 
350  friend auto size_states(const X_space &x) -> size_t {
351  return x.n_states;
352  }
353  friend auto size_orbitals(const X_space &x) -> size_t {
354  return x.n_orbitals;
355  }
356  friend auto same_size(const X_space &A, const X_space &B) -> bool {
357  return ((size_states(A) == size_states(B) &&
359  }
360  };
361 
362  // but the solver needs the functions initialized to zero for which we also need
363  // the world object.
364 
365  struct X_vector : public X_space {
366  X_vector(World &world, size_t n_orbtials) {
367  this->X_space::zero_functions(world, size_t(1), n_orbtials);
368  }
369 
370  X_vector(X_space A, size_t b)
371  : X_space(A.x[0][0].world(), size_t(1), A.num_orbitals()) {
372  x[0] = A.x[b];
373  y[0] = A.y[b];
374  }
375  friend X_vector operator-(const X_vector &A, const X_vector &B) {
377 
378  World &world = A.x[0][0].world();
379  X_vector result(world, size_orbitals(A));// create zero_functions
380  result.x = A.x - B.x;
381  result.y = A.y - B.y;
382  return result;
383  }
384  friend X_vector operator*(const X_vector &A, const double &c) {
385  World &world = A.x[0][0].world();
386  X_vector result(world, size_orbitals(A));// create zero_functions
387  result.x = A.x * c;
388  result.y = A.y * c;
389  return result;
390  }
391  X_vector copy() const {
392  X_vector copyX(x[0][0].world(), x.num_orbitals);
393  copyX.x = x.copy();
394  copyX.y = y.copy();
395  return copyX;
396  }
397  auto operator+=(const X_vector &B) -> X_vector & {
398  MADNESS_ASSERT(same_size(*this, B));
399  this->x += B.x;
400  this->y += B.y;
401  return *this;
402  }
403  inline friend auto inner(X_vector &A, X_vector &B) -> double {
407 
408  Tensor<double> G(1, 1);
409  Tensor<double> G1(1, 1);
410  Tensor<double> G2(1, 1);
411 
412  World &world = A.x[0][0].world();
413 
414  auto ax = madness::copy(world, A.x[0]);
415  auto ay = madness::copy(world, A.y[0]);
416 
417  auto bx = madness::copy(world, B.x[0]);
418  auto by = madness::copy(world, B.y[0]);
419 
420  for (auto &ayi: ay) { ax.push_back(madness::copy(ayi)); }
421  for (auto &byi: by) { bx.push_back(madness::copy(byi)); };
422 
423  double result = inner(ax, bx);
424 
425  return result;
426  }
427  };
428  // function object with allocator()()
431  const size_t n_orbtials;
434  // overloading the default constructor () operator
436  //print("allocator called with ", int(n_orbtials), " orbitals");
437  // returning constructor of x_vector
438  return zero_functions<double, 3>(world, n_orbtials);
439  }
440  // Copy constructor
441 
445  }
446  };
447 
451  // overloading the default constructor () operator
453  return real_function_3d(real_factory_3d(world).fence(true));
454  }
458  }
459  };
460 }// namespace madness
461 
462 #endif// SRC_APPS_MOLRESPONSE_X_SPACE_H_
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
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
#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)
auto to_X_space(const response_matrix &x) -> X_space
Definition: x_space.cc:99
std::vector< vector_real_function_3d > response_matrix
Definition: response_functions.h:19
void truncate(World &world, response_space &v, double tol, bool fence)
Definition: basic_operators.cc:30
auto to_conjugate_X_space(const response_matrix &x) -> X_space
response_matrix [x,y] -> Xspace X.x=y X.y=conjugate(x)
Definition: x_space.cc:122
Function< T, NDIM > copy(const Function< T, NDIM > &f, const std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > &pmap, bool fence=true)
Create a new copy of the function with different distribution and optional fence.
Definition: mra.h:2002
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
auto create_response_matrix(const size_t &num_states, const size_t &num_orbitals) -> response_matrix
Create a response matrix object.
Definition: x_space.cc:35
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))
FunctionFactory< double, 3 > real_factory_3d
Definition: functypedefs.h:93
NDIM & f
Definition: mra.h:2416
auto to_response_vector(const vector_real_function_3d &vec) -> vector_real_function_3d
Definition: x_space.cc:14
Function< double, 3 > real_function_3d
Definition: functypedefs.h:65
auto to_response_matrix(const X_space &x) -> response_matrix
Definition: x_space.cc:51
Tensor< double > norm2s_T(World &world, const std::vector< Function< T, NDIM >> &v)
Computes the 2-norms of a vector of functions.
Definition: vmra.h:839
auto to_conjugate_response_matrix(const X_space &x) -> response_matrix
Definition: x_space.cc:65
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
Vector< T, sizeof...(Ts)+1 > vec(T t, Ts... ts)
Factory function for creating a madness::Vector.
Definition: vector.h:711
auto to_flattened_vector(const X_space &x) -> vector_real_function_3d
Flattens all response functions into a single vector of functions.
Definition: x_space.cc:85
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
static const double b
Definition: nonlinschro.cc:119
static const double a
Definition: nonlinschro.cc:118
static const double c
Definition: relops.cc:10
static const double thresh
Definition: rk.cc:45
Definition: x_space.h:32
auto norm2s() const -> Tensor< double >
Definition: x_space.h:332
friend auto oop_apply(const X_space &A, const std::function< vector_real_function_3d(const vector_real_function_3d &)> &func) -> X_space
Apply a function to the X_space.
Definition: x_space.h:157
friend auto operator+(const X_space &A, const X_space &B) -> X_space
Definition: x_space.h:241
auto operator=(const X_space &B) -> X_space &
Definition: x_space.h:90
X_space(const X_space &A)
Definition: x_space.h:57
void reset_active()
Definition: x_space.h:47
void clear()
Definition: x_space.h:108
size_t num_states() const
Definition: x_space.h:42
std::list< size_t > active
Definition: x_space.h:39
auto copy(const std::shared_ptr< WorldDCPmapInterface< Key< 3 >>> &p_map, bool fence=false) const -> X_space
Definition: x_space.h:78
friend auto inner(const X_space &A, const X_space &B) -> Tensor< double >
Computes the matrix elements between two response spaces.
Definition: x_space.cc:168
static X_space zero_functions(World &world, size_t n_states, size_t n_orbitals)
Definition: x_space.h:217
friend X_space operator*(const X_space &A, const double &b)
Definition: x_space.h:258
friend auto operator*(const X_space &A, const Tensor< double > &b) -> X_space
Definition: x_space.h:294
X_space copy() const
Definition: x_space.h:60
friend auto operator*(const Function< double, 3 > &f, const X_space &A) -> X_space
Definition: x_space.h:285
auto operator+=(const X_space &B) -> X_space &
Definition: x_space.h:230
auto component_norm2s() const -> Tensor< double >
Definition: x_space.h:343
size_t num_orbitals() const
Definition: x_space.h:43
friend auto size_orbitals(const X_space &x) -> size_t
Definition: x_space.h:353
friend auto inplace_apply(X_space &A, const std::function< void(vector_real_function_3d &)> &func) -> void
Definition: x_space.h:139
size_t n_states
Definition: x_space.h:34
friend auto binary_inplace(X_space &A, const X_space &B, const T &func)
Definition: x_space.h:198
friend X_space operator-(const X_space &A, const X_space &B)
Definition: x_space.h:250
X_space(World &world, size_t n_states, size_t n_orbitals)
Definition: x_space.h:102
void push_back(const vector_real_function_3d &vx, const vector_real_function_3d &vy)
Definition: x_space.h:113
response_space y
Definition: x_space.h:38
response_space x
Definition: x_space.h:38
friend auto same_size(const X_space &A, const X_space &B) -> bool
Definition: x_space.h:356
void truncate()
Definition: x_space.h:313
friend X_space operator*(const double &b, const X_space &A)
Definition: x_space.h:267
X_space()
Definition: x_space.h:45
void set_active(const std::list< size_t > &new_active)
Definition: x_space.h:52
size_t n_orbitals
Definition: x_space.h:35
friend auto binary_apply(const X_space &A, const X_space &B, T &func) -> X_space
Definition: x_space.h:175
void truncate(double thresh)
Definition: x_space.h:323
friend X_space operator*(const X_space &A, const Function< double, 3 > &f)
Definition: x_space.h:277
void pop_back()
Definition: x_space.h:130
friend auto size_states(const X_space &x) -> size_t
Definition: x_space.h:350
Definition: x_space.h:365
X_vector(World &world, size_t n_orbtials)
Definition: x_space.h:366
auto operator+=(const X_vector &B) -> X_vector &
Definition: x_space.h:397
X_vector(X_space A, size_t b)
Definition: x_space.h:370
friend X_vector operator-(const X_vector &A, const X_vector &B)
Definition: x_space.h:375
X_vector copy() const
Definition: x_space.h:391
friend X_vector operator*(const X_vector &A, const double &c)
Definition: x_space.h:384
friend auto inner(X_vector &A, X_vector &B) -> double
Definition: x_space.h:403
Definition: x_space.h:448
real_function_3d operator()()
Definition: x_space.h:452
World & world
Definition: x_space.h:449
response_function_allocator(World &world)
Definition: x_space.h:450
response_function_allocator operator=(const response_function_allocator &other)
Definition: x_space.h:456
Definition: x_space.h:429
World & world
Definition: x_space.h:430
vector_real_function_3d operator()()
Definition: x_space.h:435
response_matrix_allocator(World &world, size_t n_orbtials)
Definition: x_space.h:432
const size_t n_orbtials
Definition: x_space.h:431
response_matrix_allocator operator=(const response_matrix_allocator &other)
Definition: x_space.h:443
Definition: response_functions.h:25
void push_back(const vector_real_function_3d &f)
Definition: response_functions.h:300
size_t num_orbitals
Definition: response_functions.h:34
void pop_back()
Definition: response_functions.h:312
size_t size() const
Definition: response_functions.h:337
response_space copy() const
Definition: response_functions.h:122
std::list< size_t > active
Definition: response_functions.h:36
void clear()
Definition: response_functions.h:323
pcomplex_operatorT G
Definition: tdse1d.cc:167
Defines and implements most of Tensor.
int G1
Definition: testperiodic.cc:63
int G2
Definition: testperiodic.cc:64