LCOV - code coverage report
Current view: top level - src/bcs - VectorEMRobinBC.C (source / functions) Hit Total Coverage
Test: idaholab/moose electromagnetics: #31405 (292dce) with base fef103 Lines: 78 78 100.0 %
Date: 2025-09-04 07:52:56 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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"
      12             : #include "ElectromagneticConstants.h"
      13             : #include "Function.h"
      14             : #include <complex>
      15             : 
      16             : registerMooseObject("ElectromagneticsApp", VectorEMRobinBC);
      17             : 
      18             : InputParameters
      19         534 : VectorEMRobinBC::validParams()
      20             : {
      21         534 :   InputParameters params = VectorIntegratedBC::validParams();
      22         534 :   params.addClassDescription("First order Robin-style Absorbing/Port BC for vector variables.");
      23        1068 :   params.addParam<FunctionName>("beta", 1.0, "Scalar wave number.");
      24        1068 :   MooseEnum component("real imaginary");
      25        1068 :   params.addParam<MooseEnum>(
      26             :       "component", component, "Variable field component (real or imaginary).");
      27        1068 :   params.addRequiredCoupledVar("coupled_field", "Coupled field variable.");
      28        1068 :   params.addParam<FunctionName>("real_incoming", 0.0, "Real incoming field vector.");
      29        1068 :   params.addParam<FunctionName>("imag_incoming", 0.0, "Imaginary incoming field vector.");
      30        1068 :   MooseEnum mode("absorbing port", "port");
      31        1068 :   params.addParam<MooseEnum>("mode", mode, "Mode of operation for VectorEMRobinBC.");
      32         534 :   return params;
      33         534 : }
      34             : 
      35         288 : VectorEMRobinBC::VectorEMRobinBC(const InputParameters & parameters)
      36             :   : VectorIntegratedBC(parameters),
      37             : 
      38         288 :     _beta(getFunction("beta")),
      39             : 
      40         576 :     _component(getParam<MooseEnum>("component")),
      41             : 
      42         288 :     _coupled_val(coupledVectorValue("coupled_field")),
      43         288 :     _coupled_var_num(coupled("coupled_field")),
      44             : 
      45         288 :     _inc_real(getFunction("real_incoming")),
      46         288 :     _inc_imag(getFunction("imag_incoming")),
      47             : 
      48         576 :     _mode(getParam<MooseEnum>("mode")),
      49             : 
      50         288 :     _real_incoming_was_set(parameters.isParamSetByUser("real_incoming")),
      51         576 :     _imag_incoming_was_set(parameters.isParamSetByUser("imag_incoming"))
      52             : {
      53         288 :   if (_mode == EM::ABSORBING && (_real_incoming_was_set || _imag_incoming_was_set))
      54             :   {
      55           2 :     mooseError(
      56             :         "In ",
      57           2 :         _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         286 : }
      62             : 
      63             : Real
      64    10819864 : VectorEMRobinBC::computeQpResidual()
      65             : {
      66             :   // Initialize E components
      67    10819864 :   std::complex<double> field_0(0, 0);
      68    10819864 :   std::complex<double> field_1(0, 0);
      69    10819864 :   std::complex<double> field_2(0, 0);
      70             : 
      71             :   // Create E and ncrossE for residual based on component parameter
      72    10819864 :   if (_component == EM::REAL)
      73             :   {
      74     5409932 :     field_0.real(_u[_qp](0));
      75     5409932 :     field_0.imag(_coupled_val[_qp](0));
      76             : 
      77     5409932 :     field_1.real(_u[_qp](1));
      78     5409932 :     field_1.imag(_coupled_val[_qp](1));
      79             : 
      80     5409932 :     field_2.real(_u[_qp](2));
      81     5409932 :     field_2.imag(_coupled_val[_qp](2));
      82             :   }
      83             :   else
      84             :   {
      85     5409932 :     field_0.real(_coupled_val[_qp](0));
      86     5409932 :     field_0.imag(_u[_qp](0));
      87             : 
      88     5409932 :     field_1.real(_coupled_val[_qp](1));
      89     5409932 :     field_1.imag(_u[_qp](1));
      90             : 
      91     5409932 :     field_2.real(_coupled_val[_qp](2));
      92     5409932 :     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             : 
     104             :   /**
     105             :    * Stops us calling un-implemented methods within the scalar ConstantFunction
     106             :    * default for _inc_real and _inc_imag function variables, since we don't have
     107             :    * an automatic vector function constant default in MOOSE FEProblemBase right now.
     108             :    */
     109    10819864 :   if (_real_incoming_was_set && _imag_incoming_was_set)
     110             :   {
     111             :     // Creating vector, curl for field_inc before residual and Jacobian contributions
     112    10800640 :     RealVectorValue inc_real_value = _inc_real.vectorValue(_t, _q_point[_qp]);
     113    10800640 :     RealVectorValue inc_imag_value = _inc_imag.vectorValue(_t, _q_point[_qp]);
     114    10800640 :     RealVectorValue inc_real_curl = _inc_real.curl(_t, _q_point[_qp]);
     115    10800640 :     RealVectorValue inc_imag_curl = _inc_imag.curl(_t, _q_point[_qp]);
     116             : 
     117    10800640 :     std::complex<double> field_inc_0(inc_real_value(0), inc_imag_value(0));
     118    10800640 :     std::complex<double> field_inc_1(inc_real_value(1), inc_imag_value(1));
     119    10800640 :     std::complex<double> field_inc_2(inc_real_value(2), inc_imag_value(2));
     120    10800640 :     field_inc = VectorValue<std::complex<double>>(field_inc_0, field_inc_1, field_inc_2);
     121             : 
     122    10800640 :     std::complex<double> curl_inc_0(inc_real_curl(0), inc_imag_curl(0));
     123    10800640 :     std::complex<double> curl_inc_1(inc_real_curl(1), inc_imag_curl(1));
     124    10800640 :     std::complex<double> curl_inc_2(inc_real_curl(2), inc_imag_curl(2));
     125    10800640 :     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    10819864 :   switch (_mode)
     135             :   {
     136    10800640 :     case EM::PORT:
     137             :       // Calculate incoming wave contribution to BC residual
     138    10800640 :       u_inc_dot_test = _test[_i][_qp].cross(_normals[_qp]) * curl_inc +
     139    10800640 :                        EM::j * _beta.value(_t, _q_point[_qp]) *
     140    10800640 :                            (_test[_i][_qp].cross(_normals[_qp]) * _normals[_qp].cross(field_inc));
     141    10800640 :       break;
     142             :     case EM::ABSORBING:
     143             :       break;
     144             :   }
     145             : 
     146             :   // Calculate solution field contribution to BC residual (first order version)
     147    10819864 :   std::complex<double> p_dot_test = EM::j * _beta.value(_t, _q_point[_qp]) *
     148    10819864 :                                     _test[_i][_qp].cross(_normals[_qp]) *
     149    10819864 :                                     _normals[_qp].cross(field);
     150             : 
     151             :   std::complex<double> diff = u_inc_dot_test - p_dot_test;
     152             :   Real res = 0.0;
     153    10819864 :   switch (_component)
     154             :   {
     155             :     case EM::REAL:
     156             :       res = diff.real();
     157     5409932 :       break;
     158             :     case EM::IMAGINARY:
     159             :       res = diff.imag();
     160     5409932 :       break;
     161             :   }
     162    10819864 :   return res;
     163             : }
     164             : 
     165             : Real
     166      100516 : VectorEMRobinBC::computeQpJacobian()
     167             : {
     168      100516 :   return 0.0;
     169             : }
     170             : 
     171             : Real
     172      100516 : VectorEMRobinBC::computeQpOffDiagJacobian(unsigned int jvar)
     173             : {
     174      100516 :   Real off_diag_jac = _beta.value(_t, _q_point[_qp]) * _test[_i][_qp].cross(_normals[_qp]) *
     175      100516 :                       _normals[_qp].cross(_phi[_j][_qp]);
     176             : 
     177      100516 :   if (_component == EM::REAL && jvar == _coupled_var_num)
     178             :     return off_diag_jac;
     179       50258 :   else if (_component == EM::IMAGINARY && jvar == _coupled_var_num)
     180       50258 :     return -off_diag_jac;
     181             :   else
     182             :     return 0.0;
     183             : }

Generated by: LCOV version 1.14