<commit_before>// Copyright (c) 2014, Facebook, Inc.  All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.

#include "port/likely.h"
#include "util/mutexlock.h"
#include "util/thread_status_impl.h"

namespace rocksdb {

ThreadStatusImpl thread_local_status;

#if ROCKSDB_USING_THREAD_STATUS
__thread ThreadStatusData* ThreadStatusImpl::thread_status_data_ = nullptr;
std::mutex ThreadStatusImpl::thread_list_mutex_;
std::unordered_set<ThreadStatusData*> ThreadStatusImpl::thread_data_set_;
std::unordered_map<const void*, ConstantColumnFamilyInfo*>
    ThreadStatusImpl::cf_info_map_;
std::unordered_map<const void*, std::unordered_set<const void*>>
    ThreadStatusImpl::db_key_map_;

ThreadStatusImpl::~ThreadStatusImpl() {
  std::lock_guard<std::mutex> lck(thread_list_mutex_);
  for (auto* thread_data : thread_data_set_) {
    assert(thread_data->thread_type == ThreadStatus::ThreadType::USER_THREAD);
    delete thread_data;
  }
  assert(thread_data_set_.size() == 0);
  thread_data_set_.clear();
}

void ThreadStatusImpl::UnregisterThread() {
  if (thread_status_data_ != nullptr) {
    std::lock_guard<std::mutex> lck(thread_list_mutex_);
    thread_data_set_.erase(thread_status_data_);
    delete thread_status_data_;
  }
}

void ThreadStatusImpl::SetThreadType(
    ThreadStatus::ThreadType ttype) {
  auto* data = InitAndGet();
  data->thread_type.store(ttype, std::memory_order_relaxed);
}

void ThreadStatusImpl::SetColumnFamilyInfoKey(
    const void* cf_key) {
  auto* data = InitAndGet();
  data->cf_key.store(cf_key, std::memory_order_relaxed);
}

void ThreadStatusImpl::SetEventInfoPtr(
    const ThreadEventInfo* event_info) {
  auto* data = InitAndGet();
  data->event_info.store(event_info, std::memory_order_relaxed);
}

Status ThreadStatusImpl::GetThreadList(
    std::vector<ThreadStatus>* thread_list) const {
  thread_list->clear();
  std::vector<std::shared_ptr<ThreadStatusData>> valid_list;

  std::lock_guard<std::mutex> lck(thread_list_mutex_);
  for (auto* thread_data : thread_data_set_) {
    assert(thread_data);
    auto thread_type = thread_data->thread_type.load(
        std::memory_order_relaxed);
    auto cf_key = thread_data->cf_key.load(
        std::memory_order_relaxed);
    auto iter = cf_info_map_.find(
        thread_data->cf_key.load(std::memory_order_relaxed));
    assert(cf_key == 0 || iter != cf_info_map_.end());
    auto* cf_info = iter != cf_info_map_.end() ?
        iter->second : nullptr;
    auto* event_info = thread_data->event_info.load(
        std::memory_order_relaxed);
    const std::string* db_name = nullptr;
    const std::string* cf_name = nullptr;
    const std::string* event_name = nullptr;
    if (cf_info != nullptr) {
      db_name = &cf_info->db_name;
      cf_name = &cf_info->cf_name;
      // display lower-level info only when higher-level info is available.
      if (event_info != nullptr) {
        event_name = &event_info->event_name;
      }
    }
    thread_list->emplace_back(
        thread_data->thread_id, thread_type,
        db_name ? *db_name : "",
        cf_name ? *cf_name : "",
        event_name ? *event_name : "");
  }

  return Status::OK();
}

ThreadStatusData* ThreadStatusImpl::InitAndGet() {
  if (UNLIKELY(thread_status_data_ == nullptr)) {
    thread_status_data_ = new ThreadStatusData();
    thread_status_data_->thread_id = reinterpret_cast<uint64_t>(
        thread_status_data_);
    std::lock_guard<std::mutex> lck(thread_list_mutex_);
    thread_data_set_.insert(thread_status_data_);
  }
  return thread_status_data_;
}

void ThreadStatusImpl::NewColumnFamilyInfo(
    const void* db_key, const std::string& db_name,
    const void* cf_key, const std::string& cf_name) {
  std::lock_guard<std::mutex> lck(thread_list_mutex_);

  cf_info_map_[cf_key] = new ConstantColumnFamilyInfo(db_key, db_name, cf_name);
  db_key_map_[db_key].insert(cf_key);
}

void ThreadStatusImpl::EraseColumnFamilyInfo(const void* cf_key) {
  std::lock_guard<std::mutex> lck(thread_list_mutex_);
  auto cf_pair = cf_info_map_.find(cf_key);
  assert(cf_pair != cf_info_map_.end());

  auto* cf_info = cf_pair->second;
  assert(cf_info);

  // Remove its entry from db_key_map_ by the following steps:
  // 1. Obtain the entry in db_key_map_ whose set contains cf_key
  // 2. Remove it from the set.
  auto db_pair = db_key_map_.find(cf_info->db_key);
  assert(db_pair != db_key_map_.end());
  int result __attribute__((unused)) = db_pair->second.erase(cf_key);
  assert(result);

  delete cf_info;
  result = cf_info_map_.erase(cf_key);
  assert(result);
}

void ThreadStatusImpl::EraseDatabaseInfo(const void* db_key) {
  std::lock_guard<std::mutex> lck(thread_list_mutex_);
  auto db_pair = db_key_map_.find(db_key);
  if (UNLIKELY(db_pair == db_key_map_.end())) {
    // In some occasional cases such as DB::Open fails, we won't
    // register ColumnFamilyInfo for a db.
    return;
  }

  int result __attribute__((unused)) = 0;
  for (auto cf_key : db_pair->second) {
    auto cf_pair = cf_info_map_.find(cf_key);
    assert(cf_pair != cf_info_map_.end());
    result = cf_info_map_.erase(cf_key);
    delete cf_pair->second;
    assert(result);
  }
  db_key_map_.erase(db_key);
}

#else

ThreadStatusImpl::~ThreadStatusImpl() {
}

void ThreadStatusImpl::UnregisterThread() {
}

void ThreadStatusImpl::SetThreadType(
    ThreadStatus::ThreadType ttype) {
}

void ThreadStatusImpl::SetColumnFamilyInfoKey(
    const void* cf_key) {
}

void ThreadStatusImpl::SetEventInfoPtr(
    const ThreadEventInfo* event_info) {
}

Status ThreadStatusImpl::GetThreadList(
    std::vector<ThreadStatus>* thread_list) const {
  return Status::NotSupported(
      "GetThreadList is not supported in the current running environment.");
}

void ThreadStatusImpl::NewColumnFamilyInfo(
    const void* db_key, const std::string& db_name,
    const void* cf_key, const std::string& cf_name) {
}

void ThreadStatusImpl::EraseColumnFamilyInfo(const void* cf_key) {
}

void ThreadStatusImpl::EraseDatabaseInfo(const void* db_key) {
}

#endif  // ROCKSDB_USING_THREAD_STATUS
}  // namespace rocksdb
<commit_msg>Fix clang compile error<commit_after>// Copyright (c) 2014, Facebook, Inc.  All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.

#include "port/likely.h"
#include "util/mutexlock.h"
#include "util/thread_status_impl.h"

namespace rocksdb {

ThreadStatusImpl thread_local_status;

#if ROCKSDB_USING_THREAD_STATUS
__thread ThreadStatusData* ThreadStatusImpl::thread_status_data_ = nullptr;
std::mutex ThreadStatusImpl::thread_list_mutex_;
std::unordered_set<ThreadStatusData*> ThreadStatusImpl::thread_data_set_;
std::unordered_map<const void*, ConstantColumnFamilyInfo*>
    ThreadStatusImpl::cf_info_map_;
std::unordered_map<const void*, std::unordered_set<const void*>>
    ThreadStatusImpl::db_key_map_;

ThreadStatusImpl::~ThreadStatusImpl() {
  std::lock_guard<std::mutex> lck(thread_list_mutex_);
  for (auto* thread_data : thread_data_set_) {
    assert(thread_data->thread_type == ThreadStatus::ThreadType::USER_THREAD);
    delete thread_data;
  }
  assert(thread_data_set_.size() == 0);
  thread_data_set_.clear();
}

void ThreadStatusImpl::UnregisterThread() {
  if (thread_status_data_ != nullptr) {
    std::lock_guard<std::mutex> lck(thread_list_mutex_);
    thread_data_set_.erase(thread_status_data_);
    delete thread_status_data_;
  }
}

void ThreadStatusImpl::SetThreadType(
    ThreadStatus::ThreadType ttype) {
  auto* data = InitAndGet();
  data->thread_type.store(ttype, std::memory_order_relaxed);
}

void ThreadStatusImpl::SetColumnFamilyInfoKey(
    const void* cf_key) {
  auto* data = InitAndGet();
  data->cf_key.store(cf_key, std::memory_order_relaxed);
}

void ThreadStatusImpl::SetEventInfoPtr(
    const ThreadEventInfo* event_info) {
  auto* data = InitAndGet();
  data->event_info.store(event_info, std::memory_order_relaxed);
}

Status ThreadStatusImpl::GetThreadList(
    std::vector<ThreadStatus>* thread_list) const {
  thread_list->clear();
  std::vector<std::shared_ptr<ThreadStatusData>> valid_list;

  std::lock_guard<std::mutex> lck(thread_list_mutex_);
  for (auto* thread_data : thread_data_set_) {
    assert(thread_data);
    auto thread_type = thread_data->thread_type.load(
        std::memory_order_relaxed);
    auto cf_key = thread_data->cf_key.load(
        std::memory_order_relaxed);
    auto iter = cf_info_map_.find(
        thread_data->cf_key.load(std::memory_order_relaxed));
    assert(cf_key == 0 || iter != cf_info_map_.end());
    auto* cf_info = iter != cf_info_map_.end() ?
        iter->second : nullptr;
    auto* event_info = thread_data->event_info.load(
        std::memory_order_relaxed);
    const std::string* db_name = nullptr;
    const std::string* cf_name = nullptr;
    const std::string* event_name = nullptr;
    if (cf_info != nullptr) {
      db_name = &cf_info->db_name;
      cf_name = &cf_info->cf_name;
      // display lower-level info only when higher-level info is available.
      if (event_info != nullptr) {
        event_name = &event_info->event_name;
      }
    }
    thread_list->emplace_back(
        thread_data->thread_id, thread_type,
        db_name ? *db_name : "",
        cf_name ? *cf_name : "",
        event_name ? *event_name : "");
  }

  return Status::OK();
}

ThreadStatusData* ThreadStatusImpl::InitAndGet() {
  if (UNLIKELY(thread_status_data_ == nullptr)) {
    thread_status_data_ = new ThreadStatusData();
    thread_status_data_->thread_id = reinterpret_cast<uint64_t>(
        thread_status_data_);
    std::lock_guard<std::mutex> lck(thread_list_mutex_);
    thread_data_set_.insert(thread_status_data_);
  }
  return thread_status_data_;
}

void ThreadStatusImpl::NewColumnFamilyInfo(
    const void* db_key, const std::string& db_name,
    const void* cf_key, const std::string& cf_name) {
  std::lock_guard<std::mutex> lck(thread_list_mutex_);

  cf_info_map_[cf_key] = new ConstantColumnFamilyInfo(db_key, db_name, cf_name);
  db_key_map_[db_key].insert(cf_key);
}

void ThreadStatusImpl::EraseColumnFamilyInfo(const void* cf_key) {
  std::lock_guard<std::mutex> lck(thread_list_mutex_);
  auto cf_pair = cf_info_map_.find(cf_key);
  assert(cf_pair != cf_info_map_.end());

  auto* cf_info = cf_pair->second;
  assert(cf_info);

  // Remove its entry from db_key_map_ by the following steps:
  // 1. Obtain the entry in db_key_map_ whose set contains cf_key
  // 2. Remove it from the set.
  auto db_pair = db_key_map_.find(cf_info->db_key);
  assert(db_pair != db_key_map_.end());
  size_t result __attribute__((unused)) = db_pair->second.erase(cf_key);
  assert(result);

  delete cf_info;
  result = cf_info_map_.erase(cf_key);
  assert(result);
}

void ThreadStatusImpl::EraseDatabaseInfo(const void* db_key) {
  std::lock_guard<std::mutex> lck(thread_list_mutex_);
  auto db_pair = db_key_map_.find(db_key);
  if (UNLIKELY(db_pair == db_key_map_.end())) {
    // In some occasional cases such as DB::Open fails, we won't
    // register ColumnFamilyInfo for a db.
    return;
  }

  size_t result __attribute__((unused)) = 0;
  for (auto cf_key : db_pair->second) {
    auto cf_pair = cf_info_map_.find(cf_key);
    assert(cf_pair != cf_info_map_.end());
    result = cf_info_map_.erase(cf_key);
    delete cf_pair->second;
    assert(result);
  }
  db_key_map_.erase(db_key);
}

#else

ThreadStatusImpl::~ThreadStatusImpl() {
}

void ThreadStatusImpl::UnregisterThread() {
}

void ThreadStatusImpl::SetThreadType(
    ThreadStatus::ThreadType ttype) {
}

void ThreadStatusImpl::SetColumnFamilyInfoKey(
    const void* cf_key) {
}

void ThreadStatusImpl::SetEventInfoPtr(
    const ThreadEventInfo* event_info) {
}

Status ThreadStatusImpl::GetThreadList(
    std::vector<ThreadStatus>* thread_list) const {
  return Status::NotSupported(
      "GetThreadList is not supported in the current running environment.");
}

void ThreadStatusImpl::NewColumnFamilyInfo(
    const void* db_key, const std::string& db_name,
    const void* cf_key, const std::string& cf_name) {
}

void ThreadStatusImpl::EraseColumnFamilyInfo(const void* cf_key) {
}

void ThreadStatusImpl::EraseDatabaseInfo(const void* db_key) {
}

#endif  // ROCKSDB_USING_THREAD_STATUS
}  // namespace rocksdb
<|endoftext|>


