usage += " see --help for all options\n" parser = OptionParser(usage) parser.add_option("--transition_charges", dest="transition_charges", type=str, default="", help="Path to .chromo file with excitation energies, transition charges and magnetic transition dipoles for building a Frenckel exciton model. [default: %default]") parser.add_option("--spectrum_file", dest="spectrum_file", type=str, default="exciton_spectrum.dat", help="Save excitonic absorption and circular dichroism spectra to this file [default: %default]") parser.add_option("--state", dest="state", type=int, default=0, help="Excitonic state for which the gradient should be calculated (0 for ground state). [default: %default]") parser.add_option("--plot_spectra", dest="plot_spectra", type=str, default="", help="Choose units ('nm', 'Hartree', 'cm-1' or 'eV') for plotting absorption and circular dichroism spectra. [default: %default]") (opts,args) = parser.parse_args() if len(args) < 1: print usage exit(-1) ff_file = args[0] #"h2.ff" #"ethene.ff" #"pyrene_crystal_expanded.ff" # # read force field definition atomlist, atomtypes, partial_charges, lattice_vectors = read_force_field(ff_file) # read transition charge for exciton model (if available) if opts.transition_charges != "": chromophores = list(read_transition_charges(opts.transition_charges)) else: chromophores = [] pff = PeriodicForceField(atomlist, atomtypes, partial_charges, lattice_vectors, chromophores) coords = XYZ.atomlist2vector(atomlist) # evaluate force field once energy, grad = pff.getEnergyAndGradient(coords, state=opts.state) print "Total energy: %s" % energy print "|gradient| : %s" % la.norm(grad) # compute exciton spectrum en, T, M = pff.getTransitionDipoles(verbose=1) save_exciton_spectrum(opts.spectrum_file, en, T, M)
def __init__(self, atomlist_full, inner_indeces, embedding="electrostatic", pff_file=None, verbose=0): """ Parameters: =========== atomlist_full: list of tuples (Zi,[xi,yi,zi]) for all atoms (QM + MM) inner_indeces: list of the indeces which belong to the QM atoms """ assert embedding in ["mechanical", "electrostatic"] if "-" in inner_indeces: # index list contains ranges such as "9-14" inner_indeces = parseAtomTags(inner_indeces) else: inner_indeces = list(eval(inner_indeces)) inner_indeces = list(set(inner_indeces)) # remove duplicate indeces inner_indeces.sort() if verbose > 0: print("Indeces of QM atoms:") print(inner_indeces) print("number of QM atoms: %d" % len(inner_indeces)) # counting in the partitioning file starts at 1 inner_indeces = np.asarray(inner_indeces, dtype=int)-1 Nat = len(atomlist_full) all_indeces = set(range(0, Nat)) outer_indeces = list(all_indeces - set(inner_indeces)) outer_indeces.sort() self.inner_indeces = inner_indeces self.outer_indeces = outer_indeces # sort atoms into inner and outer region self.atomlist_full = atomlist_full self.atomlist_inner = [self.atomlist_full[i] for i in self.inner_indeces] self.atomlist_outer = [self.atomlist_full[i] for i in self.outer_indeces] if (pff_file == None): # # prepare the drivers for the UFF calculations # E^MM(I+O) self.FF_full = Gaussian.UFF_handler(self.atomlist_full, embedding=embedding, verbose=verbose, unique_tmp=True) # E^MM(I) self.FF_inner = Gaussian.UFF_handler(self.atomlist_inner, embedding=embedding, verbose=verbose, unique_tmp=True) else: # load definitions for periodic force field if verbose > 0: print("periodic MM calculations with DREIDING") atomlist_full_ff, atomtypes_full, charges_full, lattice_vectors = read_force_field(pff_file) atomtypes_inner = [atomtypes_full[i] for i in self.inner_indeces] charges_inner = [charges_full[i] for i in self.inner_indeces] if (len(atomlist_full_ff) != Nat): raise ValueError("Wrong number of atoms in '%s'. Expected %d atoms but got %d !" \ % (pff_file, Nat, len(atomlist))) # prepare drivers for DREIDING calculations # E^MM(I+O) self.FF_full = PeriodicForceField(self.atomlist_full, atomtypes_full, charges_full, lattice_vectors, [], verbose=verbose) # E^MM(I) self.FF_inner = PeriodicForceField(self.atomlist_inner, atomtypes_inner, charges_inner, lattice_vectors, [], verbose=verbose) self.charge = 0