All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Classes | Functions
Solver.h File Reference
#include <vector>
#include "larreco/SpacePointSolver/QuadExpr.h"

Go to the source code of this file.

Classes

class  WireHit
 
class  InductionWireHit
 
class  Neighbour
 
class  SpaceCharge
 
class  CollectionWireHit
 

Functions

double Metric (const std::vector< SpaceCharge * > &scs, double alpha)
 
double Metric (const std::vector< CollectionWireHit * > &cwires, double alpha)
 
QuadExpr Metric (const SpaceCharge *sci, const SpaceCharge *scj, double alpha)
 
double SolvePair (CollectionWireHit *cwire, SpaceCharge *sci, SpaceCharge *scj, double xmin, double xmax, double alpha)
 
void Iterate (CollectionWireHit *cwire, double alpha)
 
void Iterate (SpaceCharge *sc, double alpha)
 
void Iterate (const std::vector< CollectionWireHit * > &cwires, const std::vector< SpaceCharge * > &orphanSCs, double alpha)
 

Function Documentation

void Iterate ( CollectionWireHit cwire,
double  alpha 
)

Definition at line 263 of file Solver.cxx.

264 {
265  // Consider all pairs of crossings
266  const unsigned int N = cwire->fCrossings.size();
267 
268  for(unsigned int i = 0; i+1 < N; ++i){
269  SpaceCharge* sci = cwire->fCrossings[i];
270 
271  for(unsigned int j = i+1; j < N; ++j){
272  SpaceCharge* scj = cwire->fCrossings[j];
273 
274  const double x = SolvePair(cwire, sci, scj, alpha);
275 
276  if(x == 0) continue;
277 
278  // Actually make the update
279  sci->AddCharge(+x);
280  scj->AddCharge(-x);
281  } // end for j
282  } // end for i
283 }
void AddCharge(double dq)
Definition: Solver.cxx:35
bool sci
process_name opflash particleana ie x
std::vector< SpaceCharge * > fCrossings
Definition: Solver.h:73
double SolvePair(CollectionWireHit *cwire, SpaceCharge *sci, SpaceCharge *scj, double alpha)
Definition: Solver.cxx:217
process_name largeant stream1 can override from command line with o or output physics producers generator N
void Iterate ( SpaceCharge sc,
double  alpha 
)

Definition at line 286 of file Solver.cxx.

287 {
288  const QuadExpr chisq = Metric(sc, alpha);
289 
290  // Find the minimum of a quadratic expression
291  double x = -chisq.Linear()/(2*chisq.Quadratic());
292 
293  // Don't allow the SpaceCharge to go negative
294  const double xmin = -sc->fPred;
295 
296  // Clamp to allowed range
297  x = std::max(xmin, x);
298 
299  const double chisq_new = chisq.Eval(x);
300 
301  // Should try here too, because the function might be convex not concave, so
302  // d/dx=0 gives the max not the min, and the true min is at one extreme of
303  // the range.
304  const double chisq_n = chisq.Eval(xmin);
305 
306  if(chisq_n < chisq_new)
307  sc->AddCharge(xmin);
308  else
309  sc->AddCharge(x);
310 }
void AddCharge(double dq)
Definition: Solver.cxx:35
process_name opflash particleana ie x
double Linear() const
Definition: QuadExpr.h:16
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
double Metric(double q, double p)
Definition: Solver.cxx:71
double Eval(double x) const
Definition: QuadExpr.cxx:69
double fPred
Definition: Solver.h:58
double Quadratic() const
Definition: QuadExpr.h:15
void Iterate ( const std::vector< CollectionWireHit * > &  cwires,
const std::vector< SpaceCharge * > &  orphanSCs,
double  alpha 
)

Definition at line 313 of file Solver.cxx.

316 {
317  // Visiting in a "random" order helps prevent local artefacts that are slow
318  // to break up.
319  unsigned int cwireIdx = 0;
320  if (!cwires.empty()){
321  do{
322  Iterate(cwires[cwireIdx], alpha);
323 
324  const unsigned int prime = 1299827;
325  cwireIdx = (cwireIdx+prime)%cwires.size();
326  } while(cwireIdx != 0);
327  }
328 
329  for(SpaceCharge* sc: orphanSCs) Iterate(sc, alpha);
330 }
void Iterate(CollectionWireHit *cwire, double alpha)
Definition: Solver.cxx:263
double Metric ( const std::vector< SpaceCharge * > &  scs,
double  alpha 
)

Definition at line 83 of file Solver.cxx.

