<commit_before>/*
Copyright (C) 2016 iNuron NV

This file is part of Open vStorage Open Source Edition (OSE), as available from

    http://www.openvstorage.org and
    http://www.openvstorage.com.

This file is free software; you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License v3 (GNU AGPLv3)
as published by the Free Software Foundation, in version 3 as it comes
in the <LICENSE.txt> file of the Open vStorage OSE distribution.

Open vStorage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY of any kind.
*/

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/log/trivial.hpp>

#include <chrono>
#include <ctime>
#include <iomanip>
#include <fstream>

#include "stuff.h"
#include "proxy_client.h"
#include "alba_logger.h"

using std::string;
using std::cout;
using std::endl;

using namespace alba::stuff;

namespace po = boost::program_options;

template <typename T> T getRequiredArg(po::variables_map map, string arg) {
  if (!map.count(arg)) {
    cout << "specify required argument --" << arg << endl;
    exit(1);
  }
  return map[arg].as<T>();
}

string getRequiredStringArg(po::variables_map map, string arg) {
  return getRequiredArg<string>(map, arg);
}

void logBoostMethod(alba::logger::AlbaLogLevel /*level */, std::string &msg) {
  // there should actually be a translation from AlbaLogLevel to some boost
  // log level here, but I'm too lazy for this test client
  BOOST_LOG_TRIVIAL(debug) << msg;
}

std::function<void(alba::logger::AlbaLogLevel, std::string &)> logBoost =
    std::function<void(alba::logger::AlbaLogLevel, std::string &)>(
        logBoostMethod);
std::function<void(alba::logger::AlbaLogLevel, std::string &)> *nulllog =
    nullptr;

using namespace alba::proxy_client;

void proxy_get_version(const string &host, const string &port,
                       const boost::asio::time_traits<
                           boost::posix_time::ptime>::duration_type &timeout,
                       const Transport &transport) {
  auto client = make_proxy_client(host, port, timeout, transport);
  auto version = client->get_proxy_version();

  int major = std::get<0>(version);
  int minor = std::get<1>(version);
  int patch = std::get<2>(version);
  string commit = std::get<3>(version);
  cout << "( " << major << ", " << minor << ", " << patch << ", " << commit
       << ")" << endl;
}

using namespace std::chrono;

void partial_read_benchmark(const string& host,
                            const string& port,
                            const boost::asio::time_traits<
                            boost::posix_time::ptime>::duration_type &timeout,
                            const Transport& transport,
                            const string& namespace_,
                            const string& file_name,
                            const int n,
                            const bool use_rora
    ){

    ALBA_LOG(WARNING, "partial_read_benchmark(" << host << ", " << port <<", " << transport << ")");
    auto client = make_proxy_client(host, port, timeout, transport, use_rora);
    string name = "object_000";
    const alba::Checksum* checksum = nullptr;
    using namespace alba::proxy_protocol;
    client -> write_object_fs(namespace_,
                              name,
                              file_name,
                              allow_overwrite::T,
                              checksum);

    ALBA_LOG(INFO, "uploaded" << file_name);

    std::vector<alba::byte> buffer(4096);
    SliceDescriptor sd {&buffer[0], 0,4096};
    std::vector<SliceDescriptor> slices { sd };
    ObjectSlices object_slices{name, slices};
    std::vector<ObjectSlices> objects_slices {object_slices};

    high_resolution_clock::time_point t0, t1, t2;
    double min_dur = 1000000;
    double max_dur = 0;
    std::vector<double> borders{100,200,250, 300, 350, 400, 800,100000};
    int borders_size = borders.size();
    int last_index = borders_size- 1;
    std::vector<double> dur_buckets(borders_size);
    t0 = high_resolution_clock::now();
    for(int i= 0;i < n;i++){
        t1 = high_resolution_clock::now();
        client -> read_objects_slices(namespace_, objects_slices,
                                      consistent_read::F);
        t2 = high_resolution_clock::now();

        int duration = duration_cast<microseconds>( t2 - t1 ).count();

        if(duration < min_dur){
            min_dur = duration;
        }
        if(duration > max_dur){
            max_dur = duration;
        }
        int border_index = 0;
        bool set = false;

        while (border_index < last_index){
            double border = borders[border_index];
            if (duration < border){
                dur_buckets[border_index] = dur_buckets[border_index] + 1;
                set = true;
                break;
            }
            border_index++;
        }
        if(!set){
            dur_buckets[last_index] = dur_buckets[last_index] + 1;
        }
        int dur2 = duration_cast<seconds>(t2 - t0).count();
        int reporting_period = 1;
        if(dur2 > reporting_period){
            auto time2 = system_clock::to_time_t(t2);
            //struct tm tm;
            char buffer[26];
            ctime_r(&time2, buffer);
            buffer[24] = '\0';  // Removes the newline that is added
            //localtime_r(&time2, &tm);
            cout << buffer << " i:" << i << std::endl;
            t0 = t0 + seconds(reporting_period);
        }

    }

    cout << "min_dur:" << min_dur <<std::endl;
    cout << "max_dur:" << max_dur <<std::endl;
    cout << "borders:" << borders <<std::endl;
    cout << "buckets:" << dur_buckets << std::endl;
}

int main(int argc, const char *argv[]) {
  alba::logger::setLogFunction([&](alba::logger::AlbaLogLevel level) {
    switch (level) {
    case alba::logger::AlbaLogLevel::WARNING:
      return &logBoost;
    default:
      return nulllog;
    };
  });

  ALBA_LOG(WARNING, "cucu")

  po::options_description desc("Allowed options");
  desc.add_options()("help", "produce help message")(
      "command", po::value<string>(),
      "the command you want to execute:\n"
      "\tdownload-object, download-object-partial, "
      " upload-object, delete-object, list-objects, "
      " show-object, delete-namespace, create-namespace, "
      " list-namespaces, invalidata-cache, proxy-get-version"
      " partial-read-benchmark"
      )(
      "port", po::value<string>()->default_value("10000"),
      "the alba proxy port number")(
      "host", po::value<string>()->default_value("127.0.0.1"),
      "the alba proxy port hostname")

      ("namespace", po::value<string>(), "the namespace for the relevant operation")
      ("name", po::value<string>(),"the name of the object to download/upload/delete")
      ("allow-cached", po::value<bool>()->default_value(false),"can we use cached information?")
      ("consistent-read", po::value<bool>()->default_value(true),"consistent read?")
      ("transport", po::value<string>(),"rdma | tcp (default = tcp)")
      ("file", po::value<string>(), "file to work with for download/upload")
      ("length", po::value<uint32_t>(), "length for partial object read")
      ("offset", po::value<uint64_t>()->default_value(0),"offset for partial object read")
      ("benchmark-size", po::value<uint32_t>() -> default_value(1000), "size of benchmark")
      ("use-rora", po::value<bool>() -> default_value(false), "use rora fetcher or not");
  po::positional_options_description positionalOptions;
  positionalOptions.add("command", 1);

  po::variables_map vm;

  po::store(po::command_line_parser(argc, argv)
                .options(desc)
                .positional(positionalOptions)
                .run(),
            vm);
  po::notify(vm);

  if (vm.count("help")) {
    cout << desc << endl;
    return 1;
  }

  string command = getRequiredStringArg(vm, "command");
  string port = vm["port"].as<string>();
  string host = vm["host"].as<string>();

  auto timeout = boost::posix_time::seconds(5);
  Transport transport(Transport::tcp);

  if (vm.count("transport")) {
    string transport_s = vm["transport"].as<string>();
    if (transport_s == "rdma") {
      transport = Transport::rdma;
    } else {
      assert(transport_s == "tcp");
    }
  };

  bool consistent_read_b = vm["consistent-read"].as<bool>();

  consistent_read _consistent_read =
      consistent_read_b ? consistent_read::T : consistent_read::F;
  should_cache _should_cache = should_cache::T;
  ALBA_LOG(WARNING, "parsed command line options: command = " << command);

  if ("download-object" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    string name = getRequiredStringArg(vm, "name");
    string file = getRequiredStringArg(vm, "file");
    auto client = make_proxy_client(host, port, timeout, transport);
    client->read_object_fs(ns, name, file, _consistent_read, _should_cache);
  } else if ("download-object-partial" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    string name = getRequiredStringArg(vm, "name");
    string file = getRequiredStringArg(vm, "file");
    auto offset = vm["offset"].as<uint64_t>();
    auto length = getRequiredArg<uint32_t>(vm, "length");
    auto client = make_proxy_client(host, port, timeout, transport);
    auto buf = std::unique_ptr<unsigned char>(new unsigned char[length]);
    alba::proxy_protocol::SliceDescriptor slice{buf.get(), offset, length};
    alba::proxy_protocol::ObjectSlices object_slices{name, {slice}};
    client->read_objects_slices(ns, {object_slices}, _consistent_read);
    std::ofstream fout(file);
    fout.write((char *)buf.get(), length);
  } else if ("upload-object" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    string name = getRequiredStringArg(vm, "name");
    string file = getRequiredStringArg(vm, "file");
    auto client = make_proxy_client(host, port, timeout, transport);
    client->write_object_fs(ns, name, file,
                            alba::proxy_client::allow_overwrite::T, nullptr);
  } else if ("delete-object" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    string name = getRequiredStringArg(vm, "name");
    auto client = make_proxy_client(host, port, timeout, transport);
    client->delete_object(ns, name, alba::proxy_client::may_not_exist::T);
  } else if ("list-objects" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    auto client = make_proxy_client(host, port, timeout, transport);
    string first("");
    auto res = client->list_objects(
        ns, first, alba::proxy_client::include_first::T, boost::none,
        alba::proxy_client::include_last::T, -1);
    auto objects = std::get<0>(res);
    auto has_more = std::get<1>(res);
    cout << "received " << objects.size() << " objects" << endl;
    cout << "[ ";
    for (auto &object : objects) {
      cout << object << ",\n";
    }
    cout << " ]" << endl;
    cout << has_more << endl;
  } else if ("show-object" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    string name = getRequiredStringArg(vm, "name");
    auto client = make_proxy_client(host, port, timeout, transport);
    try {
      uint64_t size;
      alba::Checksum *checksum;
      std::tie(size, checksum) =
          client->get_object_info(ns, name, _consistent_read, _should_cache);
      cout << "size = " << size << "\n checksum = " << *checksum;
      delete checksum;
    } catch (alba::proxy_client::proxy_exception &e) {
      cout << e.what() << endl;
    }
  } else if ("delete-namespace" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    auto client = make_proxy_client(host, port, timeout, transport);
    try {
      client->delete_namespace(ns);
    } catch (alba::proxy_client::proxy_exception &e) {
      cout << e.what() << endl;
    }
  } else if ("create-namespace" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    auto client = make_proxy_client(host, port, timeout, transport);
    try {
      client->create_namespace(ns, boost::none);
    } catch (alba::proxy_client::proxy_exception &e) {
      cout << e.what() << endl;
    }
  } else if ("list-namespaces" == command) {
    auto client = make_proxy_client(host, port, timeout, transport);
    std::vector<string> namespaces;
    alba::proxy_client::has_more has_more;
    std::tie(namespaces, has_more) = client->list_namespaces(
        "", alba::proxy_client::include_first::T, boost::none,
        alba::proxy_client::include_last::T, -1);

    cout << namespaces << endl
         << has_more << endl;

  } else if ("invalidate-cache" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    auto client = make_proxy_client(host, port, timeout, transport);
    try {
      client->invalidate_cache(ns);
    } catch (alba::proxy_client::proxy_exception &e) {
      cout << e.what() << endl;
    }
  } else if ("proxy-get-version" == command) {
    proxy_get_version(host, port, timeout, transport);

  } else if ("namespace-exists" == command) {
    auto client = make_proxy_client(host, port, timeout, transport);
    string ns = getRequiredStringArg(vm, "namespace");
    bool result = client->namespace_exists(ns);
    cout << "namespace_exists(" << ns << ") => " << result << endl;
  } else if("partial-read-benchmark") {
    string ns = getRequiredStringArg(vm, "namespace");
    string file = getRequiredStringArg(vm, "file");
    uint32_t n = getRequiredArg<uint32_t>(vm, "benchmark-size");
    bool use_rora = getRequiredArg<bool>(vm, "use-rora");
    partial_read_benchmark(host,port,timeout,transport, ns, file, n, use_rora);
  } else {
    cout << "got invalid command name. valid options are: "
         << "download-object, upload-object, delete-object, list-objects "
         << "show-object, delete-namespace, create-namespace, list-namespaces, "
         << "invalidate-cache, proxy-get-version, namespace-exists" << endl;
    return 1;
  }
  return 0;
}
<commit_msg>small improvements to test_client<commit_after>/*
Copyright (C) 2016 iNuron NV

This file is part of Open vStorage Open Source Edition (OSE), as available from

    http://www.openvstorage.org and
    http://www.openvstorage.com.

This file is free software; you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License v3 (GNU AGPLv3)
as published by the Free Software Foundation, in version 3 as it comes
in the <LICENSE.txt> file of the Open vStorage OSE distribution.

Open vStorage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY of any kind.
*/

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>

#include <chrono>
#include <ctime>
#include <iomanip>
#include <fstream>

#include "stuff.h"
#include "proxy_client.h"
#include "alba_logger.h"

using std::string;
using std::cout;
using std::endl;

using namespace alba::stuff;

namespace po = boost::program_options;

template <typename T> T getRequiredArg(po::variables_map map, string arg) {
  if (!map.count(arg)) {
    cout << "specify required argument --" << arg << endl;
    exit(1);
  }
  return map[arg].as<T>();
}

string getRequiredStringArg(po::variables_map map, string arg) {
  return getRequiredArg<string>(map, arg);
}

void logBoostMethod(alba::logger::AlbaLogLevel /*level */, std::string &msg) {
  // there should actually be a translation from AlbaLogLevel to some boost
  // log level here, but I'm too lazy for this test client
  BOOST_LOG_TRIVIAL(debug) << msg;
}

std::function<void(alba::logger::AlbaLogLevel, std::string &)> logBoost =
    std::function<void(alba::logger::AlbaLogLevel, std::string &)>(
        logBoostMethod);
std::function<void(alba::logger::AlbaLogLevel, std::string &)> *nulllog =
    nullptr;

using namespace alba::proxy_client;

void proxy_get_version(const string &host, const string &port,
                       const boost::asio::time_traits<
                           boost::posix_time::ptime>::duration_type &timeout,
                       const Transport &transport) {
  auto client = make_proxy_client(host, port, timeout, transport);
  auto version = client->get_proxy_version();

  int major = std::get<0>(version);
  int minor = std::get<1>(version);
  int patch = std::get<2>(version);
  string commit = std::get<3>(version);
  cout << "( " << major << ", " << minor << ", " << patch << ", " << commit
       << ")" << endl;
}

using namespace std::chrono;

void partial_read_benchmark(const string& host,
                            const string& port,
                            const boost::asio::time_traits<
                            boost::posix_time::ptime>::duration_type &timeout,
                            const Transport& transport,
                            const string& namespace_,
                            const string& file_name,
                            const int n,
                            const bool use_rora
    ){

    ALBA_LOG(WARNING, "partial_read_benchmark("
             << host << ", " << port
             << ", " << transport
             << ", use_rora=" << use_rora
             << ")");
    auto client = make_proxy_client(host, port, timeout, transport, use_rora);
    string name = "object_000";
    const alba::Checksum* checksum = nullptr;
    using namespace alba::proxy_protocol;
    client -> write_object_fs(namespace_,
                              name,
                              file_name,
                              allow_overwrite::T,
                              checksum);

    ALBA_LOG(INFO, "uploaded" << file_name);

    std::vector<alba::byte> buffer(4096);
    SliceDescriptor sd {&buffer[0], 0,4096};
    std::vector<SliceDescriptor> slices { sd };
    ObjectSlices object_slices{name, slices};
    std::vector<ObjectSlices> objects_slices {object_slices};

    high_resolution_clock::time_point t0, t1, t2;
    double min_dur = 1000000;
    double max_dur = 0;
    std::vector<double> borders{100, 125, 150, 175, 200, 225, 250, 300, 350, 400, 800,100000};
    int borders_size = borders.size();
    int last_index = borders_size- 1;
    std::vector<double> dur_buckets(borders_size);
    t0 = high_resolution_clock::now();
    for(int i= 0;i < n;i++){
        t1 = high_resolution_clock::now();
        client -> read_objects_slices(namespace_, objects_slices,
                                      consistent_read::F);
        t2 = high_resolution_clock::now();

        int duration = duration_cast<microseconds>( t2 - t1 ).count();

        if(duration < min_dur){
            min_dur = duration;
        }
        if(duration > max_dur){
            max_dur = duration;
        }
        int border_index = 0;
        bool set = false;

        while (border_index < last_index){
            double border = borders[border_index];
            if (duration < border){
                dur_buckets[border_index] = dur_buckets[border_index] + 1;
                set = true;
                break;
            }
            border_index++;
        }
        if(!set){
            dur_buckets[last_index] = dur_buckets[last_index] + 1;
        }
        int dur2 = duration_cast<seconds>(t2 - t0).count();
        int reporting_period = 1;
        if(dur2 > reporting_period){
            auto time2 = system_clock::to_time_t(t2);
            //struct tm tm;
            char buffer[26];
            ctime_r(&time2, buffer);
            buffer[24] = '\0';  // Removes the newline that is added
            //localtime_r(&time2, &tm);
            cout << buffer << " i:" << i << std::endl;
            t0 = t0 + seconds(reporting_period);
        }

    }

    cout << "min_dur:" << min_dur <<std::endl;
    cout << "max_dur:" << max_dur <<std::endl;
    cout << "borders:" << borders <<std::endl;
    cout << "buckets:" << dur_buckets << std::endl;
}

