<commit_before>#include <thread>
#include <future>
#include <mutex>
#include <iostream>
#include <sstream>
#include <fstream>
#include <cmath>
#include <cstdint>
#include <vector>
#include <chrono>

using namespace std;

class Accumulator {
    public:
        void accumulate(char *data) {
            for (int i = 0; i < 1024; i++) {
                double l = (double) data[i];
                sum += l;
                count++;
                if (l > max)
                    max = l;
                if (l < min)
                    min = l;
            }
            data[i] = sum;
        };

        double getAverage() {
            if (count == 0) return 0;
            return sum / count;
        };

        friend Accumulator operator+=(Accumulator &acc1, const Accumulator &acc2) {
            acc1.count += acc2.count;
            acc1.sum += acc2.sum;
            if (acc1.max < acc2.max)
                acc1.max = acc2.max;

            if (acc1.min > acc2.min)
                acc1.min = acc2.min;
            return acc1;
        }

        friend ostream& operator<<(ostream &o, Accumulator &acc) {
            o << "Accumulator average is: " << acc.getAverage() << ".\n"
                << acc.count << " items were counted.\n"
                << acc.min << " was the lowest value.\n"
                << acc.max << " was the highest value.\n";
            return o;
        };
    private:
        int64_t count = 0;
        double sum = 0;
        double min = std::numeric_limits<double>::max();
        double max = 0;
};

void write_hook(ostream *os, char *data) {
    std::cout
        << "This is the default write_hook. "
        << "You will want to overwrite this, "
        << "if you want to use the write_hook. "
        << "Terminating program." << std::endl;
    exit(1);
    return;
}

Accumulator* worker(istream *is, ostream *os,
    Accumulator *shared_acc, int64_t available_bytes, int datasize,
    bool use_shared_acc, bool use_write_hook) {
    static mutex im;
    static mutex om;
    static mutex shared_acc_mutex;
    Accumulator *acc;

    int64_t usable_bytes = (available_bytes / datasize) * datasize;

    char* data = new char[usable_bytes];

    if (use_shared_acc) {
        acc = shared_acc;
    } else {
        acc = new Accumulator;
    }

    bool eof = false;
    while(!eof) {
        int count = 0;
        {
            lock_guard<mutex> lock(im);

            is->read(data, usable_bytes);

            if ( fmod((float)is->gcount(), datasize) != 0.f) {
                std::cerr << "Warning: Data not aligned at finish" << std::endl;
            }
            count = is->gcount() / datasize;

//            std::cout << "Read from buffer: " << count * datasize << " bytes" << std::endl;
            if ( (is->rdstate() & std::ifstream::eofbit ) != 0 ) {
                eof = true;
            }

        }

        {
            if (use_shared_acc) {
                lock_guard<mutex> lock(shared_acc_mutex);
                for (int i = 0; i < count; i++) {
                    acc->accumulate(&data[i * datasize]);
                }
            } else {
                for (int i = 0; i < count; i++) {
                    acc->accumulate(&data[i * datasize]);
                }
            }
        }

        {
            lock_guard<mutex> lock(om);
            if (use_write_hook) {     // using
                for (int i = 0; i < count; i++) {
                    write_hook(os, &data[i * datasize]);
                }
            } else {
                os->write(data, count * datasize);
            }
            os->flush();
//            cout << "Wrote to buffer: " << count * datasize << " bytes" << std::endl;
        }

        if (eof) break;
    }
    return acc;
};

Accumulator run(
    istream &is, ostream &os, int threads,
    bool use_shared_acc, bool use_write_hook,
    int64_t available_megabytes, int datasize
) {
    int64_t available_bytes = available_megabytes * 1024 * 1024;
    int64_t bytes_per_worker = available_bytes / threads;

    std::future<Accumulator*> futures[threads];
    Accumulator acc;

    for (int i = 0; i < threads; i++) {
        std::packaged_task<Accumulator*()> task(std::bind(worker, &is, &os, &acc, bytes_per_worker, datasize, use_shared_acc, use_write_hook)); // wrap the function
        std::future<Accumulator*> future = task.get_future();  // get a future
        std::thread(std::move(task)).detach(); // launch on a thread
        futures[i] = std::move(future);
    }

    for (int i = 0; i < threads; i++) {
        try {
            if (use_shared_acc) {
                futures[i].get();
            } else {
                Accumulator *future_acc = futures[i].get();
                acc += *future_acc;
                delete future_acc;
            }
        }
        catch (exception &e) {
            cout << "Thread " << i << " threw an exception: " << e.what() << endl;;
        }
    }

    return acc;
}

main(int argc, char* argv[]) {
    if(argc < 3) {
        std::cout << "Please supply number of threads, and input file." << std::endl;
        return 0;
    }

    string in = argv[2];
    string out = "out.dat";
    if (argc > 3) out = argv[3];

    ifstream is(in,  ios::in  | ios::binary);
    ofstream os(out, ios::out | ios::binary | ios::trunc);

    if (!is.good()) {
        cout << "Could not open input file. Exiting." << endl;
        exit(1);
    }
    if (!os.good()) {
        cout << "Could not open output file. Exiting." << endl;
        exit(1);
    }

    int64_t filesize = 1024*1024*1024;
    filesize = filesize * 1;

    std::cout << "Reading data into buffer" << std::endl;
    vector<char> chars(filesize);           // init vector array
    is.read(&chars[0], filesize);           // read data into vector array
    std::string str(&chars[0], filesize);   // create string from vector array
    std::istringstream iss(str);            // create istringstream from string
    std::ostringstream oss;                 // create empty ostringstream

    int threads = stoi(argv[1]);            // number of threads to use
    bool use_shared_acc = false;            // use a shared accumulator
    bool use_write_hook = true;            // utilize the write hook function
    int available_megabytes = 500;          // available megabytes on system
    int datasize = 1024;                    // bytes per calculation unit

    std::cout << "Starting NBUF" << std::endl;
    std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
    Accumulator acc = run(iss, oss, threads, use_shared_acc, use_write_hook, available_megabytes, datasize);
    std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
    std::cout << "Stopping NBUF" << std::endl;

    auto duration =  std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();

    std::cout << "Time taken: " << duration << " us" << std::endl;

    os << oss.str();
    cout << acc;

    return 0;
}<commit_msg>nbuf works<commit_after>#include <thread>
#include <future>
#include <mutex>
#include <iostream>
#include <sstream>
#include <fstream>
#include <cmath>
#include <cstdint>
#include <vector>
#include <chrono>

using namespace std;

class Accumulator {
    public:
        void accumulate(char *data) {
            for (int i = 0; i < 1024; i++) {
                double l = (double) data[i];
                sum += l;
                count++;
                if (l > max)
                    max = l;
                if (l < min)
                    min = l;
            }
            int acc = 0;
        };

        double getAverage() {
            if (count == 0) return 0;
            return sum / count;
        };

        friend Accumulator operator+=(Accumulator &acc1, const Accumulator &acc2) {
            acc1.count += acc2.count;
            acc1.sum += acc2.sum;
            if (acc1.max < acc2.max)
                acc1.max = acc2.max;

            if (acc1.min > acc2.min)
                acc1.min = acc2.min;
            return acc1;
        }

        friend ostream& operator<<(ostream &o, Accumulator &acc) {
            o << "Accumulator average is: " << acc.getAverage() << std::endl
                << acc.count << " items were counted." << std::endl
                << acc.min << " was the lowest value." << std::endl
                << acc.max << " was the highest value.";
            return o;
        };

    private:
        int64_t count = 0;
        double sum = 0;
        double min = std::numeric_limits<double>::max();
        double max = 0;
};

class VirtualOutputFilter {
    public:
        virtual void output_filter(ostream *os, char *data) {
            std::cout
                << "This is the default output filter. "
                << "You will want to overwrite this, "
                << "if you want to use the output filter. "
                << "Terminating program." << std::endl;
            exit(1);
            return;
        };
};

class nbuf {
    public:
        Accumulator run(
            istream &is, ostream &os, int threads,
            bool use_shared_acc, bool use_output_filter, VirtualOutputFilter *filter,
            int64_t available_megabytes, int datasize
        ) {
            int64_t available_bytes = available_megabytes * 1024 * 1024;
            int64_t bytes_per_worker = available_bytes / threads;

            std::future<Accumulator*> futures[threads];
            Accumulator acc;

            for (int i = 0; i < threads; i++) {
                std::packaged_task<Accumulator*()> task(
                    std::bind(&nbuf::worker,
                        &is, &os, &acc, bytes_per_worker, datasize,
                        use_shared_acc, use_output_filter, filter)); // wrap the function

                std::future<Accumulator*> future = task.get_future();  // get a future
                std::thread(std::move(task)).detach(); // launch on a thread
                futures[i] = std::move(future);
            }

            for (int i = 0; i < threads; i++) {
                try {
                    if (use_shared_acc) {
                        futures[i].get();
                    } else {
                        Accumulator *future_acc = futures[i].get();
                        acc += *future_acc;
                        delete future_acc;
                    }
                }
                catch (exception &e) {
                    cout << "Thread " << i << " threw an exception: " << e.what() << endl;;
                }
            }

            return acc;
        };

        static Accumulator* worker(istream *is, ostream *os,
            Accumulator *shared_acc, int64_t available_bytes, int datasize,
            bool use_shared_acc, bool use_output_filter, VirtualOutputFilter *filter) {
            static mutex im;
            static mutex om;
            static mutex shared_acc_mutex;
            Accumulator *acc;

            int64_t usable_bytes = (available_bytes / datasize) * datasize;

            char* data = new char[usable_bytes];

            if (use_shared_acc) {
                acc = shared_acc;
            } else {
                acc = new Accumulator;
            }

            bool eof = false;
            while(!eof) {
                int count = 0;
                {
                    lock_guard<mutex> lock(im);

                    is->read(data, usable_bytes);

                    if ( fmod((float)is->gcount(), datasize) != 0.f) {
                        std::cerr << "Warning: Data not aligned at finish" << std::endl;
                    }
                    count = is->gcount() / datasize;

        //            std::cout << "Read from buffer: " << count * datasize << " bytes" << std::endl;
                    if ( (is->rdstate() & std::ifstream::eofbit ) != 0 ) {
                        eof = true;
                    }

                }

                {
                    if (use_shared_acc) {
                        lock_guard<mutex> lock(shared_acc_mutex);
                        for (int i = 0; i < count; i++) {
                            acc->accumulate(&data[i * datasize]);
                        }
                    } else {
                        for (int i = 0; i < count; i++) {
                            acc->accumulate(&data[i * datasize]);
                        }
                    }
                }

                {
                    lock_guard<mutex> lock(om);
                    if (use_output_filter) {     // using write_hook
                        for (int i = 0; i < count; i++) {
                            filter->output_filter(os, &data[i * datasize]);
                        }
                    } else {
                        os->write(data, count * datasize);
                    }
                    os->flush();
        //            cout << "Wrote to buffer: " << count * datasize << " bytes" << std::endl;
                }

                if (eof) break;
            }

            return acc;
        };
};

