20111228

Fun with Python: Simulating Baseball Pitches using 4th Order Runge-Kutta Method

Here is a description of the problem in PDF format. Basically this code simulates four different baseball pitches (slider, curve, fastball, screwball) by solving differential equations using the 4th order Runge-Kutta method.


#!/opt/local/bin/python
#Andrew Samuels
#baseball.py

from scipy import *
from pdb import *


#create arrays
dt = 1e-4
nMAX = int(1/dt)

x = zeros(nMAX)
y = zeros(nMAX)
z = zeros(nMAX)
vx = zeros(nMAX)
vy = zeros(nMAX)
vz = zeros(nMAX)
v = zeros(nMAX)


#constants
B = 4.1e-4 #magnus force (dimensionless)
w = 1800/60.0 * 2*pi #rotaton rate of baseball, 1800 rpm to rad/s
g = 9.81 #acceleration of gravity (m/s^2)
v0_fb = 42.4688 #initial speed of pitch, fastball (m/s)
v0_op = 38.0 #initial speed of pitch, other pitches (m/s)
l = 18.44 #distance from pitcher (m)
T_fb = l/v0_fb #step-length, estimated flight time, fastball
T_op = l/v0_op  #step-length, estimated flight time, other pitches
nT_fb = int(T_fb/dt) #number of iterations for fastball
nT_op = int(T_op/dt) #number of iterations for other pitches
d2r = pi/180 # convert degrees to radians
theta = 1 * d2r # elevation angle of pitch, degrees
phi1 = 225 * d2r #direction of w, relative to z, fastball
phi2 = 45 * d2r #direction of w, relative to z, curveball
phi3 = 0 * d2r #direction of w, relative to z, slider
phi4 = 135 * d2r #direction of w, relative to z, screwball
#drag force constants
c1 = 0.0039
c2 = 0.0058
vd = 35.0 #(m/s)
delta = 5.0 # (m/s)

#initial conditions
x[0] = 0.0
y[0] = 0.0
z[0] = 0.0
vx[0] = v0_fb * cos(theta) 
vy[0] = 0.0
vz[0] = v0_fb * sin(theta)


#pass dx/dt=vx through runkut4
def rk4dx(vx,dt):
    def dxdt(vx):
        dxdt = vx
        return dxdt
    K0 = dt * dxdt(vx)
    K1 = dt * dxdt(vx + K0/2.0)
    K2 = dt * dxdt(vx + K1/2.0)
    K3 = dt * dxdt(vx + K2)
    vxnew = (K0 + 2.0*K1 + 2.0*K2 + K3)/6.0
    return vxnew

#pass dy/dt=vy through runkut4
def rk4dy(vy,dt):
    def dydt(vy):
        dydt = vy
        return dydt
    K0 = dt * dydt(vy)
    K1 = dt * dydt(vy + K0/2.0)
    K2 = dt * dydt(vy + K1/2.0)
    K3 = dt * dydt(vy + K2)
    vynew = (K0 + 2.0*K1 + 2.0*K2 + K3)/6.0
    return vynew
    
#pass dz/dt=vz through runkut4
def rk4dz(vz,dt):
    def dzdt(vz):
        dzdt = vz
        return dzdt
    K0 = dt * dzdt(vz)
    K1 = dt * dzdt(vz + K0/2.0)
    K2 = dt * dzdt(vz + K1/2.0)
    K3 = dt * dzdt(vz + K2)
    vznew = (K0 + 2.0*K1 + 2.0*K2 + K3)/6.0
    return vznew

