Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# MFEMVectorBoundaryFluxIntegralPostprocessor

!if! function=hasCapability('mfem')

## Overview

Postprocessor for calculating the integral of the flux of a vector $H^{1,d}$,
$L^{2,d}$, $H(\mathrm{curl})$, or $H(\mathrm{div})$ conforming source variable through a given boundary surface.

!equation
(k \vec v \cdot \hat n)_{\partial\Omega}

where $\vec v \in H^{1,d}$, $L^{2,d}$, $H(\mathrm{curl})$, or $H(\mathrm{div})$,
$k$ is an optional scalar coefficient, $\partial\Omega$ is the user-specified mesh boundary,
and $\hat n$ is the outward facing unit normal vector on the boundary.
If $k$ is provided as a material coefficient, it must be defined on the boundary itself, rather than on a submesh adjacent to the boundary.

## Example Input File Syntax

!listing mfem/submeshes/av_magnetostatic.i block=Postprocessors/CoilCurrent


Comment thread
amg56 marked this conversation as resolved.
Outdated
!syntax parameters /Postprocessors/MFEMVectorBoundaryFluxIntegralPostprocessor

!syntax inputs /Postprocessors/MFEMVectorBoundaryFluxIntegralPostprocessor

!syntax children /Postprocessors/MFEMVectorBoundaryFluxIntegralPostprocessor

!if-end!

!else
!include mfem/mfem_warning.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ and $\Omega$ is the user-specified mesh subdomain.

## Example Input File Syntax

!listing mfem/submeshes/av_magnetostatic.i block=Postprocessors
!listing mfem/submeshes/av_magnetostatic.i block=Postprocessors/CoilPower

!syntax parameters /Postprocessors/MFEMVectorFEInnerProductIntegralPostprocessor

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//* This file is part of the MOOSE framework
//* https://mooseframework.inl.gov
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#ifdef MOOSE_MFEM_ENABLED

#pragma once

#include "MFEMPostprocessor.h"
#include "MFEMBoundaryRestrictable.h"

/**
* Compute the integral of the flux of an MFEM vector variable across a boundary,
* scaled by an optional scalar coefficient.
*/
class MFEMVectorBoundaryFluxIntegralPostprocessor : public MFEMPostprocessor,
public MFEMBoundaryRestrictable
{
public:
static InputParameters validParams();

MFEMVectorBoundaryFluxIntegralPostprocessor(const InputParameters & parameters);

/**
* Evaluate integral.
*/
virtual void execute() override;

/**
* Return the last evaluated integral value.
*/
virtual PostprocessorValue getValue() const override final;

private:
mfem::real_t _integral;
mfem::ParGridFunction & _var;
mfem::Coefficient & _scalar_coef;
mfem::RT_FECollection _rt_fec;
mfem::ParFiniteElementSpace _rt_vector_fespace;
mfem::ParGridFunction _rt_var;
mfem::VectorGridFunctionCoefficient _var_coef;
mfem::ParLinearForm _boundary_integrator;
};

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//* This file is part of the MOOSE framework
//* https://mooseframework.inl.gov
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#ifdef MOOSE_MFEM_ENABLED

#include "MFEMVectorBoundaryFluxIntegralPostprocessor.h"
#include "MFEMProblem.h"

registerMooseObject("MooseApp", MFEMVectorBoundaryFluxIntegralPostprocessor);

InputParameters
MFEMVectorBoundaryFluxIntegralPostprocessor::validParams()
{
InputParameters params = MFEMPostprocessor::validParams();
params += MFEMBoundaryRestrictable::validParams();
params.addClassDescription(
"Calculates the integral of the flux of a vector variable across a boundary.");
params.addParam<MFEMScalarCoefficientName>(
"coefficient", "1.", "Name of optional scalar coefficient to scale integrand by.");
params.addRequiredParam<VariableName>("variable", "Name of the vector variable.");
return params;
}

MFEMVectorBoundaryFluxIntegralPostprocessor::MFEMVectorBoundaryFluxIntegralPostprocessor(
const InputParameters & parameters)
: MFEMPostprocessor(parameters),
MFEMBoundaryRestrictable(parameters,
*getMFEMProblem()
.getProblemData()
.gridfunctions.Get(getParam<VariableName>("variable"))
->ParFESpace()
->GetParMesh()),
Comment thread
amg56 marked this conversation as resolved.
Outdated
_var(
getMFEMProblem().getProblemData().gridfunctions.GetRef(getParam<VariableName>("variable"))),
_scalar_coef(getScalarCoefficient("coefficient")),
_rt_fec(_var.ParFESpace()->GetMaxElementOrder(), getMesh().Dimension()),
_rt_vector_fespace(const_cast<mfem::ParMesh *>(&getMesh()), &_rt_fec),
_rt_var(&_rt_vector_fespace),
_var_coef(&_var),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make _var_coef a reference, and then you can drop _var and just retrieve the existing coefficient for that variable:

Suggested change
_var_coef(&_var),
_var_coef(getVectorCoefficient("variable")),

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_var is also used on Line 42 to get the order of the vector variable space, to set up the RT projection space correctly. It's cleaner for _var_coef but unless there's a similar fix for _rt_fec, _var is still needed.