main(int argc, char* argv[]) {
    if(argc < 3) {
        std::cout << "Please supply number of threads, and input file." << std::endl;
        return 0;
    }

    string in = argv[2];
    string out = "out.dat";
    if (argc > 3) out = argv[3];

    ifstream is(in,  ios::in  | ios::binary);
    ofstream os(out, ios::out | ios::binary | ios::trunc);

    if (!is.good()) {
        cout << "Could not open input file. Exiting." << endl;
        exit(1);
    }
    if (!os.good()) {
        cout << "Could not open output file. Exiting." << endl;
        exit(1);
    }

    int64_t filesize = 1024*1024*1024;
    filesize = filesize * 1;

    std::cout << "Reading data into buffer" << std::endl;
    vector<char> chars(filesize);                 // init vector array
    is.read(&chars[0], filesize);                 // read data into vector array
    std::string str(&chars[0], filesize);         // create string from vector array
    std::istringstream iss(str);                  // create istringstream from string
    std::ostringstream oss;                       // create empty ostringstream

    // SETUP nbuf
    int threads = stoi(argv[1]);                  // number of threads to use
    bool use_shared_acc = false;                  // use a shared accumulator
    bool use_output_filter = false;               // use an output filter
    VirtualOutputFilter *filter = (VirtualOutputFilter*) nullptr; // use an output filter
    int available_megabytes = 500;                // available megabytes on system
    int datasize = 1024;                          // bytes per calculation unit

    std::cout << "Starting nbuf" << std::endl;
    std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();

    // RUNNING nbuf
    nbuf nbuf;
    Accumulator acc = nbuf.run(iss, oss, threads, use_shared_acc, use_output_filter, filter, available_megabytes, datasize);

    std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
    std::cout << "Stopping nbuf" << std::endl;
    auto duration =  std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();
    std::cout << "Time taken: " << duration << " us" << std::endl;

//    skip writing output
//    os << oss.str();
    cout << acc << endl;

    return 0;
}<|endoftext|>


<commit_before>#ifndef STATEMACHINE_STATE_HPP
#define STATEMACHINE_STATE_HPP

#include <statemachine_fwd.hpp>
#include <stringref.hpp>

#include <cassert>
#include <iterator>

namespace statemachine
{
namespace detail
{

//! \brief A state in a state machine.
//!
//! The State describes a state in a finite state machine.
template <typename TOptions>
class State
{
public:
    using state_machine_type = StateMachine<TOptions>;
    using transition_type = Transition<TOptions>;

    //! \brief The possible child modes.
    //!
    //! This enum lists the possible child modes.
    //! - Exclusive: The children are active exclusively (i.e. one and only
    //!   one child will be active).
    //! - Parallel: The children are active parallely (i.e. all children
    //!   will be active simultanously).
    enum ChildMode
    {
        Exclusive,
        Parallel
    };

    template <bool TIsConst>
    class TransitionIterator;

    //! The iterator type for iterating over transitions.
    typedef TransitionIterator<false> transition_iterator;
    //! The const-iterator type for iterating over transitions.
    typedef TransitionIterator<true> const_transition_iterator;

    //! \brief Constructs a state.
    //!
    //! Constructs a state with given \p name which will be a child of the
    //! \p parent state. The \p parent may be a null-pointer. In this case
    //! the state is at the root of its hierarchy.
    explicit State(const char* name, State* parent = 0);

    State(const State&) = delete;
    State& operator=(const State&) = delete;

    //! \brief Returns the child mode.
    //!
    //! Returns the current child mode. The default is Exclusive.
    ChildMode childMode() const
    {
        return m_childMode;
    }

    transition_iterator beginTransitions()
    {
        return transition_iterator(m_transitions);
    }

    const_transition_iterator beginTransitions() const
    {
        return const_transition_iterator(m_transitions);
    }

    const_transition_iterator cbeginTransitions() const
    {
        return const_transition_iterator(m_transitions);
    }

    transition_iterator endTransitions()
    {
        return transition_iterator();
    }

    const_transition_iterator endTransitions() const
    {
        return const_transition_iterator();
    }

    const_transition_iterator cendTransitions() const
    {
        return const_transition_iterator();
    }

    State* findChild(StringRef name) const;

    //! \brief Checks if the state is active.
    //!
    //! Returns \p true, if the state is active, which means that it belongs
    //! to the current state machine configuration.
    bool isActive() const;

    //! \brief Checks for atomicity.
    //!
    //! Returns \p true, if this state is atomic which means that it does not
    //! have children.
    bool isAtomic() const
    {
        return m_children == 0;
    }

    //! \brief Checks for a compound state.
    //!
    //! Returns \p true, if this state is a compound state, i.e. it does
    //! have at least one child and the children are active exclusively.
    //! One and only one child of an active compound state will be active.
    bool isCompound() const
    {
        return !isAtomic() && m_childMode == Exclusive;
    }

    //! \brief Checks for a parallel state.
    //!
    //! Returns \p true, if this state is a parallel state, i.e. it does
    //! have at least one child and the children are active in parallel.
    //! All children of an active parallel state will be active.
    bool isParallel() const
    {
        return !isAtomic() && m_childMode == Parallel;
    }

    //! \brief The name.
    //!
    //! Returns the state's name.
    const char* name() const
    {
        return m_name;
    }

    //! \brief The on-entry method.
    //!
    //! This method is called by the state machine, whenever this state
    //! is entered. The event which triggered the configuration change
    //! is passed in \p event.
    virtual void onEntry(unsigned /*event*/)
    {
        // The default implementation does nothing.
    }

    //! \brief The on-exit method.
    //!
    //! This method is called by the state machine, when the staet is left.
    //! The event which triggered the configuration change is passed in
    //! \p event.
    virtual void onExit(unsigned /*event*/)
    {
        // The default implementation does nothing.
    }

    virtual void enterInvoke()
    {
        // The default implementation does nothing.
    }

    virtual void exitInvoke()
    {
        // The default implementation does nothing.
    }

    //! \brief The parent.
    //!
    //! Returns the state's parent or a null-pointer, if the state has no
    //! parent.
    State* parent() const
    {
        return m_parent;
    }

    //! \brief Sets the child mode.
    //!
    //! Sets the child mode to \p mode. Setting the child mode to Exclusive,
    //! will turn the state into a compound state. When the child mode is
    //! set to Parallel, this state will become a parallel state.
    //!
    //! \note The state machine's configuration won't be updated, if the child
    //! mode of one of its states changes. Changing the child mode while
    //! the associated state machine is running, results in undefined
    //! behaviour.
    void setChildMode(ChildMode mode)
    {
        m_childMode = mode;
    }

    //! \brief Changes the parent.
    //!
    //! Removes this child from its old parent and makes it a child of the
    //! new \p parent state. If \p parent is a null-pointer, this state will
    //! be at the root of its hieararchy.
    //!
    //! \note Changing the parent state while the associated state machine
    //! is running results in undefined behaviour.
    void setParent(State* parent);

    //! \brief Returns the state machine.
    //!
    //! Returns the state machine to which this state belongs. If the state
    //! has not been added to a state machine, yet, a null-pointer is
    //! returned.
    state_machine_type* stateMachine() const
    {
        return m_stateMachine;
    }

    // -------------------------------------------------------------------------
    // Iterators
    // -------------------------------------------------------------------------

    //! \brief An iterator over a state's transitions.
    template <bool TIsConst>
    class TransitionIterator
    {
    public:
        typedef std::ptrdiff_t difference_type;
        typedef transition_type value_type;
        typedef typename std::conditional<TIsConst, const transition_type*,
                                          transition_type*>::type pointer;
        typedef typename std::conditional<TIsConst, const transition_type&,
                                          transition_type&>::type reference;
        typedef std::forward_iterator_tag iterator_category;

        //! Default constructs an end-iterator.
        TransitionIterator()
            : m_current(0)
        {
        }

        //! A copy-constructor with implicit conversion from a non-const
        //! iterator.
        TransitionIterator(const TransitionIterator<false>& other)
            : m_current(other.m_current)
        {
        }

        //! Prefix increment.
        TransitionIterator& operator++()
        {
            m_current = m_current->m_nextInSourceState;
            return *this;
        }

        //! Postfix increment.
        TransitionIterator operator++ (int)
        {
            TransitionIterator temp(m_current);
            m_current = m_current->m_next;
            return temp;
        }

        //! Returns \p true, if this iterator is equal to the \p other iterator.
        bool operator== (TransitionIterator other) const
        {
            return m_current == other.m_current;
        }

        //! Returns \p true, if this iterator is not equal to the \p other
        //! iterator.
        bool operator!= (TransitionIterator other) const
        {
            return m_current != other.m_current;
        }

        //! Returns a reference to the transition.
        reference operator* () const
        {
            return *m_current;
        }

        //! Returns a pointer to the transition.
        pointer operator-> () const
        {
            return m_current;
        }

    private:
        //! The current transition.
        pointer m_current;

        //! Constructs an iterator pointing to the \p transition.
        TransitionIterator(pointer transition)
            : m_current(transition)
        {
        }

        friend class State;
        // Befriend the non-const version with the const version.
        friend TransitionIterator<true>;
    };

private:
    enum Flags
    {
        SkipTransitionSelection = 0x01,
        InEnterSet              = 0x02,
        InExitSet               = 0x04
    };

    //! The state's name.
    const char* m_name;
    //! The parent state.
    State* m_parent;
    //! The associated state machine.
    state_machine_type* m_stateMachine;
    //! A pointer to the first child.
    State* m_children;
    //! A pointer to the next sibling in the linked list.
    State* m_nextSibling;
    //! A pointer to the first transition.
    transition_type* m_transitions;
    //! This flag specifies if the children are active exclusively or parallely.
    ChildMode m_childMode;
    int m_flags; //! \todo This should be of type Flags

    bool m_internalActive;
    bool m_visibleActive;

    //! Adds a \p child.
    void addChild(State* child);
    //! Removes a \p child.
    void removeChild(State* child);

    //! Adds a \p transition.
    void pushBackTransition(transition_type* transition) noexcept;

    friend state_machine_type;

    template <typename TDerived>
    friend class EventDispatcherBase;
};

template <typename TOptions>
State<TOptions>::State(const char* name, State* parent)
    : m_name(name),
      m_parent(parent),
      m_stateMachine(parent ? parent->m_stateMachine : 0),
      m_children(0),
      m_nextSibling(0),
      m_transitions(0),
      m_childMode(Exclusive),
      m_internalActive(false),
      m_visibleActive(false)
{
    if (parent)
        parent->addChild(this);
}

template <typename TOptions>
State<TOptions>* State<TOptions>::findChild(StringRef name) const
{
#if 0
    const State* parent = this;
    while (1)
    {
        std::pair<StringRef, StringRef> splitName = name.split('.');
        if (splitName.first.empty())
            return 0;

        const_child_iterator child = parent->child_begin();
        for (; child != parent->child_end(); ++child)
        {
            if (child->name() == splitName.first)
                break;
        }
        if (child == parent->child_end())
            return 0;
        if (splitName.second.empty())
            return const_cast<State*>(&*child);

        parent = &*child;
        name = splitName.second;
    }
#endif
    return 0;
}

template <typename TOptions>
bool State<TOptions>::isActive() const
{
    if (m_stateMachine)
    {
        // TODO:
        //m_stateMachine->m_configurationChangeMutex.lock();
        bool active = m_visibleActive;
        //m_stateMachine->m_configurationChangeMutex.unlock();
        return active;
    }
    else
    {
        assert(!m_visibleActive);
        return false;
    }
}

template <typename TOptions>
void State<TOptions>::setParent(State* parent)
{
    if (parent == m_parent)
        return;

    if (m_parent)
        m_parent->removeChild(this);
    if (parent)
        parent->addChild(this);

    // Propagate the state machine of the new parent to the new child states.
    state_machine_type* newFsm = parent ? parent->stateMachine() : 0;
    state_machine_type* fsm = newFsm
                              ? newFsm
                              : (m_parent ? m_parent->stateMachine() : 0);
    if (fsm)
    {
        for (auto iter = fsm->subtree_begin(this),
              end_iter = fsm->subtree_end(this);
             iter != end_iter; ++iter)
        {
            iter->m_stateMachine = newFsm;
        }
    }

    m_parent = parent;
}

// ----=====================================================================----
//     Private methods
// ----=====================================================================----

template <typename TOptions>
void State<TOptions>::addChild(State* child)
{
    assert(child->m_nextSibling == 0);

    if (!m_children)
    {
        m_children = child;
    }
    else
    {
        State* iter = m_children;
        while (iter->m_nextSibling)
            iter = iter->m_nextSibling;
        iter->m_nextSibling = child;
    }
}

template <typename TOptions>
void State<TOptions>::removeChild(State* child)
{
    assert(m_children != 0);

    if (child == m_children)
        m_children = child->m_nextSibling;
    else
    {
        State* iter = m_children;
        while (1)
        {
            assert(iter != 0);
            if (iter->m_nextSibling == child)
            {
                iter->m_nextSibling = child->m_nextSibling;
                break;
            }
            iter = iter->m_nextSibling;
        }
    }
    child->m_nextSibling = 0;
}

template <typename TOptions>
void State<TOptions>::pushBackTransition(transition_type* transition) noexcept
{
    if (!m_transitions)
    {
        m_transitions = transition;
    }
    else
    {
        transition_type* iter = m_transitions;
        while (iter->m_nextInSourceState)
            iter = iter->m_nextInSourceState;
        iter->m_nextInSourceState = transition;
    }
}

#if 0
const State* findLeastCommonAncestor(const State* state1, const State* state2);

//! \brief Checks if a state is an ancestor of another state.
//!
//! Returns \p true, if \p ancestor is an ancestor of \p descendant. Every
//! state is its own ancestor.
bool isAncestor(const State* ancestor, const State* descendant);

inline
bool isDescendant(const State* descendant, const State* ancestor)
{
    return isAncestor(ancestor, descendant);
}

inline
bool isProperAncestor(const State* ancestor, const State* descendant)
{
    return isAncestor(ancestor, descendant->parent());
}
#endif

} // namespace detail
} // namespace statemachine

#endif // STATEMACHINE_STATE_HPP
<commit_msg>Querying the state's active flag does not lock the state machine anymore.<commit_after>#ifndef FSM11_STATE_HPP
#define FSM11_STATE_HPP

#include <statemachine_fwd.hpp>
#include <stringref.hpp>

#include <atomic>
#include <cassert>
#include <iterator>

namespace fsm11
{
namespace detail
{

//! \brief A state in a state machine.
//!
//! The State describes a state in a finite state machine.
template <typename TOptions>
class State
{
public:
    using event_type = typename TOptions::event_type;
    using state_machine_type = StateMachine<TOptions>;
    using transition_type = Transition<TOptions>;

    //! \brief The possible child modes.
    //!
    //! This enum lists the possible child modes.
    //! - Exclusive: The children are active exclusively (i.e. one and only
    //!   one child will be active).
    //! - Parallel: The children are active parallely (i.e. all children
    //!   will be active simultanously).
    enum ChildMode
    {
        Exclusive,
        Parallel
    };

    template <bool TIsConst>
    class TransitionIterator;

    //! The iterator type for iterating over transitions.
    typedef TransitionIterator<false> transition_iterator;
    //! The const-iterator type for iterating over transitions.
    typedef TransitionIterator<true> const_transition_iterator;

    //! \brief Constructs a state.
    //!
    //! Constructs a state with given \p name which will be a child of the
    //! \p parent state. The \p parent may be a null-pointer. In this case
    //! the state is at the root of its hierarchy.
    explicit State(const char* name, State* parent = 0);

    State(const State&) = delete;
    State& operator=(const State&) = delete;

    //! \brief Returns the child mode.
    //!
    //! Returns the current child mode. The default is Exclusive.
    ChildMode childMode() const
    {
        return m_childMode;
    }

    transition_iterator beginTransitions()
    {
        return transition_iterator(m_transitions);
    }

    const_transition_iterator beginTransitions() const
    {
        return const_transition_iterator(m_transitions);
    }

    const_transition_iterator cbeginTransitions() const
    {
        return const_transition_iterator(m_transitions);
    }

    transition_iterator endTransitions()
    {
        return transition_iterator();
    }

    const_transition_iterator endTransitions() const
    {
        return const_transition_iterator();
    }

    const_transition_iterator cendTransitions() const
    {
        return const_transition_iterator();
    }

    State* findChild(StringRef name) const;

    //! \brief Checks if the state is active.
    //!
    //! Returns \p true, if the state is active, which means that it belongs
    //! to the current state machine configuration.
    bool isActive() const;

    //! \brief Checks for atomicity.
    //!
    //! Returns \p true, if this state is atomic which means that it does not
    //! have children.
    bool isAtomic() const
    {
        return m_children == 0;
    }

    //! \brief Checks for a compound state.
    //!
    //! Returns \p true, if this state is a compound state, i.e. it does
    //! have at least one child and the children are active exclusively.
    //! One and only one child of an active compound state will be active.
    bool isCompound() const
    {
        return !isAtomic() && m_childMode == Exclusive;
    }

    //! \brief Checks for a parallel state.
    //!
    //! Returns \p true, if this state is a parallel state, i.e. it does
    //! have at least one child and the children are active in parallel.
    //! All children of an active parallel state will be active.
    bool isParallel() const
    {
        return !isAtomic() && m_childMode == Parallel;
    }

    //! \brief The name.
    //!
    //! Returns the state's name.
    const char* name() const
    {
        return m_name;
    }

    //! \brief The on-entry method.
    //!
    //! This method is called by the state machine, whenever this state
    //! is entered. The event which triggered the configuration change
    //! is passed in \p event.
    virtual void onEntry(event_type /*event*/)
    {
        // The default implementation does nothing.
    }

    //! \brief The on-exit method.
    //!
    //! This method is called by the state machine, when the staet is left.
    //! The event which triggered the configuration change is passed in
    //! \p event.
    virtual void onExit(event_type /*event*/)
    {
        // The default implementation does nothing.
    }

    virtual void enterInvoke()
    {
        // The default implementation does nothing.
    }

    virtual void exitInvoke()
    {
        // The default implementation does nothing.
    }

    //! \brief The parent.
    //!
    //! Returns the state's parent or a null-pointer, if the state has no
    //! parent.
    State* parent() const
    {
        return m_parent;
    }

    //! \brief Sets the child mode.
    //!
    //! Sets the child mode to \p mode. Setting the child mode to Exclusive,
    //! will turn the state into a compound state. When the child mode is
    //! set to Parallel, this state will become a parallel state.
    //!
    //! \note The state machine's configuration won't be updated, if the child
    //! mode of one of its states changes. Changing the child mode while
    //! the associated state machine is running, results in undefined
    //! behaviour.
    void setChildMode(ChildMode mode)
    {
        m_childMode = mode;
    }

    //! \brief Changes the parent.
    //!
    //! Removes this child from its old parent and makes it a child of the
    //! new \p parent state. If \p parent is a null-pointer, this state will
    //! be at the root of its hieararchy.
    //!
    //! \note Changing the parent state while the associated state machine
    //! is running results in undefined behaviour.
    void setParent(State* parent);

    //! \brief Returns the state machine.
    //!
    //! Returns the state machine to which this state belongs. If the state
    //! has not been added to a state machine, yet, a null-pointer is
    //! returned.
    state_machine_type* stateMachine() const
    {
        return m_stateMachine;
    }

    // -------------------------------------------------------------------------
    // Iterators
    // -------------------------------------------------------------------------

    //! \brief An iterator over a state's transitions.
    template <bool TIsConst>
    class TransitionIterator
    {
    public:
        typedef std::ptrdiff_t difference_type;
        typedef transition_type value_type;
        typedef typename std::conditional<TIsConst, const transition_type*,
                                          transition_type*>::type pointer;
        typedef typename std::conditional<TIsConst, const transition_type&,
                                          transition_type&>::type reference;
        typedef std::forward_iterator_tag iterator_category;

