Skip to content

Commit e275894

Browse files
added 4nec2 LD 6 support (experimental!)
1 parent a320531 commit e275894

File tree

6 files changed

+67
-12
lines changed

6 files changed

+67
-12
lines changed

doc/TODO

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
Items still to be implemented:
22

3-
* add support for the nec-2 style calling convention, using a tmp file with the input and output file names on separate lines
4-
53
* finish maa support, need to properly handle the loading based on wire and segment
64

75
* get more info on the .ez format
@@ -22,7 +20,7 @@ Items still to be implemented:
2220

2321
* nec2++ examples/medium_test.nec has an "MP" card type
2422

25-
* at some point, handle 4nec2 current sources, EX 6 and 7 (UA3SFH.nec, W2EEY.NEC, calvin.nec, class.NEC)
23+
* at some point, handle 4nec2 current sources, EX 6 (UA3SFH.nec, W2EEY.NEC, calvin.nec, class.NEC)
2624

2725
* add support for LD type 7 from 4nec2
2826

src/calculations.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -351,9 +351,9 @@ int apply_impedance_loading(nec_context_t *ctx, int *ldtyp, int *ldtag, int *ldt
351351

352352
} /* if( istep > ctx->zload.num_loads) */
353353

354-
/* ldtyp is validated (0–5) by control.c before storage; this should
354+
/* ldtyp is validated (0–6) by control.c before storage; this should
355355
* never fire. If it does, it is a programming error, not a user error. */
356-
assert(ldtyp[istepx] <= 5 && "INTERNAL: IMPROPER LOAD TYPE stored in zload.load_types");
356+
assert(ldtyp[istepx] <= 6 && "INTERNAL: IMPROPER LOAD TYPE stored in zload.load_types");
357357

358358
/* search segments for proper itags */
359359
ldtags= ldtag[istepx];
@@ -430,7 +430,30 @@ int apply_impedance_loading(nec_context_t *ctx, int *ldtyp, int *ldtag, int *ldt
430430

431431
case 6:
432432
wire_surface_impedance( ctx, zlr[istepx]* ctx->geometry.wavelength, ctx->geometry.radius[i], &zt );
433-
433+
break;
434+
435+
case 7: {
436+
/* LD type 6: LC-trap. Convert to parallel-RLC at the design frequency.
437+
* F1 = unloaded-Q of the inductor (0 -> 100), F2 = L (H), F3 = C (F)
438+
* F4 = optional design frequency in MHz (0 -> use first FR card). */
439+
double f0_mhz = (ctx->zload.load_freq[istepx] != 0.0)
440+
? ctx->zload.load_freq[istepx]
441+
: ctx->save.first_fr_mhz;
442+
double Q = (fabs(zlr[istepx]) < 1.0e-20) ? 100.0 : zlr[istepx];
443+
double L = zli[istepx];
444+
double C = zlc[istepx];
445+
double omega0 = 2.0 * M_PI * f0_mhz * 1.0e6;
446+
double R_par = Q * omega0 * L; /* parallel loss resistance at design freq */
447+
/* Apply parallel-RLC formula (same as type 1 / case 2) */
448+
zt = tpcj * ctx->geometry.half_len[i] * C / ctx->geometry.wavelength;
449+
if (fabs(L) > 1.0e-20)
450+
zt += ctx->geometry.half_len[i] * ctx->geometry.wavelength / (tpcj * L);
451+
if (R_par > 1.0e-20)
452+
zt += ctx->geometry.half_len[i] / R_par;
453+
zt = 1.0 / zt;
454+
break;
455+
}
456+
434457
} /* switch( jump ) */
435458

436459
if(( fabs( creal( ctx->zload.seg_impedance[i]))+ fabs( cimag( ctx->zload.seg_impedance[i]))) > 1.0e-20) {
@@ -499,6 +522,10 @@ int apply_impedance_loading(nec_context_t *ctx, int *ldtyp, int *ldtag, int *ldt
499522

500523
case 6:
501524
add_loading_output(ctx, ldtags, ldtagf[istepx], ldtagt[istepx], zlr[istepx], 0.0, 0.0, "WIRE");
525+
break;
526+
527+
case 7:
528+
add_loading_output(ctx, ldtags, ldtagf[istepx], ldtagt[istepx], 0.0, zli[istepx], zlc[istepx], "LC-TRAP");
502529

503530
} /* switch( jump ) */
504531
} /* while( true ) */

