* spfile.cpp - S-parameter file class implementation
*
* Copyright (C) 2004, 2005, 2006, 2008, 2009 Stefan Jahn <stefan@lkcc.org>
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* $Id$
*
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "object.h"
#include "vector.h"
#include "matrix.h"
#include "matvec.h"
#include "dataset.h"
#include "strlist.h"
#include "poly.h"
#include "spline.h"
#include "interpolator.h"
#include "spfile.h"
using namespace qucs;
spfile_vector::spfile_vector () {
v = f = 0;
isreal = 1;
inter = NULL;
r = c = 0;
}
spfile_vector::~spfile_vector () {
delete inter;
}
void spfile_vector::prepare (qucs::vector * _v, qucs::vector * _f,
bool _isreal, int it, int dt) {
v = _v;
f = _f;
isreal = _isreal;
inter = new interpolator ();
if (isreal) {
inter->rvectors (v, f);
inter->prepare (it, REPEAT_NO, dt | DATA_REAL);
}
else {
inter->cvectors (v, f);
inter->prepare (it, REPEAT_NO, dt | DATA_COMPLEX);
}
}
nr_complex_t spfile_vector::interpolate (nr_double_t x) {
if (isreal)
return inter->rinterpolate (x);
else
return inter->cinterpolate (x);
}
spfile::spfile () {
data = NULL;
sfreq = nfreq = NULL;
spara = FMIN = SOPT = RN = NULL;
interpolType = dataType = 0;
}
spfile::~spfile () {
delete[] spara;
delete RN;
delete FMIN;
delete SOPT;
#if DEBUG && 0
if (data) {
data->setFile ("spfile.dat");
data->print ();
}
#endif
delete data;
}
given frequency. It uses interpolation for frequency points which
are not part of the original touchstone file. */
matrix spfile::getInterpolMatrixS (nr_double_t frequency) {
matrix s (nPorts);
for (int r = 0; r < nPorts; r++) {
for (int c = 0; c < nPorts; c++) {
int i = r * (nPorts + 1) + c;
s.set (r, c, spara[i].interpolate (frequency));
}
}
switch (paraType) {
case 'Y':
s = ytos (s);
break;
case 'Z':
s = ztos (s);
break;
case 'H':
s = htos (s);
break;
case 'G':
s = gtos (s);
break;
}
return s;
}
within the touchstone file to have an additional reference one-port
whose S-parameter is -1 (i.e. ground). */
matrix spfile::expandSParaMatrix (matrix s) {
assert (s.getCols () == s.getRows ());
int r, c, ports = s.getCols () + 1;
nr_double_t g = -1;
nr_complex_t fr, ss, sr, sc, sa;
matrix res (ports);
for (sa = 0, r = 0; r < ports - 1; r++)
for (c = 0; c < ports - 1; c++) sa += s.get (r, c);
ss = (2 - g - ports + sa) / (1 - ports * g - sa);
res.set (ports - 1, ports - 1, ss);
fr = (1.0 - g * ss) / (1.0 - g);
for (r = 0; r < ports - 1; r++) {
for (sc = 0, c = 0; c < ports - 1; c++) sc += s.get (r, c);
res.set (r, ports - 1, fr * (1.0 - sc));
}
for (c = 0; c < ports - 1; c++) {
for (sr = 0, r = 0; r < ports - 1; r++) sr += s.get (r, c);
res.set (ports - 1, c, fr * (1.0 - sr));
}
for (r = 0; r < ports - 1; r++) {
for (c = 0; c < ports - 1; c++) {
fr = g * res (r, ports - 1) * res (ports - 1, c) / (1.0 - g * ss);
res.set (r, c, s.get (r, c) - fr);
}
}
return res;
}
function. It shrinks the S-parameter matrix by removing the
reference port. */
matrix spfile::shrinkSParaMatrix (matrix s) {
assert (s.getCols () == s.getRows () && s.getCols () > 0);
int r, c, ports = s.getCols ();
nr_double_t g = -1;
matrix res (ports - 1);
for (r = 0; r < ports - 1; r++) {
for (c = 0; c < ports - 1; c++) {
res.set (r, c, s (r, c) + g * s (r, ports - 1) *
s (ports - 1, c) / (1.0 - g * s (ports - 1, ports - 1)));
}
}
return res;
}
void spfile::prepare (void) {
}
entry and adds it to the dataset. */
void spfile::createVector (int r, int c) {
int i = r * (nPorts + 1) + c;
spara[i].r = r;
spara[i].c = c;
qucs::vector * v = new qucs::vector (matvec::createMatrixString ("S", r, c),
sfreq->getSize ());
v->setDependencies (new strlist ());
v->getDependencies()->add (sfreq->getName ());
data->addVariable (v);
spara[i].v = v;
}
touchstone file and looks for the S-parameter matrices and
frequency vector. It also tries to find the noise parameter
data. */
void spfile::createIndex (void) {
qucs::vector * v; int s = nPorts + 1;
char * n;
const char *name;
int r, c, i;
for (v = data->getDependencies (); v != NULL; v = (::vector *) v->getNext ()) {
if ((name = v->getName ()) != NULL) {
if (!strcmp (name, "frequency")) sfreq = v;
else if (!strcmp (name, "nfreq")) nfreq = v;
}
}
spara = new spfile_vector[s * s] ();
for (v = data->getVariables (); v != NULL; v = (::vector *) v->getNext ()) {
if ((n = matvec::isMatrixVector (v->getName (), r, c)) != NULL) {
i = r * s + c;
spara[i].r = r;
spara[i].c = c;
spara[i].prepare (v, sfreq, false, interpolType, dataType);
paraType = n[0];
free (n);
}
if ((name = v->getName ()) != NULL) {
if (!strcmp (name, "Rn")) {
RN = new spfile_vector ();
RN->prepare (v, nfreq, true, interpolType, dataType);
}
else if (!strcmp (name, "Fmin")) {
FMIN = new spfile_vector ();
FMIN->prepare (v, nfreq, true, interpolType, dataType);
}
else if (!strcmp (name, "Sopt")) {
SOPT = new spfile_vector ();
SOPT->prepare (v, nfreq, false, interpolType, dataType);
}
}
}
}