/* 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. */ // // Sohrab Ismail-Beigi August 2 1999 // // This is the main DFT++ executable. // It handles electronic minimizations, calculation of forces, and // ionic dynamics. Ionic relaxations are not working yet. // It has been cleaned up a bit and the structure should be clear. // The basic idea is to do any MPI setup if needed, then // to try to read the input file, and then to do any minimizations/force/ // dynamics as needed, and finally to dump the current state and exit. // /* $Id: dft-two.cpp,v 1.1.2.92 2003/05/29 18:54:16 ivan Exp $ */ #include "header.h" #include "parallel.h" #include // Default input filename #define DEFAULT_INPUTFILE "dft.in" // This report level reports all the basic messages we might // be interested to the log file. More or less anal options // can be found in header.h #define REPORT_LEVEL DFT_BASIC_LOG // Prints a banner void print_banner(char **argv,char *input_filename); // Parses the command line arguments to main(). See down below. void parse_command_line(int argc, char **argv, char *input_filename, char *log_filename); void optest(Everything &e); void Etest(Everything &e); // HACK ALERT!!! // This variable stores the square magnitude of Ygrad globally, so that the // wavelet invL routing can access it. double global_abs2Yg; /*************************************************************************** * * * Main Program: * * * ***************************************************************************/ int main(int argc,char**argv) { // Do any system dependent setup if needed System::GlobalInit(&argc,&argv); #ifdef DFT_PROFILING // Activate timers and counters timerActivateAll(); counterActivateAll(); // Turn initialization timer on timerOn(0); // Initialization timer on #endif // The variables needed to do the work. Contains inside everything // we will need! Everything everything; /********************************************************** ** ** ** Reading command line, setting up logfile. ** ** ** **********************************************************/ // initialize input/output files to defaults. char input_filename[DFT_FILENAME_LEN] = DEFAULT_INPUTFILE; char log_filename[DFT_FILENAME_LEN] = ""; // Parse command line and get input and log filenames. parse_command_line(argc,argv,input_filename,log_filename); // Open the logfile and make the system logger point to it Output logfile(REPORT_LEVEL,log_filename); System::global_log = &logfile; /********************************************************** ** Setup section: read and parser the input file, and ** ** the preform the various setup routines to prepare ** ** everything. ** **********************************************************/ // Try to open the input file dft_text_FILE *inputfile = dft_text_fopen(input_filename,"r"); if (inputfile == NULL) die("\n%s: can't read '%s'. Aborting.\n\n",argv[0], input_filename); // Print a welcome banner with useful information print_banner(argv,input_filename); // expand all includes in the input file. inputfile->expand_include(); // parse input file and do the setup parse(inputfile,everything); dft_text_fclose(inputfile); // ipd: hack to check it works - move it in everything.setup // and put the actual variable names in there // System::setup_scratch(3, 50, sizeof(complex)); // System::setup_scratch(3, 25, sizeof(complex)); // System::setup_scratch(3, 30, sizeof(complex)); // initial setup everything.setup(); #ifdef DFT_PROFILING timerOff(0); // turn off initialization timer. timerOn(1); // turn on total computation timer. #endif //optest(everything); exit(1); // Calculate the local pseudopotential vector if not reading it from file // // NOTE: this routine is basis dependent, and so // has to be supplied by the basis developers // // if doing band structure we supply the self consistent potential // which would include Vloc from the ions. // change this once starting from charge densities is included. if(everything.cntrl.band_structure_flag != TRUE) Vlocpot(everything); // calculate electron independent energies just once calc_core_ewald_pulay_energies(everything); //TEST the symemtries // symmetrize_n(everything.elecvars.Vlocpot, &everything.symm); // everything.elecvars.Vlocpot.write("Vs"); // here we may try to if(everything.cntrl.finite_diff_test_flag) { finitedifftest(everything); die("FINITE DIFF TEST DONE, EXITTING\n"); } //calc_all_energies(everything); minimize_elec(everything); //now do the forces - no iondynamics loop yet if ( everything.cntrl.calculate_forces_flag ) { calc_UVCn_d(everything); // Calculate and report the forces calc_ionic_forces(everything); everything.ioninfo.print_force(dft_global_log, everything); } // Setup the signal handlers: turned off for now... // the signal setup is disable right now. only a skeleton is left. // setup_signals(&elecinfo,&elecvars); #ifdef DFT_PROFILING timerOff(1); // turn off total computation timer. #endif // Write out final electronic state to disk dft_log("\nDone! Dumping final variables:\n\n"); dft_log_flush(); dump_and_stamp_variables(everything); #ifdef DFT_PROFILING // Print a final timer and counter report (with some very large // iteration number, which should be our last! timer_counter_Report(9999); #endif // End any system dependent stuff System::GlobalFinalize(); return 0; } // // Print the a banner with time, date, and parallelization info (if any) // void print_banner(char **argv,char *input_filename) { time_t timenow = time(0); dft_log("\n******************************************************\n"); dft_log("Current date and time: %s\n",ctime(&timenow)); #ifdef DFT_MPI dft_log("This is an MPI run: N_Procs = %d\n",System::Get_N_Procs()); dft_log("Setting NODE_ID dependent seed\n"); srand(System::Get_procID()*1234+5678);//include time in it later #endif #ifdef DFT_THREAD dft_log("This is a thread run: N_threads = %d\n",System::Get_N_threads()); #endif dft_log("%s: input file is '%s'\n",argv[0],input_filename); } // // Print out help information (e.g. command line options) // void help(char *name) { // print out some help information dft_log("\nUsage: %s [options]\n",name); dft_log("\n\tPerforms ab-initio density-functional calculations.\n\n"); dft_log("options:\n\n"); dft_log("\t-h\t\thelp (this output)\n"); dft_log("\t-i \tspecifies input file, default = 'dft.in'\n"); dft_log("\t-o \tspecifies output log file, default = stdout\n"); #ifdef DFT_THREAD dft_log("\t-n \tspecifies the number of threads, default = 1\n"); #endif dft_log("\t-t\t\tprints an example input file to stdout and exits.\n"); dft_log("\n"); } // // Parse command line. Command line options currently // are -i, -o, -t, and -h. // void parse_command_line(int argc, char **argv, char *input_filename, char *log_filename) { // Logs to stdout. We need this to report // basic errors and problems on the command line. // Make the system logging point to it for now. Output helplog; System::global_log = &helplog; int k=0; while(1) { // If we get to the end of the command line with no problems, // we are done! if (++k==argc) return; // produce a template input file. else if (MATCH(argv[k],"-t")) { Everything tempeverything; print_default_template(dft_global_log,tempeverything); break; } // override default output file. else if (MATCH(argv[k],"-o")) { if (++klength; j++){ (void)e.elecvars.states[q].Y.col[i]->data.d[j].x; (void)e.elecvars.states[q].Y.col[i]->data.d[j].y; } RealSpaceScalarFieldColumn &n = e.elecvars.n; RealSpaceScalarFieldColumn &d = e.elecvars.d; CoeffSpaceScalarFieldColumn m(d), mmm(d); RealSpaceScalarFieldColumn mm(n); real mag = 0.0; /************************************** * LJ1 = 0 **************************************/ dft_log("=============================\n"); dft_log("LJ1 = 0 Test\n"); dft_log("=============================\n"); n.setmodones(); dft_log("Calling J(n)\n"); dft_log_flush(); apply_J(n,m); dft_log("Calling L(m)\n"); dft_log_flush(); apply_L(m,mmm); compare(m,mmm, "n", "LJn"); /************************************** * IJ = 1 **************************************/ dft_log("=============================\n"); dft_log("IJ = 1 Test\n"); dft_log("=============================\n"); n.randomize(); dft_log("Calling J(n)\n"); dft_log_flush(); apply_J(n,m); dft_log("Calling I(m)\n"); dft_log_flush(); apply_I(m,mm); compare(n, mm, "n", "IJn"); /************************************** * JI = 1 **************************************/ dft_log("=============================\n"); dft_log("JI = 1 Test\n"); dft_log("=============================\n"); d.randomize(); dft_log("Calling I(d)\n"); dft_log_flush(); apply_I(d,mm); dft_log("Calling J(mm)\n"); dft_log_flush(); apply_J(mm,mmm); compare(d, mmm, "d", "JId"); /************************************** * Idag = I^ **************************************/ dft_log("=============================\n"); dft_log("Idag = I^ Test\n"); dft_log("=============================\n"); d.randomize(); dft_log("d: %s %s\n", d.getrepresentation(), d.getembedding()); m.randomize(); dft_log("m: %s %s\n", m.getrepresentation(), m.getembedding()); dft_log("Calling I(m)\n"); dft_log_flush(); apply_I(m,m);// must be in real space dft_log("Calling I(d)\n"); dft_log_flush(); apply_I(d,mm); dft_log("Calling Idag(m)\n"); dft_log_flush(); apply_Idag(m,mmm); { complex diff=(m^mm)/(mmm^d)-1; dft_log("Idag is dag of I to %le + %le i\n\n",diff.x, diff.y ); } /************************************** * Jdag = J^ **************************************/ dft_log("=============================\n"); dft_log("Jdag = J^ Test\n"); dft_log("=============================\n"); d.randomize(); dft_log("d: %s %s\n", d.getrepresentation(), d.getembedding()); m.randomize(); dft_log("m: %s %s\n", m.getrepresentation(), m.getembedding()); dft_log("Calling J(m)\n"); dft_log_flush(); apply_J(m,mmm);// must be in real space dft_log("Calling Jdag(d)\n"); dft_log_flush(); apply_Jdag(d,mm); { complex diff=(m^mm)/(mmm^d)-1; dft_log("Jdag is dag of J to %le + %le i\n\n",diff.x, diff.y ); } /************************************** * J1^OJ1 = Vol **************************************/ dft_log("=============================\n"); dft_log("J1^OJ1 = Vol Test\n"); dft_log("=============================\n"); for(i = 0; i < n.length; i++){ n.data.d[i].x = 1; n.data.d[i].y = 0; } dft_log("Calling J(n)\n"); dft_log_flush(); apply_J(n,m); dft_log("Calling O(m)\n"); dft_log_flush(); apply_O(m,mmm); compare(m,mmm, "J1", "OJ1"); /************************************** * J1^OJ1 = Vol on ColumnBundles **************************************/ dft_log("==================================\n"); dft_log("(J1)^OJ1 = Vol on ColumnBundle Test\n"); dft_log("==================================\n"); for(i = 0; i < n.length; i++){ n.data.d[i].x = 1; n.data.d[i].y = 0; } mag = 0.0; for(i = 0; i < n.length; i++) mag += abs(n.data.d[i]); dft_log("\n mag[ n ] = %lf\n",mag); ColumnBundle &C = e.elecvars.states[0].C; ColumnBundle &Y = e.elecvars.states[0].Y; for(i = 0; i < C.my_ncols; i++){ dft_log("Calling J(n)\n"); apply_J(n, *(C.col[i])); } dft_log("Calling O(Y)\n"); dft_log_flush(); O(C,Y); dft_log("Calling C^Y\n"); dft_log_flush(); Matrix COC = C^Y; dft_log("C^OC : \n"); COC.print(); dft_log("\n"); /************************************** * Orthonorm test (on ColumnBundles) **************************************/ dft_log("==================================\n"); dft_log("Orthonorm test (on ColumnBundles)\n"); dft_log("==================================\n"); C.randomize(); COC=C^O(C); dft_log("\nOverlaps before:\n"); COC.print(); COC.hermetian = TRUE; Matrix Umh=Uminusonehalf(COC,e.elecvars.states[0].W,e.elecvars.states[0].mu); Y=C*Umh; dft_log("\nOverlaps after:\n"); (Y^O(Y)).print(); dft_log("\n"); /************************************** * Test on B*M algebra: (B*B)**2=B*B^ **************************************/ dft_log("==================================\n"); dft_log("B*M algebra test (B*B^)**2=B*B^ [idenpotency]\n"); dft_log("==================================\n"); //get idenpotent projector w/o O: COC = C^C; COC.hermetian = TRUE; Y = C*Uminusonehalf(COC,e.elecvars.states[0].W,e.elecvars.states[0].mu); dft_log("Projector idenpotency check:\n"); (Y^Y).print(); int col_num_diff = 3; // whatever to make it different ColumnBundle B(Y.col_length, Y.tot_ncols-col_num_diff, Y.col[0]->basis); // just put junk there, we're testing B*M B.randomize(); ColumnBundle B1(B); B1 = Y*(Y^B); // project again B = Y*(Y^B1); dft_log("\n(PB)^(PB):\n"); (B^B).print(); //now compare B-=B1; dft_log("\nB^(PP-P)^(PP-P)B:\n"); (B^B).printe(); dft_log("\n"); } void Etest(Everything &e) { // calc_UVCn(e.elecinfo, e.elecvars, e.lattice, e.symm); // solve_poisson(e.elecvars.n,e.elecvars.d); calc_UVCn_d(e); //e.elecvars.n.read("n_new"); //e.elecvars.n_up.read("n_up_new"); //e.elecvars.n_dn.read("n_dn_new"); calc_all_energies(e); //e.elecvars.n_up.write("n_up"); //e.elecvars.n_dn.write("n_dn"); e.energies.print(System::global_log); }