<commit_before>#include <cstdlib>
#include <cmath>
#include <ctime>
#include <GL/glut.h>
#include <assert.h>
#include <cstdlib>

#include "main.hpp"
#include "Scene.hpp"

// don't define anything in headers! only declare it!!!1!one!
Vec3Df MyCameraPosition;

std::vector<Vec3Df> MyLightPositions;

// double buffered
unsigned int textures[2];
unsigned int activeTexIndex = 0;
unsigned int isDrawingTexture = 0;
unsigned int isRealtimeRaytracing = 0;
Tree MyTree;
Scene MyScene;

// options
extern bool g_phong;
extern bool g_checkerboard;
extern bool g_debug;

extern bool g_ambient;
extern bool g_diffuse;
extern bool g_specular;
extern bool g_reflect;
extern bool g_refract;
extern bool g_occlusion;

bool needRebuild = false; // if the raytrace needs to be built

/**
 * draw a full-screen texture
 */
void drawTexture(int texIndex){
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
    glBegin(GL_QUADS);
    glTexCoord2f(0, 0);
    glVertex3f(0, 0, 0);
    glTexCoord2f(1, 0);
    glVertex3f(4, 0, 0);
    glTexCoord2f(1, 1);
    glVertex3f(4, 4, 0);
    glTexCoord2f(0, 1);
    glVertex3f(0, 4, 0);
    glEnd();
}

void animate() {
    MyCameraPosition = getCameraPosition();
    glutPostRedisplay();
}

void display(void);
void reshape(int w, int h);
void keyboard(unsigned char key, int x, int y);

// entry point
int main(int argc, char** argv){
    glutInit(&argc, argv);

    // couches du framebuffer utilisees par l'application
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

    // position et taille de la fenetre
    glutInitWindowPosition(200, 100);
    glutInitWindowSize(WINDOW_RES_X, WINDOW_RES_Y);
    glutCreateWindow(argv[0]);

    // Initialisation du point de vue
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0, 0, -8);
    glRotatef(-45, -1, 0, 0);
    tbInitTransform();     // initialisation du point de vue
    tbHelp();                      // affiche l'aide sur la traqueboule
    MyCameraPosition = getCameraPosition();
    //
    // Active la lumière
    // Pour la partie
    // ECLAIRAGE

    glEnable( GL_LIGHTING);
    glEnable( GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);
    int LightPos[4] = {0, 0, 3, 1};
    glLightiv(GL_LIGHT0, GL_POSITION, LightPos);
    //glMaterialiv(GL_FRONT_AND_BACK,GL_SPECULAR,MatSpec);
    //glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,10);

    glEnable(GL_NORMALIZE);
    glClearColor(0.0, 0.0, 0.0, 0.0);

    // Details sur le mode de tracé
    glEnable( GL_DEPTH_TEST);            // effectuer le test de profondeur
    //glEnable(GL_CULL_FACE);
    //glCullFace(GL_BACK);
    glPolygonMode(GL_FRONT, GL_FILL);
    glPolygonMode(GL_BACK, GL_LINE);
    glShadeModel(GL_SMOOTH);

    // init textures
    char* buf = new char[1024 * 1024 * 3];
    glGenTextures(2, textures);

    // texture 1
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 1024, 0, GL_RGB,
    GL_UNSIGNED_BYTE, buf);

    // texture 2
    glBindTexture(GL_TEXTURE_2D, textures[1]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 1024, 0, GL_RGB,
    GL_UNSIGNED_BYTE, buf);

    delete[] buf;

    // cablage des callback
    glutReshapeFunc(reshape);
    // glutSetKeyRepeat(true);
    glutKeyboardFunc(keyboard);
    // glutKeyboardUpFunc(keyup);
    glutDisplayFunc(display);
    glutMouseFunc(tbMouseFunc);    // traqueboule utilise la souris
    glutMotionFunc(tbMotionFunc);  // traqueboule utilise la souris
    glutIdleFunc(animate);

    int ret = init(argc, argv);
    if(ret == 255)
        return 0;
    if(ret > 0)
        return ret;

    // lancement de la boucle principale
    glutMainLoop();

    return 0;  // instruction jamais exécutée
}

// draw fps
void drawFPS(){
    clock_t diff = clock() - lastFrameTime;
    lastFrameTime = clock();

    const int clock = CLOCKS_PER_SEC * (isRealtimeRaytracing ? THREADS : 1);

    if((0. + lastFrameTime - lastFPSRenderTime) / clock > .1){
        lastFPSRenderTime = lastFrameTime;
        float fps = (1. / diff) * clock;
        sprintf(screenFPS, "%.1f fps", fps);
    }

    int i = 0;
    while(screenFPS[i] != '\0'){
        glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, screenFPS[i++]);
    }
}

// display
clock_t ticks;
void display(void) {

    glPushAttrib(GL_ALL_ATTRIB_BITS);
    // Effacer tout
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // la couleur et le z
    drawFPS();

    glLoadIdentity();  // repere camera

    if(isDrawingTexture || isRealtimeRaytracing){
        const static GLdouble viewport[] = {
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
           -2,-2,-4, 1
        };

        glMultMatrixd(viewport);
        drawTexture(activeTexIndex);

        // reset view
        glLoadIdentity();
        tbVisuTransform();

        // swap buffers; draw on back buffer
        if (isRealtimeRaytracing){
            clock_t start = clock();
            startRayTracing(!activeTexIndex, false);
            ticks = clock() - start;
            activeTexIndex = !activeTexIndex;
        } else {
            if (needRebuild == true){
                int millis = (int)(ticks * 1000. / CLOCKS_PER_SEC);
                long long expected = millis;
                expected *= RAYTRACE_RES_X / PREVIEW_RES_X;
                expected *= RAYTRACE_RES_Y / PREVIEW_RES_Y;
                expected *= MSAA / PREVIEW_MSAA;
                expected *= MSAA / PREVIEW_MSAA;
                expected /= THREADS;
                if (expected < 1000)
                    printf("will take %d milliseconds\n", (int)expected);
                else if (expected < 1000 * 60)
                    printf("will take %d seconds\n", (int)(expected / 1000));
                else if (expected < 1000 * 60 * 60)
                    printf("will take %d minutes\n", (int)(expected / 1000 / 60));
                else if (expected < 1000 * 60 * 60 * 24) {
                    printf("RENDERING WILL TAKE LONG!\n");
                    printf("will take %d hour\n", (int)(expected / 1000 / 60 / 60));
                } else if (expected < (long long)1000 * 60 * 60 * 24 * 365) {
                    printf("RENDERING WILL TAKE VERY LONG!\n");
                    printf("will take %d days\n", (int)(expected / 1000 / 60 / 60 / 24));
                }
                else if (expected < (long long)1000 * 60 * 60 * 24 * 365 * 1000) {
                    printf("RENDERING will take years!\n");
                    printf("will take %d year\n", (int)(expected / 1000 / 60 / 60 / 24 / 365 / 1000));
                }
                else if (expected < (long long)1000 * 60 * 60 * 24 * 365 * 1000 * 1000) {
                    printf("RENDERING will take thousands of years!\n");
                    printf("will take %d millenia\n", (int)(expected / 1000 / 60 / 60 / 24 / 365 / 1000 / 1000));
                }
                else if (expected < (long long)1000 * 60 * 60 * 24 * 365 * 1000 * 1000) {
                    printf("RENDERING will take millions of years!\n");
                    printf("will take %d million years\n", (int)(expected / 1000 / 60 / 60 / 24 / 365 / 1000 / 1000));
                }
                else if (expected < (float)1000 * 60 * 60 * 24 * 365 * 1000 * 1000 * 1000) {
                    printf("If the dinosaurs were alive when you started rendering, it would be ready now.\n");
                    printf("will take %d billion years\n", (int)(expected / 1000 / 60 / 60 / 24 / 365 / 1000 / 100));
                }
                else {
                    printf("THIS IS MADNESS!\n");
                    printf("will take %s seconds\n", "<overflow error>");
                }
                startRayTracing(activeTexIndex, true);
                needRebuild = false;
            }
        }
    } else {
        tbVisuTransform(); // origine et orientation de la scene
        MyScene.draw();
		if (g_debug)
			MyScene.debugDraw();
    }

    glutSwapBuffers();
    glPopAttrib();
}
// pour changement de taille ou desiconification
void reshape(int w, int h){
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //glOrtho (-1.1, 1.1, -1.1,1.1, -1000.0, 1000.0);
    gluPerspective(50, (float)w / h, 1, 10);
    glMatrixMode(GL_MODELVIEW);
}

// prise en compte du clavier
void keyboard(unsigned char key, int x, int y){
    switch(key){
        case '1':
            g_phong = !g_phong;
            break;
        case '2':
            g_checkerboard = !g_checkerboard;
            break;
		case '3':
			g_debug = !g_debug;
			break;
		case '4': g_ambient = !g_ambient; break;
		case '5': g_diffuse = !g_diffuse; break;
		case '6': g_specular = !g_specular; break;
		case '7': g_reflect = !g_reflect; break;
		case '8': g_refract = !g_refract; break;
		case '9': g_occlusion = !g_occlusion; break;
        case 't':
            isDrawingTexture = 0;
            isRealtimeRaytracing = 0;
            break;
        case 'L':
            MyScene.addLightPoint(getCameraPosition());
            break;
        case 'l':
			MyScene.lights[0] = getCameraPosition();
            break;
        case 'r':
            needRebuild = true;
            isDrawingTexture = 1;
            isRealtimeRaytracing = 0;
            break;
        case 'b':
            cout << "Using " << THREADS << " threads and resolution of "
                    << PREVIEW_RES_X << "x" << PREVIEW_RES_Y << endl;
            isRealtimeRaytracing = 1;
            isDrawingTexture = 0;
            break;
        case 27:     // touche ESC
            exit(0);
    }

    yourKeyboardPress(key, x, y);
}

void keyup(unsigned char key, int x, int y) {
    yourKeyboardRelease(key, x, y);
}

<commit_msg>incorrect merge I assume?<commit_after>#include <cstdlib>
#include <cmath>
#include <ctime>
#include <GL/glut.h>
#include <assert.h>
#include <cstdlib>

#include "main.hpp"
#include "Scene.hpp"

// don't define anything in headers! only declare it!!!1!one!
Vec3Df MyCameraPosition;

std::vector<Vec3Df> MyLightPositions;

// double buffered
unsigned int textures[2];
unsigned int activeTexIndex = 0;
unsigned int isDrawingTexture = 0;
unsigned int isRealtimeRaytracing = 0;
Tree MyTree;
Scene MyScene;

// options
extern bool g_phong;
extern bool g_checkerboard;
extern bool g_debug;

extern bool g_ambient;
extern bool g_diffuse;
extern bool g_specular;
extern bool g_reflect;
extern bool g_refract;
extern bool g_occlusion;

bool needRebuild = false; // if the raytrace needs to be built

/**
 * draw a full-screen texture
 */
void drawTexture(int texIndex){
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
    glBegin(GL_QUADS);
    glTexCoord2f(0, 0);
    glVertex3f(0, 0, 0);
    glTexCoord2f(1, 0);
    glVertex3f(4, 0, 0);
    glTexCoord2f(1, 1);
    glVertex3f(4, 4, 0);
    glTexCoord2f(0, 1);
    glVertex3f(0, 4, 0);
    glEnd();
}

void animate() {
    MyCameraPosition = getCameraPosition();
    glutPostRedisplay();
}

void display(void);
void reshape(int w, int h);
void keyboard(unsigned char key, int x, int y);

