{"id":189,"date":"2023-06-06T14:39:39","date_gmt":"2023-06-06T12:39:39","guid":{"rendered":"https:\/\/logbooks.ifosim.org\/finesse\/?p=189"},"modified":"2023-06-06T15:48:06","modified_gmt":"2023-06-06T13:48:06","slug":"specifying-arbitrary-suspension-plants","status":"publish","type":"post","link":"https:\/\/logbooks.ifosim.org\/finesse\/2023\/06\/06\/specifying-arbitrary-suspension-plants\/","title":{"rendered":"Specifying arbitrary suspension plants"},"content":{"rendered":"\n<p>Arbitrary mechanical plants can be specified for each optic by giving a zpk description. The example below makes a simple Fabry-Perot cavity and specifies the longitudinal and pitch plants.<\/p>\n\n\n\n<p>First build the cavity<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import numpy as np\nfrom finesse import Model\nimport finesse.components as fcmp\nimport finesse.analysis.actions as fact\nfrom finesse.plotting import bode\n\nPin_W = 5e3    # input power &#091;W]\nTi = 0.014     # ITM transmissivity\nLcav_m = 40e3  # cavity length &#091;m]\nRi_m = 34e3    # ITM radius of curvature &#091;m]\nRe_m = 36e3    # ETM radius of curvature &#091;m]\n\n# make the cavity\nmodel = Model()\nmodel.add(fcmp.Mirror('ETM', T=0, L=0, Rc=Re_m))\nmodel.add(fcmp.Mirror('ITM', T=Ti, L=0, Rc=Ri_m))\nmodel.connect(model.ETM.p1, model.ITM.p1, L=Lcav_m)\nmodel.add(fcmp.Cavity('cav', model.ETM.p1.o))\n\n# add input\nmodel.add(fcmp.Laser('Laser', P=Pin_W))\nmodel.connect(model.Laser.p1, model.ITM.p2)<\/code><\/pre>\n\n\n\n<p>The suspension plants are specified by defining dictionaries with the zpk definition of the plant. The code below defines a simple pendulum plant with a single complex pole. The degrees of freedom which can be read out are <code>z<\/code>, <code>pitch<\/code>, or <code>yaw<\/code> and the degrees of freedom which can be driven are <code>F_z<\/code>, <code>F_pitch<\/code>, and <code>F_yaw<\/code>.<\/p>\n\n\n\n<p>So for example, <code>sus_plant['z', F_z']<\/code> is the longitudinal plant in m \/ N and <code>sus_plant['pitch', 'F_z']<\/code> is the cross-coupling of longitudinal motion into pitch in units of rad \/ N. The code below doesn&#8217;t define any cross-couplings.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># define the suspension plant\nI_kgm2 = 10  # moment of inertia\nM_kg = 0.01  # mass\n\n# for simplicity use the same poles for both pitch and z\nF0_Hz = 1  # resonance frequency &#091;Hz]\nQ = 100    # Q factor\nFp_Hz = np.array(&#091;\n    -F0_Hz \/ (2 * Q) * (1 + 1j * np.sqrt(4 * Q**2 - 1)),\n    -F0_Hz \/ (2 * Q) * (1 - 1j * np.sqrt(4 * Q**2 - 1))\n])\n\n# the suspension plant is defined with a dictionary\nsus_plant = {}\nsus_plant&#091;'z', 'F_z'] = (&#091;], 2 * np.pi * Fp_Hz, 1 \/ M_kg)\nsus_plant&#091;'pitch', 'F_pitch'] = (&#091;], 2 * np.pi * Fp_Hz, 1 \/ I_kgm2)\nmodel.add(fcmp.mechanical.SuspensionZPK('ETM_sus', model.ETM.mech, sus_plant))\nmodel.add(fcmp.mechanical.SuspensionZPK('ITM_sus', model.ITM.mech, sus_plant))<\/code><\/pre>\n\n\n\n<p>Now run the model computing both pitch and longitudinal motion. First compute pitch then detune the cavity by 1 degree so that there is a longitudinal optical spring and calculate the longitudinal motion.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>model.modes(maxtem=1)\nF_Hz = np.geomspace(0.1, 3e3, 1000)  # the best thing since sliced bread\nout = model.run(\n    fact.Series(\n        fact.FrequencyResponse(\n            F_Hz,\n            &#091;'ETM.mech.F_pitch', 'ITM.mech.F_pitch'],\n            &#091;'ETM.mech.pitch', 'ITM.mech.pitch'],\n            name='pitch',\n        ),\n        fact.Change({'ETM.phi': 1}),\n        fact.FrequencyResponse(\n            F_Hz,\n            &#091;'ETM.mech.F_z', 'ITM.mech.F_z'],\n            &#091;'ETM.mech.z', 'ITM.mech.z'],\n            name='z',\n        ),\n    )\n)\ntfs_pitch = out&#091;'pitch'].out  # (1000, 2, 2) matrix of angular transfer functions\ntfs_z     = out&#091;'z'].out      # (1000, 2, 2) matrix of longitudinal transfer functions\n<\/code><\/pre>\n\n\n\n<p>Now plot the torsional spring in the hard\/soft basis. The above transfer functions were computed in the ETM\/ITM basis. Hard and soft degrees of freedom can also be defined using <code>DegreeOfFreedom<\/code> and used to compute the transfer functions instead.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gi = 1 - Lcav_m \/ Ri_m\nge = 1 - Lcav_m \/ Re_m\nr = 2 \/ ((gi - ge) + np.sqrt((gi - ge)**2 + 4))\n\nhard = dict(ITM=-1, ETM=r)\nsoft = dict(ITM=r, ETM=1)\nvhard = np.array(&#091;hard&#091;'ETM'], hard&#091;'ITM']])\nvsoft = np.array(&#091;soft&#091;'ETM'], soft&#091;'ITM']])\n\n# tfs_pitch is in the ETM\/ITM basis, so convert to hard\/soft\ntf_hard = vhard @ tfs_pitch @ vhard.T\ntf_soft = vsoft @ tfs_pitch @ vsoft.T\n\naxs = bode(F_Hz, tf_hard, label='Hard')\nbode(F_Hz, tf_soft, axs=axs, label='Soft')\nbode(F_Hz, tfs_pitch&#091;..., 0, 0], axs=axs, label='ETM')\nfor ax in axs:\n    ax.grid(True, which='major', alpha=0.5)\n    ax.grid(True, which='minor', alpha=0.2)\n    ax.set_xlim(F_Hz&#091;0], 30)\naxs&#091;0].set_ylim(-100, 10)\naxs&#091;0].legend()<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"600\" src=\"https:\/\/logbooks.ifosim.org\/finesse\/wp-content\/uploads\/sites\/5\/2023\/06\/pitch_plants.png\" alt=\"\" class=\"wp-image-193\" srcset=\"https:\/\/logbooks.ifosim.org\/finesse\/wp-content\/uploads\/sites\/5\/2023\/06\/pitch_plants.png 600w, https:\/\/logbooks.ifosim.org\/finesse\/wp-content\/uploads\/sites\/5\/2023\/06\/pitch_plants-300x300.png 300w, https:\/\/logbooks.ifosim.org\/finesse\/wp-content\/uploads\/sites\/5\/2023\/06\/pitch_plants-150x150.png 150w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/figure>\n\n\n\n<p>And now plot the longitudinal optical spring.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>axs = bode(F_Hz, tfs_z&#091;..., 0, 0], label='ETM to ETM')\nbode(F_Hz, tfs_z&#091;..., 1, 0], axs=axs, label='ETM to ITM', ls='--')\nfor ax in axs:\n    ax.grid(True, which='major', alpha=0.5)\n    ax.grid(True, which='minor', alpha=0.2)\n    ax.set_xlim(F_Hz&#091;0], F_Hz&#091;-1])\n<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"600\" src=\"https:\/\/logbooks.ifosim.org\/finesse\/wp-content\/uploads\/sites\/5\/2023\/06\/z_plants.png\" alt=\"\" class=\"wp-image-195\" srcset=\"https:\/\/logbooks.ifosim.org\/finesse\/wp-content\/uploads\/sites\/5\/2023\/06\/z_plants.png 600w, https:\/\/logbooks.ifosim.org\/finesse\/wp-content\/uploads\/sites\/5\/2023\/06\/z_plants-300x300.png 300w, https:\/\/logbooks.ifosim.org\/finesse\/wp-content\/uploads\/sites\/5\/2023\/06\/z_plants-150x150.png 150w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Arbitrary mechanical plants can be specified for each optic by giving a zpk description. The example below makes a simple Fabry-Perot cavity and specifies the longitudinal and pitch plants. First build the cavity The suspension plants are specified by defining dictionaries with the zpk definition of the plant. The code below defines a simple pendulum [&hellip;]<\/p>\n","protected":false},"author":85,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"ssl_alp_hide_revisions":false,"footnotes":"","ssl_alp_hide_crossreferences_to":false},"categories":[14],"tags":[],"ssl-alp-coauthor":[55],"class_list":["post-189","post","type-post","status-publish","format-standard","hentry","category-finesse3"],"_links":{"self":[{"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/posts\/189","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/users\/85"}],"replies":[{"embeddable":true,"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/comments?post=189"}],"version-history":[{"count":10,"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/posts\/189\/revisions"}],"predecessor-version":[{"id":201,"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/posts\/189\/revisions\/201"}],"wp:attachment":[{"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/media?parent=189"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/categories?post=189"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/tags?post=189"},{"taxonomy":"ssl-alp-coauthor","embeddable":true,"href":"https:\/\/logbooks.ifosim.org\/finesse\/wp-json\/wp\/v2\/ssl-alp-coauthor?post=189"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}