<?php
/*
Main
© Charles Chandler
http://qdl.scs-inc.us/?top=12541
*/
/*
This simulates the collapse of 57 Debye cells.
http://127.0.0.1/SCS/Other/QuickDisclosure/2ndParty/Images/Charles/Plasmas/Collapse.php
*/
include('Functions.php');
@set_time_limit(0); // so we don't time-out after 30 seconds
define('e', 1.60217657 * pow(10, -19)); // elementary charge, in coulombs
define('p', 1.67262178 * pow(10, -27)); // mass of proton, in kilograms
define('neutralsPerIon', pow(10, 16)); // degree of ionization
$nucMass = 150 * neutralsPerIon * p; // charge-to-mass ratio for Debye nuclei
$ionMass = neutralsPerIon * p; // charge-to-mass ratio for Debye ions
$includes = DirList('Points');
$fileToInclude = end($includes);
echo $fileToInclude.'<br /><br />';
if (!$fileToInclude) {
// If we don't already have the first full $points array, we generate it from text files
// that we created using another program. The first is DebyeCellPoints.txt, which is an
// arrangement of 150 points around a center. The second is ClosestPackedCenters.txt, which
// is an arrangement of centers in an HCP closest packed arrangement. Those will be the
// negative nuclei, around which there will be 150 positive ions.
$ions = array();
foreach(explode("\r", trim(file_get_contents('DebyeCellPoints.txt'))) as $line) {
list($x, $y, $z) = explode(chr(9), $line);
$pt = Pt($x, $y, $z);
$pt['r'] = sqrt(($x * $x) + ($y * $y) + ($z * $z));
$ions[] = $pt;
}
$points = array();
$pinned = array();
$lines = explode("\r", trim(file_get_contents('ClosestPackedCenters.txt')));
for ($i = 0, $arrLen = count($lines); $i < $arrLen; $i++) {
list($x, $y, $z) = explode(chr(9), $lines[$i]);
// Snag the indexes of the two pinned points (4,0,0 and -4,0,0).
$nucIndex = count($points);
if ((abs($x) == 4) and (!$y) and (!$z)) $pinned[] = $nucIndex;
// The file has centers that are spaced 1 m apart, but we want centers that are 10 m apart,
// so we scale up the values. We also add a random factor, so we don't get a simulation
// in a perfectly geometric pattern due to the regularity of the initial condition.
$x = ($x * 10) + Random(-.1, .1);
$y = ($y * 10) + Random(-.1, .1);
$z = ($z * 10) + Random(-.1, .1);
$nucPt = Pt($x, $y, $z);
$nucPt['n'] = $nucIndex;
$nucPt['r'] = 0; // ...so it doesn't have a radius from a nucPt
$points[] = $nucPt;
// For each nucleus, throw in a complete set of ions, shifted from
// their local coordinate system, to being centered on the nucleus.
foreach($ions as $ionPt) {
$pt = Pt(
$ionPt['x'] + $nucPt['x'],
$ionPt['y'] + $nucPt['y'],
$ionPt['z'] + $nucPt['z']
);
$pt['n'] = $nucIndex;
$pt['r'] = $ionPt['r'];
$points[] = $pt;
}
}
$fileToInclude = '000.php';
file_put_array('Points/'.$fileToInclude, 'points');
file_put_array('Pinned.php', 'pinned');
}
include('Points/'.$fileToInclude);
include('Pinned.php');
$fileToExport = lpad(intval(StripOneTailer($fileToInclude, '.php')) + 1, 3, '0').'.php';
$cntPts = count($points);
$shifts = array();
for ($i = 0; $i < $cntPts; $i++) $shifts[] = Pt(0, 0, 0);
//$cntPts = 10;
// This performs 37,035,921 point comparisons per run, and then writes the info into
// the next file in the series, to serve as the initial conditions for the next run.
$begLoop = microtime(true);
for ($i = 0; $i < $cntPts; $i++) {
for ($j = $i + 1; $j < $cntPts; $j++) {
$ptI = $points[$i];
$ptJ = $points[$j];
// If it isn't an ion compared to its own nucleus,
// calculate the force, and set the resultant shift.
if ($ptJ['n'] != $i) {
if ($ptI['r']) { $massI = $ionMass; $charI = 1; } else { $massI = $nucMass; $charI = -150; }
if ($ptJ['r']) { $massJ = $ionMass; $charJ = 1; } else { $massJ = $nucMass; $charJ = -150; }
// Assign the deltas, and find the
// 3D distance from point to point.
$dX = ($ptJ['x'] - $ptI['x']);
$dY = ($ptJ['y'] - $ptI['y']);
$dZ = ($ptJ['z'] - $ptI['z']);
$dist = sqrt(($dX * $dX) + ($dY * $dY) + ($dZ * $dZ));
// Set to 1 to calculate gravity, or to 0 to do the electric force.
// Either way, we scale the force to get the amount that we're
// going to shift things in the drawing due to the force.
if (0) {
$force = Gravity_n($massI, $massJ, $dist);
$shift = $force * pow(10, 24);
} else {
// We subtract the electric force, because it's positive
// for repulsive, and we want positive for attractive,
// so it works the same as the gravity calculations.
$force = -Electricity_n($charI, $charJ, $dist);
$shift = $force * pow(10, 32) * .2857;
}
// Add the vector to the existing value in the shifts array.
// That's assuming that it isn't one of two nuclei that are
// pinned, which are at 4,0,0 and -4,0,0 respectively.
$scaler = $shift / $dist;
$shifts[$ptI['n']]['x'] += ($dX * $scaler);
$shifts[$ptI['n']]['y'] += ($dY * $scaler);
$shifts[$ptI['n']]['z'] += ($dZ * $scaler);
$shifts[$ptJ['n']]['x'] -= ($dX * $scaler);
$shifts[$ptJ['n']]['y'] -= ($dY * $scaler);
$shifts[$ptJ['n']]['z'] -= ($dZ * $scaler);
}
}
}
// Apply the shifts back to the points array.
for ($i = 0; $i < $cntPts; $i++) {
if (!in_array($points[$i]['n'], $pinned)) {
$points[$i]['x'] += $shifts[$points[$i]['n']]['x'];
$points[$i]['y'] += $shifts[$points[$i]['n']]['y'];
$points[$i]['z'] += $shifts[$points[$i]['n']]['z'];
}
}
// Find the maximum that any of the nuclei shifted.
$maxShift = 0;
for ($i = 0; $i < $cntPts; $i++) {
$dX = $shifts[$i]['x'];
$dY = $shifts[$i]['y'];
$dZ = $shifts[$i]['z'];
if (($dX) or ($dY) or ($dZ)) {
$nowShift = sqrt(($dX * $dX) + ($dY * $dY) + ($dZ * $dZ));
$maxShift = max($maxShift, $nowShift);
}
}
$endLoop = microtime(true);
file_put_array('Points/'.$fileToExport, 'points');
echo 'maxShift: '.$maxShift.'<br />';
echo 'runtime: '.round(($endLoop - $begLoop) / 60, 2).' minutes<br />';
echo '<br />';
echo 'done';
?>
|