func SanityCheck() { if Msat.isZero() { util.Log("Note: Msat = 0") } if Aex.isZero() { util.Log("Note: Aex = 0") } }
// Compares FFT-accelerated convolution against brute-force on sparse data. // This is not really needed but very quickly uncovers newly introduced bugs. func testConvolution(c *DemagConvolution, PBC [3]int, realKern [3][3]*data.Slice) { if PBC != [3]int{0, 0, 0} { // the brute-force method does not work for pbc. util.Log("skipping convolution self-test for PBC") return } util.Log("//convolution self-test...") inhost := data.NewSlice(3, c.inputSize) initConvTestInput(inhost.Vectors()) gpu := NewSlice(3, c.inputSize) defer gpu.Free() data.Copy(gpu, inhost) regions := NewBytes(prod(c.inputSize)) defer regions.Free() Bsat := NewSlice(1, [3]int{1, 1, 256}) defer Bsat.Free() Memset(Bsat, 1) BsatLUT := LUTPtr(Bsat.DevPtr(0)) vol := data.NilSlice(1, c.inputSize) c.Exec(gpu, gpu, vol, BsatLUT, regions) output := gpu.HostCopy() brute := data.NewSlice(3, c.inputSize) bruteConv(inhost.Vectors(), brute.Vectors(), realKern) a, b := output.Host(), brute.Host() err := float32(0) for c := range a { for i := range a[c] { if fabs(a[c][i]-b[c][i]) > err { err = fabs(a[c][i] - b[c][i]) } } } if err > CONV_TOLERANCE { util.Fatal("convolution self-test tolerance: ", err, " FAIL") } }
// Obtains the demag kernel either from cacheDir/ or by calculating (and then storing in cacheDir for next time). // Empty cacheDir disables caching. func DemagKernel(inputSize, pbc [3]int, cellsize [3]float64, accuracy float64, cacheDir string) (kernel [3][3]*data.Slice) { timer.Start("kernel_init") timer.Stop("kernel_init") // warm-up timer.Start("kernel_init") defer timer.Stop("kernel_init") sanityCheck(cellsize, pbc) // Cache disabled if cacheDir == "" { util.Log(`//Not using kernel cache (-cache="")`) return CalcDemagKernel(inputSize, pbc, cellsize, accuracy) } // Error-resilient kernel cache: if anything goes wrong, return calculated kernel. defer func() { if err := recover(); err != nil { util.Log("//Unable to use kernel cache:", err) kernel = CalcDemagKernel(inputSize, pbc, cellsize, accuracy) } }() // Try to load kernel basename := fmt.Sprint(cacheDir, "/", "mumax3kernel_", inputSize, "_", pbc, "_", cellsize, "_", accuracy, "_") var errLoad error for i := 0; i < 3; i++ { for j := i; j < 3; j++ { if inputSize[Z] == 1 && ((i == X && j == Z) || (i == Y && j == Z)) { continue // element not needed in 2D } kernel[i][j], errLoad = LoadKernel(fmt.Sprint(basename, i, j, ".ovf")) if errLoad != nil { break } } if errLoad != nil { break } } // make result symmetric for tools that expect it so. kernel[Y][X] = kernel[X][Y] kernel[Z][X] = kernel[X][Z] kernel[Z][Y] = kernel[Y][Z] if errLoad != nil { util.Log("//Did not use cached kernel:", errLoad) } else { util.Log("//Using cached kernel:", basename) return kernel } // Could not load kernel: calculate it and save var errSave error kernel = CalcDemagKernel(inputSize, pbc, cellsize, accuracy) for i := 0; i < 3; i++ { for j := i; j < 3; j++ { if inputSize[Z] == 1 && ((i == X && j == Z) || (i == Y && j == Z)) { continue // element not needed in 2D } errSave = SaveKernel(fmt.Sprint(basename, i, j, ".ovf"), kernel[i][j]) if errSave != nil { break } } if errSave != nil { break } } if errSave != nil { util.Log("//Failed to cache kernel:", errSave) } else { util.Log("//Cached kernel:", basename) } return kernel }
func EnableUnsafe() { util.Log("Allowing unsafe features") allowUnsafe = true }