//Red-black Gauss-Seidel relaxation for model problem. Updates the current value of the solution //u[1..n][1..n], using the right-hand side function rhs[1..n][1..n]. // Red-black, Gauss-Seidel relaxation, Neumann forced, pointwise coupled void relax(double **u, double **v, double **J[JROWS][JCOLS], int rows, int cols, double alpha) { int i, ipass, isw, j, jsw = 1; double hx, hy, hx2, hy2, discr, detU, detV; hx = 1.0 / (cols-1); hy = hx; // hx2 = hx * hx; hy2 = hy * hy; for (ipass=1; ipass<= 2; ipass++, jsw = 3-jsw) { //Red and black sweeps. isw = jsw; for (j=1; j<=cols; j++, isw=3-isw) for (i=isw; i<=rows; i+=2) { //Gauss-Seidel formula. if (i>1 && i<rows) { if (j>1 && j<cols) { discr = lin2by2det(alpha/hx2*2.0 + alpha/hy2*2.0 + J[1][1][i][j], J[1][2][i][j], J[1][2][i][j], alpha/hx2*2.0 + alpha/hy2*2.0 + J[2][2][i][j]); if (abs((double)discr)>EPS) { detU = lin2by2det(alpha/hx2*(u[i-1][j]+u[i+1][j]) + alpha/hy2*(u[i][j-1]+u[i][j+1]) - J[1][3][i][j], J[1][2][i][j], alpha/hx2*(v[i-1][j]+v[i+1][j]) + alpha/hy2*(v[i][j-1]+v[i][j+1]) - J[2][3][i][j], alpha/hx2*2.0 + alpha/hy2*2.0 + J[2][2][i][j]); u[i][j]= detU / discr; detV = lin2by2det(alpha/hx2*2.0 + alpha/hy2*2.0 + J[1][1][i][j], alpha/hx2 * (u[i-1][j]+u[i+1][j]) + alpha/hy2*(u[i][j-1]+u[i][j+1]) - J[1][3][i][j], J[1][2][i][j], alpha/hx2 * (v[i-1][j]+v[i+1][j]) + alpha/hy2*(v[i][j-1]+v[i][j+1]) - J[2][3][i][j]); v[i][j] = detV / discr; } else { u[i][j] = (alpha/hx2*(u[i-1][j]+u[i+1][j]) + alpha/hy2*(u[i][j-1]+u[i][j+1]) - (J[1][2][i][j]*v[i][j]+J[1][3][i][j])) / (alpha/hx2*2.0 + alpha/hy2*2.0 + J[1][1][i][j]); v[i][j] = (alpha/hx2*(v[i-1][j]+v[i+1][j]) + alpha/hy2*(v[i][j-1]+v[i][j+1]) - (J[1][2][i][j]*u[i][j]+J[2][3][i][j])) / (alpha/hx2*2.0 + alpha/hy2*2.0 + J[2][2][i][j]); } } else if (j==1) { u[i][j] = u[i][j+1]; v[i][j] = v[i][j+1]; } else if (j==cols) { u[i][j] = u[i][j-1]; v[i][j] = v[i][j-1]; } else { printf("relax: Bug: Index error(2).\n"); return; } } else if (i==1) { if(j>1 && j<cols) { u[i][j] = u[i+1][j]; v[i][j] = v[i+1][j]; } else if (j==1) { u[i][j] = u[i+1][j+1]; v[i][j] = v[i+1][j+1]; } else if (j==cols) { u[i][j] = u[i+1][j-1]; v[i][j] = v[i+1][j-1]; } else { printf("relax: Bug: Index error.\n"); return; } } else if (i==rows) { if(j>1 && j<cols) { u[i][j] = u[i-1][j]; v[i][j] = v[i-1][j]; } else if (j==1) { u[i][j] = u[i-1][j+1]; v[i][j] = v[i-1][j+1]; } else if (j==cols) { u[i][j] = u[i-1][j-1]; v[i][j] = v[i-1][j-1]; } else { printf("relax: Bug: Index error(3).\n"); return; } } } } }
/** * relaxPointwiseCoupledGaussSeidel * * Pointwise coupled Gauss-Seidel relaxation iteration for CLG-OF equations. * Each call to this function updates the current value of the solution, * u[1..m][1..n], v[1..m][1..n], using the motion tensor * J[JROWS][JCOLS][1..m][1..n]. * Neumann boundary conditions are used (derivatives are set to zero). * The return value is the total error of the current iteration. * * Parameters: * * u Pointer to the optical flow horizontal component * matrix/array. * v Pointer to the optical flow vertical component matrix/array. * J[JROWS][JCOLS] Pointer to the array that stores the computed (and possibly * smoothed) derivatives for each image/optical flow pixel. * nRows Number of rows of the optical flow arrrays. * nCols Number of columns of the optical flow arays. * alpha Optical flow global smoothing coefficient. * */ double relaxPointwiseCoupledGaussSeidel(double **u, double **v, double **J[JROWS][JCOLS], int nRows, int nCols, double alpha) { int i, j; double hx, hy, hx2, hy2, discr, detU, detV, error, ulocal, vlocal; // h, could be less than 1.0. hx = 1.0; hy = hx; hx2 = hx * hx; hy2 = hy * hy; error = 0.0; for (i=1; i<nRows-1; i++) { for (j=1; j<nCols-1; j++) { // Point-wise Coupled Gauss-Seidel formula. // Coupled system for two variables solved by Cramer's rule. // This is the discriminant of that system discr = lin2by2det(alpha/hx2*2.0 + alpha/hy2*2.0 + J[0][0][i][j], J[0][1][i][j], J[0][1][i][j], alpha/hx2*2.0 + alpha/hy2*2.0 + J[1][1][i][j]); if (abs(discr) > EPS) { // Determinant replacing first column to solve // the 2x2 system by using Cramer's rule. detU = lin2by2det(alpha / hx2 * (u[i-1][j] + u[i+1][j]) + alpha / hy2 * (u[i][j-1] + u[i][j+1]) - J[0][2][i][j], J[0][1][i][j], alpha / hx2 * (v[i-1][j] + v[i+1][j]) + alpha / hy2 * (v[i][j-1] + v[i][j+1]) - J[1][2][i][j], alpha / hx2 * 2.0 + alpha / hy2 * 2.0 + J[1][1][i][j]); // Determinant replacing second column to solve // the 2x2 system by using Cramer's rule. detV = lin2by2det(alpha / hx2 * 2.0 + alpha / hy2 * 2.0 + J[0][0][i][j], alpha / hx2 * (u[i-1][j] + u[i+1][j]) + alpha / hy2 * (u[i][j-1] + u[i][j+1]) - J[0][2][i][j], J[0][1][i][j], alpha / hx2 * (v[i-1][j] + v[i+1][j]) + alpha / hy2 * (v[i][j-1] + v[i][j+1]) - J[1][2][i][j]); // Division of two discriminants (Cramer's rule). ulocal = detU / discr; vlocal = detV / discr; error += (ulocal-u[i][j])*(ulocal-u[i][j]); error += (vlocal-v[i][j])*(vlocal-v[i][j]); u[i][j]=ulocal; v[i][j]=vlocal; // Normal Gauss-Seidel iteration. } else { // w_Factor=1.0, thus a Gauss-Seidel iteration. error += SOR_at(u, v, J, i, j, alpha, 1.0); } // End if. } // End columns. } // End rows. error += boundaryCondition(u, v, nRows, nCols); return sqrt(error / (nRows*nCols));; }