/* 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; }