Пример #1
0
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)
				}
			}
		}
	}
}
Пример #2
0
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
}
Пример #3
0
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
}
Пример #4
0
// 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)
}
Пример #5
0
// 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)
}
Пример #6
0
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
}
Пример #7
0
// 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])
}
Пример #8
0
// 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
}
Пример #9
0
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)
}
Пример #10
0
// 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
}
Пример #11
0
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
}
Пример #12
0
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, "#")
}
Пример #13
0
// 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
}