DSS C-API and dss.hpp
DSS C-API and dss.hpp expose a customized and extended implementation of OpenDSS to C and C++.
dss_common.hpp
1
12#pragma once
13#ifndef DSS_CPP_COMMON
14#define DSS_CPP_COMMON
15
16#include <cstdint>
17#include <string>
18#include <complex>
19#include <vector>
20#include "dss_capi_ctx.h"
21#include <Eigen/Core>
22#include "fmt/core.h"
23
24namespace dss {
25
26using std::int32_t;
27using std::string;
28
29typedef std::complex<double> complex;
30using Eigen::VectorXd;
31typedef Eigen::Matrix<int32_t, Eigen::Dynamic, 1> VectorXi;
32typedef std::vector<string> strings;
33typedef std::vector<int32_t> bools; // std::vector<bool> is a bitset, might as well reuse int32
34
35namespace obj
36{
37 class DSSObj;
38 class DSSBatch;
39}
40
41struct APIUtil
42{
43 void *ctx;
44 int32_t *error_ptr;
45 bool owns_ctx;
46 char*** data_PPAnsiChar;
47 double** data_PDouble;
48 int32_t** data_PInteger;
49 int8_t** data_PByte;
50 int32_t* count_PPAnsiChar;
51 int32_t* count_PDouble;
52 int32_t* count_PInteger;
53 int32_t* count_PByte;
54
55 void check_for_error()
56 {
57 if (!*error_ptr) return;
58
59 int32_t error = *error_ptr;
60 char* error_msg = ctx_Error_Get_Description(ctx);
61 *error_ptr = 0;
62 throw std::runtime_error(error_msg);
63 }
64
66 {
67 APIUtil *api_util;
68 ErrorChecker(APIUtil *util): api_util(util)
69 {
70
71 }
72
74 {
75 api_util->check_for_error();
76 }
77 };
78
79 APIUtil(bool create_ctx=false)
80 {
81 if (create_ctx)
82 {
83 ctx = ctx_New();
84 owns_ctx = true;
85 }
86 else
87 {
88 owns_ctx = false;
89 ctx = ctx_Get_Prime();
90 }
91 ctx_DSS_Start(ctx, 0);
92 error_ptr = ctx_Error_Get_NumberPtr(ctx);
93 ctx_DSS_GetGRPointers(
94 ctx,
95 &data_PPAnsiChar,
96 &data_PDouble,
97 &data_PInteger,
98 &data_PByte,
99 &count_PPAnsiChar,
100 &count_PDouble,
101 &count_PInteger,
102 &count_PByte
103 );
104 }
105
106 APIUtil(void *context, bool is_owner=false)
107 {
108 ctx = context;
109 owns_ctx = is_owner;
110 error_ptr = ctx_Error_Get_NumberPtr(ctx);
111 ctx_DSS_GetGRPointers(
112 ctx,
113 &data_PPAnsiChar,
114 &data_PDouble,
115 &data_PInteger,
116 &data_PByte,
117 &count_PPAnsiChar,
118 &count_PDouble,
119 &count_PInteger,
120 &count_PByte
121 );
122 }
123
124 ~APIUtil()
125 {
126 if (owns_ctx)
127 {
128 ctx_Dispose(ctx);
129 }
130 }
131
132 /*
133 Create a new element of a target class T, optionally activating and
134 flagging its edition.
135 */
136 template <typename T, typename enabled_ = std::enable_if_t<std::is_convertible<T*, dss::obj::DSSObj*>::value>>
137 T create(const char *name, bool activate=true, bool begin_edit=true)
138 {
139 void *ptr = Obj_New(ctx, T::dss_cls_idx, name, activate, begin_edit);
140 check_for_error();
141 return T(this, ptr);
142 }
143
144 /*
145 Create a new element of a target class T, optionally activating and
146 flagging its edition.
147 */
148 template <typename T, typename enabled_ = std::enable_if_t<std::is_convertible<T*, dss::obj::DSSObj*>::value>>
149 T create(const string &name, bool activate=true, bool begin_edit=true)
150 {
151 return create<T>(name.c_str(), activate, begin_edit);
152 }
153
154 /*
155 Create a new batch of elements of a target batch class T, optionally
156 flagging their edition. Names are given by the prefix concatenated with
157 a sequential number starting at `start_at`.
158 */
159 template <typename T, typename enabled_ = std::enable_if_t<std::is_convertible<T*, dss::obj::DSSBatch*>::value>>
160 T create(const char *prefix, int32_t count, bool begin_edit=true, int32_t start_at=1)
161 {
162 T batch(this);
163 std::vector<string> names;
164 std::vector<const char*> names_ptrs;
165 names.reserve(count);
166 names_ptrs.reserve(count);
167
168 std::string sprefix = prefix;
169 for (int32_t i = 0; i < count; ++i)
170 {
171 names.emplace_back(fmt::format("{}{}", prefix, start_at + i));
172 names_ptrs.push_back(names.back().c_str());
173 }
174 Batch_CreateFromNew(ctx, &batch.pointer, batch.count, T::BatchElementClass::dss_cls_idx, &names_ptrs[0], count, begin_edit);
175 check_for_error();
176 return batch;
177 }
178
179 /*
180 Create a new batch of elements of a target batch class T, optionally
181 flagging their edition. Names are given by the prefix concatenated with
182 a sequential number starting at `start_at`.
183 */
184 template <typename T, typename enabled_ =
185 std::enable_if_t<
186 std::is_convertible<T*, dss::obj::DSSBatch*>::value
187 >
188 >
189 T create(const string &prefix, int32_t count, bool begin_edit=true, int32_t start_at=1)
190 {
191 return create<T>(prefix.c_str(), count, begin_edit, start_at);
192 }
193
194 template <typename VectorT=Eigen::Matrix<double, Eigen::Dynamic, 1>, typename std::enable_if<std::is_same<typename VectorT::value_type, double>::value>::type* = nullptr>
195 VectorT get_float64_gr_array()
196 {
197 APIUtil::ErrorChecker error_checker(this);
198 VectorT res;
199 res.resize(size_t(*count_PDouble));
200 memcpy(&res[0], *data_PDouble, sizeof(typename VectorT::value_type) * (*count_PDouble));
201 return res;
202 }
203
204 template <typename VectorT=Eigen::Matrix<int32_t, Eigen::Dynamic, 1>, typename std::enable_if<std::is_same<typename VectorT::value_type, int32_t>::value>::type* = nullptr>
205 VectorT get_int32_gr_array()
206 {
207 APIUtil::ErrorChecker error_checker(this);
208 VectorT res;
209 res.resize(size_t(*count_PInteger));
210 memcpy(&res[0], *data_PInteger, sizeof(typename VectorT::value_type) * (*count_PInteger));
211 return res;
212 }
213
214 template <typename VectorT=Eigen::Matrix<int8_t, Eigen::Dynamic, 1>, typename std::enable_if<std::is_same<typename VectorT::value_type, int8_t>::value>::type* = nullptr>
215 VectorT get_int8_gr_array()
216 {
217 APIUtil::ErrorChecker error_checker(this);
218 VectorT res;
219 res.resize(size_t(*count_PByte));
220 memcpy(&res[0], *data_PByte, sizeof(typename VectorT::value_type) * (*count_PByte));
221 return res;
222 }
223
224 template<typename FunctionT, typename... Args>
225 strings get_string_array(FunctionT func, Args... args)
226 {
227 char** ResultPtr = nullptr;
228 int32_t ResultCount[2] = {0, 0};
229 func(ctx, &ResultPtr, ResultCount, args...);
230 strings res;
231 res.reserve(ResultCount[0]);
232 for (int32_t i = 0; i < ResultCount[0]; ++i)
233 {
234 res.emplace_back(ResultPtr[i]);
235 }
236 return res;
237 }
238
239 template<typename FunctionT, typename... Args>
240 void set_string_array(FunctionT func, const strings &value, Args... args)
241 {
242 std::vector<const char*> ptrs(value.size(), nullptr);
243 for (size_t i = 0; i < value.size(); ++i)
244 {
245 ptrs[i] = value[i].c_str();
246 }
247
248 func(ctx, &ptrs[0], value.size(), args...);
249 }
250};
251
256{
257public:
261 void *ctx;
262
267
268 ContextState(APIUtil *util)
269 {
270 api_util = util;
271 ctx = util->ctx;
272 }
273};
274
275}
276#endif // #ifndef DSS_CPP_COMMON
Wraps common DSSContext state data.
Definition: dss_common.hpp:256
void * ctx
Pointer to the DSSContext for easy access.
Definition: dss_common.hpp:261
APIUtil * api_util
API utility functions.
Definition: dss_common.hpp:266
Definition: dss_common.hpp:66
Definition: dss_common.hpp:42