Changeset c39675
- Timestamp:
- Apr 8, 2013, 11:56:08 AM (12 years ago)
- Branches:
- 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
- Children:
- 7cdf58
- Parents:
- 6cabaac
- git-author:
- Frederik Heber <heber@…> (03/03/13 21:15:14)
- git-committer:
- Frederik Heber <heber@…> (04/08/13 11:56:08)
- Location:
- src/Fragmentation/Exporters
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified src/Fragmentation/Exporters/ExportGraph.cpp ¶
r6cabaac rc39675 114 114 { 115 115 // create the saturation which adds itself to KeySetsInUse 116 SaturatedFragment_ptr _ptr(new SaturatedFragment(_set, KeySetsInUse, hydrogens)); 116 SaturatedFragment_ptr _ptr( 117 new SaturatedFragment( 118 _set, 119 KeySetsInUse, 120 hydrogens, 121 treatment, 122 saturation) 123 ); 117 124 // and return 118 125 return _ptr; -
TabularUnified src/Fragmentation/Exporters/SaturatedFragment.cpp ¶
r6cabaac rc39675 37 37 #include "SaturatedFragment.hpp" 38 38 39 #include <cmath> 40 #include <iostream> 41 39 42 #include "CodePatterns/Assert.hpp" 40 43 #include "CodePatterns/Log.hpp" 44 45 #include "LinearAlgebra/Exceptions.hpp" 46 #include "LinearAlgebra/Plane.hpp" 47 #include "LinearAlgebra/RealSpaceMatrix.hpp" 48 #include "LinearAlgebra/Vector.hpp" 49 50 #include "Atom/atom.hpp" 51 #include "Bond/bond.hpp" 52 #include "config.hpp" 53 #include "Descriptors/AtomIdDescriptor.hpp" 41 54 #include "Fragmentation/Exporters/HydrogenPool.hpp" 55 #include "Fragmentation/HydrogenSaturation_enum.hpp" 56 #include "Graph/BondGraph.hpp" 57 #include "World.hpp" 42 58 43 59 SaturatedFragment::SaturatedFragment( 44 60 const KeySet &_set, 45 61 KeySetsInUse_t &_container, 46 HydrogenPool &_hydrogens) : 62 HydrogenPool &_hydrogens, 63 const enum HydrogenTreatment _treatment, 64 const enum HydrogenSaturation _saturation) : 47 65 container(_container), 48 66 set(_set), 49 67 hydrogens(_hydrogens), 50 FullMolecule(set) 68 FullMolecule(set), 69 treatment(_treatment), 70 saturation(_saturation) 51 71 { 52 72 // add to in-use container … … 56 76 container.insert(set); 57 77 58 // so far, we don't saturate anything59 SaturationHydrogens.clear();78 // prepare saturation hydrogens 79 saturate(); 60 80 } 61 81 … … 77 97 container.erase(iter); 78 98 } 99 100 void SaturatedFragment::saturate() 101 { 102 // gather all atoms in a vector 103 std::vector<atom *> atoms; 104 for (KeySet::const_iterator iter = FullMolecule.begin(); 105 iter != FullMolecule.end(); 106 ++iter) { 107 atom * const Walker = World::getInstance().getAtom(AtomById(*iter)); 108 ASSERT( Walker != NULL, 109 "SaturatedFragment::OutputConfig() - id " 110 +toString(*iter)+" is unknown to World."); 111 atoms.push_back(Walker); 112 } 113 114 // bool LonelyFlag = false; 115 for (std::vector<atom *>::const_iterator iter = atoms.begin(); 116 iter != atoms.end(); 117 ++iter) { 118 atom * const Walker = *iter; 119 120 // go through all bonds 121 const BondList& ListOfBonds = Walker->getListOfBonds(); 122 for (BondList::const_iterator BondRunner = ListOfBonds.begin(); 123 BondRunner != ListOfBonds.end(); 124 ++BondRunner) { 125 atom * const OtherWalker = (*BondRunner)->GetOtherAtom(Walker); 126 // if in set 127 if (set.find(OtherWalker->getId()) != set.end()) { 128 LOG(4, "DEBUG: Walker " << *Walker << " is bound to " << *OtherWalker << "."); 129 // if (OtherWalker->getId() > Walker->getId()) { // add bond (Nr check is for adding only one of both variants: ab, ba) 130 //// std::stringstream output; 131 //// output << "ACCEPT: Adding Bond: " 132 // output << Leaf->AddBond((*iter), OtherWalker, (*BondRunner)->BondDegree); 133 //// LOG(3, output.str()); 134 // //NumBonds[(*iter)->getNr()]++; 135 // } else { 136 //// LOG(3, "REJECY: Not adding bond, labels in wrong order."); 137 // } 138 // LonelyFlag = false; 139 } else { 140 LOG(4, "DEBUG: Walker " << *Walker << " is bound to " 141 << *OtherWalker << ", who is not in this fragment molecule."); 142 if (saturation == DoSaturate) { 143 // LOG(3, "ACCEPT: Adding Hydrogen to " << (*iter)->Name << " and a bond in between."); 144 if (!AddHydrogenReplacementAtom( 145 (*BondRunner), 146 Walker, 147 OtherWalker, 148 World::getInstance().getConfig()->IsAngstroem == 1)) 149 exit(1); 150 } 151 // } else if ((treatment == ExcludeHydrogen) && (OtherWalker->getElementNo() == (atomicNumber_t)1)) { 152 // // just copy the atom if it's a hydrogen 153 // atom * const OtherWalker = Leaf->AddCopyAtom(OtherWalker); 154 // Leaf->AddBond((*iter), OtherWalker, (*BondRunner)->BondDegree); 155 // } 156 //NumBonds[(*iter)->getNr()] += Binder->BondDegree; 157 } 158 } 159 } 160 } 161 162 bool SaturatedFragment::OutputConfig( 163 std::ostream &out, 164 const ParserTypes _type) const 165 { 166 // gather all atoms in a vector 167 std::vector<atom *> atoms; 168 for (KeySet::const_iterator iter = FullMolecule.begin(); 169 iter != FullMolecule.end(); 170 ++iter) { 171 atom * const Walker = World::getInstance().getAtom(AtomById(*iter)); 172 ASSERT( Walker != NULL, 173 "SaturatedFragment::OutputConfig() - id " 174 +toString(*iter)+" is unknown to World."); 175 atoms.push_back(Walker); 176 } 177 178 // TODO: ScanForPeriodicCorrection() is missing so far! 179 // note however that this is not straight-forward for the following reasons: 180 // - we do not copy all atoms anymore, hence we are forced to shift the real 181 // atoms hither and back again 182 // - we use a long-range potential that supports periodic boundary conditions. 183 // Hence, there we would like the original configuration (split through the 184 // the periodic boundaries). Otherwise, we would have to shift (and probably 185 // interpolate) the potential with OBCs applying. 186 187 // list atoms in fragment for debugging 188 { 189 std::stringstream output; 190 output << "INFO: Contained atoms: "; 191 for (std::vector<atom *>::const_iterator iter = atoms.begin(); 192 iter != atoms.end(); ++iter) { 193 output << (*iter)->getName() << " "; 194 } 195 LOG(3, output.str()); 196 } 197 198 // store to stream via FragmentParser 199 const bool intermediateResult = 200 FormatParserStorage::getInstance().save( 201 out, 202 FormatParserStorage::getInstance().getSuffixFromType(_type), 203 atoms); 204 205 return intermediateResult; 206 } 207 208 atom * const SaturatedFragment::getHydrogenReplacement(atom * const replacement) 209 { 210 atom * const _atom = hydrogens.leaseHydrogen(); // new atom 211 _atom->setAtomicVelocity(replacement->getAtomicVelocity()); // copy velocity 212 _atom->setFixedIon(replacement->getFixedIon()); 213 // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father 214 _atom->father = replacement; 215 SaturationHydrogens.insert(_atom->getId()); 216 return _atom; 217 } 218 219 bool SaturatedFragment::AddHydrogenReplacementAtom( 220 bond::ptr TopBond, 221 atom *Origin, 222 atom *Replacement, 223 bool IsAngstroem) 224 { 225 // Info info(__func__); 226 bool AllWentWell = true; // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit 227 double bondlength; // bond length of the bond to be replaced/cut 228 double bondangle; // bond angle of the bond to be replaced/cut 229 double BondRescale; // rescale value for the hydrogen bond length 230 bond::ptr FirstBond; 231 bond::ptr SecondBond; // Other bonds in double bond case to determine "other" plane 232 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added 233 double b,l,d,f,g, alpha, factors[NDIM]; // hold temporary values in triple bond case for coordination determination 234 Vector Orthovector1, Orthovector2; // temporary vectors in coordination construction 235 Vector InBondvector; // vector in direction of *Bond 236 const RealSpaceMatrix &matrix = World::getInstance().getDomain().getM(); 237 bond::ptr Binder; 238 239 // create vector in direction of bond 240 InBondvector = Replacement->getPosition() - Origin->getPosition(); 241 bondlength = InBondvector.Norm(); 242 243 // is greater than typical bond distance? Then we have to correct periodically 244 // the problem is not the H being out of the box, but InBondvector have the wrong direction 245 // due to Replacement or Origin being on the wrong side! 246 const BondGraph * const BG = World::getInstance().getBondGraph(); 247 const range<double> MinMaxBondDistance( 248 BG->getMinMaxDistance(Origin,Replacement)); 249 if (!MinMaxBondDistance.isInRange(bondlength)) { 250 // LOG(4, "InBondvector is: " << InBondvector << "."); 251 Orthovector1.Zero(); 252 for (int i=NDIM;i--;) { 253 l = Replacement->at(i) - Origin->at(i); 254 if (fabs(l) > MinMaxBondDistance.last) { // is component greater than bond distance (check against min not useful here) 255 Orthovector1[i] = (l < 0) ? -1. : +1.; 256 } // (signs are correct, was tested!) 257 } 258 Orthovector1 *= matrix; 259 InBondvector -= Orthovector1; // subtract just the additional translation 260 bondlength = InBondvector.Norm(); 261 // LOG(4, "INFO: Corrected InBondvector is now: " << InBondvector << "."); 262 } // periodic correction finished 263 264 InBondvector.Normalize(); 265 // get typical bond length and store as scale factor for later 266 ASSERT(Origin->getType() != NULL, 267 "SaturatedFragment::AddHydrogenReplacementAtom() - element of Origin is not given."); 268 BondRescale = Origin->getType()->getHBondDistance(TopBond->BondDegree-1); 269 if (BondRescale == -1) { 270 ELOG(1, "There is no typical hydrogen bond distance in replacing bond (" << Origin->getName() << "<->" << Replacement->getName() << ") of degree " << TopBond->BondDegree << "!"); 271 return false; 272 BondRescale = bondlength; 273 } else { 274 if (!IsAngstroem) 275 BondRescale /= (1.*AtomicLengthToAngstroem); 276 } 277 278 // discern single, double and triple bonds 279 switch(TopBond->BondDegree) { 280 case 1: 281 // check whether replacement has been an excluded hydrogen 282 if (Replacement->getType()->getAtomicNumber() == HydrogenPool::HYDROGEN) { // neither rescale nor replace if it's already hydrogen 283 FirstOtherAtom = Replacement; 284 BondRescale = bondlength; 285 } else { 286 FirstOtherAtom = getHydrogenReplacement(Replacement); 287 InBondvector *= BondRescale; // rescale the distance vector to Hydrogen bond length 288 FirstOtherAtom->setPosition(Origin->getPosition() + InBondvector); // set coordination to origin and add distance vector to replacement atom 289 } 290 FullMolecule.insert(FirstOtherAtom->getId()); 291 // LOG(4, "INFO: Added " << *FirstOtherAtom << " at: " << FirstOtherAtom->x << "."); 292 break; 293 case 2: 294 { 295 // determine two other bonds (warning if there are more than two other) plus valence sanity check 296 const BondList& ListOfBonds = Origin->getListOfBonds(); 297 for (BondList::const_iterator Runner = ListOfBonds.begin(); 298 Runner != ListOfBonds.end(); 299 ++Runner) { 300 if ((*Runner) != TopBond) { 301 if (FirstBond == NULL) { 302 FirstBond = (*Runner); 303 FirstOtherAtom = (*Runner)->GetOtherAtom(Origin); 304 } else if (SecondBond == NULL) { 305 SecondBond = (*Runner); 306 SecondOtherAtom = (*Runner)->GetOtherAtom(Origin); 307 } else { 308 ELOG(2, "Detected more than four bonds for atom " << Origin->getName()); 309 } 310 } 311 } 312 } 313 if (SecondOtherAtom == NULL) { // then we have an atom with valence four, but only 3 bonds: one to replace and one which is TopBond (third is FirstBond) 314 SecondBond = TopBond; 315 SecondOtherAtom = Replacement; 316 } 317 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 318 // LOG(3, "Regarding the double bond (" << Origin->Name << "<->" << Replacement->Name << ") to be constructed: Taking " << FirstOtherAtom->Name << " and " << SecondOtherAtom->Name << " along with " << Origin->Name << " to determine orthogonal plane."); 319 320 // determine the plane of these two with the *origin 321 try { 322 Orthovector1 = Plane(Origin->getPosition(), FirstOtherAtom->getPosition(), SecondOtherAtom->getPosition()).getNormal(); 323 } 324 catch(LinearDependenceException &excp){ 325 LOG(0, boost::diagnostic_information(excp)); 326 // TODO: figure out what to do with the Orthovector in this case 327 AllWentWell = false; 328 } 329 } else { 330 Orthovector1.GetOneNormalVector(InBondvector); 331 } 332 //LOG(3, "INFO: Orthovector1: " << Orthovector1 << "."); 333 // orthogonal vector and bond vector between origin and replacement form the new plane 334 Orthovector1.MakeNormalTo(InBondvector); 335 Orthovector1.Normalize(); 336 //LOG(3, "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "."); 337 338 // create the two Hydrogens ... 339 FirstOtherAtom = getHydrogenReplacement(Replacement); 340 SecondOtherAtom = getHydrogenReplacement(Replacement); 341 FullMolecule.insert(FirstOtherAtom->getId()); 342 FullMolecule.insert(SecondOtherAtom->getId()); 343 bondangle = Origin->getType()->getHBondAngle(1); 344 if (bondangle == -1) { 345 ELOG(1, "There is no typical hydrogen bond angle in replacing bond (" << Origin->getName() << "<->" << Replacement->getName() << ") of degree " << TopBond->BondDegree << "!"); 346 return false; 347 bondangle = 0; 348 } 349 bondangle *= M_PI/180./2.; 350 // LOG(3, "INFO: ReScaleCheck: InBondvector " << InBondvector << ", " << Orthovector1 << "."); 351 // LOG(3, "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle)); 352 FirstOtherAtom->Zero(); 353 SecondOtherAtom->Zero(); 354 for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction) 355 FirstOtherAtom->set(i, InBondvector[i] * cos(bondangle) + Orthovector1[i] * (sin(bondangle))); 356 SecondOtherAtom->set(i, InBondvector[i] * cos(bondangle) + Orthovector1[i] * (-sin(bondangle))); 357 } 358 FirstOtherAtom->Scale(BondRescale); // rescale by correct BondDistance 359 SecondOtherAtom->Scale(BondRescale); 360 //LOG(3, "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "."); 361 *FirstOtherAtom += Origin->getPosition(); 362 *SecondOtherAtom += Origin->getPosition(); 363 // ... and add to molecule 364 // LOG(4, "INFO: Added " << *FirstOtherAtom << " at: " << FirstOtherAtom->x << "."); 365 // LOG(4, "INFO: Added " << *SecondOtherAtom << " at: " << SecondOtherAtom->x << "."); 366 break; 367 case 3: 368 // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid) 369 FirstOtherAtom = getHydrogenReplacement(Replacement); 370 SecondOtherAtom = getHydrogenReplacement(Replacement); 371 ThirdOtherAtom = getHydrogenReplacement(Replacement); 372 FullMolecule.insert(FirstOtherAtom->getId()); 373 FullMolecule.insert(SecondOtherAtom->getId()); 374 FullMolecule.insert(ThirdOtherAtom->getId()); 375 376 // we need to vectors orthonormal the InBondvector 377 AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(InBondvector); 378 // LOG(3, "INFO: Orthovector1: " << Orthovector1 << "."); 379 try{ 380 Orthovector2 = Plane(InBondvector, Orthovector1,0).getNormal(); 381 } 382 catch(LinearDependenceException &excp) { 383 LOG(0, boost::diagnostic_information(excp)); 384 AllWentWell = false; 385 } 386 // LOG(3, "INFO: Orthovector2: " << Orthovector2 << ".") 387 388 // create correct coordination for the three atoms 389 alpha = (Origin->getType()->getHBondAngle(2))/180.*M_PI/2.; // retrieve triple bond angle from database 390 l = BondRescale; // desired bond length 391 b = 2.*l*sin(alpha); // base length of isosceles triangle 392 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.); // length for InBondvector 393 f = b/sqrt(3.); // length for Orthvector1 394 g = b/2.; // length for Orthvector2 395 // LOG(3, "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", "); 396 // LOG(3, "The three Bond lengths: " << sqrt(d*d+f*f) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g)); 397 factors[0] = d; 398 factors[1] = f; 399 factors[2] = 0.; 400 FirstOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors); 401 factors[1] = -0.5*f; 402 factors[2] = g; 403 SecondOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors); 404 factors[2] = -g; 405 ThirdOtherAtom->LinearCombinationOfVectors(InBondvector, Orthovector1, Orthovector2, factors); 406 407 // rescale each to correct BondDistance 408 // FirstOtherAtom->x.Scale(&BondRescale); 409 // SecondOtherAtom->x.Scale(&BondRescale); 410 // ThirdOtherAtom->x.Scale(&BondRescale); 411 412 // and relative to *origin atom 413 *FirstOtherAtom += Origin->getPosition(); 414 *SecondOtherAtom += Origin->getPosition(); 415 *ThirdOtherAtom += Origin->getPosition(); 416 417 // ... and add to molecule 418 // LOG(4, "INFO: Added " << *FirstOtherAtom << " at: " << FirstOtherAtom->x << "."); 419 // LOG(4, "INFO: Added " << *SecondOtherAtom << " at: " << SecondOtherAtom->x << "."); 420 // LOG(4, "INFO: Added " << *ThirdOtherAtom << " at: " << ThirdOtherAtom->x << "."); 421 break; 422 default: 423 ELOG(1, "BondDegree does not state single, double or triple bond!"); 424 AllWentWell = false; 425 break; 426 } 427 428 return AllWentWell; 429 }; -
TabularUnified src/Fragmentation/Exporters/SaturatedFragment.hpp ¶
r6cabaac rc39675 14 14 #endif 15 15 16 #include <iosfwd> 16 17 #include <set> 18 #include <string> 17 19 20 #include "Bond/bond.hpp" 18 21 #include "Fragmentation/KeySet.hpp" 22 #include "Fragmentation/HydrogenSaturation_enum.hpp" 23 #include "Parser/FormatParserStorage.hpp" 19 24 25 class atom; 20 26 class HydrogenPool; 21 27 … … 46 52 const KeySet &_set, 47 53 KeySetsInUse_t &_container, 48 HydrogenPool &_hydrogens); 54 HydrogenPool &_hydrogens, 55 const enum HydrogenTreatment _treatment, 56 const enum HydrogenSaturation saturation); 49 57 50 58 /** Destructor of class SaturatedFragment. … … 62 70 } 63 71 72 /** Getter for the FullMolecule this instance is associated with. 73 * 74 * \return const ref to FullMolecule 75 */ 76 const KeySet & getFullMolecule() const 77 { 78 return FullMolecule; 79 } 80 81 /** Getter for the SaturationHydrogens this instance is associated with. 82 * 83 * \return const ref to SaturationHydrogens 84 */ 85 const KeySet & getSaturationHydrogens() const 86 { 87 return SaturationHydrogens; 88 } 89 90 /** Prints the config of the fragment of \a _type to \a out. 91 * 92 * \param out output stream to write to 93 * \param _type parser type to write config 94 */ 95 bool OutputConfig( 96 std::ostream &out, 97 const ParserTypes _type) const; 98 99 private: 100 /** Helper function to lease and bring in place saturation hydrogens. 101 * 102 */ 103 void saturate(); 104 105 /** Helper function to get a hydrogen replacement for a given \a replacement. 106 * 107 * \param replacement atom to "replace" with hydrogen in a fragment. 108 * \return ref to leased hydrogen atom 109 */ 110 atom * const getHydrogenReplacement(atom * const replacement); 111 112 /** Leases and adds a Hydrogen atom in replacement for the given atom \a *partner in bond with a *origin. 113 * Here, we have to distinguish between single, double or triple bonds as stated by \a BondDegree, that each demand 114 * a different scheme when adding \a *replacement atom for the given one. 115 * -# Single Bond: Simply add new atom with bond distance rescaled to typical hydrogen one 116 * -# Double Bond: Here, we need the **BondList of the \a *origin atom, by scanning for the other bonds instead of 117 * *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector(). 118 * The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two 119 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the 120 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two 121 * hydrogens forming this angle with *origin. 122 * -# Triple Bond: The idea is to set up a tetraoid (C1-H1-H2-H3) (however the lengths \f$b\f$ of the sides of the base 123 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be 124 * determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin): 125 * We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2). 126 * \f[ h = l \cdot \cos{\left (\frac{\alpha}{2} \right )} \qquad b = 2l \cdot \sin{\left (\frac{\alpha}{2} \right)} \quad \rightarrow \quad d = l \cdot \sqrt{\cos^2{\left (\frac{\alpha}{2} \right)}-\frac{1}{3}\cdot\sin^2{\left (\frac{\alpha}{2}\right )}} 127 * \f] 128 * vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates 129 * the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above. 130 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that 131 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1. 132 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 133 * \f] 134 * as the coordination of all three atoms in the coordinate system of these three vectors: 135 * \f$\pmatrix{d & f & 0}\f$, \f$\pmatrix{d & -0.5 \cdot f & g}\f$ and \f$\pmatrix{d & -0.5 \cdot f & -g}\f$. 136 * 137 * \param TopBond pointer to bond between \a *origin and \a *replacement 138 * \param Origin atom that is actually contained in the fragment 139 * \param Replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule 140 * \param isAngstroem whether the coordination of the given atoms is in AtomicLength (false) or Angstrom(true) 141 * \return number of atoms added, if < bond::BondDegree then something went wrong 142 */ 143 bool AddHydrogenReplacementAtom( 144 bond::ptr TopBond, 145 atom *Origin, 146 atom *Replacement, 147 bool IsAngstroem); 148 64 149 private: 65 150 //!> container to mark ourselves RAII-style … … 73 158 //!> key set containing the ids of all hydrogens added for saturation 74 159 KeySet SaturationHydrogens; 160 //!> whether hydrogens are generally contained in set or not 161 const enum HydrogenTreatment treatment; 162 //!> whether to actually saturate or not 163 const enum HydrogenSaturation saturation; 75 164 }; 76 165 -
TabularUnified src/Fragmentation/Exporters/unittests/Makefile.am ¶
r6cabaac rc39675 27 27 ../Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.hpp 28 28 HydrogenPoolUnitTest_LDADD = \ 29 ${FRAGMENTATIONEXPORTERSLIBS}\30 ../libMolecuilderUI.la29 ../libMolecuilderUI.la \ 30 ${FRAGMENTATIONEXPORTERSLIBS} 31 31 32 32 SaturatedFragmentUnitTest_SOURCES = $(top_srcdir)/src/unittests/UnitTestMain.cpp \ … … 34 34 ../Fragmentation/Exporters/unittests/SaturatedFragmentUnitTest.hpp 35 35 SaturatedFragmentUnitTest_LDADD = \ 36 ${FRAGMENTATIONEXPORTERSLIBS} \ 37 ../libMolecuilderUI.la 36 ../libMolecuilderUI.la \ 37 $(top_builddir)/LinearAlgebra/src/LinearAlgebra/libLinearAlgebra.la \ 38 ${FRAGMENTATIONEXPORTERSLIBS} 38 39 39 40 -
TabularUnified src/Fragmentation/Exporters/unittests/SaturatedFragmentUnitTest.cpp ¶
r6cabaac rc39675 49 49 #include "CodePatterns/Assert.hpp" 50 50 51 #include "Fragmentation/HydrogenSaturation_enum.hpp" 51 52 52 53 #ifdef HAVE_TESTRUNNER … … 68 69 69 70 set = new KeySet; 70 fragment = new SaturatedFragment(*set, KeySetsInUse, hydrogens );71 fragment = new SaturatedFragment(*set, KeySetsInUse, hydrogens, ExcludeHydrogen, DoSaturate); 71 72 } 72 73
Note:
See TracChangeset
for help on using the changeset viewer.