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
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 }
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
275 // auto result = response_space(world, y.size(), y.size_orbitals());
276 auto result =
278 result.active = y.active;
279 result.from_vector(y.to_vector() * a);
280 return result;
281
282 // auto result = y.copy();
283 // auto multiply_scalar = [&](vector_real_function_3d &vi)
284 // {
285 //madness::scale(world, vi, a, false);
286 //};
287 //inplace_unary_apply(result, multiply_scalar);
288 //return result;
289 }
290
292 {
293 // World &world = y.x.at(0).at(0).world();
294 World &world = y.x[y.active.front()][0].world();
295
296 // auto result = response_space(world, y.size(), y.size_orbitals());
297 auto result =
299 result.active = y.active;
300 result.from_vector(y.to_vector() * a);
301 return result;
302
303 // auto multiply_scalar = [&](vector_real_function_3d &vi)
304 // { madness::scale(world, vi, a, false); };
305 // auto result = y.copy();
306 // inplace_unary_apply(result, multiply_scalar);
307 // return result;
308 }
309
311 {
312 // World &world = this->x[0][0].world();
313 //World &world = x[active.front()][0].world();
314
315 this->from_vector(this->to_vector() * a);
316 // auto multiply_scalar = [&](vector_real_function_3d &vi)
317 // { madness::scale(world, vi, a, false); };
318 // inplace_unary_apply(*this, multiply_scalar);
319 return *this;
320 }
321
322 // Scaling all internal functions by an external function
323 // g[i][j] = x[i][j] * f
325 const Function<double, 3> &f)
326 {
327 // World &world = a.x.at(0).at(0).world();
328 World &world = a[a.active.front()][0].world();
329
330 auto result =
331 response_space::zero_functions(world, a.size(), a.size_orbitals());
332 result.active = a.active;
333 result.from_vector(a.to_vector() * f);
334 return result;
335
336 // auto multiply_scalar_function = [&](const vector_real_function_3d &vi)
337 // {
338 // return mul(world, f, vi, false);
339 // };
340 // return oop_unary_apply(a, multiply_scalar_function);
341 }
342
343 // Scaling all internal functions by an external function
344 // g[i][j] = x[i][j] * f
346 const response_space &a)
347 {
348
349 return a * f;
350 }
351
353 {
354 // World &world = x[0][0].world();
355 World &world = x[active.front()][0].world();
356
357 // auto result = response_space(world, size(), size_orbitals());
358 auto result =
360 result.active = active;
361 result.from_vector(this->to_vector() * f);
362
363 return result;
364
365 // auto multiply_scalar_function = [&](const vector_real_function_3d &vi)
366 // {
367 // return mul(world, f, vi, false);
368 // };
369
370 // return oop_unary_apply(*this, multiply_scalar_function);
371 }
372
374 const Tensor<double> &b)
375 {
376 MADNESS_ASSERT(a.size() > 0);
377 MADNESS_ASSERT(!a[0].empty());
378 World &world = a[0][0].world();
380 {
381 return transform(world, vi, b, true);
382 };
384 }
385
386 // KAIN must have this
388 {
389 MADNESS_ASSERT(same_size(*this, b));
390 // auto &world = b[b.active.front()][0].world();
391 this->active = b.active;
392
393 this->from_vector(this->to_vector() + b.to_vector());
394 return *this;
395
396 // auto a_plus_equal_b = [&](vector_real_function_3d &a,
397 // const vector_real_function_3d &g)
398 // {
399 // gaxpy(world, 1.0, a, 1.0, g, false);
400 // };
401 // binary_inplace(*this, b, a_plus_equal_b);
402 // return *this;
403
404 // return *this;
405 }
406
407 // Mimicking std::vector with these 4
409 {
410 x.push_back(f);
411 num_states++;
412 // print("im calling response_space push back");
413
414 // Be smart with g_states
415 if (num_orbitals > 0)
416 MADNESS_ASSERT(num_orbitals == f.size());
417 else
418 { // g_states == 0 (empty vector)
419 num_orbitals = f.size();
420 }
421 }
422
423 void pop_back()
424 {
426 x.pop_back();
427 num_states--;
428
429 // Be smart with g_states
430 if (num_states == 0)
431 { // removed last item
432 num_orbitals = 0;
433 }
434 }
435
436 void clear()
437 {
438 x.clear();
439 num_states = 0;
440 num_orbitals = 0;
441 }
442
443 auto begin() { return x.begin(); }
444
445 auto end() { return x.end(); }
446
447 const auto begin() const { return x.begin(); }
448
449 [[nodiscard]] const auto end() const { return x.end(); }
450
451 size_t size() const { return num_states; }
452
453 size_t size_orbitals() const { return num_orbitals; }
454
455 // Mimicing standard madness calls with these 3
456 void zero()
457 {
458 auto &world = x[0][0].world();
459 for (size_t i = 0; i < num_states; i++)
460 {
462 }
463 }
464
465 void compress_rf() const
466 {
467 // for (size_t k = 0; k < num_states; k++) { compress(x[0][0].world(), x[k],
468 // true); } auto &world = x[0][0].world();
469 auto &world = x[active.front()][0].world();
470 // compress only active states
471 //
472 auto xvec = to_vector();
473 compress(world, xvec, true);
474 }
475
477 {
478 // for (size_t k = 0; k < num_states; k++) { reconstruct(x[0][0].world(),
479 // x[k], true); } auto &world = x[0][0].world();
480 auto &world = x[active.front()][0].world();
481 // reconstruct only active states
482 for (auto &i : active)
483 {
484 reconstruct(world, x[i], false);
485 }
486 world.gop.fence();
487 }
488
490
491 void truncate_rf(double tol)
492 {
493 auto &world = x[active.front()][0].world();
494 // truncate only active states
495 for (auto &i : active)
496 {
497 truncate(world, x[i], tol, false);
498 }
499 world.gop.fence();
500 /*
501 for (size_t k = 0; k < num_states; k++) { truncate(x[0][0].world(), x[k],
502 tol, true); }
503 */
504 }
505
506 // Returns norms of each state
508 {
509 auto &world = x[0][0].world();
511 for (size_t i = 0; i < num_states; i++)
512 {
513 answer(i) = madness::norm2(world, x[i]);
514 }
515
516 world.gop.fence();
517
518 return answer;
519 }
520
521 // Scales each state (read: entire row) by corresponding vector element
522 // new[i] = old[i] * mat[i]
524 {
525 for (size_t i = 0; i < num_states; i++)
526 madness::scale(x[0][0].world(), x[i], mat[i], false);
527 // x[i] = x[i] * mat[i];
528 }
529
530 friend bool operator==(const response_space &a, const response_space &y)
531 {
532 if (!same_size(a, y))
533 return false;
534 for (size_t b = 0; b < a.size(); ++b)
535 {
536 for (size_t k = 0; b < a.size_orbitals(); ++k)
537 {
538 if ((a[b][k] - y[b][k]).norm2() >
539 FunctionDefaults<3>::get_thresh()) // this may be strict
540 return false;
541 }
542 }
543 return true;
544 }
545
547 size_t num_orbitals)
548 {
549 response_space result(world, num_states, num_orbitals);
550
551 for (size_t i = 0; i < num_states; i++)
552 {
553 result.x[i] =
555 }
556 return result;
557 }
558
560 const response_space &b)
561 {
562 MADNESS_ASSERT(a.size() > 0);
563 MADNESS_ASSERT(!a[0].empty());
564 MADNESS_ASSERT(a[0].size() == b[0].size());
565
566 a.compress_rf();
567 b.compress_rf();
568
569 World &world = a[0][0].world();
570
571 auto dim_a1 = a.size();
572 auto num_orbitals = a.size_orbitals();
573 auto dim_b1 = b.size();
574 // Need to take transpose of each input ResponseFunction
577 for (size_t j = 0; j < num_orbitals; j++)
578 {
579 for (size_t i = 0; i < dim_a1; i++)
580 {
581 aT[j][i] = a[i][j];
582 }
583 for (size_t i = 0; i < dim_b1; i++)
584 {
585 bT[j][i] = b[i][j];
586 }
587 }
588 // Container for result
590 for (size_t p = 0; p < num_orbitals; p++)
591 {
592 result += matrix_inner(world, aT[p], bT[p]);
593 world.gop.fence();
594 }
595 return result;
596 }
597
599 {
600
601 int n = static_cast<int>(active.size());
602 int m = static_cast<int>(num_orbitals);
603
605
606 int i = 0;
607 for (const auto &ai : active)
608 {
609 for (int j = 0; j < m; j++)
610 {
611 auto xindex = (i * m) + j;
612 rf[xindex] = x[ai][j];
613 }
614 i++;
615 }
616 return rf;
617 }
618
620 {
621
622 int m = static_cast<int>(num_orbitals);
623
624 int i = 0;
625 for (const auto &ai : active)
626 {
627 for (int j = 0; j < m; j++)
628 {
629 auto xindex = (i * m) + j;
630
631 x[ai][j] = rf[xindex];
632 }
633 i++;
634 }
635 }
636 };
637
638 // Final piece for KAIN
640 {
641 MADNESS_ASSERT(a.size() > 0);
642 MADNESS_ASSERT(!a[0].empty());
643 MADNESS_ASSERT(a[0].size() == b[0].size());
644
645 double value = 0.0;
646
647 for (unsigned int i = 0; i < a.size(); i++)
648 {
649 // vmra.h function
650 value += inner(a[i], b[i]);
651 }
652
653 return value;
654 }
655
657 // Final piece for KAIN
658
659} // End namespace madness
660#endif // SRC_APPS_MOLRESPONSE_RESPONSE_FUNCTIONS_H_
661
662// 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:122
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)
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:2528
double inner(response_space &a, response_space &b)
Definition response_functions.h:639
static XNonlinearSolver< std::vector< Function< T, NDIM > >, T, vector_function_allocator< T, NDIM > > nonlinear_vector_solver(World &world, const long nvec)
Definition nonlinsol.h:371
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:2096
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:387
Tensor< double > norm2()
Definition response_functions.h:507
void push_back(const vector_real_function_3d &f)
Definition response_functions.h:408
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:324
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:598
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:530
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:310
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:373
const auto begin() const
Definition response_functions.h:447
void compress_rf() const
Definition response_functions.h:465
void truncate_rf(double tol)
Definition response_functions.h:491
void reconstruct_rf()
Definition response_functions.h:476
friend response_space operator*(double a, response_space &y)
Definition response_functions.h:291
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:456
void pop_back()
Definition response_functions.h:423
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:559
response_space operator*(const Function< double, 3 > &f)
Definition response_functions.h:352
auto from_vector(const vector_real_function_3d &rf) -> void
Definition response_functions.h:619
size_t size() const
Definition response_functions.h:451
void truncate_rf()
Definition response_functions.h:489
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:445
friend response_space operator*(const Function< double, 3 > &f, const response_space &a)
Definition response_functions.h:345
const auto end() const
Definition response_functions.h:449
void scale(Tensor< double > &mat)
Definition response_functions.h:523
auto begin()
Definition response_functions.h:443
size_t size_orbitals() const
Definition response_functions.h:453
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:546
void clear()
Definition response_functions.h:436