Shadowrun: Awakened 29 September 2011 - Build 871
Classes | Defines | Typedefs | Enumerations | Functions | Variables
SeismicSimulation.cpp File Reference
#include "../../common/gui/video.h"
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cassert>
#include <math.h>
#include "tbb/task_scheduler_init.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"
#include "tbb/tick_count.h"
Include dependency graph for SeismicSimulation.cpp:

Go to the source code of this file.

Classes

class  seismic_video
struct  UpdateStressBody
struct  UpdateVelocityBody

Defines

#define DEFAULT_NUMBER_OF_FRAMES   100
#define VIDEO_WINMAIN_ARGS

Typedefs

typedef float value

Enumerations

enum  MaterialType { WATER = 0, SANDSTONE = 1, SHALE = 2 }

Functions

void InitializeUniverse ()
int main (int argc, char *argv[])
static void ParallelUpdateStress ()
void ParallelUpdateUniverse ()
static void ParallelUpdateVelocity ()
static void SerialUpdateStress ()
void SerialUpdateUniverse ()
static void SerialUpdateVelocity ()
static void UpdatePulse ()

Variables

static tbb::affinity_partitioner Affinity
static color_t ColorMap [4][ColorMapSize]
static const int ColorMapSize = 1024
static value D [MAX_HEIGHT][MAX_WIDTH]
 Damping coefficients.
static const int DamperSize = 32
static bool InitIsParallel = true
static value L [MAX_HEIGHT][MAX_WIDTH]
 Coefficient related to lightness.
static value M [MAX_HEIGHT][MAX_WIDTH]
 Coefficient related to modulus.
static unsigned char Material [MAX_HEIGHT][MAX_WIDTH]
 Values are MaterialType, cast to an unsigned char to save space.
static const colorcomp_t MaterialColor [4][3]
const size_t MAX_HEIGHT = 512
const size_t MAX_WIDTH = 1024
int number_of_frames = -1
static int PulseCounter
static int PulseTime = 100
static int PulseX = UniverseWidth/3
static int PulseY = UniverseHeight/4
static value S [MAX_HEIGHT][MAX_WIDTH]
 Horizontal stress.
static value T [MAX_HEIGHT][MAX_WIDTH]
 Vertical stress.
int threads_high = tbb::task_scheduler_init::automatic
int threads_low = 0
const char * titles [2] = {"Seismic Simulation: Serial", "Seismic Simulation: Parallel"}
int UniverseHeight = MAX_HEIGHT
int UniverseWidth = MAX_WIDTH
static value V [MAX_HEIGHT][MAX_WIDTH]
 Velocity at each grid point.
seismic_video video

Define Documentation

#define DEFAULT_NUMBER_OF_FRAMES   100

Definition at line 50 of file SeismicSimulation.cpp.

Referenced by main().

Definition at line 30 of file SeismicSimulation.cpp.


Typedef Documentation

typedef float value

Definition at line 58 of file SeismicSimulation.cpp.


Enumeration Type Documentation

Enumerator:
WATER 
SANDSTONE 
SHALE 

Definition at line 84 of file SeismicSimulation.cpp.

                  {
    WATER=0,
    SANDSTONE=1,
    SHALE=2
};

Function Documentation

void InitializeUniverse ( )

Definition at line 232 of file SeismicSimulation.cpp.

References ColorMap, ColorMapSize, D, DamperSize, g, video::get_color(), L, M, mission1::m, Material, MaterialColor, PulseCounter, PulseTime, S, SANDSTONE, SHALE, UniverseHeight, UniverseWidth, V, and WATER.

