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

Perfect Periodic BC #266

Merged
merged 33 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
a8ad62d
add .vscode to .gitignore
LeilaGhaffari Jun 26, 2024
5e3629a
Add test for perfect periodic boundary condition
LeilaGhaffari Jun 13, 2024
86a15b9
Populate the face dofs on the boundaries
LeilaGhaffari Jun 25, 2024
228d3fa
modify palace::FiniteElementSpace::BuildCeedBasis to work with L2 fes…
LeilaGhaffari Jul 25, 2024
e731091
Add interface for user-defined periodicity
LeilaGhaffari Jul 30, 2024
af41a41
Removed the duplicate boundary elements on periodic surfaces.
LeilaGhaffari Aug 13, 2024
61b9b89
Fix format
LeilaGhaffari Aug 13, 2024
c1bdbe7
This BE removal works for everybody except for MFEM meshes that are a…
LeilaGhaffari Aug 14, 2024
42314d3
Add a validation test: rectangular waveguide
LeilaGhaffari Aug 14, 2024
4cc0b11
geodata.cpp: a clearer error message
LeilaGhaffari Aug 16, 2024
dfa05d0
Add support for periodic BCs with lexicographic elements
LeilaGhaffari Aug 16, 2024
04500b7
PR Feedback
hughcars Aug 19, 2024
9d3555f
Remove all cube tests
LeilaGhaffari Aug 19, 2024
dfab373
Rename: GetFESpaceForTraceElement -> GetTraceElement
LeilaGhaffari Aug 20, 2024
d87b169
more refinement/cleanup
LeilaGhaffari Aug 20, 2024
8bae88a
MFEM_VERIFY when more than one direction is passed for a donor/receiv…
LeilaGhaffari Aug 20, 2024
ddc90f5
Distance should be in mesh units
LeilaGhaffari Aug 20, 2024
63bd460
Make a box mesh for arbitrary lengths
LeilaGhaffari Aug 20, 2024
037caa1
Remove the cube example
LeilaGhaffari Aug 21, 2024
06e093f
scripts/schema/config/boundaries.json: Add "Direction" and "Distance"…
LeilaGhaffari Aug 22, 2024
bfd8115
MFEM_VERIFY if MakePeriodic hasn't been successful in making the mesh…
LeilaGhaffari Aug 23, 2024
083e436
User passes "Translation" vector instead of Direction and Distance to…
LeilaGhaffari Aug 24, 2024
c4695a3
examples/cavity: update mesh.jl to differentiate top, bottom, and ext…
LeilaGhaffari Aug 28, 2024
8fc2066
examples/cavity: also updated the tet and hex meshes
LeilaGhaffari Aug 28, 2024
720da6a
Rename example cavity->cylinder (TODO: update doc)
LeilaGhaffari Aug 28, 2024
b9c05f4
Add cylinder/waveguide regression test
LeilaGhaffari Aug 29, 2024
d51bb91
fix format
LeilaGhaffari Aug 29, 2024
b5f12ba
waveguide test - only keep 15 modes
LeilaGhaffari Aug 29, 2024
747a357
docs: add cylinder/waveguide
LeilaGhaffari Aug 29, 2024
3c4b04a
Update cylinder meshes and config files to refine in gmsh
hughcars Sep 3, 2024
b1fc363
Merge branch 'main' into hughcars/periodic-bc
hughcars Sep 3, 2024
880c1ff
Update CHANGELOG
hughcars Sep 3, 2024
4c2fb95
Minor fixes to doc file
hughcars Sep 4, 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ test/examples/ref/**/*.json
.DS_Store
.gitlab-ci-local
Manifest.toml
.vscode/
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ makedocs(
"examples/examples.md",
"examples/spheres.md",
"examples/rings.md",
"examples/cavity.md",
"examples/cylinder.md",
"examples/coaxial.md",
"examples/cpw.md"
],
Expand Down
32 changes: 32 additions & 0 deletions docs/src/config/boundaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
[
...
],
"Periodic":
[
...
],
"Postprocessing":
{
"Side": <string>,
Expand Down Expand Up @@ -121,6 +125,9 @@ surface.
electrostatic simulations. Entries of the capacitance matrix are extracted corresponding to
each terminal boundary.

`"Periodic"` : Array of objects for configuring periodic boundary conditions. This imposes
periodicity on boundary surfaces that have identical meshes, meaning they are topologically periodic.

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

`"Side" ["SmallerRefractiveIndex"]` : Defines the postprocessing side for internal
Expand Down Expand Up @@ -512,6 +519,31 @@ to index the computed capacitance matrix.
`"Attributes" [None]` : Integer array of mesh boundary attributes for this terminal
boundary.

## `boundaries["Periodic"]`

```json
"Periodic":
[
{
"DonorAttributes": [<int array>],
"ReceiverAttributes": [<int array>],
"Translation": [<float array>]
},
...
]
```

with

`"DonorAttributes" [None]` : Integer array of the donor attributes of the mesh boundary
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.

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

```json
Expand Down
67 changes: 58 additions & 9 deletions docs/src/examples/cavity.md → docs/src/examples/cylinder.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
<!--- SPDX-License-Identifier: Apache-2.0 --->
```

# Eigenmodes of a Cylindrical Cavity
# Eigenmodes of a Cylinder

!!! note

The files for this example can be found in the
[`examples/cavity/`](https://github.com/awslabs/palace/blob/main/examples/cavity)
[`examples/cylinder/`](https://github.com/awslabs/palace/blob/main/examples/cylinder)
directory of the *Palace* source code.

## Cavity

This example demonstrates *Palace*'s eigenmode simulation type to solve for the lowest
frequency modes of a cylindrical cavity resonator. In particular, we consider a cylindrical
cavity filled with Teflon (``\varepsilon_r = 2.08``,
Expand Down Expand Up @@ -55,12 +57,12 @@ where ``k=\omega\sqrt{\mu\varepsilon}``, ``\eta=\sqrt{\mu/\varepsilon}``, and
``\beta=l\pi/d``.

The initial Gmsh mesh for this problem, from
[`mesh/cavity_prism.msh`](https://github.com/awslabs/palace/blob/main/examples/cavity/mesh/cavity_prism.msh),
[`mesh/cavity_prism.msh`](https://github.com/awslabs/palace/blob/main/examples/cylinder/mesh/cavity_prism.msh),
is shown below. We use quadratic triangular prism elements. There are also two other
included mesh files,
[`mesh/cavity_tet.msh`](https://github.com/awslabs/palace/blob/main/examples/cavity/mesh/cavity_tet.msh)
[`mesh/cavity_tet.msh`](https://github.com/awslabs/palace/blob/main/examples/cylinder/mesh/cavity_tet.msh)
and
[`mesh/cavity_hex.msh`](https://github.com/awslabs/palace/blob/main/examples/cavity/mesh/cavity_hex.msh),
[`mesh/cavity_hex.msh`](https://github.com/awslabs/palace/blob/main/examples/cylinder/mesh/cavity_hex.msh),
which use curved tetrahedral and hexahedral elements, respectively.

```@raw html
Expand All @@ -70,9 +72,9 @@ which use curved tetrahedral and hexahedral elements, respectively.
```

There are two configuration files for this problem,
[`cavity_pec.json`](https://github.com/awslabs/palace/blob/main/examples/cavity/cavity_pec.json)
[`cavity_pec.json`](https://github.com/awslabs/palace/blob/main/examples/cylinder/cavity_pec.json)
and
[`cavity_impedance.json`](https://github.com/awslabs/palace/blob/main/examples/cavity/cavity_impedance.json).
[`cavity_impedance.json`](https://github.com/awslabs/palace/blob/main/examples/cylinder/cavity_impedance.json).

In both, the [`config["Problem"]["Type"]`](../config/problem.md#config%5B%22Problem%22%5D)
field is set to `"Eigenmode"`, and we use the mesh shown above. The material properties for
Expand Down Expand Up @@ -188,10 +190,10 @@ for the ``\text{TE}_{011}`` mode is shown below.
</p>
```

## Mesh convergence
### Mesh convergence

The effect of mesh size can be investigated for the cylindrical cavity resonator using
[`convergence_study.jl`](https://github.com/awslabs/palace/blob/main/examples/cavity/convergence_study.jl).
[`convergence_study.jl`](https://github.com/awslabs/palace/blob/main/examples/cylinder/convergence_study.jl).
For a polynomial order of solution and refinement level, a mesh is generated using Gmsh
using polynomials of the same order to resolve the boundary geometry. The eigenvalue
problem is then solved for ``f_{\text{TM},010}`` and ``f_{\text{TE},111}``, and the
Expand All @@ -215,6 +217,53 @@ maximum convergence rate is ``2p`` [[2]](#References). The figures demonstrate t
increasing the polynomial order of the solution will give reduced error, however the effect
may only become significant on sufficiently refined meshes.

## Waveguide

This example demonstrates the eigenmode simulation type in *Palace* to solve for the
eigenfrequencies of a circular waveguide. We consider the interior material to be vacuum
with parameters ``\varepsilon_r = 1.0`` and ``\tan\delta = 0``, and with radius
``a = 2.74\text{ cm}`` and height ``d = 2a``.
Periodic boundary conditions (BCs) are applied in the $z$-direction with the wavelength $\lambda = d$.
According to [[1]](#References), the propagation constants of the ``\text{TE}_{nm}`` and ``\text{TM}_{nm}``
modes are given by

```math
\beta_{nm} = \frac{2 \pi}{\lambda} = \sqrt{\left( 2\pi f\sqrt{\mu\varepsilon} \right)^2 - \left(\frac{p^\prime_{nm}}{a}\right)^2}
```

where $p^\prime_{nm}$ is defined in [[1]](#References). Thus, the corresponding analytical
eigenfrequencies are given by

```math
f_{nm} = \sqrt{\frac{\frac{1}{\lambda^2} + \left(\frac{p^\prime_{nm}}{2\pi a}\right)^2}{\mu\varepsilon}}
```

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).

The main difference between this configuration file and those used in the cavity example is in the
`"Boundaries"` object. In `cavity_pec.json` and `cavity_impedance.json`, either a perfect electric
conductor or impedance boundary condition is prescribed on all boundaries.
In contrast, `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.

After running `waveguide.json`, we find that some of the frequencies listed in `postpro/waveguide/eig.csv`
are close to those computed using the above formula. The differences between the analytical and numerical
mode frequencies are summarized in the table below:

| ``\text{mode}`` | ``f_{\text{analytical}}`` | ``f_{\text{numerical}}`` | ``\text{relative error}`` |
|:------------------ | -------------------------:| ------------------------:| -------------------------:|
| ``\text{TM}_{01}`` | ``6.89438\text{ GHz}`` | ``6.895697\text{ GHz}`` | ``0.01911\text{ \%}`` |
| ``\text{TE}_{11}`` | ``6.34515\text{ GHz}`` | ``6.346605\text{ GHz}`` | ``0.02288\text{ \%}`` |
| ``\text{TE}_{21}`` | ``7.63480\text{ GHz}`` | ``7.635135\text{ GHz}`` | ``0.00434\text{ \%}`` |

Note that the spurious frequencies in `postpro/waveguide/eig.csv` have been ignored.
hughcars marked this conversation as resolved.
Show resolved Hide resolved

## References

[1] D. M. Pozar, _Microwave Engineering_, Wiley, Hoboken, NJ, 2012.\
Expand Down
2 changes: 1 addition & 1 deletion docs/src/examples/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ more details.

- [Capacitance Matrix for Two Spheres](spheres.md)
- [Inductance Matrix for a Pair of Concentric Rings](rings.md)
- [Eigenmodes of a Cylindrical Cavity](cavity.md)
- [Eigenmodes of a Cylinder](cylinder.md)
- [Signal Propagation in a Coaxial Cable](coaxial.md)
- [Crosstalk Between Coplanar Waveguides](cpw.md)
29 changes: 15 additions & 14 deletions examples/cavity/cavity.jl → examples/cylinder/cavity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ include(joinpath(@__DIR__, "mesh", "mesh.jl"))

Solve the cavity mode problem, with an automatically generated Gmsh mesh

See also [`generate_cylindrical_cavity_mesh`](@ref)
See also [`generate_cylindrical_mesh`](@ref)

# Arguments

Expand All @@ -34,8 +34,8 @@ See also [`generate_cylindrical_cavity_mesh`](@ref)
- geo_order - the polynomial order used in the mesh representation
- refinement - the level of mesh refinement
- mesh_type - 0 = tetrahedral mesh, 1 = prism mesh, 2 = hexahedral mesh
- radius - the radius of the cavity resonator
- aspect_ratio - the ratio of the DIAMETER of the cavity to the height
- radius - the radius of the cylinder
- aspect_ratio - the ratio of the DIAMETER of the cylinder to the height
- num_processors - number of processors to use for the simulation
- cleanup_files - delete temporary mesh and configuration files after simulation
"""
Expand All @@ -56,10 +56,10 @@ function solve_cavity_resonator(
@assert mesh_type ∈ [0, 1, 2]

# Generate a mesh
cavity_dir = @__DIR__
cylinder_dir = @__DIR__
file_root = string("cavity_p", order, "_h", refinement)
mesh_filename = string(file_root, ".msh")
generate_cylindrical_cavity_mesh(
generate_cylindrical_mesh(
filename=mesh_filename,
refinement=refinement,
order=geo_order,
Expand All @@ -71,14 +71,14 @@ function solve_cavity_resonator(

# Generate solver parameter file
params["Solver"]["Order"] = order
params["Model"]["Mesh"] = joinpath(cavity_dir, "mesh", mesh_filename)
params["Model"]["Mesh"] = joinpath(cylinder_dir, "mesh", mesh_filename)
json_filename = string(file_root, ".json")
open(joinpath(cavity_dir, json_filename), "w") do f
open(joinpath(cylinder_dir, json_filename), "w") do f
return JSON.print(f, params)
end

# Call the solver, storing the terminal output
call_command = Cmd(`palace -np $num_processors $json_filename`, dir=cavity_dir)
call_command = Cmd(`palace -np $num_processors $json_filename`, dir=cylinder_dir)
log_file = read(call_command, String)
# println(log_file)

Expand All @@ -89,13 +89,14 @@ function solve_cavity_resonator(
dof = parse(Int, filter(isdigit, log_file[start_ind:end_ind]))

# Extract the top two frequency modes
eig_df = CSV.read(joinpath(cavity_dir, "postpro", "convergence", "eig.csv"), DataFrame)
eig_df =
CSV.read(joinpath(cylinder_dir, "postpro", "convergence", "eig.csv"), DataFrame)
eig = Matrix(eig_df[:, 2:end])[:, 1]

# Clean up the parameter and mesh file
if cleanup_files
rm(joinpath(cavity_dir, "mesh", mesh_filename))
rm(joinpath(cavity_dir, json_filename))
rm(joinpath(cylinder_dir, "mesh", mesh_filename))
rm(joinpath(cylinder_dir, json_filename))
end

return dof, eig
Expand Down Expand Up @@ -212,14 +213,14 @@ function generate_cavity_convergence_data(;
num_processors::Integer = 1
)
# Load the default JSON script (the file contains comments and we need to sanitize them)
cavity_dir = @__DIR__
params = open(joinpath(cavity_dir, "cavity_pec.json"), "r") do f
cylinder_dir = @__DIR__
params = open(joinpath(cylinder_dir, "cavity_pec.json"), "r") do f
return JSON.parse(join(getindex.(split.(eachline(f), "//"), 1), "\n"))
end

# Update the dictionary
params["Problem"]["Verbose"] = 2
params["Problem"]["Output"] = joinpath(cavity_dir, "postpro", "convergence")
params["Problem"]["Output"] = joinpath(cylinder_dir, "postpro", "convergence")
params["Model"]["Refinement"]["UniformLevels"] = 0 # Don't perform any mesh refinement
params["Solver"]["Eigenmode"]["Save"] = 0 # Don't write any fields to file
params["Solver"]["Eigenmode"]["N"] = 4 # Look only for the top 4 modes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
{
"Type": "Eigenmode",
"Verbose": 2,
"Output": "postpro/impedance"
"Output": "postpro/cavity_impedance"
},
"Model":
{
"Mesh": "mesh/cavity_prism.msh",
"Mesh": "mesh/cylinder_prism.msh",
"L0": 1.0e-2, // cm
"Refinement":
{
Expand Down Expand Up @@ -41,7 +41,7 @@
"Impedance":
[
{
"Attributes": [2],
"Attributes": [2, 3, 5],
"Rs": 0.0184 // Ω, surface resistance of Cu @ 5 GHz
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
{
"Type": "Eigenmode",
"Verbose": 2,
"Output": "postpro/pec"
"Output": "postpro/cavity_pec"
},
"Model":
{
"Mesh": "mesh/cavity_prism.msh",
"Mesh": "mesh/cylinder_prism.msh",
"L0": 1.0e-2, // cm
"Refinement":
{
Expand Down Expand Up @@ -40,7 +40,7 @@
{
"PEC":
{
"Attributes": [2]
"Attributes": [2, 3, 5]
}
},
"Solver":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ for mesh_type ∈ [0, 1, 2]
println("k_f_TM_010 =", map(x -> round.(x, digits=2), k_f_TM_010))
println("k_f_TE_111 =", map(x -> round.(x, digits=2), k_f_TE_111))

cavity_dir = @__DIR__
output_dir = joinpath(cavity_dir, "postpro", "convergence")
cylinder_dir = @__DIR__
output_dir = joinpath(cylinder_dir, "postpro", "convergence")
lmesh_name = lowercase(mesh_name)

savefig(pp, joinpath(output_dir, string("cavity_error_", lmesh_name, ".png")))
Expand Down
Loading