PLaSK library

Loading...
Searching...
No Matches
combined_provider.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__COMBINATE_PROVIDERS_H
15#define PLASK__COMBINATE_PROVIDERS_H
16
17#include <set>
18#include <boost/iterator/indirect_iterator.hpp>
19
20#include "providerfor.hpp"
21
27 namespace plask {
28
35 template <typename BaseProviderT>
36 struct CombinedProviderBase: public BaseProviderT {
37
38 typedef BaseProviderT BaseType;
39
40 private:
41
43 std::set<BaseProviderT*> private_providers;
44
45 void onChange(Provider& which, bool isDeleted) {
46 if (isDeleted) {
47 private_providers.erase(static_cast<BaseProviderT*>(&which));
48 providers.erase(static_cast<BaseProviderT*>(&which));
49 }
50 this->fireChanged();
51 }
52
53 protected:
55 std::set<BaseProviderT*> providers;
56
57 public:
58
60 typedef boost::indirect_iterator<typename std::set<BaseProviderT*>::iterator> iterator;
61
63 typedef boost::indirect_iterator<typename std::set<BaseProviderT*>::const_iterator> const_iterator;
64
66 iterator begin() { return providers.begin(); }
67
69 iterator end() { return providers.end(); }
70
72 const_iterator begin() const { return providers.begin(); }
73
75 const_iterator end() const { return providers.end(); }
76
82 void add(BaseProviderT* to_add, bool providerIsPrivate = false) {
83 providers.insert(to_add);
84 if (providerIsPrivate) private_providers.insert(to_add);
85 to_add->changed.connect(boost::bind(&CombinedProviderBase::onChange, this, _1, _2));
86 this->fireChanged();
87 }
88
93 void add(std::unique_ptr<BaseProviderT>&& to_add) {
94 add(to_add->release(), true);
95 }
96
101 void remove(BaseProviderT* to_remove) {
102 to_remove->changed.disconnect(boost::bind(&CombinedProviderBase::onChange, this, _1, _2));
103 if (private_providers.erase(to_remove) > 0) delete to_remove;
104 providers.erase(to_remove);
105 }
106
111 void clear() {
112 while (!providers.empty()) remove(*providers.begin());
113 }
114
116 ~CombinedProviderBase() {
117 clear();
118 }
119
124 bool empty() const { return providers.empty(); }
125
130 std::size_t size() const { return providers.size(); }
131
135 void ensureHasProviders() const {
136 if (providers.empty())
137 throw Exception("combined {0} provider has no components", this->name());
138 }
139
140};
141
142
146 template <typename, typename, typename> struct FieldSumProviderImpl;
147
148 template <typename PropertyT, typename SpaceT, typename... ExtraArgs>
149 struct FieldSumProviderImpl<PropertyT, SpaceT, VariadicTemplateTypesHolder<ExtraArgs...>>: public CombinedProviderBase<ProviderFor<PropertyT, SpaceT>> {
150
151 typedef typename ProviderFor<PropertyT, SpaceT>::ProvidedType ProvidedType;
152 typedef typename ProviderFor<PropertyT, SpaceT>::ValueType ValueType;
153
154 struct SumLazyDataImpl: public LazyDataImpl<ValueType> {
155
156 std::vector<LazyData<ValueType>> to_sum;
157
158 std::size_t _size;
159
160 SumLazyDataImpl(std::vector<LazyData<ValueType>>&& to_sum, std::size_t size)
161 : to_sum(std::move(to_sum)), _size(size) {}
162
163 ValueType at(std::size_t index) const override {
164 ValueType sum = to_sum[0][index];
165 for (std::size_t i = 1; i < to_sum.size(); ++i)
166 sum += to_sum[i][index];
167 return sum;
168 }
169
170 std::size_t size() const override {
171 return _size;
172 }
173
174 };
175
176 ProvidedType operator()(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, ExtraArgs... extra_args, InterpolationMethod method=INTERPOLATION_DEFAULT) const override {
177 this->ensureHasProviders();
178 std::vector<LazyData<ValueType>> providers;
179 auto p = this->begin();
180 providers.push_back((*p)(dst_mesh, std::forward<ExtraArgs>(extra_args)..., method));
181 ++p;
182 if (p == this->end()) return std::move(providers.front()); // has one element
183 std::size_t size = providers.front().size();
184 do {
185 std::size_t last_size = providers.back().size();
186 if (size != last_size)
187 throw DataError("data sources sizes differ ([{0}] - [%2])", size, last_size);
188 providers.push_back((*p)(dst_mesh, std::forward<ExtraArgs>(extra_args)..., method));
189 ++p;
190 } while (p != this->end());
191 return new SumLazyDataImpl(std::move(providers), size);
192 }
193};
194
198 template <typename PropertyT, typename SpaceT>
199 struct FieldSumProvider: public FieldSumProviderImpl<PropertyT, SpaceT, typename PropertyT::ExtraParams> {};
200
201
202} // namespace plask
203
204#endif // COMBINATE_PROVIDERS_H