#solve accelerations with runge kutta 4
def rk4(v,vx,vy,vz,dt,phi):
    def ax(v,vx,vy,vz,phi):
    #drag force function, Fd(v)
        def Fd(v):
            return c1 + (c2/(1.0 + exp((v-vd)/delta)))
        return -Fd(v)*v*vx + B*w*(vz*sin(phi)-vy*cos(phi))
    def ay(v,vx,vy,phi):
    #drag force function, Fd(v)
        def Fd(v):
            return c1 + (c2/(1.0 + exp((v-vd)/delta)))
        return -Fd(v)*v*vy + B*w*vx*cos(phi1)
    def az(v,vx,vz,phi):
    #drag force function, Fd(v)
        def Fd(v):
            return c1 + (c2/(1.0 + exp((v-vd)/delta)))
        return -g*-Fd(v)*v*vz - B*w*vx*sin(phi)
    K0 = dt * ax(v,vx,vy,vz,phi)
    L0 = dt * ay(v,vx,vy,phi)
    M0 = dt * az(v,vx,vz,phi)
    K1 = dt * ax(v + dt/2.0,vx + K0/2.0,vy + L0/2.0,vz + M0/2.0,phi)
    L1 = dt * ay(v + dt/2.0,vx + K0/2.0,vy + L0/2.0,phi)
    M1 = dt * az(v + dt/2.0,vx + K0/2.0,vz + M0/2.0,phi)
    K2 = dt * ax(v + dt/2.0,vx + K1/2.0,vy + L1/2.0,vz + M1/2.0,phi)
    L2 = dt * ay(v + dt/2.0,vx + K1/2.0,vy + L1/2.0,phi)
    M2 = dt * az(v + dt/2.0,vx + K1/2.0,vz + M1/2.0,phi)
    K3 = dt * ax(v + dt,vx + K2,vy + L2,vz + M0,phi)
    L3 = dt * ay(v + dt,vx + K1,vy + L2,phi)
    M3 = dt * az(v + dt,vx + K1,vz + M2,phi)
    axnew = (K0 + 2.0*K1 + 2.0*K2 + K3)/6.0
    aynew = (L0 + 2.0*L1 + 2.0*L2 + L3)/6.0
    aznew = (M0 + 2.0*M1 + 2.0*M2 + M3)/6.0
    return axnew,aynew,aznew


f=open('fastball.dat','w')

#first time step is n + 1
#start loop

for i in range(0,nT_fb):
    v = (vx[i] * vx[i] + vy[i] * vy[i] + vz[i] * vz[i])
    v = (v)**0.5
    print "X: " + str(x[i]) + " , Y: " + str(y[i]) + " , Z: " + str(z[i]) + " ,T: " + str(x[i]/v) +" , V: "+ str(v) + "\n"
    f.write(str(x[i])+'\t'+str(y[i])+'\t'+ str(z[i])+'\t'+str(x[i]/v) + '\t' + str(v) +'\n')
    x[i+1] = x[i] + rk4dx(vx[i],dt) 
    y[i+1] = y[i] + rk4dy(vy[i],dt)
    z[i+1] = z[i] + rk4dz(vz[i],dt)
    vx[i+1] = vx[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi1)[0]
    vy[i+1] = vy[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi1)[1]
    vz[i+1] = vz[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi1)[2]


f.close()
print "Created fastball.dat"

#change initial conditions for the other pitches
vx[0] = v0_op * cos(theta) 
vz[0] = v0_op * sin(theta)

#curveball
h=open('curveball.dat','w')

for i in range(0,nT_op):
    v = (vx[i] * vx[i] + vy[i] * vy[i] + vz[i] * vz[i])
    v = (v)**0.5
    print "X: " + str(x[i]) + " , Y: " + str(y[i]) + " , Z: " + str(z[i]) + " ,T: " + str(x[i]/v) +" , V: "+ str(v) + "\n"
    h.write(str(x[i])+'\t'+str(y[i])+'\t'+ str(z[i])+'\t'+str(x[i]/v) + '\t' + str(v) +'\n')
    x[i+1] = x[i] + rk4dx(vx[i],dt) 
    y[i+1] = y[i] + rk4dy(vy[i],dt)
    z[i+1] = z[i] + rk4dz(vz[i],dt)
    vx[i+1] = vx[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi2)[0]
    vy[i+1] = vy[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi2)[1]
    vz[i+1] = vz[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi2)[2]


h.close()
print "Created curveball.dat"

#slider
j=open('slider.dat','w')

