mwsubdiv.h

Go to the documentation of this file.
00001 
00002 
00003 
00013 
00014 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00015 //
00016 // This file is part of the Homology Library.  This library is free software;
00017 // you can redistribute it and/or modify it under the terms of the GNU
00018 // General Public License as published by the Free Software Foundation;
00019 // either version 2 of the License, or (at your option) any later version.
00020 //
00021 // This library is distributed in the hope that it will be useful,
00022 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 // GNU General Public License for more details.
00025 //
00026 // You should have received a copy of the GNU General Public License along
00027 // with this software; see the file "license.txt".  If not, write to the
00028 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00029 // MA 02111-1307, USA.
00030 
00031 // Started in November 2005. Last revision: February 19, 2009.
00032 
00033 
00034 #ifndef _CHOMP_MULTIWORK_MWSUBDIV_H_
00035 #define _CHOMP_MULTIWORK_MWSUBDIV_H_
00036 
00037 #include <cmath>
00038 #include <iostream>
00039 #include <fstream>
00040 #include <string>
00041 #include <sstream>
00042 #include <exception>
00043 
00044 #include "chomp/system/config.h"
00045 #include "chomp/system/textfile.h"
00046 #include "chomp/system/timeused.h"
00047 #include "chomp/system/arg.h"
00048 #include "chomp/cubes/pointset.h"
00049 #include "chomp/cubes/cube.h"
00050 #include "chomp/multiwork/mw.h"
00051 
00052 
00053 // --------------------------------------------------
00054 // --------------- the output syntax ----------------
00055 // --------------------------------------------------
00056 
00057 // The syntax of lines in the text data file:
00058 // + n intervals. - data no. n sent
00059 // * n result level cube. - cube no. n received
00060 // # level cube. - cube subdivided
00061 
00062 // The syntax of lines in the log file of a coordinator:
00063 // + n. - data no. n prepared
00064 // * n result. - cube no. n received by the coordinator
00065 // ! Message. - data rejected by one of the workers (error)
00066 
00067 // The syntax of lines in the log file of a worker:
00068 // - n. - data no. n received by the worker
00069 // = n result. - data no. n sent back from the worker
00070 // ! Message. - data rejected by the worker (error)
00071 
00072 namespace chomp {
00073 namespace multiwork {
00074 
00075 using chomp::homology::sout;
00076 using chomp::homology::sbug;
00077 using chomp::homology::slog;
00078 using chomp::homology::ignorecomments;
00079 using chomp::homology::ignoreline;
00080 using chomp::homology::hashedset;
00081 using chomp::homology::multitable;
00082 using chomp::homology::tRectangle;
00083 using chomp::homology::tCubeFix;
00084 using chomp::homology::arguments;
00085 using chomp::homology::arg;
00086 using chomp::homology::argswitch;
00087 using chomp::homology::arghelp;
00088 using chomp::homology::argstreams;
00089 using chomp::homology::setstreams;
00090 using chomp::homology::commandline;
00091 using chomp::homology::currenttime;
00092 using chomp::homology::program_time;
00093 
00094 
00095 // --------------------------------------------------
00096 // ---------------- the worker class -----------------
00097 // --------------------------------------------------
00098 
00103 typedef int (*fcompute) (const double *left, const double *right,
00104         int dim, int level);
00105 
00107 template <int dim, class coord>
00108 class mwSubWorker: public mwWorker
00109 {
00110 public:
00112         mwSubWorker (fcompute _compute);
00113 
00114 private:
00116         int Process (mwData &data);
00117 
00119         fcompute compute;
00120 
00121 }; /* class mwSubWorker */
00122 
00123 // --------------------------------------------------
00124 
00125 template <int dim, class coord>
00126 inline mwSubWorker<dim,coord>::mwSubWorker (fcompute _compute):
00127         compute (_compute)
00128 {
00129         return;
00130 } /* mwSubWorker<dim,coord>::mwSubWorker */
00131 
00132 // --------------------------------------------------
00133 
00134 template <int dim, class coord>
00135 int mwSubWorker<dim,coord>::Process (mwData &data)
00136 {
00137         // decode the number of the data pack to process
00138         int current = 0;
00139         data >> current;
00140 
00141         // say which data pack is being processed
00142         sout << "- " << current << ".\n";
00143 
00144         // decode the subdivision level
00145         int level = 0;
00146         data >> level;
00147 
00148         // decode the information on whether this is a full box or a probe
00149         bool full = false;
00150         data >> full;
00151 
00152         // the intervals
00153         double left [dim];
00154         double right [dim];
00155         for (int i = 0; i < dim; ++ i)
00156         {
00157                 data >> left [i];
00158                 if (full)
00159                         data >> right [i];
00160         }
00161 
00162         // the marker of the end of data
00163         int dataEndMarker = 0;
00164         data >> dataEndMarker;
00165         if (dataEndMarker != 13)
00166         {
00167                 data. Reset ();
00168                 sout << "! Incompatible data received. Rejecting it.\n";
00169                 return mwReject;
00170         }
00171 
00172         // rune one set of computations
00173         int result = compute (left, full ? right : left, dim, level);
00174 
00175         // if the result is wrong then reject this piece of data
00176         if (result < 0)
00177         {
00178                 sout << "! Data no. " << current <<
00179                         " produced a negative result. Rejecting it.\n";
00180                 return mwReject;
00181         }
00182 
00183         // say what has been computed
00184         sout << "= " << current << " " << result << ".\n";
00185 
00186         // send back the data containing the result of the processing
00187         data. Reset ();
00188         data << current;
00189         data << result;
00190         return mwOk;
00191 } /* mwSubWorker<dim,coord>::Process */
00192 
00193 
00194 // --------------------------------------------------
00195 // --------------- subdivision points ---------------
00196 // --------------------------------------------------
00197 
00202 template <class coord>
00203 inline double mwSubdivPoint (const double &left, const double &right,
00204         coord part, coord full)
00205 {
00206         // uncomment if using CAPD to switch the rounding mode to the nearest
00207 //      round_nearest ();
00208 
00209         // if this is a boundary subdivision point then return the bound
00210         if (part == 0)
00211                 return left;
00212         else if (part == full)
00213                 return right;
00214 
00215         // divide 'part' and 'full' by their largest common divisor
00216         // which is a power of two
00217         while (!(part & 1) && !(full & 1))
00218         {
00219                 part >>= 1;
00220                 full >>= 1;
00221         }
00222 
00223         // compute the corresponding subdivision point of the interval
00224         double fraction = static_cast<double> (part) / full;
00225         return (left + (right - left) * fraction);
00226 } /* mwSubdivPoint */
00227 
00228 
00229 // --------------------------------------------------
00230 // ----------------- initial probes -----------------
00231 // --------------------------------------------------
00232 
00235 template <int dim, class coord>
00236 class mwIniProbes
00237 {
00238 public:
00240         mwIniProbes (int level = 2);
00241 
00243         ~mwIniProbes ();
00244 
00247         tCubeFix<dim,coord> get ();
00248 
00250         bool available () const;
00251 
00252 private:
00254         mwIniProbes (const mwIniProbes<dim,coord> &);
00255 
00257         mwIniProbes<dim,coord> &operator = (const mwIniProbes<dim,coord> &);
00258 
00260         coord left [dim];
00261 
00263         coord right [dim];
00264 
00266         tRectangle<coord> rect;
00267 
00269         const coord *next;
00270 
00271 }; /* class mwIniProbes */
00272 
00273 // --------------------------------------------------
00274 
00275 template <int dim, class coord>
00276 inline mwIniProbes<dim,coord>::mwIniProbes (int level)
00277 {
00278         if (level < 2)
00279                 throw "Too low initial level. Should be at least 2.";
00280         for (int i = 0; i < dim; ++ i)
00281         {
00282                 this -> left [i] = 1;
00283                 this -> right [i] = 1 << level;
00284         }
00285         this -> rect = tRectangle<coord> (this -> left, this -> right, dim);
00286         this -> next = this -> rect. get ();
00287         return;
00288 } /* mwIniProbes::mwIniProbes */
00289 
00290 template <int dim, class coord>
00291 inline mwIniProbes<dim,coord>::mwIniProbes (const mwIniProbes<dim,coord> &)
00292 {
00293         return;
00294 } /* mwIniProbes::mwIniProbes */
00295 
00296 template <int dim, class coord>
00297 inline mwIniProbes<dim,coord> &mwIniProbes<dim,coord>::operator =
00298         (const mwIniProbes<dim,coord> &)
00299 {
00300         return *this;
00301 } /* mwIniProbes::operator = */
00302 
00303 template <int dim, class coord>
00304 inline mwIniProbes<dim,coord>::~mwIniProbes ()
00305 {
00306         return;
00307 } /* mwIniProbes::~mwIniProbes */
00308 
00309 template <int dim, class coord>
00310 inline tCubeFix<dim,coord> mwIniProbes<dim,coord>::get ()
00311 {
00312         tCubeFix<dim,coord> q (this -> next, dim);
00313         this -> next = this -> rect. get ();
00314         return q;
00315 } /* mwIniProbes::get */
00316 
00317 template <int dim, class coord>
00318 inline bool mwIniProbes<dim,coord>::available () const
00319 {
00320         return !!(this -> next);
00321 } /* mwIniProbes::available */
00322 
00323 
00324 // --------------------------------------------------
00325 // ------------- boxes around a vertex --------------
00326 // --------------------------------------------------
00327 
00330 template <int dim, class coord>
00331 class mwBoxes
00332 {
00333 public:
00335         mwBoxes (const tCubeFix<dim,coord> &q);
00336 
00338         ~mwBoxes ();
00339 
00342         tCubeFix<dim,coord> get ();
00343 
00345         bool available () const;
00346 
00347 private:
00349         mwBoxes (const mwBoxes<dim,coord> &);
00350 
00352         mwBoxes<dim,coord> &operator = (const mwBoxes<dim,coord> &);
00353 
00355         coord left [dim];
00356 
00358         coord right [dim];
00359 
00361         tRectangle<coord> rect;
00362 
00364         const coord *next;
00365 
00366 }; /* class mwBoxes */
00367 
00368 // --------------------------------------------------
00369 
00370 template <int dim, class coord>
00371 inline mwBoxes<dim,coord>::mwBoxes (const tCubeFix<dim,coord> &q)
00372 {
00373         q. coord (this -> left);
00374         for (int i = 0; i < dim; ++ i)
00375         {
00376                 this -> right [i] = left [i] + 1;
00377                 -- (this -> left [i]);
00378         }
00379         this -> rect = tRectangle<coord> (this -> left, this -> right, dim);
00380         this -> next = this -> rect. get ();
00381         return;
00382 } /* mwBoxes::mwBoxes */
00383 
00384 template <int dim, class coord>
00385 inline mwBoxes<dim,coord>::mwBoxes (const mwBoxes<dim,coord> &)
00386 {
00387         return;
00388 } /* mwBoxes::mwBoxes */
00389 
00390 template <int dim, class coord>
00391 inline mwBoxes<dim,coord> &mwBoxes<dim,coord>::operator =
00392         (const mwBoxes<dim,coord> &)
00393 {
00394         return *this;
00395 } /* mwBoxes::operator = */
00396 
00397 template <int dim, class coord>
00398 inline mwBoxes<dim,coord>::~mwBoxes ()
00399 {
00400         return;
00401 } /* mwBoxes::~mwBoxes */
00402 
00403 template <int dim, class coord>
00404 inline tCubeFix<dim,coord> mwBoxes<dim,coord>::get ()
00405 {
00406         const coord *current = this -> next;
00407         this -> next = this -> rect. get ();
00408         return tCubeFix<dim,coord> (current, dim);
00409 } /* mwBoxes::get */
00410 
00411 template <int dim, class coord>
00412 inline bool mwBoxes<dim,coord>::available () const
00413 {
00414         return !!(this -> next);
00415 } /* mwBoxes::available */
00416 
00417 
00418 // --------------------------------------------------
00419 // ---------------- corners of a box ----------------
00420 // --------------------------------------------------
00421 
00424 template <int dim, class coord>
00425 class mwCorners
00426 {
00427 public:
00429         mwCorners (const tCubeFix<dim,coord> &q);
00430 
00432         ~mwCorners ();
00433 
00436         tCubeFix<dim,coord> get ();
00437 
00439         bool available () const;
00440 
00441 private:
00443         mwCorners (const mwCorners<dim,coord> &);
00444 
00446         mwCorners<dim,coord> &operator = (const mwCorners<dim,coord> &);
00447 
00449         coord left [dim];
00450 
00452         coord right [dim];
00453 
00455         tRectangle<coord> rect;
00456 
00458         const coord *next;
00459 
00460 }; /* class mwCorners */
00461 
00462 // --------------------------------------------------
00463 
00464 template <int dim, class coord>
00465 inline mwCorners<dim,coord>::mwCorners (const tCubeFix<dim,coord> &q)
00466 {
00467         q. coord (this -> left);
00468         for (int i = 0; i < dim; ++ i)
00469         {
00470                 this -> right [i] = left [i] + 2;
00471         }
00472         this -> rect = tRectangle<coord> (this -> left, this -> right, dim);
00473         this -> next = this -> rect. get ();
00474         return;
00475 } /* mwCorners::mwCorners */
00476 
00477 template <int dim, class coord>
00478 inline mwCorners<dim,coord>::mwCorners (const mwCorners<dim,coord> &)
00479 {
00480         return;
00481 } /* mwCorners::mwCorners */
00482 
00483 template <int dim, class coord>
00484 inline mwCorners<dim,coord> &mwCorners<dim,coord>::operator =
00485         (const mwCorners<dim,coord> &)
00486 {
00487         return *this;
00488 } /* mwCorners::operator = */
00489 
00490 template <int dim, class coord>
00491 inline mwCorners<dim,coord>::~mwCorners ()
00492 {
00493         return;
00494 } /* mwCorners::~mwCorners */
00495 
00496 template <int dim, class coord>
00497 inline tCubeFix<dim,coord> mwCorners<dim,coord>::get ()
00498 {
00499         const coord *current = this -> next;
00500         this -> next = this -> rect. get ();
00501         return tCubeFix<dim,coord> (current, dim);
00502 } /* mwCorners::get */
00503 
00504 template <int dim, class coord>
00505 inline bool mwCorners<dim,coord>::available () const
00506 {
00507         return !!(this -> next);
00508 } /* mwCorners::available */
00509 
00510 
00511 // --------------------------------------------------
00512 // ---------------- data pack class -----------------
00513 // --------------------------------------------------
00514 
00518 template <int dim, class coord>
00519 class mwSubDataPack
00520 {
00521 public:
00523         mwSubDataPack () {}
00524         
00526         mwSubDataPack (int _num, const tCubeFix<dim,coord> &_q,
00527                 int _level, bool _full):
00528                 num (_num), q (_q), level (_level), full (_full) {}
00529 
00530         // the default copy constructor and operator = is good;
00531         // no destructor is necessary
00532 
00534         int num;
00535 
00537         tCubeFix<dim,coord> q;
00538 
00540         int level;
00541 
00543         bool full;
00544 
00545 }; /* class mwSubDataPack */
00546 
00547 
00548 // --------------------------------------------------
00549 // ------------- the coordinator class --------------
00550 // --------------------------------------------------
00551 
00554 template <int dim, class coord>
00555 class mwSubCoordinator: public mwCoordinator
00556 {
00558         static const int ppMaxSubdiv = 8 * sizeof (coord) - 2;
00559 
00561 //      static const int ppMaxSubdiv;
00562 
00564         typedef tCubeFix<dim,coord> ppCube;
00565 
00567         static const int ppMaxDim = ppCube::MaxDim;
00568 
00570         typedef hashedset<ppCube> ppCubes;
00571 
00573         typedef tRectangle<coord> ppRect;
00574 
00576         typedef mwSubDataPack<dim,coord> ppPack;
00577 
00578 public:
00580         mwSubCoordinator ();
00581 
00583         mwSubCoordinator (const char *filename,
00584                 int _inilevel, int _maxlevel, bool _flushfile,
00585                 const double *_paramLeft, const double *_paramRight);
00586 
00588         ~mwSubCoordinator ();
00589 
00590 private:
00591         // --- the MultiWork interface functions ---
00592 
00594         int Prepare (mwData &data);
00595 
00597         int Accept (mwData &data);
00598 
00600         int Reject (mwData &data);
00601 
00602         // --- classes of probes and boxes ---
00603 
00606         ppCubes Negative [ppMaxSubdiv];
00607 
00610         ppCubes Good [ppMaxSubdiv];
00611 
00613         ppCubes Test [ppMaxSubdiv];
00614 
00616         ppCubes CurProbes [ppMaxSubdiv];
00617 
00619         ppCubes Failed [ppMaxSubdiv];
00620 
00623         ppCubes Successful [ppMaxSubdiv];
00624 
00626         ppCubes Waiting [ppMaxSubdiv];
00627 
00629         ppCubes CurBoxes [ppMaxSubdiv];
00630 
00631         // --- small subroutines ---
00632 
00636         bool FindMinCube
00637                 (const typename mwSubCoordinator<dim,coord>::ppCubes tab [],
00638                 const typename mwSubCoordinator<dim,coord>::ppCubes sent [],
00639                 int minlevel, int maxlevel, int &level,
00640                 typename mwSubCoordinator<dim,coord>::ppCube &q);
00641 
00644         static typename mwSubCoordinator<dim,coord>::ppCube UpLevel
00645                 (const typename mwSubCoordinator<dim,coord>::ppCube &q);
00646 
00649         static typename mwSubCoordinator<dim,coord>::ppCube UpLevel
00650                 (const typename mwSubCoordinator<dim,coord>::ppCube &box,
00651                 const typename mwSubCoordinator<dim,coord>::ppCube &corner);
00652 
00656         static typename mwSubCoordinator<dim,coord>::ppCube DownLevel
00657                 (const typename mwSubCoordinator<dim,coord>::ppCube &q);
00658 
00663         int Contained (const typename mwSubCoordinator<dim,coord>::ppCube &q,
00664                 int level,
00665                 const typename mwSubCoordinator<dim,coord>::ppCubes tab [],
00666                 int minlevel) const;
00667 
00668         // --- processing specific boxes and probes ---
00669 
00671         void NegativeProbe (const ppCube &q, int level);
00672 
00674         void GoodProbe (const ppCube &q, int level);
00675 
00677         void FailedBox (const ppCube &q, int level);
00678 
00680         void SuccessfulBox (const ppCube &q, int level);
00681 
00682         // --- parameters of the computations ---
00683 
00685         double paramLeft [dim];
00686 
00688         double paramRight [dim];
00689 
00692         int inilevel;
00693 
00695         int maxlevel;
00696 
00698         mwIniProbes<dim,coord> iniProbes;
00699 
00702         ppCubes iniProcessed;
00703 
00704         // --- results file ---
00705 
00707         std::ofstream f;
00708 
00710         bool flushfile;
00711 
00713         int ReadResults (std::istream &in);
00714 
00715         // --- data packs ---
00716 
00718         int current;
00719 
00721         multitable<ppPack> sent;
00722 
00724         int sentlen;
00725 
00726         // --- statistics ---
00727 
00729         int countNegative;
00730 
00732         int countGood;
00733 
00735         int countFailed;
00736 
00739         int countSuccessful;
00740 
00741 }; /* class mwSubCoordinator */
00742 
00743 // --------------------------------------------------
00744 
00745 template <int dim, class coord>
00746 const int mwSubCoordinator<dim,coord>::ppMaxSubdiv;
00747 
00748 // --------------------------------------------------
00749 
00750 template <int dim, class coord>
00751 inline mwSubCoordinator<dim,coord>::mwSubCoordinator ()
00752 {
00753         return;
00754 } /* mwSubCoordinator<dim,coord>::mwSubCoordinator */
00755 
00756 template <int dim, class coord>
00757 mwSubCoordinator<dim,coord>::mwSubCoordinator (const char *filename,
00758         int _inilevel, int _maxlevel, bool _flushfile,
00759         const double *_paramLeft, const double *_paramRight):
00760         inilevel ((_inilevel < 2) ? 2 : _inilevel),
00761         maxlevel ((_maxlevel <= inilevel) ? (inilevel + 1) : _maxlevel),
00762         iniProbes (inilevel),
00763         flushfile (_flushfile),
00764         current (0), sentlen (0),
00765         countNegative (0), countGood (0),
00766         countFailed (0), countSuccessful (0)
00767 {
00768         // display a warning if no file name is provided
00769         if (!filename || !*filename)
00770                 sout << "WARNING: No results file name given. "
00771                         "Computation results will not be saved.\n";
00772 
00773         // initialize the subdivision levels
00774         if (maxlevel > ppMaxSubdiv)
00775         {
00776                 sout << "WARNING: Max subdivision level decreased from " <<
00777                         maxlevel << " to " << ppMaxSubdiv << ".\n";
00778                 maxlevel = ppMaxSubdiv;
00779                 if (inilevel >= maxlevel)
00780                         inilevel = maxlevel - 1;
00781         }
00782 
00783         // read the previously computed results of the computations
00784         if (filename && *filename)
00785         {
00786                 std::ifstream in (filename);
00787                 if (!in)
00788                         sout << "Note: Could not open the results file. "
00789                         "Any previous results will be ignored.\n";
00790                 else
00791                 {
00792                         this -> ReadResults (in);
00793                         in. close ();
00794                 }
00795         }
00796 
00797         // open the results file for appending
00798         if (filename && *filename)
00799         {
00800                 f. open (filename, std::ios::out | std::ios::app);
00801                 f << "; Started on " << currenttime ();
00802                 if (flushfile)
00803                         f << std::flush;
00804         }
00805 
00806         // copy the left and right ends of the intervals
00807         for (int i = 0; i < dim; ++ i)
00808         {
00809                 paramLeft [i] = _paramLeft [i];
00810                 paramRight [i] = _paramRight [i];
00811         }
00812 
00813         return;
00814 } /* mwSubCoordinator<dim,coord>::mwSubCoordinator */
00815 
00816 template <int dim, class coord>
00817 inline mwSubCoordinator<dim,coord>::~mwSubCoordinator ()
00818 {
00819         f << "; A total of " << (countNegative + countGood) <<
00820                 " probes and " << (countFailed + countSuccessful) <<
00821                 " boxes have been processed.\n";
00822         f << "; The verification was negative for " << countNegative <<
00823                 " probes, and " << countGood << " probes were good.\n";
00824         f << "; The verification failed for " << countFailed <<
00825                 " boxes, and was successful for " << countSuccessful <<
00826                 " boxes.\n";
00827         f << "; Finished on " << currenttime ();
00828         f << "; ---------------------------------------------------\n";
00829         f. close ();
00830         return;
00831 } /* mwSubCoordinator<dim,coord>::~mwSubCoordinator */
00832 
00833 // --------------------------------------------------
00834 
00835 template <int dim, class coord>
00836 inline bool mwSubCoordinator<dim,coord>::FindMinCube
00837         (const typename mwSubCoordinator<dim,coord>::ppCubes tab [],
00838         const typename mwSubCoordinator<dim,coord>::ppCubes sent [],
00839         int minlevel, int maxlevel,
00840         int &level, typename mwSubCoordinator<dim,coord>::ppCube &q)
00841 {
00842         for (int l = minlevel; l < maxlevel; ++ l)
00843         {
00844                 const ppCubes &theSet = tab [l];
00845                 const ppCubes &sentSet = sent [l];
00846                 int number = theSet. size ();
00847                 for (int i = number - 1; i >= 0; -- i)
00848                 {
00849                         const ppCube &c = theSet [i];
00850                         if (!sentSet. check (c))
00851                         {
00852                                 level = l;
00853                                 q = c;
00854                                 return true;
00855                         }
00856                 }
00857         }
00858         return false;
00859 } /* mwSubCoordinator::FindMinCube */
00860 
00861 template <int dim, class coord>
00862 int mwSubCoordinator<dim,coord>::Prepare (mwData &data)
00863 {
00864         // prepare a data pack to send
00865         ppPack &pack = sent [sentlen];
00866 
00867         // if there is any initial probe that has not yet been processed
00868         // then take this probe
00869         bool iniProbe = false;
00870         while (iniProbes. available ())
00871         {
00872                 pack = ppPack (current, iniProbes. get (), inilevel, false);
00873                 if (iniProcessed. check (pack. q))
00874                 {
00875                         iniProcessed. remove (pack. q);
00876                         continue;
00877                 }
00878                 else
00879                 {
00880                         iniProbe = true;
00881                         break;
00882                 }
00883         }
00884 
00885         // otherwise send a probe or a box which is waiting to be verified
00886         if (!iniProbe)
00887         {
00888                 // find a probe for testing at the lowest level available
00889                 int levelT = 0;
00890                 ppCube cubeT;
00891                 bool foundT = this -> FindMinCube (Test, CurProbes,
00892                         inilevel, maxlevel, levelT, cubeT);
00893 
00894                 // find a box that is waiting at the lowest level available
00895                 int levelW = 0;
00896                 ppCube cubeW;
00897                 bool foundW = this -> FindMinCube (Waiting, CurBoxes,
00898                         inilevel, maxlevel, levelW, cubeW);
00899 
00900                 // if no cube for processing can be found, then interrupt
00901                 if (!foundT && !foundW)
00902                         return mwNoData;
00903 
00904                 // send the probe found if this is the right thing to do
00905                 if (foundT && (!foundW || (levelT <= levelW)))
00906                 {
00907                         pack = ppPack (current, cubeT, levelT, false);
00908                         CurProbes [levelT]. add (cubeT);
00909                 }
00910                 // otherwise send the box found
00911                 else
00912                 {
00913                         pack = ppPack (current, cubeW, levelW, true);
00914                         CurBoxes [levelW]. add (cubeW);
00915                 }
00916         }
00917 
00918         // prepare the intervals of parameters corresponding to the cube
00919         coord c [ppMaxDim];
00920         pack. q. coord (c);
00921         int fullSize = 1 << pack. level;
00922         double left [ppMaxDim];
00923         double right [ppMaxDim];
00924         for (int i = 0; i < dim; ++ i)
00925         {
00926                 // prepare the probe or the left corner of the box
00927                 left [i] = mwSubdivPoint (paramLeft [i], paramRight [i],
00928                         c [i], fullSize);
00929 
00930                 // if this is a full box then compute the right corner, too
00931                 if (pack. full)
00932                 {
00933                         // prepare the right corner of the box
00934                         right [i] =  mwSubdivPoint (paramLeft [i],
00935                                 paramRight [i], c [i] + 1, fullSize);
00936 
00937                         // if the resolution of the representable numbers
00938                         // has been reached then set this level to be
00939                         // the strict upper bound for the subdivision level
00940                         if (left [i] == right [i])
00941                         {
00942                                 // leave a note of this situation in the file
00943                                 f << "; The resolution of representable "
00944                                         "numbers exceeded.\n; Decreasing "
00945                                         "max level from " << maxlevel <<
00946                                         " to " << pack. level << ".\n";
00947                                 if (flushfile)
00948                                         f << std::flush;
00949 
00950                                 // notify the user about this situation
00951                                 sout << "WARNING: The resolution of "
00952                                         "representable numbers exceeded.\n"
00953                                         "Decreasing max level from " <<
00954                                         maxlevel << " to " << pack. level <<
00955                                         ".\n";
00956 
00957                                 // decrease the max level limit
00958                                 maxlevel = pack. level;
00959                                 return mwNoData;
00960                         }
00961                 }
00962         }
00963 
00964         // write th information on the prepared cube to the results file
00965         f << "+ " << pack. num;
00966         for (int i = 0; i < dim; ++ i)
00967         {
00968                 f << (i ? "x[" : " [") << left [i];
00969                 if (pack. full)
00970                         f << "," << right [i];
00971                 f << "]";
00972         }
00973         f << ".\n";
00974         if (flushfile)
00975                 f << std::flush;
00976 
00977         // send the data pack number
00978         data << pack. num;
00979         
00980         // send the subdivision level
00981         data << pack. level;
00982 
00983         // send the information on whether this is a full box or a probe
00984         data << pack. full;
00985 
00986         // send the intervals (left and right ends where applicable)
00987         for (int i = 0; i < dim; ++ i)
00988         {
00989                 data << left [i];
00990                 if (pack. full)
00991                         data << right [i];
00992         }
00993 
00994         // append the data end marker for extra verification
00995         const int dataEndMarker = 13;
00996         data << dataEndMarker;
00997 
00998         // show a message on which data pack has been prepared
00999         sout << "+ " << pack. num << ".\n";
01000 
01001         // increase the counters
01002         ++ current;
01003         ++ sentlen;
01004 
01005         return mwOk;
01006 } /* mwSubCoordinator<dim,coord>::Prepare */
01007 
01008 // --------------------------------------------------
01009 
01010 template <int dim, class coord>
01011 typename mwSubCoordinator<dim,coord>::ppCube
01012         mwSubCoordinator<dim,coord>::UpLevel
01013         (const typename mwSubCoordinator<dim,coord>::ppCube &q)
01014 {
01015         coord c [dim];
01016         q. coord (c);
01017         for (int i = 0; i < dim; ++ i)
01018                 c [i] <<= 1;
01019         return ppCube (c, dim);
01020 } /* mwSubCoordinator::UpLevel */
01021 
01022 template <int dim, class coord>
01023 typename mwSubCoordinator<dim,coord>::ppCube
01024         mwSubCoordinator<dim,coord>::UpLevel
01025         (const typename mwSubCoordinator<dim,coord>::ppCube &box,
01026         const typename mwSubCoordinator<dim,coord>::ppCube &corner)
01027 {
01028         coord cBox [dim];
01029         box. coord (cBox);
01030         coord cCorner [dim];
01031         corner. coord (cCorner);
01032         for (int i = 0; i < dim; ++ i)
01033         {
01034                 if (cBox [i] == cCorner [i])
01035                         cBox [i] <<= 1;
01036                 else
01037                         cBox [i] = (cBox [i] << 1) + 1;
01038         }
01039         return ppCube (cBox, dim);
01040 } /* mwSubCoordinator::UpLevel */
01041 
01042 template <int dim, class coord>
01043 typename mwSubCoordinator<dim,coord>::ppCube
01044         mwSubCoordinator<dim,coord>::DownLevel
01045         (const typename mwSubCoordinator<dim,coord>::ppCube &q)
01046 {
01047         coord c [dim];
01048         q. coord (c);
01049         for (int i = 0; i < dim; ++ i)
01050                 c [i] >>= 1;
01051         return ppCube (c, dim);
01052 } /* mwSubCoordinator::DownLevel */
01053 
01054 template <int dim, class coord>
01055 int mwSubCoordinator<dim,coord>::Contained
01056         (const typename mwSubCoordinator<dim,coord>::ppCube &q, int level,
01057         const typename mwSubCoordinator<dim,coord>::ppCubes tab [],
01058         int minlevel) const
01059 {
01060         // verify if the box itself is contained in any set of boxes
01061         if (tab [level]. check (q))
01062                 return level;
01063 
01064         // subdivide the box and verify at a higher level
01065         if (minlevel < inilevel)
01066                 minlevel = inilevel;
01067         ppCube box = q;
01068         while (-- level > minlevel)
01069         {
01070                 box = DownLevel (box);
01071                 if (tab [level]. check (box))
01072                         return level;
01073         }
01074 
01075         return 0;
01076 } /* mwSubCoordinator::Contained */
01077 
01078 template <int dim, class coord>
01079 void mwSubCoordinator<dim,coord>::NegativeProbe (const ppCube &q, int level)
01080 {
01081         // add the probe to the set of negative probes
01082         Negative [level]. add (q);
01083         sbug << "@ NegProbe [" << level << "]: " << q << "\n";
01084 
01085         // boxes around this probe automatically fail, so remove them
01086         // from the queue and interpret them as failed boxes
01087         mwBoxes<dim,coord> boxes (q);
01088         while (boxes. available ())
01089         {
01090                 // take a box which has this probe in its corner
01091                 ppCube box = boxes. get ();
01092 
01093                 // if it is waiting for processing but was not sent yet
01094                 // then pretend it has just returned as a failed box
01095                 if (Waiting [level]. check (box) &&
01096                         !CurBoxes [level]. check (box))
01097                 {
01098                         sbug << "# FailedBox [" << level << "]: " <<
01099                                 box << "\n";
01100                         Waiting [level]. remove (box);
01101                         FailedBox (box, level);
01102                 }
01103         }
01104 
01105         return;
01106 } /* mwSubCoordinator::NegativeProbe */
01107 
01108 template <int dim, class coord>
01109 void mwSubCoordinator<dim,coord>::GoodProbe (const ppCube &q, int level)
01110 {
01111         // if it is already known that this probe is good then skip it
01112         if (Good [level]. check (q))
01113         {
01114                 sbug << "@ GoodKnown [" << level << "]: " << q << "\n";
01115                 return;
01116         }
01117 
01118         // add the probe to the set of good probes at its level
01119         Good [level]. add (q);
01120         sbug << "@ GoodProbe [" << level << "]: " << q << "\n";
01121 
01122         // if the next level is beyond the scope then quit here
01123         if (level + 1 == maxlevel)
01124                 return;
01125 
01126         // transfer the probe to the next level and remember that it is good
01127         ppCube probe = UpLevel (q);
01128         Good [level + 1]. add (probe);
01129         sbug << "+ GoodProbe [" << (level + 1) << "]: " << probe << "\n";
01130 
01131         // consider all the boxes which contain this probe
01132         mwBoxes<dim,coord> boxes (probe);
01133         while (boxes. available ())
01134         {
01135                 // if the box is not contained in any larger successful box
01136                 // then add it to the waiting list
01137                 ppCube box = boxes. get ();
01138                 if (!Contained (box, level + 1, Successful, 0))
01139                 {
01140                         
01141                         Waiting [level + 1]. add (box);
01142                         sbug << "+ Waiting [" << (level + 1) << "]: " <<
01143                                 box << "\n";
01144                 }
01145         }
01146 
01147         return;
01148 } /* mwSubCoordinator::GoodProbe */
01149 
01150 template <int dim, class coord>
01151 void mwSubCoordinator<dim,coord>::FailedBox (const ppCube &q, int level)
01152 {
01153         // add the box to the list of boxes which failed
01154         Failed [level]. add (q);
01155         sbug << "@ FailedBox [" << level << "]: " << q << "\n";
01156 
01157         // if no further subdivisions are to be considered then quit here
01158         if (level + 1 == maxlevel)
01159                 return;
01160 
01161         // consider all the corners of the box
01162         mwCorners<dim,coord> corners (q);
01163         while (corners. available ())
01164         {
01165                 // take the next corner of the box
01166                 ppCube c = corners. get ();
01167 
01168                 // if this is a negative probe then skip it
01169                 if (Negative [level]. check (c))
01170                         continue;
01171 
01172                 // if this probe has not yet been checked
01173                 // then add it to the list of probes to test
01174                 if (!Good [level]. check (c))
01175                 {
01176                         Test [level]. add (c);
01177                         sbug << "+ Test [" << level << "]: " << c << "\n";
01178                         continue;
01179                 }
01180 
01181                 // add a twice smaller box located at the given corner
01182                 // to the list of boxes which wait for being verified,
01183                 // unless the result for this box is already known
01184                 ppCube box = UpLevel (q, c);
01185                 if (!Successful [level + 1]. check (box) &&
01186                         !Failed [level + 1]. check (box))
01187                 {
01188                         Waiting [level + 1]. add (box);
01189                         sbug << "+ Waiting [" << (level + 1) << "]: " <<
01190                                 box << "\n";
01191                 }
01192 
01193                 // mark the probe as good at the higher subdivision level
01194                 ppCube probe = UpLevel (c);
01195                 Good [level + 1]. add (probe);
01196                 sbug << "+ Good [" << (level + 1) << "]: " << probe << "\n";
01197         }
01198 
01199         return;
01200 } /* mwSubCoordinator::FailedBox */
01201 
01202 template <int dim, class coord>
01203 void mwSubCoordinator<dim,coord>::SuccessfulBox (const ppCube &q, int level)
01204 {
01205         // if the box has already been added then skip it
01206         if (Successful [level]. check (q))
01207         {
01208                 sbug << "@ SuccessKnown [" << level << "]: " << q << "\n";
01209                 return;
01210         }
01211 
01212         // if this box is already contained in a larger successful box
01213         // then ignore it
01214         if (Contained (q, level, Successful, 0))
01215         {
01216                 sbug << "@ SuccessSubset [" << level << "]: " << q << "\n";
01217                 return;
01218         }
01219 
01220         // add the box to the set of successful boxes which form the set A
01221         Successful [level]. add (q);
01222         sbug << "@ SuccessBox [" << level << "]: " << q << "\n";
01223 
01224         // consider all the vertices of this box
01225         mwCorners<dim,coord> corners (q);
01226         while (corners. available ())
01227         {
01228                 // take the next corner of the box
01229                 ppCube c = corners. get ();
01230 
01231                 // remove the corner probe from a list of probes to test
01232                 if (Test [level]. check (c))
01233                 {
01234                         Test [level]. remove (c);
01235                         sbug << "- Test [" << level << "]: " << c << "\n";
01236                 }
01237 
01238                 // remove the corner box from a list of boxes to test
01239                 ppCube cornerBox = UpLevel (q, c);
01240                 if (Waiting [level + 1]. check (cornerBox))
01241                 {
01242                         Waiting [level + 1]. remove (cornerBox);
01243                         sbug << "- Waiting [" << (level + 1) << "]: " <<
01244                                 cornerBox << "\n";
01245                         // note: there might be some boxes contained in q
01246                         // waiting at deeper levels, but determining them
01247                         // might be quite inefficient,
01248                         // so they are not cleaned in this implementation
01249                         // of the algorithm
01250                 }
01251 
01252                 // if the probe is already known to be good then skip it
01253                 if (Good [level]. check (c))
01254                         continue;
01255 
01256                 // add the probe to the list of good ones
01257                 Good [level]. add (c);
01258                 sbug << "+ Good [" << level << "]: " << c << "\n";
01259 
01260                 // propagate the probe one level deeper and mark it as good
01261                 ppCube probe = UpLevel (c);
01262                 Good [level + 1]. add (probe);
01263                 sbug << "+ Good [" << (level + 1) << "]: " << probe << "\n";
01264 
01265                 // consider all the boxes which contain this probe
01266                 mwBoxes<dim,coord> boxes (probe);
01267                 while (boxes. available ())
01268                 {
01269                         // take the next box
01270                         ppCube box = boxes. get ();
01271 
01272                         // if this box is not contained in any successful
01273                         // larger box then add it to the waiting list
01274                         if (!Contained (box, level + 1, Successful, 0))
01275                         {
01276                                 Waiting [level + 1]. add (box);
01277                                 sbug << "+ Waiting [" << (level + 1) <<
01278                                         "]: " << box << "\n";
01279                         }
01280                 }
01281         }
01282 
01283         return;
01284 } /* mwSubCoordinator::SuccessfulBox */
01285 
01286 template <int dim, class coord>
01287 int mwSubCoordinator<dim,coord>::Accept (mwData &data)
01288 {
01289         // decode the data pack number
01290         int n = 0;
01291         data >> n;
01292 
01293         // decode the result
01294         int result = 0;
01295         data >> result;
01296 
01297         // say what has been received
01298         sout << "* " << n << " " << result << ".\n";
01299 
01300         // find this data among the data packs that were sent for processing
01301         int pos = 0;
01302         while ((pos < sentlen) && (sent [pos]. num != n))
01303                 ++ pos;
01304         if (pos >= sentlen)
01305         {
01306                 sout << "ERROR: Wrong data pack number received "
01307                         "from a worker.\n";
01308                 return mwError;
01309         }
01310         const ppPack &pack = sent [pos];
01311 
01312         // save the data to the output file
01313         f << (pack. full ? "* " : "@ ") << n << " " << result <<
01314                 " " << pack. level << " " << pack. q << ".\n";
01315         if (flushfile)
01316                 f << std::flush;
01317         
01318         // extract the data from the data pack
01319         const ppCube &q = pack. q;
01320         int level = pack. level;
01321         bool full = pack. full;
01322 
01323         // remove the cube from appropriate sets and process it
01324         if (full)
01325         {
01326                 CurBoxes [level]. remove (q);
01327                 Waiting [level]. remove (q);
01328                 if (result)
01329                 {
01330                         ++ countSuccessful;
01331                         SuccessfulBox (q, level);
01332                 }
01333                 else
01334                 {
01335                         ++ countFailed;
01336                         FailedBox (q, level);
01337                 }
01338         }
01339         else
01340         {
01341                 CurProbes [level]. remove (q);
01342                 Test [level]. remove (q);
01343                 if (result)
01344                 {
01345                         ++ countGood;
01346                         GoodProbe (q, level);
01347                 }
01348                 else
01349                 {
01350                         ++ countNegative;
01351                         NegativeProbe (q, level);
01352                 }
01353         }
01354 
01355         // remove the data pack from the table containing the data packs
01356         -- sentlen;
01357         if (pos != sentlen)
01358                 sent [pos] = sent [sentlen];
01359 
01360         return mwOk;
01361 } /* mwSubCoordinator<dim,coord>::Accept */
01362 
01363 template <int dim, class coord>
01364 int mwSubCoordinator<dim,coord>::Reject (mwData &data)
01365 {
01366         // decode the number
01367         int n = 0;
01368         data >> n;
01369 
01370         // say that data has been rejected
01371         sout << "!!! Data no. " << n << " rejected.\n";
01372 
01373         return mwError;
01374 } /* mwSubCoordinator<dim,coord>::Reject */
01375 
01376 // --------------------------------------------------
01377 
01378 template <int dim, class coord>
01379 int mwSubCoordinator<dim,coord>::ReadResults (std::istream &in)
01380 {
01381         ignorecomments (in);
01382         while (!in. eof ())
01383         {
01384                 // read the first char and interprete the line
01385                 int ch = in. get ();
01386 
01387                 // ignore the line if it contains no useful information
01388                 if ((ch != '*') && (ch != '@'))
01389                 {
01390                         ignoreline (in);
01391                         ignorecomments (in);
01392                         continue;
01393                 }
01394         
01395                 // read the data number if relevant
01396                 if ((ch == '*') || (ch == '@'))
01397                 {
01398                         int n = -1;
01399                         in >> n;
01400                         if (n < 0)
01401                                 break;
01402                 }
01403 
01404                 // read the result if any
01405                 int result = -1;
01406                 if ((ch == '*') || (ch == '@'))
01407                 {
01408                         in >> result;
01409                         if (result < 0)
01410                                 break;
01411                 }
01412 
01413                 // read the subdivision level of the cube
01414                 int level = -1;
01415                 in >> level;
01416                 if (level < 0)
01417                         break;
01418 
01419                 // read the cube itself
01420                 ppCube q;
01421                 in >> q;
01422 
01423                 // make sure that there is the dot which ends the line
01424                 if (in. peek () != '.')
01425                         break;
01426 
01427                 // ignore the remaining part of the line
01428                 ignoreline (in);
01429                 ignorecomments (in);
01430 
01431                 // process the data as necessary
01432                 if (ch == '*')
01433                 {
01434                         Waiting [level]. remove (q);
01435                         if (result)
01436                                 SuccessfulBox (q, level);
01437                         else
01438                                 FailedBox (q, level);
01439                 }
01440                 else if (ch == '@')
01441                 {
01442                         if (level == inilevel)
01443                                 iniProcessed. add (q);
01444                         else
01445                                 Test [level]. remove (q);
01446                         if (result)
01447                                 GoodProbe (q, level);
01448                         else
01449                                 NegativeProbe (q, level);
01450                 }
01451         }
01452 
01453         return 0;
01454 } /* mwSubCoordinator<dim,coord>::ReadResults */
01455 
01456 
01457 // --------------------------------------------------
01458 // ---------------------- MAIN ----------------------
01459 // --------------------------------------------------
01460 
01464 template <int dim, class coord>
01465 int mwSubdivMain (int argc, char *argv [],
01466         const char *title, const char *helpinfo,
01467         int defaultPortNumber, int controlNumber,
01468         const double *paramLeft, const double *paramRight,
01469         int minSubdivLevel, fcompute compute)
01470 {
01471         const char *arginfo = "\
01472 Command line arguments (at least '-w' or '-m N' must be specified):\n\
01473 -w [port] - run as a worker (by default the program runs as a coordinator),\n\
01474 -c [port] - run as a coordinator only (don't process any data locally),\n\
01475 -p port - set the port number for the multi-work communication,\n\
01476 -k - keep workers waiting after the computations have been completed,\n\
01477 computer:port - use this connection at start-up (can be repeated),\n\
01478 -s FILE - save the workers' list to this file (default: mwsubdiv.txt),\n\
01479 -r FILE - retrieve the workers' list from this file (def: mwsubdiv.txt),\n\
01480 -f filename - results file (new results will be appended); coord only!\n\
01481 --flush - flush the results file very frequently (slows down the program),\n\
01482 -i N - set the initial subdivision level (some minimum is enforced),\n\
01483 -m N - set the maximal subdivision level (default: inilevel + 2),\n\
01484 -q - quit all the workers who are waiting (provide addresses or use -r),\n\
01485 --quiet - do not display any messages on the standard output,\n\
01486 --log filename - save the console output to the given file,\n\
01487 --help - show this brief help information and exit.\n\
01488 For more information ask the author at http://www.PawelPilarczyk.com/.";
01489 
01490         // prepare user-configurable data
01491         char *retrieveworkers = 0;
01492         char *saveworkers = 0;
01493         const int maxaddr = 1024;
01494         char *addr [maxaddr];
01495         int naddr = 0;
01496         int portnum = -1;
01497         int workport = -1;
01498         int coordport = -1;
01499         bool keepworkers = false;
01500         bool quitworkers = false;
01501         char *filename = 0;
01502         int inilevel = 0;
01503         int maxlevel = 0;
01504         bool flushfile = false;
01505 
01506         // interprete the command-line arguments
01507         arguments a;
01508         arg (a, 0, addr, naddr, maxaddr);
01509         arg (a, "r", retrieveworkers, "mwsubdiv.txt");
01510         arg (a, "s", saveworkers, "mwsubdiv.txt");
01511         arg (a, "f", filename);
01512         arg (a, "i", inilevel);
01513         arg (a, "m", maxlevel);
01514         arg (a, "w", workport, defaultPortNumber);
01515         arg (a, "p", portnum);
01516         arg (a, "c", coordport, defaultPortNumber);
01517         argswitch (a, "k", keepworkers, true);
01518         argswitch (a, "q", quitworkers, true);
01519         argswitch (a, "-flush", flushfile, true);
01520         arghelp (a);
01521 
01522         argstreamprepare (a);
01523         int argresult = a. analyze (argc, argv);
01524         argstreamset ();
01525 
01526         // show the program's main title
01527         if (argresult >= 0)
01528                 sout << title << '\n';
01529 
01530         // if something was incorrect, show an additional message and exit
01531         if (argresult < 0)
01532         {
01533                 sout << "Call with '--help' for help.\n";
01534                 return 2;
01535         }
01536 
01537         // set the right port number and determine if to run as a worker
01538         // or as a coordinator, with or without local work
01539         int port = defaultPortNumber;
01540         bool localwork = (coordport < 0);
01541         if (coordport >= 0)
01542                 port = coordport;
01543         bool worker = (workport >= 0);
01544         if (workport >= 0)
01545                 port = workport;
01546         if (portnum >= 0)
01547                 port = portnum;
01548 
01549         // if no data packs are to be processed, don't run the program
01550         if (!maxlevel && !worker && !quitworkers)
01551                 argresult = 1;
01552         
01553         // if help requested, show help information
01554         if (argresult > 0)
01555         {
01556                 sout << helpinfo << '\n' << arginfo << '\n';
01557                 return 1;
01558         }
01559 
01560         // try running the main function and catch an error message if thrown
01561         try
01562         {
01563                 // set an appropriate program time message
01564                 program_time = "Aborted after:";
01565                 program_time = 1;
01566 
01567                 // quit all the workers from the list if requested to
01568                 if (quitworkers)
01569                 {
01570                         // prepare a dummy coordinator class
01571                         mwSubCoordinator<dim,coord> c;
01572 
01573                         // set up the parameters necessary for identification
01574                         c. Port (port);
01575                         c. ControlNumber (controlNumber);
01576 
01577                         // prepare a list of workers' addresses
01578                         if (retrieveworkers)
01579                                 c. Load (retrieveworkers);
01580                         for (int i = 0; i < naddr; ++ i)
01581                                 c. Add (addr [i]);
01582 
01583                         // quit all the workers which appear in the list
01584                         sout << "Quitting workers... ";
01585                         c. QuitWorkers ();
01586                         sout << "Done.\n";
01587                 }
01588 
01589                 // run as a worker if requested to
01590                 else if (worker)
01591                 {
01592                         // prepare a worker object
01593                         mwSubWorker<dim,coord> w (compute);
01594 
01595                         // set up various options of the worker object
01596                         w. Port (port);
01597                         w. ControlNumber (controlNumber);
01598                         for (int i = 0; i < naddr; ++ i)
01599                                 w. Add (addr [i]);
01600 
01601                         // run the computations
01602                         sout << "Running as a worker...\n";
01603                         int result = w. Work ();
01604                         if (result == mwOk)
01605                                 sout << "Work completed successfully.\n";
01606                         else
01607                                 sout << "Could not work - probably "
01608                                         "an error occurred.\n";
01609                 }
01610 
01611                 // run as a coordinator otherwise
01612                 else
01613                 {
01614                         // make a correction to the subdivision level bounds
01615                         if (inilevel <= minSubdivLevel)
01616                                 inilevel = minSubdivLevel;
01617                         if (maxlevel <= inilevel)
01618                                 maxlevel = inilevel + 2;
01619 
01620                         // prepare a local worker and a coordinator
01621                         mwSubWorker<dim,coord> w (compute);
01622                         mwSubCoordinator<dim,coord> c (filename, inilevel,
01623                                 maxlevel, flushfile, paramLeft, paramRight);
01624 
01625                         // set up various options of the coordinator
01626                         c. KeepWorkers (keepworkers);
01627                         c. Port (port);
01628                         c. ControlNumber (controlNumber);
01629                         for (int i = 0; i < naddr; ++ i)
01630                                 c. Add (addr [i]);
01631                         if (retrieveworkers)
01632                                 c. Load (retrieveworkers);
01633 
01634                         // run the computations
01635                         sout << "Running as a coordinator...\n";
01636                         int result = c. Coordinate (localwork ? &w : 0);
01637                         if (result == mwOk)
01638                                 sout << "The task completed successfully.\n";
01639                         else
01640                                 sout << "Could not coordinate - probably "
01641                                         "an error occurred.\n";
01642 
01643                         // save the connected workers if necessary
01644                         if (saveworkers)
01645                                 c. SaveWorkers (saveworkers);
01646                 }
01647 
01648                 // set an appropriate program time message
01649                 program_time = "Total time used:";
01650 
01651                 // finalize
01652                 return 0;
01653         }
01654         catch (const char *msg)
01655         {
01656                 sout << "ERROR: " << msg << '\n';
01657                 return -1;
01658         }
01659         catch (const std::exception &e)
01660         {
01661                 sout << "ERROR: " << e. what () << '\n';
01662                 return -1;
01663         }
01664         catch (...)
01665         {
01666                 sout << "ABORT: An unknown error occurred.\n";
01667                 return -1;
01668         }
01669 } /* mwSubdivMain */
01670 
01671 
01672 } // namespace multiwork
01673 } // namespace chomp
01674 
01675 #endif // _CHOMP_MULTIWORK_MWSUBDIV_H_
01676 
01678