//Next Reads the next frame in a XTCObj that has been initialized for read //With initread. If keep is true, returns a pointer to matrix.DenseMatrix //With the coordinates read, otherwiser, it discards the coordinates and //returns nil. func (X *XTCObj) Next(output *v3.Matrix) error { if !X.Readable() { return Error{TrajUnIni, X.filename, []string{"Next"}, true} } cnatoms := C.int(X.natoms) worked := C.get_coords(X.fp, &X.cCoords[0], cnatoms) if worked == 11 { X.readable = false return newlastFrameError(X.filename, "Next") //This is not really an error and should be catched in the calling function } if worked != 0 { X.readable = false return Error{ReadError, X.filename, []string{"Next"}, true} } if output != nil { //col the frame r, c := output.Dims() if r < (X.natoms) { panic("Buffer v3.Matrix too small to hold trajectory frame") } for j := 0; j < r; j++ { for k := 0; k < c; k++ { l := k + (3 * j) output.Set(j, k, (10 * float64(X.cCoords[l]))) //nm to Angstroms } } return nil } return nil //Just drop the frame }
//MakeWater Creates a water molecule at distance Angstroms from a2, in a direction that is angle radians from the axis defined by a1 and a2. //Notice that the exact position of the water is not well defined when angle is not zero. One can always use the RotateAbout //function to move the molecule to the desired location. If oxygen is true, the oxygen will be pointing to a2. Otherwise, //one of the hydrogens will. func MakeWater(a1, a2 *v3.Matrix, distance, angle float64, oxygen bool) *v3.Matrix { water := v3.Zeros(3) const WaterOHDist = 0.96 const WaterAngle = 52.25 const deg2rad = 0.0174533 w := water.VecView(0) //we first set the O coordinates w.Copy(a2) w.Sub(w, a1) w.Unit(w) dist := v3.Zeros(1) dist.Sub(a1, a2) a1a2dist := dist.Norm(0) fmt.Println("ala2dist", a1a2dist, distance) ////////////////7777 w.Scale(distance+a1a2dist, w) w.Add(w, a1) for i := 0; i <= 1; i++ { o := water.VecView(0) w = water.VecView(i + 1) w.Copy(o) fmt.Println("w1", w) //////// w.Sub(w, a2) fmt.Println("w12", w) /////////////// w.Unit(w) fmt.Println("w4", w) w.Scale(WaterOHDist+distance, w) fmt.Println("w3", w, WaterOHDist, distance) o.Sub(o, a2) t, _ := v3.NewMatrix([]float64{0, 0, 1}) upp := v3.Zeros(1) upp.Cross(w, t) fmt.Println("upp", upp, w, t) upp.Add(upp, o) upp.Add(upp, a2) //water.SetMatrix(3,0,upp) w.Add(w, a2) o.Add(o, a2) sign := 1.0 if i == 1 { sign = -1.0 } temp, _ := RotateAbout(w, o, upp, deg2rad*WaterAngle*sign) w.SetMatrix(0, 0, temp) } var v1, v2 *v3.Matrix if angle != 0 { v1 = v3.Zeros(1) v2 = v3.Zeros(1) v1.Sub(a2, a1) v2.Copy(v1) v2.Set(0, 2, v2.At(0, 2)+1) //a "random" modification. The idea is that its not colinear with v1 v3 := cross(v1, v2) v3.Add(v3, a2) water, _ = RotateAbout(water, a2, v3, angle) } if oxygen { return water } //we move things so an hydrogen points to a2 and modify the distance acordingly. e1 := water.VecView(0) e2 := water.VecView(1) e3 := water.VecView(2) if v1 == nil { v1 = v3.Zeros(1) } if v2 == nil { v2 = v3.Zeros(1) } v1.Sub(e2, e1) v2.Sub(e3, e1) axis := cross(v1, v2) axis.Add(axis, e1) water, _ = RotateAbout(water, e1, axis, deg2rad*(180-WaterAngle)) v1.Sub(e1, a2) v1.Unit(v1) v1.Scale(WaterOHDist, v1) water.AddVec(water, v1) return water }