Files
mfem/fem/ceed/interface/operator.cpp
T

132 lines
3.6 KiB
C++

// 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.
#include "operator.hpp"
#include "../../../config/config.hpp"
#include "../../../linalg/vector.hpp"
#include "../../fespace.hpp"
#include "util.hpp"
#include "ceed.hpp"
namespace mfem
{
namespace ceed
{
#ifdef MFEM_USE_CEED
Operator::Operator(CeedOperator op)
{
oper = op;
CeedSize in_len, out_len;
int ierr = CeedOperatorGetActiveVectorLengths(oper, &in_len, &out_len);
PCeedChk(ierr);
height = out_len;
width = in_len;
MFEM_VERIFY(height == out_len, "height overflow");
MFEM_VERIFY(width == in_len, "width overflow");
CeedVectorCreate(internal::ceed, height, &v);
CeedVectorCreate(internal::ceed, width, &u);
}
#endif
void Operator::Mult(const mfem::Vector &x, mfem::Vector &y) const
{
#ifdef MFEM_USE_CEED
const CeedScalar *x_ptr;
CeedScalar *y_ptr;
CeedMemType mem;
CeedGetPreferredMemType(mfem::internal::ceed, &mem);
if ( Device::Allows(Backend::DEVICE_MASK) && mem==CEED_MEM_DEVICE )
{
x_ptr = x.Read();
y_ptr = y.Write();
}
else
{
x_ptr = x.HostRead();
y_ptr = y.HostWrite();
mem = CEED_MEM_HOST;
}
CeedVectorSetArray(u, mem, CEED_USE_POINTER, const_cast<CeedScalar*>(x_ptr));
CeedVectorSetArray(v, mem, CEED_USE_POINTER, y_ptr);
CeedOperatorApply(oper, u, v, CEED_REQUEST_IMMEDIATE);
CeedVectorTakeArray(u, mem, const_cast<CeedScalar**>(&x_ptr));
CeedVectorTakeArray(v, mem, &y_ptr);
#else
MFEM_ABORT("MFEM must be built with MFEM_USE_CEED=YES to use libCEED.");
#endif
}
void Operator::AddMult(const mfem::Vector &x, mfem::Vector &y,
const real_t a) const
{
#ifdef MFEM_USE_CEED
MFEM_VERIFY(a == 1.0, "General coefficient case is not yet supported!");
const CeedScalar *x_ptr;
CeedScalar *y_ptr;
CeedMemType mem;
CeedGetPreferredMemType(mfem::internal::ceed, &mem);
if ( Device::Allows(Backend::DEVICE_MASK) && mem==CEED_MEM_DEVICE )
{
x_ptr = x.Read();
y_ptr = y.ReadWrite();
}
else
{
x_ptr = x.HostRead();
y_ptr = y.HostReadWrite();
mem = CEED_MEM_HOST;
}
CeedVectorSetArray(u, mem, CEED_USE_POINTER, const_cast<CeedScalar*>(x_ptr));
CeedVectorSetArray(v, mem, CEED_USE_POINTER, y_ptr);
CeedOperatorApplyAdd(oper, u, v, CEED_REQUEST_IMMEDIATE);
CeedVectorTakeArray(u, mem, const_cast<CeedScalar**>(&x_ptr));
CeedVectorTakeArray(v, mem, &y_ptr);
#else
MFEM_ABORT("MFEM must be built with MFEM_USE_CEED=YES to use libCEED.");
#endif
}
void Operator::GetDiagonal(mfem::Vector &diag) const
{
#ifdef MFEM_USE_CEED
CeedScalar *d_ptr;
CeedMemType mem;
CeedGetPreferredMemType(mfem::internal::ceed, &mem);
if ( Device::Allows(Backend::DEVICE_MASK) && mem==CEED_MEM_DEVICE )
{
d_ptr = diag.ReadWrite();
}
else
{
d_ptr = diag.HostReadWrite();
mem = CEED_MEM_HOST;
}
CeedVectorSetArray(v, mem, CEED_USE_POINTER, d_ptr);
CeedOperatorLinearAssembleAddDiagonal(oper, v, CEED_REQUEST_IMMEDIATE);
CeedVectorTakeArray(v, mem, &d_ptr);
#else
MFEM_ABORT("MFEM must be built with MFEM_USE_CEED=YES to use libCEED.");
#endif
}
} // namespace ceed
} // namespace mfem