[MatLab] area di un ciclo di isteresi
ciao a tutti.
devo calcolare l'area di un ciclo di isteresi come questo: http://img13.imageshack.us/img13/1554/29017740.jpg
so che è molto irregolare e allora per limitare l'errore (che comunque ci sarà) ho pensato di considerare i quattro punti notevoli:
il punto che presenta la minore delle sigma positive
il punto ad epsilon massima
il punto che presenta la maggiore delle sigma negative
il punto ad epsilon minima.
E chiamiamo questi punti, rispettivamente, S' - emax - S'' - emin.
Se il "delta area" è uguale a [("epsilon con i" - "epsilon con i-1") * ("sigma con i" + "sigma con i-1")/2 ], allora per il computo dell'area totale bisognerà sommare i valori assoluti "delta area" per i punti compresi tra (S' ed emax) e per quelli tra (S'' ed emin), mentre bisognerà sottrarre i valori assoluti "delta area" per i punti compresi tra (emax ed S'') e per quelli tra (emin ed S').
i 4 punti li ho trovati. ora non so come dire mettere comporre i 4 delta area.
in precedenza per calcolare aree composte da segmenti avevo usato questo
la struttura è identica a quella che voglio usare adesso, ma non so come comportarmi con gli estremi di $q$
devo calcolare l'area di un ciclo di isteresi come questo: http://img13.imageshack.us/img13/1554/29017740.jpg
so che è molto irregolare e allora per limitare l'errore (che comunque ci sarà) ho pensato di considerare i quattro punti notevoli:
il punto che presenta la minore delle sigma positive
il punto ad epsilon massima
il punto che presenta la maggiore delle sigma negative
il punto ad epsilon minima.
E chiamiamo questi punti, rispettivamente, S' - emax - S'' - emin.
Se il "delta area" è uguale a [("epsilon con i" - "epsilon con i-1") * ("sigma con i" + "sigma con i-1")/2 ], allora per il computo dell'area totale bisognerà sommare i valori assoluti "delta area" per i punti compresi tra (S' ed emax) e per quelli tra (S'' ed emin), mentre bisognerà sottrarre i valori assoluti "delta area" per i punti compresi tra (emax ed S'') e per quelli tra (emin ed S').
i 4 punti li ho trovati. ora non so come dire mettere comporre i 4 delta area.
in precedenza per calcolare aree composte da segmenti avevo usato questo
k=numel(x); for q=1:k-1 v(q)=(x(q+1)-x(q))*(y(q+1)+y(q))/2;end r=sum(v);
la struttura è identica a quella che voglio usare adesso, ma non so come comportarmi con gli estremi di $q$
Risposte
Onestamente ho capito poco del metodo che vorresti usare per calcolare l'area. Magari prova a rispiegarti (e magari utilizza in maniera opportuna la modalità di inserimento formule
).
Ti propongo un diverso approccio, di tipo probabilistico. Considera il quadrato contenente la tua figura e genera $n$ punti in maniera casuale uniformamemente distribuiti nel quadrato e denota con $L$ il lato. Conta quanti punti di quelli generati cadono nella figura. Se $C$ è il numero di punti che sono caduti nella figura, allora la sua area può essere approssimata da
$L^2*C/n$. Ovviamente più $n$ è grande più la stima è precisa. Ti posto un codice che permette di calcolare l'area di un quadrato di lato $l$ contenuto in un quadrato di lato $L$ aventi l'origine come vertice comune.
Nel tuo caso potresti prendere $L$ come un qualcosa che sia più grande del valore assoluto di S' - emax - S'' - emin. La cosa un filo più complicata nel tuo caso è scrivere la condizione dell'if, ossia la condizione per cui un punto sta all'interno della tua figura, ma non mi sembra impossibile da fare in tempi ragionevoli.