for i in range(0,nT_op):
    v = (vx[i] * vx[i] + vy[i] * vy[i] + vz[i] * vz[i])
    v = (v)**0.5
    print "X: " + str(x[i]) + " , Y: " + str(y[i]) + " , Z: " + str(z[i]) + " ,T: " + str(x[i]/v) +" , V: "+ str(v) + "\n"
    j.write(str(x[i])+'\t'+str(y[i])+'\t'+ str(z[i])+'\t'+str(x[i]/v) + '\t' + str(v) +'\n')
    x[i+1] = x[i] + rk4dx(vx[i],dt) 
    y[i+1] = y[i] + rk4dy(vy[i],dt)
    z[i+1] = z[i] + rk4dz(vz[i],dt)
    vx[i+1] = vx[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi3)[0]
    vy[i+1] = vy[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi3)[1]
    vz[i+1] = vz[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi3)[2]


j.close()
print "Created slider.dat"

#screwball
o=open('screwball.dat','w')

for i in range(0,nT_op):
    v = (vx[i] * vx[i] + vy[i] * vy[i] + vz[i] * vz[i])
    v = (v)**0.5
    print "X: " + str(x[i]) + " , Y: " + str(y[i]) + " , Z: " + str(z[i]) + " ,T: " + str(x[i]/v) +" , V: "+ str(v) + "\n"
    o.write(str(x[i])+'\t'+str(y[i])+'\t'+ str(z[i])+'\t'+str(x[i]/v) + '\t' + str(v) +'\n')
    x[i+1] = x[i] + rk4dx(vx[i],dt) 
    y[i+1] = y[i] + rk4dy(vy[i],dt)
    z[i+1] = z[i] + rk4dz(vz[i],dt)
    vx[i+1] = vx[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi4)[0]
    vy[i+1] = vy[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi4)[1]
    vz[i+1] = vz[i] + rk4(v,vx[i],vy[i],vz[i],dt,phi4)[2]


o.close()
print "Created screwball.dat"

Fun with Python: Electric Field Using Trapezoid Method

Suppose a line of charge is given that lies on the y-axis from y=-10 cm to y=+10 cm. At any point, the electric field can be calculated by the following function:

E_x=(sigma/(4*pi*epsilon_0))*intregral_-10_10(x/((x^2+y^2)^(3/2)))dy

where sigma is the linear charge density.

This python program solves this equation using the trapezoid method for numerical integration and outputs the data into a .dat file.


#Andrew Samuels
#efield.py
#find the electric field for a given function
#Uses the trapezoid method

#import modules
from math import *

#open a data file
dfile = open('efdata.dat','w')

#make some functions
def efunc(x,y):
    return  x/(x**2.+y**2.)**(3/2.)

def efTrap(f,a,b,step=1):
    A = -(f(x,a) + f(x,b))
    S = float(b - a)
    for n in range(step+1):
        y = a + n*S/step
        A += 2*f(x,y)
    return A*float(b-a)/(2*step)

#constant
k = 10.5/1.113e-4 #10.5microC/4*pi*e_0*1e6

#integrate from x=1 to 100 in steps of 5
x=1
while x <= 100 :
    ef = k * efTrap(efunc,-10,10,10000)
    print "x = " + str(x) + " , eField = " + str(ef)
    dfile.write(str(x) + '\t' + str(ef) + '\n')
    x += 5

#close data file
dfile.close()
print "Done! Created efdata.dat"

Fun with Python: Linear Algebra Solver

This program is similar to my Gaussian Elimination script only this time the matrix is solved using Back Substitution, then checked for accuracy using the Sci-Py module.

#Andrew Samuels
#linear equation solver. Does Gauss-Jordon elimination, then back substituion.

from scipy import *
from scipy import linalg
from pdb import *

#function to compute dot product
def dot(a, b):
    return reduce(lambda sum, p: sum + p[0]*p[1], zip(a,b), 0)

matrix = zeros((3,4))
#aug = zeros((3,1))

matrix[0,0] = 1
matrix[0,1] = 1
matrix[0,2] = 1
matrix[0,3] = 0
matrix[1,0] = 1
matrix[1,1] = -2
matrix[1,2] = 2
matrix[1,3] = 4
matrix[2,0] = 1
matrix[2,1] = 2
matrix[2,2] = -1
matrix[2,3] = -1


pivot = 0
ncols = 4
nrows = 3


