Esempio n. 1
0
// Execute Method
bool Export::process(DUQ& duq, ProcessPool& procPool)
{
	/*
	* Export data from the target Configuration(s)
	 */

	// Loop over target Configurations
	for (RefListItem<Configuration,bool>* ri = targetConfigurations_.first(); ri != NULL; ri = ri->next)
	{
		// Grab Configuration pointer
		Configuration* cfg = ri->item;

		// Retrieve control parameters from Configuration
		const char* saveTrajectory = variableAsChar(cfg, "SaveTrajectory");

		/*
		 * Save XYZ Trajectory
		 */
		if (!DUQSys::isEmpty(saveTrajectory))
		{
			Messenger::print("Export: Appending to trajectory output file '%s'...\n", cfg->outputCoordinatesFile());

			// Only the pool master saves the data
			if (procPool.isMaster())
			{
				// Open the file
				LineParser parser;
				if (!parser.appendOutput(saveTrajectory))
				{
					parser.closeFiles();
					procPool.stop();
					return false;
				}
				else if (!writeConfigurationXYZ(parser, cfg, cfg->name()))
				{
					Messenger::print("Export: Failed to append to trajectory file.\n");
					parser.closeFiles();
					procPool.stop();
					return false;
				}

				procPool.proceed();
			}
			else if (!procPool.decision()) return false;

			Messenger::print("Export: Finished appending trajectory file.\n");
		}
	}

	return true;
}
Esempio n. 2
0
// Load Species information from XYZ file
bool Species::loadFromXYZ(const char* filename)
{
	Messenger::print("Loading XYZ data from file '%s'\n", filename);
	
	// Open the specified file...
	LineParser parser;
	parser.openInput(filename);
	if (!parser.isFileGoodForReading())
	{
		Messenger::error("Couldn't open XYZ file '%s'.\n", filename);
		return false;
	}

	// Clear any existing data
	clear();

	// Simple format - first line is number of atoms, next line is title, then follow atoms/coordinates, one atom per line
	parser.getArgsDelim(LineParser::Defaults);
	int nAtoms = parser.argi(0);
	parser.readNextLine(LineParser::Defaults);
	name_ = parser.line();
	int el, success;
	for (int n=0; n<nAtoms; ++n)
	{
		success = parser.getArgsDelim(LineParser::Defaults);
		if (success != 0)
		{
			parser.closeFiles();
			Messenger::error("Couldn't read Atom %i from file '%s'\n", n+1, filename);
			return false;
		}
		el = PeriodicTable::find(parser.argc(0));
		if (el == -1) el = 0;
		SpeciesAtom* i = addAtom(el, parser.argd(1), parser.argd(2),parser.argd(3));
		if (parser.hasArg(4)) i->setCharge(parser.argd(4));
	}

	Messenger::print("Succesfully loaded XYZ data from file '%s'.\n", filename);
	parser.closeFiles();
	return true;
}
Esempio n. 3
0
/*
 * \brief Perform some MD
 * \details Evolve the current Configuration using a simple molecular dynamics algorithm.
 * 
 * This is a parallel routine, with processes operating in process groups.
 */
