2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2020, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Implements nblib particle-types interactions
39 * \author Victor Holanda <victor.holanda@cscs.ch>
40 * \author Joe Jordan <ejjordan@kth.se>
41 * \author Prashanth Kanduri <kanduri@cscs.ch>
42 * \author Sebastian Keller <keller@cscs.ch>
43 * \author Artem Zhmurov <zhmurov@gmail.com>
48 #include "nblib/exception.h"
49 #include "nblib/interactions.h"
50 #include "nblib/util/internal.h"
55 C6 NonBondedInteractionMap::getC6(const ParticleTypeName& first, const ParticleTypeName& second) const
57 return std::get<0>(interactionMap_.at(std::make_tuple(first, second)));
60 C12 NonBondedInteractionMap::getC12(const ParticleTypeName& first, const ParticleTypeName& second) const
62 return std::get<1>(interactionMap_.at(std::make_tuple(first, second)));
65 void NonBondedInteractionMap::setInteractions(const ParticleTypeName& first,
66 const ParticleTypeName& second,
70 auto interactionKey = std::make_tuple(first, second);
71 interactionMap_[interactionKey] = std::make_tuple(c6_combo, c12_combo);
74 size_t NonBondedInteractionMap::count(const NonBondedInteractionMap::NamePairTuple& namePairTuple)
76 return interactionMap_.count(namePairTuple);
82 //! Combines the non-bonded parameters from two particles for pairwise interactions
83 real combineNonbondedParameters(real v, real w, CombinationRule combinationRule)
85 if (combinationRule == CombinationRule::Geometric)
87 return std::sqrt(v * w);
91 throw InputException("unknown LJ Combination rule specified\n");
97 ParticleTypesInteractions::ParticleTypesInteractions(CombinationRule cr) : combinationRule_(cr) {}
99 ParticleTypesInteractions& ParticleTypesInteractions::add(const ParticleTypeName& particleTypeName,
103 auto insertLocation = singleParticleInteractionsMap_.insert(
104 std::make_pair(particleTypeName, std::make_tuple(c6, c12)));
106 if (!insertLocation.second) // if particleTypeName already existed
108 if (std::get<0>(insertLocation.first->second) != c6
109 || std::get<1>(insertLocation.first->second) != c12)
111 std::string message = formatString(
112 "Attempting to add nonbonded interaction parameters for particle "
114 particleTypeName.value());
115 throw InputException(message);
121 ParticleTypesInteractions& ParticleTypesInteractions::add(const ParticleTypeName& particleTypeName1,
122 const ParticleTypeName& particleTypeName2,
126 auto interactionKey = std::make_tuple(particleTypeName1, particleTypeName2);
127 auto possibleInteractionKey = std::make_tuple(particleTypeName2, particleTypeName1);
129 auto insertLocation = twoParticlesInteractionsMap_.insert(
130 std::make_pair(interactionKey, std::make_tuple(c6, c12)));
131 twoParticlesInteractionsMap_.insert(std::make_pair(possibleInteractionKey, std::make_tuple(c6, c12)));
133 if (!insertLocation.second) // if particleTypeName already existed
135 if (std::get<0>(insertLocation.first->second) != c6
136 || std::get<1>(insertLocation.first->second) != c12)
138 std::string message = formatString(
139 "Attempting to add nonbonded interaction parameters between the particle types "
141 particleTypeName1.value(),
142 particleTypeName2.value());
143 throw InputException(message);
149 NonBondedInteractionMap ParticleTypesInteractions::generateTable() const
151 NonBondedInteractionMap nonbondedParameters_;
153 // creating the combination rule based interaction matrix
154 for (const auto& particleType1 : singleParticleInteractionsMap_)
156 C6 c6_1 = std::get<0>(particleType1.second);
157 C12 c12_1 = std::get<1>(particleType1.second);
159 for (const auto& particleType2 : singleParticleInteractionsMap_)
161 C6 c6_2 = std::get<0>(particleType2.second);
162 C12 c12_2 = std::get<1>(particleType2.second);
164 C6 c6_combo{ combineNonbondedParameters(c6_1, c6_2, combinationRule_) };
165 C12 c12_combo{ combineNonbondedParameters(c12_1, c12_2, combinationRule_) };
167 nonbondedParameters_.setInteractions(
168 particleType1.first, particleType2.first, c6_combo, c12_combo);
172 // updating the interaction matrix based on the user fine tuned parameters
173 for (const auto& particleTypeTuple : twoParticlesInteractionsMap_)
175 const auto& first = std::get<0>(particleTypeTuple.first);
176 const auto& second = std::get<1>(particleTypeTuple.first);
178 C6 c6_combo = std::get<0>(particleTypeTuple.second);
179 C12 c12_combo = std::get<1>(particleTypeTuple.second);
181 nonbondedParameters_.setInteractions(first, second, c6_combo, c12_combo);
184 std::set<ParticleTypeName> particleTypes;
185 for (auto const& typeKey : nonbondedParameters_)
186 { // we don't need to get<1> because the list is guaranteed to be symmetric
187 particleTypes.insert(std::get<0>(typeKey.first));
190 // check whether there is any missing interaction
191 for (const ParticleTypeName& particleTypeName1 : particleTypes)
193 for (const ParticleTypeName& particleTypeName2 : particleTypes)
195 auto interactionKey = std::make_tuple(particleTypeName1, particleTypeName2);
196 if (nonbondedParameters_.count(interactionKey) == 0)
198 std::string message = formatString("Missing interaction between {} {}",
199 particleTypeName1.value(),
200 particleTypeName2.value());
201 throw InputException(message);
205 return nonbondedParameters_;
208 CombinationRule ParticleTypesInteractions::getCombinationRule() const
210 return combinationRule_;
213 void ParticleTypesInteractions::merge(const ParticleTypesInteractions& other)
215 for (const auto& keyval : other.singleParticleInteractionsMap_)
217 add(keyval.first, std::get<0>(keyval.second), std::get<1>(keyval.second));
220 for (const auto& keyval : other.twoParticlesInteractionsMap_)
222 add(std::get<0>(keyval.first),
223 std::get<1>(keyval.first),
224 std::get<0>(keyval.second),
225 std::get<1>(keyval.second));