diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index 26900f8cdd..51e93a2e3a 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -2,138 +2,21 @@ name: CMake Build on: push: - branches: [master] + branches: [constraint] pull_request: - branches: [master] + branches: [constraint] workflow_dispatch: -jobs: - build-win: - name: Build Windows10 - runs-on: windows-2019 - steps: - - name: 2.1. Obtaining OpenSees Source Code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - # - name: CMake is already installed - # - name: Git is already installed - - name: Microsoft Visual Studio - uses: ilammy/msvc-dev-cmd@v1 - with: - vsversion: 2019 - - name: Intel oneAPI Basic & HPC Toolkits - shell: pwsh - env: - WINDOWS_BASEKIT_URL: https://registrationcenter-download.intel.com/akdlm/IRC_NAS/7dff44ba-e3af-4448-841c-0d616c8da6e7/w_BaseKit_p_2024.1.0.595_offline.exe - WINDOWS_BASEKIT_COMPONENTS: intel.oneapi.win.mkl.devel - WINDOWS_HPCKIT_URL: https://registrationcenter-download.intel.com/akdlm/IRC_NAS/c95a3b26-fc45-496c-833b-df08b10297b9/w_HPCKit_p_2024.1.0.561_offline.exe - WINDOWS_HPCKIT_COMPONENTS: "intel.oneapi.win.mpi.devel:intel.oneapi.win.ifort-compiler" - working-directory: D:\a\OpenSees\OpenSees\.github\workflows - run: | - ./install_fortran.bat $env:WINDOWS_BASEKIT_URL $env:WINDOWS_BASEKIT_COMPONENTS - ./install_fortran.bat $env:WINDOWS_HPCKIT_URL $env:WINDOWS_HPCKIT_COMPONENTS - - name: Python 3.11 - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - name: Conan 1.x - run: pip install conan<2.0 - - name: MUMPS - shell: cmd - run: | - git clone https://github.com/OpenSees/mumps.git - cd mumps - mkdir build - cd build - call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" intel64 mod - cmake .. -Darith=d -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded" -G Ninja - cmake --build . --config Release --parallel 4 - - name: 2.2.2. Building the OpenSees Applications and Python module - shell: cmd - run: | - mkdir build - cd build - conan install .. --build missing --settings compiler="Visual Studio" --settings compiler.runtime="MT" --settings compiler.version=16 - call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" intel64 mod - cmake .. -DBLA_STATIC=ON -DMKL_LINK=static -DMKL_INTERFACE_FULL=intel_lp64 -DMUMPS_DIR="..\..\mumps\build" - cmake --build . --config Release --target OpenSees -j8 - cmake --build . --config Release --target OpenSeesPy -j8 - - name: Verification OpenSeesPySP - shell: pwsh - run: | - mv ./build/bin/OpenSeesPy.dll ./build/bin/opensees.pyd - cp "C:\Program Files (x86)\Intel\oneAPI\compiler\2024.1\bin\libiomp5md.dll" ./build/bin/ - $env:PYTHONPATH = "./build/bin/" - python -c "import sys; print(sys.path)" - python ./EXAMPLES/ExamplePython/example_variable_analysis.py - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: OpenSees_Windows - path: | - ./build/bin/OpenSees.exe - ./build/bin/opensees.pyd - ./build/bin/libiomp5md.dll - - build-mac: - 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: XCode Command Line Tools is already installed. - - name: Install other dependencies via Homebrew - run: | - ln -s /opt/homebrew/bin/gcc-13 /usr/local/bin/gcc - ln -s /opt/homebrew/bin/gfortran-13 /usr/local/bin/gfortran - brew install eigen - brew install hdf5 - brew install open-mpi - brew install scalapack - sudo ln -sf /opt/homebrew/include/eigen3/Eigen /opt/homebrew/include/Eigen - - name: MUMPS - run: | - git clone https://github.com/OpenSees/mumps.git - cd mumps - mkdir build - cd build - cmake .. -Darith=d - cmake --build . --config Release --parallel 4 - - name: 2.3.2. Building the OpenSees Applications and Python module - run: | - mkdir build - cd build - cmake .. -DMUMPS_DIR=$PWD/../../mumps/build - cmake --build . --target OpenSees -j8 - cmake --build . --target OpenSeesPy -j8 - mv ./OpenSeesPy.dylib ./opensees.so - - name: Verification OpenSeesPySP - run: | - export PYTHONPATH="./build/" - 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/OpenSees - ./build/opensees.so +env: + PYTHONPATH: "./build/lib/:./mylib/" +jobs: build-ubuntu: name: Build Ubuntu runs-on: ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 10 steps: - name: 2.1. Obtaining OpenSees Source Code uses: actions/checkout@v4 @@ -146,6 +29,16 @@ jobs: # - name: Needed Applications and Libraries are already satisfied. - name: Conan 1.x run: pip install "conan<2.0" + - name: matplotlib + run: pip install matplotlib + - name: numpy + run: pip install numpy + # - name: scipy + # run: pip install scipy + # - name: vfo + # run: pip install vfo + # - name: xvfb + # run: sudo apt-get install xvfb - name: 2.4.2. Building the OpenSees Applications and Python module run: | mkdir build @@ -154,19 +47,35 @@ jobs: cmake .. cmake --build . --target OpenSees -j8 cmake --build . --target OpenSeesPy -j8 - mv lib/OpenSeesPy.so lib/opensees.so + cd lib + mkdir openseespy + mv OpenSeesPy.so openseespy/opensees.so + # - name: Verification OpenSeesPySP # Simple Sanity Test + # run: | + # export PYTHONPATH="./build/lib/" + # python3 ./EXAMPLES/ExamplePython/example_ground_motion.py - name: Verification OpenSeesPySP # Simple Sanity Test run: | - export PYTHONPATH="./build/lib/" - python3 -c "import sys; print(sys.path)" - python3 ./EXAMPLES/ExamplePython/example_variable_analysis.py + xvfb-run python3 ./EXAMPLES/ExamplePython/example_ground_motion.py + # - name: Run headless test + # uses: coactions/setup-xvfb@v1 + # with: + # run: python3 ./EXAMPLES/ExamplePython/example_ground_motion.py + # - name: Verification OpenSeesPySP # Simple Sanity Test + # run: | + # export PYTHONPATH="./build/lib/:./mylib/" + # export PYVISTA_OFF_SCREEN=true + # xvfb-run python3 ./EXAMPLES/ExamplePython/example_ground_motion.py - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: OpenSees_Ubuntu path: | - ./build/bin/OpenSees - ./build/lib/opensees.so + ground_motion.png + model.png + disp.out + force1.out + force2.out # # Simple MP sanity test # - name: Verification OpenSeesPyMP # run: | diff --git a/EXAMPLES/ExamplePython/example_ground_motion.py b/EXAMPLES/ExamplePython/example_ground_motion.py new file mode 100644 index 0000000000..8349138b34 --- /dev/null +++ b/EXAMPLES/ExamplePython/example_ground_motion.py @@ -0,0 +1,63 @@ +import matplotlib +matplotlib.use('Agg') +import matplotlib.pyplot as plt +import openseespy.opensees as ops +import numpy as np + +ops.model('basic', '-ndm', 2, '-ndf', 3) +ops.node( 1,-1.0, 0.0); ops.fix(1, 0, 1, 1) +ops.node(11, 0.0, 0.0); ops.fix(11, 1, 1, 1) +ops.node(12, 4.0, 0.0); ops.fix(12, 1, 1, 1) +ops.node(21, 0.0, 2.0) +ops.node(22, 4.0, 2.0) +ops.node(31, 0.0, 4.0) +ops.node(32, 4.0, 4.0) + +ops.geomTransf('Linear', 1) +ops.uniaxialMaterial('Steel01', 1, 3e2, 2e5, 0.2) +ops.section('WFSection2d', 1, 1, 0.6, 0.05, 0.3, 0.1, 5, 1) +ops.beamIntegration('Lobatto', 1, 1, 5) +ops.uniaxialMaterial('Steel01', 2, 5e2, 2e5, 0.01) +ops.section('WFSection2d', 2, 2, 0.6, 0.05, 0.3, 0.1, 5, 1) +ops.beamIntegration('Lobatto', 2, 2, 5) + +ops.element('forceBeamColumn', 11, 11, 21, 1, 1) +ops.element('forceBeamColumn', 12, 12, 22, 1, 1) +ops.element('elasticBeamColumn', 13, 21, 22, 0.1, 2e5, 0.05, 1) +ops.element('forceBeamColumn', 21, 21, 31, 1, 2) +ops.element('forceBeamColumn', 22, 22, 32, 1, 2) +ops.element('elasticBeamColumn', 23, 31, 32, 0.1, 2e5, 0.05, 1) + +ops.equationConstraint(31, 1, 2.0, 21, 1, 1.0, 1, 1, -3.0) + +# ops.timeSeries('Linear', 1) +ops.timeSeries('Path', 1, '-time', 0, 10, 30, 50, '-values', 0, 10, -10, 10) +ops.pattern('Plain', 1, 1) +ops.sp(1, 1, 0.01) +ops.constraints('Penalty', 1.0e6, 1.0e6) +ops.integrator('LoadControl', 1.0) +ops.analysis('Static') +ops.recorder('Node', '-file', 'disp.out', '-time', '-node', 21, 31, '-dof', 1, 'disp') +ops.recorder('Element', '-file', 'force1.out', '-time', '-ele', 11, 12, 'force') +ops.recorder('Element', '-file', 'force2.out', '-time', '-ele', 21, 22, 'force') +ops.analyze(50) +ops.wipe() + +disp = np.loadtxt('disp.out') +force1 = np.loadtxt('force1.out') +force2 = np.loadtxt('force2.out') +plt.figure() +# plt.plot(disp[:, 1], force1[:, 4] + force1[:, 10], 'o-', label = "Story 1") +# plt.plot(disp[:, 2] - disp[:, 1], force2[:, 4] + force2[:, 10], 'o-', label = "Story 2") +plt.plot(force1[:, 0], force1[:, 4] + force1[:, 10], label = "Story 1") +plt.plot(force2[:, 0], force2[:, 4] + force2[:, 10], label = "Story 2") +plt.xlim(0, 50) +plt.ylim(-40, 40) +plt.xlabel('Time') +plt.ylabel('Shear') +plt.legend() +plt.grid() +# plt.show() + +####### +plt.savefig('ground_motion.png') \ No newline at end of file diff --git a/EXAMPLES/example_ground_motion.py b/EXAMPLES/example_ground_motion.py new file mode 100644 index 0000000000..0329e27273 --- /dev/null +++ b/EXAMPLES/example_ground_motion.py @@ -0,0 +1,59 @@ +import matplotlib +matplotlib.use('Agg') +import matplotlib.pyplot as plt +import openseespy.opensees as ops +import numpy as np + +ops.model('basic', '-ndm', 2, '-ndf', 3) +ops.node( 1,-1.0, 0.0); ops.fix(1, 0, 1, 1) +ops.node(11, 0.0, 0.0); ops.fix(11, 1, 1, 1) +ops.node(12, 4.0, 0.0); ops.fix(12, 1, 1, 1) +ops.node(21, 0.0, 2.0) +ops.node(22, 4.0, 2.0) +ops.node(31, 0.0, 4.0) +ops.node(32, 4.0, 4.0) + +ops.geomTransf('Linear', 1) +ops.uniaxialMaterial('Steel01', 1, 3e2, 2e5, 0.2) +ops.section('WFSection2d', 1, 1, 0.6, 0.05, 0.3, 0.1, 5, 1) +ops.beamIntegration('Lobatto', 1, 1, 5) +ops.uniaxialMaterial('Steel01', 2, 5e2, 2e5, 0.01) +ops.section('WFSection2d', 2, 2, 0.6, 0.05, 0.3, 0.1, 5, 1) +ops.beamIntegration('Lobatto', 2, 2, 5) + +ops.element('forceBeamColumn', 11, 11, 21, 1, 1) +ops.element('forceBeamColumn', 12, 12, 22, 1, 1) +ops.element('elasticBeamColumn', 13, 21, 22, 0.1, 2e5, 0.05, 1) +ops.element('forceBeamColumn', 21, 21, 31, 1, 2) +ops.element('forceBeamColumn', 22, 22, 32, 1, 2) +ops.element('elasticBeamColumn', 23, 31, 32, 0.1, 2e5, 0.05, 1) + +ops.equationConstraint(31, 1, 2.0, 21, 1, 1.0, 1, 1, -3.0) + +# ops.timeSeries('Linear', 1) +ops.timeSeries('Path', 1, '-time', 0, 10, 30, '-values', 0, 10, -10) +ops.pattern('Plain', 1, 1) +ops.sp(1,1,0.01) +ops.constraints('Penalty', 1.0e6, 1.0e6) +ops.integrator('LoadControl',1.0) +ops.analysis('Static') +ops.recorder('Element', '-file', 'force1.out', '-time', '-ele', 11, 12, 'force') +ops.recorder('Element', '-file', 'force2.out', '-time', '-ele', 21, 22, 'force') +ops.analyze(30) +ops.wipe() + +force1 = np.loadtxt('force1.out') +force2 = np.loadtxt('force2.out') +plt.figure() +plt.plot(force1[:, 0], force1[:, 4] + force1[:, 10], label = "Story 1") +plt.plot(force2[:, 0], force2[:, 4] + force2[:, 10], label = "Story 2") +plt.xlim(0, 20) +# plt.ylim(0, 30) +plt.xlabel('Time') +plt.ylabel('Shear') +plt.legend() +plt.grid() +# plt.show() + +####### +plt.savefig('ground_motion.png') \ No newline at end of file