Laboratório 9 - Simulação Bidimensional de Dinâmica de Fluidos
Objetivo
Implementar rotinas em Assembly RISC-V para manipulação de matrizes bidimensionais e empacotamento/desempacotamento de valores.
Motivação
A dinâmica de fluidos computacional (CFD) fundamenta simulações meteorológicas, aerodinâmicas e animações gráficas realistas. Na primeira parte, analisamos a difusão simplificada em uma dimensão. Nesta etapa, estendemos o modelo para um espaço bidimensional matricial, onde cada ponto contém componentes vetoriais de velocidade horizontal (VX) e vertical (VY), além de parâmetros físicos locais.
Modelo Físico e Estrutura de Dados
Representação da Célula em Palavra de 32 Bits
Cada célula do reticulado é codificada em uma palavra única de 32 bits (word). A estrutura compactada organiza a componente de pressão/propriedade local nos bits mais significativos e os componentes vetoriais de velocidade com sinal nos bits inferiores:
| 31 20 | 19 10 | 9 0 |
+--------------------+------------------+------------------+
| Pressure | VX | VY |
+--------------------+------------------+------------------+
| 12 bits | 10 bits | 10 bits |
+--------------------+------------------+------------------+
-
Pressure (bits 31:20): Campo escalar sem sinal de 12 bits (faixa de
0a4095). -
VX (bits 19:10): Componente de velocidade horizontal com sinal em complemento de 2 (10 bits, faixa de
-512a+511). -
VY (bits 9:0): Componente de velocidade vertical com sinal em complemento de 2 (10 bits, faixa de
-512a+511).
Nota sobre Desempacotamento e Empacotamento
Ao extrair VX e VY para registradores de 32 bits, é necessário realizar a extensão de sinal a partir do bit 9 (por exemplo, combinando slli e srai de 22 posições). Ao reempacotar valores negativos atualizados de volta na palavra de 32 bits, aplique uma máscara de 10 bits (& 0x3FF) em vx_new e vy_new antes de deslocá-los e combiná-los com or, evitando que bits 1 da extensão de sinal invadam os campos vizinhos.
Atualização por Difusão Discreta e Gradiente de Pressão
A matriz possui dimensão L x C, onde o índice de linha i (0 <= i < L) cresce de Norte para Sul (de cima para baixo) e o índice de coluna j (0 <= j < C) cresce de Oeste para Leste (da esquerda para a direita).
-
Condição de Contorno (Bordas Fixas): As células localizadas nas bordas da matriz (
i = 0,i = L - 1,j = 0ouj = C - 1) atuam como fronteiras estáticas. Elas não sofrem atualização física e devem ser copiadas integralmente e sem alterações da matriz atual para a matriz de destino a cada iteração. -
Células Internas: Para cada célula estritamente interna na posição
(i, j)(isto é,1 <= i < L - 1e1 <= j < C - 1), consideram-se as quatro células ortogonalmente adjacentes (vizinhança de von Neumann): -
Norte (
north): posição(i - 1, j) - Sul (
south): posição(i + 1, j) - Oeste (
west): posição(i, j - 1) - Leste (
east): posição(i, j + 1)
A atualização de cada célula interna combina a dissipação viscosa com a aceleração gerada pelo desbalanceamento de pressão local, empurrando o fluido de regiões de maior pressão para regiões de menor pressão:
1. Difusão Viscosa
A média das velocidades das quatro células vizinhas e a diferença em relação à velocidade da célula atual (i, j) são calculadas utilizando deslocamento aritmético à direita de 2 bits (srai de 2 posições, correspondente à divisão por 4 com arredondamento para \(-\infty\)):
avg_x = (vx_north + vx_south + vx_east + vx_west) >> 2
avg_y = (vy_north + vy_south + vy_east + vy_west) >> 2
difference_x = avg_x - vx_atual
difference_y = avg_y - vy_atual
O fator de amortecimento viscoso \(k\) é obtido a partir do valor global de viscosidade \(V\) (\(0 \le V \le 255\)) por meio de um deslocamento à direita de 5 bits (k = V >> 5, resultando em \(0 \le k \le 7\)). Esse fator atenua a variação de velocidade via deslocamento aritmético à direita (sra):
k = V >> 5
vx_difusao = vx_atual + (difference_x >> k)
vy_difusao = vy_atual + (difference_y >> k)
2. Força por Gradiente de Pressão
O gradiente simétrico entre células opostas acelera o fluido ao longo dos eixos cartesianos (de Oeste para Leste no eixo \(X\) e de Norte para Sul no eixo \(Y\)). Como a pressão é representada em 12 bits sem sinal (\(0\) a \(4095\)) e os vetores de velocidade operam em 10 bits com sinal (\(-512\) a \(+511\)), a diferença de pressão é atenuada por um deslocamento aritmético fixo à direita de 4 posições (srai de 4 posições):
grad_px = (pressure_west - pressure_east) >> 4
grad_py = (pressure_north - pressure_south) >> 4
3. Combinação e Saturação (Clamping)
As velocidades resultantes somam a componente de difusão à aceleração do gradiente de pressão e passam por saturação (clamping) para garantir que permaneçam estritamente dentro do intervalo representável de 10 bits em complemento de dois (-512 a +511):
vx_calc = vx_difusao + grad_px
vy_calc = vy_difusao + grad_py
vx_new = max(-512, min(511, vx_calc))
vy_new = max(-512, min(511, vy_calc))
A componente escalar Pressure da célula atual (i, j) não sofre alteração e deve ser preservada intacta nos bits mais significativos (31:20) durante a recombinação da palavra de 32 bits escrita na matriz de destino (grid_next).
Buffers Duplos (Ping-Pong Buffering)
A atualização síncrona do reticulado exige duas matrizes em memória (grid_current e grid_next). Durante uma iteração, todas as leituras (da célula atual e de seus quatro vizinhos) devem ocorrer exclusivamente em grid_current, enquanto os novos estados reempacotados (incluindo a cópia das bordas) são gravados em grid_next. Ao final de cada iteração completa sobre toda a malha, os ponteiros base das duas matrizes são alternados (swap).
Entradas e Saídas
Entrada (stdin):
-
1ª linha: Dois inteiros separados por espaço,
L C(3 <= L, C <= 64), indicando respectivamente o número de linhas e o número de colunas da matriz. -
2ª linha: Dois inteiros separados por espaço,
T V(T >= 1,0 <= V <= 255), correspondendo ao número total de iterações temporais e ao valor global de viscosidade. -
Próximas
Llinhas: Cada linha contémCvalores hexadecimais de 8 dígitos precedidos por0x(formato0xXXXXXXXX), separados por um espaço simples, representando o estado inicial das células daquela linha.
Saída (stdout):
-
Deve imprimir a matriz resultante após as
Titerações, contendoLlinhas comCvalores cada. -
Cada célula deve ser formatada em hexadecimal com exatos 8 dígitos (letras
A–Fmaiúsculas) e prefixo0x(0xXXXXXXXX), separados por um espaço simples entre colunas adjacentes e finalizando cada linha com uma quebra de linha (\n).
Exemplos
Caso Base (Malha 3x3, Iteração Única, Difusão Pura com k = 2)
Neste exemplo, T = 1 e V = 80 (logo k = 80 >> 5 = 2). Apenas a célula central (1, 1) possui velocidade inicial não nula (0x00019000 => Pressure = 0, VX = 100, VY = 0), enquanto todas as células da borda valem 0x00000000.
3 3
1 80
0x00000000 0x00000000 0x00000000
0x00000000 0x00019000 0x00000000
0x00000000 0x00000000 0x00000000
--------------------------------
0x00000000 0x00000000 0x00000000
0x00000000 0x00012C00 0x00000000
0x00000000 0x00000000 0x00000000
Caso de Teste (Difusão + Gradiente de Pressão com k = 2)
3 3
1 80
0x00002814 0x04005028 0x00002814
0x04005028 0x02019014 0x01005028
0x00002814 0x01005028 0x00002814
--------------------------------
0x00002814 0x04005028 0x00002814
0x04005028 0x02014C1C 0x01005028
0x00002814 0x01005028 0x00002814
Entrega
O arquivo report gerado pelo simulador deve ser submetido no Classroom da disciplina, nomeado como {RA}_lab9.report.
Warning
- Qualquer alteração no arquivo de report será considerado fraude
- O uso de ferramentas de IA deve ser reportado, indicando como foi utilizado e em quais partes do código.
- Está é uma atividade individual, o qual deve ser desenvolvido individualmente, qualquer forma de cópia ou plágio será penalizada. Portanto, atividades que apresentarem semelhanças injustificadas serão atribuídas nota zero para todos os envolvidos