Can $\Gamma$ remain complex while calculating return loss?

I'm working on adding .s1p touchstone export support to the xnec2c NEC2 antenna simulator for Linux. I would like the S11 dB values in the .s1p to have both real and imaginary values.

NEC2 calculates Gamma by breaking it into real-valued components $$\Z_r\$$ and $$\Z_i\$$. It then does a real (ie, not complex) calculation to obtain a real-valued Gamma:

$$\\Gamma = \sqrt{ \frac{ (Z_r-Z_0)^2+Z_i^2 }{ (Z_r+Z_0)^2+Z_i^2 } }\$$

S11 is then calculated as a real value using Gamma above as:

$$\S_{11}\ = 20 log_{10}(\Gamma)\$$

My question: Is it correct to calculate a complex Gamma from the real values $$\Z_r\$$ and $$\Z_i\$$ by creating a complex number $$\Z = (Z_r+Z_i {\bf i})\$$ and then calcule Gamma as shown in the Wikipedia article about reflection coefficient?

$$\\Gamma = \frac{ Z-Z_0 }{ Z+Z_0 } \$$

I ran the numbers and I get the same result for the real S11 value, but I have no way to validate the imaginary value. Is this a mathematically correct way to do this? Is it the "right" way?

If this works then I can split $$\Z\$$ into its real and imaginary parts for writing to the .s1p file's S11 real and imaginary columns. Here is the actual C code that generates the real-valued gamma and s11 variables:

zrpro2 = impedance_data.zreal[idx] + calc_data.zo;
zrpro2 *= zrpro2;
zrmro2 = impedance_data.zreal[idx] - calc_data.zo;
zrmro2 *= zrmro2;
zimag2 = impedance_data.zimag[idx] * impedance_data.zimag[idx];
gamma = sqrt( (zrmro2 + zimag2) / (zrpro2 + zimag2) );

s11[idx] = 20*log10( gamma );

And here is my proposed change based on that:

double complex z_load = impedance_data.zreal[idx] + I*impedance_data.zimag[idx];
• Would you please double-check check your code as written, gamma = sqrt( (zrmro2 + zimag2) / (zrpro2 + zimag2) );, against your first equation also posted here? They do not look the same to me and this is a zero-order sniff-test I do when trying to read a post like this.
– jonk
Commented Jan 16, 2022 at 6:53
• @jonk, you're correct. The signs were swapped in the LaTeX markup. Commented Jan 16, 2022 at 22:46

I'll keep it short:

Yes, the computation of: $$\Gamma=\frac{Z-Z_0}{Z+Z_0}$$ can be properly composed in the way you suggest.

It's also the case that your first equation isn't correctly written, though in contrast to that your actual C code is written correctly to calculate the result. (Comment is no longer true as this has now been corrected in the question.)

You can readily derive the real-number magnitude calculation from the above complex rational (by applying the complex magnitude or absolute value to the rational) as: $$\mid\, \Gamma\! \mid=\sqrt{\frac{\left(Z_\mathcal{R}-Z_0\right)^2+Z_\mathcal{I}^2}{\left(Z_\mathcal{R}+Z_0\right)^2+Z_\mathcal{I}^2}}$$

Note that this isn't the same as you wrote in your question.

However, you did get the right computation in C.

If you need help figuring out how to apply the absolute magnitude using the complex conjugate, I'll expand on that. But I think you should easily manage that much on your own.

• Is the only error in my first calculation having the position of +/- needing to be swapped as -/+ in the fraction? Commented Jan 16, 2022 at 8:18
• @KJ7LNW I was focused on your question. I wasn't considering other topics, such as whether or not your proposed lines should be used. (I don't think they should be, unless you also apply the complex absolute magnitude to them or unless you share the code that follows and uses the cgamma variable.) You may have other questions also buried in there that I didn't think about. You'll need to be specific.
– jonk
Commented Jan 16, 2022 at 8:25
• @KJ7LNW The magnitude of gamma is unitless and real and the NEC2 simulator apparently was computing that. Perhaps because the square of that is directly related to the proportion of power that is reflected/absorbed. Perhaps they compute phase elsewhere. I don't know.
– jonk
Commented Jan 16, 2022 at 8:35
• @KJ7LNW I'd just like to add that if you're using complex numbers then using the direct aproach might be better, unless the compiler optimizes it. That's because the only benefit you're seeing is in the written code: you see only a diference divided by a sum, but under the hood the operations are very much split into real and imaginary, much like we do on paper. So you can trust the "heavier" looking sqrt() & co. Commented Jan 16, 2022 at 9:10