We introduce a way to calculate a sufficient part of an orbit and the
stabilizer of a point.


<Section><Heading>Orbit Stabilizer for Crystallographic Groups</Heading>

<ManSection>
    <Meth Name="OrbitStabilizerInUnitCubeOnRight"
          Arg="group, x"/>
  <Returns> 
   A record containing
   <List>
    <Item>
      <K>.stabilizer</K>: the stabilizer of <Arg>x</Arg>.
    </Item>
    <Item>
     <K>.orbit</K> set of vectors from <M>[0,1)^n</M> which
     represents the orbit. 
    </Item>
   </List>
  </Returns>
  <Description>
   Let <Arg>x</Arg> be a rational vector from <M>[0,1)^n</M> and
   <Arg>group</Arg> a space group in standard form.

   The function then calculates the part of the orbit which lies inside the
   cube <M>[0,1)^n</M> and the stabilizer of <Arg>x</Arg>. Observe that every
   element of the full orbit differs from a point in the returned orbit only
   by a pure translation.
  </Description>
</ManSection>

Note that the restriction to points from <M>[0,1)^n</M> makes sense if orbits
should be compared and the vector passed to
<C>OrbitStabilizerInUnitCubeOnRight</C> should be an element of the returned
orbit (part).

<Example>
   <![CDATA[
gap> S:=SpaceGroup(3,5);;
gap> OrbitStabilizerInUnitCubeOnRight(S,[1/2,0,9/11]);   
rec( orbit := [ [ 0, 1/2, 2/11 ], [ 1/2, 0, 9/11 ] ], 
  stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], 
          [ 0, 0, 0, 1 ] ] ]) )
gap> OrbitStabilizerInUnitCubeOnRight(S,[0,0,0]);     
rec( orbit := [ [ 0, 0, 0 ] ], stabilizer := <matrix group with 2 generators> )
]]>
</Example>

If you are interested in other parts of the orbit, you can use <Ref
Meth="VectorModOne"/> for the base point and the functions <Ref
Meth="ShiftedOrbitPart"/>, <Ref Meth="TranslationsToOneCubeAroundCenter"/> and
<Ref Meth="TranslationsToBox"/> for the resulting orbit<Br/>

Suppose we want to calculate the part of the orbit of <C>[4/3,5/3,7/3]</C> in
the cube of sidelength <C>1</C> around this point:

<Example>
gap> S:=SpaceGroup(3,5);;
gap> p:=[4/3,5/3,7/3];;
gap> o:=OrbitStabilizerInUnitCubeOnRight(S,VectorModOne(p)).orbit;
[ [ 1/3, 2/3, 1/3 ], [ 1/3, 2/3, 2/3 ] ]
gap> box:=p+[[-1,1],[-1,1],[-1,1]];
[ [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ], [ 1/3, 8/3, 7/3 ] ]
gap> o2:=Concatenation(List(o,i->i+TranslationsToBox(i,box)));;
gap> # This is what we looked for. But it is somewhat large:
gap> Size(o2);
54
</Example>


<ManSection>
    <Meth Name="OrbitStabilizerInUnitCubeOnRightOnSets"
          Arg="group, set"/>
  <Returns>
   A record containing
   <List>
    <Item>
     <K>.stabilizer</K>:  the stabilizer of <Arg>set</Arg>.
    </Item>
    <Item>
     <K>.orbit</K> set of sets of vectors from <M>[0,1)^n</M> which
     represents the orbit. 
    </Item>
   </List>
  </Returns>

  <Description>
   Calculates orbit and stabilizer of a set of vectors. Just as <Ref
   Meth="OrbitStabilizerInUnitCubeOnRight"></Ref>, it needs input from
   <M>[0,1)^n</M>.

   The returned orbit part <K>.orbit</K> is a set of sets such that every
   element of <K>.orbit</K> has a non-trivial intersection with the
   cube <M>[0,1)^n</M>. In general, these sets will not lie inside
   <M>[0,1)^n</M> completely.
  </Description>  
</ManSection>

