Ecco le funzioni di questa libreria:Da leggere:
ada(la,per)
cambiacoord(tn,InFunDiN,NuoveC,metrica)
cambiasesso(lista,litipi,gff,gmm)
cambiatipi(tn,nuovitipi,metrica)
commentalo(tn,comme)
commento(tn)
diffcov(tn,metrica,nome)
dimensione(tn)
divergenza(tn,ki,metrica)
fa_ch122(g22,listavariabili)
fa_ch222(g220)
fa_diff(tn,variabili,comme)
fa_metrica(mg,listavariabili)
fa_r1222(t22,listavariabili)
fa_r22(t22,listavariabili)
fa_r2222(t22,listavariabili)
fa_tenergiaimpulso(tpotvet,metrica)
fondetatb(ta,tb,nome)
indici(tn)
listadatensore(tn)
knbl22a(info)
knbl22b(info)
nonmetricap(metrica)
ordine(tn)
permuta(tn,per,com)
rapportolistetensori(ta,tb)
ricci_22(t22,variabili)
riemann_1222(t22,variabili)
riemann_2222(t22,variabili)
scala(ta,ia,tb,ib)
semplimetrica(metrica)
semplimetricatrig(metrica)
tassegna(tn,val,p)
tcontrov(lv,metrica)
tcov(lv,metrica)
tdueantisim(tn,metrica)
tduetracciazero(tn,metrica)
tensoredalista(lista,tipi,comme,ndim)
tensorp(tn)
ticambiotutto(tn,metrica)
tmat11(mat,metrica)
tmat12(mat,metrica)
tmat21(mat,metrica)
tmat22(mat,metrica)
tmeno(tena,tenb)
tnsemplifica(tn)
tnsemplificatrig(tn)
tprod(tscala,tenb)
traccia(tn,ih,ik)
tsca(sc,metrica)
tsomma(tena,tenb)
tvale(tn,p)
zerotensor(tipi,comme,ndim)
Versione aggiornata della mia antica libreria tensoriale del 2010
Qualche antico caso prova... camuffato da file
.html
.
- 2014crealibtensori-2010v1.wxm.html
- 2014uso-libtensori-2010v0.wxm.html
- 2014uso-libtensori-2010v2.wxm.html
Convenzioni usate in questa vecchia e nuova libreria
Un tensore è una lista di oggetti vari (atomici, liste o matrici) lunga almeno 2 ma solitamente 3 se il tensore ha rango pari e di più se ha rango dispari.
L'ultimo elemento della lista DEVE OBBLIGATORIAMENTE essere una lista ossia la lista informativa della natura del tensore.
La lunghezza della lista, che ha scopi informativi, dell'ultimo elemento, diminuita di 2, è il rango del tensore ( un tensore di rango 0 è uno scalare ossia, in pratica non sarebbe un tensore, un tensore di rango 1 è detto vettore, un tensore di rango 2 è detto matrice ).
Il penultimo elemento della lista dell'ultimo elemento è un commento di qualsiasi tipo, un numero o una stringa o una lista etc. In questo modo posso commentare le proprietà del tensore, attribuirgli un nome per identificarlo etc...
L'ultimo elemento della lista dell'ultimo elemento è la dimensione dello spazio per il tensore considerato che deve valere almeno 2 ossia sono ammessi tensori in spazi almeno bidimensionali ossia il tempo e lo spazio.
I precedenti elementi indicano la natura degli indici del tensore( uso una antica convenzione che poi ho modificato ) . La distinzione base è tra indici covarianti indicati da cifre pari ed indici controvarianti da cifre dispari...
- (0) se sono ottenuti con la derivazione preliminare ordinaria e dunque in pratica NON sono veri tensori
- (1) se sono controvarianti
- (2) se sono covarianti
- (3,4,5,6,7 ) indici personalizzabili ossia covarianti se pari o controvarianti se dispari ma ottenuti in qualche modo speciale...
- (8) se sono indici ottenuti con derivata qualificata covariante e dunque sono covarianti
- (9) se sono controvarianti ottenuti trasformando in controvariante un indice ottenuto con derivata qualificata covariante.
I tensori di rango dispari sono memorizzati in una lista lunga almeno quanto la dimensione dello spazio + 1 dato che l'ultimo elemento deve contenere la lista informativa. I tensori di rango 1 ossia i vettori hanno elementi, tranne l'ultimo, che contengono i valori delle corrispondenti componenti del vettore. Se invece i tensori sono di rango dispari maggiore di 1, gli elementi sono matrici se di rango 3 o matrici di matrici se di rango 5 etc...
I tensori di rango pari sono memorizzati in una lista di almeno due elementi ossia il primo elemento è una matrice o una matrice di matrice o una matrice di matrice di matrice etc. mentre l'ultimo, ossia almeno il secondo, contiene la lista informativa. Se sono scalari ossia hanno rango zero, il primo elemento nella lista non è una matrice ma il valore dello scalare e la lista informativa, come al solito, è il secondo o comunque l'ultimo elemento.
append(list_1, ... , list_n) e rest(expr,n) sono importanti funzione standard di Maxima per la manipolazione di liste.
La
Per l'altra, il manuale di wxMaxima spiega in inglese come funziona:append
consente di concatenare un numero arbitrario di liste,list_1
, ...,list_n
.Returns
expr
with its firstn
elements removed ifn
is positive and its last−n
elements removed ifn
is negative. Ifn
is 1 it may be omitted.expr
may be a list, matrix, or other expression...Dunque, usando la
rest(expr,n)
si elimina l'ultimo elemento della lista che costituisce il tensore e che ha solo scopo informativo sulla natura degli indici e sulla dimensione dello spazio in cui il tensore è stato definito. Quindi si può trattare quello che resta della lista come un qualsiasi oggetto algebrico di wxMaxima ossia, nelle verifiche, controllare se la differenza tra due tensori è esattamente zero.Funzioni della libreria
Le elenco in ordine alfabetico...Mancanze ed ultime aggiunte ... Fra poco sarà disponibile il calcolo dell'invariante quadratico di un qualsiasi tensore, importante, tra l'altro, nel caso del tensore di Riemann ossia l'invariante di Erich Justus Kretschmann. Il calcolo del campo elettrico ottenuto dal potenziale vettore viene fatto antisimmetrizzando un vettore di rango 2 con latdueantisim
ed ora si può fare il calcolo del tensore EnergiaInpulso che serve per dimostrare la correttezza delle singolarità della Relatività Generale ossia i buchi neri. L'importantissimo tensore EnergiaImpulso si ottiene con una funzione che crea un tensore di rango 2 con traccia nulla ossia con latduetracciazero
o, per fare tutto automaticamente, si usa lafa_tenergiaimpulso
.
ada(la,per)
funzione che attua una permutazione direttamente sulla lista da permutare in modo da ottenere il risultato della permutazione su una listala
che può contenere qualsiasi tipo di dati inizialmente ordinati e come risultato, scambiati di posto tramite la permutazioneper
.cambiacoord(tn,InFunDiN,NuoveC,metrica)
Funzione per il cambiamento del sistema di coordinate. Bisogna specificare ovviamente il tensoretn
da modificare esprimendolo, come risultato, nelle nuove coordinate, poi le funzioni che esprimono le vecchie coordinate in funzione delle nuove ossia la listaInFunDiN
, poi i simboli delle nuove coordinate ossia la listaNuoveC
ed infine la metrica valida per il tensore da modificare, usata per sapere quali erano le espressioni delle vecchie coordinate.cambiasesso(lista,litipi,gff,gmm)
Questa è la funzione applicata dallaticambiotutto(tn,metrica)
ma, dato che lavora su tensori scritti in forma di lista ed ha bisogno di ricevere in input l'indicazione del tipo di indici da attribuire alla lista , consente calcoli esplorativi senza bisogno di precalcolare la metrica ossia fare derivate.
Per questo scopo lacambiasesso
deve ricevere come terzo argomentogff
ossia la matrice da considerare come tensore metrico covariante ossia totalmente femminile e come quarto argomentogmm
ossia la inversa dellagff
che dunque considera come tensore metrico controvariante ossia totalmente maschile.cambiatipi(tn,nuovitipi,metrica)
Questa funzione cambia il sesso degli indici del tensoretn
passato come primo argomento. Bisogna specificare la lista deinuovitipi
degli indici per cui, solo se gli indici vecchi sono di tipo diverso da quello voluto, viene fatto il cambiamento. Come terzo argomento va passata lametrica
da cui trarre il tensore metrico totalmente femminile ossia covariante ed il tensore metrico totalmente maschile ossia controvariante.commentalo(tn,comme)
Per inserire un commento nel tensore, uso la commentalo ossia questa funzione... Il secondo argomentocomme
può essere qualsiasi cosa, numero, stringa, lista etc...commento(tn)
Il commento che ogni tensore contiene e che può essere una stringa ma anche un numero o una lista o un qualsiasi oggetto, è estraibile in questo modo...diffcov(tn,metrica,nome)
:derivata covariante di un tensore di qualunque tipo : si tratta di una funzione fondamentale ossia l'essenza del calcolo tensoriale. Riporto in seguito ulteriori commenti...dimensione(tn)
Ogni tensore contiene, come si è detto, la dimensione dello spazio a cui si riferisce. Per ottenere questo dato si può usare questa funzione...divergenza(tn,ki,metrica)
Crea la funzione divergenza di un tensore rispetto ad un dato indiceki
, nota la metrica e dunque la dimensione, l'ordine del tensore e il tensore metrico controvariante. Fa uso della derivata covariante per cui questa funzione è applicabile a qualunque tensore di rango positivo.La funzione ha un nome comprensibile per chi fa uso del normale calcolo vettoriale ossia calcola la divergenza di un vettore. In pratica, supponendo di partire da un vettore maschio ossia controvariante, la divergenza si fa in questo modo: si calcola la derivata covariante del vettore e quindi si ottiene una matrice ossia un tensore di rango 2, il cui primo indice è maschio ed il secondo, prodotto dalla derivata, è femmina. Poi calcolo la traccia di questa matrice ossia la somma degli elementi diagonali e cosí ottengo uno scalare che appunto è la divergenza del vettore. Questa operazione può essere generalizzata partendo non da un vettore ma da un tensore di qualsiasi altro rango e questo vuol dire che un tensore ha tante divergenze quanto è il suo rango. Dunque una matrice, ossia un tensore di rango 2, ha due divergenze diverse, a meno che la matrice non sia simmetrica o antisimmetrica...fa_ch122(g22,listavariabili)
Per fare simboli di Christoffel di seconda specie basta avere il tensore metrico totalmente femminile ossia covariante e la lista delle variabili usate nel sistema di riferimento ossia , per esempio, in spazi deformati dalla presenza di masse ma asintoticamente cartesiani lalistavariabili
potrebbe essere[ t,x,y,z ]
.fa_ch222(g220)
Se si dispone dello pseudo tensore di rango 3 ottenuto derivando tutti gli elementi del del tensore metrico femminileg22
ottenendog220
( usare lafa_diff(g22,variabili,comme)
), il calcolo del Simbolo di Christoffel di prima specie è un calcolo di pura algebra e dunque puè essere fatto in modo molto veloce...Questa funzione, opportunamente tradotta in altri linguaggi incapaci di fare direttamente calcolo simbolico ma solo numerico, consente di lavorare per esempio anche in Javascript definendo esplicimamente le funzioni dig220
.fa_diff(tn,variabili,comme)
:derivata preliminare ossia non qualificata come covariante , di un tensore di qualsiasi rango. Richiede l'uso di una permutazione finale perché spontaneamente aggiungerebbe l'indice 0 all'inizio e non alla fine degli indici del tensore.fa_metrica(mg,listavariabili)
Il calcolo differenziale tensoriale si basa su una funzione, fametrica, che genera la metrica usata per calcolare la derivata covariante. Questa funzione deve ricevere in argomento una matrice che, per sicurezza, viene simmetrizzata e usata come tensore metrico covariante della metrica."Ha creato un vettore di più di undici elementi:"),
- [1] : lista delle variabili
- [2] : tensore metrico covariante
- [3] : tensore metrico controvariante
- [4] : derivate prime del tens. metrico cov.
- [5] : derivate seconde del tens. m. cov.
- [6] : simboli di Christoffel di prima specie
- [7] : simboli di Christoffel di seconda specie
- [8] : Riemann col solo primo indice controvariante
- [9] : Riemann totalmente covariante
- [10]: Ricci totalmente covariante
- [11]: sqrt(abs(determinate del tens.metr.cov.)
Nel vettore creato da questa funzionefa_metrica
sono conservate anche alcune costanti importanti per l'elettromagnetismo e per l'astrofisica e la cosmologia.fa_r1222(t22,listavariabili)
Genera il tensore di Riemann col primo indice controvariante.Ora trascrivo il tensore di Riemann con la formula dell'HEL Hobson,Efstathiou,Lasenby ISBN 9780521829519 a pag. 158. La formula ricopiata dal libro è questa:r1d2a2b2c = ch1d2a2a0b - ch1d2a2b0c + ch1e2a2c*ch1d2e2b - ch1e2a2b*ch1d2e2cIl nome degli indici però non mi piace e preferisco usare come nomi a,b,c,d sostituti di d,a,b,c ed inoltre usare il nome j al posto del nome e, per cui la formula diventa:r1a2b2c2d = ch1a2b2d0c - ch1a2b2c0d + ch1j2b2d*ch1a2j2c - ch1j2b2c*ch1a2j2dIn linguaggio wxMaximese non interpongo i nomi degli indici alle cifre indicatrici di tipo ma scrivo i nomi tra parentesi quadre:r1222[a,b][c,d]:ch1220[a,b][d,c]- ch1220[a,b][c,d]+ ch122[j][b,d]*ch122[a][j,c]- ch122[j][b,c]*ch122[a][j,d]Per fare il calcolo bisogna disporre sia del simbolo di Christoffel di seconda specie che dello pseudotensore delle sue derivate.
Spezzo il calcolo in due parti in modo che sia possibile partire o dal tensore metrico covariante o dai simboli di Christoffel di seconda specie.fa_r22(t22,listavariabili)
Definisco il tensore di Ricci totalmente femminile, ossia doppiamente covariante seguendo ancora la definizione dell' HEL.
In pratica fa la traccia tra il primo indice, maschile, e l'ultimo, femminile.fa_r2222(t22,listavariabili)
Genera il tensore di Riemann totalmente covariante.Lo calcola in forma totalmente covariante senza fare uso delle derivate dei simboli di Christoffel, in base a quanto sta scritto sull' HEL.r2a2b2c2d = (g2b2c0d0a- g2a2c0d0b+ g2a2d0b0c- g2b2d0a0c )/2 + ch1j2b2c*ch2j2a2d - ch1j2b2d*ch2j2a2covvero in wxMaximese:r2222[a,b][c,d] = ( g2200[b,c][a,d] - g2200[a,c][b,d] + g2200[a,d][b,c] - g2200[b,d][a,c] )/2 + ch122[j][a,d]*ch222[j][b,c] - ch122[j][a,c]*ch222[j][b,d]Il tensore di Riemann in forma totalmente covariante evidenzia le sue simmetrie. E' antisimmetrico scambiando gli indici della prima coppia ed è antisimmetrico scambiando gli indici della seconda coppia mentre è simmetrico scambiando le coppie tra loro.
Per queste simmetrie il calcolo del tensore di Riemann potrebbe essere molto più veloce evitando inutili ricalcoli ma qui ...non si bada a spese...fa_tenergiaimpulso(tpotvet,metrica)
Per trovare il tensore energia impulso NON NORMALIZZATO, partendo da un potenziale vettore, ossia un tensore di rango 1, faccio questa comoda funzioncina.fondetatb(ta,tb,nome)
Importante funzione per fondere due tensori anche di diverso rango ottenendo un tensore di rango somma dei ranghi.
Notare che i due tensori possono essere anche di rango zero per cui il risultato non aumenta di rango ma viene semplicemente moltiplicato per lo scalare del tensore di rango zero.indici(tn)
ovvero la natura degli indici del tensoretn
. Se pari sono femminili ossia covarianti e se dispari sono maschili ossia controvarianti.listadatensore(tn)
Per estrarre TUTTI gli elementi di un tensore mettendoli in una lista. Notare che il tensore può essere anche di rango zero ossia uno scalare da cui si ottiene una lista con un solo elemento.knbl22a(info)
Metrica di Kerr Newman nel sistema di riferimento di Boyer e Lindquist.
L'argomentoinfo
serve solo per produrre stampe di spiegazione se è una stringa.
Questa versione contiene solo espressioni razionali e non trigonometriche in modo da facilitare le semplificazioni delle formule da parte di wxMaxima.
Si ha la possibilità di dare un valore numerico alle costanti, tipocw
ossia la velocità della luce,Gw
ossia la costante di gravitazione universale edLw
che è richiesto dal Sistema di Misura Internazionale per definire la permeabilità magnetica.
La massa è indicata daMw
, La carica daQw
e lo spin daaw
.
Oltre alla matrice del tensore metrico e alla lista delle coordinate questa funzione fornisce l'espressione del potenziale vettore elettromagnetico in forma covariante ossia femminile per consentire il calcolo del campo elettromagnetico e del tensore EnergiaImpulso necessario per verificare l'equazione di Einstein ossia verificare che la metrica di Kerr Newman nel sistema di riferimento di Boyer e Lindquist si riferisce veramente ad un buco nero ossia una soluzione singolare della R.G. Dunque, da questo vettore è possibile calcolarlo usando lafa_tenergiaimpulso
.
Viene messa a disposizione anche la espressione dell'invariante quadratico del tensore di Riemann ottenuto mediante la metrica ottenuta da questa matrice ossia lo scalare di Erich Justus Kretschmann. In questo modo, ricalcolandolo, si può verificare che le varie funzioni coinvolte nel calcolo funzionino bene.knbl22b(info)
Metrica di Kerr Newman nel sistema di riferimento di Boyer e Lindquist.
L'argomentoinfo
serve solo per produrre stampe di spiegazione se è una stringa.
Versione apparentemente semplice ma con uso di funzioni trigonometriche che rendono difficili le semplificazioni delle formule da parte di wxMaxima.
Si ha la possibilità di dare un valore numerico alle costanti, tipocw
ossia la velocità della luce,Gw
ossia la costante di gravitazione universale edLw
che è richiesto dal Sistema di Misura Internazionale per definire la permeabilità magnetica.
La massa è indicata daMw
, La carica daQw
e lo spin daaw
.nonmetricap(metrica)
L'ultimo valore della lista della metrica è sempre lo stesso e serve a capire se la lista della metrica è veramente stata creata dalla funzionefa_metrica
.ordine(tn)
o meglio, rango del tensoretn
.L'ordine di un tensore è ottenibile con la seguente funzione che, per ragioni di velocità, non effettua nessuna verifica della correttezza del tensoretn
passato in argomento.permuta(tn,per,com)
:La funzione importantissima che permuta gli indici di un qualsiasi tensore creando un altro tensore con gli indici permutati in base all'ordinamento specificato dalla listaper
. La listaper
deve indicare da dove è stato preso il dato che compare in quella posizione.Per esempio [3,1,2,4] indica che il dato che compare come primo indice è quello che prima era situato in colonna 3, come secondo dato quello che prima stava in colonna 1 etc. La rotazione degli indici sa fa con [2,3,4,1].rapportolistetensori(ta,tb)
Questa funzione serve ad evitare sbrodolate nella stampa dei tensore. Se credo che due tensori sono tra loro uguali o almeno proporzionali faccio il controllo e se veramente lo sono... ottenngo stime molto concise...ricci_22(t22,variabili)
Utilizza la libreria alternativa non ricorsiva. Dal tensore metrico covariante mi fornisce subito il tensore di Ricci covariante.Utilizza la libreria alternativa non ricorsiva. Dal tensore metrico covariante mi fornisce subito il tensore di Ricci covariante.riemann_1222(t22,variabili)
Versione alternativa dellafa_r1222(t22,listavariabili)
.Bisogna chiamare lariemann_1222
passandogli il tensore metrico covariantet22
e la lista dei nomi delle variabili del sistema di riferimentolistavariabili
e lei fa tutto... Questa funzione è utile perché è più semplice di quella ricorsiva ed adatta ad essere riempita di stampe di controllo...riemann_2222(t22,variabili)
Calcola il tensore di Riemann in forma totalmente femminile ossia covariante ossia fa lo stesso calcolo dellafa_r2222(t22,listavariabili)
ma sembra più veloce essendo meno generale dato che non fa uso di funzioni ricorsive ma utilizza il costrutto for.
Il primo argomento,t22
è il tensore metrico totalmente femminile.scala(ta,ia,tb,ib)
:Prodotto scalare generalizzato. Attenzione... è posizionale e per ottenere gli indici nell'ordine voluto bisogna poi riordinare il risultato con la funzione permuta.semplimetrica(metrica)
Per semplificare ulteriormente l'intera metrica quando di sono funzioni polinomiali e razionali ma NON ci sono funzioni trigonometriche.semplimetricatrig(metrica)
Per semplificare ulteriormente l'intera metrica quando ci sono funzioni trigonometrichetassegna(tn,val,p)
Assegna il valoreval
ad un particolare elemento del tensoretn
specificato dalla listap
la cui lunghezza deve essere uguale al rango del tensoretn
.tcontrov(lv,metrica)
Crea un vettore, tensore di rango 1 maschile ossia controvariante, ben fatto. Permetrica
si intende una lista di tensori utili per gestire una data metrica. La lista viene generata da una apposita funzionefa_metrica(matrice,listavariabili)
.
Il primo argomento,lv
è una lista di valori che vengono assegnati al vettore ossia tensore di rango 1 così creato...tcov(lv,metrica)
Crea un vettore, tensore di rango 1 femminile ossia covariante, ben fatto. Permetrica
si intende una lista di tensori utili per gestire una data metrica. La lista viene generata da una apposita funzionefa_metrica(matrice,listavariabili)
.
Il primo argomento,lv
è una lista di valori che vengono assegnati al vettore ossia tensore di rango 1 così creato...tdueantisim(tn,metrica)
Questa funzione serve soprattutto a fare il tensore campo elettromagnetico dalla derivata covariante del potenziale vettore elettromagnetico. In pratica fa il tensore antisimmetrico di un tensore assegnato che deve essere di rango due ossia essere una matrice. Se i tipi dei due indici non sono uguali li rende provvisoriamente uguali e poi, dopo avere antisimmetrizzato, li rimette come erano nel tensore assegnato.
In pratica, assegnato il vettore campo elettromagnetico, lo si deriva con ladiffcov
e il risultato lo si antisimmetrizza con questa funzione.tduetracciazero(tn,metrica)
Questa sembrerebbe una funzione piuttosto insolita ossia, dato un tensore di rango due ossia una matrice, sottrargli un opportuno tensore ( in pratica il tensore metrico ) fatto in modo che la traccia del tensore risultato sia nulla. Questa funzione e' FONDAMENTALE per costruire il tensore Energia Impulso del campo elettromagnetico che compare nell'equazione di Einstein per definire il corretto valore del tensore di Ricci-Curbastro.tensoredalista(lista,tipi,comme,ndim)
Crea un tensore del tipo voluto, prelevando i dati da una lista che se è troppo breve viene riutilizzata ciclicamente e naturalmente, se è troppo lunga, viene usata solo parzialmente.
Il secondo argomento specifica il rango del tensore e il tipo di ogni suo indice, maschile ossia controvariante se dispari e femminile ossia covariante se pari.
Il terzo argomento è un commento di qualsiasi tipo.
Il quarto argomento ossiandim
specifica il numero delle dimensioni dello spazio e deve essere un intero maggiore di 1.
Notare che questa funzione non richiede l'uso della metrica e dunque è molto più flessibile di altre funzioni che fanno sostanzialmente cose simili...
Latensoredalista
accetta anche un dato non lista che tratta come lista ed è possibile anche generare tensori di rango zero ossia scalari ma con informazioni sul loro nome e sul numero delle dimensioni dello spazio in cui vanno usati.tensorp(tn)
Raccogliamo i vari test di buona definizione in questa funzionetensorp(tn)
che dà risultatotrue
setn
è un tensore ben fatto efalse
setn
non è un tensore o è un tensore mal fatto.ticambiotutto(tn,metrica)
Dato un tensoretn
di qualsiasi rango laticambiotutto
calcola il tensore che ha tutti gli indici di tipo diverso ossia se un dato indice è di tipo covariante ossia femminile il corrispondente indice sarà di tipo controvariante ossia maschile e viceversa.
Sarebbe possibile fare questo calcolo usando lacambiatipi(tn,nuovitipi,metrica)
che è più flessibile e sfrutta varie funzioni di questa libreria ma laticambiotutto
applica altre funzioni e dunque potrebbe servire per fare la verifica dello stesso calcolo fatto con lacambiatipi
.tmat11(mat,metrica)
Crea un tensore di rango 2 ( in pratica una matrice ), totalmente maschile ossia controvariante, data una matrice e la metrica. Permetrica
si intende una lista di tensori utili per gestire una data metrica. La lista degli oggetti della metrica viene generata da una apposita funzionefa_metrica(matrice,listavariabili)
.
Forse è meglio usare la flessibilissima funzionetensoredalista(lista,tipi,comme,ndim)
che richiede più argomenti ma non obbliga a calcolare la metrica.tmat12(mat,metrica)
Crea un tensore di rango 2 ( in pratica una matrice ), col primo indice maschile ossia controvariante, ed il secondo femminile ossia covariante, data una matrice di valori e la metrica. Permetrica
si intende una lista di tensori utili per gestire una data metrica. La lista degli oggetti della metrica viene generata da una apposita funzionefa_metrica(matrice,listavariabili)
.tmat21(mat,metrica)
Crea un tensore di rango 2 ( in pratica una matrice ), col primo indice femminile ossia covariante, ed il secondo maschile ossia controvariante, data una matrice di valori e la metrica. Permetrica
si intende una lista di tensori utili per gestire una data metrica. La lista degli oggetti della metrica viene generata da una apposita funzionefa_metrica(matrice,listavariabili)
.tmat22(mat,metrica)
Crea un tensore di rango 2 ( in pratica una matrice ), totalmente femminile ossia covariante, data una matrice di valori e la metrica. Permetrica
si intende una lista di tensori utili per gestire una data metrica. La lista degli oggetti della metrica viene generata da una apposita funzionefa_metrica(matrice,listavariabili)
.tmeno(tena,tenb)
Fa la differenza tra due tensori con uguale dimensione, ordine e tipo di indici.tnsemplifica(tn)
Per semplificare ulteriormente un tensoretn
quando di sono funzioni polinomiali e razionali ma NON ci sono funzioni trigonometriche.tnsemplificatrig(tn)
Per semplificare ulteriormente un tensoretn
quando ci sono funzioni trigonometriche.tprod(tscala,tenb)
Moltiplica un tensore di rango 0 ossia uno scalaretscala
per un tensore di qualsiasi rango ossiatenb
. Una funzione molto semplice ma comoda...traccia(tn,ih,ik)
Generalizzazione del calcolo della traccia di una matrice ossia un tensore di rango 2. Il rango del tensore deve essere maggiore di 1 e i due indiciih
eik
devono essere di tipo diverso, uno maschile ossia controvariante ed uno femminile ossia covariante.tsca(sc,metrica)
Crea un tensore scalare ossia un normale scalare ma con la struttura di un tensore di rango 0. L'argomentosc
rappresenta il valore dello scalare ma per creare il tensore bisogna sapere in quante dimensioni verrà usato ossia bisogna specificare lametrica
definita dalla funzionefa_metrica(matrice,lista_variabili)
.
Forse è meglio usare la flessibilissima funzionetensoredalista(lista,tipi,comme,ndim)
che richiede più argomenti ma non obbliga a calcolare la metrica. In questo caso l'argomentolista
deve essere una lista vuota ossia[ ]
.tsomma(tena,tenb)
Fa la somma tra due tensori con uguale dimensione, ordine e tipo di indici.tvale(tn,p)
Trova il valore di un particolare elemento del tensoretn
specificato dalla listap
la cui lunghezza deve essere uguale al rango del tensoretn
.zerotensor(tipi,comme,ndim)
Questa funzione genera un tensore con elementi tutti nulli, con indici di valore prescelto specificati nella listatipi
, con commento arbitrario specificato dall'argomentocomme
e di dimensione spazio-temporale assegnata ossiandim
che deve essere un intero maggiore di 1.La derivazione covariante
Per convenzione la cifra che segnala un indice ottenuto da derivazione covariante è 8 e quello trasformato in controvariante è 9. Dunque xx28 è un vettore covariante ( xx2 ) diventato tensore del secondo ordine per derivazione covariante ed analogamente xx18 è un vettore controvariante ( xx1), derivato covariantemente. Se alzo l'ultimo indice di xx28 ottengo xx29, etc...
Dato che la derivazione covariante produce tensori, è possibile derivare qualsiasi tensore usando i simboli di Christoffel in due modi diversi a seconda della natura covariante o controvariante di un dato indice.
Per fare la derivazione occorrono tanti simboli di Christoffel quanti sono gli indici del tensore e dunque per derivare uno scalare non occorrono simboli di Christoffel ossia la derivazione di uno scalare coincide con quella ordinaria.
Esaminiamo i due casi distinti usando le convenzioni della presente libreria che impone che i tensori di qualunque ordine siano delle liste di qualcosa, scalari o matrici e che l'ultimo elemento della lista sia a sua volta una lista che contiene informazioni sulla natura degli indici del tensore.
Dunque:A[a] è uno scalare o un vettore del primo ordine. Se è uno scalare esiste solo A[1] mentre se è un vettore esistono anche le componenti A[2]...A[nd] dove nd è il numero di dimensioni dello spazio, ovvero 3 in meccanica classica e 4 in meccanica relativistica. B[a][b,c] è un tensore del secondo o del terzo ordine. C[a][b,c][d,e] è un tensore del quarto o del quinto ordine.
Per accedere alla lista dei tipi degli indici bisogna prendere l'ultimo elemento del primo indice ossia A[length(A)] o B[length(B)] o C[length[C)] è la lista dei tipi degli indici, qualunque sia l'ordine del tensore A o B o C.
L'ultima delle componenti, se il tensore ha ordine pari è sempre 2 mentre se ha ordine dispari è sempre data da nd+1. In pratica però è meglio non fare affidamento su questa regola e prendere sempre l'ultimo indice della lista perché in questo modo è possibile usare anche liste più lunghe del minimo indispensabile e memorizzare negli elementi sovrabbondanti i dati che si desidera associare in più al tensore.
Notare che in Maxima è ammesso omettere gli indici tra parentesi quadra per cui se scrivo B[1] ottengo l'unica o la prima matrice del tensore B ( o un singolo dato numerico se B è uno scalare o un vettore); la matrice ( o scalare) è l'unica se B è un tensore di ordine pari ossia ad esempio uno scalare o un tensore del secondo ordine ed è la prima se B è un tensore di ordine dispari ossia, per esempio un vettore o un tensore del terzo ordine.
Per la derivata di un vettore covariante A2, ossia di un tensore di ordine 1 dove la cifra 2 ricorda che il suo primo ed unico indice è covariante, la formula è questa:
A2a8b = A2a0b - ch1j2a2b*A2j ovvero in Maximese ( essendo 8 la cifra che indica derivata covariante ) :
A28[1][a,b] = A20[1][a,b] - ch122[j][a,b]*A2[j] dove la cifra 0 specifica la derivata preliminare e ch122 rappresenta il simbolo di Christoffel di seconda specie avente la cifra 1 che ricorda che il suo primo indice è (pseudo)controvariante e la cifra 2 che ricorda che il secondo e terzo indice sono (pseudo)covarianti.
Per la derivata di un tensore del secondo ordine totalmente covariante A22, la formula è questa:
A2a2b8c = A2a2b0c - ch1j2a2c*A2j2b - ch1j2b2c*A2a2j ovvero in Maximese, dato il tensore A[1][a,b] ottengo:
A228[a][b,c] = A220[a][b,c] - ch122[j][a,c]*A22[1][j,b] - ch122[j][b,c]*A22[1][a,j] per cui è facile intuire la regola generale da applicarsi ad un tensore di ordine qualsiasi.
La derivata di un tensore del terzo ordine totalmente covariante ossia A222, la formula è questa:
A2a2b2c2d = A2a2b2c0d - ch1j2a2d*A2j2b2c - ch1j2b2d*A2a2j2c - ch1j2c2d*A2a2b2j ovvero in Maximese, dato il tensore A[a][b,c]:
A2228[1][a,b][c,d] = A2220[1][a,b][c,d] - ch122[j][a,d]*A222[j][b,c] - ch122[j][b,d]*A222[a][j,c] - ch122[j][c,d]*A222[a][b,j] A questo punto è facile generalizzare il metodo a tensori di qualsiasi ordine.
La derivata di un vettore controvariante si fa invece in questo modo ( usando uno dei due indici pseudocovarianti del simbolo di Christoffel che è uno pseudo tensore) :
A1a8b = A1a0b + ch1a2j2b*A1j Notare che il simbolo di Christoffel è simmetrico nei suoi due ultimi indici trattati come covarianti, per cui avrei potuto scrivere anche in questo modo ( è solo una questione estetica )
A1a8b = A1a0b + ch1a2b2j*A1j ossia in Maximese, detto A1[a] il vettore da derivare ho la seguente formula
A18[1][a,b] = A10[1][a,b] + ch122[a][j,b]*A1[j]
La derivata di un tensore del secondo ordine totalmente controvariante A1a1b si fa, di conseguenza in questo modo:
A1a1b8c = A1a1b0c + ch1a2j2c*A1j1b + ch1b2j2c*A1a1j ossia in Maximese, dato A11[1][a,b] si ha:
A118[a][b,c] = A110[a][b,c] + ch122[a][j,c]*A11[1][j,b] + ch122[b][j,c]*A11[1][a,j] Attenzione: il primo contributo è dato da A11[1][j,b] che non è equivalente a A11[1][b,j] a meno che il tensore del secondo ordine non sia, in pratica, una matrice simmetrica.
[wxMaxima: comment end ] */
/* [wxMaxima: title start ]
Libreria tensoriale di Giampaolo Bottoni[wxMaxima: title end ] */ /* [wxMaxima: comment start ]@ Indice generale commentato[wxMaxima: comment end ] */ /* [wxMaxima: comment start ]
Aggiorna su disco la libreria solo se lo si vuole[wxMaxima: title end ] */ /* [wxMaxima: comment start ][wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Versione con ampliamenti nell' aprile 2014 [wxMaxima: comment end ] */ /* [wxMaxima: section start ] @ ordine(tn)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ ordine(tn):=block([], length(tn[length(tn)])-2 )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("ordine(tn)",libmia); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Il commento che ogni tensore contiene e che puo' essere una stringa ma anche un numero o una lista o un qualsiasi oggetto, e' estraibile in questo modo: [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ commento(tn)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ commento(tn):=block([u], u:length(tn), tn[u][length(tn[u])-1])$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("commento(tn)",libmia); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Per inserire un commento comme nel tensore, uso la commentalo: [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ commentalo(tn,comme)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ commentalo(tn,comme):=block([u], u:length(tn), tn[u][length(tn[u])-1]:comme,tn[u] )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("commentalo(tn,comme)",libmia); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Ogni tensore contiene, come si e' detto, la dimensione dello spazio a cui si riferisce. Per ottenere questo importante dato si puo' usare questa funzione: [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ dimensione(tn)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ dimensione(tn):=block([], tn[length(tn)][length(tn[length(tn)])])$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("dimensione(tn)",libmia); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Per estrarre dal tensore la lista dei tipi dei suoi indici (covarianti/femminili, controvarianti/maschili, etc.) senza bisogno di sapere la organizzazione interna dei dati del tensore, si puo' usare questa funzione: [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ indici(tn)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ indici(tn):=block([], rest(tn[length(tn)],-2))$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("indici(tn)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Indichiamo con tn un generico tensore ed esaminamo i test che ogni funzione, quando non ci sono esigenze di prestazioni, potrebbe fare per controllare che la struttura del tensore e' corretta. Raccogliamo i test nella funzione tensorp(tn) che da' risultato true se tn e' un tensore ben fatto e false se tn non e' un tensore o e' un tensore mal fatto. La tensorp utilizza in modo ricorsivo la matrixxp che opera su matrici di matrici. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tensorp(tn)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ matrixxp(tn,o,n):=block([basta,smetti], basta:false,smetti:true, if o>1 then ( smetti:false, if not(matrixp(tn)) then basta:true, if length(tn[1])#n then basta:true ), if basta then return(false), if smetti then return(true), matrixxp(tn[1,1],o-2,n) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ tensorp(tn):=block([u,o,n,pd], if not(listp(tn)) then return(false), u:length(tn), if not(listp(tn[u])) then return(false), o:length(tn[u])-2, if 0>o then return(false), n:floor(tn[u][o+2]), if 2>n then return(false), pd:mod(o,2), if pd=0 then ( if u>n then return(false)) else if n>u-1 then return(false), if matrixxp(tn[1],o,n) then return(true), false )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tensorp(tn)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] La funzione zerotensor genera un tensore con elementi tutti nulli, con indici di valore prescelto, con commento arbitrario e di dimensione assegnata. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ zerotensor(tipi,comme,ndim)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ zerotensor(tipi,comme,ndim):=block([tn,j,o,u,nd], if not(listp(tipi)) then return("Errore, non lista tipi"), o:length(tipi), nd:floor(ndim), if 2>nd then return("Errore, dimensione inferiore a 2"), if o=0 then return([0,[comme,nd]]), if mod(o,2)=0 then tn:makelist(0,j,1,2) else tn:makelist(0,j,1,nd+1), u:length(tn), tn[u]:append(makelist(tipi[j],j,1,o),[comme,nd]), for j:1 thru u-1 do tn[j]:zeromatmat(o,nd), tn )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ zeromatmat(o,nd):=block([tr,omm,j,k], if 2>o then return(0), tr:zeromatrix(nd,nd), omm:o-2, for j:1 thru nd do for k:1 thru nd do tr[j,k]:zeromatmat(omm,nd), tr )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("zerotensor(tipi,comme,ndim)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ tsca(sc,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tsca(sc,metrica):=block([], if nonmetricap(metrica) then return("Errore: non metrica"), [sc,["(scal)",dimensione(metrica[2])]])$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tsca(sc,metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] La funzione tcov crea un vettore covariante/femminile , data una lista e la metrica. Meglio usare anche qui la funzione tensoredalista(lista,tipi,comme,ndim) che non richiede il precalcolo della metrica. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tcov(lv,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tcov(lv,metrica):=block([nl,nd], if not(listp(lv)) then return("Non lista"), if nonmetricap(metrica) then return("Errore: non metrica"), nl:length(lv), nd:dimensione(metrica[2]), append( makelist(lv[1+mod(j-1,nl)],j,1,nd), [[2,"(v2)",nd]]) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tcov(lv,metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Crea un vettore ( tensore di rango 1) controvariante/maschile, data la lista e la metrica. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tcontrov(lv,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tcontrov(lv,metrica):=block([nl,nd], if not(listp(lv)) then return("Non lista"), if nonmetricap(metrica) then return("Errore: non metrica"), nl:length(lv), nd:dimensione(metrica[2]), append( makelist(lv[1+mod(j-1,nl)],j,1,nd), [[2,"(v2)",nd]]) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tcontrov(lv,metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Crea un tensore di rango 2, totalmente controvariante, data una matrice e la metrica. Sono funzioni alternative alla preferibile tensoredalista(lista,tipi,comme,ndim) [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tmat11(mat,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tmat11(mat,metrica):=block([], if not(matrixp(mat)) then return("Non matrice"), if nonmetricap(metrica) then return("Errore: non metrica"), [mat,[1,1,"(tm11)",dimensione(metrica[2])]])$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tmat11(mat,metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Crea un tensore di rango 2, misto ossia controvariante, covariante, data una matrice e la metrica. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tmat12(mat,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tmat12(mat,metrica):=block([], if not(matrixp(mat)) then return("Non matrice"), if nonmetricap(metrica) then return("Errore: non metrica"), [mat,[1,2,"(tm12)",dimensione(metrica[2])]])$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tmat12(mat,metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Crea un tensore di rango 2, misto ossia covariante, controvariante, data una matrice e la metrica. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tmat21(mat,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tmat21(mat,metrica):=block([], if not(matrixp(mat)) then return("Non matrice"), if nonmetricap(metrica) then return("Errore: non metrica"), [mat,[2,1,"(tm11)",dimensione(metrica[2])]])$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tmat21(mat,metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Crea un tensore di rango 2, totalmente covariante/femminile, data una matrice e la metrica. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tmat22(mat,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tmat22(mat,metrica):=block([], if not(matrixp(mat)) then return("Non matrice"), if nonmetricap(metrica) then return("Errore: non metrica"), [mat,[2,2,"(tm22)",dimensione(metrica[2])]])$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tmat22(mat,metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ tsomma(tena,tenb)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tsomma(tena,tenb):=block( [oa,ob,na,nb,ina,inb,stop], if not(tensorp(tena)) then return("Errore: primo arg. non tensore"), if not(tensorp(tenb)) then return("Errore: secondo arg. non tensore"), oa:ordine(tena), ob:ordine(tenb), if oa#ob then return("Errore: tensori di ordine diverso"), na:dimensione(tena), nb:dimensione(tenb), if na#nb then return("Errore: tensori di dimensione diversa"), ina:indici(tena), inb:indici(tenb), stop:false, for j:1 thru oa do if mod(ina[j]+inb[j],2)=1 then stop:true, if stop then return("Errore: indici incongruenti"), append(ratsimp(rest(tena,-1)+rest(tenb,-1)), [append(ina,["(Somma tensori)",na])]) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tsomma(tena,tenb)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Differenza tra due tensori con uguale dimensione, rango e tipo di indici. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tmeno(tena,tenb)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tmeno(tena,tenb):=block( [oa,ob,na,nb,ina,inb,stop], if not(tensorp(tena)) then return("Errore: primo arg. non tensore"), if not(tensorp(tenb)) then return("Errore: secondo arg. non tensore"), oa:ordine(tena), ob:ordine(tenb), if oa#ob then return("Errore: tensori di ordine diverso"), na:dimensione(tena), nb:dimensione(tenb), if na#nb then return("Errore: tensori di dimensione diversa"), ina:indici(tena), inb:indici(tenb), stop:false, for j:1 thru oa do if mod(ina[j]+inb[j],2)=1 then stop:true, if stop then return("Errore: indici incongruenti"), append(ratsimp(rest(tena,-1)-rest(tenb,-1)), [append(ina,["(Differenza tra tensori)",na])]) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tmeno(tena,tenb)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Prodotto di un tensore scalare ossia di rango zero, per un qualsiasi tensore della stessa dimensione. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tprod(tscala,tenb)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tprod(tsc,tenb):=block( [tscala,oa,ob,na,nb,inb], if not(tensorp(tenb)) then return("Errore: secondo arg. non tensore"), if tensorp(tsc) then tscala:tsc else tscala:[tsc,["(scal)",dimensione(tenb)]], oa:ordine(tscala), ob:ordine(tenb), if oa#0 then return("Errore: non scalare"), na:dimensione(tscala), nb:dimensione(tenb), if na#nb then return("Errore: tensori di dimensione diversa"), inb:indici(tenb), append(ratsimp(tscala[1]*rest(tenb,-1)),[append(indici(tenb), ["(Prodotto scalare*tensore)",nb])]) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tprod(tsc,tenb)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ tassegna(tn,val,p)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tassegna(tn,val,p):=block([o], o:length(tn[length(tn)])-2, if length(p)#o then return("errore: incongruenza di indici"), if o=0 then ( tn[1]:val,return(true)), if o=1 then ( tn[p[1]]:val, return(true)), if mod(o,2)=0 then assegnam(tn[1],2,val,p) else assegnam(tn[p[1]],2,val,rest(p)) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tassegna(tn,val,p)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tvale(tn,p)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tvale(tn,p):=block([o], o:length(tn[length(tn)])-2, if length(p)#o then return("errore: incongruenza di indici"), if o=0 then return(tn[1]), if o=1 then return(tn[p[1]]), if mod(o,2)=0 then valem(tn[1],2,p) else ( valem(tn[p[1]],2,rest(p))) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tvale(tn,p)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ permuta(tn,per,comm)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ permuta(tn,per,comm):=block([tr,u,o,a,b,j,nd,va,vb,id], if not(tensorp(tn)) then return("Errore, non tensore"), if not(listp(per)) then return("Errore, non lista permutazioni"), u:length(tn),o:length(tn[u])-2, if 2>o then return("Applicabile da ordine 2 in su"), if o#length(per) then return("Errore, lista permutazioni incongruente"), j:1,for a:1 thru o-1 do for b:a+1 thru o do if per[a]=per[b] then j:0, if j=0 then return("Permutazione errata"), nd:tn[u][o+2], va:makelist(0,j,1,o), vb:makelist(0,j,1,o), id:makelist(0,j,1,o), for j:1 thru o do id[j]:tn[u][per[j]], tr:zerotensor(id,comm,nd), funfor(tr,tn,va,vb,per,1,o,nd), tr )$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Faccio un ciclo for in forma ricorsiva... [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ funfor(ta,tb,va,vb,per,n,m,nd):=block([j,np], if n=m then ( for j:1 thru nd do ( va[n]:j, vb[per[n]]:j, tassegna(ta,tvale(tb,vb),va) )) else ( np:n+1, for j:1 thru nd do ( va[n]:j, vb[per[n]]:j, funfor(ta,tb,va,vb,per,np,m,nd)) ) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("permuta(tn,per,com)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Funzione per trovare, applicandola, come e' permutata una lista ossia data una lista e una permutazione di tutti gli elementi della lista, cosa diventa la lista permutata. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ ada(la,per)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ ada(la,per):=block([n,j,k,lr], n:length(per), if n#length(la) then return("Disuguale lunghezza liste"), for j:1 thru n-1 do for k:j+1 thru n do if per[j]=per[k] then return("Indici duplicati"), lr:makelist(0,j,1,n), for j:1 thru n do lr[j]:la[per[j]], lr)$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("ada(la,per)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ tensoredalista(lista,tipi,comme,ndim)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ forlista(tb,vb,n,m,nd,lista,dove):=block([j,np], if n=m then ( for j:1 thru nd do ( vb[n]:j, dove[1]:mod(dove[1],length(lista))+1, tassegna(tb,lista[dove[1]],vb) )) else ( np:n+1, for j:1 thru nd do ( vb[n]:j, forlista(tb,vb,np,m,nd,lista,dove)) ) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ tensoredalista(lista,tipi,comme,ndim):=block( [usolista,tr,dove,m,vb,j], if listp(lista) then usolista:lista else usolista:[lista], if 1>length(tipi) then return([usolista,[comme,ndim]]), tr:zerotensor(tipi,comme,ndim), dove[1]:0, m:length(tipi), vb:makelist(0,j,1,m), forlista(tr,vb,1,m,ndim,usolista,dove), tr)$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tensoredalista(lista,tipi,comme,ndim)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ listadatensore(tn)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ forinlista(lista,tb,vb,n,m,nd,dove):=block([j,np], if n=m then ( for j:1 thru nd do ( vb[n]:j, dove[1]:mod(dove[1],length(lista))+1, lista[dove[1]]:tvale(tb,vb))) else ( np:n+1, for j:1 thru nd do ( vb[n]:j, forinlista(lista,tb,vb,np,m,nd,dove)) ) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ listadatensore(tn):=block([lista,u,o,dove,vb,j], u:length(tn),o:length(tn[u])-2, if 1>o then return([tn[1]]), nd:tn[u][o+2], dove[1]:0, vb:makelist(0,j,1,o), lista:makelist(0,j,1,nd^o), forinlista(lista,tn,vb,1,o,nd,dove), lista)$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("listadatensore(tn)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ traccia(tn,ih,ik)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ fortraccia(tr,vr,tn,vn,h,k,n,nn,m,nd):=block([j,np,nnp,ss], if n=m then ( ss:0, for j:1 thru nd do ( vn[h]:j,vn[k]:j, ss:ss+tvale(tn,vn)), tassegna(tr,ss,vr)) else ( np:n+1, nnp:nn+1, if nnp=h then nnp:nnp+1, if nnp=k then nnp:nnp+1, for j:1 thru nd do ( vr[np]:j, vn[nnp]:j, fortraccia(tr,vr,tn,vn,h,k,np,nnp,m,nd)) ) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ traccia(tn,ih,ik):=block([u,o,nd,vr,vb,h,k,tipi,i,j], if not(tensorp(tn)) then return("Errore: non tensore"), u:length(tn),o:length(tn[u])-2,nd:tn[u][o+2], if 2>o then return("Errore, ordine inferiore a 2"), if ih=ik then return("Errore, indici uguali"), h:min(ih,ik),k:max(ih,ik), if k>o then return(["Errore, indice superiore ad ordine",k,o]), vb:makelist(0,j,1,o),vr:[], if o>2 then vr:makelist(0,j,1,o-2), tipi:indici(tn), if tipi[h]=tipi[k] then print("Attenzione: indici dello stesso tipo"), tr:zerotensor(vr,"ridotto",nd), i:0,for j:1 thru o do ( if j#h then if j#k then ( i:i+1, tr[u][i]:tipi[j])), fortraccia(tr,vr,tn,vb,h,k,0,0,o-2,nd), tr)$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("traccia(tn,ih,ik)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ scala(ta,ia,tb,ib)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ forscala(tr,vr,ta,va,tb,vb,h,k,n,nn,ma,m,nd):=block( [j,np,nnp,ss], if n=m then ( va[h]:1, vb[k]:1, ss:0, for j:1 thru nd do ( va[h]:j,vb[k]:j, ss:ss+tvale(ta,va)*tvale(tb,vb)), tassegna(tr,ss,vr)) else ( np:n+1, nnp:nn+1, if nnp=h then nnp:nnp+1, if nnp=k+ma then nnp:nnp+1, for j:1 thru nd do ( vr[np]:j, if nnp>ma then vb[nnp-ma]:j else va[nnp]:j, forscala(tr,vr,ta,va,tb,vb,h,k,np,nnp,ma,m,nd)) ) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ scala(ta,ia,tb,ib):=block( [ua,oa,ub,ob,ur,ot,nd,vr,va,vb,tipa,tipb,i,j], if not(tensorp(ta)) then return("Errore: ta non tensore"), if not(tensorp(tb)) then return("Errore: tb non tensore"), ua:length(ta),oa:length(ta[ua])-2,nd:ta[ua][oa+2], if 1>oa then return("Errore, ordine ta inferiore a 1"), ub:length(tb),ob:length(tb[ub])-2, if nd#tb[ub][ob+2] then return("Errore, dimensioni diverse"), if 1>ob then return("Errore, ordine tb inferiore a 1"), if ia>oa then return(["Errore, indice superiore ad ordine",ia,oa]), if ib>ob then return(["Errore, indice superiore ad ordine",ib,ob]), va:makelist(0,j,1,oa),vb:makelist(0,j,1,ob), ot:oa+ob-2, vr:[],if ot>0 then vr:makelist(0,j,1,ot), tipa:indici(ta),tipb:indici(tb), if tipa[ia]=tipb[ib] then print("Attenzione: indici dello stesso tipo"), tr:zerotensor(vr,"prod-scalare",nd), ur:length(tr), i:0,for j:1 thru oa+ob do ( if j>oa then ( if (j-oa)#ib then ( i:i+1, tr[ur][i]:tipb[j-oa])) else if j#ia then ( i:i+1, tr[ur][i]:tipa[j])), forscala(tr,vr,ta,va,tb,vb,ia,ib,0,0,oa,ot,nd), tr)$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("scala(ta,ia,tb,ib)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: section start ] Funzioni per il calcolo differenziale[wxMaxima: section end ] */ /* [wxMaxima: comment start ]Queste funzioni fanno uso della derivazione simbolica fattibile in ambienti dove e' definita, tipo Maxima o Mathematica etc.. [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ fa_diff(tn,variabili,comme)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ fa_diff(tn,variabili,comme):=block([tn0,tnn,indi,o,j], tnn:rest(tn,-1), o:ordine(tn), indi:indici(tn), nd:dimensione(tn), if mod(o,2)=0 then ( tn0:makelist(0,j,1,nd+1), for j:1 thru nd do tn0[j]:ratsimp(diff(tnn[1],variabili[j])), tn0[nd+1]:append(cons(0,indi),[comme,nd]) ) else ( tn0:[0,append(cons(0,indi),[comme,nd])], tn0[1]:ratsimp(matrix(diff(tnn,variabili[1]))), for j:2 thru nd do tn0[1]:addrow(tn0[1], ratsimp(matrix(diff(tnn,variabili[j])))) ), if o>0 then permuta(tn0,makelist(mod(j,o+1)+1,j,1,o+1),comme) else tn0 )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("fa_diff(tn,variabili,comme)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ fa_ch222(g220)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ fa_ch222(g220):=block([g022,g202], if controllo then print("Inizia fa_ch222"), g022:permuta(g220,[2,3,1],"-"), g202:permuta(g022,[2,3,1],"-"), append((+rest(g220,-1)+rest(g022,-1)-rest(g202,-1))/2, [[2,2,2,"Christoffel prima specie",dimensione(g220)]]) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("fa_ch222(g220)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ fa_ch122(g22,listavariabili)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ fa_ch122(g22,listavariabili):=block([g11,g220], if controllo then print("Inizia fa_ch222"), g11: [ratsimp(invert(g22[1])), [1,1,"-",dimensione(g22)]], g220: fa_diff(g22,listavariabili,"g220"), ratsimp(scala(g11,2,fa_ch222(g220),1)) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("fa_ch122(g22,listavariabili)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ fa_r1222(t22,listavariabili)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ fa_r1222(t22,listavariabili):=block( [nd,g22,g11,g220,g022,g202,ch222,ch122], if controllo then print("Inizia fa_r1222"), if not(tensorp(t22)) then return("Primo argomento non tensore"), nd:dimensione(t22), g22:[ratsimp((t22[1]+transpose(t22[1]))/2),[2,2,"(g22)",nd]], g11:[ratsimp(invert(g22[1])),[1,1,"(g11)",nd]], g220:fa_diff(g22,listavariabili,"(g220)"), g022:permuta(g220,[2,3,1],"-"), g202:permuta(g022,[2,3,1],"-"), ch222:append((rest(g220,-1)+rest(g022,-1)-rest(g202,-1))/2, [[2,2,2,"Christoffel prima specie",dimensione(g220)]]), ch122:scala(g11,2,ch222,1), fa_ch_r1222(ch122,listavariabili))$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ fa_ch_r1222(ch122,listavariabili):=block( [r1222,ch1a2b2c2d,ch1a2b2d2c,xabcd,xacbd,xadbc], if controllo then print("Inizia fa_ch_r1222"), ch1a2b2c2d:fa_diff(ch122,listavariabili,"ch1a2b2c2d"), ch1a2b2d2c:permuta(ch1a2b2c2d,[1,2,4,3],"ch1a2b2d2c"), xabcd:scala(ch122,3,ch122,1), xacbd:permuta(xabcd,[1,3,2,4],"xacbd"), xadbc:permuta(xabcd,[1,4,3,2],"xadbc"), r1222:[ch1a2b2d2c[1]-ch1a2b2c2d[1]+ xacbd[1] - xadbc[1], [1,2,2,2,"(r1222)",dimensione(ch122)]] )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("fa_r1222(t22,listavariabili)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] VERIFICA: Le funzioni della libreria alternativa, usabile per calcolare il tensore di Riemann r1222 sono queste che non sono ricorsive e non gestiscono gli indici. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ riemann_1222(t22,variabili)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ der2(t2,variabili):=block([t3,nd,j], nd:length(variabili), t3:makelist(0,j,1,nd), for j:1 thru nd do t3[j]:diff(t2,variabili[j]), t3)$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ chris222(g22,variabili):=block([g220,ss,tn], g220:r3(der2(g22,variabili)), ss:r3(g220), tn:g220+ss, ss:r3(ss), ratsimp((tn-ss)/2) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ chris122(g22,variabili):=block([g11], g11:invert(g22), ch222:chris222(g22,variabili), transpose(g11.ch222)[1] )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ r3(t3):=block([nd,j,k,h,t3n], nd:length(t3), t3n:makelist(ident(nd),j,1,nd), for j:1 thru nd do for k:1 thru nd do for h:1 thru nd do t3n[j][k,h]:t3[h][j,k], t3n )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ r4(t4):=block([nd,i,j,k,h,t4n], nd:length(t4), t4n:genmatrix(lambda([i,j],ident(nd)),nd,nd), for i:1 thru nd do for j:1 thru nd do for k:1 thru nd do for h:1 thru nd do t4n[i,j][k,h]:t4[h,i][j,k], t4n )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ der3(t3,variabili):=block([t4,t4d,nd,j], if not(listp(t3)) then (print(["Errore",t3]), return("Non lista t3")), nd:length(variabili), t4d:der2(t3,variabili), t4:matrix(t4d[1]), for j:2 thru nd do t4:addrow(t4,t4d[j]), ratsimp(t4))$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Bisogna chiamare la riemann_1222 passandogli il tensore metrico covariante e lei fa tutto... Questa funzione e' utile perche' e' piu' semplice di quella ricorsiva ed adatta ad essere riempita di stampe di controllo... [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ riemann_1222(t22,variabili):=block( [g22,ch122,ch1220,r1222,nd,a,b,c,d,j,sp], if not(tensorp(t22)) then return("Primo argomento non tensore"), nd:dimensione(t22), g22:ratsimp((t22[1]+transpose(t22[1]))/2), ch122:chris122(g22,variabili), ch1220:r4(der3(ch122,variabili)), r1222:genmatrix(lambda([i,j],ident(nd)),nd,nd), for a:1 thru nd do for b:1 thru nd do for c:1 thru nd do for d:1 thru nd do ( sp:ch1220[a,b][d,c]-ch1220[a,b][c,d], for j:1 thru nd do sp:sp+ ch122[j][b,d]*ch122[a][j,c]- ch122[j][b,c]*ch122[a][j,d], r1222[a,b][c,d]:sp), [ ratsimp(r1222),[1,2,2,2,"(r1222)",nd]] )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("riemann_1222(t22,variabili)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ fa_r2222(t22,listavariabili)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ fa_r2222(t22,listavariabili):=block( [nd,g22,xg11,g11,g220,g022,g202,ch222,ch122,g2200], if controllo then print("Inizia fa_r2222"), if not(tensorp(t22)) then return("Primo argomento non tensore"), nd:dimensione(t22), g22:[ratsimp((t22[1]+transpose(t22[1]))/2), [2,2,"(g22)",nd]], xg11:trigsimp(ratsimp(invert(g22[1]))), g11:[xg11,[1,1,"(g11)",nd]], g220:fa_diff(g22,listavariabili,"(g220)"), g022:permuta(g220,[2,3,1],"-"), g202:permuta(g022,[2,3,1],"-"), ch222:append(ratsimp((rest(g220,-1)+ rest(g022,-1)-rest(g202,-1))/2), [[2,2,2,"Christoffel prima specie",dimensione(g220)]]), ch122:scala(g11,2,ch222,1), g2200:fa_diff(g220,listavariabili,"(yabcd) ovvero g2200"), fa_poi_r2222(ch222,ch122,g2200) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ fa_poi_r2222(ch222,ch122,g2200):=block( [zabcd,zadbc,zacbd,ybcad,yacbd,yadbc,ybdac], if controllo then print("Inizia fa_poi_r2222"), zabcd:scala(ch122,1,ch222,1), zadbc:permuta(zabcd,[1,3,4,2],"(zadbc)"), zacbd:permuta(zabcd,[1,3,2,4],"(zacbd)"), ybcad:permuta(g2200,[3,1,2,4],"(ybcad)"), yacbd:permuta(g2200,[1,3,2,4],"(yacbd)"), yadbc:permuta(g2200,[1,3,4,2],"(yadbc)"), ybdac:permuta(g2200,[3,1,4,2],"(ybdac)"), [ratsimp((ybcad[1]-yacbd[1]+yadbc[1]-ybdac[1])/2 +zadbc[1]-zacbd[1]), [2,2,2,2,"(r2222)",nd]] )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("fa_r2222(t22,listavariabili)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Il tensore di Riemann e' IMPORTANTISSIMO anche se richiede calcoli FATICOSISSIMI e difficilmente verificabili a mano. Per sicurezza includo nella libreria parecchi modi di calcolarlo.. Ecco la funzione tratta della altra libreria... Sembra piu' veloce essendo meno generale dato che non fa uso di funzioni ricorsive ma utilizza il costrutto for. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ riemann_2222(t22,variabili)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ riemann_2222(t22,variabili):=block( [ss,tn,nd,g22,ch222,ch122, g2200,r2222,a,b,c,d,j], if not(tensorp(t22)) then return("Primo argomento non tensore"), nd:dimensione(t22), g22:ratsimp((t22[1]+transpose(t22[1]))/2), g220:r3(der2(g22,variabili)), ss:r3(g220), tn:g220+ss, ss:r3(ss), ch222:ratsimp((tn-ss)/2), ch122:transpose(invert(g22).ch222)[1], g2200:r4(der3(g220,variabili)), r2222:genmatrix(lambda([i,j],ident(nd)),nd,nd), for a:1 thru nd do for b:1 thru nd do for c:1 thru nd do for d:1 thru nd do ( ss:(g2200[b,c][a,d] - g2200[a,c][b,d] + g2200[a,d][b,c] - g2200[b,d][a,c] )/2, for j:1 thru nd do ss:ss+ ch122[j][a,d]*ch222[j][b,c] - ch122[j][a,c]*ch222[j][b,d], r2222[a,b][c,d]:ss), [ ratsimp(r2222),[2,2,2,2,"(r2222)",nd]] )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("riemann_2222(t22,variabili)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ fa_r22(t22,listavariabili)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ fa_r22(t22,listavariabili):=block([], if controllo then print("Inizia fa_r22"), traccia(fa_r1222(t22,listavariabili),1,4) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("fa_r22(t22,listavariabili)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Utilizza la libreria alternativa non ricorsiva. Dal tensore metrico covariante mi fornisce subito il tensore di Ricci covariante. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ ricci_22(t22,variabili)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ ricci_22(t22,variabili):=block( [nd,r1222,ric22,a,b,sp,j], if not(tensorp(t22)) then return("Primo argomento non tensore"), nd:dimensione(t22), r1222:riemann_1222(t22,variabili)[1], r22:zeromatrix(nd,nd), for a:1 thru nd do for b:a thru nd do ( sp:0, for j:1 thru nd do sp:sp+r1222[j,a][b,j], r22[a,b]:sp, r22[b,a]:sp ), [ ratsimp(r22),[2,2,"(Ricci 22)",nd ] ] )$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] fa_metrica: costruttore di metrica. Genera una lista che include tutto quello che serve per fare derivate covarianti. [wxMaxima: subsect end ] */ /* [wxMaxima: comment start ] Il calcolo differenziale tensoriale si basa su una funzione riassuntiva, fametrica, che genera la metrica usata, tra l'altro, per calcolare la derivata covariante. Calcolata una volta per tutte questa funzione, la sua lista, che rappresenta il risultato, puo' essere usata ovunque serva fare calcoli tensoriali di vario tipo e per vari scopi. Questa funzione deve ricevere in argomento una matrice che, per sicurezza, viene simmetrizzata e usata come tensore metrico covariante della metrica ed ovviamente va indicata la lista dei nomi usati per le coordinate spazio_temporali. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ fa_metrica(mg,listavariabili)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ fa_metrica(mg,listavariabili):=block( [metrica,nd,m2,m3,m4,m4,m6,m7,m8,m9,ma,mb,costanti], if not(matrixp(mg)) then return("Errore, primo arg. non matrice"), if not(listp(listavariabili)) then return("Errore, secondo arg. non lista variabili"), if length(listavariabili)#length(mg) then return("Errore: incongruenza ", " tra matrice e lista variabili") else nd:length(listavariabili), if controllo then print("Inizia g22"), m2: [ratsimp((mg + transpose(mg) )/2), [2,2,"(tensore metrico covariante)",nd]], m2: trigsimp(m2), if controllo then print("Inizia g11"), m3: [ratsimp(invert(m2[1])), [1,1,"(tensore metrico controvariante)",nd]], if controllo then print("Inizia g220"), m4: fa_diff(m2,listavariabili,"g220"), if controllo then print("Inizia g2200"), m5: fa_diff(m4,listavariabili,"g2200"), m6: fa_ch222(m4), commentalo(m6,"(Christoffel prima specie)"), if controllo then print("Inizia ch122"), m7: scala(m3,2,m6,1), commentalo(m7,"(Christoffel seconda specie)"), m8: fa_r1222(m2,listavariabili), m9: fa_r2222(m2,listavariabili), if controllo then print("Inizia r22"), ma: traccia(m8,1,4), commentalo(ma,"(Ricci totalmente covariante)"), mb:[ratsimp(sqrt(abs(determinant(m2[1])))), ["sqrt(|determinant(g22)|)",nd]], costanti:[ [8*%pi*Gw/cw^4,["kweinstein",nd]], [4*%pi/Lw,["muwz",nd]], [Lw/(4*%pi*cw^2),["epswz",nd]], [cw^2/Lw,["kwcou",nd]], [bfloat(299792458),["[m/s] cwluce",nd] ], [bfloat(10000000),["[C^2/(kg*m)] Lwnumerica",nd]], [bfloat(22468879468420441/2500000), ["[kg*m^3/(s*C)^2] kwcoulomb",nd]], [bfloat(4*%pi/10000000), ["[kg*m/C^2] ossia [Henry/m] muwzero ",nd]], [bfloat(7*8*729*773),["[s] awgregoriano",nd]], [bfloat(667428/10^16), ["[m^3/(kg*s^2)] Gwuniversale",nd]], [bfloat(60221415*10^16),["[adim.] nwavogadro",nd]], [bfloat(1602176487/10^28),["[C] qwelet",nd]], [bfloat(91093826/10^38),["[kg] mwelet",nd]], [bfloat(166053886/10^35),["[kg] mwuatom",nd]], [bfloat(149597870700),["[m] uwastro",nd]], [bfloat(19891*10^26),["[kg] mwsole",nd]], [bfloat(19891*10^26/332946),["[kg] mwterra",nd]], [bfloat(73483*10^18),["[kg] mwluna",nd]], [bfloat(6371*10^3),["[m] rwterra",nd]] ], metrica:[listavariabili,m2,m3,m4,m5,m6,m7,m8,m9,ma,mb, costanti,7*%pi*%gamma], infometrica(), metrica)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Per conoscere il significato dei vari elementi della lista del risultato della fa_metrica ... [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ infometrica():=block([], print("Ha creato un vettore di piu' di undici elementi:"), print("[1] : lista delle variabili"), print("[2] : tensore metrico covariante"), print("[3] : tensore metrico controvariante"), print("[4] : derivate prime del tens. metrico cov."), print("[5] : derivate seconde del tens. m. cov."), print("[6] : simboli di Christoffel di prima specie"), print("[7] : simboli di Christoffel di seconda specie"), print("[8] : Riemann col solo primo indice controvariante"), print("[9] : Riemann totalmente covariante"), print("[10]: Ricci totalmente covariante"), print("[11]: sqrt(abs(determinate del tens.metr.cov.))"), print("[12...] : varie costanti utili...") )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("fa_metrica(mg,listavariabili)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] IMPORTANTE: L'ultimo valore della lista della metrica e' sempre lo stesso e serve a capire se la lista della metrica e' veramente stata creata dalla funzione fa_metrica. Usando la nonmetricap si puo' controllare se la lista passata in argomento e' veramente una lista della metrica. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ nonmetricap(metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ nonmetricap(metrica):=block([errata], if not(listp(metrica)) then ( print("Errore: la metrica deve essere una lista"), return(true)), errata:is(metrica[length(metrica)]#(7*%pi*%gamma)), if errata then print("Questa non e' una metrica !"), return (errata))$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("nonmetricap(metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ diffcov(tn,metrica,nome)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ diffcov(tn,metrica,nome):=block([indi,o,ch122,tr,lp,j,temp], if not(tensorp(tn)) then return("Errore: non tensore"), if nonmetricap(metrica) then return("Errore: non metrica"), indi:indici(tn), o:ordine(tn), if dimensione(tn)#dimensione(metrica[2]) then return("Errore, dimensioni incongruenti"), ch122:metrica[7], tr:rest(fa_diff(tn,metrica[1],"-"),-1), lp:makelist(mod(j,o+1)+1,j,1,o+1), lp[1]:1,lp[o+1]:2, for j:1 thru o do ( if mod(indi[j],2)=0 then ( tr:tr-rest(permuta(scala(ch122,1,tn,j),lp,o),-1) ) else ( tr:tr+rest(permuta(scala(ch122,2,tn,j),lp,o),-1) ), temp:lp[j],lp[j]:lp[j+1],lp[j+1]:temp ), endcons(append(indi, [8,nome,dimensione(tn)]),ratsimp(tr)) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("diffcov(tn,metrica,nome)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ divergenza(tn,ki,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ divergenza(tn,ki,metrica):=block([k,tm,j], if not(tensorp(tn)) then return("Errore: non tensore"), if not(numberp(ki)) then return("Errore: non numero intero"), if nonmetricap(metrica) then return("Errore: non metrica"), k:floor(ki), if 1>k then return("Errore: indice non positivo"), j:indici(tn), if k>length(j) then return("Errore: indice troppo elevato"), if mod(j[k],2)=1 then tm:diffcov(tn,metrica,"(div)") else ( tm:scala(metrica[3],1,tn,k), tm:diffcov(tm,metrica,"(div)")), traccia(tm,k,ordine(tm)) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("divergenza(tn,ki,metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: section start ] @ knbl22a(info)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ knbl22a(info):=block([Materiaw,Roqw,Deltaw,Sigqw,g22,av2, Kretschmann], Materiaw:Gw*(2*Mw*rw-Qw^2/Lw)/cw^2, Roqw:rw^2+(aw*hw)^2, Deltaw:rw^2-Materiaw+aw^2, Sigqw:(rw^2+aw^2)^2-aw^2*Deltaw*(1-hw^2), g22:ratsimp(diag_matrix(cw^2*(Deltaw-aw^2*(1-hw^2))/Roqw, -Roqw/Deltaw, -Roqw/(1-hw^2),-Sigqw*(1-hw^2)/Roqw)), g22[1,4]:aw*cw*Materiaw*(1-hw^2)/Roqw, g22[4,1]:g22[1,4], g22:ratsimp(g22), av2:[rw*Qw*cw^2/(Lw*rw^2+Lw*(aw*hw)^2),0,0, -Qw*cw*rw*aw*(1-hw^2)/(Lw*rw^2+Lw*(aw*hw)^2)], Kretschmann:8*Gw^2*( rw^4*(7*Qw^4-12*Lw*Mw*Qw^2*rw+6*(Lw*Mw)^2*rw^2)- 2*(aw*hw)^2*rw^2*(17*Qw^4- 60*Lw*Mw*Qw^2*rw+45*(Lw*Mw)^2*rw^2)+ (aw*hw)^4*(7*Qw^4-60*Lw*Mw*Qw^2*rw+90*(Lw*Mw)^2*rw^2)- 6*(aw*hw)^6*(Lw*Mw)^2)/(cw^4*Lw^2*((aw*hw)^2+rw^2)^6), if stringp(info) then ( print("Tensore metrico ",info), print("Coordinate usate : [tw,rw,hw,pw]"), print("Costanti : cw,Gw,Lw"), print("Invarianti : Mw,Qw,aw"), print("Non sono nulli :"), print(g22[1,1]," ossia [1,1];"), print(g22[2,2]," ossia [2,2];"), print(g22[3,3]," ossia [3,3];"), print(g22[4,4]," ossia [4,4];"), print(g22[4,1]," ossia [4,1] ossia [1,4];"), print(av2," ossia Potenziale Vettore Elettromagnetico;"), print(Kretschmann," ossia invariante quadratico;") ), return ([ratsimp(g22),[tw,rw,hw,pw],av2,Kretschmann]))$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("knbl22a(info)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Versione apparentemente piu' semplice ma con uso di funzioni trigonometriche che rendono difficili, per Maxima, le semplificazioni delle formule [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ knbl22b(info)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ knbl22b(info):=block([g22], g22:matrix( [1-(2*m*r-q^2)/(r^2+a^2-a^2*sin(h)^2), 0,0,-(a*(q^2-2*m*r)*sin(h)^2)/(r^2+a^2-a^2*sin(h)^2)], [0,-(r^2+a^2-a^2*sin(h)^2)/(r^2-2*m*r+q^2+a^2),0,0], [0,0,-(r^2+a^2-a^2*sin(h)^2),0], [-(a*(q^2-2*m*r)*sin(h)^2)/(r^2+a^2-a^2*sin(h)^2),0,0, -(sin(h)^2*((r^2+a^2)^2 - sin(h)^2*a^2*(r^2-2*m*r+q^2+a^2)))/ (r^2+a^2-a^2*sin(h)^2)]), if stringp(info) then ( print("Tensore metrico ",info), print("Coordinate usate : [t,r,h,p]"), print("Invarianti : m,q,a"), print("Non sono nulli :"), print(g22[1,1]," ossia [1,1];"), print(g22[2,2]," ossia [2,2];"), print(g22[3,3]," ossia [3,3];"), print(g22[4,4]," ossia [4,4];"), print(g22[4,1]," ossia [4,1] ossia [1,4];")), return([trigsimp(g22),[t,r,h,p]]))$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("knbl22b(info)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] @ tnsemplifica(tn)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tnsemplifica(tn):=block([j], if mod(ordine(tn),2)=0 then ( tn[1]:ratsimp(tn[1]), print("semplificato pari")) else ( for j:1 step 1 thru dimensione(tn) do ( tn[j]:ratsimp(tn[j])), print("semplificato dispari")) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tnsemplifica(tn)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ semplimetrica(metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ semplimetrica(metrica):=block([j,nk], if nonmetricap(metrica) then return("Errore: non metrica"), print("Semplifica la metrica : coordinate ",metrica[1]), for nk:2 step 1 thru length(metrica)-1 do tnsemplifica(metrica[nk]), print("Semplificazione finita") )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("semplimetrica(metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Per semplificare un singolo tensore o per semplificare l'intera metrica quando CI SONO funzioni trigonometriche... [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tnsemplificatrig(tn)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tnsemplificatrig(tn):=block([j], if mod(ordine(tn),2)=0 then ( tn[1]:trigsimp(tn[1]), print("semplificato pari")) else ( for j:1 step 1 thru dimensione(tn) do ( tn[j]:trigsimp(tn[j])), print("semplificato dispari")) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tnsemplificatrig(tn)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ semplimetricatrig(metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ semplimetricatrig(metrica):=block([j,nk], if nonmetricap(metrica) then return("Errore: non metrica"), print("Semplifica la metrica : coordinate ",metrica[1]), for nk:2 step 1 thru length(metrica)-1 do tnsemplificatrig(metrica[nk]), print("Semplificazione finita") )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("semplimetricatrig(metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ fondetatb(ta,tb,nome)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ fondetatb(ta,tb,nome):=block([ltna,na,ina,ltnb,nb,inb, ltnv,tab], if (not tensorp(ta)) then ( print("Non tensore primo argomento"), return ([]) ), if (not tensorp(tb)) then ( print("Non tensore secondo argomento"), return ([]) ), if not(dimensione(ta)=dimensione(tb)) then ( print("Tensori di dimensione diversa"), return ([]) ), ltna:listadatensore(ta), ltnb:listadatensore(tb), na:length(ltna), nb:length(ltnb), tab=[0], ltnv:makelist(0,na*nb), for k:1 step 1 thru na do( for j:1 step 1 thru nb do (ltnv[j+(k-1)*nb]:ltna[k]*ltnb[j])), ina:rest(ta[length(ta)],-2), inb:rest(tb[length(tb)],-2), tab:tensoredalista(ltnv,append(ina,inb),nome,dimensione(ta)), return (tab) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("fondetatb(ta,tb,nome)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Questa funzione cambiatipi, cambia il sesso degli indici del tensore tn passato come primo argomento. Bisogna specificare la lista dei nuovi tipi degli indici per cui, se gli indici vecchi sono di tipo diverso da quello voluto, viene fatto il cambiamento. Come terzo argomento va passata la metrica da cui trarre il tensore metrico totalmente femminile ossia covariante ed il tensore metrico totalmente maschile ossia controvariante Questa funzione e' molto comoda perche' evita all'utilizzatore di questa libreria la conoscenza di come fare questa trasformazione usando altre funzioni di questa stessa libreria. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ cambiatipi(tn,nuovitipi,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ cambiatipi(tn,nuovitipi,metrica):= block([wt,pwt,mwt, itrovati,litr,miaper,i,j,k], if nonmetricap(metrica) then return("Errore: non metrica"), wt:tn, itrovati:indici(wt), litr:length(itrovati), if is(litr#length(nuovitipi)) then ( print(sconcat("Errata lista nuovi tipi ", litr," # ",length(nuovitipi))), print("Errata lista nuovi tipi"), return (wt) ), for j:1 step 1 thru litr do ( if is(mod(nuovitipi[j],2)#mod(itrovati[j],2)) then ( miaper:makelist(i,i,litr), k:miaper[1], miaper[1]:miaper[j], miaper[j]:k, pwt:permuta(wt,miaper,"xPerm"), if is(mod(nuovitipi[j],2)=0) then ( mwt:scala(metrica[2],2,pwt,1)) else ( mwt:scala(metrica[3],2,pwt,1)), wt:permuta(mwt,miaper,"xPerm")) ), return (ratsimp(wt)))$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("cambiatipi(tn,nuovitipi,metrica)",libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Funzione per il cambiamento del sistema di coordinate [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Bisogna specificare ovviamente il tensore tn da modificare esprimendolo, come risultato, nelle nuove coordinate, poi le funzioni che esprimono le vecchie coordinate in funzione delle nuove ossia la lista InFunDiN , poi i simboli delle nuove coordinate ossia la lista NuoveC ed infine la metrica valida per il tensore da modificare, usata per sapere quali erano le espressioni delle vecchie coordinate [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ cambiacoord(tn,InFunDiN,NuoveC,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ cambiacoord(tn,InFunDiN,NuoveC,metrica):=block([MD, wt,pwt,mwt,itrovati,litr,miaper,i,j,k], if nonmetricap(metrica) then return("Errore: non metrica"), MD:jacobian(InFunDiN,NuoveC), tTMD:tmat21(transpose(MD),metrica), tIMD:tmat12(invert(MD),metrica), wt:tn, itrovati:indici(wt), litr:length(itrovati), for j:1 step 1 thru litr do ( miaper:makelist(i,i,litr), k:miaper[1], miaper[1]:miaper[j], miaper[j]:k, pwt:permuta(wt,miaper,"xPerm"), if is(mod(itrovati[j],2)=0) then ( mwt:scala(tTMD,2,pwt,1)) else ( mwt:scala(tIMD,2,pwt,1)), wt:permuta(mwt,miaper,"xPerm")), for j:1 step 1 thru length(metrica[1]) do ( mwt:trigsimp(ev(wt,metrica[1][j]=InFunDiN[j])), wt:mwt), return (wt) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("cambiacoord(tn,InFunDiN,NuoveC,metrica)", libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Dato un tensore di qualsiasi rango la ticambiotutto calcola il tensore che ha tutti gli indici di tipo diverso ossia se un dato indice e' di tipo covariante ossia femminile il corrispondente indice sara' di tipo controvariante ossia maschile e viceversa. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Sarebbe possibile fare questo calcolo usando la cambiatipi(tn,nuovitipi,metrica) che e' piu' flessibile e sfrutta varie funzioni di questa libreria ma la ticambiotutto applica altre funzioni e dunque potrebbe servire anche per fare la verifica dello stesso calcolo fatto con la cambiatipi. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ ticambiotutto(tn,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ ticambiotutto(tn,metrica):=block([lista,litipi, gff,gmm,listan,tipin,i], if nonmetricap(metrica) then return("Errore: non metrica"), lista:listadatensore(tn), litipi:indici(tn), gff:metrica[2][1], gmm:metrica[3][1], listan:cambiasesso(lista,litipi,gff,gmm), tipin:makelist((2+mod(1+litipi[i],2)),i,length(litipi)), return(tensoredalista(listan,tipin,"tipicambiati", dimensione(tn))) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("ticambiotutto(tn,metrica)", libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] La cambiasesso(lista,litipi,gff,gmm) e' la funzione applicata dalla ticambiotutto(tn,metrica) ma, dato che lavora su tensori scritti in forma di lista ed ha bisogno di ricevere in input l'indicazione del tipo di indici da attribuire alla lista , consente calcoli esplorativi senza bisogno di precalcolare la metrica ossia fare derivate. Per questo scopo la cambiasesso deve ricevere come terzo argomento gff ossia la matrice da considerare come tensore metrico totalmente covariante ossia totalmente femminile e come quarto argomento gmm ossia la inversa della gff che dunque considera come tensore metrico controvariante ossia totalmente maschile. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ cambiasesso(lista,litipi,gff,gmm)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ cambiasesso(lista,litipi,gff,gmm):=block([base,quanti, ncifre,motipi,listan,lidove,aa,vale,lecifre, ll,j,h,k], if not(listp(lista)) then return( "Non lista il primo argomento"), if not(listp(litipi))then return( "Non lista il secondo argomento"), if not(matrixp(gff)) then return( "Non matrice il terzo argomento"), base:length(gff), quanti:length(lista), if is(quanti#base^length(litipi)) then return(["Errore quanti :",quanti, " base^length(litipi) :",base^length(litipi)]), ncifre:length(litipi), motipi:makelist(mod(litipi[1+ncifre-i],2),i,ncifre), listan:makelist(0,quanti), lidove:makelist(0,quanti), for k:1 step 1 thru quanti do( vale:k-1, lecifre:makelist(0,ncifre), for j:1 step 1 thru ncifre do( aa:mod(vale,base), vale:(vale-aa)/base, lecifre[j]:aa+1 ), lidove[k]:lecifre ), for k:1 step 1 thru quanti do( aa:lista[k], lecifre:lidove[k], for h:1 step 1 thru quanti do ( ll:lidove[h], vale:aa, for j:1 step 1 thru ncifre do( if motipi[j]=0 then vale:vale*gmm[ll[j],lecifre[j]] else vale:vale*gff[ll[j],lecifre[j]] ), listan[h]:listan[h]+vale ) ), return(listan) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("cambiasesso(lista,litipi,gff,gmm)", libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Questa funzione, rapportolistetensori, serve ad evitare sbrodolate nella stampa dei tensore. Se credo che due tensori sono tra loro uguali o almeno proporzionali, faccio il controllo e se veramente lo sono ottenngo stime molto concise... [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ rapportolistetensori(ta,tb)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ rapportolistetensori(ta,tb):=block([lta,ltb,ltt, ra,rb,nuni], if not(tensorp(ta)) then return("Primo argomento NON tensore"), if not(tensorp(tb)) then return("Secondo argomento NON tensore"), if(ordine(ta)#ordine(tb)) then return("Tensori di rango diverso"), if(dimensione(ta)#dimensione(tb)) then return("Dimensione spaziotemporale diversa"), lta:listadatensore(ta), ltb:listadatensore(tb), ltt:makelist(0,length(lta)), nuni:0, for j:1 step 1 thru length(ltt) do( ra:ratsimp(lta[j]), rb:ratsimp(ltb[j]), if is(rb=0) then ( if is(ra=0) then (ltt[j]:1, nuni:nuni+1) else ltt[j]:ra/DivisoZero ) else (ltt[j]:ratsimp(ra/rb), if is(ltt[j]=1) then nuni:nuni+1)), if nuni=length(ltt) then return(sconcat("Tutti uguali ",nuni," elementi")) else return(ltt) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("rapportolistetensori(ta,tb)", libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Questa funzione, tdueantisim, fa il tensore antisimmetrico di un tensore assegnato che deve essere di rango due ossia essere una matrice. Se i tipi dei due indici non sono uguali li rende provvisoriamente uguali e poi, dopo avere antisimmetrizzato, li rimette come erano nel tensore assegnato. Si tratta di una funzione utilissima per calcolare il tensore elettromagnetico partendo dalla derivata qualificata del potenziale vettore del campo elettromagnetico. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tdueantisim(tn,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tdueantisim(tn,metrica):=block([indi,inda,indb, asim,pro], if not(tensorp(tn)) then return("Primo argomento NON tensore"), if nonmetricap(metrica) then return("Errore: non metrica"), indi:indici(tn), if is(length(indi)#2) then return("Tensore non di rango 2"), inda:2-mod(indi[1],2), indb:2-mod(indi[2],2), if inda=indb then ( asim:ratsimp(tn[1]-transpose(tn[1])), pro:[asim,[inda,indb,"Asim",dimensione(tn)]] ) else ( asim:cambiatipi(tn,[inda,inda],metrica), pro:ratsimp(asim[1]-transpose(asim[1])), asim:[pro,[inda,inda,"Asim",dimensione(tn)]], pro:cambiatipi(asim,[inda,indb],metrica) ), return(pro) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tdueantisim(tn,metrica)", libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Questa sembrerebbe una funzione piuttosto insolita ossia, dato un tensore di rango due ossia una matrice, sottrargli un opportuno tensore ( in pratica il tensore metrico ) fatto in modo che la traccia del tensore risultato sia nulla. Questa funzione e' FONDAMENTALE per costruire il tensore Energia Impulso del campo elettromagnetico che compare nell'equazione di Einstein per definire il corretto valore del tensore di Gregorio Ricci-Curbastro. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ tduetracciazero(tn,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ tduetracciazero(tn,metrica):=block([tmisto,indi, traccia,tnotra], if not(tensorp(tn)) then ( print("Errore: Primo arg. NON tensore"), return(false) ), if nonmetricap(metrica) then ( print("Errore: Secondo arg. NON metrica"), return(false) ), indi:indici(tn), if is(length(indi)#2) then ( print("Errore: tensore non di rango 2"), return(false) ), tmisto:cambiatipi(tn,[1,2],metrica), traccia:ratsimp(mat_trace(tmisto[1])/dimensione(tn)), tmisto[1]:ratsimp(tmisto[1]-traccia*ident(dimensione(tn))), tnotra:cambiatipi(tmisto,indi,metrica), return(ratsimp(tnotra)) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("tduetracciazero(tn,metrica)", libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Per trovare il tensore energia impulso NON NORMALIZZATO, partendo da un potenziale vettore, ossia un tensore di rango 1, faccio questa comoda funzioncina. Evito di obbligare l'utilizzatore di questa libreria a sapere come fare questo calcolo.... [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] @ fa_tenergiaimpulso(tpotvet,metrica)[wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ fa_tenergiaimpulso(tpotvet,metrica):=block([pvf, tnsff,tcampoff,tcampomf,tqmf], if not(tensorp(tpotvet)) then ( print("Errore: Primo arg. NON tensore"), return(false) ), if nonmetricap(metrica) then ( print("Errore: Secondo arg. NON metrica"), return(false) ), if is(length(indici(tpotvet))#1) then return("Tensore non di rango 1"), pvf:cambiatipi(tpotvet,[2],metrica), tnsff:ratsimp(diffcov(pvf,metrica,"gradiente")), tcampoff:tdueantisim(tnsff,metrica), tcampomf:cambiatipi(tcampoff,[1,2],metrica), tqmf:scala(tcampomf,2,tcampomf,1), return(tduetracciazero(tqmf,metrica)) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ libmia:cons("fa_tenergiaimpulso(tpotvet,metrica)", libmia)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] In complesso le funzioni attualmente definite in questa libreria sono queste: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ libmia:sort(libmia); /* [wxMaxima: input end ] */ /* [wxMaxima: subsect start ]Per usare questo file con http://maxima.sourceforge.net/ cancellare l'estensione .html e lasciargli l'estensione .wxm Amen versione 3 del generatore della lib. tensoriale |
Verifiche della validità di questa libreria
Verifica della prima identità di Luigi Bianchi
A pag. 344, formula (92,4), per esempio il Landau afferma:
La somma ciclica di qualsiasi terna di indici del tensore di Riemann r2222 deve essere sempre nulla.In altre parole tenendo fisso il primo indicea
e facendo girare gli altri treb
,c
ed
si dovrebbe ottenere, scrivendo in pseudolinguaggio maximese :r2222[1][a,b][c,d] + r2222[1][a,d][b,c] + r2222[1][a,c][d,b] == 0
Ma applichiamo in concreto questa libreria usando la funzione intrinseca di wxMaxima
rest(lista,-1)
che serve a scartare l'ultimo elemento della lista che contiene il tensore ossia l'elemento che contiene le informazioni sulla natura del tensore:print( rest(r2222,-1)+ rest(permuta(r2222,[1,3,4,2],""),-1)+ rest(permuta(r2222,[1,4,2,3],""),-1))$
Si deve ottenere una montagna di zeri...
Verifica della seconda identità di Luigi Bianchi
Vedere: http://it.wikipedia.org/wiki/Tensore_di_Riemann e http://en.wikipedia.org/wiki/Einstein_tensor e da meditare ed applicare questa interessantissima pagina che spiega come fa a curvare lo spazio non un campo elettromagnetico ma un campo scalare ossia generato da un potenziale scalare e non da un potenziale vettore: http://en.wikipedia.org/wiki/Scalar_field_solution
La somma ciclica di qualsiasi terna di indici del tensore di Riemann r22228 deve essere sempre nulla.In altre parole tenendo fisso il primo ed il secondo indicea
eb
e facendo girare gli altri trec
,d
ede
si dovrebbe ottenere, scrivendo in pseudolinguaggio maximese :r12228[a][b,c][d,e] + r12228[a][b,e][c,d] + r12228[a][b,d][e,c] == 0
e lo stesso dicasi, per esempio, se si abbassa il primo indice ossia si deriva in modo covariante r2222 e non r1222
r22228[a][b,c][d,e] + r22228[a][b,e][c,d] + r22228[a][b,d][e,c] == 0
Usiamo dunque, per esempio, questa libreria per calcolare la derivata covariante di
r1222
. Si fa così usando la funzione intrinseca di wxMaximaratsimp( ... )
che serve a fare semplificazioni di espressioni algebriche razionali...r12228:ratsimp(diffcov(r1222,metrica,"r12228"))$
Notare che è un calcolo lungo perché si tratta di calcolare un tensore del quinto ordine ossia con 45 ossia 1024 componenti!
Noto
r12228
, ecco come va calcolata la seconda identità di Luigi Bianchi con questa libreria ossia permutando gli indici. In quattro dimensioni questo tensore del quinto ordine ha 1024 componenti che dovrebbero risultare tutte nulle, URKA!idlbianchi:rest(r12228,-1)+ rest(permuta(r12228,[1,2,4,5,3],""),-1)+ rest(permuta(r12228,[1,2,5,3,4],""),-1)$
E naturalmente si avrebbe ottenuta una valanga di 1024 zeri anche lavorando non a partire da
r1222
ma dar2222
ossia:idlbianchif:rest(r22228,-1)+ rest(permuta(r22228,[1,2,4,5,3],""),-1)+ rest(permuta(r22228,[1,2,5,3,4],""),-1)$
http://www.elegio.it/max/