| 1 | /*
 | 
|---|
| 2 | **
 | 
|---|
| 3 | ** PSI Input Class
 | 
|---|
| 4 | **
 | 
|---|
| 5 | ** This helper class will set up input decks for the PSI suite of
 | 
|---|
| 6 | ** ab initio quantum chemistry programs.
 | 
|---|
| 7 | **
 | 
|---|
| 8 | ** David Sherrill & Justin Fermann
 | 
|---|
| 9 | ** Center for Computational Quantum Chemistry, University of Georgia
 | 
|---|
| 10 | **
 | 
|---|
| 11 | */
 | 
|---|
| 12 | 
 | 
|---|
| 13 | #ifdef __GNUG__
 | 
|---|
| 14 | #pragma implementation
 | 
|---|
| 15 | #endif
 | 
|---|
| 16 | 
 | 
|---|
| 17 | #include <iostream>
 | 
|---|
| 18 | #include <math.h>
 | 
|---|
| 19 | 
 | 
|---|
| 20 | #include <util/misc/string.h>
 | 
|---|
| 21 | #include <util/misc/formio.h>
 | 
|---|
| 22 | #include <math/symmetry/corrtab.h>
 | 
|---|
| 23 | #include <chemistry/qc/wfn/obwfn.h>
 | 
|---|
| 24 | #include <chemistry/molecule/molecule.h>
 | 
|---|
| 25 | #include <chemistry/molecule/atominfo.h>
 | 
|---|
| 26 | #include <chemistry/qc/basis/basis.h>
 | 
|---|
| 27 | #include <chemistry/qc/basis/petite.h>
 | 
|---|
| 28 | #include <chemistry/qc/psi/psiexenv.h>
 | 
|---|
| 29 | #include <chemistry/qc/psi/psiinput.h>
 | 
|---|
| 30 | 
 | 
|---|
| 31 | using namespace std;
 | 
|---|
| 32 | 
 | 
