<commit_before>//
//  main.cpp
//  wpm
//
//  Created by Adawat Chanchua on 6/29/2560 BE.
//  Copyright © 2560 Adawat Chanchua. All rights reserved.
//

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Lib in the Wonderland
#include "Util.hpp"

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// C/C++ lib

#include <iostream>
#include <string>
#include <sstream>
#include <map>

using namespace std;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Rapid JSON lib

#include "rapidjson.h"
#include "document.h"

using namespace rapidjson;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Function declaration

string view(int argc, const char* argv[]);
string install(int argc, const char* argv[]);
string uninstall(int argc, const char* argv[]);
string update(int argc, const char* argv[]);
string npm(int argc, const char* argv[]);
string exec(int argc, const char* argv[]);
string help(int argc, const char* argv[]);
string version(int argc, const char* argv[]);
string run(int argc, const char* argv[]);

void showWelcomeMessage();

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Constants
const string VERSION = "0.0.0.1";
const string WONDER_MODULE = "wonder_modules";
const string WONDER_TEMP_MODULE = "wonder_modules/tmp";
const string WONDER_CONF = "wonderconf.json";

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Shared vars

map<string, void*> commandMap;
map<string, string> descMap;

void addCommand(string name, void* commandFunctionPointer, string desc) {

    commandMap.insert(pair<string, void*>(name, commandFunctionPointer));
    descMap.insert(pair<string, string>(name, desc));
}

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
int main(int argc, const char * argv[]) {

    /***********************************************
     Params order note (From argc, argv convention):
        [0] File path
        [1] command
        [2][And more] command params
     ***********************************************/

    // Show info if hitting wpm without any command
    if (argc <= 1) {

        showWelcomeMessage();
        return 0;
    }

    // Map all command
    addCommand("view",      (void*)&view,       "View package info");
    addCommand("install",   (void*)&install,    "Install package");
    addCommand("uninstall", (void*)&uninstall,  "Uninstall package");
    addCommand("update",    (void*)&update,     "Update package");
    addCommand("npm",       (void*)&npm,        "Call npm");
    addCommand("exec",      (void*)&exec,       "Run OS command");
    addCommand("help",      (void*)&help,       "Show helpful info");
    addCommand("version",   (void*)&version,    "Show wpm version");
    addCommand("run",       (void*)&run,        "Execute command(s) inside the package");

    string command = argv[1];
    string result = "";

    if (commandMap[command]) {

        void* f = commandMap[command];
        result = ((string(*)(int, const char* []))f)(argc, argv);
    }
    else {

        result = string("-wpm: ") + command + string(": command not found");
    }

    // Print out result
    cout << result << endl;

    return 0;
}

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Function implementation

string view(int argc, const char* argv[]) {

    cout << "To view something" << endl;
    return "";
}

string install(int argc, const char* argv[]) {

    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    // Execute sub command
    if (argc > 2) {

        string subCommand = argv[2];

        // Clean if need
        if (subCommand.compare("-clean") == 0) {

            execute(string("rm -rf " + string(WONDER_MODULE)));
        }
    }

    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    // Create wonder_modules directory if NOT exist
    execute(string("mkdir -p ") + string(WONDER_MODULE));

    // Read wonderconf.json
    string wonderConfStr = execute(string("cat ") + string(WONDER_CONF));

    // Parse to JSON document
    Document wonderConf;
    wonderConf.Parse<0>(wonderConfStr.c_str());

    string name = getJsonString(wonderConf, "name");
    string description = getJsonString(wonderConf, "description");
    string host = getJsonString(wonderConf, "host");
    string version = getJsonString(wonderConf, "version");

    // Get dependency objects
    Value& dependencies = wonderConf["dependencies"];

    rapidjson::Value::MemberIterator depIt;
    for (depIt = dependencies.MemberBegin(); depIt != dependencies.MemberEnd(); ++depIt) {

        // Get OS name
        std::string osName = depIt->name.GetString();

        cout << "osName: " << osName << endl;

        // Get OS object
        Value& osDep = dependencies[osName.c_str()];

        // Parse to map
        map<string, string> osDepMap;
        createDependenciesMap(osDep, osDepMap);

        // Download dependency
        typedef std::map<std::string, std::string>::iterator it_type;
        for(it_type iterator = osDepMap.begin(); iterator != osDepMap.end(); iterator++) {

            string name = iterator->first;
            string version = iterator->second;

            // Check is module exist
            string existantResult = execute("ls " + string(WONDER_MODULE) + string("/") + name);

            cout << "Existant Result: " << existantResult << endl;

            // Directory exist
            if (!existantResult.empty()) {

                cout << existantResult << " is exist!" << endl;
                continue;
            }

            // Validate URL
            string checkCommand = string("curl -o - -s -w \"%{http_code}\n\" " +
                                         host + name + string(".zip"));
            string checkResult = execute(checkCommand);

            // Do not download if invalid
            if (checkResult.compare("404") == 0 || checkResult.compare("404\n") == 0) {

                cout << name << " not found!" << endl;
            }
            else {

                // Create tmp dir
                execute(string("mkdir -p ") + string(WONDER_TEMP_MODULE));

                // Start download
                string downloadCommand = string("curl ") + host + name + string(".zip") +
                 " --output ./" + WONDER_TEMP_MODULE + "/" + name + ".zip";

                cout << "Download cmd: " << downloadCommand << endl;

                execute(downloadCommand);

                // Extract
                string zipSrc = string("./") + string(WONDER_TEMP_MODULE) +
                                    string("/") + name + string(".zip");
                string zipDst = string("./") + string(WONDER_TEMP_MODULE) +
                                    string("/") + name;
                string unzipCommand = string("unzip ") + zipSrc + string(" -d ") + zipDst;

                execute(unzipCommand);

                // Move
                string moduleDst = string("./") + string(WONDER_MODULE) + string("/") + name;
                execute("mv " + zipDst + " " + moduleDst);

                // Delete tmp dir
                execute("rm -rf " + string(WONDER_TEMP_MODULE));
            }
        }
    }

    return "Success";
}

string uninstall(int argc, const char* argv[]) {

    cout << "To uninstall something" << endl;
    return "";
}

string update(int argc, const char* argv[]) {

    cout << "To update something" << endl;
    return "";
}

string npm(int argc, const char* argv[]) {

    stringstream ss;

    for (int i=1; i<argc; ++i) {

        ss << argv[i];

        if (i < argc -1)
            ss << " ";
    }

    cout << "Execute npm with command: " << ss.str().c_str() << endl;

    return execute(ss.str().c_str());
}

string exec(int argc, const char* argv[]) {

    stringstream ss;

    for (int i=2; i<argc; ++i) {

        ss << argv[i];

        if (i < argc -1)
            ss << " ";
    }

    cout << "Execute OS with command: " << ss.str().c_str() << endl;

    return execute(ss.str().c_str());
}

string help(int argc, const char* argv[]) {

    stringstream ss;

    ss << "Usage: wpm <command>" << endl;

    typedef std::map<string, void*>::iterator it_type;
    for(it_type iterator = commandMap.begin(); iterator != commandMap.end(); iterator++) {

        string key = iterator->first;

        ss << key << "\t\t" << descMap[key] << endl;
    }

    return ss.str().c_str();
}

string version(int argc, const char* argv[]) {

    return VERSION;
}

string run(int argc, const char* argv[]) {

    // Validate package name
    if (argc <= 2)
        return "Package name NOT found!";

    string packageName = argv[2];

    // Todo: Execute package commands
    string executingCommand = string("./") + string(WONDER_MODULE) + "/" +
        packageName + string("/init ") + packageName + string(" ") + "./" + string(WONDER_CONF);

    cout << "run command: " << executingCommand << endl;

    return execute(executingCommand);
}

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

void showWelcomeMessage() {

    cout << "                                                                                " << endl;
    cout << "                     N                                                     dhh  " << endl;
    cout << "                   Nhsd                                             NdhysssooN  " << endl;
    cout << "                  y+o+d           dhysso++o++++osyh N         N dysoossyyyyod   " << endl;
    cout << "                s++ss/d     Ndyo+oooooooooooo+oooooooosyh dhso+ssssysyyyyyoy    " << endl;
    cout << "             Ns//ooss/d  Nho++ooooooooo+oo+ooooossssssssossosssyyysyyyyyyooN    " << endl;
    cout << "            h++++oo+/s do:/++ooooo+////+ooosssosooooossyyyyyyyyyyyyyysyyso      " << endl;
    cout << "          No/+ooo+/odh+/+++++++//+shdNN          N hysossyyyyyyyyyyyyyys+h      " << endl;
    cout << "          +/+oo+/+dd+/+o++++//oh N                 dNNNdyosyyyyyyyyyyyyss       " << endl;
    cout << "         //+ooo/s s:/++o+/:/y                    yossyhdNNhsoyyyyyyyyyso        " << endl;
    cout << "        +:++++/h +:/++++//hN                   yoosyyyyssh Nhoosyyyyss+d        " << endl;
    cout << "      N+::/osoh +:++++/:sN                   s+osssyyyyyyysy Ns+syyyso+d        " << endl;
    cout << "      h:+///oNN+:/+++/:h                   s++osssyyyyyyhhhysh y+ssssyo/        " << endl;
    cout << "     N//+++:+Ny:///+::d                 Ns//+oooossyyyhhhhhhyoy h/ossys+o       " << endl;
    cout << "     h:+++/: N://///-y                    yyyyhhhhhsshhhhhhhyyoN s+ssyys/d      " << endl;
    cout << "    No/+++:+ y:++//:+                              hshhhhhhyshN   oossss+o      " << endl;
    cout << "  h++/++++-hN//++//-h                              hyhhhhyyy      hosysso/N     " << endl;
    cout << "  s/+o++//:  :/+++/:N                              hyhhyyy         oossso/      " << endl;
    cout << "  s:+o/:shdNd:++++/:N                              hyyyy          Noossso/d     " << endl;
    cout << "  o:+++//// h:+ooo/:N                               sy            Nsossso/      " << endl;
    cout << "  h+//++++:hd:+oooo:d                                              oosso+/N     " << endl;
    cout << "     :/++o/o //ooos+o        NNNN    N                            y+ssoo/o      " << endl;
    cout << "     /:+oo+: y:+ssso/y Nysssoooooo++oN                           d++oooo:d      " << endl;
    cout << "     h:/ooo/+N/+sssso+h y/+ososssss+y                            o+ooo+/o       " << endl;
    cout << "      +/oo++sN /osysso+h d+oyssssss/h                          do+ooo+//N       " << endl;
    cout << "       /+//ossyd/osssssosNNhsssyyys+                         Ny/+oo++//         " << endl;
    cout << "       h/+oooo+yd/+ssyyyssdNNhsssyssN                      Nh+/+oo++/+          " << endl;
    cout << "        y:+ssoo  y+syyyyyyyydNNdysoy                     Nho++ooo++:sN          " << endl;
    cout << "         h/+o+  hoosyyyyyyhhyyhdNN                   NNds++osoo++/+dNNNNNNNNN   " << endl;
    cout << "           ++  hosssyyyhhhhhhhhysyd N          NNNdhys++ooosoo+//y y+++++++ohN  " << endl;
    cout << "           N  d+ossyyyyyyyhhhhhhyssssyyyyhhhyssoo++oossssooo+/oh y/:/+///:o     " << endl;
    cout << "             d+ossssyssssyhyyyyyyyssyyyssssssososooosooo++/oydds//++oo+/o       " << endl;
    cout << "            d++ssooosyd NNd ddhyssssossssssosssooo+++//+shdhs//+oooo++od        " << endl;
    cout << "           d//++sydNN dhyyhhyyNN  ddysoo++++++oooosyhdd  o//++++++//sd          " << endl;
    cout << "           ooydN    dsssyhhhssdssyhhd       Nddhhyso+//:s+:++++//+yN            " << endl;
    cout << "         N            Ndysssssssyyyyysssso+N +oo+++o+o++:/:///+y                " << endl;
    cout << "                          Ndhsoossyyyyssss+ooooooooo++////oydN                  " << endl;
    cout << "                               N dhhysoosss+ooo+/++ooyhdN                       " << endl;
    cout << "                                       /+o++++/:d                               " << endl;
    cout << "                                       N                                        " << endl;
    cout << "Welcome to wpm (Wonder Package Manager)" << endl;
    cout << "wpm is about to make life easier like coding in the wonderland!" << endl << endl;
}
<commit_msg>wpm + wpmPackageInit support running both local & global mode<commit_after>//
//  main.cpp
//  wpm
//
//  Created by Adawat Chanchua on 6/29/2560 BE.
//  Copyright © 2560 Adawat Chanchua. All rights reserved.
//

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Lib in the Wonderland
#include "Util.hpp"

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// C/C++ lib