Ti propongo un diverso approccio, di tipo probabilistico. Considera il quadrato contenente la tua figura e genera $n$ punti in maniera casuale uniformamemente distribuiti nel quadrato e denota con $L$ il lato. Conta quanti punti di quelli generati cadono nella figura. Se $C$ è il numero di punti che sono caduti nella figura, allora la sua area può essere approssimata da
$L^2*C/n$. Ovviamente più $n$ è grande più la stima è precisa. Ti posto un codice che permette di calcolare l'area di un quadrato di lato $l$ contenuto in un quadrato di lato $L$ aventi l'origine come vertice comune.
clear all, close all n=1000; L=2; l=0.5; x=L*rand(1,n); y=L*rand(1,n); cont=0; figure(1); for i=1:n if x(i)<=l && y(i)<=l cont=cont+1; hold on plot(x(i),y(i),'.r'); else hold on plot(x(i),y(i),'.g'); end end area_stimata=L^2*cont/n errore=abs(l^2-area_stimata)
Nel tuo caso potresti prendere $L$ come un qualcosa che sia più grande del valore assoluto di S' - emax - S'' - emin. La cosa un filo più complicata nel tuo caso è scrivere la condizione dell'if, ossia la condizione per cui un punto sta all'interno della tua figura, ma non mi sembra impossibile da fare in tempi ragionevoli.
quindi potrei traslare l'origine degli assi al valore minimo del mio ciclo di isteresi (si può fare?), creare un quadrato come il tuo e poi parametrizzare la mia figura. purtroppo non ho idea di come si possa fare quest'ultima cosa.
la mia idea era di usare il metodo dei rettangoli applicato alla figura in soldoni.
qui comunque ho disegnato i due metodi: http://img705.imageshack.us/img705/6070/wp000002r.jpg
la mia idea era di usare il metodo dei rettangoli applicato alla figura in soldoni.
qui comunque ho disegnato i due metodi: http://img705.imageshack.us/img705/6070/wp000002r.jpg
La traslazione non è necessaria; basta traslare la distribuzione dei punti. Ho pensato un pò a come si potrebbe tradurre la condizione dell'if ma così su due piedi non mi sono venute idee. Però potrei aver trovato quello che fa per te. Prova a vedere il comando polyarea(x,y). Dati i vettori x e y delle coordinate calcola l'area del poligono avente come coordinate dei vertici i vettori x e y.
A prima vista sembrerebbe possibile estrarre, per ogni valore di stress, uno strain minimo e massimo di rottura. Sono due linee spezzate che si incontreranno nei valori di minimo e massimo dello stress (e in numerosi altri punti nella tua figura). Concatenando queste due linee spezzate potresti usare polyarea (che non credo dia valori corretti nel caso ci fossero autointersezioni). Non avendo idea di quali dati tu abbia esattamente a disposizione non saprei dire se questo metodo è fattibile nel tuo caso o se sia sufficiente usare polyarea sui dati in tuo possesso senza passaggi intermedi.
è questo il punto. con polyarea il discorso sarebbe chiuso. purtroppo non ho dati di area sperimentali con cui comparare i miei risultati. infatti il mio scopo sarebbe quello di dimostrare che le aree (ovvero il lavoro assorbito in un ciclo) sono costanti ciclo dopo ciclo.
il file su cui mi baso è fatto così: http://img46.imageshack.us/img46/3218/immagineim.jpg
i miei input sono le colonne evidenziate in giallo.
ho iniziato a lavorare sull'elaborazione del singolo ciclo; in un secondo momento avrei creato un comando per svolgere il singolo compito per ogni ciclo e infine plottare il tutto (se mi viene fuori una retta con pendenza "leggera" sono a posto).
il file su cui mi baso è fatto così: http://img46.imageshack.us/img46/3218/immagineim.jpg
i miei input sono le colonne evidenziate in giallo.
ho iniziato a lavorare sull'elaborazione del singolo ciclo; in un secondo momento avrei creato un comando per svolgere il singolo compito per ogni ciclo e infine plottare il tutto (se mi viene fuori una retta con pendenza "leggera" sono a posto).
Onestamente non ho mai usato polyarea, ma ho scoperto la sua esistenza pensando al tuo problema. Apatriarca ha sollevato la questione sulla possibilità che esso non restituisca valori corretti in caso di autointersezioni della figura. Ho provato a testare su un esempio semplice e in effetti sembra che polyarea non funzioni per poligoni che si autointersechino. Ho trovato però un comando (inpolygon) che date le ascisse e le ordinate di una serie di punti e le ascisse e le ordinate dei vertici di un poligono stabilisce se il punto è all'interno del poligono o no. In questo modo puoi usare il metodo montecarlo che ti ho descritto prima per calcolare l'area.
Ti descrivo brevemente quello che ho fatto: xv e yv sono le coordinate dei vertice. Il poligono che esce è costituito da due triangoli con un vertice in comune. Il vertice ha coordinate $(5,4)$. In questo modo è facile calcolare l'area vera della figura come somma delle aree dei due triangoli, che a loro volta vengono facilmente calcolate con la regola del determinante (vedi variabile area_vera). Con L determino il lato di un quadrato che contine la figura, mentre x e y sono la distribuzione di punti. Quindi uso la function inpoligon che crea una matrice fatta di 0 e 1 a seconda che il punto in posizione $(i,j)$ corrispondente al punto di coordinate $x(i),y(j)$ appartiene o no al poligono. Contando (domando sum) quanti 1 ci sono nella matrice si ha il numero di punti che sono caduti dentro il poligono. Disegno in rosso i punti interni, in blu quelli esterni e stimo l'area. Poi disegno in verde il bordo del poligono. Come puoi vedere area_stimata e area_vera hanno valori "simili", mentre polyarea restituisce 0.
Attendo solo a scegliere L in maniera corretta. Spero che funzioni e di non aver scritto cavolate
n=50000; xv = [2 8 7 4 2]; yv = [2 5 2 5 2]; L=max( max(xv)-min(xv), max(yv)-min(yv))+1; x=min(xv)+L*rand(1,n); y=min(yv)+L*rand(1,n); figure(1); [in on] = inpolygon(x,y,xv,yv); cont=sum(in)+sum(on); plot(x(~in),y(~in),'bo',x(in),y(in),'r.') area_stimata=L^2*cont/n hold on plot(xv,yv,'-*g') T1=[2 5 4;2 4 5;1 1 1]; T2=[5 7 8; 4 2 5; 1 1 1]; area_vera=(det(T1)+det(T2))/2 area_pol=polyarea(xv,yv)
Ti descrivo brevemente quello che ho fatto: xv e yv sono le coordinate dei vertice. Il poligono che esce è costituito da due triangoli con un vertice in comune. Il vertice ha coordinate $(5,4)$. In questo modo è facile calcolare l'area vera della figura come somma delle aree dei due triangoli, che a loro volta vengono facilmente calcolate con la regola del determinante (vedi variabile area_vera). Con L determino il lato di un quadrato che contine la figura, mentre x e y sono la distribuzione di punti. Quindi uso la function inpoligon che crea una matrice fatta di 0 e 1 a seconda che il punto in posizione $(i,j)$ corrispondente al punto di coordinate $x(i),y(j)$ appartiene o no al poligono. Contando (domando sum) quanti 1 ci sono nella matrice si ha il numero di punti che sono caduti dentro il poligono. Disegno in rosso i punti interni, in blu quelli esterni e stimo l'area. Poi disegno in verde il bordo del poligono. Come puoi vedere area_stimata e area_vera hanno valori "simili", mentre polyarea restituisce 0.
Attendo solo a scegliere L in maniera corretta. Spero che funzioni e di non aver scritto cavolate

