PLaSK library

Loading...
Searching...
No Matches
providerfor.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#ifndef PLASK__PROVIDERFOR_H
15#define PLASK__PROVIDERFOR_H
16
22#include "provider.hpp"
23#include "../utils/stl.hpp" // VariadicTemplateTypesHolder
24
25#include "../mesh/transformed.hpp"
26#include "../mesh/rectangular_spline.hpp"
27
28 namespace plask {
29
34 enum PropertyType {
35 SINGLE_VALUE_PROPERTY = 0,
36 MULTI_VALUE_PROPERTY = 1,
37 FIELD_PROPERTY = 2,
38 MULTI_FIELD_PROPERTY = 3
39};
40
41 template <PropertyType prop_type>
42 struct PropertyTypeToProviderName {
43 static constexpr const char* value = "undefined";
44};
45
46 template <>
47 struct PropertyTypeToProviderName<SINGLE_VALUE_PROPERTY> {
48 static constexpr const char* value = "undefined value";
49};
50
51 template <>
52 struct PropertyTypeToProviderName<MULTI_VALUE_PROPERTY> {
53 static constexpr const char* value = "undefined value";
54};
55
56 template <>
57 struct PropertyTypeToProviderName<FIELD_PROPERTY> {
58 static constexpr const char* value = "undefined field";
59};
60
61 template <>
62 struct PropertyTypeToProviderName<MULTI_FIELD_PROPERTY> {
63 static constexpr const char* value = "undefined field";
64};
65
79 template <PropertyType _propertyType, typename _ValueType2D, typename _ValueType3D, typename... _ExtraParams>
80 struct Property {
82 static const PropertyType propertyType = _propertyType;
83
85 typedef _ValueType2D ValueType2D;
86
88 typedef _ValueType3D ValueType3D;
89
91 static constexpr const char* NAME = PropertyTypeToProviderName<_propertyType>::value;
92
94 static inline ValueType2D getDefaultValue2D() { return ValueType2D(); }
95
97 static inline ValueType3D getDefaultValue3D() { return ValueType3D(); }
98
100 typedef VariadicTemplateTypesHolder<_ExtraParams...> ExtraParams;
101
103 static constexpr bool hasUniqueValueType = false;
104
105};
106
107 template <PropertyType _propertyType, typename _ValueType, typename... _ExtraParams>
108 struct Property<_propertyType, _ValueType, _ValueType, _ExtraParams...> {
110 static const PropertyType propertyType = _propertyType;
111
113 typedef _ValueType ValueType;
114
116 typedef _ValueType ValueType2D;
117
119 typedef _ValueType ValueType3D;
120
122 static constexpr const char* NAME = PropertyTypeToProviderName<_propertyType>::value;
123
125 static inline ValueType getDefaultValue() { return ValueType(); }
126
128 typedef VariadicTemplateTypesHolder<_ExtraParams...> ExtraParams;
129
131 static constexpr bool hasUniqueValueType = true;
132
138 static const ValueType2D& value3Dto2D(const ValueType3D& v) { return v; }
139
145 static const ValueType3D& value2Dto3D(const ValueType2D& v) { return v; }
146
152 static const ValueType2D& value3Dto2Dcyl(const ValueType3D& v, const Vec<3, double>&) { return v; }
153
159 static const ValueType3D& value2Dto3Dcyl(const ValueType2D& v, const Vec<3, double>&) { return v; }
160};
161
162
164 template <typename PropertyTag, int DIM, bool hasUniqueValueType>
165 struct PropertyAtDimImpl {};
166
168 template <typename PropertyTag>
169 struct PropertyAtDimImpl<PropertyTag, 2, true> {
170 typedef typename PropertyTag::ValueType2D ValueType;
171
172 static ValueType getDefaultValue() { return PropertyTag::getDefaultValue(); }
173
174 template <typename MeshT>
175 static LazyData<ValueType> convertLazyData(const LazyData<ValueType>& src, const shared_ptr<MeshT>&) { return src; }
176};
177
178 template <typename PropertyTag>
179 struct PropertyAtDimImpl<PropertyTag, 2, false> {
180 typedef typename PropertyTag::ValueType2D ValueType;
181
182 static ValueType getDefaultValue() { return PropertyTag::getDefaultValue2D(); }
183
184 static LazyData<ValueType> convertLazyData(const LazyData<ValueType>& src) { return src; }
185
186 template <typename MeshT>
187 static LazyData<ValueType> convertLazyData(const LazyData<typename PropertyTag::ValueType3D>& src, const shared_ptr<MeshT>&) {
188 return LazyData<ValueType>(src.size(), [src](std::size_t i) { return PropertyTag::value3Dto2D(src[i]); });
189 }
190};
191
193 template <typename PropertyTag>
194 struct PropertyAtDimImpl<PropertyTag, 3, true> {
195 typedef typename PropertyTag::ValueType3D ValueType;
196
197 static ValueType getDefaultValue() { return PropertyTag::getDefaultValue(); }
198
199 template <typename MeshT>
200 static LazyData<ValueType> convertLazyData(const LazyData<ValueType>& src, const shared_ptr<MeshT>&) { return src; }
201};
202
203 template <typename PropertyTag>
204 struct PropertyAtDimImpl<PropertyTag, 3, false> {
205 typedef typename PropertyTag::ValueType3D ValueType;
206
207 static ValueType getDefaultValue() { return PropertyTag::getDefaultValue3D(); }
208
209 static LazyData<ValueType> convertLazyData(const LazyData<ValueType>& src) { return src; }
210
211 template <typename MeshT>
212 static LazyData<ValueType> convertLazyData(const LazyData<typename PropertyTag::ValueType2D>& src, const shared_ptr<MeshT>&) {
213 return LazyData<ValueType>(src.size(), [src](std::size_t i) { return PropertyTag::value2Dto3D(src[i]); });
214 }
215};
216
217 template <typename PropertyTag, int dim>
218 using PropertyAtDim = PropertyAtDimImpl<PropertyTag, dim, PropertyTag::hasUniqueValueType>;
219
220
221 template <typename PropertyTag, typename Space, typename SrcSpace, bool hasUniqueValueType>
222 struct PropertyAtImpl: public PropertyAtDimImpl<PropertyTag, Space::DIM, hasUniqueValueType> {};
223
224 template <typename PropertyTag>
225 struct PropertyAtImpl<PropertyTag, Geometry3D, Geometry2DCylindrical, false>: public PropertyAtDimImpl<PropertyTag, 3, false> {
226 typedef typename PropertyTag::ValueType3D ValueType;
227
228 static LazyData<ValueType> convertLazyData(const LazyData<typename PropertyTag::ValueType2D>& src, const shared_ptr<CylReductionTo2DMesh>& mesh) {
229 return LazyData<ValueType>(src.size(), [src, mesh](std::size_t i) { return PropertyTag::value2Dto3Dcyl(src[i], mesh->rVector(i)); });
230 }
231};
232
233 template <typename PropertyTag>
234 struct PropertyAtImpl<PropertyTag, Geometry2DCylindrical, Geometry3D, false>: public PropertyAtDimImpl<PropertyTag, 2, false> {
235 typedef typename PropertyTag::ValueType2D ValueType;
236
237 static LazyData<ValueType> convertLazyData(const LazyData<typename PropertyTag::ValueType3D>& src, const shared_ptr<PointsOnCircleMeshExtend>& mesh) {
238 return LazyData<ValueType>(src.size(), [src, mesh](std::size_t i) { return PropertyTag::value3Dto2Dcyl(src[i], mesh->rVector(i)); });
239 }
240};
249 template <typename PropertyTag, typename Space, typename SrcSpace = void>
250 struct PropertyAt: public PropertyAtImpl<PropertyTag, Space, SrcSpace, PropertyTag::hasUniqueValueType> {};
251
252 template <typename PropertyTag>
253 struct PropertyAt<PropertyTag, void>: public PropertyAtDim<PropertyTag, 2> {
254 static_assert(PropertyTag::hasUniqueValueType, "Space was not given in PropertyAt for property which has different types of values in 2D and 3D.");
255};
256
257
264 template<typename ValueT=double, typename... _ExtraParams>
265 struct SingleValueProperty: public Property<SINGLE_VALUE_PROPERTY, ValueT, ValueT, _ExtraParams...> {};
266
273 template<typename ValueT=double, typename... _ExtraParams>
274 struct MultiValueProperty: public Property<MULTI_VALUE_PROPERTY, ValueT, ValueT, _ExtraParams...> {
276 typedef size_t EnumType;
277};
278
285 template<typename ValueT=double, typename... _ExtraParams>
286 struct FieldProperty: public Property<FIELD_PROPERTY, ValueT, ValueT, _ExtraParams...> {};
287
294 template<typename ValueT = double, typename... _ExtraParams>
295 struct MultiFieldProperty: public Property<MULTI_FIELD_PROPERTY, ValueT, ValueT, _ExtraParams...> {
297 typedef size_t EnumType;
298};
299
310 template<typename ValueT_2D, typename ValueT_3D, typename... _ExtraParams>
311 struct CustomFieldProperty: public Property<FIELD_PROPERTY, ValueT_2D, ValueT_3D, _ExtraParams...> {};
312
323 template<typename ValueT_2D, typename ValueT_3D, typename... _ExtraParams>
324 struct MultiCustomFieldProperty: public Property<MULTI_FIELD_PROPERTY, ValueT_2D, ValueT_3D, _ExtraParams...> {
326 typedef size_t EnumType;
327};
328
339 template<typename ValueT = double, typename... _ExtraParams>
340 struct VectorFieldProperty: public Property<FIELD_PROPERTY, Vec<2, ValueT>, Vec<3, ValueT>, _ExtraParams...> {
341
347 static Vec<2, ValueT> value3Dto2D(const Vec<3, ValueT>& v) { return vec<2>(v); }
348
354 static Vec<3, ValueT> value2Dto3D(const Vec<2, ValueT>& v) { return vec(v, ValueT()); }
355
361 static const Vec<2, ValueT> value3Dto2Dcyl(const Vec<3, ValueT>& v, const Vec<3, double>& p) {
362 // v * p / |p|, v.c2
363 return vec(::plask::fma(v.c0, p.c0, v.c1 * p.c1) / std::hypot(p.c0, p.c1), v.c2);
364 }
365
371 static const Vec<3, ValueT> value2Dto3Dcyl(const Vec<2, ValueT>& v, const Vec<3, double>& p) {
372 double r = std::hypot(p.c0, p.c1);
373 return vec(v.c0 * p.c0/r, v.c0 * p.c1/r, v.c1);
374 }
375};
376
387 template<typename ValueT = double, typename... _ExtraParams>
388 struct MultiVectorFieldProperty: public Property<MULTI_FIELD_PROPERTY, Vec<2, ValueT>, Vec<3, ValueT>, _ExtraParams...> {
389
391 typedef size_t EnumType;
392
398 static Vec<2, ValueT> value3Dto2D(const Vec<3, ValueT>& v) { return vec<2>(v); }
399
405 static Vec<3, ValueT> value2Dto3D(const Vec<2, ValueT>& v) { return vec(v, ValueT()); }
406};
407
414 typedef FieldProperty<double> ScalarFieldProperty;
415
422 typedef MultiFieldProperty<double> MultiScalarFieldProperty;
423
424
425
426
427
433 template <typename PropertyT, PropertyType propertyType, typename spaceType, typename VariadicTemplateTypesHolder>
434 struct ProviderImpl {};
435
446 template <typename PropertyT, typename SpaceT = void>
447 struct ProviderFor: public ProviderImpl<PropertyT, PropertyT::propertyType, SpaceT, typename PropertyT::ExtraParams> {
448
449 typedef PropertyT PropertyTag;
450 typedef SpaceT SpaceType;
451
453 template<typename ...Args>
454 ProviderFor(Args&&... params)
455 : ProviderImpl<PropertyT, PropertyT::propertyType, SpaceT, typename PropertyT::ExtraParams>(std::forward<Args>(params)...) {
456 }
457
458};
459//TODO redefine ProviderFor using template aliases (does not work with GCC)
460//template <typename PropertyT, typename SpaceT = void>
461//using ProviderFor = ProviderImpl<PropertyT, PropertyT::propertyType, SpaceT, typename PropertyT::ExtraParams>;
462
463
464
465
471 template <typename PropertyT, typename SpaceT = void>
472 struct ReceiverFor: public Receiver<ProviderImpl<PropertyT, PropertyT::propertyType, SpaceT, typename PropertyT::ExtraParams>> {
473 ReceiverFor & operator=(const ReceiverFor&) = delete;
474 ReceiverFor(const ReceiverFor&) = delete;
475 ReceiverFor() = default;
476
477 typedef PropertyT PropertyTag;
478 typedef SpaceT SpaceType;
479 typedef typename PropertyAt<PropertyT, SpaceT>::ValueType ValueType;
480
488 ReceiverFor<PropertyT, SpaceT>& operator=(const ValueType& v) {
489 this->setConstValue(v);
490 return *this;
491 }
492
497 template <typename... Args, PropertyType propertyType = PropertyTag::propertyType>
498 typename std::enable_if<propertyType == SINGLE_VALUE_PROPERTY>::type
499 setValue(Args&&... value) {
500 this->setProvider(new typename ProviderFor<PropertyTag>::WithValue(std::forward<Args>(value)...), true);
501 }
502
507 template <typename... Args, PropertyType propertyType = PropertyTag::propertyType>
508 typename std::enable_if<propertyType == MULTI_VALUE_PROPERTY>::type
509 setValue(const ValueType& value) {
510 this->setProvider(new typename ProviderFor<PropertyTag>::WithValue(value), true);
511 }
512
517 template <typename... Args, PropertyType propertyType = PropertyTag::propertyType>
518 typename std::enable_if<propertyType == MULTI_VALUE_PROPERTY>::type
519 setValues(Args&&... value) {
520 this->setProvider(new typename ProviderFor<PropertyTag>::WithValue(std::forward<Args>(value)...), true);
521 }
522
528 template <typename MeshT, PropertyType propertyType = PropertyTag::propertyType>
529 typename std::enable_if<propertyType == FIELD_PROPERTY || propertyType == MULTI_FIELD_PROPERTY>::type
530 setValue(DataVector<const ValueType> data, shared_ptr<MeshT> mesh) {
531 if (data.size() != mesh->size())
532 throw BadMesh("receiverFor::setValues()", "Mesh size ({1}) and data size ({0}) do not match", data.size(), mesh->size());
533 this->setProvider(new typename ProviderFor<PropertyTag, SpaceType>::template WithValue<MeshT>(data, mesh), true);
534 }
535
540 template <typename Iterator, PropertyType propertyType = PropertyTag::propertyType>
541 typename std::enable_if<propertyType == MULTI_FIELD_PROPERTY>::type
542 setValues(Iterator begin, Iterator end) {
543 this->setProvider(new typename ProviderFor<PropertyTag, SpaceType>::ConstProviderType(begin, end), true);
544 }
545
551 template <typename MeshT, typename Iterator, PropertyType propertyType = PropertyTag::propertyType>
552 typename std::enable_if<propertyType == MULTI_FIELD_PROPERTY>::type
553 setValues(Iterator begin, Iterator end, shared_ptr<MeshT> mesh) {
554 size_t i = 0;
555 for (Iterator it = begin; it != end; ++it, ++i )
556 if (*it.size() != mesh->size())
557 throw BadMesh("receiverFor::setValues()", "Mesh size ({1}) and data[{2}] size ({0}) do not match", it->size(), mesh->size(), i);
558 this->setProvider(new typename ProviderFor<PropertyTag, SpaceType>::template WithValue<MeshT>(begin, end, mesh), true);
559 }
560
566 template <typename MeshT, PropertyType propertyType = PropertyTag::propertyType>
567 typename std::enable_if<propertyType == MULTI_FIELD_PROPERTY>::type
568 setValue(const std::vector<DataVector<const ValueType>>& data, shared_ptr<MeshT> mesh) {
569 for (auto it = data.begin(); it != data.end(); ++it)
570 if (it->size() != mesh->size())
571 throw BadMesh("receiverFor::setValues()", "Mesh size ({1}) and data[{2}] size ({0}) do not match", it->size(), mesh->size(), it-data.begin());
572 this->setProvider(new typename ProviderFor<PropertyTag, SpaceType>::template WithValue<MeshT>(data.begin(), data.end(), mesh), true);
573 }
574
578 template <typename GeometryT = SpaceT>
579 typename std::enable_if<std::is_same<GeometryT, Geometry3D>::value>::type
580 setTransformedProvider(ProviderFor<PropertyT, Geometry2DCartesian>* provider) {
581 this->setProvider(new typename ProviderFor<PropertyT, GeometryT>::template Transform<ReductionTo2DMesh>(provider), true);
582 }
583
587 template <typename GeometryT = SpaceT>
588 typename std::enable_if<std::is_same<GeometryT, Geometry3D>::value>::type
589 setTransformedProvider(ProviderFor<PropertyT, Geometry2DCylindrical>* provider) {
590 this->setProvider(new typename ProviderFor<PropertyT, GeometryT>::template Transform<CylReductionTo2DMesh>(provider), true);
591 }
592
596 template <typename GeometryT = SpaceT>
597 typename std::enable_if<std::is_same<GeometryT, Geometry2DCartesian>::value>::type
598 setTransformedProvider(ProviderFor<PropertyT, Geometry3D>* provider) {
599 this->setProvider(new typename ProviderFor<PropertyT, GeometryT>::template Transform<CartesianMesh2DTo3D>(provider), true);
600 }
601
605 template <typename GeometryT = SpaceT>
606 typename std::enable_if<std::is_same<GeometryT, Geometry2DCylindrical>::value>::type
607 setTransformedProvider(ProviderFor<PropertyT, Geometry3D>* provider) {
608 this->setProvider(new typename ProviderFor<PropertyT, GeometryT>::template Transform<PointsOnCircleMeshExtend>(provider), true);
609 }
610
614 template <PropertyType propertyType = PropertyTag::propertyType>
615 typename std::enable_if<propertyType == MULTI_VALUE_PROPERTY || propertyType == MULTI_FIELD_PROPERTY, size_t>::type
616 size() const {
617 this->ensureHasProvider();
618 return this->provider->size();
619 }
620
621 static_assert(!(std::is_same<SpaceT, void>::value && (PropertyT::propertyType == FIELD_PROPERTY || PropertyT::propertyType == MULTI_FIELD_PROPERTY)),
622 "Receivers for fields properties require SpaceT. Use ReceiverFor<propertyTag, SpaceT>, where SpaceT is one of the classes defined in <plask/geometry/space.h>.");
623 static_assert(!(!std::is_same<SpaceT, void>::value && (PropertyT::propertyType == SINGLE_VALUE_PROPERTY || PropertyT::propertyType == MULTI_VALUE_PROPERTY)),
624 "Receivers for single value properties doesn't need SpaceT. Use ReceiverFor<propertyTag> (without second template parameter).");
625
627 // * Set provider to of derived type
628 // * \param provider new provider
629 // */
630 //template <typename OtherProvidersT>
631 //void setProvider(OtherProviderT* provider) {
632 // auto provider = new ProviderFor<OtherProviderT::PropertyTag>::Delegate([&provider](){})
633 //}
634
635};
636//struct ReceiverFor: public Receiver< ProviderFor<PropertyT> > {};
637
645 template <typename PropertyT, typename SpaceT, typename... _ExtraParams>
646 struct ProviderImpl<PropertyT, SINGLE_VALUE_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >: public SingleValueProvider<typename PropertyAt<PropertyT, SpaceT>::ValueType, _ExtraParams...> {
647
648 typedef PropertyT PropertyTag;
649 typedef SpaceT SpaceType;
650
651 static constexpr const char* NAME = PropertyT::NAME;
652 const char* name() const override { return NAME; }
653
654 static_assert(std::is_same<SpaceT, void>::value,
655 "Providers for single value properties doesn't need SpaceT. Use ProviderFor<propertyTag> (without second template parameter).");
656
657 typedef typename PropertyAt<PropertyT, SpaceT>::ValueType ValueType;
658
660 typedef typename SingleValueProvider<ValueType>::ProvidedType ProvidedType;
661
668 struct WithDefaultValue: public ProviderFor<PropertyT, SpaceT> {
669
671 typedef ValueType ProvidedType;
672
674 ProvidedType value;
675
677 template<typename ...Args>
678 WithDefaultValue(Args&&... params): value(std::forward<Args>(params)...) {}
679
685 WithDefaultValue& operator=(const ValueType& v) {
686 value = v;
687 return *this;
688 }
689
694 ProvidedType operator()(_ExtraParams...) const override { return value; }
695 };
696
704 struct WithValue: public ProviderFor<PropertyT, SpaceT> {
705
707 typedef ValueType ProvidedType;
708
710 plask::optional<ProvidedType> value;
711
713 void invalidate() { value.reset(); }
714
719 bool hasValue() const { return bool(value); }
720
722 void ensureHasValue() const {
723 if (!hasValue()) throw NoValue(NAME);
724 }
725
727 WithValue(const ProvidedType& value): value(value) {}
728
730 WithValue(ProvidedType&& value): value(value) {}
731
733 WithValue() {}
734
740 WithValue& operator=(const ValueType& v) {
741 value.reset(v);
742 return *this;
743 }
744
750 ProvidedType operator()(_ExtraParams...) const override {
751 ensureHasValue();
752 return *value;
753 }
754 };
755
759 typedef PolymorphicDelegateProvider<ProviderFor<PropertyT, SpaceT>, ProvidedType(_ExtraParams...)> Delegate;
760
762 typedef WithValue ConstProviderType;
763
764};
765
773 template <typename PropertyT, typename SpaceT, typename... _ExtraParams>
774 struct ProviderImpl<PropertyT, MULTI_VALUE_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >: public MultiValueProvider<typename PropertyAt<PropertyT, SpaceT>::ValueType, typename PropertyT::EnumType, _ExtraParams...> {
775
776 typedef PropertyT PropertyTag;
777 typedef SpaceT SpaceType;
778
779 typedef typename PropertyT::EnumType EnumType;
780
781 static constexpr const char* NAME = PropertyT::NAME;
782 const char* name() const override { return NAME; }
783
784 static_assert(std::is_same<SpaceT, void>::value,
785 "Providers for single value properties doesn't need SpaceT. Use ProviderFor<propertyTag> (without second template parameter).");
786
787 typedef typename PropertyAt<PropertyT, SpaceT>::ValueType ValueType;
788
790 typedef typename MultiValueProvider<ValueType, EnumType>::ProvidedType ProvidedType;
791
798 struct WithDefaultValue: public ProviderFor<PropertyT, SpaceT> {
799
801 typedef ValueType ProvidedType;
802
804 ProvidedType default_value;
805
807 std::vector<ProvidedType> values;
808
810 WithDefaultValue(const std::initializer_list<ProvidedType>& values, const ProvidedType& defval=ProvidedType()): default_value(defval), values(values) {}
811
813 template <typename Iterator>
814 explicit WithDefaultValue(const Iterator& begin, const Iterator& end, const ProvidedType& defval=ProvidedType()): default_value(defval), values(begin, end) {}
815
817 WithDefaultValue(const ProvidedType& defval=ProvidedType()): default_value(defval) {}
818
824 ProvidedType& operator[](size_t n) {
825 size_t n0 = values.size();
826 if (n > n0) {
827 values.resize(n);
828 for (size_t i = n0; i != n; ++i) values[i] = default_value;
829 }
830 return values[n];
831 }
832
837 void resize(size_t n) {
838 size_t n0 = values.size();
839 values.resize(n);
840 if (n > n0) {
841 for (size_t i = n0; i != n; ++i) values[i] = default_value;
842 }
843 }
844
849 size_t size() const override {
850 return values.size();
851 }
852
857 ProvidedType operator()(EnumType num, _ExtraParams...) const override {
858 size_t n(num);
859 if (n > values.size()) return default_value;
860 return values[n];
861 }
862 };
863
871 struct WithValue: public ProviderFor<PropertyT, SpaceT> {
872
874 typedef ValueType ProvidedType;
875
877 std::vector<ProvidedType> values; //TODO powinien trzymać DataVectory
878
880 void invalidate() { values.clear(); }
881
886 void ensureIndex(size_t n) const {
887 if (n >= values.size()) throw NoValue(NAME);
888 }
889
891 explicit WithValue(const ProvidedType& value): values({value}) {}
892
894 explicit WithValue(ProvidedType&& value): values({value}) {}
895
897 WithValue(const std::initializer_list<ProvidedType>& values): values(values) {}
898
900 template <typename Iterator>
901 explicit WithValue(const Iterator& begin, const Iterator& end): values(begin, end) {}
902
904 WithValue() {}
905
911 ProvidedType& operator[](size_t n) {
912 if (n > values.size()) throw BadInput(NAME, "Wrong value index");
913 return values[n];
914 }
915
920 void push_back(const ProvidedType& value) {
921 values.push_back(value);
922 }
923
928 template <typename... Args>
929 void emplate_back(Args&&... args) {
930 values.emplace_back(std::forward<Args>(args)...);
931 }
932
937 size_t size() const override {
938 return values.size();
939 }
940
947 ProvidedType operator()(EnumType n, _ExtraParams...) const override {
948 ensureIndex(n);
949 return values[n];
950 }
951 };
952
956 struct Delegate: public PolymorphicDelegateProvider<ProviderFor<PropertyT, SpaceT>, ProvidedType(EnumType, _ExtraParams...)> {
957
958 typedef PolymorphicDelegateProvider<ProviderFor<PropertyT, SpaceT>, ProvidedType(EnumType, _ExtraParams...)> Base;
959
960 std::function<size_t()> sizeGetter;
961
966 template<typename Functor, typename Sizer>
967 Delegate(Functor functor, Sizer sizer): Base(functor), sizeGetter(sizer) {}
968
975 template<typename ClassType, typename MemberType>
976 Delegate(ClassType* object, MemberType member, size_t (ClassType::*sizer)()const): Base(object, member),
977 sizeGetter([object, sizer]() { return (object->*sizer)(); }) {}
978
985 template<typename ClassType, typename MemberType>
986 Delegate(ClassType* object, MemberType member, size_t (ClassType::*sizer)()): Base(object, member),
987 sizeGetter([object, sizer]() { return (object->*sizer)(); }) {}
988
993 template<typename Functor>
994 Delegate(Functor functor): Base(functor), sizeGetter([]{return PropertyT::NUM_VALS;}) {}
995
1002 template<typename ClassType, typename MemberType>
1003 Delegate(ClassType* object, MemberType member): Base(object, member), sizeGetter([]{return PropertyT::NUM_VALS;}) {}
1004
1005 size_t size() const override {
1006 return sizeGetter();
1007 }
1008
1009 };
1010
1012 typedef WithValue ConstProviderType;
1013
1014};
1015
1019 template <typename PropertyT, typename SpaceT, typename... _ExtraParams>
1020 struct ProviderImpl<PropertyT, FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >: public FieldProvider<typename PropertyAt<PropertyT, SpaceT>::ValueType, SpaceT, _ExtraParams...> {
1021
1022 typedef PropertyT PropertyTag;
1023 typedef SpaceT SpaceType;
1024
1025 static constexpr const char* NAME = PropertyT::NAME;
1026 const char* name() const override { return NAME; }
1027
1028 static_assert(!std::is_same<SpaceT, void>::value,
1029 "Providers for fields properties require SpaceT. Use ProviderFor<propertyTag, SpaceT>, where SpaceT is one of the class defined in plask/geometry/space.h.");
1030
1031 typedef typename PropertyAt<PropertyT, SpaceT>::ValueType ValueType;
1032
1034 typedef typename FieldProvider<ValueType, SpaceT>::ProvidedType ProvidedType;
1035
1041 template <typename MeshType>
1042 struct WithValue: public ProviderFor<PropertyT, SpaceT> {
1043
1045 typedef shared_ptr<MeshType> MeshPointerType;
1046
1048 typedef typename ProviderImpl<PropertyT, FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >::ProvidedType ProvidedType;
1049
1051 typedef DataVector<const ValueType> HeldType;
1052
1054 HeldType values;
1055
1056 protected:
1057
1059 MeshPointerType mesh_ptr;
1060
1062 InterpolationMethod default_interpolation;
1063
1064 public:
1065
1070 auto getMesh() -> decltype(*mesh_ptr) { return *mesh_ptr; }
1071
1076 auto getMesh() const -> decltype(*mesh_ptr) { return *mesh_ptr; }
1077
1082 void setMesh(MeshPointerType mesh_p) {
1083 if (mesh_ptr) mesh_ptr->changedDisconnectMethod(this, &ProviderImpl<PropertyT, FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >::WithValue<MeshType>::onMeshChange);
1084 mesh_ptr = mesh_p;
1085 mesh_ptr->changedConnectMethod(this, &ProviderImpl<PropertyT, FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...>>::WithValue<MeshType>::onMeshChange);
1086 }
1087
1089 void invalidate() { values.reset(); }
1090
1092 void allocate() { values.reset(mesh_ptr->size); }
1093
1098 bool hasValue() const { return values.data() != nullptr; }
1099
1101 void ensureHasValue() const {
1102 if (!hasValue()) throw NoValue(this->name());
1103 }
1104
1109 bool hasCorrectValue() const { return hasValue() && values.size() == mesh_ptr->size(); }
1110
1112 void ensureHasCorrectValue() const {
1113 if (!hasValue()) throw NoValue(this->name());
1114 if (values.size() != mesh_ptr->size())
1115 throw BadMesh("provider::WithValue", "Mesh size ({1}) and values size ({0}) do not match", values.size(), mesh_ptr->size());
1116 }
1117
1123 void onMeshChange(const Mesh::Event& PLASK_UNUSED(evt)) {
1124 this->invalidate();
1125 }
1126
1127
1133 explicit WithValue(HeldType values, MeshPointerType mesh_ptr = nullptr, InterpolationMethod default_interpolation = INTERPOLATION_LINEAR)
1134 : values(values), mesh_ptr(mesh_ptr), default_interpolation(default_interpolation) {
1135 if (mesh_ptr) mesh_ptr->changedConnectMethod(this, &ProviderImpl<PropertyT, FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...>>::WithValue<MeshType>::onMeshChange);
1136 }
1137
1142 explicit WithValue(MeshPointerType mesh_ptr = nullptr, const InterpolationMethod& default_interpolation = INTERPOLATION_LINEAR)
1143 : mesh_ptr(mesh_ptr), default_interpolation(default_interpolation) {
1144 if (mesh_ptr) mesh_ptr->changedConnectMethod(this, &ProviderImpl<PropertyT, FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...>>::WithValue<MeshType>::onMeshChange);
1145 }
1146
1147 ~WithValue() {
1148 if (mesh_ptr) mesh_ptr->changedDisconnectMethod(this, &ProviderImpl<PropertyT, FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >::WithValue<MeshType>::onMeshChange);
1149 }
1150
1155 ProvidedType& operator()() {
1156 ensureHasCorrectValue();
1157 return values;
1158 }
1159
1164 const ProvidedType& operator()() const {
1165 ensureHasCorrectValue();
1166 return values;
1167 }
1168
1175 ProvidedType operator()(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, _ExtraParams..., InterpolationMethod method = INTERPOLATION_DEFAULT) const override {
1176 ensureHasCorrectValue();
1177 if (method == INTERPOLATION_DEFAULT) method = default_interpolation;
1178 return interpolate(mesh_ptr, values, dst_mesh, method);
1179 }
1180 };
1181
1185 template <typename MeshTransform>
1186 struct Transform: public ProviderFor<PropertyT, SpaceT> {
1187
1188 static_assert(std::is_same<SpaceT, typename MeshTransform::SourceGeometry>::value, "Bad transform source mesh type");
1189
1191 typedef typename ProviderImpl<PropertyT, FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >::ProvidedType ProvidedType;
1192
1194 ReceiverFor<PropertyT, typename MeshTransform::TargetGeometry> receiver;
1195
1196 Transform() {
1197 receiver.changedConnectMethod(this, &Transform::_receiverChanged);
1198 }
1199
1200 Transform(ProviderFor<PropertyT, typename MeshTransform::TargetGeometry>* provider) {
1201 receiver.changedConnectMethod(this, &Transform::_receiverChanged);
1202 receiver.setProvider(provider);
1203 }
1204
1205 ~Transform() {
1206 receiver.changedDisconnectMethod(this, &Transform::_receiverChanged);
1207 }
1208
1209 ProvidedType operator()(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, _ExtraParams...params, InterpolationMethod method = INTERPOLATION_DEFAULT) const override {
1210 auto trans_mesh(make_shared<MeshTransform>(dst_mesh));
1211 return PropertyAt<PropertyT, SpaceT, typename MeshTransform::TargetGeometry>::convertLazyData(receiver(trans_mesh, params..., method), trans_mesh);
1212 }
1213
1214 private:
1215
1216 void _receiverChanged(ReceiverBase&, ReceiverBase::ChangeReason) {
1217 this->fireChanged();
1218 }
1219
1220 };
1221
1225 typedef PolymorphicDelegateProvider<ProviderFor<PropertyT, SpaceT>, ProvidedType(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, _ExtraParams..., InterpolationMethod method)> Delegate;
1226
1234 struct ConstProviderType: public ProviderFor<PropertyT, SpaceT> {
1235
1236 typedef typename ProviderImpl<PropertyT, FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...>>::ProvidedType ProvidedType;
1237
1239 ValueType value;
1240
1241 //ConstProviderType(const ValueT& value): value(value) {}
1242
1247 template<typename ...Args>
1248 ConstProviderType(Args&&... params): value(std::forward<Args>(params)...) {}
1249
1253 ProvidedType operator()(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, _ExtraParams..., InterpolationMethod) const override {
1254 return ProvidedType(dst_mesh->size(), value);
1255 }
1256 };
1257};
1258
1262 template <typename PropertyT, typename SpaceT, typename... _ExtraParams>
1263 struct ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >: public MultiFieldProvider<typename PropertyAt<PropertyT, SpaceT>::ValueType, SpaceT, typename PropertyT::EnumType, _ExtraParams...> {
1264
1265 typedef PropertyT PropertyTag;
1266 typedef SpaceT SpaceType;
1267
1268 typedef typename PropertyT::EnumType EnumType;
1269
1270 static constexpr const char* NAME = PropertyT::NAME;
1271 const char* name() const override { return NAME; }
1272
1273 static_assert(!std::is_same<SpaceT, void>::value,
1274 "Providers for fields properties require SpaceT. Use ProviderFor<propertyTag, SpaceT>, where SpaceT is one of the class defined in plask/geometry/space.h.");
1275
1276 typedef typename PropertyAt<PropertyT, SpaceT>::ValueType ValueType;
1277
1279 typedef typename MultiFieldProvider<ValueType, SpaceT, EnumType>::ProvidedType ProvidedType;
1280
1286 template <typename MeshType>
1287 struct WithValue: public ProviderFor<PropertyT, SpaceT> {
1288
1290 typedef shared_ptr<MeshType> MeshPointerType;
1291
1293 typedef typename ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >::ProvidedType ProvidedType;
1294
1296 typedef DataVector<const ValueType> HeldType;
1297
1299 std::vector<HeldType> values;
1300
1301 protected:
1302
1304 MeshPointerType mesh_ptr;
1305
1307 InterpolationMethod default_interpolation;
1308
1309 public:
1310
1315 auto getMesh() -> decltype(*mesh_ptr) { return *mesh_ptr; }
1316
1321 auto getMesh() const -> decltype(*mesh_ptr) { return *mesh_ptr; }
1322
1327 void setMesh(MeshPointerType mesh_p) {
1328 if (mesh_ptr) mesh_ptr->changedDisconnectMethod(this, &ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >::WithValue<MeshType>::onMeshChange);
1329 mesh_ptr = mesh_p;
1330 mesh_ptr->changedConnectMethod(this, &ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...>>::WithValue<MeshType>::onMeshChange);
1331 }
1332
1334 void invalidate() { values.clear(); }
1335
1339 void allocate(size_t num) {
1340 values.resize(num);
1341 for (auto& val: values) val.reset(mesh_ptr->size);
1342 }
1343
1348 void push_back(const HeldType& value) {
1349 values.push_back(value);
1350 }
1351
1356 size_t size() const override {
1357 return values.size();
1358 }
1359
1365 bool hasCorrectValue(size_t n) const {
1366 return n < values.size() && values[n].size() = mesh_ptr->size();
1367 }
1368
1373 bool hasCorrectValues() const {
1374 if (values.size() == 0) return false;
1375 for (const auto& val: values)
1376 if (val.size() != mesh_ptr->size()) return false;
1377 return true;
1378 }
1379
1384 void ensureHasCorrectValue(size_t n) const {
1385 if (n >= values.size()) throw NoValue(this->name());
1386 if (values[n].size() != mesh_ptr->size())
1387 throw BadMesh("provider::WithValue", "Mesh size ({1}) and values[{2}] size ({0}) do not match", values.size(), mesh_ptr->size(), n);
1388 }
1389
1391 void ensureHasCorrectValues() const {
1392 if (values.size() == 0) throw NoValue(this->name());
1393 for (size_t i = 0; i != values.size(); ++i)
1394 if (values[i].size() != mesh_ptr->size())
1395 throw BadMesh("provider::WithValue", "Mesh size ({1}) and values[{2}] size ({0}) do not match", values.size(), mesh_ptr->size(), i);
1396 }
1397
1403 void onMeshChange(const Mesh::Event& PLASK_UNUSED(evt)) {
1404 this->invalidate();
1405 }
1406
1407
1413 explicit WithValue(HeldType values, MeshPointerType mesh_ptr = nullptr, InterpolationMethod default_interpolation = INTERPOLATION_LINEAR)
1414 : values({values}), mesh_ptr(mesh_ptr), default_interpolation(default_interpolation) {
1415 if (mesh_ptr) mesh_ptr->changedConnectMethod(this, &ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...>>::WithValue<MeshType>::onMeshChange);
1416 }
1417
1423 explicit WithValue(const std::initializer_list<HeldType>& values, MeshPointerType mesh_ptr = nullptr, InterpolationMethod default_interpolation = INTERPOLATION_LINEAR)
1424 : values(values), mesh_ptr(mesh_ptr), default_interpolation(default_interpolation) {
1425 if (mesh_ptr) mesh_ptr->changedConnectMethod(this, &ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...>>::WithValue<MeshType>::onMeshChange);
1426 }
1427
1433 template <typename Iterator>
1434 explicit WithValue(const Iterator& begin, const Iterator& end, MeshPointerType mesh_ptr = nullptr, InterpolationMethod default_interpolation = INTERPOLATION_LINEAR)
1435 : values(begin, end), mesh_ptr(mesh_ptr), default_interpolation(default_interpolation) {
1436 if (mesh_ptr) mesh_ptr->changedConnectMethod(this, &ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...>>::WithValue<MeshType>::onMeshChange);
1437 }
1438
1443 explicit WithValue(MeshPointerType mesh_ptr = nullptr, const InterpolationMethod& default_interpolation = INTERPOLATION_LINEAR)
1444 : mesh_ptr(mesh_ptr), default_interpolation(default_interpolation) {
1445 if (mesh_ptr) mesh_ptr->changedConnectMethod(this, &ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...>>::WithValue<MeshType>::onMeshChange);
1446 }
1447
1448 ~WithValue() {
1449 if (mesh_ptr) mesh_ptr->changedDisconnectMethod(this, &ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >::WithValue<MeshType>::onMeshChange);
1450 }
1451
1457 HeldType& operator()(size_t n) {
1458 ensureHasCorrectValue(n);
1459 return values[n];
1460 }
1461
1467 const HeldType& operator()(size_t n) const {
1468 ensureHasCorrectValue(n);
1469 return values[n];
1470 }
1471
1479 ProvidedType operator()(EnumType num, shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, _ExtraParams..., InterpolationMethod method = INTERPOLATION_DEFAULT) const override {
1480 size_t n(num);
1481 ensureHasCorrectValue(n);
1482 if (method == INTERPOLATION_DEFAULT) method = default_interpolation;
1483 return interpolate(mesh_ptr, values[n], dst_mesh, method);
1484 }
1485 };
1486
1490 template <typename MeshTransform>
1491 struct Transform: public ProviderFor<PropertyT, SpaceT> {
1492
1493 static_assert(std::is_same<SpaceT, typename MeshTransform::SourceGeometry>::value, "Bad transform source mesh type");
1494
1496 typedef typename ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...> >::ProvidedType ProvidedType;
1497
1499 ReceiverFor<PropertyT, typename MeshTransform::TargetGeometry> receiver;
1500
1501 Transform() {
1502 receiver.changedConnectMethod(this, &Transform::_receiverChanged);
1503 }
1504
1505 Transform(ProviderFor<PropertyT, typename MeshTransform::TargetGeometry>* provider) {
1506 receiver.changedConnectMethod(this, &Transform::_receiverChanged);
1507 receiver.setProvider(provider);
1508 }
1509
1510 ~Transform() {
1511 receiver.changedDisconnectMethod(this, &Transform::_receiverChanged);
1512 }
1513
1518 size_t size() const override {
1519 return receiver.size();
1520 }
1521
1522
1523 ProvidedType operator()(EnumType num, shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, _ExtraParams...params, InterpolationMethod method = INTERPOLATION_DEFAULT) const override {
1524 auto trans_mesh(make_shared<MeshTransform>(dst_mesh));
1525 return PropertyAt<PropertyT, SpaceT, typename MeshTransform::TargetGeometry>::convertLazyData(receiver(num, trans_mesh, params..., method), trans_mesh);
1526 }
1527
1528 private:
1529
1530 void _receiverChanged(ReceiverBase&, ReceiverBase::ChangeReason) {
1531 this->fireChanged();
1532 }
1533
1534 };
1535
1539 struct Delegate: public PolymorphicDelegateProvider<ProviderFor<PropertyT, SpaceT>, ProvidedType(EnumType n, shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, _ExtraParams..., InterpolationMethod method)> {
1540
1541 typedef PolymorphicDelegateProvider<ProviderFor<PropertyT, SpaceT>, ProvidedType(EnumType n, shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, _ExtraParams..., InterpolationMethod method)> Base;
1542
1543 std::function<size_t()> sizeGetter;
1544
1550 template<typename Functor, typename Sizer>
1551 Delegate(Functor functor, Sizer sizer): Base(functor), sizeGetter(sizer) {}
1552
1559 template<typename ClassType, typename MemberType, typename Sizer>
1560 Delegate(ClassType* object, MemberType member, Sizer sizer): Base(object, member), sizeGetter(sizer) {}
1561
1568 template<typename ClassType, typename MemberType>
1569 Delegate(ClassType* object, MemberType member, size_t (ClassType::*sizer)()const): Base(object, member),
1570 sizeGetter([object, sizer]() { return (object->*sizer)(); }) {}
1571
1578 template<typename ClassType, typename MemberType>
1579 Delegate(ClassType* object, MemberType member, size_t (ClassType::*sizer)()): Base(object, member),
1580 sizeGetter([object, sizer]() { return (object->*sizer)(); }) {}
1581
1586 template<typename Functor>
1587 Delegate(Functor functor): Base(functor), sizeGetter([]{return PropertyT::NUM_VALS;}) {}
1588
1594 template<typename ClassType, typename MemberType, typename Sizer>
1595 Delegate(ClassType* object, MemberType member): Base(object, member), sizeGetter([]{return PropertyT::NUM_VALS;}) {}
1596
1602 template<typename ClassType, typename MemberType>
1603 Delegate(ClassType* object, MemberType member): Base(object, member), sizeGetter([]{return PropertyT::NUM_VALS;}) {}
1604
1605 size_t size() const override {
1606 return sizeGetter();
1607 }
1608
1609 };
1610
1618 struct ConstProviderType: public ProviderFor<PropertyT, SpaceT> {
1619
1620 typedef typename ProviderImpl<PropertyT, MULTI_FIELD_PROPERTY, SpaceT, VariadicTemplateTypesHolder<_ExtraParams...>>::ProvidedType ProvidedType;
1621
1623 std::vector<ValueType> values;
1624
1625 // /**
1626 // * Constructor which delegates all parameters to the vector constructor.
1627 // * @param params ValueT constructor parameters, forwarded to value
1628 // */
1629 // template<typename ...Args>
1630 // ConstProviderType(Args&&... params): values(std::forward<Args>(params)...) {}
1631
1636 ConstProviderType(const ValueType& value): values({value}) {}
1637
1642 ConstProviderType(ValueType&& value): values({std::move(value)}) {}
1643
1648 ConstProviderType(const std::initializer_list<ValueType>& values): values(values) {}
1649
1654 template <typename Iterator>
1655 explicit ConstProviderType(const Iterator& begin, const Iterator& end): values(begin, end) {}
1656
1660 ProvidedType operator()(EnumType num, shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, _ExtraParams..., InterpolationMethod) const override {
1661 if (num >= values.size()) throw BadInput(std::string("Provider for ") + PropertyT::NAME, "value number too large");
1662 return ProvidedType(dst_mesh->size(), values[num]);
1663 }
1664
1665 size_t size() const override {
1666 return values.size();
1667 }
1668 };
1669};
1670
1671} // namespace plask
1672
1673#endif // PLASK__PROVIDERFOR_H