double[,] BuildLocalMatrix(FiniteElement e)
        {
            Point p1 = Mesh.Points[e[0]];
            Point p2 = Mesh.Points[e[1]];
            Point p3 = Mesh.Points[e[2]];

            double hx = p2.X - p1.X;
            double hy = p3.Y - p1.Y;

            double mes   = hx * hy;
            double avgB  = GetAverageB(e);
            double mu    = e.Material.Mu(avgB);
            double muDer = e.Material.MuDer(avgB);

            double[,] G = new double[FEMParameters.BasisSize, FEMParameters.BasisSize];

            double lambda = 1.0 / mu;

            // Calculate G(q0)
            for (int i = 0; i < FEMParameters.BasisSize; i++)
            {
                for (int j = 0; j < FEMParameters.BasisSize; j++)
                {
                    G[i, j] = lambda * P[i, j];
                }
            }

            if (!FloatComparision.IsEqual(0.0, muDer))
            {
                // Calculate sums
                double der = -muDer / (mu * mu * 2 * avgB);

                for (int i = 0; i < FEMParameters.BasisSize; i++)
                {
                    for (int r = 0; r < FEMParameters.BasisSize; r++)
                    {
                        double sum1 = 0;
                        for (int s = 0; s < FEMParameters.BasisSize; s++)
                        {
                            sum1 += P[i, s] * q[e[s]];
                        }

                        double sum2 = 0;
                        for (int p = 0; p < FEMParameters.BasisSize; p++)
                        {
                            sum2 += P[r, p] * q[e[p]];
                        }

                        G[i, r] += 2.0 * der * sum1 * sum2 / mes;
                    }
                }
            }

            return(G);
        }
        double[] BuildLocalB(FiniteElement e)
        {
            Point p1 = Mesh.Points[e[0]];
            Point p2 = Mesh.Points[e[1]];
            Point p3 = Mesh.Points[e[2]];

            double hx  = p2.X - p1.X;
            double hy  = p3.Y - p1.Y;
            double mes = hx * hy;

            double avgB  = GetAverageB(e);
            double mu    = e.Material.Mu(avgB);
            double muDer = e.Material.MuDer(avgB);

            double[] B = new double[FEMParameters.BasisSize];
            double   J = e.Material.J;

            // Calculate b(q0)
            for (int i = 0; i < FEMParameters.BasisSize; i++)
            {
                for (int j = 0; j < FEMParameters.BasisSize; j++)
                {
                    B[i] += localM[i, j] * J;
                }
            }

            for (int i = 0; i < FEMParameters.BasisSize; i++)
            {
                B[i] *= hx * hy / 36;
            }

            if (!FloatComparision.IsEqual(0.0, muDer))
            {
                double der = -muDer / (mu * mu * 2 * avgB);

                // Calculate sum
                for (int i = 0; i < FEMParameters.BasisSize; i++)
                {
                    double sum1 = 0;
                    for (int s = 0; s < FEMParameters.BasisSize; s++)
                    {
                        sum1 += P[i, s] * q[e[s]];
                    }

                    double sum2 = 0;
                    for (int r = 0; r < FEMParameters.BasisSize; r++)
                    {
                        double sum = 0;
                        for (int p = 0; p < FEMParameters.BasisSize; p++)
                        {
                            sum += P[r, p] * q[e[p]];
                        }

                        sum2 += q[e[r]] * sum;
                    }

                    B[i] += 2.0 * der * sum1 * sum2 / mes;
                }
            }

            return(B);
        }