source: src/Potentials/Specifics/SaturationPotential.cpp@ caa00e9

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing 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_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since caa00e9 was dbf8c8, checked in by Frederik Heber <heber@…>, 12 years ago

FIX: Now default parameters are present for every potential and used for check_derivatives.

  • checking derivatives with exp() is numerically very unstable as large numbers may easily occur. Hence, rather check the derivatives at some fixed but nicely behaved spot that is probably not the minimum.
  • Property mode set to 100644
File size: 10.5 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2012 University of Bonn. 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 * SaturationPotential.cpp
26 *
27 * Created on: Oct 11, 2012
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 "SaturationPotential.hpp"
40
41#include <boost/assign.hpp>
42#include <boost/assign/list_of.hpp> // for 'map_list_of()'
43#include <iostream>
44#include <string>
45
46#include "CodePatterns/Assert.hpp"
47#include "CodePatterns/Log.hpp"
48
49#include "Potentials/helpers.hpp"
50#include "Potentials/ParticleTypeCheckers.hpp"
51
52using namespace boost::assign;
53
54// static definitions
55const SaturationPotential::ParameterNames_t
56SaturationPotential::ParameterNames =
57 boost::assign::list_of<std::string>
58 ("all_energy_offset")
59 ("")
60 ("")
61 ("")
62 ("")
63 ("")
64 ;
65const std::string SaturationPotential::potential_token("saturation");
66
67SaturationPotential::SaturationPotential(
68 const ParticleTypes_t &_ParticleTypes,
69 const double _saturation_cutoff,
70 boost::function< std::vector<arguments_t>(const argument_t &, const double)> &_triplefunction) :
71 SerializablePotential(_ParticleTypes),
72 morse(_ParticleTypes),
73 angle(symmetrizeTypes(_ParticleTypes)),
74 energy_offset(0.),
75 triplefunction(_triplefunction),
76 saturation_cutoff(_saturation_cutoff)
77{}
78
79SaturationPotential::SaturationPotential(
80 const ParticleTypes_t &_ParticleTypes,
81 const double _all_energy_offset,
82 const double _morse_spring_constant,
83 const double _morse_equilibrium_distance,
84 const double _morse_dissociation_energy,
85 const double _angle_spring_constant,
86 const double _angle_equilibrium_distance,
87 const double _saturation_cutoff,
88 boost::function< std::vector<arguments_t>(const argument_t &, const double)> &_triplefunction) :
89 SerializablePotential(_ParticleTypes),
90 morse(_ParticleTypes),
91 angle(symmetrizeTypes(_ParticleTypes)),
92 energy_offset(_all_energy_offset),
93 triplefunction(_triplefunction),
94 saturation_cutoff(_saturation_cutoff)
95{
96 parameters_t morse_params(morse.getParameterDimension());
97 morse_params[PairPotential_Morse::spring_constant] = _morse_spring_constant;
98 morse_params[PairPotential_Morse::equilibrium_distance] = _morse_equilibrium_distance;
99 morse_params[PairPotential_Morse::dissociation_energy] = _morse_dissociation_energy;
100 morse_params[PairPotential_Morse::energy_offset] = 0.;
101 morse.setParameters(morse_params);
102 parameters_t angle_params(angle.getParameterDimension());
103 angle_params[PairPotential_Angle::spring_constant] = _angle_spring_constant;
104 angle_params[PairPotential_Angle::equilibrium_distance] = _angle_equilibrium_distance;
105 angle_params[PairPotential_Angle::energy_offset] = 0.;
106 angle.setParameters(angle_params);
107}
108
109void SaturationPotential::setParameters(const parameters_t &_params)
110{
111 const size_t paramsDim = _params.size();
112 ASSERT( paramsDim <= getParameterDimension(),
113 "SaturationPotential::setParameters() - we need not more than "
114 +toString(getParameterDimension())+" parameters.");
115// LOG(1, "INFO: Setting new SaturationPotential params: " << _params);
116
117
118 // offsets
119 if (paramsDim > all_energy_offset)
120 energy_offset = _params[all_energy_offset];
121
122 // Morse
123 {
124 parameters_t morse_params(morse.getParameters());
125 if (paramsDim > morse_spring_constant)
126 morse_params[PairPotential_Morse::spring_constant] = _params[morse_spring_constant];
127 if (paramsDim > morse_equilibrium_distance)
128 morse_params[PairPotential_Morse::equilibrium_distance] = _params[morse_equilibrium_distance];
129 if (paramsDim > morse_dissociation_energy)
130 morse_params[PairPotential_Morse::dissociation_energy] = _params[morse_dissociation_energy];
131 morse_params[PairPotential_Morse::energy_offset] = 0.;
132 morse.setParameters(morse_params);
133 }
134
135 // Angle
136 {
137 parameters_t angle_params(angle.getParameters());
138 if (paramsDim > angle_spring_constant)
139 angle_params[PairPotential_Angle::spring_constant] = _params[angle_spring_constant];
140 if (paramsDim > angle_equilibrium_distance)
141 angle_params[PairPotential_Angle::equilibrium_distance] = _params[angle_equilibrium_distance];
142 angle_params[PairPotential_Angle::energy_offset] = 0.;
143 angle.setParameters(angle_params);
144 }
145#ifndef NDEBUG
146 parameters_t check_params(getParameters());
147 check_params.resize(paramsDim); // truncate to same size
148 ASSERT( check_params == _params,
149 "SaturationPotential::setParameters() - failed, mismatch in to be set "
150 +toString(_params)+" and set "+toString(check_params)+" params.");
151#endif
152}
153
154SaturationPotential::parameters_t SaturationPotential::getParameters() const
155{
156 parameters_t params(getParameterDimension());
157 const parameters_t morse_params = morse.getParameters();
158 const parameters_t angle_params = angle.getParameters();
159
160 params[all_energy_offset] = energy_offset;
161
162 params[morse_spring_constant] = morse_params[PairPotential_Morse::spring_constant];
163 params[morse_equilibrium_distance] = morse_params[PairPotential_Morse::equilibrium_distance];
164 params[morse_dissociation_energy] = morse_params[PairPotential_Morse::dissociation_energy];
165
166 params[angle_spring_constant] = angle_params[PairPotential_Angle::spring_constant];
167 params[angle_equilibrium_distance] = angle_params[PairPotential_Angle::equilibrium_distance];
168 return params;
169}
170
171SaturationPotential::results_t
172SaturationPotential::operator()(
173 const arguments_t &arguments
174 ) const
175{
176 double result = 0.;
177 const ParticleTypes_t &morse_types = morse.getParticleTypes();
178 for(arguments_t::const_iterator argiter = arguments.begin();
179 argiter != arguments.end();
180 ++argiter) {
181 const argument_t &r_ij = *argiter;
182 if (((r_ij.types.first == morse_types[0]) && (r_ij.types.second == morse_types[1]))
183 || ((r_ij.types.first == morse_types[1]) && (r_ij.types.second == morse_types[0]))) {
184 arguments_t args(1, r_ij);
185
186 // Morse contribution
187 const double tmp = morse(args)[0];
188// LOG(2, "DEBUG: Morse yields " << tmp << " for << " << r_ij << ".");
189 result += tmp;
190 if (result != result)
191 ELOG(1, "result is NAN.");
192 }
193 }
194 {
195 // Angle contribution
196 const double tmp = angle(arguments)[0]; // as we have all distances we get both jk and kj
197// LOG(2, "DEBUG: angle yields " << tmp << " for << " << arguments << ".");
198 result += tmp;
199 if (result != result)
200 ELOG(1, "result is NAN.");
201 }
202 return std::vector<result_t>(1, energy_offset + result);
203}
204
205SaturationPotential::derivative_components_t
206SaturationPotential::derivative(
207 const arguments_t &arguments
208 ) const
209{
210 ASSERT( 0,
211 "SaturationPotential::operator() - not implemented.");
212 derivative_components_t result;
213 return result;
214}
215
216SaturationPotential::results_t
217SaturationPotential::parameter_derivative(
218 const arguments_t &arguments,
219 const size_t index
220 ) const
221{
222 double result = 0.;
223 switch (index) {
224 case all_energy_offset:
225 {
226 result = 1.;
227 break;
228 }
229 case morse_spring_constant:
230 case morse_equilibrium_distance:
231 case morse_dissociation_energy:
232 {
233 const ParticleTypes_t &morse_types = morse.getParticleTypes();
234 for(arguments_t::const_iterator argiter = arguments.begin();
235 argiter != arguments.end();
236 ++argiter) {
237 const argument_t &r_ij = *argiter;
238 if (((r_ij.types.first == morse_types[0]) && (r_ij.types.second == morse_types[1]))
239 || ((r_ij.types.first == morse_types[1]) && (r_ij.types.second == morse_types[0]))) {
240 arguments_t args(1, r_ij);
241 switch (index) {
242 case morse_spring_constant:
243 result += morse.parameter_derivative(args, PairPotential_Morse::spring_constant)[0];
244 break;
245 case morse_equilibrium_distance:
246 result += morse.parameter_derivative(args, PairPotential_Morse::equilibrium_distance)[0];
247 break;
248 case morse_dissociation_energy:
249 result += morse.parameter_derivative(args, PairPotential_Morse::dissociation_energy)[0];
250 break;
251 default:
252 ASSERT( 0, "SaturationPotential::parameter_derivative() - impossible to get here.");
253 break;
254 }
255 }
256 }
257 break;
258 }
259 case angle_spring_constant:
260 {
261 result = angle.parameter_derivative(arguments, PairPotential_Angle::spring_constant)[0];
262 break;
263 }
264 case angle_equilibrium_distance:
265 {
266 result = angle.parameter_derivative(arguments, PairPotential_Angle::equilibrium_distance)[0];
267 break;
268 }
269 default:
270 ELOG(1, "SaturationPotential::parameter_derivative() - index " << index << " invalid.");
271 break;
272 }
273 return SaturationPotential::results_t(1, result);
274}
275
276const SaturationPotential::ParticleTypes_t
277SaturationPotential::symmetrizeTypes(const ParticleTypes_t &_ParticleTypes)
278{
279 ASSERT( _ParticleTypes.size() == (size_t)2,
280 "SaturationPotential::symmetrizeTypes() - require initial _ParticleTypes with two elements.");
281// // insert before couple
282// ParticleTypes_t types(1, _ParticleTypes[1]);
283// types.insert(types.end(), _ParticleTypes.begin(), _ParticleTypes.end());
284 // insert after the couple
285 ParticleTypes_t types(_ParticleTypes);
286 types.push_back( _ParticleTypes.back() );
287 ASSERT( types.size() == (size_t)3,
288 "SaturationPotential::symmetrizeTypes() - failed to generate three types for angle.");
289 return types;
290}
291
292std::ostream& operator<<(std::ostream &ost, const SaturationPotential &potential)
293{
294 ost << potential.morse;
295 ost << potential.angle;
296 return ost;
297}
298
299std::istream& operator>>(std::istream &ist, SaturationPotential &potential)
300{
301 ist >> potential.morse;
302 ist >> potential.angle;
303 return ist;
304}
Note: See TracBrowser for help on using the repository browser.