Indice |
Introduzione
Nel primo articolo [I] è stata illustrata la modellazione di semplici forme geometriche e la creazione di una macro "da history list", d'ora in poi chiamata semplicemente macro. Questo secondo articolo vuole spiegare i ragionamenti dietro alla creazione di una macro più complessa: un dipolo rototraslabile a piacere. La macro verrà poi adattata ad un semplice progetto, un dipolo λ/2 per i 100 MHz. Il libro al quale si farà riferimento per il progetto è il Balanis, [II].
Scrittura della macro
La macro sarà composta di più comandi eseguiti in sequenza. Vi saranno quattro sezioni: la prima fungerà da interfaccia per l'utente che vuole creare il dipolo, la seconda formerà geometria, la terza traslerà e ruoterà il tutto e la quarta "pulirà l'ambiente" eliminando le variabili.
Metodo e definizione della geometria
In prima approssimazione un dipolo realizzato con fili a sezione circolare è fatto così:
Possiamo creare due cilindri oppure crearne uno solo e tagliarlo nel mezzo. Adottiamo la seconda tecnica.
Costrutti usati nella macro
Per imparare si fa prima ad analizzare direttamente il codice della macro, ma questa sezione potrebbe essere utile per chiarire alcuni dubbi.
Definire una variabile in VBA
Dim nome_scelto As tipo_variabile
Usiamo il tipo Double per i numeri reali, String per i testi.
Esempio, definire la lunghezza del dipolo:
Dim length As double length = 12
Esempio, definire il nome di un solido:
Dim nome_dipolo As String nome_dipolo = "dipolo1"
La pulizia delle variabili in VBA ed i sospetti sul garbage collector
Poniamo che si voglia richiamare più volte una macro, in successione. Avendo definito delle variabili nella macro, magari usandole per fare dei calcoli, la seconda volta che richiameremo la macro CST darà errore. Protesterà dicendoci che quelle variabili esistono già, e che non possiamo crearle di nuovo.
Questo non accade sempre, dipende da come scriviamo la definizione delle variabili: se le definiamo una per una, separatamente, interverrà un meccanismo di pulizia automatica detto "garbage collector", che appena si accorgerà che una variabile non è più in uso la eliminerà, permettendo così di ridefinirla in seguito. Ciò fa in modo che si possa richiamare in seguito una macro uguale, con le stesse variabili.
Questo concetto è molto più facile da capire con un paio di esperimenti.
DISCLAIMER: chi scrive non è sicuro che si chiami "garbage collector". Pare che in VBA, il linguaggio di Excel, tale entità esista, assolvendo funzioni simili al garbage collector di Java. Tuttavia il sottoscritto non è un programmatore VBA e non è chiaro quanta parte del linguaggio sia stata portata su CST e lasciata immutata.
ATTENZIONE: il garbage collector pulisce solo e soltanto la variabile che precede As nome_tipo.
Definendo più variabili in una sola riga il garbage collector pulirà solo l'ultima. Ad esempio:
Dim length, diameter, gap As Double
Al termine dell'esecuzione della macro il garbage collector pulirà solo gap, che potrà essere re-istanziato in un'altra macro con il comando Dim gap As Double.
Tutte le variabili non pulite dal garbage collector andranno eliminate manualmente col comando:
Set nome_variabile = Nothing
Quindi al termine della macro inseriremo una sequenza di questi comandi per pulire tutte le variabili di cui non si è già occupato il garbage collector.
ATTENZIONE: Non è possibile eliminare una variabile già eliminata dal garbage collector.
Esempio sulla gestione della pulizia:
- Creiamo più variabili con un'unica riga di codice, per comodità:
Dim angleX, angleY, angleZ As Double
- Appena il garbage collector si accorgerà che nessuno usa o modifica angleZ lo eliminerà. Il garbage collector si occuperà solo di angleZ perchè è la variabile accanto ad As Double; le altre due variabili dovremo pulirne noi manualente, coi comandi
Set angleX = Nothing Set angleY = Nothing
- Per comodità e per evitare errori conviene farlo al termine della macro.
Concatenare delle stringhe
I nomi dei layer e dei solidi sono delle stringhe. Per unirle tra loro si usa il comando +, ad esempio:
"Oggi è una" + " bella giornata" risulterà come "Oggi è una bella giornata".
Esempio, definire tre stringhe, concatenare le prime due nella terza:
Dim primo_verso, secondo_verso, poesia As String primo_verso = "Chi vuol esser lieto sia" secondo_verso = " non si iscriva a ingegneria" poesia = primo_verso + secondo_verso
I layer
I layer sono dei gruppi in cui vengono riuniti i solidi. Consideriamo il vuoto un gruppo e quindi un layer, così come il PEC (Perfect Electric Conductor) con cui formeremo il dipolo. I layer non equivalgono esattamente ai materiali; è possibile agire con i Materials, ad esempio caricando dalla libreria di CST il rame (Copper) puro. In questo articolo lavoreremo soltanto con i layer.
Attenzione alle operazioni di traslazione e rotazione: come verrà specificato in seguito, posso far riferimento sia a tutti i solidi di un layer sia ad un solido in particolare.
Esempio, layer "Copper":
Scrivendo "Copper" il programma agirà su tutti i solidi del layer.
Scrivendo invece "Copper:nome_solido_facente_parte_di_Copper" il programma agirà su tale solido. Concateneremo delle stringhe per poter definire a parte i nomi dei solidi.
L'operazione di taglio
Solid.Subtract "nome_layer_solido1:nome_solido1", "nome_layer_solido2:nome_solido2"
Questa operazione prende solido2, guarda quale parte di esso interseca solido1 e taglia da solido1 tale intersezione.
ATTENZIONE: dopo l'operazione di taglio solido2 verrà eliminato.
Le operazioni di traslazione e rotazione
Entrambe utilizzano la classe Transform, quindi iniziano con With Transform e terminano con End with.
Per la traslazione si modifica il metodo .Vector, per la rotazione .Angle.
Per evitare di ruotare tutti i solidi del layer verrà specificato il nome del solido da ruotare, unendo delle stringhe. Ad esempio volendo ruotare il dipolo "dipolo_1" appartenende al layer "Copper" scriveremo "Copper:dipolo_1".
Disclaimer: non sono sicuro che i programmatori VBA li chiamino metodi, in C++ si chiamano membri, in Java metodi, ma il concetto è quello.
Il codice della macro
Questo è il codice completo, incollabile in un comando qualsiasi della history list. In alternativa lo si può inserire in una macro vera e propria, all'interno del main.
Attenzione alla parte di pulizia delle variabili al fondo: solo alcune verranno pulite manualmente, poiché il garbage collector si occuperà autonomamente delle altre. Tentanto di pulirle tutte si otterrebbero degli errori.
Notare come tutte le operazioni (taglio, rotazione, traslazione) siano state legate specificamente al nome del dipolo definito nell'interfaccia utente.
Si è scelto di utilizzare direttamente dei layer, senza usare dei Material. Il dipolo è stato creato come PEC, Perfect Electric Conductor.
Dim length, diameter, gap As Double Dim translationX, translationY, translationZ As Double Dim angleX, angleY, angleZ As Double Dim dipole_name As String '---------------------------------------------------------- 'USER INTERFACE dipole_name = "dipole_1" length = 12 diameter = 0.2 gap = 0.12 'ROTATION: angleX = 90 angleY = 90 angleZ = 0 'TRANSLATION: translationX = 0 translationY = 0 translationZ = 0 'END OF THE USER INTERFACE '---------------------------------------------------------- 'PEC LAYER CREATION With Layer .Reset .Name "Copper" .FrqType "hf" .Type "Pec" .Epsilon "1.0" .Mue "1.0" .Rho "0.0" .Colour "0", "1", "1" .Wireframe "False" .Transparency "0" .Create End With 'VACUUM LAYER CREATION With Layer .Reset .Name "Vacuum" .FrqType "hf" .Type "Normal" .Epsilon "1.0" .Mue "1.0" .Kappa "0.0" .TanD "0.0" .TanDFreq "10" .TanDGiven "True" .TanDModel "ConstTanD" .KappaM "0.0" .KappaM "0.0" .TanDM "0.0" .TanDMFreq "0.0" .TanDMGiven "False" .DispModelEps "None" .DispModelMue "None" .Rho "0.0" .Colour "1", "1", "1" .Wireframe "False" .Transparency "30" .Create End With 'CREATION OF THE STRUCTURE WITHOUT THE GAP With Cylinder .Reset .Name dipole_name .Component "Copper" .Material "Copper" .OuterRadius diameter/2 .InnerRadius "0" .Axis "z" .Zrange -length/2, length/2 .Xcenter 0 .Ycenter 0 .Segments "0" .Create End With 'CREATION OF A VACUUM CYLINDER TO CUT THE GAP With Cylinder .Reset .Name dipole_name+"_gap" .Component "Vacuum" .Material "Vacuum" .OuterRadius diameter/2 .InnerRadius "0" .Axis "z" .Zrange -gap/2, gap/2 .Xcenter 0 .Ycenter 0 .Segments "0" .Create End With 'CUT OF THE GAP Solid.Subtract "Copper:"+dipole_name, "Vacuum:"+dipole_name+"_gap" 'ROTATION ALONG X With Transform .Reset .Name "Copper:"+dipole_name .Origin "Free" .Center "0", "0", "0" .Angle angleX, "0", "0" .MultipleObjects "False" .GroupObjects "False" .Repetitions "1" .MultipleSelection "False" .Transform "Shape", "Rotate" End With 'ROTATION ALONG Y With Transform .Reset .Name "Copper:"+dipole_name .Origin "Free" .Center "0", "0", "0" .Angle "0", angleY, "0" .MultipleObjects "False" .GroupObjects "False" .Repetitions "1" .MultipleSelection "False" .Transform "Shape", "Rotate" End With 'ROTATION ALONG Z With Transform .Reset .Name "Copper:"+dipole_name .Origin "Free" .Center "0", "0", "0" .Angle "0", "0", angleZ .MultipleObjects "False" .GroupObjects "False" .Repetitions "1" .MultipleSelection "False" .Transform "Shape", "Rotate" End With 'TRANSLATION ALONG X With Transform .Reset .Name "Copper:"+dipole_name .Vector translationX, "0", "0" .UsePickedPoints "False" .InvertPickedPoints "False" .MultipleObjects "False" .GroupObjects "False" .Repetitions "1" .MultipleSelection "False" .Transform "Shape", "Translate" End With 'TRANSLATION ALONG Y With Transform .Reset .Name "Copper:"+dipole_name .Vector "0", translationY, "0" .UsePickedPoints "False" .InvertPickedPoints "False" .MultipleObjects "False" .GroupObjects "False" .Repetitions "1" .MultipleSelection "False" .Transform "Shape", "Translate" End With 'TRANSLATION ALONG Z With Transform .Reset .Name "Copper:"+dipole_name .Vector "0", "0", translationZ .UsePickedPoints "False" .InvertPickedPoints "False" .MultipleObjects "False" .GroupObjects "False" .Repetitions "1" .MultipleSelection "False" .Transform "Shape", "Translate" End With 'VARIABLE DESTRUCTION Set length = Nothing Set diameter = Nothing Set translationX = Nothing Set translationY = Nothing Set angleX = Nothing Set angleY = Nothing
Adattare la macro ad un semplice progetto
Si desidera simulare il comportamento un dipolo λ/2 (half-wavelength dipole) per la frequenza di 100 MHz, usando come riferimento [II]. La lunghezza d'onda è indicata con λ, la frequenza con f, la velocità della luce nel vuoto con c.
Progetto
In prima approssimazione:
Il libro [II] afferma che per un dipolo lungo λ/2 l'impedenza ai terminali di ingresso è di (73 +j42.5) Ω. Volendo collegare il dipolo a qualcosa con 73 Ω di impedenza conviene cercare di azzerare la parte immaginaria: per farlo il professor Balanis consiglia di ridurre la lunghezza del dipolo, tra 0.47 λ e 0.48 λ, mantenendo al contempo il filo molto sottile: più il filo è sottile più la lunghezza si avvicina a 0.48 λ.
Impostare le unità di misura corrette su CST
Nel menù Home impostiamo col menù Units le unità di misura corrette:
Tutti i i numeri inseriti nella macro assumeranno le unità di misura impostate dall'utente in questo modo.
Notare come impostando le misure sia apparso un nuovo comando in history list; si potrebbe implementare all'interno delle macro, è un pezzo di codice come gli altri.
Adattare la macro inserendovi all'interno i dati
Nell'interfaccia utente inseriamo i dati del progetto, specificando un nome appropriato per il dipolo:
dipole_name = "dipolo_100MHz" length = 1.425 diameter = 0.02 gap = 0.01
e lasciamo a 0 i vari angle e translation.
Poi creiamo una forma geometrica inutile, come un cubo, apriamo il corrispettivo comando in history list, cancelliamo tutto e incolliamo la nostra macro. Dando OK e cliccando Update dovremmo ottenere un risultato del genere:
Risultato finale. Nell'immagine è mostrato l'Edit del comando numero 3, che è stato sostituito con la macro. Il palallepepipedo dagli spigoli neri disegnato attorno al dipolo ci segnala che il background attorno ad esso è molto stretto. Se ne parlerà nella terza parte.
Adattare la macro tramite i parametri della parameter list
La parameter list è un menù nel quale l'utente può definire dei parametri. È utile perché permette di impostare facilmente delle simulazioni parametriche, in cui il CST simula più volte variando dei parametri; si può utilizzare la parameter list con l'Optimizer, un potentissimo strumento che va a variare i parametri di una geometria mirando ad obiettivo imposto dall'utente.
Una volta definiti i parametri nella parameter list:
È possibile passarli direttamente alla macro, scrivendo i nomi dei parametri al posto dei valori numerici:
dipole_name = "dipolo_100MHz" length = lunghezza_100MHz diameter = diametro_100MHz gap = gap_100MHz
Bibliografia
[I] Fedhman, Dipolo con CST - I, Electroyou marzo 2016.
[II] Constantine A. Balanis, 2005, Antenna Theory, 3 ed., U.K., John Wiley & Sons