N-body problem: Difference between revisions
Content added Content deleted
SqrtNegInf (talk | contribs) (Added Perl example) |
(Add Swift) |
||
Line 5,048: | Line 5,048: | ||
Body 2 : 0.426346 -0.111425 -0.681150 | 0.234987 0.006241 -0.440245 |
Body 2 : 0.426346 -0.111425 -0.681150 | 0.234987 0.006241 -0.440245 |
||
Body 3 : -1.006089 -4.103186 -3.122591 | -0.359686 -1.177995 -0.875924</pre> |
Body 3 : -1.006089 -4.103186 -3.122591 | -0.359686 -1.177995 -0.875924</pre> |
||
=={{header|Swift}}== |
|||
<lang swift>import Foundation |
|||
public struct Vector { |
|||
public var px = 0.0 |
|||
public var py = 0.0 |
|||
public var pz = 0.0 |
|||
public init(px: Double, py: Double, pz: Double) { |
|||
(self.px, self.py, self.pz) = (px, py, pz) |
|||
} |
|||
public init?(array: [Double]) { |
|||
guard array.count == 3 else { |
|||
return nil |
|||
} |
|||
(self.px, self.py, self.pz) = (array[0], array[1], array[2]) |
|||
} |
|||
public func mod() -> Double { |
|||
(px * px + py * py + pz * pz).squareRoot() |
|||
} |
|||
static func + (lhs: Vector, rhs: Vector) -> Vector { |
|||
return Vector( |
|||
px: lhs.px + rhs.px, |
|||
py: lhs.py + rhs.py, |
|||
pz: lhs.pz + rhs.pz |
|||
) |
|||
} |
|||
static func - (lhs: Vector, rhs: Vector) -> Vector { |
|||
return Vector( |
|||
px: lhs.px - rhs.px, |
|||
py: lhs.py - rhs.py, |
|||
pz: lhs.pz - rhs.pz |
|||
) |
|||
} |
|||
static func * (lhs: Vector, rhs: Double) -> Vector { |
|||
return Vector( |
|||
px: lhs.px * rhs, |
|||
py: lhs.py * rhs, |
|||
pz: lhs.pz * rhs |
|||
) |
|||
} |
|||
} |
|||
extension Vector { |
|||
public static let origin = Vector(px: 0, py: 0, pz: 0) |
|||
} |
|||
extension Vector: Equatable { |
|||
public static func == (lhs: Vector, rhs: Vector) -> Bool { |
|||
return lhs.px == rhs.px && lhs.py == rhs.py && lhs.pz == rhs.pz |
|||
} |
|||
} |
|||
extension Vector: CustomStringConvertible { |
|||
public var description: String { |
|||
return String(format: "%.6f\t%.6f\t%.6f", px, py, pz) |
|||
} |
|||
} |
|||
public class NBody { |
|||
public let gravitationalConstant: Double |
|||
public let numBodies: Int |
|||
public let timeSteps: Int |
|||
public private(set) var masses: [Double] |
|||
public private(set) var positions: [Vector] |
|||
public private(set) var velocities: [Vector] |
|||
public private(set) var accelerations: [Vector] |
|||
public init?(file: String) { |
|||
guard let data = try? String(contentsOfFile: file) else { |
|||
return nil |
|||
} |
|||
print("Input file:\n\(data)") |
|||
let lines = data.components(separatedBy: "\n").map({ $0.components(separatedBy: " ") }) |
|||
let worldData = lines.first! |
|||
guard worldData.count == 3, |
|||
let gc = Double(worldData[0]), |
|||
let bodies = Int(worldData[1]), |
|||
let timeSteps = Int(worldData[2]) else { |
|||
return nil |
|||
} |
|||
let defaultState = Array(repeating: Vector.origin, count: bodies) |
|||
self.gravitationalConstant = gc |
|||
self.numBodies = bodies |
|||
self.timeSteps = timeSteps |
|||
self.masses = Array(repeating: 0, count: bodies) |
|||
self.positions = defaultState |
|||
self.accelerations = defaultState |
|||
self.velocities = defaultState |
|||
let bodyData = lines.dropFirst().map({ $0.compactMap(Double.init) }) |
|||
guard bodyData.count == bodies * 3 else { |
|||
return nil |
|||
} |
|||
for n in 0..<bodies { |
|||
masses[n] = bodyData[0 + n * 3][0] |
|||
guard let position = Vector(array: bodyData[1 + n * 3]), |
|||
let velocity = Vector(array: bodyData[2 + n * 3]) else { |
|||
return nil |
|||
} |
|||
positions[n] = position |
|||
velocities[n] = velocity |
|||
} |
|||
} |
|||
private func computeAccelerations() { |
|||
for i in 0..<numBodies { |
|||
accelerations[i] = .origin |
|||
for j in 0..<numBodies where i != j { |
|||
let t = gravitationalConstant * masses[j] / pow((positions[i] - positions[j]).mod(), 3) |
|||
accelerations[i] = accelerations[i] + (positions[j] - positions[i]) * t |
|||
} |
|||
} |
|||
} |
|||
private func resolveCollisions() { |
|||
for i in 0..<numBodies { |
|||
for j in 0..<numBodies where positions[i] == positions[j] { |
|||
velocities.swapAt(i, j) |
|||
} |
|||
} |
|||
} |
|||
private func computeVelocities() { |
|||
for i in 0..<numBodies { |
|||
velocities[i] = velocities[i] + accelerations[i] |
|||
} |
|||
} |
|||
private func computePositions() { |
|||
for i in 0..<numBodies { |
|||
positions[i] = positions[i] + velocities[i] + accelerations[i] * 0.5 |
|||
} |
|||
} |
|||
public func printState() { |
|||
for i in 0..<numBodies { |
|||
print("Body \(i + 1): \(positions[i]) | \(velocities[i])") |
|||
} |
|||
} |
|||
public func simulate() { |
|||
computeAccelerations() |
|||
computePositions() |
|||
computeVelocities() |
|||
resolveCollisions() |
|||
} |
|||
} |
|||
guard let sim = NBody(file: "input.txt") else { |
|||
fatalError() |
|||
} |
|||
print() |
|||
print("Body : x y z | vx vy vz") |
|||
for i in 0..<sim.timeSteps { |
|||
print("Step \(i + 1)") |
|||
sim.simulate() |
|||
sim.printState() |
|||
print() |
|||
} |
|||
</lang> |
|||
{{out}} |
|||
<pre style="height: 20em; overflow: auto;">Input file: |
|||
0.01 3 20 |
|||
1 |
|||
0.000000 0.000000 0.000000 |
|||
0.010000 0.000000 0.000000 |
|||
0.100000 |
|||
1.000000 1.000000 0.000000 |
|||
0.000000 0.000000 0.020000 |
|||
0.001000 |
|||
0.000000 1.000000 1.000000 |
|||
0.010000 -0.010000 -0.010000 |
|||
Body : x y z | vx vy vz |
|||
Step 1 |
|||
Body 1: 0.010177 0.000179 0.000002 | 0.010354 0.000357 0.000004 |
|||
Body 2: 0.998230 0.998232 0.020002 | -0.003539 -0.003536 0.020004 |
|||
Body 3: 0.010177 0.988232 0.988055 | 0.010354 -0.013536 -0.013889 |
|||
Step 2 |
|||
Body 1: 0.020709 0.000718 0.000011 | 0.010710 0.000721 0.000014 |
|||
Body 2: 0.992907 0.992896 0.039971 | -0.007109 -0.007138 0.019935 |
|||
Body 3: 0.020717 0.972888 0.972173 | 0.010727 -0.017153 -0.017876 |
|||
Step 3 |
|||
Body 1: 0.031600 0.001625 0.000034 | 0.011072 0.001094 0.000033 |
|||
Body 2: 0.983985 0.983910 0.059834 | -0.010735 -0.010835 0.019790 |
|||
Body 3: 0.031643 0.953868 0.952235 | 0.011125 -0.020886 -0.021999 |
|||
Step 4 |
|||
Body 1: 0.042858 0.002913 0.000081 | 0.011443 0.001481 0.000060 |
|||
Body 2: 0.971393 0.971163 0.079509 | -0.014448 -0.014659 0.019561 |
|||
Body 3: 0.042981 0.931039 0.928087 | 0.011552 -0.024772 -0.026299 |
|||
Step 5 |
|||
Body 1: 0.054492 0.004595 0.000160 | 0.011826 0.001884 0.000097 |
|||
Body 2: 0.955030 0.954509 0.098909 | -0.018278 -0.018649 0.019238 |
|||
Body 3: 0.054766 0.904225 0.899522 | 0.012018 -0.028857 -0.030829 |
|||
Step 6 |
|||
Body 1: 0.066517 0.006691 0.000281 | 0.012224 0.002308 0.000145 |
|||
Body 2: 0.934759 0.933760 0.117931 | -0.022265 -0.022849 0.018806 |
|||
Body 3: 0.067040 0.873197 0.866280 | 0.012530 -0.033199 -0.035655 |
|||
Step 7 |
|||
Body 1: 0.078950 0.009225 0.000456 | 0.012642 0.002759 0.000206 |
|||
Body 2: 0.910400 0.908677 0.136456 | -0.026454 -0.027316 0.018244 |
|||
Body 3: 0.079856 0.837662 0.828023 | 0.013101 -0.037871 -0.040861 |
|||
Step 8 |
|||
Body 1: 0.091815 0.012227 0.000702 | 0.013086 0.003245 0.000284 |
|||
Body 2: 0.881722 0.878958 0.154340 | -0.030902 -0.032122 0.017523 |
|||
Body 3: 0.093281 0.797239 0.784313 | 0.013749 -0.042975 -0.046559 |
|||
Step 9 |
|||
Body 1: 0.105140 0.015737 0.001035 | 0.013564 0.003775 0.000383 |
|||
Body 2: 0.848429 0.844216 0.171401 | -0.035684 -0.037362 0.016600 |
|||
Body 3: 0.107405 0.751427 0.734579 | 0.014498 -0.048649 -0.052908 |
|||
Step 10 |
|||
Body 1: 0.118964 0.019805 0.001481 | 0.014085 0.004362 0.000509 |
|||
Body 2: 0.810137 0.803953 0.187408 | -0.040900 -0.043166 0.015414 |
|||
Body 3: 0.122346 0.699554 0.678056 | 0.015384 -0.055097 -0.060138 |
|||
Step 11 |
|||
Body 1: 0.133337 0.024498 0.002071 | 0.014662 0.005025 0.000672 |
|||
Body 2: 0.766343 0.757509 0.202050 | -0.046687 -0.049720 0.013868 |
|||
Body 3: 0.138268 0.640690 0.613685 | 0.016460 -0.062633 -0.068603 |
|||
Step 12 |
|||
Body 1: 0.148327 0.029907 0.002851 | 0.015317 0.005792 0.000888 |
|||
Body 2: 0.716377 0.703998 0.214889 | -0.053246 -0.057302 0.011810 |
|||
Body 3: 0.155406 0.573482 0.539941 | 0.017816 -0.071782 -0.078886 |
|||
Step 13 |
|||
Body 1: 0.164025 0.036157 0.003887 | 0.016079 0.006709 0.001184 |
|||
Body 2: 0.659310 0.642172 0.225282 | -0.060887 -0.066351 0.008976 |
|||
Body 3: 0.174112 0.495836 0.454475 | 0.019596 -0.083511 -0.092045 |
|||
Step 14 |
|||
Body 1: 0.180564 0.043437 0.005286 | 0.017000 0.007852 0.001613 |
|||
Body 2: 0.593807 0.570186 0.232208 | -0.070119 -0.077621 0.004875 |
|||
Body 3: 0.194929 0.404136 0.353320 | 0.022038 -0.099890 -0.110265 |
|||
Step 15 |
|||
Body 1: 0.198150 0.052049 0.007234 | 0.018171 0.009372 0.002283 |
|||
Body 2: 0.517817 0.485100 0.233878 | -0.081861 -0.092550 -0.001535 |
|||
Body 3: 0.218605 0.290860 0.228583 | 0.025314 -0.126661 -0.139210 |
|||
Step 16 |
|||
Body 1: 0.217126 0.062542 0.010117 | 0.019781 0.011614 0.003484 |
|||
Body 2: 0.427899 0.381659 0.226654 | -0.097974 -0.114332 -0.012913 |
|||
Body 3: 0.244268 0.131956 0.057562 | 0.026013 -0.191148 -0.202831 |
|||
Step 17 |
|||
Body 1: 0.238346 0.076539 0.015221 | 0.022658 0.016380 0.006723 |
|||
Body 2: 0.317489 0.248502 0.200967 | -0.122846 -0.151982 -0.038461 |
|||
Body 3: 0.075592 -0.559591 -0.487315 | -0.363366 -1.191945 -0.886924 |
|||
Step 18 |
|||
Body 1: 0.263123 0.097523 0.026918 | 0.026898 0.025587 0.016672 |
|||
Body 2: 0.173428 0.050424 0.112716 | -0.165275 -0.244174 -0.138041 |
|||
Body 3: -0.286241 -1.745597 -1.369528 | -0.360299 -1.180066 -0.877501 |
|||
Step 19 |
|||
Body 1: 0.270854 0.113045 0.061923 | -0.011436 0.005457 0.053339 |
|||
Body 2: 0.199821 -0.093105 -0.208666 | 0.218061 -0.042882 -0.504723 |
|||
Body 3: -0.646318 -2.924909 -2.246453 | -0.359856 -1.178559 -0.876350 |
|||
Step 20 |
|||
Body 1: 0.258572 0.116046 0.112038 | -0.013129 0.000544 0.046890 |
|||
Body 2: 0.426346 -0.111425 -0.681150 | 0.234987 0.006241 -0.440245 |
|||
Body 3: -1.006089 -4.103186 -3.122591 | -0.359686 -1.177995 -0.875924 |
|||
Process finished with exit code 0 |
|||
</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |