nec2++ 2.1.1
nec_results.h
1/*
2 Copyright (C) 2004-2008, 2015 Timothy C.A. Molteno
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
18#pragma once
19
20#include <vector>
21#include <ostream>
22#include <iostream>
23#include <iomanip>
24#include <string>
25
26#include "math_util.h"
27using namespace std;
28
29enum RESULT_FORMAT {
30 RESULT_FORMAT_NEC = 1,
31 RESULT_FORMAT_XML = 2,
32 RESULT_FORMAT_CSV = 3
33};
34
35
41{
42private:
43 ostream& os;
44 enum RESULT_FORMAT m_format;
45 bool m_in_section;
46
47public:
48
49 output_helper(ostream& in_os, enum RESULT_FORMAT in_format)
50 : os(in_os), m_format(in_format), m_in_section(false)
51 {
52 }
53
55 section_end();
56 }
57
58
59 inline void separator() {
60 switch (m_format) {
61 case RESULT_FORMAT_CSV:
62 os << ",";
63 break;
64
65 case RESULT_FORMAT_NEC:
66 default:
67 os << " ";
68 break;
69 }
70 }
71
72 inline void start_record() {
73 switch (m_format) {
74 case RESULT_FORMAT_XML:
75 os << "<record>";
76 break;
77
78 default:
79 break;
80 }
81 }
82
83 inline void end_record() {
84 switch (m_format) {
85 case RESULT_FORMAT_XML:
86 os << "</record>" << endl;
87 break;
88
89 default:
90 os << endl;
91 break;
92 }
93 }
94
95 inline void padding(const char* s) {
96 switch (m_format) {
97 case RESULT_FORMAT_NEC:
98 os << s;
99 break;
100
101 default:
102 break;
103 }
104 }
105
106 void center_text(const std::string& text, const string& border) {
107 size_t len = text.length() + 2*(border.length() + 1);
108 size_t offset = 40 - len/2;
109 for (size_t i=0;i<offset;i++)
110 os << " ";
111 os << border << " " << text << " " << border << endl;
112 }
113
114 inline void section_start(const std::string& section_name) {
115 if (m_in_section)
116 section_end();
117
118 switch (m_format) {
119 case RESULT_FORMAT_NEC:
120 os << endl << endl << endl;
121 center_text(section_name, "-----");
122 break;
123
124 case RESULT_FORMAT_XML:
125 os << "<section name=\"" << section_name << "\">" << endl;
126 break;
127
128 default:
129 os << endl << endl << endl;
130 break;
131 }
132 m_in_section = true;
133 }
134
135 inline void section_end() {
136 m_in_section = false;
137
138 switch (m_format) {
139 case RESULT_FORMAT_NEC:
140 os << endl << endl << endl;
141 break;
142
143 case RESULT_FORMAT_XML:
144 os << "</section>" << endl;
145 break;
146
147 default:
148 os << endl << endl << endl;
149 break;
150 }
151 }
152
153 inline void int_out(int w, int i) {
154 os << setw(w) << i;
155 }
156
157 inline void string_out(int w, const std::string& s) {
158 os << right << setw(w) << s;
159 }
160 inline void string_out(int w, const char* s) {
161 os << right << setw(w) << s;
162 }
163
164 inline void real_out(int w, int p, nec_float f, bool sci = true) {
165 ios::fmtflags flags = ios::showpoint | ios::uppercase | ios::right;
166 if (sci)
167 flags |= ios::scientific;
168 else
169 flags |= ios::fixed;
170
171 os.unsetf(ios::adjustfield | ios::basefield | ios::floatfield);
172 os.setf(flags);
173 os.precision(p);
174 os.width(w);
175 os << f;
176 }
177
178 inline void complex_out(int w, int p, nec_complex c, bool sci = true) {
179 real_out(w,p,real(c),sci);
180 separator();
181 real_out(w,p,imag(c),sci);
182 }
183
184 inline void polar_out(int w, int p, nec_complex c, bool sci = true) {
185 real_out(w,p,abs(c),sci);
186 separator();
187 real_out(w,p,arg_degrees(c),sci);
188 }
189};
190
191
194enum nec_result_type {
195 RESULT_NORMALIZED_RECEIVING_PATTERN = 1,
196 RESULT_STRUCTURE_EXCITATION = 2,
197 RESULT_ANTENNA_INPUT = 3,
198 RESULT_RADIATION_PATTERN = 4,
199 RESULT_NEAR_FIELD_PATTERN = 5,
200 RESULT_STRUCTURE_CURRENTS = 6
201};
202
209private:
210 bool _write_file;
211 nec_float _frequency;
212
213protected:
214 enum RESULT_FORMAT _result_format;
215
216public:
217 virtual void write_to_file(ostream& os) = 0;
218 virtual enum nec_result_type get_result_type() = 0;
219
221 : _write_file(true), _result_format(RESULT_FORMAT_NEC)
222 {
223 }
224
225 virtual ~nec_base_result() {
226 }
227
228 inline bool write_file() const {
229 return _write_file;
230 }
231
232 inline void set_write_file(bool f) {
233 _write_file = f;
234 }
235
236 inline void set_frequency(nec_float f) {
237 _frequency = f;
238 }
239
240 nec_float get_frequency() {
241 return _frequency;
242 }
243
244 inline void set_result_format(enum RESULT_FORMAT f) {
245 _result_format = f;
246 }
247};
248
249
253{
254 // Receiving Pattern
255 nec_float _eta, _axial_ratio;
256 int _segment_number;
257 string _type;
258
259 int n_theta;
260 int n_phi;
261 nec_float _theta0, _theta_step;
262 nec_float _phi0, _phi_step;
263
264 real_array _mag;
265
266public:
268 int in_n_theta, int in_n_phi,
269 real_matrix& in_mag,
270 nec_float theta0, nec_float theta_step,
271 nec_float phi0, nec_float phi_step,
272 nec_float in_eta,
273 nec_float in_axial_ratio,
274 int in_segment_number,
275 string in_type)
276 {
277 n_theta = in_n_theta;
278 n_phi = in_n_phi;
279
280 _mag = in_mag;
281 _mag.resize(n_theta, n_phi);
282
283 _theta0 = theta0;
284 _theta_step = theta_step;
285
286 _phi0 = phi0;
287 _phi_step = phi_step;
288
289 _eta = in_eta;
290 _axial_ratio = in_axial_ratio;
291 _segment_number = in_segment_number;
292 _type = in_type;
293
294 _mag.resize(n_theta, n_phi);
295 }
296
297 virtual ~nec_norm_rx_pattern() override {
298 }
299
300 virtual enum nec_result_type get_result_type() override {
301 return RESULT_NORMALIZED_RECEIVING_PATTERN;
302 }
303
304 void set_input(int theta_index, int phi_index, nec_float mag) {
305 _mag(theta_index,phi_index) = mag;
306 }
307
308
309 /*Added for the python wrapping : some basic access functions...*/
310
311 int get_n_theta() {
312 return n_theta;
313 }
314
315 int get_n_phi() {
316 return n_phi;
317 }
318
319 nec_float get_theta_start() {
320 return _theta0;
321 }
322
323 nec_float get_phi_start() {
324 return _phi0;
325 }
326
327 nec_float get_delta_theta() {
328 return _theta_step;
329 }
330
331 nec_float get_delta_phi() {
332 return _phi_step;
333 }
334
335 nec_float get_eta() {
336 return _eta;
337 }
338
339 nec_float get_axial_ratio() {
340 return _axial_ratio;
341 }
342
343 int get_segment_number() {
344 return _segment_number;
345 }
346
347 string get_type() {
348 return _type;
349 }
350
351 real_array get_mag() {
352 return _mag;
353 }
354
355 /*End of access functions added for the wrapping*/
356
357 nec_float get_mag(int theta_index, int phi_index) {
358 return _mag(theta_index, phi_index);
359 }
360
361 nec_float get_norm_factor() {
362 return _mag.maxCoeff();
363 }
364
365 virtual void write_to_file(ostream& os) override {
366 if (n_theta == 0)
367 return;
368 if (n_phi == 0)
369 return;
370
371 nec_float norm_factor = get_norm_factor();
372
373 output_helper oh(os,_result_format);
374
375 oh.section_start("NORMALIZED RECEIVING PATTERN");
376 os << " NORMALIZATION FACTOR: ";oh.real_out(11,4,norm_factor);os << endl;
377 os << " ETA: ";oh.real_out(7,2,_eta,false); os << " DEGREES" << endl;
378 os << " TYPE: " << _type << endl;
379 os << " AXIAL RATIO: "; oh.real_out(6,3,_axial_ratio,false); os << endl;
380 os << " SEGMENT No: ";oh.int_out( 5, _segment_number); os << endl << endl;
381 os << " THETA PHI ---- PATTERN ----" << endl;
382 os << " (DEG) (DEG) DB MAGNITUDE" << endl;
383
384 nec_float theta = _theta0;
385
386 for (int t=0; t<n_theta; t++) {
387 nec_float phi = _phi0;
388
389 for (int p=0; p<n_phi;p++) {
390 nec_float magnitude = _mag(t,p) / norm_factor;
391 nec_float gain = db20(magnitude);
392
393 oh.start_record();
394 oh.padding(" ");
395 oh.real_out(7,2, theta, false); oh.separator();
396 oh.real_out(7,2, phi, false); oh.separator();
397 oh.padding(" "); oh.real_out(7,2, gain, false); oh.separator();
398 oh.padding(" "); oh.real_out(11,4, magnitude);
399 oh.end_record();
400
401 phi += _phi_step;
402 }
403 theta += _theta_step;
404 }
405 }
406};
407
408
409
413private:
414 vector<int> _tag, _segment;
415 vector<nec_complex> _voltage, _current, _impedance, _admittance;
416 vector<nec_float> _power;
417 int64_t n_items;
418 nec_complex voli, curi;
419
420public:
421
423 n_items = 0;
424 }
425
426 virtual ~nec_structure_excitation() override { }
427
428
429 virtual enum nec_result_type get_result_type() override {
430 return RESULT_STRUCTURE_EXCITATION;
431 }
432
433 /*The two methods bellow have been modified to get rid of "nec_structure_excitation_data" */
434
435 void add(int segment, int tag, nec_complex voltage, nec_complex current, nec_float power) {
436 n_items++;
437 _tag.push_back(tag);
438 _segment.push_back(segment);
439 _voltage.push_back(voltage);
440 _current.push_back(current);
441 _impedance.push_back(voltage/current);
442 _admittance.push_back(current/voltage);
443 _power.push_back(power);
444
445 }
446
447 virtual void write_to_file(ostream& os) override {
448 output_helper oh(os,_result_format);
449 oh.section_start("STRUCTURE EXCITATION DATA AT NETWORK CONNECTION POINTS");
450 os << " TAG SEG VOLTAGE (VOLTS) CURRENT (AMPS) IMPEDANCE (OHMS) ADMITTANCE (MHOS) POWER" << endl;
451 os << " No: No: REAL IMAGINARY REAL IMAGINARY REAL IMAGINARY REAL IMAGINARY (WATTS)" << endl;
452
453 for (int i=0; i<n_items; i++) {
454 oh.start_record();
455 oh.int_out(4, _tag[i]); oh.separator();
456 oh.int_out(5, _segment[i]); oh.separator();
457 oh.complex_out(11,4, _voltage[i]); oh.separator();
458 oh.complex_out(11,4, _current[i]); oh.separator();
459 oh.complex_out(11,4, _impedance[i]); oh.separator();
460 oh.complex_out(11,4, _admittance[i]); oh.separator();
461 oh.real_out(11,4, _power[i]);
462 oh.end_record();
463 }
464 }
465
466 /*Added for the python wrapping : some basic access functions...*/
467
468 vector<int> get_tag() {
469 return _tag;
470 }
471
472 vector<int> get_segment() {
473 return _segment;
474 }
475
476 vector<nec_complex> get_current() {
477 return _current;
478 }
479
480 vector<nec_complex> get_voltage() {
481 return _voltage;
482 }
483
484 vector<nec_float> get_power() {
485 return _power;
486 }
487
488 /*End of access functions added for the wrapping*/
489
490};
491
495 // Antenna Input Parameters
496 vector<int> _tag, _segment;
497 vector<nec_float> _power;
498 vector<nec_complex> _voltage, _current, _impedance, _admittance;
499 long n_items;
500
501public:
503 n_items = 0;
504 }
505
506 virtual ~nec_antenna_input() override {
507 }
508
509 virtual enum nec_result_type get_result_type() override {
510 return RESULT_ANTENNA_INPUT;
511 }
512
513 void set_input(int tag, int segment, nec_complex voltage, nec_complex current, nec_complex impedance, nec_complex admittance, nec_float power);
514
515 virtual void write_to_file(ostream& os) override {
516 if (n_items == 0)
517 return;
518
519 output_helper oh(os,_result_format);
520 oh.section_start("ANTENNA INPUT PARAMETERS");
521 os << " TAG SEG VOLTAGE (VOLTS) CURRENT (AMPS) IMPEDANCE (OHMS) ADMITTANCE (MHOS) POWER" << endl;
522 os << " NO. NO. REAL IMAGINARY REAL IMAGINARY REAL IMAGINARY REAL IMAGINARY (WATTS)" << endl;
523 for (int i=0; i<n_items; i++) {
524 oh.start_record();
525 oh.int_out(4, _tag[i]); oh.separator();
526 oh.int_out(5, _segment[i]); oh.separator();
527 oh.complex_out(11,4, _voltage[i]); oh.separator();
528 oh.complex_out(11,4, _current[i]); oh.separator();
529 oh.complex_out(11,4, _impedance[i]); oh.separator();
530 oh.complex_out(11,4, _admittance[i]); oh.separator();
531 oh.real_out(11,4, _power[i]);
532 oh.end_record();
533 }
534 }
535
536 /*Added for the python wrapping : some basic access functions...*/
537
538 vector<int> get_tag() {
539 return _tag;
540 }
541
542 vector<int> get_segment() {
543 return _segment;
544 }
545
546 vector<nec_complex> get_current() {
547 return _current;
548 }
549
550 vector<nec_complex> get_voltage() {
551 return _voltage;
552 }
553
554 vector<nec_complex>& get_impedance();
555
556 vector<nec_float> get_power() {
557 return _power;
558 }
559
560 /*End of access functions added for the wrapping*/
561};
562
563
565private:
566 /*Near field pattern*/
567 int nfeh;
568 vector<nec_float> _x, _y, _z;
569 vector<nec_complex> _field_x, _field_y, _field_z;
570 long n_items;
571
572public:
573 nec_near_field_pattern(int in_nfeh) {
574 nfeh = in_nfeh;
575 n_items = 0;
576 }
577
578 virtual ~nec_near_field_pattern() override {
579 }
580
581 virtual enum nec_result_type get_result_type() override {
582 return RESULT_NEAR_FIELD_PATTERN;
583 }
584
585 void set_input(nec_float x, nec_float y, nec_float z, nec_complex field_x, nec_complex field_y, nec_complex field_z);
586
587 virtual void write_to_file(ostream& os) override {
588 if (n_items == 0)
589 return;
590
591 output_helper oh(os,_result_format);
592
593 if ( nfeh != 1) {
594 oh.section_start("NEAR ELECTRIC FIELDS");
595 os << " ------- LOCATION ------- ------- EX ------ ------- EY ------ ------- EZ ------" << endl;
596 os << " X Y Z MAGNITUDE PHASE MAGNITUDE PHASE MAGNITUDE PHASE" << endl;
597 os << " METERS METERS METERS VOLTS/M DEGREES VOLTS/M DEGREES VOLTS/M DEGREES" << endl;
598 } else {
599 oh.section_start("NEAR MAGNETIC FIELDS");
600 os << " ------- LOCATION ------- ------- HX ------ ------- HY ------ ------- HZ ------" << endl;
601 os << " X Y Z MAGNITUDE PHASE MAGNITUDE PHASE MAGNITUDE PHASE" << endl;
602 os << " METERS METERS METERS AMPS/M DEGREES AMPS/M DEGREES AMPS/M DEGREES" << endl;
603 }
604 for (int i=0; i<n_items; i++) {
605 oh.start_record();
606 oh.padding(" ");
607 oh.real_out(9, 4, _x[i], false); oh.separator();
608 oh.real_out(9, 4, _y[i], false); oh.separator();
609 oh.real_out(9, 4, _z[i], false); oh.separator();
610 oh.padding(" ");
611 oh.real_out(11, 4, abs(_field_x[i]), true); oh.separator();
612 oh.real_out(7, 2, arg_degrees(_field_x[i]), false); oh.separator();
613 oh.padding(" ");
614 oh.real_out(11, 4, abs(_field_y[i]), true); oh.separator();
615 oh.real_out(7, 2, arg_degrees(_field_y[i]), false); oh.separator();
616 oh.padding(" ");
617 oh.real_out(11, 4, abs(_field_z[i]), true); oh.separator();
618 oh.real_out(7, 2, arg_degrees(_field_z[i]), false); oh.separator();
619 oh.end_record();
620 }
621 }
622
623 /*Added for the python wrapping : some basic access functions...*/
624
625 int get_nfeh() {
626 return nfeh;
627 }
628
629 vector<nec_float> get_x() {
630 return _x;
631 }
632
633 vector<nec_float> get_y() {
634 return _y;
635 }
636
637 vector<nec_float> get_z() {
638 return _z;
639 }
640
641 vector<nec_complex> get_field_x() {
642 return _field_x;
643 }
644
645 vector<nec_complex> get_field_y() {
646 return _field_y;
647 }
648
649 vector<nec_complex> get_field_z() {
650 return _field_z;
651 }
652
653 /*End of access functions added for the wrapping*/
654};
655
656
658
660
675 vector<nec_base_result*> _results;
676 int _n;
677 bool _file_out;
678
679
680public:
681 enum RESULT_FORMAT m_result_format;
682
683 nec_results() {
684 m_result_format = RESULT_FORMAT_NEC;
685
686 _n = 0;
687 _file_out = false;
688 }
689
690 // On destruction we write to a file.
691 ~nec_results() {
692 // write_to_file();
693 for (int i=0;i<_n;i++) {
694 delete _results[i];
695 _results[i] = NULL;
696 }
697 }
698
699 void add(nec_base_result* br) {
700 br->set_result_format(m_result_format);
701 _results.push_back(br);
702 _n++;
703 }
704
711 nec_base_result* get_result(const long index, const enum nec_result_type result_type) {
712 long counter = 0;
713
714 for (int i=0;i<_n;i++) {
715 if (_results[i]->get_result_type() == result_type) {
716 if (index == counter++)
717 return _results[i];
718 }
719 }
720
721 return NULL;
722 }
723
730 return (nec_norm_rx_pattern*)get_result(index, RESULT_NORMALIZED_RECEIVING_PATTERN);
731 }
732
739 return (nec_radiation_pattern*)get_result(index, RESULT_RADIATION_PATTERN);
740 }
741
748 return (nec_antenna_input*)get_result(index, RESULT_ANTENNA_INPUT);
749 }
750
757 return (nec_structure_excitation*)get_result(index, RESULT_STRUCTURE_EXCITATION);
758 }
759
766 return (nec_near_field_pattern*)get_result(index, RESULT_NEAR_FIELD_PATTERN);
767 }
768
775 return (nec_structure_currents*)get_result(index, RESULT_STRUCTURE_CURRENTS);
776 }
777
778 void write(ostream& os) {
779 for (int i=0;i<_n;i++) {
780 if (_results[i]->write_file()) {
781 _results[i]->write_to_file(os);
782 _results[i]->set_write_file(false);
783 }
784 }
785 }
786};
787
Definition nec_results.h:494
Definition nec_results.h:208
Definition nec_results.h:564
Definition nec_results.h:253
Definition nec_radiation_pattern.h:49
Definition nec_results.h:674
nec_structure_excitation * get_structure_excitation(const long index)
Get structure excitation results.
Definition nec_results.h:756
nec_base_result * get_result(const long index, const enum nec_result_type result_type)
Get the nth result that matches the specified result type.
Definition nec_results.h:711
nec_norm_rx_pattern * get_norm_rx_pattern(const long index)
Get normalized receiving pattern results.
Definition nec_results.h:729
nec_antenna_input * get_antenna_input(const long index)
Get antenna input parameter results.
Definition nec_results.h:747
nec_structure_currents * get_structure_currents(const long index)
Get structure currents results.
Definition nec_results.h:774
nec_near_field_pattern * get_near_field_pattern(const long index)
Get near field pattern results.
Definition nec_results.h:765
nec_radiation_pattern * get_radiation_pattern(const long index)
Get radiation pattern results.
Definition nec_results.h:738
Definition nec_structure_currents.h:30
Holds structure excitation data at network connection points.
Definition nec_results.h:412
A class that handles various standard output functions for the results.
Definition nec_results.h:41
Definition CurrentInput.h:26