0% acharam este documento útil (0 voto)
22 visualizações31 páginas

T2 MNUM FelipeBaglioli

Enviado por

Felipe Baglioli
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
22 visualizações31 páginas

T2 MNUM FelipeBaglioli

Enviado por

Felipe Baglioli
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 31

UNIVERSIDADE FEDERAL DO PARANÁ

Felipe Baglioli

Método dos Elementos Finitos Bidimensional


Aplicado a uma Viga Biapoiada

CURITIBA
2023
Universidade Federal do Paraná – Setor de Tecnologia

Sumário
1 Introdução e Contextualização 4

2 Métodos 4
2.1 Apresentação do Problema e Formulação Matemática . . . . . . . . . . 4
2.2 Implementação Computacional . . . . . . . . . . . . . . . . . . . . . . 9

3 Resultados e Discussão 16
3.1 Deslocamentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2 Tensões horizontais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

4 Considerações Finais 20

A Código desenvolvido 21

3
Universidade Federal do Paraná – Setor de Tecnologia

1 Introdução e Contextualização
Em várias áreas da engenharia, é comum a presença de problemas que são descritos
por uma ou mais equações diferenciais. Muitas vezes, a obtenção de uma solução ana-
lítica para tais problemas é custosa e, em alguns casos, impossível. Portanto, uma série
de esquemas numéricos foram desenvolvidos, simplificando a resolução dessas equações
através de uma discretização espacial, temporal, ou espaço-temporal (Šolín, 2005). Um
exemplo desses métodos muito utilizado principalmente na área de Engenharia Civil é
o Método dos Elementos Finitos (MEF ou FEM, para a sigla em inglês).
O MEF consiste na separação de um domínio geral em pequenas partes, ou elemen-
tos. Para elementos bidimensionais, esses são unidos por pontos denominados nós, além
de arestas. Dessa forma, buscamos resolver uma forma fraca da equação que descreve
determinada propriedade de interesse no domínio, apenas nos nós. Posteriormente, os
valores dessa propriedade nos pontos interiores aos elementos são obtidas através de
interpolação. Para tal, são utilizadas funções específicas, que recebem a alcunha de
funções de forma (Zienkiewicz e Taylor, 2005).
No caso aqui apresentado, o MEF é empregado para a resolução do campo de
deslocamentos de uma viga biapoiada. Especificamente, a estrutura considerada não
possui altura desprezível e, portanto, será aplicada a forma bidimensional do MEF,
visando resolver os deslocamentos nodais verticais e horizontais.

2 Métodos

2.1 Apresentação do Problema e Formulação Matemática

Nesse caso, utilizamos o Método dos Elementos Finitos para avaliar a deformação
de uma viga, apresentada na figura 1. As dimensões consideradas são L = 9, 0 m,
h = 3, 0 m, e b = 0, 1 m. Como mostrado no esquema geral, forma considerados dois
suportes verticais na parte inferior da viga, de extensões L/10 = 0, 9 m. Além disso,
as cargas aplicadas sobre a estrutura são seu peso próprio p e a carga uniformemente
distribuída q, aplicada na região superior. Seus valores foram tomados como p = 25
kN/m3 e q = 200 kN/m. Por fim, as propriedades materiais utilizadas foram módulo
de elasticidade E = 2 × 107 kN/m2 e coeficiente de Poisson ν = 0, 3.
Para a modelagem do problema, foram utilizados elementos finitos triangulares, com
funções de forma lineares em x e y. Usualmente, esse tipo de elemento é denominado
CST, para a sigla em inglês de Constant Strain Triangle, ou Triângulo de Tensão
Constante, como será discutido mais a frente. Para essa formulação, temos 3 nós por
elemento, e portanto, no problema bidimensional, 6 graus de liberdade (G.L.’s) por

4
Universidade Federal do Paraná – Setor de Tecnologia

Figura 1: Esquema geral do problema a ser analisado.

elemento. Ainda, é importante garantir uma numeração em sentido anti-horário para


os nós de cada elemento. Sob essa condições, as funções de formas Ni relativas aos nós
i = 1, 2, 3 podem ser obtidas através de
1
Ni = (ai + bi x + ci y) , (1)
2Ae
onde Ae representa a área do elemento, e ai , bi e ci são funções das coordenadas nodais,
definidas por

= x2 y 3 − y 2 x3 = y2 − y3 = −x2 + x3
  
 a1 b1  c1

 
 


a2 = −x1 y3 + y1 x3 , b2 = −y1 + y3 , e  c2 = x 1 − x 3 . (2)
a3 = x 1 y 2 − y 1 x 2 b3 = y 1 − y 2 c3 = −x1 + x2

 
 

Utilizando álgebra linear, podemos obter o valor de Ae com base nessas coordenadas,
de acordo com
1
Ae = (x2 y3 + x1 y2 + x3 y1 − x2 y1 − x1 y3 − x3 y2 ) . (3)
2

A equação 3 também é uma boa forma de checagem da correta ordem de enumeração


dos nós, uma vez que um valor negativo de área indica um sentido horário, o que é
indesejado na formulação que será apresentada.

5
Universidade Federal do Paraná – Setor de Tecnologia

Considerando um vetor de deslocamentos nodais elemental ue , e as funções de forma


Ni , podemos obter a expressão de interpolação para deslocamentos u em cada ponto
do domínio, como
 
u1 

 

 v1 

 

N1 0 N2 0 N3 0
( ) " # 
u u 
 
u= = 2
= N · ue , (4)
v 0 N1 0 N2 0 N3 

 v2 


u

 



  3 

v3
 

onde u representa deslocamentos horizontais e v deslocamentos verticais. Portanto,


com base em N, podemos dar início ao cálculo da matriz de rigidez elementar Ke . Na
realidade, essa matriz é descrita pela expressão
Z
Ke = B⊺ DB dVe , (5)
Ve

onde Ve representa o volume do elemento. Para um estado plano de tensões, com


espessura t constante, essa expressão é simplificada para

Ke = tAe B⊺ DB . (6)

Nas fórmulas acima, observamos o aparecimento de duas novas matrizes, B e D. A


segunda, muitas vezes denominada de matriz de rigidez do material, pode ser obtida
em função do módulo de elasticidade E e no coeficiente de Poisson ν. Considerando
estado plano de tensões, pode ser calculada por

1 ν 0
 
E 
D= ν 1 0 . (7)

1−ν 2
0 0 (1 − ν)/2

Por sua vez, a matriz de deformação-deslocamento B é relacionada intrinsecamente


às funções de forma Ni , uma vez que sua obtenção dá-se por B = LN, onde L é uma
matriz de operadores diferenciais. No caso dos elementos CST, pode ser obtida por

b 0 b2 0 b3 0
 
1  1
B=  0 c1 0 c2 0 c3  (8)

2Ae
c 1 b1 c 2 b2 c 3 b3 ,

onde os bi e ci são as funções das coordenadas previamente definidas. De acordo com


