gaussopt.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. """
  2. Gaussian optics.
  3. The module implements:
  4. - Ray transfer matrices for geometrical and gaussian optics.
  5. See RayTransferMatrix, GeometricRay and BeamParameter
  6. - Conjugation relations for geometrical and gaussian optics.
  7. See geometric_conj*, gauss_conj and conjugate_gauss_beams
  8. The conventions for the distances are as follows:
  9. focal distance
  10. positive for convergent lenses
  11. object distance
  12. positive for real objects
  13. image distance
  14. positive for real images
  15. """
  16. __all__ = [
  17. 'RayTransferMatrix',
  18. 'FreeSpace',
  19. 'FlatRefraction',
  20. 'CurvedRefraction',
  21. 'FlatMirror',
  22. 'CurvedMirror',
  23. 'ThinLens',
  24. 'GeometricRay',
  25. 'BeamParameter',
  26. 'waist2rayleigh',
  27. 'rayleigh2waist',
  28. 'geometric_conj_ab',
  29. 'geometric_conj_af',
  30. 'geometric_conj_bf',
  31. 'gaussian_conj',
  32. 'conjugate_gauss_beams',
  33. ]
  34. from sympy.core.expr import Expr
  35. from sympy.core.numbers import (I, pi)
  36. from sympy.core.sympify import sympify
  37. from sympy.functions.elementary.complexes import (im, re)
  38. from sympy.functions.elementary.miscellaneous import sqrt
  39. from sympy.functions.elementary.trigonometric import atan2
  40. from sympy.matrices.dense import Matrix, MutableDenseMatrix
  41. from sympy.polys.rationaltools import together
  42. from sympy.utilities.misc import filldedent
  43. ###
  44. # A, B, C, D matrices
  45. ###
  46. class RayTransferMatrix(MutableDenseMatrix):
  47. """
  48. Base class for a Ray Transfer Matrix.
  49. It should be used if there isn't already a more specific subclass mentioned
  50. in See Also.
  51. Parameters
  52. ==========
  53. parameters :
  54. A, B, C and D or 2x2 matrix (Matrix(2, 2, [A, B, C, D]))
  55. Examples
  56. ========
  57. >>> from sympy.physics.optics import RayTransferMatrix, ThinLens
  58. >>> from sympy import Symbol, Matrix
  59. >>> mat = RayTransferMatrix(1, 2, 3, 4)
  60. >>> mat
  61. Matrix([
  62. [1, 2],
  63. [3, 4]])
  64. >>> RayTransferMatrix(Matrix([[1, 2], [3, 4]]))
  65. Matrix([
  66. [1, 2],
  67. [3, 4]])
  68. >>> mat.A
  69. 1
  70. >>> f = Symbol('f')
  71. >>> lens = ThinLens(f)
  72. >>> lens
  73. Matrix([
  74. [ 1, 0],
  75. [-1/f, 1]])
  76. >>> lens.C
  77. -1/f
  78. See Also
  79. ========
  80. GeometricRay, BeamParameter,
  81. FreeSpace, FlatRefraction, CurvedRefraction,
  82. FlatMirror, CurvedMirror, ThinLens
  83. References
  84. ==========
  85. .. [1] https://en.wikipedia.org/wiki/Ray_transfer_matrix_analysis
  86. """
  87. def __new__(cls, *args):
  88. if len(args) == 4:
  89. temp = ((args[0], args[1]), (args[2], args[3]))
  90. elif len(args) == 1 \
  91. and isinstance(args[0], Matrix) \
  92. and args[0].shape == (2, 2):
  93. temp = args[0]
  94. else:
  95. raise ValueError(filldedent('''
  96. Expecting 2x2 Matrix or the 4 elements of
  97. the Matrix but got %s''' % str(args)))
  98. return Matrix.__new__(cls, temp)
  99. def __mul__(self, other):
  100. if isinstance(other, RayTransferMatrix):
  101. return RayTransferMatrix(Matrix.__mul__(self, other))
  102. elif isinstance(other, GeometricRay):
  103. return GeometricRay(Matrix.__mul__(self, other))
  104. elif isinstance(other, BeamParameter):
  105. temp = self*Matrix(((other.q,), (1,)))
  106. q = (temp[0]/temp[1]).expand(complex=True)
  107. return BeamParameter(other.wavelen,
  108. together(re(q)),
  109. z_r=together(im(q)))
  110. else:
  111. return Matrix.__mul__(self, other)
  112. @property
  113. def A(self):
  114. """
  115. The A parameter of the Matrix.
  116. Examples
  117. ========
  118. >>> from sympy.physics.optics import RayTransferMatrix
  119. >>> mat = RayTransferMatrix(1, 2, 3, 4)
  120. >>> mat.A
  121. 1
  122. """
  123. return self[0, 0]
  124. @property
  125. def B(self):
  126. """
  127. The B parameter of the Matrix.
  128. Examples
  129. ========
  130. >>> from sympy.physics.optics import RayTransferMatrix
  131. >>> mat = RayTransferMatrix(1, 2, 3, 4)
  132. >>> mat.B
  133. 2
  134. """
  135. return self[0, 1]
  136. @property
  137. def C(self):
  138. """
  139. The C parameter of the Matrix.
  140. Examples
  141. ========
  142. >>> from sympy.physics.optics import RayTransferMatrix
  143. >>> mat = RayTransferMatrix(1, 2, 3, 4)
  144. >>> mat.C
  145. 3
  146. """
  147. return self[1, 0]
  148. @property
  149. def D(self):
  150. """
  151. The D parameter of the Matrix.
  152. Examples
  153. ========
  154. >>> from sympy.physics.optics import RayTransferMatrix
  155. >>> mat = RayTransferMatrix(1, 2, 3, 4)
  156. >>> mat.D
  157. 4
  158. """
  159. return self[1, 1]
  160. class FreeSpace(RayTransferMatrix):
  161. """
  162. Ray Transfer Matrix for free space.
  163. Parameters
  164. ==========
  165. distance
  166. See Also
  167. ========
  168. RayTransferMatrix
  169. Examples
  170. ========
  171. >>> from sympy.physics.optics import FreeSpace
  172. >>> from sympy import symbols
  173. >>> d = symbols('d')
  174. >>> FreeSpace(d)
  175. Matrix([
  176. [1, d],
  177. [0, 1]])
  178. """
  179. def __new__(cls, d):
  180. return RayTransferMatrix.__new__(cls, 1, d, 0, 1)
  181. class FlatRefraction(RayTransferMatrix):
  182. """
  183. Ray Transfer Matrix for refraction.
  184. Parameters
  185. ==========
  186. n1 :
  187. Refractive index of one medium.
  188. n2 :
  189. Refractive index of other medium.
  190. See Also
  191. ========
  192. RayTransferMatrix
  193. Examples
  194. ========
  195. >>> from sympy.physics.optics import FlatRefraction
  196. >>> from sympy import symbols
  197. >>> n1, n2 = symbols('n1 n2')
  198. >>> FlatRefraction(n1, n2)
  199. Matrix([
  200. [1, 0],
  201. [0, n1/n2]])
  202. """
  203. def __new__(cls, n1, n2):
  204. n1, n2 = map(sympify, (n1, n2))
  205. return RayTransferMatrix.__new__(cls, 1, 0, 0, n1/n2)
  206. class CurvedRefraction(RayTransferMatrix):
  207. """
  208. Ray Transfer Matrix for refraction on curved interface.
  209. Parameters
  210. ==========
  211. R :
  212. Radius of curvature (positive for concave).
  213. n1 :
  214. Refractive index of one medium.
  215. n2 :
  216. Refractive index of other medium.
  217. See Also
  218. ========
  219. RayTransferMatrix
  220. Examples
  221. ========
  222. >>> from sympy.physics.optics import CurvedRefraction
  223. >>> from sympy import symbols
  224. >>> R, n1, n2 = symbols('R n1 n2')
  225. >>> CurvedRefraction(R, n1, n2)
  226. Matrix([
  227. [ 1, 0],
  228. [(n1 - n2)/(R*n2), n1/n2]])
  229. """
  230. def __new__(cls, R, n1, n2):
  231. R, n1, n2 = map(sympify, (R, n1, n2))
  232. return RayTransferMatrix.__new__(cls, 1, 0, (n1 - n2)/R/n2, n1/n2)
  233. class FlatMirror(RayTransferMatrix):
  234. """
  235. Ray Transfer Matrix for reflection.
  236. See Also
  237. ========
  238. RayTransferMatrix
  239. Examples
  240. ========
  241. >>> from sympy.physics.optics import FlatMirror
  242. >>> FlatMirror()
  243. Matrix([
  244. [1, 0],
  245. [0, 1]])
  246. """
  247. def __new__(cls):
  248. return RayTransferMatrix.__new__(cls, 1, 0, 0, 1)
  249. class CurvedMirror(RayTransferMatrix):
  250. """
  251. Ray Transfer Matrix for reflection from curved surface.
  252. Parameters
  253. ==========
  254. R : radius of curvature (positive for concave)
  255. See Also
  256. ========
  257. RayTransferMatrix
  258. Examples
  259. ========
  260. >>> from sympy.physics.optics import CurvedMirror
  261. >>> from sympy import symbols
  262. >>> R = symbols('R')
  263. >>> CurvedMirror(R)
  264. Matrix([
  265. [ 1, 0],
  266. [-2/R, 1]])
  267. """
  268. def __new__(cls, R):
  269. R = sympify(R)
  270. return RayTransferMatrix.__new__(cls, 1, 0, -2/R, 1)
  271. class ThinLens(RayTransferMatrix):
  272. """
  273. Ray Transfer Matrix for a thin lens.
  274. Parameters
  275. ==========
  276. f :
  277. The focal distance.
  278. See Also
  279. ========
  280. RayTransferMatrix
  281. Examples
  282. ========
  283. >>> from sympy.physics.optics import ThinLens
  284. >>> from sympy import symbols
  285. >>> f = symbols('f')
  286. >>> ThinLens(f)
  287. Matrix([
  288. [ 1, 0],
  289. [-1/f, 1]])
  290. """
  291. def __new__(cls, f):
  292. f = sympify(f)
  293. return RayTransferMatrix.__new__(cls, 1, 0, -1/f, 1)
  294. ###
  295. # Representation for geometric ray
  296. ###
  297. class GeometricRay(MutableDenseMatrix):
  298. """
  299. Representation for a geometric ray in the Ray Transfer Matrix formalism.
  300. Parameters
  301. ==========
  302. h : height, and
  303. angle : angle, or
  304. matrix : a 2x1 matrix (Matrix(2, 1, [height, angle]))
  305. Examples
  306. ========
  307. >>> from sympy.physics.optics import GeometricRay, FreeSpace
  308. >>> from sympy import symbols, Matrix
  309. >>> d, h, angle = symbols('d, h, angle')
  310. >>> GeometricRay(h, angle)
  311. Matrix([
  312. [ h],
  313. [angle]])
  314. >>> FreeSpace(d)*GeometricRay(h, angle)
  315. Matrix([
  316. [angle*d + h],
  317. [ angle]])
  318. >>> GeometricRay( Matrix( ((h,), (angle,)) ) )
  319. Matrix([
  320. [ h],
  321. [angle]])
  322. See Also
  323. ========
  324. RayTransferMatrix
  325. """
  326. def __new__(cls, *args):
  327. if len(args) == 1 and isinstance(args[0], Matrix) \
  328. and args[0].shape == (2, 1):
  329. temp = args[0]
  330. elif len(args) == 2:
  331. temp = ((args[0],), (args[1],))
  332. else:
  333. raise ValueError(filldedent('''
  334. Expecting 2x1 Matrix or the 2 elements of
  335. the Matrix but got %s''' % str(args)))
  336. return Matrix.__new__(cls, temp)
  337. @property
  338. def height(self):
  339. """
  340. The distance from the optical axis.
  341. Examples
  342. ========
  343. >>> from sympy.physics.optics import GeometricRay
  344. >>> from sympy import symbols
  345. >>> h, angle = symbols('h, angle')
  346. >>> gRay = GeometricRay(h, angle)
  347. >>> gRay.height
  348. h
  349. """
  350. return self[0]
  351. @property
  352. def angle(self):
  353. """
  354. The angle with the optical axis.
  355. Examples
  356. ========
  357. >>> from sympy.physics.optics import GeometricRay
  358. >>> from sympy import symbols
  359. >>> h, angle = symbols('h, angle')
  360. >>> gRay = GeometricRay(h, angle)
  361. >>> gRay.angle
  362. angle
  363. """
  364. return self[1]
  365. ###
  366. # Representation for gauss beam
  367. ###
  368. class BeamParameter(Expr):
  369. """
  370. Representation for a gaussian ray in the Ray Transfer Matrix formalism.
  371. Parameters
  372. ==========
  373. wavelen : the wavelength,
  374. z : the distance to waist, and
  375. w : the waist, or
  376. z_r : the rayleigh range.
  377. Examples
  378. ========
  379. >>> from sympy.physics.optics import BeamParameter
  380. >>> p = BeamParameter(530e-9, 1, w=1e-3)
  381. >>> p.q
  382. 1 + 1.88679245283019*I*pi
  383. >>> p.q.n()
  384. 1.0 + 5.92753330865999*I
  385. >>> p.w_0.n()
  386. 0.00100000000000000
  387. >>> p.z_r.n()
  388. 5.92753330865999
  389. >>> from sympy.physics.optics import FreeSpace
  390. >>> fs = FreeSpace(10)
  391. >>> p1 = fs*p
  392. >>> p.w.n()
  393. 0.00101413072159615
  394. >>> p1.w.n()
  395. 0.00210803120913829
  396. See Also
  397. ========
  398. RayTransferMatrix
  399. References
  400. ==========
  401. .. [1] https://en.wikipedia.org/wiki/Complex_beam_parameter
  402. .. [2] https://en.wikipedia.org/wiki/Gaussian_beam
  403. """
  404. #TODO A class Complex may be implemented. The BeamParameter may
  405. # subclass it. See:
  406. # https://groups.google.com/d/topic/sympy/7XkU07NRBEs/discussion
  407. def __new__(cls, wavelen, z, z_r=None, w=None):
  408. wavelen = sympify(wavelen)
  409. z = sympify(z)
  410. if z_r is not None and w is None:
  411. z_r = sympify(z_r)
  412. elif w is not None and z_r is None:
  413. z_r = waist2rayleigh(sympify(w), wavelen)
  414. else:
  415. raise ValueError('Constructor expects exactly one named argument.')
  416. return Expr.__new__(cls, wavelen, z, z_r)
  417. @property
  418. def wavelen(self):
  419. return self.args[0]
  420. @property
  421. def z(self):
  422. return self.args[1]
  423. @property
  424. def z_r(self):
  425. return self.args[2]
  426. @property
  427. def q(self):
  428. """
  429. The complex parameter representing the beam.
  430. Examples
  431. ========
  432. >>> from sympy.physics.optics import BeamParameter
  433. >>> p = BeamParameter(530e-9, 1, w=1e-3)
  434. >>> p.q
  435. 1 + 1.88679245283019*I*pi
  436. """
  437. return self.z + I*self.z_r
  438. @property
  439. def radius(self):
  440. """
  441. The radius of curvature of the phase front.
  442. Examples
  443. ========
  444. >>> from sympy.physics.optics import BeamParameter
  445. >>> p = BeamParameter(530e-9, 1, w=1e-3)
  446. >>> p.radius
  447. 1 + 3.55998576005696*pi**2
  448. """
  449. return self.z*(1 + (self.z_r/self.z)**2)
  450. @property
  451. def w(self):
  452. """
  453. The beam radius at `1/e^2` intensity.
  454. See Also
  455. ========
  456. w_0 :
  457. The minimal radius of beam.
  458. Examples
  459. ========
  460. >>> from sympy.physics.optics import BeamParameter
  461. >>> p = BeamParameter(530e-9, 1, w=1e-3)
  462. >>> p.w
  463. 0.001*sqrt(0.2809/pi**2 + 1)
  464. """
  465. return self.w_0*sqrt(1 + (self.z/self.z_r)**2)
  466. @property
  467. def w_0(self):
  468. """
  469. The beam waist (minimal radius).
  470. See Also
  471. ========
  472. w : the beam radius at `1/e^2` intensity
  473. Examples
  474. ========
  475. >>> from sympy.physics.optics import BeamParameter
  476. >>> p = BeamParameter(530e-9, 1, w=1e-3)
  477. >>> p.w_0
  478. 0.00100000000000000
  479. """
  480. return sqrt(self.z_r/pi*self.wavelen)
  481. @property
  482. def divergence(self):
  483. """
  484. Half of the total angular spread.
  485. Examples
  486. ========
  487. >>> from sympy.physics.optics import BeamParameter
  488. >>> p = BeamParameter(530e-9, 1, w=1e-3)
  489. >>> p.divergence
  490. 0.00053/pi
  491. """
  492. return self.wavelen/pi/self.w_0
  493. @property
  494. def gouy(self):
  495. """
  496. The Gouy phase.
  497. Examples
  498. ========
  499. >>> from sympy.physics.optics import BeamParameter
  500. >>> p = BeamParameter(530e-9, 1, w=1e-3)
  501. >>> p.gouy
  502. atan(0.53/pi)
  503. """
  504. return atan2(self.z, self.z_r)
  505. @property
  506. def waist_approximation_limit(self):
  507. """
  508. The minimal waist for which the gauss beam approximation is valid.
  509. Explanation
  510. ===========
  511. The gauss beam is a solution to the paraxial equation. For curvatures
  512. that are too great it is not a valid approximation.
  513. Examples
  514. ========
  515. >>> from sympy.physics.optics import BeamParameter
  516. >>> p = BeamParameter(530e-9, 1, w=1e-3)
  517. >>> p.waist_approximation_limit
  518. 1.06e-6/pi
  519. """
  520. return 2*self.wavelen/pi
  521. ###
  522. # Utilities
  523. ###
  524. def waist2rayleigh(w, wavelen):
  525. """
  526. Calculate the rayleigh range from the waist of a gaussian beam.
  527. See Also
  528. ========
  529. rayleigh2waist, BeamParameter
  530. Examples
  531. ========
  532. >>> from sympy.physics.optics import waist2rayleigh
  533. >>> from sympy import symbols
  534. >>> w, wavelen = symbols('w wavelen')
  535. >>> waist2rayleigh(w, wavelen)
  536. pi*w**2/wavelen
  537. """
  538. w, wavelen = map(sympify, (w, wavelen))
  539. return w**2*pi/wavelen
  540. def rayleigh2waist(z_r, wavelen):
  541. """Calculate the waist from the rayleigh range of a gaussian beam.
  542. See Also
  543. ========
  544. waist2rayleigh, BeamParameter
  545. Examples
  546. ========
  547. >>> from sympy.physics.optics import rayleigh2waist
  548. >>> from sympy import symbols
  549. >>> z_r, wavelen = symbols('z_r wavelen')
  550. >>> rayleigh2waist(z_r, wavelen)
  551. sqrt(wavelen*z_r)/sqrt(pi)
  552. """
  553. z_r, wavelen = map(sympify, (z_r, wavelen))
  554. return sqrt(z_r/pi*wavelen)
  555. def geometric_conj_ab(a, b):
  556. """
  557. Conjugation relation for geometrical beams under paraxial conditions.
  558. Explanation
  559. ===========
  560. Takes the distances to the optical element and returns the needed
  561. focal distance.
  562. See Also
  563. ========
  564. geometric_conj_af, geometric_conj_bf
  565. Examples
  566. ========
  567. >>> from sympy.physics.optics import geometric_conj_ab
  568. >>> from sympy import symbols
  569. >>> a, b = symbols('a b')
  570. >>> geometric_conj_ab(a, b)
  571. a*b/(a + b)
  572. """
  573. a, b = map(sympify, (a, b))
  574. if a.is_infinite or b.is_infinite:
  575. return a if b.is_infinite else b
  576. else:
  577. return a*b/(a + b)
  578. def geometric_conj_af(a, f):
  579. """
  580. Conjugation relation for geometrical beams under paraxial conditions.
  581. Explanation
  582. ===========
  583. Takes the object distance (for geometric_conj_af) or the image distance
  584. (for geometric_conj_bf) to the optical element and the focal distance.
  585. Then it returns the other distance needed for conjugation.
  586. See Also
  587. ========
  588. geometric_conj_ab
  589. Examples
  590. ========
  591. >>> from sympy.physics.optics.gaussopt import geometric_conj_af, geometric_conj_bf
  592. >>> from sympy import symbols
  593. >>> a, b, f = symbols('a b f')
  594. >>> geometric_conj_af(a, f)
  595. a*f/(a - f)
  596. >>> geometric_conj_bf(b, f)
  597. b*f/(b - f)
  598. """
  599. a, f = map(sympify, (a, f))
  600. return -geometric_conj_ab(a, -f)
  601. geometric_conj_bf = geometric_conj_af
  602. def gaussian_conj(s_in, z_r_in, f):
  603. """
  604. Conjugation relation for gaussian beams.
  605. Parameters
  606. ==========
  607. s_in :
  608. The distance to optical element from the waist.
  609. z_r_in :
  610. The rayleigh range of the incident beam.
  611. f :
  612. The focal length of the optical element.
  613. Returns
  614. =======
  615. a tuple containing (s_out, z_r_out, m)
  616. s_out :
  617. The distance between the new waist and the optical element.
  618. z_r_out :
  619. The rayleigh range of the emergent beam.
  620. m :
  621. The ration between the new and the old waists.
  622. Examples
  623. ========
  624. >>> from sympy.physics.optics import gaussian_conj
  625. >>> from sympy import symbols
  626. >>> s_in, z_r_in, f = symbols('s_in z_r_in f')
  627. >>> gaussian_conj(s_in, z_r_in, f)[0]
  628. 1/(-1/(s_in + z_r_in**2/(-f + s_in)) + 1/f)
  629. >>> gaussian_conj(s_in, z_r_in, f)[1]
  630. z_r_in/(1 - s_in**2/f**2 + z_r_in**2/f**2)
  631. >>> gaussian_conj(s_in, z_r_in, f)[2]
  632. 1/sqrt(1 - s_in**2/f**2 + z_r_in**2/f**2)
  633. """
  634. s_in, z_r_in, f = map(sympify, (s_in, z_r_in, f))
  635. s_out = 1 / ( -1/(s_in + z_r_in**2/(s_in - f)) + 1/f )
  636. m = 1/sqrt((1 - (s_in/f)**2) + (z_r_in/f)**2)
  637. z_r_out = z_r_in / ((1 - (s_in/f)**2) + (z_r_in/f)**2)
  638. return (s_out, z_r_out, m)
  639. def conjugate_gauss_beams(wavelen, waist_in, waist_out, **kwargs):
  640. """
  641. Find the optical setup conjugating the object/image waists.
  642. Parameters
  643. ==========
  644. wavelen :
  645. The wavelength of the beam.
  646. waist_in and waist_out :
  647. The waists to be conjugated.
  648. f :
  649. The focal distance of the element used in the conjugation.
  650. Returns
  651. =======
  652. a tuple containing (s_in, s_out, f)
  653. s_in :
  654. The distance before the optical element.
  655. s_out :
  656. The distance after the optical element.
  657. f :
  658. The focal distance of the optical element.
  659. Examples
  660. ========
  661. >>> from sympy.physics.optics import conjugate_gauss_beams
  662. >>> from sympy import symbols, factor
  663. >>> l, w_i, w_o, f = symbols('l w_i w_o f')
  664. >>> conjugate_gauss_beams(l, w_i, w_o, f=f)[0]
  665. f*(1 - sqrt(w_i**2/w_o**2 - pi**2*w_i**4/(f**2*l**2)))
  666. >>> factor(conjugate_gauss_beams(l, w_i, w_o, f=f)[1])
  667. f*w_o**2*(w_i**2/w_o**2 - sqrt(w_i**2/w_o**2 -
  668. pi**2*w_i**4/(f**2*l**2)))/w_i**2
  669. >>> conjugate_gauss_beams(l, w_i, w_o, f=f)[2]
  670. f
  671. """
  672. #TODO add the other possible arguments
  673. wavelen, waist_in, waist_out = map(sympify, (wavelen, waist_in, waist_out))
  674. m = waist_out / waist_in
  675. z = waist2rayleigh(waist_in, wavelen)
  676. if len(kwargs) != 1:
  677. raise ValueError("The function expects only one named argument")
  678. elif 'dist' in kwargs:
  679. raise NotImplementedError(filldedent('''
  680. Currently only focal length is supported as a parameter'''))
  681. elif 'f' in kwargs:
  682. f = sympify(kwargs['f'])
  683. s_in = f * (1 - sqrt(1/m**2 - z**2/f**2))
  684. s_out = gaussian_conj(s_in, z, f)[0]
  685. elif 's_in' in kwargs:
  686. raise NotImplementedError(filldedent('''
  687. Currently only focal length is supported as a parameter'''))
  688. else:
  689. raise ValueError(filldedent('''
  690. The functions expects the focal length as a named argument'''))
  691. return (s_in, s_out, f)
  692. #TODO
  693. #def plot_beam():
  694. # """Plot the beam radius as it propagates in space."""
  695. # pass
  696. #TODO
  697. #def plot_beam_conjugation():
  698. # """
  699. # Plot the intersection of two beams.
  700. #
  701. # Represents the conjugation relation.
  702. #
  703. # See Also
  704. # ========
  705. #
  706. # conjugate_gauss_beams
  707. # """
  708. # pass