KJ7LNW / xnec2c

Xnec2c is a high-performance multi-threaded electromagnetic simulation package to model antenna near- and far-field radiation patterns for Linux and UNIX operating systems.
https://www.xnec2c.org/
GNU General Public License v3.0
77 stars 16 forks source link

Save more simulation data (radiation pattern, currents etc.) to csv #34

Closed bjohan closed 1 year ago

bjohan commented 1 year ago

It would be nice to be able to save radiation pattern, current data etc. to csv so that the data can be analyzed in an external program.

Motivation: In some cases max gain and f/b ratio is not enough. For instance when evaluating a feeder for a dish reflector gain is integrated over the angle that covers the reflector. Or if you want to reduce side lobes etc.

KJ7LNW commented 1 year ago

The radiation pattern can be exported as a static-width set of x,y,z columns, which should be pretty easy to import into a spreadsheet: Radiation Pattern window -> File -> Save As GNUPlot

As for currents, you're right, that isn't available. How would you want that data? What should each column represent?

I've not yet looked to see how its stored in the NEC2 engine, so not sure what makes the most sense there.

KJ7LNW commented 1 year ago

I just realized that the radiation pattern save is to re-create the pattern as a 3d object, but rho,phi,theta is probably more useful.

bjohan commented 1 year ago

I agree that spherical coordinates are probably more useful when it comes to radiation pattern data. Is it possible to create gnuplot files for all frequency radiation patterns in batch mode with the current version?

Regarding current data: In the nec2c output file there is first a table describing the structure which includes a column for first and last segment numbers.

                           -------- STRUCTURE SPECIFICATION --------
                                 COORDINATES MUST BE INPUT IN
                                 METERS OR BE SCALED TO METERS
                                 BEFORE STRUCTURE INPUT IS ENDED

WIRE SEG FIRST LAST TAG No: X1 Y1 Z1 X2 Y2 Z2 RADIUS No: SEG SEG No: 1 -0.25894 0.00000 -0.01797 -0.25894 0.08817 -0.01797 0.00050 78 1 78 1 2 -0.25894 0.00000 -0.01797 -0.22726 0.00000 -0.01590 0.00050 29 79 107 2

Then there is another table of all segments: ---------- SEGMENTATION DATA ---------- COORDINATES IN METERS I+ AND I- INDICATE THE SEGMENTS BEFORE AND AFTER I

SEG COORDINATES OF SEGM CENTER SEGM ORIENTATION ANGLES WIRE CONNECTION DATA TAG No: X Y Z LENGTH ALPHA BETA RADIUS I- I I+ No: 1 -0.2589 0.0006 -0.0180 0.0011 0.0000 90.0000 0.0005 -79 1 2 1 2 -0.2589 0.0017 -0.0180 0.0011 0.0000 90.0000 0.0005 1 2 3 1

Finally for each frequency there is a table with segment numbers and current data:

                       -------- CURRENTS AND LOCATION --------
                              DISTANCES IN WAVELENGTHS

SEG TAG COORDINATES OF SEGM CENTER SEGM ------------- CURRENT (AMPS) ------------- No: No: X Y Z LENGTH REAL IMAGINARY MAGN PHASE 1 1 -2.9496 0.0064 -0.2047 0.01288 3.9431E-06 -1.7680E-07 3.9471E-06 -2.567 2 1 -2.9496 0.0193 -0.2047 0.01288 3.9569E-06 -4.5664E-07 3.9831E-06 -6.583

I mostly use current info to check that the antenna operates as intended and that my segment sizes seems reasonable. I have never had any use for the information connecting the the segment numbers back to wire numbers. So for the way i use the data i think just storing the start/stop coordinates for each segment and the current in the segment in a table would be very useful. perhaps the columns could be: XStart YStart ZStart XEnd YEnd ZEnd ComplexCurrent

However other users might have use for the connection between segment and wire number.

The following should perhaps be a separate discussion, but i choose to mention it here anyway :)

