Commit 235f09b4 authored by Francois Gygi's avatar Francois Gygi
Browse files

merge trunk into efield branch


git-svn-id: http://qboxcode.org/svn/qb/branches/efield@1622 cba15fb0-1239-40c8-b417-11db7ca47a34
parent decfcf37
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014 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 <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////
//
// AlphaPBE0.h
//
////////////////////////////////////////////////////////////////////////////////
#ifndef ALPHAPBE0_H
#define ALPHAPBE0_H
#include<iostream>
#include<iomanip>
#include<sstream>
#include<stdlib.h>
#include "Sample.h"
class AlphaPBE0 : public Var
{
Sample *s;
public:
const char *name ( void ) const { return "alpha_PBE0"; };
int set ( int argc, char **argv )
{
if ( argc != 2 )
{
if ( ui->onpe0() )
cout << " alpha_PBE0 takes only one value" << endl;
return 1;
}
double v = atof(argv[1]);
if ( v < 0.0 )
{
if ( ui->onpe0() )
cout << " alpha_PBE0 must be non-negative" << endl;
return 1;
}
s->ctrl.alpha_PBE0 = v;
return 0;
}
string print (void) const
{
ostringstream st;
st.setf(ios::left,ios::adjustfield);
st << setw(10) << name() << " = ";
st.setf(ios::right,ios::adjustfield);
st << s->ctrl.alpha_PBE0;
return st.str();
}
AlphaPBE0(Sample *sample) : s(sample)
{
s->ctrl.alpha_PBE0 = 0.25;
}
};
#endif
......@@ -15,13 +15,40 @@
// AndersonMixer.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: AndersonMixer.C,v 1.12 2009-09-08 14:26:01 fgygi Exp $
#include "AndersonMixer.h"
#include "blas.h"
#include <iostream>
#if USE_MPI
#include <mpi.h>
#else
typedef int MPI_Comm;
#endif
using namespace std;
////////////////////////////////////////////////////////////////////////////////
AndersonMixer::AndersonMixer(const int m, const int nmax,
const MPI_Comm* const pcomm) : m_(m), nmax_(nmax), pcomm_(pcomm)
{
#if USE_MPI
if ( pcomm_ != 0 )
{
MPI_Comm_rank(*pcomm_,&mype_);
MPI_Comm_size(*pcomm_,&npes_);
}
#endif
assert( nmax >= 0 );
x_.resize(nmax_+1);
f_.resize(nmax_+1);
for ( int n = 0; n < nmax_+1; n++ )
{
x_[n].resize(m_);
f_[n].resize(m_);
}
restart();
}
////////////////////////////////////////////////////////////////////////////////
void AndersonMixer::restart(void)
{
......@@ -52,15 +79,17 @@ void AndersonMixer::update(double* x, double* f, double* xbar, double* fbar)
f_[k_][i] = f[i];
}
valarray<double> a;
valarray<double> b;
valarray<double> a,atmp;
valarray<double> b,btmp;
valarray<double> theta;
if ( n_ > 0 )
{
// compute matrix A = F^T F and rhs b = F^T f
// compute the lower part of A only (i>=j)
a.resize(n_*n_);
atmp.resize(n_*n_);
b.resize(n_);
btmp.resize(n_);
theta.resize(n_);
for ( int i = 0; i < n_; i++ )
{
......@@ -85,42 +114,19 @@ void AndersonMixer::update(double* x, double* f, double* xbar, double* fbar)
b[i] = bsum;
}
if ( pctxt_ != 0 )
#if USE_MPI
if ( pcomm_ != 0 )
{
pctxt_->dsum(n_*n_,1,&a[0],n_*n_);
pctxt_->dsum(n_,1,&b[0],n_);
}
#if 0
// print matrix a and rhs b
if ( pctxt_ != 0 )
{
for ( int ip =0; ip < pctxt_->size(); ip++ )
{
pctxt_->barrier();
if ( pctxt_->mype() == ip )
{
// print matrix a and rhs b
double anrm = 0.0;
for ( int i = 0; i < n_; i++ )
for ( int j = 0; j <=i; j++ )
{
cout << pctxt_->mype() << ": "
<< "a("<<i<<","<<j<<")=" << a[i+j*n_] << endl;
anrm += a[i+j*n_]*a[i+j*n_];
}
for ( int i = 0; i < n_; i++ )
cout << pctxt_->mype() << ": "
<< "b("<<i<<")=" << b[i] << endl;
//cout << " AndersonMixer: n=" << n_ << " anorm = " << anrm << endl;
}
}
MPI_Allreduce(&a[0],&atmp[0],n_*n_,MPI_DOUBLE,MPI_SUM,*pcomm_);
a = atmp;
MPI_Allreduce(&b[0],&btmp[0],n_,MPI_DOUBLE,MPI_SUM,*pcomm_);
b = btmp;
}
#endif
// solve the linear system a * theta = b
// solve on task 0 and bcast result
if ( pctxt_ == 0 || pctxt_->onpe0() )
if ( pcomm_ == 0 || mype_ == 0 )
{
const bool diag = false;
if ( diag )
......@@ -241,27 +247,11 @@ void AndersonMixer::update(double* x, double* f, double* xbar, double* fbar)
}
#if USE_MPI
// broadcast theta from task 0
if ( pctxt_ != 0 )
{
if ( pctxt_->onpe0() )
pctxt_->dbcast_send(n_,1,&theta[0],n_);
else
pctxt_->dbcast_recv(n_,1,&theta[0],n_,0,0);
}
#if 0
for ( int ip = 0; ip < pctxt_->size(); ip++ )
if ( pcomm_ != 0 )
{
pctxt_->barrier();
if ( pctxt_->mype() == ip )
{
cout << pctxt_->mype() << ": ";
cout << " AndersonMixer: theta = ";
for ( int i = 0; i < theta.size(); i++ )
cout << theta[i] << " ";
cout << endl;
}
MPI_Bcast(&theta[0],n_,MPI_DOUBLE,0,*pcomm_);
}
#endif
......
......@@ -15,7 +15,6 @@
// AndersonMixer.h
//
////////////////////////////////////////////////////////////////////////////////
// $Id: AndersonMixer.h,v 1.8 2009-03-08 01:10:30 fgygi Exp $
#ifndef ANDERSONMIXER_H
#define ANDERSONMIXER_H
......@@ -23,7 +22,11 @@
#include <vector>
#include <valarray>
#include <cassert>
#include "Context.h"
#ifdef USE_MPI
#include <mpi.h>
#else
typedef int MPI_Comm;
#endif
class AndersonMixer
{
......@@ -34,26 +37,15 @@ class AndersonMixer
int nmax_; // maximum number of vectors (without current)
int n_; // number of vectors
int k_; // index of current vector
const Context* const pctxt_; // pointer to relevant Context, null if local
const MPI_Comm* const pcomm_;// pointer to relevant Context, null if local
int mype_;
int npes_;
std::vector<std::valarray<double> > x_,f_;
public:
AndersonMixer(const int m, const int nmax, const Context* const pctxt) :
m_(m), nmax_(nmax), pctxt_(pctxt)
{
assert( nmax >= 0 );
x_.resize(nmax_+1);
f_.resize(nmax_+1);
for ( int n = 0; n < nmax_+1; n++ )
{
x_[n].resize(m_);
f_[n].resize(m_);
}
restart();
}
AndersonMixer(const int m, const int nmax, const MPI_Comm* const pcomm);
void update(double* x, double* f, double* xbar, double* fbar);
void restart(void);
};
......
......@@ -32,29 +32,53 @@ class AngleCmd : public Cmd
AngleCmd(Sample *sample) : s(sample) {};
char *name(void) const { return "angle"; }
char *help_msg(void) const
const char *name(void) const { return "angle"; }
const char *help_msg(void) const
{
return
"\n angle\n\n"
" syntax: angle name1 name2 name3\n\n"
" The angle command prints the angle defined by three atoms.\n\n";
" syntax: angle [-pbc] name1 name2 name3\n\n"
" The angle command prints the angle defined by three atoms.\n"
" If the -pbc option is used, the angle is computed using the\n"
" nearest atoms taking into account periodic boundary conditions.\n\n";
}
int action(int argc, char **argv)
{
if ( argc != 4 )
if ( ! ( argc == 4 || argc == 5 ) )
{
if ( ui->onpe0() )
{
cout << " use: angle name1 name2 name3" << endl;
cout << " use: angle [-pbc] name1 name2 name3" << endl;
}
return 1;
}
string name1(argv[1]);
string name2(argv[2]);
string name3(argv[3]);
string name1, name2, name3;
bool use_pbc = false;
if ( argc == 4 )
{
name1 = argv[1];
name2 = argv[2];
name3 = argv[3];
}
if ( argc == 5 )
{
if ( strcmp(argv[1],"-pbc") )
{
if ( ui->onpe0() )
{
cout << " use: angle [-pbc] name1 name2 name3" << endl;
}
return 1;
}
use_pbc = true;
name1 = argv[2];
name2 = argv[3];
name3 = argv[4];
}
Atom* a1 = s->atoms.findAtom(name1);
Atom* a2 = s->atoms.findAtom(name2);
Atom* a3 = s->atoms.findAtom(name3);
......@@ -82,22 +106,25 @@ class AngleCmd : public Cmd
return 1;
}
D3vector r12(a1->position()-a2->position());
D3vector r32(a3->position()-a2->position());
if ( norm2(r12) == 0.0 || norm2(r32) == 0.0 )
if ( ui->onpe0() )
{
if ( ui->onpe0() )
D3vector r12(a1->position()-a2->position());
D3vector r32(a3->position()-a2->position());
if ( norm2(r12) == 0.0 || norm2(r32) == 0.0 )
{
cout << " AngleCmd: atoms are too close" << endl;
return 1;
}
return 1;
}
const double sp = normalized(r12) * normalized(r32);
const double c = max(-1.0,min(1.0,sp));
const double a = (180.0/M_PI)*acos(c);
if ( ui->onpe0() )
{
if ( use_pbc )
{
const UnitCell& cell = s->wf.cell();
cell.fold_in_ws(r12);
cell.fold_in_ws(r32);
}
const double sp = normalized(r12) * normalized(r32);
const double c = max(-1.0,min(1.0,sp));
const double a = (180.0/M_PI)*acos(c);
cout.setf(ios::fixed,ios::floatfield);
cout << " angle " << name1 << "-" << name2 << "-" << name3
<< ": "
......
......@@ -34,8 +34,8 @@ class AtomCmd : public Cmd
AtomCmd(Sample *sample) : s(sample) {};
char *name(void) const { return "atom"; }
char *help_msg(void) const
const char *name(void) const { return "atom"; }
const char *help_msg(void) const
{
return
"\n atom\n\n"
......
......@@ -496,6 +496,7 @@ void AtomSet::randomize_velocities(double temp)
v[is][3*ia+2] = width * xi2;
}
}
reset_vcm();
set_velocities(v);
}
......
......@@ -15,9 +15,6 @@
// AtomSetHandler.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: AtomSetHandler.C,v 1.13 2008-09-08 15:56:18 fgygi Exp $
#if USE_XERCES
#include "AtomSetHandler.h"
#include "AtomSet.h"
......@@ -104,20 +101,6 @@ void AtomSetHandler::endElement(const XMLCh* const uri,
istringstream stst(content);
if ( locname == "unit_cell")
{
event_type event = unit_cell;
as_.context().ibcast_send(1,1,(int*)&event,1);
// notify listening nodes
double buf[9];
buf[0] = as_.cell().a(0).x;
buf[1] = as_.cell().a(0).y;
buf[2] = as_.cell().a(0).z;
buf[3] = as_.cell().a(1).x;
buf[4] = as_.cell().a(1).y;
buf[5] = as_.cell().a(1).z;
buf[6] = as_.cell().a(2).x;
buf[7] = as_.cell().a(2).y;
buf[8] = as_.cell().a(2).z;
as_.context().dbcast_send(9,1,buf,9);
}
else if ( locname == "atom")
{
......@@ -143,21 +126,6 @@ void AtomSetHandler::endElement(const XMLCh* const uri,
throw;
}
// notify listening nodes and broadcast atom info
event_type event = atom;
as_.context().ibcast_send(1,1,(int*)&event,1);
as_.context().string_bcast(current_atom_name,0);
as_.context().string_bcast(current_atom_species,0);
double buf[3];
buf[0] = current_atom_position.x;
buf[1] = current_atom_position.y;
buf[2] = current_atom_position.z;
as_.context().dbcast_send(3,1,buf,3);
buf[0] = current_atom_velocity.x;
buf[1] = current_atom_velocity.y;
buf[2] = current_atom_velocity.z;
as_.context().dbcast_send(3,1,buf,3);
}
else if ( locname == "position" )
{
......@@ -193,7 +161,7 @@ StructureHandler* AtomSetHandler::startSubHandler(const XMLCh* const uri,
}
// delegate to SpeciesHandler
current_species = new Species(as_.context(),current_species_name);
current_species = new Species(current_species_name);
return new SpeciesHandler(*current_species);
}
else
......@@ -211,7 +179,7 @@ void AtomSetHandler::endSubHandler(const XMLCh* const uri,
// cout << " AtomSetHandler::endSubHandler " << locname << endl;
if ( locname == "species" )
{
SpeciesReader sp_reader(current_species->context());
SpeciesReader sp_reader;
// check if only the uri was provided
if ( current_species->uri() != "" )
......@@ -219,22 +187,9 @@ void AtomSetHandler::endSubHandler(const XMLCh* const uri,
// href was found in species definition
// attempt to read the species from that uri
try
{
sp_reader.readSpecies(*current_species,current_species->uri());
}
catch ( const SpeciesReaderException& e )
{
cout << " SpeciesReaderException caught in AtomSetHandler" << endl;
}
sp_reader.uri_to_species(current_species->uri(),*current_species);
}
// notify listening nodes and broadcast species info
event_type event = species;
as_.context().ibcast_send(1,1,(int*)&event,1);
as_.context().string_bcast(current_species_name,0);
sp_reader.bcastSpecies(*current_species);
// cout << "AtomSetHandler::endSubHandler: adding Species:"
// << current_species_name << endl;
try
......@@ -250,5 +205,3 @@ void AtomSetHandler::endSubHandler(const XMLCh* const uri,
}
delete last;
}
#endif
......@@ -33,7 +33,7 @@ class AtomsDyn : public Var
public:
char *name ( void ) const { return "atoms_dyn"; };
const char *name ( void ) const { return "atoms_dyn"; };
int set ( int argc, char **argv )
{
......
......@@ -25,6 +25,7 @@
#include "PSDWavefunctionStepper.h"
#include "PSDAWavefunctionStepper.h"
#include "JDWavefunctionStepper.h"
#include "Preconditioner.h"
#include "SDIonicStepper.h"
#include "SDAIonicStepper.h"
#include "CGIonicStepper.h"
......@@ -146,7 +147,17 @@ void BOSampleStepper::initialize_density(void)
}
}
// Initialize charge equally for both spins
cd_.rhog[0] = rhopst;
if ( cd_.rhog.size() == 2 )
{
assert(cd_.rhog[0].size()==cd_.rhog[1].size());
for ( int i = 0; i < cd_.rhog[0].size(); i++ )
{
cd_.rhog[0][i] = 0.5 * rhopst[i];
cd_.rhog[1][i] = 0.5 * rhopst[i];
}
}
initial_atomic_density = true;
}
......@@ -198,6 +209,8 @@ void BOSampleStepper::step(int niter)
Timer tm_iter;
Preconditioner prec(wf,ef_,s_.ctrl.ecutprec);
WavefunctionStepper* wf_stepper = 0;
if ( wf_dyn == "SD" )
{
......@@ -213,11 +226,11 @@ void BOSampleStepper::step(int niter)
wf_stepper = new SDWavefunctionStepper(wf,dt2bye,tmap);
}
else if ( wf_dyn == "PSD" )
wf_stepper = new PSDWavefunctionStepper(wf,s_.ctrl.ecutprec,tmap);
wf_stepper = new PSDWavefunctionStepper(wf,prec,tmap);
else if ( wf_dyn == "PSDA" )
wf_stepper = new PSDAWavefunctionStepper(wf,s_.ctrl.ecutprec,tmap);
wf_stepper = new PSDAWavefunctionStepper(wf,prec,tmap);
else if ( wf_dyn == "JD" )
wf_stepper = new JDWavefunctionStepper(wf,s_.ctrl.ecutprec,ef_,tmap);
wf_stepper = new JDWavefunctionStepper(wf,prec,ef_,tmap);
// wf_stepper == 0 indicates that wf_dyn == LOCKED
......@@ -273,26 +286,18 @@ void BOSampleStepper::step(int niter)
mlwft[ispin] = new MLWFTransform(*wf.sd(ispin,0));
}
// Charge mixing variables
vector<vector<complex<double> > > rhog_in(nspin);
vector<vector<complex<double> > > drhog(nspin);
vector<vector<complex<double> > > rhobar(nspin);
vector<vector<complex<double> > > drhobar(nspin);
for ( int ispin = 0; ispin < nspin; ispin++ )
{
rhog_in[ispin].resize(cd_.rhog[ispin].size());
drhog[ispin].resize(rhog_in[ispin].size());
rhobar[ispin].resize(rhog_in[ispin].size());
drhobar[ispin].resize(rhog_in[ispin].size());
}
// Charge mixing variables: include both spins in the same vector
if ( nspin > 1 ) assert(cd_.rhog[0].size()==cd_.rhog[1].size());
const int ng = cd_.rhog[0].size();
vector<complex<double> > rhog_in(nspin*ng), drhog(nspin*ng),
rhobar(nspin*ng), drhobar(nspin*ng);
const int anderson_ndim = s_.ctrl.charge_mix_ndim;
vector<double> wkerker(cd_.rhog[0].size());
vector<double> wls(cd_.rhog[0].size());
vector<double> wkerker(ng), wls(ng);
vector<AndersonMixer*> mixer(nspin);
for ( int ispin = 0; ispin < nspin; ispin++ )
mixer[ispin] =
new AndersonMixer(2*rhog_in[ispin].size(),anderson_ndim,&cd_.vcontext());
// Anderson charge mixer: include both spins in the same vector
// Factor of 2: complex coeffs stored as double
MPI_Comm vcomm = cd_.vcomm();
AndersonMixer mixer(2*nspin*ng,anderson_ndim,&vcomm);
// compute Kerker preconditioning
// real space Kerker cutoff in a.u.
......@@ -309,7 +314,8 @@ void BOSampleStepper::step(int niter)
istringstream is(s_.ctrl.debug);
string s;
is >> s >> rc1;
cout << " override rc1 value: rc1 = " << rc1 << endl;
if ( onpe0 )
cout << " override rc1 value: rc1 = " << rc1 << endl;
assert(rc1 >= 0.0);
}
......@@ -364,7 +370,7 @@ void BOSampleStepper::step(int niter)
cd_.update_density();
tmap["charge"].stop();
ef_.update_vhxc();
ef_.update_vhxc(compute_stress);
const bool compute_forces = true;
double energy =
ef_.energy(false,dwf,compute_forces,fion,compute_stress,sigma_eks);
......@@ -708,16 +714,15 @@ void BOSampleStepper::step(int niter)
{
wf_stepper->preprocess();
if ( anderson_charge_mixing )
{
for ( int ispin = 0; ispin < nspin; ispin++ )
mixer[ispin]->restart();
}
mixer.restart();
double ehart, ehart_m;
bool scf_converged = false;
int itscf = 0;
for ( int itscf = 0; itscf < nitscf_; itscf++ )
while ( !scf_converged && itscf < nitscf_ )
{
if ( nite_ > 1 && onpe0 )
if ( nite_ > 0 && onpe0 )
cout << " BOSampleStepper: start scf iteration" << endl;