<commit_before>#include <KnowledgeBase.h>
#include <AttributeType.h>

#include <boost/filesystem.hpp>

#include <ratio>
#include <algorithm>
#include <iostream>
#include <boost/filesystem/fstream.hpp>

namespace test {

 using namespace ::id::attribute;
 using std::ratio;
 using std::cout;
 using std::endl;
 using std::vector;
 using std::any_of;
 using boost::filesystem::ofstream;
 using boost::filesystem::current_path;
 using boost::filesystem::path;

  struct KnowledgeBaseTestSuite : public ::testing::Test {

    struct Test0: public ::id::attribute::Base {
      static constexpr const ::id::attribute::ID value()  { return 251; }
    };

    struct Test1 : public ::id::attribute::Base {
      static constexpr const ::id::attribute::ID value()  { return 252; }
    };

    struct Test2 : public ::id::attribute::Base {
      static constexpr const ::id::attribute::ID value()  { return 253; }
    };

    struct Test3 : public ::id::attribute::Base {
      static constexpr const ::id::attribute::ID value()  { return 254; }
    };

    struct Test4 : public ::id::attribute::Base {
      static constexpr const ::id::attribute::ID value() { return 255; }
    };

    struct HetTrans0 : public Transformation {
      const EventType& outE;
      const EventType& inE;
      HetTrans0(const EventType& outE, const EventType& inE)
        : Transformation(Type::heterogeneus, 1, EventID({Test2::value()})), outE(outE), inE(inE)
      {}
      virtual EventIDs in(EventID goal) const  {
        return EventIDs({ EventID({Test3::value()}) });
      }
      virtual vector<EventType> in(const EventType& goal) const  {
        if(goal == outE)
          return {inE};
        else
          return {};
      }
      virtual TransPtr create(const EventType& outE, const EventTypes& inE) const { return TransPtr(); }
      virtual void print(std::ostream& o) const { o << "Heterogeneus Transform 1"; }
    };

    struct HetTrans1 : public Transformation {
      const EventType& outE;
      const EventType& in0;
      const EventType& in1;
      HetTrans1(const EventType& outE, const EventType& in0, const EventType& in1)
        : Transformation(Type::heterogeneus, 2, EventID({Test0::value()})), outE(outE), in0(in0), in1(in1)
      {}
      virtual EventIDs in(EventID goal) const  {
        return EventIDs({ EventID({Test1::value()}), EventID({Test2::value()})});
      }
      virtual vector<EventType> in(const EventType& goal) const  {
        if(goal == outE)
          return {in0, in1};
        else
          return {};
      }
      virtual TransPtr create(const EventType& outE, const EventTypes& inE) const { return TransPtr(); }
      virtual void print(std::ostream& o) const { o << "Heterogeneus Transform 2"; }
    };

    struct HomTrans0 : public Transformation {
      const EventType& outE;
      const EventType& inE;
      const EventType& p;
      HomTrans0(const EventType& outE, const EventType& inE, const EventType& p)
        : Transformation(Type::attribute, 1, EventID::any), outE(outE), inE(inE), p(p)
      {}
      virtual EventIDs in(EventID goal) const  {
        return EventIDs({ goal });
      }
      virtual vector<EventType> in(const EventType& goal,  const EventType& provided) const  {
        if(goal == outE && provided == p)
          return {inE};
        else
          return {};
      }
      virtual TransPtr create(const EventType& outE, const EventTypes& inE) const { return TransPtr(); }
      virtual void print(std::ostream& o) const { o << "Homogeneus Transform 1"; }
    };

    struct HomTrans1 : public Transformation {
      const EventType& outE;
      const EventType& in0;
      const EventType& in1;
      const EventType& p;
      HomTrans1(const EventType& outE, const EventType& in0, const EventType& in1, const EventType& p)
        : Transformation(Type::attribute, 2, EventID::any), outE(outE), in0(in0), in1(in1), p(p)
      {}
      virtual EventIDs in(EventID goal) const  {
        return EventIDs({ goal, EventID({Test4::value()})});
      }
      virtual vector<EventType> in(const EventType& goal,  const EventType& provided) const  {
        if(goal == outE && provided == p)
          return {in0, in1};
        else
          return {};
      }
      virtual TransPtr create(const EventType& outE, const EventTypes& inE) const { return TransPtr(); }
      virtual void print(std::ostream& o) const { o << "Homogeneus Transform 2"; }
    };

    EventType eT0, eT1, eT2, eT3, eT4, eT5, eT6, eT7;

    HetTrans0 het0=HetTrans0(eT2, eT3);
    HetTrans1 het1=HetTrans1(eT0, eT1, eT2);
    HomTrans0 hom0=HomTrans0(eT3, eT4, eT4);
    HomTrans1 hom1=HomTrans1(eT1, eT5, eT6, eT5);
    HomTrans0 hom2=HomTrans0(eT4, eT7, eT7);
    HomTrans0 hom3=HomTrans0(eT3, eT4, eT7);

    KnowledgeBaseTestSuite() {
      ValueType v(id::type::Float::value(), 1, 1, false);
      ValueType v2(id::type::UInt64::value(), 1, 1, false);
      KnowledgeBase::clear();
      KnowledgeBase::registerTransformation(het0);
      KnowledgeBase::registerTransformation(het1);
      KnowledgeBase::registerTransformation(hom0);
      KnowledgeBase::registerTransformation(hom1);
      KnowledgeBase::registerTransformation(hom2);
      KnowledgeBase::registerTransformation(hom3);
      eT0.add(AttributeType(Test0::value(), v, Scale<>(), Dimensionless()));
      eT1.add(AttributeType(Test1::value(), v, Scale<>(), Dimensionless()));
      eT2.add(AttributeType(Test2::value(), v, Scale<>(), Dimensionless()));
      eT3.add(AttributeType(Test3::value(), v, Scale<>(), Dimensionless()));
      eT4.add(AttributeType(Test3::value(), v, Scale<ratio<1, 1000>>(), Dimensionless()));
      eT5.add(AttributeType(Test1::value(), v, Scale<ratio<1, 1>, 1>(), Dimensionless()));
      eT6.add(AttributeType(Test1::value(), v, Scale<ratio<1, 1>, 0>(), Dimensionless()));
      eT6.add(AttributeType(Test4::value(), v, Scale<ratio<1, 1>, 1>(), Dimensionless()));
      eT7.add(AttributeType(Test3::value(), v2, Scale<ratio<1, 1000>>(), Dimensionless()));
      path file = current_path()/"doc"/"kb.dot";
      ofstream out(file);
      KnowledgeBase::print(out);
    }

    using  Transformations = KnowledgeBase::Transformations;

    bool checkResult(const Transformations& ts, const Transformation & t) {
      auto pred = [&t](const CompositeTransformation& cT) {
        return *cT.graph()[cT.root()].trans() == t;
      };
      return any_of(ts.begin(), ts.end(), pred);
    }
  };

  TEST_F(KnowledgeBaseTestSuite, singleHeterogeneusTransform) {
    EXPECT_EQ(EventID(eT2), het0.out()) << "Wrong Output ID";
    EXPECT_EQ(het0.arity(), 1U) << "Wrong arity";
    ASSERT_EQ(het0.in(EventID(eT2)).size(), 1U) << "Wrong number of input IDs";
    EXPECT_EQ(EventID(eT3), het0.in(EventID(eT2)).front()) << "Wrong input ID";
    ASSERT_EQ(het0.in(eT2).size(), 1U) << "Wrong number of input Types";
    EXPECT_EQ(eT3, het0.in(eT2).front()) << "Wrong input Type";
  }

  TEST_F(KnowledgeBaseTestSuite, singleHomogeneusTransform) {
    EXPECT_EQ(EventID::any, hom0.out()) << "Wrong Output ID";
    EXPECT_EQ(hom0.arity(), 1U) << "Wrong arity";
    ASSERT_EQ(hom0.in(EventID(eT3)).size(), 1U) << "Wrong number of input IDs";
    EXPECT_EQ(EventID(eT4), hom0.in(EventID(eT3)).front()) << "Wrong input ID";
    ASSERT_EQ(hom0.in(eT3, eT4).size(), 1U) << "Wrong number of input Types";
    EXPECT_EQ(eT4, hom0.in(eT3, eT4).front()) << "Wrong input Type";
  }

  TEST_F(KnowledgeBaseTestSuite, findSingleHeterogeneusTransform) {
    KnowledgeBase::registerEventType(eT3);
    Transformations ts = KnowledgeBase::findTransforms(eT2);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
    EXPECT_TRUE(checkResult(ts, het0)) << "Searched Transform not found";
  }

