aboutsummaryrefslogtreecommitdiff
path: root/Source/Parser/WarpXParser.H
blob: ffa61e457b5eaa24e84f25d81bc12dee5341a6a9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#ifndef WARPX_PARSER_H_
#define WARPX_PARSER_H_

#include <array>
#include <vector>
#include <string>
#include <set>

#include "wp_parser_c.h"
#include "wp_parser_y.h"

#ifdef _OPENMP
#include <omp.h>
#endif

class GpuParser;

class WarpXParser
{
public:
    WarpXParser (std::string const& func_body);
    WarpXParser () = default;
    ~WarpXParser ();
    void define (std::string const& func_body);

    void setConstant (std::string const& name, double c);

    //
    // Option 1: Register every variable to an address provided.
    //           Assign values to external variables.
    //           Call eval().
    void registerVariable (std::string const& name, double& var);
    //
    inline double eval () const noexcept;

    //
    // Option 2: Register all variables at once. Parser will create
    //               variables internally.
    //           Call eval(...) with variable values.
    void registerVariables (std::vector<std::string> const& names);
    //
    template <typename T, typename... Ts> inline
    double eval (T x, Ts... yz) const noexcept;

    void print () const;

    std::string const& expr () const;

    std::set<std::string> symbols () const;

    friend class GpuParser;

private:
    void clear ();

    template <typename T> inline
    void unpack (double* p, T x) const noexcept;

    template <typename T, typename... Ts> inline
    void unpack (double* p, T x, Ts... yz) const noexcept;

    std::string m_expression;
#ifdef _OPENMP
    std::vector<struct wp_parser*> m_parser;
    mutable std::vector<std::array<double,16> > m_variables;
#else
    struct wp_parser* m_parser = nullptr;
    mutable std::array<double,16> m_variables;
#endif
};

inline
double
WarpXParser::eval () const noexcept
{
#ifdef _OPENMP
    return wp_ast_eval(m_parser[omp_get_thread_num()]->ast);
#else
    return wp_ast_eval(m_parser->ast);
#endif
}

template <typename T, typename... Ts>
inline
double
WarpXParser::eval (T x, Ts... yz) const noexcept
{
#ifdef _OPENMP
    unpack(m_variables[omp_get_thread_num()].data(), x, yz...);
#else
    unpack(m_variables.data(), x, yz...);
#endif
    return eval();
}

template <typename T>
inline
void
WarpXParser::unpack (double* p, T x) const noexcept
{
    *p = x;
}

template <typename T, typename... Ts>
inline
void
WarpXParser::unpack (double* p, T x, Ts... yz) const noexcept
{
    *p++ = x;
    unpack(p, yz...);
}

#endif