Referenced by main().

                          {
    PulseCounter = PulseTime;
    // Initialize V, S, and T to slightly non-zero values, in order to avoid denormal waves.
    for( int i=0; i<UniverseHeight; ++i ) 
#pragma ivdep
        for( int j=0; j<UniverseWidth; ++j ) {
            T[i][j] = S[i][j] = V[i][j] = value(1.0E-6);
        }
    for( int i=1; i<UniverseHeight-1; ++i ) {
        for( int j=1; j<UniverseWidth-1; ++j ) {
            float x = float(j-UniverseWidth/2)/(UniverseWidth/2);
            value t = (value)i/UniverseHeight;
            MaterialType m;
            D[i][j] = 1.0;
            // Coefficient values are fictitious, and chosen to visually exaggerate 
            // physical effects such as Rayleigh waves.  The fabs/exp line generates
            // a shale layer with a gentle upwards slope and an anticline.
            if( t<0.3f ) {
                m = WATER;
                M[i][j] = 0.125;
                L[i][j] = 0.125;
            } else if( fabs(t-0.7+0.2*exp(-8*x*x)+0.025*x)<=0.1 ) {
                m = SHALE;
                M[i][j] = 0.5;
                L[i][j] = 0.6;
            } else {
                m = SANDSTONE;
                M[i][j] = 0.3;
                L[i][j] = 0.4;
            } 
            Material[i][j] = m;
        }
    }
    value scale = 2.0f/ColorMapSize;
    for( int k=0; k<4; ++k ) {
        for( int i=0; i<ColorMapSize; ++i ) {
            colorcomp_t c[3];
            value t = (i-ColorMapSize/2)*scale;
            value r = t>0 ? t : 0;
            value b = t<0 ? -t : 0;
            value g = 0.5f*fabs(t);
            memcpy(c, MaterialColor[k], sizeof(c));
            c[2] = colorcomp_t(r*(255-c[2])+c[2]);
            c[1] = colorcomp_t(g*(255-c[1])+c[1]);
            c[0] = colorcomp_t(b*(255-c[0])+c[0]);
            ColorMap[k][i] = video.get_color(c[2], c[1], c[0]);
        }
    }
    // Set damping coefficients around border to reduce reflections from boundaries.
    value d = 1.0;
    for( int k=DamperSize-1; k>0; --k ) {
        d *= 1-1.0f/(DamperSize*DamperSize);
        for( int j=1; j<UniverseWidth-1; ++j ) {
            D[k][j] *= d;
            D[UniverseHeight-1-k][j] *= d;
        }
        for( int i=1; i<UniverseHeight-1; ++i ) {
            D[i][k] *= d;
            D[i][UniverseWidth-1-k] *= d;
        }
    }
}
int main ( int  argc,
char *  argv[] 
)

Definition at line 300 of file SeismicSimulation.cpp.

References tbb::task_scheduler_init::automatic, video::calc_fps, DEFAULT_NUMBER_OF_FRAMES, tbb::task_scheduler_init::deferred, IDC_SEISMICSIMULATION, IDI_SEISMICSIMULATION, IDI_SMALL, video::init_console(), video::init_window(), tbb::task_scheduler_init::initialize(), InitializeUniverse(), InitIsParallel, video::main_loop(), tbb::tick_count::now(), number_of_frames, ParallelUpdateUniverse(), SerialUpdateUniverse(), t0, video::terminate(), video::threaded, threads_high, threads_low, video::title, titles, and UniverseHeight.