#include <iostream>
#include <string>
#include <sstream>
#include <map>

using namespace std;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Rapid JSON lib

#include "rapidjson.h"
#include "document.h"

using namespace rapidjson;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Function declaration

string view(int argc, const char* argv[]);
string install(int argc, const char* argv[]);
string uninstall(int argc, const char* argv[]);
string update(int argc, const char* argv[]);
string npm(int argc, const char* argv[]);
string exec(int argc, const char* argv[]);
string help(int argc, const char* argv[]);
string version(int argc, const char* argv[]);
string run(int argc, const char* argv[]);

void showWelcomeMessage();

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Constants
const string VERSION = "0.0.1.0";
const string WONDER_MODULE = "wonder_modules";
const string WONDER_TEMP_MODULE = "wonder_modules/tmp";
const string WONDER_CONF = "wonderconf.json";

const string MODE_LOCAL = "MODE_LOCAL";
const string MODE_GLOBAL = "MODE_GLOBAL";

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Shared vars

map<string, void*> commandMap;
map<string, string> descMap;
string mode;

void addCommand(string name, void* commandFunctionPointer, string desc) {

    commandMap.insert(pair<string, void*>(name, commandFunctionPointer));
    descMap.insert(pair<string, string>(name, desc));
}

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
int main(int argc, const char * argv[]) {

    /***********************************************
     Params order note (From argc, argv convention):
        [0] File path
        [1] command
        [2][And more] command params
     ***********************************************/

    // Set mode from command
    if (string(argv[0]).compare("wpm") == 0)
        mode = MODE_GLOBAL;
    else
        mode = MODE_LOCAL;

    // Show info if hitting wpm without any command
    if (argc <= 1) {

        showWelcomeMessage();
        return 0;
    }

    // Map all command
    addCommand("view",      (void*)&view,       "View package info");
    addCommand("install",   (void*)&install,    "Install package");
    addCommand("uninstall", (void*)&uninstall,  "Uninstall package");
    addCommand("update",    (void*)&update,     "Update package");
    addCommand("npm",       (void*)&npm,        "Call npm");
    addCommand("exec",      (void*)&exec,       "Run OS command");
    addCommand("help",      (void*)&help,       "Show helpful info");
    addCommand("version",   (void*)&version,    "Show wpm version");
    addCommand("run",       (void*)&run,        "Execute command(s) inside the package");

    string command = argv[1];
    string result = "";

    if (commandMap[command]) {

        void* f = commandMap[command];
        result = ((string(*)(int, const char* []))f)(argc, argv);
    }
    else {

        result = string("-wpm: ") + command + string(": command not found");
    }

    // Print out result
    cout << result << endl;

    return 0;
}

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// Function implementation

string view(int argc, const char* argv[]) {

    cout << "To view something" << endl;
    return "";
}

string install(int argc, const char* argv[]) {

    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    // Execute sub command
    if (argc > 2) {

        string subCommand = argv[2];

        // Clean if need
        if (subCommand.compare("-clean") == 0) {

            execute(string("rm -rf " + string(WONDER_MODULE)));
        }
    }

    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    // Create wonder_modules directory if NOT exist
    execute(string("mkdir -p ") + string(WONDER_MODULE));

    // Read wonderconf.json
    string wonderConfStr = execute(string("cat ") + string(WONDER_CONF));

    // Parse to JSON document
    Document wonderConf;
    wonderConf.Parse<0>(wonderConfStr.c_str());

    string name = getJsonString(wonderConf, "name");
    string description = getJsonString(wonderConf, "description");
    string host = getJsonString(wonderConf, "host");
    string version = getJsonString(wonderConf, "version");

    // Get dependency objects
    Value& dependencies = wonderConf["dependencies"];

    rapidjson::Value::MemberIterator depIt;
    for (depIt = dependencies.MemberBegin(); depIt != dependencies.MemberEnd(); ++depIt) {

        // Get OS name
        std::string osName = depIt->name.GetString();

        cout << "osName: " << osName << endl;

        // Get OS object
        Value& osDep = dependencies[osName.c_str()];

        // Parse to map
        map<string, string> osDepMap;
        createDependenciesMap(osDep, osDepMap);

        // Download dependency
        typedef std::map<std::string, std::string>::iterator it_type;
        for(it_type iterator = osDepMap.begin(); iterator != osDepMap.end(); iterator++) {

            string name = iterator->first;
            string version = iterator->second;

            // Check is module exist
            string existantResult = execute("ls " + string(WONDER_MODULE) + string("/") + name);

            cout << "Existant Result: " << existantResult << endl;

            // Directory exist
            if (!existantResult.empty()) {

                cout << existantResult << " is exist!" << endl;
                continue;
            }

            // Validate URL
            string checkCommand = string("curl -o - -s -w \"%{http_code}\n\" " +
                                         host + name + string(".zip"));
            string checkResult = execute(checkCommand);

            // Do not download if invalid
            if (checkResult.compare("404") == 0 || checkResult.compare("404\n") == 0) {

                cout << name << " not found!" << endl;
            }
            else {

                // Create tmp dir
                execute(string("mkdir -p ") + string(WONDER_TEMP_MODULE));

                // Start download
                string downloadCommand = string("curl ") + host + name + string(".zip") +
                 " --output ./" + WONDER_TEMP_MODULE + "/" + name + ".zip";

                cout << "Download cmd: " << downloadCommand << endl;

                execute(downloadCommand);

                // Extract
                string zipSrc = string("./") + string(WONDER_TEMP_MODULE) +
                                    string("/") + name + string(".zip");
                string zipDst = string("./") + string(WONDER_TEMP_MODULE) +
                                    string("/") + name;
                string unzipCommand = string("unzip ") + zipSrc + string(" -d ") + zipDst;

                execute(unzipCommand);

                // Move
                string moduleDst = string("./") + string(WONDER_MODULE) + string("/") + name;
                execute("mv " + zipDst + " " + moduleDst);

                // Delete tmp dir
                execute("rm -rf " + string(WONDER_TEMP_MODULE));
            }
        }
    }

    return "Success";
}

string uninstall(int argc, const char* argv[]) {

    cout << "To uninstall something" << endl;
    return "";
}

string update(int argc, const char* argv[]) {

    cout << "To update something" << endl;
    return "";
}

string npm(int argc, const char* argv[]) {

    stringstream ss;

    for (int i=1; i<argc; ++i) {

        ss << argv[i];

        if (i < argc -1)
            ss << " ";
    }

    cout << "Execute npm with command: " << ss.str().c_str() << endl;

    return execute(ss.str().c_str());
}

string exec(int argc, const char* argv[]) {

    stringstream ss;

    for (int i=2; i<argc; ++i) {

        ss << argv[i];

        if (i < argc -1)
            ss << " ";
    }

    cout << "Execute OS with command: " << ss.str().c_str() << endl;

    return execute(ss.str().c_str());
}

string help(int argc, const char* argv[]) {

    stringstream ss;

    ss << "Usage: wpm <command>" << endl;

    typedef std::map<string, void*>::iterator it_type;
    for(it_type iterator = commandMap.begin(); iterator != commandMap.end(); iterator++) {

        string key = iterator->first;

        ss << key << "\t\t" << descMap[key] << endl;
    }

    return ss.str().c_str();
}

string version(int argc, const char* argv[]) {

    return VERSION;
}

string run(int argc, const char* argv[]) {

    // Validate package name
    if (argc <= 2)
        return "Package name NOT found!";

    string packageName = argv[2];

    // Execute package commands
    string wpmPackageInit = "";

    if (mode.compare(MODE_LOCAL) == 0)
        wpmPackageInit = "./wpmPackageInit";
    else if (mode.compare(MODE_GLOBAL) == 0)
        wpmPackageInit = "wpmPackageInit";
    else {
        cout << "wpmPackageInit has error! mode " << mode << " does NOT support!" << endl;
    }

    string executingCommand = wpmPackageInit + string(" ") +
        packageName + string(" ") + "./" + string(WONDER_CONF);

    cout << "run command: " << executingCommand << endl;

    return execute(executingCommand);
}

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----

