public LinearProblemProperties UpdateConstantsTerm(
            JacobianConstraint[] constraints,
            LinearProblemProperties input)
        {
            for (int i = 0; i < constraints.Length; i++)
            {
                var    constraint    = constraints[i];
                double correctionVal = constraint.CorrectionValue * EngineParameters.TimeStep;

                double correctionValue = (correctionVal) < 0 ?
                                         Math.Max(correctionVal, -EngineParameters.MaxCorrectionValue) :
                                         Math.Min(correctionVal, EngineParameters.MaxCorrectionValue);

                double jacobianVelocityValue = 0.0;

                if (constraint.LinearComponentA.HasValue)
                {
                    jacobianVelocityValue += constraint.LinearComponentA.Value.Dot(constraint.ObjectA.LinearVelocity);
                }
                if (constraint.LinearComponentB.HasValue)
                {
                    jacobianVelocityValue += constraint.LinearComponentB.Value.Dot(constraint.ObjectA.LinearVelocity);
                }

                jacobianVelocityValue += constraint.AngularComponentA.Dot(constraint.ObjectA.AngularVelocity) +
                                         constraint.AngularComponentB.Dot(constraint.ObjectB.AngularVelocity);

                input.B[i] = correctionValue - jacobianVelocityValue - constraint.ConstraintValue;
            }

            return(input);
        }
Example #2
0
 public double[] Solve(
     LinearProblemProperties linearProblemProperties,
     JacobianConstraint[] constraints,
     double[] x)
 {
     return(solver.Solve(linearProblemProperties.M, linearProblemProperties.B, SolverParameters.MaxIterations));
 }
        public double[] Solve(LinearProblemProperties input, JacobianConstraint[] constraints, double[] x)
        {
            x = gaussSeidelSolver.Solve(input, constraints, x);



            return(x);
        }
Example #4
0
        static void Main(string[] args)
        {
            GaussSeidel solver = new GaussSeidel(1.0);

            double[] M = new double[9];
            M[0] = 12.0;
            M[1] = 3.0;
            M[2] = -5.0;
            M[3] = 1.0;
            M[4] = 5.0;
            M[5] = 3.0;
            M[6] = 3.0;
            M[7] = 7.0;
            M[8] = 13.0;


            double[] B = new double[3];
            B[0] = 1.0;
            B[1] = 28.0;
            B[2] = 76.0;

            double[] startX = new double[3];
            startX[0] = 1.0;
            startX[0] = 0.0;
            startX[0] = 1.0;

            LinearProblemProperties linearProblemProperties = new LinearProblemProperties(
                M,
                B,
                startX,
                3);

            double[] X = new double[3];

            NonLinearConjugateGradient nonLinearConjugateGradient = new NonLinearConjugateGradient(3);

            double[] X1 = nonLinearConjugateGradient.Solve(linearProblemProperties);

            for (int i = 0; i < 4; i++)
            {
                X = solver.Solve(linearProblemProperties);
            }

            double[] out0 = nonLinearConjugateGradient.CalculateError(linearProblemProperties.M, linearProblemProperties.B, X1);
            double[] out1 = nonLinearConjugateGradient.CalculateError(linearProblemProperties.M, linearProblemProperties.B, X);

            Console.ReadLine();
        }
Example #5
0
        private double[] BuildMatrixAndExecuteSolver(
            JacobianConstraint[] contactConstraints,
            LinearProblemProperties linearProblemProperties,
            int nIterations)
        {
            if (linearProblemProperties != null)
            {
                Solver.GetSolverParameters().SetSolverMaxIteration(nIterations);

                double[] solutionValues = Solver.Solve(linearProblemProperties, contactConstraints, new double[linearProblemProperties.Count]);

                return(solutionValues);
            }

            return(null);
        }
        private SubspaceValues GetIndexSets(LinearProblemProperties input, double[] x)
        {
            var result = new SubspaceValues();

            for (int i = 0; i < x.Length; i++)
            {
                switch (input.ConstraintType[i])
                {
                case ConstraintType.Collision:
                case ConstraintType.JointLimit:
                    if (x[i] <= 0.0)
                    {
                        result.LowerIndexes.Add(i);
                    }
                    else
                    {
                        result.UnboundedIndexes.Add(i);
                    }
                    break;

                case ConstraintType.Friction:
                    int    sign          = (input.Constraints[i].Value < 0) ? -1 : 1;
                    int    normalIndex   = sign * input.Constraints[i].Value;
                    double frictionLimit = x[normalIndex] * input.ConstraintLimit[i];
                    int    idx1          = normalIndex + sign;
                    int    idx2          = normalIndex + sign * 2;

                    double directionA    = x[idx1];
                    double directionB    = x[idx2];
                    double frictionValue = Math.Sqrt(directionA * directionA + directionB * directionB);

                    if (frictionValue > frictionLimit)
                    {
                        Vector2d frictionNormal = new Vector2d(directionA / frictionValue, directionB / frictionValue);
                    }

                    break;

                default:
                    break;
                }
            }

            return(result);
        }