bool DUQ::md(Configuration& cfg, double cutoffDistance, int nSteps, double deltaT)
{
	// Check input values if necessary
	if (cutoffDistance < 0.0) cutoffDistance = pairPotentialRange_;
	const double cutoffSq = cutoffDistance * cutoffDistance;
	const double temperature = cfg.temperature();
	bool writeTraj = false;
	bool calcEnergy = true;
	int writeFreq = 10;

	// Print summary of parameters
	Messenger::print("MD: Number of steps = %i\n", nSteps);
	Messenger::print("MD: Cutoff distance is %f\n", cutoffDistance);
	Messenger::print("MD: Timestep = %10.3e ps\n", deltaT);
	if (writeTraj) Messenger::print("MD: Trajectory file '%s' will be appended.\n");
	else Messenger::print("MD: Trajectory file off.\n");
	Messenger::print("MD: Energy %s be calculated at each step.\n", calcEnergy ? "will" : "will not");
	Messenger::print("MD: Summary will be written every %i step(s).\n", writeFreq);

	// Create force arrays as simple double arrays (easier to sum with MPI) - others are Vec3<double> arrays
	Array<double> mass(cfg.nAtoms()), fx(cfg.nAtoms()), fy(cfg.nAtoms()), fz(cfg.nAtoms());
	Array< Vec3<double> > a(cfg.nAtoms()), v(cfg.nAtoms()), deltaR(cfg.nAtoms());

	// Variables
	int n, maxDeltaId;
	Atom* atoms = cfg.atoms();
	Atom* i;
	double maxDelta, deltaSq, massSum, tInstant, ke, tScale, pe;
	double deltaTSq = deltaT*deltaT;
	Vec3<double> vCom;
	double maxForce = 100.0;

	/*
	 * Calculation Begins
	 */
	
	// Assign random velocities to start... (grab atomic masses at the same time...)
	Messenger::print("Assigning random velocities...\n");
	vCom.zero();
	massSum = 0.0;
	for (n=0; n<cfg.nAtoms(); ++n)
	{
		i = cfg.atom(n);
		v[n].x = exp(DUQMath::random()-0.5) / sqrt(TWOPI);
		v[n].y = exp(DUQMath::random()-0.5) / sqrt(TWOPI);
		v[n].z = exp(DUQMath::random()-0.5) / sqrt(TWOPI);
		mass[n] = PeriodicTable::element(i->element()).isotope(0)->atomicWeight();
		vCom += v[n] * mass[n];
		massSum += mass[n];
	}

	// Remove velocity shift
	vCom /= massSum;
	v -= vCom;

	// Calculate instantaneous temperature
        // J = kg m2 s-2  -->   10 J = g Ang2 ps-2
        // If ke is in units of [g mol-1 Angstroms2 ps-2] then must use kb in units of 10 J mol-1 K-1 (= 0.8314462)
	const double kb = 0.8314462;
	ke = 0.0;
	pe = 0.0;
	for (n=0; n<cfg.nAtoms(); ++n) ke += 0.5 * mass[n] * v[n].dp(v[n]);
	tInstant = ke * 2.0 / (3.0 * cfg.nAtoms() * kb);
	
	// Rescale velocities for desired temperature
	tScale = sqrt(temperature / tInstant);
	for (n=0; n<cfg.nAtoms(); ++n) v[n] *= tScale;

	// Open trajectory file (if requested)
	LineParser trajParser;
	if (writeTraj)
	{
		Dnchar trajectoryFile = cfg.name();
		trajectoryFile.strcat(".md.xyz");
		if (Comm.master())
		{
			if ((!trajParser.openOutput(trajectoryFile, true)) || (!trajParser.isFileGoodForWriting()))
			{
				Messenger::error("Failed to open MD trajectory output file '%s'.\n", trajectoryFile.get());
				Comm.decide(false);
				return false;
			}
			Comm.decide(true);
		}
		else if (!Comm.decision()) return false;
	}

	// Write header to screen
	if (calcEnergy) Messenger::print("  Step             T(K)      K.E.(kJ/mol) P.E.(kJ/mol) Etot(kJ/mol)\n");
	else Messenger::print("  Step             T(K)      K.E.(kj/mol)\n");

	// Start a timer
	Timer timer;

	// Ready to do MD propagation of system
	timer.start();
	Comm.resetAccumulatedTime();
	for (int step=0; step<nSteps; ++step)
	{
// 		 deltaT = 0.001;
// 		 deltaTSq = deltaT*deltaT;
// 		// Velocity Verlet first stage (A) and zero forces
// 		// A:  r(t+dt) = r(t) + v(t)*dt + 0.5*a(t)*dt**2
// 		// A:  v(t+dt/2) = v(t) + 0.5*a(t)*dt
// 		// B:  a(t+dt) = F(t+dt)/m
// 		// B:  v(t+dt) = v(t+dt/2) + 0.5*a(t+dt)*dt
// 		maxDelta = 0.0;
// 		maxDeltaId = -1;
// 		for (n=0; n<cfg.nAtoms(); ++n)
// 		{
// 			// Calculate position deltas and determine maximum displacement for current timestep
// 			deltaR[n] = v[n]*deltaT + a[n]*0.5*deltaTSq;
// 			deltaSq = deltaR[n].magnitudeSq();
// 			if (deltaSq > maxDelta)
// 			{
// 				maxDelta = deltaSq;
// 				maxDeltaId = n;
// 			}
// 		}
// 		maxDelta = sqrt(maxDelta);
// 		Messenger::print("Current timestep (%e) will give a maximum displacement of %f Angstroms\n", deltaT, maxDelta);
// 		if (step > 0)
// 		{
// 			do
// 			{
// 				deltaT *= (v[maxDeltaId]*deltaT + a[maxDeltaId]*0.5*deltaTSq).magnitude() > maxDisplacement ? 0.99 : 1.01;
// 				deltaTSq = deltaT*deltaT;
// 			} while (fabs((v[maxDeltaId]*deltaT + a[maxDeltaId]*0.5*deltaTSq).magnitude() - maxDisplacement) > (maxDisplacement*0.05));
// 			// Adjust timestep to give maximum movement and avoid explosion
// 			// dR/dT = v + a*deltaT
// // 			printf("Deriv = %f %f\n", (v[maxDeltaId]+a[maxDeltaId]*deltaT).magnitude(), (v[maxDeltaId]+a[maxDeltaId]*deltaT).magnitude() / (maxDelta - 0.1));
// // 			deltaT = 1.0 / ((v[maxDeltaId]+a[maxDeltaId]*deltaT).magnitude() / 0.1);
// // 			printf("xxx = %f %f\n", 1.0 / deltaT, (maxDelta/maxDisplacement) * (v[maxDeltaId]+a[maxDeltaId]*deltaT).magnitude());
// // // 			deltaT = 0.000564480;
// // 			deltaT = 1.0 / ((maxDelta/maxDisplacement) * (v[maxDeltaId]+a[maxDeltaId]*deltaT).magnitude());
// // 			deltaT = deltaT/2.0;
// 			printf("New DeltaT = %f\n", deltaT);
// 		}

// 		// TEST - Check max displacement with new deltaT
// 		maxDelta = 0.0;
// 		for (n=0; n<cfg.nAtoms(); ++n)
// 		{
// 			// Calculate position deltas and determine maximum displacement for current timestep
// 			deltaR[n] = v[n]*deltaT + a[n]*0.5*deltaTSq;
// 			deltaSq = deltaR[n].magnitudeSq();
// 			if (deltaSq > maxDelta) maxDelta = deltaSq;
// 		}
// 		printf("New max delta = %f\n", sqrt(maxDelta));
		
		for (n=0; n<cfg.nAtoms(); ++n)
		{
			i = cfg.atom(n);

			// Propagate positions (by whole step)...
			i->translateCoordinates(v[n]*deltaT + a[n]*0.5*deltaTSq);

			// ...velocities (by half step)...
			v[n] += a[n]*0.5*deltaT;
			
			// Zero force ready for next calculation
			fx[n] = 0.0;
			fy[n] = 0.0;
			fz[n] = 0.0;
		}

		// Grain coordinates will have changed...
		cfg.updateGrains();

		// Calculate forces - must multiply by 100.0 to convert from kJ/mol to 10J/mol (internal MD units)
		totalForces(cfg, fx, fy, fz, cutoffSq);
		fx *= 100.0;
		fy *= 100.0;
		fz *= 100.0;

// 		// Cap forces
// 		for (n=0; n<cfg.nAtoms(); ++n)
// 		{
// 			// Calculate position deltas and determine maximum displacement for current timestep
// 			if (fx[n] < maxForce) fx[n] = -maxForce;
// 			else if (fx[n] > maxForce) fx[n] = maxForce;
// 			if (fy[n] < maxForce) fy[n] = -maxForce;
// 			else if (fy[n] > maxForce) fy[n] = maxForce;
// 			if (fz[n] < maxForce) fz[n] = -maxForce;
// 			else if (fz[n] > maxForce) fz[n] = maxForce;
// 		}

		// Velocity Verlet second stage (B) and velocity scaling
		// A:  r(t+dt) = r(t) + v(t)*dt + 0.5*a(t)*dt**2
		// A:  v(t+dt/2) = v(t) + 0.5*a(t)*dt
		// B:  a(t+dt) = F(t+dt)/m
		// B:  v(t+dt) = v(t+dt/2) + 0.5*a(t+dt)*dt
		ke = 0.0;
		for (n=0; n<cfg.nAtoms(); ++n)
		{
			// Determine new accelerations
			a[n].set(fx[n], fy[n], fz[n]);
			a[n] /= mass[n];

			// ..and finally velocities again (by second half-step)
			v[n] += a[n]*0.5*deltaT;
			
			ke += 0.5 * mass[n] * v[n].dp(v[n]);
		}

		// Rescale velocities for desired temperature
		tInstant = ke * 2.0 / (3.0 * cfg.nAtoms() * kb);
		tScale = sqrt(temperature / tInstant);
		v *= tScale;
		
		// Convert ke from 10J mol-1 to kJ/mol
		ke *= 0.01;

		// Calculate step energy
		if (calcEnergy) pe = intergrainEnergy(cfg) + intramolecularEnergy(cfg);
		
		// Write step summary?
		if (step%writeFreq == 0)
		{
			if (calcEnergy) Messenger::print("  %-10i    %10.3e   %10.3e   %10.3e   %10.3e\n", step+1, tInstant, ke, pe, ke+pe);
			else Messenger::print("  %-10i    %10.3e   %10.3e\n", step+1, tInstant, ke);
		}

		// Save trajectory frame
		if (writeTraj)
		{
			if (Comm.master())
			{
				// Write number of atoms
				trajParser.writeLineF("%i\n", cfg.nAtoms());

				// Construct and write header
				Dnchar header(-1, "Step %i of %i, T = %10.3e, ke = %10.3e", step+1, nSteps, tInstant, ke);
				if (calcEnergy) header.strcatf(", pe = %10.3e, tot = %10.3e", pe, ke+pe);
				trajParser.writeLineF("%s\n", header.get());
				// Write Atoms
				for (int n=0; n<cfg.nAtoms(); ++n)
				{
					i = cfg.atom(n);
					trajParser.writeLineF("%-3s   %10.3f  %10.3f  %10.3f\n", PeriodicTable::element(i->element()).symbol(), i->r().x, i->r().y, i->r().z);
				}
			}
			else if (!Comm.decision()) return false;
		}
        }
        timer.stop();

	// Close trajectory file
	if (writeTraj && Comm.master()) trajParser.closeFiles();

        Messenger::print("%i molecular dynamics steps performed (%s work, %s comms)\n", nSteps, timer.timeString(), Comm.accumulatedTimeString());

	// Increment configuration changeCount_
	cfg.incrementCoordinateIndex();

	/*
	 * Calculation End
	 */
	
	return true;
}
Esempio n. 4
0
ATEN_USING_NAMESPACE