void showWelcomeMessage() {

    cout << "                                                                                " << endl;
    cout << "                     N                                                     dhh  " << endl;
    cout << "                   Nhsd                                             NdhysssooN  " << endl;
    cout << "                  y+o+d           dhysso++o++++osyh N         N dysoossyyyyod   " << endl;
    cout << "                s++ss/d     Ndyo+oooooooooooo+oooooooosyh dhso+ssssysyyyyyoy    " << endl;
    cout << "             Ns//ooss/d  Nho++ooooooooo+oo+ooooossssssssossosssyyysyyyyyyooN    " << endl;
    cout << "            h++++oo+/s do:/++ooooo+////+ooosssosooooossyyyyyyyyyyyyyysyyso      " << endl;
    cout << "          No/+ooo+/odh+/+++++++//+shdNN          N hysossyyyyyyyyyyyyyys+h      " << endl;
    cout << "          +/+oo+/+dd+/+o++++//oh N                 dNNNdyosyyyyyyyyyyyyss       " << endl;
    cout << "         //+ooo/s s:/++o+/:/y                    yossyhdNNhsoyyyyyyyyyso        " << endl;
    cout << "        +:++++/h +:/++++//hN                   yoosyyyyssh Nhoosyyyyss+d        " << endl;
    cout << "      N+::/osoh +:++++/:sN                   s+osssyyyyyyysy Ns+syyyso+d        " << endl;
    cout << "      h:+///oNN+:/+++/:h                   s++osssyyyyyyhhhysh y+ssssyo/        " << endl;
    cout << "     N//+++:+Ny:///+::d                 Ns//+oooossyyyhhhhhhyoy h/ossys+o       " << endl;
    cout << "     h:+++/: N://///-y                    yyyyhhhhhsshhhhhhhyyoN s+ssyys/d      " << endl;
    cout << "    No/+++:+ y:++//:+                              hshhhhhhyshN   oossss+o      " << endl;
    cout << "  h++/++++-hN//++//-h                              hyhhhhyyy      hosysso/N     " << endl;
    cout << "  s/+o++//:  :/+++/:N                              hyhhyyy         oossso/      " << endl;
    cout << "  s:+o/:shdNd:++++/:N                              hyyyy          Noossso/d     " << endl;
    cout << "  o:+++//// h:+ooo/:N                               sy            Nsossso/      " << endl;
    cout << "  h+//++++:hd:+oooo:d                                              oosso+/N     " << endl;
    cout << "     :/++o/o //ooos+o        NNNN    N                            y+ssoo/o      " << endl;
    cout << "     /:+oo+: y:+ssso/y Nysssoooooo++oN                           d++oooo:d      " << endl;
    cout << "     h:/ooo/+N/+sssso+h y/+ososssss+y                            o+ooo+/o       " << endl;
    cout << "      +/oo++sN /osysso+h d+oyssssss/h                          do+ooo+//N       " << endl;
    cout << "       /+//ossyd/osssssosNNhsssyyys+                         Ny/+oo++//         " << endl;
    cout << "       h/+oooo+yd/+ssyyyssdNNhsssyssN                      Nh+/+oo++/+          " << endl;
    cout << "        y:+ssoo  y+syyyyyyyydNNdysoy                     Nho++ooo++:sN          " << endl;
    cout << "         h/+o+  hoosyyyyyyhhyyhdNN                   NNds++osoo++/+dNNNNNNNNN   " << endl;
    cout << "           ++  hosssyyyhhhhhhhhysyd N          NNNdhys++ooosoo+//y y+++++++ohN  " << endl;
    cout << "           N  d+ossyyyyyyyhhhhhhyssssyyyyhhhyssoo++oossssooo+/oh y/:/+///:o     " << endl;
    cout << "             d+ossssyssssyhyyyyyyyssyyyssssssososooosooo++/oydds//++oo+/o       " << endl;
    cout << "            d++ssooosyd NNd ddhyssssossssssosssooo+++//+shdhs//+oooo++od        " << endl;
    cout << "           d//++sydNN dhyyhhyyNN  ddysoo++++++oooosyhdd  o//++++++//sd          " << endl;
    cout << "           ooydN    dsssyhhhssdssyhhd       Nddhhyso+//:s+:++++//+yN            " << endl;
    cout << "         N            Ndysssssssyyyyysssso+N +oo+++o+o++:/:///+y                " << endl;
    cout << "                          Ndhsoossyyyyssss+ooooooooo++////oydN                  " << endl;
    cout << "                               N dhhysoosss+ooo+/++ooyhdN                       " << endl;
    cout << "                                       /+o++++/:d                               " << endl;
    cout << "                                       N                                        " << endl;
    cout << "Welcome to wpm (Wonder Package Manager)" << endl;
    cout << "wpm is about to make life easier like coding in the wonderland!" << endl << endl;
}
<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/
#include "TransientMultiApp.h"

#include "TimeStepper.h"
#include "LayeredSideFluxAverage.h"
#include "AllLocalDofIndicesThread.h"

// libMesh
#include "libmesh/mesh_tools.h"

template<>
InputParameters validParams<TransientMultiApp>()
{
  InputParameters params = validParams<MultiApp>();
  params += validParams<TransientInterface>();

  params.addParam<bool>("sub_cycling", false, "Set to true to allow this MultiApp to take smaller timesteps than the rest of the simulation.  More than one timestep will be performed for each 'master' timestep");

  params.addParam<bool>("interpolate_transfers", false, "Only valid when sub_cycling.  This allows transferred values to be interpolated over the time frame the MultiApp is executing over when sub_cycling");

  params.addParam<bool>("detect_steady_state", false, "If true then while sub_cycling a steady state check will be done.  In this mode output will only be done once the MultiApp reaches the target time or steady state is reached");

  params.addParam<Real>("steady_state_tol", 1e-8, "The relative difference between the new solution and the old solution that will be considered to be at steady state");

  params.addParam<bool>("output_sub_cycles", false, "If true when sub_cycling every sub-cycle will be output.");

  params.addParam<unsigned int>("max_failures", 0, "Maximum number of solve failures tolerated while sub_cycling.");

  params.addParam<bool>("tolerate_failure", false, "If true this MultiApp won't participate in dt decisions and will always be fast-forwarded to the current time.");

  params.addParam<bool>("catch_up", false, "If true this will allow failed solves to attempt to 'catch up' using smaller timesteps.");

  params.addParam<Real>("max_catch_up_steps", 2, "Maximum number of steps to allow an app to take when trying to catch back up after a failed solve.");

  return params;
}

TransientMultiApp::TransientMultiApp(const std::string & name, InputParameters parameters):
    MultiApp(name, parameters),
    _sub_cycling(getParam<bool>("sub_cycling")),
    _interpolate_transfers(getParam<bool>("interpolate_transfers")),
    _detect_steady_state(getParam<bool>("detect_steady_state")),
    _steady_state_tol(getParam<Real>("steady_state_tol")),
    _output_sub_cycles(getParam<bool>("output_sub_cycles")),
    _max_failures(getParam<unsigned int>("max_failures")),
    _tolerate_failure(getParam<bool>("tolerate_failure")),
    _failures(0),
    _catch_up(getParam<bool>("catch_up")),
    _max_catch_up_steps(getParam<Real>("max_catch_up_steps"))
{
  // Transfer interpolation only makes sense for sub-cycling solves
  if(_interpolate_transfers && !_sub_cycling)
    mooseError("MultiApp " << _name << " is set to interpolate_transfers but is not sub_cycling!  That is not valid!");

  if(!_has_an_app)
    return;

  MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

  if(_has_an_app)
  {
    _transient_executioners.resize(_my_num_apps);
    // Grab Transient Executioners from each app
    for(unsigned int i=0; i<_my_num_apps; i++)
      setupApp(i);
  }

  // Swap back
  Moose::swapLibMeshComm(swapped);
}

TransientMultiApp::~TransientMultiApp()
{
  if(!_has_an_app)
    return;

  MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

  for(unsigned int i=0; i<_my_num_apps; i++)
  {
    Transient * ex = _transient_executioners[i];

    ex->postExecute();
  }

  // Swap back
  Moose::swapLibMeshComm(swapped);
}

NumericVector<Number> &
TransientMultiApp::appTransferVector(unsigned int app, std::string var_name)
{
  if(std::find(_transferred_vars.begin(), _transferred_vars.end(), var_name) == _transferred_vars.end())
    _transferred_vars.push_back(var_name);

  if(_interpolate_transfers)
    return appProblem(app)->getAuxiliarySystem().system().get_vector("transfer");

  return appProblem(app)->getAuxiliarySystem().solution();
}

void
TransientMultiApp::solveStep(Real dt, Real target_time)
{
  if(!_has_an_app)
    return;

  std::cout<<"Solving MultiApp "<<_name<<std::endl;

  // "target_time" must always be in global time
  target_time += _app.getGlobalTimeOffset();

  MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

  int rank;
  int ierr;
  ierr = MPI_Comm_rank(_orig_comm, &rank); mooseCheckMPIErr(ierr);

  for(unsigned int i=0; i<_my_num_apps; i++)
  {
    Transient * ex = _transient_executioners[i];

    // The App might have a different local time from the rest of the problem
    Real app_time_offset = _apps[i]->getGlobalTimeOffset();

    if((ex->getTime() + app_time_offset) + 2e-14 >= target_time) // Maybe this MultiApp was already solved
      continue;

    if(_sub_cycling)
    {
      Real time_old = ex->getTime() + app_time_offset;

      if(_interpolate_transfers)
      {
        FEProblem * problem = appProblem(_first_local_app + i);
        AuxiliarySystem & aux_system = problem->getAuxiliarySystem();
        System & libmesh_aux_system = aux_system.system();

        NumericVector<Number> & solution = *libmesh_aux_system.solution;
        NumericVector<Number> & transfer_old = libmesh_aux_system.get_vector("transfer_old");

        solution.close();

        // Save off the current auxiliary solution
        transfer_old = solution;

        transfer_old.close();

        // Snag all of the local dof indices for all of these variables
        AllLocalDofIndicesThread aldit(libmesh_aux_system, _transferred_vars);
        ConstElemRange & elem_range = *problem->mesh().getActiveLocalElementRange();
        Threads::parallel_reduce(elem_range, aldit);

        _transferred_dofs = aldit._all_dof_indices;
      }

      if(_output_sub_cycles)
        ex->allowOutput(true);
      else
        ex->allowOutput(false);

      ex->setTargetTime(target_time-app_time_offset);

//      unsigned int failures = 0;

      bool at_steady = false;

      // Now do all of the solves we need
      while(!at_steady && ex->getTime() + app_time_offset + 2e-14 < target_time)
      {
        ex->computeDT();

        if(_interpolate_transfers)
        {
          // See what time this executioner is going to go to.
          Real future_time = ex->getTime() + app_time_offset + ex->computeConstrainedDT();

          // How far along we are towards the target time:
          Real step_percent = (future_time - time_old) / (target_time - time_old);

          Real one_minus_step_percent = 1.0 - step_percent;

          // Do the interpolation for each variable that was transferred to
          FEProblem * problem = appProblem(_first_local_app + i);
          AuxiliarySystem & aux_system = problem->getAuxiliarySystem();
          System & libmesh_aux_system = aux_system.system();

          NumericVector<Number> & solution = *libmesh_aux_system.solution;
          NumericVector<Number> & transfer = libmesh_aux_system.get_vector("transfer");
          NumericVector<Number> & transfer_old = libmesh_aux_system.get_vector("transfer_old");

          solution.close(); // Just to be sure
          transfer.close();
          transfer_old.close();

          std::set<unsigned int>::iterator it  = _transferred_dofs.begin();
          std::set<unsigned int>::iterator end = _transferred_dofs.end();

          for(; it != end; ++it)
          {
            unsigned int dof = *it;
            solution.set(dof, (transfer_old(dof) * one_minus_step_percent) + (transfer(dof) * step_percent));
//            solution.set(dof, transfer_old(dof));
//            solution.set(dof, transfer(dof));
//            solution.set(dof, 1);
          }

          solution.close();
        }

        ex->takeStep();

        bool converged = ex->lastSolveConverged();

        if(!converged)
        {
          mooseWarning("While sub_cycling "<<_name<<_first_local_app+i<<" failed to converge!"<<std::endl);
          _failures++;

          if(_failures > _max_failures)
            mooseError("While sub_cycling "<<_name<<_first_local_app+i<<" REALLY failed!"<<std::endl);
        }

        Real solution_change_norm = ex->getSolutionChangeNorm();

        if(_detect_steady_state)
          std::cout<<"Solution change norm: "<<solution_change_norm<<std::endl;

        if(converged && _detect_steady_state && solution_change_norm < _steady_state_tol)
        {
          std::cout<<"Detected Steady State!  Fast-forwarding to "<<target_time<<std::endl;

          at_steady = true;

          // Set the time for the problem to the target time we were looking for
          ex->setTime(target_time-app_time_offset);

          // Force it to output right now
          ex->forceOutput();

          // Clean up the end
          ex->endStep();
        }
        else
          ex->endStep();
      }

      // If we were looking for a steady state, but didn't reach one, we still need to output one more time
      if(!at_steady)
        ex->forceOutput();
    }
    else if(_tolerate_failure)
    {
      ex->takeStep(dt);
      ex->setTime(target_time-app_time_offset);
      ex->forceOutput();
      ex->endStep();
    }
    else
    {
      std::cout<<"Solving Normal Step!"<<std::endl;

      ex->takeStep(dt);
      ex->endStep();

      if(!ex->lastSolveConverged())
      {
        mooseWarning(_name<<_first_local_app+i<<" failed to converge!"<<std::endl);

        if(_catch_up)
        {
          std::cout<<"Starting Catch Up!"<<std::endl;

          bool caught_up = false;

          unsigned int catch_up_step = 0;

          Real catch_up_dt = dt/2;

          ex->allowOutput(false); // Don't output while catching up

          while(!caught_up && catch_up_step < _max_catch_up_steps)
          {
            std::cerr<<"Solving " << _name << "catch up step " << catch_up_step <<std::endl;

            ex->computeDT();
            ex->takeStep(catch_up_dt); // Cut the timestep in half to try two half-step solves

            if(ex->lastSolveConverged())
            {
              if(ex->getTime() + app_time_offset + 2e-14 >= target_time)
              {
                ex->forceOutput(); // This is here so that it is called before endStep()
                caught_up = true;
              }
            }
            else
              catch_up_dt /= 2.0;

            ex->endStep(); // This is here so it is called after forceOutput()

            catch_up_step++;
          }

          if(!caught_up)
            mooseError(_name << " Failed to catch up!" << std::endl);

          ex->allowOutput(true);
        }
      }
    }
  }

  // Swap back
  Moose::swapLibMeshComm(swapped);

  _transferred_vars.clear();

  std::cout<<"Finished Solving MultiApp "<<_name<<std::endl;
}

