Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Box.cpp

    r57f243 r0ae36b  
    1111
    1212#include <cmath>
    13 #include <iostream>
    14 #include <cstdlib>
    1513
    16 #include "LinearAlgebra/Matrix.hpp"
    17 #include "LinearAlgebra/Vector.hpp"
    18 #include "LinearAlgebra/Plane.hpp"
     14#include "Matrix.hpp"
     15#include "vector.hpp"
    1916
    2017#include "Helpers/Assert.hpp"
    21 
    22 using namespace std;
    2318
    2419Box::Box()
     
    2823  Minv = new Matrix();
    2924  Minv->one();
    30   conditions.resize(3);
    31   conditions[0] = conditions[1] = conditions[2] = Wrap;
    3225}
    3326
     
    3528  M=new Matrix(*src.M);
    3629  Minv = new Matrix(*src.Minv);
    37   conditions = src.conditions;
    3830}
    3931
     
    6860  Vector helper = translateOut(point);
    6961  for(int i=NDIM;i--;){
    70 
    71     switch(conditions[i]){
    72     case Wrap:
    73       helper.at(i)=fmod(helper.at(i),1);
    74       helper.at(i)+=(helper.at(i)>=0)?0:1;
    75       break;
    76     case Bounce:
    77       {
    78         // there probably is a better way to handle this...
    79         // all the fabs and fmod modf probably makes it very slow
    80         double intpart,fracpart;
    81         fracpart = modf(fabs(helper.at(i)),&intpart);
    82         helper.at(i) = fabs(fracpart-fmod(intpart,2));
    83       }
    84       break;
    85     case Ignore:
    86       break;
    87     default:
    88       ASSERT(0,"No default case for this");
    89     }
    90 
     62    double intpart,fracpart;
     63    fracpart = modf(helper.at(i),&intpart);
     64    if(fracpart<0.)
     65      fracpart+=1.;
     66    helper.at(i)=fracpart;
    9167  }
    9268  return translateIn(helper);
     
    9672{
    9773  bool result = true;
    98   Vector tester = translateOut(point);
     74  Vector tester = (*Minv) * point;
    9975
    10076  for(int i=0;i<NDIM;i++)
    101     result = result &&
    102               ((conditions[i] == Ignore) ||
    103                ((tester[i] >= -MYEPSILON) &&
    104                ((tester[i] - 1.) < MYEPSILON)));
     77    result = result && ((tester[i] >= -MYEPSILON) && ((tester[i] - 1.) < MYEPSILON));
    10578
    10679  return result;
     
    10982
    11083VECTORSET(std::list) Box::explode(const Vector &point,int n) const{
    111   ASSERT(isInside(point),"Exploded point not inside Box");
    11284  VECTORSET(std::list) res;
    11385
    114   Vector translater = translateOut(point);
    115   Vector mask; // contains the ignored coordinates
     86  // translate the Vector into each of the 27 neighbourhoods
    11687
    117   // count the number of coordinates we need to do
    118   int dims = 0; // number of dimensions that are not ignored
    119   vector<int> coords;
    120   vector<int> index;
    121   for(int i=0;i<NDIM;++i){
    122     if(conditions[i]==Ignore){
    123       mask[i]=translater[i];
    124       continue;
    125     }
    126     coords.push_back(i);
    127     index.push_back(-n);
    128     dims++;
    129   } // there are max vectors in total we need to create
    130 
    131   if(!dims){
    132     // all boundaries are ignored
    133     res.push_back(point);
    134     return res;
     88  // first create all translation Vectors
     89  // there are (n*2+1)^3 such vectors
     90  int max_dim = (n*2+1);
     91  int max_dim2 = max_dim*max_dim;
     92  int max = max_dim2*max_dim;
     93  // only one loop to avoid unneccessary jumps
     94  for(int i = 0;i<max;++i){
     95    // get all coordinates for this iteration
     96    int n1 = (i%max_dim)-n;
     97    int n2 = ((i/max_dim)%max_dim)-n;
     98    int n3 = ((i/max_dim2))-n;
     99    Vector translation = translateIn(Vector(n1,n2,n3));
     100    res.push_back(translation);
    135101  }
    136 
    137   bool done = false;
    138   while(!done){
    139     // create this vector
    140     Vector helper;
    141     for(int i=0;i<dims;++i){
    142       switch(conditions[coords[i]]){
    143         case Wrap:
    144           helper[coords[i]] = index[i]+translater[coords[i]];
    145           break;
    146         case Bounce:
    147           {
    148             // Bouncing the coordinate x produces the series:
    149             // 0 -> x
    150             // 1 -> 2-x
    151             // 2 -> 2+x
    152             // 3 -> 4-x
    153             // 4 -> 4+x
    154             // the first number is the next bigger even number (n+n%2)
    155             // the next number is the value with alternating sign (x-2*(n%2)*x)
    156             // the negative numbers produce the same sequence reversed and shifted
    157             int n = abs(index[i]) + ((index[i]<0)?-1:0);
    158             int sign = (index[i]<0)?-1:+1;
    159             int even = n%2;
    160             helper[coords[i]]=n+even+translater[coords[i]]-2*even*translater[coords[i]];
    161             helper[coords[i]]*=sign;
    162           }
    163           break;
    164         case Ignore:
    165           ASSERT(0,"Ignored coordinate handled in generation loop");
    166         default:
    167           ASSERT(0,"No default case for this switch-case");
    168       }
    169 
    170     }
    171     // add back all ignored coordinates (not handled in above loop)
    172     helper+=mask;
    173     res.push_back(translateIn(helper));
    174     // set the new indexes
    175     int pos=0;
    176     ++index[pos];
    177     while(index[pos]>n){
    178       index[pos++]=-n;
    179       if(pos>=dims) { // it's trying to increase one beyond array... all vectors generated
    180         done = true;
    181         break;
    182       }
    183       ++index[pos];
    184     }
    185   }
     102  // translate all the translation vector by the offset defined by point
     103  res.translate(point);
    186104  return res;
    187105}
    188106
    189107VECTORSET(std::list) Box::explode(const Vector &point) const{
    190   ASSERT(isInside(point),"Exploded point not inside Box");
    191   return explode(point,1);
     108  VECTORSET(std::list) res;
     109
     110  // translate the Vector into each of the 27 neighbourhoods
     111
     112  // first create all 27 translation Vectors
     113  // these loops depend on fixed parameters and can easily be expanded
     114  // by the compiler to allow code without jumps
     115  for(int n1 = -1;n1<=1;++n1){
     116    for(int n2 = -1;n2<=1;++n2){
     117      for(int n3 = -1;n3<=1;++n3){
     118        // get all coordinates for this iteration
     119        Vector translation = translateIn(Vector(n1,n2,n3));
     120        res.push_back(translation);
     121      }
     122    }
     123  }
     124  // translate all the translation vector by the offset defined by point
     125  res.translate(point);
     126  return res;
    192127}
    193128
    194129double Box::periodicDistanceSquared(const Vector &point1,const Vector &point2) const{
    195   Vector helper1 = WrapPeriodically(point1);
    196   Vector helper2 = WrapPeriodically(point2);
    197   VECTORSET(std::list) expansion = explode(helper1);
    198   double res = expansion.minDistSquared(helper2);
     130  VECTORSET(std::list) expansion = explode(point1);
     131  double res = expansion.minDistSquared(point2);
    199132  return res;
    200133}
     
    206139}
    207140
    208 const Box::Conditions_t Box::getConditions(){
    209   return conditions;
    210 }
    211 
    212 void Box::setCondition(int i,Box::BoundaryCondition_t condition){
    213   conditions[i]=condition;
    214 }
    215 
    216 const vector<pair<Plane,Plane> >  Box::getBoundingPlanes(){
    217   vector<pair<Plane,Plane> > res;
    218   for(int i=0;i<NDIM;++i){
    219     Vector base1,base2,base3;
    220     base2[(i+1)%NDIM] = 1.;
    221     base3[(i+2)%NDIM] = 1.;
    222     Plane p1(translateIn(base1),
    223              translateIn(base2),
    224              translateIn(base3));
    225     Vector offset;
    226     offset[i]=1;
    227     Plane p2(translateIn(base1+offset),
    228              translateIn(base2+offset),
    229              translateIn(base3+offset));
    230     res.push_back(make_pair(p1,p2));
    231   }
    232   return res;
    233 }
    234 
    235 void Box::setCuboid(const Vector &endpoint){
    236   ASSERT(endpoint[0]>0 && endpoint[1]>0 && endpoint[2]>0,"Vector does not define a full cuboid");
    237   M->one();
    238   M->diagonal()=endpoint;
    239   Vector &dinv = Minv->diagonal();
    240   for(int i=NDIM;i--;)
    241     dinv[i]=1/endpoint[i];
    242 }
    243 
    244141Box &Box::operator=(const Box &src){
    245142  if(&src!=this){
     
    248145    M    = new Matrix(*src.M);
    249146    Minv = new Matrix(*src.Minv);
    250     conditions = src.conditions;
    251147  }
    252148  return *this;
Note: See TracChangeset for help on using the changeset viewer.