/*
DFT++ is a density functional package developed by the research group
of Professor Tomas Arias
Copyright 1996-2003 Sohrab Ismail-Beigi
This file is part of DFT++.
DFT++ is free software; you can redistribute it and/or modify
it 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.
DFT++ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DFT++; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Please see the file CREDITS for a list of authors.
For academic users, we request that publications using results obtained with
this software reference
"New algebraic formulation of density functional calculation," by Sohrab Ismail-Beigi
and T.A. Arias, Computer Physics Communications 128:1-2, 1-45 (June 2000).
and, if using the wavelet basis, further reference
"Multiresolution analysis of electronic structure: semicardinal and wavelet bases,"
T.A. Arias, Reviews of Modern Physics 71:1, 267-311 (January 1999).
and
"Robust ab initio calculation of condensed matter: transparent convergence through
semicardinal multiresolution analysis,'' I.P. Daykov, T.A. Arias, and
Torkel D. Engeness, Physical Review Letters, 90:21, 216402 (May 2003).
For your convenience, preprints of the above articles may be obtained from
http://arXiv.org/abs/cond-mat/9909130, 9805262, and 0204411, respectively.
*/
#include "header.h"
/*
* check_symm_fftbox
*
* Make sure that the FFT-box doesn't destroy the intrinsic symmetries of
* the system.
*
* And calculate the symmetry matrix for charge density mesh.
*/
int check_basis_symm_compatibility(Symmetries &symm, const PW_Basis &basis)
{
int N[3] = { basis.basis_spec->Nx,
basis.basis_spec->Ny,
basis.basis_spec->Nz };
matrix3 tmp, Nmat(basis.basis_spec->Nx,
basis.basis_spec->Ny,
basis.basis_spec->Nz),
Nmat_inv(1.0/basis.basis_spec->Nx,
1.0/basis.basis_spec->Ny,
1.0/basis.basis_spec->Nz);
int nrot = symm.nrot, irot, i1, i2, error = FALSE;
for (irot = 0; irot < nrot; irot++) {
tmp = symm.sym[irot] * Nmat;
for (i1 = 0; i1 < 3; i1++) {
for (i2 = 0; i2 < 3; i2++) {
if (fmod(tmp.m[i1][i2], N[i1]) > MIN_SYMM_TOL) {
if (!error)
dft_log(">>>> FFT box not comensurate with symmetries:\n");
symm.sym[irot].print(dft_global_log,"%4.0f ");
dft_log(">>>> \n");
error = TRUE;
}
}
}
symm.n_sym[irot] = Nmat * symm.sym[irot] * Nmat_inv;
}
if (error) {
dft_log(DFT_SILENCE,">>>> \t[ %d %d %d ]\n",N[0], N[1], N[2]);
dft_log(DFT_SILENCE,">>>> You have two options:\n\t1. disable symmetry\n");
dft_log(DFT_SILENCE,"\t2. manually input FFT box size\n");
die("");
}
return (! error);
}
/*
* Symmetrize the charge density for planewaves
*/
int symmetrize_n(RealSpaceScalarFieldColumn &n, Symmetries *symm)
{
Basis * basis = n.basis;
// Z is the outer index, Y the next, X the inner index.
vector3 r, rnew;
int irot, i;
int index, index2, N[3], ind[48];
real one_over_nrot, n_sum;
if (symm->nrot <= 1) // no need to do any symmetrization
return 0;
one_over_nrot = 1.0/symm->nrot;
for (i = 0; i < n.length; i++)
symm->done[i] = FALSE;
N[0] = basis->basis_spec->Nx;
N[1] = basis->basis_spec->Ny;
N[2] = basis->basis_spec->Nz;
index = 0;
for (r.v[0]=0; r.v[0] < N[0]; r.v[0]+=1) {
for (r.v[1]=0; r.v[1] < N[1]; r.v[1]+=1) {
for (r.v[2]=0; r.v[2] < N[2]; r.v[2]+=1, index++) {
// for all points in the box
// if not yet related by symmetry to a previous point
if ( !symm->done[index] ) {
n_sum = REAL( n.data.d[index] ); // first symmetry is identity.
ind[0] = index;
// for all other symmetries
for (irot = 1; irot < symm->nrot; irot++) {
// get the point related by symmetry.
rnew = symm->n_sym[irot] * r;
for (i=0;i<3;i++) { // project back into range.
rnew.v[i] = rint(rnew.v[i]);
rnew.v[i] = fmod(rnew.v[i], N[i]);
if (rnew.v[i] < 0.0)
rnew.v[i] += N[i];
}
index2 = (int)(rnew.v[2] + N[2]*(rnew.v[1] + N[1]*rnew.v[0]));
n_sum += REAL(n.data.d[ index2 ]); // add the charge density.
ind[irot] = index2; // remember the index.
}
n_sum *= one_over_nrot; // get averaged charge density.
// put symmetrized value in the star.
for (irot = 0; irot < symm->nrot; irot++) {
n.data.d[ ind[irot] ] = n_sum;
symm->done[ ind[irot] ] = TRUE;
}
}
}
}
}
return 1;
}
int symmetrize_n_dag(RealSpaceScalarFieldColumn &n, Symmetries *symm)
{
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1