Skip to content

Commit c62524e

Browse files
committed
add non functional code to give a bit structure to the implementation
1 parent f5f65ea commit c62524e

File tree

4 files changed

+163
-9
lines changed

4 files changed

+163
-9
lines changed

bindings/bind_py_models.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,29 @@ namespace rascal {
193193
return neg_stress_global;
194194
},
195195
py::call_guard<py::gil_scoped_release>());
196+
197+
mod.def(
198+
"compute_sparse_kernel_local_neg_stress",
199+
[](const Calculator & calculator, SparseKernel & kernel,
200+
ManagerCollection & managers, SparsePoints & sparse_points,
201+
math::Vector_t & weights) {
202+
std::string neg_stress_name = compute_sparse_kernel_local_neg_stress(
203+
calculator, kernel, managers, sparse_points, weights);
204+
math::Matrix_t neg_stress_global{managers.size(), 6};
205+
size_t i_manager{0};
206+
for (const auto & manager : managers) {
207+
auto && neg_stress{
208+
*manager
209+
->template get_property<Property<double, 0, Manager_t, 6>>(
210+
neg_stress_name, true)};
211+
neg_stress_global.block(i_manager, 0, 1, 6) =
212+
Eigen::Map<const math::Matrix_t>(neg_stress.view().data(), 1,
213+
6);
214+
i_manager++;
215+
}
216+
return neg_stress_global;
217+
},
218+
py::call_guard<py::gil_scoped_release>());
196219
}
197220