Real
TransientMultiApp::computeDT()
{
  if(_sub_cycling) // Bow out of the timestep selection dance
    return std::numeric_limits<Real>::max();

  Real smallest_dt = std::numeric_limits<Real>::max();

  if(_has_an_app)
  {
    MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

    for(unsigned int i=0; i<_my_num_apps; i++)
    {
      Transient * ex = _transient_executioners[i];
      ex->computeDT();
      Real dt = ex->computeConstrainedDT();

      smallest_dt = std::min(dt, smallest_dt);
    }

    // Swap back
    Moose::swapLibMeshComm(swapped);
  }

  if(_tolerate_failure) // Bow out of the timestep selection dance, we do this down here because we need to call computeConstrainedDT at least once for these executioners...
    return std::numeric_limits<Real>::max();

  Parallel::min(smallest_dt);
  return smallest_dt;
}

void
TransientMultiApp::resetApp(unsigned int global_app, Real /*time*/)  // FIXME: Note that we are passing in time but also grabbing it below
{
  if(hasLocalApp(global_app))
  {
    unsigned int local_app = globalAppToLocal(global_app);

    // Grab the current time the App is at so we can start the new one at the same place
    Real time = _transient_executioners[local_app]->getTime() + _apps[local_app]->getGlobalTimeOffset();

    MultiApp::resetApp(global_app, time);

    MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

    setupApp(local_app, time, false);

    // Swap back
    Moose::swapLibMeshComm(swapped);
  }
}

void
TransientMultiApp::setupApp(unsigned int i, Real /*time*/, bool output_initial)  // FIXME: Should we be passing time?
{
  MooseApp * app = _apps[i];
  Transient * ex = dynamic_cast<Transient *>(app->getExecutioner());
  if(!ex)
    mooseError("MultiApp " << _name << " is not using a Transient Executioner!");

  if(!output_initial)
    ex->outputInitial(false);

  ex->init();

  FEProblem * problem = appProblem(_first_local_app + i);

  if(_interpolate_transfers)
  {
    AuxiliarySystem & aux_system = problem->getAuxiliarySystem();
    System & libmesh_aux_system = aux_system.system();

    // We'll store a copy of the auxiliary system's solution at the old time in here
    libmesh_aux_system.add_vector("transfer_old", false);

    // This will be where we'll transfer the value to for the "target" time
    libmesh_aux_system.add_vector("transfer", false);
  }

  ex->preExecute();
  problem->copyOldSolutions();
  _transient_executioners[i] = ex;

  if(_detect_steady_state || _tolerate_failure)
    ex->allowOutput(false);
}

