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>
10
11#include <algorithm>
12#include <cstdint>
13#include <memory>
14#include <vector>
15
16// real_function_3d == Function<double,3>
17namespace madness
18{
19
20 typedef std::vector<vector_real_function_3d> response_matrix;
21
22 /* *
23 * @brief response matrix holds response vectors for response state
24 *
25 */
27 {
28 // Member variables
29 /**
30 * @brief vector of vector of real 3d functions
31 *
32 */
33
34 public:
35 size_t num_states; // Num. of resp. states
36 size_t num_orbitals; // Num. of ground states
38 std::list<size_t> active;
39
40 // Member functions
41 public:
42 /**
43 * @brief default Construct a new response space object
44 * num_states(0)
45 * num_orbitals(0)
46 * x() default constructor of std::vector
47 */
49
51 {
52 active.resize(num_states);
53 size_t i{0};
54 for (auto &ai : active)
55 {
56 ai = i++;
57 }
58 }
59
60 // Copy constructor
61 /**
62 * @brief copy construct a new response space object
63 * we are using copying defined by std:vector
64 * we copy madness functions therefore we are copying pointers to function
65 * implementations
66 * @param y
67 */
71
72 // assignment
73 // Copy assignment should copy the members of y and leave y Unchanged
74 // The problem is what happens when we copy two functions
76 {
77 //
78 if (this != &y)
79 { // is it the same object?
80 this->num_states = y.size();
81 this->num_orbitals = y.size_orbitals();
82 this->x = y.x;
83 this->active = y.active;
84 if (x.size() != num_states)
85 {
86 x.resize(num_states);
87 }
88 }
89 return *this; //
90 }
91
93 {
94 //
95 this->num_states = y.size();
96 this->num_orbitals = y[0].size();
97 this->x = y;
98 return *this; //
99 }
100 // Initialize functions to zero
101 // m = number of response states
102 // n = number of ground state orbitals
103
104 // Zero Constructor constructs m vectors
105 /**
106 * @brief Construct a new response space with zero functions
107 *
108 * @param world
109 * @param num_states
110 * @param num_orbitals
111 */
115 {
116 for (auto &state : x)
117 {
119 }
120 reset_active();
121 // world.gop.fence();
122 }
123 // Conversion from respones_matrix
124 /**
125 * @brief Construct a new response space object from vector of functions
126 *
127 * @param x
128 */
130 : num_states(x.size()), num_orbitals(x[0].size()), x(x),
132 {
133 reset_active();
134 }
135
136 // Determines if two ResponseFunctions are the same size
137 friend bool same_size(const response_space &a, const response_space &b)
138 {
139 return ((a.size() == b.size()) && (a.size_orbitals() == b.size_orbitals()));
140 }
141 // Returns a deep copy
142 [[nodiscard]] response_space copy() const
143 {
144 World &world = x[0][0].world();
145 response_space result(*this);
146 // copy each state
147 for (size_t i = 0; i < num_states; i++)
148 {
149 result.x[i] = madness::copy(world, x[i], false);
150 }
151 world.gop.fence();
152 return result;
153 }
154 [[nodiscard]] response_space
155 copy(const std::shared_ptr<WorldDCPmapInterface<Key<3>>> &pmap,
156 bool fence = false) const
157 {
158 auto &world = x[0][0].world();
159 response_space result(*this);
160 std::transform(x.begin(), x.end(), result.x.begin(), [&](const auto &xi)
161 { return madness::copy(world, xi, pmap, fence); });
162 world.gop.fence();
163 return result;
164 }
165
166 vector_real_function_3d &operator[](size_t i) { return x.at(i); }
167 const vector_real_function_3d &operator[](size_t i) const { return x.at(i); }
168
171 const std::function<void(vector_real_function_3d &)> &func)
172 {
173 auto &world = A.x[A.active.front()][0].world();
174 for (auto &i : A.active)
175 {
176 func(A.x[i]);
177 }
178 world.gop.fence();
179 }
180
181 friend auto oop_unary_apply(const response_space &A,
182 const std::function<vector_real_function_3d(
183 const vector_real_function_3d &)> &func)
185 {
186 auto result = A.copy();
187 auto &world = result.x[A.active.front()][0].world();
188 result.active = A.active;
189 for (auto &i : result.active)
190 {
191 result.x[i] = func(A.x[i]);
192 }
193 world.gop.fence();
194 return result;
195 }
196
197 friend auto
199 const std::function<vector_real_function_3d(
202 {
204
205 response_space result = A.copy(); // create zero_functions
206 auto &world = result.x[A.active.front()][0].world();
207
208 for (const auto &i : result.active)
209 {
210 auto ax = result.x[i];
211 auto bx = B.x[i];
212 result.x[i] = func(ax, bx);
213 }
214 world.gop.fence();
215 return result;
216 }
217
218 template <class T>
220 const T &func)
221 {
223 auto &world = A.x[A.active.front()][0].world();
224 for (const auto &i : A.active)
225 {
226 auto ax = A.x[i];
227 auto bx = B.x[i];
228 func(ax, bx);
229 }
230 world.gop.fence();
231
232 return A;
233 }
234
236 {
237
238 MADNESS_ASSERT(size() > 0);
239 MADNESS_ASSERT(same_size(*this, rhs_y)); // assert that same size
240 World &world = x[rhs_y.active.front()][0].world();
241 auto result = response_space(world, size(), size_orbitals());
242 result.active = rhs_y.active;
243
244 result.from_vector(this->to_vector() + rhs_y.to_vector());
245 return result;
246
247 // auto result =
248 // binary_apply(*this, rhs_y, [&](auto xi, auto vi)
249 // { return gaxpy_oop(1.0, xi, 1.0, vi, false); });
250 // return result;
251 }
252
254 {
255 MADNESS_ASSERT(size() > 0);
256 MADNESS_ASSERT(same_size(*this, rhs_y)); // assert that same size
257 World &world = x[rhs_y.active.front()][0].world();
258 auto result = this->copy();
259 result.active = rhs_y.active;
260
261 result.from_vector(result.to_vector() - rhs_y.to_vector());
262 return result;
263
264 // auto result =
265 // binary_apply(*this, rhs_y, [&](auto xi, auto vi)
266 // { return gaxpy_oop(1.0, xi, -1.0, vi, false); });
267 return result;
268 }
269
270 friend response_space operator*(const response_space &y, double a)
271 {
272 // World &world = y.x.at(0).at(0).world();
273 World &world = y.x[y.active.front()][0].world();
274 auto multiply_scalar = [&](vector_real_function_3d &vi)
275 {
276 madness::scale(world, vi, a, false);
277 };
278
279 // auto result = response_space(world, y.size(), y.size_orbitals());
280 auto result =
282 result.active = y.active;
283 result.from_vector(y.to_vector() * a);
284 return result;
285
286 // auto result = y.copy();
287
288 inplace_unary_apply(result, multiply_scalar);
289 return result;
290 }
291
293 {
294 // World &world = y.x.at(0).at(0).world();
295 World &world = y.x[y.active.front()][0].world();
296
297 // auto result = response_space(world, y.size(), y.size_orbitals());
298 auto result =
300 result.active = y.active;
301 result.from_vector(y.to_vector() * a);
302 return result;
303
304 // auto multiply_scalar = [&](vector_real_function_3d &vi)
305 // { madness::scale(world, vi, a, false); };
306 // auto result = y.copy();
307 // inplace_unary_apply(result, multiply_scalar);
308 // return result;
309 }
310
312 {
313 // World &world = this->x[0][0].world();
314 World &world = x[active.front()][0].world();
315
316 this->from_vector(this->to_vector() * a);
317 // auto multiply_scalar = [&](vector_real_function_3d &vi)
318 // { madness::scale(world, vi, a, false); };
319 // inplace_unary_apply(*this, multiply_scalar);
320 return *this;
321 }
322
323 // Scaling all internal functions by an external function
324 // g[i][j] = x[i][j] * f
326 const Function<double, 3> &f)
327 {
328 // World &world = a.x.at(0).at(0).world();
329 World &world = a[a.active.front()][0].world();
330
331 auto result =
332 response_space::zero_functions(world, a.size(), a.size_orbitals());
333 result.active = a.active;
334 result.from_vector(a.to_vector() * f);
335 return result;
336
337 auto multiply_scalar_function = [&](const vector_real_function_3d &vi)
338 {
339 return mul(world, f, vi, false);
340 };
341 return oop_unary_apply(a, multiply_scalar_function);
342 }
343
344 // Scaling all internal functions by an external function
345 // g[i][j] = x[i][j] * f
347 const response_space &a)
348 {
349
350 return a * f;
351 }
352
354 {
355 // World &world = x[0][0].world();
356 World &world = x[active.front()][0].world();
357
358 // auto result = response_space(world, size(), size_orbitals());
359 auto result =
361 result.active = active;
362 result.from_vector(this->to_vector() * f);
363
364 return result;
365
366 auto multiply_scalar_function = [&](const vector_real_function_3d &vi)
367 {
368 return mul(world, f, vi, false);
369 };
370
371 return oop_unary_apply(*this, multiply_scalar_function);
372 }
373
375 const Tensor<double> &b)
376 {
377 MADNESS_ASSERT(a.size() > 0);
378 MADNESS_ASSERT(!a[0].empty());
379 World &world = a[0][0].world();
380 auto response_transform = [&](const vector_real_function_3d &vi)
381 {
382 return transform(world, vi, b, true);
383 };
384 return oop_unary_apply(a, response_transform);
385 }
386
387 // KAIN must have this
389 {
390 MADNESS_ASSERT(same_size(*this, b));
391 auto &world = b[b.active.front()][0].world();
392 this->active = b.active;
393
394 this->from_vector(this->to_vector() + b.to_vector());
395 return *this;
396
397 auto a_plus_equal_b = [&](vector_real_function_3d &a,
399 {
400 gaxpy(world, 1.0, a, 1.0, g, false);
401 };
402 binary_inplace(*this, b, a_plus_equal_b);
403 return *this;
404
405 return *this;
406 }
407
408 // Mimicking std::vector with these 4
410 {
411 x.push_back(f);
412 num_states++;
413 // print("im calling response_space push back");
414
415 // Be smart with g_states
416 if (num_orbitals > 0)
417 MADNESS_ASSERT(num_orbitals == f.size());
418 else
419 { // g_states == 0 (empty vector)
420 num_orbitals = f.size();
421 }
422 }
423
424 void pop_back()
425 {
427 x.pop_back();
428 num_states--;
429
430 // Be smart with g_states
431 if (num_states == 0)
432 { // removed last item
433 num_orbitals = 0;
434 }
435 }
436
437 void clear()
438 {
439 x.clear();
440 num_states = 0;
441 num_orbitals = 0;
442 }
443
444 auto begin() { return x.begin(); }
445
446 auto end() { return x.end(); }
447
448 const auto begin() const { return x.begin(); }
449
450 [[nodiscard]] const auto end() const { return x.end(); }
451
452 size_t size() const { return num_states; }
453
454 size_t size_orbitals() const { return num_orbitals; }
455
456 // Mimicing standard madness calls with these 3
457 void zero()
458 {
459 auto &world = x[0][0].world();
460 for (int i = 0; i < num_states; i++)
461 {
462 x[i] = ::madness::zero_functions<double, 3>(world, num_orbitals, false);
463 }
464 }
465
466 void compress_rf() const
467 {
468 // for (size_t k = 0; k < num_states; k++) { compress(x[0][0].world(), x[k],
469 // true); } auto &world = x[0][0].world();
470 auto &world = x[active.front()][0].world();
471 // compress only active states
472 //
473 auto xvec = to_vector();
474 compress(world, xvec, true);
475 }
476
478 {
479 // for (size_t k = 0; k < num_states; k++) { reconstruct(x[0][0].world(),
480 // x[k], true); } auto &world = x[0][0].world();
481 auto &world = x[active.front()][0].world();
482 // reconstruct only active states
483 for (auto &i : active)
484 {
485 reconstruct(world, x[i], false);
486 }
487 world.gop.fence();
488 }
489
491
492 void truncate_rf(double tol)
493 {
494 auto &world = x[active.front()][0].world();
495 // truncate only active states
496 for (auto &i : active)
497 {
498 truncate(world, x[i], tol, false);
499 }
500 world.gop.fence();
501 /*
502 for (size_t k = 0; k < num_states; k++) { truncate(x[0][0].world(), x[k],
503 tol, true); }
504 */
505 }
506
507 // Returns norms of each state
509 {
510 auto &world = x[0][0].world();
512 for (size_t i = 0; i < num_states; i++)
513 {
514 answer(i) = madness::norm2(world, x[i]);
515 }
516
517 world.gop.fence();
518
519 return answer;
520 }
521
522 // Scales each state (read: entire row) by corresponding vector element
523 // new[i] = old[i] * mat[i]
525 {
526 for (size_t i = 0; i < num_states; i++)
527 madness::scale(x[0][0].world(), x[i], mat[i], false);
528 // x[i] = x[i] * mat[i];
529 }
530
531 friend bool operator==(const response_space &a, const response_space &y)
532 {
533 if (!same_size(a, y))
534 return false;
535 for (size_t b = 0; b < a.size(); ++b)
536 {
537 for (size_t k = 0; b < a.size_orbitals(); ++k)
538 {
539 if ((a[b][k] - y[b][k]).norm2() >
540 FunctionDefaults<3>::get_thresh()) // this may be strict
541 return false;
542 }
543 }
544 return true;
545 }
546
548 size_t num_orbitals)
549 {
550 response_space result(world, num_states, num_orbitals);
551
552 for (int i = 0; i < num_states; i++)
553 {
554 result.x[i] =
555 ::madness::zero_functions<double, 3>(world, num_orbitals, false);
556 }
557 return result;
558 }
559
561 const response_space &b)
562 {
563 MADNESS_ASSERT(a.size() > 0);
564 MADNESS_ASSERT(!a[0].empty());
565 MADNESS_ASSERT(a[0].size() == b[0].size());
566
567 a.compress_rf();
568 b.compress_rf();
569
570 World &world = a[0][0].world();
571
572 auto dim_a1 = a.size();
573 auto num_orbitals = a.size_orbitals();
574 auto dim_b1 = b.size();
575 // Need to take transpose of each input ResponseFunction
576 response_space aT(world, num_orbitals, dim_a1);
577 response_space bT(world, num_orbitals, dim_b1);
578 for (size_t j = 0; j < num_orbitals; j++)
579 {
580 for (size_t i = 0; i < dim_a1; i++)
581 {
582 aT[j][i] = a[i][j];
583 }
584 for (size_t i = 0; i < dim_b1; i++)
585 {
586 bT[j][i] = b[i][j];
587 }
588 }
589 // Container for result
590 Tensor<double> result(dim_a1, dim_b1);
591 for (size_t p = 0; p < num_orbitals; p++)
592 {
593 result += matrix_inner(world, aT[p], bT[p]);
594 world.gop.fence();
595 }
596 return result;
597 }
598
599 [[nodiscard]] auto to_vector() const -> vector_real_function_3d
600 {
601
602 int n = static_cast<int>(active.size());
603 int m = static_cast<int>(num_orbitals);
604
606
607 int i = 0;
608 for (const auto &ai : active)
609 {
610 for (int j = 0; j < m; j++)
611 {
612 auto xindex = (i * m) + j;
613 rf[xindex] = x[ai][j];
614 }
615 i++;
616 }
617 return rf;
618 }
619
620 auto from_vector(const vector_real_function_3d &rf) -> void
621 {
622
623 int m = static_cast<int>(num_orbitals);
624
625 int i = 0;
626 for (const auto &ai : active)
627 {
628 for (int j = 0; j < m; j++)
629 {
630 auto xindex = (i * m) + j;
631
632 x[ai][j] = rf[xindex];
633 }
634 i++;
635 }
636 }
637 };
638
639 // Final piece for KAIN
641 {
642 MADNESS_ASSERT(a.size() > 0);
643 MADNESS_ASSERT(!a[0].empty());
644 MADNESS_ASSERT(a[0].size() == b[0].size());
645
646 double value = 0.0;
647
648 for (unsigned int i = 0; i < a.size(); i++)
649 {
650 // vmra.h function
651 value += inner(a[i], b[i]);
652 }
653
654 return value;
655 }
656
658 // Final piece for KAIN
659
660} // End namespace madness
661#endif // SRC_APPS_MOLRESPONSE_RESPONSE_FUNCTIONS_H_
662
663// Deuces
Definition test_ar.cc:118
Definition test_ar.cc:141
FunctionDefaults holds default paramaters as static class members.
Definition funcdefaults.h:100
A multiresolution adaptive numerical function.
Definition mra.h:139
Key is the index for a node of the 2^NDIM-tree.
Definition key.h:69
A tensor is a multidimensional array.
Definition tensor.h:317
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
ProcessID size() const
Returns the number of processes in this World (same as MPI_Comm_size()).
Definition world.h:330
WorldGopInterface & gop
Global operations.
Definition world.h:207
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
auto T(World &world, response_space &f) -> response_space
Definition global_functions.cc:28
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.
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
response_space scale(response_space a, double b)
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:1765
std::vector< vector_real_function_3d > response_matrix
Definition response_functions.h:20
void truncate(World &world, response_space &v, double tol, bool fence)
Definition basic_operators.cc:31
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:707
void compress(World &world, const std::vector< Function< T, NDIM > > &v, bool fence=true)
Compress a vector of functions.
Definition vmra.h:149
const std::vector< Function< T, NDIM > > & reconstruct(const std::vector< Function< T, NDIM > > &v)
reconstruct a vector of functions
Definition vmra.h:162
double norm2(World &world, const std::vector< Function< T, NDIM > > &v)
Computes the 2-norm of a vector of functions.
Definition vmra.h:871
std::vector< real_function_3d > vector_real_function_3d
Definition functypedefs.h:94
std::shared_ptr< FunctionFunctorInterface< double, 3 > > func(new opT(g))
NDIM & f
Definition mra.h:2481
NDIM const Function< R, NDIM > & g
Definition mra.h:2481
double inner(response_space &a, response_space &b)
Definition response_functions.h:640
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
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:2066
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:245
auto transposeResponseMatrix(const response_matrix &x) -> response_matrix
Definition x_space.cc:157
static const double b
Definition nonlinschro.cc:119
static const double a
Definition nonlinschro.cc:118
Implements most functionality of separated operators.
static const double m
Definition relops.cc:9
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:27
response_space()
default Construct a new response space object num_states(0) num_orbitals(0) x() default constructor o...
Definition response_functions.h:48
response_space operator-(const response_space &rhs_y) const
Definition response_functions.h:253
friend bool same_size(const response_space &a, const response_space &b)
Definition response_functions.h:137
response_space & operator+=(const response_space &b)
Definition response_functions.h:388
Tensor< double > norm2()
Definition response_functions.h:508
void push_back(const vector_real_function_3d &f)
Definition response_functions.h:409
const vector_real_function_3d & operator[](size_t i) const
Definition response_functions.h:167
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:68
friend response_space operator*(const response_space &a, const Function< double, 3 > &f)
Definition response_functions.h:325
response_space(const response_matrix &x)
Construct a new response space object from vector of functions.
Definition response_functions.h:129
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:198
response_space copy(const std::shared_ptr< WorldDCPmapInterface< Key< 3 > > > &pmap, bool fence=false) const
Definition response_functions.h:155
response_space operator+(const response_space &rhs_y) const
Definition response_functions.h:235
auto to_vector() const -> vector_real_function_3d
Definition response_functions.h:599
void reset_active()
Definition response_functions.h:50
size_t num_orbitals
Definition response_functions.h:36
friend auto inplace_unary_apply(response_space &A, const std::function< void(vector_real_function_3d &)> &func)
Definition response_functions.h:169
friend auto binary_inplace(response_space &A, const response_space &B, const T &func)
Definition response_functions.h:219
friend bool operator==(const response_space &a, const response_space &y)
Definition response_functions.h:531
response_space & operator=(const response_space &y)
Definition response_functions.h:75
friend response_space operator*(const response_space &y, double a)
Definition response_functions.h:270
response_space & operator*=(double a)
Definition response_functions.h:311
size_t num_states
vector of vector of real 3d functions
Definition response_functions.h:35
friend response_space operator*(const response_space &a, const Tensor< double > &b)
Definition response_functions.h:374
const auto begin() const
Definition response_functions.h:448
void compress_rf() const
Definition response_functions.h:466
void truncate_rf(double tol)
Definition response_functions.h:492
void reconstruct_rf()
Definition response_functions.h:477
friend response_space operator*(double a, response_space &y)
Definition response_functions.h:292
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:181
void zero()
Definition response_functions.h:457
void pop_back()
Definition response_functions.h:424
response_space(World &world, size_t num_states, size_t num_orbitals)
Construct a new response space with zero functions.
Definition response_functions.h:112
friend Tensor< double > response_space_inner(const response_space &a, const response_space &b)
Definition response_functions.h:560
response_space operator*(const Function< double, 3 > &f)
Definition response_functions.h:353
auto from_vector(const vector_real_function_3d &rf) -> void
Definition response_functions.h:620
size_t size() const
Definition response_functions.h:452
void truncate_rf()
Definition response_functions.h:490
vector_real_function_3d & operator[](size_t i)
Definition response_functions.h:166
response_space copy() const
Definition response_functions.h:142
auto end()
Definition response_functions.h:446
friend response_space operator*(const Function< double, 3 > &f, const response_space &a)
Definition response_functions.h:346
const auto end() const
Definition response_functions.h:450
void scale(Tensor< double > &mat)
Definition response_functions.h:524
auto begin()
Definition response_functions.h:444
size_t size_orbitals() const
Definition response_functions.h:454
response_matrix x
Definition response_functions.h:37
std::list< size_t > active
Definition response_functions.h:38
response_space & operator=(const response_matrix &y)
Definition response_functions.h:92
static response_space zero_functions(World &world, size_t num_states, size_t num_orbitals)
Definition response_functions.h:547
void clear()
Definition response_functions.h:437