Il Bar dell'Ingegneria

Verifiche sezioni complesse in c.a. agli SLE ed SLU

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

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    La formulina 'madre' è la seguente:

    CODICE
    geo.alfa=atan(-2*geo.ixy/(geo.ix-geo.iy))/2


    Non ho un manuale a portata di mano, ma penso proprio di si.
     
    Top
    .
  2.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,163
    Reputation
    +294

    Status
    Offline
    CITAZIONE (zax2010 @ 3/10/2012, 10:21) 
    La formulina 'madre' è la seguente:

    CODICE
    geo.alfa=atan(-2*geo.ixy/(geo.ix-geo.iy))/2


    Non ho un manuale a portata di mano, ma penso proprio di si.

    ok
    L'errore sta nella formula di rotazione e nel fatto che devo disporre l'ellisse iniziale (cioè prima delle rototraslazione) con l'asse "a" verticale.

    La formula di rotazione riportata è quella che da le coordinate del punto rispetto ad un nuovo sistema ruotato di alfa menrte a noi serve mantenere fermo il sistema e ruotare i punti.

    Quindi:

    inizialmente:

    x= b*cos(teta)
    y=a*sen(teta)

    rotazione
    x'= x*cos(alfa) - y*sen(alfa)
    y'= x*sen(alfa) +y*cos(alfa)

    traslazione
    x"= x' + xg
    y"= y' + yg

    Aggiornato il file : https://www.box.com/s/2s40gvf7n2cbyaphkilh

    ed ecco la nuova ellisse centrale. DA notare che per adesso è stata disegnata nel baricentro di figura

    ellisse01
     
    Top
    .
  3.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Posso chiedere quanti punti hai utilizzato per schematizzare l'ellisse?
     
    Top
    .
  4.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,163
    Reputation
    +294

    Status
    Offline
    CITAZIONE (zax2010 @ 3/10/2012, 10:55) 
    Posso chiedere quanti punti hai utilizzato per schematizzare l'ellisse?

    36

    li vedi nel foglio "servizio"

    Il trentasettesimo serve solo a chiudere la polilgonale.

    Però! E' venuta una bella ellisse
     
    Top
    .
  5.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Infatti!
    Adesso mi copio il codice e faccio la traduzione inversa.
     
    Top
    .
  6.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,163
    Reputation
    +294

    Status
    Offline
    CITAZIONE (zax2010 @ 3/10/2012, 11:08) 
    Infatti!
    Adesso mi copio il codice e faccio la traduzione inversa.

    MA per l'ellisse non ho scritto nessun codice. Sono tutte funzioni di foglio.

    Illustro il codice fin qui scritto e/o modificato.

    Al tasto attuale "calcola geo", che è destinato a cambiare via via con l'evoluzione del codice per diventare il definitivo "calcola", ho associato il seguente codice:

    CODICE
    Sub CalcolaGeometria()
    ' chiamo la sub che legge i dati di input e li mette
    ' nelle variabili globali poli() ed arm
    ' contemporaneamente inverte i poligoni se sono definiti in senso negativo
    ' cioè se presentano area negativa
    Call LeggiDatiInput

    ' chiamo la sub che determina il baricentro della sezione senza le armature
    ' qui devo togliere qualsiasi inversione dato che è stata gia fatta prima
    Call definisci_baricentro
    ' chiamo la sub che mi calcola le caratteristiche geometriche della sezione
    ' omogeneizzata in presenza di armature
    '
    Call calcola_caratt_geometriche(poli(), arm, geo)

    ' scrivo i risultati sul foglio
    Range("x_g").Cells(1, 1) = geo.xg
    Range("y_g").Cells(1, 1) = geo.yg
    Range("tab_geometria").Cells(1, 1) = geo.area / 10 ^ 3
    Range("tab_geometria").Cells(1, 2) = geo.scx / 10 ^ 3
    Range("tab_geometria").Cells(1, 3) = geo.scy / 10 ^ 3
    Range("tab_geometria").Cells(1, 4) = geo.ix / 10 ^ 6
    Range("tab_geometria").Cells(1, 5) = geo.iy / 10 ^ 6
    Range("tab_geometria").Cells(1, 6) = geo.ixy / 10 ^ 6
    Range("tab_geometria").Cells(1, 7) = geo.alfa
    Range("tab_geometria").Cells(1, 8) = geo.ia / 10 ^ 6
    Range("tab_geometria").Cells(1, 9) = geo.ib / 10 ^ 6

    End Sub


    la sub richiama in cascata una dietro l'altra le seguenti sub:
    Call LeggiDatiInput (che ho scritto io ex novo e che zax avrà all'interno del suo programma) serve a caricare le variabili.
    Call definisci_baricentro (scritta da zax e modificata da me per i motivi che illustro a seguire)
    Call calcola_caratt_geometriche(poli(), arm, geo) (scritta da zax ed adattata da me per non avere tra i piedi variabili globali sparse qua e là. Con l'adattamento passo direttamente io le variabili globali da trattare.

    Il codice di zax prevede un controllo del senso di rotazione dei poligoni e nel caso ne inverte il senso. Ma non ho ben seguito la logica di quei cambiamenti dato che effettua un controllo del segno dell'area dopo averla moltiplicata per il coefficiente omog. Cosi io ho preferito abolire ogni controllo del senso del poligono condotto da zax e sostituirlo con un controllo iniziale all'ato del caricamento dei dati nelle variabili. In questo modo da quel punto in po abbiamo certezza che nelle successive fasi del codice i poligoni arrivano come noi li vogliamo.


    La lettura dei dati di input avviene leggendoli dal foglio dove ho disseminato diversi nomi "convenienti" di range
    Cosi ho per esempio chiamato la tabella contenente le coordinate dei vertici del primo poligono con "Poligono_1", del secondo poligono "Poligono_2". Allo stato attuale non vi sono altri poligoni definiti, ma qualora ve ne fosse un terzo chiamero' la relativa tabella col nome "Poligono_3" e cosi via.
    In questo modo posso cambiare all'interno del codice il nome del range da leggere mediante una semplice concatenazione di testi legandola al contatore.

    Tabella = "Poligono_" & i

    Questo significa che se i vale 2, la tabella da legegre diventa "Poligono_2"



    ecco la sub in questione. Abbastanza commentata.

    CODICE
    Sub LeggiDatiInput()

    Dim i As Integer
    Dim j As Integer
    Dim n As Integer
    Dim col As Integer
    Dim Tabella As String
    Dim Mat As String
    Dim Tipo As String
    Dim area As String
    Dim pi As Double
    pi = 4 * Atn(1)

    Dim NPoligoni As Integer
    NPoligoni = Range("N_poligoni").Value
    ' leggo i dati relativi ai poligoni
    For i = 1 To NPoligoni
       Tabella = "poligono_" & i ' nome range da dove leggere le coordinate del poligono i-esimo
       Mat = "Mat_" & i    ' nome della cella da dove leggere l'indice del materiale
       Tipo = "Tipo_" & i  ' nome della cella da dove leggere se il poligono è un pieno o un vuoto
       area = "area_" & i  ' nome della cella dove scrivere l'area del poligono
       col = Range(Mat).Value ' indice della colonna dell'archivio materiale da dove leggere i dati
       
       n = Range(Tabella).Rows.Count 'numero dei vertici del poligono i-esimo
       ' riempio i dati della struttura del poligono i-esimo
       poli(i - 1).numv = n
       poli(i - 1).omog = Range("Archivio_Materiali_poligoni").Cells(3, col).Value
       poli(i - 1).traz = Range("Archivio_Materiali_poligoni").Cells(4, col).Value
       poli(i - 1).fd = Range("Archivio_Materiali_poligoni").Cells(5, col).Value
       poli(i - 1).dominio = Range("Archivio_Materiali_poligoni").Cells(6, col).Value
       poli(i - 1).epsc0 = Range("Archivio_Materiali_poligoni").Cells(7, col).Value
       poli(i - 1).epscU = Range("Archivio_Materiali_poligoni").Cells(8, col).Value
       poli(i - 1).E_prof = Range("Archivio_Materiali_poligoni").Cells(9, col).Value
       poli(i - 1).Incr_prof = Range("Archivio_Materiali_poligoni").Cells(10, col).Value
       ' se il tipo è un vuoto cambio il segno all'omogeneizzazione
       If Range(Tipo).Text = "vuoto" Then poli(i - 1).omog = -poli(i - 1).omog
       ' adesso leggo le coordinate dei vertici e li metto in poli
       For j = 1 To n
         poli(i - 1).x(j - 1) = Range(Tabella).Cells(j, 1).Value
         poli(i - 1).y(j - 1) = Range(Tabella).Cells(j, 2).Value
       Next
       ' calcolo l'area del poligono e se risulta negativa inverto il poligono
       If Calcola_Area_poligono(poli(i - 1)) < 0 Then Call inversione_poligono(poli(i - 1))
       ' scrivo l'area del singolo poligono sul foglio
       Range(area).Value = Calcola_Area_poligono(poli(i - 1))
    Next
    ' leggo i dati relativi alle barre
       Tabella = "barre_0" ' nome range da dove leggere le coordinate dei tondini
       Mat = "Mat_B"   ' nome della cella da dove leggere l'indice del materiale
       col = Range(Mat).Value  ' indice della colonna dell'archivio materiale da dove leggere i dati
       
       n = Range(Tabella).Rows.Count 'numero complessivo della barre di armatura
       ' riempio i dati della struttura arm
       arm.numarm = n
       arm.omogarm = Range("Archivio_Materiali_Barre").Cells(3, col).Value
       arm.fyd_arm = Range("Archivio_Materiali_Barre").Cells(4, col).Value
       arm.E_arm = Range("Archivio_Materiali_Barre").Cells(5, col).Value
       arm.incr_arm = Range("Archivio_Materiali_Barre").Cells(6, col).Value
       ' leggo le coordinate dei tondini, il diametro e calcolo l'area di ogni tondino
       For i = 1 To n
           arm.x(i - 1) = Range(Tabella).Cells(i, 1).Value
           arm.y(i - 1) = Range(Tabella).Cells(i, 2).Value
           arm.diam(i - 1) = Range(Tabella).Cells(i, 3).Value
           arm.af(i - 1) = pi * arm.diam(i - 1) ^ 2 / 4
           arm.cong(i - 1) = 0
       Next
    End Sub


    I questa sub c'è da notare il rigo fondamentale:

    If Calcola_Area_poligono(poli(i - 1)) < 0 Then Call inversione_poligono(poli(i - 1))

    con questo viene controllato il segno dell'area del poligono iesimo e se questa è negativa viene richiamata la sub di zax che inverte il senso del poligono. Da questo punto in poi il poligono sarà come ci serve e non è piu necessario condurre controlli.

    La funzione Calcola_Area_poligono() [nel codice di zax non c'è nessuna funzione dedicata a questo, calcola le aree sempre al volo] è la seguente:

    CODICE
    ' --------------------------------------------------------------------------
    ' Nome Funzione  : Calcola_Area_poligono(
    ' Scopo             : calcola l'area di un singolo poligono
    ' Parametri         : il  poligono di cui si vuole l'area
    ' restituisce       : L'area del poligono con segno
    ' Implementazione  : Ottobre 2012
    ' Autore           : Afazio
    ' ---------------------------------------------------------------------------
    Function Calcola_Area_poligono(polic As TipoPoligono) As Double
    Dim i As Long
    Dim k As Long
    Dim area As Double
    area = 0
    For i = 0 To polic.numv - 1
       k = i + 1
       If i = polic.numv - 1 Then k = 0
       area = area - 0.5 * (polic.x(i) * polic.y(k) - polic.x(k) * polic.y(i))
    Next
    Calcola_Area_poligono = area
    End Function


    Edited by afazio - 3/10/2012, 11:42
     
    Top
    .
  7.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    CITAZIONE (afazio @ 3/10/2012, 11:25) 
    Il codice di zax prevede un controllo del senso di rotazione dei poligoni e nel caso ne inverte il senso. Ma non ho ben seguito la logica di quei cambiamenti dato che effettua un controllo del segno dell'area dopo averla moltiplicata per il coefficiente omog. Cosi io ho preferito abolire ogni controllo del senso del poligono condotto da zax e sostituirlo con un controllo iniziale all'ato del caricamento dei dati nelle variabili. In questo modo da quel punto in po abbiamo certezza che nelle successive fasi del codice i poligoni arrivano come noi li vogliamo.

    Il codice cui ti riferisci è il seguente:

    CODICE
    /* Controlla inizialmente l'input invertendo all'occorrenza i poligoni */
    for (np=0;np<=NMAXPOLI-1;np++)
    {
    area=0.0;
    for (k=0;k<=poli[np].numv-1;k++)
    {
    if (k==poli[np].numv-1) kp1=0; else kp1=k+1;
             a=poli[np].x[kp1]-poli[np].x[k];
             d=poli[np].y[kp1]-poli[np].y[k];

             area+=poli[np].omog*a*(poli[np].y[k]+d/2);
            }
        if (area*poli[np].omog<0.0) inversione_poligono(np);
       }


    Effettivamente è vero, prima moltiplico per omog l'area. Però poi il controllo lo faccio non sul segno dell'area, ma sull'area moltiplicata nuovamente per omog. Insomma, nel caso di poligono antiorario sia che esso sia un vuoto sia che sia normale, il risultato dell'operazione dentro l'if è sempre minore di 0 e dunque 'scatta' l'inversione del poligono.
    (Sono sicuro che questo pezzetto di codice inizialmente era in qualche altra parte, per cui mi serviva questa doppia moltiplicazione. Adesso per dove è messo, in effetti ci sono delle moltiplicazioni di troppo senza senso)
     
    Top
    .
  8.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,163
    Reputation
    +294

    Status
    Offline
    Altra nota merita la sub

    inversione_poligono(poli(np))
    Nel codice di zax, viene passato l'indice del poligono da trattare attraverso il parametro np [ inversione_poligono(np) ], La sub poi agisce sulla variabile globale poli(np)

    Nella traduzione ho apportato la modifica che sostanzialmente passa tutto il poligono np da trattare e di conseguenza non si appoggia a nessuna variabile globale ma ad una variabile passata attraverso il suo riferimento.
    Questo significa che la procedura puo' essere utilizzata per trattare qualsiasi altro poligono diverso da poli.

    Ecco la sub in questione modificata nel senso sopra descritto.
    CODICE
    ' --------------------------------------------------------------------------
    ' Nome sub: Inversione_poligono(
    ' Scopo             : Inverte il senso di input del singolo poligono orario
    '                     in antiorario e viceversa
    ' Parametri         : il  poligono da invertire passato come riferimento
    ' Valore            : nessuno. Agisce sulla variabile globale poli() passata byRef
    '                    invertendone il senso di definizione dei vertici
    ' Implementazione  : Luglio 2011
    ' Autore           : Zax2010
    ' traduzione in VBA : Afazio Settembre 2012
    ' ---------------------------------------------------------------------------
    Sub inversione_poligono(ByRef polic As TipoPoligono)
    Dim k As Integer
    Dim provv As Double
       For k = 1 To Int(polic.numv / 2)
           provv = polic.x(k)
           polic.x(k) = polic.x(polic.numv - k)
           polic.x(polic.numv - k) = provv

           provv = polic.y(k)
           polic.y(k) = polic.y(polic.numv - k)
           polic.y(polic.numv - k) = provv
       Next
    End Sub
     
    Top
    .
  9. francesco.coppola
        +1   -1
     
    .

    User deleted


    Altra ottima cosa per rendere le funzioni sempre meno dipendenti.
     
    Top
    .
  10.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,163
    Reputation
    +294

    Status
    Offline
    Considerato che ho condotto il controllo del senso di definizione dei poligoni a monte, e cioè nella fase di lettura dei dati di input, a questo punto occorre togliere dal codice di zax tutte quelle parti che farebbero la stessa cosa.

    Ho iniziato a toglierlo dalla sub :definisci_baricentro(

    CODICE
    ' --------------------------------------------------------------------------
    ' Nome sub          :definisci_baricentro(
    ' Scopo funzione   : Determina le coordinate del baricentro della sezione
    '                    omogenea senza tenere in conto le armature
    '                    agisce direttamente sull'input poli dell'utente, al li-
    '                    mite modificandolo (con inversione_poligono())
    ' Parametri formali:
    ' Valore restituito: Determina xg,yg già variabili globali
    ' Implementazione  : Luglio 2011
    ' Autore           : Zax2010
    ' traduzione VBA    : Afazio Ottobre 2012
    ' --------------------------------------------------------------------------
    Sub definisci_baricentro()
    Dim k As Integer, np As Integer
    Dim kp1 As Integer
    Dim a As Double, d As Double, hx As Double, hy As Double
    Dim area As Double, scx As Double, scy As Double

    '---------------------- parte di codice soppresso-----------------------------------------
    ' motivo: i poligoni vengono controllati all'inizio, in fase di lettura dei dati
    '           nella sub LeggiDatiInput(), e viaggiano da li a seguire col giusto orientamento
    '----------------------------------------------------------------------------------------
    ' Controlla inizialmente l'input invertendo all'occorrenza i poligoni
    'For np = 0 To NMAXPOLI - 1
    '     area = 0#
    '     For k = 0 To poli(np).numv - 1
    '          If k = poli(np).numv - 1 Then kp1 = 0 Else kp1 = k + 1
    '          a = poli(np).x(kp1) - poli(np).x(k)
    '          d = poli(np).y(kp1) - poli(np).y(k)
    '          area = area + poli(np).omog * a * (poli(np).y(k) + d / 2)
    '     Next
    '     If (area * poli(np).omog < 0#) Then Call inversione_poligono(poli(np))
    ' Next
    '---------------------- fine parte di codice soppresso---------------------------------------

    ' Determina coordinate del baricentro sezione omogenea
    area = 0#
    scx = 0#
    scy = 0#
    ' Caratteristiche statiche di ogni poligono
    For np = 0 To NMAXPOLI - 1
         For k = 0 To poli(np).numv - 1
              If (k = poli(np).numv - 1) Then kp1 = 0 Else kp1 = k + 1
              a = poli(np).x(kp1) - poli(np).x(k)
              d = poli(np).y(kp1) - poli(np).y(k)
              hy = poli(np).y(k)
              hx = poli(np).x(k)

              area = area + poli(np).omog * a * (hy + d / 2)
              scx = scx + poli(np).omog * a / 2 * (hy * hy + d * d / 3 + d * hy)
              scy = scy - poli(np).omog * d / 2 * (hx * hx + a * a / 3 + a * hx)
         Next
    Next
    If (area <> 0#) Then
       ' N.B.: rispettto al codice di zax, le coordinate del baricentro vengono inserite
       ' nella struttura dati geo e quindi spariscono dall'elenco della variabili globali "isolate"
       ' tutto le occorrenze di xg e di yg nel resto del codice sono state sostituite con i seguenti
       ' xg ---> geo.xg
       ' yg ---> geo.yg
       geo.xg = scy / area
       geo.yg = scx / area
    End If

    End Sub


    Purtroppo questa sub fa uso di variabili globali e quindi inutilizzabile se volessimo utilizzarla per il calcolo del baricentro di poligoni con altro nome e di armature con altro nome. Significa che questa sub puo essere usata solo e soltanto nell'ambito di questo programma.
    MI propongo di apportare variazioni a questa sub per renderla idnipendente da variabili globali.
     
    Top
    .
  11. francesco.coppola
        +1   -1
     
    .

    User deleted


    Afazio. Perchè non eliminare completamente questa sub?
    Proprio quel pezzetto di codice potrebbe essere posizionato all'interno di calcola_caratt_geometriche, che quindi calcolerà contemporaneamente le caratteristiche della sezione isolata ed il baricentro della sezione senza armature.
     
    Top
    .
  12.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Francesco, mi hai costretto ad una giravolta.
    A primo acchito la tua idea mi pareva buona.
    Poi però riflettendo avevo visto un problema.
    Ma alla fine penso che possa andare.

    Nelle verifiche SLE ogni volta ridefinisco la geometria della sezione reagente. Pensavo quindi che la modifica anche di geo.xg e geo.yg (perchè la sezione via via si modifica) sarebbe risultata deleteria per la sezione 'tutta'.

    In effetti la variabile geo viene però definita come variabile locale all'interno di deform verifica_SLE. Quindi non dovrebbe 'sporcare' una variabile 'globale' di tipo geometria_sezione che raccoglie i dati della sezione 'tutta'.

    Bisogna allora definire una variabile globale geo_glob in cui memorizzare questi valori.
     
    Top
    .
  13.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,163
    Reputation
    +294

    Status
    Offline
    CITAZIONE (zax2010 @ 3/10/2012, 12:32) 
    Francesco, mi hai costretto ad una giravolta.
    A primo acchito la tua idea mi pareva buona.
    Poi però riflettendo avevo visto un problema.
    Ma alla fine penso che possa andare.

    Nelle verifiche SLE ogni volta ridefinisco la geometria della sezione reagente. Pensavo quindi che la modifica anche di geo.xg e geo.yg (perchè la sezione via via si modifica) sarebbe risultata deleteria per la sezione 'tutta'.

    In effetti la variabile geo viene però definita come variabile locale all'interno di deform verifica_SLE. Quindi non dovrebbe 'sporcare' una variabile 'globale' di tipo geometria_sezione che raccoglie i dati della sezione 'tutta'.

    Bisogna allora definire una variabile globale geo_glob in cui memorizzare questi valori.

    I campi geo.xg e geo.yg vengono toccati solo una volta e non vengono mai piu' modificati

    riprendo questa immagine:

    valori

    Qualcosa non mi convince nel calcolo di Scx e Scy
     
    Top
    .
  14.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Considerando che le coordinate del baricentro sono corrette, non capisco cosa non ti convince di Scx ed Scy....
     
    Top
    .
  15.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,163
    Reputation
    +294

    Status
    Offline
    CITAZIONE (zax2010 @ 3/10/2012, 13:03) 
    Considerando che le coordinate del baricentro sono corrette, non capisco cosa non ti convince di Scx ed Scy....

    le coordinate del baricentro sono quelle di figura e quindi determinate come rapporto tra S/A in cui sia S che A sono relativi alla sola figura (coi relativi coefficienti vuoto/pieno)

    I valori di Scx ed Scy riportati in tabella sono quelli della sezione ideale (divisi per 1000, sia l'area che i momenti statici)
    Le coordinate del baricentro della sezione ideale dovrebbero potersi calcolare come rapporto tra i valori riportati in tabella
    ma se provo a fare Scx/A ottengo poco piu di 1 (millimetro)

    Quindi qualcosa non va
     
    Top
    .
390 replies since 26/9/2012, 10:47   29394 views
  Share  
.