FresnelZonePlate.frink

View or download FresnelZonePlate.frink in plain text format


// Uses Frink's ability to render accurately-sized graphics to draw Fresnel
// zone plates.  You can print these out accurately on a laser printer with
// transparencies.  A Fresnel Zone plate is almost like a printable lens.
// it takes advantage of quantum diffraction of light to focus light onto
// a target. They are freaking awesome.
//
// The main limitation of creating your own zone plates is that you have to
// be able to print at very high resolution to be able to focus visible light
// with a short focal length.
//
// http://zoneplate.lbl.gov/theory
// http://en.wikipedia.org/wiki/Zone_plate

// Draw a (printable, exactly-scaled) zone plate.
//   * f is the focal length,
//   * lambda is the target wavelength of light you want to focus
//   * phase is 0 or 1.  If phase=0, the center will be clear.  If phase=1,
//     the center will be dark.  Surprisingly, both will focus the light at
//     the geometric center of the target, even if the center is geometrically
//     in shadow!
//   * r is the radius of the zone plate to be drawn.
//   * res is the limiting resolution of your printer.  (This is at best half
//     the actual resolution of your printer.)  This affects the "max effective
//     zones" that your printer can meaningfully render.
drawZonePlate[f=27 feet, lambda=700 nm, phase=0, r=3 in, res=600/in] :=
{
   g = new graphics

   // maxn is the number of zones that will be drawn
   maxn = floor[-2 f lambda^-1 + 2 lambda^-2 (f^2 lambda^2 + lambda^2 r^2)^(1/2)]
   if (maxn > 10000)
      maxn=10000

   // maxr is the radius that will actually be drawn
   maxr = sqrt[maxn lambda f + maxn^2 lambda^2 / 4]
   n = maxn
   while n > 0
   {
      r = sqrt[n lambda f + n^2 lambda^2 / 4]
      c = (n+phase) mod 2 
      g.color[c,c,c]
      g.fillEllipseCenter[0 in, 0 in, 2 r, 2r]
      n = n - 1
   }

   // maxEffectiveN is the maximum number of zones that can be meaningfully
   // rendered (due to your printer's resolution limits)
   maxEffectiveN = floor[(lambda (4 f + lambda) res^2 (4 - lambda^2 res^2) - 2 sqrt[(lambda^2 res^2 (-2 + lambda res) (2 + lambda res)(-4 + (-16 f^2 + lambda^2) res^2))]) / (2 lambda^2 res^2 (-4 + lambda^2 res^2))]

   // maxEffectiveR is the maximum radius of the zone plate that will be
   // meaningfully rendered (due to your printer's resolution limits)
   maxEffectiveR = sqrt[maxEffectiveN lambda f + maxEffectiveN^2 lambda^2 / 4]

   // maxEffectiveArea is the maximum area of the zone plate that will be
   // meaningfully rendered (due to your printer's resolution limits)
   maxEffectiveArea = pi maxEffectiveR^2

   maxPower = maxEffectiveArea * 500 W/m^2
   
   str = ""
   g.color[0,0,0]
   g.font["SansSerif", .5 cm]
   str = str + "wavelength =" + format[lambda, "nm", 2] + "\n"
   str = str + "focal length =" + format[f, "m", 3] + "\n"
   str = str + "$maxn zones drawn" + "\n"
   str = str + "diameter =" + format[2 maxr,"in",3] + "\n"
   str = str + "Max effective zones=$maxEffectiveN\n" 
   str = str + "Max effective diameter=" + format[2 maxEffectiveR, "cm", 4]  + "\n"
   str = str + "Max effective area=" + format[maxEffectiveArea, "m^2", 6] + "\n"
   str = str + "Max power=" + format[maxPower, "W", 3]

   g.text[str, 0 cm, maxr, "center", "top"]
   
   g.write["zoneplate.svg", 1200, 1200]
   g.show[]
}


// Alter this line to match the focal length and wavelength you desire.
drawZonePlate[50 feet, 700. nm, 0, 3.5 in, 600/in]



View or download FresnelZonePlate.frink in plain text format


This is a program written in the programming language Frink.
For more information, view the Frink Documentation or see More Sample Frink Programs.

Alan Eliasen was born 17649 days, 5 hours, 41 minutes ago.