I know it is possible to see the current distribution in the xnec2c structure view. However when simulating antennas that takes several hours to compute for each frequency, the fact that many gui actions causes the simulation to re run becomes cumbersome. For instance changing frequency by clicking the frequency data plots causes the gui to freeze until a new simulation is run makes it difficult to use for structures with long simulation time. A simple way to disable computation except for the initial one would be very useful in these cases.

KJ7LNW commented 1 year ago

Is it possible to create gnuplot files for all frequency radiation patterns in batch mode with the current version?

Not as a batch option, its just a save-as option. Patches are welcome if you want to implement that. The funciton just needs to be separated from UI behavior (if any) and linked in as --write-csv-rdpat somehow, and then it would work with --batch.

XStart YStart ZStart XEnd YEnd ZEnd ComplexCurrent

Good idea. Adding segment and tag numbers to that should be easy enough, then users can have both.

For instance changing frequency by clicking the frequency data plots causes the gui to freeze until a new simulation is run makes it difficult to use for structures with long simulation time

Right-click instead of click. It will jump to a pre-computed point instead of re-calculating at the arbitrary click point.

[...] causes the gui to freeze until a new simulation is run makes it difficult to use for structures with long simulation time.

Performance tips you may or may not know:

I mostly use current info to check that the antenna operates

I suppose once we have current data exported in batch, you can then optimize geometry based on current values with xnec2c-optimize.

KJ7LNW commented 1 year ago

If you want to experiment, you could play with the nec2c-output branch. This is a work-in-progress that I started to bring the nec2c output format to xnec2c as a "save-as" feature. However, at the moment, it will unilaterally overwrite nec2c.out and far.out to the current working directory (ie, no save-as option):

         --------------- FAR FIELD PATTERN DATA ---------------

Frequency = 5.00 MHz

   Reference = 0.0 dBi (what is this? Hard-coded at 0 for now.)

Azimuth Pattern   Elevation angle = 90.0 deg.
 Deg      V dB      H dB      Tot dB
  0.0      3.25    -50.34      3.25
 10.0      3.12    -12.06      3.25
 20.0      2.71     -6.12      3.25

Input current data does work:

                        --------- ANTENNA INPUT PARAMETERS ---------
  TAG   SEG       VOLTAGE (VOLTS)         CURRENT (AMPS)         IMPEDANCE (OHMS)        ADMITTANCE (MHOS)     POWER
  No:   No:     REAL      IMAGINARY     REAL      IMAGINARY     REAL      IMAGINARY    REAL       IMAGINARY   (WATTS)
  256   257  1.0000E+00  0.0000E+00  5.2756E-03  7.0132E-03  6.8500E+01 -9.1060E+01  5.2756E-03  7.0132E-03  2.6378E-03

but per-segment current data does not:

                                  DISTANCES IN WAVELENGTHS

   SEG  TAG    COORDINATES OF SEGM CENTER     SEGM    ------------- CURRENT (AMPS) -------------
   No:  No:       X         Y         Z      LENGTH     REAL      IMAGINARY    MAGN        PHASE
     1    1   -0.0968   -0.0025   -0.0080   0.00509  0.0000E+00  0.0000E+00  0.0000E+00    0.000
     2    2   -0.0105    0.0014    0.0166   0.00277  0.0000E+00  0.0000E+00  0.0000E+00    0.000
     3    3    0.0231    0.0014    0.0148   0.06754  0.0000E+00  0.0000E+00  0.0000E+00    0.000

Ultimately I reached the point where the save-as for an NEC2-style text format would rely on too many pre-calculated per-frequency fields that are not (currently) stored in xnec2c's data structures. Traditional Fortran NEC2 (and nec2c) write the output per iteration and don't nicely save these in RAM for a "save-as" feature (memory was pretty expensive back then, so "RAM" was feed paper to print out the data and iterate the next frequency). Many structures are reused on each frequency iteration, making it non-thread-safe, which is why xnec2c fork()s for parallelism instead of using threading.

I'm in the middle of a project right now to tease apart the per-frequency vs static-structure data that is calculated once. When this is done it will facilitate nec2-text output and pthreads-based parallelism, which in turn would allow a MinGW windows port (if anyone cares). Per-frequency pthreads (or OpenMP?) could make the UI more responsive, too (ie, render in background without interrupting the foreground). Thus, the thread-safe xnec2c implementation became the priority over nec2-text output... but it is still out an unknown amount of dev time in terms of implementation.

