55 if (symmetry_operations.size() <= 1)
60 for (
int polarization_index_a = 0; polarization_index_a < 3; polarization_index_a++) {
61 for (
int polarization_index_b = 0; polarization_index_b < 3; polarization_index_b++) {
62 stress_matrix[polarization_index_a][polarization_index_b] =
67 for (
int polarization_index_a = 0; polarization_index_a < 3; polarization_index_a++) {
68 for (
int polarization_index_b = 0; polarization_index_b < 3; polarization_index_b++) {
70 stress_matrix[polarization_index_a][polarization_index_b];
75 symmetrize_contribution(contributions.
kinetic);
76 symmetrize_contribution(contributions.
hartree);
78 symmetrize_contribution(contributions.
ewald);
79 symmetrize_contribution(contributions.
local);
80 symmetrize_contribution(contributions.
nonlocal);
83 symmetrize_contribution(contributions.
hubbard);
84 symmetrize_contribution(contributions.
dispersion);
113 for (
int polarization_index_a = 0; polarization_index_a < 3; polarization_index_a++) {
114 for (
int polarization_index_b = 0; polarization_index_b < 3; polarization_index_b++) {
115 stress_tensor_result.
values[polarization_index_a][polarization_index_b] =
116 contributions.
kinetic[polarization_index_a][polarization_index_b] +
117 contributions.
hartree[polarization_index_a][polarization_index_b] +
119 contributions.
ewald[polarization_index_a][polarization_index_b] +
120 contributions.
local[polarization_index_a][polarization_index_b] +
121 contributions.
nonlocal[polarization_index_a][polarization_index_b] +
122 contributions.
core_correction[polarization_index_a][polarization_index_b] +
123 contributions.
hubbard[polarization_index_a][polarization_index_b] +
124 contributions.
dispersion[polarization_index_a][polarization_index_b];
129 (stress_tensor_result.
values[0][0] + stress_tensor_result.
values[1][1] +
130 stress_tensor_result.
values[2][2]) /
134 for (
int direction_a = 0; direction_a < 3; direction_a++) {
135 for (
int direction_b = 0; direction_b < 3; direction_b++) {
154 log::info(
" ┌──────────────────────────────────────────┐");
155 for (
int direction_a = 0; direction_a < 3; direction_a++) {
156 log::info(
" │ {:>12.2f} {:>12.2f} {:>12.2f} │",
157 stress_tensor_result.
values[direction_a][0],
158 stress_tensor_result.
values[direction_a][1],
159 stress_tensor_result.
values[direction_a][2]);
161 log::info(
" └──────────────────────────────────────────┘");
167 Real stress_pressure =
169 log::info(
" {:<12s}: {:>10.2f} {:>10.2f} {:>10.2f} (P={:.2f})",
176 print_contribution(
"kinetic", contributions.
kinetic);
177 print_contribution(
"Hartree", contributions.
hartree);
179 print_contribution(
"Ewald", contributions.
ewald);
180 print_contribution(
"local PP", contributions.
local);
181 print_contribution(
"nonlocal", contributions.
nonlocal);
184 print_contribution(
"augment", contributions.
augmentation);
186 print_contribution(
"DFT+U", contributions.
hubbard);
188 print_contribution(
"dispersion", contributions.
dispersion);
191 return stress_tensor_result;
212 const std::string& nonlocal_stress_derivative_method =
"analytical",
213 const std::string& dispersion_correction =
"none",
214 bool disable_symmetry =
false) {
222 auto timer_start = std::chrono::high_resolution_clock::now();
226 crystal_structure, planewave_basis, kpoint_grid, scf_state, contributions);
228 auto timer_kinetic = std::chrono::high_resolution_clock::now();
232 crystal_structure, planewave_basis, scf_state, contributions);
234 auto timer_hartree = std::chrono::high_resolution_clock::now();
239 auto timer_ewald = std::chrono::high_resolution_clock::now();
247 auto dispersion_calculator =
249 bool has_dispersion = dispersion_calculator->name() !=
"none";
250 Matrix3x3 dispersion_stress = dispersion_calculator->compute_gradients().stress;
251 for (
int direction_a = 0; direction_a < 3; direction_a++) {
252 for (
int direction_b = 0; direction_b < 3; direction_b++) {
253 contributions.
dispersion[direction_a][direction_b] =
254 dispersion_stress[direction_a][direction_b];
264 projector_overlap_coefficients,
266 nonlocal_stress_derivative_method);
267 pseudopotential_calculator.
compute();
268 auto timer_pseudo = std::chrono::high_resolution_clock::now();
284 auto reduce_within_pool = [&](
Real contribution[3][3]) {
285 std::vector<Real> flat(9);
286 for (
int row = 0; row < 3; ++row) {
287 for (
int column = 0; column < 3; ++column) {
288 flat[
static_cast<std::size_t
>(row * 3 + column)] = contribution[row][column];
292 for (
int row = 0; row < 3; ++row) {
293 for (
int column = 0; column < 3; ++column) {
294 contribution[row][column] = flat[
static_cast<std::size_t
>(row * 3 + column)];
298 auto reduce_across_pools = [&](
Real contribution[3][3]) {
299 std::vector<Real> flat(9);
300 for (
int row = 0; row < 3; ++row) {
301 for (
int column = 0; column < 3; ++column) {
302 flat[
static_cast<std::size_t
>(row * 3 + column)] = contribution[row][column];
306 for (
int row = 0; row < 3; ++row) {
307 for (
int column = 0; column < 3; ++column) {
308 contribution[row][column] = flat[
static_cast<std::size_t
>(row * 3 + column)];
317 reduce_within_pool(contributions.
kinetic);
318 reduce_within_pool(contributions.
hartree);
320 reduce_within_pool(contributions.
ewald);
321 reduce_within_pool(contributions.
local);
322 reduce_within_pool(contributions.
nonlocal);
325 reduce_within_pool(contributions.
hubbard);
331 reduce_across_pools(contributions.
kinetic);
332 reduce_across_pools(contributions.
nonlocal);
333 reduce_across_pools(contributions.
hubbard);
337 if (!disable_symmetry) {
342 has_ultrasoft, has_dispersion, !scf_state.
hubbard_manifolds.empty(), contributions);
346 std::chrono::duration<double, std::milli>(timer_kinetic - timer_start).count());
348 std::chrono::duration<double, std::milli>(timer_hartree - timer_kinetic).count());
350 std::chrono::duration<double, std::milli>(timer_ewald - timer_hartree).count());
352 std::chrono::duration<double, std::milli>(timer_pseudo - timer_ewald).count());
354 return {stress_tensor_result, contributions};