source: src/Potentials/CompoundPotential.cpp@ 154e88

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

Added CompoundPotential as container for multiple FunctionModels.

  • added unit test that uses libMolecuilderFragmentation_getFromKeysetStub.la as HomologyGraphUnitTest. Hence, we are not dependent full libMolecuilder.
  • so far, we simply test with a wrapped PairPotential_Morse.
  • Property mode set to 100644
File size: 10.1 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 dim = 0;
123 } else {
124 std::copy(iter, iter+model_dim, std::back_inserter(subparams));
125 dim -= model_dim;
126 }
127 model->setParameters(subparams);
128 }
129 }
130}
131
132CompoundPotential::parameters_t CompoundPotential::getParameters() const
133{
134 const size_t dimension = getParameterDimension();
135 CompoundPotential::parameters_t parameters(dimension);
136 CompoundPotential::parameters_t::iterator iter = parameters.begin();
137 BOOST_FOREACH( const FunctionModel* model, models) {
138 const CompoundPotential::parameters_t &params = model->getParameters();
139 std::copy(params.begin(), params.end(), iter);
140 ASSERT( iter != parameters.end(),
141 "CompoundPotential::getParameters() - iter already at end.");
142 }
143 return parameters;
144}
145
146void CompoundPotential::setParametersToRandomInitialValues(const TrainingData &data)
147{
148 std::for_each(models.begin(), models.end(),
149 boost::bind(&FunctionModel::setParametersToRandomInitialValues, _1, boost::cref(data))
150 );
151}
152
153size_t CompoundPotential::getParameterDimension() const
154{
155 std::vector<size_t> dimensions(models.size(), 0);
156 std::transform(models.begin(), models.end(), dimensions.begin(),
157 boost::bind(&FunctionModel::getParameterDimension, _1));
158 return std::accumulate(dimensions.begin(), dimensions.end(), 0, std::plus<size_t>());
159}
160
161void CompoundPotential::setTriplefunction(triplefunction_t &_triplefunction)
162{
163 std::for_each(models.begin(), models.end(),
164 boost::bind(&FunctionModel::setTriplefunction, _1, boost::ref(_triplefunction))
165 );
166}
167
168CompoundPotential::results_t CompoundPotential::operator()(const arguments_t &arguments) const
169{
170 results_t results(1,0.);
171 std::vector<results_t> partial_results(models.size());
172 std::transform(models.begin(), models.end(), partial_results.begin(),
173 boost::bind(&FunctionModel::operator(), _1, boost::cref(arguments))
174 );
175 std::for_each(partial_results.begin(), partial_results.end(),
176 results[0] += (boost::lambda::_1)[0]);
177 return results;
178}
179
180CompoundPotential::results_t CompoundPotential::parameter_derivative(const arguments_t &arguments, const size_t index) const
181{
182 // get parameter dimensions per model
183 std::vector<size_t> dimensions(models.size(), 0);
184 std::transform(models.begin(), models.end(), dimensions.begin(),
185 boost::bind(&FunctionModel::getParameterDimension, _1));
186
187 // convert to index end+1 per model
188 std::partial_sum(dimensions.begin(), dimensions.end(), dimensions.begin());
189
190 // look for value not less than index
191 std::vector<size_t>::const_iterator iter =
192 std::lower_bound(dimensions.begin(), dimensions.end(), index);
193 models_t::const_iterator modeliter = models.begin();
194
195 // step forward to same model
196 std::advance(modeliter,
197 std::distance(const_cast<const std::vector<size_t> &>(dimensions).begin(), iter) );
198
199 // evaluate with correct relative index and return
200 const size_t indexbase = (iter == dimensions.begin()) ? 0 : *(--iter);
201 CompoundPotential::results_t results =
202 (*modeliter)->parameter_derivative(arguments, index-indexbase);
203 return results;
204}
205
206bool CompoundPotential::isBoxConstraint() const
207{
208 std::vector<bool> constraints(models.size(), 0);
209 std::transform(models.begin(), models.end(), constraints.begin(),
210 boost::bind(&FunctionModel::getParameterDimension, _1));
211 return std::accumulate(constraints.begin(), constraints.end(), true,
212 std::logical_and<bool>());
213}
214
215CompoundPotential::parameters_t CompoundPotential::getLowerBoxConstraints() const
216{
217 const size_t dimension = getParameterDimension();
218 CompoundPotential::parameters_t constraints(dimension);
219 CompoundPotential::parameters_t::iterator iter = constraints.begin();
220 BOOST_FOREACH( FunctionModel* model, models) {
221 const CompoundPotential::parameters_t params = model->getLowerBoxConstraints();
222 std::copy(params.begin(), params.end(), iter);
223 ASSERT( iter != constraints.end(),
224 "CompoundPotential::getParameters() - iter already at end.");
225 }
226 return constraints;
227}
228
229CompoundPotential::parameters_t CompoundPotential::getUpperBoxConstraints() const
230{
231 const size_t dimension = getParameterDimension();
232 CompoundPotential::parameters_t constraints(dimension);
233 CompoundPotential::parameters_t::iterator iter = constraints.begin();
234 BOOST_FOREACH( FunctionModel* model, models) {
235 const CompoundPotential::parameters_t params = model->getUpperBoxConstraints();
236 std::copy(params.begin(), params.end(), iter);
237 ASSERT( iter != constraints.end(),
238 "CompoundPotential::getParameters() - iter already at end.");
239 }
240 return constraints;
241}
242
243FunctionModel::extractor_t CompoundPotential::getFragmentSpecificExtractor() const
244{
245 // create initial returnfunction
246 particletypes_per_model_t::const_iterator typesiter = particletypes_per_model.begin();
247 Fragment::charges_t charges;
248 {
249 charges.resize((*typesiter).size());
250 std::transform((*typesiter).begin(), (*typesiter).end(),
251 charges.begin(), boost::lambda::_1);
252 }
253 FunctionModel::extractor_t returnfunction =
254 boost::bind(&Extractors::gatherAllDistancesFromFragment,
255 boost::bind(&Fragment::getPositions, _1),
256 boost::bind(&Fragment::getCharges, _1),
257 charges, // no crefs here as are temporaries!
258 _2);
259
260 // every following fragments combines its arguments with the initial function
261 for (; typesiter != particletypes_per_model.end(); ++typesiter) {
262 Fragment::charges_t charges;
263 {
264 charges.resize((*typesiter).size());
265 std::transform((*typesiter).begin(), (*typesiter).end(),
266 charges.begin(), boost::lambda::_1);
267 }
268
269 returnfunction =
270 boost::bind(&Extractors::combineArguments,
271 boost::bind(returnfunction, _1, _2),
272 boost::bind(&Extractors::gatherAllDistancesFromFragment,
273 boost::bind(&Fragment::getPositions, _1),
274 boost::bind(&Fragment::getCharges, _1),
275 charges, // no crefs here as are temporaries!
276 _2)
277 );
278 }
279 return returnfunction;
280}
Note: See TracBrowser for help on using the repository browser.