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