        //! Default constructs an end-iterator.
        TransitionIterator()
            : m_current(0)
        {
        }

        //! A copy-constructor with implicit conversion from a non-const
        //! iterator.
        TransitionIterator(const TransitionIterator<false>& other)
            : m_current(other.m_current)
        {
        }

        //! Prefix increment.
        TransitionIterator& operator++()
        {
            m_current = m_current->m_nextInSourceState;
            return *this;
        }

        //! Postfix increment.
        TransitionIterator operator++ (int)
        {
            TransitionIterator temp(m_current);
            m_current = m_current->m_next;
            return temp;
        }

        //! Returns \p true, if this iterator is equal to the \p other iterator.
        bool operator== (TransitionIterator other) const
        {
            return m_current == other.m_current;
        }

        //! Returns \p true, if this iterator is not equal to the \p other
        //! iterator.
        bool operator!= (TransitionIterator other) const
        {
            return m_current != other.m_current;
        }

        //! Returns a reference to the transition.
        reference operator* () const
        {
            return *m_current;
        }

        //! Returns a pointer to the transition.
        pointer operator-> () const
        {
            return m_current;
        }

    private:
        //! The current transition.
        pointer m_current;

        //! Constructs an iterator pointing to the \p transition.
        TransitionIterator(pointer transition)
            : m_current(transition)
        {
        }

        friend class State;
        // Befriend the non-const version with the const version.
        friend TransitionIterator<true>;
    };

private:
    enum Flags
    {
        SkipTransitionSelection = 0x01,
        InEnterSet              = 0x02,
        InExitSet               = 0x04
    };

    //! The state's name.
    const char* m_name;
    //! The associated state machine.
    state_machine_type* m_stateMachine;
    //! The parent state.
    State* m_parent;
    //! A pointer to the first child.
    State* m_children;
    //! A pointer to the next sibling in the linked list.
    State* m_nextSibling;
    //! A pointer to the first transition.
    transition_type* m_transitions;
    //! This flag specifies if the children are active exclusively or parallely.
    ChildMode m_childMode;
    int m_flags; //! \todo This should be of type Flags

    bool m_internalActive;
    std::atomic_bool m_visibleActive;

    //! Adds a \p child.
    void addChild(State* child);
    //! Removes a \p child.
    void removeChild(State* child);

    //! Adds a \p transition.
    void pushBackTransition(transition_type* transition) noexcept;

    friend state_machine_type;

    template <typename TDerived>
    friend class EventDispatcherBase;
};

template <typename TOptions>
State<TOptions>::State(const char* name, State* parent)
    : m_name(name),
      m_stateMachine(parent ? parent->m_stateMachine : 0),
      m_parent(parent),
      m_children(0),
      m_nextSibling(0),
      m_transitions(0),
      m_childMode(Exclusive),
      m_internalActive(false),
      m_visibleActive(false)
{
    if (parent)
        parent->addChild(this);
}

template <typename TOptions>
State<TOptions>* State<TOptions>::findChild(StringRef name) const
{
#if 0
    const State* parent = this;
    while (1)
    {
        std::pair<StringRef, StringRef> splitName = name.split('.');
        if (splitName.first.empty())
            return 0;

        const_child_iterator child = parent->child_begin();
        for (; child != parent->child_end(); ++child)
        {
            if (child->name() == splitName.first)
                break;
        }
        if (child == parent->child_end())
            return 0;
        if (splitName.second.empty())
            return const_cast<State*>(&*child);

        parent = &*child;
        name = splitName.second;
    }
#endif
    return 0;
}

template <typename TOptions>
bool State<TOptions>::isActive() const
{
    return m_visibleActive;
}

template <typename TOptions>
void State<TOptions>::setParent(State* parent)
{
    if (parent == m_parent)
        return;

    if (m_parent)
        m_parent->removeChild(this);
    if (parent)
        parent->addChild(this);

    // Propagate the state machine of the new parent to the new child states.
    state_machine_type* newFsm = parent ? parent->stateMachine() : 0;
    state_machine_type* fsm = newFsm
                              ? newFsm
                              : (m_parent ? m_parent->stateMachine() : 0);
    if (fsm)
    {
        for (auto iter = fsm->subtree_begin(this),
              end_iter = fsm->subtree_end(this);
             iter != end_iter; ++iter)
        {
            iter->m_stateMachine = newFsm;
        }
    }

    m_parent = parent;
}

// ----=====================================================================----
//     Private methods
// ----=====================================================================----

template <typename TOptions>
void State<TOptions>::addChild(State* child)
{
    assert(child->m_nextSibling == 0);

    if (!m_children)
    {
        m_children = child;
    }
    else
    {
        State* iter = m_children;
        while (iter->m_nextSibling)
            iter = iter->m_nextSibling;
        iter->m_nextSibling = child;
    }
}

template <typename TOptions>
void State<TOptions>::removeChild(State* child)
{
    assert(m_children != 0);

    if (child == m_children)
        m_children = child->m_nextSibling;
    else
    {
        State* iter = m_children;
        while (1)
        {
            assert(iter != 0);
            if (iter->m_nextSibling == child)
            {
                iter->m_nextSibling = child->m_nextSibling;
                break;
            }
            iter = iter->m_nextSibling;
        }
    }
    child->m_nextSibling = 0;
}

template <typename TOptions>
void State<TOptions>::pushBackTransition(transition_type* transition) noexcept
{
    if (!m_transitions)
    {
        m_transitions = transition;
    }
    else
    {
        transition_type* iter = m_transitions;
        while (iter->m_nextInSourceState)
            iter = iter->m_nextInSourceState;
        iter->m_nextInSourceState = transition;
    }
}

#if 0
const State* findLeastCommonAncestor(const State* state1, const State* state2);

//! \brief Checks if a state is an ancestor of another state.
//!
//! Returns \p true, if \p ancestor is an ancestor of \p descendant. Every
//! state is its own ancestor.
bool isAncestor(const State* ancestor, const State* descendant);

inline
bool isDescendant(const State* descendant, const State* ancestor)
{
    return isAncestor(ancestor, descendant);
}

inline
bool isProperAncestor(const State* ancestor, const State* descendant)
{
    return isAncestor(ancestor, descendant->parent());
}
#endif

} // namespace detail
} // namespace fsm11

#endif // FSM11_STATE_HPP
<|endoftext|>


<commit_before>/**
 * @file commander.cpp
 *
 * Definition of the set of functions handling sending commands to the pixhawk.
 *
 * @author Adrien Perkins <adrienp@stanford.edu>
 */

// Standard includes
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <cmath>
#include <string.h>
#include <inttypes.h>
#include <fstream>
#include <vector>
#include <sys/time.h>

// Serial includes
#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#
#ifdef __linux
#include <sys/ioctl.h>
#endif

#include "libs/serial/mavlink_serial.h"
#include "common.h"
#include "commander.h"

// include what is needed ofr  the POMDP commands
#include "planner/pomdp.h"

using std::string;
using std::vector;
using namespace std;

/** rotation handling for DF antenna */
bool second_rotation_required = true;

void send_next_command(uint8_t &prev_state, uint8_t &new_state) {

	LOG_STATUS("[COMMANDER] the previous state was: %i\n", prev_state);

	vector<float> commands;
	float d_north = 0.0;
	float d_east = 0.0;
	float yaw_angle = 270.0;
	float alt = common::flight_alt;
	switch (prev_state) {
		case TRACKING_HUNT_STATE_OFF:
		case TRACKING_HUNT_STATE_START:
		case TRACKING_HUNT_STATE_ROTATE:
			// rotating = false;	// NO LONGER NEEDED

			// if running emily config, will need to rotate twice
			if (common::emily && second_rotation_required) {
				send_df_mode(1);
				common::pixhawk->send_rotate_command(-1.0);
				second_rotation_required = false;
				break;
			}

			// get next command from the current planner
			commands = common::planner->action();
			LOG_STATUS("[COMMANDER] planner command received with length %d", commands.size());

			// check to make sure the commands have enough arguments
			if (commands.size() < 2) {
				LOG_ERROR("[COMMANDER] invalid command received from planner");
				common::pixhawk->send_finish_command();
				return;
			}

			if (commands.size() >= 2) {
				d_north = commands[0];
				d_east = commands[1];
			}

			if (commands.size() >= 3) {
				yaw_angle = commands[2];
			}

			// get the altitude, but not always set
			if (commands.size() > 3 && commands[3] > 0.0) {
				alt = commands[3];
			}

			LOG_DEBUG("[COMMANDER] following tracking command (%f, %f)", d_north, d_east);

			// check to see if rotating again or moving
			if (d_north == 0 && d_east == 0) {
				common::pixhawk->send_rotate_command(-1.0);
			} else {
				common::pixhawk->send_tracking_command(d_north, d_east, yaw_angle, alt);
			}

			if (d_north == 1000.0 || d_north == -1000.0) {
				LOG_STATUS("[COMMANDER] sending finish command\n");
				common::pixhawk->send_finish_command();
				return;
			}
			break;

		case TRACKING_HUNT_STATE_MOVE:
			// moving = false;		// NO LONGER NEEDED

			if (common::emily) {
				// make sure in "normal" mode of operation
				send_df_mode(0);
			}

			// send a rotate command
			common::pixhawk->send_rotate_command(-1.0);

			// management for emily config
			second_rotation_required = true;
			break;

	}

	return;
}

void send_df_mode(int mode) {

	if (mode == 1) {
		write(common::df_arduino->fd, "1", 1);
	} else {
		write(common::df_arduino->fd, "0", 1);
	}
}
<commit_msg>fix error on sending finish command<commit_after>/**
 * @file commander.cpp
 *
 * Definition of the set of functions handling sending commands to the pixhawk.
 *
 * @author Adrien Perkins <adrienp@stanford.edu>
 */

// Standard includes
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <cmath>
#include <string.h>
#include <inttypes.h>
#include <fstream>
#include <vector>
#include <sys/time.h>

// Serial includes
#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

#ifdef __linux
#include <sys/ioctl.h>
#endif

#include "libs/serial/mavlink_serial.h"
#include "common.h"
#include "commander.h"

// include what is needed ofr  the POMDP commands
#include "planner/pomdp.h"

