diff --git a/flare/dft_interface/__init__.py b/flare/dft_interface/__init__.py index 665b6c099..b8d4a182b 100644 --- a/flare/dft_interface/__init__.py +++ b/flare/dft_interface/__init__.py @@ -14,4 +14,4 @@ from flare.dft_interface import vasp_util dft_software["vasp"]=vasp_util except ImportError: - pass + pass \ No newline at end of file diff --git a/flare/dft_interface/qe_util.py b/flare/dft_interface/qe_util.py index c06acaff9..95cbc7817 100644 --- a/flare/dft_interface/qe_util.py +++ b/flare/dft_interface/qe_util.py @@ -18,15 +18,15 @@ name = "QE" -def run_dft_par(dft_input, structure, dft_loc, ncpus=1, dft_out='pwscf.out', +def run_dft_par(dft_input, structure, dft_loc, n_cpus=1, dft_out='pwscf.out', npool=None, mpi="mpi", **dft_kwargs): """run DFT calculation with given input template - and atomic configurations. if ncpus == 1, it executes serial run. + and atomic configurations. if n_cpus == 1, it executes serial run. :param dft_input: input template file name :param structure: atomic configuration :param dft_loc: relative/absolute executable of the DFT code - :param ncpus: # of CPU for mpi + :param n_cpus: # of CPU for mpi :param dft_out: output file name :param npool: not used :param mpi: not used @@ -43,11 +43,11 @@ def run_dft_par(dft_input, structure, dft_loc, ncpus=1, dft_out='pwscf.out', dft_command = \ f'{dft_loc} -nk {npool} -i {newfilename} > {dft_out}' - if (ncpus > 1): + if (n_cpus > 1): if (mpi == "mpi"): - dft_command = f'mpirun -np {ncpus} {dft_command}' + dft_command = f'mpirun -np {n_cpus} {dft_command}' else: - dft_command = f'srun -n {ncpus} --mpi=pmi2 {dft_command}' + dft_command = f'srun -n {n_cpus} --mpi=pmi2 {dft_command}' call(dft_command, shell=True) os.remove(newfilename) @@ -55,16 +55,16 @@ def run_dft_par(dft_input, structure, dft_loc, ncpus=1, dft_out='pwscf.out', return parse_dft_forces(dft_out) -def run_dft_en_par(dft_input, structure, dft_loc, ncpus): +def run_dft_en_par(dft_input, structure, dft_loc, n_cpus): """run DFT calculation with given input template and atomic configurations. This function is not used atm - if ncpus == 1, it executes serial run. + if n_cpus == 1, it executes serial run. :param dft_input: input template file name :param structure: atomic configuration :param dft_loc: relative/absolute executable of the DFT code - :param ncpus: # of CPU for mpi + :param n_cpus: # of CPU for mpi :param dft_out: output file name :param npool: not used :param mpi: not used @@ -75,7 +75,7 @@ def run_dft_en_par(dft_input, structure, dft_loc, ncpus): run_qe_path = dft_input edit_dft_input_positions(run_qe_path, structure) qe_command = \ - 'mpirun -np {ncpus} {dft_loc} < {run_qe_path} > pwscf.out' + 'mpirun -np {n_cpus} {dft_loc} < {run_qe_path} > pwscf.out' call(qe_command, shell=True) forces, energy = parse_dft_forces_and_energy('pwscf.out') diff --git a/flare/dft_interface/vasp_util.py b/flare/dft_interface/vasp_util.py index 7c17fd652..553842bd0 100644 --- a/flare/dft_interface/vasp_util.py +++ b/flare/dft_interface/vasp_util.py @@ -99,7 +99,7 @@ def run_dft(calc_dir: str, dft_loc: str, def run_dft_par(dft_input: str, structure: Structure, - dft_command:str= None, ncpus=1, + dft_command:str= None, n_cpus=1, dft_out="vasprun.xml", parallel_prefix="mpi", mpi = None, npool = None, @@ -112,9 +112,9 @@ def run_dft_par(dft_input: str, structure: Structure, ("Warning: No VASP Command passed, or stored in " "environment as VASP_COMMAND. ") - if ncpus > 1: + if n_cpus > 1: if parallel_prefix == "mpi": - dft_command = f'mpirun -np {ncpus} {dft_command}' + dft_command = f'mpirun -np {n_cpus} {dft_command}' else: serial_prefix = dft_kwargs.get('serial_prefix', '') dft_command = f'{serial_prefix} {dft_command}' diff --git a/flare/gp.py b/flare/gp.py index 508edfbb6..a516267c0 100644 --- a/flare/gp.py +++ b/flare/gp.py @@ -51,7 +51,7 @@ class GaussianProcess: hyperparameter optimization algorithm. Defaults to 10. par (bool, optional): If True, the covariance matrix K of the GP is computed in parallel. Defaults to False. - ncpus (int, optional): Number of cpus used for parallel + n_cpus (int, optional): Number of cpus used for parallel calculations. Defaults to 1. output (Output, optional): Output object used to dump hyperparameters during optimization. Defaults to None. @@ -66,7 +66,7 @@ def __init__(self, kernel: Callable, opt_algorithm: str = 'L-BFGS-B', maxiter: int = 10, par: bool = False, per_atom_par: bool = True, - ncpus: int = None, nsample: int = 100, + n_cpus: int = 1, nsample: int = 100, output: Output = None, multihyps: bool = False, hyps_mask: dict = None): """Initialize GP parameters and training data.""" @@ -89,7 +89,7 @@ def __init__(self, kernel: Callable, self.maxiter = maxiter self.par = par self.per_atom_par = per_atom_par - self.ncpus = ncpus + self.n_cpus = n_cpus self.nsample = nsample self.output = output @@ -245,7 +245,7 @@ def train(self, output=None, custom_bounds=None, args = (self.training_data, self.training_labels_np, self.kernel_grad, output, self.cutoffs, self.hyps_mask, - self.ncpus, self.nsample) + self.n_cpus, self.nsample) objective_func = get_neg_like_grad res = None @@ -323,16 +323,16 @@ def predict(self, x_t: AtomicEnvironment, d: int) -> [float, float]: # Kernel vector allows for evaluation of At. Env. if (self.par and not self.per_atom_par): - ncpus = self.ncpus + n_cpus = self.n_cpus else: - ncpus = 1 + n_cpus = 1 k_v = get_kernel_vector_par(self.training_data, self.kernel, x_t, d, self.hyps, cutoffs=self.cutoffs, hyps_mask=self.hyps_mask, - ncpus=self.ncpus, + n_cpus=self.n_cpus, nsample=self.nsample) # Guarantee that alpha is up to date with training set @@ -479,7 +479,7 @@ def set_L_alpha(self): self.kernel, cutoffs=self.cutoffs, hyps_mask=self.hyps_mask, - ncpus=self.ncpus, + n_cpus=self.n_cpus, nsample=self.nsample) l_mat = np.linalg.cholesky(ky_mat) @@ -506,16 +506,16 @@ def update_L_alpha(self): return if (self.par and not self.per_atom_par): - ncpus=self.ncpus + n_cpus=self.n_cpus else: - ncpus=1 + n_cpus=1 ky_mat = get_ky_mat_update_par(self.ky_mat, self.hyps, self.training_data, self.kernel, cutoffs=self.cutoffs, hyps_mask=self.hyps_mask, - ncpus=ncpus, + n_cpus=n_cpus, nsample=self.nsample) l_mat = np.linalg.cholesky(ky_mat) @@ -585,7 +585,7 @@ def from_dict(dictionary): """Create GP object from dictionary representation.""" if 'mc' in dictionary['kernel_name']: - if (dictionary['multihyps'] is False): + if (dictionary.get('multihyps',False) is False): force_kernel, grad = \ str_to_mc_kernel(dictionary['kernel_name'], include_grad=True) else: @@ -615,11 +615,13 @@ def from_dict(dictionary): hyps=np.array(dictionary['hyps']), hyp_labels=dictionary['hyp_labels'], par=dictionary['par'], - ncpus=dictionary['ncpus'], + per_atom_par=dictionary.get('per_atom_par',True), + n_cpus=dictionary.get('n_cpus') or dictionary.get('no_cpus'), maxiter=dictionary['maxiter'], opt_algorithm=dictionary['algo'], - multihyps=dictionary['multihyps'], - hyps_mask=dictionary['hyps_mask']) + multihyps=dictionary.get('multihyps',False), + hyps_mask=dictionary.get('hyps_mask',None) + ) new_gp.training_data = [AtomicEnvironment.from_dict(env) for env in dictionary['training_data']] @@ -688,3 +690,28 @@ def write_model(self, name: str, format: str = 'json'): if (len(self.training_data)>5000): self.ky_mat = np.load(f"{name}_ky_mat.npy") self.compute_matrices() + + + @staticmethod + def from_file(filename: str, format: str=''): + """ + One-line convenience method to load a GP from a file stored using + write_file + + Args: + filename (str): path to GP model + format (str): json or pickle if format is not in filename + :return: + """ + + if '.json' in filename or 'json' in format: + with open(filename, 'r') as f: + return GaussianProcess.from_dict(json.loads(f.readline())) + + elif '.pickle' in filename or 'pickle' in format: + with open(filename, 'rb') as f: + return pickle.load(f) + + else: + raise ValueError("Warning: Format unspecified or file is not " + ".json or .pickle format.") diff --git a/flare/gp_algebra.py b/flare/gp_algebra.py index 2e454205a..a2c997f15 100644 --- a/flare/gp_algebra.py +++ b/flare/gp_algebra.py @@ -10,7 +10,7 @@ ####################################### def get_ky_mat_par(hyps: np.ndarray, training_data: list, - kernel: Callable, cutoffs=None, ncpus=None, nsample=100): + kernel: Callable, cutoffs=None, n_cpus=None, nsample=100): """ Parallelized version of function which computes ky matrix @@ -18,14 +18,14 @@ def get_ky_mat_par(hyps: np.ndarray, training_data: list, :param training_data: list of atomic envirionments :param kernel: :param cutoffs: - :param ncpus: number of cpus to use. + :param n_cpus: number of cpus to use. :return: ky_mat """ - if (ncpus is None): - ncpus = mp.cpu_count() - if (ncpus == 1): + if (n_cpus is None): + n_cpus = mp.cpu_count() + if (n_cpus == 1): return get_ky_mat(hyps, training_data, kernel, cutoffs) @@ -37,11 +37,11 @@ def get_ky_mat_par(hyps: np.ndarray, training_data: list, size = len(training_data) size3 = 3*len(training_data) k_mat = np.zeros([size3, size3]) - with mp.Pool(processes=ncpus) as pool: + with mp.Pool(processes=n_cpus) as pool: ns = int(math.ceil(size/nsample)) nproc = ns*(ns+1)//2 - if (nproc < ncpus): - nsample = int(size/int(np.sqrt(ncpus*2))) + if (nproc < n_cpus): + nsample = int(size/int(np.sqrt(n_cpus*2))) ns = int(math.ceil(size/nsample)) block_id = [] @@ -70,7 +70,7 @@ def get_ky_mat_par(hyps: np.ndarray, training_data: list, bool(s1==s2), kernel, cutoffs))] count += 1 - if (count >= ncpus*3): + if (count >= n_cpus*3): for iget in range(base, count+base): s1, e1, s2, e2 = block_id[iget] k_mat_block = k_mat_slice[iget-base].get() @@ -147,7 +147,7 @@ def get_ky_mat_pack(hyps: np.ndarray, training_data1: list, def get_ky_and_hyp_par(hyps: np.ndarray, training_data: list, - kernel_grad: Callable, cutoffs=None, ncpus=None, nsample=100): + kernel_grad: Callable, cutoffs=None, n_cpus=None, nsample=100): """ Parallelized version of function which computes ky matrix and its derivative to hyper-parameter @@ -158,14 +158,14 @@ def get_ky_and_hyp_par(hyps: np.ndarray, training_data: list, :param kernel_grad: function object of the kernel gradient :param cutoffs: The cutoff values used for the atomic environments :type cutoffs: list of 2 float numbers - :param ncpus: number of cpus to use. + :param n_cpus: number of cpus to use. :return: hyp_mat, ky_mat """ - if (ncpus is None): - ncpus = mp.cpu_count() - if (ncpus == 1): + if (n_cpus is None): + n_cpus = mp.cpu_count() + if (n_cpus == 1): return get_ky_and_hyp(hyps, training_data, kernel_grad, cutoffs) @@ -180,11 +180,11 @@ def get_ky_and_hyp_par(hyps: np.ndarray, training_data: list, k_mat = np.zeros([size3, size3]) hyp_mat = np.zeros([number_of_hyps, size3, size3]) - with mp.Pool(processes=ncpus) as pool: + with mp.Pool(processes=n_cpus) as pool: ns = int(math.ceil(size/nsample)) nproc = ns*(ns+1)//2 - if (nproc < ncpus): - nsample = int(size/int(np.sqrt(ncpus*2))) + if (nproc < n_cpus): + nsample = int(size/int(np.sqrt(n_cpus*2))) ns = int(math.ceil(size/nsample)) block_id = [] @@ -212,7 +212,7 @@ def get_ky_and_hyp_par(hyps: np.ndarray, training_data: list, hyps, t1, t2, bool(s1==s2), kernel_grad, cutoffs))] count += 1 - if (count >= ncpus*3): + if (count >= n_cpus*3): for iget in range(base, count+base): s1, e1, s2, e2 = block_id[iget] h_mat_block, k_mat_block = mat_slice[iget-base].get() @@ -402,7 +402,7 @@ def get_ky_and_hyp(hyps: np.ndarray, training_data: list, return hyp_mat, ky_mat def get_ky_mat_update_par(ky_mat_old, hyps: np.ndarray, training_data: list, - kernel: Callable, cutoffs=None, ncpus=None, nsample=100): + kernel: Callable, cutoffs=None, n_cpus=None, nsample=100): ''' used for update_L_alpha, especially for parallelization parallelized for added atoms, for example, if add 10 atoms to the training @@ -416,9 +416,9 @@ def get_ky_mat_update_par(ky_mat_old, hyps: np.ndarray, training_data: list, :return: updated covariance matrix ''' - if (ncpus is None): - ncpus = mp.cpu_count() - if (ncpus == 1): + if (n_cpus is None): + n_cpus = mp.cpu_count() + if (n_cpus == 1): return get_ky_mat_update(ky_mat_old, hyps, training_data, kernel, cutoffs) @@ -432,12 +432,12 @@ def get_ky_mat_update_par(ky_mat_old, hyps: np.ndarray, training_data: list, size3 = 3*len(training_data) ky_mat = np.zeros([size3, size3]) ky_mat[:old_size3, :old_size3] = ky_mat_old - with mp.Pool(processes=ncpus) as pool: + with mp.Pool(processes=n_cpus) as pool: ns = int(math.ceil(size/nsample)) nproc = (size3-old_size3)*(ns+old_size3)//2 - if (nproc < ncpus): - nsample = int(size/int(np.sqrt(ncpus*2))) + if (nproc < n_cpus): + nsample = int(size/int(np.sqrt(n_cpus*2))) ns = int(math.ceil(size/nsample)) ns_new = int(math.ceil((size-old_size)/nsample)) @@ -478,7 +478,7 @@ def get_ky_mat_update_par(ky_mat_old, hyps: np.ndarray, training_data: list, bool(s1==s2), kernel, cutoffs))] count += 1 - if (count >= ncpus*3): + if (count >= n_cpus*3): for iget in range(base, count+base): s1, e1, s2, e2 = block_id[iget] k_mat_block = k_mat_slice[iget-base].get() @@ -630,7 +630,7 @@ def get_neg_likelihood(hyps: np.ndarray, training_data: list, training_labels_np: np.ndarray, kernel: Callable, output = None, cutoffs=None, - ncpus=None, nsample=100): + n_cpus=None, nsample=100): """compute the negative log likelihood :param hyps: list of hyper-parameters @@ -645,13 +645,13 @@ def get_neg_likelihood(hyps: np.ndarray, training_data: list, :param output: Output object for dumping every hyper-parameter sets computed :type output: class Output - :param ncpus: number of cpus to use. + :param n_cpus: number of cpus to use. :return: float """ ky_mat = get_ky_mat_par(hyps, training_data, - kernel, cutoffs, ncpus, nsample) + kernel, cutoffs, n_cpus, nsample) like = get_like_from_ky_mat(ky_mat, training_labels_np) @@ -664,7 +664,7 @@ def get_neg_likelihood(hyps: np.ndarray, training_data: list, def get_neg_like_grad(hyps: np.ndarray, training_data: list, training_labels_np: np.ndarray, kernel_grad: Callable, cutoffs=None, - output = None, ncpus=None, nsample=100): + output = None, n_cpus=None, nsample=100): """compute the log likelihood and its gradients :param hyps: list of hyper-parameters @@ -679,7 +679,7 @@ def get_neg_like_grad(hyps: np.ndarray, training_data: list, :param output: Output object for dumping every hyper-parameter sets computed :type output: class Output - :param ncpus: number of cpus to use. + :param n_cpus: number of cpus to use. :return: float, np.array """ @@ -687,7 +687,7 @@ def get_neg_like_grad(hyps: np.ndarray, training_data: list, hyp_mat, ky_mat = \ get_ky_and_hyp_par(hyps, training_data, - kernel_grad, cutoffs, ncpus, nsample) + kernel_grad, cutoffs, n_cpus, nsample) like, like_grad = \ get_like_grad_from_mats(ky_mat, hyp_mat, training_labels_np) @@ -725,7 +725,7 @@ def get_kernel_vector_unit(training_data, kernel, x, def get_kernel_vector_par(training_data, kernel, x, d_1, hyps, cutoffs, - ncpus=None, nsample=100): + n_cpus=None, nsample=100): """ Compute kernel vector, comparing input environment to all environments in the GP's training set. @@ -737,17 +737,17 @@ def get_kernel_vector_par(training_data, kernel, x, :rtype: np.ndarray """ - if (ncpus is None): - ncpus = mp.cpu_count() - if (ncpus == 1): + if (n_cpus is None): + n_cpus = mp.cpu_count() + if (n_cpus == 1): return get_kernel_vector(training_data, kernel, x, d_1, hyps, cutoffs) with mp.Pool(processes=processes) as pool: size = len(training_data) ns = int(math.ceil(size/nsample)) - if (ns < ncpus): - nsample = int(size/int(ncpus)) + if (ns < n_cpus): + nsample = int(size/int(n_cpus)) ns = int(math.ceil(size/nsample)) k12_slice = [] for ibatch in range(ns): diff --git a/flare/gp_algebra_multi.py b/flare/gp_algebra_multi.py index 53d7a56e4..e41aed836 100644 --- a/flare/gp_algebra_multi.py +++ b/flare/gp_algebra_multi.py @@ -119,7 +119,7 @@ def get_neg_likelihood(hyps: np.ndarray, training_data: list, training_labels_np: np.ndarray, kernel, output = None, cutoffs=None, hyps_mask=None, - ncpus=None, nsample=100): + n_cpus=None, nsample=100): if output is not None: ostring="hyps:" @@ -132,7 +132,7 @@ def get_neg_likelihood(hyps: np.ndarray, training_data: list, ky_mat = \ get_ky_mat_par(hyps, training_data, kernel, cutoffs=cutoffs, hyps_mask=hyps_mask, - ncpus=ncpus, nsample=nsample) + n_cpus=n_cpus, nsample=nsample) output.write_to_log(f"get_key_mat {time.time()-time0}\n", name="hyps") @@ -152,7 +152,7 @@ def get_neg_like_grad(hyps: np.ndarray, training_data: list, training_labels_np: np.ndarray, kernel_grad, output = None, cutoffs=None, hyps_mask=None, - ncpus=None, nsample=100): + n_cpus=None, nsample=100): time0 = time.time() if output is not None: @@ -168,7 +168,7 @@ def get_neg_like_grad(hyps: np.ndarray, training_data: list, kernel_grad, cutoffs=cutoffs, hyps_mask=hyps_mask, - ncpus=ncpus, nsample=nsample) + n_cpus=n_cpus, nsample=nsample) if output is not None: output.write_to_log(f"get_ky_and_hyp {time.time()-time0}\n", name="hyps") @@ -287,11 +287,11 @@ def get_ky_mat_pack(hyps: np.ndarray, training_data1: list, def get_ky_mat_par(hyps: np.ndarray, training_data: list, kernel, cutoffs=None, hyps_mask=None, - ncpus=None, nsample=100): + n_cpus=None, nsample=100): - if (ncpus is None): - ncpus =mp.cpu_count() - if (ncpus == 1): + if (n_cpus is None): + n_cpus =mp.cpu_count() + if (n_cpus == 1): return get_ky_mat(hyps, training_data, kernel, cutoffs, hyps_mask) @@ -309,12 +309,12 @@ def get_ky_mat_par(hyps: np.ndarray, training_data: list, size3 = 3*len(training_data) k_mat_slice = [] k_mat = np.zeros([size3, size3]) - with mp.Pool(processes=ncpus) as pool: + with mp.Pool(processes=n_cpus) as pool: ns = int(math.ceil(size/nsample)) nproc = ns*(ns+1)//2 - if (nproc < ncpus): - nsample = int(math.ceil(size/int(np.sqrt(ncpus*2)))) + if (nproc < n_cpus): + nsample = int(math.ceil(size/int(np.sqrt(n_cpus*2)))) ns = int(math.ceil(size/nsample)) block_id = [] @@ -343,7 +343,7 @@ def get_ky_mat_par(hyps: np.ndarray, training_data: list, kernel, cutoffs, hyps_mask))) count += 1 - if (count >= ncpus*3): + if (count >= n_cpus*3): for iget in range(base, count+base): s1, e1, s2, e2 = block_id[iget] k_mat_block = k_mat_slice[iget-base].get() @@ -381,12 +381,12 @@ def get_ky_mat_par(hyps: np.ndarray, training_data: list, def get_ky_and_hyp_par(hyps: np.ndarray, training_data: list, kernel_grad, cutoffs=None, hyps_mask=None, - ncpus=None, nsample=100): + n_cpus=None, nsample=100): - if (ncpus is None): - ncpus = mp.cpu_count() - if (ncpus == 1): + if (n_cpus is None): + n_cpus = mp.cpu_count() + if (n_cpus == 1): return get_ky_and_hyp(hyps, training_data, kernel_grad, cutoffs, hyps_mask) @@ -409,12 +409,12 @@ def get_ky_and_hyp_par(hyps: np.ndarray, training_data: list, k_mat = np.zeros([size3, size3]) hyp_mat0 = np.zeros([non_noise_hyps, size3, size3]) - with mp.Pool(processes=ncpus) as pool: + with mp.Pool(processes=n_cpus) as pool: ns = int(math.ceil(size/nsample)) nproc = ns*(ns+1)//2 - if (nproc < ncpus): - nsample = int(math.ceil(size/np.sqrt(ncpus*2))) + if (nproc < n_cpus): + nsample = int(math.ceil(size/np.sqrt(n_cpus*2))) ns = int(math.ceil(size/nsample)) block_id = [] @@ -446,7 +446,7 @@ def get_ky_and_hyp_par(hyps: np.ndarray, training_data: list, cutoffs, hyps_mask))) count += 1 - if (count > ncpus*3): + if (count > n_cpus*3): for iget in range(base, count+base): s1, e1, s2, e2 = block_id[iget] h_mat_block, k_mat_block = mat_slice[iget-base].get() @@ -492,7 +492,7 @@ def get_ky_and_hyp_par(hyps: np.ndarray, training_data: list, def get_ky_mat_update_par(ky_mat_old, hyps: np.ndarray, training_data: list, kernel, cutoffs=None, hyps_mask=None, - ncpus=None, nsample=100): + n_cpus=None, nsample=100): ''' used for update_L_alpha, especially for parallelization parallelized for added atoms, for example, if add 10 atoms to the training @@ -500,9 +500,9 @@ def get_ky_mat_update_par(ky_mat_old, hyps: np.ndarray, training_data: list, be distributed to 30 processors ''' - if (ncpus is None): - ncpus = mp.cpu_count() - if (ncpus == 1): + if (n_cpus is None): + n_cpus = mp.cpu_count() + if (n_cpus == 1): return get_ky_mat_update(ky_mat_old, hyps, training_data, kernel, cutoffs, hyps_mask) @@ -521,11 +521,11 @@ def get_ky_mat_update_par(ky_mat_old, hyps: np.ndarray, training_data: list, ky_mat = np.zeros([size3, size3]) ky_mat[:old_size3, :old_size3] = ky_mat_old ds = [1, 2, 3] - with mp.Pool(processes=ncpus) as pool: + with mp.Pool(processes=n_cpus) as pool: ns = int(math.ceil(size/nsample)) nproc = (size3-old_size3)*(ns+old_size3)//2 - if (nproc < ncpus): - nsample = int(math.ceil(size/np.sqrt(ncpus*2))) + if (nproc < n_cpus): + nsample = int(math.ceil(size/np.sqrt(n_cpus*2))) ns = int(math.ceil(size/nsample)) ns_new = int(math.ceil((size-old_size)/nsample)) @@ -566,7 +566,7 @@ def get_ky_mat_update_par(ky_mat_old, hyps: np.ndarray, training_data: list, bool(s1==s2), kernel, cutoffs, hyps_mask))] count += 1 - if (count >= ncpus*3): + if (count >= n_cpus*3): for iget in range(base, count+base): s1, e1, s2, e2 = block_id[iget] k_mat_block = k_mat_slice[iget-base].get() @@ -667,7 +667,7 @@ def get_kernel_vector_unit(training_data, kernel, x, def get_kernel_vector_par(training_data, kernel, x, d_1, hyps, cutoffs=None, hyps_mask=None, - ncpus=None, nsample=100): + n_cpus=None, nsample=100): """ Compute kernel vector, comparing input environment to all environments in the GP's training set. @@ -679,18 +679,18 @@ def get_kernel_vector_par(training_data, kernel, :rtype: np.ndarray """ - if (ncpus is None): - ncpus = mp.cpu_count() - if (ncpus == 1): + if (n_cpus is None): + n_cpus = mp.cpu_count() + if (n_cpus == 1): return get_kernel_vector(training_data, kernel, x, d_1, hyps, cutoffs, hyps_mask) - with mp.Pool(processes=ncpus) as pool: + with mp.Pool(processes=n_cpus) as pool: # sort of partition size = len(training_data) - ns = int(math.ceil(size/nsample/ncpus)*ncpus) + ns = int(math.ceil(size/nsample/n_cpus)*n_cpus) nsample = int(math.ceil(size/ns)) ns = int(math.ceil(size/nsample)) diff --git a/flare/gp_from_aimd.py b/flare/gp_from_aimd.py index 15b6a27b0..ee8512677 100644 --- a/flare/gp_from_aimd.py +++ b/flare/gp_from_aimd.py @@ -65,8 +65,10 @@ def __init__(self, frames: List[Structure], calculate_energy: bool = False, output_name: str = 'gp_from_aimd', pre_train_max_iter: int = 50, - max_atoms_from_frame: int = inf, max_trains: int = inf, - min_atoms_added: int = 1, shuffle_frames: bool = False, + max_atoms_from_frame: int = np.inf, + max_trains: int = np.inf, + min_atoms_per_train: int = 1, + shuffle_frames: bool = False, verbose: int = 0, pre_train_on_skips: int = -1, pre_train_seed_frames: List[Structure] = None, @@ -127,10 +129,12 @@ def __init__(self, frames: List[Structure], self.max_force_error = max_force_error self.max_trains = max_trains self.max_atoms_from_frame = max_atoms_from_frame - self.min_atoms_added = min_atoms_added + self.min_atoms_per_train = min_atoms_per_train + self.verbose = verbose + self.train_count = 0 + self.parallel = parallel self.n_cpus = n_cpus - # Set prediction function based on if forces or energies are # desired, and parallelization accordingly if (parallel and gp.par and gp.per_atom_par): @@ -145,6 +149,10 @@ def __init__(self, frames: List[Structure], self.pred_func = predict_on_structure # Parameters for negotiating with the training frames + self.output = Output(output_name, always_flush=True) + + # To later be filled in using the time library + self.start_time = None self.skip = skip assert (isinstance(skip, int) and skip >= 1), "Skip needs to be a " \ @@ -336,7 +344,7 @@ def run(self): cur_frame, train_atoms, train=False) nsample += len(train_atoms) # Re-train if number of sampled atoms is high enough - if nsample >= self.min_atoms_added or ( + if nsample >= self.min_atoms_per_train or ( i + 1) == train_frame: if self.train_count < self.max_trains: self.train_gp() diff --git a/flare/mc_sephyps.py b/flare/mc_sephyps.py index f746bb9e5..6db89bbee 100644 --- a/flare/mc_sephyps.py +++ b/flare/mc_sephyps.py @@ -38,8 +38,9 @@ to identify which element to be optimized. All three have to be defined. train_noise = Bool (True/False), whether the noise parameter can be optimized original: np.array. Full set of initial values for hyperparmeters -map: np.array, array to map the hyper parameter back to the full set. map[i]=j means the i-th element in hyps should be - the j-th element in hyps_mask['original'] +map: np.array, array to map the hyper parameter back to the full set. +map[i]=j means the i-th element in hyps should be the j-th element in +hyps_mask['original'] For example, the full set of hyper parmeters @@ -53,12 +54,14 @@ ls21, ls22 etc... represent floating-point variables which correspond to the initial guesses / static values. You would then pass in: + hyps = [ls21, sig21] hyps_mask = { ..., 'train_noise': False, 'map':[0, 2], 'original': [ls21, ls22, sig21, sig22, ls3, sg3, noise]} the hyps argument should only contain the values that need to be optimized. If you want noise to be trained as well include noise as the final hyperparameter value in hyps. + """ diff --git a/flare/otf.py b/flare/otf.py index caba5a5dd..b5e2edd58 100644 --- a/flare/otf.py +++ b/flare/otf.py @@ -16,7 +16,6 @@ class OTF: - def __init__(self, dft_input: str, dt: float, number_of_steps: int, gp: gp.GaussianProcess, dft_loc: str, std_tolerance_factor: float = 1, @@ -26,7 +25,7 @@ def __init__(self, dft_input: str, dt: float, number_of_steps: int, max_atoms_added: int = 1, freeze_hyps: int = 10, rescale_steps: List[int] = [], rescale_temps: List[int] = [], dft_softwarename: str = "qe", - no_cpus: int = 1, npool: int = None, mpi: str = "srun", + n_cpus: int = 1, npool: int = None, mpi: str = "srun", dft_kwargs=None, store_dft_output: Tuple[Union[str,List[str]],str] = None): """Trains a Gaussian process force field on the fly during @@ -69,7 +68,7 @@ def __init__(self, dft_input: str, dt: float, number_of_steps: int, Defaults to []. dft_softwarename (str, optional): DFT code used to calculate ab initio forces during training. Defaults to "qe". - no_cpus (int, optional): Number of cpus used during training. + n_cpus (int, optional): Number of cpus used during training. Defaults to 1. npool (int, optional): Number of k-point pools for DFT calculations. Defaults to None. @@ -104,9 +103,8 @@ def __init__(self, dft_input: str, dt: float, number_of_steps: int, positions, species, cell, masses = \ self.dft_module.parse_dft_input(self.dft_input) - _, coded_species = struc.get_unique_species(species) - self.structure = struc.Structure(cell=cell, species=coded_species, + self.structure = struc.Structure(cell=cell, species=species, positions=positions, mass_dict=masses, prev_positions=prev_pos_init, @@ -150,7 +148,7 @@ def __init__(self, dft_input: str, dt: float, number_of_steps: int, self.output = Output(output_name, always_flush=True) # set number of cpus and npool for DFT runs - self.no_cpus = no_cpus + self.n_cpus = n_cpus self.npool = npool self.mpi = mpi @@ -160,6 +158,10 @@ def __init__(self, dft_input: str, dt: float, number_of_steps: int, def run(self): """ Performs an on-the-fly training run. + + If OTF has store_dft_output set, then the specified DFT files will + be copied with the current date and time prepended in the format + 'Year.Month.Day:Hour:Minute:Second:'. """ self.output.write_header(self.gp.cutoffs, self.gp.kernel_name, @@ -173,7 +175,7 @@ def run(self): while self.curr_step < self.number_of_steps: print('curr_step:', self.curr_step) # run DFT and train initial model if first step and DFT is on - if self.curr_step == 0 and self.std_tolerance != 0: + if self.curr_step == 0 and self.std_tolerance != 0 and len(self.gp.training_data)==0: # call dft and update positions self.run_dft() dft_frcs = copy.deepcopy(self.structure.forces) @@ -190,7 +192,7 @@ def run(self): # after step 1, try predicting with GP model else: self.gp.check_L_alpha() - self.pred_func(self.structure, self.gp, self.no_cpus) + self.pred_func(self.structure, self.gp, self.n_cpus) self.dft_step = False new_pos = md.update_positions(self.dt, self.noa, self.structure) @@ -230,6 +232,19 @@ def run(self): if (self.dft_count-1) < self.freeze_hyps: self.train_gp() + # Store DFT outputs in another folder if desired + # specified in self.store_dft_output + if self.store_dft_output is not None: + dest = self.store_dft_output[1] + target_files = self.store_dft_output[0] + now = datetime.now() + dt_string = now.strftime("%Y.%m.%d:%H:%M:%S:") + if isinstance(target_files, str): + to_copy = [target_files] + else: + to_copy = target_files + for file in to_copy: + copyfile(file, dest+'/'+dt_string+file) # write gp forces if counter >= self.skip and not self.dft_step: @@ -249,14 +264,15 @@ def run_dft(self): If OTF has store_dft_output set, then the specified DFT files will be copied with the current date and time prepended in the format 'Year.Month.Day:Hour:Minute:Second:'. - """ + + Calculates DFT forces on atoms in the current structure.""" self.output.write_to_log('\nCalling DFT...\n') # calculate DFT forces forces = self.dft_module.run_dft_par(self.dft_input, self.structure, self.dft_loc, - ncpus=self.no_cpus, + n_cpus=self.n_cpus, npool=self.npool, mpi=self.mpi, dft_kwargs=self.dft_kwargs) @@ -284,7 +300,9 @@ def run_dft(self): copyfile(file, dest+'/'+dt_string+file) def update_gp(self, train_atoms: List[int], dft_frcs: 'ndarray'): - """Updates the current GP model. + """ + Updates the current GP model. + Args: train_atoms (List[int]): List of atoms whose local environments diff --git a/flare/sampler.py b/flare/sampler.py new file mode 100644 index 000000000..c9e449934 --- /dev/null +++ b/flare/sampler.py @@ -0,0 +1,358 @@ +import numpy as np +import pymatgen as pmg +import flare as flare + +from flare.predict import predict_on_atom +from flare.gp import GaussianProcess + +from typing import List, Tuple, Union, Callable +from flare.struc import Structure + +from pymatgen import Molecule +from pymatgen.io.ase import AseAtomsAdaptor + +import time + +from pymatgen.analysis.defects.utils import StructureMotifInterstitial + +# TODO: ALLOW FOR A FEW RELAXATION FRAMES TO PROBE ANY INTERESTING ADJACENT +# CONFIGURATIONS + + +def get_rand_vec(distance,min_distance=0): + # Implementation borrowed from Pymatgen structure object's + # perturb method. + vector = np.random.randn(3) + vnorm = np.linalg.norm(vector) + dist = distance + if isinstance(min_distance, (float, int)): + dist = np.random.uniform(min_distance, dist) + return vector / vnorm * dist if vnorm != 0 else get_rand_vec(distance, + min_distance) + + + +def check_local_threshold(structure: pmg.core.Structure, + site, + threshold:float, + gp: GaussianProcess, + verbose: int = 0)->bool: + """ + + :param structure: + :param i: + :param cutoff: + :param threshold: + :return: + """ + + if verbose: + print("Now checking around neighbors of " + "site {} in a ball of radius {}".format(site, np.max(gp.cutoffs))) + now = time.time() + + + to_check_sites = structure.get_sites_in_sphere(site.coords, + r=np.max(gp.cutoffs),include_index=True, + include_image=True) + if verbose: + print(f'Now checking error on {len(to_check_sites)} sites:') + + cutoff = np.max(gp.cutoffs) + + to_check_idxs = [site[2] for site in to_check_sites] + flare_struc = Structure.from_pmg_structure(structure) + + # Loop over atoms and break if one is high uncertainty + for i in to_check_idxs: + if np.max(predict_on_atom((flare_struc,i,gp))[1])>threshold: + if verbose: + print("Condition triggered: Took {} seconds".format(time.time()-now)) + return False + if verbose: + print("No high uncertainty configurations found: Took {} seconds".format(time.time()-now)) + return True + + +def check_new_site_threshold(base_structure, + position: 'np.ndarray', + new_atom_type: Union[str, Molecule], + gp: GaussianProcess, + threshold: float, + verbose: int = 0 ): + """ + Given a base structure, a new position, and an atom type, + add the atom and test if it triggers the uncertainty + + :param base_structure: + :param site: + :param new_atom: + :param gp: + :param threshold: + :param verbose: + :return: + """ + + + # Convert to pymatgen structure to inspect atoms around radius + new_structure = base_structure.to_pmg_structure() + + if isinstance(new_atom_type, str): + new_structure.append(species=new_atom_type, + coords=position, coords_are_cartesian=True) + else: + raise NotImplementedError + target_site = new_structure.sites[-1] + + # Check if too-high uncertainty + pre = time.time() + triggers_threshold = check_local_threshold(structure = new_structure, + site=target_site, + threshold=threshold, gp=gp, + verbose=verbose) + post = time.time() + if verbose > 2: + print("Time to check configuration: {}".format(post - pre)) + + return triggers_threshold, new_structure + + + +class Sampler(object): + + def __init__(self, base_structure: flare.struc.Structure, + gp:GaussianProcess, + dft_module: str, + sampling_protocol: str = None, + rel_threshold: float = 1, + abs_threshold: float = .5): + """ + + :param base_structure: Base structure to permute + :param gp: Gaussian Process to develop + :param dft_module: String + :param sampling_protocol: TBD but will determine which way to go + :param rel_threshold: Relative uncertainty threshold + :param abs_threshold: Absolute uncertainty thre + """ + self.base_structure = base_structure + self.gp = gp + self.dft_module = dft_module + + self.sampling_protocol = None + + self.cutoff = np.max(gp.cutoffs) + + if rel_threshold == 0: + self.threshold = abs_threshold + elif abs_threshold == 0: + self.threshold = rel_threshold * gp.hyps[-1] + else: + self.threshold = min(rel_threshold * gp.hyps[-1], abs_threshold) + + def permutation_site_sampler(self, site_positions: np.array, new_atom: + 'str',depth: int = 1,cur_depth = 0, halt_number: int = np.inf, + veto_function: Callable = None, + verbose:int = 0, + relax = False, + kick: float =.05)->List[ + pmg.core.Structure]: + """ + :param site_positions: List of positions within the unit cell with + which to gauge new sites. + :param new_atom: Element of new atom to include. Will later be + extended to molecules. + :param depth: Number of simultaneous sites to consider (depth) Not yet + implemented. + :param halt_number: When this many structures have been sampled, + stop (can help to produce a managable set of configurations to run) + :param verbose: Will increase output based on setting + :return: + """ + + high_uncertainty_configs = [] + + for new_atom_coord in site_positions: + + within_thresh, new_struc = check_new_site_threshold( + self.base_structure, new_atom_coord, + new_atom_type=new_atom, gp = self.gp, + threshold=self.threshold) + + if not within_thresh: + high_uncertainty_configs.append(new_struc) + + if len(high_uncertainty_configs) >= halt_number: + break + + return high_uncertainty_configs + + + def neb_idpp_site_sampler(self,point_1: np.array, point_2: + np.array, + new_atom:'str',depth: int = 1, + cur_depth = 0, halt_number: int = np.inf, + veto_function: Callable = None, + verbose:int = 0, + relax = False, + kick: float =.05)->List[ + pmg.core.Structure]: + """ + :param site_positions: List of positions within the unit cell with + which to gauge new sites. + :param new_atom: Element of new atom to include. Will later be + extended to molecules. + :param depth: Number of simultaneous sites to consider (depth) Not yet + implemented. + :param halt_number: When this many structures have been sampled, + stop (can help to produce a managable set of configurations to run) + :param verbose: Will increase output based on setting + :return: + """ + + + high_uncertainty_configs = [] + + aaa = AseAtomsAdaptor() + + new_struc_1 = self.base_structure.to_pmg_structure() + new_struc_1.append(new_atom,point_1, coords_are_cartesian=True) + new_struc_2 = self.base_structure.to_pmg_structure() + new_struc_2.append(new_atom,point_2, coords_are_cartesian=True) + + ase_struc_1 = aaa.get_atoms(new_struc_1) + ase_struc_2 = aaa.get_atoms(new_struc_2) + + return high_uncertainty_configs + + def cheap_interp_site_sampler(self, new_points: np.ndarray, + new_atom: 'str', + halt_number: int = np.inf, + search_hump = False)->List[ + pmg.core.Structure]: + """ + :param site_positions: List of positions within the unit cell with + which to gauge new sites. + :param new_atom: Element of new atom to include. Will later be + extended to molecules. + :param depth: Number of simultaneous sites to consider (depth) Not yet + implemented. + :param halt_number: When this many structures have been sampled, + stop (can help to produce a managable set of configurations to run) + :param verbose: Will increase output based on setting + :param search_hump: Will try above and below the midpoint + :return: + """ + + high_uncertainty_configs = [] + new_points = np.array(new_points) + + for pt1 in new_points[:]: + for pt2 in new_points[:]: + + if np.allclose(pt1, pt2): + continue + joint_struc = self.base_structure.to_pmg_structure() + + joint_struc.append(new_atom, pt1, coords_are_cartesian=True) + joint_struc.append(new_atom, pt2, coords_are_cartesian=True) + + if joint_struc.get_distance(-2, -1) > 3: + continue + + new_struc_1 = self.base_structure.to_pmg_structure() + new_struc_2 = self.base_structure.to_pmg_structure() + + new_struc_1.append(new_atom, pt1, coords_are_cartesian=True) + new_struc_2.append(new_atom, pt2, coords_are_cartesian=True) + + interp_strucs = new_struc_1.interpolate(new_struc_2, + nimages=3)[1] + assert len(interp_strucs) == 3 + mid_struc = interp_strucs[1] + + within_thresh = check_local_threshold( + mid_struc, mid_struc.sites[-1], gp=self.gp, + threshold=self.threshold) + + if not within_thresh and mid_struc.is_valid(.5): + high_uncertainty_configs.append(mid_struc) + + if search_hump: + mid_struc.translate_sites([-1],np.array([0,0,-.3])) + if mid_struc.is_valid(.5) and not check_local_threshold( + mid_struc, mid_struc.sites[-1], gp=self.gp, + threshold=self.threshold): + high_uncertainty_configs.append(mid_struc) + + mid_struc.translate_sites([-1], np.array([0, 0, .45])) + within_thresh = check_local_threshold( + mid_struc, mid_struc.sites[-1], gp=self.gp, + threshold=self.threshold) + if not within_thresh: + high_uncertainty_configs.append(mid_struc) + + if len(high_uncertainty_configs) >= halt_number: + break + if len(high_uncertainty_configs) >= halt_number: + break + + return high_uncertainty_configs + + def substitution_site_sampler(self, target_indexes: List[int], + new_species: str, + target_species: Union[str,List[str]] =[], + halt: int = np.inf, + depth: int = 1): + """ + Samples substitution + + :param target_indexes: + :param target_species: Not supported yet + :param new_species: + :param depth: + :return: + """ + + if len(target_indexes) == 0 and len(target_species) == 0: + raise ValueError("Need to have target indices or target species!") + + if len(target_species)>0: + raise NotImplementedError + + # Loop through indexes and swap out, test the uncertainty + + high_uncertainty_configs = [] + for site in target_indexes: + + new_structure = self.base_structure.to_pmg_structure() + + + new_structure.sites[site].species = new_species + + if not check_local_threshold(new_structure, site, + self.cutoff, self.threshold, self.gp): + high_uncertainty_configs.append(new_structure) + + if len(high_uncertainty_configs) >= halt: + break + + return high_uncertainty_configs + + + + def random_substitution_site_sampler(self, transformation_dict, + target_species: Union[str,List[str]], + new_species: str, depth: int = 1): + """ + Generates several `alloy' versions of the structure passed in + and tests the uncertainty associated with the configurations. + + :param transformation_dict: + :param target_species: + :param new_species: + :param depth: + :return: + """ + + raise NotImplementedError() diff --git a/tests/test_OTF_cp2k_par.py b/tests/test_OTF_cp2k_par.py index 85453f499..771d88845 100644 --- a/tests/test_OTF_cp2k_par.py +++ b/tests/test_OTF_cp2k_par.py @@ -68,7 +68,7 @@ def test_otf_h2_par(): std_tolerance_factor, init_atoms=[0], calculate_energy=True, max_atoms_added=1, dft_softwarename="cp2k", - no_cpus=2, + n_cpus=2, par=True, mpi="mpi", output_name='h2_otf_cp2k_par') diff --git a/tests/test_OTF_qe.py b/tests/test_OTF_qe.py index 7cf4ce989..6e470c40c 100644 --- a/tests/test_OTF_qe.py +++ b/tests/test_OTF_qe.py @@ -55,7 +55,7 @@ def test_otf_h2(): cutoffs=cutoffs, hyp_labels=hyp_labels, energy_force_kernel=energy_force_kernel, - maxiter=50) + maxiter=50,par=False, per_atom_par = True, n_cpus=1) otf = OTF(qe_input, dt, number_of_steps, gp, dft_loc, std_tolerance_factor, init_atoms=[0], @@ -95,7 +95,7 @@ def test_otf_al(): cutoffs=cutoffs, hyp_labels=hyp_labels, energy_force_kernel=energy_force_kernel, - maxiter=50) + maxiter=50,n_cpus=1) # set up DFT calculator qe_input = './pwscf.in' # quantum espresso input file diff --git a/tests/test_OTF_qe_par.py b/tests/test_OTF_qe_par.py index c8eb041f9..d9092554e 100644 --- a/tests/test_OTF_qe_par.py +++ b/tests/test_OTF_qe_par.py @@ -62,7 +62,7 @@ def test_otf_h2(): otf = OTF(qe_input, dt, number_of_steps, gp, dft_loc, std_tolerance_factor, init_atoms=[0], calculate_energy=True, max_atoms_added=1, - no_cpus=2, par=True, + n_cpus=2, par=True, mpi="mpi", output_name='h2_otf_qe_par', store_dft_output=('pwscf.out', '.')) @@ -112,7 +112,7 @@ def test_otf_Al_npool(): otf = OTF(qe_input, dt, number_of_steps, gp, dft_loc, std_tolerance_factor, init_atoms=[0], calculate_energy=True, max_atoms_added=1, - no_cpus=2, par=True, npool=2, + n_cpus=2, par=True, npool=2, mpi="mpi", output_name='h2_otf_qe_par') diff --git a/tests/test_OTF_vasp.py b/tests/test_OTF_vasp.py index aafa0c2c8..f778bb17d 100644 --- a/tests/test_OTF_vasp.py +++ b/tests/test_OTF_vasp.py @@ -45,7 +45,7 @@ def test_otf_h2(): otf = OTF(vasp_input, dt, number_of_steps, gp, dft_loc, std_tolerance_factor, init_atoms=[0], calculate_energy=True, max_atoms_added=1, - no_cpus=1, dft_softwarename='vasp', + n_cpus=1, dft_softwarename='vasp', output_name='h2_otf_vasp') otf.run() diff --git a/tests/test_gp.py b/tests/test_gp.py index ed562cc5e..98ce780b0 100644 --- a/tests/test_gp.py +++ b/tests/test_gp.py @@ -280,6 +280,7 @@ def test_load_and_reload(two_body_gp, test_point): os.remove('two_body.pickle') two_body_gp.write_model('two_body', 'json') + with open('two_body.json', 'r') as f: new_gp = GaussianProcess.from_dict(json.loads(f.readline())) for d in [0, 1, 2]: diff --git a/tests/test_gp_algebra.py b/tests/test_gp_algebra.py index 6537117b8..795878d20 100644 --- a/tests/test_gp_algebra.py +++ b/tests/test_gp_algebra.py @@ -116,7 +116,7 @@ def test_ky_mat(): # parallel version ky_mat = func[1](hyps, training_data, kernel[0], cutoffs, - ncpus=2, nsample=20) + n_cpus=2, nsample=20) diff = (np.max(np.abs(ky_mat-ky_mat0))) assert (diff==0), "parallel implementation is wrong" @@ -150,7 +150,7 @@ def test_ky_mat(): # parallel implementation ky_mat = func[3](hyps, training_data, ker, - cutoffs, hyps_mask, ncpus=2, nsample=20) + cutoffs, hyps_mask, n_cpus=2, nsample=20) diff = (np.max(np.abs(ky_mat-ky_mat0))) assert (diff==0), "multi hyps parallel "\ "implementation is wrong"\ @@ -187,7 +187,7 @@ def test_ky_mat_update(): ky_mat = func[2](ky_mat_old, hyps, training_data, kernel[0], cutoffs, - ncpus=2, nsample=20) + n_cpus=2, nsample=20) diff = (np.max(np.abs(ky_mat-ky_mat0))) assert (diff==0), "parallel implementation is wrong" @@ -211,7 +211,7 @@ def test_ky_mat_update(): # parallel implementation ky_mat = func[4](ky_mat_old, hyps, training_data, ker, cutoffs, - hyps_mask, ncpus=2, nsample=20) + hyps_mask, n_cpus=2, nsample=20) diff = (np.max(np.abs(ky_mat-ky_mat0))) assert (diff<1e-12), "multi hyps parameter parallel "\ "implementation is wrong" @@ -232,7 +232,7 @@ def test_ky_and_hyp(): # parallel version hypmat, ky_mat = func[1](hyps, training_data, - kernel[1], cutoffs, ncpus=2) + kernel[1], cutoffs, n_cpus=2) diff = (np.max(np.abs(ky_mat-ky_mat0))) assert (diff==0), "parallel implementation is wrong" @@ -272,7 +272,7 @@ def test_ky_and_hyp(): # parallel implementation hypmat_par, ky_mat_par = func[3](hyps, training_data, ker, cutoffs, hyps_mask, - ncpus=2, nsample=2) + n_cpus=2, nsample=2) # compare to serial implementation diff = (np.max(np.abs(ky_mat-ky_mat_par))) diff --git a/tests/test_gp_multi.py b/tests/test_gp_multi.py index 87d7c90db..0450c3551 100644 --- a/tests/test_gp_multi.py +++ b/tests/test_gp_multi.py @@ -13,6 +13,7 @@ from flare import mc_simple from flare.otf_parser import OtfAnalysis from flare.mc_sephyps import _str_to_kernel as stk +import flare.mc_sephyps as en def get_random_structure(cell, unique_species, noa): """Create a random test structure """ @@ -129,7 +130,7 @@ def two_body_gp() -> GaussianProcess: hyps=hyps, hyp_labels=hm['hyps_label'], cutoffs=cutoffs, multihyps=True, hyps_mask=hm, - par=False, ncpus=1) + par=False, n_cpus=1) gaussian.update_db(test_structure, forces) # return gaussian @@ -440,7 +441,7 @@ def test_constrained_optimization_simple(): kernel_grad=en.two_plus_three_body_mc_grad, hyps=hyps, hyp_labels=hyp_labels, - cutoffs=cutoffs, par=False, ncpus=1, + cutoffs=cutoffs, par=False, n_cpus=1, hyps_mask=hyps_mask, maxiter=1,multihyps=True) diff --git a/tests/test_gp_par.py b/tests/test_gp_par.py index ae5010498..916b6d974 100644 --- a/tests/test_gp_par.py +++ b/tests/test_gp_par.py @@ -54,7 +54,7 @@ def two_body_gp() -> GaussianProcess: kernel_grad=en.three_body_grad, hyps=np.array([1, 1, 1]), hyp_labels=['Length', 'Signal Var.', 'Noise Var.'], - par=True, ncpus=2, + par=True, n_cpus=2, cutoffs=cutoffs) gaussian.update_db(test_structure, forces) @@ -170,7 +170,7 @@ def test_set_L_alpha(two_body_gp, params): GaussianProcess(kernel, kernel_grad, hyps, cutoffs, hyp_labels, energy_force_kernel, energy_kernel, opt_algorithm, - par=True, ncpus=2) + par=True, n_cpus=2) gaussian.update_db(test_structure, forces) gaussian.set_L_alpha() diff --git a/tests/test_kernels.py b/tests/test_kernels.py index 27ea5cee5..aeddd66e2 100644 --- a/tests/test_kernels.py +++ b/tests/test_kernels.py @@ -643,4 +643,4 @@ def test_grad_mask_function(): # Test map if the last parameter is not sigma_noise grad = [1, 2, 3, 4, 5] hyps_mask = {'map': [0, 3, 5]} - assert (from_grad_to_mask(grad, hyps_mask) == [1, 4]).all() + assert (from_grad_to_mask(grad, hyps_mask) == [1, 4]).all() \ No newline at end of file diff --git a/tests/test_mgp.py b/tests/test_mgp.py index 6ff38c3b1..7f133f361 100644 --- a/tests/test_mgp.py +++ b/tests/test_mgp.py @@ -182,7 +182,7 @@ def test_lammps(otf_object, structure): lammps_calculator.write_text(data_file_name, data_text) # create lammps input - style_string = 'mgp' + style_string = 'mgp' coeff_string = '* * {} Ag I yes yes'.format(lammps_location) lammps_executable = '$lmp' dump_file_name = 'tmp.dump' @@ -206,5 +206,5 @@ def test_lammps(otf_object, structure): ' log.lammps') os.system('rm '+lammps_location) os.system('rm grid3*.npy') - os.system('rm -r kv3') + os.system('rm -r kv3*')