source: src/Fragmentation/Interfragmenter.cpp@ 78202b

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults 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_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 IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix 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 78202b was d713ce, checked in by Frederik Heber <heber@…>, 9 years ago

AtomFragmentsMap is now a Singleton and part of Homology code.

  • Property mode set to 100644
File size: 9.3 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 "Descriptors/AtomDescriptor.hpp"
45#include "Element/element.hpp"
46#include "Fragmentation/Graph.hpp"
47#include "Fragmentation/KeySet.hpp"
48#include "LinkedCell/LinkedCell_View.hpp"
49#include "LinkedCell/types.hpp"
50#include "World.hpp"
51
52static Vector getAtomIdSetCenter(
53 const AtomIdSet &_atoms)
54{
55 const molecule * const _mol = (*_atoms.begin())->getMolecule();
56 const size_t atoms_size = _atoms.getAtomIds().size();
57 Vector center;
58 for (AtomIdSet::const_iterator iter = _atoms.begin();
59 iter != _atoms.end(); ++iter) {
60 center += (*iter)->getPosition();
61 ASSERT ( _mol == (*iter)->getMolecule(),
62 "getAtomIdSetCenter() - ids in same keyset belong to different molecule.");
63 }
64 center *= 1./(double)atoms_size;
65
66 return center;
67}
68
69Interfragmenter::candidates_t Interfragmenter::getNeighborsOutsideMolecule(
70 const AtomIdSet &_atoms,
71 double _Rcut,
72 const enum HydrogenTreatment _treatment) const
73{
74 /// go through linked cell and get all neighboring atoms up to Rcut
75 const LinkedCell::LinkedCell_View view = World::getInstance().getLinkedCell(_Rcut);
76 const Vector center = getAtomIdSetCenter(_atoms);
77 const LinkedCell::LinkedList neighbors = view.getAllNeighbors(_Rcut, center);
78 LOG(4, "DEBUG: Obtained " << neighbors.size() << " neighbors in distance of "
79 << _Rcut << " around " << center << ".");
80
81 /// remove all atoms that belong to same molecule as does one of the
82 /// fragment's atoms
83 const molecule * const _mol = (*_atoms.begin())->getMolecule();
84 candidates_t candidates;
85 candidates.reserve(neighbors.size());
86 for (LinkedCell::LinkedList::const_iterator iter = neighbors.begin();
87 iter != neighbors.end(); ++iter) {
88 const atom * const _atom = static_cast<const atom * const >(*iter);
89 ASSERT( _atom != NULL,
90 "Interfragmenter::getNeighborsOutsideMolecule() - a neighbor is not actually an atom?");
91 if ((_atom->getMolecule() != _mol)
92 && (_atom->getPosition().DistanceSquared(center) < _Rcut*_Rcut)
93 && ((_treatment == IncludeHydrogen) || (_atom->getType()->getAtomicNumber() != 1))) {
94 candidates.push_back(_atom);
95 }
96 }
97 LOG(3, "DEBUG: There remain " << candidates.size() << " candidates.");
98
99 return candidates;
100}
101
102Interfragmenter::atomkeyset_t Interfragmenter::getCandidatesSpecificKeySetMap(
103 const candidates_t &_candidates,
104 const atomkeyset_t &_atomkeyset) const
105{
106 atomkeyset_t fragmentmap;
107 for (candidates_t::const_iterator candidateiter = _candidates.begin();
108 candidateiter != _candidates.end(); ++candidateiter) {
109 const atomId_t atomid = (*candidateiter)->getId();
110 atomkeyset_t::const_iterator iter = _atomkeyset.find(atomid);
111 ASSERT( iter != _atomkeyset.end(),
112 "Interfragmenter::getAtomSpecificKeySetMap() - could not find atom "
113 +toString(atomid)+" in lookup.");
114 fragmentmap.insert( std::make_pair( atomid, iter->second) );
115 }
116 LOG(4, "DEBUG: Copied part of lookup map contains " << fragmentmap.size() << " keys.");
117
118 return fragmentmap;
119}
120
121void Interfragmenter::combineFragments(
122 const size_t _MaxOrder,
123 const candidates_t &_candidates,
124 const atomkeyset_t &_fragmentmap,
125 const KeySet &_keyset,
126 Graph &_InterFragments,
127 int &_counter)
128{
129 for (candidates_t::const_iterator candidateiter = _candidates.begin();
130 candidateiter != _candidates.end(); ++candidateiter) {
131 const atom *_atom = *candidateiter;
132 LOG(3, "DEBUG: Current candidate is " << *_atom << ".");
133 atomkeyset_t::const_iterator finditer = _fragmentmap.find(_atom->getId());
134 ASSERT( finditer != _fragmentmap.end(),
135 "Interfragmenter::combineFragments() - could not find atom "
136 +toString(_atom->getId())+" in fragment specific lookup.");
137 // copy set to allow erase
138 keysets_t othersets(finditer->second);
139 ASSERT( !othersets.empty(),
140 "Interfragmenter::combineFragments() - keysets to "+toString(_atom->getId())+
141 "is empty.");
142 keysets_t::iterator otheriter = othersets.begin();
143 while (otheriter != othersets.end()) {
144 const KeySet &otherset = *otheriter;
145 LOG(3, "DEBUG: Current keyset is " << otherset << ".");
146 // only add them one way round and not the other
147 if (otherset < _keyset) {
148 ++otheriter;
149 continue;
150 }
151 // only add if combined they don't exceed the desired maxorder
152 if (otherset.size() + _keyset.size() > _MaxOrder) {
153 LOG(3, "INFO: Rejecting " << otherset << " as in sum their orders exceed " << _MaxOrder);
154 ++otheriter;
155 continue;
156 }
157 KeySet newset(otherset);
158 newset.insert(_keyset.begin(), _keyset.end());
159 LOG(3, "DEBUG: Inserting new combined set " << newset << ".");
160 _InterFragments.insert( std::make_pair(newset, std::make_pair(++_counter, 1.)));
161 // finally, remove the set such that no other combination exists
162 otheriter = othersets.erase(otheriter);
163 }
164 }
165}
166
167void Interfragmenter::operator()(
168 const size_t MaxOrder,
169 const double Rcut,
170 const enum HydrogenTreatment treatment)
171{
172 AtomFragmentsMap& atomfragments_container = AtomFragmentsMap::getInstance();
173 atomfragments_container.insert(TotalGraph, MaxOrder);
174 const atomkeyset_t &atomkeyset = atomfragments_container.getMap();
175
176 Graph InterFragments;
177 int counter = TotalGraph.size();
178
179 /// go through all fragments up to MaxOrder
180 LOG(1, "INFO: Creating inter-fragments.");
181 for (Graph::const_iterator keysetiter = TotalGraph.begin();
182 keysetiter != TotalGraph.end(); ++keysetiter) {
183 const KeySet &keyset = keysetiter->first;
184 LOG(2, "DEBUG: Current keyset is " << keyset);
185 const AtomIdSet atoms(keyset);
186 const size_t atoms_size = atoms.getAtomIds().size();
187 if ((atoms_size > MaxOrder) || (atoms_size == 0))
188 continue;
189
190 // get neighboring atoms outside the current molecule
191 candidates_t candidates = getNeighborsOutsideMolecule(atoms, Rcut, treatment);
192
193 // create a lookup specific to this fragment
194 atomkeyset_t fragmentmap = getCandidatesSpecificKeySetMap(candidates, atomkeyset);
195
196 /// combine each remaining fragment with current fragment to a new fragment
197 /// if keyset is less (to prevent addding same inter-fragment twice)
198 combineFragments(MaxOrder, candidates, fragmentmap, keyset, InterFragments, counter);
199 }
200
201 /// eventually, add all new fragments to the Graph
202 counter = TotalGraph.size();
203 TotalGraph.InsertGraph(InterFragments, counter);
204}
205
206double Interfragmenter::findLargestCutoff(
207 const size_t _MaxOrder,
208 const double _upperbound,
209 const enum HydrogenTreatment _treatment) const
210{
211 double Rcut = _upperbound*_upperbound;
212 std::pair<atomId_t, atomId_t> ClosestPair;
213 // place all atoms into LC grid with some upper bound
214 const LinkedCell::LinkedCell_View view = World::getInstance().getLinkedCell(_upperbound);
215
216 // go through each atom and find closest atom not in the same keyset
217 for (Graph::const_iterator keysetiter = TotalGraph.begin();
218 keysetiter != TotalGraph.end(); ++keysetiter) {
219 const KeySet &keyset = keysetiter->first;
220 LOG(2, "DEBUG: Current keyset is " << keyset);
221 const AtomIdSet atoms(keyset);
222
223 // get neighboring atoms outside the current molecule
224 const candidates_t candidates = getNeighborsOutsideMolecule(atoms, _upperbound, _treatment);
225 const Vector center = getAtomIdSetCenter(atoms);
226
227 for (candidates_t::const_iterator candidateiter = candidates.begin();
228 candidateiter != candidates.end(); ++candidateiter) {
229 atom const * const Walker = *candidateiter;
230 // go through each atom in set and pick minimal distance
231 for (AtomIdSet::const_iterator setiter = atoms.begin(); setiter != atoms.end(); ++setiter) {
232 const double distanceSquared = Walker->getPosition().DistanceSquared(center);
233 // pick the smallest compared to current Rcut if smaller
234 if (distanceSquared < Rcut) {
235 Rcut = distanceSquared;
236 ClosestPair.first = (*setiter)->getId();
237 ClosestPair.second = Walker->getId();
238 LOG(2, "DEBUG: Found new pair " << ClosestPair << " with distance " << sqrt(Rcut));
239 }
240 }
241 }
242 }
243 const double largest_distance = sqrt(Rcut);
244 LOG(1, "INFO: Largest inter-fragment distance to cause no additional fragments: "
245 << largest_distance);
246
247 return largest_distance;
248}
Note: See TracBrowser for help on using the repository browser.