using std::string;
using std::vector;
using namespace std;

/** rotation handling for DF antenna */
bool second_rotation_required = true;

void send_next_command(uint8_t &prev_state, uint8_t &new_state) {

	LOG_STATUS("[COMMANDER] the previous state was: %i\n", prev_state);

	vector<float> commands;
	float d_north = 0.0;
	float d_east = 0.0;
	float yaw_angle = 270.0;
	float alt = common::flight_alt;
	switch (prev_state) {
		case TRACKING_HUNT_STATE_OFF:
		case TRACKING_HUNT_STATE_START:
		case TRACKING_HUNT_STATE_ROTATE:
			// rotating = false;	// NO LONGER NEEDED

			// if running emily config, will need to rotate twice
			if (common::emily && second_rotation_required) {
				send_df_mode(1);
				common::pixhawk->send_rotate_command(-1.0);
				second_rotation_required = false;
				break;
			}

			// get next command from the current planner
			commands = common::planner->action();
			LOG_STATUS("[COMMANDER] planner command received with length %d", commands.size());

			// check to make sure the commands have enough arguments
			if (commands.size() < 2) {
				LOG_ERROR("[COMMANDER] invalid command received from planner");
				common::pixhawk->send_finish_command();
				return;
			}

			if (commands.size() >= 2) {
				d_north = commands[0];
				d_east = commands[1];
			}

			if (commands.size() >= 3) {
				yaw_angle = commands[2];
			}

			// get the altitude, but not always set
			if (commands.size() > 3 && commands[3] > 0.0) {
				alt = commands[3];
			}

			LOG_DEBUG("[COMMANDER] following tracking command (%f, %f)", d_north, d_east);

			// check to see if rotating again or moving
			if (d_north == 0 && d_east == 0) {
				common::pixhawk->send_rotate_command(-1.0);
			} else if (d_north >= 999.0 || d_north <= -999.0) {
				LOG_STATUS("[COMMANDER] sending finish command\n");
				common::pixhawk->send_finish_command();
			} else {
				common::pixhawk->send_tracking_command(d_north, d_east, yaw_angle, alt);
			}

			break;

		case TRACKING_HUNT_STATE_MOVE:
			// moving = false;		// NO LONGER NEEDED

			if (common::emily) {
				// make sure in "normal" mode of operation
				send_df_mode(0);
			}

			// send a rotate command
			common::pixhawk->send_rotate_command(-1.0);

			// management for emily config
			second_rotation_required = true;
			break;

	}

	return;
}

void send_df_mode(int mode) {

	if (mode == 1) {
		write(common::df_arduino->fd, "1", 1);
	} else {
		write(common::df_arduino->fd, "0", 1);
	}
}
<|endoftext|>


<commit_before>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include <list>
#include <map>
#include <set>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>

#include "log.h"

NEXTPNR_NAMESPACE_BEGIN

std::vector<FILE *> log_files;
std::vector<std::ostream *> log_streams;
FILE *log_errfile = NULL;
log_write_type log_write_function = nullptr;

bool log_error_stderr = false;
bool log_cmd_error_throw = false;
bool log_quiet_warnings = false;
std::string log_last_error;
void (*log_error_atexit)() = NULL;

// static bool next_print_log = false;
static int log_newline_count = 0;

std::string vstringf(const char *fmt, va_list ap)
{
    std::string string;
    char *str = NULL;

#ifdef _WIN32
    int sz = 64 + strlen(fmt), rc;
    while (1) {
        va_list apc;
        va_copy(apc, ap);
        str = (char *)realloc(str, sz);
        rc = vsnprintf(str, sz, fmt, apc);
        va_end(apc);
        if (rc >= 0 && rc < sz)
            break;
        sz *= 2;
    }
#else
    if (vasprintf(&str, fmt, ap) < 0)
        str = NULL;
#endif

    if (str != NULL) {
        string = str;
        free(str);
    }

    return string;
}

void logv(const char *format, va_list ap)
{
    //
    // Trim newlines from the beginning
    while (format[0] == '\n' && format[1] != 0) {
        log_always("\n");
        format++;
    }

    std::string str = vstringf(format, ap);

    if (str.empty())
        return;

    size_t nnl_pos = str.find_last_not_of('\n');
    if (nnl_pos == std::string::npos)
        log_newline_count += str.size();
    else
        log_newline_count = str.size() - nnl_pos - 1;

    for (auto f : log_files)
        fputs(str.c_str(), f);

    for (auto f : log_streams)
        *f << str;
    if (log_write_function)
        log_write_function(str);
}

void logv_info(const char *format, va_list ap)
{
    std::string message = vstringf(format, ap);

    log_always("Info: %s", message.c_str());
    log_flush();
}

void logv_warning(const char *format, va_list ap)
{
    std::string message = vstringf(format, ap);

    log_always("Warning: %s", message.c_str());
    log_flush();
}

void logv_warning_noprefix(const char *format, va_list ap)
{
    std::string message = vstringf(format, ap);

    log_always("%s", message.c_str());
}

void logv_error(const char *format, va_list ap)
{
#ifdef EMSCRIPTEN
    auto backup_log_files = log_files;
#endif

    if (log_errfile != NULL)
        log_files.push_back(log_errfile);

    if (log_error_stderr)
        for (auto &f : log_files)
            if (f == stdout)
                f = stderr;

    log_last_error = vstringf(format, ap);
    log_always("ERROR: %s", log_last_error.c_str());
    log_flush();

    if (log_error_atexit)
        log_error_atexit();

#ifdef EMSCRIPTEN
    log_files = backup_log_files;
#endif
    throw log_execution_error_exception();
}

void log_always(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);
    logv(format, ap);
    va_end(ap);
}

void log(const char *format, ...)
{
    if (log_quiet_warnings) return;
    va_list ap;
    va_start(ap, format);
    logv(format, ap);
    va_end(ap);
}

void log_info(const char *format, ...)
{
    if (log_quiet_warnings) return;
    va_list ap;
    va_start(ap, format);
    logv_info(format, ap);
    va_end(ap);
}

void log_warning(const char *format, ...)
{
    if (log_quiet_warnings) return;
    va_list ap;
    va_start(ap, format);
    logv_warning(format, ap);
    va_end(ap);
}

void log_warning_noprefix(const char *format, ...)
{
    if (log_quiet_warnings) return;
    va_list ap;
    va_start(ap, format);
    logv_warning_noprefix(format, ap);
    va_end(ap);
}

void log_error(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);
    logv_error(format, ap);
}

void log_cmd_error(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);

    if (log_cmd_error_throw) {
        log_last_error = vstringf(format, ap);
        log_always("ERROR: %s", log_last_error.c_str());
        log_flush();
        throw log_cmd_error_exception();
    }

    logv_error(format, ap);
}

void log_break()
{
    if (log_quiet_warnings) return;
    if (log_newline_count < 2)
        log_always("\n");
    if (log_newline_count < 2)
        log_always("\n");
}

void log_flush()
{
    for (auto f : log_files)
        fflush(f);

    for (auto f : log_streams)
        f->flush();
}

NEXTPNR_NAMESPACE_END
<commit_msg>Fix compile warning<commit_after>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include <list>
#include <map>
#include <set>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>

#include "log.h"

NEXTPNR_NAMESPACE_BEGIN

NPNR_NORETURN void logv_error(const char *format, va_list ap) NPNR_ATTRIBUTE(noreturn);

std::vector<FILE *> log_files;
std::vector<std::ostream *> log_streams;
FILE *log_errfile = NULL;
log_write_type log_write_function = nullptr;

bool log_error_stderr = false;
bool log_cmd_error_throw = false;
bool log_quiet_warnings = false;
std::string log_last_error;
void (*log_error_atexit)() = NULL;

// static bool next_print_log = false;
static int log_newline_count = 0;

std::string vstringf(const char *fmt, va_list ap)
{
    std::string string;
    char *str = NULL;

#ifdef _WIN32
    int sz = 64 + strlen(fmt), rc;
    while (1) {
        va_list apc;
        va_copy(apc, ap);
        str = (char *)realloc(str, sz);
        rc = vsnprintf(str, sz, fmt, apc);
        va_end(apc);
        if (rc >= 0 && rc < sz)
            break;
        sz *= 2;
    }
#else
    if (vasprintf(&str, fmt, ap) < 0)
        str = NULL;
#endif

    if (str != NULL) {
        string = str;
        free(str);
    }

    return string;
}

void logv(const char *format, va_list ap)
{
    //
    // Trim newlines from the beginning
    while (format[0] == '\n' && format[1] != 0) {
        log_always("\n");
        format++;
    }

    std::string str = vstringf(format, ap);

    if (str.empty())
        return;

    size_t nnl_pos = str.find_last_not_of('\n');
    if (nnl_pos == std::string::npos)
        log_newline_count += str.size();
    else
        log_newline_count = str.size() - nnl_pos - 1;

    for (auto f : log_files)
        fputs(str.c_str(), f);

    for (auto f : log_streams)
        *f << str;
    if (log_write_function)
        log_write_function(str);
}

void logv_info(const char *format, va_list ap)
{
    std::string message = vstringf(format, ap);

    log_always("Info: %s", message.c_str());
    log_flush();
}

void logv_warning(const char *format, va_list ap)
{
    std::string message = vstringf(format, ap);

    log_always("Warning: %s", message.c_str());
    log_flush();
}

void logv_warning_noprefix(const char *format, va_list ap)
{
    std::string message = vstringf(format, ap);

    log_always("%s", message.c_str());
}

void logv_error(const char *format, va_list ap)
{
#ifdef EMSCRIPTEN
    auto backup_log_files = log_files;
#endif

    if (log_errfile != NULL)
        log_files.push_back(log_errfile);

    if (log_error_stderr)
        for (auto &f : log_files)
            if (f == stdout)
                f = stderr;

    log_last_error = vstringf(format, ap);
    log_always("ERROR: %s", log_last_error.c_str());
    log_flush();

    if (log_error_atexit)
        log_error_atexit();

#ifdef EMSCRIPTEN
    log_files = backup_log_files;
#endif
    throw log_execution_error_exception();
}

void log_always(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);
    logv(format, ap);
    va_end(ap);
}

void log(const char *format, ...)
{
    if (log_quiet_warnings) return;
    va_list ap;
    va_start(ap, format);
    logv(format, ap);
    va_end(ap);
}