os valores calculados para cada grau de liberdade nas matrizes de rigidez elementares,
podemos montar a matriz global K, seguindo o mesmo algoritmo explanado no rela-
tório anterior. Com essa definição de B podemos notar que, de fato, a matriz é de
coeficientes constantes. Desse modo, obteremos uma matriz de rigidez constante para
cada elemento. Consequentemente, calcularemos tensões constantes no interior de cada
elemento, explicando o nome Constant Strain Triangle dado à esse tipo de elemento.

6
Universidade Federal do Paraná – Setor de Tecnologia

Podemos agora passar para a obtenção dos vetores de força elementares, f e . Nesse
caso, podemos separar as forças atuantes sobre o domínio em dois grupos: forças de
volume e forças de superfície. De um modo geral, forças de volume são aquelas que,
como o nome sugere, atuam sobre o volume total da viga, também conhecidas como
forças de campo. No problema estudado, possuímos apenas o peso próprio da estrutura
nessa classificação. Isso é, as cargas de volume são

0
( ) ( )
p
p= x = . (9)
py −p

O sinal negativo representa a orientação do peso próprio, verticalmente para baixo.


Como p é uma força de campo uniforme, e trabalhamos com uma viga de espessura t
constante, o vetor de forças de volume fve pode ser expresso por
Z Z
fve = N p dVe = t

N⊺ p dAe . (10)
Ve Ae

Como as funções de forma Ni foram construídas de maneira a valer 1 nos seus res-
pectivos nós e 0 nos demais, e os elementos de p são constantes, a integral apresentada
resulta no cálculo do volume de uma pirâmide de altura unitária, cuja base é o próprio
elemento que está sendo avaliado. Isso é, podemos nesse caso representar o vetor de
forças de volume como
 0 
 
 
−p

 

 

0
 
tA

 

e
fv =
e
. (11)
3  −p
0

 


 

 

−p
 

Diferentemente do caso das forças de volume, as forças de superfície não necessaria-


mente são aplicadas sobre todos os elementos do domínio. No caso estudado, possuímos
apenas uma carga uniformemente distribuída q sobre a parte superior da viga. Dessa
forma, aplicaremos cargas diferentes de zero apenas sobre as arestas nas quais q está
presente. Ou seja, nos elementos contendo arestas no topo da viga, temos um vetor de
cargas de superfície dado por

0
( ) ( )
q
q= x = . (12)
qy −q

Novamente, o sinal negativo está de acordo com a orientação da carga distribuída.


Dessa forma, o vetor elementar de forças de superfície, definido pela integral na super-
fície Se do elemento, é Z
fs = N⊺ q dSe .
e
(13)
Se

7
Universidade Federal do Paraná – Setor de Tecnologia

Considerando que os elementos de q também não constantes, a integral acima se


torna o cálculo da área de um triângulo de altura unitária, cuja base é a aresta do
elemento sobre a qual a carga é aplicada. Por exemplo, caso tenhamos um elemento
cuja aresta 1-2 se encontra na parte superior da viga, seu vetor de forças superficiais
elementar tornar-se-á:
 0 
 
 
−q 

 

 

0
 
L

 

1,2
fv =
e
. (14)
2   −q 

0

 


 

 
0
 

Acima, L1,2 representa o comprimento da aresta. Note que, nesse caso, aplicamos
a carga uniforme apenas nos gruas de liberdade verticais dos nós 1 e 2, que são por
ela afetados. Portanto, esse vetor é somado ao vetor de forças de volume em todos
elementos que contém arestas no topo da estrutura. Assim, formamos os vetores de
forças elementares, e, de acordo com os graus de liberdade de cada nó, podemos montar
o vetor de forças global f . Com isso, construímos o sistema matricial global

K·u=f, (15)

e podemos resolvê-lo através de ordenação e remoção de parâmetros nodais. Para isso,


implementamos as condições de contorno devido aos suportes verticais presentes na
figura 1. Para a viga estudada, tempo apoios nos trechos de x = 0 até x = 0, 9 m; e
x = 8, 1 até x = 9 m, ambos em y = 0. Portanto, definimos que, em todos os nós cuja
coordenada y é nula, e a coordenada x está dentro dos intervalos mencionados, o grau
de liberdade referente ao movimento vertical tem seu deslocamento anulado.
Para o problema bidimensional avaliado, sabemos que o G.L. horizontal de cada nó
de número n é dado por 2n, enquanto o G.L. vertical é expresso por 2n+1. Claramente,
por estarmos utilizando a linguagem Python, nossas enumerações iniciam-se em zero,
e as expressões acima devem ser avaliadas levando isso em consideração.
Com a implementação dessas condições, podemos finalmente obter o deslocamento
de cada nó da malha utilizada. Assim, podemos obter as tensões, considerando tensões
iniciais nulas, através da expressão
 
u
 1

 
 v1 
  
 

 σx 
 
  u 
 
σ =  σy  = Dε = DLNue = DB  2  (16)
v2 
τxy
  

u 
 



 3 

 
v3

Na próxima seção, será apresentado o código em Python desenvolvido para a im-


plementação computacional da relações supracitadas.

8
Universidade Federal do Paraná – Setor de Tecnologia

2.2 Implementação Computacional

O código desenvolvido para a resolução de problema está disponibilizado, na íntegra,


no apêndice A, e também neste link para o GitHub. Nessa seção, o algoritmo será
explanado, parte por parte. Primeiramente, tratemos das funções definidas no início
do código. A primeira delas, calc_lenght, é a mais simples, e visa simplesmente
a obtenção do comprimento de um segmento de reta definido por dois pontos. Seu
código é
1 def calc_lenght(x1, y1, x2, y2):
2
3 side = np.sqrt((x2 - x1)**2 + (y2 - y1)**2)
4

5 return side

Acima, simplesmente utilizamos as coordenadas dos pontos que definem a reta, e


obtemos seu comprimento pela equação
q
L= (x2 − x1 )2 + (y2 − y1 )2 . (17)

Então, definimos duas outras funções, relativamente semelhantes, que buscam gerar
e plotar malhas e configurações deformadas no domínio da viga. Nesse contexto, função
delaunay_mesh_mid é utilizada para criação de malhas, e é implementada como
1 def delaunay_mesh_mid(L, h, divX, divY, save = False, node_dots = False,
2 node_labels = False, element_labels = False,
target_coords = None):
3

4 # Garante que o ponto central inferior seja um no:


5
6 x_points = np.unique(np.concatenate([np.linspace(0, L, divX), [L/2]]))
7 y_points = np.unique(np.concatenate([np.linspace(0, h, divY), [0]]))
8
9 # vetores com coordenadas dos pontos:
10
11 X, Y = np.meshgrid(x_points, y_points)
12
13 # conversao em um array 2d:
14
15 vertices = np.column_stack((X.ravel(), Y.ravel()))
16
17 # Criacao da malha:
18
19 tri = Delaunay(vertices)
20
21 # Coleta das coord. dos nos e da matriz de incidencia:
22
23 nodes = tri.points
24 inci = tri.simplices
25
26 # Calculos dos centroides de cada elemento:
27

9
Universidade Federal do Paraná – Setor de Tecnologia

28 centroids = np.mean(nodes[inci], axis=1)


