Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Box.cpp

    r0ae36b r57f243  
    1111
    1212#include <cmath>
    13 
    14 #include "Matrix.hpp"
    15 #include "vector.hpp"
     13#include <iostream>
     14#include <cstdlib>
     15
     16#include "LinearAlgebra/Matrix.hpp"
     17#include "LinearAlgebra/Vector.hpp"
     18#include "LinearAlgebra/Plane.hpp"
    1619
    1720#include "Helpers/Assert.hpp"
     21
     22using namespace std;
    1823
    1924Box::Box()
     
    2328  Minv = new Matrix();
    2429  Minv->one();
     30  conditions.resize(3);
     31  conditions[0] = conditions[1] = conditions[2] = Wrap;
    2532}
    2633
     
    2835  M=new Matrix(*src.M);
    2936  Minv = new Matrix(*src.Minv);
     37  conditions = src.conditions;
    3038}
    3139
     
    6068  Vector helper = translateOut(point);
    6169  for(int i=NDIM;i--;){
    62     double intpart,fracpart;
    63     fracpart = modf(helper.at(i),&intpart);
    64     if(fracpart<0.)
    65       fracpart+=1.;
    66     helper.at(i)=fracpart;
     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
    6791  }
    6892  return translateIn(helper);
     
    7296{
    7397  bool result = true;
    74   Vector tester = (*Minv) * point;
     98  Vector tester = translateOut(point);
    7599
    76100  for(int i=0;i<NDIM;i++)
    77     result = result && ((tester[i] >= -MYEPSILON) && ((tester[i] - 1.) < MYEPSILON));
     101    result = result &&
     102              ((conditions[i] == Ignore) ||
     103               ((tester[i] >= -MYEPSILON) &&
     104               ((tester[i] - 1.) < MYEPSILON)));
    78105
    79106  return result;
     
    82109
    83110VECTORSET(std::list) Box::explode(const Vector &point,int n) const{
     111  ASSERT(isInside(point),"Exploded point not inside Box");
    84112  VECTORSET(std::list) res;
    85113
    86   // translate the Vector into each of the 27 neighbourhoods
    87 
    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);
    101   }
    102   // translate all the translation vector by the offset defined by point
    103   res.translate(point);
     114  Vector translater = translateOut(point);
     115  Vector mask; // contains the ignored coordinates
     116
     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;
     135  }
     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  }
    104186  return res;
    105187}
    106188
    107189VECTORSET(std::list) Box::explode(const Vector &point) const{
    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;
     190  ASSERT(isInside(point),"Exploded point not inside Box");
     191  return explode(point,1);
    127192}
    128193
    129194double Box::periodicDistanceSquared(const Vector &point1,const Vector &point2) const{
    130   VECTORSET(std::list) expansion = explode(point1);
    131   double res = expansion.minDistSquared(point2);
     195  Vector helper1 = WrapPeriodically(point1);
     196  Vector helper2 = WrapPeriodically(point2);
     197  VECTORSET(std::list) expansion = explode(helper1);
     198  double res = expansion.minDistSquared(helper2);
    132199  return res;
    133200}
     
    137204  res = sqrt(periodicDistanceSquared(point1,point2));
    138205  return res;
     206}
     207
     208const Box::Conditions_t Box::getConditions(){
     209  return conditions;
     210}
     211
     212void Box::setCondition(int i,Box::BoundaryCondition_t condition){
     213  conditions[i]=condition;
     214}
     215
     216const 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
     235void 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];
    139242}
    140243
     
    145248    M    = new Matrix(*src.M);
    146249    Minv = new Matrix(*src.Minv);
     250    conditions = src.conditions;
    147251  }
    148252  return *this;
Note: See TracChangeset for help on using the changeset viewer.