#for all pivots
for col in range(ncols-1):
    #divide pivot by itself to make it 1
    matrix[pivot,:] = matrix[pivot,:]/matrix[pivot,pivot]
   
    #for all pivots that haven't been done yet
    for row in range(pivot+1,nrows):
        matrix[row,:] = matrix[row,:] - matrix[pivot,:]
    pivot = pivot + 1

print " "
print "Row Echelon Form: "   
print matrix 
print "\n"

#solve the matrix and print solution
for pivot in range(nrows-1,-1,-1):
    matrix[pivot] = (matrix[pivot] - dot(matrix[pivot,pivot+1:nrows],matrix[pivot+1:nrows]))/matrix[pivot,pivot]
print "Solved by Back Subst.: "
print matrix 
print "\n"  

#check with scipy
a = array([[1,1,1],[1,-2,2],[1,2,-1]])
b = array([[0],[4],[-1]])
sol = linalg.solve(a,b)
print "Solved by Scipy (check): "
print sol
print "\n"

Fun with Python: Gaussian Elimination

Here is my python program that does Gaussian Elimination on a 3 x 4 matrix. Of course, there are existing modules with functions that could do this automatically, but this was a good learning exercise doing it the hard way.

#Andrew Samuels
#Gaussian Elimination
#performs gaussian elimination on a 3 by 4 matrix

#import scipy module
from scipy import *
from pdb import *

#construct the matrix
matrix = zeros((3,4))

matrix[0,0] = 1
matrix[0,1] = 1
matrix[0,2] = 1
matrix[0,3] = 0
matrix[1,0] = 1
matrix[1,1] = -2
matrix[1,2] = 2
matrix[1,3] = 4
matrix[2,0] = 1
matrix[2,1] = 2
matrix[2,2] = -1
matrix[2,3] = -1


pivot = 0
ncols = 4
nrows = 3

#for all pivots
for col in range(ncols-1):
    #divide pivot by itself to make it 1
    matrix[pivot,:] = matrix[pivot,:]/matrix[pivot,pivot]
   
    #for all pivots that haven't been done yet
    for row in range(pivot+1,nrows):
        matrix[row,:] = matrix[row,:] - matrix[pivot,:]
    pivot = pivot + 1
   

print matrix

Fun with Python: Factorial Calculator

This program written in python calculates a factorial when given an integer. The program will complain if you don't give it a valid integer, such as a letter or dollar sign.

#Andrew Samuels
#factorial calculator
#Fall 2011
#calculates a factorial from integer input from user

n = raw_input('Enter an integer: ')
try:
    n=int(n)
except:
    print 'Enter a valid integer, dummy!'
    exit(1)

f=1
while n > 1 :
    f = f * n
    n = n - 1
    print f

20110819

Towards a 27 Day Prediction of Ionospheric and Thermospheric Space Weather

    In March of 2011, during my winter semester at Eastern Michigan University Department of Physics & Astronomy, I had the honor of writing a proposal for a research scholarship program award with my computational physics professor, Dr. Dave Pawlowski.  The proposal was for the University Research Stimulus Program (URSP) at EMU. The objective of this award was to facilitate research partnerships between undergraduate students and Eastern Michigan University faculty along with a reward of scholarship for the undergraduate.

  Shortly after submitting my proposal, I had received confirmation that I had in fact been granted the URSP award. During the months of April through August 2011, I had been working daily as an undergraduate research assistant under the direction of Dr. Pawlowski. This research was my first plunge into the discipline of computational physics. Over this time period I had gained experience in the subject and performed the following:

• Running computer simulations of Earth’s upper atmosphere based on observations of the sun. Creating a probabilistic forecast for space weather.
• Programmed software scripts using IDL and FORTRAN
• Completed NASA’s Information Security Training, granted access to NASA’s Pleiades supercomputer.
• Parallel computing protocol with Message Passing Interface (MPI)

This post is the contents of a research poster I had put together for a presentation I had made to three groups of visiting 7th and 8th graders, fellow science undergraduates and faculty. You may also download my poster in PDF format here.
 