<commit_msg>computeConstrainedDT() is not called from application level any more (refs #1953)<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/
#include "TransientMultiApp.h"

#include "TimeStepper.h"
#include "LayeredSideFluxAverage.h"
#include "AllLocalDofIndicesThread.h"

// libMesh
#include "libmesh/mesh_tools.h"

template<>
InputParameters validParams<TransientMultiApp>()
{
  InputParameters params = validParams<MultiApp>();
  params += validParams<TransientInterface>();

  params.addParam<bool>("sub_cycling", false, "Set to true to allow this MultiApp to take smaller timesteps than the rest of the simulation.  More than one timestep will be performed for each 'master' timestep");

  params.addParam<bool>("interpolate_transfers", false, "Only valid when sub_cycling.  This allows transferred values to be interpolated over the time frame the MultiApp is executing over when sub_cycling");

  params.addParam<bool>("detect_steady_state", false, "If true then while sub_cycling a steady state check will be done.  In this mode output will only be done once the MultiApp reaches the target time or steady state is reached");

  params.addParam<Real>("steady_state_tol", 1e-8, "The relative difference between the new solution and the old solution that will be considered to be at steady state");

  params.addParam<bool>("output_sub_cycles", false, "If true when sub_cycling every sub-cycle will be output.");

  params.addParam<unsigned int>("max_failures", 0, "Maximum number of solve failures tolerated while sub_cycling.");

  params.addParam<bool>("tolerate_failure", false, "If true this MultiApp won't participate in dt decisions and will always be fast-forwarded to the current time.");

  params.addParam<bool>("catch_up", false, "If true this will allow failed solves to attempt to 'catch up' using smaller timesteps.");

  params.addParam<Real>("max_catch_up_steps", 2, "Maximum number of steps to allow an app to take when trying to catch back up after a failed solve.");

  return params;
}

TransientMultiApp::TransientMultiApp(const std::string & name, InputParameters parameters):
    MultiApp(name, parameters),
    _sub_cycling(getParam<bool>("sub_cycling")),
    _interpolate_transfers(getParam<bool>("interpolate_transfers")),
    _detect_steady_state(getParam<bool>("detect_steady_state")),
    _steady_state_tol(getParam<Real>("steady_state_tol")),
    _output_sub_cycles(getParam<bool>("output_sub_cycles")),
    _max_failures(getParam<unsigned int>("max_failures")),
    _tolerate_failure(getParam<bool>("tolerate_failure")),
    _failures(0),
    _catch_up(getParam<bool>("catch_up")),
    _max_catch_up_steps(getParam<Real>("max_catch_up_steps"))
{
  // Transfer interpolation only makes sense for sub-cycling solves
  if(_interpolate_transfers && !_sub_cycling)
    mooseError("MultiApp " << _name << " is set to interpolate_transfers but is not sub_cycling!  That is not valid!");

  if(!_has_an_app)
    return;

  MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

  if(_has_an_app)
  {
    _transient_executioners.resize(_my_num_apps);
    // Grab Transient Executioners from each app
    for(unsigned int i=0; i<_my_num_apps; i++)
      setupApp(i);
  }

  // Swap back
  Moose::swapLibMeshComm(swapped);
}

TransientMultiApp::~TransientMultiApp()
{
  if(!_has_an_app)
    return;

  MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

  for(unsigned int i=0; i<_my_num_apps; i++)
  {
    Transient * ex = _transient_executioners[i];

    ex->postExecute();
  }

  // Swap back
  Moose::swapLibMeshComm(swapped);
}

NumericVector<Number> &
TransientMultiApp::appTransferVector(unsigned int app, std::string var_name)
{
  if(std::find(_transferred_vars.begin(), _transferred_vars.end(), var_name) == _transferred_vars.end())
    _transferred_vars.push_back(var_name);

  if(_interpolate_transfers)
    return appProblem(app)->getAuxiliarySystem().system().get_vector("transfer");

  return appProblem(app)->getAuxiliarySystem().solution();
}

void
TransientMultiApp::solveStep(Real dt, Real target_time)
{
  if(!_has_an_app)
    return;

  std::cout<<"Solving MultiApp "<<_name<<std::endl;

  // "target_time" must always be in global time
  target_time += _app.getGlobalTimeOffset();

  MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

  int rank;
  int ierr;
  ierr = MPI_Comm_rank(_orig_comm, &rank); mooseCheckMPIErr(ierr);

  for(unsigned int i=0; i<_my_num_apps; i++)
  {
    Transient * ex = _transient_executioners[i];

    // The App might have a different local time from the rest of the problem
    Real app_time_offset = _apps[i]->getGlobalTimeOffset();

    if((ex->getTime() + app_time_offset) + 2e-14 >= target_time) // Maybe this MultiApp was already solved
      continue;

    if(_sub_cycling)
    {
      Real time_old = ex->getTime() + app_time_offset;

      if(_interpolate_transfers)
      {
        FEProblem * problem = appProblem(_first_local_app + i);
        AuxiliarySystem & aux_system = problem->getAuxiliarySystem();
        System & libmesh_aux_system = aux_system.system();

        NumericVector<Number> & solution = *libmesh_aux_system.solution;
        NumericVector<Number> & transfer_old = libmesh_aux_system.get_vector("transfer_old");

        solution.close();

        // Save off the current auxiliary solution
        transfer_old = solution;

        transfer_old.close();

        // Snag all of the local dof indices for all of these variables
        AllLocalDofIndicesThread aldit(libmesh_aux_system, _transferred_vars);
        ConstElemRange & elem_range = *problem->mesh().getActiveLocalElementRange();
        Threads::parallel_reduce(elem_range, aldit);

        _transferred_dofs = aldit._all_dof_indices;
      }

      if(_output_sub_cycles)
        ex->allowOutput(true);
      else
        ex->allowOutput(false);

      ex->setTargetTime(target_time-app_time_offset);

//      unsigned int failures = 0;

      bool at_steady = false;

      // Now do all of the solves we need
      while(!at_steady && ex->getTime() + app_time_offset + 2e-14 < target_time)
      {
        ex->computeDT();

        if(_interpolate_transfers)
        {
          // See what time this executioner is going to go to.
          Real future_time = ex->getTime() + app_time_offset + ex->getDT();

          // How far along we are towards the target time:
          Real step_percent = (future_time - time_old) / (target_time - time_old);

          Real one_minus_step_percent = 1.0 - step_percent;

          // Do the interpolation for each variable that was transferred to
          FEProblem * problem = appProblem(_first_local_app + i);
          AuxiliarySystem & aux_system = problem->getAuxiliarySystem();
          System & libmesh_aux_system = aux_system.system();

          NumericVector<Number> & solution = *libmesh_aux_system.solution;
          NumericVector<Number> & transfer = libmesh_aux_system.get_vector("transfer");
          NumericVector<Number> & transfer_old = libmesh_aux_system.get_vector("transfer_old");

          solution.close(); // Just to be sure
          transfer.close();
          transfer_old.close();

          std::set<unsigned int>::iterator it  = _transferred_dofs.begin();
          std::set<unsigned int>::iterator end = _transferred_dofs.end();

          for(; it != end; ++it)
          {
            unsigned int dof = *it;
            solution.set(dof, (transfer_old(dof) * one_minus_step_percent) + (transfer(dof) * step_percent));
//            solution.set(dof, transfer_old(dof));
//            solution.set(dof, transfer(dof));
//            solution.set(dof, 1);
          }

          solution.close();
        }

        ex->takeStep();

        bool converged = ex->lastSolveConverged();

        if(!converged)
        {
          mooseWarning("While sub_cycling "<<_name<<_first_local_app+i<<" failed to converge!"<<std::endl);
          _failures++;

          if(_failures > _max_failures)
            mooseError("While sub_cycling "<<_name<<_first_local_app+i<<" REALLY failed!"<<std::endl);
        }

        Real solution_change_norm = ex->getSolutionChangeNorm();

        if(_detect_steady_state)
          std::cout<<"Solution change norm: "<<solution_change_norm<<std::endl;

        if(converged && _detect_steady_state && solution_change_norm < _steady_state_tol)
        {
          std::cout<<"Detected Steady State!  Fast-forwarding to "<<target_time<<std::endl;

          at_steady = true;

          // Set the time for the problem to the target time we were looking for
          ex->setTime(target_time-app_time_offset);

          // Force it to output right now
          ex->forceOutput();

          // Clean up the end
          ex->endStep();
        }
        else
          ex->endStep();
      }

      // If we were looking for a steady state, but didn't reach one, we still need to output one more time
      if(!at_steady)
        ex->forceOutput();
    }
    else if(_tolerate_failure)
    {
      ex->takeStep(dt);
      ex->setTime(target_time-app_time_offset);
      ex->forceOutput();
      ex->endStep();
    }
    else
    {
      std::cout<<"Solving Normal Step!"<<std::endl;

      ex->takeStep(dt);
      ex->endStep();

      if(!ex->lastSolveConverged())
      {
        mooseWarning(_name<<_first_local_app+i<<" failed to converge!"<<std::endl);

        if(_catch_up)
        {
          std::cout<<"Starting Catch Up!"<<std::endl;

          bool caught_up = false;

          unsigned int catch_up_step = 0;

          Real catch_up_dt = dt/2;

          ex->allowOutput(false); // Don't output while catching up

          while(!caught_up && catch_up_step < _max_catch_up_steps)
          {
            std::cerr<<"Solving " << _name << "catch up step " << catch_up_step <<std::endl;

            ex->computeDT();
            ex->takeStep(catch_up_dt); // Cut the timestep in half to try two half-step solves

            if(ex->lastSolveConverged())
            {
              if(ex->getTime() + app_time_offset + 2e-14 >= target_time)
              {
                ex->forceOutput(); // This is here so that it is called before endStep()
                caught_up = true;
              }
            }
            else
              catch_up_dt /= 2.0;

            ex->endStep(); // This is here so it is called after forceOutput()

            catch_up_step++;
          }

          if(!caught_up)
            mooseError(_name << " Failed to catch up!" << std::endl);

          ex->allowOutput(true);
        }
      }
    }
  }

  // Swap back
  Moose::swapLibMeshComm(swapped);

  _transferred_vars.clear();

  std::cout<<"Finished Solving MultiApp "<<_name<<std::endl;
}

Real
TransientMultiApp::computeDT()
{
  if(_sub_cycling) // Bow out of the timestep selection dance
    return std::numeric_limits<Real>::max();

  Real smallest_dt = std::numeric_limits<Real>::max();

  if(_has_an_app)
  {
    MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

    for(unsigned int i=0; i<_my_num_apps; i++)
    {
      Transient * ex = _transient_executioners[i];
      ex->computeDT();
      Real dt = ex->getDT();

      smallest_dt = std::min(dt, smallest_dt);
    }

    // Swap back
    Moose::swapLibMeshComm(swapped);
  }

  if(_tolerate_failure) // Bow out of the timestep selection dance, we do this down here because we need to call computeConstrainedDT at least once for these executioners...
    return std::numeric_limits<Real>::max();

  Parallel::min(smallest_dt);
  return smallest_dt;
}

void
TransientMultiApp::resetApp(unsigned int global_app, Real /*time*/)  // FIXME: Note that we are passing in time but also grabbing it below
{
  if(hasLocalApp(global_app))
  {
    unsigned int local_app = globalAppToLocal(global_app);

    // Grab the current time the App is at so we can start the new one at the same place
    Real time = _transient_executioners[local_app]->getTime() + _apps[local_app]->getGlobalTimeOffset();

    MultiApp::resetApp(global_app, time);

    MPI_Comm swapped = Moose::swapLibMeshComm(_my_comm);

    setupApp(local_app, time, false);

    // Swap back
    Moose::swapLibMeshComm(swapped);
  }
}

void
TransientMultiApp::setupApp(unsigned int i, Real /*time*/, bool output_initial)  // FIXME: Should we be passing time?
{
  MooseApp * app = _apps[i];
  Transient * ex = dynamic_cast<Transient *>(app->getExecutioner());
  if(!ex)
    mooseError("MultiApp " << _name << " is not using a Transient Executioner!");

  if(!output_initial)
    ex->outputInitial(false);

  ex->init();

  FEProblem * problem = appProblem(_first_local_app + i);

  if(_interpolate_transfers)
  {
    AuxiliarySystem & aux_system = problem->getAuxiliarySystem();
    System & libmesh_aux_system = aux_system.system();

    // We'll store a copy of the auxiliary system's solution at the old time in here
    libmesh_aux_system.add_vector("transfer_old", false);

    // This will be where we'll transfer the value to for the "target" time
    libmesh_aux_system.add_vector("transfer", false);
  }

  ex->preExecute();
  problem->copyOldSolutions();
  _transient_executioners[i] = ex;

  if(_detect_steady_state || _tolerate_failure)
    ex->allowOutput(false);
}

<|endoftext|>


<commit_before>#include "MainMenuScene.h"
#include "NNInputSystem.h"
#include "NNSceneDirector.h"
#include "GameScene.h"
#include "NNApplication.h"

MainMenuScene::MainMenuScene()
	: m_MainMenuImage(nullptr)
{
	float width = (float)NNApplication::GetInstance()->GetScreenWidth();
	float height = (float)NNApplication::GetInstance()->GetScreenHeight();

	m_MainMenuImage = NNSprite::Create( L"Sprite/MainMenu.jpg" );
	m_MainMenuImage->SetPosition( width/2, height/2 );
	m_MainMenuImage->SetCenter( m_MainMenuImage->GetPositionX()/2.f, m_MainMenuImage->GetPositionY()/2.f + 70.f );
	AddChild( m_MainMenuImage );

	m_MianMenuLable[MENU_PLAY] = NNLabel::Create( L"Play", L" ", 35.f );
	m_MianMenuLable[MENU_PLAY]->SetPosition( width/2 + 200.f, height/2 + 150.f );
	AddChild( m_MianMenuLable[MENU_PLAY] );

	m_MianMenuLable[MENU_EXIT] = NNLabel::Create( L"Exit", L" ", 35.f );
	m_MianMenuLable[MENU_EXIT]->SetPosition( width/2 + 200.f, height/2 + 200.f);
	AddChild( m_MianMenuLable[MENU_EXIT] );
}

MainMenuScene::~MainMenuScene()
{
}

void MainMenuScene::Render()
{
	NNScene::Render();
}

void MainMenuScene::Update( float dTime )
{
	NNScene::Update( dTime );

	m_MainMenuImage->SetVisible( true );

	if ( NNInputSystem::GetInstance()->GetKeyState( VK_RETURN ) == KEY_UP )
	{
		NNSceneDirector::GetInstance()->ChangeScene( CGameScene::Create() );
		return;
	}
}<commit_msg>* Change Next Scene GameScene -> StoryScene<commit_after>#include "MainMenuScene.h"
#include "NNInputSystem.h"
#include "NNSceneDirector.h"
#include "NNApplication.h"

#include "StoryScene.h"

MainMenuScene::MainMenuScene()
	: m_MainMenuImage(nullptr)
{
	float width = (float)NNApplication::GetInstance()->GetScreenWidth();
	float height = (float)NNApplication::GetInstance()->GetScreenHeight();

	m_MainMenuImage = NNSprite::Create( L"Sprite/MainMenu.jpg" );
	m_MainMenuImage->SetPosition( width/2, height/2 );
	m_MainMenuImage->SetCenter( m_MainMenuImage->GetPositionX()/2.f, m_MainMenuImage->GetPositionY()/2.f + 70.f );
	AddChild( m_MainMenuImage );

	m_MianMenuLable[MENU_PLAY] = NNLabel::Create( L"Play", L" ", 35.f );
	m_MianMenuLable[MENU_PLAY]->SetPosition( width/2 + 200.f, height/2 + 150.f );
	AddChild( m_MianMenuLable[MENU_PLAY] );

	m_MianMenuLable[MENU_EXIT] = NNLabel::Create( L"Exit", L" ", 35.f );
	m_MianMenuLable[MENU_EXIT]->SetPosition( width/2 + 200.f, height/2 + 200.f);
	AddChild( m_MianMenuLable[MENU_EXIT] );
}

MainMenuScene::~MainMenuScene()
{
}

void MainMenuScene::Render()
{
	NNScene::Render();
}

void MainMenuScene::Update( float dTime )
{
	NNScene::Update( dTime );

	m_MainMenuImage->SetVisible( true );

	if ( NNInputSystem::GetInstance()->GetKeyState( VK_RETURN ) == KEY_UP )
	{
		NNSceneDirector::GetInstance()->ChangeScene( StoryScene::Create() );
		return;
	}
}<|endoftext|>


<commit_before>#include <iostream>
using namespace std;

double division(int a, int b)
{
   if( b == 0 )
   {
      throw "Division by zero condition!";
   }
   return (a/b);
}

int main ()
{
   int x = 50;
   int y = 0;
   double z = 0;

   try {
     z = division(x, y);
     cout << z << endl;
   }catch (const char* msg) {
     cerr << msg << endl;
   }

   return 0;
}
<commit_msg>exception<commit_after>#include <iostream>
using namespace std;

double division(int a, int b)
{
   if( b == 0 )
   {
      throw "Division by zero condition!";
   }
   return (a/b);
}

int main ()
{
   int x = 50;
   int y = 0;
   double z = 0;

   try {
     z = division(x, y);
     cout << z << endl;
  }catch (const char* msg) {
     cerr << msg << endl;
  }

  std::cout << "Hello am I continuing?" << std::endl;
  return 0;
}
<|endoftext|>


<commit_before>
/*
 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * $Id$
 *
 */

#include "mem/ruby/tester/Check.hh"
#include "mem/ruby/system/Sequencer.hh"
#include "mem/ruby/system/System.hh"
#include "mem/ruby/common/SubBlock.hh"
#include "mem/protocol/Chip.hh"
#include "mem/packet.hh"

Check::Check(const Address& address, const Address& pc)
{
  m_status = TesterStatus_Idle;

  pickValue();
  pickInitiatingNode();
  changeAddress(address);
  m_pc = pc;
  m_access_mode = AccessModeType(random() % AccessModeType_NUM);
  m_store_count = 0;
}

void Check::initiate()
{
  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating");
  DEBUG_EXPR(TESTER_COMP, MedPrio, *this);

  // current CMP protocol doesn't support prefetches
  if (!Protocol::m_CMP && (random() & 0xf) == 0) { // 1 in 16 chance
    initiatePrefetch(); // Prefetch from random processor
  }

  if(m_status == TesterStatus_Idle) {
    initiateAction();
  } else if(m_status == TesterStatus_Ready) {
    initiateCheck();
  } else {
    // Pending - do nothing
    DEBUG_MSG(TESTER_COMP, MedPrio, "initiating action/check - failed: action/check is pending\n");
  }
}

void Check::initiatePrefetch(Sequencer* targetSequencer_ptr)
{
  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating prefetch");

  CacheRequestType type;
  if ((random() & 0x7) != 0) { // 1 in 8 chance
    if ((random() & 0x1) == 0) { // 50% chance
      type = CacheRequestType_LD;
    } else {
      type = CacheRequestType_IFETCH;
    }
  } else {
    type = CacheRequestType_ST;
  }

  Addr data_addr = m_address.getAddress();
  Addr pc_addr = m_pc.getAddress();
  Request request(0, data_addr, 0, Flags<unsigned int>(Request::PREFETCH), pc_addr, 0, 0);
  MemCmd::Command command;
  if (type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
    request.setFlags(Request::INST_FETCH);
  } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
  } else if (type == CacheRequestType_ST) {
    command = MemCmd::WriteReq;
  } else if (type == CacheRequestType_ATOMIC) {
    command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
  } else {
    assert(false);
  }

  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID

  assert(targetSequencer_ptr != NULL);
  if (targetSequencer_ptr->isReady(&pkt)) {
    targetSequencer_ptr->makeRequest(&pkt);
  }
}