Example #7
0
        private double[] Solve(JacobianConstraint[] jacobianConstraints)
        {
            LinearProblemProperties LCP = LinearSystemBuilder.BuildLCP(jacobianConstraints, 0.001);

            double[] partialSolution = new double[LCP.Count];
            double[] overallSolution = new double[LCP.Count];

            Solver.GetSolverParameters().SetSolverMaxIteration(2);

            for (int i = 0; i < 15; i++)
            {
                overallSolution = MathUtils.Add(overallSolution, partialSolution);
                partialSolution = Solver.Solve(LCP, jacobianConstraints, overallSolution);
            }

            //double[] overallSolution = Solver.Solve(LCP, LCP.StartImpulse);

            return(overallSolution);
        }
Example #8
0
        private void SolveConstraints()
        {
            #region Contact and Joint elaboration

            //SaveShapePreviousProperties(collisionPoints);

            if (Partitions != null && Partitions.Any())
            {
                var rangePartitioner = Partitioner.Create(
                    0,
                    Partitions.Count,
                    Convert.ToInt32(Partitions.Count / EngineParameters.MaxThreadNumber) + 1);

                Parallel.ForEach(
                    rangePartitioner,
                    new ParallelOptions {
                    MaxDegreeOfParallelism = EngineParameters.MaxThreadNumber
                },
                    (range, loopState) =>
                {
                    for (int i = range.Item1; i < range.Item2; i++)
                    {
                        JacobianConstraint[] jacobianConstraints = GetJacobianConstraints(
                            Partitions[i].PartitionedCollisionPoints.ToArray(),
                            Partitions[i].PartitionedJoints,
                            Shapes,
                            EngineParameters);

                        if (jacobianConstraints.Length > 0)
                        {
                            LinearProblemProperties LCP = GenerateLCP(jacobianConstraints);
                            double[]  overallSolution   = Solver.Solve(LCP, jacobianConstraints, LCP.StartImpulse);
                            //double[] overallSolution = Solve(jacobianConstraints);

                            IntegrateVelocityEngine.UpdateVelocity(jacobianConstraints, overallSolution);
                        }
                    }
                });
            }

            #endregion
        }
        public LinearProblemProperties BuildLCP(
            JacobianConstraint[] constraints,
            double timeStep)
        {
            LinearProblemBaseProperties baseProperties = new LinearProblemBaseProperties(constraints.Length);

            Dictionary <HashSetStruct, List <DictionaryConstraintValue> > constraintsDictionary = new Dictionary <HashSetStruct, List <DictionaryConstraintValue> >();

            for (int i = 0; i < constraints.Length; i++)
            {
                JacobianConstraint itemConstraint = constraints[i];

                HashSetStruct hash = new HashSetStruct(itemConstraint.ObjectA.ID, itemConstraint.ObjectB.ID);

                if (constraintsDictionary.TryGetValue(hash, out List <DictionaryConstraintValue> jc))
                {
                    jc.Add(new DictionaryConstraintValue(itemConstraint, i));
                }
                else
                {
                    constraintsDictionary.Add(hash, new List <DictionaryConstraintValue> {
                        new DictionaryConstraintValue(itemConstraint, i)
                    });
                }
            }

            Graph graph = new Graph(constraints.Length);

            var dictionaryArray = constraintsDictionary.ToArray();

            var key_ID_A = constraintsDictionary.ToLookup(x => x.Key.ID_A);
            var key_ID_B = constraintsDictionary.ToLookup(x => x.Key.ID_B);

            var rangePartitioner = Partitioner.Create(
                0,
                dictionaryArray.Length,
                Convert.ToInt32(dictionaryArray.Length / EngineParameters.MaxThreadNumber) + 1);

            double timeFreq = 1.0 / timeStep;

            Parallel.ForEach(
                rangePartitioner,
                new ParallelOptions {
                MaxDegreeOfParallelism = EngineParameters.MaxThreadNumber
            },
                (range, loopState) =>
            {
                for (int i = range.Item1; i < range.Item2; i++)
                {
                    var constraintValues   = dictionaryArray[i];
                    var constraintValueKey = constraintValues.Key;

                    int contactA_ID_A = constraintValues.Key.ID_A;
                    int contactA_ID_B = constraintValues.Key.ID_B;

                    for (int w = 0; w < constraintValues.Value.Count; w++)
                    {
                        JacobianConstraint contactA = constraintValues.Value[w].Constraint;

                        List <int> index     = new List <int>();
                        List <double> values = new List <double>();

                        int indexVal = constraintValues.Value[w].Index;

                        double correctionVal = contactA.CorrectionValue * timeFreq;

                        double correctionValue = (correctionVal) < 0 ?
                                                 Math.Max(correctionVal, -EngineParameters.MaxCorrectionValue) :
                                                 Math.Min(correctionVal, EngineParameters.MaxCorrectionValue);

                        baseProperties.B[indexVal] = correctionValue - contactA.JacobianVelocity - contactA.ConstraintValue;
                        baseProperties.ConstraintsArray[indexVal] = contactA.ContactReference;
                        baseProperties.ConstraintLimit[indexVal]  = contactA.ConstraintLimit;
                        baseProperties.ConstraintType[indexVal]   = contactA.Type;

                        //Diagonal value
                        double mValue = GetLCPDiagonalValue(contactA) +
                                        (contactA.CFM * timeFreq) +
                                        EngineParameters.CFM +
                                        1E-40;

                        baseProperties.D[indexVal]    = mValue;
                        baseProperties.InvD[indexVal] = 1.0 / mValue;

                        //contactA_ID_A == contactB_ID_A && contactA_ID_B == contactB_ID_B
                        for (int j = 0; j < constraintValues.Value.Count; j++)
                        {
                            int innerIndex = constraintValues.Value[j].Index;

                            if (innerIndex != indexVal)
                            {
                                JacobianConstraint contactB = constraintValues.Value[j].Constraint;

                                mValue = GetLCPMatrixValue(
                                    contactA.LinearComponentA,
                                    contactB.LinearComponentA,
                                    contactA.AngularComponentA,
                                    contactB.AngularComponentA,
                                    contactA.ObjectA.MassInfo);

                                mValue += GetLCPMatrixValue(
                                    contactA.LinearComponentB,
                                    contactB.LinearComponentB,
                                    contactA.AngularComponentB,
                                    contactB.AngularComponentB,
                                    contactA.ObjectB.MassInfo);

                                AddValues(ref index, ref values, mValue, innerIndex);
                            }
                        }

                        //contactA_ID_A == contactB_ID_B && contactA_ID_B == contactB_ID_A
                        var symmetricHashSet = new HashSetStruct(contactA_ID_B, contactA_ID_A);
                        if (constraintsDictionary.TryGetValue(symmetricHashSet, out List <DictionaryConstraintValue> symmetricList))
                        {
                            foreach (var item in symmetricList)
                            {
                                int innerIndex = item.Index;

                                if (innerIndex != indexVal)
                                {
                                    JacobianConstraint contactB = item.Constraint;

                                    mValue = GetLCPMatrixValue(
                                        contactA.LinearComponentA,
                                        contactB.LinearComponentB,
                                        contactA.AngularComponentA,
                                        contactB.AngularComponentB,
                                        contactA.ObjectA.MassInfo);

                                    mValue += GetLCPMatrixValue(
                                        contactA.LinearComponentB,
                                        contactB.LinearComponentA,
                                        contactA.AngularComponentB,
                                        contactB.AngularComponentA,
                                        contactA.ObjectB.MassInfo);

                                    AddValues(ref index, ref values, mValue, innerIndex);
                                }
                            }
                        }

                        //contactA_ID_A == contactB_ID_A
                        foreach (var constraintCheckItem in key_ID_A[contactA_ID_A])
                        {
                            AddLCPValues(
                                ref index,
                                ref values,
                                indexVal,
                                constraintCheckItem,
                                constraintValueKey,
                                symmetricHashSet,
                                contactA.LinearComponentA,
                                contactA.AngularComponentA,
                                contactA.ObjectA.MassInfo,
                                true);
                        }

                        //contactA_ID_A == contactB_ID_B
                        foreach (var constraintCheckItem in key_ID_B[contactA_ID_A])
                        {
                            AddLCPValues(
                                ref index,
                                ref values,
                                indexVal,
                                constraintCheckItem,
                                constraintValueKey,
                                symmetricHashSet,
                                contactA.LinearComponentA,
                                contactA.AngularComponentA,
                                contactA.ObjectA.MassInfo,
                                false);
                        }

                        //contactA_ID_B == contactB_ID_A
                        foreach (var constraintCheckItem in key_ID_A[contactA_ID_B])
                        {
                            AddLCPValues(
                                ref index,
                                ref values,
                                indexVal,
                                constraintCheckItem,
                                constraintValueKey,
                                symmetricHashSet,
                                contactA.LinearComponentB,
                                contactA.AngularComponentB,
                                contactA.ObjectB.MassInfo,
                                true);
                        }

                        //contactA_ID_B == contactB_ID_B
                        foreach (var constraintCheckItem in key_ID_B[contactA_ID_B])
                        {
                            AddLCPValues(
                                ref index,
                                ref values,
                                indexVal,
                                constraintCheckItem,
                                constraintValueKey,
                                symmetricHashSet,
                                contactA.LinearComponentB,
                                contactA.AngularComponentB,
                                contactA.ObjectB.MassInfo,
                                false);
                        }

                        //Sparse Matrix
                        baseProperties.M.Rows[indexVal] = new SparseVector(
                            values.ToArray(),
                            index.ToArray(),
                            baseProperties.M.m);

                        UpdateGraph(ref graph, index, indexVal);
                    }
                }
            });

            var lp = new LinearProblemProperties(
                baseProperties,
                graph,
                EngineParameters.FrictionDirections);

            return(lp);
        }
        //TODO Refactor
        public LinearProblemProperties GetLCPFrictionMatrix(LinearProblemProperties linearProblem)
        {
            var collisionIndexes = linearProblem.ConstraintType
                                   .Select((constraint, index) => new { constraint, index })
                                   .Where(x => x.constraint == ConstraintType.Collision).ToList();

            if (collisionIndexes.Count > 0)
            {
                var numberOfCollision = collisionIndexes.Count;
                var lcpMatrixDim      = linearProblem.Count + numberOfCollision;

                var frictionIndexes = linearProblem.ConstraintType
                                      .Select((constraint, index) => new { constraint, index })
                                      .Where(x => x.constraint == ConstraintType.Friction).ToList();

                LinearProblemBaseProperties baseProperties = new LinearProblemBaseProperties(lcpMatrixDim);

                var b                = linearProblem.B.ToList();
                var d                = linearProblem.D.ToList();
                var invD             = linearProblem.InvD.ToList();
                var constraintType   = linearProblem.ConstraintType.ToList();
                var constraintLimit  = linearProblem.ConstraintLimit.ToList();
                var m                = linearProblem.GetOriginalSparseMatrix().Rows.ToList();
                var constraintsArray = linearProblem.Constraints.ToList();
                var startValue       = linearProblem.StartImpulse.ToList();
                var E_dim            = numberOfCollision * EngineParameters.FrictionDirections;
                var newRowLength     = b.Count + numberOfCollision;

                //Add fields to friction rows
                for (int i = 0; i < numberOfCollision; i++)
                {
                    var colIdx = collisionIndexes[i].index;

                    var fIndexes = constraintsArray.Select((constraint, index) => new { constraint, index })
                                   .Where(x => x.constraint.HasValue && x.constraint.Value == colIdx).ToList();

                    //Add elements to matrix M, friction values
                    var rowIndexes = new List <int>()
                    {
                        collisionIndexes[i].index
                    };
                    var rowValues = new List <double>()
                    {
                        constraintLimit[frictionIndexes[0].index]
                    };

                    //Columns and rows update
                    for (int j = 0; j < fIndexes.Count; j++)
                    {
                        var idx      = fIndexes[j].index;
                        var mIdx     = m[idx];
                        var bufIndex = new List <int>(mIdx.Index);
                        var bufValue = new List <double>(mIdx.Value);
                        bufIndex.Add(mIdx.Length + i);
                        bufValue.Add(1.0);

                        m[idx] = new SparseVector(
                            bufValue.ToArray(),
                            bufIndex.ToArray(),
                            mIdx.Length + numberOfCollision);

                        rowIndexes.Add(idx);
                        rowValues.Add(-1.0);
                    }

                    //Rows Update
                    constraintType.Add(ConstraintType.FrictionValue);
                    b.Add(0.0);
                    d.Add(0.0);
                    invD.Add(0.0);
                    constraintLimit.Add(0.0);
                    startValue.Add(0.0);

                    var sparseElement = new SparseVector(
                        rowValues.ToArray(),
                        rowIndexes.ToArray(),
                        newRowLength);

                    m.Add(sparseElement);
                }

                for (int i = 0; i < m.Count; i++)
                {
                    m[i]  = new SparseVector(m[i].Value, m[i].Index, newRowLength);
                    b[i] *= -1.0;
                }

                baseProperties.B               = b.ToArray();
                baseProperties.D               = d.ToArray();
                baseProperties.InvD            = invD.ToArray();
                baseProperties.ConstraintType  = constraintType.ToArray();
                baseProperties.ConstraintLimit = constraintLimit.ToArray();
                baseProperties.StartValue      = startValue.ToArray();
                baseProperties.M.Rows          = m.ToArray();

                var lcp = new LinearProblemProperties(baseProperties, null, EngineParameters.FrictionDirections);

                //TODO Test
                //var test = lcp.GetOriginalMatrix();

                return(lcp);
            }

            return(linearProblem);
        }