├── pyframe3dd ├── __init__.py ├── meson.build └── src │ ├── Makefile │ ├── microstran │ ├── config.h │ └── vec3.h │ ├── common.h │ ├── coordtrans.h │ ├── eig.h │ ├── py_eig.h │ ├── py_structs.h │ ├── HPGutil.h │ ├── NRutil.h │ ├── coordtrans.c │ ├── HPGutil.c │ ├── frame3dd.h │ ├── py_frame3dd.h │ ├── py_io.h │ ├── HPGmatrix.h │ ├── py_HPGmatrix.h │ ├── preframe.c │ ├── eig.c │ └── py_eig.c ├── environment.yml ├── .github ├── tools │ └── cibw_repair_wheel_command_windows.sh ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── Publish_pyFrame3DD.yml │ └── CI_pyFrame3DD.yml ├── .gitignore ├── meson_options.txt ├── meson.build ├── README.md ├── test ├── test_beam_theory.py └── test_breakdown.py ├── pyproject.toml └── examples ├── exB.3dd └── exB.py /pyframe3dd/__init__.py: -------------------------------------------------------------------------------- 1 | from .pyframe3dd import Frame, StaticLoadCase, NodeData, ReactionData, ElementData, Options 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | channels: 2 | - conda-forge 3 | - defaults 4 | 5 | dependencies: 6 | - meson 7 | - meson-python 8 | - ninja 9 | - numpy 10 | - pip 11 | - python 12 | - pytest 13 | -------------------------------------------------------------------------------- /.github/tools/cibw_repair_wheel_command_windows.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -x 5 | 6 | WHEEL=$1 7 | DEST_DIR=$2 8 | 9 | python -m pip install delvewheel 10 | python -m delvewheel show "$WHEEL" && python -m delvewheel repair -w "$DEST_DIR" "$WHEEL" --no-mangle-all 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | # Description of feature 11 | Describe the feature here and provide some context. Under what scenario would this be useful? 12 | 13 | # Potential solution 14 | Can you think of ways to implement this? -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | frame3dd 3 | .DS_Store 4 | 5 | # C extensions 6 | *.so 7 | *.o 8 | *.dSYM 9 | 10 | # Packages 11 | *.egg 12 | *.egg-info 13 | dist 14 | build 15 | eggs 16 | parts 17 | bin 18 | var 19 | sdist 20 | develop-eggs 21 | .installed.cfg 22 | lib 23 | lib64 24 | 25 | # Installer logs 26 | pip-log.txt 27 | 28 | # Unit test / coverage reports 29 | .coverage 30 | .tox 31 | nosetests.xml 32 | 33 | # Translations 34 | *.mo 35 | 36 | # Mr Developer 37 | .mr.developer.cfg 38 | .project 39 | .pydevproject 40 | 41 | # Emacs 42 | *~ 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Description 11 | _Describe the bug here_ 12 | 13 | ### Steps to reproduce issue 14 | _Please provide a minimum working example (MWE) if possible_ 15 | 16 | 1. … 17 | 2. … 18 | 3. … 19 | 20 | ### Current behavior 21 | … 22 | 23 | ### Expected behavior 24 | … 25 | 26 | 27 | ### Code versions 28 | _List versions only if relevant_ 29 | - Python 30 | - … -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('incdir_numpy', type: 'string', value: '', 2 | description: 'Include directory for numpy. If left empty Meson will try to find it on its own.') 3 | 4 | option('python_target', type: 'string', value: '', 5 | description: '''Target python path. This is used in the case that the Python installation that PyOptSparse is intended 6 | to be built for is different than the Python installation that is used to run Meson. For example, Meson may be installed 7 | on the user's system which is run using the system Python installation, but the user may want build PyOptSparse for 8 | a Python installation in a virtual environment. Leave as an empty string to build for Python installation running 9 | Meson.''') 10 | -------------------------------------------------------------------------------- /pyframe3dd/meson.build: -------------------------------------------------------------------------------- 1 | python_sources = [ 2 | '__init__.py', 3 | 'pyframe3dd.py', 4 | ] 5 | 6 | py3.install_sources( 7 | python_sources, 8 | subdir: 'pyframe3dd', 9 | ) 10 | 11 | sources = [ 12 | 'src/HPGutil.h', 13 | 'src/HPGutil.c', 14 | 'src/coordtrans.h', 15 | 'src/coordtrans.c', 16 | 'src/NRutil.h', 17 | 'src/NRutil.c', 18 | 'src/py_io.h', 19 | 'src/py_io.c', 20 | 'src/py_eig.h', 21 | 'src/py_eig.c', 22 | 'src/py_structs.h', 23 | 'src/py_HPGmatrix.h', 24 | 'src/py_HPGmatrix.c', 25 | 'src/py_frame3dd.h', 26 | 'src/py_frame3dd.c', 27 | 'src/py_main.c', 28 | ] 29 | 30 | # We need to build a shared library NOT A PYTHON EXTENSION 31 | # The ctypes wrapper handles the extension part. 32 | # If the interface was done purely in C, then need the python extension. 33 | temp = shared_library( 34 | '_pyframe3dd', 35 | sources, 36 | name_prefix: '', 37 | include_directories: ['src','src/microstran'], 38 | install_dir: py3.get_install_dir() / 'pyframe3dd', 39 | install : true, 40 | ) 41 | -------------------------------------------------------------------------------- /pyframe3dd/src/Makefile: -------------------------------------------------------------------------------- 1 | CC ?= clang #gcc 2 | CFLAGS = -c -g -O2 -fPIC -Wall 3 | 4 | OBS = coordtrans.o HPGutil.o NRutil.o 5 | PYOBS = py_main.o py_io.o py_frame3dd.o py_eig.o py_HPGmatrix.o 6 | EOBS = main.o frame3dd.o frame3dd_io.o eig.o HPGmatrix.o 7 | 8 | ifeq ($(OS),Windows_NT) 9 | ARCHFLAGS=-D WIN64 10 | LIB := _pyframe3dd.dll 11 | LDFLAGS=-g -shared 12 | else 13 | UNAME_S := $(shell uname -s) 14 | ifeq ($(UNAME_S),Linux) 15 | ARCHFLAGS=-D LINUX 16 | LIB := _pyframe3dd.so 17 | LDFLAGS=-g -shared -Wl,-soname,$(LIB) 18 | endif 19 | ifeq ($(UNAME_S),Darwin) 20 | ARCHFLAGS=-D OSX 21 | LIB := _pyframe3dd.so 22 | LDFLAGS=-g -dynamiclib 23 | endif 24 | endif 25 | 26 | EXE = frame3dd 27 | 28 | all: shared exec 29 | 30 | %.o: %.c %.h 31 | $(CC) $(CFLAGS) -o $@ $< 32 | 33 | shared : $(OBS) $(PYOBS) 34 | $(CC) $(LDFLAGS) -o $(LIB) $(PYOBS) $(OBS) 35 | 36 | exec : $(EOBS) $(OBS) 37 | $(CC) -g -o $(EXE) $(EOBS) $(OBS) -lm 38 | 39 | clean: 40 | /bin/rm -rf $(OBS) $(EOBS) $(PYOBS) $(LIB) $(EXE) *~ *.pyc 41 | 42 | .PHONY: clean 43 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('pyframe3dd', 'c', 2 | meson_version: '>= 1.1', 3 | default_options: [ 4 | 'buildtype=debugoptimized', 5 | ], 6 | license : 'Apache') 7 | 8 | cc = meson.get_compiler('c') 9 | 10 | # We need -lm for all C code (assuming it uses math functions, which is safe to 11 | # assume for SciPy). For C++ it isn't needed, because libstdc++/libc++ is 12 | # guaranteed to depend on it. For Fortran code, Meson already adds `-lm`. 13 | m_dep = cc.find_library('m', required : false) 14 | if m_dep.found() 15 | add_project_link_arguments('-lm', language : 'c') 16 | endif 17 | 18 | is_windows = host_machine.system() == 'windows' 19 | add_project_arguments('-DANSI=1', language : 'c') 20 | if is_windows 21 | add_project_arguments('-D_WIN64=1', language : 'c') 22 | endif 23 | 24 | # https://mesonbuild.com/Python-module.html 25 | # Here we differentiate from the python used by meson, py3_command, and that python target, py3_target. This is useful 26 | # when cross compiling like on conda-forge 27 | py3 = import('python').find_installation(pure: false) 28 | py3_dep = py3.dependency() 29 | 30 | message(py3.path()) 31 | message(py3.get_install_dir()) 32 | 33 | subdir('pyframe3dd') 34 | -------------------------------------------------------------------------------- /pyframe3dd/src/microstran/config.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROSTRAN_CONFIG_H 2 | #define MICROSTRAN_CONFIG_H 3 | 4 | #ifdef __WIN32__ 5 | # define MSTRANP_EXPORT __declspec(dllexport) 6 | # define MSTRANP_IMPORT __declspec(dllimport) 7 | #else 8 | # ifdef HAVE_GCCVISIBILITY 9 | # define MSTRANP_EXPORT __attribute__ ((visibility("default"))) 10 | # define MSTRANP_IMPORT 11 | # else 12 | # define MSTRANP_EXPORT 13 | # define MSTRANP_IMPORT 14 | # endif 15 | #endif 16 | 17 | #ifdef HAVE_GCCVISIBILITY 18 | # define MSTRANP_LOCAL __attribute__ ((visibility("hidden"))) 19 | #else 20 | # define MSTRANP_LOCAL 21 | #endif 22 | 23 | #ifdef MSTRANP_BUILD 24 | # define MSTRANP_API extern MSTRANP_EXPORT 25 | # define MSTRANP_DLL MSTRANP_EXPORT 26 | #else 27 | # define MSTRANP_API extern MSTRANP_IMPORT 28 | # define MSTRANP_DLL MSTRANP_IMPORT 29 | #endif 30 | 31 | #if !defined(MSTRANP_API) || !defined(MSTRANP_EXPORT) || !defined(MSTRANP_IMPORT) 32 | # error "NO MSTRANP_API, MSTRANP_EXPORT, MSTRANP_IMPORT DEFINED" 33 | #endif 34 | 35 | #ifdef WIN32 36 | # define FRAME3DD_PATHSEP "\\" 37 | # define FRAME3DD_DEFAULT_DATA_DIR "c:\\Program Files\\FRAME3DD" 38 | #else 39 | # define FRAME3DD_DEFAULT_DATA_DIR "/home/john/frame3dd/src/microstran" 40 | # define FRAME3DD_PATHSEP "/" 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Delete the text explanations below these headers and replace them with information about your PR. 2 | Please first consult the [developer guide](https://weis.readthedocs.io/en/latest/how_to_contribute_code.html) to make sure your PR follows all code, testing, and documentation conventions. 3 | 4 | ## Purpose 5 | Explain the goal of this pull request. If it addresses an existing issue be sure to link to it. Describe the big picture of your changes here, perhaps using a bullet list if multiple changes are done to accomplish a single goal. If it accomplishes multiple goals, it may be best to create separate PR's for each. 6 | 7 | ## Type of change 8 | What types of change is it? 9 | _Select the appropriate type(s) that describe this PR_ 10 | 11 | - [ ] Bugfix (non-breaking change which fixes an issue) 12 | - [ ] New feature (non-breaking change which adds functionality) 13 | - [ ] Breaking change (non-backwards-compatible fix or feature) 14 | - [ ] Code style update (formatting, renaming) 15 | - [ ] Refactoring (no functional changes, no API changes) 16 | - [ ] Documentation update 17 | - [ ] Maintenance update 18 | - [ ] Other (please describe) 19 | 20 | ## Testing 21 | Explain the steps needed to test the new code to verify that it does indeed address the issue and produce the expected behavior. 22 | 23 | ## Checklist 24 | _Put an `x` in the boxes that apply._ 25 | 26 | - [ ] I have run existing tests which pass locally with my changes 27 | - [ ] I have added new tests or examples that prove my fix is effective or that my feature works 28 | - [ ] I have added necessary documentation -------------------------------------------------------------------------------- /pyframe3dd/src/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FRAME3DD: 3 | Static and dynamic structural analysis of 2D & 3D frames and trusses 4 | with elastic and geometric stiffness. 5 | --------------------------------------------------------------------------- 6 | http://frame3dd.sourceforge.net/ 7 | --------------------------------------------------------------------------- 8 | Copyright (C) 1992-2014 Henri P. Gavin 9 | 10 | FRAME3DD is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | FRAME3DD is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with FRAME3DD. If not, see . 22 | *//** @file 23 | */ 24 | 25 | #ifndef FRAME_COMMON_H 26 | #define FRAME_COMMON_H 27 | 28 | #define FRAME3DD_PATHMAX 512 29 | #ifndef MAXL 30 | #define MAXL 512 31 | #endif 32 | 33 | #define FILENMAX 128 34 | 35 | #ifndef VERSION 36 | #define VERSION "20140514+" 37 | #endif 38 | 39 | #ifndef PI 40 | #define PI 3.14159265358979323846264338327950288419716939937510 41 | #endif 42 | 43 | // Zvert=1: Z axis is vertical... rotate about Y-axis, then rotate about Z-axis 44 | // Zvert=0: Y axis is vertical... rotate about Z-axis, then rotate about Y-axis 45 | #define Zvert 1 46 | 47 | #endif /* FRAME_COMMON_H */ 48 | 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyFrame3DD 2 | 3 | Python bindings to [Frame3DD](http://frame3dd.sourceforge.net) 4 | 5 | ## Documentation 6 | 7 | Browse the [documentation for Frame3DD](http://svn.code.sourceforge.net/p/frame3dd/code/trunk/doc/Frame3DD-manual.html). This is a Python wrapper to that code with the following modifications: 8 | 9 | * Elimination of all input/output files in favor of direct variable passing 10 | * Arbitrary stiffness values can be passed in (rather than only rigid or free). ``ReactionData(node, Rx, Ry, Rz, Rxx, Ryy, Rzz, rigid=1)`` takes as input the optional parameter rigid (defaults to 1, which is what Frame3DD uses), which defines what number in the reaction inputs corresponds to a rigid connection. If a user wants to input spring constants in Rx, Ry, etc. those will be used directly in the stiffness matrix. The parameter ``rigid`` can then be set to anything else like ``-1``. 11 | * Frame3DD allows inclusion of concentrated masses but they only affect the modal analysis. In pyFrame3DD they also affect the loads. 12 | 13 | There is example code that shows usage contained in ``examples/exB.py``. This follows example (B) Pyramid Frame contained on the [Frame3DD home page](http://frame3dd.sourceforge.net). 14 | 15 | ## Prerequisites 16 | 17 | pyFrame3DD requires a C compiler 18 | 19 | ## Install (as a library) 20 | 21 | For detailed installation instructions of WISDEM modules see or to install pyFrame3DD by itself do: 22 | 23 | $ pip install WISDEM-pyFrame3DD 24 | 25 | 26 | ## Install (from source) 27 | 28 | If you would like to build the project locally from source for easier access to the underlying methods and tests, do: 29 | 30 | $ git clone https://github.com/WISDEM/pyFrame3DD.git 31 | $ cd pyFrame3DD 32 | $ pip install . 33 | 34 | If developer/editable mode, do the same `git clone` step, but on install do: 35 | 36 | $ pip install --no-build-isolation -e . 37 | 38 | The `--no-build-isolation` option is important per [Meson guidelines](https://meson-python.readthedocs.io/en/latest/how-to-guides/editable-installs.html). 39 | 40 | 41 | ## Unit Tests 42 | 43 | $ pytest test 44 | 45 | For software issues please use . For functionality and theory related questions and comments please use the NWTC forum for [Systems Engineering Software Questions](https://wind.nrel.gov/forum/wind/viewtopic.php?f=34&t=1002). 46 | 47 | 48 | ## License 49 | 50 | Frame3DD uses the GNU GPL so this code must also be under the same license. The larger WISDEM code has a special dispensation to use the Apache License. 51 | 52 | -------------------------------------------------------------------------------- /pyframe3dd/src/coordtrans.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FRAME3DD: 3 | Static and dynamic structural analysis of 2D and 3D frames and trusses with 4 | elastic and geometric stiffness. 5 | --------------------------------------------------------------------------- 6 | http://frame3dd.sourceforge.net/ 7 | --------------------------------------------------------------------------- 8 | Copyright (C) 1992-2009 Henri P. Gavin 9 | 10 | FRAME3DD is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | FRAME3DD is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with FRAME3DD. If not, see . 22 | *//** 23 | @file 24 | Coordinate transformations for the FRAME3DD solver API. 25 | */ 26 | #ifndef FRAME_COORDTRANS_H 27 | #define FRAME_COORDTRANS_H 28 | 29 | #include "microstran/vec3.h" 30 | 31 | #include "common.h" 32 | #include "HPGutil.h" 33 | 34 | 35 | /** 36 | COORD_TRANS - evaluate the 3D coordinate transformation coefficients 1dec04 37 | Default order of coordinate rotations... typical for Y as the vertical axis 38 | 1. rotate about the global Z axis 39 | 2. rotate about the global Y axis 40 | 3. rotate about the local x axis --- element 'roll' 41 | 42 | If Zvert is defined as 1, then the order of coordinate rotations is typical 43 | for Z as the vertical axis 44 | 1. rotate about the global Y axis 45 | 2. rotate about the global Z axis 46 | 3. rotate about the local x axis --- element 'roll' 47 | 48 | Q=TF; U=TD; T'T=I; Q=kU; TF=kTD; T'TF=T'kTD; T'kT = K; F=KD 49 | */ 50 | void coord_trans ( 51 | vec3 *xyz, // XYZ coordinate of all nodes 52 | double L, // length of all beam elements 53 | int n1, int n2, // node connectivity 54 | double *t1, double *t2, double *t3, double *t4, double *t5, 55 | double *t6, double *t7, double *t8, double *t9, // coord transformation 56 | float p // the roll angle (radians) 57 | ); 58 | 59 | /** 60 | ATMA - carry out the coordinate transformation 61 | */ 62 | void atma ( 63 | double t1, double t2, double t3, 64 | double t4, double t5, double t6, 65 | double t7, double t8, double t9, 66 | double **m, float r1, float r2 67 | ); 68 | 69 | #endif /* FRAME_COORDTRANS_H */ 70 | 71 | -------------------------------------------------------------------------------- /pyframe3dd/src/microstran/vec3.h: -------------------------------------------------------------------------------- 1 | /* FRAME3DD: Static and dynamic structural analysis of 2D & 3D frames and trusses 2 | Copyright (C) 2007-2008 John Pye 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | *//** 17 | @file 18 | 3D vector type and related functions/methods. 19 | */ 20 | #ifndef MSTRAP_VEC3_H 21 | #define MSTRAP_VEC3_H 22 | 23 | #include "config.h" 24 | #include 25 | 26 | #ifdef __cplusplus 27 | extern "C"{ 28 | #endif 29 | 30 | /** 31 | 3D vector type used by the microstran parser 32 | */ 33 | 34 | typedef struct vec3_struct{ 35 | double x, y, z; 36 | } vec3; 37 | 38 | MSTRANP_API const vec3 VEC3_ZERO; 39 | 40 | MSTRANP_API vec3 vec3_create(double x, double y, double z); 41 | MSTRANP_API double vec3_dot(vec3 A, vec3 B); 42 | MSTRANP_API vec3 vec3_add(vec3 A, vec3 B); 43 | MSTRANP_API vec3 vec3_cross(vec3 A, vec3 B); 44 | MSTRANP_API vec3 vec3_scale(vec3 A, double s); 45 | MSTRANP_API vec3 vec3_norm(vec3 A); 46 | MSTRANP_API double vec3_mod(vec3 A); 47 | MSTRANP_API vec3 vec3_negate(vec3 A); 48 | 49 | /** 50 | Vector difference/subtraction. 51 | @return the vector (A - B) 52 | */ 53 | MSTRANP_API vec3 vec3_diff(vec3 A, vec3 B); 54 | 55 | MSTRANP_API int vec3_print(FILE *f, vec3 A); 56 | 57 | MSTRANP_API vec3 vec3_rotate(vec3 A, vec3 axis, double theta); 58 | 59 | /** 60 | Calculate the angle between two vectors, in radians. 61 | */ 62 | MSTRANP_API double vec3_angle(vec3 A, vec3 B); 63 | 64 | /** 65 | Calculate the angle between two vectors, in radians. Also return 66 | the cross-product of the two vectors, useful with vec3_rotate. 67 | */ 68 | MSTRANP_API double vec3_angle_cross(vec3 A, vec3 B, vec3 *C); 69 | 70 | MSTRANP_API char vec3_equal(vec3 A, vec3 B); 71 | MSTRANP_API char vec3_equal_tol(vec3 A, vec3 B, double tol); 72 | 73 | char vec3_isnan(const vec3 *A); 74 | 75 | #define VEC3_PR(V) (fprintf(stderr,"%s = ",#V), vec3_print(stderr,V), fprintf(stderr,"\n")) 76 | 77 | #define VEC3_CHECK_NAN(V) (vec3_isnan(&(V)) ? (VEC3_PR(V), assert(!vec3_isnan(&(V)))) : 0) 78 | 79 | #define VEC3_ASSERT_EQUAL_TOL(X,Y,TOL) (vec3_equal_tol((X),(Y),TOL) ? 0 : (VEC3_PR(X), VEC3_PR(Y), assert(vec3_equal_tol((X),(Y),TOL)))) 80 | 81 | #define VEC3_NOT_EQUAL(X,Y) ((X).x!=(Y).x || (X).y!=(Y).y || (X).z!=(Y).z) 82 | 83 | #define VEC3_NOT_ZERO(X) ((X).x!=0 || (X).y!=0 || (X).z!=0) 84 | 85 | #ifdef __cplusplus 86 | }; 87 | #endif 88 | 89 | #endif 90 | 91 | -------------------------------------------------------------------------------- /.github/workflows/Publish_pyFrame3DD.yml: -------------------------------------------------------------------------------- 1 | name: Build and upload to PyPI 2 | # https://github.com/pypa/cibuildwheel/blob/main/examples/github-deploy.yml 3 | # Best comparable example: https://github.com/pdfo/pdfo 4 | 5 | # Build on every pull request (no need for every push) and release change: 6 | on: [pull_request, release] 7 | 8 | jobs: 9 | build_wheels: 10 | name: Build wheels on ${{ matrix.os }} 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | os: [ubuntu-latest, windows-latest, macos-13, macos-14] 16 | 17 | steps: 18 | - name: Install compiler 19 | if: false == contains( matrix.os, 'windows') 20 | id: install_cc 21 | uses: rlalik/setup-cpp-compiler@master 22 | with: 23 | compiler: clang 24 | 25 | - name: Install mingw-w64 on Windows 26 | if: contains( matrix.os, 'windows') 27 | uses: msys2/setup-msys2@v2 28 | with: 29 | path-type: inherit 30 | install: | 31 | mingw-w64-x86_64-gcc 32 | 33 | - name: Checkout 34 | uses: actions/checkout@v4 35 | 36 | - name: Build wheels mac and linux 37 | if: false == contains( matrix.os, 'windows') 38 | uses: pypa/cibuildwheel@v2.17.0 39 | env: 40 | CC: ${{ steps.install_cc.outputs.cc }} 41 | CXX: ${{ steps.install_cc.outputs.cxx }} 42 | 43 | - name: Build wheels windows 44 | if: contains( matrix.os, 'windows') 45 | uses: pypa/cibuildwheel@v2.17.0 46 | 47 | - uses: actions/upload-artifact@v4 48 | with: 49 | name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} 50 | path: ./wheelhouse/*.whl 51 | 52 | build_sdist: 53 | name: Build source distribution 54 | runs-on: ubuntu-latest 55 | steps: 56 | - uses: actions/checkout@v4 57 | 58 | - name: Build sdist 59 | run: pipx run build --sdist 60 | 61 | - uses: actions/upload-artifact@v4 62 | with: 63 | name: cibw-sdist 64 | path: dist/*.tar.gz 65 | 66 | upload_pypi: 67 | needs: [build_wheels, build_sdist] 68 | runs-on: ubuntu-latest 69 | environment: pypi 70 | permissions: 71 | id-token: write # IMPORTANT: this permission is mandatory for trusted publishing 72 | # upload to PyPI on every tag starting with 'v' 73 | #if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') 74 | # alternatively, to publish when a GitHub Release is created, use the following rule: 75 | if: github.event_name == 'release' && github.event.action == 'published' 76 | steps: 77 | - uses: actions/download-artifact@v4 78 | with: 79 | # unpacks all CIBW artifacts into dist/ 80 | pattern: cibw-* 81 | path: dist 82 | merge-multiple: true 83 | 84 | - name: Upload to PyPI 85 | uses: pypa/gh-action-pypi-publish@release/v1 86 | #with: 87 | # user: __token__ 88 | # password: ${{ secrets.pypi_password }} 89 | # # To test: repository_url: https://test.pypi.org/legacy/ 90 | 91 | -------------------------------------------------------------------------------- /pyframe3dd/src/eig.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FRAME3DD: 3 | Static and dynamic structural analysis of 2D and 3D frames and trusses with 4 | elastic and geometric stiffness. 5 | --------------------------------------------------------------------------- 6 | http://frame3dd.sourceforge.net/ 7 | --------------------------------------------------------------------------- 8 | Copyright (C) 1992-2009 Henri P. Gavin 9 | 10 | FRAME3DD is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | FRAME3DD is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with FRAME3DD. If not, see . 22 | *//** @file 23 | Routines to solve the generalized eigenvalue problem 24 | 25 | H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 1 March 2007 26 | Bathe, Finite Element Procecures in Engineering Analysis, Prentice Hall, 1982 27 | */ 28 | #ifndef FRAME_EIG_H 29 | #define FRAME_EIG_H 30 | 31 | /** 32 | Find the lowest m eigenvalues, w, and eigenvectors, V, of the 33 | general eigenproblem, K V = w M V, using sub-space / Jacobi iteration. 34 | 35 | @param K is an n by n symmetric real (stiffness) matrix 36 | @param M is an n by n symmetric positive definate real (mass) matrix 37 | @param w is a diagonal matrix of eigen-values 38 | @param V is a rectangular matrix of eigen-vectors 39 | */ 40 | void subspace( 41 | double **K, double **M, /**< stiffness and mass matrices */ 42 | int n, int m, /**< DoF and number of required modes */ 43 | double *w, double **V, /**< modal frequencies and mode shapes */ 44 | double tol, /**< covergence tolerence */ 45 | double shift, /**< frequency shift for unrestrained frames */ 46 | int *iter, /**< number of sub-space iterations */ 47 | int *ok, /**< Sturm check result */ 48 | int verbose /**< 1: copious screen output, 0: none */ 49 | ); 50 | 51 | 52 | /** 53 | carry out matrix-matrix-matrix multiplication for symmetric A 54 | C = X' A X C is J by J X is N by J A is N by N 55 | */ 56 | void xtAx( double **A, double **X, double **C, int N, int J ); 57 | 58 | /** 59 | calculate the lowest m eigen-values and eigen-vectors of the 60 | generalized eigen-problem, K v = w M v, using a matrix 61 | iteration approach with shifting. 62 | 63 | @param n number of degrees of freedom 64 | @param m number of required modes 65 | */ 66 | void stodola( 67 | double **K, double **M, /**< stiffness and mass matrices */ 68 | int n, int m, /**< DoF and number of required modes */ 69 | double *w, double **V, /**< modal frequencies and mode shapes */ 70 | double tol, /**< covergence tolerence */ 71 | double shift, /**< frequency shift for unrestrained frames */ 72 | int *iter, /**< number of sub-space iterations */ 73 | int *ok, /**< Sturm check result */ 74 | int verbose /**< 1: copious screen output, 0: none */ 75 | ); 76 | 77 | #endif /* FRAME_EIG_H */ 78 | 79 | -------------------------------------------------------------------------------- /pyframe3dd/src/py_eig.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FRAME3DD: 3 | Static and dynamic structural analysis of 2D and 3D frames and trusses with 4 | elastic and geometric stiffness. 5 | --------------------------------------------------------------------------- 6 | http://frame3dd.sourceforge.net/ 7 | --------------------------------------------------------------------------- 8 | Copyright (C) 1992-2009 Henri P. Gavin 9 | 10 | FRAME3DD is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | FRAME3DD is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with FRAME3DD. If not, see . 22 | *//** @file 23 | Routines to solve the generalized eigenvalue problem 24 | 25 | H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 1 March 2007 26 | Bathe, Finite Element Procecures in Engineering Analysis, Prentice Hall, 1982 27 | */ 28 | #ifndef PYFRAME_EIG_H 29 | #define PYFRAME_EIG_H 30 | 31 | /** 32 | Find the lowest m eigenvalues, w, and eigenvectors, V, of the 33 | general eigenproblem, K V = w M V, using sub-space / Jacobi iteration. 34 | 35 | @param K is an n by n symmetric real (stiffness) matrix 36 | @param M is an n by n symmetric positive definate real (mass) matrix 37 | @param w is a diagonal matrix of eigen-values 38 | @param V is a rectangular matrix of eigen-vectors 39 | */ 40 | int subspace( 41 | double **K, double **M, /**< stiffness and mass matrices */ 42 | int n, int m, /**< DoF and number of required modes */ 43 | double *w, double **V, /**< modal frequencies and mode shapes */ 44 | double tol, /**< covergence tolerence */ 45 | double shift, /**< frequency shift for unrestrained frames */ 46 | int *iter, /**< number of sub-space iterations */ 47 | int *ok, /**< Sturm check result */ 48 | int verbose /**< 1: copious screen output, 0: none */ 49 | ); 50 | 51 | 52 | /** 53 | carry out matrix-matrix-matrix multiplication for symmetric A 54 | C = X' A X C is J by J X is N by J A is N by N 55 | */ 56 | void xtAx( double **A, double **X, double **C, int N, int J ); 57 | 58 | /** 59 | calculate the lowest m eigen-values and eigen-vectors of the 60 | generalized eigen-problem, K v = w M v, using a matrix 61 | iteration approach with shifting. 62 | 63 | @param n number of degrees of freedom 64 | @param m number of required modes 65 | */ 66 | int stodola( 67 | double **K, double **M, /**< stiffness and mass matrices */ 68 | int n, int m, /**< DoF and number of required modes */ 69 | double *w, double **V, /**< modal frequencies and mode shapes */ 70 | double tol, /**< covergence tolerence */ 71 | double shift, /**< frequency shift for unrestrained frames */ 72 | int *iter, /**< number of sub-space iterations */ 73 | int *ok, /**< Sturm check result */ 74 | int verbose /**< 1: copious screen output, 0: none */ 75 | ); 76 | 77 | #endif /* FRAME_EIG_H */ 78 | 79 | -------------------------------------------------------------------------------- /pyframe3dd/src/py_structs.h: -------------------------------------------------------------------------------- 1 | /* ---------------- 2 | S. Andrew Ning 3 | Nov 1, 2013 4 | Structs used for passing variables in/out from Python (or from other C code) 5 | ---------------- */ 6 | 7 | 8 | // -------------- 9 | // General Inputs 10 | // -------------- 11 | 12 | typedef struct { 13 | 14 | int nN; 15 | int *N; 16 | double *x, *y, *z, *r; 17 | 18 | } Nodes; 19 | 20 | 21 | typedef struct { 22 | 23 | int nK; 24 | int* N; 25 | double *Kx, *Ky, *Kz, *Ktx, *Kty, *Ktz; 26 | double rigid; 27 | 28 | } Reactions; 29 | 30 | 31 | typedef struct { 32 | 33 | int nE; 34 | int *EL, *N1, *N2; 35 | double *Ax, *Asy, *Asz, *Jx, *Iy, *Iz, *E, *G, *roll, *density; 36 | 37 | } Elements; 38 | 39 | 40 | typedef struct { 41 | 42 | int shear, geom; 43 | double exagg_static, dx; 44 | 45 | } OtherElementData; 46 | 47 | 48 | // -------------- 49 | // Load Inputs 50 | // -------------- 51 | 52 | 53 | typedef struct { 54 | int nF; 55 | int *N; 56 | double *Fx, *Fy, *Fz, *Mxx, *Myy, *Mzz; 57 | 58 | } PointLoads; 59 | 60 | 61 | typedef struct { 62 | int nU; 63 | int *EL; 64 | double *Ux, *Uy, *Uz; 65 | 66 | } UniformLoads; 67 | 68 | 69 | typedef struct { 70 | int nW; 71 | int *EL; 72 | double *xx1, *xx2, *wx1, *wx2; 73 | double *xy1, *xy2, *wy1, *wy2; 74 | double *xz1, *xz2, *wz1, *wz2; 75 | 76 | } TrapezoidalLoads; 77 | 78 | 79 | typedef struct { 80 | int nP; 81 | int *EL; 82 | double *Px, *Py, *Pz, *x; 83 | 84 | } ElementLoads; 85 | 86 | 87 | typedef struct { 88 | int nT; 89 | int *EL; 90 | double *a, *hy, *hz, *Typ, *Tym, *Tzp, *Tzm; 91 | 92 | } TemperatureLoads; 93 | 94 | 95 | typedef struct { 96 | int nD; 97 | int *N; 98 | double *Dx, *Dy, *Dz, *Dxx, *Dyy, *Dzz; 99 | 100 | } PrescribedDisplacements; 101 | 102 | 103 | typedef struct{ 104 | 105 | double gx, gy, gz; 106 | PointLoads pointLoads; 107 | UniformLoads uniformLoads; 108 | TrapezoidalLoads trapezoidalLoads; 109 | ElementLoads elementLoads; 110 | TemperatureLoads temperatureLoads; 111 | PrescribedDisplacements prescribedDisplacements; 112 | 113 | } LoadCase; 114 | 115 | 116 | // -------------- 117 | // Dynamic Inputs 118 | // -------------- 119 | 120 | 121 | typedef struct { 122 | int nM; 123 | int Mmethod, lump; 124 | double tol, shift, exagg_modal; 125 | 126 | } DynamicData; 127 | 128 | 129 | typedef struct { 130 | int nI; 131 | int *N; 132 | double *EMs, *EMx, *EMy, *EMz, *EMxy, *EMxz, *EMyz; 133 | double *rhox, *rhoy, *rhoz; 134 | 135 | } ExtraInertia; 136 | 137 | 138 | typedef struct { 139 | int nX; 140 | int *EL; 141 | double *EMs; 142 | 143 | } ExtraMass; 144 | 145 | 146 | typedef struct { 147 | int Cmethod, nC; 148 | int *N; 149 | double *cx, *cy, *cz, *cxx, *cyy, *czz; 150 | int *m; 151 | 152 | } Condensation; 153 | 154 | 155 | 156 | // -------------- 157 | // Static Data Outputs 158 | // -------------- 159 | 160 | 161 | typedef struct{ 162 | 163 | int *node; 164 | double *x, *y, *z, *xrot, *yrot, *zrot; 165 | 166 | } Displacements; 167 | 168 | 169 | typedef struct{ 170 | 171 | int *element; 172 | int *node; 173 | double *Nx, *Vy, *Vz, *Txx, *Myy, *Mzz; 174 | 175 | } Forces; 176 | 177 | 178 | typedef struct{ 179 | 180 | int *node; 181 | double *Fx, *Fy, *Fz, *Mxx, *Myy, *Mzz; 182 | 183 | } ReactionForces; 184 | 185 | 186 | // -------------- 187 | // Internal Force Outputs 188 | // -------------- 189 | 190 | 191 | typedef struct { 192 | 193 | double *x, *Nx, *Vy, *Vz, *Tx, *My, *Mz, *Dx, *Dy, *Dz, *Rx; 194 | 195 | } InternalForces; 196 | 197 | 198 | 199 | 200 | // -------------- 201 | // Modal Outputs 202 | // -------------- 203 | 204 | 205 | typedef struct { 206 | double *total_mass, *struct_mass; 207 | int *N; 208 | double *xmass, *ymass, *zmass, *xinrta, *yinrta, *zinrta; 209 | 210 | } MassResults; 211 | 212 | typedef struct { 213 | double *freq; 214 | double *xmpf, *ympf, *zmpf; 215 | int *N; 216 | double *xdsp, *ydsp, *zdsp, *xrot, *yrot, *zrot; 217 | 218 | } ModalResults; 219 | 220 | 221 | -------------------------------------------------------------------------------- /pyframe3dd/src/HPGutil.h: -------------------------------------------------------------------------------- 1 | /* hpgUtils.h --- library of general-purpose utility functions */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define MAXL 512 9 | 10 | #define ANSI_SYS 1 /* compile for ANSI_SYS driver; 0: don't */ 11 | // ... requires ANSI.SYS and the line DEVICE = C:\ANSI.SYS in C:\CONFIG.SYS 12 | 13 | 14 | /* --------------------------------------------------------------------------- 15 | COLOR - change color on the screen ... 16 | Screen Color Scheme : 0 = white on black, 1 = bright 17 | first digit= 3 for text color first digit= 4 for background color 18 | second digit codes: 1=red, 2=green, 3=gold, 4=blue, 5=purple, 6=lght blue 19 | ---------------------------------------------------------------------------- */ 20 | void color ( const int colorCode ); /* change the screen color */ 21 | 22 | 23 | /* --------------------------------------------------------------------------- 24 | TEXTCOLOR - change color of text and background 25 | tColor : text color : one of 'k' 'r' 'g' 'y' 'b' 'm' 'c' 'w' 26 | bColor : back color : one of 'k' 'r' 'g' 'y' 'b' 'm' 'c' 'w' 27 | nbf : 'n' = normal, 'b' = bright/bold, 'f' = faint 28 | uline : 'u' = underline 29 | http://en.wikipedia.org/wiki/ANSI_escape_code 30 | --------------------------------------------------------------------------- */ 31 | void textColor ( const char tColor, const char bColor, const char nbf, const char uline ); 32 | 33 | 34 | /* --------------------------------------------------------------------------- 35 | ERRORMSG - write a diagnostic error message in color 36 | ---------------------------------------------------------------------------- */ 37 | void errorMsg ( const char *errString ); 38 | 39 | 40 | /* ------------------------------------------------------------------------- 41 | OPENFILE - open a file or print a diagnostic error message 42 | ---------------------------------------------------------------------------- */ 43 | FILE *openFile (const char *path, const char *fileName, const char *mode, char *usage ); 44 | 45 | 46 | /* --------------------------------------------------------------------------- 47 | SCANLINE - scan through a line until a 'a' is reached, like getline() 3feb94 48 | ---------------------------------------------------------------------------- */ 49 | int scanLine ( FILE *fp, int lim, char *s, const char a ); 50 | 51 | 52 | /* --------------------------------------------------------------------------- 53 | SCANLABEL - scan through a line until a '"' is reached, like getline() 54 | ---------------------------------------------------------------------------- */ 55 | int scanLabel ( FILE *fp, int lim, char *s, const char a ); 56 | 57 | int scanFile ( FILE *fp, int head_lines, int start_chnl, int stop_chnl ); 58 | 59 | 60 | /* --------------------------------------------------------------------------- 61 | * GETLINE - get line form a stream into a character string, return length 62 | * from K&R 3feb94 63 | * --------------------------------------------------------------------------- 64 | */ 65 | int getLine ( FILE *fp, int lim, char *s ); 66 | 67 | 68 | /* --------------------------------------------------------------------------- 69 | * getTime parse a numeric time string of YYYYMMDDhhmmss 70 | * The input variables y, m, d, hr, mn, sc are the indices of the string s[] 71 | * which start the YYYY, MM, DD, hh, mm, ss sections of the time string. 72 | * An offset (os) in seconds is added to allow for correction between 73 | * time zones, UTC and GPS times. 74 | * The corresponding time is returned in "time_t" format. 75 | * --------------------------------------------------------------------------- 76 | */ 77 | time_t getTime( char s[], int y, int m, int d, int hr, int mn, int sc, int os ); 78 | 79 | 80 | /* --------------------------------------------------------------------------- 81 | SHOW_PROGRESS - show the progress of long computations 82 | --------------------------------------------------------------------------- */ 83 | void showProgress ( int i, int n, int count ); 84 | 85 | 86 | /* --------------------------------------------------------------------------- 87 | * SFERR - Display error message upon an erronous *scanf operation 88 | * ------------------------------------------------------------------------- */ 89 | void sferr ( char s[] ); 90 | -------------------------------------------------------------------------------- /test/test_beam_theory.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | """ 4 | untitled.py 5 | 6 | Created by Andrew Ning on 2013-11-04. 7 | Copyright (c) NREL. All rights reserved. 8 | """ 9 | 10 | import unittest 11 | import numpy as np 12 | 13 | from pyframe3dd import Frame, NodeData, ReactionData, ElementData, Options, StaticLoadCase 14 | 15 | 16 | class FrameTestEXA(unittest.TestCase): 17 | 18 | def testFixedFree_FreeFree(self): 19 | 20 | # nodes 21 | nn = 11 22 | node = np.arange(1, nn+1, dtype=np.int_ ) 23 | x = y = r = np.zeros(nn) 24 | z = np.linspace(0, 100, nn) 25 | nodes = NodeData(node, x, y, z, r) 26 | 27 | # reactions 28 | rnode = np.array( [1], dtype=np.int_ ) 29 | Kx = Ky = Kz = Ktx = Kty = Ktz = np.ones(1) 30 | rigid = 1 31 | reactions = ReactionData(rnode, Kx, Ky, Kz, Ktx, Kty, Ktz, rigid) 32 | 33 | # reactions 34 | rnode = np.array( [], dtype=np.int_ ) 35 | Kx = Ky = Kz = Ktx = Kty = Ktz = rnode #np.zeros(1) 36 | reactions0 = ReactionData(rnode, Kx, Ky, Kz, Ktx, Kty, Ktz, rigid) 37 | 38 | # elements 39 | ne = nn-1 40 | EL = np.arange(1, ne+1, dtype=np.int_ ) 41 | N1 = np.arange(1, nn, dtype=np.int_ ) 42 | N2 = np.arange(2, nn+1, dtype=np.int_ ) 43 | Ax = Jx = Iy = Iz = 10*np.ones(ne) 44 | Asy = Asz = 8*np.ones(ne) 45 | E = 2e6*np.ones(ne) 46 | G = 1e6*np.ones(ne) 47 | roll = np.zeros(ne) 48 | rho = 1e-5*np.ones(ne) 49 | elements = ElementData(EL, N1, N2, Ax, Asy, Asz, Jx, Iy, Iz, E, G, roll, rho) 50 | 51 | # parameters 52 | shear = False # 1: include shear deformation 53 | geom = False # 1: include geometric stiffness 54 | dx = -1.0 # x-axis increment for internal forces 55 | options = Options(shear, geom, dx) 56 | 57 | #### Fixed-free 58 | frame = Frame(nodes, reactions, elements, options) 59 | 60 | # dynamics 61 | nM = 15 # number of desired dynamic modes of vibration 62 | Mmethod = 1 # 1: subspace Jacobi 2: Stodola 63 | lump = 0 # 0: consistent mass ... 1: lumped mass matrix 64 | tol = 1e-9 # mode shape tolerance 65 | shift = -1e3 # shift value ... for unrestrained structures 66 | frame.enableDynamics(nM, Mmethod, lump, tol, shift) 67 | 68 | # load cases 1 69 | gx = 0.0 70 | gy = 0.0 71 | gz = -980.6 72 | 73 | load = StaticLoadCase(gx, gy, gz) 74 | 75 | frame.addLoadCase(load) 76 | 77 | displacements, forces, rxns, internalForces, mass, modal = frame.run() 78 | 79 | L = z.max() - z.min() 80 | beta = np.array([1.875194, 4.69361268, 7.85429819]) 81 | anal = beta**2 / L**2 * np.sqrt( E[0]*Iy[0] / (rho[0]*Ax[0])) / np.pi / 2 82 | 83 | self.assertAlmostEqual(modal.freq[0], anal[0], 1) 84 | self.assertAlmostEqual(modal.freq[1], anal[0], 1) 85 | self.assertAlmostEqual(modal.freq[2], anal[1], 0) 86 | self.assertAlmostEqual(modal.freq[3], anal[1], 0) 87 | self.assertAlmostEqual(modal.freq[4], anal[2], -1) 88 | self.assertAlmostEqual(modal.freq[5], anal[2], -1) 89 | 90 | 91 | 92 | #### Free-free 93 | frame0 = Frame(nodes, reactions0, elements, options) 94 | frame0.enableDynamics(nM, Mmethod, lump, tol, shift) 95 | frame0.addLoadCase(load) 96 | displacements, forces, rxns, internalForces, mass, modal = frame0.run(nanokay=True) 97 | 98 | beta = np.array([4.72969344, 7.85302489, 10.99545361]) 99 | anal = beta**2 / L**2 * np.sqrt( E[0]*Iy[0] / (rho[0]*Ax[0])) / np.pi / 2 100 | freq = modal.freq 101 | freq = freq[freq>1e-1] 102 | self.assertAlmostEqual(freq[0], anal[0], -1) 103 | self.assertAlmostEqual(freq[1], anal[0], -1) 104 | self.assertAlmostEqual(freq[2], anal[1], -1) 105 | self.assertAlmostEqual(freq[3], anal[1], -1) 106 | self.assertAlmostEqual(freq[4], anal[2], -2) 107 | self.assertAlmostEqual(freq[5], anal[2], -2) 108 | 109 | 110 | if __name__ == '__main__': 111 | unittest.main() 112 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["numpy", "ninja", "meson>=1.1", "meson-python", "wheel"] 3 | build-backend = "mesonpy" 4 | 5 | [project] 6 | name = "WISDEM-pyFrame3DD" 7 | version = "1.1.1" 8 | description = "Python bindings to Frame3DD, a code for static and dynamic structural analysis of 2D and 3D frames and trusses, with permission from Prof Henri Gavin" 9 | readme = "README.md" 10 | requires-python = ">=3.9" 11 | license = {text = "GPL-3.0-only"} 12 | keywords = ["wind", "turbine", "mdao", "design", "optimization"] 13 | authors = [ 14 | {name = "NREL WISDEM Team", email = "systems.engineering@nrel.gov" } 15 | ] 16 | maintainers = [ 17 | {name = "NREL WISDEM Team", email = "systems.engineering@nrel.gov" } 18 | ] 19 | classifiers = [ # Optional 20 | # How mature is this project? Common values are 21 | # 3 - Alpha 22 | # 4 - Beta 23 | # 5 - Production/Stable 24 | "Development Status :: 4 - Beta", 25 | 26 | # Indicate who your project is intended for 27 | "Intended Audience :: Science/Research", 28 | "Topic :: Scientific/Engineering", 29 | 30 | "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", 31 | 32 | # Specify the Python versions you support here. In particular, ensure 33 | # that you indicate you support Python 3. These classifiers are *not* 34 | # checked by "pip install". See instead "python_requires" below. 35 | "Programming Language :: Python :: 3", 36 | "Programming Language :: Python :: 3.9", 37 | "Programming Language :: Python :: 3.10", 38 | "Programming Language :: Python :: 3.11", 39 | "Programming Language :: Python :: 3.12", 40 | "Programming Language :: Python :: 3 :: Only", 41 | "Programming Language :: C", 42 | "Operating System :: Microsoft :: Windows", 43 | "Operating System :: POSIX :: Linux", 44 | "Operating System :: POSIX", 45 | "Operating System :: Unix", 46 | "Operating System :: MacOS", 47 | ] 48 | 49 | dependencies = [ 50 | "numpy", 51 | ] 52 | 53 | # List additional groups of dependencies here (e.g. development 54 | # dependencies). Users will be able to install these using the "extras" 55 | # syntax, for example: 56 | # 57 | # $ pip install sampleproject[dev] 58 | # 59 | # Similar to `dependencies` above, these must be valid existing 60 | # projects. 61 | [project.optional-dependencies] # Optional 62 | dev = ["meson", "ninja"] 63 | test = ["pytest"] 64 | 65 | # List URLs that are relevant to your project 66 | # 67 | # This field corresponds to the "Project-URL" and "Home-Page" metadata fields: 68 | # https://packaging.python.org/specifications/core-metadata/#project-url-multiple-use 69 | # https://packaging.python.org/specifications/core-metadata/#home-page-optional 70 | # 71 | # Examples listed include a pattern for specifying where the package tracks 72 | # issues, where the source is hosted, where to say thanks to the package 73 | # maintainers, and where to support the project financially. The key is 74 | # what's used to render the link text on PyPI. 75 | [project.urls] # Optional 76 | "Homepage" = "https://github.com/WISDEM/pyFrame3DD" 77 | "Project" = "https://frame3dd.sourceforge.net" 78 | 79 | [tool.meson-python.args] 80 | setup = ['--python.install-env=auto'] 81 | install = ['--tags=runtime,python-runtime,bin'] 82 | 83 | [tool.black] 84 | line-length = 120 85 | target-version = ['py311'] 86 | include = '\.pyi?$' 87 | exclude = ''' 88 | /( 89 | \.git 90 | | \.hg 91 | | \.mypy_cache 92 | | \.tox 93 | | \.venv 94 | | _build 95 | | buck-out 96 | | build 97 | | dist 98 | )/ 99 | ''' 100 | 101 | [tool.isort] 102 | # https://github.com/PyCQA/isort 103 | multi_line_output = "3" 104 | include_trailing_comma = true 105 | force_grid_wrap = false 106 | use_parentheses = true 107 | line_length = "120" 108 | sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"] 109 | known_first_party = ["wisdem"] 110 | length_sort = "1" 111 | profile = "black" 112 | skip_glob = ['__init__.py'] 113 | atomic = true 114 | #lines_after_imports = 2 115 | #lines_between_types = 1 116 | #src_paths=isort,test 117 | 118 | [tool.cibuildwheel] 119 | skip = ["pp*", "cp36-*", "cp37-*", "cp38-*", "*-win32", "*-win_arm64"] #, "*-musllinux*"] 120 | build-frontend = { name = "build", args = ["-w","-n","-x"] } 121 | before-build = "pip install numpy ninja meson meson-python" 122 | build-verbosity = "3" 123 | 124 | # https://github.com/pdfo/pdfo 125 | [[tool.cibuildwheel.overrides]] 126 | select = "*-win_amd64" 127 | environment = { PKG_CONFIG_PATH="c:/opt/64/lib/pkgconfig" } 128 | 129 | [tool.cibuildwheel.windows] 130 | repair-wheel-command = "bash .github/tools/cibw_repair_wheel_command_windows.sh {wheel} {dest_dir}" 131 | -------------------------------------------------------------------------------- /examples/exB.3dd: -------------------------------------------------------------------------------- 1 | Example B: a pyramid-shaped frame --- static and dynamic analysis (N,mm,ton) 2 | 3 | 5 # number of nodes 4 | #.node x y z r 5 | # mm mm mm mm 6 | 7 | 1 0.0 0.0 1000 0.0 8 | 2 -1200 -900 0.0 0.0 9 | 3 1200 -900 0.0 0.0 10 | 4 1200 900 0.0 0.0 11 | 5 -1200 900 0.0 0.0 12 | 13 | 4 # number of nodes with reactions 14 | #.n x y z xx yy zz 1=fixed, 0=free 15 | 16 | 2 1 1 1 1 1 1 17 | 3 1 1 1 1 1 1 18 | 4 1 1 1 1 1 1 19 | 5 1 1 1 1 1 1 20 | 21 | 4 # number of frame elements 22 | #.e n1 n2 Ax Asy Asz Jxx Iyy Izz E G roll density 23 | # . . mm^2 mm^2 mm^2 mm^4 mm^4 mm^4 MPa MPa deg T/mm^3 24 | 25 | 1 2 1 36.0 20.0 20.0 1000 492 492 200000 79300 0 7.85e-9 26 | 2 1 3 36.0 20.0 20.0 1000 492 492 200000 79300 0 7.85e-9 27 | 3 1 4 36.0 20.0 20.0 1000 492 492 200000 79300 0 7.85e-9 28 | 4 5 1 36.0 20.0 20.0 1000 492 492 200000 79300 0 7.85e-9 29 | 30 | 31 | 1 # 1: include shear deformation 32 | 1 # 1: include geometric stiffness 33 | 10.0 # exaggerate static mesh deformations 34 | 2.5 # zoom scale for 3D plotting 35 | 20.0 # x-axis increment for internal forces, mm 36 | # if dx is -1 then internal force calculations are skipped. 37 | 38 | 3 # number of static load cases 39 | # Begin Static Load Case 1 of 3 40 | 41 | # gravitational acceleration for self-weight loading (global) 42 | #.gX gY gZ 43 | #.mm/s^2 mm/s^2 mm/s^2 44 | 0 0 -9806.33 45 | 46 | 1 # number of loaded nodes 47 | #.e Fx Fy Fz Mxx Myy Mzz 48 | # N N N N.mm N.mm N.mm 49 | 1 100 -200 -100 0.0 0.0 0.0 50 | 0 # number of uniform loads 51 | 0 # number of trapezoidal loads 52 | 0 # number of internal concentrated loads 53 | 0 # number of temperature loads 54 | 0 # number of nodes with prescribed displacements 55 | # End Static Load Case 1 of 3 56 | 57 | # Begin Static Load Case 2 of 3 58 | 59 | # gravitational acceleration for self-weight loading (global) 60 | #.gX gY gZ 61 | #.mm/s^2 mm/s^2 mm/s^2 62 | 0 0 -9806.33 63 | 64 | 0 # number of loaded nodes 65 | 2 # number of uniform loads 66 | #.e Ux Uy Uz 67 | # N/mm N/mm N/mm 68 | 2 0 0.1 0 69 | 1 0 0 0.1 70 | 2 # number of trapezoidally distributed loads 71 | #.e x1 x2 w1 w2 72 | # mm mm N/mm N/mm 73 | 3 20 80 0.01 0.05 # location and loading - local x-axis 74 | 0 0 0 0 # location and loading - local y-axis 75 | 80 830 -0.05 0.07 # location and loading - local z-axis 76 | 77 | 4 0 0 0 0 # location and loading - local x-axis 78 | 68 330 0.05 0.00 # location and loading - local y-axis 79 | 80 830 -0.05 0.07 # location and loading - local z-axis 80 | 81 | 0 # number of internal concentrated loads 82 | 1 # number of temperature loads 83 | #.e alpha hy hz Ty+ Ty- Tz+ Tz- 84 | # /degC mm mm degC degC degC degC 85 | 1 12e-6 10 10 20 10 10 -10 86 | 0 # number of nodes with prescribed displacements 87 | # End Static Load Case 2 of 3 88 | 89 | # Begin Static Load Case 3 of 3 90 | 91 | # gravitational acceleration for self-weight loading (global) 92 | #.gX gY gZ 93 | #.mm/s^2 mm/s^2 mm/s^2 94 | 0 0 -9806.33 95 | 96 | 0 # number of loaded nodes 97 | 0 # number of uniform loads 98 | 0 # number of trapezoidal loads 99 | 2 # number of internal concentrated loads 100 | #.e Px Py Pz x 101 | # N N N mm 102 | 1 0 100 -900 600 103 | 2 0 -200 200 800 104 | 0 # number of temperature loads 105 | 0 # number of nodes with prescribed displacements 106 | # End Static Load Case 3 of 3 107 | 108 | 109 | 6 # number of desired dynamic modes of vibration 110 | 1 # 1: subspace Jacobi 2: Stodola 111 | 0 # 0: consistent mass ... 1: lumped mass matrix 112 | 1e-9 # mode shape tolerance 113 | 0.0 # shift value ... for unrestrained structures 114 | 10.0 # exaggerate modal mesh deformations 115 | 116 | # nodes and concentrated mass and inertia 117 | 1 # number of nodes with extra inertia 118 | #.n Mass Ixx Iyy Izz 119 | # ton ton.mm^2 ton.mm^2 ton.mm^2 120 | 1 0.1 0 0 0 121 | 122 | 0 # frame elements with extra mass 123 | 124 | 6 # number of modes to animate, nA 125 | 1 2 3 4 5 6 # list of modes to animate - omit if nA == 0 126 | 2 # pan rate during animation 127 | 128 | # End of input data file for example B 129 | -------------------------------------------------------------------------------- /pyframe3dd/src/NRutil.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | Memory allocation functions from Numerical Recipes in C, by Press, 3 | Cambridge University Press, 1988 4 | http://www.nr.com/public-domain.html 5 | */ 6 | 7 | #ifndef _FRAME_NRUTIL_H_ 8 | #define _FRAME_NRUTIL_H_ 9 | 10 | typedef struct FCOMPLEX {float r,i;} fcomplex; // also in complex.h 11 | 12 | /* 13 | static float sqrarg; 14 | #define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg) 15 | 16 | static double dsqrarg; 17 | #define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg) 18 | 19 | static double dmaxarg1,dmaxarg2; 20 | #define DMAX(a,b) (dmaxarg1=(a),dmaxarg2=(b),(dmaxarg1) > (dmaxarg2) ?\ 21 | (dmaxarg1) : (dmaxarg2)) 22 | 23 | static double dminarg1,dminarg2; 24 | #define DMIN(a,b) (dminarg1=(a),dminarg2=(b),(dminarg1) < (dminarg2) ?\ 25 | (dminarg1) : (dminarg2)) 26 | 27 | static float maxarg1,maxarg2; 28 | #define FMAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\ 29 | (maxarg1) : (maxarg2)) 30 | 31 | static float minarg1,minarg2; 32 | #define FMIN(a,b) (minarg1=(a),minarg2=(b),(minarg1) < (minarg2) ?\ 33 | (minarg1) : (minarg2)) 34 | 35 | static long lmaxarg1,lmaxarg2; 36 | #define LMAX(a,b) (lmaxarg1=(a),lmaxarg2=(b),(lmaxarg1) > (lmaxarg2) ?\ 37 | (lmaxarg1) : (lmaxarg2)) 38 | 39 | static long lminarg1,lminarg2; 40 | #define LMIN(a,b) (lminarg1=(a),lminarg2=(b),(lminarg1) < (lminarg2) ?\ 41 | (lminarg1) : (lminarg2)) 42 | 43 | static int imaxarg1,imaxarg2; 44 | #define IMAX(a,b) (imaxarg1=(a),imaxarg2=(b),(imaxarg1) > (imaxarg2) ?\ 45 | (imaxarg1) : (imaxarg2)) 46 | 47 | static int iminarg1,iminarg2; 48 | #define IMIN(a,b) (iminarg1=(a),iminarg2=(b),(iminarg1) < (iminarg2) ?\ 49 | (iminarg1) : (iminarg2)) 50 | 51 | #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a)) 52 | */ 53 | 54 | #if defined(__STDC__) || defined(ANSI) || defined(NRANSI) /* ANSI */ 55 | 56 | void NRerror(char error_text[]); 57 | float *vector(long nl, long nh); 58 | int *ivector(long nl, long nh); 59 | unsigned char *cvector(long nl, long nh); 60 | unsigned long *lvector(long nl, long nh); 61 | double *dvector(long nl, long nh); 62 | float **matrix(long nrl, long nrh, long ncl, long nch); 63 | double **dmatrix(long nrl, long nrh, long ncl, long nch); 64 | int **imatrix(long nrl, long nrh, long ncl, long nch); 65 | float **subMatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch, 66 | long newrl, long newcl); 67 | float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch); 68 | float ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh); 69 | void free_vector(float *v, long nl, long nh); 70 | void free_ivector(int *v, long nl, long nh); 71 | void free_cvector(unsigned char *v, long nl, long nh); 72 | void free_lvector(unsigned long *v, long nl, long nh); 73 | void free_dvector(double *v, long nl, long nh); 74 | void free_matrix(float **m, long nrl, long nrh, long ncl, long nch); 75 | void free_dmatrix(double **m, long nrl, long nrh, long ncl, long nch); 76 | void free_imatrix(int **m, long nrl, long nrh, long ncl, long nch); 77 | void free_subMatrix(float **b, long nrl, long nrh, long ncl, long nch); 78 | void free_convert_matrix(float **b, long nrl, long nrh, long ncl, long nch); 79 | void free_f3tensor(float ***t, long nrl, long nrh, long ncl, long nch, 80 | long ndl, long ndh); 81 | 82 | fcomplex *Cvector(int nl, int nh); 83 | fcomplex **Cmatrix(int nrl, int nrh, int ncl, int nch); 84 | void free_Cvector(fcomplex *v, int nl, int nh); 85 | void free_Cmatrix(fcomplex **m, int nrl, int nrh, int ncl, int nch); 86 | 87 | void NRerror(char error_text[]); 88 | 89 | float ***D3matrix(int nrl,int nrh, int ncl, int nch, int nzl, int nzh); 90 | double ***D3dmatrix(int nrl,int nrh, int ncl, int nch, int nzl, int nzh); 91 | void free_D3matrix(float ***m, int nrl, int nrh, int ncl, int nch, int nzl, int nzh); 92 | void free_D3dmatrix(double ***m, int nrl, int nrh, int ncl, int nch, int nzl, int nzh); 93 | 94 | void show_vector(float *A, int n); 95 | void show_dvector(double *A, int n ); 96 | void show_matrix(float **A, int m, int n ); 97 | void show_dmatrix(double **A, int m, int n ); 98 | 99 | void save_vector(char filename[], float *V, int nl, int nh, const char *mode); 100 | void save_dvector(char filename[], double *V, int nl, int nh, const char *mode); 101 | void save_ivector(char filename[], int *V, int nl, int nh, const char *mode); 102 | 103 | void save_matrix ( char filename[], float **A, int ml, int mh, int nl, int nh, int transpose, const char *mode ); 104 | void save_dmatrix ( char filename[], double **A, int ml, int mh, int nl, int nh, int transpose, const char *mode ); 105 | 106 | void save_ut_matrix ( char filename[], float **A, int n, const char *mode ); 107 | void save_ut_dmatrix ( char filename[], double **A, int n, const char *mode ); 108 | 109 | 110 | 111 | #else /* ANSI */ 112 | /* traditional - K&R */ 113 | 114 | void NRerror(); 115 | float *vector(); 116 | float **matrix(); 117 | float **subMatrix(); 118 | float **convert_matrix(); 119 | float ***f3tensor(); 120 | double *dvector(); 121 | double **dmatrix(); 122 | int *ivector(); 123 | int **imatrix(); 124 | unsigned char *cvector(); 125 | unsigned long *lvector(); 126 | void free_vector(); 127 | void free_dvector(); 128 | void free_ivector(); 129 | void free_cvector(); 130 | void free_lvector(); 131 | void free_matrix(); 132 | void free_subMatrix(); 133 | void free_convert_matrix(); 134 | void free_dmatrix(); 135 | void free_imatrix(); 136 | void free_f3tensor(); 137 | 138 | #endif /* ANSI */ 139 | 140 | #endif /* _FRAME_NRUTIL_H */ 141 | 142 | 143 | -------------------------------------------------------------------------------- /.github/workflows/CI_pyFrame3DD.yml: -------------------------------------------------------------------------------- 1 | name: CI_pyFrame3DD 2 | 3 | # We run CI on push commits and pull requests on all branches 4 | on: [push, pull_request] 5 | 6 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 7 | jobs: 8 | build_pip: 9 | name: Pip Build (${{ matrix.os }}) - ${{ matrix.python-version }} 10 | runs-on: ${{ matrix.os }} 11 | defaults: 12 | run: 13 | shell: bash -l {0} 14 | 15 | strategy: 16 | fail-fast: false #true 17 | matrix: 18 | os: ["ubuntu-latest", "macOS-latest", "windows-latest"] 19 | python-version: ["3.9", "3.10", "3.11", "3.12"] 20 | 21 | steps: 22 | - name: Setup C/C++ Compiler 23 | if: false == contains( matrix.os, 'windows') 24 | id: install_cc 25 | uses: rlalik/setup-cpp-compiler@master 26 | with: 27 | compiler: clang 28 | 29 | - name: Install mingw-w64 on Windows 30 | if: contains( matrix.os, 'windows') 31 | uses: msys2/setup-msys2@v2 32 | with: 33 | path-type: inherit 34 | install: | 35 | mingw-w64-x86_64-gcc 36 | 37 | - name: checkout repository 38 | uses: actions/checkout@v4 39 | 40 | - name: Set compilers 41 | if: false == contains( matrix.os, 'windows') 42 | run: | 43 | echo "CC=${{ steps.install_cc.outputs.cc }}" >> $GITHUB_ENV 44 | echo "CXX=${{ steps.install_cc.outputs.cxx }}" >> $GITHUB_ENV 45 | 46 | - name: Set up Python ${{ matrix.python-version }} 47 | uses: actions/setup-python@v5 48 | id: cp 49 | with: 50 | python-version: ${{ matrix.python-version }} 51 | update-environment: true 52 | 53 | - name: Editable Pip Install pyFrame3DD 54 | run: | 55 | '${{ steps.cp.outputs.python-path }}' -m pip install --upgrade pip 56 | '${{ steps.cp.outputs.python-path }}' -m pip install meson-python meson numpy ninja wheel 57 | '${{ steps.cp.outputs.python-path }}' -m pip install --no-build-isolation -e .[test] 58 | 59 | - name: Editable Test run 60 | run: | 61 | '${{ steps.cp.outputs.python-path }}' -m pytest test 62 | 63 | - name: Pip Install pyFrame3DD 64 | run: | 65 | '${{ steps.cp.outputs.python-path }}' -m pip uninstall pyframe3dd 66 | '${{ steps.cp.outputs.python-path }}' -m pip install -v .[test] 67 | 68 | #- name: Setup tmate session 69 | # uses: mxschmitt/action-tmate@v3 70 | # with: 71 | # detached: true 72 | # if: contains( matrix.os, 'ubuntu') 73 | 74 | - name: Test run 75 | run: | 76 | '${{ steps.cp.outputs.python-path }}' -m pytest test 77 | 78 | 79 | build_conda: 80 | name: Conda Build (${{ matrix.os }}) - ${{ matrix.python-version }} 81 | runs-on: ${{ matrix.os }} 82 | defaults: 83 | run: 84 | shell: bash -el {0} 85 | 86 | strategy: 87 | fail-fast: false #true 88 | matrix: 89 | os: ["ubuntu-latest", "macOS-latest", "windows-latest"] 90 | python-version: ["3.9", "3.10", "3.11", "3.12"] 91 | 92 | steps: 93 | - name: checkout repository 94 | uses: actions/checkout@v3 95 | 96 | - uses: conda-incubator/setup-miniconda@v2 97 | # https://github.com/marketplace/actions/setup-miniconda 98 | with: 99 | #mamba-version: "*" 100 | miniforge-version: "latest" 101 | auto-update-conda: true 102 | python-version: ${{ matrix.python-version }} 103 | environment-file: environment.yml 104 | activate-environment: test 105 | auto-activate-base: false 106 | 107 | # Install dependencies of WISDEM specific to windows 108 | - name: Add dependencies windows specific 109 | if: contains( matrix.os, 'windows') 110 | run: | 111 | conda install -y m2w64-toolchain libpython 112 | 113 | # Install dependencies of WISDEM specific to windows 114 | - name: Add dependencies mac specific 115 | if: false == contains( matrix.os, 'windows') 116 | run: | 117 | conda install -y compilers 118 | 119 | - name: Debug 120 | run: | 121 | conda list 122 | printenv 123 | 124 | - name: Conda Install pyFrame3DD 125 | env: 126 | MESON_ARGS: "" 127 | run: | 128 | python -m pip install . -v 129 | 130 | - name: Test run 131 | run: | 132 | python -m pytest test 133 | 134 | - name: Editable Conda Install pyFrame3DD 135 | env: 136 | MESON_ARGS: "" 137 | run: | 138 | python -m pip uninstall pyframe3dd 139 | python -m pip install --no-build-isolation -e . -v 140 | 141 | - name: Editable Test run 142 | run: | 143 | python -m pytest test 144 | 145 | -------------------------------------------------------------------------------- /pyframe3dd/src/coordtrans.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FRAME3DD: 3 | Static and dynamic structural analysis of 2D and 3D frames and trusses with 4 | elastic and geometric stiffness. 5 | --------------------------------------------------------------------------- 6 | http://frame3dd.sourceforge.net/ 7 | --------------------------------------------------------------------------- 8 | Copyright (C) 1992-2009 Henri P. Gavin 9 | 10 | FRAME3DD is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | FRAME3DD is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with FRAME3DD. If not, see . 22 | */ 23 | 24 | #include 25 | 26 | #include "coordtrans.h" 27 | #include "NRutil.h" 28 | 29 | /* ------------------------------------------------------------------------- 30 | COORD_TRANS - calculate the 9 elements of the block-diagonal 12-by-12 31 | coordinate transformation matrix, t1, t2, ..., t9. 32 | 33 | These coordinate transformation factors are used to: 34 | * transform frame element end forces from the element (local) coordinate system 35 | to the structral (global) coordinate system. 36 | * transfrom end displacements from the structural (global) coordinate system 37 | to the element (local) coordinate system, 38 | * transform the frame element stiffness and mass matrices 39 | from element (local) coordinates to structral (global) coordinates. 40 | 41 | Element matrix coordinate transformations are carried out by function ATMA 42 | in frame3dd.c 43 | 44 | Currently coordinate transformations do not consider the effect of 45 | finite node sizes ... this needs work, and could require a substantial 46 | re-write of much of the code. 47 | 48 | Currently the effect of finite node sizes is used only in the calculation 49 | of the element stiffness matrices. 50 | ------------------------------------------------------------------------- */ 51 | void coord_trans( 52 | vec3 *xyz, 53 | double L, 54 | int n1, int n2, 55 | double *t1, double *t2, double *t3, double *t4, double *t5, 56 | double *t6, double *t7, double *t8, double *t9, 57 | float p /**< the roll angle (radians) */ 58 | ){ 59 | double Cx, Cy, Cz, den, /* direction cosines */ 60 | Cp, Sp; /* cosine and sine of roll angle */ 61 | 62 | Cx = (xyz[n2].x - xyz[n1].x) / L; 63 | Cy = (xyz[n2].y - xyz[n1].y) / L; 64 | Cz = (xyz[n2].z - xyz[n1].z) / L; 65 | 66 | *t1 = *t2 = *t3 = *t4 = *t5 = *t6 = *t7 = *t8 = *t9 = 0.0; 67 | 68 | Cp = cos(p); 69 | Sp = sin(p); 70 | 71 | #if Zvert // the global Z axis is vertical 72 | 73 | if ( fabs(Cz) == 1.0 ) { 74 | *t3 = Cz; 75 | *t4 = -Cz*Sp; 76 | *t5 = Cp; 77 | *t7 = -Cz*Cp; 78 | *t8 = -Sp; 79 | } else { 80 | 81 | den = sqrt ( 1.0 - Cz*Cz ); 82 | 83 | *t1 = Cx; 84 | *t2 = Cy; 85 | *t3 = Cz; 86 | 87 | *t4 = (-Cx*Cz*Sp - Cy*Cp)/den; 88 | *t5 = (-Cy*Cz*Sp + Cx*Cp)/den; 89 | *t6 = Sp*den; 90 | 91 | *t7 = (-Cx*Cz*Cp + Cy*Sp)/den; 92 | *t8 = (-Cy*Cz*Cp - Cx*Sp)/den; 93 | *t9 = Cp*den; 94 | } 95 | 96 | #else // the global Y axis is vertical 97 | 98 | if ( fabs(Cy) == 1.0 ) { 99 | *t2 = Cy; 100 | *t4 = -Cy*Cp; 101 | *t6 = Sp; 102 | *t7 = Cy*Sp; 103 | *t9 = Cp; 104 | } else { 105 | 106 | den = sqrt ( 1.0 - Cy*Cy ); 107 | 108 | *t1 = Cx; 109 | *t2 = Cy; 110 | *t3 = Cz; 111 | 112 | *t4 = (-Cx*Cy*Cp - Cz*Sp)/den; 113 | *t5 = den*Cp; 114 | *t6 = (-Cy*Cz*Cp + Cx*Sp)/den; 115 | 116 | *t7 = (Cx*Cy*Sp - Cz*Cp)/den; 117 | *t8 = -den*Sp; 118 | *t9 = (Cy*Cz*Sp + Cx*Cp)/den; 119 | } 120 | 121 | #endif 122 | 123 | return; 124 | } 125 | 126 | 127 | /* ------------------------------------------------------------------------------ 128 | * ATMA - perform the coordinate transformation from local to global 6jan96 129 | * include effects of a finite node radii, r1 and r2. 9dec04 130 | * ------------------------------------------------------------------------------*/ 131 | void atma( 132 | double t1, double t2, double t3, 133 | double t4, double t5, double t6, 134 | double t7, double t8, double t9, 135 | double **m, float r1, float r2 136 | ){ 137 | double **a, **ma;//, **dmatrix(); 138 | int i,j,k; 139 | 140 | a = dmatrix(1,12,1,12); 141 | ma = dmatrix(1,12,1,12); 142 | 143 | for (i=1; i<=12; i++) 144 | for (j=i; j<=12; j++) 145 | ma[j][i] = ma[i][j] = a[j][i] = a[i][j] = 0.0; 146 | 147 | for (i=0; i<=3; i++) { 148 | a[3*i+1][3*i+1] = t1; 149 | a[3*i+1][3*i+2] = t2; 150 | a[3*i+1][3*i+3] = t3; 151 | a[3*i+2][3*i+1] = t4; 152 | a[3*i+2][3*i+2] = t5; 153 | a[3*i+2][3*i+3] = t6; 154 | a[3*i+3][3*i+1] = t7; 155 | a[3*i+3][3*i+2] = t8; 156 | a[3*i+3][3*i+3] = t9; 157 | } 158 | 159 | 160 | /* effect of finite node radius on coordinate transformation ... */ 161 | /* this needs work ... */ 162 | /* 163 | a[5][1] = r1*t7; 164 | a[5][2] = r1*t8; 165 | a[5][3] = r1*t9; 166 | a[6][1] = -r1*t4; 167 | a[6][2] = -r1*t5; 168 | a[6][3] = -r1*t6; 169 | 170 | a[11][7] = -r2*t7; 171 | a[11][8] = -r2*t8; 172 | a[11][9] = -r2*t9; 173 | a[12][7] = r2*t4; 174 | a[12][8] = r2*t5; 175 | a[12][9] = r2*t6; 176 | */ 177 | 178 | #ifdef MATRIX_DEBUG 179 | save_dmatrix( "aa", a, 1,12, 1,12, 0, "w"); /* save cord xfmtn */ 180 | #endif 181 | 182 | for (j=1; j <= 12; j++) /* MT = M T */ 183 | for (i=1; i <= 12; i++) 184 | for (k=1; k <= 12; k++) ma[i][j] += m[i][k] * a[k][j]; 185 | 186 | #ifdef MATRIX_DEBUG 187 | save_dmatrix( "ma", ma, 1,12, 1,12, 0, "w"); /* partial transformation */ 188 | #endif 189 | 190 | for (i=1; i<=12; i++) for (j=i; j<=12; j++) m[j][i] = m[i][j] = 0.0; 191 | 192 | for (j=1; j <= 12; j++) /* T'MT = T' MT */ 193 | for (i=1; i <= 12; i++) 194 | for (k=1; k <= 12; k++) m[i][j] += a[k][i] * ma[k][j]; 195 | 196 | #ifdef MATRIX_DEBUG 197 | save_dmatrix( "atma", m, 1,12, 1,12, 0, "w"); /* debug atma */ 198 | #endif 199 | 200 | free_dmatrix(a, 1,12,1,12); 201 | free_dmatrix(ma,1,12,1,12); 202 | } 203 | -------------------------------------------------------------------------------- /examples/exB.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | """ 4 | example.py 5 | 6 | Created by Andrew Ning on 2013-11-05. 7 | Copyright (c) NREL. All rights reserved. 8 | """ 9 | 10 | import numpy as np 11 | 12 | from pyframe3dd import Frame, NodeData, ReactionData, ElementData, Options, \ 13 | StaticLoadCase 14 | 15 | 16 | # ------- node data ---------------- 17 | 18 | node = np.array([1, 2, 3, 4, 5]) 19 | x = np.array([0.0, -1200, 1200, 1200, -1200]) 20 | y = np.array([0.0, -900, -900, 900, 900]) 21 | z = np.array([1000.0, 0.0, 0.0, 0.0, 0.0]) 22 | r = np.array([0.0, 0.0, 0.0, 0.0, 0.0]) 23 | 24 | nodes = NodeData(node, x, y, z, r) 25 | 26 | # ----------------------------------- 27 | 28 | # ------ reaction data ------------ 29 | 30 | node = np.array([2, 3, 4, 5]) 31 | Rx = np.ones(4) 32 | Ry = np.ones(4) 33 | Rz = np.ones(4) 34 | Rxx = np.ones(4) 35 | Ryy = np.ones(4) 36 | Rzz = np.ones(4) 37 | 38 | reactions = ReactionData(node, Rx, Ry, Rz, Rxx, Ryy, Rzz, rigid=1) 39 | 40 | # ----------------------------------- 41 | 42 | # ------ frame element data ------------ 43 | element = np.array([1, 2, 3, 4]) 44 | N1 = np.array([2, 1, 1, 5]) 45 | N2 = np.array([1, 3, 4, 1]) 46 | Ax = 36.0*np.ones(4) 47 | Asy = 20.0*np.ones(4) 48 | Asz = 20.0*np.ones(4) 49 | Jx = 1000.0*np.ones(4) 50 | Iy = 492.0*np.ones(4) 51 | Iz = 492.0*np.ones(4) 52 | E = 200000.0*np.ones(4) 53 | G = 79300.0*np.ones(4) 54 | roll = np.zeros(4) 55 | density = 7.85e-9*np.ones(4) 56 | 57 | 58 | elements = ElementData(element, N1, N2, Ax, Asy, Asz, Jx, Iy, Iz, E, G, roll, density) 59 | 60 | # ----------------------------------- 61 | 62 | 63 | # ------ other data ------------ 64 | 65 | shear = 1 # 1: include shear deformation 66 | geom = 1 # 1: include geometric stiffness 67 | dx = 20.0 # x-axis increment for internal forces 68 | 69 | other = Options(shear, geom, dx) 70 | 71 | # ----------------------------------- 72 | 73 | 74 | # initialize frame3dd object 75 | frame = Frame(nodes, reactions, elements, other) 76 | 77 | 78 | # ------ static load case 1 ------------ 79 | 80 | # gravity in the X, Y, Z, directions (global) 81 | gx = 0.0 82 | gy = 0.0 83 | gz = -9806.33 84 | 85 | load = StaticLoadCase(gx, gy, gz) 86 | 87 | # point load 88 | nF = np.array([1]) 89 | Fx = np.array([100.0]) 90 | Fy = np.array([-200.0]) 91 | Fz = np.array([-100.0]) 92 | Mxx = np.array([0.0]) 93 | Myy = np.array([0.0]) 94 | Mzz = np.array([0.0]) 95 | 96 | load.changePointLoads(nF, Fx, Fy, Fz, Mxx, Myy, Mzz) 97 | 98 | 99 | frame.addLoadCase(load) 100 | 101 | # ----------------------------------- 102 | 103 | 104 | 105 | # ------ static load case 2 ------------ 106 | 107 | gx = 0.0 108 | gy = 0.0 109 | gz = -9806.33 110 | 111 | load = StaticLoadCase(gx, gy, gz) 112 | 113 | # uniform loads 114 | EL = np.array([2, 1]) 115 | Ux = np.array([0.0, 0.0]) 116 | Uy = np.array([0.1, 0.0]) 117 | Uz = np.array([0.0, 0.1]) 118 | 119 | load.changeUniformLoads(EL, Ux, Uy, Uz) 120 | 121 | # trapezoidally distributed loads 122 | EL = np.array([3, 4]) 123 | xx1 = np.array([20.0, 0.0]) 124 | xx2 = np.array([80.0, 0.0]) 125 | wx1 = np.array([0.01, 0.0]) 126 | wx2 = np.array([0.05, 0.0]) 127 | xy1 = np.array([0.0, 68.0]) 128 | xy2 = np.array([0.0, 330.0]) 129 | wy1 = np.array([0.0, 0.05]) 130 | wy2 = np.array([0.0, 0.0]) 131 | xz1 = np.array([80.0, 80.0]) 132 | xz2 = np.array([830.0, 830.0]) 133 | wz1 = np.array([-0.05, -0.05]) 134 | wz2 = np.array([0.07, 0.07]) 135 | 136 | load.changeTrapezoidalLoads(EL, xx1, xx2, wx1, wx2, xy1, xy2, wy1, wy2, xz1, xz2, wz1, wz2) 137 | 138 | EL = np.array([1]) 139 | a = np.array([12e-6]) 140 | hy = np.array([10.0]) 141 | hz = np.array([10.0]) 142 | Typ = np.array([20.0]) 143 | Tym = np.array([10.0]) 144 | Tzp = np.array([10.0]) 145 | Tzm = np.array([-10.0]) 146 | 147 | load.changeTemperatureLoads(EL, a, hy, hz, Typ, Tym, Tzp, Tzm) 148 | 149 | 150 | # prescribed displacements 151 | # load.changePrescribedDisplacements(N, Dx, Dy, Dz, Dxx, Dyy, Dzz) 152 | 153 | frame.addLoadCase(load) 154 | 155 | # ----------------------------------- 156 | 157 | 158 | # ------ static load case 3 ------------ 159 | 160 | gx = 0.0 161 | gy = 0.0 162 | gz = -9806.33 163 | 164 | load = StaticLoadCase(gx, gy, gz) 165 | 166 | # concentrated interior point loads 167 | EL = np.array([1, 2]) 168 | Px = np.array([0.0, 0.0]) 169 | Py = np.array([100.0, -200.0]) 170 | Pz = np.array([-900.0, 200.0]) 171 | x = np.array([600.0, 800.0]) 172 | 173 | load.changeElementLoads(EL, Px, Py, Pz, x) 174 | 175 | 176 | frame.addLoadCase(load) 177 | 178 | # ----------------------------------- 179 | 180 | 181 | # ------ dyamic analysis data ------------ 182 | 183 | nM = 6 # number of desired dynamic modes of vibration 184 | Mmethod = 1 # 1: subspace Jacobi 2: Stodola 185 | lump = 0 # 0: consistent mass ... 1: lumped mass matrix 186 | tol = 1e-9 # mode shape tolerance 187 | shift = 0.0 # shift value ... for unrestrained structures 188 | 189 | frame.enableDynamics(nM, Mmethod, lump, tol, shift) 190 | 191 | # extra node inertia data 192 | N = np.array([1]) 193 | EMs = np.array([0.1]) 194 | EMx = np.array([0.0]) 195 | EMy = np.array([0.0]) 196 | EMz = np.array([0.0]) 197 | 198 | # frame.changeExtraInertia(N, EMs, EMx, EMy, EMz) 199 | frame.changeExtraNodeMass(N, EMs, EMx, EMy, EMz, [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], False) 200 | 201 | # extra frame element mass data ... 202 | # dynamic.changeExtraMass(EL, EMs) 203 | 204 | # set dynamic analysis 205 | # frame.useDynamicAnalysis(dynamic) 206 | 207 | # ------------------------------------ 208 | 209 | # run the analysis 210 | displacements, forces, reactions, internalForces, mass, modal = frame.run() 211 | 212 | nC = len(frame.loadCases) # number of load cases 213 | nN = len(nodes.node) # number of nodes 214 | nE = len(elements.element) # number of elements 215 | # nM = dynamic.nM # number of modes 216 | 217 | # node displacements 218 | ''' 219 | for iCase in range(nC): 220 | 221 | print 'case_idx:', iCase 222 | 223 | print 'node:', displacements.node[iCase, :] 224 | print 'dx:', displacements.dx[iCase, :] 225 | print 'dy:', displacements.dy[iCase, :] 226 | print 'dz:', displacements.dz[iCase, :] 227 | print 'dxrot:', displacements.dxrot[iCase, :] 228 | print 'dyrot:', displacements.dyrot[iCase, :] 229 | print 'dzrot:', displacements.dzrot[iCase, :] 230 | print 231 | print 'element =', forces.element[iCase, :] 232 | print 'node =', forces.node[iCase, :] 233 | print 'Nx =', forces.Nx[iCase, :] 234 | print 'Vy =', forces.Vy[iCase, :] 235 | print 'Vz =', forces.Vz[iCase, :] 236 | print 'Txx =', forces.Txx[iCase, :] 237 | print 'Myy =', forces.Myy[iCase, :] 238 | print 'Mzz =', forces.Mzz[iCase, :] 239 | print 240 | print 'nodesR =', reactions.node[iCase, :] 241 | print 'RFx =', reactions.Fx[iCase, :] 242 | print 'RFy =', reactions.Fy[iCase, :] 243 | print 'RFz =', reactions.Fz[iCase, :] 244 | print 'RMxx =', reactions.Mxx[iCase, :] 245 | print 'RMyy =', reactions.Myy[iCase, :] 246 | print 'RMzz =', reactions.Mzz[iCase, :] 247 | print 248 | 249 | print 250 | print 251 | 252 | 253 | # internal forces 254 | 255 | # note just showing for one element 256 | iE = 3 257 | 258 | 259 | for iCase in range(nC): 260 | 261 | print 'case_idx:', iCase 262 | print 'element_idx:', iE 263 | 264 | print 'x =', internalForces[iE].x[iCase, :] 265 | print 'Nx =', internalForces[iE].Nx[iCase, :] 266 | print 'Vy =', internalForces[iE].Vy[iCase, :] 267 | print 'Vz =', internalForces[iE].Vz[iCase, :] 268 | print 'Tx =', internalForces[iE].Tx[iCase, :] 269 | print 'My =', internalForces[iE].My[iCase, :] 270 | print 'Mz =', internalForces[iE].Mz[iCase, :] 271 | print 'Dx =', internalForces[iE].Dx[iCase, :] 272 | print 'Dy =', internalForces[iE].Dy[iCase, :] 273 | print 'Dz =', internalForces[iE].Dz[iCase, :] 274 | print 'Rx =', internalForces[iE].Rx[iCase, :] 275 | print 276 | 277 | print 278 | print 279 | 280 | 281 | # mass data 282 | 283 | print 'total_mass =', mass.total_mass 284 | print 'struct_mass =', mass.struct_mass 285 | print 'node =', mass.node 286 | print 'xmass =', mass.xmass 287 | print 'ymass =', mass.ymass 288 | print 'zmass =', mass.zmass 289 | print 'xinrta =', mass.xinrta 290 | print 'yinrta =', mass.yinrta 291 | print 'zinrta =', mass.zinrta 292 | print 293 | print 294 | 295 | 296 | 297 | for iM in range(nM): 298 | 299 | print 'mode_idx', iM 300 | 301 | print 'freq =', modal.freq[iM] 302 | print 'xmpf =', modal.xmpf[iM] 303 | print 'ympf =', modal.ympf[iM] 304 | print 'zmpf =', modal.zmpf[iM] 305 | print 'node =', modal.node[iM, :] 306 | print 'xdsp =', modal.xdsp[iM, :] 307 | print 'ydsp =', modal.ydsp[iM, :] 308 | print 'zdsp =', modal.zdsp[iM, :] 309 | print 'xrot =', modal.xrot[iM, :] 310 | print 'yrot =', modal.yrot[iM, :] 311 | print 'zrot =', modal.zrot[iM, :] 312 | print 313 | 314 | ''' 315 | -------------------------------------------------------------------------------- /pyframe3dd/src/HPGutil.c: -------------------------------------------------------------------------------- 1 | /* HPGutil.c --- library of general-purpose utility functions */ 2 | 3 | /* 4 | Copyright (C) 2012 Henri P. Gavin 5 | 6 | HPGutil is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | HPGutil is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with HPGutil. If not, see . 18 | */ 19 | 20 | #include "HPGutil.h" 21 | #include 22 | #include 23 | 24 | #define DEBUG 0 25 | 26 | 27 | /* 28 | * COLOR - change color on the screen ... 29 | * Screen Color Scheme : 0 = white on black, 1 = bright 30 | * first digit= 3 for text color first digit= 4 for background color 31 | * second digit codes: 32 | * 0=black, 1=red, 2=green, 3=gold, 4=blue, 5=magenta, 6=cyan, 7=white 33 | * http://en.wikipedia.org/wiki/ANSI_escape_code 34 | */ 35 | void color ( const int colorCode ) /* change the screen color */ 36 | { 37 | #if ANSI_SYS 38 | fprintf (stderr, "\033[%02dm", colorCode ); 39 | (void) fflush(stderr); 40 | #endif 41 | return; 42 | } 43 | 44 | 45 | /* 46 | * TEXTCOLOR - change color of text and background 47 | * tColor : text color : one of 'k' 'r' 'g' 'y' 'b' 'm' 'c' 'w' 48 | * bColor : back color : one of 'k' 'r' 'g' 'y' 'b' 'm' 'c' 'w' 49 | * nbf : 'n' = normal, 'b' = bright/bold, 'f' = faint 50 | * uline : 'u' = underline 51 | * http://en.wikipedia.org/wiki/ANSI_escape_code 52 | */ 53 | void textColor ( const char tColor, const char bColor, const char nbf, const char uline ) 54 | { 55 | #if ANSI_SYS 56 | fprintf (stderr, "\033[%02d",0);// Control Sequence Introducer & reset 57 | // background colors 58 | if ( bColor == 'k' ) fprintf (stderr, ";%02d", 40 ); // black 59 | if ( bColor == 'r' ) fprintf (stderr, ";%02d", 41 ); // red 60 | if ( bColor == 'g' ) fprintf (stderr, ";%02d", 42 ); // green 61 | if ( bColor == 'y' ) fprintf (stderr, ";%02d", 43 ); // yellow 62 | if ( bColor == 'b' ) fprintf (stderr, ";%02d", 44 ); // blue 63 | if ( bColor == 'm' ) fprintf (stderr, ";%02d", 45 ); // magenta 64 | if ( bColor == 'c' ) fprintf (stderr, ";%02d", 46 ); // cyan 65 | if ( bColor == 'w' ) fprintf (stderr, ";%02d", 47 ); // white 66 | 67 | // text colors 68 | if ( tColor == 'k' ) fprintf (stderr, ";%02d", 30 ); // black 69 | if ( tColor == 'r' ) fprintf (stderr, ";%02d", 31 ); // red 70 | if ( tColor == 'g' ) fprintf (stderr, ";%02d", 32 ); // green 71 | if ( tColor == 'y' ) fprintf (stderr, ";%02d", 33 ); // yellow 72 | if ( tColor == 'b' ) fprintf (stderr, ";%02d", 34 ); // blue 73 | if ( tColor == 'm' ) fprintf (stderr, ";%02d", 35 ); // magenta 74 | if ( tColor == 'c' ) fprintf (stderr, ";%02d", 36 ); // cyan 75 | if ( tColor == 'w' ) fprintf (stderr, ";%02d", 37 ); // white 76 | 77 | // printf(" tColor = %c bColor = %c nbf = %c\n", tColor, bColor, nbf ); 78 | if ( nbf == 'b' ) fprintf (stderr, ";%02d", 1 ); // bright 79 | if ( nbf == 'f' ) fprintf (stderr, ";%02d", 2 ); // faint 80 | 81 | if ( uline == 'u' ) fprintf (stderr, ";%02d", 4 ); // underline 82 | 83 | fprintf (stderr,"m"); // Select Graphic Rendition (SGR) 84 | 85 | (void) fflush(stderr); 86 | #endif 87 | return; 88 | } 89 | 90 | 91 | /* 92 | * ERRORMSG - write a diagnostic error message in color 93 | */ 94 | void errorMsg ( const char *errString ) 95 | { 96 | fprintf(stderr,"\n\n"); 97 | fflush(stderr); 98 | #if ANSI_SYS 99 | color(1); color(41); color(37); 100 | #endif 101 | fprintf(stderr," %s ", errString ); 102 | #if ANSI_SYS 103 | fflush(stderr); 104 | color(0); 105 | #endif 106 | fprintf(stderr,"\n\n"); 107 | return; 108 | } 109 | 110 | 111 | /* 112 | * OPENFILE - open a file or print a diagnostic error message 113 | */ 114 | FILE *openFile ( const char *path, const char *fileName, const char *mode, char *usage ) 115 | { 116 | FILE *fp; 117 | char pathToFile[MAXL], errMsg[MAXL]; 118 | 119 | if (mode == 0) return 0; 120 | 121 | sprintf(pathToFile,"%s%s", path, fileName ); 122 | #if DEBUG 123 | printf(" openFile ... file name = %s\n", pathToFile); 124 | #endif 125 | if ((fp=fopen(pathToFile,mode)) == NULL ) { // open file 126 | switch (*mode) { 127 | sprintf(errMsg," openFile: "); 128 | case 'w': 129 | sprintf(errMsg,"%s%s\n usage: %s","cannot write to file: ", pathToFile, usage ); 130 | break; 131 | case 'r': 132 | sprintf(errMsg,"%s%s\n usage: %s","cannot read from file: ", pathToFile, usage ); 133 | break; 134 | case 'a': 135 | sprintf(errMsg,"%s%s\n usage: %s","cannot append to file: ", pathToFile, usage ); 136 | break; 137 | default: 138 | sprintf(errMsg,"%s%s\n usage: %s","cannot open file: ", pathToFile, usage ); 139 | } 140 | errorMsg ( errMsg ); 141 | exit(1); 142 | } else { 143 | #if DEBUG 144 | printf(" openFile ... fp = %x\n", fp); 145 | #endif 146 | 147 | return fp; 148 | } 149 | } 150 | 151 | 152 | /* 153 | * SCANLINE - scan through a line until a 'a' is reached, like getline() 3feb94 154 | */ 155 | int scanLine ( FILE *fp, int lim, char *s, const char a ) 156 | { 157 | int c=0, i=-1; 158 | 159 | while (--lim > 0 && (c=getc(fp)) != EOF && c != a) s[++i] = c; 160 | s[++i]='\0'; 161 | return i ; 162 | } 163 | 164 | 165 | /* 166 | * SCANLABEL - scan through a line until a '"' is reached, like getline() 167 | */ 168 | int scanLabel ( FILE *fp, int lim, char *s, const char a ) 169 | { 170 | int c=0, i=-1; 171 | 172 | while (--lim > 0 && (c=getc(fp)) != EOF && c != a) 173 | ; // scan to first delimitter char 174 | while (--lim > 0 && (c=getc(fp)) != EOF && c != a) 175 | s[++i] = c; // read the label between delimitters 176 | s[++i]='\0'; 177 | return i ; 178 | } 179 | 180 | 181 | /* 182 | * SCANFILE - count the number of lines of multi-column data in a data file, 183 | * skipping over "head_lines" lines of header information 184 | */ 185 | int scanFile ( FILE *fp, int head_lines, int start_chnl, int stop_chnl ) 186 | { 187 | int points = 0, 188 | i, chn, ok=1; 189 | float data_value; 190 | char ch; 191 | 192 | // scan through the header 193 | for (i=1;i<=head_lines;i++) while (( ch = getc(fp)) != '\n') ; 194 | 195 | // count the number of lines of data 196 | do { 197 | for ( chn=start_chnl; chn <= stop_chnl; chn++ ) { 198 | ok=fscanf(fp,"%f",&data_value); 199 | if (ok==1) ++points; 200 | } 201 | if(ok>0) while (( ch = getc(fp)) != '\n') ; 202 | } while (ok==1); 203 | 204 | points = (int) ( points / (stop_chnl - start_chnl + 1) ); 205 | // printf ("%% %d data points\n", points); 206 | 207 | rewind (fp); 208 | 209 | return(points); 210 | } 211 | 212 | 213 | /* 214 | * GETLINE - get line form a stream into a character string, return length 215 | * from K&R 3feb94 216 | */ 217 | int getLine ( FILE *fp, int lim, char *s ) 218 | { 219 | int c=0, i=0; 220 | 221 | while (--lim > 0 && (c=getc(fp)) != EOF && c != '\n' ) 222 | s[i++] = c; 223 | /* if (c == '\n') s[i++] = c; */ 224 | s[i++] = '\0'; 225 | return(i); 226 | } 227 | 228 | 229 | /* 230 | * getTime parse a numeric time string similar to YYYYMMDDhhmmss 231 | * The input variables y, m, d, hr, mn, sc are the indices of the string s[] 232 | * which start the YYYY, MM, DD, hh, mm, ss sections of the time string. 233 | * The corresponding time is returned in "time_t" format. 234 | */ 235 | time_t getTime( char s[], int y, int m, int d, int hr, int mn, int sc, int os ) 236 | { 237 | char temp[16]; 238 | 239 | struct tm t_tm; 240 | time_t t_time; 241 | 242 | t_tm.tm_year = atoi( strncpy( temp, s+y, 4 ) )-1900; 243 | temp[2]='\0'; 244 | t_tm.tm_mon = atoi( strncpy( temp, s+m, 2 ) )-1; 245 | t_tm.tm_mday = atoi( strncpy( temp, s+d, 2 ) ); 246 | t_tm.tm_hour = atoi( strncpy( temp, s+hr, 2 ) ); 247 | t_tm.tm_min = atoi( strncpy( temp, s+mn, 2 ) ); 248 | t_tm.tm_sec = atoi( strncpy( temp, s+sc, 2 ) )+os; 249 | 250 | /* all times are Universal Time never daylight savings time */ 251 | t_tm.tm_isdst = -1 ; 252 | 253 | t_time = mktime(&t_tm); // normalize t_tm 254 | 255 | // printf("%d ... %s", (int) t_time, ctime(&t_time) ); 256 | 257 | return t_time; 258 | 259 | } 260 | 261 | 262 | /* 263 | * SHOW_PROGRESS - show the progress of long computations 264 | */ 265 | void showProgress ( int i, int n, int count ) 266 | { 267 | int k,j, line_length = 55; 268 | float percent_done; 269 | 270 | percent_done = (float)(i) / (float)(n); 271 | 272 | j = (int) ceil(percent_done*line_length); 273 | 274 | for (k=1;k<=line_length+13;k++) fprintf(stderr,"\b"); 275 | for (k=1;k"); 276 | for (k=j;k> Input Data file error while reading %s\n",s); 293 | errorMsg(errMsg); 294 | return; 295 | } 296 | 297 | #undef DEBUG 298 | -------------------------------------------------------------------------------- /test/test_breakdown.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import numpy as np 3 | import numpy.testing as npt 4 | from pyframe3dd import Frame, NodeData, ReactionData, ElementData, Options, StaticLoadCase 5 | 6 | class TestBreakdown(unittest.TestCase): 7 | 8 | def testRXNs(self): 9 | # Nodal data 10 | ntop = 5 11 | nbase = 10 12 | nall = ntop + nbase - 1 13 | xyz_top = np.c_[np.linspace(0.0, -10, ntop), np.zeros(ntop), 100*np.ones(ntop)] 14 | xyz_base = np.c_[np.zeros((nbase,2)), np.linspace(0, 100, nbase)] 15 | xyz_all = np.vstack( (xyz_base, xyz_top[1:,:]) ) 16 | 17 | zero_top = np.zeros(ntop) 18 | inode_top = np.arange(ntop, dtype=np.int_)+1 19 | node_top = NodeData(inode_top, xyz_top[:,0], xyz_top[:,1], xyz_top[:,2], zero_top) 20 | 21 | zero_base = np.zeros(nbase) 22 | inode_base = np.arange(nbase, dtype=np.int_)+1 23 | node_base = NodeData(inode_base, xyz_base[:,0], xyz_base[:,1], xyz_base[:,2], zero_base) 24 | 25 | zero_all = np.zeros(nall) 26 | inode_all = np.arange(nall, dtype=np.int_)+1 27 | node_all = NodeData(inode_all, xyz_all[:,0], xyz_all[:,1], xyz_all[:,2], zero_all) 28 | 29 | # Reactions 30 | rnode = np.array([1], dtype=np.int_) 31 | Kval = np.array([1], dtype=np.int_) 32 | rigid = 1 33 | reactions = ReactionData(rnode, Kval, Kval, Kval, Kval, Kval, Kval, rigid) 34 | 35 | # Element data 36 | top1 = np.ones(ntop-1) 37 | base1 = np.ones(nbase-1) 38 | all1 = np.ones(nall-1) 39 | ielem_top = np.arange(1, ntop) 40 | ielem_base = np.arange(1, nbase) 41 | ielem_all = np.arange(1, nall) 42 | N1_top = np.arange(ntop-1, dtype=np.int_)+1 43 | N1_base = np.arange(nbase-1, dtype=np.int_)+1 44 | N1_all = np.arange(nall-1, dtype=np.int_)+1 45 | N2_top = N1_top + 1 46 | N2_base = N1_base + 1 47 | N2_all = N1_all + 1 48 | Ax = 2.0 49 | Asx = Asy = 4.0 50 | J0 = 2e1 51 | Ix = Iy = 1e1 52 | E = 5e6 53 | G = 5e6 54 | density = 8e2 55 | elem_top = ElementData(ielem_top, N1_top, N2_top, 56 | Ax*top1, Asx*top1, Asy*top1, 57 | J0*top1, Ix*top1, Iy*top1, 58 | E*top1, G*top1, 0.0*top1, density*top1) 59 | elem_base = ElementData(ielem_base, N1_base, N2_base, 60 | Ax*base1, Asx*base1, Asy*base1, 61 | J0*base1, Ix*base1, Iy*base1, 62 | E*base1, G*base1, 0.0*base1, density*base1) 63 | elem_all = ElementData(ielem_all, N1_all, N2_all, 64 | Ax*all1, Asx*all1, Asy*all1, 65 | J0*all1, Ix*all1, Iy*all1, 66 | E*all1, G*all1, 0.0*all1, density*all1) 67 | 68 | # parameters 69 | shear = False # 1: include shear deformation 70 | geom = False # 1: include geometric stiffness 71 | dx = -1.0 # x-axis increment for internal forces 72 | options = Options(shear, geom, dx) 73 | 74 | frame_top = Frame(node_top, reactions, elem_top, options) 75 | frame_base = Frame(node_base, reactions, elem_base, options) 76 | frame_all = Frame(node_all, reactions, elem_all, options) 77 | 78 | # load case 79 | gx = 0.0 80 | gy = 0.0 81 | gz = -9.81 82 | load_top = StaticLoadCase(gx, gy, gz) 83 | load_base = StaticLoadCase(gx, gy, gz) 84 | load_all = StaticLoadCase(gx, gy, gz) 85 | 86 | # pseudo-rotor loads 87 | nF_top = [inode_top[-1]] 88 | nF_base = [inode_base[-1]] 89 | nF_all = [inode_all[-1]] 90 | F = 1e2 91 | M = 1e3 92 | load_top.changePointLoads(nF_top, [F], [F], [F], [M], [M], [M]) 93 | load_all.changePointLoads(nF_all, [F], [F], [F], [M], [M], [M]) 94 | 95 | frame_top.addLoadCase(load_top) 96 | frame_all.addLoadCase(load_all) 97 | 98 | # Added mass 99 | AN_top = [inode_top[-2]] 100 | AN_all = [inode_all[-2]] 101 | AN_base = [inode_base[-2]] 102 | EMs = np.array([1e2]) 103 | EMxx = EMyy = EMzz = EMxy = EMxz = EMyz = np.array([0.0]) 104 | rhox = rhoy = rhoz = np.array([0.0]) 105 | addGravityLoad = True 106 | frame_top.changeExtraNodeMass(AN_top, EMs, EMxx, EMyy, EMzz, EMxy, EMxz, EMyz, rhox, rhoy, rhoz, addGravityLoad) 107 | frame_all.changeExtraNodeMass(AN_all, EMs, EMxx, EMyy, EMzz, EMxy, EMxz, EMyz, rhox, rhoy, rhoz, addGravityLoad) 108 | 109 | # Run first models 110 | disp_top, forces_top, rxns_top, _, _, _ = frame_top.run() 111 | disp_all, forces_all, rxns_all, _, _, _ = frame_all.run() 112 | 113 | # Transfer loads to base 114 | load_base.changePointLoads(nF_base, 115 | [-rxns_top.Fx], 116 | [-rxns_top.Fy], 117 | [-rxns_top.Fz], 118 | [-rxns_top.Mxx], 119 | [-rxns_top.Myy], 120 | [-rxns_top.Mzz], 121 | ) 122 | frame_base.addLoadCase(load_base) 123 | disp_base, forces_base, rxns_base, _, _, _ = frame_base.run() 124 | 125 | npt.assert_almost_equal(rxns_all.Fx, rxns_base.Fx, decimal=3) 126 | npt.assert_almost_equal(rxns_all.Fy, rxns_base.Fy, decimal=3) 127 | npt.assert_almost_equal(rxns_all.Fz, rxns_base.Fz, decimal=3) 128 | npt.assert_almost_equal(rxns_all.Mxx, rxns_base.Mxx, decimal=2) 129 | npt.assert_almost_equal(rxns_all.Myy, rxns_base.Myy, decimal=2) 130 | npt.assert_almost_equal(rxns_all.Mzz, rxns_base.Mzz, decimal=2) 131 | 132 | 133 | def testModal(self): 134 | 135 | # nodes 136 | nn = 11 137 | node = np.arange(1, nn + 1, dtype=np.int_) 138 | x = y = r = np.zeros(nn) 139 | z = np.linspace(0, 100, nn) 140 | nodes = NodeData(node, x, y, z, r) 141 | 142 | # reactions 143 | rnode = np.array([1], dtype=np.int_) 144 | Kx = Ky = Kz = Ktx = Kty = Ktz = np.ones(1) 145 | rigid = 1 146 | reactions = ReactionData(rnode, Kx, Ky, Kz, Ktx, Kty, Ktz, rigid) 147 | 148 | # elements 149 | ne = nn - 1 150 | EL = np.arange(1, ne + 1, dtype=np.int_) 151 | N1 = np.arange(1, nn, dtype=np.int_) 152 | N2 = np.arange(2, nn + 1, dtype=np.int_) 153 | Ax = Jx = Iy = Iz = 10 * np.ones(ne) 154 | Asy = Asz = 8 * np.ones(ne) 155 | E = 2e6 * np.ones(ne) 156 | G = 1e6 * np.ones(ne) 157 | roll = np.zeros(ne) 158 | rho = 1e-5 * np.ones(ne) 159 | elements = ElementData(EL, N1, N2, Ax, Asy, Asz, Jx, Iy, Iz, E, G, roll, rho) 160 | 161 | # parameters 162 | shear = False # 1: include shear deformation 163 | geom = True # 1: include geometric stiffness 164 | dx = -1.0 # x-axis increment for internal forces 165 | options = Options(shear, geom, dx) 166 | 167 | #### Fixed-free 168 | frame_mass = Frame(nodes, reactions, elements, options) 169 | frame_force = Frame(nodes, reactions, elements, options) 170 | 171 | # dynamics 172 | nM = 15 # number of desired dynamic modes of vibration 173 | Mmethod = 1 # 1: subspace Jacobi 2: Stodola 174 | lump = 0 # 0: consistent mass ... 1: lumped mass matrix 175 | tol = 1e-7 # mode shape tolerance 176 | shift = -1e2 # shift value ... for unrestrained structures 177 | frame_mass.enableDynamics(nM, Mmethod, lump, tol, shift) 178 | frame_force.enableDynamics(nM, Mmethod, lump, tol, shift) 179 | 180 | # load cases 1 181 | gx = 0.0 182 | gy = 0.0 183 | gz = -980.6 184 | 185 | load_mass = StaticLoadCase(gx, gy, gz) 186 | load_force = StaticLoadCase(gx, gy, gz) 187 | 188 | mymass = 4.0 189 | 190 | # pseudo-mass loads 191 | nadd = [node[-2]] 192 | F = mymass * gz 193 | load_force.changePointLoads(nadd, [0], [0], [F], [0], [0], [0]) 194 | frame_force.addLoadCase(load_force) 195 | 196 | # Added mass 197 | frame_mass.addLoadCase(load_mass) 198 | EMs = [mymass] 199 | EMxx = EMyy = EMzz = EMxy = EMxz = EMyz = np.array([0.0]) 200 | rhox = rhoy = rhoz = np.array([0.0]) 201 | addGravityLoad = True 202 | frame_mass.changeExtraNodeMass(nadd, EMs, EMxx, EMyy, EMzz, EMxy, EMxz, EMyz, rhox, rhoy, rhoz, addGravityLoad) 203 | frame_force.changeExtraNodeMass(nadd, EMs, EMxx, EMyy, EMzz, EMxy, EMxz, EMyz, rhox, rhoy, rhoz, False) 204 | 205 | _, _, rxns_mass, _, _, modal_mass = frame_mass.run() 206 | _, _, rxns_force, _, _, modal_force = frame_force.run() 207 | 208 | npt.assert_almost_equal(modal_mass.freq, modal_force.freq) 209 | 210 | npt.assert_almost_equal(rxns_mass.Fx, rxns_force.Fx) 211 | npt.assert_almost_equal(rxns_mass.Fy, rxns_force.Fy) 212 | npt.assert_almost_equal(rxns_mass.Fz, rxns_force.Fz) 213 | npt.assert_almost_equal(rxns_mass.Mxx, rxns_force.Mxx) 214 | npt.assert_almost_equal(rxns_mass.Myy, rxns_force.Myy) 215 | npt.assert_almost_equal(rxns_mass.Mzz, rxns_force.Mzz) 216 | 217 | 218 | 219 | if __name__ == "__main__": 220 | unittest.main() 221 | 222 | 223 | -------------------------------------------------------------------------------- /pyframe3dd/src/frame3dd.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FRAME3DD: 3 | Static and dynamic structural analysis of 2D and 3D frames and trusses with 4 | elastic and geometric stiffness. 5 | --------------------------------------------------------------------------- 6 | http://frame3dd.sourceforge.net/ 7 | --------------------------------------------------------------------------- 8 | Copyright (C) 1992-2014 Henri P. Gavin 9 | 10 | FRAME3DD is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | FRAME3DD is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with FRAME3DD. If not, see . 22 | *//** 23 | @file 24 | Main functions of the FRAME3DD solver API 25 | */ 26 | 27 | #ifndef FRAME_FRAME_H 28 | #define FRAME_FRAME_H 29 | 30 | /* for Micro-Stran compatability, structure for cartesian vectors */ 31 | #include "microstran/vec3.h" 32 | 33 | /* maximum number of load cases */ 34 | #define _NL_ 32 35 | 36 | 37 | /** form the global stiffness matrix */ 38 | void assemble_K( 39 | double **K, /**< stiffness matrix */ 40 | int DoF, /**< number of degrees of freedom */ 41 | int nE, /**< number of frame elements */ 42 | vec3 *xyz, /**< XYZ locations of every node */ 43 | float *r, /**< rigid radius of every node */ 44 | double *L, double *Le, /**< length of each frame element, effective */ 45 | int *N1, int *N2, /**< node connectivity */ 46 | float *Ax, float *Asy, float *Asz, /**< section areas */ 47 | float *Jx, float *Iy, float *Iz, /**< section inertias */ 48 | float *E, float *G, /**< elastic and shear moduli */ 49 | float *p, /**< roll angle, radians */ 50 | int shear, /**< 1: include shear deformation, 0: don't */ 51 | int geom, /**< 1: include goemetric stiffness, 0: don't */ 52 | double **Q, /**< frame element end forces */ 53 | int debug /**< 1: write element stiffness matrices*/ 54 | ); 55 | 56 | 57 | /** solve {F} = [K]{D} via L D L' decomposition */ 58 | void solve_system( 59 | double **K, /**< stiffness matrix for the restrained frame */ 60 | double *D, /**< displacement vector to be solved */ 61 | double *F, /**< external load vector */ 62 | double *R, /**< reaction vector */ 63 | int DoF, /**< number of degrees of freedom */ 64 | int *q, /**< 1: not a reaction; 0: a reaction coordinate */ 65 | int *r, /**< 0: not a reaction; 1: a reaction coordinate */ 66 | int *ok, /**< indicates positive definite stiffness matrix */ 67 | int verbose, /**< 1: copious screen output; 0: none */ 68 | double *rms_resid /**< the RMS error of the solution residual */ 69 | ); 70 | 71 | 72 | /* 73 | * COMPUTE_REACTION_FORCES : R(r) = [K(r,q)]*{D(q)} + [K(r,r)]*{D(r)} - F(r) 74 | * reaction forces satisfy equilibrium in the solved system 75 | * 2012-10-12 , 2014-05-16 76 | */ 77 | void compute_reaction_forces( 78 | double *R, /**< computed reaction forces */ 79 | double *F, /**< vector of equivalent external loads */ 80 | double **K, /**< stiffness matrix for the solved system */ 81 | double *D, /**< displacement vector for the solved system */ 82 | int DoF, /**< number of structural coordinates */ 83 | int *r /**< 0: not a reaction; 1: a reaction coordinate */ 84 | ); 85 | 86 | 87 | /* add_feF : add fixed end forces to internal element forces 88 | * removed reaction calculations on 2014-05-14 89 | * 90 | void add_feF( 91 | vec3 *xyz, //< XYZ locations of each node 92 | double *L, //< length of each frame element, effective 93 | int *N1, int *N2, //< node connectivity 94 | float *p, //< roll angle, radians 95 | double **Q, //< frame element end forces 96 | double **eqF_temp, //< temp. equiv.end forces for all frame elements 97 | double **eqF_mech, //< mech. equiv.end forces for all frame elements 98 | int nE, //< number of frame elements 99 | int DoF, //< number of degrees of freedom 100 | int verbose //< 1: copious screen output; 0: none 101 | ); 102 | */ 103 | 104 | 105 | /* 106 | * EQUILBRIUM_ERROR - compute {dF} = {F} - [K_qq]{D_q} - [K_qr]{D_r} 107 | * and return ||dF|| / ||F|| 108 | * use only the upper trianlge of [K_qq] 109 | */ 110 | double equilibrium_error( 111 | double *dF, /**< equilibrium error {dF} = {F} - [K]{D} */ 112 | double *F, /**< load vector */ 113 | double **K, /**< stiffness matrix for the restrained frame */ 114 | double *D, /**< displacement vector to be solved */ 115 | int DoF, /**< number of degrees of freedom */ 116 | int *q, /**< 1: not a reaction; 0: a reaction coordinate */ 117 | int *r /**< 0: not a reaction; 1: a reaction coordinate */ 118 | ); 119 | 120 | 121 | /** evaluate the member end forces for every member */ 122 | void element_end_forces( 123 | double **Q, /**< frame element end forces */ 124 | int nE, /**< number of frame elements */ 125 | vec3 *xyz, /** XYZ locations of each node */ 126 | double *L, double *Le, /**< length of each frame element, effective */ 127 | int *N1, int *N2, /**< node connectivity */ 128 | float *Ax, float *Asy, float *Asz, /**< section areas */ 129 | float *Jx, float *Iy, float *Iz, /**< section area inertias */ 130 | float *E, float *G, /**< elastic and shear moduli */ 131 | float *p, /**< roll angle, radians */ 132 | double **eqF_temp, /**< equivalent temp loads on elements, global */ 133 | double **eqF_mech, /**< equivalent mech loads on elements, global */ 134 | double *D, /**< displacement vector */ 135 | int shear, /**< 1: include shear deformation, 0: don't */ 136 | int geom, /**< 1: include goemetric stiffness, 0: don't */ 137 | int *axial_strain_warning /** < 0: strains < 0.001 */ 138 | ); 139 | 140 | 141 | 142 | /** assemble global mass matrix from element mass & inertia */ 143 | void assemble_M( 144 | double **M, /**< mass matrix */ 145 | int DoF, /**< number of degrees of freedom */ 146 | int nN, int nE, /**< number of nodes, number of frame elements */ 147 | vec3 *xyz, /** XYZ locations of each node */ 148 | float *r, /**< rigid radius of every node */ 149 | double *L, /**< length of each frame element, effective */ 150 | int *N1, int *N2, /**< node connectivity */ 151 | float *Ax, /**< node connectivity */ 152 | float *Jx, float *Iy, float *Iz, /**< section area inertias*/ 153 | float *p, /**< roll angle, radians */ 154 | float *d, /**< frame element density */ 155 | float *EMs, /**< extra frame element mass */ 156 | float *NMs, /**< node mass */ 157 | float *NMx, float *NMy, float *NMz, /**< node inertias */ 158 | int lump, /**< 1: lumped mass matrix, 0: consistent mass */ 159 | int debug /**< 1: write element mass matrices */ 160 | ); 161 | 162 | 163 | /** static condensation of stiffness matrix from NxN to nxn */ 164 | void static_condensation( 165 | double **A, /**< a square matrix */ 166 | int N, /**< the dimension of the matrix */ 167 | int *q, /**< list of matrix indices to retain */ 168 | int n, /**< the dimension of the condensed matrix */ 169 | double **Ac, /**< the condensed matrix */ 170 | int verbose /**< 1: copious screen output; 0: none */ 171 | ); 172 | 173 | 174 | /** 175 | Paz condensation of mass and stiffness matrices 176 | matches the response at a particular frequency, sqrt(L)/2/pi 177 | Paz M. Dynamic condensation. AIAA J 1984;22(5):724-727. 178 | */ 179 | void paz_condensation( 180 | double **M, double **K, /**< mass and stiffness matrices */ 181 | int N, /**< dimension of the matrices, DoF */ 182 | int *q, /**< list of degrees of freedom to retain */ 183 | int n, /**< dimension of the condensed matrices */ 184 | double **Mc, double **Kc, /**< the condensed matrices */ 185 | double w2, /**< matched value of frequency squared */ 186 | int verbose /**< 1: copious screen output; 0: none */ 187 | ); 188 | 189 | 190 | /** 191 | dynamic condensation of mass and stiffness matrices 192 | matches the response at a set of frequencies 193 | 194 | @NOTE Kc and Mc may be ill-conditioned, and xyzsibly non-positive def. 195 | */ 196 | void modal_condensation( 197 | double **M, double **K, /**< mass and stiffness matrices */ 198 | int N, /**< dimension of the matrices, DoF */ 199 | int *R, /**< R[i]=1: DoF i is fixed, R[i]=0: DoF i is free */ 200 | int *p, /**< list of primary degrees of freedom */ 201 | int n, /**< the dimension of the condensed matrix */ 202 | double **Mc, double **Kc, /**< the condensed matrices */ 203 | double **V, double *f, /**< mode shapes and natural frequencies*/ 204 | int *m, /**< list of modes to match in the condensed model */ 205 | int verbose /**< 1: copious screen output; 0: none */ 206 | ); 207 | 208 | 209 | /** 210 | release allocated memory 211 | */ 212 | void deallocate( 213 | int nN, int nE, int nL, int *nF, int *nU, int *nW, int *nP, int *nT, int DoF, 214 | int modes, 215 | vec3 *xyz, float *rj, double *L, double *Le, 216 | int *N1, int *N2, int *q, int *r, 217 | float *Ax, float *Asy, float *Asz, 218 | float *Jx, float *Iy, float *Iz, 219 | float *E, float *G, 220 | float *p, 221 | float ***U, float ***W, float ***P, float ***T, 222 | float **Dp, 223 | double **F_mech, double **F_temp, 224 | double ***eqF_mech, double ***eqF_temp, double *F, double *dF, 225 | double **K, double **Q, 226 | double *D, double *dD, 227 | double *R, double *dR, 228 | float *d, float *EMs, 229 | float *NMs, float *NMx, float *NMy, float *NMz, 230 | double **M, double *f, double **V, 231 | int *c, int *m, 232 | double **pkNx, double **pkVy, double **pkVz, double **pkTx, double **pkMy, double **pkMz, 233 | double **pkDx, double **pkDy, double **pkDz, double **pkRx, double **pkSy, double **pkSz 234 | ); 235 | 236 | 237 | #endif /* FRAME_FRAME_H */ 238 | 239 | -------------------------------------------------------------------------------- /pyframe3dd/src/py_frame3dd.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FRAME3DD: 3 | Static and dynamic structural analysis of 2D and 3D frames and trusses with 4 | elastic and geometric stiffness. 5 | --------------------------------------------------------------------------- 6 | http://frame3dd.sourceforge.net/ 7 | --------------------------------------------------------------------------- 8 | Copyright (C) 1992-2014 Henri P. Gavin 9 | 10 | FRAME3DD is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | FRAME3DD is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with FRAME3DD. If not, see . 22 | *//** 23 | @file 24 | Main functions of the FRAME3DD solver API 25 | */ 26 | 27 | #ifndef FRAME_PY_FRAME_H 28 | #define FRAME_PY_FRAME_H 29 | 30 | /* for Micro-Stran compatability, structure for cartesian vectors */ 31 | #include "microstran/vec3.h" 32 | 33 | /* maximum number of load cases */ 34 | #define _NL_ 32 35 | 36 | 37 | /** form the global stiffness matrix */ 38 | void assemble_K( 39 | double **K, /**< stiffness matrix */ 40 | int DoF, /**< number of degrees of freedom */ 41 | int nE, /**< number of frame elements */ 42 | int nN, /**< number of frame nodes */ 43 | vec3 *xyz, /**< XYZ locations of every node */ 44 | float *r, /**< rigid radius of every node */ 45 | double *L, double *Le, /**< length of each frame element, effective */ 46 | int *N1, int *N2, /**< node connectivity */ 47 | float *Ax, float *Asy, float *Asz, /**< section areas */ 48 | float *Jx, float *Iy, float *Iz, /**< section inertias */ 49 | float *E, float *G, /**< elastic and shear moduli */ 50 | float *p, /**< roll angle, radians */ 51 | int shear, /**< 1: include shear deformation, 0: don't */ 52 | int geom, /**< 1: include goemetric stiffness, 0: don't */ 53 | double **Q, /**< frame element end forces */ 54 | int debug, /**< 1: write element stiffness matrices*/ 55 | float *EKx, float *EKy, float *EKz, // extra nodal stiffness 56 | float *EKtx, float *EKty, float *EKtz 57 | ); 58 | 59 | 60 | /** solve {F} = [K]{D} via L D L' decomposition */ 61 | void solve_system( 62 | double **K, /**< stiffness matrix for the restrained frame */ 63 | double *D, /**< displacement vector to be solved */ 64 | double *F, /**< external load vector */ 65 | double *R, /**< reaction vector */ 66 | int DoF, /**< number of degrees of freedom */ 67 | int *q, /**< 1: not a reaction; 0: a reaction coordinate */ 68 | int *r, /**< 0: not a reaction; 1: a reaction coordinate */ 69 | int *ok, /**< indicates positive definite stiffness matrix */ 70 | int verbose, /**< 1: copious screen output; 0: none */ 71 | double *rms_resid /**< the RMS error of the solution residual */ 72 | ); 73 | 74 | 75 | /* 76 | * COMPUTE_REACTION_FORCES : R(r) = [K(r,q)]*{D(q)} + [K(r,r)]*{D(r)} - F(r) 77 | * reaction forces satisfy equilibrium in the solved system 78 | * 2012-10-12 , 2014-05-16 79 | */ 80 | void compute_reaction_forces( 81 | double *R, /**< computed reaction forces */ 82 | double *F, /**< vector of equivalent external loads */ 83 | double **K, /**< stiffness matrix for the solved system */ 84 | double *D, /**< displacement vector for the solved system */ 85 | int DoF, /**< number of structural coordinates */ 86 | int *r /**< 0: not a reaction; 1: a reaction coordinate */ 87 | ); 88 | 89 | 90 | /* add_feF : add fixed end forces to internal element forces 91 | * removed reaction calculations on 2014-05-14 92 | * 93 | void add_feF( 94 | vec3 *xyz, //< XYZ locations of each node 95 | double *L, //< length of each frame element, effective 96 | int *N1, int *N2, //< node connectivity 97 | float *p, //< roll angle, radians 98 | double **Q, //< frame element end forces 99 | double **eqF_temp, //< temp. equiv.end forces for all frame elements 100 | double **eqF_mech, //< mech. equiv.end forces for all frame elements 101 | int nE, //< number of frame elements 102 | int DoF, //< number of degrees of freedom 103 | int verbose //< 1: copious screen output; 0: none 104 | ); 105 | */ 106 | 107 | 108 | /* 109 | * EQUILBRIUM_ERROR - compute {dF} = {F} - [K_qq]{D_q} - [K_qr]{D_r} 110 | * and return ||dF|| / ||F|| 111 | * use only the upper trianlge of [K_qq] 112 | */ 113 | double equilibrium_error( 114 | double *dF, /**< equilibrium error {dF} = {F} - [K]{D} */ 115 | double *F, /**< load vector */ 116 | double **K, /**< stiffness matrix for the restrained frame */ 117 | double *D, /**< displacement vector to be solved */ 118 | int DoF, /**< number of degrees of freedom */ 119 | int *q, /**< 1: not a reaction; 0: a reaction coordinate */ 120 | int *r /**< 0: not a reaction; 1: a reaction coordinate */ 121 | ); 122 | 123 | 124 | /** evaluate the member end forces for every member */ 125 | void element_end_forces( 126 | double **Q, /**< frame element end forces */ 127 | int nE, /**< number of frame elements */ 128 | vec3 *xyz, /** XYZ locations of each node */ 129 | double *L, double *Le, /**< length of each frame element, effective */ 130 | int *N1, int *N2, /**< node connectivity */ 131 | float *Ax, float *Asy, float *Asz, /**< section areas */ 132 | float *Jx, float *Iy, float *Iz, /**< section area inertias */ 133 | float *E, float *G, /**< elastic and shear moduli */ 134 | float *p, /**< roll angle, radians */ 135 | double **eqF_temp, /**< equivalent temp loads on elements, global */ 136 | double **eqF_mech, /**< equivalent mech loads on elements, global */ 137 | double *D, /**< displacement vector */ 138 | int shear, /**< 1: include shear deformation, 0: don't */ 139 | int geom, /**< 1: include goemetric stiffness, 0: don't */ 140 | int *axial_strain_warning /** < 0: strains < 0.001 */ 141 | ); 142 | 143 | 144 | 145 | /** assemble global mass matrix from element mass & inertia */ 146 | void assemble_M( 147 | double **M, /**< mass matrix */ 148 | int DoF, /**< number of degrees of freedom */ 149 | int nN, int nE, /**< number of nodes, number of frame elements */ 150 | vec3 *xyz, /** XYZ locations of each node */ 151 | float *r, /**< rigid radius of every node */ 152 | double *L, /**< length of each frame element, effective */ 153 | int *N1, int *N2, /**< node connectivity */ 154 | float *Ax, /**< node connectivity */ 155 | float *Jx, float *Iy, float *Iz, /**< section area inertias*/ 156 | float *p, /**< roll angle, radians */ 157 | float *d, /**< frame element density */ 158 | float *EMs, /**< extra frame element mass */ 159 | float *NMs, /**< node mass */ 160 | float *NMx, float *NMy, float *NMz, /**< node inertias */ 161 | int lump, /**< 1: lumped mass matrix, 0: consistent mass */ 162 | int debug /**< 1: write element mass matrices */ 163 | ); 164 | 165 | 166 | /** static condensation of stiffness matrix from NxN to nxn */ 167 | void static_condensation( 168 | double **A, /**< a square matrix */ 169 | int N, /**< the dimension of the matrix */ 170 | int *q, /**< list of matrix indices to retain */ 171 | int n, /**< the dimension of the condensed matrix */ 172 | double **Ac, /**< the condensed matrix */ 173 | int verbose /**< 1: copious screen output; 0: none */ 174 | ); 175 | 176 | 177 | /** 178 | Paz condensation of mass and stiffness matrices 179 | matches the response at a particular frequency, sqrt(L)/2/pi 180 | Paz M. Dynamic condensation. AIAA J 1984;22(5):724-727. 181 | */ 182 | void paz_condensation( 183 | double **M, double **K, /**< mass and stiffness matrices */ 184 | int N, /**< dimension of the matrices, DoF */ 185 | int *q, /**< list of degrees of freedom to retain */ 186 | int n, /**< dimension of the condensed matrices */ 187 | double **Mc, double **Kc, /**< the condensed matrices */ 188 | double w2, /**< matched value of frequency squared */ 189 | int verbose /**< 1: copious screen output; 0: none */ 190 | ); 191 | 192 | 193 | /** 194 | dynamic condensation of mass and stiffness matrices 195 | matches the response at a set of frequencies 196 | 197 | @NOTE Kc and Mc may be ill-conditioned, and xyzsibly non-positive def. 198 | */ 199 | void modal_condensation( 200 | double **M, double **K, /**< mass and stiffness matrices */ 201 | int N, /**< dimension of the matrices, DoF */ 202 | int *R, /**< R[i]=1: DoF i is fixed, R[i]=0: DoF i is free */ 203 | int *p, /**< list of primary degrees of freedom */ 204 | int n, /**< the dimension of the condensed matrix */ 205 | double **Mc, double **Kc, /**< the condensed matrices */ 206 | double **V, double *f, /**< mode shapes and natural frequencies*/ 207 | int *m, /**< list of modes to match in the condensed model */ 208 | int verbose /**< 1: copious screen output; 0: none */ 209 | ); 210 | 211 | 212 | /** 213 | release allocated memory 214 | */ 215 | void deallocate( 216 | int nN, int nE, int nL, int *nF, int *nU, int *nW, int *nP, int *nT, int DoF, 217 | int modes, 218 | vec3 *xyz, float *rj, double *L, double *Le, 219 | int *N1, int *N2, int *q, int *r, 220 | float *Ax, float *Asy, float *Asz, 221 | float *Jx, float *Iy, float *Iz, 222 | float *E, float *G, 223 | float *p, 224 | float ***U, float ***W, float ***P, float ***T, 225 | float **Dp, 226 | double **F_mech, double **F_temp, 227 | double ***eqF_mech, double ***eqF_temp, double *F, double *dF, 228 | double **K, double **Q, 229 | double *D, double *dD, 230 | double *R, double *dR, 231 | float *d, float *EMs, 232 | float *NMs, float *NMx, float *NMy, float *NMz, 233 | double **M, double *f, double **V, 234 | int *c, int *m, 235 | double **pkNx, double **pkVy, double **pkVz, double **pkTx, double **pkMy, double **pkMz, 236 | double **pkDx, double **pkDy, double **pkDz, double **pkRx, double **pkSy, double **pkSz, 237 | float *EKx, float *EKy, float *EKz, float *EKtx, float *EKty, float *EKtz 238 | 239 | ); 240 | 241 | 242 | #endif /* FRAME_PY_FRAME_H */ 243 | 244 | -------------------------------------------------------------------------------- /pyframe3dd/src/py_io.h: -------------------------------------------------------------------------------- 1 | /* 2 | S. Andrew Ning 3 | Nov 1, 2013 4 | */ 5 | 6 | #include "common.h" 7 | #include 8 | #include "microstran/vec3.h" 9 | #include "py_structs.h" 10 | 11 | #include 12 | 13 | 14 | 15 | 16 | 17 | /** 18 | Read node coordinate data 19 | */ 20 | int read_node_data ( 21 | Nodes *nodes, /**node struct */ 22 | int nN, /**< number of nodes */ 23 | vec3 *xyz, /**< XYZ coordinates of each node */ 24 | float *rj /**< rigid radius of each node */ 25 | ); 26 | 27 | /** 28 | Read frame element property data 29 | */ 30 | int read_frame_element_data ( 31 | Elements *elements, // element data 32 | int nN, /**< number of nodes */ 33 | int nE, /**< number of frame elements */ 34 | vec3 *xyz, /**< XYZ coordinates of each node */ 35 | float *rj, /**< rigid radius of each node */ 36 | double *L, double *Le, /**< length of each frame element, effective */ 37 | int *N1, int *N2, /**< node connectivity */ 38 | float *Ax, float *Asy, float *Asz, /**< section areas */ 39 | float *Jx, float *Iy, float *Iz, /**< section inertias */ 40 | float *E, float *G, /**< elastic moduli and shear moduli */ 41 | float *p, /**< roll angle of each frame element (radians) */ 42 | float *d /**< mass density of each frame element */ 43 | ); 44 | 45 | 46 | /** 47 | Read data controlling certain aspects of the analysis 48 | */ 49 | int read_run_data ( 50 | OtherElementData *other, // struct 51 | int *shear, /**< 1: include shear deformations, 0: don't */ 52 | int *geom, /**< 1: include geometric stiffness, 0: don't */ 53 | double *exagg_static,/**< factor for static displ. exaggeration */ 54 | float *dx /**< frame element increment for internal forces*/ 55 | ); 56 | 57 | 58 | /** 59 | Read fixed node displacement boundary conditions 60 | */ 61 | int read_reaction_data( 62 | Reactions *reactions, // struct 63 | int DoF, /**< number of degrees of freedom */ 64 | int nN, /**< number of nodes */ 65 | int *nR, /**< number of nodes with reactions */ 66 | int *q, /**< q[i]=0: DoF i is fixed, q[i]=1: DoF i is free */ 67 | int *r, /**< r[i]=1: DoF i is fixed, r[i]=0: DoF i is free */ 68 | int *sumR, /**< sum of vector R */ 69 | int verbose, /**< 1: copious screen output; 0: none */ 70 | int geom, 71 | float *EKx, float *EKy, float *EKz, /* extra stiffness */ 72 | float *EKtx, float *EKty, float *EKtz 73 | ); 74 | 75 | 76 | /** 77 | read load information data, form un-restrained load vector 78 | */ 79 | int read_and_assemble_loads( 80 | LoadCase* loadcases, //struct 81 | int nN, /**< number of nodes */ 82 | int nE, /**< number of frame elements */ 83 | int nL, /**< number of load cases */ 84 | int DoF, /**< number of degrees of freedom */ 85 | vec3 *xyz, /**< XYZ coordinates of each node */ 86 | double *L, double *Le, /**< length of each frame element, effective */ 87 | int *N1, int *N2, /**< node connectivity */ 88 | float *Ax, float *Asy, float *Asz, /**< section areas */ 89 | float *Iy, float *Iz, /**< section inertias */ 90 | float *E, float *G, /**< elastic moduli and shear moduli */ 91 | float *p, /**< roll angle of each frame element (radians) */ 92 | float *d, /**< mass density of each frame element */ 93 | float *gX, /**< gravitational acceleration in global X each load case */ 94 | float *gY, /**< gravitational acceleration in global Y each load case */ 95 | float *gZ, /**< gravitational acceleration in global Z each load case */ 96 | int *r, /**< r[i]=1: DoF i is fixed, r[i]=0: DoF i is free */ 97 | int shear, /**< 1: include shear deformations, 0: don't */ 98 | int *nF, /**< number of concentrated node loads */ 99 | int *nU, /**< number of uniformly distributed loads */ 100 | int *nW, /**< number of trapezoidaly distributed loads */ 101 | int *nP, /**< number of concentrated point loads */ 102 | int *nT, /**< number of temperature loads */ 103 | int *nD, /**< number of prescribed displacements */ 104 | double **Q, /**< frame element end forces, every beam */ 105 | double **F_temp, /**< thermal loads */ 106 | double **F_mech, /**< mechanical loads */ 107 | double *Fo, /**< thermal loads + mechanical loads */ 108 | float ***U, /**< uniformally distributed loads */ 109 | float ***W, /**< trapezoidally distributed loads */ 110 | float ***P, /**< concentrated point loads */ 111 | float ***T, /**< temperature loads */ 112 | float **Dp, /**< prescribed displacements at rctns */ 113 | double ***feF_mech, /**< fixed end forces for mechanical loads */ 114 | double ***feF_temp, /**< fixed end forces for temperature loads */ 115 | int verbose /**< 1: copious output to screen, 0: none */ 116 | ); 117 | 118 | 119 | /** 120 | read member densities and extra inertial mass data 121 | */ 122 | int read_mass_data( 123 | DynamicData *dynamic, ExtraInertia *extraInertia, ExtraMass *extraMass, // structs 124 | int nN, int nE, /**< number of nodes, number of frame elements */ 125 | int *nI, /**< number of nodes with extra inertia */ 126 | int *nX, /**< number of elements with extra mass */ 127 | float *d, float *EMs, /**< density, extra frame element mass */ 128 | float *NMs, float *NMx, float *NMy, float *NMz, /**< node inertia*/ 129 | double *L, /**< length of each frame element */ 130 | float *Ax, /**< cross section area of each frame element */ 131 | double *total_mass, /**< total mass of structure and extra mass */ 132 | double *struct_mass, /**< mass of structural elements */ 133 | int *nM, /**< number of modes to find */ 134 | int *Mmethod, /**< modal analysis method */ 135 | int *lump, /**< 1: use lumped mass matrix, 0: consistent mass */ 136 | double *tol, /**< convergence tolerance for mode shapes */ 137 | double *shift, /**< frequency shift for unrestrained frames */ 138 | double *exagg_modal, /**< exaggerate modal displacements */ 139 | int *anim, /**< list of modes to be graphically animated */ 140 | float *pan, /**< 1: pan viewpoint during animation, 0: don't */ 141 | int verbose, /**< 1: copious output to screen, 0: none */ 142 | int debug /**< 1: debugging output to screen, 0: none */ 143 | ); 144 | 145 | 146 | /** 147 | read matrix condensation information 148 | */ 149 | int read_condensation_data( 150 | Condensation *condensation, //struct 151 | int nN, int nM, /**< number of nodes, number of modes */ 152 | int *nC, /**< number of nodes with condensed DoF's */ 153 | int *Cdof, /**< list of DoF's retained in condensed model */ 154 | int *Cmethod, /**< matrix conden'n method, static, Guyan, dynamic*/ 155 | int *c, /**< list of retained degrees of freedom */ 156 | int *m, /**< list of retained modes in dynamic condensation */ 157 | int verbose /**< 1: copious output to screen, 0: none */ 158 | ); 159 | 160 | 161 | /** 162 | save node displacements and member end forces in a text file 9sep08 163 | */ 164 | void write_static_results( 165 | Displacements* displacements, Forces* forces, ReactionForces* reactionForces, //structs 166 | Reactions* reactions, int nR, 167 | int nN, int nE, int nL, int lc, int DoF, 168 | int *N1, int *N2, 169 | double *F, double *D, int *r, double **Q, 170 | double err, int ok 171 | ); 172 | 173 | 174 | /** 175 | calculate frame element internal forces, Nx, Vy, Vz, Tx, My, Mz 176 | calculate frame element local displacements, Rx, Dx, Dy, Dz 177 | write internal forces and local displacements to an output data file 178 | 4jan10 179 | */ 180 | void write_internal_forces( 181 | InternalForces **internalForces, // array of arrays of structs 182 | int lc, /**< load case number */ 183 | int nL, /**< number of static load cases */ 184 | float dx, /**< increment distance along local x axis */ 185 | vec3 *xyz, /**< XYZ locations of each node */ 186 | double **Q, /**< frame element end forces */ 187 | int nN, /**< number of nodes */ 188 | int nE, /**< number of frame elements */ 189 | double *L, /**< length of each frame element */ 190 | int *N1, int *N2, /**< node connectivity */ 191 | float *Ax, /**< cross sectional area */ 192 | float *Asy, float *Asz, /**< effective shear area */ 193 | float *Jx, /**< torsional moment of inertia */ 194 | float *Iy, float *Iz, /**< bending moment of inertia */ 195 | float *E, float *G, /**< elastic and shear modulii */ 196 | float *p, /**< roll angle, radians */ 197 | float *d, /**< mass density */ 198 | float gX, float gY, float gZ, /**< gravitational acceleration */ 199 | int nU, /**< number of uniformly-distributed loads */ 200 | float **U, /**< uniformly distributed load data */ 201 | int nW, /**< number of trapezoidally-distributed loads */ 202 | float **W, /**< trapezoidally distributed load data */ 203 | int nP, /**< number of internal point loads */ 204 | float **P, /**< internal point load data */ 205 | double *D, /**< node displacements */ 206 | int shear, /**< shear deformation flag */ 207 | double error /**< RMS equilibrium error */ 208 | ); 209 | 210 | 211 | /** 212 | save modal frequencies and mode shapes 16aug01 213 | */ 214 | void write_modal_results( 215 | MassResults* massR, ModalResults* modalR, //structs 216 | int nN, int nE, int nI, int DoF, 217 | double **M, double *f, double **V, 218 | double total_mass, double struct_mass, 219 | int iter, int sumR, int nM, 220 | double shift, int lump, double tol, int ok 221 | ); 222 | 223 | 224 | 225 | /** print a set of dots (periods) */ 226 | void dots ( FILE *fp, int n ); 227 | 228 | 229 | /** EVALUATE - displays a randomly-generated evaluation message. */ 230 | // void evaluate ( float error, float rms_resid, float tol, int geom ); 231 | 232 | -------------------------------------------------------------------------------- /pyframe3dd/src/HPGmatrix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ========================================================================== 3 | * 4 | * Filename: HPGmatrix.h 5 | * 6 | * Description: header files for functions in matrix.c 7 | * 8 | * Version: 1.0 9 | * Created: 12/30/11 18:09:26 10 | * Revision: 10/15/12 11 | * Compiler: gcc 12 | * 13 | * Author: Henri P. Gavin (hpgavin), h p gavin ~at~ duke ~dot~ e d v 14 | * Company: Duke Univ. 15 | * 16 | * ========================================================================== 17 | */ 18 | 19 | 20 | /* 21 | Copyright (C) 2012 Henri P. Gavin 22 | 23 | HPGmatrix is free software: you can redistribute it and/or modify 24 | it under the terms of the GNU General Public License as published by 25 | the Free Software Foundation, either version 3 of the License, or 26 | (at your option) any later version. 27 | 28 | HPGmatrix is distributed in the hope that it will be useful, 29 | but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | GNU General Public License for more details. 32 | 33 | You should have received a copy of the GNU General Public License 34 | along with HPGmatrix. If not, see . 35 | */ 36 | 37 | /* 38 | * GAUSSJ 39 | * Linear equation solution by Gauss-Jordan elimination, [A][X]=[B] above. A[1..n][1..n] 40 | * is the input matrix. B[1..n][1..m] is input containing the m right-hand side vectors. On 41 | * output, a is replaced by its matrix inverse, and B is replaced by the corresponding set of solution 42 | * vectors. 43 | */ 44 | void gaussj ( float **A, int n, float **B, int m ); 45 | 46 | /* 47 | * LU_DCMP 48 | * Solves [A]{x} = {b}, simply and efficiently, by performing an 49 | * LU-decomposition of matrix [A]. No pivoting is performed. 50 | * @param A is a diagonally dominant matrix of dimension [1..n][1..n]. 51 | * @param b is a r.h.s. vector of dimension [1..n]. 52 | * 53 | * {b} is updated using [LU] and then back-substitution is done to obtain {x}. 54 | * {b} is replaced by {x} and [A] is replaced by the LU-reduction of itself. 55 | */ 56 | void lu_dcmp ( 57 | double **A, /**< the system matrix, and its LU-reduction */ 58 | int n, /**< the dimension of the matrix */ 59 | double *b, /**< the right hand side vector, and the solution vector */ 60 | int reduce, /**< 1: do a forward reduction; 0: don't */ 61 | int solve, /**< 1: do a back substitution for {x}; 0: don't */ 62 | int *pd /**< 1: positive diagonal and successful LU decomp'n */ 63 | ); 64 | 65 | 66 | /* 67 | * LDL_DCMP 68 | * Solves [A]{x} = {b} simply and efficiently by performing an 69 | * L D L' - decomposition of [A]. No pivoting is performed. 70 | * [A] is a symmetric diagonally-dominant matrix of dimension [1..n][1..n]. 71 | * {b} is a r.h.s. vector of dimension [1..n]. 72 | * {b} is updated using L D L' and then back-substitution is done to obtain {x}. 73 | * {b} is returned unchanged. ldl_dcmp(A,n,d,x,x,1,1,&pd) is valid. 74 | * The lower triangle of [A] is replaced by the lower triangle L of the 75 | * L D L' reduction. The diagonal of D is returned in the vector {d} 76 | */ 77 | void ldl_dcmp ( 78 | double **A, /**< the system matrix, and L of the L D L' decomp.*/ 79 | int n, /**< the dimension of the matrix */ 80 | double *d, /**< diagonal of D in the L D L' - decomp'n */ 81 | double *b, /**< the right hand side vector */ 82 | double *x, /**< the solution vector */ 83 | int reduce, /**< 1: do a forward reduction of A; 0: don't */ 84 | int solve, /**< 1: do a back substitution for {x}; 0: don't */ 85 | int *pd /**< 1: definite matrix and successful L D L' decomp'n*/ 86 | ); 87 | 88 | /* 89 | * LDL_MPROVE improves a solution vector x[1..n] of the linear set of equations 90 | * [A]{x} = {b}. 91 | * The matrix A[1..n][1..n], and the vectors b[1..n] and x[1..n] 92 | * are input, as is the dimension n. The matrix [A] is the L D L' 93 | * decomposition of the original system matrix, as returned by ldl_dcmp(). 94 | * Also input is the diagonal vector, {d} of [D] of the L D L' decompositon. 95 | * On output, only {x} is modified to an improved set of values. 96 | */ 97 | void ldl_mprove( 98 | double **A, 99 | int n, double *d, double *b, double *x, 100 | double *rms_resid, /**< the RMS error of the solution residual */ 101 | int *ok 102 | ); 103 | 104 | 105 | /* 106 | * LDL_DCMP_PM - Solves partitioned matrix equations 107 | * 108 | * [A_qq]{x_q} + [A_qr]{x_r} = {b_q} 109 | * [A_rq]{x_q} + [A_rr]{x_r} = {b_r}+{c_r} 110 | * where {b_q}, {b_r}, and {x_r} are known and 111 | * where {x_q} and {c_r} are unknown 112 | * 113 | * via L D L' - decomposition of [A_qq]. No pivoting is performed. 114 | * [A] is a symmetric diagonally-dominant matrix of dimension [1..n][1..n]. 115 | * {b} is a r.h.s. vector of dimension [1..n]. 116 | * {b} is updated using L D L' and then back-substitution is done to obtain {x} 117 | * {b_q} and {b_r} are returned unchanged. 118 | * {c_r} is returned as a vector of [1..n] with {c_q}=0. 119 | * {q} is a vector of the indexes of known values {b_q} 120 | * {r} is a vector of the indexes of known values {x_r} 121 | * The lower triangle of [A_qq] is replaced by the lower triangle L of its 122 | * L D L' reduction. The diagonal of D is returned in the vector {d} 123 | * 124 | * usage: double **A, *d, *b, *x; 125 | * int n, reduce, solve, pd; 126 | * ldl_dcmp_pm ( A, n, d, b, x, c, q, r, reduce, solve, &pd ); 127 | * 128 | * H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 129 | * Bathe, Finite Element Procecures in Engineering Analysis, Prentice Hall, 1982 130 | * 2014-05-14 131 | */ 132 | void ldl_dcmp_pm ( 133 | double **A, /**< the system matrix, and L of the L D L' decomp.*/ 134 | int n, /**< the dimension of the matrix */ 135 | double *d, /**< diagonal of D in the L D L' - decomp'n */ 136 | double *b, /**< the right hand side vector */ 137 | double *x, /**< part of the solution vector */ 138 | double *c, /**< the part of the solution vector in the rhs */ 139 | int *q, /**< q[j]=1 if b[j] is known; q[j]=0 otherwise */ 140 | int *r, /**< r[j]=1 if x[j] is known; r[j]=0 otherwise */ 141 | int reduce, /**< 1: do a forward reduction of A; 0: don't */ 142 | int solve, /**< 1: do a back substitution for {x}; 0: don't */ 143 | int *pd ); /**< 1: definite matrix and successful L D L' decomp'n*/ 144 | 145 | 146 | /* 147 | * LDL_MPROVE_PM 148 | * Improves a solution vector x[1..n] of the partitioned set of linear equations 149 | * [A_qq]{x_q} + [A_qr]{x_r} = {b_q} 150 | * [A_rq]{x_q} + [A_rr]{x_r} = {b_r}+{c_r} 151 | * where {b_q}, {b_r}, and {x_r} are known and 152 | * where {x_q} and {c_r} are unknown 153 | * by reducing the residual r_q 154 | * A_qq r_q = {b_q} - [A_qq]{x_q+r_q} + [A_qr]{x_r} 155 | * The matrix A[1..n][1..n], and the vectors b[1..n] and x[1..n] 156 | * are input, as is the dimension n. The matrix [A] is the L D L' 157 | * decomposition of the original system matrix, as returned by ldl_dcmp_pm(). 158 | * Also input is the diagonal vector, {d} of [D] of the L D L' decompositon. 159 | * On output, only {x} is modified to an improved set of values. 160 | * The calculations in ldl_mprove_pm do not involve b_r. 161 | * 162 | * usage: double **A, *d, *b, *x, rms_resid; 163 | * int n, ok, *q, *r; 164 | * ldl_mprove_pm ( A, n, d, b, x, q, r, &rms_resid, &ok ); 165 | * 166 | * H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 167 | * 2001-05-01, 2014-05-14 168 | */ 169 | void ldl_mprove_pm ( 170 | double **A, /**< the system matrix, and L of the L D L' decomp.*/ 171 | int n, /**< the dimension of the matrix */ 172 | double *d, /**< diagonal of D in the L D L' - decomp'n */ 173 | double *b, /**< the right hand side vector */ 174 | double *x, /**< part of the solution vector */ 175 | double *c, /**< the part of the solution vector in the rhs */ 176 | int *q, /**< q[j]=1 if b[j] is known; q[j]=0 otherwise */ 177 | int *r, /**< r[j]=1 if x[j] is known; r[j]=0 otherwise */ 178 | double *rms_resid, /**< root-mean-square of residual error */ 179 | int *ok ); /**< 1: >10% reduction in rms_resid; 0: not */ 180 | 181 | 182 | /* 183 | * PSB_UPDATE 184 | * Update secant stiffness matrix via the Powell-Symmetric-Broyden update eqn. 185 | * 186 | * B = B - (f*d' + d*f') / (d' * d) + f'*d * d*d' / (d' * d)^2 ; 187 | * 188 | * H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 24 Oct 2012 189 | */ 190 | void PSB_update ( 191 | double **B, /**< secant stiffness matrix */ 192 | double *f, /**< out-of-balance force vector */ 193 | double *d, /**< incremental displacement vector */ 194 | int n ); /**< matrix dimension is n-by-n */ 195 | 196 | /* 197 | * PSEUDO_INV - calculate the pseudo-inverse of A , 198 | * Ai = inv ( A'*A + beta * trace(A'*A) * I ) * A' 199 | * beta is a regularization factor, which should be small (1e-10) 200 | * A is m by n Ai is m by n 201 | */ 202 | void pseudo_inv( 203 | double **A, /**< an n-by-m matrix */ 204 | double **Ai, /**< the pseudo-inverse of A */ 205 | int n, int m, /**< matrix dimensions */ 206 | double beta, /**< regularization factor */ 207 | int verbose /**< 1: copious output to screen; 0: none */ 208 | ); 209 | 210 | /* 211 | * PRODABj - matrix-matrix multiplication for symmetric A 27apr01 212 | * u = A * B(:,j) 213 | */ 214 | void prodABj ( double **A, double **B, double *u, int n, int j ); 215 | 216 | /* 217 | * prodAB - matrix-matrix multiplication C = A * B 27apr01 218 | */ 219 | void prodAB ( double **A, double **B, double **C, int nI, int nJ, int nK ); 220 | 221 | /* 222 | * INVAB - calculate product inv(A) * B 223 | * A is n by n B is n by m 6jun07 224 | */ 225 | void invAB( 226 | double **A, double **B, 227 | int n, int m, double **AiB, 228 | int *ok, int verbose ); 229 | 230 | /** 231 | XTAIY - calculate quadratic form with inverse matrix X' * inv(A) * Y 232 | A is n by n X is n by m Y is n by m 15sep01 233 | */ 234 | void xtinvAy( 235 | double **X, double **A, double **Y, int n, int m, double **Ac, int verbose ); 236 | 237 | /* 238 | * xtAx - carry out matrix-matrix-matrix multiplication for symmetric A 7nov02 239 | * C = X' A X C is J by J X is N by J A is N by N 240 | */ 241 | void xtAx(double **A, double **X, double **C, int N, int J); 242 | 243 | /* 244 | * xAy1 - carry out vector-matrix-vector multiplication for symmetric A 7apr94 245 | */ 246 | double xtAy(double *x, double **A, double *y, int n, double *d); 247 | 248 | /* --------------------------------------------------------------------------- 249 | * invAXinvA - calculate quadratic form with inverse matrix 250 | * replace X with inv(A) * X * inv(A) 251 | * A is n by n and symmetric X is n by n and symmetric 15sep01 252 | * --------------------------------------------------------------------------*/ 253 | void invAXinvA ( double **A, double **X, int n, int verbose ); 254 | 255 | /* 256 | * RELATIVE_NORM - compute the relative 2-norm between two vectors 257 | * compute the relative 2-norm between two vectors N and D 258 | * return ( sqrt(sum(N[i]*N[i]) / sqrt(D[i]*D[i]) ) 259 | * 26dec01 260 | */ 261 | double relative_norm( double *N, double *D, int n ); 262 | 263 | /* 264 | * LEGENDRE 265 | * compute matrices of the Legendre polynomials and its first two derivitives 266 | */ 267 | void Legendre( int order, float *t, int n, float **P, float **Pp, float **Ppp ); 268 | 269 | -------------------------------------------------------------------------------- /pyframe3dd/src/py_HPGmatrix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ========================================================================== 3 | * 4 | * Filename: py_HPGmatrix.h 5 | * 6 | * Description: header files for functions in matrix.c 7 | * 8 | * Version: 1.0 9 | * Created: 12/30/11 18:09:26 10 | * Revision: 10/15/12 11 | * Compiler: gcc 12 | * 13 | * Author: Henri P. Gavin (hpgavin), h p gavin ~at~ duke ~dot~ e d v 14 | * Company: Duke Univ. 15 | * 16 | * ========================================================================== 17 | */ 18 | 19 | 20 | /* 21 | Copyright (C) 2012 Henri P. Gavin 22 | 23 | HPGmatrix is free software: you can redistribute it and/or modify 24 | it under the terms of the GNU General Public License as published by 25 | the Free Software Foundation, either version 3 of the License, or 26 | (at your option) any later version. 27 | 28 | HPGmatrix is distributed in the hope that it will be useful, 29 | but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | GNU General Public License for more details. 32 | 33 | You should have received a copy of the GNU General Public License 34 | along with HPGmatrix. If not, see . 35 | */ 36 | 37 | /* 38 | * GAUSSJ 39 | * Linear equation solution by Gauss-Jordan elimination, [A][X]=[B] above. A[1..n][1..n] 40 | * is the input matrix. B[1..n][1..m] is input containing the m right-hand side vectors. On 41 | * output, a is replaced by its matrix inverse, and B is replaced by the corresponding set of solution 42 | * vectors. 43 | */ 44 | void gaussj ( float **A, int n, float **B, int m ); 45 | 46 | /* 47 | * LU_DCMP 48 | * Solves [A]{x} = {b}, simply and efficiently, by performing an 49 | * LU-decomposition of matrix [A]. No pivoting is performed. 50 | * @param A is a diagonally dominant matrix of dimension [1..n][1..n]. 51 | * @param b is a r.h.s. vector of dimension [1..n]. 52 | * 53 | * {b} is updated using [LU] and then back-substitution is done to obtain {x}. 54 | * {b} is replaced by {x} and [A] is replaced by the LU-reduction of itself. 55 | */ 56 | void lu_dcmp ( 57 | double **A, /**< the system matrix, and its LU-reduction */ 58 | int n, /**< the dimension of the matrix */ 59 | double *b, /**< the right hand side vector, and the solution vector */ 60 | int reduce, /**< 1: do a forward reduction; 0: don't */ 61 | int solve, /**< 1: do a back substitution for {x}; 0: don't */ 62 | int *pd /**< 1: positive diagonal and successful LU decomp'n */ 63 | ); 64 | 65 | 66 | /* 67 | * LDL_DCMP 68 | * Solves [A]{x} = {b} simply and efficiently by performing an 69 | * L D L' - decomposition of [A]. No pivoting is performed. 70 | * [A] is a symmetric diagonally-dominant matrix of dimension [1..n][1..n]. 71 | * {b} is a r.h.s. vector of dimension [1..n]. 72 | * {b} is updated using L D L' and then back-substitution is done to obtain {x}. 73 | * {b} is returned unchanged. ldl_dcmp(A,n,d,x,x,1,1,&pd) is valid. 74 | * The lower triangle of [A] is replaced by the lower triangle L of the 75 | * L D L' reduction. The diagonal of D is returned in the vector {d} 76 | */ 77 | void ldl_dcmp ( 78 | double **A, /**< the system matrix, and L of the L D L' decomp.*/ 79 | int n, /**< the dimension of the matrix */ 80 | double *d, /**< diagonal of D in the L D L' - decomp'n */ 81 | double *b, /**< the right hand side vector */ 82 | double *x, /**< the solution vector */ 83 | int reduce, /**< 1: do a forward reduction of A; 0: don't */ 84 | int solve, /**< 1: do a back substitution for {x}; 0: don't */ 85 | int *pd /**< 1: definite matrix and successful L D L' decomp'n*/ 86 | ); 87 | 88 | /* 89 | * LDL_MPROVE improves a solution vector x[1..n] of the linear set of equations 90 | * [A]{x} = {b}. 91 | * The matrix A[1..n][1..n], and the vectors b[1..n] and x[1..n] 92 | * are input, as is the dimension n. The matrix [A] is the L D L' 93 | * decomposition of the original system matrix, as returned by ldl_dcmp(). 94 | * Also input is the diagonal vector, {d} of [D] of the L D L' decompositon. 95 | * On output, only {x} is modified to an improved set of values. 96 | */ 97 | void ldl_mprove( 98 | double **A, 99 | int n, double *d, double *b, double *x, 100 | double *rms_resid, /**< the RMS error of the solution residual */ 101 | int *ok 102 | ); 103 | 104 | 105 | /* 106 | * LDL_DCMP_PM - Solves partitioned matrix equations 107 | * 108 | * [A_qq]{x_q} + [A_qr]{x_r} = {b_q} 109 | * [A_rq]{x_q} + [A_rr]{x_r} = {b_r}+{c_r} 110 | * where {b_q}, {b_r}, and {x_r} are known and 111 | * where {x_q} and {c_r} are unknown 112 | * 113 | * via L D L' - decomposition of [A_qq]. No pivoting is performed. 114 | * [A] is a symmetric diagonally-dominant matrix of dimension [1..n][1..n]. 115 | * {b} is a r.h.s. vector of dimension [1..n]. 116 | * {b} is updated using L D L' and then back-substitution is done to obtain {x} 117 | * {b_q} and {b_r} are returned unchanged. 118 | * {c_r} is returned as a vector of [1..n] with {c_q}=0. 119 | * {q} is a vector of the indexes of known values {b_q} 120 | * {r} is a vector of the indexes of known values {x_r} 121 | * The lower triangle of [A_qq] is replaced by the lower triangle L of its 122 | * L D L' reduction. The diagonal of D is returned in the vector {d} 123 | * 124 | * usage: double **A, *d, *b, *x; 125 | * int n, reduce, solve, pd; 126 | * ldl_dcmp_pm ( A, n, d, b, x, c, q, r, reduce, solve, &pd ); 127 | * 128 | * H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 129 | * Bathe, Finite Element Procecures in Engineering Analysis, Prentice Hall, 1982 130 | * 2014-05-14 131 | */ 132 | void ldl_dcmp_pm ( 133 | double **A, /**< the system matrix, and L of the L D L' decomp.*/ 134 | int n, /**< the dimension of the matrix */ 135 | double *d, /**< diagonal of D in the L D L' - decomp'n */ 136 | double *b, /**< the right hand side vector */ 137 | double *x, /**< part of the solution vector */ 138 | double *c, /**< the part of the solution vector in the rhs */ 139 | int *q, /**< q[j]=1 if b[j] is known; q[j]=0 otherwise */ 140 | int *r, /**< r[j]=1 if x[j] is known; r[j]=0 otherwise */ 141 | int reduce, /**< 1: do a forward reduction of A; 0: don't */ 142 | int solve, /**< 1: do a back substitution for {x}; 0: don't */ 143 | int *pd ); /**< 1: definite matrix and successful L D L' decomp'n*/ 144 | 145 | 146 | /* 147 | * LDL_MPROVE_PM 148 | * Improves a solution vector x[1..n] of the partitioned set of linear equations 149 | * [A_qq]{x_q} + [A_qr]{x_r} = {b_q} 150 | * [A_rq]{x_q} + [A_rr]{x_r} = {b_r}+{c_r} 151 | * where {b_q}, {b_r}, and {x_r} are known and 152 | * where {x_q} and {c_r} are unknown 153 | * by reducing the residual r_q 154 | * A_qq r_q = {b_q} - [A_qq]{x_q+r_q} + [A_qr]{x_r} 155 | * The matrix A[1..n][1..n], and the vectors b[1..n] and x[1..n] 156 | * are input, as is the dimension n. The matrix [A] is the L D L' 157 | * decomposition of the original system matrix, as returned by ldl_dcmp_pm(). 158 | * Also input is the diagonal vector, {d} of [D] of the L D L' decompositon. 159 | * On output, only {x} is modified to an improved set of values. 160 | * The calculations in ldl_mprove_pm do not involve b_r. 161 | * 162 | * usage: double **A, *d, *b, *x, rms_resid; 163 | * int n, ok, *q, *r; 164 | * ldl_mprove_pm ( A, n, d, b, x, q, r, &rms_resid, &ok ); 165 | * 166 | * H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 167 | * 2001-05-01, 2014-05-14 168 | */ 169 | void ldl_mprove_pm ( 170 | double **A, /**< the system matrix, and L of the L D L' decomp.*/ 171 | int n, /**< the dimension of the matrix */ 172 | double *d, /**< diagonal of D in the L D L' - decomp'n */ 173 | double *b, /**< the right hand side vector */ 174 | double *x, /**< part of the solution vector */ 175 | double *c, /**< the part of the solution vector in the rhs */ 176 | int *q, /**< q[j]=1 if b[j] is known; q[j]=0 otherwise */ 177 | int *r, /**< r[j]=1 if x[j] is known; r[j]=0 otherwise */ 178 | double *rms_resid, /**< root-mean-square of residual error */ 179 | int *ok ); /**< 1: >10% reduction in rms_resid; 0: not */ 180 | 181 | 182 | /* 183 | * PSB_UPDATE 184 | * Update secant stiffness matrix via the Powell-Symmetric-Broyden update eqn. 185 | * 186 | * B = B - (f*d' + d*f') / (d' * d) + f'*d * d*d' / (d' * d)^2 ; 187 | * 188 | * H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 24 Oct 2012 189 | */ 190 | void PSB_update ( 191 | double **B, /**< secant stiffness matrix */ 192 | double *f, /**< out-of-balance force vector */ 193 | double *d, /**< incremental displacement vector */ 194 | int n ); /**< matrix dimension is n-by-n */ 195 | 196 | /* 197 | * PSEUDO_INV - calculate the pseudo-inverse of A , 198 | * Ai = inv ( A'*A + beta * trace(A'*A) * I ) * A' 199 | * beta is a regularization factor, which should be small (1e-10) 200 | * A is m by n Ai is m by n 201 | */ 202 | void pseudo_inv( 203 | double **A, /**< an n-by-m matrix */ 204 | double **Ai, /**< the pseudo-inverse of A */ 205 | int n, int m, /**< matrix dimensions */ 206 | double beta, /**< regularization factor */ 207 | int verbose /**< 1: copious output to screen; 0: none */ 208 | ); 209 | 210 | /* 211 | * PRODABj - matrix-matrix multiplication for symmetric A 27apr01 212 | * u = A * B(:,j) 213 | */ 214 | void prodABj ( double **A, double **B, double *u, int n, int j ); 215 | 216 | /* 217 | * prodAB - matrix-matrix multiplication C = A * B 27apr01 218 | */ 219 | void prodAB ( double **A, double **B, double **C, int nI, int nJ, int nK ); 220 | 221 | /* 222 | * INVAB - calculate product inv(A) * B 223 | * A is n by n B is n by m 6jun07 224 | */ 225 | void invAB( 226 | double **A, double **B, 227 | int n, int m, double **AiB, 228 | int *ok, int verbose ); 229 | 230 | /** 231 | XTAIY - calculate quadratic form with inverse matrix X' * inv(A) * Y 232 | A is n by n X is n by m Y is n by m 15sep01 233 | */ 234 | void xtinvAy( 235 | double **X, double **A, double **Y, int n, int m, double **Ac, int verbose ); 236 | 237 | /* 238 | * xtAx - carry out matrix-matrix-matrix multiplication for symmetric A 7nov02 239 | * C = X' A X C is J by J X is N by J A is N by N 240 | */ 241 | void xtAx(double **A, double **X, double **C, int N, int J); 242 | 243 | /* 244 | * xAy1 - carry out vector-matrix-vector multiplication for symmetric A 7apr94 245 | */ 246 | double xtAy(double *x, double **A, double *y, int n, double *d); 247 | 248 | /* --------------------------------------------------------------------------- 249 | * invAXinvA - calculate quadratic form with inverse matrix 250 | * replace X with inv(A) * X * inv(A) 251 | * A is n by n and symmetric X is n by n and symmetric 15sep01 252 | * --------------------------------------------------------------------------*/ 253 | void invAXinvA ( double **A, double **X, int n, int verbose ); 254 | 255 | /* 256 | * RELATIVE_NORM - compute the relative 2-norm between two vectors 257 | * compute the relative 2-norm between two vectors N and D 258 | * return ( sqrt(sum(N[i]*N[i]) / sqrt(D[i]*D[i]) ) 259 | * 26dec01 260 | */ 261 | double relative_norm( double *N, double *D, int n ); 262 | 263 | /* 264 | * LEGENDRE 265 | * compute matrices of the Legendre polynomials and its first two derivitives 266 | */ 267 | void Legendre( int order, float *t, int n, float **P, float **Pp, float **Ppp ); 268 | 269 | -------------------------------------------------------------------------------- /pyframe3dd/src/preframe.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | preframe.c - interactive data input for frame analysis program 3 | to compile: gcc -O -o preframe preframe.c 4 | to run: preframe output_file 5 | David Hoang, Duke University, April, 1997 6 | ******************************************************************************/ 7 | 8 | #include 9 | #include 10 | #include 11 | #define MAXLINE 80 12 | 13 | void file_names(void); 14 | void joint_loads(void); 15 | void distrb_loads(void); 16 | void concen_loads(void); 17 | void temperature(void); 18 | void reactions(void); 19 | void displacements(void); 20 | void modal_files(void); 21 | void inertia(void); 22 | 23 | FILE *fpout; 24 | 25 | int nJ=0, /* number of joints */ 26 | nM=0, /* number of members */ 27 | nF=0, /* number of joint loads */ 28 | nW=0, /* number of distributed member loads */ 29 | nP=0, /* number of concentrated member loads */ 30 | nT=0, /* number of thermal loads */ 31 | nR=0, /* number of supported joints (reactions) */ 32 | nD=0; /* number of prescribed displacements */ 33 | 34 | void main(argc, argv) 35 | int argc; 36 | char *argv[]; 37 | { 38 | char ans; 39 | int j, m; /* a joint number, a member number */ 40 | float x, y, z, r; /* joint coordinates */ 41 | 42 | int J1, J2; /* member location joints */ 43 | float Ax, Ay, Az; /* member cross section area properties */ 44 | float Jp, Iy, Iz; /* member cross section inertia prop's */ 45 | float E,G; /* member material property constants */ 46 | 47 | 48 | if (argc <= 2) { 49 | if ((fpout = fopen (argv[1], "w")) == 0) { 50 | fprintf (stderr," error: cannot open file '%s'\n", argv[2]); 51 | fprintf (stderr," usage: preframe output_file\n"); 52 | exit(0); 53 | } 54 | } else { 55 | fprintf (stderr," usage: preframe output_file\n"); 56 | exit(0); 57 | } 58 | 59 | /********* Start Execution **********/ 60 | 61 | do { 62 | printf("How many joints do you have? "); scanf ("%d",&nJ); 63 | printf("How many members do you have? "); scanf ("%d",&nM); 64 | printf("\n\t%5d joints %5d members ", nJ, nM ); 65 | printf("\t\t ... Is this okay? (y/n) "); scanf ("%s", &ans); 66 | } while ( ans !='y' ); 67 | 68 | fprintf(fpout,"%d %d \n\n",nJ, nM); 69 | 70 | /***** Joint Data *****/ 71 | 72 | printf("\nFor each joint, enter its x,y,z coordinates and its radius, r .\n"); 73 | for (j=1; j<=nJ ; j++) { 74 | do { 75 | printf("\n For joint %i, enter coordinate values ... \n", j ); 76 | printf(" input x[%i] : ",j); scanf ("%f",&x); 77 | printf(" input y[%i] : ",j); scanf ("%f",&y); 78 | printf(" input z[%i] : ",j); scanf ("%f",&z); 79 | printf(" input r[%i] : ",j); scanf ("%f",&r); 80 | printf("joint x y z r\n",j,j,j,j); 81 | printf("----- ------------ ------------ ------------ ----------\n"); 82 | printf("%5d %12.4f %12.4f %12.4f %10.4f \n",j, x, y, z, r); 83 | printf("\t\t\t\t\t\t ... Is this okay? (y/n) "); scanf ("%s", &ans); 84 | } while ( ans !='y'); 85 | fprintf(fpout,"%4d %12.4f %12.4f %12.4f %12.4f\n", j, x, y, z, r); 86 | } 87 | 88 | /***** Member Data *****/ 89 | 90 | printf("\nFor each member, enter its geometric and material properties.\n"); 91 | printf("Members connect joints 'J1' to 'J2' \n"); 92 | fprintf(fpout,"\n"); 93 | for (m=1; m<=nM ; m++) { 94 | do { 95 | printf("\n For member %i, enter values for the ... \n", m); 96 | printf(" joint number J1[%i] : ",m); scanf ("%d", &J1); 97 | printf(" joint number J2[%i] : ",m); scanf ("%d", &J2); 98 | printf(" cross section area, Ax[%i] : ",m); scanf ("%f", &Ax); 99 | printf(" shear section area, Ay[%i] : ",m); scanf ("%f", &Ay); 100 | printf(" shear section area, Az[%i] : ",m); scanf ("%f", &Az); 101 | printf(" torsion moment of inertia, Jp[%i] : ",m); scanf("%f", &Jp); 102 | printf(" bending moment of inertia, Iy[%i] : ",m); scanf("%f", &Iy); 103 | printf(" bending moment of inertia, Iz[%i] : ",m); scanf("%f", &Iz); 104 | printf(" Young's elastic modulus, E[%i] : ",m); scanf ("%f", &E); 105 | printf(" shear elastic modulus, G[%i] : ",m); scanf ("%f", &G); 106 | printf(" J1 J2 Ax Ay Az Jp Iy Iz E G \n"); 107 | printf("---- ---- ----- ----- ----- ------ ------ ------ ------- -------"); 108 | printf("\n%4d %4d %5.1f %5.1f %5.1f %6.1f %6.1f %6.1f %7.1f %7.1f \n", 109 | J1, J2, Ax, Ay, Az, Jp, Iy, Iz, E, G ); 110 | printf("\t\t\t\t\t\t ... Is this okay? (y/n) "); scanf ("%s", &ans); 111 | } while( ans != 'y' || J1 > nJ || J2 > nJ || E == 0 ); 112 | 113 | fprintf(fpout,"%4d %4d %4d %7.1f %7.1f %7.1f", m, J1, J2, Ax, Ay, Az ); 114 | fprintf(fpout,"%7.1f %7.1f %7.1f %7.1f %7.1f\n", Jp, Iy, Iz, E, G ); 115 | } 116 | 117 | file_names(); 118 | joint_loads(); 119 | distrb_loads(); 120 | concen_loads(); 121 | temperature(); 122 | reactions(); 123 | displacements(); 124 | modal_files(); 125 | inertia(); 126 | 127 | fclose(fpout); 128 | 129 | } /*end main */ 130 | 131 | 132 | /***** Mesh, shear, analysis, and annotation file name *****/ 133 | void file_names(void) 134 | { float exagg /*exagg mesh deformations*/; 135 | 136 | int shear, /*include shear deformations*/ 137 | anlyz; /*1:stiff analysis 0:data check only*/ 138 | 139 | char ans, /*for use in yes/no procedure */ 140 | mesh_file[MAXLINE], /* mesh file name */ 141 | ann_file[MAXLINE]; 142 | 143 | do { 144 | printf("\nEnter \"1\" to include shear deformation. "); 145 | printf(" Otherwise, enter \"0\" : "); 146 | scanf ("%i",&shear);} 147 | while (shear !=1 && shear != 0); 148 | 149 | do { 150 | printf("\nWhat is the mesh file name? "); scanf ("%s", mesh_file); 151 | printf(" The file name you input is %s", mesh_file ); 152 | printf(" ... Is this okay? (y/n) "); scanf ("%s", &ans); 153 | } while (ans != 'y'); 154 | 155 | do { 156 | printf("\nWhat is the annotation file name? "); 157 | scanf ("%s", ann_file); 158 | printf(" The file name you input is %s", ann_file); 159 | printf(" ... Is this okay? (y/n) "); scanf ("%s", &ans); 160 | } while (ans != 'y'); 161 | 162 | do { 163 | printf("\nBy what factor do you want to exaggerate mesh deformation? "); 164 | scanf ("%f", &exagg); 165 | printf(" The number you input is %f ", exagg ); 166 | printf(" ... Is this okay? (y/n) "); scanf ("%s", &ans); 167 | } while ( ans != 'y'); 168 | 169 | do { 170 | printf("\nEnter \"1\" to include stiffness analysis. "); 171 | printf("Enter \"0\" to data check only. "); scanf ("%i",&anlyz); 172 | } while ( anlyz != 1 && anlyz != 0 ); 173 | 174 | fprintf(fpout,"\n%d\n",shear); 175 | fprintf(fpout,"%s %s %f\n", mesh_file, ann_file, exagg); 176 | fprintf(fpout,"%d\n", anlyz); 177 | } 178 | 179 | /***** Loaded Joints *****/ 180 | void joint_loads(void) 181 | { 182 | char ans; 183 | int j, f; 184 | float Fx, Fy, Fz, Mxx, Myy, Mzz; /*loaded joints*/ 185 | 186 | printf ("\nYour frame may have concentrated loads at the joints.\n"); 187 | do { 188 | printf (" Input the number of joint loads : "); scanf ("%d",&nF); 189 | printf(" %5d joint loads", nF ); 190 | printf("\t\t\t\t ... Is this okay? (y/n) "); 191 | scanf("%s", &ans); 192 | } while( ans != 'y' || nF < 0 ); 193 | 194 | fprintf(fpout,"\n%d\n", nF); 195 | 196 | for ( f=1; f<=nF ; f++ ) { 197 | do { 198 | printf(" Enter the joint number for joint load number %d : ", f); 199 | scanf("%d", &j); 200 | printf(" For joint %d, input values for the ... \n", j); 201 | printf(" point force in the x-direction, Fx[%d] : ",j); 202 | scanf ("%f",&Fx); 203 | printf(" point force in the y-direction, Fy[%d] : ",j); 204 | scanf ("%f",&Fy); 205 | printf(" point force in the z-direction, Fz[%d] : ",j); 206 | scanf ("%f",&Fz); 207 | printf(" moment about the x-axis, Mxx[%d] : ",j); 208 | scanf ("%f",&Mxx); 209 | printf(" moment about the y-axis, Myy[%d] : ",j); 210 | scanf ("%f",&Myy); 211 | printf(" moment about the z-axis, Mzz[%d] : ",j); 212 | scanf ("%f",&Mzz); 213 | printf("joint Fx Fy Fz Mxx Myy Mzz \n"); 214 | printf("----- -------- -------- -------- -------- -------- --------\n"); 215 | printf("%5d %8.3f %8.3f %8.3f %8.2f %8.2f %8.2f\n", 216 | j, Fx, Fy, Fz, Mxx, Myy, Mzz ); 217 | printf("\t\t\t\t\t\t ... Is this okay? (y/n) "); scanf("%s", &ans); 218 | } while( ans != 'y' || j > nJ ); 219 | fprintf(fpout,"%4d %f %f %f %f %f %f\n", j, Fx,Fy,Fz, Mxx,Myy,Mzz ); 220 | } /*****End "for" Loaded Joints ****/ 221 | 222 | } /* end Function joint_loads */ 223 | 224 | 225 | /***** Uniform Distributed Loads *****/ 226 | void distrb_loads(void) 227 | { 228 | int m, f; 229 | char ans; 230 | float Wx, Wy, Wz; /*Uniform Distributed loads*/ 231 | 232 | printf ("\nYour frame may have distributed loads on the members.\n"); 233 | do { 234 | printf (" Input the number of distributed loads : "); scanf ("%d",&nW); 235 | printf(" %5d distributed loads", nW ); 236 | printf("\t\t\t ... Is this okay? (y/n) "); 237 | scanf("%s", &ans); 238 | } while( ans != 'y' || nW < 0 ); 239 | 240 | fprintf(fpout,"\n%d\n", nW); 241 | 242 | for (f=1; f<=nW ; f++) { 243 | do { 244 | printf(" Enter the member number for distributed load number %d : ", f); 245 | scanf("%d", &m); 246 | printf(" For member %d, input values for the ... \n", m); 247 | printf(" distributed load in the x-direction, Wx[%d] : ",m); 248 | scanf ("%f",&Wx); 249 | printf(" distributed load in the y-direction, Wy[%d] : ",m); 250 | scanf ("%f",&Wy); 251 | printf(" distributed load in the z-direction, Wz[%d] : ",m); 252 | scanf ("%f",&Wz); 253 | printf("member Wx Wy Wz \n"); 254 | printf("------ ------------ ------------ ------------\n"); 255 | printf("%6d %12.4f %12.4f %12.4f", m, Wx, Wy, Wz ); 256 | printf(" ... Is this okay? (y/n) "); scanf ("%s", &ans); 257 | } while( ans != 'y' || m > nM ); 258 | fprintf(fpout,"%4d %.4f %.4f %.4f\n",m, Wx, Wy, Wz); 259 | } /*****End "for" Loaded Members ****/ 260 | 261 | } /* end Function distrb_loads */ 262 | 263 | 264 | /***** Concentrated Point Loads On Members *****/ 265 | void concen_loads (void) 266 | { 267 | char ans; 268 | int m=0,f=0; 269 | float Px, Py, Pz, x; 270 | 271 | printf ("\nYour frame may have point loads on the members.\n"); 272 | printf("Point loads are specified by their values in member coordinates"); 273 | printf(" (Px, Py, Pz),\n"); 274 | printf("and a distance (x) along the member from joint J1.\n"); 275 | 276 | do { 277 | printf (" Input the number of point loads : "); scanf ("%d",&nP); 278 | printf(" %5d concentrated point loads", nP ); 279 | printf("\t\t\t ... Is this okay? (y/n) "); 280 | scanf("%s", &ans); 281 | } while( ans != 'y' || nP < 0 ); 282 | 283 | fprintf(fpout,"\n%d\n", nP); 284 | 285 | for (f=1; f<=nP ; f++) { 286 | do { 287 | printf(" Enter the member number for concentrated load number %d : ",f); 288 | scanf("%d", &m); 289 | printf(" For member %d, input values for the ... \n", m); 290 | printf(" concentrated load in the x-direction, Px[%d] : ",m); 291 | scanf ("%f",&Px); 292 | printf(" concentrated load in the y-direction, Py[%d] : ",m); 293 | scanf ("%f",&Py); 294 | printf(" concentrated load in the z-direction, Pz[%d] : ",m); 295 | scanf ("%f",&Pz); 296 | printf(" distance from joint J1, x[%d] : ",m); 297 | scanf ("%f",&x); 298 | printf("member Px Py Pz x \n"); 299 | printf("------ ------------ ------------ ------------ -------- \n"); 300 | printf("%6d %12.4f %12.4f %12.4f %8.3f\n", m, Px, Py, Pz, x ); 301 | printf("\t\t\t\t\t\t ... Is this okay? (y/n) "); scanf("%s", &ans); 302 | } while( ans != 'y' || m < 1 || m > nM ); 303 | fprintf(fpout,"%4d %f %f %f %f\n",m, Px, Py, Pz, x); 304 | } 305 | } /* end Function concen_loads */ 306 | 307 | 308 | /***** Temperature Changes *****/ 309 | void temperature(void) 310 | { 311 | int m, t; 312 | char ans; 313 | float a, hy, hz, /* member properties */ 314 | Typls, Tymin, Tzpls, Tzmin ; /* temperature changes */ 315 | 316 | printf("\nYou may specify temperature changes or thermal gradients "); 317 | printf("for any member.\n"); 318 | printf("These are specified by the coef. of thermal expansion (a), \n"); 319 | printf("member depths (hy,hz) and surface temperatures "); 320 | printf("(Ty+, Ty-, Tz+, Tz-).\n"); 321 | 322 | do { 323 | printf (" Input the number of members with temperature changes : "); 324 | scanf ("%d", &nT); 325 | printf(" %5d members with temperature changes", nT ); 326 | printf("\t\t ... Is this okay? (y/n) "); scanf("%s", &ans); 327 | } while( ans != 'y' || nT < 0 || nT > nM ); 328 | 329 | fprintf(fpout,"\n%d\n", nT); 330 | 331 | for ( t=1; t <= nT; t++ ) { 332 | do { 333 | printf(" Enter the member number for temperature change %d : ",t); 334 | scanf("%d", &m); 335 | printf(" For member %d, input values for the ... \n", m); 336 | printf(" coefficient of thermal expansion, a[%d] : ",m); 337 | scanf ("%f", &a); 338 | printf(" depth in the local y direction, hy[%d] : ",m); 339 | scanf ("%f", &hy); 340 | printf(" depth in the local z direction, hy[%d] : ",m); 341 | scanf ("%f", &hz); 342 | printf(" temperature on the positive y surface, Ty+[%d] : ",m); 343 | scanf ("%f", &Typls); 344 | printf(" temperature on the negative y surface, Ty-[%d] : ",m); 345 | scanf ("%f", &Tymin); 346 | printf(" temperature on the positive z surface, Tz+[%d] : ",m); 347 | scanf ("%f", &Tzpls); 348 | printf(" temperature on the negative z surface, Tz-[%d] : ",m); 349 | scanf ("%f", &Tzmin); 350 | printf("member a hy hz Ty+ Ty- Tz+ Tz- \n"); 351 | printf("------ ------- ------- ------- ------ ------ ------ ------ \n"); 352 | printf("%6d %7.1e %7.3f %7.3f %6.1f %6.1f %6.1f %6.1f \n", 353 | m, a, hy, hz, Typls, Tymin, Tzpls, Tzmin ); 354 | printf("\t\t\t\t\t\t ... Is this okay? (y/n) "); scanf("%s", &ans); 355 | } while( ans != 'y' || m < 1 || m > nM ); 356 | fprintf(fpout,"%4d %.4e %.3f %.3f %.3f %.3f %.3f %.3f \n", 357 | m, a, hy, hz, Typls, Tymin, Tzpls, Tzmin ); 358 | } 359 | } /* end function temperature */ 360 | 361 | /***** Reactions *****/ 362 | void reactions(void) 363 | { 364 | int j, r; 365 | char ans; 366 | int Rx, Ry, Rz, Rxx, Ryy, Rzz; /*Restrained Joints */ 367 | 368 | printf("\nYou must specify enough reactions "); 369 | printf("to restrain your frame in all six directions.\n"); 370 | do { 371 | printf (" Input the number of restrained joints : "); scanf ("%d",&nR); 372 | printf(" %5d restrained joints", nR ); 373 | printf("\t\t\t ... Is this okay? (y/n) "); scanf("%s", &ans); 374 | } while( ans != 'y' || nR < 1 || nR > nJ ); 375 | 376 | fprintf(fpout,"\n%d\n", nR); 377 | 378 | for (r=1; r <= nR; r++) { 379 | do { 380 | printf(" Enter the joint number for reaction number %d : ", r); 381 | scanf ("%d", &j); 382 | printf(" For joint %d, input values for the ... \n", j); 383 | printf(" x- direction reaction (1:fixed 0:free), Rx[%i] : ",j); 384 | scanf ("%d", &Rx); 385 | printf(" y- direction reaction (1:fixed 0:free), Ry[%i] : ",j); 386 | scanf ("%d", &Ry); 387 | printf(" z- direction reaction (1:fixed 0:free), Rz[%i] : ",j); 388 | scanf ("%d", &Rz); 389 | printf(" x-axis moment reaction (1:fixed 0:free), Rxx[%i] : ",j); 390 | scanf ("%d", &Rxx); 391 | printf(" y-axis moment reaction (1:fixed 0:free), Ryy[%i] : ",j); 392 | scanf ("%d", &Ryy); 393 | printf(" z-axis moment reaction (1:fixed 0:free), Rzz[%i] : ",j); 394 | scanf ("%d", &Rzz); 395 | 396 | printf("joint Rx Ry Rz Rxx Ryy Rzz \n"); 397 | printf("----- --- --- --- --- --- --- \n"); 398 | printf("%5d %3d %3d %3d %3d %3d %3d", j, Rx, Ry, Rz, Rxx, Ryy, Rzz ); 399 | printf("\t\t\t ... Is this okay? (y/n) "); 400 | scanf("%s", &ans); 401 | } while( tolower(ans) != 'y' || j < 1 || j > nJ ); 402 | fprintf(fpout,"%4d %3d %3d %3d %3d %3d %3d \n", j, Rx,Ry,Rz, Rxx,Ryy,Rzz ); 403 | } 404 | } 405 | 406 | /***** Prescribed Displacements *****/ 407 | void displacements(void) 408 | { 409 | int j, d; 410 | char ans; 411 | float Dx, Dy, Dz, Dxx, Dyy, Dzz; 412 | 413 | printf("\nYou may prescribe a displacement "); 414 | printf("at any coordinate that has a reaction.\n"); 415 | do { 416 | printf (" Input the number of joints with prescribed displacements : "); 417 | scanf ("%d",&nD); 418 | printf(" %5d prescribed displacements", nD ); 419 | printf("\t\t\t ... Is this okay? (y/n) "); scanf("%s", &ans); 420 | } while( ans != 'y' || nD < 0 || nD > nR ); 421 | 422 | fprintf(fpout,"\n%d\n", nD); 423 | 424 | for (d=1; d <= nD; d++) { 425 | do { 426 | printf(" Enter the joint number for displacement number %d : ", d); 427 | scanf ("%d", &j); 428 | printf(" For joint %d, input values for the ... \n", j); 429 | printf(" x-direction displacement Dx[%i] : ", j); scanf ("%f", &Dx); 430 | printf(" y-direction displacement Dy[%i] : ", j); scanf ("%f", &Dy); 431 | printf(" z-direction displacement Dz[%i] : ", j); scanf ("%f", &Dz); 432 | printf(" x- axis rotation Dxx[%i] : ", j); scanf ("%f", &Dxx ); 433 | printf(" y- axis rotation Dyy[%i] : ", j); scanf ("%f", &Dyy ); 434 | printf(" z- axis rotation Dzz[%i] : ", j); scanf ("%f", &Dzz ); 435 | 436 | printf("joint Dx Dy Dz Dxx Dyy Dzz \n"); 437 | printf("----- -------- -------- -------- -------- -------- --------\n"); 438 | printf("%5d %8.5f %8.5f %8.5f %8.6f %8.6f %8.6f \n", 439 | j, Dx, Dy, Dz, Dxx, Dyy, Dzz ); 440 | printf("\t\t\t\t\t\t ... Is this okay? (y/n) "); scanf("%s", &ans); 441 | } while( tolower(ans) == 'n' || j < 1 || j > nJ ); 442 | fprintf(fpout,"%4d %8.5f %8.5f %8.5f %8.6f %8.6f %8.6f \n", 443 | j, Dx, Dy, Dz, Dxx, Dyy, Dzz ); 444 | } 445 | } 446 | 447 | /***** DYNAMIC INERTIA DATA INPUT *****/ 448 | void modal_files(void) 449 | { 450 | char ans, mode_file[MAXLINE]; 451 | int lump, modes; 452 | float tol; 453 | 454 | printf("\nYou may compute dynamic vibrational properties for your frame.\n"); 455 | do { 456 | printf(" Input the number of desired modes : "); 457 | scanf("%d", &modes); 458 | do { 459 | printf(" Input 0 for consistent mass, 1 for lumped : "); 460 | scanf("%d",&lump); 461 | } while( lump!=0 && lump!=1 ); 462 | printf(" Input the mode shape data file name : "); 463 | scanf("%s", mode_file); 464 | printf(" Input the convergence tolerance : "); 465 | scanf("%f",&tol); 466 | printf("modes lump mode file name tol \n"); 467 | printf("----- ---- -------------------- --------\n"); 468 | printf("%5d %4d %20s %8.6f", modes, lump, mode_file, tol ); 469 | printf(" ... Is this okay? (y/n) "); scanf("%s", &ans); 470 | } while( tolower(ans) != 'y' || modes > nJ || tol <= 0 ); 471 | 472 | fprintf(fpout,"\n%d \n%d \n %.80s \n %f \n", modes, lump, mode_file, tol ); 473 | } /* ^^^-THIS IS THE FIX ... don't ask me why ... */ 474 | 475 | /***** Member Density and extra masses, not including self masses *****/ 476 | void inertia(void) 477 | { 478 | int m; 479 | char ans; 480 | float d, Ms; 481 | 482 | printf(" You must specify density and lumped masses for each member\n"); 483 | 484 | for (m=1; m<=nM ; m++) { 485 | do { 486 | printf(" For member %i, input values for the ...\n", m); 487 | printf(" mass density, d[%i] : ",m); scanf ("%f",&d ); 488 | printf(" lumped mass, Ms[%i] : ",m); scanf ("%f",&Ms ); 489 | printf("member d Ms \n", m, m); 490 | printf("------ ------------ ------------ \n"); 491 | printf("%6d %12.8f %12.8f", m, d, Ms ); 492 | printf("\t\t ... Is this okay? (y/n) "); scanf("%s", &ans); 493 | } while ( tolower(ans) != 'y' || (Ms <= 0 && d <= 0) ); 494 | fprintf(fpout,"%4d %f %f \n", m, d, Ms ); 495 | } 496 | } 497 | -------------------------------------------------------------------------------- /pyframe3dd/src/eig.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FRAME3DD: 3 | Static and dynamic structural analysis of 2D and 3D frames and trusses with 4 | elastic and geometric stiffness. 5 | --------------------------------------------------------------------------- 6 | http://frame3dd.sourceforge.net/ 7 | --------------------------------------------------------------------------- 8 | Copyright (C) 1992-2009 Henri P. Gavin 9 | 10 | FRAME3DD is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | FRAME3DD is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with FRAME3DD. If not, see . 22 | *//** 23 | @file 24 | Routines to solve the generalized eigenvalue problem 25 | 26 | Henri P. Gavin hpgavin@duke.edu 27 | Department of Civil and Environmental Engineering 28 | Duke University, Box 90287 29 | Durham, NC 27708--0287 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include "eig.h" 37 | #include "common.h" 38 | #include "HPGmatrix.h" 39 | #include "HPGutil.h" 40 | #include "NRutil.h" 41 | 42 | /* #define EIG_DEBUG */ 43 | 44 | /* forward declarations */ 45 | 46 | static void jacobi( double **K, double **M, double *E, double **V, int n ); 47 | 48 | static void rotate ( double **A, int n,double alpha, double beta, int i,int j); 49 | 50 | void eigsort ( double *e, double **v, int n, int m); 51 | 52 | int sturm ( double **K, double **M, int n, int m, double shift, double ws, int verbose ); 53 | 54 | /*----------------------------------------------------------------------------- 55 | SUBSPACE - Find the lowest m eigen-values, w, and eigen-vectors, V, of the 56 | general eigen-problem ... K V = w M V using sub-space / Jacobi iteration 57 | where 58 | K is an n by n symmetric real (stiffness) matrix 59 | M is an n by n symmetric positive definate real (mass) matrix 60 | w is a diagonal matrix of eigen-values 61 | V is a rectangular matrix of eigen-vectors 62 | 63 | H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 1 March 2007 64 | Bathe, Finite Element Procecures in Engineering Analysis, Prentice Hall, 1982 65 | -----------------------------------------------------------------------------*/ 66 | void subspace( 67 | double **K, double **M, 68 | int n, int m, /**< DoF and number of required modes */ 69 | double *w, double **V, 70 | double tol, double shift, 71 | int *iter, /**< sub-space iterations */ 72 | int *ok, /**< Sturm check result */ 73 | int verbose 74 | ){ 75 | double **Kb, **Mb, **Xb, **Qb, *d, *u, *v, km, km_old, 76 | error=1.0, w_old = 0.0; 77 | 78 | int i=0, j=0, k=0, 79 | modes, 80 | disp = 0, /* display convergence info. */ 81 | *idx; 82 | char errMsg[MAXL]; 83 | 84 | if ( m > n ) { 85 | sprintf(errMsg,"subspace: Number of eigen-values must be less than the problem dimension.\n Desired number of eigen-values=%d \n Dimension of the problem= %d \n", m, n); 86 | errorMsg(errMsg); 87 | exit(32); 88 | } 89 | 90 | d = dvector(1,n); 91 | u = dvector(1,n); 92 | v = dvector(1,n); 93 | Kb = dmatrix(1,m,1,m); 94 | Mb = dmatrix(1,m,1,m); 95 | Xb = dmatrix(1,n,1,m); 96 | Qb = dmatrix(1,m,1,m); 97 | idx = ivector(1,m); 98 | 99 | for (i=1; i<=m; i++) { 100 | idx[i] = 0; 101 | for (j=i; j<=m; j++) 102 | Kb[i][j]=Kb[j][i] = Mb[i][j]=Mb[j][i] = Qb[i][j]=Qb[j][i] = 0.0; 103 | } 104 | 105 | for (i=1; i<=n; i++) for (j=1; j<=m; j++) Xb[i][j] = V[i][j] = 0.0; 106 | 107 | modes = (int) ( (double)(0.5*m) > (double)(m-8.0) ? (int)(m/2.0) : m-8 ); 108 | 109 | /* shift eigen-values by this much */ 110 | for (i=1;i<=n;i++) for (j=i;j<=n;j++) K[i][j] += shift*M[i][j]; 111 | 112 | 113 | ldl_dcmp ( K, n, u, v, v, 1, 0, ok ); /* use L D L' decomp */ 114 | 115 | for (i=1; i<=n; i++) { 116 | if ( M[i][i] <= 0.0 ) { 117 | sprintf(errMsg," subspace: M[%d][%d] = %e \n", i,i, M[i][i] ); 118 | errorMsg(errMsg); 119 | exit(32); 120 | } 121 | d[i] = K[i][i] / M[i][i]; 122 | } 123 | 124 | km_old = 0.0; 125 | for (k=1; k<=m; k++) { 126 | km = d[1]; 127 | for (i=1; i<=n; i++) { 128 | if ( km_old <= d[i] && d[i] <= km ) { 129 | *ok = 1; 130 | for (j=1; j<=k-1; j++) if ( i == idx[j] ) *ok = 0; 131 | if (*ok) { 132 | km = d[i]; 133 | idx[k] = i; 134 | } 135 | } 136 | } 137 | if ( idx[k] == 0 ) { 138 | i = idx[1]; 139 | for ( j=1; j 1000 ) { 205 | sprintf(errMsg," subspace: Iteration limit exceeded\n rel. error = %e > %e\n", error, tol ); 206 | errorMsg(errMsg); 207 | exit(32); 208 | } 209 | 210 | } while ( error > tol ); /* End sub-space iterations */ 211 | 212 | 213 | for (k=1; k<=m; k++) { /* shift eigen-values */ 214 | if ( w[k] > shift ) w[k] = w[k] - shift; 215 | else w[k] = shift - w[k]; 216 | } 217 | 218 | if ( verbose ) { 219 | fprintf(stdout," %4d sub-space iterations, error: %.4e \n", *iter, error ); 220 | for ( k=1; k<=m; k++ ) 221 | fprintf(stdout," mode: %2d\tDoF: %5d\t %9.4lf Hz\n", 222 | k, idx[k], sqrt(w[k])/(2.0*PI) ); 223 | } 224 | 225 | *ok = sturm ( K, M, n, m, shift, w[modes]+tol, verbose ); 226 | 227 | for (i=1;i<=n;i++) for (j=i;j<=n;j++) K[i][j] -= shift*M[i][j]; 228 | 229 | free_dmatrix(Kb,1,m,1,m); 230 | free_dmatrix(Mb,1,m,1,m); 231 | free_dmatrix(Xb,1,n,1,m); 232 | free_dmatrix(Qb,1,m,1,m); 233 | 234 | return; 235 | } 236 | 237 | 238 | /*----------------------------------------------------------------------------- 239 | JACOBI - Find all eigen-values, E, and eigen-vectors, V, 240 | of the general eigen-problem K V = E M V 241 | using Jacobi iteration, with efficient matrix rotations. 242 | K is a symmetric real (stiffness) matrix 243 | M is a symmetric positive definate real (mass) matrix 244 | E is a diagonal matrix of eigen-values 245 | V is a square matrix of eigen-vectors 246 | 247 | H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 1 March 2007 248 | Bathe, Finite Element Procecures in Engineering Analysis, Prentice Hall, 1982 249 | -----------------------------------------------------------------------------*/ 250 | void jacobi ( double **K, double **M, double *E, double **V, int n ) 251 | { 252 | int iter, 253 | d,i,j,k; 254 | double Kii, Kjj, Kij, Mii, Mjj, Mij, Vki, Vkj, 255 | alpha, beta, gamma, 256 | s, tol=0.0; 257 | 258 | Kii = Kjj = Kij = Mii = Mjj = Mij = Vki = Vkj = 0.0; 259 | 260 | for (i=1; i<=n; i++) for (j=i+1; j<=n; j++) V[i][j] = V[j][i] = 0.0; 261 | for (d=1; d<=n; d++) V[d][d] = 1.0; 262 | 263 | for (iter=1; iter<=2*n; iter++) { /* Begin Sweep Iteration */ 264 | 265 | tol = pow(0.01,(2*iter)); 266 | tol = 0.0; 267 | 268 | for (d=1; d<=(n-1); d++) { /* sweep along upper diagonals */ 269 | for (i=1; i<=(n-d); i++) { /* row */ 270 | j = i+d; /* column */ 271 | 272 | Kij = K[i][j]; 273 | Mij = M[i][j]; 274 | 275 | if ( Kij*Kij/(K[i][i]*K[j][j]) > tol || 276 | Mij*Mij/(M[i][i]*M[j][j]) > tol ) { /* do a rotation */ 277 | 278 | Kii = K[i][i] * Mij - Kij * M[i][i]; 279 | Kjj = K[j][j] * Mij - Kij * M[j][j]; 280 | s = K[i][i] * M[j][j] - K[j][j] * M[i][i]; 281 | 282 | if ( s >= 0.0 ) gamma = 0.5*s + sqrt( 0.25*s*s + Kii*Kjj ); 283 | else gamma = 0.5*s - sqrt( 0.25*s*s + Kii*Kjj ); 284 | 285 | alpha = Kjj / gamma ; 286 | beta = -Kii / gamma ; 287 | 288 | rotate(K,n,alpha,beta,i,j); /* make Kij zero */ 289 | rotate(M,n,alpha,beta,i,j); /* make Mij zero */ 290 | 291 | for (k=1; k<=n; k++) { /* update eigen-vectors V = V * P */ 292 | Vki = V[k][i]; 293 | Vkj = V[k][j]; 294 | V[k][i] = Vki + beta *Vkj; 295 | V[k][j] = Vkj + alpha*Vki; 296 | } 297 | } /* rotations complete */ 298 | } /* row */ 299 | } /* diagonal */ 300 | } /* End Sweep Iteration */ 301 | 302 | for (j=1; j<=n; j++) { /* scale eigen-vectors */ 303 | Mjj = sqrt(M[j][j]); 304 | for (i=1; i<=n; i++) V[i][j] /= Mjj; 305 | } 306 | 307 | for (j=1; j<=n; j++) 308 | E[j] = K[j][j]/M[j][j]; /* eigen-values */ 309 | 310 | return; 311 | } 312 | 313 | 314 | /*----------------------------------------------------------------------------- 315 | ROTATE - rotate an n by n symmetric matrix A such that A[i][j] = A[j][i] = 0 316 | A = P' * A * P where diag(P) = 1 and P[i][j] = alpha and P[j][i] = beta. 317 | Since P is sparse, this matrix multiplcation can be done efficiently. 318 | -----------------------------------------------------------------------------*/ 319 | void rotate ( double **A, int n, double alpha, double beta, int i, int j ) 320 | { 321 | double Aii, Ajj, Aij, /* elements of A */ 322 | *Ai, *Aj; /* i-th and j-th rows of A */ 323 | int k; 324 | 325 | 326 | Ai = dvector(1,n); 327 | Aj = dvector(1,n); 328 | 329 | for (k=1; k<=n; k++) { 330 | Ai[k] = A[i][k]; 331 | Aj[k] = A[j][k]; 332 | } 333 | 334 | Aii = A[i][i]; 335 | Ajj = A[j][j]; 336 | Aij = A[i][j]; 337 | 338 | A[i][i] = Aii + 2*beta *Aij + beta *beta *Ajj ; 339 | A[j][j] = Ajj + 2*alpha*Aij + alpha*alpha*Aii ; 340 | 341 | for (k=1; k<=n; k++) { 342 | if ( k != i && k != j ) { 343 | A[k][i] = A[i][k] = Ai[k] + beta *Aj[k]; 344 | A[k][j] = A[j][k] = Aj[k] + alpha*Ai[k]; 345 | } 346 | } 347 | A[j][i] = A[i][j] = 0; 348 | 349 | free_dvector(Ai,1,n); 350 | free_dvector(Aj,1,n); 351 | 352 | return; 353 | } 354 | 355 | 356 | /*------------------------------------------------------------------------------ 357 | STODOLA - calculate the lowest m eigen-values and eigen-vectors of the 358 | generalized eigen-problem, K v = w M v, using a matrix iteration approach 359 | with shifting. 15oct98 360 | 361 | H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 12 Jul 2001 362 | ------------------------------------------------------------------------------*/ 363 | void stodola ( 364 | double **K, double **M, /* stiffness and mass matrices */ 365 | int n, int m, /* DoF and number of required modes */ 366 | double *w, double **V, double tol, double shift, int *iter, int *ok, 367 | int verbose 368 | ){ 369 | double **D, /* the dynamics matrix, D = K^(-1) M */ 370 | d_min = 0.0, /* minimum value of D[i][i] */ 371 | d_max = 0.0, /* maximum value of D[i][i] */ 372 | d_old = 0.0, /* previous extreme value of D[i][i] */ 373 | *d, /* columns of the D, M, and V matrices */ 374 | *u, *v, /* trial eigen-vector vectors */ 375 | *c, /* coefficients for lower mode purge */ 376 | vMv, /* factor for mass normalization */ 377 | RQ, RQold=0.0, /* Raliegh quotient */ 378 | error = 1.0; 379 | 380 | int i_ex = 9999, /* location of minimum value of D[i][i] */ 381 | modes, /* number of desired modes */ 382 | disp = 0, /* 1: display convergence error; 0: dont*/ 383 | i,j,k; 384 | 385 | char errMsg[MAXL]; 386 | 387 | D = dmatrix(1,n,1,n); 388 | d = dvector(1,n); 389 | u = dvector(1,n); 390 | v = dvector(1,n); 391 | c = dvector(1,m); 392 | 393 | modes = (int) ( (double)(0.5*m) > (double)(m-8) ? (int)(m/2.0) : m-8 ); 394 | 395 | /* shift eigen-values by this much */ 396 | for (i=1;i<=n;i++) for (j=i;j<=n;j++) K[i][j] += shift*M[i][j]; 397 | 398 | ldl_dcmp ( K, n, u, v, v, 1, 0, ok ); /* use L D L' decomp */ 399 | if (*ok<0) { 400 | sprintf(errMsg," Make sure that all six rigid body translation are restrained.\n"); 401 | errorMsg(errMsg); 402 | exit(32); 403 | } 404 | /* calculate D = K^(-1) M */ 405 | for (j=1; j<=n; j++) { 406 | for (i=1; i<=n; i++) v[i] = M[i][j]; 407 | 408 | ldl_dcmp ( K, n, u, v, d, 0, 1, ok ); /* L D L' bk-sub */ 409 | 410 | /* improve the solution iteratively */ 411 | if (disp) fprintf(stdout," RMS matrix error:"); 412 | error = *ok = 1; 413 | do { 414 | ldl_mprove ( K, n, u, v, d, &error, ok ); 415 | if (disp) fprintf(stdout,"%9.2e", error ); 416 | } while ( *ok ); 417 | if (disp) fprintf(stdout,"\n"); 418 | 419 | for (i=1; i<=n; i++) D[i][j] = d[i]; 420 | } 421 | 422 | #ifdef EIG_DEBUG 423 | save_dmatrix ( "D", D, 1,n, 1,n, 0, "w" ); /* save dynamics matrix */ 424 | #endif 425 | 426 | *iter = 0; 427 | for (i=1; i<=n; i++) if ( D[i][i] > d_max ) d_max = D[i][i]; 428 | d_old = d_min = d_max; 429 | for (i=1; i<=n; i++) if ( D[i][i] < d_min ) d_min = D[i][i]; 430 | 431 | for (k=1; k<=m; k++) { /* loop over lowest m modes */ 432 | 433 | d_max = d_min; 434 | for (i=1; i<=n; i++) { /* initial guess */ 435 | u[i] = 0.0; 436 | if ( D[i][i] < d_old && D[i][i] > d_max ) { 437 | d_max = D[i][i]; 438 | i_ex = i; 439 | } 440 | } 441 | u[i_ex] = 1.0; u[i_ex+1] = 1.e-4; 442 | d_old = d_max; 443 | 444 | vMv = xtAy ( u, M, u, n, d ); /* mass-normalize */ 445 | for (i=1; i<=n; i++) u[i] /= sqrt ( vMv ); 446 | 447 | for (j=1; j 1000 ) { 482 | sprintf(errMsg," stodola: Iteration limit exceeded\n rel. error = %e > %e\n", (fabs(RQ - RQold)/RQ) , tol ); 483 | errorMsg(errMsg); 484 | exit(32); 485 | } 486 | 487 | } while ( (fabs(RQ - RQold)/RQ) > tol ); 488 | 489 | for (i=1; i<=n; i++) V[i][k] = v[i]; 490 | 491 | w[k] = xtAy ( u, K, u, n, d ); 492 | if ( w[k] > shift ) w[k] = w[k] - shift; 493 | else w[k] = shift - w[k]; 494 | 495 | fprintf(stdout," mode: %2d\tDoF: %5d\t", k, i_ex ); 496 | fprintf(stdout," %9.4f Hz\t iter: %4d error: %.4e \n", 497 | sqrt(w[k])/(2.0*PI), *iter, (fabs(RQ - RQold)/RQ) ); 498 | } 499 | 500 | eigsort ( w, V, n, m ); 501 | 502 | *ok = sturm ( K, M, n, m, shift, w[modes]+tol, verbose ); 503 | 504 | #ifdef EIG_DEBUG 505 | save_dmatrix ( "V", V, 1,n, 1,m, 0, "w" ); /* save mode shape matrix */ 506 | #endif 507 | 508 | free_dmatrix(D,1,n,1,n); 509 | free_dvector(d,1,n); 510 | free_dvector(u,1,n); 511 | free_dvector(v,1,n); 512 | free_dvector(c,1,m); 513 | 514 | return; 515 | } 516 | 517 | 518 | /*------------------------------------------------------------------------------ 519 | EIGSORT - Given the eigenvallues e[1..m] and eigenvectors v[1..n][1..m], 520 | this routine sorts the eigenvalues into ascending order, and rearranges 521 | the columns of v correspondingly. The method is straight insertion. 522 | Adapted from Numerical Recipes in C, Ch 11 523 | ------------------------------------------------------------------------------*/ 524 | void eigsort ( double *e, double **v, int n, int m ) 525 | { 526 | int k,j,i; 527 | double p=0; 528 | 529 | for (i=1;i (float)(m-8.0) ? (int)(m/2.0) : m-8 ); 573 | 574 | ws_shift = ws + shift; /* shift [K] */ 575 | for (i=1; i<=n; i++) for (j=i; j<=n; j++) K[i][j] -= ws_shift*M[i][j]; 576 | 577 | ldl_dcmp ( K, n, d, d, d, 1, 0, &ok ); 578 | 579 | if ( verbose ) 580 | fprintf(stdout," There are %d modes below %f Hz.", -ok, sqrt(ws)/(2.0*PI) ); 581 | 582 | if ( -ok > modes ) { 583 | fprintf(stderr," ... %d modes were not found.\n", -ok-modes ); 584 | fprintf(stderr," Try increasing the number of modes in \n"); 585 | fprintf(stderr," order to get the missing modes below %f Hz.\n", 586 | sqrt(ws)/(2.0*PI) ); 587 | } else if ( verbose ) 588 | fprintf(stdout," All %d modes were found.\n",modes); 589 | 590 | for (i=1; i<=n; i++) for (j=i; j<=n; j++) K[i][j] += ws_shift*M[i][j]; 591 | 592 | free_dvector(d,1,n); 593 | 594 | return ok; 595 | } 596 | 597 | 598 | /*---------------------------------------------------------------------------- 599 | CHECK_NON_NEGATIVE - checks that a value is non-negative 600 | -----------------------------------------------------------------------------*/ 601 | void check_non_negative( double x, int i) 602 | { 603 | if ( x <= 1.0e-100 ) { 604 | fprintf(stderr," value %e is less than or equal to zero ", x ); 605 | fprintf(stderr," i = %d \n", i ); 606 | } else { 607 | return; 608 | } 609 | } 610 | 611 | -------------------------------------------------------------------------------- /pyframe3dd/src/py_eig.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FRAME3DD: 3 | Static and dynamic structural analysis of 2D and 3D frames and trusses with 4 | elastic and geometric stiffness. 5 | --------------------------------------------------------------------------- 6 | http://frame3dd.sourceforge.net/ 7 | --------------------------------------------------------------------------- 8 | Copyright (C) 1992-2009 Henri P. Gavin 9 | 10 | FRAME3DD is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | FRAME3DD is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with FRAME3DD. If not, see . 22 | *//** 23 | @file 24 | Routines to solve the generalized eigenvalue problem 25 | 26 | Henri P. Gavin hpgavin@duke.edu 27 | Department of Civil and Environmental Engineering 28 | Duke University, Box 90287 29 | Durham, NC 27708--0287 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include "py_eig.h" 37 | #include "common.h" 38 | #include "py_HPGmatrix.h" 39 | #include "HPGutil.h" 40 | #include "NRutil.h" 41 | 42 | /* #define EIG_DEBUG */ 43 | 44 | /* forward declarations */ 45 | 46 | static void jacobi( double **K, double **M, double *E, double **V, int n ); 47 | 48 | static void rotate ( double **A, int n,double alpha, double beta, int i,int j); 49 | 50 | void eigsort ( double *e, double **v, int n, int m); 51 | 52 | int sturm ( double **K, double **M, int n, int m, double shift, double ws, int verbose ); 53 | 54 | /*----------------------------------------------------------------------------- 55 | SUBSPACE - Find the lowest m eigen-values, w, and eigen-vectors, V, of the 56 | general eigen-problem ... K V = w M V using sub-space / Jacobi iteration 57 | where 58 | K is an n by n symmetric real (stiffness) matrix 59 | M is an n by n symmetric positive definate real (mass) matrix 60 | w is a diagonal matrix of eigen-values 61 | V is a rectangular matrix of eigen-vectors 62 | 63 | H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 1 March 2007 64 | Bathe, Finite Element Procecures in Engineering Analysis, Prentice Hall, 1982 65 | -----------------------------------------------------------------------------*/ 66 | int subspace( 67 | double **K, double **M, 68 | int n, int m, /**< DoF and number of required modes */ 69 | double *w, double **V, 70 | double tol, double shift, 71 | int *iter, /**< sub-space iterations */ 72 | int *ok, /**< Sturm check result */ 73 | int verbose 74 | ){ 75 | double **Kb, **Mb, **Xb, **Qb, *d, *u, *v, km, km_old, 76 | error=1.0, w_old = 0.0; 77 | 78 | int i=0, j=0, k=0, 79 | modes, 80 | disp = 0, /* display convergence info. */ 81 | *idx; 82 | char errMsg[MAXL]; 83 | 84 | if ( m > n ) { 85 | sprintf(errMsg,"subspace: Number of eigen-values must be less than the problem dimension.\n Desired number of eigen-values=%d \n Dimension of the problem= %d \n", m, n); 86 | errorMsg(errMsg); 87 | return 32; 88 | } 89 | 90 | d = dvector(1,n); 91 | u = dvector(1,n); 92 | v = dvector(1,n); 93 | Kb = dmatrix(1,m,1,m); 94 | Mb = dmatrix(1,m,1,m); 95 | Xb = dmatrix(1,n,1,m); 96 | Qb = dmatrix(1,m,1,m); 97 | idx = ivector(1,m); 98 | 99 | for (i=1; i<=m; i++) { 100 | idx[i] = 0; 101 | for (j=i; j<=m; j++) 102 | Kb[i][j]=Kb[j][i] = Mb[i][j]=Mb[j][i] = Qb[i][j]=Qb[j][i] = 0.0; 103 | } 104 | 105 | for (i=1; i<=n; i++) for (j=1; j<=m; j++) Xb[i][j] = V[i][j] = 0.0; 106 | 107 | modes = (int) ( (double)(0.5*m) > (double)(m-8.0) ? (int)(m/2.0) : m-8 ); 108 | 109 | /* shift eigen-values by this much */ 110 | for (i=1;i<=n;i++) for (j=i;j<=n;j++) K[i][j] += shift*M[i][j]; 111 | 112 | 113 | ldl_dcmp ( K, n, u, v, v, 1, 0, ok ); /* use L D L' decomp */ 114 | 115 | for (i=1; i<=n; i++) { 116 | if ( M[i][i] <= 0.0 ) { 117 | sprintf(errMsg," subspace: M[%d][%d] = %e \n", i,i, M[i][i] ); 118 | errorMsg(errMsg); 119 | return 32; 120 | } 121 | d[i] = K[i][i] / M[i][i]; 122 | } 123 | 124 | km_old = 0.0; 125 | for (k=1; k<=m; k++) { 126 | km = d[1]; 127 | for (i=1; i<=n; i++) { 128 | if ( km_old <= d[i] && d[i] <= km ) { 129 | *ok = 1; 130 | for (j=1; j<=k-1; j++) if ( i == idx[j] ) *ok = 0; 131 | if (*ok) { 132 | km = d[i]; 133 | idx[k] = i; 134 | } 135 | } 136 | } 137 | if ( idx[k] == 0 ) { 138 | i = idx[1]; 139 | for ( j=1; j 2000 ) { 206 | sprintf(errMsg," subspace: Iteration limit exceeded\n rel. error = %e > %e\n", error, tol ); 207 | errorMsg(errMsg); 208 | return 32; 209 | } 210 | 211 | } while ( error > tol ); /* End sub-space iterations */ 212 | 213 | 214 | for (k=1; k<=m; k++) { /* shift eigen-values */ 215 | if ( w[k] > shift ) w[k] = w[k] - shift; 216 | else w[k] = shift - w[k]; 217 | } 218 | 219 | if ( verbose ) { 220 | fprintf(stdout," %4d sub-space iterations, error: %.4e \n", *iter, error ); 221 | for ( k=1; k<=m; k++ ) 222 | fprintf(stdout," mode: %2d\tDoF: %5d\t %9.4lf Hz\n", 223 | k, idx[k], sqrt(w[k])/(2.0*PI) ); 224 | } 225 | 226 | *ok = sturm ( K, M, n, m, shift, w[modes]+tol, verbose ); 227 | 228 | for (i=1;i<=n;i++) for (j=i;j<=n;j++) K[i][j] -= shift*M[i][j]; 229 | 230 | free_dmatrix(Kb,1,m,1,m); 231 | free_dmatrix(Mb,1,m,1,m); 232 | free_dmatrix(Xb,1,n,1,m); 233 | free_dmatrix(Qb,1,m,1,m); 234 | 235 | return 0; 236 | } 237 | 238 | 239 | /*----------------------------------------------------------------------------- 240 | JACOBI - Find all eigen-values, E, and eigen-vectors, V, 241 | of the general eigen-problem K V = E M V 242 | using Jacobi iteration, with efficient matrix rotations. 243 | K is a symmetric real (stiffness) matrix 244 | M is a symmetric positive definate real (mass) matrix 245 | E is a diagonal matrix of eigen-values 246 | V is a square matrix of eigen-vectors 247 | 248 | H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 1 March 2007 249 | Bathe, Finite Element Procecures in Engineering Analysis, Prentice Hall, 1982 250 | -----------------------------------------------------------------------------*/ 251 | void jacobi ( double **K, double **M, double *E, double **V, int n ) 252 | { 253 | int iter, 254 | d,i,j,k; 255 | double Kii, Kjj, Kij, Mii, Mjj, Mij, Vki, Vkj, 256 | alpha, beta, gamma, 257 | s, tol=0.0; 258 | 259 | Kii = Kjj = Kij = Mii = Mjj = Mij = Vki = Vkj = 0.0; 260 | 261 | for (i=1; i<=n; i++) for (j=i+1; j<=n; j++) V[i][j] = V[j][i] = 0.0; 262 | for (d=1; d<=n; d++) V[d][d] = 1.0; 263 | 264 | for (iter=1; iter<=2*n; iter++) { /* Begin Sweep Iteration */ 265 | 266 | tol = pow(0.01,(2*iter)); 267 | tol = 0.0; 268 | 269 | for (d=1; d<=(n-1); d++) { /* sweep along upper diagonals */ 270 | for (i=1; i<=(n-d); i++) { /* row */ 271 | j = i+d; /* column */ 272 | 273 | Kij = K[i][j]; 274 | Mij = M[i][j]; 275 | 276 | if ( Kij*Kij/(K[i][i]*K[j][j]) > tol || 277 | Mij*Mij/(M[i][i]*M[j][j]) > tol ) { /* do a rotation */ 278 | 279 | Kii = K[i][i] * Mij - Kij * M[i][i]; 280 | Kjj = K[j][j] * Mij - Kij * M[j][j]; 281 | s = K[i][i] * M[j][j] - K[j][j] * M[i][i]; 282 | 283 | if ( s >= 0.0 ) gamma = 0.5*s + sqrt( 0.25*s*s + Kii*Kjj ); 284 | else gamma = 0.5*s - sqrt( 0.25*s*s + Kii*Kjj ); 285 | 286 | alpha = Kjj / gamma ; 287 | beta = -Kii / gamma ; 288 | 289 | rotate(K,n,alpha,beta,i,j); /* make Kij zero */ 290 | rotate(M,n,alpha,beta,i,j); /* make Mij zero */ 291 | 292 | for (k=1; k<=n; k++) { /* update eigen-vectors V = V * P */ 293 | Vki = V[k][i]; 294 | Vkj = V[k][j]; 295 | V[k][i] = Vki + beta *Vkj; 296 | V[k][j] = Vkj + alpha*Vki; 297 | } 298 | } /* rotations complete */ 299 | } /* row */ 300 | } /* diagonal */ 301 | } /* End Sweep Iteration */ 302 | 303 | for (j=1; j<=n; j++) { /* scale eigen-vectors */ 304 | Mjj = sqrt(M[j][j]); 305 | for (i=1; i<=n; i++) V[i][j] /= Mjj; 306 | } 307 | 308 | for (j=1; j<=n; j++) 309 | E[j] = K[j][j]/M[j][j]; /* eigen-values */ 310 | 311 | return; 312 | } 313 | 314 | 315 | /*----------------------------------------------------------------------------- 316 | ROTATE - rotate an n by n symmetric matrix A such that A[i][j] = A[j][i] = 0 317 | A = P' * A * P where diag(P) = 1 and P[i][j] = alpha and P[j][i] = beta. 318 | Since P is sparse, this matrix multiplcation can be done efficiently. 319 | -----------------------------------------------------------------------------*/ 320 | void rotate ( double **A, int n, double alpha, double beta, int i, int j ) 321 | { 322 | double Aii, Ajj, Aij, /* elements of A */ 323 | *Ai, *Aj; /* i-th and j-th rows of A */ 324 | int k; 325 | 326 | 327 | Ai = dvector(1,n); 328 | Aj = dvector(1,n); 329 | 330 | for (k=1; k<=n; k++) { 331 | Ai[k] = A[i][k]; 332 | Aj[k] = A[j][k]; 333 | } 334 | 335 | Aii = A[i][i]; 336 | Ajj = A[j][j]; 337 | Aij = A[i][j]; 338 | 339 | A[i][i] = Aii + 2*beta *Aij + beta *beta *Ajj ; 340 | A[j][j] = Ajj + 2*alpha*Aij + alpha*alpha*Aii ; 341 | 342 | for (k=1; k<=n; k++) { 343 | if ( k != i && k != j ) { 344 | A[k][i] = A[i][k] = Ai[k] + beta *Aj[k]; 345 | A[k][j] = A[j][k] = Aj[k] + alpha*Ai[k]; 346 | } 347 | } 348 | A[j][i] = A[i][j] = 0; 349 | 350 | free_dvector(Ai,1,n); 351 | free_dvector(Aj,1,n); 352 | 353 | return; 354 | } 355 | 356 | 357 | /*------------------------------------------------------------------------------ 358 | STODOLA - calculate the lowest m eigen-values and eigen-vectors of the 359 | generalized eigen-problem, K v = w M v, using a matrix iteration approach 360 | with shifting. 15oct98 361 | 362 | H.P. Gavin, Civil Engineering, Duke University, hpgavin@duke.edu 12 Jul 2001 363 | ------------------------------------------------------------------------------*/ 364 | int stodola ( 365 | double **K, double **M, /* stiffness and mass matrices */ 366 | int n, int m, /* DoF and number of required modes */ 367 | double *w, double **V, double tol, double shift, int *iter, int *ok, 368 | int verbose 369 | ){ 370 | double **D, /* the dynamics matrix, D = K^(-1) M */ 371 | d_min = 0.0, /* minimum value of D[i][i] */ 372 | d_max = 0.0, /* maximum value of D[i][i] */ 373 | d_old = 0.0, /* previous extreme value of D[i][i] */ 374 | *d, /* columns of the D, M, and V matrices */ 375 | *u, *v, /* trial eigen-vector vectors */ 376 | *c, /* coefficients for lower mode purge */ 377 | vMv, /* factor for mass normalization */ 378 | RQ, RQold=0.0, /* Raliegh quotient */ 379 | error = 1.0; 380 | 381 | int i_ex = 9999, /* location of minimum value of D[i][i] */ 382 | modes, /* number of desired modes */ 383 | disp = 0, /* 1: display convergence error; 0: dont*/ 384 | i,j,k; 385 | 386 | char errMsg[MAXL]; 387 | 388 | D = dmatrix(1,n,1,n); 389 | d = dvector(1,n); 390 | u = dvector(1,n); 391 | v = dvector(1,n); 392 | c = dvector(1,m); 393 | 394 | modes = (int) ( (double)(0.5*m) > (double)(m-8) ? (int)(m/2.0) : m-8 ); 395 | 396 | /* shift eigen-values by this much */ 397 | for (i=1;i<=n;i++) for (j=i;j<=n;j++) K[i][j] += shift*M[i][j]; 398 | 399 | ldl_dcmp ( K, n, u, v, v, 1, 0, ok ); /* use L D L' decomp */ 400 | if (*ok<0) { 401 | //sprintf(errMsg," Make sure that all six rigid body translation are restrained.\n"); 402 | //errorMsg(errMsg); 403 | return 32; 404 | } 405 | /* calculate D = K^(-1) M */ 406 | for (j=1; j<=n; j++) { 407 | for (i=1; i<=n; i++) v[i] = M[i][j]; 408 | 409 | ldl_dcmp ( K, n, u, v, d, 0, 1, ok ); /* L D L' bk-sub */ 410 | 411 | /* improve the solution iteratively */ 412 | if (disp) fprintf(stdout," RMS matrix error:"); 413 | error = *ok = 1; 414 | do { 415 | ldl_mprove ( K, n, u, v, d, &error, ok ); 416 | if (disp) fprintf(stdout,"%9.2e", error ); 417 | } while ( *ok ); 418 | if (disp) fprintf(stdout,"\n"); 419 | 420 | for (i=1; i<=n; i++) D[i][j] = d[i]; 421 | } 422 | 423 | #ifdef EIG_DEBUG 424 | save_dmatrix ( "D", D, 1,n, 1,n, 0, "w" ); /* save dynamics matrix */ 425 | #endif 426 | 427 | *iter = 0; 428 | for (i=1; i<=n; i++) if ( D[i][i] > d_max ) d_max = D[i][i]; 429 | d_old = d_min = d_max; 430 | for (i=1; i<=n; i++) if ( D[i][i] < d_min ) d_min = D[i][i]; 431 | 432 | for (k=1; k<=m; k++) { /* loop over lowest m modes */ 433 | 434 | d_max = d_min; 435 | for (i=1; i<=n; i++) { /* initial guess */ 436 | u[i] = 0.0; 437 | if ( D[i][i] < d_old && D[i][i] > d_max ) { 438 | d_max = D[i][i]; 439 | i_ex = i; 440 | } 441 | } 442 | u[i_ex] = 1.0; u[i_ex+1] = 1.e-4; 443 | d_old = d_max; 444 | 445 | vMv = xtAy ( u, M, u, n, d ); /* mass-normalize */ 446 | for (i=1; i<=n; i++) u[i] /= sqrt ( vMv ); 447 | 448 | for (j=1; j 2000 ) { 483 | sprintf(errMsg," stodola: Iteration limit exceeded\n rel. error = %e > %e\n", (fabs(RQ - RQold)/RQ) , tol ); 484 | errorMsg(errMsg); 485 | return 32; 486 | } 487 | 488 | } while ( (fabs(RQ - RQold)/RQ) > tol ); 489 | 490 | for (i=1; i<=n; i++) V[i][k] = v[i]; 491 | 492 | w[k] = xtAy ( u, K, u, n, d ); 493 | if ( w[k] > shift ) w[k] = w[k] - shift; 494 | else w[k] = shift - w[k]; 495 | 496 | if ( verbose ) { 497 | fprintf(stdout," mode: %2d\tDoF: %5d\t", k, i_ex ); 498 | fprintf(stdout," %9.4f Hz\t iter: %4d error: %.4e \n", 499 | sqrt(w[k])/(2.0*PI), *iter, (fabs(RQ - RQold)/RQ) ); 500 | } 501 | } 502 | 503 | eigsort ( w, V, n, m ); 504 | 505 | *ok = sturm ( K, M, n, m, shift, w[modes]+tol, verbose ); 506 | 507 | #ifdef EIG_DEBUG 508 | save_dmatrix ( "V", V, 1,n, 1,m, 0, "w" ); /* save mode shape matrix */ 509 | #endif 510 | 511 | free_dmatrix(D,1,n,1,n); 512 | free_dvector(d,1,n); 513 | free_dvector(u,1,n); 514 | free_dvector(v,1,n); 515 | free_dvector(c,1,m); 516 | 517 | return 0; 518 | } 519 | 520 | 521 | /*------------------------------------------------------------------------------ 522 | EIGSORT - Given the eigenvallues e[1..m] and eigenvectors v[1..n][1..m], 523 | this routine sorts the eigenvalues into ascending order, and rearranges 524 | the columns of v correspondingly. The method is straight insertion. 525 | Adapted from Numerical Recipes in C, Ch 11 526 | ------------------------------------------------------------------------------*/ 527 | void eigsort ( double *e, double **v, int n, int m ) 528 | { 529 | int k,j,i; 530 | double p=0; 531 | 532 | for (i=1;i (float)(m-8.0) ? (int)(m/2.0) : m-8 ); 576 | 577 | ws_shift = ws + shift; /* shift [K] */ 578 | for (i=1; i<=n; i++) for (j=i; j<=n; j++) K[i][j] -= ws_shift*M[i][j]; 579 | 580 | ldl_dcmp ( K, n, d, d, d, 1, 0, &ok ); 581 | 582 | if ( verbose ) 583 | fprintf(stdout," There are %d modes below %f Hz.", -ok, sqrt(ws)/(2.0*PI) ); 584 | 585 | if (( -ok > modes ) && (verbose)){ 586 | fprintf(stderr," ... %d modes were not found.\n", -ok-modes ); 587 | fprintf(stderr," Try increasing the number of modes in \n"); 588 | fprintf(stderr," order to get the missing modes below %f Hz.\n", 589 | sqrt(ws)/(2.0*PI) ); 590 | } else if ( verbose ) 591 | fprintf(stdout," All %d modes were found.\n",modes); 592 | 593 | for (i=1; i<=n; i++) for (j=i; j<=n; j++) K[i][j] += ws_shift*M[i][j]; 594 | 595 | free_dvector(d,1,n); 596 | 597 | return ok; 598 | } 599 | 600 | 601 | /*---------------------------------------------------------------------------- 602 | CHECK_NON_NEGATIVE - checks that a value is non-negative 603 | -----------------------------------------------------------------------------*/ 604 | void check_non_negative( double x, int i) 605 | { 606 | if ( x <= 1.0e-100 ) { 607 | fprintf(stderr," value %e is less than or equal to zero ", x ); 608 | fprintf(stderr," i = %d \n", i ); 609 | } else { 610 | return; 611 | } 612 | } 613 | 614 | --------------------------------------------------------------------------------