Apostila Python
Apostila Python
Escola de Engenharia
Programa de Pós-Graduação em Engenharia Civil
Porto Alegre
2020
LISTA DE FIGURAS
1 INTRODUÇÃO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1 Por que Python? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2 Instalação do Anaconda . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Spyder: Ambiente semelhante ao MATLAB . . . . . . . . . . . . . . . . 6
1.4 Jupyter notebook: Caderno interativo . . . . . . . . . . . . . . . . . . . 7
1.4.1 Células de código Python . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4.2 Células de Markdown . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2 A LINGUAGEM PYTHON . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.1 Entrada e Saída de dados . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2 Tipos de variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.1 Numéricas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.2 Textual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.3 Booleanas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.4 Listas, tuplas e dicionários . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.5 Extra: Formatando strings . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3 Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3.1 Aritiméticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3.2 Atualização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3.3 Comparativos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3.4 Participação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3.5 Lógicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.4 Blocos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4.1 Condicionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4.2 Repetição . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.5 Funções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1 INTRODUÇÃO
Python é uma linguagem de código aberto, de fácil interpretação que exige menos o
programador e mais da máquina, sendo, portanto, uma linguagem facilmente legível,
que não prioriza a velocidade de execução. Hoje, a linguagem é amplamente utilizada
devido ao vasto número de bibliotecas gratuitas disponíveis, que possibilitam uma
infinidade realizações.
Anaconda é uma distribuição gratuita da linguagem Python que possui diversas ferra-
mentas, bibliotecas e ambientes.Sua instalação é aconselhável por já possuir as prin-
cipais bibliotecas necessárias e um gerenciador de pacotes. Para baixar clique aqui e
escolha a versão adequada para o seu sistema operacional.
Dos ambientes que podem ser visualizados na figura acima, os que serão abordados
neste minicurso são Spyder e Jupyter notebook.
O Jupyter notebook consiste numa aplicação que permite criar e compartilhar documen-
tos com código ativo. Este permite que o código permite que o código seja construído
por células, não havendo a necessidade rodar todo o programa a cada alteração feita
no código. Neste ambiente são encontradas dois tipos principais de células, sendo elas
Python e Markdown. A célula Python é utilizada para o processamento do código,
enquanto a markdown é utilizada com o intuito de documentar o código. O ambiente
Jupyter pode ser visualizado abaixo.
2 A LINGUAGEM PYTHON
Mais a frente, após a explicação dos tipos de variáveis, será ensinado como formatar as
informações que serão printadas na tela.
2.2.1 Numéricas
A linguagem Python possui três tipos de variáveis para o armazenamento de números :
os int, os float e os complex. As variáveis do tipo int armazenam apenas números
inteiros, os floats armazenam números reais e os complex armazenam números
complexos. O divisor de décimais é marcado por um “.” e o número complexo é
indicado por “j”. Abaixo são declaradas três variáveis, e seus tipos são exibidos na tela
a patir do comando type.
[2]: a = 1
b = 1.
c = 1+1j
9
print(type(a))
print(type(b))
print(type(c))
<class 'int'>
<class 'float'>
<class 'complex'>
2.2.2 Textual
Para o armazenamento de uma sequência de caracteres, utiliza-se uma variável do tipo
string, em que esta sequência deve ser declarada entre aspas simples ou duplas.
<class 'str'>
2.2.3 Booleanas
A linguagem Python também é dotada de operadores booleanos, ou seja True e False.
[4]: a = 10
y = a > 10
print(y, type(y))
As tuples,diferentemente das lists, são imutáveis, ou seja, não podem ter seus
valores alterados ao longo da execução.
Para acessar um termo específico de uma lista ou de uma tupla, basta utilizar o seus
nome seguido do seu “indexing” entre colchetes. Por exemplo, vamos acessar o terceiro
termo da lista a. O último termo de uma sequência pode ser acessada utilizando -1
como índice.
[7]: print(a[2])
print(a[-1])
oi
(1+2j)
É possível acessar os termos da lista e alterar seus valores específicos, como se mostra
abaixo.
-----------------------------------------
TypeError Traceback (most
,→recent call last)
<ipython-input-9-0a2d922de335> in <module>
----> 1 b[2] = 'tchau'
[10]: print(a[0:3])
[1, 2, 'tchau']
[11]: print(a[::2])
Para inverter a sequência de uma lista, pode-se utilizar o comando reversed, ou sim-
plesmente. . .
[12]: print(a[::-1])
As variáveis do tipo dictionary são como listas onde os índices podem ser quaisquer
tipos de valores. Dicionáros são criados fazendo o uso de chaves ({}), onde é fornecido
o indíce (key) e seu valor seguido de :. Os valores dos dicionários são mutáveis e esses
são expansíveis, conforme os exemplos a seguir:
[13]: d = {'a': 1,
'b': 2,
30: 0,
(2,3): 77}
print(d)
print(d['a'])
print(d[2,3])
print(d[30])
Para remover valores é usado o comando d.pop(key) fornecendo a key a ser remo-
vida, esse retornará o valor removido. Por exemplo removendo o elemento b a função
retorna 2.
[15]: d.pop('b')
[15]: 2
[16]: d
Outro tipo de variável importante no Python é o None, que significa nenhum. Esse
tipo de variável é bastante útil para representar a ausência de valores, visto que 0 tem
significado em alguns casos. Vamos declarar uma variável como None e verificar seu
tipo:
print(msg)
Onde observamos que todas as casas decimais dos valores são impressas, mesmo não
havendo necessidade de tamanha precisão.
print(msg1)
print(msg2)
[22]: a = 3
b = 3.14159
c = 123456789123.456789
a: 3, 3, 3, 3.00
b: 3.14159, 3.141590, 3.14, 3.14159000
c: 123456789123.45679, 123456789123.456787, 123456789123.46,
,→1.2E+11,
1.23457e+11
2.3 OPERADORES
2.3.1 Aritiméticos
Os operadores aritiméticos do Python são: * +, -, *, / para adição, subtração, multipli-
cação e divisão; * ** para exponenciação (3ˆ2 em Python é 3**2); * // e % para divisão
de inteiros e cálculo do seu resto. Por exemplo, 14/5 = 2.8, já 14//5=2 (inteiro) e
14%5=4 (resto), logo 14=2*5+4.
2.3.2 Atualização
Todos os operadores aritiméticos anteriores podem ser combinados com o símbolo de
atribuição (=), obtendo operadores que atualizam o valores das variáveis. São exemplos
+=, *=, **=, exemplíficados a seguir:
b = 3 # Define b como 3
b *= 9 # Multiplica valor de b por 9, 3*9=27
print('b={}'.format(b))
c = 2 # Define c como 2
c **= 3 # Eleva c ao cubo 2**3=8
print('c={}'.format(c))
a=7
b=27
c=8
2.3.3 Comparativos
O conteúdo de variáveis pode ser comparado através dos operadores: * >, >=, <, <=
para verificar se uma é maior, maior igual, menor ou menor igual; * == para verificar
são iguais; * != para verificar são diferentes.
a<b? True
c<a? False
a=b? False
a<>b? True
b=b? True
2.3.4 Participação
A participação de um valor em um elemento (lista, dicionário, tupla, array) pode ser
verificada através do comando in, conforme exemplo:
[25]: a = [1, 3, 5, 7, 9]
print('Temos 1 em a?', 1 in a)
print('Temos 8 em a?', 8 in a)
Temos 1 em a? True
Temos 8 em a? False
2.3.5 Lógicos
Os operadores lógicos trabalham em conjunto com as operações booleanas, eles são
and, or e not que tem como significado seus próprios nomes. Através desses podemos
comparar operações para avaliar condições (vistas na próxima seção).
Como exemplo vamos adotar a lista a anterior, três escalares b=0, c=5, d=88, e fazer
alguams verificações:
[26]: b = 0
c = 5
d = 88
# Verificações
V1 = b <= c # b é menor ou igual à c? Sim
V2 = d in a # d está em a? Não
V3 = c in a # c está em a? Sim
print(V1, V2, V3)
2.4 BLOCOS
2.4.1 Condicionais
Se imaginarmos um fluxograma, um bloco condicional é um separador de fluxo defi-
nido por uma condição imposta pelo usuário. Por exemplo, vamos imaginar que você
precisa validar uma senha de 8 dígitos, a primeira condição a ser verificada é o tamanho
da senha, se essa condição for verdadeira a senha deve ser confirmada, se as senhas
forem iguais e tiverem mais de 8 dígitos é informado ao usuário que a senha foi aceita.
else:
senha2 = input("Por favor, confirme sua senha:")
if senha1 == senha2:
print("Senha aceita.")
elif len(senha2) < 8:
print("Senha inválida, a senha precisa ter no mínimo 8
,→digitos.")
else:
print("As senhas inseridas são diferentes!")
2.4.2 Repetição
Observando o exemplo acima, veja que ele não faz sentido visto que se a senha digitada
não for válida o código apenas termina sem a possibilidade de inserçõa de uma nova
senha. A forma correta de executar o código acima é dentro de um loop em que esse
loop só acabará quando a condição for satisfeita. Vamos então usar o artíficio while
True: onde o código é repetido infinitamente até que o loop seja quebrado.
else:
senha2 = input("Por favor, confirme sua senha:")
if senha1 == senha2:
print("Senha aceita.")
break # Quebra o loop
elif len(senha2) < 8:
print("Senha inválida, a senha precisa ter no mínimo 8
,→digitos.")
else:
print("As senhas inseridas são diferentes!")
Outras condições, como as utilizadas em if, podem ser consideradas pelo comando
while. Como por exemplo while x1!=x2 irá repetir o bloco de código até que x1
seja igual à x2, sem a necessidade de uso do break.
Para iterar uma lista ou sequência pode ser usado o comando for. Diferentemente
de outras linguagens de programação, o comando for tem como entrada um objeto
iterável (como uma lista, tupla, dicionário ou sequencias).
Por exemplo vamos criar uma lista de valores e percorrer esta, onde em cada loop um
elemento da lista é acessado e tem seu valor passado para a variável n.
3
4
1
23
42
5
Esse comando é muito utilizado para acessar e percorrer arrays, realizar processo
iterativos e muito mais. Para criar um for tradicional, ou seja, em que a variável n
segue uma sequencia de números inteiros pode ser usado o comando range(inicio,
fim, passo) ou range(fim), conforme exemplos à seguir:
10
11
12
13
14
15
16
17
18
19
10
12
14
16
18
0
1
2
3
4
5
6
Podemos observar que o iterador range() cria uma sequencia de números inteiros a
partir de um intervalo definido, matemáticamente falando temos um invervalo fechado-
aberto.
O termo 0 é 3.
O termo 1 é 4.
O termo 2 é 1.
O termo 3 é 23.
O termo 4 é 42.
O termo 5 é 5.
2.5 FUNÇÕES
Uma função é um bloco que realiza uma operação pré-definida que será realizada
sempre que chamada pelo usuário. Podemos criar funções para representar expressões
matemáticas, ou mesmo operações mais trabalhosas. Funções apresentar valores de
retorno. Adotando equações de segundo grau no formato y = ax2 + bx + c vamos
return x1, x2
Perceba que na definição da função nada é executado, agora chamando essas teremos
alguns resultados.
2.0 1.0
0.0
Os argumentos das funções podem ter valores pré-definidos, dessa forma seu preenchi-
mento é opcional. Além disso, na chamada das funções deve-se respeitar a ordem dos
argumentos ou deve ser especificado o argumento que recebe cada valor.
Vamos então redefinir a função quad com argumentos padrões (a=1, b=c=0) e chama-
la embaralhando seus argumentos.
[38]: quad(2)
[38]: 4
[39]: 0.0
Módulos são bibliotecas de funções e classes que podem ser facilmente importados e
introduzem novas funcionalidades à linguagem. Os principáis módulos para aplicações
científicas são: - NumPy para operações matriciais; - SciPy para cálculo numérico; -
matplotlib para plotagem de gráficos; - Pandas para trabalho com séries de dados.
Além desses, diversos outros módulos criados pela comunidade estão disponíveis
nos repositórios do PyPi e do Anaconda. A criação de módulos pelo usuário pode ser
realizada de forma simplificada inserindo todas as funções e variáveis de interesse em
um arquivo .py (ou em uma pasta) no diretório de trabalho.
<class 'module'>
<class 'module'>
25
Existem ainda módulos internos à outros módulos, sua importação é realizada na forma
import modulo.submodulo. Um exemplo de submódulo é o pyplot que pertence
ao módulo matplotlib, usualmente sua importação é realizada com o “apelido” plt,
dessa forma:
A importação de módulos pode ainda ser realizada sem a manutenção de vínculo entre
o nome do módulo e a função através da sintaxe from modulo import funcao,
entretanto tal prática não é recomendada na presença de diferentes módulos.
3.2 NUMPY
3.2.1.1 np.array
Arrays podem ser criadas a partir de listas e tuplas com a função np.array(lista).
Ao passar uma lista de valores para a função um vetor é gerado, uma lista de listas
produz uma matriz e etc.
Como exemplo vamos criar e printar 3 listas: l1, l2 e l3, onde l3 é uma lista de listas
formada pelas outras duas.
[6]: l1 = [1,3,5]
l2 = [20,30,40]
l3 = [l1, l2]
print('l1:', l1)
print('l2:', l2)
print('l3:', l3)
l1: [1, 3, 5]
l2: [20, 30, 40]
l3: [[1, 3, 5], [20, 30, 40]]
Tranformando as três listas em arrays temos 2 vetores (v1 e v2) e uma matriz (m1):
[7]: v1 = np.array(l1)
v2 = np.array(l2)
m1 = np.array(l3)
print('v1:\n', v1)
print('v2:\n', v2)
print('m1:\n', m1)
v1:
[1 3 5]
v2:
[20 30 40]
m1:
[[ 1 3 5]
[20 30 40]]
Os termos dos vetores e da matriz gerada podem ser acessados como os itens de listas,
tuplas e dicionários:
3.2.1.2 np.zeros
[0. 0. 0. 0. 0.]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
3.2.1.3 np.ones
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
Essa função pode ser usada para outros valores, como um vetor onde todos termos são
25:
3.2.1.4 np.eye
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
[[1. 0. 0. 0. 0. 0.]
[0. 1. 0. 0. 0. 0.]
[0. 0. 1. 0. 0. 0.]
[0. 0. 0. 1. 0. 0.]]
3.2.1.5 np.diag
[17]: m3 = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
diag = np.diag(m3)
print(diag)
[1 5 9]
Ok! A função retornou os termos da diagonal, vamos agora construir uma matriz com
base nesse vetor:
[19]: m4 = np.diag(diag)
print(m4)
[[1 0 0]
[0 5 0]
[0 0 9]]
3.2.1.6 np.linspace
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
Existem ainda diversas outras funções para criação de arrays no NumPy, essas podem
ser acessadas aqui.
[45]: m4[0, 2] = 99
print(m4)
[[ 1 0 99]
[ 0 5 0]
[ 0 0 9]]
Toda uma linha ou coluna pode ser alterada, usando : para sinalizar todos seus ele-
mentos. A seguir vamos definir todos elementos da primeira coluna de m4 como -1.
[46]: m4[:,0] = -1
print(m4)
[[-1 0 99]
[-1 5 0]
[-1 0 9]]
O tamanho e a forma de arrays podem ser determinados pelos comandos size e shape,
respectivamente, onde ambos podem ser acessados tanto através da biblioteca prin-
cipal (np.size(array) e np.shape(array)) como através do próprio elemento
Forma de m4
(3, 3)
(3, 3)
Tamanho de m4
9
9
Como resultado para a forma de m4 obtivemos (3,3), o que significa que a array m4
tem 3 linhas e 3 colunas. Já o tamanho de m4 encontrado é 9, ou seja, m4 tem 9 elementos
(3x3=9). Vamos printar agora os tamanhos e formas de outros vetores e matrizes:
m4 original:
[[-1 0 99]
[-1 5 0]
[-1 0 9]]
m4:
[[ -1 0 99]
[ -1 666 0]
[ -1 0 9]]
A:
[[ -1 0 99]
[ -1 666 0]
[ -1 0 9]]
B:
[[ -1 0 99]
[ -1 999 0]
[ -1 0 9]]
True
False
[79]: print(m_id46.shape)
print(m_id46.T.shape)
print(v1_10.shape)
print(v1_10.T.shape)
(4, 6)
(6, 4)
(10,)
(10,)
• np.pi: π;
Diferentemente das listas, as arrays do NumPy são operadas termo a termo, dessa
forma as funções anteriores possuem a mesma propriedade. Vamos então ilustrar
calculando a expressão a seguir para valores de x de 0 à 10.
√
y( x ) = exp5x−10 sin(3π + 4x )
print(x)
[69]: y = np.exp(+5*x-10)*np.sin(3*np.pi+np.sqrt(4*x))
print(y)
-9.73511413e+15]
da array x por ela mesma é realizada pela função np.dot(x,x) ou x.dot(x). Cabe
lembrar que no caso de matrizes o número de colunas de primeira matriz (n x j) deve
ser igual o número de linhas da segunda matriz (j x m), que podem ser acessados por
np.shape(), resultando em uma matriz n x m. Já no caso de vetores esses devem ter
o mesmo comprimento, não havendo diferença entre vetores linha e vetores coluna.
[45]: np.random.seed(8198916)
X1 = np.random.randint(0, 10, (4,2)) # Gera número inteiros
,→aleatórios entre 0 e 10
X3 = X1.dot(X2)
print('X3:\n', X3)
X1:
[[7 8]
[9 4]
[0 2]
[0 7]]
X2:
[[6 9 6 1]
[7 2 4 9]]
X3:
[[98 79 74 79]
[82 89 70 45]
[14 4 8 18]
[49 14 28 63]]
[46]: print(np.linalg.inv(X3))
print(np.linalg.det(X3))
-2.3271643223052853e-26
É possível, também, solucionar sistemas pela forma matricial, sendo necessário apenas
o conhecimento da matriz de coeficientes e o vetor resposta. Vamos utilizar o exemplo
abaixo:
5 2 1 x 63
2 5 2 y = 18 (3.1)
3 −2 4 z 11
x = np.linalg.solve(A, b)
print(x)
[1. 2. 3.]
3.3 SCIPY
-1.0000000000000004
w = w[iw]
phi = phi[:, iw]
print(phi)
print(w)
[ ]:
[3]: data
Linha 4 24 29 34 39 44
,→ 49
Linha 5 25 30 35 40 45
,→ 50
... ... ... ... ... ...
,→ ...
Linha 84 104 109 114 119 124
,→ 129
Linha 85 105 110 115 120 125
,→ 130
Linha 86 106 111 116 121 126
,→ 131
Linha 87 107 112 117 122 127
,→ 132
Linha 88 108 113 118 123 128
,→ 133
Coluna 34 Coluna 35
Linha 1 168 173
Linha 2 187 192
Linha 3 188 193
Linha 4 189 194
Linha 5 190 195
... ... ...
Você pode, também, usar o método sort_values() para ordenar os valores conforme
a sua vontade.
[6]: reduc.mean()
[7]: reduc.std()
[8]: reduc.describe()
dados
[11]: dados.to_excel('Resources/planilha_python.xlsx')
t = np.linspace(0,50,204) # Criando o
,→eixo do tempo[s]
A = 2 # Amplitude do
,→movimento[m]
w = 0.5 # Frequência de
,→oscilação[rad/s]
X = A*np.cos(phi+w*t) # Equação da
,→elongação (MHS)
plt.figure(1,figsize=(8,4)) # Criando a
,→figura e definindo seu número e tamanho em X e Y
plt.plot(t,X,'b',linewidth = 4) #
,→Plotando os valores de X e Y e definindo a cor do gráfico
plt.grid(True) # Plotando a
,→grade
plt.plot(t,X,'g.') # Plotando os
,→valores de X e Y e definindo a cor do gráfico
plt.grid(True) # Plotando a
,→grade
plt.subplot(1,2,2)
plt.plot(t,X,'m:',linewidth = 3) #
,→Plotando os valores de X e Y e definindo a cor do gráfico
plt.xscale('log') # Mudando a
,→escala do gráfico
plt.grid(True) # Plotando a
,→grade
Você também pode plotar gráficos do tipo scatter, para a plotagem de uma nuvem de
pontos.
plt.figure(1,figsize=(8,4)) # Criando a
,→figura e definindo seu número e tamanho em X e Y
rand = np.random.randn(len(t))
plt.scatter(t,rand,color ='b',marker ='2')
,→ # Plotando os valores de X e Y e definindo a cor
,→do gráfico
plt.grid(True) # Plotando a
,→grade
x2 = np.linspace(0, 4, 65)
y2 = np.linspace(0, 4, 65)
f = interp2d(x, y, Z, kind='cubic')
Z2 = f(x2, y2)
plt.figure(6,figsize=(8,6))
plt.subplot(1,2,1)
plt.pcolormesh(X, Y, Z)
plt.show()
x.plot_surface(X,Y,Z,cmap = cm.ocean)
y.plot_surface(X2,Y2,Z2,cmap = cm.ocean)
[19]: <mpl_toolkits.mplot3d.art3d.Poly3DCollection at
,→0x17d26ff8fa0>
[ ]:
Num sistema local, a barra de treliça plana possui apenas um grau de liberdade (gdl)
por nó, tendo sua matriz de rigidez expressa por:
" #
EA 1 −1
Kll = (5.1)
L −1 1
Adotando o eixo x’ (local) sobre o eixo da barra (conforme figura anterior), a matriz
local, considerando o grau de liberdade adicional y’ perpendicular ao eixo x’, tem a
seguinte configuração, que não altera suas propriedades.
1 0 −1 0
Kll = 0
EA 0 0 0 (5.2)
L
−1 0 1 0
0 0 0 0
ui 0 cos θ sin θ 0 0 ui
vi0 − sin θ cosθ 0 0 vi
= (5.7)
u 0 0 0 cos θ sin θ u j
j
v j0 0 0 − sin θ cos θ vj
Ou ainda:
U l = ΘU G (5.8)
cos θ sin θ 0 0
− sin θ cosθ 0 0
Θ=
(5.9)
0 0 cos θ sin θ
0 0 − sin θ cos θ
Escrevendo, agora, as equações de equilíbrio local (de uma barra de treliça plana) e
equilibrio global (de toda estrutura), temos:
KlL U l = F l (5.10)
KG U G = FG (5.11)
FG = ΘT Fl (5.12)
Θ T KlL ΘU G = Θ T F l (5.13)
KlG U G = F G (5.14)
Sendo possível afirmar que a matriz de rigidez em coordendas globais pode ser expressa
por:
Neste exemplo é possível verificar a presença de 4 barras de treliça plana, 4 nós e 8 gdl
(2 por nó). A numeração dos graus de liberdade é feita nó a nó, onde a direção x tem o
primeiro gdl do nó e a direção y o segundo, dessa forma, a numeração dos gdls para o
nó n é dada por:
gdlh = 2n − 1 (5.16)
gdlv = 2n (5.17)
1 0 −1 0 1
29.5 ∗ 106
K1 = 0 0 0 0
2
40 −1
0 1 0
3
0 0 0 0 4
0 0 0 0 5
29.5 ∗ 106
0 1 0 −1
6
K2 =
30 −1 0
1 0
3
0 −1 0 1 4
.64 .48 −.64 −.48 1
29.5 ∗ 106
.48 .36 − .48 − .36 2
K3 =
50 .48 −.36 .48
.36 5
0 0 0 0 6
1 0 −1 0 7
29.5 ∗ 106
K4 = 0 0 0 0
8
40 −1
0 1 0
5
0 0 0 0 6
Perceba que cada linha e coluna estão numeradas conforme o seu grau de liberdade
correspondente.
As matrizes locais serão agora alocadas na matriz global(8x8) conforme os seus graus
de liberdade. Caso haja a superposição de valores, esses devem ser somados.
22.68 5.76 −15 0 −7.68 −5.76 0 0 1
5.76
4.32 0 0 −5.76 −4.32 0 0
2
−15 0 15 0 0 0 0 0
3
29.5 ∗ 106
0 0 0 20 0 −20 0 0
4
K=
600 −7.68 −5.76
0 0 22.68 5.76 −15 0
5
−5.76 −4.32 0 −20 5.76 24.32 0 0
6
0
0 0 0 −15 0 15 0
7
0 0 0 0 0 0 0 0 8
0 1
0 2
20000 3
G
0 4
F =
0 5
(5.20)
−25000 6
0 7
0 8
1 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0
2
0 0 15 0 0 0 0 0
3
6
29.5 ∗ 10 0 0 0 1 0 0 0 0
4
KR = (5.21)
600 0
0 0 0 22.68 5.76 0 0
5
0 0 0 0 5.76 24.32 0
6
0 0 0 0 0 0 1 0
7
0 0 0 0 0 0 0 0 8
KR U = FG (5.22)
Kll U l = F l (5.23)
5.2 INTRODUÇÃO
A análise matricial de treliças requer a criação de arrays que nos permitem modelar a
estrutura de forma matemática. São necessárias:
Para criação dessas arrays os dados serão importados através do módulo pandas de
planilha do Excel chamada entrada.xlsx. A planilha de entrada de dados deve
ter duas abas, a primeira chamada de Nós contendo as coordenadas de cada nó e a
segunda chamada Barras com as conectividades (nó inicial e final) e as propriedades
de cada barra.
15kN
9kN 9kN
6
1m 1m 1m
8kN 2 10 8kN
1 3 5 9 11 12
7
2m 2m 2m 2m 2m 2m
Figura 14 – Estrutura em estudo
barras = pd.read_excel('resources/entrada.xlsx',
,→sheet_name='Barras')
nos.index += 1
barras.index += 1
[4]: X Y RX RY FX FY
1 0 0 1.0 1.0 0.0 0.0
2 2 1 0.0 0.0 8000.0 -9000.0
3 2 0 0.0 0.0 0.0 0.0
4 4 2 0.0 0.0 8000.0 -9000.0
5 4 0 0.0 0.0 0.0 0.0
6 6 3 0.0 0.0 0.0 -15000.0
7 6 0 0.0 0.0 0.0 0.0
8 8 2 0.0 0.0 -8000.0 -9000.0
9 8 0 0.0 0.0 0.0 0.0
10 10 1 0.0 0.0 -8000.0 -9000.0
11 10 0 0.0 0.0 0.0 0.0
12 12 0 0.0 1.0 0.0 0.0
[5]: barras
[5]: N1 N2 A E
1 1 2 0.01 210000000000
2 1 3 0.01 210000000000
3 2 3 0.01 210000000000
4 2 4 0.01 210000000000
5 2 5 0.01 210000000000
6 3 5 0.01 210000000000
7 4 5 0.01 210000000000
8 4 6 0.01 210000000000
9 4 7 0.01 210000000000
10 5 7 0.01 210000000000
11 6 7 0.01 210000000000
12 6 8 0.01 210000000000
13 7 8 0.01 210000000000
14 7 9 0.01 210000000000
15 8 9 0.01 210000000000
16 8 10 0.01 210000000000
17 9 10 0.01 210000000000
18 9 11 0.01 210000000000
19 10 11 0.01 210000000000
20 10 12 0.01 210000000000
21 11 12 0.01 210000000000
[6]: plt.figure(1,figsize=(12,4))
plt.ylim(-1,5)
if RY == 1:
plt.scatter(X,Y,400,marker =6,zorder = -2,color
,→='gray')
if Fx >0:
plt.arrow(X-1.5,Y,1,0,width =0.05,color='k')
plt.text(X-1.5,Y,'{}kN'.format(Fx/1000),va='bottom')
if Fx <0:
plt.arrow(X+1.5,Y,-1,0,width =0.05,color='k')
plt.text(X+.5,Y,'{}kN'.format(Fx/1000),va='bottom')
if Fy >0:
plt.arrow(X,Y-1.5,0,1,width =0.05,color='k')
plt.text(X,Y,'{}kN'.format(Fy/
,→1000),va='bottom',rotation=90)
if Fy <0:
plt.arrow(X,Y+1.5,0,-1,width =0.05,color='k')
plt.text(X,Y+.5,'{}kN'.format(Fy/
,→1000),ha='right',rotation=90)
plt.plot(x,y,'black')
plt.scatter(x,y, s=80,marker ='o',color ='black')
#plt.grid(True)
Vamos, então, determinar os comprimentos das barras e seus cossenos diretores. Para
isso vamos percorrer DataFrame de barras e a cada passo acessar o DataFrame de nós
para obter suas coordendas. Os valores cálculados serão armazenados em listas que
serão inseridas no DataFrame ao fim do processo.
L = np.sqrt(Lx**2 + Ly**2)
Em posse das propriedades das barras podemos agora montar as matrizes de rigidez
locais e acoplalas na matriz de rigidez global. Por se tratar de barras de treliça plana
cada nó possui 2 graus de liberdade (deslocamentos horizontal e vertical), portanto em
treliças planas o números de graus de liberdade sempre será o dobro do número de
nós.
Neste nosso exemplo teremos então 24 graus de liberdade, esses são numerados em
função do número do nó conforme as expressões a seguir:
gdlh = 2n − 1
gdlv = 2n
Nossa matriz de rigidez global será então uma matriz de ordem 24x24, em que os
graus de liberdade ímpares correspondem aos deslocamentos horizontais e pares aos
verticais.
A matriz de rigidez global é a obtida pela superposição das matrizes de rigidez locais
nos respectivos graus de liberdade. Inicialmente a matriz global K deve ser pré alocada
como uma matriz de zeros.
L = barras.loc[barra, 'L']
sen = barras.loc[barra, 'sen']
cos = barras.loc[barra, 'cos']
A = barras.loc[barra, 'A']
E = barras.loc[barra, 'E']
N1 = barras.loc[barra, 'N1']
N2 = barras.loc[barra, 'N2']
# Matriz de rotação
Mrot = np.array([[ cos, sen, 0, 0],
[-sen, cos, 0, 0],
[ 0, 0, cos, sen],
[ 0, 0, -sen, cos]])
for no in nos.index:
RX, RY = nos.loc[no, ['RX','RY']]
# Se RX restrito aplica sobre gl de X
if RX == 1:
gl = 2*no - 1
K[:, gl-1] = 0
K[gl-1, :] = 0
K[gl-1, gl-1] = 1
print('Aplicando restrição horizontal no nó {:d}.'.
,→format(no))
if RY == 1:
gl = 2*no
K[:, gl-1] = 0
K[gl-1, :] = 0
K[gl-1, gl-1] = 1
print('Aplicando restrição vertical no nó {:d}.'.
,→format(no))
Com a matriz global restringida vamos montar o vetor de forças aplicadas. Este vetor
tem como dimensão o número de graus de liberdade.
[11]: F = np.zeros(maxgl)
F[gl2-1] = FY
[13]: U = np.linalg.solve(K, F)
[14]: e = 1000
for barra in barras.index:
# Vamos passar os nós para as variáveis N1 e N2
N1 = barras.loc[barra, 'N1']
N2 = barras.loc[barra, 'N2']
dx = np.array([U[2*N1-2],U[2*N2-2]])
dy = np.array([U[2*N1-1],U[2*N2-1]])
y = [y1,y2]
x = [x1,x2]
plt.figure(1,figsize=(12,4))
plt.plot(x,y,'g:')
plt.plot(x+dx*e,y+dy*e,'black')
plt.scatter(x+dx*e,y+dy*e, s=80,marker ='o',color
,→='black')
#plt.grid(True)
_=plt.title('Treliça deformada')
[15]: R = np.dot(Kcompleta,U)
print(R)
[16]: plt.figure(1,figsize=(12,4))
plt.xlim(-2,15)
plt.ylim(-1,5)
gl1 = 2*no - 1
gl2 = 2*no
Fx = R[gl1-1]
Fy = R[gl2-1]
if RY == 1:
plt.arrow(X,Y,0,1,width =0.05,color='k')
plt.text(X+0.2,Y+0.8,'{:.2f}kN'.format(Fy/
,→1000),va='bottom')
plt.plot(x,y,'black')
plt.scatter(x,y, s=80,marker ='o',color ='black')
#plt.grid(True)
Para finalizar a análise, é interessante o cálculo dos esforços atuantes em cada elemento,
para isso, realiza-se o script abaixo:
[17]: Esf = []
L = barras.loc[barra, 'L']
sen = barras.loc[barra, 'sen']
cos = barras.loc[barra, 'cos']
A = barras.loc[barra, 'A']
E = barras.loc[barra, 'E']
N1 = barras.loc[barra, 'N1']
N2 = barras.loc[barra, 'N2']
# Matriz de rotação
Mrot = np.array([[ cos, sen, 0, 0],
Ul = np.zeros(4)
Ul[0] = U[2*N1-2]
Ul[1] = U[2*N1-1]
Ul[2] = U[2*N2-2]
Ul[3] = U[2*N2-1]
F = np.dot(Kl,np.dot(Mrot,Ul))
Esf.append(F[2])
Agora, vamos plotar os esforços, sinalizando as barras comprimidas pela cor azul e as
tracionadas pela cor vermelha.
plt.figure(1,figsize=(18,4.5))
if ax>0:
cor = 'r'
elif ax == 0:
cor = 'k'
else:
cor = 'b'
plt.plot(x,y,cor,zorder = -1)
plt.text(np.mean(x),np.mean(y),'{:.2f}kN'.format(ax/
,→1000),rotation =180*np.arctan(tg)/np.pi,
horizontalalignment='center',
verticalalignment='center',
size = 16,
weight = 'bold')
_=plt.title('Esforços atuantes')