BLEngeFunction.hh

Go to the documentation of this file.
00001 //      BLEngeFunction.hh
00002 /*
00003 This source file is part of G4beamline, http://g4beamline.muonsinc.com
00004 Copyright (C) 2003,2004,2005,2006 by Tom Roberts, all rights reserved.
00005 
00006 This program is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU General Public License
00008 as published by the Free Software Foundation; either version 2
00009 of the License, or (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 http://www.gnu.org/copyleft/gpl.html
00017 */
00018 
00019 #ifndef BLENGEFUNCTION_HH
00020 #define BLENGEFUNCTION_HH
00021 
00022 #include <math.h>
00023 
00024 /**     enum BLEngeType specifies the default parameters of BLEngeFunction.
00025  **/
00026 enum BLEngeType { ENGE_BLOCK, ENGE_BEND, ENGE_QUAD, ENGE_OTHER };
00027 
00028 /**     class EngeFunction implements the Enge function for fringe fields.
00029  *
00030  *      z is the distance from the nominal edge, with z=0 being the edge.
00031  *      it should be divided by the aperture diameter or full width/height.
00032  *      z<0 is inside, z>0 is outside.
00033  *
00034  *      See the COSY reference manual (pp 32-35) for suggested values of
00035  *      a1-a6, or use the ENGE_BEND or ENGE_QUAD types (which come from there).
00036  *      http://cosy.pa.msu.edu/cosymanu/index.html
00037  *
00038  *      Mathematica was used to compute the derivatives.
00039  **/
00040 class BLEngeFunction {
00041         BLEngeType type;
00042         double a1,a2,a3,a4,a5,a6;
00043 public:
00044         /// default constructor.
00045         BLEngeFunction() { type=ENGE_BLOCK; set(0,0,0,0,0,0); }
00046         /// constructor for common magnet types.
00047         BLEngeFunction(BLEngeType t) {
00048                 switch(t) {
00049                 case ENGE_BLOCK:
00050                 case ENGE_OTHER:
00051                   set(0,0,0,0,0,0);
00052                   break;
00053                 case ENGE_BEND:
00054                   set(0.478959,1.911289,-1.185953,1.630554,-1.082657,0.318111);
00055                   break;
00056                 case ENGE_QUAD:
00057                   set(0.296471,4.533219,-2.270982,1.068627,-0.036391,0.022261);
00058                   break;
00059                 }
00060                 type = t;
00061         }
00062         /// general constructor.
00063         BLEngeFunction(double _a1, double _a2, double _a3, double _a4,
00064                                                 double _a5, double _a6) {
00065                 set(_a1,_a2,_a3,_a4,_a5,_a6);
00066         }
00067         /// set the parameters.
00068         void set(double _a1, double _a2, double _a3, double _a4,
00069                                                 double _a5, double _a6) {
00070                 a1=_a1; a2=_a2; a3=_a3; a4=_a4; a5=_a5; a6=_a6;
00071                 if(a1==0.0 && a2==0.0 && a3==0.0 && a4==0.0 && a5==0.0 && 
00072                                                                 a6==0.0)
00073                         type = ENGE_BLOCK;
00074                 else
00075                         type = ENGE_OTHER;
00076         }
00077         /// evaluate the Enge function at z.
00078         double operator()(double z) const {
00079                 if(type == ENGE_BLOCK) return (z<=0.0 ? 1.0 : 0.0);
00080                 if(z < -4.0) return 1.0;
00081                 if(z > 4.0) return 0.0;
00082                 return 1.0/(1.0+exp(a1+z*(a2+z*(a3+z*(a4+z*(a5+z*a6))))));
00083         }
00084         /// evaluate the derivative of the Enge function at z.
00085         double prime(double z) const {
00086                 if(type == ENGE_BLOCK) return 0.0;
00087                 if(fabs(z) > 4.0) return 0.0;
00088                 double exp1 = exp(a1+z*(a2+z*(a3+z*(a4+z*(a5+z*a6)))));
00089                 return -exp1/(1.0+exp1)/(1.0+exp1)*
00090                         (a2+z*(2.0*a3+z*(3.0*a4+z*(4.0*a5+z*5.0*a6))));
00091         }
00092         double first(double z) { return prime(z); }
00093         /// evaluate the second derivative of the Enge function at z.
00094         double second(double z) const {
00095                 if(type == ENGE_BLOCK) return 0.0;
00096                 if(fabs(z) > 4.0) return 0.0;
00097                 double f1 = a1+z*(a2+z*(a3+z*(a4+z*(a5+z*a6))));
00098                 double f2 = (a2+2*a3*z+3*a4*z*z+4*a5*z*z*z+5*a6*z*z*z*z);
00099                 double f3 = (2*a3+6*a4*z+12*a5*z*z+20*a6*z*z*z);
00100                 double exp1 = exp(f1);
00101                 return exp1*((exp1-1.0)*f2*f2-(1.0+exp1)*f3)/
00102                                         (1.0+exp1)/(1.0+exp1)/(1.0+exp1);
00103         }
00104         /// evaluate the third derivative of the Enge function at z.
00105         double third(double z) const {
00106                 if(type == ENGE_BLOCK) return 0.0;
00107                 if(fabs(z) > 4.0) return 0.0;
00108                 double f1 = a1+z*(a2+z*(a3+z*(a4+z*(a5+z*a6))));
00109                 double f2 = a2+z*(2*a3+z*(3*a4+4*a5*z+5*a6*z*z));
00110                 double f3 = 2*(a3+z*(3*a4+2*z*(3*a5+5*a6*z)));
00111                 double f4 = a4+2.0*z*(2.0*a5+5.0*a6*z);
00112                 double exp1 = exp(f1);
00113                 double onepexp1 = 1.0 + exp1;
00114                 return -exp1*(6*exp1*exp1*f2*f2*f2-6*exp1*f2*(f2*f2+f3)*onepexp1
00115                         +(f2*f2*f2+3*f2*f3+6*f4)*onepexp1*onepexp1)
00116                         /(onepexp1*onepexp1*onepexp1*onepexp1);
00117         }
00118         /// evaluate the fourth derivative of the Enge function at z.
00119         double fourth(double z) const {
00120                 if(type == ENGE_BLOCK) return 0.0;
00121                 if(fabs(z) > 4.0) return 0.0;
00122                 double f1 = a1+z*(a2+z*(a3+z*(a4+z*(a5+z*a6))));
00123                 double f2 = a2+z*(2*a3+z*(3*a4+4*a5*z+5*a6*z*z));
00124                 double f3 = 2*(a3+z*(3*a4+2*z*(3*a5+5*a6*z)));
00125                 double f4 = a4+2.0*z*(2.0*a5+5.0*a6*z);
00126                 double f5 = a5 + 5*a6*z;
00127                 double exp1 = exp(f1);
00128                 double onepexp1 = 1.0 + exp1;
00129                 return -exp1*(-24*exp1*exp1*exp1*f2*f2*f2*f2+onepexp1*
00130                     (36*exp1*exp1*f2*f2*(f2*f2+f3)-2*exp1*(7*f2*f2*f2*f2
00131                     +18*f2*f2*f3+3*f3*f3+24*f2*f4)*onepexp1
00132                     +(f2*f2*f2*f2+6*f2*f2*f3+3*f3*f3+24*f2*f4+24*f5)
00133                     *onepexp1*onepexp1))
00134                     /(onepexp1*onepexp1*onepexp1*onepexp1*onepexp1);
00135         }
00136         /// evaluate the fifth derivative of the Enge function at z.
00137         double fifth(double z) const {
00138                 if(type == ENGE_BLOCK) return 0.0;
00139                 if(fabs(z) > 4.0) return 0.0;
00140                 double f1 = a1+z*(a2+z*(a3+z*(a4+z*(a5+z*a6))));
00141                 double f2 = a2+z*(2*a3+z*(3*a4+4*a5*z+5*a6*z*z));
00142                 double f3 = 2*(a3+z*(3*a4+2*z*(3*a5+5*a6*z)));
00143                 double f4 = a4+2.0*z*(2.0*a5+5.0*a6*z);
00144                 double f5 = a5 + 5*a6*z;
00145                 double exp1 = exp(f1);
00146                 double onepexp1 = 1.0 + exp1;
00147                 return -exp1/(onepexp1*onepexp1*onepexp1*onepexp1*onepexp1*onepexp1)
00148                     *(120*exp1*exp1*exp1*exp1*f2*f2*f2*f2*f2
00149                     -240*exp1*exp1*exp1*f2*f2*f2*(f2*f2+f3)*onepexp1
00150                     +onepexp1*onepexp1*(30*exp1*exp1*f2*(5*f2*f2*f2*f2
00151                     +12*f2*f2*f3+3*f3*f3+12*f2*f4)-10*exp1*(3*f2*f2*f2*f2*f2
00152                     +14*f2*f2*f2*f3+9*f2*f3*f3+36*f2*f2*f4+12*f3*f4+24*f2*f5)
00153                     *onepexp1+(120*a6+f2*f2*f2*f2*f2+10*f2*f2*f2*f3+60*f2*f2*f4
00154                     +60*f3*f4+15*f2*(f3*f3+8*f5))*onepexp1*onepexp1));
00155         }
00156         /// return the type of Enge function
00157         BLEngeType getType() const { return type; }
00158 };
00159 
00160 #endif // BLENGEFUNCTION_HH
g4beamline