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 typedef std::vector<vector_real_function_3d> response_matrix;
20
21 /* *
22 * @brief response matrix holds response vectors for response state
23 *
24 */
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 */
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 */
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 */
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,
153 const std::function<vector_real_function_3d(const vector_real_function_3d &)> &func)
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
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();
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]
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
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
Definition test_ar.cc:118
Definition test_ar.cc:141
FunctionDefaults holds default paramaters as static class members.
Definition funcdefaults.h:204
A multiresolution adaptive numerical function.
Definition mra.h:122
Key is the index for a node of the 2^NDIM-tree.
Definition key.h:66
A tensor is a multidimension 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:328
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
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.
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
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
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:1701
std::vector< vector_real_function_3d > response_matrix
Definition response_functions.h:19
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
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
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
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 &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
response_space & operator+=(const response_space &b)
Definition response_functions.h:283
Tensor< double > norm2()
Definition response_functions.h:384
void push_back(const vector_real_function_3d &f)
Definition response_functions.h:300
const vector_real_function_3d & operator[](size_t i) const
Definition response_functions.h:141
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 copy(const std::shared_ptr< WorldDCPmapInterface< Key< 3 > > > &pmap, bool fence=false) const
Definition response_functions.h:130
response_space operator+(const response_space &rhs_y) const
Definition response_functions.h:195
void reset_active()
Definition response_functions.h:48
size_t num_orbitals
Definition response_functions.h:34
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
response_space & operator=(const response_space &y)
Definition response_functions.h:68
friend response_space operator*(const response_space &y, double a)
Definition response_functions.h:215
response_space & operator*=(double a)
Definition response_functions.h:235
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
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
friend Tensor< double > response_space_inner(const response_space &a, const response_space &b)
Definition response_functions.h:414
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
response_space & operator=(const response_matrix &y)
Definition response_functions.h:80
void clear()
Definition response_functions.h:323