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

Generated by: LCOV version 1.14