29
30 # Enumeracao dos elementos de acordo com centroides, para melhor
condicionamento:
31
32 sorting_order = np.lexsort((centroids[:, 0], centroids[:, 1]))
33 inci_sorted = inci[sorting_order]
34
35 fig = plt.figure(figsize = (24, 16))
36
37 # Plotagem da malha:
38

39 plt.triplot(nodes[:, 0], nodes[:, 1], inci_sorted, color = ’green’, ls


= ’-’, lw = 0.8)
40
41 # Plotagem dos nos:
42 if node_dots == True:
43 plt.scatter(nodes[:, 0], nodes[:, 1], color = ’orange’, marker = ’o’,
s = 70)
44
45 offsetx = 0.12
46 offsety = 0.2
47
48 # Anbotar numeros dos elementos em seus centroides
49 for element_number, element in enumerate(inci_sorted):
50
51 centroid_x = np.mean(nodes[element, 0])
52 centroid_y = np.mean(nodes[element, 1])
53
54 if element_labels == True:
55 plt.text(centroid_x, centroid_y, str(element_number), ha=’center’
, va=’center’, color=’green’, fontsize=20)
56
57 # Anotar numeros dos nos:
58 if node_labels == True:
59

60 for node_number, node_coordinate in enumerate(nodes):


61 plt.text(node_coordinate[0] + offsetx, node_coordinate[1] +
offsety, str(node_number), ha=’center’, va=’center’, color=’orange’,
fontsize=20)
62
63 N = len(inci_sorted) # Numero de elementos
64
65 # Parametros de plotagem:
66
67 plt.xlabel(’X (m)’)
68 plt.ylabel(’Y (m)’)
69 plt.title(’N = ’ + str(N))
70 plt.axis(’scaled’)
71 plt.xlim(-1, L+1)
72 plt.ylim(-1, h+1)
73 plt.grid(axis = ’both’, ls = ’:’)
74 plt.tight_layout()
75 if save == True:

10
Universidade Federal do Paraná – Setor de Tecnologia

76 plt.savefig(’grid’+str(N)+’.png’)
77 else:
78 plt.show()
79
80 # Obtencao do indice do no passado como target_index
81

82 if target_coords is not None:


83 for i, node in enumerate(nodes):
84 if np.allclose(node, target_coords):
85 target_index = i
86 break
87

88 # Retorno dos resultados de interesse:


89 return nodes, inci_sorted, target_index

O algoritmo listado acima recebe como entradas os limites do domínio, ou seja,


seu comprimento L e sua altura h. Ainda, passamos o número de nós desejado em
cada uma das direções, divX e divY. Criamos a grade em x e y utilizando a função
linspace, e tomamos medidas para garantir o posicionamento de um nó na posição
central inferior da viga.
Com essas informações, utilizamos a função Delaunay do módulo scipy, para
a criação da malha. A triangulação de Delaunay, ou tesselação de Delaunay, é um
procedimento geométrico que permite a discretização de um domínio em triângulos,
dado um conjunto de vértices no interior desse domínio. Basicamente, o procedimento
é realizado avaliando círculos nos quais os triângulos são inscritos. Na malha final,
para qualquer triângulo, seu círculo inscrito deve conter apenas os vértices do próprio
triângulo, e mais nenhum dos vértices do grupo original. Dessa forma, podemos esperar
grades uniformes e com elementos pouco deformados (Lee e Schachter, 1980).
Após a criação da malha, reordenamos os elementos de acordo com seus centroides,
buscando mais a frente, gerar matrizes mais bem condicionadas. Posteriormente, utili-
zamos a função triplot para a plotagem da malha gerada. Como resultados, a função
delaunay_mesh_mid retorna os arrays contendo coordenadas dos nós (nodes) e a
matriz de incidência dos elementos (inci_sorted). A figura 2 apresenta, a título
de exemplo, uma das grades geradas com esse algoritmo. Nesse caso, apresentamos
os elementos em verde, os nós em amarelo, e, adicionalmente, os números dos nós e
elementos.
Por fim, adicionamos uma opção para a captura do índice de um nó de interesse na
malha gerada, retornado como taget_index. Essa funcionalidade será útil durante
o pós-processamento, para avaliar a convergência do método desenvolvido.
A figura 4 apresenta as 6 malhas que foram utilizadas para a resolução do problema
em questão. Tais malhas foram geradas para 24, 72, 200, 400, 800 e 1800 elementos.
A terceira função utilizada durante a implementação computacional foi
deform_plot. Muito semelhante ao final da função anterior, desenvolvemos ela como:

11
Universidade Federal do Paraná – Setor de Tecnologia

Figura 2: Malha com 24 elementos produzida pela função delaunay_mesh_mid.

1 def deform_plot(nodes, desloc, els, save = False, fator_def = 1.0,


2 node_dots = False, node_labels = False, element_labels =
False):
3
4 # Reorganizar a matriz de deslocamentos para um array 2D e aplicar
fator_def:
5

6 deformed_node_coordinates = nodes + (desloc.reshape((-1, 2))*fator_def)


7
8 # Plotar a grade deformada:
9 fig = plt.figure(figsize = (24, 16))
10
11 plt.triplot(deformed_node_coordinates[:, 0], deformed_node_coordinates
[:, 1], els, color = ’green’, ls = ’-’, lw = 0.8)
12
13 # Adicionar pontos dos nos:
14 if node_dots == True:
15 plt.scatter(deformed_node_coordinates[:, 0],
deformed_node_coordinates[:, 1], color = ’orange’, marker = ’o’, s =
70)
16
17 offsetx = 0.1
18 offsety = 0.15
19
20 # Adicionar numeros dos elementos:
21 for element_number, element in enumerate(els):
22 centroid_x = np.mean(deformed_node_coordinates[element, 0])
23 centroid_y = np.mean(deformed_node_coordinates[element, 1])
24 if element_labels == True:
25 plt.text(centroid_x, centroid_y, str(element_number), ha=’center’
, va=’center’, color=’green’, fontsize=20)
26

12
Universidade Federal do Paraná – Setor de Tecnologia

27 # Adicionar numeros dos nos:


28 if node_labels == True:
29 for node_number, node_coordinate in enumerate(
deformed_node_coordinates):
30 plt.text(node_coordinate[0] + offsetx, node_coordinate[1] + offsety
, str(node_number), ha=’center’, va=’center’, color=’orange’, fontsize
=20)
31
32 # Parametros do plot
33
34 N = len(els)
35

36 plt.xlabel(’X (m)’)
37 plt.ylabel(’Y (m)’)
38 plt.title(’N = ’ + str(N))
39 plt.axis(’scaled’)
40 plt.xlim(-1, L+1)
41 plt.ylim(-1, h+1)
42 plt.grid(axis = ’both’, ls = ’:’)
43 plt.tight_layout()
44 if save == True:
45 plt.savefig(’def’+str(N)+’.png’)
46 else:
47 plt.show()
48
49 return None

De fato, a função acima tem o objetivo de plotar a configuração deformada da grade


