-
.
posto un piccolo aggiornamento del file di tex, numerato come rev.5.
le modifiche sono solo nei commenti al codice, non nel codice, che rimane quello della rev.4.
nell'interfaccia ho invece applicato il colore ai nomi degli assi principali per renderli dello stesso colore dell'ellisse d'inerzia.
edit: file rimosso perché pubblicata da tex una release più aggiornata.
Edited by reversi - 25/3/2014, 09:14. -
.
Ho aggiunto il controllo massima trazione e massima compressione agli SLU, come suggerito da Zax.
La revisione 6 del file è ora scaricabile dal link già segnalato.CODICEDim Nc_max As Double
Dim Nt_max As Double
maxTrazCompr Nc_max, Nt_max
If Ndt < Nt_max Then
MsgBox "La trazione eccede quella massima ammissibile.", vbOKOnly + vbExclamation, "Errore!!!"
Exit Sub
End If
If Ndt > Nc_max Then
MsgBox "La compressione eccede quella massima ammissibile.", vbOKOnly + vbExclamation, "Errore!!!"
Exit Sub
End IfCODICE'*********************************************************************
' maxTrazCompr
'*********************************************************************
'Determina la massima compressione e la massima trazione allo stato
'limite ultimo.
Public Sub maxTrazCompr(Nc_max As Double, Nt_max As Double)
Dim s As Double: s = 0#
Dim S_g As Double: S_g = 0#
If N_POLI > 0 Then s = Area_polig(1) 'Area trave
If N_POLI > 1 Then S_g = Area_polig(2) 'Area getto
'********************************
'Trazione massima
'********************************
Nt_max = 0#
'Acciaio barre
Dim i As Integer
For i = 1 To n_barre_sez
Nt_max = Nt_max - aso(i) * elast_plast_indef(-epsyd_arm, arm.fyd(i), E_arm) * arm.fyd(i)
Next i
'Cavi
For i = 1 To n_cavi_sez
Nt_max = Nt_max - Asp(i) * elast_plast_indefps(Abs(-epsyd_arm + armp.def_prec(i)), armp.fyd(i), E_armp) * armp.fyd(i)
Next i
'********************************
'Compressione massima
'********************************
Nc_max = 0#
For i = 1 To n_barre_sez
Nc_max = Nc_max + aso(i) * elast_plast_indef(poli(1).epscu, arm.fyd(i), E_arm) * arm.fyd(i)
Next i
'Cavi
For i = 1 To n_cavi_sez
Nc_max = Nc_max + Asp(i) * elast_plast_indefps(Abs(poli(1).epscu + armp.def_prec(i)), armp.fyd(i), E_armp) * armp.fyd(i)
Next i
'Cls trave
If N_POLI > 0 Then Nc_max = Nc_max + s * parabola_rett(poli(1).epscu, poli(1).epsc0) * poli(1).fd
'Cls getto
If N_POLI > 1 Then Nc_max = Nc_max + S_g * parabola_rett(poli(2).epscu, poli(2).epsc0) * poli(2).fd
End Sub
'Calcola area poligono specificato
Private Function Area_polig(Indice_poligono As Integer) As Double
Dim k As Integer
Dim kp1 As Integer
Dim Area_poligono As Double: Area_poligono = 0#
For k = 1 To poli(Indice_poligono).numv
If k = poli(Indice_poligono).numv Then kp1 = 1 Else kp1 = k + 1
Area_poligono = Area_poligono + 0.5 * (poli(Indice_poligono).X(kp1) - poli(Indice_poligono).X(k)) * (poli(Indice_poligono).Y(kp1) + poli(Indice_poligono).Y(k))
Next
Area_polig = Abs(Area_poligono)
End Function. -
.Ho aggiunto il controllo massima trazione e massima compressione agli SLU, come suggerito da Zax.
La revisione 6 del file è ora scaricabile dal link già segnalato.
Hai agito sulla rev 5.0 pubblicata da reversi poco sopra?. -
.
Si è la copia aggiornata da reversi con l'aggiunta del codice sopra.
ecco ripropongo il link:
Rimosso perchè più avanti nel topic c'è la versione aggiornata
Edited by texitaliano64 - 2/4/2014, 20:43. -
.
Ho corretto i segni nella sub maxtrazcompr, ed ho spostato la posizione della chiamata dopo l'assegnamento dei valori alla struttura. CODICE' --------------------------------------------------------------------------
' Nome funzione : maxTrazCompr
' Scopo funzione : Determina la massima compressione e la massima trazione
' allo stato limite ultimo.
' Parametri formali : -
' Valore restituito : massima compressione Nc_max, massima trazione Nt_max
' Implementazione : Marzo 2014
' Autore : Tex
' --------------------------------------------------------------------------
Public Sub maxTrazCompr(Nc_max As Double, Nt_max As Double)
Dim def As Double 'deformazione
Dim i As Integer 'contatore
'********************************
'Trazione massima
'********************************
Nt_max = 0#
'Acciaio barre
For i = 1 To n_barre_sez
def = epsyd_arm
Nt_max = Nt_max - _
arm.af(i) * elast_plast_indef(Abs(def), arm.fyd(i), E_arm) * arm.fyd(i)
Next i
'Cavi
For i = 1 To n_cavi_sez
def = epsyd_arm
Nt_max = Nt_max - _
armp.af(i) * elast_plast_indefps(Abs(def), armp.fyd(i), E_armp) * armp.fyd(i)
Next i
'********************************
'Compressione massima
'********************************
Nc_max = 0#
'Acciaio barre
For i = 1 To n_barre_sez
def = poli(1).epsc0
Nc_max = Nc_max + _
arm.af(i) * elast_plast_indef(def, arm.fyd(i), E_arm) * arm.fyd(i)
Next i
'Cavi
For i = 1 To n_cavi_sez
def = poli(1).epsc0
Nc_max = Nc_max + _
armp.af(i) * elast_plast_indefps(def, armp.fyd(i), E_armp) * armp.fyd(i)
Next i
'Cls trave
If N_POLI > 0 Then
Dim s As Double: s = 0#
s = Area_polig(1) 'Area trave
def = poli(1).epsc0
Nc_max = Nc_max + _
s * parabola_rett(def, poli(1).epsc0) * poli(1).fd
End If
'Cls getto
If N_POLI > 1 Then
Dim S_g As Double: S_g = 0#
S_g = Area_polig(2) 'Area getto
def = poli(2).epsc0
Nc_max = Nc_max + _
S_g * parabola_rett(def, poli(2).epsc0) * poli(2).fd
End If
End Sub
Ho corretto sostituendo epscu con epsc0.
Edited by texitaliano64 - 18/3/2014, 20:49. -
.
Aggiornato il foglio, per determinare Nlimite adesso adotto epsc0 anzichè epscu, ecco il legame costitutivo di esempio del cls.
Uploaded with ImageShack.us. -
.
Hai ragione in quel caso la procedura non converge ed il foglio va in stallo.
Per risolvere ho modificato il valore della variabile locale delta che passa da 250mm a 1000mm nella sub "determina_asse_neutro"CODICE'***************************************************************************
'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
'***************************************************************************
' ASSE NEUTRO
'***************************************************************************
'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
'***************************************************************************
' --------------------------------------------------------------------------
' Nome Sub :determina_asse_neutro(
' Scopo funzione : Calcola la posizione effettiva dell'asse neutro in modo
' che la somma algebrica delle risultanti di compressio-
' ne e trazione sia proprio Nd (sforzo normale di solle-
' citazione)
' Parametri formali: Struttura dati con tutti i poligoni che costituiscono la
' sezione, struttura dati con tutte le armature della se-
' zione. Nd=sforzo normale di sollecitazione.
' ult_snerv flag per determinare cosa si cerca, se Mr, Ms
' oppure momenti a data curvatura, curv=curvatura
' Valore restituito: Struttura dati con varie informazioni: risultanti di
' compressione e trazione, posizioni risultanti, posizio-
' ne asse neutro, deformazioni limite a rottura sezione
' Implementazione : Luglio 2011
' Autore : Zax2010
' traduzione in VBA : Afazio Settembre 2012
' modifica : Tex Dicembre 2012
' --------------------------------------------------------------------------
Private Function asse_neutro_SLU(ByRef polic() As poligono_sezione, armco As armo_sezione, armcp As armp_sezione, nd As Double) As risultante_n_finale
.....
.....
.....
'inizializzo variazione della posizione dell'asse neutro
delta = 1000# 'NUOVO VALORE IN SOSTITUZIONE DI 250#
.....
.....
.....
End Function
Adesso converge anche nel caso da te segnalato.. -
.
io l'ho portato a 1250# per tener conto del seguente successivo stralcio di codice: CODICEIf delta * diff > 0# And Abs(diff) > precisione Then
delta = -delta / 5
yn = yn + delta
avendolo portato a 1250# la divisione per 5 mi ridà il valore 250# che c'era nel vecchio codice (quindi ho fatto una sola operazione in più e tutto mi ritorna a funzionare come l'originale).. -
.
Trattandosi di un valore puramente arbitrario, io sarei propenso a sostituire questa costante con un valore che dipende dalla dimensione massima della trave MAX(base, altezza) moltiplicato per 1.4 ovvero circa sqrt(2).
Così evitiamo in ogni caso il possibile stallo.. -
.
Io sono abbastanza perplesso.
A me pare che in questo modo si sia risolto UN problema. Ma non IL problema.
Ora, risulta evidente che il valore assegnato a delta, in se, non ha alcuna importanza.
Infatti secondo il ragionamento svolto da Reversi, ad un certo punto da 1250 mm la variabile delta ridiventa 250 mm.
250 mm che era il valore originario della variabile.
Per velocizzare le operazioni, e ridurre le iterazioni (forse), io nel mio codice originario avevo pensato ad una 'spazzolatura' delle possibili posizioni dell'asse neutro con passo variabile dell'algoritmo.
Proprio delta è la variabile che indica il passo di variazione dell'asse neutro. Passo che, al progredire delle iterazioni, diminuisce man mano che l'algoritmo si avvicina all'asse neutro 'vero'.
Faccio un esempio di flessione semplice. Immaginiamo che in una certa posizione dell'asse neutro si abbia che Nc>Na ( in valore assoluto - indicando con Nc la risultante di compressione e con Na la risultante di trazione), risulta evidente che bisognerà diminuire Nc ed aumentare Na per bilanciare le cose. Ecco quindi che l'algoritmo 'alza' l'asse neutro della quantità yn+delta. E definiamo y'n la nuova posizione dell'asse neutro.
Con questa seconda configurazione (esempio) vedremo che invece si verifica Nc<na (sempre in valore assoluto). Ecco quindi che l'asse neutro dovrà nuovamente 'scendere'. Ma lo faremo scendere di una quantità non più delta (altrimenti torneremmo al primo caso e già sappiamo che succede). Quindi l'algoritmo divide delta per 5, e sottrae questo valore a y'n, ricavando un y''n, e così via.
Ogni volta che si ha 'inversione' nella diseguaglianza Nc<>Na ecco che il passo di 'spazzolamento' della probabile posizione dell'asse neutro si riduce (e si inverte il senso di 'slaita' o 'discesa' dell'asse neutro), fino a quando Nc-Na (sempre in valore assoluto) non diventa inferiore ad una tolleranza fissata.
Detto questo lo stallo perchè si verifica?
I casi possono esse molteplici........si può verificare che nella ricerca il valore di delta diventa così piccolo da superare i limiti imposti dal suo 'tipo', di fatto azzerandosi, per cui l'algoritmo non fa altro che ricercare sempre la condizione Nc=Na con identica posizione di yn, oppure che i numeri siano tali da far fare all'algoritmo sempre prove tra due posizioni senza riuscire ad 'entrare dentro' un certo segmento (dove presumibilmente giace l'asse neutro)......
Ma tutto questo potrà accertarsi solamente con una bella sessione di debug, evitando di mettere la 'pezza' che risolve istantaneamente il caso in specie, ma che lascia inalterata la possibilità che per altri casi il fenomeno possa verificarsi ancora.. -
.
Lavorando con sezioni con dimensioni in millimetri, ritengo che appena delta scende al di sotto del valore di 0.5 mm, non abbiamo più nulla da chiedere a meno che non vogliamo la posizione dell'asse neutro con la precisione del decimo di millimetro ed allora fisseremo come delta a cui fermarci il valore 0.05 mm.
Questa dovrebbe essere una condizione di uscita dal ciclo while.
Puo' accadere, come ha evidenziato zax, che se la condizione di uscita dal ciclo è basata sul valore della differenza tra due valori successivi di N (che deve essere inferiore per esempio al millesimo di Newton), il corrispondente valore di delta diventi prossimo allo zero macchina o qualche altro "fattore" che entra nelle formule abbia raggiunto il suo limite numerico.. -
.
Afazio, io non sono d'accordo.
O meglio, posso essere d'accordo se quello che vogliamo è proprio il valore 'posizionale' dell'asse neutro.
Ma se vogliamo che la nostra sezione non sia 'squilibrata' la condizione di fine ciclo non può porsi sul 'grado di raffittimento' della posizione geometrica di yn. Ma proprio sullo squilibrio.
Da mie sessioni di debug, ed ovviamente in base anche alla grandezza della sezione, posso dirti che a volte, a seguito di variazioni anche minime dell'asse neutro tu puoi avere anche 1000 kg di squilibrio tra Nc ed Na.
La mia condizione di fine ciclo comunque è questa:CODICEwhile (fabs(Nd-ntot)>1.0 && fabs(delta)>1e-6);
Ovvero fintanto che contemporaneamente lo squilibrio è maggiore di 1 (daN nel mio codice), e il valore di delta è maggiore di 1e-6 l'iterazione deve andare avanti.
Non appena uno dei due casi si verifica ecco che il ciclo si interrompe.
La condizione sul valore di delta l'ho imposta successivamente, non avrei voluto, per risolvere qualche caso di 'indecisione' dell'algoritmo ad auto-chiudersi.. -
.
Io propongo questa modifica, che pare funzionare a dovere. CODICE'***************************************************************************
'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
'***************************************************************************
' ASSE NEUTRO
'***************************************************************************
'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
'***************************************************************************
' --------------------------------------------------------------------------
' Nome Sub :determina_asse_neutro(
' Scopo funzione : Calcola la posizione effettiva dell'asse neutro in modo
' che la somma algebrica delle risultanti di compressio-
' ne e trazione sia proprio Nd (sforzo normale di solle-
' citazione)
' Parametri formali: Struttura dati con tutti i poligoni che costituiscono la
' sezione, struttura dati con tutte le armature della se-
' zione. Nd=sforzo normale di sollecitazione.
' ult_snerv flag per determinare cosa si cerca, se Mr, Ms
' oppure momenti a data curvatura, curv=curvatura
' Valore restituito: Struttura dati con varie informazioni: risultanti di
' compressione e trazione, posizioni risultanti, posizio-
' ne asse neutro, deformazioni limite a rottura sezione
' Implementazione : Luglio 2011
' Autore : Zax2010
' traduzione in VBA : Afazio Settembre 2012
' modifica : Tex Dicembre 2012
' --------------------------------------------------------------------------
Private Function asse_neutro_SLU(ByRef polic() As poligono_sezione, armco As armo_sezione, armcp As armp_sezione, nd As Double) As risultante_n_finale
Dim k As Integer
Dim Np As Integer
Dim npm As Integer 'numero del poligono con il vertice di ordinata massima
Dim ymax As Double: ymax = -1000000# 'ordinata massima dei vertici della sezione
Dim yamin As Double: yamin = 1000000# 'ordinata minima delle armature
Dim Ntot As Double 'sforzo normale risultante
Dim cont As Integer 'contatore massimo numero di tentativi
Dim diff As Double 'variabile ausiliaria
Dim yn As Double 'posizione asse neutro
Dim delta As Double 'variazione della posizione dell'asse neutro
Dim deform As deform_sezione 'configurazione deformata della sezione
Dim nc As risultante_n, nt As risultante_n
' Per prima cosa determina ymax della sezione di cls ed yamin della sezione di ferro
For Np = 1 To N_POLI
If polic(Np).traz = 0 Then
For k = 1 To polic(Np).numv
If (polic(Np).Y(k) > ymax) Then
'cls trave
ymax = polic(Np).Y(k)
npm = Np
End If
Next
Else
For k = 1 To polic(Np).numv
If (polic(Np).Y(k) < yamin) Then
'cls resistente a trazione
yamin = polic(Np).Y(k)
End If
Next
End If
Next
' Poi determina yamin tra tutte le armature
For k = 1 To armco.numarm
If armco.Y(k) < yamin Then yamin = armco.Y(k)
Next
For k = 1 To armcp.numarm
If armcp.Y(k) < yamin Then yamin = armcp.Y(k)
Next
' Quindi definisce un primo posizionamento dell'asse neutro
yn = yamin + 0.8 * (ymax - yamin)
'inizializzo contatore massimo numero di tentativi
cont = 0
'inizializzo variazione della posizione dell'asse neutro
delta = (ymax - yamin) '1250#
' Inizia il ciclo iterativo alla ricerca della effettiva posizione dell'asse neutro
' procede con un ciclo a passo variabile, diminuendo il passo di scansione di ricerca
' della posizione dell'asse neutro ogni volta che la differenza tra ncompr ed ntraz cambia di segno
Do
cont = cont + 1
' Calcola le deformazioni ultime della sezione
deform = deform_ultime(polic, ymax, npm, yamin, yn)
' Calcola lo sforzo normale nella parte compressa della sezione
nc = risult_compr(polic, armco, armcp, deform, ymax, yamin, yn)
' Calcola lo sforzo normale della parte tesa della sezione
nt = risult_traz(polic, armco, armcp, deform, ymax, yamin, yn)
' Totale sforzo normale sulla sezione da confrontare con Nd
Const precisione As Double = 0.01
Const minDelta As Double = 0.000001
Ntot = nc.n + nt.n
diff = nd - Ntot
If Abs(diff) > precisione And delta * diff > 0# Then delta = -delta / 5
yn = yn + delta
If cont = 250 Then Exit Do 'max 250 tentativi
Loop While Abs(diff) > precisione And Abs(delta) > minDelta
' Copia nella struttura dati i risultati definitivi con il posizionamento ultimo dell'asse neutro
asse_neutro_SLU.ncf.n = nc.n
asse_neutro_SLU.ncf.X = nc.X
asse_neutro_SLU.ncf.Y = nc.Y
asse_neutro_SLU.ntf.n = nt.n
asse_neutro_SLU.ntf.X = nt.X
asse_neutro_SLU.ntf.Y = nt.Y
asse_neutro_SLU.yn = yn
asse_neutro_SLU.epsc = deform.epsa
asse_neutro_SLU.epss = deform.epsb
asse_neutro_SLU.curv = deform.epsa / (ymax - yn)
End Function. -
.
perchè le due costanti Precisione e MinDelta le definisci all'interno del ciclo Do?
Const precisione As Double = 0.01
Const minDelta As Double = 0.000001
Non sarebbe opportuno spostarle in testa insieme alle altre definizioni di variabili? In questo modo vengono ridefintie ad ogni passo del ciclo Do ... While. -
.
Tex, il conteggio del numero massimo di iterazioni era presente anche prima, oppure lo hai aggiunto adesso?
Mi pare di capire anche che adesso delta viene posto pari a ymax-yamin e non ad un ben preciso valore numerico.
Anche quando avevo visto il precedente 250 (mm) esteso a 1000 o 1250 (mm) mi ero chiesto il perchè di questa variazione in 'eccesso' del parametro. Nel mio codice io ho un 10 (cm), quindi un misero 100 mm.
Il valore attuale mi pare veramente 'enorme'. E' vero si tratta di 1-2 iterazioni in più rispetto a valori più piccoli, ma non ne capisco la ragione..