84 {
85  double ret = 0;
86 
87  std::set<InductionWireHit*> iwires;
88  for(const SpaceCharge* sc: scs){
89  if(sc->fWire1) iwires.insert(sc->fWire1);
90  if(sc->fWire2) iwires.insert(sc->fWire2);
91 
92  if(alpha != 0){
93  ret -= alpha*sqr(sc->fPred);
94  // "Double-counting" of the two ends of the connection is
95  // intentional. Otherwise we'd have a half in the line above.
96  ret -= alpha * sc->fPred * sc->fNeiPotential;
97  }
98  }
99 
100  for(const InductionWireHit* iwire: iwires){
101  ret += Metric(iwire->fCharge, iwire->fPred);
102  }
103 
104  return ret;
105 }
constexpr T sqr(T v)
double Metric(double q, double p)
Definition: Solver.cxx:71
double Metric ( const std::vector< CollectionWireHit * > &  cwires,
double  alpha 
)

Definition at line 108 of file Solver.cxx.

109 {
110  std::vector<SpaceCharge*> scs;
111  for(CollectionWireHit* cwire: cwires)
112  scs.insert(scs.end(), cwire->fCrossings.begin(), cwire->fCrossings.end());
113  return Metric(scs, alpha);
114 }
double Metric(double q, double p)
Definition: Solver.cxx:71
QuadExpr Metric ( const SpaceCharge sci,
const SpaceCharge scj,
double  alpha 
)

Definition at line 117 of file Solver.cxx.

118 {
119  QuadExpr ret = 0;
120 
121  // How much charge moves from scj to sci
122  QuadExpr x = QuadExpr::X();
123 
124  if(alpha != 0){
125  const double scip = sci->fPred;
126  const double scjp = scj->fPred;
127 
128  // Self energy. SpaceCharges are never the same object
129  ret -= alpha*sqr(scip + x);
130  ret -= alpha*sqr(scjp - x);
131 
132  // Interaction. We're only seeing one end of the double-ended connection
133  // here, so multiply by two.
134  ret -= 2 * alpha * (scip + x) * sci->fNeiPotential;
135  ret -= 2 * alpha * (scjp - x) * scj->fNeiPotential;
136 
137  // This miscounts if i and j are neighbours of each other
138  for(const Neighbour& n: sci->fNeighbours){
139  if(n.fSC == scj){
140  // If we detect that case, remove the erroneous terms
141  ret += 2 * alpha * (scip + x) * scjp * n.fCoupling;
142  ret += 2 * alpha * (scjp - x) * scip * n.fCoupling;
143 
144  // And replace with the correct interaction terms
145  ret -= 2 * alpha * (scip + x) * (scjp - x) * n.fCoupling;
146  break;
147  }
148  }
149  }
150 
151 
152  const InductionWireHit* iwire1 = sci->fWire1;
153  const InductionWireHit* jwire1 = scj->fWire1;
154 
155  const double qi1 = iwire1 ? iwire1->fCharge : 0;
156  const double pi1 = iwire1 ? iwire1->fPred : 0;
157 
158  const double qj1 = jwire1 ? jwire1->fCharge : 0;
159  const double pj1 = jwire1 ? jwire1->fPred : 0;
160 
161  if(iwire1 == jwire1){
162  // Same wire means movement of charge cancels itself out
163  if(iwire1) ret += Metric(qi1, pi1);
164  }
165  else{
166  if(iwire1) ret += Metric(qi1, pi1 + x);
167  if(jwire1) ret += Metric(qj1, pj1 - x);
168  }
169 
170  const InductionWireHit* iwire2 = sci->fWire2;
171  const InductionWireHit* jwire2 = scj->fWire2;
172 
173  const double qi2 = iwire2 ? iwire2->fCharge : 0;
174  const double pi2 = iwire2 ? iwire2->fPred : 0;
175 
176  const double qj2 = jwire2 ? jwire2->fCharge : 0;
177  const double pj2 = jwire2 ? jwire2->fPred : 0;
178 
179  if(iwire2 == jwire2){
180  if(iwire2) ret += Metric(qi2, pi2);
181  }
182  else{
183  if(iwire2) ret += Metric(qi2, pi2 + x);
184  if(jwire2) ret += Metric(qj2, pj2 - x);
185  }
186 
187  return ret;
188 }
process_name opflash particleana ie x
double fCharge
Definition: Solver.h:25
double fPred
Definition: Solver.h:27
double fCoupling
Definition: Solver.h:37
std::vector< Neighbour > fNeighbours
Definition: Solver.h:56
double fNeiPotential
Neighbour-induced potential.
Definition: Solver.h:59
InductionWireHit * fWire2
Definition: Solver.h:54
static QuadExpr X()
Definition: QuadExpr.cxx:8
constexpr T sqr(T v)
InductionWireHit * fWire1
Definition: Solver.h:54
double Metric(double q, double p)
Definition: Solver.cxx:71
double fPred
Definition: Solver.h:58
SpaceCharge * fSC
Definition: Solver.h:36
double SolvePair ( CollectionWireHit cwire,
SpaceCharge sci,
SpaceCharge scj,
double  xmin,
double  xmax,
double  alpha 
)