The Computer Language
24.11 Benchmarks Game

n-body PHP #8 program

source code

<? /* The Computer Language Benchmarks Game
   https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
   
   Naive transliteration from bearophile's program 
   contributed by Isaac Gouy   
*/

const PI = 3.14159265358979323;
const SOLAR_MASS = 4 * PI * PI;
const DAYS_PER_YEAR = 365.24;

final class Body {
   var $x, $y, $z, $vx, $vy, $vz, $mass = 0.0;

   public function __construct($x, $y, $z, $vx, $vy, $vz, $mass) {
      $this->x = $x;
      $this->y = $y;
      $this->z = $z;
      $this->vx = $vx;
      $this->vy = $vy;
      $this->vz = $vz;
      $this->mass = $mass;
   }    
}

function offsetMomentum(&$bodies) { 
    $px = $py = $pz = 0.0;
    foreach ($bodies as $b) {
        $px += $b->vx * $b->mass;
        $py += $b->vy * $b->mass;
        $pz += $b->vz * $b->mass;
    }
    $b = $bodies[0];
    $b->vx = -$px / SOLAR_MASS;
    $b->vy = -$py / SOLAR_MASS;
    $b->vz = -$pz / SOLAR_MASS;
}

function energy(&$bodies) {
    $e = 0.0;
    $numBodies = count($bodies);
    for ($i = 0; $i < $numBodies; $i++) {
        $b = $bodies[$i];
        $sq = $b->vx * $b->vx + $b->vy * $b->vy + $b->vz * $b->vz;    
        $e += 0.5 * $bodies[$i]->mass * $sq;
        for ($j = $i + 1; $j < $numBodies; $j++) {
            $dx = $b->x - $bodies[$j]->x; 
            $dy = $b->y - $bodies[$j]->y; 
            $dz = $b->z - $bodies[$j]->z;   
            $sq = $dx * $dx + $dy * $dy + $dz * $dz;          
            $e -= ($b->mass * $bodies[$j]->mass) / sqrt($sq);        
        }
    }
    return $e;
}

function advance(&$bodies, $dt) {
    $numBodies = count($bodies);
    for ($i = 0; $i < $numBodies; $i++) {
        for ($j = $i + 1; $j < $numBodies; $j++) {
            $dx = $bodies[$i]->x - $bodies[$j]->x; 
            $dy = $bodies[$i]->y - $bodies[$j]->y; 
            $dz = $bodies[$i]->z - $bodies[$j]->z;          
            $sq = $dx * $dx + $dy * $dy + $dz * $dz;
            $mag = $dt / ($sq * sqrt($sq));           

            $mj = $bodies[$j]->mass * $mag;
            $bodies[$i]->vx -= $dx * $mj;  
            $bodies[$i]->vy -= $dy * $mj;   
            $bodies[$i]->vz -= $dz * $mj;

            $mi = $bodies[$i]->mass * $mag;
            $bodies[$j]->vx += $dx * $mi;  
            $bodies[$j]->vy += $dy * $mi;   
            $bodies[$j]->vz += $dz * $mi;
        }
    }
    foreach ($bodies as $b) {    
        $b->x += $b->vx * $dt;  
        $b->y += $b->vy * $dt;   
        $b->z += $b->vz * $dt;
    }
}

function nbody ($n) { 
    $bodies = [
        // sun 
        new Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS),
   
        // jupiter            
        new Body(
            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
        ),   
        
        // saturn            
        new Body(
            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        
        ),        
        
        // uranus            
        new Body(
            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                
        ),   
        
        // neptune            
        new Body(        
            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         
        ),          
    ];   

    offsetMomentum($bodies); 
    printf("%0.9f\n", energy($bodies)); 
    for ($i = 0; $i < $n; $i++) {
        advance($bodies,0.01);
    }    
    printf("%0.9f\n", energy($bodies));    
}

$n = $argc > 1 ? $argv[1] : 1000;
nbody($n);

?>
    

notes, command-line, and program output

NOTES:
64-bit Ubuntu quad core
PHP 8.4.1 (cli)
(built: Nov 22 2024 14:22:47) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.4.1,
with Zend OPcache v8.4.1,
Copyright (c) Zend Technologies


 Sat, 23 Nov 2024 05:08:57 GMT

COMMAND LINE:
 /opt/src/php-8.4.1/bin/php -dzend_extension=/opt/src/php-8.4.1/lib/php/extensions/no-debug-non-zts-20240924/opcache.so -dopcache.enable_cli=1 -dopcache.jit_buffer_size=64M -n  nbody.php-8.php 50000000

PROGRAM OUTPUT:
-0.169075164
-0.169059907