void Check::initiatePrefetch()
{
  // Any sequencer can issue a prefetch for this address
  Sequencer* targetSequencer_ptr = g_system_ptr->getChip(random() % RubyConfig::numberOfChips())->getSequencer(random() % RubyConfig::numberOfProcsPerChip());
  assert(targetSequencer_ptr != NULL);
  initiatePrefetch(targetSequencer_ptr);
}

void Check::initiateAction()
{
  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Action");
  assert(m_status == TesterStatus_Idle);

  CacheRequestType type = CacheRequestType_ST;
  if ((random() & 0x1) == 0) { // 50% chance
    type = CacheRequestType_ATOMIC;
  }

  Addr data_addr = m_address.getAddress()+m_store_count;
  Addr pc_addr = m_pc.getAddress();
  Request request(0, data_addr, 1, Flags<unsigned int>(), pc_addr, 0, 0);
  MemCmd::Command command;
  if (type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
    request.setFlags(Request::INST_FETCH);
  } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
  } else if (type == CacheRequestType_ST) {
    command = MemCmd::WriteReq;
  } else if (type == CacheRequestType_ATOMIC) {
    command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
  } else {
    assert(false);
  }

  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID

  Sequencer* sequencer_ptr = initiatingSequencer();
  if (sequencer_ptr->isReady(&pkt) == false) {
    DEBUG_MSG(TESTER_COMP, MedPrio, "failed to initiate action - sequencer not ready\n");
  } else {
    DEBUG_MSG(TESTER_COMP, MedPrio, "initiating action - successful\n");
    DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
    m_status = TesterStatus_Action_Pending;

    sequencer_ptr->makeRequest(&pkt);
  }
  DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
}

void Check::initiateCheck()
{
  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Check");
  assert(m_status == TesterStatus_Ready);

  CacheRequestType type = CacheRequestType_LD;
  if ((random() & 0x1) == 0) { // 50% chance
    type = CacheRequestType_IFETCH;
  }

  Addr data_addr = m_address.getAddress()+m_store_count;
  Addr pc_addr = m_pc.getAddress();
  Request request(0, data_addr, CHECK_SIZE, Flags<unsigned int>(), pc_addr, 0, 0);
  MemCmd::Command command;
  if (type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
    request.setFlags(Request::INST_FETCH);
  } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
  } else if (type == CacheRequestType_ST) {
    command = MemCmd::WriteReq;
  } else if (type == CacheRequestType_ATOMIC) {
    command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
  } else {
    assert(false);
  }

  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID

  Sequencer* sequencer_ptr = initiatingSequencer();
  if (sequencer_ptr->isReady(&pkt) == false) {
    DEBUG_MSG(TESTER_COMP, MedPrio, "failed to initiate check - sequencer not ready\n");
  } else {
    DEBUG_MSG(TESTER_COMP, MedPrio, "initiating check - successful\n");
    DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
    m_status = TesterStatus_Check_Pending;

    sequencer_ptr->makeRequest(&pkt);
  }
  DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
}

void Check::performCallback(NodeID proc, SubBlock& data)
{
  Address address = data.getAddress();
  //  assert(getAddress() == address);  // This isn't exactly right since we now have multi-byte checks
  assert(getAddress().getLineAddress() == address.getLineAddress());

  DEBUG_MSG(TESTER_COMP, MedPrio, "Callback");
  DEBUG_EXPR(TESTER_COMP, MedPrio, *this);

  if (m_status == TesterStatus_Action_Pending) {
    DEBUG_MSG(TESTER_COMP, MedPrio, "Action callback");
    // Perform store
    data.setByte(0, m_value+m_store_count); // We store one byte at a time
    m_store_count++;

    if (m_store_count == CHECK_SIZE) {
      m_status = TesterStatus_Ready;
    } else {
      m_status = TesterStatus_Idle;
    }
  } else if (m_status == TesterStatus_Check_Pending) {
    DEBUG_MSG(TESTER_COMP, MedPrio, "Check callback");
    // Perform load/check
    for(int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
      if (uint8(m_value+byte_number) != data.getByte(byte_number) && (DATA_BLOCK == true)) {
        WARN_EXPR(proc);
        WARN_EXPR(address);
        WARN_EXPR(data);
        WARN_EXPR(byte_number);
        WARN_EXPR((int)m_value+byte_number);
        WARN_EXPR((int)data.getByte(byte_number));
        WARN_EXPR(*this);
        WARN_EXPR(g_eventQueue_ptr->getTime());
        ERROR_MSG("Action/check failure");
      }
    }
    DEBUG_MSG(TESTER_COMP, HighPrio, "Action/check success:");
    DEBUG_EXPR(TESTER_COMP, HighPrio, *this);
    DEBUG_EXPR(TESTER_COMP, MedPrio, data);

    m_status = TesterStatus_Idle;
    pickValue();

  } else {
    WARN_EXPR(*this);
    WARN_EXPR(proc);
    WARN_EXPR(data);
    WARN_EXPR(m_status);
    WARN_EXPR(g_eventQueue_ptr->getTime());
    ERROR_MSG("Unexpected TesterStatus");
  }

  DEBUG_EXPR(TESTER_COMP, MedPrio, proc);
  DEBUG_EXPR(TESTER_COMP, MedPrio, data);
  DEBUG_EXPR(TESTER_COMP, MedPrio, getAddress().getLineAddress());
  DEBUG_MSG(TESTER_COMP, MedPrio, "Callback done");
  DEBUG_EXPR(TESTER_COMP, MedPrio, *this);
}

void Check::changeAddress(const Address& address)
{
  assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready));
  m_status = TesterStatus_Idle;
  m_address = address;
  m_store_count = 0;
}

Sequencer* Check::initiatingSequencer() const
{
  return g_system_ptr->getChip(m_initiatingNode/RubyConfig::numberOfProcsPerChip())->getSequencer(m_initiatingNode%RubyConfig::numberOfProcsPerChip());
}

void Check::pickValue()
{
  assert(m_status == TesterStatus_Idle);
  m_status = TesterStatus_Idle;
  //  DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
  DEBUG_MSG(TESTER_COMP, MedPrio, *this);
  m_value = random() & 0xff; // One byte
  //  DEBUG_MSG(TESTER_COMP, MedPrio, m_value);
  DEBUG_MSG(TESTER_COMP, MedPrio, *this);
  m_store_count = 0;
}

void Check::pickInitiatingNode()
{
  assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready));
  m_status = TesterStatus_Idle;
  DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
  m_initiatingNode = (random() % RubyConfig::numberOfProcessors());
  DEBUG_MSG(TESTER_COMP, MedPrio, m_initiatingNode);
  m_store_count = 0;
}

void Check::print(ostream& out) const
{
  out << "["
      << m_address << ", value: "
      << (int) m_value << ", status: "
      << m_status << ", initiating node: "
      << m_initiatingNode << ", store_count: "
      << m_store_count
      << "]" << flush;
}
<commit_msg>ruby: assert(false) should be panic. This also fixes some compiler warnings<commit_after>
/*
 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * $Id$
 *
 */

#include "mem/ruby/tester/Check.hh"
#include "mem/ruby/system/Sequencer.hh"
#include "mem/ruby/system/System.hh"
#include "mem/ruby/common/SubBlock.hh"
#include "mem/protocol/Chip.hh"
#include "mem/packet.hh"

Check::Check(const Address& address, const Address& pc)
{
  m_status = TesterStatus_Idle;

  pickValue();
  pickInitiatingNode();
  changeAddress(address);
  m_pc = pc;
  m_access_mode = AccessModeType(random() % AccessModeType_NUM);
  m_store_count = 0;
}

