#include <iostream>
#include <vector>
#include <cmath>
#include <cassert>
using namespace std;
// Estructura para representar un nodo
struct Nodo {
double x, y; // Coordenadas del nodo
double fx, fy; // Fuerzas aplicadas en el nodo (si las hay)
bool fijo_x, fijo_y; // Condiciones de frontera (si el nodo es fijo en X o Y)
};
// Estructura para representar una barra entre dos nodos
struct Barra {
int nodo1, nodo2; // Índices de los nodos conectados
double longitud; // Longitud de la barra
double area; // Área de la sección transversal
double E; // Módulo de elasticidad
};
// Función para ingresar los nodos
void ingresarNodos(vector<Nodo>& nodos, int num_nodos) {
for (int i = 0; i < num_nodos; ++i) {
Nodo nodo;
cout << "Ingrese las coordenadas del nodo " << i + 1 << " (x, y): ";
cin >> nodo.x >> nodo.y;
cout << "Ingrese las fuerzas aplicadas en el nodo " << i + 1 << " (fx, fy): ";
cin >> nodo.fx >> nodo.fy;
// Condiciones de frontera
if (i == 0) { // Nodo 1 fijo en X y Y
nodo.fijo_x = true;
nodo.fijo_y = true;
} else if (i == 1) { // Nodo 2 fijo solo en Y
nodo.fijo_x = false;
nodo.fijo_y = true;
} else { // Nodo 3 sin restricciones
nodo.fijo_x = false;
nodo.fijo_y = false;
}
nodos.push_back(nodo);
}
}
// Función para ingresar las barras
void ingresarBarras(vector<Barra>& barras, int num_barras) {
for (int i = 0; i < num_barras; ++i) {
Barra barra;
cout << "Ingrese los nodos conectados por la barra " << i + 1 << " (nodo1, nodo2): ";
cin >> barra.nodo1 >> barra.nodo2;
cout << "Ingrese la longitud de la barra " << i + 1 << ": ";
cin >> barra.longitud;
cout << "Ingrese el área de la barra " << i + 1 << ": ";
cin >> barra.area;
cout << "Ingrese el módulo de elasticidad de la barra " << i + 1 << ": ";
cin >> barra.E;
barras.push_back(barra);
}
}
// Función para calcular la rigidez de una barra (en 2D)
vector<vector<double>> rigidezBarra(const Barra& barra, const Nodo& n1, const Nodo& n2) {
double L = barra.longitud;
double A = barra.area;
double E = barra.E;
// Cálculo de la matriz de rigidez local de la barra
double c = (n2.x - n1.x) / L; // Coseno de la dirección de la barra
double s = (n2.y - n1.y) / L; // Seno de la dirección de la barra
vector<vector<double>> K(4, vector<double>(4, 0)); // Matriz de rigidez local (4x4)
// Matriz de rigidez local (considerando 2D)
double k_local = (A * E) / L;
K[0][0] = k_local * c * c;
K[0][1] = k_local * c * s;
K[1][0] = k_local * c * s;
K[1][1] = k_local * s * s;
K[2][2] = k_local * c * c;
K[2][3] = k_local * c * s;
K[3][2] = k_local * c * s;
K[3][3] = k_local * s * s;
return K;
}
// Función para ensamblar la matriz de rigidez global
vector<vector<double>> ensamblarRigidezGlobal(const vector<Barra>& barras, const vector<Nodo>& nodos) {
int n = nodos.size();
vector<vector<double>> K_global(2 * n, vector<double>(2 * n, 0)); // Matriz de rigidez global (2n x 2n)
// Ensamblaje de la matriz de rigidez global
for (const Barra& barra : barras) {
Nodo n1 = nodos[barra.nodo1];
Nodo n2 = nodos[barra.nodo2];
// Obtener la matriz de rigidez local
vector<vector<double>> K_local = rigidezBarra(barra, n1, n2);
// Incluir K_local en la matriz de rigidez global
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
K_global[2 * barra.nodo1 + i / 2][2 * barra.nodo1 + j / 2] += K_local[i][j];
}
}
}
return K_global;
}
// Función para aplicar condiciones de frontera (restringir desplazamientos)
void aplicarCondicionesFrontera(vector<vector<double>>& K, vector<double>& F, const vector<Nodo>& nodos) {
int n = nodos.size();
for (int i = 0; i < n; i++) {
if (nodos[i].fijo_x) {
// Fijar el desplazamiento en X (columna correspondiente)
for (int j = 0; j < 2 * n; j++) {
K[2 * i][j] = 0;
K[j][2 * i] = 0;
}
K[2 * i][2 * i] = 1;
F[2 * i] = 0; // Fuerza en X es 0
}
if (nodos[i].fijo_y) {
// Fijar el desplazamiento en Y (columna correspondiente)
for (int j = 0; j < 2 * n; j++) {
K[2 * i + 1][j] = 0;
K[j][2 * i + 1] = 0;
}
K[2 * i + 1][2 * i + 1] = 1;
F[2 * i + 1] = 0; // Fuerza en Y es 0
}
}
}
// Función para resolver el sistema de ecuaciones (desplazamientos)
vector<double> resolverDesplazamientos(vector<vector<double>>& K, vector<double>& F) {
int n = K.size();
// Resolver el sistema Kx = F usando eliminación de Gauss
vector<double> X(n, 0); // Desplazamientos inicializados a 0
vector<vector<double>> A = K;
// Eliminación de Gauss
for (int i = 0; i < n; i++) {
// Buscar el máximo en la columna para estabilidad
int max_row = i;
for (int k = i + 1; k < n; k++) {
if (abs(A[k][i]) > abs(A[max_row][i])) {
max_row = k;
}
}
// Intercambiar filas
swap(A[i], A[max_row]);
swap(F[i], F[max_row]);
// Hacer cero las entradas debajo de la diagonal
for (int j = i + 1; j < n; j++) {
double factor = A[j][i] / A[i][i];
for (int k = i; k < n; k++) {
A[j][k] -= factor * A[i][k];
}
F[j] -= factor * F[i];
}
}
// Resolución hacia atrás
for (int i = n - 1; i >= 0; i--) {
X[i] = F[i] / A[i][i];
for (int j = i - 1; j >= 0; j--) {
F[j] -= A[j][i] * X[i];
}
}
return X;
}
// Función para calcular las fuerzas axiales en las barras
vector<double> calcularFuerzasAxiales(const vector<Barra>& barras, const vector<double>& desplazamientos, const vector<Nodo>& nodos) {
vector<double> fuerzas_axiales;
for (const Barra& barra : barras) {
Nodo n1 = nodos[barra.nodo1];
Nodo n2 = nodos[barra.nodo2];
// Desplazamientos en los nodos 1 y 2
double u1 = desplazamientos[2 * barra.nodo1]; // Desplazamiento en X del nodo 1
double v1 = desplazamientos[2 * barra.nodo1 + 1]; // Desplazamiento en Y del nodo 1
double u2 = desplazamientos[2 * barra.nodo2]; // Desplazamiento en X del nodo 2
double v2 = desplazamientos[2 * barra.nodo2 + 1]; // Desplazamiento en Y del nodo 2
// Longitud de la barra
double L = barra.longitud;
// Cálculo de las fuerzas axiales
double c = (n2.x - n1.x) / L;
double s = (n2.y - n1.y) / L;
// Fuerza axial
double fuerza_axial = barra.E * barra.area / L * ( (u2 - u1) * c + (v2 - v1) * s );
fuerzas_axiales.push_back(fuerza_axial);
}
return fuerzas_axiales;
}
int main() {
int num_nodos = 3;
int num_barras = 3;
vector<Nodo> nodos;
vector<Barra> barras;
// Ingresar los nodos y las barras
ingresarNodos(nodos, num_nodos);
ingresarBarras(barras, num_barras);
// Ensamblar la matriz de rigidez global
vector<vector<double>> K_global = ensamblarRigidezGlobal(barras, nodos);
// Definir el vector de fuerzas (aplicadas en los nodos)
vector<double> F(2 * nodos.size(), 0);
F[5] = nodos[2].fy; // Fuerza en el nodo 3 (Y)
// Aplicar condiciones de frontera
aplicarCondicionesFrontera(K_global, F, nodos);
// Resolver el sistema de ecuaciones para obtener los desplazamientos
vector<double> desplazamientos = resolverDesplazamientos(K_global, F);
// Mostrar los resultados de los desplazamientos
for (int i = 0; i < desplazamientos.size(); ++i) {
cout << "Desplazamiento en nodo " << i / 2 << " (componente " << i % 2 << "): "
<< desplazamientos[i] << " m" << endl;
}
// Calcular las fuerzas axiales en las barras
vector<double> fuerzas_axiales = calcularFuerzasAxiales(barras, desplazamientos, nodos);
// Mostrar las fuerzas axiales
for (int i = 0; i < fuerzas_axiales.size(); ++i) {
cout << "Fuerza axial en barra " << i + 1 << ": "
<< fuerzas_axiales[i] << " N" << endl;
}
return 0;
}