예제 #1
0
        private void build()
        {
            double l, r, c;

            double next_h = points[2].X - points[1].X; // h1
            double prev_h = points[1].X - points[0].X; // h2

            // f'0
            l = -1.0 * (3.0 * prev_h + 2.0 * next_h) /
                (prev_h * (prev_h + next_h));
            c = (2.0 * next_h + prev_h) /
                (prev_h * next_h);
            r = -1.0 * prev_h /
                (next_h * (prev_h + next_h));
            coeffs[0] = 0.5 * (points[0].Y * l + points[1].Y * c + points[2].Y * r);

            // f'n
            next_h           = points[size - 1].X - points[size - 2].X;
            prev_h           = points[size - 2].X - points[size - 3].X;
            l                = next_h / (prev_h * (prev_h + next_h));
            c                = -1.0 * (next_h + 2.0 * prev_h) / (prev_h * next_h);
            r                = (3.0 * next_h + 2.0 * prev_h) / (next_h * (prev_h + next_h));
            coeffs[size - 1] = 0.5 * (points[size - 3].Y * l + points[size - 2].Y * c + points[size - 1].Y * r);

            diagonals[1, 0]        = 1;
            diagonals[1, size - 1] = 1;

            for (int i = 1; i < size - 1; i++)
            {
                next_h = points[i + 1].X - points[i].X;
                prev_h = points[i].X - points[i - 1].X;

                diagonals[0, i] = 2.0 / prev_h;
                diagonals[1, i] = 4.0 * (1.0 / prev_h + 1.0 / next_h);
                diagonals[2, i] = 2.0 / next_h;

                coeffs[i] = -6.0 * points[i - 1].Y / (prev_h * prev_h) +
                            6.0 * points[i].Y * (1.0 / (prev_h * prev_h) - 1.0 / (next_h * next_h)) +
                            6.0 * points[i + 1].Y / (next_h * next_h);
            }

            DiagMatrix matrix = new DiagMatrix(size, offsets, diagonals);
            Vector     vec    = new Vector(coeffs);
            Vector     x      = new Vector(coeffs.Length);

            SoLESolver.Epsilon = 1E-12;
            SoLESolver.SolveSeidel(matrix, vec, x, 1.5);

            coeffs = x.values;
        }