gerada por delaunay_mesh_mid. Portanto, recebe, além das coordenadas dos nós e
da matriz de incidência, a matriz de deslocamentos nodais como parâmetro de entrada.
Dessa forma, será apenas empregada após a resolução do problema. Para a plotagem,
inicialmente convertemos a matriz de deslocamentos em um array bidimensional, e os
adicionamos às coordenadas nodais. Posteriormente, utilizamos novamente a função
triplot para a plotagem da malha deformada. A figura 3 apresenta um exemplo da
saída dessa função, com um fator de deformação de 100 vezes.
Com a explicação acerca das funções definidas realizada, partimos agora ao código
que resolverá de fato o problema estudado.
1) Malha, matriz D e nós de topo:
Inicialmente, definimos todos os parâmetros de entrada do modelo, referentes ao
caso estudado. Adicionalmente, criamos uma lista de divisões mesh_divs, que contém
o número de nós horizontais e verticais que cada malha terá. Então, para cada elemento
da lista, chamamos a função delaunay_mesh_mid para gerar as diferentes malhas.
Assim, geramos as 6 malhas que serão utilizadas.
Posteriormente, calculamos a matriz D, além de criar uma lista que receberá todos
os nós localizados na parte superior do domínio. Essa lista irá nos auxiliar durante a
implementação do vetor de forças de superfície.

13
Universidade Federal do Paraná – Setor de Tecnologia

Figura 3: Malha com 24 elementos deformada, produzida pela função deform_plot .

2) Cálculo da matriz de rigidez elementar:


Nesse momento, partimos para a implementação das equações (2) a (8). Para cada
elemento, extraímos as coordenadas nodais e, com elas, calculamos a área elementar
e os coeficientes bi e ci . Assim, podemos obter a matriz B para cada elemento. Com
isso, a matriz D e a largura t da viga, calculamos a matriz de rigidez elementar Ke.
3) Vetor de forças de volume elementar:
Para os vetores de força, iniciamos pelas cargas de volume, uma vez que se apli-
cam indiscriminadamente sobre todos os elementos da malha. Para isso, simplesmente
implementamos a equação (11).
4) Vetor de forcas de superfície elementar:
Para as cargas de superfície, necessitamos de um maior cuidado. Obviamente, o
vetor de forças de superfície será nulo em todos elementos que não contenham uma
aresta localizada no extremo superior da viga. Para garantir essa condição, lançamos
mão da lista de nós de topo criada previamente, mesh_divs. Caso o elemento em
que estejamos trabalhando contenha dois de seus nós nessa lista, ele terá uma aresta
no topo do domínio. Nesse caso, extraímos as coordenadas desses nós, bem como seus
índices e, com essas informações aplicamos a equação (14). Após isso, somamos o vetor
elementar de forças de volume ao vetor elementar de forças de superfície, obtendo o
vetor de forças elementar fe.

14
Universidade Federal do Paraná – Setor de Tecnologia

5) Construção da matriz de rigidez e vetor de forças globais:


Agora, criamos uma lista pos que, para cada elemento, apresenta os graus de
liberdade relacionados a cada nó. Com base nessa lista e nas contrapartes elementais,
construímos a matriz de rigidez K e o vetor de forças f global, seguindo o algoritmo
apresentado no trabalho anterior.
6) Condições de contorno essenciais:
Para implementar os apoios, definimos que quaisquer nós localizados em y = 0 e
x na região dos apoios, o deslocamento vertical é zero. Para cada um desses graus de
liberdade, guardamos seu índice em uma lista. Essa lista é então utilizada para ordenar
a matriz e o vetor posteriormente.
7) Ordenação e resolução do sistema:
Nesse momento, criamos uma lista ordem que contém todos os números dos G.L.’s
do problema global. Então, reorganizamos essa lista, posicionando os graus de liberdade
apoiados em seu final.
Utilizando as opções avançadas de indexação do numpy, reordenamos K e f de
acordo com a nova ordem. Em algumas malhas, podemos notar um leve mau condi-
cionamento da matriz de rigidez global, que pode se tornar esparsa. Portanto, para
a resolução do sistema livre, optamos pelo emprego do módulo de álgebra linear para
matrizes esparsas. Por essa razão, é utilizado spsolve para a obtenção dos desloca-
mentos não apoiados.
8) Processamento dos deslocamentos:
Essa etapa consiste na plotagem da configuração deformada da viga para cada
diferente malha. Além disso, nela salvamos o deslocamento vertical dy e horizontal dx
do nó central inferior, para o diagrama de convergência. O deslocamento total d desse
nó é obtido por q
d = d2x + d2y . (18)

9) Gráfico de convergência:
Essa seção é dedicada para a plotagem do gráfico de convergência. Para cada malha
gerada, salvamos o número de nós e o deslocamento total do nó central inferior. Aqui
então, plotamos essas listas utilizando matplotlib.
10) Tensões horizontais:
Por fim, recuperamos as tensões horizontais nos nós centrais da malha mais refinada.
Para isso, fazemos um procedimentos semelhante à extração dos elementos de topo,
selecionando todos os elementos que contenham dois nós sobre a seção transversal
central. Então, para cada um desses elementos, obtemos novamente os coeficientes bi
e ci , sua área elementar Ae , e recalculamos sua matriz B.

15
Universidade Federal do Paraná – Setor de Tecnologia

Com isso, buscamos no vetor de deslocamentos nodais os valores relacionados aos


nós de cada elemento, e utilizamos a equação (16) para obtenção de σx . Por fim,
tiramos as médias entre valores obtidos para elementos que compartilham arestas, e
plotamos o gráfico.

3 Resultados e Discussão

Figura 4: Malhas utilizadas para a resolução do problema. N representa o número de


elementos utilizados.

Ao todo, foram utilizadas seis diferentes malhas para a avaliação do problema. A


mais simples dela, já apresentada nas imagens exemplo 2 e 3, possui 24 elementos. A
partir dela, foi realizado um refino h, aumentando o número de elementos nas malhas
posteriores. Tais malhas contém, respectivamente, 72, 200, 400, 800 e 1800 elementos.
Esses números foram escolhidos de forma a avaliar o comportamento do algoritmo não
somente de acordo com o número de elementos, mas também com a uniformidade da
malha. Todas as malhas utilizadas estão apresentadas na figura 4.

16
Universidade Federal do Paraná – Setor de Tecnologia

Figura 5: Configuração deformada da viga obtida para cada diferente malha. N


representa o número de elementos utilizados.

Dessa forma, para cada diferente malha, foram calculadas a configuração deformada
da viga e o deslocamento total do nó central inferior. Adicionalmente, para a malha
mais refinada com 1800 elementos, foram recuperadas as tensões horizontais σx na
seção transversal central da viga.

3.1 Deslocamentos

Com o código desenvolvido, para cada malha foram obtidos os deslocamentos no-
dais verticais e horizontais. Assim, adicionamos esses deslocamentos às coordenadas
originais dos nós, de forma a obter a configuração deformada da viga. A figura 5
apresenta os resultados desse cálculo para cada malha gerada.
A partir desses resultados, podemos notar primeiramente uma tendência de flexibi-
lização da viga para maiores números de elementos. De maneira geral, as grades com
mais elementos permitiram que o domínio se deslocasse mais intensamente. Esse com-
portamento é esperado, uma vez que, conforme adicionamos mais elementos a nossa