void log_info(const char *format, ...)
{
    if (log_quiet_warnings) return;
    va_list ap;
    va_start(ap, format);
    logv_info(format, ap);
    va_end(ap);
}

void log_warning(const char *format, ...)
{
    if (log_quiet_warnings) return;
    va_list ap;
    va_start(ap, format);
    logv_warning(format, ap);
    va_end(ap);
}

void log_warning_noprefix(const char *format, ...)
{
    if (log_quiet_warnings) return;
    va_list ap;
    va_start(ap, format);
    logv_warning_noprefix(format, ap);
    va_end(ap);
}

void log_error(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);
    logv_error(format, ap);
}

void log_cmd_error(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);

    if (log_cmd_error_throw) {
        log_last_error = vstringf(format, ap);
        log_always("ERROR: %s", log_last_error.c_str());
        log_flush();
        throw log_cmd_error_exception();
    }

    logv_error(format, ap);
}

void log_break()
{
    if (log_quiet_warnings) return;
    if (log_newline_count < 2)
        log_always("\n");
    if (log_newline_count < 2)
        log_always("\n");
}

void log_flush()
{
    for (auto f : log_files)
        fflush(f);

    for (auto f : log_streams)
        f->flush();
}

NEXTPNR_NAMESPACE_END
<|endoftext|>


<commit_before>#include <string>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include "pongcolor.h"
#include "sysio.h"

#ifdef POSIX
#include <termios.h>
#endif
#ifdef LINUX_GPIO_RPI
#include <wiringPi.h>
#endif

using std::string;
using pong::PColor;
using pong::Rect;
using pong::PRect;

namespace pong { namespace sys
{
	void SOut::GotoPos(int x, int y)
	{
		#ifdef POSIX
		printf("\033[%d;%df", y, x);
		fflush(stdout);
		#endif
	}

	void SOut::GotoPos(Point pos)
	{
		GotoPos(pos.GetXpos(), pos.GetYpos());
	}

	void SOut::PrintColorString(string str, PColor colornum)
	{
		#ifdef POSIX
		printf("\033[%dm%s\033[0m", colornum.GetNum(), str.c_str());
		#endif
	}

	SOut& SOut::Clear(void)
	{
		#ifdef POSIX
		system("clear");
		#endif

		return *this;
	}

	int SOut::GetLength(void)
	{
		return 100;
	}

	int SOut::GetWidth(void)
	{
		return 40;
	}

	SOut& SOut::EraseWrite(PRect drect, PRect wrect)
	{
		static SOut sout;
		drect.SetColor(PColor::BLACK);

		sout << drect << wrect;

		return *this;
	}

	SOut& SOut::operator<<(PRect rect)
	{
		for(int width=0; width<rect.GetWidth(); width++)
		{
			GotoPos((rect.GetSpoint()).GetXpos(), (rect.GetSpoint()).GetYpos() + width);

			for(int length=0; length<rect.GetLength(); length++)
			{
				PrintColorString("█", rect.GetColor());
			}
		}

		return *this;
	}

	SOut& SOut::operator<<(PString str)
	{
		GotoPos(str.GetSpoint());
		PrintColorString(str.GetString(), str.GetColor());

		return *this;
	}

	void SIn::ClearBuf(void)
	{
		while (getchar() != EOF);
	}

	void SIn::operator>>(int& target)
	{
		#ifdef POSIX
		target = getchar();
		// ClearBuf();
		#endif
	}

	SIn::SIn(void)
	{
		// empty
	}

	SIn::~SIn()
	{

		// empty
	}

	SInInitial::SInInitial(void)
	{
		#ifdef POSIX
		regulartset = new struct termios;
		newtset = new struct termios;

		tcgetattr(0, regulartset);
		*newtset = *regulartset;
		(*newtset).c_lflag &= ~ICANON;
		(*newtset).c_lflag &= ~ECHO;
		(*newtset).c_cc[VTIME] = 0;
		(*newtset).c_cc[VMIN] = 0;

		tcsetattr(0, TCSANOW, newtset);
		#endif
	}

	SInInitial::~SInInitial()
	{
		#ifdef POSIX
		tcsetattr(0, TCSANOW, regulartset);

		delete regulartset;
		delete newtset;
		#endif
	}

	SCurrent& SCurrent::DelayMsec(long msec)
	{
		#ifdef POSIX
		static struct timespec tim;
		static int ini = 0;

		if (ini == 0)
		{
			tim.tv_sec = 0;
			tim.tv_nsec = (msec * 1000000L);
		}

		nanosleep(&tim, NULL);
		#endif

		return *this;
	}

	bool SCurrent::CycleTick(int cyclenum)
	{
		static int cycount = 0;

		if (cycount == 0)
		{
			cycount++;
			return true;
		}
		else
		{
			cycount++;
		}

		if (cycount >= cyclenum)
			cycount = 0;

		return false;
	}
}}
<commit_msg>Move fflush(stdout) to PrintColorString<commit_after>#include <string>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include "pongcolor.h"
#include "sysio.h"

#ifdef POSIX
#include <termios.h>
#endif
#ifdef LINUX_GPIO_RPI
#include <wiringPi.h>
#endif

using std::string;
using pong::PColor;
using pong::Rect;
using pong::PRect;

namespace pong { namespace sys
{
	void SOut::GotoPos(int x, int y)
	{
		#ifdef POSIX
		printf("\033[%d;%df", y, x);
		#endif
	}

	void SOut::GotoPos(Point pos)
	{
		GotoPos(pos.GetXpos(), pos.GetYpos());
	}

	void SOut::PrintColorString(string str, PColor colornum)
	{
		#ifdef POSIX
		printf("\033[%dm%s\033[0m", colornum.GetNum(), str.c_str());
		fflush(stdout);
		#endif
	}

	SOut& SOut::Clear(void)
	{
		#ifdef POSIX
		system("clear");
		#endif

		return *this;
	}

	int SOut::GetLength(void)
	{
		return 100;
	}

	int SOut::GetWidth(void)
	{
		return 40;
	}

	SOut& SOut::EraseWrite(PRect drect, PRect wrect)
	{
		static SOut sout;
		drect.SetColor(PColor::BLACK);

		sout << drect << wrect;

		return *this;
	}

	SOut& SOut::operator<<(PRect rect)
	{
		for(int width=0; width<rect.GetWidth(); width++)
		{
			GotoPos((rect.GetSpoint()).GetXpos(), (rect.GetSpoint()).GetYpos() + width);

			for(int length=0; length<rect.GetLength(); length++)
			{
				PrintColorString("█", rect.GetColor());
			}
		}

		return *this;
	}

	SOut& SOut::operator<<(PString str)
	{
		GotoPos(str.GetSpoint());
		PrintColorString(str.GetString(), str.GetColor());

		return *this;
	}

	void SIn::ClearBuf(void)
	{
		while (getchar() != EOF);
	}

	void SIn::operator>>(int& target)
	{
		#ifdef POSIX
		target = getchar();
		// ClearBuf();
		#endif
	}

	SIn::SIn(void)
	{
		// empty
	}

	SIn::~SIn()
	{

		// empty
	}

	SInInitial::SInInitial(void)
	{
		#ifdef POSIX
		regulartset = new struct termios;
		newtset = new struct termios;

		tcgetattr(0, regulartset);
		*newtset = *regulartset;
		(*newtset).c_lflag &= ~ICANON;
		(*newtset).c_lflag &= ~ECHO;
		(*newtset).c_cc[VTIME] = 0;
		(*newtset).c_cc[VMIN] = 0;

		tcsetattr(0, TCSANOW, newtset);
		#endif
	}

	SInInitial::~SInInitial()
	{
		#ifdef POSIX
		tcsetattr(0, TCSANOW, regulartset);

		delete regulartset;
		delete newtset;
		#endif
	}

	SCurrent& SCurrent::DelayMsec(long msec)
	{
		#ifdef POSIX
		static struct timespec tim;
		static int ini = 0;

		if (ini == 0)
		{
			tim.tv_sec = 0;
			tim.tv_nsec = (msec * 1000000L);
		}

		nanosleep(&tim, NULL);
		#endif

		return *this;
	}

	bool SCurrent::CycleTick(int cyclenum)
	{
		static int cycount = 0;

		if (cycount == 0)
		{
			cycount++;
			return true;
		}
		else
		{
			cycount++;
		}

		if (cycount >= cyclenum)
			cycount = 0;

		return false;
	}
}}
<|endoftext|>


<commit_before>
#include <deal.II/base/logstream.h>
#include <deal.II/base/tensor.h>

#include "command_line.h"

#include <fstream>
#include <iostream>

/**
 * This is an example class that makes very little sense here. @note
 * The convention is dim, rank, ValueType, ...
 */
template <int dim, typename ValueType = double>
class Step0
{
public:

  /**
   * Constructor.
   */
  Step0 ();

  /**
   * Destructor.
   */
  ~Step0 ();

  /**
   * Run the problem.
   */
  void run ();

  /**
   * Read in file from the command line.
   */
  nil::CommandLine command_line;

private:

  /**
   * Distribute coefficients on to the first-order
   * piezoelectric tensor.
   */
  void distribute_first_order_piezoelectric_coefficients (const std::list<ValueType> coefficients);

  /**
   * Distribute coefficients on to the second-order
   * piezoelectric tensor.
   */
  void distribute_second_order_piezoelectric_coefficients (const std::list<ValueType> coefficients);

  /**
   * A tensor holding the first order piezoelectric constants.
   */
  dealii::Tensor<2, dim> first_order_piezoelectric;

  /**
   * A tensor holding the first order mechanical strain.
   */
  dealii::Tensor<2, dim> first_order_strain;

  /**
   * A list of first-order piezoelectric coefficients.
   */
  std::list<ValueType> first_order_piezoelectric_coefficients;

  /**
   * A list of second-order piezoelectric coefficients.
   */
  std::list<ValueType> second_order_piezoelectric_coefficients;

};

template <int dim, typename ValueType>
Step0<dim, ValueType>::Step0 ()
{}

template <int dim, typename ValueType>
Step0<dim, ValueType>::~Step0 ()
{}

template <int dim, typename ValueType>
void
Step0<dim, ValueType>::distribute_first_order_piezoelectric_coefficients
(const std::list<ValueType> coefficients)
{
  AssertThrow (coefficients.size ()!=0,
	       dealii::ExcMessage ("The number of coefficients can not be zero."));

  // At this point we are interested in zinc-blende structure only,
  // hence:
  AssertThrow (coefficients.size ()==0,
	       dealii::ExcMessage ("The number of coefficients does not match the number required for zinc-blende structure."));
}

