示例#1
0
文件: forces.cpp 项目: trisyoungs/duq
// Calculate total intramolecular forces
void DUQ::intramolecularForces(ProcessPool& procPool, Configuration* cfg, double* fx, double* fy, double* fz)
{
	/*
	 * Calculate the total intramolecular forces within the system, arising from Bond, Angle, and Torsion
	 * terms in all molecules.
	 * 
	 * This is a parallel routine.
	 */

	double distance, angle, force, dp, magji, magjk;
	int index, start, stride;
	Atom* i, *j, *k;
	Vec3<double> vecji, vecjk, forcei, forcek;

	// Set start/skip for parallel loop
	start = procPool.interleavedLoopStart(ProcessPool::OverPoolProcesses);
	stride = procPool.interleavedLoopStride(ProcessPool::OverPoolProcesses);

	// Main loop over molecules
	for (Molecule* mol = cfg->molecules(); mol != NULL; mol = mol->next)
	{
		// Bonds
		for (SpeciesBond* b = mol->species()->bonds(); b != NULL; b = b->next)
		{
			// Grab pointers to atoms involved in bond
			i = mol->atom(b->indexI());
			j = mol->atom(b->indexJ());

			// Determine whether we need to apply minimum image to the vector calculation
			if (cfg->useMim(i->grain()->cell(), j->grain()->cell())) vecji = cfg->box()->minimumVector(i, j);
			else vecji = j->r() - i->r();
			
			// Get distance and normalise vector ready for force calculation
			distance = vecji.magAndNormalise();

			// Determine final forces
			vecji *= b->force(distance);

			// Calculate forces
			index = b->i()->index();
			fx[index] -= vecji.x;
			fy[index] -= vecji.y;
			fz[index] -= vecji.z;
			index = b->j()->index();
			fx[index] += vecji.x;
			fy[index] += vecji.y;
			fz[index] += vecji.z;
		}

		// Angles
		for (SpeciesAngle* a = mol->species()->angles(); a != NULL; a = a->next)
		{
			// Grab pointers to atoms involved in angle
			i = mol->atom(a->indexI());
			j = mol->atom(a->indexJ());
			k = mol->atom(a->indexK());

			// Determine whether we need to apply minimum image between 'j-i' and 'j-k'
			if (cfg->useMim(j->grain()->cell(), i->grain()->cell())) vecji = cfg->box()->minimumVector(j, i);
			else vecji = i->r() - j->r();
			if (cfg->useMim(j->grain()->cell(), k->grain()->cell())) vecjk = cfg->box()->minimumVector(j, k);
			else vecjk = k->r() - j->r();
			
			// Calculate angle
			magji = vecji.magAndNormalise();
			magjk = vecjk.magAndNormalise();
			angle = Box::angle(vecji, vecjk, dp);

			// Determine Angle force vectors for atoms
			force = a->force(angle);
			forcei = vecjk - vecji * dp;
			forcei *= force / magji;
			forcek = vecji - vecjk * dp;
			forcek *= force / magjk;
			
			// Store forces
			index = a->i()->index();
			fx[index] += forcei.x;
			fy[index] += forcei.y;
			fz[index] += forcei.z;
			index = a->j()->index();
			fx[index] -= forcei.x + forcek.x;
			fy[index] -= forcei.y + forcek.y;
			fz[index] -= forcei.z + forcek.z;
			index = a->k()->index();
			fx[index] += forcek.x;
			fy[index] += forcek.y;
			fz[index] += forcek.z;
		}

	}
}
示例#2
0
文件: forces.cpp 项目: trisyoungs/duq
// Calculate Grain forces within the system
void DUQ::grainForces(ProcessPool& procPool, Configuration* cfg, double* fx, double* fy, double* fz, double cutoffSq)
{
	/*
	 * Calculates the total Grain forces within the system, i.e. the energy contributions from PairPotential
	 * interactions between Grains. Any connections between Grains (which in reality correspond to proper chemical bonds
	 * between Atoms) are automatically excluded.
	 * 
	 * This is a parallel routine.
	 */

	// Initialise the Cell distributor
	const bool willBeModified = false, allowRepeats = false;
	cfg->initialiseCellDistribution();

	// Create a ForcesKernel
	ForceKernel kernel(procPool, cfg->box(), potentialMap_);

	int cellId, n, m, start, stride;
	Cell* cell;
	Grain* grainI, *grainJ;

	// Set start/skip for parallel loop
	start = procPool.interleavedLoopStart(ProcessPool::OverGroups);
	stride = procPool.interleavedLoopStride(ProcessPool::OverGroups);

	while (cellId = cfg->nextAvailableCell(procPool, willBeModified, allowRepeats), cellId != Cell::AllCellsComplete)
	{
		// Check for valid cell
		if (cellId == Cell::NoCellsAvailable)
		{
			Messenger::printVerbose("Nothing for this process to do.\n");
			cfg->finishedWithCell(procPool, willBeModified, cellId);
			continue;
		}
		cell = cfg->cell(cellId);
		Messenger::printVerbose("Cell %i now the target, containing %i Grains interacting with %i neighbours.\n", cellId, cell->nGrains(), cell->nTotalCellNeighbours());

		/*
		 * Calculation Begins
		 */

		for (n=start; n<cell->nGrains(); n += stride)
		{
			grainI = cell->grain(n);

			// Inter-Grain interactions in this Cell...
			for (m=n+1; m<cell->nGrains(); ++m)
			{
				grainJ = cell->grain(m);
				kernel.forces(grainI, grainJ, false, false, fx, fy, fz);
			}
			
			// Inter-Grain interactions between this Grain and those in Cell neighbours
			kernel.forces(grainI, cell->nCellNeighbours(), cell->cellNeighbours(), false, true, fx, fy, fz, ProcessPool::Individual);
			kernel.forces(grainI, cell->nMimCellNeighbours(), cell->mimCellNeighbours(), true, true, fx, fy, fz, ProcessPool::Individual);
		}

		/*
		 * Calculation End
		 */
		
		// Must unlock the Cell when we are done with it!
		cfg->finishedWithCell(procPool, willBeModified, cellId);
	}
}