Skip to content
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

Support Floquet periodic boundary conditions #314

Open
wants to merge 64 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
86d6055
Try different ways to compute the affine transformation matrix
simlapointe Oct 25, 2024
31a4a9b
Add periodic boundary operator class for periodic/floquet BCs
simlapointe Oct 29, 2024
6420322
Improve Bloch wave vector specification and fix some bugs
simlapointe Oct 31, 2024
707b32b
Initial implementation of floquet periodicity terms in governing equa…
simlapointe Oct 31, 2024
82d1d61
Update surface normal calculation and add planar boundary check
simlapointe Nov 1, 2024
1de268d
Fix some with floquet operators and their use in eigensolver
simlapointe Nov 1, 2024
95502e2
Remove some prints
simlapointe Nov 1, 2024
6021e8f
Add a new matrix for the mass periodic term
simlapointe Nov 8, 2024
0301a71
Ensure enough mesh elements in the periodic direction
simlapointe Nov 12, 2024
63096b3
Debugging tests
simlapointe Nov 13, 2024
974da2a
Debugging tests
simlapointe Nov 19, 2024
3f6bef0
Allow non-symmetric material properties and merge floquet terms in a …
simlapointe Nov 25, 2024
975a274
Merge floquet periodic terms into one operator
simlapointe Nov 25, 2024
57e6d3a
Remove print
simlapointe Nov 25, 2024
c45ef21
Use CEED Symmetric operator
simlapointe Nov 25, 2024
ff552d2
Merge branch 'main' into simlapointe/periodic-bc
simlapointe Nov 25, 2024
5a4f614
Disable divergence-free projection when using Floquet BCs
simlapointe Nov 26, 2024
447df80
Define vector indices in SetOperator
simlapointe Nov 26, 2024
e2d6e46
Constrain Floquet wave vector components
simlapointe Nov 26, 2024
49b29e4
Update comments since quadrature data is no longer symmetric
simlapointe Nov 26, 2024
e8b0d95
Add floquet periodic mass term to auxiliary operator
simlapointe Dec 2, 2024
3b2700c
Merge main
simlapointe Dec 2, 2024
951d70f
Fix formatting
simlapointe Dec 3, 2024
1557829
Merge branch 'main' into simlapointe/periodic-bc
simlapointe Dec 3, 2024
7dfcccc
Warn against using div-free projection and Floquet BCs
simlapointe Dec 4, 2024
e687ab9
Combine periodic terms in a single helper functions
simlapointe Dec 4, 2024
967c6e6
Test term to help aux space smoother
simlapointe Dec 4, 2024
12ab759
Test Floquet terms in divergence free projection
simlapointe Dec 6, 2024
e713a6f
Clean and reorganize automated periodic boundary matching
simlapointe Dec 6, 2024
b5ef9bd
Remove print
simlapointe Dec 6, 2024
9382889
Use symmetricOperator
simlapointe Dec 6, 2024
6a27333
Add Floquet BC regression test
simlapointe Dec 6, 2024
bebcab6
Allow Floquet wave vector specification for meshes with and without b…
simlapointe Dec 9, 2024
1101ef9
Fix error in VERIFY
simlapointe Dec 10, 2024
0dd577d
Implement B field Floquet correction
simlapointe Dec 10, 2024
00e4b8c
Clean up periodic transform detection
simlapointe Dec 10, 2024
cc6aeca
Undo Floquet divfree test
simlapointe Dec 12, 2024
0a862ec
Use RT-space B field correction
simlapointe Dec 12, 2024
f2288a5
Remove Aux space preconditioner tests
simlapointe Dec 12, 2024
9fbe941
Remove print
simlapointe Dec 12, 2024
b865e9c
Undo Aux space preconditioner tests
simlapointe Dec 12, 2024
18eab19
Remove print
simlapointe Dec 12, 2024
a01573c
Remove unnecessary include
simlapointe Dec 12, 2024
76e325b
Update regression test results
simlapointe Dec 12, 2024
650dce3
Fix formatting
simlapointe Dec 12, 2024
2e2ae18
Update CHANGELOG
simlapointe Dec 13, 2024
102386d
Remove prints
simlapointe Dec 13, 2024
7a1d90e
Initialize Floquet correction solver outside of frequency loop
simlapointe Dec 13, 2024
14c8ce3
Remove unnecessary comments
simlapointe Dec 13, 2024
7259f7c
Update schema for Floquet BCs
simlapointe Dec 13, 2024
4ea97e0
Fix bug assuming symmetric coefficients
simlapointe Dec 13, 2024
d72f40d
Update waveguide example
simlapointe Dec 13, 2024
320b333
Merge branch 'main' into simlapointe/periodic-bc
simlapointe Dec 13, 2024
ed3532e
Merge branch 'main' into simlapointe/periodic-bc
simlapointe Dec 30, 2024
f0e0c2e
Remove complex coarse solve code before merging in main
simlapointe Dec 30, 2024
d7e972a
Merge branch 'main' into simlapointe/periodic-bc
simlapointe Dec 30, 2024
494a51a
Fix formatting
simlapointe Dec 30, 2024
d31c929
Update docs
simlapointe Dec 30, 2024
5ae3cf3
Use FP for Floquet periodic term
simlapointe Dec 30, 2024
a4ea4f1
Fix formatting
simlapointe Dec 30, 2024
c14cb5b
Add comments
simlapointe Dec 30, 2024
d21f1e7
Update docs
simlapointe Dec 30, 2024
81a8fec
Update docs
simlapointe Dec 30, 2024
a029c60
Update docs
simlapointe Dec 31, 2024
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ The format of this changelog is based on
- Added an option to use the complex-valued system matrix for the coarse level solve (sparse
direct solve) instead of the real-valued approximation. This can be specified with
`config["Solver"]["Linear"]["ComplexCoarseSolve"]`.
- Added support for Floquet periodic boundary conditions with phase-delay constraints.
The Floquet wave vector can be specified along with periodic boundaries in the
`config["Boundaries"]["Periodic"]` configuration.

