//============================================================================= //============================================================================= // Copyright 2006 by the authors, X. Prieto-Blanco, C. Montero-Orille, // and R. de la Fuente. // All rights reserved. // No part of this ccl program script may be reproduced, transmitted, transcribed, // stored in a retrieval system, or translated into any language or computer language, // in any form or by any means, electronic, mechanical, magnetic, optical, chemical, // manual or otherwise, without the prior written permission of the authors. // Users of this ccl program script are authorized to modify this code for their // own personal use, be it to improve efficiency or to suit specific needs. // Suggestions to the author regarding changes are welcome. Send them to // famonty@usc.es //============================================================================= //============================================================================= // This routine is an implementation in OSLO of the equations presented in // ref. [1]. It provides a graphical interface to design Offner imaging // spectrometers. To use it save this file in the private/ccl folder, open // OSLO and run ccl command. To access the routine run Spectrograph_3m command. // Bibliography // ============= // [1] X. Prieto-Blanco, C. Montero-Orille, B. Couce, and R. de la Fuente, // "Analytical design of an Offner imaging spectrometer", // Optics Express, Vol. 14, 20, 9156-9168 (2006). /**************************************************************************** *****************************************************************************/ //Prototypes cmd Spectrograph_3m(); cmd Spectrograph_3m_setup(int order, double frec, double thetap3, double spectra_height, double wv_range, double wavdes); static cmd S3m_chng(int slider_id, double slider_value); /**************************************************************************** ****************************************************************************/ cmd Spectrograph_3m() { double frec, thetap3; int order; double object_height, spectra_height, fnumber, wave, wv_range, wavdes; char gaclstat; gaclstat = char_pref(graphics_autoclear); set_preference(graphics_autoclear, off); set_preference(graphics_labels, on); set_preference(graphics_axes, on); stp outp off; file_new Spectrograph3 cus 5; lid "Three Mirrors Spectrograph"; des "Monty"; uni mm; ast 3; drw 0 on; /* Surfaces 1 and 5 are dummy */ drw 1 on; drw 5 on; drw imsnbr on; drl_aperstop set off; drl_firstsrf set 0; drl_lastsrf set imsnbr; drl_raystosrf set img; drl_nbrfpts set 3; drl_nbrrays 0 set 3; drl_nbrrays 1 set 3; drl_nbrrays 2 set 3; drl_yfieldpt 1 set 1.0; drl_yfieldpt 2 set -1.0; drl_maxpup 1 set 1.0; drl_minpup 1 set -1.0; drl_maxpup 2 set 1.0; drl_minpup 2 set -1.0; /* Ray fan on x-z plane */ drl_ypupfan 0 set off; drl_ypupfan 1 set off; drl_ypupfan 2 set off; drl_hatchrefl set on; gla 2 refl_hatch; gla 3 refl_hatch; gla 4 refl_hatch; opdw set off; //opd measured in lens units for (i=2;i<7;i++) gwc i; //remove all current graphics windows graphwin_open(1); graphwin_reset(); graphwin_sliderassign(1, int, drag, "Order (1/-1)", "S3m_chng", -1, 1, Za[20] = order = 1); graphwin_sliderassign(2, real, drag, "Grating density (l/mm)", "S3m_chng", 25, 275, Za[21] = frec = 150); graphwin_sliderassign(3, real, drag, "Angle mirror 3","S3m_chng", 0, 25, Za[22] = thetap3 = 12); graphwin_sliderassign(4, real, drag, "Input f/#", "S3m_chng", 1, 5, Za[23] = fnumber = 3.5); graphwin_sliderassign(5, real, drag, "Obj. Size", "S3m_chng", 2, 10, Za[24] = object_height = 8.8); graphwin_sliderassign(6, real, drag, "Spectral Image Size", "S3m_chng", 2, 10, Za[25] = spectra_height = 6.6); graphwin_sliderassign(7, real, drag, "Central Wavelength", "S3m_chng", 0.4, 1.4, Za[26] = wave = 0.7); graphwin_sliderassign(8, real, drag, "Wavelength range", "S3m_chng", 0.2, 1, Za[27] = wv_range = 0.6); graphwin_sliderassign(9, real, drag, "Design wavelength", "S3m_chng", 0.4, 1.4, Za[28] = wavdes = 0.7); graphwin_slidershow(); wv wave; obh object_height/2; nao 1/(2*fnumber); Spectrograph_3m_setup(order,frec,thetap3,spectra_height,wv_range,wavdes); ray_aiming_mode set crr; draw_lens x; draw_default_rays(); graphwin_open(2); gclear(); sdsa on; gwe "rptg_spots"; graphwin_open(3); gclear(); gwe "rpt_ric ray 0 0 0 0 0 0 0 0:rpt_ric"; if (gaclstat) set_preference(graphics_autoclear, on); stp outp on; } /******************************************************************************/ cmd Spectrograph_3m_setup(int order, double frec, double thetap3, double spectra_height, double wv_range, double wavdes) { double r1val, r2val, r3val; // Curvature radius (>0) to be calculated double thetap1, theta2, thetap2, tp3, tilt1, tilt2; // Angles in radians double tt2; tp3 = thetap3*pi/180; // thetap3 in radians /* Five iterations should be enough in most cases */ for(tt2=0,i=0;i<5;i++) tt2=pow(sin(tp3),2)*tan(tp3)-tan(tp3)*cos(2*tp3)*pow(tt2,2)-0.5*(1+pow(sin(tp3),2))*pow(tt2,3); tilt2 = atan (tt2); thetap2 = tilt2-2*tp3; r2val = 1e3*spectra_height/(wv_range*frec); // in mm r3val = -r2val*sin(thetap2)/sin(tp3); theta2 = -asin(order*wavdes*frec*1e-3+sin(thetap2)); tilt1 = -atan(sin(thetap2)/sin(theta2)*tan(tilt2)); thetap1 = (theta2-tilt1)/2; r1val = r2val*sin(theta2)/sin(thetap1); /* Surfaces 1 and 5 are dummy */ th 0 r2val; th 1 (r1val-r2val); pk 2 thm 1 0.0; th 3 (r3val-r2val); pk 4 thm 3 0.0; th 5 -r2val; rd 2 -r1val; rd 3 -r2val; rd 4 -r3val; dcx 0 r1val*sin(thetap1)*cos(tilt1); dcz 0 -r1val*sin(thetap1)*sin(tilt1); dcx imsnbr -r3val*sin(tp3)*cos(tilt2); dcz imsnbr r3val*sin(tp3)*sin(tilt2); tlb imsnbr (atan(0.5*sin(2*tilt2))-tilt2)*180/pi; tlc 3 90; rco 3 3; gor 3 order; gsp 3 1/frec; ap 2 r1val*(sin(thetap1)+nao); ap 4 r3val*(sin(tp3)+nao); } //=========================================================================== static cmd S3m_chng(int slider_id, double slider_value) { int order; double frec, thetap3; double object_height, spectra_height, fnumber, wave, wv_range, wavdes; double maxspotrad, PKVALopd, RMSopd, strehl; char gaclstat; gaclstat = char_pref(graphics_autoclear); set_preference(graphics_autoclear, off); set_preference(output_text, off); stp noeb on; order = Za[20]; frec = Za[21]; thetap3 = Za[22]; fnumber = Za[23]; object_height = Za[24]; spectra_height = Za[25]; wave = Za[26]; wv_range = Za[27]; wavdes = Za[28]; if (slider_id == 1) Za[20] = order = slider_value; else if (slider_id == 2) Za[21] = frec = slider_value; else if (slider_id == 3) Za[22] = thetap3 = slider_value; else if (slider_id == 4) Za[23] = fnumber = slider_value; else if (slider_id == 5) Za[24] = object_height = slider_value; else if (slider_id == 6) Za[25] = spectra_height = slider_value; else if (slider_id == 7) Za[26] = wave = slider_value; else if (slider_id == 8) Za[27] = wv_range = slider_value; else if (slider_id == 9) Za[28] = wavdes = slider_value; graphwin_open(1); gclear(); wv wave; obh object_height/2; nao 1/(2*fnumber); Spectrograph_3m_setup(order,frec,thetap3,spectra_height,wv_range,wavdes); ray_aiming_mode set crr; autofocus; th imsnbr 0.0; // Refresh spreadsheet data without // changing the image plane position // From OSLO version 6.3.2 you can replace this // line with update_surface_spreadheet (uss) command maxspotrad = 0.0; PKVALopd = 0.0; RMSopd = 0.0; strehl = 1.0; /* Calculation of max spot_radius, max PKVAL, max RMS and min strehl for */ /* band-edge and central wavelengths, and for three field points */ for(i=1;i>-2;i--) { wv wave+i*order*wv_range/2; for(j=0;j<2;j++) { sop j 0; twr; sps none 0.0; wvf; if(c1>maxspotrad) maxspotrad=c1; if(a2>PKVALopd) PKVALopd = a2; if(b2>RMSopd) RMSopd = b2; if(c2