  TEST_F(KnowledgeBaseTestSuite, findSingleHomogeneusTransform) {
    KnowledgeBase::registerEventType(eT4);
    Transformations ts = KnowledgeBase::findTransforms(eT3);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
    EXPECT_TRUE(checkResult(ts, hom0)) << "Searched Transform not found";
  }

  TEST_F(KnowledgeBaseTestSuite, findMultiHeterogeneusTransform) {
    KnowledgeBase::registerEventType(eT1);
    KnowledgeBase::registerEventType(eT2);
    Transformations ts = KnowledgeBase::findTransforms(eT0);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
    EXPECT_TRUE(checkResult(ts, het1)) << "Searched Transform not found";
  }

  TEST_F(KnowledgeBaseTestSuite, findMultiHomogeneusTransform) {
    KnowledgeBase::registerEventType(eT5);
    KnowledgeBase::registerEventType(eT6);
    Transformations ts = KnowledgeBase::findTransforms(eT1);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
    EXPECT_TRUE(checkResult(ts, hom1)) << "Searched Transform not found";
  }

  TEST_F(KnowledgeBaseTestSuite, findCombinedAttributeTransform) {
    KnowledgeBase::registerEventType(eT7);
    Transformations ts = KnowledgeBase::findTransforms(eT3);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
    TransformationPtr hom2Ptr(&hom2);
    TransformationPtr hom3Ptr(&hom3);
    auto check = [hom2Ptr, hom3Ptr](const CompositeTransformation& cT){
      const CompositeTransformation::Graph& g = cT.graph();
      auto pred0 = [hom2Ptr, &g](CompositeTransformation::Vertex v){ return g[v].trans()==hom2Ptr; };
      auto pred1 = [hom3Ptr, &g](CompositeTransformation::Vertex v){ return g[v].trans()==hom3Ptr; };
      auto vertices = boost::vertices(g);
      return any_of(vertices.first, vertices.second, pred0) &&
             any_of(vertices.first, vertices.second, pred1);
    };
    EXPECT_TRUE(any_of(ts.begin(), ts.end(), check));
  }

  TEST_F(KnowledgeBaseTestSuite, fullTree) {
    KnowledgeBase::registerEventType(eT7);
    KnowledgeBase::registerEventType(eT4);
    KnowledgeBase::registerEventType(eT5);
    KnowledgeBase::registerEventType(eT6);
    Transformations ts = KnowledgeBase::findTransforms(eT0);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
  }
}
<commit_msg>UNit-Test: add combined heterogeneus trans test<commit_after>#include <KnowledgeBase.h>
#include <AttributeType.h>

#include <boost/filesystem.hpp>

#include <ratio>
#include <algorithm>
#include <iostream>
#include <boost/filesystem/fstream.hpp>

namespace test {

 using namespace ::id::attribute;
 using std::ratio;
 using std::cout;
 using std::endl;
 using std::vector;
 using std::any_of;
 using boost::filesystem::ofstream;
 using boost::filesystem::current_path;
 using boost::filesystem::path;

  struct KnowledgeBaseTestSuite : public ::testing::Test {

    struct Test0: public ::id::attribute::Base {
      static constexpr const ::id::attribute::ID value()  { return 251; }
    };

    struct Test1 : public ::id::attribute::Base {
      static constexpr const ::id::attribute::ID value()  { return 252; }
    };

    struct Test2 : public ::id::attribute::Base {
      static constexpr const ::id::attribute::ID value()  { return 253; }
    };

    struct Test3 : public ::id::attribute::Base {
      static constexpr const ::id::attribute::ID value()  { return 254; }
    };

    struct Test4 : public ::id::attribute::Base {
      static constexpr const ::id::attribute::ID value() { return 255; }
    };

    struct HetTrans0 : public Transformation {
      const EventType& outE;
      const EventType& inE;
      HetTrans0(const EventType& outE, const EventType& inE)
        : Transformation(Type::heterogeneus, 1, EventID({Test2::value()})), outE(outE), inE(inE)
      {}
      virtual EventIDs in(EventID goal) const  {
        return EventIDs({ EventID({Test3::value()}) });
      }
      virtual vector<EventType> in(const EventType& goal) const  {
        if(goal == outE)
          return {inE};
        else
          return {};
      }
      virtual TransPtr create(const EventType& outE, const EventTypes& inE) const { return TransPtr(); }
      virtual void print(std::ostream& o) const { o << "Heterogeneus Transform 1"; }
    };

    struct HetTrans1 : public Transformation {
      const EventType& outE;
      const EventType& in0;
      const EventType& in1;
      HetTrans1(const EventType& outE, const EventType& in0, const EventType& in1)
        : Transformation(Type::heterogeneus, 2, EventID({Test0::value()})), outE(outE), in0(in0), in1(in1)
      {}
      virtual EventIDs in(EventID goal) const  {
        return EventIDs({ EventID({Test1::value()}), EventID({Test2::value()})});
      }
      virtual vector<EventType> in(const EventType& goal) const  {
        if(goal == outE)
          return {in0, in1};
        else
          return {};
      }
      virtual TransPtr create(const EventType& outE, const EventTypes& inE) const { return TransPtr(); }
      virtual void print(std::ostream& o) const { o << "Heterogeneus Transform 2"; }
    };

    struct HomTrans0 : public Transformation {
      const EventType& outE;
      const EventType& inE;
      const EventType& p;
      HomTrans0(const EventType& outE, const EventType& inE, const EventType& p)
        : Transformation(Type::attribute, 1, EventID::any), outE(outE), inE(inE), p(p)
      {}
      virtual EventIDs in(EventID goal) const  {
        return EventIDs({ goal });
      }
      virtual vector<EventType> in(const EventType& goal,  const EventType& provided) const  {
        if(goal == outE && provided == p)
          return {inE};
        else
          return {};
      }
      virtual TransPtr create(const EventType& outE, const EventTypes& inE) const { return TransPtr(); }
      virtual void print(std::ostream& o) const { o << "Homogeneus Transform 1"; }
    };

    struct HomTrans1 : public Transformation {
      const EventType& outE;
      const EventType& in0;
      const EventType& in1;
      const EventType& p;
      HomTrans1(const EventType& outE, const EventType& in0, const EventType& in1, const EventType& p)
        : Transformation(Type::attribute, 2, EventID::any), outE(outE), in0(in0), in1(in1), p(p)
      {}
      virtual EventIDs in(EventID goal) const  {
        return EventIDs({ goal, EventID({Test4::value()})});
      }
      virtual vector<EventType> in(const EventType& goal,  const EventType& provided) const  {
        if(goal == outE && provided == p)
          return {in0, in1};
        else
          return {};
      }
      virtual TransPtr create(const EventType& outE, const EventTypes& inE) const { return TransPtr(); }
      virtual void print(std::ostream& o) const { o << "Homogeneus Transform 2"; }
    };

    EventType eT0, eT1, eT2, eT3, eT4, eT5, eT6, eT7;

    HetTrans0 het0=HetTrans0(eT2, eT3);
    HetTrans1 het1=HetTrans1(eT0, eT1, eT2);
    HomTrans0 hom0=HomTrans0(eT3, eT4, eT4);
    HomTrans1 hom1=HomTrans1(eT1, eT5, eT6, eT5);
    HomTrans0 hom2=HomTrans0(eT4, eT7, eT7);
    HomTrans0 hom3=HomTrans0(eT3, eT4, eT7);

    KnowledgeBaseTestSuite() {
      ValueType v(id::type::Float::value(), 1, 1, false);
      ValueType v2(id::type::UInt64::value(), 1, 1, false);
      KnowledgeBase::clear();
      KnowledgeBase::registerTransformation(het0);
      KnowledgeBase::registerTransformation(het1);
      KnowledgeBase::registerTransformation(hom0);
      KnowledgeBase::registerTransformation(hom1);
      KnowledgeBase::registerTransformation(hom2);
      KnowledgeBase::registerTransformation(hom3);
      eT0.add(AttributeType(Test0::value(), v, Scale<>(), Dimensionless()));
      eT1.add(AttributeType(Test1::value(), v, Scale<>(), Dimensionless()));
      eT2.add(AttributeType(Test2::value(), v, Scale<>(), Dimensionless()));
      eT3.add(AttributeType(Test3::value(), v, Scale<>(), Dimensionless()));
      eT4.add(AttributeType(Test3::value(), v, Scale<ratio<1, 1000>>(), Dimensionless()));
      eT5.add(AttributeType(Test1::value(), v, Scale<ratio<1, 1>, 1>(), Dimensionless()));
      eT6.add(AttributeType(Test1::value(), v, Scale<ratio<1, 1>, 0>(), Dimensionless()));
      eT6.add(AttributeType(Test4::value(), v, Scale<ratio<1, 1>, 1>(), Dimensionless()));
      eT7.add(AttributeType(Test3::value(), v2, Scale<ratio<1, 1000>>(), Dimensionless()));
      path file = current_path()/"doc"/"kb.dot";
      ofstream out(file);
      KnowledgeBase::print(out);
    }

    using  Transformations = KnowledgeBase::Transformations;

    bool checkResult(const Transformations& ts, const Transformation & t) {
      auto pred = [&t](const CompositeTransformation& cT) {
        return *cT.graph()[cT.root()].trans() == t;
      };
      return any_of(ts.begin(), ts.end(), pred);
    }
  };

  TEST_F(KnowledgeBaseTestSuite, singleHeterogeneusTransform) {
    EXPECT_EQ(EventID(eT2), het0.out()) << "Wrong Output ID";
    EXPECT_EQ(het0.arity(), 1U) << "Wrong arity";
    ASSERT_EQ(het0.in(EventID(eT2)).size(), 1U) << "Wrong number of input IDs";
    EXPECT_EQ(EventID(eT3), het0.in(EventID(eT2)).front()) << "Wrong input ID";
    ASSERT_EQ(het0.in(eT2).size(), 1U) << "Wrong number of input Types";
    EXPECT_EQ(eT3, het0.in(eT2).front()) << "Wrong input Type";
  }

  TEST_F(KnowledgeBaseTestSuite, singleHomogeneusTransform) {
    EXPECT_EQ(EventID::any, hom0.out()) << "Wrong Output ID";
    EXPECT_EQ(hom0.arity(), 1U) << "Wrong arity";
    ASSERT_EQ(hom0.in(EventID(eT3)).size(), 1U) << "Wrong number of input IDs";
    EXPECT_EQ(EventID(eT4), hom0.in(EventID(eT3)).front()) << "Wrong input ID";
    ASSERT_EQ(hom0.in(eT3, eT4).size(), 1U) << "Wrong number of input Types";
    EXPECT_EQ(eT4, hom0.in(eT3, eT4).front()) << "Wrong input Type";
  }

  TEST_F(KnowledgeBaseTestSuite, findSingleHeterogeneusTransform) {
    KnowledgeBase::registerEventType(eT3);
    Transformations ts = KnowledgeBase::findTransforms(eT2);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
    EXPECT_TRUE(checkResult(ts, het0)) << "Searched Transform not found";
  }

  TEST_F(KnowledgeBaseTestSuite, findSingleHomogeneusTransform) {
    KnowledgeBase::registerEventType(eT4);
    Transformations ts = KnowledgeBase::findTransforms(eT3);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
    EXPECT_TRUE(checkResult(ts, hom0)) << "Searched Transform not found";
  }

  TEST_F(KnowledgeBaseTestSuite, findMultiHeterogeneusTransform) {
    KnowledgeBase::registerEventType(eT1);
    KnowledgeBase::registerEventType(eT2);
    Transformations ts = KnowledgeBase::findTransforms(eT0);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
    EXPECT_TRUE(checkResult(ts, het1)) << "Searched Transform not found";
  }

