source: src/Potentials/Specifics/ThreeBodyPotential_Angle.cpp@ 67044a

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 67044a was 67044a, checked in by Frederik Heber <heber@…>, 8 years ago

Extractors require additional binding model which EmpiricalPotentials supply in getSpecificFilter().

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