// entry point
int main(int argc, char** argv){
    glutInit(&argc, argv);

    // couches du framebuffer utilisees par l'application
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

    // position et taille de la fenetre
    glutInitWindowPosition(200, 100);
    glutInitWindowSize(WINDOW_RES_X, WINDOW_RES_Y);
    glutCreateWindow(argv[0]);

    // Initialisation du point de vue
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0, 0, -8);
    glRotatef(-45, -1, 0, 0);
    tbInitTransform();     // initialisation du point de vue
    tbHelp();                      // affiche l'aide sur la traqueboule
    MyCameraPosition = getCameraPosition();
    //
    // Active la lumière
    // Pour la partie
    // ECLAIRAGE

    glEnable( GL_LIGHTING);
    glEnable( GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);
    int LightPos[4] = {0, 0, 3, 1};
    glLightiv(GL_LIGHT0, GL_POSITION, LightPos);
    //glMaterialiv(GL_FRONT_AND_BACK,GL_SPECULAR,MatSpec);
    //glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,10);

    glEnable(GL_NORMALIZE);
    glClearColor(0.0, 0.0, 0.0, 0.0);

    // Details sur le mode de tracé
    glEnable( GL_DEPTH_TEST);            // effectuer le test de profondeur
    //glEnable(GL_CULL_FACE);
    //glCullFace(GL_BACK);
    glPolygonMode(GL_FRONT, GL_FILL);
    glPolygonMode(GL_BACK, GL_LINE);
    glShadeModel(GL_SMOOTH);

    // init textures
    char* buf = new char[1024 * 1024 * 3];
    glGenTextures(2, textures);

    // texture 1
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 1024, 0, GL_RGB,
    GL_UNSIGNED_BYTE, buf);

    // texture 2
    glBindTexture(GL_TEXTURE_2D, textures[1]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 1024, 0, GL_RGB,
    GL_UNSIGNED_BYTE, buf);

    delete[] buf;

    // cablage des callback
    glutReshapeFunc(reshape);
    // glutSetKeyRepeat(true);
    glutKeyboardFunc(keyboard);
    // glutKeyboardUpFunc(keyup);
    glutDisplayFunc(display);
    glutMouseFunc(tbMouseFunc);    // traqueboule utilise la souris
    glutMotionFunc(tbMotionFunc);  // traqueboule utilise la souris
    glutIdleFunc(animate);

    int ret = init(argc, argv);
    if(ret == 255)
        return 0;
    if(ret > 0)
        return ret;

    // lancement de la boucle principale
    glutMainLoop();

    return 0;  // instruction jamais exécutée
}

// draw fps
void drawFPS(){
    clock_t diff = clock() - lastFrameTime;
    lastFrameTime = clock();

    const int clock = CLOCKS_PER_SEC * (isRealtimeRaytracing ? THREADS : 1);

    if((0. + lastFrameTime - lastFPSRenderTime) / clock > .1){
        lastFPSRenderTime = lastFrameTime;
        float fps = (1. / diff) * clock;
        sprintf(screenFPS, "%.1f fps", fps);
    }

    int i = 0;
    while(screenFPS[i] != '\0'){
        glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, screenFPS[i++]);
    }
}

// display
clock_t ticks;
void display(void) {

    glPushAttrib(GL_ALL_ATTRIB_BITS);
    // Effacer tout
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // la couleur et le z
    drawFPS();

    glLoadIdentity();  // repere camera

    if(isDrawingTexture || isRealtimeRaytracing){
        const static GLdouble viewport[] = {
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
           -2,-2,-4, 1
        };

        glMultMatrixd(viewport);
        drawTexture(activeTexIndex);

        // reset view
        glLoadIdentity();
        tbVisuTransform();

        // swap buffers; draw on back buffer
        if (isRealtimeRaytracing){
            clock_t start = clock();
            startRayTracing(!activeTexIndex, false);
            ticks = clock() - start;
            activeTexIndex = !activeTexIndex;
        } else {
            if (needRebuild == true){
                int millis = (int)(ticks * 1000. / CLOCKS_PER_SEC);
                long long expected = millis;
                expected *= RAYTRACE_RES_X / PREVIEW_RES_X;
                expected *= RAYTRACE_RES_Y / PREVIEW_RES_Y;
                expected *= MSAA / PREVIEW_MSAA;
                expected *= MSAA / PREVIEW_MSAA;
                expected /= THREADS;
                if (expected < 1000)
                    printf("will take %d milliseconds\n", (int)expected);
                else if (expected < 1000 * 60)
                    printf("will take %d seconds\n", (int)(expected / 1000));
                else if (expected < 1000 * 60 * 60)
                    printf("will take %d minutes\n", (int)(expected / 1000 / 60));
                else if (expected < 1000 * 60 * 60 * 24) {
                    printf("RENDERING WILL TAKE LONG!\n");
                    printf("will take %d hour\n", (int)(expected / 1000 / 60 / 60));
                } else if (expected < (long long)1000 * 60 * 60 * 24 * 365) {
                    printf("RENDERING WILL TAKE VERY LONG!\n");
                    printf("will take %d days\n", (int)(expected / 1000 / 60 / 60 / 24));
                }
                else if (expected < (long long)1000 * 60 * 60 * 24 * 365 * 1000) {
                    printf("RENDERING will take years!\n");
                    printf("will take %d year\n", (int)(expected / 1000 / 60 / 60 / 24 / 365 / 1000));
                }
                else if (expected < (long long)1000 * 60 * 60 * 24 * 365 * 1000 * 1000) {
                    printf("RENDERING will take thousands of years!\n");
                    printf("will take %d millenia\n", (int)(expected / 1000 / 60 / 60 / 24 / 365 / 1000 / 1000));
                }
                else if (expected < (long long)1000 * 60 * 60 * 24 * 365 * 1000 * 1000) {
                    printf("RENDERING will take millions of years!\n");
                    printf("will take %d million years\n", (int)(expected / 1000 / 60 / 60 / 24 / 365 / 1000 / 1000));
                }
                else if (expected < (float)1000 * 60 * 60 * 24 * 365 * 1000 * 1000 * 1000) {
                    printf("If the dinosaurs were alive when you started rendering, it would be ready now.\n");
                    printf("will take %d billion years\n", (int)(expected / 1000 / 60 / 60 / 24 / 365 / 1000 / 100));
                }
                else {
                    printf("THIS IS MADNESS!\n");
                    printf("will take %s seconds\n", "<overflow error>");
                }
                startRayTracing(activeTexIndex, true);
                needRebuild = false;
            }
        }
    } else {
        tbVisuTransform(); // origine et orientation de la scene
        MyScene.draw();
		if (g_debug)
			MyScene.debugDraw();
    }

    glutSwapBuffers();
    glPopAttrib();
}
// pour changement de taille ou desiconification
void reshape(int w, int h){
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //glOrtho (-1.1, 1.1, -1.1,1.1, -1000.0, 1000.0);
    gluPerspective(50, (float)w / h, 1, 10);
    glMatrixMode(GL_MODELVIEW);
}

// prise en compte du clavier
void keyboard(unsigned char key, int x, int y){
    switch(key){
        case '1':
            g_phong = !g_phong;
            break;
        case '2':
            g_checkerboard = !g_checkerboard;
            break;
		case '3':
			g_debug = !g_debug;
			break;
		case '4': g_ambient = !g_ambient; break;
		case '5': g_diffuse = !g_diffuse; break;
		case '6': g_specular = !g_specular; break;
		case '7': g_reflect = !g_reflect; break;
		case '8': g_refract = !g_refract; break;
		case '9': g_occlusion = !g_occlusion; break;
        case 't':
            isDrawingTexture = 0;
            isRealtimeRaytracing = 0;
            break;
        case 'L':
            MyCameraPosition = getCameraPosition();
            MyScene.addLightPoint(MyCameraPosition);
            break;
        case 'l':
			MyScene.lights[0] = getCameraPosition();
            break;
        case 'r':
            needRebuild = true;
            isDrawingTexture = 1;
            isRealtimeRaytracing = 0;
            break;
        case 'b':
            cout << "Using " << THREADS << " threads and resolution of "
                    << PREVIEW_RES_X << "x" << PREVIEW_RES_Y << endl;
            isRealtimeRaytracing = 1;
            isDrawingTexture = 0;
            break;
        case 27:     // touche ESC
            exit(0);
    }

    yourKeyboardPress(key, x, y);
}

void keyup(unsigned char key, int x, int y) {
    yourKeyboardRelease(key, x, y);
}

<|endoftext|>


<commit_before>//node.cpp
#include <random>
#include <cstdlib>
#include <iostream>
#include "node.hpp"

using namespace utils;

    //--------------------CONSTRUTOR E DESTRUTOR--------------------------//

Node::Node(bool grow, int maxDepth, int numberOfXs){

    //construtor, que recebe se deve construir a árvore no modo growStyle
    //(caso falso, constrói no modo fullStyle). maxDepth determina a pro-
    //fundidade máxima que a subárvore pode assumir. numberOfXs é nece-
    //sário para que o construtor saiba quantas variáveis existem e possa
    //criar este mesmo número de diferentes variáveis nas folhas.
    //por padrão, grow = false, maxDepth = 0, numberOfXs = 1.

    this->numberOfXs = numberOfXs;
    this->maxDepth = maxDepth;

    if (grow) growStyle();
    else      fullStyle();
}

Node::~Node(){

    //destrutor, que recursivamente deleta o nó e todos os seus filhos.

    if (left)  delete left;
    if (right) delete right;
}

    //------------ESTILOS DE CRIAÇÃO DE ÁRVORES DE EXPRESSÕES-------------//

void Node::growStyle(){

    //estilo de crescimento aleatório, que funciona da seguinte forma:
    //enquanto ainda há profundidade para as subárvores, não restringe
    //o tipo que o nó pode ser. Quando chega na profundidade máxima,
    //só cria folhas.

    if (maxDepth>1){
        tipo = random()%SIZETYPE;

        if      (tipo==CTE)  makeThisCte();
        else if (tipo==VAR)  makeThisVar();
        else if (tipo==FUN1) makeThisFunc1(true);
        else                 makeThisFunc2(true); //tipo==FUN2
    }
    else {
        tipo = random()%2;

        if (tipo==CTE) makeThisCte();
        else           makeThisVar(); //tipo==VAR
    }
}

void Node::fullStyle(){

    //estilo de crescimento que gera sempre uma árvore binária completa
    //(salvo casos onde são sorteadas funções de 1 parâmetro, tendo
    //apenas um filho, e não dois).

    if (maxDepth>1){
        tipo = random()%2 + 2;

        if (tipo==FUN1) makeThisFunc1(false);
        else            makeThisFunc2(false); //tipo==FUN2
    }
    else {
        tipo = random()%2;

        if (tipo==CTE) makeThisCte();
        else           makeThisVar(); //tipo==VAR
    }
}

    //----------FUNÇÕES AJUSTADORAS DE VALORES DA ÁRVORE------------------//

void Node::makeThisVar(){

    //função que ajusta valores do nó para ser uma variável. Sorteia um
    //índice de x para os n numberOfXs, deleta e "nulla" os ponteiros.

    C.idX = random()%numberOfXs;

    left = NULL;
    right = NULL;
}

void Node::makeThisCte(){

    //ajusta os valores do nó para ser uma constante. Atribui um valor de
    // 0 a 9 para o nó, deleta e "nulla" os ponteiros.

    C.value = random()%10;

    left = NULL;
    right = NULL;
}

void Node::makeThisFunc1(bool grow){

    //ajusta os valores do nó para ser uma função de 1 parâmetro. A fun-
    //ção é sorteada dentro do utils, e por padrão o filho criado será na
    //direita (isso não faria diferença aqui se fosse na esquerda), mas
    //as funções do programa estão preparadas para lidar com casos onde
    //a subárvore foi criada no lado esquerdo. chama recursivamente
    //o construtor para que a árvore não fique incompleta.

    C.function = random() % SIZEFUNC1;

    right = new Node(grow, maxDepth-1, numberOfXs);
    left = NULL;
}

void Node::makeThisFunc2(bool grow){

    //ajusta os valores do nó para ser uma função de 2 parâmetros. A
    //função é sorteada dentro do utils. Chama recursivamente o cons-
    //trutor dos dois filhos para que a árvore não fique incompleta.

    C.function = random() % SIZEFUNC2;

    right = new Node(grow, maxDepth-1, numberOfXs);
    left  = new Node(grow, maxDepth-1, numberOfXs);
}

    //----------------FUNÇÕES DE UTILIDADE GERAL--------------------------//

double Node::eval(DataPoint p) {

    //calcula o valor que a expressão retorna quando tem como valores
    //para suas n variáveis os valores do DataPoint.x (vector<double>).

    if (this->tipo==VAR){
        return p.x[C.idX];
    } else if(this->tipo==CTE) {
        return C.value;
    } else if (this->tipo==FUN1){
        if (left)
            return func1_solver(C.function, left->eval(p));
        else
            return func1_solver(C.function, right->eval(p));
    } else //this->tipo==FUN2
        return func2_solver(C.function, left->eval(p), right->eval(p));
}