int main(int argc, const char *argv[]) {
  alba::logger::setLogFunction([&](alba::logger::AlbaLogLevel level) {
    switch (level) {
    case alba::logger::AlbaLogLevel::WARNING:
      return &logBoost;
    default:
      return nulllog;
    };
  });

  ALBA_LOG(WARNING, "cucu")

  //gobjfs directly plugs in boost logging.
  namespace logging = boost::log;
  logging::core::get()->set_filter
      (
       logging::trivial::severity >= logging::trivial::info
       );

  po::options_description desc("Allowed options");
  desc.add_options()("help", "produce help message")(
      "command", po::value<string>(),
      "the command you want to execute:\n"
      "\tdownload-object, download-object-partial, "
      " upload-object, delete-object, list-objects, "
      " show-object, delete-namespace, create-namespace, "
      " list-namespaces, invalidata-cache, proxy-get-version"
      " partial-read-benchmark"
      )(
      "port", po::value<string>()->default_value("10000"),
      "the alba proxy port number")(
      "host", po::value<string>()->default_value("127.0.0.1"),
      "the alba proxy port hostname")

      ("namespace", po::value<string>(), "the namespace for the relevant operation")
      ("name", po::value<string>(),"the name of the object to download/upload/delete")
      ("allow-cached", po::value<bool>()->default_value(false),"can we use cached information?")
      ("consistent-read", po::value<bool>()->default_value(true),"consistent read?")
      ("transport", po::value<string>(),"rdma | tcp (default = tcp)")
      ("file", po::value<string>(), "file to work with for download/upload")
      ("length", po::value<uint32_t>(), "length for partial object read")
      ("offset", po::value<uint64_t>()->default_value(0),"offset for partial object read")
      ("benchmark-size", po::value<uint32_t>() -> default_value(1000), "size of benchmark")
      ("use-rora", po::value<bool>() -> default_value(true), "use rora fetcher or not");

  po::positional_options_description positionalOptions;
  positionalOptions.add("command", 1);

  po::variables_map vm;

  po::store(po::command_line_parser(argc, argv)
                .options(desc)
                .positional(positionalOptions)
                .run(),
            vm);
  po::notify(vm);

  if (vm.count("help")) {
    cout << desc << endl;
    return 1;
  }

  string command = getRequiredStringArg(vm, "command");
  string port = vm["port"].as<string>();
  string host = vm["host"].as<string>();

  auto timeout = boost::posix_time::seconds(5);
  Transport transport(Transport::tcp);

  if (vm.count("transport")) {
    string transport_s = vm["transport"].as<string>();
    if (transport_s == "rdma") {
      transport = Transport::rdma;
    } else {
      assert(transport_s == "tcp");
    }
  };

  bool consistent_read_b = vm["consistent-read"].as<bool>();

  consistent_read _consistent_read =
      consistent_read_b ? consistent_read::T : consistent_read::F;
  should_cache _should_cache = should_cache::T;
  ALBA_LOG(WARNING, "parsed command line options: command = " << command);

  if ("download-object" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    string name = getRequiredStringArg(vm, "name");
    string file = getRequiredStringArg(vm, "file");
    auto client = make_proxy_client(host, port, timeout, transport);
    client->read_object_fs(ns, name, file, _consistent_read, _should_cache);
  } else if ("download-object-partial" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    string name = getRequiredStringArg(vm, "name");
    string file = getRequiredStringArg(vm, "file");
    auto offset = vm["offset"].as<uint64_t>();
    auto length = getRequiredArg<uint32_t>(vm, "length");
    auto client = make_proxy_client(host, port, timeout, transport);
    auto buf = std::unique_ptr<unsigned char>(new unsigned char[length]);
    alba::proxy_protocol::SliceDescriptor slice{buf.get(), offset, length};
    alba::proxy_protocol::ObjectSlices object_slices{name, {slice}};
    client->read_objects_slices(ns, {object_slices}, _consistent_read);
    std::ofstream fout(file);
    fout.write((char *)buf.get(), length);
  } else if ("upload-object" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    string name = getRequiredStringArg(vm, "name");
    string file = getRequiredStringArg(vm, "file");
    auto client = make_proxy_client(host, port, timeout, transport);
    client->write_object_fs(ns, name, file,
                            alba::proxy_client::allow_overwrite::T, nullptr);
  } else if ("delete-object" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    string name = getRequiredStringArg(vm, "name");
    auto client = make_proxy_client(host, port, timeout, transport);
    client->delete_object(ns, name, alba::proxy_client::may_not_exist::T);
  } else if ("list-objects" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    auto client = make_proxy_client(host, port, timeout, transport);
    string first("");
    auto res = client->list_objects(
        ns, first, alba::proxy_client::include_first::T, boost::none,
        alba::proxy_client::include_last::T, -1);
    auto objects = std::get<0>(res);
    auto has_more = std::get<1>(res);
    cout << "received " << objects.size() << " objects" << endl;
    cout << "[ ";
    for (auto &object : objects) {
      cout << object << ",\n";
    }
    cout << " ]" << endl;
    cout << has_more << endl;
  } else if ("show-object" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    string name = getRequiredStringArg(vm, "name");
    auto client = make_proxy_client(host, port, timeout, transport);
    try {
      uint64_t size;
      alba::Checksum *checksum;
      std::tie(size, checksum) =
          client->get_object_info(ns, name, _consistent_read, _should_cache);
      cout << "size = " << size << "\n checksum = " << *checksum;
      delete checksum;
    } catch (alba::proxy_client::proxy_exception &e) {
      cout << e.what() << endl;
    }
  } else if ("delete-namespace" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    auto client = make_proxy_client(host, port, timeout, transport);
    try {
      client->delete_namespace(ns);
    } catch (alba::proxy_client::proxy_exception &e) {
      cout << e.what() << endl;
    }
  } else if ("create-namespace" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    auto client = make_proxy_client(host, port, timeout, transport);
    try {
      client->create_namespace(ns, boost::none);
    } catch (alba::proxy_client::proxy_exception &e) {
      cout << e.what() << endl;
    }
  } else if ("list-namespaces" == command) {
    auto client = make_proxy_client(host, port, timeout, transport);
    std::vector<string> namespaces;
    alba::proxy_client::has_more has_more;
    std::tie(namespaces, has_more) = client->list_namespaces(
        "", alba::proxy_client::include_first::T, boost::none,
        alba::proxy_client::include_last::T, -1);

    cout << namespaces << endl
         << has_more << endl;

  } else if ("invalidate-cache" == command) {
    string ns = getRequiredStringArg(vm, "namespace");
    auto client = make_proxy_client(host, port, timeout, transport);
    try {
      client->invalidate_cache(ns);
    } catch (alba::proxy_client::proxy_exception &e) {
      cout << e.what() << endl;
    }
  } else if ("proxy-get-version" == command) {
    proxy_get_version(host, port, timeout, transport);

  } else if ("namespace-exists" == command) {
    auto client = make_proxy_client(host, port, timeout, transport);
    string ns = getRequiredStringArg(vm, "namespace");
    bool result = client->namespace_exists(ns);
    cout << "namespace_exists(" << ns << ") => " << result << endl;
  } else if("partial-read-benchmark") {
    string ns = getRequiredStringArg(vm, "namespace");
    string file = getRequiredStringArg(vm, "file");
    uint32_t n = getRequiredArg<uint32_t>(vm, "benchmark-size");
    bool use_rora = getRequiredArg<bool>(vm, "use-rora");
    partial_read_benchmark(host,port,timeout,transport, ns, file, n, use_rora);
  } else {
    cout << "got invalid command name. valid options are: "
         << "download-object, upload-object, delete-object, list-objects "
         << "show-object, delete-namespace, create-namespace, list-namespaces, "
         << "invalidate-cache, proxy-get-version, namespace-exists" << endl;
    return 1;
  }
  return 0;
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015-2017 Simon Ninon <simon.ninon@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <netflex/http/response.hpp>
#include <netflex/misc/output.hpp>

namespace netflex {

namespace http {

//!
//! ctor & dtor
//!
response::response(void)
: m_http_version("HTTP/1.1")
, m_status(200)
, m_reason("OK") {}

//!
//! convert response to http packet
//!
std::string
response::to_http_packet(void) const {
  return m_http_version + " " + std::to_string(m_status) + " " + m_reason + "\r\n" + misc::header_list_to_http_packet(m_headers) + m_body;
}

//!
//! status line
//!
const std::string&
response::get_http_version(void) const {
  return m_http_version;
}

unsigned int
response::get_status_code(void) const {
  return m_status;
}

const std::string&
response::get_reason_phase(void) const {
  return m_reason;
}

void
response::set_http_version(const std::string& version) {
  m_http_version = version;
}

void
response::set_status_code(unsigned int code) {
  m_status = code;
}

void
response::set_reason_phrase(const std::string& reason) {
  m_reason = reason;
}

//!
//! headers
//!
const header_list_t&
response::get_headers(void) const {
  return m_headers;
}

void
response::add_header(const header& header) {
  m_headers[header.field_name] = header.field_value;
}

void
response::set_headers(const header_list_t& headers) {
  m_headers = headers;
}

//!
//! body
//!
const std::string&
response::get_body(void) const {
  return m_body;
}

void
response::set_body(const std::string& body) {
  m_body = body;
}

} // namespace http

} // namespace netflex
<commit_msg>use the misc formatting to build the status line<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015-2017 Simon Ninon <simon.ninon@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <netflex/http/response.hpp>
#include <netflex/misc/output.hpp>

namespace netflex {

namespace http {

//!
//! ctor & dtor
//!
response::response(void)
: m_http_version("HTTP/1.1")
, m_status(200)
, m_reason("OK") {}

//!
//! convert response to http packet
//!
std::string
response::to_http_packet(void) const {
  return misc::status_line_to_http_packet(m_http_version, m_status, m_reason) + misc::header_list_to_http_packet(m_headers) + m_body;
}

//!
//! status line
//!
const std::string&
response::get_http_version(void) const {
  return m_http_version;
}

unsigned int
response::get_status_code(void) const {
  return m_status;
}

const std::string&
response::get_reason_phase(void) const {
  return m_reason;
}

void
response::set_http_version(const std::string& version) {
  m_http_version = version;
}

void
response::set_status_code(unsigned int code) {
  m_status = code;
}

void
response::set_reason_phrase(const std::string& reason) {
  m_reason = reason;
}

//!
//! headers
//!
const header_list_t&
response::get_headers(void) const {
  return m_headers;
}

void
response::add_header(const header& header) {
  m_headers[header.field_name] = header.field_value;
}

void
response::set_headers(const header_list_t& headers) {
  m_headers = headers;
}

//!
//! body
//!
const std::string&
response::get_body(void) const {
  return m_body;
}

void
response::set_body(const std::string& body) {
  m_body = body;
}

} // namespace http

} // namespace netflex
<|endoftext|>


<commit_before>#include "Halide.h"

using namespace Halide;

int main(int argc, char **argv) {
    Var x("x"), y("y"), z("z");

    Image<float> noise(32);
    for (int i = 0; i < 32; i++) {
        noise(i) = (float)rand() / RAND_MAX;
    }

    Func f("f");
    Func g("g");
    RDom r(0, 32);

    g(x, y) = 0.0f;
    g(r.x, y) += noise(r.x);

    f(x, y, z) = g(x, y) + g(x+1, y);

    g.chunk(y);
    f.unroll(z, 2);

    Image<float> im = f.realize(64, 64, 4);

    printf("Success!\n");
    return 0;
}
<commit_msg>Updated unrolled reduction test<commit_after>#include "Halide.h"

using namespace Halide;

int main(int argc, char **argv) {
    Var x("x"), y("y"), z("z");

    Image<float> noise(32);
    for (int i = 0; i < 32; i++) {
        noise(i) = (float)rand() / RAND_MAX;
    }

    Func f("f");
    Func g("g");
    RDom r(0, 32);

    g(x, y) = 0.0f;
    g(r.x, y) += noise(r.x);

    f(x, y, z) = g(x, y) + g(x+1, y);

    g.compute_at(f, y);
    f.unroll(z, 2);

    Image<float> im = f.realize(64, 64, 4);

    printf("Success!\n");
    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>

#include "tagged_struct.h"

int main() {
  tagged_struct<member<"hello", auto_, [] { return 5; }>,
                member<"world", std::string, [] {}>,
                member<"test", auto_,
                       [](auto& t) {
                         return 2 * get<"hello">(t) + get<"world">(t).size();
                       }>,
                member<"last", int, [] { return 0; }>>
      ts{arg<"world"> = "Universe", arg<"hello"> = 1};

  using T = decltype(ts);
  T t2{arg<"world"> = "JRB"};

  std::cout << get<"hello">(ts) << "\n";
  std::cout << get<"world">(ts) << "\n";
  std::cout << get<"test">(ts) << "\n";
  std::cout << get<"hello">(t2) << "\n";
  std::cout << get<"world">(t2) << "\n";
  std::cout << get<"test">(t2) << "\n";
}<commit_msg>Add example of named arguments<commit_after>#include <iostream>
#include <string>

#include "tagged_struct.h"

using test_arguments =
    tagged_struct<member<"a", int, [] {}>,  // Required argument.
                  member<"b", auto_, [](auto& t) { return get<"a">(t) + 2; }>,
                  member<"c", auto_, [](auto& t) { return get<"b">(t) + 2; }>>;

void test(test_arguments args) {
  std::cout << get<"a">(args) << "\n";
  std::cout << get<"b">(args) << "\n";
  std::cout << get<"c">(args) << "\n";
}

int main() {
  tagged_struct<member<"hello", auto_, [] { return 5; }>,
                member<"world", std::string, [] {}>,
                member<"test", auto_,
                       [](auto& t) {
                         return 2 * get<"hello">(t) + get<"world">(t).size();
                       }>,
                member<"last", int, [] { return 0; }>>
      ts{arg<"world"> = "Universe", arg<"hello"> = 1};

  using T = decltype(ts);
  T t2{arg<"world"> = "JRB"};

  std::cout << get<"hello">(ts) << "\n";
  std::cout << get<"world">(ts) << "\n";
  std::cout << get<"test">(ts) << "\n";
  std::cout << get<"hello">(t2) << "\n";
  std::cout << get<"world">(t2) << "\n";
  std::cout << get<"test">(t2) << "\n";

  test({arg<"c"> = 1, arg<"a"> = 5});
  test({arg<"a"> = 1});
}<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_LA_SOLVER_EIGEN_HH
#define DUNE_STUFF_LA_SOLVER_EIGEN_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#if HAVE_EIGEN

#include <Eigen/SparseCore>
#include <Eigen/IterativeLinearSolvers>
#include <Eigen/SparseCholesky>

#if HAVE_SUPERLU
#include <Eigen/SuperLUSupport>
#endif // HAVE_SUPERLU

#include <dune/stuff/common/color.hh>
#include <dune/stuff/common/parameter/configcontainer.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/aliases.hh>
#include <dune/stuff/la/container/eigen.hh>

#include "interface.hh"

namespace Dune {
namespace Stuff {
namespace LA {

template <class MatrixImp, class VectorImp>
struct IsEigenMV {
  typedef typename std::is_base_of< Dune::Stuff::LA::EigenMatrixInterface<typename MatrixImp::Traits>, MatrixImp>::type Mtype;
  typedef typename std::is_base_of< Dune::Stuff::LA::EigenVectorInterface<typename VectorImp::Traits>, VectorImp>::type Vtype;
  static constexpr bool value = Mtype::value && Vtype::value;
};

//! \attention Slow!
//! \todo Implement via Eigen::CG and identity preconditioner!
template< class MatrixImp, class VectorImp >
class CgSolver< MatrixImp, VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type>
  : public SolverInterface< MatrixImp, VectorImp>
{
public:
  typedef SolverInterface< MatrixImp, VectorImp>
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  CgSolver()
  {
    DSC_LOG_DEBUG << "\n" << Dune::Stuff::Common::colorString("WARNING:")
                  << " this solver is believed to be slow! " << std::flush;
  }

  virtual size_t apply(const MatrixType& systemMatrix,
                          const VectorType& rhsVector,
                          VectorType& solutionVector,
                          const Dune::ParameterTree description = BaseType::defaultIterativeSettings()) const
  {
    auto& x_i = solutionVector.backend();
    const auto& b = rhsVector.backend();
    const auto& A = systemMatrix.backend();
    const int cols = A.cols();
    size_t iteration(1);
    const size_t maxIter = description.get<size_t >("maxIter");
    const ElementType precision = description.get<ElementType>("precision");
    ElementType rho(0), rho_prev(1), beta, alpha;
    const ElementType tolerance = precision * precision * b.squaredNorm();
    typedef typename DSL::EigenDenseVector<typename VectorType::ElementType >::BackendType RealEigenVector;
    RealEigenVector residuum = b - A * x_i;
    RealEigenVector correction_p(cols);
    RealEigenVector correction_q(cols);
    rho = residuum.squaredNorm();
    while (iteration <= maxIter) {
      if (iteration == 1) {
          correction_p = residuum;
      }
      else {
          beta = rho / rho_prev;
          correction_p = residuum + beta * correction_p;
      }
      correction_q.noalias() = A * correction_p;
      alpha = rho / correction_p.dot(correction_q);
      x_i += alpha * correction_p;
      residuum -= alpha * correction_q;
      rho = residuum.squaredNorm();
      if (rho < tolerance)
          return 0;
      rho_prev = rho;
    }
    return 1;
  } // virtual bool apply(...)
}; // class Cg

template< class MatrixImp, class VectorImp >
class CgDiagonalSolver< MatrixImp, VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type>
  : public SolverInterface< MatrixImp,
                      VectorImp >
{
public:
  typedef SolverInterface<  MatrixImp,
                      VectorImp >
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  CgDiagonalSolver()
  {
    DSC_LOG_DEBUG << "\n" << Dune::Stuff::Common::colorString("WARNING:", Dune::Stuff::Common::Colors::red)
                  << " this solver is believed to produce utterly wrong results! " << std::flush;
  }

  virtual size_t apply(const MatrixType& systemMatrix,
                          const VectorType& rhsVector,
                          VectorType& solutionVector,
                          const Dune::ParameterTree description = BaseType::defaultIterativeSettings()) const
  {
    typedef ::Eigen::ConjugateGradient< typename MatrixType::BackendType,
                                        ::Eigen::Lower,
                                        ::Eigen::DiagonalPreconditioner< ElementType > > EigenSolverType;
    EigenSolverType eigenSolver(systemMatrix.backend());
    eigenSolver.setMaxIterations(description.get<size_t>("maxIter"));
    eigenSolver.setTolerance(description.get<ElementType>("precision"));
    solutionVector.backend() = eigenSolver.solve(rhsVector.backend());
    return BaseType::translateInfo(eigenSolver.info());
  } // virtual bool apply(...)
}; // class CgDiagonal

template< class MatrixImp, class VectorImp >
class BicgstabSolver< MatrixImp,
                VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type >
  : public SolverInterface< MatrixImp,
                      VectorImp >
{
public:
  typedef SolverInterface<  MatrixImp,
                      VectorImp >
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  virtual size_t apply(const MatrixType& systemMatrix,
                          const VectorType& rhsVector,
                          VectorType& solutionVector,
                          const Dune::ParameterTree description = BaseType::defaultIterativeSettings()) const
  {
    typedef ::Eigen::BiCGSTAB< typename MatrixType::BackendType, ::Eigen::IdentityPreconditioner > EigenSolverType;
    EigenSolverType eigenSolver(systemMatrix.backend());
    eigenSolver.setMaxIterations(description.get<size_t>("maxIter"));
    eigenSolver.setTolerance(description.get<ElementType>("precision"));
    solutionVector.backend() = eigenSolver.solve(rhsVector.backend());
    return BaseType::translateInfo(eigenSolver.info());
  } // virtual bool apply(...)
}; // class Bicgstab

template< class MatrixImp, class VectorImp >
class BicgstabDiagonalSolver< MatrixImp,
                        VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type >
  : public SolverInterface< MatrixImp,
                      VectorImp >
{
public:
  typedef SolverInterface<  MatrixImp,
                      VectorImp >
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  virtual size_t apply(const MatrixType& systemMatrix,
                          const VectorType& rhsVector,
                          VectorType& solutionVector,
                          const Dune::ParameterTree description = BaseType::defaultIterativeSettings()) const
  {
    typedef ::Eigen::BiCGSTAB< typename MatrixType::BackendType, ::Eigen::DiagonalPreconditioner< ElementType > > EigenSolverType;
    EigenSolverType eigenSolver(systemMatrix.backend());
    eigenSolver.setMaxIterations(description.get<size_t >("maxIter"));
    eigenSolver.setTolerance(description.get<ElementType>("precision"));
    solutionVector.backend() = eigenSolver.solve(rhsVector.backend());
    return BaseType::translateInfo(eigenSolver.info());
  } // virtual bool apply(...)static_assert
}; // class BicgstabDiagonal

template< class MatrixImp, class VectorImp >
class BicgstabILUTSolver< MatrixImp,
                    VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type >
  : public SolverInterface< MatrixImp,
                      VectorImp >
{
public:
  typedef SolverInterface<  MatrixImp,
                      VectorImp >
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  static Dune::ParameterTree defaultSettings()
  {
    Dune::ParameterTree description = BaseType::defaultIterativeSettings();
    description["precision"] = "1.0e-8";
    description["preconditioner.dropTol"] = "1e-4";
    description["preconditioner.fillFactor"] = "10";
    return description;
  } // Dune::ParameterTree defaultSettings()

  virtual size_t apply(const MatrixType& systemMatrix,
                       const VectorType& rhsVector,
                       VectorType& solutionVector,
                       const Dune::ParameterTree description = defaultSettings()) const
  {
    typedef ::Eigen::BiCGSTAB< typename MatrixType::BackendType, ::Eigen::IncompleteLUT< ElementType > > EigenSolverType;
    EigenSolverType solver(systemMatrix.backend());
    // configure solver and preconditioner
    solver.setTolerance(description.get<double>("precision"));
    solver.setMaxIterations(description.get<size_t>("maxIter", solutionVector.size()));
    solver.preconditioner().setDroptol(description.get<double>("preconditioner.dropTol"));
    solver.preconditioner().setFillfactor(description.get<double>("preconditioner.fillFactor"));

    solutionVector.backend() = solver.solve(rhsVector.backend());
    return BaseType::translateInfo(solver.info());
  } // virtual bool apply(...)
}; // class BicgstabILUT

#if HAVE_SUPERLU

template< class MatrixImp, class VectorImp >
class DirectSuperLuSolver< MatrixImp,
                      VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type >
  : public SolverInterface< MatrixImp,
                      VectorImp >
{
public:
  typedef SolverInterface<  MatrixImp,
                      VectorImp >
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  DirectSuperLuSolver()
  {}

  virtual size_t apply(const MatrixType& systemMatrix,
                          const VectorType& rhsVector,
                          VectorType& solutionVector,
                          const Dune::ParameterTree /*description*/ = Dune::ParameterTree()) const
  {

    typedef ::Eigen::SuperLU<const typename MatrixType::BackendType> EigenSolverType;
    EigenSolverType eigenSolver;
    eigenSolver.compute(systemMatrix.backend());
    solutionVector.backend() = eigenSolver.solve(rhsVector.backend());
    const ::Eigen::ComputationInfo info = eigenSolver.info();
    return (info == ::Eigen::Success);
  } // virtual bool apply(...)
}; // class SimplicialLDLT

#endif //HAVE_SUPERLU

} // namespace LA
} // namespace Stuff
} // namespace Dune

#endif // HAVE_EIGEN

#endif // DUNE_STUFF_LA_SOLVER_EIGEN_HH
<commit_msg>[la.solver.eigen] let bicgstab.ilut default to its defaults instead of crashing<commit_after>#ifndef DUNE_STUFF_LA_SOLVER_EIGEN_HH
#define DUNE_STUFF_LA_SOLVER_EIGEN_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#if HAVE_EIGEN

#include <Eigen/SparseCore>
#include <Eigen/IterativeLinearSolvers>
#include <Eigen/SparseCholesky>

#if HAVE_SUPERLU
#include <Eigen/SuperLUSupport>
#endif // HAVE_SUPERLU

#include <dune/stuff/common/color.hh>
#include <dune/stuff/common/parameter/configcontainer.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/aliases.hh>
#include <dune/stuff/la/container/eigen.hh>

#include "interface.hh"

namespace Dune {
namespace Stuff {
namespace LA {

template <class MatrixImp, class VectorImp>
struct IsEigenMV {
  typedef typename std::is_base_of< Dune::Stuff::LA::EigenMatrixInterface<typename MatrixImp::Traits>, MatrixImp>::type Mtype;
  typedef typename std::is_base_of< Dune::Stuff::LA::EigenVectorInterface<typename VectorImp::Traits>, VectorImp>::type Vtype;
  static constexpr bool value = Mtype::value && Vtype::value;
};

//! \attention Slow!
//! \todo Implement via Eigen::CG and identity preconditioner!
template< class MatrixImp, class VectorImp >
class CgSolver< MatrixImp, VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type>
  : public SolverInterface< MatrixImp, VectorImp>
{
public:
  typedef SolverInterface< MatrixImp, VectorImp>
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  CgSolver()
  {
    DSC_LOG_DEBUG << "\n" << Dune::Stuff::Common::colorString("WARNING:")
                  << " this solver is believed to be slow! " << std::flush;
  }

  virtual size_t apply(const MatrixType& systemMatrix,
                          const VectorType& rhsVector,
                          VectorType& solutionVector,
                          const Dune::ParameterTree description = BaseType::defaultIterativeSettings()) const
  {
    auto& x_i = solutionVector.backend();
    const auto& b = rhsVector.backend();
    const auto& A = systemMatrix.backend();
    const int cols = A.cols();
    size_t iteration(1);
    const size_t maxIter = description.get<size_t >("maxIter");
    const ElementType precision = description.get<ElementType>("precision");
    ElementType rho(0), rho_prev(1), beta, alpha;
    const ElementType tolerance = precision * precision * b.squaredNorm();
    typedef typename DSL::EigenDenseVector<typename VectorType::ElementType >::BackendType RealEigenVector;
    RealEigenVector residuum = b - A * x_i;
    RealEigenVector correction_p(cols);
    RealEigenVector correction_q(cols);
    rho = residuum.squaredNorm();
    while (iteration <= maxIter) {
      if (iteration == 1) {
          correction_p = residuum;
      }
      else {
          beta = rho / rho_prev;
          correction_p = residuum + beta * correction_p;
      }
      correction_q.noalias() = A * correction_p;
      alpha = rho / correction_p.dot(correction_q);
      x_i += alpha * correction_p;
      residuum -= alpha * correction_q;
      rho = residuum.squaredNorm();
      if (rho < tolerance)
          return 0;
      rho_prev = rho;
    }
    return 1;
  } // virtual bool apply(...)
}; // class Cg

template< class MatrixImp, class VectorImp >
class CgDiagonalSolver< MatrixImp, VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type>
  : public SolverInterface< MatrixImp,
                      VectorImp >
{
public:
  typedef SolverInterface<  MatrixImp,
                      VectorImp >
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  CgDiagonalSolver()
  {
    DSC_LOG_DEBUG << "\n" << Dune::Stuff::Common::colorString("WARNING:", Dune::Stuff::Common::Colors::red)
                  << " this solver is believed to produce utterly wrong results! " << std::flush;
  }

  virtual size_t apply(const MatrixType& systemMatrix,
                          const VectorType& rhsVector,
                          VectorType& solutionVector,
                          const Dune::ParameterTree description = BaseType::defaultIterativeSettings()) const
  {
    typedef ::Eigen::ConjugateGradient< typename MatrixType::BackendType,
                                        ::Eigen::Lower,
                                        ::Eigen::DiagonalPreconditioner< ElementType > > EigenSolverType;
    EigenSolverType eigenSolver(systemMatrix.backend());
    eigenSolver.setMaxIterations(description.get<size_t>("maxIter"));
    eigenSolver.setTolerance(description.get<ElementType>("precision"));
    solutionVector.backend() = eigenSolver.solve(rhsVector.backend());
    return BaseType::translateInfo(eigenSolver.info());
  } // virtual bool apply(...)
}; // class CgDiagonal

template< class MatrixImp, class VectorImp >
class BicgstabSolver< MatrixImp,
                VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type >
  : public SolverInterface< MatrixImp,
                      VectorImp >
{
public:
  typedef SolverInterface<  MatrixImp,
                      VectorImp >
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  virtual size_t apply(const MatrixType& systemMatrix,
                          const VectorType& rhsVector,
                          VectorType& solutionVector,
                          const Dune::ParameterTree description = BaseType::defaultIterativeSettings()) const
  {
    typedef ::Eigen::BiCGSTAB< typename MatrixType::BackendType, ::Eigen::IdentityPreconditioner > EigenSolverType;
    EigenSolverType eigenSolver(systemMatrix.backend());
    eigenSolver.setMaxIterations(description.get<size_t>("maxIter"));
    eigenSolver.setTolerance(description.get<ElementType>("precision"));
    solutionVector.backend() = eigenSolver.solve(rhsVector.backend());
    return BaseType::translateInfo(eigenSolver.info());
  } // virtual bool apply(...)
}; // class Bicgstab

template< class MatrixImp, class VectorImp >
class BicgstabDiagonalSolver< MatrixImp,
                        VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type >
  : public SolverInterface< MatrixImp,
                      VectorImp >
{
public:
  typedef SolverInterface<  MatrixImp,
                      VectorImp >
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  virtual size_t apply(const MatrixType& systemMatrix,
                          const VectorType& rhsVector,
                          VectorType& solutionVector,
                          const Dune::ParameterTree description = BaseType::defaultIterativeSettings()) const
  {
    typedef ::Eigen::BiCGSTAB< typename MatrixType::BackendType, ::Eigen::DiagonalPreconditioner< ElementType > > EigenSolverType;
    EigenSolverType eigenSolver(systemMatrix.backend());
    eigenSolver.setMaxIterations(description.get<size_t >("maxIter"));
    eigenSolver.setTolerance(description.get<ElementType>("precision"));
    solutionVector.backend() = eigenSolver.solve(rhsVector.backend());
    return BaseType::translateInfo(eigenSolver.info());
  } // virtual bool apply(...)static_assert
}; // class BicgstabDiagonal

template< class MatrixImp, class VectorImp >
class BicgstabILUTSolver< MatrixImp,
                    VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type >
  : public SolverInterface< MatrixImp,
                      VectorImp >
{
public:
  typedef SolverInterface<  MatrixImp,
                      VectorImp >
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  static Dune::ParameterTree defaultSettings()
  {
    Dune::ParameterTree description = BaseType::defaultIterativeSettings();
    description["precision"] = "1.0e-8";
    description["preconditioner.dropTol"] = "1e-4";
    description["preconditioner.fillFactor"] = "10";
    return description;
  } // Dune::ParameterTree defaultSettings()

  virtual size_t apply(const MatrixType& systemMatrix,
                       const VectorType& rhsVector,
                       VectorType& solutionVector,
                       const Dune::ParameterTree description = defaultSettings()) const
  {
    typedef ::Eigen::BiCGSTAB< typename MatrixType::BackendType, ::Eigen::IncompleteLUT< ElementType > > EigenSolverType;
    EigenSolverType solver(systemMatrix.backend());
    // configure solver and preconditioner
    // do not fail, but warn on non existing settings
    const auto defaults = defaultSettings();
    solver.setTolerance(description.get("precision", defaults.get< double >("precision")));
    solver.setMaxIterations(description.get("maxIter", solutionVector.size()));
    solver.preconditioner().setDroptol(description.get("preconditioner.dropTol", defaults.get< double >("preconditioner.dropTol")));
    solver.preconditioner().setFillfactor(description.get("preconditioner.fillFactor", defaults.get< double >("preconditioner.fillFactor")));

    solutionVector.backend() = solver.solve(rhsVector.backend());
    return BaseType::translateInfo(solver.info());
  } // virtual bool apply(...)
}; // class BicgstabILUT

#if HAVE_SUPERLU

template< class MatrixImp, class VectorImp >
class DirectSuperLuSolver< MatrixImp,
                      VectorImp, typename std::enable_if<IsEigenMV<MatrixImp, VectorImp>::value>::type >
  : public SolverInterface< MatrixImp,
                      VectorImp >
{
public:
  typedef SolverInterface<  MatrixImp,
                      VectorImp >
      BaseType;

  typedef typename BaseType::MatrixType MatrixType;
  typedef typename BaseType::VectorType VectorType;
  typedef typename BaseType::ElementType ElementType;

  DirectSuperLuSolver()
  {}

  virtual size_t apply(const MatrixType& systemMatrix,
                          const VectorType& rhsVector,
                          VectorType& solutionVector,
                          const Dune::ParameterTree /*description*/ = Dune::ParameterTree()) const
  {

    typedef ::Eigen::SuperLU<const typename MatrixType::BackendType> EigenSolverType;
    EigenSolverType eigenSolver;
    eigenSolver.compute(systemMatrix.backend());
    solutionVector.backend() = eigenSolver.solve(rhsVector.backend());
    const ::Eigen::ComputationInfo info = eigenSolver.info();
    return (info == ::Eigen::Success);
  } // virtual bool apply(...)
}; // class SimplicialLDLT

#endif //HAVE_SUPERLU

} // namespace LA
} // namespace Stuff
} // namespace Dune

#endif // HAVE_EIGEN

#endif // DUNE_STUFF_LA_SOLVER_EIGEN_HH
<|endoftext|>


<commit_before>#include "Tree30Dof.h"

#include <RBDyn/Coriolis.h>

#define BOOST_TEST_MODULE Expand
#include <boost/test/unit_test.hpp>

#include <RBDyn/FD.h>
#include <RBDyn/FK.h>
#include <RBDyn/FV.h>
#include <RBDyn/EulerIntegration.h>

#include <iostream>

BOOST_AUTO_TEST_CASE(ExpandJacobianTest)
{
	std::srand(133757348);

	rbd::MultiBody mb;
	rbd::MultiBodyConfig mbc;
	rbd::MultiBodyGraph mbg;

	std::tie(mb, mbc, mbg) = makeTree30Dof(false);

	const static int ROUNDS = 1000;

	rbd::Jacobian jac(mb, mb.body(mb.nrBodies() - 1).name());

	for(int i = 0; i < ROUNDS; ++i)
	{
		mbc.zero(mb);

		Eigen::VectorXd q = Eigen::VectorXd::Random(mb.nrParams());
		mbc.q = rbd::sVectorToParam(mb, q);

		for(auto& q : mbc.q)
		{
			if(q.size() == 7)
			{
				Eigen::Vector3d axis = Eigen::Vector3d::Random();
				Eigen::AngleAxisd aa(0.5, axis/axis.norm());
				Eigen::Quaterniond qd(aa);
				q[0] = qd.w();
				q[1] = qd.x();
				q[2] = qd.y();
				q[3] = qd.z();
			}
		}

		rbd::forwardKinematics(mb, mbc);
		rbd::forwardVelocity(mb, mbc);

		Eigen::MatrixXd jacMat = jac.jacobian(mb, mbc);

		Eigen::MatrixXd fullJacMat(6, mb.nrDof());
		jac.fullJacobian(mb, jacMat, fullJacMat);

		Eigen::MatrixXd res = fullJacMat.transpose()*fullJacMat;

		Eigen::MatrixXd product = jacMat.transpose()*jacMat;
		Eigen::MatrixXd fullProduct = rbd::expand(jac, mb, product);

		BOOST_CHECK_EQUAL((fullProduct - res).norm(), 0);
	}
}
<commit_msg>Test every style of expansion<commit_after>#include "Tree30Dof.h"

#include <RBDyn/Coriolis.h>

#define BOOST_TEST_MODULE Expand
#include <boost/test/unit_test.hpp>

#include <RBDyn/FD.h>
#include <RBDyn/FK.h>
#include <RBDyn/FV.h>
#include <RBDyn/EulerIntegration.h>

#include <iostream>

BOOST_AUTO_TEST_CASE(ExpandJacobianTest)
{
	std::srand(133757348);

	rbd::MultiBody mb;
	rbd::MultiBodyConfig mbc;
	rbd::MultiBodyGraph mbg;

	std::tie(mb, mbc, mbg) = makeTree30Dof(false);

	const static int ROUNDS = 1000;

	rbd::Jacobian jac(mb, mb.body(mb.nrBodies() - 1).name());
	rbd::Blocks compact = rbd::compactPath(jac, mb);

	for(int i = 0; i < ROUNDS; ++i)
	{
		mbc.zero(mb);

		Eigen::VectorXd q = Eigen::VectorXd::Random(mb.nrParams());
		mbc.q = rbd::sVectorToParam(mb, q);

		for(auto& q : mbc.q)
		{
			if(q.size() == 7)
			{
				Eigen::Vector3d axis = Eigen::Vector3d::Random();
				Eigen::AngleAxisd aa(0.5, axis/axis.norm());
				Eigen::Quaterniond qd(aa);
				q[0] = qd.w();
				q[1] = qd.x();
				q[2] = qd.y();
				q[3] = qd.z();
			}
		}

		rbd::forwardKinematics(mb, mbc);
		rbd::forwardVelocity(mb, mbc);

		Eigen::MatrixXd jacMat = jac.jacobian(mb, mbc);

		Eigen::MatrixXd fullJacMat(6, mb.nrDof());
		jac.fullJacobian(mb, jacMat, fullJacMat);

		Eigen::MatrixXd res = fullJacMat.transpose()*fullJacMat;

		Eigen::MatrixXd product = jacMat.transpose()*jacMat;
		Eigen::MatrixXd fullProduct = rbd::expand(jac, mb, product);

		BOOST_CHECK_EQUAL((fullProduct - res).norm(), 0);

		fullProduct.setZero();
		rbd::expandAdd(jac, mb, product, fullProduct);

		BOOST_CHECK_EQUAL((fullProduct - res).norm(), 0);

		fullProduct.setZero();
		rbd::compactExpandAdd(compact, product, fullProduct);

		BOOST_CHECK_EQUAL((fullProduct - res).norm(), 0);
	}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <map>
#include <vector>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <ext/stdio_filebuf.h>
#include <cstring>
#include <signal.h>

using namespace std;

int iabs(int a) { return a < 0 ? -a : a; }

void exit_verifier(int result_code, int exit_code) {
    cout << endl << result_code;
    exit(exit_code);
}

int main(int argc, char* argv[]) {
    ifstream instance(argv[1]);
    ifstream solver_output(argv[2]);
    string line;

    map<int, int> variables;
    bool SAT_answer = false;
    bool UNSAT_answer = false;
    while (getline(solver_output, line)) {
        istringstream lss(line);
        string prefix;
        lss >> prefix;
        if (prefix == "s") {
            string answer;
            lss >> answer;
            if (answer == "UNKNOWN") {
                cout << "Solver reported unknown." << endl;
                exit_verifier(0, 0);
            }
            else if (answer == "SATISFIABLE") {
                cout << "Solver reported satisfiable. Checking." << endl;
                SAT_answer = true;
            }
            else if (answer == "UNSATISFIABLE") {
                cout << "Solver reported unsatisfiable. Checking." << endl;
                UNSAT_answer = true;
                break; // Proof should follow.
            }
        }
        else if (prefix == "v") {
            // read solution
            int v;
            while (lss >> v && v != 0) {
                variables[iabs(v)] = v;
            }
        }
    }
    if (SAT_answer) {
        while (getline(instance, line)) {
            if (line.substr(0, 1) == "c" || line.substr(0, 1) == "p") continue;
            istringstream lss(line);
            int v;
            bool sat_clause = false;
            int num_vars = 0;
            while (lss >> v && v != 0) {
                num_vars++;
                if (variables[iabs(v)] == v) {
                    sat_clause = true;
                    break;
                }
            }
            if (!sat_clause && num_vars > 0) {
                cout << "Clause " << line << " not satisfied" << endl;
                cout << "Wrong solution." << endl;
                exit_verifier(-1, 0);
            }
        }
        cout << "Solution verified." << endl;
        exit_verifier(11, 0);
    } else if (UNSAT_answer) {
        // Verify the solution that should be given in DRUP or TRACECHECK format following the solution line.

        // First line is used to detect the proof format
        string first_line;
        getline(solver_output, first_line);
        //first_line = first_line.substr(first_line.find('\t')); // skip timestamp
        istringstream lss(first_line);
        string format = "";
        /*bool trace = false;
        if (first_line.find(" 0 0") != string::npos) { // "0 0" means TRACE proof format
            trace = true;
            cout << "Detected TRACE proof format." << endl;
        } else { // DRUP format
            cout << "Detected RUP proof format." << endl;
            trace = false;
        }*/
        if (first_line.find("p proof BRUP") != string::npos) {
            format = "brup";
        } else if (first_line.find("p proof DRUP") != string::npos) {
            format = "drup";
        } else if (first_line.find("p proof TC") != string::npos) {
            format = "tc";
        } else {
            cout << "Could not find 'p proof' line with proof format identifier." << endl;
            exit_verifier(0, 0);
        }

        // Prepare communication pipes with checker programs
        int outfd[2];
        int infd[2];
        pipe(outfd);
        pipe(infd);

        char* checker_cmd = new char[4096];
        if (format == "brup") {
            strcpy(checker_cmd, "./brup.py");
        } else if (format == "drup") {
            strcpy(checker_cmd, "./drup-check");
        } else if (format == "tc") {
            strcpy(checker_cmd, "./stc");
        }

        cout << "Calling " << checker_cmd << " " << argv[1] << endl;
        char* argvc[] = {checker_cmd, argv[1], 0 };

        if (!fork()) {
            // This is the child, connect pipes and launch checker program
            close(STDOUT_FILENO); // Close default stdout
            close(STDIN_FILENO); // Close default stdin

            dup2(outfd[0], STDIN_FILENO); // Connect read end of parent-child pipe with stdin
            dup2(infd[1], STDOUT_FILENO); // Connect write end of parent-child pipe with stdout

            // Close now unneeded pipe FDs
            close(outfd[0]);
            close(outfd[1]);
            close(infd[0]);
            close(infd[1]);

            execv(argvc[0], argvc);
        } else {
            // This is the parent (verifier), write the proof to the checker's stdin and read result from stdout.
            close(outfd[0]); // Don't need the read end of the pipe to the child
            close(infd[1]); // Don't need the write end of the pipe from the child

            int t0 = time(NULL);

            //write(outfd[1], first_line.c_str(), first_line.length());
            while (getline(solver_output, line)) {
                line = line + "\n"; // skip timestamp, add newline
                write(outfd[1], line.c_str(), line.length());
            }
            close(outfd[1]); // This should signal the checker the end of the proof

            __gnu_cxx::stdio_filebuf<char> filebuf(infd[0], std::ios::in);
            istream checker_output(&filebuf);
            string line;
            cout << "Reading output from checker." << endl;
            getline(checker_output, line);
            int t1 = time(NULL);
            cout << "Verification took " << (t1 - t0) << " seconds. Checker output: " << line << endl;
            if (line.find("s VERIFIED") != string::npos) {
                close(outfd[1]);
                close(infd[0]);
                exit_verifier(10, 0);
            }

        }
    }
    cout << "Could not find a valid solution" << endl;
    exit_verifier(0, 0);
}
<commit_msg>change o line<commit_after>#include <iostream>
#include <map>
#include <vector>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <ext/stdio_filebuf.h>
#include <cstring>
#include <signal.h>

using namespace std;

int iabs(int a) { return a < 0 ? -a : a; }

void exit_verifier(int result_code, int exit_code) {
    cout << endl << result_code;
    exit(exit_code);
}

int main(int argc, char* argv[]) {
    ifstream instance(argv[1]);
    ifstream solver_output(argv[2]);
    string line;

    map<int, int> variables;
    bool SAT_answer = false;
    bool UNSAT_answer = false;
    while (getline(solver_output, line)) {
        istringstream lss(line);
        string prefix;
        lss >> prefix;
        if (prefix == "s") {
            string answer;
            lss >> answer;
            if (answer == "UNKNOWN") {
                cout << "Solver reported unknown." << endl;
                exit_verifier(0, 0);
            }
            else if (answer == "SATISFIABLE") {
                cout << "Solver reported satisfiable. Checking." << endl;
                SAT_answer = true;
            }
            else if (answer == "UNSATISFIABLE") {
                cout << "Solver reported unsatisfiable. Checking." << endl;
                UNSAT_answer = true;
                break; // Proof should follow.
            }
        }
        else if (prefix == "v") {
            // read solution
            int v;
            while (lss >> v && v != 0) {
                variables[iabs(v)] = v;
            }
        }
    }
    if (SAT_answer) {
        while (getline(instance, line)) {
            if (line.substr(0, 1) == "c" || line.substr(0, 1) == "p") continue;
            istringstream lss(line);
            int v;
            bool sat_clause = false;
            int num_vars = 0;
            while (lss >> v && v != 0) {
                num_vars++;
                if (variables[iabs(v)] == v) {
                    sat_clause = true;
                    break;
                }
            }
            if (!sat_clause && num_vars > 0) {
                cout << "Clause " << line << " not satisfied" << endl;
                cout << "Wrong solution." << endl;
                exit_verifier(-1, 0);
            }
        }
        cout << "Solution verified." << endl;
        exit_verifier(11, 0);
    } else if (UNSAT_answer) {
        // Verify the solution that should be given in DRUP or TRACECHECK format following the solution line.

        // First line is used to detect the proof format
        string first_line;
        getline(solver_output, first_line);
        //first_line = first_line.substr(first_line.find('\t')); // skip timestamp
        istringstream lss(first_line);
        string format = "";
        /*bool trace = false;
        if (first_line.find(" 0 0") != string::npos) { // "0 0" means TRACE proof format
            trace = true;
            cout << "Detected TRACE proof format." << endl;
        } else { // DRUP format
            cout << "Detected RUP proof format." << endl;
            trace = false;
        }*/
        if (first_line.find("o proof BDRUP") != string::npos) {
            format = "brup";
        } else if (first_line.find("o proof DRUP") != string::npos) {
            format = "drup";
        } else if (first_line.find("o proof TC") != string::npos) {
            format = "tc";
        } else {
            cout << "Could not find 'p proof' line with proof format identifier." << endl;
            exit_verifier(0, 0);
        }

        // Prepare communication pipes with checker programs
        int outfd[2];
        int infd[2];
        pipe(outfd);
        pipe(infd);

        char* checker_cmd = new char[4096];
        if (format == "brup") {
            strcpy(checker_cmd, "./brup.py");
        } else if (format == "drup") {
            strcpy(checker_cmd, "./drup-check");
        } else if (format == "tc") {
            strcpy(checker_cmd, "./stc");
        }

        cout << "Calling " << checker_cmd << " " << argv[1] << endl;
        char* argvc[] = {checker_cmd, argv[1], 0 };

        if (!fork()) {
            // This is the child, connect pipes and launch checker program
            close(STDOUT_FILENO); // Close default stdout
            close(STDIN_FILENO); // Close default stdin

            dup2(outfd[0], STDIN_FILENO); // Connect read end of parent-child pipe with stdin
            dup2(infd[1], STDOUT_FILENO); // Connect write end of parent-child pipe with stdout

            // Close now unneeded pipe FDs
            close(outfd[0]);
            close(outfd[1]);
            close(infd[0]);
            close(infd[1]);

            execv(argvc[0], argvc);
        } else {
            // This is the parent (verifier), write the proof to the checker's stdin and read result from stdout.
            close(outfd[0]); // Don't need the read end of the pipe to the child
            close(infd[1]); // Don't need the write end of the pipe from the child

            int t0 = time(NULL);

            //write(outfd[1], first_line.c_str(), first_line.length());
            while (getline(solver_output, line)) {
                line = line + "\n"; // skip timestamp, add newline
                write(outfd[1], line.c_str(), line.length());
            }
            close(outfd[1]); // This should signal the checker the end of the proof

            __gnu_cxx::stdio_filebuf<char> filebuf(infd[0], std::ios::in);
            istream checker_output(&filebuf);
            string line;
            cout << "Reading output from checker." << endl;
            getline(checker_output, line);
            int t1 = time(NULL);
            cout << "Verification took " << (t1 - t0) << " seconds. Checker output: " << line << endl;
            if (line.find("s VERIFIED") != string::npos) {
                close(outfd[1]);
                close(infd[0]);
                exit_verifier(10, 0);
            }

        }
    }
    cout << "Could not find a valid solution" << endl;
    exit_verifier(0, 0);
}
<|endoftext|>


<commit_before>#ifndef VIENNAGRID_ELEMENT_CREATION_HPP
#define VIENNAGRID_ELEMENT_CREATION_HPP

/* =======================================================================
   Copyright (c) 2011-2012, Institute for Microelectronics,
                            Institute for Analysis and Scientific Computing,
                            TU Wien.

                            -----------------
                     ViennaGrid - The Vienna Grid Library
                            -----------------

   Authors:      Karl Rupp                           rupp@iue.tuwien.ac.at
                 Josef Weinbub                    weinbub@iue.tuwien.ac.at

   (A list of additional contributors can be found in the PDF manual)

   License:      MIT (X11), see file LICENSE in the base directory
======================================================================= */

#include "viennagrid/element/tagging.hpp"
#include "viennagrid/domain/topologic_domain.hpp"
#include "viennagrid/domain/geometric_domain.hpp"

namespace viennagrid
{

    template<typename element_type, typename domain_type>
    typename result_of::element_hook<domain_type, element_type>::type create_element( domain_type & domain )
    {
        return push_element(domain, element_type() ).first;
    }

    template<typename element_type, typename domain_type>
    typename result_of::element_hook<domain_type, element_type>::type create_element( domain_type & domain, typename element_type::id_type id )
    {
        //typedef typename result_of::element<domain_type, viennagrid::vertex_tag>::type vertex_type;

        element_type element;
        element.id( id );

        return push_element_noid(domain, element).first;
    }

    template<typename element_type, typename domain_type, typename hook_array_iterator_type>
    typename result_of::element_hook<domain_type, typename element_type::tag>::type create_element( domain_type & domain,
                                                                                hook_array_iterator_type array_start, const hook_array_iterator_type & array_end )
    {
        element_type element = element_type( inserter(domain).get_physical_container_collection() );

        size_t element_index = 0;
        for ( ; array_start != array_end; ++array_start, ++element_index )
            viennagrid::set_vertex( element, *array_start, element_index );

        //for (typename hook_array_type::const_iterator it = array.begin(); it != array.end(); ++it, ++element_index)
            //viennagrid::set_vertex( element, *it, element_index );

        return push_element(domain, element ).first;
    }

    template<typename element_type, typename domain_type, typename hook_array_type>
    typename result_of::element_hook<domain_type, typename element_type::tag>::type create_element( domain_type & domain, const hook_array_type & array )
    {
        return create_element<element_type>(domain, array.begin(), array.end() );
    }

    template<typename element_type, typename domain_type, typename hook_array_iterator_type>
    typename result_of::element_hook<domain_type, typename element_type::tag>::type create_element( domain_type & domain,
                                                                                hook_array_iterator_type array_start, const hook_array_iterator_type & array_end,
                                                                                typename element_type::id_type id )
    {
        element_type element = element_type( inserter(domain).get_physical_container_collection() );

        element.id( id );

        size_t element_index = 0;
        for ( ; array_start != array_end; ++array_start, ++element_index )
            viennagrid::set_vertex( element, *array_start, element_index );

        return push_element_noid(domain, element ).first;
    }

    template<typename element_type, typename domain_type, typename hook_array_type>
    typename result_of::element_hook<domain_type, typename element_type::tag>::type create_element( domain_type & domain, const hook_array_type & array, typename element_type::id_type id )
    {
        return create_element<element_type>(domain, array.begin(), array.end(), id );
    }

    template<typename plc_type, typename domain_type, typename polygon_hook_array_iterator_type,
                typename line_hook_array_iterator_type, typename vertex_hook_array_iterator_type>
    typename result_of::element_hook<domain_type, plc_type>::type create_element( domain_type & domain,
                             polygon_hook_array_iterator_type bounding_polygon_it, const polygon_hook_array_iterator_type & bounding_polygons_end,
                             polygon_hook_array_iterator_type hole_polygon_it, const polygon_hook_array_iterator_type & hole_polygons_end,
                             line_hook_array_iterator_type line_it, const line_hook_array_iterator_type & lines_end,
                             vertex_hook_array_iterator_type vertex_it, const vertex_hook_array_iterator_type & vertices_end)
    {
        std::pair<typename result_of::element_hook<domain_type, plc_type>::type, bool> ret = viennagrid::push_element(domain, plc_type( inserter(domain).get_physical_container_collection() ) );
        typename result_of::element_hook<domain_type, plc_type>::type plc_hook = ret.first;
        plc_type & plc = viennagrid::dereference_hook(domain, plc_hook);

        typename tagging::result_of::element_tag<plc_type, hole_tag>::type plc_hole_tag(plc);
        typename tagging::result_of::element_tag<plc_type, bounding_tag>::type plc_bounding_tag(plc);
        typename tagging::result_of::element_tag<plc_type, loose_tag>::type plc_loose_tag(plc);

        for ( ; bounding_polygon_it != bounding_polygons_end; ++bounding_polygon_it)
        {
            plc.container( viennagrid::polygon_tag() ).insert_hook( *bounding_polygon_it );
            tagging::tag(viennagrid::dereference_hook(domain, *bounding_polygon_it), plc_bounding_tag);
        }

        for ( ; hole_polygon_it != hole_polygons_end; ++hole_polygon_it)
        {
            plc.container( viennagrid::polygon_tag() ).insert_hook( *hole_polygon_it );
            tagging::tag(viennagrid::dereference_hook(domain, *hole_polygon_it), plc_hole_tag);
            tagging::tag(viennagrid::dereference_hook(domain, *hole_polygon_it), plc_loose_tag);
        }

        for ( ; line_it != lines_end; ++line_it)
        {
            plc.container( viennagrid::line_tag() ).insert_hook( *line_it );
            tagging::tag(viennagrid::dereference_hook(domain, *line_it), plc_loose_tag);
            //viennadata::access<tag_key<loose_tag, plc_type>, bool>( tag_key<loose_tag, plc_type>(plc) )( viennagrid::dereference_hook(domain, *line_it) ) = true;
        }

        for ( ; vertex_it != vertices_end; ++vertex_it)
        {
            plc.container( viennagrid::vertex_tag() ).insert_hook( *vertex_it );
            tagging::tag(viennagrid::dereference_hook(domain, *vertex_it), plc_loose_tag);
//             viennadata::access<tag_key<loose_tag, plc_type>, bool>( tag_key<loose_tag, plc_type>(plc) )( viennagrid::dereference_hook(domain, *vertex_it) ) = true;
        }

        plc.insert_callback( inserter(domain), ret.second );
        return plc_hook;
    }

}

#endif
<commit_msg>adapted plc creation to new plc concept added specialized create functions for lines and triangles<commit_after>#ifndef VIENNAGRID_ELEMENT_CREATION_HPP
#define VIENNAGRID_ELEMENT_CREATION_HPP

/* =======================================================================
   Copyright (c) 2011-2012, Institute for Microelectronics,
                            Institute for Analysis and Scientific Computing,
                            TU Wien.

                            -----------------
                     ViennaGrid - The Vienna Grid Library
                            -----------------

   Authors:      Karl Rupp                           rupp@iue.tuwien.ac.at
                 Josef Weinbub                    weinbub@iue.tuwien.ac.at

   (A list of additional contributors can be found in the PDF manual)

   License:      MIT (X11), see file LICENSE in the base directory
======================================================================= */

#include "viennagrid/element/tagging.hpp"
#include "viennagrid/domain/topologic_domain.hpp"
#include "viennagrid/domain/geometric_domain.hpp"
#include "viennagrid/topology/plc.hpp"

namespace viennagrid
{

    template<typename element_type, typename domain_type>
    typename result_of::element_hook<domain_type, element_type>::type create_element( domain_type & domain )
    {
        return push_element(domain, element_type() ).first;
    }

    template<typename element_type, typename domain_type>
    typename result_of::element_hook<domain_type, element_type>::type create_element( domain_type & domain, typename element_type::id_type id )
    {
        //typedef typename result_of::element<domain_type, viennagrid::vertex_tag>::type vertex_type;

        element_type element;
        element.id( id );

        return push_element_noid(domain, element).first;
    }

    template<typename element_type, typename domain_type, typename hook_array_iterator_type>
    typename result_of::element_hook<domain_type, typename element_type::tag>::type create_element( domain_type & domain,
                                                                                hook_array_iterator_type array_start, const hook_array_iterator_type & array_end )
    {
        element_type element = element_type( inserter(domain).get_physical_container_collection() );

        size_t element_index = 0;
        for ( ; array_start != array_end; ++array_start, ++element_index )
            viennagrid::set_vertex( element, *array_start, element_index );

        //for (typename hook_array_type::const_iterator it = array.begin(); it != array.end(); ++it, ++element_index)
            //viennagrid::set_vertex( element, *it, element_index );

        return push_element(domain, element).first;
    }

    template<typename element_type, typename domain_type, typename hook_array_type>
    typename result_of::element_hook<domain_type, typename element_type::tag>::type create_element( domain_type & domain, const hook_array_type & array )
    {
        return create_element<element_type>(domain, array.begin(), array.end() );
    }

    template<typename element_type, typename domain_type, typename hook_array_iterator_type>
    typename result_of::element_hook<domain_type, typename element_type::tag>::type create_element( domain_type & domain,
                                                                                hook_array_iterator_type array_start, const hook_array_iterator_type & array_end,
                                                                                typename element_type::id_type id )
    {
        element_type element = element_type( inserter(domain).get_physical_container_collection() );

        element.id( id );

        size_t element_index = 0;
        for ( ; array_start != array_end; ++array_start, ++element_index )
            viennagrid::set_vertex( element, *array_start, element_index );

        return push_element_noid(domain, element ).first;
    }

    template<typename element_type, typename domain_type, typename hook_array_type>
    typename result_of::element_hook<domain_type, typename element_type::tag>::type create_element( domain_type & domain, const hook_array_type & array, typename element_type::id_type id )
    {
        return create_element<element_type>(domain, array.begin(), array.end(), id );
    }

    template<typename plc_type, typename domain_type, typename polygon_hook_array_iterator_type,
//                 typename polygon_hook_type,
                typename line_hook_array_iterator_type, typename vertex_hook_array_iterator_type,
                typename point_iterator_type>
    typename result_of::element_hook<domain_type, plc_type>::type create_element( domain_type & domain,
                             polygon_hook_array_iterator_type bounding_polygon_it, polygon_hook_array_iterator_type const & bounding_polygon_end,
//                              polygon_hook_type bounding_polygon,
                             line_hook_array_iterator_type line_it, line_hook_array_iterator_type const & lines_end,
                             vertex_hook_array_iterator_type vertex_it, vertex_hook_array_iterator_type const & vertices_end,
                             point_iterator_type hole_point_it, point_iterator_type const & hole_point_end
                                                                                )
    {
        std::pair<typename result_of::element_hook<domain_type, plc_type>::type, bool> ret = viennagrid::push_element<true, false>(domain, plc_type( inserter(domain).get_physical_container_collection() ) );
        typename result_of::element_hook<domain_type, plc_type>::type plc_hook = ret.first;
        plc_type & plc = viennagrid::dereference_hook(domain, plc_hook);

        typename tagging::result_of::element_tag<plc_type, bounding_tag>::type plc_bounding_tag(plc);
        typename tagging::result_of::element_tag<plc_type, loose_tag>::type plc_loose_tag(plc);

        for ( ; bounding_polygon_it != bounding_polygon_end; ++bounding_polygon_it)
        {
            plc.container( viennagrid::polygon_tag() ).insert_hook( *bounding_polygon_it );
        }

        for ( ; line_it != lines_end; ++line_it)
        {
            plc.container( viennagrid::line_tag() ).insert_hook( *line_it );
            tagging::tag(viennagrid::dereference_hook(domain, *line_it), plc_loose_tag);
        }

        for ( ; vertex_it != vertices_end; ++vertex_it)
        {
            plc.container( viennagrid::vertex_tag() ).insert_hook( *vertex_it );
            tagging::tag(viennagrid::dereference_hook(domain, *vertex_it), plc_loose_tag);
        }

        typedef typename std::iterator_traits<point_iterator_type>::value_type point_type;
        std::vector<point_type> hole_points;
        std::copy(hole_point_it, hole_point_end, std::back_inserter(hole_points) );
        viennadata::access< plc_hole_point_tag, std::vector<point_type> >()(plc) = hole_points;

        plc.insert_callback( inserter(domain), ret.second );
        return plc_hook;
    }

    template<typename plc_type, typename domain_type,
                typename polygon_hook_array_iterator_type,
//                 typename polygon_hook_type,
//                 typename polygon_hook_array_iterator_type,
                typename line_hook_array_iterator_type, typename vertex_hook_array_iterator_type,
                typename point_iterator_type>
    typename result_of::element_hook<domain_type, plc_type>::type create_element( domain_type & domain,
//                              polygon_hook_type bounding_polygon,
                             polygon_hook_array_iterator_type bounding_polygon_it, polygon_hook_array_iterator_type const & bounding_polygon_end,
                             polygon_hook_array_iterator_type polygon_it, polygon_hook_array_iterator_type const & polygons_end,
                             line_hook_array_iterator_type line_it, line_hook_array_iterator_type const & lines_end,
                             vertex_hook_array_iterator_type vertex_it, vertex_hook_array_iterator_type const & vertices_end,
                             point_iterator_type hole_point_it, point_iterator_type const & hole_point_end
                                                                                )
    {
        typedef typename std::iterator_traits<line_hook_array_iterator_type>::value_type line_hook_type;
        std::vector<line_hook_type> lines;

        std::copy( line_it, lines_end, std::back_inserter(lines) );

        for ( ; polygon_it != polygons_end; ++polygon_it  )
        {
            typedef typename viennagrid::result_of::element<domain_type, viennagrid::polygon_tag>::type polygon_type;

            polygon_type & polygon = viennagrid::dereference_hook( domain, *polygon_it );

            typedef typename viennagrid::result_of::element_range<polygon_type, viennagrid::line_tag>::type line_on_polygon_range;
            line_on_polygon_range lines_on_polygon = viennagrid::elements<viennagrid::line_tag>(polygon);

            std::copy( lines_on_polygon.hook_begin(), lines_on_polygon.hook_end(), std::back_inserter(lines) );
        }

        return create_element<plc_type>(domain, bounding_polygon_it, bounding_polygon_end, lines.begin(), lines.end(), vertex_it, vertices_end, hole_point_it, hole_point_end);
    }

    template<typename domain_type, typename vertex_hook_type>
    typename result_of::element_hook<domain_type, line_tag>::type create_line( domain_type & domain, vertex_hook_type v0, vertex_hook_type v1 )
    {
        typedef typename result_of::element<domain_type, line_tag>::type element_type;
        element_type element = element_type( inserter(domain).get_physical_container_collection() );

        viennagrid::set_vertex( element, v0, 0 );
        viennagrid::set_vertex( element, v1, 1 );

        return push_element(domain, element).first;
    }

    template<typename domain_type, typename vertex_hook_type>
    typename result_of::element_hook<domain_type, triangle_tag>::type create_triangle( domain_type & domain, vertex_hook_type v0, vertex_hook_type v1, vertex_hook_type v2 )
    {
        typedef typename result_of::element<domain_type, triangle_tag>::type element_type;
        element_type element = element_type( inserter(domain).get_physical_container_collection() );

        viennagrid::set_vertex( element, v0, 0 );
        viennagrid::set_vertex( element, v1, 1 );
        viennagrid::set_vertex( element, v2, 2 );

        return push_element(domain, element).first;
    }

}

#endif
<|endoftext|>