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

added alternative radial stub model #33

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
266 changes: 254 additions & 12 deletions src/components/microstrip/msrstub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ msrstub::msrstub () : circuit (1) {

// Returns the microstrip radial stub reactance.
nr_double_t msrstub::calcReactance (nr_double_t r1, nr_double_t r2,
nr_double_t alpha, nr_double_t er,
nr_double_t phi, nr_double_t er,
nr_double_t h, nr_double_t frequency) {

nr_double_t l0 = C0 / frequency;
nr_double_t W = (r1 + (r2 - r1) / 2) * deg2rad (alpha);
nr_double_t W = (r1 + (r2 - r1) / 2) * (phi);
nr_double_t ereff = (er + 1.0) / 2 + (er - 1.0) /
(2.0 * qucs::sqrt (1 + 10.0 * h / W));
nr_double_t k = 2.0 * pi * qucs::sqrt (ereff) / l0;
Expand All @@ -55,7 +55,7 @@ nr_double_t msrstub::calcReactance (nr_double_t r1, nr_double_t r2,
nr_double_t phi_1 = qucs::atan (-j1 (a) / y1 (a));
nr_double_t phi_2 = qucs::atan (-j1 (b) / y1 (b));

nr_double_t X1 = h * Z_0 / (2.0 * pi * r1) * 360.0 / alpha *
nr_double_t X1 = h * Z_0 / (2.0 * pi * r1) * (2.0 * pi / phi) *
qucs::cos (theta_1 - phi_2) / qucs::sin (phi_1 - phi_2);

return X1;
Expand All @@ -67,17 +67,248 @@ void msrstub::calcSP (nr_double_t frequency) {

nr_complex_t msrstub::calcZ (nr_double_t frequency) {

/* get properties of this component */
nr_double_t r1 = getPropertyDouble ("ri");
nr_double_t r2 = getPropertyDouble ("ro");
nr_double_t al = getPropertyDouble ("alpha");

/* get properties of the substrate */
//radial stub - get parameters
substrate * subst = getSubstrate ();
nr_double_t er = subst->getPropertyDouble ("er");
nr_double_t h = subst->getPropertyDouble ("h");
nr_double_t r_i = getPropertyDouble ("ri"); //inner radius
nr_double_t r_o = getPropertyDouble ("ro"); //outer radius
nr_double_t phi = deg2rad(getPropertyDouble ("alpha")); //stub radius (called phi in formulas, although left alpha in UI)
nr_double_t w = getPropertyDouble ("Wf"); //feed line width
nr_double_t h = subst->getPropertyDouble ("h"); //substrate thickness
nr_double_t t = subst->getPropertyDouble ("t"); //metal thickness
nr_double_t eps_r = subst->getPropertyDouble ("er"); //substrate relative permittivity
nr_double_t resist = subst->getPropertyDouble ("rho"); //metal resistivity
nr_double_t loss_tan = subst->getPropertyDouble ("tand"); //loss tangent of substrate
const char * EffDimens = getPropertyString ("EffDimens");
const char * Model = getPropertyString ("Model");

////////////////////////////////////////////
//corrected dimensions of the stub to account for fringing fields:
nr_double_t p = r_i * qucs::cos(phi/2); //the following intermediate values can be put into conditions to speed up calculations of siple models, like no corrections at all
nr_double_t u = w / h;
nr_double_t del_u1 = t / pi * qucs::log(1 + 4*euler / (t * qucs::pow(qucs::coth(qucs::sqrt(6.517*u)), 2.0)));
nr_double_t w_e = w + h * del_u1 / 2 * (1 + 1 / (qucs::cosh(qucs::sqrt(eps_r - 1))));
nr_double_t r_s = (2 * p + w_e - w) / (2 * qucs::cos(phi/2));

nr_double_t u_rad = (phi * r_s) / h;
nr_double_t del_u1_rad = t / pi * qucs::log(1 + 4*euler / (t * qucs::pow(qucs::coth(qucs::sqrt(6.517*u_rad)), 2.0)));
nr_double_t w_e_phi_r_s = (phi * r_s) + h * del_u1_rad / 2 * (1 + 1 / (qucs::cosh(qucs::sqrt(eps_r - 1))));
nr_double_t del_rs = (w_e_phi_r_s - phi * r_s) / 2;

nr_double_t w_g = (2 * p + w_e - w) * qucs::tan(phi/2);
nr_double_t w_ge = w_g + 2 * del_rs / qucs::cos(phi/2);

nr_double_t r_ie;
nr_double_t r_oe;

if (!strcmp (EffDimens, "Chew_Kong")) {
r_ie = r_s + del_rs / qucs::tan(phi/2) + del_rs * qucs::tan(phi/2);
r_oe = r_o * qucs::sqrt(1 + 2 * h / (pi * eps_r * r_o) * (qucs::log(pi * r_o / (2 * h)) + 1.7726));
}
else if (!strcmp (EffDimens, "Giannini")) {
r_ie = w_e / (2 * qucs::sin(phi/2));
r_oe = r_o * qucs::sqrt(1 + 2 * h / (pi * r_o) * (qucs::log(pi * r_o / (2 * h)) + 1.7726)) + (w_e - w) / (2 * qucs::sin(phi/2));
}
else
{
r_ie = r_i;
r_oe = r_o;
}


if (!strcmp (Model, "March")) {

// effective dielectric constant of line with width (r_o + r_i) * sin(phi/2)
nr_double_t w_eq_stub = (r_o + r_i) * qucs::sin(phi/2);
nr_double_t u_eq_stub = w_eq_stub / h;
nr_double_t a_feed_eq_stub = 1.0 + 1.0/49.0 * qucs::log((qucs::pow(u_eq_stub, 4.0) + qucs::pow(u_eq_stub/52.0, 2.0)) / (qucs::pow(u_eq_stub, 4.0) + 0.432)) + 1.0/18.7 * qucs::log(1.0 + qucs::pow(u_eq_stub/18.1, 3.0));
nr_double_t b_feed_eq_stub = 0.564 * qucs::pow((eps_r - 0.9) / (eps_r + 3), 0.053);
nr_double_t eps_e1_eq_stub = (eps_r + 1.0) / 2.0 + (eps_r - 1.0) / 2.0 * qucs::pow(1.0 + 10.0/u_eq_stub, -a_feed_eq_stub * b_feed_eq_stub);
nr_double_t eps_e_eq_stub = eps_e1_eq_stub; // TODO, eq 4.6 - skipped the correction (copper thickness?), to clarify, maybe check https://pure.tue.nl/ws/files/46936050/640261-1.pdf
//complex propagation constant (with losses):
nr_double_t depth = qucs::sqrt(resist / (pi * frequency * 1 * MU0)); //calculate skin depth (assume mu relative 1)
if(depth > t)
depth = t;
nr_double_t Rsurf = resist / depth; //surface resistivity
nr_double_t k_beta = 2 * pi * frequency * qucs::sqrt(eps_e_eq_stub) / C0; //real part of complex wavenumber
nr_double_t k_alpha = Rsurf * qucs::sqrt(eps_e_eq_stub) / (Z0) + k_beta / 2 * loss_tan; //imaginary part of complex wavenumber (losses)
nr_complex_t k = nr_complex_t(k_beta, -k_alpha);

//impedance calculation
nr_double_t Z0_rie = Z0 * h / (r_ie * phi * qucs::sqrt(eps_e_eq_stub));
nr_complex_t cot_krie_kroe = (yn(0, k * r_ie) * jn(1, k * r_oe) - jn(0, k * r_ie) * yn(1, k * r_oe)) /
(jn(1, k * r_ie) * yn(1, k * r_oe) - yn(1, k * r_ie) * jn(1, k * r_oe));
nr_complex_t Zin = nr_complex_t(0, -1) * Z0_rie * cot_krie_kroe;
return Zin;
}

else if (!strcmp (Model, "Giannini")) {

// Solving equation for k0n:
// J'0(k0n*r_oe) * Y'0(k0n*r_ie) - J'0(k0n*r_ie) * Y'0(k0n*r_oe) = 0
// note that J'0(x)=-J1(x)
int n_max = 20; //how long is the series to calculate - adjust for acceptable accuracy and computation time
nr_double_t k0n_steps = 2 * pi / (4 * r_o) * 0.002; // estimate step in finding the roots numerically (estimate wavenember of first resonance of lambda/4 stub, step is 0.2%)
nr_double_t k0n_root[n_max], k0n_x, k0n_x_inc;
for(int i_root = 0, zeros_cnt = 0; zeros_cnt < n_max; ++i_root)
{
k0n_x = i_root * k0n_steps;
k0n_x_inc = (i_root+1) * k0n_steps;
if ((jn(1, k0n_x*r_oe) * yn(1, k0n_x*r_ie) - jn(1, k0n_x*r_ie) * yn(1, k0n_x*r_oe)) *
(jn(1, k0n_x_inc*r_oe) * yn(1, k0n_x_inc*r_ie) - jn(1, k0n_x_inc*r_ie) * yn(1, k0n_x_inc*r_oe)) < 0)
{
k0n_root[zeros_cnt] = k0n_x;
++zeros_cnt;
}
}

return nr_complex_t (0, calcReactance (r1, r2, al, er, h, frequency));

// free space wavenumber
nr_double_t k = 2.0 * pi * frequency / C0;

// kg - wavenumber of feed line
nr_double_t a_feed = 1.0 + 1.0/49.0 * qucs::log((qucs::pow(u, 4.0) + qucs::pow(u/52.0, 2.0)) / (qucs::pow(u, 4.0) + 0.432)) + 1.0/18.7 * qucs::log(1.0 + qucs::pow(u/18.1, 3.0));
nr_double_t b_feed = 0.564 * qucs::pow((eps_r - 0.9) / (eps_r + 3), 0.053);
nr_double_t eps_e1_feed_eff = (eps_r + 1.0) / 2.0 + (eps_r - 1.0) / 2.0 * qucs::pow(1.0 + 10.0/u, -a_feed * b_feed);
nr_double_t eps_e_feed_eff = eps_e1_feed_eff; // TODO, eq 4.6 - skipped the correction (copper thickness?), to clarify, maybe check https://pure.tue.nl/ws/files/46936050/640261-1.pdf
nr_double_t kg = 2.0 * pi * frequency * qucs::sqrt(eps_e_feed_eff) / C0; // feed line wavenumber (should be complex?)

// characteristic impedance of the radial stub
nr_double_t Z0rs = Z0 * h / (r_ie * phi * qucs::sqrt(eps_r));

// static mode Qt and P coefficients
nr_double_t Qt0 = 1.0 / loss_tan;
nr_double_t P0 = qucs::sqrt((2.0 * w_ge) / (phi * (qucs::pow(r_oe, 2.0) - qucs::pow(r_ie, 2.0)))); // is the alpha the same as phi (angle of stub)?


// impedance and phase velocity in annular and radial directions for capacitances calculations
// annular:
nr_double_t w_ann = r_o - r_i;
nr_double_t del_u1_ann = t / pi * qucs::log(1.0 + 4.0 * euler / (t * qucs::pow((qucs::coth(qucs::sqrt(6.517 * w_ann/h))), 2.0))); //not sure if correction for effective width is needed here, probably doesn't matter much
nr_double_t we_ann = w_ann + h * del_u1_ann / 2.0 * (1.0 + 1.0 / (qucs::cosh(qucs::sqrt(eps_r - 1))));
nr_double_t ue_ann = we_ann / h;
nr_double_t u_ann = w_ann / h; // TODO need separate w/h and weffective/h ?
nr_double_t f_ann = 6.0 + (2.0 * pi - 6.0) * qucs::exp(-qucs::pow(30.666/ue_ann, 0.7528));
nr_double_t a_ann = 1.0 + 1.0/49.0 * qucs::log((qucs::pow(u_ann, 4.0) + qucs::pow((u_ann/52), 2.0)) / (qucs::pow(u_ann, 4.0) + 0.432)) + 1/18.7 * qucs::log(1.0 + qucs::pow(u_ann/18.1, 3.0));
nr_double_t b_ann = 0.564 * qucs::pow((eps_r - 0.9) / (eps_r + 3), 0.053);
nr_double_t Z01_we_ann = 60.0 * qucs::log(f_ann / ue_ann + qucs::sqrt(1.0 + 4.0 / qucs::pow(ue_ann, 2.0)));
nr_double_t eps_e1_ann = (eps_r + 1.0) / 2.0 + (eps_r - 1.0) / 2.0 * qucs::pow(1.0 + 10.0/ue_ann, -a_ann*b_ann);
nr_double_t Z0_ann = Z01_we_ann / qucs::sqrt(eps_e1_ann);
nr_double_t eps_e_ann = eps_e1_ann; // TODO, eq 4.6 - skipped the correction (copper thickness?), to clarify, maybe check https://pure.tue.nl/ws/files/46936050/640261-1.pdf
nr_double_t Zphi = Z0_ann;
nr_double_t vphi = C0 / qucs::sqrt(eps_e_ann);
// as above but free for free space (eps_r=1)
nr_double_t we_ann_eps0 = w_ann + h * del_u1_ann;
nr_double_t ue_ann_eps0 = we_ann_eps0 / h;
nr_double_t f_ann_eps0 = 6.0 + (2.0 * pi - 6.0) * qucs::exp(-qucs::pow(30.666/ue_ann_eps0, 0.7528));
nr_double_t a_ann_eps0 = 1.0 + 1.0/49.0 * qucs::log((qucs::pow(ue_ann_eps0, 4.0) + qucs::pow((ue_ann_eps0/52), 2.0)) / (qucs::pow(ue_ann_eps0, 4.0) + 0.432)) + 1/18.7 * qucs::log(1.0 + qucs::pow(ue_ann_eps0/18.1, 3.0));
nr_double_t b_ann_eps0 = 0.564 * qucs::pow((1 - 0.9) / (1 + 3), 0.053);
nr_double_t Z01_we_ann_eps0 = 60.0 * qucs::log(f_ann_eps0 / ue_ann_eps0 + qucs::sqrt(1.0 + 4.0 / qucs::pow(ue_ann_eps0, 2.0)));
nr_double_t eps_e1_ann_eps0 = (1.0 + 1.0) / 2.0 + (1.0 - 1.0) / 2.0 * qucs::pow(1.0 + 10.0/ue_ann_eps0, -a_ann_eps0*b_ann_eps0);
nr_double_t Z0_ann_eps0 = Z01_we_ann_eps0 / qucs::sqrt(eps_e1_ann_eps0);
nr_double_t eps_e_ann_eps0 = eps_e1_ann_eps0; // TODO, eq 4.6 - skipped the correction (copper thickness?), to clarify, maybe check https://pure.tue.nl/ws/files/46936050/640261-1.pdf
nr_double_t Zphi_eps0 = Z0_ann_eps0;
nr_double_t vphi_eps0 = C0 / qucs::sqrt(eps_e_ann_eps0);
// radial (calculate average width):
int int_steps = 100;
nr_double_t Zr_vr_int_sum = 0;
nr_double_t step_rad = phi * (r_i + (r_o - r_i) * 2.0 / (int_steps-1.0)) - phi * (r_i + (r_o - r_i) * 1.0 / (int_steps-1.0));
nr_double_t w_rad, del_u1_rad, we_rad, ue_rad, u_rad, f_rad, a_rad, b_rad, Z01_we_rad, eps_e1_rad, Z0_rad, eps_e_rad, Zrad, vrad;
for(int i_rad = 0; i_rad < int_steps; ++i_rad)
{
w_rad = phi * (r_i + (r_o - r_i) * i_rad / (int_steps-1.0)); // width in radial direction
del_u1_rad = t / pi * qucs::log(1.0 + 4.0 * euler / (t * qucs::pow((qucs::coth(qucs::sqrt(6.517 * w_rad/h))), 2.0))); //not sure if correction for effective width is needed here, probably doesn't matter much
we_rad = w_rad + h * del_u1_rad / 2.0 * (1.0 + 1.0 / (qucs::cosh(qucs::sqrt(eps_r - 1))));
ue_rad = we_rad / h;
u_rad = w_rad / h; // TODO need separate w/h and weffective/h ?
f_rad = 6.0 + (2.0 * pi - 6.0) * qucs::exp(-qucs::pow(30.666/ue_rad, 0.7528));
a_rad = 1.0 + 1.0/49 * qucs::log((qucs::pow(u_rad, 4.0) + qucs::pow((u_rad/52.0), 2.0)) / (qucs::pow(u_rad, 4.0) + 0.432)) + 1/18.7 * qucs::log(1.0 + qucs::pow(u_rad/18.1, 3.0));
b_rad = 0.564 * qucs::pow((eps_r - 0.9) / (eps_r + 3), 0.053);
Z01_we_rad = 60.0 * qucs::log(f_rad / ue_rad + qucs::sqrt(1.0 + 4.0 / qucs::pow(ue_rad, 2.0)));
eps_e1_rad = (eps_r + 1.0) / 2.0 + (eps_r - 1.0) / 2.0 * qucs::pow(1.0 + 10.0/ue_rad, -a_rad*b_rad);
Z0_rad = Z01_we_rad / qucs::sqrt(eps_e1_rad);
eps_e_rad = eps_e1_rad; // TODO, eq 4.6 - skipped the correction (copper thickness?), to clarify, maybe check https://pure.tue.nl/ws/files/46936050/640261-1.pdf
Zrad = Z0_rad;
vrad = C0 / qucs::sqrt(eps_e_rad);
Zr_vr_int_sum += 1.0 / (Zrad * vrad) * step_rad;
}
nr_double_t ZrVr = 1.0 / (1.0 / (phi * (r_o - r_i)) * Zr_vr_int_sum);
// as above but free for free air (eps_r=1)
nr_double_t Zr_vr_int_sum_eps0 = 0;
nr_double_t w_rad_eps0, del_u1_rad_eps0, we_rad_eps0, ue_rad_eps0, u_rad_eps0, f_rad_eps0, a_rad_eps0, b_rad_eps0, Z01_we_rad_eps0, eps_e1_rad_eps0, Z0_rad_eps0, eps_e_rad_eps0, Zrad_eps0, vrad_eps0;
for(int i_rad = 0; i_rad < int_steps; ++i_rad)
{
w_rad_eps0 = phi * (r_i + (r_o - r_i) * i_rad / (int_steps-1.0)); // width in radial direction
del_u1_rad_eps0 = t / pi * qucs::log(1.0 + 4.0 * euler / (t * qucs::pow((qucs::coth(qucs::sqrt(6.517 * w_rad_eps0/h))), 2.0))); //not sure if correction for effective width is needed here, probably doesn't matter much
we_rad_eps0 = w_rad_eps0 + h * del_u1_rad_eps0;
ue_rad_eps0 = we_rad_eps0 / h;
u_rad_eps0 = w_rad_eps0 / h; // TODO need separate w/h and weffective/h ?
f_rad_eps0 = 6.0 + (2.0 * pi - 6.0) * qucs::exp(-qucs::pow(30.666/u_rad_eps0, 0.7528));
a_rad_eps0 = 1.0 + 1.0/49 * qucs::log((qucs::pow(u_rad_eps0, 4.0) + qucs::pow((u_rad_eps0/52), 2.0)) / (qucs::pow(u_rad_eps0, 4.0) + 0.432)) + 1/18.7 * qucs::log(1.0 + qucs::pow(u_rad_eps0/18.1, 3.0));
b_rad_eps0 = 0.564 * qucs::pow((1 - 0.9) / (1 + 3), 0.053);
Z01_we_rad_eps0 = 60.0 * qucs::log(f_rad_eps0 / ue_rad_eps0 + qucs::sqrt(1.0 + 4.0 / qucs::pow(ue_rad_eps0, 2.0)));
eps_e1_rad_eps0 = (1.0 + 1.0) / 2.0 + (1.0 - 1.0) / 2.0 * qucs::pow(1.0 + 10.0/ue_rad_eps0, -a_rad_eps0*b_rad_eps0);
Z0_rad_eps0 = Z01_we_rad_eps0 / qucs::sqrt(eps_e1_rad_eps0);
eps_e_rad_eps0 = eps_e1_rad_eps0; // TODO, eq 4.6 - skipped the correction (copper thickness?), to clarify, maybe check https://pure.tue.nl/ws/files/46936050/640261-1.pdf
Zrad_eps0 = Z0_rad_eps0;
vrad_eps0 = C0 / qucs::sqrt(eps_e_rad_eps0);
Zr_vr_int_sum_eps0 += 1.0 / (Zrad_eps0 * vrad_eps0) * step_rad;
}
nr_double_t ZrVr_eps0 = 1.0 / (1.0 / (phi * (r_o - r_i)) * Zr_vr_int_sum_eps0);

// calculations of capacitances for dynamic permittivity calculations
nr_double_t Cd0_eps_r = E0 * eps_r * phi * (qucs::pow(r_o, 2.0) - qucs::pow(r_i, 2.0)) / (2.0 * h);
nr_double_t Cdf_eps_r = (r_o + r_i) * phi / 2.0 * (1.0 / (Zphi * vphi) - E0 * eps_r * (r_o - r_i) / h);
nr_double_t Cdf_eps0 = (r_o + r_i) * phi / 2.0 * (1.0 / (Zphi_eps0 * vphi_eps0) - E0 * 1 * (r_o - r_i) / h);
nr_double_t Cds_eps_r = (r_o - r_i) / 2.0 * (1.0 / (ZrVr) - E0 * eps_r * (r_o + r_i) * phi / (2.0 * h));
nr_double_t Cds_eps0 = (r_o - r_i) / 2.0 * (1.0 / (ZrVr_eps0) - E0 * 1 * (r_o + r_i) * phi / (2.0 * h));

// static mode dynamic permittivity
nr_double_t eps_d0 = (Cd0_eps_r + Cdf_eps_r + 2 * Cds_eps_r) / (Cd0_eps_r / eps_r + Cdf_eps0 + 2 * Cds_eps0);

// higher modes
nr_complex_t sum_part_zin = nr_complex_t(0, 0);
nr_double_t Kn, A0n, B0n, P0n, Cd0n_eps_r, eps_d0n, omega0n, Rs, K, Itheta, dItheta, Qc0n, Qr0n, Qt0n;
for(int i_loop = 0; i_loop < n_max; ++i_loop)
{
// coefficients ...
Kn = -jn(1, k0n_root[i_loop]*r_oe) / yn(1, k0n_root[i_loop]*r_oe);
A0n = qucs::sqrt(2/phi) / qucs::sqrt(qucs::pow(r_oe, 2.0) * qucs::pow(jn(0, k0n_root[i_loop]*r_oe) + Kn*yn(0, k0n_root[i_loop]*r_oe), 2.0) - qucs::pow(r_ie, 2.0) * qucs::pow(jn(0, k0n_root[i_loop]*r_ie) + Kn*yn(0, k0n_root[i_loop]*r_ie), 2.0));
B0n = Kn * A0n;
P0n = qucs::sqrt(w_ge) * (A0n * jn(0, k0n_root[i_loop]*r_ie) + B0n * yn(0, k0n_root[i_loop]*r_ie));

// calculation of capacitance Cd0n and dynamic permittivity (higher modes)
Cd0n_eps_r = E0 * eps_r * phi / (2.0 * h) * (qucs::pow(r_o, 2.0) - qucs::pow(r_i, 2.0) * qucs::pow((jn(0, k0n_root[i_loop] * r_oe) + Kn * yn(0, k0n_root[i_loop] * r_oe)) / (jn(0, k0n_root[i_loop] * r_ie) + Kn * yn(0, k0n_root[i_loop] * r_ie)), 2.0));
eps_d0n = (Cd0n_eps_r + Cdf_eps_r + Cds_eps_r) / (Cd0n_eps_r / eps_r + Cdf_eps0 + Cds_eps0);

// quality factors calculations
omega0n = k0n_root[i_loop] * C0 / qucs::sqrt(eps_d0n); //TODO - correct?
Rs = qucs::sqrt(omega0n * MU0 / (2.0 * 1.0 / resist)); //TODO - what kind of resistivity? what with skin effect?
K = 1.0 -
(qucs::pow(r_ie, 2.0) * qucs::pow(jn(0, k0n_root[i_loop]*r_ie) * yn(1, k0n_root[i_loop]*r_ie) - jn(1, k0n_root[i_loop]*r_ie) * yn(0, k0n_root[i_loop]*r_ie), 2.0)) /
(qucs::pow(r_oe, 2.0) * qucs::pow(jn(0, k0n_root[i_loop]*r_oe) * yn(1, k0n_root[i_loop]*r_oe) - jn(1, k0n_root[i_loop]*r_ie) * yn(0, k0n_root[i_loop]*r_oe), 2.0));
Itheta = 0;
for(int i_theta = 1; i_theta <= 180; ++i_theta) // integrate numerically (each step 1deg)
{
dItheta = 1.0/180.0 * qucs::pow(jn(1, K * r_oe * qucs::sin(deg2rad(i_theta))), 2.0) * qucs::sin(deg2rad(i_theta));
Itheta += dItheta;
}
Qc0n = omega0n * MU0 * h / (2.0 * Rs);
Qr0n = 1.0 / (omega0n * h * Itheta / (eps_d0 * K * C0));
Qt0n = 1.0 / (1.0 / Qt0 + 1.0 / Qc0n + 1.0 / Qr0n);

// part of stub impedance (higher modes)
sum_part_zin += (kg * qucs::pow(P0n, 2.0)) / (qucs::pow(k0n_root[i_loop], 2.0) * (1.0 + nr_complex_t(0,1) / Qt0n) - qucs::pow(k, 2.0) * eps_d0n);
}

//normalized impedance and impedance calculations
nr_complex_t z_in = (1.0 / Qt0 - nr_complex_t(0,1) * kg * qucs::pow(P0, 2.0)) / (qucs::pow(k, 2.0) * eps_d0) + nr_complex_t(0,1) * sum_part_zin;
nr_complex_t Zin = Z0rs * z_in;
return Zin;
}

else {
return nr_complex_t (0, calcReactance (r_ie, r_oe, phi, eps_r, h, frequency)); //old model used in qucs
}
}

void msrstub::initDC (void) {
Expand All @@ -93,10 +324,21 @@ void msrstub::calcAC (nr_double_t frequency) {
PROP_REQ [] = {
{ "ri", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
{ "ro", PROP_REAL, { 10e-3, PROP_NO_STR }, PROP_POS_RANGE },
{ "Wf", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
{ "alpha", PROP_REAL, { 90, PROP_NO_STR }, PROP_RNGII (0, 180) },
{ "Subst", PROP_STR, { PROP_NO_VAL, "Subst1" }, PROP_NO_RANGE },
{ "EffDimens", PROP_STR, { PROP_NO_VAL, "OldQucsNoCorrection" }, PROP_RNG_MRSCORR },
{ "Model", PROP_STR, { PROP_NO_VAL, "OldQucsModel" }, PROP_RNG_MRSMOD },
PROP_NO_PROP };
PROP_OPT [] = {
PROP_NO_PROP };
struct define_t msrstub::cirdef =
{ "MRSTUB", 1, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };


// Literature
// Design of a rectenna for wireless low-power transmission, Akkermans, J.A.G.
// A New Simple and Accurate Formula for Microstrip Radial Stub, Roberto Sorrentino, Luca Roselli
// A Crooked U-Slot Dual-Band Antenna With RadialStub Feeding, Hyo Rim Bae, Soon One So, Choon Sik Cho, Member, IEEE, Jae W. Lee, Member, IEEE, and Jaeheung Kim, Member, IEEE
// Performance Characterization of Radial Stub Microstrip Bow-Tie Antenna, B.T.P.Madhav, 2S.S.Mohan Reddy, 3Neha Sharma, 3J. Ravindranath Chowdary 3Bala Rama Pavithra, 3K.N.V.S. Kishore, 3G. Sriram, 3B. Sachin Kumar 1Associate Professor, Department of ECE, K L University, Guntur DT, AP, India 2Associate Professor, Department of ECE, SRKR Engineering College, Bhimavaram, AP, India 3Project Students, Department of ECE, K L University, Guntur DT, AP, India, Performance Characterization of Radial Stub Microstrip Bow-Tie Antenna. Available from: https://www.researchgate.net/publication/286889155_Performance_Characterization_of_Radial_Stub_Microstrip_Bow-Tie_Antenna [accessed Oct 19 2021].
//https://www.jpier.org/PIERL/view/12012009/
Loading