void Node::print_node_d(){

    //imprime a árvore recursivamente.

    if (tipo==FUN2){
        std::cout << " (";
        left->print_node_d();

        switch(C.function){
                case ADD:
                    std::cout << "+";
                    break;
                case DIV:
                    std::cout << "/";
                    break;
                case SUB:
                    std::cout << "-";
                    break;
                case MULT:
                    std::cout << "*";
                    break;
                case POW:
                    std::cout << "^";
                    break;
        }

        right->print_node_d();
        std::cout << ") ";
    }
    else if (tipo==CTE)
        std::cout << this->C.value;
    else if (tipo==VAR)
        std::cout << "x" << C.idX;
    else{ //tipo==FUN2
        switch(C.function){
            case LN:
                std::cout << " ln(";
                break;
            case EXP:
                std::cout <<" (e^";
                break;
            case SQRT:
                std::cout  << " sqrt(";
                break;
            case SIN:
                std::cout << " sin(";
                break;
            case COS:
                std::cout << " cos(";
                break;
            case TAN:
                std::cout << " tan(";
                break;
        }
        right->print_node_d();
        std::cout << ") ";
    }
}

Node *Node::get_copy(){

    //cria um novo Node, deleta seus filhos e ajusta todos os seus parâ-
    //metros para que seja um ponteiro para uma cópia idêntica do nó que
    //invocou o método.

    Node *aux = new Node(false, 0, 1);

    aux->tipo = this->tipo;
    aux->numberOfXs = this->numberOfXs;
    aux->maxDepth = this->maxDepth;

    if (tipo==VAR){
        aux->C.idX = this->C.idX;
    }
    else if (tipo==CTE){
        aux->C.value = this->C.value;
    }
    else if (tipo==FUN1){
        aux->C.function = this->C.function;

        if (right) aux->right = this->right->get_copy();
        else       aux->left  = this->left->get_copy();
    }
    else { //tipo==FUN2
        aux->C.function = this->C.function;

        aux->left  = this->left->get_copy();
        aux->right = this->right->get_copy();
    }
    return aux;
}

int Node::get_type(){

    //retorna o tipo do nó. útil para funções da classe individual, já
    //que o tipo é uma variável privada.

    return this->tipo;
}
<commit_msg>2.0.2 Print_node e println_node<commit_after>//node.cpp
#include <random>
#include <cstdlib>
#include <iostream>
#include "node.hpp"

using namespace utils;

    //--------------------CONSTRUTOR E DESTRUTOR--------------------------//

Node::Node(bool grow, int maxDepth, int numberOfXs){

    //construtor, que recebe se deve construir a árvore no modo growStyle
    //(caso falso, constrói no modo fullStyle). maxDepth determina a pro-
    //fundidade máxima que a subárvore pode assumir. numberOfXs é nece-
    //sário para que o construtor saiba quantas variáveis existem e possa
    //criar este mesmo número de diferentes variáveis nas folhas.
    //por padrão, grow = false, maxDepth = 0, numberOfXs = 1.

    this->numberOfXs = numberOfXs;
    this->maxDepth = maxDepth;

    if (grow) growStyle();
    else      fullStyle();
}

Node::~Node(){

    //destrutor, que recursivamente deleta o nó e todos os seus filhos.

    if (left)  delete left;
    if (right) delete right;
}

    //------------ESTILOS DE CRIAÇÃO DE ÁRVORES DE EXPRESSÕES-------------//

void Node::growStyle(){

    //estilo de crescimento aleatório, que funciona da seguinte forma:
    //enquanto ainda há profundidade para as subárvores, não restringe
    //o tipo que o nó pode ser. Quando chega na profundidade máxima,
    //só cria folhas.

    if (maxDepth>1){
        tipo = random()%SIZETYPE;

        if      (tipo==CTE)  makeThisCte();
        else if (tipo==VAR)  makeThisVar();
        else if (tipo==FUN1) makeThisFunc1(true);
        else                 makeThisFunc2(true); //tipo==FUN2
    }
    else {
        tipo = random()%2;

        if (tipo==CTE) makeThisCte();
        else           makeThisVar(); //tipo==VAR
    }
}

void Node::fullStyle(){

    //estilo de crescimento que gera sempre uma árvore binária completa
    //(salvo casos onde são sorteadas funções de 1 parâmetro, tendo
    //apenas um filho, e não dois).

    if (maxDepth>1){
        tipo = random()%2 + 2;

        if (tipo==FUN1) makeThisFunc1(false);
        else            makeThisFunc2(false); //tipo==FUN2
    }
    else {
        tipo = random()%2;

        if (tipo==CTE) makeThisCte();
        else           makeThisVar(); //tipo==VAR
    }
}

    //----------FUNÇÕES AJUSTADORAS DE VALORES DA ÁRVORE------------------//

void Node::makeThisVar(){

    //função que ajusta valores do nó para ser uma variável. Sorteia um
    //índice de x para os n numberOfXs, deleta e "nulla" os ponteiros.

    C.idX = random()%numberOfXs;

    left = NULL;
    right = NULL;
}

void Node::makeThisCte(){

    //ajusta os valores do nó para ser uma constante. Atribui um valor de
    // 0 a 9 para o nó, deleta e "nulla" os ponteiros.

    C.value = random()%10;

    left = NULL;
    right = NULL;
}

void Node::makeThisFunc1(bool grow){

    //ajusta os valores do nó para ser uma função de 1 parâmetro. A fun-
    //ção é sorteada dentro do utils, e por padrão o filho criado será na
    //direita (isso não faria diferença aqui se fosse na esquerda), mas
    //as funções do programa estão preparadas para lidar com casos onde
    //a subárvore foi criada no lado esquerdo. chama recursivamente
    //o construtor para que a árvore não fique incompleta.

    C.function = random() % SIZEFUNC1;

    right = new Node(grow, maxDepth-1, numberOfXs);
    left = NULL;
}

void Node::makeThisFunc2(bool grow){

    //ajusta os valores do nó para ser uma função de 2 parâmetros. A
    //função é sorteada dentro do utils. Chama recursivamente o cons-
    //trutor dos dois filhos para que a árvore não fique incompleta.

    C.function = random() % SIZEFUNC2;

    right = new Node(grow, maxDepth-1, numberOfXs);
    left  = new Node(grow, maxDepth-1, numberOfXs);
}

    //----------------FUNÇÕES DE UTILIDADE GERAL--------------------------//

double Node::eval(DataPoint p) {

    //calcula o valor que a expressão retorna quando tem como valores
    //para suas n variáveis os valores do DataPoint.x (vector<double>).

    if (this->tipo==VAR){
        return p.x[C.idX];
    } else if(this->tipo==CTE) {
        return C.value;
    } else if (this->tipo==FUN1){
        if (left)
            return func1_solver(C.function, left->eval(p));
        else
            return func1_solver(C.function, right->eval(p));
    } else //this->tipo==FUN2
        return func2_solver(C.function, left->eval(p), right->eval(p));
}

void Node::print_node_d(){

    //imprime a árvore recursivamente.

    if (tipo==FUN2){
        std::cout << " (";
        left->print_node_d();

        switch(C.function){
                case ADD:
                    std::cout << "+";
                    break;
                case DIV:
                    std::cout << "/";
                    break;
                case SUB:
                    std::cout << "-";
                    break;
                case MULT:
                    std::cout << "*";
                    break;
                case POW:
                    std::cout << "^";
                    break;
        }

        right->print_node_d();
        std::cout << ") ";
    }
    else if (tipo==CTE)
        std::cout << this->C.value;
    else if (tipo==VAR)
        std::cout << "x" << C.idX;
    else{ //tipo==FUN2
        switch(C.function){
            case LN:
                std::cout << " ln(";
                break;
            case EXP:
                std::cout <<" (e^";
                break;
            case SQRT:
                std::cout  << " sqrt(";
                break;
            case SIN:
                std::cout << " sin(";
                break;
            case COS:
                std::cout << " cos(";
                break;
            case TAN:
                std::cout << " tan(";
                break;
        }
        right->print_node_d();
        std::cout << ") ";
    }
}

void Node::println_node_d(){
    print_node_d();
    std::cout << std::endl;
}

Node *Node::get_copy(){

    //cria um novo Node, deleta seus filhos e ajusta todos os seus parâ-
    //metros para que seja um ponteiro para uma cópia idêntica do nó que
    //invocou o método.

    Node *aux = new Node(false, 0, 1);

    aux->tipo = this->tipo;
    aux->numberOfXs = this->numberOfXs;
    aux->maxDepth = this->maxDepth;

    if (tipo==VAR){
        aux->C.idX = this->C.idX;
    }
    else if (tipo==CTE){
        aux->C.value = this->C.value;
    }
    else if (tipo==FUN1){
        aux->C.function = this->C.function;

        if (right) aux->right = this->right->get_copy();
        else       aux->left  = this->left->get_copy();
    }
    else { //tipo==FUN2
        aux->C.function = this->C.function;

        aux->left  = this->left->get_copy();
        aux->right = this->right->get_copy();
    }
    return aux;
}

int Node::get_type(){

    //retorna o tipo do nó. útil para funções da classe individual, já
    //que o tipo é uma variável privada.

    return this->tipo;
}
<|endoftext|>


<commit_before>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#define LUABIND_BUILDING

#include <luabind/lua_include.hpp>

#include <luabind/luabind.hpp>
#include <luabind/function.hpp>

namespace luabind {

namespace
{

  int make_property(lua_State* L)
  {
      int args = lua_gettop(L);

      if (args == 0 || args > 2)
      {
          lua_pushstring(L, "make_property() called with wrong number of arguments.");
          lua_error(L);
      }

      if (args == 1)
          lua_pushnil(L);

      lua_pushcclosure(L, &detail::property_tag, 2);
      return 1;
  }

} // namespace unnamed

    void open(lua_State* L)
    {
        // get the global class registry, or create one if it doesn't exist
        // (it's global within a lua state)
        detail::class_registry* r = 0;

        // If you hit this assert it's because you have called luabind::open()
        // twice on the same lua_State.
        assert((detail::class_registry::get_registry(L) == 0)
            && "you cannot call luabind::open() twice");

        lua_pushstring(L, "__luabind_classes");
        r = static_cast<detail::class_registry*>(
            lua_newuserdata(L, sizeof(detail::class_registry)));

        // set gc metatable
        lua_newtable(L);
        lua_pushstring(L, "__gc");
        lua_pushcclosure(
            L
          , detail::garbage_collector_s<
                detail::class_registry
            >::apply
          , 0);

        lua_settable(L, -3);
        lua_setmetatable(L, -2);

        new(r) detail::class_registry(L);
        lua_settable(L, LUA_REGISTRYINDEX);

        // add functions (class, cast etc...)
        lua_pushstring(L, "class");
        lua_pushcclosure(L, detail::create_class::stage1, 0);
        lua_settable(L, LUA_GLOBALSINDEX);

        lua_pushstring(L, "property");
        lua_pushcclosure(L, &make_property, 0);
        lua_settable(L, LUA_GLOBALSINDEX);
    }

} // namespace luabind

<commit_msg>Add missing LUABIND_API to luabind::open().<commit_after>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#define LUABIND_BUILDING

#include <luabind/lua_include.hpp>

#include <luabind/luabind.hpp>
#include <luabind/function.hpp>

namespace luabind {

namespace
{

  int make_property(lua_State* L)
  {
      int args = lua_gettop(L);

      if (args == 0 || args > 2)
      {
          lua_pushstring(L, "make_property() called with wrong number of arguments.");
          lua_error(L);
      }

      if (args == 1)
          lua_pushnil(L);

      lua_pushcclosure(L, &detail::property_tag, 2);
      return 1;
  }

} // namespace unnamed

