// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. #pragma once #include "util.hpp" #include "../../linalg/tensor.hpp" namespace mfem::future { template MFEM_HOST_DEVICE void process_qf_arg(const T0 &, const T1 &, T2 &) { static_assert(dfem::always_false, "process_qf_arg not implemented for arg type"); } template MFEM_HOST_DEVICE void process_qf_arg( const DeviceTensor<1, T> &u, const DeviceTensor<1, T> &v, T &arg) { arg = u(0); } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<1> &u, tensor, n, m> &arg) { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { arg(j, i).value = u((i * n) + j); } } } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<1> &u, dual &arg) { arg.value = u(0); } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<1> &u, const DeviceTensor<1> &v, dual &arg) { arg.value = u(0); arg.gradient = v(0); } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<1> &u, const DeviceTensor<1> &v, tensor, n> &arg) { for (int i = 0; i < n; i++) { arg(i).value = u(i); arg(i).gradient = v(i); } } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<1> &u, const DeviceTensor<1> &v, tensor, n, m> &arg) { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { arg(j, i).value = u((i * n) + j); arg(j, i).gradient = v((i * n) + j); } } } template MFEM_HOST_DEVICE inline void process_qf_result( DeviceTensor<1, T> &r, const tensor, n> &x) { for (size_t i = 0; i < n; i++) { r(i) = x(i).value; } } template MFEM_HOST_DEVICE inline void process_qf_result( DeviceTensor<1, T> &r, const tensor, n, m> &x) { for (size_t i = 0; i < n; i++) { for (size_t j = 0; j < m; j++) { r(i + n * j) = x(i, j).value; } } } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<2> &u, const DeviceTensor<2> &v, arg_type &arg, const int &qp) { const auto u_qp = Reshape(&u(0, qp), u.GetShape()[0]); const auto v_qp = Reshape(&v(0, qp), v.GetShape()[0]); process_qf_arg(u_qp, v_qp, arg); } template MFEM_HOST_DEVICE inline void process_qf_args( const std::array, num_fields> &u, const std::array, num_fields> &v, qf_args &args, const int &qp) { for_constexpr::value>([&](auto i) { process_qf_arg(u[i], v[i], get(args), qp); }); } template MFEM_HOST_DEVICE inline void process_derivative_from_native_dual( DeviceTensor<1, T> &r, const tensor, n, m> &x) { for (size_t i = 0; i < n; i++) { for (size_t j = 0; j < m; j++) { r(i + n * j) = x(i, j).gradient; } } } template MFEM_HOST_DEVICE inline void process_derivative_from_native_dual( DeviceTensor<1, T> &r, const tensor, n> &x) { for (size_t i = 0; i < n; i++) { r(i) = x(i).gradient; } } template MFEM_HOST_DEVICE inline void process_derivative_from_native_dual( DeviceTensor<1, T> &r, const dual &x) { r(0) = x.gradient; } template MFEM_HOST_DEVICE inline void process_qf_arg(const T0 &, T1 &) { static_assert(dfem::always_false, "process_qf_arg not implemented for arg type"); } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<1, T> &u, T &arg) { arg = u(0); } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<1, T> &u, tensor &arg) { arg(0) = u(0); } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<1> &u, tensor &arg) { for (int i = 0; i < n; i++) { arg(i) = u(i); } } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<1> &u, tensor &arg) { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { arg(j, i) = u((i * n) + j); } } } template MFEM_HOST_DEVICE inline void process_qf_arg(const DeviceTensor<2> &u, arg_type &arg, int qp) { const auto u_qp = Reshape(&u(0, qp), u.GetShape()[0]); process_qf_arg(u_qp, arg); } template MFEM_HOST_DEVICE inline void process_qf_args( const std::array, num_fields> &u, qf_args &args, const int &qp) { for_constexpr::value>([&](auto i) { process_qf_arg(u[i], get(args), qp); }); } template MFEM_HOST_DEVICE inline Vector process_qf_result(T0, T1) { static_assert(dfem::always_false, "process_qf_result not implemented for result type"); return Vector{}; } template MFEM_HOST_DEVICE inline void process_qf_result( DeviceTensor<1, T> &r, const T &x) { r(0) = x; } template MFEM_HOST_DEVICE inline void process_qf_result( DeviceTensor<1> &r, const dual &x) { r(0) = x.value; } template MFEM_HOST_DEVICE inline void process_qf_result( DeviceTensor<1, T> &r, const tensor &x) { r(0) = x(0); } template MFEM_HOST_DEVICE inline void process_qf_result( DeviceTensor<1, T> &r, const tensor &x) { for (size_t i = 0; i < n; i++) { r(i) = x(i); } } template MFEM_HOST_DEVICE inline void process_qf_result( DeviceTensor<1, T> &r, const tensor &x) { for (size_t i = 0; i < n; i++) { for (size_t j = 0; j < m; j++) { r(i + n * j) = x(i, j); } } } template MFEM_HOST_DEVICE inline void process_qf_arg( const DeviceTensor<1, T> &u, const DeviceTensor<1, T> &v, tensor &arg) { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { arg(j, i) = u((i * n) + j); } } } } // namespace mfem::future