KJ7LNW commented 1 year ago

@bjohan,

I've added the features you are looking for with one caveat: Saving a CSV of currents only works for a single frequency because xnec2c does not store per-frequency current data in memory. See the commits and commit messages above for more detail.

Please try it out and see if it works for you. Also note these cmdline options:

  -b|--batch:        enable batch mode, exit after the frequency loop runs
     --optimize:     Activate the optimizer immediately.
  --write-rdpat           <filename>  - write CSV of the radiation pattern
  --write-currents        <filename>  - write CSV of currents and charges
KJ7LNW commented 1 year ago

If you can, please also verify that the data looks correct. I checked the radiation patterns and they look right, but I'm not sure how to verify that the currents and charges are right. If you can confirm with nec2c or another nec implementation then it would be good to know that the data I'm providing is actually the data you expect.

If there is any data error, then please send me your .NEC file and what you are getting vs what you expect, and maybe I can hunt down the difference.

bjohan commented 1 year ago

Im not finished examining the output files yet, but i have started looking at the data and have the following observations:

The file written using --write-currents only contains data for the last frequency.

The file written using --write-rdpat has an issue where the phi column is not set to the start value between frequencies, below is the boundary between two frequencies where phi goes from 0-180 and theta from 0-360. I would expect phi to be 0 at the first row for the new frequency but instead it is 180.17999999088923.

850.000000,179.99999999089835,359.99999998179669,-3.8825630707162633,-4.5052251783398027,-12.625493789020204,-6.4927835055597587,-7.3335731592988473 1734.482800,180.17999999088923,0,-4.2752790023114908,-4.3117015468191839,-25.05761783328358,-7.5666474810055373,-7.0216003183838218

As soon as i have looked a bit more at the data i will upload nec-files and my python script to check the data somewhere so that you can verify the issues if they are non trivial to reproduce.

KJ7LNW commented 1 year ago

The file written using --write-currents only contains data for the last frequency.

Yes, because of this, which I cannot fix easily:

"Saving a CSV of currents only works for a single frequency because xnec2c does not store per-frequency current data in memory. "

So, you should be able to (right-)click the frequency you want before saving currents.

I would expect phi to be 0 at the first row for the new frequency but instead it is 180.17999999088923.

Not sure what that means, could be an error in xnec2c's step calculation, or it could just be by design in how it decides to slice the sample points. I copy-pasted the radiation pattern rendering code and changed line drawing into printf's, so whatever it was doing graphically is the same thing it shows in the CSV. Still it might be a bug, so I can look when I have a copy of your .nec file.

As soon as i have looked a bit more at the data i will upload nec-files and my python script to check the data somewhere so that you can verify the issues if they are non trivial to reproduce.

sounds good.

bjohan commented 1 year ago

It was a pretty bad explanation from me... Let me try again :)

Run this from the src directory where the xnec2c binary lives after build:

./xnec2c -i ../examples/1MHz_tower.nec -b --write-rdpat /tmp/rdpat.csv | awk "NR==704, NR==705" /tmp/rdpat.csv

The output I get is:

0.980000,359.999999981803,89.999999995450693,4.3157408914062163,-278.80124584084143,4.3157408914062163,1.3054409347664033,1.3054409347664055
0.982000,"369.99999998129755",0,-66.039313878966738,-108.18696589108194,-66.03957874871179,-69.049731174526045,-69.049496499857256

I would expect the number in quotes to be zero, it should start at the same coordinates as the radiation pattern for the preceding frequency in the file?

bjohan commented 1 year ago

Moving line gnuplot.c:430 to gnuplot.c:442 seems to fix the issue. But i have not analyzed the code to see if there would be any unforeseen consequences...

KJ7LNW commented 1 year ago

I see what you mean: phi needs to reset on each frequency index, good catch.

Fixed.

KJ7LNW commented 1 year ago

Closing the ticket, re-open if something needs attention.