    LUABIND_API void open(lua_State* L)
    {
        // get the global class registry, or create one if it doesn't exist
        // (it's global within a lua state)
        detail::class_registry* r = 0;

        // If you hit this assert it's because you have called luabind::open()
        // twice on the same lua_State.
        assert((detail::class_registry::get_registry(L) == 0)
            && "you cannot call luabind::open() twice");

        lua_pushstring(L, "__luabind_classes");
        r = static_cast<detail::class_registry*>(
            lua_newuserdata(L, sizeof(detail::class_registry)));

        // set gc metatable
        lua_newtable(L);
        lua_pushstring(L, "__gc");
        lua_pushcclosure(
            L
          , detail::garbage_collector_s<
                detail::class_registry
            >::apply
          , 0);

        lua_settable(L, -3);
        lua_setmetatable(L, -2);

        new(r) detail::class_registry(L);
        lua_settable(L, LUA_REGISTRYINDEX);

        // add functions (class, cast etc...)
        lua_pushstring(L, "class");
        lua_pushcclosure(L, detail::create_class::stage1, 0);
        lua_settable(L, LUA_GLOBALSINDEX);

        lua_pushstring(L, "property");
        lua_pushcclosure(L, &make_property, 0);
        lua_settable(L, LUA_GLOBALSINDEX);
    }

} // namespace luabind

<|endoftext|>


<commit_before>#include "param.h"
#include <TError.h>

namespace bdm {

// simulation group
std::string Param::backup_file_ = "";
std::string Param::restore_file_ = "";
uint32_t Param::backup_interval_ = 1800;
double Param::simulation_time_step_ = 0.01;
double Param::simulation_max_displacement_ = 3.0;
bool Param::run_mechanical_interactions_ = true;
bool Param::bound_space_ = false;
double Param::min_bound_ = 0;
double Param::max_bound_ = 100;

// visualization group
bool Param::live_visualization_ = false;
bool Param::export_visualization_ = false;
uint32_t Param::visualization_export_interval_ = 1;
std::unordered_map<std::string, std::set<std::string>>
    Param::visualize_sim_objects_;
std::vector<Param::VisualizeDiffusion> Param::visualize_diffusion_;

// development group
bool Param::output_op_runtime_ = false;
bool Param::python_catalyst_pipeline_ = false;

#define BDM_ASSIGN_CONFIG_VALUE(variable, config_key)                      \
  {                                                                        \
    auto value = config->get_qualified_as<decltype(variable)>(config_key); \
    if (value) {                                                           \
      variable = *value;                                                   \
    }                                                                      \
  }

void Param::AssignFromConfig(const std::shared_ptr<cpptoml::table>& config) {
  // simulation group
  BDM_ASSIGN_CONFIG_VALUE(backup_file_, "simulation.backup_file");
  BDM_ASSIGN_CONFIG_VALUE(restore_file_, "simulation.restore_file");
  BDM_ASSIGN_CONFIG_VALUE(backup_interval_, "simulation.backup_interval");
  BDM_ASSIGN_CONFIG_VALUE(simulation_time_step_, "simulation.time_step");
  BDM_ASSIGN_CONFIG_VALUE(simulation_max_displacement_,
                          "simulation.max_displacement");
  BDM_ASSIGN_CONFIG_VALUE(run_mechanical_interactions_,
                          "simulation.run_mechanical_interactions");
  BDM_ASSIGN_CONFIG_VALUE(bound_space_, "simulation.bound_space");
  BDM_ASSIGN_CONFIG_VALUE(min_bound_, "simulation.min_bound");
  BDM_ASSIGN_CONFIG_VALUE(max_bound_, "simulation.max_bound");
  // visualization group
  BDM_ASSIGN_CONFIG_VALUE(live_visualization_, "visualization.live");
  BDM_ASSIGN_CONFIG_VALUE(export_visualization_, "visualization.export");
  BDM_ASSIGN_CONFIG_VALUE(visualization_export_interval_,
                          "visualization.export_interval");

  //   visualize_sim_objects_
  auto visualize_sim_objects_tarr =
      config->get_table_array("visualize_sim_object");
  if (visualize_sim_objects_tarr) {
    for (const auto& table : *visualize_sim_objects_tarr) {
      // We do a 'redundant' check here, because `get_as` on Mac OS does not
      // catch the exception when the "name" is not defined in the bdm.toml
      // Same goes for all the other redundant checks
      if (table->contains("name")) {
        auto name = table->get_as<std::string>("name");
        if (!name) {
          Warning("AssignFromConfig",
                  "Missing name for attribute visualize_sim_object");
          continue;
        }

        if (table->contains("additional_data_members")) {
          auto dm_option =
              table->get_array_of<std::string>("additional_data_members");

          std::set<std::string> data_members;
          for (const auto& val : *dm_option) {
            data_members.insert(val);
          }
          visualize_sim_objects_[*name] = data_members;
        } else {
          std::set<std::string> data_members;
          visualize_sim_objects_[*name] = data_members;
        }
      }
    }
  }

  //   visualize_diffusion_
  auto visualize_diffusion_tarr =
      config->get_table_array("visualize_diffusion");
  if (visualize_diffusion_tarr) {
    for (const auto& table : *visualize_diffusion_tarr) {
      if (table->contains("name")) {
        auto name = table->get_as<std::string>("name");
        if (!name) {
          Warning("AssignFromConfig",
                  "Missing name for attribute visualize_diffusion");
          continue;
        }

        VisualizeDiffusion vd;
        vd.name_ = *name;

        if (table->contains("concentration")) {
          auto concentration = table->get_as<bool>("concentration");
          if (concentration) {
            vd.concentration_ = *concentration;
          }
        }
        if (table->contains("gradient")) {
          auto gradient = table->get_as<bool>("gradient");
          if (gradient) {
            vd.gradient_ = *gradient;
          }
        }

        visualize_diffusion_.push_back(vd);
      }
    }
  }

  // development group
  BDM_ASSIGN_CONFIG_VALUE(output_op_runtime_, "development.output_op_runtime");
}

void Param::Reset() {
  // simulation group
  backup_file_ = "";
  restore_file_ = "";
  backup_interval_ = 1800;
  simulation_time_step_ = 0.01;
  simulation_max_displacement_ = 3.0;
  run_mechanical_interactions_ = true;
  bound_space_ = false;
  min_bound_ = 0;
  max_bound_ = 100;

  // visualization group
  live_visualization_ = false;
  export_visualization_ = false;
  visualization_export_interval_ = 1;
  visualize_sim_objects_.clear();
  visualize_diffusion_.clear();

  // development group
  output_op_runtime_ = false;
  python_catalyst_pipeline_ = false;
}

}  // namespace bdm
<commit_msg>Fix toml segfault on OS X<commit_after>#include "param.h"
#include <TError.h>

namespace bdm {

// simulation group
std::string Param::backup_file_ = "";
std::string Param::restore_file_ = "";
uint32_t Param::backup_interval_ = 1800;
double Param::simulation_time_step_ = 0.01;
double Param::simulation_max_displacement_ = 3.0;
bool Param::run_mechanical_interactions_ = true;
bool Param::bound_space_ = false;
double Param::min_bound_ = 0;
double Param::max_bound_ = 100;

// visualization group
bool Param::live_visualization_ = false;
bool Param::export_visualization_ = false;
uint32_t Param::visualization_export_interval_ = 1;
std::unordered_map<std::string, std::set<std::string>>
    Param::visualize_sim_objects_;
std::vector<Param::VisualizeDiffusion> Param::visualize_diffusion_;

// development group
bool Param::output_op_runtime_ = false;
bool Param::python_catalyst_pipeline_ = false;

#define BDM_ASSIGN_CONFIG_VALUE(variable, config_key)                        \
  {                                                                          \
    if (config->contains_qualified(config_key)) {                            \
      auto value = config->get_qualified_as<decltype(variable)>(config_key); \
      if (value) {                                                           \
        variable = *value;                                                   \
      }                                                                      \
    }                                                                        \
  }

void Param::AssignFromConfig(const std::shared_ptr<cpptoml::table>& config) {
  // simulation group
  BDM_ASSIGN_CONFIG_VALUE(backup_file_, "simulation.backup_file");
  BDM_ASSIGN_CONFIG_VALUE(restore_file_, "simulation.restore_file");
  BDM_ASSIGN_CONFIG_VALUE(backup_interval_, "simulation.backup_interval");
  BDM_ASSIGN_CONFIG_VALUE(simulation_time_step_, "simulation.time_step");
  BDM_ASSIGN_CONFIG_VALUE(simulation_max_displacement_,
                          "simulation.max_displacement");
  BDM_ASSIGN_CONFIG_VALUE(run_mechanical_interactions_,
                          "simulation.run_mechanical_interactions");
  BDM_ASSIGN_CONFIG_VALUE(bound_space_, "simulation.bound_space");
  BDM_ASSIGN_CONFIG_VALUE(min_bound_, "simulation.min_bound");
  BDM_ASSIGN_CONFIG_VALUE(max_bound_, "simulation.max_bound");
  // visualization group
  BDM_ASSIGN_CONFIG_VALUE(live_visualization_, "visualization.live");
  BDM_ASSIGN_CONFIG_VALUE(export_visualization_, "visualization.export");
  BDM_ASSIGN_CONFIG_VALUE(visualization_export_interval_,
                          "visualization.export_interval");

  //   visualize_sim_objects_
  auto visualize_sim_objects_tarr =
      config->get_table_array("visualize_sim_object");
  if (visualize_sim_objects_tarr) {
    for (const auto& table : *visualize_sim_objects_tarr) {
      // We do a 'redundant' check here, because `get_as` on Mac OS does not
      // catch the exception when the "name" is not defined in the bdm.toml
      // Same goes for all the other redundant checks
      if (table->contains("name")) {
        auto name = table->get_as<std::string>("name");
        if (!name) {
          Warning("AssignFromConfig",
                  "Missing name for attribute visualize_sim_object");
          continue;
        }

        if (table->contains("additional_data_members")) {
          auto dm_option =
              table->get_array_of<std::string>("additional_data_members");

          std::set<std::string> data_members;
          for (const auto& val : *dm_option) {
            data_members.insert(val);
          }
          visualize_sim_objects_[*name] = data_members;
        } else {
          std::set<std::string> data_members;
          visualize_sim_objects_[*name] = data_members;
        }
      }
    }
  }

  //   visualize_diffusion_
  auto visualize_diffusion_tarr =
      config->get_table_array("visualize_diffusion");
  if (visualize_diffusion_tarr) {
    for (const auto& table : *visualize_diffusion_tarr) {
      if (table->contains("name")) {
        auto name = table->get_as<std::string>("name");
        if (!name) {
          Warning("AssignFromConfig",
                  "Missing name for attribute visualize_diffusion");
          continue;
        }

        VisualizeDiffusion vd;
        vd.name_ = *name;

        if (table->contains("concentration")) {
          auto concentration = table->get_as<bool>("concentration");
          if (concentration) {
            vd.concentration_ = *concentration;
          }
        }
        if (table->contains("gradient")) {
          auto gradient = table->get_as<bool>("gradient");
          if (gradient) {
            vd.gradient_ = *gradient;
          }
        }

        visualize_diffusion_.push_back(vd);
      }
    }
  }

  // development group
  BDM_ASSIGN_CONFIG_VALUE(output_op_runtime_, "development.output_op_runtime");
}

void Param::Reset() {
  // simulation group
  backup_file_ = "";
  restore_file_ = "";
  backup_interval_ = 1800;
  simulation_time_step_ = 0.01;
  simulation_max_displacement_ = 3.0;
  run_mechanical_interactions_ = true;
  bound_space_ = false;
  min_bound_ = 0;
  max_bound_ = 100;

  // visualization group
  live_visualization_ = false;
  export_visualization_ = false;
  visualization_export_interval_ = 1;
  visualize_sim_objects_.clear();
  visualize_diffusion_.clear();

  // development group
  output_op_runtime_ = false;
  python_catalyst_pipeline_ = false;
}

}  // namespace bdm
<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>
#include "config.hpp"
#include "peers.hpp"

Peer::Peer(std::string hexIP, class User* u, bool seeding, unsigned int fid, std::string client) {
	std::cout << "Creating peer on torrent " << std::to_string(fid) << " using client " << client << " (" << hexIP << ")\n";
	this->hexIP = hexIP;
	this->user = u;
	this->seeding = seeding;
	this->fid = fid;
	this->client = client;
	auto duration = std::chrono::system_clock::now().time_since_epoch();
	lastUpdate = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
	seedtime = 0;
}

User* Peer::User() {
	return this->user;
}

std::string* Peer::getHexIP() {
	return &this->hexIP;
}

