source: src/Fragmentation/Interfragmenter.cpp@ b1c5f46

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

Interfragmenter now combines two fragments up to (in sum) till MaxOrder.

  • before only fragments of each MaxOrder were allowed, now the sum of their bond order must not exceed maxOrder, i.e. MaxOrder of 4 means 1+1, 1+2, 1+3, 2+2, 3+1, 2+1, 1+1 (with order of left and right fragment that are joined).
  • Property mode set to 100644
File size: 8.5 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2013 Frederik Heber. 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 * Interfragmenter.cpp
25 *
26 * Created on: Jul 5, 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 "Interfragmenter.hpp"
38
39#include "CodePatterns/Assert.hpp"
40#include "CodePatterns/Log.hpp"
41
42#include "LinearAlgebra/Vector.hpp"
43
44#include "Element/element.hpp"
45#include "Fragmentation/Graph.hpp"
46#include "Fragmentation/KeySet.hpp"
47#include "LinkedCell/LinkedCell_View.hpp"
48#include "LinkedCell/types.hpp"
49#include "World.hpp"
50
51
52Interfragmenter::atomkeyset_t Interfragmenter::getAtomKeySetMap(
53 size_t _MaxOrder
54 ) const
55{
56 /// create a map of atom to keyset (below equal MaxOrder)
57 atomkeyset_t atomkeyset;
58 LOG(1, "INFO: Placing all atoms and their keysets into a map.");
59 for (Graph::const_iterator keysetiter = TotalGraph.begin();
60 keysetiter != TotalGraph.end(); ++keysetiter) {
61 const KeySet &keyset = keysetiter->first;
62 LOG(2, "DEBUG: Current keyset is " << keyset);
63 const AtomIdSet atoms(keyset);
64 const size_t atoms_size = atoms.getAtomIds().size();
65 if ((atoms_size > _MaxOrder) || (atoms_size == 0))
66 continue;
67 for (AtomIdSet::const_iterator atomiter = atoms.begin();
68 atomiter != atoms.end(); ++atomiter) {
69 // either create new list ...
70 std::pair<atomkeyset_t::iterator, bool> inserter =
71 atomkeyset.insert( std::make_pair(*atomiter, keysets_t(1, &keyset) ));
72 // ... or push to end
73 if (inserter.second) {
74 LOG(3, "DEBUG: Created new entry in map.");
75 } else {
76 LOG(3, "DEBUG: Added keyset to present entry.");
77 inserter.first->second.push_back(&keyset);
78 }
79 }
80 }
81 LOG(2, "DEBUG: There are " << atomkeyset.size() << " entries in lookup.");
82
83 return atomkeyset;
84}
85
86static Vector getAtomIdSetCenter(
87 const AtomIdSet &_atoms)
88{
89 const molecule * const _mol = (*_atoms.begin())->getMolecule();
90 const size_t atoms_size = _atoms.getAtomIds().size();
91 Vector center;
92 for (AtomIdSet::const_iterator iter = _atoms.begin();
93 iter != _atoms.end(); ++iter) {
94 center += (*iter)->getPosition();
95 ASSERT ( _mol == (*iter)->getMolecule(),
96 "getAtomIdSetCenter() - ids in same keyset belong to different molecule.");
97 }
98 center *= 1./(double)atoms_size;
99
100 return center;
101}
102
103Interfragmenter::candidates_t Interfragmenter::getNeighborsOutsideMolecule(
104 const AtomIdSet &_atoms,
105 double _Rcut,
106 const enum HydrogenTreatment _treatment) const
107{
108 /// go through linked cell and get all neighboring atoms up to Rcut
109 const LinkedCell::LinkedCell_View view = World::getInstance().getLinkedCell(_Rcut);
110 const Vector center = getAtomIdSetCenter(_atoms);
111 const LinkedCell::LinkedList neighbors = view.getAllNeighbors(_Rcut, center);
112 LOG(4, "DEBUG: Obtained " << neighbors.size() << " neighbors in distance of "
113 << _Rcut << " around " << center << ".");
114
115 /// remove all atoms that belong to same molecule as does one of the
116 /// fragment's atoms
117 const molecule * const _mol = (*_atoms.begin())->getMolecule();
118 candidates_t candidates;
119 candidates.reserve(neighbors.size());
120 for (LinkedCell::LinkedList::const_iterator iter = neighbors.begin();
121 iter != neighbors.end(); ++iter) {
122 const atom * const _atom = static_cast<const atom * const >(*iter);
123 ASSERT( _atom != NULL,
124 "Interfragmenter::getNeighborsOutsideMolecule() - a neighbor is not actually an atom?");
125 if ((_atom->getMolecule() != _mol)
126 && (_atom->getPosition().DistanceSquared(center) < _Rcut*_Rcut)
127 && ((_treatment == IncludeHydrogen) || (_atom->getType()->getAtomicNumber() != 1))) {
128 candidates.push_back(_atom);
129 }
130 }
131 LOG(3, "DEBUG: There remain " << candidates.size() << " candidates.");
132
133 return candidates;
134}
135
136Interfragmenter::atomkeyset_t Interfragmenter::getCandidatesSpecificKeySetMap(
137 const candidates_t &_candidates,
138 const atomkeyset_t &_atomkeyset) const
139{
140 atomkeyset_t fragmentmap;
141 for (candidates_t::const_iterator candidateiter = _candidates.begin();
142 candidateiter != _candidates.end(); ++candidateiter) {
143 const atom * _atom = *candidateiter;
144 atomkeyset_t::const_iterator iter = _atomkeyset.find(_atom);
145 ASSERT( iter != _atomkeyset.end(),
146 "Interfragmenter::getAtomSpecificKeySetMap() - could not find atom "
147 +toString(_atom->getId())+" in lookup.");
148 fragmentmap.insert( std::make_pair( _atom, iter->second) );
149 }
150 LOG(4, "DEBUG: Copied part of lookup map contains " << fragmentmap.size() << " keys.");
151
152 return fragmentmap;
153}
154
155void Interfragmenter::combineFragments(
156 const size_t _MaxOrder,
157 const candidates_t &_candidates,
158 atomkeyset_t &_fragmentmap,
159 const KeySet &_keyset,
160 Graph &_InterFragments,
161 int &_counter)
162{
163 for (candidates_t::const_iterator candidateiter = _candidates.begin();
164 candidateiter != _candidates.end(); ++candidateiter) {
165 const atom *_atom = *candidateiter;
166 LOG(3, "DEBUG: Current candidate is " << *_atom << ".");
167 atomkeyset_t::iterator finditer = _fragmentmap.find(_atom);
168 ASSERT( finditer != _fragmentmap.end(),
169 "Interfragmenter::combineFragments() - could not find atom "
170 +toString(_atom->getId())+" in fragment specific lookup.");
171 keysets_t &othersets = finditer->second;
172 ASSERT( !othersets.empty(),
173 "Interfragmenter::combineFragments() - keysets to "+toString(_atom->getId())+
174 "is empty.");
175 keysets_t::iterator otheriter = othersets.begin();
176 while (otheriter != othersets.end()) {
177 const KeySet &otherset = **otheriter;
178 LOG(3, "DEBUG: Current keyset is " << otherset << ".");
179 // only add them one way round and not the other
180 if (otherset < _keyset) {
181 ++otheriter;
182 continue;
183 }
184 // only add if combined they don't exceed the desired maxorder
185 if (otherset.size() + _keyset.size() > _MaxOrder) {
186 LOG(3, "INFO: Rejecting " << otherset << " as in sum their orders exceed " << _MaxOrder);
187 ++otheriter;
188 continue;
189 }
190 KeySet newset(otherset);
191 newset.insert(_keyset.begin(), _keyset.end());
192 LOG(3, "DEBUG: Inserting new combined set " << newset << ".");
193 _InterFragments.insert( std::make_pair(newset, std::make_pair(++_counter, 1.)));
194 // finally, remove the set such that no other combination exists
195 otheriter = othersets.erase(otheriter);
196 }
197 }
198}
199
200void Interfragmenter::operator()(
201 const size_t MaxOrder,
202 const double Rcut,
203 const enum HydrogenTreatment treatment)
204{
205 atomkeyset_t atomkeyset = getAtomKeySetMap(MaxOrder);
206
207 Graph InterFragments;
208 int counter = TotalGraph.size();
209
210 /// go through all fragments up to MaxOrder
211 LOG(1, "INFO: Creating inter-fragments.");
212 for (Graph::const_iterator keysetiter = TotalGraph.begin();
213 keysetiter != TotalGraph.end(); ++keysetiter) {
214 const KeySet &keyset = keysetiter->first;
215 LOG(2, "DEBUG: Current keyset is " << keyset);
216 const AtomIdSet atoms(keyset);
217 const size_t atoms_size = atoms.getAtomIds().size();
218 if ((atoms_size > MaxOrder) || (atoms_size == 0))
219 continue;
220
221 // get neighboring atoms outside the current molecule
222 candidates_t candidates = getNeighborsOutsideMolecule(atoms, Rcut, treatment);
223
224 // create a lookup specific to this fragment
225 atomkeyset_t fragmentmap = getCandidatesSpecificKeySetMap(candidates, atomkeyset);
226
227 /// combine each remaining fragment with current fragment to a new fragment
228 /// if keyset is less (to prevent addding same inter-fragment twice)
229 combineFragments(MaxOrder, candidates, fragmentmap, keyset, InterFragments, counter);
230 }
231
232 /// eventually, add all new fragments to the Graph
233 counter = TotalGraph.size();
234 TotalGraph.InsertGraph(InterFragments, counter);
235}
Note: See TracBrowser for help on using the repository browser.