Бонусное задание (часть 3)
Требуемые условия завершения
Открыто с: воскресенье, 21 апреля 2024, 00:00
Срок сдачи: воскресенье, 28 апреля 2024, 00:00
- Изменим отображение узловых перемещений. Добавим в класс model новый метод
std::map<nodal_displacement, double> get_the_nodal_solution( const std::map<nodal_displacement, double>& constraints, const std::map<nodal_displacement, double>& loads) const;
Если реализовать этот метод правильно, код видаconst auto solution = m.get_the_nodal_solution(constraints, loads); for (auto x : solution) { std::cout << x.first << " " << x.second << std::endl; }
Будет выводить на консоль следующееx = 0, y = 3, ux: 0 x = 0, y = 3, uy: 0 x = 0, y = 0, ux: 0 x = 0, y = 0, uy: 0 x = 0, y = -3, ux: 0 x = 0, y = -3, uy: 0 x = 4, y = 0, ux: 0 x = 4, y = 0, uy: 0.0003472221
(теперь стало понятно, что к чему и каким узловым перемещениям соответствуют эти числа). Чтобы добиться такого эффекта, следует также перегрузить операцию вывода в поток для классов nodal_displacement и node. -
Теперь найдём реакции в опорах. Для этого следует добавить в класс model метод
/// <summary> /// отыскание реакций в опорах /// </summary> /// <param name="constraints"> набор закреплений </param> /// <param name="solution"> решение (результат solve) </param> /// <returns> реакции в опораз </returns> std::map<nodal_displacement, double> nodal_reactions( const std::map<nodal_displacement, double>& constraints, const std::map<nodal_displacement, double>& loads, const std::vector<double>& solution) const;
Алгоритм его работы следующий:- для того, чтобы найти силы, действующие в узлах, умножаем глобальную матрицы жёсткости на вектор solution;
- для того, чтобы найти реакцию в точке закрепления, создаём контейнер std::map<nodal_displacement, double> result. Затем в цикле по constraints записываем в контейнер, ключами в которых являются ключи constraints, а значениями - силы, действующие в узлах в направлении перемещений, соответствующих ключам;
- далее следует учесть нагрузки, действующие в направлении перемещений, присутствующих в контейнере constraints. Для этого проходимся в цикле по контейнеру loads, и если ключевое значение из него есть в контейнере result, вычитаем значение из loads из значения в result
const auto solution = m.solve(constraints, loads); const auto reactions = m.nodal_reactions(constraints, loads, solution); for (auto& reaction : reactions) { std::cout << reaction.first << " " << reaction.second << std::endl; }
выводит такой результат:x = 0, y = 3, ux: 666.667 x = 0, y = 3, uy: 500 x = 0, y = 0, ux: 0 x = 0, y = 0, uy: 0 x = 0, y = -3, ux: -666.667 x = 0, y = -3, uy: 500
(таким образом, мы видим координаты узлов с закреплениями, а также величины усилий в направлении перемещений ux и uy) - Теперь найдём усилия в стержнях Чтобы сделать это:
-
добавляем в класс element чисто абстрактный метод
/// <summary> /// усилия в элементе /// </summary> /// <param name="displacements"> перемещения в узлах </param> /// <returns> вектор усилий </returns> virtual std::vector<double> get_the_element_solution( const std::vector<double>&) const = 0;
который принимает вектор узловых перемещений (в порядке, соответствующем nodal_displacements()) и возвращает вектор усилий в элементе. При перегрузке метода в linear_element следует вектор узловых перемещений, умножить его на матрицу поворота, а затем на матрицу жёсткости в локальной системе координат. Чтобы всё это сделать, придётся добавить новые поля и (возможно) методы в linear_element. - Добавит в класс model метод
/// <summary> /// усилия в элементе /// </summary> /// <param name="nodal_solution"> перемещение в узлах </param> /// <param name="el"> элемент </param> /// <returns> вектор усилий </returns> std::vector<double> get_the_element_solution( const std::map<nodal_displacement, double>& nodal_solution, const element* el) const;
Метод формирует вектор узловых перемещений, соответствующий элементу, затем находит вектор усилий с помощью метода get_the_element_solution класса element
const auto nodal_solution = m.get_the_nodal_solution(solution); const auto elements = m.get_elements(); for (size_t i = 0; i < elements.size(); i++) { std::cout << i + 1 << ". "; const auto element_solution = m.get_the_element_solution(nodal_solution, elements[i]); for (auto x : element_solution) { std::cout << x << " "; } std::cout << std::endl; }
выводит следующее1. 833.333 0 -833.333 0 2. 0 0 0 0 3. -833.333 0 833.333 0
(мы видим номер элемента и действующие силы) -
добавляем в класс element чисто абстрактный метод
-
Теперь решим задачу из первой главы методички Наседкина. Код из функции main для решения задачи имеет вид:
// создаём узлы node n1 = { 1, 0.0, 0.0 }; node n2 = { 2, 2.0, 0.0 }; node n3 = { 3, 4.0, 0.0 }; node n4 = { 4, 2.5, sqrt(3.0) / 2 }; node n5 = { 5, 1.0, sqrt(3.0) }; // создаём элементы element* el1 = new linear_element(n1, n2, 2e11, 0.1e-3); element* el2 = new linear_element(n2, n3, 2e11, 0.1e-3); element* el3 = new linear_element(n3, n4, 2e11, 0.1e-3); element* el4 = new linear_element(n4, n5, 2e11, 0.1e-3); element* el5 = new linear_element(n5, n1, 2e11, 0.1e-3); element* el6 = new linear_element(n5, n2, 2e11, 0.1e-3); element* el7 = new linear_element(n2, n4, 2e11, 0.1e-3); // создаём ферму model m = { {el1, el2, el3, el4, el5, el6, el7 } }; // создаём закрепления std::map<nodal_displacement, double> constraints = { {{n1, uy}, 0}, {{n3, uy}, 0}, {{n3, ux}, 0}, }; // создаём нагрузки std::map<nodal_displacement, double> loads = { {{n1, uy}, -1000}, {{n3, uy}, -1000}, {{n4, uy}, -2000}, {{n5, uy}, -2000} }; // решаем задачу const auto solution = m.solve(constraints, loads); // ищем реакции опор std::cout << "реакции опор" << std::endl; const auto reactions = m.nodal_reactions(constraints, loads, solution); for (auto& reaction : reactions) { std::cout << reaction.first << " " << reaction.second << std::endl; } // ищем усилия в стержнях std::cout << "усилия в стержнях" << std::endl; const auto nodal_solution = m.get_the_nodal_solution(solution); const auto elements = m.get_elements(); for (size_t i = 0; i < elements.size(); i++) { std::cout << i + 1 << ". "; const auto element_solution = m.get_the_element_solution(nodal_solution, elements[i]); std::cout << element_solution.front() << std::endl; }
Вывод следующий:реакции опор x = 0, y = 0, uy: 3250 x = 4, y = 0, ux: 9.09495e-13 x = 4, y = 0, uy: 2750 усилия в стержнях 1. 1299.04 2. 3031.09 3. -3500 4. -2500 5. -2598.08 6. 1732.05 7. -1732.05
- Теперь с помощью написанной программы решите свой вариант лабораторной работы №1