## [0.13.0] - 2024-05-20

Expand Down
36 changes: 32 additions & 4 deletions docs/src/config/boundaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@
[
...
],
"FloquetWaveVector":
[
...
],
"Postprocessing":
{
"SurfaceFlux":
Expand Down Expand Up @@ -125,7 +129,10 @@ electrostatic simulations. Entries of the capacitance matrix are extracted corre
each terminal boundary.

`"Periodic"` : Array of objects for configuring periodic boundary conditions for surfaces
with meshes that are identical after a specified translation.
with meshes that are identical after translation and/or rotation.

`"FloquetWaveVector"` : Array for specifying Floquet wave vector for
meshes generated with built-in periodicity.

`"Postprocessing"` : Top-level object for configuring boundary postprocessing.

Expand Down Expand Up @@ -527,7 +534,9 @@ boundary.
{
"DonorAttributes": [<int array>],
"ReceiverAttributes": [<int array>],
"Translation": [<float array>]
"Translation": [<float array>],
"AffineTransformation": [<float array>],
"FloquetWaveVector": [<float array>]
},
...
]
Expand All @@ -541,8 +550,27 @@ attributes for this periodic boundary.
`"ReceiverAttributes" [None]` : Integer array of the receiver attributes of the mesh boundary
attributes for this periodic boundary.

`"Translation" [None]` : Defines the distance between the donor and receiver attributes in
mesh units.
`"Translation" [None]` : Optional floating point array defining the distance from the donor
attribute to the receiver attribute in mesh units. If neither `"Translation"` or
`"AffineTransformation"` are specified, the transformation between donor and receiver boundaries
Comment on lines +554 to +555
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: neither "Translation" nor "AffineTransformation"

is automatically detected.

`"AffineTransformation" [None]` : Optional floating point array of size 16 defining the
three-dimensional (4 x 4) affine transformation matrix (in row major format) from the donor attribute
to the receiver attribute in mesh units. If neither `"Translation"` or `"AffineTransformation"` are
specified, the transformation between donor and receiver boundaries is automatically detected.