{
    // threads number init
    if(argc > 1 && isdigit(argv[1][0])) {
        char* end; threads_high = threads_low = (int)strtol(argv[1],&end,0);
        switch( *end ) {
            case ':': threads_high = (int)strtol(end+1,0,0); break;
            case '\0': break;
            default: printf("unexpected character = %c\n",*end);
        }
    }
    if (argc > 2 && isdigit(argv[2][0])){
        number_of_frames = (int)strtol(argv[2],0,0);
    }
    // video layer init
    video.title = InitIsParallel?titles[1]:titles[0];
#ifdef _WINDOWS
    #define MAX_LOADSTRING 100
    TCHAR szWindowClass[MAX_LOADSTRING];    // the main window class name
    LoadStringA(video::win_hInstance, IDC_SEISMICSIMULATION, szWindowClass, MAX_LOADSTRING);
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    WNDCLASSEX wcex; memset(&wcex, 0, sizeof(wcex));
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.hIcon          = LoadIcon(video::win_hInstance, MAKEINTRESOURCE(IDI_SEISMICSIMULATION));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = LPCTSTR(IDC_SEISMICSIMULATION);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(video::win_hInstance, MAKEINTRESOURCE(IDI_SMALL));
    video.win_set_class(wcex); // ascii convention here
    video.win_load_accelerators(IDC_SEISMICSIMULATION);
#endif
    if(video.init_window(UniverseWidth, UniverseHeight)) {
        video.calc_fps = true;
        video.threaded = threads_low > 0;
        // video is ok, init universe
        InitializeUniverse();
        // main loop
        video.main_loop();
    }
    else if(video.init_console()) {
        // do console mode
        if(number_of_frames <= 0) number_of_frames = DEFAULT_NUMBER_OF_FRAMES;
        if(threads_high == tbb::task_scheduler_init::automatic) threads_high = 4;
        if(threads_high < threads_low) threads_high = threads_low;
        for( int p = threads_low; p <= threads_high; ++p ) {
            InitializeUniverse();
            tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred);
            if( p > 0 )
                init.initialize( p );
            tbb::tick_count t0 = tbb::tick_count::now();
            if( p > 0 )
                for( int i=0; i<number_of_frames; ++i )
                    ParallelUpdateUniverse();
            else
                for( int i=0; i<number_of_frames; ++i )
                    SerialUpdateUniverse();
            tbb::tick_count t1 = tbb::tick_count::now();
            printf("%.1f frame per sec", number_of_frames/(t1-t0).seconds());
            if( p > 0 ) 
                printf(" with %d way parallelism\n",p);
            else
                printf(" with serial version\n"); 
        }
    }
    video.terminate();
    return 0;
}
static void ParallelUpdateStress ( ) [static]

Definition at line 161 of file SeismicSimulation.cpp.

References Affinity, tbb::parallel_for(), and UniverseHeight.

Referenced by ParallelUpdateUniverse().

                                   {
    tbb::parallel_for( tbb::blocked_range<int>( 1, UniverseHeight-1 ), // Index space for loop
                       UpdateStressBody(),                             // Body of loop
                       Affinity );                                     // Affinity hint
}
void ParallelUpdateUniverse ( )
static void ParallelUpdateVelocity ( ) [static]

Definition at line 184 of file SeismicSimulation.cpp.

References Affinity, tbb::parallel_for(), and UniverseHeight.

Referenced by ParallelUpdateUniverse().

                                     {
    tbb::parallel_for( tbb::blocked_range<int>( 1, UniverseHeight-1 ), // Index space for loop
                       UpdateVelocityBody(),                           // Body of loop
                       Affinity );                                     // Affinity hint
}
static void SerialUpdateStress ( ) [static]

Definition at line 124 of file SeismicSimulation.cpp.

References ColorMap, ColorMapSize, M, Material, drawing_area::put_pixel(), S, drawing_area::set_pos(), T, UniverseHeight, UniverseWidth, and V.

Referenced by SerialUpdateUniverse().

                                 {
    drawing_area drawing(0, 0, UniverseWidth, UniverseHeight);
    for( int i=1; i<UniverseHeight-1; ++i ) {
        drawing.set_pos(1, i);
#pragma ivdep
        for( int j=1; j<UniverseWidth-1; ++j ) {
            S[i][j] += M[i][j]*(V[i][j+1]-V[i][j]);
            T[i][j] += M[i][j]*(V[i+1][j]-V[i][j]);
            int index = (int)(V[i][j]*(ColorMapSize/2)) + ColorMapSize/2;
            if( index<0 ) index = 0;
            if( index>=ColorMapSize ) index = ColorMapSize-1;
            color_t* c = ColorMap[Material[i][j]];
            drawing.put_pixel(c[index]);
        }
    }
}
void SerialUpdateUniverse ( )
static void SerialUpdateVelocity ( ) [static]