  TEST_F(KnowledgeBaseTestSuite, findMultiHomogeneusTransform) {
    KnowledgeBase::registerEventType(eT5);
    KnowledgeBase::registerEventType(eT6);
    Transformations ts = KnowledgeBase::findTransforms(eT1);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
    EXPECT_TRUE(checkResult(ts, hom1)) << "Searched Transform not found";
  }

  TEST_F(KnowledgeBaseTestSuite, findCombinedAttributeTransform) {
    KnowledgeBase::registerEventType(eT7);
    Transformations ts = KnowledgeBase::findTransforms(eT3);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
    TransformationPtr hom2Ptr(&hom2);
    TransformationPtr hom3Ptr(&hom3);
    auto check = [hom2Ptr, hom3Ptr](const CompositeTransformation& cT){
      const CompositeTransformation::Graph& g = cT.graph();
      auto pred0 = [hom2Ptr, &g](CompositeTransformation::Vertex v){ return g[v].trans()==hom2Ptr; };
      auto pred1 = [hom3Ptr, &g](CompositeTransformation::Vertex v){ return g[v].trans()==hom3Ptr; };
      auto vertices = boost::vertices(g);
      return any_of(vertices.first, vertices.second, pred0) &&
             any_of(vertices.first, vertices.second, pred1);
    };
    EXPECT_TRUE(any_of(ts.begin(), ts.end(), check));
  }

  TEST_F(KnowledgeBaseTestSuite, findCombinedHeterogeneusTransform) {
    KnowledgeBase::registerEventType(eT1);
    KnowledgeBase::registerEventType(eT3);
    Transformations ts = KnowledgeBase::findTransforms(eT0);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
  }

  TEST_F(KnowledgeBaseTestSuite, fullTree) {
    KnowledgeBase::registerEventType(eT7);
    KnowledgeBase::registerEventType(eT5);
    KnowledgeBase::registerEventType(eT6);
    Transformations ts = KnowledgeBase::findTransforms(eT0);
    ASSERT_GE(ts.size(), 1U) << "Wrong number of Transformations found";
  }
}
<|endoftext|>


<commit_before>/*
 * buildingBlock.cpp
 *
 *  Created on: 22 mars 2013
 *      Author: dom
 */

#include <iostream>

#include "buildingBlock.h"
#include "world.h"
#include "simulator.h"
#include "scheduler.h"
#include "trace.h"

using namespace std;

namespace BaseSimulator {

bID BuildingBlock::nextId = 0;
bool BuildingBlock::userConfigHasBeenParsed = false;

//===========================================================================================================
//
//          BuildingBlock  (class)
//
//===========================================================================================================

  BuildingBlock::BuildingBlock(int bId, BlockCodeBuilder bcb, int nbInterfaces) {
    OUTPUT << "BuildingBlock constructor (id:" << nextId << ")" << endl;

    if (bId < 0) {
      blockId = nextId;
      nextId++;
    } else {
      blockId = bId;
    }

    state.store(ALIVE);
    clock = new PerfectClock();

    ruint seed = Simulator::getSimulator()->getRandomUint();
    seed *= bId;
    generator = uintRNG(seed);

    buildNewBlockCode = bcb;

    if (utils::StatsIndividual::enable) {
      stats = new StatsIndividual();
    }

    for (int i = 0; i < nbInterfaces; i++) {
        P2PNetworkInterfaces.push_back(new P2PNetworkInterface(this));
    }

    //setDefaultHardwareParameters();

    blockCode = (BaseSimulator::BlockCode*)bcb(this);

    // Parse user configuration from configuration file, only performed once
    if (!userConfigHasBeenParsed) {
      userConfigHasBeenParsed = true;
      blockCode->parseUserElements(Simulator::getSimulator()->getConfigDocument());
    }

    isMaster = false;
}

BuildingBlock::~BuildingBlock() {
    delete blockCode;
	OUTPUT << "BuildingBlock destructor" << endl;

	if (clock != NULL) {
		delete clock;
	}

	if (stats != NULL) {
	        delete stats;
	}

	for (P2PNetworkInterface *p2p : P2PNetworkInterfaces)
		delete p2p;
}

bool BuildingBlock::addP2PNetworkInterfaceAndConnectTo(BuildingBlock *destBlock) {
    P2PNetworkInterface *ni1, *ni2;
    ni1 = NULL;
    ni2 = NULL;
    if (!getP2PNetworkInterfaceByBlockRef(destBlock)) {
		// creation of the new network interface
		OUTPUT << "adding a new interface to block " << destBlock->blockId << endl;
		ni1 = new P2PNetworkInterface(this);
		P2PNetworkInterfaces.push_back(ni1);
    }

    if (!destBlock->getP2PNetworkInterfaceByBlockRef(this)) {
		// creation of the new network interface
		OUTPUT << "adding a new interface to block " << this->blockId << endl;
		ni2 = new P2PNetworkInterface(destBlock);
		destBlock->P2PNetworkInterfaces.push_back(ni2);
    }

    if (ni1!=NULL && ni2!=NULL) {
		ni1->connect(ni2);
		return (true);
    } else {
		OUTPUT << "*** ERROR *** could not connect the new interfaces" << endl;
    }
    return false;
}

bool BuildingBlock::addP2PNetworkInterfaceAndConnectTo(int destBlockId) {
    // if the link is not in the list
    BuildingBlock *destBlock = BaseSimulator::getWorld()->getBlockById(destBlockId);
    if (!getP2PNetworkInterfaceByBlockRef(destBlock)) {
		// creation of the new network interface
		P2PNetworkInterface* ni1 = new P2PNetworkInterface(this);
		P2PNetworkInterfaces.push_back(ni1);
		// if the corresponding interface exists in the connected block, we link the two interfaces
		if (destBlock->addP2PNetworkInterfaceAndConnectTo(this)) {
			P2PNetworkInterface* ni2 = destBlock->getP2PNetworkInterfaceByBlockRef(this);
			ni1->connect(ni2);
		}
    }
    return false;
}

P2PNetworkInterface *BuildingBlock::getP2PNetworkInterfaceByBlockRef(BuildingBlock *destBlock) {
    for(P2PNetworkInterface *p2p : P2PNetworkInterfaces) {
		if (p2p->connectedInterface) {
			if (p2p->connectedInterface->hostBlock == destBlock) {
				return p2p;
			}
		}
    }
    return NULL;
}

P2PNetworkInterface*BuildingBlock::getP2PNetworkInterfaceByDestBlockId(bID destBlockId) {
    for(P2PNetworkInterface *p2p : P2PNetworkInterfaces) {
		if (p2p->connectedInterface) {
			if (p2p->connectedInterface->hostBlock->blockId == destBlockId) {
				return p2p;
			}
		}
    }
    return NULL;
}

unsigned short BuildingBlock::getNbNeighbors() {
  unsigned short n = 0;
  P2PNetworkInterface *p;
  vector<P2PNetworkInterface*>::iterator it;
  for (it = P2PNetworkInterfaces.begin(); it != P2PNetworkInterfaces.end(); ++it) {
    p = *it;
    if (p->isConnected()) {
      n++;
    }
  }
  return n;
}

void BuildingBlock::scheduleLocalEvent(EventPtr pev) {
    localEventsList.push_back(pev);

    if (localEventsList.size() == 1) {
		Time date;
		date = max(pev->date,this->blockCode->availabilityDate); // WARNING: is blockCode->availabilityDate considered?
		if (date < getScheduler()->now()) date=getScheduler()->now();
		getScheduler()->schedule(new ProcessLocalEvent(date,this));
    }
    return;
}

void BuildingBlock::processLocalEvent() {
    EventPtr pev;

    if (localEventsList.size() == 0) {
		cerr << "*** ERROR *** The local event list should not be empty !!" << endl;
		getScheduler()->trace("*** ERROR *** The local event list should not be empty !!");
		exit(EXIT_FAILURE);
    }
    pev = localEventsList.front();
    localEventsList.pop_front();
    blockCode->processLocalEvent(pev);

    if (pev->eventType == EVENT_NI_RECEIVE ) {
      utils::StatsIndividual::decIncommingMessageQueueSize(stats);
    }

    if (blockCode->availabilityDate < getScheduler()->now()) blockCode->availabilityDate = getScheduler()->now();
    if (localEventsList.size() > 0) {
		getScheduler()->schedule(new ProcessLocalEvent(blockCode->availabilityDate,this));
    }
}

void BuildingBlock::setColor(int idColor) {
    const GLfloat *col = tabColors[idColor%12];
    color.set(col[0],col[1],col[2],col[3]);
    getWorld()->updateGlData(this);
}

void BuildingBlock::setColor(const Color &c) {
    if (state.load() >= ALIVE) {
		color = c;
    }
    getWorld()->updateGlData(this);
}

void BuildingBlock::setPosition(const Cell3DPosition &p) {
    position = p;
    getWorld()->updateGlData(this);
}

void BuildingBlock::tap(Time date, int face) {
    OUTPUT << "tap scheduled" << endl;
    getScheduler()->schedule(new TapEvent(date, this, (uint8_t)face));
}

ruint BuildingBlock::getRandomUint() {
    return generator();
}

void BuildingBlock::setClock(Clock *c) {
  if (clock != NULL) {
    delete clock;
  }
  clock = c;
}

Time BuildingBlock::getLocalTime(Time simTime) {
  if (clock == NULL) {
    cerr << "device has no internal clock" << endl;
    return 0;
  }
  return clock->getTime(simTime);
}

Time BuildingBlock::getLocalTime() {
    if (clock == NULL) {
      cerr << "device has no internal clock" << endl;
      return 0;
    }
    return clock->getTime();
}

Time BuildingBlock::getSimulationTime(Time localTime) {
    if (clock == NULL) {
      cerr << "device has no internal clock" << endl;
      return localTime;
    }
    return clock->getSimulationTime(localTime);
}

/*************************************************
 *            MeldInterpreter Functions
 *************************************************/

unsigned short BuildingBlock::getNeighborIDForFace(int faceNum) {
    short nodeID = P2PNetworkInterfaces[faceNum]->getConnectedBlockId();

	return nodeID > 0  ? (unsigned short)nodeID : 0;
}

int BuildingBlock::getFaceForNeighborID(int nId) {
	for (uint face = 0; face < P2PNetworkInterfaces.size(); face++) {
		if (nId == getNeighborIDForFace(face))
			return face;
	}

	return -1;
}

} // BaseSimulator namespace
<commit_msg>NetworkInterface inheritance skeleton<commit_after>/*
 * buildingBlock.cpp
 *
 *  Created on: 22 mars 2013
 *      Author: dom
 */

#include <iostream>

#include "buildingBlock.h"
#include "world.h"
#include "simulator.h"
#include "scheduler.h"
#include "trace.h"

using namespace std;

namespace BaseSimulator {

bID BuildingBlock::nextId = 0;
bool BuildingBlock::userConfigHasBeenParsed = false;

//===========================================================================================================
//
//          BuildingBlock  (class)
//
//===========================================================================================================

