| 1 | #include "sopnamsp.h" | 
|---|
| 2 | #include "machdefs.h" | 
|---|
| 3 | #include <iostream> | 
|---|
| 4 | #include <stdlib.h> | 
|---|
| 5 | #include <stdio.h> | 
|---|
| 6 | #include <string.h> | 
|---|
| 7 | #include <math.h> | 
|---|
| 8 | #include <vector> | 
|---|
| 9 |  | 
|---|
| 10 | #include "pexceptions.h" | 
|---|
| 11 |  | 
|---|
| 12 | #include "histos.h" | 
|---|
| 13 | #include "hisprof.h" | 
|---|
| 14 | #include "srandgen.h" | 
|---|
| 15 |  | 
|---|
| 16 | #include "geneutils.h" | 
|---|
| 17 |  | 
|---|
| 18 | namespace SOPHYA { | 
|---|
| 19 |  | 
|---|
| 20 | //------------------------------------------------------------------- | 
|---|
| 21 | // Classe d'interpolation lineaire: | 
|---|
| 22 | // Le vecteur y a n elements y_i tels que y_i = f(x_i) | 
|---|
| 23 | //   ou les x_i sont regulierement espaces | 
|---|
| 24 | //   et x_0=xmin et x_{n-1}=xmax   (xmax inclus!) | 
|---|
| 25 | InterpFunc::InterpFunc(double xmin,double xmax,vector<double>& y) | 
|---|
| 26 | : _xmin(xmin), _xmax(xmax), _y(y) | 
|---|
| 27 | { | 
|---|
| 28 | if(_xmin>=_xmax || _y.size()<=2) {  // au moins 3 points! | 
|---|
| 29 | cout<<"InterpFunc::InterpFunc : bad arguments values"<<endl; | 
|---|
| 30 | throw ParmError("InterpFunc::InterpFunc : bad arguments values"); | 
|---|
| 31 | } | 
|---|
| 32 | _nm1   = _y.size()-1; | 
|---|
| 33 | _dx    = (_xmax-_xmin)/(double)_nm1; | 
|---|
| 34 | } | 
|---|
| 35 |  | 
|---|
| 36 | double InterpFunc::Linear(double x,unsigned short& ok) | 
|---|
| 37 | { | 
|---|
| 38 | ok=0; if(x<_xmin) ok=1; else if(x>_xmax) ok=2; | 
|---|
| 39 | x -= _xmin; | 
|---|
| 40 | long i = long(x/_dx);  // On prend le "i" juste en dessous | 
|---|
| 41 | if(i<0) i=0; else if(i>=_nm1) i=_nm1-1; | 
|---|
| 42 | return _y[i] + (_y[i+1]-_y[i])/_dx*(x-i*_dx); | 
|---|
| 43 | } | 
|---|
| 44 |  | 
|---|
| 45 | double InterpFunc::Parab(double x,unsigned short& ok) | 
|---|
| 46 | { | 
|---|
| 47 | ok=0; if(x<_xmin) ok=1; else if(x>_xmax) ok=2; | 
|---|
| 48 | x -= _xmin; | 
|---|
| 49 | long i = long(x/_dx+0.5);  // On prend le "i" le + proche | 
|---|
| 50 | if(i<1) i=1; else if(i>=_nm1-1) i=_nm1-2; | 
|---|
| 51 | double a = (_y[i+1]-2.*_y[i]+_y[i-1])/(2.*_dx*_dx); | 
|---|
| 52 | double b = (_y[i+1]-_y[i-1])/(2.*_dx); | 
|---|
| 53 | return _y[i] + (x-i*_dx)*(a*(x-i*_dx)+b); | 
|---|
| 54 | } | 
|---|
| 55 |  | 
|---|
| 56 | //------------------------------------------------------------------- | 
|---|
| 57 | // Classe d'inversion d'une fonction STRICTEMENT MONOTONE CROISSANTE | 
|---|
| 58 | // | 
|---|
| 59 | // - On part de deux vecteurs x,y de "Nin" elements tels que "y_i = f[x_i]" | 
|---|
| 60 | //   ou la fonction "f" est strictement monotone croissante: | 
|---|
| 61 | //          x(i) < x(i+1)   et   y(i) < y(i+1) | 
|---|
| 62 | // - Le but de la classe est de remplir un vecteur X de "Nout" elements | 
|---|
| 63 | //   tels que:    X_j = f^-1[Y_j]    avec   j=[0,Nout[ | 
|---|
| 64 | //   avec les Y_j regulierement espaces entre ymin=y(0) , ymax=y(Nin -1) | 
|---|
| 65 | //   cad:     X_j = f^-1[ ymin+j*(ymax-ymin)/(Nout-1) ] | 
|---|
| 66 | // - La construction du vecteur X est realisee | 
|---|
| 67 | //   par interpolation lineaire (ComputeLinear) ou parabolique (ComputeParab) | 
|---|
| 68 | InverseFunc::InverseFunc(vector<double>& x,vector<double>& y) | 
|---|
| 69 | : _ymin(0.) , _ymax(0.) , _x(x) , _y(y) | 
|---|
| 70 | { | 
|---|
| 71 | uint_4 ns = _x.size(); | 
|---|
| 72 | if(ns<3 || _y.size()<=0 || ns!=_y.size()) | 
|---|
| 73 | throw ParmError("InverseFunc::InverseFunc_Error: bad array size"); | 
|---|
| 74 |  | 
|---|
| 75 | // Check "x" strictement monotone croissant | 
|---|
| 76 | for(uint_4 i=0;i<ns-1;i++) | 
|---|
| 77 | if(_x[i+1]<=_x[i]) { | 
|---|
| 78 | cout<<"InverseFunc::InverseFunc_Error: _x array not stricly growing"<<endl; | 
|---|
| 79 | throw ParmError("InverseFunc::InverseFunc_Error: _x array not stricly growing"); | 
|---|
| 80 | } | 
|---|
| 81 |  | 
|---|
| 82 | // Check "y" monotone croissant | 
|---|
| 83 | for(uint_4 i=0;i<ns-1;i++) | 
|---|
| 84 | if(_y[i+1]<_y[i]) { | 
|---|
| 85 | cout<<"InverseFunc::InverseFunc_Error: _y array not growing"<<endl; | 
|---|
| 86 | throw ParmError("InverseFunc::InverseFunc_Error: _y array not growing"); | 
|---|
| 87 | } | 
|---|
| 88 |  | 
|---|
| 89 | // define limits | 
|---|
| 90 | _ymin = _y[0]; | 
|---|
| 91 | _ymax = _y[ns-1]; | 
|---|
| 92 |  | 
|---|
| 93 | } | 
|---|
| 94 |  | 
|---|
| 95 | InverseFunc::~InverseFunc(void) | 
|---|
| 96 | { | 
|---|
| 97 | } | 
|---|
| 98 |  | 
|---|
| 99 | int InverseFunc::ComputeLinear(long nout,vector<double>& xfcty) | 
|---|
| 100 | // Compute table "xfcty" by linear interpolation of "x" versus "y" | 
|---|
| 101 | //   on "nout" points from "ymin" to "ymax": | 
|---|
| 102 | // xfcty[i] = interpolation of function "x" for "ymin+i*(ymax-ymin)/(nout-1)" | 
|---|
| 103 | { | 
|---|
| 104 | if(nout<3) return -1; | 
|---|
| 105 |  | 
|---|
| 106 | xfcty.resize(nout); | 
|---|
| 107 |  | 
|---|
| 108 | long i1,i2; | 
|---|
| 109 | double x; | 
|---|
| 110 | for(int_4 i=0;i<nout;i++) { | 
|---|
| 111 | double y = _ymin + i*(_ymax-_ymin)/(nout-1.); | 
|---|
| 112 | find_in_y(y,i1,i2); | 
|---|
| 113 | double dy = _y[i2]-_y[i1]; | 
|---|
| 114 | if(dy==0.) { | 
|---|
| 115 | x = (_x[i2]+_x[i1])/2.; // la fct a inverser est plate! | 
|---|
| 116 | } else { | 
|---|
| 117 | x = _x[i1] + (_x[i2]-_x[i1])/dy * (y-_y[i1]); | 
|---|
| 118 | } | 
|---|
| 119 | xfcty[i] = x; | 
|---|
| 120 | } | 
|---|
| 121 |  | 
|---|
| 122 | return 0; | 
|---|
| 123 | } | 
|---|
| 124 |  | 
|---|
| 125 | int InverseFunc::ComputeParab(long nout,vector<double>& xfcty) | 
|---|
| 126 | { | 
|---|
| 127 | if(nout<3) return -1; | 
|---|
| 128 |  | 
|---|
| 129 | xfcty.resize(nout); | 
|---|
| 130 |  | 
|---|
| 131 | long i1,i2,i3; | 
|---|
| 132 | double x; | 
|---|
| 133 | for(int_4 i=0;i<nout;i++) { | 
|---|
| 134 | double y = _ymin + i*(_ymax-_ymin)/(nout-1.); | 
|---|
| 135 | find_in_y(y,i1,i2); | 
|---|
| 136 | // On cherche le 3ieme point selon la position de y / au 2 premiers | 
|---|
| 137 | double my = (_y[i1]+_y[i2])/2.; | 
|---|
| 138 | if(y<my) {i3=i2; i2=i1; i1--;} else {i3=i2+1;} | 
|---|
| 139 | // Protection | 
|---|
| 140 | if(i1<0) {i1++; i2++; i3++;} | 
|---|
| 141 | if(i3==(long)_y.size()) {i1--; i2--; i3--;} | 
|---|
| 142 | // Interpolation parabolique | 
|---|
| 143 | double dy = _y[i3]-_y[i1]; | 
|---|
| 144 | if(dy==0.) { | 
|---|
| 145 | x = (_x[i3]+_x[i1])/2.; // la fct a inverser est plate! | 
|---|
| 146 | } else { | 
|---|
| 147 | double X1=_x[i1]-_x[i2], X3=_x[i3]-_x[i2]; | 
|---|
| 148 | double Y1=_y[i1]-_y[i2], Y3=_y[i3]-_y[i2]; | 
|---|
| 149 | double den = Y1*Y3*dy; | 
|---|
| 150 | double a = (X3*Y1-X1*Y3)/den; | 
|---|
| 151 | double b = (X1*Y3*Y3-X3*Y1*Y1)/den; | 
|---|
| 152 | y -= _y[i2]; | 
|---|
| 153 | x = (a*y+b)*y + _x[i2]; | 
|---|
| 154 | } | 
|---|
| 155 | xfcty[i] = x; | 
|---|
| 156 | } | 
|---|
| 157 |  | 
|---|
| 158 | return 0; | 
|---|
| 159 | } | 
|---|
| 160 |  | 
|---|
| 161 | //---------------------------------------------------- | 
|---|
| 162 | double InterpTab(double x0,vector<double>& X,vector<double>& Y,unsigned short typint) | 
|---|
| 163 | // Interpole in x0 the table Y = f(X) | 
|---|
| 164 | //           X doit etre ordonne par ordre croissant (strictement) | 
|---|
| 165 | // typint = 0 : nearest value | 
|---|
| 166 | //          1 : linear interpolation | 
|---|
| 167 | //          2 : parabolique interpolation | 
|---|
| 168 | { | 
|---|
| 169 | long n = X.size(); | 
|---|
| 170 | if(n>(long)Y.size() || n<2) | 
|---|
| 171 | throw ParmError("InterpTab_Error :  incompatible size between X and Y tables!"); | 
|---|
| 172 |  | 
|---|
| 173 | if(x0<X[0] || x0>X[n-1]) return 0.; | 
|---|
| 174 | if(typint>2) typint = 0; | 
|---|
| 175 |  | 
|---|
| 176 | // Recherche des indices encadrants par dichotomie | 
|---|
| 177 | long k, klo=0, khi=n-1; | 
|---|
| 178 | while (khi-klo > 1) { | 
|---|
| 179 | k = (khi+klo) >> 1; | 
|---|
| 180 | if (X[k] > x0) khi=k; else klo=k; | 
|---|
| 181 | } | 
|---|
| 182 |  | 
|---|
| 183 | // Quel est le plus proche? | 
|---|
| 184 | k = (x0-X[klo]<X[khi]-x0) ? klo: khi; | 
|---|
| 185 |  | 
|---|
| 186 | // On retourne le plus proche | 
|---|
| 187 | if(typint==0) return Y[k]; | 
|---|
| 188 |  | 
|---|
| 189 | // On retourne l'extrapolation lineaire | 
|---|
| 190 | if(typint==1 || n<3) | 
|---|
| 191 | return Y[klo] + (Y[khi]-Y[klo])/(X[khi]-X[klo])*(x0-X[klo]); | 
|---|
| 192 |  | 
|---|
| 193 | // On retourne l'extrapolation parabolique | 
|---|
| 194 | if(k==0) k++; else if(k==n-1) k--; | 
|---|
| 195 | klo = k-1; khi = k+1; | 
|---|
| 196 | double x1 = X[klo]-X[k], x2 = X[khi]-X[k]; | 
|---|
| 197 | double y1 = Y[klo]-Y[k], y2 = Y[khi]-Y[k]; | 
|---|
| 198 | double den = x1*x2*(x1-x2); | 
|---|
| 199 | double a = (y1*x2-y2*x1)/den; | 
|---|
| 200 | double b = (y2*x1*x1-y1*x2*x2)/den; | 
|---|
| 201 | x0 -= X[k]; | 
|---|
| 202 | return Y[k] + (a*x0+b)*x0;; | 
|---|
| 203 |  | 
|---|
| 204 | } | 
|---|
| 205 |  | 
|---|
| 206 | //------------------------------------------------------------------- | 
|---|
| 207 | int FuncToHisto(GenericFunc& func,Histo& h,bool logaxex) | 
|---|
| 208 | // Remplit l'histo 1D "h" avec la fonction "func" | 
|---|
| 209 | // INPUT: | 
|---|
| 210 | // logaxex = false : remplissage lineaire | 
|---|
| 211 | //        les abscisses "x" des bins sont remplis avec f(x) | 
|---|
| 212 | // logaxex = true : remplissage logarithmique (base 10) | 
|---|
| 213 | //        les abscisses "x" des bins sont remplis avec f(10^x) | 
|---|
| 214 | // RETURN: | 
|---|
| 215 | //       0 = OK | 
|---|
| 216 | //       1 = error | 
|---|
| 217 | { | 
|---|
| 218 | if(h.NBins()<=0) return 1; | 
|---|
| 219 |  | 
|---|
| 220 | h.Zero(); | 
|---|
| 221 |  | 
|---|
| 222 | for(int_4 i=0;i<h.NBins();i++) { | 
|---|
| 223 | double x = h.BinCenter(i); | 
|---|
| 224 | if(logaxex) x = pow(10.,x); | 
|---|
| 225 | h.SetBin(i,func(x)); | 
|---|
| 226 | } | 
|---|
| 227 |  | 
|---|
| 228 | return 0; | 
|---|
| 229 | } | 
|---|
| 230 |  | 
|---|
| 231 | int FuncToVec(GenericFunc& func,TVector<r_8>& v,double xmin,double xmax,bool logaxex) | 
|---|
| 232 | // Remplit le TVector avec la fonction "func" | 
|---|
| 233 | // INPUT: | 
|---|
| 234 | // logaxex = false : remplissage lineaire | 
|---|
| 235 | //        les abscisses "x" des bins sont remplis avec f(x) | 
|---|
| 236 | // logaxex = true : remplissage logarithmique (base 10) | 
|---|
| 237 | //        les abscisses "x" des bins sont remplis avec f(10^x) | 
|---|
| 238 | // RETURN: | 
|---|
| 239 | //       0 = OK | 
|---|
| 240 | //       1 = error | 
|---|
| 241 | // Remarque: | 
|---|
| 242 | //  v(i) = f(xmin+i*dx) avec dx = (xmax-xmin)/v.NElts() | 
|---|
| 243 | { | 
|---|
| 244 | if(v.NElts()<=0 || xmax<=xmin) return 1; | 
|---|
| 245 |  | 
|---|
| 246 | v = 0.; | 
|---|
| 247 | double dx = (xmax-xmin)/v.NElts(); | 
|---|
| 248 |  | 
|---|
| 249 | for(int_4 i=0;i<v.NElts();i++) { | 
|---|
| 250 | double x = xmin + i * dx;; | 
|---|
| 251 | if(logaxex) x = pow(10.,x); | 
|---|
| 252 | v(i) = func(x); | 
|---|
| 253 | } | 
|---|
| 254 |  | 
|---|
| 255 | return 0; | 
|---|
| 256 | } | 
|---|
| 257 |  | 
|---|
| 258 | //------------------------------------------------------------------- | 
|---|
| 259 | double AngSol(double dtheta,double dphi,double theta0) | 
|---|
| 260 | // Retourne l'angle solide d'un "rectangle" et coordonnees spheriques | 
|---|
| 261 | // de DEMI-COTE "dtheta" x "dphi" et centre en "theta0" | 
|---|
| 262 | // Attention: Le "theta0" de l'equateur est Pi/2  (et non pas zero) | 
|---|
| 263 | //            Les unites des angles sont en radians | 
|---|
| 264 | //               theta0 in [0,Pi] | 
|---|
| 265 | //               dtheta in [0,Pi] | 
|---|
| 266 | //               dphi   in [0,2Pi] | 
|---|
| 267 | // Return: l'angle solide en steradian | 
|---|
| 268 | { | 
|---|
| 269 | double theta1 = theta0-dtheta, theta2 = theta0+dtheta; | 
|---|
| 270 | if(theta1<0.) theta1=0.; | 
|---|
| 271 | if(theta2>M_PI) theta2=M_PI; | 
|---|
| 272 |  | 
|---|
| 273 | return   2.*dphi * (cos(theta1)-cos(theta2)); | 
|---|
| 274 | } | 
|---|
| 275 |  | 
|---|
| 276 | double AngSol(double dtheta) | 
|---|
| 277 | // Retourne l'angle solide d'une calotte spherique de demi-ouverture "dtheta" | 
|---|
| 278 | // Attention: Les unites des angles sont en radians | 
|---|
| 279 | //               dtheta in [0,Pi] | 
|---|
| 280 | // Return: l'angle solide en steradian | 
|---|
| 281 | // Approx pour theta petit: PI * theta^2 | 
|---|
| 282 | { | 
|---|
| 283 | return   2.*M_PI * (1.-cos(dtheta)); | 
|---|
| 284 | } | 
|---|
| 285 |  | 
|---|
| 286 | double FrAngSol(double angsol) | 
|---|
| 287 | // Retourne la demi-ouverture "dtheta" d'une calotte spherique d'angle solide "angsol" | 
|---|
| 288 | // Input: angle solide de la calotte spherique en steradians | 
|---|
| 289 | // Return: demi-ouverture de la calotte spherique en radians | 
|---|
| 290 | { | 
|---|
| 291 | angsol = 1. - angsol/(2.*M_PI); | 
|---|
| 292 | if(angsol<-1. || angsol>1.) return -1.; | 
|---|
| 293 | return acos(angsol); | 
|---|
| 294 | } | 
|---|
| 295 |  | 
|---|
| 296 | //------------------------------------------------------------------- | 
|---|
| 297 | double SinXsX(double x,bool app) | 
|---|
| 298 | // Calcul de sin(x)/x | 
|---|
| 299 | // Le Dl est en O[x]^10  (cad on va jusqu'au terme en x^8 compris) | 
|---|
| 300 | // Approx: terme en x^6/(6*20*42) ~ 1e-13 -> x^2 ~ 1.7e-4 | 
|---|
| 301 | { | 
|---|
| 302 | double x2 = x*x; | 
|---|
| 303 | if(app || x2<1.7e-4) return 1.-x2/6.*(1.-x2/20.*(1.-x2/42.*(1.-x2/72.))); | 
|---|
| 304 | return sin(x)/x; | 
|---|
| 305 | } | 
|---|
| 306 |  | 
|---|
| 307 | double SinXsX_Sqr(double x,bool app) | 
|---|
| 308 | // Calcul de (sin(x)/x)^2 | 
|---|
| 309 | // Le Dl est en O[x]^10  (cad on va jusqu'au terme en x^8 compris) | 
|---|
| 310 | // Approx: terme 2*x^6/(3*15*14) ~ 1e-13 -> x^2 ~ 6.8e-5 | 
|---|
| 311 | { | 
|---|
| 312 | double x2 = x*x; | 
|---|
| 313 | if(app || x2<6.8e-5) return 1.-x2/3.*(1.-2.*x2/15.*(1.-x2/14.*(1.-2.*x2/45.))); | 
|---|
| 314 | x2 = sin(x)/x; | 
|---|
| 315 | return x2*x2; | 
|---|
| 316 | } | 
|---|
| 317 |  | 
|---|
| 318 | double SinNXsX(double x,unsigned long N,bool app) | 
|---|
| 319 | // Calcul de sin(N*x)/sin(x)  avec N entier positif | 
|---|
| 320 | // ATTENTION: N est entier | 
|---|
| 321 | //  1. pour que sin(N*x) et sin(x) soient nuls en meme temps | 
|---|
| 322 | //     (on peut faire le DL popur sin(N*x) et sin(x)) | 
|---|
| 323 | //  2. pour traiter correctement le DL en x = p*Pi+e  avec e<<1 et p entier | 
|---|
| 324 | //     sin(N*x)/sin(x) = sin(N*p*Pi+N*e)/sin(p*Pi+e) | 
|---|
| 325 | //                     = [sin(N*p*Pi)*cos(N*e)+cos(N*p*Pi)*sin(N*e)] | 
|---|
| 326 | //                         / [sin(p*Pi)*cos(e)+cos(p*Pi)*sin(e)] | 
|---|
| 327 | //                     comme sin(N*p*Pi)=0 | 
|---|
| 328 | //                     = [cos(N*p*Pi)*sin(N*e)] / [cos(p*Pi)*sin(e)] | 
|---|
| 329 | //                     = [sin(N*e)/sin(e)] * [cos(N*p*Pi)/cos(p*Pi)] | 
|---|
| 330 | //                     = [DL autour de x=0] * (+1 ou -1) | 
|---|
| 331 | //     Le seul cas ou on a "-1" est quand "p=impair" (cos(p*Pi)=-1) et "N=pair" | 
|---|
| 332 | // Approx: dernier terme x^4*N^4/120 ~ 1e-13 -> x^2 ~ 3.5e-6/N^2 | 
|---|
| 333 | { | 
|---|
| 334 | if(N==0) return 0; | 
|---|
| 335 | double sx = sin(x), N2 = N*N; | 
|---|
| 336 | if(app || sx*sx<3.5e-6/N2) { | 
|---|
| 337 | double x2 = asin(sx); x2 *= x2; | 
|---|
| 338 | double s = 1.; | 
|---|
| 339 | if(N%2==0 && cos(x)<0.) s = -1.; // cas x ~ (2p+1)*Pi et N pair | 
|---|
| 340 | return s*N*(1.-(N-1.)*(N+1.)/6.*x2*(1.-(3.*N2-7.)/60.*x2)); | 
|---|
| 341 | } | 
|---|
| 342 | return sin((double)N*x)/sx; | 
|---|
| 343 | } | 
|---|
| 344 |  | 
|---|
| 345 | double SinNXsX_Sqr(double x,unsigned long N,bool app) | 
|---|
| 346 | // Calcul de [sin(N*x)/sin(x)]^2  avec N entier positif | 
|---|
| 347 | // ATTENTION: cf remarque pour N entier dans SinNXsX | 
|---|
| 348 | //            maximum de la fonction: N^2 | 
|---|
| 349 | // Approx: dernier terme x^4*2*N^4/45 ~ 1e-13 -> x^2 ~ 1.5e-6/N^2 | 
|---|
| 350 | { | 
|---|
| 351 | if(N==0) return 0; | 
|---|
| 352 | double sx = sin(x), N2 = N*N; | 
|---|
| 353 | if(app || sx*sx<1.5e-6/N2) { | 
|---|
| 354 | double x2 = asin(sx); x2 *= x2; | 
|---|
| 355 | //return N2*(1.-(N*N-1.)/3.*x2); | 
|---|
| 356 | return N2*(1.-(N-1.)*(N+1.)/3.*x2*(1.-(2.*N2-3.)/15.*x2)); | 
|---|
| 357 | } | 
|---|
| 358 | sx = sin((double)N*x)/sx; | 
|---|
| 359 | return sx*sx; | 
|---|
| 360 | } | 
|---|
| 361 |  | 
|---|
| 362 | //------------------------------------------------------------------- | 
|---|
| 363 | /*========================================================= | 
|---|
| 364 | Antenne de longueur totale d (lue au milieu cad 2 brins de d/2) | 
|---|
| 365 | see Jackson p401  (antenne selon Oz, centre z=0 en O) | 
|---|
| 366 | k = w/C = 2 Pi Nu / C = 2 Pi / Lambda | 
|---|
| 367 | - densite de courant: J = I sin(kd/2 - k|z|)*delta(x)*delta(y) | 
|---|
| 368 | (selon Oz) et pour |z|<d/2 | 
|---|
| 369 | I current peak value if kd>=Pi | 
|---|
| 370 | - current at gap (center): I0 = I sin(kd/2) | 
|---|
| 371 | # | 
|---|
| 372 | Z=sqrt(Mu/Epsilon) is the impedance of the vacum (376.7 Ohms) | 
|---|
| 373 | cad pour le vecteur de pointing: |S| = |E0|^2/Z | 
|---|
| 374 | - Time average radiated power by solid angle unit: | 
|---|
| 375 | t is theta the polar angle, t=0 along antenna, Pi/2 perpendicular | 
|---|
| 376 | dP/dOmega = Z*I^2/(8Pi^2) * (cos(kd/2*cos(t)) - cos(kd/2))^2 / sin(t)^2 | 
|---|
| 377 | if we define  L = d/lambda ,  kd/2= Pi * L | 
|---|
| 378 | dP/dOmega = Z*I^2/(8Pi^2) * (cos(Pi*L*cos(t)) - cos(Pi*L))^2 / sin(t)^2 | 
|---|
| 379 | # | 
|---|
| 380 | - pour t -> 0 | 
|---|
| 381 | dP/dOmega = Z*I^2/(8Pi^2) * ( 1/4 * (Pi*L*sin(Pi*L)*t)^2 ) | 
|---|
| 382 | - pour t -> Pi | 
|---|
| 383 | dP/dOmega = Z*I^2/(8Pi^2) * ( 1/4 * (Pi*L*sin(Pi*L)*(t-Pi))^2 ) | 
|---|
| 384 | # | 
|---|
| 385 | - Polarisation in plane containing antenna and the direction of propagation | 
|---|
| 386 | # | 
|---|
| 387 | - pour kd << 1  (L->0)  -> approximation du dipole: | 
|---|
| 388 | dP/dOmega = Z*I^2/(8Pi^2) * ( (Pi*L)^4/4 * sin(t)^2 ) | 
|---|
| 389 | - pour kd=Pi  (L=1/2)  -> half-wave length: | 
|---|
| 390 | dP/dOmega = Z*I^2/(8Pi^2) * cos(Pi/2*cos(t))^2/sin(t)^2 | 
|---|
| 391 | - pour kd=2*Pi  (L=1)  -> full-wave length: | 
|---|
| 392 | dP/dOmega = Z*I^2/(8Pi^2) * 4*cos(Pi/2*cos(t))^4/sin(t)^2 | 
|---|
| 393 | # | 
|---|
| 394 | - Le programme retourne Val tel que: dP/dOmega = Z*I^2/(8Pi^2) * Val | 
|---|
| 395 | L<0 (arg[0]<0) alors Val est normalise tel que le maximum = 1 | 
|---|
| 396 | # | 
|---|
| 397 | La carte antenne fournie par Peterson: | 
|---|
| 398 | d=8cm, distance entre 2 centres consecutifs 10cm | 
|---|
| 399 | # | 
|---|
| 400 | # ---- AntCentFed , AntDipole et LobeSinc | 
|---|
| 401 | # Input: | 
|---|
| 402 | #   t = angle entre la direction de la radiation et le fil de l'antenne (radian) | 
|---|
| 403 | #   L = d/Lambda  (d=longueur totale de l'antenne) | 
|---|
| 404 | # Output: | 
|---|
| 405 | #   (8Pi^2) dP/dOmega / (Z*I^2) | 
|---|
| 406 | ========================================================= */ | 
|---|
| 407 |  | 
|---|
| 408 | double AntCentFed(double L, double trad) | 
|---|
| 409 | { | 
|---|
| 410 | double pil = M_PI*L; | 
|---|
| 411 | double st = sin(trad), ct = cos(trad); | 
|---|
| 412 | // L'antenne standing-wave | 
|---|
| 413 | double v = 0.; | 
|---|
| 414 | if(fabs(st)<1e-3) { | 
|---|
| 415 | if(ct>0.) {  // theta ~= 0 | 
|---|
| 416 | v = pil*sin(pil)*trad/2.;  v *= v; | 
|---|
| 417 | } else {  // theta ~= 180 | 
|---|
| 418 | v = -pil*sin(pil)*(trad-M_PI)/2.;  v *= v; | 
|---|
| 419 | } | 
|---|
| 420 | } else { | 
|---|
| 421 | v = (cos(pil*ct) - cos(pil))/st;  v *= v; | 
|---|
| 422 | } | 
|---|
| 423 |  | 
|---|
| 424 | return v; | 
|---|
| 425 | } | 
|---|
| 426 |  | 
|---|
| 427 | double AntDipole(double L, double trad) | 
|---|
| 428 | { | 
|---|
| 429 | double pil = M_PI*L; | 
|---|
| 430 | double st = sin(trad); | 
|---|
| 431 | // L'approximation du dipole | 
|---|
| 432 | double vd = pil*pil*st/2.;  vd *= vd; | 
|---|
| 433 | return vd; | 
|---|
| 434 | } | 
|---|
| 435 |  | 
|---|
| 436 | double LobeSinc(double L, double trad) | 
|---|
| 437 | { | 
|---|
| 438 | double x = M_PI*L*sin(trad); | 
|---|
| 439 | return SinXsX_Sqr(x); | 
|---|
| 440 | } | 
|---|
| 441 |  | 
|---|
| 442 | //------------------------------------------------------------------- | 
|---|
| 443 |  | 
|---|
| 444 | static unsigned short IntegrateFunc_GlOrder = 0; | 
|---|
| 445 | static vector<double> IntegrateFunc_x; | 
|---|
| 446 | static vector<double> IntegrateFunc_w; | 
|---|
| 447 |  | 
|---|
| 448 | /////////////////////////////////////////////////////////// | 
|---|
| 449 | //************** Integration of Functions ***************// | 
|---|
| 450 | /////////////////////////////////////////////////////////// | 
|---|
| 451 |  | 
|---|
| 452 |  | 
|---|
| 453 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 454 | double IntegrateFunc(GenericFunc& func,double xmin,double xmax | 
|---|
| 455 | ,double perc,double dxinc,double dxmax,unsigned short glorder) | 
|---|
| 456 | // --- Integration adaptative --- | 
|---|
| 457 | //     Integrate[func[x], {x,xmin,xmax}] | 
|---|
| 458 | // ..xmin,xmax are the integration limits | 
|---|
| 459 | // ..dxinc is the searching increment x = xmin+i*dxinc | 
|---|
| 460 | //         if <0  npt = int(|dxinc|)   (si<2 alors npt=100) | 
|---|
| 461 | //                et dxinc = (xmax-xmin)/npt | 
|---|
| 462 | // ..dxmax is the maximum possible increment (if dxmax<=0 no test) | 
|---|
| 463 | // --- | 
|---|
| 464 | // Partition de [xmin,xmax] en intervalles [x(i),x(i+1)]: | 
|---|
| 465 | // on parcourt [xmin,xmax] par pas de "dxinc" : x(i) = xmin + i*dxinc | 
|---|
| 466 | // on cree un intervalle [x(i),x(i+1)] | 
|---|
| 467 | //     - si |f[x(i+1)] - f[x(i)]| > perc*|f[[x(i)]| | 
|---|
| 468 | //     - si |x(i+1)-x(i)| >= dxmax  (si dxmax>0.) | 
|---|
| 469 | // Dans un intervalle [x(i),x(i+1)] la fonction est integree | 
|---|
| 470 | //   avec une methode de gauss-legendre d'ordre "glorder" | 
|---|
| 471 | { | 
|---|
| 472 | double signe = 1.; | 
|---|
| 473 | if(xmin>xmax) {double tmp=xmax; xmax=xmin; xmin=tmp; signe=-1.;} | 
|---|
| 474 |  | 
|---|
| 475 | if(glorder==0) glorder = 4; | 
|---|
| 476 | if(perc<=0.) perc=0.1; | 
|---|
| 477 | if(dxinc<=0.) {int n=int(-dxinc); if(n<2) n=100; dxinc=(xmax-xmin)/n;} | 
|---|
| 478 | if(glorder != IntegrateFunc_GlOrder) { | 
|---|
| 479 | IntegrateFunc_GlOrder = glorder; | 
|---|
| 480 | Compute_GaussLeg(glorder,IntegrateFunc_x,IntegrateFunc_w,0.,1.); | 
|---|
| 481 | } | 
|---|
| 482 |  | 
|---|
| 483 | // Recherche des intervalles [x(i),x(i+1)] | 
|---|
| 484 | int_4 ninter = 0; | 
|---|
| 485 | double sum = 0., xbas=xmin, fbas=func(xbas), fabsfbas=fabs(fbas); | 
|---|
| 486 | for(double x=xmin+dxinc; x<xmax+dxinc/2.; x += dxinc) { | 
|---|
| 487 | double f = func(x); | 
|---|
| 488 | double dx = x-xbas; | 
|---|
| 489 | bool doit = false; | 
|---|
| 490 | if( x>xmax ) {doit = true; x=xmax;} | 
|---|
| 491 | else if( dxmax>0. && dx>dxmax ) doit = true; | 
|---|
| 492 | else if( fabs(f-fbas)>perc*fabsfbas ) doit = true; | 
|---|
| 493 | if( ! doit ) continue; | 
|---|
| 494 | double s = 0.; | 
|---|
| 495 | for(unsigned short i=0;i<IntegrateFunc_GlOrder;i++) | 
|---|
| 496 | s += IntegrateFunc_w[i]*func(xbas+IntegrateFunc_x[i]*dx); | 
|---|
| 497 | sum += s*dx; | 
|---|
| 498 | xbas = x; fbas = f; fabsfbas=fabs(fbas); ninter++; | 
|---|
| 499 | } | 
|---|
| 500 | //cout<<"Ninter="<<ninter<<endl; | 
|---|
| 501 |  | 
|---|
| 502 | return sum*signe; | 
|---|
| 503 | } | 
|---|
| 504 |  | 
|---|
| 505 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 506 | double IntegrateFuncLog(GenericFunc& func,double lxmin,double lxmax | 
|---|
| 507 | ,double perc,double dlxinc,double dlxmax,unsigned short glorder) | 
|---|
| 508 | // --- Integration adaptative --- | 
|---|
| 509 | // Idem IntegrateFunc but integrate on logarithmic (base 10) intervals: | 
|---|
| 510 | //    Int[ f(x) dx ] = Int[ x*f(x) dlog10(x) ] * log(10) | 
|---|
| 511 | // ..lxmin,lxmax are the log10() of the integration limits | 
|---|
| 512 | // ..dlxinc is the searching logarithmic (base 10) increment lx = lxmin+i*dlxinc | 
|---|
| 513 | // ..dlxmax is the maximum possible logarithmic (base 10) increment (if dlxmax<=0 no test) | 
|---|
| 514 | // Remarque: to be use if "x*f(x) versus log10(x)" looks like a polynomial | 
|---|
| 515 | //            better than "f(x) versus x" | 
|---|
| 516 | // ATTENTION: la fonction func que l'on passe en argument | 
|---|
| 517 | //            est "func(x)" et non pas "func(log10(x))" | 
|---|
| 518 | { | 
|---|
| 519 | double signe = 1.; | 
|---|
| 520 | if(lxmin>lxmax) {double tmp=lxmax; lxmax=lxmin; lxmin=tmp; signe=-1.;} | 
|---|
| 521 |  | 
|---|
| 522 | if(glorder==0) glorder = 4; | 
|---|
| 523 | if(perc<=0.) perc=0.1; | 
|---|
| 524 | if(dlxinc<=0.) {int n=int(-dlxinc); if(n<2) n=100; dlxinc=(lxmax-lxmin)/n;} | 
|---|
| 525 | if(glorder != IntegrateFunc_GlOrder) { | 
|---|
| 526 | IntegrateFunc_GlOrder = glorder; | 
|---|
| 527 | Compute_GaussLeg(glorder,IntegrateFunc_x,IntegrateFunc_w,0.,1.); | 
|---|
| 528 | } | 
|---|
| 529 |  | 
|---|
| 530 | // Recherche des intervalles [lx(i),lx(i+1)] | 
|---|
| 531 | int_4 ninter = 0; | 
|---|
| 532 | double sum = 0., lxbas=lxmin, fbas=func(pow(10.,lxbas)), fabsfbas=fabs(fbas); | 
|---|
| 533 | for(double lx=lxmin+dlxinc; lx<lxmax+dlxinc/2.; lx += dlxinc) { | 
|---|
| 534 | double f = func(pow(10.,lx)); | 
|---|
| 535 | double dlx = lx-lxbas; | 
|---|
| 536 | bool doit = false; | 
|---|
| 537 | if( lx>lxmax ) {doit = true; lx=lxmax;} | 
|---|
| 538 | else if( dlxmax>0. && dlx>dlxmax ) doit = true; | 
|---|
| 539 | else if( fabs(f-fbas)>perc*fabsfbas ) doit = true; | 
|---|
| 540 | if( ! doit ) continue; | 
|---|
| 541 | double s = 0.; | 
|---|
| 542 | for(unsigned short i=0;i<IntegrateFunc_GlOrder;i++) { | 
|---|
| 543 | double y = pow(10.,lxbas+IntegrateFunc_x[i]*dlx); | 
|---|
| 544 | s += IntegrateFunc_w[i]*y*func(y); | 
|---|
| 545 | } | 
|---|
| 546 | sum += s*dlx; | 
|---|
| 547 | lxbas = lx; fbas = f; fabsfbas=fabs(fbas); ninter++; | 
|---|
| 548 | } | 
|---|
| 549 | //cout<<"Ninter="<<ninter<<endl; | 
|---|
| 550 |  | 
|---|
| 551 | return M_LN10*sum*signe; | 
|---|
| 552 | } | 
|---|
| 553 |  | 
|---|
| 554 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 555 | /* | 
|---|
| 556 | Integration des fonctions a une dimension y=f(x) par la Methode de Gauss-Legendre. | 
|---|
| 557 | --> Calcul des coefficients du developpement pour [x1,x2] | 
|---|
| 558 | | INPUT: | 
|---|
| 559 | |  x1,x2 : bornes de l'intervalle (dans nbinteg.h -> x1=-0.5 x2=0.5) | 
|---|
| 560 | |  glorder = degre n du developpement de Gauss-Legendre | 
|---|
| 561 | | OUTPUT: | 
|---|
| 562 | |  x[] = valeur des abscisses ou l'on calcule (dim=n) | 
|---|
| 563 | |  w[] = valeur des coefficients associes | 
|---|
| 564 | | REMARQUES: | 
|---|
| 565 | |  - x et w seront dimensionnes a n. | 
|---|
| 566 | |  - l'integration est rigoureuse si sur l'intervalle d'integration | 
|---|
| 567 | |    la fonction f(x) peut etre approximee par un polynome | 
|---|
| 568 | |    de degre 2*m (monome le + haut x**(2*n-1) ) | 
|---|
| 569 | */ | 
|---|
| 570 | void Compute_GaussLeg(unsigned short glorder,vector<double>& x,vector<double>& w,double x1,double x2) | 
|---|
| 571 | { | 
|---|
| 572 | if(glorder==0) return; | 
|---|
| 573 | int n = (int)glorder; | 
|---|
| 574 | x.resize(n,0.); w.resize(n,0.); | 
|---|
| 575 |  | 
|---|
| 576 | int m,j,i; | 
|---|
| 577 | double z1,z,xm,xl,pp,p3,p2,p1; | 
|---|
| 578 |  | 
|---|
| 579 | m=(n+1)/2; | 
|---|
| 580 | xm=0.5*(x2+x1); | 
|---|
| 581 | xl=0.5*(x2-x1); | 
|---|
| 582 | for (i=1;i<=m;i++)  { | 
|---|
| 583 | z=cos(M_PI*(i-0.25)/(n+0.5)); | 
|---|
| 584 | do { | 
|---|
| 585 | p1=1.0; | 
|---|
| 586 | p2=0.0; | 
|---|
| 587 | for (j=1;j<=n;j++) { | 
|---|
| 588 | p3=p2; | 
|---|
| 589 | p2=p1; | 
|---|
| 590 | p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j; | 
|---|
| 591 | } | 
|---|
| 592 | pp=n*(z*p1-p2)/(z*z-1.0); | 
|---|
| 593 | z1=z; | 
|---|
| 594 | z=z1-p1/pp; | 
|---|
| 595 | } while (fabs(z-z1) > 3.0e-11);  // epsilon | 
|---|
| 596 | x[i-1]=xm-xl*z; | 
|---|
| 597 | x[n-i]=xm+xl*z; | 
|---|
| 598 | w[i-1]=2.0*xl/((1.0-z*z)*pp*pp); | 
|---|
| 599 | w[n-i]=w[i-1]; | 
|---|
| 600 | } | 
|---|
| 601 | } | 
|---|
| 602 |  | 
|---|
| 603 | }  // Fin namespace SOPHYA | 
|---|