-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add palace::GridFunction
to unify mfem::ParGridFunction
and mfem::ParComplexGridFunction
#204
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#include "gridfunction.hpp" | ||
|
||
#include "fem/fespace.hpp" | ||
|
||
namespace palace | ||
{ | ||
|
||
GridFunction::GridFunction(mfem::ParFiniteElementSpace &fespace, bool complex) | ||
: gfr(&fespace) | ||
{ | ||
if (complex) | ||
{ | ||
gfi.SetSpace(&fespace); | ||
} | ||
} | ||
|
||
GridFunction::GridFunction(FiniteElementSpace &fespace, bool complex) | ||
: GridFunction(fespace.Get(), complex) | ||
{ | ||
} | ||
|
||
GridFunction &GridFunction::operator=(std::complex<double> s) | ||
{ | ||
Real() = s.real(); | ||
if (HasImag()) | ||
{ | ||
Imag() = s.imag(); | ||
} | ||
else | ||
{ | ||
MFEM_ASSERT( | ||
s.imag() == 0.0, | ||
"Cannot assign complex scalar to a non-complex-valued GridFunction object!"); | ||
} | ||
return *this; | ||
} | ||
|
||
GridFunction &GridFunction::operator*=(double s) | ||
{ | ||
Real() *= s; | ||
if (HasImag()) | ||
{ | ||
Imag() *= s; | ||
} | ||
return *this; | ||
} | ||
|
||
void GridFunction::Update() | ||
{ | ||
Real().Update(); | ||
if (HasImag()) | ||
{ | ||
Imag().Update(); | ||
} | ||
} | ||
|
||
} // namespace palace |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#ifndef PALACE_FEM_GRIDFUNCTION_HPP | ||
#define PALACE_FEM_GRIDFUNCTION_HPP | ||
|
||
#include <mfem.hpp> | ||
|
||
namespace palace | ||
{ | ||
|
||
class FiniteElementSpace; | ||
|
||
// | ||
// A real- or complex-valued grid function represented as two real grid functions, one for | ||
// each component. This unifies mfem::ParGridFunction and mfem::ParComplexGridFunction, and | ||
// replaces the latter due to some issues observed with memory aliasing on GPUs. | ||
// | ||
class GridFunction | ||
{ | ||
private: | ||
mfem::ParGridFunction gfr, gfi; | ||
Comment on lines
+19
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The alternative here is something like
where the I think the runtime flag here is a better approach though, as the template is only going to eliminate if branches at a very high level, so the template isn't really worth it imo. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I considered the template version but came to the same conclusion you have, that the runtime flag is just fine in this case from a performance and from an interface point of view. |
||
|
||
public: | ||
GridFunction(mfem::ParFiniteElementSpace &fespace, bool complex = false); | ||
GridFunction(FiniteElementSpace &fespace, bool complex = false); | ||
|
||
// Get access to the real and imaginary grid function parts. | ||
const mfem::ParGridFunction &Real() const { return gfr; } | ||
mfem::ParGridFunction &Real() { return gfr; } | ||
const mfem::ParGridFunction &Imag() const | ||
{ | ||
MFEM_ASSERT(HasImag(), | ||
"Invalid access of imaginary part of a real-valued GridFunction object!"); | ||
return gfi; | ||
} | ||
mfem::ParGridFunction &Imag() | ||
{ | ||
MFEM_ASSERT(HasImag(), | ||
"Invalid access of imaginary part of a real-valued GridFunction object!"); | ||
return gfi; | ||
} | ||
|
||
// Check if the grid function is suited for storing complex-valued fields. | ||
bool HasImag() const { return (gfi.ParFESpace() != nullptr); } | ||
|
||
// Get access to the underlying finite element space (match MFEM interface). | ||
mfem::FiniteElementSpace *FESpace() { return gfr.FESpace(); } | ||
const mfem::FiniteElementSpace *FESpace() const { return gfr.FESpace(); } | ||
mfem::ParFiniteElementSpace *ParFESpace() { return gfr.ParFESpace(); } | ||
const mfem::ParFiniteElementSpace *ParFESpace() const { return gfr.ParFESpace(); } | ||
|
||
// Set all entries equal to s. | ||
GridFunction &operator=(std::complex<double> s); | ||
GridFunction &operator=(double s) | ||
{ | ||
*this = std::complex<double>(s, 0.0); | ||
return *this; | ||
} | ||
|
||
// Scale all entries by s. | ||
GridFunction &operator*=(double s); | ||
|
||
// Transform for space update (for example on mesh change). | ||
void Update(); | ||
|
||
// Get the associated MPI communicator. | ||
MPI_Comm GetComm() const { return ParFESpace()->GetComm(); } | ||
}; | ||
|
||
} // namespace palace | ||
|
||
#endif // PALACE_FEM_GRIDFUNCTION_HPP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MFEM_ASSERT(s.imag() == 0.0 || !HasImag(), "Cannot assign complex scalar to a non-complex grid function!");
Assigning an actually complex into a real grid function is almost certainly an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in 5f0543e