_boundary_integrator(&_rt_vector_fespace)
{
_boundary_integrator.AddBoundaryIntegrator(
new mfem::VectorFEBoundaryFluxLFIntegrator(_scalar_coef), getBoundaryMarkers());
}

void
MFEMVectorBoundaryFluxIntegralPostprocessor::execute()
{
_rt_var.ProjectBdrCoefficientNormal(_var_coef, getBoundaryMarkers());
_boundary_integrator.Assemble();
_integral = _boundary_integrator(_rt_var);
}

PostprocessorValue
MFEMVectorBoundaryFluxIntegralPostprocessor::getValue() const
{
return _integral;
}

#endif
45 changes: 45 additions & 0 deletions test/tests/mfem/submeshes/av_magnetostatic.i
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,20 @@
type = MFEMProblem
[]

[SubMeshes]
inactive = 'fluxcut'
[fluxcut]
type = MFEMCutTransitionSubMesh
cut_boundary = 'MeasurementPlane'
block = 'TorusCore TorusSheath'
transition_subdomain = transition_dom
transition_subdomain_boundary = transition_bdr
closed_subdomain = coil_dom
[]
[]

[FESpaces]
inactive = 'FluxFESpace'
[HCurlFESpace]
type = MFEMVectorFESpace
fec_type = ND
Expand All @@ -21,6 +34,12 @@
fec_type = RT
fec_order = CONSTANT
[]
[FluxFESpace]
type = MFEMVectorFESpace
fec_type = ND
fec_order = FIRST
submesh = fluxcut
[]
[]

[Variables]
Expand All @@ -31,6 +50,7 @@
[]

[AuxVariables]
inactive = 'flux_e_field'
[b_field]
type = MFEMVariable
fespace = HDivFESpace
Expand All @@ -39,6 +59,10 @@
type = MFEMVariable
fespace = HCurlFESpace
[]
[flux_e_field]
type = MFEMVariable
fespace = FluxFESpace
[]
[]

[AuxKernels]
Expand Down Expand Up @@ -70,6 +94,7 @@
[]

[FunctorMaterials]
inactive = 'ConductorBoundary'
[Vacuum]
type = MFEMGenericFunctorMaterial
prop_names = reluctivity
Expand All @@ -81,6 +106,12 @@
prop_values = 1.0
block = 'TorusCore TorusSheath'
[]
[ConductorBoundary]
type = MFEMGenericFunctorMaterial
prop_names = conductivity_boundary
prop_values = 1.0
boundary = 'MeasurementPlane'
[]
[]

[Kernels]
Expand Down Expand Up @@ -131,22 +162,36 @@
[]

[Transfers]
inactive = 'submesh_transfer_to_fluxsurface'
[from_coil]
type = MultiAppMFEMCopyTransfer
source_variable = e_field
variable = e_field
from_multi_app = coil
[]
[submesh_transfer_to_fluxsurface]
type = MFEMSubMeshTransfer
from_variable = e_field
to_variable = flux_e_field
execute_on = TIMESTEP_END
[]
[]

[Postprocessors]
inactive = 'CoilCurrent'
[CoilPower]
type = MFEMVectorFEInnerProductIntegralPostprocessor
coefficient = conductivity
dual_variable = e_field
primal_variable = e_field
block = 'TorusCore TorusSheath'
[]
[CoilCurrent]
type = MFEMVectorBoundaryFluxIntegralPostprocessor
coefficient = conductivity_boundary
variable = flux_e_field
boundary = 'MeasurementPlane'
[]
[]

[Outputs]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
time,CoilCurrent
0,0
1,-0.099634666692599
21 changes: 20 additions & 1 deletion test/tests/mfem/submeshes/tests
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
compute_devices = 'cpu cuda'
max_parallel = 1
recover = false
[]
[]
[MFEMGeometryCutTransitionSubMesh]
design = 'syntax/MFEM/ClosedCoilMagnetostatic.md'
issues = '#31404'
Expand All @@ -58,6 +58,25 @@
recover = false
valgrind = heavy
[]
[MFEMBoundaryFluxCutTransitionSubMesh]
design = 'MFEMVectorBoundaryFluxIntegralPostprocessor.md'
issues = '#32851'
type = CSVDiff
input = av_magnetostatic.i
cli_args = 'SubMeshes/inactive="" '
'FESpaces/inactive="" '
'AuxVariables/inactive="" '
'FunctorMaterials/inactive="" '
'Transfers/inactive="" '
'Postprocessors/inactive="CoilPower" '
'Outputs/ReportedPostprocessors/file_base=OutputData/AVMagnetostaticClosedCoilBoundaryFluxCSV'
csvdiff = 'OutputData/AVMagnetostaticClosedCoilBoundaryFluxCSV.csv'
requirement = 'MOOSE shall have the ability to determine the flux through an internal or external MFEM boundary surface'
capabilities = 'mfem'
compute_devices = 'cpu cuda'
recover = false
valgrind = heavy
[]
[MFEMVacuumCutTransitionSubMesh]
design = 'syntax/MFEM/ClosedCoilMagnetostatic.md'
issues = '#31404'
Expand Down