void Check::initiate()
{
  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating");
  DEBUG_EXPR(TESTER_COMP, MedPrio, *this);

  // current CMP protocol doesn't support prefetches
  if (!Protocol::m_CMP && (random() & 0xf) == 0) { // 1 in 16 chance
    initiatePrefetch(); // Prefetch from random processor
  }

  if(m_status == TesterStatus_Idle) {
    initiateAction();
  } else if(m_status == TesterStatus_Ready) {
    initiateCheck();
  } else {
    // Pending - do nothing
    DEBUG_MSG(TESTER_COMP, MedPrio, "initiating action/check - failed: action/check is pending\n");
  }
}

void Check::initiatePrefetch(Sequencer* targetSequencer_ptr)
{
  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating prefetch");

  CacheRequestType type;
  if ((random() & 0x7) != 0) { // 1 in 8 chance
    if ((random() & 0x1) == 0) { // 50% chance
      type = CacheRequestType_LD;
    } else {
      type = CacheRequestType_IFETCH;
    }
  } else {
    type = CacheRequestType_ST;
  }

  Addr data_addr = m_address.getAddress();
  Addr pc_addr = m_pc.getAddress();
  Request request(0, data_addr, 0, Flags<unsigned int>(Request::PREFETCH), pc_addr, 0, 0);
  MemCmd::Command command;
  if (type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
    request.setFlags(Request::INST_FETCH);
  } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
  } else if (type == CacheRequestType_ST) {
    command = MemCmd::WriteReq;
  } else if (type == CacheRequestType_ATOMIC) {
    command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
  } else {
    panic("Cannot convert request to packet");
  }

  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID

  assert(targetSequencer_ptr != NULL);
  if (targetSequencer_ptr->isReady(&pkt)) {
    targetSequencer_ptr->makeRequest(&pkt);
  }
}

void Check::initiatePrefetch()
{
  // Any sequencer can issue a prefetch for this address
  Sequencer* targetSequencer_ptr = g_system_ptr->getChip(random() % RubyConfig::numberOfChips())->getSequencer(random() % RubyConfig::numberOfProcsPerChip());
  assert(targetSequencer_ptr != NULL);
  initiatePrefetch(targetSequencer_ptr);
}

void Check::initiateAction()
{
  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Action");
  assert(m_status == TesterStatus_Idle);

  CacheRequestType type = CacheRequestType_ST;
  if ((random() & 0x1) == 0) { // 50% chance
    type = CacheRequestType_ATOMIC;
  }

  Addr data_addr = m_address.getAddress()+m_store_count;
  Addr pc_addr = m_pc.getAddress();
  Request request(0, data_addr, 1, Flags<unsigned int>(), pc_addr, 0, 0);
  MemCmd::Command command;
  if (type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
    request.setFlags(Request::INST_FETCH);
  } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
  } else if (type == CacheRequestType_ST) {
    command = MemCmd::WriteReq;
  } else if (type == CacheRequestType_ATOMIC) {
    command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
  } else {
    panic("Cannot convert request to packet");
  }

  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID

  Sequencer* sequencer_ptr = initiatingSequencer();
  if (sequencer_ptr->isReady(&pkt) == false) {
    DEBUG_MSG(TESTER_COMP, MedPrio, "failed to initiate action - sequencer not ready\n");
  } else {
    DEBUG_MSG(TESTER_COMP, MedPrio, "initiating action - successful\n");
    DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
    m_status = TesterStatus_Action_Pending;

    sequencer_ptr->makeRequest(&pkt);
  }
  DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
}

void Check::initiateCheck()
{
  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Check");
  assert(m_status == TesterStatus_Ready);

  CacheRequestType type = CacheRequestType_LD;
  if ((random() & 0x1) == 0) { // 50% chance
    type = CacheRequestType_IFETCH;
  }

  Addr data_addr = m_address.getAddress()+m_store_count;
  Addr pc_addr = m_pc.getAddress();
  Request request(0, data_addr, CHECK_SIZE, Flags<unsigned int>(), pc_addr, 0, 0);
  MemCmd::Command command;
  if (type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
    request.setFlags(Request::INST_FETCH);
  } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
    command = MemCmd::ReadReq;
  } else if (type == CacheRequestType_ST) {
    command = MemCmd::WriteReq;
  } else if (type == CacheRequestType_ATOMIC) {
    command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
  } else {
    panic("Cannot convert request to packet");
  }

  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID

  Sequencer* sequencer_ptr = initiatingSequencer();
  if (sequencer_ptr->isReady(&pkt) == false) {
    DEBUG_MSG(TESTER_COMP, MedPrio, "failed to initiate check - sequencer not ready\n");
  } else {
    DEBUG_MSG(TESTER_COMP, MedPrio, "initiating check - successful\n");
    DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
    m_status = TesterStatus_Check_Pending;

    sequencer_ptr->makeRequest(&pkt);
  }
  DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
}

void Check::performCallback(NodeID proc, SubBlock& data)
{
  Address address = data.getAddress();
  //  assert(getAddress() == address);  // This isn't exactly right since we now have multi-byte checks
  assert(getAddress().getLineAddress() == address.getLineAddress());

  DEBUG_MSG(TESTER_COMP, MedPrio, "Callback");
  DEBUG_EXPR(TESTER_COMP, MedPrio, *this);

  if (m_status == TesterStatus_Action_Pending) {
    DEBUG_MSG(TESTER_COMP, MedPrio, "Action callback");
    // Perform store
    data.setByte(0, m_value+m_store_count); // We store one byte at a time
    m_store_count++;

    if (m_store_count == CHECK_SIZE) {
      m_status = TesterStatus_Ready;
    } else {
      m_status = TesterStatus_Idle;
    }
  } else if (m_status == TesterStatus_Check_Pending) {
    DEBUG_MSG(TESTER_COMP, MedPrio, "Check callback");
    // Perform load/check
    for(int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
      if (uint8(m_value+byte_number) != data.getByte(byte_number) && (DATA_BLOCK == true)) {
        WARN_EXPR(proc);
        WARN_EXPR(address);
        WARN_EXPR(data);
        WARN_EXPR(byte_number);
        WARN_EXPR((int)m_value+byte_number);
        WARN_EXPR((int)data.getByte(byte_number));
        WARN_EXPR(*this);
        WARN_EXPR(g_eventQueue_ptr->getTime());
        ERROR_MSG("Action/check failure");
      }
    }
    DEBUG_MSG(TESTER_COMP, HighPrio, "Action/check success:");
    DEBUG_EXPR(TESTER_COMP, HighPrio, *this);
    DEBUG_EXPR(TESTER_COMP, MedPrio, data);

    m_status = TesterStatus_Idle;
    pickValue();

  } else {
    WARN_EXPR(*this);
    WARN_EXPR(proc);
    WARN_EXPR(data);
    WARN_EXPR(m_status);
    WARN_EXPR(g_eventQueue_ptr->getTime());
    ERROR_MSG("Unexpected TesterStatus");
  }

  DEBUG_EXPR(TESTER_COMP, MedPrio, proc);
  DEBUG_EXPR(TESTER_COMP, MedPrio, data);
  DEBUG_EXPR(TESTER_COMP, MedPrio, getAddress().getLineAddress());
  DEBUG_MSG(TESTER_COMP, MedPrio, "Callback done");
  DEBUG_EXPR(TESTER_COMP, MedPrio, *this);
}

void Check::changeAddress(const Address& address)
{
  assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready));
  m_status = TesterStatus_Idle;
  m_address = address;
  m_store_count = 0;
}

Sequencer* Check::initiatingSequencer() const
{
  return g_system_ptr->getChip(m_initiatingNode/RubyConfig::numberOfProcsPerChip())->getSequencer(m_initiatingNode%RubyConfig::numberOfProcsPerChip());
}

void Check::pickValue()
{
  assert(m_status == TesterStatus_Idle);
  m_status = TesterStatus_Idle;
  //  DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
  DEBUG_MSG(TESTER_COMP, MedPrio, *this);
  m_value = random() & 0xff; // One byte
  //  DEBUG_MSG(TESTER_COMP, MedPrio, m_value);
  DEBUG_MSG(TESTER_COMP, MedPrio, *this);
  m_store_count = 0;
}

void Check::pickInitiatingNode()
{
  assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready));
  m_status = TesterStatus_Idle;
  DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
  m_initiatingNode = (random() % RubyConfig::numberOfProcessors());
  DEBUG_MSG(TESTER_COMP, MedPrio, m_initiatingNode);
  m_store_count = 0;
}

void Check::print(ostream& out) const
{
  out << "["
      << m_address << ", value: "
      << (int) m_value << ", status: "
      << m_status << ", initiating node: "
      << m_initiatingNode << ", store_count: "
      << m_store_count
      << "]" << flush;
}
<|endoftext|>


<commit_before><commit_msg>Fix error in GL renderer<commit_after><|endoftext|>


<commit_before>#pragma once

#include "protofy.hpp"

#include <boost/proto/core.hpp>
#include <boost/proto/debug.hpp>
#include <boost/proto/transform.hpp>
#include <boost/proto/functional/fusion/at.hpp>
#include <boost/fusion/container/generation/make_vector.hpp>

namespace metaSMT {

  namespace detail {
    // implementation details

    template <typename N>
    struct argument
    {
      typedef N type;
      enum { value = N::value };
    };

    //template<typename O, typename N>
    //O& operator<< (O & out, argument<N> const & ) {
    //  return out << "arg" << (N::value+1);
    //}

    struct replace_args
    : proto::or_<
        proto::when<proto::terminal< argument<proto::_> >
          , boost::proto::functional::at( proto::_state, proto::_value )
        >
      , proto::nary_expr<proto::_, proto::vararg<replace_args> >
    > {};

    template <typename Context, typename Expr>
    struct lazy_call {

      lazy_call(Context& ctx, Expr const & e)
      : ctx_( ctx )
      , e_( proto::deep_copy(e) )
      { }

      typename Context::result_type operator() ( )
      {
        return evaluate(ctx_, e_);
      }

      template<typename Arg1>
      typename Context::result_type operator() ( Arg1 const & arg1)
      {
        return evaluate(ctx_, replace_args()(e_,
          boost::fusion::make_vector( protofy(arg1) )
        ));
      }

      template<typename Arg1, typename Arg2>
      typename Context::result_type operator() ( Arg1 const & arg1
        , Arg2 const & arg2 )
      {
        return evaluate(ctx_, replace_args()(e_,
          boost::fusion::make_vector( protofy(arg1), protofy(arg2) )
        ));
      }

      template<typename Arg1, typename Arg2, typename Arg3>
      typename Context::result_type operator() ( Arg1 const & arg1
        , Arg2 const & arg2, Arg3 const & arg3 )
      {
        return evaluate(ctx_, replace_args()(e_,
          boost::fusion::make_vector(protofy(arg1), protofy(arg2), protofy(arg3))
        ));
      }