Definition at line 167 of file SeismicSimulation.cpp.

References D, L, S, UniverseHeight, and V.

Referenced by SerialUpdateUniverse().

                                   {
    for( int i=1; i<UniverseHeight-1; ++i ) 
#pragma ivdep
        for( int j=1; j<UniverseWidth-1; ++j ) 
            V[i][j] = D[i][j]*(V[i][j] + L[i][j]*(S[i][j] - S[i][j-1] + T[i][j] - T[i-1][j]));
}
static void UpdatePulse ( ) [static]

Definition at line 116 of file SeismicSimulation.cpp.

References M, PulseCounter, PulseTime, PulseX, PulseY, and V.

Referenced by ParallelUpdateUniverse(), and SerialUpdateUniverse().

                          {
    if( PulseCounter>0 ) {
        value t = (PulseCounter-PulseTime/2)*0.05f;
        V[PulseY][PulseX] += 64*sqrt(M[PulseY][PulseX])*exp(-t*t);
        --PulseCounter;
    }
}

Variable Documentation

Affinity is an argument to parallel_for to hint that an iteration of a loop is best replayed on the same processor for each execution of the loop. It is a global object because it must remember where the iterations happened in previous executions.

Definition at line 82 of file SeismicSimulation.cpp.

Referenced by ParallelUpdateStress(), and ParallelUpdateVelocity().

Definition at line 102 of file SeismicSimulation.cpp.

Referenced by InitializeUniverse(), and SerialUpdateStress().

const int ColorMapSize = 1024 [static]

Definition at line 101 of file SeismicSimulation.cpp.

Referenced by InitializeUniverse(), and SerialUpdateStress().

const int DamperSize = 32 [static]

Definition at line 99 of file SeismicSimulation.cpp.

Referenced by InitializeUniverse().

bool InitIsParallel = true [static]

Definition at line 109 of file SeismicSimulation.cpp.

Referenced by main().

unsigned char Material[MAX_HEIGHT][MAX_WIDTH] [static]

Definition at line 91 of file SeismicSimulation.cpp.

Referenced by InitializeUniverse(), and SerialUpdateStress().

const colorcomp_t MaterialColor[4][3] [static]
Initial value:
 { 
    {96,0,0},     
    {0,48,48},    
    {32,32,23}    
}

Definition at line 93 of file SeismicSimulation.cpp.

Referenced by InitializeUniverse().

const size_t MAX_HEIGHT = 512

Definition at line 53 of file SeismicSimulation.cpp.

const size_t MAX_WIDTH = 1024

Definition at line 52 of file SeismicSimulation.cpp.

int number_of_frames = -1

Definition at line 51 of file SeismicSimulation.cpp.

Referenced by main().

int PulseCounter [static]

Definition at line 105 of file SeismicSimulation.cpp.

Referenced by InitializeUniverse(), and UpdatePulse().

int PulseTime = 100 [static]

Definition at line 104 of file SeismicSimulation.cpp.

Referenced by InitializeUniverse(), and UpdatePulse().

int PulseX = UniverseWidth/3 [static]

Definition at line 106 of file SeismicSimulation.cpp.

Referenced by UpdatePulse().

int PulseY = UniverseHeight/4 [static]

Definition at line 107 of file SeismicSimulation.cpp.

Referenced by UpdatePulse().

Definition at line 114 of file SeismicSimulation.cpp.

Referenced by main().

int threads_low = 0

It is used for console mode for test with different number of threads and also has meaning for gui: threads_low - use sepatate event/updating loop thread (>0) or not (0). threads_high - initialization value for scheduler

Definition at line 114 of file SeismicSimulation.cpp.

Referenced by main().

const char* titles[2] = {"Seismic Simulation: Serial", "Seismic Simulation: Parallel"}

Definition at line 110 of file SeismicSimulation.cpp.

Referenced by main().

Definition at line 56 of file SeismicSimulation.cpp.

Referenced by InitializeUniverse(), and SerialUpdateStress().


Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net