//Gravitational Wave Source Simulations

//Jeff Jauregui, April 2003

            //code for implementing graphics borrowed from

            //Andre LaMothe, "Windows game programming for dummies"

//***NOTE: This code may only compile correctly by creating

//a Win32 app in MS Visual C++

 

 

//header files needed to run windows program

#define WIN32_LEAN_AND_MEAN 

#include <windows.h> 

#include <windowsx.h>

#include <stdio.h>

#include <math.h>

#include <fstream.h>

 

 

//define a color and paint brush for drawing on the screen

COLORREF black = RGB(0,0,0);

HBRUSH bbrush = (HBRUSH__ *)GetStockObject(BLACK_BRUSH);

 

 

//define the number of radial and angular steps in the 2D polar grid

#define R_MAX                       300

#define THETA_MAX 200

 

//define the number of time steps

#define T_MAX                       100

 

#define pi                                 3.1416

 

//prototypes for various functions

double  density_R_0(double, double, double);   //returns a density as a function of r, theta, and time

double  get_angle(double);                                                                    //converts an angle index into an actual angle, in radians

double  get_r(double);                                                                          //converts an radius index into an actual value for the radius

double  get_t(double);                                                                           //converts a time index into a normalized time value

double  calc_Q00();                                                                                         //returns the first component of the mass quadrupole moment

void    d2Q_dt2();                                                                                            //calculates grav. wave amplitude using the second time derivative of Q00

 

//global variables

double grid[R_MAX][THETA_MAX];                        //defines density(r,theta) polar grid

double Q00[T_MAX];                                                 //an array to hold Q00 as a function of time

 

// defines for windows

#define WINDOW_CLASS_NAME "WINCLASS1"

 

// GLOBALS ////////////////////////////////////////////////

HWND main_window_handle = NULL; // save the window handle

 

//GRAPHICS FUNCTIONS:

 

 

LRESULT CALLBACK WindowProc(HWND hwnd,

                                                                            UINT msg,

                            WPARAM wparam,

                            LPARAM lparam)

{

// this is the main message handler of the system

PAINTSTRUCT                      ps;                    // used in WM_PAINT

HDC                                        hdc;      // handle to a device context

 

// what is the message

            int y = (int)HIWORD(lparam);

 

            switch(msg)

            {         

            case WM_CREATE:

        {

                        // do initialization stuff here

                        return(0);

                        } break;

 

            case WM_PAINT:

                        {

                        // simply validate the window

                        hdc = BeginPaint(hwnd,&ps);  

 

                        EndPaint(hwnd,&ps);

                        return(0);

                        } break;

 

            case WM_KEYDOWN:

 

                        PostMessage(hwnd,WM_DESTROY,NULL,NULL);

                        return 0;

                        break;

                       

            case WM_MOUSEMOVE:

 

                        break;

           

            case WM_DESTROY:

                        {

                        // kill the application                             

                        DeleteObject(bbrush);

                        PostQuitMessage(0);

                        return(0);

                        } break;

 

            default:break;

 

    } // end switch

 

// process any messages that we didn't take care of

return (DefWindowProc(hwnd, msg, wparam, lparam));

 

} // end WinProc

 

// WINMAIN ////////////////////////////////////////////////

int WINAPI WinMain( HINSTANCE hinstance,

                                                            HINSTANCE hprevinstance,

                                                            LPSTR lpcmdline,

                                                            int ncmdshow)

{

 

WNDCLASS winclass;            // this will hold the class we create

HWND            hwnd;              // generic window handle

MSG                msg;                // generic message

 

// first fill in the window class stucture

winclass.style                            = CS_DBLCLKS | CS_OWNDC |

                          CS_HREDRAW | CS_VREDRAW;

winclass.lpfnWndProc  = WindowProc;

winclass.cbClsExtra                  = 0;

winclass.cbWndExtra               = 0;

winclass.hInstance                    = hinstance;

winclass.hIcon                          = LoadIcon(NULL, IDI_APPLICATION);

winclass.hCursor                      = LoadCursor(NULL, IDC_ARROW);

winclass.hbrBackground           = (HBRUSH__ *)GetStockObject(BLACK_BRUSH);

winclass.lpszMenuName           = NULL;

winclass.lpszClassName           = WINDOW_CLASS_NAME;

 

// register the window class

if (!RegisterClass(&winclass))

            return(0);

 

// create the window

if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class

                                                                          "Gravity",             // title

                                                                          WS_OVERLAPPEDWINDOW | WS_VISIBLE,

                                                                          0,0,       // x,y

                                                                          320,200, // width, height

                                                                          NULL,              // handle to parent

                                                                          NULL,              // handle to menu

                                                                          hinstance,// instance

                                                                          NULL)))        // creation parms

return(0);

 

ShowWindow(hwnd, SW_SHOWMAXIMIZED);

 