template <int dim, typename ValueType>
void
Step0<dim, ValueType>::distribute_second_order_piezoelectric_coefficients
(const std::list<ValueType> coefficients)
{
  AssertThrow (coefficients.size ()!=0,
	       dealii::ExcMessage ("The number of coefficients can not be zero."));

  // At this point we are interested in zinc-blende structure only,
  // hence:
  AssertThrow (coefficients.size ()==0,
	       dealii::ExcMessage ("The number of coefficients does not match the number required for zinc-blende structure."));
}

template <int dim, typename ValueType>
void
Step0<dim, ValueType>::run ()
{
  // First up, fill the piezoelectric tensors with coefficent
  // values. Starting with first-order coefficients...
  distribute_first_order_piezoelectric_coefficients (first_order_piezoelectric_coefficients);

  // and then second-order coefficients.
  distribute_second_order_piezoelectric_coefficients (second_order_piezoelectric_coefficients);
}

int main (int argc, char **argv)
{

  try
    {
      // Set deal.II's logger depth.
      dealii::deallog.depth_console (0);

      // Initialise the problem.
      Step0<3, double> problem;

      // Parse the command line and input file.
      problem.command_line.parse_command_line (argc, argv);

      // Run the problem.
      problem.run ();
    }

  // ...and if this should fail, try to gather as much information as
  // possible. Specifically, if the exception that was thrown is an
  // object of a class that is derived from the C++ standard class
  // exception.
  catch (std::exception &exc)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Exception on processing: " << std::endl
                << exc.what() << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;

      return 1;
    }

  // If the exception that was thrown somewhere was not an object of a
  // class derived from the standard exception class,
  // then nothing cane be done at all - simply print an error message
  // and exit.
  catch (...)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Unknown exception!" << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;
      return 1;
    }

  // At this point, the application performed as was expected - return
  // without error.
  return 0;
}
<commit_msg>Add a setup function.<commit_after>
#include <deal.II/base/logstream.h>
#include <deal.II/base/tensor.h>

#include "command_line.h"

#include <fstream>
#include <iostream>

/**
 * This is an example class that makes very little sense here. @note
 * The convention is dim, rank, ValueType, ...
 */
template <int dim, typename ValueType = double>
class Step0
{
public:

  /**
   * Constructor.
   */
  Step0 ();

  /**
   * Destructor.
   */
  ~Step0 ();

  /**
   * Run the problem.
   */
  void run ();

  /**
   * Read in file from the command line.
   */
  nil::CommandLine command_line;

private:

  /**
   * Initialise all tensors used in this problem.
   */
  void setup_problem ();

  /**
   * Distribute coefficients on to the first-order
   * piezoelectric tensor.
   */
  void distribute_first_order_piezoelectric_coefficients (const std::list<ValueType> coefficients);

  /**
   * Distribute coefficients on to the second-order
   * piezoelectric tensor.
   */
  void distribute_second_order_piezoelectric_coefficients (const std::list<ValueType> coefficients);

  /**
   * A tensor holding the first-order piezoelectric constants.
   */
  dealii::Tensor<2, dim> first_order_piezoelectric;

  /**
   * A tensor holding the second-order piezoelectric constants.
   */
  dealii::Tensor<2, dim> second_order_piezoelectric;

  /**
   * A tensor holding the first order mechanical strain.
   */
  dealii::Tensor<2, dim> first_order_strain;

  /**
   * A list of first-order piezoelectric coefficients.
   */
  std::list<ValueType> first_order_piezoelectric_coefficients;

  /**
   * A list of second-order piezoelectric coefficients.
   */
  std::list<ValueType> second_order_piezoelectric_coefficients;

};

template <int dim, typename ValueType>
Step0<dim, ValueType>::Step0 ()
{}

template <int dim, typename ValueType>
Step0<dim, ValueType>::~Step0 ()
{}

template <int dim, typename ValueType>
void
Step0<dim, ValueType>::setup_problem ()
{
  // Initialise the first- and second-order piezoelectric tensors...
  first_order_piezoelectric.reinit ();
  second_order_piezoelectric.reinit ();

  // and then the strain tensor.
  first_order_strain.reinit ();
}

template <int dim, typename ValueType>
void
Step0<dim, ValueType>::distribute_first_order_piezoelectric_coefficients
(const std::list<ValueType> coefficients)
{
  AssertThrow (coefficients.size ()!=0,
	       dealii::ExcMessage ("The number of coefficients can not be zero."));

  // At this point we are interested in zinc-blende structure only,
  // hence:
  AssertThrow (coefficients.size ()==0,
	       dealii::ExcMessage ("The number of coefficients does not match the number required for zinc-blende structure."));

  // Then distribute the coefficients on to the tensor.
  // for (unsigned int i=0; i<dim; ++i)

}

template <int dim, typename ValueType>
void
Step0<dim, ValueType>::distribute_second_order_piezoelectric_coefficients
(const std::list<ValueType> coefficients)
{
  AssertThrow (coefficients.size ()!=0,
	       dealii::ExcMessage ("The number of coefficients can not be zero."));

  // At this point we are interested in zinc-blende structure only,
  // hence:
  AssertThrow (coefficients.size ()==0,
	       dealii::ExcMessage ("The number of coefficients does not match the number required for zinc-blende structure."));
}

template <int dim, typename ValueType>
void
Step0<dim, ValueType>::run ()
{
  // First up, fill the piezoelectric tensors with coefficent
  // values. Starting with first-order coefficients...
  distribute_first_order_piezoelectric_coefficients (first_order_piezoelectric_coefficients);

  // and then second-order coefficients.
  distribute_second_order_piezoelectric_coefficients (second_order_piezoelectric_coefficients);

  // Having done that now we want to start applying an incremental
  // strain pattern

}

int main (int argc, char **argv)
{

  try
    {
      // Set deal.II's logger depth.
      dealii::deallog.depth_console (0);

      // Initialise the problem.
      Step0<3, double> problem;

      // Parse the command line and input file.
      problem.command_line.parse_command_line (argc, argv);

      // Run the problem.
      problem.run ();
    }

  // ...and if this should fail, try to gather as much information as
  // possible. Specifically, if the exception that was thrown is an
  // object of a class that is derived from the C++ standard class
  // exception.
  catch (std::exception &exc)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Exception on processing: " << std::endl
                << exc.what() << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;

      return 1;
    }

  // If the exception that was thrown somewhere was not an object of a
  // class derived from the standard exception class,
  // then nothing cane be done at all - simply print an error message
  // and exit.
  catch (...)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Unknown exception!" << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;
      return 1;
    }

  // At this point, the application performed as was expected - return
  // without error.
  return 0;
}
<|endoftext|>


<commit_before>// -------------------------------------------------------------------
// @author Toby D. Young
//
// Copyright 2014 nil authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the following
//    disclaimer in the documentation and/or other materials provided
//    with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE NAMEPSACE EWALENA AUTHORS ``AS
// IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// NAMESPACE EWALENA AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and
// documentation are those of the authors and should not be
// interpreted as representing official policies, either expressed or
// implied, of the namespace ewalena authors.
// -------------------------------------------------------------------

// deal.II headers
#include <deal.II/base/logstream.h>
#include <deal.II/base/parameter_handler.h>
#include <deal.II/base/tensor.h>
#include <deal.II/base/table_handler.h>

// Library-based headers.
#include "group_symmetry.h"
#include "piezoelectric_tensor.h"

// Application-base headers.
#include "command_line.h"

#include <fstream>
#include <iostream>

template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType = double>
class Step0
{
public:

  // First, are the usual class constructors and destructors.
  Step0 ();
  ~Step0 ();

  void run ();

  // Coefficients are held in a parameter file, so it will be
  // necessary to read in a file from the command line.
  nil::CommandLine command_line;

private:

  // First is a list of functions that belong to this class (they are
  // explained later on).
  void get_parameters ();
  void setup_system ();

  void output_results () const;

  // Following that we have a list of the tensors that will be used in
  // this calculation. They are, first- and second-order piezoelectric
  // tensors
  nil::PiezoelectricTensor<GroupSymm, 1, ValueType> first_order_piezoelectric_tensor;
  nil::PiezoelectricTensor<GroupSymm, 2, ValueType> second_order_piezoelectric_tensor;

  // Additionally, lists of coefficients are needed for those tensors
  // that are tensors of empirical moduli
  std::vector<ValueType> first_order_piezoelectric_coefficients;
  std::vector<ValueType> second_order_piezoelectric_coefficients;

  // as well as a list of the size of the Bravais lattice in the
  // relaxed configuration
  std::vector<ValueType> bravais_lattice;

  // as well as the main object of interest, the polarisation vector.
  dealii::Tensor<1, 3, ValueType> polarisation_tensor;

  // Then we need an object to hold various run-time parameters that
  // are specified in an "prm file".
  dealii::ParameterHandler parameters;

  // and finally, a table to handle the results.
  dealii::TableHandler output_table;
};

// The constructor is typically borning...
template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
Step0<dim, GroupSymm, ValueType>::Step0 ()
{}

// as is the destructor.
template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
Step0<dim, GroupSymm, ValueType>::~Step0 ()
{}

// The first step is to obtain a complete list of the coefficients
// needed for this calculation. First comes a declaration of the
// entries expected to be find in the parameter file and then they are
// read into the object parameters.
template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
void
Step0<dim, GroupSymm, ValueType>::get_parameters ()
{
  // First declare the parameters that are expected to be found.
  parameters.declare_entry ("First-order piezoelectric coefficients",
			    "-0.230",
			    dealii::Patterns::List (dealii::Patterns::Double (), 1),
			    "A list of the first-order piezoelectric coefficients. "
			    "Default is zinc-blende GaAs. "
			    "See: PRL 96, 187602 (2006). ");

  parameters.declare_entry ("Second-order piezoelectric coefficients",
			    "-0.439, -3.765, -0.492",
			    dealii::Patterns::List (dealii::Patterns::Double (), 1),
			    "A list of the second-order piezoelectric coefficients. "
			    "Default is zinc-blende GaAs. "
			    "See: PRL 96, 187602 (2006). ");

  parameters.declare_entry ("Bravais lattice dimensions",
			    "1., 1., 1.",
			    dealii::Patterns::List (dealii::Patterns::Double (), 1),
			    "A list of the Bravais lattice dimensions. ");

  parameters.read_input (command_line.get_prm_file ());

  first_order_piezoelectric_coefficients =
    dealii::Utilities::string_to_double
    (dealii::Utilities::split_string_list (parameters.get ("First-order piezoelectric coefficients")));

  second_order_piezoelectric_coefficients =
    dealii::Utilities::string_to_double
    (dealii::Utilities::split_string_list (parameters.get ("Second-order piezoelectric coefficients")));

  bravais_lattice =
    dealii::Utilities::string_to_double
    (dealii::Utilities::split_string_list (parameters.get ("Bravais lattice dimensions")));

  // Some checks
  AssertThrow (bravais_lattice.size ()==3,
	       dealii::ExcMessage ("The Bravais lattice is required to have three components."));

}

// Next initialise all of the objects we are going to use.
template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
void
Step0<dim, GroupSymm, ValueType>::setup_system ()
{
  // Initialise the first- and second-order piezoelectric tensors...
  first_order_piezoelectric_tensor.reinit ();
  second_order_piezoelectric_tensor.reinit ();

  // and distribute the coefficients.
  first_order_piezoelectric_tensor.distribute_coefficients (first_order_piezoelectric_coefficients);
  second_order_piezoelectric_tensor.distribute_coefficients (second_order_piezoelectric_coefficients);
}

// This is the run function, which wraps all of the above into a
// single logical routine.
template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
void
Step0<dim, GroupSymm, ValueType>::run ()
{

  // First find the parameters need for this calculation
  get_parameters ();

}

int main (int argc, char **argv)
{

  try
    {
      // Set deal.II's logger depth.
      dealii::deallog.depth_console (0);

      // Initialise the problem, 3d wurtzite.
      Step0<3, nil::GroupSymmetry::Wurtzite> problem;

      // Parse the command line and input file.
      problem.command_line.parse_command_line (argc, argv);

      // Run the problem.
      problem.run ();
    }

  // ...and if this should fail, try to gather as much information as
  // possible. Specifically, if the exception that was thrown is an
  // object of a class that is derived from the C++ standard class
  // exception.
  catch (std::exception &exc)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Exception on processing: " << std::endl
                << exc.what() << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;

      return 1;
    }

  // If the exception that was thrown somewhere was not an object of a
  // class derived from the standard exception class,
  // then nothing cane be done at all - simply print an error message
  // and exit.
  catch (...)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Unknown exception!" << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;
      return 1;
    }

  // At this point, the application performed as was expected - return
  // without error.
  return 0;
}
<commit_msg>Create triangulation.<commit_after>// -------------------------------------------------------------------
// @author Toby D. Young
//
// Copyright 2014 nil authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the following
//    disclaimer in the documentation and/or other materials provided
//    with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE NAMEPSACE EWALENA AUTHORS ``AS
// IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// NAMESPACE EWALENA AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and
// documentation are those of the authors and should not be
// interpreted as representing official policies, either expressed or
// implied, of the namespace ewalena authors.
// -------------------------------------------------------------------

// deal.II headers
#include <deal.II/base/conditional_ostream.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/numbers.h>
#include <deal.II/base/parameter_handler.h>
#include <deal.II/base/tensor.h>
#include <deal.II/base/table_handler.h>

#include <deal.II/grid/grid_generator.h>

#include <deal.II/distributed/tria.h>
#include <deal.II/distributed/grid_refinement.h>

// Library-based headers.
#include "group_symmetry.h"
#include "piezoelectric_tensor.h"

// Application-base headers.
#include "command_line.h"

#include <fstream>
#include <iostream>

template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType = double>
class Step0
{
public:

  // First, are the usual class constructors and destructors.
  Step0 ();
  ~Step0 ();

  void run ();

  // Coefficients are held in a parameter file, so it will be
  // necessary to read in a file from the command line.
  nil::CommandLine command_line;

private:

  // First is a list of functions that belong to this class (they are
  // explained later on).
  void get_parameters ();

  void create_coarse_grid (const unsigned int n_refinement_cycles = 0);

  void setup_system ();

  void output_results () const;

  // Following that we have a list of the tensors that will be used in
  // this calculation. They are, first- and second-order piezoelectric
  // tensors
  nil::PiezoelectricTensor<GroupSymm, 1, ValueType> first_order_piezoelectric_tensor;
  nil::PiezoelectricTensor<GroupSymm, 2, ValueType> second_order_piezoelectric_tensor;

  // Additionally, lists of coefficients are needed for those tensors
  // that are tensors of empirical moduli
  std::vector<ValueType> first_order_piezoelectric_coefficients;
  std::vector<ValueType> second_order_piezoelectric_coefficients;

  dealii::ConditionalOStream pcout;

  // A parallel distributed triangulation
  dealii::parallel::distributed::Triangulation<dim> triangulation;

  // Then we need an object to hold various run-time parameters that
  // are specified in an "prm file".
  dealii::ParameterHandler parameters;

  // and finally, a table to handle the results.
  dealii::TableHandler output_table;
};

// The constructor is typically borning...
template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
Step0<dim, GroupSymm, ValueType>::Step0 ()
  :
  pcout (std::cout, (dealii::Utilities::MPI::this_mpi_process (MPI_COMM_WORLD) == 0)),

  triangulation (MPI_COMM_WORLD,
                   typename dealii::Triangulation<dim>::MeshSmoothing
                   (dealii::Triangulation<dim>::smoothing_on_refinement |
		    dealii::Triangulation<dim>::smoothing_on_coarsening))
{}

// as is the destructor.
template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
Step0<dim, GroupSymm, ValueType>::~Step0 ()
{}

// The first step is to obtain a complete list of the coefficients
// needed for this calculation. First comes a declaration of the
// entries expected to be find in the parameter file and then they are
// read into the object parameters.
template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
void
Step0<dim, GroupSymm, ValueType>::get_parameters ()
{
  // First declare the parameters that are expected to be found.
  parameters.declare_entry ("First-order piezoelectric coefficients",
			    "-0.230",
			    dealii::Patterns::List (dealii::Patterns::Double (), 1),
			    "A list of the first-order piezoelectric coefficients. "
			    "Default is zinc-blende GaAs. "
			    "See: PRL 96, 187602 (2006). ");

  parameters.declare_entry ("Second-order piezoelectric coefficients",
			    "-0.439, -3.765, -0.492",
			    dealii::Patterns::List (dealii::Patterns::Double (), 1),
			    "A list of the second-order piezoelectric coefficients. "
			    "Default is zinc-blende GaAs. "
			    "See: PRL 96, 187602 (2006). ");

  // parameters.declare_entry ("Bravais lattice dimensions",
  // 			    "1., 1., 1.",
  // 			    dealii::Patterns::List (dealii::Patterns::Double (), 1),
  // 			    "A list of the Bravais lattice dimensions. ");

  parameters.read_input (command_line.get_prm_file ());

  first_order_piezoelectric_coefficients =
    dealii::Utilities::string_to_double
    (dealii::Utilities::split_string_list (parameters.get ("First-order piezoelectric coefficients")));

  second_order_piezoelectric_coefficients =
    dealii::Utilities::string_to_double
    (dealii::Utilities::split_string_list (parameters.get ("Second-order piezoelectric coefficients")));

  // bravais_lattice =
  //   dealii::Utilities::string_to_double
  //   (dealii::Utilities::split_string_list (parameters.get ("Bravais lattice dimensions")));

  // Some checks
  // AssertThrow (bravais_lattice.size ()==3,
  // 	       dealii::ExcMessage ("The Bravais lattice is required to have three components."));

}

template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
void
Step0<dim, GroupSymm, ValueType>::create_coarse_grid (const unsigned int n_refinement_levels_cycles)
{
  dealii::GridGenerator::hyper_rectangle (triangulation,
					  dealii::Point<dim> (-20,-20,-20),
					  dealii::Point<dim> ( 20, 20, 20),
					  true);

  triangulation.refine_global (n_refinement_cycles);
}

// Next initialise all of the objects we are going to use.
template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
void
Step0<dim, GroupSymm, ValueType>::setup_system ()
{
  // Initialise the first- and second-order piezoelectric tensors...
  first_order_piezoelectric_tensor.reinit ();
  second_order_piezoelectric_tensor.reinit ();

  // and distribute the coefficients.
  first_order_piezoelectric_tensor.distribute_coefficients (first_order_piezoelectric_coefficients);
  second_order_piezoelectric_tensor.distribute_coefficients (second_order_piezoelectric_coefficients);
}

// This is the run function, which wraps all of the above into a
// single logical routine.
template <int dim, enum nil::GroupSymmetry GroupSymm, typename ValueType>
void
Step0<dim, GroupSymm, ValueType>::run ()
{

  // First find the parameters need for this calculation
  get_parameters ();

  // Then create the coarse grid
  create_coarse_grid (5);

  pcout << "Number of active cells: "
	<< triangulation.n_global_active_cells ()
	<< " (on "
	<< triangulation.n_levels ()
	<< " levels)"
	<< std::endl;
}

int main (int argc, char **argv)
{

  // Initialise MPI as we allways do.
  dealii::Utilities::MPI::MPI_InitFinalize mpi_initialization (argc, argv,
							       dealii::numbers::invalid_unsigned_int);

  try
    {
      // Set deal.II's logger depth.
      dealii::deallog.depth_console (0);

      // Initialise the problem, 3d wurtzite.
      Step0<3, nil::GroupSymmetry::Wurtzite> problem;

      // Parse the command line and input file.
      problem.command_line.parse_command_line (argc, argv);

      // Run the problem.
      problem.run ();
    }

  // ...and if this should fail, try to gather as much information as
  // possible. Specifically, if the exception that was thrown is an
  // object of a class that is derived from the C++ standard class
  // exception.
  catch (std::exception &exc)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Exception on processing: " << std::endl
                << exc.what() << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;

      return 1;
    }

  // If the exception that was thrown somewhere was not an object of a
  // class derived from the standard exception class,
  // then nothing cane be done at all - simply print an error message
  // and exit.
  catch (...)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Unknown exception!" << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;
      return 1;
    }

  // At this point, the application performed as was expected - return
  // without error.
  return 0;
}
<|endoftext|>