\DocumentMetadata{} %% $Id: pst-massspring-doc.tex 1191 2025-12-18 09:53:56Z herbert $ \documentclass[fontsize=11pt,english,BCOR=10mm,DIV=12,bibliography=totoc,parskip=false, headings=small, headinclude=false,footinclude=false,twoside]{pst-doc} \usepackage{pst-gears} \usepackage{pst-plot} \usepackage{animate} \usepackage{pst-tools,pst-solides3d,pst-massspring} \let\PSTfileversion\fileversion \let\PSTfiledate\filedate \addbibresource{\jobname.bib} \renewcommand\bgImage{\begin{pspicture}(-1,-0.5)(4,2) \psElectromagnet \end{pspicture}} \addbibresource{\jobname.bib} \usepackage{enumitem} \setlist{nosep} \begin{document} \title{\texttt{pst-massspring}} \subtitle{Spring and mass; v.\PSTfileversion} \author{Manuel Luque \\ Herbert Voß} \docauthor{} \date{\today} \settitle \def\DatsSystem{ % valeurs par défaut utilisées dans cet exemple /kR 7.5 def /L0 5 def /m1 0.5 def /m2 2 def /radius1 m1 1 3 div exp def /radius2 m2 1 3 div exp def /Gravity 9.8 def /dl0 m2 Gravity mul kR div def /mu m1 m2 mul m1 m2 add div def /w0 kR mu div sqrt 180 mul 6.283185 div def % en degrees /T0 6.283185 kR mu div sqrt div def % période % /t@ 0 def /z20 radius1 radius2 add L0 add m2 Gravity mul kR div add def /Z@ m2 Gravity mul kR div t@ w0 mul cos mul L0 add radius1 add radius2 add def /zG0 m2 z20 mul m1 m2 add div def /zG 0.5 Gravity mul t@ 2 exp mul zG0 add def /Z1 zG m2 m1 m2 add div Z@ mul sub def /Z2 Z@ Z1 add def /zR1 Z1 neg radius1 sub def /zR2 Z2 neg radius2 add def % les tensions /Tension2 kR zR2 zR1 sub L0 add mul def /Tension1 kR zR2 zR1 sub L0 add mul neg def }% \part{Representation of a spring in pseudo-perspective} Timothy Van Zandt's pst-coil package (later expanded by subsequent maintainers) is primarily dedicated to the perspective representation of springs and offers numerous options. However, despite the number of options, these cannot fully satisfy physicists. Indeed, the two options `coilwidth`, which sets the spring diameter, and `coilheight`, which sets the distance between two coils—that is, the helix pitch—do not account for the fact that if the spring length is changed by compressing or stretching it, the number of coils remains the same, and the distance between the coils, as well as the spring diameter, a re modified. The \Lcs{psMassSpring} command allows for consideration of the physical behavior of a spring. \section{Initial state of the spring} \newcommand\bille{% \psset{linewidth=0.02,fillstyle=solid,fillcolor=blue!70} \pscircle[linecolor=blue](0,0){0.5} \psarc[linecolor=black](0,0){0.425}{-110}{90} \psarc[linecolor=black](0,0){0.3}{-90}{70} \psarc[linecolor=black](0,0){0.2}{-70}{60}} %%%% \newcommand\billeB{% \pscircle(0,0){0.5} \psarc(0,0){0.425}{-110}{90} \psarc(0,0){0.3}{-90}{70} \psarc(0,0){0.2}{-70}{60}} \begin{exampleM}{The default spiral} \begin{pspicture}[showgrid](-2,-2)(14,2)\psframe(-2,-2)(14,2) \psSpiral[N=20,li=10,R=0.5,alpha=20,dl=0.5,linewidth=0.05]{*-*}(0,0)(11,0) \psline[linewidth=0.5\pslinewidth](0.5,0)(0.5,1.25) \psline[linewidth=0.5\pslinewidth](10.5,0)(10.5,1.25) \psline[arrowsize=0.2,arrowinset=0.1]{<->}(0.5,1)(10.5,1)\uput[u](5.5,1){li=10 cm} \psline[linewidth=0.5\pslinewidth](0,0)(0,1.25) \psline[arrowsize=0.2,arrowinset=0.1]{>-}(-0.22,1)(0.5,1)\uput[u](0.25,1){dl} \psline[linewidth=0.5\pslinewidth](11,0)(11,1.25) \psline[arrowsize=0.2,arrowinset=0.1]{-<}(10.5,1)(11.25,1)\uput[u](10.75,1){dl} \end{pspicture} \end{exampleM} The same spring stretched by 5 cm. \begin{exampleM}{A stretched spiral} \begin{pspicture}[showframe](-2,-2)(14,2) \psSpiral[N=20,li=10,R=0.5,alpha=20,dl=0.5,linewidth=0.05]{*-*}(-2,0)(14,0) \psline[linewidth=0.5\pslinewidth](-1.5,0)(-1.5,1.25) \psline[linewidth=0.5\pslinewidth](13.5,0)(13.5,1.25) \psline[arrowsize=0.2,arrowinset=0.1]{<->}(-1.5,1)(13.5,1)\uput[u](5.5,1){L=15 cm} \psline[linewidth=0.5\pslinewidth](-2,0)(-2,1.25) \psline[arrowsize=0.2,arrowinset=0.1]{>-}(-2.25,1)(-1.5,1)\uput[u](-1.75,1){dl} \psline[linewidth=0.5\pslinewidth](14,0)(14,1.25) \psline[arrowsize=0.2,arrowinset=0.1]{-<}(13.5,1)(14.25,1)\uput[u](13.75,1){dl} \end{pspicture} \end{exampleM} \newpage \subsection{Parameters} \verb+\psSpiral[N=10,li=5,R=0.5,alpha=15,dl=0,nS=25](x1,y1)(x2,y2)+ The default values are: \begin{description}[nosep] \item[\Lkeyset{N=10}]: number of turns; \item[\Lkeyset{li=5}]: initial length; \item[\Lkeyset{R=0.5}]: initial radius of the spring; \item[\Lkeyset{dl=0}]: length of any attachments at the ends; \item[\Lkeyset{alpha=15}]: angle of the projection direction (see below); \item[\Lkeyset{nS=25}]: for the plot, number of points per turn. \end{description} \begin{center} \psset{unit=0.75} \def\nFrames{44}% 44 images \def\calc{% /Z0 -16 def /OMEGA 20 0.1 div sqrt def % pulsation des oscillations /Period TwoPi OMEGA div def % 0.4442883 /ti \rt\space def /ZR Z0 -5 OMEGA RadtoDeg ti mul cos mul add def } \begin{animateinline}[controls,loop,% begin={\begin{pspicture}(-2,1)(2,-23)}, end={\end{pspicture}}]{5}% 5 images/s \multiframe{\nFrames}{rt=0+0.01}{\psframe(-2,1)(2,-23) \psframe[fillstyle=hlines,linestyle=none,hatchcolor=black](-1,0)(1,0.2) \psline(-1,0)(1,0)\psdot(0,0) \psgrid[subgriddiv=0,griddots=10,gridlabels=0pt] \psSpiral[dl=0.5,R=0.5,alpha=25,N=20,li=10,linewidth=0.05](0,0)(! 0 \calc ZR) \rput(! 0 \calc ZR 0.5 sub){\bille}% }% \end{animateinline} \end{center} \newpage \section{Other examples} \begin{exampleM}{Example 1} \psset{unit=0.9} \begin{pspicture}[showgrid](-2,0)(16,15) \psSpiral(0,0)(0,15) \psSpiral[linecolor=blue,N=20,R=0.5,linewidth=0.1, alpha=-20,dl=1,arrowinset=0.1]{<->}(7,2)(11,10) \psSpiral[linecolor=red,N=20,R=0.5](13,5)(15,1) \end{pspicture} \end{exampleM} \begin{exampleM}{Example 2} \psset{unit=0.9} \begin{pspicture}[showgrid](-0.5,-5)(16.5,5) \psSpiral[linecolor=blue,N=25,R=1,li=5,dl=0.5,alpha=-20,doubleline=true](0,3)(16,3) \psset{alpha=25} \psSpiral[linecolor=red,N=8,R=0.5,li=5,dl=0](0,0)(4,0) \psSpiral[linecolor=black,N=8,R=0.5,li=5,dl=0](16,0) \psSpiral[linecolor=blue,N=15.5,R=0.5,li=5,dl=0.5,alpha=0](0,-2)(16,-2) \end{pspicture} \end{exampleM} \section{Some explanations} \begin{center} \includegraphics{images/image0} \end{center} Parametric equations of the cylindrical helix: \begin{align} x_H&=x_0+R\cos(2\pi{}t)\\ y_H&=x_0+R\sin(2\pi{}t)\\ z_H&=z_0+\mathrm{p}t \end{align} $R$ is the radius of the cylinder and $p$ is the pitch of the helix. This helix is a projected onto the $Oyz$ plane (or a plane parallel to it) along a direction $\overrightarrow{u}(\cos\alpha,0,\sin\alpha)$. The parametric equations of a line in direction u and passing through a point $P(x_H,y_H,z_H)$ on the helix are \begin{align} x&=x_H+\lambda\cos\alpha\\ y&=y_H\\ z&=z_H+\lambda\sin\alpha \end{align} he intersection of one of these lines with the $Oyz$ plane gives the expression for $\lambda$: \[ 0=x_H+\lambda\cos\alpha \Longrightarrow \lambda=-\frac{x_H}{\cos\alpha} \] The coordinates are: \begin{align} x&=0\\ y&=y_H\\ z&=z_H-x_H\tan\alpha \end{align} \begin{align} x&=0\\ y&=y_0+R\sin(2\pi{}t)\\ z&=z_0+\mathrm{p}t-\Big(x_0+R\cos(2\pi{}t)\Big)\tan\alpha \end{align} For the 2D representation, we will take: \begin{align} X&=z_0+\mathrm{p}t-\Big(x_0+R\cos(2\pi{}t)\Big)\tan\alpha\\ Y&=y_0+R\sin(2\pi{}t) \end{align} If the spring has a straight attachment at each end of length $\mathrm{d}l$, then $z_0=\mathrm{d}l$. \begin{align} X&=\mathrm{d}l+\mathrm{p}t-\Big(x_0+R\cos(2\pi{}t)\Big)\tan\alpha\\ Y&=y_0+R\sin(2\pi{}t) \end{align} We want the starting point of the helix to be on the axis $(X=\mathrm{d}l,Y=0)$. We deduce $x_0$ by setting $t = 0$: \[ x_0=-R \] The equations for the 2D projection of the helix are: \begin{align} X&=\mathrm{d}l+\mathrm{p}t-\Big(-R+R\cos(2\pi{}t)\Big)\tan\alpha\\ Y&=R\sin(2\pi{}t) \end{align} For the spring, the number of turns, its initial radius, and its initial length must be specified, that is, when it is neither compressed nor stretched. When the spring is stretched or compressed, its length changes, of course, but also its radius, albeit less perceptibly; the \Lcs{psMassSpring} command takes this into account. From the initial length and the number of turns, the initial pitch of the spring can be deduced. \begin{verbatim} /NbreSpires \psk@NbreSpires def % nombre de spires /Alpha \psk@Alpha def % direction de projection /R_0 \psk@RayonInitial \pst@number\psunit mul def /dl \psk@dl \pst@number\psunit mul def /l_0 \psk@LongueurInitiale \pst@number\psunit mul def /nS \psk@nS def % nombre de points par spire /Pas_0 l_0 NbreSpires div def \end{verbatim} The length of a coil, which remains constant, is calculated using the following relationship: \[ l=2\pi\sqrt{R_0^2+\left(\frac{\mathrm{p_0}}{2\pi}\right)^2} \] $R_0$ and $p_0$ are respectively the radius and the initial pitch. When the spring is under load, its length is calculated using the coordinates of its ends, taking into account, if necessary, the length of the end strands. From this new length, the new pitch is deduced, followed by the current radius of the spring and the parametric equations of the helix. \begin{verbatim} % longueur de l'hélice sur un tour % = sqrt(4*pi^2*R^2+p^2) /Longueur_Helice_pas 39.47842 R_0 dup mul mul Pas_0 dup mul add sqrt def % R=1/(2*pi)*sqrt(L^2-p^2) /Radius 0.1591549 Longueur_Helice_pas dup mul Pas dup mul sub sqrt mul def /xH {Radius 360 t mul cos mul Radius sub} def /yH {Radius 360 t mul sin mul} def /zH {Pas t mul dl add} def \end{verbatim} \clearpage \part{Mass and spring} \section{Basics} \begin{center} \begin{pspicture}(-3,-0.5)(3,1.5) \psset{unit=1,dimen=middle} \psSpiral[R=0.4,N=15,l0=5]{-}(-2.5,0)(2.5,0) \psline{<->}(-2.5,1)(2.5,1) \uput[u](0,1){$l_0$} %\psgrid[subgriddiv=0,gridcolor=lightgray,griddots=10,gridlabels=0pt,unit=1]% \end{pspicture} \end{center} \begin{center} \includegraphics{images/image1} \end{center} \section{Equations of Motion} This is an exercise I found in two physics textbooks: “Lagrangian Dynamics” by Dare A. Wells \parencite[p. 12--13]{wells1967} and under the title “System of two masses in elastic interaction and free fall” exercise E25-1 in \textcite{perez2011}. The latter offers a solution but does not take into account the respective radii of the masses. The spring, with initial (unstretched) length $l_0$, is massless and has a spring constant $k$. The two balls have respective masses and radii $m_1$, $r_1$ and $m_2$, $r_2$. \[ m_2g=k\Big(\big(z_2(0)-z_1(0)\big)-(r_1+r_2)-l_0\Big) \] $z_1(0)=0$ due to the choice of the axis origin, we deduce $z_2(0)$: \[ z_2(0)=(r_1+r_2)+l_0+\frac{m_2g}{k} \] and the position of the system's center of mass: \[ z_G(0)=\frac{m_2}{m_1+m_2}\Big((r_1+r_2)+l_0+\frac{m_2g}{k}\Big) \] At any given time $t$, the spring length is: \[ l(t)=z_2(t)-z_1(t)-(r_1+r_2) \] and its extension (or compression): \[ \Delta l(t)=l(t)-l_0 \] The fundamental relationship of dynamics applied to each of the two balls gives: \[ m_1\ddot{z_1}=\hphantom{-}k\big((z_2-z_1)-(r_1+r_2)-l_0\big) + m_1g \] \[ m_2\ddot{z_2}=-k\big((z_2-z_1)-(r_1+r_2)-l_0\big) + m_2g \] \begin{equation} \ddot{z_1}=\hphantom{-}\frac{k}{m_1}\big((z_2-z_1)-(r_1+r_2)-l_0\big) + g \end{equation} \begin{equation} \ddot{z_2}=-\frac{k}{m_2}\big((z_2-z_1)-(r_1+r_2)-l_0\big) + g \end{equation} We choose as variables $Z=z_2-z_1$, $\ddot{Z}=\ddot{z_2}-\ddot{z_1}$. \[ \ddot{Z}=-k\Big(Z-(r_1+r_2)-l_0\Big)\Big(\frac{1}{m_1}+\frac{1}{m_2}\Big) \] By setting $\mu=\dfrac{m_1m_2}{m_1+m_2}$, the differential equation in $Z$ becomes: \[ \ddot{Z}+\frac{k}{\mu}Z=\frac{k}{\mu}\big((r_1+r_2)+l_0\big) \] $\omega_0^2=\dfrac{k}{\mu}$ \[ \ddot{Z}+\omega_0^2Z=\omega_0^2(r_1+r_2+l_0) \] Given the initial conditions: $Z(0)=z_2(0)$ and $\dot{Z}(0)=0$, the solution to this equation is: \[ Z(t)=\frac{m_2g}{k}\cos\omega_0t+r_1+r_2+l_0 \] We can deduce $z_1(t)$ and $z_2(t)$, knowing that: \[ z_G(t)=\frac{m_1z_1(t)+m_2z_2(t)}{m_1+m_2} \] therefore \[ z_1(t)=z_G(t)-\frac{m_2}{m_1+m_2}Z(t) \] Therefore: \[ z_G(t)=\frac{1}{2}gt^2+z_G(0) \] And that: \[ z_2(t)=z_1(t)+Z(t)=z_G(t)+\frac{m_1}{m_1+m_2}Z(t) \] \section{The macro \nxLcs{pstMassSpring}} The "pst-massspring" package contains only one command, \Lcs{psMassSpring}\Largs{options}, whose options and default values are as follows: \begin{enumerate}[nosep] \item \texttt{t=0}: time in seconds;; \item \texttt{m1=0.5}: mass of (1) in kg; \item \texttt{m2=2}: mass of (2) in kg; \item \texttt{k=7.5}: spring constant N/m; \item \texttt{l0=5}: initial length of the spring. \end{enumerate} The radii are calculated from the masses (we assume both are made of steel). This package was written to create animations; here are two, the first with default values. To save space the following animations are not included in this documentation. We show only the code and an image how it looks if viewd with the Adobe Acrobat pdf-viewer: \begin{codeblockA}[breakable,title=Code for two animations] \begin{tabularx}{\linewidth}{ X X } \begin{center} \psset{unit=0.75} \begin{animateinline}[controls,loop, begin={\begin{pspicture}(-3,2)(2,-27)}, end={\end{pspicture}}]{10}% 10 images/s \multiframe{200}{rt=0.00+0.02, n=0+1}{% \psset{unit=0.5} \ifnum\n < 10 \psMassSpring[t=0]% delay switch closed \else \psMassSpring[t=\rt]% \fi \psgrid[subgriddiv=0,gridcolor=orange,griddots=10,gridlabels=0pt,unit=2]% }% \end{animateinline} \end{center} & \begin{center} \psset{unit=0.75} \begin{animateinline}[controls,loop, begin={\begin{pspicture}(-3,2)(2,-27)}, end={\end{pspicture}}]{10}% 10 images/s \multiframe{200}{rt=0.00+0.02, n=0+1}{% \psset{unit=0.5} \ifnum\n < 10 \psMassSpring[t=0,m1=1,m2=1,k=10]% switch closed \else \psMassSpring[t=\rt,m1=1,m2=1,k=10]% \fi \psgrid[subgriddiv=0,gridcolor=orange,griddots=10,gridlabels=0pt,unit=2]% }% \end{animateinline} \end{center} \end{tabularx} \end{codeblockA} \begin{center} \includegraphics[width=0.75\linewidth]{images/image3} \end{center} \section{Helper macro} \begin{exampleM}{Electromagnet with switch} \begin{pspicture}(-1,-0.5)(4,2) \psElectromagnet \end{pspicture} \qquad \begin{pspicture}(-1,-0.5)(4,2) \psset{t=1}\psElectromagnet \end{pspicture} \end{exampleM} \section{Animations} It is easier to create an \Lext{gif}-Animation than a \Lext{pdf} one. The latter needs the AdobeReader to run it on screen. The \Lext{gif} file can be viewed as part of a \Lext{html} page or as a standalone image. For the \Lext{gif} file we have to create a document with single pdf pages and then convert this to \Lext{gif}. The following example creates a 310 pages document by running \Lprog{lualatex}. It is also possible with \Lprog{latex} and the \Lprog{dvips}$\rightarrow$\Lprog{ps2pdf} route, which is, of course, faster than \Lprog{lualatex}. \begin{codeblockA}[title=Creating a gif animation from single pdf's] \DocumentMetadata{} \documentclass[pstricks]{standalone} \usepackage{pst-massspring,multido} \begin{document} \multido{\i=0+1}{10}{% \begin{pspicture}(-3,2)(2,-24)% \psset{unit=0.5} \psMassSpring[t=0,m1=1,m2=1,k=10]% \psgrid[subgriddiv=0,gridcolor=orange,griddots=10,gridlabels=0pt,unit=2]% \end{pspicture}} \multido{\n=0.00+0.01}{300}{% nearly 2 periodes \begin{pspicture}(-3,2)(2,-24) \psset{unit=0.5} \psMassSpring[t=\n,m1=1,m2=1,k=10]% \psgrid[subgriddiv=0,gridcolor=orange,griddots=10,gridlabels=0pt,unit=2]% \end{pspicture}} \end{document} \end{codeblockA} The conversion to \Lext{gif} is done by the program \Lprog{magick}, formerly known as \Lprog{convert}: \begin{codeblock}[minted language=bash, title=Converting pdf to gif] magick convert -delay 5 -density 100x100 -alpha remove anim1.pdf -loop 0 anim1.gif \end{codeblock} \printbibliography \printindex \end{document}