mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-06 06:53:37 +00:00
WIP: use Eigen::MatrixXcd in parameters in preparation for arbitrary number of ports
This commit is contained in:
parent
ef8cdeccd7
commit
d4df1c1b22
347 changed files with 270 additions and 197 deletions
|
|
@ -3,18 +3,20 @@
|
|||
using namespace std;
|
||||
|
||||
Sparam::Sparam(const Tparam &t) {
|
||||
m11 = t.m12 / t.m22;
|
||||
m21 = Type(1) / t.m22;
|
||||
m12 = (t.m11*t.m22 - t.m12*t.m21) / t.m22;
|
||||
m22 = -t.m21 / t.m22;
|
||||
data = Eigen::MatrixXcd(2,2);
|
||||
set(1,1, t.get(1,2) / t.get(2,2));
|
||||
set(2,1, Type(1) / t.get(2,2));
|
||||
set(1,2, (t.get(1,1)*t.get(2,2) - t.get(1,2)*t.get(2,1)) / t.get(2,2));
|
||||
set(2,2, -t.get(2,1) / t.get(2,2));
|
||||
}
|
||||
|
||||
Sparam::Sparam(const ABCDparam &a, Type Z01, Type Z02) {
|
||||
auto denom = a.m11*Z02+a.m12+a.m21*Z01*Z02+a.m22*Z01;
|
||||
m11 = (a.m11*Z02+a.m12-a.m21*conj(Z01)*Z02-a.m22*conj(Z01)) / denom;
|
||||
m12 = (2.0*(a.m11*a.m22-a.m12*a.m21)*sqrt(real(Z01)*real(Z02))) / denom;
|
||||
m21 = (2.0*sqrt(real(Z01)*real(Z02))) / denom;
|
||||
m22 = (-a.m11*conj(Z02)+a.m12-a.m21*Z01*conj(Z02)+a.m22*Z01) / denom;
|
||||
data = Eigen::MatrixXcd(2,2);
|
||||
auto denom = a.get(1,1)*Z02+a.get(1,2)+a.get(2,1)*Z01*Z02+a.get(2,2)*Z01;
|
||||
set(1,1, (a.get(1,1)*Z02+a.get(1,2)-a.get(2,1)*conj(Z01)*Z02-a.get(2,2)*conj(Z01)) / denom);
|
||||
set(1,2, (2.0*(a.get(1,1)*a.get(2,2)-a.get(1,2)*a.get(2,1))*sqrt(real(Z01)*real(Z02))) / denom);
|
||||
set(2,1, (2.0*sqrt(real(Z01)*real(Z02))) / denom);
|
||||
set(2,2, (-a.get(1,1)*conj(Z02)+a.get(1,2)-a.get(2,1)*Z01*conj(Z02)+a.get(2,2)*Z01) / denom);
|
||||
}
|
||||
|
||||
Sparam::Sparam(const ABCDparam &a, Type Z0)
|
||||
|
|
@ -22,21 +24,43 @@ Sparam::Sparam(const ABCDparam &a, Type Z0)
|
|||
{
|
||||
}
|
||||
|
||||
void Sparam::swapPorts(unsigned int p1, unsigned int p2)
|
||||
{
|
||||
// swap columns
|
||||
data.col(p1-1).swap(data.col(p2-1));
|
||||
data.row(p1-1).swap(data.row(p2-1));
|
||||
// auto cbuf = data.col(p1-1);
|
||||
// data.col(p1-1) = data.col(p2-1);
|
||||
// data.col(p2-1) = cbuf;
|
||||
// // swap rows
|
||||
// auto rbuf = data.row(p1-1);
|
||||
// data.row(p1-1) = data.row(p2-1);
|
||||
// data.row(p2-1) = rbuf;
|
||||
}
|
||||
|
||||
ABCDparam::ABCDparam(const Sparam &s, Type Z01, Type Z02)
|
||||
{
|
||||
auto denom = 2.0*s.m21*sqrt(real(Z01)*real(Z02));
|
||||
m11 = ((conj(Z01)+s.m11*Z01)*(1.0-s.m22)+s.m12*s.m21*Z01) / denom;
|
||||
m12 = ((conj(Z01)+s.m11*Z01)*(conj(Z02)+s.m22*Z02)-s.m12*s.m21*Z01*Z02) / denom;
|
||||
m21 = ((1.0-s.m11)*(1.0-s.m22)-s.m12*s.m21) / denom;
|
||||
m22 = ((1.0-s.m11)*(conj(Z02)+s.m22*Z02)+s.m12*s.m21*Z02) / denom;
|
||||
if(s.ports() != 2) {
|
||||
throw std::runtime_error("Can only create ABCD parameter from 2 port S parameters");
|
||||
}
|
||||
data = Eigen::MatrixXcd(2,2);
|
||||
auto denom = 2.0*s.get(2,1)*sqrt(real(Z01)*real(Z02));
|
||||
set(1,1, ((conj(Z01)+s.get(1,1)*Z01)*(1.0-s.get(2,2))+s.get(1,2)*s.get(2,1)*Z01) / denom);
|
||||
set(1,2, ((conj(Z01)+s.get(1,1)*Z01)*(conj(Z02)+s.get(2,2)*Z02)-s.get(1,2)*s.get(2,1)*Z01*Z02) / denom);
|
||||
set(2,1, ((1.0-s.get(1,1))*(1.0-s.get(2,2))-s.get(1,2)*s.get(2,1)) / denom);
|
||||
set(2,2, ((1.0-s.get(1,1))*(conj(Z02)+s.get(2,2)*Z02)+s.get(1,2)*s.get(2,1)*Z02) / denom);
|
||||
}
|
||||
|
||||
Tparam::Tparam(const Sparam &s)
|
||||
{
|
||||
m11 = -(s.m11*s.m22 - s.m12*s.m21) / s.m21;
|
||||
m12 = s.m11 / s.m21;
|
||||
m21 = -s.m22 / s.m21;
|
||||
m22 = 1.0 / s.m21;
|
||||
if(s.ports() != 2) {
|
||||
throw std::runtime_error("Can only create ABCD parameter from 2 port S parameters");
|
||||
}
|
||||
data = Eigen::MatrixXcd(2,2);
|
||||
set(1,1, -(s.get(1,1)*s.get(2,2) - s.get(1,2)*s.get(2,1)) / s.get(2,1));
|
||||
set(1,2, s.get(1,1) / s.get(2,1));
|
||||
set(2,1, -s.get(2,2) / s.get(2,1));
|
||||
set(2,2, 1.0 / s.get(2,1));
|
||||
}
|
||||
|
||||
ABCDparam::ABCDparam(const Sparam &s, Type Z0)
|
||||
|
|
@ -44,36 +68,77 @@ ABCDparam::ABCDparam(const Sparam &s, Type Z0)
|
|||
{
|
||||
}
|
||||
|
||||
Parameters::Parameters(Type m11, Type m12, Type m21, Type m22)
|
||||
: Parameters(2)
|
||||
{
|
||||
data(0, 0) = m11;
|
||||
data(0, 1) = m12;
|
||||
data(1, 0) = m21;
|
||||
data(1, 1) = m22;
|
||||
}
|
||||
|
||||
Parameters::Parameters(int num_ports)
|
||||
{
|
||||
data = Eigen::MatrixXd::Zero(num_ports, num_ports);
|
||||
}
|
||||
|
||||
nlohmann::json Parameters::toJSON()
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["m11_real"] = m11.real();
|
||||
j["m11_imag"] = m11.imag();
|
||||
j["m12_real"] = m12.real();
|
||||
j["m12_imag"] = m12.imag();
|
||||
j["m21_real"] = m21.real();
|
||||
j["m21_imag"] = m21.imag();
|
||||
j["m22_real"] = m22.real();
|
||||
j["m22_imag"] = m22.imag();
|
||||
return j;
|
||||
nlohmann::json ret;
|
||||
for(unsigned int i=0;i<data.cols();i++) {
|
||||
for(unsigned int j=0;j<data.cols();j++) {
|
||||
QString s_real = "m"+QString::number(i+1)+QString::number(j+1)+"_real";
|
||||
QString s_imag = "m"+QString::number(i+1)+QString::number(j+1)+"_imag";
|
||||
ret[s_real.toStdString()] = data(i, j).real();
|
||||
ret[s_imag.toStdString()] = data(i, j).imag();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Parameters::fromJSON(nlohmann::json j)
|
||||
{
|
||||
m11 = complex<double>(j.value("m11_real", 0.0), j.value("m11_imag", 0.0));
|
||||
m12 = complex<double>(j.value("m12_real", 0.0), j.value("m12_imag", 0.0));
|
||||
m21 = complex<double>(j.value("m21_real", 0.0), j.value("m21_imag", 0.0));
|
||||
m22 = complex<double>(j.value("m22_real", 0.0), j.value("m22_imag", 0.0));
|
||||
// figure out how many ports we need
|
||||
unsigned int max_port = 0;
|
||||
for(auto names : j.items()) {
|
||||
auto key = QString::fromStdString(names.key());
|
||||
unsigned int i = key.mid(1, 1).toInt();
|
||||
unsigned int j = key.mid(2, 1).toInt();
|
||||
if(i > max_port) {
|
||||
max_port = i;
|
||||
}
|
||||
if(j > max_port) {
|
||||
max_port = j;
|
||||
}
|
||||
}
|
||||
data = Eigen::MatrixXcd(max_port, max_port);
|
||||
for(unsigned int i=0;i<data.cols();i++) {
|
||||
for(unsigned int _j=0;_j<data.cols();_j++) {
|
||||
std::string s_real = ("m"+QString::number(i+1)+QString::number(_j+1)+"_real").toStdString();
|
||||
std::string s_imag = ("m"+QString::number(i+1)+QString::number(_j+1)+"_imag").toStdString();
|
||||
if(j.contains(s_real) && j.contains((s_imag))) {
|
||||
data(i, _j) = complex<double>(j.value(s_real, 0.0), j.value(s_imag, 0.0));
|
||||
} else {
|
||||
// no data, set to zero
|
||||
data(i, _j) = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Yparam::Yparam(const Sparam &s, Type Z01, Type Z02)
|
||||
{
|
||||
// TODO can this be done for any number of ports
|
||||
if(s.ports() != 2) {
|
||||
throw std::runtime_error("Can only create ABCD parameter from 2 port S parameters");
|
||||
}
|
||||
data = Eigen::MatrixXcd(2,2);
|
||||
// from https://www.rfcafe.com/references/electrical/s-h-y-z.htm
|
||||
auto denom = (conj(Z01)+s.m11*Z01)*(conj(Z02)+s.m22*Z02)-s.m12*s.m21*Z01*Z02;
|
||||
m11 = ((1.0-s.m11)*(conj(Z02)+s.m22*Z02)+s.m12*s.m21*Z02) / denom;
|
||||
m12 = -2.0*s.m12*sqrt(real(Z01)*real(Z02));
|
||||
m21 = -2.0*s.m21*sqrt(real(Z01)*real(Z02));
|
||||
m22 = ((conj(Z01)+s.m11*Z01)*(1.0-s.m22)+s.m12*s.m21*Z01) / denom;
|
||||
auto denom = (conj(Z01)+s.get(1,1)*Z01)*(conj(Z02)+s.get(2,2)*Z02)-s.get(1,2)*s.get(2,1)*Z01*Z02;
|
||||
set(1,1, ((1.0-s.get(1,1))*(conj(Z02)+s.get(2,2)*Z02)+s.get(1,2)*s.get(2,1)*Z02) / denom);
|
||||
set(1,2, -2.0*s.get(1,2)*sqrt(real(Z01)*real(Z02)));
|
||||
set(2,1, -2.0*s.get(2,1)*sqrt(real(Z01)*real(Z02)));
|
||||
set(2,2, ((conj(Z01)+s.get(1,1)*Z01)*(1.0-s.get(2,2))+s.get(1,2)*s.get(2,1)*Z01) / denom);
|
||||
}
|
||||
|
||||
Yparam::Yparam(const Sparam &s, Type Z0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue