Source code for ccs_fit.scripts.ccs_validate

import sys
import os
import numpy as np
import ase.db as db
import json
import random
from ase.calculators.singlepoint import SinglePointCalculator
from tqdm import tqdm
import time
from ase.calculators.mixing import LinearCombinationCalculator
from copy import deepcopy

from ccs_fit.ase_calculator.ccs_ase_calculator import CCS


[docs]def ccs_validate( mode=None, CCS_params=None, Ns='all', DFT_DB="DFT.db", CCS_DB="CCS_validate.db", DFTB_DB=None, charge_dict=None, charge_scaling=False, include_forces=False, verbose=False, ): """ Function to verify database generation. --------------------------------------- Input ----- mode : str String describing which mode is used, supported modes are: CCS: CCS_params_file(string) NumberOfSamples(int) DFT.db(string)") CCS+Q: CCS_params_file(string) NumberOfSamples(int) DFT.db(string) charge_dict(string) charge_scaling(bool)") DFTB: CCS_params_file(string) NumberOfSamples(int) DFT.db(string) DFTB.db(string)") Returns ------- To be specified. Example usage ------------- ccs_validate MODE [...] """ if os.path.isfile(CCS_DB): os.remove(CCS_DB) DFT_DB = db.connect(DFT_DB) CCS_DB = db.connect(CCS_DB) if mode == "DFTB": DFTB_DB = db.connect(DFTB_DB) if isinstance(charge_dict, str): charge_dict_orig = json.loads(charge_dict) charge_dict = deepcopy(charge_dict_orig) # Necessary as the dicts act as mutable objects, changes in these functions would change the global dicts, which is not desired if isinstance(CCS_params, str): with open(CCS_params, "r") as f: CCS_params_orig = json.load(f) CCS_params = deepcopy(CCS_params_orig) # Necessary as the dicts act as mutable objects, changes in these functions would change the global dicts, which is not desired if charge_dict is None: charge = False else: charge = True f = open("CCS_validate.dat", "w") print("{:^13s} {:^13s} {:^13s} {:^13s} {:^13s}".format("#Reference", "Predicted", "Error", "No_of_atoms", "structure_no"), file=f) if include_forces: f_force = open("CCS_validate_forces.dat", "w") print("{:^13s} {:^13s} {:^13s} {:^13s}".format("#Reference", "Predicted", "Error", "structure_no"), file=f_force) CCS_calc = CCS(CCS_params=CCS_params, charge=charge, q=charge_dict, charge_scaling=charge_scaling) calc = LinearCombinationCalculator([CCS_calc], [1]) if Ns == 'all': Ns = -1 # CONVERT TO INTEGER INPUT FORMAT if Ns > 0: Ns = int(Ns) mask = [a <= Ns for a in range(len(DFT_DB))] random.shuffle(mask) else: mask = len(DFT_DB) * [True] counter = 0 for row in tqdm(DFT_DB.select(), total=len(DFT_DB), colour="#800000"): if mask[counter]: structure = row.toatoms() EDFT = structure.get_potential_energy() if include_forces: FREF = structure.get_forces() EREF = EDFT structure.calc = calc ECCS = structure.get_potential_energy() if include_forces: FCCS = structure.get_forces() if mode == "DFTB": key = row.key EDFTB = DFTB_DB.get("key=" + str(key)).energy EREF = EDFT - EDFTB if include_forces: FDFTB= DFTB_DB.get("key=" + str(key)).forces FREF = [FREF[i]-FDFTB[i] for i in range(len(FREF))] sp_calculator = SinglePointCalculator( structure, energy=EDFTB + ECCS) structure.calc = sp_calculator structure.get_potential_energy() print('{:13.8f} {:13.8f} {:13.8f} {:13d} {:13d}'.format( EREF, ECCS, np.abs(EREF - ECCS), len(structure), counter), file=f) if include_forces: FREF = [item for sublist in FREF for item in sublist] FCCS = [item for sublist in FCCS for item in sublist] for force_id, force_ref in enumerate(FREF): print('{:13.8f} {:13.8f} {:13.8f} {:13d}'.format( force_ref, FCCS[force_id], np.abs(force_ref - FCCS[force_id]), counter), file=f_force) # try: # CCS_DB.write(structure, key=key) # print("key found") # except: # print(counter) # print(structure.get_potential_energy()) # print(structure.get_forces()) # print(dir(structure)) # # print(structure.results["energy"]) # print(" ") # CCS_DB.write(structure) CCS_DB.write(structure) counter += 1
[docs]def main(): import argparse try: size = os.get_terminal_size() c = size.columns txt = "-"*c print("") print(txt) import art txt = art.text2art('CCS:Validate') print(txt) except: pass parser = argparse.ArgumentParser(description='CCS fetching tool') parser.add_argument("-m", "--mode", type=str, metavar="", default='CCS', help="Mode. Availble option: CCS, CCS+Q, DFTB") parser.add_argument("-d", "--DFT_DB", type=str, metavar="", default='DFT.db', help="Name of DFT reference data-base") parser.add_argument("-dc", "--CCS_DB", type=str, metavar="", default='CCS_validate.db', help="Name of data-base to store results") parser.add_argument("-p", "--CCS_params", type=str, metavar="", default='CCS_params.json', help="CCS_params.json file") parser.add_argument("-n", "--Ns", type=int, metavar="", default=-1, help="Number of structures to include") parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output") parser.add_argument("-chg", "--charge_dict", type=json.loads, metavar="", help="Specify atomic charges in json format, e.g.: \n \'{ \"Zn\" : 2.0 , \"O\" : -2.0 }\' ") parser.add_argument("-chg_s", "--charge_scaling", type=bool, metavar="", default=False) parser.add_argument("-f", "--include_forces", type=bool, metavar="", default=False, help="Validation of the reproduced forces w.r.t. those they were fitted on.") args = parser.parse_args() ccs_validate(**vars(args))
if __name__ == "__main__": main()