void Peer::updateStats (unsigned long stats, const long long &now) {
	std::cout << "Updating stats (" << std::to_string(this->stats) << " -> " << std::to_string(stats) << ") on a user from torrent " << std::to_string(fid) << " (" << hexIP << ")\n";
	this->stats += stats;
	seedtime += now - lastUpdate;
	lastUpdate = now;
}

void Peer::resetStats() {
	this->stats = 0;
}

std::string Peer::record(const unsigned int& left, const std::string& peerID) {
	std::cout << "Recording stats of peer " << peerID << " (left: " << left << ")\n";
	unsigned int downloaded,uploaded = 0;
	auto duration = std::chrono::system_clock::now().time_since_epoch();
	auto now = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
	if (seeding) {
		uploaded = stats;
		downloaded = 0;
		seedtime = now - lastUpdate;
	} else {
		downloaded = stats;
		uploaded = 0;
	}
	stats = 0;
	lastUpdate = now;
	return "INSERT INTO xbt_files_users(uid,downloaded,uploaded,remaining,seedtime,useragent,peerid,fid) VALUES ('"
						+ std::to_string(*user->getID()) + "', " +
					"'" + std::to_string(downloaded) + "', " +
					"'" + std::to_string(uploaded) + "', " +
					"'" + std::to_string(left) + "', " +
					"'" + std::to_string(seedtime) + "', " +
					"'" + client + "', " +
					"'" + peerID + "', " +
					"'" + std::to_string(fid) + "') ON DUPLICATE downloaded = downloaded + VALUES(downloaded), uploaded = uploaded + VALUES(uploaded), seedtime = seedtime + VALUES(seedtime)";
	user->updateStats(downloaded,uploaded);
}

std::string Peer::remove(const std::string& peerID, const unsigned int& fid) {
	std::cout << "Removing peer " << peerID << " from torrent " << std::to_string(fid) << '\n';
	return "DELETE FROM xbt_files_users WHERE peer_id LIKE '"
		+ peerID
		+ "' AND fid = "
		+ std::to_string(fid);
}

bool Peer::timedOut(const long long &now) {
	std::cout << "A PEER TIMED OUT\n";
	return (now - lastUpdate > Config::getInt("timeout"));
}
<commit_msg>fix mysql on duplicate syntax<commit_after>#include <chrono>
#include <iostream>
#include "config.hpp"
#include "peers.hpp"

Peer::Peer(std::string hexIP, class User* u, bool seeding, unsigned int fid, std::string client) {
	std::cout << "Creating peer on torrent " << std::to_string(fid) << " using client " << client << " (" << hexIP << ")\n";
	this->hexIP = hexIP;
	this->user = u;
	this->seeding = seeding;
	this->fid = fid;
	this->client = client;
	auto duration = std::chrono::system_clock::now().time_since_epoch();
	lastUpdate = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
	seedtime = 0;
}

User* Peer::User() {
	return this->user;
}

std::string* Peer::getHexIP() {
	return &this->hexIP;
}

void Peer::updateStats (unsigned long stats, const long long &now) {
	std::cout << "Updating stats (" << std::to_string(this->stats) << " -> " << std::to_string(stats) << ") on a user from torrent " << std::to_string(fid) << " (" << hexIP << ")\n";
	this->stats += stats;
	seedtime += now - lastUpdate;
	lastUpdate = now;
}

void Peer::resetStats() {
	this->stats = 0;
}

std::string Peer::record(const unsigned int& left, const std::string& peerID) {
	std::cout << "Recording stats of peer " << peerID << " (left: " << left << ")\n";
	unsigned int downloaded,uploaded = 0;
	auto duration = std::chrono::system_clock::now().time_since_epoch();
	auto now = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
	if (seeding) {
		uploaded = stats;
		downloaded = 0;
		seedtime = now - lastUpdate;
	} else {
		downloaded = stats;
		uploaded = 0;
	}
	stats = 0;
	lastUpdate = now;
	return "INSERT INTO xbt_files_users(uid,downloaded,uploaded,remaining,seedtime,useragent,peerid,fid) VALUES ('"
						+ std::to_string(*user->getID()) + "', " +
					"'" + std::to_string(downloaded) + "', " +
					"'" + std::to_string(uploaded) + "', " +
					"'" + std::to_string(left) + "', " +
					"'" + std::to_string(seedtime) + "', " +
					"'" + client + "', " +
					"'" + peerID + "', " +
					"'" + std::to_string(fid) + "') ON DUPLICATE KEY UPDATE downloaded = downloaded + VALUES(downloaded), uploaded = uploaded + VALUES(uploaded), seedtime = seedtime + VALUES(seedtime)";
	user->updateStats(downloaded,uploaded);
}

std::string Peer::remove(const std::string& peerID, const unsigned int& fid) {
	std::cout << "Removing peer " << peerID << " from torrent " << std::to_string(fid) << '\n';
	return "DELETE FROM xbt_files_users WHERE peer_id LIKE '"
		+ peerID
		+ "' AND fid = "
		+ std::to_string(fid);
}

