/* 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. */ /************************************************************************* * * Defines the Wavelet_Complex_Column class * ************************************************************************/ #include "header.h" WL_ComplexColumn::WL_ComplexColumn():fat(TRUE) { // fat = TRUE; length = 0; basis_spec = NULL; basis = NULL; representation = REALSPACE; //default embedding = SPARSE; } WL_ComplexColumn::WL_ComplexColumn(WL_Basis *b, char s[10]) { if(!strcmp(s,"fat")) fat = TRUE; else if (!strcmp(s,"slim")) fat = FALSE; else die("WL_Column(): Identity crisis - don't know if i'm slim or fat\n"); basis = b; // We must be able to accept a null pointer! if(b != NULL) { basis_spec = b->basis_spec; // ipd: get rid of these - make everything like PW_Column length = b->nbasis; // Grab the quantum numbers from the basis. // kvec = b->qnum->kvec; } // These are defaults. representation = REALSPACE; embedding = SPARSE; } WL_ComplexColumn::WL_ComplexColumn(const WL_ComplexColumn &col, char s[10]) { if(!strcmp(s,"fat")) fat = TRUE; else if (!strcmp(s,"slim")) fat = FALSE; else die("PW_Column(): Identity crisis - don't know if i'm slim or fat\n"); length = col.length; basis_spec = col.basis_spec; basis = col.basis; representation = col.representation; embedding = col.embedding; //can we get rid of these? // kvec = col.kvec; // weight = col.weight; if(fat) { data.init(length); data = col.data; } else die("You can't copy a slim column, fatso!\n"); } // destructor WL_ComplexColumn::~WL_ComplexColumn() { if(fat) data.free(); } void WL_ComplexColumn::init_wavefunction(WL_Basis &b) { length = b.nbasis; basis_spec = b.basis_spec; basis = &b; representation = COEFFSPACE; embedding = SPARSE; } // We'll decide later if this should be different. void WL_ComplexColumn::init_scalarfield(WL_Basis &b, int space) { // ipd: since *qnum is part of basis we want scalarfields and wfs to // have different basis - think how to fix it basis = &b; basis_spec = b.basis_spec; representation = space; //ipd:replace this w/ an input flag (in basis/basis_spec) if(basis_spec->use_dense){ embedding = DENSE; length = 8*b.nbasis; } else { embedding = SPARSE; length = b.nbasis; } if(fat) data.init(length); else die("You cannot initialize a slim column to contain a scalar field\n"); } void WL_ComplexColumn::read(char *realfile, char *imagfile) { FILE *fpin; int ii; double *databuf; databuf=(double *)mymalloc(length*sizeof(double), "databuf", "WL_ComplexColumn::read(...)"); fpin = dft_fopen(realfile,"r"); // Store the data into databuf. if(dft_fread(databuf, sizeof(double), length, fpin) != length) die("Error reading %d items for column initialization!",length); dft_fclose(fpin); // And store it in the real parts. for(ii=0; iigridspec,NULL); GetRe(grid,*this); zeroghostrec(grid); PutRe(grid,*this); GetIm(grid,*this); zeroghostrec(grid); PutIm(grid,*this); killgridnew(grid); return dot(data, col.data); } default: die("Unknown rerpesentation: %d\n",representation); } return 0.; } //ipd: would be nicer to do it in one loop - just change adjustdown/zeroghost void WL_ComplexColumn::randomize() { Gridspec *gridspec; // choose the appropriate gridspec switch(embedding){ case SPARSE: gridspec = basis_spec->gridspec; break; case DENSE: gridspec = basis_spec->gridspec_dense; break; default: die("randomize(): Unknown input embedding %d\n",embedding); } Grid *grid = mkgridnew(gridspec,NULL); // Do the real part. for(int i=0; i<(grid->nxyzwholegrid); i++) grid->dat[i] = rand()/(RAND_MAX+1.0)-0.5; switch(representation) { case REALSPACE: // Realspace convention is: ghost=parent adjustdown(grid); PutRe(grid,*this); break; case COEFFSPACE: // Coeffspace convention is: ghost=0 zeroghostrec(grid); PutRe(grid,*this); break; default: dft_log("\nInvalid representation in WL_ComplexColumn::randomize()!\n"); break; } // Do the imaginary part. for(int i=0; i<(grid->nxyzwholegrid); i++) grid->dat[i] = rand()/(RAND_MAX+1.0)-0.5; switch(representation) { case REALSPACE: // Realspace convention is: ghost=parent adjustdown(grid); PutIm(grid,*this); break; case COEFFSPACE: // Coeffspace convention is: ghost=0 zeroghostrec(grid); PutIm(grid,*this); break; default: dft_log("\nInvalid representation in WL_ComplexColumn::randomize()!\n"); break; } killgridnew(grid); } void WL_ComplexColumn::setones() { int ii; for(ii=0; iirepresentation == COEFFSPACE) apply_J(*this, *this); return; } // BASIS SPECIFIC // Returns the real part of the data as a Grid structure. void GetRe(Grid *out, const WL_ComplexColumn &col) { #ifdef DFT_PROFILING timerOn(60); counterIncr(25); #endif // DFT_PROFILING // Consistency checks. if(out == NULL) die("Passed NULL Grid to GetRe!\n"); if(out->nxyzwholegrid != col.length) die("Grid structure doesn't match Column length in GetRe!%d %d\n", out->nxyzwholegrid, col.length); // In mkgridnew, the data is allocated as a single block (instead of // level-by-level. Thus, we should just need to copy the data as a vector. int ii; for(ii=0;iidat[ii] = col.data.d[ii].x; #ifdef DFT_PROFILING timerOff(60); #endif // DFT_PROFILING return; } void GetIm(Grid *out, const WL_ComplexColumn &col) { #ifdef DFT_PROFILING timerOn(60); counterIncr(25); #endif // DFT_PROFILING // Consistency checks. if(out == NULL) die("Passed NULL Grid to GetIm!\n"); if(out->nxyzwholegrid != col.length) die("Grid structure doesn't match Column length in GetIm!\n"); // In mkgridnew, the data is allocated as a single block (instead of // level-by-level. Thus, we should just need to copy the data as a vector. int ii; for(ii=0;iidat[ii] = col.data.d[ii].y; #ifdef DFT_PROFILING timerOff(60); #endif // DFT_PROFILING return; } void PutRe(const Grid *in, WL_ComplexColumn &col) { #ifdef DFT_PROFILING timerOn(60); counterIncr(25); #endif // DFT_PROFILING // Again, if we assume that the grid storage is allocated as a block, this is // pretty easy. int ii; for(ii=0;iidat[ii]; #ifdef DFT_PROFILING timerOff(60); #endif // DFT_PROFILING return; } void PutIm(const Grid *in, WL_ComplexColumn &col) { #ifdef DFT_PROFILING timerOn(60); counterIncr(25); #endif // DFT_PROFILING int ii; for(ii=0;iidat[ii]; #ifdef DFT_PROFILING timerOff(60); #endif // DFT_PROFILING return; } // adds the square of the absolute value void add_scale_abs2(const complex &c, const WL_ComplexColumn & in, WL_ComplexColumn &out) { add_scale_abs2(c, in.data, out.data); } WL_ComplexColumn abs2(WL_ComplexColumn &in) { int i; WL_ComplexColumn out(in); for(i=0; i