/*************************************************************************** TPofBCalc.cpp Author: Bastian M. Wojek e-mail: bastian.wojek@psi.ch 2008/09/04 ***************************************************************************/ /*************************************************************************** * Copyright (C) 2009 by Bastian M. Wojek * * * * * * 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. * ***************************************************************************/ #include "TPofTCalc.h" #include #include #include #include #include #include /* USED FOR DEBUGGING----------------------------------- #include #include /-------------------------------------------------------*/ TPofBCalc::TPofBCalc(const vector ¶) : fBmin(0.0), fBmax(0.0), fDT(para[0]), fDB(para[1]), fPBExists(false) { fPBSize = static_cast(1.0/(gBar*fDT*fDB)); if (fPBSize % 2) { fPBSize += 1; } else { fPBSize += 2; } fB = new double[fPBSize]; fPB = new double[fPBSize]; int i; for (i = 0; i < static_cast(fPBSize); i++) { fB[i] = static_cast(i)*fDB; fPB[i] = 0.0; } } // Do not actually calculate P(B) but take it from a B and a P(B) vector of the same size TPofBCalc::TPofBCalc(const vector& b, const vector& pb, double dt) { assert(b.size() == pb.size() && b.size() >= 2); fPBSize = pb.size(); fB = new double[fPBSize]; fPB = new double[fPBSize]; for (unsigned int i(0); i < fPBSize; i++) { fB[i] = b[i]; fPB[i] = pb[i]; } vector::const_iterator iter, iterB; iterB = b.begin(); for(iter = pb.begin(); iter != pb.end(); iter++){ if(*iter != 0.0) { fBmin = *iterB; // cout << fBmin << endl; break; } iterB++; } for( ; iter != b.end(); iter++){ if(*iter == 0.0) { fBmax = *(iterB-1); // cout << fBmax << endl; break; } iterB++; } fDT = dt; // needed if a convolution should be done fDB = b[1]-b[0]; // cout << fDB << endl; fPBExists = true; } void TPofBCalc::UnsetPBExists() { int i; #pragma omp parallel for default(shared) private(i) schedule(dynamic) for (i = 0; i < static_cast(fPBSize); i++) { fPB[i] = 0.0; } fPBExists = false; } void TPofBCalc::Calculate(const string &type, const vector ¶) { if (type == "skg"){ // skewed Gaussian fBmin = 0.0; fBmax = para[2]/gBar+10.0*fabs(para[4])/(2.0*pi*gBar); int a3(static_cast(floor(fBmax/fDB))); int a4(static_cast(ceil(fBmax/fDB))); unsigned int BmaxIndex((a3 < a4) ? a4 : (a4 + 1)); unsigned int B0Index(static_cast(ceil(para[2]/(gBar*fDB)))); double expominus(para[3]*para[3]/(2.0*pi*pi*gBar*gBar)); double expoplus(para[4]*para[4]/(2.0*pi*pi*gBar*gBar)); double B0(para[2]/(gBar)); for (unsigned int i(0); i < B0Index; i++) { fPB[i] = exp(-(fB[i]-B0)*(fB[i]-B0)/expominus); } for (unsigned int i(B0Index); i <= BmaxIndex; i++) { fPB[i] = exp(-(fB[i]-B0)*(fB[i]-B0)/expoplus); } // normalize p(B) double pBsum = 0.0; for (unsigned int i(0); i <= BmaxIndex; i++) pBsum += fPB[i]; pBsum *= fDB; for (unsigned int i(0); i <= BmaxIndex; i++) fPB[i] /= pBsum; } fPBExists = true; return; } //----------- // Calculate-method that does the P(B) calculation for given analytical inverse of B(z) and its derivative and n(z) // Parameters: dt[us], dB[G], Energy[keV], Bbg[G], width[us^{-1}], weight[1] //----------- void TPofBCalc::Calculate(const TBofZCalcInverse *BofZ, const TTrimSPData *dataTrimSP, const vector ¶) { if(fPBExists) return; fBmin = BofZ->GetBmin(); fBmax = BofZ->GetBmax(); int a1(static_cast(floor(fBmin/fDB))); int a2(static_cast(ceil(fBmin/fDB))); int a3(static_cast(floor(fBmax/fDB))); int a4(static_cast(ceil(fBmax/fDB))); unsigned int firstZerosEnd ((a1 < a2) ? a1 : ((a1 > 0) ? (a1 - 1) : 0)); unsigned int lastZerosStart ((a3 < a4) ? a4 : (a4 + 1)); if (lastZerosStart >= fPBSize) { lastZerosStart = fPBSize - 1; } unsigned int i; // calculate p(B) from the inverse of B(z) for (i = firstZerosEnd; i <= lastZerosStart; i++) { vector< pair > inv; inv = BofZ->GetInverseAndDerivative(fB[i]); for (unsigned int j(0); j < inv.size(); j++) { fPB[i] += dataTrimSP->GetNofZ(inv[j].first, para[2])*fabs(inv[j].second); } // if (fPB[i]) // cout << fB[i] << " " << fPB[i] << endl; } // normalize p(B) double pBsum = 0.0; for (i = firstZerosEnd; i<=lastZerosStart; i++) pBsum += fPB[i]; pBsum *= fDB; for (i = firstZerosEnd; i<=lastZerosStart; i++) fPB[i] /= pBsum; if(para.size() == 6) AddBackground(para[3], para[4], para[5]); } //----------- // Calculate-method that does the P(B) calculation for given B(z) and n(z) // Parameters: dt[us], dB[G], Energy[keV] //----------- void TPofBCalc::Calculate(const TBofZCalc *BofZ, const TTrimSPData *dataTrimSP, const vector ¶, unsigned int zonk) { if(fPBExists) return; fBmin = BofZ->GetBmin(); fBmax = BofZ->GetBmax(); int a1(static_cast(floor(fBmin/fDB))); int a2(static_cast(ceil(fBmin/fDB))); int a3(static_cast(floor(fBmax/fDB))); int a4(static_cast(ceil(fBmax/fDB))); unsigned int firstZerosEnd ((a1 < a2) ? a1 : ((a1 > 0) ? (a1 - 1) : 0)); unsigned int lastZerosStart ((a3 < a4) ? a4 : (a4 + 1)); double BB, BBnext; double zm, zp, zNext, dz; // calculate p(B) from B(z) vector *bofzZ = BofZ->DataZ(); vector *bofzBZ = BofZ->DataBZ(); double ddZ(BofZ->GetDZ()); /* USED FOR DEBUGGING----------------------------------- cout << "Bmin = " << fBmin << ", Bmax = " << fBmax << endl; time_t seconds; seconds = time (NULL); char debugfile[50]; int n = sprintf (debugfile, "test_Bz_%ld_%f.dat", seconds, fBmin); if (n > 0) { ofstream of(debugfile); // assure(of, debugfile); for (unsigned int i(0); i 0) { ofstream of1(debugfile1); // assure(of1, debugfile1); dataTrimSP.Normalize(para[2]); for (unsigned int i(0); i 0) { ofstream of2(debugfile2); // assure(of1, debugfile1); dataTrimSP.ConvolveGss(10.0,para[2]); dataTrimSP.Normalize(para[2]); for (unsigned int i(0); isize() - 1; j++ ) { if ( (*bofzBZ)[j] >= BB && (*bofzBZ)[j+1] <= BB ) { zm = (BB-(*bofzBZ)[j])*ddZ/((*bofzBZ)[j+1]-(*bofzBZ)[j]) + (*bofzZ)[j]; for (unsigned int k(0); k < j; k++) { if ( ( (*bofzBZ)[j-k] <= BBnext && (*bofzBZ)[j-k-1] >= BBnext ) ) { // cout << "1 " << j << " " << k << endl; zNext = (BBnext-(*bofzBZ)[j-k-1])*ddZ/((*bofzBZ)[j-k]-(*bofzBZ)[j-k-1]) + (*bofzZ)[j-k-1]; zNextFound = true; break; } } if(zNextFound) { zNextFound = false; dz = zNext-zm; nn = dataTrimSP->GetNofZ(zm, para[2]); if (nn != -1.0) { // cout << "zNext = " << zNextm << ", zm = " << zm << ", dz = " << dz << endl; fPB[i] += nn*fabs(dz/fDB); } } } else if ((*bofzBZ)[j] <= BB && (*bofzBZ)[j+1] >= BB ) { zp = (BB-(*bofzBZ)[j])*ddZ/((*bofzBZ)[j+1]-(*bofzBZ)[j]) + (*bofzZ)[j]; for (unsigned int k(0); k < bofzZ->size() - j - 1; k++) { if ( ( (*bofzBZ)[j+k] <= BBnext && (*bofzBZ)[j+k+1] >= BBnext ) ) { // cout << "2 " << j << " " << k << endl; zNext = (BBnext-(*bofzBZ)[j+k])*ddZ/((*bofzBZ)[j+k+1]-(*bofzBZ)[j+k]) + (*bofzZ)[j+k]; zNextFound = true; break; } } if(zNextFound) { zNextFound = false; dz = zNext-zp; nn = dataTrimSP->GetNofZ(zp, para[2]); if (nn != -1.0) { // cout << "zNext = " << zNextp << ", zp = " << zp << ", dz = " << dz << endl; fPB[i] += nn*fabs(dz/fDB); } } } } } bofzZ = 0; bofzBZ = 0; // normalize p(B) double pBsum = 0.0; for (unsigned int i(firstZerosEnd); i<=lastZerosStart; i++) pBsum += fPB[i]; pBsum *= fDB; for (unsigned int i(firstZerosEnd); i<=lastZerosStart; i++) fPB[i] /= pBsum; fPBExists = true; return; } //----------- // Calculate method that does the P(B) calculation for a bulk vortex lattice // Parameters: dt[us], dB[G] [, Bbg[G], width[us^{-1}], weight[1] ] //----------- void TPofBCalc::Calculate(const TBulkVortexFieldCalc *vortexLattice, const vector ¶) { if(fPBExists) return; fBmin = vortexLattice->GetBmin(); fBmax = vortexLattice->GetBmax(); int a1(static_cast(floor(fBmin/fDB))); int a2(static_cast(ceil(fBmin/fDB))); int a3(static_cast(floor(fBmax/fDB))); int a4(static_cast(ceil(fBmax/fDB))); unsigned int firstZerosEnd ((a1 < a2) ? a1 : ((a1 > 0) ? (a1 - 1) : 0)); unsigned int lastZerosStart ((a3 < a4) ? a4 : (a4 + 1)); unsigned int numberOfSteps(vortexLattice->GetNumberOfSteps()); unsigned int numberOfStepsSq(numberOfSteps*numberOfSteps); unsigned int numberOfSteps_2(numberOfSteps/2); unsigned int numberOfStepsSq_2(numberOfStepsSq/2); if (lastZerosStart >= fPBSize) lastZerosStart = fPBSize - 1; // cout << endl << fBmin << " " << fBmax << " " << firstZerosEnd << " " << lastZerosStart << " " << numberOfSteps << endl; if (!vortexLattice->GridExists()) { vortexLattice->CalculateGrid(); } double *vortexFields = vortexLattice->DataB(); unsigned int fill_index, counter(0); for (unsigned int j(0); j < numberOfStepsSq_2; j++) { fill_index = static_cast(ceil(fabs((vortexFields[j]/fDB)))); if (fill_index >= fPBSize) fPB[fPBSize - 1] += 1.0; else fPB[fill_index] += 1.0; counter++; if (counter == numberOfSteps_2) { // sum only over the first quadrant of B(x,y) counter = 0; j += numberOfSteps_2; } } vortexFields = 0; double normalizer(static_cast(numberOfStepsSq_2/2)*fDB); int i; #pragma omp parallel for default(shared) private(i) schedule(dynamic) for (i = firstZerosEnd; i <= static_cast(lastZerosStart); i++) { fPB[i] /= normalizer; } // end pragma omp parallel if(para.size() == 5) AddBackground(para[2], para[3], para[4]); fPBExists = true; return; } // TPofBCalc::AddBackground, Parameters: field B[G], width s[us], weight w void TPofBCalc::AddBackground(double B, double s, double w) { if(!s || w<0.0 || w>1.0 || B<0.0) return; double BsSq(s*s/(gBar*gBar*4.0*pi*pi)); // calculate Gaussian background double bg[fPBSize]; for(unsigned int i(0); i < fPBSize; i++) { bg[i] = exp(-(fB[i]-B)*(fB[i]-B)/(2.0*BsSq)); } // normalize background double bgsum(0.0); for (unsigned int i(0); i < fPBSize; i++) bgsum += bg[i]; bgsum *= fDB; for (unsigned int i(0); i < fPBSize; i++) bg[i] /= bgsum; // add background to P(B) for (unsigned int i(0); i < fPBSize; i++) fPB[i] = (1.0 - w)*fPB[i] + w*bg[i]; // // check if normalization is still valid // double pBsum(0.0); // for (unsigned int i(0); i < sizePB; i++) // pBsum += fPB[i]; // // cout << "pBsum = " << pBsum << endl; } void TPofBCalc::ConvolveGss(double w) { if(!w) return; unsigned int NFFT(fPBSize); double TBin; fftw_plan FFTplanToTimeDomain; fftw_plan FFTplanToFieldDomain; fftw_complex *FFTout; TBin = 1.0/(gBar*double(NFFT-1)*fDB); FFTout = new fftw_complex[NFFT/2 + 1]; //(fftw_complex *)fftw_malloc(sizeof(fftw_complex) * (NFFT/2+1)); // do the FFT to time domain FFTplanToTimeDomain = fftw_plan_dft_r2c_1d(NFFT, fPB, FFTout, FFTW_ESTIMATE); fftw_execute(FFTplanToTimeDomain); // multiply everything by a gaussian double GssInTimeDomain; double expo(-2.0*PI*PI*gBar*gBar*w*w*TBin*TBin); for (unsigned int i(0); i < NFFT/2+1; i++) { GssInTimeDomain = exp(expo*static_cast(i*i)); FFTout[i][0] *= GssInTimeDomain; FFTout[i][1] *= GssInTimeDomain; } // FFT back to the field domain FFTplanToFieldDomain = fftw_plan_dft_c2r_1d(NFFT, FFTout, fPB, FFTW_ESTIMATE); fftw_execute(FFTplanToFieldDomain); // cleanup fftw_destroy_plan(FFTplanToTimeDomain); fftw_destroy_plan(FFTplanToFieldDomain); delete[] FFTout; // fftw_free(FFTout); FFTout = 0; // fftw_cleanup(); // normalize p(B) double pBsum = 0.0; for (unsigned int i(0); i < NFFT; i++) pBsum += fPB[i]; pBsum *= fDB; for (unsigned int i(0); i < NFFT; i++) fPB[i] /= pBsum; return; }