项目作者: ppizarror

项目描述 :
Finite element structural analysis using GPU+CUDA
高级语言: C++
项目地址: git://github.com/ppizarror/FNELEM-GPU.git
创建时间: 2018-11-01T12:58:47Z
项目社区:https://github.com/ppizarror/FNELEM-GPU

开源协议:MIT License

下载


FNELEM-GPU

Simple finite elements matrix structural analysis using GPU. Supports 2D planar membrane/shell.

Requirements

C++ STANDARD 14 and CUDA. No other libraries are needed.

Import

To fully use this library, you must include the following files:

  1. #include "fnelem/math/fematrix.cpp"
  2. #include "fnelem/math/fematrix_utils.cpp"
  3. #include "fnelem/math/matrix_inversion_cpu.cpp"
  4. #include "fnelem/math/matrix_inversion_cuda.cu"
  5. #include "fnelem/analysis/static_analysis.cpp"
  6. #include "fnelem/model/base/model.cpp"
  7. #include "fnelem/model/base/model_component.cpp"
  8. #include "fnelem/model/elements/element.cpp"
  9. #include "fnelem/model/elements/membrane.cpp"
  10. #include "fnelem/model/loads/load.cpp"
  11. #include "fnelem/model/loads/load_membrane_distributed.cpp"
  12. #include "fnelem/model/loads/load_node.cpp"
  13. #include "fnelem/model/loads/load_pattern.cpp"
  14. #include "fnelem/model/loads/load_pattern_constant.cpp"
  15. #include "fnelem/model/nodes/node.cpp"
  16. #include "fnelem/model/restraints/restraint.cpp"
  17. #include "fnelem/model/restraints/restraint_node.cpp"

Usage

Model

The model class is the base object for defining a problem. It needs the number of degrees of freedom, the dimension (actually, only 2D is supported), the nodes, elements, restraints, loads, and load patterns.

  1. Model *model = new Model(dimension, number_degrees_of_freedom);
  2. // Define nodes
  3. model->add_nodes(nodes);
  4. model->add_elements(elements);
  5. model->add_restraints(restraints);
  6. model->add_load_patterns(load_pattern);

Nodes, elements, restraints, and load_pattern are std::vector objects containing library Objects.

StaticAnalysis

The StaticAnalysis class performs the primary static analysis method. Using the model definition, it creates the structure stiffness matrix, and then, using K*u = F, it solves the displacement vector of the nodes.

  1. StaticAnalysis *analysis = new StaticAnalysis(model);
  2. analysis->analyze(use_gpu);

If use_gpu is true, GPU performs the primary matrix inversion. After the analysis, the model can save the results into a file. That file contains the main structure elements: nodes, shells, reactions, and internal forces of the elements.

  1. model->save_results("file.txt");

Example of the output:

  1. FNELEM-GPU - Finite element structural analysis using CUDA and GPU.
  2. v0.2.0 (21/12/2018) @ ppizarror
  3. --------------------------------------------------------------------
  4. Input model properties:
  5. --------------------------------------------------------------------
  6. Nodes:
  7. Node count: 6
  8. Node N1: 0.000000 0.000000
  9. ...
  10. Elements:
  11. Element count: 2
  12. Membrane MEM1:
  13. Width (2b): 2
  14. Height (2h): 2
  15. Thickness: 1
  16. Elastic mod: 2000
  17. Poisson mod: 0.2
  18. Element nodes: N1, N3, N4, N2
  19. ...
  20. --------------------------------------------------------------------
  21. Analysis results:
  22. --------------------------------------------------------------------
  23. Node displacements:
  24. Node N1: 0.000000 0.000000
  25. ...
  26. Node reactions:
  27. Node N1: 369.158879 500.000000
  28. ...
  29. Element stresses:
  30. Membrane MEM1:
  31. Node N1 (-b, -h): 369.159, 500
  32. Node N3 (+b, -h): 130.841, 0
  33. Node N4 (+b, +h): -500, -500
  34. Node N2 (-b, +h): 0, 0
  35. Stress MEM1 [GLX GLY X Y SIGMAX SIGMAY SIGMAXY DISPLX DISPLY]
  36. 0 0 -1 -1 -44.3925 -221.963 -193.9250 0
  37. ...

Node

The node class must be defined using the global coordinates. Nodes are used by the elements.

  1. std::vector<Node *> *nodes = new std::vector<Node *>();
  2. nodes->push_back(new Node(node_tag, coordinate_x, coorinate_y));
  3. nodes->push_back(new Node(node_tag, coordinate_x, coordinate_y, coordinate_z));

Element

The membrane shell must be defined using four nodes, the elastic and Poisson modulus, and the thickness.

  1. std::vector<Element *> *elements = new std::vector<Element *>();
  2. elements->push_back(new Membrane(membrane_tag, node1, node2, node3, node4, E, poisson, thickness));

Restraints

The restraint class must be used when a node cannot move in any direction.

  1. std::vector<Restraint *> *restraints = new std::vector<Restraint *>();
  2. RestraintNode *r = new RestraintNode(restraint_tag, node);
  3. r1->add_dofid(index);
  4. r1->add_all(); // This method adds all degrees of freedom
  5. restraints->push_back(r);

Load

LoadNode

NodeLoad is a load applied to a node; it needs the node reference and a load vector. In FNELEM-GPU matrices and vectors are defined using FEMatrix class. That class provides the following main methods:

  • Add
  • Subtract
  • Multiply
  • Inverse (Using CPU and GPU)
  • Determinant
  • max(), min()
  • clone()

To define a vector:

  1. FEMatrix *vector = FEMatrix_vector(size);
  2. vector->set(index, value);
  3. vector->get(index);

