Add Maxwell-Boltzmann method for velocities
This commit is contained in:
@@ -20,11 +20,8 @@ int main() {
|
|||||||
|
|
||||||
System system(0.001);
|
System system(0.001);
|
||||||
|
|
||||||
std::vector<Atom> atoms = generateFCCAtoms(5.26, 3);
|
std::vector<Atom> atoms = generateFCCAtoms(5.26, 3, "Ar", 1);
|
||||||
system.addAtom(std::move(atoms));
|
initMaxwellBoltzmannVelocities(atoms, 300);
|
||||||
|
|
||||||
atoms = generateFCCAtoms(5.26, 3);
|
|
||||||
offsetAtoms(atoms, 15, 15, 15);
|
|
||||||
system.addAtom(std::move(atoms));
|
system.addAtom(std::move(atoms));
|
||||||
|
|
||||||
system.printAtoms();
|
system.printAtoms();
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
#include "Atom.hpp"
|
#include "Atom.hpp"
|
||||||
|
|
||||||
void printAtom(Atom atom) {
|
void printAtom(Atom atom) {
|
||||||
std::cout << "Atom(" << atom.x << ", " << atom.y << ", " << atom.z << ")" << std::endl;
|
// Print an atom in XYZ format with extra information
|
||||||
|
std::cout << atom.name << " " << atom.x << " " << atom.y << " " << atom.z << " " << atom.vx << " "
|
||||||
|
<< atom.vy << " " << atom.vz << " " << atom.m << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAtoms(std::vector<Atom> atoms) {
|
void printAtoms(std::vector<Atom> atoms) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,11 +20,13 @@
|
|||||||
*/
|
*/
|
||||||
class Atom {
|
class Atom {
|
||||||
public:
|
public:
|
||||||
double x, y, z; ///< Positions
|
double x, y, z; ///< Positions
|
||||||
double vx, vy, vz; ///< Velocities
|
double vx, vy, vz; ///< Velocities
|
||||||
double m; ///< Mass
|
double m = 1; ///< Mass
|
||||||
|
std::string name = ""; ///< Name
|
||||||
|
|
||||||
Atom(double x, double y, double z) : x(x), y(y), z(z), vx(0), vy(0), vz(0), m(1) {
|
Atom(double x, double y, double z, std::string name, double mass)
|
||||||
|
: x(x), y(y), z(z), vx(0), vy(0), vz(0), m(mass), name(name) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,18 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "AtomsGenerator.hpp"
|
#include "AtomsGenerator.hpp"
|
||||||
|
|
||||||
std::vector<Atom> generateFCCAtoms(double latticeConstant, std::size_t numberOfCells) {
|
// Private declarations
|
||||||
|
double gaussrand();
|
||||||
|
|
||||||
|
std::vector<Atom> generateFCCAtoms(double latticeConstant,
|
||||||
|
std::size_t numberOfCells,
|
||||||
|
std::string element,
|
||||||
|
double mass) {
|
||||||
// Check for invalid lattice constants
|
// Check for invalid lattice constants
|
||||||
if (latticeConstant <= 0)
|
if (latticeConstant <= 0)
|
||||||
throw std::invalid_argument("Lattice constant must be positive");
|
throw std::invalid_argument("Lattice constant must be positive");
|
||||||
@@ -24,13 +31,23 @@ std::vector<Atom> generateFCCAtoms(double latticeConstant, std::size_t numberOfC
|
|||||||
for (std::size_t i = 0; i < numberOfCells; i++)
|
for (std::size_t i = 0; i < numberOfCells; i++)
|
||||||
for (std::size_t j = 0; j < numberOfCells; j++)
|
for (std::size_t j = 0; j < numberOfCells; j++)
|
||||||
for (std::size_t k = 0; k < numberOfCells; k++) {
|
for (std::size_t k = 0; k < numberOfCells; k++) {
|
||||||
atoms.push_back(Atom(i * latticeConstant, j * latticeConstant, k * latticeConstant));
|
|
||||||
atoms.push_back(
|
atoms.push_back(
|
||||||
Atom((i + 0.5) * latticeConstant, (j + 0.5) * latticeConstant, k * latticeConstant));
|
Atom(i * latticeConstant, j * latticeConstant, k * latticeConstant, element, mass));
|
||||||
atoms.push_back(
|
atoms.push_back(Atom((i + 0.5) * latticeConstant,
|
||||||
Atom((i + 0.5) * latticeConstant, j * latticeConstant, (k + 0.5) * latticeConstant));
|
(j + 0.5) * latticeConstant,
|
||||||
atoms.push_back(
|
k * latticeConstant,
|
||||||
Atom(i * latticeConstant, (j + 0.5) * latticeConstant, (k + 0.5) * latticeConstant));
|
element,
|
||||||
|
mass));
|
||||||
|
atoms.push_back(Atom((i + 0.5) * latticeConstant,
|
||||||
|
j * latticeConstant,
|
||||||
|
(k + 0.5) * latticeConstant,
|
||||||
|
element,
|
||||||
|
mass));
|
||||||
|
atoms.push_back(Atom(i * latticeConstant,
|
||||||
|
(j + 0.5) * latticeConstant,
|
||||||
|
(k + 0.5) * latticeConstant,
|
||||||
|
element,
|
||||||
|
mass));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use std::move to move the vector to the caller
|
// Use std::move to move the vector to the caller
|
||||||
@@ -44,3 +61,51 @@ void offsetAtoms(std::vector<Atom> &atoms, double x, double y, double z) {
|
|||||||
atom.z += z;
|
atom.z += z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initMaxwellBoltzmannVelocities(std::vector<Atom> &atoms, double temperature) {
|
||||||
|
// Check for invalid temperature
|
||||||
|
if (temperature <= 0)
|
||||||
|
throw std::invalid_argument("Temperature must be positive");
|
||||||
|
|
||||||
|
double vx_sum = 0, vy_sum = 0, vz_sum = 0;
|
||||||
|
|
||||||
|
// Initialize random velocities according to the Maxwell-Boltzmann distribution
|
||||||
|
for (auto &atom : atoms) {
|
||||||
|
atom.vx = gaussrand() * sqrt(temperature / atom.m);
|
||||||
|
atom.vy = gaussrand() * sqrt(temperature / atom.m);
|
||||||
|
atom.vz = gaussrand() * sqrt(temperature / atom.m);
|
||||||
|
vx_sum += atom.vx;
|
||||||
|
vy_sum += atom.vy;
|
||||||
|
vz_sum += atom.vz;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the average velocity
|
||||||
|
vx_sum /= atoms.size();
|
||||||
|
vy_sum /= atoms.size();
|
||||||
|
vz_sum /= atoms.size();
|
||||||
|
|
||||||
|
// Set the average velocity to zero
|
||||||
|
for (auto &atom : atoms) {
|
||||||
|
atom.vx -= vx_sum;
|
||||||
|
atom.vy -= vy_sum;
|
||||||
|
atom.vz -= vz_sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double gaussrand() {
|
||||||
|
static double U, V;
|
||||||
|
static int phase = 0;
|
||||||
|
double Z;
|
||||||
|
|
||||||
|
if (phase == 0) {
|
||||||
|
double u = (rand() + 1.0) / (RAND_MAX + 2.0);
|
||||||
|
double v = rand() / (RAND_MAX + 1.0);
|
||||||
|
Z = sqrt(-2.0 * log(u)) * sin(2.0 * M_PI * v);
|
||||||
|
} else {
|
||||||
|
Z = sqrt(-2.0 * log(U)) * cos(2.0 * M_PI * V);
|
||||||
|
}
|
||||||
|
|
||||||
|
phase = 1 - phase;
|
||||||
|
|
||||||
|
return Z;
|
||||||
|
}
|
||||||
@@ -22,7 +22,18 @@
|
|||||||
* @param numberOfCells
|
* @param numberOfCells
|
||||||
* @return std::vector<Atom>
|
* @return std::vector<Atom>
|
||||||
*/
|
*/
|
||||||
std::vector<Atom> generateFCCAtoms(double latticeConstant, std::size_t numberOfCells);
|
std::vector<Atom> generateFCCAtoms(double latticeConstant,
|
||||||
|
std::size_t numberOfCells,
|
||||||
|
std::string element,
|
||||||
|
double mass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize random velocities according to the Maxwell-Boltzmann distribution
|
||||||
|
*
|
||||||
|
* @param atoms
|
||||||
|
* @param temperature
|
||||||
|
*/
|
||||||
|
void initMaxwellBoltzmannVelocities(std::vector<Atom> &atoms, double temperature);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilitary functions
|
* Utilitary functions
|
||||||
|
|||||||
@@ -9,14 +9,35 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "System.hpp"
|
#include "System.hpp"
|
||||||
|
|
||||||
System::System(double timeDelta) : timeDelta(timeDelta) {
|
System::System(double timeDelta,
|
||||||
|
double rcut,
|
||||||
|
PotentialFunction potentialFunction,
|
||||||
|
ForceFunction forceFunction,
|
||||||
|
std::size_t tableResolution)
|
||||||
|
: timeDelta(timeDelta), rcut(rcut), rcut2(rcut * rcut), potentialGenerator(potentialFunction),
|
||||||
|
forceGenerator(forceFunction), tableResolution(tableResolution) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::initForceTable() {
|
void System::initTables() {
|
||||||
|
// Generate the force table based on squared distance
|
||||||
|
double dr = this->rcut2 / this->tableResolution;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < this->tableResolution; i++) {
|
||||||
|
double r2 = i * dr;
|
||||||
|
this->forceTable.push_back(this->forceGenerator(sqrt(r2)));
|
||||||
|
this->potentialTable.push_back(this->potentialGenerator(sqrt(r2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::stepFirst() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::evaulateForces() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::addAtom(Atom atom) {
|
void System::addAtom(Atom atom) {
|
||||||
|
|||||||
@@ -11,33 +11,58 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Atom.hpp"
|
#include "Atom.hpp"
|
||||||
|
|
||||||
|
typedef std::function<double(double)> PotentialFunction;
|
||||||
|
typedef std::function<double(double)> ForceFunction;
|
||||||
|
|
||||||
class System {
|
class System {
|
||||||
private:
|
private:
|
||||||
std::vector<Atom> atoms; ///< Atoms in the system
|
std::vector<Atom> atoms; ///< Atoms in the system
|
||||||
std::vector<Atom> atomsOld; ///< Atoms in the system in the previous step
|
std::vector<Atom> atomsOld; ///< Atoms in the system in the previous step
|
||||||
|
|
||||||
|
std::vector<double> forceTable; ///< Force table
|
||||||
|
std::vector<double> forceTableOld; ///< Force table in the previous step
|
||||||
|
std::vector<double> potentialTable; ///< Potential table
|
||||||
|
|
||||||
|
ForceFunction forceGenerator; ///< Force generator
|
||||||
|
PotentialFunction potentialGenerator; ///< Potential generator
|
||||||
|
|
||||||
|
double rcut; ///< Cutoff radius
|
||||||
|
double rcut2; ///< Cutoff radius squared
|
||||||
|
|
||||||
|
std::size_t tableResolution = 1000; ///< Resolution of the force table
|
||||||
|
|
||||||
double timeDelta = 0; ///< Time delta between steps
|
double timeDelta = 0; ///< Time delta between steps
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize the force table
|
* @brief Initialize the force and potential tables
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void initForceTable();
|
void initTables();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize the potential table
|
* @brief Evaluate interaction forces between atoms
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void initPotentialTable();
|
void evaulateForces();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit System(double timeDelta);
|
explicit System(double timeDelta,
|
||||||
|
double rcut,
|
||||||
|
PotentialFunction potentialFunction,
|
||||||
|
ForceFunction forceFunction,
|
||||||
|
std::size_t tableResolution = 1000);
|
||||||
|
|
||||||
void step();
|
void step();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Step the system to the first step using euler method
|
||||||
|
*
|
||||||
|
*/
|
||||||
void stepFirst();
|
void stepFirst();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user