Zoals aangehaald kan de D-block voor verschillende Anvil code stukken gebruikt worden, die al dan niet op een bepaald tijdstip worden uitgevoerd.
De D-block wordt binnen SimNEC lost van de rest geëvaluaeerd en wordt daarom best visueel voor de Load geplaatst. om aan te geven dat het geen onderdel vormt van de evaluatie van een model.
In het D-block kan men allerhande code samen brengen.:
Functies, die vanuit andere blokken kunnen aangeroepen worden
Dictionaries die worden samengesteld uit waardes die vanuit andere blokken verkregen zijn
Waarde aanpassingen die hiermee de settings van andere blokken bepalen enz.
Optimalisatie zoals Nelder Mead code zie Optimalisatie Nelder Mead
Interactie met de NEC2 engine voor het bepalen van draden of ophalen van berekende waardes
Interactie met de plot area
....
Hierdoor vormt het D-blok de meest uitgebreide interface voor het automatiseren van je antenne model.
Bij SimNEC worden heel wat bruikbare D-bloks als voorbeeld bij geleverd (SCCE filename extentie), die ook als bibliotheek kunnen gebruikt worden.
In de code ervan kan je lezen hoe ze gebruikt dienen te worden, eventueel aangevuld met hulp in het menu: help/Less Used Manuals voor specifieke delen (Animated gif etc)
Om een bewaarde D-blok te kunnen gebruiken, drag&drop je hem in een circuit vanuit de folder:
Vb: selecteer de folder c:/Users/<name>/.SimNEC/3/2/Examples/UsefulDaemonBlocks/AnimationDriver.scce en drop hem links bovenaan als eerste blok in je circuit.
Om een eigen geschreven blok te bewaren voor later gebruik, kopier je deze in je circuit en met drag&drop neem je de kopie en verplaats je hem naar een folder naar keuze.
Wil je alle Example D-blokken als bibliotheek toevoegen, dan doe je dit door in Library de optie add te kiezen en de folder met blokken te selecteren.
Blokken voor jezelf, die je niet als library wil maken, kan je vanuit de D-blok editor bewaren en laden.
Dit is echter een standaard TXT formaat en nadien niet te gebruiken als bibliotheek.
Wanneer de antenne getekend is in een RUSE blok kan je de lengte van de draden bepalen aan de hand van de locatie posities.
Dit geeft je de mogelijkheid om support systemen niet mee te laten tellen.
Volgende voorbeeld is van de Fieldday antenne, waarbij een lus wordt gevormd rond verschillende posities.
Het begin en eindpunt zijn identiek
dcl lengthwire(){
//Length between 2 points:$Length= $Length +((p2x-p1x)**2+(p2y-p1y)**2+(p2z-p1z)**2)**0.5;
$listpoints={A.pnt16,A.pnt15,A.pnt13,A.pnt128,A.pnt14, A.pnt132, A.pnt131, A.pnt127, A.pnt129, A.pnt134, A.pnt133, A.pnt130, A.pnt16};
$Length=0;
$p1=$listpoints[0];
for($L=1;$L<SizeOf($listpoints);++$L){
$p2=$listpoints[$L];
$Length += +(($p2[0]-$p1[0])**2+($p2[1]-$p1[1])**2+($p2[2]-$p1[2])**2)**0.5;
$p1=$p2;
}
Tot=$Length;
}
Binnen de NECBLOCK worden de dragden gedefinieerd en kan je per draad heel wat parameters opvragen zoals de lengte.
Het volgende voorbeeld telt de lengte van alle draden op en verwijdert nadien de draagmast (A.high) die gebruikt wordt om de single-draad antenne op te hangen.
Op die wijze kan je alle onderdelen, steunen en objecten die invloed kunnen hebben modelleren en nadien verwijderen uit de totale lijst van een "grillige" draadantenne.
Tot = 0;
$wirestable = A._NECBLOCK.wires;
$i=0;
for (dcl $tot:$wirestable) {
Tot += A._NECBLOCK.wires[$i].length;
$i += 1;
//pl $i; pl Tot;
}
Tot -= A.high;
Met deze code kan je aan de hand van de band limieten die ingesteld zijn in de band settings, de berekening van de waardes verdelen over een aantal per band.
De keuze van welke banden worden opgenomen, doe je in het menu View/bands menu, door het aanvinken van de banden.
Het doorgeven aan de sweep om enkel deze waardes te gebruiken, doe je door als sweep een expressie te geven (type expr), die enkel de berekende waardes gebruikt.
PS: Vergeet niet de D blok de naam te geven SweepBands
AddToSweepPath(SweepBands.generate(null),1)
//SweepBands
// usage:
//AddToSweepPath(SweepBands.generate(null),1)
PointsPerBand;
Button generate() {
$points = {};
if (PointsPerBand <= 0)
PointsPerBand = 10;
for (dcl b:GetBandMenu()) {
pl b;
if (! b.en) continue;
for (int i=0;i<=PointsPerBand;++i) {
$f = b.from + (b.to-b.from)/PointsPerBand*i;
Add($points,$f);
}
}
pe $points;
return $points;
}
Met deze functie passen we de sheet aan, zodat we de extra parameters kunnen gebruiken om het ontwerp van de antennen verder te automatiseren.
Uiteindelijk kan je zo in de sheet een aantal vaste waardes plaatsen (vb ankerpunten, hoogte, afstanden etc) die fysiek vast liggen en de variabele waardes (seg160m en seg80m) gebruiken om de rest van de fysieke antenne te berekenen.
Eens deze berekening gedaan is, kan SimNEC de antennen maken (N-blok) en verdere verwerking doen.
De X,Y,Z pos en de Base(horizontale afstand van mast tot anker) Maxl (maximale lengte bovenste draad antenne) zijn waardes ter indicatie.
Voor het berekenen van de afstand tussen twee punten in de ruimte, kan je gebruik maken van de formule waarmee je de som maakt tussen alle punten die verbonden zijn met één draad.
$Length= $Length +((p2x-p1x)**2+(p2y-p1y)**2+(p2z-p1z)**2)**0.5;
Je kan de lengte ook nadien bekomen vanuit het NEC modelen eventueel alle draden doorlopen via een lus om de totale lengte te bepalen.
vb: A._NECBLOCK.wires.pnt11_pnt12.length;
//Calcpositions
//pl SS.W1;
//SS.W1={seg:1 ,E1X:0 ,E1Y:0 ,E1Z:0 ,E2X:0 ,E2Y:0 ,E2Z:0.3 ,RAD:20m}; -> werkt niet
Base;Maxl;Seg160m;Seg80m;L160;L80;
//
//Calc Base line
SS.L160m=Seg160m;
SS.L80=Seg80m;
Base=Sqrt(SS.ANCHORX**2+SS.ANCHORY**2);
$CosPos=SS.ANCHORX/Base;
$SinPos=SS.ANCHORY/Base;
//Calc max length top wire
Maxl=Sqrt(Base**2+SS.TOP**2);
$CosAngel=Base/Maxl;
$SinAngel=SS.TOP/Maxl;
$Ltube=11.5;
//Calculating positions
//W1, W2,W3 -> Tubing up to 11.5m (pt1 -pt3)
SS.W1.Dia=SS.DIA1;
SS.W1.E1X=0;
SS.W1.E1Y=0;
SS.W1.E1Z=0;
SS.W1.E2X=0;
SS.W1.E2Y=0;
SS.W1.E2Z=0.3;
//W2
SS.W2.Dia=SS.DIA1;
SS.W2.E1X=0;
SS.W2.E1Y=0;
SS.W2.E1Z=0.3;
SS.W2.E2X=0;
SS.W2.E2Y=0;
SS.W2.E2Z=6;
//W3
SS.W3.Dia=SS.DIA2;
SS.W3.E1X=0;
SS.W3.E1Y=0;
SS.W3.E1Z=6;
SS.W3.E2X=0;
SS.W3.E2Y=0;
SS.W3.E2Z=11.5;
//Position wire end W4
//W4 slope 40gr L160m (pt3-pt4) +X,+Y
$BasePos=SS.L160m*$CosAngel;
ZPos=SS.TOP - SS.L160m*$SinAngel;
XPos=$BasePos*$CosPos;
YPos=$BasePos*$SinPos;
SS.W4.Dia=SS.DIA3;
SS.W4.E1X=SS.W3.E2X;
SS.W4.E1Y=SS.W3.E2Y;
SS.W4.E1Z=SS.W3.E2Z;
SS.W4.E2X=XPos;
SS.W4.E2Y=YPos;
SS.W4.E2Z=ZPos;
SS.W4.DielC=SS.PR;
SS.W4.Thk=SS.th;
SS.W4.LossTan=SS.LT;
L160= $Ltube + ((SS.W4.E2X-SS.W4.E1X)**2+(SS.W4.E2Y-SS.W4.E1Y)**2+(SS.W4.E2Z-SS.W4.E1Z)**2)**0.5;
//Position wire end W5
//W5 slope (pt4-pt5) pt5-outside tubing 20cm +X,-Y
SS.W5.Dia=SS.DIA3;
SS.W5.E1X=SS.W4.E2X;
SS.W5.E1Y=SS.W4.E2Y;
SS.W5.E1Z=SS.W4.E2Z;
SS.W5.E2X=SS.SPTUB2*$CosPos;
SS.W5.E2Y=-SS.SPTUB2*$SinPos;
SS.W5.E2Z=SS.MID;
SS.W5.DielC=SS.PR;
SS.W5.Thk=SS.th;
SS.W5.LossTan=SS.LT;
L160 +=((SS.W5.E2X-SS.W5.E1X)**2+(SS.W5.E2Y-SS.W5.E1Y)**2+(SS.W5.E2Z-SS.W5.E1Z)**2)**0.5;
//Position wire end W6
//W6 slope(pt5-pt6) pt6=opposite pt4 -X,-Y
SS.W6.Dia=SS.DIA3;
SS.W6.E1X=SS.W5.E2X;
SS.W6.E1Y=SS.W5.E2Y;
SS.W6.E1Z=SS.W5.E2Z;
SS.W6.E2X=-XPos;
SS.W6.E2Y=-YPos;
SS.W6.E2Z=ZPos;
SS.W6.DielC=SS.PR;
SS.W6.Thk=SS.th;
SS.W6.LossTan=SS.LT;
L160 +=((SS.W6.E2X-SS.W6.E1X)**2+(SS.W6.E2Y-SS.W6.E1Y)**2+(SS.W6.E2Z-SS.W6.E1Z)**2)**0.5;
//Position wire end W7
//W7slope (pt6-pt7) pt7 = outside tubing 10cm -X,-Y
SS.W7.Dia=SS.DIA3;
SS.W7.E1X=SS.W6.E2X;
SS.W7.E1Y=SS.W6.E2Y;
SS.W7.E1Z=SS.W6.E2Z;
SS.W7.E2X=-SS.SPTUB1*$CosPos;
SS.W7.E2Y=-SS.SPTUB1*$SinPos;
SS.W7.E2Z=SS.TOP;
SS.W7.DielC=SS.PR;
SS.W7.Thk=SS.th;
SS.W7.LossTan=SS.LT;
L160 +=((SS.W7.E2X-SS.W7.E1X)**2+(SS.W7.E2Y-SS.W7.E1Y)**2+(SS.W7.E2Z-SS.W7.E1Z)**2)**0.5;
//Position wire end W8
//W8 drop (pt7-pt8) pt8 = outside tubing 10cm on ground -X,-Y
SS.W8.Dia=SS.DIA3;
SS.W8.E1X=SS.W7.E2X;
SS.W8.E1Y=SS.W7.E2Y;
SS.W8.E1Z=SS.W7.E2Z;
SS.W8.E2X=-SS.SPTUB1*$CosPos;
SS.W8.E2Y=-SS.SPTUB1*$SinPos;
SS.W8.E2Z=0;
SS.W8.DielC=SS.PR;
SS.W8.Thk=SS.th;
SS.W8.LossTan=SS.LT;
L160 +=((SS.W8.E2X-SS.W8.E1X)**2+(SS.W8.E2Y-SS.W8.E1Y)**2+(SS.W8.E2Z-SS.W8.E1Z)**2)**0.5;
//Position wire end W9
//W9 slope 40gr L80m (pt3-pt9) +X,-Y
$BasePos2=SS.L80*$CosAngel;
ZPos2=SS.TOP - SS.L80*$SinAngel;
XPos2=$BasePos2*$CosPos;
YPos2=$BasePos2*$SinPos;
SS.W9.Dia=SS.DIA3;
SS.W9.E1X=SS.W3.E2X;
SS.W9.E1Y=SS.W3.E2Y;
SS.W9.E1Z=SS.W3.E2Z;
SS.W9.E2X=XPos2;
SS.W9.E2Y=-YPos2;
SS.W9.E2Z=ZPos2;
SS.W9.DielC=SS.PR;
SS.W9.Thk=SS.th;
SS.W9.LossTan=SS.LT;
L80 = $Ltube + ((SS.W9.E2X-SS.W9.E1X)**2+(SS.W9.E2Y-SS.W9.E1Y)**2+(SS.W9.E2Z-SS.W9.E1Z)**2)**0.5;
//Position wire end W10
//W10 slope (pt9-pt10) pt10=outside tubing 20cm +X,+Y
SS.W10.Dia=SS.DIA3;
SS.W10.E1X=SS.W9.E2X;
SS.W10.E1Y=SS.W9.E2Y;
SS.W10.E1Z=SS.W9.E2Z;
SS.W10.E2X=SS.SPTUB2*$CosPos;
SS.W10.E2Y=SS.SPTUB2*$SinPos;
SS.W10.E2Z=SS.MID+0.2;
SS.W10.DielC=SS.PR;
SS.W10.Thk=SS.th;
SS.W10.LossTan=SS.LT;
L80 +=((SS.W10.E2X-SS.W10.E1X)**2+(SS.W10.E2Y-SS.W10.E1Y)**2+(SS.W10.E2Z-SS.W10.E1Z)**2)**0.5;
//Position wire end W11
//W11 slope (pt10-pt11) pt11= opposite pt9 -X,+Y
SS.W11.Dia=SS.DIA3;
SS.W11.E1X=SS.W10.E2X;
SS.W11.E1Y=SS.W10.E2Y;
SS.W11.E1Z=SS.W10.E2Z;
SS.W11.E2X=-XPos2;
SS.W11.E2Y=YPos2;
SS.W11.E2Z=ZPos2;
SS.W11.DielC=SS.PR;
SS.W11.Thk=SS.th;
SS.W11.LossTan=SS.LT;
L80 +=((SS.W11.E2X-SS.W11.E1X)**2+(SS.W11.E2Y-SS.W11.E1Y)**2+(SS.W11.E2Z-SS.W11.E1Z)**2)**0.5;
//Position wire end W12
//W12 slope (pt11-pt12) pt12=outside tubing 10cm -X,+Y
SS.W12.Dia=SS.DIA3;
SS.W12.E1X=SS.W11.E2X;
SS.W12.E1Y=SS.W11.E2Y;
SS.W12.E1Z=SS.W11.E2Z;
SS.W12.E2X=-SS.SPTUB1*$CosPos;
SS.W12.E2Y=SS.SPTUB1*$SinPos;
SS.W12.E2Z=SS.TOP;
SS.W12.DielC=SS.PR;
SS.W12.Thk=SS.th;
SS.W12.LossTan=SS.LT;
L80 +=((SS.W12.E2X-SS.W12.E1X)**2+(SS.W12.E2Y-SS.W12.E1Y)**2+(SS.W12.E2Z-SS.W12.E1Z)**2)**0.5;
//Position wire end W13
//W13 slope (pt12-pt13) pt13 =outside tubing 10cm on ground -X,+Y
SS.W13.Dia=SS.DIA3;
SS.W13.E1X=SS.W12.E2X;
SS.W13.E1Y=SS.W12.E2Y;
SS.W13.E1Z=SS.W12.E2Z;
SS.W13.E2X=-SS.SPTUB1*$CosPos;
SS.W13.E2Y=SS.SPTUB1*$SinPos;
SS.W13.E2Z=0;
SS.W13.DielC=SS.PR;
SS.W13.Thk=SS.th;
SS.W13.LossTan=SS.LT;
L80 +=((SS.W13.E2X-SS.W13.E1X)**2+(SS.W13.E2Y-SS.W13.E1Y)**2+(SS.W13.E2Z-SS.W13.E1Z)**2)**0.5;
//length_wire160m=tubing + W4->W8
//length_wire 80m= tubing + W9->W13
Deze code laat je toe om de correlatie tussen een meeting en een model automatisch uit te voeren, door gebruik te maken van de Smith Chart en de aanpassing van het model aan de meting. Zie Draad kwalificatie meting
Het model wordt vooraf gegaan door een delay line en de bepaling van de seep zorgt voor een keuze tussen de uitersten waarop de correlatie dient te gebeuren.
In de code voorzien we knoppen voor het instellen van standaard waardes in het antenne model, alsook voor het uitvoeren van de NM code.
Delen van de code worden op specifieke tijdstippen uitgevoerd (at) om ervoor te zorgen dat de evaluatie van het model correct verloopt.
Tevens vinden we code terug om markers te generen op de Smith Chart, zodat de meetpunten goed zichtbaar zijn.
Het opsplitsen van de NM code in 3 sequentiële stappen geeft een efficiëntiewinst en zorgt ervoor dat de uiteindelijk totale evaluatie (nm4) niet een foutief minimum kiest.
Dit kan belangrijk zijn indien een functie als resultaat meerdere minima geeft.
//markers
//executed every evaluation
X0; //dialog visible variable, number of resonance freq points
X_hyst; //hysteresis value detection x=0
$x=L.Z.X.M; //internal variable
//look for X=0 points
Button initAnt(){
A.LT=0.2;
A.dia=1m;
A.Mat=56M;
A.thick=100u;
A.Pr=4;
DELAY.ft=0;
};
//execution on the start of the sweep
at(startOfSweep,endOfEval){
$lastx =$x;
$i=0;
$result=100;
$arr={};
}
//execution every sweep point
at (inSweep,endOfEval) {
//if x is within 1 ohm
$lastx = $x; //get new value from evaluation of the model
if((($lastx > -X_hyst) && ($lastx <X_hyst))||(G.MHz~=1)||(G.MHz~=2)||(G.MHz~=4)||(G.MHz~=8)||(G.MHz~=16))
{
Add($arr,{G.MHz,L.Z,DELAY.Z});
$result= $result + (L.Z.G-DELAY.Z.G);
++$i;
}
}
//execution at the end of the sweep
at (endOfSweep,endOfEval) {
markerset($arr);
}
//execute before drawing charts
at(finalValue){
X0=SizeOf($arr); //display number of X=0 found
}
SelectOneOf {idle,auto} optimization;
// turn it off after any edit.
once optimization = "idle";//execute only once
//Execute when button is pressed
Button single() {
$nm1=NelderMead(POSITIVES,TOLERANCE=1u,COUNT=500,A.thick=InRange(0,2m),A.Pr=InRange(0,10),A.dia=InRange(1m,2m)) func();
if ($nm1.result=="ReachedGoal"){
$nm2=NelderMead(POSITIVES,TOLERANCE=1u,COUNT=500,A.LT=InRange(0,1)) func();
if ($nm2.result=="ReachedGoal"){
$nm3=NelderMead(POSITIVES,TOLERANCE=1u,COUNT=500,A.Mat=InRange(1M,65M)) func();
if($nm3.result=="ReachedGoal"){
//final optimization
$nm4=NelderMead(TOLERANCE=1u,COUNT=500,A.LT=InRange(0,1),A.Mat=InRange(1M,65M),A.thick=InRange(0,2m),A.Pr=InRange(0,10),DELAY.ft=InRange(-100m,100m)) func();
}
}
}
pl $nm1;
pl $nm2;
pl $nm3;
pl $nm4;
}
//execute at the very last point in evaluation epilog
if (optimization == "auto") {
at(epilog){ single(null);}
}
//function search for minima NM code
dcl func() {
$sum =0;
Beep();
for($c=0;$c<SizeOf($arr);++$c){
InCircuitWith(G.MHz=$arr[$c][0]){
//$sum += Mag(L.Z.G-DELAY.Z.G)*(X0/($c+1));
$sum += Mag(L.Z.G-DELAY.Z.G);
}
}
return $sum;
}
//marker on chart using frequency which is the first element in list array
dcl markerset($list){
for ($m=0;$m<SizeOf($list);++$m){
AddMarker(L.Z,"aHook",G.MHz=$list[$m][0]);
AddMarker(DELAY.Z,"aHook",G.MHz=$list[$m][0]);
}
}
Het is mogelijk om de draden in de _NECBLOCK.wires te gebruiken, maar dit verhindert niet dat je draden, structuren en alle zaken die je mee opnmeent in het NEC2 model ook hierin kan terug vinden en mee wordt genomen in je som.
Een andere mogelijkheid is om je RUSE model als bron te gebruiken om de lengte van een draadantenne te bepalen.
Je geeft de volgorde van punten op waarlangs de draad gevoerd wordt om zo de totale som te bepalen.
In ons voorbeeld loopt de draad van pnt16 naar pnt14, door eerst naar pnt15 te gaan en dan naar pnt13. De draad(structuur) pnt11_pnt12 is een mast en dient niet mee gerekend te worden.
Je plaatst de punten in de $listpoints array, in de volgorde {start, .....,end}
In Tot zal je de som van de afstanden vinden.
dcl lengthwire(){
//Length between 2 points:$Length= $Length +((p2x-p1x)**2+(p2y-p1y)**2+(p2z-p1z)**2)**0.5;
$listpoints={A.pnt16,A.pnt15,A.pnt13,A.pnt14};
$Length=0;
$p1=$listpoints[0];
for($L=1;$L<SizeOf($listpoints);++$L){
$p2=$listpoints[$L];
$Length += +(($p2[0]-$p1[0])**2+($p2[1]-$p1[1])**2+($p2[2]-$p1[2])**2)**0.5;
$p1 = $p2;
}
Tot=$Length;
}