17
Universidade Federal do Paraná – Setor de Tecnologia

Figura 6: Convergência do deslocamento do nó central inferior conforme o aumento do


número de elementos da malha utilizada.

malha, chegamos cada vez mais próximos do comportamento contínuo que a estrutura
teria na realidade. Dessa forma, o número de graus de liberdade cada vez mais se
aproxima do que seria analítico.
Esse comportamento pode ser observado com mais clareza ao escolhermos um nó
para realizar a análise. O comportamento do deslocamento do nó central inferior da
viga com o refino da malha pode ser observado no gráfico da figura 6. Nela, claramente
percebemos que, a partir de 200 elementos, o deslocamento desse nó tende a aumentar
levemente conforme adicionamos elementos à malha. Isso não é verdade, entretanto,
para as duas primeiras malhas. Essas, com 24 e 72 elementos, resultaram nos maiores
deslocamentos obtidos para qualquer uma das malhas utilizadas.
Uma possível explicação para esse fato se dá pela aplicação da carga de superfície.
Como nesse caso ela é aplicada na parte superior do domínio, é esperado uma certa
amortização de seu efeito conforme analisamos sessões mais inferiores. Contudo, as
duas primeiras malhas possuem um baixo nível de resolução espacial na direção vertical.
Portanto, falham ao avaliar o efeito desse amortecimento pela elasticidade da estrutura.
Conforme adicionamos mais elementos na direção y, podemos capturar de maneira mais
acurada essa tendência.

18
Universidade Federal do Paraná – Setor de Tecnologia

Figura 7: Distribuição da tensão horizontal σx ao longo da seção transversal central, para


a malha com 1800 elementos.

Ainda de acordo com a figura 6, podemos notar que, ao variar o número de elementos
de 800 para 1800, chegamos a uma diferença entre os valores de deslocamento obtidos
de apenas 0,007 cm. Isso é um indiciativo de que, a partir dessa marca, atingimos a
convergência da malha para refino do tipo h. Obviamente, tal convergência deve ser
avaliada para malhas ainda mais refinadas, de modo a garantir que ela ocorra.

3.2 Tensões horizontais

Como anteriormente mencionado, as tensões horizontais foram avaliadas utilizando


a malha de 1800 nós, para a seção mais central da viga, ou seja, x = L/2 = 4, 5 m. O
gráfico da figura 7 apresenta os valores da tensão σx obtidos nessa seção.
Como mostrado na figura, pode-se notar uma leve simetria em relação a linha média
da viga (y = 1, 5 m). Na região superior dessa linha, observamos tensões horizontais
negativas, chegando próximas de até −9, 0 MPa. Em contrapartida, a região abaixo da
linha é caracterizada por tensões positivas, admitindo valores em módulo semelhantes
aos presentes na área superior. Mais que isso, o valor de tensão horizontal na linha
média da viga pode ser observado como tendente a zero.
Tais comportamentos são esperados, uma vez que, dada a carga uniforme aplicada,
a deformação da estrutura ocorre de forma a tracionar as fibras inferiores e comprimir
as fibras superiores da viga. Assim, por convenção, ao alongamentos caracterizados por

19
Universidade Federal do Paraná – Setor de Tecnologia

tensões horizontais positivas aparecem na região inferior à linha neutra. Outrossim,


encurtamentos, relacionados à tensões horizontais negativas são observados na região
superior à linha neutra. Ainda, podemos inferir que a linha neutra, nesses caso, deveria
realmente localizar-se em y = h/2 = 1, 5 m, devido à simetria do domínio, de das cargas
de superfície e de campo nele aplicadas. Adicionalmente, o gráfico da figura 7 é capaz
de mostrar que, para a malha mais refinada, é possível de se capturar o comportamento
linear das tensões horizontais esperado em uma viga em flexão pura (Beer et al., 2011).

4 Considerações Finais
Novamente, o estudo apresentado demonstra a eficácia do MEF na modelagem de
problemas estruturais. Para um problema bidimensional de relativa baixa complexi-
dade como o mostrado, o custo computacional da solução numérica por MEF é baixo.
Mesmo assim, os resultado obtidos foram de encontro ao que seria esperado, fornecendo
dados úteis e confiáveis.
Adicionalmente, a análise de convergência foi capaz de indicar que, para malhas a
partir de 800 elementos, a solução tende a convergir. Dessa forma, grades mais refina-
das, com maior número de elementos, passam a não implicar em grandes diferenças nos
resultados obtidos. Certamente, outros tipos de refino podem ser empregados, visando
aprimorar ainda mais os resultados obtidos. O uso de funções de forma e elementos
de grau superior, bem como outras técnicas de enriquecimento são essenciais para que,
em problemas de maior complexidade, o MEF atinga os melhores resultados possíveis.

Referências
Beer, F. P. et al. (2011). Flexão Pura, capítulo 4, páginas 228 – 326. McGrawHill. 5
ed.

Lee, D. T. e Schachter, B. J. (1980). Two algorithms for constructing a Delaunay


triangulation. International Journal of Computer and Information Sciences, 9(3):219–
242.

Zienkiewicz, O. C. e Taylor, R. (2005). A Direct Approach to Problems in Elasticity,


capítulo 2, páginas 18–38. Butterworth-Heinemann.

Šolín (2005). Partial Differential Equations, capítulo 1, páginas 1–44. John Wiley
Sons, Ltd.

20
A Código desenvolvido

Listagem 1: MEF_T2_sparse.py - Aplica o MEF para o problema de viga estudado.


Disponível aqui.
1 # -*- coding: utf-8 -*-
2 ’’’
3 ----------------------------------------------------------------------
4 MEF_T2_sparse.py : resolve um viga bidimensional utilizando MEF e a
biblioteca
5 de scipy para matrizes esparsas.
6

7 Autor: Felipe Baglioli


8 Data de criacao: 04/09/2023
9 Ultima alteracao em: 16/04/2023 - Obtencao de tensoes horizontais
10 Contexto: MNUM7122 - 2o trim. de 2023 - Trabalho 2
11 ----------------------------------------------------------------------
12 ENTRADAS:
13
14 - L (float): comprimento em m;
15 - h (float): altura em m;
16 - t (float): espessura em m;
17 - E (float): modulo de elasticidade em kN/m2;
18 - nu (float): coef. de Poisson;
19 - qx e qy (float): cargas de superficie em kN;
20 - px e py (float): cargas de volume em kN;
21 - nx e ny (int): numero de nos da malha em cada direcao.
22
23 ----------------------------------------------------------------------
24 SAIDAS:
25
26 - Graficos de cada uma das malhas utilizadas;
27 - Grraficos da configuracao deformada da viga para cada malha;
28 - Diagrama de convergencia (deslocamento x no. de nos);
29 - Diagrama de tensoes na secao transversal central;
30

