MADNESS  0.10.1
diamagneticpotentialfactor.h
Go to the documentation of this file.
1 /*
2  * diamagneticpotentialfactor.h
3  *
4  * Created on: 16 Apr 2019
5  * Author: fbischoff
6  */
7 
8 #ifndef SRC_APPS_CHEM_DIAMAGNETICPOTENTIALFACTOR_H_
9 #define SRC_APPS_CHEM_DIAMAGNETICPOTENTIALFACTOR_H_
10 
11 
12 #include <madness/mra/mra.h>
13 #include<madness/chem/znemo.h>
14 
15 namespace madness {
16 
17 
18 /// to be put in a separate file
20 
21 public:
22 
23  /// constructor takes a world and the parameters for the calculation
25  const std::vector<coord_3d>& coords)
26  : world(world), coords(coords) {
27 
28  use_v_vector=param.use_v_vector();
29  physical_B={0,0,param.physical_B()};
30  explicit_B={0,0,param.explicit_B()};
31 
33 
34  potential_radius=param.potential_radius();
35 
36  // initialize all functions to their default values
37  diamagnetic_factor_=real_factory_3d(world).functor([] (const coord_3d& r) {return 1.0;});
38  diamagnetic_factor_square=real_factory_3d(world).functor([] (const coord_3d& r) {return 1.0;});
39  diamagnetic_U2=real_factory_3d(world).functor([] (const coord_3d& r) {return 0.0;});
40  diamagnetic_U1=zero_functions<double,3>(world,3);
41 
43  if (param.printlevel()>9) print_info();
44  }
45 
46  void reset_explicit_B_and_v(const coord_3d& eB) {
47  explicit_B=eB;
49  }
50 
51  static std::vector<coord_3d> compute_v_vector(const coord_3d& B,
52  const std::vector<coord_3d>& coords, bool use_v_vector) {
53  std::vector<coord_3d> v;
54  if (use_v_vector) {
55  for (auto& c : coords) v.push_back(0.5*cross(B,c));
56  } else {
57  v=std::vector<coord_3d> (1,{0.0,0.0,0.0});
58  }
59  return v;
60  }
61 
62 
63  void print_info() const;
64 
65  /// return the diamagnetic factor
67 
68  /// return the square of the diamagnetic factor
70 
71  /// return a custom factor for a given magnetic field
72  real_function_3d custom_factor(const coord_3d& B, const std::vector<coord_3d>& vv,
73  const double extra_exponent=1.0) const {
74  const double absB=B.normf();
75  if (absB==0.0) return real_factory_3d(world).functor([](const coord_3d& r){return 1.0;}).truncate_on_project();
76  const double& ee=extra_exponent;
77  auto diamagnetic_HO = [&absB, &B, &vv, &ee](const coord_3d& r) {
78  double result=0.0;
79  const coord_3d A=0.5*cross(B,r);
80  for (auto& v : vv) {
81  coord_3d arg=A-v;
82  result+=exp(-1.0/absB*inner(arg,arg));
83  }
84  if (ee!=1.0) result=std::pow(result,ee);
85  return result;
86  };
87  real_function_3d result=real_factory_3d(world).functor(diamagnetic_HO);
88  return result;
89  }
90 
91 
92  /// return a custom factor for a given magnetic field
93  complex_function_3d factor_with_phase(const coord_3d& B, const std::vector<coord_3d>& vv) const {
94  const double absB=B.normf();
95  if (absB==0.0) return complex_factory_3d(world).functor([](const coord_3d& r){return 1.0;}).truncate_on_project();
96  auto diamagnetic_HO = [&absB, &B, &vv](const coord_3d& r) {
97  double result=0.0;
98  const coord_3d A=0.5*cross(B,r);
99  for (auto& v : vv) {
100  coord_3d arg=A-v;
101  result+=exp(-1.0/absB*inner(arg,arg));
102  }
103  double theta=acos(r[2]/r.normf());
104  double phi=atan2(r[1],r[0]);
105  double_complex phase=r.normf()*sin(theta)*exp(absB*double_complex(0.0,1.0)*phi);
106  return result*phase;
107  };
108  complex_function_3d result=complex_factory_3d(world).functor(diamagnetic_HO);
109  return result;
110  }
111 
112  /// compute the bare potential without confinement or factors
115  const double b_square=inner(physical_B,physical_B);
117  .functor([& b_square](const coord_3d& r){return 0.125*b_square*(r[0]*r[0] + r[1]*r[1]);});
118  return result;
119  }
120 
121  /// apply the diamagnetic potential on rhs
122  std::vector<complex_function_3d> apply_potential(const std::vector<complex_function_3d>& rhs) const;
123 
124  /// make sure the magnetic field is oriented along the z axis
125  static bool B_along_z(const coord_3d& B) {
126  return((B[0]==0.0) && (B[1]==0.0));
127  }
128 
129  std::vector<coord_3d> get_v() const {return v;}
130  std::vector<coord_3d> get_coords() const {return coords;}
131 
133 
135 
136  /// given the explicit and the physical B, estimate the radius
137  /// of the wave function
138  double estimate_wavefunction_radius(const double eps=1.e-8) const {
139  double remaining_B=(get_physical_B()-get_explicit_B()).normf();
140  return 2.0*sqrt(-log(eps)/remaining_B);
141  }
142 
143 private:
144  World& world; ///< the world
145  coord_3d physical_B={0,0,0}; ///< the actual magnetic field strength
146  coord_3d explicit_B={0,0,0}; ///< the magnetic field strength encoded in the diamagnetic factor
147 
148  /// the diamagnetic factor to cancel the diamagnetic potential
151 
152  /// radius where the diamagnetic potential flattens out
154 
155  /// the boxed diamagnetic potential (for a given B)
157  std::vector<real_function_3d> diamagnetic_U1;
158 
159  /// the position of the nuclei in the coordinate space:
160  std::vector<coord_3d> coords;
161 
162  /// the position of the nuclei in the "A" space: v = 1/2 B cross R
163  std::vector<coord_3d> v;
164 
165  bool use_v_vector=true;
166 
167 public:
168  /// recompute the factor and the potentials for given physical and explicit magnetic fields
170 
171  /// compute the commutator of the orbital-zeeman term with the diamagnetic factor
172 
173  /// @return a local potential: iB \sum_i \vec r \cdot \vec v_i
175 
178 
179  /// returns \f$R^{-1} \vec\nabla R\f$
180  std::vector<real_function_3d> compute_nabla_R_div_R() const;
181 
182  /// run the tests
183 
184  /// @param[in] level: 1: basic tests, .. , 3: all the tests
185  bool test_me(const int level) const {
186  bool success=true;
187  if ((level<1) or (level>3)) {
188  print("testing diamagneticpotentialfactor with an invalid level of ",level);
189  }
190  if (level<2) {
191  success=test_factor() and success;
192  success=test_lz_commutator() and success;
193  success=test_harmonic_potential() and success;
194  success=test_scalar_potentials() and success;
195  success=test_vector_potentials() and success;
196  }
197  if (level<3) {
198  ;
199  }
200  if (level<4) {
201  ;
202  }
203  return success;
204  }
205 
206 private:
207 
208 
209  /// compute a factor for comparison in coordinate space
210  bool test_factor() const;
211 
212  /// test the harmonic potential
213  bool test_harmonic_potential() const;
214 
215  /// test analytical vs numerical computation of the potentials
216  bool test_scalar_potentials() const;
217 
218  /// test analytical vs numerical computation of the potentials
219  bool test_vector_potentials() const;
220 
221  bool test_lz_commutator() const;
222 
223 public:
224  /// make a set orbitals for testing (not orthonormalized!)
225  std::vector<complex_function_3d> make_fake_orbitals(const int n,
226  const coord_3d& offset={0.0,0.0,0.0}) const;
227 
228  /// compute the radius for the diamagnetic potential
229  double get_potential_radius() const {
230  return potential_radius;
231  }
232 
233 };
234 
235 
236 } /* namespace madness */
237 
238 #endif /* SRC_APPS_CHEM_DIAMAGNETICPOTENTIALFACTOR_H_ */
std::complex< double > double_complex
Definition: cfft.h:14
Definition: test_ar.cc:118
Definition: test_ar.cc:141
to be put in a separate file
Definition: diamagneticpotentialfactor.h:19
real_function_3d custom_factor(const coord_3d &B, const std::vector< coord_3d > &vv, const double extra_exponent=1.0) const
return a custom factor for a given magnetic field
Definition: diamagneticpotentialfactor.h:72
static bool B_along_z(const coord_3d &B)
make sure the magnetic field is oriented along the z axis
Definition: diamagneticpotentialfactor.h:125
real_function_3d diamagnetic_factor_square
Definition: diamagneticpotentialfactor.h:150
real_function_3d diamagnetic_factor_
the diamagnetic factor to cancel the diamagnetic potential
Definition: diamagneticpotentialfactor.h:149
double estimate_wavefunction_radius(const double eps=1.e-8) const
Definition: diamagneticpotentialfactor.h:138
bool test_me(const int level) const
run the tests
Definition: diamagneticpotentialfactor.h:185
std::vector< real_function_3d > compute_nabla_R_div_R() const
returns
Definition: diamagneticpotentialfactor.cc:188
complex_function_3d compute_lz_commutator() const
compute the commutator of the orbital-zeeman term with the diamagnetic factor
Definition: diamagneticpotentialfactor.cc:135
static std::vector< coord_3d > compute_v_vector(const coord_3d &B, const std::vector< coord_3d > &coords, bool use_v_vector)
Definition: diamagneticpotentialfactor.h:51
std::vector< coord_3d > get_v() const
Definition: diamagneticpotentialfactor.h:129
real_function_3d factor_square() const
return the square of the diamagnetic factor
Definition: diamagneticpotentialfactor.h:69
bool test_scalar_potentials() const
test analytical vs numerical computation of the potentials
Definition: diamagneticpotentialfactor.cc:306
std::vector< complex_function_3d > make_fake_orbitals(const int n, const coord_3d &offset={0.0, 0.0, 0.0}) const
make a set orbitals for testing (not orthonormalized!)
Definition: diamagneticpotentialfactor.cc:369
coord_3d explicit_B
the magnetic field strength encoded in the diamagnetic factor
Definition: diamagneticpotentialfactor.h:146
coord_3d get_explicit_B() const
Definition: diamagneticpotentialfactor.h:132
std::vector< coord_3d > get_coords() const
Definition: diamagneticpotentialfactor.h:130
std::vector< complex_function_3d > apply_potential(const std::vector< complex_function_3d > &rhs) const
apply the diamagnetic potential on rhs
Definition: diamagneticpotentialfactor.cc:216
World & world
the world
Definition: diamagneticpotentialfactor.h:144
double get_potential_radius() const
compute the radius for the diamagnetic potential
Definition: diamagneticpotentialfactor.h:229
bool test_harmonic_potential() const
test the harmonic potential
Definition: diamagneticpotentialfactor.cc:282
bool test_vector_potentials() const
test analytical vs numerical computation of the potentials
Definition: diamagneticpotentialfactor.cc:327
real_function_3d compute_U2() const
Definition: diamagneticpotentialfactor.cc:151
void print_info() const
Definition: diamagneticpotentialfactor.cc:110
std::vector< coord_3d > coords
the position of the nuclei in the coordinate space:
Definition: diamagneticpotentialfactor.h:160
std::vector< coord_3d > v
the position of the nuclei in the "A" space: v = 1/2 B cross R
Definition: diamagneticpotentialfactor.h:163
real_function_3d bare_diamagnetic_potential() const
compute the bare potential without confinement or factors
Definition: diamagneticpotentialfactor.h:113
Diamagnetic_potential_factor(World &world, const Nemo_complex_Parameters &param, const std::vector< coord_3d > &coords)
constructor takes a world and the parameters for the calculation
Definition: diamagneticpotentialfactor.h:24
real_function_3d factor() const
return the diamagnetic factor
Definition: diamagneticpotentialfactor.h:66
void recompute_factors_and_potentials()
recompute the factor and the potentials for given physical and explicit magnetic fields
Definition: diamagneticpotentialfactor.cc:122
coord_3d physical_B
the actual magnetic field strength
Definition: diamagneticpotentialfactor.h:145
bool test_factor() const
compute a factor for comparison in coordinate space
Definition: diamagneticpotentialfactor.cc:239
coord_3d get_physical_B() const
Definition: diamagneticpotentialfactor.h:134
complex_function_3d factor_with_phase(const coord_3d &B, const std::vector< coord_3d > &vv) const
return a custom factor for a given magnetic field
Definition: diamagneticpotentialfactor.h:93
bool test_lz_commutator() const
Definition: diamagneticpotentialfactor.cc:349
real_function_3d diamagnetic_U2
the boxed diamagnetic potential (for a given B)
Definition: diamagneticpotentialfactor.h:156
bool use_v_vector
Definition: diamagneticpotentialfactor.h:165
real_function_3d compute_R_times_T_commutator_scalar_term_numerically() const
Definition: diamagneticpotentialfactor.cc:176
double potential_radius
radius where the diamagnetic potential flattens out
Definition: diamagneticpotentialfactor.h:153
void reset_explicit_B_and_v(const coord_3d &eB)
Definition: diamagneticpotentialfactor.h:46
std::vector< real_function_3d > diamagnetic_U1
Definition: diamagneticpotentialfactor.h:157
Definition: znemo.h:56
T normf() const
Calculate the 2-norm of the vector elements.
Definition: vector.h:400
A parallel world class.
Definition: world.h:132
Tensor< typename Tensor< T >::scalar_type > arg(const Tensor< T > &t)
Return a new tensor holding the argument of each element of t (complex types only)
Definition: tensor.h:2502
static double pow(const double *a, const double *b)
Definition: lda.h:74
#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
FunctionFactory< double, 3 > real_factory_3d
Definition: functypedefs.h:93
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition: print.h:225
double inner(response_space &a, response_space &b)
Definition: response_functions.h:442
FunctionFactory< double_complex, 3 > complex_factory_3d
Definition: functypedefs.h:100
static double phase(long i)
Definition: twoscale.cc:85
std::vector< Function< TENSOR_RESULT_TYPE(T, R), NDIM > > cross(const std::vector< Function< T, NDIM > > &f, const std::vector< Function< R, NDIM > > &g, bool do_refine=false, bool fence=true)
shorthand cross operator
Definition: vmra.h:2013
static const double c
Definition: relops.cc:10
Tensor< double > B
Definition: tdse1d.cc:166
InputParameters param
Definition: tdse.cc:203
const double offset
Definition: testfuns.cc:143