OpenLB 1.8.1
Loading...
Searching...
No Matches
projection.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2012-13, 2016, 2023-24 Mathias J. Krause, Lukas Baron,
4 * Benjamin Förster, Julius Jeßberger
5 * E-mail contact: info@openlb.net
6 * The most recent release of OpenLB can be downloaded at
7 * <http://www.openlb.net/>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23*/
24
25
26// This file contains projections which can be used to rescale control variables.
27
28#ifndef PROJECTION_H
29#define PROJECTION_H
30
31#include <regex>
32
33#include "core/unitConverter.h"
34
35
36// All OpenLB code is contained in this namespace.
37namespace olb {
38
40namespace opti {
41
43
44namespace projection {
45
46template <typename T>
47struct Base {
48
49 virtual T project(T) const = 0;
50 virtual T derivative(T) const = 0;
51 virtual T inverse(T) const = 0;
52};
53
54template <typename T>
55struct Identity : public Base<T> {
56
57 T project(T x) const override { return x; }
58 T derivative(T x) const override { return 1; }
59 T inverse(T x) const override { return x; }
60};
61
62template <typename T>
63struct Sigmoid : public Base<T> {
64
65 T project(T x) const override { return util::exp(x) / ( util::exp(x) + T(1) ); }
66 T derivative(T x) const override { return util::exp(x) / util::pow( util::exp(x) + T(1), 2 ); }
67 T inverse(T x) const override { return -util::log(T(1)/x - T(1)); }
68};
69
70template <typename T>
71struct SigmoidD : public Base<T> {
72
73 T project(T x) const override { return util::exp(x) / util::pow( util::exp(x) + T(1), 2 ); }
74 T derivative(T x) const override { return 0; }
75 T inverse(T x) const override { return 0; }
76};
77
79template <typename T>
80struct ForceFactor : public Base<T> {
81
82 const T scale;
83
84 template <typename DESCRIPTOR>
86 : scale {converter.getConversionFactorMass() / converter.getConversionFactorForce()}
87 { }
88
89 T project(T x) const override { return scale * x; }
90 T derivative(T x) const override { return scale; }
91 T inverse(T x) const override { return x / scale; }
92};
93
94template <typename T>
95struct ForceFactorD : public Base<T> {
96
97 const T scale;
98
99 template <typename DESCRIPTOR>
101 : scale {converter.getConversionFactorMass() / converter.getConversionFactorForce()}
102 { }
103
104 T project(T x) const override { return scale; }
105 T derivative(T x) const override { return 0; }
106 T inverse(T x) const override { return 0; }
107};
108
109template <typename T>
110struct Rectifier : public Base<T> {
111
112 T project(T x) const override { return T(1) - T(1)/util::max( T(1), x ); }
113 T derivative(T x) const override { return (x >= T(1) ? T(1)/(x*x) : T(0)); }
114 T inverse(T x) const override { return T(1)/(T(1)-x); }
115};
116
117template <typename T>
118struct Softplus : public Base<T> {
119
120 T project(T x) const override { return T(1) - T(1)/(util::log(T(1)+util::exp(x))+T(1)); }
121 T derivative(T x) const override { return util::exp(x)
122 / ((util::exp(x)+T(1))*(util::log(T(1)+util::exp(x))+T(1))*(util::log(T(1)+util::exp(x))+T(1))); }
123 T inverse(T x) const override { return util::log(util::exp(x/(T(1)-x))-T(1)); }
124};
125
126template <typename T>
127struct Baron : public Base<T> {
128
129 const T pi {T(4) * util::atan(T(1))};
130
131 T project(T x) const override {
132 const T y = T(0.5) + T(0.5) * util::sin((x-T(0.5))*pi);
133 return y*y;
134 }
135 T derivative(T x) const override {
136 return (T(1) + util::sin((x-T(0.5))*pi))
137 * util::cos((x-T(0.5))*pi)
138 * pi * T(0.5);
139 }
140 T inverse(T x) const override {
141 return T(0.5) + util::asin(T(2)*x-T(1)) / pi;
142 }
143};
144
145template <typename T>
146struct Krause : public Base<T> {
147
148 T project(T x) const override {
149 return T(1) - T(1) / util::exp(x*x);
150 }
151 T derivative(T x) const override {
152 return T(2)*x / util::exp(x*x);
153 }
154 T inverse(T x) const override {
155 return util::sqrt(util::log(T(1)/(T(1)-x)));
156 }
157};
158
159
160// ------------------------------------------ //
161// helper functions //
162// ------------------------------------------ //
163
164template<typename T, typename DESCRIPTOR>
166 return converter.getPhysDeltaX()
167 * converter.getPhysDeltaX()
168 * converter.getLatticeViscosity()
169 * converter.getLatticeRelaxationTime();
170}
171
173// Inverse projection function to get startValue from porosity
174template<typename T>
175T porosityToControl(T porosity, const Base<T>& projection)
176{
177 return projection.inverse(porosity);
178}
179
181template<typename T, typename DESCRIPTOR>
182T permeabilityToPorosity(T permeability,
183 const UnitConverter<T,DESCRIPTOR>& converter)
184{
185 return (T(1) - gridTerm(converter) / permeability);
186}
187
189template<typename T, typename DESCRIPTOR>
191 const UnitConverter<T,DESCRIPTOR>& converter)
192{
193 return gridTerm(converter) / (T(1) - porosity);
194}
195
197template<typename T, typename DESCRIPTOR>
199 const UnitConverter<T,DESCRIPTOR>& converter)
200{
201 return (T(1) - porosity) / gridTerm(converter);
202}
203
205template<typename T, typename DESCRIPTOR>
206T permeabilityToControl(T permeability,
207 const Base<T>& projection,
208 const UnitConverter<T,DESCRIPTOR>& converter)
209{
210 const T porosity = permeabilityToPorosity(permeability, converter);
211 return porosityToControl(porosity);
212}
213
215template<typename T, typename DESCRIPTOR>
216T getInitialControl(T startValue,
217 const Base<T>& projection,
218 const UnitConverter<T,DESCRIPTOR>& converter,
219 StartValueType type,
220 bool verbose = true)
221{
222 T control {0};
223 OstreamManager clout(std::cout, "getInitialControl");
224
225 if (type == Porosity) {
226 control = projection::porosityToControl(startValue, projection);
227 if (verbose) {
228 clout << "Transform porosity startValue into control startValue:\n";
229 clout << "Porosity: " << startValue << std::endl;
230 clout << "Control: " << control << std::endl;
231 }
232 }
233 else if (type == Permeability) {
234 const T tmpPorosity = projection::permeabilityToPorosity(startValue, converter);
235 control = projection::porosityToControl(tmpPorosity, projection);
236 if (verbose) {
237 clout << "Transform permeability startValue into control startValue:\n";
238 clout << "Permeability: " << startValue << std::endl;
239 clout << "Porosity: " << tmpPorosity << std::endl;
240 clout << "Control: " << control << std::endl;
241 }
242 }
243 else if (type == ProjectedControl) {
244 control = projection.inverse(startValue);
245 } else if (type == Control) {
246 control = startValue;
247 } else {
248 throw std::invalid_argument(
249 "Error: unknown start value type.");
250 }
251 return control;
252}
253
254template<typename T, typename OptiCaseDual_Type>
255T getInitialControl(T startValue, OptiCaseDual_Type& optiCase)
256{
257 return getInitialControl(startValue,
258 *(optiCase._projection),
259 *(optiCase._converter),
260 optiCase._startValueType,
261 optiCase._verbose);
262}
263
264// ------------------------------------------ //
265// grid-independent projections //
266// ------------------------------------------ //
267
269
273template <typename T, typename DESCRIPTOR>
274struct GiBase : public Base<T> {
275
276 const T _gridTerm;
277
279 : _gridTerm {gridTerm(converter)}
280 { }
281
282 virtual T subprojection(T x) const = 0;
283 virtual T derivSubprojection(T x) const = 0;
284 virtual T inverseSubprojection(T x) const = 0;
285
286 T project(T x) const override {
287 return subprojection(x) / (subprojection(x) + _gridTerm);
288 }
289 T derivative(T x) const override {
290 const T y = subprojection(x) + _gridTerm;
291 return _gridTerm*derivSubprojection(x) / (y*y);
292 }
293 T inverse(T x) const override {
294 return inverseSubprojection(_gridTerm*x/(T(1)-x));
295 }
296};
297
298template <typename T, typename DESCRIPTOR>
299struct Foerster : public GiBase<T,DESCRIPTOR> {
300
302 : GiBase<T,DESCRIPTOR>{converter}
303 { }
304
305 T subprojection(T x) const override { return util::exp(x); }
306 T derivSubprojection(T x) const override { return util::exp(x); }
307 T inverseSubprojection(T x) const override { return util::log(x); }
308};
309
311
314template <typename T, typename DESCRIPTOR>
315struct FoersterN : public GiBase<T,DESCRIPTOR> {
316
317 const unsigned _n;
318
319 FoersterN(const UnitConverter<T,DESCRIPTOR>& converter, unsigned n)
320 : GiBase<T,DESCRIPTOR>(converter), _n(n)
321 {
322 OLB_PRECONDITION(_n >= 1);
323 }
324
325 T subprojection(T x) const override { return util::exp(util::pow(x, 2*_n)) - T(1); }
326 T derivSubprojection(T x) const override {
327 return T(2*_n) * util::pow(x, 2*_n-1) * subprojection(x);
328 }
329 T inverseSubprojection(T x) const override {
330 return util::pow(util::log(x+T(1)), T(1)/T(2*_n));
331 }
332};
333
335
338template <typename T, typename DESCRIPTOR>
339struct StasiusN : public GiBase<T,DESCRIPTOR> {
340
341 const unsigned _n;
342
343 StasiusN(const UnitConverter<T,DESCRIPTOR>& converter, unsigned n)
344 : GiBase<T,DESCRIPTOR>(converter), _n(n)
345 {
346 OLB_PRECONDITION(_n >= 1);
347 }
348
349 T subprojection(T x) const override { return util::pow(x, 2*_n); }
350 T derivSubprojection(T x) const override { return T(2*_n) * util::pow(x, 2*_n-1); }
351 T inverseSubprojection(T x) const override {
352 return util::pow(x, T(1)/T(2*_n));
353 }
354};
355
356
357
358template <typename T, typename DESCRIPTOR>
359std::shared_ptr<projection::Base<T>> construct(
360 const UnitConverter<T,DESCRIPTOR>& converter, std::string& name)
361{
362 std::smatch match;
363 if (name == "Identity") {
364 return std::make_shared<Identity<T>>();
365 } else if (name == "Sigmoid") {
366 return std::make_shared<Sigmoid<T>>();
367 } else if (name == "ForceFactor") {
368 return std::make_shared<ForceFactor<T>>(converter);
369 } else if (name == "Rectifier") {
370 return std::make_shared<Rectifier<T>>();
371 } else if (name == "Softplus") {
372 return std::make_shared<Softplus<T>>();
373 } else if (name == "Baron") {
374 return std::make_shared<Baron<T>>();
375 } else if (name == "Krause") {
376 return std::make_shared<Krause<T>>();
377 } else if (name == "Foerster") {
378 return std::make_shared<Foerster<T,DESCRIPTOR>>(converter);
379 } else if (std::regex_match(name, match, std::regex ("(Foerster)([0-9])"))) {
380 const unsigned n = std::stoi(match[2]);
381 return std::make_shared<FoersterN<T,DESCRIPTOR>>(converter, n);
382 } else if (std::regex_match(name, match, std::regex ("(Stasius)([0-9])"))) {
383 const unsigned n = std::stoi(match[2]);
384 return std::make_shared<StasiusN<T,DESCRIPTOR>>(converter, n);
385 } else {
386 throw std::invalid_argument(
387 "Error: unknown projection name selected.");
388 }
389}
390
391}
392
393template <typename PROJECTION, typename T>
394std::vector<T> applyProjection(const std::vector<T>& vector) {
395 std::vector<T> projected;
396 for (auto& e : vector) {
397 projected.push_back(PROJECTION().project(e));
398 }
399 return projected;
400}
401
402template <typename PROJECTION, typename T, typename ARG>
403std::vector<T> applyProjection(const std::vector<T>& vector, ARG arg) {
404 std::vector<T> projected;
405 for (auto& e : vector) {
406 projected.push_back(PROJECTION(arg).project(e));
407 }
408 return projected;
409}
410
411} // namespace opti
412
413} // namespace olb
414#endif // PROJECTION_H
class for marking output with some text
Conversion between physical and lattice units, as well as discretization.
constexpr T getLatticeViscosity() const
conversion from physical to lattice viscosity
constexpr T getLatticeRelaxationTime() const
return relaxation time in lattice units
constexpr T getPhysDeltaX() const
returns grid spacing (voxel length) in m
std::shared_ptr< projection::Base< T > > construct(const UnitConverter< T, DESCRIPTOR > &converter, std::string &name)
Definition projection.h:359
T porosityToControl(T porosity, const Base< T > &projection)
Get control value for given porosity.
Definition projection.h:175
T porosityToPermeability(T porosity, const UnitConverter< T, DESCRIPTOR > &converter)
Get permeability for given porosity.
Definition projection.h:190
T permeabilityToControl(T permeability, const Base< T > &projection, const UnitConverter< T, DESCRIPTOR > &converter)
Get control for given permeability.
Definition projection.h:206
T getInitialControl(T startValue, const Base< T > &projection, const UnitConverter< T, DESCRIPTOR > &converter, StartValueType type, bool verbose=true)
Transform porosity/ permeability/ other startValue into control.
Definition projection.h:216
T permeabilityToPorosity(T permeability, const UnitConverter< T, DESCRIPTOR > &converter)
Get porosity for given permeability.
Definition projection.h:182
T gridTerm(const UnitConverter< T, DESCRIPTOR > &converter)
Definition projection.h:165
T porosityToInvPermeability(T porosity, const UnitConverter< T, DESCRIPTOR > &converter)
Get inverse of permeability for given porosity.
Definition projection.h:198
@ ProjectedControl
Definition projection.h:42
std::vector< T > applyProjection(const std::vector< T > &vector)
Definition projection.h:394
Expr sqrt(Expr x)
Definition expr.cpp:225
Expr max(Expr a, Expr b)
Definition expr.cpp:245
ADf< T, DIM > log(const ADf< T, DIM > &a)
Definition aDiff.h:475
ADf< T, DIM > sin(const ADf< T, DIM > &a)
Definition aDiff.h:569
Expr pow(Expr base, Expr exp)
Definition expr.cpp:235
ADf< T, DIM > asin(const ADf< T, DIM > &a)
Definition aDiff.h:596
Expr exp(Expr x)
Definition expr.cpp:240
ADf< T, DIM > atan(const ADf< T, DIM > &a)
Definition aDiff.h:614
ADf< T, DIM > cos(const ADf< T, DIM > &a)
Definition aDiff.h:578
Top level namespace for all of OpenLB.
Optimization Code.
#define OLB_PRECONDITION(COND)
Definition olbDebug.h:46
T derivative(T x) const override
Definition projection.h:135
T project(T x) const override
Definition projection.h:131
T inverse(T x) const override
Definition projection.h:140
virtual T inverse(T) const =0
virtual T derivative(T) const =0
virtual T project(T) const =0
FoersterProjection for arbitrary n.
Definition projection.h:315
T subprojection(T x) const override
Definition projection.h:325
FoersterN(const UnitConverter< T, DESCRIPTOR > &converter, unsigned n)
Definition projection.h:319
T derivSubprojection(T x) const override
Definition projection.h:326
T inverseSubprojection(T x) const override
Definition projection.h:329
Foerster(const UnitConverter< T, DESCRIPTOR > &converter)
Definition projection.h:301
T subprojection(T x) const override
Definition projection.h:305
T derivSubprojection(T x) const override
Definition projection.h:306
T inverseSubprojection(T x) const override
Definition projection.h:307
T project(T x) const override
Definition projection.h:104
T derivative(T x) const override
Definition projection.h:105
ForceFactorD(const UnitConverter< T, DESCRIPTOR > &converter)
Definition projection.h:100
T inverse(T x) const override
Definition projection.h:106
Convert force to lattice units.
Definition projection.h:80
T project(T x) const override
Definition projection.h:89
ForceFactor(const UnitConverter< T, DESCRIPTOR > &converter)
Definition projection.h:85
T inverse(T x) const override
Definition projection.h:91
T derivative(T x) const override
Definition projection.h:90
Gridterm-dependent projection base class.
Definition projection.h:274
virtual T inverseSubprojection(T x) const =0
T project(T x) const override
Definition projection.h:286
virtual T derivSubprojection(T x) const =0
GiBase(const UnitConverter< T, DESCRIPTOR > &converter)
Definition projection.h:278
T inverse(T x) const override
Definition projection.h:293
virtual T subprojection(T x) const =0
T derivative(T x) const override
Definition projection.h:289
T derivative(T x) const override
Definition projection.h:58
T inverse(T x) const override
Definition projection.h:59
T project(T x) const override
Definition projection.h:57
T project(T x) const override
Definition projection.h:148
T derivative(T x) const override
Definition projection.h:151
T inverse(T x) const override
Definition projection.h:154
T derivative(T x) const override
Definition projection.h:113
T project(T x) const override
Definition projection.h:112
T inverse(T x) const override
Definition projection.h:114
T derivative(T x) const override
Definition projection.h:74
T inverse(T x) const override
Definition projection.h:75
T project(T x) const override
Definition projection.h:73
T project(T x) const override
Definition projection.h:65
T inverse(T x) const override
Definition projection.h:67
T derivative(T x) const override
Definition projection.h:66
T derivative(T x) const override
Definition projection.h:121
T project(T x) const override
Definition projection.h:120
T inverse(T x) const override
Definition projection.h:123
StasiusProjection for arbitrary n.
Definition projection.h:339
T inverseSubprojection(T x) const override
Definition projection.h:351
StasiusN(const UnitConverter< T, DESCRIPTOR > &converter, unsigned n)
Definition projection.h:343
T derivSubprojection(T x) const override
Definition projection.h:350
T subprojection(T x) const override
Definition projection.h:349
Unit conversion handling – header file.