LCOV - code coverage report
Current view: top level - include/materials - CompileTimeDerivativesMaterialInternal.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 15 15 100.0 %
Date: 2025-07-17 01:28:37 Functions: 98 98 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : #include <cstddef>
      13             : 
      14             : namespace CompileTimeDerivativesMaterialInternal
      15             : {
      16             : namespace details
      17             : {
      18             : 
      19             : /**
      20             :  * Check if the given index sequence is sorted ()internal function)
      21             :  */
      22             : template <std::size_t first, std::size_t second, std::size_t... tail>
      23             : constexpr bool
      24             : is_sorted()
      25             : {
      26             :   if constexpr (first <= second)
      27             :   {
      28             :     if constexpr (sizeof...(tail) == 0)
      29             :       return true;
      30             :     else
      31             :       return is_sorted<second, tail...>();
      32             :   }
      33             :   else
      34             :     return false;
      35             : }
      36             : 
      37             : /**
      38             :  * Compile time evaluation of the factorial of N
      39             :  */
      40             : template <std::size_t N>
      41             : constexpr std::size_t
      42             : factorial()
      43             : {
      44             :   if constexpr (N == 0)
      45             :     return 1;
      46             :   else if constexpr (N == 1)
      47             :     return 1;
      48             :   else
      49             :     return N * factorial<N - 1>();
      50             : }
      51             : 
      52             : /**
      53             :  * Number of distinct order N derivatives of a function with M variables
      54             :  */
      55             : template <std::size_t N, std::size_t M>
      56             : constexpr std::size_t
      57             : num_derivatives()
      58             : {
      59             :   return factorial<N + M - 1>() / (factorial<N>() * factorial<M - 1>());
      60             : }
      61             : 
      62             : /**
      63             :  * Merge two index sequences into one
      64             :  */
      65             : template <std::size_t... first, std::size_t... second>
      66             : constexpr auto
      67        8265 : merge(std::index_sequence<first...>, std::index_sequence<second...>)
      68             : {
      69        8265 :   return std::index_sequence<first..., second...>{};
      70             : }
      71             : 
      72             : /**
      73             :  * Increment the first number in an index sequence, but roll over into the next number if it reaches
      74             :  * Nmax. This basically increments a base-Nmax number with its digits in reverse!
      75             :  */
      76             : template <std::size_t Nmax, std::size_t first, std::size_t... tail>
      77             : constexpr auto
      78       29754 : increment(std::index_sequence<first, tail...>)
      79             : {
      80             :   if constexpr (first + 1 == Nmax)
      81             :   {
      82             :     if constexpr (sizeof...(tail) == 0)
      83        1653 :       return std::index_sequence<>{};
      84             :     else
      85        8265 :       return merge(std::index_sequence<0>{}, increment<Nmax>(std::index_sequence<tail...>{}));
      86             :   }
      87             :   else
      88       19836 :     return std::index_sequence<first + 1, tail...>{};
      89             : }
      90             : 
      91             : /**
      92             :  * Compute the total number of distinct derivatives for all orders N
      93             :  */
      94             : template <std::size_t M, std::size_t... N>
      95             : constexpr std::size_t
      96             : total_derivatives(std::index_sequence<N...>)
      97             : {
      98             :   return (num_derivatives<N, M>() + ...);
      99             : }
     100             : 
     101             : /**
     102             :  * Take an index sequence and return an index sequence of the same length with all entries replaced
     103             :  * by zeroes
     104             :  */
     105             : template <std::size_t... Ns>
     106             : constexpr auto
     107         551 : zeroes(std::index_sequence<Ns...>)
     108             : {
     109         551 :   return std::index_sequence<(void(Ns), 0)...>{};
     110             : }
     111             : 
     112             : } // namespace details
     113             : 
     114             : /**
     115             :  * Check if the given index sequence is sorted
     116             :  */
     117             : template <std::size_t first, std::size_t second, std::size_t... tail>
     118             : constexpr bool
     119             : is_sorted(std::index_sequence<first, second, tail...>)
     120             : {
     121             :   return details::is_sorted<first, second, tail...>();
     122             : }
     123             : 
     124             : /**
     125             :  * A sequence of size 1 is always sorted
     126             :  */
     127             : template <std::size_t first>
     128             : constexpr bool
     129             : is_sorted(std::index_sequence<first>)
     130             : {
     131             :   return true;
     132             : }
     133             : 
     134             : /**
     135             :  * Compute the total number of distinct derivatives for all orders 1 through N
     136             :  */
     137             : template <std::size_t N, std::size_t M>
     138             : constexpr std::size_t
     139             : total_derivatives()
     140             : {
     141             :   // we compute derivatives of orders 0 up to and including N, and subtract 1 for
     142             :   // the 0th order derivative (underived original function)
     143             :   return details::total_derivatives<M>(std::make_index_sequence<N + 1>{}) - 1;
     144             : }
     145             : 
     146             : // shim for C++20 std::type_identity
     147             : template <class T>
     148             : struct type_identity
     149             : {
     150             :   using type = T;
     151             : };
     152             : 
     153             : /**
     154             :  * Create a tuple with sizeof...(Ns) entries, containing CTArrayRefs with tags given by the Ns...
     155             :  */
     156             : template <typename T, std::size_t... Ns>
     157             : constexpr auto
     158             : make_tuple_array(std::index_sequence<Ns...>)
     159             : {
     160             :   // we cannot default construct the tuple, so we wrap it in the type_identity template
     161             :   return type_identity<std::tuple<CompileTimeDerivatives::CTArrayRef<Ns, T, unsigned int>...>>{};
     162             : }
     163             : 
     164             : /**
     165             :  * Create an index sequence containing N zeroes
     166             :  */
     167             : template <std::size_t N>
     168             : constexpr auto
     169         551 : zeroes()
     170             : {
     171         551 :   return details::zeroes(std::make_index_sequence<N>{});
     172             : }
     173             : 
     174             : /**
     175             :  * Take all derivatives of expression listed in the index sequence
     176             :  */
     177             : template <typename T, std::size_t first, std::size_t... tags>
     178             : auto
     179       23040 : take_derivatives(const T & expression, std::index_sequence<first, tags...>)
     180             : {
     181             :   if constexpr (sizeof...(tags) == 0)
     182        9728 :     return expression.template D<static_cast<CompileTimeDerivatives::CTTag>(first)>();
     183             :   else
     184       13312 :     return take_derivatives(
     185       26624 :         expression.template D<static_cast<CompileTimeDerivatives::CTTag>(first)>(),
     186       26624 :         std::index_sequence<tags...>{});
     187             : }
     188             : 
     189             : } // namespace CompileTimeDerivativesMaterialInternal

Generated by: LCOV version 1.14