deeplearning/modulus/modulus-sym/_modules/modulus/sym/eq/pdes/electromagnetic.html

Source code for modulus.sym.eq.pdes.electromagnetic

# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Maxwell's equation
"""

from sympy import Symbol, Function, Number
import numpy as np

from modulus.sym.eq.pde import PDE
from modulus.sym.node import Node

# helper functions computing curl
def _curl(v):
    x, y, z = Symbol("x"), Symbol("y"), Symbol("z")
    dim = len(v)
    if dim == 3:
        vx, vy, vz = v
        return [
            vz.diff(y) - vy.diff(z),
            vx.diff(z) - vz.diff(x),
            vy.diff(x) - vx.diff(y),
        ]
    elif dim == 2:
        vx, vy = v
        return [vy.diff(x) - vx.diff(y)]
    elif dim == 1:
        return [v[0].diff(y), -v[0].diff(x)]
    else:
        raise Exception("Input dimension for Curl operator must be 1, 2 or 3!")


# helper functions computing cross product
def _cross(a, b):
    x, y, z = Symbol("x"), Symbol("y"), Symbol("z")
    dim = len(a)
    if dim == 3:
        a1, a2, a3 = a
        b1, b2, b3 = b
        return [a2 * b3 - a3 * b2, a3 * b1 - a1 * b3, a1 * b2 - a2 * b1]
    elif dim == 2:
        a1, a2 = a
        b1, b2 = b
        return [a1 * b2 - a2 * b1]
    else:
        raise Exception("Input dimension for cross product must be 2 or 3!")


[docs]class MaxwellFreqReal(PDE): """ Frequency domain Maxwell's equation Parameters ========== ux : str Ex uy : str Ey uz : str Ez k : float, Sympy Symbol/Expr, str Wave number. If `k` is a str then it is converted to Sympy Function of form 'k(x,y,z,t)'. If 'k' is a Sympy Symbol or Expression then this is substituted into the equation. mixed_form: bool If True, use the mixed formulation of the diffusion equations. """ name = "MaxwellFreqReal" def __init__(self, ux="ux", uy="uy", uz="uz", k=1.0, mixed_form=False): # set params self.ux = ux self.uy = uy self.uz = uz self.mixed_form = mixed_form if self.mixed_form: raise NotImplementedError( "Maxwell's equation is not implemented in mixed form" ) # coordinates x, y, z = Symbol("x"), Symbol("y"), Symbol("z") # make input variables input_variables = {"x": x, "y": y, "z": z} # wave speed coefficient if isinstance(k, str): k = Function(k)(*input_variables) elif isinstance(k, (float, int)): k = Number(k) # E field assert isinstance(ux, str), "uz needs to be string" ux = Function(ux)(*input_variables) assert isinstance(uy, str), "uy needs to be string" uy = Function(uy)(*input_variables) assert isinstance(uz, str), "uz needs to be string" uz = Function(uz)(*input_variables) # compute del X (del X E) c2ux, c2uy, c2uz = _curl(_curl([ux, uy, uz])) # set equations self.equations = {} self.equations["Maxwell_Freq_real_x"] = c2ux - k**2 * ux self.equations["Maxwell_Freq_real_y"] = c2uy - k**2 * uy self.equations["Maxwell_Freq_real_z"] = c2uz - k**2 * uz
[docs]class SommerfeldBC(PDE): """ Frequency domain ABC, Sommerfeld radiation condition Only for real part Equation: 'n x _curl(E) = 0' Parameters ========== ux : str Ex uy : str Ey uz : str Ez """ name = "SommerfeldBC" def __init__(self, ux="ux", uy="uy", uz="uz"): # set params self.ux = ux self.uy = uy self.uz = uz # coordinates x, y, z = Symbol("x"), Symbol("y"), Symbol("z") normal_x = Symbol("normal_x") normal_y = Symbol("normal_y") normal_z = Symbol("normal_z") # make input variables, t is wave number input_variables = {"x": x, "y": y, "z": z} # E field assert isinstance(ux, str), "uz needs to be string" ux = Function(ux)(*input_variables) assert isinstance(uy, str), "uy needs to be string" uy = Function(uy)(*input_variables) assert isinstance(uz, str), "uz needs to be string" uz = Function(uz)(*input_variables) # compute cross product of curl for sommerfeld bc n = [normal_x, normal_y, normal_z] u = [ux, uy, uz] bcs = _cross(n, _curl(u)) # set equations self.equations = {} self.equations["SommerfeldBC_real_x"] = bcs[0] self.equations["SommerfeldBC_real_y"] = bcs[1] self.equations["SommerfeldBC_real_z"] = bcs[2]
[docs]class PEC(PDE): """ Perfect Electric Conduct BC for Parameters ========== ux : str Ex uy : str Ey uz : str Ez dim : int Dimension of the equations (2, or 3). Default is 3. """ name = "PEC_3D" def __init__(self, ux="ux", uy="uy", uz="uz", dim=3): # set params self.ux = ux self.uy = uy self.uz = uz self.dim = dim # coordinates x, y, z = Symbol("x"), Symbol("y"), Symbol("z") normal_x = Symbol("normal_x") normal_y = Symbol("normal_y") normal_z = Symbol("normal_z") # make input variables, t is wave number input_variables = {"x": x, "y": y, "z": z} # E field assert isinstance(ux, str), "uz needs to be string" ux = Function(ux)(*input_variables) assert isinstance(uy, str), "uy needs to be string" uy = Function(uy)(*input_variables) if self.dim == 3: assert isinstance(uz, str), "uz needs to be string" uz = Function(uz)(*input_variables) # compute cross of electric field if self.dim == 2: n = [normal_x, normal_y] u = [ux, uy] elif self.dim == 3: n = [normal_x, normal_y, normal_z] u = [ux, uy, uz] else: raise ValueError("'dim' needs to be 2 or 3") bcs = _cross(n, u) # set equations self.equations = {} self.equations["PEC_x"] = bcs[0] if self.dim == 3: self.equations["PEC_y"] = bcs[1] self.equations["PEC_z"] = bcs[2]
© Copyright 2023, NVIDIA Modulus Team. Last updated on Jan 25, 2024.