Abstract
  The prospect of what we can do to increase the knowledge of space weather is promising. One of the practical reasons for doing so is the fact that perturbations in density and temperature in the upper atmosphere can have a significant effect on satellites and instrumentation in low orbit of Earth.  By utilizing ensembles of simulations or ensembles that are based on the uncertainty of the system drivers,  we can run computer simulations to help us make probabilistic forecasts about space weather. In this study, we prepared an ensemble simulation based on uncertainties in the solar extreme ultraviolet (EUV) flux. Then, using the Global Ionosphere-Thermosphere Model (GITM) we ran simulations simultaneously using these ensembles, and analyzed the results.

Introduction
Space weather

the conditions in Earth’s upper atmosphere (ionosphere and thermosphere) in response to changing conditions on the sun. 


Why do we scarcely hear meteorologists in our local news reports making predictions about space weather?  

The overarching reasons:

Society at large generally doesn’t know that space weather affects expensive infrastructure we use daily (e.g. satellite communications, GPS navigation)

Space weather forecasting is currently in significant need of more scientific research in order to make reasonably accurate, long-term predictions.

Ensemble forecasting

Create a statistical sample of weather outcomes by performing multiple computer simulations simultaneously.

Ensembles, are based on a number of input conditions called “system drivers”.

Ensemble members are created based on the uncertainty of these drivers and are used as inputs to our Global Ionosphere and Thermosphere Model (GITM) and simulations are performed which will create a probabilistic forecast of space weather.

  This first segment of this long-term study involves understanding and collecting solar flux data. Utilizing the known uncertainties of this data, we created an ensemble of drivers that were used as input to multiple GITM simulations.  This study examines the effect of the uncertainty in the solar flux on the state of the upper atmosphere.

About the Global Ionosphere and Thermosphere Models

3-D coupled thermosphere-ionosphere model [Ridley et al., 2006]

Solves for 11 Neutral and 10 Ion species, neutral winds (horizontal and vertical), ion and electron velocities and neutral, ion, and electron temperatures

Does not assume hydrostatic equilibrium: Coriolis, vertical ion drag, non- constant gravity, massive auroral zone heating

Flexible grid resolution, fully parallel, with an altitude grid 

Allows for 1D simulations to perform long duration

For this study: 2.5o Latitude x 5o Longitude resolution using 64 processors on the NASA Pleiades supercomputer

Drivers: Solar Flux
 
Plot of the Solar Flux vs. Time.  The black line represents the actual solar flux. The colored lines represent the 5 ensemble members that are used to drive the simulations.

Thermosphere Results
The following plots show the mean mass atmospheric density which is determined from the mean of 5 ensemble members  (top plots) and their standard deviations (bottom plots) of the thermosphere at a 403 km altitude.
1:00 UT: The simulation has just started and thus there is small  difference between the simulations due to the different solar fluxes being used.

4:00 UT: The effects of the flare on the mass density begin to appear.





6:00 UT: Here the effects of the flare reaches its maximum. On a large scale, this is when the largest effects occur. Notice the time delay in effects from Figure 1's peak.


13:00 UT: The effects of the uncertainty have propagated globally. High levels of standard deviation are probably due to significantly different wind patterns. The black arrow points to a maximum uncertainty of 1.7%


Ionosphere Results
The following plots show the mean electron density which is determined from the mean of the 5 ensemble members (top plots) and their standard deviations (bottom plots) of the ionosphere at an altitude of 118 km (left) and 403km (right) .



3:00 UT (118 km): Flare has just ended. Ionosphere is significantly uncertain on the day side.


3:00 UT (403 km): At this higher altitude our standard deviation has significantly increased along with the mean density of electrons.  

Conclusions and Future Work

    Given the uncertainties in the solar flux, it takes several hours for thermosphere to become uncertain. Within 12 hours, the uncertainties have propagated globally in the thermosphere. This is interesting because the thermosphere only affects the day side directly.

•At 13 UT the maximum uncertainty is 1.7%

The ionosphere, however can become uncertain very quickly.

•At 3:00 UT (403 km): The maximum uncertainty is 47%.

The ultimate goal of this research is to predict space weather over one solar rotation period (27 days). We need to study the uncertainty involved in using data on this month’s drivers to predict next month’s space weather. This research also has yet to account for both types of uncertainty in the driver: flare and daily uncertainty. In the future, it will use even more ensemble inputs, like interplanetary magnetic fields (IMF) and solar wind to the GITM model.

