5 #include <gsl/gsl_sf_legendre.h> 9 #include "CLHEP/GenericFunctions/ClebschGordanCoefficientSet.hh" 12 FUNCTION_OBJECT_IMP(SphericalHarmonicFit)
18 Clockwork(
unsigned int LMAX):LMAX(LMAX),coefficientsA(LMAX),coefficientsASq(2*LMAX) {}
50 std::complex<double> I(0,1.0);
53 for (
unsigned int l=0;l<=LMAX;l++) {
57 const LStruct *lStructThis= (l==0 ? NULL: & lstruct[l-1]);
58 const LStruct *lStructNext= (l==LMAX ? NULL: & lstruct[l]);
60 double fThis = f*(1-fHigher);
65 for (
int m=0;m<=int(l);m++) {
69 const MStruct *mStructThis= ((m==0 || !lStructThis) ? NULL: & lStructThis->
mstruct[m-1]);
70 const MStruct *mStructNext= (m==int(l) ? NULL: & lStructThis->
mstruct[m]);
72 double gThis = g*(1-gHigher);
76 std::cout <<
"L-fraction correction" << fThis <<
"-->0" << std::endl;
80 std::cout <<
"M-fraction correction" << gThis <<
"-->0" << std::endl;
86 double amplitude = sqrt(fThis*gThis);
87 px = lStructThis->
phaseLM0->getValue();;
88 coefficientsA(l,m)=exp(I*px)*amplitude;
92 double amplitude = sqrt(fThis*gThis);
93 coefficientsA(l,m)=exp(I*px)*amplitude;
101 coefficientsA(l,m)=exp(I*px)*amplitude;
104 double amplitude = sqrt(fThis*gThis*(1-mStructThis->
fractionMPositive->getValue()));
106 coefficientsA(l,-m)=exp(I*px)*amplitude;
118 SphericalHarmonicFit::SphericalHarmonicFit(
unsigned int LMAX):
119 c(new Clockwork(LMAX))
121 for (
unsigned int l=1;l<=
LMAX;l++) {
125 std::ostringstream stream;
126 stream <<
"Fraction L>=" << l;
127 lstruct.fractionLOrHigher=
new Genfun::Parameter(stream.str(), 0.5, 0, 1);
130 std::ostringstream stream;
131 stream <<
"Phase L=" << l <<
"; M=0";
132 lstruct.phaseLM0=
new Genfun::Parameter(stream.str(), M_PI, -2*M_PI, 2*M_PI);
134 for (
unsigned int m=1;m<=l;m++) {
135 Clockwork::MStruct mstruct;
138 std::ostringstream stream;
139 stream <<
"Fraction L= " << l <<
"; |M| >=" << m;
140 mstruct.fractionAbsMOrHigher=
new Genfun::Parameter(stream.str(), 0.5, 0, 1);
143 std::ostringstream stream;
144 stream <<
"Fraction L=" << l <<
"; M=+" << m ;
145 mstruct.fractionMPositive=
new Genfun::Parameter(stream.str(), 0.5, 0, 1);
148 std::ostringstream stream;
149 stream <<
"Phase L=" << l <<
"; M=+" << m ;
150 mstruct.phaseMPlus=
new Genfun::Parameter(stream.str(), M_PI, -2*M_PI, 2*M_PI);
153 std::ostringstream stream;
154 stream <<
"Phase L=" << l <<
"; M=-" << m ;
155 mstruct.phaseMMinus=
new Genfun::Parameter(stream.str(), M_PI, -2*M_PI, 2*M_PI);
158 lstruct.mstruct.push_back(mstruct);
166 SphericalHarmonicFit::~SphericalHarmonicFit() {
167 for (
unsigned int i=0;i<c->lstruct.size();i++) {
168 delete c->lstruct[i].fractionLOrHigher;
169 delete c->lstruct[i].phaseLM0;
170 for (
unsigned int j=0;j<c->lstruct[i].mstruct.size();j++) {
171 delete c->lstruct[i].mstruct[j].fractionAbsMOrHigher;
172 delete c->lstruct[i].mstruct[j].fractionMPositive;
173 delete c->lstruct[i].mstruct[j].phaseMPlus;
174 delete c->lstruct[i].mstruct[j].phaseMMinus;
181 SphericalHarmonicFit::SphericalHarmonicFit(
const SphericalHarmonicFit & right):
183 c(new Clockwork(right.c->LMAX))
185 for (
unsigned int i=0;i<right.c->lstruct.size();i++) {
187 lstruct.L= right.c->lstruct[i].L;
188 lstruct.fractionLOrHigher =
new Parameter(*right.c->lstruct[i].fractionLOrHigher);
189 lstruct.phaseLM0 =
new Parameter(*right.c->lstruct[i].phaseLM0);
190 for (
unsigned int j=0;j<right.c->lstruct[i].mstruct.size();j++) {
191 Clockwork::MStruct mstruct;
192 mstruct.M=right.c->lstruct[i].mstruct[j].M;
193 mstruct.fractionAbsMOrHigher=
new Parameter(*right.c->lstruct[i].mstruct[j].fractionAbsMOrHigher);
194 mstruct.fractionMPositive =
new Parameter(*right.c->lstruct[i].mstruct[j].fractionMPositive);
195 mstruct.phaseMPlus =
new Parameter(*right.c->lstruct[i].mstruct[j].phaseMPlus);
196 mstruct.phaseMMinus =
new Parameter(*right.c->lstruct[i].mstruct[j].phaseMMinus);
197 lstruct.mstruct.push_back(mstruct);
204 double SphericalHarmonicFit::operator() (
double )
const {
205 throw std::runtime_error(
"Dimensionality error in SphericalHarmonicFit");
210 double SphericalHarmonicFit::operator() (
const Argument & a )
const {
211 unsigned int LMAX=c->LMAX;
219 std::vector< std::vector<double> > Plm(LMAX+1);
220 for (
int m=0;m<=int(LMAX);m++) {
221 Plm[m].resize(LMAX+1);
222 gsl_sf_legendre_sphPlm_array (LMAX, m, x, &*Plm[m].begin());
225 c->recomputeCoefficients();
226 std::complex<double> P=0.0;
227 std::complex<double> I(0,1.0);
228 for (
unsigned int l=0;l<=LMAX;l++) {
229 for (
int m=0;m<=int(l);m++) {
232 double Pn= Plm[abs(m)][LP];
234 if (!finite(Pn))
return 0.0;
237 P+=(c->coefficientsA(l,m)*Pn*exp(I*(m*phi)));
239 if (m!=0) P+= ( (m%2 ?-1.0:1.0)*c->coefficientsA(l,-m)*Pn*exp(-I*(m*phi)));
244 double retVal=std::norm(P);
245 if (!finite(retVal)) {
252 unsigned int SphericalHarmonicFit::lMax()
const {
257 unsigned int SphericalHarmonicFit::numComponents()
const {
258 return (c->LMAX+1)*(c->LMAX+1)-1;
263 Parameter *SphericalHarmonicFit::getFractionLOrHigher(
unsigned int L){
264 return c->lstruct[L-1].fractionLOrHigher;
268 const Parameter *SphericalHarmonicFit::getFractionLOrHigher(
unsigned int L)
const {
269 return c->lstruct[L-1].fractionLOrHigher;
274 Parameter *SphericalHarmonicFit::getPhaseLM0(
unsigned int L){
275 return c->lstruct[L-1].phaseLM0;
279 const Parameter *SphericalHarmonicFit::getPhaseLM0(
unsigned int L)
const{
280 return c->lstruct[L-1].phaseLM0;
285 Parameter *SphericalHarmonicFit::getFractionAbsMOrHigher(
unsigned int L,
unsigned int M){
286 return c->lstruct[L-1].mstruct[M-1].fractionAbsMOrHigher;
290 const Parameter *SphericalHarmonicFit::getFractionAbsMOrHigher(
unsigned int L,
unsigned int M)
const{
291 return c->lstruct[L-1].mstruct[M-1].fractionAbsMOrHigher;
297 Parameter *SphericalHarmonicFit::getFractionMPositive(
unsigned int L,
unsigned int M){
298 return c->lstruct[L-1].mstruct[M-1].fractionMPositive;
302 const Parameter *SphericalHarmonicFit::getFractionMPositive(
unsigned int L,
unsigned int M)
const{
303 return c->lstruct[L-1].mstruct[M-1].fractionMPositive;
309 Parameter *SphericalHarmonicFit::getPhaseMPlus(
unsigned int L,
unsigned int M){
310 return c->lstruct[L-1].mstruct[M-1].phaseMPlus;
314 const Parameter *SphericalHarmonicFit::getPhaseMPlus(
unsigned int L,
unsigned int M)
const{
315 return c->lstruct[L-1].mstruct[M-1].phaseMPlus;
321 Parameter *SphericalHarmonicFit::getPhaseMMinus(
unsigned int L,
unsigned int M){
322 return c->lstruct[L-1].mstruct[M-1].phaseMMinus;
326 const Parameter *SphericalHarmonicFit::getPhaseMMinus(
unsigned int L,
unsigned int M)
const{
327 return c->lstruct[L-1].mstruct[M-1].phaseMMinus;
331 const SphericalHarmonicCoefficientSet & SphericalHarmonicFit::coefficientsA()
const {
332 c->recomputeCoefficients();
333 return c->coefficientsA;
337 const SphericalHarmonicCoefficientSet & SphericalHarmonicFit::coefficientsASq()
const{
338 c->recomputeCoefficients();
339 unsigned int LMAX=c->coefficientsA.getLMax();
340 for (
unsigned int L=0;L<=2*LMAX;L++) {
341 for (
int M=-L; M<=int(L); M++) {
342 c->coefficientsASq(L,M)=0.0;
343 for (
unsigned int l1=0;l1<=LMAX;l1++) {
344 for (
unsigned int l2=0;l2<=LMAX;l2++) {
345 for (
int m1=-l1;m1<=int(l1);m1++) {
346 for (
int m2=-l2;m2<=int(l2);m2++) {
348 if (((l1+l2) >= L) && abs(l1-l2) <=int(L)) {
349 c->coefficientsASq(L,M) += (c->coefficientsA(l1,m1)*
350 conj(c->coefficientsA(l2,m2))*
352 sqrt((2*l1+1)*(2*l2+1)/(4*M_PI*(2*L+1)))*
353 c->ClebschGordan(l1,l2,0,0,L,0)*c->ClebschGordan(l1,l2,m1,-m2,L,M));
362 return c->coefficientsASq;
366 void SphericalHarmonicFit::recomputeCoefficients()
const {
367 c->recomputeCoefficients();
SphericalHarmonicCoefficientSet coefficientsA
Clockwork(unsigned int LMAX)
Genfun::Parameter * fractionMPositive
Genfun::Parameter * phaseMPlus
std::vector< MStruct > mstruct
Genfun::Parameter * phaseMMinus
ClebschGordanCoefficientSet ClebschGordan
SphericalHarmonicCoefficientSet coefficientsASq
std::vector< LStruct > lstruct
Genfun::Parameter * fractionLOrHigher
Genfun::Parameter * fractionAbsMOrHigher
Genfun::Parameter * phaseLM0
void recomputeCoefficients()