├── .gitattributes ├── LICENSE ├── README.md ├── bin └── STAN_binary.zip ├── examples └── Example1.zip ├── images ├── MainView.png ├── Properties.png ├── Results.png └── Solver.PNG └── src ├── Icons ├── Clip.png ├── Logo.png ├── Mesh.png ├── MeshTrans.png ├── Trans.png ├── ViewFit.png ├── ViewIso.png ├── ViewXY.png ├── ViewXZ.png ├── ViewYX.png ├── ViewYZ.png ├── ViewZX.png ├── ViewZY.png └── logo.ico ├── STAN.sln ├── STAN_Database ├── Analysis.cs ├── BoundaryCondition.cs ├── Database.cs ├── Element.cs ├── FE_Library.cs ├── Information.cs ├── Material.cs ├── MatrixST.cs ├── Node.cs ├── Part.cs └── STAN_Database.csproj ├── STAN_PrePost ├── App.config ├── App.xaml ├── App.xaml.cs ├── BOX_Analysis.xaml ├── BOX_Analysis.xaml.cs ├── BOX_BC.xaml ├── BOX_BC.xaml.cs ├── BOX_Mat.xaml ├── BOX_Mat.xaml.cs ├── BOX_Part.xaml ├── BOX_Part.xaml.cs ├── BOX_Result.xaml ├── BOX_Result.xaml.cs ├── ExportWindow.xaml ├── ExportWindow.xaml.cs ├── Functions.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── RenderInterface.cs ├── ResultControl.cs ├── STAN_Label.xaml ├── STAN_PrePost.csproj ├── STAN_PrePost.csproj.user ├── STAN_Slider.xaml ├── TreeViewModel.cs └── packages.config └── STAN_Solver ├── App.config ├── Properties └── AssemblyInfo.cs ├── STAN_Solver.csproj ├── Solver.cs ├── SolverFunctions.cs ├── logo.ico └── packages.config /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, Michal 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # STAN - Structural Analyser 2 | STructural ANalyser - C#/.NET Finite Element Software\ 3 | [Download](https://github.com/galuszkm/STAN/raw/main/bin/STAN_binary.zip) binary files and [Example](https://github.com/galuszkm/STAN/raw/main/examples/Example1.zip) to test it! 4 | 5 | This app is still under development, a lot of features are not avaliable at the moment.\ 6 | If you like it, you are more than welcome to join the project!\ 7 | Documentation and code description soon! 8 | 9 | ## Introduction 10 | STAN is a stand-alone C#/.NET Finite Element environment with Pre/Post Processor and Solver for 3D structural analysis. 11 | Main purpose is to provide user-friendly and object oriented code to develop custom algorithms, FE formulation, structures, etc. 12 | Obviously, it is not as fast as comercial Fortran or C++ codes (and most likely will never be). 13 | Although this app provides really efficient enviroment for pre/post processing and solving boundary value problems. 14 | Therefore if you are intrested only in finite element code or only in data visualisation, you may find it very usefull.\ 15 |
Pre/Post Processor:
16 | * Nastran format (.bdf) mesh import 17 | * Currently only 8-node hexahedral finite elements supported 18 | * Boundary condition: Point Load and Single Point Constraint 19 | * Result export to .vtu format (readable in ParaView) 20 | 21 | Solver: 22 | * Linear static analysis 23 | * Linear elasic material 24 | * Iterative (Conjugate Gradient) and Direct (Cholesky) linear system solver 25 | 26 | ## Getting started 27 | ### Create new project 28 | To create new project unzip binary package and run STAN_PrePost.exe. User interface layout consists of: Menus (1), Toolbar(2), TreeView (3), Property Box (4), Graphics Viewport (5), Part Box (6). Graphics settings such as background and label color, mesh wireframe, transparency, colorbar setup could be modified using Menus. Toolbar contains several buttons used to open STAN database file, import a mesh, export results, add material and boundary condition, etc. All model properties are collected in TreeView. By selecting item in TreeView you are able to modify it in Property Box. Part Box allows you to control Part visibility in Viewport. 29 | 30 | 31 | 32 | ### Mesh 33 | First step is to import a mesh. Click Import button in Toolbar and select .bdf Nastran file. 34 | There are many excellent both comercial as well as open source mesh generators avaliable on the market. Therefore I decided to skip this point and allow user to import mesh created by any tool. Currently only short Nastran format is supported. An example of mesh file is presented below: 35 | ``` 36 | $$ GRID Data 37 | GRID 1 0.0 15.0 0.0 38 | GRID 2 -7.11-15 5.0 0.0 39 | GRID 3 0.0 -5.0 0.0 40 | ... 41 | $$ CHEXA Elements: First Order 42 | CHEXA 1 1 573 570 571 572 1236 1237+ 43 | + 1238 1239 44 | CHEXA 2 1 575 569 570 573 1240 1241+ 45 | + 1237 1236 46 | CHEXA 3 1 576 573 572 574 1242 1236+ 47 | + 1239 1243 48 | ... 49 | ``` 50 | At the moment, only 8-none hexahedral elements are avaliable (4-node tetrahedron and 6-node pentahedron are under development). In STAN third number in element line defines PART ID. You can use Mesh.bdf file from Example 1 as a test run. Note that only one mesh can be imported in single project. 51 | 52 | ### Boundary Conditions, Materials and Analysis 53 | When mesh is loaded you can create boundary conditions, materials and analysis setup. 54 | * To add Material click Add Mat button in Toolbar. New item appears in Material TreeView, select and modify it in Property Box. Only linear elastic material type is avaliable at the moment. 55 | * To add Boundary Condition click Add BC button in Toolbar. There are two types of BC avaliable: Single Point Constraint (SPC) and Point Load. Currently only "Paste mode" is implemented to assign DOF. Therefore you can prepare BC setup with any text editor, copy it and use Clipboard button to paste. 4 column format with tab separators is required: Node ID, X value, Y value, Z value. For SPC value 1 means that DOF is fixed, 0 means free. Point Load values specify forces acting in each direction. 56 | * Select Part in TreeView and to assign material from the list. You also change its name, color of finite element formulation (G2 - full integration, G1 - reduced integration). 57 | * Select Analysis setup in TreeView to modify setup. Only linear static analysis is currently avaliable. Two linear system solver have been implemented: Iterative (Conjugate Gradient) and Direct (Cholesky - LLT factorization). 58 | ``` 59 | SPC (XYZ fixed): 60 | 4 1 1 1 61 | 5 1 1 1 62 | 16 1 1 1 63 | ... 64 | Point Load: 65 | 2 0 0 50 66 | 3 0 0 50 67 | 102 0 0 50 68 | ... 69 | ``` 70 | 71 | 72 | ### Solve 73 | To solve the job click Solve button in Toolbar. First of all you need to save the model in STdb (STAN database) format. This file will be read by solver and overwritten with results. In general, STAN PrePost and STAN Solver use the same binary database format, serialized with Google Protocol Buffers (most efficient way for reading and writting I could find). Solver is a separated console app so you can still use PrePost while the job is running. In console you can see current status of analysis. 74 | 75 |

76 | 77 |

