diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index 73be67a34d..6d8303945a 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -9,6 +9,9 @@ on: workflow_dispatch: +env: + PYTHONPATH: "./build/Release" + jobs: build-ubuntu: name: Build Ubuntu @@ -27,6 +30,10 @@ jobs: run: | pip install conan conan profile detect --force + - name: matplotlib + run: pip install matplotlib + - name: numpy + run: pip install numpy - name: build OpenSees & OpenSeesPy run: | conan install . --build=missing @@ -34,62 +41,15 @@ jobs: cd build/Release cmake --build . --target OpenSees -j8 cmake --build . --target OpenSeesPy -j8 - mv OpenSeesPy.so opensees.so + mkdir openseespy + mv OpenSeesPy.so openseespy/opensees.so - name: Verification OpenSeesPy # Simple Sanity Test run: | - export PYTHONPATH="./build/Release" - python3 -c "import sys; print(sys.path)" - python3 ./EXAMPLES/ExamplePython/example_variable_analysis.py - - name: Run pytest in tests/ folder - run: | - python3 -m pip install pytest - cp build/Release/opensees.so tests/ - cd tests - pytest -v + xvfb-run python3 ./EXAMPLES/ExamplePython/example_ground_motion.py - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: OpenSees_Ubuntu path: | - ./build/Release/OpenSees - ./build/Release/opensees.so - - build-mac-conan: - name: Build Mac OS - runs-on: macos-latest - timeout-minutes: 30 - steps: - - name: 2.1. Obtaining OpenSees Source Code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Python 3.11 - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - name: conan install - run: | - pip install conan - conan profile detect --force - - name: 2.3.2. Building the OpenSees Applications and Python module - run: | - export FC=/opt/homebrew/bin/gfortran-13 - export LDFLAGS="-L/opt/homebrew/lib/gcc/current -lgfortran" - conan install . --build=missing - cmake -S . -B build/Release -DCMAKE_TOOLCHAIN_FILE=build/Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/bin - cd build/Release - cmake --build . --target OpenSees -j8 - cmake --build . --target OpenSeesPy -j8 - mv ./OpenSeesPy.dylib ./opensees.so - - name: Verification OpenSeesPySP - run: | - export PYTHONPATH="./build/Release" - python3 -c "import sys; print(sys.path)" - python3 ./EXAMPLES/ExamplePython/example_variable_analysis.py - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: OpenSees_Mac - path: | - ./build/Release/OpenSees - ./build/Release/opensees.so + ground_motion.png + disp.out diff --git a/EXAMPLES/ExamplePython/example_ground_motion.py b/EXAMPLES/ExamplePython/example_ground_motion.py new file mode 100644 index 0000000000..b0c7757c97 --- /dev/null +++ b/EXAMPLES/ExamplePython/example_ground_motion.py @@ -0,0 +1,32 @@ +import matplotlib +matplotlib.use('Agg') +import matplotlib.pyplot as plt +import openseespy.opensees as ops +import numpy as np + +# Create a basic model with a single node +ops.wipe() +ops.model('basic', '-ndm', 1, '-ndf', 1) +ops.node(1, 0.0); ops.fix(1, 1) +ops.node(2, 0.0); ops.mass(2, 1.0) +ops.uniaxialMaterial('Elastic', 1, 100.0) +ops.damping('Uniform', 1, 0.05, 1.0, 100.0) +ops.element('zeroLength', 1, 1, 2, '-mat', 1, '-dir', 1, '-damp', 1) +ops.timeSeries('Sine', 1, 0.0, 100.0, 0.628, '-factor', -10.0) +ops.pattern('UniformExcitation', 1, 1, '-accel', 1) +ops.analysis('Transient') +ops.recorder('Node', '-file', 'disp.out', '-time', '-node', 2, '-dof', 1, 'disp') + +ops.analyze(1000, 0.01) + +ops.wipe() +data = np.loadtxt('disp.out') +plt.figure() +plt.plot(data[:, 0], data[:, 1]) +plt.xlabel('Time') +plt.ylabel('Displacement') +plt.grid() +plt.show() + +####### +plt.savefig('./build/Release/ground_motion.png') \ No newline at end of file diff --git a/SRC/damping/UniformDamping.cpp b/SRC/damping/UniformDamping.cpp index e542b53104..a1252bb589 100644 --- a/SRC/damping/UniformDamping.cpp +++ b/SRC/damping/UniformDamping.cpp @@ -131,6 +131,9 @@ UniformDamping::Initialize(void) double delta = 0.05; double f1log = log10(freq1); double f2log = log10(freq2); + double pi = 6.28318530718; + double w1 = pi * freq1; + double w2 = pi * freq2; nFilter = 2; for (int iter = 0; iter < 100; ++iter) @@ -141,29 +144,31 @@ UniformDamping::Initialize(void) alpha = new Vector(nFilter); omegac = new Vector(nFilter); + Vector *y = new Vector(nFilter); + Matrix *X = new Matrix(nFilter, nFilter); + Vector *psi = new Vector(nFilter); + for (int i = 0; i < nFilter; ++i) { - (*omegac)(i) = 6.28318530718 * pow(10.0, f1log + i * dfreq); + double wc = pi * pow(10.0, f1log + i * dfreq); + (*omegac)(i) = wc; + (*psi)(i) = wc * atan((wc * (w2 - w1)) / (wc * wc + w1 * w2)); + (*y)(i) = wc * log((wc * wc + w2 * w2) / (wc * wc + w1 * w1)); + (*X)(i, i) = 2.0 * (*psi)(i) - ( + (2.0 * wc * wc * w2) / (wc * wc + w2 * w2) - + (2.0 * wc * wc * w1) / (wc * wc + w1 * w1) + ); } - int nf = 100 * nFilter; - double df = (f2log - f1log) / (nf - 1); - Vector *y = new Vector(nFilter); - Matrix *X = new Matrix(nFilter, nFilter); - for (int i = 0; i < nf; ++i) + for (int i = 0; i < nFilter; ++i) { - double omega = 6.28318530718 * pow(10.0, f1log + i * df); - for (int j = 0; j < nFilter; ++j) + double wi = (*omegac)(i); + for (int j = i + 1; j < nFilter; ++j) { - double wjn = omega / (*omegac)[j]; - double phij = 2.0 * wjn / (1.0 + wjn * wjn); - (*y)(j) += phij; - for (int k = 0; k < nFilter; ++k) - { - double wkn = omega / (*omegac)[k]; - double phik = 2.0 * wkn / (1.0 + wkn * wkn); - (*X)(j, k) += phij * phik; - } + double wj = (*omegac)(j); + double val = (4.0 * wi * wj * ((*psi)(i) - (*psi)(j))) / (wi * wi - wj * wj); + (*X)(i, j) = val; + (*X)(j, i) = val; } } @@ -171,11 +176,14 @@ UniformDamping::Initialize(void) delete y; delete X; + delete psi; bool converged = true; + int nf = 100 * nFilter; + double df = (f2log - f1log) / (nf - 1); for (int i = 0; i < nf; ++i) { - double omega = 6.28318530718 * pow(10.0, f1log + i * df); + double omega = pi * pow(10.0, f1log + i * df); double err = 0.0; for (int j = 0; j < nFilter; ++j) {