MercuryDPM  0.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HGridOptimiser.cc
Go to the documentation of this file.
1 //Copyright (c) 2013-2014, The MercuryDPM Developers Team. All rights reserved.
2 //For the list of developers, see <http://www.MercuryDPM.org/Team>.
3 //
4 //Redistribution and use in source and binary forms, with or without
5 //modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name MercuryDPM nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 //DISCLAIMED. IN NO EVENT SHALL THE MERCURYDPM DEVELOPERS TEAM BE LIABLE FOR ANY
19 //DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 //(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 //ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 //(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #include <iostream>
27 #include <iomanip>
28 #include <limits>
29 #include <math.h>
30 #include "HGridOptimiser.h"
31 #include "Particles/BaseParticle.h"
32 
33 void HGridOptimiser::Initialise(HGRID_base& problem, int verbosity)
34 {
35  NCells=100;
36  k=0.2;
37  CellN.resize(NCells);
38  for (std::vector<int>::iterator it = CellN.begin() ; it != CellN.end(); ++it)
39  {
40  *it=0;
41  }
42 
44  rMax=nextafter(problem.getParticleHandler().getLargestParticle()->get_InteractionRadius(),std::numeric_limits<double>::max());
45  for (std::vector<BaseParticle*>::iterator it = problem.getParticleHandler().begin() ; it != problem.getParticleHandler().end(); ++it)
46  {
47  CellN[radius2Cell((*it)->get_InteractionRadius())]++;
48  }
50 
51  if(verbosity>0)
52  {
53  std::cout<<"rMin="<<rMin<<" rMax="<<rMax<<" NParticles="<<NParticles<<std::endl;
54  for (unsigned int i=0;i<CellN.size();i++)
55  {
56  std::cout<<"From"<<std::setw(8)<<cell2Min(i)<<" to"<<std::setw(8)<<cell2Max(i)<<" number="<<std::setw(5)<<CellN[i]<<std::endl;
57  }
58  std::cout<<"Domain size ["<<problem.get_xmin()<<","<<problem.get_xmax()<<"]x["<<problem.get_ymin()<<","<<problem.get_ymax()<<"]x["<<problem.get_zmin()<<","<<problem.get_zmax()<<"]"<<std::endl;
59  /*std::cout<<"["<<CellN[0];
60  for (unsigned int i=1;i<CellN.size();i++)
61  {
62  std::cout<<","<<CellN[i];
63  }
64  std::cout<<"]"<<std::endl;*/
65  }
66 
67  dimension=problem.get_dim();
68  switch(dimension)
69  {
70  case 1:
71  length=pow((problem.get_xmax()-problem.get_xmin())/NParticles,1);
72  case 2:
73  length=pow((problem.get_xmax()-problem.get_xmin())*(problem.get_ymax()-problem.get_ymin())/NParticles,1.0/2.0);
74  case 3:
75  length=pow((problem.get_xmax()-problem.get_xmin())*(problem.get_ymax()-problem.get_ymin())*(problem.get_zmax()-problem.get_zmin())/NParticles,1.0/3.0);
76  }
77 }
78 
80 {
81  int y=floor(NCells*(r-rMin)/(rMax-rMin));
82  if(y<0) y=0;
83  if(y>=NCells) y=NCells-1;
84  return y;
85 }
87 {
88  return rMin+(rMax-rMin)*i/NCells;
89 }
91 {
92  return rMin+(rMax-rMin)*(i+1)/NCells;
93 }
94 
97 double HGridOptimiser::pdfInt(double start, double end, int p)
98 {
99  int startCell=radius2Cell(start);
100  int endCell=radius2Cell(end);
101  if(startCell<0||startCell>=NCells)
102  {
103  std::cout<<"Error in startCell (startCell="<<startCell<<" start="<<start<<" rMin="<<rMin<<" rMax="<<rMax<<" NCells="<<NCells<<std::endl;
104  }
105  if(endCell<0||endCell>=NCells)
106  {
107  std::cout<<"Error in endCell (endCell="<<endCell<<" end="<<end<<" rMin="<<rMin<<" rMax="<<rMax<<" NCells="<<NCells<<std::endl;
108  }
109 
110  double teller=0;
111  if(startCell==endCell)
112  {
113  teller=CellN[startCell]/(p+1)*(pow(end,p+1)-pow(start,p+1));
114  }
115  else if(endCell<startCell)
116  {
117  teller=0;
118  }
119  else
120  {
121  teller=CellN[startCell]/(p+1)*(pow(cell2Max(startCell),p+1)-pow(start,p+1));
122  for(int i=startCell+1;i<endCell;i++)
123  {
124  teller+=CellN[i]/(p+1)*(pow(cell2Max(i),p+1)-pow(cell2Min(i),p+1));
125  }
126  teller+=CellN[endCell]/(p+1)*(pow(end,p+1)-pow(cell2Min(endCell),p+1));
127  }
128  double noemer=0;
129  for(int i=0;i<NCells;i++)
130  {
131  noemer+=CellN[i]*(cell2Max(i)-cell2Min(i));
132  }
133  return teller/noemer;
134 }
135 
137 double HGridOptimiser::diffPdfInt(double x, int p)
138 {
139  int xCell=radius2Cell(x);
140  double noemer=0;
141  for(int i=0;i<NCells;i++)
142  {
143  noemer+=CellN[i]*(cell2Max(i)-cell2Min(i));
144  }
145  return CellN[xCell]*pow(x,p)/noemer;
146 }
147 
148 
152 double HGridOptimiser::expectedCellsIntegral(double start, double end, int p, double h)
153 {
154  int startCell=radius2Cell(start);
155  int endCell=radius2Cell(end);
156 
157  double teller=0;
158  double noemer=0;
159  if(startCell==endCell)
160  {
161  teller=CellN[startCell]*h/2/(p+1)*(pow(2/h*end+2,p+1)-pow(2/h*start+2,p+1));
162  noemer=CellN[startCell]*(end-start);
163  }
164  else
165  {
166  teller=CellN[startCell]*h/2/(p+1)*(pow(2/h*cell2Max(startCell)+2,p+1)-pow(2/h*start+2,p+1));
167  noemer=CellN[startCell]*(cell2Max(startCell)-start);
168  for(int i=startCell+1;i<endCell;i++)
169  {
170  teller+=CellN[i]*h/2/(p+1)*(pow(2/h*cell2Max(i)+2,p+1)-pow(2/h*cell2Min(i)+2,p+1));
171  noemer+=CellN[i]*(cell2Max(i)-cell2Min(i));
172  }
173  teller+=CellN[endCell]*h/2/(p+1)*(pow(2/h*end+2,p+1)-pow(2/h*cell2Min(endCell)+2,p+1));
174  noemer+=CellN[endCell]*(end-cell2Min(endCell));
175  }
176  if(noemer==0)
177  return 0;
178  else
179  return teller/noemer;
180 }
181 
182 double HGridOptimiser::diffStartExpectedCellsIntegral(double start, double end, int p, double h)
183 {
184  int startCell=radius2Cell(start);
185  int endCell=radius2Cell(end);
186 
187  double teller=0;
188  double noemer=0;
189  double diffTeller=-CellN[startCell]*(pow(2/h*start+2,p));
190  double diffNoemer=-CellN[startCell];
191  if(startCell==endCell)
192  {
193  teller=CellN[startCell]*h/2/(p+1)*(pow(2/h*end+2,p+1)-pow(2/h*start+2,p+1));
194  noemer=CellN[startCell]*(end-start);
195  }
196  else
197  {
198  teller=CellN[startCell]*h/2/(p+1)*(pow(2/h*cell2Max(startCell)+2,p+1)-pow(2/h*start+2,p+1));
199  noemer=CellN[startCell]*(cell2Max(startCell)-start);
200  for(int i=startCell+1;i<endCell;i++)
201  {
202  teller+=CellN[i]*h/2/(p+1)*(pow(2/h*cell2Max(i)+2,p+1)-pow(2/h*cell2Min(i)+2,p+1));
203  noemer+=CellN[i]*(cell2Max(i)-cell2Min(i));
204  }
205  teller+=CellN[endCell]*h/2/(p+1)*(pow(2/h*end+2,p+1)-pow(2/h*cell2Min(endCell)+2,p+1));
206  noemer+=CellN[endCell]*(end-cell2Min(endCell));
207  }
208  if(noemer==0)
209  return 0;
210  else
211  return (diffTeller*noemer-teller*diffNoemer)/(noemer*noemer);
212 }
213 
214 double HGridOptimiser::diffEndExpectedCellsIntegral(double start, double end, int p, double h)
215 {
216  int startCell=radius2Cell(start);
217  int endCell=radius2Cell(end);
218 
219  double teller=0;
220  double noemer=0;
221  double diffTeller=CellN[endCell]*(pow(2/h*end+2,p));
222  double diffNoemer=CellN[endCell];
223  if(startCell==endCell)
224  {
225  teller=CellN[startCell]*h/2/(p+1)*(pow(2/h*end+2,p+1)-pow(2/h*start+2,p+1));
226  noemer=CellN[startCell]*(end-start);
227  }
228  else
229  {
230  teller=CellN[startCell]*h/2/(p+1)*(pow(2/h*cell2Max(startCell)+2,p+1)-pow(2/h*start+2,p+1));
231  noemer=CellN[startCell]*(cell2Max(startCell)-start);
232  for(int i=startCell+1;i<endCell;i++)
233  {
234  teller+=CellN[i]*h/2/(p+1)*(pow(2/h*cell2Max(i)+2,p+1)-pow(2/h*cell2Min(i)+2,p+1));
235  noemer+=CellN[i]*(cell2Max(i)-cell2Min(i));
236  }
237  teller+=CellN[endCell]*h/2/(p+1)*(pow(2/h*end+2,p+1)-pow(2/h*cell2Min(endCell)+2,p+1));
238  noemer+=CellN[endCell]*(end-cell2Min(endCell));
239  }
240  if(noemer==0)
241  return 0;
242  else
243  return (diffTeller*noemer-teller*diffNoemer)/(noemer*noemer);
244 }
245 
246 double HGridOptimiser::diffHExpectedCellsIntegral(double start, double end, int p, double h)
247 {
248  int startCell=radius2Cell(start);
249  int endCell=radius2Cell(end);
250 
251  double teller=0;
252  double noemer=0;
253  double diffTeller=0;
254  if(startCell==endCell)
255  {
256  teller=CellN[startCell]*h/2/(p+1)*(pow(2/h*end+2,p+1)-pow(2/h*start+2,p+1));
257  diffTeller=CellN[startCell]/2/(p+1)*(pow(2/h*end+2,p+1)-pow(2/h*start+2,p+1))-CellN[startCell]/h*(end*pow(2/h*end+2,p)-start*pow(2/h*start+2,p));
258  noemer=CellN[startCell]*(end-start);
259  }
260  else
261  {
262  teller =0.5*CellN[startCell]*h/(p+1)*(pow(2/h*cell2Max(startCell)+2,p+1)-pow(2/h*start+2,p+1));
263  diffTeller=0.5*CellN[startCell] /(p+1)*(pow(2/h*cell2Max(startCell)+2,p+1)-pow(2/h*start+2,p+1))-CellN[startCell]/h*(cell2Max(startCell)*pow(2/h*cell2Max(startCell)+2,p)-start*pow(2/h*start+2,p));
264  noemer=CellN[startCell]*(cell2Max(startCell)-start);
265  for(int i=startCell+1;i<endCell;i++)
266  {
267  teller +=0.5*CellN[i]*h/(p+1)*(pow(2/h*cell2Max(i)+2,p+1)-pow(2/h*cell2Min(i)+2,p+1));
268  diffTeller+=0.5*CellN[i] /(p+1)*(pow(2/h*cell2Max(i)+2,p+1)-pow(2/h*cell2Min(i)+2,p+1))-CellN[i]/h*(cell2Max(i)*pow(2/h*cell2Max(i)+2,p)-cell2Min(i)*pow(2/h*cell2Min(i)+2,p));
269  noemer+=CellN[i]*(cell2Max(i)-cell2Min(i));
270  }
271  teller +=0.5*CellN[endCell]*h/(p+1)*(pow(2/h*end+2,p+1)-pow(2/h*cell2Min(endCell)+2,p+1));
272  diffTeller+=0.5*CellN[endCell] /(p+1)*(pow(2/h*end+2,p+1)-pow(2/h*cell2Min(endCell)+2,p+1))-CellN[endCell]/h*(end*pow(2/h*end+2,p)-cell2Min(endCell)*pow(2/h*cell2Min(endCell)+2,p));
273  noemer+=CellN[endCell]*(end-cell2Min(endCell));
274  }
275  if(noemer==0)
276  return 0;
277  else
278  return diffTeller/noemer;
279 }
280 
281 void HGridOptimiser::calculateDiffWork(std::vector<double>& hGridCellSizes, std::vector<double>& dfdx, HGridMethod method, int verbosity)
282 {
283  unsigned int NLevels=hGridCellSizes.size()-1;
284  unsigned int NParams=hGridCellSizes.size();
285 
286  if(verbosity>0)
287  {
288  std::cout<<"Length scale="<<length<<std::endl;
289  }
290  if(verbosity>0)
291  {
292  std::cout<<"Level sizes:";
293  for(unsigned int i=0;i<NParams;i++)
294  {
295  std::cout<<" "<<hGridCellSizes[i];
296  }
297  std::cout<<std::endl;
298  }
299 
300  std::vector<double> particlesPerLevel;
301  for(unsigned int i=0;i<NLevels;i++)
302  {
303  particlesPerLevel.push_back(pdfInt(0.5*hGridCellSizes[i],0.5*hGridCellSizes[i+1],0));
304  if(particlesPerLevel.back()<0)
305  {
306  particlesPerLevel.back()=0;
307  }
308  }
309  if(verbosity>0)
310  {
311  std::cout<<"Particles per level: ";
312  for(unsigned int i=0;i<NLevels;i++)
313  {
314  std::cout<<" "<<particlesPerLevel[i];
315  }
316  std::cout<<std::endl;
317  }
318 
319  //How changes particlesPerLeve[i] when hGridCellSize[j] is changed
320  std::vector< std::vector< double > > diffParticlesPerLevel;
321  diffParticlesPerLevel.resize(NLevels);
322  for(unsigned int i=0;i<NLevels;i++)
323  {
324  for(unsigned int j=0;j<NParams;j++)
325  {
326  diffParticlesPerLevel[i].push_back(0.0);
327  if(j==i)
328  {
329  diffParticlesPerLevel[i][j]+=-0.5*diffPdfInt(0.5*hGridCellSizes[i],0);
330  }
331  if(j==i+1)
332  {
333  diffParticlesPerLevel[i][j]+= 0.5*diffPdfInt(0.5*hGridCellSizes[i+1],0);
334  }
335  }
336  }
337  if(verbosity>0)
338  {
339  std::cout<<"Diff Particles per level: "<<std::endl;
340  for(unsigned int i=0;i<NLevels;i++)
341  {
342  for(unsigned int j=0;j<NParams;j++)
343  {
344  std::cout<<" "<<std::setw(12)<<diffParticlesPerLevel[i][j];
345  }
346  std::cout<<std::endl;
347  }
348  }
349 
350  std::vector<double> cellsPerLevel;
351  for(unsigned int i=0;i<NLevels;i++)
352  {
353  cellsPerLevel.push_back(pow(length/hGridCellSizes[i+1],dimension));
354  }
355  if(verbosity>0)
356  {
357  std::cout<<"Cells per level: ";
358  for(unsigned int i=0;i<NLevels;i++)
359  {
360  std::cout<<" "<<cellsPerLevel[i];
361  }
362  std::cout<<std::endl;
363  }
364 
365  //How changes cellsPerLevel[i] when hGridCellSize[j] is changed
366  std::vector< std::vector< double > > diffCellsPerLevel;
367  diffCellsPerLevel.resize(hGridCellSizes.size());
368  for(unsigned int i=0;i<NLevels;i++)
369  {
370  for(unsigned int j=0;j<NParams;j++)
371  {
372  if(j==i+1)
373  {
374  diffCellsPerLevel[i].push_back(-pow(length/hGridCellSizes[i+1],dimension)*dimension/hGridCellSizes[i+1]);
375  }
376  else
377  {
378  diffCellsPerLevel[i].push_back(0.0);
379  }
380  }
381  }
382  if(verbosity>0)
383  {
384  std::cout<<"Diff Cells per level: "<<std::endl;
385  for(unsigned int i=0;i<NLevels;i++)
386  {
387  for(unsigned int j=0;j<NParams;j++)
388  {
389  std::cout<<" "<<std::setw(12)<<diffCellsPerLevel[i][j];
390  }
391  std::cout<<std::endl;
392  }
393  }
394 
395  std::vector<double> particlesPerCell;
396  for(unsigned int i=0;i<NLevels;i++)
397  {
398  particlesPerCell.push_back(particlesPerLevel[i]/cellsPerLevel[i]);
399  }
400  if(verbosity>0)
401  {
402  std::cout<<"Particles per cell: ";
403  for(unsigned int i=0;i<particlesPerCell.size();i++)
404  {
405  std::cout<<" "<<particlesPerCell[i];
406  }
407  std::cout<<std::endl;
408  }
409 
410  //How changes particlesPerCell[i] when hGridCellSize[j] is changed
411  std::vector< std::vector< double > > diffParticlesPerCell;
412  diffParticlesPerCell.resize(NLevels);
413  for(unsigned int i=0;i<NLevels;i++)
414  {
415  for(unsigned int j=0;j<NParams;j++)
416  {
417  diffParticlesPerCell[i].push_back((diffParticlesPerLevel[i][j]*cellsPerLevel[i]-particlesPerLevel[i]*diffCellsPerLevel[i][j])/(cellsPerLevel[i]*cellsPerLevel[i]));
418  }
419  }
420  if(verbosity>0)
421  {
422  std::cout<<"Diff Particles per Cell: "<<std::endl;
423  for(unsigned int i=0;i<NLevels;i++)
424  {
425  for(unsigned int j=0;j<NParams;j++)
426  {
427  std::cout<<" "<<std::setw(12)<<diffParticlesPerCell[i][j];
428  }
429  std::cout<<std::endl;
430  }
431  }
432 
433  double contactWork=0, overheadWork=0;
434  std::vector<double> diffContactWork;
435  std::vector<double> diffOverheadWork;
436  diffContactWork.resize(NParams);
437  diffOverheadWork.resize(NParams);
438  for(unsigned int j=0;j<NParams;j++)
439  {
440  diffContactWork[j]=0;
441  diffOverheadWork[j]=0;
442  }
443 
444  for(unsigned int i=0;i<NLevels;i++)
445  {
446  contactWork+=0.5*pow(3,dimension)*particlesPerCell[i]*particlesPerLevel[i];
447  overheadWork+=0.5*(pow(3,dimension)+1)*particlesPerLevel[i];
448  for(unsigned int j=0;j<NParams;j++)
449  {
450  diffContactWork[j]+=0.5*pow(3,dimension)*(diffParticlesPerCell[i][j]*particlesPerLevel[i]+particlesPerCell[i]*diffParticlesPerLevel[i][j]);
451  diffOverheadWork[j]+=0.5*(pow(3,dimension)+1)*diffParticlesPerLevel[i][j];
452  }
453 
454  int startJ,endJ;
455  switch(method)
456  {
457  case BOTTOMUP:
458  {
459  startJ=i+1;
460  endJ=NLevels;
461  break;
462  }
463  case TOPDOWN:
464  {
465  startJ=0;
466  endJ=i;
467  break;
468  }
469  }
470  for(unsigned int j=startJ;j<endJ;j++)
471  {
472  double numberOfCellToCheck;
473  numberOfCellToCheck=expectedCellsIntegral(0.5*hGridCellSizes[i],0.5*hGridCellSizes[i+1],dimension,hGridCellSizes[j+1]);
474 
475  std::vector<double> diffNumberOfCellToCheck;
476  for(unsigned int k=0;k<NParams;k++)
477  {
478  diffNumberOfCellToCheck.push_back(0.0);
479  if(k==i)
480  {
481  diffNumberOfCellToCheck[k]+=0.5*diffStartExpectedCellsIntegral(0.5*hGridCellSizes[i],0.5*hGridCellSizes[i+1],dimension,hGridCellSizes[j+1]);
482  }
483  if(k==i+1)
484  {
485  diffNumberOfCellToCheck[k]+=0.5*diffEndExpectedCellsIntegral(0.5*hGridCellSizes[i],0.5*hGridCellSizes[i+1],dimension,hGridCellSizes[j+1]);
486  }
487  if(k==j+1)
488  {
489  diffNumberOfCellToCheck[k]+=diffHExpectedCellsIntegral(0.5*hGridCellSizes[i],0.5*hGridCellSizes[i+1],dimension,hGridCellSizes[j+1]);
490  }
491  }
492  contactWork+=particlesPerLevel[i]*numberOfCellToCheck*particlesPerCell[j];
493  overheadWork+=particlesPerLevel[i]*numberOfCellToCheck;
494  //std::cout<<"i= "<<i<<" j= "<<j<<" NumberOfCellToCheck= "<<numberOfCellToCheck<<" diffNumberOfCellToCheck[2]= "<<diffNumberOfCellToCheck[2]<<std::endl;
495  for(unsigned int k=0;k<NParams;k++)
496  {
497  diffContactWork[k]+=(diffParticlesPerLevel[i][k]*numberOfCellToCheck*particlesPerCell[j]+particlesPerLevel[i]*diffNumberOfCellToCheck[k]*particlesPerCell[j]+particlesPerLevel[i]*numberOfCellToCheck*diffParticlesPerCell[j][k]);
498  diffOverheadWork[k]+=(diffParticlesPerLevel[i][k]*numberOfCellToCheck+particlesPerLevel[i]*diffNumberOfCellToCheck[k]);
499  }
500  }
501  }
502  if(verbosity>0)
503  {
504  std::cout<<"Contact work: "<<contactWork<<std::endl;
505  std::cout<<"Overhead work: "<<k*overheadWork<<std::endl;
506  std::cout<<"Sum work: "<<contactWork+k*overheadWork<<std::endl;
507  std::cout<<"diff Contactwork: ";
508  for(unsigned int j=0;j<NParams;j++)
509  {
510  std::cout<<" "<<diffContactWork[j];
511  }
512  std::cout<<std::endl;
513  std::cout<<"diff Overheadwork: ";
514  for(unsigned int j=0;j<NParams;j++)
515  {
516  std::cout<<" "<<k*diffOverheadWork[j];
517  }
518  std::cout<<std::endl;
519  std::cout<<"diff sum: ";
520  for(unsigned int j=0;j<NParams;j++)
521  {
522  std::cout<<" "<<diffContactWork[j]+k*diffOverheadWork[j];
523  }
524  std::cout<<std::endl;
525  }
526  dfdx.clear();
527  for(unsigned int j=0;j<NParams;j++)
528  {
529  dfdx.push_back(diffContactWork[j]+k*diffOverheadWork[j]);
530  }
531 }
532 
533 double HGridOptimiser::calculateWork(std::vector<double>& hGridCellSizes, HGridMethod method, int verbosity)
534 {
535  unsigned int NLevels=hGridCellSizes.size()-1;
536  unsigned int NParams=hGridCellSizes.size();
537 
538  if(verbosity>0)
539  {
540  std::cout<<"Length scale="<<length<<std::endl;
541  }
542  if(verbosity>0)
543  {
544  std::cout<<"Level sizes:";
545  for(unsigned int i=0;i<NParams;i++)
546  {
547  std::cout<<" "<<hGridCellSizes[i];
548  }
549  std::cout<<std::endl;
550  }
551 
552  std::vector<double> particlesPerLevel;
553  for(unsigned int i=0;i<NLevels;i++)
554  {
555  particlesPerLevel.push_back(pdfInt(0.5*hGridCellSizes[i],0.5*hGridCellSizes[i+1],0));
556  if(particlesPerLevel.back()<0)
557  {
558  particlesPerLevel.back()=0;
559  }
560  }
561  if(verbosity>0)
562  {
563  std::cout<<"Particles per level: ";
564  for(unsigned int i=0;i<NLevels;i++)
565  {
566  std::cout<<" "<<particlesPerLevel[i];
567  }
568  std::cout<<std::endl;
569  }
570 
571  std::vector<double> cellsPerLevel;
572  for(unsigned int i=0;i<NLevels;i++)
573  {
574  cellsPerLevel.push_back(pow(length/hGridCellSizes[i+1],dimension));
575  }
576  if(verbosity>0)
577  {
578  std::cout<<"Cells per level: ";
579  for(unsigned int i=0;i<NLevels;i++)
580  {
581  std::cout<<" "<<cellsPerLevel[i];
582  }
583  std::cout<<std::endl;
584  }
585 
586  std::vector<double> particlesPerCell;
587  for(unsigned int i=0;i<NLevels;i++)
588  {
589  particlesPerCell.push_back(particlesPerLevel[i]/cellsPerLevel[i]);
590  }
591  if(verbosity>0)
592  {
593  std::cout<<"Particles per cell: ";
594  for(unsigned int i=0;i<particlesPerCell.size();i++)
595  {
596  std::cout<<" "<<particlesPerCell[i];
597  }
598  std::cout<<std::endl;
599  }
600 
601  double contactWork=0, overheadWork=0;
602  for(unsigned int i=0;i<NLevels;i++)
603  {
604  contactWork+=0.5*pow(3,dimension)*particlesPerCell[i]*particlesPerLevel[i];
605  overheadWork+=0.5*(pow(3,dimension)+1)*particlesPerLevel[i];
606 
607  int startJ,endJ;
608  switch(method)
609  {
610  case BOTTOMUP:
611  {
612  startJ=i+1;
613  endJ=NLevels;
614  break;
615  }
616  case TOPDOWN:
617  {
618  startJ=0;
619  endJ=i;
620  break;
621  }
622  }
623  for(unsigned int j=startJ;j<endJ;j++)
624  {
625  double numberOfCellToCheck;
626  numberOfCellToCheck=expectedCellsIntegral(0.5*hGridCellSizes[i],0.5*hGridCellSizes[i+1],dimension,hGridCellSizes[j+1]);
627  contactWork+=particlesPerLevel[i]*numberOfCellToCheck*particlesPerCell[j];
628  overheadWork+=particlesPerLevel[i]*numberOfCellToCheck;
629 
630  }
631  }
632 
633  if(verbosity>0)
634  {
635  std::cout<<"Contact work: "<<contactWork<<std::endl;
636  std::cout<<"Overhead work: "<<k*overheadWork<<std::endl;
637  }
638  return contactWork+k*overheadWork;
639 }
640 
641 void HGridOptimiser::calcDfDx(std::vector<double>& hGridCellSizes, std::vector<double>& dfdx, HGridMethod method, int verbosity)
642 {
643  if(verbosity>0)
644  {
645  std::cout<<"calcDfDx"<<std::endl;
646  }
647  double W=calculateWork(hGridCellSizes, method,verbosity-1);
648  double dx=1e-10;
649  double nW;
650  dfdx.clear();
651  for(unsigned int i=0;i<hGridCellSizes.size();i++)
652  {
653  hGridCellSizes[i]+=dx;
654  nW=calculateWork(hGridCellSizes, method, verbosity-1);
655  dfdx.push_back((nW-W)/dx);
656  hGridCellSizes[i]-=dx;
657  if(verbosity>0)
658  {
659  std::cout<<"i="<<i<<" Value="<<hGridCellSizes[i]<<" Change="<<nW-W<<" dfdx="<<dfdx.back()<<std::endl;
660  }
661  }
662 }
663 
664 double HGridOptimiser::checkLimit(std::vector<double>& hGridCellSizes, std::vector<double>& dfdx, int verbosity)
665 {
666  if(verbosity>0)
667  {
668  std::cout<<"checkLimits part 1 remove levels"<<std::endl;
669  }
670 
671  dfdx[0]=0;
672  dfdx.back()=0;
673  for(unsigned int i=1;i<hGridCellSizes.size();i++)
674  {
675  if(std::abs(hGridCellSizes[i-1]-hGridCellSizes[i])<1e-6)
676  {
677  if(dfdx[i-1]<dfdx[i])
678  {
679  if(verbosity>0)
680  {
681  std::cout<<"Remove level"<<i<<std::endl;
682  }
683  if(i>0.5*hGridCellSizes.size())
684  {
685  hGridCellSizes.erase(hGridCellSizes.begin()+i-1);
686  dfdx.erase(dfdx.begin()+i-1);
687  }
688  else
689  {
690  hGridCellSizes.erase(hGridCellSizes.begin()+i);
691  dfdx.erase(dfdx.begin()+i);
692  }
693  i--;
694  }
695  }
696  }
697 
698  if(verbosity>0)
699  {
700  std::cout<<"checkLimits part 2 calculate limit"<<std::endl;
701  for(unsigned int i=0;i<hGridCellSizes.size();i++)
702  {
703  std::cout<<"i="<<i<<" Value="<<hGridCellSizes[i]<<" dfdx="<<dfdx[i]<<std::endl;
704  }
705  }
706  double maxStepSize=-std::numeric_limits<double>::max();
707  double nmax;
708  for(unsigned int i=1;i<hGridCellSizes.size();i++)
709  {
710  nmax=(hGridCellSizes[i-1]-hGridCellSizes[i])/(dfdx[i]-dfdx[i-1]);
711  if(verbosity>0)
712  {
713  std::cout<<"Max f="<<nmax<<" because otherwise "<<hGridCellSizes[i-1]<<"+x*"<<dfdx[i-1]<<">"<<hGridCellSizes[i]<<"+x*"<<dfdx[i]<<std::endl;
714  }
715  if(nmax<0)
716  {
717  maxStepSize=std::max(nmax,maxStepSize);
718  }
719  }
720  if(verbosity>0)
721  {
722  std::cout<<"maxStepSize="<<maxStepSize<<std::endl;
723  }
724  return maxStepSize;
725 }
726 
727 void HGridOptimiser::applyStep(std::vector<double>& hGridCellSizes, std::vector<double>& dfdx, double stepsize, int verbosity)
728 {
729  if(verbosity>0)
730  {
731  std::cout<<"Apply step:"<<std::endl;
732  }
733  for(unsigned int i=0;i<hGridCellSizes.size()-1;i++)
734  {
735  hGridCellSizes[i]+=stepsize*dfdx[i];
736  if(verbosity>0)
737  {
738  std::cout<<"hGridCellSizes[i]"<<"+"<<stepsize<<"*"<<dfdx[i]<<"="<<hGridCellSizes[i]<<std::endl;
739  }
740  }
741 }
742 
743 double HGridOptimiser::goldenSectionSearch(std::vector<double>& startHGridCellSizes, std::vector<double>& searchDirection, double min, double cur, double max, HGridMethod method, int verbosity)
744 {
745  std::vector<double> curHGridCellSizes=startHGridCellSizes;
746  std::vector<double> xHGridCellSizes=startHGridCellSizes;
747 
748  applyStep(curHGridCellSizes, searchDirection, cur, verbosity-1);
749  double curWork=calculateWork(curHGridCellSizes, method, verbosity-1);
750 
751  double x;
752  double resphi=2.0-0.5*(1+std::sqrt(5));
753 
754  //Determine new probing point
755  if(max-cur>cur-min)
756  {
757  //x between cur and max
758  x=cur+resphi*(max-cur);
759  }
760  else
761  {
762  //x between min and cur
763  x=cur-resphi*(cur-min);
764  }
765 
766  if (std::abs(max-min)<1e-7*(std::abs(cur)+std::abs(x)))
767  {
768  return 0.5*(min + max);
769  }
770 
771  applyStep(xHGridCellSizes, searchDirection, x, 0);
772  double xWork=calculateWork(xHGridCellSizes, method, 0);
773  if(verbosity>0)
774  {
775  std::cout<<"min="<<min<<" max="<<max<<" cur="<<cur<<" curWork="<<curWork<<" x="<<x<<" xWork="<<xWork<<std::endl;
776  }
777  if(xWork<curWork) //x is better
778  {
779  if(max-cur>cur-min)
780  {
781  return goldenSectionSearch(startHGridCellSizes, searchDirection, cur, x, max, method, verbosity);
782  }
783  else
784  {
785  return goldenSectionSearch(startHGridCellSizes, searchDirection, min, x, cur, method, verbosity);
786  }
787  }
788  else //cur is better
789  {
790  if(max-cur>cur-min)
791  {
792  return goldenSectionSearch(startHGridCellSizes, searchDirection, min, cur, x, method, verbosity);
793  }
794  else
795  {
796  return goldenSectionSearch(startHGridCellSizes, searchDirection, x, cur, max, method, verbosity);
797  }
798  }
799 }
800 
801 void HGridOptimiser::getOptimalDistribution(std::vector<double>& hGridCellSizes, int numberOfLevels, HGridMethod method, int verbosity)
802 {
803  hGridCellSizes.clear();
804  for (unsigned int i=0; i<=numberOfLevels; i++)
805  {
806  hGridCellSizes.push_back(2.0*(rMin+(rMax-rMin)*i/numberOfLevels));
807  }
808 
809  std::vector<double> dfdx;
810  double step,max,nW,W;
811  W=calculateWork(hGridCellSizes, method,verbosity-3);
812  for(int i=0;i<100;i++)
813  {
814  calculateDiffWork(hGridCellSizes, dfdx, method,verbosity-3);
815  max=checkLimit(hGridCellSizes,dfdx,verbosity-3);
816  step=goldenSectionSearch(hGridCellSizes, dfdx, max, 0.5*max, 0, method,verbosity-2);
817  applyStep(hGridCellSizes,dfdx,step,verbosity-3);
818  nW=calculateWork(hGridCellSizes, method,verbosity-3);
819  if(verbosity>1)
820  {
821  std::cout<<"Correct step: old work="<<W<<" new work="<<nW<<" difference="<<nW-W<<" step="<<step/max<<std::endl;
822  }
823  W=nW;
824  }
825  calculateDiffWork(hGridCellSizes, dfdx, method,verbosity-2);
826  if(verbosity>0)
827  {
828  std::cout<<"Work="<<nW<<std::endl;
829  std::cout<<"Optimal cell sizes:";
830  for(unsigned int i=0;i<hGridCellSizes.size();i++)
831  {
832  std::cout<<" "<<hGridCellSizes[i];
833  }
834  std::cout<<std::endl;
835  }
836 }
837 
double goldenSectionSearch(std::vector< double > &startHGridCellSizes, std::vector< double > &searchDirection, double min, double cur, double max, HGridMethod method, int verbosity)
BaseParticle * getLargestParticle() const
Gets a pointer to the largest BaseParticle (by interactionRadius) in this ParticleHandler.
Mdouble get_zmin()
Gets zmin.
Definition: MD.h:313
double diffPdfInt(double x, int power)
diff(int(f(r)*r^power*dr,r=s..e)/int(f(r)*dr,r=0..omega),e)=f(e)*e^power/int(f(r)*dr,r=0..omega)
This is the base class for both HGRID_2D and HGRID_3D.
Definition: HGRID_base.h:43
void Initialise(HGRID_base &problem, int verbosity)
std::vector< int > CellN
Mdouble get_InteractionRadius() const
double calculateWork(std::vector< double > &hGridCellSizes, HGridMethod method, int verbosity)
double diffStartExpectedCellsIntegral(double start, double end, int p, double h)
double cell2Max(int i)
const std::vector< T * >::const_iterator begin() const
Gets the begin of the const_iterator over all Object in this BaseHandler.
Definition: BaseHandler.h:220
void getOptimalDistribution(std::vector< double > &hGridCellSizes, int numberOfLevels, HGridMethod method, int verbosity)
int get_dim()
Allows the dimension of the simulation to be accessed.
Definition: MD.h:369
Mdouble get_ymax()
Gets ymax.
Definition: MD.h:311
double expectedCellsIntegral(double start, double end, int p, double h)
This function calculates: int((2*r/h+2)^d f(r) dr,r=s..e)/int(f(r) dr,r=s..e)+ Used to calculated the...
void calculateDiffWork(std::vector< double > &hGridCellSizes, std::vector< double > &dfdx, HGridMethod method, int verbosity)
Mdouble get_ymin()
Gets ymin.
Definition: MD.h:309
void calcDfDx(std::vector< double > &hGridCellSizes, std::vector< double > &dfdx, HGridMethod method, int verbosity)
BaseParticle * getSmallestParticle() const
Gets a pointer to the smallest BaseParticle (by interactionRadius) in this ParticleHandler.
double cell2Min(int i)
Mdouble get_xmin()
Get xmin.
Definition: MD.h:305
const std::vector< T * >::const_iterator end() const
Gets the end of the const_iterator over all BaseBoundary in this BaseHandler.
Definition: BaseHandler.h:233
HGridMethod
Definition: HGRID_base.h:36
int radius2Cell(double r)
double checkLimit(std::vector< double > &hGridCellSizes, std::vector< double > &dfdx, int verbosity)
unsigned int getNumberOfObjects() const
Gets the number of Object in this BaseHandler.
Definition: BaseHandler.h:199
void applyStep(std::vector< double > &hGridCellSizes, std::vector< double > &dfdx, double stepsize, int verbosity)
ParticleHandler & getParticleHandler()
Definition: MD.h:147
Mdouble get_xmax()
Get xmax.
Definition: MD.h:307
double diffHExpectedCellsIntegral(double start, double end, int p, double h)
double pdfInt(double start, double end, int power)
This function calculates: int(f(r)*r^power*dr,r=start..end)/int(f(r)*dr,r=0..omega) ...
Mdouble get_zmax()
Gets zmax.
Definition: MD.h:315
double diffEndExpectedCellsIntegral(double start, double end, int p, double h)