Branch data Line data Source code
1 : : /*
2 : : * rectline.cpp - rectangular waveguide class implementation
3 : : *
4 : : * Copyright (C) 2008 Bastien ROUCARIES <roucaries.bastien@gmail.com>
5 : : * Copyright (C) 2008 Andrea Zonca <andrea.zonca@gmail.com>
6 : : *
7 : : * This is free software; you can redistribute it and/or modify
8 : : * it under the terms of the GNU General Public License as published by
9 : : * the Free Software Foundation; either version 2, or (at your option)
10 : : * any later version.
11 : : *
12 : : * This software is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : * GNU General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU General Public License
18 : : * along with this package; see the file COPYING. If not, write to
19 : : * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 : : * Boston, MA 02110-1301, USA.
21 : : *
22 : : * $Id$
23 : : *
24 : : */
25 : :
26 : : #if HAVE_CONFIG_H
27 : : # include <config.h>
28 : : #endif
29 : :
30 : : #include "component.h"
31 : : #include "rectline.h"
32 : :
33 : : /*!\file rectangular.cpp
34 : : A TE10 rectangular waveguide
35 : :
36 : : References:
37 : : [1] Microwave engineering
38 : : David M. Pozar
39 : : John Wiley & sons
40 : : 2d edition
41 : : 1998
42 : : isbn 0-471-17096-8
43 : :
44 : : [2] Fundation for Microwave Engineering
45 : : The {IEEE} press serie on Electromagnetics Wave Theory
46 : : Robert E. Collin
47 : : IEEE Press,
48 : : 2d edition
49 : : 1992
50 : : isbn 0-7803-6331-1
51 : :
52 : : */
53 : :
54 : :
55 : : using namespace qucs;
56 : :
57 : 0 : rectline::rectline () : circuit (2) {
58 : 0 : alpha = beta = fc_low = fc_high = 0.0;
59 : 0 : zl = 0.0;
60 : 0 : type = CIR_RECTANGULAR;
61 : 0 : }
62 : :
63 : 0 : void rectline::calcResistivity (const char * const Mat, nr_double_t T) {
64 [ # # ]: 0 : if (!strcmp (Mat, "Copper")) {
65 [ # # ]: 0 : if (T < 7) {
66 : 0 : rho = 2e-11;
67 : : }
68 [ # # ]: 0 : else if (T < 15) {
69 : 0 : rho = 6.66667e-17 * qucs::pow (T, 5.0) - 3.88549e-15 * qucs::pow (T, 4.0) +
70 : 0 : 9.82267e-14 * qucs::pow (T, 3.0) - 1.29684e-12 * qucs::pow (T, 2.0) +
71 : 0 : 8.68341e-12 * T - 2.72120e-12;
72 : : }
73 [ # # ]: 0 : else if (T < 45) {
74 : 0 : rho = 6.60731e-15 * qucs::pow (T, 3.0) - 1.14812e-13 * qucs::pow (T, 2.0) -
75 : 0 : 1.11681e-12 * T + 4.23709e-11;
76 : : }
77 [ # # ]: 0 : else if (T < 100) {
78 : 0 : rho = -6.53059e-15 * qucs::pow (T, 3.0) + 1.73783e-12 * qucs::pow (T, 2.0) -
79 : 0 : 8.73888e-11 * T + 1.37016e-9;
80 : : }
81 [ # # ]: 0 : else if (T < 350) {
82 : 0 : rho = 1.00018e-17 * qucs::pow (T, 3.0) - 8.72408e-15 * qucs::pow (T, 2.0) +
83 : 0 : 7.06020e-11 * T - 3.51125e-9;
84 : : }
85 : : else {
86 : 0 : rho = 0.000000020628;
87 : : }
88 : : // in ADS iT_K is forced T_Ko Cu_300K:
89 : : //rho = 1.7e-8;
90 : : }
91 [ # # ]: 0 : else if (!strcmp (Mat, "StainlessSteel")) {
92 : 0 : rho = 7.4121e-17 * qucs::pow (T, 4.0) - 5.3504e-14 * qucs::pow (T, 3.0) +
93 : 0 : 1.2902e-11 * qucs::pow (T, 2.0) - 2.9186e-10 * T +4.9320e-7;
94 : : }
95 [ # # ]: 0 : else if (!strcmp (Mat, "Gold")) {
96 [ # # ]: 0 : if (T < 20) {
97 : 0 : rho = 0.00000000024;
98 : : }
99 [ # # ]: 0 : else if (T < 65) {
100 : 0 : rho = 2e-12 * qucs::pow (T, 2.0) - 8e-11 * T + 1e-9;
101 : : }
102 [ # # ]: 0 : else if (T < 80) {
103 : 0 : rho = 5e-13 * qucs::pow (T, 3.0) - 1e-10 * qucs::pow (T, 2.0) + 9e-9 * T - 2e-7;
104 : : }
105 [ # # ]: 0 : else if (T < 300) {
106 : 0 : rho = 8e-11 * T - 1e-10;
107 : : }
108 : : else {
109 : 0 : rho = 2.4e-8;
110 : : }
111 : : }
112 : 0 : }
113 : :
114 : : /*! Compute propagation constant
115 : :
116 : : According to [1] table 3.2 p 128
117 : : Wawe number in vacuum is:
118 : : \f[
119 : : k=\omega\sqrt{\mu\varepsilon}=\omega\sqrt{\mu_r \varepsilon_r \mu_0 \varepsilon_0}
120 : : \f]
121 : : Where \f$\omega=2\pi f\f$, \f$f\f$ is the frequency, $\f\mu\f$ the magnetic permeability,
122 : : \f$\varepsilon_r\f$ the permitivity. Using well known formula \f$c^2\mu_0\varepsilon_0=1\f$, we found:
123 : : \f[
124 : : k=\frac{\omega}{c} std::sqrt{\mu_r \varepsilon_r}
125 : : \f]
126 : : In general case \f$k_c\f$ is:
127 : : \f[
128 : : k_c = \sqrt{\left(\frac{m\pi}{a}\right)^2+\left(\frac{n\pi}{b}\right)^2}
129 : : \f]
130 : : Where \f$a\f$ is the wider dimension of the guide and \f$b\f$ the smaller and \f$(n,m)\in\mathbb{N}^2\f$.
131 : : In the TE10 case it simplifies to:
132 : : \f[
133 : : k_c = \sqrt{\left(\frac{\pi}{a}\right)^2} = \frac{\pi}{a}
134 : : \f]
135 : : The propagation constant is:
136 : : \f[
137 : : \beta = \sqrt{k^2 - k_c^2}
138 : : \f]
139 : : Loss could be divised in dielectric and resistive loss.
140 : : Dielectric loss are computed using:
141 : : \f[
142 : : \alpha_d = \frac{k^2 \tan \delta}{2\beta}
143 : : \f]
144 : : Resistive using [1] eq (3.96) p 125 (valid only for TE10 mode)
145 : : \f[
146 : : \alpha_c=\frac{R_s}{a^3 b \beta k Z_0} \left( 2 b \pi^2 + a^3 k^2 \right)
147 : : \f]
148 : : Wave impedance is for TE10:
149 : : \f[
150 : : Z = \frac{k Z_0}{\beta}
151 : : \f]
152 : : */
153 : 0 : void rectline::calcPropagation (nr_double_t frequency) {
154 : 0 : nr_double_t er = getPropertyDouble ("er");
155 : 0 : nr_double_t mur = getPropertyDouble ("mur");
156 : 0 : nr_double_t tand = getPropertyDouble ("tand");
157 : 0 : nr_double_t a = getPropertyDouble ("a");
158 : 0 : nr_double_t b = getPropertyDouble ("b");
159 : :
160 : : /* wave number */
161 : : nr_double_t k0;
162 : : nr_double_t kc;
163 : : /* dielectric loss */
164 : : nr_double_t ad, ac, rs;
165 : :
166 : : // check cutoff frequency
167 [ # # ]: 0 : if (frequency >= fc_high) {
168 : : logprint (LOG_ERROR, "WARNING: Operating frequency (%g) outside TE10 "
169 : : "band (%g <= TE10 <= %g) or outside non propagative mode "
170 : 0 : "<= %g\n", frequency, fc_low, fc_high, fc_low);
171 : : }
172 : : // calculate wave number
173 : 0 : k0 = (2.0 * M_PI * frequency * std::sqrt (er * mur)) / C0;
174 : 0 : kc = M_PI / a;
175 : :
176 : : // calculate losses only for propagative mode
177 [ # # ]: 0 : if (frequency >= fc_low) {
178 : : // calculate beta
179 : 0 : beta = std::sqrt (sqr (k0) - sqr (kc));
180 : :
181 : : // dielectric
182 : 0 : ad = (sqr(k0) * tand) / (2.0 * beta);
183 : : // resistive
184 : 0 : rs = std::sqrt (M_PI * frequency * mur * MU0 * rho);
185 : 0 : ac = rs * (2.0 * b * sqr (M_PI) + cubic (a) * sqr (k0)) /
186 : 0 : (cubic (a) * b * beta * k0 * Z0);
187 : 0 : alpha = (ad + ac);
188 : :
189 : : // wave impedance
190 : 0 : zl = (k0 * Z0) / beta;
191 : :
192 : : } else {
193 : : /* according to [2] eq 3.207 */
194 : 0 : beta = 0;
195 : 0 : alpha = -std::sqrt (- (sqr (k0) - sqr (kc)));
196 : : // wave impedance
197 [ # # ]: 0 : zl = (k0 * Z0) / nr_complex_t (0, -alpha) ;
198 : : }
199 : 0 : }
200 : :
201 : : /*! Compute noise parameter */
202 : 0 : void rectline::calcNoiseSP (nr_double_t) {
203 [ # # ]: 0 : nr_double_t l = getPropertyDouble ("L");
204 [ # # ]: 0 : if (l < 0) return;
205 : : // calculate noise using Bosma's theorem
206 [ # # ]: 0 : nr_double_t T = getPropertyDouble ("Temp");
207 [ # # ]: 0 : matrix s = getMatrixS ();
208 [ # # ]: 0 : matrix e = eye (getSize ());
209 [ # # ][ # # ]: 0 : setMatrixN (kelvin (T) / T0 * (e - s * transpose (conj (s))));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
210 : : }
211 : :
212 : : /*! Check validity of parameter and compute cutoff frequencies
213 : : \note do not check validity of epsr or mur because some research stuff could use epsr < 1 (plasma)
214 : : */
215 : 0 : void rectline::initCheck (void) {
216 : 0 : nr_double_t a = getPropertyDouble ("a");
217 : 0 : nr_double_t b = getPropertyDouble ("b");
218 : 0 : nr_double_t epsr = getPropertyDouble ("er");
219 : 0 : nr_double_t mur = getPropertyDouble ("mur");
220 : : // check validity
221 [ # # ]: 0 : if (a < b) {
222 : 0 : logprint (LOG_ERROR, "ERROR: a < b should be a >= b.\n");
223 : : }
224 : 0 : nr_double_t c = std::sqrt (epsr * mur);
225 : 0 : fc_low = C0 / (2.0 * a * c);
226 : : /* min of second TE mode and first TM mode */
227 [ # # ]: 0 : fc_high = MIN (C0 / (a * c), C0 / (2.0 * b * c));
228 : : // calculation of resistivity
229 : 0 : rho = getPropertyDouble ("rho");
230 : 0 : nr_double_t T = getPropertyDouble ("Temp");
231 : 0 : calcResistivity (getPropertyString ("Material"), kelvin (T));
232 : 0 : }
233 : :
234 : 0 : void rectline::saveCharacteristics (nr_complex_t) {
235 : 0 : setCharacteristic ("Zl", real (zl));
236 : 0 : }
237 : :
238 : : /*! initialize S-parameters */
239 : 0 : void rectline::initSP (void) {
240 : : // allocate S-parameter matrix
241 : 0 : allocMatrixS ();
242 : 0 : initCheck ();
243 : 0 : }
244 : :
245 : : /*! Compute S parameter use generic transmission line formulae */
246 : 0 : void rectline::calcSP (nr_double_t frequency) {
247 [ # # ]: 0 : nr_double_t l = getPropertyDouble ("L");
248 : :
249 : : // calculate propagation constants
250 [ # # ]: 0 : calcPropagation (frequency);
251 : :
252 : : // calculate S-parameters
253 : 0 : nr_complex_t z = zl / z0;
254 [ # # ]: 0 : nr_complex_t y = 1.0 / z;
255 : 0 : nr_complex_t g = nr_complex_t (alpha, beta);
256 [ # # ][ # # ]: 0 : nr_complex_t n = 2.0 * cosh (g * l) + (z + y) * sinh (g * l);
[ # # ][ # # ]
[ # # ]
257 [ # # ][ # # ]: 0 : nr_complex_t s11 = (z - y) * sinh (g * l) / n;
[ # # ][ # # ]
258 [ # # ]: 0 : nr_complex_t s21 = 2.0 / n;
259 [ # # ][ # # ]: 0 : setS (NODE_1, NODE_1, s11); setS (NODE_2, NODE_2, s11);
260 [ # # ][ # # ]: 0 : setS (NODE_1, NODE_2, s21); setS (NODE_2, NODE_1, s21);
261 : 0 : }
262 : :
263 : : /* ! Compute DC
264 : : \note below cut off it is an open circuit
265 : : */
266 : 0 : void rectline::initDC (void) {
267 : 0 : allocMatrixMNA ();
268 : : // open circuit
269 : 0 : clearY ();
270 : 0 : }
271 : :
272 : : /*! init AC */
273 : 0 : void rectline::initAC (void) {
274 : 0 : setVoltageSources (0);
275 : 0 : allocMatrixMNA ();
276 : 0 : initCheck ();
277 : 0 : }
278 : :
279 : : /*! calc propagation using classical transmission line formulae */
280 : 0 : void rectline::calcAC (nr_double_t frequency) {
281 [ # # ]: 0 : nr_double_t l = getPropertyDouble ("L");
282 : :
283 : : // calculate propagation constants
284 [ # # ]: 0 : calcPropagation (frequency);
285 : :
286 : : // calculate Y-parameters
287 : 0 : nr_complex_t g = nr_complex_t (alpha, beta);
288 [ # # ][ # # ]: 0 : nr_complex_t y11 = coth (g * l) / zl;
289 [ # # ][ # # ]: 0 : nr_complex_t y21 = -cosech (g * l) / zl;
290 [ # # ][ # # ]: 0 : setY (NODE_1, NODE_1, y11); setY (NODE_2, NODE_2, y11);
291 [ # # ][ # # ]: 0 : setY (NODE_1, NODE_2, y21); setY (NODE_2, NODE_1, y21);
292 : 0 : }
293 : :
294 : : /*! Compute noise */
295 : 0 : void rectline::calcNoiseAC (nr_double_t) {
296 : 0 : nr_double_t l = getPropertyDouble ("L");
297 [ # # ]: 0 : if (l < 0) return;
298 : : // calculate noise using Bosma's theorem
299 : 0 : nr_double_t T = getPropertyDouble ("Temp");
300 [ # # ][ # # ]: 0 : setMatrixN (4.0 * kelvin (T) / T0 * real (getMatrixY ()));
[ # # ][ # # ]
[ # # ]
301 : : }
302 : :
303 : : // properties
304 : : PROP_REQ [] = {
305 : : { "a", PROP_REAL, { 2.86e-2, PROP_NO_STR }, PROP_POS_RANGEX },
306 : : { "b", PROP_REAL, { 1.016e-2, PROP_NO_STR }, PROP_POS_RANGEX },
307 : : { "L", PROP_REAL, { 1500e-3, PROP_NO_STR }, PROP_NO_RANGE },
308 : : { "er", PROP_REAL, { 1, PROP_NO_STR }, PROP_RNGII (1, 100) },
309 : : { "mur", PROP_REAL, { 1, PROP_NO_STR }, PROP_RNGII (1, 100) },
310 : : { "tand", PROP_REAL, { 4e-4, PROP_NO_STR }, PROP_POS_RANGE },
311 : : { "rho", PROP_REAL, { 0.022e-6, PROP_NO_STR }, PROP_POS_RANGE },
312 : : PROP_NO_PROP };
313 : : PROP_OPT [] = {
314 : : { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
315 : : { "Material", PROP_STR, { PROP_NO_VAL, "unspecified" },
316 : : PROP_RNG_STR4 ("unspecified", "Copper", "StainlessSteel", "Gold") },
317 : : PROP_NO_PROP };
318 : : struct define_t rectline::cirdef =
319 : : { "RECTLINE", 2, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };
|