Loading [MathJax]/extensions/TeX/AMSsymbols.js
 deal.II version GIT relicensing-3075-gc235bd4825 2025-04-15 08:10:00+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
derivative_form.h
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2013 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_derivative_form_h
16#define dealii_derivative_form_h
17
18#include <deal.II/base/config.h>
19
23#include <deal.II/base/tensor.h>
24
25#include <cstddef>
26
27
29
62template <int order, int dim, int spacedim, typename Number = double>
64{
65public:
69 DerivativeForm() = default;
70
75
83
88 operator[](const unsigned int i);
89
94 operator[](const unsigned int i) const;
95
101
106 operator=(const Tensor<order, spacedim, Tensor<1, dim, Number>> &);
107
113
117 template <typename OtherNumber>
120
127
131 operator Tensor<1, dim, Number>() const;
132
138 transpose() const;
139
146 norm() const;
147
153 Number
154 determinant() const;
155
167
172 static std::size_t
174
179 int,
180 << "Invalid DerivativeForm index " << arg1);
181
182private:
189
190
195};
196
197
198/*--------------------------- Inline functions -----------------------------*/
199
200#ifndef DOXYGEN
201
202template <int order, int dim, int spacedim, typename Number>
205{
206 Assert((dim == spacedim),
207 ExcMessage("Only allowed for forms with dim==spacedim."));
208 if (dim == spacedim)
209 for (unsigned int j = 0; j < dim; ++j)
210 (*this)[j] = T[j];
211}
212
213
214
215template <int order, int dim, int spacedim, typename Number>
217 const Tensor<1, spacedim, Tensor<order, dim, Number>> &T)
218{
219 for (unsigned int j = 0; j < spacedim; ++j)
220 (*this)[j] = T[j];
221}
222
223
224
225template <int order, int dim, int spacedim, typename Number>
229{
230 Assert((dim == spacedim), ExcMessage("Only allowed when dim==spacedim."));
231
232 if (dim == spacedim)
233 for (unsigned int j = 0; j < dim; ++j)
234 (*this)[j] = ta[j];
235 return *this;
236}
237
238
239
240template <int order, int dim, int spacedim, typename Number>
243 const Tensor<order, spacedim, Tensor<1, dim, Number>> &T)
244{
245 for (unsigned int j = 0; j < spacedim; ++j)
246 (*this)[j] = T[j];
247 return *this;
248}
249
250
251
252template <int order, int dim, int spacedim, typename Number>
255 const Tensor<1, dim, Number> &T)
256{
257 Assert((1 == spacedim) && (order == 1),
258 ExcMessage("Only allowed for spacedim==1 and order==1."));
259
260 (*this)[0] = T;
261
262 return *this;
263}
264
265
266
267template <int order, int dim, int spacedim, typename Number>
268template <typename OtherNumber>
272{
273 for (unsigned int j = 0; j < spacedim; ++j)
274 (*this)[j] = df[j];
275 return *this;
276}
277
278
279
280template <int order, int dim, int spacedim, typename Number>
283{
284 AssertIndexRange(i, spacedim);
285
286 return tensor[i];
287}
288
289
290
291template <int order, int dim, int spacedim, typename Number>
292inline const Tensor<order, dim, Number> &
294 const unsigned int i) const
295{
296 AssertIndexRange(i, spacedim);
297
298 return tensor[i];
299}
300
301
302
303template <int order, int dim, int spacedim, typename Number>
305operator Tensor<1, dim, Number>() const
306{
307 Assert((1 == spacedim) && (order == 1),
308 ExcMessage("Only allowed for spacedim==1."));
309
310 return (*this)[0];
311}
312
313
314
315template <int order, int dim, int spacedim, typename Number>
317operator Tensor<order + 1, dim, Number>() const
318{
319 Assert((dim == spacedim), ExcMessage("Only allowed when dim==spacedim."));
320
322
323 if (dim == spacedim)
324 for (unsigned int j = 0; j < dim; ++j)
325 t[j] = (*this)[j];
326
327 return t;
328}
329
330
331
332template <int order, int dim, int spacedim, typename Number>
335{
336 Assert(order == 1, ExcMessage("Only for rectangular DerivativeForm."));
338
339 for (unsigned int i = 0; i < spacedim; ++i)
340 for (unsigned int j = 0; j < dim; ++j)
341 tt[j][i] = (*this)[i][j];
342
343 return tt;
344}
345
346
347
348template <int order, int dim, int spacedim, typename Number>
351 const Tensor<2, dim, Number> &T) const
352{
353 Assert(order == 1, ExcMessage("Only for order == 1."));
355 for (unsigned int i = 0; i < spacedim; ++i)
356 for (unsigned int j = 0; j < dim; ++j)
357 dest[i][j] = (*this)[i] * T[j];
358
359 return dest;
360}
361
362
363
364template <int order, int dim, int spacedim, typename Number>
367{
368 typename numbers::NumberTraits<Number>::real_type sum_of_squares = 0;
369 for (unsigned int i = 0; i < spacedim; ++i)
370 sum_of_squares += tensor[i].norm_square();
371 return std::sqrt(sum_of_squares);
372}
373
374
375
376template <int order, int dim, int spacedim, typename Number>
377inline Number
379{
380 Assert(order == 1, ExcMessage("Only for order == 1."));
381 if (dim == spacedim)
382 {
384 static_cast<Tensor<2, dim, Number>>(*this);
385 return ::determinant(T);
386 }
387 else
388 {
389 Assert(spacedim > dim, ExcMessage("Only for spacedim>dim."));
391 Tensor<2, dim, Number> G; // First fundamental form
392 for (unsigned int i = 0; i < dim; ++i)
393 for (unsigned int j = 0; j < dim; ++j)
394 G[i][j] = DF_t[i] * DF_t[j];
395
396 return (std::sqrt(::determinant(G)));
397 }
398}
399
400
401
402template <int order, int dim, int spacedim, typename Number>
405{
406 if (dim == spacedim)
407 {
408 const Tensor<2, dim, Number> DF_t =
409 ::transpose(invert(static_cast<Tensor<2, dim, Number>>(*this)));
411 }
412 else
413 {
415 Tensor<2, dim, Number> G; // First fundamental form
416 for (unsigned int i = 0; i < dim; ++i)
417 for (unsigned int j = 0; j < dim; ++j)
418 G[i][j] = DF_t[i] * DF_t[j];
419
420 return (this->times_T_t(invert(G)));
421 }
422}
423
424
425template <int order, int dim, int spacedim, typename Number>
426inline std::size_t
428{
430}
431
432#endif // DOXYGEN
433
434
435
443template <int order, int dim, int spacedim, typename Number>
444inline std::ostream &
445operator<<(std::ostream &out,
447{
448 for (unsigned int i = 0; i < spacedim; ++i)
449 {
450 out << df[i];
451 if (i != spacedim - 1)
452 for (unsigned int j = 0; j < order + 1; ++j)
453 out << ' ';
454 }
455
456 return out;
457}
458
459
460
482template <int spacedim, int dim, typename Number1, typename Number2>
485 const Tensor<1, dim, Number2> &d_x)
486{
488 for (unsigned int i = 0; i < spacedim; ++i)
489 dest[i] = grad_F[i] * d_x;
490 return dest;
491}
492
493
494
503// rank=2
504template <int spacedim, int dim, typename Number1, typename Number2>
505inline DerivativeForm<1,
506 spacedim,
507 dim,
510 const Tensor<2, dim, Number2> &D_X)
511{
513 dest;
514 for (unsigned int i = 0; i < dim; ++i)
515 dest[i] = apply_transformation(grad_F, D_X[i]);
516
517 return dest;
518}
519
520
521
532// rank=2
533template <int dim, typename Number1, typename Number2>
536 const Tensor<2, dim, Number2> &D_X)
537{
539 for (unsigned int i = 0; i < dim; ++i)
540 dest[i] = apply_transformation(grad_F, D_X[i]);
541
542 return dest;
543}
544
545
546
554template <int spacedim,
555 int dim,
556 int n_components,
557 typename Number1,
558 typename Number2>
559inline Tensor<1,
560 n_components,
564 const Tensor<1, n_components, Tensor<1, dim, Number2>> &D_X)
565{
566 Tensor<1,
567 n_components,
569 dest;
570 for (unsigned int i = 0; i < n_components; ++i)
571 dest[i] = apply_transformation(grad_F, D_X[i]);
572
573 return dest;
574}
575
576
577
593template <int spacedim, int dim, typename Number1, typename Number2>
597{
599
600 for (unsigned int i = 0; i < spacedim; ++i)
601 dest[i] = apply_transformation(DF1, DF2[i]);
602
603 return dest;
604}
605
606
607
614template <int dim, int spacedim, typename Number>
620
621
622
628template <int spacedim, int dim, typename Number1, typename Number2>
632 const Tensor<1, dim, Number2> &d_x)
633{
634 Assert(dim == spacedim,
635 ExcMessage("Only dim = spacedim allowed for diagonal transformation"));
637 for (unsigned int i = 0; i < spacedim; ++i)
638 dest[i] = grad_F[i][i] * d_x[i];
639 return dest;
640}
641
642
653template <int dim, typename Number1, typename Number2>
657 const Tensor<2, dim, Number2> &D_X)
658{
660 for (unsigned int i = 0; i < dim; ++i)
661 dest[i] = apply_diagonal_transformation(grad_F, D_X[i]);
662
663 return dest;
664}
665
666
667
675template <int spacedim,
676 int dim,
677 int n_components,
678 typename Number1,
679 typename Number2>
680inline Tensor<1,
681 n_components,
685 const Tensor<1, n_components, Tensor<1, dim, Number2>> &D_X)
686{
687 Tensor<1,
688 n_components,
690 dest;
691 for (unsigned int i = 0; i < n_components; ++i)
692 dest[i] = apply_diagonal_transformation(grad_F, D_X[i]);
693
694 return dest;
695}
696
697
698
707// rank=2
708template <int spacedim, int dim, typename Number1, typename Number2>
709inline DerivativeForm<1,
710 spacedim,
711 dim,
715 const Tensor<2, dim, Number2> &D_X)
716{
718 dest;
719 for (unsigned int i = 0; i < dim; ++i)
720 dest[i] = apply_diagonal_transformation(grad_F, D_X[i]);
721
722 return dest;
723}
724
725
727
728#endif
static std::size_t memory_consumption()
DerivativeForm & operator=(const Tensor< order, spacedim, Tensor< 1, dim, Number > > &)
Tensor< 2, dim, typename ProductType< Number1, Number2 >::type > apply_transformation(const DerivativeForm< 1, dim, dim, Number1 > &grad_F, const Tensor< 2, dim, Number2 > &D_X)
Tensor< order, dim, Number > tensor[spacedim]
Tensor< 2, dim, typename ProductType< Number1, Number2 >::type > apply_diagonal_transformation(const DerivativeForm< 1, dim, dim, Number1 > &grad_F, const Tensor< 2, dim, Number2 > &D_X)
Number determinant() const
Tensor< 1, n_components, Tensor< 1, spacedim, typename ProductType< Number1, Number2 >::type > > apply_transformation(const DerivativeForm< 1, dim, spacedim, Number1 > &grad_F, const Tensor< 1, n_components, Tensor< 1, dim, Number2 > > &D_X)
DerivativeForm< 1, dim, spacedim, Number > covariant_form() const
DerivativeForm< 1, spacedim, dim, Number > transpose(const DerivativeForm< 1, dim, spacedim, Number > &DF)
DerivativeForm< 1, spacedim, dim, typename ProductType< Number1, Number2 >::type > apply_transformation(const DerivativeForm< 1, dim, spacedim, Number1 > &grad_F, const Tensor< 2, dim, Number2 > &D_X)
DerivativeForm< 1, spacedim, dim, Number > transpose() const
DerivativeForm()=default
Tensor< 1, spacedim, typename ProductType< Number1, Number2 >::type > apply_transformation(const DerivativeForm< 1, dim, spacedim, Number1 > &grad_F, const Tensor< 1, dim, Number2 > &d_x)
DerivativeForm & operator=(const DerivativeForm< order, dim, spacedim, OtherNumber > &df)
const Tensor< order, dim, Number > & operator[](const unsigned int i) const
DerivativeForm< 1, spacedim, dim, typename ProductType< Number1, Number2 >::type > apply_diagonal_transformation(const DerivativeForm< 1, dim, spacedim, Number1 > &grad_F, const Tensor< 2, dim, Number2 > &D_X)
DerivativeForm< 1, dim, spacedim, Number > times_T_t(const Tensor< 2, dim, Number > &T) const
Tensor< 2, spacedim, typename ProductType< Number1, Number2 >::type > apply_transformation(const DerivativeForm< 1, dim, spacedim, Number1 > &DF1, const DerivativeForm< 1, dim, spacedim, Number2 > &DF2)
DerivativeForm & operator=(const Tensor< order+1, dim, Number > &)
numbers::NumberTraits< Number >::real_type norm() const
Tensor< 1, spacedim, typename ProductType< Number1, Number2 >::type > apply_diagonal_transformation(const DerivativeForm< 1, dim, spacedim, Number1 > &grad_F, const Tensor< 1, dim, Number2 > &d_x)
DerivativeForm & operator=(const Tensor< 1, dim, Number > &)
DerivativeForm(const Tensor< order+1, dim, Number > &)
Tensor< 1, n_components, Tensor< 1, spacedim, typename ProductType< Number1, Number2 >::type > > apply_diagonal_transformation(const DerivativeForm< 1, dim, spacedim, Number1 > &grad_F, const Tensor< 1, n_components, Tensor< 1, dim, Number2 > > &D_X)
DerivativeForm(const Tensor< 1, spacedim, Tensor< order, dim, Number > > &)
Tensor< order, dim, Number > & operator[](const unsigned int i)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:35
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:36
DerivativeForm< 1, spacedim, dim, Number > transpose(const DerivativeForm< 1, dim, spacedim, Number > &DF)
std::ostream & operator<<(std::ostream &out, const DerivativeForm< order, dim, spacedim, Number > &df)
Tensor< 1, spacedim, typename ProductType< Number1, Number2 >::type > apply_transformation(const DerivativeForm< 1, dim, spacedim, Number1 > &grad_F, const Tensor< 1, dim, Number2 > &d_x)
Tensor< 1, spacedim, typename ProductType< Number1, Number2 >::type > apply_diagonal_transformation(const DerivativeForm< 1, dim, spacedim, Number1 > &grad_F, const Tensor< 1, dim, Number2 > &d_x)
static ::ExceptionBase & ExcInvalidTensorIndex(int arg1)
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcMessage(std::string arg1)
constexpr char T
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
typename internal::ProductTypeImpl< std::decay_t< T >, std::decay_t< U > >::type type
DEAL_II_HOST constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)