📄 f_analytic.c
字号:
#define RCSID "$Id: F_Analytic.c,v 1.26 2006/02/26 00:42:53 geuzaine Exp $"/* * Copyright (C) 1997-2006 P. Dular, C. Geuzaine * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. * * Please report all bugs and problems to <getdp@geuz.org>. * * Contributor(s): * Ruth Sabariego */#include "GetDP.h"#include "Data_DefineE.h"#include "F_Function.h"#include "GeoData.h"#include "Numeric.h"#include "Numeric_F.h"#include "Get_Geometry.h"#include "Cal_Value.h" #include "CurrentData.h"#include "Legendre.h"#include "SphBessel.h"/* ------------------------------------------------------------------------ *//* Warning: the pointers A and V can be identical. You must *//* use temporary variables in your computations: you can only *//* affect to V at the very last time (when you're sure you will *//* not use A any more). *//* ------------------------------------------------------------------------ */#define F_ARG struct Function * Fct, struct Value * A, struct Value * V/* some utility functions to deal with complex numbers */typedef struct { double r; double i;} cplx;static cplx Csum(cplx a, cplx b){ cplx s; s.r = a.r + b.r; s.i = a.i + b.i; return(s);}static cplx Csub(cplx a, cplx b){ cplx s; s.r = a.r - b.r; s.i = a.i - b.i; return(s);}static cplx Cprod(cplx a, cplx b){ cplx s; s.r = a.r * b.r - a.i * b.i; s.i = a.r * b.i + a.i * b.r; return(s);}static cplx Cdiv(cplx a, cplx b){ cplx s; double den; den = b.r * b.r + b.i * b.i; s.r = (a.r * b.r + a.i * b.i) / den; s.i = (a.i * b.r - a.r * b.i) / den; return(s);}static cplx Cconj(cplx a){ cplx s; s.r = a.r; s.i = -a.i; return(s);}static cplx Cneg(cplx a){ cplx s; s.r = -a.r; s.i = -a.i; return(s);}static double Cmodu(cplx a){ return(sqrt(a.r * a.r + a.i * a.i));}static cplx Cpow(cplx a, double b){ cplx s; double mod, arg; mod = a.r * a.r + a.i * a.i; arg = atan2(a.i,a.r); mod = pow(mod,0.5*b); arg *= b; s.r = mod * cos(arg); s.i = mod * sin(arg); return(s);}static cplx Cprodr(double a, cplx b){ cplx s; s.r = a * b.r; s.i = a * b.i; return(s);}/* ------------------------------------------------------------------------ *//* Exact solutions for spheres *//* ------------------------------------------------------------------------ *//* Solid and hollow sphere, in magnetostatics and magnetodynamics. Returns field at any point */void F_Sphere (F_ARG) { double x, y, z ; double sxr, sxi, syr, syi, szr, szi ; double mur, sigma, freq, r0, r1 ; GetDP_Begin("F_Sphere"); x = Current.x; y = Current.y; z = Current.z; mur = Fct->Para[1] ; sigma = Fct->Para[2] ; freq = Fct->Para[3] ; r0 = Fct->Para[4] ; r1 = Fct->Para[5] ; if (r0 == 0.0){ /* sphere pleine */ if (Fct->Para[0] == 0){ /* induction */ solsph_(&x,&y,&z,&sxr,&sxi,&syr,&syi,&szr,&szi,&mur,&sigma,&freq,&r1); } else { Msg(GERROR, "Not done ..."); } } else{ /* sphere creuse */ Msg(GERROR, "Not done ..."); } if (Current.NbrHar == 1) { V->Val[0] = sxr ; V->Val[1] = syr ; V->Val[2] = szr ; } else { V->Val[0] = sxr ; V->Val[1] = syr ; V->Val[2] = szr ; V->Val[MAX_DIM] = sxi ; V->Val[MAX_DIM+1] = syi ; V->Val[MAX_DIM+2] = szi ; } V->Type = VECTOR ; GetDP_End ;}/* Scattering by solid PEC sphere. Returns theta-component of surface current */void F_JFIE_SphTheta(F_ARG){ double k0, r, kr, e0, eta, theta, phi, a1, b1, c1, d1, den1, P, P0, dP ; double ctheta, stheta, cteRe1, cteRe2, a2, b2, c2, d2, den2 ; int i, n ; GetDP_Begin("F_JFIE_SphTheta") ; theta = atan2(sqrt( A->Val[0]* A->Val[0] + A->Val[1]*A->Val[1] ), A->Val[2]); phi = atan2( A->Val[1], A->Val[0] ) ; k0 = Fct->Para[0] ; eta = Fct->Para[1] ; e0 = Fct->Para[2] ; r = Fct->Para[3] ; kr = k0*r ; n = 50 ; V->Val[0] = 0.; V->Val[MAX_DIM] = 0. ; if ( theta == 0. ) theta += 1e-7; /* Warning! This is an approximation. */ if ( theta == PI || theta == -PI ) theta -= 1e-7; for (i = 1 ; i <= n ; i++ ){ ctheta = cos(theta); stheta = sin(theta); P = Legendre(i,1,ctheta); P0 = Legendre(i,0,ctheta); dP = (i+1)*i* P0/stheta-(ctheta/(ctheta*ctheta-1))* P; cteRe1 = (2*i+1) * stheta * dP/i/(i+1); cteRe2 = (2*i+1) * P/stheta/i/(i+1); a1 = cos((1-i)*PI/2) ; b1 = sin((1-i)*PI/2) ; c1 = -AltSpherical_j_n(i+1, kr) + (i+1) * AltSpherical_j_n(i, kr)/kr ; /* Derivative */ d1 = -(-AltSpherical_y_n(i+1, kr) + (i+1) * AltSpherical_y_n(i, kr)/kr) ; a2 = cos((2-i)*PI/2) ; b2 = sin((2-i)*PI/2) ; c2 = AltSpherical_j_n(i, kr) ; d2 = -AltSpherical_y_n(i, kr) ; den1 = c1*c1+d1*d1 ; den2 = c2*c2+d2*d2 ; V->Val[0] += cteRe1*(a1*c1+b1*d1)/den1 + cteRe2*(a2*c2+b2*d2)/den2 ; V->Val[MAX_DIM] += cteRe1*(b1*c1-a1*d1)/den1 + cteRe2*(b2*c2-a2*d2)/den2 ; } V->Val[0] *= e0*cos(phi)/eta/kr ; V->Val[MAX_DIM] *= e0*cos(phi)/eta/kr ; V->Type = SCALAR ; GetDP_End;} /* Scattering by solid PEC sphere. Returns theta-component of RCS */void F_RCS_SphTheta(F_ARG){ double k0, r, kr, e0, rinf, krinf, theta, phi, a1 =0., b1=0., d1, den1, P, P0, dP ; double J, J_1, dJ, ctheta, stheta, cteRe1, cteRe2, a2, b2, d2, den2, lambda ; int i, n ; GetDP_Begin("F_RCS_SphTheta") ; theta = atan2(sqrt( A->Val[0]* A->Val[0] + A->Val[1]*A->Val[1] ), A->Val[2]); phi = atan2( A->Val[1], A->Val[0] ) ; k0 = Fct->Para[0] ; e0 = Fct->Para[1] ; r = Fct->Para[2] ; rinf = Fct->Para[3] ; kr = k0*r ; krinf = k0*rinf ; lambda = 2*PI/k0 ; n = 50 ; if ( theta == 0. ) theta += 1e-7; /* Warning! This is an approximation. */ if ( theta == PI || theta == -PI ) theta -= 1e-7; for (i = 1 ; i <= n ; i++ ){ ctheta = cos(theta); stheta = sin(theta); P = Legendre(i,1,ctheta); P0 = Legendre(i,0,ctheta); dP = (i+1)*i* P0/stheta-(ctheta/(ctheta*ctheta-1))* P; J = AltSpherical_j_n(i, kr) ; J_1 = AltSpherical_j_n(i+1, kr) ; dJ = -J_1 + (i + 1) * J/kr ; cteRe1 = -(2*i+1) * stheta * dP * dJ /i/(i+1); cteRe2 = (2*i+1) * P * J /stheta/i/(i+1); d1 = -(-AltSpherical_y_n(i+1, kr) + (i+1) * AltSpherical_y_n(i, kr)/kr) ; d2 = -AltSpherical_y_n(i, kr) ; den1 = dJ*dJ+d1*d1 ; den2 = J*J+d2*d2 ; a1 += cteRe1 * dJ /den1 + cteRe2 * J /den2 ; b1 += cteRe1*(-d1) /den1 + cteRe2*(-d2) /den2 ; } a2 = e0*cos(phi)*sin(krinf)/krinf ; b2 = e0*cos(phi)*cos(krinf)/krinf ; V->Val[0] = 10*log10( 4*PI*SQU(rinf/lambda)*(SQU(a1*a2-b1*b2) + SQU(a1*b2+a2*b1)) ); V->Val[MAX_DIM] = 0. ; V->Type = SCALAR ; GetDP_End;}/* Scattering by solid PEC sphere. Returns phi-component of surface current */void F_JFIE_SphPhi(F_ARG){ double k0, r, kr, e0, eta, theta, phi, a1, b1, c1, d1, den1, P, P0, dP ; double ctheta, stheta, cteRe1, cteRe2, a2, b2, c2, d2, den2 ; int i, n ; GetDP_Begin("F_JFIE_SphPhi") ; theta = atan2( sqrt( A->Val[0]*A->Val[0] + A->Val[1]*A->Val[1] ), A->Val[2]); phi = atan2( A->Val[1], A->Val[0] ) ; k0 = Fct->Para[0] ; eta = Fct->Para[1] ; e0 = Fct->Para[2] ; r = Fct->Para[3] ; kr = k0*r ; n = 50 ; V->Val[0] = 0.; V->Val[MAX_DIM] = 0. ; if ( theta == 0. ) theta += 1e-7; /* Warning! This is an approximation. */ if ( theta == PI || theta == -PI ) theta -= 1e-7; for (i = 1 ; i <= n ; i++ ){ ctheta = cos(theta); stheta = sin(theta); P = Legendre(i,1,ctheta); P0 = Legendre(i,0,ctheta); dP = (i+1)*i* P0/stheta - ctheta/(ctheta*ctheta-1)*P; /* Derivative */ cteRe1 = (2*i+1) * P /i/(i+1)/stheta; cteRe2 = (2*i+1) * stheta * dP/i/(i+1); a1 = cos((1-i)*PI/2) ; b1 = sin((1-i)*PI/2) ; c1 = -AltSpherical_j_n(i+1, kr) + (i+1)*AltSpherical_j_n(i, kr)/kr ; /* Derivative */ d1 = -(-AltSpherical_y_n(i+1, kr) + (i+1)*AltSpherical_y_n(i, kr)/kr) ; a2 = cos((2-i)*PI/2) ; b2 = sin((2-i)*PI/2) ; c2 = AltSpherical_j_n(i, kr) ; d2 = -AltSpherical_y_n(i, kr) ; den1 = c1*c1+d1*d1 ; den2 = c2*c2+d2*d2 ; V->Val[0] += cteRe1*(a1*c1+b1*d1)/den1 + cteRe2*(a2*c2+b2*d2)/den2 ; V->Val[MAX_DIM] += cteRe1*(b1*c1-a1*d1)/den1 + cteRe2*(b2*c2-a2*d2)/den2 ; } V->Val[0] *= e0*sin(phi)/eta/kr ; V->Val[MAX_DIM] *= e0*sin(phi)/eta/kr ; V->Type = SCALAR ; GetDP_End;}/* Scattering by solid PEC sphere. Returns phi-component of RCS */void F_RCS_SphPhi(F_ARG){ double k0, r, kr, e0, rinf, krinf, theta, phi, a1 =0., b1=0., d1, den1, P, P0, dP ; double J, J_1, dJ, ctheta, stheta, cteRe1, cteRe2, a2, b2, d2, den2, lambda ; int i, n ; GetDP_Begin("F_RCS_SphPhi") ; theta = atan2(sqrt( A->Val[0]* A->Val[0] + A->Val[1]*A->Val[1] ), A->Val[2]); phi = PI/2 ; k0 = Fct->Para[0] ; e0 = Fct->Para[1] ; r = Fct->Para[2] ; rinf = Fct->Para[3] ; kr = k0*r ; krinf = k0*rinf ; lambda = 2*PI/k0 ; n = 50 ; if ( theta == 0. ) theta += 1e-7; /* Warning! This is an approximation. */ if ( theta == PI || theta == -PI ) theta -= 1e-7; for (i = 1 ; i <= n ; i++ ){ ctheta = cos(theta); stheta = sin(theta); P = Legendre(i,1,ctheta); P0 = Legendre(i,0,ctheta); dP = (i+1)*i* P0/stheta-(ctheta/(ctheta*ctheta-1))* P; J = AltSpherical_j_n(i, kr) ; J_1 = AltSpherical_j_n(i+1, kr) ; dJ = -J_1 + (i + 1) * J/kr ; cteRe1 = -(2*i+1) * P * dJ /stheta/i/(i+1); cteRe2 = (2*i+1) * stheta * dP * J/i/(i+1); d1 = -(-AltSpherical_y_n(i+1, kr) + (i+1) * AltSpherical_y_n(i, kr)/kr) ; d2 = -AltSpherical_y_n(i, kr) ; den1 = dJ*dJ+d1*d1 ; den2 = J*J+d2*d2 ; a1 += cteRe1 * dJ /den1 + cteRe2 * J /den2 ; b1 += cteRe1*(-d1) /den1 + cteRe2*(-d2) /den2 ; } a2 = e0*sin(phi)*sin(krinf)/krinf ; b2 = e0*sin(phi)*cos(krinf)/krinf ; V->Val[0] = 10*log10( 4*PI*SQU(rinf/lambda)*(SQU(a1*a2-b1*b2) + SQU(a1*b2+a2*b1)) ); V->Val[MAX_DIM] = 0. ; V->Type = SCALAR ; GetDP_End;} /* Scattering by solid acoustically soft sphere (exterior Dirichlet problem) by incident plane wave in the direction of the negative z-axis. Returns total field at any exterior point. J.J. Bowman, T.B.A. Senior and P.L.E. Uslenghi, Electromagnetic and Acoustic Scattering by Simple Shapes, p. 358 In: k: wave number a: sphere radius r: r coord in spherical coords theta: theta coord in spherical coords Out: total field V_i+V_s*/void F_AcousticSoftSphere(F_ARG){#define N 50 double k, a, r, theta, ka, kr, fact; int n; double jnka[N], jnkr[N], hnkar[N], hnkai[N], hnkrr[N], hnkri[N]; struct Value V_tmp, V_tmp2, V_mi, V_jnka, V_jnkr, V_hnka, V_hnkr, V_an; GetDP_Begin("F_AcousticSoftSphere") ; k = A->Val[0]; a = (A+1)->Val[0]; r = (A+2)->Val[0]; theta = (A+3)->Val[0]; kr = k*r ; ka = k*a ; V->Type = SCALAR ; V->Val[0] = 0.; V->Val[MAX_DIM] = 0. ; V_tmp.Type = V_tmp2.Type = SCALAR; V_mi.Type = V_jnka.Type = V_jnkr.Type = SCALAR; V_hnka.Type = V_hnkr.Type = V_an.Type = SCALAR; n = 0; Spherical_j_nArray(n,kr,N,&jnkr[0]); Spherical_j_nArray(n,ka,N,&jnka[0]); Spherical_h_nArray(1,n,kr,N,hnkrr,hnkri); Spherical_h_nArray(1,n,ka,N,hnkar,hnkai); /* to compare with gsl/python */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -