Qucs-GUI  0.0.18
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
matchdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  matchdialog.cpp
3  -----------------
4  begin : Fri Jul 22 2005
5  copyright : (C) 2005 by Michael Margraf
6  email : michael.margraf@alumni.tu-berlin.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 
22 #include <QtGui>
23 #include "matchdialog.h"
24 #include "main.h"
25 #include "qucs.h"
26 #include "element.h"
27 #include "../components/capacitor.h"
28 #include "../components/inductor.h"
29 #include "../components/ground.h"
30 
31 #include <QLabel>
32 #include <QHBoxLayout>
33 #include <QVBoxLayout>
34 #include <QLineEdit>
35 #include <QComboBox>
36 #include <QCheckBox>
37 #include <QValidator>
38 #include <QPushButton>
39 #include <QMessageBox>
40 #include <QApplication>
41 #include <QClipboard>
42 #include <QGroupBox>
43 
44 
45 MatchDialog::MatchDialog(QWidget *parent)
46  : QDialog(parent) //, 0, TRUE, Qt::WDestructiveClose)
47 {
48  setWindowTitle(tr("Create Matching Circuit"));
49  DoubleVal = new QDoubleValidator(this);
50 
51  all = new QVBoxLayout(this);
52 
53  TwoCheck = new QCheckBox(tr("calculate two-port matching"));
54  all->addWidget(TwoCheck);
55  TwoCheck->setChecked(true);
56  connect(TwoCheck, SIGNAL(toggled(bool)), SLOT(slotSetTwoPort(bool)));
57 
58  // ...........................................................
59  QGroupBox *ImpBox = new QGroupBox(tr("Reference Impedance"));
60  all->addWidget(ImpBox);
61  QHBoxLayout *ImpLayout = new QHBoxLayout();
62  Port1Label = new QLabel(tr("Port 1"));
63  Ref1Edit = new QLineEdit("50");
64  Ref1Edit->setValidator(DoubleVal);
65  Ohm1Label = new QLabel(tr("ohms"));
66  connect(Ref1Edit, SIGNAL(textChanged(const QString&)),
67  SLOT(slotImpedanceChanged(const QString&)));
68  Port2Label = new QLabel(tr("Port 2"));
69  Ref2Edit = new QLineEdit("50");
70  Ref2Edit->setValidator(DoubleVal);
71  Ohm2Label = new QLabel(tr("ohms"));
72  ImpLayout->addWidget(Port1Label);
73  ImpLayout->addWidget(Ref1Edit);
74  ImpLayout->addWidget(Ohm1Label);
75  ImpLayout->addSpacing(50);
76  ImpLayout->addWidget(Port2Label);
77  ImpLayout->addWidget(Ref2Edit);
78  ImpLayout->addWidget(Ohm2Label);
79  ImpBox->setLayout(ImpLayout);
80 
81  // ...........................................................
82  QGroupBox *SParBox = new QGroupBox(tr("S Parameter"));
83  all->addWidget(SParBox);
84  QVBoxLayout *SParLayout = new QVBoxLayout();
85  SParBox->setLayout(SParLayout);
86 
87  QHBoxLayout *h1 = new QHBoxLayout();
88  h1->setSpacing(3);
89  FormatLabel = new QLabel(tr("Input format"));
90  h1->addWidget(FormatLabel);
91  FormatCombo = new QComboBox();
92  h1->addWidget(FormatCombo);
93  FormatCombo->insertItem(tr("real/imag"));
94  FormatCombo->insertItem(tr("mag/deg"));
95  connect(FormatCombo, SIGNAL(activated(int)), SLOT(slotChangeMode(int)));
96  h1->addStretch(5);
97  SParLayout->addLayout(h1);
98 
99  QHBoxLayout *h3 = new QHBoxLayout();
100  h3->setSpacing(3);
101  QVBoxLayout *VBox1 = new QVBoxLayout();
102  h3->addLayout(VBox1);
103  S11Label = new QLabel(tr("S11"));
104  S21Label = new QLabel(tr("S21"));
105  VBox1->addWidget(S11Label);
106  VBox1->addWidget(S21Label);
107  QVBoxLayout *VBox2 = new QVBoxLayout();
108  h3->addLayout(VBox2);
109  S11magEdit = new QLineEdit("0.5");
110  S11magEdit->setValidator(DoubleVal);
111  S21magEdit = new QLineEdit("0.5");
112  S21magEdit->setValidator(DoubleVal);
113  VBox2->addWidget(S11magEdit);
114  VBox2->addWidget(S21magEdit);
115  QVBoxLayout *VBox3 = new QVBoxLayout();
116  h3->addLayout(VBox3);
117  S11sLabel = new QLabel("+j");
118  S21sLabel = new QLabel("+j");
119  VBox3->addWidget(S11sLabel);
120  VBox3->addWidget(S21sLabel);
121  QVBoxLayout *VBox4 = new QVBoxLayout();
122  h3->addLayout(VBox4);
123  S11degEdit = new QLineEdit("0");
124  S11degEdit->setValidator(DoubleVal);
125  S21degEdit = new QLineEdit("0");
126  S21degEdit->setValidator(DoubleVal);
127  VBox4->addWidget(S11degEdit);
128  VBox4->addWidget(S21degEdit);
129  QVBoxLayout *VBox5 = new QVBoxLayout();
130  h3->addLayout(VBox5);
131  S11uLabel = new QLabel(" ");
132  S21uLabel = new QLabel(" ");
133  VBox5->addWidget(S11uLabel);
134  VBox5->addWidget(S21uLabel);
135  h3->addStretch(5);
136  QVBoxLayout *VBox6 = new QVBoxLayout();
137  h3->addLayout(VBox6);
138  S12Label = new QLabel(tr("S12"));
139  S22Label = new QLabel(tr("S22"));
140  VBox6->addWidget(S12Label);
141  VBox6->addWidget(S22Label);
142  QVBoxLayout *VBox7 = new QVBoxLayout();
143  h3->addLayout(VBox7);
144  S12magEdit = new QLineEdit("0");
145  S12magEdit->setValidator(DoubleVal);
146  S22magEdit = new QLineEdit("0.5");
147  S22magEdit->setValidator(DoubleVal);
148  VBox7->addWidget(S12magEdit);
149  VBox7->addWidget(S22magEdit);
150  QVBoxLayout *VBox8 = new QVBoxLayout();
151  h3->addLayout(VBox8);
152  S12sLabel = new QLabel("+j");
153  S22sLabel = new QLabel("+j");
154  VBox8->addWidget(S12sLabel);
155  VBox8->addWidget(S22sLabel);
156  QVBoxLayout *VBox9 = new QVBoxLayout();
157  h3->addLayout(VBox9);
158  S12degEdit = new QLineEdit("0");
159  S12degEdit->setValidator(DoubleVal);
160  S22degEdit = new QLineEdit("0");
161  S22degEdit->setValidator(DoubleVal);
162  VBox9->addWidget(S12degEdit);
163  VBox9->addWidget(S22degEdit);
164  QVBoxLayout *VBox0 = new QVBoxLayout();
165  h3->addLayout(VBox0);
166  S12uLabel = new QLabel(" ");
167  S22uLabel = new QLabel(" ");
168  VBox0->addWidget(S12uLabel);
169  VBox0->addWidget(S22uLabel);
170  SParLayout->addLayout(h3);
171 
172  connect(S21magEdit, SIGNAL(textChanged(const QString&)),
173  SLOT(slotImpedanceChanged(const QString&)));
174  connect(S21degEdit, SIGNAL(textChanged(const QString&)),
175  SLOT(slotImpedanceChanged(const QString&)));
176  connect(S11magEdit, SIGNAL(textChanged(const QString&)),
177  SLOT(slotReflexionChanged(const QString&)));
178  connect(S11degEdit, SIGNAL(textChanged(const QString&)),
179  SLOT(slotReflexionChanged(const QString&)));
180 
181 
182  QHBoxLayout *h2 = new QHBoxLayout();
183  h2->setSpacing(3);
184  FrequencyLabel = new QLabel(tr("Frequency:"));
185  FrequencyEdit = new QLineEdit();
186  FrequencyEdit->setValidator(DoubleVal);
187  h2->addWidget(FrequencyLabel);
188  h2->addWidget(FrequencyEdit);
189  UnitCombo = new QComboBox();
190  UnitCombo->insertItem("Hz");
191  UnitCombo->insertItem("kHz");
192  UnitCombo->insertItem("MHz");
193  UnitCombo->insertItem("GHz");
194  h2->addWidget(UnitCombo);
195  h2->addStretch(5);
196  SParLayout->addLayout(h2);
197 
198  // ...........................................................
199  QHBoxLayout *h0 = new QHBoxLayout();
200  h0->setSpacing(5);
201  all->addLayout(h0);
202  h0->addStretch(5);
203  QPushButton *buttCreate = new QPushButton(tr("Create"));
204  QPushButton *buttCancel = new QPushButton(tr("Cancel"));
205  h0->addWidget(buttCreate);
206  h0->addWidget(buttCancel);
207  connect(buttCreate, SIGNAL(clicked()), SLOT(slotButtCreate()));
208  connect(buttCancel, SIGNAL(clicked()), SLOT(reject()));
209 
210  slotReflexionChanged(""); // calculate impedance
211  setFrequency(1e9); // set 1GHz
212  resize(520, 100);
213 }
214 
216 {
217  delete all;
218  delete DoubleVal;
219 }
220 
221 // -----------------------------------------------------------------------
222 void MatchDialog::setFrequency(double Freq_)
223 {
224  int Expo = int(log10(Freq_) / 3.0);
225  if(Expo < 0) Expo = 0;
226  else if(Expo > 3) Expo = 3;
227  UnitCombo->setCurrentItem(Expo);
228  Freq_ /= pow(10.0, double(3*Expo));
229  FrequencyEdit->setText(QString::number(Freq_));
230 }
231 
232 // -----------------------------------------------------------------------
233 // Is called when the checkbox for two-port matching changes.
235 {
236  if(on) { // two-port matching ?
237  S11Label->setText(tr("S11"));
238  S21Label->setText(tr("S21"));
239  S12magEdit->setEnabled(true);
240  S22magEdit->setEnabled(true);
241  S12degEdit->setEnabled(true);
242  S22degEdit->setEnabled(true);
243  S12Label->setEnabled(true);
244  S22Label->setEnabled(true);
245  S12sLabel->setEnabled(true);
246  S22sLabel->setEnabled(true);
247  S12degEdit->setEnabled(true);
248  S22degEdit->setEnabled(true);
249  S12uLabel->setEnabled(true);
250  S22uLabel->setEnabled(true);
251  Port2Label->setEnabled(true);
252  Ref2Edit->setEnabled(true);
253  Ohm2Label->setEnabled(true);
254  }
255  else {
256  S11Label->setText(tr("Reflexion Coefficient"));
257  S21Label->setText(tr("Impedance (ohms)"));
258  S12magEdit->setEnabled(false);
259  S22magEdit->setEnabled(false);
260  S12degEdit->setEnabled(false);
261  S22degEdit->setEnabled(false);
262  S12Label->setEnabled(false);
263  S22Label->setEnabled(false);
264  S12sLabel->setEnabled(false);
265  S22sLabel->setEnabled(false);
266  S12degEdit->setEnabled(false);
267  S22degEdit->setEnabled(false);
268  S12uLabel->setEnabled(false);
269  S22uLabel->setEnabled(false);
270  Port2Label->setEnabled(false);
271  Ref2Edit->setEnabled(false);
272  Ohm2Label->setEnabled(false);
273  }
274 }
275 
276 // -----------------------------------------------------------------------
277 // Is called when the combobox changes between mag/deg and real/imag.
279 {
280  if(Index) { // polar ?
281  S11sLabel->setText("/");
282  S12sLabel->setText("/");
283  S21sLabel->setText("/");
284  S22sLabel->setText("/");
285  S11uLabel->setText(QString::fromUtf8("°"));
286  S12uLabel->setText(QString::fromUtf8("°"));
287  S21uLabel->setText(QString::fromUtf8("°"));
288  S22uLabel->setText(QString::fromUtf8("°"));
289 
290  double Real = S11magEdit->text().toDouble();
291  double Imag = S11degEdit->text().toDouble();
292  c2p(Real, Imag);
293  S11magEdit->setText(QString::number(Real));
294  S11degEdit->setText(QString::number(Imag));
295 
296  Real = S12magEdit->text().toDouble();
297  Imag = S12degEdit->text().toDouble();
298  c2p(Real, Imag);
299  S12magEdit->setText(QString::number(Real));
300  S12degEdit->setText(QString::number(Imag));
301 
302  Real = S21magEdit->text().toDouble();
303  Imag = S21degEdit->text().toDouble();
304  c2p(Real, Imag);
305  S21magEdit->setText(QString::number(Real));
306  S21degEdit->setText(QString::number(Imag));
307 
308  Real = S22magEdit->text().toDouble();
309  Imag = S22degEdit->text().toDouble();
310  c2p(Real, Imag);
311  S22magEdit->setText(QString::number(Real));
312  S22degEdit->setText(QString::number(Imag));
313  }
314  else { // cartesian
315  S11sLabel->setText("+j");
316  S12sLabel->setText("+j");
317  S21sLabel->setText("+j");
318  S22sLabel->setText("+j");
319  S11uLabel->setText(" ");
320  S12uLabel->setText(" ");
321  S21uLabel->setText(" ");
322  S22uLabel->setText(" ");
323 
324  double Mag = S11magEdit->text().toDouble();
325  double Phase = S11degEdit->text().toDouble();
326  p2c(Mag, Phase);
327  S11magEdit->setText(QString::number(Mag));
328  S11degEdit->setText(QString::number(Phase));
329 
330  Mag = S12magEdit->text().toDouble();
331  Phase = S12degEdit->text().toDouble();
332  p2c(Mag, Phase);
333  S12magEdit->setText(QString::number(Mag));
334  S12degEdit->setText(QString::number(Phase));
335 
336  Mag = S21magEdit->text().toDouble();
337  Phase = S21degEdit->text().toDouble();
338  p2c(Mag, Phase);
339  S21magEdit->setText(QString::number(Mag));
340  S21degEdit->setText(QString::number(Phase));
341 
342  Mag = S22magEdit->text().toDouble();
343  Phase = S22degEdit->text().toDouble();
344  p2c(Mag, Phase);
345  S22magEdit->setText(QString::number(Mag));
346  S22degEdit->setText(QString::number(Phase));
347  }
348 }
349 
350 // -----------------------------------------------------------------------
351 // Is called if the user changed the impedance. -> The reflexion
352 // coefficient is calculated.
354 {
355  if(TwoCheck->isChecked()) return;
356 
357  double Z0 = Ref1Edit->text().toDouble();
358  double Real = S21magEdit->text().toDouble();
359  double Imag = S21degEdit->text().toDouble();
360  z2r(Real, Imag, Z0);
361  S11magEdit->blockSignals(true); // do not call "changed-slot"
362  S11magEdit->setText(QString::number(Real));
363  S11magEdit->blockSignals(false);
364  S11degEdit->blockSignals(true); // do not call "changed-slot"
365  S11degEdit->setText(QString::number(Imag));
366  S11degEdit->blockSignals(false);
367 }
368 
369 // -----------------------------------------------------------------------
370 // Is called if the user changed the reflexion coefficient. -> The impedance
371 // is calculated.
373 {
374  if(TwoCheck->isChecked()) return;
375 
376  double Z0 = Ref1Edit->text().toDouble();
377  double Real = S11magEdit->text().toDouble();
378  double Imag = S11degEdit->text().toDouble();
379  r2z(Real, Imag, Z0);
380  S21magEdit->blockSignals(true); // do not call "changed-slot"
381  S21magEdit->setText(QString::number(Real));
382  S21magEdit->blockSignals(false);
383  S21degEdit->blockSignals(true); // do not call "changed-slot"
384  S21degEdit->setText(QString::number(Imag));
385  S21degEdit->blockSignals(false);
386 }
387 
388 // -----------------------------------------------------------------------
389 // Is called if the "Create"-button is pressed.
391 {
392  double Z1 = Ref1Edit->text().toDouble();
393  double Z2 = Ref2Edit->text().toDouble();
394  double Freq = FrequencyEdit->text().toDouble() *
395  pow(10.0, 3.0*double(UnitCombo->currentItem()));
396 
397  double S11real = S11magEdit->text().toDouble();
398  double S11imag = S11degEdit->text().toDouble();
399  double S12real = S12magEdit->text().toDouble();
400  double S12imag = S12degEdit->text().toDouble();
401  double S21real = S21magEdit->text().toDouble();
402  double S21imag = S21degEdit->text().toDouble();
403  double S22real = S22magEdit->text().toDouble();
404  double S22imag = S22degEdit->text().toDouble();
405  if(FormatCombo->currentItem()) { // are they polar ?
406  p2c(S11real, S11imag);
407  p2c(S12real, S12imag);
408  p2c(S21real, S21imag);
409  p2c(S22real, S22imag);
410  }
411 
412  if(TwoCheck->isChecked()) { // two-port matching ?
413  // determinante of S-parameter matrix
414  double DetReal = S11real*S22real - S11imag*S22imag
415  - S12real*S21real + S12imag*S21imag;
416  double DetImag = S11real*S22imag + S11imag*S22real
417  - S12real*S21imag - S12imag*S21real;
418 
419  if(!MatchDialog::calc2PortMatch(S11real, S11imag, S22real, S22imag,
420  DetReal, DetImag, Z1, Z2, Freq))
421  return;
422  }
423  else
424  if(!calcMatchingCircuit(S11real, S11imag, Z1, Freq))
425  return;
426 
427  QucsMain->slotEditPaste(true);
428  accept();
429 }
430 
431 
432 // -----------------------------------------------------------------------
433 // transform real/imag into mag/deg (cartesian to polar)
434 void MatchDialog::c2p(double& Real, double& Imag)
435 {
436  double Real_ = Real;
437  Real = sqrt(Real*Real + Imag*Imag); // magnitude
438  Imag = 180.0/M_PI * atan2(Imag, Real_); // phase in degree
439 }
440 
441 // -----------------------------------------------------------------------
442 // transform mag/deg into real/imag (polar to cartesian)
443 void MatchDialog::p2c(double& Real, double& Imag)
444 {
445  double Real_ = Real;
446  Real = Real_ * cos(Imag * M_PI/180.0); // real part
447  Imag = Real_ * sin(Imag * M_PI/180.0); // imaginary part
448 }
449 
450 // -----------------------------------------------------------------------
451 // transform reflexion coefficient into impedance
452 void MatchDialog::r2z(double& Real, double& Imag, double Z0)
453 {
454  double tmp = Z0 / ((1.0-Real)*(1.0-Real) + Imag*Imag);
455  Real = (1.0 - Real*Real - Imag*Imag) * tmp;
456  Imag *= 2.0 * tmp;
457 }
458 
459 // -----------------------------------------------------------------------
460 // transform impedance into reflexion coefficient
461 void MatchDialog::z2r(double& Real, double& Imag, double Z0)
462 {
463  double tmp = (Real+Z0)*(Real+Z0) + Imag*Imag;
464  Real = (Real*Real + Imag*Imag - Z0*Z0) / tmp;
465  Imag *= 2.0 * Z0 / tmp;
466 }
467 
468 // -----------------------------------------------------------------------
469 // Calculate matching circuit. Returns string like "sp:1nH:5pF"
470 QString MatchDialog::calcMatching(double r_real, double r_imag,
471  double Z0, double Freq)
472 {
473  double Zreal = r_real, Zimag = r_imag;
474  r2z(Zreal, Zimag, Z0);
475 
476  if (Zreal < 0.0) {
477  if (Zreal < -1e-13) {
478  QMessageBox::critical(0, tr("Error"),
479  tr("Real part of impedance must be greater zero,\nbut is %1 !").arg(Zreal));
480  return QString(""); // matching not possible
481  }
482 
483  // In high-Q circuits, Zreal often becomes somewhat about -1e-16
484  // because of numerical inaccuracy.
485  Zreal = 0.0;
486  }
487 
488 
489  double X1, X2, Omega = 2.0 * M_PI * Freq;
490  QString Str;
491  if(r_real < 0) {
492  // ...................................................
493  // first serial than parallel component (possible if Zreal <= Z0)
494  Str = "sp";
495  X1 = sqrt(Zreal * (Z0 - Zreal));
496  if (Zimag < 0.0) X1 *= -1.0; // always use shortest matching path
497  X1 -= Zimag;
498 
499  // parallel component
500  X2 = (Zimag + X1) / (Zreal*Zreal + (Zimag + X1)*(Zimag + X1));
501  }
502  else {
503 
504  Str = "ps";
505  X1 = Zreal + Zimag*Zimag / Zreal - Z0;
506  // ...................................................
507  // first parallel than serial component (possible if X >= 0.0)
508  X1 = sqrt(Z0 * X1);
509  if (Zimag > 0.0) X1 *= -1.0; // always use shortest matching path
510 
511  // parallel component
512  X2 = Zimag / (Zreal*Zreal + Zimag*Zimag) + X1 / (Z0*Z0 + X1*X1);
513  }
514 
515 
516  // serial component
517  if (X1 < 0.0) // capacitance ?
518  Str += ':' + num2str(-1.0 / Omega / X1) + 'F';
519  else // inductance
520  Str += ':' + num2str(X1 / Omega) + 'H';
521 
522  // parallel component
523  if (X2 < 0.0) // inductance ?
524  Str += ':' + num2str(-1.0 / Omega / X2) + 'H';
525  else // capacitance
526  Str += ':' + num2str(X2 / Omega) + 'F';
527 
528  return Str;
529 }
530 
531 // -----------------------------------------------------------------------
532 bool MatchDialog::calcMatchingCircuit(double r_real, double r_imag,
533  double Z0, double Freq)
534 {
535  QString Schematic =
536  "<Qucs Schematic " PACKAGE_VERSION ">\n"
537  "<Components>\n";
538 
539 
540  QString Str = calcMatching(r_real, r_imag, Z0, Freq);
541  if(Str.isEmpty()) return false;
542 
543  if(Str.section(':', 0,0) == "sp") {
544  // ...................................................
545  // first serial than parallel component
546 
547  if(Str.section(':', 1,1).right(1) == "F")
548  Schematic += "<C C1";
549  else
550  Schematic += "<L L1";
551  Schematic += " 1 100 10 -26 10 0 0 \"" + Str.section(':', 1,1) + "\" 1>\n";
552 
553  if(Str.section(':', 2,2).right(1) == "F")
554  Schematic += "<C C2";
555  else
556  Schematic += "<L L2";
557  Schematic += " 1 30 80 17 -26 0 1 \"" + Str.section(':', 2,2) + "\" 1>\n";
558 
559  Schematic +=
560  "<GND * 1 30 110 0 0 0 0>\n"
561  "</Components>\n"
562  "<Wires>\n"
563  "<10 10 30 10 \"\" 0 0 0 \"\">\n"
564  "<30 10 70 10 \"\" 0 0 0 \"\">\n"
565  "<30 10 30 50 \"\" 0 0 0 \"\">\n";
566  }
567  else {
568  // ...................................................
569  // first parallel than serial component
570 
571  if(Str.section(':', 1,1).right(1) == "F")
572  Schematic += "<C C1";
573  else
574  Schematic += "<L L1";
575  Schematic += " 1 50 10 -26 10 0 0 \"" + Str.section(':', 1,1) + "\" 1>\n";
576 
577  if(Str.section(':', 2,2).right(1) == "F")
578  Schematic += "<C C2";
579  else
580  Schematic += "<L L2";
581  Schematic += " 1 130 70 17 -26 0 1 \"" + Str.section(':', 2,2) + "\" 1>\n";
582 
583  Schematic +=
584  "<GND * 1 130 100 0 0 0 0>\n"
585  "</Components>\n"
586  "<Wires>\n"
587  "<130 10 130 40 \"\" 0 0 0 \"\">\n"
588  "<130 10 150 10 \"\" 0 0 0 \"\">\n"
589  "<80 10 130 10 \"\" 0 0 0 \"\">\n";
590  }
591 
592  Schematic += QString(
593  "</Wires>\n"
594  "<Diagrams>\n"
595  "</Diagrams>\n"
596  "<Paintings>\n"
597  " <Text -20 -10 12 #000000 0 \"%1 Ohm\">\n"
598  " <Text 120 -10 12 #000000 0 \"device\">\n"
599  "</Paintings>\n").arg(Z0);
600 
601  QApplication::clipboard()->setText(Schematic, QClipboard::Clipboard);
602  return true;
603 }
604 
605 // -----------------------------------------------------------------------
606 // Fundamental calculations for concurrent 2-port matching.
607 QString MatchDialog::calcBiMatch(double S11real, double S11imag,
608  double S22real, double S22imag, double DetReal, double DetImag,
609  double Z0, double Freq)
610 {
611  double B = 1.0 + S11real*S11real + S11imag*S11imag
612  - S22real*S22real - S22imag*S22imag
613  - DetReal*DetReal - DetImag*DetImag;
614  double Creal = S11real - S22real*DetReal - S22imag*DetImag;
615  double Cimag = S22real*DetImag - S11imag - S22imag*DetReal;
616  double Cmag = 2.0 * (Creal*Creal + Cimag*Cimag);
617  Creal /= Cmag;
618  Cimag /= Cmag;
619 
620  double Rreal = B*B - 2.0*Cmag;
621  double Rimag;
622  if(Rreal < 0.0) {
623  Rimag = Cimag * B - Creal * sqrt(-Rreal);
624  Rreal = Creal * B + Cimag * sqrt(-Rreal);
625  }
626  else {
627  Rreal = B - sqrt(Rreal);
628  Rimag = Cimag * Rreal;
629  Rreal *= Creal;
630  }
631 
632  return calcMatching(Rreal, -Rimag, Z0, Freq);
633 }
634 
635 // -----------------------------------------------------------------------
636 bool MatchDialog::calc2PortMatch(double S11real, double S11imag,
637  double S22real, double S22imag, double DetReal, double DetImag,
638  double Z1, double Z2, double Freq)
639 {
640  QString Input = calcBiMatch(S11real, S11imag, S22real, S22imag,
641  DetReal, DetImag, Z1, Freq);
642  if(Input.isEmpty()) return false;
643 
644  QString Output = calcBiMatch(S22real, S22imag, S11real, S11imag,
645  DetReal, DetImag, Z2, Freq);
646  if(Output.isEmpty()) return false;
647 
648  QString Schematic =
649  "<Qucs Schematic " PACKAGE_VERSION ">\n"
650  "<Components>\n";
651 
652 
653  // ...................................................
654  // create input circuit
655  if(Input.section(':', 0,0) == "sp") {
656  // first serial than parallel component
657 
658  if(Input.section(':', 1,1).right(1) == "F")
659  Schematic += "<C C1";
660  else
661  Schematic += "<L L1";
662  Schematic += " 1 -50 10 -26 10 0 0 \"" + Input.section(':', 1,1) + "\" 1>\n";
663 
664  if(Input.section(':', 2,2).right(1) == "F")
665  Schematic += "<C C2";
666  else
667  Schematic += "<L L2";
668  Schematic += " 1 -120 80 17 -26 0 1 \"" + Input.section(':', 2,2) + "\" 1>\n";
669 
670  Schematic += "<GND * 1 -120 110 0 0 0 0>\n";
671  }
672  else {
673  // first parallel than serial component
674 
675  if(Input.section(':', 1,1).right(1) == "F")
676  Schematic += "<C C1";
677  else
678  Schematic += "<L L1";
679  Schematic += " 1 -140 10 -26 10 0 0 \"" + Input.section(':', 1,1) + "\" 1>\n";
680 
681  if(Input.section(':', 2,2).right(1) == "F")
682  Schematic += "<C C2";
683  else
684  Schematic += "<L L2";
685  Schematic += " 1 -60 70 17 -26 0 1 \"" + Input.section(':', 2,2) + "\" 1>\n";
686 
687  Schematic += "<GND * 1 -60 100 0 0 0 0>\n";
688  }
689 
690 
691  // ...................................................
692  // create output circuit
693  if(Output.section(':', 0,0) == "sp") {
694  // first serial than parallel component
695 
696  if(Output.section(':', 1,1).right(1) == "F")
697  Schematic += "<C C1";
698  else
699  Schematic += "<L L1";
700  Schematic += " 1 50 10 -26 10 0 0 \"" + Output.section(':', 1,1) + "\" 1>\n";
701 
702  if(Output.section(':', 2,2).right(1) == "F")
703  Schematic += "<C C2";
704  else
705  Schematic += "<L L2";
706  Schematic += " 1 120 80 17 -26 0 1 \"" + Output.section(':', 2,2) + "\" 1>\n";
707 
708  Schematic += "<GND * 1 120 110 0 0 0 0>\n";
709  }
710  else {
711  // ...................................................
712  // first parallel than serial component
713 
714  if(Output.section(':', 1,1).right(1) == "F")
715  Schematic += "<C C1";
716  else
717  Schematic += "<L L1";
718  Schematic += " 1 140 10 -26 10 0 0 \"" + Output.section(':', 1,1) + "\" 1>\n";
719 
720  if(Output.section(':', 2,2).right(1) == "F")
721  Schematic += "<C C2";
722  else
723  Schematic += "<L L2";
724  Schematic += " 1 60 70 17 -26 0 1 \"" + Output.section(':', 2,2) + "\" 1>\n";
725 
726  Schematic += "<GND * 1 60 100 0 0 0 0>\n";
727  }
728  Schematic += "</Components>\n"
729  "<Wires>\n";
730 
731 
732  // ...................................................
733  // create wires for input circuit
734  if(Input.section(':', 0,0) == "sp") // first serial than parallel component
735  Schematic +=
736  "<-140 10 -120 10 \"\" 0 0 0 \"\">\n"
737  "<-120 10 -80 10 \"\" 0 0 0 \"\">\n"
738  "<-120 10 -120 50 \"\" 0 0 0 \"\">\n";
739  else // first parallel than serial component
740  Schematic +=
741  "<-60 10 -60 40 \"\" 0 0 0 \"\">\n"
742  "<-60 10 -40 10 \"\" 0 0 0 \"\">\n"
743  "<-110 10 -60 10 \"\" 0 0 0 \"\">\n";
744 
745 
746  // ...................................................
747  // create wires for output circuit
748  if(Output.section(':', 0,0) == "sp") // first serial than parallel component
749  Schematic +=
750  "<140 10 120 10 \"\" 0 0 0 \"\">\n"
751  "<120 10 80 10 \"\" 0 0 0 \"\">\n"
752  "<120 10 120 50 \"\" 0 0 0 \"\">\n";
753  else // first parallel than serial component
754  Schematic +=
755  "<60 10 60 40 \"\" 0 0 0 \"\">\n"
756  "<60 10 40 10 \"\" 0 0 0 \"\">\n"
757  "<110 10 60 10 \"\" 0 0 0 \"\">\n";
758 
759  Schematic +=
760  "</Wires>\n"
761  "<Diagrams>\n"
762  "</Diagrams>\n"
763  "<Paintings>\n"
764  " <Text -200 -10 12 #000000 0 \"Port 1\">\n"
765  " <Text -20 -10 12 #000000 0 \"device\">\n"
766  " <Text 160 -10 12 #000000 0 \"Port 2\">\n"
767  "</Paintings>\n";
768 
769  QApplication::clipboard()->setText(Schematic, QClipboard::Clipboard);
770  return true;
771 }
QLabel * S11uLabel
Definition: matchdialog.h:67
Defines drawing elements for schematics.
QLabel * Port1Label
Definition: matchdialog.h:67
void slotChangeMode(int)
QLineEdit * S12magEdit
Definition: matchdialog.h:52
QLabel * FrequencyLabel
Definition: matchdialog.h:67
static void p2c(double &, double &)
MatchDialog(QWidget *parent=0)
Definition: matchdialog.cpp:45
QLabel * S12uLabel
Definition: matchdialog.h:67
void slotSetTwoPort(bool)
static QString calcBiMatch(double, double, double, double, double, double, double, double)
QLabel * S22Label
Definition: matchdialog.h:67
QLineEdit * S21degEdit
Definition: matchdialog.h:52
static void z2r(double &, double &, double)
QVBoxLayout * all
Definition: matchdialog.h:65
QLabel * S21Label
Definition: matchdialog.h:67
Definitions and declarations for the main application.
void slotButtCreate()
QucsApp * QucsMain
Definition: main.cpp:54
static bool calcMatchingCircuit(double, double, double, double)
void slotEditPaste(bool)
QLabel * Ohm2Label
Definition: matchdialog.h:67
QString num2str(double Num)
Definition: main.cpp:384
QLineEdit * Ref1Edit
Definition: matchdialog.h:52
QLabel * S12sLabel
Definition: matchdialog.h:67
QLineEdit * S11degEdit
Definition: matchdialog.h:52
QComboBox * UnitCombo
Definition: matchdialog.h:73
QLabel * S12Label
Definition: matchdialog.h:67
void slotReflexionChanged(const QString &)
static bool calc2PortMatch(double, double, double, double, double, double, double, double, double)
QCheckBox * TwoCheck
Definition: matchdialog.h:55
QLabel * S21uLabel
Definition: matchdialog.h:67
static void r2z(double &, double &, double)
QLineEdit * FrequencyEdit
Definition: matchdialog.h:52
QLineEdit * S22degEdit
Definition: matchdialog.h:52
void setFrequency(double)
QLineEdit * S21magEdit
Definition: matchdialog.h:52
QLabel * S11sLabel
Definition: matchdialog.h:67
QComboBox * FormatCombo
Definition: matchdialog.h:73
QLabel * Port2Label
Definition: matchdialog.h:67
QLabel * Ohm1Label
Definition: matchdialog.h:67
QLabel * S22uLabel
Definition: matchdialog.h:67
void slotImpedanceChanged(const QString &)
QLineEdit * Ref2Edit
Definition: matchdialog.h:52
QLabel * FormatLabel
Definition: matchdialog.h:67
QDoubleValidator * DoubleVal
Definition: matchdialog.h:66
#define M_PI
Definition: diagramdialog.h:25
QLabel * S21sLabel
Definition: matchdialog.h:67
QLineEdit * S11magEdit
Definition: matchdialog.h:52
QLabel * S11Label
Definition: matchdialog.h:67
QLineEdit * S22magEdit
Definition: matchdialog.h:52
static QString calcMatching(double, double, double, double)
QLineEdit * S12degEdit
Definition: matchdialog.h:52
QLabel * S22sLabel
Definition: matchdialog.h:67
static void c2p(double &, double &)