To define a matrix:

  1. FEMatrix *matrix = FEMatrix_vector(n, m);
  2. matrix->set(i, j, value);
  3. matrix->get(i, j);

Then, node load is defined by:

  1. // Create load vector
  2. std::vector<Load *> *loads = new std::vector<Load *>();
  3. // Create LoadNode
  4. FEMatrix *load = FEMatrix_vector(size);
  5. load->set(index, value);
  6. ...
  7. loads->push_back(new LoadNode(load_tag, node, load));

LoadMembraneDistributed

This class can apply a distributed load. It needs the membrane, the node position (1, 2, 3, 4)


Node definiton shell
  1. std::vector<Load *> *loads = new std::vector<Load *>();
  2. loads->push_back(new LoadMembraneDistributed(load_tag, membrane, position_initial,
  3. position_final, load_at_initial, distance_from_initial, load_at_final, distance_from_initial));

Load pattern

The load pattern must be used to apply the loads to the model. Only the constant load pattern is defined.

  1. std::vector<LoadPattern *> *loadpattern = new std::vector<LoadPattern *>();
  2. loadpattern->push_back(new LoadPatternConstant(load_tag, loads));

Example

The following code defines a simple bridge composed of N membranes under a distributed load of 100kN/m. The membranes are the same: 100cm height, 100cm width, 15cm thickness, elastic modulus of 300000kN/cm^2, Poisson modulus of 0.2. This example can also be found in test/analysis/test_static_analysis.h.


Bridge example
  1. int N = 3; // Number of membranes
  2. int b = 100; // Pier width
  3. int h = 100; // Pier height
  4. // N = 2
  5. // 4 ------ 5 ------ 6
  6. // | | |
  7. // h | (1) | (2) | ......
  8. // | | |
  9. // 1 ------ 2 ------ 3 .....
  10. // ^ b ^
  11. //
  12. // N = 3
  13. // 4 ------ 5 ------ 6 ------- 8
  14. // | | | |
  15. // h | (1) | (2) | (3) |
  16. // | | | |
  17. // 1 ------ 2 ------ 3 ------- 4
  18. // ^ b ^
  19. // =====================================
  20. double t = 15; // Thickness (cm)
  21. double E = 300000; // Elastic modulus
  22. double nu = 0.15; // Poisson modulus
  23. // Number degrees of freedom
  24. int gdl = N * 4;
  25. // Create model
  26. Model *model = new Model(2, gdl);
  27. // Create nodes
  28. std::vector<Node *> *nodes = new std::vector<Node *>();
  29. int j;
  30. for (int i = 1; i <= N + 1; i++) {
  31. nodes->push_back(new Node("N" + std::to_string(i), b * (i - 1), 0));
  32. }
  33. for (int i = 1; i <= N + 1; i++) {
  34. j = N + 1 + i;
  35. nodes->push_back(new Node("N" + std::to_string(j), b * (i - 1), h));
  36. }
  37. // Add nodes to model
  38. model->add_nodes(nodes);
  39. // Create elements
  40. // n4 ------------ n3
  41. // | |
  42. // | (i) |
  43. // | |
  44. // n1 ------------ n2
  45. unsigned long n1, n2, n3, n4;
  46. std::vector<Element *> *elements = new std::vector<Element *>();
  47. for (unsigned long i = 0; i < N; i++) {
  48. n1 = i;
  49. n2 = i + 1;
  50. n3 = N + i + 2;
  51. n4 = N + i + 1;
  52. elements->push_back(new Membrane("MEM" + std::to_string(i), nodes->at(n1),
  53. nodes->at(n2), nodes->at(n3), nodes->at(n4), E, nu, t));
  54. }
  55. model->add_elements(elements);
  56. // Create restraints
  57. std::vector<Restraint *> *restraints = new std::vector<Restraint *>();
  58. RestraintNode *r1 = new RestraintNode("R1", nodes->at(0));
  59. RestraintNode *r2 = new RestraintNode("R2", nodes->at(static_cast<unsigned long>(N)));
  60. r1->add_all();
  61. r2->add_all();
  62. restraints->push_back(r1);
  63. restraints->push_back(r2);
  64. model->add_restraints(restraints);
  65. // Add distribuited load
  66. std::vector<Load *> *loads = new std::vector<Load *>();
  67. for (int i = 0; i < elements->size(); i++) {
  68. Membrane *mem = dynamic_cast<Membrane *>(elements->at
  69. (static_cast<unsigned long>(i)));
  70. loads->push_back( new LoadMembraneDistributed("DV100kN V @" +
  71. std::to_string(i + 1), mem, 4, 3, -100, 0, -100, 1));
  72. }
  73. std::vector<LoadPattern *> *loadpattern = new std::vector<LoadPattern *>();
  74. loadpattern->push_back(new LoadPatternConstant("LOADCONSTANT", loads));
  75. model->add_load_patterns(loadpattern);
  76. // Create analysis
  77. StaticAnalysis *analysis = new StaticAnalysis(model);
  78. analysis->analyze(false);
  79. // Save results to file
  80. model->save_results("bridge.txt");
  81. // Delete data
  82. analysis->clear();
  83. delete elements;
  84. delete loadpattern;
  85. delete loads;
  86. delete restraints;
  87. delete nodes;
  88. delete model;
  89. delete analysis;

The results are the following:

Bridge example, displacement x
Bridge example, displacement y
Bridge example, stress x
Bridge example, stress x

GPU analysis will be faster if N (number of membranes) is greater.


Comparision between GPU/CPU

License

This project is licensed under MIT [https://opensource.org/licenses/MIT/]

Author

Pablo Pizarro R. | 2018 - 2019