Files
MemMAPR-MKE/Solver.cpp

152 lines
5.1 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, double _D, int _N, int _l, int _u) {
A = _A, B = _B, C = _C, D = _D, 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) {
int mat_dim = 1 + N * 3;
Eigen::MatrixXd Amat(mat_dim, mat_dim);
Eigen::VectorXd b(mat_dim);
Amat.setZero();
b.setZero();
// Assemble matrix
for (int i = 0; i < mat_dim - 3; i += 3) {
Amat(i, i + 0) -= A * 37.0 / 10.0 / dx;
Amat(i, i + 1) -= A * (-189.0) / 40.0 / dx;
Amat(i, i + 2) -= A * 27.0 / 20.0 / dx;
Amat(i, i + 3) -= A * (-13.0) / 40.0 / dx;
Amat(i + 1, i + 0) -= A * (-189.0) / 40.0 / dx;
Amat(i + 1, i + 1) -= A * 54.0 / 5.0 / dx;
Amat(i + 1, i + 2) -= A * (-297.0) / 40.0 / dx;
Amat(i + 1, i + 3) -= A * 27.0 / 20.0 / dx;
Amat(i + 2, i + 0) -= A * 27.0 / 20.0 / dx;
Amat(i + 2, i + 1) -= A * (-297.0) / 40.0 / dx;
Amat(i + 2, i + 2) -= A * 54.0 / 5.0 / dx;
Amat(i + 2, i + 3) -= A * (-189.0) / 40.0 / dx;
Amat(i + 3, i + 0) -= A * (-13.0) / 40.0 / dx;
Amat(i + 3, i + 1) -= A * 27.0 / 20.0 / dx;
Amat(i + 3, i + 2) -= A * (-189.0) / 40.0 / dx;
Amat(i + 3, i + 3) -= A * 37.0 / 10.0 / dx;
Amat(i + 0, i + 0) += B * (-1.0) / 2.0;
Amat(i + 0, i + 1) += B * 57.0 / 80.0;
Amat(i + 0, i + 2) += B * (-3.0) / 10.0;
Amat(i + 0, i + 3) += B * 7.0 / 80.0;
Amat(i + 1, i + 0) += B * (-57.0) / 80.0;
Amat(i + 1, i + 2) += B * 81.0 / 80.0;
Amat(i + 1, i + 3) += B * (-3.0) / 10;
Amat(i + 2, i + 0) += B * 3.0 / 10.0;
Amat(i + 2, i + 1) += B * (-81.0) / 80.0;
Amat(i + 2, i + 3) += B * 57.0 / 80.0;
Amat(i + 3, i + 0) += B * (-7.0) / 80.0;
Amat(i + 3, i + 1) += B * 3.0 / 10.0;
Amat(i + 3, i + 2) += B * (-57.0) / 80.0;
Amat(i + 3, i + 3) += B * 1.0 / 2.0;
}
// Assembdxe vector
for (int i = 0; i < mat_dim - 3; i += 3) {
b(i) -= D * dx / 8.0;
b(i + 1) -= D * 3.0 * dx / 8.0;
b(i + 2) -= D * 3.0 * dx / 8.0;
b(i + 3) -= D * dx / 8.0;
}
Amat.row(0).setZero();
Amat(0, 0) = dx / 3.0 + 1;
Amat(0, 1) = -1;
b(0) = 0;
Amat.row(mat_dim - 1).setZero();
Amat(mat_dim - 1, mat_dim - 1) = 1;
b(mat_dim - 1) = val2;
// Решение системы
VectorXd solution = Amat.colPivHouseholderQr().solve(b);
std::cout << "\nSolution:" << std::endl;
std::cout << solution << std::endl;
std::ofstream file("matrix_cubic.txt");
for (int i = 0; i < solution.size(); i++) {
file << solution(i) << ' ';
}
file << std::endl;
}