diff --git a/src/BOSampleStepper.C b/src/BOSampleStepper.C
index da507c5..559541a 100644
--- a/src/BOSampleStepper.C
+++ b/src/BOSampleStepper.C
@@ -1012,7 +1012,8 @@ void BOSampleStepper::step(int niter)
if ( fractional_occ )
{
- wf.update_occ(s_.ctrl.fermi_temp);
+ if ( s_.ctrl.fermi_temp > 0 )
+ wf.update_occ(s_.ctrl.fermi_temp);
#if 0
if ( onpe0 )
{
diff --git a/src/Makefile b/src/Makefile
index a047193..ec499a3 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -548,6 +548,9 @@ Nrowmax.o: Control.h
Nspin.o: Sample.h AtomSet.h Context.h blacs.h Atom.h D3vector.h UnitCell.h
Nspin.o: D3tensor.h blas.h ConstraintSet.h ExtForceSet.h Wavefunction.h
Nspin.o: Control.h
+Occ.o: Sample.h AtomSet.h Context.h blacs.h Atom.h D3vector.h UnitCell.h
+Occ.o: D3tensor.h blas.h ConstraintSet.h ExtForceSet.h Wavefunction.h
+Occ.o: Control.h
PBEFunctional.o: PBEFunctional.h XCFunctional.h
PBEFunctional.o: XCFunctional.h
PSDAWavefunctionStepper.o: PSDAWavefunctionStepper.h WavefunctionStepper.h
@@ -837,8 +840,8 @@ qb.o: CellLock.h CellMass.h ChargeMixCoeff.h ChargeMixNdim.h ChargeMixRcut.h
qb.o: Debug.h Dspin.h Ecut.h Ecutprec.h Ecuts.h Efield.h ForceTol.h
qb.o: Polarization.h Emass.h ExtStress.h FermiTemp.h IterCmd.h
qb.o: IterCmdPeriod.h Dt.h MuRSH.h Nempty.h NetCharge.h Nrowmax.h Nspin.h
-qb.o: RefCell.h ScfTol.h Stress.h StressTol.h Thermostat.h ThTemp.h ThTime.h
-qb.o: ThWidth.h Vext.h ExternalPotential.h WfDiag.h WfDyn.h Xc.h
+qb.o: Occ.h RefCell.h ScfTol.h Stress.h StressTol.h Thermostat.h ThTemp.h
+qb.o: ThTime.h ThWidth.h Vext.h ExternalPotential.h WfDiag.h WfDyn.h Xc.h
qbox_xmlns.o: qbox_xmlns.h
release.o: release.h
sinft.o: sinft.h
diff --git a/src/Occ.h b/src/Occ.h
new file mode 100644
index 0000000..be873cf
--- /dev/null
+++ b/src/Occ.h
@@ -0,0 +1,179 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2008 The Regents of the University of California
+//
+// This file is part of Qbox
+//
+// Qbox is distributed under the terms of the GNU General Public License
+// as published by the Free Software Foundation, either version 2 of
+// the License, or (at your option) any later version.
+// See the file COPYING in the root directory of this distribution
+// or .
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// Occ.h
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef OCC_H
+#define OCC_H
+
+#include
+#include
+#include
+#include
+
+#include "Sample.h"
+
+class Occ : public Var
+{
+ Sample *s;
+
+ public:
+
+ const char *name ( void ) const { return "occ"; };
+
+ int set ( int argc, char **argv )
+ {
+ if ( (argc!=3) && (argc!=4) )
+ {
+ if ( ui->onpe0() )
+ {
+ cout << " use: set occ [ispin] n f" << endl;
+ cout << " ispin = {1|2}" << endl;
+ }
+ return 1;
+ }
+
+ if ( s->wf.nkp() != 1 )
+ {
+ if ( ui->onpe0() )
+ cout << " set occ: not implemented for multiple k-points" << endl;
+ return 1;
+ }
+
+ if ( argc == 3 )
+ {
+ // set occ n f
+ if ( s->wf.nspin() != 1 )
+ {
+ if ( ui->onpe0() )
+ cout << "nspin must be 1" << endl;
+ return 1;
+ }
+
+ const int n = atoi(argv[1]);
+ if ( (n < 1) || n > s->wf.nst() )
+ {
+ if ( ui->onpe0() )
+ cout << " n must be in [1," << s->wf.nst() << "]" << endl;
+ return 1;
+ }
+
+ const double f = atof(argv[2]);
+ if ( (f < 0.0) || (f > 2.0) )
+ {
+ if ( ui->onpe0() )
+ cout << " f must be in [0,2]" << endl;
+ return 1;
+ }
+
+ Wavefunction& wf = s->wf;
+ SlaterDet& sd = *wf.sd(0,0);
+ // n-1 in next line: states are numbered starting from 1 in
+ // the set occ command
+ sd.set_occ(n-1,f);
+ // recompute total electronic charge
+ double sum = 0.0;
+ for ( int i = 0; i < sd.nst(); i++ )
+ sum += sd.occ(i);
+ if ( ui->onpe0() )
+ cout << " total electronic charge: " << sum << endl;
+ // adjust total number of electrons
+ //wf.set_nel((int)sum);
+ }
+
+ if ( argc == 4 )
+ {
+ // set occ ispin n f
+ if ( s->wf.nspin() != 2 )
+ {
+ if ( ui->onpe0() )
+ cout << "nspin must be 2 when using ispin" << endl;
+ return 1;
+ }
+
+ const int ispin = atoi(argv[1]);
+ if ( (ispin < 1) || (ispin > 2) )
+ {
+ if ( ui->onpe0() )
+ cout << " ispin must be 1 or 2" << endl;
+ return 1;
+ }
+
+ const int n = atoi(argv[2]);
+ if ( (n < 1) || n > s->wf.nst(ispin-1) )
+ {
+ if ( ui->onpe0() )
+ cout << " n must be in [1," << s->wf.nst(ispin-1) << "]" << endl;
+ return 1;
+ }
+
+ const double f = atof(argv[3]);
+ if ( (f < 0.0) || (f > 1.0) )
+ {
+ if ( ui->onpe0() )
+ cout << " f must be in [0,1] when using ispin" << endl;
+ return 1;
+ }
+
+ Wavefunction& wf = s->wf;
+ // ispin-1 in next line: spins are numbered starting from 1 in
+ // the set occ command
+ SlaterDet& sd = *wf.sd(ispin-1,0);
+ // n-1 in next line: states are numbered starting from 1 in
+ // the set occ command
+ sd.set_occ(n-1,f);
+ // recompute total electronic charge
+ double sum = 0.0;
+ for ( int isp = 0; isp < wf.nspin(); isp++ )
+ for ( int i = 0; i < wf.nst(isp); i++ )
+ sum += wf.sd(isp,0)->occ(i);
+ if ( ui->onpe0() )
+ cout << " total electronic charge: " << sum << endl;
+ // adjust total number of electrons
+ //wf.set_nel((int)sum);
+ }
+ return 0;
+ }
+
+ string print (void) const
+ {
+ ostringstream st;
+ st.setf(ios::right,ios::adjustfield);
+ st.setf(ios::fixed,ios::floatfield);
+
+ const Wavefunction& wf = s->wf;
+ st << " occupation numbers" << endl;
+ for ( int ispin = 0; ispin < wf.nspin(); ispin++ )
+ {
+ const SlaterDet& sd = *wf.sd(ispin,0);
+ const int nst = sd.nst();
+ for ( int n = 0; n < nst; n++ )
+ {
+ st << setw(7) << setprecision(4) << sd.occ(n);
+ if ( ( n%10 ) == 9 ) st << endl;
+ }
+ if ( nst % 10 != 0 )
+ st << endl;
+ if ( (wf.nspin() == 2) && (ispin == 0) )
+ st << endl;
+ }
+ st << " total electronic charge: " << wf.nel();
+ return st.str();
+ }
+
+ Occ(Sample *sample) : s(sample) {};
+};
+#endif
diff --git a/src/SlaterDet.h b/src/SlaterDet.h
index 7d0e39e..aa2a581 100644
--- a/src/SlaterDet.h
+++ b/src/SlaterDet.h
@@ -89,6 +89,7 @@ class SlaterDet
const double* occ_ptr(int i) const { return &occ_[i]; }
void set_occ(std::vector& occ)
{ assert(occ_.size()==occ.size()); occ_ = occ; }
+ void set_occ(int i, double f) { occ_[i] = f; }
void set_eig(std::vector& eig)
{ assert(eig_.size()==eig.size()); eig_ = eig; }
void set_eig(std::valarray& eig)
diff --git a/src/Wavefunction.C b/src/Wavefunction.C
index 47633c4..13b9c88 100644
--- a/src/Wavefunction.C
+++ b/src/Wavefunction.C
@@ -42,15 +42,12 @@ nempty_(0), nspin_(1), deltaspin_(0), ecut_(0.0), nrowmax_(32)
////////////////////////////////////////////////////////////////////////////////
Wavefunction::Wavefunction(const Wavefunction& wf) : ctxt_(wf.ctxt_),
-nel_(wf.nel_), nempty_(wf.nempty_), nspin_(wf.nspin_),
+nel_(wf.nel_), nempty_(wf.nempty_), nspin_(wf.nspin_), nst_(wf.nst_),
deltaspin_(wf.deltaspin_), nrowmax_(wf.nrowmax_),
cell_(wf.cell_), refcell_(wf.refcell_),
ecut_(wf.ecut_), weight_(wf.weight_), kpoint_(wf.kpoint_)
{
// Create a Wavefunction using the dimensions of the argument
-
- compute_nst();
-
// Next lines: do special allocation of contexts to ensure that
// contexts are same as those of wf
spincontext_ = new Context(*wf.spincontext_);
@@ -58,8 +55,7 @@ ecut_(wf.ecut_), weight_(wf.weight_), kpoint_(wf.kpoint_)
sdcontext_ = new Context(*wf.sdcontext_);
allocate();
-
- resize(cell_,refcell_,ecut_);
+ resize();
init();
}
@@ -147,6 +143,34 @@ double Wavefunction::entropy(void) const
}
////////////////////////////////////////////////////////////////////////////////
+void Wavefunction::resize(void)
+{
+ try
+ {
+ // resize all SlaterDets using current cell_, refcell_, ecut_, nst_[ispin]
+ for ( int ispin = 0; ispin < nspin_; ispin++ )
+ {
+ for ( int ikp = 0; ikp < kpoint_.size(); ikp++ )
+ {
+ sd_[ispin][ikp]->resize(cell_,refcell_,ecut_,nst_[ispin]);
+ }
+ }
+ }
+ catch ( const SlaterDetException& sdex )
+ {
+ cout << " Wavefunction: SlaterDetException during resize: " << endl
+ << sdex.msg << endl;
+ // no resize took place
+ return;
+ }
+ catch ( bad_alloc )
+ {
+ cout << " Wavefunction: insufficient memory for resize operation" << endl;
+ return;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
void Wavefunction::resize(const UnitCell& cell, const UnitCell& refcell,
double ecut)
{
@@ -176,7 +200,6 @@ void Wavefunction::resize(const UnitCell& cell, const UnitCell& refcell,
cout << " Wavefunction: insufficient memory for resize operation" << endl;
return;
}
-
}
////////////////////////////////////////////////////////////////////////////////
@@ -252,7 +275,7 @@ void Wavefunction::set_nel(int nel)
nel_ = nel;
compute_nst();
- resize(cell_,refcell_,ecut_);
+ resize();
}
////////////////////////////////////////////////////////////////////////////////
@@ -267,7 +290,7 @@ void Wavefunction::set_nempty(int nempty)
nempty_ = nempty;
compute_nst();
update_occ(0.0);
- resize(cell_,refcell_,ecut_);
+ resize();
}
////////////////////////////////////////////////////////////////////////////////
@@ -281,7 +304,7 @@ void Wavefunction::set_nspin(int nspin)
compute_nst();
allocate();
- resize(cell_,refcell_,ecut_);
+ resize();
init();
update_occ(0.0);
}
@@ -306,7 +329,7 @@ void Wavefunction::set_deltaspin(int deltaspin)
deltaspin_ = deltaspin;
compute_nst();
allocate();
- resize(cell_,refcell_,ecut_);
+ resize();
init();
update_occ(0.0);
}
@@ -345,7 +368,7 @@ void Wavefunction::set_nrowmax(int n)
create_contexts();
compute_nst();
allocate();
- resize(cell_,refcell_,ecut_);
+ resize();
init();
}
@@ -421,7 +444,7 @@ void Wavefunction::del_kpoint(D3vector kpoint)
kpoint_.erase(pk);
weight_.erase(pw);
allocate();
- resize(cell_,refcell_,ecut_);
+ resize();
init();
update_occ(0.0);
}
diff --git a/src/qb.C b/src/qb.C
index 596ebc2..66774a7 100644
--- a/src/qb.C
+++ b/src/qb.C
@@ -108,6 +108,7 @@ using namespace std;
#include "NetCharge.h"
#include "Nrowmax.h"
#include "Nspin.h"
+#include "Occ.h"
#include "RefCell.h"
#include "ScfTol.h"
#include "Stress.h"
@@ -301,6 +302,7 @@ int main(int argc, char **argv, char **envp)
ui.addVar(new NetCharge(s));
ui.addVar(new Nrowmax(s));
ui.addVar(new Nspin(s));
+ ui.addVar(new Occ(s));
ui.addVar(new Dspin(s));
ui.addVar(new RefCell(s));
ui.addVar(new ScfTol(s));