Changeset 01120c for src/Actions
- Timestamp:
- May 18, 2016, 10:02:53 PM (9 years ago)
- Branches:
- 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, 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, 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
- Children:
- c1ec8e
- Parents:
- d8ed62
- git-author:
- Frederik Heber <heber@…> (03/07/16 19:10:44)
- git-committer:
- Frederik Heber <heber@…> (05/18/16 22:02:53)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Actions/PotentialAction/FitPartialChargesAction.cpp
rd8ed62 r01120c 44 44 #include "World.hpp" 45 45 46 #include <boost/bimap.hpp> 46 47 #include <boost/bind.hpp> 47 48 #include <boost/filesystem.hpp> … … 56 57 #include "Potentials/PartialNucleiChargeFitter.hpp" 57 58 59 #include "AtomIdSet.hpp" 60 #include "Descriptors/AtomIdDescriptor.hpp" 58 61 #include "Element/element.hpp" 59 62 #include "Element/periodentafel.hpp" … … 76 79 /** =========== define the function ====================== */ 77 80 78 inline 79 HomologyGraph getFirstGraphwithSpecifiedElements( 80 const HomologyContainer &homologies, 81 const SerializablePotential::ParticleTypes_t &types) 82 { 83 ASSERT( !types.empty(), 84 "getFirstGraphwithSpecifiedElements() - charges is empty?"); 85 // create charges 86 Fragment::charges_t charges; 87 charges.resize(types.size()); 88 std::transform(types.begin(), types.end(), 89 charges.begin(), boost::lambda::_1); 90 // convert into count map 91 Extractors::elementcounts_t counts_per_charge = 92 Extractors::_detail::getElementCounts(charges); 93 ASSERT( !counts_per_charge.empty(), 94 "getFirstGraphwithSpecifiedElements() - charge counts are empty?"); 95 LOG(2, "DEBUG: counts_per_charge is " << counts_per_charge << "."); 96 // we want to check each (unique) key only once 97 HomologyContainer::const_key_iterator olditer = homologies.key_end(); 98 for (HomologyContainer::const_key_iterator iter = 99 homologies.key_begin(); iter != homologies.key_end(); 100 iter = homologies.getNextKey(iter)) { 101 // if it's the same as the old one, skip it 102 if (olditer == iter) 103 continue; 104 else 105 olditer = iter; 106 // if it's a new key, check if every element has the right number of counts 107 Extractors::elementcounts_t::const_iterator countiter = counts_per_charge.begin(); 108 for (; countiter != counts_per_charge.end(); ++countiter) 109 if (!(*iter).hasTimesAtomicNumber( 110 static_cast<size_t>(countiter->first), 111 static_cast<size_t>(countiter->second)) 112 ) 113 break; 114 if( countiter == counts_per_charge.end()) 115 return *iter; 116 } 117 return HomologyGraph(); 118 } 119 120 void enforceZeroTotalCharge( 81 static void enforceZeroTotalCharge( 121 82 PartialNucleiChargeFitter::charges_t &_averaged_charges) 122 83 { … … 134 95 "enforceZeroTotalCharge() - enforcing neutral net charge failed, " 135 96 +toString(charge_sum)+" is the remaining net charge."); 136 } 137 138 size_t obtainAverageChargesOverFragments( 97 98 LOG(2, "DEBUG: final charges with net zero charge are " << _averaged_charges); 99 } 100 101 static size_t obtainAverageChargesOverFragments( 139 102 PartialNucleiChargeFitter::charges_t &_average_charges, 140 103 const std::pair< … … 196 159 } 197 160 161 inline SerializablePotential::ParticleTypes_t 162 getParticleTypesForAtomIdSet(const AtomIdSet &_atoms) 163 { 164 SerializablePotential::ParticleTypes_t particletypes; 165 particletypes.resize(_atoms.size()); 166 std::transform( 167 _atoms.begin(), _atoms.end(), 168 particletypes.begin(), 169 boost::bind(&atom::getElementNo, _1)); 170 return particletypes; 171 } 172 198 173 ActionState::ptr PotentialFitPartialChargesAction::performCall() 199 174 { … … 206 181 207 182 /// obtain possible fragments to each selected atom 208 AtomFragmentsMap::keysets_t fragments; 209 const AtomFragmentsMap::AtomFragmentsMap_t &atommap = 210 AtomFragmentsMap::getConstInstance().getMap(); 183 const AtomFragmentsMap &atomfragments = AtomFragmentsMap::getConstInstance(); 184 if (!atomfragments.checkCompleteness()) { 185 STATUS("AtomFragmentsMap failed internal consistency check, missing forcekeysets?"); 186 return Action::failure; 187 } 188 std::set<KeySet> fragments; 189 const AtomFragmentsMap::AtomFragmentsMap_t &atommap = atomfragments.getMap(); 211 190 for (World::AtomSelectionConstIterator iter = world.beginAtomSelection(); 212 191 iter != world.endAtomSelection(); ++iter) { 213 192 const AtomFragmentsMap::AtomFragmentsMap_t::const_iterator atomiter = 214 193 atommap.find(iter->first); 215 if (atomiter == atommap.end()) { 216 ELOG(2, "There are no fragments associated to " << iter->first << "."); 217 continue; 218 } 219 const AtomFragmentsMap::keysets_t &keysets = atomiter->second; 220 fragments.insert( fragments.end(), keysets.begin(), keysets.end() ); 194 if (iter->second->getElementNo() != 1) { 195 if (atomiter == atommap.end()) { 196 ELOG(2, "There are no fragments associated to " << iter->first << "."); 197 continue; 198 } 199 const AtomFragmentsMap::keysets_t &keysets = atomiter->second; 200 LOG(2, "DEBUG: atom " << iter->first << " has " << keysets.size() << " fragments."); 201 fragments.insert( keysets.begin(), keysets.end() ); 202 } else { 203 LOG(3, "DEBUG: Skipping atom " << iter->first << " as it's hydrogen."); 204 } 205 } 206 207 // reduce given fragments to homologous graphs to avoid multiple fittings 208 typedef std::map<KeySet, HomologyGraph> KeysetsToGraph_t; 209 KeysetsToGraph_t keyset_graphs; 210 typedef std::map<HomologyGraph, PartialNucleiChargeFitter::charges_t> GraphFittedChargeMap_t; 211 GraphFittedChargeMap_t fittedcharges_per_fragment; 212 HomologyContainer &homologies = World::getInstance().getHomologies(); 213 for (std::set<KeySet>::const_iterator fragmentiter = fragments.begin(); 214 fragmentiter != fragments.end(); ++fragmentiter) { 215 const KeySet &keyset = *fragmentiter; 216 const AtomFragmentsMap::indices_t &forceindices = atomfragments.getFullKeyset(keyset); 217 ASSERT( !forceindices.empty(), 218 "PotentialFitPartialChargesAction::performCall() - force keyset to " 219 +toString(keyset)+" is empty."); 220 KeySet forcekeyset; 221 forcekeyset.insert(forceindices.begin(), forceindices.end()); 222 forcekeyset.erase(-1); 223 const HomologyGraph graph(forcekeyset); 224 LOG(2, "DEBUG: Associating keyset " << forcekeyset << " with graph " << graph); 225 keyset_graphs.insert( std::make_pair(keyset, graph) ); 226 fittedcharges_per_fragment.insert( std::make_pair(graph, PartialNucleiChargeFitter::charges_t()) ); 221 227 } 222 228 223 229 /// then go through all fragments and get partial charges for each 224 typedef std::map< 225 KeySet, 226 PartialNucleiChargeFitter::charges_t> FragmentFittedChargeMap_t; 227 FragmentFittedChargeMap_t fittedcharges_per_fragment; 228 for (AtomFragmentsMap::keysets_t::const_iterator fragmentiter = fragments.begin(); 229 fragmentiter != fragments.end(); ++fragmentiter) { 230 // fragment specifies the homology fragment to use 231 SerializablePotential::ParticleTypes_t fragmentnumbers(fragmentiter->begin(), fragmentiter->end()); 232 233 // obtain range of homogolous fragments from container 234 HomologyContainer &homologies = World::getInstance().getHomologies(); 235 const HomologyGraph graph = getFirstGraphwithSpecifiedElements(homologies,fragmentnumbers); 230 for (GraphFittedChargeMap_t::iterator graphiter = fittedcharges_per_fragment.begin(); 231 graphiter != fittedcharges_per_fragment.end(); ++graphiter) { 232 const HomologyGraph &graph = graphiter->first; 233 LOG(2, "DEBUG: Now fitting charges to graph " << graph); 236 234 const HomologyContainer::range_t range = homologies.getHomologousGraphs(graph); 237 235 if (range.first == range.second) { … … 241 239 242 240 // fit and average partial charges over all homologous fragments 243 PartialNucleiChargeFitter::charges_t averaged_charges;241 PartialNucleiChargeFitter::charges_t &averaged_charges = graphiter->second; 244 242 const size_t NoFragments = 245 243 obtainAverageChargesOverFragments(averaged_charges, range, params.radius.get()); 246 244 if ((NoFragments == 0) && (range.first != range.second)) { 247 STATUS("Fitting for fragment "+toString(* fragmentiter)+" failed.");245 STATUS("Fitting for fragment "+toString(*graphiter)+" failed."); 248 246 return Action::failure; 249 247 } … … 253 251 enforceZeroTotalCharge(averaged_charges); 254 252 255 // place into map for later retrieval256 fittedcharges_per_fragment.insert( std::make_pair(*fragmentiter, averaged_charges));257 258 253 // output status info fitted charges 259 LOG(2, "DEBUG: For fragment " << * fragmentiter << " we have fitted the following charges "254 LOG(2, "DEBUG: For fragment " << *graphiter << " we have fitted the following charges " 260 255 << averaged_charges << ", averaged over " << NoFragments << " fragments."); 261 256 } … … 266 261 for (World::AtomSelectionConstIterator atomiter = world.beginAtomSelection(); 267 262 atomiter != world.endAtomSelection(); ++atomiter) { 263 const atom * walker = atomiter->second; 264 if (walker->getElementNo() == 1) { 265 // it's hydrogen, check its bonding and use its bond partner instead to request 266 // keysets 267 const BondList &ListOfBonds = walker->getListOfBonds(); 268 if ( ListOfBonds.size() != 1) { 269 ELOG(1, "Solitary hydrogen in atom " << atomiter->first << " detected, skipping."); 270 continue; 271 } 272 walker = (*ListOfBonds.begin())->GetOtherAtom(walker); 273 } 274 const atomId_t walkerid = walker->getId(); 268 275 const AtomFragmentsMap::AtomFragmentsMap_t::const_iterator keysetsiter = 269 atommap.find( atomiter->first);276 atommap.find(walkerid); 270 277 ASSERT(keysetsiter != atommap.end(), 271 278 "PotentialFitPartialChargesAction::performCall() - we checked already that " 272 +toString( atomiter->first)+" should be present!");279 +toString(walkerid)+" should be present!"); 273 280 const AtomFragmentsMap::keysets_t & keysets = keysetsiter->second; 274 281 … … 280 287 const KeySet &keyset = *keysetsiter; 281 288 289 const AtomFragmentsMap::indices_t &forcekeyset = atomfragments.getFullKeyset(keyset); 290 ASSERT( !forcekeyset.empty(), 291 "PotentialFitPartialChargesAction::performCall() - force keyset to " 292 +toString(keyset)+" is empty."); 293 282 294 // find the associated charge in the charge vector 283 const FragmentFittedChargeMap_t::const_iterator chargesiter = 284 fittedcharges_per_fragment.find(keyset); 295 const HomologyGraph &graph = keyset_graphs[keyset]; 296 const GraphFittedChargeMap_t::const_iterator chargesiter = 297 fittedcharges_per_fragment.find(graph); 285 298 ASSERT(chargesiter != fittedcharges_per_fragment.end(), 286 299 "PotentialFitPartialChargesAction::performCall() - no charge to "+toString(keyset) 287 300 +" any longer present in fittedcharges_per_fragment?"); 288 301 const PartialNucleiChargeFitter::charges_t &charges = chargesiter->second; 302 ASSERT( charges.size() == forcekeyset.size(), 303 "PotentialFitPartialChargesAction::performCall() - charges " 304 +toString(charges.size())+" and keyset "+toString(forcekeyset.size()) 305 +" do not have the same length?"); 289 306 PartialNucleiChargeFitter::charges_t::const_iterator chargeiter = 290 307 charges.begin(); 291 const KeySet::const_iterator keysetiter = keyset.find(atomiter->first); 292 ASSERT( keysetiter != keyset.end(), 308 const AtomFragmentsMap::indices_t::const_iterator forcekeysetiter = 309 std::find(forcekeyset.begin(), forcekeyset.end(), atomiter->first); 310 ASSERT( forcekeysetiter != forcekeyset.end(), 293 311 "PotentialFitPartialChargesAction::performCall() - atom " 294 +toString(atomiter->first)+" not contained in keyset "+toString(keyset)); 295 std::advance(chargeiter, std::distance(keyset.begin(), keysetiter)); 296 ASSERT( chargeiter != charges.end(), 297 "PotentialFitPartialChargesAction::performCall() - charges " 298 +toString(charges.size())+" and keyset "+toString(keyset.size()) 299 +" do not have the same length?"); 312 +toString(atomiter->first)+" not contained in force keyset "+toString(forcekeyset)); 313 std::advance(chargeiter, std::distance(forcekeyset.begin(), forcekeysetiter)); 300 314 301 315 // and add onto charge sum … … 305 319 } 306 320 // average to obtain final partial charge for this atom 307 average_charge = 1./(size_t)NoFragments;321 average_charge *= 1./(double)NoFragments; 308 322 fitted_charges.insert( std::make_pair(atomiter->first, average_charge) ); 323 324 LOG(2, "DEBUG: For atom " << atomiter->first << " we have an average charge of " 325 << average_charge); 309 326 } 310 327
Note:
See TracChangeset
for help on using the changeset viewer.