|---|
| 33 | namespace sc {
 | 
|---|
| 34 | 
 | 
|---|
| 35 | PsiInput::PsiInput(const string& name) : file_()
 | 
|---|
| 36 | {
 | 
|---|
| 37 |   filename_ = string(name);
 | 
|---|
| 38 |   indentation_ = 0;
 | 
|---|
| 39 | }
 | 
|---|
| 40 | 
 | 
|---|
| 41 | PsiInput::~PsiInput()
 | 
|---|
| 42 | {
 | 
|---|
| 43 | }
 | 
|---|
| 44 | 
 | 
|---|
| 45 | void
 | 
|---|
| 46 | PsiInput::open()
 | 
|---|
| 47 | {
 | 
|---|
| 48 |   file_.open(filename_.c_str(),ios::out);
 | 
|---|
| 49 |   indentation_ = 0;
 | 
|---|
| 50 | }
 | 
|---|
| 51 | 
 | 
|---|
| 52 | void
 | 
|---|
| 53 | PsiInput::close()
 | 
|---|
| 54 | {
 | 
|---|
| 55 |   file_.close();
 | 
|---|
| 56 |   indentation_ = 0;
 | 
|---|
| 57 | }
 | 
|---|
| 58 | 
 | 
|---|
| 59 | 
 | 
|---|
| 60 | void 
 | 
|---|
| 61 | PsiInput::write_indent()
 | 
|---|
| 62 | {
 | 
|---|
| 63 |   for (int i=0; i<indentation_; i++)
 | 
|---|
| 64 |     file_ << " ";
 | 
|---|
| 65 | }
 | 
|---|
| 66 | 
 | 
|---|
| 67 | void
 | 
|---|
| 68 | PsiInput::incindent(int i)
 | 
|---|
| 69 | {
 | 
|---|
| 70 |   if (i > 0)
 | 
|---|
| 71 |     indentation_ += i;
 | 
|---|
| 72 | }
 | 
|---|
| 73 | 
 | 
|---|
| 74 | void
 | 
|---|
| 75 | PsiInput::decindent(int i)
 | 
|---|
| 76 | {
 | 
|---|
| 77 |   if (i > 0)
 | 
|---|
| 78 |     indentation_ -= i;
 | 
|---|
| 79 | }
 | 
|---|
| 80 | 
 | 
|---|
| 81 | void
 | 
|---|
| 82 | PsiInput::begin_section(const char * s)
 | 
|---|
| 83 | {
 | 
|---|
| 84 |    write_indent();
 | 
|---|
| 85 |    file_ << s << ":(" << endl;
 | 
|---|
| 86 |    incindent(2);
 | 
|---|
| 87 | }
 | 
|---|
| 88 | 
 | 
|---|
| 89 | void
 | 
|---|
| 90 | PsiInput::end_section(void)
 | 
|---|
| 91 | {
 | 
|---|
| 92 |    decindent(2);
 | 
|---|
| 93 |    write_indent();
 | 
|---|
| 94 |    file_ << ")" << endl;
 | 
|---|
| 95 |    write_string("\n");
 | 
|---|
| 96 | }
 | 
|---|
| 97 | 
 | 
|---|
| 98 | void
 | 
|---|
| 99 | PsiInput::write_keyword(const char *keyword, const char *value)
 | 
|---|
| 100 | {
 | 
|---|
| 101 |    write_indent();
 | 
|---|
| 102 |    file_ << scprintf("%s = %s",keyword,value) << endl;
 | 
|---|
| 103 | }
 | 
|---|
| 104 | 
 | 
|---|
| 105 | void
 | 
|---|
| 106 | PsiInput::write_keyword(const char *keyword, int value)
 | 
|---|
| 107 | {
 | 
|---|
| 108 |    write_indent();
 | 
|---|
| 109 |    file_ << scprintf("%s = %d",keyword,value) << endl;
 | 
|---|
| 110 | }
 | 
|---|
| 111 | 
 | 
|---|
| 112 | void
 | 
|---|
| 113 | PsiInput::write_keyword(const char *keyword, double value)
 | 
|---|
| 114 | {
 | 
|---|
| 115 |    write_indent();
 | 
|---|
| 116 |    file_ << scprintf("%s = %20.15lf",keyword,value) << endl;
 | 
|---|
| 117 | }
 | 
|---|
| 118 | 
 | 
|---|
| 119 | void
 | 
|---|
| 120 | PsiInput::write_keyword_array(const char *keyword, int num, int *values)
 | 
|---|
| 121 | {
 | 
|---|
| 122 |   write_indent();
 | 
|---|
| 123 |   file_ << scprintf("%s = (", keyword);
 | 
|---|
| 124 |   for (int i=0; i<num; i++) {
 | 
|---|
| 125 |     file_ << scprintf(" %d", values[i]);
 | 
|---|
| 126 |   }
 | 
|---|
| 127 |   file_ << ")" << endl;
 | 
|---|
| 128 | }
 | 
|---|
| 129 | 
 | 
|---|
| 130 | void
 | 
|---|
| 131 | PsiInput::write_keyword_array(const char *keyword, int num, double *values)
 | 
|---|
| 132 | {
 | 
|---|
| 133 |    write_indent();
 | 
|---|
| 134 |    file_ << scprintf("%s = (", keyword);
 | 
|---|
| 135 |   for (int i=0; i<num; i++) {
 | 
|---|
| 136 |     file_ << scprintf(" %20.15lf", values[i]);
 | 
|---|
| 137 |   }
 | 
|---|
| 138 |   file_ << ")" << endl;
 | 
|---|
| 139 | }
 | 
|---|
| 140 | 
 | 
|---|
| 141 | void 
 | 
|---|
| 142 | PsiInput::write_string(const char *s)
 | 
|---|
| 143 | {
 | 
|---|
| 144 |    write_indent();
 | 
|---|
| 145 |    file_ << s;
 | 
|---|
| 146 | }
 | 
|---|
| 147 | 
 | 
|---|
| 148 | void
 | 
|---|
| 149 | PsiInput::write_key_wq(const char *keyword, const char *value)
 | 
|---|
| 150 | {
 | 
|---|
| 151 |    write_indent();
 | 
|---|
| 152 |    file_ << scprintf("%s = \"%s\"", keyword, value) << endl;
 | 
|---|
| 153 | }
 | 
|---|
| 154 | 
 | 
|---|
| 155 | 
 | 
|---|
| 156 | void
 | 
|---|
| 157 | PsiInput::write_geom(const Ref<Molecule>& mol)
 | 
|---|
| 158 | {
 | 
|---|
| 159 |   // If the highest symmetry group is not the actual group - use subgroup keyword
 | 
|---|
| 160 |   if (!mol->point_group()->equiv(mol->highest_point_group())) {
 | 
|---|
| 161 |     write_keyword("subgroup",mol->point_group()->symbol());
 | 
|---|
| 162 |   }
 | 
|---|
| 163 | 
 | 
|---|
| 164 |   write_keyword("units","bohr");
 | 
|---|
| 165 |   write_string("geometry = (\n");
 | 
|---|
| 166 |   for (int i=0; i < mol->natom(); i++) {
 | 
|---|
| 167 |     write_string("  (");
 | 
|---|
| 168 |     char *s;
 | 
|---|
| 169 |     file_ << mol->atom_symbol(i) <<
 | 
|---|
| 170 |         scprintf(" %14.12lf %14.12lf %14.12lf",mol->r(i,0),mol->r(i,1),mol->r(i,2))
 | 
|---|
| 171 |           << ")" << endl;
 | 
|---|
| 172 |   } 
 | 
|---|
| 173 |   write_string(")\n");
 | 
|---|
| 174 | }
 | 
|---|
| 175 | 
 | 
|---|
| 176 | 
 | 
|---|
| 177 | void
 | 
|---|
| 178 | PsiInput::write_basis(const Ref<GaussianBasisSet>& basis)
 | 
|---|
| 179 | {
 | 
|---|
| 180 |   Ref<Molecule> molecule = basis->molecule();
 | 
|---|
| 181 |   int natom = molecule->natom();
 | 
|---|
| 182 | 
 | 
|---|
| 183 |   write_string("basis = (\n");
 | 
|---|
| 184 |   incindent(2);
 | 
|---|
| 185 |   for(int atom=0; atom<natom; atom++) {
 | 
|---|
| 186 |     int uatom = molecule->atom_to_unique(atom);
 | 
|---|
| 187 | 
 | 
|---|
| 188 |     // Replace all spaces with underscores in order for Psi libipv1 to parse properly
 | 
|---|
| 189 |     char *name = strdup(basis->name());
 | 
|---|
| 190 |     int len = strlen(name);
 | 
|---|
| 191 |     for (int i=0; i<len; i++)
 | 
|---|
| 192 |       if (name[i] == ' ')
 | 
|---|
| 193 |         name[i] = '_';
 | 
|---|
| 194 | 
 | 
|---|
| 195 |     char *basisname = new char[strlen(basis->name()) + ((int)ceil(log10((long double)uatom+2))) + 5];
 | 
|---|
| 196 |     sprintf(basisname,"\"%s%d\" \n",name,uatom);
 | 
|---|
| 197 |     write_string(basisname);
 | 
|---|
| 198 |     delete[] name;
 | 
|---|
| 199 |   }
 | 
|---|
| 200 |   decindent(2);
 | 
|---|
| 201 |   write_string(")\n");
 | 
|---|
| 202 | }
 | 
|---|
| 203 | 
 | 
|---|
| 204 | void
 | 
|---|
| 205 | PsiInput::write_basis_sets(const Ref<GaussianBasisSet>& basis)
 | 
|---|
| 206 | {
 | 
|---|
| 207 |   begin_section("basis");
 | 
|---|
| 208 |   Ref<Molecule> molecule = basis->molecule();
 | 
|---|
| 209 |   Ref<AtomInfo> atominfo = basis->molecule()->atominfo();
 | 
|---|
| 210 |   int nunique = molecule->nunique();
 | 
|---|
| 211 | 
 | 
|---|
| 212 |   for(int uatom=0; uatom<nunique; uatom++) {
 | 
|---|
| 213 |     int atom = molecule->unique(uatom);
 | 
|---|
| 214 |     std::string atomname = atominfo->name(molecule->Z(atom));
 | 
|---|
| 215 | 
 | 
|---|
| 216 |     // Replace all spaces with underscores in order for Psi libipv1 to parse properly
 | 
|---|
| 217 |     char *name = strdup(basis->name());
 | 
|---|
| 218 |     int len = strlen(name);
 | 
|---|
| 219 |     for (int i=0; i<len; i++)
 | 
|---|
| 220 |       if (name[i] == ' ')
 | 
|---|
| 221 |         name[i] = '_';
 | 
|---|
| 222 | 
 | 
|---|
| 223 |     char *psibasisname = new char[atomname.size() + strlen(basis->name()) + ((int)ceil(log10((long double)uatom+2))) + 9];
 | 
|---|
| 224 |     sprintf(psibasisname,"%s:\"%s%d\" = (\n",atomname.c_str(),name,uatom);
 | 
|---|
| 225 |     write_string(psibasisname);
 | 
|---|
| 226 |     delete[] name;
 | 
|---|
| 227 |     incindent(2);
 | 
|---|
| 228 |     int nshell = basis->nshell_on_center(atom);
 | 
|---|
| 229 |     for(int sh=0;sh<nshell;sh++) {
 | 
|---|
| 230 |       int shell = basis->shell_on_center(atom,sh);
 | 
|---|
| 231 |       GaussianShell& Shell = basis->shell(shell);
 | 
|---|
| 232 |       int ncon = Shell.ncontraction();
 | 
|---|
| 233 |       int nprim = Shell.nprimitive();
 | 
|---|
| 234 |       for(int con=0; con<ncon; con++) {
 | 
|---|
| 235 |         char amstring[4];
 | 
|---|
| 236 |         sprintf(amstring,"(%c\n",Shell.amchar(con));
 | 
|---|
| 237 |         write_string(amstring);
 | 
|---|
| 238 |         incindent(2);
 | 
|---|
| 239 |         for(int prim=0; prim<nprim; prim++) {
 | 
|---|
| 240 |           char primstring[50];
 | 
|---|
| 241 |           sprintf(primstring,"(%20.10lf    %20.10lf)\n",
 | 
|---|
| 242 |                   Shell.exponent(prim),
 | 
|---|
| 243 |                   Shell.coefficient_norm(con,prim));
 | 
|---|
| 244 |           write_string(primstring);
 | 
|---|
| 245 |         }
 | 
|---|
| 246 |         decindent(2);
 | 
|---|
| 247 |         write_string(")\n");
 | 
|---|
| 248 |       }
 | 
|---|
| 249 |     }
 | 
|---|
| 250 |     decindent(2);
 | 
|---|
| 251 |     write_string(")\n");
 | 
|---|
| 252 |     delete[] psibasisname;
 | 
|---|
| 253 |   }
 | 
|---|
| 254 |   end_section();
 | 
|---|
| 255 | }
 | 
|---|
| 256 | 
 | 
|---|
| 257 | void
 | 
|---|
| 258 | PsiInput::write_defaults(const Ref<PsiExEnv>& exenv, const char *dertype)
 | 
|---|
| 259 | {
 | 
|---|
| 260 |   begin_section("psi");
 | 
|---|
| 261 |   
 | 
|---|
| 262 |   write_key_wq("label"," ");
 | 
|---|
| 263 |   write_keyword("dertype",dertype);
 | 
|---|
| 264 |   begin_section("files");
 | 
|---|
| 265 |   begin_section("default");
 | 
|---|
| 266 |   write_key_wq("name",(exenv->get_fileprefix()).c_str());
 | 
|---|
| 267 |   int nscratch = exenv->get_nscratch();
 | 
|---|
| 268 |   write_keyword("nvolume",nscratch);
 | 
|---|
| 269 |   char *scrname; scrname = new char[10];
 | 
|---|
| 270 |   for(int i=0; i<nscratch; i++) {
 | 
|---|
| 271 |     sprintf(scrname,"volume%d",i+1);
 | 
|---|
| 272 |     write_key_wq(scrname,(exenv->get_scratch(i)).c_str());
 | 
|---|
| 273 |   }
 | 
|---|
| 274 |   delete[] scrname;
 | 
|---|
| 275 |   end_section();
 | 
|---|
| 276 |   write_string("file32: ( nvolume = 1 volume1 = \"./\" )\n");
 | 
|---|
| 277 |   end_section();
 | 
|---|
| 278 | 
 | 
|---|
| 279 |   end_section();
 | 
|---|
| 280 | }
 | 
|---|
| 281 | 
 | 
|---|
| 282 | 
 | 
|---|
| 283 | void
 | 
|---|
| 284 | PsiInput::print(ostream& o)
 | 
|---|
| 285 | {
 | 
|---|
| 286 | }
 | 
|---|
| 287 | 
 | 
|---|
| 288 | }
 | 
|---|