/// <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); }
/// <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; }