├── LICENSE.txt ├── README.org ├── examples ├── QST2.com └── optimize.com └── xtb-gaussian /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Cyrille Lavigne 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | * An xtb wrapper for Gaussian 2 | This is a wrapper that allows xtb to be used as part of Gaussian. This is 3 | useful in particular for TS optimizations that xtb doesn't otherwise do, and 4 | that Gaussian does very well. 5 | 6 | As xtb already has most of the functionality built-in, we mostly just leverage 7 | that. The only improvement really is the use of some perl scripting to 8 | transform xtb Hessians to Gaussian Hessians, which xtb doesn't do on it's own. 9 | The short script is in ~xtb-gaussian~. 10 | 11 | ** Usage 12 | The files ~examples/optimize.com~ and ~example/QST2.com~ provide examples of usage 13 | (the optimization of a water molecule and finding an SN2 transition state and 14 | reaction path using quasi-Newton synchronous transit). In short, the Gaussian 15 | input file should have a method line like this one, 16 | #+BEGIN_SRC text 17 | %chk=ts 18 | # external="xtb-gaussian -P 12 --etemp 300.0" 19 | opt=(calcfc,ts,noeigentest,nodownhill,nomicro) 20 | #+END_SRC 21 | Here, we set the number of threads for xtb to 12 (~-P 12~ above) and perform a 22 | transition state search using an initial xtb Hessian and xtb gradient 23 | calculations. Additional arguments to xtb can be passed in the external 24 | variable (like ~--etemp 300.0~ above). Passing ~--log-all~ as the first argument 25 | to ~xtb-gaussian~ will mix in the (often very long) xtb output with the Gaussian 26 | output, which is not done by default for performance and easier parsing of 27 | Gaussian log files. 28 | 29 | Note that the molecular charge included in the Gaussian molecule deck is 30 | automatically used the wrapper script. *However, that is not true of the 31 | multiplicity!* The script will warn of non-singlet multiplicity, which you can 32 | technically treat by passing the appropriate ~--uhf~ argument to xtb in the 33 | external string (caveat emptor). 34 | 35 | ** Installation 36 | Installation consists solely of putting ~xtb-gaussian~ and ~xtb~ both on $PATH so 37 | that they are visible to Gaussian. The only dependency is Perl. This code was 38 | tested against ~xtb 6.2.3~ and ~xtb 6.3.1rc1~ binaries on linux. 39 | 40 | ** Performance 41 | There are some things to keep in mind to ensure the best possible performance, 42 | mostly because of Gaussian is a bit old-school. 43 | 44 | Firstly, passing %CPU to gaussian makes xtb use 1 thread. *So don't do it!* 45 | Furthermore, %NProcShared= will make Gaussian wait busily for xtb using a full 46 | half of the NProcShared cores while xtb is running, but use all the cores for 47 | it's own routines (like Hessian diagonalization). It is best to give only 1 or 48 | 2 processes to Gaussian and the rest to xtb using ~-P~ as above if Hessians are 49 | often computed (with xtb parallelization) or the system is large. Otherwise, 50 | allocating some threads to Gaussian can make the code faster. 51 | 52 | Secondly, performance is very IO centric as Gaussian and xtb keep writing and 53 | reading files over and over again. The wrapper respects the Gaussian scratch 54 | directory. Running with ~$GAUSS_SCRDIR~ pointing at a fast filesystem (such as 55 | ~/dev/shm/~ on linux) makes a huge difference. 56 | 57 | * Contributors 58 | I wrote this perl version based on a Python script developed by postdoctoral 59 | fellows [[https://github.com/kjelljorner][Kjell Jorner]] (at AstraZeneca, UK) and [[https://github.com/gabegomes][Gabriel dos Passos Gomes]] 60 | (University of Toronto, Canada). 61 | 62 | -------------------------------------------------------------------------------- /examples/QST2.com: -------------------------------------------------------------------------------- 1 | %chk=QST2.chk 2 | # external="xtb-gaussian -P 4 --gbsa methanol" 3 | opt=(qst2,nomicro,bimolecular,recalcfc=5) 4 | 5 | Reactants 6 | 7 | -1 1 8 | C 0.17018 0.21174 0.13324 9 | H 5.06088 2.98871 -0.14203 10 | C 3.98680 3.17835 0.06099 11 | H 3.69821 4.16131 -0.36476 12 | O 3.21837 2.17405 -0.52559 13 | H 3.81307 3.18453 1.15664 14 | H 1.07380 -0.42261 0.24181 15 | Br -1.40261 -0.91134 0.07494 16 | H 0.24082 0.79824 -0.80576 17 | H 0.09847 0.90406 0.99711 18 | 19 | Product 20 | 21 | -1 1 22 | C 1.52906 1.10575 0.08840 23 | H 4.27492 2.83367 -0.19811 24 | C 3.19935 2.67900 0.02532 25 | H 2.62596 3.33749 -0.66470 26 | O 2.89366 1.32040 -0.18881 27 | H 3.04341 2.96691 1.08892 28 | H 1.30406 0.03298 -0.08161 29 | Br -1.80094 -1.13121 0.05621 30 | H 0.87835 1.68803 -0.60155 31 | H 1.29209 1.32264 1.15391 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /examples/optimize.com: -------------------------------------------------------------------------------- 1 | # external="xtb-gaussian " 2 | opt(calcall,nomicro) 3 | 4 | Simple H2 test with frequencies 5 | 6 | 0 1 7 | H 0.0000 0.0000 0.0000 8 | H 1.0000 0.0000 0.0000 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /xtb-gaussian: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # 3 | # An interface between Gaussian and xtb that takes care of Hessian 4 | # calculations and command line arguments. 5 | use strict; 6 | use warnings; 7 | use File::Basename; 8 | 9 | # if the first argument is --log-all, then the full xtb output will be 10 | # added to the Gaussian log file 11 | my $DEBUG = 0; 12 | if ($ARGV[0] eq '--log-all') { 13 | $DEBUG = 1; 14 | shift; 15 | } 16 | 17 | # Final 6 arguments are those passed by Gaussian. 18 | my @arg_gauss = splice @ARGV, @ARGV - 6; 19 | 20 | # Remaining arguments are for xtb. 21 | my $arg_xtb = join ' ', @ARGV; 22 | 23 | # First, move to the directory containing the .EIn file (the Gaussian scratch 24 | # directory.) This is so that xtb can produce a .EOut file in the same 25 | # directory. 26 | (my $Ein, my $Ein_dir) = fileparse($arg_gauss[1]); 27 | (my $Eout, my $Eout_dir) = fileparse($arg_gauss[2]); 28 | (my $Elog, my $Elog_dir) = fileparse($arg_gauss[3]); 29 | 30 | chdir $Ein_dir; 31 | # Open input file and load parameters. 32 | open (INF, "<$Ein") || die "failed to open input"; 33 | my ($natoms,$deriv,$icharg,$multip) = split(" ",scalar()); 34 | close(INF); 35 | 36 | # Setup redirection of xtb output. Here we throw it out instead, unless $DEBUG 37 | # is on. We do this because otherwise the Gaussian output gets way too 38 | # cluttered. 39 | my $msg_output = $DEBUG ? "> $Elog 2>&1" : ">/dev/null 2>$Elog"; 40 | 41 | # Setup xtb according to run type 42 | my $runtype = $deriv<2 ? "--grad" : "--hess"; 43 | my $xtb_run = "xtb ./$Ein $arg_xtb $runtype --charge $icharg $msg_output"; 44 | system($xtb_run); 45 | 46 | open(LOGF, ">>$Elog") || die "couldn't open log file"; 47 | print LOGF "\n------- xtb command was ---------\n"; 48 | print LOGF "?> $xtb_run\n"; 49 | print LOGF "---------------------------------\n"; 50 | 51 | # Currently, non-singlet spins are not supported explicitly by the interface. 52 | unless ($multip == 1) { 53 | print LOGF "WARNING: Gaussian multiplicity S=$multip is not singlet.\n"; 54 | print LOGF " This is not not explicitly supported. Results are likely wrong without\n"; 55 | print LOGF " an appropriate --uhf argument xtb command line!\n";} 56 | 57 | 58 | if ($deriv < 2) { 59 | # This is the standard and identical to the xtb example from the repo. If 60 | # we don't need a hessian, just run xtb with the correct Gaussian 61 | # input/output file formats and --grad. 62 | 63 | } else { 64 | # Appending to xtb gaussian formatted output 65 | open(OUTP, ">>$Eout") || die "failed to open output"; 66 | 67 | # First, we fake the polarizability and the dipole derivatives, which the 68 | # Gaussian Manual says should be of this form, 69 | 70 | # Polar(I), I=1,6 3D20.12 71 | # DDip(I), I=1,9*NAtoms 3D20.12 72 | foreach (1 .. 3*$natoms + 2) { 73 | printf OUTP "%20.12e%20.12e%20.12e\n", 0.0, 0.0, 0.0; 74 | } 75 | 76 | # Now we have to convert the hessian from the turbomole format that xtb 77 | # outputs to the Gaussian format that we want. This is fairly trivial, 78 | open(HESSF, "; 82 | 83 | # Now we are iterating over Hessian matrix elements. We will 84 | # append those to the output file in the correct format, given in 85 | # the Gaussian manual as 86 | 87 | # FFX(I), I=1,(3*NAtoms*(3*NAtoms+1))/2 3D20.12 88 | 89 | # That is, the lower triangular part of the Hessian only. For this we need 90 | # to remember which indices we have done. 91 | my $icol=0; my $irow=0; 92 | # Finally we only print three numbers per line, 93 | my $counter3=0; 94 | 95 | while () { 96 | # split the line on whitespaces 97 | foreach (split){ 98 | 99 | 100 | # print only if the column index < row index (lower triangle) 101 | if ($icol <= $irow) { 102 | # If printed more than three in a row, start new line 103 | if ($counter3 == 3) {$counter3=0; print OUTP "\n";} 104 | printf OUTP "%20.12e", $_; 105 | # print OUTP "$icol x $irow ($_) "; 106 | $counter3++; 107 | } 108 | 109 | # Increment column index 110 | $icol++; 111 | if ($icol == (3*$natoms)) { # done this row 112 | $irow++; $icol = 0; 113 | } 114 | } 115 | } 116 | 117 | # Close and flush 118 | close(OUTP); 119 | } 120 | 121 | # Close log and flush 122 | print LOGF " Control returned to Gaussian.\n"; 123 | print LOGF "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; 124 | close(LOGF); 125 | --------------------------------------------------------------------------------