All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nbody.nbody-4.venice Maven / Gradle / Ivy

There is a newer version: 1.12.34
Show newest version
;;;;   __    __         _
;;;;   \ \  / /__ _ __ (_) ___ ___
;;;;    \ \/ / _ \ '_ \| |/ __/ _ \
;;;;     \  /  __/ | | | | (_|  __/
;;;;      \/ \___|_| |_|_|\___\___|
;;;;
;;;;
;;;; Copyright 2017-2024 Venice
;;;;
;;;; Licensed under the Apache License, Version 2.0 (the "License");
;;;; you may not use this file except in compliance with the License.
;;;; You may obtain a copy of the License at
;;;;
;;;;     http://www.apache.org/licenses/LICENSE-2.0
;;;;
;;;; Unless required by applicable law or agreed to in writing, software
;;;; distributed under the License is distributed on an "AS IS" BASIS,
;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;;; See the License for the specific language governing permissions and
;;;; limitations under the License.

;;;; N-body: https://benchmarksgame-team.pages.debian.net/benchmarksgame/


(ns nbody)

(def PI 3.141592653589793)
(def SOLAR_MASS (* 4.0 PI PI))
(def DAYS_PER_YEAR 365.24)

(defn body [name x y z vx vy vz mass]
  (mutable-map :name name
               :x x
               :y y
               :z z
               :vx vx
               :vy vy
               :vz vz
               :mass mass))


(def sun (body "sun"
                0.0
                0.0
                0.0
                0.0
                0.0
                0.0
                SOLAR_MASS))

(def jupiter (body "jupiter"
                   4.84143144246472090e+00
                   -1.16032004402742839e+00
                   -1.03622044471123109e-01
                   (* 1.66007664274403694e-03  DAYS_PER_YEAR)
                   (* 7.69901118419740425e-03  DAYS_PER_YEAR)
                   (* -6.90460016972063023e-05 DAYS_PER_YEAR)
                   (* 9.54791938424326609e-04  SOLAR_MASS)))

(def saturn (body  "saturn"
                   8.34336671824457987e+00
                   4.12479856412430479e+00
                   -4.03523417114321381e-01
                   (* -2.76742510726862411e-03 DAYS_PER_YEAR)
                   (* 4.99852801234917238e-03  DAYS_PER_YEAR)
                   (* 2.30417297573763929e-05  DAYS_PER_YEAR)
                   (* 2.85885980666130812e-04  SOLAR_MASS)))

(def uranus (body  "uranus"
                   1.28943695621391310e+01
                   -1.51111514016986312e+01
                   -2.23307578892655734e-01
                   (* 2.96460137564761618e-03  DAYS_PER_YEAR)
                   (* 2.37847173959480950e-03  DAYS_PER_YEAR)
                   (* -2.96589568540237556e-05 DAYS_PER_YEAR)
                   (* 4.36624404335156298e-05  SOLAR_MASS)))

(def neptune (body "neptune"
                   1.53796971148509165e+01
                   -2.59193146099879641e+01
                   1.79258772950371181e-01
                   (* 2.68067772490389322e-03  DAYS_PER_YEAR)
                   (* 1.62824170038242295e-03  DAYS_PER_YEAR)
                   (* -9.51592254519715870e-05 DAYS_PER_YEAR)
                   (* 5.15138902046611451e-05  SOLAR_MASS)))

(def system (mutable-vector sun jupiter saturn uranus neptune))

(def body-pairs (combinations system 2))


(defn run [iterations]
  ;; 100'000 runs     complex types:              43s
  ;;                  hash maps for bodies:       23s
  ;;                  mutable types:              16s
  ;;                  (get :x y) for (:x y):      12s
  ;;                  qualified core symbols:     10s
  ;; Energy (start):  -0.1690751638285245
  ;; Energy (end):    -0.1690798593916589
  (init! system)
  (println "Energy: "(energy system))
  (dorun iterations (advance! system 0.01))
  (println "Energy: "(energy system)))


(defn init! [bodies]
  (let [px   (reduce #(+ %1 (* (get %2 :vx) (get %2 :mass))) 0.0 bodies)
        py   (reduce #(+ %1 (* (get %2 :vy) (get %2 :mass))) 0.0 bodies)
        pz   (reduce #(+ %1 (* (get %2 :vz) (get %2 :mass))) 0.0 bodies)
        sun  (first bodies)]
    (offset-momentum! sun px py pz)
    nil))


(defn energy [bodies]
  (let [e+  (reduce #(+ %1 (kinetic-energy %2))
                    0.0
                    bodies)
        e-  (reduce #(+ %1 (gravitational-energy (first %2) (second %2)))
                    0.0
                    body-pairs)]
  (- e+ e-)))


(defn advance! [bodies dt]
  (map #(advance-velocity! (first %) (second %) dt) body-pairs)
  (map #(advance-movement! % dt) bodies)
  nil)


(defn advance-velocity! [b1 b2 dt]
  (let [dx       (core/- (core/get b1 :x) (core/get b2 :x))
        dy       (core/- (core/get b1 :y) (core/get b2 :y))
        dz       (core/- (core/get b1 :z) (core/get b2 :z))
        dsquared (core/+ (core/square dx) (core/square dy) (core/square dz))
        distance (core/sqrt dsquared)
        mag      (core// dt dsquared distance)
        b1-mass  (core/get b1 :mass)
        b2-mass  (core/get b2 :mass)]
    (core/assoc! b1 :vx (core/- (core/get b1 :vx) (core/* dx b2-mass mag))
                    :vy (core/- (core/get b1 :vy) (core/* dy b2-mass mag))
                    :vz (core/- (core/get b1 :vz) (core/* dz b2-mass mag)))
    (core/assoc! b2 :vx (core/+ (core/get b2 :vx) (core/* dx b1-mass mag))
                    :vy (core/+ (core/get b2 :vy) (core/* dy b1-mass mag))
                    :vz (core/+ (core/get b2 :vz) (core/* dz b1-mass mag)))
    nil))


(defn advance-movement! [body dt]
  (core/assoc! body :x (core/+ (core/get body :x) (core/* dt (core/get body :vx)))
                    :y (core/+ (core/get body :y) (core/* dt (core/get body :vy)))
                    :z (core/+ (core/get body :z) (core/* dt (core/get body :vz))))
  nil)


(defn offset-momentum! [body px py pz]
  (let [mass (:mass body)]
    (assoc! body :vx (/ (negate px) mass)
                 :vy (/ (negate py) mass)
                 :vz (/ (negate pz) mass))
    nil))


(defn distance [b1 b2]
  (let [dx  (- (get b1 :x) (get b2 :x))
        dy  (- (get b1 :y) (get b2 :y))
        dz  (- (get b1 :z) (get b2 :z))]
      (sqrt (+ (square dx) (square dy) (square dz)))))


(defn kinetic-energy [body]
  (* 0.5
     (:mass body)
     (+ (square (get body :vx))
        (square (get body :vy))
        (square (get body :vz)))))


(defn gravitational-energy [body1 body2]
  (let [dx       (- (get body1 :x) (get body2 :x))
        dy       (- (get body1 :y) (get body2 :y))
        dz       (- (get body1 :z) (get body2 :z))
        distance (sqrt (+ (square dx) (square dy) (square dz)))]
    (/ (* (get body1 :mass) (get body2 :mass))
       distance)))




© 2015 - 2024 Weber Informatics LLC | Privacy Policy