//!Precompute relative rotations (and precompute ScGeom3D) void ScGeom6D::precomputeRotations(const State& rbp1, const State& rbp2, bool isNew, bool creep){ if (isNew) { initRotations(rbp1,rbp2); } else { Quaternionr delta((rbp1.ori * (initialOrientation1.conjugate())) * (initialOrientation2 * (rbp2.ori.conjugate()))); delta.normalize(); if (creep) delta = delta * twistCreep; AngleAxisr aa(delta); // axis of rotation - this is the Moment direction UNIT vector; // angle represents the power of resistant ELASTIC moment //Eigen::AngleAxisr(q) returns nan's when q close to identity, next tline fixes the pb. // add -DYADE_SCGEOM_DEBUG to CXXFLAGS to enable this piece or just do // #define YADE_SCGEOM_DEBUG //(but do not commit with that enabled in the code) #ifdef YADE_SCGEOM_DEBUG if (isnan(aa.angle())) { cerr<<"NaN angle found in angleAxisr(q), for quaternion "<<delta<<", after quaternion product"<<endl; cerr<<"rbp1.ori * (initialOrientation1.conjugate())) * (initialOrientation2 * (rbp2.ori.conjugate()) with quaternions :"<<endl; cerr<<rbp1.ori<<" * "<<initialOrientation1<<" * "<<initialOrientation2<<" * "<<rbp2.ori<<endl<<" and sub-products :"<<endl<<rbp1.ori * (initialOrientation1.conjugate())<<" * "<<initialOrientation2 * (rbp2.ori.conjugate())<<endl; cerr <<"q.w (before normalization) "<<delta.w(); delta.normalize(); cerr <<"q.w (after) "<<delta.w()<<endl; AngleAxisr bb(delta); cerr<<delta<<" "<<bb.angle()<<endl; } #else if (isnan(aa.angle())) aa.angle()=0; #endif if (aa.angle() > Mathr::PI) aa.angle() -= Mathr::TWO_PI; // angle is between 0 and 2*pi, but should be between -pi and pi twist = (aa.angle() * aa.axis().dot(normal)); bending = Vector3r(aa.angle()*aa.axis() - twist*normal); } }
int TorsionalMinimisation::runcore() { if( m_InitPickerSerial != getPickerSerial() ) { initRotations(); // reinitialisation must occur, the atomic range definition has changed. } m_BestStore.store(); // Important to reinitialise these to ensure that we can call Run again without affecting the minimisation outcome. for( size_t i = 0; i < ChiRotDefs.size(); i++ ) { ChiRotDefs[i].Value = 0.0; ChiRotDefs[i].PrevValue = 0.0; } for( size_t i = 0; i < PhiPsiRotDefs.size(); i++ ) { PhiPsiRotDefs[i].Value = 0.0; PhiPsiRotDefs[i].PrevValue = 0.0; } getWSpace().Step = Step = 0; // let WorkSpace know about the current Step # // set the initial Step size // should be 100% if we are not in steric clash! AngleCap = IntendedMaxAngleCap * InitialCapFactor; //if require a gentle start - depends a bit on steric condition SCAngleCap = IntendedMaxSCAngleCap * InitialCapFactor; previous_epot = DBL_MAX; PrevSquare = RESET_PREV_SQUARE; Uphill = 0; // Ene monitoring for grad cutoff const size_t gradWindowSize = 20; std::vector<double> xGradMarker(gradWindowSize); std::vector<double> yGradMarker(gradWindowSize); size_t currentGradMarker = 0; Hamiltonian best_epot; // record the best energy, store the conformation when we beat it ... best_epot.epot = DBL_MAX; // Big number, the first step of minimisation will beat this ... if(OutputLevel) infoLineHeader(); // Main simulation inner-loop for( Step = 0; Step < Steps; Step++ ) { if( AngleCap < 0.00001 ) { // The minimisation has stalled, there is no point in doing more steps break; } getWSpace().Step = Step;// let particle system know about the current Step # //getWSpace().nlist().calcNewList(); refreshNeighborList(); ff->calcForces(); if(!isNumber(getWSpace().ene.epot)) { if(OutputLevel) { printf("Torsional CG Minimisation Unstable. Terminating... \n"); } return -1; } if( getWSpace().ene.epot < best_epot.epot ) { best_epot = getWSpace().ene; m_BestStore.store(); // record the best over the minimisation } ApplyXYZAbsoluteDotVector(); // 1. calculate the required torsional magnitudes. ActionConjugateGradient(); // 2. Normalise the magnitudes to give required changes in radians and apply. if(Step > 2) // until you have had 2 rounds, you cant assess "up-hill" or "down-hill" { if (getWSpace().ene.epot <= previous_epot) { Uphill = 0; // we are going "downhill" AngleCap *= CapRise; // if move was downhill then increase Step size (1.2 is an empiricly "good" weighting) SCAngleCap *= CapRise; if(AngleCap > IntendedMaxAngleCap) AngleCap = IntendedMaxAngleCap; if(SCAngleCap > IntendedMaxSCAngleCap) SCAngleCap = IntendedMaxSCAngleCap; //previous_epot = getWSpace().ene.epot; // : if Enabled here, disable after if(Step > 2)... } else { if( Uphill > 20 ) // The minimisation has stalled, there is no point in doing more steps { break; } Uphill++; // if move was uphill then halve Step size AngleCap *= CapDrop; SCAngleCap *= CapDrop; // reinitialise these for( size_t i = 0; i < ChiRotDefs.size(); i++ ) { ChiRotDefs[i].PrevValue = 0.0; } for( size_t i = 0; i < PhiPsiRotDefs.size(); i++ ) { PhiPsiRotDefs[i].PrevValue = 0.0; } PrevSquare = RESET_PREV_SQUARE; } } previous_epot = getWSpace().ene.epot; // : if Enabled here, disable in if(getWSpace().ene.epot <= previous_epot)... // Energy change over a number of Steps. // If no improvement over a gradient Cutoff then quit, our work is done... if( SlopeCutoff > 0.0 ) { if( currentGradMarker < gradWindowSize ) { xGradMarker[currentGradMarker] = (double)Step; yGradMarker[currentGradMarker++] = getWSpace().ene.epot; } else { double b = TMleastSquaresFit( xGradMarker, yGradMarker ); if( SlopeCutoff > -b ) { break; } xGradMarker[currentGradMarker % gradWindowSize] = (double)Step; yGradMarker[currentGradMarker % gradWindowSize] = getWSpace().ene.epot; currentGradMarker++; } } runmonitors(); // Save the coordinates in the trajectory as required if((UpdateTra > 0) && ((Step % UpdateTra) == 0) ) { getWSpace().outtra.append(); } // Display any information as required if( OutputLevel && (UpdateScr > 0) && ((Step % UpdateScr) == 0) ) { // now print info line infoLine(); ff->infoLine(); printf("\n"); } } m_BestStore.revert(); getWSpace().ene = best_epot; // its quicker to memcpy the energies than to ff->calcForces() ... return Step; // success } // end procedure
TorsionalMinimisation::TorsionalMinimisation( Physics::Forcefield &_ff, const PickAtomRanges& _newRange ): RangesProtocolBase( _ff, _newRange ) { settodefault(); initRotations(); // initialise the rotations that will be used during simulation }
void CylScGeom6D::precomputeRotations(const State& rbp1, const State& rbp2, bool isNew, bool creep) { initRotations(rbp1,rbp2); }