31 ----------------------------------------------------------------------
32 ’’’
33 import matplotlib.pyplot as plt
34 from matplotlib import rc
35 import numpy as np
36 import scipy
37 from scipy.spatial import Delaunay
38 from scipy.sparse.linalg import spsolve
39
40 # Parametros gerais para os plots de malha e deformacao:
41
42 font = {’family’ : ’sans-serif’,
43 ’weight’ : ’normal’,
44 ’size’ : 16}
45
46 rc(’font’, **font)
47
48 # ---------------------------- FUNCOES ----------------------------
49
50 def calc_lenght(x1, y1, x2, y2):
51 ’’’
52 --------------------------------------------------------------------
53 Calcula o comprimento de um segmento de reta (x1, y1) ate (x2, y2).
54 --------------------------------------------------------------------
55 ENTRADAS:
56
57 - x1, y1, x2, y2 (int): coordenadas dos pontos que definem a reta.
58 --------------------------------------------------------------------
59 SAIDAS:
60
61 - side (integer): comprimento do segmento.
62 --------------------------------------------------------------------
63 ’’’
64
65 side = np.sqrt((x2 - x1)**2 + (y2 - y1)**2)
66
67 return side
68
69 # --------------------------------------------------------------------
70
71 def delaunay_mesh_mid(L, h, divX, divY, save = False, node_dots = False,
72 node_labels = False, element_labels = False,
73 target_coords = None):
74 ’’’
75 --------------------------------------------------------------------
76 Gera uma malha triangular para um dominio retangular, utilizando o
77 algoritmo de triangulacao de Delaunay e garantindo a colocacao
78 de um no na posicao central inferior do dominio.
79 --------------------------------------------------------------------
80 ENTRADAS:
81
82 - L, h (float): comprimento e altura do dominio, respectivamente;
83 - divX e divY (int): numero de nos a serem posicionados em cada
84 direcao;
85 - target_coords (tupla de 2 val.): contem coordenadas de um no
86 cujo indice deseja ser conhecido.
87
88 FLAGS (boolean):
89
90 - save: padrao False. Caso seja True, a figura da malha sera salva;
91 - node_dots: padrao False. Caso seja True, plota os pontos dos nos;
92 - node_label: padrao False. Caso seja True, plota os numeros dos nos;
93 - element_labels: padrao False. Caso seja True, plota os
94 numeros dos elementos;
95 --------------------------------------------------------------------
96 SAIDAS:
97
98 - nodes (float, array 2D): coordenadas dos nos da malha;
99 - inci_sorted (int, array 2D): matriz de incidencia dos elementos;
100 - target_index (int): indice do no com as coordenadas informadas.
101
102 - Caso save = True: grafico da malha gerada.
103 --------------------------------------------------------------------
104 ’’’
105
106 # Garante que o ponto central inferior seja um no:
107
108 x_points = np.unique(np.concatenate([np.linspace(0, L, divX), [L/2]]))
109 y_points = np.unique(np.concatenate([np.linspace(0, h, divY), [0]]))
110
111 # vetores com coordenadas dos pontos:
112
113 X, Y = np.meshgrid(x_points, y_points)
114

115 # conversao em um array 2d:


116
117 vertices = np.column_stack((X.ravel(), Y.ravel()))
118
119 # Criacao da malha:
120

121 tri = Delaunay(vertices)


122
123 # Coleta das coord. dos nos e da matriz de incidencia:
124
125 nodes = tri.points
126 inci = tri.simplices
127
128 # Calculos dos centroides de cada elemento:
129
130 centroids = np.mean(nodes[inci], axis=1)
131

132 # Enumeracao dos elementos de acordo com centroides, para melhor


condicionamento:
133
134 sorting_order = np.lexsort((centroids[:, 0], centroids[:, 1]))
135 inci_sorted = inci[sorting_order]
136

137 fig = plt.figure(figsize = (24, 16))


138
139 # Plotagem da malha:
140
141 plt.triplot(nodes[:, 0], nodes[:, 1], inci_sorted, color = ’green’,
142 ls = ’-’, lw = 0.8)
143
144 # Plotagem dos nos:
145 if node_dots == True:
146 plt.scatter(nodes[:, 0], nodes[:, 1], color = ’orange’,
147 marker = ’o’, s = 70)
148

149 offsetx = 0.12


150 offsety = 0.2
151
152 # Anotar numeros dos elementos em seus centroides
153 for element_number, element in enumerate(inci_sorted):
154

155 centroid_x = np.mean(nodes[element, 0])


156 centroid_y = np.mean(nodes[element, 1])
157
158 if element_labels == True:
159 plt.text(centroid_x, centroid_y, str(element_number),
160 ha=’center’, va=’center’, color=’green’, fontsize=20)
161
162 # Anotar numeros dos nos:
163 if node_labels == True:
164
165 for node_number, node_coordinate in enumerate(nodes):
166 plt.text(node_coordinate[0] + offsetx,
167 node_coordinate[1] + offsety, str(node_number),
168 ha=’center’, va=’center’, color=’orange’, fontsize=20)
169
170 N = len(inci_sorted) # Numero de elementos
171
172 # Parametros de plotagem:
173
174 plt.xlabel(’X (m)’)
175 plt.ylabel(’Y (m)’)
176 plt.title(’N = ’ + str(N))
177 plt.axis(’scaled’)
178 plt.xlim(-1, L+1)
179 plt.ylim(-1, h+1)
180 plt.grid(axis = ’both’, ls = ’:’)
181 plt.tight_layout()
182 if save == True:
183 plt.savefig(’grid’+str(N)+’.png’)
184 else:
185 plt.show()
186
187 # Obtencao do indice do no passado como target_index
188
189 if target_coords is not None:
190 for i, node in enumerate(nodes):
191 if np.allclose(node, target_coords):
192 target_index = i
193 break
194
195 # Retorno dos resultados de interesse:
196 return nodes, inci_sorted, target_index
197
198 # -------------------------------------------------------------------
199
200 def deform_plot(nodes, desloc, els, save = False, fator_def = 1.0,
201 node_dots = False, node_labels = False,
202 element_labels = False):
203 ’’’
204 --------------------------------------------------------------------
205 Plota a configuracao deformada de uma certa malha de nos.
206 --------------------------------------------------------------------
207 ENTRADAS:
208
209 - nodes (float, array 2D): array com as coord. inciais dos nos;
210 - nodes (float, array 1D): array com os deslocamentos nodais,
organizados
211 verticalmente por no, com ordem x e depois y;
212 - els (int, array 1D): matriz de incidencia dos elementos;
213 - fator_def (float): padrao 1. Amplifica ou reduz a deformacao
214 real no plot.
215
216 FLAGS (boolean):
217
218 - save: padrao False. Caso seja True, a figura da malha sera salva;
219 - node_dots: padrao False. Caso seja True, plota os pontos dos nos;
220 - node_label: padrao False. Caso seja True, plota os numeros dos nos;
221 - element_labels: padrao False. Caso seja True, plota os
222 numeros dos elementos;
223 --------------------------------------------------------------------
224 SAIDAS:
225
226 - Caso save = True: grafico da malha gerada.
227 --------------------------------------------------------------------
228 ’’’
229
230 # Reorganizar a matriz de deslocamentos para um array 2D e aplicar
fator_def:
231
232 deformed_node_coordinates = nodes + (desloc.reshape((-1, 2))*fator_def)
233
234 # Plotar a grade deformada:
235 fig = plt.figure(figsize = (24, 16))
236
237 plt.triplot(deformed_node_coordinates[:, 0],
238 deformed_node_coordinates[:, 1],
239 els, color = ’green’, ls = ’-’, lw = 0.8)
240
241 # Adicionar pontos dos nos:
242 if node_dots == True:
243 plt.scatter(deformed_node_coordinates[:, 0],
244 deformed_node_coordinates[:, 1],
245 color = ’orange’, marker = ’o’, s = 70)
246

