func writeOvf2Binary4(out io.Writer, array *data.Slice) { data := array.Tensors() gridsize := array.Mesh().Size() var bytes []byte // OOMMF requires this number to be first to check the format var controlnumber float32 = OMF_CONTROL_NUMBER // Conversion form float32 [4]byte in big-endian // encoding/binary is too slow // Inlined for performance, terabytes of data will pass here... bytes = (*[4]byte)(unsafe.Pointer(&controlnumber))[:] out.Write(bytes) // Here we loop over X,Y,Z, not Z,Y,X, because // internal in C-order == external in Fortran-order ncomp := array.NComp() for i := 0; i < gridsize[X]; i++ { for j := 0; j < gridsize[Y]; j++ { for k := 0; k < gridsize[Z]; k++ { for c := 0; c < ncomp; c++ { bytes = (*[4]byte)(unsafe.Pointer(&data[swapIndex(c, ncomp)][i][j][k]))[:] out.Write(bytes) } } } } }
func dumpGnuplot(out io.Writer, f *data.Slice) (err error) { buf := bufio.NewWriter(out) defer buf.Flush() data := f.Tensors() gridsize := f.Mesh().Size() cellsize := f.Mesh().CellSize() // If no cell size is set, use generic cell index. if cellsize == [3]float64{0, 0, 0} { cellsize = [3]float64{1, 1, 1} } ncomp := f.NComp() // Here we loop over X,Y,Z, not Z,Y,X, because // internal in C-order == external in Fortran-order for i := 0; i < gridsize[0]; i++ { x := float64(i) * cellsize[0] for j := 0; j < gridsize[1]; j++ { y := float64(j) * cellsize[1] for k := 0; k < gridsize[2]; k++ { z := float64(k) * cellsize[2] _, err = fmt.Fprint(buf, z, " ", y, " ", x, "\t") for c := 0; c < ncomp; c++ { _, err = fmt.Fprint(buf, data[swapIndex(c, ncomp)][i][j][k], " ") // converts to user space. } _, err = fmt.Fprint(buf, "\n") } _, err = fmt.Fprint(buf, "\n") } } return }
func writeVTKHeader(out io.Writer, q *data.Slice) (err error) { gridsize := q.Mesh().Size() _, err = fmt.Fprintln(out, "<?xml version=\"1.0\"?>") _, err = fmt.Fprintln(out, "<VTKFile type=\"StructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">") _, err = fmt.Fprintf(out, "\t<StructuredGrid WholeExtent=\"0 %d 0 %d 0 %d\">\n", gridsize[Z]-1, gridsize[Y]-1, gridsize[X]-1) _, err = fmt.Fprintf(out, "\t\t<Piece Extent=\"0 %d 0 %d 0 %d\">\n", gridsize[Z]-1, gridsize[Y]-1, gridsize[X]-1) return }
// Add effective field of Dzyaloshinskii-Moriya interaction to Beff (Tesla). // According to Bagdanov and Röβler, PRL 87, 3, 2001. eq.8 (out-of-plane symmetry breaking). // m: normalized // D: J/m² func AddDMI(Beff *data.Slice, m *data.Slice, D, Msat float64) { // TODO: size check mesh := Beff.Mesh() N := mesh.Size() c := mesh.CellSize() dx := float32(D / (Msat * c[0])) // actually (2*D) / (Msat * 2*c), 2*c disappears in kernel. dy := float32(D / (Msat * c[1])) dz := float32(D / (Msat * c[2])) cfg := make2DConf(N[2], N[1]) k_adddmi(Beff.DevPtr(0), Beff.DevPtr(1), Beff.DevPtr(2), m.DevPtr(0), m.DevPtr(1), m.DevPtr(2), dx, dy, dz, N[0], N[1], N[2], cfg) }
// Copies src into dst, which is larger or smaller, and multiplies by vol*Bsat. // The remainder of dst is not filled with zeros. func copyPadMul(dst, src *data.Slice, dstsize, srcsize [3]int, vol *data.Slice, Bsat float64, str cu.Stream) { util.Argument(dst.NComp() == 1) util.Argument(src.NComp() == 1) util.Argument(vol.NComp() == 1) util.Assert(dst.Len() == prod(dstsize) && src.Len() == prod(srcsize)) util.Assert(vol.Mesh().Size() == srcsize) N0 := iMin(dstsize[1], srcsize[1]) N1 := iMin(dstsize[2], srcsize[2]) cfg := make2DConf(N0, N1) k_copypadmul_async(dst.DevPtr(0), dstsize[0], dstsize[1], dstsize[2], src.DevPtr(0), srcsize[0], srcsize[1], srcsize[2], vol.DevPtr(0), float32(Bsat), cfg, str) }
func writeVTKPoints(out io.Writer, q *data.Slice, dataformat string) (err error) { _, err = fmt.Fprintln(out, "\t\t\t<Points>") fmt.Fprintf(out, "\t\t\t\t<DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"%s\">\n\t\t\t\t\t", dataformat) gridsize := q.Mesh().Size() cellsize := q.Mesh().CellSize() switch dataformat { case "ascii": for k := 0; k < gridsize[X]; k++ { for j := 0; j < gridsize[Y]; j++ { for i := 0; i < gridsize[Z]; i++ { x := (float32)(i) * (float32)(cellsize[Z]) y := (float32)(j) * (float32)(cellsize[Y]) z := (float32)(k) * (float32)(cellsize[X]) _, err = fmt.Fprint(out, x, " ", y, " ", z, " ") } } } case "binary": buffer := new(bytes.Buffer) for k := 0; k < gridsize[X]; k++ { for j := 0; j < gridsize[Y]; j++ { for i := 0; i < gridsize[Z]; i++ { x := (float32)(i) * (float32)(cellsize[Z]) y := (float32)(j) * (float32)(cellsize[Y]) z := (float32)(k) * (float32)(cellsize[X]) binary.Write(buffer, binary.LittleEndian, x) binary.Write(buffer, binary.LittleEndian, y) binary.Write(buffer, binary.LittleEndian, z) } } } b64len := uint32(len(buffer.Bytes())) bufLen := new(bytes.Buffer) binary.Write(bufLen, binary.LittleEndian, b64len) base64out := base64.NewEncoder(base64.StdEncoding, out) base64out.Write(bufLen.Bytes()) base64out.Write(buffer.Bytes()) base64out.Close() default: log.Fatalf("Illegal VTK data format: %v. Options are: ascii, binary", dataformat) } _, err = fmt.Fprintln(out, "\n\t\t\t\t</DataArray>") _, err = fmt.Fprintln(out, "\t\t\t</Points>") return }
// Add exchange field to Beff with different exchange constant for X,Y,Z direction. // m must be normalized to unit length. func AddAnisoExchange(Beff *data.Slice, m *data.Slice, AexX, AexY, AexZ, Msat float64) { // TODO: size check mesh := Beff.Mesh() N := mesh.Size() c := mesh.CellSize() w0 := float32(2 * AexX / (Msat * c[0] * c[0])) w1 := float32(2 * AexY / (Msat * c[1] * c[1])) w2 := float32(2 * AexZ / (Msat * c[2] * c[2])) cfg := make2DConfSize(N[2], N[1], STENCIL_BLOCKSIZE) str := [3]cu.Stream{stream(), stream(), stream()} for c := 0; c < 3; c++ { k_addexchange1comp_async(Beff.DevPtr(c), m.DevPtr(c), w0, w1, w2, N[0], N[1], N[2], cfg, str[c]) } syncAndRecycle(str[0]) syncAndRecycle(str[1]) syncAndRecycle(str[2]) }
// Writes data in OMF Text format func writeOmfText(out io.Writer, tens *data.Slice) (err error) { data := tens.Tensors() gridsize := tens.Mesh().Size() // Here we loop over X,Y,Z, not Z,Y,X, because // internal in C-order == external in Fortran-order for i := 0; i < gridsize[X]; i++ { for j := 0; j < gridsize[Y]; j++ { for k := 0; k < gridsize[Z]; k++ { for c := 0; c < tens.NComp(); c++ { _, err = fmt.Fprint(out, data[swapIndex(c, tens.NComp())][i][j][k], " ") // converts to user space. } _, err = fmt.Fprint(out, "\n") } } } return }
func AddZhangLiTorque(torque, m *data.Slice, j [3]float64, Msat float64, j_MsMap *data.Slice, alpha, xi float64) { // TODO: assert... util.Argument(j_MsMap == nil) // not yet supported c := torque.Mesh().CellSize() N := torque.Mesh().Size() cfg := make2DConfSize(N[2], N[1], STENCIL_BLOCKSIZE) b := MuB / (Qe * Msat * (1 + xi*xi)) ux := float32((j[0] * b) / (Gamma0 * 2 * c[0])) uy := float32((j[1] * b) / (Gamma0 * 2 * c[1])) uz := float32((j[2] * b) / (Gamma0 * 2 * c[2])) k_addzhanglitorque(torque.DevPtr(0), torque.DevPtr(1), torque.DevPtr(2), m.DevPtr(0), m.DevPtr(1), m.DevPtr(2), ux, uy, uz, j_MsMap.DevPtr(0), j_MsMap.DevPtr(1), j_MsMap.DevPtr(2), float32(alpha), float32(xi), N[0], N[1], N[2], cfg) }
// Writes the OMF header func writeOmfHeader(out io.Writer, q *data.Slice) (err error) { gridsize := q.Mesh().Size() cellsize := q.Mesh().CellSize() err = hdr(out, "OOMMF", "rectangular mesh v1.0") hdr(out, "Segment count", "1") hdr(out, "Begin", "Segment") hdr(out, "Begin", "Header") dsc(out, "Time", 0) //q.Time) // TODO !! hdr(out, "Title", q.Tag()) hdr(out, "meshtype", "rectangular") hdr(out, "meshunit", "m") hdr(out, "xbase", cellsize[Z]/2) hdr(out, "ybase", cellsize[Y]/2) hdr(out, "zbase", cellsize[X]/2) hdr(out, "xstepsize", cellsize[Z]) hdr(out, "ystepsize", cellsize[Y]) hdr(out, "zstepsize", cellsize[X]) hdr(out, "xmin", 0) hdr(out, "ymin", 0) hdr(out, "zmin", 0) hdr(out, "xmax", cellsize[Z]*float64(gridsize[Z])) hdr(out, "ymax", cellsize[Y]*float64(gridsize[Y])) hdr(out, "zmax", cellsize[X]*float64(gridsize[X])) hdr(out, "xnodes", gridsize[Z]) hdr(out, "ynodes", gridsize[Y]) hdr(out, "znodes", gridsize[X]) hdr(out, "ValueRangeMinMag", 1e-08) // not so "optional" as the OOMMF manual suggests... hdr(out, "ValueRangeMaxMag", 1) // TODO hdr(out, "valueunit", "?") hdr(out, "valuemultiplier", 1) hdr(out, "End", "Header") return }
func writeVTKCellData(out io.Writer, q *data.Slice, dataformat string) (err error) { N := q.NComp() data := q.Tensors() switch N { case 1: fmt.Fprintf(out, "\t\t\t<PointData Scalars=\"%s\">\n", q.Tag()) fmt.Fprintf(out, "\t\t\t\t<DataArray type=\"Float32\" Name=\"%s\" NumberOfComponents=\"%d\" format=\"%s\">\n\t\t\t\t\t", q.Tag(), N, dataformat) case 3: fmt.Fprintf(out, "\t\t\t<PointData Vectors=\"%s\">\n", q.Tag()) fmt.Fprintf(out, "\t\t\t\t<DataArray type=\"Float32\" Name=\"%s\" NumberOfComponents=\"%d\" format=\"%s\">\n\t\t\t\t\t", q.Tag(), N, dataformat) case 6, 9: fmt.Fprintf(out, "\t\t\t<PointData Tensors=\"%s\">\n", q.Tag()) fmt.Fprintf(out, "\t\t\t\t<DataArray type=\"Float32\" Name=\"%s\" NumberOfComponents=\"%d\" format=\"%s\">\n\t\t\t\t\t", q.Tag(), 9, dataformat) // must be 9! default: log.Fatalf("vtk: cannot handle %v components", N) } gridsize := q.Mesh().Size() switch dataformat { case "ascii": for i := 0; i < gridsize[X]; i++ { for j := 0; j < gridsize[Y]; j++ { for k := 0; k < gridsize[Z]; k++ { // if symmetric tensor manage it appart to write the full 9 components if N == 6 { fmt.Fprint(out, data[swapIndex(0, 9)][i][j][k], " ") fmt.Fprint(out, data[swapIndex(1, 9)][i][j][k], " ") fmt.Fprint(out, data[swapIndex(2, 9)][i][j][k], " ") fmt.Fprint(out, data[swapIndex(1, 9)][i][j][k], " ") fmt.Fprint(out, data[swapIndex(3, 9)][i][j][k], " ") fmt.Fprint(out, data[swapIndex(4, 9)][i][j][k], " ") fmt.Fprint(out, data[swapIndex(2, 9)][i][j][k], " ") fmt.Fprint(out, data[swapIndex(4, 9)][i][j][k], " ") fmt.Fprint(out, data[swapIndex(5, 9)][i][j][k], " ") } else { for c := 0; c < N; c++ { fmt.Fprint(out, data[swapIndex(c, N)][i][j][k], " ") } } } } } case "binary": // Inlined for performance, terabytes of data will pass here... buffer := new(bytes.Buffer) for i := 0; i < gridsize[X]; i++ { for j := 0; j < gridsize[Y]; j++ { for k := 0; k < gridsize[Z]; k++ { // if symmetric tensor manage it appart to write the full 9 components if N == 6 { binary.Write(buffer, binary.LittleEndian, data[swapIndex(0, 9)][i][j][k]) binary.Write(buffer, binary.LittleEndian, data[swapIndex(1, 9)][i][j][k]) binary.Write(buffer, binary.LittleEndian, data[swapIndex(2, 9)][i][j][k]) binary.Write(buffer, binary.LittleEndian, data[swapIndex(1, 9)][i][j][k]) binary.Write(buffer, binary.LittleEndian, data[swapIndex(3, 9)][i][j][k]) binary.Write(buffer, binary.LittleEndian, data[swapIndex(4, 9)][i][j][k]) binary.Write(buffer, binary.LittleEndian, data[swapIndex(2, 9)][i][j][k]) binary.Write(buffer, binary.LittleEndian, data[swapIndex(4, 9)][i][j][k]) binary.Write(buffer, binary.LittleEndian, data[swapIndex(5, 9)][i][j][k]) } else { for c := 0; c < N; c++ { binary.Write(buffer, binary.LittleEndian, data[swapIndex(c, N)][i][j][k]) } } } } } b64len := uint32(len(buffer.Bytes())) bufLen := new(bytes.Buffer) binary.Write(bufLen, binary.LittleEndian, b64len) base64out := base64.NewEncoder(base64.StdEncoding, out) base64out.Write(bufLen.Bytes()) base64out.Write(buffer.Bytes()) base64out.Close() default: panic(fmt.Errorf("vtk: illegal data format " + dataformat + ". Options are: ascii, binary")) } fmt.Fprintln(out, "\n\t\t\t\t</DataArray>") fmt.Fprintln(out, "\t\t\t</PointData>") return }
func writeOvf2Header(out io.Writer, q *data.Slice, time, tstep float64) { gridsize := q.Mesh().Size() cellsize := q.Mesh().CellSize() fmt.Fprintln(out, "# OOMMF OVF 2.0") fmt.Fprintln(out, "#") hdr(out, "Segment count", "1") fmt.Fprintln(out, "#") hdr(out, "Begin", "Segment") hdr(out, "Begin", "Header") fmt.Fprintln(out, "#") hdr(out, "Title", q.Tag()) // TODO hdr(out, "meshtype", "rectangular") hdr(out, "meshunit", "m") hdr(out, "xmin", 0) hdr(out, "ymin", 0) hdr(out, "zmin", 0) hdr(out, "xmax", cellsize[Z]*float64(gridsize[Z])) hdr(out, "ymax", cellsize[Y]*float64(gridsize[Y])) hdr(out, "zmax", cellsize[X]*float64(gridsize[X])) name := q.Tag() var labels []interface{} if q.NComp() == 1 { labels = []interface{}{name} } else { for i := 0; i < q.NComp(); i++ { labels = append(labels, name+"_"+string('x'+i)) } } hdr(out, "valuedim", q.NComp()) hdr(out, "valuelabels", labels...) // TODO unit := q.Unit() if unit == "" { unit = "1" } if q.NComp() == 1 { hdr(out, "valueunits", unit) } else { hdr(out, "valueunits", unit, unit, unit) } // We don't really have stages fmt.Fprintln(out, "# Desc: Stage simulation time: ", tstep, " s") fmt.Fprintln(out, "# Desc: Total simulation time: ", time, " s") hdr(out, "xbase", cellsize[Z]/2) hdr(out, "ybase", cellsize[Y]/2) hdr(out, "zbase", cellsize[X]/2) hdr(out, "xnodes", gridsize[Z]) hdr(out, "ynodes", gridsize[Y]) hdr(out, "znodes", gridsize[X]) hdr(out, "xstepsize", cellsize[Z]) hdr(out, "ystepsize", cellsize[Y]) hdr(out, "zstepsize", cellsize[X]) fmt.Fprintln(out, "#") hdr(out, "End", "Header") fmt.Fprintln(out, "#") }
// Returns a copy of in, allocated on GPU. func GPUCopy(in *data.Slice) *data.Slice { s := NewSlice(in.NComp(), in.Mesh()) data.Copy(s, in) return s }