      typename proto::result_of::deep_copy<Expr>::type e_;
      Context & ctx_;
    };

  } /* detail */

  /**
   * @brief lazy evaluation of expressions with arguments
   *
   * lazy created a polymorphic function object that, when called
   * evaluates the enclosed expression.
   *
   * lazy can be used store an expression in a function
   * @code
   * boost::function< result_type ( predicate const &, predicate const & ) >
   *   andiN = metaSMT::lazy( ctx, And( arg1, Not(arg2)) ) ;
   * @endcode
   *
   * or to use in stl algorithms:
   * @code
   * std::vector< result_type > expr;
   * ...
   * tmp = std::accumulate(expr.begin(), expr.end(), initial,
   *    metaSMT::lazy(ctx, Xor(arg1, arg2) )
   * );
   * @endcode
   *
   * @ingroup Support
   * @defgroup Lazy Lazy expression evaluation
   * @{
   */

  /**
   * @brief create a functor from an expression
   */
  template< typename Context, typename Expr>
  detail::lazy_call< Context, Expr >
  lazy(Context & ctx, Expr const & e)
  {
    return detail::lazy_call< Context, Expr> (ctx, e);
  }

  /**
   * @brief placeholder for an argument of lazy
   */
  static const detail::argument< boost::mpl::int_<0> > arg1 = {};
  /**
   * @brief placeholder for an argument of lazy
   */
  static const detail::argument< boost::mpl::int_<1> > arg2 = {};
  /**
   * @brief placeholder for an argument of lazy
   */
  static const detail::argument< boost::mpl::int_<2> > arg3 = {};

  /**@}*/
} /* metaSMT */

<commit_msg>fixed warning about initialization order in lazy<commit_after>#pragma once

#include "protofy.hpp"

#include <boost/proto/core.hpp>
#include <boost/proto/debug.hpp>
#include <boost/proto/transform.hpp>
#include <boost/proto/functional/fusion/at.hpp>
#include <boost/fusion/container/generation/make_vector.hpp>

namespace metaSMT {

  namespace detail {
    // implementation details

    template <typename N>
    struct argument
    {
      typedef N type;
      enum { value = N::value };
    };

    //template<typename O, typename N>
    //O& operator<< (O & out, argument<N> const & ) {
    //  return out << "arg" << (N::value+1);
    //}

    struct replace_args
    : proto::or_<
        proto::when<proto::terminal< argument<proto::_> >
          , boost::proto::functional::at( proto::_state, proto::_value )
        >
      , proto::nary_expr<proto::_, proto::vararg<replace_args> >
    > {};

    template <typename Context, typename Expr>
    struct lazy_call {

      lazy_call(Context& ctx, Expr const & e)
      : ctx_( ctx )
      , e_( proto::deep_copy(e) )
      { }

      typename Context::result_type operator() ( )
      {
        return evaluate(ctx_, e_);
      }

      template<typename Arg1>
      typename Context::result_type operator() ( Arg1 const & arg1)
      {
        return evaluate(ctx_, replace_args()(e_,
          boost::fusion::make_vector( protofy(arg1) )
        ));
      }

      template<typename Arg1, typename Arg2>
      typename Context::result_type operator() ( Arg1 const & arg1
        , Arg2 const & arg2 )
      {
        return evaluate(ctx_, replace_args()(e_,
          boost::fusion::make_vector( protofy(arg1), protofy(arg2) )
        ));
      }

      template<typename Arg1, typename Arg2, typename Arg3>
      typename Context::result_type operator() ( Arg1 const & arg1
        , Arg2 const & arg2, Arg3 const & arg3 )
      {
        return evaluate(ctx_, replace_args()(e_,
          boost::fusion::make_vector(protofy(arg1), protofy(arg2), protofy(arg3))
        ));
      }

      Context & ctx_;
      typename proto::result_of::deep_copy<Expr>::type e_;
    };

  } /* detail */

  /**
   * @brief lazy evaluation of expressions with arguments
   *
   * lazy created a polymorphic function object that, when called
   * evaluates the enclosed expression.
   *
   * lazy can be used store an expression in a function
   * @code
   * boost::function< result_type ( predicate const &, predicate const & ) >
   *   andiN = metaSMT::lazy( ctx, And( arg1, Not(arg2)) ) ;
   * @endcode
   *
   * or to use in stl algorithms:
   * @code
   * std::vector< result_type > expr;
   * ...
   * tmp = std::accumulate(expr.begin(), expr.end(), initial,
   *    metaSMT::lazy(ctx, Xor(arg1, arg2) )
   * );
   * @endcode
   *
   * @ingroup Support
   * @defgroup Lazy Lazy expression evaluation
   * @{
   */

  /**
   * @brief create a functor from an expression
   */
  template< typename Context, typename Expr>
  detail::lazy_call< Context, Expr >
  lazy(Context & ctx, Expr const & e)
  {
    return detail::lazy_call< Context, Expr> (ctx, e);
  }

  /**
   * @brief placeholder for an argument of lazy
   */
  static const detail::argument< boost::mpl::int_<0> > arg1 = {};
  /**
   * @brief placeholder for an argument of lazy
   */
  static const detail::argument< boost::mpl::int_<1> > arg2 = {};
  /**
   * @brief placeholder for an argument of lazy
   */
  static const detail::argument< boost::mpl::int_<2> > arg3 = {};

  /**@}*/
} /* metaSMT */

<|endoftext|>


<commit_before><commit_msg>Fix post processing pipeline bug<commit_after><|endoftext|>


<commit_before>#ifndef ALEPH_TOPOLOGY_IO_LINES_AND_POINTS_HH__
#define ALEPH_TOPOLOGY_IO_LINES_AND_POINTS_HH__

#include <fstream>
#include <ostream>
#include <stdexcept>
#include <string>

namespace aleph
{

namespace topology
{

namespace io
{

/**
  @class LinesAndPoints
  @brief Writes files as lines and points

  This writer class uses coordinate information of a simplicial complex
  to represent its 1-skeleton, i.e. its vertices and edges. All data is
  stored in a simple format, representing 0-simplex by its coordinates,
  and a 1-simplex by a sequence of coordinates.

  An edge \f$(u,v)\f$ will be stored as:

  \[
    x_u y_u
    x_v y_v\n
  \]

  Vertices and edges will be separated by two newlines in order to show
  that a new block was started. This makes it possible to use `gnuplot`
  for the visualization:

  \code
  plot "output.txt" index 0 with points pt 7, # to represent vertices
       ""           index 1 with lines        # to represent edges
  \endcode
*/

class LinesAndPoints
{
public:

  /** Writes the simplicial complex to a new file. */
  template <class SimplicialComplex, class Container> void operator()( const std::string& filename,
                                                                       const SimplicialComplex& K,
                                                                       const Container& container )
  {
    std::ofstream out( filename );
    if( !out )
      throw std::runtime_error( "Unable to open output file" );

    this->operator()( out, K, container );
  }

  /** Writes the simplicial complex to a new output stream. */
  template <class SimplicialComplex, class Container> void operator()( std::ostream& out,
                                                                       const SimplicialComplex& K,
                                                                       const Container& container )
  {
    for( auto&& s : K )
    {
      if( s.dimension() != 0 )
        continue;

      auto u = s[0];         // vertex
      auto p = container[u]; // coordinate

      if( p.size() >= 2 )
        out << p[0] << "\t" << p[1] << "\n";
      else
        throw std::runtime_error( "Insufficient number of dimensions for storing coordinates" );
    }

    out << "\n\n";

    for( auto&& s : K )
    {
      if( s.dimension() != 1 )
        continue;

      auto u = s[0];         // vertex
      auto v = s[1];         // vertex
      auto p = container[u]; // first coordinate
      auto q = container[v]; // second coordinate

      if( p.size() >= 2 && q.size() >= 2 )
      {
        out << p[0] << "\t" << p[1] << "\n"
            << q[0] << "\t" << q[1] << "\n\n";
      }
      else
        throw std::runtime_error( "Insufficient number of dimensions for storing coordinates" );
    }
  }
};

} // namespace io

} // namespace topology

} // namespace aleph

#endif
<commit_msg>Updated output for lines and points visualization<commit_after>#ifndef ALEPH_TOPOLOGY_IO_LINES_AND_POINTS_HH__
#define ALEPH_TOPOLOGY_IO_LINES_AND_POINTS_HH__

#include <fstream>
#include <ostream>
#include <stdexcept>
#include <string>

namespace aleph
{

namespace topology
{

namespace io
{

/**
  @class LinesAndPoints
  @brief Writes files as lines and points

  This writer class uses coordinate information of a simplicial complex
  to represent its 1-skeleton, i.e. its vertices and edges. All data is
  stored in a simple format, representing 0-simplex by its coordinates,
  and a 1-simplex by a sequence of coordinates.

  An edge \f$(u,v)\f$ will be stored as:

  \[
    x_u y_u
    x_v y_v\n
  \]

  Vertices and edges will be separated by two newlines in order to show
  that a new block was started. This makes it possible to use `gnuplot`
  for the visualization:

  \code
  plot "output.txt" index 0 with points pt 7, # to represent vertices
       ""           index 1 with lines        # to represent edges
  \endcode
*/

class LinesAndPoints
{
public:

  /** Writes the simplicial complex to a new file. */
  template <class SimplicialComplex, class Container> void operator()( const std::string& filename,
                                                                       const SimplicialComplex& K,
                                                                       const Container& container )
  {
    std::ofstream out( filename );
    if( !out )
      throw std::runtime_error( "Unable to open output file" );

    this->operator()( out, K, container );
  }

  /** Writes the simplicial complex to a new output stream. */
  template <class SimplicialComplex, class Container> void operator()( std::ostream& out,
                                                                       const SimplicialComplex& K,
                                                                       const Container& container )
  {
    for( auto&& s : K )
    {
      if( s.dimension() != 0 )
        continue;

      auto u = s[0];         // vertex
      auto p = container[u]; // coordinate

      if( p.size() >= 2 )
        write( out, p );
      else
        throw std::runtime_error( "Insufficient number of dimensions for storing coordinates" );
    }

    out << "\n\n";

    for( auto&& s : K )
    {
      if( s.dimension() != 1 )
        continue;

      auto u = s[0];         // vertex
      auto v = s[1];         // vertex
      auto p = container[u]; // first coordinate
      auto q = container[v]; // second coordinate

      if( p.size() >= 2 && q.size() >= 2 )
      {
        write(out, p);
        write(out, q);

        out << "\n";
      }
      else
        throw std::runtime_error( "Insufficient number of dimensions for storing coordinates" );
    }
  }
private:
  template <class Container> void write( std::ostream& out, Container& p )
  {
    out << p[0] << "\t" << p[1] << " ";

    if( p.size() >= 3 )
      out << p[2];

    out << "\n";
  }
};

} // namespace io

} // namespace topology

} // namespace aleph

#endif
<|endoftext|>