private static void Tst() { int n = 8; int[] ia /*[9]*/ = new int[] { 1, 5, 8, 10, 12, 15, 17, 18, 19 }; int[] ja /*[18]*/ = new int[] { 1, 3, 6, 7, 2, 3, 5, 3, 8, 4, 7, 5, 6, 7, 6, 8, 7, 8 }; double[] a /*[18]*/ = new double[] { 7.0, 1.0, 2.0, 7.0, -4.0, 8.0, 2.0, 1.0, 5.0, 7.0, 9.0, 5.0, 1.0, 5.0, -1.0, 5.0, 11.0, 5.0 }; var csr = new CSparse.Double.SparseMatrix(n, n, 18); csr.ColumnPointers = ia; csr.RowIndices = ja; csr.Values = a; }
public CSR GetAdjacencyGraph(CSR P_delta) { var p = P_delta.Clone(); for (var i = 0; i < p.NonZerosCount; i++) { p.Values[i] = 1; } var buf = (CSR)p.Multiply(p.Transpose()); return(buf); }
public static SparseEqSystem Generate(CSparse.Double.SparseMatrix eqSystem) { var buf = new SparseEqSystem(); var lastCol = eqSystem.ColumnCount; var eqs = buf.Equations = new SparseRow[eqSystem.RowCount]; var colNnzs = buf.ColumnNonzeros = new int[eqSystem.ColumnCount]; buf.RowNonzeros = new int[eqSystem.RowCount]; for (var i = 0; i < eqs.Length; i++) { buf.Equations[i] = new SparseRow(1); } foreach (var tuple in eqSystem.EnumerateIndexed()) { var rw = tuple.Item1; //tuple.Item1; var col = tuple.Item2; //tuple.Item2; var val = tuple.Item3; eqs[rw].Add(col, val); if (col != lastCol) { colNnzs[col]++; } } for (var i = 0; i < eqs.Length; i++) { buf.RowNonzeros[i] = buf.Equations[i].CalcNnz(lastCol); } buf.RowCount = eqSystem.RowCount; buf.ColumnCount = eqSystem.ColumnCount; return(buf); }
public CCS CalculateRref(CCS a) { var singleMemberColumns = 00; var aTran = a.Transpose(); var n = a.ColumnCount; for (var i = 0; i < n; i++) { if (a.GetNnzcForColumn(i) == 1) { singleMemberColumns++; } } if (singleMemberColumns == a.RowCount) { return((CCS)a.Clone()); } var pat = new CoordinateStorage <double>(a.RowCount, a.ColumnCount - 1, 1); var bCrd = new CoordinateStorage <double>(a.RowCount, a.ColumnCount - 1, 1);//a matrix without last column a.EnumerateIndexed((row, col, val) => { if (col != a.ColumnCount - 1) { pat.At(row, col, 1); bCrd.At(row, col, val); } }); //nonzero pattern of a, except last column var b = bCrd.ToCCs(); var bTran = b.Transpose(); var patt = pat.ToCCs(); var pattTr = patt.Transpose(); var varGraph = pattTr.Multiply(patt); varGraph.Values.FillWith(1); var eqnGraph = patt.Multiply(pattTr); eqnGraph.Values.FillWith(1); if (!varGraph.IsSymmetric() || !eqnGraph.IsSymmetric()) { throw new Exception(); } var eqnParts = CalcUtil.EnumerateGraphParts(eqnGraph); var varParts = CalcUtil.EnumerateGraphParts(varGraph); var varVisited = new bool[varGraph.ColumnCount]; foreach (var eqnPart in eqnParts) { //i'th independent system. var firstEq = eqnPart.First(); int firstVarOfFirstEq = -1; /* * patt.EnumerateRowMembers(firstEq, (row, col, val) => { * if (firstValOfFirstEq != -1) * firstValOfFirstEq = col; * ); */ pattTr.EnumerateColumnMembers(firstEq, (row, col, val) => { if (firstVarOfFirstEq == -1) { firstVarOfFirstEq = row; } }); //var firstVar = patt.EnumerateColumnMembers() var connectedVariables = CalcUtil.DepthFirstSearch(varGraph, varVisited, firstVarOfFirstEq); connectedVariables.Sort(); var vp = new Dictionary <int, int>();//variablePermute //vp[a] = b, a: number of variable in original system // b: index of variable in connectedVariables for (var i = 0; i < connectedVariables.Count; i++) { vp[connectedVariables[i]] = i; } var denseSubSytem = new Matrix(eqnPart.Count, connectedVariables.Count + 1);////i'th independent system as dense // Convert sparse to dense. //var dns = Matrix.OfMatrix(aTran); for (var i = 0; i < eqnPart.Count; i++) { //insert i'th eqn into denseSubSytem var row = i; var st = aTran.ColumnPointers[i]; var en = aTran.ColumnPointers[i + 1]; for (int j = st; j < en; j++) { var col = aTran.RowIndices[j]; if (col == a.ColumnCount - 1) { continue; } var val = aTran.Values[j]; denseSubSytem[i, vp[col]] = val; } } } throw new NotImplementedException(); }
/// <summary> /// The Direct Conformal Parameterization (DCP) method, see (Desbrun et al. 2002) /// </summary> /// <param name="meshin"></param> /// <param name="meshout"></param> private void DCP(TriangleMesh meshin, out TriangleMesh meshout) { MeshLaplacian.PrecomputeTraits(meshin); /// copy the mesh meshout = meshin.Copy(); /// counters var vertexCount = meshout.Vertices.Count; /// output uv-coordinates var bu = new double[vertexCount]; var bv = new double[vertexCount]; var b0 = new double[vertexCount]; // A * x = b var x = new double[vertexCount * 2 + 4]; var M_A = new TripletMatrix(2 * (vertexCount + 2), 2 * vertexCount, 4 * (vertexCount + 1) * vertexCount); var M_X = new TripletMatrix(2 * (vertexCount + 2), 2 * vertexCount, 4 * (vertexCount + 1) * vertexCount); foreach (var vertex in meshin.Vertices.Where(v => !v.OnBoundary)) { var angleWeightSum = 0d; var areaWeightSum = 0d; foreach (var halfEdge in vertex.Halfedges) { // cot(alpha) + cot(beta) var angleWeight = halfEdge.Previous.Traits.Cotan + halfEdge.Opposite.Previous.Traits.Cotan; // cot(gamma) + cot(delta) var areaWeight = (halfEdge.Next.Traits.Cotan + halfEdge.Opposite.Traits.Cotan); areaWeight /= (halfEdge.FromVertex.Traits.Position - halfEdge.ToVertex.Traits.Position).LengthSquared(); M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, angleWeight); M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, angleWeight); M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, areaWeight); M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, areaWeight); angleWeightSum += angleWeight; areaWeightSum += areaWeight; } M_A.Entry(vertex.Index * 2, vertex.Index * 2, -angleWeightSum); M_A.Entry(vertex.Index * 2 + 1, vertex.Index * 2 + 1, -angleWeightSum); M_X.Entry(vertex.Index * 2, vertex.Index * 2, -areaWeightSum); M_X.Entry(vertex.Index * 2 + 1, vertex.Index * 2 + 1, -areaWeightSum); } // Free boundary foreach (var vertex in meshin.Vertices.Where(v => v.OnBoundary)) { var weightSum = 0d; // Inner edges foreach (var halfEdge in vertex.Halfedges.Where(he => !he.Edge.OnBoundary)) { // cot(alpha) + cot(beta) var borderWeight = halfEdge.Previous.Traits.Cotan + halfEdge.Opposite.Previous.Traits.Cotan; M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight); M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight); M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight); M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight); weightSum += borderWeight; } // Boundary edges foreach (var halfEdge in vertex.Halfedges.Where(he => he.Edge.OnBoundary)) { // Last edge if (halfEdge.OnBoundary) { var borderWeight = halfEdge.Opposite.Previous.Traits.Cotan; // Weight edge by cotan once and substract the rotated uv vector M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight); M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2 + 1, -1); M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight); M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2, 1); M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight); M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2 + 1, -1); M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight); M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2, 1); weightSum += borderWeight; } // First edge else { // cot(alpha) + cot(beta) var borderWeight = halfEdge.Previous.Traits.Cotan; // Weight edge by cotan once and substract the rotated uv vector M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight); M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2 + 1, 1); M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight); M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2, -1); M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight); M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2 + 1, 1); M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight); M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2, -1); weightSum += borderWeight; } } M_A.Entry(vertex.Index * 2, vertex.Index * 2, weightSum); M_A.Entry(vertex.Index * 2 + 1, vertex.Index * 2 + 1, weightSum); M_X.Entry(vertex.Index * 2, vertex.Index * 2, weightSum); M_X.Entry(vertex.Index * 2 + 1, vertex.Index * 2 + 1, weightSum); } // Fixed vertices // M^n M_A.Entry(2 * vertexCount, 2 * P1Index, 1); M_A.Entry(2 * vertexCount + 1, 2 * P1Index + 1, 1); M_X.Entry(2 * vertexCount, 2 * P1Index, 1); M_X.Entry(2 * vertexCount + 1, 2 * P1Index + 1, 1); M_A.Entry(2 * vertexCount + 2, 2 * P2Index, 1); M_A.Entry(2 * vertexCount + 3, 2 * P2Index + 1, 1); M_X.Entry(2 * vertexCount + 2, 2 * P2Index, 1); M_X.Entry(2 * vertexCount + 3, 2 * P2Index + 1, 1); // M^n transp M_A.Entry(2 * P1Index, 2 * vertexCount, 1); M_A.Entry(2 * P1Index + 1, 2 * vertexCount + 1, 1); M_X.Entry(2 * P1Index, 2 * vertexCount, 1); M_X.Entry(2 * P1Index + 1, 2 * vertexCount + 1, 1); M_A.Entry(2 * P2Index, 2 * vertexCount + 2, 1); M_A.Entry(2 * P2Index + 1, 2 * vertexCount + 3, 1); M_X.Entry(2 * P2Index, 2 * vertexCount + 2, 1); M_X.Entry(2 * P2Index + 1, 2 * vertexCount + 3, 1); // b^n x[2 * vertexCount] = P1UV.X; x[2 * vertexCount + 1] = P1UV.Y; x[2 * vertexCount + 2] = P2UV.X; x[2 * vertexCount + 3] = P2UV.Y; var matrix = SparseMatrix.Add(M_A.Compress(), M_X.Compress(), AngleToAreaRatio, 1 - AngleToAreaRatio); var solver = QR.Create(matrix); solver.Solve(x); for (var vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) { bu[vertexIndex] = x[2 * vertexIndex]; bv[vertexIndex] = x[2 * vertexIndex + 1]; } /// update mesh positions and uv's MeshLaplacian.UpdateMesh(meshout, bu, bv, b0, bu, bv); MeshLaplacian.UpdateMesh(meshin, bu, bv); }
/// <summary> /// Divides the zones of reduced <see cref="matrix"/>. /// </summary> /// <param name="model">The model.</param> /// <param name="matrix">The reduced matrix.</param> /// <param name="dofMap">The DoF map.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> public static ZoneDevidedMatrix DivideZones(Model model, CCS matrix, DofMappingManager dofMap) { //see Calcutil.GetReducedZoneDividedMatrix throw new NotImplementedException(); }
/// <summary> /// Extracts the free free part. /// </summary> /// <param name="matrix">The matrix.</param> /// <param name="nodeMapping">The node mapping.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> public static CCS ExtractFreeFreePart(CCS matrix, int[] nodeMapping) { throw new NotImplementedException(); }
public Tuple <CCS, double[]> CalculateDisplacementPermutation(CCS a) { //based on this solution : https://github.com/wo80/CSparse.NET/issues/7#issuecomment-317268696 if (a.RowCount < a.ColumnCount) { //For a matrix A with rows < columns, SparseQR does a factorization of the transpose A' //so we add zero rows to A and make it rectangular! var a2 = new CoordinateStorage <double>(a.ColumnCount, a.ColumnCount, a.NonZerosCount); foreach (var t in a.EnumerateIndexed()) { a2.At(t.Item1, t.Item2, t.Item3); } a = a2.ToCCs(); } SparseMatrix buf; var n = a.RowCount; var m = a.ColumnCount; var order = ColumnOrdering.MinimumDegreeAtA; var sp = System.Diagnostics.Stopwatch.StartNew(); var qr = SparseQR.Create(a, order); var t2 = sp.ElapsedMilliseconds; var r = GetFactorR(qr); var q = GetFactorQ(qr); var leads = new int[a.RowCount]; leads.FillWith(-1); var epsilon = 1e-8; foreach (var t in r.EnumerateIndexed()) { if (Math.Abs(t.Item3) > epsilon) { if (leads[t.Item1] == -1) { leads[t.Item1] = t.Item2; } else { leads[t.Item1] = Math.Min(leads[t.Item1], t.Item2); } } } var leadCount = leads.Count(i => i != -1); { var nnzApprox = leadCount; var p1Crd = new CoordinateStorage <double>(leadCount, r.RowCount, nnzApprox); var p2Crd = new CoordinateStorage <double>(r.ColumnCount, leadCount, nnzApprox); var p2pCrd = new CoordinateStorage <double>(r.ColumnCount, r.ColumnCount - leadCount, nnzApprox); var cnt1 = 0; var cnt2 = 0; for (var i = 0; i < leads.Length; i++) { if (leads[i] != -1) { var j = leads[i]; p1Crd.At(cnt1, i, 1); p2Crd.At(j, cnt1, 1); cnt1++; } if (leads[i] == -1) { var j = i;// leads[i]; p2pCrd.At(j, cnt2, 1); cnt2++; } } var p1 = p1Crd.ToCCs(); var p2 = p2Crd.ToCCs(); var p2p = p2pCrd.ToCCs(); //var rp = r.Transpose(); var rdep = p1.Multiply(r).Multiply(p2); var rinDep = p1.Multiply(r).Multiply(p2p); var qr2 = SparseQR.Create(rdep, order); var t = sp.ElapsedMilliseconds; var right = new double[rinDep.RowCount]; var sol = new double[rinDep.RowCount]; var bufCrd = new CoordinateStorage <double>(leadCount, a.ColumnCount - leadCount, leadCount); for (var j = 0; j < rinDep.ColumnCount; j++) { //put the j'th column of r into the rightSide right.FillWith(0); { var col = j; var st = rinDep.ColumnPointers[j]; var end = rinDep.ColumnPointers[j + 1]; for (var ii = st; ii < end; ii++) { var row = rinDep.RowIndices[ii]; var val = rinDep.Values[ii]; right[row] = val; } } qr2.Solve(right, sol); for (var i = 0; i < rdep.RowCount; i++) { bufCrd.At(i, j, sol[i]); } } buf = bufCrd.ToCCs(); } //var top = buf.ToDenseMatrix(); var buft = buf.Transpose(); var masterCount = a.ColumnCount - 1 - leadCount; //var p_d_dense = new Matrix(a.ColumnCount - 1, masterCount); var p_d = new CoordinateStorage <double>(a.ColumnCount - 1, masterCount, 1); var rightSideDense = new double[a.ColumnCount - 1]; var rightSide = new double[a.ColumnCount - 1]; var cnt = 0; var cnt3 = 0; for (var i = 0; i < a.ColumnCount - 1; i++) { if (leads[i] != -1) { /*{//dense * var rw = top.ExtractRow(cnt).CoreArray; * * var right = rw.Last(); * Array.Resize(ref rw, rw.Length - 1); * * for (var j = 0; j < rw.Length; j++) * { * p_d_dense[i, j] = -rw[j]; * } * * rightSideDense[i] = -right; * }*/ {//sparse var right = 0.0; foreach (var t in buft.EnumerateColumnMembers(cnt))//enumerate column members of transposed matrix { if (t.Item1 != p_d.ColumnCount) { p_d.At(i, t.Item1, -t.Item2); } else { right = t.Item2; } } rightSide[i] = -right; } cnt++; } else { { var t = cnt3++; //p_d_dense[i, t] = 1; p_d.At(i, t, 1); } } } //var top2 = p_d_dense;//.ToDenseMatrix(); //var top3 = p_d.ToCCs().ToDenseMatrix(); //var d = (top2 - top3); //var d2 = rightSide.Plus(rightSideDense, -1); var pdd = (CCS)p_d.ToCCs(); return(Tuple.Create(pdd, rightSide)); var tol = 1e-6; throw new NotImplementedException(); }
public Tuple <CCS, double[]> CalculateDisplacementPermutation(CCS a) { //based on this solution : https://github.com/wo80/CSparse.NET/issues/7#issuecomment-317268696 if (a.RowCount < a.ColumnCount) { //For a matrix A with rows < columns, SparseQR does a factorization of the transpose A' //so we add zero rows to A and make it rectangular! var a2 = new CoordinateStorage <double>(a.ColumnCount, a.ColumnCount, a.NonZerosCount); foreach (var t in a.EnumerateIndexed()) { a2.At(t.Item1, t.Item2, t.Item3); } a = a2.ToCCs(); } //var adense = a.ToDenseMatrix(); SparseMatrix buf; var n = a.RowCount; var m = a.ColumnCount; var order = ColumnOrdering.Natural; var sp = System.Diagnostics.Stopwatch.StartNew(); var qr = SparseQR.Create(a, order); var t2 = sp.ElapsedMilliseconds; var r = GetFactorR(qr); var q = GetFactorQ(qr); var s = GetSymbolicFactorization(qr); var leads = new int[a.RowCount]; leads.FillWith(-1); //leads[i] = columnIndex of first nonzero in i'th row of r fasctor //if leads[i] == -1, then there is no nonzero in row[i] then i'th equation in original a matrix in non usable //this will be used for rdep and rindep var epsilon = 1e-8; foreach (var r_item in r.EnumerateIndexed()) { var rowNum = r_item.Item1; var colNum = r_item.Item2; var val = r_item.Item3; if (Math.Abs(val) <= epsilon) { ; //then row at } if (Math.Abs(val) > epsilon) //Then, if abs(R[i, i]) > tol, you found an independent row //Make sure to take row permutations into account (again, you can get the SymbolicFactorization containing row and column permutations using reflection) { if (leads[rowNum] == -1) { leads[rowNum] = colNum; } else { leads[rowNum] = Math.Min(leads[rowNum], colNum); } } } //throw new NotImplementedException("above section not right"); var leadCount = leads.Count(i => i != -1); { var nnzApprox = leadCount; var p1Crd = new CoordinateStorage <double>(leadCount, r.RowCount, nnzApprox); var p2Crd = new CoordinateStorage <double>(r.ColumnCount, leadCount, nnzApprox); var p2pCrd = new CoordinateStorage <double>(r.ColumnCount, r.ColumnCount - leadCount, nnzApprox); var cnt1 = 0; var cnt2 = 0; for (var i = 0; i < leads.Length; i++) { if (leads[i] != -1) { var j = leads[i]; p1Crd.At(cnt1, i, 1); p2Crd.At(j, cnt1, 1); cnt1++; } if (leads[i] == -1) { var j = i;// leads[i]; p2pCrd.At(j, cnt2, 1); cnt2++; } } var p1 = p1Crd.ToCCs(); var p2 = p2Crd.ToCCs(); var p2p = p2pCrd.ToCCs(); //var rp = r.Transpose(); var rdep = p1.Multiply(r).Multiply(p2); var rinDep = p1.Multiply(r).Multiply(p2p); var qr2 = SparseQR.Create(rdep, order); var t = sp.ElapsedMilliseconds; var right = new double[rinDep.RowCount]; var sol = new double[rinDep.RowCount]; var bufCrd = new CoordinateStorage <double>(leadCount, a.ColumnCount - leadCount, leadCount); for (var j = 0; j < rinDep.ColumnCount; j++) { //put the j'th column of r into the rightSide right.FillWith(0); { var col = j; var st = rinDep.ColumnPointers[j]; var end = rinDep.ColumnPointers[j + 1]; for (var ii = st; ii < end; ii++) { var row = rinDep.RowIndices[ii]; var val = rinDep.Values[ii]; right[row] = val; } } qr2.Solve(right, sol); for (var i = 0; i < rdep.RowCount; i++) { bufCrd.At(i, j, sol[i]); } } buf = bufCrd.ToCCs(); } //var top = buf.ToDenseMatrix(); var buft = buf.Transpose(); var masterCount = a.ColumnCount - 1 - leadCount; //var p_d_dense = new Matrix(a.ColumnCount - 1, masterCount); var p_d = new CoordinateStorage <double>(a.ColumnCount - 1, masterCount, 1); var rightSideDense = new double[a.ColumnCount - 1]; var rightSide = new double[a.ColumnCount - 1]; var cnt = 0; var cnt3 = 0; for (var i = 0; i < a.ColumnCount - 1; i++) { if (leads[i] != -1) { /*{//dense * var rw = top.ExtractRow(cnt).CoreArray; * * var right = rw.Last(); * Array.Resize(ref rw, rw.Length - 1); * * for (var j = 0; j < rw.Length; j++) * { * p_d_dense[i, j] = -rw[j]; * } * * rightSideDense[i] = -right; * }*/ {//sparse var right = 0.0; //var rowNum = s.pinv[i]; foreach (var t in buft.EnumerateColumnMembers(cnt))//enumerate column members of transposed matrix { var rowNum = i; var colNum = t.Item1; //var colNum = s.q[t.Item1]; var value = t.Item2; if (t.Item1 != p_d.ColumnCount) { p_d.At(rowNum, colNum, -value); } else { right = value; } } //rightSide[s.cp[i]] = -right; rightSide[i] = -right; } cnt++; } else { var t = cnt3++; var rowNum = i; // s.pinv[ i]; var colNum = t; // s.q[ t]; p_d.At(rowNum, colNum, 1); } } //var top2 = p_d_dense;//.ToDenseMatrix(); //var top3 = p_d.ToCCs().ToDenseMatrix(); //var d = (top2 - top3); //var d2 = rightSide.Plus(rightSideDense, -1); var pdd = (CCS)p_d.ToCCs(); return(Tuple.Create(pdd, rightSide)); var tol = 1e-6; throw new NotImplementedException(); }