`"FloquetWaveVector" [None]` : Optional floating point array defining the phase delay between
this pair of donor and receiver periodic boundaries in the X/Y/Z directions in radians per mesh
unit. If multiple periodic boundary pairs are used, the Floquet wave vector will be summed over
the periodic boundary pairs.

## `boundaries["FloquetWaveVector"]`

Optional floating point array defining the phase delay between the periodic boundaries in the X/Y/Z
directions in radians per mesh unit, for meshes generated with built-in periodicity. This should not
be used for non-periodic meshes, or for meshes generated without built-in periodicity. In the latter
case, the Floquet wave vector should be specified via `"boundaries["Periodic"]["FloquetWaveVector"]"`.

## `boundaries["Postprocessing"]["SurfaceFlux"]`

Expand Down
8 changes: 6 additions & 2 deletions docs/src/config/solver.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,10 +432,14 @@ iterative solver choices, and the default choice depends on the iterative solver
- `"Default"`

`"DivFreeTol" [1.0e-12]` : Relative tolerance for divergence-free cleaning used in the
eigenmode simulation type.
eigenmode simulation type. Ignored if non-zero Floquet wave vector is specified in
[`config["Boundaries"]["Periodic"]["FloquetWaveVector"]`](boundaries.md##boundaries%5B%%22Periodic%22%5D%22FloquetWaveVector%22%5D)
or [`config["Boundaries"]["FloquetWaveVector"]`](boundaries.md##boundaries%5B%%22FloquetWaveVector%22%5D).
Comment on lines +435 to +437
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is also necessary for London equations, so you'll need to reconcile this.


`"DivFreeMaxIts" [1000]` : Maximum number of iterations for divergence-free cleaning use in
the eigenmode simulation type.
the eigenmode simulation type. Ignored if non-zero Floquet wave vector is specified in
[`config["Boundaries"]["Periodic"]["FloquetWaveVector"]`](boundaries.md##boundaries%5B%%22Periodic%22%5D%22FloquetWaveVector%22%5D)
or [`config["Boundaries"]["FloquetWaveVector"]`](boundaries.md##boundaries%5B%%22FloquetWaveVector%22%5D).

`"EstimatorTol" [1.0e-6]` : Relative tolerance for flux projection used in the
error estimate calculation.
Expand Down
11 changes: 7 additions & 4 deletions docs/src/examples/cylinder.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,15 +254,18 @@ such modes to higher frequencies. The relevant modes are tabulated as

For this problem, we use curved tetrahedral elements from the mesh file
[`mesh/cavity_tet.msh`](https://github.com/awslabs/palace/blob/main/examples/cylinder/mesh/cavity_tet.msh),
and the configuration file
[`waveguide.json`](https://github.com/awslabs/palace/blob/main/examples/cylinder/waveguide.json).
and the configuration files
[`waveguide.json`](https://github.com/awslabs/palace/blob/main/examples/cylinder/waveguide.json) and
[`floquet.json`](https://github.com/awslabs/palace/blob/main/examples/cylinder/floquet.json).

The main difference between this configuration file and those used in the cavity example is
The main difference between these configuration files and those used in the cavity example is
in the `"Boundaries"` object: `waveguide.json` specifies a perfect electric conductor
(`"PEC"`) boundary condition for the exterior surface and a periodic boundary condition
(`"Periodic"`) on the cross-sections of the cylinder (in the $z-$ direction). The periodic
attribute pairs are defined by `"DonorAttributes"` and `"ReceiverAttributes"`, and the
distance between them is given by the `"Translation"` vector in mesh units.
distance between them is given by the `"Translation"` vector in mesh units. In `floquet.json`,
an additional `"FloquetWaveVector"` specifies the phase delay between the donor and receiver
boundaries in the X/Y/Z directions.
Comment on lines +266 to +268
Copy link
Collaborator

Choose a reason for hiding this comment

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

Given the relative simplicity of this example, it would be great if we can derive the expected modes analytically. I suspect it'll be possible to map them to an equivalent set of modes on a full length cylinder without phase shift, at which point analytic results can be compared against like for the waveguide case.


The file `postpro/waveguide/eig.csv` contains information about the computed eigenfrequencies and
associated quality factors:
Expand Down
2 changes: 1 addition & 1 deletion docs/src/guide/boundaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Periodic boundary conditions on an existing mesh can be specified using the
["Periodic"](../config/boundaries.md#boundaries%5B%22Periodic%22%5D) boundary keyword. This
boundary condition enforces that the solution on the specified boundaries be exactly equal,
and requires that the surface meshes on the donor and receiver boundaries be identical up to
translation. Periodicity in *Palace* is also supported through meshes generated
translation or rotation. Periodicity in *Palace* is also supported through meshes generated
Copy link
Collaborator

Choose a reason for hiding this comment

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

How have you tested the rotational case? Might make for a cool example, thinking plausibly the waveguide cylinder could be split into wedges maybe and analyzed.

incorporating periodicity as part of the meshing process.

## Lumped and wave port excitation
Expand Down
1 change: 0 additions & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,4 @@ the frequency or time domain, using the
- Improved adaptive mesh refinement (AMR) support for transient simulations and numeric
wave ports on nonconformal meshes
- Perfectly matched layer (PML) boundaries
- Periodic boundaries with phase delay constraints
- Automatic mesh generation and optimization
69 changes: 69 additions & 0 deletions examples/cylinder/floquet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"Problem":
{
"Type": "Eigenmode",
"Verbose": 2,
"Output": "postpro/floquet"
},
"Model":
{
"Mesh": "mesh/cylinder_tet.msh",
"L0": 1.0e-2, // cm
},
"Domains":
{
"Materials":
[
{
"Attributes": [1],
"Permeability": 1.0,
"Permittivity": 2.08,
"LossTan": 0.0004
}
],
"Postprocessing":
{
"Energy":
[
{
"Index": 1,
"Attributes": [1]
}
]
}
},
"Boundaries":
{
"Periodic":
[
{
"DonorAttributes": [2],
"ReceiverAttributes": [3],
"FloquetWaveVector": [0.0, 0.0, 0.2]
}
],
"PEC":
{
"Attributes": [4]
}
},
"Solver":
{
"Order": 4,
"Device": "CPU",
"Eigenmode":
{
"N": 15,
"Tol": 1.0e-8,
"Target": 2.0, // TE f111 ~ 2.9 GHz
"Save": 15
},
"Linear":
{
"Type": "Default",
"KSPType": "GMRES",
"Tol": 1.0e-8,
"MaxIts": 100
}
}
}
2 changes: 1 addition & 1 deletion examples/cylinder/waveguide.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
{
"DonorAttributes": [2],
"ReceiverAttributes": [3],
"Translation": [0.0, 0.0, 5.48] // in L0 units
"Translation": [0.0, 0.0, -5.48] // in L0 units
}
],
"PEC":
Expand Down
22 changes: 19 additions & 3 deletions palace/drivers/drivensolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "fem/errorindicator.hpp"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Missing the correction on the adaptive branch.

#include "fem/mesh.hpp"
#include "linalg/errorestimator.hpp"
#include "linalg/floquetcorrection.hpp"
#include "linalg/ksp.hpp"
#include "linalg/operator.hpp"
#include "linalg/vector.hpp"
Expand Down Expand Up @@ -117,17 +118,17 @@ ErrorIndicator DrivenSolver::SweepUniform(SpaceOperator &space_op, PostOperator
auto C = space_op.GetDampingMatrix<ComplexOperator>(Operator::DIAG_ZERO);
auto M = space_op.GetMassMatrix<ComplexOperator>(Operator::DIAG_ZERO);
auto A2 = space_op.GetExtraSystemMatrix<ComplexOperator>(omega0, Operator::DIAG_ZERO);
auto FP = space_op.GetFloquetMatrix<ComplexOperator>(Operator::DIAG_ZERO);
const auto &Curl = space_op.GetCurlMatrix();

// Set up the linear solver and set operators for the first frequency step. The
// preconditioner for the complex linear system is constructed from a real approximation
// to the complex system matrix.
auto A = space_op.GetSystemMatrix(std::complex<double>(1.0, 0.0), 1i * omega0,
std::complex<double>(-omega0 * omega0, 0.0), K.get(),
C.get(), M.get(), A2.get());
C.get(), M.get(), A2.get(), FP.get());
auto P = space_op.GetPreconditionerMatrix<ComplexOperator>(1.0, omega0, -omega0 * omega0,
omega0);

ComplexKspSolver ksp(iodata, space_op.GetNDSpaces(), &space_op.GetH1Spaces());
ksp.SetOperators(*A, *P);

Expand All @@ -147,6 +148,15 @@ ErrorIndicator DrivenSolver::SweepUniform(SpaceOperator &space_op, PostOperator
iodata.solver.linear.estimator_mg);
ErrorIndicator indicator;

// If using Floquet BCs, a correction term (kp x E) needs to be added to the B field.
std::unique_ptr<FloquetCorrSolver<ComplexVector>> floquet_corr;
if (FP)
{
floquet_corr = std::make_unique<FloquetCorrSolver<ComplexVector>>(
space_op.GetMaterialOp(), space_op.GetPeriodicOp(), space_op.GetNDSpace(),
space_op.GetRTSpace(), iodata.solver.linear.tol, iodata.solver.linear.max_it, 0);
}

// Main frequency sweep loop.
int step = step0;
double omega = omega0;
Expand All @@ -164,7 +174,7 @@ ErrorIndicator DrivenSolver::SweepUniform(SpaceOperator &space_op, PostOperator
A2 = space_op.GetExtraSystemMatrix<ComplexOperator>(omega, Operator::DIAG_ZERO);
A = space_op.GetSystemMatrix(std::complex<double>(1.0, 0.0), 1i * omega,
std::complex<double>(-omega * omega, 0.0), K.get(),
C.get(), M.get(), A2.get());
C.get(), M.get(), A2.get(), FP.get());
P = space_op.GetPreconditionerMatrix<ComplexOperator>(1.0, omega, -omega * omega,
omega);
ksp.SetOperators(*A, *P);
Expand All @@ -179,6 +189,12 @@ ErrorIndicator DrivenSolver::SweepUniform(SpaceOperator &space_op, PostOperator
Curl.Mult(E.Real(), B.Real());
Curl.Mult(E.Imag(), B.Imag());
B *= -1.0 / (1i * omega);
if (FP)
{
// Calculate B field correction for Floquet BCs.
// B = -1/(iω) ∇ x E - 1/ω kp x E
floquet_corr->AddMult(E, B, -1.0 / omega);
}
post_op.SetEGridFunction(E);
post_op.SetBGridFunction(B);
post_op.UpdatePorts(space_op.GetLumpedPortOp(), space_op.GetWavePortOp(), omega);
Expand Down
42 changes: 38 additions & 4 deletions palace/drivers/eigensolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "linalg/arpack.hpp"
#include "linalg/divfree.hpp"
#include "linalg/errorestimator.hpp"
#include "linalg/floquetcorrection.hpp"
#include "linalg/ksp.hpp"
#include "linalg/operator.hpp"
#include "linalg/slepc.hpp"
Expand Down Expand Up @@ -36,6 +37,10 @@ EigenSolver::Solve(const std::vector<std::unique_ptr<Mesh>> &mesh) const
auto K = space_op.GetStiffnessMatrix<ComplexOperator>(Operator::DIAG_ONE);
auto C = space_op.GetDampingMatrix<ComplexOperator>(Operator::DIAG_ZERO);
auto M = space_op.GetMassMatrix<ComplexOperator>(Operator::DIAG_ZERO);
auto FP = space_op.GetFloquetMatrix<ComplexOperator>(Operator::DIAG_ZERO);
auto A2 = space_op.GetExtraSystemMatrix<ComplexOperator>(1.0, Operator::DIAG_ZERO);
A2 = nullptr;
Comment on lines +40 to +42
Copy link
Collaborator

Choose a reason for hiding this comment

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

Delete. We don't support the extra system matrix just yet with eigen solves.


const auto &Curl = space_op.GetCurlMatrix();
SaveMetadata(space_op.GetNDSpaces());

Expand Down Expand Up @@ -124,11 +129,25 @@ EigenSolver::Solve(const std::vector<std::unique_ptr<Mesh>> &mesh) const
: EigenvalueSolver::ScaleType::NONE;
if (C)
{
eigen->SetOperators(*K, *C, *M, scale);
if (FP)
{
eigen->SetOperators(*K, *C, *M, *FP, scale);
}
else
{
eigen->SetOperators(*K, *C, *M, scale);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Delete after FP into K.

}
}
else
{
eigen->SetOperators(*K, *M, scale);
if (FP)
{
eigen->SetOperators(*K, *M, *FP, scale);
}
else
{
eigen->SetOperators(*K, *M, scale);
}
}
eigen->SetNumModes(iodata.solver.eigenmode.n, iodata.solver.eigenmode.max_size);
eigen->SetTol(iodata.solver.eigenmode.tol);
Expand All @@ -154,7 +173,7 @@ EigenSolver::Solve(const std::vector<std::unique_ptr<Mesh>> &mesh) const
// Construct a divergence-free projector so the eigenvalue solve is performed in the space
// orthogonal to the zero eigenvalues of the stiffness matrix.
std::unique_ptr<DivFreeSolver<ComplexVector>> divfree;
if (iodata.solver.linear.divfree_max_it > 0)
if (iodata.solver.linear.divfree_max_it > 0 && !FP)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Given this will be disabled for both the London equatio and now Floquet, we should have a better mechanism for knowing if K has a mass term and thus does not have a kernel to remove. Either make an option for asking the operator (complicated) or have a means of setting divfree_max_it to zero in the configfile.cpp based on if Floquet or London equations are active.

{
Mpi::Print(" Configuring divergence-free projection\n");
constexpr int divfree_verbose = 0;
Expand All @@ -165,6 +184,15 @@ EigenSolver::Solve(const std::vector<std::unique_ptr<Mesh>> &mesh) const
eigen->SetDivFreeProjector(*divfree);
}

// If using Floquet BCs, a correction term (kp x E) needs to be added to the B field.
std::unique_ptr<FloquetCorrSolver<ComplexVector>> floquet_corr;
if (FP)
{
floquet_corr = std::make_unique<FloquetCorrSolver<ComplexVector>>(
space_op.GetMaterialOp(), space_op.GetPeriodicOp(), space_op.GetNDSpace(),
space_op.GetRTSpace(), iodata.solver.linear.tol, iodata.solver.linear.max_it, 0);
}
Comment on lines +188 to +194
Copy link
Collaborator

Choose a reason for hiding this comment

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

Rather than checking for the existence of FP, use mat_op.HasLondonDepth() and a new HasWaveVector() or the like.


// Set up the initial space for the eigenvalue solve. Satisfies boundary conditions and is
// projected appropriately.
if (iodata.solver.eigenmode.init_v0)
Expand Down Expand Up @@ -242,7 +270,7 @@ EigenSolver::Solve(const std::vector<std::unique_ptr<Mesh>> &mesh) const
// to the complex system matrix.
auto A = space_op.GetSystemMatrix(std::complex<double>(1.0, 0.0), 1i * target,
std::complex<double>(-target * target, 0.0), K.get(),
C.get(), M.get());
C.get(), M.get(), A2.get(), FP.get());
auto P = space_op.GetPreconditionerMatrix<ComplexOperator>(1.0, target, -target * target,
target);
auto ksp = std::make_unique<ComplexKspSolver>(iodata, space_op.GetNDSpaces(),
Expand Down Expand Up @@ -306,6 +334,12 @@ EigenSolver::Solve(const std::vector<std::unique_ptr<Mesh>> &mesh) const
Curl.Mult(E.Real(), B.Real());
Curl.Mult(E.Imag(), B.Imag());
B *= -1.0 / (1i * omega);
if (FP)
{
// Calculate B field correction for Floquet BCs.
// B = -1/(iω) ∇ x E - 1/ω kp x E.
floquet_corr->AddMult(E, B, -1.0 / omega);
}
post_op.SetEGridFunction(E);
post_op.SetBGridFunction(B);
post_op.UpdatePorts(space_op.GetLumpedPortOp(), omega.real());
Expand Down
Loading
Loading