OpenLB 1.8.1
Loading...
Searching...
No Matches
objective.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2024 Julius Jessberger
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24#ifndef OBJECTIVE_H
25#define OBJECTIVE_H
26
27
31#include "utilities/aliases.h"
32
33
34namespace olb {
35
36namespace opti {
37
40// Provides interface for evaluation as well as relevant partial derivatives
41template <
42 typename T,
43 template<typename,SolverMode> typename SOLVER
44>
46{
47protected:
48 static constexpr unsigned dim = SOLVER<T,SolverMode::Primal>::dim;
49 std::shared_ptr<SOLVER<T,SolverMode::Primal>> _primalSolver;
50 std::shared_ptr<SuperIndicatorF<T,dim>> _objectiveDomain;
51 std::shared_ptr<SuperIndicatorF<T,dim>> _designDomain;
52
54 std::shared_ptr<GeometrySerializer<T,dim>> _serializer;
55
56public:
57 virtual T evaluate() = 0;
58
59 virtual std::shared_ptr<SuperF<dim,T,T>> derivativeByPopulations() = 0;
60
61 virtual std::shared_ptr<SuperF<dim,T,T>> derivativeByControl() = 0;
62
63 void setPrimalSolver(std::shared_ptr<SOLVER<T,SolverMode::Primal>> primalSolver) {
64 _primalSolver = primalSolver;
65 }
66
67 virtual void initialize(Controller<T>* controller,
68 std::shared_ptr<GeometrySerializer<T,dim>> serializer) {
69 _controller = controller;
70 _serializer = serializer;
71 }
72};
73
78// the partial derivatives of objective w.r.t. populations and control variables
79// are implemented in this class, generically with forward AD
80template <
81 typename T,
82 template<typename,SolverMode> typename SOLVER,
83 typename OBJECTIVE,
84 template<typename...> typename PRIMAL_DYNAMICS,
85 unsigned FieldDim
86>
87class GenericObjective : public DistributedObjective<T,SOLVER> {
88protected:
89 using DESCRIPTOR = SOLVER<T,SolverMode::Primal>::DESCRIPTOR;
90 using DistributedObjective<T,SOLVER>::dim;
91
92 // helper structure, where the details for evaluation are provided (by user)
93 std::shared_ptr<OBJECTIVE> _objective;
95
96public:
97 GenericObjective() = default;
98
99 GenericObjective(std::shared_ptr<OBJECTIVE> objective)
100 : _objective(objective)
101 {
102 this->_objectiveDomain = objective->_objectiveDomain;
103 this->_designDomain = objective->_designDomain;
105 this->_objectiveDomain->getSuperGeometry().getCuboidDecomposition().getDeltaR(),
106 dim);
107 }
108
109 T evaluate() override {
110 // main term that depends on state
112 this->_primalSolver->lattice(),
113 [this](T* output, auto cell, int iC, const int* coords) {
114 _objective->j(output, cell, iC, coords);
115 });
117
118 // additional term that depends (directly) on control
120 this->_primalSolver->lattice(),
121 [this](T* output, int iC, const int* coords) {
122 const T* control = getControlPointer(iC, coords);
123 _objective->r(output, iC, coords, control);
124 });
126
127 int dummy[dim+1]{0}; T result{0}; T result2{0};
128 J(&result, dummy);
129 R(&result2, dummy);
130 return result + result2;
131 }
132
133 std::shared_ptr<SuperF<dim,T,T>> derivativeByPopulations() override {
134 using T_AD1 = util::ADf<T,DESCRIPTOR::q>;
135 std::shared_ptr<SuperF<dim,T,T>> djdf = std::make_shared<SuperLatticeFfromCallableF<T,DESCRIPTOR>> (
136 this->_primalSolver->lattice(),
137 [this](T* output, auto cell, int iC, const int* coords){
138 const int iCglob = this->_primalSolver->lattice().getLoadBalancer().glob(iC);
139 bool isInside;
140 if constexpr (DESCRIPTOR::d == 3) {
141 isInside = this->_objectiveDomain->operator()(iCglob,coords[0],coords[1],coords[2]);
142 } else {
143 isInside = this->_objectiveDomain->operator()(iCglob,coords[0],coords[1]);
144 }
145 if (isInside) {
146 // get ADf-typed clone of cell
147 const Vector<int,dim> extent(1);
148 ConcreteBlockLattice<T_AD1,DESCRIPTOR> blockLatticeAD(extent, 0);
149 const Vector<int,dim> position(0);
150 blockLatticeAD.template defineDynamics<PRIMAL_DYNAMICS>(position);
151 auto adFcell = blockLatticeAD.get(position);
152 DESCRIPTOR::fields_t::for_each([&](auto id) {
153 using field = typename decltype(id)::type;
154 adFcell.template setField<field>(cell.template getField<field>());
155 });
156
157 for (unsigned iPop=0; iPop<DESCRIPTOR::q; ++iPop){
158 adFcell.template getFieldPointer<descriptors::POPULATION>()[iPop].setDiffVariable(iPop);
159 }
160 T_AD1 result;
161 _objective->j(&result, adFcell, iC, coords);
162 for (unsigned iPop=0; iPop<DESCRIPTOR::q; ++iPop){
163 output[iPop] = _cellVolume * result.d(iPop);
164 }
165 }
166 else {
167 for (unsigned iPop=0; iPop<DESCRIPTOR::q; ++iPop){
168 output[iPop] = T(0);
169 }
170 }
171 });
172 return djdf;
173 }
174
175 std::shared_ptr<SuperF<dim,T,T>> derivativeByControl() override {
176 using T_AD2 = util::ADf<T,FieldDim>;
177 std::shared_ptr<SuperF<dim,T,T>> drdc = std::make_shared<SuperLatticeFfromCallableF<T,DESCRIPTOR>> (
178 this->_primalSolver->lattice(),
179 [this](T* output, int iC, const int* coords){
180 const int iCglob = this->_primalSolver->lattice().getLoadBalancer().glob(iC);
181 if constexpr (DESCRIPTOR::d == 3) {
182 if (this->_designDomain->operator()(iCglob,coords[0],coords[1],coords[2])) {
183 // get ADf-typed copy of control
184 const T* control = getControlPointer(iC, coords);
186 for (unsigned iControl=0; iControl<FieldDim; ++iControl){
187 adFcontrol[iControl].setDiffVariable(iControl);
188 }
189
190 T_AD2 result;
191 _objective->r(&result, iC, coords, adFcontrol.data());
192 for (unsigned iControl=0; iControl<FieldDim; ++iControl){
193 output[iControl] = _cellVolume * result.d(iControl);
194 }
195 }
196 else {
197 for (unsigned iControl=0; iControl<FieldDim; ++iControl){
198 output[iControl] = T(0);
199 }
200 }
201 }
202 else {
203 if (this->_designDomain->operator()(iCglob,coords[0],coords[1])) {
204 // get ADf-typed copy of control
205 const T* control = getControlPointer(iC, coords);
207 for (unsigned iControl=0; iControl<FieldDim; ++iControl){
208 adFcontrol[iControl].setDiffVariable(iControl);
209 }
210
211 T_AD2 result;
212 _objective->r(&result, iC, coords, adFcontrol.data());
213 for (unsigned iControl=0; iControl<FieldDim; ++iControl){
214 output[iControl] = _cellVolume * result.d(iControl);
215 }
216 }
217 else {
218 for (unsigned iControl=0; iControl<FieldDim; ++iControl){
219 output[iControl] = T(0);
220 }
221 }
222 }
223 });
224 return drdc;
225 }
226
227protected:
232 const T* getControlPointer(int iC, const int* coords) const {
233 int latticeR[dim+1] = {
234 this->_primalSolver->lattice().getLoadBalancer().glob(iC),
235 coords[0],
236 coords[1]};
237 if constexpr (dim == 3) {
238 latticeR[3] = coords[2];
239 }
240 const auto index = this->_serializer->getSerializedCellIndex(latticeR);
241 return this->_controller->getControlPointer(index);
242 }
243};
244
245
246}
247}
248
249#endif
Cell< T, DESCRIPTOR > get(CellID iCell)
Get Cell interface for index iCell.
Implementation of BlockLattice on a concrete PLATFORM.
Generate a SuperLatticeF from an arbitrary function.
Plain old scalar vector.
constexpr const T * data() const any_platform
Definition vector.h:172
const S * getControlPointer(int i) const
Definition controller.h:68
Objective in optimization with adjoint LBM.
Definition objective.h:46
virtual void initialize(Controller< T > *controller, std::shared_ptr< GeometrySerializer< T, dim > > serializer)
Definition objective.h:67
std::shared_ptr< SOLVER< T, SolverMode::Primal > > _primalSolver
Definition objective.h:49
Controller< T > * _controller
Definition objective.h:53
virtual std::shared_ptr< SuperF< dim, T, T > > derivativeByPopulations()=0
std::shared_ptr< SuperIndicatorF< T, dim > > _objectiveDomain
Definition objective.h:50
std::shared_ptr< GeometrySerializer< T, dim > > _serializer
Definition objective.h:54
void setPrimalSolver(std::shared_ptr< SOLVER< T, SolverMode::Primal > > primalSolver)
Definition objective.h:63
static constexpr unsigned dim
Definition objective.h:48
std::shared_ptr< SuperIndicatorF< T, dim > > _designDomain
Definition objective.h:51
virtual std::shared_ptr< SuperF< dim, T, T > > derivativeByControl()=0
Objective in optimization with adjoint LBM.
Definition objective.h:87
std::shared_ptr< SuperF< dim, T, T > > derivativeByPopulations() override
Definition objective.h:133
SOLVER< T, SolverMode::Primal >::DESCRIPTOR DESCRIPTOR
Definition objective.h:89
std::shared_ptr< SuperF< dim, T, T > > derivativeByControl() override
Definition objective.h:175
std::shared_ptr< OBJECTIVE > _objective
Definition objective.h:93
const T * getControlPointer(int iC, const int *coords) const
Access control at some position.
Definition objective.h:232
GenericObjective(std::shared_ptr< OBJECTIVE > objective)
Definition objective.h:99
This class serializes the cells inside the geometry.
Definition of a description of a algoritmic differentiation data type using the forward method.
Expr pow(Expr base, Expr exp)
Definition expr.cpp:235
Top level namespace for all of OpenLB.
std::conditional_t< DIM==2, SuperIntegral2D< T, W >, SuperIntegral3D< T, W > > SuperIntegral
Definition aliases.h:127
Optimization Code.
Objective functional results, always scalar.
Definition fields.h:548