Files
MemMAPR-MKE/Solver.cpp
ParkSuMin e53cef771a Complete cubic solver
Изменены коэффициенты в локальных матрицах жёсткости. Значения int приведены к double формату
2025-09-12 23:23:26 +03:00

167 lines
6.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Header.h"
#include <Eigen/Dense>
using namespace Eigen;
Solver::Solver(double _A, double _B, double _C, int _N, int _l, int _u) {
A = _A, B = _B, C = _C, N = _N;
upper = _u, lower = _l;
L = upper - lower;
dx = L / N;
}
void Solver::Execute_Linear(double val1, double val2) {
MatrixXd local = MatrixXd::Zero(2, 2);
local(0, 0) = A / dx - B / 2.;
local(0, 1) = -A / dx + B / 2.;
local(1, 0) = -A / dx - B / 2.;
local(1, 1) = A / dx + B / 2.;
std::cout << "Local matrix:\n" << local << std::endl;
VectorXd local_load(2);
local_load(0) = C * dx / 2;
local_load(1) = C * dx / 2;
// Ансаблированные матрицы и вектор
MatrixXd ansamb = MatrixXd::Zero(N + 1, N + 1);
VectorXd global_load = VectorXd::Zero(N + 1);
// Ансамблирование для каждого конечного элемента
for (int elem = 0; elem < N; ++elem) {
int node_i = elem;
int node_j = elem + 1;
// Матрица жесткости
ansamb(node_i, node_i) += local(0, 0);
ansamb(node_i, node_j) += local(0, 1);
ansamb(node_j, node_i) += local(1, 0);
ansamb(node_j, node_j) += local(1, 1);
// Вектор нагрузки
global_load(node_i) += local_load(0);
global_load(node_j) += local_load(1);
}
std::cout << "Before:" << std::endl;
std::cout << "Ansamb matrix:\n" << ansamb << std::endl;
std::cout << "Ansamb load vector:\n" << global_load << std::endl;
// ГУ 1-го рода
double u_left = val1; // u(1) = 5
double u_right = val2; // u(6) = 15
// Обнуляем первую строку и столбец матрицы, устанавливаем диагональ = 1
ansamb.row(0).setZero();
ansamb.col(0).setZero();
ansamb(0, 0) = 1.0;
global_load(0) = u_left;
// Обнуляем последнюю строку и столбец матрицы, устанавливаем диагональ = 1
ansamb.row(N).setZero();
ansamb.col(N).setZero();
ansamb(N, N) = 1.0;
global_load(N) = u_right;
std::cout << "\nAfter:" << std::endl;
std::cout << "Modified matrix:\n" << ansamb << std::endl;
std::cout << "Modified load vector:\n" << global_load << std::endl;
VectorXd solution = ansamb.fullPivLu().solve(global_load);
std::cout << "\nSolution:" << std::endl;
std::cout << solution << std::endl;
std::ofstream file("matrix_2.txt");
for (int i = 0; i < N + 1; i++) {
file << solution(i) << ' ';
}
file << std::endl;
}
void Solver::Execute_Cubic(double val1, double val2) {
// Локальная матрица жесткости (4x4)
MatrixXd local = MatrixXd::Zero(4, 4);
local(0, 0) = -37. * A / (10 * dx) - B / 2.;
local(0, 1) = 189. * A / (40 * dx) + 57. * B / 80.;
local(0, 2) = -27. * A / (20 * dx) - 3. * B / 10.;
local(0, 3) = 13. * A / (40. * dx) + 7. * B / 10.;
local(1, 0) = 189. * A / (40 * dx) - 57. * B / 80.;
local(1, 1) = -54. * A / (5 * dx);
local(1, 2) = 297. * A / (40. * dx) + 81. * B / 80.;
local(1, 3) = -27 * A / (20. * dx) - 3. * B / 10.;
local(2, 0) = -27. * A / (20. * dx) + 3. * B / 10.;
local(2, 1) = 297. * A / (40. * dx) - 81. * B / 80.;
local(2, 2) = -54. * A / (5. * dx);
local(2, 3) = 189. * A / (40. * dx) + 57. * B / 80.;
local(3, 0) = 13. * A / (40. * dx) - 7. * B / 80.;
local(3, 1) = -27. * A / (20. * dx) + 3. * B / 10.;
local(3, 2) = 189. * A / (40. * dx) - 57. * B / 80.;
local(3, 3) = -37. * A / (10. * dx) + B / 2.;
// Локальный вектор нагрузки (4x1)
VectorXd local_load(4);
local_load(0) = -C * dx / 8.;
local_load(1) = -3. * C * dx / 8.;
local_load(2) = -3. * C * dx / 8.;
local_load(3) = -C * dx / 8.;
std::cout << "Local matrix:\n" << local << std::endl;
std::cout << "Local load vector:\n" << local_load << std::endl;
// Размер глобальной системы: для кубических элементов (4 узла на элемент, перекрытие по 2 узла)
int ndof = 2 * N + 2;
MatrixXd ansamb = MatrixXd::Zero(ndof, ndof);
VectorXd global_load = VectorXd::Zero(ndof);
// АНСАМБЛИРОВАНИЕ
for (int elem = 0; elem < N; ++elem) {
int node_start = 2 * elem; // Начальный индекс для текущего элемента
// Добавляем локальную матрицу
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
ansamb(node_start + i, node_start + j) += local(i, j);
}
}
// Добавляем локальный вектор нагрузки
for (int i = 0; i < 4; ++i) {
global_load(node_start + i) += local_load(i);
}
}
std::cout << "Before boundary conditions:" << std::endl;
std::cout << "Ansamb matrix:\n" << ansamb << std::endl;
std::cout << "Ansamb load vector:\n" << global_load << std::endl;
// ГРАНИЧНЫЕ УСЛОВИЯ
double u_left = val1; // u(1) = 5
double u_right = val2; // u(6) = 15
ansamb.row(0).setZero();
ansamb.col(0).setZero();
ansamb(0, 0) = 1.0;
global_load(0) = u_left;
ansamb.row(ndof - 1).setZero();
ansamb.col(ndof - 1).setZero();
ansamb(ndof - 1, ndof - 1) = 1.0;
global_load(ndof - 1) = u_right;
std::cout << "\nAfter boundary conditions:" << std::endl;
std::cout << "Modified matrix:\n" << ansamb << std::endl;
std::cout << "Modified load vector:\n" << global_load << std::endl;
// Решение системы
VectorXd solution = ansamb.fullPivLu().solve(global_load);
std::cout << "\nSolution:" << std::endl;
std::cout << solution << std::endl;
// Сохранение результатов (берем только значения функции в узлах, шаг 2)
std::ofstream file("matrix_cubic.txt");
for (int i = 0; i < ndof; i += 2) {
file << solution(i) << ' ';
}
file << std::endl;
}