source: src/Potentials/Specifics/FourBodyPotential_Torsion.cpp@ 1155ba

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 1155ba was 1155ba, checked in by Frederik Heber <heber@…>, 8 years ago

Converted filterArguments... into faster filter, renamed other to ..ByBindingModel.

  • there are now two filters: One filters by list of particles types and is meant for simple pair potentials. The other one filters (and reorders) by the binding model. This takes more computation time but is required for more complex potentials.
  • TESTFIX: This allows morse and harmonic pair potentials tests to pass again, removed XFAIL from the corresponding regression tests.
  • Property mode set to 100644
File size: 10.6 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2013 Frederik Heber. All rights reserved.
5 * Please see the COPYING file or "Copyright notice" in builder.cpp for details.
6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24/*
25 * FourBodyPotential_Torsion.cpp
26 *
27 * Created on: Jul 08, 2013
28 * Author: heber
29 */
30
31
32// include config.h
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36
37#include "CodePatterns/MemDebug.hpp"
38
39#include "FourBodyPotential_Torsion.hpp"
40
41#include <boost/assign/list_of.hpp> // for 'map_list_of()'
42#include <boost/bind.hpp>
43#include <boost/lambda/lambda.hpp>
44#include <string>
45
46#include "CodePatterns/Assert.hpp"
47
48#include "FunctionApproximation/Extractors.hpp"
49#include "FunctionApproximation/TrainingData.hpp"
50#include "Potentials/helpers.hpp"
51#include "Potentials/InternalCoordinates/FourBody_TorsionAngle.hpp"
52#include "Potentials/ParticleTypeCheckers.hpp"
53#include "RandomNumbers/RandomNumberGeneratorFactory.hpp"
54#include "RandomNumbers/RandomNumberGenerator.hpp"
55
56class Fragment;
57
58// static definitions1
59const FourBodyPotential_Torsion::ParameterNames_t
60FourBodyPotential_Torsion::ParameterNames =
61 boost::assign::list_of<std::string>
62 ("spring_constant")
63 ("equilibrium_distance")
64 ;
65const std::string FourBodyPotential_Torsion::potential_token("torsion");
66Coordinator::ptr FourBodyPotential_Torsion::coordinator(Memory::ignore(new FourBody_TorsionAngle()));
67
68static BindingModel generateBindingModel(const EmpiricalPotential::ParticleTypes_t &_ParticleTypes)
69{
70 // fill nodes
71 BindingModel::vector_nodes_t nodes;
72 {
73 ASSERT( _ParticleTypes.size() == (size_t)4,
74 "generateBindingModel() - FourBodyPotential_Torsion needs four types.");
75 nodes.push_back( FragmentNode(_ParticleTypes[0], 1) );
76 nodes.push_back( FragmentNode(_ParticleTypes[1], 2) );
77 nodes.push_back( FragmentNode(_ParticleTypes[2], 2) );
78 nodes.push_back( FragmentNode(_ParticleTypes[3], 1) );
79 }
80
81 // there are no edges
82 HomologyGraph::edges_t edges;
83 {
84 std::pair<HomologyGraph::edges_t::iterator, bool > inserter;
85 inserter = edges.insert( std::make_pair( FragmentEdge(_ParticleTypes[0], _ParticleTypes[1]), 1) );
86 if (!inserter.second)
87 ++(inserter.first->second);
88 inserter = edges.insert( std::make_pair( FragmentEdge(_ParticleTypes[1], _ParticleTypes[2]), 1) );
89 if (!inserter.second)
90 ++(inserter.first->second);
91 inserter = edges.insert( std::make_pair( FragmentEdge(_ParticleTypes[2], _ParticleTypes[3]), 1) );
92 if (!inserter.second)
93 ++(inserter.first->second);
94 }
95
96 return BindingModel(nodes, edges);
97}
98
99FourBodyPotential_Torsion::FourBodyPotential_Torsion() :
100 EmpiricalPotential(),
101 params(parameters_t(MAXPARAMS, 0.)),
102 bindingmodel(BindingModel())
103{
104 // have some decent defaults for parameter_derivative checking
105 params[spring_constant] = 1.;
106 params[equilibrium_distance] = 0.1;
107}
108
109FourBodyPotential_Torsion::FourBodyPotential_Torsion(
110 const ParticleTypes_t &_ParticleTypes
111 ) :
112 EmpiricalPotential(_ParticleTypes),
113 params(parameters_t(MAXPARAMS, 0.)),
114 bindingmodel(generateBindingModel(_ParticleTypes))
115{
116 // have some decent defaults for parameter_derivative checking
117 params[spring_constant] = 1.;
118 params[equilibrium_distance] = 0.1;
119}
120
121FourBodyPotential_Torsion::FourBodyPotential_Torsion(
122 const ParticleTypes_t &_ParticleTypes,
123 const double _spring_constant,
124 const double _equilibrium_distance) :
125 EmpiricalPotential(_ParticleTypes),
126 params(parameters_t(MAXPARAMS, 0.)),
127 bindingmodel(generateBindingModel(_ParticleTypes))
128{
129 params[spring_constant] = _spring_constant;
130 params[equilibrium_distance] = _equilibrium_distance;
131}
132
133void FourBodyPotential_Torsion::setParameters(const parameters_t &_params)
134{
135 const size_t paramsDim = _params.size();
136 ASSERT( paramsDim <= getParameterDimension(),
137 "FourBodyPotential_Torsion::setParameters() - we need not more than "
138 +toString(getParameterDimension())+" parameters.");
139 for(size_t i=0;i<paramsDim;++i)
140 params[i] = _params[i];
141
142#ifndef NDEBUG
143 parameters_t check_params(getParameters());
144 check_params.resize(paramsDim); // truncate to same size
145 ASSERT( check_params == _params,
146 "FourBodyPotential_Torsion::setParameters() - failed, mismatch in to be set "
147 +toString(_params)+" and set "+toString(check_params)+" params.");
148#endif
149}
150
151FourBodyPotential_Torsion::result_t
152FourBodyPotential_Torsion::function_theta(
153 const double &r_ij,
154 const double &r_ik,
155 const double &r_il,
156 const double &r_jk,
157 const double &r_jl,
158 const double &r_kl
159 ) const
160{
161// Info info(__func__);
162 const double h_1 = .5*sqrt(2.*(Helpers::pow(r_ij,2)+Helpers::pow(r_ik,2))-Helpers::pow(r_jk,2));
163 const double h_2 = .5*sqrt(2.*(Helpers::pow(r_jl,2)+Helpers::pow(r_kl,2))-Helpers::pow(r_jk,2));
164 const double angle = Helpers::pow(h_1,2) + Helpers::pow(h_2,2) - Helpers::pow(r_il,2);
165 const double divisor = 2.* h_1 * h_2;
166
167// LOG(2, "DEBUG: cos(theta)= " << angle/divisor);
168 if (divisor == 0.)
169 return 0.;
170 else
171 return angle/divisor;
172}
173
174FourBodyPotential_Torsion::results_t
175FourBodyPotential_Torsion::operator()(
176 const list_of_arguments_t &listarguments
177 ) const
178{
179 result_t result = 0.;
180 for(list_of_arguments_t::const_iterator iter = listarguments.begin();
181 iter != listarguments.end(); ++iter) {
182 const arguments_t &arguments = *iter;
183 ASSERT( arguments.size() == getSpecificArgumentCount(),
184 "FourBodyPotential_Torsion::operator() - requires exactly three arguments.");
185 ASSERT( ParticleTypeChecker::checkArgumentsAgainstParticleTypes(
186 arguments, getParticleTypes()),
187 "FourBodyPotential_Torsion::operator() - types don't match with ones in arguments.");
188 const argument_t &r_ij = arguments[0]; // 01
189 const argument_t &r_ik = arguments[1]; // 02
190 const argument_t &r_il = arguments[2]; // 03
191 const argument_t &r_jk = arguments[3]; // 12
192 const argument_t &r_jl = arguments[4]; // 13
193 const argument_t &r_kl = arguments[5]; // 23
194 result +=
195 params[spring_constant]
196 * Helpers::pow( function_theta(r_ij.distance, r_ik.distance, r_il.distance, r_jk.distance, r_jl.distance, r_kl.distance)
197 - params[equilibrium_distance], 2 );
198 }
199 return results_t(1, result);
200}
201
202FourBodyPotential_Torsion::derivative_components_t
203FourBodyPotential_Torsion::derivative(
204 const list_of_arguments_t &listarguments
205 ) const
206{
207 result_t result = 0.;
208 for(list_of_arguments_t::const_iterator iter = listarguments.begin();
209 iter != listarguments.end(); ++iter) {
210 const arguments_t &arguments = *iter;
211 ASSERT( arguments.size() == getSpecificArgumentCount(),
212 "FourBodyPotential_Torsion::operator() - requires exactly three arguments.");
213 ASSERT( ParticleTypeChecker::checkArgumentsAgainstParticleTypes(
214 arguments, getParticleTypes()),
215 "FourBodyPotential_Torsion::operator() - types don't match with ones in arguments.");
216 const argument_t &r_ij = arguments[0]; // 01
217 const argument_t &r_ik = arguments[1]; // 02
218 const argument_t &r_il = arguments[2]; // 03
219 const argument_t &r_jk = arguments[3]; // 12
220 const argument_t &r_jl = arguments[4]; // 13
221 const argument_t &r_kl = arguments[5]; // 23
222 result +=
223 2. * params[spring_constant] *
224 ( function_theta(r_ij.distance, r_ik.distance, r_il.distance, r_jk.distance, r_jl.distance, r_kl.distance)
225 - params[equilibrium_distance]);
226 }
227 return derivative_components_t(1, result);
228}
229
230FourBodyPotential_Torsion::results_t
231FourBodyPotential_Torsion::parameter_derivative(
232 const list_of_arguments_t &listarguments,
233 const size_t index
234 ) const
235{
236 result_t result = 0.;
237 for(list_of_arguments_t::const_iterator iter = listarguments.begin();
238 iter != listarguments.end(); ++iter) {
239 const arguments_t &arguments = *iter;
240 ASSERT( arguments.size() == getSpecificArgumentCount(),
241 "FourBodyPotential_Torsion::parameter_derivative() - requires exactly three arguments.");
242 ASSERT( ParticleTypeChecker::checkArgumentsAgainstParticleTypes(
243 arguments, getParticleTypes()),
244 "FourBodyPotential_Torsion::operator() - types don't match with ones in arguments.");
245 const argument_t &r_ij = arguments[0]; // 01
246 const argument_t &r_ik = arguments[1]; // 02
247 const argument_t &r_il = arguments[2]; // 03
248 const argument_t &r_jk = arguments[3]; // 12
249 const argument_t &r_jl = arguments[4]; // 13
250 const argument_t &r_kl = arguments[5]; // 23
251 switch (index) {
252 case spring_constant:
253 {
254 result +=
255 Helpers::pow( function_theta(r_ij.distance, r_ik.distance, r_il.distance, r_jk.distance, r_jl.distance, r_kl.distance) - params[equilibrium_distance], 2 );
256 break;
257 }
258 case equilibrium_distance:
259 {
260 result +=
261 -2. * params[spring_constant]
262 * ( function_theta(r_ij.distance, r_ik.distance, r_il.distance, r_jk.distance, r_jl.distance, r_kl.distance) - params[equilibrium_distance]);
263 break;
264 }
265 default:
266 ASSERT(0, "FourBodyPotential_Torsion::parameter_derivative() - derivative to unknown parameter desired.");
267 break;
268 }
269 }
270 return results_t(1, result);
271}
272
273FunctionModel::filter_t
274FourBodyPotential_Torsion::getSpecificFilter() const
275{
276 FunctionModel::filter_t returnfunction =
277 boost::bind(&Extractors::filterArgumentsByBindingModel,
278 _2, _1,
279 boost::cref(getParticleTypes()), boost::cref(getBindingModel())
280 );
281 return returnfunction;
282}
283
284void
285FourBodyPotential_Torsion::setParametersToRandomInitialValues(
286 const TrainingData &data)
287{
288 RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();
289 const double rng_min = random.min();
290 const double rng_max = random.max();
291 params[FourBodyPotential_Torsion::spring_constant] = 2.*(random()/(rng_max-rng_min));
292 params[FourBodyPotential_Torsion::equilibrium_distance] = 2.*(random()/(rng_max-rng_min));
293}
294
Note: See TracBrowser for help on using the repository browser.