  BuildingBlock::BuildingBlock(int bId, BlockCodeBuilder bcb, int nbInterfaces) {
    OUTPUT << "BuildingBlock constructor (id:" << nextId << ")" << endl;

    if (bId < 0) {
      blockId = nextId;
      nextId++;
    } else {
      blockId = bId;
    }

    state.store(ALIVE);
    clock = new PerfectClock();

    ruint seed = Simulator::getSimulator()->getRandomUint();
    seed *= bId;
    generator = uintRNG(seed);

    buildNewBlockCode = bcb;

    if (utils::StatsIndividual::enable) {
      stats = new StatsIndividual();
    }

    for (int i = 0; i < nbInterfaces; i++) {
        P2PNetworkInterfaces.push_back(new P2PNetworkInterface(this));
    }

    wirelessNetworkInterface = new WirelessNetworkInterface(this,100);
    //setDefaultHardwareParameters();

    blockCode = (BaseSimulator::BlockCode*)bcb(this);

    // Parse user configuration from configuration file, only performed once
    if (!userConfigHasBeenParsed) {
      userConfigHasBeenParsed = true;
      blockCode->parseUserElements(Simulator::getSimulator()->getConfigDocument());
    }

    isMaster = false;
}

BuildingBlock::~BuildingBlock() {
    delete blockCode;
	OUTPUT << "BuildingBlock destructor" << endl;

	if (clock != NULL) {
		delete clock;
	}

	if (stats != NULL) {
	        delete stats;
	}

	for (P2PNetworkInterface *p2p : P2PNetworkInterfaces)
		delete p2p;
}

bool BuildingBlock::addP2PNetworkInterfaceAndConnectTo(BuildingBlock *destBlock) {
    P2PNetworkInterface *ni1, *ni2;
    ni1 = NULL;
    ni2 = NULL;
    if (!getP2PNetworkInterfaceByBlockRef(destBlock)) {
		// creation of the new network interface
		OUTPUT << "adding a new interface to block " << destBlock->blockId << endl;
		ni1 = new P2PNetworkInterface(this);
		P2PNetworkInterfaces.push_back(ni1);
    }

    if (!destBlock->getP2PNetworkInterfaceByBlockRef(this)) {
		// creation of the new network interface
		OUTPUT << "adding a new interface to block " << this->blockId << endl;
		ni2 = new P2PNetworkInterface(destBlock);
		destBlock->P2PNetworkInterfaces.push_back(ni2);
    }

    if (ni1!=NULL && ni2!=NULL) {
		ni1->connect(ni2);
		return (true);
    } else {
		OUTPUT << "*** ERROR *** could not connect the new interfaces" << endl;
    }
    return false;
}

bool BuildingBlock::addP2PNetworkInterfaceAndConnectTo(int destBlockId) {
    // if the link is not in the list
    BuildingBlock *destBlock = BaseSimulator::getWorld()->getBlockById(destBlockId);
    if (!getP2PNetworkInterfaceByBlockRef(destBlock)) {
		// creation of the new network interface
		P2PNetworkInterface* ni1 = new P2PNetworkInterface(this);
		P2PNetworkInterfaces.push_back(ni1);
		// if the corresponding interface exists in the connected block, we link the two interfaces
		if (destBlock->addP2PNetworkInterfaceAndConnectTo(this)) {
			P2PNetworkInterface* ni2 = destBlock->getP2PNetworkInterfaceByBlockRef(this);
			ni1->connect(ni2);
		}
    }
    return false;
}

P2PNetworkInterface *BuildingBlock::getP2PNetworkInterfaceByBlockRef(BuildingBlock *destBlock) {
    for(P2PNetworkInterface *p2p : P2PNetworkInterfaces) {
		if (p2p->connectedInterface) {
			if (p2p->connectedInterface->hostBlock == destBlock) {
				return p2p;
			}
		}
    }
    return NULL;
}

P2PNetworkInterface*BuildingBlock::getP2PNetworkInterfaceByDestBlockId(bID destBlockId) {
    for(P2PNetworkInterface *p2p : P2PNetworkInterfaces) {
		if (p2p->connectedInterface) {
			if (p2p->connectedInterface->hostBlock->blockId == destBlockId) {
				return p2p;
			}
		}
    }
    return NULL;
}

unsigned short BuildingBlock::getNbNeighbors() {
  unsigned short n = 0;
  P2PNetworkInterface *p;
  vector<P2PNetworkInterface*>::iterator it;
  for (it = P2PNetworkInterfaces.begin(); it != P2PNetworkInterfaces.end(); ++it) {
    p = *it;
    if (p->isConnected()) {
      n++;
    }
  }
  return n;
}

void BuildingBlock::scheduleLocalEvent(EventPtr pev) {
    localEventsList.push_back(pev);

    if (localEventsList.size() == 1) {
		Time date;
		date = max(pev->date,this->blockCode->availabilityDate); // WARNING: is blockCode->availabilityDate considered?
		if (date < getScheduler()->now()) date=getScheduler()->now();
		getScheduler()->schedule(new ProcessLocalEvent(date,this));
    }
    return;
}

void BuildingBlock::processLocalEvent() {
    EventPtr pev;

    if (localEventsList.size() == 0) {
		cerr << "*** ERROR *** The local event list should not be empty !!" << endl;
		getScheduler()->trace("*** ERROR *** The local event list should not be empty !!");
		exit(EXIT_FAILURE);
    }
    pev = localEventsList.front();
    localEventsList.pop_front();
    blockCode->processLocalEvent(pev);

    if (pev->eventType == EVENT_NI_RECEIVE ) {
      utils::StatsIndividual::decIncommingMessageQueueSize(stats);
    }

    if (blockCode->availabilityDate < getScheduler()->now()) blockCode->availabilityDate = getScheduler()->now();
    if (localEventsList.size() > 0) {
		getScheduler()->schedule(new ProcessLocalEvent(blockCode->availabilityDate,this));
    }
}

void BuildingBlock::setColor(int idColor) {
    const GLfloat *col = tabColors[idColor%12];
    color.set(col[0],col[1],col[2],col[3]);
    getWorld()->updateGlData(this);
}

void BuildingBlock::setColor(const Color &c) {
    if (state.load() >= ALIVE) {
		color = c;
    }
    getWorld()->updateGlData(this);
}

void BuildingBlock::setPosition(const Cell3DPosition &p) {
    position = p;
    getWorld()->updateGlData(this);
}

void BuildingBlock::tap(Time date, int face) {
    OUTPUT << "tap scheduled" << endl;
    getScheduler()->schedule(new TapEvent(date, this, (uint8_t)face));
}

ruint BuildingBlock::getRandomUint() {
    return generator();
}

void BuildingBlock::setClock(Clock *c) {
  if (clock != NULL) {
    delete clock;
  }
  clock = c;
}

Time BuildingBlock::getLocalTime(Time simTime) {
  if (clock == NULL) {
    cerr << "device has no internal clock" << endl;
    return 0;
  }
  return clock->getTime(simTime);
}

Time BuildingBlock::getLocalTime() {
    if (clock == NULL) {
      cerr << "device has no internal clock" << endl;
      return 0;
    }
    return clock->getTime();
}

Time BuildingBlock::getSimulationTime(Time localTime) {
    if (clock == NULL) {
      cerr << "device has no internal clock" << endl;
      return localTime;
    }
    return clock->getSimulationTime(localTime);
}

/*************************************************
 *            MeldInterpreter Functions
 *************************************************/

unsigned short BuildingBlock::getNeighborIDForFace(int faceNum) {
    short nodeID = P2PNetworkInterfaces[faceNum]->getConnectedBlockId();

	return nodeID > 0  ? (unsigned short)nodeID : 0;
}

int BuildingBlock::getFaceForNeighborID(int nId) {
	for (uint face = 0; face < P2PNetworkInterfaces.size(); face++) {
		if (nId == getNeighborIDForFace(face))
			return face;
	}

	return -1;
}

} // BaseSimulator namespace
<|endoftext|>


<commit_before>#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Config/config.h"

#define LLVM_350_AND_NEWER \
  (LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5))

#if LLVM_350_AND_NEWER
#include <system_error>

#define ERROR_CODE std::error_code
#define UNIQUE_PTR std::unique_ptr
#else
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/system_error.h"

#define ERROR_CODE error_code
#define UNIQUE_PTR OwningPtr
#endif

using namespace llvm;

static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));

static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"),
               cl::value_desc("filename"));

int main(int argc, char **argv) {
  LLVMContext &Context = getGlobalContext();
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.

  cl::ParseCommandLineOptions(argc, argv, "libclc builtin preparation tool\n");

  std::string ErrorMessage;
  std::auto_ptr<Module> M;

  {
    UNIQUE_PTR<MemoryBuffer> BufferPtr;
    if (ERROR_CODE ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr))
      ErrorMessage = ec.message();
    else {
#if LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
      ErrorOr<Module *> ModuleOrErr = parseBitcodeFile(BufferPtr.get(), Context);
      if (ERROR_CODE ec = ModuleOrErr.getError())
        ErrorMessage = ec.message();
      M.reset(ModuleOrErr.get());
#else
      M.reset(ParseBitcodeFile(BufferPtr.get(), Context, &ErrorMessage));
#endif
    }
  }

  if (M.get() == 0) {
    errs() << argv[0] << ": ";
    if (ErrorMessage.size())
      errs() << ErrorMessage << "\n";
    else
      errs() << "bitcode didn't read correctly.\n";
    return 1;
  }

  // Set linkage of every external definition to linkonce_odr.
  for (Module::iterator i = M->begin(), e = M->end(); i != e; ++i) {
    if (!i->isDeclaration() && i->getLinkage() == GlobalValue::ExternalLinkage)
      i->setLinkage(GlobalValue::LinkOnceODRLinkage);
  }

  for (Module::global_iterator i = M->global_begin(), e = M->global_end();
       i != e; ++i) {
    if (!i->isDeclaration() && i->getLinkage() == GlobalValue::ExternalLinkage)
      i->setLinkage(GlobalValue::LinkOnceODRLinkage);
  }

  if (OutputFilename.empty()) {
    errs() << "no output file\n";
    return 1;
  }

  std::string ErrorInfo;
  UNIQUE_PTR<tool_output_file> Out
  (new tool_output_file(OutputFilename.c_str(), ErrorInfo,
#if (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 4)
                        sys::fs::F_Binary));
#elif LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5)
                        sys::fs::F_None));
#else
                        raw_fd_ostream::F_Binary));
#endif
  if (!ErrorInfo.empty()) {
    errs() << ErrorInfo << '\n';
    exit(1);
  }

  WriteBitcodeToFile(M.get(), Out->os());

  // Declare success.
  Out->keep();
  return 0;
}

<commit_msg>prepare-builtins: Fix broken build due to recent LLVM API change<commit_after>#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Config/config.h"

#define LLVM_350_AND_NEWER \
  (LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5))

#if LLVM_350_AND_NEWER
#include <system_error>

#define ERROR_CODE std::error_code
#define UNIQUE_PTR std::unique_ptr
#else
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/system_error.h"

#define ERROR_CODE error_code
#define UNIQUE_PTR OwningPtr
#endif

using namespace llvm;

static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));

static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"),
               cl::value_desc("filename"));

