{"id":25854769,"url":"https://github.com/jchristopherson/dynamics","last_synced_at":"2026-02-08T20:26:29.240Z","repository":{"id":210298950,"uuid":"726180621","full_name":"jchristopherson/dynamics","owner":"jchristopherson","description":"A library of routines used for the analysis of dynamic systems.","archived":false,"fork":false,"pushed_at":"2025-01-29T22:09:44.000Z","size":1649,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-29T22:31:45.936Z","etag":null,"topics":["frequency-analysis","frequency-response","frf-fitting","kinematics","modal-analysis","rotation-matrix","structural-dynamics"],"latest_commit_sha":null,"homepage":"","language":"Fortran","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jchristopherson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-01T17:52:35.000Z","updated_at":"2025-01-25T20:03:23.000Z","dependencies_parsed_at":"2024-02-29T13:47:45.987Z","dependency_job_id":"b9230cf8-fe27-41aa-9a15-a99c002093a0","html_url":"https://github.com/jchristopherson/dynamics","commit_stats":null,"previous_names":["jchristopherson/dynamics"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristopherson%2Fdynamics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristopherson%2Fdynamics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristopherson%2Fdynamics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristopherson%2Fdynamics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jchristopherson","download_url":"https://codeload.github.com/jchristopherson/dynamics/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241389134,"owners_count":19955107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["frequency-analysis","frequency-response","frf-fitting","kinematics","modal-analysis","rotation-matrix","structural-dynamics"],"created_at":"2025-03-01T16:18:05.463Z","updated_at":"2026-02-08T20:26:24.201Z","avatar_url":"https://github.com/jchristopherson.png","language":"Fortran","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dynamics\nA library of routines used for the analysis of dynamic systems.\n\n## Status\n[![CMake](https://github.com/jchristopherson/dynamics/actions/workflows/cmake.yml/badge.svg)](https://github.com/jchristopherson/dynamics/actions/workflows/cmake.yml)\n[![Actions Status](https://github.com/jchristopherson/dynamics/workflows/fpm/badge.svg)](https://github.com/jchristopherson/dynamics/actions)\n\n## Documentation\nThe documentation can be found [here](https://jchristopherson.github.io/dynamics/).\n\n## Capabilities\nHere is a high-level list of the capabilities of this library.\n- Compute linear frequency response functions for LTI systems.\n- Perform modal analysis of an LTI system.\n- Compute the frequency response of nonlinear systems in such a manner as to expose nonlinear behaviors such as jump phenomenon.\n- Fit transfer functions to experimental data.\n- Describe rigid body rotation and translation.\n- Perform forward and inverse kinematic analysis for linkages.\n- Analyze structural vibrations problems via linear 2D and 3D beam FEM.\n- Determine properties of vibrating systems from experimental data such as resonant frequency, damping ratio, Q-factor, rise time, settling amplitudes, etc.\n- Evaluate the step response behavior of SDOF systems.\n\n## Kinematics Example\nThe following example illustrates the forward and inverse kinematic models of the illustrated 3R mechanism.  This example is Example 127 from Jazar's text \"Theory of Applied Robotics, Kinematics, Dynamics, \u0026 Control.\"\n\n![](images/3R%20Manipulator.PNG?raw=true)\n\nThe following module describes the geometry of the linkage.\n```fortran\nmodule linkage\n    use iso_fortran_env\n    use dynamics\n    \n    ! Parameters\n    real(real64), parameter :: pi = 2.0d0 * acos(0.0d0)\n\n    ! Model Properties\n    real(real64), parameter :: L1 = 1.5d0\n    real(real64), parameter :: L2 = 2.0d1\n    real(real64), parameter :: L3 = 1.0d1\n\n    ! Denavit-Hartenberg Parameters\n    real(real64) :: a(3) = [0.0d0, L2, L3]\n    real(real64) :: alpha(3) = [0.5d0 * pi, 0.0d0, 0.0d0]\n    real(real64) :: d(3) = [0.0d0, L1, 0.0d0]\n\ncontains\n    subroutine kinematics_equations(jointvars, equations)\n        ! The kinematics equations.\n        real(real64), intent(in), dimension(:) :: jointvars\n            ! The joint variables.\n        real(real64), intent(out), dimension(:) :: equations\n            ! The resulting kinematic equations.\n\n        ! Local Variables\n        real(real64) :: T(4, 4)\n        \n        ! Compute the forward kinematics problem\n        T = dh_forward_kinematics(alpha, a, jointvars, d)\n\n        ! Define the equations.\n        ! 1. X position of the end effector\n        ! 2. Y position of the end effector\n        ! 3. Z position of the end effector\n        ! 4. Orientation component of the end-effector\n        ! 5. Orientation component of the end-effector\n        ! 6. Orientation component of the end-effector\n        equations(1:3) = T(1:3,4)\n        equations(4) = T(1,1)\n        equations(5) = T(2,2)\n        equations(6) = T(3,1)\n    end subroutine\nend module\n```\nThe kinematics code is as follows.\n```fortran\nprogram example\n    use iso_fortran_env\n    use dynamics\n    use linkage\n    implicit none\n\n    ! Local Variables\n    real(real64) :: theta(3), T(4, 4), qo(3), q(3), constraints(6)\n    procedure(vecfcn), pointer :: mdl\n\n    ! Define the Denavit-Hartenberg (DH) parameters\n    call random_number(theta)   ! Randomly assign theta.  This is the joint variable\n\n    ! Compute the forward kinematics problem\n    T = dh_forward_kinematics(alpha, a, theta, d)\n\n    ! -------------------------\n    ! Solve the inverse problem.  Use the end-effector position and orientation\n    ! computed by the forward kinematics process as a target for the inverse\n    ! calculations.\n\n    ! First define an initial guess\n    qo = [0.0d0, 0.0d0, 0.0d0]\n\n    ! Define the constraints for each kinematic equation\n    constraints(1:3) = T(1:3,4)\n    constraints(4) = T(1,1)\n    constraints(5) = T(2,2)\n    constraints(6) = T(3,1)\n\n    ! Solve the model\n    mdl =\u003e kinematics_equations\n    q = solve_inverse_kinematics(mdl, qo, constraints)\nend program\n```\nThe output of the forward kinematics is the 4-by-4 transformation matrix relating the end-effector coordinate frame to the base coordinate frame.\n\n```math\nT = \\begin{bmatrix} 0.63810402550972301 \u0026 -0.68876728703171164 \u0026 0.34412625145905751 \u0026 21.729664033078443 \\\\ 0.23387248611350506 \u0026 -0.25244115588063465 \u0026 -0.93892338508354212 \u0026 6.3665980889762501 \\\\ 0.73357134136181679 \u0026 0.67961245363267497 \u0026 6.1230317691118863E-017 \u0026 19.601355890978652 \\\\ 0 \u0026 0 \u0026 0 \u0026 1 \\end{bmatrix}\n```\n\nThis forward result was arrived at for the following values of each joint variable (units = radians).\n\n```math\n\\theta = \\begin{Bmatrix} 0.35130804065430021 \\\\ 0.66020922397550363 \\\\ 0.16335289838907696 \\end{Bmatrix}\n```\n\nThe inverse model computed these joint variables, starting from a zero condition, as follows.\n\n```math\n\\theta_{inv} = \\begin{Bmatrix} 0.35130804065430021 \\\\ 0.66020922397550375 \\\\ 0.16335289838907677 \\end{Bmatrix}\n```\n\n## Frequency Response Example\nConsider the following 3 DOF system.  The following example illustrates how to use this library to compute the frequency response functions for this system.  \n\n![](images/3%20DOF%20Schematic.PNG?raw=true)\n\nThe equations describing this system are as follows.\n\n```math\n\\begin{bmatrix} m_1 \u0026 0 \u0026 0 \\\\ 0 \u0026 m_2 \u0026 0 \\\\ 0 \u0026 0 \u0026 m_3 \\end{bmatrix} \\begin{Bmatrix} \\ddot{x}_1 \\\\ \\ddot{x}_2 \\\\ \\ddot{x}_3 \\end{Bmatrix} + \\begin{bmatrix} b_1 + b_2 \u0026 -b_2 \u0026 0 \\\\ -b_2 \u0026 b_2 + b_3 \u0026 -b_3 \\\\ 0 \u0026 -b_3 \u0026 b_3 + b_4 \\end{bmatrix} \\begin{Bmatrix} \\dot{x}_1 \\\\ \\dot{x}_2 \\\\ \\dot{x}_3 \\end{Bmatrix} + \\begin{bmatrix} k_1 + k_2 \u0026 -k_2 \u0026 0 \\\\ -k_2 \u0026 k_2 + k_3 \u0026 -k_3 \\\\ 0 \u0026 -k_3 \u0026 k_3 + k_4 \\end{bmatrix} \\begin{Bmatrix} x_{1} \\\\ x_{2} \\\\ x_{3} \\end{Bmatrix} = \\begin{Bmatrix} F(t) \\\\ 0 \\\\ 0 \\end{Bmatrix}\n```\n\nThis analysis makes use of proportional damping.  Using proportional damping, the damping matrix is determined as follows.\n\n```math\nB = \\alpha M + \\beta K\n```\n\nThe following module contains the forcing term.\n```fortran\nmodule excitation\n    use iso_fortran_env\n    implicit none\n\ncontains\n    subroutine modal_frf_forcing_term(freq, f)\n        real(real64), intent(in) :: freq\n        complex(real64), intent(out), dimension(:) :: f\n\n        complex(real64), parameter :: zero = (0.0d0, 0.0d0)\n        complex(real64), parameter :: one = (1.0d0, 0.0d0)\n\n        f = [1.0d3 * one, zero, zero]\n    end subroutine\nend module\n```\nThe calling program is as follows.\n```fortran\nprogram example\n    use iso_fortran_env\n    use dynamics\n    use excitation\n    implicit none\n\n    ! Parameters\n    integer(int32), parameter :: nfreq = 1000\n    real(real64), parameter :: pi = 2.0d0 * acos(0.0d0)\n    real(real64), parameter :: fmin = 2.0d0 * pi * 10.0d0\n    real(real64), parameter :: fmax = 2.0d0 * pi * 1.0d3\n    real(real64), parameter :: alpha = 1.0d-3\n    real(real64), parameter :: beta = 2.0d-6\n\n    ! Define the model parameters\n    real(real64), parameter :: m1 = 0.5d0\n    real(real64), parameter :: m2 = 2.5d0\n    real(real64), parameter :: m3 = 0.75d0\n    real(real64), parameter :: k1 = 5.0d6\n    real(real64), parameter :: k2 = 10.0d6\n    real(real64), parameter :: k3 = 10.0d6\n    real(real64), parameter :: k4 = 5.0d6\n\n    ! Local Variables\n    real(real64) :: m(3,3), k(3,3)\n    type(frf) :: rsp\n    procedure(modal_excite), pointer :: fcn\n\n    ! Initialization\n    fcn =\u003e modal_frf_forcing_term\n\n    ! Define the mass matrix\n    m = reshape([m1, 0.0d0, 0.0d0, 0.0d0, m2, 0.0d0, 0.0d0, 0.0d0, m3], [3, 3])\n\n    ! Define the stiffness matrix\n    k = reshape([k1 + k2, -k2, 0.0d0, -k2, k2 + k3, -k3, 0.0d0, -k3, k3 + k4], \u0026\n        [3, 3])\n\n    ! Compute the frequency response functions\n    rsp = frequency_response(m, k, alpha, beta, nfreq, fmin, fmax, fcn)\nend program\n```\n\nThe computed frequency response functions.\n![](images/frf_proportional_example_1.png?raw=true)\n\n## Nonlinear FRF Example\nComputing the frequency response function for a nonlinear system is not as straight-forward.  A technique for capturing nonlinear behaviors, such as jump phenomenon, is to sweep through frequency, in both an ascending and a descending manner.  This example illustrates such a frequency sweeping using the famous Duffing equation as the model.\n\n```math\n\\ddot{x} + \\delta \\dot{x} + \\alpha x + \\beta x^3 = \\gamma \\sin \\omega t\n```\n\nThe following module contains the equation.\n```fortran\nmodule duffing_ode_container\n    use iso_fortran_env\n    use dynamics\n    implicit none\n\n    ! Duffing Model Parameters\n    real(real64), parameter :: alpha = 1.0d0\n    real(real64), parameter :: beta = 4.0d-2\n    real(real64), parameter :: delta = 1.0d-1\n    real(real64), parameter :: gamma = 1.0d0\n\ncontains\n    pure subroutine duffing_ode(freq, x, y, dydx)\n        real(real64), intent(in) :: freq\n            ! The excitation frequency\n        real(real64), intent(in) :: x\n            ! The independent variable.\n        real(real64), intent(in), dimension(:) :: y\n            ! An array of the N dependent variables.\n        real(real64), intent(out), dimension(:) :: dydx\n            ! An output array of length N where the derivatives are written.\n\n        ! Variables\n        real(real64) :: f\n\n        ! Compute the harmonic forcing function\n        f = gamma * sin(freq * x)\n\n        ! Compute the derivatives\n        dydx(1) = y(2)\n        dydx(2) = f - delta * y(2) - alpha * y(1) - beta * y(1)**3\n    end subroutine\nend module\n```\nThe calling program is as follows.\n```fortran\nprogram example\n    use iso_fortran_env\n    use dynamics\n    use duffing_ode_container\n    implicit none\n\n    ! Parameters\n    real(real64), parameter :: f1 = 0.5d0\n    real(real64), parameter :: f2 = 2.0d0\n    integer(int32), parameter :: nfreq = 100\n    \n    ! Local Variables\n    procedure(harmonic_ode), pointer :: fcn\n    type(frf) :: solup, soldown\n\n    ! Point to the ODE routine\n    fcn =\u003e duffing_ode\n\n    ! Perform the ascending sweep\n    solup = frequency_sweep(fcn, nfreq, f1, f2, [0.0d0, 0.0d0])\n\n    ! Perform the descending sweep\n    soldown = frequency_sweep(fcn, nfreq, f2, f1, [0.0d0, 0.0d0])\nend program\n```\nThe computed frequency response functions, both ascending and descending, as compared with the analytical approximation.\n\n![](images/frf_sweep_example_1.png?raw=true)\n\n## References\n1. J. D. Hartog, \"Mechanical Vibrations,\" New York: Dover Publications, Inc., 1985.\n2. S. S. Rau, \"Mechanical Vibrations,\" 3rd ed., Reading, MA: Addison-Wesley Publishing Co., 1995.\n3. R. N. Jazar, \"Advanced Vibrations,\" 2nd ed., New York: Springer, 2022.\n4. W. T. Thomson, \"Theory of Vibration with Applications,\" 4th ed., New York: Springer, 1993.\n5. A. H. Nayfeh and B. Balachandran, \"Applied Nonlinear Dynamics. Analytical, Computational, and Experimental Methods,\" New York: John WIley \u0026 Sons, Inc., 1995.\n6. L. Meirovitch, \"Fundamentals of Vibrations,\" Long Grove, IL: Waveland Press, Inc., 2001.\n7. R. N. Jazar, \"Theory of Applied Robotics, Kinematics, Dynamics, and Control,\" New York: Springer, 2007.\n8. A. H. Nayfeh, \"Introduction to Perturbation Techniques,\" New York: John Wiley \u0026 Sons, Inc., 1993.\n9. Jolicoeur, M.P., Roumy, J.G., Vanreusel, S., Dionne, D., Douville, H., Boulet, B., Michalska, H., Masson, P., \u0026 Berry, A. (2005). \"Reduction of structure-borne noise in automobiles by multivariable feedback.\" 1397 - 1402. 10.1109/CCA.2005.1507327. ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjchristopherson%2Fdynamics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjchristopherson%2Fdynamics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjchristopherson%2Fdynamics/lists"}