Il problema del metodo Montecarlo è che ha una convergenza molto lenta e che le performance dipendono anche da quanto la superficie presa in considerazione approssimi quella di cui si vuole calcolare l'area. Ma ha certamente il vantaggio della semplicità.
il metodo montecarlo non mi dispiacerebbe.
anche tenendo un errore "elevato", vorrei arrivare lo stesso ad una soluzione. polyarea ha un errore troppo elevato da quello che ho capito (ho svolto anche io una prova simile alla tua).
non mi serve un algoritmo più di tanto preciso perchè alla fine dovrò dimostrare che l'area di ogni ciclo è costante (quindi se l'errore è uguale per tutti, arriverei lo stesso al mio scopo).
anche tenendo un errore "elevato", vorrei arrivare lo stesso ad una soluzione. polyarea ha un errore troppo elevato da quello che ho capito (ho svolto anche io una prova simile alla tua).
non mi serve un algoritmo più di tanto preciso perchè alla fine dovrò dimostrare che l'area di ogni ciclo è costante (quindi se l'errore è uguale per tutti, arriverei lo stesso al mio scopo).
Non puoi usare un metodo montecarlo per fare quello che desideri. L'errore è del tutto casuale può variare tra esecuzioni successive. Ma il metodo corretto già te l'ho descritto, ti calcoli il bordo del poligono e poi usi polyarea.
dovrebbe funzionare grazie
ciao a tutti.
devo creare una funzione matlab che mi restituisca dei vettori a partire da questo file .mat di esempio: http://img541.imageshack.us/img541/253/immaginezij.jpg
nell'ultima colonna a destra ho il "ciclo" in cui mi trovo. i cicli non sono tutti lunghi uguali e sono in totale $n=3474$. se il ciclo è lungo 50, vorrei come output 2 vettori di eguale lunghezza contenenti i valori corrispondenti nella terza e quarta colonna.
per ogni ciclo compirei una certa operazione (funzione $polyarea$) e salverei il risultato in un altro vettore. poi plotterei il tutto per trovare l'area del ciclo in funzione del ciclo corrispondente.
il punto è che non so come muovermi per la prima parte della programmazione.
fin'ora sono riuscito a calcolare l'area del primo ciclo, ma non so come fare per quella degli altri:
devo creare una funzione matlab che mi restituisca dei vettori a partire da questo file .mat di esempio: http://img541.imageshack.us/img541/253/immaginezij.jpg
nell'ultima colonna a destra ho il "ciclo" in cui mi trovo. i cicli non sono tutti lunghi uguali e sono in totale $n=3474$. se il ciclo è lungo 50, vorrei come output 2 vettori di eguale lunghezza contenenti i valori corrispondenti nella terza e quarta colonna.
per ogni ciclo compirei una certa operazione (funzione $polyarea$) e salverei il risultato in un altro vettore. poi plotterei il tutto per trovare l'area del ciclo in funzione del ciclo corrispondente.
il punto è che non so come muovermi per la prima parte della programmazione.
fin'ora sono riuscito a calcolare l'area del primo ciclo, ma non so come fare per quella degli altri:
clear all close all tic esempio=xlsread ('esempio.xls'); save ('esempio') %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% change the name of the file in both lines load ('esempio'); data=esempio; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% strain=data(:,3); stress=data(:,4); cycle=data(:,7); p=1; k=1; for i=1:length(cycle)-1 if cycle(i)==cycle(i+1) e(i)=stress(i); s(i)=strain(i); A=polyarea(e,s); elseif ?????????? end end toc
up
ciao a tutti.
ho un file sotto forma di tabella $"data"$ a partire dal quale devo calcolare delle aree.
di esso uso 3 colonne: $x,y,c$
c va da 1 a 3000 circa (non continuamente; ad esempio manca il 13, il 17, ecc...)
in $c=k$ ad esempio ho n$x$ e n$y$ diverse.
devo calcolare l'area di ogni ciclo a partire dalle ascisse e coordinate corrispondenti.
fin'ora ho partorito questo:
pongo $=0$ ciclo per ciclo tutte le ascisse e ordinate che non hanno sulla stessa riga il $c$ voluto e calcolo l'area con il comando
purtroppo non funziona. avete idee?
ho un file sotto forma di tabella $"data"$ a partire dal quale devo calcolare delle aree.
di esso uso 3 colonne: $x,y,c$
c va da 1 a 3000 circa (non continuamente; ad esempio manca il 13, il 17, ecc...)
in $c=k$ ad esempio ho n$x$ e n$y$ diverse.
devo calcolare l'area di ogni ciclo a partire dalle ascisse e coordinate corrispondenti.
fin'ora ho partorito questo:
strain=data(:,3); stress=data(:,4); cycle=data(:,7); A=[cycle,stress,strain]; c=1; for i=1:length(cycle) if A(i)~=c A(i,2)=0; A(i,3)=0; area(c)=polyarea(A(:,2),A(:,3)); c=c+1; end end x=1:max(cycle)-1; plot(x,area); end
pongo $=0$ ciclo per ciclo tutte le ascisse e ordinate che non hanno sulla stessa riga il $c$ voluto e calcolo l'area con il comando
polyarea(X,Y)
purtroppo non funziona. avete idee?
ciao a tutti
ho questo file .mat: http://img23.imageshack.us/img23/8251/immagineipi.jpg
nella prima riga ho il numero di ciclo.
nella seconda un valore di deformazione.
nella terza un valore di sforzo.
usando il comando $polyarea(x,y)$ dovrei prendere, per ogni ciclo, tutti i valori di sforzo e quelli di deformazione corrispondenti per trovare l'area del singolo ciclo sul diagramma sforzo-deformazione.
alla fine andrei a plottare il tutto per ottenere un diagramma area-numero di ciclo.
non ho idee. per il singolo ciclo sono riuscito ad ottenere l'area (in input gli do un numero di ciclo che mi interessa), ora vorrei rappresentare appunto l'andamento dell'area in funzione del ciclo
ho questo file .mat: http://img23.imageshack.us/img23/8251/immagineipi.jpg
nella prima riga ho il numero di ciclo.
nella seconda un valore di deformazione.
nella terza un valore di sforzo.
usando il comando $polyarea(x,y)$ dovrei prendere, per ogni ciclo, tutti i valori di sforzo e quelli di deformazione corrispondenti per trovare l'area del singolo ciclo sul diagramma sforzo-deformazione.
alla fine andrei a plottare il tutto per ottenere un diagramma area-numero di ciclo.
non ho idee. per il singolo ciclo sono riuscito ad ottenere l'area (in input gli do un numero di ciclo che mi interessa), ora vorrei rappresentare appunto l'andamento dell'area in funzione del ciclo
nella prima riga il numero di ciclo va da 1 a 3000 e passa (alcuni cicli però non esistono; passo, ad esempio, dal ciclo 9 al 14).
all'interno di ogni ciclo ho N coppie di valori (2° e 3° riga della stessa colonna). N non è costante per ogni ciclo: ci sono cicli da 100 coppie, da 30...
all'interno di ogni ciclo ho N coppie di valori (2° e 3° riga della stessa colonna). N non è costante per ogni ciclo: ci sono cicli da 100 coppie, da 30...
Non ho capito che cosa non riesci a fare..
Se è sufficiente vedere la variazione nel valore numerico puoi memorizzare area e numero di ciclo in due vettori che passi alla funzione plot. C'è qualcosa che mi sfugge?
ora vorrei rappresentare appunto l'andamento dell'area in funzione del ciclo
Se è sufficiente vedere la variazione nel valore numerico puoi memorizzare area e numero di ciclo in due vettori che passi alla funzione plot. C'è qualcosa che mi sfugge?
"apatriarca":
Non ho capito che cosa non riesci a fare..
ora vorrei rappresentare appunto l'andamento dell'area in funzione del ciclo
Se è sufficiente vedere la variazione nel valore numerico puoi memorizzare area e numero di ciclo in due vettori che passi alla funzione plot. C'è qualcosa che mi sfugge?
non riesco a dare in pasto a polyarea le coppie di valori.
dovrei dire che finchè il valore nella prima riga è 1, salva i 2 valori sotto come punti $(x,y)$ e con $polyarea$ ricava l'area del ciclo 1. questo per ogni ciclo da 1 alla fine (ricordo che ne manca qualcuno in mezzo).
alla fine con
plot(area)dovrei trovare il grafico $(N,area)$
up
Senza vedere il tuo codice è molto difficile capire cosa stai facendo e cosa ci sia di sbagliato nel tuo metodo.
ciao
ho questo file .mat: http://img834.imageshack.us/img834/3659 ... neovcg.jpg
nella terza e quarta colonna ho rispettivamente i valori di strain e stress che descrivono un'isteresi di un provino.
nell'ultima colonna ho il ciclo in cui mi trovo.
per calcolare l'area voglio usare la funzione $polyarea(x,y)$ applicata al singolo ciclo.
quindi voglio salvare tutte le coppie di valori che hanno nell'ultima colonna della stessa riga identico valore.
questo valore va da 1 a 3474 ma non ci sono tutti i cicli e non hanno tutti la stessa lunghezza
questo è il codice che ho prodotto fin'ora ma mi impalla il pc:
cosa posso fare?
ho questo file .mat: http://img834.imageshack.us/img834/3659 ... neovcg.jpg
nella terza e quarta colonna ho rispettivamente i valori di strain e stress che descrivono un'isteresi di un provino.
nell'ultima colonna ho il ciclo in cui mi trovo.
per calcolare l'area voglio usare la funzione $polyarea(x,y)$ applicata al singolo ciclo.
quindi voglio salvare tutte le coppie di valori che hanno nell'ultima colonna della stessa riga identico valore.
questo valore va da 1 a 3474 ma non ci sono tutti i cicli e non hanno tutti la stessa lunghezza
questo è il codice che ho prodotto fin'ora ma mi impalla il pc:
function [] = Diagramma_Area_Isteresi() %UNTITLED2 Summary of this function goes here % Detailed explanation goes here clear all close all %predo un file di excel e lo converto in uno elaborabile da matlab esempio=xlsread ('esempio.xls'); c=1; %faccio leggere al programma tutti i valori della colonna del ciclo. se è %diverso dall'indice, azzera tutti i valori non appartenenti a quella riga. %con le colonne rimaste uso polyarea. for i=1:length(esempio) if esempio(i,7)~=c esempio(i,:)=0; area(c)=polyarea(esempio(3,:),esempio(4,:)); c=c+1; esempio=xlsread ('esempio.xls'); end end plot(area); end
cosa posso fare?