/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2021 Frederik Heber. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * MoleCuilder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MoleCuilder. If not, see . */ /* * GeneratePotentialsAction.cpp * * Created on: May 13, 2021 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif // include headers that implement a archive in simple text format // and before MemDebug due to placement new #include #include //#include "CodePatterns/MemDebug.hpp" #include #include #include #include #include "Actions/PotentialAction/GeneratePotentialsAction.hpp" #include "CodePatterns/Log.hpp" #include "Potentials/EmpiricalPotential.hpp" #include "Potentials/Exceptions.hpp" #include "Potentials/PotentialFactory.hpp" #include "Potentials/PotentialRegistry.hpp" #include "Potentials/PotentialTrainer.hpp" using namespace MoleCuilder; // and construct the stuff #include "GeneratePotentialsAction.def" #include "Action_impl_pre.hpp" /** =========== define the function ====================== */ ActionState::ptr PotentialGeneratePotentialsAction::performCall() { // fragment specifies the homology fragment to use SerializablePotential::ParticleTypes_t fragmentnumbers = PotentialTrainer::getNumbersFromElements(params.fragment.get()); // parse homologies into container const HomologyContainer &homologies = World::getInstance().getHomologies(); // then we ought to pick the right HomologyGraph ... const HomologyGraph graph = PotentialTrainer::getFirstGraphwithSpecifiedElements(homologies,fragmentnumbers); if (graph != HomologyGraph()) { LOG(1, "First representative graph containing fragment " << fragmentnumbers << " is " << graph << "."); } else { STATUS("Specific fragment "+toString(fragmentnumbers)+" not found in homologies!"); return Action::failure; } // gather list of potential candidates std::vector potentials; if (!params.potential_list.isSet()) { for (unsigned int i=0; i unique_models_t; unique_models_t unique_models; BOOST_FOREACH(std::string &potential_name, potentials) { unique_models.clear(); /** * Approach: * 1. get the number of particle types for the potential * 2. create all combinations for the given elements and the number of particles * 3. create the potential * 4. gather all created potential's binding model in a set * 5. if the binding model is already contained, discard the potential * 6. if the binding model is not contained in the fragment's graph, discard it * 7. if still valid, register potential */ // first need to construct potential, then may access it const enum PotentialTypes potential_type = factory.getTypeForName(potential_name); EmpiricalPotential const * const defaultPotential = factory.getDefaultPotential(potential_type); /// 1. get its number of particles const unsigned int num_particles = defaultPotential->getParticleTypeNumber(); LOG(1, "INFO: Number of particles of " << potential_name << " is " << num_particles); if (num_particles > fragmentnumbers.size()) { LOG(2, "DEBUG: Skipping potential " << potential_name << " as " << num_particles << " required but fragment has only " << fragmentnumbers.size() << " particles."); continue; } /** * 2. create all unique combinations for the given elements and the number of particles * * Use the {1,...,fragmentnumbers.size()}, create every permutation and pick the first num_particle * from the given charges. Finally, put all those into a set to retain only unique combinations. */ std::set charges_for_potentials; std::vector selection(boost::counting_iterator(0), boost::counting_iterator(fragmentnumbers.size())); do { charges.clear(); for (unsigned int i = 0; i < num_particles; ++i) { charges.push_back(fragmentnumbers[selection[i]]); } // LOG(3, "DEBUG: Inserting charges " << charges); charges_for_potentials.insert(charges); } while (std::next_permutation(selection.begin(), selection.end())); for (std::set::const_iterator iter = charges_for_potentials.begin(); iter != charges_for_potentials.end(); ++iter) { /// 3. create the potential EmpiricalPotential* potential = factory.createInstance(potential_name, *iter); /// 4. Gather all created potential's binding model in a set std::pair inserter = unique_models.insert(potential->getBindingModel()); /// 5. if the binding model is already contained, discard the potential if (inserter.second) { /// 6. if the binding model is not contained in the fragment's graph, discard it if (graph.contains(potential->getBindingModel().getGraph())) { /// 7. If still valid, register potential LOG(2, "DEBUG: Registering potential " << *potential); registry.registerInstance(potential); continue; } } LOG(2, "DEBUG: Discarding potential " << *potential); delete(potential); } } return Action::success; } ActionState::ptr PotentialGeneratePotentialsAction::performUndo(ActionState::ptr _state) { STATUS("Undo of PotentialGeneratePotentialsAction not implemented."); return Action::failure; } ActionState::ptr PotentialGeneratePotentialsAction::performRedo(ActionState::ptr _state){ STATUS("Redo of PotentialGeneratePotentialsAction not implemented."); return Action::failure; } bool PotentialGeneratePotentialsAction::canUndo() { return false; } bool PotentialGeneratePotentialsAction::shouldUndo() { return false; } /** =========== end of function ====================== */