1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
// quadtbox.cmd
// finds bounding box for quadratic facets
// Suitable for torus model.
// Tricky to define a bounding box in a torus, with the wraps.
// So the bounding box is based on unwrapped edges and facets
// relative to the first vertex.;
// Bounding box calculations are done in normalized unit cell
// coordinates, so bounding box is really parallelogram
// parallel to unit cell.
// Programmer: Ken Brakke, brakke@susqu.edu www.susqu.edu/brakke
// xmin,xmax,ymin,ymax,zmin,zmax
define edge attribute ebox real [3][2]
define facet attribute fbox real [3][2]
eboxes := {
local ii,v0,v1,v2,v4,uopt,denom;
local u0,u1,u2;
define u0 real[space_dimension];
define u1 real[space_dimension];
define u2 real[space_dimension];
if ( !quadratic ) then
{ errprintf "eboxes: Must be in quadratic mode.\n";
abort;
};
if ( !torus ) then
{ errprintf "eboxes: Must be in torus model.\n";
abort;
};
foreach edge ee do
{
u0 := ee.vertex[1].__x * inverse_periods;
u1 := ee.edge_vector * inverse_periods;
u2 := ee.vertex[3].__x * inverse_periods;
for ( ii := 1; ii <= space_dimension; ii++ )
{
// get normalized vertex coordinates, recalling midv is third vertex
// of the edge, and on the same wrap as the tail.
v0 := u0[ii];
v1 := v0 + u1[ii];
v2 := u2[ii];
// now set bounding boxes
if ( v0 > v1 )
then { ee.ebox[ii][1] := v1; ee.ebox[ii][2] := v0; }
else { ee.ebox[ii][1] := v0; ee.ebox[ii][2] := v1; };
if ( v2 < ee.ebox[ii][1] ) then ee.ebox[ii][1] := v2;
if ( v2 > ee.ebox[ii][2] ) then ee.ebox[ii][2] := v2;
denom := v0 - 2*v1 + v2;
if ( denom == 0.0 ) then continue;
uopt := (-1.5*v0 + 2*v1 - .5*v2)/denom;
if ( uopt <= 0.0 or uopt >= 1.0 )
then continue;
v4 := 0.5*(1-uopt)*(2-uopt)*v0 + uopt*(2-uopt)*v1
+ 0.5*uopt*(uopt-1)*v2;
if ( v4 < ee.ebox[ii][1] ) then ee.ebox[ii][1] := v4;
if ( v4 > ee.ebox[ii][2] ) then ee.ebox[ii][2] := v4;
}
}
} // end eboxes
fboxes := {
local ewraps,ii,ww,jj,www,tempbox,vwrap,v0,v1,v2,v3,v4,v5;
local a11,a12,b1,a21,a22,b2,denom,uopt,vopt,vcrit;
define ewraps integer[3][space_dimension];
local u0,u1,u2,u3,u4,u5;
define u0 real[space_dimension];
define u1 real[space_dimension];
define u2 real[space_dimension];
define u3 real[space_dimension];
define u4 real[space_dimension];
define u5 real[space_dimension];
eboxes;
if ( ! quadratic ) then
{ print "fboxes: Must be in quadratic mode.\n";
abort;
};
foreach facet ff do
{ // extract wraps on edges
for ( ii := 1; ii <= 3 ; ii++ )
{ ww := ff.edge[ii].wrap;
for ( jj := 1 ; jj <= space_dimension ; jj++ )
{ www := ww imod 64;
if www == 0 then ewraps[ii][jj] := 0
else if www < 16 then ewraps[ii][jj] := www
else ewraps[ii][jj] := www-32;
ww /= 64;
}
};
u0 := ff.edge[1].vertex[1].__x * inverse_periods;
u1 := ff.edge[1].vertex[3].__x * inverse_periods;
u2 := ff.edge[1].edge_vector * inverse_periods;
u3 := ff.edge[3].vertex[3].__x * inverse_periods;
u4 := ff.edge[2].vertex[3].__x * inverse_periods;
u5 := ff.edge[2].edge_vector * inverse_periods;
for ( ii := 1; ii <= space_dimension ; ii++ )
{ define tempbox real[2];
/* first, edge boxes */
ff.fbox[ii] := ff.edge[1].ebox[ii];
if ff.edge[1].oid < 0 then
ff.fbox[ii] += ewraps[1][ii];
vwrap := ewraps[1][ii];
for ( jj := 2 ; jj <= 3; jj++ )
{ tempbox := ff.edge[jj].ebox[ii];
tempbox += vwrap;
if ff.edge[jj].oid < 0 then
tempbox += ewraps[jj][ii];
if ( tempbox[1] < ff.fbox[ii][1] )
then ff.fbox[ii][1] := tempbox[1];
if ( tempbox[2] > ff.fbox[ii][2] )
then ff.fbox[ii][2] := tempbox[2];
vwrap += ewraps[jj][ii];
};
v0 := u0[ii];
v1 := u1[ii];
v2 := v0 + u2[ii];
v3 := u3[ii];
v4 := u4[ii];
v5 := v2 + u5[ii];
// fix up midpoint to be near endpoints, since don't have edge vector to midpoint
v1 := ((7+v1-(v0+v2-1)/2) mod 1) + (v0+v2-1)/2;
v3 := ((7+v3-(v0+v5-1)/2) mod 1) + (v0+v5-1)/2;
v4 := ((7+v4-(v5+v2-1)/2) mod 1) + (v5+v2-1)/2;
// x_u coeff of u
a11 := v0 - 2*v1 + v2;
// x_u coeff of v
a12 := v0 - v1 - v3 + v4;
// x_u rhs
b1 := -(-1.5*v0 + 2*v1 - .5*v2);
// x_v coeff of u
a21 := v0 - v1 - v3 + v4;
// x_v coeff of v
a22 := v0 - 2*v3 + v5;
// x_v rhs
b2 := -(-1.5*v0 + 2*v3 - 0.5*v5);
// solve for critical point
denom := a11*a22 - a12*a21;
if ( denom == 0.0 ) then continue;
uopt := (b1*a22 - b2*a12)/denom;
vopt := (a11*b2 - a21*b1)/denom;
if ( uopt <= 0.0 ) then continue;
if ( vopt <= 0.0 ) then continue;
if ( uopt+vopt >= 2.0 ) then continue;
vcrit := 0.5*(uopt+vopt-1)*(uopt+vopt-2)*v0
+ uopt*(2-uopt-vopt)*v1
+ 0.5*uopt*(uopt-1)*v2
+ vopt*(2-uopt-vopt)*v3
+ uopt*vopt*v4
+ 0.5*vopt*(vopt-1)*v5;
if ( vcrit < ff.fbox[ii][1] ) then ff.fbox[ii][1] := vcrit;
if ( vcrit > ff.fbox[ii][2] ) then ff.fbox[ii][2] := vcrit;
}
}
}
// End quadtbox.cmd
// Usage: fboxes
|