AmpTools
AmpVecs.cc
Go to the documentation of this file.
1 //******************************************************************************
2 // This file is part of AmpTools, a package for performing Amplitude Analysis
3 //
4 // Copyright Trustees of Indiana University 2010, all rights reserved
5 //
6 // This software written by Matthew Shepherd, Ryan Mitchell, and
7 // Hrayr Matevosyan at Indiana University, Bloomington
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 // 1. Redistributions of source code must retain the above copyright
13 // notice and author attribution, this list of conditions and the
14 // following disclaimer.
15 // 2. Redistributions in binary form must reproduce the above copyright
16 // notice and author attribution, this list of conditions and the
17 // following disclaimer in the documentation and/or other materials
18 // provided with the distribution.
19 // 3. Neither the name of the University nor the names of its contributors
20 // may be used to endorse or promote products derived from this software
21 // without specific prior written permission.
22 //
23 // Creation of derivative forms of this software for commercial
24 // utilization may be subject to restriction; written permission may be
25 // obtained from the Trustees of Indiana University.
26 //
27 // INDIANA UNIVERSITY AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES,
28 // EXPRESS OR IMPLIED. By way of example, but not limitation, INDIANA
29 // UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCANTABILITY OR
30 // FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THIS SOFTWARE OR
31 // DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS,
32 // OR OTHER RIGHTS. Neither Indiana University nor the authors shall be
33 // held liable for any liability with respect to any claim by the user or
34 // any other party arising from use of the program.
35 //******************************************************************************
36 
37 #include <cassert>
38 
39 #include "IUAmpTools/AmpVecs.h"
41 #include "IUAmpTools/DataReader.h"
42 #include "IUAmpTools/Kinematics.h"
43 
44 #ifdef GPU_ACCELERATION
45 #include "GPUManager/GPUManager.h"
46 #include "cuda_runtime.h"
47 #endif //GPU_ACCELERATION
48 
50 
51  m_iNEvents = 0 ;
52  m_iNTrueEvents = 0 ;
53  m_dAbsSumWeights = 0 ;
54  m_iNParticles = 0 ;
55  m_iNTerms = 0 ;
56  m_maxFactPerEvent = 0 ;
57 
58  m_pdData = 0 ;
59  m_pdWeights = 0 ;
60 
61  m_pdAmps = 0 ;
62  m_pdAmpFactors = 0 ;
63 
64  m_pdIntensity = 0 ;
65  m_pdIntegralMatrix = 0 ;
66 
67  m_termsValid = false ;
68  m_integralValid = false ;
69 }
70 
71 
72 void
74 {
75 
76  m_iNEvents = 0 ;
77  m_iNTrueEvents = 0 ;
78  m_dAbsSumWeights = 0 ;
79  m_iNParticles = 0 ;
80  m_iNTerms = 0 ;
81  m_maxFactPerEvent = 0 ;
82 
83  m_termsValid = false ;
84  m_integralValid = false ;
85 
86  if(m_pdData)
87  delete[] m_pdData;
88  m_pdData=0;
89 
90  if(m_pdWeights)
91  delete[] m_pdWeights;
92  m_pdWeights=0;
93 
94  if(m_pdIntensity)
95  delete[] m_pdIntensity;
96  m_pdIntensity=0;
97 
99  delete[] m_pdIntegralMatrix;
101 
102 #ifndef GPU_ACCELERATION
103 
104  if(m_pdAmps)
105  delete[] m_pdAmps;
106  m_pdAmps=0;
107 
108  if(m_pdAmpFactors)
109  delete[] m_pdAmpFactors;
110  m_pdAmpFactors=0;
111 
112 #else
113  //Deallocate "pinned memory"
114  if(m_pdAmps)
115  cudaFreeHost(m_pdAmps);
116  m_pdAmps=0;
117 
118  if(m_pdAmpFactors)
119  cudaFreeHost(m_pdAmpFactors);
120  m_pdAmpFactors=0;
121 
122  m_gpuMan.clearAll();
123 
124 #endif // GPU_ACCELERATION
125 }
126 
127 void
128 AmpVecs::loadEvent( const Kinematics* pKinematics, unsigned long long iEvent,
129  unsigned long long iNTrueEvents, bool bForceNegativeWeight ){
130 
131  // allocate memory and set variables
132  // if this is the first call to this method
133 
134  if (m_pdData == NULL){
135 
136  m_iNTrueEvents = iNTrueEvents;
137  m_iNEvents = iNTrueEvents;
138 
139 #ifdef GPU_ACCELERATION
140  m_iNEvents = GPUManager::calcNEventsGPU(iNTrueEvents);
141 #endif
142 
143  m_iNParticles = pKinematics->particleList().size();
144  assert(m_iNParticles);
145 
148 
149  }
150 
151  // check to be sure we won't exceed the bounds of the array
152  assert( iEvent < m_iNEvents );
153 
154  // for cpu calculations, fill the m_pdData array in this order:
155  // e(p1,ev1), px(p1,ev1), py(p1,ev1), pz(p1,ev1),
156  // e(p2,ev1), px(p2,ev1), ...,
157  // e(p1,ev2), px(p1,ev2), ...
158  //
159  // for gpu calculations, fill the m_pdData array in this order:
160  // e(p1,ev1), e(p1,ev2), e(p1,ev3), ...,
161  // px(p1,ev1), px(p1,ev2), ...,
162  // e(p2,ev1), e(p2,ev2). ...
163  //
164  // where pn is particle n and evn is event n
165 
166 #ifndef GPU_ACCELERATION
167 
168  for (int iParticle = 0; iParticle < m_iNParticles; iParticle++){
169  m_pdData[4*iEvent*m_iNParticles+4*iParticle+0]=pKinematics->particle(iParticle).E();
170  m_pdData[4*iEvent*m_iNParticles+4*iParticle+1]=pKinematics->particle(iParticle).Px();
171  m_pdData[4*iEvent*m_iNParticles+4*iParticle+2]=pKinematics->particle(iParticle).Py();
172  m_pdData[4*iEvent*m_iNParticles+4*iParticle+3]=pKinematics->particle(iParticle).Pz();
173  }
174 #else
175  for (int iParticle = 0; iParticle < m_iNParticles; iParticle++){
176  m_pdData[(4*iParticle+0)*m_iNEvents+iEvent] = pKinematics->particle(iParticle).E();
177  m_pdData[(4*iParticle+1)*m_iNEvents+iEvent] = pKinematics->particle(iParticle).Px();
178  m_pdData[(4*iParticle+2)*m_iNEvents+iEvent] = pKinematics->particle(iParticle).Py();
179  m_pdData[(4*iParticle+3)*m_iNEvents+iEvent] = pKinematics->particle(iParticle).Pz();
180  }
181 #endif
182 
183  m_pdWeights[iEvent] = ( bForceNegativeWeight ?
184  -fabsf( pKinematics->weight() ) :
185  pKinematics->weight() );
186 
187  m_termsValid = false;
188  m_integralValid = false;
189 }
190 
191 
192 void
193 AmpVecs::loadData( DataReader* pDataReader, bool bForceNegativeWeight ){
194 
195  // Make sure no data is already loaded
196 
197  if( m_pdData!=0 || m_pdWeights!=0 ){
198  cout<<"\n ERROR: Trying to load data into a non-empty AmpVecs object\n"<<flush;
199  assert(false);
200  }
201 
202  // Get the number of events and reset the data reader
203 
204  pDataReader->resetSource();
205  m_iNTrueEvents = pDataReader->numEvents();
206 
207  if( m_iNTrueEvents < 1 ){
208  cout << "The data source is empty." << endl;
209  assert(false);
210  }
211 
212  // Loop over events and load each one individually
213 
214  Kinematics* pKinematics;
215  for(int iEvent = 0; iEvent < m_iNTrueEvents; iEvent++){
216  pKinematics = pDataReader->getEvent();
217  loadEvent(pKinematics, iEvent, m_iNTrueEvents, bForceNegativeWeight );
218  m_dAbsSumWeights += fabsf( pKinematics->weight() );
219  if (iEvent < (m_iNTrueEvents - 1)) delete pKinematics;
220  }
221 
222  // Fill any remaining space in the data array with the last event's kinematics
223 
224  for (unsigned long long int iEvent = m_iNTrueEvents; iEvent < m_iNEvents; iEvent++){
225  loadEvent(pKinematics, iEvent, m_iNTrueEvents, bForceNegativeWeight );
226  }
227  delete pKinematics;
228 
229  m_termsValid = false;
230  m_integralValid = false;
231 }
232 
233 
234 void
235 AmpVecs::allocateTerms( const IntensityManager& intenMan, bool bAllocIntensity ){
236 
237  m_iNTerms = intenMan.getTermNames().size();
239 
240  if( m_pdAmps!=0 || m_pdAmpFactors!=0 || m_pdIntensity!=0 )
241  {
242  cout << "ERROR: trying to reallocate terms in AmpVecs after\n" << flush;
243  cout << " they have already been allocated. Please\n" << flush;
244  cout << " deallocate them first." << endl;
245  assert(false);
246  }
247 
248  if (m_iNEvents == 0){
249  cout << "ERROR: trying to allocate space for terms in\n" << flush;
250  cout << " AmpVecs before any events have been loaded\n" << flush;
251  assert(false);
252  }
253 
255 
256  //Allocate the Intensity only when needed
257  if( bAllocIntensity )
258  {
260  }
261 
262 #ifndef GPU_ACCELERATION
263 
264  m_pdAmps = new GDouble[m_iNEvents * intenMan.termStoragePerEvent()];
266 
267 #else
268 
269  m_gpuMan.init( *this );
270  m_gpuMan.copyDataToGPU( *this );
271 
272 #endif // GPU_ACCELERATION
273 
274  m_termsValid = false;
275  m_integralValid = false;
276 }
277 
278 #ifdef GPU_ACCELERATION
279 void
281 
282  // we should start with unallocated memory
283  assert( m_pdAmps == NULL && m_pdAmpFactors == NULL );
284 
285  // allocate as "pinned memory" for fast CPU<->GPU memcopies
286  cudaMallocHost( (void**)&m_pdAmps, m_iNEvents * intenMan.termStoragePerEvent() * sizeof(GDouble) );
287  cudaMallocHost( (void**)&m_pdAmpFactors, m_iNEvents * m_maxFactPerEvent * sizeof(GDouble));
288 
289  cudaError_t cudaErr = cudaGetLastError();
290  if( cudaErr != cudaSuccess ){
291 
292  cout<<"\n\nHOST MEMORY ALLOCATION ERROR: "<< cudaGetErrorString( cudaErr ) << endl;
293  assert( false );
294  }
295 }
296 #endif
297 
298 Kinematics*
299 AmpVecs::getEvent( int iEvent ){
300 
301  // check to be sure the event request is realistic
302  assert( iEvent < m_iNTrueEvents );
303 
304  vector< TLorentzVector > particleList;
305 
306  for( int iPart = 0; iPart < m_iNParticles; ++iPart ){
307 
308  // packing is different for GPU and CPU
309 
310 #ifndef GPU_ACCELERATION
311 
312  int i = iEvent*4*m_iNParticles + 4*iPart;
313  particleList.push_back( TLorentzVector( m_pdData[i+1], m_pdData[i+2],
314  m_pdData[i+3], m_pdData[i] ) );
315 #else
316 
317  particleList.
318  push_back( TLorentzVector( m_pdData[(4*iPart+1)*m_iNEvents+iEvent],
319  m_pdData[(4*iPart+2)*m_iNEvents+iEvent],
320  m_pdData[(4*iPart+3)*m_iNEvents+iEvent],
321  m_pdData[(4*iPart+0)*m_iNEvents+iEvent] ) );
322 #endif // GPU_ACCELERATION
323  }
324 
325  return new Kinematics( particleList, m_pdWeights[iEvent] );
326 }
unsigned long long m_iNEvents
Definition: AmpVecs.h:68
const TLorentzVector & particle(unsigned int index) const
Definition: Kinematics.cc:53
void allocateTerms(const IntensityManager &intenMan, bool bAllocIntensity=false)
Definition: AmpVecs.cc:235
bool m_termsValid
Definition: AmpVecs.h:145
AmpVecs()
Definition: AmpVecs.cc:49
virtual unsigned int termStoragePerEvent() const =0
unsigned int m_maxFactPerEvent
Definition: AmpVecs.h:100
void init(const AmpVecs &a)
Definition: GPUManager.cc:161
GPUManager m_gpuMan
Definition: AmpVecs.h:159
void allocateCPUAmpStorage(const IntensityManager &intenMan)
Definition: AmpVecs.cc:280
void clearAll()
Definition: GPUManager.cc:484
double GDouble
void deallocAmpVecs()
Definition: AmpVecs.cc:73
bool m_integralValid
Definition: AmpVecs.h:153
GDouble * m_pdAmps
Definition: AmpVecs.h:117
const vector< string > & getTermNames() const
virtual unsigned int maxFactorStoragePerEvent() const =0
#define NULL
Definition: URtypes.h:72
virtual void resetSource()=0
unsigned long long m_iNTrueEvents
Definition: AmpVecs.h:75
GDouble * m_pdWeights
Definition: AmpVecs.h:111
double m_dAbsSumWeights
Definition: AmpVecs.h:83
const vector< TLorentzVector > & particleList() const
Definition: Kinematics.cc:47
virtual Kinematics * getEvent()=0
virtual unsigned int numEvents() const =0
unsigned int m_iNParticles
Definition: AmpVecs.h:88
void loadData(DataReader *pDataReader, bool bForceNegativeWeight=false)
Definition: AmpVecs.cc:193
GDouble * m_pdIntensity
Definition: AmpVecs.h:137
Kinematics * getEvent(int i)
Definition: AmpVecs.cc:299
GDouble * m_pdData
Definition: AmpVecs.h:106
static int calcNEventsGPU(int iNEvents)
Definition: GPUManager.h:104
void loadEvent(const Kinematics *pKinematics, unsigned long long iEvent=0, unsigned long long iNTrueEvents=1, bool bForceNegativeWeight=false)
Definition: AmpVecs.cc:128
GDouble * m_pdAmpFactors
Definition: AmpVecs.h:124
void copyDataToGPU(const AmpVecs &a)
Definition: GPUManager.cc:221
GDouble * m_pdIntegralMatrix
Definition: AmpVecs.h:132
float weight() const
Definition: Kinematics.h:187
unsigned int m_iNTerms
Definition: AmpVecs.h:94