int main(int argc, char **argv) {
  LLVMContext &Context = getGlobalContext();
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.

  cl::ParseCommandLineOptions(argc, argv, "libclc builtin preparation tool\n");

  std::string ErrorMessage;
  std::auto_ptr<Module> M;

  {
#if LLVM_350_AND_NEWER
    ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFile(InputFilename);
    std::unique_ptr<MemoryBuffer> &BufferPtr = BufferOrErr.get();
    if (std::error_code  ec = BufferOrErr.getError())
#else
    UNIQUE_PTR<MemoryBuffer> BufferPtr;
    if (ERROR_CODE ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr))
#endif
      ErrorMessage = ec.message();
    else {
#if LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
      ErrorOr<Module *> ModuleOrErr = parseBitcodeFile(BufferPtr.get(), Context);
      if (ERROR_CODE ec = ModuleOrErr.getError())
        ErrorMessage = ec.message();
      M.reset(ModuleOrErr.get());
#else
      M.reset(ParseBitcodeFile(BufferPtr.get(), Context, &ErrorMessage));
#endif
    }
  }

  if (M.get() == 0) {
    errs() << argv[0] << ": ";
    if (ErrorMessage.size())
      errs() << ErrorMessage << "\n";
    else
      errs() << "bitcode didn't read correctly.\n";
    return 1;
  }

  // Set linkage of every external definition to linkonce_odr.
  for (Module::iterator i = M->begin(), e = M->end(); i != e; ++i) {
    if (!i->isDeclaration() && i->getLinkage() == GlobalValue::ExternalLinkage)
      i->setLinkage(GlobalValue::LinkOnceODRLinkage);
  }

  for (Module::global_iterator i = M->global_begin(), e = M->global_end();
       i != e; ++i) {
    if (!i->isDeclaration() && i->getLinkage() == GlobalValue::ExternalLinkage)
      i->setLinkage(GlobalValue::LinkOnceODRLinkage);
  }

  if (OutputFilename.empty()) {
    errs() << "no output file\n";
    return 1;
  }

  std::string ErrorInfo;
  UNIQUE_PTR<tool_output_file> Out
  (new tool_output_file(OutputFilename.c_str(), ErrorInfo,
#if (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 4)
                        sys::fs::F_Binary));
#elif LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5)
                        sys::fs::F_None));
#else
                        raw_fd_ostream::F_Binary));
#endif
  if (!ErrorInfo.empty()) {
    errs() << ErrorInfo << '\n';
    exit(1);
  }

  WriteBitcodeToFile(M.get(), Out->os());

  // Declare success.
  Out->keep();
  return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/traits.hh>
#include <libport/unit-test.hh>

using libport::test_suite;
using namespace libport;

#define BOOST_CHECK_TYPE(T1, T2)                                        \
  BOOST_CHECK_MESSAGE((meta::Eq<T1, T2>::res),                          \
                      (std::string(#T1 " != " #T2 " (")                 \
                       + typeid(T1).name() + " != "                    \
                       + typeid(T2).name() + ")"));                    \

void
check_argument()
{
  BOOST_CHECK_TYPE(traits::Arg<int>::res, int);
  BOOST_CHECK_TYPE(traits::Arg<std::string>::res, const std::string&);
  BOOST_CHECK_TYPE(traits::Flatten<const int&>::res, int);
}

test_suite*
init_test_suite()
{
  test_suite* suite = BOOST_TEST_SUITE("libport::traits");
  suite->add(BOOST_TEST_CASE(check_argument));
  return suite;
}
<commit_msg>Traits: test traits::Arg harder.<commit_after>/*
 * Copyright (C) 2009-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/traits.hh>
#include <libport/unit-test.hh>

using libport::test_suite;
using namespace libport;

#define BOOST_CHECK_TYPE(T1, T2)                                        \
  BOOST_CHECK_MESSAGE((meta::Eq<T1, T2>::res),                          \
                      (std::string(#T1 " != " #T2 " (")                 \
                       + typeid(T1).name() + " != "                    \
                       + typeid(T2).name() + ")"));                    \

void
check_argument()
{
  BOOST_CHECK_TYPE(traits::RemoveConst<int      >::res, int);
  BOOST_CHECK_TYPE(traits::RemoveConst<const int>::res, int);

  BOOST_CHECK_TYPE(traits::Arg<int>::res, int);
  BOOST_CHECK_TYPE(traits::Arg<std::string>::res, const std::string&);

  BOOST_CHECK_TYPE(traits::Flatten<int>::res, int);
  BOOST_CHECK_TYPE(traits::Flatten<int&>::res, int);
  BOOST_CHECK_TYPE(traits::Flatten<const int>::res, int);
  BOOST_CHECK_TYPE(traits::Flatten<const int&>::res, int);
}

test_suite*
init_test_suite()
{
  test_suite* suite = BOOST_TEST_SUITE("libport::traits");
  suite->add(BOOST_TEST_CASE(check_argument));
  return suite;
}
<|endoftext|>


<commit_before>// This file is part of the dune-hdd project:
//   http://users.dune-project.org/projects/dune-hdd
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_HDD_test_case_LINEARELLIPTIC_EOC_STUDY_HH
#define DUNE_HDD_test_case_LINEARELLIPTIC_EOC_STUDY_HH

#include <memory>
#include <vector>
#include <limits>
#include <algorithm>

#include <dune/common/timer.hh>

#if HAVE_DUNE_FEM
# include <dune/fem/misc/gridwidth.hh>
#else
# error "We need dune-fem until we have a reliable and fast method to compute the grid width!"
#endif

#include <dune/stuff/common/memory.hh>
#include <dune/stuff/common/convergence-study.hh>
#include <dune/stuff/grid/layers.hh>

#include <dune/gdt/discretefunction/default.hh>
#include <dune/gdt/operators/prolongations.hh>

namespace Dune {
namespace HDD {
namespace LinearElliptic {
namespace Tests {

/**
 *  Assumes that the DiscretizationImp is derived from Discretizations::ContainerBasedDefault and has a ctor of type
 *  DiscretizationImp(Stuff::Grid::ConstProviderInterface, BoundaryInfoConfig, ProblemType, level).
 *  Assumes that TestCaseType is derived from TestCases::Base and additionally provides
 *  * const Stuff::Common::ConfigTree& boundary_info() const
 *  * const ProblemType& problem() const
 *  * bool provides_exact_solution() const
 *  * const ExactSolutionType& exact_solution() const
 *  and the appropriate types.
 *
 *  Any derived class only has to provide identifier(), provided_norms(), expected_rate(), compute_norm_() and
 *  expected_results().
 */
template< class TestCaseType, class DiscretizationImp >
class EocStudyBase
  : public Stuff::Common::ConvergenceStudy
{
  typedef Stuff::Common::ConvergenceStudy BaseType;
protected:

  typedef DiscretizationImp DiscretizationType;
  typedef typename DiscretizationType::VectorType VectorType;
  typedef typename DiscretizationType::AnsatzSpaceType SpaceType;
  typedef GDT::DiscreteFunction< SpaceType, VectorType >      DiscreteFunctionType;
  typedef GDT::ConstDiscreteFunction< SpaceType, VectorType > ConstDiscreteFunctionType;

  typedef typename TestCaseType::ExactSolutionType ExactSolutionType;
  typedef typename TestCaseType::template Level< Stuff::Grid::ChoosePartView::view >::Type GridViewType;
  typedef typename TestCaseType::FunctionType FunctionType;

public:
  EocStudyBase(const TestCaseType& test_case)
    : test_case_(test_case)
    , current_refinement_(0)
    , last_computed_refinement_(std::numeric_limits< size_t >::max())
    , time_to_solution_(0)
    , reference_solution_computed_(false)
    , current_discretization_(nullptr)
    , current_solution_vector_on_level_(nullptr)
    , reference_discretization_(nullptr)
    , reference_solution_vector_(nullptr)
    , current_solution_vector_(nullptr)
  {
    if (test_case_.problem().parametric())
      DUNE_THROW(NotImplemented, "Parametric problems are not implemented yet!");
  }

  virtual ~EocStudyBase() {}

  virtual size_t num_refinements() const DS_OVERRIDE DS_FINAL
  {
    return test_case_.num_refinements();
  }

  virtual std::vector< std::string > provided_norms() const DS_OVERRIDE DS_FINAL
  {
    std::vector< std::string > ret = available_norms_();
    for (auto estimator : available_estimators_()) {
      if (is_norm(estimator))
        DUNE_THROW(Stuff::Exceptions::internal_error,
                   "We do not want to handle the case that norms and estimators have the same name!");
      ret.push_back(estimator);
    }
    return ret;
  } // ... provided_norms(...)

  virtual double norm_reference_solution(const std::string type) DS_OVERRIDE DS_FINAL
  {
    if (is_norm(type)) {
      if (test_case_.provides_exact_solution()) {
        return compute_norm_(*(test_case_.reference_grid_view()), test_case_.exact_solution(), type);
      } else {
        compute_reference_solution();
        assert(reference_discretization_);
        assert(reference_solution_vector_);
        const ConstDiscreteFunctionType reference_solution(*(reference_discretization_->ansatz_space()),
                                                           *reference_solution_vector_,
                                                           "reference solution");
        return compute_norm_(*(test_case_.reference_grid_view()), reference_solution, type);
      }
    } else
      return 1.0;
  } // ... norm_reference_solution(...)

  virtual size_t current_grid_size() const DS_OVERRIDE DS_FINAL
  {
    assert(current_refinement_ <= num_refinements());
    const int level = test_case_.level_of(current_refinement_);
    return test_case_.grid()->size(level, 0);
  } // ... current_grid_size(...)

  virtual double current_grid_width() const DS_OVERRIDE DS_FINAL
  {
    assert(current_refinement_ <= num_refinements());
    const int level = test_case_.level_of(current_refinement_);
    const auto grid_part = test_case_.template level< Stuff::Grid::ChoosePartView::part >(level);
    return Fem::GridWidth::calcGridWidth(*grid_part);
  } // ... current_grid_width(...)

  virtual double compute_on_current_refinement() DS_OVERRIDE DS_FINAL
  {
    using namespace Dune;
    using namespace Dune::GDT;
    if (current_refinement_ != last_computed_refinement_) {
      assert(current_refinement_ <= num_refinements());
      // compute solution
      Timer timer;
      current_discretization_
          = Stuff::Common::make_unique< DiscretizationType >(test_case_,
                                                             test_case_.boundary_info(),
                                                             test_case_.problem(),
                                                             test_case_.level_of(current_refinement_));
      current_discretization_->init();
      current_solution_vector_on_level_
          = Stuff::Common::make_unique< VectorType >(current_discretization_->create_vector());
      current_discretization_->solve(*current_solution_vector_on_level_);
      time_to_solution_ = timer.elapsed();
      const ConstDiscreteFunctionType current_refinement_solution(*current_discretization_->ansatz_space(),
                                                                  *current_solution_vector_on_level_,
                                                                  "solution on current level");
      // prolong to reference grid part
      if (!reference_solution_computed_)
        compute_reference_solution();
      const auto reference_grid_view = test_case_.reference_grid_view();
      const Operators::Prolongation< GridViewType > prolongation_operator(*reference_grid_view);
      assert(reference_discretization_);
      if (!current_solution_vector_)
        current_solution_vector_ = Stuff::Common::make_unique< VectorType >(reference_discretization_->create_vector());
      DiscreteFunctionType reference_refinement_solution(*(reference_discretization_->ansatz_space()),
                                                    *current_solution_vector_,
                                                    "solution on reference grid part");
      prolongation_operator.apply(current_refinement_solution, reference_refinement_solution);
      last_computed_refinement_ = current_refinement_;
    }
    return time_to_solution_;
  } // ... compute_on_current_refinement(...)

  virtual double current_error_norm(const std::string type) DS_OVERRIDE DS_FINAL
  {
    // get current solution
    assert(current_refinement_ <= num_refinements());
    if (last_computed_refinement_ != current_refinement_) {
      compute_on_current_refinement();
    }
    assert(last_computed_refinement_ == current_refinement_);
    if (is_norm(type)) {
      assert(current_solution_vector_);
      if (!reference_solution_computed_)
        compute_reference_solution();
      assert(reference_discretization_);
      const ConstDiscreteFunctionType current_solution(*(reference_discretization_->ansatz_space()),
                                                       *current_solution_vector_,
                                                       "current solution");
      // compute error
      if (test_case_.provides_exact_solution()) {
        return compute_norm_(*(test_case_.reference_grid_view()), test_case_.exact_solution() - current_solution, type);
      } else {
        // get reference solution
        compute_reference_solution();
        assert(reference_discretization_);
        assert(reference_solution_vector_);
        const ConstDiscreteFunctionType reference_solution(*(reference_discretization_->ansatz_space()),
                                                           *reference_solution_vector_,
                                                           "reference solution");
        return compute_norm_(*(test_case_.reference_grid_view()), reference_solution- current_solution, type);
      }
    } else {
      assert(current_solution_vector_on_level_);
      return estimate_(*current_solution_vector_on_level_, type);
    }
  } // ... current_error_norm(...)

  virtual void refine() DS_OVERRIDE DS_FINAL
  {
    if (current_refinement_ <= num_refinements())
      ++current_refinement_;
  } // ... refine()

  virtual std::vector< double > expected_results(const std::string type) const = 0;

private:
  void compute_reference_solution()
  {
    if (!reference_solution_computed_) {
      reference_discretization_
          = Stuff::Common::make_unique< DiscretizationType >(test_case_,
                                                             test_case_.boundary_info(),
                                                             test_case_.problem(),
                                                             test_case_.reference_level());
      reference_discretization_->init();
      reference_solution_vector_ = Stuff::Common::make_unique< VectorType >(reference_discretization_->create_vector());
      reference_discretization_->solve(*reference_solution_vector_);
      reference_solution_computed_ = true;
    }
  } // ... compute_reference_solution()

protected:
  bool is_norm(const std::string type) const
  {
    const auto available_norms = available_norms_();
    return std::find(available_norms.begin(), available_norms.end(), type) != available_norms.end();
  } // ... is_norm(...)

private:
  virtual std::vector< std::string > available_norms_() const = 0;

  virtual std::vector< std::string > available_estimators_() const = 0;

  virtual double estimate_(const VectorType& vector, const std::string type) const = 0;

  virtual double compute_norm_(const GridViewType& grid_view,
                               const FunctionType& function,
                               const std::string type) const = 0;

protected:
  const TestCaseType& test_case_;
private:
  size_t current_refinement_;
  size_t last_computed_refinement_;
  double time_to_solution_;
  bool reference_solution_computed_;
protected:
  std::unique_ptr< DiscretizationType > current_discretization_;
private:
  std::unique_ptr< VectorType > current_solution_vector_on_level_;
  std::unique_ptr< DiscretizationType > reference_discretization_;
  std::unique_ptr< VectorType > reference_solution_vector_;
  std::unique_ptr< VectorType > current_solution_vector_;
}; // class EocStudyBase

} // namespace Tests
} // namespace LinearElliptic
} // namespace HDD
} // namespace Dune