// Load includes
void Aten::loadEncoderDefinitions()
{
	Messenger::enter("Aten::loadEncoderDefinitions");

	QString encoderDefsFile = dataDirectoryFile("external/encoders.txt");
	Messenger::print(Messenger::Verbose, "Looking for encoder definitions (%s)...", qPrintable(encoderDefsFile));
	
	LineParser parser;
	parser.openInput(encoderDefsFile);
	if (!parser.isFileGoodForReading())
	{
		Messenger::print("Unable to open encoder definitions file.\n");
		return;
	}

	// Read in encoder definitions from file
	QString keyword;
	EncoderDefinition::EncoderDefinitionKeyword edk;
	EncoderDefinition* encoder = NULL;
	ExternalCommand* command = NULL;
	while (!parser.eofOrBlank())
	{
		// Read first argument from file, which is our keyword
		parser.getArgsDelim(Parser::SkipBlanks + Parser::StripComments + Parser::UseQuotes);
		keyword = parser.argc(0);
		edk = EncoderDefinition::encoderDefinitionKeyword(keyword);
		if (edk == EncoderDefinition::nEncoderDefinitionKeywords)
		{
			Messenger::print("Unrecognised encoder definition keyword '%s'. Ignoring...\n", qPrintable(keyword));
			continue;
		}

		// Deal with remaining keywords
		switch (edk)
		{
			// Command Name
			case (EncoderDefinition::CommandNameKeyword):
				if (!encoder)
				{
					Messenger::error("No encoder definition yet created in which to set name data (use 'Name' keyword before all others).\n");
					continue;
				}
				command = encoder->addCommand();
				command->setName(parser.argc(1));
				break;
			// Command
			case (EncoderDefinition::CommandKeyword):
				if (!command)
				{
					Messenger::error("No command definition yet created in which to set command data (use 'CommandName' keyword before its siblings).\n");
					continue;
				}
				command->setExecutable(parser.argc(1));
				break;
			// Command arguments
			case (EncoderDefinition::CommandArgumentsKeyword):
				if (!command)
				{
					Messenger::error("No command definition yet created in which to set argument data (use 'CommandName' keyword before its siblings).\n");
					continue;
				}
				command->setArguments(parser.argc(1));
				break;
			case (EncoderDefinition::CommandSearchPathsKeyword):
				if (!command)
				{
					Messenger::error("No command definition yet created in which to set searchpath data (use 'CommandName' keyword before its siblings).\n");
					continue;
				}
				for (int n=1; n<parser.nArgs(); ++n) command->addSearchPath(parser.argc(n));
				break;
			// Name (create new object)
			case (EncoderDefinition::NameKeyword):
				encoder = encoders_.add();
				encoder->setName(parser.argc(1));
				break;
			case (EncoderDefinition::NicknameKeyword):
				if (!encoder)
				{
					Messenger::error("No encoder definition yet created in which to set data (use 'Name' keyword before all others).\n");
					continue;
				}
				encoder->setNickname(parser.argc(1));
				break;
      default:
        break;  
		}
	}
	parser.closeFiles();

	Messenger::exit("Aten::loadEncoderDefinitions");
}