source: src/Fragmentation/Interfragmenter.cpp@ c0f2fc

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 c0f2fc was 17e4fd, checked in by Frederik Heber <heber@…>, 9 years ago

Added new option DoSmearElectronicCharges to FragmentationAutomationAction.

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