Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
adolcfunction.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4// SPDX-FileCopyrightText: Copyright © DUNE-FUFEM Project contributors, see file AUTHORS.md
5// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
6
7#ifndef DUNE_FUFEM_FUNCTIONS_ADOLCFUNCTION_HH
8#define DUNE_FUFEM_FUNCTIONS_ADOLCFUNCTION_HH
9
10#ifdef HAVE_ADOLC
11
12#include <vector>
13#include <array>
14#include <utility>
15
16#include <adolc/adolc.h>
17#include <adolc/drivers/drivers.h>
18#include <adolc/taping.h>
19
20
23
24#include <dune/istl/matrix.hh>
25
28
29
30
31namespace Dune::Fufem {
32
33
34namespace Impl {
35
59template<class T>
60struct AdolCConversion;
61
62
63
72template<class T>
73using AdolCActiveType = typename AdolCConversion<T>::ActiveType;
74
75
76
97template<class T>
98struct AdolCConstVectorDataHandle;
99
100
101
127template<class T>
128struct AdolCMutableMatrixDataHandle;
129
130
131
155template<class Signature, class F, class D>
156auto adolCTapeFunction(short int tapeTag, F&& f, const D& xp)
157{
160
161 Range yp;
162
163 trace_on(tapeTag);
164
165 AdolCActiveType<Domain> x;
166 AdolCActiveType<Range> y;
167
168 AdolCConversion<Domain>::toActiveType(xp, x);
169 y = f(x);
170 AdolCConversion<Range>::fromActiveType(y, yp);
171
172 trace_off();
173
174 return yp;
175}
176
177
178
194template<class DerivativeSignature, class D, class R>
195auto adolCJacobian(short int tapeTag, const D& x, const R&y)
196{
199
200 auto J = DerivativeRange();
201
202 auto x_data_handle = AdolCConstVectorDataHandle<const Domain>(x);
203 auto J_data_handle = AdolCMutableMatrixDataHandle<DerivativeRange>(J);
204 J_data_handle.resizeTo(y, x);
205
206 int n = J_data_handle.N();
207 int m = J_data_handle.M();
208 assert(m == x_data_handle.size());
209
210 jacobian(tapeTag, n, m, x_data_handle.data(), J_data_handle.data());
211
212 return J;
213}
214
215
216
227template<class SecondDerivativeSignature, class D>
228auto adolCHessian(short int tapeTag, const D& x)
229{
230 using SecondDerivativeRange = typename Dune::Functions::SignatureTraits<SecondDerivativeSignature>::Range;
231
232 auto H = SecondDerivativeRange();
233
234 auto x_data_handle = AdolCConstVectorDataHandle<const D>(x);
235 auto H_data_handle = AdolCMutableMatrixDataHandle<SecondDerivativeRange>(H);
236 H_data_handle.resizeTo(x, x);
237
238 int n = H_data_handle.N();
239
240 // Hack around a bug in the AdolC hessian interface which requires
241 // that this pointer is mutable (although it hopefully does not
242 // modify the pointed value).
243 auto x_data_pointer = const_cast<double*>(x_data_handle.data());
244 hessian(tapeTag, n, x_data_pointer, H_data_handle.data());
245
246 // Copy upper half
247 for(auto i : range(n))
248 for(auto j : range(i+1,n))
249 H_data_handle.data()[i][j] = H_data_handle.data()[j][i];
250
251 return H;
252}
253
254
255
256// *****************************************************************************
257// Spezializations of AdolCConversion
258// *****************************************************************************
259
260template<>
261struct AdolCConversion<double>
262{
263 using PassiveType = double;
264 using ActiveType = adouble;
265
266 static void toActiveType(const PassiveType& px, ActiveType& x) {
267 x <<= px;
268 }
269
270 static void fromActiveType(ActiveType& y, PassiveType& py) {
271 y >>= py;
272 }
273
274};
275
276
277
278template<class K, int n>
279struct AdolCConversion<std::array<K,n>>
280{
281 using PassiveType = std::array<K, n>;
283
284 static void toActiveType(const PassiveType& px, ActiveType& x) {
285 for(auto i : range(px.size()))
286 AdolCConversion<K>::toActiveType(px[i], x[i]);
287 }
288
289 static void fromActiveType(ActiveType& y, PassiveType& py) {
290 for(auto i : range(y.size()))
291 AdolCConversion<K>::fromActiveType(y[i], py[i]);
292 }
293
294};
295
296
297
298template<class K>
299struct AdolCConversion<std::vector<K>>
300{
301 using PassiveType = std::vector<K>;
303
304 static void toActiveType(const PassiveType& px, ActiveType& x) {
305 x.resize(px.size());
306 for(auto i : range(px.size()))
307 AdolCConversion<K>::toActiveType(px[i], x[i]);
308 }
309
310 static void fromActiveType(ActiveType& y, PassiveType& py) {
311 py.resize(y.size());
312 for(auto i : range(y.size()))
313 AdolCConversion<K>::fromActiveType(y[i], py[i]);
314 }
315
316};
317
318
319
320template<int n>
321struct AdolCConversion<Dune::FieldVector<double,n>>
322{
323 using PassiveType = Dune::FieldVector<double, n>;
325
326 static void toActiveType(const PassiveType& px, ActiveType& x) {
327 for(auto i : range(px.size()))
328 AdolCConversion<double>::toActiveType(px[i], x[i]);
329 }
330
331 static void fromActiveType(ActiveType& y, PassiveType& py) {
332 for(auto i : range(y.size()))
333 AdolCConversion<double>::fromActiveType(y[i], py[i]);
334 }
335
336};
337
338
339
340template<class K, int n, int m>
341struct AdolCConversion<Dune::FieldMatrix<K,n, m>>
342{
343 using PassiveType = Dune::FieldMatrix<K, n, m>;
345
346 static void toActiveType(const PassiveType& px, ActiveType& x) {
347 for(auto i : range(px.N()))
348 for(auto j : range(px.M()))
349 AdolCConversion<K>::toActiveType(px[i][j], x[i][j]);
350 }
351
352 static void fromActiveType(ActiveType& y, PassiveType& py) {
353 for(auto i : range(y.N()))
354 for(auto j : range(y.M()))
355 AdolCConversion<K>::fromActiveType(y[i][j], py[i][j]);
356 }
357
358};
359
360
361
362template<class K>
363struct AdolCConversion<Dune::Matrix<K>>
364{
365 using PassiveType = Dune::Matrix<K>;
367
368 static void toActiveType(const PassiveType& px, ActiveType& x) {
369 x.resize(px.N(), px.M());
370 for(auto row : range(px.N()))
371 for(auto col : range(px.M()))
372 AdolCConversion<K>::toActiveType(px[row][col], x[row][col]);
373 }
374
375 static void fromActiveType(const ActiveType& y, PassiveType& py) {
376 py.resize(y.N(), y.M());
377 for(auto row : range(y.N()))
378 for(auto col : range(y.M()))
379 AdolCConversion<K>::fromActiveType(y[row][col], py[row][col]);
380 }
381
382};
383
384
385
386// *****************************************************************************
387// Spezializations of AdolCConstVectorDataHandle
388// *****************************************************************************
389
390template<class T>
391struct AdolCConstVectorDataHandle
392{
393 AdolCConstVectorDataHandle(const T& t) : t_(t) {}
394 int size() const { return t_.size(); }
395 const double* data() const { return t_.data(); }
396 const T& t_;
397};
398
399template<>
400struct AdolCConstVectorDataHandle<const double>
401{
402 AdolCConstVectorDataHandle(const double& t) : tp_(&t) {}
403 int size() const { return 1; }
404 const double* data() const { return tp_; }
405 const double* tp_;
406};
407
408
409
410// *****************************************************************************
411// Spezializations of AdolCMutableMatrixDataHandle
412// *****************************************************************************
413
414template<class T>
415struct AdolCMutableMatrixDataHandle
416{
417 AdolCMutableMatrixDataHandle(T& t) : t_(t), data_(t_.data()) {}
418 int N() const { return 1; }
419 int M() const { return t_.size(); }
420 double** data() { return &data_; }
421
422 template<class RowVector, class ColVector>
423 void resizeTo(const RowVector& rowVector, const ColVector& colVector) {}
424
425 T& t_;
426 double* data_;
427};
428
429template<>
430struct AdolCMutableMatrixDataHandle<double>
431{
432 AdolCMutableMatrixDataHandle(double& t) : data_(&t) {}
433 int N() const { return 1; }
434 int M() const { return 1; }
435 double** data() { return &data_; }
436
437 template<class RowVector, class ColVector>
438 void resizeTo(const RowVector& rowVector, const ColVector& colVector) {}
439
440 double* data_;
441};
442
443template<int n, int m>
444struct AdolCMutableMatrixDataHandle<Dune::FieldMatrix<double,n,m>>
445{
446 AdolCMutableMatrixDataHandle(Dune::FieldMatrix<double,n,m>& t)
447 {
448 for(auto i : range(n))
449 data_[i] = t[i].data();
450 }
451 int N() const { return n; }
452 int M() const { return m; }
453 double** data() { return data_.data(); }
454
455 template<class RowVector, class ColVector>
456 void resizeTo(const RowVector& rowVector, const ColVector& colVector) {}
457
459};
460
461template<>
462struct AdolCMutableMatrixDataHandle<std::vector<double>>
463{
464 using T = std::vector<double>;
465 AdolCMutableMatrixDataHandle(T& t) : t_(t), data_(t_.data()) {}
466 int N() const { return 1; }
467 int M() const { return t_.size(); }
468 double** data() { return &data_; }
469
470 template<class RowVector>
471 void resizeTo(const RowVector& rowVector, const T& colVector) {
472 t_.resize(colVector.size());
473 data_ = t_.data();
474 }
475
476 T& t_;
477 double* data_;
478};
479
480template<>
481struct AdolCMutableMatrixDataHandle<Dune::Matrix<double>>
482{
483 AdolCMutableMatrixDataHandle(Dune::Matrix<double>& matrix) :
484 matrix_(matrix)
485 {
486 data_.resize(matrix_.N());
487 for(auto i : range(matrix.N()))
488 data_[i] = &matrix_[i][0];
489 }
490 int N() const { return matrix_.N(); }
491 int M() const { return matrix_.M(); }
492 double** data() { return data_.data(); }
493
494 template<class RowVector, class ColVector>
495 void resizeTo(const RowVector& rowVector, const ColVector& colVector) {
496 matrix_.setSize(rowVector.size(), colVector.size());
497 data_.resize(matrix_.N());
498 for(auto i : range(matrix_.N()))
499 data_[i] = &matrix_[i][0];
500 }
501
502 Dune::Matrix<double>& matrix_;
504};
505
506
507} // namespace Impl (withinin Dune::Fufem::)
508
509
510
511
540template<class Signature, template<class> class DerivativeTraits, class F>
541auto makeAdolCFunction(const Dune::Functions::SignatureTag<Signature, DerivativeTraits>& signatureTag, F f, short int tapeTag=0)
542{
544
545 using DerivativeRange = typename DerivativeTraits<Signature>::Range;
546 using DerivativeSignature = DerivativeRange(Domain);
547
548 using SecondDerivativeRange = typename DerivativeTraits<DerivativeSignature>::Range;
549 using SecondDerivativeSignature = SecondDerivativeRange(Domain);
550
551 auto df = [f, tapeTag](const Domain& x) {
552 auto y = Dune::Fufem::Impl::adolCTapeFunction<Signature>(tapeTag, f, x);
553 return Dune::Fufem::Impl::adolCJacobian<DerivativeSignature>(tapeTag, x, y);
554 };
555
557 {
558 return Dune::Functions::makeDifferentiableFunctionFromCallables(signatureTag, std::move(f), std::move(df));
559 }
560 else
561 {
562 auto ddf = [f, tapeTag](const Domain& x) {
563 [[maybe_unused]] auto y = Dune::Fufem::Impl::adolCTapeFunction<Signature>(tapeTag, f, x);
564 return Dune::Fufem::Impl::adolCHessian<SecondDerivativeSignature>(tapeTag, x);
565 };
566 return Dune::Functions::makeDifferentiableFunctionFromCallables(signatureTag, std::move(f), std::move(df), std::move(ddf));
567 }
568}
569
570
571
572} // namespace Dune::Fufem
573
574#endif // HAVE_ADOLC
575
576#endif // DUNE_FUFEM_FUNCTIONS_ADOLCFUNCTION_HH
Col col
Dune::BCRSMatrix< FieldMatrix< T, n, m >, TA > Matrix
OperatorHierarchy::ParallelMatrixHierarchy::ConstIterator matrix
DifferentiableFunctionFromCallables< Signature, DerivativeTraits, F... > makeDifferentiableFunctionFromCallables(const SignatureTag< Signature, DerivativeTraits > &signatureTag, F &&... f)
int size() const
static constexpr IntegralRange< std::decay_t< T > > range(T &&from, U &&to) noexcept
static constexpr size_type M()
static constexpr size_type N()
auto jacobian(const FEFunctionOperator< B, TP, argIndex > &op)
Obtain the jacobian of an operator.
Definition userfunctions.hh:1063
STL namespace.
Definition dunefunctionsboundaryfunctionalassembler.hh:29
T data(T... args)
T forward(T... args)
T resize(T... args)