예제 #2
0
파일: Problem.cs 프로젝트: Hrenaki/2D-FEM
        public void Solve()
        {
            generatePortrait();

            double[,] localMatrix = new double[3, 3]; // local matrix
            double[] localB = new double[3];          // local B
            double[,] D_1 = new double[3, 3];

            Func   localFunction;
            double gamma;
            double lambda;

            double detD;      //  detD: (x2 - x1)(y3 - y1) - (x3 - x1)(y2 - y1)

            int[]    numbers; // global numbers of element's vertexes
            double[] v1;      // vertex 1
            double[] v2;      // vertex 2
            double[] v3;      // vertex 3
            double   timeValue;

            double dt, dt0, dt1;
            Vector q0, q1;

            int    i, j, k, s, m, t;
            double temp;

            double[] curVert;

            int condSize = conditions.Length;

            int[] curBound;

            #region first step
            //timeValue = timeLayers[1];
            //dt = timeLayers[1] - timeLayers[0];
            //temp = 1.0 / dt;
            //
            //q1 = coeffs[0];
            //
            //// element loop
            //for (k = 0; k < elemCount; k++)
            //{
            //    numbers = elems[k].Take(3).ToArray();
            //
            //    gamma = sigma_values[elems[k][3]];
            //    lambda = lambda_values[elems[k][3]];
            //    localFunction = function[elems[k][3]];
            //
            //    v1 = vertexes[numbers[0]]; // (x1, y1)
            //    v2 = vertexes[numbers[1]]; // (x2, y2)
            //    v3 = vertexes[numbers[2]]; // (x3, y3)
            //
            //    detD = (v2[0] - v1[0]) * (v3[1] - v1[1]) - (v3[0] - v1[0]) * (v2[1] - v1[1]);
            //
            //    #region Вычисление матрицы D^(-1)
            //    D_1[0, 0] = (v2[0] * v3[1] - v3[0] * v2[1]) / detD; // x2 * y3 - x3 * y2
            //    D_1[1, 0] = (v1[1] * v3[0] - v1[0] * v3[1]) / detD; // -(x1 * y3 - y1 * x3)
            //    D_1[2, 0] = (v1[0] * v2[1] - v1[1] * v2[0]) / detD; // x1 * y2 - y1 * x2
            //
            //    D_1[0, 1] = (v2[1] - v3[1]) / detD; // -(y3 - y2)
            //    D_1[1, 1] = (v3[1] - v1[1]) / detD; // y3 - y1
            //    D_1[2, 1] = (v1[1] - v2[1]) / detD; // -(y2 - y1)
            //
            //    D_1[0, 2] = (v3[0] - v2[0]) / detD; // x3 - x2
            //    D_1[1, 2] = (v1[0] - v3[0]) / detD; // -(x3 - x1)
            //    D_1[2, 2] = (v2[0] - v1[0]) / detD; // x2 - x1
            //    #endregion
            //
            //    detD = Math.Abs(detD);
            //
            //    // mass matrix
            //    for (i = 0; i < 3; i++)
            //    {
            //        localMatrix[i, i] = gamma * detD / 12.0;
            //        for (j = i + 1; j < 3; j++)
            //        {
            //            localMatrix[i, j] = gamma * detD / 24.0;
            //            localMatrix[j, i] = localMatrix[i, j];
            //        }
            //
            //        // b[i] = 1 / dt * Mq_j-1
            //        localB[i] = temp * (localMatrix[i, 0] * q1[numbers[0]] + localMatrix[i, 1] * q1[numbers[1]] + localMatrix[i, 2] * q1[numbers[2]]);
            //        localMatrix[i, 0] *= temp;
            //        localMatrix[i, 1] *= temp;
            //        localMatrix[i, 2] *= temp;
            //    }
            //
            //    // adding G to local A
            //    for (i = 0; i < 3; i++)
            //        for (j = 0; j < 3; j++)
            //            localMatrix[i, j] += lambda * detD / 2.0 *
            //                (D_1[i, 1] * D_1[j, 1] + D_1[i, 2] * D_1[j, 2]);
            //    // Gij = lambda * |detD| / 2.0 * (a(i,1) * a(j,1) + a(i,2) * a(j,2))
            //    // Aij = Gij + Mij
            //
            //    // adding diagonal to global matrix
            //    for (i = 0; i < 3; i++)
            //        di[numbers[i]] += localMatrix[i, i];
            //
            //    for (i = 1; i < 3; i++)
            //    {
            //        m = ig[numbers[i]];
            //        for (j = 0; j < i; j++)
            //        {
            //            for (s = m; s < ig[numbers[i] + 1]; s++)
            //                if (jg[s] == numbers[j])
            //                {
            //                    gg[s] += localMatrix[i, j];
            //                    m++;
            //                    break;
            //                }
            //        }
            //    }
            //
            //    // local B
            //    localB[0] += (2.0 * localFunction(v1[0], v1[1], timeValue) + localFunction(v2[0], v2[1], timeValue) + localFunction(v3[0], v3[1], timeValue)) / 24.0 * detD;
            //    localB[1] += (localFunction(v1[0], v1[1], timeValue) + 2.0 * localFunction(v2[0], v2[1], timeValue) + localFunction(v3[0], v3[1], timeValue)) / 24.0 * detD;
            //    localB[2] += (localFunction(v1[0], v1[1], timeValue) + localFunction(v2[0], v2[1], timeValue) + 2.0 * localFunction(v3[0], v3[1], timeValue)) / 24.0 * detD;
            //
            //    #region Second type boundary conditions
            //    for (m = 0; m < condSize; m++)
            //    {
            //        if (conditions[m].Type == 2)
            //        {
            //            for(i = 0; i < 2; i++)
            //                for(j = i + 1; j < 3; j++)
            //                    if(conditions[m].CheckEdge(numbers[i], numbers[j]))
            //                    {
            //                        v1 = vertexes[numbers[i]];
            //                        v2 = vertexes[numbers[j]];
            //                        localFunction = conditions[m].Value;
            //
            //                        temp = localFunction(v1[0], v1[1], timeValue);
            //                        gamma = localFunction(v2[0], v2[1], timeValue);
            //                        lambda = 2.0 * temp + gamma;
            //                        detD = temp + 2.0 * gamma;
            //                        temp = Math.Sqrt((v2[0] - v1[0]) * (v2[0] - v1[0]) + (v2[1] - v1[1]) * (v2[1] - v1[1])) / 6.0;
            //
            //                        localB[i] += temp * lambda;
            //                        localB[j] += temp * detD;
            //                    }
            //        }
            //    }
            //    #endregion
            //
            //    // adding local B to global B
            //    for (i = 0; i < 3; i++)
            //        globalB[numbers[i]] += localB[i];
            //}
            //
            //// First type boundary conditions
            //foreach (BoundaryCondition condition in conditions)
            //{
            //    if (condition.Type == 1)
            //    {
            //        curBound = condition.Vertexes;
            //        localFunction = condition.Value;
            //        for (k = 0; k < curBound.Length; k++)
            //        {
            //            i = curBound[k];
            //            curVert = vertexes[i];
            //
            //            di[i] = 1;
            //            globalB[i] = localFunction(curVert[0], curVert[1], timeValue);
            //
            //            for (s = ig[i]; s < ig[i + 1]; s++)
            //            {
            //                globalB[jg[s]] -= gg[s] * globalB[i];
            //                gg[s] = 0;
            //            }
            //
            //            for (s = i + 1; s < vertexesCount; s++)
            //            {
            //                for (j = ig[s]; j < ig[s + 1] && jg[j] <= i; j++)
            //                {
            //                    if (jg[j] == i)
            //                    {
            //                        globalB[s] -= gg[j] * globalB[i];
            //                        gg[j] = 0;
            //                        break;
            //                    }
            //                }
            //            }
            //        }
            //    }
            //}
            //
            //SoLESolver.SolveCGM_LLT(globalMatrix, globalB, coeffs[1]);
            #endregion

            for (t = 2; t < timeLayers.Length; t++)
            {
                globalMatrix.ClearValues();
                globalB.ClearValues();

                timeValue = timeLayers[t];
                dt        = timeLayers[t] - timeLayers[t - 2];
                dt1       = timeLayers[t - 1] - timeLayers[t - 2];
                dt0       = timeLayers[t] - timeLayers[t - 1];

                q1 = coeffs[t - 1];
                q0 = coeffs[t - 2];

                // element loop
                for (k = 0; k < elemCount; k++)
                {
                    numbers = elems[k];

                    gamma         = sigma_values[numbers[3]];
                    lambda        = lambda_values[numbers[3]];
                    localFunction = function[numbers[3]];

                    v1 = vertexes[numbers[0]]; // (x1, y1)
                    v2 = vertexes[numbers[1]]; // (x2, y2)
                    v3 = vertexes[numbers[2]]; // (x3, y3)

                    detD = (v2[0] - v1[0]) * (v3[1] - v1[1]) - (v3[0] - v1[0]) * (v2[1] - v1[1]);

                    #region Вычисление матрицы D^(-1)
                    D_1[0, 0] = (v2[0] * v3[1] - v3[0] * v2[1]) / detD; // x2 * y3 - x3 * y2
                    D_1[1, 0] = (v1[1] * v3[0] - v1[0] * v3[1]) / detD; // -(x1 * y3 - y1 * x3)
                    D_1[2, 0] = (v1[0] * v2[1] - v1[1] * v2[0]) / detD; // x1 * y2 - y1 * x2

                    D_1[0, 1] = (v2[1] - v3[1]) / detD;                 // -(y3 - y2)
                    D_1[1, 1] = (v3[1] - v1[1]) / detD;                 // y3 - y1
                    D_1[2, 1] = (v1[1] - v2[1]) / detD;                 // -(y2 - y1)

                    D_1[0, 2] = (v3[0] - v2[0]) / detD;                 // x3 - x2
                    D_1[1, 2] = (v1[0] - v3[0]) / detD;                 // -(x3 - x1)
                    D_1[2, 2] = (v2[0] - v1[0]) / detD;                 // x2 - x1
                    #endregion

                    detD = Math.Abs(detD);

                    // mass matrix
                    for (i = 0; i < 3; i++)
                    {
                        localMatrix[i, i] = gamma * detD / 12.0;
                        for (j = i + 1; j < 3; j++)
                        {
                            localMatrix[i, j] = gamma * detD / 24.0;
                            localMatrix[j, i] = localMatrix[i, j];
                        }

                        // b[i] = -(dt0 / (dt * dt1)) * Mq_j-2 + (dt / (dt1 * dt0)) * Mq_j-1
                        localB[i] = -dt0 / (dt * dt1) * (localMatrix[i, 0] * q0[numbers[0]] + localMatrix[i, 1] * q0[numbers[1]] + localMatrix[i, 2] * q0[numbers[2]]) +
                                    dt / (dt1 * dt0) * (localMatrix[i, 0] * q1[numbers[0]] + localMatrix[i, 1] * q1[numbers[1]] + localMatrix[i, 2] * q1[numbers[2]]);

                        // (dt + dt0) / (dt * dt0) * M
                        temp = (dt + dt0) / (dt * dt0);
                        localMatrix[i, 0] *= temp;
                        localMatrix[i, 1] *= temp;
                        localMatrix[i, 2] *= temp;
                    }

                    // adding G to local A
                    for (i = 0; i < 3; i++)
                    {
                        for (j = 0; j < 3; j++)
                        {
                            localMatrix[i, j] += lambda * detD / 2.0 *
                                                 (D_1[i, 1] * D_1[j, 1] + D_1[i, 2] * D_1[j, 2]);
                        }
                    }
                    // Gij = lambda * |detD| / 2.0 * (a(i,1) * a(j,1) + a(i,2) * a(j,2))
                    // Aij = Gij + Mij

                    // local B
                    localB[0] += (2.0 * localFunction(v1[0], v1[1], timeValue) + localFunction(v2[0], v2[1], timeValue) + localFunction(v3[0], v3[1], timeValue)) / 24.0 * detD;
                    localB[1] += (localFunction(v1[0], v1[1], timeValue) + 2.0 * localFunction(v2[0], v2[1], timeValue) + localFunction(v3[0], v3[1], timeValue)) / 24.0 * detD;
                    localB[2] += (localFunction(v1[0], v1[1], timeValue) + localFunction(v2[0], v2[1], timeValue) + 2.0 * localFunction(v3[0], v3[1], timeValue)) / 24.0 * detD;

                    #region Second and third type boundary conditions
                    for (m = 0; m < condSize; m++)
                    {
                        if (conditions[m].Type == BoundaryConditionType.Second)
                        {
                            for (i = 0; i < 2; i++)
                            {
                                for (j = i + 1; j < 3; j++)
                                {
                                    if (conditions[m].CheckEdge(numbers[i], numbers[j]))
                                    {
                                        v1            = vertexes[numbers[i]];
                                        v2            = vertexes[numbers[j]];
                                        localFunction = conditions[m].Value;

                                        temp   = localFunction(v1[0], v1[1], timeValue);
                                        gamma  = localFunction(v2[0], v2[1], timeValue);
                                        lambda = 2.0 * temp + gamma;
                                        detD   = temp + 2.0 * gamma;
                                        temp   = Math.Sqrt((v2[0] - v1[0]) * (v2[0] - v1[0]) + (v2[1] - v1[1]) * (v2[1] - v1[1])) / 6.0;

                                        localB[i] += temp * lambda;
                                        localB[j] += temp * detD;
                                    }
                                }
                            }
                        }
                        else if (conditions[m].Type == BoundaryConditionType.Third)
                        {
                            for (i = 0; i < 2; i++)
                            {
                                for (j = i + 1; j < 3; j++)
                                {
                                    if (conditions[m].CheckEdge(numbers[i], numbers[j]))
                                    {
                                        v1            = vertexes[numbers[i]];
                                        v2            = vertexes[numbers[j]];
                                        localFunction = conditions[m].Value;

                                        temp   = localFunction(v1[0], v1[1], timeValue);
                                        gamma  = localFunction(v2[0], v2[1], timeValue);
                                        lambda = 2.0 * temp + gamma;
                                        detD   = temp + 2.0 * gamma;
                                        temp   = Math.Sqrt((v2[0] - v1[0]) * (v2[0] - v1[0]) + (v2[1] - v1[1]) * (v2[1] - v1[1])) * conditions[m].Beta / 6.0;

                                        localMatrix[i, i] += temp * 2.0;
                                        localMatrix[i, j] += temp;
                                        localMatrix[j, i] += temp;
                                        localMatrix[j, j] += temp * 2.0;

                                        localB[i] += temp * lambda;
                                        localB[j] += temp * detD;
                                    }
                                }
                            }
                        }
                    }
                    #endregion

                    // adding diagonal to global matrix
                    for (i = 0; i < 3; i++)
                    {
                        di[numbers[i]] += localMatrix[i, i];
                    }

                    for (i = 1; i < 3; i++)
                    {
                        m = ig[numbers[i]];
                        for (j = 0; j < i; j++)
                        {
                            for (s = m; s < ig[numbers[i] + 1]; s++)
                            {
                                if (jg[s] == numbers[j])
                                {
                                    gg[s] += localMatrix[i, j];
                                    m++;
                                    break;
                                }
                            }
                        }
                    }

                    // adding local B to global B
                    for (i = 0; i < 3; i++)
                    {
                        globalB[numbers[i]] += localB[i];
                    }
                }

                // First type boundary conditions
                foreach (BoundaryCondition condition in conditions)
                {
                    if (condition.Type == BoundaryConditionType.First)
                    {
                        curBound      = condition.Vertexes;
                        localFunction = condition.Value;
                        for (k = 0; k < curBound.Length; k++)
                        {
                            i       = curBound[k];
                            curVert = vertexes[i];

                            di[i]      = 1;
                            globalB[i] = localFunction(curVert[0], curVert[1], timeValue);

                            for (s = ig[i]; s < ig[i + 1]; s++)
                            {
                                globalB[jg[s]] -= gg[s] * globalB[i];
                                gg[s]           = 0;
                            }

                            for (s = i + 1; s < vertexesCount; s++)
                            {
                                for (j = ig[s]; j < ig[s + 1] && jg[j] <= i; j++)
                                {
                                    if (jg[j] == i)
                                    {
                                        globalB[s] -= gg[j] * globalB[i];
                                        gg[j]       = 0;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                SoLESolver.SolveCGM_LLT(globalMatrix, globalB, coeffs[t]);
            }
        }
예제 #3
0
파일: Problem.cs 프로젝트: Hrenaki/2D-FEM
 public void Solve()
 {
     createGlobalMatrixAndGlobalVector();
     SoLESolver.SolveCGM_LLT(new SymmSparseMatrix(vertexesCount, ig, jg, di, gg), globalB, coeffs);
 }