// Result must be as large as Mesh.MaxVertexID public bool SolveMultipleRHS(Vector3d[] Result) { if (WeightsM == null) { Initialize(); // force initialize... } UpdateForSolve(); // use initial positions as initial solution. double[][] B = BufferUtil.InitNxM(3, N, new double[][] { Bx, By, Bz }); double[][] X = BufferUtil.InitNxM(3, N, new double[][] { Px, Py, Pz }); Action <double[][], double[][]> CombinedMultiply = (Xt, Bt) => { PackedM.Multiply_Parallel_3(Xt, Bt); gParallel.ForEach(Interval1i.Range(3), (j) => { BufferUtil.MultiplyAdd(Bt[j], WeightsM.D, Xt[j]); }); }; var Solver = new SparseSymmetricCGMultipleRHS() { B = B, X = X, MultiplyF = CombinedMultiply, PreconditionMultiplyF = null, UseXAsInitialGuess = true }; bool ok = Solver.Solve(); if (ok == false) { return(false); } for (int i = 0; i < N; ++i) { int vid = ToMeshV[i]; Result[vid] = new Vector3d(X[0][i], X[1][i], X[2][i]); } // apply post-fixed constraints if (HavePostFixedConstraints) { foreach (var constraint in SoftConstraints) { if (constraint.Value.PostFix) { int vid = constraint.Key; Result[vid] = constraint.Value.Position; } } } return(true); }