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 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 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 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))