1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2019 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Raymond Clay, Sandia National Laboratories
8 //
9 // File created by: Raymond Clay, rclay@sandia.gov, Sandia National Laboratories
10 //////////////////////////////////////////////////////////////////////////////////////
11
12
13 /**@file ACForce.cpp
14 *@brief Implementation of ACForce, Assaraf-Caffarel ZVZB style force estimation.
15 */
16 #include "ACForce.h"
17 #include <sstream>
18 #include "OhmmsData/AttributeSet.h"
19
20 namespace qmcplusplus
21 {
ACForce(ParticleSet & source,ParticleSet & target,TrialWaveFunction & psi_in,QMCHamiltonian & H)22 ACForce::ACForce(ParticleSet& source, ParticleSet& target, TrialWaveFunction& psi_in, QMCHamiltonian& H)
23 : ions(source),
24 elns(target),
25 psi(psi_in),
26 ham(H),
27 FirstForceIndex(-1),
28 Nions(ions.getTotalNum()),
29 useSpaceWarp(false),
30 swt(target, source)
31 {
32 prefix = "ACForce";
33 myName = prefix;
34
35 hf_force.resize(Nions);
36 pulay_force.resize(Nions);
37 wf_grad.resize(Nions);
38 sw_pulay.resize(Nions);
39 sw_grad.resize(Nions);
40 delta = 1e-4;
41 };
42
makeClone(ParticleSet & qp,TrialWaveFunction & psi)43 OperatorBase* ACForce::makeClone(ParticleSet& qp, TrialWaveFunction& psi)
44 {
45 APP_ABORT("ACForce::makeClone(ParticleSet&,TrialWaveFunction&) shouldn't be called");
46 return nullptr;
47 }
48
makeClone(ParticleSet & qp,TrialWaveFunction & psi_in,QMCHamiltonian & ham_in)49 OperatorBase* ACForce::makeClone(ParticleSet& qp, TrialWaveFunction& psi_in, QMCHamiltonian& ham_in)
50 {
51 OperatorBase* myclone = new ACForce(ions, qp, psi_in, ham_in);
52 return myclone;
53 }
54
put(xmlNodePtr cur)55 bool ACForce::put(xmlNodePtr cur)
56 {
57 std::string useSpaceWarpString("no");
58 std::string ionionforce("yes");
59 RealType swpow(4);
60 OhmmsAttributeSet attr;
61 attr.add(useSpaceWarpString, "spacewarp"); //"yes" or "no"
62 attr.add(swpow, "swpow"); //Real number"
63 attr.add(delta, "delta"); //Real number"
64 attr.put(cur);
65
66 useSpaceWarp = (useSpaceWarpString == "yes") || (useSpaceWarpString == "true");
67 swt.setPow(swpow);
68
69 if (useSpaceWarp)
70 app_log() << "ACForce is using space warp with power=" << swpow << std::endl;
71 else
72 app_log() << "ACForce is not using space warp\n";
73
74 return true;
75 }
76
add2Hamiltonian(ParticleSet & qp,TrialWaveFunction & psi,QMCHamiltonian & ham_in)77 void ACForce::add2Hamiltonian(ParticleSet& qp, TrialWaveFunction& psi, QMCHamiltonian& ham_in)
78 {
79 //The following line is modified
80 OperatorBase* myclone = makeClone(qp, psi, ham_in);
81 if (myclone)
82 ham_in.addOperator(myclone, myName, UpdateMode[PHYSICAL]);
83 }
evaluate(ParticleSet & P)84 ACForce::Return_t ACForce::evaluate(ParticleSet& P)
85 {
86 hf_force = 0;
87 pulay_force = 0;
88 wf_grad = 0;
89 sw_pulay = 0;
90 sw_grad = 0;
91 //This function returns d/dR of the sum of all observables in the physical hamiltonian.
92 //Note that the sign will be flipped based on definition of force = -d/dR.
93 Value = ham.evaluateIonDerivs(P, ions, psi, hf_force, pulay_force, wf_grad);
94
95 if (useSpaceWarp)
96 {
97 Force_t el_grad;
98 el_grad.resize(P.getTotalNum());
99 el_grad = 0;
100
101 ham.evaluateElecGrad(P, psi, el_grad, delta);
102 swt.computeSWT(P, ions, el_grad, P.G, sw_pulay, sw_grad);
103 }
104 return 0.0;
105 };
106
addObservables(PropertySetType & plist,BufferType & collectables)107 void ACForce::addObservables(PropertySetType& plist, BufferType& collectables)
108 {
109 if (FirstForceIndex < 0)
110 FirstForceIndex = plist.size();
111 for (int iat = 0; iat < Nions; iat++)
112 {
113 for (int x = 0; x < OHMMS_DIM; x++)
114 {
115 std::ostringstream hfname;
116 std::ostringstream pulayname;
117 std::ostringstream wfgradname1;
118 std::ostringstream wfgradname2;
119 hfname << prefix << "_hf_" << iat << "_" << x;
120 pulayname << prefix << "_pulay_" << iat << "_" << x;
121 wfgradname1 << prefix << "_Ewfgrad_" << iat << "_" << x;
122 wfgradname2 << prefix << "_wfgrad_" << iat << "_" << x;
123
124 plist.add(hfname.str());
125 plist.add(pulayname.str());
126 plist.add(wfgradname1.str());
127 plist.add(wfgradname2.str());
128
129 //TODO: Remove when ACForce is production ready.
130 // if(useSpaceWarp)
131 // {
132 // std::ostringstream swctname1;
133 // std::ostringstream swctname2;
134 // std::ostringstream swctname3;
135 // swctname1 << prefix << "_swct1_" << iat << "_" << x;
136 // swctname2 << prefix << "_swct2_" << iat << "_" << x;
137 // swctname3 << prefix << "_swct3_" << iat << "_" << x;
138 // plist.add(swctname1.str());
139 // plist.add(swctname2.str());
140 // plist.add(swctname3.str());
141 // }
142 }
143 }
144 };
setObservables(PropertySetType & plist)145 void ACForce::setObservables(PropertySetType& plist)
146 {
147 int myindex = FirstForceIndex;
148 for (int iat = 0; iat < Nions; iat++)
149 {
150 for (int iondim = 0; iondim < OHMMS_DIM; iondim++)
151 {
152 //Flipping the sign, since these terms currently store d/dR values.
153 // add the minus one to be a force.
154 plist[myindex++] = -hf_force[iat][iondim];
155 plist[myindex++] = -(pulay_force[iat][iondim] + sw_pulay[iat][iondim]);
156 plist[myindex++] = -Value * (wf_grad[iat][iondim] + sw_grad[iat][iondim]);
157 plist[myindex++] = -(wf_grad[iat][iondim] + sw_grad[iat][iondim]);
158
159 //TODO: Remove when ACForce is production ready
160 // if(useSpaceWarp)
161 // {
162 // plist[myindex++] = -sw_pulay[iat][iondim];
163 // plist[myindex++] = -Value*sw_grad[iat][iondim];
164 // plist[myindex++] = -sw_grad[iat][iondim];
165 // }
166 }
167 }
168 };
setParticlePropertyList(PropertySetType & plist,int offset)169 void ACForce::setParticlePropertyList(PropertySetType& plist, int offset)
170 {
171 int myindex = FirstForceIndex + offset;
172 for (int iat = 0; iat < Nions; iat++)
173 {
174 for (int iondim = 0; iondim < OHMMS_DIM; iondim++)
175 {
176 plist[myindex++] = -hf_force[iat][iondim];
177 plist[myindex++] = -(pulay_force[iat][iondim] + sw_pulay[iat][iondim]);
178 plist[myindex++] = -Value * (wf_grad[iat][iondim] + sw_grad[iat][iondim]);
179 plist[myindex++] = -(wf_grad[iat][iondim] + sw_grad[iat][iondim]);
180 //TODO: Remove when ACForce is production ready
181 // if(useSpaceWarp)
182 // {
183 // plist[myindex++] = -sw_pulay[iat][iondim];
184 // plist[myindex++] = -Value*sw_grad[iat][iondim];
185 // plist[myindex++] = -sw_grad[iat][iondim];
186 // }
187 }
188 }
189 };
190
191 } // namespace qmcplusplus
192