Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better user interface and consistency check through out env/gp/kernel modules #184

Merged
merged 255 commits into from
Jun 18, 2020

Conversation

nw13slx
Copy link
Collaborator

@nw13slx nw13slx commented Jun 11, 2020

Major changes:

  1. Input arguments:
  • cutoff is no longer an array. but a dictionary {'twobody': 7, 'threebody':4.5}
  • kernel_name, kernel functions are all removed. replace by "kernels" that takes an array of all different kernels ['twobody', 'threebody', 'manybody']
  1. new class:
  • Parameters class and methods that check whether hyper-parameters, hyper-parameter-mask, cutoffs, kernels are consistent. All relevant checks and info retrival in GP, kernel/utils, mgp are shifted to the parameters.py . (hopefully it's easier to maintain.)
  1. special kernel for MGP that loops over grid point, xyz, and triplets inside the kernel.
  2. all prints are replaced by logger. Output class is rewritten with logger. So it can be easier to print to screen and files at the same time. As a result, the verbose level of GPFA and OTF are all changed from "1-5" to "error, warning, info, debug"

Minor changes:

  1. backward_arguments and backward_attributes are added to GP. All old changes in argument and attributes over different versions of Flare are documented there. So old json and pickle file can still be loaded.
  2. a couple more functions are added to GP class to reduce repeated lines
  3. OTF and GPFA header printing, parser, GP reconstruction are slightly revised to make it easier to maintain.
  4. unit tests were adapted

An example of the new GP initialization:

from flare.gp import GaussianProcess
from flare.utils.parameter_helper import ParameterHelper

pm = ParameterHelper(species=['Cu', 'C', 'H', 'O'],
                          kernels={'twobody':[['*', '*'], ['Cu','Cu']],
                                  'threebody':[['*', '*', '*'], ['Cu','Cu', 'Cu']]},
                           parameters={'twobody0':[1.29, 1.47], 'twobody1':[7e-3, 0.19],
                                 'threebody0':[8e-4, 0.89], 'threebody1':[6.1e-3, 0.72],
                                 'cutoff_twobody':7.0, 'cutoff_threebody':4.5,
                                 'noise':0.05, 'energy_noise':0.01})
hm = pm.as_dict()
cutoffs = hm['cutoffs']
hyps = hm['hyps']
hyp_labels = hm['hyp_labels']
kernels = hm['kernels']
 
gp_model = GaussianProcess(kernels=kernels,
                                                 hyps=hyps, cutoffs=cutoffs,
                                                 hyp_labels=hyp_labels,
                                                 hyps_mask=hm)

nw13slx and others added 30 commits May 19, 2020 20:59
… into user_interface_refactory

Conflicts:
	flare/mgp/mgp.py
…flare into user_interface_refactory

Conflicts:
	flare/env.py
	flare/mgp/mgp.py
	tests/test_env.py
if std_in_bound:
new_pos = self.md_step()

else:
# record GP forces
self.update_temperature(new_pos)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic is wrong here; velocities get sent to zero, since new_pos hasn't been updated. (I'll fix this)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8544b9f addresses this by mirroring the otf loop on master (new positions are calculated first, and then is_std_in_bound is called)

flare/ase/otf.py Outdated
FLARE_Calculator or DFT calculator
'''
self.md.step()
return self.atoms.positions
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is different from the md_step method in otf.py, which computes the new positions but doesn't overwrite the positions attribute of the structure

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've attempted to resolve this with 125c08f by removing the second call to md.step() in the otf loop

Get new position in molecular dynamics based on the forces predicted by
FLARE_Calculator or DFT calculator
'''
self.md.step()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somehow, self.md.step() updates the positions of self.structure, even though it should act only on self.atoms. This causes the velocities and temperatures to be reported as zero in the OTF output file.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1829b0c seems to give a temporary fix to this problem by manually resetting the positions of self.structure. But I'm still confused why self.md.step() updates self.structure.positions...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue was that self.md.step() returned atoms.positions rather than a copy of it, which caused self.atoms and self.structure to get updated together downstream. a2a785a fixes this

Comment on lines +37 to +38
kernels (list, optional): Determine the type of kernels. Example:
['2', '3'], ['2', '3', 'mb'], ['2']. Defaults to ['2', '3']
Copy link
Contributor

@stevetorr stevetorr Jun 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a nice change.

@@ -682,33 +625,29 @@ def as_dict(self):

return out_dict

def sync_data(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should move the setting of the NP training labels to this function, so that it's only a matter of adding to training data and training labels?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating the 'all labels' attribute could also happen here.

kernel, grad, ek, efk = str_to_kernel_set(kernel_name, multihyps)
def update_kernel(self, kernels, component="mc", hyps_mask=None):
kernel, grad, ek, efk = str_to_kernel_set(
kernels, component, hyps_mask)
Copy link
Contributor

@stevetorr stevetorr Jun 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No docstring & typehints? :)

@@ -962,3 +933,76 @@ def __del__(self):
if (self.name in _global_training_labels):
_global_training_labels.pop(self.name, None)
_global_training_data.pop(self.name, None)

@staticmethod
def backward_arguments(kwargs, new_args={}):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love these deprecation warnings. It's great we have this! Will save a lot of grief in using old scripts

@@ -74,7 +75,7 @@ def __init__(self, frames: List[Structure],
max_trains: int = np.inf,
min_atoms_per_train: int = 1,
shuffle_frames: bool = False,
verbose: int = 1,
verbose: str = "INFO",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great call to re-do it this way

flare/kernels/kernels.py Outdated Show resolved Hide resolved
Comment on lines 128 to 146
# triplet1 = array([r1, r2, r12])
# triplet2 = array([r2, r1, r12])
#
# if spc1 <= spc2:
# spcs = [ctype, spc1, spc2]
# else:
# spcs = [ctype, spc2, spc1]
#
# triplet = [triplet1, triplet2]
# coord = [c1, c2]
#
# if spcs not in exist_species:
# exist_species.append(spcs)
# tris += [triplet]
# tri_dir += [coord]
# else:
# k = exist_species.index(spcs)
# tris[k] += triplet
# tri_dir[k] += coord
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why these guys are still here?

Comment on lines +17 to +19
print('running test_otf.py')
print('current working directory:')
print(os.getcwd())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect these were accidentally left over from debugging?

Comment on lines +63 to +65
print('running test_otf.py')
print('current working directory:')
print(os.getcwd())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise :)

@stevetorr
Copy link
Contributor

stevetorr commented Jun 18, 2020

LGTM (looks good to me). Major kudos to @nw13slx and @YuuuuXie for all their blood, sweat, and tears in making FLARE easier to use and maintain. This is really important work that often goes underappreciated.

@YuuuXie YuuuXie merged commit 8395cd6 into development Jun 18, 2020
@YuuuXie YuuuXie deleted the user_interface_refactory branch June 19, 2020 17:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants