My Project
pinn_network.hpp
Go to the documentation of this file.
1 #pragma once
7 #include <algorithm>
8 #include <array>
9 #include <cmath>
10 #include <iostream>
11 #include <random>
12 #include <tuple>
13 #include <vector>
14 
16 using Real = double;
17 
19 #ifndef ENZYME_INLINE
20  #define ENZYME_INLINE __attribute__((always_inline)) inline
21 #endif
22 
24 struct Tanh {
25  static ENZYME_INLINE Real apply(Real x) { return std::tanh(x); }
26 };
27 
29 struct Linear {
30  static ENZYME_INLINE Real apply(Real x) { return x; }
31 };
32 
36 template <int In, int Out, typename Activation> struct Dense {
37  static constexpr int InSize = In;
38  static constexpr int OutSize = Out;
39  static constexpr int NumParams = (In * Out) + Out;
40 
42  static ENZYME_INLINE void forward(const Real *p, const Real *in, Real *out) {
43  const Real *W = p;
44  const Real *b = p + (In * Out);
45 
46  for (int i = 0; i < Out; ++i) {
47  Real z = 0.0;
48  for (int j = 0; j < In; ++j) {
49  z += W[i * In + j] * in[j];
50  }
51  z += b[i];
52  out[i] = Activation::apply(z);
53  }
54  }
55 };
56 
60 template <typename... Layers> class PINN {
61 public:
62  using Architecture = std::tuple<Layers...>;
63  static constexpr int TotalParams = (0 + ... + Layers::NumParams);
64  static constexpr int MaxLayerSize = std::max({Layers::InSize..., Layers::OutSize...});
65 
66  std::vector<Real> params;
67 
68  PINN() {
69  params.resize(TotalParams);
70  init_params();
71  }
72 
74  void init_params() {
75  std::random_device rd;
76  std::mt19937 gen(rd());
77  Real *ptr = params.data();
78 
79  auto init_layer = [&](auto &&self, auto index_const) -> void {
80  constexpr size_t I = decltype(index_const)::value;
81  if constexpr (I < sizeof...(Layers)) {
82  using LayerType = std::tuple_element_t<I, Architecture>;
83  Real limit = std::sqrt(6.0 / (LayerType::InSize + LayerType::OutSize));
84  std::uniform_real_distribution<Real> dist(-limit, limit);
85  // Fill parameters for the current layer.
86  for (int i = 0; i < LayerType::NumParams; ++i)
87  *ptr++ = dist(gen);
88  self(self, std::integral_constant<size_t, I + 1>{});
89  }
90  };
91  init_layer(init_layer, std::integral_constant<size_t, 0>{});
92  }
93 
95  template <size_t I> static ENZYME_INLINE void process_layers(const Real *&p_ptr, Real *input_buf, Real *output_buf) {
96  if constexpr (I < sizeof...(Layers)) {
97  using CurrentLayer = std::tuple_element_t<I, Architecture>;
98 
99  // Layer forward pass.
100  CurrentLayer::forward(p_ptr, input_buf, output_buf);
101 
102  p_ptr += CurrentLayer::NumParams;
103 
104  process_layers<I + 1>(p_ptr, output_buf, input_buf);
105  }
106  }
107 
109  static ENZYME_INLINE Real forward_static(const Real *x_ptr, const Real *p_ptr) {
110  Real buf1[MaxLayerSize];
111  Real buf2[MaxLayerSize];
112 
113  // Clear scratch buffers.
114  for (int i = 0; i < MaxLayerSize; ++i) {
115  buf1[i] = 0.0;
116  buf2[i] = 0.0;
117  }
118 
119  using FirstLayer = std::tuple_element_t<0, Architecture>;
120  // Load input into the first buffer.
121  for (int i = 0; i < FirstLayer::InSize; ++i)
122  buf1[i] = x_ptr[i];
123 
124  process_layers<0>(p_ptr, buf1, buf2);
125 
126  constexpr bool OddLayers = (sizeof...(Layers) % 2 != 0);
127  return OddLayers ? buf2[0] : buf1[0];
128  }
129 };
Compile-time feedforward network with static forward.
Definition: pinn_network.hpp:60
std::tuple< Layers... > Architecture
Definition: pinn_network.hpp:62
std::vector< Real > params
Definition: pinn_network.hpp:66
void init_params()
Initialize parameters with layer-wise uniform bounds.
Definition: pinn_network.hpp:74
static constexpr int TotalParams
Definition: pinn_network.hpp:63
static constexpr int MaxLayerSize
Definition: pinn_network.hpp:64
PINN()
Definition: pinn_network.hpp:68
static ENZYME_INLINE Real forward_static(const Real *x_ptr, const Real *p_ptr)
Stateless forward evaluation for a single input.
Definition: pinn_network.hpp:109
static ENZYME_INLINE void process_layers(const Real *&p_ptr, Real *input_buf, Real *output_buf)
Apply all layers in sequence using alternating buffers.
Definition: pinn_network.hpp:95
double Real
Scalar type for PINN utilities.
Definition: pinn_network.hpp:16
#define ENZYME_INLINE
Force inline expansion in performance-critical paths.
Definition: pinn_network.hpp:20
Compile-time dense layer definition.
Definition: pinn_network.hpp:36
static constexpr int NumParams
Definition: pinn_network.hpp:39
static constexpr int OutSize
Definition: pinn_network.hpp:38
static ENZYME_INLINE void forward(const Real *p, const Real *in, Real *out)
Forward pass for a single input vector.
Definition: pinn_network.hpp:42
static constexpr int InSize
Definition: pinn_network.hpp:37
Linear activation.
Definition: pinn_network.hpp:29
static ENZYME_INLINE Real apply(Real x)
Definition: pinn_network.hpp:30
Tanh activation.
Definition: pinn_network.hpp:24
static ENZYME_INLINE Real apply(Real x)
Definition: pinn_network.hpp:25