References and Acknowledgements
Ridley, A.J., Deng, Y., Toth, G., The Global Ionosphere-Thermosphere Model, J. Atmos. Sol-Terr. Phys., 68, 839, 2006


Flare irradiance data was processed and provided by Phil Chamberlin and Anne Wilson, University of Colorado. http://lasp.colorado.edu/lisird/fism/fism.html


Special thanks to Eastern Michigan University for proving the Undergraduate Research Stimulus Program.

20110710

Artificial Intelligence Software Class @ AHA Hackerspace

  Yesterday, I had the pleasure of attending a free introductory class on artificial intelligence presented by All Hands Active, a hackerspace located in downtown Ann Arbor. The experience helped inform me of several things. Thinking about how to think is not easy, but boy oh boy does it have potential. And artificial intelligences are certainly fun to think about.

by RedKidOne
When the general public thinks of AI, it tends to think of the things Hollywood has thrown at us over the decades. Some examples would be HAL from 2001 A Space Odyssey, or Gerty from the more recent film Moon. Science fiction story junkies like myself tend to imagine a general artificial intelligence that may lead to a technological singularity, like ones depicted in Accelerando by Charles Stross or the Metamorphosis of Prime Intellect by Roger Williams.

Well, the AI we were working with in our two hour long introductory class were nothing like the ones depicted by Hollywood or the sci-fi stories I've read. Instead, they were what one might call "Weak AI", meaning the AI had a very narrow task in mind, and is not capable of thinking in a general or abstract way like a human would.

Our class revolved around cognitive architecture software called Soar which was developed by Carnegie Mellon University in 1982 and is now maintained by the University of Michigan.  This software allows us to write the code or rules for they our AI thinks about it's environment and the objects within the environment.

Cognitive architecture is simply put, a model of human cognition. Defense companies like the ones who develop the predator drones in operation over Afghanistan use these cognitive architectures like Soar to create the autonomous vehicle behavior that has now become a reality on the battle field. Soar has also been used to develop the game AI of popular video games America's Army and Quake.

Our instructor, Jonathon Beard, told us that the overall research goal of the Soar technology was human-level intelligence. And for that to be true, several criteria must be met for our AI: it must be autonomous, adaptive, persistent, real-time, general, robust, able to assess settings, and then make decisions.

Now the AI systems in place at the present time in various industries have some of these capabilities to varying degrees. But these are still systems that are not in any meaningful sense, "conscious", yet in very specific cases they are able to assess their environment and make decisions based on their environment.


The simple AI we are working with involve the use of something called problem space computational model (PSCM). This is the model that gives AI the ability to interact with an environment. PCSM involves the following:
-input from environment
-state: what do i know right now?
-operator: transitions between states
    -elaborate states: characterize, and make generalization about object: alive, dead? green,
blue?
    -propose, select, then apply operators
    -output
Each step from the input to the output in important when it comes to making decisions. And when our AI is making decisions, it's not doing them one by one, it happens in parallel. This fact is what particularly amazed me about this technology. While our AI was taking in data about it's environment, it was making decisions on a top level called a "state" and was working out other decisions concurrently on lower levels called "elaborate states". 

All of this was enabled by a very important factor, memory. Both short and long term memory are critical in helping an artficial intelligence make decisions based on things that have happened in the past and are happening in the present.

This class was extremely informative for an introductory class, and I'd recommend looking into the Soar architecture that is free to download if you have an interest working with AI.

20110624

The Diamond in the Sickly Green Sky

The Diamond in the Sickly Green Sky
                Michael Aaron walked out the door of his parent’s home on Gratiot Avenue, the squeaky screen door slamming shut behind him. Cool wind met his face and whipped his iridescent trimmed motojacket. The hazy starless sky was a harsh dark green like a grumpy muppet you would see on a kid’s public television show.
 He had full netwear on his person tonight. His robotic spider, Uttu, strapped to his back in sleep mode. Aaron commanded his multiphone to set his glasses to heads-up display, instantly logging him into the public mesh network overlayed by the municipal GLADnet. Aaron’s surroundings were now transformed by colorful simulated trees, flowers and corporate advertisements.  
