Beispiel #1
0
//!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
	}
Beispiel #4
0
void CylScGeom6D::precomputeRotations(const State& rbp1, const State& rbp2, bool isNew, bool creep) {
    initRotations(rbp1,rbp2);
}