funcy  1.6.1
principal_invariants.h
1 #pragma once
2 
3 #include <funcy/cmath/pow.h>
4 #include <funcy/concepts.h>
5 #include <funcy/linalg/cofactor.h>
6 #include <funcy/linalg/concepts.h>
7 #include <funcy/linalg/determinant.h>
8 #include <funcy/linalg/dimension.h>
9 #include <funcy/linalg/trace.h>
10 #include <funcy/util/chainer.h>
11 #include <funcy/util/type_traits.h>
12 
13 #include <type_traits>
14 
15 namespace funcy::linalg
16 {
18  namespace detail
19  {
20 
21  template < int row, Matrix Mat >
22  [[nodiscard]] auto symmetric_cofactor_derivative( const Mat& A, const Mat& dA )
23  {
24  return compute_cofactor_directional_derivative< row, row >( A, dA ) +
25  compute_cofactor_directional_derivative< row, row >( dA, A );
26  }
27 
28  template < int dim, Matrix Mat >
29  [[nodiscard]] static auto sum_of_diagonal_cofactors( const Mat& A ) requires( dim == 2 )
30  {
31  return linalg::compute_cofactor< 0, 0 >( A ) + linalg::compute_cofactor< 1, 1 >( A );
32  }
33 
34  template < int dim, Matrix Mat >
35  [[nodiscard]] static auto
36  sum_of_symmetric_cofactor_derivatives( const Mat& A, const Mat& B ) requires( dim == 2 )
37  {
38  return symmetric_cofactor_derivative< 0 >( A, B ) +
39  symmetric_cofactor_derivative< 1 >( A, B );
40  }
41 
42  template < int dim, Matrix Mat >
43  [[nodiscard]] static auto sum_of_diagonal_cofactors( const Mat& A ) requires( dim == 3 )
44  {
45  return linalg::compute_cofactor< 0, 0 >( A ) + linalg::compute_cofactor< 1, 1 >( A ) +
46  linalg::compute_cofactor< 2, 2 >( A );
47  }
48 
49  template < int dim, Matrix Mat >
50  [[nodiscard]] static auto
51  sum_of_symmetric_cofactor_derivatives( const Mat& A, const Mat& B ) requires( dim == 3 )
52  {
53  return symmetric_cofactor_derivative< 0 >( A, B ) +
54  symmetric_cofactor_derivative< 1 >( A, B ) +
55  symmetric_cofactor_derivative< 2 >( A, B );
56  }
57 
58  template < int dim, Matrix Mat >
59  [[nodiscard]] static auto sum_of_diagonal_cofactors( const Mat& A ) requires( dim == -1 )
60  {
61  if ( rows( A ) == 2 )
62  return sum_of_diagonal_cofactors< 2 >( A );
63  /*if(rows(A) == 3)*/ return sum_of_diagonal_cofactors< 3 >( A );
64  }
65 
66  template < int dim, Matrix Mat >
67  [[nodiscard]] static auto
68  sum_of_symmetric_cofactor_derivatives( const Mat& A, const Mat& B ) requires( dim == -1 )
69  {
70  if ( rows( A ) == 2 )
71  return sum_of_symmetric_cofactor_derivatives< 2 >( A, B );
72  /*if(rows(A) == 3)*/ return sum_of_symmetric_cofactor_derivatives< 3 >( A, B );
73  }
74  } // namespace detail
76 
79  template < Matrix Mat >
82  class SecondPrincipalInvariant : public Chainer< SecondPrincipalInvariant< Mat > >
83  {
84  public:
85  SecondPrincipalInvariant() = default;
86 
91  SecondPrincipalInvariant( const Mat& A )
92  {
93  update( A );
94  }
95 
97  void update( const Mat& A )
98  {
99  if ( !initialized )
100  {
101  new ( &A_ ) Mat{ A };
102  initialized = true;
103  }
104  else
105  A_ = A;
106  value = detail::sum_of_diagonal_cofactors< dim< Mat >() >( A );
107  }
108 
110  [[nodiscard]] auto d0() const noexcept
111  {
112  return value;
113  }
114 
119  [[nodiscard]] auto d1( const Mat& dA1 ) const
120  {
121  return detail::sum_of_symmetric_cofactor_derivatives< dim< Mat >() >( A_, dA1 );
122  }
123 
129  [[nodiscard]] auto d2( const Mat& dA1, const Mat& dA2 ) const
130  {
131  return detail::sum_of_symmetric_cofactor_derivatives< dim< Mat >() >( dA1, dA2 );
132  }
133 
134  private:
135  Mat A_;
136  std::decay_t< decltype( at( std::declval< Mat >(), 0, 0 ) ) > value = 0;
137  bool initialized = false;
138  };
139 
150  template < class Arg >
151  [[nodiscard]] auto i1( Arg&& x )
152  {
153  return trace( std::forward< Arg >( x ) );
154  }
155 
161  template < Matrix M >
162  [[nodiscard]] auto i2( M&& A )
163  {
164  return SecondPrincipalInvariant( std::forward< M >( A ) );
165  }
166 
172  template < Function F >
173  [[nodiscard]] auto i2( const F& f )
174  {
175  return SecondPrincipalInvariant( f() )( f );
176  }
177 
187  template < class Arg >
188  [[nodiscard]] auto i3( const Arg& x )
189  {
190  return det( x );
191  }
192 
199  template < class Arg, int n = dim< Arg >() >
200  [[nodiscard]] auto mi1( const Arg& x )
201  {
202  return i1( x ) * pow< -1, n >( det( x ) );
203  }
204 
211  template < class Arg, int n = dim< Arg >() >
212  [[nodiscard]] auto mi2( const Arg& x )
213  {
214  return i2( x ) * pow< -2, n >( det( x ) );
215  }
217 } // namespace funcy::linalg
auto d1(const Mat &dA1) const
First directional derivative.
Definition: principal_invariants.h:119
auto trace(const Mat &A) requires(!Function< Mat > &&!ConstantSize< Mat >)
Generate .
Definition: trace.h:138
auto mi1(const Arg &x)
Isochoric (volume-preserving), first modified principal invariant , where is the first and is the t...
Definition: principal_invariants.h:200
auto det(const Mat &A) requires(!Function< Mat > &&!SquareMatrix< Mat >)
Generate .
Definition: determinant.h:214
constexpr int dim()
Dimension of a fixed size matrix in .
Definition: dimension.h:19
auto rows(const Mat &A) requires(!ConstantSize< Mat > &&static_check
Number of rows of a dynamic size matrix.
Definition: rows_and_cols.h:13
auto pow(const F &f)
Generate .
Definition: pow.h:439
auto d0() const noexcept
Value of the second principal invariant.
Definition: principal_invariants.h:110
auto mi2(const Arg &x)
Isochoric (volume-preserving), second modified principal invariant , where is the second and is the...
Definition: principal_invariants.h:212
Functionality from linear algebra such as (modified) principal and mixed matrix invariants.
SecondPrincipalInvariant(const Mat &A)
Constructor.
Definition: principal_invariants.h:91
void update(const Mat &A)
Reset matrix to compute second principal invariant from.
Definition: principal_invariants.h:97
auto i2(M &&A)
Convenient generation of second principal invariant for .
Definition: principal_invariants.h:162
Definition: principal_invariants.h:82
auto i1(Arg &&x)
Generate first principal invariant.
Definition: principal_invariants.h:151
auto i3(const Arg &x)
Generate third principal invariant.
Definition: principal_invariants.h:188
auto d2(const Mat &dA1, const Mat &dA2) const
Second directional derivative.
Definition: principal_invariants.h:129