src/control.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ static void reset_loading_buffers(nec_context_t *ctx)
434434
mem_free(ctx, (void **)&ctx->zload.load_r);
435435
mem_free(ctx, (void **)&ctx->zload.load_l);
436436
mem_free(ctx, (void **)&ctx->zload.load_c);
437+
mem_free(ctx, (void **)&ctx->zload.load_freq);
437438
ctx->zload.num_loads = 0;
438439
}
439440
if (ctx->loading_outputs.entries != NULL) {
@@ -643,14 +644,16 @@ static int process_next_batch(nec_context_t *ctx, deck_t *deck, int *batch_start
643644
ctx->save.num_freq = (i2 == 0) ? 1 : i2;
644645
ctx->save.freq_mhz = f1;
645646
ctx->save.freq_step = f2;
647+
if (ctx->save.first_fr_mhz == 0.0)
648+
ctx->save.first_fr_mhz = f1;
646649
}
647650
else if (strcmp(code, "LD") == 0) {
648651
// LD card - Loading
649652
if (i1 == -1) {
650653
continue;
651654
}
652655

653-
if (i1 > 5) {
656+
if (i1 > 6) {
654657
char msg[MAX_ERROR_LEN];
655658
snprintf(msg, sizeof(msg), "LD on line %d: type %d is not supported.", card_idx + 1, i1);
656659
add_error(ctx, &ctx->errors, msg, FATAL);
@@ -676,6 +679,7 @@ static int process_next_batch(nec_context_t *ctx, deck_t *deck, int *batch_start
676679
mem_realloc(ctx, (void **)&ctx->zload.load_r, mreq);
677680
mem_realloc(ctx, (void **)&ctx->zload.load_l, mreq);
678681
mem_realloc(ctx, (void **)&ctx->zload.load_c, mreq);
682+
mem_realloc(ctx, (void **)&ctx->zload.load_freq, mreq);
679683

680684
int idx = ctx->zload.num_loads - 1;
681685
ctx->zload.load_types[idx] = i1;
@@ -696,6 +700,9 @@ static int process_next_batch(nec_context_t *ctx, deck_t *deck, int *batch_start
696700
ctx->zload.load_r[idx] = f1;
697701
ctx->zload.load_l[idx] = f2;
698702
ctx->zload.load_c[idx] = f3;
703+
/* For LD type 6: f4 optionally overrides the design frequency (MHz).
704+
* 0 means "use the first FR card's frequency" (resolved at compute time). */
705+
ctx->zload.load_freq[idx] = (i1 == 6) ? f4 : 0.0;
699706
}
700707
else if (strcmp(code, "GN") == 0) {
701708
// GN card - Ground parameters

src/deck_validations.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ void test_deck_structure(const nec_context_t *ctx, const deck_t *deck, errors_li
561561
int tag = deck->cards[i].i[2];
562562
int seg1 = deck->cards[i].i[3];
563563
int seg2 = deck->cards[i].i[4];
564-
if (type < -1)
564+
if (type < -1 || (type > 6 && type != -1))
565565
{
566566
snprintf(msg, sizeof(msg), "LD on line %d: unexpected type I1=%d.", i, type);
567567
add_error(ctx, errors, msg, 0);
@@ -588,6 +588,15 @@ void test_deck_structure(const nec_context_t *ctx, const deck_t *deck, errors_li
588588
snprintf(msg, sizeof(msg), "LD on line %d: load values F1..F3 are all zero.", i);
589589
add_error(ctx, errors, msg, 0);
590590
}
591+
// LD type 6 (LC-trap): L and C are required
592+
if (deck->cards[i].ints_used >= 1 && deck->cards[i].i[1] == 6)
593+
{
594+
if (deck->cards[i].flts_used < 3 || deck->cards[i].f[2] == 0.0 || deck->cards[i].f[3] == 0.0)
595+
{
596+
snprintf(msg, sizeof(msg), "LD on line %d (LC-trap): F2 (L) and F3 (C) must be non-zero.", i);
597+
add_error(ctx, errors, msg, 0);
598+
}
599+
}
591600
}
592601
// record for open-end placement validation later (only for LD cards)
593602
if (strcmp(code, "LD") == 0 && deck->cards[i].ints_used >= 3)

src/internals.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,8 @@ typedef struct
412412
screen_wire_len, /* scrwlt — Fortran SCRWLT: screen radial wire length (m) */
413413
screen_wire_radius, /* scrwrt — Fortran SCRWRT: screen radial wire radius (m) */
414414
freq_mhz, /* fmhz — Fortran FMHZ: current frequency (MHz) */
415-
freq_step; /* delfrq: frequency step size */
415+
freq_step, /* delfrq: frequency step size */
416+
first_fr_mhz; /* frequency from the first FR card; used as LD6 design-freq default */
416417

417418
} run_params_t;
418419

@@ -588,9 +589,10 @@ typedef struct
588589
*ldcard_num; /* Deck line number of the originating LD card */
589590

590591
double
591-
*load_r, /* zlr — Fortran ZLR: R value (Ω, H, or F depending on type) */
592-
*load_l, /* zli — Fortran ZLI: L value */
593-
*load_c; /* zlc — Fortran ZLC: C value */
592+
*load_r, /* zlr — Fortran ZLR: R value (Ω, H, or F depending on type) */
593+
*load_l, /* zli — Fortran ZLI: L value */
594+
*load_c, /* zlc — Fortran ZLC: C value */
595+
*load_freq; /* LD type-6 design frequency (MHz); 0 = use first FR card */
594596

595597
complex double *seg_impedance; /* zarray — Fortran ZARRAY: per-segment normalized impedance */
596598
} impedance_loading_t;

test/ld6_trap_test.deck

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CM LC-trap loading test (LD type 6)
2+
CM Based on example from 4nec2 manual: LD 6 2 1 16 16 5.5e-6 45e-12
3+
CM A simple dipole with an LC-trap on tag 2.
4+
CE
5+
GW 1 10 0 0 0 0.1 0 0 0.001
6+
GW 2 16 0.1 0 0 0.2 0 0 0.001
7+
GE 0
8+
FR 0 1 0 0 300
9+
LD 6 2 1 16 16 5.5e-6 45e-12
10+
EX 0 1 5 0 1 0
11+
RP 0 1 1 1000 90 0 0 0
12+
EN

0 commit comments

Comments
 (0)