OpenMD 3.1
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
MC.cpp
1/*
2 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 *
4 * The University of Notre Dame grants you ("Licensee") a
5 * non-exclusive, royalty free, license to use, modify and
6 * redistribute this software in source and binary code form, provided
7 * that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * This software is provided "AS IS," without a warranty of any
18 * kind. All express or implied conditions, representations and
19 * warranties, including any implied warranty of merchantability,
20 * fitness for a particular purpose or non-infringement, are hereby
21 * excluded. The University of Notre Dame and its licensors shall not
22 * be liable for any damages suffered by licensee as a result of
23 * using, modifying or distributing the software or its
24 * derivatives. In no event will the University of Notre Dame or its
25 * licensors be liable for any lost revenue, profit or data, or for
26 * direct, indirect, special, consequential, incidental or punitive
27 * damages, however caused and regardless of the theory of liability,
28 * arising out of the use of or inability to use software, even if the
29 * University of Notre Dame has been advised of the possibility of
30 * such damages.
31 *
32 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33 * research, please cite the appropriate papers when you publish your
34 * work. Good starting points are:
35 *
36 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 */
42
43/**
44 * @file MoleculeCreator.cpp
45 * @author tlin
46 * @date 11/04/2004
47 * @version 1.0
48 */
49
50#include <cassert>
51#include <typeinfo>
52#include <set>
53
56#include "primitives/GhostTorsion.hpp"
57#include "types/AtomType.hpp"
59#include "types/BondTypeParser.hpp"
60#include "types/BendTypeParser.hpp"
61#include "types/TorsionTypeParser.hpp"
62#include "types/InversionTypeParser.hpp"
63#include "types/UFFAdapter.hpp"
64#include "types/HarmonicBondType.hpp"
66#include "utils/simError.h"
67#include "utils/StringUtils.hpp"
68#include "forcefields/UFF.hpp"
69
70namespace OpenMD {
71
72 Molecule* MoleculeCreator::createMolecule(ForceField* ff,
73 MoleculeStamp *molStamp,
74 int stampId, int globalIndex,
75 LocalIndexManager* localIndexMan) {
76 Molecule* mol = new Molecule(stampId, globalIndex, molStamp->getName(),
77 molStamp->getRegion() );
78
79 //create atoms
80 Atom* atom;
81 AtomStamp* currentAtomStamp;
82 int nAtom = molStamp->getNAtoms();
83 for (int i = 0; i < nAtom; ++i) {
84 currentAtomStamp = molStamp->getAtomStamp(i);
85 atom = createAtom(ff, mol, currentAtomStamp, localIndexMan);
86 mol->addAtom(atom);
87 }
88
89 //create rigidbodies
90 RigidBody* rb;
91 RigidBodyStamp * currentRigidBodyStamp;
92 int nRigidbodies = molStamp->getNRigidBodies();
93
94 for (int i = 0; i < nRigidbodies; ++i) {
95 currentRigidBodyStamp = molStamp->getRigidBodyStamp(i);
96 rb = createRigidBody(molStamp, mol, currentRigidBodyStamp,
97 localIndexMan);
98 mol->addRigidBody(rb);
99 }
100
101 //create bonds
102 Bond* bond;
103 BondStamp* currentBondStamp;
104 int nBonds = molStamp->getNBonds();
105
106 for (int i = 0; i < nBonds; ++i) {
107 currentBondStamp = molStamp->getBondStamp(i);
108 bond = createBond(ff, mol, currentBondStamp, localIndexMan);
109 mol->addBond(bond);
110 }
111
112 //create bends
113 Bend* bend;
114 BendStamp* currentBendStamp;
115 int nBends = molStamp->getNBends();
116 for (int i = 0; i < nBends; ++i) {
117 currentBendStamp = molStamp->getBendStamp(i);
118 bend = createBend(ff, mol, currentBendStamp, localIndexMan);
119 mol->addBend(bend);
120 }
121
122 //create torsions
123 Torsion* torsion;
124 TorsionStamp* currentTorsionStamp;
125 int nTorsions = molStamp->getNTorsions();
126 for (int i = 0; i < nTorsions; ++i) {
127 currentTorsionStamp = molStamp->getTorsionStamp(i);
128 torsion = createTorsion(ff, mol, currentTorsionStamp, localIndexMan);
129 mol->addTorsion(torsion);
130 }
131
132 //create inversions
133 Inversion* inversion;
134 InversionStamp* currentInversionStamp;
135 int nInversions = molStamp->getNInversions();
136 for (int i = 0; i < nInversions; ++i) {
137 currentInversionStamp = molStamp->getInversionStamp(i);
138 inversion = createInversion(ff, mol, currentInversionStamp,
139 localIndexMan);
140 if (inversion != NULL ) {
141 mol->addInversion(inversion);
142 }
143 }
144
145 //create cutoffGroups
146 CutoffGroup* cutoffGroup;
147 CutoffGroupStamp* currentCutoffGroupStamp;
148 int nCutoffGroups = molStamp->getNCutoffGroups();
149 for (int i = 0; i < nCutoffGroups; ++i) {
150 currentCutoffGroupStamp = molStamp->getCutoffGroupStamp(i);
151 cutoffGroup = createCutoffGroup(mol, currentCutoffGroupStamp,
152 localIndexMan);
153 mol->addCutoffGroup(cutoffGroup);
154 }
155
156 //every free atom is a cutoff group
157 std::vector<Atom*> freeAtoms;
158 std::vector<Atom*>::iterator ai;
159 std::vector<Atom*>::iterator fai;
160
161 //add all atoms into allAtoms set
162 for(atom = mol->beginAtom(fai); atom != NULL; atom = mol->nextAtom(fai)) {
163 freeAtoms.push_back(atom);
164 }
165
166 Molecule::CutoffGroupIterator ci;
167 CutoffGroup* cg;
168
169 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
170 cg = mol->nextCutoffGroup(ci)) {
171
172 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
173 //erase the atoms belong to cutoff groups from freeAtoms vector
174 freeAtoms.erase(std::remove(freeAtoms.begin(), freeAtoms.end(), atom),
175 freeAtoms.end());
176 }
177 }
178
179 // loop over the free atoms and then create one cutoff group for
180 // every single free atom
181
182 for (fai = freeAtoms.begin(); fai != freeAtoms.end(); ++fai) {
183 cutoffGroup = createCutoffGroup(mol, *fai, localIndexMan);
184 mol->addCutoffGroup(cutoffGroup);
185 }
186
187 //create bonded constraintPairs:
188 createConstraintPair(mol);
189
190 //create non-bonded constraintPairs
191 for (std::size_t i = 0; i < molStamp->getNConstraints(); ++i) {
192 ConstraintStamp* cStamp = molStamp->getConstraintStamp(i);
193 Atom* atomA;
194 Atom* atomB;
195
196 atomA = mol->getAtomAt(cStamp->getA());
197 atomB = mol->getAtomAt(cStamp->getB());
198 assert( atomA && atomB );
199
200 bool printConstraintForce = false;
201
202 if (cStamp->havePrintConstraintForce()) {
203 printConstraintForce = cStamp->getPrintConstraintForce();
204 }
205
206 if (!cStamp->haveConstrainedDistance()) {
207 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
208 "Constraint Error: A non-bond constraint was specified\n"
209 "\twithout providing a value for the constrainedDistance.\n");
210 painCave.isFatal = 1;
211 simError();
212 } else {
213 RealType distance = cStamp->getConstrainedDistance();
214 ConstraintElem* consElemA = new ConstraintElem(atomA);
215 ConstraintElem* consElemB = new ConstraintElem(atomB);
216 ConstraintPair* cPair = new ConstraintPair(consElemA, consElemB,
217 distance,
218 printConstraintForce);
219 mol->addConstraintPair(cPair);
220 }
221 }
222
223 // now create the constraint elements:
224
225 createConstraintElem(mol);
226
227 // Does this molecule stamp define a total constrained charge value?
228 // If so, let the created molecule know about it.
229 if (molStamp->haveConstrainTotalCharge() ) {
230 mol->setConstrainTotalCharge( molStamp->getConstrainTotalCharge() );
231 }
232
233 // The construction of this molecule is finished:
234 mol->complete();
235
236 return mol;
237 }
238
239
241 AtomStamp* stamp,
242 LocalIndexManager* localIndexMan) {
243 AtomType * atomType;
244 Atom* atom;
245
246 atomType = ff->getAtomType(stamp->getType());
247
248 if (atomType == NULL) {
249 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "Can not find Matching Atom Type for[%s]",
250 stamp->getType().c_str());
251
252 painCave.isFatal = 1;
253 simError();
254 }
255
256 //below code still have some kind of hard-coding smell
257 if (atomType->isDirectional()){
258
259 DirectionalAtom* dAtom;
260 dAtom = new DirectionalAtom(atomType);
261 atom = dAtom;
262 }
263 else{
264 atom = new Atom(atomType);
265 }
266
267 atom->setLocalIndex(localIndexMan->getNextAtomIndex());
268
269 return atom;
270 }
271
272 RigidBody* MoleculeCreator::createRigidBody(MoleculeStamp *molStamp,
273 Molecule* mol,
274 RigidBodyStamp* rbStamp,
275 LocalIndexManager* localIndexMan){
276 Atom* atom;
277 int nAtoms;
278 Vector3d refCoor;
279 AtomStamp* atomStamp;
280
281 RigidBody* rb = new RigidBody();
282 nAtoms = rbStamp->getNMembers();
283 for (int i = 0; i < nAtoms; ++i) {
284 //rbStamp->getMember(i) return the local index of current atom
285 //inside the molecule. It is not the same as local index of
286 //atom which is the index of atom at DataStorage class
287 atom = mol->getAtomAt(rbStamp->getMemberAt(i));
288 atomStamp= molStamp->getAtomStamp(rbStamp->getMemberAt(i));
289 rb->addAtom(atom, atomStamp);
290 }
291
292 //after all of the atoms are added, we need to calculate the
293 //reference coordinates
294 rb->calcRefCoords();
295
296 //set the local index of this rigid body, global index will be set later
297 rb->setLocalIndex(localIndexMan->getNextRigidBodyIndex());
298
299 // The rule for naming a rigidbody is: MoleculeName_RB_Integer
300 // The first part is the name of the molecule
301 // The second part is always fixed as "RB"
302 // The third part is the index of the rigidbody defined in meta-data file
303 // For example, Butane_RB_0 is a valid rigid body name of butane molecule
304
305 std::string s = OpenMD_itoa(mol->getNRigidBodies(), 10);
306 rb->setType(mol->getType() + "_RB_" + s.c_str());
307 return rb;
308 }
309
310 Bond* MoleculeCreator::createBond(ForceField* ff, Molecule* mol,
311 BondStamp* stamp,
312 LocalIndexManager* localIndexMan) {
313 BondTypeParser btParser;
314 BondType* bondType = NULL;
315 Atom* atomA;
316 Atom* atomB;
317
318 atomA = mol->getAtomAt(stamp->getA());
319 atomB = mol->getAtomAt(stamp->getB());
320
321 assert( atomA && atomB);
322
323 if (stamp->hasOverride()) {
324 try {
325 bondType = btParser.parseTypeAndPars(stamp->getOverrideType(),
326 stamp->getOverridePars() );
327 }
328 catch( OpenMDException& e) {
329 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "MoleculeCreator Error: %s "
330 "for molecule %s\n",
331 e.what(), mol->getType().c_str() );
332 painCave.isFatal = 1;
333 simError();
334 }
335
336 } else {
337
338 bondType = ff->getBondType(atomA->getType(), atomB->getType());
339
340 if (bondType == NULL) {
341
342 if (ff->getForceFieldOptions().getDelayedParameterCalculation()) {
343
344 RealType bondorder = stamp->getBondOrder();
345
346 RealType b0 = UFF::calcBondRestLength(bondorder,
347 atomA->getAtomType(),
348 atomB->getAtomType() );
349
350 RealType kb = UFF::calcBondForceConstant(b0,
351 atomA->getAtomType(),
352 atomB->getAtomType() );
353
354 bondType = new HarmonicBondType(b0, kb);
355
356 ff->addBondType(atomA->getType(), atomB->getType(), bondType);
357
358 } else {
359
360 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "Can not find Matching Bond Type for[%s, %s]",
361 atomA->getType().c_str(),
362 atomB->getType().c_str());
363
364 painCave.isFatal = 1;
365 simError();
366 }
367 }
368 }
369
370 Bond* bond = new Bond(atomA, atomB, bondType);
371
372 //set the local index of this bond, the global index will be set later
373 bond->setLocalIndex(localIndexMan->getNextBondIndex());
374
375 // The rule for naming a bond is: MoleculeName_Bond_Integer
376 // The first part is the name of the molecule
377 // The second part is always fixed as "Bond"
378 // The third part is the index of the bond defined in meta-data file
379 // For example, Butane_bond_0 is a valid Bond name in a butane molecule
380
381 std::string s = OpenMD_itoa(mol->getNBonds(), 10);
382 bond->setName(mol->getType() + "_Bond_" + s.c_str());
383 return bond;
384 }
385
386 Bend* MoleculeCreator::createBend(ForceField* ff, Molecule* mol,
387 BendStamp* stamp,
388 LocalIndexManager* localIndexMan) {
389 BendTypeParser btParser;
390 BendType* bendType = NULL;
391 Bend* bend = NULL;
392
393 std::vector<int> bendAtoms = stamp->getMembers();
394 if (bendAtoms.size() == 3) {
395 Atom* atomA = mol->getAtomAt(bendAtoms[0]);
396 Atom* atomB = mol->getAtomAt(bendAtoms[1]);
397 Atom* atomC = mol->getAtomAt(bendAtoms[2]);
398
399 assert( atomA && atomB && atomC );
400
401 if (stamp->hasOverride()) {
402
403 try {
404 bendType = btParser.parseTypeAndPars(stamp->getOverrideType(),
405 stamp->getOverridePars() );
406 }
407 catch( OpenMDException& e) {
408 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "MoleculeCreator Error: %s "
409 "for molecule %s\n",
410 e.what(), mol->getType().c_str() );
411 painCave.isFatal = 1;
412 simError();
413 }
414 } else {
415
416 bendType = ff->getBendType(atomA->getType().c_str(),
417 atomB->getType().c_str(),
418 atomC->getType().c_str());
419
420 if (bendType == NULL) {
421
422 if (ff->getForceFieldOptions().getDelayedParameterCalculation()) {
423 UFFAdapter uffj = UFFAdapter(atomB->getAtomType());
424 RealType theta0 = uffj.getTheta0() * Constants::PI / 180.0;
425
426
427 RealType bo12 =
428 RealType ktheta = UFF:calcAngleForceConstant(theta0, bo12, bo23,
429 atomA->getAtomType(),
430 atomB->getAtomType(),
431 atomC->getAtomType());
432 bendType = new HarmonicBendType(theta0, ktheta);
433
434 ff->addBendType(atomA->getType(), atomB->getType(),
435 atomC->getType(), bendType);
436
437 } else {
438
439 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
440 "Can not find Matching Bend Type for[%s, %s, %s]",
441 atomA->getType().c_str(),
442 atomB->getType().c_str(),
443 atomC->getType().c_str());
444
445 painCave.isFatal = 1;
446 simError();
447 }
448 }
449
450 bend = new Bend(atomA, atomB, atomC, bendType);
451
452
453 } else if ( bendAtoms.size() == 2 && stamp->haveGhostVectorSource()) {
454 int ghostIndex = stamp->getGhostVectorSource();
455 int normalIndex = ghostIndex != bendAtoms[0] ?
456 bendAtoms[0] : bendAtoms[1];
457 Atom* normalAtom = mol->getAtomAt(normalIndex) ;
458 DirectionalAtom* ghostAtom = dynamic_cast<DirectionalAtom*>(mol->getAtomAt(ghostIndex));
459 if (ghostAtom == NULL) {
460 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "Can not cast Atom to DirectionalAtom");
461 painCave.isFatal = 1;
462 simError();
463 }
464
465 if (stamp->hasOverride()) {
466
467 try {
468 bendType = btParser.parseTypeAndPars(stamp->getOverrideType(),
469 stamp->getOverridePars() );
470 }
471 catch( OpenMDException& e) {
472 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "MoleculeCreator Error: %s "
473 "for molecule %s\n",
474 e.what(), mol->getType().c_str() );
475 painCave.isFatal = 1;
476 simError();
477 }
478 } else {
479
480 bendType = ff->getBendType(normalAtom->getType(),
481 ghostAtom->getType(),
482 "GHOST");
483
484 if (bendType == NULL) {
485 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
486 "Can not find Matching Bend Type for[%s, %s, %s]",
487 normalAtom->getType().c_str(),
488 ghostAtom->getType().c_str(),
489 "GHOST");
490
491 painCave.isFatal = 1;
492 simError();
493 }
494 }
495
496 bend = new GhostBend(normalAtom, ghostAtom, bendType);
497
498 }
499 }
500 //set the local index of this bend, the global index will be set later
501 bend->setLocalIndex(localIndexMan->getNextBendIndex());
502
503 // The rule for naming a bend is: MoleculeName_Bend_Integer
504 // The first part is the name of the molecule
505 // The second part is always fixed as "Bend"
506 // The third part is the index of the bend defined in meta-data file
507 // For example, Butane_Bend_0 is a valid Bend name in a butane molecule
508
509 std::string s = OpenMD_itoa(mol->getNBends(), 10);
510 bend->setName(mol->getType() + "_Bend_" + s.c_str());
511 return bend;
512 }
513
514
515 Torsion* MoleculeCreator::createTorsion(ForceField* ff, Molecule* mol,
516 TorsionStamp* stamp,
517 LocalIndexManager* localIndexMan) {
518
519 TorsionTypeParser ttParser;
520 TorsionType* torsionType = NULL;
521 Torsion* torsion = NULL;
522
523 std::vector<int> torsionAtoms = stamp->getMembers();
524 if (torsionAtoms.size() < 3) {
525 return torsion;
526 }
527
528 Atom* atomA = mol->getAtomAt(torsionAtoms[0]);
529 Atom* atomB = mol->getAtomAt(torsionAtoms[1]);
530 Atom* atomC = mol->getAtomAt(torsionAtoms[2]);
531
532 if (torsionAtoms.size() == 4) {
533 Atom* atomD = mol->getAtomAt(torsionAtoms[3]);
534
535 assert(atomA && atomB && atomC && atomD );
536
537 if (stamp->hasOverride()) {
538
539 try {
540 torsionType = ttParser.parseTypeAndPars(stamp->getOverrideType(),
541 stamp->getOverridePars() );
542 }
543 catch( OpenMDException& e) {
544 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "MoleculeCreator Error: %s "
545 "for molecule %s\n",
546 e.what(), mol->getType().c_str() );
547 painCave.isFatal = 1;
548 simError();
549 }
550 } else {
551
552
553 torsionType = ff->getTorsionType(atomA->getType(),
554 atomB->getType(),
555 atomC->getType(),
556 atomD->getType());
557 if (torsionType == NULL) {
558 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
559 "Can not find Matching Torsion Type for[%s, %s, %s, %s]",
560 atomA->getType().c_str(),
561 atomB->getType().c_str(),
562 atomC->getType().c_str(),
563 atomD->getType().c_str());
564
565 painCave.isFatal = 1;
566 simError();
567 }
568 }
569
570 torsion = new Torsion(atomA, atomB, atomC, atomD, torsionType);
571 } else {
572
573 DirectionalAtom* dAtom = dynamic_cast<DirectionalAtom*>(mol->getAtomAt(stamp->getGhostVectorSource()));
574 if (dAtom == NULL) {
575 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "Can not cast Atom to DirectionalAtom");
576 painCave.isFatal = 1;
577 simError();
578 }
579
580 if (stamp->hasOverride()) {
581
582 try {
583 torsionType = ttParser.parseTypeAndPars(stamp->getOverrideType(),
584 stamp->getOverridePars() );
585 }
586 catch( OpenMDException& e) {
587 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "MoleculeCreator Error: %s "
588 "for molecule %s\n",
589 e.what(), mol->getType().c_str() );
590 painCave.isFatal = 1;
591 simError();
592 }
593 } else {
594 torsionType = ff->getTorsionType(atomA->getType(), atomB->getType(),
595 atomC->getType(), "GHOST");
596
597 if (torsionType == NULL) {
598 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
599 "Can not find Matching Torsion Type for[%s, %s, %s, %s]",
600 atomA->getType().c_str(),
601 atomB->getType().c_str(),
602 atomC->getType().c_str(),
603 "GHOST");
604
605 painCave.isFatal = 1;
606 simError();
607 }
608 }
609
610 torsion = new GhostTorsion(atomA, atomB, dAtom, torsionType);
611 }
612
613 //set the local index of this torsion, the global index will be set later
614 torsion->setLocalIndex(localIndexMan->getNextTorsionIndex());
615
616 // The rule for naming a torsion is: MoleculeName_Torsion_Integer
617 // The first part is the name of the molecule
618 // The second part is always fixed as "Torsion"
619 // The third part is the index of the torsion defined in meta-data file
620 // For example, Butane_Torsion_0 is a valid Torsion name in a
621 // butane molecule
622
623 std::string s = OpenMD_itoa(mol->getNTorsions(), 10);
624 torsion->setName(mol->getType() + "_Torsion_" + s.c_str());
625 return torsion;
626 }
627
628 Inversion* MoleculeCreator::createInversion(ForceField* ff, Molecule* mol,
629 InversionStamp* stamp,
630 LocalIndexManager* localIndexMan) {
631
632 InversionTypeParser itParser;
633 InversionType* inversionType = NULL;
634 Inversion* inversion = NULL;
635
636 int center = stamp->getCenter();
637 std::vector<int> satellites = stamp->getSatellites();
638 if (satellites.size() != 3) {
639 return inversion;
640 }
641
642 Atom* atomA = mol->getAtomAt(center);
643 Atom* atomB = mol->getAtomAt(satellites[0]);
644 Atom* atomC = mol->getAtomAt(satellites[1]);
645 Atom* atomD = mol->getAtomAt(satellites[2]);
646
647 assert(atomA && atomB && atomC && atomD);
648
649 if (stamp->hasOverride()) {
650
651 try {
652 inversionType = itParser.parseTypeAndPars(stamp->getOverrideType(),
653 stamp->getOverridePars() );
654 }
655 catch( OpenMDException& e) {
656 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH, "MoleculeCreator Error: %s "
657 "for molecule %s\n",
658 e.what(), mol->getType().c_str() );
659 painCave.isFatal = 1;
660 simError();
661 }
662 } else {
663
664 inversionType = ff->getInversionType(atomA->getType(),
665 atomB->getType(),
666 atomC->getType(),
667 atomD->getType());
668
669 if (inversionType == NULL) {
670 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
671 "No Matching Inversion Type for[%s, %s, %s, %s]\n"
672 "\t(May not be a problem: not all inversions are parametrized)\n",
673 atomA->getType().c_str(),
674 atomB->getType().c_str(),
675 atomC->getType().c_str(),
676 atomD->getType().c_str());
677
678 painCave.isFatal = 0;
679 painCave.severity = OPENMD_INFO;
680 simError();
681 }
682 }
683 if (inversionType != NULL) {
684
685 inversion = new Inversion(atomA, atomB, atomC, atomD, inversionType);
686
687 // set the local index of this inversion, the global index will
688 // be set later
689 inversion->setLocalIndex(localIndexMan->getNextInversionIndex());
690
691 // The rule for naming an inversion is: MoleculeName_Inversion_Integer
692 // The first part is the name of the molecule
693 // The second part is always fixed as "Inversion"
694 // The third part is the index of the inversion defined in meta-data file
695 // For example, Benzene_Inversion_0 is a valid Inversion name in a
696 // Benzene molecule
697
698 std::string s = OpenMD_itoa(mol->getNInversions(), 10);
699 inversion->setName(mol->getType() + "_Inversion_" + s.c_str());
700 return inversion;
701 } else {
702 return NULL;
703 }
704 }
705
706
707 CutoffGroup* MoleculeCreator::createCutoffGroup(Molecule* mol,
708 CutoffGroupStamp* stamp,
709 LocalIndexManager* localIndexMan) {
710 int nAtoms;
711 CutoffGroup* cg;
712 Atom* atom;
713 cg = new CutoffGroup();
714
715 nAtoms = stamp->getNMembers();
716 for (int i =0; i < nAtoms; ++i) {
717 atom = mol->getAtomAt(stamp->getMemberAt(i));
718 assert(atom);
719 cg->addAtom(atom);
720 }
721
722 //set the local index of this cutoffGroup, global index will be set later
723 cg->setLocalIndex(localIndexMan->getNextCutoffGroupIndex());
724
725 return cg;
726 }
727
728 CutoffGroup* MoleculeCreator::createCutoffGroup(Molecule * mol, Atom* atom,
729 LocalIndexManager* localIndexMan) {
730 CutoffGroup* cg;
731 cg = new CutoffGroup();
732 cg->addAtom(atom);
733
734 //set the local index of this cutoffGroup, global index will be set later
735 cg->setLocalIndex(localIndexMan->getNextCutoffGroupIndex());
736
737 return cg;
738 }
739
740 void MoleculeCreator::createConstraintPair(Molecule* mol) {
741
742 //add bond constraints
743 Molecule::BondIterator bi;
744 Bond* bond;
745 ConstraintPair* cPair;
746
747 for (bond = mol->beginBond(bi); bond != NULL; bond = mol->nextBond(bi)) {
748
749 BondType* bt = bond->getBondType();
750
751 if (typeid(FixedBondType) == typeid(*bt)) {
752 FixedBondType* fbt = dynamic_cast<FixedBondType*>(bt);
753
754 ConstraintElem* consElemA = new ConstraintElem(bond->getAtomA());
755 ConstraintElem* consElemB = new ConstraintElem(bond->getAtomB());
756 cPair = new ConstraintPair(consElemA, consElemB,
757 fbt->getEquilibriumBondLength(), false);
758 mol->addConstraintPair(cPair);
759 }
760 }
761
762 //rigidbody -- rigidbody constraint is not support yet
763 }
764
765 void MoleculeCreator::createConstraintElem(Molecule* mol) {
766
767 ConstraintPair* consPair;
768 Molecule::ConstraintPairIterator cpi;
769 std::set<StuntDouble*> sdSet;
770 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
771 consPair = mol->nextConstraintPair(cpi)) {
772
773 StuntDouble* sdA = consPair->getConsElem1()->getStuntDouble();
774 if (sdSet.find(sdA) == sdSet.end()){
775 sdSet.insert(sdA);
776 mol->addConstraintElem(new ConstraintElem(sdA));
777 }
778
779 StuntDouble* sdB = consPair->getConsElem2()->getStuntDouble();
780 if (sdSet.find(sdB) == sdSet.end()){
781 sdSet.insert(sdB);
782 mol->addConstraintElem(new ConstraintElem(sdB));
783 }
784 }
785 }
786 }
AtomType is what OpenMD looks to for unchanging data about an atom.
Definition AtomType.hpp:66
AtomType * getAtomType(const std::string &at)
getAtomType by string
"utils/LocalIndexManager.hpp"
virtual Atom * createAtom(ForceField *ff, Molecule *, AtomStamp *stamp, LocalIndexManager *localIndexMan)
Create an atom by its stamp.
Definition MC.cpp:240
size_t getNRigidBodies()
Returns the total number of rigid bodies in this molecule.
Definition Molecule.hpp:176
std::string getType()
Returns the name of the molecule.
Definition Molecule.hpp:120
virtual void setType(const std::string &name)
Sets the name of this stuntRealType.
Definition RigidBody.hpp:71
void calcRefCoords()
calculates the reference coordinates
void setLocalIndex(int index)
Sets the local index of this stuntDouble.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.