-
Notifications
You must be signed in to change notification settings - Fork 129
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
Support fitting atomic virial, dipole, and polarizability #907
base: master
Are you sure you want to change the base?
Conversation
… been stored in virial
…update_polarizability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! 🚀 I had a few questions and comments. Additionally, I have some general questions:
- When does one want to train on per-atom virials/dipoles/polarizabilities? Do they make sense in their per-atom versions?
- Does the models take longer to train when using atomic vs global virials?
CHECK(gpuSetDevice(device_id)); | ||
const int block_size = 256; | ||
|
||
if (structures[0].atomic_virial_diag_only) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a check when loading the data to make sure that all structures have atomic_virial_diag_only
? Or is there a change that these may be set differently for different structures?
for (int nc = 0; nc < dataset.Nc; ++nc) { | ||
int offset = dataset.Na_sum_cpu[nc]; | ||
for (int m = 0; m < dataset.structures[nc].num_atom; ++m) { | ||
int n = offset + m; | ||
fprintf( | ||
fid_virial, | ||
"%g %g %g %g %g %g %g %g %g %g %g %g\n", | ||
dataset.virial_cpu[n] / dataset.Na_cpu[nc], | ||
dataset.virial_cpu[n + dataset.N] / dataset.Na_cpu[nc], | ||
dataset.virial_cpu[n + dataset.N * 2] / dataset.Na_cpu[nc], | ||
dataset.virial_cpu[n + dataset.N * 3] / dataset.Na_cpu[nc], | ||
dataset.virial_cpu[n + dataset.N * 4] / dataset.Na_cpu[nc], | ||
dataset.virial_cpu[n + dataset.N * 5] / dataset.Na_cpu[nc], | ||
dataset.avirial_ref_cpu[n], | ||
dataset.avirial_ref_cpu[n + dataset.N], | ||
dataset.avirial_ref_cpu[n + dataset.N * 2], | ||
dataset.avirial_ref_cpu[n + dataset.N * 3], | ||
dataset.avirial_ref_cpu[n + dataset.N * 4], | ||
dataset.avirial_ref_cpu[n + dataset.N * 5]); | ||
fprintf( | ||
fid_stress, | ||
"%g %g %g %g %g %g %g %g %g %g %g %g\n", | ||
dataset.virial_cpu[n] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.virial_cpu[n + dataset.N] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.virial_cpu[n + dataset.N * 2] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.virial_cpu[n + dataset.N * 3] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.virial_cpu[n + dataset.N * 4] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.virial_cpu[n + dataset.N * 5] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.avirial_ref_cpu[n] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.avirial_ref_cpu[n + dataset.N] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.avirial_ref_cpu[n + dataset.N * 2] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.avirial_ref_cpu[n + dataset.N * 3] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.avirial_ref_cpu[n + dataset.N * 4] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION, | ||
dataset.avirial_ref_cpu[n + dataset.N * 5] / dataset.structures[nc].volume * PRESSURE_UNIT_CONVERSION); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be possible to use/modify the existing output
function, or alternatively, make a new function called output_atomic
to clean this up a bit?
if (!atomic) { | ||
output(false, 3, fid_dipole, dataset.virial_cpu.data(), dataset.virial_ref_cpu.data(), dataset); | ||
} else { | ||
for (int nc = 0; nc < dataset.Nc; ++nc) { | ||
int offset = dataset.Na_sum_cpu[nc]; | ||
for (int m = 0; m < dataset.structures[nc].num_atom; ++m) { | ||
int n = offset + m; | ||
fprintf( | ||
fid_dipole, | ||
"%g %g %g %g %g %g\n", | ||
dataset.virial_cpu[n], | ||
dataset.virial_cpu[n + dataset.N], | ||
dataset.virial_cpu[n + dataset.N * 2], | ||
dataset.avirial_ref_cpu[n], | ||
dataset.avirial_ref_cpu[n + dataset.N], | ||
dataset.avirial_ref_cpu[n + dataset.N * 2]); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same; try and reuse printing functionality if possible
if (!atomic) { | ||
output(false, 6, fid_polarizability, dataset.virial_cpu.data(), dataset.virial_ref_cpu.data(), dataset); | ||
} else { | ||
for (int nc = 0; nc < dataset.Nc; ++nc) { | ||
int offset = dataset.Na_sum_cpu[nc]; | ||
for (int m = 0; m < dataset.structures[nc].num_atom; ++m) { | ||
int n = offset + m; | ||
fprintf( | ||
fid_polarizability, | ||
"%g %g %g %g %g %g %g %g %g %g %g %g\n", | ||
dataset.virial_cpu[n], | ||
dataset.virial_cpu[n + dataset.N], | ||
dataset.virial_cpu[n + dataset.N * 2], | ||
dataset.virial_cpu[n + dataset.N * 3], | ||
dataset.virial_cpu[n + dataset.N * 4], | ||
dataset.virial_cpu[n + dataset.N * 5], | ||
dataset.avirial_ref_cpu[n], | ||
dataset.avirial_ref_cpu[n + dataset.N], | ||
dataset.avirial_ref_cpu[n + dataset.N * 2], | ||
dataset.avirial_ref_cpu[n + dataset.N * 3], | ||
dataset.avirial_ref_cpu[n + dataset.N * 4], | ||
dataset.avirial_ref_cpu[n + dataset.N * 5]); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reuse output
if possible
@@ -172,7 +174,7 @@ void Parameters::calculate_parameters() | |||
lambda_e = lambda_f = 0.0f; | |||
enable_zbl = false; | |||
if (!is_lambda_v_set) { | |||
lambda_v = 1.0f; | |||
lambda_v = 1.0f; // by default, dipole or polarizability is fitted with global quantities |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the same lambda_v
used for atomic and global virials? You might have to double check the relative weight so that the default value of lambda_v
still make sense for atomic virials.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be fine, since as far as I can tell lambda_v
is multiplied by the per-atom virials in both cases already.
std::ifstream& input, | ||
const Parameters& para, | ||
Structure& structure, | ||
std::string& xyz_filename, | ||
int& line_number) | ||
int& line_number, | ||
int train_mode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does train_mode
do? is it a keyword that indicates if it's atomic
or global
virials that are being used?
Summary
This PR supports fitting atomic virial (for potential model), atomic dipole (for dipole model), and atomic polarizability (for polarizability model). The atmoic tensorial quatities can be used either alone or together with the global counterparts.
Modification
In struct
Structure
, 6 member variables (which are vectors of float)avirialxx
,avirialyy
,avirialzz
,avirialxy
,avirialyz
, andavirialzx
are added. These vectors are used to store the values of atomic virial and polarizability (use all 6 vectors) or dipole (only uses the first 3 vectors).In class
Dataset
, a member functionget_rmse_avirial
is added. This function calculates the rmse of the atomic tensors. Two cuda kernels are added, i.e.,gpu_sum_avirial_error
andgpu_sum_avirial_diag_only_error
. They are used to deal with the full 6-element tensor and the 3-element tensor with only diagonal terms, respectively.In class
Parameters
, a member variableatomic_v
is added. This variable can be set innep.in
and is used to determine whether to fit atomic or global tensor.In class
Fitness
, the functionsupdate_energy_force_virial
,update_dipole
, andupdate_polarizability
are passed with a new variablepara.atomic_v
, which is used to decide whether to print atomic or global tensor.Others
An example of training the atomic dipole of water is added in


examples/15_NEP_atomic_dipole_water
. The data is taken from the example of DeePMD-kit. The result of the training is as follows:An example of training the atomic polarizability of water is added in
examples/16_NEP_atomic_polarizability_water
. The data is taken from the example of DeePMD-kit. The result of the training is as follows: