Beispiel #1
0
                private CLCalc.Program.Variable LUBackSubstitute(CLCalc.Program.Variable MLUDecomp, double[] b, int n, CLCalc.Program.Variable varindx)
                {
                    CLCalc.Program.Variable varx = new Program.Variable(b);
                    CLCalc.Program.Variable varN = new Program.Variable(new int[1] { n });
                    int[] J = new int[1];
                    CLCalc.Program.Variable varJ = new Program.Variable(J);

                    CLCalc.Program.Variable[] args = new Program.Variable[] { MLUDecomp, varx, varindx, varN, varJ };
                    int[] max = new int[1];

                    //ajeita o vetor com respeito as trocas de linha
                    max[0] = 1;
                    doubleLUUnscramble.Execute(args, max);

                    //Forward subst
                    for (int i = n - 1; i >= 1; i--)
                    {
                        max[0] = i;
                        doubleLUForwardSubs.Execute(args, max);
                    }

                    //Backward subst
                    for (int j = n - 1; j >= 1; j--)
                    {
                        max[0] = 1;
                        J[0] = j;
                        varJ.WriteToDevice(J);
                        doubleLUDivide.Execute(args, max);

                        max[0] = j;
                        doubleLUBackSubs.Execute(args, max);
                    }
                    //Primeiro elemento
                    max[0] = 1;
                    J[0] = 0;
                    varJ.WriteToDevice(J);
                    doubleLUDivide.Execute(args, max);

                    return varx;
                }
Beispiel #2
0
                /// <summary>Calculates LU decomposition of M matrix</summary>
                /// <param name="M">Matrix to decompose</param>
                /// <param name="n">Matrix dimension</param>
                /// <param name="varindx">Swap index</param>
                private CLCalc.Program.Variable LUDecomp(double[,] M, int n, out CLCalc.Program.Variable varindx)
                {
                    //arguments and work_dim
                    CLCalc.Program.Variable[] args;
                    int[] max;

                    //Matrix to vector
                    double[] vecM = MatrixToVector(M, ref n, ref n);
                    CLCalc.Program.Variable varM = new Program.Variable(vecM);

                    //Scaling transformation
                    double[] vv = new double[n];
                    CLCalc.Program.Variable varvv = new Program.Variable(vv);
                    max = new int[1] { n };
                    args = new CLCalc.Program.Variable[] { varM, varvv };
                    doubleLUScale.Execute(args, max);

                    //In order LU factorization (Crout)
                    int[] J = new int[1] { 0 };
                    CLCalc.Program.Variable varJ = new Program.Variable(J);
                    int[] N = new int[1] { n };
                    CLCalc.Program.Variable varN = new Program.Variable(N);
                    int[] indx = new int[n];
                    varindx = new Program.Variable(indx);

                    args = new Program.Variable[] { varM, varJ, varN, varindx, varvv };
                    for (J[0] = 0; J[0] < n; J[0]++)
                    {
                        varJ.WriteToDevice(J);
                        max[0] = J[0];
                        doubleLUCalcBetas.Execute(args, max);

                        max[0] = n - J[0];
                        doubleLUCalcAlphas.Execute(args, max);

                        max[0] = 1;
                        doubleLUCalcPivo.Execute(args, max);

                        max[0] = n;
                        doubleLUTrocaCols.Execute(args, max);

                        if (J[0] != n - 1)
                        {
                            max[0] = n - J[0] - 1;
                            doubleLUDivByPivot.Execute(args, max);
                        }
                    }

                    return varM;
                }
Beispiel #3
0
                /// <summary>Returns the sum of two matrices</summary>
                /// <param name="M1">Matrix 1</param>
                /// <param name="M2">Matrix 2</param>
                public double[,] MatrixSum(double[,] M1, double[,] M2)
                {
                    //Creates OpenCL variables to store data
                    int maxi = M1.GetLength(0);
                    int maxj = M1.GetLength(1);
                    double[] vecM1 = new double[maxi * maxj];
                    double[] vecM2 = new double[maxi * maxj];

                    if (M2.GetLength(0) != maxi || M2.GetLength(1) != maxj) throw new Exception("Incompatible dimensions");

                    for (int i = 0; i < maxi; i++)
                    {
                        for (int j = 0; j < maxj; j++)
                        {
                            vecM1[i + maxi * j] = M1[i, j];
                            vecM2[i + maxi * j] = M2[i, j];
                        }
                    }

                    CLCalc.Program.Variable varM1 = new Program.Variable(vecM1);
                    CLCalc.Program.Variable varM2 = new Program.Variable(vecM2);

                    CLCalc.Program.Variable[] args = new Program.Variable[2] { varM1, varM2 };
                    int[] max = new int[1] { maxi * maxj };

                    doubleVecSum.Execute(args, max);

                    //Escreve o resultado em varM1; devo ler os resultados de la
                    varM1.ReadFromDeviceTo(vecM1);

                    return VectorToMatrix(vecM1, ref maxi, ref maxj);
                }
Beispiel #4
0
                /// <summary>Matrix multiplication</summary>
                /// <param name="M1">Matrix 1</param>
                /// <param name="M2">Matrix 2</param>
                public double[,] MatrixMultiply(double[,] M1, double[,] M2)
                {
                    //M pxq, N qxr
                    int p = M1.GetLength(0);
                    int q = M1.GetLength(1);
                    int r = M2.GetLength(1);

                    if (q != M2.GetLength(0)) throw new Exception("Matrix dimensions do not match for multiplication");

                    double[] vecM1 = MatrixToVector(M1, ref p, ref q);
                    double[] vecM2 = MatrixToVector(M2, ref q, ref r);
                    double[] vecResp = new double[p * r];

                    CLCalc.Program.Variable varResp = new Program.Variable(vecResp);

                    CLCalc.Program.Variable varM1 = new Program.Variable(vecM1);
                    CLCalc.Program.Variable varM2 = new Program.Variable(vecM2);

                    //Finaliza a soma dos elementos
                    int[] vecQ = new int[1] { q };
                    CLCalc.Program.Variable varQ = new Program.Variable(vecQ);
                    CLCalc.Program.Variable[] args = new Program.Variable[4] { varResp, varM1, varM2, varQ };
                    int[] max = new int[2] { p, r };
                    doubleMatrixMult.Execute(args, max);

                    varResp.ReadFromDeviceTo(vecResp);

                    varResp.Dispose();

                    return VectorToMatrix(vecResp, ref p, ref r);
                }
Beispiel #5
0
                /// <summary>Solves linear system Mx = b by LU decomposition. Returns x</summary>
                /// <param name="M">Matrix M</param>
                /// <param name="b">Vector b</param>
                /// <param name="maxAbsErr">Maximum acceptable absolute error</param>
                /// <param name="maxIters">Maximum iterations</param>
                public double[] LinSolve(double[,] M, double[] b, double maxAbsErr, int maxIters)
                {
                    int n = M.GetLength(0);
                    if (M.GetLength(1) != n) throw new Exception("Matrix not square");
                    if (b.Length != n) throw new Exception("Incompatible vector dimension");

                    double[] x = new double[b.Length];
                    double[] errx = new double[b.Length];
                    CLCalc.Program.Variable varindx;
                    CLCalc.Program.Variable MLUDecomp = LUDecomp(M, n, out varindx);

                    double[] localMLUDecomp = new double[n*n];
                    MLUDecomp.ReadFromDeviceTo(localMLUDecomp);

                    //Backsubstitution
                    CLCalc.Program.Variable varx = LUBackSubstitute(MLUDecomp, b, n, varindx);

                    //Error control
                    CLCalc.Program.Variable varerrx = new Program.Variable(errx);
                    double[] vecM = MatrixToVector(M, ref n, ref n);
                    CLCalc.Program.Variable varM = new Program.Variable(vecM);
                    CLCalc.Program.Variable varb = new Program.Variable(b);

                    CLCalc.Program.Variable[] args = new Program.Variable[] { varM, varb, varerrx, varx };
                    int[] max = new int[] { n };

                    double absErr = maxAbsErr + 1;

                    int iter = 0;
                    while (absErr > maxAbsErr && iter < maxIters)
                    {
                        CLCalc.Program.Variable vardelta = LUBackSubstitute(MLUDecomp, errx, n, varindx);

                        //Acopla correção na solução
                        CLCalc.Program.Variable[] args2 = new Program.Variable[] { vardelta, varx };
                        doubleLUSubErr.Execute(args2, max);

                        doubleSolveError.Execute(args, max);
                        varerrx.ReadFromDeviceTo(errx);
                        absErr = 0;
                        for (int j = 0; j < n; j++) absErr += errx[j] * errx[j];
                        absErr = (double)Math.Sqrt(absErr);

                        iter++;
                    }

                    varx.ReadFromDeviceTo(x);
                    return x;
                }
Beispiel #6
0
                /// <summary>Gauss Seidel method for iterative linear system solving. Returns unknown x</summary>
                /// <param name="M">Matrix M so that Mx=b</param>
                /// <param name="x">Initial estimate</param>
                /// <param name="b">Known vector b</param>
                /// <param name="Iterations">Gauss-Seidel iterations per step</param>
                /// <param name="MaxIter">Maximum number of times Gauss-Seidel iterations</param>
                /// <param name="totalError">Desired sqrt(Sum(error[i]^2))*number of equations</param>
                /// <param name="err">Estimated absolute error per component</param>
                public double[] LeastSquaresGS(double[,] M, double[] b, double[] x, int Iterations, int MaxIter, double totalError, out double[] err)
                {
                    //M pxp
                    int p = M.GetLength(0);
                    int q = M.GetLength(1);
                    //Consistencia
                    if (p != b.Length) throw new Exception("Matrix and vector b dimensions not compatible");
                    if (q != x.Length) throw new Exception("Matrix and initial guess x dimensions not compatible");

                    double[] vecM = MatrixToVector(M, ref p, ref q);
                    //Calculo de MtM e Mtb
                    CLCalc.Program.Variable varMtM = new Program.Variable(new double[q * q]);
                    CLCalc.Program.Variable varMtb = new Program.Variable(new double[q]);

                    {
                        CLCalc.Program.Variable varM = new Program.Variable(vecM);
                        CLCalc.Program.Variable varb = new Program.Variable(b);
                        CLCalc.Program.Variable varp = new Program.Variable(new int[1] { p });

                        CLCalc.Program.Variable[] arg = new Program.Variable[] { varM, varMtM, varp };
                        int[] maxs = new int[2] { q, q };
                        doubleCalcMtM.Execute(arg, maxs);

                        arg = new Program.Variable[] { varM, varb, varMtb, varp };
                        maxs = new int[1] { q };
                        doubleCalcMtb.Execute(arg, maxs);

                        varM.Dispose(); varb.Dispose(); varp.Dispose();
                    }

                    //Solucao do sistema
                    CLCalc.Program.Variable varx = new Program.Variable(x);
                    CLCalc.Program.Variable varerrx = new Program.Variable(x);
                    CLCalc.Program.Variable[] args = new Program.Variable[3] { varMtM, varMtb, varx };
                    CLCalc.Program.Variable[] args2 = new Program.Variable[4] { varMtM, varMtb, varerrx, varx };

                    int[] max = new int[1] { q };

                    double[] resp = new double[q];
                    err = new double[q];
                    double absErr = totalError + 1;
                    int i = 0;
                    while (i < MaxIter && absErr > totalError * (double)q)
                    //while (i < MaxIter && absErr > totalError)
                    {
                        for (int j = 0; j < Iterations; j++)
                        {
                            doubleGaussSeidel.Execute(args, max);
                            i++;
                        }
                        //Calcula o erro
                        doubleGaussSeidelError.Execute(args2, max);
                        varerrx.ReadFromDeviceTo(err);

                        absErr = 0;
                        for (int j = 0; j < q; j++) absErr += err[j] * err[j];
                        absErr = (double)Math.Sqrt(absErr);
                    }

                    //Retorna a resposta
                    varx.ReadFromDeviceTo(resp);
                    varerrx.ReadFromDeviceTo(err);

                    //Limpa memoria
                    varMtM.Dispose(); varx.Dispose(); varerrx.Dispose(); varMtb.Dispose();

                    return resp;
                }
