source: src/Potentials/Specifics/SaturationPotential.cpp@ 7b019a

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 Candidate_v1.7.0 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 7b019a was 7b019a, checked in by Frederik Heber <heber@…>, 13 years ago

Extended FunctionModel by getFragmentSpecificExtractor() definition.

  • shifted extractor_t from TrainingData to FunctionModel.
  • implemented function for every specific potential.
  • this is preparatory for generalizing function approximation in LevMartester.
  • we make use of the newly introduced extractors in the potentials and the required number of charges is ASSERT'd.
  • Property mode set to 100644
File size: 13.4 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 "FunctionApproximation/Extractors.hpp"
50#include "Potentials/helpers.hpp"
51#include "Potentials/ParticleTypeCheckers.hpp"
52
53class Fragment;
54
55using namespace boost::assign;
56
57// static definitions
58const SaturationPotential::ParameterNames_t
59SaturationPotential::ParameterNames =
60 boost::assign::list_of<std::string>
61 ("all_energy_offset")
62 ("")
63 ("")
64 ("")
65 ("")
66 ("")
67 ;
68const std::string SaturationPotential::potential_token("saturation");
69
70SaturationPotential::SaturationPotential(
71 const ParticleTypes_t &_ParticleTypes,
72 const double _saturation_cutoff,
73 boost::function< std::vector<arguments_t>(const argument_t &, const double)> &_triplefunction) :
74 SerializablePotential(_ParticleTypes),
75 morse(_ParticleTypes),
76 angle(symmetrizeTypes(_ParticleTypes)),
77 energy_offset(0.),
78 triplefunction(_triplefunction),
79 saturation_cutoff(_saturation_cutoff)
80{
81 // have some decent defaults for parameter_derivative checking
82 // Morse and Angle have their own defaults, offset is set
83 ASSERT( _ParticleTypes.size() == (size_t)2,
84 "SaturationPotential::SaturationPotential() - exactly two types must be given.");
85 ASSERT( _ParticleTypes[1] == 1,
86 "SaturationPotential::SaturationPotential() - second type must be hydrogen.");
87}
88
89SaturationPotential::SaturationPotential(
90 const ParticleTypes_t &_ParticleTypes,
91 const double _all_energy_offset,
92 const double _morse_spring_constant,
93 const double _morse_equilibrium_distance,
94 const double _morse_dissociation_energy,
95 const double _angle_spring_constant,
96 const double _angle_equilibrium_distance,
97 const double _saturation_cutoff,
98 boost::function< std::vector<arguments_t>(const argument_t &, const double)> &_triplefunction) :
99 SerializablePotential(_ParticleTypes),
100 morse(_ParticleTypes),
101 angle(symmetrizeTypes(_ParticleTypes)),
102 energy_offset(_all_energy_offset),
103 triplefunction(_triplefunction),
104 saturation_cutoff(_saturation_cutoff)
105{
106 ASSERT( _ParticleTypes.size() == (size_t)2,
107 "SaturationPotential::SaturationPotential() - exactly two types must be given.");
108 ASSERT( _ParticleTypes[1] == 1,
109 "SaturationPotential::SaturationPotential() - second type must be hydrogen.");
110 parameters_t morse_params(morse.getParameterDimension());
111 morse_params[PairPotential_Morse::spring_constant] = _morse_spring_constant;
112 morse_params[PairPotential_Morse::equilibrium_distance] = _morse_equilibrium_distance;
113 morse_params[PairPotential_Morse::dissociation_energy] = _morse_dissociation_energy;
114 morse_params[PairPotential_Morse::energy_offset] = 0.;
115 morse.setParameters(morse_params);
116 parameters_t angle_params(angle.getParameterDimension());
117 angle_params[PairPotential_Angle::spring_constant] = _angle_spring_constant;
118 angle_params[PairPotential_Angle::equilibrium_distance] = _angle_equilibrium_distance;
119 angle_params[PairPotential_Angle::energy_offset] = 0.;
120 angle.setParameters(angle_params);
121}
122
123void SaturationPotential::setParameters(const parameters_t &_params)
124{
125 const size_t paramsDim = _params.size();
126 ASSERT( paramsDim <= getParameterDimension(),
127 "SaturationPotential::setParameters() - we need not more than "
128 +toString(getParameterDimension())+" parameters.");
129// LOG(1, "INFO: Setting new SaturationPotential params: " << _params);
130
131
132 // offsets
133 if (paramsDim > all_energy_offset)
134 energy_offset = _params[all_energy_offset];
135
136 // Morse
137 {
138 parameters_t morse_params(morse.getParameters());
139 if (paramsDim > morse_spring_constant)
140 morse_params[PairPotential_Morse::spring_constant] = _params[morse_spring_constant];
141 if (paramsDim > morse_equilibrium_distance)
142 morse_params[PairPotential_Morse::equilibrium_distance] = _params[morse_equilibrium_distance];
143 if (paramsDim > morse_dissociation_energy)
144 morse_params[PairPotential_Morse::dissociation_energy] = _params[morse_dissociation_energy];
145 morse_params[PairPotential_Morse::energy_offset] = 0.;
146 morse.setParameters(morse_params);
147 }
148
149 // Angle
150 {
151 parameters_t angle_params(angle.getParameters());
152 if (paramsDim > angle_spring_constant)
153 angle_params[PairPotential_Angle::spring_constant] = _params[angle_spring_constant];
154 if (paramsDim > angle_equilibrium_distance)
155 angle_params[PairPotential_Angle::equilibrium_distance] = _params[angle_equilibrium_distance];
156 angle_params[PairPotential_Angle::energy_offset] = 0.;
157 angle.setParameters(angle_params);
158 }
159#ifndef NDEBUG
160 parameters_t check_params(getParameters());
161 check_params.resize(paramsDim); // truncate to same size
162 ASSERT( check_params == _params,
163 "SaturationPotential::setParameters() - failed, mismatch in to be set "
164 +toString(_params)+" and set "+toString(check_params)+" params.");
165#endif
166}
167
168SaturationPotential::parameters_t SaturationPotential::getParameters() const
169{
170 parameters_t params(getParameterDimension());
171 const parameters_t morse_params = morse.getParameters();
172 const parameters_t angle_params = angle.getParameters();
173
174 params[all_energy_offset] = energy_offset;
175
176 params[morse_spring_constant] = morse_params[PairPotential_Morse::spring_constant];
177 params[morse_equilibrium_distance] = morse_params[PairPotential_Morse::equilibrium_distance];
178 params[morse_dissociation_energy] = morse_params[PairPotential_Morse::dissociation_energy];
179
180 params[angle_spring_constant] = angle_params[PairPotential_Angle::spring_constant];
181 params[angle_equilibrium_distance] = angle_params[PairPotential_Angle::equilibrium_distance];
182 return params;
183}
184
185SaturationPotential::results_t
186SaturationPotential::operator()(
187 const arguments_t &arguments
188 ) const
189{
190 double result = 0.;
191 const ParticleTypes_t &morse_types = morse.getParticleTypes();
192 for(arguments_t::const_iterator argiter = arguments.begin();
193 argiter != arguments.end();
194 ++argiter) {
195 const argument_t &r_ij = *argiter;
196 if (((r_ij.types.first == morse_types[0]) && (r_ij.types.second == morse_types[1]))
197 || ((r_ij.types.first == morse_types[1]) && (r_ij.types.second == morse_types[0]))) {
198 arguments_t args(1, r_ij);
199
200 // Morse contribution
201 const double tmp = morse(args)[0];
202// LOG(2, "DEBUG: Morse yields " << tmp << " for << " << r_ij << ".");
203 result += tmp;
204 if (result != result)
205 ELOG(1, "result is NAN.");
206 }
207 }
208 {
209 // Angle contribution
210 const double tmp = angle(arguments)[0]; // as we have all distances we get both jk and kj
211// LOG(2, "DEBUG: angle yields " << tmp << " for << " << arguments << ".");
212 result += tmp;
213 if (result != result)
214 ELOG(1, "result is NAN.");
215 }
216 return std::vector<result_t>(1, energy_offset + result);
217}
218
219SaturationPotential::derivative_components_t
220SaturationPotential::derivative(
221 const arguments_t &arguments
222 ) const
223{
224 ASSERT( 0,
225 "SaturationPotential::operator() - not implemented.");
226 derivative_components_t result;
227 return result;
228}
229
230SaturationPotential::results_t
231SaturationPotential::parameter_derivative(
232 const arguments_t &arguments,
233 const size_t index
234 ) const
235{
236 double result = 0.;
237 switch (index) {
238 case all_energy_offset:
239 {
240 result = 1.;
241 break;
242 }
243 case morse_spring_constant:
244 case morse_equilibrium_distance:
245 case morse_dissociation_energy:
246 {
247 const ParticleTypes_t &morse_types = morse.getParticleTypes();
248 for(arguments_t::const_iterator argiter = arguments.begin();
249 argiter != arguments.end();
250 ++argiter) {
251 const argument_t &r_ij = *argiter;
252 if (((r_ij.types.first == morse_types[0]) && (r_ij.types.second == morse_types[1]))
253 || ((r_ij.types.first == morse_types[1]) && (r_ij.types.second == morse_types[0]))) {
254 arguments_t args(1, r_ij);
255 switch (index) {
256 case morse_spring_constant:
257 result += morse.parameter_derivative(args, PairPotential_Morse::spring_constant)[0];
258 break;
259 case morse_equilibrium_distance:
260 result += morse.parameter_derivative(args, PairPotential_Morse::equilibrium_distance)[0];
261 break;
262 case morse_dissociation_energy:
263 result += morse.parameter_derivative(args, PairPotential_Morse::dissociation_energy)[0];
264 break;
265 default:
266 ASSERT( 0, "SaturationPotential::parameter_derivative() - impossible to get here.");
267 break;
268 }
269 }
270 }
271 break;
272 }
273 case angle_spring_constant:
274 {
275 result = angle.parameter_derivative(arguments, PairPotential_Angle::spring_constant)[0];
276 break;
277 }
278 case angle_equilibrium_distance:
279 {
280 result = angle.parameter_derivative(arguments, PairPotential_Angle::equilibrium_distance)[0];
281 break;
282 }
283 default:
284 ELOG(1, "SaturationPotential::parameter_derivative() - index " << index << " invalid.");
285 break;
286 }
287 return SaturationPotential::results_t(1, result);
288}
289
290const SaturationPotential::ParticleTypes_t
291SaturationPotential::symmetrizeTypes(const ParticleTypes_t &_ParticleTypes)
292{
293 ASSERT( _ParticleTypes.size() == (size_t)2,
294 "SaturationPotential::symmetrizeTypes() - require initial _ParticleTypes with two elements.");
295// // insert before couple
296// ParticleTypes_t types(1, _ParticleTypes[1]);
297// types.insert(types.end(), _ParticleTypes.begin(), _ParticleTypes.end());
298 // insert after the couple
299 ParticleTypes_t types(_ParticleTypes);
300 types.push_back( _ParticleTypes.back() );
301 ASSERT( types.size() == (size_t)3,
302 "SaturationPotential::symmetrizeTypes() - failed to generate three types for angle.");
303 return types;
304}
305
306std::ostream& operator<<(std::ostream &ost, const SaturationPotential &potential)
307{
308 ost << potential.morse;
309 ost << potential.angle;
310 return ost;
311}
312
313std::istream& operator>>(std::istream &ist, SaturationPotential &potential)
314{
315 ist >> potential.morse;
316 ist >> potential.angle;
317 return ist;
318}
319
320FunctionModel::extractor_t
321SaturationPotential::getFragmentSpecificExtractor(
322 const charges_t &charges) const
323{
324 ASSERT(charges.size() == (size_t)2,
325 "SaturationPotential::getFragmentSpecificExtractor() - requires 2 charges.");
326 FunctionModel::extractor_t returnfunction;
327 if (charges[0] == charges[1]) {
328 // In case both types are equal there is only a single pair of possible
329 // type combinations.
330 returnfunction =
331 boost::bind(&Extractors::gatherAllDistancesFromFragment,
332 boost::bind(&Fragment::getPositions, _1),
333 boost::bind(&Fragment::getCharges, _1),
334 boost::cref(charges),
335 _2);
336 } else {
337 // we have to chain here a rather complex "tree" of functions
338 // as we only have a couple of ParticleTypes but need to get
339 // all possible three pairs of the set of the two types.
340 // Finally, we also need to arrange them in correct order
341 // (for PairPotentiale_Angle).
342 charges_t firstpair(2, boost::cref(charges[0]));
343 charges_t secondpair(2, boost::cref(charges[1]));
344 const charges_t &thirdpair = charges;
345 returnfunction =
346 boost::bind(&Extractors::reorderArgumentsByParticleTypes,
347 boost::bind(&Extractors::combineArguments,
348 boost::bind(&Extractors::combineArguments,
349 boost::bind(&Extractors::gatherAllDistancesFromFragment,
350 boost::bind(&Fragment::getPositions, _1),
351 boost::bind(&Fragment::getCharges, _1),
352 firstpair, // no crefs here as are temporaries!
353 _2),
354 boost::bind(&Extractors::gatherAllDistancesFromFragment,
355 boost::bind(&Fragment::getPositions, _1),
356 boost::bind(&Fragment::getCharges, _1),
357 secondpair, // no crefs here as are temporaries!
358 _2)
359 ),
360 boost::bind(&Extractors::gatherAllDistancesFromFragment,
361 boost::bind(&Fragment::getPositions, _1),
362 boost::bind(&Fragment::getCharges, _1),
363 boost::cref(thirdpair), // only the last one is no temporary
364 _2)
365 ),
366 boost::cref(angle.getParticleTypes())
367 );
368}
369 return returnfunction;
370}
Note: See TracBrowser for help on using the repository browser.