Changes in src/Box.cpp [57f243:0ae36b]
- File:
-
- 1 edited
-
src/Box.cpp (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Box.cpp
r57f243 r0ae36b 11 11 12 12 #include <cmath> 13 #include <iostream>14 #include <cstdlib>15 13 16 #include "LinearAlgebra/Matrix.hpp" 17 #include "LinearAlgebra/Vector.hpp" 18 #include "LinearAlgebra/Plane.hpp" 14 #include "Matrix.hpp" 15 #include "vector.hpp" 19 16 20 17 #include "Helpers/Assert.hpp" 21 22 using namespace std;23 18 24 19 Box::Box() … … 28 23 Minv = new Matrix(); 29 24 Minv->one(); 30 conditions.resize(3);31 conditions[0] = conditions[1] = conditions[2] = Wrap;32 25 } 33 26 … … 35 28 M=new Matrix(*src.M); 36 29 Minv = new Matrix(*src.Minv); 37 conditions = src.conditions;38 30 } 39 31 … … 68 60 Vector helper = translateOut(point); 69 61 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; 91 67 } 92 68 return translateIn(helper); … … 96 72 { 97 73 bool result = true; 98 Vector tester = translateOut(point);74 Vector tester = (*Minv) * point; 99 75 100 76 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)); 105 78 106 79 return result; … … 109 82 110 83 VECTORSET(std::list) Box::explode(const Vector &point,int n) const{ 111 ASSERT(isInside(point),"Exploded point not inside Box");112 84 VECTORSET(std::list) res; 113 85 114 Vector translater = translateOut(point); 115 Vector mask; // contains the ignored coordinates 86 // translate the Vector into each of the 27 neighbourhoods 116 87 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); 135 101 } 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); 186 104 return res; 187 105 } 188 106 189 107 VECTORSET(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; 192 127 } 193 128 194 129 double 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); 199 132 return res; 200 133 } … … 206 139 } 207 140 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 244 141 Box &Box::operator=(const Box &src){ 245 142 if(&src!=this){ … … 248 145 M = new Matrix(*src.M); 249 146 Minv = new Matrix(*src.Minv); 250 conditions = src.conditions;251 147 } 252 148 return *this;
Note:
See TracChangeset
for help on using the changeset viewer.