<Example>
gap> S:=SpaceGroup(3,5);;
gap> OrbitStabilizerInUnitCubeOnRightOnSets(S,[[0,0,0],[0,1/2,0]]);
rec( orbit := [ [ [ -1/2, 0, 0 ], [ 0, 0, 0 ] ], 
                [ [ 0, 0, 0 ], [ 0, 1/2, 0 ] ],
                [ [ 1/2, 0, 0 ], [ 1, 0, 0 ] ] ],
  stabilizer := Group([ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], 
                        [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ]) )
</Example>

<ManSection>
  <Meth Name="OrbitPartInVertexSetsStandardSpaceGroup"
	Arg="group vertexset allvertices"/>
<Returns>
 Set of subsets of <A>allvertices</A>.
</Returns>
  <Description>
    If <A>allvertices</A> is a set of vectors and <A>vertexset</A> is
    a subset thereof, then <Ref
    Meth="OrbitPartInVertexSetsStandardSpaceGroup"></Ref> returns
    that part of the orbit of <A>vertexset</A> which consists entirely of
    subsets of <A>allvertices</A>.
    Note that,unlike the other <C>OrbitStabilizer</C> algorithms, this does not
    require the input to lie in some particular part of the space.
  </Description>
</ManSection>

<Example>
gap> S:=SpaceGroup(3,5);;
gap> OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));
[ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ]
gap> OrbitPartInVertexSetsStandardSpaceGroup(S, [[1,2,0]],
> Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));
[ [ [ 0, 1, 5 ] ], [ [ 1, 1, 0 ] ], [ [ 1, 2, 0 ] ], [ [ 1, 2, 6 ] ], [ [ 2, 3, 1 ] ] ]
</Example>


<ManSection>
  <Meth Name="OrbitPartInFacesStandardSpaceGroup"
	Arg="group vertexset faceset"/>
<Returns>
 Set of subsets of <A>faceset</A>.
</Returns>
  <Description>
    This calculates the orbit of a space group on sets restricted to a set of
faces.<Br/>
    If <A>faceset</A> is a set of sets of vectors and <A>vertexset</A> is
    an element of <A>faceset</A>, then <Ref
    Meth="OrbitPartInFacesStandardSpaceGroup"></Ref> returns
    that part of the orbit of <A>vertexset</A> which consists entirely of
    elements of <A>faceset</A>.<Br/>
    Note that,unlike the other <C>OrbitStabilizer</C> algorithms, this does not
    require the input to lie in some particular part of the space.
  </Description>
</ManSection>



<ManSection>
  <Meth Name="OrbitPartAndRepresentativesInFacesStandardSpaceGroup"
	Arg="group vertexset faceset"/>
<Returns>
 A set of face-matrix pairs .
</Returns>
  <Description>
    This is a slight variation of 
    <Ref Meth="OrbitPartInFacesStandardSpaceGroup"></Ref> 
    that also returns a representative for every orbit element.
  </Description>
</ManSection>

<Example>
gap> S:=SpaceGroup(3,5);;
gap> OrbitPartInVertexSetsStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set([[1,2,0],[2,3,1],[1,2,6],[1,1,0],[0,1,5],[3/5,7,12],[1/17,6,1/2]]));
[ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [ [ 1, 2, 6 ], [ 2, 3, 1 ] ] ]
gap> OrbitPartInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]]));
[ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ] ]
gap> OrbitPartAndRepresentativesInFacesStandardSpaceGroup(S,[[0,1,5],[1,2,0]],
> Set( [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ], [[1/17,6,1/2],[1,2,7]]]));
[ [ [ [ 0, 1, 5 ], [ 1, 2, 0 ] ],
      [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] ] ]
</Example>



<ManSection>
  <Meth Name="StabilizerOnSetsStandardSpaceGroup"
        Arg="group set"/>
  <Returns>finite group of affine matrices (OnRight)</Returns>
  <Description>
   Given a set <A>set</A> of vectors and a space group <A>group</A> in
   standard form, this method calculates the stabilizer of that set in
   the full crystallographic group.<Br/>
  </Description>
