Changeset a13e21 for src/FunctionApproximation/Extractors.cpp
- Timestamp:
- Oct 2, 2016, 1:59:41 PM (9 years ago)
- Branches:
- Fix_FitPotential_needs_atomicnumbers
- Children:
- 6ffdf2
- Parents:
- 8d5db8
- git-author:
- Frederik Heber <heber@…> (10/02/16 13:59:35)
- git-committer:
- Frederik Heber <heber@…> (10/02/16 13:59:41)
- File:
-
- 1 edited
-
src/FunctionApproximation/Extractors.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/FunctionApproximation/Extractors.cpp
r8d5db8 ra13e21 55 55 56 56 using namespace boost::assign; 57 58 FunctionModel::arguments_t59 Extractors::gatherAllDistanceArguments(60 const Fragment::positions_t& positions,61 const Fragment::charges_t& charges,62 const size_t globalid)63 {64 FunctionModel::arguments_t result;65 66 // go through current configuration and gather all other distances67 Fragment::positions_t::const_iterator firstpositer = positions.begin();68 for (;firstpositer != positions.end(); ++firstpositer) {69 Fragment::positions_t::const_iterator secondpositer = positions.begin();//firstpositer;70 for (; secondpositer != positions.end(); ++secondpositer) {71 if (firstpositer == secondpositer)72 continue;73 argument_t arg;74 const Vector firsttemp((*firstpositer)[0],(*firstpositer)[1],(*firstpositer)[2]);75 const Vector secondtemp((*secondpositer)[0],(*secondpositer)[1],(*secondpositer)[2]);76 arg.distance = firsttemp.distance(secondtemp);77 arg.types = std::make_pair(78 charges[ std::distance(positions.begin(), firstpositer) ],79 charges[ std::distance(positions.begin(), secondpositer) ]80 );81 arg.indices = std::make_pair(82 std::distance(83 positions.begin(), firstpositer),84 std::distance(85 positions.begin(), secondpositer)86 );87 arg.globalid = globalid;88 result.push_back(arg);89 }90 }91 92 return result;93 }94 57 95 58 FunctionModel::arguments_t … … 131 94 } 132 95 133 Fragment::positions_t Extractors::_detail::gatherPositionsFromTargets(134 const Fragment::positions_t& positions,135 const Fragment::charges_t& charges,136 const chargeiters_t &targets137 )138 {139 Fragment::positions_t filtered_positions;140 for (chargeiters_t::const_iterator firstpairiter = targets.begin();141 firstpairiter != targets.end(); ++firstpairiter) {142 Fragment::positions_t::const_iterator positer = positions.begin();143 const size_t steps = std::distance(charges.begin(), *firstpairiter);144 std::advance(positer, steps);145 filtered_positions.push_back(*positer);146 }147 return filtered_positions;148 }149 150 FunctionModel::arguments_t Extractors::_detail::gatherDistancesFromTargets(151 const Fragment::positions_t& positions,152 const Fragment::charges_t& charges,153 const chargeiters_t &targets,154 const size_t globalid155 )156 {157 Fragment::positions_t filtered_positions;158 Fragment::charges_t filtered_charges;159 for (chargeiters_t::const_iterator firstpairiter = targets.begin();160 firstpairiter != targets.end(); ++firstpairiter) {161 Fragment::positions_t::const_iterator positer = positions.begin();162 const size_t steps = std::distance(charges.begin(), *firstpairiter);163 std::advance(positer, steps);164 filtered_positions.push_back(*positer);165 filtered_charges.push_back(**firstpairiter);166 }167 return Extractors::gatherAllSymmetricDistanceArguments(168 filtered_positions,169 filtered_charges,170 globalid);171 }172 173 96 Extractors::elementcounts_t 174 97 Extractors::_detail::getElementCounts( … … 188 111 return elementcounts; 189 112 } 190 191 Extractors::elementtargets_t192 Extractors::_detail::convertElementcountsToTargets(193 const Fragment::charges_t &charges,194 const elementcounts_t &elementcounts195 )196 {197 elementtargets_t elementtargets;198 for (elementcounts_t::const_iterator countiter = elementcounts.begin();199 countiter != elementcounts.end();200 ++countiter) {201 chargeiter_t chargeiter = charges.begin();202 const element_t &element = countiter->first;203 const count_t &count = countiter->second;204 for (count_t i = 0; i < count; ++i) {205 chargeiter_t tempiter = std::find(chargeiter, charges.end(), element);206 if (tempiter != charges.end()) {207 // try to insert new list208 std::pair< elementtargets_t::iterator, bool> inserter =209 elementtargets.insert( std::make_pair( countiter->first, chargeiters_t(1, tempiter)) );210 // if already present, append to it211 if (!inserter.second) {212 inserter.first->second.push_back(tempiter);213 } else { // if created, increase vector's reserve to known size214 inserter.first->second.reserve(countiter->second);215 }216 // search from this element onwards then217 chargeiter = ++tempiter;218 } else {219 ELOG(1, "Could not find desired number " << count << " of element "220 << element << " in fragment with " << charges << ".");221 return Extractors::elementtargets_t();222 }223 }224 }225 return elementtargets;226 }227 228 Extractors::elementtargets_t229 Extractors::_detail::convertChargesToTargetMap(230 const Fragment::charges_t& charges,231 Fragment::charges_t elements232 )233 {234 // place each charge into a map235 elementtargets_t completeelementtargets;236 for (chargeiter_t chargeiter = charges.begin();237 chargeiter != charges.end();238 ++chargeiter) {239 std::pair< elementtargets_t::iterator, bool> inserter =240 completeelementtargets.insert( std::make_pair( *chargeiter, chargeiters_t(1, chargeiter)) );241 // if already present, append to it242 if (!inserter.second) {243 inserter.first->second.push_back(chargeiter);244 }245 }246 // pick out desired charges only247 std::sort(elements.begin(), elements.end());248 Fragment::charges_t::iterator eraseiter =249 std::unique(elements.begin(), elements.end());250 elements.erase(eraseiter, elements.end());251 elementtargets_t elementtargets;252 for(Fragment::charges_t::const_iterator iter = elements.begin();253 iter != elements.end();254 ++iter) {255 elementtargets_t::const_iterator finditer = completeelementtargets.find(*iter);256 ASSERT( finditer != completeelementtargets.end(),257 "Extractors::_detail::convertChargesToTargetMap() - no element "+toString(*iter)+" present?");258 std::pair< elementtargets_t::iterator, bool> inserter =259 elementtargets.insert( std::make_pair( finditer->first, finditer->second) );260 ASSERT( inserter.second,261 "Extractors::_detail::convertChargesToTargetMap() - key twice?");262 }263 return elementtargets;264 }265 266 267 Extractors::chargeiters_t268 Extractors::_detail::realignElementtargets(269 const elementtargets_t &elementtargets,270 const Fragment::charges_t elements,271 const elementcounts_t &elementcounts272 )273 {274 chargeiters_t targets;275 elementcounts_t counts; // how many chargeiters of this element have been used276 if (!elements.empty()) { // skip if no elements given277 targets.reserve(elements.size());278 for (Fragment::charges_t::const_iterator elementiter = elements.begin();279 elementiter != elements.end(); ++elementiter) {280 const element_t &element = *elementiter;281 count_t &count = counts[element]; // if not present, std::map creates instances with default of 0282 #ifndef NDEBUG283 {284 elementcounts_t::const_iterator testiter = elementcounts.find(element);285 ASSERT( (testiter != elementcounts.end()) && (count < testiter->second),286 "Extractors::_detail::realignElementTargets() - we want to use more chargeiters for element "287 +toString(element)+" than we counted initially.");288 }289 #endif290 elementtargets_t::const_iterator targetiter = elementtargets.find(element);291 if (targetiter != elementtargets.end()) {292 const chargeiters_t &chargeiters = targetiter->second;293 const chargeiter_t &chargeiter = chargeiters[count++];294 targets.push_back(chargeiter);295 }296 }297 }298 return targets;299 }300 301 FunctionModel::arguments_t302 Extractors::gatherAllDistancesFromFragment(303 const Fragment::positions_t& positions,304 const Fragment::charges_t& charges,305 const Fragment::charges_t elements,306 const size_t globalid307 )308 {309 /// The main problem here is that we have to know how many same310 /// elements (but different atoms!) we are required to find. Hence,311 /// we first have to count same elements, then get different targets312 /// for each and then associated them in correct order back again.313 314 // 0. if no elements given, we return empty arguments315 if (elements.empty())316 return FunctionModel::arguments_t();317 318 // 1. we have to place each charge into a map as unique chargeiter, i.e. map319 elementtargets_t elementtargets =320 Extractors::_detail::convertChargesToTargetMap(321 charges,322 elements);323 324 // 2. now we have to combine elementcounts out of elementtargets per desired element325 // in a combinatorial fashion326 targets_per_combination_t combinations =327 Extractors::_detail::CombineChargesAndTargets(328 elements,329 elementtargets);330 331 // 3. finally, convert chargeiters into argument list332 FunctionModel::arguments_t args =333 Extractors::_detail::convertTargetsToArguments(334 positions,335 charges,336 combinations,337 globalid);338 339 return args;340 }341 342 Extractors::targets_per_combination_t343 Extractors::_detail::CombineChargesAndTargets(344 const Fragment::charges_t& elements,345 const elementtargets_t& elementtargets346 )347 {348 // recursively create all correct combinations of targets349 targets_per_combination_t combinations;350 chargeiters_t currenttargets;351 boost::function<void (const chargeiters_t ¤ttargets)> addFunction =352 boost::bind(&targets_per_combination_t::push_back,353 boost::ref(combinations),354 _1);355 pickLastElementAsTarget(elements, elementtargets, currenttargets, addFunction);356 357 return combinations;358 }359 360 const Fragment::position_t& getPositionToChargeIter(361 const Fragment::positions_t& positions,362 const Fragment::charges_t& charges,363 const Extractors::chargeiter_t &iter364 )365 {366 Fragment::positions_t::const_iterator positer = positions.begin();367 std::advance(positer, std::distance(charges.begin(), iter));368 const Fragment::position_t &position = *positer;369 return position;370 }371 372 373 FunctionModel::arguments_t374 Extractors::_detail::convertTargetsToArguments(375 const Fragment::positions_t& positions,376 const Fragment::charges_t& charges,377 const targets_per_combination_t combinations,378 const size_t globalid379 )380 {381 FunctionModel::arguments_t args;382 // create arguments from each combination. We cannot use383 // gatherallSymmetricDistanceArguments() because it would not create the384 // correct indices.385 for (targets_per_combination_t::const_iterator iter = combinations.begin();386 iter != combinations.end();387 ++iter) {388 for(chargeiters_t::const_iterator firstiter = iter->begin();389 firstiter != iter->end();390 ++firstiter) {391 const Fragment::position_t &firstpos =392 getPositionToChargeIter(positions, charges, *firstiter);393 const Vector firsttemp(firstpos[0],firstpos[1],firstpos[2]);394 for(chargeiters_t::const_iterator seconditer = firstiter;395 seconditer != iter->end();396 ++seconditer) {397 if (firstiter == seconditer)398 continue;399 const Fragment::position_t &secondpos =400 getPositionToChargeIter(positions, charges, *seconditer);401 const Vector secondtemp(secondpos[0],secondpos[1],secondpos[2]);402 argument_t arg;403 arg.distance = firsttemp.distance(secondtemp);404 arg.indices.first = std::distance(charges.begin(), *firstiter);405 arg.indices.second = std::distance(charges.begin(), *seconditer);406 arg.types.first = **firstiter;407 arg.types.second = **seconditer;408 args.push_back( arg );409 }410 }411 }412 413 return args;414 }415 416 void417 Extractors::_detail::pickLastElementAsTarget(418 Fragment::charges_t elements,419 elementtargets_t elementtargets,420 chargeiters_t ¤ttargets,421 boost::function<void (const chargeiters_t ¤ttargets)> &addFunction422 )423 {424 // get last element from charges425 ASSERT( !elements.empty(),426 "Extractors::_detail::pickLastElementAsTarget() - no elements given to pick targets for.");427 const Fragment::charge_t charge = elements.back();428 elements.pop_back();429 elementtargets_t::iterator iter = elementtargets.find(charge);430 if (iter == elementtargets.end())431 return;432 bool NotEmpty = !iter->second.empty();433 while (NotEmpty) {434 // get last target from the vector of chargeiters435 chargeiter_t target = iter->second.back();436 iter->second.pop_back();437 // remove this key if empty438 if (iter->second.empty()) {439 elementtargets.erase(iter);440 NotEmpty = false;441 }442 currenttargets.push_back(target);443 if (elements.empty()) {444 // call add function445 {446 std::stringstream targetstream;447 BOOST_FOREACH( chargeiter_t target, currenttargets ) {448 targetstream << " " << *target;449 }450 LOG(3, "DEBUG: Adding set" << targetstream.str() << ".");451 }452 addFunction(currenttargets);453 } else {454 // if not, call us recursively455 pickLastElementAsTarget(elements, elementtargets, currenttargets, addFunction);456 }457 // pop last in currenset again458 currenttargets.pop_back();459 }460 }461 462 Extractors::chargeiters_t463 Extractors::_detail::gatherTargetsFromFragment(464 const Fragment::charges_t& charges,465 const Fragment::charges_t elements466 )467 {468 /// The main problem here is that we have to know how many same469 /// elements (but different atoms!) we are required to find. Hence,470 /// we first have to count same elements, then get different targets471 /// for each and then associated them in correct order back again.472 473 // 1. we have to make elements unique with counts, hence convert to map474 elementcounts_t elementcounts =475 Extractors::_detail::getElementCounts(elements);476 477 // 2. then for each element we need as many targets (chargeiters) as counts478 elementtargets_t elementtargets =479 Extractors::_detail::convertElementcountsToTargets(charges, elementcounts);480 481 // 3. we go again through elements and use one found target for each count482 // in that order483 chargeiters_t targets =484 Extractors::_detail::realignElementtargets(elementtargets, elements, elementcounts);485 486 #ifndef NDEBUG487 // check all for debugging488 for (chargeiters_t::const_iterator chargeiter = targets.begin();489 chargeiter != targets.end();490 ++chargeiter)491 ASSERT( *chargeiter != charges.end(),492 "Extractors::gatherTargetsFromFragment() - we have not found enough targets?!");493 #endif494 495 return targets;496 }497 498 Fragment::positions_t499 Extractors::gatherPositionsFromFragment(500 const Fragment::positions_t positions,501 const Fragment::charges_t charges,502 const Fragment::charges_t& elements503 )504 {505 // 1.-3. gather correct charge positions506 chargeiters_t targets =507 Extractors::_detail::gatherTargetsFromFragment(charges, elements);508 // 4. convert position_t to Vector509 return Extractors::_detail::gatherPositionsFromTargets(510 positions,511 charges,512 targets);513 }514 515 FunctionModel::arguments_t516 Extractors::gatherDistancesFromFragment(517 const Fragment::positions_t positions,518 const Fragment::charges_t charges,519 const Fragment::charges_t& elements,520 const size_t globalid521 )522 {523 // 1.-3. gather correct charge positions524 chargeiters_t targets =525 Extractors::_detail::gatherTargetsFromFragment(charges, elements);526 // 4. convert position_t to Vector527 return Extractors::_detail::gatherDistancesFromTargets(528 positions,529 charges,530 targets,531 globalid);532 }533 534 FunctionModel::list_of_arguments_t Extractors::reorderArgumentsByIncreasingDistance(535 const FunctionModel::list_of_arguments_t &listargs536 )537 {538 FunctionModel::list_of_arguments_t returnargs;539 for (FunctionModel::list_of_arguments_t::const_iterator iter = listargs.begin();540 iter != listargs.end(); ++iter) {541 const FunctionModel::arguments_t &args = *iter;542 FunctionModel::arguments_t sortedargs(args);543 std::sort(sortedargs.begin(), sortedargs.end(), argument_t::DistanceComparator);544 returnargs.push_back(sortedargs);545 }546 return returnargs;547 }548 549 113 550 114 struct ParticleTypesComparator {
Note:
See TracChangeset
for help on using the changeset viewer.
