{"id":193,"date":"2019-01-10T00:48:26","date_gmt":"2019-01-10T08:48:26","guid":{"rendered":"http:\/\/gantovnik.com\/bio-tips\/?p=193"},"modified":"2024-04-26T17:50:03","modified_gmt":"2024-04-27T00:50:03","slug":"double-pendulum","status":"publish","type":"post","link":"https:\/\/gantovnik.com\/bio-tips\/2019\/01\/double-pendulum\/","title":{"rendered":"#39 Double pendulum using python"},"content":{"rendered":"<p>import os<br \/>\nimport numpy as np<br \/>\nimport matplotlib.pyplot as plt<br \/>\nfrom scipy import integrate<br \/>\nimport sympy<br \/>\nos.chdir(r&#8217;D:\\projects\\wordpress\\ex39&#8242;)<br \/>\nos.getcwd()<br \/>\nt, g, m1, l1, m2, l2 = sympy.symbols(&#8220;t, g, m_1, l_1, m_2, l_2&#8221;)<br \/>\ntheta1, theta2 = sympy.symbols(&#8220;theta_1, theta_2&#8221;, cls=sympy.Function)<br \/>\node1 = sympy.Eq((m1+m2)*l1 * theta1(t).diff(t,t) +<br \/>\nm2*l2 * theta2(t).diff(t,t) +<br \/>\nm2*l2 * theta2(t).diff(t)**2 * sympy.sin(theta1(t)-theta2(t)) +<br \/>\ng*(m1+m2) * sympy.sin(theta1(t)))<br \/>\node1<br \/>\node2 = sympy.Eq(m2*l2 * theta2(t).diff(t,t) +<br \/>\nm2*l1 * theta1(t).diff(t,t) * sympy.cos(theta1(t)-theta2(t)) &#8211;<br \/>\nm2*l1 * theta1(t).diff(t)**2 * sympy.sin(theta1(t) &#8211; theta2(t)) +<br \/>\nm2*g * sympy.sin(theta2(t)))<br \/>\node2<br \/>\n# sympy cannot solve these ODEs<br \/>\ntry:<br \/>\n    sympy.dsolve(ode1, ode2)<br \/>\nexcept Exception as e:<br \/>\n    print(e)<\/p>\n<p>y1, y2, y3, y4 = sympy.symbols(&#8220;y_1, y_2, y_3, y_4&#8221;, cls=sympy.Function)<br \/>\nvarchange = {theta1(t).diff(t, t): y2(t).diff(t),<br \/>\ntheta1(t): y1(t),<br \/>\ntheta2(t).diff(t, t): y4(t).diff(t),<br \/>\ntheta2(t): y3(t)}<br \/>\node1_vc = ode1.subs(varchange)<br \/>\node2_vc = ode2.subs(varchange)<br \/>\node3 = y1(t).diff(t) &#8211; y2(t)<br \/>\node4 = y3(t).diff(t) &#8211; y4(t)<br \/>\ny = sympy.Matrix([y1(t), y2(t), y3(t), y4(t)])<br \/>\nvcsol = sympy.solve((ode1_vc, ode2_vc, ode3, ode4), y.diff(t), dict=True)<br \/>\nf = y.diff(t).subs(vcsol[0])<br \/>\nsympy.Eq(y.diff(t), f)<br \/>\nparams = {m1: 5.0, l1: 2.0,<br \/>\nm2: 1.0, l2: 1.0, g: 10.0}<br \/>\nf_np = sympy.lambdify((t, y), f.subs(params), &#8216;numpy&#8217;)<br \/>\njac = sympy.Matrix([[fj.diff(yi) for yi in y] for fj in f])<br \/>\njac_np = sympy.lambdify((t, y), jac.subs(params), &#8216;numpy&#8217;)<br \/>\ny0 = [2.0, 0, 0.0, 0]\nt = np.linspace(0, 20, 1000)<br \/>\njac_np(0, y0)<br \/>\nr = integrate.ode(f_np, jac_np).set_initial_value(y0, t[0]);<br \/>\ndt = t[1] &#8211; t[0]\ny = np.zeros((len(t), len(y0)))<br \/>\nidx = 0<br \/>\nwhile r.successful() and r.t &lt; t[-1]:<br \/>\n    y[idx, :] = r.y<br \/>\n    r.integrate(r.t + dt)<br \/>\n    idx += 1<\/p>\n<p>fig = plt.figure(figsize=(10, 4))<br \/>\nax1 = plt.subplot2grid((2, 5), (0, 0), colspan=3)<br \/>\nax2 = plt.subplot2grid((2, 5), (1, 0), colspan=3)<br \/>\nax3 = plt.subplot2grid((2, 5), (0, 3), colspan=2, rowspan=2)<br \/>\nax1.plot(t, y[:, 0], &#8216;r&#8217;)<br \/>\nax1.set_ylabel(r&#8217;$\\theta_1$&#8217;, fontsize=18)<br \/>\nax2.plot(t, y[:, 2], &#8216;b&#8217;)<br \/>\nax2.set_xlabel(&#8216;$t$&#8217;, fontsize=18)<br \/>\nax2.set_ylabel(r&#8217;$\\theta_2$&#8217;, fontsize=18)<br \/>\nax3.plot(y[:, 0], y[:, 2], &#8216;k&#8217;)<br \/>\nax3.set_xlabel(r&#8217;$\\theta_1$&#8217;, fontsize=18)<br \/>\nax3.set_ylabel(r&#8217;$\\theta_2$&#8217;, fontsize=18)<br \/>\nfig.tight_layout()<br \/>\nplt.savefig(&#8220;example39.png&#8221;, dpi=100)<\/p>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" class=\"  wp-image-194 aligncenter\" src=\"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example39.png?resize=634%2C254\" alt=\"example39\" width=\"634\" height=\"254\" srcset=\"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example39.png?w=1000&amp;ssl=1 1000w, https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example39.png?resize=300%2C120&amp;ssl=1 300w, https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example39.png?resize=768%2C307&amp;ssl=1 768w\" sizes=\"(max-width: 634px) 100vw, 634px\" \/><\/p>\n<p>theta1_np, theta2_np = y[:, 0], y[:, 2]\nx1 = params[l1] * np.sin(theta1_np)<br \/>\ny1 = -params[l1] * np.cos(theta1_np)<br \/>\nx2 = x1 + params[l2] * np.sin(theta2_np)<br \/>\ny2 = y1 &#8211; params[l2] * np.cos(theta2_np)<br \/>\nfig = plt.figure(figsize=(10, 4))<br \/>\nax1 = plt.subplot2grid((2, 5), (0, 0), colspan=3)<br \/>\nax2 = plt.subplot2grid((2, 5), (1, 0), colspan=3)<br \/>\nax3 = plt.subplot2grid((2, 5), (0, 3), colspan=2, rowspan=2)<br \/>\nax1.plot(t, x1, &#8216;r&#8217;)<br \/>\nax1.plot(t, y1, &#8216;b&#8217;)<br \/>\nax1.set_ylabel(&#8216;$x_1, y_1$&#8217;, fontsize=18)<br \/>\nax1.set_yticks([-3, 0, 3])<br \/>\nax2.plot(t, x2, &#8216;r&#8217;)<br \/>\nax2.plot(t, y2, &#8216;b&#8217;)<br \/>\nax2.set_xlabel(&#8216;$t$&#8217;, fontsize=18)<br \/>\nax2.set_ylabel(&#8216;$x_2, y_2$&#8217;, fontsize=18)<br \/>\nax2.set_yticks([-3, 0, 3])<br \/>\nax3.plot(x1, y1, &#8216;r&#8217;)<br \/>\nax3.plot(x2, y2, &#8216;b&#8217;, lw=0.5)<br \/>\nax3.set_xlabel(&#8216;$x$&#8217;, fontsize=18)<br \/>\nax3.set_ylabel(&#8216;$y$&#8217;, fontsize=18)<br \/>\nax3.set_xticks([-3, 0, 3])<br \/>\nax3.set_yticks([-3, 0, 3])<br \/>\nfig.tight_layout()<br \/>\nplt.savefig(&#8220;example39_2.png&#8221;, dpi=100)<br \/>\nplt.show()<br \/>\nplt.close()<\/p>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" class=\"  wp-image-195 aligncenter\" src=\"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example39_2.png?resize=639%2C256\" alt=\"example39_2\" width=\"639\" height=\"256\" srcset=\"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example39_2.png?w=1000&amp;ssl=1 1000w, https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example39_2.png?resize=300%2C120&amp;ssl=1 300w, https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example39_2.png?resize=768%2C307&amp;ssl=1 768w\" sizes=\"(max-width: 639px) 100vw, 639px\" \/><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>import os import numpy as np import matplotlib.pyplot as plt from scipy import integrate import sympy os.chdir(r&#8217;D:\\projects\\wordpress\\ex39&#8242;) os.getcwd() t, g, m1, l1, m2, l2 = sympy.symbols(&#8220;t, g, m_1, l_1, m_2, l_2&#8221;) theta1, theta2 = sympy.symbols(&#8220;theta_1, theta_2&#8221;, cls=sympy.Function) ode1 = sympy.Eq((m1+m2)*l1 * theta1(t).diff(t,t) + m2*l2 * theta2(t).diff(t,t) + m2*l2 * theta2(t).diff(t)**2 * sympy.sin(theta1(t)-theta2(t)) + g*(m1+m2) * [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","_lmt_disableupdate":"yes","_lmt_disable":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[2],"tags":[],"class_list":["post-193","post","type-post","status-publish","format-standard","hentry","category-python"],"modified_by":"gantovnik","jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8bH0k-37","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":148,"url":"https:\/\/gantovnik.com\/bio-tips\/2019\/01\/damped-harmonic-oscillator\/","url_meta":{"origin":193,"position":0},"title":"Damped harmonic oscillator","author":"gantovnik","date":"2019-01-06","format":false,"excerpt":"import os import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl mpl.rcParams['text.usetex'] = True import sympy from IPython.display import display sympy.init_printing() def apply_ics(sol, ics, x, known_params): free_params = sol.free_symbols - set(known_params) eqs = [(sol.lhs.diff(x, n) - sol.rhs.diff(x, n)).subs(x, 0).subs(ics) for n in range(len(ics))] sol_params = sympy.solve(eqs, free_params)\u2026","rel":"","context":"In &quot;python&quot;","block_context":{"text":"python","link":"https:\/\/gantovnik.com\/bio-tips\/category\/python\/"},"img":{"alt_text":"example31","src":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example31.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example31.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example31.png?resize=525%2C300 1.5x"},"classes":[]},{"id":1204,"url":"https:\/\/gantovnik.com\/bio-tips\/2021\/11\/210-parametric-curve-in-3d-2-2\/","url_meta":{"origin":193,"position":1},"title":"#212 The double pendulum simulation using python","author":"gantovnik","date":"2021-11-27","format":false,"excerpt":"","rel":"","context":"In &quot;animation&quot;","block_context":{"text":"animation","link":"https:\/\/gantovnik.com\/bio-tips\/category\/animation\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2021\/11\/ex212.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":143,"url":"https:\/\/gantovnik.com\/bio-tips\/2019\/01\/143\/","url_meta":{"origin":193,"position":2},"title":"#30 Newton&#8217;s Law of Cooling","author":"gantovnik","date":"2019-01-06","format":false,"excerpt":"import os import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl mpl.rcParams['text.usetex'] = True import sympy from IPython.display import display sympy.init_printing() #%matplotlib inline #%config InlineBackend.figure_format='retina' os.chdir(r'D:\\projects\\wordpress\\ex30') os.getcwd() #Symbolic ODE solving with SymPy #Newton's law of cooling t, k, T0, Ta = sympy.symbols(\"t, k, T_0, T_a\") T =\u2026","rel":"","context":"In &quot;python&quot;","block_context":{"text":"python","link":"https:\/\/gantovnik.com\/bio-tips\/category\/python\/"},"img":{"alt_text":"example30","src":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example30.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example30.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example30.png?resize=525%2C300 1.5x"},"classes":[]},{"id":154,"url":"https:\/\/gantovnik.com\/bio-tips\/2019\/01\/inexact-solutions-to-odes\/","url_meta":{"origin":193,"position":3},"title":"Inexact solutions to ODEs","author":"gantovnik","date":"2019-01-08","format":false,"excerpt":"\u00a0 import os import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl import sympy from IPython.display import display sympy.init_printing() mpl.rcParams['text.usetex'] = True import sympy os.chdir(r'D:\\projects\\wordpress\\ex33') os.getcwd() def plot_direction_field(x, y_x, f_xy, x_lim=(-5, 5), y_lim=(-5, 5), ax=None): f_np = sympy.lambdify((x, y_x), f_xy, 'numpy') x_vec = np.linspace(x_lim[0], x_lim[1], 20) y_vec\u2026","rel":"","context":"In &quot;python&quot;","block_context":{"text":"python","link":"https:\/\/gantovnik.com\/bio-tips\/category\/python\/"},"img":{"alt_text":"example33","src":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example33.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example33.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example33.png?resize=525%2C300 1.5x"},"classes":[]},{"id":190,"url":"https:\/\/gantovnik.com\/bio-tips\/2019\/01\/coupled-damped-springs-jacobian-is-available\/","url_meta":{"origin":193,"position":4},"title":"Coupled damped springs (Jacobian is available)","author":"gantovnik","date":"2019-01-10","format":false,"excerpt":"\u00a0 import os import numpy as np import matplotlib.pyplot as plt from scipy import integrate os.chdir(r'D:\\projects\\wordpress\\ex38') os.getcwd() def f(t, y, args): m1, k1, g1, m2, k2, g2 = args return [y[1], - k1\/m1 * y[0] + k2\/m1 * (y[2] - y[0]) - g1\/m1 * y[1], y[3], - k2\/m2 * (y[2]\u2026","rel":"","context":"In &quot;python&quot;","block_context":{"text":"python","link":"https:\/\/gantovnik.com\/bio-tips\/category\/python\/"},"img":{"alt_text":"example38","src":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example38.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example38.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example38.png?resize=525%2C300 1.5x"},"classes":[]},{"id":151,"url":"https:\/\/gantovnik.com\/bio-tips\/2019\/01\/direction-fields\/","url_meta":{"origin":193,"position":5},"title":"Direction fields","author":"gantovnik","date":"2019-01-07","format":false,"excerpt":"","rel":"","context":"In &quot;python&quot;","block_context":{"text":"python","link":"https:\/\/gantovnik.com\/bio-tips\/category\/python\/"},"img":{"alt_text":"example32","src":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example32.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example32.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/gantovnik.com\/bio-tips\/wp-content\/uploads\/2019\/01\/example32.png?resize=525%2C300 1.5x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/gantovnik.com\/bio-tips\/wp-json\/wp\/v2\/posts\/193","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gantovnik.com\/bio-tips\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gantovnik.com\/bio-tips\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gantovnik.com\/bio-tips\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gantovnik.com\/bio-tips\/wp-json\/wp\/v2\/comments?post=193"}],"version-history":[{"count":2,"href":"https:\/\/gantovnik.com\/bio-tips\/wp-json\/wp\/v2\/posts\/193\/revisions"}],"predecessor-version":[{"id":2151,"href":"https:\/\/gantovnik.com\/bio-tips\/wp-json\/wp\/v2\/posts\/193\/revisions\/2151"}],"wp:attachment":[{"href":"https:\/\/gantovnik.com\/bio-tips\/wp-json\/wp\/v2\/media?parent=193"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gantovnik.com\/bio-tips\/wp-json\/wp\/v2\/categories?post=193"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gantovnik.com\/bio-tips\/wp-json\/wp\/v2\/tags?post=193"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}