neighbor.h

Go to the documentation of this file.
00001 
00002 
00003 
00014 
00015 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00016 //
00017 // This file is part of the Homology Library.  This library is free software;
00018 // you can redistribute it and/or modify it under the terms of the GNU
00019 // General Public License as published by the Free Software Foundation;
00020 // either version 2 of the License, or (at your option) any later version.
00021 //
00022 // This library is distributed in the hope that it will be useful,
00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 // GNU General Public License for more details.
00026 //
00027 // You should have received a copy of the GNU General Public License along
00028 // with this software; see the file "license.txt".  If not, write to the
00029 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00030 // MA 02111-1307, USA.
00031 
00032 // Started in January 2002. Last revision: October 25, 2008.
00033 
00034 
00035 #ifndef _CHOMP_CUBES_NEIGHBOR_H_
00036 #define _CHOMP_CUBES_NEIGHBOR_H_
00037 
00038 #include "chomp/system/config.h"
00039 #include "chomp/system/textfile.h"
00040 #include "chomp/cubes/pointset.h"
00041 #include "chomp/struct/hashsets.h"
00042 #include "chomp/cubes/pointbas.h"
00043 #include "chomp/cubes/cube.h"
00044 #include "chomp/cubes/cell.h"
00045 #include "chomp/homology/cubacycl.h"
00046 #include "chomp/homology/tabulate.h"
00047 #include "chomp/homology/known.h"
00048 
00049 #include <iostream>
00050 #include <fstream>
00051 #include <cstdlib>
00052 
00053 namespace chomp {
00054 namespace homology {
00055 
00056 // --------------------------------------------------
00057 // ----------------- max neighbors ------------------
00058 // --------------------------------------------------
00059 
00061 inline int_t getmaxneighbors (int dim)
00062 {
00063         if (dim < 0)
00064                 return 0;
00065         const int maxdim = 17;
00066         const int neighbors [maxdim] = {0, 2, 8, 26, 80, 242, 728,
00067                 2186, 6560, 19682, 59048, 177146, 531440, 1594322,
00068                 4782968, 14348906, 43046720};
00069         if (dim < maxdim)
00070                 return neighbors [dim];
00071         int_t ncount = neighbors [maxdim - 1] + 1;
00072         for (int i = maxdim - 1; i < dim; ++ i)
00073                 ncount *= 3;
00074         return (ncount - 1);
00075 } /* getmaxneighbors */
00076 
00077 
00078 // --------------------------------------------------
00079 // ----------------- neighbor bits ------------------
00080 // --------------------------------------------------
00081 
00084 template <class tCube>
00085 int_t neighbor2bit (const tCube &q, const tCube &neighbor)
00086 {
00087         // define the type of coordinates
00088         typedef typename tCube::CoordType coordType;
00089 
00090         coordType c0 [tCube::MaxDim];
00091         q. coord (c0);
00092         coordType c1 [tCube::MaxDim];
00093         neighbor. coord (c1);
00094         int dim = q. dim ();
00095 
00096         int_t number = 0;
00097         const coordType *wrap = tCube::PointBase::getwrapping (dim);
00098         for (int i = 0; i < dim; ++ i)
00099         {
00100                 if (i)
00101                         number *= 3;
00102                 switch (c1 [i] - c0 [i])
00103                 {
00104                         case -1:
00105                                 ++ number;
00106                         case 1:
00107                                 ++ number;
00108                                 break;
00109                         case 0:
00110                                 break;
00111                         default:
00112                                 if (!wrap || !wrap [i])
00113                                         return -1;
00114                                 if ((c1 [i] - c0 [i]) == (wrap [i] - 1))
00115                                         number += 2;
00116                                 else if ((c1 [i] - c0 [i]) == (1 - wrap [i]))
00117                                         ++ number;
00118                                 else
00119                                         return -1;
00120                                 break;
00121                 }
00122         }
00123 
00124         return number - 1;
00125 } /* neighbor2bit */
00126 
00129 template <class tCube>
00130 int_t neighbor2bit (const tCube &q, const typename tCube::CellType &face)
00131 {
00132         // define the type of coordinates
00133         typedef typename tCube::CoordType coordType;
00134 
00135         // determine the space dimension and the coordinates of the input
00136         int dim = q. dim ();
00137         coordType coord [tCube::MaxDim];
00138         q. coord (coord);
00139         coordType cLeft [tCube::MaxDim];
00140         face. leftcoord (cLeft);
00141         coordType cRight [tCube::MaxDim];
00142         face. rightcoord (cRight);
00143 
00144         // compute the number of the neighbor based on the coordinates
00145         int_t number = 0;
00146         for (int i = 0; i < dim; ++ i)
00147         {
00148                 if (i)
00149                         number *= 3;
00150                 // if the neighbor is shifted upwards
00151                 if (cLeft [i] != coord [i])
00152                         number += 1;
00153                 // if the neighbor is shifted downwards
00154                 else if (cRight [i] == cLeft [i])
00155                         number += 2;
00156                 // otherwise the neighbor is at the same level
00157         }
00158 
00159         return number - 1;
00160 } /* neighbor2bit */
00161 
00165 template <class tCube>
00166 tCube bit2neighbor (const tCube &q, int_t number, bool unconditional = false)
00167 {
00168         // define the type of coordinates
00169         typedef typename tCube::CoordType coordType;
00170 
00171         coordType c0 [tCube::MaxDim];
00172         q. coord (c0);
00173         coordType c1 [tCube::MaxDim];
00174         int dim = q. dim ();
00175 
00176         ++ number;
00177         for (int i = dim - 1; i >= 0; -- i)
00178         {
00179                 switch (number % 3)
00180                 {
00181                         case 2:
00182                                 c1 [i] = c0 [i] - 1;
00183                                 break;
00184                         case 1:
00185                                 c1 [i] = c0 [i] + 1;
00186                                 break;
00187                         case 0:
00188                                 c1 [i] = c0 [i];
00189                                 break;
00190                         default:
00191                                 throw "Erratic neighbor.";
00192                 }
00193                 number /= 3;
00194         }
00195 
00196         if (unconditional || tCube::PointBase::check (c1, dim))
00197                 return tCube (c1, dim);
00198         else
00199                 return q;
00200 } /* bit2neighbor */
00201 
00202 
00203 // --------------------------------------------------
00204 // ----------------- get neighbors ------------------
00205 // --------------------------------------------------
00206 
00211 template <class tCube, class tCubeSet1, class tCubeSet2>
00212 int_t getneighbors_scan (const tCube &q, BitField *bits,
00213         const tCubeSet1 &theset, tCubeSet2 *neighbors, int_t limit)
00214 {
00215         // prepare a counter for the number of neighbors
00216         int_t count = 0;
00217 
00218         // go through all the elements in the set
00219         for (int_t i = 0; i < theset. size (); ++ i)
00220         {
00221                 // if this is the current cube, ignore it
00222                 if (theset [i] == q)
00223                         continue;
00224 
00225                 // determine the number of this neighbor
00226                 int_t number = neighbor2bit (q, theset [i]);
00227 
00228                 // if not neighbor, ignore it
00229                 if (number < 0)
00230                         continue;
00231 
00232                 // set the corresponding bit in the bit field
00233                 if (bits)
00234                         bits -> set (number);
00235 
00236                 // add the cube to the set of neighbors
00237                 if (neighbors)
00238                         neighbors -> add (theset [i]);
00239 
00240                 // increase the counter
00241                 ++ count;
00242 
00243                 // if this is enough then finish
00244                 if (limit && (count >= limit))
00245                         return count;
00246         }
00247 
00248         return count;
00249 } /* getneighbors_scan */
00250 
00255 template <class tCube, class tCubeSet1, class tCubeSet2>
00256 int_t getneighbors_generate (const tCube &q, BitField *bits,
00257         const tCubeSet1 &theset, tCubeSet2 *neighbors, int_t limit)
00258 {
00259         // determine the upper bound for the number of neighbors
00260         int_t maxneighbors = getmaxneighbors (q. dim ());
00261 
00262         // prepare a counter for the number of neighbors
00263         int_t count = 0;
00264 
00265         // go through all possible neighbor numbers
00266         for (int_t number = 0; number < maxneighbors; ++ number)
00267         {
00268                 // create a neighbor cube
00269                 tCube neighbor = bit2neighbor (q, number);
00270 
00271                 // if the neighbor doesn't exist, ignore it
00272                 if (neighbor == q)
00273                         continue;
00274 
00275                 // if this cube is not in the set, ignore it
00276                 if (!theset. check (neighbor))
00277                         continue;
00278 
00279                 // set the appropriate bit in the bit field
00280                 if (bits)
00281                         bits -> set (number);
00282 
00283                 // add the cube to the set of neighbors
00284                 if (neighbors)
00285                         neighbors -> add (neighbor);
00286 
00287                 // increase the counter
00288                 ++ count;
00289 
00290                 // if this is enough then finish
00291                 if (limit && (count >= limit))
00292                         return count;
00293         }
00294 
00295         return count;
00296 } /* getneighbors_generate */
00297 
00302 template <class tCube, class tCubeSet1, class tCubeSet2>
00303 int_t getneighbors (const tCube &q, BitField *bits,
00304         const tCubeSet1 &theset, tCubeSet2 *neighbors, int_t limit)
00305 {
00306         // if the answer is trivial, return it
00307         if (theset. empty ())
00308                 return 0;
00309 
00310         // if the set is small
00311         if (theset. size () < getmaxneighbors (q. dim ()))
00312         {
00313                 return getneighbors_scan (q, bits, theset, neighbors, limit);
00314         }
00315         else
00316         {
00317                 return getneighbors_generate (q, bits, theset, neighbors,
00318                         limit);
00319         }
00320 } /* getneighbors */
00321 
00322 // Gets neighbors of the given cube from the given set and indicates them
00323 // in the bit field provided. Returns the number of neighbors.
00324 // If the limit is nonzero then quits after having found
00325 // that many neighbors.
00326 template <class tCube, class tCubeSet>
00327 int_t getneighbors (const tCube &q, BitField *bits,
00328         const tCubeSet &theset, int_t limit)
00329 {
00330         hashedset<typename tCubeSet::value_type> *none = 0;
00331         return getneighbors (q, bits, theset, none, limit);
00332 } /* getneighbors */
00333 
00334 
00335 // --------------------------------------------------
00336 // ----------------- add neighbors ------------------
00337 // --------------------------------------------------
00338 
00342 template <class tCube, class tCubeSet>
00343 int_t addneighbors (const tCube &q, const BitField &bits, tCubeSet &set,
00344         const tCubeSet &notthese)
00345 {
00346         int_t maxneighbors = getmaxneighbors (q. dim ());
00347 
00348         int_t count = 0;
00349         int_t number = bits. find (0, maxneighbors);
00350         while (number >= 0)
00351         {
00352                 tCube neighbor = bit2neighbor (q, number);
00353                 if (!notthese. check (neighbor))
00354                         set. add (neighbor);
00355                 number = bits. find (number + 1, maxneighbors);
00356                 ++ count;
00357         }
00358 
00359         return count;
00360 } /* addneighbors */
00361 
00364 template <class tCube, class tCubeSet>
00365 int_t addneighbors (const tCube &q, const BitField &bits, tCubeSet &set,
00366         bool unconditional = false)
00367 {
00368         int_t maxneighbors = getmaxneighbors (q. dim ());
00369         int_t count = 0;
00370 
00371         int_t number = bits. find (0, maxneighbors);
00372         while (number >= 0)
00373         {
00374                 tCube neighbor = bit2neighbor (q, number, unconditional);
00375                 set. add (neighbor);
00376                 number = bits. find (number + 1, maxneighbors);
00377                 ++ count;
00378         }
00379 
00380         return count;
00381 } /* addneighbors */
00382 
00386 template <class tCube, class tCell>
00387 int_t addneighbors (const tCube &q, const BitField &bits,
00388         gcomplex<tCell,integer> &c, bool unconditional = false)
00389 {
00390         // define the type of coordinates
00391         typedef typename tCube::CoordType coordType;
00392 
00393         // determine the space dimension
00394         int dim = q. dim ();
00395 
00396         // compute the maximal number of neighbors
00397         int_t maxneighbors = getmaxneighbors (dim);
00398 
00399         // extract the coordinates of the central cube
00400         coordType coord [tCube::MaxDim];
00401         q. coord (coord);
00402 
00403         // prepare arrays for the coordinates of boundary cells
00404         coordType cLeft [tCube::MaxDim];
00405         coordType cRight [tCube::MaxDim];
00406 
00407         // prepare a counter of boundary cells
00408         int_t count = 0;
00409 
00410         // find the first neighbor number
00411         int_t number = bits. find (0, maxneighbors);
00412 
00413         // process all the neighbor numbers
00414         while (number >= 0)
00415         {
00416                 // prepare the coordinates of the boundary cell
00417                 int_t n = number + 1;
00418                 for (int i = dim - 1; i >= 0; -- i)
00419                 {
00420                         switch (n % 3)
00421                         {
00422                                 case 2:
00423                                         cLeft [i] = coord [i];
00424                                         cRight [i] = coord [i];
00425                                         break;
00426                                 case 1:
00427                                         cLeft [i] = coord [i] + 1;
00428                                         cRight [i] = coord [i] + 1;
00429                                         break;
00430                                 case 0:
00431                                         cLeft [i] = coord [i];
00432                                         cRight [i] = coord [i] + 1;
00433                                         break;
00434                         }
00435                         n /= 3;
00436                 }
00437 
00438                 // add the cell to the complex of boundary cells
00439                 c. add (tCell (cLeft, cRight, dim));
00440 
00441                 // increase the counter of boundary cells
00442                 ++ count;
00443 
00444                 // take the next neighbor number
00445                 number = bits. find (number + 1, maxneighbors);
00446         }
00447 
00448         return count;
00449 } /* addneighbors */
00450 
00451 
00452 } // namespace homology
00453 } // namespace chomp
00454 
00455 #endif // _CHOMP_CUBES_NEIGHBOR_H_
00456 
00458