198221
/**

bindings/rascal/lib/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
kernels,
55
compute_sparse_kernel_gradients,
66
compute_sparse_kernel_neg_stress,
7+
compute_sparse_kernel_local_neg_stress
78
)

bindings/rascal/models/krr.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
train_gap_model Train a GAP model given a kernel matrix and sparse points
99
"""
1010
from ..utils import BaseIO
11-
from ..lib import compute_sparse_kernel_gradients, compute_sparse_kernel_neg_stress
11+
from ..lib import (
12+
compute_sparse_kernel_gradients,
13+
compute_sparse_kernel_neg_stress,
14+
compute_sparse_kernel_local_neg_stress
15+
)
1216

1317
import scipy
1418
import numpy as np
@@ -352,7 +356,7 @@ def predict_forces(self, managers, KNM=None):
352356

353357
return -gradients
354358

355-
def predict_stress(self, managers, KNM=None):
359+
def predict_stress(self, managers, KNM=None, local_stress=False):
356360
"""Predict gradients w.r.t cell parameters, e.g. stress, associated with the atomic structures in managers.
357361
The stress is returned using the Voigt order: xx, yy, zz, yz, xz, xy.
358362
@@ -376,14 +380,26 @@ def predict_stress(self, managers, KNM=None):
376380

377381
if KNM is None:
378382
rep = self.kernel._representation
379-
neg_stress = compute_sparse_kernel_neg_stress(
380-
rep,
381-
self.kernel._kernel,
382-
managers.managers,
383-
self.X_train._sparse_points,
384-
self.weights.reshape((1, -1)),
385-
)
383+
if local_stress:
384+
neg_stress = compute_sparse_kernel_local_neg_stress(
385+
rep,
386+
self.kernel._kernel,
387+
managers.managers,
388+
self.X_train._sparse_points,
389+
self.weights.reshape((1, -1)),
390+
)
391+
else:
392+
neg_stress = compute_sparse_kernel_neg_stress(
393+
rep,
394+
self.kernel._kernel,
395+
managers.managers,
396+
self.X_train._sparse_points,
397+
self.weights.reshape((1, -1)),
398+
)
386399
else:
400+
if local_stress:
401+
raise ValueError("Option local_stress does not work with KNM.
402+
Please set KNM to None.")
387403
if 6 * len(managers) != KNM.shape[0]:
388404
raise ValueError(
389405
"KNM size mismatch {}!={}".format(6 * len(managers), KNM.shape[0])

src/rascal/models/sparse_kernel_predict.hh

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,5 +374,119 @@ namespace rascal {
374374
} // manager
375375
return neg_stress_name;
376376
}
377+
378+
379+
/**
380+
* Compute the atomic gradients of a structure w.r.t atomic cell paramaters
381+
* using a sparse GPR model. Only SOAP-GAP model is implemented at the moment
382+
* (see
383+
* @ref SparseKernelImpl<internal::SparseKernelType::GAP>::compute_derivative)
384+
*
385+
* The point of this function is to provide a faster prediction routine
386+
* compared to computing the kernel elements and then multiplying them with
387+
* the weights of the model.
388+
*
389+
* The gradients are attached to the input manager in a Property of
390+
* Order 1 with the name
391+
* '"kernel: "+kernel_type+" ; "+representation_grad_name+" negative stress;
392+
* weight_hash:"+weight_hash' gradients [2*n_managers, 3]
393+
*
394+
* @tparam StructureManagers should be an iterable over shared pointer
395+
* of structure managers like ManagerCollection
396+
* @param sparse_points a SparsePoints* class
397+
* @param managers a ManagerCollection or similar collection of
398+
* structure managers
399+
* @param weights regression weights of the sparse GPR model
400+
* @return name used to register the gradients in the managers
401+
*/
402+
template <class Calculator, class StructureManagers, class SparsePoints>
403+
std::string compute_sparse_kernel_local_neg_stress(const Calculator & calculator,
404+
SparseKernel & kernel,
405+
StructureManagers & managers,
406+
SparsePoints & sparse_points,
407+
math::Vector_t & weights) {
408+
using Manager_t = typename StructureManagers::Manager_t;
409+
using Property_t = typename Calculator::template Property_t<Manager_t>;
410+
using PropertyGradient_t =
411+
typename Calculator::template PropertyGradient_t<Manager_t>;
412+
auto && representation_name{calculator.get_name()};
413+
const auto representation_grad_name{calculator.get_gradient_name()};
414+
size_t n_centers{0};
415+
// find the total number of gradients
416+
for (const auto & manager : managers) {
417+
n_centers += manager->size();
418+
}
419+
420+
// Voigt order is xx, yy, zz, yz, xz, xy. To compute xx, yy, zz
421+
// and yz, xz, xy in one loop over the three spatial dimensions
422+
// dK/dr_{x,y,z}, we fill the off-diagonals yz, xz, xy by computing
423+
// xz, yx, zy exploiting the symmetry of the stress tensor
424+
// thus yx=xy and zx=xz
425+
// array accessed by voigt_idx and returns spatial_dim_idx
426+
const std::array<std::array<int, 2>, ThreeD> voigt_id_to_spatial_dim = {
427+
{ // voigt_idx, spatial_dim_idx
428+
{{4, 2}}, // xz, z
429+
{{5, 0}}, // xy, x
430+
{{3, 1}}}}; // yz, y
431+
432+
internal::Hash<math::Vector_t, double> hasher{};
433+
auto kernel_type_str = kernel.parameters.at("name").get<std::string>();
434+
std::string weight_hash = std::to_string(hasher(weights));
435+
std::string pair_grad_atom_i_r_j_name =
436+
std::string("kernel: ") + kernel_type_str + std::string(" ; ") +
437+
representation_grad_name +
438+
std::string(" partial gradients; weight_hash:") + weight_hash;
439+
std::string neg_stress_name =
440+
std::string("kernel: ") + kernel_type_str + std::string(" ; ") +
441+
representation_grad_name +
442+
std::string(" negative stress; weight_hash:") + weight_hash;
443+
444+
for (const auto & manager : managers) {
445+
if (kernel_type_str == "GAP") {
446+
const auto zeta = kernel.parameters.at("zeta").get<size_t>();
447+
448+
compute_partial_gradients_gap<Property_t, PropertyGradient_t>(
449+
manager, sparse_points, weights, zeta, representation_name,
450+
representation_grad_name, pair_grad_atom_i_r_j_name);
451+
}
452+
453+
auto && neg_stress{
454+
*manager->template get_property<Property<double, 0, Manager_t, 6>>(
455+
neg_stress_name, true, true, true)};
456+
if (neg_stress.is_updated()) {
457+
continue;
458+
}
459+
460+
neg_stress.resize();
461+
neg_stress.setZero();
462+
463+
auto && pair_grad_atom_i_r_j{*manager->template get_property<
464+
Property<double, 2, Manager_t, 1, ThreeD>>(pair_grad_atom_i_r_j_name,
465+
true)};
466+
for (auto center : manager) {
467+
Eigen::Vector3d r_i = center.get_position();
468+
// accumulate partial gradients onto gradients
469+
for (auto neigh : center.pairs_with_self_pair()) {
470+
Eigen::Vector3d r_ji = r_i - neigh.get_position();
471+
for (int i_der{0}; i_der < ThreeD; i_der++) {
472+
const auto & voigt = voigt_id_to_spatial_dim[i_der];
473+
neg_stress(i_der) +=
474+
r_ji(i_der) * pair_grad_atom_i_r_j[neigh](i_der);
475+
neg_stress(voigt[0]) +=
476+
r_ji(voigt[1]) * pair_grad_atom_i_r_j[neigh](i_der);
477+
}
478+
}
479+
}
480+
auto manager_root = extract_underlying_manager<0>(manager);
481+
json structure_copy = manager_root->get_atomic_structure();
482+
auto atomic_structure =
483+
structure_copy.template get<AtomicStructure<ThreeD>>();
484+
neg_stress[0] /= atomic_structure.get_volume();
485+
neg_stress.set_updated_status(true);
486+
} // manager
487+
return neg_stress_name;
488+
}
489+
490+
377491
} // namespace rascal
378492
#endif // SRC_RASCAL_MODELS_SPARSE_KERNEL_PREDICT_HH_

0 commit comments

Comments
 (0)