ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/primitives/RigidBody.cpp
Revision: 1211
Committed: Wed Jan 23 16:38:22 2008 UTC (17 years, 3 months ago) by gezelter
File size: 15478 byte(s)
Log Message:
A few formatting changes to prettify the code

File Contents

# User Rev Content
1 gezelter 507 /*
2 gezelter 246 * 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. Acknowledgement of the program authors must be made in any
10     * publication of scientific results based in part on use of the
11     * program. An acceptable form of acknowledgement is citation of
12     * the article in which the program was described (Matthew
13     * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14     * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15     * Parallel Simulation Engine for Molecular Dynamics,"
16     * J. Comput. Chem. 26, pp. 252-271 (2005))
17     *
18     * 2. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 3. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in the
23     * documentation and/or other materials provided with the
24     * distribution.
25     *
26     * This software is provided "AS IS," without a warranty of any
27     * kind. All express or implied conditions, representations and
28     * warranties, including any implied warranty of merchantability,
29     * fitness for a particular purpose or non-infringement, are hereby
30     * excluded. The University of Notre Dame and its licensors shall not
31     * be liable for any damages suffered by licensee as a result of
32     * using, modifying or distributing the software or its
33     * derivatives. In no event will the University of Notre Dame or its
34     * licensors be liable for any lost revenue, profit or data, or for
35     * direct, indirect, special, consequential, incidental or punitive
36     * damages, however caused and regardless of the theory of liability,
37     * arising out of the use of or inability to use software, even if the
38     * University of Notre Dame has been advised of the possibility of
39     * such damages.
40     */
41     #include <algorithm>
42 tim 253 #include <math.h>
43 tim 3 #include "primitives/RigidBody.hpp"
44     #include "utils/simError.h"
45 tim 374 #include "utils/NumericConstant.hpp"
46 gezelter 246 namespace oopse {
47 gezelter 1211
48     RigidBody::RigidBody() : StuntDouble(otRigidBody, &Snapshot::rigidbodyData),
49     inertiaTensor_(0.0){
50 gezelter 507 }
51 gezelter 1211
52 gezelter 507 void RigidBody::setPrevA(const RotMat3x3d& a) {
53 gezelter 246 ((snapshotMan_->getPrevSnapshot())->*storage_).aMat[localIndex_] = a;
54 gezelter 1211
55 gezelter 246 for (int i =0 ; i < atoms_.size(); ++i){
56 gezelter 507 if (atoms_[i]->isDirectional()) {
57 gezelter 882 atoms_[i]->setPrevA(refOrients_[i].transpose() * a);
58 gezelter 507 }
59 gezelter 246 }
60 gezelter 1211
61 gezelter 507 }
62 gezelter 1211
63    
64 gezelter 507 void RigidBody::setA(const RotMat3x3d& a) {
65 gezelter 246 ((snapshotMan_->getCurrentSnapshot())->*storage_).aMat[localIndex_] = a;
66 gezelter 2
67 gezelter 246 for (int i =0 ; i < atoms_.size(); ++i){
68 gezelter 507 if (atoms_[i]->isDirectional()) {
69 gezelter 882 atoms_[i]->setA(refOrients_[i].transpose() * a);
70 gezelter 507 }
71 gezelter 246 }
72 gezelter 507 }
73 gezelter 1211
74 gezelter 507 void RigidBody::setA(const RotMat3x3d& a, int snapshotNo) {
75 gezelter 246 ((snapshotMan_->getSnapshot(snapshotNo))->*storage_).aMat[localIndex_] = a;
76 gezelter 1211
77 gezelter 246 //((snapshotMan_->getSnapshot(snapshotNo))->*storage_).electroFrame[localIndex_] = a.transpose() * sU_;
78 gezelter 1211
79 gezelter 246 for (int i =0 ; i < atoms_.size(); ++i){
80 gezelter 507 if (atoms_[i]->isDirectional()) {
81 gezelter 882 atoms_[i]->setA(refOrients_[i].transpose() * a, snapshotNo);
82 gezelter 507 }
83 gezelter 2 }
84 gezelter 1211
85 gezelter 507 }
86 gezelter 1211
87 gezelter 507 Mat3x3d RigidBody::getI() {
88 gezelter 246 return inertiaTensor_;
89 gezelter 507 }
90 gezelter 1211
91 tim 963 std::vector<RealType> RigidBody::getGrad() {
92     std::vector<RealType> grad(6, 0.0);
93 gezelter 246 Vector3d force;
94     Vector3d torque;
95     Vector3d myEuler;
96 tim 963 RealType phi, theta, psi;
97     RealType cphi, sphi, ctheta, stheta;
98 gezelter 246 Vector3d ephi;
99     Vector3d etheta;
100     Vector3d epsi;
101 gezelter 1211
102 gezelter 246 force = getFrc();
103     torque =getTrq();
104     myEuler = getA().toEulerAngles();
105 gezelter 1211
106 gezelter 246 phi = myEuler[0];
107     theta = myEuler[1];
108     psi = myEuler[2];
109 gezelter 1211
110 gezelter 246 cphi = cos(phi);
111     sphi = sin(phi);
112     ctheta = cos(theta);
113     stheta = sin(theta);
114 gezelter 1211
115 gezelter 246 // get unit vectors along the phi, theta and psi rotation axes
116 gezelter 1211
117 gezelter 246 ephi[0] = 0.0;
118     ephi[1] = 0.0;
119     ephi[2] = 1.0;
120 gezelter 1211
121 gezelter 246 etheta[0] = cphi;
122     etheta[1] = sphi;
123     etheta[2] = 0.0;
124 gezelter 1211
125 gezelter 246 epsi[0] = stheta * cphi;
126     epsi[1] = stheta * sphi;
127     epsi[2] = ctheta;
128 gezelter 1211
129 gezelter 246 //gradient is equal to -force
130     for (int j = 0 ; j<3; j++)
131 gezelter 507 grad[j] = -force[j];
132 gezelter 1211
133 gezelter 246 for (int j = 0; j < 3; j++ ) {
134 gezelter 1211
135 gezelter 507 grad[3] += torque[j]*ephi[j];
136     grad[4] += torque[j]*etheta[j];
137     grad[5] += torque[j]*epsi[j];
138 gezelter 1211
139 gezelter 246 }
140    
141     return grad;
142 gezelter 507 }
143 gezelter 1211
144 gezelter 507 void RigidBody::accept(BaseVisitor* v) {
145 gezelter 246 v->visit(this);
146 gezelter 507 }
147 gezelter 2
148 gezelter 507 /**@todo need modification */
149     void RigidBody::calcRefCoords() {
150 tim 963 RealType mtmp;
151 gezelter 246 Vector3d refCOM(0.0);
152     mass_ = 0.0;
153     for (std::size_t i = 0; i < atoms_.size(); ++i) {
154 gezelter 507 mtmp = atoms_[i]->getMass();
155     mass_ += mtmp;
156     refCOM += refCoords_[i]*mtmp;
157 gezelter 246 }
158     refCOM /= mass_;
159 gezelter 1211
160 gezelter 246 // Next, move the origin of the reference coordinate system to the COM:
161     for (std::size_t i = 0; i < atoms_.size(); ++i) {
162 gezelter 507 refCoords_[i] -= refCOM;
163 gezelter 246 }
164 gezelter 2
165 gezelter 507 // Moment of Inertia calculation
166 tim 642 Mat3x3d Itmp(0.0);
167 gezelter 246 for (std::size_t i = 0; i < atoms_.size(); i++) {
168 tim 642 Mat3x3d IAtom(0.0);
169 gezelter 507 mtmp = atoms_[i]->getMass();
170 tim 642 IAtom -= outProduct(refCoords_[i], refCoords_[i]) * mtmp;
171 tim 963 RealType r2 = refCoords_[i].lengthSquare();
172 tim 642 IAtom(0, 0) += mtmp * r2;
173     IAtom(1, 1) += mtmp * r2;
174     IAtom(2, 2) += mtmp * r2;
175 tim 648 Itmp += IAtom;
176 gezelter 1211
177 tim 642 //project the inertial moment of directional atoms into this rigid body
178 gezelter 507 if (atoms_[i]->isDirectional()) {
179 tim 646 Itmp += refOrients_[i].transpose() * atoms_[i]->getI() * refOrients_[i];
180 tim 648 }
181 tim 273 }
182    
183 chrisfen 695 // std::cout << Itmp << std::endl;
184 gezelter 663
185 gezelter 246 //diagonalize
186     Vector3d evals;
187     Mat3x3d::diagonalize(Itmp, evals, sU_);
188 gezelter 2
189 gezelter 246 // zero out I and then fill the diagonals with the moments of inertia:
190     inertiaTensor_(0, 0) = evals[0];
191     inertiaTensor_(1, 1) = evals[1];
192     inertiaTensor_(2, 2) = evals[2];
193    
194     int nLinearAxis = 0;
195     for (int i = 0; i < 3; i++) {
196 gezelter 507 if (fabs(evals[i]) < oopse::epsilon) {
197     linear_ = true;
198     linearAxis_ = i;
199     ++ nLinearAxis;
200     }
201 gezelter 246 }
202 gezelter 2
203 gezelter 246 if (nLinearAxis > 1) {
204 gezelter 507 sprintf( painCave.errMsg,
205     "RigidBody error.\n"
206     "\tOOPSE found more than one axis in this rigid body with a vanishing \n"
207     "\tmoment of inertia. This can happen in one of three ways:\n"
208     "\t 1) Only one atom was specified, or \n"
209     "\t 2) All atoms were specified at the same location, or\n"
210     "\t 3) The programmers did something stupid.\n"
211     "\tIt is silly to use a rigid body to describe this situation. Be smarter.\n"
212     );
213     painCave.isFatal = 1;
214     simError();
215 gezelter 246 }
216 gezelter 2
217 gezelter 507 }
218 gezelter 2
219 gezelter 507 void RigidBody::calcForcesAndTorques() {
220 gezelter 246 Vector3d afrc;
221     Vector3d atrq;
222     Vector3d apos;
223     Vector3d rpos;
224     Vector3d frc(0.0);
225 gezelter 1126 Vector3d trq(0.0);
226 gezelter 246 Vector3d pos = this->getPos();
227     for (int i = 0; i < atoms_.size(); i++) {
228 gezelter 2
229 gezelter 507 afrc = atoms_[i]->getFrc();
230     apos = atoms_[i]->getPos();
231     rpos = apos - pos;
232 gezelter 246
233 gezelter 507 frc += afrc;
234 gezelter 2
235 gezelter 507 trq[0] += rpos[1]*afrc[2] - rpos[2]*afrc[1];
236     trq[1] += rpos[2]*afrc[0] - rpos[0]*afrc[2];
237     trq[2] += rpos[0]*afrc[1] - rpos[1]*afrc[0];
238 gezelter 2
239 gezelter 507 // If the atom has a torque associated with it, then we also need to
240     // migrate the torques onto the center of mass:
241 gezelter 2
242 gezelter 507 if (atoms_[i]->isDirectional()) {
243     atrq = atoms_[i]->getTrq();
244     trq += atrq;
245 gezelter 1126 }
246     }
247     addFrc(frc);
248     addTrq(trq);
249     }
250    
251     Mat3x3d RigidBody::calcForcesAndTorquesAndVirial() {
252     Vector3d afrc;
253     Vector3d atrq;
254     Vector3d apos;
255     Vector3d rpos;
256 gezelter 1211 Vector3d dfrc;
257 gezelter 1126 Vector3d frc(0.0);
258     Vector3d trq(0.0);
259     Vector3d pos = this->getPos();
260     Mat3x3d tau_(0.0);
261    
262     for (int i = 0; i < atoms_.size(); i++) {
263 gezelter 1211
264 gezelter 1126 afrc = atoms_[i]->getFrc();
265     apos = atoms_[i]->getPos();
266     rpos = apos - pos;
267    
268     frc += afrc;
269    
270     trq[0] += rpos[1]*afrc[2] - rpos[2]*afrc[1];
271     trq[1] += rpos[2]*afrc[0] - rpos[0]*afrc[2];
272     trq[2] += rpos[0]*afrc[1] - rpos[1]*afrc[0];
273    
274     // If the atom has a torque associated with it, then we also need to
275     // migrate the torques onto the center of mass:
276    
277     if (atoms_[i]->isDirectional()) {
278     atrq = atoms_[i]->getTrq();
279     trq += atrq;
280 gezelter 507 }
281 gezelter 1126
282     tau_(0,0) -= rpos[0]*afrc[0];
283     tau_(0,1) -= rpos[0]*afrc[1];
284     tau_(0,2) -= rpos[0]*afrc[2];
285     tau_(1,0) -= rpos[1]*afrc[0];
286     tau_(1,1) -= rpos[1]*afrc[1];
287     tau_(1,2) -= rpos[1]*afrc[2];
288     tau_(2,0) -= rpos[2]*afrc[0];
289     tau_(2,1) -= rpos[2]*afrc[1];
290     tau_(2,2) -= rpos[2]*afrc[2];
291 gezelter 1211
292     }
293 tim 899 addFrc(frc);
294     addTrq(trq);
295 gezelter 1126 return tau_;
296 gezelter 507 }
297 gezelter 2
298 gezelter 507 void RigidBody::updateAtoms() {
299 gezelter 246 unsigned int i;
300     Vector3d ref;
301     Vector3d apos;
302     DirectionalAtom* dAtom;
303     Vector3d pos = getPos();
304     RotMat3x3d a = getA();
305 gezelter 2
306 gezelter 246 for (i = 0; i < atoms_.size(); i++) {
307    
308 gezelter 507 ref = body2Lab(refCoords_[i]);
309 gezelter 2
310 gezelter 507 apos = pos + ref;
311 gezelter 2
312 gezelter 507 atoms_[i]->setPos(apos);
313 gezelter 2
314 gezelter 507 if (atoms_[i]->isDirectional()) {
315 gezelter 246
316 gezelter 507 dAtom = (DirectionalAtom *) atoms_[i];
317 gezelter 882 dAtom->setA(refOrients_[i].transpose() * a);
318 gezelter 507 }
319 gezelter 2
320     }
321    
322 gezelter 507 }
323 gezelter 2
324    
325 gezelter 507 void RigidBody::updateAtoms(int frame) {
326 tim 318 unsigned int i;
327     Vector3d ref;
328     Vector3d apos;
329     DirectionalAtom* dAtom;
330     Vector3d pos = getPos(frame);
331     RotMat3x3d a = getA(frame);
332    
333     for (i = 0; i < atoms_.size(); i++) {
334    
335 gezelter 507 ref = body2Lab(refCoords_[i], frame);
336 tim 318
337 gezelter 507 apos = pos + ref;
338 tim 318
339 gezelter 507 atoms_[i]->setPos(apos, frame);
340 tim 318
341 gezelter 507 if (atoms_[i]->isDirectional()) {
342 tim 318
343 gezelter 507 dAtom = (DirectionalAtom *) atoms_[i];
344 gezelter 882 dAtom->setA(refOrients_[i].transpose() * a, frame);
345 gezelter 507 }
346 tim 318
347     }
348    
349 gezelter 507 }
350 tim 318
351 gezelter 507 void RigidBody::updateAtomVel() {
352 tim 318 Mat3x3d skewMat;;
353    
354     Vector3d ji = getJ();
355     Mat3x3d I = getI();
356    
357     skewMat(0, 0) =0;
358     skewMat(0, 1) = ji[2] /I(2, 2);
359     skewMat(0, 2) = -ji[1] /I(1, 1);
360    
361     skewMat(1, 0) = -ji[2] /I(2, 2);
362     skewMat(1, 1) = 0;
363     skewMat(1, 2) = ji[0]/I(0, 0);
364    
365     skewMat(2, 0) =ji[1] /I(1, 1);
366     skewMat(2, 1) = -ji[0]/I(0, 0);
367     skewMat(2, 2) = 0;
368    
369     Mat3x3d mat = (getA() * skewMat).transpose();
370     Vector3d rbVel = getVel();
371    
372    
373     Vector3d velRot;
374     for (int i =0 ; i < refCoords_.size(); ++i) {
375 gezelter 507 atoms_[i]->setVel(rbVel + mat * refCoords_[i]);
376 tim 318 }
377    
378 gezelter 507 }
379 tim 318
380 gezelter 507 void RigidBody::updateAtomVel(int frame) {
381 tim 318 Mat3x3d skewMat;;
382    
383     Vector3d ji = getJ(frame);
384     Mat3x3d I = getI();
385    
386     skewMat(0, 0) =0;
387     skewMat(0, 1) = ji[2] /I(2, 2);
388     skewMat(0, 2) = -ji[1] /I(1, 1);
389    
390     skewMat(1, 0) = -ji[2] /I(2, 2);
391     skewMat(1, 1) = 0;
392     skewMat(1, 2) = ji[0]/I(0, 0);
393    
394     skewMat(2, 0) =ji[1] /I(1, 1);
395     skewMat(2, 1) = -ji[0]/I(0, 0);
396     skewMat(2, 2) = 0;
397    
398     Mat3x3d mat = (getA(frame) * skewMat).transpose();
399     Vector3d rbVel = getVel(frame);
400    
401    
402     Vector3d velRot;
403     for (int i =0 ; i < refCoords_.size(); ++i) {
404 gezelter 507 atoms_[i]->setVel(rbVel + mat * refCoords_[i], frame);
405 tim 318 }
406    
407 gezelter 507 }
408 tim 318
409    
410    
411 gezelter 507 bool RigidBody::getAtomPos(Vector3d& pos, unsigned int index) {
412 gezelter 246 if (index < atoms_.size()) {
413 gezelter 2
414 gezelter 507 Vector3d ref = body2Lab(refCoords_[index]);
415     pos = getPos() + ref;
416     return true;
417 gezelter 246 } else {
418 gezelter 507 std::cerr << index << " is an invalid index, current rigid body contains "
419     << atoms_.size() << "atoms" << std::endl;
420     return false;
421 gezelter 246 }
422 gezelter 507 }
423 gezelter 2
424 gezelter 507 bool RigidBody::getAtomPos(Vector3d& pos, Atom* atom) {
425 gezelter 246 std::vector<Atom*>::iterator i;
426     i = std::find(atoms_.begin(), atoms_.end(), atom);
427     if (i != atoms_.end()) {
428 gezelter 507 //RigidBody class makes sure refCoords_ and atoms_ match each other
429     Vector3d ref = body2Lab(refCoords_[i - atoms_.begin()]);
430     pos = getPos() + ref;
431     return true;
432 gezelter 246 } else {
433 gezelter 507 std::cerr << "Atom " << atom->getGlobalIndex()
434     <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
435     return false;
436 gezelter 2 }
437 gezelter 507 }
438     bool RigidBody::getAtomVel(Vector3d& vel, unsigned int index) {
439 gezelter 2
440 gezelter 246 //velRot = $(A\cdot skew(I^{-1}j))^{T}refCoor$
441 gezelter 2
442 gezelter 246 if (index < atoms_.size()) {
443 gezelter 2
444 gezelter 507 Vector3d velRot;
445     Mat3x3d skewMat;;
446     Vector3d ref = refCoords_[index];
447     Vector3d ji = getJ();
448     Mat3x3d I = getI();
449 gezelter 2
450 gezelter 507 skewMat(0, 0) =0;
451     skewMat(0, 1) = ji[2] /I(2, 2);
452     skewMat(0, 2) = -ji[1] /I(1, 1);
453 gezelter 2
454 gezelter 507 skewMat(1, 0) = -ji[2] /I(2, 2);
455     skewMat(1, 1) = 0;
456     skewMat(1, 2) = ji[0]/I(0, 0);
457 gezelter 2
458 gezelter 507 skewMat(2, 0) =ji[1] /I(1, 1);
459     skewMat(2, 1) = -ji[0]/I(0, 0);
460     skewMat(2, 2) = 0;
461 gezelter 2
462 gezelter 507 velRot = (getA() * skewMat).transpose() * ref;
463 gezelter 2
464 gezelter 507 vel =getVel() + velRot;
465     return true;
466 gezelter 246
467     } else {
468 gezelter 507 std::cerr << index << " is an invalid index, current rigid body contains "
469     << atoms_.size() << "atoms" << std::endl;
470     return false;
471 gezelter 2 }
472 gezelter 507 }
473 gezelter 2
474 gezelter 507 bool RigidBody::getAtomVel(Vector3d& vel, Atom* atom) {
475 gezelter 2
476 gezelter 246 std::vector<Atom*>::iterator i;
477     i = std::find(atoms_.begin(), atoms_.end(), atom);
478     if (i != atoms_.end()) {
479 gezelter 507 return getAtomVel(vel, i - atoms_.begin());
480 gezelter 246 } else {
481 gezelter 507 std::cerr << "Atom " << atom->getGlobalIndex()
482     <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
483     return false;
484 gezelter 246 }
485 gezelter 507 }
486 gezelter 2
487 gezelter 507 bool RigidBody::getAtomRefCoor(Vector3d& coor, unsigned int index) {
488 gezelter 246 if (index < atoms_.size()) {
489    
490 gezelter 507 coor = refCoords_[index];
491     return true;
492 gezelter 246 } else {
493 gezelter 507 std::cerr << index << " is an invalid index, current rigid body contains "
494     << atoms_.size() << "atoms" << std::endl;
495     return false;
496 gezelter 2 }
497    
498 gezelter 507 }
499 gezelter 2
500 gezelter 507 bool RigidBody::getAtomRefCoor(Vector3d& coor, Atom* atom) {
501 gezelter 246 std::vector<Atom*>::iterator i;
502     i = std::find(atoms_.begin(), atoms_.end(), atom);
503     if (i != atoms_.end()) {
504 gezelter 507 //RigidBody class makes sure refCoords_ and atoms_ match each other
505     coor = refCoords_[i - atoms_.begin()];
506     return true;
507 gezelter 246 } else {
508 gezelter 507 std::cerr << "Atom " << atom->getGlobalIndex()
509     <<" does not belong to Rigid body "<< getGlobalIndex() << std::endl;
510     return false;
511 gezelter 246 }
512 gezelter 2
513 gezelter 507 }
514 gezelter 2
515    
516 gezelter 507 void RigidBody::addAtom(Atom* at, AtomStamp* ats) {
517 gezelter 2
518 gezelter 507 Vector3d coords;
519     Vector3d euler;
520 gezelter 2
521    
522 gezelter 507 atoms_.push_back(at);
523 gezelter 246
524 gezelter 507 if( !ats->havePosition() ){
525     sprintf( painCave.errMsg,
526     "RigidBody error.\n"
527     "\tAtom %s does not have a position specified.\n"
528     "\tThis means RigidBody cannot set up reference coordinates.\n",
529 tim 770 ats->getType().c_str() );
530 gezelter 507 painCave.isFatal = 1;
531     simError();
532     }
533 gezelter 2
534 gezelter 507 coords[0] = ats->getPosX();
535     coords[1] = ats->getPosY();
536     coords[2] = ats->getPosZ();
537 gezelter 2
538 gezelter 507 refCoords_.push_back(coords);
539 gezelter 2
540 gezelter 507 RotMat3x3d identMat = RotMat3x3d::identity();
541 gezelter 2
542 gezelter 507 if (at->isDirectional()) {
543 gezelter 2
544 gezelter 507 if( !ats->haveOrientation() ){
545     sprintf( painCave.errMsg,
546     "RigidBody error.\n"
547     "\tAtom %s does not have an orientation specified.\n"
548     "\tThis means RigidBody cannot set up reference orientations.\n",
549 tim 770 ats->getType().c_str() );
550 gezelter 507 painCave.isFatal = 1;
551     simError();
552     }
553 gezelter 246
554 gezelter 507 euler[0] = ats->getEulerPhi() * NumericConstant::PI /180.0;
555     euler[1] = ats->getEulerTheta() * NumericConstant::PI /180.0;
556     euler[2] = ats->getEulerPsi() * NumericConstant::PI /180.0;
557 gezelter 2
558 gezelter 507 RotMat3x3d Atmp(euler);
559     refOrients_.push_back(Atmp);
560 gezelter 2
561 gezelter 507 }else {
562     refOrients_.push_back(identMat);
563     }
564 gezelter 2
565    
566 gezelter 507 }
567 gezelter 2
568     }
569