Il Bar dell'Ingegneria

Ci A Pi

« Older   Newer »
 
  Share  
.
  1.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    3,345
    Reputation
    +213

    Status
    Online
    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
     
    Top
    .
  2.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    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.

    CODICE
    Dim 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 If


    CODICE
    '*********************************************************************
    '                          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
     
    Top
    .
  3.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,169
    Reputation
    +294

    Status
    Offline
    CITAZIONE (texitaliano64 @ 13/3/2014, 20:19) 
    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?
     
    Top
    .
  4.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    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
     
    Top
    .
  5.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    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
     
    Top
    .
  6.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    Aggiornato il foglio, per determinare Nlimite adesso adotto epsc0 anzichè epscu, ecco il legame costitutivo di esempio del cls.

    Uploaded with ImageShack.us
     
    Top
    .
  7.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    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.
     
    Top
    .
  8.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    3,345
    Reputation
    +213

    Status
    Online
    io l'ho portato a 1250# per tener conto del seguente successivo stralcio di codice:

    CODICE
    If 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).
     
    Top
    .
  9.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    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.
     
    Top
    .
  10.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,942
    Reputation
    +187

    Status
    Offline
    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.
     
    Top
    .
  11.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,169
    Reputation
    +294

    Status
    Offline
    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.
     
    Top
    .
  12.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,942
    Reputation
    +187

    Status
    Offline
    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:

    CODICE
    while (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.
     
    Top
    .
  13.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    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
     
    Top
    .
  14.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,169
    Reputation
    +294

    Status
    Offline
    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
     
    Top
    .
  15.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,942
    Reputation
    +187

    Status
    Offline
    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.
     
    Top
    .
283 replies since 18/1/2014, 10:24   14202 views
  Share  
.