LCOV - code coverage report
Current view: top level - include/neml2/utils - NEML2Utils.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 26ef6a Lines: 13 17 76.5 %
Date: 2026-06-24 21:19:51 Functions: 10 10 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 <string>
      13             : 
      14             : #ifdef NEML2_ENABLED
      15             : 
      16             : #include "neml2/tensors/tensors.h"
      17             : #include "neml2/base/Factory.h"
      18             : #include "neml2/models/Model.h"
      19             : #include "RankTwoTensor.h"
      20             : #include "RankFourTensor.h"
      21             : #include "SymmetricRankTwoTensor.h"
      22             : #include "SymmetricRankFourTensor.h"
      23             : #include "MaterialProperty.h"
      24             : 
      25             : #endif
      26             : 
      27             : class MooseObject;
      28             : class Action;
      29             : class SubProblem;
      30             : 
      31             : namespace NEML2Utils
      32             : {
      33             : #ifdef NEML2_ENABLED
      34             : 
      35             : enum class MOOSEIOType
      36             : {
      37             :   // unbatched
      38             :   TIME,
      39             :   SCALAR,
      40             :   // batched
      41             :   FUNCTION,
      42             :   VARIABLE,
      43             :   MATERIAL
      44             : };
      45             : 
      46             : std::string stringify(MOOSEIOType type);
      47             : 
      48             : /**
      49             :  * @brief Get the NEML2 Model
      50             :  *
      51             :  * This is mostly the same as the plain neml2::get_model() method, but it also guards the default
      52             :  * dtype and sends the model to the target device.
      53             :  * @return neml2::Model&
      54             :  */
      55             : std::shared_ptr<neml2::Model>
      56             : getModel(neml2::Factory & factory, const std::string & name, neml2::Dtype dtype = neml2::kFloat64);
      57             : 
      58             : template <typename T>
      59             : struct Layout
      60             : {
      61             : };
      62             : template <>
      63             : struct Layout<Real>
      64             : {
      65             :   static constexpr std::array<neml2::Size, 0> shape{};
      66             :   static constexpr std::array<neml2::Size, 1> strides{1};
      67             : };
      68             : template <>
      69             : struct Layout<RealVectorValue>
      70             : {
      71             :   static constexpr std::array<neml2::Size, 1> shape{3};
      72             :   static constexpr std::array<neml2::Size, 2> strides{3, 1};
      73             : };
      74             : template <>
      75             : struct Layout<RankTwoTensor>
      76             : {
      77             :   static constexpr std::array<neml2::Size, 2> shape{3, 3};
      78             :   static constexpr std::array<neml2::Size, 3> strides{9, 3, 1};
      79             : };
      80             : template <>
      81             : struct Layout<SymmetricRankTwoTensor>
      82             : {
      83             :   static constexpr std::array<neml2::Size, 1> shape{6};
      84             :   static constexpr std::array<neml2::Size, 2> strides{6, 1};
      85             : };
      86             : template <>
      87             : struct Layout<RankFourTensor>
      88             : {
      89             :   static constexpr std::array<neml2::Size, 4> shape{3, 3, 3, 3};
      90             :   static constexpr std::array<neml2::Size, 5> strides{81, 27, 9, 3, 1};
      91             : };
      92             : template <>
      93             : struct Layout<SymmetricRankFourTensor>
      94             : {
      95             :   static constexpr std::array<neml2::Size, 2> shape{6, 6};
      96             :   static constexpr std::array<neml2::Size, 3> strides{36, 6, 1};
      97             : };
      98             : 
      99             : /**
     100             :  * @brief Map from std::vector<T> to neml2::Tensor without copying the data
     101             :  *
     102             :  * This method is used in gatherers which gather data from MOOSE as input variables to the NEML2
     103             :  * material model. So in theory, we only need to provide Layout specializations for MOOSE types that
     104             :  * can potentially be used as NEML2 input variables.
     105             :  *
     106             :  * For this method to work, the underlying data in \p data must be reinterpretable as Real
     107             :  * (neml2::kFloat64). The data class T must also be aligned and follow the striding implied by
     108             :  * Layout<T>::shape. The data class T must also have no padding or overhead.
     109             :  */
     110             : template <typename T>
     111             : neml2::Tensor
     112        1825 : fromBlob(const std::vector<T> & data)
     113             : {
     114             :   // The const_cast is fine because torch works with non-const ptr so that it can optionally handle
     115             :   // deallocation. But we are not going to let torch do that.
     116        1825 :   const auto torch_tensor = at::from_blob(const_cast<T *>(data.data()),
     117        1825 :                                           neml2::utils::add_shapes(data.size(), Layout<T>::shape),
     118        1825 :                                           at::TensorOptions().dtype(neml2::kFloat64));
     119        3650 :   return neml2::Tensor(torch_tensor, 1);
     120        1825 : }
     121             : 
     122             : /**
     123             :  * @brief Directly copy a contiguous chunk of memory of a at::Tensor to a MOOSE data of type T
     124             :  *
     125             :  * This assumes the at::Tensor and T have the same layout, for example both row-major
     126             :  * with T = RankTwoTensor. If the layouts are different, we may need to reshape/reorder/transpose
     127             :  * the at::Tensor before copying.
     128             :  *
     129             :  * For this method to work,
     130             :  * 1. the address of \p dest must align with the first element of the data,
     131             :  * 2. the number of elements in \p dest must match the number of elements in \p src,
     132             :  * 3. the \p src tensor must be of type neml2::kFloat64, and
     133             :  * 4. data in \p dest must be reinterpretable as Real.
     134             :  */
     135             : template <typename T>
     136             : void
     137      180886 : copyTensorToMOOSEData(const at::Tensor & src, T & dest)
     138             : {
     139      180886 :   if (src.dtype() != neml2::kFloat64)
     140           0 :     mooseError(
     141           0 :         "Cannot copy at::Tensor with dtype ", src.dtype(), " into ", demangle(typeid(T).name()));
     142      180886 :   if (src.numel() != Layout<T>::strides[0])
     143           0 :     mooseError("Cannot copy at::Tensor with shape ",
     144           0 :                src.sizes(),
     145             :                " into ",
     146             :                demangle(typeid(T).name()),
     147             :                " with different number of elements.");
     148      180886 :   auto dest_tensor = at::from_blob(reinterpret_cast<Real *>(&dest),
     149             :                                    Layout<T>::shape,
     150      180886 :                                    at::TensorOptions().dtype(neml2::kFloat64));
     151      180886 :   dest_tensor.copy_(src.reshape(Layout<T>::shape));
     152      180886 : }
     153             : 
     154             : static std::string NEML2_help_message = R""""(
     155             : ==============================================================================
     156             : To debug NEML2 related issues:
     157             : 1. Build and run MOOSE in dbg mode.
     158             : 2. Re-run the simulation using the dbg executable, and often times
     159             :    NEML2 will provide a more helpful error message.
     160             : 3. If the error message is not helpful, or if there is still no error message,
     161             :    run the simulation through a debugger: See
     162             :    https://mooseframework.inl.gov/application_development/debugging.html
     163             : 4. If the issue is due to a NEML2 bug, feel free to report it at
     164             :    https://github.com/applied-material-modeling/neml2/issues
     165             : ==============================================================================
     166             : )"""";
     167             : 
     168             : #endif // NEML2_ENABLED
     169             : 
     170             : /// Determine whether the NEML2 material model should be evaluated
     171             : bool shouldCompute(const SubProblem &);
     172             : 
     173             : /**
     174             :  * Augment docstring if NEML2 is not enabled
     175             :  */
     176             : std::string docstring(const std::string & desc);
     177             : 
     178             : /**
     179             :  * Assert that NEML2 is enabled. A MooseError is raised if NEML2 is not enabled.
     180             :  */
     181             : void assertNEML2Enabled();
     182             : 
     183             : } // namespace NEML2Utils

Generated by: LCOV version 1.14