#endif // DUNE_HDD_test_case_LINEARELLIPTIC_EOC_STUDY_HH
<commit_msg>[tests.linearelliptic] added MultiscaleEocStudyBase<commit_after>// This file is part of the dune-hdd project:
//   http://users.dune-project.org/projects/dune-hdd
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_HDD_test_case_LINEARELLIPTIC_EOC_STUDY_HH
#define DUNE_HDD_test_case_LINEARELLIPTIC_EOC_STUDY_HH

#include <memory>
#include <vector>
#include <limits>
#include <algorithm>

#include <dune/common/timer.hh>

#if HAVE_DUNE_FEM
# include <dune/fem/misc/gridwidth.hh>
#else
# error "We need dune-fem until we have a reliable and fast method to compute the grid width!"
#endif

#include <dune/stuff/common/memory.hh>
#include <dune/stuff/common/convergence-study.hh>
#include <dune/stuff/grid/layers.hh>

#include <dune/gdt/discretefunction/default.hh>
#include <dune/gdt/operators/prolongations.hh>

namespace Dune {
namespace HDD {
namespace LinearElliptic {
namespace Tests {

/**
 *  Assumes that the DiscretizationImp is derived from Discretizations::ContainerBasedDefault and has a ctor of type
 *  DiscretizationImp(Stuff::Grid::ConstProviderInterface, BoundaryInfoConfig, ProblemType, level).
 *  Assumes that TestCaseType is derived from TestCases::Base and additionally provides
 *  * const Stuff::Common::ConfigTree& boundary_info() const
 *  * const ProblemType& problem() const
 *  * bool provides_exact_solution() const
 *  * const ExactSolutionType& exact_solution() const
 *  and the appropriate types.
 *
 *  Any derived class only has to provide identifier(), provided_norms(), expected_rate(), compute_norm_() and
 *  expected_results().
 */
template< class TestCaseType, class DiscretizationImp >
class EocStudyBase
  : public Stuff::Common::ConvergenceStudy
{
  typedef Stuff::Common::ConvergenceStudy BaseType;
protected:

  typedef DiscretizationImp DiscretizationType;
  typedef typename DiscretizationType::VectorType VectorType;
  typedef typename DiscretizationType::AnsatzSpaceType SpaceType;
  typedef GDT::DiscreteFunction< SpaceType, VectorType >      DiscreteFunctionType;
  typedef GDT::ConstDiscreteFunction< SpaceType, VectorType > ConstDiscreteFunctionType;

  typedef typename TestCaseType::ExactSolutionType ExactSolutionType;
  typedef typename TestCaseType::template Level< Stuff::Grid::ChoosePartView::view >::Type GridViewType;
  typedef typename TestCaseType::FunctionType FunctionType;

public:
  EocStudyBase(const TestCaseType& test_case)
    : test_case_(test_case)
    , current_refinement_(0)
    , last_computed_refinement_(std::numeric_limits< size_t >::max())
    , time_to_solution_(0)
    , reference_solution_computed_(false)
    , current_discretization_(nullptr)
    , current_solution_vector_on_level_(nullptr)
    , reference_discretization_(nullptr)
    , reference_solution_vector_(nullptr)
    , current_solution_vector_(nullptr)
  {
    if (test_case_.problem().parametric())
      DUNE_THROW(NotImplemented, "Parametric problems are not implemented yet!");
  }

  virtual ~EocStudyBase() {}

  virtual size_t num_refinements() const DS_OVERRIDE DS_FINAL
  {
    return test_case_.num_refinements();
  }

  virtual std::vector< std::string > provided_norms() const DS_OVERRIDE DS_FINAL
  {
    std::vector< std::string > ret = available_norms_();
    for (auto estimator : available_estimators_()) {
      if (is_norm(estimator))
        DUNE_THROW(Stuff::Exceptions::internal_error,
                   "We do not want to handle the case that norms and estimators have the same name!");
      ret.push_back(estimator);
    }
    return ret;
  } // ... provided_norms(...)

  virtual double norm_reference_solution(const std::string type) DS_OVERRIDE DS_FINAL
  {
    if (is_norm(type)) {
      if (test_case_.provides_exact_solution()) {
        return compute_norm_(*(test_case_.reference_grid_view()), test_case_.exact_solution(), type);
      } else {
        compute_reference_solution();
        assert(reference_discretization_);
        assert(reference_solution_vector_);
        const ConstDiscreteFunctionType reference_solution(*(reference_discretization_->ansatz_space()),
                                                           *reference_solution_vector_,
                                                           "reference solution");
        return compute_norm_(*(test_case_.reference_grid_view()), reference_solution, type);
      }
    } else
      return 1.0;
  } // ... norm_reference_solution(...)

  virtual size_t current_grid_size() const DS_OVERRIDE DS_FINAL
  {
    assert(current_refinement_ <= num_refinements());
    const int level = test_case_.level_of(current_refinement_);
    return test_case_.grid()->size(level, 0);
  } // ... current_grid_size(...)

  virtual double current_grid_width() const DS_OVERRIDE DS_FINAL
  {
    assert(current_refinement_ <= num_refinements());
    const int level = test_case_.level_of(current_refinement_);
    const auto grid_part = test_case_.template level< Stuff::Grid::ChoosePartView::part >(level);
    return Fem::GridWidth::calcGridWidth(*grid_part);
  } // ... current_grid_width(...)

  virtual double compute_on_current_refinement() DS_OVERRIDE DS_FINAL
  {
    using namespace Dune;
    using namespace Dune::GDT;
    if (current_refinement_ != last_computed_refinement_) {
      assert(current_refinement_ <= num_refinements());
      // compute solution
      Timer timer;
      current_discretization_
          = Stuff::Common::make_unique< DiscretizationType >(test_case_,
                                                             test_case_.boundary_info(),
                                                             test_case_.problem(),
                                                             test_case_.level_of(current_refinement_));
      current_discretization_->init();
      current_solution_vector_on_level_
          = Stuff::Common::make_unique< VectorType >(current_discretization_->create_vector());
      current_discretization_->solve(*current_solution_vector_on_level_);
      time_to_solution_ = timer.elapsed();
      const ConstDiscreteFunctionType current_refinement_solution(*current_discretization_->ansatz_space(),
                                                                  *current_solution_vector_on_level_,
                                                                  "solution on current level");
      // prolong to reference grid part
      if (!reference_solution_computed_)
        compute_reference_solution();
      const auto reference_grid_view = test_case_.reference_grid_view();
      const Operators::Prolongation< GridViewType > prolongation_operator(*reference_grid_view);
      assert(reference_discretization_);
      if (!current_solution_vector_)
        current_solution_vector_ = Stuff::Common::make_unique< VectorType >(reference_discretization_->create_vector());
      DiscreteFunctionType reference_refinement_solution(*(reference_discretization_->ansatz_space()),
                                                    *current_solution_vector_,
                                                    "solution on reference grid part");
      prolongation_operator.apply(current_refinement_solution, reference_refinement_solution);
      last_computed_refinement_ = current_refinement_;
    }
    return time_to_solution_;
  } // ... compute_on_current_refinement(...)

  virtual double current_error_norm(const std::string type) DS_OVERRIDE DS_FINAL
  {
    // get current solution
    assert(current_refinement_ <= num_refinements());
    if (last_computed_refinement_ != current_refinement_) {
      compute_on_current_refinement();
    }
    assert(last_computed_refinement_ == current_refinement_);
    if (is_norm(type)) {
      assert(current_solution_vector_);
      if (!reference_solution_computed_)
        compute_reference_solution();
      assert(reference_discretization_);
      const ConstDiscreteFunctionType current_solution(*(reference_discretization_->ansatz_space()),
                                                       *current_solution_vector_,
                                                       "current solution");
      // compute error
      if (test_case_.provides_exact_solution()) {
        return compute_norm_(*(test_case_.reference_grid_view()), test_case_.exact_solution() - current_solution, type);
      } else {
        // get reference solution
        compute_reference_solution();
        assert(reference_discretization_);
        assert(reference_solution_vector_);
        const ConstDiscreteFunctionType reference_solution(*(reference_discretization_->ansatz_space()),
                                                           *reference_solution_vector_,
                                                           "reference solution");
        return compute_norm_(*(test_case_.reference_grid_view()), reference_solution- current_solution, type);
      }
    } else {
      assert(current_solution_vector_on_level_);
      return estimate_(*current_solution_vector_on_level_, type);
    }
  } // ... current_error_norm(...)

  virtual void refine() DS_OVERRIDE DS_FINAL
  {
    if (current_refinement_ <= num_refinements())
      ++current_refinement_;
  } // ... refine()

  virtual std::vector< double > expected_results(const std::string type) const = 0;

private:
  void compute_reference_solution()
  {
    if (!reference_solution_computed_) {
      reference_discretization_
          = Stuff::Common::make_unique< DiscretizationType >(test_case_,
                                                             test_case_.boundary_info(),
                                                             test_case_.problem(),
                                                             test_case_.reference_level());
      reference_discretization_->init();
      reference_solution_vector_ = Stuff::Common::make_unique< VectorType >(reference_discretization_->create_vector());
      reference_discretization_->solve(*reference_solution_vector_);
      reference_solution_computed_ = true;
    }
  } // ... compute_reference_solution()

protected:
  bool is_norm(const std::string type) const
  {
    const auto available_norms = available_norms_();
    return std::find(available_norms.begin(), available_norms.end(), type) != available_norms.end();
  } // ... is_norm(...)

private:
  virtual std::vector< std::string > available_norms_() const = 0;

  virtual std::vector< std::string > available_estimators_() const = 0;

  virtual double estimate_(const VectorType& vector, const std::string type) const = 0;

  virtual double compute_norm_(const GridViewType& grid_view,
                               const FunctionType& function,
                               const std::string type) const = 0;

protected:
  const TestCaseType& test_case_;
private:
  size_t current_refinement_;
  size_t last_computed_refinement_;
  double time_to_solution_;
  bool reference_solution_computed_;
protected:
  std::unique_ptr< DiscretizationType > current_discretization_;
private:
  std::unique_ptr< VectorType > current_solution_vector_on_level_;
  std::unique_ptr< DiscretizationType > reference_discretization_;
  std::unique_ptr< VectorType > reference_solution_vector_;
  std::unique_ptr< VectorType > current_solution_vector_;
}; // class EocStudyBase

#if HAVE_DUNE_GRID_MULTISCALE

template< class MultiscaleTestCaseType, class DiscretizationImp >
class MultiscaleEocStudyBase
  : public Stuff::Common::ConvergenceStudy
{
  typedef Stuff::Common::ConvergenceStudy BaseType;
protected:

  typedef DiscretizationImp DiscretizationType;
  typedef typename DiscretizationType::VectorType VectorType;
  typedef typename DiscretizationType::AnsatzSpaceType SpaceType;
  typedef GDT::DiscreteFunction< SpaceType, VectorType >      DiscreteFunctionType;
  typedef GDT::ConstDiscreteFunction< SpaceType, VectorType > ConstDiscreteFunctionType;

  typedef typename MultiscaleTestCaseType::ExactSolutionType ExactSolutionType;
  typedef typename DiscretizationType::GridViewType GridViewType;
  typedef typename MultiscaleTestCaseType::FunctionType FunctionType;

public:
  MultiscaleEocStudyBase(const MultiscaleTestCaseType& test_case)
    : test_case_(test_case)
    , current_refinement_(0)
    , last_computed_refinement_(std::numeric_limits< size_t >::max())
    , time_to_solution_(0)
    , reference_solution_computed_(false)
    , current_discretization_(nullptr)
    , current_solution_vector_on_level_(nullptr)
    , reference_discretization_(nullptr)
    , reference_solution_vector_(nullptr)
    , current_solution_vector_(nullptr)
  {
    if (test_case_.problem().parametric())
      DUNE_THROW(NotImplemented, "Parametric problems are not implemented yet!");
  }

  virtual ~MultiscaleEocStudyBase() {}

  virtual size_t num_refinements() const DS_OVERRIDE DS_FINAL
  {
    return test_case_.num_refinements();
  }

  virtual std::vector< std::string > provided_norms() const DS_OVERRIDE DS_FINAL
  {
    std::vector< std::string > ret = available_norms_();
    for (auto estimator : available_estimators_()) {
      if (is_norm(estimator))
        DUNE_THROW(Stuff::Exceptions::internal_error,
                   "We do not want to handle the case that norms and estimators have the same name!");
      ret.push_back(estimator);
    }
    return ret;
  } // ... provided_norms(...)

  virtual double norm_reference_solution(const std::string type) DS_OVERRIDE DS_FINAL
  {
//    if (is_norm(type)) {
//      if (test_case_.provides_exact_solution()) {
//        return compute_norm_(*(test_case_.reference_grid_view()), test_case_.exact_solution(), type);
//      } else {
//        compute_reference_solution();
//        assert(reference_discretization_);
//        assert(reference_solution_vector_);
//        const ConstDiscreteFunctionType reference_solution(*(reference_discretization_->ansatz_space()),
//                                                           *reference_solution_vector_,
//                                                           "reference solution");
//        return compute_norm_(*(test_case_.reference_grid_view()), reference_solution, type);
//      }
//    } else
//      return 1.0;
    DUNE_THROW(NotImplemented, "");
  } // ... norm_reference_solution(...)

  virtual size_t current_grid_size() const DS_OVERRIDE DS_FINAL
  {
    assert(current_refinement_ <= num_refinements());
    const auto grid_part
        = test_case_.level_provider(current_refinement_)->template global< Stuff::Grid::ChoosePartView::part >();
    return grid_part->gridView().size(0);
  } // ... current_grid_size(...)

  virtual double current_grid_width() const DS_OVERRIDE DS_FINAL
  {
    assert(current_refinement_ <= num_refinements());
    const auto grid_part
        = test_case_.level_provider(current_refinement_)->template global< Stuff::Grid::ChoosePartView::part >();
    return Fem::GridWidth::calcGridWidth(*grid_part);
  } // ... current_grid_width(...)

  virtual double compute_on_current_refinement() DS_OVERRIDE DS_FINAL
  {
    using namespace Dune;
    using namespace Dune::GDT;
    if (current_refinement_ != last_computed_refinement_) {
      assert(current_refinement_ <= num_refinements());
      // compute solution
      Timer timer;
      current_discretization_
          = Stuff::Common::make_unique< DiscretizationType >(*(test_case_.level_provider(current_refinement_)),
                                                             test_case_.boundary_info(),
                                                             test_case_.problem());
      current_discretization_->init();
      current_solution_vector_on_level_
          = Stuff::Common::make_unique< VectorType >(current_discretization_->create_vector());
      current_discretization_->solve(*current_solution_vector_on_level_);
      time_to_solution_ = timer.elapsed();
      const ConstDiscreteFunctionType current_refinement_solution(*current_discretization_->ansatz_space(),
                                                                  *current_solution_vector_on_level_,
                                                                  "solution on current level");
      // prolong to reference grid part
      if (!reference_solution_computed_)
        compute_reference_solution();
      assert(reference_discretization_);
      const auto reference_grid_view = test_case_.reference_provider()->template global< Stuff::Grid::ChoosePartView::view >();
      const Operators::Prolongation< GridViewType > prolongation_operator(*reference_grid_view);
      if (!current_solution_vector_)
        current_solution_vector_ = Stuff::Common::make_unique< VectorType >(reference_discretization_->create_vector());
      DiscreteFunctionType reference_refinement_solution(*(reference_discretization_->ansatz_space()),
                                                    *current_solution_vector_,
                                                    "solution on reference grid part");
      prolongation_operator.apply(current_refinement_solution, reference_refinement_solution);
      last_computed_refinement_ = current_refinement_;
    }
    return time_to_solution_;
  } // ... compute_on_current_refinement(...)

  virtual double current_error_norm(const std::string type) DS_OVERRIDE DS_FINAL
  {
    // get current solution
    assert(current_refinement_ <= num_refinements());
    if (last_computed_refinement_ != current_refinement_) {
      compute_on_current_refinement();
    }
    assert(last_computed_refinement_ == current_refinement_);
    if (is_norm(type)) {
      assert(current_solution_vector_);
      if (!reference_solution_computed_)
        compute_reference_solution();
      assert(reference_discretization_);
      const ConstDiscreteFunctionType current_solution(*(reference_discretization_->ansatz_space()),
                                                       *current_solution_vector_,
                                                       "current solution");
      // compute error
      const auto reference_grid_view
          = test_case_.reference_provider()-> template global< Stuff::Grid::ChoosePartView::view >();
      if (test_case_.provides_exact_solution()) {
        return compute_norm_(*reference_grid_view, test_case_.exact_solution() - current_solution, type);
      } else {
        // get reference solution
        compute_reference_solution();
        assert(reference_discretization_);
        assert(reference_solution_vector_);
        const ConstDiscreteFunctionType reference_solution(*(reference_discretization_->ansatz_space()),
                                                           *reference_solution_vector_,
                                                           "reference solution");
        return compute_norm_(*reference_grid_view, reference_solution- current_solution, type);
      }
    } else {
      assert(current_solution_vector_on_level_);
      return estimate_(*current_solution_vector_on_level_, type);
    }
  } // ... current_error_norm(...)

  virtual void refine() DS_OVERRIDE DS_FINAL
  {
    if (current_refinement_ <= num_refinements())
      ++current_refinement_;
  } // ... refine()

  virtual std::vector< double > expected_results(const std::string type) const = 0;

private:
  void compute_reference_solution()
  {
    if (!reference_solution_computed_) {
      reference_discretization_
          = Stuff::Common::make_unique< DiscretizationType >(*(test_case_.reference_provider()),
                                                             test_case_.boundary_info(),
                                                             test_case_.problem());
      reference_discretization_->init();
      reference_solution_vector_ = Stuff::Common::make_unique< VectorType >(reference_discretization_->create_vector());
      reference_discretization_->solve(*reference_solution_vector_);
      reference_solution_computed_ = true;
    }
  } // ... compute_reference_solution()

protected:
  bool is_norm(const std::string type) const
  {
    const auto available_norms = available_norms_();
    return std::find(available_norms.begin(), available_norms.end(), type) != available_norms.end();
  } // ... is_norm(...)

private:
  virtual std::vector< std::string > available_norms_() const = 0;

  virtual std::vector< std::string > available_estimators_() const = 0;

  virtual double estimate_(const VectorType& vector, const std::string type) const = 0;

  virtual double compute_norm_(const GridViewType& grid_view,
                               const FunctionType& function,
                               const std::string type) const = 0;

protected:
  const MultiscaleTestCaseType& test_case_;
private:
  size_t current_refinement_;
  size_t last_computed_refinement_;
  double time_to_solution_;
  bool reference_solution_computed_;
protected:
  std::unique_ptr< DiscretizationType > current_discretization_;
private:
  std::unique_ptr< VectorType > current_solution_vector_on_level_;
  std::unique_ptr< DiscretizationType > reference_discretization_;
  std::unique_ptr< VectorType > reference_solution_vector_;
  std::unique_ptr< VectorType > current_solution_vector_;
}; // class MultiscaleEocStudyBase

#endif // HAVE_DUNE_GRID_MULTISCALE

} // namespace Tests
} // namespace LinearElliptic
} // namespace HDD
} // namespace Dune

#endif // DUNE_HDD_test_case_LINEARELLIPTIC_EOC_STUDY_HH
<|endoftext|>