// — Parâmetros físicos e numéricos —
real nu = 0.01; // Viscosidade cinemática
real dt = 0.001; // Passo de tempo
int nmax = 50; // Máx passos de tempo
int imax = 20; // Máx iterações Newton por passo
real tol = 1e-6; // Tolerância de Newton
real deltaGLS = 1e-2; // Parâmetro de estabilização GLS (τ)
// — Malha: Cavidade quadrada —
border a1(t=0,1){x=t; y=0; label=3;}
border a2(t=0,1){x=1; y=t; label=4;}
border a3(t=0,1){x=1-t; y=1; label=1;}
border a4(t=0,1){x=0; y=1-t; label=2;}
int n = 40;
mesh Th = buildmesh(a1(n)+a2(n)+a3(n)+a4(n));
// — Espaços de funções —
fespace Vh(Th, P1); // Velocidade escalar
fespace Ph(Th, P1); // Pressão
fespace Vh2(Th, [P1, P1]); // Velocidade vetorial (2 componentes)
// — Variáveis —
Vh u1n=0, u2n=0, u1np=0, u2np=0, du1=0, du2=0, v1, v2;
Ph pn=0, dp=0, q;
func f1 = 0;
func f2 = 0;
// — Loop no tempo —
for (int nt=0; nt<nmax; nt++) {
cout << "Tempo " << nt << endl;
u1np = u1n; u2np = u2n; pn = pn;
int iter = 0;
bool convergiu = false;
while (iter < imax && !convergiu) {
// --- Resíduo Total (R) ---
varf Res([du1, du2, dp], [v1, v2, q], optimize=0) =
int2d(Th)(
(u1np/dt)*v1 + (u2np/dt)*v2
+ nu*(dx(u1np)*dx(v1) + dy(u1np)*dy(v1)
+ dx(u2np)*dx(v2) + dy(u2np)*dy(v2))
+ (u1np*dx(u1np) + u2np*dy(u1np))*v1
+ (u1np*dx(u2np) + u2np*dy(u2np))*v2
- pn*(dx(v1) + dy(v2))
- f1*v1 - f2*v2
)
+ int2d(Th)( -(dx(u1np) + dy(u2np)) * q )
+ on(1, du1=1, du2=0) + on(2,3,4, du1=0, du2=0);
// --- Jacobiano sem estabilização ---
varf Jac([du1, du2, dp], [v1, v2, q]) =
int2d(Th)(
(du1/dt)*v1 + (du2/dt)*v2
+ nu*(dx(du1)*dx(v1) + dy(du1)*dy(v1) + dx(du2)*dx(v2) + dy(du2)*dy(v2))
+ (u1np*dx(du1) + u2np*dy(du1))*v1
+ (u1np*dx(du2) + u2np*dy(du2))*v2
- dp*(dx(v1) + dy(v2))
+ q*(dx(du1) + dy(du2))
)+ on(1, du1=1, du2=0) + on(2,3,4, du1=0, du2=0);
// --- Estabilização GLS (Petrov-Galerkin Least Squares) ---
varf GLS([du1, du2, dp], [v1, v2, q]) =
int2d(Th)(
deltaGLS * (
((du1/dt) + u1np*dx(du1) + u2np*dy(du1) + dx(dp)) *
((v1/dt) + u1np*dx(v1) + u2np*dy(v1) + dx(q)) +
((du2/dt) + u1np*dx(du2) + u2np*dy(du2) + dy(dp)) *
((v2/dt) + u1np*dx(v2) + u2np*dy(v2) + dy(q)) +
(dx(du1)+dy(du2)) * (dx(v1)+dy(v2))
)
)+ on(1, du1=1, du2=0) + on(2,3,4, du1=0, du2=0);
// --- Montagem da matriz global ---
matrix J = Jac(Vh2, Vh2, solver=UMFPACK); // Corrigido para usar as variáveis corretas
matrix JGLS = GLS(Vh2, Vh2);
J = J + JGLS; // Soma as matrizes
// --- Vetor de resíduos ---
real[int] R = Res(0, Vh2); // Vetor de resíduos
// --- Resolver sistema linear ---
real[int] minusR = -1 * R;
set(J, solver=UMFPACK);
real[int] Delta = J^-1 * minusR;
// --- Atualizar solução ---
[du1[], du2[], dp[]] = Delta;
u1np[] += du1[];
u2np[] += du2[];
pn[] += dp[];
// --- Convergência ---
real normDelta = sqrt(du1[].l2^2 + du2[].l2^2 + dp[].l2^2);
cout << " Iter Newton " << iter << ", ||Delta|| = " << normDelta << endl;
if (normDelta < tol) convergiu = true;
iter++;
}
if (!convergiu)
cout << "Newton NAO convergiu no tempo " << nt << endl;
// Atualiza para próximo passo
u1n[] = u1np[];
u2n[] = u2np[];
// Visualização
plot([u1n, u2n], cmm="Velocidade - t=" + nt, wait=0, value=true, fill=true);
//plot(pn, cmm="Pressao - t=" + nt, wait=0, value=true, fill=true);
}