As he walked north down the sidewalk, Aaron found himself wading almost waist deep in a vast assortment of purring kittens, unicorn heads, and busts of a famous pornstars. It was probably all some poser artist’s idea of political hacktivism or just some noob troll’s way of getting his jollies.  It was hard to tell the difference these days.
Aaron finally sifted through the dense spam hack and found himself staring a group of barefooted Ludds right in the face.  He shut off his HUD display, since it was useless at this point; the Ludds didn’t wear electronics and were fixin’ to beat his techno ass to a pulp. 
“Jinkies! Looky wooky what we have here young buds. Found ourselves an ooglay blerd!” said the tallest, bleach-haired one of the group of three. Aaron immediately felt a blow to his stomach, and landed on his side. A short and stocky Ludd with missing teeth was holding a hefty wooden stick. Aaron could hear his robot spider on his back whirring and beeping out of sleep mode.  Aaron didn’t want his pride and joy to get smashed into pieces along with him, so he ordered her to go home. “Uttu, home, now.” he barked.  The dinner plate sized spider unstrapped herself from Aaron’s back and scampered home faster than the Ludds could bother to chase.
Aaron felt another blow, this time to the head. His glasses smacked clean off his face. Eyes blurry, and ears ringing, he could barely make out what was happening around him. But one of the Ludds had apparently tripped over him. The Ludd’s face thudded hard against the curb.  Aaron could hear the other two Ludds growling in rage, scuffling with an unknown assailant.  He looked back, his eyes slightly more focused. He saw the attacker’s blurred leg give an immensely powerful kick to the jaw of a second Ludd, whose blood and teeth splattered a bit on Aaron clothes.
 With two Ludds on the ground, unconscious, maybe dead, the third bleach-haired one was running away so fast you’d think he was being chased by a missile.  “Fuckin’ dipsticks.” said the familiar female voice in the cutest manner you could possibly say those two words.
“Larissa...” said Aaron, half thankfully, half grudgingly as he eyed up her endless muscular legs towering over him. He finally met her Japanese-Brazilian face and long dark brown hair wrapped in a side ponytail; a glowing diamond framed against the sickly green Detroit sky. “Yeah-yeah, you’re welcome, barf bag. Let’s get you to a hospital.”

20110531

A Look of Disapproval


A Look of Disapproval

Michael Aaron anticipated the sound of the lunch bell. A precognitive ability he picked up in his two long years at Great Lakes Technical High School. Famished, he tucked his e-desk away and slipped out of the classroom door in two swift strides. Nearly pummeling the assistant principal, Mrs. Eddelson; who subsequently shot him a look of disapproval. Aaron pardoned himself, smiled widely, and rushed ahead toward the lunch line like an embarrassed cheetah. 

Fried lamprey chips and a bowl of snot were dropped on his tray. Aaron scuttled over to where his friends, Korbin and Hao, were playing Star Command on their netwear.  After wolfing down his food, Aaron logged into the game in mid-play, where the game A.I. gave him a half worn down fleet of starships.

Enkki has joined the game.                            
 
  Starships projected onto the transparent lens of his glasses, appearing to be in the space over the lunch table.  Aaron flanked Korbin at his nine and launched a battery of EMP, disabling his defenses. His attack ship’s rail guns and Hao’s antimatter took care of the rest.

Kronos’ fleet was destroyed by Enkki!

 Just one on one now, and Aaron had noticed a small mob of students crowded around his lunch table, all watching the game on their netwear in spectator mode.  Watch this. Aaron thought as he made short work of Hao’s starfleet, bringing it down to 2%. The instant Aaron fired off the rounds that annihilated Hao’s fleet, a new foe emerged out of nowhere.

Inanna has joined the game.

“Surprise, airhead!” said Larissa Sato as all the students busted out laughing. Barf me out. Thought Aaron as his academic rival flanked him at his six, her EMP knocking out his fleet’s power. Helpless. Larissa surrounded Aaron’s starfleet in a half circle, and then unleashed a combo of phasers and rail slugs. Flawless.

Enkki’s fleet was crushed by Inanna! Game A.I. recommends Enkki to uninstall!

Aaron swore loudly. Mrs. Eddelson, spectating across the room, shot him another look of disapproval.