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; }
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]); } }
public void Solve() { createGlobalMatrixAndGlobalVector(); SoLESolver.SolveCGM_LLT(new SymmSparseMatrix(vertexesCount, ig, jg, di, gg), globalB, coeffs); }