78 | 79 | ### Results 80 | When solving is done, you can load the results using Load results button or you can create new project and Open overwritten STdb file. Result item is now avaliable in TreeView. You can choose several result type like Displacement, Stress and Strain presented as smooth contour map or element min/max/average values. For Stress and Strain postprocessing, STAN uses extrapolated values from Gauss points to Nodes.\ 81 | If you need advanced postprocessing features, you can export any result in .vtu format and read it e.g. in ParaView. Finally, if you don't need results any more and want to reduce STdb file size, click Remove results button and save the model. 82 | 83 | 84 | -------------------------------------------------------------------------------- /bin/STAN_binary.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/bin/STAN_binary.zip -------------------------------------------------------------------------------- /examples/Example1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/examples/Example1.zip -------------------------------------------------------------------------------- /images/MainView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/images/MainView.png -------------------------------------------------------------------------------- /images/Properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/images/Properties.png -------------------------------------------------------------------------------- /images/Results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/images/Results.png -------------------------------------------------------------------------------- /images/Solver.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/images/Solver.PNG -------------------------------------------------------------------------------- /src/Icons/Clip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/Clip.png -------------------------------------------------------------------------------- /src/Icons/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/Logo.png -------------------------------------------------------------------------------- /src/Icons/Mesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/Mesh.png -------------------------------------------------------------------------------- /src/Icons/MeshTrans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/MeshTrans.png -------------------------------------------------------------------------------- /src/Icons/Trans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/Trans.png -------------------------------------------------------------------------------- /src/Icons/ViewFit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/ViewFit.png -------------------------------------------------------------------------------- /src/Icons/ViewIso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/ViewIso.png -------------------------------------------------------------------------------- /src/Icons/ViewXY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/ViewXY.png -------------------------------------------------------------------------------- /src/Icons/ViewXZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/ViewXZ.png -------------------------------------------------------------------------------- /src/Icons/ViewYX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/ViewYX.png -------------------------------------------------------------------------------- /src/Icons/ViewYZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/ViewYZ.png -------------------------------------------------------------------------------- /src/Icons/ViewZX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/ViewZX.png -------------------------------------------------------------------------------- /src/Icons/ViewZY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/ViewZY.png -------------------------------------------------------------------------------- /src/Icons/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galuszkm/STAN/a01742d78a28b9c3a1e3cfbed37b8649466eb4f8/src/Icons/logo.ico -------------------------------------------------------------------------------- /src/STAN.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30621.155 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STAN_PrePost", "STAN_PrePost\STAN_PrePost.csproj", "{E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "STAN_Database", "STAN_Database\STAN_Database.csproj", "{89EA718E-E258-41D3-97DE-C8F704EC67F1}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STAN_Solver", "STAN_Solver\STAN_Solver.csproj", "{359ABCDC-6831-47FF-9F6C-A439674A98DF}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Debug|x64 = Debug|x64 16 | Debug|x86 = Debug|x86 17 | Release|Any CPU = Release|Any CPU 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Debug|x64.ActiveCfg = Debug|Any CPU 25 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Debug|x64.Build.0 = Debug|Any CPU 26 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Debug|x86.ActiveCfg = Debug|Any CPU 27 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Debug|x86.Build.0 = Debug|Any CPU 28 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Release|x64.ActiveCfg = Release|Any CPU 31 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Release|x86.ActiveCfg = Release|Any CPU 32 | {E2FD32FB-FEB6-4AB7-B2C4-FB6BEA1B0269}.Release|x86.Build.0 = Release|Any CPU 33 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Debug|x64.ActiveCfg = Debug|Any CPU 36 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Debug|x64.Build.0 = Debug|Any CPU 37 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Debug|x86.ActiveCfg = Debug|Any CPU 38 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Debug|x86.Build.0 = Debug|Any CPU 39 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Release|Any CPU.Build.0 = Release|Any CPU 41 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Release|x64.ActiveCfg = Release|Any CPU 42 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Release|x64.Build.0 = Release|Any CPU 43 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Release|x86.ActiveCfg = Release|Any CPU 44 | {89EA718E-E258-41D3-97DE-C8F704EC67F1}.Release|x86.Build.0 = Release|Any CPU 45 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 46 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Debug|Any CPU.Build.0 = Debug|Any CPU 47 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Debug|x64.ActiveCfg = Debug|Any CPU 48 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Debug|x64.Build.0 = Debug|Any CPU 49 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Debug|x86.ActiveCfg = Debug|Any CPU 50 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Debug|x86.Build.0 = Debug|Any CPU 51 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Release|Any CPU.ActiveCfg = Release|Any CPU 52 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Release|Any CPU.Build.0 = Release|Any CPU 53 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Release|x64.ActiveCfg = Release|Any CPU 54 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Release|x64.Build.0 = Release|Any CPU 55 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Release|x86.ActiveCfg = Release|Any CPU 56 | {359ABCDC-6831-47FF-9F6C-A439674A98DF}.Release|x86.Build.0 = Release|Any CPU 57 | EndGlobalSection 58 | GlobalSection(SolutionProperties) = preSolution 59 | HideSolutionNode = FALSE 60 | EndGlobalSection 61 | GlobalSection(ExtensibilityGlobals) = postSolution 62 | SolutionGuid = {034F6CB8-6054-457D-9F96-D6311A4F3362} 63 | EndGlobalSection 64 | EndGlobal 65 | -------------------------------------------------------------------------------- /src/STAN_Database/Analysis.cs: -------------------------------------------------------------------------------- 1 | using ProtoBuf; 2 | 3 | namespace STAN_Database 4 | { 5 | [ProtoContract(SkipConstructor = true)] 6 | public class Analysis 7 | { 8 | [ProtoMember(1)] private string Type; 9 | [ProtoMember(2)] private string LinSolver; 10 | [ProtoMember(3)] private double LinSolverTolerance; 11 | [ProtoMember(4)] private int LinSolverIterMax; 12 | [ProtoMember(5)] private int IncNumb; 13 | [ProtoMember(6)] private int Result_StepNo; 14 | 15 | public Analysis() 16 | { 17 | Type = "Linear_Statics"; 18 | LinSolver = "CG"; 19 | LinSolverTolerance = 1.0e-6; 20 | LinSolverIterMax = 0; 21 | IncNumb = 0; 22 | 23 | // Result status 24 | Result_StepNo = 0; 25 | } 26 | 27 | public void SetAnalysisType(string type) 28 | { 29 | Type = type; 30 | } 31 | 32 | public string GetAnalysisType() 33 | { 34 | return Type; 35 | } 36 | 37 | public void SetLinSolver(string linsol) 38 | { 39 | LinSolver = linsol; 40 | } 41 | 42 | public string GetLinSolver() 43 | { 44 | return LinSolver; 45 | } 46 | 47 | public void SetLinSolverTolerance(double tolerance) 48 | { 49 | LinSolverTolerance = tolerance; 50 | } 51 | 52 | public double GetLinSolverTolerance() 53 | { 54 | return LinSolverTolerance; 55 | } 56 | 57 | public void SetLinSolverMaxIter(int maxiter) 58 | { 59 | LinSolverIterMax = maxiter; 60 | } 61 | 62 | public int GetLinSolverMaxIter() 63 | { 64 | return LinSolverIterMax; 65 | } 66 | 67 | public void SetIncNumb(int inc) 68 | { 69 | IncNumb = inc; 70 | } 71 | 72 | public int GetIncNumb() 73 | { 74 | return IncNumb; 75 | } 76 | 77 | public int GetResultStepNo() 78 | { 79 | return Result_StepNo; 80 | } 81 | 82 | public void SetResultStepNo(int inc) 83 | { 84 | Result_StepNo = inc; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/STAN_Database/BoundaryCondition.cs: -------------------------------------------------------------------------------- 1 | using Kitware.VTK; 2 | using ProtoBuf; 3 | using System.Collections.Generic; 4 | 5 | namespace STAN_Database 6 | { 7 | [ProtoContract(SkipConstructor = true)] 8 | public class BoundaryCondition 9 | { 10 | [ProtoMember(1)] public string Type { get; set; } 11 | [ProtoMember(2)] public string Name { get; set; } 12 | [ProtoMember(3)] public int ID { get; set; } 13 | [ProtoMember(4)] public Dictionary NodalValues { get; set; } 14 | [ProtoMember(5)] public int ColorID { get; set; } 15 | 16 | private vtkGlyph3D GlyphX; 17 | private vtkGlyph3D GlyphY; 18 | private vtkGlyph3D GlyphZ; 19 | private vtkDataSetMapper MapperX; 20 | private vtkDataSetMapper MapperY; 21 | private vtkDataSetMapper MapperZ; 22 | private vtkActor ActorX; 23 | private vtkActor ActorY; 24 | private vtkActor ActorZ; 25 | private vtkTableBasedClipDataSet ClipperX; 26 | private vtkTableBasedClipDataSet ClipperY; 27 | private vtkTableBasedClipDataSet ClipperZ; 28 | 29 | public BoundaryCondition(string name, string type, int id) 30 | { 31 | Name = name; 32 | Type = type; 33 | ID = id; 34 | ColorID = ID % 9; 35 | NodalValues = new Dictionary(); 36 | 37 | } 38 | 39 | public void Initialize() 40 | { 41 | // Initialize Actors 42 | GlyphX = vtkGlyph3D.New(); 43 | MapperX = vtkDataSetMapper.New(); 44 | MapperX.SetInputConnection(GlyphX.GetOutputPort()); 45 | ActorX = vtkActor.New(); 46 | ActorX.SetMapper(MapperX); 47 | ClipperX = vtkTableBasedClipDataSet.New(); 48 | 49 | GlyphY = vtkGlyph3D.New(); 50 | MapperY = vtkDataSetMapper.New(); 51 | MapperY.SetInputConnection(GlyphY.GetOutputPort()); 52 | ActorY = vtkActor.New(); 53 | ActorY.SetMapper(MapperY); 54 | ClipperY = vtkTableBasedClipDataSet.New(); 55 | 56 | GlyphZ = vtkGlyph3D.New(); 57 | MapperZ = vtkDataSetMapper.New(); 58 | MapperZ.SetInputConnection(GlyphZ.GetOutputPort()); 59 | ActorZ = vtkActor.New(); 60 | ActorZ.SetMapper(MapperZ); 61 | ClipperZ = vtkTableBasedClipDataSet.New(); 62 | 63 | // Enable wireframe display mode 64 | ActorX.GetProperty().EdgeVisibilityOn(); 65 | ActorY.GetProperty().EdgeVisibilityOn(); 66 | ActorZ.GetProperty().EdgeVisibilityOn(); 67 | 68 | // Hide Actors 69 | ActorX.VisibilityOff(); 70 | ActorY.VisibilityOff(); 71 | ActorZ.VisibilityOff(); 72 | } 73 | 74 | /// 75 | /// Add nodal value to List 76 | /// 77 | /// nid 78 | /// - Node ID 79 | /// direction 80 | /// - X=0; Y=1; Z=2 81 | /// value 82 | /// - Value of BC (double for Force BC, 0 or 1 for Fix BC) 83 | /// NodeLib 84 | /// - Database Node library 85 | /// 86 | /// 87 | public void Add(int nid, double[] value, Dictionary NodeLib) 88 | { 89 | if (NodeLib.ContainsKey(nid)) 90 | { 91 | MatrixST nVal = new MatrixST(3, 1); 92 | nVal.SetFast(0, 0, value[0]); 93 | nVal.SetFast(1, 0, value[1]); 94 | nVal.SetFast(2, 0, value[2]); 95 | 96 | NodalValues.Add(nid, nVal); 97 | } 98 | } 99 | 100 | /// 101 | /// Clear list of Nodal Values 102 | /// 103 | public void Clear() 104 | { 105 | NodalValues = new Dictionary(); 106 | } 107 | 108 | /// 109 | /// Update Boundary Condition actor (arrows) in Viewport 110 | /// 111 | public void Update_Arrows(Dictionary NodeLib, double scale, int Step, bool ClipMode) 112 | { 113 | vtkPoints PointsX = vtkPoints.New(); 114 | vtkPoints PointsY = vtkPoints.New(); 115 | vtkPoints PointsZ = vtkPoints.New(); 116 | 117 | // Create Cone Sources for X, Y and Z direction 118 | vtkConeSource ConeSourceX = vtkConeSource.New(); 119 | vtkConeSource ConeSourceY = vtkConeSource.New(); 120 | vtkConeSource ConeSourceZ = vtkConeSource.New(); 121 | 122 | ConeSourceX.SetAngle(15); 123 | ConeSourceX.SetHeight(scale); 124 | ConeSourceX.SetRadius(scale / 4); 125 | ConeSourceX.SetResolution(12); 126 | ConeSourceX.SetDirection(1, 0, 0); 127 | 128 | ConeSourceY.SetAngle(15); 129 | ConeSourceY.SetHeight(scale); 130 | ConeSourceY.SetRadius(scale / 4); 131 | ConeSourceY.SetResolution(12); 132 | ConeSourceY.SetDirection(0, 1, 0); 133 | 134 | ConeSourceZ.SetAngle(15); 135 | ConeSourceZ.SetHeight(scale); 136 | ConeSourceZ.SetRadius(scale / 4); 137 | ConeSourceZ.SetResolution(12); 138 | ConeSourceZ.SetDirection(0, 0, 1); 139 | 140 | // Create Points 141 | foreach (int i in NodalValues.Keys) 142 | { 143 | double X = NodeLib[i].X + NodeLib[i].GetDisp(Step, 0); 144 | double Y = NodeLib[i].Y + NodeLib[i].GetDisp(Step, 1); 145 | double Z = NodeLib[i].Z + NodeLib[i].GetDisp(Step, 2); 146 | 147 | if (NodalValues[i].Get(0, 0) != 0) PointsX.InsertNextPoint(X - scale / 2, Y, Z); 148 | if (NodalValues[i].Get(1, 0) != 0) PointsY.InsertNextPoint(X, Y - scale / 2, Z); 149 | if (NodalValues[i].Get(2, 0) != 0) PointsZ.InsertNextPoint(X, Y, Z - scale / 2); 150 | } 151 | 152 | // Set Points to PolyData 153 | vtkPolyData PolyX = vtkPolyData.New(); PolyX.SetPoints(PointsX); 154 | vtkPolyData PolyY = vtkPolyData.New(); PolyY.SetPoints(PointsY); 155 | vtkPolyData PolyZ = vtkPolyData.New(); PolyZ.SetPoints(PointsZ); 156 | 157 | // Create Glyphs 3D 158 | GlyphX = vtkGlyph3D.New(); 159 | GlyphY = vtkGlyph3D.New(); 160 | GlyphZ = vtkGlyph3D.New(); 161 | 162 | GlyphX.SetSourceConnection(ConeSourceX.GetOutputPort()); 163 | GlyphX.SetInput(PolyX); 164 | GlyphX.Update(); 165 | 166 | GlyphY.SetSourceConnection(ConeSourceY.GetOutputPort()); 167 | GlyphY.SetInput(PolyY); 168 | GlyphY.Update(); 169 | 170 | GlyphZ.SetSourceConnection(ConeSourceZ.GetOutputPort()); 171 | GlyphZ.SetInput(PolyZ); 172 | GlyphZ.Update(); 173 | 174 | // Set Mapper based on Clip Mode 175 | if (ClipMode == true) 176 | { 177 | // Add Clippers to Mapper 178 | ClipperX.SetInputConnection(GlyphX.GetOutputPort()); 179 | ClipperX.Update(); 180 | MapperX.SetInputConnection(ClipperX.GetOutputPort()); 181 | MapperX.Update(); 182 | 183 | ClipperY.SetInputConnection(GlyphY.GetOutputPort()); 184 | ClipperY.Update(); 185 | MapperY.SetInputConnection(ClipperY.GetOutputPort()); 186 | MapperY.Update(); 187 | 188 | ClipperZ.SetInputConnection(GlyphZ.GetOutputPort()); 189 | ClipperZ.Update(); 190 | MapperZ.SetInputConnection(ClipperZ.GetOutputPort()); 191 | MapperZ.Update(); 192 | } 193 | else 194 | { 195 | // Add Glyphs to Mapper 196 | MapperX.SetInputConnection(GlyphX.GetOutputPort()); 197 | MapperY.SetInputConnection(GlyphY.GetOutputPort()); 198 | MapperZ.SetInputConnection(GlyphZ.GetOutputPort()); 199 | MapperX.Update(); 200 | MapperY.Update(); 201 | MapperZ.Update(); 202 | } 203 | 204 | // Update Actor color 205 | ActorX.GetProperty().SetColor( 206 | GetColor()[0] / 255.0, 207 | GetColor()[1] / 255.0, 208 | GetColor()[2] / 255.0); 209 | 210 | ActorY.GetProperty().SetColor( 211 | GetColor()[0] / 255.0, 212 | GetColor()[1] / 255.0, 213 | GetColor()[2] / 255.0); 214 | 215 | ActorZ.GetProperty().SetColor( 216 | GetColor()[0] / 255.0, 217 | GetColor()[1] / 255.0, 218 | GetColor()[2] / 255.0); 219 | } 220 | 221 | public void ShowActor() 222 | { 223 | ActorX.VisibilityOn(); 224 | ActorY.VisibilityOn(); 225 | ActorZ.VisibilityOn(); 226 | } 227 | 228 | public void HideActor() 229 | { 230 | ActorX.VisibilityOff(); 231 | ActorY.VisibilityOff(); 232 | ActorZ.VisibilityOff(); 233 | } 234 | 235 | public vtkActor[] GetActor() 236 | { 237 | return new vtkActor[3] { ActorX, ActorY, ActorZ }; 238 | } 239 | 240 | private double[] GetColor() 241 | { 242 | List Colors = new List 243 | { 244 | new double[3]{ 12, 197, 19 }, 245 | new double[3]{ 141, 245, 145 }, 246 | new double[3]{ 109, 232, 226 }, 247 | new double[3]{ 42, 85, 199 }, 248 | new double[3]{ 223, 232, 28 }, 249 | new double[3]{ 236, 134, 64 }, 250 | new double[3]{ 216, 52, 52 }, 251 | new double[3]{ 184, 61, 241 }, 252 | new double[3]{ 110, 10, 120 } 253 | }; 254 | return Colors[ColorID]; 255 | } 256 | 257 | public void ClipBC (vtkPlane ClipPlane, bool clip) 258 | { 259 | if (clip == true) 260 | { 261 | ClipperX = vtkTableBasedClipDataSet.New(); 262 | ClipperX.SetClipFunction(ClipPlane); 263 | ClipperX.SetInputConnection(GlyphX.GetOutputPort()); 264 | ClipperX.Update(); 265 | MapperX.SetInputConnection(ClipperX.GetOutputPort()); 266 | MapperX.Update(); 267 | 268 | ClipperY = vtkTableBasedClipDataSet.New(); 269 | ClipperY.SetClipFunction(ClipPlane); 270 | ClipperY.SetInputConnection(GlyphY.GetOutputPort()); 271 | ClipperY.Update(); 272 | MapperY.SetInputConnection(ClipperY.GetOutputPort()); 273 | MapperY.Update(); 274 | 275 | ClipperZ = vtkTableBasedClipDataSet.New(); 276 | ClipperZ.SetClipFunction(ClipPlane); 277 | ClipperZ.SetInputConnection(GlyphZ.GetOutputPort()); 278 | ClipperZ.Update(); 279 | MapperZ.SetInputConnection(ClipperZ.GetOutputPort()); 280 | MapperZ.Update(); 281 | } 282 | else 283 | { 284 | // Add Glyphs to Mapper 285 | MapperX.SetInputConnection(GlyphX.GetOutputPort()); 286 | MapperY.SetInputConnection(GlyphY.GetOutputPort()); 287 | MapperZ.SetInputConnection(GlyphZ.GetOutputPort()); 288 | MapperX.Update(); 289 | MapperY.Update(); 290 | MapperZ.Update(); 291 | } 292 | } 293 | 294 | public void SetWireframe(int arg) 295 | { 296 | ActorX.GetProperty().SetEdgeVisibility(arg); 297 | ActorY.GetProperty().SetEdgeVisibility(arg); 298 | ActorZ.GetProperty().SetEdgeVisibility(arg); 299 | } 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /src/STAN_Database/Database.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.IO; 4 | using System.Linq; 5 | using ProtoBuf; 6 | 7 | namespace STAN_Database 8 | { 9 | [ProtoContract(SkipConstructor = true)] 10 | public class Database 11 | { 12 | [ProtoMember(1)] public Dictionary NodeLib { get;} 13 | [ProtoMember(2)] public Dictionary ElemLib { get; } 14 | [ProtoMember(3)] public Dictionary MatLib { get; set; } 15 | public Dictionary PartLib { get; set; } 16 | [ProtoMember(4)] public Dictionary BCLib { get; set; } 17 | public FE_Library FELib { get; set; } 18 | private List Import_Error; 19 | [ProtoMember(5)] public int nDOF; 20 | [ProtoMember(6)] public Analysis AnalysisLib {get; set;} 21 | [ProtoMember(7)] public Information Info { get; set; } 22 | 23 | 24 | public Database() 25 | { 26 | // ============================ Initialize ================================== 27 | 28 | NodeLib = new Dictionary(); // Node library - key is Node ID, value is Node object 29 | ElemLib = new Dictionary(); // Element library - key is Element ID, value is Element object 30 | MatLib = new Dictionary(); // Material library - key is Mat ID, value is Material object 31 | BCLib = new Dictionary(); // Boundary Conditions library 32 | FELib = new FE_Library(); // Finite Element library - key is FE type, value is FE_Library object 33 | PartLib = new Dictionary(); // Part library - key is Part ID, value is Part object 34 | AnalysisLib = new Analysis(); // Analysis library - analysis settings 35 | Import_Error = new List(); // List with import errors 36 | Info = new Information(); // Additional info to serialize 37 | } 38 | 39 | public void ReadNastranMesh(string path) 40 | { 41 | CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); 42 | 43 | // ==================== List of element type supported ======================== 44 | List Elem_types_allowed = new List 45 | { 46 | "CHEXA", 47 | //"CTETRA" 48 | }; 49 | 50 | // ========================= Read file =================================== 51 | string[] data = File.ReadAllLines(path); 52 | 53 | for (int i = 0; i < data.Length; i++) // Find lines in text file 54 | { 55 | if (data[i].StartsWith("$") == false) // Skip commented lines 56 | { 57 | // ----------------------- Find elements ------------------------- 58 | if (Elem_types_allowed.Any(s => data[i].Contains(s))) // Check if element type is supported 59 | { 60 | string temp = data[i]; // Temporary string to collect text line 61 | 62 | for (int j = i + 1; j < data.Length; j++) // Check next lines (usually starts with + or whitespace) 63 | { 64 | if (data[j].StartsWith("+") || data[j].StartsWith(" ")) 65 | { 66 | temp += data[j]; // Append next line 67 | i = j; // Increase i - to skip this line in outer loop 68 | } 69 | else break; // Break inner loop otherwise 70 | } 71 | 72 | try 73 | { 74 | Element E = new Element(temp); // Try to create element based on collected lines 75 | ElemLib.Add(E.ID, E); // Add new element to Element Library 76 | } 77 | catch 78 | { 79 | Import_Error.Add(temp); // Catch error 80 | } 81 | } 82 | 83 | // ----------------------- Find nodes ------------------------- 84 | if (data[i].StartsWith("GRID")) 85 | { 86 | try 87 | { 88 | Node N = new Node(data[i]); // Try to create element based on collected lines 89 | NodeLib.Add(N.ID, N); // Add new node to Node Library 90 | } 91 | catch 92 | { 93 | Import_Error.Add(data[i]); 94 | } 95 | } 96 | } 97 | 98 | } 99 | 100 | // Create list with Parts - using LINQ select PID of all elements, remove duplicates and sort 101 | List PartList = ElemLib.Values.Select(x => x.PID).Distinct().ToList(); 102 | PartList.Sort(); 103 | 104 | // Create Part objects and add to Part Library 105 | foreach (int pid in PartList) 106 | { 107 | Part NewPart = new Part(pid); 108 | NewPart.CreatePart(NodeLib, ElemLib); 109 | PartLib.Add(pid, NewPart); 110 | } 111 | } 112 | 113 | public int Get_nDoF() 114 | { 115 | return nDOF; 116 | } 117 | 118 | public void AddMat(int id, Material Mat) 119 | { 120 | MatLib.Add(id, Mat); 121 | } 122 | 123 | public string Database_Summary() 124 | { 125 | string summary = ""; 126 | summary += "\n ================== DATABASE SUMMARY =================="; 127 | summary += "\n Number of nodes:".PadRight(25) + NodeLib.Count.ToString().PadLeft(31); 128 | summary += "\n Number of elements:".PadRight(25) + ElemLib.Count.ToString().PadLeft(31); 129 | summary += "\n Number of DoF:".PadRight(25) + nDOF.ToString().PadLeft(31); 130 | summary += "\n ========================================================== \n"; 131 | 132 | return summary; 133 | } 134 | 135 | public void Set_nDOF() 136 | { 137 | nDOF = NodeLib.Count * 3; 138 | } 139 | 140 | public void AssignDOF() 141 | { 142 | // Initialize Node EList - if empty before Serializing than not pass through Protocol Buffers 143 | foreach (Node n in NodeLib.Values) 144 | { 145 | n.Initialize_EList(); 146 | } 147 | 148 | // Add Elements to Node EList 149 | foreach (Element E in ElemLib.Values) 150 | { 151 | E.AddElem2Nodes(NodeLib); 152 | } 153 | 154 | // Remove duplicated Element IDs in Node EList 155 | foreach (Node n in NodeLib.Values) 156 | { 157 | n.RemoveElemDuplicates(); 158 | } 159 | 160 | // Dictionary with neighbor nodes 161 | Dictionary> Neighbors = new Dictionary>(); 162 | foreach (Node N in NodeLib.Values) 163 | { 164 | List N_neighbors = new List(); // List of Node n neighbors 165 | foreach (int E in N.GetElements()) // Get Element E that contains Node N 166 | { 167 | foreach (int NID in ElemLib[E].NList) // Get Nodes NID of Element E 168 | { 169 | N_neighbors.Add(NID); // Add Node NID to neighbors of Node N 170 | } 171 | } 172 | N_neighbors = N_neighbors.Distinct().ToList(); // Remove duplicates 173 | N_neighbors.Remove(N.ID); // Remove Node N form its neighbors 174 | 175 | Neighbors.Add(N.ID, N_neighbors); // Add Node N to dict 176 | } 177 | 178 | // Find some peripheral Node 179 | int FirstNode = 0; 180 | bool GoOn = true; 181 | for (int i = 1; i < 7; i++) 182 | { 183 | if (GoOn) 184 | { 185 | foreach (Node n in NodeLib.Values) 186 | { 187 | if (n.GetElements().Count == i) 188 | { 189 | FirstNode = n.ID; 190 | GoOn = false; 191 | break; 192 | } 193 | } 194 | } 195 | else break; 196 | } 197 | 198 | // Assign DOF index to Node 199 | int index = 0; 200 | 201 | // Create Node dict with data if Node has assigned DOF 202 | Dictionary NID_Done = new Dictionary(); 203 | foreach (int NID in NodeLib.Keys) 204 | { 205 | NID_Done.Add(NID, false); 206 | } 207 | 208 | // Start 209 | NodeLib[FirstNode].SetDOF(index); // Set DOF of First Node 210 | index++; // Increase DOF index 211 | NID_Done[FirstNode] = true; // Set First Node as done 212 | 213 | List NextNode = Neighbors[FirstNode]; // List with next nodes to do 214 | 215 | int index2 = 0; 216 | while (index < NodeLib.Count) 217 | { 218 | int NID = NextNode[index2]; 219 | if (NID_Done[NID] == false) 220 | { 221 | NodeLib[NID].SetDOF(index); 222 | NID_Done[NID] = true; 223 | index++; 224 | foreach (int n in Neighbors[NID]) 225 | { 226 | if (NID_Done[n] == false) 227 | { 228 | NextNode.Add(n); 229 | } 230 | } 231 | } 232 | index2++; 233 | } 234 | } 235 | 236 | public double[] GetBounds() 237 | { 238 | List X = new List(); 239 | List Y = new List(); 240 | List Z = new List(); 241 | 242 | for (int inc = 0; inc <= AnalysisLib.GetResultStepNo(); inc++) 243 | { 244 | foreach (Node N in NodeLib.Values) 245 | { 246 | X.Add(N.X + N.GetDisp(inc, 0)); 247 | Y.Add(N.Y + N.GetDisp(inc, 1)); 248 | Z.Add(N.Z + N.GetDisp(inc, 2)); 249 | } 250 | } 251 | 252 | double[] bounds = new double[6] 253 | { 254 | X.Min(), X.Max(), Y.Min(), Y.Max(), Z.Min(), Z.Max() 255 | }; 256 | return bounds; 257 | } 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/STAN_Database/Information.cs: -------------------------------------------------------------------------------- 1 | using ProtoBuf; 2 | using System.Collections.Generic; 3 | 4 | namespace STAN_Database 5 | { 6 | [ProtoContract(SkipConstructor = true)] 7 | public class Information 8 | { 9 | [ProtoMember(1)] private Dictionary InfoPart { get; set; } 10 | 11 | public Information() 12 | { 13 | 14 | } 15 | 16 | public void ClearPartInfo() 17 | { 18 | InfoPart = new Dictionary(); 19 | } 20 | 21 | public void AddPart(int id) 22 | { 23 | InfoPart.Add(id, new PartInfo()); 24 | } 25 | 26 | public PartInfo GetPart(int id) 27 | { 28 | return InfoPart[id]; 29 | } 30 | } 31 | 32 | [ProtoContract(SkipConstructor = true)] 33 | public class PartInfo 34 | { 35 | [ProtoMember(1)] public int ColorID { get; set; } 36 | [ProtoMember(2)] public int MatID { get; set; } 37 | [ProtoMember(3)] public string Name { get; set; } 38 | [ProtoMember(4)] public string HEX_Type { get; set; } 39 | [ProtoMember(5)] public string PENTA_Type { get; set; } 40 | [ProtoMember(6)] public string TET_Type { get; set; } 41 | 42 | public PartInfo() 43 | { 44 | // Default data 45 | ColorID = 0; 46 | MatID = 0; 47 | Name = "blank"; 48 | HEX_Type = "blank"; 49 | PENTA_Type = "blank"; 50 | TET_Type = "blank"; 51 | } 52 | 53 | public void SetData(int colorid, int matid, string name, string[] FE_types) 54 | { 55 | ColorID = colorid; 56 | MatID = matid; 57 | Name = name; 58 | HEX_Type = FE_types[0]; 59 | PENTA_Type = FE_types[1]; 60 | TET_Type = FE_types[2]; 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/STAN_Database/Material.cs: -------------------------------------------------------------------------------- 1 | using ProtoBuf; 2 | using System.Collections.Generic; 3 | 4 | namespace STAN_Database 5 | { 6 | [ProtoContract(SkipConstructor = true)] 7 | public class Material 8 | { 9 | [ProtoMember(1)] public int ID { get; } 10 | [ProtoMember(2)] public string Type { get; set; } 11 | [ProtoMember(3)] public string Name { get; set; } 12 | [ProtoMember(4)] public double E { get; set; } 13 | [ProtoMember(5)] public double Poisson { get; set; } 14 | [ProtoMember(6)] public int ColorID { get; set; } 15 | 16 | // Solver properties 17 | private MatrixST ElasticMatrix; 18 | 19 | public Material(int id) 20 | { 21 | // Assign data 22 | ID = id; 23 | Type = "Elastic"; 24 | ColorID = ID % 9; 25 | 26 | // Default values of elastic properties 27 | E = -999; 28 | Poisson = -999; 29 | } 30 | 31 | public void SetElastic(double Young, double PoissonRatio) 32 | { 33 | // Set elastic properties 34 | E = Young; 35 | Poisson = PoissonRatio; 36 | 37 | // Calculate elastic D matrix 38 | ElasticMatrix = new MatrixST(6, 6); 39 | double lambda = (E * Poisson) / ((1 - 2 * Poisson) * (1 + Poisson)); 40 | double G = (0.5 * E) / (1 + Poisson); 41 | 42 | ElasticMatrix.SetFast(0, 0, lambda + (2 * G)); 43 | ElasticMatrix.SetFast(0, 1, lambda); 44 | ElasticMatrix.SetFast(0, 2, lambda); 45 | ElasticMatrix.SetFast(1, 0, lambda); 46 | ElasticMatrix.SetFast(1, 1, lambda + (2 * G)); 47 | ElasticMatrix.SetFast(1, 2, lambda); 48 | ElasticMatrix.SetFast(2, 0, lambda); 49 | ElasticMatrix.SetFast(2, 1, lambda); 50 | ElasticMatrix.SetFast(2, 2, lambda + (2 * G)); 51 | ElasticMatrix.SetFast(3, 3, G); 52 | ElasticMatrix.SetFast(4, 4, G); 53 | ElasticMatrix.SetFast(5, 5, G); 54 | 55 | 56 | } 57 | 58 | public MatrixST GetElastic() 59 | { 60 | return ElasticMatrix; 61 | } 62 | 63 | private double[] GetColor() 64 | { 65 | List Colors = new List 66 | { 67 | new double[3]{ 12, 197, 19 }, 68 | new double[3]{ 141, 245, 145 }, 69 | new double[3]{ 109, 232, 226 }, 70 | new double[3]{ 42, 85, 199 }, 71 | new double[3]{ 223, 232, 28 }, 72 | new double[3]{ 236, 134, 64 }, 73 | new double[3]{ 216, 52, 52 }, 74 | new double[3]{ 184, 61, 241 }, 75 | new double[3]{ 110, 10, 120 } 76 | }; 77 | return Colors[ColorID]; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/STAN_Database/Node.cs: -------------------------------------------------------------------------------- 1 | using ProtoBuf; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | 6 | namespace STAN_Database 7 | { 8 | [ProtoContract(SkipConstructor = true)] 9 | public class Node 10 | { 11 | [ProtoMember(1)] public int ID { get; } 12 | [ProtoMember(2)] public double X { get; } 13 | [ProtoMember(3)] public double Y { get; } 14 | [ProtoMember(4)] public double Z { get; } 15 | 16 | [ProtoMember(5)] public List EList; // List of Elements that contain this Node 17 | [ProtoMember(6)] public int[] DOF { get; set; } // Degrees of Freedom array 18 | 19 | [ProtoMember(7)] private List DispX; 20 | [ProtoMember(8)] private List DispY; 21 | [ProtoMember(9)] private List DispZ; 22 | public double[] dU; 23 | public double[] dU_buffer; 24 | 25 | public Node(string input) 26 | { 27 | CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); // Set format - comma issue in floats 28 | 29 | List data = new List(); // Initialize list to store 8-char columns 30 | 31 | for (int i = 0; i < input.Length / 8; i++) // Catch 8-char substrings form line 32 | { 33 | string text = input.Substring(i * 8, 8).Replace(" ", ""); // Remove whitespace chars 34 | 35 | if (!string.IsNullOrWhiteSpace(text)) 36 | { 37 | // Nastran .bdf format can use scientific notation without "e" (only "-" or "+") 38 | // Issue for double.Parse() 39 | // Substring may start with "-" for negative number 40 | 41 | if (!text.Contains("e") && !text.Contains("E")) // if not contains "e" or "E" 42 | { 43 | if (text.Substring(1).Contains("-")) // if "e-" is required 44 | { 45 | if (text[0] == '-') // if number is negative ("-" at start) 46 | { 47 | text = "-" + text.Substring(1).Replace("-", "e-"); 48 | } 49 | else text = text.Replace("-", "e-"); // if number is positive 50 | } 51 | 52 | if (text.Substring(1).Contains("+")) // if "e+" is required 53 | { 54 | text.Replace("+", "e+"); 55 | } 56 | } 57 | 58 | // Also it's possible that number starts with "." (without 0) in .bdf format - must be added to avoid exception 59 | if (text[0] == '.') text = "0" + text; 60 | 61 | data.Add(text); // Add modified string to list 62 | } 63 | } 64 | 65 | // Assign properties 66 | ID = int.Parse(data[1]); // Node ID - identification for Elements 67 | X = double.Parse(data[2], CultureInfo.InvariantCulture); // X position 68 | Y = double.Parse(data[3], CultureInfo.InvariantCulture); // Y position 69 | Z = double.Parse(data[4], CultureInfo.InvariantCulture); // Z position 70 | 71 | // Initialize Element List and DoF array 72 | EList = new List(); 73 | Initialize_EList(); 74 | DOF = new int[3]; 75 | 76 | // Initialize Displacement list and add Disp at time 0 77 | DispX = new List { 0 }; 78 | DispY = new List { 0 }; 79 | DispZ = new List { 0 }; 80 | } 81 | 82 | /// 83 | /// Initialize Element list that contain this Node. 84 | ///
If it was empty before Serializing then not pass through Protocol Buffers.
85 | ///
86 | public void Initialize_EList() 87 | { 88 | EList = new List(); 89 | } 90 | 91 | /// 92 | /// Node displacement initialization at time 0 93 | ///
Reset Node displacement list
94 | ///
95 | public void Initialize_StepZero() 96 | { 97 | // Initialize Displacement list and add Disp at time 0 98 | DispX = new List { 0 }; 99 | DispY = new List { 0 }; 100 | DispZ = new List { 0 }; 101 | dU = new double[3]; 102 | dU_buffer = new double[3]; 103 | } 104 | 105 | /// 106 | /// Initialize Displacement table for new increment. 107 | /// Displacements at the end of previous increment are used. 108 | /// 109 | public void Initialize_NewDisp(int inc) 110 | { 111 | DispX.Add(DispX[inc - 1]); 112 | DispY.Add(DispY[inc - 1]); 113 | DispZ.Add(DispZ[inc - 1]); 114 | dU = new double[3]; 115 | dU_buffer = new double[3]; 116 | } 117 | 118 | /// 119 | /// Get Node displacement at the end of increment 120 | /// 121 | /// inc 122 | /// - increment number 123 | /// dir 124 | /// - direction: X=0; Y=1; Z=2 125 | /// 126 | /// 127 | /// Value of displacement as double 128 | public double GetDisp(int inc, int dir) 129 | { 130 | double output = 0; 131 | if (dir == 0) output = DispX[inc]; 132 | if (dir == 1) output = DispY[inc]; 133 | if (dir == 2) output = DispZ[inc]; 134 | 135 | return output; 136 | } 137 | 138 | public double[] GetDispRange(int dir) 139 | { 140 | double min = 0; 141 | double max = 0; 142 | if (dir == 0) 143 | { 144 | foreach (double disp in DispX) 145 | { 146 | if (min > disp) min = disp; 147 | if (max < disp) max = disp; 148 | } 149 | } 150 | if (dir == 1) 151 | { 152 | foreach (double disp in DispY) 153 | { 154 | if (min > disp) min = disp; 155 | if (max < disp) max = disp; 156 | } 157 | } 158 | if (dir == 2) 159 | { 160 | foreach (double disp in DispZ) 161 | { 162 | if (min > disp) min = disp; 163 | if (max < disp) max = disp; 164 | } 165 | } 166 | return new double[2] { min, max }; 167 | } 168 | 169 | public void SetDisp(int inc, double[] disp) 170 | { 171 | DispX[inc] = disp[0]; 172 | DispY[inc] = disp[1]; 173 | DispZ[inc] = disp[2]; 174 | } 175 | 176 | public void Update_Displacement(int inc) 177 | { 178 | DispX[inc] += dU_buffer[0]; 179 | DispY[inc] += dU_buffer[1]; 180 | DispZ[inc] += dU_buffer[2]; 181 | } 182 | 183 | /// 184 | /// Number of analysis increments (results) 185 | /// 186 | public int GetIncrementNumb() 187 | { 188 | return DispX.Count - 1; 189 | } 190 | 191 | /// 192 | /// Add Element ID to list 193 | /// 194 | public void AddElement(int EID) 195 | { 196 | EList.Add(EID); 197 | } 198 | 199 | /// 200 | /// Removes duplicated Element ID from Element list 201 | /// 202 | public void RemoveElemDuplicates() 203 | { 204 | EList = EList.Distinct().ToList(); 205 | } 206 | 207 | /// 208 | /// Number of Elements that contains this Node 209 | /// 210 | public List GetElements() 211 | { 212 | return EList; 213 | } 214 | 215 | /// 216 | /// Assign DOF to Node 217 | /// 218 | public void SetDOF(int index) 219 | { 220 | DOF[0] = 3 * index; 221 | DOF[1] = 3 * index + 1; 222 | DOF[2] = 3 * index + 2; 223 | } 224 | 225 | public void ClearResults() 226 | { 227 | DispX = null; 228 | DispY = null; 229 | DispZ = null; 230 | } 231 | 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /src/STAN_Database/STAN_Database.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | x64 9 | bin\ 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/STAN_PrePost/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/STAN_PrePost/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/STAN_PrePost/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace STAN 10 | { 11 | /// 12 | /// Logika interakcji dla klasy App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/STAN_PrePost/BOX_Analysis.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 71 | 72 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 147 | 148 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /src/STAN_PrePost/BOX_Result.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Linq; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using STAN_Database; 7 | 8 | namespace STAN_PrePost 9 | { 10 | /// 11 | /// Logika interakcji dla klasy BOX_Result.xaml 12 | /// 13 | public partial class BOX_Result : UserControl 14 | { 15 | Functions Fun = new Functions(); 16 | ResultControl ResControl; 17 | Database DB; 18 | RenderInterface iRen; 19 | bool Initial_Load; 20 | 21 | public BOX_Result(ResultControl res, Database db, RenderInterface iren) 22 | { 23 | InitializeComponent(); 24 | ResControl = res; 25 | DB = db; 26 | iRen = iren; 27 | 28 | // Set changes as initial load - not update mesh 29 | Initial_Load = true; 30 | 31 | // Select current Result general type (Stress, strain, etc.) 32 | foreach (ComboBoxItem i in Result_ComboBox.Items) 33 | { 34 | if (ResControl.Result.Contains(i.Content.ToString())) 35 | { 36 | Result_ComboBox.SelectedItem = i; 37 | break; 38 | } 39 | } 40 | 41 | // Select current Result direction (XX, YY, XY, etc.) 42 | foreach (string i in ResultBox.Items) 43 | { 44 | if (i.ToString() == ResControl.Result) 45 | { 46 | ResultBox.SelectedItem = i; 47 | break; 48 | } 49 | } 50 | 51 | // Select current Result style ("Element Max", etc.) 52 | foreach (ComboBoxItem i in ResultStyle_ComboBox.Items) 53 | { 54 | if(i.Content.ToString() == ResControl.ResultStyle) 55 | { 56 | ResultStyle_ComboBox.SelectedItem = i; 57 | break; 58 | } 59 | } 60 | 61 | // Set Manual or Automatic range 62 | if (ResControl.ManualRange == true) 63 | { 64 | Manual_CheckBox.IsChecked = true; 65 | ResultManualWindow.IsEnabled = true; 66 | } 67 | else 68 | { 69 | Manual_CheckBox.IsChecked = false; 70 | ResultManualWindow.IsEnabled = false; 71 | } 72 | 73 | // Set Current analysis step 74 | Step.Content = ResControl.Step.ToString(); 75 | 76 | // Update Manual Range textboxes 77 | Update_RangeText(); 78 | 79 | 80 | // Set window as loaded - from now on the mesh will be updated 81 | Initial_Load = false; 82 | 83 | // Disable this window if there are no results in Database 84 | if(DB.AnalysisLib.GetIncNumb() > 0) 85 | { 86 | ResultWindow.IsEnabled = true; 87 | } 88 | else 89 | { 90 | ResultWindow.IsEnabled = false; 91 | } 92 | } 93 | 94 | private void Result_Changed(object sender, SelectionChangedEventArgs e) 95 | { 96 | if ((sender as ComboBox).Name == "Result_ComboBox") 97 | { 98 | // Clear ResultBox if exists 99 | if (ResultBox != null) 100 | { 101 | ResultBox.Items.Clear(); 102 | } 103 | 104 | // Catch selected Result type 105 | ComboBoxItem item = (ComboBoxItem) Result_ComboBox.SelectedItem; 106 | string type = item.Content.ToString(); 107 | 108 | if (type == "None") 109 | { 110 | ResControl.Result = "None"; 111 | } 112 | if (type == "Displacement") 113 | { 114 | ResultBox.Items.Add("Displacement X"); 115 | ResultBox.Items.Add("Displacement Y"); 116 | ResultBox.Items.Add("Displacement Z"); 117 | ResultBox.Items.Add("Total Displacement"); 118 | } 119 | if (type == "Stress") 120 | { 121 | ResultBox.Items.Add("von Mises Stress"); 122 | ResultBox.Items.Add("Stress P1"); 123 | ResultBox.Items.Add("Stress P2"); 124 | ResultBox.Items.Add("Stress P3"); 125 | ResultBox.Items.Add("Stress XX"); 126 | ResultBox.Items.Add("Stress YY"); 127 | ResultBox.Items.Add("Stress ZZ"); 128 | ResultBox.Items.Add("Stress XY"); 129 | ResultBox.Items.Add("Stress YZ"); 130 | ResultBox.Items.Add("Stress XZ"); 131 | } 132 | if (type == "Strain") 133 | { 134 | ResultBox.Items.Add("Effective Strain"); 135 | ResultBox.Items.Add("Strain P1"); 136 | ResultBox.Items.Add("Strain P2"); 137 | ResultBox.Items.Add("Strain P3"); 138 | ResultBox.Items.Add("Strain XX"); 139 | ResultBox.Items.Add("Strain YY"); 140 | ResultBox.Items.Add("Strain ZZ"); 141 | ResultBox.Items.Add("Strain XY"); 142 | ResultBox.Items.Add("Strain YZ"); 143 | ResultBox.Items.Add("Strain XZ"); 144 | } 145 | } 146 | 147 | if ((sender as ComboBox).Name == "ResultStyle_ComboBox") 148 | { 149 | ComboBoxItem item = (ComboBoxItem)ResultStyle_ComboBox.SelectedItem; 150 | ResControl.ResultStyle = item.Content.ToString(); 151 | } 152 | 153 | // Update Mesh 154 | ResControl = Fun.UpdateMesh(DB, iRen, ResControl); 155 | Update_RangeText(); 156 | } 157 | 158 | private void Result_SelectionChanged(object sender, SelectionChangedEventArgs e) 159 | { 160 | if (Initial_Load == false && ResultBox.Items.Count > 0) 161 | { 162 | // Catch selected result in ResultBox 163 | ResControl.Result = ResultBox.SelectedItem.ToString(); 164 | 165 | // Update View 166 | ResControl = Fun.UpdateMesh(DB, iRen, ResControl); 167 | Update_RangeText(); 168 | 169 | } 170 | } 171 | 172 | private void Manual_CheckBox_Click(object sender, RoutedEventArgs e) 173 | { 174 | bool status = (bool)(sender as CheckBox).IsChecked; 175 | 176 | if (status == true) 177 | { 178 | ResultManualWindow.IsEnabled = true; 179 | ResControl.ManualRange = true; 180 | } 181 | else 182 | { 183 | ResultManualWindow.IsEnabled = false; 184 | ResControl.ManualRange = false; 185 | 186 | if (Initial_Load == false) 187 | { 188 | ResControl = Fun.UpdateMesh(DB, iRen, ResControl); 189 | Update_RangeText(); 190 | } 191 | } 192 | } 193 | 194 | private void Manual_Range_Apply(object sender, RoutedEventArgs e) 195 | { 196 | if (double.TryParse(Manual_Min.Text, NumberStyles.Float, CultureInfo.InvariantCulture, out _)) 197 | ResControl.ResultRange[0] = double.Parse(Manual_Min.Text, CultureInfo.InvariantCulture); 198 | 199 | if (double.TryParse(Manual_Max.Text, NumberStyles.Float, CultureInfo.InvariantCulture, out _)) 200 | ResControl.ResultRange[1] = double.Parse(Manual_Max.Text, CultureInfo.InvariantCulture); 201 | 202 | ResControl = Fun.UpdateMesh(DB, iRen, ResControl); 203 | } 204 | 205 | private void StepClick(object sender, RoutedEventArgs e) 206 | { 207 | // Hide BC actors 208 | foreach (BoundaryCondition bc in DB.BCLib.Values) bc.HideActor(); 209 | 210 | string s = (sender as Button).Name.ToString(); 211 | if (s.Contains("NextStep")) 212 | { 213 | int step = int.Parse(Step.Content.ToString()); 214 | if (step < DB.AnalysisLib.GetIncNumb()) 215 | { 216 | ResControl.Step = step + 1; 217 | Step.Content = (step + 1).ToString(); 218 | ResControl = Fun.UpdateMesh(DB, iRen, ResControl); 219 | Update_RangeText(); 220 | } 221 | } 222 | if (s.Contains("PrevStep")) 223 | { 224 | int step = int.Parse(Step.Content.ToString()); 225 | if (step > 0) 226 | { 227 | ResControl.Step = step - 1; 228 | Step.Content = (step - 1).ToString(); 229 | ResControl = Fun.UpdateMesh(DB, iRen, ResControl); 230 | Update_RangeText(); 231 | } 232 | } 233 | } 234 | 235 | private void Update_RangeText() 236 | { 237 | if (ResControl.ManualRange == false) 238 | { 239 | // Set data format 240 | string format = "e3"; 241 | 242 | // Set text in Manual Result range boxes 243 | if (ResControl.ResultRange[1] >= 1e-3) 244 | { 245 | if (ResControl.ResultRange[1] >= 1e-1) 246 | { 247 | format = "f2"; 248 | } 249 | else 250 | { 251 | format = "f4"; 252 | } 253 | } 254 | 255 | Manual_Min.Text = ResControl.ResultRange[0].ToString(format, CultureInfo.InvariantCulture); 256 | Manual_Max.Text = ResControl.ResultRange[1].ToString(format, CultureInfo.InvariantCulture); 257 | 258 | } 259 | } 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /src/STAN_PrePost/ExportWindow.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 15 |