Fix a bug in the init
[charm.git] / src / ck-ldb / LBDatabase.C
1 /**
2  * \addtogroup CkLdb
3 */
4 /*@{*/
5
6 #include "converse.h"
7
8 /*
9  * This C++ file contains the Charm stub functions
10  */
11
12 #include "LBDatabase.h"
13 #include "LBSimulation.h"
14 #include "topology.h"
15
16 #include "NullLB.h"
17
18 CkGroupID _lbdb;
19
20 CkpvDeclare(int, numLoadBalancers);  /**< num of lb created */
21 CkpvDeclare(int, hasNullLB);         /**< true if NullLB is created */
22 CkpvDeclare(int, lbdatabaseInited);  /**< true if lbdatabase is inited */
23
24 // command line options
25 CkLBArgs _lb_args;
26 int _lb_predict=0;
27 int _lb_predict_delay=10;
28 int _lb_predict_window=20;
29
30 // registry class stores all load balancers linked and created at runtime
31 class LBDBRegistry {
32 friend class LBDBInit;
33 friend class LBDatabase;
34 private:
35   // table for all available LBs linked in
36   struct LBDBEntry {
37     const char *name;
38     LBCreateFn  cfn;
39     LBAllocFn   afn;
40     const char *help;
41     int         shown;          // if 0, donot show in help page
42     LBDBEntry(): name(0), cfn(0), afn(0), help(0), shown(1) {}
43     LBDBEntry(int) {}
44     LBDBEntry(const char *n, LBCreateFn cf, LBAllocFn af,
45               const char *h, int show=1):
46       name(n), cfn(cf), afn(af), help(h), shown(show) {};
47   };
48   CkVec<LBDBEntry> lbtables;            // a list of available LBs linked
49   CkVec<const char *>   compile_lbs;    // load balancers at compile time
50   CkVec<const char *>   runtime_lbs;    // load balancers at run time
51 public:
52   LBDBRegistry() {}
53   void displayLBs()
54   {
55     CmiPrintf("\nAvailable load balancers:\n");
56     for (int i=0; i<lbtables.length(); i++) {
57       LBDBEntry &entry = lbtables[i];
58       if (entry.shown) CmiPrintf("* %s: %s\n", entry.name, entry.help);
59     }
60     CmiPrintf("\n");
61   }
62   void addEntry(const char *name, LBCreateFn fn, LBAllocFn afn, const char *help, int shown) {
63     lbtables.push_back(LBDBEntry(name, fn, afn, help, shown));
64   }
65   void addCompiletimeBalancer(const char *name) {
66     compile_lbs.push_back(name);
67   }
68   void addRuntimeBalancer(const char *name) {
69     runtime_lbs.push_back(name);
70   }
71   LBCreateFn search(const char *name) {
72     char *ptr = strpbrk((char *)name, ":,");
73     int slen = ptr!=NULL?ptr-name:strlen(name);
74     for (int i=0; i<lbtables.length(); i++)
75       if (0==strncmp(name, lbtables[i].name, slen)) return lbtables[i].cfn;
76     return NULL;
77   }
78   LBAllocFn getLBAllocFn(const char *name) {
79     char *ptr = strpbrk((char *)name, ":,");
80     int slen = ptr-name;
81     for (int i=0; i<lbtables.length(); i++)
82       if (0==strncmp(name, lbtables[i].name, slen)) return lbtables[i].afn;
83     return NULL;
84   }
85 };
86
87 static LBDBRegistry lbRegistry;
88
89 void LBDefaultCreate(const char *lbname)
90 {
91   lbRegistry.addCompiletimeBalancer(lbname);
92 }
93
94 // default is to show the helper
95 void LBRegisterBalancer(const char *name, LBCreateFn fn, LBAllocFn afn, const char *help, int shown)
96 {
97   lbRegistry.addEntry(name, fn, afn, help, shown);
98 }
99
100 LBAllocFn getLBAllocFn(char *lbname) {
101     return lbRegistry.getLBAllocFn(lbname);
102 }
103
104 // create a load balancer group using the strategy name
105 static void createLoadBalancer(const char *lbname)
106 {
107     LBCreateFn fn = lbRegistry.search(lbname);
108     if (!fn) {    // invalid lb name
109       CmiPrintf("Abort: Unknown load balancer: '%s'!\n", lbname);
110       lbRegistry.displayLBs();    // display help page
111       CkAbort("Abort");
112     }
113     // invoke function to create load balancer
114     fn();
115 }
116
117 // mainchare
118 LBDBInit::LBDBInit(CkArgMsg *m)
119 {
120 #if CMK_LBDB_ON
121   _lbdb = CProxy_LBDatabase::ckNew();
122
123   // runtime specified load balancer
124   if (lbRegistry.runtime_lbs.size() > 0) {
125     for (int i=0; i<lbRegistry.runtime_lbs.size(); i++) {
126       const char *balancer = lbRegistry.runtime_lbs[i];
127       createLoadBalancer(balancer);
128     }
129   }
130   else if (lbRegistry.compile_lbs.size() > 0) {
131     for (int i=0; i<lbRegistry.compile_lbs.size(); i++) {
132       const char* balancer = lbRegistry.compile_lbs[i];
133       createLoadBalancer(balancer);
134     }
135   }
136   else {
137     // NullLB is the default when none of above lb created
138     // note user may create his own load balancer in his code manually like
139     // in NAMD, but never mind NullLB can disable itself if there is
140     // a non NULL LB.
141     createLoadBalancer("NullLB");
142   }
143
144   // simulation mode
145   if (LBSimulation::doSimulation) {
146     CmiPrintf("Charm++> Entering Load Balancer Simulation Mode ... \n");
147     CProxy_LBDatabase(_lbdb).ckLocalBranch()->StartLB();
148   }
149 #endif
150   delete m;
151 }
152
153 // called from init.C
154 void _loadbalancerInit()
155 {
156   CkpvInitialize(int, lbdatabaseInited);
157   CkpvAccess(lbdatabaseInited) = 0;
158   CkpvInitialize(int, numLoadBalancers);
159   CkpvAccess(numLoadBalancers) = 0;
160   CkpvInitialize(int, hasNullLB);
161   CkpvAccess(hasNullLB) = 0;
162
163   char **argv = CkGetArgv();
164   char *balancer = NULL;
165   CmiArgGroup("Charm++","Load Balancer");
166   while (CmiGetArgStringDesc(argv, "+balancer", &balancer, "Use this load balancer")) {
167     if (CkMyRank() == 0)
168       lbRegistry.addRuntimeBalancer(balancer);   /* lbRegistry is a static */
169   }
170
171   // set up init value for LBPeriod time in seconds
172   // it can also be set by calling LDSetLBPeriod()
173   CmiGetArgDoubleDesc(argv,"+LBPeriod", &_lb_args.lbperiod(),"the minimum time period in seconds allowed for two consecutive automatic load balancing");
174   _lb_args.loop() = CmiGetArgFlagDesc(argv, "+LBLoop", "Use multiple load balancing strategies in loop");
175
176   // now called in cldb.c: CldModuleGeneralInit()
177   // registerLBTopos();
178   CmiGetArgStringDesc(argv, "+LBTopo", &_lbtopo, "define load balancing topology");
179   //Read the K parameter for RefineKLB
180   CmiGetArgIntDesc(argv, "+LBNumMoves", &_lb_args.percentMovesAllowed() , "Percentage of chares to be moved (used by RefineKLB) [0-100]");
181
182   /**************** FUTURE PREDICTOR ****************/
183   _lb_predict = CmiGetArgFlagDesc(argv, "+LBPredictor", "Turn on LB future predictor");
184   CmiGetArgIntDesc(argv, "+LBPredictorDelay", &_lb_predict_delay, "Number of balance steps before learning a model");
185   CmiGetArgIntDesc(argv, "+LBPredictorWindow", &_lb_predict_window, "Number of steps to use to learn a model");
186   if (_lb_predict_window < _lb_predict_delay) {
187     CmiPrintf("LB> [%d] Argument LBPredictorWindow (%d) less than LBPredictorDelay (%d) , fixing\n", CkMyPe(), _lb_predict_window, _lb_predict_delay);
188     _lb_predict_delay = _lb_predict_window;
189   }
190
191   /******************* SIMULATION *******************/
192   // get the step number at which to dump the LB database
193   CmiGetArgIntDesc(argv, "+LBVersion", &_lb_args.lbversion(), "LB database file version number");
194   CmiGetArgIntDesc(argv, "+LBCentPE", &_lb_args.central_pe(), "CentralLB processor");
195   int _lb_dump_activated = 0;
196   if (CmiGetArgIntDesc(argv, "+LBDump", &LBSimulation::dumpStep, "Dump the LB state from this step"))
197     _lb_dump_activated = 1;
198   if (_lb_dump_activated && LBSimulation::dumpStep < 0) {
199     CmiPrintf("LB> Argument LBDump (%d) negative, setting to 0\n",LBSimulation::dumpStep);
200     LBSimulation::dumpStep = 0;
201   }
202   CmiGetArgIntDesc(argv, "+LBDumpSteps", &LBSimulation::dumpStepSize, "Dump the LB state for this amount of steps");
203   if (LBSimulation::dumpStepSize <= 0) {
204     CmiPrintf("LB> Argument LBDumpSteps (%d) too small, setting to 1\n",LBSimulation::dumpStepSize);
205     LBSimulation::dumpStepSize = 1;
206   }
207   CmiGetArgStringDesc(argv, "+LBDumpFile", &LBSimulation::dumpFile, "Set the LB state file name");
208   // get the simulation flag and number. Now the flag can also be avoided by the presence of the number
209   LBSimulation::doSimulation = CmiGetArgIntDesc(argv, "+LBSim", &LBSimulation::simStep, "Read LB state from LBDumpFile since this step");
210   // check for stupid LBSim parameter
211   if (LBSimulation::doSimulation && LBSimulation::simStep < 0) {
212     CmiPrintf("LB> Argument LBSim (%d) invalid, should be >= 0\n");
213     CkExit();
214     return;
215   }
216   CmiGetArgIntDesc(argv, "+LBSimSteps", &LBSimulation::simStepSize, "Read LB state for this number of steps");
217   if (LBSimulation::simStepSize <= 0) {
218     CmiPrintf("LB> Argument LBSimSteps (%d) too small, setting to 1\n",LBSimulation::simStepSize);
219     LBSimulation::simStepSize = 1;
220   }
221
222
223   LBSimulation::simProcs = 0;
224   CmiGetArgIntDesc(argv, "+LBSimProcs", &LBSimulation::simProcs, "Number of target processors.");
225
226   LBSimulation::showDecisionsOnly =
227     CmiGetArgFlagDesc(argv, "+LBShowDecisions",
228                       "Write to File: Load Balancing Object to Processor Map decisions during LB Simulation");
229
230   // force a global barrier after migration done
231   _lb_args.syncResume() = CmiGetArgFlagDesc(argv, "+LBSyncResume",
232                   "LB performs a barrier after migration is finished");
233
234   // both +LBDebug and +LBDebug level should work
235   if (!CmiGetArgIntDesc(argv, "+LBDebug", &_lb_args.debug(),
236                                           "Turn on LB debugging printouts"))
237     _lb_args.debug() = CmiGetArgFlagDesc(argv, "+LBDebug",
238                                              "Turn on LB debugging printouts");
239
240   // getting the size of the team with +teamSize
241   if (!CmiGetArgIntDesc(argv, "+teamSize", &_lb_args.teamSize(),
242                                           "Team size"))
243     _lb_args.teamSize() = 1;
244
245   // ask to print summary/quality of load balancer
246   _lb_args.printSummary() = CmiGetArgFlagDesc(argv, "+LBPrintSummary",
247                 "Print load balancing result summary");
248
249   // to ignore baclground load
250   _lb_args.ignoreBgLoad() = CmiGetArgFlagDesc(argv, "+LBNoBackground",
251                       "Load balancer ignores the background load.");
252 #ifdef __BIGSIM__
253   _lb_args.ignoreBgLoad() = 1;
254 #endif
255   _lb_args.migObjOnly() = CmiGetArgFlagDesc(argv, "+LBObjOnly",
256                       "Only load balancing migratable objects, ignoring all others.");
257   if (_lb_args.migObjOnly()) _lb_args.ignoreBgLoad() = 1;
258
259   // assume all CPUs are identical
260   _lb_args.testPeSpeed() = CmiGetArgFlagDesc(argv, "+LBTestPESpeed",
261                       "Load balancer test all CPUs speed.");
262   _lb_args.samePeSpeed() = CmiGetArgFlagDesc(argv, "+LBSameCpus",
263                       "Load balancer assumes all CPUs are of same speed.");
264   if (!_lb_args.testPeSpeed()) _lb_args.samePeSpeed() = 1;
265
266   _lb_args.useCpuTime() = CmiGetArgFlagDesc(argv, "+LBUseCpuTime",
267                       "Load balancer uses CPU time instead of wallclock time.");
268
269   // turn instrumentation off at startup
270   _lb_args.statsOn() = !CmiGetArgFlagDesc(argv, "+LBOff",
271                         "Turn load balancer instrumentation off");
272
273   // turn instrumentation of communicatin off at startup
274   _lb_args.traceComm() = !CmiGetArgFlagDesc(argv, "+LBCommOff",
275                 "Turn load balancer instrumentation of communication off");
276
277         // turn on MetaBalancer if set
278         _lb_args.metaLbOn() = CmiGetArgFlagDesc(argv, "+MetaLB",
279                 "Turn on MetaBalancer");
280
281   // set alpha and beeta
282   _lb_args.alpha() = PER_MESSAGE_SEND_OVERHEAD_DEFAULT;
283   _lb_args.beeta() = PER_BYTE_SEND_OVERHEAD_DEFAULT;
284   CmiGetArgDoubleDesc(argv,"+LBAlpha", &_lb_args.alpha(),
285                            "per message send overhead");
286   CmiGetArgDoubleDesc(argv,"+LBBeta", &_lb_args.beeta(),
287                            "per byte send overhead");
288
289   if (CkMyPe() == 0) {
290     if (_lb_args.debug()) {
291       CmiPrintf("CharmLB> Verbose level %d, load balancing period: %g seconds\n", _lb_args.debug(), _lb_args.lbperiod());
292     }
293     if (_lb_args.debug() > 1) {
294       CmiPrintf("CharmLB> Topology %s alpha: %es beta: %es.\n", _lbtopo, _lb_args.alpha(), _lb_args.beeta());
295     }
296     if (_lb_args.printSummary())
297       CmiPrintf("CharmLB> Load balancer print summary of load balancing result.\n");
298     if (_lb_args.ignoreBgLoad())
299       CmiPrintf("CharmLB> Load balancer ignores processor background load.\n");
300     if (_lb_args.samePeSpeed())
301       CmiPrintf("CharmLB> Load balancer assumes all CPUs are same.\n");
302     if (_lb_args.useCpuTime())
303       CmiPrintf("CharmLB> Load balancer uses CPU time instead of wallclock time.\n");
304     if (LBSimulation::doSimulation)
305       CmiPrintf("CharmLB> Load balancer running in simulation mode on file '%s' version %d.\n", LBSimulation::dumpFile, _lb_args.lbversion());
306     if (_lb_args.statsOn()==0)
307       CkPrintf("CharmLB> Load balancing instrumentation is off.\n");
308     if (_lb_args.traceComm()==0)
309       CkPrintf("CharmLB> Load balancing instrumentation for communication is off.\n");
310     if (_lb_args.migObjOnly())
311       CkPrintf("LB> Load balancing strategy ignores non-migratable objects.\n");
312   }
313 }
314
315 int LBDatabase::manualOn = 0;
316 char *LBDatabase::avail_vector = NULL;
317 CmiNodeLock avail_vector_lock;
318
319 static LBRealType * _expectedLoad = NULL;
320
321 void LBDatabase::initnodeFn()
322 {
323   int proc;
324   int num_proc = CkNumPes();
325   avail_vector= new char[num_proc];
326   for(proc = 0; proc < num_proc; proc++)
327       avail_vector[proc] = 1;
328   avail_vector_lock = CmiCreateLock();
329
330   _expectedLoad = new LBRealType[num_proc];
331   for (proc=0; proc<num_proc; proc++) _expectedLoad[proc]=0.0;
332 }
333
334 // called my constructor
335 void LBDatabase::init(void)
336 {
337   myLDHandle = LDCreate();
338   mystep = 0;
339   nloadbalancers = 0;
340   new_ld_balancer = 0;
341         metabalancer = NULL;
342
343   CkpvAccess(lbdatabaseInited) = 1;
344 #if CMK_LBDB_ON
345   if (manualOn) TurnManualLBOn();
346 #endif
347 }
348
349 LBDatabase::LastLBInfo::LastLBInfo()
350 {
351   expectedLoad = _expectedLoad;
352 }
353
354 void LBDatabase::get_avail_vector(char * bitmap) {
355     CmiAssert(bitmap && avail_vector);
356     const int num_proc = CkNumPes();
357     for(int proc = 0; proc < num_proc; proc++){
358       bitmap[proc] = avail_vector[proc];
359     }
360 }
361
362 // new_ld == -1(default) : calcualte a new ld
363 //           -2 : ignore new ld
364 //           >=0: given a new ld
365 void LBDatabase::set_avail_vector(char * bitmap, int new_ld){
366     int assigned = 0;
367     const int num_proc = CkNumPes();
368     if (new_ld == -2) assigned = 1;
369     else if (new_ld >= 0) {
370       CmiAssert(new_ld < num_proc);
371       new_ld_balancer = new_ld;
372       assigned = 1;
373     }
374     CmiAssert(bitmap && avail_vector);
375     for(int count = 0; count < num_proc; count++){
376         avail_vector[count] = bitmap[count];
377         if((bitmap[count] == 1) && !assigned){
378             new_ld_balancer = count;
379             assigned = 1;
380         }
381     }
382 }
383
384 // called in CreateFooLB() when multiple load balancers are created
385 // on PE0, BaseLB of each load balancer applies a ticket number
386 // and broadcast the ticket number to all processors
387 int LBDatabase::getLoadbalancerTicket()  {
388   int seq = nloadbalancers;
389   nloadbalancers ++;
390   loadbalancers.resize(nloadbalancers);
391   loadbalancers[seq] = NULL;
392   return seq;
393 }
394
395 void LBDatabase::addLoadbalancer(BaseLB *lb, int seq) {
396 //  CmiPrintf("[%d] addLoadbalancer for seq %d\n", CkMyPe(), seq);
397   if (seq == -1) return;
398   if (CkMyPe() == 0) {
399     CmiAssert(seq < nloadbalancers);
400     if (loadbalancers[seq]) {
401       CmiPrintf("Duplicate load balancer created at %d\n", seq);
402       CmiAbort("LBDatabase");
403     }
404   }
405   else
406     nloadbalancers ++;
407   loadbalancers.resize(seq+1);
408   loadbalancers[seq] = lb;
409 }
410
411 // switch strategy in order
412 void LBDatabase::nextLoadbalancer(int seq) {
413   if (seq == -1) return;                // -1 means this is the only LB
414   int next = seq+1;
415   if (_lb_args.loop()) {
416     if (next == nloadbalancers) next = 0;
417   }
418   else {
419     if (next == nloadbalancers) next --;  // keep using the last one
420   }
421   if (seq != next) {
422     loadbalancers[seq]->turnOff();
423     CmiAssert(loadbalancers[next]);
424     loadbalancers[next]->turnOn();
425   }
426 }
427
428 // return the seq-th load balancer string name of
429 // it can be specified in either compile time or runtime
430 // runtime has higher priority
431 const char *LBDatabase::loadbalancer(int seq) {
432   if (lbRegistry.runtime_lbs.length()) {
433     CmiAssert(seq < lbRegistry.runtime_lbs.length());
434     return lbRegistry.runtime_lbs[seq];
435   }
436   else {
437     CmiAssert(seq < lbRegistry.compile_lbs.length());
438     return lbRegistry.compile_lbs[seq];
439   }
440 }
441
442 void LBDatabase::pup(PUP::er& p)
443 {
444         IrrGroup::pup(p);
445         // the memory should be already allocated
446         int np;
447         if (!p.isUnpacking()) np = CkNumPes();
448         p|np;
449         CmiAssert(avail_vector);
450         // in case number of processors changes
451         if (p.isUnpacking() && np > CkNumPes()) {
452                 CmiLock(avail_vector_lock);
453                 delete [] avail_vector;
454                 avail_vector = new char[np];
455                 for (int i=0; i<np; i++) avail_vector[i] = 1;
456                 CmiUnlock(avail_vector_lock);
457         }
458         p(avail_vector, np);
459         p|mystep;
460         if(p.isUnpacking()) {
461     nloadbalancers = 0;
462                 if (_lb_args.metaLbOn()) {
463       // if unpacking set metabalancer using the id
464       metabalancer = (MetaBalancer*)CkLocalBranch(_metalb);
465                 }
466   }
467 }
468
469
470 void LBDatabase::EstObjLoad(const LDObjHandle &_h, double cputime)
471 {
472 #if CMK_LBDB_ON
473   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
474   LBObj *const obj = db->LbObj(_h);
475
476   CmiAssert(obj != NULL);
477   obj->setTiming(cputime);
478 #endif
479 }
480
481 void LBDatabase::ResetAdaptive() {
482 #if CMK_LBDB_ON
483         if (_lb_args.metaLbOn()) {
484                 if (metabalancer == NULL) {
485                         metabalancer = CProxy_MetaBalancer(_metalb).ckLocalBranch();
486                 }
487                 if (metabalancer != NULL) {
488                         metabalancer->ResetAdaptive();
489                 }
490         }
491 #endif
492 }
493
494 void LBDatabase::ResumeClients() {
495 #if CMK_LBDB_ON
496         if (_lb_args.metaLbOn()) {
497                 if (metabalancer == NULL) {
498                         metabalancer = CProxy_MetaBalancer(_metalb).ckLocalBranch();
499                 }
500                 if (metabalancer != NULL) {
501                         metabalancer->ResumeClients();
502                 }
503         }
504 #endif
505   LDResumeClients(myLDHandle);
506 }
507
508 void LBDatabase::SetMigrationCost(double cost) {
509 #if CMK_LBDB_ON
510         if (_lb_args.metaLbOn()) {
511                 if (metabalancer == NULL) {
512                         metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
513                 }
514                 if (metabalancer != NULL)  {
515                         metabalancer->SetMigrationCost(cost);
516                 }
517         }
518 #endif
519 }
520
521 void LBDatabase::SetStrategyCost(double cost) {
522 #if CMK_LBDB_ON
523         if (_lb_args.metaLbOn()) {
524                 if (metabalancer == NULL) {
525                         metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
526                 }
527                 if (metabalancer != NULL)  {
528                         metabalancer->SetStrategyCost(cost);
529                 }
530         }
531 #endif
532 }
533
534 void LBDatabase::UpdateDataAfterLB(double mLoad, double mCpuLoad, double avgLoad) {
535 #if CMK_LBDB_ON
536         if (_lb_args.metaLbOn()) {
537                 if (metabalancer == NULL) {
538                         metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
539                 }
540                 if (metabalancer != NULL)  {
541                         metabalancer->UpdateAfterLBData(mLoad, mCpuLoad, avgLoad);
542                 }
543         }
544 #endif
545 }
546 /*
547   callable from user's code
548 */
549 void TurnManualLBOn()
550 {
551 #if CMK_LBDB_ON
552    LBDatabase * myLbdb = LBDatabase::Object();
553    if (myLbdb) {
554      myLbdb->TurnManualLBOn();
555    }
556    else {
557      LBDatabase::manualOn = 1;
558    }
559 #endif
560 }
561
562 void TurnManualLBOff()
563 {
564 #if CMK_LBDB_ON
565    LBDatabase * myLbdb = LBDatabase::Object();
566    if (myLbdb) {
567      myLbdb->TurnManualLBOff();
568    }
569    else {
570      LBDatabase::manualOn = 0;
571    }
572 #endif
573 }
574
575 extern "C" void LBTurnInstrumentOn() {
576 #if CMK_LBDB_ON
577   if (CkpvAccess(lbdatabaseInited))
578     LBDatabase::Object()->CollectStatsOn();
579   else
580     _lb_args.statsOn() = 1;
581 #endif
582 }
583
584 extern "C" void LBTurnInstrumentOff() {
585 #if CMK_LBDB_ON
586   if (CkpvAccess(lbdatabaseInited))
587     LBDatabase::Object()->CollectStatsOff();
588   else
589     _lb_args.statsOn() = 0;
590 #endif
591 }
592
593 extern "C" void LBTurnCommOn() {
594 #if CMK_LBDB_ON
595   _lb_args.traceComm() = 1;
596 #endif
597 }
598
599 extern "C" void LBTurnCommOff() {
600 #if CMK_LBDB_ON
601   _lb_args.traceComm() = 0;
602 #endif
603 }
604
605 void LBClearLoads() {
606 #if CMK_LBDB_ON
607   LBDatabase::Object()->ClearLoads();
608 #endif
609 }
610
611 void LBTurnPredictorOn(LBPredictorFunction *model) {
612 #if CMK_LBDB_ON
613   LBDatabase::Object()->PredictorOn(model);
614 #endif
615 }
616
617 void LBTurnPredictorOn(LBPredictorFunction *model, int wind) {
618 #if CMK_LBDB_ON
619   LBDatabase::Object()->PredictorOn(model, wind);
620 #endif
621 }
622
623 void LBTurnPredictorOff() {
624 #if CMK_LBDB_ON
625   LBDatabase::Object()->PredictorOff();
626 #endif
627 }
628
629 void LBChangePredictor(LBPredictorFunction *model) {
630 #if CMK_LBDB_ON
631   LBDatabase::Object()->ChangePredictor(model);
632 #endif
633 }
634
635 void LBSetPeriod(double second) {
636 #if CMK_LBDB_ON
637   if (CkpvAccess(lbdatabaseInited))
638     LBDatabase::Object()->SetLBPeriod(second);
639   else
640     _lb_args.lbperiod() = second;
641 #endif
642 }
643
644 #include "LBDatabase.def.h"
645
646 /*@}*/