def vibmodes(atoms, startdir=None, mask=None, workhere=False, save=None, give_output=0, pmap=pmap3, **kwargs): """ Wrapper around vibmode, which used the atoms objects The hessian is calculated by derivatef qfunc.fwrapper is used as a wrapper to calulate the gradients """ from pts.memoize import Memoize, DirStore coord = atoms.get_positions() if mask == None: mask = constraints2mask(atoms) if mask == None: # (if still None) fun = Cartesian() else: fun = Masked(Cartesian(), mask, coord.flatten()) xcenter = fun.pinv(coord) myfunc = QFunc(atoms, atoms.get_calculator()) myfunc = Memoize(myfunc, DirStore("cache.d")) myfunc = compose(myfunc, fun) pmapc = pwrapper(pmap) func = fwrapper(myfunc, startdir=startdir, mask=mask, workhere=workhere) # the derivatives are needed hessian = derivatef(func, xcenter, pmap=pmapc, **kwargs) # save is assumend to be a filename, so far only the hessian is saved: if save is not None: savetxt(save, hessian) mass = mass_matrix(atoms.get_masses(), mask) freqs, modes = vibmod(mass, hessian) # the output will be printed on demand, with modes if wanted # the output for the freqs can easily be recreated later on, but # for the mode vectors the mass (not included in the direct output_ # is needed if VERBOSE or give_output == 2: output(freqs, modes, mass, mask) elif give_output == 1: output(freqs) return freqs, modes
def vibmodes(atoms, startdir=None, mask=None, workhere=False, save=None, give_output = 0, pmap = pmap3, **kwargs): """ Wrapper around vibmode, which used the atoms objects The hessian is calculated by derivatef qfunc.fwrapper is used as a wrapper to calulate the gradients """ from pts.memoize import Memoize, DirStore coord = atoms.get_positions() if mask == None: mask = constraints2mask(atoms) if mask == None: # (if still None) fun = Cartesian() else: fun = Masked(Cartesian(), mask, coord.flatten()) xcenter = fun.pinv(coord) myfunc = QFunc(atoms, atoms.get_calculator()) myfunc = Memoize(myfunc, DirStore("cache.d")) myfunc = compose( myfunc, fun) pmapc = pwrapper(pmap) func = fwrapper(myfunc, startdir = startdir, mask = mask, workhere = workhere) # the derivatives are needed hessian = derivatef( func, xcenter, pmap = pmapc, **kwargs) # save is assumend to be a filename, so far only the hessian is saved: if save is not None: savetxt(save, hessian) mass = mass_matrix (atoms.get_masses(), mask) freqs, modes = vibmod(mass, hessian) # the output will be printed on demand, with modes if wanted # the output for the freqs can easily be recreated later on, but # for the mode vectors the mass (not included in the direct output_ # is needed if VERBOSE or give_output == 2: output(freqs, modes, mass, mask) elif give_output == 1: output(freqs) return freqs, modes
def main(argv): format = None zmat = None while argv[0].startswith("--"): if argv[0] == '--format': format = argv[1] argv = argv[2:] elif argv[0] == '--zmatrix': __, zmat, v_name, __, __, __, __ = read_zmt_from_file(argv[1]) argv = argv[2:] elif argv[0] == '--help': print __doc__ return geo1 = read(argv[0], format=format) geos = [read(arg, format=format) for arg in argv[1:]] if zmat == None: fun = Cartesian() else: fun = ZMat(zmat) symbols = geo1.get_chemical_symbols() assert len(geos) > 0 for geo in geos: assert geo.get_chemical_symbols() == symbols compare(geo1.get_positions(), geo.get_positions(), symbols, fun)
def read_path_fix(symbfile, zmatifiles = None, maskfile = None, maskedgeo = None): """ If not stored in a pickle.path it does not makes too much sense to give unchangeable things for every geoemtry, thus separate them Here the symbols (define the system) are read in, the function to tranform into cartesian is also generated, uses zmat files to build the same system as before, if the coordinates are with a mask, here is the possibility to set this also """ # loadtxt (and especially savetxt) do not seems to like strings f = open(symbfile, "r") sr = f.read() f.close() symbols = sr.split() if len(zmatifiles)==0: trafo = Cartesian() else: trafo, __, __, __, __ = get_transformation(zmatifiles, len(symbols) * 3, "direct") if maskfile is not None: assert (maskedgeo is not None) f = open(maskfile, "r") sr = f.read() f.close() mask = get_mask(sr) geo_raw = loadtxt(maskedgeo) trafo = Masked(trafo, mask, geo_raw) return symbols, trafo
def get_geos(geos, dc, zmi): """ Creates the inital path, the atoms object and the function for changing between internal and Cartesian (Cartesian to be fed into atoms object) """ at, geo_carts = get_cartesian_geos(geos, dc) # RETURN POINT: only Cartesian geometry if zmi == []: geo_int = array([ge.flatten() for ge in geo_carts]) return at, geo_int, Cartesian(), [[]], [False], [ len(geo_carts[0].flatten()) ], None func, d_nums, quats, size_nums, mask1 = get_transformation( zmi, len(geo_carts[0].flatten()), dc["zmt_format"]) # transform Cartesians to internals (all functions used # till know have pseudoinverse) geo_int = [func.pinv(geo) for geo in geo_carts] return at, geo_int, func, d_nums, quats, size_nums, mask1
def make_uranyl(x, flexible=6): """ Return the "best" linear approximation to the uranyl geometry as a Fixed() func. """ from pts.zmat import ZMat # Make uranyl linear: zmt = ZMat([(None, None, None), (1, None, None), (1, 2, None)], base=1) # Bond length and the bond angle for uranyl, use the same Z-matrix # for uranyl: s = zmt.pinv(x) # Set the bond lengths equal and 180 degrees angle. Note that if # you plug these internal variables into z-matrix you will not get # zmt(s) ~ x even when s was derived from x. That is because of # the default orientation z-matrix chooses: s_bond = 1.79 # A or sum (s[:2]) / 2 s = [s_bond, s_bond, pi] # Uranyl may or may not be fixed, but to adjust orientation, # rotate a rigid object: Y = Rigid(zmt(s)) y = Y(Y.pinv(x)) if flexible == 0: return Fixed(y) # 0 dof elif flexible == 2: # liear uranyl with flexible bonds: def f(x): ra, rb = x return array([[0., 0., 0.], [0., 0., ra], [0., 0., -rb]]) return Affine(f, array([0., 0.])) # 2 dof elif flexible == 6: # return Move (relate (x, zmt (s)), zmt) return ManyBody(Fixed(x[0:1]), Cartesian(x[1:3]), dof=[0, 6]) else: assert False
def get_transformation(zmi, len_carts, zmt_format): # extract data from (several) zmatrices if zmt_format == "gx": datas = [read_zmt_from_gx(zm) for zm in zmi] elif zmt_format == "gauss": datas = [read_zmt_from_gauss(zm) for zm in zmi] else: datas = [read_zmt_from_file(zm) for zm in zmi] names, zmat, var_nums, mult, d_nums, size_sys, size_nums, size_carts, mask1 = restructure( datas) # decide if global positioning is needed # it is needed if there are more than one option, first one checks for # if there are cartesian coordinates with_globs = (len_carts > size_sys) or len(zmat) > 1 # gx mask, only valid if gx's zmat is for complete system if with_globs: mask1 = None else: mask1 = mask1[0] # first only the zmatrix functions, allow multiple use of variables funcs = [] quats = [] # build function for every zmatrix for i, zm, va_nm, mul in zip(range(len(var_nums)), zmat, var_nums, mult): fun = ZMat(zm) # some variables are used several times if mul > 0: fun = With_equals(fun, va_nm) # global positioning needed if with_globs: fun = With_globals(fun) quats.append(True) # attention, this changes number of internal coordinates # belonging to this specific zmatrix size_nums[i] = size_nums[i] + 6 else: quats.append(False) funcs.append(fun) # if not all variables are used up, the rest are in Cartesians if len_carts > size_sys: funcs.append(Cartesian()) # there is also some need to specify their sizes size_nums.append(len_carts - size_sys) size_carts.append(len_carts - size_sys) quats.append(False) d_nums.append([]) # how many atoms per single function # needed for Mergefuncs.pinv size_carts = [s / 3. for s in size_carts] # now merge the functions to one: if len(size_nums) > 1: func = Mergefuncs(funcs, size_nums, size_carts) else: # no need to merge a single function func = funcs[0] return func, d_nums, quats, size_nums, mask1
# Here the different ways of using the different functions are given if choice == 0: """ Cartesian is used for only rearranging the input variables. From our functions we expect ouput of the three Cartesian coordinates for each atom in an array of the kind (N, 3) For further use in our pathsearcher we need the function itself and the two minima Cartesian expects its input vector to be a one-dimensional array, as does pathsearcher. """ func = Cartesian() min1 = func.pinv(m1) min2 = func.pinv(m2) elif choice == 1: """ It is intended for real internal coordinates: but works with every function: With_globals adds paramter for global rotation and translation. Notice that here the start geometries have 6 parameter more each. The first three of them describe an quaternion (or the vector v of unit quaternion e^iv. The rotation by this is obtained to every atom alone. The other three describe the global translation. """ func = With_globals(Cartesian()) # Trick as there are not enough coordinates to revert them
""" func = diagsandhight() der = 1.0 # diag1, diag2, hight min1 = [td_s, td_s, td_s / sqrt(2.)] min2 = [td_s, td_s, -td_s / sqrt(2.)] middle = [td_s * der, td_s * sqrt(4. - der**2.) , 0.] elif testfun == "carts": """ The starting geometries are provided by the diag and high function. See case "diaghigh". The optimization and else is done in Cartesian coordinates. """ func = Cartesian() # generate starting geometries with the help of function # diagsandhight: func_h = diagsandhight() min1 = func_h(asarray([td_s, td_s, td_s / sqrt(2.)])).flatten() min2 = func_h(asarray([td_s, td_s, -td_s / sqrt(2.)])).flatten() middle = func_h(asarray([td_s, td_s * sqrt(3.) , 0.])).flatten() elif testfun == "cartsred": """ Same starting situation as in case "carts", only that in this case some coordinates are fixed (y,z) direction for first two atoms and (x) for the last two. """ func2 = Cartesian()
, lwave = False , kpts = (5,5,1) ) # Atoms object needs to have all these in order to be able to run correctly: PdH.set_calculator(calculator) PdH.set_pbc(True) sc = 5.59180042562320832916 cell = [[1.0000000000000000, 0.0000000000000000, 0.0000000000000000], [0.5000000000000000, 0.8660254037844386, 0.0000000000000000], [0.0000000000000000, 0.0000000000000000, 1.0000000000000000]] cell = array(cell) * sc PdH.set_cell(cell) # Do calculation in Cartesian coordinates fun1 = Cartesian() # PES in cartesian coordiantes: pes = QFunc(PdH, PdH.get_calculator()) def reduce(vec, mask): """ Function for generating starting values. Use a mask to reduce the complete vector. """ vec_red = [] for i, m in enumerate(mask): if m: vec_red.append(vec[i]) return array(vec_red)