コード例 #1
0
        // Result must be as large as Mesh.MaxVertexID
        public bool SolveMultipleCG(Vector3d[] Result)
        {
            if (WeightsM == null)
            {
                Initialize();       // force initialize...
            }
            UpdateForSolve();

            // use initial positions as initial solution.
            Array.Copy(Px, Sx, N);
            Array.Copy(Py, Sy, N);
            Array.Copy(Pz, Sz, N);

            Action <double[], double[]> CombinedMultiply = (X, B) => {
                //PackedM.Multiply(X, B);
                PackedM.Multiply_Parallel(X, B);

                for (int i = 0; i < N; ++i)
                {
                    B[i] += WeightsM.D[i] * X[i];
                }
            };

            SparseSymmetricCG SolverX = new SparseSymmetricCG()
            {
                B                  = Bx, X = Sx,
                MultiplyF          = CombinedMultiply, PreconditionMultiplyF = Preconditioner.Multiply,
                UseXAsInitialGuess = true
            };
            SparseSymmetricCG SolverY = new SparseSymmetricCG()
            {
                B                  = By, X = Sy,
                MultiplyF          = CombinedMultiply, PreconditionMultiplyF = Preconditioner.Multiply,
                UseXAsInitialGuess = true
            };
            SparseSymmetricCG SolverZ = new SparseSymmetricCG()
            {
                B                  = Bz, X = Sz,
                MultiplyF          = CombinedMultiply, PreconditionMultiplyF = Preconditioner.Multiply,
                UseXAsInitialGuess = true
            };

            SparseSymmetricCG[] solvers = new SparseSymmetricCG[3] {
                SolverX, SolverY, SolverZ
            };
            bool[] ok      = new bool[3];
            int[]  indices = new int[3] {
                0, 1, 2
            };

            // preconditioned solve is marginally faster
            Action <int> SolveF = (i) => { ok[i] = solvers[i].SolvePreconditioned(); };

            //Action<int> SolveF = (i) => {  ok[i] = solvers[i].Solve(); };
            gParallel.ForEach(indices, SolveF);

            if (ok[0] == false || ok[1] == false || ok[2] == false)
            {
                return(false);
            }

            for (int i = 0; i < N; ++i)
            {
                int vid = ToMeshV[i];
                Result[vid] = new Vector3d(Sx[i], Sy[i], Sz[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);
        }
コード例 #2
0
        // Result must be as large as Mesh.MaxVertexID
        public bool SolveMultipleCG(Vector3d[] Result)
        {
            if (WeightsM == null)
            {
                Initialize();       // force initialize...
            }
            UpdateForSolve();

            // use initial positions as initial solution.
            Array.Copy(Px, Sx, N);
            Array.Copy(Py, Sy, N);
            Array.Copy(Pz, Sz, N);


            Action <double[], double[]> CombinedMultiply = (X, B) => {
                //PackedM.Multiply(X, B);
                PackedM.Multiply_Parallel(X, B);

                for (int i = 0; i < N; ++i)
                {
                    B[i] += WeightsM[i, i] * X[i];
                }
            };

            List <SparseSymmetricCG> Solvers = new List <SparseSymmetricCG>();

            if (SolveX)
            {
                Solvers.Add(new SparseSymmetricCG()
                {
                    B                  = Bx, X = Sx,
                    MultiplyF          = CombinedMultiply, PreconditionMultiplyF = Preconditioner.Multiply,
                    UseXAsInitialGuess = true
                });
            }
            if (SolveY)
            {
                Solvers.Add(new SparseSymmetricCG()
                {
                    B                  = By, X = Sy,
                    MultiplyF          = CombinedMultiply, PreconditionMultiplyF = Preconditioner.Multiply,
                    UseXAsInitialGuess = true
                });
            }
            if (SolveZ)
            {
                Solvers.Add(new SparseSymmetricCG()
                {
                    B                  = Bz, X = Sz,
                    MultiplyF          = CombinedMultiply, PreconditionMultiplyF = Preconditioner.Multiply,
                    UseXAsInitialGuess = true
                });
            }
            bool[] ok = new bool[Solvers.Count];

            gParallel.ForEach(Interval1i.Range(Solvers.Count), (i) => {
                ok[i] = Solvers[i].Solve();
                // preconditioned solve is slower =\
                //ok[i] = solvers[i].SolvePreconditioned();
            });

            ConvergeFailed = false;
            foreach (bool b in ok)
            {
                if (b == false)
                {
                    ConvergeFailed = true;
                }
            }

            for (int i = 0; i < N; ++i)
            {
                int vid = ToCurveV[i];
                Result[vid] = new Vector3d(Sx[i], Sy[i], Sz[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);
        }