double UpdateSystemImplicit( VoronoiDiagram *voronoiDiagram, double timeStep, double timeDifference) { double time; int N = voronoiDiagram->xN[0]*voronoiDiagram->xN[1]*voronoiDiagram->xN[2]; //float **B = newMatrix( N, N); for( time = 0; time+timeStep <= timeDifference; time += timeStep){ //fprintf( stderr, "%i. iteration:\nSetup Matrix\n", (int)(time / timeStep + 0.5)); int passedTime = clock(); fprintf( stderr, "Set Matrix... \n"); setupMatrixImplicit( voronoiDiagram, timeStep, 'G'); fprintf( stderr, "...finished ( %li clocks, %.3lf sec)\n", (clock() - passedTime), (float)(clock() - passedTime)/CLOCKS_PER_SEC); /*for(int m=0; m<N; m++){ for(int n=0; n<N; n++) fprintf( stderr, "%6.0lf ", A[m][n]); fprintf( stderr, "\n"); }*/ /*for(int m=0; m<N; m++){ for(int n=0; n<N; n++) fprintf( stdout, "%i %i %lf \n", m, n, (A[m][n]!=0.?1.:0.)); //fprintf( stderr, "\n"); }*/ /*fprintf( stderr, "Solve Matrix\n"); solveLinearSystemB( A, b, x, N, B); fprintf( stderr, "Actualize Values\n"); for(int m=0; m<N; m++) voronoiDiagram->voronoiCells[m]->glucose = b[m]; */ for(int m=0; m<N; m++) x[m] = voronoiDiagram->voronoiCells[m]->glucose; passedTime = clock(); fprintf( stderr, "ConjugateGradient... \n"); ConjugateGradient( A, b, x, N, 1); fprintf( stderr, "...finished ( %li clocks, %.3lf sec)\n", (clock() - passedTime), (float)(clock() - passedTime)/CLOCKS_PER_SEC); //fprintf( stderr, "...finished ( %lisec)\n", (clock() - passedTime)/CLOCKS_PER_SEC); for(int m=0; m<N; m++) voronoiDiagram->voronoiCells[m]->glucose = x[m]; } return timeDifference - time; }
void StableFluid3D::projectVelocity(double dt) { setBoundary(); Vector divergence(vel.Length()); // fill in velocities double dx = width / (double)resX; double dy = height / (double)resY; double dz = depth / (double)resZ; for (int i = 0; i < resX; ++i) { for (int j = 0; j < resY; ++j) { for (int k = 0; k < resZ; ++k) { int index = makeIndex(i, j, k); double div = (tempVelocities[0][i + 1][j][k] - tempVelocities[0][i][j][k]) / dx + (tempVelocities[1][i][j + 1][k] - tempVelocities[1][i][j][k]) / dy + (tempVelocities[2][i][j][k + 1] - tempVelocities[2][i][j][k]) / dz; vel[index] = div; divergence[index] = div; } } } // vel *= density / dt; bool useOldPCG = false; if (useOldPCG) { int k = 0; Vector laplacianTimesPressure(pressure.Length()); laplacian.Multiply(pressure, laplacianTimesPressure); r[0] = vel - laplacianTimesPressure; double error = r[0].Magnitude2(); while ((std::sqrt(error) > PCG_EPS) && (k < PCG_MAXITER)) { //cerr << "PCG iteration " << k << ", error: " << std::sqrt(error) << endl; ConjugateGradient(preconditioner, z[k % 2], r[k % 2], 0.0001, 500.0); ++k; int i1 = (k - 1) % 2; int i2 = k % 2; if (k == 1) { p = z[0]; } else { double beta = (InnerProduct(r[i1], z[i1])) / (InnerProduct(r[i2], z[i2])); p *= beta; p += z[i1]; } Vector laplacianTimesP(p.Length()); laplacian.Multiply(p, laplacianTimesP); double alpha = (InnerProduct(r[i1], z[i1])) / (InnerProduct(p, laplacianTimesP)); pressure += alpha * p; r[i2] = r[i1] - alpha * (laplacianTimesP); error = r[i2].Magnitude2(); } if (std::sqrt(error) > PCG_EPS) { std::cout << "end preconditioned conj grad " << "error: " << error << std::endl; } } else { p = Vector(vel.Length()); r[0] = divergence; //ApplyPreconditioner(r[0], z[0]); double sigma = InnerProduct(r[0], z[0]); int k = 0; double error = r[0].Magnitude2(); while (k < PCG_MAXITER) { ++k; Vector s(vel.Length()); s = z[0]; int k = 0; laplacian.Multiply(s, z[0]); double rho = 1.0; double alpha = rho / InnerProduct(s, z[0]); p += alpha * s; r[0] -= alpha * z[0]; error = r[0].Magnitude2(); if (error < PCG_EPS * PCG_EPS) { pressure = p; break; } //ApplyPreconditioner(r[0], z[0]); double sigmaNew = InnerProduct(r[0], z[0]); double beta = sigmaNew / rho; s = z[0] + beta * s; sigma = sigmaNew; } Vector laplacianTimesPressure(pressure.Length()); laplacian.Multiply(pressure, laplacianTimesPressure); r[0] = vel - laplacianTimesPressure; error = r[0].Magnitude2(); while ((std::sqrt(error) > PCG_EPS) && (k < PCG_MAXITER)) { //cerr << "PCG iteration " << k << ", error: " << std::sqrt(error) << endl; ConjugateGradient(preconditioner, z[k % 2], r[k % 2], 0.0001, 500.0); ++k; int i1 = (k - 1) % 2; int i2 = k % 2; if (k == 1) { p = z[0]; } else { double beta = (InnerProduct(r[i1], z[i1])) / (InnerProduct(r[i2], z[i2])); p *= beta; p += z[i1]; } Vector laplacianTimesP(p.Length()); laplacian.Multiply(p, laplacianTimesP); double alpha = (InnerProduct(r[i1], z[i1])) / (InnerProduct(p, laplacianTimesP)); pressure += alpha * p; r[i2] = r[i1] - alpha * (laplacianTimesP); error = r[i2].Magnitude2(); } if (std::sqrt(error) > PCG_EPS) { std::cout << "end preconditioned conj grad " << "error: " << error << std::endl; } } /* mathlib::Vector PCGr, PCGd, PCGq, PCGs; PCGr.Resize(resX * resY * resZ); PCGd.Resize(resX * resY * resZ); PCGq.Resize(resX * resY * resZ); PCGs.Resize(resX * resY * resZ); int iter = 0; PCGr = vel - laplacian * pressure; mathlib::ConjugateGradient(preconditioner, PCGd, PCGr); double deltaNew = mathlib::InnerProduct(PCGr, PCGd); double errBound = PCG_EPS * PCG_EPS * deltaNew; while ((iter < PCG_MAXITER) && (deltaNew > errBound)) { if (!(iter % 3)) cerr << "iteration " << iter << ", error: " << deltaNew << endl; PCGq = laplacian * PCGd; double alpha = deltaNew / (mathlib::InnerProduct(PCGd, PCGq)); pressure += alpha * PCGd; if ((iter % 10) == 0) PCGr = vel - laplacian * pressure; else PCGr -= alpha * PCGq; mathlib::ConjugateGradient(preconditioner, PCGs, PCGr); double deltaOld = deltaNew; deltaNew = mathlib::InnerProduct(PCGr, PCGs); double beta = deltaNew / deltaOld; PCGd *= beta; PCGd += PCGs; ++iter; } cout << "end preconditioned conj grad "<< "error: " << deltaNew << endl; */ std::cout << "dt:" << dt << "\t density:" << density << std::endl; // dt = 1.0; for (int i = 0; i < resX; ++i) { for (int j = 0; j < resY; ++j) { for (int k = 0; k < resZ; ++k) { int i1 = makeIndex(i, j, k); int i2; double deltaPressure; i2 = (i == 0 ? i1 : i1 - 1); velocities[0][i][j][k] = tempVelocities[0][i][j][k] - dt* 0.5 * (pressure[i1] - pressure[i2]) / dx; deltaPressure = pressure[i1] - pressure[i2]; i2 = (j == 0 ? i1 : i1 - resX); velocities[1][i][j][k] = tempVelocities[1][i][j][k] - dt * 0.5 * (pressure[i1] - pressure[i2]) / dy; deltaPressure = pressure[i1] - pressure[i2]; i2 = (k == 0 ? i1 : i1 - resY * resX); velocities[2][i][j][k] = tempVelocities[2][i][j][k] - dt * 0.5 * (pressure[i1] - pressure[i2]) / dz; deltaPressure = pressure[i1] - pressure[i2]; } } } }
int main(){ double *x,*b, *bbarra; int n =100, i, tol =5; Matriz*** A, ***M, ***N; for(n=100; n<=10000;n=n*10){ A = mat_esparsa(n); x = (double*) calloc(n+IDX,sizeof(double)); b = (double*) calloc(n+IDX,sizeof(double)); bbarra = (double*) calloc(n+IDX,sizeof(double)); //Vetor solução for(int i =IDX; i< n+IDX; i++) x[i]=1; // Calculo do vetor b correto obtido atraves de Ax = b mat_multv(n,A,x,b); /*****SEM PRECOND*****/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de Sem PreCond , n= %d \n",n ); i = ConjugateGradient(n, A, b, x,tol); printf("\n\ti = %d \t\n",i ); /******Jacobi*********/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; // Matriz pre condicionador de Jacobi M = JacobiPC(A, n); //Minv Ax = Minv b/ N = mat_cria(n,n); mat_multm(n,M,A,N); mat_multv(n, M, b, bbarra); printf("\n\tMetodo gradiente Conjugado com pre condicionador de Jacobi , n= %d \n",n ); // Metodo gradiente Conjugado com pre condicionador de Jacobi , n= 1000 i = ConjugateGradient(n, N, bbarra, x,tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); mat_libera(n,N); /******Gaus Seidel****/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de GaussSeidel , n= %d \n",n ); M = pre_cond(A,n,1); i = ConjugateGradientPC(n, A, M, b, x, tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); /***** SSOR *********/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de SSOR , n= %d \n",n ); M = pre_cond(A,n,1.5); i = ConjugateGradientPC(n, A, M, b, x, tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); //=======Fim do Loop======// free(x); free(b); free(bbarra); mat_libera(n,A); } for(n=100; n<=10000;n=n*10){ A = mat_esparsa_extend(n); x = (double*) calloc(n+IDX,sizeof(double)); b = (double*) calloc(n+IDX,sizeof(double)); bbarra = (double*) calloc(n+IDX,sizeof(double)); //Vetor solução for(int i =IDX; i< n+IDX; i++) x[i]=1; // Calculo do vetor b correto obtido atraves de Ax = b mat_multv(n,A,x,b); /*****SEM PRECOND*****/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de Sem PreCond , n= %d \n",n ); i = ConjugateGradient(n, A, b, x,tol); printf("\n\ti = %d \t\n",i ); /******Jacobi*********/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; // Matriz pre condicionador de Jacobi M = JacobiPC(A, n); //Minv Ax = Minv b/ N = mat_cria(n,n); mat_multm(n,M,A,N); mat_multv(n, M, b, bbarra); printf("\n\tMetodo gradiente Conjugado com pre condicionador de Jacobi , n= %d \n",n ); // Metodo gradiente Conjugado com pre condicionador de Jacobi , n= 1000 i = ConjugateGradient(n, N, bbarra, x,tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); mat_libera(n,N); /******Gaus Seidel****/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de GaussSeidel , n= %d \n",n ); M = pre_cond(A,n,1); i = ConjugateGradientPC(n, A, M, b, x, tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); /***** SSOR *********/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de SSOR , n= %d \n",n ); M = pre_cond(A,n,1.5); i = ConjugateGradientPC(n, A, M, b, x, tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); //=======Fim do Loop======// free(x); free(b); free(bbarra); mat_libera(n,A); } }
int main (void){ double ** A0 = mat_cria(3,3); double *b0 = (double*)malloc(3*sizeof(double)); double ** A1 = mat_cria(3,3); double *b1 = (double*)malloc(3*sizeof(double)); double *x0 = (double*)malloc(3*sizeof(double)); double *x1 = (double*)malloc(3*sizeof(double)); A0[0][0] = 1; A0[0][1] = -1; A0[0][2] = 0; A0[1][0] = -1; A0[1][1] = 2; A0[1][2] = 1; A0[2][0] = 0; A0[2][1] = 1; A0[2][2] = 2; b0[0] = 0; b0[1] = 2; b0[2] = 3; A1[0][0] = 1; A1[0][1] = -1; A1[0][2] = 0; A1[1][0] = -1; A1[1][1] = 2; A1[1][2] = 1; A1[2][0] = 0; A1[2][1] = 1; A1[2][2] = 5; b1[0] = 3; b1[1] = -3; b1[2] = 4; printf("Vetor Solucao 1 \n"); x0[0] = 0;x0[1] = 0;x0[2] = 0; ConjugateGradient(3, A0, b0, x0); printv(3, x0); printf("Matriz R1 \n"); Cholesky(3, A0); printm(3, A0); printf("Vetor Solucao 2 \n"); x1[0] = 0;x1[1] = 0;x1[2] = 0; ConjugateGradient(3, A1, b1, x1); printv(3, x1); printf("Matriz R2 \n"); Cholesky(3, A1); printm(3, A1); free(A0); free(A1); free(b0); free(b1); free(x0); free(x1); return 0; }
int ConjugateGradientPC(int n, Matriz ***A,Matriz ***M, double *b, double *x, double tol){ double * Rk, *Rk1, *Dk, *temp, *w; double Alfa, Beta,y; int i; Rk = (double*) calloc(n+IDX,sizeof(double)); Rk1 = (double*) calloc(n+IDX,sizeof(double)); Dk = (double*) calloc(n+IDX,sizeof(double)); temp = (double*) calloc(n+IDX,sizeof(double)); w = (double*) calloc(n+IDX,sizeof(double)); //R0= b - Ax; mat_multv(n,A,x,temp); mat_sumV(n, -1, b, temp,Rk); //D0 = M_inv * R0 ou M*D0 = R0 ConjugateGradient(n,M,Rk,Dk,tol+1); ///Para a 1a vez o y eh diferente, muda o calculo de alpha y = mat_escalar_vu(n,Rk,Dk); // For K= 0...n-1 for (i = IDX; i < n+IDX; ++i){ // puts("A1"); // if (Rk = 0) stop if(mat_modulo(n, Rk) < 0.5*pow(10,-tol)) break; // puts("A2"); // Alfa = RkT*(Dk ou W) / DkT * A *Dk mat_multv(n,A,Dk,temp); Alfa = y/ mat_escalar_vu(n,temp,Dk); // Xk1 = Xk + Alfa*Dk mat_sumV(n,Alfa,x,Dk,x); //Rk1 = Rk - Alfa * A* Dk ;; Obs: temp já contém A*Dk mat_sumV(n, -1*Alfa,Rk,temp,Rk1); ////w = M_inv * R0 ou M*w = R0 ConjugateGradient(n,M,Rk,w,tol+1); /// y = mat_escalar_vu(n,Rk1,w); //Beta = Rk1T * w / RkT * Rk Beta = y / mat_escalar_vu(n,Rk,Rk); //Dk1 = w + Beta*Dk mat_sumV(n,Beta,w,Dk,Dk); //Atualiza o Rk copiaV(n,Rk,Rk1); } free(Rk); free(Rk1); free(Dk); free(temp); free(w); return i-IDX; }