Beispiel #7
0
                /// <summary>Initializes physics program. Components indexes: [i] - x, [i+1] - y, [i+2] - z</summary>
                /// <param name="nParticles">Number of particles</param>
                public floatBodyPhysics(int nParticles)
                {
                    string[] s = new string[] { CollisionAppliers, ForceAppliers, ConstAccelMotionEDOSolver };
                    Program.Compile(s);
                    //Kernels
                    MotionStep = new Program.Kernel("constAccelStep");
                    Kernel_ApplyGravity = new Program.Kernel("ApplyGravity");
                    Kernel_FloorCollision = new Program.Kernel("FloorCollision");
                    Kernel_SelfCollision = new Program.Kernel("SelfCollision");
                    Kernel_WallCollision = new Program.Kernel("WallCollision");
                    Kernel_ResetForces = new Program.Kernel("ResetForces");
                    Kernel_ResetCloseNeighbors = new Program.Kernel("ResetCloseNeighbors");

                    float[] t = new float[1] { 0 };
                    float[] gg = new float[3] { 0, 0, 0 };
                    step = new float[1] { 0 };
                    //Tamanho de alocacao de velocidades e posicoes
                    float[] aloc = new float[nParticles * 3];

                    //Tamanho de alocacao de caracteristicas das particulas
                    float[] alocPart = new float[nParticles];
                    //3*Nparticulas
                    CL_pos = new CLCalc.Program.Variable(aloc);
                    CL_vel = new CLCalc.Program.Variable(aloc);
                    CL_forces = new CLCalc.Program.Variable(aloc);
                    //Nparticulas
                    closeNeighbors = new int[nParticles];
                    CL_closeNeighbors = new CLCalc.Program.Variable(closeNeighbors);
                    for (int i = 0; i < nParticles; i++) alocPart[i] = 1f; //inicializa massas como 1 e tamanhos de colisao como 1
                    CL_masses = new CLCalc.Program.Variable(alocPart);
                    CL_collisionSizes = new CLCalc.Program.Variable(alocPart);
                    
                    //escalares
                    CL_t = new CLCalc.Program.Variable(t);
                    CL_step = new CLCalc.Program.Variable(step);

                    //gravidade
                    CL_g = new CLCalc.Program.Variable(gg);

                    //Argumentos de funcoes
                    stepArgs = new CLCalc.Program.Variable[] { CL_t, CL_step, CL_forces, CL_masses, CL_pos, CL_vel };
                    applyGravArgs = new CLCalc.Program.Variable[] { CL_forces, CL_masses, CL_g };
                    floorCollisionArgs = new CLCalc.Program.Variable[] { CL_vel, CL_pos, CL_collisionSizes };
                    wallCollisionArgs = floorCollisionArgs;
                    selfCollisionArgs = new CLCalc.Program.Variable[] { CL_vel, CL_pos, CL_masses, CL_forces, CL_closeNeighbors, CL_collisionSizes };
                    resetForcesArgs = new Program.Variable[] { CL_forces };
                    resetCloseNeighborsArgs = new Program.Variable[] { CL_closeNeighbors };

                    nArgs = new int[1] { nParticles * 3 };
                    nPartics = new int[1] { nParticles };
                    nPartics2 = new int[2] { nParticles, nParticles };
                }