https://mooseframework.inl.gov
VectorEMRobinBC.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "VectorEMRobinBC.h"
11 #include "ElectromagneticEnums.h"
13 #include "Function.h"
14 #include <complex>
15 
16 registerMooseObject("ElectromagneticsApp", VectorEMRobinBC);
17 
20 {
22  params.addClassDescription("First order Robin-style Absorbing/Port BC for vector variables.");
23  params.addParam<FunctionName>("beta", 1.0, "Scalar wave number.");
24  MooseEnum component("real imaginary");
25  params.addParam<MooseEnum>(
26  "component", component, "Variable field component (real or imaginary).");
27  params.addRequiredCoupledVar("coupled_field", "Coupled field variable.");
28  params.addParam<FunctionName>("real_incoming", 0.0, "Real incoming field vector.");
29  params.addParam<FunctionName>("imag_incoming", 0.0, "Imaginary incoming field vector.");
30  MooseEnum mode("absorbing port", "port");
31  params.addParam<MooseEnum>("mode", mode, "Mode of operation for VectorEMRobinBC.");
32  return params;
33 }
34 
36  : VectorIntegratedBC(parameters),
37 
38  _beta(getFunction("beta")),
39 
40  _component(getParam<MooseEnum>("component")),
41 
42  _coupled_val(coupledVectorValue("coupled_field")),
43  _coupled_var_num(coupled("coupled_field")),
44 
45  _inc_real(getFunction("real_incoming")),
46  _inc_imag(getFunction("imag_incoming")),
47 
48  _mode(getParam<MooseEnum>("mode")),
49 
50  _real_incoming_was_set(parameters.isParamSetByUser("real_incoming")),
51  _imag_incoming_was_set(parameters.isParamSetByUser("imag_incoming"))
52 {
54  {
55  mooseError(
56  "In ",
57  _name,
58  ", mode was set to Absorbing, while an incoming profile function (used for Port BCs) was "
59  "defined. Either remove the profile function parameters, or set your BC to Port mode!");
60  }
61 }
62 
63 Real
65 {
66  // Initialize E components
67  std::complex<double> field_0(0, 0);
68  std::complex<double> field_1(0, 0);
69  std::complex<double> field_2(0, 0);
70 
71  // Create E and ncrossE for residual based on component parameter
72  if (_component == EM::REAL)
73  {
74  field_0.real(_u[_qp](0));
75  field_0.imag(_coupled_val[_qp](0));
76 
77  field_1.real(_u[_qp](1));
78  field_1.imag(_coupled_val[_qp](1));
79 
80  field_2.real(_u[_qp](2));
81  field_2.imag(_coupled_val[_qp](2));
82  }
83  else
84  {
85  field_0.real(_coupled_val[_qp](0));
86  field_0.imag(_u[_qp](0));
87 
88  field_1.real(_coupled_val[_qp](1));
89  field_1.imag(_u[_qp](1));
90 
91  field_2.real(_coupled_val[_qp](2));
92  field_2.imag(_u[_qp](2));
93  }
94  VectorValue<std::complex<double>> field(field_0, field_1, field_2);
95 
96  // Initialize proper zero defaults for the case when real and imag incoming functions are not set
97  VectorValue<std::complex<double>> field_inc(std::complex<double>(0.0, 0.0),
98  std::complex<double>(0.0, 0.0),
99  std::complex<double>(0.0, 0.0));
100  VectorValue<std::complex<double>> curl_inc(std::complex<double>(0.0, 0.0),
101  std::complex<double>(0.0, 0.0),
102  std::complex<double>(0.0, 0.0));
103 
110  {
111  // Creating vector, curl for field_inc before residual and Jacobian contributions
112  RealVectorValue inc_real_value = _inc_real.vectorValue(_t, _q_point[_qp]);
113  RealVectorValue inc_imag_value = _inc_imag.vectorValue(_t, _q_point[_qp]);
114  RealVectorValue inc_real_curl = _inc_real.curl(_t, _q_point[_qp]);
115  RealVectorValue inc_imag_curl = _inc_imag.curl(_t, _q_point[_qp]);
116 
117  std::complex<double> field_inc_0(inc_real_value(0), inc_imag_value(0));
118  std::complex<double> field_inc_1(inc_real_value(1), inc_imag_value(1));
119  std::complex<double> field_inc_2(inc_real_value(2), inc_imag_value(2));
120  field_inc = VectorValue<std::complex<double>>(field_inc_0, field_inc_1, field_inc_2);
121 
122  std::complex<double> curl_inc_0(inc_real_curl(0), inc_imag_curl(0));
123  std::complex<double> curl_inc_1(inc_real_curl(1), inc_imag_curl(1));
124  std::complex<double> curl_inc_2(inc_real_curl(2), inc_imag_curl(2));
125  curl_inc = VectorValue<std::complex<double>>(curl_inc_0, curl_inc_1, curl_inc_2);
126  }
127 
128  // Do some error checking
129  mooseAssert(_beta.value(_t, _q_point[_qp]) > 0,
130  "Wave number expected to be positive, calculated to be "
131  << _beta.value(_t, _q_point[_qp]));
132 
133  std::complex<double> u_inc_dot_test = 0.0;
134  switch (_mode)
135  {
136  case EM::PORT:
137  // Calculate incoming wave contribution to BC residual
138  u_inc_dot_test = _test[_i][_qp].cross(_normals[_qp]) * curl_inc +
139  EM::j * _beta.value(_t, _q_point[_qp]) *
140  (_test[_i][_qp].cross(_normals[_qp]) * _normals[_qp].cross(field_inc));
141  break;
142  case EM::ABSORBING:
143  break;
144  }
145 
146  // Calculate solution field contribution to BC residual (first order version)
147  std::complex<double> p_dot_test = EM::j * _beta.value(_t, _q_point[_qp]) *
148  _test[_i][_qp].cross(_normals[_qp]) *
149  _normals[_qp].cross(field);
150 
151  std::complex<double> diff = u_inc_dot_test - p_dot_test;
152  Real res = 0.0;
153  switch (_component)
154  {
155  case EM::REAL:
156  res = diff.real();
157  break;
158  case EM::IMAGINARY:
159  res = diff.imag();
160  break;
161  }
162  return res;
163 }
164 
165 Real
167 {
168  return 0.0;
169 }
170 
171 Real
173 {
174  Real off_diag_jac = _beta.value(_t, _q_point[_qp]) * _test[_i][_qp].cross(_normals[_qp]) *
175  _normals[_qp].cross(_phi[_j][_qp]);
176 
177  if (_component == EM::REAL && jvar == _coupled_var_num)
178  return off_diag_jac;
179  else if (_component == EM::IMAGINARY && jvar == _coupled_var_num)
180  return -off_diag_jac;
181  else
182  return 0.0;
183 }
VectorEMRobinBC(const InputParameters &parameters)
unsigned int _j
const Function & _beta
Scalar waveguide propagation constant.
const VectorVariableValue & _coupled_val
Coupled field vector variable.
virtual Real computeQpResidual() override
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
virtual RealVectorValue curl(Real t, const Point &p) const
static const std::string component
Definition: NS.h:153
unsigned int _i
unsigned int _qp
static InputParameters validParams()
const MooseArray< Point > & _q_point
Case when the boundary is configured to absorb impinging electromagnetic radiation.
const bool _real_incoming_was_set
Boolean marking whether real component of the incoming wave was set by the user.
const Function & _inc_real
Real incoming field vector.
virtual Real computeQpJacobian() override
const Function & _inc_imag
Imaginary incoming field vector.
const bool _imag_incoming_was_set
Boolean marking whether imaginary component of the incoming wave was set by the user.
Case when the boundary is configured to both absorb impinging electromagnetic radiation and launch an...
const MooseArray< Point > & _normals
const VectorVariableTestValue & _test
const MooseEnum _component
Variable field component (real or imaginary)
const std::string _name
const MooseEnum _mode
Mode of operation (absorbing or port)
registerMooseObject("ElectromagneticsApp", VectorEMRobinBC)
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
virtual RealVectorValue vectorValue(Real t, const Point &p) const
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
unsigned int _coupled_var_num
Coupled field vector variable id.
static InputParameters validParams()
const VectorVariableValue & _u
virtual Real value(Real t, const Point &p) const
First order Robin-style Absorbing/Port boundary condition for vector nonlinear variables.
const VectorVariablePhiValue & _phi