13#include <dpsim-models/Config.h>
14#include <dpsim-models/Definitions.h>
15#include <dpsim-models/MathUtils.h>
16#include <dpsim-models/PtrFactory.h>
31 UPDATE_ON_SIMULATION_STEP,
46template <
class T>
class AttributePointer {
48 using element_type = T;
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){};
56 template <
class U> AttributePointer(AttributePointer<U> ptr) : mPtr() {
57 this->mPtr = ptr.getPtr();
60 template <
class U> AttributePointer(std::shared_ptr<U> ptr) : mPtr(ptr){};
62 AttributePointer &operator=(
const AttributePointer &r)
noexcept {
63 this->mPtr = r.getPtr();
68 AttributePointer &operator=(
const AttributePointer<U> &r)
noexcept {
69 this->mPtr = r.getPtr();
73 AttributePointer &operator=(AttributePointer &&r) {
74 this->mPtr = r.getPtr();
78 template <
class U> AttributePointer &operator=(AttributePointer<U> &&r) {
79 this->mPtr = r.getPtr();
83 T &operator*()
const noexcept {
return *mPtr; }
85 T *operator->()
const noexcept {
return mPtr.operator->(); }
87 T *get()
const {
return mPtr.get(); }
89 std::shared_ptr<T> getPtr()
const {
return mPtr; }
91 bool isNull()
const {
return mPtr ==
nullptr; }
94 std::shared_ptr<T> mPtr;
103 return a.getPtr() < b.getPtr();
113 return a.getPtr() == b.getPtr();
123 typedef std::vector<Ptr> List;
124 typedef std::set<Ptr, AttributeCmp<AttributeBase>> Set;
125 typedef std::map<String, Ptr> Map;
144 virtual bool copyValue(AttributeBase::Ptr copyFrom) = 0;
170 AttributeBase::Set deps = AttributeBase::Set();
182 typedef std::shared_ptr<AttributeUpdateTaskBase<DependentType>> Ptr;
184 virtual void executeUpdate(std::shared_ptr<DependentType> &dependent) = 0;
185 virtual AttributeBase::List getDependencies() = 0;
194template <
class DependentType,
class... DependencyTypes>
195class AttributeUpdateTask
198 AttributeUpdateTask<DependentType, DependencyTypes...>> {
202 std::function<void(std::shared_ptr<DependentType> &,
203 typename Attribute<DependencyTypes>::Ptr...)>;
206 std::tuple<typename Attribute<DependencyTypes>::Ptr...> mDependencies;
207 Actor mActorFunction;
208 UpdateTaskKind mKind;
211 AttributeUpdateTask(UpdateTaskKind kind, Actor &actorFunction,
212 typename Attribute<DependencyTypes>::Ptr... dependencies)
213 : mDependencies(std::forward<
typename Attribute<DependencyTypes>::Ptr>(
215 mActorFunction(actorFunction), mKind(kind) {}
218 executeUpdate(std::shared_ptr<DependentType> &dependent)
override {
221 std::get<
typename Attribute<DependencyTypes>::Ptr...>(mDependencies));
229 [](
auto &&...elems) {
230 return std::vector<AttributeBase::Ptr>{
231 std::forward<decltype(elems)>(elems)...};
243 public std::enable_shared_from_this<Attribute<T>> {
246 std::shared_ptr<T> mData;
252 Attribute(T initialValue = T())
254 *mData = initialValue;
261 virtual void set(T value) = 0;
286 std::stringstream ss;
301 operator const T &() {
return this->
get(); }
315 Attribute<T>::Ptr copyFromTyped =
316 std::dynamic_pointer_cast<Attribute<T>>(copyFrom.getPtr());
317 if (copyFromTyped.getPtr() ==
nullptr) {
320 this->
set(**copyFromTyped);
328 const std::type_info &
getType()
override {
return typeid(T); }
336 AttributeStatic<T>::make(this->
get()));
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>>();
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())));
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())));
369 return derivedAttribute;
376 template <
typename U = T,
377 std::enable_if_t<std::is_same_v<Complex, U>,
bool> =
true>
381 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor getter =
382 [](std::shared_ptr<Real> &dependent,
383 typename Attribute<Complex>::Ptr dependency) {
384 *dependent = (**dependency).real();
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);
400 template <
typename U = T,
401 std::enable_if_t<std::is_same_v<Complex, U>,
bool> =
true>
405 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor getter =
406 [](std::shared_ptr<Real> &dependent,
407 Attribute<Complex>::Ptr dependency) {
408 *dependent = (**dependency).imag();
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);
424 template <
typename U = T,
425 std::enable_if_t<std::is_same_v<Complex, U>,
bool> =
true>
429 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor getter =
430 [](std::shared_ptr<Real> &dependent,
431 Attribute<Complex>::Ptr dependency) {
432 *dependent = Math::abs(**dependency);
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)));
447 template <
typename U = T,
448 std::enable_if_t<std::is_same_v<Complex, U>,
bool> =
true>
452 AttributeUpdateTask<CPS::Real, CPS::Complex>::Actor getter =
453 [](std::shared_ptr<Real> &dependent,
454 Attribute<Complex>::Ptr dependency) {
455 *dependent = Math::phase(**dependency);
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));
471 template <
typename U = T, std::enable_if_t<std::is_same_v<Real, U> ||
472 std::is_same_v<Complex, U>,
477 typename AttributeUpdateTask<T, T>::Actor getter =
478 [scale](std::shared_ptr<T> &dependent, Attribute<T>::Ptr dependency) {
479 *dependent = scale * (**dependency);
481 typename AttributeUpdateTask<T, T>::Actor setter =
482 [scale](std::shared_ptr<T> &dependent, Attribute<T>::Ptr dependency) {
483 dependency->set((*dependent) / scale);
495 template <
class U,
class V = T,
496 std::enable_if_t<std::is_same_v<CPS::MatrixVar<U>, V>,
bool> =
true>
499 typename CPS::MatrixVar<U>::Index column)
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);
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);
523class AttributeStatic :
public Attribute<T>,
528 AttributeStatic(T initialValue = T()) : Attribute<T>(initialValue) {}
530 virtual void set(T value)
override { *this->mData = value; };
532 virtual T &
get()
override {
return *this->mData; };
534 virtual bool isStatic()
const override {
return true; }
536 virtual void setReference(
typename Attribute<T>::Ptr reference)
override {
540 virtual std::shared_ptr<T>
asRawPointer()
override {
return this->mData; }
543 deps->insert(this->shared_from_this());
551class AttributeDynamic :
public Attribute<T>,
556 std::vector<typename AttributeUpdateTaskBase<T>::Ptr> updateTasksOnce;
557 std::vector<typename AttributeUpdateTaskBase<T>::Ptr> updateTasksOnGet;
558 std::vector<typename AttributeUpdateTaskBase<T>::Ptr> updateTasksOnSet;
561 AttributeDynamic(T initialValue = T()) : Attribute<T>(initialValue) {}
569 typename AttributeUpdateTaskBase<T>::Ptr task) {
571 case UpdateTaskKind::UPDATE_ONCE:
572 updateTasksOnce.push_back(task);
574 task->executeUpdate(this->mData);
576 case UpdateTaskKind::UPDATE_ON_GET:
577 updateTasksOnGet.push_back(task);
579 case UpdateTaskKind::UPDATE_ON_SET:
580 updateTasksOnSet.push_back(task);
582 case UpdateTaskKind::UPDATE_ON_SIMULATION_STEP:
593 case UpdateTaskKind::UPDATE_ONCE:
594 updateTasksOnce.clear();
596 case UpdateTaskKind::UPDATE_ON_GET:
597 updateTasksOnGet.clear();
599 case UpdateTaskKind::UPDATE_ON_SET:
600 updateTasksOnSet.clear();
602 case UpdateTaskKind::UPDATE_ON_SIMULATION_STEP:
611 updateTasksOnce.clear();
612 updateTasksOnGet.clear();
613 updateTasksOnSet.clear();
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();
623 if (reference->isStatic()) {
624 this->
addTask(UpdateTaskKind::UPDATE_ONCE,
625 AttributeUpdateTask<T, T>::make(UpdateTaskKind::UPDATE_ONCE,
628 this->
addTask(UpdateTaskKind::UPDATE_ON_GET,
629 AttributeUpdateTask<T, T>::make(
630 UpdateTaskKind::UPDATE_ON_GET, getter, reference));
635 for (
typename AttributeUpdateTaskBase<T>::Ptr task : updateTasksOnGet) {
636 task->executeUpdate(this->mData);
641 virtual void set(T value)
override {
642 *this->mData = value;
643 for (
typename AttributeUpdateTaskBase<T>::Ptr task : updateTasksOnSet) {
644 task->executeUpdate(this->mData);
648 virtual T &
get()
override {
649 for (
typename AttributeUpdateTaskBase<T>::Ptr task : updateTasksOnGet) {
650 task->executeUpdate(this->mData);
655 virtual bool isStatic()
const override {
return false; }
663 deps->insert(this->shared_from_this());
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());
671 for (
typename AttributeUpdateTaskBase<T>::Ptr task : updateTasksOnGet) {
672 AttributeBase::List taskDeps = task->getDependencies();
673 newDeps.insert(taskDeps.begin(), taskDeps.end());
676 for (
auto dependency : newDeps) {
677 dependency->appendDependencies(deps);
694template <
typename T>
struct hash<CPS::AttributePointer<T>> {
696 return std::hash<std::shared_ptr<T>>()(x.getPtr());
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
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)
virtual void setReference(typename Attribute< T >::Ptr reference) override
virtual void appendDependencies(AttributeBase::Set *deps) override
void clearTasks(UpdateTaskKind kind)
virtual void set(T value) override
virtual std::shared_ptr< T > asRawPointer() override
virtual bool isStatic() const override
virtual T & get() override
const std::type_info & getType() override
Get the type of this attribute.
T & operator*()
User-defined dereference operator.
AttributePointer< Attribute< T > > deriveScaled(T scale)
AttributePointer< Attribute< Real > > deriveImag()
AttributePointer< Attribute< Real > > derivePhase()
AttributePointer< Attribute< U > > deriveCoeff(typename CPS::MatrixVar< U >::Index row, typename CPS::MatrixVar< U >::Index column)
virtual std::shared_ptr< T > asRawPointer()=0
AttributePointer< Attribute< Real > > deriveReal()
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....
AttributeBase::Ptr cloneValueOntoNewAttribute() override
Generates a new attribute of the same type and copies the current value in the heap....
AttributePointer< Attribute< Real > > deriveMag()
bool copyValue(AttributeBase::Ptr copyFrom) override
Copy the attribute value of copyFrom onto this attribute.
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())
virtual void set(T value) override
virtual std::shared_ptr< T > asRawPointer() override
virtual void appendDependencies(AttributeBase::Set *deps) override
virtual void setReference(typename Attribute< T >::Ptr reference) override
virtual bool isStatic() const override
virtual T & get() override
virtual AttributeBase::List getDependencies() override