247 offsetx = 0.1


248 offsety = 0.15
249
250 # Adicionar numeros dos elementos:
251 for element_number, element in enumerate(els):
252 centroid_x = np.mean(deformed_node_coordinates[element, 0])
253 centroid_y = np.mean(deformed_node_coordinates[element, 1])
254 if element_labels == True:
255 plt.text(centroid_x, centroid_y, str(element_number),
256 ha=’center’, va=’center’, color=’green’, fontsize=20)
257
258 # Adicionar numeros dos nos:
259 if node_labels == True:
260 for node_number, node_coordinate in enumerate(
deformed_node_coordinates):
261 plt.text(node_coordinate[0] + offsetx,
262 node_coordinate[1] + offsety, str(node_number),
263 ha=’center’, va=’center’, color=’orange’, fontsize=20)
264
265 # Parametros do plot
266
267 N = len(els)
268
269 plt.xlabel(’X (m)’)
270 plt.ylabel(’Y (m)’)
271 plt.title(’N = ’ + str(N))
272 plt.axis(’scaled’)
273 plt.xlim(-1, L+1)
274 plt.ylim(-1, h+1)
275 plt.grid(axis = ’both’, ls = ’:’)
276 plt.tight_layout()
277 if save == True:
278 plt.savefig(’def’+str(N)+’.png’)
279 else:
280 plt.show()
281

282 return None


283
284 #--------------------- SOLVER -----------------------------
285
286 # Parametros de entrada:
287

288 L = 9.0 # m (comprimento)


289 h = 3.0 # m (altura)
290 t = 0.1 # m (espessura)
291
292 E = 2.0e+7 # kN/m2 (modulo de elasticidade)
293 nu = 0.3 # adim. (coef. de Poisson)
294
295 p = -25.0 # kN/m3 (Peso proprio)
296 q = - 200.0 # kN/m (Carga distribuida)
297
298 # Array com numero de divisoes em x e y para cada malha:
299

300 mesh_divs = np.array([[7, 3],


301 [7, 7],
302 [11, 11],
303 [21, 11],
304 [21, 21],
305 [31, 31]])
306
307 N_elmnt = []
308 defmid = []
309
310 for div in mesh_divs: # loop para varias malhas
311
312 # 1) Malha, matriz D e nos de topo:
313
314 divX = div[0]
315 divY = div[1]
316

317 nodes, els, mid_idx = delaunay_mesh_mid(L, h, divX, divY,


318 target_coords=(L/2, 0), save = True)
319
320 nnos = len(nodes)
321 nelem = len(els)
322

323 N_elmnt.append(nelem)
324
325 #print(’No central inferior: ’, mid_idx)
326
327 D = E/(1-(nu**2))*np.array([[1, nu, 0],
328 [nu, 1, 0],
329 [0, 0, (1-nu)/2]])
330
331 tam = nnos*2 # 2 DoF by node
332
333 Kg = np.zeros(shape = (tam, tam))
334 Fg = np.zeros(shape = (tam, 1))
335
336 top_nodes = []
337
338 for i in range(nnos):
339
340 if nodes[i][1] == h:
341 top_nodes.append(i)
342
343 #print(top_nodes)
344
345 for i, e in enumerate(els): # Loop em cada elemento:
346

347 # 2) Calculo da matriz de rigidez elementar:


348
349 #print(’Elemento ’, i)
350 #print(e)
351
352 x1, y1 = nodes[e[0]]
353 x2, y2 = nodes[e[1]]
354 x3, y3 = nodes[e[2]]
355
356 #print(’No 1: ’, x1, y1, ’ (No geral ’, e[0], ’)’)
357 #print(’No 2: ’, x2, y2, ’ (No geral ’, e[1], ’)’)
358 #print(’No 3: ’, x3, y3, ’ (No geral ’, e[2], ’)’)
359
360 # Area:
361
362 Ae = 0.5*((x2*y3) + (x1*y2) + (x3*y1) - (x2*y1) - (x1*y3) - (x3*y2))
363

364 #print(’Area: ’, Ae)


365
366 b1 = y2 - y3
367 b2 = -y1 + y3
368 b3 = y1 - y2
369

370 c1 = -x2 + x3
371 c2 = x1 - x3
372 c3 = -x1 + x2
373
374 # Matriz deslocamento-deformacao:
375

376 B = (1/(2*Ae))*np.array([[b1, 0, b2, 0, b3, 0],


377 [0, c1, 0, c2, 0, c3],
378 [c1, b1, c2, b2, c3, b3]])
379
380 #print(’\nMatriz B: ’)
381 #print(B)
382
383 Ke = np.dot(D, B)
384 Ke = np.dot(np.transpose(B), Ke)
385 Ke = t*Ae*Ke
386
387 #print(’\nMatriz de rigidez: ’)
388 #print(Ke)
389
390 # 3) Vetor de forcas de volume elementar
391
392 px = 0
393 py = p
394
395 fe_vol = ((t*Ae)/3)*np.array([[px],
396 [py],
397 [px],
398 [py],
399 [px],
400 [py]])
401
402 #print(’\nForcas de volume: ’)
403 #print(fe_vol)
404
405 #print(’\n’)
406
407 # 4)Vetor de forcas de superficie elementar
408
409 qy = q # kN/m
410 qx = 0
411

412 fe_sup = np.zeros_like(fe_vol)


413 # Nulo em elementos que nao sao de topo
414
415 count_top_nodes = 0
416 el_top_nodes = []
417 local_node_idx = []
418
419 for j in range(3):
420
421 if e[j] in (top_nodes):
422 count_top_nodes += 1
423 el_top_nodes.append(e[j])
424 local_node_idx.append(j)
425
426 # Elementos com 2 nos de topo tem aresta no topo:
427
428 if count_top_nodes == 2:
429 #print(’------- Elemento de topo. ------- \n’)
430 #print(’Nos de topo: ’, el_top_nodes)
431
432 xi = nodes[el_top_nodes[0]][0]
433 yi = nodes[el_top_nodes[0]][1]
434

435 xf = nodes[el_top_nodes[1]][0]
436 yf = nodes[el_top_nodes[1]][1]
437
438 # Calcula o comprimento da aresta de topo
439 top_side_length = calc_lenght(xi, yi, xf, yf)
440

441 #print(’Comprimento aresta de topo: ’, top_side_length, ’\n’)


442
443 fe_vol[(2*local_node_idx[0])] += (top_side_length/2)*qx
444 fe_vol[(2*local_node_idx[0])+1] += (top_side_length/2)*qy
445
446 fe_vol[(2*local_node_idx[1])] += (top_side_length/2)*qx
447 fe_vol[(2*local_node_idx[1])+1] += (top_side_length/2)*qy
448
449 # 5) Construcao da matriz de rigidez e vetor de forcas globais:
450
451 fe = fe_sup + fe_vol
452

