nec2++ 2.1.1
nec_radiation_pattern.h
1/*
2 Copyright (C) 2004-2015 Timothy C.A. Molteno
3 tim@molteno.net
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19#pragma once
20
21#include "nec_results.h"
22#include "math_util.h"
23#include "nec_ground.h"
24#include "c_plot_card.h"
25
26
27
30enum polarization_norm {
31 POL_MAJOR_AXIZ=1,
32 POL_MINOR_AXIS=2,
33 POL_VERTICAL=3,
34 POL_HORIZONTAL=4,
35 POL_TOTAL=5
36};
37
40enum polarization_sense {
41 POL_LINEAR=0,
42 POL_RIGHT=1,
43 POL_LEFT=2
44};
45
46class nec_context;
47
49{
50public:
51 // Radiation Pattern
52 nec_radiation_pattern(int in_n_theta, int in_n_phi,
53 nec_float in_theta_start, nec_float in_phi_start,
54 nec_float in_delta_theta, nec_float in_delta_phi,
55 nec_float in_range,
56 nec_ground& in_ground,
57 int in_ifar, nec_float in_wavelength,
58 nec_float pinr, nec_float pnlr,
59 int in_rp_output_format, int in_rp_normalization, int in_rp_ipd, int in_rp_power_average,
60 nec_float in_gnor,
61 c_plot_card& in_plot_card);
62
63 virtual void write_to_file(ostream& os) override {
64 write_to_file_aux(os);
65 }
66
67 virtual enum nec_result_type get_result_type() override {
68 return RESULT_RADIATION_PATTERN;
69 }
70
71 void analyze(nec_context* in_context);
72
73 void write_gain_normalization() {
74 if (_ifar != 1) {
75 nec_float norm = get_maximum_gain_db();
76 printf("Max Gain: %f\n",norm);
77 }
78 }
79
80
81 /*Added for the python wrapping : some basic access functions...*/
82
83 real_matrix get_gain() {
84 return _gain;
85 }
86
87 real_array get_gain_vert() {
88 return _power_gain_vert;
89 }
90
91 real_array get_gain_horiz() {
92 return _power_gain_horiz;
93 }
94
95 real_array get_gain_tot() {
96 return _power_gain_tot;
97 }
98
99 real_array get_pol_axial_ratio() {
100 return _polarization_axial_ratio;
101 }
102
105 nec_float get_pol_axial_ratio(int theta_index, int phi_index) const {
106 return _polarization_axial_ratio(theta_index, phi_index);
107 }
108
109 real_array get_pol_tilt() {
110 return _polarization_tilt;
111 }
112
113 int_array get_pol_sense_index() {
114 return _polarization_sense_index;
115 }
116
120 int get_pol_sense(int theta_index, int phi_index) const {
121 return _polarization_sense_index(theta_index, phi_index);
122 }
123
126 nec_float get_etheta_magnitude(int theta_index, int phi_index) {
127 return abs(_e_theta(theta_index, phi_index));
128 }
129
132 nec_float get_etheta_phase(int theta_index, int phi_index) {
133 return arg_degrees(_e_theta(theta_index, phi_index));
134 }
135
139 return _e_theta;
140 }
141
144 nec_float get_ephi_magnitude(int theta_index, int phi_index) {
145 return abs(_e_phi(theta_index, phi_index));
146 }
147
150 nec_float get_ephi_phase(int theta_index, int phi_index) {
151 return arg_degrees(_e_phi(theta_index, phi_index));
152 }
153
157 return _e_phi;
158 }
159
160 complex_array get_e_r() {
161 return _e_r;
162 }
163
164 nec_float get_normalization_factor() {
165 return get_gain_normalization_factor(m_rp_gnor);
166 }
167
168 nec_float get_average_power_gain() {
169 return _average_power_gain;
170 }
171
172 nec_float get_average_power_solid_angle() {
173 return _average_power_solid_angle;
174 }
175
176 nec_ground get_ground() {
177 return m_ground;
178 }
179
180 nec_float get_range() {
181 return m_range;
182 }
183
184 nec_float get_wavelength() {
185 return _wavelength;
186 }
187
190 real_array ret(n_theta);
191 for (int32_t i=0; i<n_theta; i++)
192 ret[i] = get_theta(i);
193 return ret;
194 }
195
196 nec_float get_delta_theta() {
197 return delta_theta;
198 }
199
200 nec_float get_theta_start() {
201 return m_theta_start;
202 }
203
206 real_array ret(n_phi);
207 for (int32_t i=0; i<n_phi; i++)
208 ret[i] = get_phi(i);
209 return ret;
210 }
211
212 nec_float get_delta_phi() {
213 return delta_phi;
214 }
215
216 nec_float get_phi_start() {
217 return m_phi_start;
218 }
219
220
221 int get_ifar() {
222 return _ifar;
223 }
224
225 int get_rp_normalization() {
226 return m_rp_normalization;
227 }
228
229 int get_rp_output_format() {
230 return m_rp_output_format;
231 }
232
233 int get_rp_power_average() {
234 return m_rp_power_average;
235 }
236
237 int get_rp_ipd() {
238 return m_rp_ipd;
239 }
240
241 /*End of access functions added for the wrapping*/
242
243
244 nec_float get_maximum_gain_db() {
245 return get_gain_normalization_factor(0);
246 }
247
248 /****************** STATISTICS ********************/
249
250
251private:
252 nec_float mean(const real_matrix& pattern) const {
253 nec_float sum = 0.0;
254 int64_t rows = pattern.rows();
255 int64_t cols = pattern.cols();
256 for (int64_t i=0;i<rows;i++) {
257 for (int64_t j=0;j<cols;j++) {
258 sum += pattern(i,j) * _averaging_scales(i,j);
259 }
260 }
261 int64_t len = rows*cols;
262 return sum/(nec_float(len*2) / pi());
263 }
264
265 nec_float sd(const real_matrix& pattern, nec_float _mean) const {
266 nec_float sum = 0.0;
267 int64_t rows = pattern.rows();
268 int64_t cols = pattern.cols();
269
270 for (int64_t i=0;i<rows;i++) {
271 for (int64_t j=0;j<cols;j++) {
272 nec_float diff = pattern(i,j) - _mean;
273 sum += diff*diff * _averaging_scales(i,j);
274 }
275 }
276 int64_t len = rows*cols;
277 return std::sqrt(sum/(nec_float(len*2) / pi()));
278 }
279
280
281public:
282 nec_float get_gain_max() const {
283 return _power_gain_tot.maxCoeff();
284 }
285
286 nec_float get_gain_min() const {
287 return _power_gain_tot.minCoeff();
288 }
289
290 nec_float get_gain_mean() const {
291 return mean(_power_gain_tot);
292 }
293
294 nec_float get_gain_sd() const {
295 nec_float _mean = get_gain_mean();
296 return sd(_power_gain_tot, _mean);
297 }
298
299 /********************** RHCP ********************************/
300 nec_float get_gain_rhcp_max() const {
301 return _power_gain_rhcp.maxCoeff();
302 }
303
304 nec_float get_gain_rhcp_min() const {
305 return _power_gain_rhcp.minCoeff();
306 }
307
308 nec_float get_gain_rhcp_mean() const {
309 return mean(_power_gain_rhcp);
310 }
311
312 nec_float get_gain_rhcp_sd() const {
313 nec_float _mean = get_gain_rhcp_mean();
314 return sd(_power_gain_rhcp, _mean);
315 }
316
317 /********************** LHCP ********************************/
318 nec_float get_gain_lhcp_max() const {
319 return _power_gain_lhcp.maxCoeff();
320 }
321
322 nec_float get_gain_lhcp_min() const {
323 return _power_gain_lhcp.minCoeff();
324 }
325
326 nec_float get_gain_lhcp_mean() const {
327 return mean(_power_gain_lhcp);
328 }
329
330 nec_float get_gain_lhcp_sd() const {
331 nec_float _mean = get_gain_lhcp_mean();
332 return sd(_power_gain_lhcp, _mean);
333 }
334
335 /* End of Statistics functions for the C interface */
336
337
338
341 nec_float get_theta(int theta_index) const {
342 return (m_theta_start + delta_theta*theta_index);
343 }
344
347 int get_ntheta() const {
348 return (n_theta);
349 }
350
353 nec_float get_phi(int phi_index) const {
354 return (m_phi_start + delta_phi*phi_index);
355 }
356
359 int get_nphi() const {
360 return (n_phi);
361 }
362
365 nec_float get_power_gain(int theta_index, int phi_index) const {
366 return _gain(theta_index, phi_index);
367 }
368
371 nec_float get_power_gain_vert(int theta_index, int phi_index) const {
372 return _power_gain_vert(theta_index, phi_index);
373 }
374
377 nec_float get_power_gain_horiz(int theta_index, int phi_index) const {
378 return _power_gain_horiz(theta_index, phi_index);
379 }
380
383 nec_float get_power_gain_tot(int theta_index, int phi_index) const {
384 return _power_gain_tot(theta_index, phi_index);
385 }
386
389 nec_float get_power_gain_rhcp(int theta_index, int phi_index) const {
390 nec_float a = get_pol_axial_ratio(theta_index, phi_index);
391 nec_float dbi = get_power_gain_tot(theta_index, phi_index);
392 if (get_pol_sense(theta_index, phi_index) == POL_RIGHT)
393 a = -a;
394
395 nec_float f = (1-2*a+a*a)/(2*(1+a*a));
396 return dbi + 10*log10(f);
397 }
398
401 nec_float get_power_gain_lhcp(int theta_index, int phi_index) const {
402 nec_float a = get_pol_axial_ratio(theta_index, phi_index);
403 nec_float dbi = get_power_gain_tot(theta_index, phi_index);
404 if (get_pol_sense(theta_index, phi_index) == POL_RIGHT)
405 a = -a;
406
407 nec_float f = (1+2*a+a*a)/(2*(1+a*a));
408 return dbi + 10*log10(f);
409 }
410
411private:
412
413 int get_index(int theta_index, int phi_index) const;
414
415 bool m_analysis_done;
416
417 int n_theta, n_phi;
418
419 nec_float m_theta_start, delta_theta;
420 nec_float m_phi_start, delta_phi;
421
422 int _ifar;
423
424 nec_float m_range;
425
426 nec_float _wavelength;
427 nec_float _pinr;
428 nec_float _pnlr;
429
430 nec_float _average_power_gain;
431 nec_float _average_power_solid_angle;
432 nec_float _maximum_gain;
433
434 int m_rp_normalization;
435 int m_rp_output_format;
436 int m_rp_power_average;
437 int m_rp_ipd;
438
439 nec_float m_rp_gnor;
440
441 real_matrix _gain;
442 real_matrix _power_gain_lhcp;
443 real_matrix _power_gain_rhcp;
444 real_matrix _power_gain_vert;
445 real_matrix _power_gain_horiz;
446 real_matrix _power_gain_tot;
447 real_matrix _polarization_axial_ratio;
448 real_matrix _polarization_tilt;
449 real_matrix _averaging_scales;
450 int_matrix _polarization_sense_index;
451
452 complex_matrix _e_theta;
453 complex_matrix _e_phi;
454 complex_matrix _e_r;
455
456 void write_to_file_aux(ostream& os);
457
458 nec_float get_gain_normalization_factor(nec_float gnor);
459
460 void write_normalized_gain(ostream& os);
461
462 nec_ground m_ground;
463 c_plot_card m_plot_card;
464};
Definition c_plot_card.h:44
Definition nec_results.h:208
Container for an nec2++ simulation.
Definition nec_context.h:80
Definition nec_ground.h:63
Definition nec_radiation_pattern.h:49
real_array get_theta_angles() const
Definition nec_radiation_pattern.h:189
int get_nphi() const
Get the number of phi angles.
Definition nec_radiation_pattern.h:359
nec_float get_power_gain_vert(int theta_index, int phi_index) const
Get a power gain (vertical) from the radiation pattern.
Definition nec_radiation_pattern.h:371
real_array get_phi_angles() const
Definition nec_radiation_pattern.h:205
nec_float get_power_gain(int theta_index, int phi_index) const
Get a total power gain from the radiation pattern.
Definition nec_radiation_pattern.h:365
complex_array get_e_theta()
Return a complex array for the electric field E(THETA)
Definition nec_radiation_pattern.h:138
nec_float get_power_gain_lhcp(int theta_index, int phi_index) const
Get the power gain if the antenna were receiving LHCP signals.
Definition nec_radiation_pattern.h:401
nec_float get_phi(int phi_index) const
Get the phi angle corresponding to the phi_index.
Definition nec_radiation_pattern.h:353
nec_float get_etheta_phase(int theta_index, int phi_index)
Get the phase (in degrees) of E(THETA)
Definition nec_radiation_pattern.h:132
int get_ntheta() const
Get the number of theta angles.
Definition nec_radiation_pattern.h:347
nec_float get_ephi_phase(int theta_index, int phi_index)
Get the phase (in degrees) of E(PHI)
Definition nec_radiation_pattern.h:150
nec_float get_power_gain_rhcp(int theta_index, int phi_index) const
Get the power gain if the antenna were receiving RHCP signals.
Definition nec_radiation_pattern.h:389
nec_float get_power_gain_horiz(int theta_index, int phi_index) const
Get a power gain (horizontal) from the radiation pattern.
Definition nec_radiation_pattern.h:377
void analyze(nec_context *in_context)
Generate the data for the radiation pattern.
Definition nec_radiation_pattern.cpp:205
nec_float get_power_gain_tot(int theta_index, int phi_index) const
Get a power gain (total dBi) from the radiation pattern.
Definition nec_radiation_pattern.h:383
int get_pol_sense(int theta_index, int phi_index) const
Get the polarization sense.
Definition nec_radiation_pattern.h:120
complex_array get_e_phi()
Return a complex array for the electric field E(PHI)
Definition nec_radiation_pattern.h:156
nec_float get_pol_axial_ratio(int theta_index, int phi_index) const
Get the polarization axial ratio.
Definition nec_radiation_pattern.h:105
nec_float get_theta(int theta_index) const
Get the theta angle corresponding to the theta_index.
Definition nec_radiation_pattern.h:341
nec_float get_ephi_magnitude(int theta_index, int phi_index)
Get the magnitude of E(PHI)
Definition nec_radiation_pattern.h:144
nec_float get_etheta_magnitude(int theta_index, int phi_index)
Get the magnitude of E(THETA)
Definition nec_radiation_pattern.h:126