</ManSection>

<Example> 
<![CDATA[
gap> G:=SpaceGroup(3,12);;
gap> v:=[ 0, 0,0 ];;
gap> s:=StabilizerOnSetsStandardSpaceGroup(G,[v]);
<matrix group with 2 generators>
gap> s2:=OrbitStabilizerInUnitCubeOnRight(G,v).stabilizer;
<matrix group with 2 generators>
gap> s2=s;
true
]]>
</Example>

<ManSection>
  <Meth Name="RepresentativeActionOnRightOnSets"
	Arg="group set imageset"/>
<Returns>
Affine matrix.
</Returns>
  <Description>
    Returns an element of the space group
    <M>S</M> which takes the set <A>set</A> to the set
    <A>imageset</A>. The group must be in standard form and act on the right.
  </Description>	  
</ManSection>

<Example>
gap> S:=SpaceGroup(3,5);;
gap> RepresentativeActionOnRightOnSets(G, [[0,0,0],[0,1/2,0]],
>        [ [ 0, 1/2, 0 ], [ 0, 1, 0 ] ]);
[ [ 0, -1, 0, 0 ], [ -1, 0, 0, 0 ], [ 0, 0, -1, 0 ], [ 0, 1, 0, 1 ] ]
</Example>


<Subsection><Heading>Getting other orbit parts</Heading>

<Package>HAPcryst</Package> does not calculate the full orbit but only the part
of it having coefficients between <M>-1/2</M> and <M>1/2</M>. The other parts
of the orbit can be calculated using the following functions.
</Subsection>

<ManSection>
    <Meth Name="ShiftedOrbitPart" Arg="point, orbitpart"/>
   <Returns>Set of vectors </Returns>
   <Description>
    Takes each vector in <A>orbitpart</A> to the cube unit cube centered in
    <A>point</A>.
   </Description>
</ManSection>

<Example>
gap> ShiftedOrbitPart([0,0,0],[[1/2,1/2,1/3],-[1/2,1/2,1/2],[19,3,1]]);
[ [ 1/2, 1/2, 1/3 ], [ 1/2, 1/2, 1/2 ], [ 0, 0, 0 ] ]
gap> ShiftedOrbitPart([1,1,1],[[1/2,1/2,1/2],-[1/2,1/2,1/2]]);
[ [ 3/2, 3/2, 3/2 ] ]
</Example>



<ManSection>
  <Meth Name="TranslationsToOneCubeAroundCenter" Arg="point, center"/>
  <Returns>List of integer vectors</Returns>
  <Description>
   This method returns the list of all integer vectors which translate
   <A>point</A> into the box <A>center</A><M>+[-1/2,1/2]^n</M>
  </Description>
</ManSection>

<Example>
gap> TranslationsToOneCubeAroundCenter([1/2,1/2,1/3],[0,0,0]);
[ [ 0, 0, 0 ], [ 0, -1, 0 ], [ -1, 0, 0 ], [ -1, -1, 0 ] ]
gap> TranslationsToOneCubeAroundCenter([1,0,1],[0,0,0]);
[ [ -1, 0, -1 ] ]
</Example>


<ManSection>
 <Meth Name="TranslationsToBox" Arg="point, box"/>
<!-- <Returns>List of integer vectors or the empty list</Returns>-->
 <Returns>An iterator of integer vectors or the empty iterator</Returns>
 <Description>
  Given a vector <M>v</M> and a list of pairs, this function returns the
  translation vectors (integer vectors) which take <M>v</M> into the box
  <A>box</A>.  The box <A>box</A> has to be given as a list of pairs.
 </Description>
</ManSection>

<Example>
gap> TranslationsToBox([0,0],[[1/2,2/3],[1/2,2/3]]);
[  ]
gap> TranslationsToBox([0,0],[[-3/2,1/2],[1,4/3]]);
[ [ -1, 1 ], [ 0, 1 ] ]
gap> TranslationsToBox([0,0],[[-3/2,1/2],[2,1]]);
Error, Box must not be empty called from
...
</Example>



</Section>
