def test_init_welltemp_s(self): f = [('s', 'wt', 4, (0.5, 2.0, 3.0, 4.0))] bs = BasisSet.from_sequence(funs=f, element='H', name='small wt') self.assertIsInstance(bs, BasisSet) self.assertTrue(np.allclose(bs.functions['s']['e'], np.array([16.000, 3.8984375, 1.1875, 0.50585938])))
def bsprint(): ''' CLI script to read a basis set from a file in internal format and print in a specified format ''' parser = ArgumentParser() parser.add_argument("file", help="file name with a pickled BasisSet object") parser.add_argument("-f", "--format", choices=[ "cfour", "dalton", "gamessus", "gaussian", "json", "molpro", "nwchem" ], default="default") args = parser.parse_args() bs = BasisSet.from_pickle(args.file) if args.format == 'default': print(str(bs)) else: writer = "to_" + args.format method = getattr(bs, writer) print(method())
def get_basis_dict(bso, x0): ''' Return a dictionary with :py:class:`BasisSet` objects as values and element symbols as keys. The dictionary is composed based on the current parameters ``x0`` and attributes of the :py:class:`BSOptimizer` including the ``staticbs`` ''' bsdict = dict() for atom, functs in bso.fsopt.items(): bsdict[atom] = BasisSet.from_optpars(x0, funs=functs, name='opt', element=atom, explogs=bso.uselogs) if bso.staticbs is not None: if isinstance(bso.staticbs, dict): common_atoms = set(bso.staticbs.keys()) & set(bsdict.keys()) if common_atoms: for atom in common_atoms: bsdict[atom].append(bso.staticbs[atom]) diff_atoms = set(bso.staticbs.keys()) - set(bsdict.keys()) if diff_atoms: for atom in diff_atoms: bsdict[atom] = bso.staticbs[atom] elif isinstance(bso.staticbs, BasisSet): if bso.staticbs.element in set(bsdict.keys()): bsdict[atom].append(bso.staticbs) else: bsdict[bso.staticbs.element] = bso.staticbs return bsdict
def test_init_legendre_s(self): le_s = np.array([20.08553692, 5.29449005, 1.39561243, 0.36787944]) f = [('s', 'le', 4, (1.0, 2.0))] bs = BasisSet.from_sequence(funs=f, element='H', name='small et') self.assertIsInstance(bs, BasisSet) self.assertTrue(np.allclose(bs.functions['s']['e'], le_s))
def opt_multishell(shells=None, nfps=None, guesses=None, max_params=5, opt_tol=1.0e-4, save=False, bsopt=None, **kwargs): ''' Optimize a basis set by saturating the function space shell by shell Kwargs: shells (list of strings): list of shells to be optimized, in the order the optimization should be performed, nfps (list of lists of integers): list specifying a set of function numbers to be scanned per each shell, guesses (list of lists of floats): list specifying a set of starting parameters per each shell, max_params (int) maximal number of parameters to be used in the legendre expansion, (length of the expansion) opt_tol (float): threshold controlling the termination of the shell optimization, if energy difference between two basis sets with subsequent number of functionsis larger than this threshold, another function is added to this shell and parameters are reoptimized kwargs: options for the basis set optimization driver, see driver function from the basisopt module ''' # bsnoopt needs to exists since it will be appended with optimized # functions after each shell is optimized if kwargs['bsnoopt'] is None: kwargs['bsnoopt'] = BasisSet.from_dict({"element" : "Be", "functions" : {}}) # begin the main loop over shells, nr f per shell and guesses for shell, nfs, guess in zip(shells, nfps, guesses): header = " Beginning optimization for {s:s} shell ".format(s=shell) print("="*100) print(format(header, '-^100')) print("="*100) bsopt['params'] = [tuple(guess)] # begin the optimization for a given shell and store the optimized # functions under optimized_shell optimized_shell = opt_shell_by_nf(shell, nfs, max_params=max_params, opt_tol=opt_tol, save=save, bsopt=bsopt, **kwargs) # add the optimized shell to the total basis set kwargs['bsnoopt'].add(optimized_shell) # save the final complete basis set basis_dict = vars(kwargs['bsnoopt']) with open("final.bas", 'wb') as ff: ff.write(str(basis_dict))
def test_init_eventemp_s(self): f = [('s', 'et', 5, (0.5, 2.0))] bs = BasisSet.from_sequence(funs=f, element='H', name='small et') self.assertIsInstance(bs, BasisSet) self.assertEqual(bs.name, 'small et') self.assertEqual(bs.element, 'H') self.assertTrue(np.allclose(bs.functions['s']['e'], np.array([8.0, 4.0, 2.0, 1.0, 0.5])))
def test_init_eventemp_df(self): f = [('d', 'et', 4, (0.5, 2.0)), ('f', 'et', 3, (1.0, 3.0))] bs = BasisSet.from_sequence(funs=f, element='H', name='small et') self.assertIsInstance(bs, BasisSet) self.assertTrue(np.allclose(bs.functions['d']['e'], np.array([4.0, 2.0, 1.0, 0.5]))) self.assertTrue(np.allclose(bs.functions['f']['e'], np.array([9.0, 3.0, 1.0])))
def test_optimize(tmpdir): tmpdir.chdir() be = Molecule(name="Be", atoms=[('Be', )], charge=0, multiplicity=1) template = '''***,be ccpvdz tight fs test memory,100,m %geometry %basis %core {rhf; wf,4,1,0} cisd ''' mp = Molpro(exevar="MOLPRO_EXE", runopts=["-s", "-n", "1", "-d", "."]) corefs = {'Be': [('s', 'exp', 1, (1.1, )), ('p', 'exp', 1, (4.2, ))]} ccpvdz_str = '''basis={ !BAZA Petersona s,Be,2.940000E+03,4.412000E+02,1.005000E+02,2.843000E+01,9.169000E+00,3.196000E+00,1.159000E+00,1.811000E-01,5.890000E-02; c,1.9,6.800000E-04,5.236000E-03,2.660600E-02,9.999300E-02,2.697020E-01,4.514690E-01,2.950740E-01,1.258700E-02,-3.756000E-03; c,1.9,-1.230000E-04,-9.660000E-04,-4.831000E-03,-1.931400E-02,-5.328000E-02,-1.207230E-01,-1.334350E-01,5.307670E-01,5.801170E-01; c,9.9,1.000000E+00; p,Be,3.619000E+00,7.110000E-01,1.951000E-01,6.018000E-02; c,1.4,2.911100E-02,1.693650E-01,5.134580E-01,4.793380E-01; c,4.4,1.000000E+00; ! !d,Be,2.354000E-01; !c,1.1,1.000000E+00; } ''' ccpvdz = BasisSet.from_str(ccpvdz_str, fmt='molpro') bso = BSOptimizer(objective='cisd total energy', core=[[1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]], template=template, verbose=True, code=mp, mol=be, fsopt=corefs, staticbs={'Be': ccpvdz}, uselogs=True, runcore=True, fname='be_tight.inp') bso.run() coreenergy = -0.031510764610001019 assert abs(bso.result.fun - coreenergy) < 1.0e-8, 'wrong objective'
def test_to_json(): bs = BasisSet.from_str(VTZGAUSSIAN, fmt='gaussian', name='VTZ') bsdumped = bs.to_json(indent=4) bsloaded = BasisSet.from_json(bsdumped) assert bs.name == bsloaded.name, 'inconsistent name' assert bs.element == bsloaded.element, 'inconsistent element' for shell, funs in bs.functions.items(): assert shell in bsloaded.functions.keys(), 'missing shell {}'.format(shell) assert np.allclose(funs['e'], bsloaded.functions[shell]['e']) for f1, f2 in zip(funs['cf'], bsloaded.functions[shell]['cf']): assert np.allclose(f1['idx'], f2['idx']), 'inconsistent idx' assert np.allclose(f1['cc'], f2['cc']), 'inconsistent cc'
def main(): res = driver(code=mp, job=job, mol=be, bsopt=event, opt=optimization) print res.success print res.x print res.fun #save the basis set opt_basis = vars(BasisSet.from_optdict(res.x, event)) with open('optimized_functions.bas', 'wb') as ff: ff.write(str(opt_basis))
def test_init_welltemp_sp(self): wt_s = np.array([30.4, 13.78515502, 6.21305899, 2.78349551, 1.24082247, 0.55241203]) wt_p = np.array([72.9, 21.58054659, 6.35310115, 1.86463574, 0.54936271]) f = [('s', 'wt', 6, (0.5, 2.0, 0.9, 1.2)), ('p', 'wt', 5, (0.5, 3.0, 0.8, 1.3))] bs = BasisSet.from_sequence(funs=f, element='H', name='small wt') self.assertIsInstance(bs, BasisSet) self.assertTrue(np.allclose(bs.functions['s']['e'], wt_s)) self.assertTrue(np.allclose(bs.functions['p']['e'], wt_p))
def test_init_mixed_formula_spd(self): et_s = np.array([8.0, 4.0, 2.0, 1.0, 0.5]) wt_p = np.array([16.000, 3.8984375, 1.1875, 0.50585938]) leg_d = np.array([36.59823444, 1.8221188, 1.56831219]) f = [('s', 'et', 5, (0.5, 2.0)), ('p', 'wt', 4, (0.5, 2.0, 3.0, 4.0)), ('d', 'le', 3, (1.0, 1.5, 1.1))] bs = BasisSet.from_sequence(funs=f, element='H', name='small et') self.assertIsInstance(bs, BasisSet) self.assertTrue(np.allclose(bs.functions['s']['e'], et_s)) self.assertTrue(np.allclose(bs.functions['p']['e'], wt_p)) self.assertTrue(np.allclose(bs.functions['d']['e'], leg_d))
def test_init_legendre_spd(self): leg_s = np.array([1.48029993e+03, 7.57611094e+00, 1.22140276e+00, 6.53769785e-01, 1.22456428e-01]) leg_p = np.array([330.29955991, 5.21663132, 4.70275331, 1.8221188]) leg_d = np.array([36.59823444, 1.8221188, 1.56831219]) f = [('s', 'le', 5, (1.0, 3.5, 1.6, 1.2)), ('p', 'le', 4, (2.0, 1.5, 1.2, 1.1)), ('d', 'le', 3, (1.0, 1.5, 1.1))] bs = BasisSet.from_sequence(funs=f, element='H', name='small et') self.assertIsInstance(bs, BasisSet) self.assertTrue(np.allclose(bs.functions['s']['e'], leg_s)) self.assertTrue(np.allclose(bs.functions['p']['e'], leg_p)) self.assertTrue(np.allclose(bs.functions['d']['e'], leg_d))
def test_basis_set_parser_molpro(tmpdir): tmpdir.chdir() fpath = tmpdir.join('augtz.molpro') fpath.write(AUGTZ_MOLPRO) bsd = BasisSet.from_file(str(fpath), fmt='molpro') assert isinstance(bsd, dict) assert 'H' in bsd.keys() assert 'Li' in bsd.keys() assert 'Be' in bsd.keys() assert isinstance(bsd['H'], BasisSet) assert isinstance(bsd['Li'], BasisSet) assert isinstance(bsd['Be'], BasisSet) assert bsd['H'].nf() == 9 assert bsd['Li'].nf() == 23 assert bsd['Be'].nf() == 23
def test_basis_set_parser_gaussian(tmpdir): tmpdir.chdir() fpath = tmpdir.join('augtz.gaussian') fpath.write(AUGTZ_GAUSSIAN) bsd = BasisSet.from_file(str(fpath), fmt='gaussian') assert isinstance(bsd, dict) assert 'H' in bsd.keys() assert 'Li' in bsd.keys() assert 'Be' in bsd.keys() assert isinstance(bsd['H'], BasisSet) assert isinstance(bsd['Li'], BasisSet) assert isinstance(bsd['Be'], BasisSet) assert bsd['H'].nf() == 9 assert bsd['Li'].nf() == 23 assert bsd['Be'].nf() == 23
def get_basis(self, name=None, element=None): ''' Construct the BasisSet object from the result of the optimized exponents and function definition. Args: name : str Name to be assigned to the basis set element : str Element symbol for the basis set Returns: basis : chemtools.basisset.BasisSet :py:class:`BasisSet <chemtools.basisset.BasisSet>` object with the optimized functions ''' bsdict = {} # get number of parameters per atom npars = [sum(get_num_params(t) for t in funs) for funs in self.fsopt.values()] x0peratom = sliceinto(self.result.x, npars) for (atom, funs), xpars in zip(self.fsopt.items(), x0peratom): bsdict[atom] = BasisSet.from_optpars(xpars, funs, name=name, element=element, explogs=self.uselogs) if self.staticbs is not None: if isinstance(self.staticbs, dict): common_atoms = set(self.staticbs.keys()) & set(bsdict.keys()) if common_atoms: for atom in common_atoms: bsdict[atom].append(self.staticbs[atom]) diff_atoms = set(self.staticbs.keys()) - set(bsdict.keys()) if diff_atoms: for atom in diff_atoms: bsdict[atom] = self.staticbs[atom] elif isinstance(self.staticbs, BasisSet): if self.staticbs.element in set(bsdict.keys()): bsdict[atom].append(self.staticbs) else: bsdict[self.staticbs.element] = self.staticbs return bsdict
def bsconvert(): ''' CLI script to convert between different basis set formats ''' parser = ArgumentParser( description='Convert basis set between formats of different programs') parser.add_argument("filename", help="file name with a basis set, default='pickle'") parser.add_argument( "-from", "--inputformat", choices=["gamessus", "gaussian", "json", "molpro", "pickle"], help="Basis set input format", default="pickle") parser.add_argument("-to", "--outputformat", choices=[ "cfour", "dalton", "gamessus", "gaussian", "json", "molpro", "nwchem", "pickle" ], help="Basis set output format", default="molpro") parser.add_argument('-o', '--output', help='name of the output file') args = parser.parse_args() name = os.path.splitext(args.filename)[0] if args.inputformat == "pickle": bsets = BasisSet.from_pickle(args.filename) elif args.inputformat == "json": bsets = BasisSet.from_json(args.filename) else: bsets = BasisSet.from_file(fname=args.filename, fmt=args.inputformat, name=name) if args.outputformat == "pickle": if isinstance(bsets, dict): for elem, bset in bsets.items(): bset.to_pickle(name + '_' + elem + '.pkl') elif isinstance(bsets, BasisSet): bsets.to_pickle(name + '_' + bsets.element + '.pkl') else: writer_name = "to_" + args.outputformat writer_objs = [] if isinstance(bsets, dict): for elem, bset in bsets.items(): writer_objs.append(getattr(bset, writer_name)) elif isinstance(bsets, BasisSet): writer_objs.append(getattr(bsets, writer_name)) else: raise ValueError('Something went wrong') if args.output: fobj = open(args.output, 'w') else: fobj = sys.stdout for writer in writer_objs: print(writer(), file=fobj)
def setUp(self): fs = [('s', 'et', 4, (0.5, 2.0)), ('p', 'et', 3, (1.0, 3.0)), ('d', 'et', 2, (1.5, 4.0))] self.bs = BasisSet.from_sequence(name='test', element='H', funs=fs) self.maxDiff = None
def run_total_energy(x0, *args): ''' Funtion for running a single point calculation and parsing the resulting energy (or property) as specified by the objective function. Args: x0 : list or numpy.array contains a list of parameters to be optimized, may be explicit exponents or parametrized exponents in terms of some polynomial args : tuple of dicts bsopt, bsnoopt, code, job, mol, opt, needed for writing input and parsing output Returns: parsed result of the single point calculation as speficied by the objective function in the "job" dictionary ''' # unpack the args tuple for code readability bso = args[0] for atom, functs in bso.fsopt.items(): ni = 0 nt = 0 for shell, seq, nf, params in functs: nt += nf if seq not in ['le', 'legendre'] and not bso.uselogs: x0[ni:nt] = np.abs(x0[ni:nt]) ni += nf bsdict = get_basis_dict(bso, x0) # set the penalty value if bso.penalize: penalty = get_penalty(bsdict, **bso.penaltykwargs) else: penalty = 1.0 if bso.verbose: bso.log.write("Current exponents being optimized:\n") for atom, functs in bso.fsopt.items(): basis = BasisSet.from_optpars(x0, funs=functs, name='opt', element=atom, explogs=bso.uselogs) bso.log.write(atom + basis.print_functions()) bso.log.flush() bso.code.write_input(fname=bso.fname, template=bso.template, basis=bsdict, mol=bso.mol, core=bso.core) output = bso.code.run(bso.fname) if bso.code.accomplished(output): if callable(bso.objective): objective = bso.objective(output) else: objective = bso.code.parse(output, bso.objective, bso.regexp) if objective is None: raise ValueError("Unable to parse the objective, check output") if bso.verbose: bso.log.write("{0:<s}".format("Job Terminated without errors\n")) bso.log.write("x0 : " + ", ".join([str(x) for x in x0]) + "\n") bso.log.write("\n{0:<20s} : {1:>30s}\n".format("Output", output)) bso.log.write("{0:<20s} : {1:>30.10f}\n".format(str(bso.objective), objective)) bso.log.write("{0:<20s} : {1:>30.10f}\n".format("Objective", objective * penalty)) bso.log.write("=" * 80 + "\n") bso.log.flush() return objective * penalty else: raise ValueError("something went wrong, check output {0:s}".format(output))
def run_core_energy(x0, *args): ''' Funtion for running two single point calculations and parsing the resulting energy (or property) as specified by the objective function, primarily designed to extract core energy. Args: x0: list or numpy.array contains a list of parameters to be optimized, may be explicit exponents or parametrized exponents in terms of some polynomial args: tuple of dicts bsopt, bsnoopt, code, job, mol, opt, needed for writing input and parsing output Returns: parsed result of the single point calculation as speficied by the objective function in the "job" dictionary ''' # unpack the args tuple for code readability bso = args[0] for atom, functs in bso.fsopt.items(): ni = 0 nt = 0 for shell, seq, nf, params in functs: nt += nf if seq not in ['le', 'legendre'] and not bso.uselogs: x0[ni:nt] = np.abs(x0[ni:nt]) ni += nf bsdict = get_basis_dict(bso, x0) # set the penalty value if bso.penalize: penalty = get_penalty(bsdict, bso.penaltykwargs) else: penalty = 1.0 if bso.verbose: bso.log.write("Current exponents being optimized:\n") for atom, functs in bso.fsopt.items(): basis = BasisSet.from_optpars(x0, funs=functs, name='opt', element=atom, explogs=bso.uselogs) bso.log.write(atom + "\n" + basis.print_functions()) bso.log.flush() citote = [] stats = [] base = os.path.splitext(bso.fname)[0] inputs = [base + "_core" + str(sum(x)) + ".inp" for x in bso.core] for inpname, core in zip(inputs, bso.core): bso.code.write_input(fname=inpname, core=core, basis=bsdict, mol=bso.mol, template=bso.template) outputs = bso.code.run_multiple(inputs) for output in outputs: citote.append(bso.code.parse(output, bso.objective, bso.regexp)) stats.append(bso.code.accomplished(output)) if stats[0] and stats[1]: if bso.verbose: bso.log.write("x0 : " + ", ".join([str(x) for x in x0]) + "\n") bso.log.write("{0:<20s} : {1:>30s} {2:>30s}\n".format("Terminated OK", str(stats[0]), str(stats[1]))) bso.log.write("{0:<20s} : {1:>30.10f} {2:>30.10f}\n".format(str(bso.objective), citote[0], citote[1])) bso.log.write("-" * 84) coreenergy = citote[0] - citote[1] if coreenergy > 0.0: coreenergy = -1.0 * coreenergy if bso.verbose: bso.log.write("{0:<20s} : {1:>30.10f}\n".format("Core energy", coreenergy)) bso.log.write("{0:<20s} : {1:>30.10f}\n".format("Objective", coreenergy * penalty)) bso.log.write("=" * 84) bso.log.flush() return coreenergy * penalty else: raise ValueError("something went wrong, check outputs {0:s}".format(", ".join(outputs)))
def test_optimize(tmpdir): tmpdir.chdir() dalton = Dalton(exevar='DALTON_EXE', runopts=['-nobackup', '-noarch', '-d']) beh = Molecule(name="BeH-", atoms=[('Be',), ('H', (0.0, 0.0, 2.724985))], sym="cnv 2", charge=-1, multiplicity=1) moltemplate = '''INTGRL basis set optimization test dalton calculator Atomtypes=2 Charge=-1 Integrals=1.0D-20 %basis ''' hftemplate = '''**DALTON INPUT .RUN WAVE FUNCTIONS **WAVE FUNCTION .HF **END OF DALTON INPUT ''' fname = {'dal': 'hf.dal', 'mol': 'BeH-.mol'} template = {'mol': moltemplate, 'dal': hftemplate} optimization = {"method": "Nelder-Mead", "tol": 1.0e-4, "options": {"maxiter": 100, "disp": True} } ccpvdz_str = '''basis={ s,Be,2.940000E+03,4.412000E+02,1.005000E+02,2.843000E+01,9.169000E+00,3.196000E+00,1.159000E+00,1.811000E-01,5.890000E-02; c,1.9,6.800000E-04,5.236000E-03,2.660600E-02,9.999300E-02,2.697020E-01,4.514690E-01,2.950740E-01,1.258700E-02,-3.756000E-03; c,1.9,-1.230000E-04,-9.660000E-04,-4.831000E-03,-1.931400E-02,-5.328000E-02,-1.207230E-01,-1.334350E-01,5.307670E-01,5.801170E-01; c,9.9,1.000000E+00; p,Be,3.619000E+00,7.110000E-01,1.951000E-01,6.018000E-02; c,1.4,2.911100E-02,1.693650E-01,5.134580E-01,4.793380E-01; c,4.4,1.000000E+00; d,Be,2.354000E-01; c,1.1,1.000000E+00; s, H , 13.0100000, 1.9620000, 0.4446000, 0.1220000, 0.0297400 c, 1.3, 0.0196850, 0.1379770, 0.4781480 c, 4.4, 1 c, 5.5, 1 p, H , 0.7270000, 0.1410000 c, 1.1, 1 c, 2.2, 1 } ''' ccpvdz = BasisSet.from_str(ccpvdz_str, fmt='molpro') augfs = {'Be': [('s', 'exp', 1, (0.02,)), ('p', 'exp', 1, (0.01,)), ('d', 'exp', 1, (0.07,))]} bso = BSOptimizer(objective='hf total energy', template=template, code=dalton, mol=beh, fsopt=augfs, staticbs=ccpvdz, verbose=True, optalg=optimization, fname=fname) bso.run() energy = -15.131589405116999 assert abs(bso.result.fun - energy) < 1.0e-8, 'wrong objective'
def test_optimize(tmpdir): tmpdir.chdir() psi = Psi4(exevar="PSI4_EXE", runopts=["-n", "4"]) beh = Molecule(name="BeH-", atoms=[('Be', ), ('H', (0.0, 0.0, 2.724985))], sym="cnv 2", charge=-1, multiplicity=1) psitemp = '''#! test BeH- memory 100 mb molecule beh { Be 0.0000 0.0000 0.0000 H 0.0000 0.0000 1.4420 units angstrom } beh.set_molecular_charge(-1) beh.set_multiplicity(1) basis = { assign mybasis [ mybasis ] spherical %basisset } set { freeze_core True e_convergence 13 d_convergence 10 } energy('cisd') ''' optimization = { "method": "Nelder-Mead", "tol": 1.0e-4, "options": { "maxiter": 100, "disp": True, } } ccpvdz_str = '''basis={ s,Be,2.940000E+03,4.412000E+02,1.005000E+02,2.843000E+01,9.169000E+00,3.196000E+00,1.159000E+00,1.811000E-01,5.890000E-02; c,1.9,6.800000E-04,5.236000E-03,2.660600E-02,9.999300E-02,2.697020E-01,4.514690E-01,2.950740E-01,1.258700E-02,-3.756000E-03; c,1.9,-1.230000E-04,-9.660000E-04,-4.831000E-03,-1.931400E-02,-5.328000E-02,-1.207230E-01,-1.334350E-01,5.307670E-01,5.801170E-01; c,9.9,1.000000E+00; p,Be,3.619000E+00,7.110000E-01,1.951000E-01,6.018000E-02; c,1.4,2.911100E-02,1.693650E-01,5.134580E-01,4.793380E-01; c,4.4,1.000000E+00; d,Be,2.354000E-01; c,1.1,1.000000E+00; s, H , 13.0100000, 1.9620000, 0.4446000, 0.1220000, 0.0297400 c, 1.3, 0.0196850, 0.1379770, 0.4781480 c, 4.4, 1 c, 5.5, 1 p, H , 0.7270000, 0.1410000 c, 1.1, 1 c, 2.2, 1 } ''' ccpvdz = BasisSet.from_str(ccpvdz_str, fmt='molpro') augfs = { 'Be': [('s', 'exp', 1, (0.02, )), ('p', 'exp', 1, (0.01, )), ('d', 'exp', 1, (0.07, ))] } bso = BSOptimizer(objective='cisd total energy', template=psitemp, code=psi, mol=beh, fsopt=augfs, staticbs=ccpvdz, core=[1, 0, 0, 0, 0, 0, 0, 0], verbose=True, optalg=optimization, fname='beh_aug.dat') bso.run() energy = -15.204232302468 assert abs(bso.result.fun - energy) < 1.0e-8, 'wrong objective'
def test_optimize(tmpdir): tmpdir.chdir() gamesstemp = ''' $CONTRL scftyp=rhf cityp=guga runtyp=energy maxit=30 mult=1 ispher=1 units=bohr exetyp=run $END $SYSTEM timlim=525600 mwords=100 $END $CIDRT iexcit=2 nfzc=2 ndoc=2 nval=40 group=d2h $END %basis ''' be2X = Molecule(name="Be2", atoms=[('Be', (0.0, 0.0, -1.5)), ('H', (0.0, 0.0, 0.0), True), ('Be', (0.0, 0.0, 1.5))], sym="dnh 2", charge=0, multiplicity=1, unique=[0, 1]) bsstr = '''basis={ s,Be,2.940000E+03,4.412000E+02,1.005000E+02,2.843000E+01,9.169000E+00,3.196000E+00,1.159000E+00,1.811000E-01,5.890000E-02; c,1.9,6.800000E-04,5.236000E-03,2.660600E-02,9.999300E-02,2.697020E-01,4.514690E-01,2.950740E-01,1.258700E-02,-3.756000E-03; c,1.9,-1.230000E-04,-9.660000E-04,-4.831000E-03,-1.931400E-02,-5.328000E-02,-1.207230E-01,-1.334350E-01,5.307670E-01,5.801170E-01; c,9.9,1.000000E+00; p,Be,3.619000E+00,7.110000E-01,1.951000E-01,6.018000E-02; c,1.4,2.911100E-02,1.693650E-01,5.134580E-01,4.793380E-01; c,4.4,1.000000E+00; d,Be,2.354000E-01; c,1.1,1.000000E+00; } ''' vdz = BasisSet.from_str(bsstr, fmt='molpro') optimization = { "method": "CG", "tol": 1.0e-4, "jacob": False, "options": { "maxiter": 100, "disp": True, 'eps': 1.0e-3 } } gams = GamessUS(exevar="GAMESS_EXE", runopts=['1']) midbond = {'H': [('s', 'et', 4, (0.05, 2.0)), ('p', 'et', 4, (0.04, 2.0))]} bso = BSOptimizer(objective='cisd total energy', template=gamesstemp, code=gams, mol=be2X, fsopt=midbond, staticbs={'Be': vdz}, core=2, fname='midbond.inp', verbose=True, optalg=optimization) bso.run() energy = -29.1326831928 assert abs(bso.result.fun - energy) < 1.0e-8, 'wrong objective'
def opt_shell_by_nf(shell=None, nfs=None, max_params=5, opt_tol=1.0e-4, save=False, bsopt=None, **kwargs): ''' For a given shell optimize the functions until the convergence criterion is reached the energy difference for two consecutive function numbers is less than the threshold Kwargs: shell : string string label for the shell to be optimized nfs : list of ints list of integers representing the number of basis functions to be inceremented in the optimization, max_params : int maximal number of parameters to be used in the legendre expansion, (length of the expansion) opt_tol : float threshold controlling the termination of the shell optimization, if energy difference between two basis sets with subsequent number of functionsis larger than this threshold, another function is added to this shell and parameters are reoptimized, save : bool a flag to trigger saving all the optimized basis functions for each shell, kwargs : dict options for the basis set optimization driver, see driver function from the basisopt module Returns: BasisSet object instance with optimized functions for the specified shell Raises: ValueError: when `shell` is different from `s`, `p`, `d`, `f`, `g`, `h`, `i` when number of parameters equals 1 and there are more functions when there are more parameters than functions to optimize ''' _shells = ['s', 'p', 'd', 'f', 'g', 'h', 'i'] if shell not in _shells: raise ValueError('shell must be one of the following: {}'.format(", ".join(_shells))) if len(bsopt['params'][0]) == 1 and min(nfs) != 1: raise ValueError("1 parameter and {0} functions doesn't make sense".format(min(nfs))) if min(nfs) < len(bsopt['params'][0]): raise ValueError("more parameters ({0}) than functions to optimize ({1})".format(len(bsopt['params'][0]), min(nfs))) bsopt["typ"] = "legendre" e_last = 0.0 x_last = bsopt['params'][0] for nf in nfs: bsopt['nfpshell'] = [0]*_shells.index(shell) + [nf] res = driver(bsopt=bsopt, **kwargs) print("Completed optimization for {0:d} {1}-type functions".format(nf, shell)) print("{s:<25s} : {v:>20.10f}".format(s="Current Function value", v=res.fun)) print("{s:<25s} : {v:>20.10f}".format(s="Previous Function value", v=e_last)) print("{s:<25s} : {v:>20.10f}".format(s="Difference", v=abs(res.fun-e_last))) if abs(res.fun - e_last) < opt_tol: print("Basis saturated with respect to threshold") bsopt['nfpshell'] = nfps_last if save: save_basis(x_last, bsopt) return BasisSet.from_optdict(x_last, bsopt) else: print("Threshold exceeded, continuing optimization.") x_last = res.x.tolist() nfps_last = bsopt['nfpshell'] if len(bsopt['params'][0]) < max_params: print("adding more parameters") restup = tuple(res.x) # this assumption should be revised, improved or justified # suggestion: maybe change to average of existing parameters restup += tuple([abs(min(restup)*0.25)]) bsopt['params'] = [restup,] else: print("not adding more parameters") bsopt['params'] = [tuple(res.x),] e_last = res.fun else: print("Supplied number of functions exhausted but the required accuracy was not reached") if save: save_basis(res.x.tolist(), bsopt) return BasisSet.from_optdict(res.x.tolist(), bsopt)