void OStream::writeArchiveMetadata() { if (mRuntimeVersion >= 6) { // Max possible size. const std::size_t BufferLen = 1+5+5+1; char buffer[BufferLen] = {0}; buffer[0] = BeginArchiveMetadata; RCF::ByteBuffer byteBuffer(&buffer[0], BufferLen); std::size_t pos = 1; encodeInt(mRuntimeVersion, byteBuffer, pos); encodeInt(mArchiveVersion, byteBuffer, pos); if (mRuntimeVersion >= 10) { encodeBool(getTrackingContext().getEnabled(), byteBuffer, pos); } writeRaw(&buffer[0], static_cast<UInt32>(pos)); } }
bool OStream::getEnablePointerTracking() const { return getTrackingContext().getEnabled(); }
void OStream::setEnablePointerTracking(bool enable) { getTrackingContext().setEnabled(enable); }
void OStream::clearState() { getTrackingContext().clear(); mArchiveMetadataWritten = false; }
bool IStream::begin(Node &node) { while (true) { Byte8 byte = 0; read_byte(byte); switch (byte) { case Blank: { Byte8 count = 0; read_byte(count); std::vector<Byte8> buffer(count); UInt32 bytesRead = read( &(buffer[0]), count); if (bytesRead != static_cast<UInt32>(count)) { RCF::Exception e(RCF::_SfError_DataFormat()); RCF_THROW(e)(bytesRead)(count); } continue; } case BeginArchiveMetadata: { int runtimeVersion = 0; int archiveVersion = 0; bool pointerTrackingEnabled = false; bool * pPointerTrackingEnabled = NULL; const size_t BufferLen = 11; char buffer[BufferLen] = {0}; RCF::ByteBuffer byteBuffer( &buffer[0], BufferLen); std::size_t pos0 = static_cast<std::size_t>(mpIs->tellg()); #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4996 ) // warning C4996: 'std::basic_istream<_Elem,_Traits>::readsome': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators' #endif std::size_t bytesRead = static_cast<std::size_t>(mpIs->readsome(buffer, BufferLen)); #ifdef _MSC_VER #pragma warning( pop ) #endif byteBuffer = RCF::ByteBuffer(byteBuffer, 0, bytesRead); std::size_t pos1 = 0; decodeInt(runtimeVersion, byteBuffer, pos1); decodeInt(archiveVersion, byteBuffer, pos1); if (runtimeVersion >= 10) { decodeBool(pointerTrackingEnabled, byteBuffer, pos1); pPointerTrackingEnabled = &pointerTrackingEnabled; } mpIs->seekg( static_cast<std::istream::off_type>(pos0 + pos1), std::ios_base::beg); if (!mIgnoreVersionStamp) { if (runtimeVersion) { mRuntimeVersion = runtimeVersion; } if (archiveVersion) { mArchiveVersion = archiveVersion; } } if (pPointerTrackingEnabled && !*pPointerTrackingEnabled) { getTrackingContext().setEnabled(false); } continue; } case Begin: { read_byte( byte ); Byte8 attrSpec = byte; // id if (attrSpec & 1) { read_int(node.id); } // ref attrSpec = attrSpec >> 1; if (attrSpec & 1) { node.ref = 1; } // type attrSpec = attrSpec >> 1; if (attrSpec & 1) { UInt32 length = 0; read_int(length); node.type.allocate(length); read(node.type.get(), length ); } // label attrSpec = attrSpec >> 1; if (attrSpec & 1) { UInt32 length = 0; read_int(length); node.label.allocate(length); read(node.label.get(), length); } return true; } default: { RCF::Exception e(RCF::_SfError_DataFormat()); RCF_THROW(e)(byte); } } } }
void IStream::clearState() { getTrackingContext().clear(); }
void optimizeBinSettingsForImpedance(double timeSpan, double freq, double Q, double *binSize, long *nBins, long maxBins) { long n_bins, maxBins2; double bin_size, factor; TRACKING_CONTEXT tcontext; n_bins = *nBins; bin_size = *binSize; getTrackingContext(&tcontext); if (maxBins<=0) maxBins2 = pow(2, 20); else maxBins2 = pow(2, (long)(log(maxBins)/log(2)+1)); if (maxBins>0 && maxBins!=maxBins2) fprintf(stdout, "Adjusted maximum number of bins for %s %s to %ld\n", entity_name[tcontext.elementType], tcontext.elementName, maxBins2); if (1/(2*freq*bin_size)<10) { /* want maximum frequency in Z > 10*fResonance */ fprintf(stdout, "%s %s has excessive bin size for given resonance frequency\n", entity_name[tcontext.elementType], tcontext.elementName); bin_size = 1./freq/20; fprintf(stdout, " Bin size adjusted to %e\n", bin_size); fflush(stdout); } if (2*timeSpan>bin_size*n_bins) { fprintf(stdout, "%s %s has insufficient time span for initial bunch\n", entity_name[tcontext.elementType], tcontext.elementName); n_bins = pow(2, (long)(log(2*timeSpan*1.05/bin_size)/log(2)+1)); if (maxBins2<n_bins) { fprintf(stderr, " Maximum number of bins does not allow sufficient time span!\n"); exitElegant(1); } fprintf(stdout, " Number of bins adjusted to %ld\n", n_bins); fflush(stdout); } if (Q<1) /* Ideally, want frequency resolution < fResonance/200 and < fResonanceWidth/200 */ factor = 200/(n_bins*bin_size*freq/Q); else factor = 200/(n_bins*bin_size*freq); if (factor>1) { fprintf(stdout, "%s %s has too few bins or excessively small bin size for given frequency\n", entity_name[tcontext.elementType], tcontext.elementName); if (n_bins*factor>maxBins2) { if ((n_bins*factor)/maxBins2>50) { if (Q<1) fprintf(stdout, " With %ld bins, the frequency resolution is only %.1g times the resonant frequency\n", maxBins2, freq*maxBins2*bin_size); else fprintf(stdout, " With %ld bins, the frequency resolution is only %.1g times the resonance width\n", maxBins2, freq/Q*maxBins2*bin_size); fprintf(stdout, " It isn't possible to model this situation accurately with %ld bins. Consider the RFMODE or TRFMODE element.\n", maxBins2); fprintf(stdout, " Alternatively, consider increasing your bin size or maximum number of bins\n"); exitElegant(1); } n_bins = maxBins2; fprintf(stdout, " Number of bins adjusted to %ld\n", n_bins); } else { n_bins = pow(2, (long)(log(n_bins*factor)/log(2)+1)); fprintf(stdout, " Number of bins adjusted to %ld\n", n_bins); } fflush(stdout); } *nBins = n_bins; *binSize = bin_size; }
void track_through_ztransverse(double **part, long np, ZTRANSVERSE *ztransverse, double Po, RUN *run, long i_pass, CHARGE *charge ) { static double *posItime[2] = {NULL, NULL}; /* array for particle density times x, y*/ static double *posIfreq; /* array for FFT of particle density times x or y*/ static double *Vtime = NULL; /* array for voltage acting on each bin */ static long max_n_bins = 0; static long *pbin = NULL; /* array to record which bin each particle is in */ static double *time = NULL; /* array to record arrival time of each particle */ static double *pz = NULL; static long max_np = 0; double *Vfreq, *iZ; #if USE_MPI long i; #endif long ib, nb, n_binned, nfreq, iReal, iImag, plane, first; double factor, tmin, tmax, tmean, dt, userFactor[2], rampFactor=1; static long not_first_call = -1; long ip, ip1, ip2, bunches, bunch, npb, i_pass0; long bucketEnd[MAX_BUCKETS]; #if USE_MPI float *buffer_send, *buffer_recv; #endif #if defined(DEBUG) FILE *fp; #endif i_pass0 = i_pass; if ((i_pass -= ztransverse->startOnPass)<0) return; if (i_pass>=(ztransverse->rampPasses-1)) rampFactor = 1; else rampFactor = (i_pass+1.0)/ztransverse->rampPasses; not_first_call += 1; #if (!USE_MPI) if (np>max_np) { pbin = trealloc(pbin, sizeof(*pbin)*(max_np=np)); time = trealloc(time, sizeof(*time)*max_np); pz = trealloc(pz, sizeof(*pz)*max_np); } #else if (USE_MPI) { long np_total; if (isSlave) { MPI_Allreduce(&np, &np_total, 1, MPI_LONG, MPI_SUM, workers); if (np_total>max_np) { /* if the total number of particles is increased, we do reallocation for every CPU */ pbin = trealloc(pbin, sizeof(*pbin)*(max_np=np)); time = trealloc(time, sizeof(*time)*max_np); pz = trealloc(pz, sizeof(*pz)*max_np); max_np = np_total; /* max_np should be the sum across all the processors */ } } } #endif if ((part[0][6]-floor(part[0][6]))!=0) { /* This is a kludgey way to determine that particles have been assigned to buckets */ printf("Bunched beam detected\n"); fflush(stdout); #if USE_MPI if (n_processors!=1) { printf("Error (ZTRANSVERSE): must have bunch_frequency=0 for parallel mode.\n"); MPI_Barrier(MPI_COMM_WORLD); /* Make sure the information can be printed before aborting */ MPI_Abort(MPI_COMM_WORLD, 2); } #endif /* Start by sorting in bucket order */ qsort(part[0], np, COORDINATES_PER_PARTICLE*sizeof(double), comp_BucketNumbers); /* Find the end of the buckets in the particle list */ bunches = 0; for (ip=1; ip<np; ip++) { if ((part[ip-1][6]-floor(part[ip-1][6]))!=(part[ip][6]-floor(part[ip][6]))) { /* printf("Bucket %ld ends with ip=%ld\n", bunches, ip-1); fflush(stdout); */ bucketEnd[bunches++] = ip-1; if (bunches>=MAX_BUCKETS) { bombElegant("Error (wake): maximum number of buckets was exceeded", NULL); } } } bucketEnd[bunches++] = np-1; } else { bunches = 1; bucketEnd[0] = np-1; } /* printf("Bucket %ld ends with ip=%ld\n", bunches, bucketEnd[bunches-1]); fflush(stdout); */ ip2 = -1; for (bunch=0; bunch<bunches; bunch++) { ip1 = ip2+1; ip2 = bucketEnd[bunch]; npb = ip2-ip1+1; /* printf("Processing bunch %ld with %ld particles\n", bunch, npb); fflush(stdout); */ /* Compute time coordinate of each particle */ tmean = computeTimeCoordinates(time+ip1, Po, part+ip1, npb); find_min_max(&tmin, &tmax, time+ip1, npb); #if USE_MPI find_global_min_max(&tmin, &tmax, np, workers); #endif if (bunch==0) { /* use np here since we need to compute the macroparticle charge */ set_up_ztransverse(ztransverse, run, i_pass, np, charge, tmax-tmin); } nb = ztransverse->n_bins; dt = ztransverse->bin_size; tmin -= dt; tmax -= dt; if ((tmax-tmin)*2>nb*dt) { TRACKING_CONTEXT tcontext; getTrackingContext(&tcontext); fprintf(stderr, "%s %s: Time span of bunch (%le s) is more than half the total time span (%le s).\n", entity_name[tcontext.elementType], tcontext.elementName, tmax-tmin, nb*dt); fprintf(stderr, "If using broad-band impedance, you should increase the number of bins and rerun.\n"); fprintf(stderr, "If using file-based impedance, you should increase the number of data points or decrease the frequency resolution.\n"); exitElegant(1); } if (nb>max_n_bins) { posItime[0] = trealloc(posItime[0], 2*sizeof(**posItime)*(max_n_bins=nb)); posItime[1] = trealloc(posItime[1], 2*sizeof(**posItime)*(max_n_bins=nb)); posIfreq = trealloc(posIfreq, 2*sizeof(*posIfreq)*(max_n_bins=nb)); Vtime = trealloc(Vtime, 2*sizeof(*Vtime)*(max_n_bins+1)); } for (ib=0; ib<nb; ib++) posItime[0][2*ib] = posItime[0][2*ib+1] = posItime[1][2*ib] = posItime[1][2*ib+1] = 0; /* make arrays of I(t)*x and I(t)*y */ n_binned = binTransverseTimeDistribution(posItime, pz, pbin, tmin, dt, nb, time+ip1, part+ip1, Po, npb, ztransverse->dx, ztransverse->dy, ztransverse->xDriveExponent, ztransverse->yDriveExponent); #if (!USE_MPI) if (n_binned!=npb) { fprintf(stdout, "Warning: only %ld of %ld particles were binned (ZTRANSVERSE)!\n", n_binned, npb); if (!not_first_call) { fprintf(stdout, "*** This may produce unphysical results. Your wake needs smaller frequency\n"); fprintf(stdout, " spacing to cover a longer time span.\n"); } fflush(stdout); } #else if (USE_MPI) { int all_binned, result = 1; if (isSlave) result = ((n_binned==np) ? 1 : 0); MPI_Allreduce(&result, &all_binned, 1, MPI_INT, MPI_LAND, workers); if (!all_binned) { if (myid==1) { /* This warning will be given only if the flag MPI_DEBUG is defined for the Pelegant */ fprintf(stdout, "warning: Not all of %ld particles were binned (WAKE)\n", np); fprintf(stdout, "consider setting n_bins=0 in WAKE definition to invoke autoscaling\n"); fflush(stdout); } } } #endif userFactor[0] = ztransverse->factor*ztransverse->xfactor*rampFactor; userFactor[1] = ztransverse->factor*ztransverse->yfactor*rampFactor; first = 1; for (plane=0; plane<2; plane++) { #if USE_MPI /* This could be good for some advanced network structures */ /* if (isSlave) { double buffer[nb]; MPI_Allreduce(posItime[plane], buffer, nb, MPI_DOUBLE, MPI_SUM, workers); memcpy(posItime[plane], buffer, sizeof(double)*nb); } */ if (isSlave) { buffer_send = malloc(sizeof(float) * nb); buffer_recv = malloc(sizeof(float) * nb); for (i=0; i<nb; i++) buffer_send[i] = posItime[plane][i]; MPI_Reduce(buffer_send, buffer_recv, nb, MPI_FLOAT, MPI_SUM, 1, workers); MPI_Bcast(buffer_recv, nb, MPI_FLOAT, 1, workers); for (i=0; i<nb; i++) posItime[plane][i] = buffer_recv[i]; free(buffer_send); free(buffer_recv); } #endif if (userFactor[plane]==0) { for (ib=0; ib<nb; ib++) Vtime[ib] = 0; } else { if (ztransverse->smoothing) SavitzyGolaySmooth(posItime[plane], nb, ztransverse->SGOrder, ztransverse->SGHalfWidth, ztransverse->SGHalfWidth, 0); /* Take the FFT of (x*I)(t) to get (x*I)(f) */ memcpy(posIfreq, posItime[plane], 2*nb*sizeof(*posIfreq)); realFFT(posIfreq, nb, 0); /* Compute V(f) = i*Z(f)*(x*I)(f), putting in a factor * to normalize the current waveform */ Vfreq = Vtime; factor = ztransverse->macroParticleCharge*particleRelSign/dt*userFactor[plane]; iZ = ztransverse->iZ[plane]; Vfreq[0] = posIfreq[0]*iZ[0]*factor; nfreq = nb/2 + 1; if (nb%2==0) /* Nyquist term */ Vfreq[nb-1] = posIfreq[nb-1]*iZ[nb-1]*factor; for (ib=1; ib<nfreq-1; ib++) { iImag = (iReal = 2*ib-1)+1; /* The signs are chosen here to get agreement with TRFMODE. In particular, test particles following closely behind the drive particle get defocused. */ Vfreq[iReal] = (posIfreq[iReal]*iZ[iImag] + posIfreq[iImag]*iZ[iReal])*factor; Vfreq[iImag] = -(posIfreq[iReal]*iZ[iReal] - posIfreq[iImag]*iZ[iImag])*factor; } /* Compute inverse FFT of V(f) to get V(t) */ realFFT(Vfreq, nb, INVERSE_FFT); Vtime = Vfreq; /* change particle transverse momenta to reflect voltage in relevant bin */ applyTransverseWakeKicks(part+ip1, time+ip1, pz, pbin, npb, Po, plane, Vtime, nb, tmin, dt, ztransverse->interpolate, plane==0?ztransverse->xProbeExponent:ztransverse->yProbeExponent); } if (ztransverse->SDDS_wake_initialized && ztransverse->wakes) { /* wake potential output */ factor = ztransverse->macroParticleCharge*particleRelSign/dt; if ((ztransverse->wake_interval<=0 || ((i_pass0-ztransverse->wake_start)%ztransverse->wake_interval)==0) && i_pass0>=ztransverse->wake_start && i_pass0<=ztransverse->wake_end) { if (first && !SDDS_StartTable(&ztransverse->SDDS_wake, nb)) { SDDS_SetError("Problem starting SDDS table for wake output (track_through_ztransverse)"); SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } for (ib=0; ib<nb; ib++) { if (!SDDS_SetRowValues(&ztransverse->SDDS_wake, SDDS_SET_BY_INDEX|SDDS_PASS_BY_VALUE, ib, 0, ib*dt, 1+plane*2, posItime[plane][ib]*factor, 2+plane*2, Vtime[ib], -1)) { SDDS_SetError("Problem setting rows of SDDS table for wake output (track_through_ztransverse)"); SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } } if (!SDDS_SetParameters(&ztransverse->SDDS_wake, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE, "Pass", i_pass0, "q", ztransverse->macroParticleCharge*particleRelSign*np, NULL)) { SDDS_SetError("Problem setting parameters of SDDS table for wake output (track_through_ztransverse)"); SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } if (ztransverse->broad_band) { if (!SDDS_SetParameters(&ztransverse->SDDS_wake, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE, "Rs", ztransverse->Rs, "fo", ztransverse->freq, "Deltaf", ztransverse->bin_size, NULL)) { SDDS_SetError("Problem setting parameters of SDDS table for wake output (track_through_ztransverse)"); SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } } if (!first) { if (!SDDS_WriteTable(&ztransverse->SDDS_wake)) { SDDS_SetError("Problem writing SDDS table for wake output (track_through_ztransverse)"); SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } if (!inhibitFileSync) SDDS_DoFSync(&ztransverse->SDDS_wake); } } } first = 0; } } #if defined(MIMIMIZE_MEMORY) free(posItime[0]); free(posItime[1]); free(posIfreq); free(Vtime); free(pbin); free(time); free(pz); posItime[0] = posItime[1] = Vtime = time = pz = posIfreq = NULL; pbin = NULL; max_n_bins = max_np = 0 ; #endif }