source: src/Potentials/CompoundPotential.cpp@ 7e5b94

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

CompoundPotential now combines ConstantPotential and PairPotential_Morse successfully.

  • we set PairPotential_Morse::energy_offset to 0 as default value, but we need to remove the offsets fully from all potentials.
  • Property mode set to 100644
File size: 11.8 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2013 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder 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
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * CompoundPotential.cpp
25 *
26 * Created on: May 8, 2013
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include "CodePatterns/MemDebug.hpp"
36
37#include "Potentials/CompoundPotential.hpp"
38
39#include <algorithm>
40#include <boost/bind.hpp>
41#include <boost/foreach.hpp>
42#include <boost/lambda/lambda.hpp>
43#include <iterator>
44#include <numeric>
45
46#include "CodePatterns/Assert.hpp"
47#include "CodePatterns/Log.hpp"
48
49#include "Element/element.hpp"
50#include "Fragmentation/Homology/HomologyGraph.hpp"
51#include "Fragmentation/Summation/SetValues/Fragment.hpp"
52#include "FunctionApproximation/Extractors.hpp"
53#include "Potentials/EmpiricalPotential.hpp"
54#include "Potentials/PotentialRegistry.hpp"
55
56
57CompoundPotential::CompoundPotential(const HomologyGraph &graph)
58{
59 LOG(1, "INFO: Creating CompoundPotential for graph " << graph << ".");
60 // look though graph and place all matching FunctionModel's in
61 // PotentialRegistry in models
62 PotentialRegistry::const_iterator potentialiter =
63 PotentialRegistry::getInstance().getBeginIter();
64 while (potentialiter != PotentialRegistry::getInstance().getEndIter()) {
65 // get model and types
66 EmpiricalPotential * const potential = potentialiter->second;
67 const SerializablePotential::ParticleTypes_t &types =
68 potential->getParticleTypes();
69
70 // create charges
71 Fragment::charges_t charges;
72 charges.resize(types.size());
73 std::transform(types.begin(), types.end(),
74 charges.begin(), boost::lambda::_1);
75 // convert into count map
76 Extractors::elementcounts_t counts_per_charge =
77 Extractors::_detail::getElementCounts(charges);
78// ASSERT( !counts_per_charge.empty(),
79// "getFirstGraphwithSpecifiedElements() - charge counts are empty?");
80 LOG(2, "DEBUG: counts_per_charge is " << counts_per_charge << ".");
81
82 // check whether graph contains suitable types
83 Extractors::elementcounts_t::const_iterator countiter = counts_per_charge.begin();
84 for (; countiter != counts_per_charge.end(); ++countiter)
85 if (!graph.hasTimesAtomicNumber(
86 static_cast<size_t>(countiter->first),
87 static_cast<size_t>(countiter->second))
88 )
89 break;
90 // if we have a match for every count, store model
91 if( countiter == counts_per_charge.end()) {
92 LOG(1, "INFO: Potential " << potentialiter->first << " matches with fragment.");
93 models.push_back(static_cast<FunctionModel*>(potential));
94 particletypes_per_model.push_back(types);
95 }
96 ++potentialiter;
97 }
98
99 // check that models and particletypes_per_model match
100 ASSERT( models.size() == particletypes_per_model.size(),
101 "CompoundPotential::CompoundPotential() - particletypes not stored for all models?");
102}
103
104CompoundPotential::~CompoundPotential()
105{
106 // clear all models and internally stored particletypes
107 models.clear();
108 particletypes_per_model.clear();
109}
110
111void CompoundPotential::setParameters(const parameters_t &_params)
112{
113 size_t dim = _params.size();
114 parameters_t::const_iterator iter = _params.begin();
115 BOOST_FOREACH( FunctionModel* model, models) {
116 const parameters_t &model_params = model->getParameters();
117 const size_t model_dim = model_params.size();
118 if (dim > 0) {
119 parameters_t subparams;
120 if (dim < model_dim) {
121 std::copy(iter, iter+dim, std::back_inserter(subparams));
122 iter += dim;
123 dim = 0;
124 } else {
125 std::copy(iter, iter+model_dim, std::back_inserter(subparams));
126 iter += model_dim;
127 dim -= model_dim;
128 }
129 model->setParameters(subparams);
130 }
131 }
132}
133
134CompoundPotential::parameters_t CompoundPotential::getParameters() const
135{
136 const size_t dimension = getParameterDimension();
137 CompoundPotential::parameters_t parameters(dimension);
138 CompoundPotential::parameters_t::iterator iter = parameters.begin();
139 BOOST_FOREACH( const FunctionModel* model, models) {
140 const CompoundPotential::parameters_t &params = model->getParameters();
141 std::copy(params.begin(), params.end(), iter);
142 ASSERT( iter != parameters.end(),
143 "CompoundPotential::getParameters() - iter already at end.");
144 }
145 return parameters;
146}
147
148void CompoundPotential::setParametersToRandomInitialValues(const TrainingData &data)
149{
150 std::for_each(models.begin(), models.end(),
151 boost::bind(&FunctionModel::setParametersToRandomInitialValues, _1, boost::cref(data))
152 );
153}
154
155size_t CompoundPotential::getParameterDimension() const
156{
157 std::vector<size_t> dimensions(models.size(), 0);
158 std::transform(models.begin(), models.end(), dimensions.begin(),
159 boost::bind(&FunctionModel::getParameterDimension, _1));
160 return std::accumulate(dimensions.begin(), dimensions.end(), 0, std::plus<size_t>());
161}
162
163void CompoundPotential::setTriplefunction(triplefunction_t &_triplefunction)
164{
165 std::for_each(models.begin(), models.end(),
166 boost::bind(&FunctionModel::setTriplefunction, _1, boost::ref(_triplefunction))
167 );
168}
169
170std::vector<CompoundPotential::arguments_t> CompoundPotential::splitUpArgumentsByModels(
171 const arguments_t &arguments) const
172{
173 std::vector<arguments_t> partial_args(models.size());
174 std::vector<arguments_t>::iterator partialiter = partial_args.begin();
175 arguments_t::const_iterator argiter = arguments.begin();
176 BOOST_FOREACH( const SerializablePotential::ParticleTypes_t &types, particletypes_per_model) {
177 // we always expect N(N-1)/2 distances for N particle types
178 arguments_t::const_iterator enditer = argiter+(types.size()*(types.size()-1)/2);
179 ASSERT( argiter != arguments.end(),
180 "CompoundPotential::splitUpArgumentsByModels() - incorrect number of arguments.");
181 std::copy(argiter, enditer, std::back_inserter(*partialiter++));
182 argiter = enditer;
183 }
184 ASSERT( argiter == arguments.end(),
185 "CompoundPotential::splitUpArgumentsByModels() - incorrect number of arguments.");
186 return partial_args;
187}
188
189CompoundPotential::results_t CompoundPotential::operator()(const arguments_t &arguments) const
190{
191 // first, we have to split up the given arguments
192 std::vector<arguments_t> partial_args =
193 splitUpArgumentsByModels(arguments);
194 // then, with each bunch of arguments, we call the specific model
195 results_t results(1,0.);
196 std::vector<results_t> partial_results(models.size());
197 std::transform(
198 models.begin(), models.end(),
199 partial_args.begin(),
200 partial_results.begin(),
201 boost::bind(&FunctionModel::operator(), _1, _2)
202 );
203 std::for_each(partial_results.begin(), partial_results.end(),
204 std::cout << (boost::lambda::_1)[0] << "\t");
205 std::for_each(partial_results.begin(), partial_results.end(),
206 results[0] += (boost::lambda::_1)[0]);
207 return results;
208}
209
210CompoundPotential::results_t CompoundPotential::parameter_derivative(const arguments_t &arguments, const size_t index) const
211{
212 // first, we have to split up the given arguments
213 std::vector<arguments_t> partial_args =
214 splitUpArgumentsByModels(arguments);
215 // then, with each bunch of arguments, we call the specific model
216 // get parameter dimensions per model
217 std::vector<size_t> dimensions(models.size(), 0);
218 std::transform(models.begin(), models.end(), dimensions.begin(),
219 boost::bind(&FunctionModel::getParameterDimension, _1));
220
221 // convert to index end+1 per model
222 std::partial_sum(dimensions.begin(), dimensions.end(), dimensions.begin());
223
224 // look for value not less than index
225 std::vector<size_t>::const_iterator iter =
226 std::lower_bound(dimensions.begin(), dimensions.end(), index);
227
228 // step forward to same model
229 models_t::const_iterator modeliter = models.begin();
230 std::advance(modeliter,
231 std::distance(const_cast<const std::vector<size_t> &>(dimensions).begin(), iter) );
232 std::vector<arguments_t>::const_iterator argiter = partial_args.begin();
233 std::advance(argiter,
234 std::distance(const_cast<const std::vector<size_t> &>(dimensions).begin(), iter) );
235
236 // evaluate with correct relative index and return
237 const size_t indexbase = (iter == dimensions.begin()) ? 0 : *(--iter);
238 CompoundPotential::results_t results =
239 (*modeliter)->parameter_derivative(*argiter, index-indexbase);
240 return results;
241}
242
243bool CompoundPotential::isBoxConstraint() const
244{
245 std::vector<bool> constraints(models.size(), 0);
246 std::transform(models.begin(), models.end(), constraints.begin(),
247 boost::bind(&FunctionModel::getParameterDimension, _1));
248 return std::accumulate(constraints.begin(), constraints.end(), true,
249 std::logical_and<bool>());
250}
251
252CompoundPotential::parameters_t CompoundPotential::getLowerBoxConstraints() const
253{
254 const size_t dimension = getParameterDimension();
255 CompoundPotential::parameters_t constraints(dimension);
256 CompoundPotential::parameters_t::iterator iter = constraints.begin();
257 BOOST_FOREACH( FunctionModel* model, models) {
258 const CompoundPotential::parameters_t params = model->getLowerBoxConstraints();
259 std::copy(params.begin(), params.end(), iter);
260 ASSERT( iter != constraints.end(),
261 "CompoundPotential::getParameters() - iter already at end.");
262 }
263 return constraints;
264}
265
266CompoundPotential::parameters_t CompoundPotential::getUpperBoxConstraints() const
267{
268 const size_t dimension = getParameterDimension();
269 CompoundPotential::parameters_t constraints(dimension);
270 CompoundPotential::parameters_t::iterator iter = constraints.begin();
271 BOOST_FOREACH( FunctionModel* model, models) {
272 const CompoundPotential::parameters_t params = model->getUpperBoxConstraints();
273 std::copy(params.begin(), params.end(), iter);
274 ASSERT( iter != constraints.end(),
275 "CompoundPotential::getParameters() - iter already at end.");
276 }
277 return constraints;
278}
279
280FunctionModel::extractor_t CompoundPotential::getFragmentSpecificExtractor() const
281{
282 // create initial returnfunction
283 particletypes_per_model_t::const_iterator typesiter = particletypes_per_model.begin();
284 Fragment::charges_t charges;
285 {
286 charges.resize((*typesiter).size());
287 std::transform((*typesiter).begin(), (*typesiter).end(),
288 charges.begin(), boost::lambda::_1);
289 }
290 FunctionModel::extractor_t returnfunction =
291 boost::bind(&Extractors::gatherAllDistancesFromFragment,
292 boost::bind(&Fragment::getPositions, _1),
293 boost::bind(&Fragment::getCharges, _1),
294 charges, // no crefs here as are temporaries!
295 _2);
296
297 // every following fragments combines its arguments with the initial function
298 for (; typesiter != particletypes_per_model.end(); ++typesiter) {
299 Fragment::charges_t charges;
300 {
301 charges.resize((*typesiter).size());
302 std::transform((*typesiter).begin(), (*typesiter).end(),
303 charges.begin(), boost::lambda::_1);
304 }
305
306 returnfunction =
307 boost::bind(&Extractors::concatenateArguments,
308 boost::bind(returnfunction, _1, _2),
309 boost::bind(&Extractors::gatherAllDistancesFromFragment,
310 boost::bind(&Fragment::getPositions, _1),
311 boost::bind(&Fragment::getCharges, _1),
312 charges, // no crefs here as are temporaries!
313 _2)
314 );
315 }
316 return returnfunction;
317}
Note: See TracBrowser for help on using the repository browser.