Changeset c1ec8e for src/Actions


Ignore:
Timestamp:
May 18, 2016, 10:02:53 PM (9 years ago)
Author:
Frederik Heber <heber@…>
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:
91f907
Parents:
01120c
git-author:
Frederik Heber <heber@…> (03/07/16 21:03:37)
git-committer:
Frederik Heber <heber@…> (05/18/16 22:02:53)
Message:

Split FitPartialChargesAction's extensive performCall() into subfunctions.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Actions/PotentialAction/FitPartialChargesAction.cpp

    r01120c rc1ec8e  
    171171}
    172172
    173 ActionState::ptr PotentialFitPartialChargesAction::performCall()
    174 {
    175   // check for selected atoms
    176   const World &world = const_cast<const World &>(World::getInstance());
    177   if (world.beginAtomSelection() == world.endAtomSelection()) {
    178     STATUS("There are no atoms selected for fitting partial charges to.");
    179     return Action::failure;
    180   }
    181 
    182   /// obtain possible fragments to each selected atom
    183   const AtomFragmentsMap &atomfragments = AtomFragmentsMap::getConstInstance();
    184   if (!atomfragments.checkCompleteness()) {
    185     STATUS("AtomFragmentsMap failed internal consistency check, missing forcekeysets?");
    186     return Action::failure;
    187   }
     173static
     174std::set<KeySet> accumulateKeySetsForAtoms(
     175    const AtomFragmentsMap::AtomFragmentsMap_t &_atommap,
     176    const std::vector<const atom *> &_selected_atoms)
     177{
    188178  std::set<KeySet> fragments;
    189   const AtomFragmentsMap::AtomFragmentsMap_t &atommap = atomfragments.getMap();
    190   for (World::AtomSelectionConstIterator iter = world.beginAtomSelection();
    191       iter != world.endAtomSelection(); ++iter) {
     179  for (std::vector<const atom *>::const_iterator iter = _selected_atoms.begin();
     180      iter != _selected_atoms.end(); ++iter) {
     181    const atomId_t atomid = (*iter)->getId();
    192182    const AtomFragmentsMap::AtomFragmentsMap_t::const_iterator atomiter =
    193         atommap.find(iter->first);
    194     if (iter->second->getElementNo() != 1) {
    195       if (atomiter == atommap.end()) {
    196         ELOG(2, "There are no fragments associated to " << iter->first << ".");
     183        _atommap.find(atomid);
     184    if ((*iter)->getElementNo() != 1) {
     185      if (atomiter == _atommap.end()) {
     186        ELOG(2, "There are no fragments associated to " << atomid << ".");
    197187        continue;
    198188      }
    199189      const AtomFragmentsMap::keysets_t &keysets = atomiter->second;
    200       LOG(2, "DEBUG: atom " << iter->first << " has " << keysets.size() << " fragments.");
     190      LOG(2, "DEBUG: atom " << atomid << " has " << keysets.size() << " fragments.");
    201191      fragments.insert( keysets.begin(), keysets.end() );
    202192    } 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) {
     193      LOG(3, "DEBUG: Skipping atom " << atomid << " as it's hydrogen.");
     194    }
     195  }
     196  return fragments;
     197}
     198
     199static
     200void getKeySetsToGraphMapping(
     201    std::map<KeySet, HomologyGraph> &_keyset_graphs,
     202    std::map<HomologyGraph, PartialNucleiChargeFitter::charges_t> &_fittedcharges_per_fragment,
     203    const std::set<KeySet> &_fragments,
     204    const AtomFragmentsMap &_atomfragments)
     205{
     206  for (std::set<KeySet>::const_iterator fragmentiter = _fragments.begin();
     207      fragmentiter != _fragments.end(); ++fragmentiter) {
    215208    const KeySet &keyset = *fragmentiter;
    216     const AtomFragmentsMap::indices_t &forceindices = atomfragments.getFullKeyset(keyset);
     209    const AtomFragmentsMap::indices_t &forceindices = _atomfragments.getFullKeyset(keyset);
    217210    ASSERT( !forceindices.empty(),
    218         "PotentialFitPartialChargesAction::performCall() - force keyset to "
    219         +toString(keyset)+" is empty.");
     211        "getKeySetsToGraphMapping() - force keyset to "+toString(keyset)+" is empty.");
    220212    KeySet forcekeyset;
    221213    forcekeyset.insert(forceindices.begin(), forceindices.end());
     
    223215    const HomologyGraph graph(forcekeyset);
    224216    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()) );
    227   }
    228 
    229   /// then go through all fragments and get partial charges for each
    230   for (GraphFittedChargeMap_t::iterator graphiter = fittedcharges_per_fragment.begin();
    231       graphiter != fittedcharges_per_fragment.end(); ++graphiter) {
     217    _keyset_graphs.insert( std::make_pair(keyset, graph) );
     218    _fittedcharges_per_fragment.insert( std::make_pair(graph, PartialNucleiChargeFitter::charges_t()) );
     219  }
     220}
     221
     222static
     223bool getPartialChargesForAllGraphs(
     224    std::map<HomologyGraph, PartialNucleiChargeFitter::charges_t> &_fittedcharges_per_fragment,
     225    const HomologyContainer &_homologies,
     226    const double _mask_radius,
     227    const bool enforceZeroCharge)
     228{
     229  typedef std::map<HomologyGraph, PartialNucleiChargeFitter::charges_t> GraphFittedChargeMap_t;
     230  for (GraphFittedChargeMap_t::iterator graphiter = _fittedcharges_per_fragment.begin();
     231      graphiter != _fittedcharges_per_fragment.end(); ++graphiter) {
    232232    const HomologyGraph &graph = graphiter->first;
    233233    LOG(2, "DEBUG: Now fitting charges to graph " << graph);
    234     const HomologyContainer::range_t range = homologies.getHomologousGraphs(graph);
     234    const HomologyContainer::range_t range = _homologies.getHomologousGraphs(graph);
    235235    if (range.first == range.second) {
    236       STATUS("HomologyContainer does not contain specified fragment.");
    237       return Action::failure;
     236      ELOG(0, "HomologyContainer does not contain specified fragment.");
     237      return false;
    238238    }
    239239
     
    241241    PartialNucleiChargeFitter::charges_t &averaged_charges = graphiter->second;
    242242    const size_t NoFragments =
    243         obtainAverageChargesOverFragments(averaged_charges, range, params.radius.get());
     243        obtainAverageChargesOverFragments(averaged_charges, range, _mask_radius);
    244244    if ((NoFragments == 0) && (range.first != range.second)) {
    245       STATUS("Fitting for fragment "+toString(*graphiter)+" failed.");
    246       return Action::failure;
     245      ELOG(0, "Fitting for fragment "+toString(*graphiter)+" failed.");
     246      return false;
    247247    }
    248248
    249249    // make sum of charges zero if desired
    250     if (params.enforceZeroCharge.get())
     250    if (enforceZeroCharge)
    251251      enforceZeroTotalCharge(averaged_charges);
    252252
     
    255255        << averaged_charges << ", averaged over " << NoFragments << " fragments.");
    256256  }
    257 
    258   /// obtain average charge for each atom the fitted charges over all its fragments
     257  return true;
     258}
     259
     260double fitAverageChargeToAtom(
     261    const atom * const _walker,
     262    const AtomFragmentsMap &_atomfragments,
     263    const std::map<KeySet, HomologyGraph> &_keyset_graphs,
     264    const std::map<HomologyGraph, PartialNucleiChargeFitter::charges_t> &_fittedcharges_per_fragment)
     265{
     266  typedef std::map<HomologyGraph, PartialNucleiChargeFitter::charges_t> GraphFittedChargeMap_t;
     267  const atom * surrogate = _walker;
     268  if (surrogate->getElementNo() == 1) {
     269    // it's hydrogen, check its bonding and use its bond partner instead to request
     270    // keysets
     271    const BondList &ListOfBonds = surrogate->getListOfBonds();
     272    if ( ListOfBonds.size() != 1) {
     273      ELOG(1, "Solitary hydrogen in atom " << surrogate->getId() << " detected, skipping.");
     274      return 0.;
     275    }
     276    surrogate = (*ListOfBonds.begin())->GetOtherAtom(surrogate);
     277  }
     278  const atomId_t walkerid = surrogate->getId();
     279  const AtomFragmentsMap::AtomFragmentsMap_t &atommap = _atomfragments.getMap();
     280  const AtomFragmentsMap::AtomFragmentsMap_t::const_iterator keysetsiter =
     281      atommap.find(walkerid);
     282  ASSERT(keysetsiter != atommap.end(),
     283      "fitAverageChargeToAtom() - we checked already that "+toString(walkerid)
     284      +" should be present!");
     285  const AtomFragmentsMap::keysets_t & keysets = keysetsiter->second;
     286
     287  double average_charge = 0.;
     288  size_t NoFragments = 0;
     289  // go over all fragments associated to this atom
     290  for (AtomFragmentsMap::keysets_t::const_iterator keysetsiter = keysets.begin();
     291      keysetsiter != keysets.end(); ++keysetsiter) {
     292    const KeySet &keyset = *keysetsiter;
     293
     294    const AtomFragmentsMap::indices_t &forcekeyset = _atomfragments.getFullKeyset(keyset);
     295    ASSERT( !forcekeyset.empty(),
     296        "fitAverageChargeToAtom() - force keyset to "+toString(keyset)+" is empty.");
     297
     298    // find the associated charge in the charge vector
     299    std::map<KeySet, HomologyGraph>::const_iterator keysetgraphiter =
     300        _keyset_graphs.find(keyset);
     301    ASSERT( keysetgraphiter != _keyset_graphs.end(),
     302        "fitAverageChargeToAtom() - keyset "+toString(keyset)
     303        +" not contained in keyset_graphs.");
     304    const HomologyGraph &graph = keysetgraphiter->second;
     305    const GraphFittedChargeMap_t::const_iterator chargesiter =
     306        _fittedcharges_per_fragment.find(graph);
     307    ASSERT(chargesiter != _fittedcharges_per_fragment.end(),
     308        "fitAverageChargeToAtom() - no charge to "+toString(keyset)
     309        +" any longer present in fittedcharges_per_fragment?");
     310    const PartialNucleiChargeFitter::charges_t &charges = chargesiter->second;
     311    ASSERT( charges.size() == forcekeyset.size(),
     312        "fitAverageChargeToAtom() - charges "+toString(charges.size())+" and keyset "
     313        +toString(forcekeyset.size())+" do not have the same length?");
     314    PartialNucleiChargeFitter::charges_t::const_iterator chargeiter =
     315        charges.begin();
     316    const AtomFragmentsMap::indices_t::const_iterator forcekeysetiter =
     317        std::find(forcekeyset.begin(), forcekeyset.end(), _walker->getId());
     318    ASSERT( forcekeysetiter != forcekeyset.end(),
     319        "fitAverageChargeToAtom() - atom "+toString(_walker->getId())
     320        +" not contained in force keyset "+toString(forcekeyset));
     321    std::advance(chargeiter, std::distance(forcekeyset.begin(), forcekeysetiter));
     322
     323    // and add onto charge sum
     324    const double & charge_in_fragment = *chargeiter;
     325    average_charge += charge_in_fragment;
     326    ++NoFragments;
     327  }
     328  // average to obtain final partial charge for this atom
     329  average_charge *= 1./(double)NoFragments;
     330
     331  return average_charge;
     332}
     333
     334void addToParticleRegistry(
     335    const ParticleFactory &factory,
     336    const periodentafel &periode,
     337    const std::map<atomId_t, double> &_fitted_charges)
     338{
    259339  typedef std::map<atomId_t, double> fitted_charges_t;
    260   fitted_charges_t fitted_charges;
    261   for (World::AtomSelectionConstIterator atomiter = world.beginAtomSelection();
    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();
    275     const AtomFragmentsMap::AtomFragmentsMap_t::const_iterator keysetsiter =
    276         atommap.find(walkerid);
    277     ASSERT(keysetsiter != atommap.end(),
    278         "PotentialFitPartialChargesAction::performCall() - we checked already that "
    279         +toString(walkerid)+" should be present!");
    280     const AtomFragmentsMap::keysets_t & keysets = keysetsiter->second;
    281 
    282     double average_charge = 0.;
    283     size_t NoFragments = 0;
    284     // go over all fragments associated to this atom
    285     for (AtomFragmentsMap::keysets_t::const_iterator keysetsiter = keysets.begin();
    286         keysetsiter != keysets.end(); ++keysetsiter) {
    287       const KeySet &keyset = *keysetsiter;
    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 
    294       // find the associated charge in the charge vector
    295       const HomologyGraph &graph = keyset_graphs[keyset];
    296       const GraphFittedChargeMap_t::const_iterator chargesiter =
    297           fittedcharges_per_fragment.find(graph);
    298       ASSERT(chargesiter != fittedcharges_per_fragment.end(),
    299           "PotentialFitPartialChargesAction::performCall() - no charge to "+toString(keyset)
    300           +" any longer present in fittedcharges_per_fragment?");
    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?");
    306       PartialNucleiChargeFitter::charges_t::const_iterator chargeiter =
    307           charges.begin();
    308       const AtomFragmentsMap::indices_t::const_iterator forcekeysetiter =
    309           std::find(forcekeyset.begin(), forcekeyset.end(), atomiter->first);
    310       ASSERT( forcekeysetiter != forcekeyset.end(),
    311           "PotentialFitPartialChargesAction::performCall() - atom "
    312           +toString(atomiter->first)+" not contained in force keyset "+toString(forcekeyset));
    313       std::advance(chargeiter, std::distance(forcekeyset.begin(), forcekeysetiter));
    314 
    315       // and add onto charge sum
    316       const double & charge_in_fragment = *chargeiter;
    317       average_charge += charge_in_fragment;
    318       ++NoFragments;
    319     }
    320     // average to obtain final partial charge for this atom
    321     average_charge *= 1./(double)NoFragments;
    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);
    326   }
    327 
    328   /// place all fitted charges into ParticleRegistry
    329   const ParticleFactory &factory =
    330       const_cast<const ParticleFactory&>(ParticleFactory::getInstance());
    331   const periodentafel &periode = *World::getInstance().getPeriode();
    332   for (fitted_charges_t::const_iterator chargeiter = fitted_charges.begin();
    333       chargeiter != fitted_charges.end(); ++chargeiter) {
     340  for (fitted_charges_t::const_iterator chargeiter = _fitted_charges.begin();
     341      chargeiter != _fitted_charges.end(); ++chargeiter) {
    334342    const atom * const walker = World::getInstance().getAtom(AtomById(chargeiter->first));
    335343    ASSERT( walker != NULL,
     
    343351    factory.createInstance(name, elementno, charge);
    344352  }
     353}
     354
     355ActionState::ptr PotentialFitPartialChargesAction::performCall()
     356{
     357  // check for selected atoms
     358  const World &world = const_cast<const World &>(World::getInstance());
     359  if (world.beginAtomSelection() == world.endAtomSelection()) {
     360    STATUS("There are no atoms selected for fitting partial charges to.");
     361    return Action::failure;
     362  }
     363
     364  /// obtain possible fragments to each selected atom
     365  const AtomFragmentsMap &atomfragments = AtomFragmentsMap::getConstInstance();
     366  if (!atomfragments.checkCompleteness()) {
     367    STATUS("AtomFragmentsMap failed internal consistency check, missing forcekeysets?");
     368    return Action::failure;
     369  }
     370  std::set<KeySet> fragments =
     371      accumulateKeySetsForAtoms( atomfragments.getMap(), world.getSelectedAtoms());
     372
     373  // reduce given fragments to homologous graphs to avoid multiple fittings
     374  typedef std::map<KeySet, HomologyGraph> KeysetsToGraph_t;
     375  KeysetsToGraph_t keyset_graphs;
     376  typedef std::map<HomologyGraph, PartialNucleiChargeFitter::charges_t> GraphFittedChargeMap_t;
     377  GraphFittedChargeMap_t fittedcharges_per_fragment;
     378  getKeySetsToGraphMapping(keyset_graphs, fittedcharges_per_fragment, fragments, atomfragments);
     379
     380  /// then go through all fragments and get partial charges for each
     381  const bool status = getPartialChargesForAllGraphs(
     382      fittedcharges_per_fragment,
     383      World::getInstance().getHomologies(),
     384      params.radius.get(),
     385      params.enforceZeroCharge.get());
     386  if (!status)
     387    return Action::failure;
     388
     389  /// obtain average charge for each atom the fitted charges over all its fragments
     390  typedef std::map<atomId_t, double> fitted_charges_t;
     391  fitted_charges_t fitted_charges;
     392  for (World::AtomSelectionConstIterator atomiter = world.beginAtomSelection();
     393      atomiter != world.endAtomSelection(); ++atomiter) {
     394    const double average_charge = fitAverageChargeToAtom(
     395        atomiter->second, atomfragments, keyset_graphs, fittedcharges_per_fragment);
     396
     397    if (average_charge != 0.) {
     398      LOG(2, "DEBUG: For atom " << atomiter->first << " we have an average charge of "
     399          << average_charge);
     400
     401      fitted_charges.insert( std::make_pair(atomiter->first, average_charge) );
     402    }
     403  }
     404
     405  /// place all fitted charges into ParticleRegistry
     406  addToParticleRegistry(
     407      ParticleFactory::getConstInstance(),
     408      *World::getInstance().getPeriode(),
     409      fitted_charges);
    345410
    346411  return Action::success;
Note: See TracChangeset for help on using the changeset viewer.