├── 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 |
--------------------------------------------------------------------------------