DPsim
Loading...
Searching...
No Matches
Attribute.h
1/* Copyright 2017-2022 Institute for Automation of Complex Power Systems,
2 * EONERC, RWTH Aachen University
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7 *********************************************************************************/
8
9#pragma once
10#include <iostream>
11#include <set>
12
13#include <dpsim-models/Config.h>
14#include <dpsim-models/Definitions.h>
15#include <dpsim-models/MathUtils.h>
16#include <dpsim-models/PtrFactory.h>
17namespace CPS {
18
27enum UpdateTaskKind {
28 UPDATE_ONCE,
29 UPDATE_ON_GET,
30 UPDATE_ON_SET,
31 UPDATE_ON_SIMULATION_STEP,
32};
33
34template <class T> class Attribute;
35
36template <class T> class AttributeStatic;
37
38template <class T> class AttributeDynamic;
39
46template <class T> class AttributePointer {
47public:
48 using element_type = T;
49
50 AttributePointer() : mPtr(){};
51 AttributePointer(const AttributePointer &r) = default;
52 AttributePointer(std::shared_ptr<T> ptr) : mPtr(ptr){};
53 AttributePointer(std::nullptr_t ptr) : mPtr(ptr){};
54 explicit AttributePointer(T *ptr) : mPtr(ptr){};
55
56 template <class U> AttributePointer(AttributePointer<U> ptr) : mPtr() {
57 this->mPtr = ptr.getPtr();
58 };
59
60 template <class U> AttributePointer(std::shared_ptr<U> ptr) : mPtr(ptr){};
61
62 AttributePointer &operator=(const AttributePointer &r) noexcept {
63 this->mPtr = r.getPtr();
64 return *this;
65 };
66
67 template <class U>
68 AttributePointer &operator=(const AttributePointer<U> &r) noexcept {
69 this->mPtr = r.getPtr();
70 return *this;
71 };
72
73 AttributePointer &operator=(AttributePointer &&r) {
74 this->mPtr = r.getPtr();
75 return *this;
76 }
77
78 template <class U> AttributePointer &operator=(AttributePointer<U> &&r) {
79 this->mPtr = r.getPtr();
80 return *this;
81 }
82
83 T &operator*() const noexcept { return *mPtr; }
84
85 T *operator->() const noexcept { return mPtr.operator->(); }
86
87 T *get() const { return mPtr.get(); }
88
89 std::shared_ptr<T> getPtr() const { return mPtr; }
90
91 bool isNull() const { return mPtr == nullptr; }
92
93private:
94 std::shared_ptr<T> mPtr;
95};
96
100template <class T> struct AttributeCmp {
101 bool operator()(CPS::AttributePointer<T> a,
102 CPS::AttributePointer<T> b) const {
103 return a.getPtr() < b.getPtr();
104 }
105};
106
110template <class T> struct AttributeEq {
111 bool operator()(CPS::AttributePointer<T> a,
112 CPS::AttributePointer<T> b) const {
113 return a.getPtr() == b.getPtr();
114 }
115};
116
121public:
123 typedef std::vector<Ptr> List;
124 typedef std::set<Ptr, AttributeCmp<AttributeBase>> Set;
125 typedef std::map<String, Ptr> Map;
126
130 virtual String toString() = 0;
131
136 virtual bool isStatic() const = 0;
137
138 virtual ~AttributeBase() = default;
139
144 virtual bool copyValue(AttributeBase::Ptr copyFrom) = 0;
145
150 virtual const std::type_info &getType() = 0;
151
156 virtual AttributeBase::Ptr cloneValueOntoNewAttribute() = 0;
157
163 virtual void appendDependencies(AttributeBase::Set *deps) = 0;
164
169 virtual AttributeBase::Set getDependencies() final {
170 AttributeBase::Set deps = AttributeBase::Set();
171 this->appendDependencies(&deps);
172 return deps;
173 }
174};
175
179template <class DependentType> class AttributeUpdateTaskBase {
180
181public:
182 typedef std::shared_ptr<AttributeUpdateTaskBase<DependentType>> Ptr;
183
184 virtual void executeUpdate(std::shared_ptr<DependentType> &dependent) = 0;
185 virtual AttributeBase::List getDependencies() = 0;
186 virtual ~AttributeUpdateTaskBase() = default;
187};
188
194template <class DependentType, class... DependencyTypes>
195class AttributeUpdateTask
196 : public AttributeUpdateTaskBase<DependentType>,
197 public SharedFactory<
198 AttributeUpdateTask<DependentType, DependencyTypes...>> {
199
200public:
201 using Actor =
202 std::function<void(std::shared_ptr<DependentType> &,
203 typename Attribute<DependencyTypes>::Ptr...)>;
204
205protected:
206 std::tuple<typename Attribute<DependencyTypes>::Ptr...> mDependencies;
207 Actor mActorFunction;
208 UpdateTaskKind mKind;
209
210public:
211 AttributeUpdateTask(UpdateTaskKind kind, Actor &actorFunction,
212 typename Attribute<DependencyTypes>::Ptr... dependencies)
213 : mDependencies(std::forward<typename Attribute<DependencyTypes>::Ptr>(
214 dependencies)...),
215 mActorFunction(actorFunction), mKind(kind) {}
216
217 virtual void
218 executeUpdate(std::shared_ptr<DependentType> &dependent) override {
219 mActorFunction(
220 dependent,
221 std::get<typename Attribute<DependencyTypes>::Ptr...>(mDependencies));
222 }
223
227 virtual AttributeBase::List getDependencies() override {
228 return std::apply(
229 [](auto &&...elems) {
230 return std::vector<AttributeBase::Ptr>{
231 std::forward<decltype(elems)>(elems)...};
232 },
233 mDependencies);
234 };
235};
236
241template <class T>
242class Attribute : public AttributeBase,
243 public std::enable_shared_from_this<Attribute<T>> {
244
245protected:
246 std::shared_ptr<T> mData;
247
248public:
249 using Type = T;
251
252 Attribute(T initialValue = T())
253 : AttributeBase(), mData(std::make_shared<T>()) {
254 *mData = initialValue;
255 }
256
261 virtual void set(T value) = 0;
262
266 virtual T &get() = 0;
267
274 virtual void setReference(Attribute<T>::Ptr reference) = 0;
275
280 virtual std::shared_ptr<T> asRawPointer() = 0;
281
285 String toString() override {
286 std::stringstream ss;
287 ss << this->get();
288 return ss.str();
289 }
290
301 operator const T &() { return this->get(); }
302
308 T &operator*() { return this->get(); }
309
314 bool copyValue(AttributeBase::Ptr copyFrom) override {
315 Attribute<T>::Ptr copyFromTyped =
316 std::dynamic_pointer_cast<Attribute<T>>(copyFrom.getPtr());
317 if (copyFromTyped.getPtr() == nullptr) {
318 return false;
319 }
320 this->set(**copyFromTyped);
321 return true;
322 }
323
328 const std::type_info &getType() override { return typeid(T); }
329
334 AttributeBase::Ptr cloneValueOntoNewAttribute() override {
336 AttributeStatic<T>::make(this->get()));
337 // TODO: This is in the real time path. We should not use heap here.
338 };
339
348 template <class U>
349 typename Attribute<U>::Ptr
350 derive(typename AttributeUpdateTask<U, T>::Actor getter =
351 typename AttributeUpdateTask<U, T>::Actor(),
352 typename AttributeUpdateTask<U, T>::Actor setter =
353 typename AttributeUpdateTask<U, T>::Actor()) {
354 auto derivedAttribute = std::make_shared<AttributeDynamic<U>>();
355 if (setter) {
356 derivedAttribute->addTask(
357 UpdateTaskKind::UPDATE_ON_SET,
358 AttributeUpdateTask<U, T>::make(
359 UpdateTaskKind::UPDATE_ON_SET, setter,
360 Attribute<T>::Ptr(this->shared_from_this())));
361 }
362 if (getter) {
363 derivedAttribute->addTask(
364 UpdateTaskKind::UPDATE_ON_GET,
365 AttributeUpdateTask<U, T>::make(
366 UpdateTaskKind::UPDATE_ON_GET, getter,
367 Attribute<T>::Ptr(this->shared_from_this())));
368 }
369 return derivedAttribute;
370 }
371
376 template <typename U = T,
377 std::enable_if_t<std::is_same_v<Complex, U>, bool> = true>
379 // requires std::same_as<T, CPS::Complex> //CPP20
380 {
381 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor getter =
382 [](std::shared_ptr<Real> &dependent,
383 typename Attribute<Complex>::Ptr dependency) {
384 *dependent = (**dependency).real();
385 };
386 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor setter =
387 [](std::shared_ptr<Real> &dependent,
388 typename Attribute<Complex>::Ptr dependency) {
389 CPS::Complex currentValue = dependency->get();
390 currentValue.real(*dependent);
391 dependency->set(currentValue);
392 };
393 return derive<CPS::Real>(getter, setter);
394 }
395
400 template <typename U = T,
401 std::enable_if_t<std::is_same_v<Complex, U>, bool> = true>
403 // requires std::same_as<T, CPS::Complex> //CPP20
404 {
405 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor getter =
406 [](std::shared_ptr<Real> &dependent,
407 Attribute<Complex>::Ptr dependency) {
408 *dependent = (**dependency).imag();
409 };
410 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor setter =
411 [](std::shared_ptr<Real> &dependent,
412 Attribute<Complex>::Ptr dependency) {
413 CPS::Complex currentValue = dependency->get();
414 currentValue.imag(*dependent);
415 dependency->set(currentValue);
416 };
417 return derive<CPS::Real>(getter, setter);
418 }
419
424 template <typename U = T,
425 std::enable_if_t<std::is_same_v<Complex, U>, bool> = true>
427 // requires std::same_as<T, CPS::Complex> //CPP20
428 {
429 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor getter =
430 [](std::shared_ptr<Real> &dependent,
431 Attribute<Complex>::Ptr dependency) {
432 *dependent = Math::abs(**dependency);
433 };
434 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor setter =
435 [](std::shared_ptr<Real> &dependent,
436 Attribute<Complex>::Ptr dependency) {
437 CPS::Complex currentValue = dependency->get();
438 dependency->set(Math::polar(*dependent, Math::phase(currentValue)));
439 };
440 return derive<CPS::Real>(getter, setter);
441 }
442
447 template <typename U = T,
448 std::enable_if_t<std::is_same_v<Complex, U>, bool> = true>
450 // requires std::same_as<T, CPS::Complex> //CPP20
451 {
452 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor getter =
453 [](std::shared_ptr<Real> &dependent,
454 Attribute<Complex>::Ptr dependency) {
455 *dependent = Math::phase(**dependency);
456 };
457 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor setter =
458 [](std::shared_ptr<Real> &dependent,
459 Attribute<Complex>::Ptr dependency) {
460 CPS::Complex currentValue = dependency->get();
461 dependency->set(Math::polar(Math::abs(currentValue), *dependent));
462 };
463 return derive<CPS::Real>(getter, setter);
464 }
465
471 template <typename U = T, std::enable_if_t<std::is_same_v<Real, U> ||
472 std::is_same_v<Complex, U>,
473 bool> = true>
475 // requires std::same_as<T, CPS::Complex> || std::same_as<T, CPS::Real> //CPP20
476 {
477 typename AttributeUpdateTask<T, T>::Actor getter =
478 [scale](std::shared_ptr<T> &dependent, Attribute<T>::Ptr dependency) {
479 *dependent = scale * (**dependency);
480 };
481 typename AttributeUpdateTask<T, T>::Actor setter =
482 [scale](std::shared_ptr<T> &dependent, Attribute<T>::Ptr dependency) {
483 dependency->set((*dependent) / scale);
484 };
485 return derive<T>(getter, setter);
486 }
487
495 template <class U, class V = T,
496 std::enable_if_t<std::is_same_v<CPS::MatrixVar<U>, V>, bool> = true>
498 deriveCoeff(typename CPS::MatrixVar<U>::Index row,
499 typename CPS::MatrixVar<U>::Index column)
500 // requires std::same_as<T, CPS::MatrixVar<U>> //CPP20
501 {
502 typename AttributeUpdateTask<U, T>::Actor getter =
503 [row, column](std::shared_ptr<U> &dependent,
504 Attribute<T>::Ptr dependency) {
505 *dependent = (**dependency)(row, column);
506 };
507 typename AttributeUpdateTask<U, T>::Actor setter =
508 [row, column](std::shared_ptr<U> &dependent,
509 Attribute<T>::Ptr dependency) {
510 CPS::MatrixVar<U> currentValue = dependency->get();
511 currentValue(row, column) = *dependent;
512 dependency->set(currentValue);
513 };
514 return derive<U>(getter, setter);
515 }
516};
517
522template <class T>
523class AttributeStatic : public Attribute<T>,
524 public SharedFactory<AttributeStatic<T>> {
525 friend class SharedFactory<AttributeStatic<T>>;
526
527public:
528 AttributeStatic(T initialValue = T()) : Attribute<T>(initialValue) {}
529
530 virtual void set(T value) override { *this->mData = value; };
531
532 virtual T &get() override { return *this->mData; };
533
534 virtual bool isStatic() const override { return true; }
535
536 virtual void setReference(typename Attribute<T>::Ptr reference) override {
537 throw TypeException();
538 }
539
540 virtual std::shared_ptr<T> asRawPointer() override { return this->mData; }
541
542 virtual void appendDependencies(AttributeBase::Set *deps) override {
543 deps->insert(this->shared_from_this());
544 }
545};
546
550template <class T>
551class AttributeDynamic : public Attribute<T>,
552 public SharedFactory<AttributeDynamic<T>> {
553 friend class SharedFactory<AttributeDynamic<T>>;
554
555protected:
556 std::vector<typename AttributeUpdateTaskBase<T>::Ptr> updateTasksOnce;
557 std::vector<typename AttributeUpdateTaskBase<T>::Ptr> updateTasksOnGet;
558 std::vector<typename AttributeUpdateTaskBase<T>::Ptr> updateTasksOnSet;
559
560public:
561 AttributeDynamic(T initialValue = T()) : Attribute<T>(initialValue) {}
562
568 void addTask(UpdateTaskKind kind,
569 typename AttributeUpdateTaskBase<T>::Ptr task) {
570 switch (kind) {
571 case UpdateTaskKind::UPDATE_ONCE:
572 updateTasksOnce.push_back(task);
573 // THISISBAD: This is probably not the right time to run this kind of task
574 task->executeUpdate(this->mData);
575 break;
576 case UpdateTaskKind::UPDATE_ON_GET:
577 updateTasksOnGet.push_back(task);
578 break;
579 case UpdateTaskKind::UPDATE_ON_SET:
580 updateTasksOnSet.push_back(task);
581 break;
582 case UpdateTaskKind::UPDATE_ON_SIMULATION_STEP:
584 };
585 }
586
591 void clearTasks(UpdateTaskKind kind) {
592 switch (kind) {
593 case UpdateTaskKind::UPDATE_ONCE:
594 updateTasksOnce.clear();
595 break;
596 case UpdateTaskKind::UPDATE_ON_GET:
597 updateTasksOnGet.clear();
598 break;
599 case UpdateTaskKind::UPDATE_ON_SET:
600 updateTasksOnSet.clear();
601 break;
602 case UpdateTaskKind::UPDATE_ON_SIMULATION_STEP:
604 };
605 }
606
611 updateTasksOnce.clear();
612 updateTasksOnGet.clear();
613 updateTasksOnSet.clear();
614 }
615
616 virtual void setReference(typename Attribute<T>::Ptr reference) override {
617 typename AttributeUpdateTask<T, T>::Actor getter =
618 [](std::shared_ptr<T> &dependent,
619 typename Attribute<T>::Ptr dependency) {
620 dependent = dependency->asRawPointer();
621 };
622 this->clearAllTasks();
623 if (reference->isStatic()) {
624 this->addTask(UpdateTaskKind::UPDATE_ONCE,
625 AttributeUpdateTask<T, T>::make(UpdateTaskKind::UPDATE_ONCE,
626 getter, reference));
627 } else {
628 this->addTask(UpdateTaskKind::UPDATE_ON_GET,
629 AttributeUpdateTask<T, T>::make(
630 UpdateTaskKind::UPDATE_ON_GET, getter, reference));
631 }
632 }
633
634 virtual std::shared_ptr<T> asRawPointer() override {
635 for (typename AttributeUpdateTaskBase<T>::Ptr task : updateTasksOnGet) {
636 task->executeUpdate(this->mData);
637 }
638 return this->mData;
639 }
640
641 virtual void set(T value) override {
642 *this->mData = value;
643 for (typename AttributeUpdateTaskBase<T>::Ptr task : updateTasksOnSet) {
644 task->executeUpdate(this->mData);
645 }
646 };
647
648 virtual T &get() override {
649 for (typename AttributeUpdateTaskBase<T>::Ptr task : updateTasksOnGet) {
650 task->executeUpdate(this->mData);
651 }
652 return *this->mData;
653 };
654
655 virtual bool isStatic() const override { return false; }
656
662 virtual void appendDependencies(AttributeBase::Set *deps) override {
663 deps->insert(this->shared_from_this());
664
665 AttributeBase::Set newDeps = AttributeBase::Set();
666 for (typename AttributeUpdateTaskBase<T>::Ptr task : updateTasksOnce) {
667 AttributeBase::List taskDeps = task->getDependencies();
668 newDeps.insert(taskDeps.begin(), taskDeps.end());
669 }
670
671 for (typename AttributeUpdateTaskBase<T>::Ptr task : updateTasksOnGet) {
672 AttributeBase::List taskDeps = task->getDependencies();
673 newDeps.insert(taskDeps.begin(), taskDeps.end());
674 }
675
676 for (auto dependency : newDeps) {
677 dependency->appendDependencies(deps);
678 }
679 }
680};
681
682template <> String Attribute<Real>::toString();
683
684template <> String Attribute<Complex>::toString();
685
686template <> String Attribute<String>::toString();
687
688} // namespace CPS
689
690namespace std {
694template <typename T> struct hash<CPS::AttributePointer<T>> {
695 size_t operator()(CPS::AttributePointer<T> const &x) const {
696 return std::hash<std::shared_ptr<T>>()(x.getPtr());
697 }
698};
699} // namespace std
virtual bool isStatic() const =0
virtual const std::type_info & getType()=0
Get the type of this attribute.
virtual bool copyValue(AttributeBase::Ptr copyFrom)=0
Copy the attribute value of copyFrom onto this attribute.
virtual String toString()=0
virtual AttributeBase::Set getDependencies() final
Definition Attribute.h:169
virtual void appendDependencies(AttributeBase::Set *deps)=0
virtual AttributeBase::Ptr cloneValueOntoNewAttribute()=0
Generates a new attribute of the same type and copies the current value in the heap....
void addTask(UpdateTaskKind kind, typename AttributeUpdateTaskBase< T >::Ptr task)
Definition Attribute.h:568
virtual void setReference(typename Attribute< T >::Ptr reference) override
Definition Attribute.h:616
virtual void appendDependencies(AttributeBase::Set *deps) override
Definition Attribute.h:662
void clearTasks(UpdateTaskKind kind)
Definition Attribute.h:591
virtual void set(T value) override
Definition Attribute.h:641
virtual std::shared_ptr< T > asRawPointer() override
Definition Attribute.h:634
virtual bool isStatic() const override
Definition Attribute.h:655
virtual T & get() override
Definition Attribute.h:648
const std::type_info & getType() override
Get the type of this attribute.
Definition Attribute.h:328
T & operator*()
User-defined dereference operator.
Definition Attribute.h:308
AttributePointer< Attribute< T > > deriveScaled(T scale)
Definition Attribute.h:474
AttributePointer< Attribute< Real > > deriveImag()
Definition Attribute.h:402
AttributePointer< Attribute< Real > > derivePhase()
Definition Attribute.h:449
AttributePointer< Attribute< U > > deriveCoeff(typename CPS::MatrixVar< U >::Index row, typename CPS::MatrixVar< U >::Index column)
Definition Attribute.h:498
virtual std::shared_ptr< T > asRawPointer()=0
AttributePointer< Attribute< Real > > deriveReal()
Definition Attribute.h:378
virtual void setReference(Attribute< T >::Ptr reference)=0
virtual void set(T value)=0
String toString() override
Fallback method for all attribute types not covered by the specifications in Attribute....
Definition Attribute.h:285
AttributeBase::Ptr cloneValueOntoNewAttribute() override
Generates a new attribute of the same type and copies the current value in the heap....
Definition Attribute.h:334
virtual T & get()=0
AttributePointer< Attribute< Real > > deriveMag()
Definition Attribute.h:426
bool copyValue(AttributeBase::Ptr copyFrom) override
Copy the attribute value of copyFrom onto this attribute.
Definition Attribute.h:314
Attribute< U >::Ptr derive(typename AttributeUpdateTask< U, T >::Actor getter=typename AttributeUpdateTask< U, T >::Actor(), typename AttributeUpdateTask< U, T >::Actor setter=typename AttributeUpdateTask< U, T >::Actor())
Definition Attribute.h:350
virtual void set(T value) override
Definition Attribute.h:530
virtual std::shared_ptr< T > asRawPointer() override
Definition Attribute.h:540
virtual void appendDependencies(AttributeBase::Set *deps) override
Definition Attribute.h:542
virtual void setReference(typename Attribute< T >::Ptr reference) override
Definition Attribute.h:536
virtual bool isStatic() const override
Definition Attribute.h:534
virtual T & get() override
Definition Attribute.h:532
virtual AttributeBase::List getDependencies() override
Definition Attribute.h:227