SIRIUS 7.5.0
Electronic structure library and applications
symmetrize_forces.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2023 Anton Kozhevnikov, Thomas Schulthess
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
5// the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8// following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10// and the following disclaimer in the documentation and/or other materials provided with the distribution.
11//
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
13// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
15// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
18// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20/** \file symmetrize_forces.hpp
21 *
22 * \brief Symmetrize atomic forces.
23 */
24
25#ifndef __SYMMETRIZE_FORCES_HPP__
26#define __SYMMETRIZE_FORCES_HPP__
27
28#include "crystal_symmetry.hpp"
29
30namespace sirius {
31
32inline void
33symmetrize_forces(Unit_cell const& uc__, sddk::mdarray<double, 2>& f__)
34{
35 auto& sym = uc__.symmetry();
36
37 if (sym.size() == 1) {
38 return;
39 }
40
41 sddk::mdarray<double, 2> sym_forces(3, uc__.spl_num_atoms().local_size());
42 sym_forces.zero();
43
44 for (int isym = 0; isym < sym.size(); isym++) {
45 auto const& Rc = sym[isym].spg_op.Rc;
46
47 for (int ia = 0; ia < uc__.num_atoms(); ia++) {
48 r3::vector<double> force_ia(&f__(0, ia));
49 int ja = sym[isym].spg_op.sym_atom[ia];
50 auto location = uc__.spl_num_atoms().location(typename atom_index_t::global(ja));
51 if (location.ib == uc__.comm().rank()) {
52 auto force_ja = dot(Rc, force_ia);
53 for (int x : {0, 1, 2}) {
54 sym_forces(x, location.index_local) += force_ja[x];
55 }
56 }
57 }
58 }
59
60 double alpha = 1.0 / double(sym.size());
61 for (int ia = 0; ia < uc__.spl_num_atoms().local_size(); ia++) {
62 for (int x: {0, 1, 2}) {
63 sym_forces(x, ia) *= alpha;
64 }
65 }
66 double* sbuf = uc__.spl_num_atoms().local_size() ? sym_forces.at(sddk::memory_t::host) : nullptr;
67 uc__.comm().allgather(sbuf, f__.at(sddk::memory_t::host), 3 * uc__.spl_num_atoms().local_size(),
68 3 * uc__.spl_num_atoms().global_offset());
69}
70
71}
72
73#endif
Contains definition and partial implementation of sirius::Crystal_symmetry class.
Namespace of the SIRIUS library.
Definition: sirius.f90:5