// get the window handle for graphics

main_window_handle = hwnd;

HDC hdc = GetDC(hwnd);

 

//***********Main body of program here***********

 

//create a rectangle to help erase the screen later

RECT rect;

rect.top = 0;

rect.bottom= 800;

rect.left = 0;

rect.right = 1200;

 

//loop through each time step, indexed by n

for(int n = 0; n < T_MAX; n++)

{

 

 

            int r,o;  //looping variables, r = radius, o = theta (angle)

 

            //the min and max will be determined in order to perform color-mapping

            double max = 0;

            double min = 1000000;

 

            //loop through grid for every point

            for(r = 0; r < R_MAX; r++)

            {         

                        for(o = 0; o < THETA_MAX; o++)

                        {

                                    //fill each discrete point on the grid with a density value

                                    grid[r][o] = density_R_0(get_r(r),get_angle(o),(double)n);

 

                                    if(grid[r][o] > max)

                                                max = grid[r][o];

                                    if(grid[r][o] < min)

                                                min = grid[r][o];

                        }

            }

 

 

            //plot the density function in the window

            bool draw_graphics = true;                                                       //turns on/off the displaying of graphics

            if(draw_graphics)

            {

                        //fill the screen with black in order to erase

                        FillRect(hdc,&rect,bbrush);

 

                        //loop through each point in the polar grid

                        for(r = 0; r < R_MAX; r++)

                        {

                                    for(o = 0; o <= THETA_MAX; o++)

                                    {

                                                //draw a pixel whose intensity is determined by the density at that point

                                                SetPixel(hdc, 1152/2+ 300*get_r(r)*cos(2*3.14*o/THETA_MAX),

                                                            864/2 + 300*get_r(r)*sin(2*3.14*o/THETA_MAX),

                                                            RGB(255/(max-min)*(grid[r][o]-min),0,0));

                                    }

                        }

 

            }

           

            Q00[n] = calc_Q00();

 

}//end the main simulation loop

 

//calculate and output the gravitational wave amplitudes to a file wavedata.m

d2Q_dt2();

 

//***********End Main body of program***********

 

// enter windows event loop

while(1)

            {

 

            if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))

                        {

                        // test if this is a quit

        if (msg.message == WM_QUIT)

           break;

           

                        // translate any accelerator keys

                        TranslateMessage(&msg);

 

                        // send the message to the window proc

                        DispatchMessage(&msg);

                        } // end if

 

   

} // end while

 

 

// return to Windows like this

 

return(msg.wParam);

 

} // end WinMain

 

//returns the density as a function of radius, angle o, and time

double density_R_0(double r, double o, double t)

{

            double w = .12*get_t(t)*10;                 //angular frequency of rotation

 

//various possible density functions:       

            //          return exp(-r*0.2);

            //          return exp(-r*(2+sin(2*o+w*t)));

            //return exp(-r*0.2*t)*exp(-r*(1.1+sin(2*o+w*t)));

 

            //let the mass be more concentrated toward the center over time,

            //and let the distribution be asymmetric

            return exp(-r*0.5*(get_t(t)+1)*(2+sin(2*o+w*get_t(t))));

}

 

//take in an angle "index", and return an angle on a scale of 0 to pi

double get_angle(double o)

{

            return 2*pi*o/THETA_MAX;

}

//take in an radius "index", and return a radius on a scale of 0 to 1

double get_r(double r)

{

            return r/R_MAX;

}

 

//take in an time "index",and return a time on a scale of 0 to 10

double get_t(double t)

{

            return 10*t/T_MAX;

}

 

//calculate the Q00 component of the mass quadrupole moment

double calc_Q00()

{

            //define the summing variable for numerical integration

            double sum = 0;

           

            //looping variables

            int r, o;

 

            //loop through the polargrid

            for(r = 0; r < R_MAX; r++)

            {

                        for(o = 0; o < THETA_MAX; o++)

                        {

                                    //add to the sum the integrand (2x^2-y^2) times the density, times the area element

                                    sum += pow(get_r(r),3)*(2*pow(cos(get_angle(o)),2)-pow(sin(get_angle(o)),2))*grid[r][o]*2*pi/THETA_MAX/R_MAX;//*10*2*pi/THETA_MAX;

                        }

            }

            //return the total sum

            return sum;

}

 

//calculate the second time derivative the mass quadrupole moment, and output to a file

void d2Q_dt2()

{

            //create and open the file for output

            ofstream outfile;

            outfile.open("wavedata.m");

 

            //loop through the Q00 data and numerically evaluate the 2nd derivative

            for(int i = 0; i < T_MAX-3; i++)

                        outfile << (Q00[i+2]-2*Q00[i+1]+Q00[i])*(double)(T_MAX*T_MAX) << '\n';

           

            //close the file

            outfile.close();

}