453 #print(’Vetor de forcas: ’)


454 #print(fe, ’\n’)
455
456 #G.L.’s relacionados a cada elemento:
457
458 pos = [e[0]*2, (e[0]*2) + 1, e[1]*2,
459 (e[1]*2) + 1, e[2]*2, (e[2]*2) + 1]
460
461 #print(’GLs :’, pos, ’\n’)
462
463 local_size = len(fe)
464

465 for m in range(local_size): # Loop nas linhas


466 Fg[pos[m]] += fe[m]
467 for n in range(local_size): # loop nas colunas
468 Kg[pos[m], pos[n]] += Ke[m, n]
469
470 #print(Kg, ’\n’)
471 #print(Fg, ’\n’)
472
473 left_supX = L/10
474 right_supX = L - (L/10)
475
476 #print(left_supX)
477 #print(right_supX)
478
479 # 6) Condicoes de contorno essenciais:
480
481 sup_gls = []
482
483 for i, coord in enumerate(nodes):
484 if (coord[1] == 0 and coord[0] <= left_supX) or (coord[1] == 0 and
coord[0] >= right_supX):
485
486 # Apoios atuam no GL vertical:
487 glv = (i*2) + 1
488
489 sup_gls.append(glv)
490 #print(i, ’ e no apoiado.’)
491
492 #print(’C.C.s em : ’, sup_gls)
493
494 ncon = len(sup_gls)
495
496 ordem = np.arange(0, tam, 1).tolist()
497
498 #print(ordem)
499
500 # 7) Ordenacao e resolucao do sistema
501
502 for gl in sup_gls:
503
504 ordem.remove(gl)
505 ordem.append(gl)
506
507 #print(ordem)
508
509 # Reorganizar Kg
510 K= Kg[np.ix_(ordem, ordem)]
511
512 # Reorganizar Fg
513 F = Fg[ordem]
514
515 #print(Fg, ’\n’)
516 #print(F, ’\n’)
517
518 dim = tam - ncon
519
520 sparse_K = scipy.sparse.csr_matrix(K[:dim, :dim]) # matriz esparsa
521
522 dl = spsolve(sparse_K, F[:dim, 0])
523
524 desloc = np.zeros((tam, 1)) # valores prescritos sao nulos
525
526 for l in range(dim):
527 desloc[ordem[l]] = dl[l]
528

529 dx = []
530 dy = []
531
532 for d in range(len(desloc)):
533
534 if d%2 == 0:
535 dx.append(desloc[d][0])
536
537 else:
538 dy.append(desloc[d][0])
539

540 #print(desloc)
541
542 # 8) Processamento dos deslocamentos:
543
544 # Salvar dados relativos ao no central inferior:
545

546 mid_x = desloc[mid_idx*2]


547 mid_y = desloc[mid_idx*2 + 1]
548
549 mid_tot = np.sqrt((mid_x**2) + (mid_y**2))
550
551 defmid.append(mid_tot*100) # Conversao para cm
552
553 #print(’\nDeslocamento no central inferior (No ’, mid_idx, ’): ’)
554 #print(’Horiz. : ’, mid_x)
555 #print(’Vert. : ’, mid_y)
556 #print(’Total : ’, mid_tot)
557 #print(’No. de elementos: ’, nelem)
558
559 # Plotagem da configuracao deformada:
560
561 deform_plot(nodes, desloc, els, fator_def = 100, save = True)
562
563 # 9) Grafico de convergencia:
564
565 conv = plt.figure()
566
567 plt.rcdefaults()
568
569 print(defmid)
570
571 plt.plot(N_elmnt, defmid, color = ’black’, marker = ’o’)
572 plt.grid(axis = ’both’, ls = ’:’)
573 plt.xlim(0, 1900)
574 plt.ylim(0.1, 0.5)
575 plt.xlabel(’Numero de elementos’)
576 plt.ylabel(’Deslocamento total (cm)’)
577 plt.tight_layout()
578 plt.savefig(’conv_plot.png’)
579
580 # 10) Tensoes horizontais:
581

582 mid_nodes = []
583
584 for i in range(nnos):
585
586 if nodes[i][0] == L/2:
587 mid_nodes.append(i)
588
589 mid_els = []
590
591 for i, e in enumerate(els):
592 count_mid_nodes = 0
593

594 for j in range(3):


595
596 if e[j] in (mid_nodes):
597 count_mid_nodes += 1
598

599 if count_mid_nodes == 2:
600
601 mid_els.append(i)
602
603 mid_els.sort()
604

605 mid_inc = els[mid_els]


606
607 sigmaX = []
608
609 for i, e in enumerate(mid_inc):
610

611 x1, y1 = nodes[e[0]]


612 x2, y2 = nodes[e[1]]
613 x3, y3 = nodes[e[2]]
614
615 no1, no2, no3 = e[0], e[1], e[2]
616

617 #print(’No 1: ’, x1, y1, ’ (No geral ’, e[0], ’)’)


618 #print(’No 2: ’, x2, y2, ’ (No geral ’, e[1], ’)’)
619 #print(’No 3: ’, x3, y3, ’ (No geral ’, e[2], ’)’)
620
621 # Area:
622

623 Ae = 0.5*((x2*y3) + (x1*y2) + (x3*y1) - (x2*y1) - (x1*y3) - (x3*y2))


624
625 #print(’Area: ’, Ae)
626
627 b1 = y2 - y3
628 b2 = -y1 + y3
629 b3 = y1 - y2
630
631 c1 = -x2 + x3
632 c2 = x1 - x3
633 c3 = -x1 + x2
634

635 # Matriz deslocamento-deformacao:


636
637 B = (1/(2*Ae))*np.array([[b1, 0, b2, 0, b3, 0],
638 [0, c1, 0, c2, 0, c3],
639 [c1, b1, c2, b2, c3, b3]])
640

641 loc_d = np.array([[desloc[no1*2, 0]],


642 [desloc[no1*2+1, 0]],
643 [desloc[no2*2, 0]],
644 [desloc[no2*2+1, 0]],
645 [desloc[no3*2, 0]],
646 [desloc[no3*2+1, 0]]])
647
648 S = np.dot(np.dot(D, B), loc_d)/1000
649 sigmaX.append(S[0,0])
650
651
652 sxMed = []
653
654 for i in range(len(sigmaX)-1):
655 sigma_med = (sigmaX[i] + sigmaX[i+1])/2
656 sxMed.append(sigma_med)
657

658 yy = np.linspace(0, h, len(sxMed))


659
660 sig = plt.figure()
661
662 plt.plot(sxMed, yy, color = ’black’)
663 plt.ylim(-0.5, 3.5)
664 plt.xlim(-10, 10)
665 plt.grid(axis = ’both’, ls = ’:’)
666 plt.xlabel(’Tensao horizontal (MPa)’)
667 plt.ylabel(’Distancia vertical (m)’)
668 plt.tight_layout()
669 plt.savefig(’sigma_plot.png’)

Você também pode gostar