bool Peer::timedOut(const long long &now) {
	std::cout << "A PEER TIMED OUT\n";
	return (now - lastUpdate > Config::getInt("timeout"));
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <unistd.h>
#include <dirent.h>
#include <fstream>
#include <sstream>
#include <queue>
#include <errno>
#include "omp.h"

// Contains the various options the user can pass ptgz.
struct Settings {
	Settings(): extract(),
				compress(),
   				verbose(),
				keep(),
				output() {}
	bool extract;
	bool compress;
	bool verbose;
	bool keep;
	bool output;
	std::string name;
};

// Checks if the user asks for help.
// Provides usage information to the user.
// Parameters: argc (int) number of cli arguments.
// 			   argv (char *[]) user provided arguments.
void helpCheck(int argc, char *argv[]) {
	if (argc == 1) {
		std::cout << "ERROR: ptgz was passed no parameters. \"ptgz -h\" for help." << std::endl;
		exit(0);
	}

	if (argv[1] == std::string("-h") || argv[1] == std::string("--help")) {
		std::cout << "\nptgz - Parallel Tar GZ by Ryan Chui (2017)\n" << std::endl;
		std::cout << "    ptgz is a custom multi-threaded C++ file archiving utility to quickly bundle millions of files in \n";
		std::cout << "    terrabyte sized directories into a single file. ptgz was developed at the National Center for \n";
		std::cout << "    Supercomputing Applications.\n" << std::endl;
		std::cout << "    Usage:\n";
		std::cout << "    If you are compressing, your current working directory should be parent directory of all directories you\n";
		std::cout << "    want to archive. If you are extracting, your current working directory should be the same as your archive.\n" << std::endl;
		std::cout << "    ptgz [-c|-k|-v|-x] <archive>\n" << std::endl;
		std::cout << "    Modes:\n";
		std::cout << "    -c    Compression           ptgz will perform file compression. The current directory and all of it's\n";
		std::cout << "                                children will be archived and added to a single tarball. <archive> will be \n";
		std::cout << "                                prefix of the ptgz archive created.\n" << std::endl;
		std::cout << "    -k    Keep Archive          ptgz will not delete the ptgz archive it has been passed to extract. \"-x\" \n";
		std::cout << "                                must also be used to use this option.\n" << std::endl;
		std::cout << "    -v    Enable Verbose        ptgz will print the commands as they are called to STDOUT\n" << std::endl;
		std::cout << "    -x    Extraction            ptgz will perform file extraction from an archive. The passed ptgz archive\n";
		std::cout << "                                will be unpacked and split into its component files. <archive> should be the\n";
		std::cout << "                                the name of the archive to extract." << std::endl;
		exit(0);
	}
}

// Gets the parameters passed by the user and stores them.
// Parameters: argc (int) number of cli arguments.
// 			   argv (char *[]) user provided arguments.
// 			   instance (Settings *) user argument storage.
void getSettings(int argc, char *argv[], Settings *instance) {
	// Get all passed arguments
	std::queue<std::string> settings;
	for (int i = 1; i < argc; ++i) {
		settings.push(argv[i]);
	}

	// Continue to check until there are no more passed arguments.
	while (!settings.empty()) {
		std::string arg = settings.front();

		if (arg == "-x") {
			if ((*instance).compress) {
				std::cout << "ERROR: ptgz cannot both compress and extract. \"ptgz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).extract = true;
		} else if (arg == "-c") {
			if ((*instance).extract) {
				std::cout << "ERROR: ptgz cannot both compress and extract. \"ptgz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).compress = true;
		} else if (arg == "-v"){
			(*instance).verbose = true;
		} else if (arg == "-o") {
			(*instance).output = true;
		} else if (arg == "-k") {
			(*instance).keep = true;
		} else {
			if (settings.size() > 1) {
				std::cout << "ERROR: ptgz was called incorrectly. \"ptgz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).output = true;
			(*instance).name = arg;
		}

		settings.pop();
	}

	if (!(*instance).output) {
		std::cout << "ERROR: No output file name given. \"ptgz -h\" for help." << std::endl;
		exit(0);
	} else if ((*instance).keep && !(*instance).extract) {
		std::cout << "ERROR: Can't use keep option without extract. \"ptgz -h\" for help." << std::endl;
	}
}

// Finds the number of files in the space to store.
// Parameters: numFiles (int *) number of files.
// 			   cwd (const char *) current working directory.
void findAll(int *numFiles, const char *cwd) {
	DIR *dir;
	struct dirent *ent;

	// Check if cwd is a directory
	if ((dir = opendir(cwd)) != NULL) {
		// Get all file paths within directory.
		while ((ent = readdir (dir)) != NULL) {
			std::string fileBuff = std::string(ent -> d_name);
			if (fileBuff != "." && fileBuff != "..") {
				DIR *dir2;
				std::string filePath = std::string(cwd) + "/" + fileBuff;
				// Check if file path is a directory.
				if ((dir2 = opendir(filePath.c_str())) != NULL) {
					closedir(dir2);
					findAll(numFiles, filePath.c_str());
				} else {
					*numFiles += 1;
				}
			}
		}
		closedir(dir);
	}
}

// Gets the paths for all files in the space to store.
// Parameters: filePaths (std::vector<std::string> *) holder for all file paths.
// 			   cwd (const char *) current working directory.
// 			   rootPath (std::string) path from the root of the directory to be stored.
void getPaths(std::vector<std::string> *filePaths, const char *cwd, std::string rootPath) {
	DIR *dir;
	struct dirent *ent;

	// Check if cwd is a directory
	if ((dir = opendir(cwd)) != NULL) {
		// Get all file paths within directory.
		while ((ent = readdir (dir)) != NULL) {
			std::string fileBuff = std::string(ent -> d_name);
			if (fileBuff != "." && fileBuff != "..") {
				DIR *dir2;
				std::string filePath = std::string(cwd) + "/" + fileBuff;
				// Check if file path is a directory.
				if ((dir2 = opendir(filePath.c_str())) != NULL) {
					closedir(dir2);
					getPaths(filePaths, filePath.c_str(), rootPath + fileBuff + "/");
				} else {
					filePaths->push_back(rootPath + fileBuff);
				}
			}
		}
		closedir(dir);
	}
}

// Divides files into blocks.
// Compresses each block into a single file.
// Combines all compressed blocks into a single file.
// Removes temporary blocks and header files.
// Parameters: filePaths (std::vector<std::string> *) holder for all file paths.
// 			   name (std::string) user given name for storage file.
// 			   verbose (bool) user option for verbose output.
void compression(std::vector<std::string> *filePaths, std::string name, bool verbose) {
	std::random_shuffle(filePaths->begin(), filePaths->end());
	unsigned long long int filePathSize = filePaths->size();
	unsigned long long int blockSize = (filePathSize / (omp_get_max_threads() * 10)) + 1;
	std::vector<std::string> *tarNames = new std::vector<std::string>(filePathSize / blockSize + 1);

	// Gzips the blocks of files into a single compressed file
	#pragma omp parallel for schedule(dynamic)
	for (int i = 0; i < omp_get_max_threads() * 10; ++i) {
		unsigned long long int start = blockSize * i;
		if (start < filePathSize) {
			// Store the name of each file for a block owned by each thread.
			// Each thread will use the file to tar and gzip compress their block.
			std::ofstream tmp;
			tmp.open(std::to_string(i) + "." + name + ".ptgz.tmp", std::ios_base::app);
			std::string gzCommand = "GZIP=-1 tar -cz -T " + std::to_string(i) + "." + name + ".ptgz.tmp -f " + std::to_string(i) + "." + name + ".tar.gz";
			for (unsigned long long int j = start; j < std::min(start + blockSize, filePathSize); ++j) {
				tmp << filePaths->at(j) + "\n";
			}

			if (verbose) {
				std::cout << gzCommand + "\n";
			}

			tmp.close();
			system(gzCommand.c_str());
			tarNames->at(i) = std::to_string(i) + "." + name + ".tar.gz";
		}
	}

	// Combines gzipped blocks together into a single tarball.
	// Write tarball names into an idx file for extraction.
	std::ofstream idx, tmp;
	idx.open(name + ".ptgz.idx", std::ios_base::app);
	std::string tarCommand = "tar -c -T " + name + ".ptgz.idx -f " + name + ".ptgz.tar";
	for (unsigned long long int i = 0; i < tarNames->size(); ++i) {
		idx << tarNames->at(i) + "\n";
	}
	idx << name + ".ptgz.idx" + "\n";
	idx.close();

	if (verbose) {
		std::cout << tarCommand + "\n";
	}

	system(tarCommand.c_str());

	// Removes all temporary blocks and idx file.
	#pragma omp parallel for schedule(static)
	for (unsigned long long int i = 0; i < tarNames->size(); ++i) {
		std::string rmCommand = tarNames->at(i);
		if (verbose) {
			std::cout << "remove(" + rmCommand + ")\n";
		}
		if (remove(rmCommand.c_str())) {
			std::cout << "ERROR: " + rmCommand + " could not be removed.\n";
		}

		rmCommand = std::to_string(i) + "." + name + ".ptgz.tmp";
		if (verbose) {
			std::cout << "remove(" + rmCommand + ")\n";
		}
		// if (remove(rmCommand.c_str())) {
			// std::cout << "ERROR: " + rmCommand + " could not be removed.\n";
		// }
	}

	std::string rmCommand;
	if (verbose) {
		std::cout << "remove(" + name + ".ptgz.idx)\n";
	}
	rmCommand = name + ".ptgz.idx";
	if (remove(rmCommand.c_str())) {
		std::cout << "ERROR: " + rmCommand + " could not be removed.\n";
	}

	tarNames->clear();
	delete(tarNames);
}

// Unpacks the archive.
// Reads in all the files from the index file.
// Unpacks each file.
// Deletes all temporary file blocks and header files.
// Parameters: filePaths (std::vector<std::string> *) holder for all file paths.
// 			   name (std::string) name of ptgz archive file.
// 			   verbose (bool) user option for verbose output.
// 			   keep (bool) user option for keeping ptgz archive.
void extraction(std::vector<std::string> *filePaths, std::string name, bool verbose, bool keep) {
	// Unpack the 1st layer tarball
	std::string exCommand = "tar xf " + name;
	if (verbose) {
		std::cout << exCommand + "\n";
	}
	system(exCommand.c_str());

	// Get the name from the name of the 1st layer tarball
	for (int i = 0; i < 9; ++i) {
		name.pop_back();
	}

	// Read in all tar.gz files form the ptgz.idx file
	// Delete the ptgz.idx file
	std::ifstream idx;
	std::string line;
	idx.open(name + ".ptgz.idx", std::ios_base::in);
	while (std::getline(idx, line)) {
		filePaths->push_back(line);
	}
	idx.close();
	std::string idxRmCommand = filePaths->back();
	if (remove(idxRmCommand.c_str())) {
		std::cout << "ERROR: " + idxRmCommand + " could not be removed.\n";
	}
	filePaths->pop_back();

	// Unpack each tar.gz file
	#pragma omp parallel for schedule(dynamic)
	for (int i = 0; i < filePaths->size(); ++i) {
		std::string gzCommand = "tar xzf " + filePaths->at(i);
		if (verbose) {
			std::cout << gzCommand + "\n";
		}
		system(gzCommand.c_str());
		std::cout << std::errno(errno) << std::endl;
	}

	// Delete each tar.gz file
	#pragma omp parallel for schedule(static)
	for (int i = 0; i < filePaths->size(); ++i) {
		std::string gzRmCommand = filePaths->at(i);
		if (verbose) {
			std::cout << "remove(" + gzRmCommand + ")\n";
		}
		// if (remove(gzRmCommand.c_str())) {
			// std::cout << "ERROR: " + gzRmCommand + " could not be removed.\n";
		// }
	}

	// Decided whether or not to keep the ptgz.tar archive
	if (!keep) {
		std::string tarRmCommand = name + ".ptgz.tar";
		if (verbose) {
			std::cout << "remove(" + tarRmCommand + ")\n";
		}
		if (remove(tarRmCommand.c_str())) {
			std::cout << "ERROR: " + tarRmCommand + " could not be removed.\n";
		}
	}
}

char cwd [PATH_MAX];

// Checks to see if the user asks for help.
// Gathers the user provided settings for ptgz.
// Finds the number of files that need to be stored.
// Gathers the file paths of all files to be stored.
// Either compresses the files or extracts the ptgz.tar archive.
int main(int argc, char *argv[]) {
	Settings *instance = new Settings;
	int *numFiles = new int(0);
	std::vector<std::string> *filePaths = new std::vector<std::string>();

	helpCheck(argc, argv);
	getSettings(argc, argv, instance);
	getcwd(cwd, PATH_MAX);

	if ((*instance).compress) {
		findAll(numFiles, cwd);
		getPaths(filePaths, cwd, "");
		compression(filePaths, (*instance).name, (*instance).verbose);
	} else {
		extraction(filePaths, (*instance).name, (*instance).verbose, (*instance).keep);
	}

	delete(instance);
	delete(numFiles);
	filePaths->clear();
	delete(filePaths);
	return 0;
}
<commit_msg>Fixed include<commit_after>#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <unistd.h>
#include <dirent.h>
#include <fstream>
#include <sstream>
#include <queue>
#include <cerrno>
#include "omp.h"

// Contains the various options the user can pass ptgz.
struct Settings {
	Settings(): extract(),
				compress(),
   				verbose(),
				keep(),
				output() {}
	bool extract;
	bool compress;
	bool verbose;
	bool keep;
	bool output;
	std::string name;
};

// Checks if the user asks for help.
// Provides usage information to the user.
// Parameters: argc (int) number of cli arguments.
// 			   argv (char *[]) user provided arguments.
void helpCheck(int argc, char *argv[]) {
	if (argc == 1) {
		std::cout << "ERROR: ptgz was passed no parameters. \"ptgz -h\" for help." << std::endl;
		exit(0);
	}

	if (argv[1] == std::string("-h") || argv[1] == std::string("--help")) {
		std::cout << "\nptgz - Parallel Tar GZ by Ryan Chui (2017)\n" << std::endl;
		std::cout << "    ptgz is a custom multi-threaded C++ file archiving utility to quickly bundle millions of files in \n";
		std::cout << "    terrabyte sized directories into a single file. ptgz was developed at the National Center for \n";
		std::cout << "    Supercomputing Applications.\n" << std::endl;
		std::cout << "    Usage:\n";
		std::cout << "    If you are compressing, your current working directory should be parent directory of all directories you\n";
		std::cout << "    want to archive. If you are extracting, your current working directory should be the same as your archive.\n" << std::endl;
		std::cout << "    ptgz [-c|-k|-v|-x] <archive>\n" << std::endl;
		std::cout << "    Modes:\n";
		std::cout << "    -c    Compression           ptgz will perform file compression. The current directory and all of it's\n";
		std::cout << "                                children will be archived and added to a single tarball. <archive> will be \n";
		std::cout << "                                prefix of the ptgz archive created.\n" << std::endl;
		std::cout << "    -k    Keep Archive          ptgz will not delete the ptgz archive it has been passed to extract. \"-x\" \n";
		std::cout << "                                must also be used to use this option.\n" << std::endl;
		std::cout << "    -v    Enable Verbose        ptgz will print the commands as they are called to STDOUT\n" << std::endl;
		std::cout << "    -x    Extraction            ptgz will perform file extraction from an archive. The passed ptgz archive\n";
		std::cout << "                                will be unpacked and split into its component files. <archive> should be the\n";
		std::cout << "                                the name of the archive to extract." << std::endl;
		exit(0);
	}
}

// Gets the parameters passed by the user and stores them.
// Parameters: argc (int) number of cli arguments.
// 			   argv (char *[]) user provided arguments.
// 			   instance (Settings *) user argument storage.
void getSettings(int argc, char *argv[], Settings *instance) {
	// Get all passed arguments
	std::queue<std::string> settings;
	for (int i = 1; i < argc; ++i) {
		settings.push(argv[i]);
	}

	// Continue to check until there are no more passed arguments.
	while (!settings.empty()) {
		std::string arg = settings.front();

		if (arg == "-x") {
			if ((*instance).compress) {
				std::cout << "ERROR: ptgz cannot both compress and extract. \"ptgz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).extract = true;
		} else if (arg == "-c") {
			if ((*instance).extract) {
				std::cout << "ERROR: ptgz cannot both compress and extract. \"ptgz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).compress = true;
		} else if (arg == "-v"){
			(*instance).verbose = true;
		} else if (arg == "-o") {
			(*instance).output = true;
		} else if (arg == "-k") {
			(*instance).keep = true;
		} else {
			if (settings.size() > 1) {
				std::cout << "ERROR: ptgz was called incorrectly. \"ptgz -h\" for help." << std::endl;
				exit(0);
			}
			(*instance).output = true;
			(*instance).name = arg;
		}

		settings.pop();
	}

	if (!(*instance).output) {
		std::cout << "ERROR: No output file name given. \"ptgz -h\" for help." << std::endl;
		exit(0);
	} else if ((*instance).keep && !(*instance).extract) {
		std::cout << "ERROR: Can't use keep option without extract. \"ptgz -h\" for help." << std::endl;
	}
}

// Finds the number of files in the space to store.
// Parameters: numFiles (int *) number of files.
// 			   cwd (const char *) current working directory.
void findAll(int *numFiles, const char *cwd) {
	DIR *dir;
	struct dirent *ent;

	// Check if cwd is a directory
	if ((dir = opendir(cwd)) != NULL) {
		// Get all file paths within directory.
		while ((ent = readdir (dir)) != NULL) {
			std::string fileBuff = std::string(ent -> d_name);
			if (fileBuff != "." && fileBuff != "..") {
				DIR *dir2;
				std::string filePath = std::string(cwd) + "/" + fileBuff;
				// Check if file path is a directory.
				if ((dir2 = opendir(filePath.c_str())) != NULL) {
					closedir(dir2);
					findAll(numFiles, filePath.c_str());
				} else {
					*numFiles += 1;
				}
			}
		}
		closedir(dir);
	}
}

// Gets the paths for all files in the space to store.
// Parameters: filePaths (std::vector<std::string> *) holder for all file paths.
// 			   cwd (const char *) current working directory.
// 			   rootPath (std::string) path from the root of the directory to be stored.
void getPaths(std::vector<std::string> *filePaths, const char *cwd, std::string rootPath) {
	DIR *dir;
	struct dirent *ent;

	// Check if cwd is a directory
	if ((dir = opendir(cwd)) != NULL) {
		// Get all file paths within directory.
		while ((ent = readdir (dir)) != NULL) {
			std::string fileBuff = std::string(ent -> d_name);
			if (fileBuff != "." && fileBuff != "..") {
				DIR *dir2;
				std::string filePath = std::string(cwd) + "/" + fileBuff;
				// Check if file path is a directory.
				if ((dir2 = opendir(filePath.c_str())) != NULL) {
					closedir(dir2);
					getPaths(filePaths, filePath.c_str(), rootPath + fileBuff + "/");
				} else {
					filePaths->push_back(rootPath + fileBuff);
				}
			}
		}
		closedir(dir);
	}
}

// Divides files into blocks.
// Compresses each block into a single file.
// Combines all compressed blocks into a single file.
// Removes temporary blocks and header files.
// Parameters: filePaths (std::vector<std::string> *) holder for all file paths.
// 			   name (std::string) user given name for storage file.
// 			   verbose (bool) user option for verbose output.
void compression(std::vector<std::string> *filePaths, std::string name, bool verbose) {
	std::random_shuffle(filePaths->begin(), filePaths->end());
	unsigned long long int filePathSize = filePaths->size();
	unsigned long long int blockSize = (filePathSize / (omp_get_max_threads() * 10)) + 1;
	std::vector<std::string> *tarNames = new std::vector<std::string>(filePathSize / blockSize + 1);

	// Gzips the blocks of files into a single compressed file
	#pragma omp parallel for schedule(dynamic)
	for (int i = 0; i < omp_get_max_threads() * 10; ++i) {
		unsigned long long int start = blockSize * i;
		if (start < filePathSize) {
			// Store the name of each file for a block owned by each thread.
			// Each thread will use the file to tar and gzip compress their block.
			std::ofstream tmp;
			tmp.open(std::to_string(i) + "." + name + ".ptgz.tmp", std::ios_base::app);
			std::string gzCommand = "GZIP=-1 tar -cz -T " + std::to_string(i) + "." + name + ".ptgz.tmp -f " + std::to_string(i) + "." + name + ".tar.gz";
			for (unsigned long long int j = start; j < std::min(start + blockSize, filePathSize); ++j) {
				tmp << filePaths->at(j) + "\n";
			}

			if (verbose) {
				std::cout << gzCommand + "\n";
			}

			tmp.close();
			system(gzCommand.c_str());
			tarNames->at(i) = std::to_string(i) + "." + name + ".tar.gz";
		}
	}

	// Combines gzipped blocks together into a single tarball.
	// Write tarball names into an idx file for extraction.
	std::ofstream idx, tmp;
	idx.open(name + ".ptgz.idx", std::ios_base::app);
	std::string tarCommand = "tar -c -T " + name + ".ptgz.idx -f " + name + ".ptgz.tar";
	for (unsigned long long int i = 0; i < tarNames->size(); ++i) {
		idx << tarNames->at(i) + "\n";
	}
	idx << name + ".ptgz.idx" + "\n";
	idx.close();

	if (verbose) {
		std::cout << tarCommand + "\n";
	}

	system(tarCommand.c_str());

	// Removes all temporary blocks and idx file.
	#pragma omp parallel for schedule(static)
	for (unsigned long long int i = 0; i < tarNames->size(); ++i) {
		std::string rmCommand = tarNames->at(i);
		if (verbose) {
			std::cout << "remove(" + rmCommand + ")\n";
		}
		if (remove(rmCommand.c_str())) {
			std::cout << "ERROR: " + rmCommand + " could not be removed.\n";
		}

		rmCommand = std::to_string(i) + "." + name + ".ptgz.tmp";
		if (verbose) {
			std::cout << "remove(" + rmCommand + ")\n";
		}
		// if (remove(rmCommand.c_str())) {
			// std::cout << "ERROR: " + rmCommand + " could not be removed.\n";
		// }
	}

	std::string rmCommand;
	if (verbose) {
		std::cout << "remove(" + name + ".ptgz.idx)\n";
	}
	rmCommand = name + ".ptgz.idx";
	if (remove(rmCommand.c_str())) {
		std::cout << "ERROR: " + rmCommand + " could not be removed.\n";
	}

	tarNames->clear();
	delete(tarNames);
}

// Unpacks the archive.
// Reads in all the files from the index file.
// Unpacks each file.
// Deletes all temporary file blocks and header files.
// Parameters: filePaths (std::vector<std::string> *) holder for all file paths.
// 			   name (std::string) name of ptgz archive file.
// 			   verbose (bool) user option for verbose output.
// 			   keep (bool) user option for keeping ptgz archive.
void extraction(std::vector<std::string> *filePaths, std::string name, bool verbose, bool keep) {
	// Unpack the 1st layer tarball
	std::string exCommand = "tar xf " + name;
	if (verbose) {
		std::cout << exCommand + "\n";
	}
	system(exCommand.c_str());

	// Get the name from the name of the 1st layer tarball
	for (int i = 0; i < 9; ++i) {
		name.pop_back();
	}

	// Read in all tar.gz files form the ptgz.idx file
	// Delete the ptgz.idx file
	std::ifstream idx;
	std::string line;
	idx.open(name + ".ptgz.idx", std::ios_base::in);
	while (std::getline(idx, line)) {
		filePaths->push_back(line);
	}
	idx.close();
	std::string idxRmCommand = filePaths->back();
	if (remove(idxRmCommand.c_str())) {
		std::cout << "ERROR: " + idxRmCommand + " could not be removed.\n";
	}
	filePaths->pop_back();

	// Unpack each tar.gz file
	#pragma omp parallel for schedule(dynamic)
	for (int i = 0; i < filePaths->size(); ++i) {
		std::string gzCommand = "tar xzf " + filePaths->at(i);
		if (verbose) {
			std::cout << gzCommand + "\n";
		}
		system(gzCommand.c_str());
		std::cout << std::errno(errno) << std::endl;
	}

	// Delete each tar.gz file
	#pragma omp parallel for schedule(static)
	for (int i = 0; i < filePaths->size(); ++i) {
		std::string gzRmCommand = filePaths->at(i);
		if (verbose) {
			std::cout << "remove(" + gzRmCommand + ")\n";
		}
		// if (remove(gzRmCommand.c_str())) {
			// std::cout << "ERROR: " + gzRmCommand + " could not be removed.\n";
		// }
	}

	// Decided whether or not to keep the ptgz.tar archive
	if (!keep) {
		std::string tarRmCommand = name + ".ptgz.tar";
		if (verbose) {
			std::cout << "remove(" + tarRmCommand + ")\n";
		}
		if (remove(tarRmCommand.c_str())) {
			std::cout << "ERROR: " + tarRmCommand + " could not be removed.\n";
		}
	}
}

char cwd [PATH_MAX];

// Checks to see if the user asks for help.
// Gathers the user provided settings for ptgz.
// Finds the number of files that need to be stored.
// Gathers the file paths of all files to be stored.
// Either compresses the files or extracts the ptgz.tar archive.
int main(int argc, char *argv[]) {
	Settings *instance = new Settings;
	int *numFiles = new int(0);
	std::vector<std::string> *filePaths = new std::vector<std::string>();

	helpCheck(argc, argv);
	getSettings(argc, argv, instance);
	getcwd(cwd, PATH_MAX);

	if ((*instance).compress) {
		findAll(numFiles, cwd);
		getPaths(filePaths, cwd, "");
		compression(filePaths, (*instance).name, (*instance).verbose);
	} else {
		extraction(filePaths, (*instance).name, (*instance).verbose, (*instance).keep);
	}

	delete(instance);
	delete(numFiles);
	filePaths->clear();
	delete(filePaths);
	return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 Plenluno All rights reserved.

#include <assert.h>
#include <unistd.h>
#include <libj/string_buffer.h>

#include "libnode/path.h"

namespace libj {
namespace node {
namespace path {

String::CPtr normalize(String::CPtr path) {
    static const String::CPtr empty = String::create();
    static const String::CPtr current = String::create(".");
    static const String::CPtr parent = String::create("..");

    if (!path) return empty;

    Boolean absolute = false;
    Boolean endsWithSep = false;
    JsArray::Ptr dirs = JsArray::create();
    Size len = path->length();
    for (Size i = 0; i < len;) {
        Size idx = path->indexOf('/', i);
        if (idx == 0) {
            absolute = true;
        } else if (idx != i) {
            String::CPtr dir;
            if (idx == NO_POS) {
                dir = path->substring(i);
            } else {
                dir = path->substring(i, idx);
            }
            if (dir->compareTo(parent) == 0) {
                Size numDirs = dirs->size();
                if (numDirs > 0 &&
                    dirs->get(numDirs - 1).compareTo(parent) != 0) {
                    dirs->remove(numDirs - 1);
                } else {
                    dirs->add(dir);
                }
            } else if (dir->compareTo(current) != 0) {
                dirs->add(dir);
            }
        }

        if (idx == NO_POS) {
            endsWithSep = false;
            i = len;
        } else {
            endsWithSep = true;
            i = idx + 1;
        }

    }

    StringBuffer::Ptr normal = StringBuffer::create();
    if (absolute)
        normal->append(sep());
    Size numDirs = dirs->size();
    for (Size i = 0; i < numDirs; i++) {
        if (i) normal->append(sep());
        normal->append(dirs->get(i));
    }
    if (numDirs > 0 && endsWithSep)
        normal->append(sep());
    if (normal->length() == 0) {
        return current;
    } else {
        return normal->toString();
    }
}

String::CPtr join(JsArray::CPtr paths) {
    static const String::CPtr current = String::create(".");

    if (!paths) return current;

    StringBuffer::Ptr joined = StringBuffer::create();
    Size len = paths->length();
    Boolean first = true;
    for (Size i = 0; i < len; i++) {
        String::CPtr path = toCPtr<String>(paths->get(i));
        if (path) {
            if (first) {
                first = false;
            } else {
                joined->append(sep());
            }
            joined->append(path);
        }
    }
    return normalize(joined->toString());
}

static String::CPtr getCwd() {
    const Size kMax = 8192;
    char dir[kMax];
    getcwd(dir, kMax);
    return String::create(dir);
}

String::CPtr resolve(JsArray::CPtr paths) {
    if (!paths) return getCwd();

    StringBuffer::Ptr resolved = StringBuffer::create();
    resolved->append(getCwd());
    Size len = paths->length();
    for (Size i = 0; i < len; i++) {
        String::CPtr path = toCPtr<String>(paths->get(i));
        if (path) {
            if (path->startsWith(sep())) {
                resolved = StringBuffer::create();
            } else {
                resolved->append(sep());
            }
            resolved->append(path);
        }
    }
    return normalize(resolved->toString());
}

String::CPtr relative(String::CPtr from, String::CPtr to) {
    // TODO(plenluno): implement
    return String::create();
}

String::CPtr dirname(String::CPtr path) {
    static const String::CPtr current = String::create(".");

    if (!path) return current;

    String::CPtr base = basename(path);
    Size baseLen = base->length();
    Size pathLen = path->length();
    if (baseLen == pathLen) {
        return current;
    } else {
        Size sepPos = pathLen - baseLen - 1;
        assert(path->charAt(sepPos) == '/');
        if (sepPos) {
            return path->substring(0, sepPos);
        } else { // path[0] is '/'
            return sep();
        }
    }
}

String::CPtr basename(String::CPtr path) {
    static const String::CPtr empty = String::create();
    static const String::CPtr doubleSep = sep()->concat(sep());

    if (!path) return empty;
    if (path->compareTo(sep()) == 0) return empty;
    if (path->compareTo(doubleSep) == 0) return empty;

    Size lastIndex;
    Size len = path->length();
    if (path->endsWith(sep())) {
        Size from = len - sep()->length() - 1;
        lastIndex = path->lastIndexOf(sep(), from);
    } else {
        lastIndex = path->lastIndexOf(sep());
    }
    String::CPtr base;
    if (lastIndex == NO_POS) {
        base = path;
    } else {
        base = path->substring(lastIndex + 1);
    }
    return base;
}

String::CPtr extname(String::CPtr path) {
    static const String::CPtr empty = String::create();

    if (!path) return empty;

    String::CPtr base = basename(path);
    if (base->endsWith(sep())) return empty;

    Size lastIndex = NO_POS;
    if (base->length() > 1)
        lastIndex = base->lastIndexOf('.');
    String::CPtr ext;
    if (lastIndex == NO_POS) {
        ext = empty;
    } else {
        ext = base->substring(lastIndex);
    }
    return ext;
}

String::CPtr sep() {
    static const String::CPtr separator = String::create("/");
    return separator;
}

}  // namespace path
}  // namespace node
}  // namespace libj
<commit_msg>modify for cpplint<commit_after>// Copyright (c) 2012 Plenluno All rights reserved.

#include <assert.h>
#include <unistd.h>
#include <libj/string_buffer.h>

#include "libnode/path.h"

namespace libj {
namespace node {
namespace path {

String::CPtr normalize(String::CPtr path) {
    static const String::CPtr empty = String::create();
    static const String::CPtr current = String::create(".");
    static const String::CPtr parent = String::create("..");

    if (!path) return empty;

    Boolean absolute = false;
    Boolean endsWithSep = false;
    JsArray::Ptr dirs = JsArray::create();
    Size len = path->length();
    for (Size i = 0; i < len;) {
        Size idx = path->indexOf('/', i);
        if (idx == 0) {
            absolute = true;
        } else if (idx != i) {
            String::CPtr dir;
            if (idx == NO_POS) {
                dir = path->substring(i);
            } else {
                dir = path->substring(i, idx);
            }
            if (dir->compareTo(parent) == 0) {
                Size numDirs = dirs->size();
                if (numDirs > 0 &&
                    dirs->get(numDirs - 1).compareTo(parent) != 0) {
                    dirs->remove(numDirs - 1);
                } else {
                    dirs->add(dir);
                }
            } else if (dir->compareTo(current) != 0) {
                dirs->add(dir);
            }
        }

        if (idx == NO_POS) {
            endsWithSep = false;
            i = len;
        } else {
            endsWithSep = true;
            i = idx + 1;
        }
    }

    StringBuffer::Ptr normal = StringBuffer::create();
    if (absolute)
        normal->append(sep());
    Size numDirs = dirs->size();
    for (Size i = 0; i < numDirs; i++) {
        if (i) normal->append(sep());
        normal->append(dirs->get(i));
    }
    if (numDirs > 0 && endsWithSep)
        normal->append(sep());
    if (normal->length() == 0) {
        return current;
    } else {
        return normal->toString();
    }
}

String::CPtr join(JsArray::CPtr paths) {
    static const String::CPtr current = String::create(".");

    if (!paths) return current;

    StringBuffer::Ptr joined = StringBuffer::create();
    Size len = paths->length();
    Boolean first = true;
    for (Size i = 0; i < len; i++) {
        String::CPtr path = toCPtr<String>(paths->get(i));
        if (path) {
            if (first) {
                first = false;
            } else {
                joined->append(sep());
            }
            joined->append(path);
        }
    }
    return normalize(joined->toString());
}

static String::CPtr getCwd() {
    const Size kMax = 8192;
    char dir[kMax];
    getcwd(dir, kMax);
    return String::create(dir);
}

String::CPtr resolve(JsArray::CPtr paths) {
    if (!paths) return getCwd();

    StringBuffer::Ptr resolved = StringBuffer::create();
    resolved->append(getCwd());
    Size len = paths->length();
    for (Size i = 0; i < len; i++) {
        String::CPtr path = toCPtr<String>(paths->get(i));
        if (path) {
            if (path->startsWith(sep())) {
                resolved = StringBuffer::create();
            } else {
                resolved->append(sep());
            }
            resolved->append(path);
        }
    }
    return normalize(resolved->toString());
}

String::CPtr relative(String::CPtr from, String::CPtr to) {
    // TODO(plenluno): implement
    return String::create();
}

String::CPtr dirname(String::CPtr path) {
    static const String::CPtr current = String::create(".");

    if (!path) return current;

    String::CPtr base = basename(path);
    Size baseLen = base->length();
    Size pathLen = path->length();
    if (baseLen == pathLen) {
        return current;
    } else {
        Size sepPos = pathLen - baseLen - 1;
        assert(path->charAt(sepPos) == '/');
        if (sepPos) {
            return path->substring(0, sepPos);
        } else {  // path[0] is '/'
            return sep();
        }
    }
}

String::CPtr basename(String::CPtr path) {
    static const String::CPtr empty = String::create();
    static const String::CPtr doubleSep = sep()->concat(sep());

    if (!path) return empty;
    if (path->compareTo(sep()) == 0) return empty;
    if (path->compareTo(doubleSep) == 0) return empty;

    Size lastIndex;
    Size len = path->length();
    if (path->endsWith(sep())) {
        Size from = len - sep()->length() - 1;
        lastIndex = path->lastIndexOf(sep(), from);
    } else {
        lastIndex = path->lastIndexOf(sep());
    }
    String::CPtr base;
    if (lastIndex == NO_POS) {
        base = path;
    } else {
        base = path->substring(lastIndex + 1);
    }
    return base;
}

String::CPtr extname(String::CPtr path) {
    static const String::CPtr empty = String::create();

    if (!path) return empty;

    String::CPtr base = basename(path);
    if (base->endsWith(sep())) return empty;

    Size lastIndex = NO_POS;
    if (base->length() > 1)
        lastIndex = base->lastIndexOf('.');
    String::CPtr ext;
    if (lastIndex == NO_POS) {
        ext = empty;
    } else {
        ext = base->substring(lastIndex);
    }
    return ext;
}

String::CPtr sep() {
    static const String::CPtr separator = String::create("/");
    return separator;
}

}  // namespace path
}  // namespace node
}  // namespace libj
<|endoftext|>


<commit_before>
#include<iostream>
#include "petsc.h"
#include "geom.hpp"

int main(int argc,char **args)
{
  PetscErrorCode ierr;
  int nid,np;
  int N,numThetan,nTau;
  polygon_t rectangle;
  double tol = 1e-2;
  double omega[4] = {-2, 2, -2, 2};
  double sparsity = 0.1;
  int m[2];
  PetscInt Istart,Iend;
  linestring_t line;
  std::vector<point_t> intersect_pts;
  detector_geometry det;
  Mat A;

  // Initialize PETSc and MPI
  ierr = PetscInitialize(&argc,&args,(char*)0,NULL); CHKERRQ(ierr);
  /* Get core's id */
  ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&nid); CHKERRQ(ierr);
  /* Get number of processors */
  ierr = MPI_Comm_size(PETSC_COMM_WORLD,&np); CHKERRQ(ierr);

  N = 30;
  numThetan = 60;
  nTau = (int)ceil(sqrt(2*N*N));

  m[0] = N; m[1] = N;

  ierr = MatCreate(PETSC_COMM_WORLD,&A); CHKERRQ(ierr);
  ierr = MatSetType(A,MATMPIAIJ); CHKERRQ(ierr);
  ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,nTau*numThetan,m[0]*m[1]); CHKERRQ(ierr);
  ierr = MatSetFromOptions(A); CHKERRQ(ierr);
  ierr = MatMPIAIJSetPreallocation(A,sparsity*nTau*numThetan,NULL,sparsity*m[0]*m[1],NULL); CHKERRQ(ierr);
  det = detector_geometry(omega,tol,numThetan,m,nTau);

  ierr = MatGetOwnershipRange(A,&Istart,&Iend); CHKERRQ(ierr);

  for (int i=Istart;i<Iend;i++){
    //i' = (j-1)*numThetan + i where j=tau and i=theta
    int tau_idx   = i/numThetan;
    int theta_idx = i%numThetan;
    setMatrixElements(tau_idx, theta_idx, det, A);
    // intersectionSet(tau_idx, theta_idx, det);
  }
  MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
  MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);

  ierr = PetscFinalize(); CHKERRQ(ierr);
  return 0;
}
<commit_msg>Add TAO solving of synthetic data. Code needs cleaning and restructuring.<commit_after>
#include<iostream>
#include "petsctao.h"
#include "geom.hpp"
#include <fstream>
void read_synthetic_data(Mat *A,Vec *sample,Vec *answer,int m[2],int *nTau,int numThetan);
PetscErrorCode FormFunctionGradient(Tao tao,Vec X,PetscReal *f, Vec G,void *ptr);
Mat A;
Vec data;
int main(int argc,char **args)
{
  int nid,np;
  int N,numThetan,nTau;
  polygon_t rectangle;
  double tol = 1e-2;
  double omega[4] = {-2, 2, -2, 2};
  double sparsity = 0.05;
  int m[2];
  PetscInt Istart,Iend;
  linestring_t line;
  std::vector<point_t> intersect_pts;
  detector_geometry det;
  int synthetic_data = 1;
  Vec sample, rec_sample;
  Tao tao;

  // Initialize PETSc and MPI
  PetscInitialize(&argc,&args,(char*)0,NULL);
  /* Get core's id */
  MPI_Comm_rank(PETSC_COMM_WORLD,&nid);
  /* Get number of processors */
  MPI_Comm_size(PETSC_COMM_WORLD,&np);

  N = 300;
  numThetan = 160;
  nTau = (int)ceil(sqrt(2*N*N));
  m[0] = N; m[1] = N;

  if (synthetic_data) {
    numThetan = 130;
    read_synthetic_data(&A,&sample,&data,m,&nTau,numThetan);
  } else {
    MatCreate(PETSC_COMM_WORLD,&A);
    MatSetType(A,MATMPIAIJ);
    MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,nTau*numThetan,m[0]*m[1]);
    MatSetFromOptions(A);
    MatMPIAIJSetPreallocation(A,sparsity*nTau*numThetan,NULL,sparsity*m[0]*m[1],NULL);
  }
  det = detector_geometry(omega,tol,numThetan,m,nTau);

  MatGetOwnershipRange(A,&Istart,&Iend);

  //Set up matrix
  for (int i=Istart;i<Iend;i++){
    //i' = (j-1)*numThetan + i where j=tau and i=theta
    int tau_idx   = i/numThetan;
    int theta_idx = i%numThetan;
    setMatrixElements(tau_idx, theta_idx, det, A);
  }
  MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
  MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);

  MatMult(A,sample,data);
  VecDuplicate(sample,&rec_sample);

  //Set TAO things
  TaoCreate(PETSC_COMM_SELF,&tao);
  TaoSetObjectiveAndGradientRoutine(tao,FormFunctionGradient,NULL);
  VecSet(rec_sample, 0.0);
  TaoSetInitialVector(tao,rec_sample);

  /*
   * This allows one to set the solver at runtime; i.e.
   * ./pirt -tao_type lmvm
   * or
   * ./pirt -tau_type ntr
   * etc. Some require hessians which we have not yet coded
   */
  TaoSetFromOptions(tao);
  TaoSolve(tao);

  PetscReal norm;
  VecMin(rec_sample,NULL,&norm);
  std::cout << "Min val " << norm << std::endl;
  VecMax(rec_sample,NULL,&norm);
  std::cout << "Max val " << norm << std::endl;

  //Uncomment below to print the full vector
  //VecView(rec_sample,PETSC_VIEWER_STDOUT_SELF);

  //calculate rec_sample = rec_sample + -1 * sample
  VecAXPY(rec_sample,-1.0,sample);
  VecNorm(rec_sample,NORM_2,&norm);
  std::cout << "Diff norm: " << norm << std::endl;
  MatNorm(A,NORM_FROBENIUS,&norm);
  if (nid==0) std::cout << "Norm: " << norm << "\n";
  PetscFinalize();
  return 0;
}

PetscErrorCode FormFunctionGradient(Tao tao,Vec X,PetscReal *f, Vec G,void *ptr){
  Vec tmp;
  PetscReal norm;

  MatCreateVecs(A,NULL,&tmp);
  //tmp = A * X
  MatMult(A,X,tmp);

  // tmp = tmp + -1.0 * data
  VecAXPY(tmp,-1.0,data);
  VecNorm(tmp,NORM_2,&norm);
  *f = 0.5*norm*norm;

  MatMultTranspose(A,tmp,G);

  VecDestroy(&tmp);
  PetscFunctionReturn(0);
}

void read_synthetic_data(Mat *A,Vec *sample,Vec *answer,int m[2],int *nTau, int numThetan){
  std::ifstream inFile;
  PetscScalar Aij;
  PetscInt i,j,iMax,jMax;
  inFile.open("sample.dat");
  if (inFile.fail()){
    std::cout << "Error in read file\n";
    exit(0);
  }
  iMax = -1; jMax = -1;

  while (!inFile.eof()){
    inFile >> i;
    inFile >> j;
    inFile >> Aij;

    if(i>iMax) iMax = i;
    if(j>jMax) jMax = j;
  }
  m[0] = iMax; m[1] = jMax;
  *nTau = (int)ceil(sqrt(2*m[0]*m[1]));

  MatCreate(PETSC_COMM_WORLD,A);
  MatSetType(*A,MATMPIAIJ);
  MatSetSizes(*A,PETSC_DECIDE,PETSC_DECIDE,(*nTau)*numThetan,iMax*jMax);
  MatSetFromOptions(*A);
  MatMPIAIJSetPreallocation(*A,iMax*2,NULL,iMax*2,NULL);

  MatCreateVecs(*A,sample,answer);
  //Reset file to start
  inFile.clear();
  inFile.seekg(0);
  while (!inFile.eof()){
    inFile >> i;
    inFile >> j;
    inFile >> Aij;
    i = i-1; j = j-1;
    VecSetValue(*sample,i*iMax+j,Aij,INSERT_VALUES);
    if(i>iMax) iMax = i;
    if(j>jMax) jMax = j;
  }
  return;
}
<|endoftext|>