// InitPositionFCC initializes particle positions in a face-centered cubic configuration func InitPositionFCC(N int, L float64) [][3]float64 { R := make([][3]float64, N) Ncube := 1 for N > 4*Ncube*Ncube*Ncube { Ncube++ } o := -L / 2 origin := [3]float64{o, o, o} rs := L / float64(Ncube) roffset := rs / 2 i := 0 for x := 0; x < Ncube; x++ { x := float64(x) for y := 0; y < Ncube; y++ { y := float64(y) for z := 0; z < Ncube; z++ { z := float64(z) pos := vector.Scale([3]float64{x, y, z}, rs) pos = vector.Sum(pos, origin) R[i] = pos i++ R[i] = vector.Sum(pos, [3]float64{roffset, roffset, 0}) i++ R[i] = vector.Sum(pos, [3]float64{roffset, 0, roffset}) i++ R[i] = vector.Sum(pos, [3]float64{0, roffset, roffset}) i++ } } } return R }
// InternalForceParallel does the same as InternalForce but with channels func InternalForceParallel(i int, R [][3]float64, L float64, c chan ForceReturn) { F := [3]float64{0, 0, 0} for j := range R { if i != j { F = vector.Sum(F, PairwiseLennardJonesForce(R[i], R[j], L)) } } c <- ForceReturn{i, F} }
// InternalForce calculates the total force vector on particle Ri due to the other particles in R due to a pairwise force. func InternalForce(i int, R [][3]float64, L float64) [3]float64 { F := [3]float64{0, 0, 0} for j := range R { if i != j { F = vector.Sum(F, PairwiseLennardJonesForce(R[i], R[j], L)) } } return F }
// NextR calculates the next position vector based on current position, velocity, and acceleration. func NextR(r, v, a [3]float64, h float64) [3]float64 { return vector.Sum(vector.Sum(r, vector.Scale(v, h)), vector.Scale(a, 0.5*h*h)) }
// NextV calculates the next velocity vector based on current velocity and acceleration and future acceleration. func NextV(v, a1, a2 [3]float64, h float64) [3]float64 { return vector.Sum(v, vector.Scale(vector.Sum(a1, a2), 0.5*h)) }