├── script ├── test.txt ├── Makefile ├── child.go ├── const.go ├── ronly.go ├── source.go ├── exec.go ├── if.go ├── index.go ├── function.go ├── expr.go ├── unaryexpr.go ├── incdecstmt.go ├── funcif.go ├── for.go ├── stmt.go ├── selector.go ├── error.go ├── blockstmt.go ├── lvalue.go └── lit.go ├── gui ├── Makefile ├── page_test.go ├── data.go ├── util.go ├── img.go ├── meter.go ├── progress.go ├── element.go ├── button.go ├── console.go ├── span.go ├── checkbox.go ├── range.go ├── clibox.go ├── number.go ├── textbox.go ├── select.go └── datamodels.go ├── svgo ├── Makefile └── LICENSE ├── bench ├── oommf4M.txt ├── gpus.gplot └── bench.mx3 ├── data ├── Makefile ├── doc.go ├── meta.go ├── slice_test.go ├── crop.go ├── reshape.go └── vector.go ├── draw ├── Makefile ├── doc.go ├── svg.go ├── colorscale.go ├── hslscale.go └── encode.go ├── dump └── Makefile ├── engine ├── Makefile ├── unsafe.go ├── ext_angles.go ├── zeeman.go ├── effectivefield.go ├── maxangle.go ├── ext_dwtilt.go ├── ext_topologicalcharge.go ├── euler.go ├── ext_topologicalchargelattice.go ├── od.go ├── number.go ├── ext_centerbubble.go ├── mfm.go ├── comp.go ├── heun.go ├── average.go ├── asyncio.go ├── engine.go ├── backwardeuler.go ├── ext_corepos.go ├── gofiles.go ├── rk4.go ├── energy.go └── log.go ├── httpfs ├── Makefile └── reader.go ├── mag ├── Makefile └── constants.go ├── oommf ├── Makefile └── util.go ├── timer └── Makefile ├── util ├── Makefile ├── atom.go └── util.go ├── cmd ├── mumax3 │ ├── Makefile │ ├── mumax3.sh │ ├── browser.go │ └── vet.go ├── mumax3-httpfsd │ ├── Makefile │ └── main.go ├── mumax3-plot │ └── Makefile ├── mumax3-server │ ├── Makefile │ ├── utitl.go │ ├── user.go │ ├── watchdog.go │ └── peers.go ├── mumax3-convert │ ├── Makefile │ ├── json.go │ ├── csv.go │ ├── resize.go │ ├── tasks.go │ ├── gnuplot.go │ ├── numpy.go │ └── normalize.go ├── mumax3-script │ ├── Makefile │ ├── mumax3-int │ └── main.go └── gccgorun ├── cuda ├── cu │ ├── doc.go │ ├── dim3.go │ ├── version_test.go │ ├── init_test.go │ ├── version.go │ ├── init.go │ ├── Makefile │ ├── testdata │ │ └── testmodule.cu │ ├── cgoflags.go │ ├── context_test.go │ ├── module_test.go │ ├── module.go │ ├── memset.go │ ├── peer.go │ ├── execution.go │ ├── stream.go │ └── function.go ├── cufft │ ├── doc.go │ ├── init_test.go │ ├── Makefile │ ├── cgoflags.go │ ├── mode.go │ ├── fft_test.go │ └── type.go ├── cuda2go ├── sum.h ├── exchange.h ├── atomicf.h ├── init_test.go ├── reducesum.cu ├── reducemaxabs.cu ├── reducedot.cu ├── mul.cu ├── reducemaxdiff.cu ├── regionselect.cu ├── reducemaxvecnorm2.cu ├── regiondecode.cu ├── zeromask.go ├── madd2.cu ├── lut.go ├── normalize.go ├── div.cu ├── zeromask.cu ├── constants.h ├── regionadds.cu ├── minimize.go ├── theta.cu ├── crossproduct.go ├── curand │ ├── Makefile │ ├── cgoflags.go │ └── generator.go ├── madd3.cu ├── phi.cu ├── angles.go ├── reducemaxvecdiff2.cu ├── copyunpad.cu ├── crop.cu ├── madd4.cu ├── kernmulc.cu ├── dotproduct.go ├── topologicalchargelattice.go ├── maxangle.go ├── normalize.cu ├── temperature.go ├── dotproduct.cu ├── topologicalcharge.go ├── regionaddv.cu ├── madd5.cu ├── crop.go ├── alloc.go ├── fftplan.go ├── resize.go ├── crossproduct.cu ├── buffer_test.go ├── madd6.cu ├── zhangli.go ├── shiftbytesy.cu ├── kernmulrsymm2dz.cu ├── madd7.cu ├── llnoprecess.cu ├── temperature2.cu ├── SOT.go ├── shiftbytes.cu ├── amul.h ├── shiftx.cu ├── shifty.cu ├── shiftz.cu ├── dmibulk.go ├── minimize.cu ├── resize.cu ├── copypadmul2.cu ├── fatbin.go ├── lltorque.go ├── dmi.go ├── slonczewski.go ├── lltorque2.cu ├── stencil.h ├── mslice.go ├── kernmulrsymm2dxy.cu ├── conv_copypad.go ├── exchange.go ├── region.go ├── uniaxialanisotropy2.cu ├── anisotropy.go ├── util.go ├── shift.go ├── exchangedecode.cu ├── magnetoelastic.go ├── conv_common.go ├── fft3dc2r.go ├── magnetoelasticfield.cu ├── conv_kernmul.go ├── fft3dr2c.go └── reduce_test.go ├── doc ├── mask.png ├── myfile.ovf ├── static │ ├── web1.png │ ├── web2.png │ ├── nimble-cubes128.png │ ├── nimble-cubes128-xmas.png │ └── style.css ├── README ├── tex │ └── Makefile ├── Makefile └── templates │ ├── header.html │ └── head.html ├── pre-commit ├── freetype ├── LICENSE ├── AUTHORS ├── README └── CONTRIBUTORS ├── post-commit ├── README.md └── Makefile /script/test.txt: -------------------------------------------------------------------------------- 1 | a:=1 2 | -------------------------------------------------------------------------------- /gui/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install 3 | -------------------------------------------------------------------------------- /svgo/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install 3 | -------------------------------------------------------------------------------- /bench/oommf4M.txt: -------------------------------------------------------------------------------- 1 | 2048 3 35 2 | 3 | -------------------------------------------------------------------------------- /data/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /draw/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /dump/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /engine/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /httpfs/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install 3 | -------------------------------------------------------------------------------- /mag/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /oommf/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /script/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /timer/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /util/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /cmd/mumax3/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /cmd/mumax3-httpfsd/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install 3 | -------------------------------------------------------------------------------- /cmd/mumax3-plot/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /cmd/mumax3-server/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install 3 | -------------------------------------------------------------------------------- /cmd/mumax3-convert/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /cmd/mumax3-script/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go install -v 3 | -------------------------------------------------------------------------------- /draw/doc.go: -------------------------------------------------------------------------------- 1 | // 2D rendering of data slices. 2 | package draw 3 | -------------------------------------------------------------------------------- /cuda/cu/doc.go: -------------------------------------------------------------------------------- 1 | // Go bindings for the CUDA driver API. 2 | package cu 3 | -------------------------------------------------------------------------------- /cuda/cufft/doc.go: -------------------------------------------------------------------------------- 1 | // Go bindings for the CUDA CUFFT API. 2 | package cufft 3 | -------------------------------------------------------------------------------- /cmd/mumax3-script/mumax3-int: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | rlwrap -m -S '> ' mumax3-script 3 | -------------------------------------------------------------------------------- /cuda/cu/dim3.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | type Dim3 struct { 4 | X, Y, Z int 5 | } 6 | -------------------------------------------------------------------------------- /cuda/cuda2go: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhujialin2018/mumax3-STT-SOT/HEAD/cuda/cuda2go -------------------------------------------------------------------------------- /doc/mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhujialin2018/mumax3-STT-SOT/HEAD/doc/mask.png -------------------------------------------------------------------------------- /doc/myfile.ovf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhujialin2018/mumax3-STT-SOT/HEAD/doc/myfile.ovf -------------------------------------------------------------------------------- /doc/static/web1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhujialin2018/mumax3-STT-SOT/HEAD/doc/static/web1.png -------------------------------------------------------------------------------- /doc/static/web2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhujialin2018/mumax3-STT-SOT/HEAD/doc/static/web2.png -------------------------------------------------------------------------------- /gui/page_test.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "testing" 4 | 5 | func TestNewPage(t *testing.T) { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /doc/static/nimble-cubes128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhujialin2018/mumax3-STT-SOT/HEAD/doc/static/nimble-cubes128.png -------------------------------------------------------------------------------- /data/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package data provides structures to store arrays in a hardware-agnostic (GPU-CPU) way. 3 | */ 4 | package data 5 | -------------------------------------------------------------------------------- /doc/static/nimble-cubes128-xmas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhujialin2018/mumax3-STT-SOT/HEAD/doc/static/nimble-cubes128-xmas.png -------------------------------------------------------------------------------- /cuda/sum.h: -------------------------------------------------------------------------------- 1 | #ifndef _SUM_H_ 2 | #define _SUM_H_ 3 | 4 | inline __device__ float sum(float a, float b){ 5 | return a + b; 6 | } 7 | 8 | #endif 9 | 10 | -------------------------------------------------------------------------------- /doc/README: -------------------------------------------------------------------------------- 1 | This directory contains everything needed to build the mumax3 website (Home page, API, and examples) 2 | 3 | "make html" builds the complete website in ${BUILDDIR}. 4 | -------------------------------------------------------------------------------- /svgo/LICENSE: -------------------------------------------------------------------------------- 1 | The contents of this repository are Licensed under 2 | the Creative Commons Attribution 3.0 license as described in 3 | http://creativecommons.org/licenses/by/3.0/us/ 4 | -------------------------------------------------------------------------------- /gui/data.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | type data struct { 4 | val interface{} 5 | } 6 | 7 | func (d *data) set(v interface{}) { d.val = v } 8 | func (d *data) value() interface{} { return d.val } 9 | -------------------------------------------------------------------------------- /gui/util.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | // concatenate elements 4 | func cat(s []string) string { 5 | str := "" 6 | for _, s := range s { 7 | str += s + " " 8 | } 9 | return str 10 | } 11 | -------------------------------------------------------------------------------- /cuda/cu/version_test.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestVersion(t *testing.T) { 9 | fmt.Println("CUDA driver version: ", Version()) 10 | } 11 | -------------------------------------------------------------------------------- /cuda/exchange.h: -------------------------------------------------------------------------------- 1 | #ifndef _EXCHANGE_H_ 2 | #define _EXCHANGE_H_ 3 | 4 | // indexing in symmetric matrix 5 | #define symidx(i, j) ( (j<=i)? ( (((i)*((i)+1)) /2 )+(j) ) : ( (((j)*((j)+1)) /2 )+(i) ) ) 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /doc/tex/Makefile: -------------------------------------------------------------------------------- 1 | mumax3.pdf: mumax3.tex 2 | pdflatex -halt-on-error mumax3.tex 3 | pdflatex -halt-on-error mumax3.tex 4 | 5 | .PHONY: clean 6 | clean: 7 | rm -f *.aux *.bbl *.blg *.ind *.ilg *.log *.toc *.out mumax3.pdf *.idx 8 | -------------------------------------------------------------------------------- /cuda/atomicf.h: -------------------------------------------------------------------------------- 1 | #ifndef _ATOMICF_H_ 2 | #define _ATOMICF_H_ 3 | 4 | // Atomic max of abs value. 5 | inline __device__ void atomicFmaxabs(float* a, float b){ 6 | b = fabs(b); 7 | atomicMax((int*)(a), *((int*)(&b))); 8 | } 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /cmd/gccgorun: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # wrapper for "go run" using gccgo with flags for speed. 3 | echo go run -compiler=gccgo -gccgoflags '-static-libgcc -O4 -Ofast -march=native' $@ 4 | go run -compiler=gccgo -gccgoflags '-static-libgcc -O4 -Ofast -march=native' $@ 5 | -------------------------------------------------------------------------------- /cuda/init_test.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/cuda/cu" 5 | ) 6 | 7 | // needed for all other tests. 8 | func init() { 9 | cu.Init(0) 10 | ctx := cu.CtxCreate(cu.CTX_SCHED_AUTO, 0) 11 | cu.CtxSetCurrent(ctx) 12 | } 13 | -------------------------------------------------------------------------------- /cuda/cu/init_test.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // needed for all other tests. 8 | func init() { 9 | Init(0) 10 | ctx := CtxCreate(CTX_SCHED_AUTO, 0) 11 | CtxSetCurrent(ctx) 12 | fmt.Println("Created CUDA context") 13 | } 14 | -------------------------------------------------------------------------------- /cuda/reducesum.cu: -------------------------------------------------------------------------------- 1 | #include "reduce.h" 2 | #include "sum.h" 3 | 4 | #define load(i) src[i] 5 | 6 | extern "C" __global__ void 7 | reducesum(float* __restrict__ src, float*__restrict__ dst, float initVal, int n) { 8 | reduce(load, sum, atomicAdd) 9 | } 10 | 11 | -------------------------------------------------------------------------------- /cmd/mumax3-convert/json.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | 7 | "github.com/mumax/3/data" 8 | ) 9 | 10 | func dumpJSON(f *data.Slice, info data.Meta, out io.Writer) { 11 | w := json.NewEncoder(out) 12 | w.Encode(f.Tensors()) 13 | } 14 | -------------------------------------------------------------------------------- /util/atom.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "sync/atomic" 4 | 5 | // Atomic int 6 | type Atom int32 7 | 8 | func (a *Atom) Add(v int32) { 9 | atomic.AddInt32((*int32)(a), v) 10 | } 11 | 12 | func (a *Atom) Load() int32 { 13 | return atomic.LoadInt32((*int32)(a)) 14 | } 15 | -------------------------------------------------------------------------------- /data/meta.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | // Holds meta data to be saved together with a slice. 4 | // Typically winds up in OVF or DUMP header 5 | type Meta struct { 6 | Name, Unit string 7 | Time, TimeStep float64 8 | CellSize [3]float64 9 | MeshUnit string 10 | } 11 | -------------------------------------------------------------------------------- /cuda/reducemaxabs.cu: -------------------------------------------------------------------------------- 1 | #include "reduce.h" 2 | #include "atomicf.h" 3 | 4 | #define load_fabs(i) fabs(src[i]) 5 | 6 | extern "C" __global__ void 7 | reducemaxabs(float* __restrict__ src, float* __restrict__ dst, float initVal, int n) { 8 | reduce(load_fabs, fmax, atomicFmaxabs) 9 | } 10 | 11 | -------------------------------------------------------------------------------- /cuda/cufft/init_test.go: -------------------------------------------------------------------------------- 1 | package cufft 2 | 3 | import ( 4 | "fmt" 5 | "github.com/mumax/3/cuda/cu" 6 | ) 7 | 8 | // needed for all other tests. 9 | func init() { 10 | cu.Init(0) 11 | ctx := cu.CtxCreate(cu.CTX_SCHED_AUTO, 0) 12 | cu.CtxSetCurrent(ctx) 13 | fmt.Println("Created CUDA context") 14 | } 15 | -------------------------------------------------------------------------------- /script/child.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | func Contains(tree, search Expr) bool { 4 | if tree == search { 5 | return true 6 | } else { 7 | children := tree.Child() 8 | for _, e := range children { 9 | if Contains(e, search) { 10 | return true 11 | } 12 | } 13 | } 14 | return false 15 | } 16 | -------------------------------------------------------------------------------- /cuda/reducedot.cu: -------------------------------------------------------------------------------- 1 | #include "reduce.h" 2 | #include "sum.h" 3 | 4 | #define load_prod(i) (x1[i] * x2[i]) 5 | 6 | extern "C" __global__ void 7 | reducedot(float* __restrict__ x1, float* __restrict__ x2, 8 | float*__restrict__ dst, float initVal, int n) { 9 | reduce(load_prod, sum, atomicAdd) 10 | } 11 | 12 | -------------------------------------------------------------------------------- /cuda/mul.cu: -------------------------------------------------------------------------------- 1 | // dst[i] = a[i] * b[i] 2 | extern "C" __global__ void 3 | mul(float* __restrict__ dst, float* __restrict__ a, float* __restrict__ b, int N) { 4 | 5 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 6 | 7 | if(i < N) { 8 | dst[i] = a[i] * b[i]; 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /engine/unsafe.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | func init() { 4 | // There are no unsafe features since version 3.10, but we want maximal backwards compatibility 5 | DeclFunc("ext_EnableUnsafe", EnableUnsafe, "Deprecated. Only here to ensure maximal backwards compatibility with mumax3.9c.") 6 | } 7 | 8 | func EnableUnsafe() { 9 | } 10 | -------------------------------------------------------------------------------- /cuda/reducemaxdiff.cu: -------------------------------------------------------------------------------- 1 | #include "reduce.h" 2 | #include "atomicf.h" 3 | 4 | #define load_diff(i) fabs(src1[i] - src2[i]) 5 | 6 | extern "C" __global__ void 7 | reducemaxdiff(float* __restrict__ src1, float* __restrict__ src2, float* __restrict__ dst, float initVal, int n) { 8 | reduce(load_diff, fmax, atomicFmaxabs) 9 | } 10 | 11 | -------------------------------------------------------------------------------- /cmd/mumax3/mumax3.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # This script adds the current directory to your library path 4 | # and launches mumax3 using the shipped cuda libraries. 5 | # 6 | # When you have correctly set-up cuda, you can just run 7 | # mumax directly without this wrapper. 8 | # 9 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd) 10 | ./mumax3-cuda6.0 $@ 11 | -------------------------------------------------------------------------------- /cuda/regionselect.cu: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern "C" __global__ void 4 | regionselect(float* __restrict__ dst, float* __restrict__ src, uint8_t* regions, uint8_t region, int N) { 5 | 6 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 7 | if (i < N) { 8 | dst[i] = (regions[i] == region? src[i]: 0.0f); 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /mag/constants.go: -------------------------------------------------------------------------------- 1 | // package mag provides magnetism-specific constants and the demag kernel. 2 | package mag 3 | 4 | import "math" 5 | 6 | const ( 7 | Mu0 = 4 * math.Pi * 1e-7 // Permeability of vacuum in Tm/A 8 | MuB = 9.2740091523e-24 // Bohr magneton in J/T 9 | Kb = 1.380650424e-23 // Boltzmann's constant in J/K 10 | Qe = 1.60217646e-19 // Electron charge in C 11 | ) 12 | -------------------------------------------------------------------------------- /cuda/reducemaxvecnorm2.cu: -------------------------------------------------------------------------------- 1 | #include "reduce.h" 2 | #include "atomicf.h" 3 | #include "float3.h" 4 | 5 | #define load_vecnorm2(i) \ 6 | pow2(x[i]) + pow2(y[i]) + pow2(z[i]) 7 | 8 | extern "C" __global__ void 9 | reducemaxvecnorm2(float* __restrict__ x, float* __restrict__ y, float* __restrict__ z, float* __restrict__ dst, float initVal, int n) { 10 | reduce(load_vecnorm2, fmax, atomicFmaxabs) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /cuda/cu/version.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | // This file implements CUDA driver version management 4 | 5 | //#include 6 | import "C" 7 | 8 | const CUDA_VERSION = C.CUDA_VERSION 9 | 10 | // Returns the CUDA driver version. 11 | func Version() int { 12 | var version C.int 13 | err := Result(C.cuDriverGetVersion(&version)) 14 | if err != SUCCESS { 15 | panic(err) 16 | } 17 | return int(version) 18 | } 19 | -------------------------------------------------------------------------------- /cuda/regiondecode.cu: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // decode the regions+LUT pair into an uncompressed array 4 | extern "C" __global__ void 5 | regiondecode(float* __restrict__ dst, float* __restrict__ LUT, uint8_t* regions, int N) { 6 | 7 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 8 | if (i < N) { 9 | 10 | dst[i] = LUT[regions[i]]; 11 | 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /cuda/zeromask.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "unsafe" 5 | 6 | "github.com/mumax/3/data" 7 | ) 8 | 9 | // Sets vector dst to zero where mask != 0. 10 | func ZeroMask(dst *data.Slice, mask LUTPtr, regions *Bytes) { 11 | N := dst.Len() 12 | cfg := make1DConf(N) 13 | 14 | for c := 0; c < dst.NComp(); c++ { 15 | k_zeromask_async(dst.DevPtr(c), unsafe.Pointer(mask), regions.Ptr, N, cfg) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /cuda/madd2.cu: -------------------------------------------------------------------------------- 1 | 2 | // dst[i] = fac1*src1[i] + fac2*src2[i]; 3 | extern "C" __global__ void 4 | madd2(float* __restrict__ dst, 5 | float* __restrict__ src1, float fac1, 6 | float* __restrict__ src2, float fac2, int N) { 7 | 8 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 9 | 10 | if(i < N) { 11 | dst[i] = fac1*src1[i] + fac2*src2[i]; 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /cuda/lut.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | // Look-up tables holding per-region parameter values. 4 | // LUT[regions[cellindex]] gives parameter value for cell. 5 | 6 | import "unsafe" 7 | 8 | type LUTPtr unsafe.Pointer // points to 256 float32's 9 | type LUTPtrs []unsafe.Pointer // elements point to 256 float32's 10 | type SymmLUT unsafe.Pointer // points to 256x256 symmetric matrix, only lower half stored. See exchange.cu 11 | -------------------------------------------------------------------------------- /cuda/normalize.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // Normalize vec to unit length, unless length or vol are zero. 9 | func Normalize(vec, vol *data.Slice) { 10 | util.Argument(vol == nil || vol.NComp() == 1) 11 | N := vec.Len() 12 | cfg := make1DConf(N) 13 | k_normalize_async(vec.DevPtr(X), vec.DevPtr(Y), vec.DevPtr(Z), vol.DevPtr(0), N, cfg) 14 | } 15 | -------------------------------------------------------------------------------- /gui/img.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type img struct { 6 | data 7 | } 8 | 9 | func (e *img) update(id string) []jsCall { 10 | return []jsCall{{F: "setAttr", Args: []interface{}{id, "src", e.value()}}} 11 | } 12 | 13 | func (d *Page) Img(id string, value interface{}, extra ...string) string { 14 | e := &img{data: data{value}} 15 | d.addElem(id, e) 16 | return fmt.Sprintf(` `, id, cat(extra)) 17 | } 18 | -------------------------------------------------------------------------------- /cuda/div.cu: -------------------------------------------------------------------------------- 1 | // dst[i] = a[i] / b[i] 2 | extern "C" __global__ void 3 | pointwise_div(float* __restrict__ dst, float* __restrict__ a, float* __restrict__ b, int N) { 4 | 5 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 6 | 7 | if(i < N) { 8 | if (b[i] != 0.0f) { 9 | dst[i] = a[i] / b[i]; 10 | } else { 11 | dst[i] = 0.0f; 12 | } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /cuda/zeromask.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include "float3.h" 3 | 4 | // set dst to zero in cells where mask != 0 5 | extern "C" __global__ void 6 | zeromask(float* __restrict__ dst, float* maskLUT, uint8_t* regions, int N) { 7 | 8 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 9 | if (i < N) { 10 | if (maskLUT[regions[i]] != 0) { 11 | dst[i] = 0; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | BUILDDIR="build" 2 | STATIC="static" 3 | 4 | # build the html pages in ${BUILDDIR} 5 | .PHONY: html 6 | html: doc mumax3libs 7 | mkdir -p ${BUILDDIR} 8 | ./doc -examples -builddir ${BUILDDIR} 9 | cp ${STATIC}/* build 10 | 11 | .PHONY: doc 12 | doc: 13 | go build -v 14 | 15 | .PHONY: mumax3libs 16 | mumax3libs: 17 | go install -v github.com/mumax/3/cmd/... 18 | 19 | .PHONY: clean 20 | clean: 21 | rm -rf build 22 | rm -f doc -------------------------------------------------------------------------------- /bench/gpus.gplot: -------------------------------------------------------------------------------- 1 | #! /usr/bin/gnuplot 2 | 3 | set term pdf size 4in, 3in; 4 | set output "gpus.pdf" 5 | set boxwidth 0.5 6 | set style fill solid 7 | set key off 8 | set ylabel "throughput (M cells/s)" 9 | set xtics rotate by -90 10 | #set xtics out offset 0,-1.2 11 | 12 | set yrange[0:650] 13 | plot "gpus.txt" u ($0+1):($2/1e6):xtic(4) w boxes, "oommf4M.txt" u (0):(4*$1**2 * $2 /$3/1e6):xtic("OOMMF(CPU)") w boxes 14 | 15 | set output 16 | 17 | -------------------------------------------------------------------------------- /cuda/constants.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONSTANTS_H_ 2 | #define _CONSTANTS_H_ 3 | 4 | #define PI 3.1415926535897932384626433 5 | #define MU0 (4*PI*1e-7) // Permeability of vacuum in Tm/A 6 | #define QE 1.60217646E-19 // Electron charge in C 7 | #define MUB 9.2740091523E-24 // Bohr magneton in J/T 8 | #define GAMMA0 1.7595e11 // Gyromagnetic ratio of electron, in rad/Ts 9 | #define HBAR 1.05457173E-34 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /cuda/cu/init.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | // This file implements CUDA driver initialization 4 | 5 | //#include 6 | import "C" 7 | 8 | // Initialize the CUDA driver API. 9 | // Currently, flags must be 0. 10 | // If Init() has not been called, any function from the driver API will panic with ERROR_NOT_INITIALIZED. 11 | func Init(flags int) { 12 | err := Result(C.cuInit(C.uint(flags))) 13 | if err != SUCCESS { 14 | panic(err) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /cuda/regionadds.cu: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // add region-based scalar to dst: 4 | // dst[i] += LUT[region[i]] 5 | extern "C" __global__ void 6 | regionadds(float* __restrict__ dst, 7 | float* __restrict__ LUT, 8 | uint8_t* regions, int N) { 9 | 10 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 11 | if (i < N) { 12 | 13 | uint8_t r = regions[i]; 14 | dst[i] += LUT[r]; 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /engine/ext_angles.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "github.com/mumax/3/cuda" 5 | "github.com/mumax/3/data" 6 | ) 7 | 8 | var ( 9 | ext_phi = NewScalarField("ext_phi", "rad", "Azimuthal angle", SetPhi) 10 | ext_theta = NewScalarField("ext_theta", "rad", "Polar angle", SetTheta) 11 | ) 12 | 13 | func SetPhi(dst *data.Slice) { 14 | cuda.SetPhi(dst, M.Buffer()) 15 | } 16 | 17 | func SetTheta(dst *data.Slice) { 18 | cuda.SetTheta(dst, M.Buffer()) 19 | } 20 | -------------------------------------------------------------------------------- /gui/meter.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type meter struct { 6 | data 7 | } 8 | 9 | func (e *meter) update(id string) []jsCall { 10 | return []jsCall{{F: "setAttr", Args: []interface{}{id, "value", e.value()}}} 11 | } 12 | 13 | func (d *Page) Meter(id string, min, max, value int, extra ...string) string { 14 | e := &meter{data: data{value}} 15 | d.addElem(id, e) 16 | return fmt.Sprintf(``, id, min, max) 17 | } 18 | -------------------------------------------------------------------------------- /gui/progress.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type progress struct { 6 | data 7 | } 8 | 9 | func (e *progress) update(id string) []jsCall { 10 | return []jsCall{{F: "setAttr", Args: []interface{}{id, "value", e.value()}}} 11 | } 12 | 13 | func (d *Page) Progress(id string, max, value int, extra ...string) string { 14 | e := &progress{data: data{value}} 15 | d.addElem(id, e) 16 | return fmt.Sprintf(``, id, max) 17 | } 18 | -------------------------------------------------------------------------------- /script/const.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import "reflect" 4 | 5 | type Const struct { 6 | value interface{} 7 | typ reflect.Type 8 | } 9 | 10 | func NewConst(e Expr) *Const { 11 | return &Const{value: e.Eval(), typ: e.Type()} 12 | } 13 | 14 | func (c *Const) Eval() interface{} { return c.value } 15 | func (c *Const) Type() reflect.Type { return c.typ } 16 | func (c *Const) Child() []Expr { return nil } 17 | func (c *Const) Fix() Expr { return c } 18 | -------------------------------------------------------------------------------- /gui/element.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type element struct { 6 | data 7 | } 8 | 9 | func (e *element) update(id string) []jsCall { 10 | return []jsCall{{F: "setAttr", Args: []interface{}{id, "innerHTML", e.value()}}} 11 | } 12 | 13 | func (d *Page) Element(id, typ, attr string, value interface{}, extra ...string) string { 14 | e := &element{data: data{value}} 15 | d.addElem(id, e) 16 | return fmt.Sprintf(` `, id, cat(extra)) 17 | } 18 | -------------------------------------------------------------------------------- /gui/button.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type button struct { 6 | data 7 | } 8 | 9 | func (e *button) update(id string) []jsCall { 10 | return []jsCall{{F: "setAttr", Args: []interface{}{id, "innerHTML", e.value()}}} 11 | } 12 | 13 | func (d *Page) Button(id string, value interface{}, extra ...string) string { 14 | e := &button{data: data{value}} 15 | d.addElem(id, e) 16 | return fmt.Sprintf(``, id, id) 17 | } 18 | -------------------------------------------------------------------------------- /cuda/minimize.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | ) 6 | 7 | // m = 1 / (4 + τ²(m x H)²) [{4 - τ²(m x H)²} m - 4τ(m x m x H)] 8 | // note: torque from LLNoPrecess has negative sign 9 | func Minimize(m, m0, torque *data.Slice, dt float32) { 10 | N := m.Len() 11 | cfg := make1DConf(N) 12 | 13 | k_minimize_async(m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 14 | m0.DevPtr(X), m0.DevPtr(Y), m0.DevPtr(Z), 15 | torque.DevPtr(X), torque.DevPtr(Y), torque.DevPtr(Z), 16 | dt, N, cfg) 17 | } 18 | -------------------------------------------------------------------------------- /gui/console.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type console struct { 6 | data 7 | } 8 | 9 | func (e *console) update(id string) []jsCall { 10 | return []jsCall{{F: "setConsoleText", Args: []interface{}{e.value()}}} 11 | } 12 | 13 | func (d *Page) Console(id string, rows, cols int, value interface{}, extra ...string) string { 14 | e := &console{data: data{value}} 15 | d.addElem(id, e) 16 | return fmt.Sprintf(``, id, rows, cols, cat(extra)) 17 | } 18 | -------------------------------------------------------------------------------- /gui/span.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type span struct { 6 | data 7 | } 8 | 9 | func (e *span) update(id string) []jsCall { 10 | return []jsCall{{F: "setAttr", Args: []interface{}{id, "innerHTML", e.value()}}} 11 | } 12 | 13 | // {{.Span id value}} adds a piece of text ("label") to the document. 14 | func (d *Page) Span(id string, value interface{}, extra ...string) string { 15 | e := &span{data: data{value}} 16 | d.addElem(id, e) 17 | return fmt.Sprintf(` `, id, cat(extra)) 18 | } 19 | -------------------------------------------------------------------------------- /gui/checkbox.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type checkbox struct { 6 | data 7 | } 8 | 9 | func (e *checkbox) update(id string) []jsCall { 10 | return []jsCall{{F: "setAttr", Args: []interface{}{id, "checked", e.value()}}} 11 | } 12 | 13 | func (d *Page) Checkbox(id, text string, value bool, extra ...string) string { 14 | e := &checkbox{data: data{value}} 15 | d.addElem(id, e) 16 | return fmt.Sprintf(`%v`, id, id, text) 17 | } 18 | -------------------------------------------------------------------------------- /cuda/theta.cu: -------------------------------------------------------------------------------- 1 | #include "stencil.h" 2 | 3 | extern "C" __global__ void 4 | setTheta(float* __restrict__ theta, float* __restrict__ mz, int Nx, int Ny, int Nz) { 5 | 6 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 7 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 8 | int iz = blockIdx.z * blockDim.z + threadIdx.z; 9 | 10 | if (ix >= Nx || iy >= Ny || iz >= Nz) 11 | { 12 | return; 13 | } 14 | 15 | int I = idx(ix, iy, iz); // central cell index 16 | theta[I] = acosf(mz[I]); 17 | } -------------------------------------------------------------------------------- /cuda/crossproduct.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | func CrossProduct(dst, a, b *data.Slice) { 9 | util.Argument(dst.NComp() == 3 && a.NComp() == 3 && b.NComp() == 3) 10 | util.Argument(dst.Len() == a.Len() && dst.Len() == b.Len()) 11 | 12 | N := dst.Len() 13 | cfg := make1DConf(N) 14 | k_crossproduct_async(dst.DevPtr(X), dst.DevPtr(Y), dst.DevPtr(Z), 15 | a.DevPtr(X), a.DevPtr(Y), a.DevPtr(Z), 16 | b.DevPtr(X), b.DevPtr(Y), b.DevPtr(Z), 17 | N, cfg) 18 | } 19 | -------------------------------------------------------------------------------- /gui/range.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type slider struct { 6 | data 7 | } 8 | 9 | func (e *slider) update(id string) []jsCall { 10 | return []jsCall{{F: "setAttr", Args: []interface{}{id, "value", e.value()}}} 11 | } 12 | 13 | func (d *Page) Range(id string, min, max, value int, extra ...string) string { 14 | e := &slider{data: data{value}} 15 | d.addElem(id, e) 16 | return fmt.Sprintf(``, id, min, max, id) 17 | } 18 | -------------------------------------------------------------------------------- /gui/clibox.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type clibox struct { 6 | data 7 | } 8 | 9 | func (e *clibox) update(id string) []jsCall { 10 | return []jsCall{} // We never set the value of the CLI box, only the user does 11 | } 12 | 13 | // Command-line interface textbox where user types commands. 14 | func (d *Page) CliBox(id string, value interface{}, extra ...string) string { 15 | e := &clibox{data: data{value}} 16 | d.addElem(id, e) 17 | return fmt.Sprintf(``, "text", id, cat(extra)) 18 | } 19 | -------------------------------------------------------------------------------- /data/slice_test.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestIndex(t *testing.T) { 8 | mesh := [3]int{6, 5, 4} 9 | slice := NewSlice(7, mesh) 10 | data := slice.Tensors() 11 | 12 | if len(data) != 7 { //c 13 | t.Fail() 14 | } 15 | if len(data[0]) != 4 { // z 16 | t.Fail() 17 | } 18 | if len(data[0][0]) != 5 { // y 19 | t.Fail() 20 | } 21 | if len(data[0][0][0]) != 6 { // x 22 | t.Fail() 23 | } 24 | 25 | slice.Set(4, 5, 4, 3, 345) // c x y z 26 | if data[4][3][4][5] != 345 { 27 | t.Fail() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /engine/zeeman.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | var ( 4 | B_ext = NewExcitation("B_ext", "T", "Externally applied field") 5 | Edens_zeeman = NewScalarField("Edens_Zeeman", "J/m3", "Zeeman energy density", AddEdens_zeeman) 6 | E_Zeeman = NewScalarValue("E_Zeeman", "J", "Zeeman energy", GetZeemanEnergy) 7 | ) 8 | 9 | var AddEdens_zeeman = makeEdensAdder(B_ext, -1) 10 | 11 | func init() { 12 | registerEnergy(GetZeemanEnergy, AddEdens_zeeman) 13 | } 14 | 15 | func GetZeemanEnergy() float64 { 16 | return -1 * cellVolume() * dot(&M_full, B_ext) 17 | } 18 | -------------------------------------------------------------------------------- /cuda/curand/Makefile: -------------------------------------------------------------------------------- 1 | all: 6g gccgo doc 2 | 3 | 6g: 4 | go install -v 5 | gofmt -w *.go 6 | 7 | GCCGO=gccgo -gccgoflags '-static-libgcc -O3' 8 | 9 | gccgo: 10 | go build -v -compiler $(GCCGO) 11 | 12 | test: 6gtest gccgotest 13 | 14 | 6gtest: 15 | go test 16 | 17 | gccgotest: 18 | go test -compiler $(GCCGO) 19 | 20 | bench: 6gbench gccgobench 21 | 22 | 6gbench: 23 | go test -bench=. 24 | 25 | gccgobench: 26 | go test -bench=. -compiler $(GCCGO) 27 | 28 | clean: 29 | go clean 30 | 31 | doc: 32 | godoc github.com/barnex/cuda5/curand > README 33 | -------------------------------------------------------------------------------- /cuda/madd3.cu: -------------------------------------------------------------------------------- 1 | 2 | // dst[i] = fac1 * src1[i] + fac2 * src2[i] + fac3 * src3[i] 3 | extern "C" __global__ void 4 | madd3(float* __restrict__ dst, 5 | float* __restrict__ src1, float fac1, 6 | float* __restrict__ src2, float fac2, 7 | float* __restrict__ src3, float fac3, int N) { 8 | 9 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 10 | 11 | if(i < N) { 12 | dst[i] = (fac1 * src1[i]) + (fac2 * src2[i] + fac3 * src3[i]); 13 | // parens for better accuracy heun solver. 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /cuda/phi.cu: -------------------------------------------------------------------------------- 1 | #include "stencil.h" 2 | 3 | extern "C" __global__ void 4 | setPhi(float* __restrict__ phi, float* __restrict__ mx, float* __restrict__ my, int Nx, int Ny, int Nz) { 5 | 6 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 7 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 8 | int iz = blockIdx.z * blockDim.z + threadIdx.z; 9 | 10 | if (ix >= Nx || iy >= Ny || iz >= Nz) 11 | { 12 | return; 13 | } 14 | 15 | int I = idx(ix, iy, iz); // central cell index 16 | phi[I] = atan2f(my[I], mx[I]); 17 | } -------------------------------------------------------------------------------- /cmd/mumax3-convert/csv.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | 7 | "github.com/mumax/3/data" 8 | ) 9 | 10 | // comma-separated values 11 | func dumpCSV(f *data.Slice, info data.Meta, out io.Writer) { 12 | f2 := ", " + *flag_format 13 | a := f.Tensors() 14 | for _, a := range a { 15 | for _, a := range a { 16 | for _, a := range a { 17 | fmt.Fprintf(out, *flag_format, a[0]) 18 | for i := 1; i < len(a); i++ { 19 | fmt.Fprintf(out, f2, a[i]) 20 | } 21 | fmt.Fprintln(out) 22 | } 23 | fmt.Fprintln(out) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /cuda/angles.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | func SetPhi(s *data.Slice, m *data.Slice) { 9 | N := s.Size() 10 | util.Argument(m.Size() == N) 11 | cfg := make3DConf(N) 12 | k_setPhi_async(s.DevPtr(X), m.DevPtr(X), m.DevPtr(Y), N[X], N[Y], N[Z], cfg) 13 | return 14 | } 15 | 16 | func SetTheta(s *data.Slice, m *data.Slice) { 17 | N := s.Size() 18 | util.Argument(m.Size() == N) 19 | cfg := make3DConf(N) 20 | k_setTheta_async(s.DevPtr(X), m.DevPtr(Z), N[X], N[Y], N[Z], cfg) 21 | return 22 | } 23 | -------------------------------------------------------------------------------- /cuda/cu/Makefile: -------------------------------------------------------------------------------- 1 | all: 6g gccgo doc 2 | 3 | 6g: 4 | go install -v 5 | go tool vet *.go 6 | gofmt -w *.go 7 | 8 | GCCGO=gccgo -gccgoflags '-static-libgcc -O3' 9 | 10 | gccgo: 11 | go build -v -compiler $(GCCGO) 12 | 13 | test: 6gtest gccgotest 14 | 15 | 6gtest: 16 | go test 17 | 18 | gccgotest: 19 | go test -compiler $(GCCGO) 20 | 21 | bench: 6gbench gccgobench 22 | 23 | 6gbench: 24 | go test -bench=. 25 | 26 | gccgobench: 27 | go test -bench=. -compiler $(GCCGO) 28 | 29 | clean: 30 | go clean 31 | 32 | doc: 33 | godoc github.com/barnex/cuda5/cu > README 34 | -------------------------------------------------------------------------------- /cuda/reducemaxvecdiff2.cu: -------------------------------------------------------------------------------- 1 | #include "reduce.h" 2 | #include "atomicf.h" 3 | #include "float3.h" 4 | 5 | #define load_vecdiff2(i) \ 6 | pow2(x1[i] - x2[i]) + \ 7 | pow2(y1[i] - y2[i]) + \ 8 | pow2(z1[i] - z2[i]) \ 9 | 10 | extern "C" __global__ void 11 | reducemaxvecdiff2(float* __restrict__ x1, float* __restrict__ y1, float* __restrict__ z1, 12 | float* __restrict__ x2, float* __restrict__ y2, float* __restrict__ z2, 13 | float* __restrict__ dst, float initVal, int n) { 14 | reduce(load_vecdiff2, fmax, atomicFmaxabs) 15 | } 16 | 17 | -------------------------------------------------------------------------------- /cuda/cu/testdata/testmodule.cu: -------------------------------------------------------------------------------- 1 | /* 2 | * Module to test CUDA module loading and execution. 3 | * To be compiled with: 4 | * nvcc -ptx testmodule.cu 5 | */ 6 | 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #define threadindex ( ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x ) 13 | 14 | /// Sets the first N elements of array to value. 15 | __global__ void testMemset(float* array, float value, int N){ 16 | int i = threadindex; 17 | if(i < N){ 18 | array[i] = value; 19 | } 20 | } 21 | 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /cuda/cufft/Makefile: -------------------------------------------------------------------------------- 1 | all: 6g gccgo doc 2 | 3 | 6g: 4 | go install -v 5 | go tool vet *.go 6 | gofmt -w *.go 7 | 8 | GCCGO=gccgo -gccgoflags '-static-libgcc -O3' 9 | 10 | gccgo: 11 | go build -v -compiler $(GCCGO) 12 | 13 | test: 6gtest gccgotest 14 | 15 | 6gtest: 16 | go test 17 | 18 | gccgotest: 19 | go test -compiler $(GCCGO) 20 | 21 | bench: 6gbench gccgobench 22 | 23 | 6gbench: 24 | go test -bench=. 25 | 26 | gccgobench: 27 | go test -bench=. -compiler $(GCCGO) 28 | 29 | clean: 30 | go clean 31 | 32 | doc: 33 | godoc github.com/barnex/cuda5/cufft > README 34 | -------------------------------------------------------------------------------- /pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # A hook script to verify what is about to be committed. 4 | # Called by git-commit with no arguments. The hook should 5 | # exit with non-zero status after issuing an appropriate message if 6 | # it wants to stop the commit. 7 | # 8 | # Add this file to .git/hooks 9 | # 10 | # Runs gofmt on the code and stops commit if files were affected. 11 | # 12 | fail=0; 13 | 14 | if (gofmt -w -l */*.go */*/*.go | grep \.go); then exit 1; fi; 15 | make || exit 1 16 | 17 | #if astyle --indent=tab cuda/*.cu | grep Formatted; then exit 1; fi; 18 | 19 | exit 0 20 | -------------------------------------------------------------------------------- /cmd/mumax3/browser.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os/exec" 6 | ) 7 | 8 | // Try to open url in a browser. Instruct to do so if it fails. 9 | func openbrowser(url string) { 10 | for _, cmd := range browsers { 11 | err := exec.Command(cmd, url).Start() 12 | if err == nil { 13 | fmt.Println("//openend web interface in", cmd) 14 | return 15 | } 16 | } 17 | fmt.Println("//please open ", url, " in a browser") 18 | } 19 | 20 | // list of browsers to try. 21 | var browsers = []string{"x-www-browser", "google-chrome", "chromium-browser", "firefox", "explorer"} 22 | -------------------------------------------------------------------------------- /cuda/copyunpad.cu: -------------------------------------------------------------------------------- 1 | #include "stencil.h" 2 | 3 | // Copy src (size S, larger) to dst (size D, smaller) 4 | extern "C" __global__ void 5 | copyunpad(float* __restrict__ dst, int Dx, int Dy, int Dz, 6 | float* __restrict__ src, int Sx, int Sy, int Sz) { 7 | 8 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 9 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 10 | int iz = blockIdx.z * blockDim.z + threadIdx.z; 11 | 12 | if (ix= Nx || iy>=Ny) { 8 | return; 9 | } 10 | 11 | int I = iy*Nx + ix; 12 | int e = 2 * I; 13 | 14 | float reM = fftM[e ]; 15 | float imM = fftM[e+1]; 16 | float reK = fftK[e ]; 17 | float imK = fftK[e+1]; 18 | 19 | fftM[e ] = reM * reK - imM * imK; 20 | fftM[e+1] = reM * imK + imM * reK; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /gui/number.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type number struct { 6 | data 7 | } 8 | 9 | func (e *number) update(id string) []jsCall { 10 | return []jsCall{{F: "setAttr", Args: []interface{}{id, "value", e.value()}}} 11 | } 12 | 13 | func (d *Page) Number(id string, min, max, value int, extra ...string) string { 14 | e := &number{data: data{value}} 15 | d.addElem(id, e) 16 | return fmt.Sprintf(``, "number", id, id, id, id, min, max, cat(extra)) 17 | } 18 | -------------------------------------------------------------------------------- /cuda/dotproduct.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // dst += prefactor * dot(a, b), as used for energy density 9 | func AddDotProduct(dst *data.Slice, prefactor float32, a, b *data.Slice) { 10 | util.Argument(dst.NComp() == 1 && a.NComp() == 3 && b.NComp() == 3) 11 | util.Argument(dst.Len() == a.Len() && dst.Len() == b.Len()) 12 | 13 | N := dst.Len() 14 | cfg := make1DConf(N) 15 | k_dotproduct_async(dst.DevPtr(0), prefactor, 16 | a.DevPtr(X), a.DevPtr(Y), a.DevPtr(Z), 17 | b.DevPtr(X), b.DevPtr(Y), b.DevPtr(Z), 18 | N, cfg) 19 | } 20 | -------------------------------------------------------------------------------- /cuda/topologicalchargelattice.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // Topological charge according to Berg and Lüscher 9 | func SetTopologicalChargeLattice(s *data.Slice, m *data.Slice, mesh *data.Mesh) { 10 | cellsize := mesh.CellSize() 11 | N := s.Size() 12 | util.Argument(m.Size() == N) 13 | cfg := make3DConf(N) 14 | icxcy := float32(1.0 / (cellsize[X] * cellsize[Y])) 15 | 16 | k_settopologicalchargelattice_async(s.DevPtr(X), 17 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 18 | icxcy, N[X], N[Y], N[Z], mesh.PBC_code(), cfg) 19 | } 20 | -------------------------------------------------------------------------------- /data/crop.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | // Cut-out a piece between given bounds (incl, excl) 4 | func Crop(in *Slice, x1, x2, y1, y2, z1, z2 int) *Slice { 5 | Nx := x2 - x1 6 | Ny := y2 - y1 7 | Nz := z2 - z1 8 | 9 | size := [3]int{Nx, Ny, Nz} 10 | ncomp := in.NComp() 11 | 12 | out := NewSlice(ncomp, size) 13 | 14 | a := in.Tensors() 15 | b := out.Tensors() 16 | 17 | for c := 0; c < ncomp; c++ { 18 | for z := 0; z < Nz; z++ { 19 | for y := 0; y < Ny; y++ { 20 | for x := 0; x < Nx; x++ { 21 | b[c][z][y][x] = a[c][z+z1][y+y1][x+x1] 22 | } 23 | } 24 | } 25 | } 26 | 27 | return out 28 | } 29 | -------------------------------------------------------------------------------- /freetype/LICENSE: -------------------------------------------------------------------------------- 1 | Use of the Freetype-Go software is subject to your choice of exactly one of 2 | the following two licenses: 3 | * The FreeType License, which is similar to the original BSD license with 4 | an advertising clause, or 5 | * The GNU General Public License (GPL), version 2 or later. 6 | 7 | The text of these licenses are available in the licenses/ftl.txt and the 8 | licenses/gpl.txt files respectively. They are also available at 9 | http://freetype.sourceforge.net/license.html 10 | 11 | The Luxi fonts in the testdata directory are licensed separately. See the 12 | testdata/COPYING file for details. 13 | -------------------------------------------------------------------------------- /gui/textbox.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type textbox struct { 6 | data 7 | } 8 | 9 | func (e *textbox) update(id string) []jsCall { 10 | return []jsCall{{F: "setTextbox", Args: []interface{}{id, e.value()}}} 11 | } 12 | 13 | func (d *Page) TextBox(id string, value interface{}, extra ...string) string { 14 | e := &textbox{data: data{value}} 15 | d.addElem(id, e) 16 | return fmt.Sprintf(``, "text", id, id, id, id, id, cat(extra)) 17 | } 18 | -------------------------------------------------------------------------------- /cmd/mumax3-convert/resize.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "strconv" 6 | "strings" 7 | 8 | "github.com/mumax/3/data" 9 | "github.com/mumax/3/util" 10 | ) 11 | 12 | func resize(f *data.Slice, arg string) { 13 | s := parseSize(arg) 14 | resized := data.Resample(f, s) 15 | *f = *resized 16 | } 17 | 18 | func parseSize(arg string) (size [3]int) { 19 | words := strings.Split(arg, "x") 20 | if len(words) != 3 { 21 | log.Fatal("resize: need N0xN1xN2 argument") 22 | } 23 | for i, w := range words { 24 | v, err := strconv.Atoi(w) 25 | util.FatalErr(err) 26 | size[i] = v 27 | } 28 | return 29 | } 30 | -------------------------------------------------------------------------------- /cuda/maxangle.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "unsafe" 5 | 6 | "github.com/mumax/3/data" 7 | ) 8 | 9 | // SetMaxAngle sets dst to the maximum angle of each cells magnetization with all of its neighbors, 10 | // provided the exchange stiffness with that neighbor is nonzero. 11 | func SetMaxAngle(dst, m *data.Slice, Aex_red SymmLUT, regions *Bytes, mesh *data.Mesh) { 12 | N := mesh.Size() 13 | pbc := mesh.PBC_code() 14 | cfg := make3DConf(N) 15 | k_setmaxangle_async(dst.DevPtr(0), 16 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 17 | unsafe.Pointer(Aex_red), regions.Ptr, 18 | N[X], N[Y], N[Z], pbc, cfg) 19 | } 20 | -------------------------------------------------------------------------------- /cuda/normalize.cu: -------------------------------------------------------------------------------- 1 | #include "float3.h" 2 | 3 | // normalize vector {vx, vy, vz} to unit length, unless length or vol are zero. 4 | extern "C" __global__ void 5 | normalize(float* __restrict__ vx, float* __restrict__ vy, float* __restrict__ vz, float* __restrict__ vol, int N) { 6 | 7 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 8 | if (i < N) { 9 | 10 | float v = (vol == NULL? 1.0f: vol[i]); 11 | float3 V = {v*vx[i], v*vy[i], v*vz[i]}; 12 | V = normalized(V); 13 | vx[i] = V.x; 14 | vy[i] = V.y; 15 | vz[i] = V.z; 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /cuda/cu/cgoflags.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | // This file provides CGO flags to find CUDA libraries and headers. 4 | 5 | //#cgo LDFLAGS:-lcuda 6 | // 7 | ////default location: 8 | //#cgo LDFLAGS:-L/usr/local/cuda/lib64/stubs/ 9 | //#cgo CFLAGS: -I/usr/local/cuda/include/ 10 | // 11 | ////Ubuntu 15.04: 12 | //#cgo LDFLAGS:-L/usr/lib/x86_64-linux-gnu/ 13 | //#cgo CFLAGS: -I/usr/include 14 | // 15 | ////arch linux: 16 | //#cgo LDFLAGS:-L/opt/cuda/lib64 -L/opt/cuda/lib 17 | //#cgo CFLAGS: -I/opt/cuda/include 18 | // 19 | ////WINDOWS: 20 | //#cgo windows LDFLAGS:-LC:/cuda/lib/x64 21 | //#cgo windows CFLAGS: -IC:/cuda/include 22 | import "C" 23 | -------------------------------------------------------------------------------- /cuda/temperature.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // Set Bth to thermal noise (Brown). 9 | // see temperature.cu 10 | func SetTemperature(Bth, noise *data.Slice, k2mu0_Mu0VgammaDt float64, Msat, Temp, Alpha MSlice) { 11 | util.Argument(Bth.NComp() == 1 && noise.NComp() == 1) 12 | 13 | N := Bth.Len() 14 | cfg := make1DConf(N) 15 | 16 | k_settemperature2_async(Bth.DevPtr(0), noise.DevPtr(0), float32(k2mu0_Mu0VgammaDt), 17 | Msat.DevPtr(0), Msat.Mul(0), 18 | Temp.DevPtr(0), Temp.Mul(0), 19 | Alpha.DevPtr(0), Alpha.Mul(0), 20 | N, cfg) 21 | } 22 | -------------------------------------------------------------------------------- /post-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # A hook script to verify what is about to be committed. 4 | # Called by git-commit with no arguments. The hook should 5 | # exit with non-zero status after issuing an appropriate message if 6 | # it wants to stop the commit. 7 | # 8 | # Add this file to .git/hooks 9 | 10 | # Run all unit tests 11 | echo Running unit tests in background 12 | rm test.log -rf 13 | (if (make test >> test.log 2>> test.log); then 14 | notify-send "Unit tests passed" 2> /dev/null 15 | exit 0; 16 | else 17 | notify-send "Unit tests failed" 2> /dev/null 18 | cat test.log; 19 | rm test.log; 20 | exit 2; 21 | fi;)& 22 | -------------------------------------------------------------------------------- /bench/bench.mx3: -------------------------------------------------------------------------------- 1 | msat = 800e3 2 | aex = 13e-12 3 | alpha = 0.01 4 | c := 4e-9 5 | setcellsize(c, c, c) 6 | setsolver(2) 7 | 8 | for e:=5; e<14; e++{ 9 | n := pow(2, e) 10 | setgridsize(n, n, 1) 11 | print(n, "x", n) 12 | 13 | steps(1) // warm-up kernel 14 | 15 | b_ext = vector(0, 0.01, 0) 16 | m=uniform(1, 0, 0) // warm-up dt 17 | steps(3) 18 | 19 | m=uniform(1, 0, 0) // start! 20 | t = 0 21 | start := now() 22 | neval0 := Neval.get() 23 | 24 | steps(100) 25 | 26 | wall := since(start).Seconds() 27 | nevl := Neval.get() - neval0 28 | N2 := n*n 29 | fprintln("benchmark.txt", N2, N2*nevl/wall, t/nevl) 30 | 31 | } 32 | -------------------------------------------------------------------------------- /cuda/dotproduct.cu: -------------------------------------------------------------------------------- 1 | 2 | #include "float3.h" 3 | 4 | // dst += prefactor * dot(a,b) 5 | extern "C" __global__ void 6 | dotproduct(float* __restrict__ dst, float prefactor, 7 | float* __restrict__ ax, float* __restrict__ ay, float* __restrict__ az, 8 | float* __restrict__ bx, float* __restrict__ by, float* __restrict__ bz, 9 | int N) { 10 | 11 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 12 | if (i < N) { 13 | float3 A = {ax[i], ay[i], az[i]}; 14 | float3 B = {bx[i], by[i], bz[i]}; 15 | dst[i] += prefactor * dot(A, B); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /cuda/topologicalcharge.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // Set s to the toplogogical charge density s = m · (∂m/∂x ❌ ∂m/∂y) 9 | // See topologicalcharge.cu 10 | func SetTopologicalCharge(s *data.Slice, m *data.Slice, mesh *data.Mesh) { 11 | cellsize := mesh.CellSize() 12 | N := s.Size() 13 | util.Argument(m.Size() == N) 14 | cfg := make3DConf(N) 15 | icxcy := float32(1.0 / (cellsize[X] * cellsize[Y])) 16 | 17 | k_settopologicalcharge_async(s.DevPtr(X), 18 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 19 | icxcy, N[X], N[Y], N[Z], mesh.PBC_code(), cfg) 20 | } 21 | -------------------------------------------------------------------------------- /cuda/regionaddv.cu: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // add region-based vector to dst: 4 | // dst[i] += LUT[region[i]] 5 | extern "C" __global__ void 6 | regionaddv(float* __restrict__ dstx, float* __restrict__ dsty, float* __restrict__ dstz, 7 | float* __restrict__ LUTx, float* __restrict__ LUTy, float* __restrict__ LUTz, 8 | uint8_t* regions, int N) { 9 | 10 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 11 | if (i < N) { 12 | 13 | uint8_t r = regions[i]; 14 | dstx[i] += LUTx[r]; 15 | dsty[i] += LUTy[r]; 16 | dstz[i] += LUTz[r]; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mumax3-STT-SOT 2 | 3 | ## This software currently has many problems and is not recommended for computational simulations and experiments! 4 | 5 | based on mumax3, with sot(spin orbit torque) 6 | 7 | new APIs: 8 | 9 | SOThickness : free layer thickness in sot (m) 10 | 11 | HFLoverHDL : ratio of field-like term to damping-like term 12 | 13 | JSOT : electrical current density in sot (A/m2) 14 | 15 | SOTFixedLayer : FixedLayer in sot 16 | 17 | SPINHALL : spin hall angle 18 | 19 | DisableSOTorque : Disable SOT torque 20 | 21 | 22 | 23 | developed by ZJL in Xi'an Jiaotong University 24 | 25 | 977952515@qq.com 26 | 27 | 2020.9.20 28 | -------------------------------------------------------------------------------- /cuda/cufft/cgoflags.go: -------------------------------------------------------------------------------- 1 | package cufft 2 | 3 | // This file provides CGO flags to find CUDA libraries and headers. 4 | 5 | //#cgo LDFLAGS:-lcufft 6 | // 7 | ////default location: 8 | //#cgo LDFLAGS:-L/usr/local/cuda/lib64 -L/usr/local/cuda/lib 9 | //#cgo CFLAGS: -I/usr/local/cuda/include/ 10 | // 11 | ////Ubuntu 15.04: 12 | //#cgo LDFLAGS:-L/usr/lib/x86_64-linux-gnu/ 13 | //#cgo CFLAGS: -I/usr/include 14 | // 15 | ////arch linux: 16 | //#cgo LDFLAGS:-L/opt/cuda/lib64 -L/opt/cuda/lib 17 | //#cgo CFLAGS: -I/opt/cuda/include 18 | // 19 | ////WINDOWS: 20 | //#cgo windows LDFLAGS:-LC:/cuda/lib/x64 21 | //#cgo windows CFLAGS: -IC:/cuda/include -w 22 | import "C" 23 | -------------------------------------------------------------------------------- /util/util.go: -------------------------------------------------------------------------------- 1 | // package util provides common utilities for all other packages. 2 | package util 3 | 4 | import ( 5 | "net" 6 | "path" 7 | "strings" 8 | ) 9 | 10 | // Remove extension from file name. 11 | func NoExt(file string) string { 12 | ext := path.Ext(file) 13 | return file[:len(file)-len(ext)] 14 | } 15 | 16 | // returns all network interface addresses, without CIDR mask 17 | func InterfaceAddrs() []string { 18 | addrs, _ := net.InterfaceAddrs() 19 | ips := make([]string, 0, len(addrs)) 20 | for _, addr := range addrs { 21 | IpCidr := strings.Split(addr.String(), "/") 22 | ips = append(ips, IpCidr[0]) 23 | } 24 | return ips 25 | } 26 | -------------------------------------------------------------------------------- /cuda/curand/cgoflags.go: -------------------------------------------------------------------------------- 1 | package curand 2 | 3 | // This file provides CGO flags to find CUDA libraries and headers. 4 | 5 | //#cgo LDFLAGS:-lcurand 6 | // 7 | ////default location: 8 | //#cgo LDFLAGS:-L/usr/local/cuda/lib64 -L/usr/local/cuda/lib 9 | //#cgo CFLAGS: -I/usr/local/cuda/include/ 10 | // 11 | ////Ubuntu 15.04: 12 | //#cgo LDFLAGS:-L/usr/lib/x86_64-linux-gnu/ 13 | //#cgo CFLAGS: -I/usr/include 14 | // 15 | ////arch linux: 16 | //#cgo LDFLAGS:-L/opt/cuda/lib64 -L/opt/cuda/lib 17 | //#cgo CFLAGS: -I/opt/cuda/include 18 | // 19 | ////WINDOWS: 20 | //#cgo windows LDFLAGS:-LC:/cuda/lib/x64 21 | //#cgo windows CFLAGS: -IC:/cuda/include -w 22 | import "C" 23 | -------------------------------------------------------------------------------- /engine/effectivefield.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | // Effective field 4 | 5 | import "github.com/mumax/3/data" 6 | 7 | var B_eff = NewVectorField("B_eff", "T", "Effective field", SetEffectiveField) 8 | 9 | // Sets dst to the current effective field, in Tesla. 10 | // This is the sum of all effective field terms, 11 | // like demag, exchange, ... 12 | func SetEffectiveField(dst *data.Slice) { 13 | SetDemagField(dst) // set to B_demag... 14 | AddExchangeField(dst) // ...then add other terms 15 | AddAnisotropyField(dst) 16 | AddMagnetoelasticField(dst) 17 | B_ext.AddTo(dst) 18 | if !relaxing { 19 | B_therm.AddTo(dst) 20 | } 21 | AddCustomField(dst) 22 | } 23 | -------------------------------------------------------------------------------- /cuda/madd5.cu: -------------------------------------------------------------------------------- 1 | 2 | // dst[i] = src1[i] * fac1 + src2[i] * fac2 + src3[i] * fac3 + src4[i] * fac4 + src5[i] * fac5 3 | extern "C" __global__ void 4 | madd5(float* __restrict__ dst, 5 | float* __restrict__ src1, float fac1, 6 | float* __restrict__ src2, float fac2, 7 | float* __restrict__ src3, float fac3, 8 | float* __restrict__ src4, float fac4, 9 | float* __restrict__ src5, float fac5, int N) { 10 | 11 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 12 | 13 | if(i < N) { 14 | dst[i] = (fac1*src1[i]) + (fac2*src2[i]) + (fac3*src3[i]) + (fac4*src4[i]) + (fac5*src5[i]); 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /engine/maxangle.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "github.com/mumax/3/cuda" 5 | "github.com/mumax/3/data" 6 | ) 7 | 8 | var ( 9 | MaxAngle = NewScalarValue("MaxAngle", "rad", "maximum angle between neighboring spins", GetMaxAngle) 10 | SpinAngle = NewScalarField("spinAngle", "rad", "Angle between neighboring spins", SetSpinAngle) 11 | ) 12 | 13 | func SetSpinAngle(dst *data.Slice) { 14 | cuda.SetMaxAngle(dst, M.Buffer(), lex2.Gpu(), regions.Gpu(), M.Mesh()) 15 | } 16 | 17 | func GetMaxAngle() float64 { 18 | s := ValueOf(SpinAngle) 19 | defer cuda.Recycle(s) 20 | return float64(cuda.MaxAbs(s)) // just a max would be fine, but not currently implemented 21 | } 22 | -------------------------------------------------------------------------------- /cuda/cufft/mode.go: -------------------------------------------------------------------------------- 1 | package cufft 2 | 3 | //#include 4 | import "C" 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | // CUFFT compatibility mode 11 | type CompatibilityMode int 12 | 13 | const ( 14 | COMPATIBILITY_FFTW_PADDING CompatibilityMode = C.CUFFT_COMPATIBILITY_FFTW_PADDING 15 | ) 16 | 17 | func (t CompatibilityMode) String() string { 18 | if str, ok := compatibilityModeString[t]; ok { 19 | return str 20 | } 21 | return fmt.Sprint("CUFFT Compatibility mode with unknown number:", int(t)) 22 | } 23 | 24 | var compatibilityModeString map[CompatibilityMode]string = map[CompatibilityMode]string{ 25 | COMPATIBILITY_FFTW_PADDING: "CUFFT_COMPATIBILITY_FFTW_PADDING"} 26 | -------------------------------------------------------------------------------- /cuda/crop.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // Crop stores in dst a rectangle cropped from src at given offset position. 9 | // dst size may be smaller than src. 10 | func Crop(dst, src *data.Slice, offX, offY, offZ int) { 11 | D := dst.Size() 12 | S := src.Size() 13 | util.Argument(dst.NComp() == src.NComp()) 14 | util.Argument(D[X]+offX <= S[X] && D[Y]+offY <= S[Y] && D[Z]+offZ <= S[Z]) 15 | 16 | cfg := make3DConf(D) 17 | 18 | for c := 0; c < dst.NComp(); c++ { 19 | k_crop_async(dst.DevPtr(c), D[X], D[Y], D[Z], 20 | src.DevPtr(c), S[X], S[Y], S[Z], 21 | offX, offY, offZ, cfg) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /cmd/mumax3-convert/tasks.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "runtime" 5 | "sync" 6 | ) 7 | 8 | var tasks chan func() 9 | var taskWG sync.WaitGroup 10 | 11 | const TaskCap = 100 12 | 13 | func Queue(f func()) { 14 | if tasks == nil { 15 | tasks = make(chan func(), TaskCap) 16 | startWorkers() 17 | } 18 | 19 | taskWG.Add(1) 20 | tasks <- func() { defer taskWG.Add(-1); f() } 21 | } 22 | 23 | func Wait() { 24 | taskWG.Wait() 25 | } 26 | 27 | func startWorkers() { 28 | runtime.GOMAXPROCS(runtime.NumCPU()) 29 | nCPU := runtime.GOMAXPROCS(-1) 30 | for i := 0; i < nCPU+1; i++ { 31 | go func() { 32 | for f := range tasks { 33 | f() 34 | } 35 | }() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cuda/alloc.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "log" 5 | "unsafe" 6 | 7 | "github.com/mumax/3/cuda/cu" 8 | "github.com/mumax/3/data" 9 | ) 10 | 11 | // Wrapper for cu.MemAlloc, fatal exit on out of memory. 12 | func MemAlloc(bytes int64) unsafe.Pointer { 13 | defer func() { 14 | err := recover() 15 | if err == cu.ERROR_OUT_OF_MEMORY { 16 | log.Fatal(err) 17 | } 18 | if err != nil { 19 | panic(err) 20 | } 21 | }() 22 | return unsafe.Pointer(uintptr(cu.MemAlloc(bytes))) 23 | } 24 | 25 | // Returns a copy of in, allocated on GPU. 26 | func GPUCopy(in *data.Slice) *data.Slice { 27 | s := NewSlice(in.NComp(), in.Size()) 28 | data.Copy(s, in) 29 | return s 30 | } 31 | -------------------------------------------------------------------------------- /freetype/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Freetype-Go authors for copyright purposes. 2 | # This file is distinct from the CONTRIBUTORS files. 3 | # See the latter for an explanation. 4 | # 5 | # Freetype-Go is derived from Freetype, which is written in C. The latter 6 | # is copyright 1996-2010 David Turner, Robert Wilhelm, and Werner Lemberg. 7 | 8 | # Names should be added to this file as 9 | # Name or Organization 10 | # The email address is not required for organizations. 11 | 12 | # Please keep the list sorted. 13 | 14 | Google Inc. 15 | Jeff R. Allen 16 | Rémy Oudompheng 17 | Roger Peppe 18 | -------------------------------------------------------------------------------- /cmd/mumax3/vet.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | 9 | "github.com/mumax/3/engine" 10 | "github.com/mumax/3/util" 11 | ) 12 | 13 | // check all input files for errors, don't run. 14 | func vet() { 15 | status := 0 16 | for _, f := range flag.Args() { 17 | src, ioerr := ioutil.ReadFile(f) 18 | util.FatalErr(ioerr) 19 | engine.World.EnterScope() // avoid name collisions between separate files 20 | _, err := engine.World.Compile(string(src)) 21 | engine.World.ExitScope() 22 | if err != nil { 23 | fmt.Println(f, ":", err) 24 | status = 1 25 | } else { 26 | fmt.Println(f, ":", "OK") 27 | } 28 | } 29 | os.Exit(status) 30 | } 31 | -------------------------------------------------------------------------------- /cuda/fftplan.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | // INTERNAL 4 | // Base implementation for all FFT plans. 5 | 6 | import ( 7 | "github.com/mumax/3/cuda/cu" 8 | "github.com/mumax/3/cuda/cufft" 9 | ) 10 | 11 | // Base implementation for all FFT plans. 12 | type fftplan struct { 13 | handle cufft.Handle 14 | } 15 | 16 | func prod3(x, y, z int) int { 17 | return x * y * z 18 | } 19 | 20 | // Releases all resources associated with the FFT plan. 21 | func (p *fftplan) Free() { 22 | if p.handle != 0 { 23 | p.handle.Destroy() 24 | p.handle = 0 25 | } 26 | } 27 | 28 | // Associates a CUDA stream with the FFT plan. 29 | func (p *fftplan) setStream(stream cu.Stream) { 30 | p.handle.SetStream(stream) 31 | } 32 | -------------------------------------------------------------------------------- /cuda/resize.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // Select and resize one layer for interactive output 9 | func Resize(dst, src *data.Slice, layer int) { 10 | dstsize := dst.Size() 11 | srcsize := src.Size() 12 | util.Assert(dstsize[Z] == 1) 13 | util.Assert(dst.NComp() == 1 && src.NComp() == 1) 14 | 15 | scalex := srcsize[X] / dstsize[X] 16 | scaley := srcsize[Y] / dstsize[Y] 17 | util.Assert(scalex > 0 && scaley > 0) 18 | 19 | cfg := make3DConf(dstsize) 20 | 21 | k_resize_async(dst.DevPtr(0), dstsize[X], dstsize[Y], dstsize[Z], 22 | src.DevPtr(0), srcsize[X], srcsize[Y], srcsize[Z], layer, scalex, scaley, cfg) 23 | } 24 | -------------------------------------------------------------------------------- /cuda/crossproduct.cu: -------------------------------------------------------------------------------- 1 | #include "float3.h" 2 | 3 | extern "C" __global__ void 4 | crossproduct(float* __restrict__ dstx, float* __restrict__ dsty, float* __restrict__ dstz, 5 | float* __restrict__ ax, float* __restrict__ ay, float* __restrict__ az, 6 | float* __restrict__ bx, float* __restrict__ by, float* __restrict__ bz, 7 | int N) { 8 | 9 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 10 | if (i < N) { 11 | float3 A = {ax[i], ay[i], az[i]}; 12 | float3 B = {bx[i], by[i], bz[i]}; 13 | float3 AxB = cross(A, B); 14 | dstx[i] = AxB.x; 15 | dsty[i] = AxB.y; 16 | dstz[i] = AxB.z; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /data/reshape.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | // Array reshaping. 4 | 5 | import "fmt" 6 | 7 | // Re-interpret a contiguous array as a multi-dimensional array of given size. 8 | // Underlying storage is shared. 9 | func reshape(array []float32, size [3]int) [][][]float32 { 10 | Nx, Ny, Nz := size[0], size[1], size[2] 11 | if Nx*Ny*Nz != len(array) { 12 | panic(fmt.Errorf("reshape: size mismatch: %v*%v*%v != %v", Nx, Ny, Nz, len(array))) 13 | } 14 | sliced := make([][][]float32, Nz) 15 | for i := range sliced { 16 | sliced[i] = make([][]float32, Ny) 17 | } 18 | for i := range sliced { 19 | for j := range sliced[i] { 20 | sliced[i][j] = array[(i*Ny+j)*Nx+0 : (i*Ny+j)*Nx+Nx] 21 | } 22 | } 23 | return sliced 24 | } 25 | -------------------------------------------------------------------------------- /doc/templates/header.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 | mumax3
7 | GPU-accelerated micromagnetism

8 | Home 9 | Download 10 | Examples 11 | API 12 | Forum 13 |
14 |
15 | 16 |
-------------------------------------------------------------------------------- /cuda/buffer_test.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import "testing" 4 | 5 | // In case of memory leak, this will crash 6 | func TestBuffer(t *testing.T) { 7 | m1 := [3]int{2, 1024, 2048} 8 | m2 := [3]int{4, 1024, 2048} 9 | a := Buffer(3, m1) 10 | b := Buffer(3, m2) 11 | c := Buffer(1, m1) 12 | d := Buffer(2, m2) 13 | 14 | Recycle(a) 15 | Recycle(b) 16 | Recycle(c) 17 | Recycle(d) 18 | 19 | for i := 0; i < 10000; i++ { 20 | b := Buffer(3, m2) 21 | Recycle(b) 22 | } 23 | } 24 | 25 | func BenchmarkBuffer(b *testing.B) { 26 | b.StopTimer() 27 | m := [3]int{2, 1024, 2048} 28 | a := Buffer(3, m) 29 | Recycle(a) 30 | b.StartTimer() 31 | for i := 0; i < b.N; i++ { 32 | a := Buffer(3, m) 33 | Recycle(a) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /script/ronly.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import "reflect" 4 | 5 | // read-only value (from script, but mutable from outside) 6 | type reflectROnly struct { 7 | elem reflect.Value 8 | } 9 | 10 | func newReflectROnly(addr interface{}) *reflectROnly { 11 | elem := reflect.ValueOf(addr) 12 | if elem.Kind() == 0 { 13 | panic("variable/constant needs to be passed as pointer to addressable value") 14 | } 15 | return &reflectROnly{elem} 16 | } 17 | 18 | func (l *reflectROnly) Eval() interface{} { return l.elem.Interface() } 19 | func (l *reflectROnly) Type() reflect.Type { return l.elem.Type() } 20 | func (l *reflectROnly) Child() []Expr { return nil } 21 | func (l *reflectROnly) Fix() Expr { return NewConst(l) } 22 | -------------------------------------------------------------------------------- /script/source.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "io/ioutil" 7 | ) 8 | 9 | func (w *World) compileSource(n *ast.CallExpr) Expr { 10 | if len(n.Args) != 1 { 11 | panic(err(n.Pos(), "source() needs 1 string argument, got", len(n.Args))) 12 | } 13 | arg := n.Args[0] 14 | if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { 15 | 16 | code, err1 := ioutil.ReadFile(lit.Value[1 : len(lit.Value)-1]) 17 | if err1 != nil { 18 | panic(err(n.Pos(), err1)) 19 | } 20 | block, err2 := w.Compile(string(code)) 21 | if err1 != nil { 22 | panic(err(n.Pos(), err2)) 23 | } 24 | return block 25 | } else { 26 | panic(err(n.Pos(), "source() needs literal string argument")) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /cuda/madd6.cu: -------------------------------------------------------------------------------- 1 | 2 | // dst[i] = src1[i] * fac1 + src2[i] * fac2 + src3[i] * fac3 + src4[i] * fac4 + src5[i] * fac5 + src6[i] * fac6 3 | extern "C" __global__ void 4 | madd6(float* __restrict__ dst, 5 | float* __restrict__ src1, float fac1, 6 | float* __restrict__ src2, float fac2, 7 | float* __restrict__ src3, float fac3, 8 | float* __restrict__ src4, float fac4, 9 | float* __restrict__ src5, float fac5, 10 | float* __restrict__ src6, float fac6, int N) { 11 | 12 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 13 | 14 | if(i < N) { 15 | dst[i] = (fac1*src1[i]) + (fac2*src2[i]) + (fac3*src3[i]) + (fac4*src4[i]) + (fac5*src5[i]) + (fac6*src6[i]); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /doc/templates/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | mumax3 4 | 5 | 6 | 7 | 17 | -------------------------------------------------------------------------------- /engine/ext_dwtilt.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "math" 5 | ) 6 | 7 | // PMA domain wall tilt assuming straight wall. 8 | var DWTiltPMA = NewScalarValue("ext_dwtilt", "rad", "PMA domain wall tilt", dwTiltPMA) 9 | 10 | func dwTiltPMA() float64 { 11 | m := Download(&M) 12 | mz := m.Vectors()[Z][0] // slice0 13 | 14 | nx := Mesh().Size()[X] 15 | ny := Mesh().Size()[Y] 16 | // find domain wall at these y positions: 17 | y1 := 4 18 | y2 := ny - 5 19 | 20 | // search for x values where mz = 0 (=wall) 21 | x1, x2 := 0, 0 22 | for i := 1; i < nx; i++ { 23 | if mz[y1][i-1]*mz[y1][i] < 0 { 24 | x1 = i 25 | } 26 | if mz[y2][i-1]*mz[y2][i] < 0 { 27 | x2 = i 28 | } 29 | } 30 | angle := math.Atan(float64(x1-x2) / float64(y1-y2)) 31 | return angle 32 | } 33 | -------------------------------------------------------------------------------- /cuda/zhangli.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | ) 6 | 7 | // Add Zhang-Li ST torque (Tesla) to torque. 8 | // see zhangli.cu 9 | func AddZhangLiTorque(torque, m *data.Slice, Msat, J, alpha, xi, pol MSlice, mesh *data.Mesh) { 10 | c := mesh.CellSize() 11 | N := mesh.Size() 12 | cfg := make3DConf(N) 13 | 14 | k_addzhanglitorque2_async( 15 | torque.DevPtr(X), torque.DevPtr(Y), torque.DevPtr(Z), 16 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 17 | Msat.DevPtr(0), Msat.Mul(0), 18 | J.DevPtr(X), J.Mul(X), 19 | J.DevPtr(Y), J.Mul(Y), 20 | J.DevPtr(Z), J.Mul(Z), 21 | alpha.DevPtr(0), alpha.Mul(0), 22 | xi.DevPtr(0), xi.Mul(0), 23 | pol.DevPtr(0), pol.Mul(0), 24 | float32(c[X]), float32(c[Y]), float32(c[Z]), 25 | N[X], N[Y], N[Z], mesh.PBC_code(), cfg) 26 | } 27 | -------------------------------------------------------------------------------- /cuda/shiftbytesy.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include "stencil.h" 3 | 4 | // shift dst by shy cells (positive or negative) along Y-axis. 5 | extern "C" __global__ void 6 | shiftbytesy(uint8_t* __restrict__ dst, uint8_t* __restrict__ src, 7 | int Nx, int Ny, int Nz, int shy, uint8_t clamp) { 8 | 9 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 10 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 11 | int iz = blockIdx.z * blockDim.z + threadIdx.z; 12 | 13 | if(ix < Nx && iy < Ny && iz < Nz) { 14 | int iy2 = iy-shy; 15 | uint8_t newval; 16 | if (iy2 < 0 || iy2 >= Ny) { 17 | newval = clamp; 18 | } else { 19 | newval = src[idx(ix, iy2, iz)]; 20 | } 21 | dst[idx(ix, iy, iz)] = newval; 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /cuda/kernmulrsymm2dz.cu: -------------------------------------------------------------------------------- 1 | // 2D Z (out-of-plane only) micromagnetic kernel multiplication: 2 | // Mz = Kzz * Mz 3 | // Using the same symmetries as kernmulrsymm3d.cu 4 | extern "C" __global__ void 5 | kernmulRSymm2Dz(float* __restrict__ fftMz, float* __restrict__ fftKzz, int Nx, int Ny) { 6 | 7 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 8 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 9 | 10 | if(ix>= Nx || iy>=Ny) { 11 | return; 12 | } 13 | 14 | int I = iy*Nx + ix; 15 | int e = 2 * I; 16 | 17 | float reMz = fftMz[e ]; 18 | float imMz = fftMz[e+1]; 19 | 20 | if (iy > Ny/2) { 21 | iy = Ny-iy; 22 | } 23 | I = iy*Nx + ix; 24 | 25 | float Kzz = fftKzz[I]; 26 | 27 | fftMz[e ] = reMz * Kzz; 28 | fftMz[e+1] = imMz * Kzz; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /cuda/cu/context_test.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestContext(t *testing.T) { 9 | fmt.Println("CtxCreate") 10 | ctx := CtxCreate(CTX_SCHED_AUTO, 0) 11 | fmt.Println("CtxSetCurrent") 12 | CtxSetCurrent(ctx) 13 | fmt.Println("CtxGetApiVersion:", ctx.ApiVersion()) 14 | fmt.Println("CtxGetDevice:", CtxGetDevice()) 15 | (&ctx).Destroy() 16 | } 17 | 18 | func BenchmarkGetContext(b *testing.B) { 19 | b.StopTimer() 20 | ctx := CtxCreate(CTX_SCHED_AUTO, 0) 21 | CtxSetCurrent(ctx) 22 | b.StartTimer() 23 | for i := 0; i < b.N; i++ { 24 | CtxGetCurrent() 25 | } 26 | } 27 | 28 | func BenchmarkSetContext(b *testing.B) { 29 | b.StopTimer() 30 | ctx := CtxCreate(CTX_SCHED_AUTO, 0) 31 | b.StartTimer() 32 | for i := 0; i < b.N; i++ { 33 | ctx.SetCurrent() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /gui/select.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import "fmt" 4 | 5 | type sel struct { 6 | data 7 | } 8 | 9 | func (e *sel) update(id string) []jsCall { 10 | return []jsCall{{F: "setSelect", Args: []interface{}{id, e.value()}}} 11 | } 12 | 13 | func (d *Page) SelectArray(id string, value string, options []string) string { 14 | return d.Select(id, value, options...) 15 | } 16 | 17 | func (d *Page) Select(id string, value string, options ...string) string { 18 | e := &sel{data: data{value}} 19 | d.addElem(id, e) 20 | html := fmt.Sprintf(`` 26 | return html 27 | } 28 | -------------------------------------------------------------------------------- /cuda/madd7.cu: -------------------------------------------------------------------------------- 1 | 2 | // dst[i] = src1[i] * fac1 + src2[i] * fac2 + src3[i] * fac3 + src4[i] * fac4 + src5[i] * fac5 + src6[i] * fac6 + src7[i] * fac7 3 | extern "C" __global__ void 4 | madd7(float* __restrict__ dst, 5 | float* __restrict__ src1, float fac1, 6 | float* __restrict__ src2, float fac2, 7 | float* __restrict__ src3, float fac3, 8 | float* __restrict__ src4, float fac4, 9 | float* __restrict__ src5, float fac5, 10 | float* __restrict__ src6, float fac6, 11 | float* __restrict__ src7, float fac7, int N) { 12 | 13 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 14 | 15 | if(i < N) { 16 | dst[i] = (fac1*src1[i]) + (fac2*src2[i]) + (fac3*src3[i]) + (fac4*src4[i]) + (fac5*src5[i]) + (fac6*src6[i]) + (fac7*src7[i]); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /cuda/llnoprecess.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include "float3.h" 3 | 4 | // Landau-Lifshitz torque without precession 5 | extern "C" __global__ void 6 | llnoprecess(float* __restrict__ tx, float* __restrict__ ty, float* __restrict__ tz, 7 | float* __restrict__ mx, float* __restrict__ my, float* __restrict__ mz, 8 | float* __restrict__ hx, float* __restrict__ hy, float* __restrict__ hz, int N) { 9 | 10 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 11 | if (i < N) { 12 | 13 | float3 m = {mx[i], my[i], mz[i]}; 14 | float3 H = {hx[i], hy[i], hz[i]}; 15 | 16 | float3 mxH = cross(m, H); 17 | float3 torque = -cross(m, mxH); 18 | 19 | tx[i] = torque.x; 20 | ty[i] = torque.y; 21 | tz[i] = torque.z; 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /cuda/temperature2.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include "amul.h" 3 | 4 | // TODO: this could act on x,y,z, so that we need to call it only once. 5 | extern "C" __global__ void 6 | settemperature2(float* __restrict__ B, float* __restrict__ noise, float kB2_VgammaDt, 7 | float* __restrict__ Ms_, float Ms_mul, 8 | float* __restrict__ temp_, float temp_mul, 9 | float* __restrict__ alpha_, float alpha_mul, 10 | int N) { 11 | 12 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 13 | if (i < N) { 14 | float invMs = inv_Msat(Ms_, Ms_mul, i); 15 | float temp = amul(temp_, temp_mul, i); 16 | float alpha = amul(alpha_, alpha_mul, i); 17 | B[i] = noise[i] * sqrtf((kB2_VgammaDt * alpha * temp * invMs )); 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /engine/ext_topologicalcharge.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "math" 5 | 6 | "github.com/mumax/3/cuda" 7 | "github.com/mumax/3/data" 8 | ) 9 | 10 | var ( 11 | Ext_TopologicalCharge = NewScalarValue("ext_topologicalcharge", "", "2D topological charge", GetTopologicalCharge) 12 | Ext_TopologicalChargeDensity = NewScalarField("ext_topologicalchargedensity", "1/m2", 13 | "2D topological charge density m·(∂m/∂x ✕ ∂m/∂y)", SetTopologicalChargeDensity) 14 | ) 15 | 16 | func SetTopologicalChargeDensity(dst *data.Slice) { 17 | cuda.SetTopologicalCharge(dst, M.Buffer(), M.Mesh()) 18 | } 19 | 20 | func GetTopologicalCharge() float64 { 21 | s := ValueOf(Ext_TopologicalChargeDensity) 22 | defer cuda.Recycle(s) 23 | c := Mesh().CellSize() 24 | N := Mesh().Size() 25 | return (0.25 * c[X] * c[Y] / math.Pi / float64(N[Z])) * float64(cuda.Sum(s)) 26 | } 27 | -------------------------------------------------------------------------------- /cuda/SOT.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | ) 6 | 7 | // Add spin orbit torque to torque (Tesla). 8 | // see sot.cu 9 | func AddSOTorque(torque, m *data.Slice, Msat, JSOT, sotfixedP, alpha, spinhall, hfloverhdl, sothickness MSlice, mesh *data.Mesh) { 10 | N := torque.Len() 11 | cfg := make1DConf(N) 12 | 13 | k_addsotorque_async( 14 | torque.DevPtr(X), torque.DevPtr(Y), torque.DevPtr(Z), 15 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 16 | Msat.DevPtr(0), Msat.Mul(0), 17 | JSOT.DevPtr(Z), JSOT.Mul(Z), 18 | sotfixedP.DevPtr(X), sotfixedP.Mul(X), 19 | sotfixedP.DevPtr(Y), sotfixedP.Mul(Y), 20 | sotfixedP.DevPtr(Z), sotfixedP.Mul(Z), 21 | alpha.DevPtr(0), alpha.Mul(0), 22 | spinhall.DevPtr(0), spinhall.Mul(0), 23 | hfloverhdl.DevPtr(0), hfloverhdl.Mul(0), 24 | sothickness.DevPtr(0), sothickness.Mul(0), 25 | N, cfg) 26 | } 27 | -------------------------------------------------------------------------------- /cuda/shiftbytes.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include "stencil.h" 3 | 4 | // shift dst by shx cells (positive or negative) along X-axis. 5 | // new edge value is clampL at left edge or clampR at right edge. 6 | extern "C" __global__ void 7 | shiftbytes(uint8_t* __restrict__ dst, uint8_t* __restrict__ src, 8 | int Nx, int Ny, int Nz, int shx, uint8_t clamp) { 9 | 10 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 11 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 12 | int iz = blockIdx.z * blockDim.z + threadIdx.z; 13 | 14 | if(ix < Nx && iy < Ny && iz < Nz) { 15 | int ix2 = ix-shx; 16 | uint8_t newval; 17 | if (ix2 < 0 || ix2 >= Nx) { 18 | newval = clamp; 19 | } else { 20 | newval = src[idx(ix2, iy, iz)]; 21 | } 22 | dst[idx(ix, iy, iz)] = newval; 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /cuda/amul.h: -------------------------------------------------------------------------------- 1 | #ifndef _AMUL_H_ 2 | #define _AMUL_H_ 3 | 4 | #include "float3.h" 5 | 6 | // Returns mul * arr[i], or mul when arr == NULL; 7 | inline __device__ float amul(float *arr, float mul, int i) { 8 | return (arr == NULL)? (mul): (mul * arr[i]); 9 | } 10 | 11 | // Returns m * a[i], or m when a == NULL; 12 | inline __device__ float3 vmul(float *ax, float *ay, float *az, 13 | float mx, float my, float mz, int i) { 14 | return make_float3(amul(ax, mx, i), 15 | amul(ay, my, i), 16 | amul(az, mz, i)); 17 | } 18 | 19 | // Returns 1/Msat, or 0 when Msat == 0. 20 | inline __device__ float inv_Msat(float *Ms_, float Ms_mul, int i) { 21 | float ms = amul(Ms_, Ms_mul, i); 22 | if (ms == 0.0f) { 23 | return 0.0f; 24 | } else { 25 | return 1.0f / ms; 26 | } 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /cuda/shiftx.cu: -------------------------------------------------------------------------------- 1 | #include "stencil.h" 2 | 3 | // shift dst by shx cells (positive or negative) along X-axis. 4 | // new edge value is clampL at left edge or clampR at right edge. 5 | extern "C" __global__ void 6 | shiftx(float* __restrict__ dst, float* __restrict__ src, 7 | int Nx, int Ny, int Nz, int shx, float clampL, float clampR) { 8 | 9 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 10 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 11 | int iz = blockIdx.z * blockDim.z + threadIdx.z; 12 | 13 | if(ix < Nx && iy < Ny && iz < Nz) { 14 | int ix2 = ix-shx; 15 | float newval; 16 | if (ix2 < 0) { 17 | newval = clampL; 18 | } else if (ix2 >= Nx) { 19 | newval = clampR; 20 | } else { 21 | newval = src[idx(ix2, iy, iz)]; 22 | } 23 | dst[idx(ix, iy, iz)] = newval; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /cuda/shifty.cu: -------------------------------------------------------------------------------- 1 | #include "stencil.h" 2 | 3 | // shift dst by shy cells (positive or negative) along Y-axis. 4 | // new edge value is clampL at left edge or clampR at right edge. 5 | extern "C" __global__ void 6 | shifty(float* __restrict__ dst, float* __restrict__ src, 7 | int Nx, int Ny, int Nz, int shy, float clampL, float clampR) { 8 | 9 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 10 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 11 | int iz = blockIdx.z * blockDim.z + threadIdx.z; 12 | 13 | if(ix < Nx && iy < Ny && iz < Nz) { 14 | int iy2 = iy-shy; 15 | float newval; 16 | if (iy2 < 0) { 17 | newval = clampL; 18 | } else if (iy2 >= Ny) { 19 | newval = clampR; 20 | } else { 21 | newval = src[idx(ix, iy2, iz)]; 22 | } 23 | dst[idx(ix, iy, iz)] = newval; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /cuda/shiftz.cu: -------------------------------------------------------------------------------- 1 | #include "stencil.h" 2 | 3 | // shift dst by shy cells (positive or negative) along Z-axis. 4 | // new edge value is clampL at left edge or clampR at right edge. 5 | extern "C" __global__ void 6 | shiftz(float* __restrict__ dst, float* __restrict__ src, 7 | int Nx, int Ny, int Nz, int shz, float clampL, float clampR) { 8 | 9 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 10 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 11 | int iz = blockIdx.z * blockDim.z + threadIdx.z; 12 | 13 | if(ix < Nx && iy < Ny && iz < Nz) { 14 | int iz2 = iz-shz; 15 | float newval; 16 | if (iz2 < 0) { 17 | newval = clampL; 18 | } else if (iz2 >= Nz) { 19 | newval = clampR; 20 | } else { 21 | newval = src[idx(ix, iy, iz2)]; 22 | } 23 | dst[idx(ix, iy, iz)] = newval; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /script/exec.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | // Exec compiles and executes the source statements. 4 | func (w *World) Exec(src string) error { 5 | code, err := w.Compile(src) 6 | if err != nil { 7 | return err 8 | } 9 | code.Eval() 10 | return nil 11 | } 12 | 13 | // Exec with panic on error. 14 | func (w *World) MustExec(src string) { 15 | code := w.MustCompile(src) 16 | code.Eval() 17 | } 18 | 19 | // Eval with panic on error. 20 | func (w *World) MustEval(src string) interface{} { 21 | Expr := w.MustCompileExpr(src) 22 | return Expr.Eval() 23 | } 24 | 25 | // Eval compiles and evaluates src, which must be an expression, and returns the result(s). E.g.: 26 | // world.Eval("1+1") // returns 2, nil 27 | func (w *World) Eval(src string) (ret interface{}, err error) { 28 | Expr, err := w.CompileExpr(src) 29 | if err != nil { 30 | return nil, err 31 | } 32 | return Expr.Eval(), nil 33 | } 34 | -------------------------------------------------------------------------------- /script/if.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "go/ast" 5 | ) 6 | 7 | // if statement 8 | type ifStmt struct { 9 | cond, body, else_ Expr 10 | void 11 | } 12 | 13 | func (b *ifStmt) Eval() interface{} { 14 | if b.cond.Eval().(bool) { 15 | b.body.Eval() 16 | } else { 17 | if b.else_ != nil { 18 | b.else_.Eval() 19 | } 20 | } 21 | return nil // void 22 | } 23 | 24 | func (w *World) compileIfStmt(n *ast.IfStmt) *ifStmt { 25 | w.EnterScope() 26 | defer w.ExitScope() 27 | 28 | stmt := &ifStmt{ 29 | cond: typeConv(n.Cond.Pos(), w.compileExpr(n.Cond), bool_t), 30 | body: w.compileBlockStmt_noScope(n.Body)} 31 | if n.Else != nil { 32 | stmt.else_ = w.compileStmt(n.Else) 33 | } 34 | 35 | return stmt 36 | } 37 | 38 | func (e *ifStmt) Child() []Expr { 39 | child := []Expr{e.cond, e.body, e.else_} 40 | if e.else_ == nil { 41 | child = child[:2] 42 | } 43 | return child 44 | } 45 | -------------------------------------------------------------------------------- /script/index.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "go/ast" 5 | "reflect" 6 | ) 7 | 8 | func (w *World) compileIndexExpr(n *ast.IndexExpr) Expr { 9 | x := w.compileExpr(n.X) 10 | kind := x.Type().Kind() 11 | if !(kind == reflect.Array || kind == reflect.Slice) { 12 | panic(err(n.Pos(), "can not index", x.Type())) 13 | } 14 | i := typeConv(n.Index.Pos(), w.compileExpr(n.Index), int_t) 15 | return &index{x, i} 16 | } 17 | 18 | type index struct { 19 | x, index Expr 20 | } 21 | 22 | func (e *index) Type() reflect.Type { 23 | return e.x.Type().Elem() 24 | } 25 | func (e *index) Eval() interface{} { 26 | x := reflect.ValueOf(e.x.Eval()) 27 | i := e.index.Eval().(int) 28 | return x.Index(i).Interface() 29 | } 30 | 31 | func (e *index) Child() []Expr { 32 | return []Expr{e.x, e.index} 33 | } 34 | 35 | func (e *index) Fix() Expr { 36 | return &index{x: e.x.Fix(), index: e.index.Fix()} 37 | } 38 | -------------------------------------------------------------------------------- /cuda/dmibulk.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "unsafe" 5 | 6 | "github.com/mumax/3/data" 7 | "github.com/mumax/3/util" 8 | ) 9 | 10 | // Add effective field due to bulk Dzyaloshinskii-Moriya interaction to Beff. 11 | // See dmibulk.cu 12 | func AddDMIBulk(Beff *data.Slice, m *data.Slice, Aex_red, D_red SymmLUT, Msat MSlice, regions *Bytes, mesh *data.Mesh, OpenBC bool) { 13 | cellsize := mesh.CellSize() 14 | N := Beff.Size() 15 | util.Argument(m.Size() == N) 16 | cfg := make3DConf(N) 17 | var openBC byte 18 | if OpenBC { 19 | openBC = 1 20 | } 21 | 22 | k_adddmibulk_async(Beff.DevPtr(X), Beff.DevPtr(Y), Beff.DevPtr(Z), 23 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 24 | Msat.DevPtr(0), Msat.Mul(0), 25 | unsafe.Pointer(Aex_red), unsafe.Pointer(D_red), regions.Ptr, 26 | float32(cellsize[X]), float32(cellsize[Y]), float32(cellsize[Z]), N[X], N[Y], N[Z], mesh.PBC_code(), openBC, cfg) 27 | } 28 | -------------------------------------------------------------------------------- /cuda/minimize.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include "float3.h" 3 | 4 | // Steepest descent energy minimizer 5 | extern "C" __global__ void 6 | minimize(float* __restrict__ mx, float* __restrict__ my, float* __restrict__ mz, 7 | float* __restrict__ m0x, float* __restrict__ m0y, float* __restrict__ m0z, 8 | float* __restrict__ tx, float* __restrict__ ty, float* __restrict__ tz, 9 | float dt, int N) { 10 | 11 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 12 | if (i < N) { 13 | 14 | float3 m0 = {m0x[i], m0y[i], m0z[i]}; 15 | float3 t = {tx[i], ty[i], tz[i]}; 16 | 17 | float t2 = dt*dt*dot(t, t); 18 | float3 result = (4 - t2) * m0 + 4 * dt * t; 19 | float divisor = 4 + t2; 20 | 21 | mx[i] = result.x / divisor; 22 | my[i] = result.y / divisor; 23 | mz[i] = result.z / divisor; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /cuda/resize.cu: -------------------------------------------------------------------------------- 1 | 2 | // Select and resize one layer for interactive output 3 | extern "C" __global__ void 4 | resize(float* __restrict__ dst, int Dx, int Dy, int Dz, 5 | float* __restrict__ src, int Sx, int Sy, int Sz, 6 | int layer, int scalex, int scaley) { 7 | 8 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 9 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 10 | 11 | if (ix 5 | 6 | // Copy src (size S, smaller) into dst (size D, larger), 7 | // and multiply by Bsat * vol 8 | extern "C" __global__ void 9 | copypadmul2(float* __restrict__ dst, int Dx, int Dy, int Dz, 10 | float* __restrict__ src, int Sx, int Sy, int Sz, 11 | float* __restrict__ Ms_, float Ms_mul, 12 | float* __restrict__ vol) { 13 | 14 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 15 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 16 | int iz = blockIdx.z * blockDim.z + threadIdx.z; 17 | 18 | if (ix 1 { 18 | panic(fmt.Errorf("multiple return values not allowed: %v", val.Type())) 19 | } 20 | return &function{val} 21 | } 22 | 23 | // type of the function itself (when not called) 24 | func (f *function) Type() reflect.Type { return f.Value.Type() } 25 | func (f *function) NumIn() int { return f.Type().NumIn() } 26 | func (f *function) In(i int) reflect.Type { return f.Type().In(i) } 27 | func (f *function) Eval() interface{} { return f.Value.Interface() } 28 | func (f *function) Child() []Expr { return nil } 29 | func (f *function) Fix() Expr { return f } 30 | -------------------------------------------------------------------------------- /cuda/fatbin.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/mumax/3/cuda/cu" 7 | ) 8 | 9 | // load PTX code for function name, find highest SM that matches our card. 10 | func fatbinLoad(sm map[int]string, fn string) cu.Function { 11 | cc := determineCC() 12 | return cu.ModuleLoadData(sm[cc]).GetFunction(fn) 13 | } 14 | 15 | var UseCC = 0 16 | 17 | func determineCC() int { 18 | if UseCC != 0 { 19 | return UseCC 20 | } 21 | 22 | for k, _ := range madd2_map { 23 | if k > UseCC && ccIsOK(k) { 24 | UseCC = k 25 | } 26 | } 27 | if UseCC == 0 { 28 | log.Fatalln("\nNo binary for GPU. Your nvidia driver may be out-of-date\n") 29 | } 30 | return UseCC 31 | } 32 | 33 | // check wheter compute capability cc works 34 | func ccIsOK(cc int) (ok bool) { 35 | defer func() { 36 | if err := recover(); err == cu.ERROR_NO_BINARY_FOR_GPU { 37 | ok = false 38 | } 39 | }() 40 | cu.ModuleLoadData(madd2_map[cc]).GetFunction("madd2") 41 | return true 42 | } 43 | -------------------------------------------------------------------------------- /cuda/lltorque.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | ) 6 | 7 | // Landau-Lifshitz torque divided by gamma0: 8 | // - 1/(1+α²) [ m x B + α m x (m x B) ] 9 | // torque in Tesla 10 | // m normalized 11 | // B in Tesla 12 | // see lltorque.cu 13 | func LLTorque(torque, m, B *data.Slice, alpha MSlice) { 14 | N := torque.Len() 15 | cfg := make1DConf(N) 16 | 17 | k_lltorque2_async(torque.DevPtr(X), torque.DevPtr(Y), torque.DevPtr(Z), 18 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 19 | B.DevPtr(X), B.DevPtr(Y), B.DevPtr(Z), 20 | alpha.DevPtr(0), alpha.Mul(0), N, cfg) 21 | } 22 | 23 | // Landau-Lifshitz torque with precession disabled. 24 | // Used by engine.Relax(). 25 | func LLNoPrecess(torque, m, B *data.Slice) { 26 | N := torque.Len() 27 | cfg := make1DConf(N) 28 | 29 | k_llnoprecess_async(torque.DevPtr(X), torque.DevPtr(Y), torque.DevPtr(Z), 30 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 31 | B.DevPtr(X), B.DevPtr(Y), B.DevPtr(Z), N, cfg) 32 | } 33 | -------------------------------------------------------------------------------- /engine/euler.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "github.com/mumax/3/cuda" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | type Euler struct{} 9 | 10 | // Euler method, can be used as solver.Step. 11 | func (_ *Euler) Step() { 12 | y := M.Buffer() 13 | dy0 := cuda.Buffer(VECTOR, y.Size()) 14 | defer cuda.Recycle(dy0) 15 | 16 | torqueFn(dy0) 17 | setMaxTorque(dy0) 18 | 19 | // Adaptive time stepping: treat MaxErr as the maximum magnetization delta 20 | // (proportional to the error, but an overestimation for sure) 21 | var dt float32 22 | if FixDt != 0 { 23 | Dt_si = FixDt 24 | dt = float32(Dt_si * GammaLL) 25 | } else { 26 | dt = float32(MaxErr / LastTorque) 27 | Dt_si = float64(dt) / GammaLL 28 | } 29 | util.AssertMsg(dt > 0, "Euler solver requires fixed time step > 0") 30 | setLastErr(float64(dt) * LastTorque) 31 | 32 | cuda.Madd2(y, y, dy0, 1, dt) // y = y + dt * dy 33 | M.normalize() 34 | Time += Dt_si 35 | NSteps++ 36 | } 37 | 38 | func (_ *Euler) Free() {} 39 | -------------------------------------------------------------------------------- /cuda/cufft/fft_test.go: -------------------------------------------------------------------------------- 1 | package cufft 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "unsafe" 7 | 8 | "github.com/mumax/3/cuda/cu" 9 | ) 10 | 11 | func TestExampleFFT1D(t *testing.T) { 12 | N := 8 13 | 14 | hostIn := make([]float32, N) 15 | hostIn[0] = 1 16 | 17 | devIn := cu.MemAlloc(int64(len(hostIn)) * cu.SIZEOF_FLOAT32) 18 | defer cu.MemFree(devIn) 19 | cu.MemcpyHtoD(devIn, unsafe.Pointer(&hostIn[0]), devIn.Bytes()) 20 | 21 | hostOut := make([]complex64, N/2+1) 22 | devOut := cu.MemAlloc(int64(len(hostOut)) * cu.SIZEOF_COMPLEX64) 23 | defer cu.MemFree(devOut) 24 | 25 | plan := Plan1d(N, R2C, 1) 26 | defer plan.Destroy() 27 | plan.ExecR2C(devIn, devOut) 28 | 29 | cu.MemcpyDtoH(unsafe.Pointer(&hostOut[0]), devOut, devOut.Bytes()) 30 | 31 | fmt.Println("hostIn:", hostIn) 32 | fmt.Println("hostOut:", hostOut) 33 | 34 | for i := 0; i < N; i++ { 35 | if hostOut[0] != 1+0i { 36 | t.Errorf("hostOut[%d]: got %f, want %f", i, hostOut[0], 1+0i) 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /cuda/dmi.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "unsafe" 5 | 6 | "github.com/mumax/3/data" 7 | "github.com/mumax/3/util" 8 | ) 9 | 10 | // Add effective field of Dzyaloshinskii-Moriya interaction to Beff (Tesla). 11 | // According to Bagdanov and Röβler, PRL 87, 3, 2001. eq.8 (out-of-plane symmetry breaking). 12 | // See dmi.cu 13 | func AddDMI(Beff *data.Slice, m *data.Slice, Aex_red, Dex_red SymmLUT, Msat MSlice, regions *Bytes, mesh *data.Mesh, OpenBC bool) { 14 | cellsize := mesh.CellSize() 15 | N := Beff.Size() 16 | util.Argument(m.Size() == N) 17 | cfg := make3DConf(N) 18 | var openBC byte 19 | if OpenBC { 20 | openBC = 1 21 | } 22 | 23 | k_adddmi_async(Beff.DevPtr(X), Beff.DevPtr(Y), Beff.DevPtr(Z), 24 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 25 | Msat.DevPtr(0), Msat.Mul(0), 26 | unsafe.Pointer(Aex_red), unsafe.Pointer(Dex_red), regions.Ptr, 27 | float32(cellsize[X]), float32(cellsize[Y]), float32(cellsize[Z]), N[X], N[Y], N[Z], mesh.PBC_code(), openBC, cfg) 28 | } 29 | -------------------------------------------------------------------------------- /freetype/README: -------------------------------------------------------------------------------- 1 | This is a port of the Freetype font rasterizer (www.freetype.org) to the Go 2 | programming language (golang.org). 3 | 4 | To download and install from source: 5 | $ go get code.google.com/p/freetype-go/freetype 6 | 7 | It is an incomplete port: 8 | * It only supports TrueType fonts, and not Type 1 fonts nor bitmap fonts. 9 | * It only supports the Unicode encoding. 10 | 11 | There are also some implementation differences: 12 | * It uses a 24.8 fixed point co-ordinate system everywhere internally, 13 | as opposed to the original Freetype's mix of 26.6 (or 10.6 for 16-bit 14 | systems) in some places, and 24.8 in the "smooth" rasterizer. 15 | 16 | Freetype-Go is derived from Freetype, which is written in C. Freetype is 17 | copyright 1996-2010 David Turner, Robert Wilhelm, and Werner Lemberg. 18 | Freetype-Go is copyright The Freetype-Go Authors, who are listed in the 19 | AUTHORS file. 20 | 21 | The Freetype-Go homepage is http://code.google.com/p/freetype-go/ 22 | 23 | -------------------------------------------------------------------------------- /cuda/slonczewski.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | ) 6 | 7 | // Add Slonczewski ST torque to torque (Tesla). 8 | // see slonczewski.cu 9 | func AddSlonczewskiTorque2(torque, m *data.Slice, Msat, J, fixedP, alpha, pol, λ, ε_prime MSlice, thickness MSlice, flp float64, mesh *data.Mesh) { 10 | N := torque.Len() 11 | cfg := make1DConf(N) 12 | meshThickness := mesh.WorldSize()[Z] 13 | 14 | k_addslonczewskitorque2_async( 15 | torque.DevPtr(X), torque.DevPtr(Y), torque.DevPtr(Z), 16 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 17 | Msat.DevPtr(0), Msat.Mul(0), 18 | J.DevPtr(Z), J.Mul(Z), 19 | fixedP.DevPtr(X), fixedP.Mul(X), 20 | fixedP.DevPtr(Y), fixedP.Mul(Y), 21 | fixedP.DevPtr(Z), fixedP.Mul(Z), 22 | alpha.DevPtr(0), alpha.Mul(0), 23 | pol.DevPtr(0), pol.Mul(0), 24 | λ.DevPtr(0), λ.Mul(0), 25 | ε_prime.DevPtr(0), ε_prime.Mul(0), 26 | thickness.DevPtr(0), thickness.Mul(0), 27 | float32(meshThickness), 28 | float32(flp), 29 | N, cfg) 30 | } 31 | -------------------------------------------------------------------------------- /engine/ext_topologicalchargelattice.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "math" 5 | 6 | "github.com/mumax/3/cuda" 7 | "github.com/mumax/3/data" 8 | ) 9 | 10 | var ( 11 | Ext_TopologicalChargeLattice = NewScalarValue("ext_topologicalchargelattice", "", "2D topological charge according to Berg and Lüscher", GetTopologicalChargeLattice) 12 | Ext_TopologicalChargeDensityLattice = NewScalarField("ext_topologicalchargedensitylattice", "1/m2", 13 | "2D topological charge density according to Berg and Lüscher", SetTopologicalChargeDensityLattice) 14 | ) 15 | 16 | func SetTopologicalChargeDensityLattice(dst *data.Slice) { 17 | Refer("Berg1981") 18 | cuda.SetTopologicalChargeLattice(dst, M.Buffer(), M.Mesh()) 19 | } 20 | 21 | func GetTopologicalChargeLattice() float64 { 22 | s := ValueOf(Ext_TopologicalChargeDensityLattice) 23 | defer cuda.Recycle(s) 24 | c := Mesh().CellSize() 25 | N := Mesh().Size() 26 | return (0.25 * c[X] * c[Y] / math.Pi / float64(N[Z])) * float64(cuda.Sum(s)) 27 | } 28 | -------------------------------------------------------------------------------- /cuda/cufft/type.go: -------------------------------------------------------------------------------- 1 | package cufft 2 | 3 | //#include 4 | import "C" 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | // FFT type 11 | type Type int 12 | 13 | const ( 14 | R2C Type = C.CUFFT_R2C // Real to Complex (interleaved) 15 | C2R Type = C.CUFFT_C2R // Complex (interleaved) to Real 16 | C2C Type = C.CUFFT_C2C // Complex to Complex, interleaved 17 | D2Z Type = C.CUFFT_D2Z // Double to Double-Complex 18 | Z2D Type = C.CUFFT_Z2D // Double-Complex to Double 19 | Z2Z Type = C.CUFFT_Z2Z // Double-Complex to Double-Complex 20 | ) 21 | 22 | const ( 23 | FORWARD = -1 // Forward FFT 24 | INVERSE = 1 // Inverse FFT 25 | ) 26 | 27 | func (t Type) String() string { 28 | if str, ok := typeString[t]; ok { 29 | return str 30 | } 31 | return fmt.Sprint("CUFFT Type with unknown number:", int(t)) 32 | } 33 | 34 | var typeString map[Type]string = map[Type]string{ 35 | R2C: "CUFFT_R2C", 36 | C2R: "CUFFT_C2R", 37 | C2C: "CUFFT_C2C", 38 | D2Z: "CUFFT_D2Z", 39 | Z2D: "CUFFT_Z2D", 40 | Z2Z: "CUFFT_Z2Z"} 41 | -------------------------------------------------------------------------------- /script/expr.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "go/ast" 5 | "reflect" 6 | ) 7 | 8 | // an expression can be evaluated 9 | type Expr interface { 10 | Eval() interface{} // evaluate and return result (nil for void) 11 | Type() reflect.Type // return type, nil for void 12 | Child() []Expr 13 | Fix() Expr // replace all variables by their current value, except for the time "t". 14 | } 15 | 16 | // compiles an expression 17 | func (w *World) compileExpr(e ast.Expr) Expr { 18 | switch e := e.(type) { 19 | default: 20 | panic(err(e.Pos(), "not allowed:", typ(e))) 21 | case *ast.Ident: 22 | return w.resolve(e.Pos(), e.Name) 23 | case *ast.BasicLit: 24 | return w.compileBasicLit(e) 25 | case *ast.BinaryExpr: 26 | return w.compileBinaryExpr(e) 27 | case *ast.UnaryExpr: 28 | return w.compileUnaryExpr(e) 29 | case *ast.CallExpr: 30 | return w.compileCallExpr(e) 31 | case *ast.ParenExpr: 32 | return w.compileExpr(e.X) 33 | case *ast.IndexExpr: 34 | return w.compileIndexExpr(e) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /engine/od.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | // Management of output directory. 4 | 5 | import ( 6 | "github.com/mumax/3/httpfs" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | outputdir string // Output directory 12 | InputFile string 13 | ) 14 | 15 | func OD() string { 16 | if outputdir == "" { 17 | panic("output not yet initialized") 18 | } 19 | return outputdir 20 | } 21 | 22 | // SetOD sets the output directory where auto-saved files will be stored. 23 | // The -o flag can also be used for this purpose. 24 | func InitIO(inputfile, od string, force bool) { 25 | if outputdir != "" { 26 | panic("output directory already set") 27 | } 28 | 29 | InputFile = inputfile 30 | if !strings.HasSuffix(od, "/") { 31 | od += "/" 32 | } 33 | outputdir = od 34 | if strings.HasPrefix(outputdir, "http://") { 35 | httpfs.SetWD(outputdir + "/../") 36 | } 37 | LogOut("output directory:", outputdir) 38 | 39 | if force { 40 | httpfs.Remove(od) 41 | } 42 | 43 | _ = httpfs.Mkdir(od) 44 | 45 | initLog() 46 | initBib() 47 | } 48 | -------------------------------------------------------------------------------- /cuda/lltorque2.cu: -------------------------------------------------------------------------------- 1 | #include "amul.h" 2 | #include "float3.h" 3 | #include 4 | 5 | // Landau-Lifshitz torque. 6 | extern "C" __global__ void 7 | lltorque2(float* __restrict__ tx, float* __restrict__ ty, float* __restrict__ tz, 8 | float* __restrict__ mx, float* __restrict__ my, float* __restrict__ mz, 9 | float* __restrict__ hx, float* __restrict__ hy, float* __restrict__ hz, 10 | float* __restrict__ alpha_, float alpha_mul, int N) { 11 | 12 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 13 | if (i < N) { 14 | 15 | float3 m = {mx[i], my[i], mz[i]}; 16 | float3 H = {hx[i], hy[i], hz[i]}; 17 | float alpha = amul(alpha_, alpha_mul, i); 18 | 19 | float3 mxH = cross(m, H); 20 | float gilb = -1.0f / (1.0f + alpha * alpha); 21 | float3 torque = gilb * (mxH + alpha * cross(m, mxH)); 22 | 23 | tx[i] = torque.x; 24 | ty[i] = torque.y; 25 | tz[i] = torque.z; 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /engine/number.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | // TODO: wrap around outputValue 8 | 9 | // inputValue is like outputValue, but settable 10 | type inputValue struct { 11 | v float64 12 | onSet func() 13 | name, unit string 14 | } 15 | 16 | func numParam(v float64, name, unit string, onSet func()) inputValue { 17 | return inputValue{v: v, onSet: onSet, name: name, unit: unit} 18 | } 19 | 20 | func (p *inputValue) NComp() int { return 1 } 21 | func (p *inputValue) Name() string { return p.name } 22 | func (p *inputValue) Unit() string { return p.unit } 23 | func (p *inputValue) getRegion(int) []float64 { return []float64{float64(p.v)} } 24 | func (p *inputValue) Type() reflect.Type { return reflect.TypeOf(float64(0)) } 25 | func (p *inputValue) IsUniform() bool { return true } 26 | func (p *inputValue) Eval() interface{} { return p.v } 27 | 28 | func (p *inputValue) SetValue(v interface{}) { 29 | p.v = v.(float64) 30 | p.onSet() 31 | } 32 | -------------------------------------------------------------------------------- /script/unaryexpr.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "reflect" 7 | ) 8 | 9 | func (w *World) compileUnaryExpr(n *ast.UnaryExpr) Expr { 10 | x := w.compileExpr(n.X) 11 | switch n.Op { 12 | default: 13 | panic(err(n.Pos(), "not allowed:", n.Op)) 14 | case token.SUB: 15 | return &minus{typeConv(n.X.Pos(), x, float64_t)} 16 | case token.NOT: 17 | return ¬{typeConv(n.X.Pos(), x, bool_t)} 18 | } 19 | } 20 | 21 | type minus struct{ x Expr } 22 | 23 | func (m *minus) Type() reflect.Type { return float64_t } 24 | func (m *minus) Eval() interface{} { return -m.x.Eval().(float64) } 25 | func (m *minus) Child() []Expr { return []Expr{m.x} } 26 | func (m *minus) Fix() Expr { return &minus{m.x.Fix()} } 27 | 28 | type not struct{ x Expr } 29 | 30 | func (m *not) Type() reflect.Type { return bool_t } 31 | func (m *not) Eval() interface{} { return !m.x.Eval().(bool) } 32 | func (m *not) Child() []Expr { return []Expr{m.x} } 33 | func (m *not) Fix() Expr { return ¬{m.x.Fix()} } 34 | -------------------------------------------------------------------------------- /cuda/stencil.h: -------------------------------------------------------------------------------- 1 | #ifndef _STENCIL_H_ 2 | #define _STENCIL_H_ 3 | 4 | // 3D array indexing 5 | #define index(ix,iy,iz,Nx,Ny,Nz) ( ( (iz)*(Ny) + (iy) ) * (Nx) + (ix) ) 6 | #define idx(ix,iy,iz) ( index((ix),(iy),(iz),(Nx),(Ny),(Nz)) ) 7 | 8 | 9 | // modulo used for PBC wrap around 10 | #define MOD(n, M) ( (( (n) % (M) ) + (M) ) % (M) ) 11 | 12 | // have PBC in x, y or z? 13 | #define PBCx (PBC & 1) 14 | #define PBCy (PBC & 2) 15 | #define PBCz (PBC & 4) 16 | 17 | // clamp or wrap index at boundary, depending on PBC 18 | // hclamp*: clamps on upper side (index+1) 19 | // lclamp*: clamps on lower side (index-1) 20 | // *clampx: clamps along x 21 | // ... 22 | #define hclampx(ix) (PBCx? MOD(ix, Nx) : min((ix), Nx-1)) 23 | #define lclampx(ix) (PBCx? MOD(ix, Nx) : max((ix), 0)) 24 | 25 | #define hclampy(iy) (PBCy? MOD(iy, Ny) : min((iy), Ny-1)) 26 | #define lclampy(iy) (PBCy? MOD(iy, Ny) : max((iy), 0)) 27 | 28 | #define hclampz(iz) (PBCz? MOD(iz, Nz) : min((iz), Nz-1)) 29 | #define lclampz(iz) (PBCz? MOD(iz, Nz) : max((iz), 0)) 30 | 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /cmd/mumax3-server/utitl.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/url" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | // BaseDir returns the first path element, without slashes and ignoring http:// . E.g.: 11 | // /home/user/file -> home 12 | // user/file -> user 13 | // http://home/user/file -> home 14 | func BaseDir(dir string) string { 15 | if strings.HasPrefix(dir, "http://") { 16 | return BaseDir(dir[len("http://"):]) 17 | } 18 | firstSlash := strings.Index(dir, "/") 19 | switch { 20 | case firstSlash < 0: 21 | return dir 22 | case firstSlash == 0: 23 | return BaseDir(dir[1:]) 24 | default: 25 | return dir[:firstSlash] 26 | } 27 | } 28 | 29 | func Fatal(err error) { 30 | if err != nil { 31 | log.Fatal(err) 32 | } 33 | } 34 | 35 | // rounded up to 1s precission 36 | func Since(a, b time.Time) time.Duration { 37 | d := a.Sub(b) 38 | return (d/1e9)*1e9 + 1e9 39 | } 40 | 41 | // Parse URL, panic on error 42 | func MustParseURL(URL string) *url.URL { 43 | u, err := url.Parse(URL) 44 | if err != nil { 45 | panic(err) 46 | } 47 | return u 48 | } 49 | -------------------------------------------------------------------------------- /cuda/mslice.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "unsafe" 6 | ) 7 | 8 | // Slice + scalar multiplier. 9 | type MSlice struct { 10 | arr *data.Slice 11 | mul []float64 12 | } 13 | 14 | func ToMSlice(s *data.Slice) MSlice { 15 | return MSlice{ 16 | arr: s, 17 | mul: ones(s.NComp()), 18 | } 19 | } 20 | 21 | func MakeMSlice(arr *data.Slice, mul []float64) MSlice { 22 | return MSlice{arr, mul} 23 | } 24 | 25 | func (m MSlice) Size() [3]int { 26 | return m.arr.Size() 27 | } 28 | 29 | func (m MSlice) Len() int { 30 | return m.arr.Len() 31 | } 32 | 33 | func (m MSlice) DevPtr(c int) unsafe.Pointer { 34 | return m.arr.DevPtr(c) 35 | } 36 | 37 | func (m MSlice) Mul(c int) float32 { 38 | return float32(m.mul[c]) 39 | } 40 | 41 | func (m MSlice) SetMul(c int, mul float32) { 42 | m.mul[c] = float64(mul) 43 | } 44 | 45 | func (m MSlice) Recycle() { 46 | if m.arr != nil { 47 | Recycle(m.arr) 48 | m.arr = nil 49 | } 50 | } 51 | 52 | var _ones = [4]float64{1, 1, 1, 1} 53 | 54 | func ones(n int) []float64 { 55 | return _ones[:n] 56 | 57 | } 58 | -------------------------------------------------------------------------------- /cuda/cu/module_test.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | import ( 4 | "testing" 5 | "unsafe" 6 | //"fmt" 7 | ) 8 | 9 | func TestModule(test *testing.T) { 10 | mod := ModuleLoad("/testdata/testmodule.ptx") 11 | f := mod.GetFunction("testMemset") 12 | 13 | N := 1000 14 | N4 := 4 * int64(N) 15 | a := make([]float32, N) 16 | A := MemAlloc(N4) 17 | defer A.Free() 18 | aptr := unsafe.Pointer(&a[0]) 19 | MemcpyHtoD(A, aptr, N4) 20 | 21 | var value float32 22 | value = 42 23 | 24 | var n int 25 | n = N / 2 26 | 27 | block := 128 28 | grid := DivUp(N, block) 29 | shmem := 0 30 | args := []unsafe.Pointer{unsafe.Pointer(&A), unsafe.Pointer(&value), unsafe.Pointer(&n)} 31 | LaunchKernel(f, grid, 1, 1, block, 1, 1, shmem, 0, args) 32 | 33 | MemcpyDtoH(aptr, A, N4) 34 | for i := 0; i < N/2; i++ { 35 | if a[i] != 42 { 36 | test.Fail() 37 | } 38 | } 39 | for i := N / 2; i < N; i++ { 40 | if a[i] != 0 { 41 | test.Fail() 42 | } 43 | } 44 | //fmt.Println(a) 45 | } 46 | 47 | // Integer division rounded up. 48 | func DivUp(x, y int) int { 49 | return ((x - 1) / y) + 1 50 | } 51 | -------------------------------------------------------------------------------- /cmd/mumax3-convert/gnuplot.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Output for gnuplot's "splot" 4 | 5 | import ( 6 | "bufio" 7 | "fmt" 8 | "io" 9 | 10 | "github.com/mumax/3/data" 11 | ) 12 | 13 | const DELIM = "\t" 14 | 15 | func dumpGnuplot(f *data.Slice, m data.Meta, out io.Writer) { 16 | buf := bufio.NewWriter(out) 17 | defer buf.Flush() 18 | 19 | data := f.Tensors() 20 | cellsize := m.CellSize 21 | // If no cell size is set, use generic cell index. 22 | if cellsize == [3]float64{0, 0, 0} { 23 | cellsize = [3]float64{1, 1, 1} 24 | } 25 | ncomp := f.NComp() 26 | 27 | for iz := range data[0] { 28 | z := float64(iz) * cellsize[Z] 29 | for iy := range data[0][iz] { 30 | y := float64(iy) * cellsize[Y] 31 | for ix := range data[0][iz][iy] { 32 | x := float64(ix) * cellsize[X] 33 | fmt.Fprint(buf, x, DELIM, y, DELIM, z, DELIM) 34 | for c := 0; c < ncomp-1; c++ { 35 | fmt.Fprint(buf, data[c][iz][iy][ix], DELIM) 36 | } 37 | fmt.Fprint(buf, data[ncomp-1][iz][iy][ix]) 38 | fmt.Fprint(buf, "\n") 39 | } 40 | fmt.Fprint(buf, "\n") 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /script/incdecstmt.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "reflect" 7 | ) 8 | 9 | func (w *World) compileIncDecStmt(n *ast.IncDecStmt) Expr { 10 | l := w.compileLvalue(n.X) 11 | switch n.Tok { 12 | case token.INC: 13 | rhs_plus1 := &addone{incdec{typeConv(n.Pos(), l, float64_t)}} 14 | return &assignStmt{lhs: l, rhs: typeConv(n.Pos(), rhs_plus1, l.Type())} 15 | case token.DEC: 16 | rhs_minus1 := &subone{incdec{typeConv(n.Pos(), l, float64_t)}} 17 | return &assignStmt{lhs: l, rhs: typeConv(n.Pos(), rhs_minus1, l.Type())} 18 | default: 19 | panic(err(n.Pos(), "not allowed:", n.Tok)) 20 | } 21 | } 22 | 23 | type incdec struct{ x Expr } 24 | 25 | func (e *incdec) Type() reflect.Type { return float64_t } 26 | func (e *incdec) Child() []Expr { return []Expr{e.x} } 27 | func (e *incdec) Fix() Expr { panic(invalid_closure) } 28 | 29 | type addone struct{ incdec } 30 | type subone struct{ incdec } 31 | 32 | func (s *addone) Eval() interface{} { return s.x.Eval().(float64) + 1 } 33 | func (s *subone) Eval() interface{} { return s.x.Eval().(float64) - 1 } 34 | -------------------------------------------------------------------------------- /engine/ext_centerbubble.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "math" 6 | ) 7 | 8 | func init() { 9 | DeclFunc("ext_centerBubble", CenterBubble, "centerBubble shifts m after each step to keep the bubble position close to the center of the window") 10 | } 11 | 12 | func centerBubble() { 13 | c := Mesh().CellSize() 14 | 15 | position := bubblePos() 16 | var centerIdx [2]int 17 | centerIdx[X] = int(math.Floor((position[X] - GetShiftPos()) / c[X])) 18 | centerIdx[Y] = int(math.Floor((position[Y] - GetShiftYPos()) / c[Y])) 19 | 20 | zero := data.Vector{0, 0, 0} 21 | if ShiftMagL == zero || ShiftMagR == zero || ShiftMagD == zero || ShiftMagU == zero { 22 | ShiftMagL[Z] = -BubbleMz 23 | ShiftMagR[Z] = -BubbleMz 24 | ShiftMagD[Z] = -BubbleMz 25 | ShiftMagU[Z] = -BubbleMz 26 | } 27 | 28 | //put bubble to center 29 | if centerIdx[X] != 0 { 30 | Shift(-centerIdx[X]) 31 | } 32 | if centerIdx[Y] != 0 { 33 | YShift(-centerIdx[Y]) 34 | } 35 | 36 | } 37 | 38 | // This post-step function centers the simulation window on a bubble 39 | func CenterBubble() { 40 | PostStep(func() { centerBubble() }) 41 | } 42 | -------------------------------------------------------------------------------- /script/funcif.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | // Here be dragons 4 | 5 | import ( 6 | "github.com/mumax/3/data" 7 | "reflect" 8 | ) 9 | 10 | type ScalarFunction interface { 11 | Expr 12 | Float() float64 13 | } 14 | 15 | // converts float64 to ScalarFunction 16 | type scalFn struct{ in Expr } 17 | 18 | func (c *scalFn) Eval() interface{} { return c } 19 | func (c *scalFn) Type() reflect.Type { return ScalarFunction_t } 20 | func (c *scalFn) Float() float64 { return c.in.Eval().(float64) } 21 | func (c *scalFn) Child() []Expr { return []Expr{c.in} } 22 | func (c *scalFn) Fix() Expr { return &scalFn{in: c.in.Fix()} } 23 | 24 | type VectorFunction interface { 25 | Expr 26 | Float3() data.Vector 27 | } 28 | 29 | // converts data.Vector to VectorFunction 30 | type vecFn struct{ in Expr } 31 | 32 | func (c *vecFn) Eval() interface{} { return c } 33 | func (c *vecFn) Type() reflect.Type { return VectorFunction_t } 34 | func (c *vecFn) Float3() data.Vector { return c.in.Eval().(data.Vector) } 35 | func (c *vecFn) Child() []Expr { return []Expr{c.in} } 36 | func (c *vecFn) Fix() Expr { return &vecFn{in: c.in.Fix()} } 37 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Use the default go compiler 3 | GO_BUILDFLAGS=-compiler gc 4 | # Or uncomment the line below to use the gccgo compiler, which may 5 | # or may not be faster than gc and which may or may not compile... 6 | # GO_BUILDFLAGS=-compiler gccgo -gccgoflags '-static-libgcc -O4 -Ofast -march=native' 7 | 8 | CGO_CFLAGS_ALLOW='(-fno-schedule-insns|-malign-double|-ffast-math)' 9 | 10 | 11 | .PHONY: all cudakernels clean realclean checktests runtests hooks 12 | 13 | 14 | all: cudakernels hooks 15 | go install -v $(GO_BUILDFLAGS) github.com/mumax/3/... 16 | 17 | cudakernels: 18 | cd cuda && $(MAKE) 19 | 20 | doc: 21 | cd doc && $(MAKE) 22 | 23 | test: all 24 | go test -vet=off -i github.com/mumax/3/... 25 | go test -vet=off $(PKGS) github.com/mumax/3/... 26 | cd test && ./run.bash 27 | 28 | hooks: .git/hooks/post-commit .git/hooks/pre-commit 29 | 30 | .git/hooks/post-commit: post-commit 31 | ln -sf $(CURDIR)/$< $@ 32 | 33 | .git/hooks/pre-commit: pre-commit 34 | ln -sf $(CURDIR)/$< $@ 35 | 36 | clean: 37 | rm -frv $(GOPATH)/pkg/*/github.com/mumax/3/* 38 | rm -frv $(GOPATH)/bin/mumax3* 39 | cd cuda && $(MAKE) clean 40 | 41 | realclean: clean 42 | cd cuda && ${MAKE} realclean -------------------------------------------------------------------------------- /cmd/mumax3-server/user.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | type User struct { 6 | Jobs []*Job 7 | FairShare float64 // Used-up compute time in the past (decays) 8 | nextPtr int // pointer suggesting next job to start. Reset on re-scan. len(Jobs) means no queued job 9 | } 10 | 11 | func NewUser() *User { 12 | return &User{} 13 | } 14 | 15 | // nextJob looks for the next free job in the list. 16 | // it does a tiny bit of linear search, starting from nextPtr. 17 | func (u *User) giveJob(node string) *Job { 18 | index := u.nextJobPtr() 19 | if index >= len(u.Jobs) { 20 | return nil 21 | } 22 | u.nextPtr++ 23 | j := u.Jobs[index] 24 | // all below are preliminary, to get rapid gui response. 25 | // may be overwritten by update 26 | j.Host = node 27 | j.Output = OutputDir(j.ID) 28 | j.Start = time.Now() 29 | return j 30 | } 31 | 32 | func (u *User) HasJob() bool { 33 | i := u.nextJobPtr() 34 | return i < len(u.Jobs) 35 | } 36 | 37 | // returns 38 | func (u *User) nextJobPtr() int { 39 | for ; u.nextPtr < len(u.Jobs); u.nextPtr++ { 40 | j := u.Jobs[u.nextPtr] 41 | if j.IsQueued() { 42 | return u.nextPtr 43 | } 44 | } 45 | return u.nextPtr 46 | } 47 | -------------------------------------------------------------------------------- /cmd/mumax3-convert/numpy.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | "github.com/mumax/3/data" 7 | "io" 8 | ) 9 | 10 | func dumpNUMPY(f *data.Slice, info data.Meta, out io.Writer) { 11 | 12 | // see npy format: https://www.numpy.org/devdocs/reference/generated/numpy.lib.format.html 13 | 14 | // write the first 10 bytes of the 128 byte header 15 | fmt.Fprintf(out, "\x93NUMPY") // magic string 16 | fmt.Fprintf(out, "\x01\x00") // npy format version 17 | binary.Write(out, binary.LittleEndian, uint16(118)) // length of the actual header data (128-10) 18 | 19 | // write the actual header data (118 bytes) 20 | shapestr := fmt.Sprintf("(%d,%d,%d,%d)", f.NComp(), f.Size()[2], f.Size()[1], f.Size()[0]) 21 | headerData := fmt.Sprintf("{'descr': '= 0 && c < parent.NComp()) 20 | return AsScalarField(&component{parent, c}) 21 | } 22 | 23 | func (q *component) NComp() int { return 1 } 24 | func (q *component) Name() string { return fmt.Sprint(NameOf(q.parent), "_", compname[q.comp]) } 25 | func (q *component) Unit() string { return UnitOf(q.parent) } 26 | func (q *component) Mesh() *data.Mesh { return MeshOf(q.parent) } 27 | 28 | func (q *component) Slice() (*data.Slice, bool) { 29 | p := q.parent 30 | src := ValueOf(p) 31 | defer cuda.Recycle(src) 32 | c := cuda.Buffer(1, src.Size()) 33 | return c, true 34 | } 35 | 36 | func (q *component) EvalTo(dst *data.Slice) { 37 | src := ValueOf(q.parent) 38 | defer cuda.Recycle(src) 39 | data.Copy(dst, src.Comp(q.comp)) 40 | } 41 | 42 | var compname = map[int]string{0: "x", 1: "y", 2: "z"} 43 | -------------------------------------------------------------------------------- /cuda/kernmulrsymm2dxy.cu: -------------------------------------------------------------------------------- 1 | // 2D XY (in-plane) micromagnetic kernel multiplication: 2 | // |Mx| = |Kxx Kxy| * |Mx| 3 | // |My| |Kyx Kyy| |My| 4 | // Using the same symmetries as kernmulrsymm3d.cu 5 | extern "C" __global__ void 6 | kernmulRSymm2Dxy(float* __restrict__ fftMx, float* __restrict__ fftMy, 7 | float* __restrict__ fftKxx, float* __restrict__ fftKyy, float* __restrict__ fftKxy, 8 | int Nx, int Ny) { 9 | 10 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 11 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 12 | 13 | if(ix>= Nx || iy>=Ny) { 14 | return; 15 | } 16 | 17 | int I = iy*Nx + ix; 18 | int e = 2 * I; 19 | 20 | float reMx = fftMx[e ]; 21 | float imMx = fftMx[e+1]; 22 | float reMy = fftMy[e ]; 23 | float imMy = fftMy[e+1]; 24 | 25 | // symmetry factor 26 | float fxy = 1.0f; 27 | if (iy > Ny/2) { 28 | iy = Ny-iy; 29 | fxy = -fxy; 30 | } 31 | I = iy*Nx + ix; 32 | 33 | float Kxx = fftKxx[I]; 34 | float Kyy = fftKyy[I]; 35 | float Kxy = fxy * fftKxy[I]; 36 | 37 | fftMx[e ] = reMx * Kxx + reMy * Kxy; 38 | fftMx[e+1] = imMx * Kxx + imMy * Kxy; 39 | fftMy[e ] = reMx * Kxy + reMy * Kyy; 40 | fftMy[e+1] = imMx * Kxy + imMy * Kyy; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /cuda/conv_copypad.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // Copies src (larger) into dst (smaller). 9 | // Used to extract demag field after convolution on padded m. 10 | func copyUnPad(dst, src *data.Slice, dstsize, srcsize [3]int) { 11 | util.Argument(dst.NComp() == 1 && src.NComp() == 1) 12 | util.Argument(dst.Len() == prod(dstsize) && src.Len() == prod(srcsize)) 13 | 14 | cfg := make3DConf(dstsize) 15 | 16 | k_copyunpad_async(dst.DevPtr(0), dstsize[X], dstsize[Y], dstsize[Z], 17 | src.DevPtr(0), srcsize[X], srcsize[Y], srcsize[Z], cfg) 18 | } 19 | 20 | // Copies src into dst, which is larger, and multiplies by vol*Bsat. 21 | // The remainder of dst is not filled with zeros. 22 | // Used to zero-pad magnetization before convolution and in the meanwhile multiply m by its length. 23 | func copyPadMul(dst, src, vol *data.Slice, dstsize, srcsize [3]int, Msat MSlice) { 24 | util.Argument(dst.NComp() == 1 && src.NComp() == 1) 25 | util.Assert(dst.Len() == prod(dstsize) && src.Len() == prod(srcsize)) 26 | 27 | cfg := make3DConf(srcsize) 28 | 29 | k_copypadmul2_async(dst.DevPtr(0), dstsize[X], dstsize[Y], dstsize[Z], 30 | src.DevPtr(0), srcsize[X], srcsize[Y], srcsize[Z], 31 | Msat.DevPtr(0), Msat.Mul(0), vol.DevPtr(0), cfg) 32 | } 33 | -------------------------------------------------------------------------------- /engine/heun.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "github.com/mumax/3/cuda" 5 | "github.com/mumax/3/util" 6 | "math" 7 | ) 8 | 9 | // Adaptive Heun solver. 10 | type Heun struct{} 11 | 12 | // Adaptive Heun method, can be used as solver.Step 13 | func (_ *Heun) Step() { 14 | y := M.Buffer() 15 | dy0 := cuda.Buffer(VECTOR, y.Size()) 16 | defer cuda.Recycle(dy0) 17 | 18 | if FixDt != 0 { 19 | Dt_si = FixDt 20 | } 21 | 22 | dt := float32(Dt_si * GammaLL) 23 | util.Assert(dt > 0) 24 | 25 | // stage 1 26 | torqueFn(dy0) 27 | cuda.Madd2(y, y, dy0, 1, dt) // y = y + dt * dy 28 | 29 | // stage 2 30 | dy := cuda.Buffer(3, y.Size()) 31 | defer cuda.Recycle(dy) 32 | Time += Dt_si 33 | torqueFn(dy) 34 | 35 | err := cuda.MaxVecDiff(dy0, dy) * float64(dt) 36 | 37 | // adjust next time step 38 | if err < MaxErr || Dt_si <= MinDt || FixDt != 0 { // mindt check to avoid infinite loop 39 | // step OK 40 | cuda.Madd3(y, y, dy, dy0, 1, 0.5*dt, -0.5*dt) 41 | M.normalize() 42 | NSteps++ 43 | adaptDt(math.Pow(MaxErr/err, 1./2.)) 44 | setLastErr(err) 45 | setMaxTorque(dy) 46 | } else { 47 | // undo bad step 48 | util.Assert(FixDt == 0) 49 | Time -= Dt_si 50 | cuda.Madd2(y, y, dy0, 1, -dt) 51 | NUndone++ 52 | adaptDt(math.Pow(MaxErr/err, 1./3.)) 53 | } 54 | } 55 | 56 | func (_ *Heun) Free() {} 57 | -------------------------------------------------------------------------------- /cuda/exchange.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "unsafe" 5 | 6 | "github.com/mumax/3/data" 7 | ) 8 | 9 | // Add exchange field to Beff. 10 | // m: normalized magnetization 11 | // B: effective field in Tesla 12 | // Aex_red: Aex / (Msat * 1e18 m2) 13 | // see exchange.cu 14 | func AddExchange(B, m *data.Slice, Aex_red SymmLUT, Msat MSlice, regions *Bytes, mesh *data.Mesh) { 15 | c := mesh.CellSize() 16 | wx := float32(2 / (c[X] * c[X])) 17 | wy := float32(2 / (c[Y] * c[Y])) 18 | wz := float32(2 / (c[Z] * c[Z])) 19 | N := mesh.Size() 20 | pbc := mesh.PBC_code() 21 | cfg := make3DConf(N) 22 | k_addexchange_async(B.DevPtr(X), B.DevPtr(Y), B.DevPtr(Z), 23 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 24 | Msat.DevPtr(0), Msat.Mul(0), 25 | unsafe.Pointer(Aex_red), regions.Ptr, 26 | wx, wy, wz, N[X], N[Y], N[Z], pbc, cfg) 27 | } 28 | 29 | // Finds the average exchange strength around each cell, for debugging. 30 | func ExchangeDecode(dst *data.Slice, Aex_red SymmLUT, regions *Bytes, mesh *data.Mesh) { 31 | c := mesh.CellSize() 32 | wx := float32(2 / (c[X] * c[X])) 33 | wy := float32(2 / (c[Y] * c[Y])) 34 | wz := float32(2 / (c[Z] * c[Z])) 35 | N := mesh.Size() 36 | pbc := mesh.PBC_code() 37 | cfg := make3DConf(N) 38 | k_exchangedecode_async(dst.DevPtr(0), unsafe.Pointer(Aex_red), regions.Ptr, wx, wy, wz, N[X], N[Y], N[Z], pbc, cfg) 39 | } 40 | -------------------------------------------------------------------------------- /engine/average.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | // Averaging of quantities over entire universe or just magnet. 4 | 5 | import ( 6 | "github.com/mumax/3/cuda" 7 | "github.com/mumax/3/data" 8 | ) 9 | 10 | // average of quantity over universe 11 | func qAverageUniverse(q Quantity) []float64 { 12 | s := ValueOf(q) 13 | defer cuda.Recycle(s) 14 | return sAverageUniverse(s) 15 | } 16 | 17 | // average of slice over universe 18 | func sAverageUniverse(s *data.Slice) []float64 { 19 | nCell := float64(prod(s.Size())) 20 | avg := make([]float64, s.NComp()) 21 | for i := range avg { 22 | avg[i] = float64(cuda.Sum(s.Comp(i))) / nCell 23 | checkNaN1(avg[i]) 24 | } 25 | return avg 26 | } 27 | 28 | // average of slice over the magnet volume 29 | func sAverageMagnet(s *data.Slice) []float64 { 30 | if geometry.Gpu().IsNil() { 31 | return sAverageUniverse(s) 32 | } else { 33 | avg := make([]float64, s.NComp()) 34 | for i := range avg { 35 | avg[i] = float64(cuda.Dot(s.Comp(i), geometry.Gpu())) / magnetNCell() 36 | checkNaN1(avg[i]) 37 | } 38 | return avg 39 | } 40 | } 41 | 42 | // number of cells in the magnet. 43 | // not necessarily integer as cells can have fractional volume. 44 | func magnetNCell() float64 { 45 | if geometry.Gpu().IsNil() { 46 | return float64(Mesh().NCell()) 47 | } else { 48 | return float64(cuda.Sum(geometry.Gpu())) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /gui/datamodels.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strconv" 7 | ) 8 | 9 | type interfaceData struct { 10 | v interface{} 11 | } 12 | 13 | func (d *interfaceData) setValue(v interface{}) { 14 | d.v = v 15 | } 16 | 17 | func (d *interfaceData) value() interface{} { 18 | return d.v 19 | } 20 | 21 | type boolData struct{ interfaceData } 22 | 23 | func (d *boolData) setValue(v interface{}) { 24 | d.v = v.(bool) 25 | } 26 | 27 | func BoolData(v bool) *boolData { 28 | return &boolData{interfaceData{v}} 29 | } 30 | 31 | type intData struct{ interfaceData } 32 | 33 | func IntData(v int) *intData { 34 | return &intData{interfaceData{v}} 35 | } 36 | 37 | func (d *intData) setValue(v interface{}) { 38 | switch v := v.(type) { 39 | case int: 40 | d.v = v 41 | default: 42 | i, err := strconv.Atoi(fmt.Sprint(v)) 43 | if err == nil { 44 | d.v = i 45 | } else { 46 | log.Println(err) 47 | } 48 | } 49 | } 50 | 51 | type floatData struct{ interfaceData } 52 | 53 | func FloatData(v float64) *floatData { 54 | return &floatData{interfaceData{v}} 55 | } 56 | 57 | func (d *floatData) setValue(v interface{}) { 58 | switch v := v.(type) { 59 | case float64: 60 | d.v = v 61 | default: 62 | i, err := strconv.ParseFloat(fmt.Sprint(v), 64) 63 | if err == nil { 64 | d.v = i 65 | } else { 66 | log.Println(err) 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /cmd/mumax3-server/watchdog.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "time" 6 | ) 7 | 8 | var runWatchdog = make(chan struct{}) 9 | 10 | func init() { 11 | // run watchdog daemon in background 12 | go func() { 13 | for { 14 | <-runWatchdog // wait for start 15 | DoWatchdog() 16 | } 17 | }() 18 | } 19 | 20 | func LoopWatchdog() { 21 | for { 22 | WakeupWatchdog("") 23 | time.Sleep(3 * KeepaliveInterval) 24 | } 25 | } 26 | 27 | func WakeupWatchdog(string) string { 28 | select { 29 | default: 30 | return "already running" 31 | case runWatchdog <- struct{}{}: 32 | return "" // ok 33 | } 34 | } 35 | 36 | // single watchdog run: 37 | // re-queues all dead processes 38 | func DoWatchdog() { 39 | //log.Println("Watchdog wake-up") 40 | WLock() 41 | defer WUnlock() 42 | for _, u := range Users { 43 | for _, j := range u.Jobs { 44 | id := j.ID 45 | //log.Println(id, "running:", j.IsRunning(), "alive:", time.Since(j.Alive)) 46 | if j.IsRunning() && time.Since(j.Alive) > 3*KeepaliveInterval { 47 | j.Update() 48 | lastHeartbeat := time.Since(j.Alive) 49 | if lastHeartbeat > 3*KeepaliveInterval { 50 | log.Println("*** Re-queue", id, "after", lastHeartbeat, "inactivity") 51 | j.Reque() 52 | } 53 | } 54 | } 55 | // re-set nextPtr to beginning so we can start re-queued jobs 56 | if u.nextPtr >= len(u.Jobs) { 57 | u.nextPtr = 0 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /cmd/mumax3-convert/normalize.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "math" 5 | 6 | "github.com/mumax/3/data" 7 | ) 8 | 9 | // normalize vector data to given length 10 | func normalize(f *data.Slice, length float64) { 11 | a := f.Vectors() 12 | for i := range a[0] { 13 | for j := range a[0][i] { 14 | for k := range a[0][i][j] { 15 | x, y, z := a[0][i][j][k], a[1][i][j][k], a[2][i][j][k] 16 | norm := math.Sqrt(float64(x*x + y*y + z*z)) 17 | invnorm := float32(1) 18 | if norm != 0 { 19 | invnorm = float32(length / norm) 20 | } 21 | a[0][i][j][k] *= invnorm 22 | a[1][i][j][k] *= invnorm 23 | a[2][i][j][k] *= invnorm 24 | 25 | } 26 | } 27 | } 28 | } 29 | 30 | func normpeak(f *data.Slice) { 31 | a := f.Vectors() 32 | maxnorm := 0. 33 | for i := range a[0] { 34 | for j := range a[0][i] { 35 | for k := range a[0][i][j] { 36 | 37 | x, y, z := a[0][i][j][k], a[1][i][j][k], a[2][i][j][k] 38 | norm := math.Sqrt(float64(x*x + y*y + z*z)) 39 | if norm > maxnorm { 40 | maxnorm = norm 41 | } 42 | 43 | } 44 | } 45 | } 46 | scale(f, float32(1/maxnorm)) 47 | } 48 | 49 | func scale(f *data.Slice, factor float32) { 50 | a := f.Vectors() 51 | for i := range a[0] { 52 | for j := range a[0][i] { 53 | for k := range a[0][i][j] { 54 | a[0][i][j][k] *= factor 55 | a[1][i][j][k] *= factor 56 | a[2][i][j][k] *= factor 57 | 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /cuda/cu/module.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | // This file implements loading of CUDA ptx modules 4 | 5 | //#include 6 | import "C" 7 | 8 | import ( 9 | "unsafe" 10 | ) 11 | 12 | // Represents a CUDA CUmodule, a reference to executable device code. 13 | type Module uintptr 14 | 15 | // Loads a compute module from file 16 | func ModuleLoad(fname string) Module { 17 | //fmt.Fprintln(os.Stderr, "driver.ModuleLoad", fname) 18 | var mod C.CUmodule 19 | err := Result(C.cuModuleLoad(&mod, C.CString(fname))) 20 | if err != SUCCESS { 21 | panic(err) 22 | } 23 | return Module(uintptr(unsafe.Pointer(mod))) 24 | } 25 | 26 | // Loads a compute module from string 27 | func ModuleLoadData(image string) Module { 28 | var mod C.CUmodule 29 | err := Result(C.cuModuleLoadData(&mod, unsafe.Pointer(C.CString(image)))) 30 | if err != SUCCESS { 31 | panic(err) 32 | } 33 | return Module(uintptr(unsafe.Pointer(mod))) 34 | } 35 | 36 | // Returns a Function handle. 37 | func ModuleGetFunction(module Module, name string) Function { 38 | var function C.CUfunction 39 | err := Result(C.cuModuleGetFunction( 40 | &function, 41 | C.CUmodule(unsafe.Pointer(uintptr(module))), 42 | C.CString(name))) 43 | if err != SUCCESS { 44 | panic(err) 45 | } 46 | return Function(uintptr(unsafe.Pointer(function))) 47 | } 48 | 49 | // Returns a Function handle. 50 | func (m Module) GetFunction(name string) Function { 51 | return ModuleGetFunction(m, name) 52 | } 53 | -------------------------------------------------------------------------------- /oommf/util.go: -------------------------------------------------------------------------------- 1 | package oommf 2 | 3 | import ( 4 | "io" 5 | "strconv" 6 | ) 7 | 8 | func readLine(in io.Reader) (line string, eof bool) { 9 | char := readChar(in) 10 | eof = isEOF(char) 11 | 12 | for !isEndline(char) { 13 | line += string(byte(char)) 14 | char = readChar(in) 15 | } 16 | return line, eof 17 | } 18 | 19 | func isEOF(char int) bool { 20 | return char == -1 21 | } 22 | 23 | func isEndline(char int) bool { 24 | return isEOF(char) || char == int('\n') 25 | } 26 | 27 | //// Blocks until all requested bytes are read. 28 | //type fullReader struct{ io.Reader } 29 | // 30 | //func (r fullReader) Read(p []byte) (n int, err error) { 31 | // return io.ReadFull(r.Reader, p) 32 | //} 33 | 34 | // Reads one character from the Reader. 35 | // -1 means EOF. 36 | // Errors are cought and cause panic 37 | func readChar(in io.Reader) int { 38 | buffer := [1]byte{} 39 | switch nr, err := in.Read(buffer[0:]); true { 40 | case nr < 0: // error 41 | panic(err) 42 | case nr == 0: // eof 43 | return -1 44 | case nr > 0: // ok 45 | return int(buffer[0]) 46 | } 47 | panic("unreachable") 48 | } 49 | 50 | func atoi(a string) int { 51 | i, err := strconv.Atoi(a) 52 | if err != nil { 53 | panic(err) 54 | } 55 | return i 56 | } 57 | 58 | func atof(a string) float64 { 59 | i, err := strconv.ParseFloat(a, 64) 60 | if err != nil { 61 | panic(err) 62 | } 63 | return i 64 | } 65 | 66 | const ( 67 | X = 0 68 | Y = 1 69 | Z = 2 70 | ) 71 | -------------------------------------------------------------------------------- /script/stmt.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "go/ast" 5 | "reflect" 6 | ) 7 | 8 | // compiles expression or statement 9 | func (w *World) compile(n ast.Node) Expr { 10 | switch n := n.(type) { 11 | case ast.Stmt: 12 | return w.compileStmt(n) 13 | case ast.Expr: 14 | return w.compileExpr(n) 15 | default: 16 | panic(err(n.Pos(), "not allowed")) 17 | } 18 | } 19 | 20 | // compiles a statement 21 | func (w *World) compileStmt(st ast.Stmt) Expr { 22 | switch st := st.(type) { 23 | default: 24 | panic(err(st.Pos(), "not allowed:", typ(st))) 25 | case *ast.EmptyStmt: 26 | return &emptyStmt{} 27 | case *ast.AssignStmt: 28 | return w.compileAssignStmt(st) 29 | case *ast.ExprStmt: 30 | return w.compileExpr(st.X) 31 | case *ast.IfStmt: 32 | return w.compileIfStmt(st) 33 | case *ast.ForStmt: 34 | return w.compileForStmt(st) 35 | case *ast.IncDecStmt: 36 | return w.compileIncDecStmt(st) 37 | case *ast.BlockStmt: 38 | w.EnterScope() 39 | defer w.ExitScope() 40 | return w.compileBlockStmt_noScope(st) 41 | } 42 | } 43 | 44 | // embed to get Type() that returns nil 45 | type void struct{} 46 | 47 | func (v *void) Type() reflect.Type { return nil } 48 | func (v *void) Fix() Expr { panic(invalid_closure) } 49 | 50 | type emptyStmt struct{ void } 51 | 52 | func (*emptyStmt) Child() []Expr { return nil } 53 | func (*emptyStmt) Eval() interface{} { return nil } 54 | 55 | const invalid_closure = "illegal statement in closure" 56 | -------------------------------------------------------------------------------- /cuda/cu/memset.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | // This file implements CUDA memset functions. 4 | 5 | //#include 6 | import "C" 7 | 8 | import ( 9 | "unsafe" 10 | ) 11 | 12 | // Sets the first N 32-bit values of dst array to value. 13 | // Asynchronous. 14 | func MemsetD32(deviceptr DevicePtr, value uint32, N int64) { 15 | err := Result(C.cuMemsetD32(C.CUdeviceptr(deviceptr), C.uint(value), C.size_t(N))) 16 | if err != SUCCESS { 17 | panic(err) 18 | } 19 | } 20 | 21 | // Asynchronously sets the first N 32-bit values of dst array to value. 22 | func MemsetD32Async(deviceptr DevicePtr, value uint32, N int64, stream Stream) { 23 | err := Result(C.cuMemsetD32Async(C.CUdeviceptr(deviceptr), C.uint(value), C.size_t(N), C.CUstream(unsafe.Pointer(uintptr(stream))))) 24 | if err != SUCCESS { 25 | panic(err) 26 | } 27 | } 28 | 29 | // Sets the first N 8-bit values of dst array to value. 30 | // Asynchronous. 31 | func MemsetD8(deviceptr DevicePtr, value uint8, N int64) { 32 | err := Result(C.cuMemsetD8(C.CUdeviceptr(deviceptr), C.uchar(value), C.size_t(N))) 33 | if err != SUCCESS { 34 | panic(err) 35 | } 36 | } 37 | 38 | // Asynchronously sets the first N 32-bit values of dst array to value. 39 | func MemsetD8Async(deviceptr DevicePtr, value uint8, N int64, stream Stream) { 40 | err := Result(C.cuMemsetD8Async(C.CUdeviceptr(deviceptr), C.uchar(value), C.size_t(N), C.CUstream(unsafe.Pointer(uintptr(stream))))) 41 | if err != SUCCESS { 42 | panic(err) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cuda/region.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "unsafe" 5 | 6 | "github.com/mumax/3/data" 7 | "github.com/mumax/3/util" 8 | ) 9 | 10 | // dst += LUT[region], for vectors. Used to add terms to excitation. 11 | func RegionAddV(dst *data.Slice, lut LUTPtrs, regions *Bytes) { 12 | util.Argument(dst.NComp() == 3) 13 | N := dst.Len() 14 | cfg := make1DConf(N) 15 | k_regionaddv_async(dst.DevPtr(X), dst.DevPtr(Y), dst.DevPtr(Z), 16 | lut[X], lut[Y], lut[Z], regions.Ptr, N, cfg) 17 | } 18 | 19 | // dst += LUT[region], for scalar. Used to add terms to scalar excitation. 20 | func RegionAddS(dst *data.Slice, lut LUTPtr, regions *Bytes) { 21 | util.Argument(dst.NComp() == 1) 22 | N := dst.Len() 23 | cfg := make1DConf(N) 24 | k_regionadds_async(dst.DevPtr(0), unsafe.Pointer(lut), regions.Ptr, N, cfg) 25 | } 26 | 27 | // decode the regions+LUT pair into an uncompressed array 28 | func RegionDecode(dst *data.Slice, lut LUTPtr, regions *Bytes) { 29 | N := dst.Len() 30 | cfg := make1DConf(N) 31 | k_regiondecode_async(dst.DevPtr(0), unsafe.Pointer(lut), regions.Ptr, N, cfg) 32 | } 33 | 34 | // select the part of src within the specified region, set 0's everywhere else. 35 | func RegionSelect(dst, src *data.Slice, regions *Bytes, region byte) { 36 | util.Argument(dst.NComp() == src.NComp()) 37 | N := dst.Len() 38 | cfg := make1DConf(N) 39 | 40 | for c := 0; c < dst.NComp(); c++ { 41 | k_regionselect_async(dst.DevPtr(c), src.DevPtr(c), regions.Ptr, region, N, cfg) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /engine/asyncio.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "github.com/mumax/3/cuda" 5 | "github.com/mumax/3/timer" 6 | "github.com/mumax/3/util" 7 | "time" 8 | ) 9 | 10 | // Asynchronous I/O queue flushes data to disk while simulation keeps running. 11 | // See save.go, autosave.go 12 | 13 | var ( 14 | saveQue chan func() // passes save requests to runSaver for asyc IO 15 | queLen util.Atom // # tasks in queue 16 | ) 17 | 18 | const maxOutputQueLen = 16 // number of outputs that can be queued for asynchronous I/O. 19 | 20 | func init() { 21 | DeclFunc("Flush", drainOutput, "Flush all pending output to disk.") 22 | 23 | saveQue = make(chan func()) 24 | go runSaver() 25 | } 26 | 27 | func queOutput(f func()) { 28 | if cuda.Synchronous { 29 | timer.Start("io") 30 | } 31 | queLen.Add(1) 32 | saveQue <- f 33 | if cuda.Synchronous { 34 | timer.Stop("io") 35 | } 36 | } 37 | 38 | // Continuously executes tasks the from SaveQue channel. 39 | func runSaver() { 40 | for f := range saveQue { 41 | f() 42 | queLen.Add(-1) 43 | } 44 | } 45 | 46 | // Finalizer function called upon program exit. 47 | // Waits until all asynchronous output has been saved. 48 | func drainOutput() { 49 | if saveQue == nil { 50 | return 51 | } 52 | for queLen.Load() > 0 { 53 | select { 54 | default: 55 | time.Sleep(1 * time.Millisecond) // other goroutine has the last job, wait for it to finish 56 | case f := <-saveQue: 57 | f() 58 | queLen.Add(-1) 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /data/vector.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import "math" 4 | 5 | // 3-component vector 6 | type Vector [3]float64 7 | 8 | func (v Vector) X() float64 { return v[0] } 9 | func (v Vector) Y() float64 { return v[1] } 10 | func (v Vector) Z() float64 { return v[2] } 11 | 12 | // Returns a*v. 13 | func (v Vector) Mul(a float64) Vector { 14 | return Vector{a * v[0], a * v[1], a * v[2]} 15 | } 16 | 17 | // Returns (1/a)*v. 18 | func (v Vector) Div(a float64) Vector { 19 | return v.Mul(1 / a) 20 | } 21 | 22 | // Returns a+b. 23 | func (a Vector) Add(b Vector) Vector { 24 | return Vector{a[0] + b[0], a[1] + b[1], a[2] + b[2]} 25 | } 26 | 27 | // Returns a+s*b. 28 | func (a Vector) MAdd(s float64, b Vector) Vector { 29 | return Vector{a[0] + s*b[0], a[1] + s*b[1], a[2] + s*b[2]} 30 | } 31 | 32 | // Returns a-b. 33 | func (a Vector) Sub(b Vector) Vector { 34 | return Vector{a[0] - b[0], a[1] - b[1], a[2] - b[2]} 35 | } 36 | 37 | // Returns the norm of v. 38 | func (v Vector) Len() float64 { 39 | len2 := v.Dot(v) 40 | return math.Sqrt(len2) 41 | } 42 | 43 | // Returns the dot (inner) product a.b. 44 | func (a Vector) Dot(b Vector) float64 { 45 | return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] 46 | } 47 | 48 | // Returns the cross (vector) product a x b 49 | // in a right-handed coordinate system. 50 | func (a Vector) Cross(b Vector) Vector { 51 | x := a[1]*b[2] - a[2]*b[1] 52 | y := a[2]*b[0] - a[0]*b[2] 53 | z := a[0]*b[1] - a[1]*b[0] 54 | return Vector{x, y, z} 55 | } 56 | 57 | const ( 58 | X = 0 59 | Y = 1 60 | Z = 2 61 | ) 62 | -------------------------------------------------------------------------------- /script/selector.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "fmt" 5 | "go/ast" 6 | "reflect" 7 | "strings" 8 | "unicode" 9 | ) 10 | 11 | const GoExclusiveMethodSuffix = "Go" 12 | 13 | type selector struct { 14 | x Expr 15 | method string 16 | } 17 | 18 | // compiles a selector statement like x.sel 19 | func (w *World) compileSelectorStmt(n *ast.SelectorExpr) Expr { 20 | x := w.compileExpr(n.X) 21 | t := x.Type() 22 | 23 | if t == nil { 24 | panic(err(n.Pos(), "void does not have member", n.Sel.Name)) 25 | } 26 | 27 | sel := strings.ToLower(n.Sel.Name) 28 | N := "" 29 | for i := 0; i < t.NumMethod(); i++ { 30 | name := t.Method(i).Name 31 | if strings.ToLower(name) == sel && unicode.IsUpper(rune(name[0])) && !strings.HasSuffix(name, GoExclusiveMethodSuffix) { 32 | N = t.Method(i).Name 33 | break 34 | } 35 | } 36 | if N == "" { 37 | panic(err(n.Pos(), t, "has no method", n.Sel.Name)) 38 | } 39 | return &selector{x, N} 40 | } 41 | 42 | func (e *selector) Eval() interface{} { 43 | obj := reflect.ValueOf(e.x.Eval()) 44 | meth := obj.MethodByName(e.method) 45 | if meth.Kind() == 0 { 46 | panic(fmt.Sprint(e.x, " has no method ", e.method)) 47 | } 48 | return meth.Interface() 49 | } 50 | 51 | func (e *selector) Type() reflect.Type { 52 | return reflect.New(e.x.Type()).Elem().MethodByName(e.method).Type() 53 | } 54 | 55 | func (e *selector) Child() []Expr { 56 | return []Expr{e.x} 57 | } 58 | 59 | func (e *selector) Fix() Expr { 60 | return &selector{x: e.x.Fix(), method: e.method} 61 | } 62 | -------------------------------------------------------------------------------- /cuda/uniaxialanisotropy2.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include "float3.h" 3 | #include "amul.h" 4 | 5 | // Add uniaxial magnetocrystalline anisotropy field to B. 6 | // http://www.southampton.ac.uk/~fangohr/software/oxs_uniaxial4.html 7 | extern "C" __global__ void 8 | adduniaxialanisotropy2(float* __restrict__ Bx, float* __restrict__ By, float* __restrict__ Bz, 9 | float* __restrict__ mx, float* __restrict__ my, float* __restrict__ mz, 10 | float* __restrict__ Ms_, float Ms_mul, 11 | float* __restrict__ K1_, float K1_mul, 12 | float* __restrict__ K2_, float K2_mul, 13 | float* __restrict__ ux_, float ux_mul, 14 | float* __restrict__ uy_, float uy_mul, 15 | float* __restrict__ uz_, float uz_mul, 16 | int N) { 17 | 18 | int i = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 19 | if (i < N) { 20 | 21 | float3 u = normalized(vmul(ux_, uy_, uz_, ux_mul, uy_mul, uz_mul, i)); 22 | float invMs = inv_Msat(Ms_, Ms_mul, i); 23 | float K1 = amul(K1_, K1_mul, i) * invMs; 24 | float K2 = amul(K2_, K2_mul, i) * invMs; 25 | float3 m = {mx[i], my[i], mz[i]}; 26 | float mu = dot(m, u); 27 | float3 Ba = 2.0f*K1* (mu)*u+ 28 | 4.0f*K2*pow3(mu)*u; 29 | 30 | Bx[i] += Ba.x; 31 | By[i] += Ba.y; 32 | Bz[i] += Ba.z; 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /engine/engine.go: -------------------------------------------------------------------------------- 1 | /* 2 | engine does the simulation bookkeeping, I/O and GUI. 3 | 4 | space-dependence: 5 | value: space-independent 6 | param: region-dependent parameter (always input) 7 | field: fully space-dependent field 8 | 9 | TODO: godoc everything 10 | 11 | */ 12 | package engine 13 | 14 | import ( 15 | "fmt" 16 | "os" 17 | "runtime" 18 | "sync" 19 | "time" 20 | 21 | "github.com/mumax/3/cuda/cu" 22 | "github.com/mumax/3/timer" 23 | ) 24 | 25 | const VERSION = "mumax 3.10" 26 | 27 | var UNAME = fmt.Sprintf("%s [%s_%s %s(%s) CUDA-%d.%d]", 28 | VERSION, runtime.GOOS, runtime.GOARCH, runtime.Version(), runtime.Compiler, 29 | cu.CUDA_VERSION/1000, (cu.CUDA_VERSION%1000)/10) 30 | 31 | var StartTime = time.Now() 32 | 33 | var ( 34 | busyLock sync.Mutex 35 | busy bool // are we so busy we can't respond from run loop? (e.g. calc kernel) 36 | ) 37 | 38 | // We set SetBusy(true) when the simulation is too busy too accept GUI input on Inject channel. 39 | // E.g. during kernel init. 40 | func SetBusy(b bool) { 41 | busyLock.Lock() 42 | defer busyLock.Unlock() 43 | busy = b 44 | } 45 | 46 | func GetBusy() bool { 47 | busyLock.Lock() 48 | defer busyLock.Unlock() 49 | return busy 50 | } 51 | 52 | // Cleanly exits the simulation, assuring all output is flushed. 53 | func Close() { 54 | drainOutput() 55 | LogUsedRefs() 56 | Table.flush() 57 | if logfile != nil { 58 | logfile.Close() 59 | } 60 | if bibfile != nil { 61 | bibfile.Close() 62 | } 63 | if *Flag_sync { 64 | timer.Print(os.Stdout) 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /cuda/anisotropy.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // Add uniaxial magnetocrystalline anisotropy field to Beff. 9 | // see uniaxialanisotropy.cu 10 | func AddCubicAnisotropy2(Beff, m *data.Slice, Msat, k1, k2, k3, c1, c2 MSlice) { 11 | util.Argument(Beff.Size() == m.Size()) 12 | 13 | N := Beff.Len() 14 | cfg := make1DConf(N) 15 | k_addcubicanisotropy2_async( 16 | Beff.DevPtr(X), Beff.DevPtr(Y), Beff.DevPtr(Z), 17 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 18 | Msat.DevPtr(0), Msat.Mul(0), 19 | k1.DevPtr(0), k1.Mul(0), 20 | k2.DevPtr(0), k2.Mul(0), 21 | k3.DevPtr(0), k3.Mul(0), 22 | c1.DevPtr(X), c1.Mul(X), 23 | c1.DevPtr(Y), c1.Mul(Y), 24 | c1.DevPtr(Z), c1.Mul(Z), 25 | c2.DevPtr(X), c2.Mul(X), 26 | c2.DevPtr(Y), c2.Mul(Y), 27 | c2.DevPtr(Z), c2.Mul(Z), 28 | N, cfg) 29 | } 30 | 31 | // Add uniaxial magnetocrystalline anisotropy field to Beff. 32 | // see uniaxialanisotropy.cu 33 | func AddUniaxialAnisotropy2(Beff, m *data.Slice, Msat, k1, k2, u MSlice) { 34 | util.Argument(Beff.Size() == m.Size()) 35 | 36 | checkSize(Beff, m, k1, k2, u, Msat) 37 | 38 | N := Beff.Len() 39 | cfg := make1DConf(N) 40 | 41 | k_adduniaxialanisotropy2_async( 42 | Beff.DevPtr(X), Beff.DevPtr(Y), Beff.DevPtr(Z), 43 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 44 | Msat.DevPtr(0), Msat.Mul(0), 45 | k1.DevPtr(0), k1.Mul(0), 46 | k2.DevPtr(0), k2.Mul(0), 47 | u.DevPtr(X), u.Mul(X), 48 | u.DevPtr(Y), u.Mul(Y), 49 | u.DevPtr(Z), u.Mul(Z), 50 | N, cfg) 51 | } 52 | -------------------------------------------------------------------------------- /cuda/cu/peer.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | // This file implements CUDA unified addressing. 4 | 5 | //#include 6 | import "C" 7 | 8 | import ( 9 | "unsafe" 10 | ) 11 | 12 | // Make allocations from the peer Context available to the current context. 13 | func CtxEnablePeerAccess(peer Context) { 14 | err := Result(C.cuCtxEnablePeerAccess(C.CUcontext(unsafe.Pointer(uintptr(peer))), C.uint(0))) 15 | if err != SUCCESS { 16 | panic(err) 17 | } 18 | } 19 | 20 | // Make allocations from the peer Context available to the current context. 21 | func (peer Context) EnablePeerAccess() { 22 | CtxEnablePeerAccess(peer) 23 | } 24 | 25 | // Reverses CtxEnablePeerAccess(). 26 | func CtxDisablePeerAccess(peer Context) { 27 | err := Result(C.cuCtxDisablePeerAccess(C.CUcontext(unsafe.Pointer(uintptr(peer))))) 28 | if err != SUCCESS { 29 | panic(err) 30 | } 31 | } 32 | 33 | // Reverses EnablePeerAccess(). 34 | func (peer Context) DisablePeerAccess() { 35 | CtxDisablePeerAccess(peer) 36 | } 37 | 38 | // Returns true if CtxEnablePeerAccess can be called on a context for dev and peerDev. 39 | func DeviceCanAccessPeer(dev, peer Device) bool { 40 | var canAccessPeer C.int 41 | err := Result(C.cuDeviceCanAccessPeer(&canAccessPeer, C.CUdevice(dev), C.CUdevice(peer))) 42 | if err != SUCCESS { 43 | panic(err) 44 | } 45 | return int(canAccessPeer) != 0 46 | } 47 | 48 | // Returns true if CtxEnablePeerAccess can be called on a context for dev and peerDev. 49 | func (dev Device) CanAccessPeer(peer Device) bool { 50 | return DeviceCanAccessPeer(dev, peer) 51 | } 52 | -------------------------------------------------------------------------------- /cuda/cu/execution.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | // This file implements execution of CUDA kernels 4 | 5 | //#include 6 | import "C" 7 | 8 | import ( 9 | "unsafe" 10 | ) 11 | 12 | const pointerSize = 8 // sorry, 64 bits only. 13 | 14 | func LaunchKernel(f Function, gridDimX, gridDimY, gridDimZ int, blockDimX, blockDimY, blockDimZ int, sharedMemBytes int, stream Stream, kernelParams []unsafe.Pointer) { 15 | 16 | // Since Go 1.6, a cgo argument cannot have a Go pointer to Go pointer, 17 | // so we copy the argument values go C memory first. 18 | argv := C.malloc(C.size_t(len(kernelParams) * pointerSize)) 19 | argp := C.malloc(C.size_t(len(kernelParams) * pointerSize)) 20 | defer C.free(argv) 21 | defer C.free(argp) 22 | for i := range kernelParams { 23 | *((*unsafe.Pointer)(offset(argp, i))) = offset(argv, i) // argp[i] = &argv[i] 24 | *((*uint64)(offset(argv, i))) = *((*uint64)(kernelParams[i])) // argv[i] = *kernelParams[i] 25 | } 26 | 27 | err := Result(C.cuLaunchKernel( 28 | C.CUfunction(unsafe.Pointer(uintptr(f))), 29 | C.uint(gridDimX), 30 | C.uint(gridDimY), 31 | C.uint(gridDimZ), 32 | C.uint(blockDimX), 33 | C.uint(blockDimY), 34 | C.uint(blockDimZ), 35 | C.uint(sharedMemBytes), 36 | C.CUstream(unsafe.Pointer(uintptr(stream))), 37 | (*unsafe.Pointer)(argp), 38 | (*unsafe.Pointer)(unsafe.Pointer(uintptr(0))))) 39 | if err != SUCCESS { 40 | panic(err) 41 | } 42 | } 43 | 44 | func offset(ptr unsafe.Pointer, i int) unsafe.Pointer { 45 | return unsafe.Pointer(uintptr(ptr) + pointerSize*uintptr(i)) 46 | } 47 | -------------------------------------------------------------------------------- /freetype/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This is the official list of people who can contribute 2 | # (and typically have contributed) code to the Freetype-Go repository. 3 | # The AUTHORS file lists the copyright holders; this file 4 | # lists people. For example, Google employees are listed here 5 | # but not in AUTHORS, because Google holds the copyright. 6 | # 7 | # The submission process automatically checks to make sure 8 | # that people submitting code are listed in this file (by email address). 9 | # 10 | # Names should be added to this file only after verifying that 11 | # the individual or the individual's organization has agreed to 12 | # the appropriate Contributor License Agreement, found here: 13 | # 14 | # http://code.google.com/legal/individual-cla-v1.0.html 15 | # http://code.google.com/legal/corporate-cla-v1.0.html 16 | # 17 | # The agreement for individuals can be filled out on the web. 18 | # 19 | # When adding J Random Contributor's name to this file, 20 | # either J's name or J's organization's name should be 21 | # added to the AUTHORS file, depending on whether the 22 | # individual or corporate CLA was used. 23 | 24 | # Names should be added to this file like so: 25 | # Name 26 | 27 | # Please keep the list sorted. 28 | 29 | Andrew Gerrand 30 | Jeff R. Allen 31 | Nigel Tao 32 | Rémy Oudompheng 33 | Rob Pike 34 | Roger Peppe 35 | Russ Cox 36 | -------------------------------------------------------------------------------- /cmd/mumax3-script/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Toy interpreter executes scripts or stdin. 3 | */ 4 | package main 5 | 6 | import ( 7 | "bufio" 8 | "flag" 9 | "fmt" 10 | "github.com/mumax/3/script" 11 | "io" 12 | "log" 13 | "os" 14 | ) 15 | 16 | var debug = flag.Bool("g", false, "print debug output") 17 | 18 | var ( 19 | world *script.World 20 | ps1 string 21 | ) 22 | 23 | func main() { 24 | log.SetFlags(0) 25 | flag.Parse() 26 | world = script.NewWorld() 27 | world.Func("exit", exit) 28 | script.Debug = *debug 29 | 30 | if flag.NArg() > 1 { 31 | check(fmt.Errorf("need 0 or 1 input files")) 32 | } 33 | 34 | if flag.NArg() == 1 { 35 | src, err := os.Open(flag.Arg(0)) 36 | check(err) 37 | ps1 = ">" 38 | interpret(src) 39 | } else { 40 | ps1 = "" 41 | interpret(os.Stdin) 42 | } 43 | } 44 | 45 | func interpret(in io.Reader) { 46 | scanner := bufio.NewScanner(in) 47 | for scanner.Scan() { 48 | safecall(scanner.Text()) 49 | } 50 | check(scanner.Err()) 51 | } 52 | 53 | func safecall(code string) { 54 | if code == "" { 55 | return 56 | } 57 | defer func() { 58 | err := recover() 59 | if err != nil { 60 | fmt.Fprintln(os.Stderr, "panic:", err) 61 | } 62 | }() 63 | tree, err := world.Compile(code) 64 | if err == nil { 65 | for _, stmt := range tree.Child() { 66 | fmt.Println(stmt.Eval()) 67 | } 68 | } else { 69 | fmt.Fprintln(os.Stderr, err) 70 | } 71 | 72 | } 73 | 74 | func check(e error) { 75 | if e != nil { 76 | fmt.Fprintln(os.Stderr, e) 77 | os.Exit(1) 78 | } 79 | } 80 | 81 | func exit() { 82 | os.Exit(0) 83 | } 84 | -------------------------------------------------------------------------------- /draw/svg.go: -------------------------------------------------------------------------------- 1 | package draw 2 | 3 | import ( 4 | "fmt" 5 | "github.com/mumax/3/svgo" 6 | "io" 7 | "math" 8 | ) 9 | 10 | // Renders svg image of vector data. 11 | func SVG(out io.Writer, arr [3][][][]float32) { 12 | 13 | h, w := len(arr[0][0]), len(arr[0][0][0]) 14 | 15 | const ( 16 | r1 = 1. / 2. // arrow half length 17 | r2 = 1. / 4. // arrow half width 18 | ) 19 | 20 | canvas := svg.New(out) 21 | canvas.Start(w, h) 22 | 23 | for slice := 0; slice < len(arr[0]); slice++ { 24 | Mx := arr[X][slice] 25 | My := arr[Y][slice] 26 | Mz := arr[Z][slice] 27 | 28 | for i := 0; i < h; i++ { 29 | y := float64(h) - (float64(i) + 1./2.) 30 | for j := 0; j < w; j++ { 31 | x := float64(j) + 1./2. 32 | 33 | mx := Mx[i][j] 34 | my := My[i][j] 35 | mz := Mz[i][j] 36 | 37 | // skip zero-length vectors 38 | if mx*mx+my*my+mz*mz == 0 { 39 | continue 40 | } 41 | 42 | theta := math.Atan2(float64(my), float64(mx)) 43 | c := math.Cos(theta) 44 | s := math.Sin(theta) 45 | r1 := r1 * math.Cos(math.Asin(float64(mz))) 46 | 47 | xs := []float64{(r1 * c) + x, (r2*s - r1*c) + x, (-r2*s - r1*c) + x} 48 | ys := []float64{-(r1 * s) + y, -(-r2*c - r1*s) + y, -(r2*c - r1*s) + y} 49 | 50 | col := HSLMap(mx, my, mz) 51 | style := "fill:#" + hex(col.R) + hex(col.G) + hex(col.B) 52 | 53 | canvas.Polygon(xs, ys, style) 54 | } 55 | } 56 | } 57 | 58 | canvas.End() 59 | } 60 | 61 | func hex(i uint8) string { 62 | j := int(i) - 32 // make it a bit darker 63 | if j < 0 { 64 | j = 0 65 | } 66 | return fmt.Sprintf("%02X", j) 67 | } 68 | -------------------------------------------------------------------------------- /cuda/cu/stream.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | // This file implements CUDA streams 4 | 5 | //#include 6 | import "C" 7 | import "unsafe" 8 | 9 | // CUDA stream. 10 | type Stream uintptr 11 | 12 | // Creates an asynchronous stream 13 | func StreamCreate() Stream { 14 | var stream C.CUstream 15 | err := Result(C.cuStreamCreate(&stream, C.uint(0))) // flags has to be zero 16 | if err != SUCCESS { 17 | panic(err) 18 | } 19 | return Stream(uintptr(unsafe.Pointer(stream))) 20 | } 21 | 22 | // Destroys the asynchronous stream 23 | func (stream *Stream) Destroy() { 24 | str := *stream 25 | err := Result(C.cuStreamDestroy(C.CUstream(unsafe.Pointer(uintptr(str))))) 26 | *stream = 0 27 | if err != SUCCESS { 28 | panic(err) 29 | } 30 | } 31 | 32 | // Destroys an asynchronous stream 33 | func StreamDestroy(stream *Stream) { 34 | stream.Destroy() 35 | } 36 | 37 | // Blocks until the stream has completed. 38 | func (stream Stream) Synchronize() { 39 | err := Result(C.cuStreamSynchronize(C.CUstream(unsafe.Pointer(uintptr(stream))))) 40 | if err != SUCCESS { 41 | panic(err) 42 | } 43 | } 44 | 45 | // Returns Success if all operations have completed, ErrorNotReady otherwise 46 | func (stream Stream) Query() Result { 47 | return Result(C.cuStreamQuery(C.CUstream(unsafe.Pointer(uintptr(stream))))) 48 | } 49 | 50 | // Returns Success if all operations have completed, ErrorNotReady otherwise 51 | func StreamQuery(stream Stream) Result { 52 | return stream.Query() 53 | } 54 | 55 | // Blocks until the stream has completed. 56 | func StreamSynchronize(stream Stream) { 57 | stream.Synchronize() 58 | } 59 | -------------------------------------------------------------------------------- /script/error.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "fmt" 5 | "go/token" 6 | "reflect" 7 | "strings" 8 | ) 9 | 10 | var Debug = false // print debug info? 11 | 12 | // compileErr, and only compileErr will be caught by Compile and returned as an error. 13 | type compileErr struct { 14 | pos token.Pos 15 | msg string 16 | } 17 | 18 | // implements error 19 | func (c *compileErr) Error() string { 20 | return c.msg 21 | } 22 | 23 | // constructs a compileErr 24 | func err(pos token.Pos, msg ...interface{}) *compileErr { 25 | str := fmt.Sprintln(msg...) // use Sprinln to insert spaces 26 | str = str[:len(str)-1] // strip final \n 27 | return &compileErr{pos, str} 28 | } 29 | 30 | // type string for value i 31 | func typ(i interface{}) string { 32 | typ := reflect.TypeOf(reflect.ValueOf(i).Interface()).String() 33 | if strings.HasPrefix(typ, "*ast.") { 34 | typ = typ[len("*ast."):] 35 | } 36 | return typ 37 | } 38 | 39 | func assert(test bool) { 40 | if !test { 41 | panic("assertion failed") 42 | } 43 | } 44 | 45 | // decodes a token position in source to a line number 46 | // and returns the line number + line code. 47 | func pos2line(pos token.Pos, src string) string { 48 | if pos == 0 { 49 | return "" 50 | } 51 | lines := strings.Split(src, "\n") 52 | line := 0 53 | for i, b := range src { 54 | if token.Pos(i) == pos { 55 | return fmt.Sprint("line ", line, ": ", strings.Trim(lines[line], " \t")) // func{ prefix makes lines count from 1 56 | } 57 | if b == '\n' { 58 | line++ 59 | } 60 | } 61 | return fmt.Sprint("position", pos) // we should not reach this 62 | } 63 | -------------------------------------------------------------------------------- /draw/colorscale.go: -------------------------------------------------------------------------------- 1 | package draw 2 | 3 | import "image/color" 4 | import "fmt" 5 | 6 | type ColorMapSpec struct { 7 | Cmap []color.RGBA 8 | Ccomp int 9 | } 10 | 11 | func ColorMap(min, max, value float32, colormap ...color.RGBA) color.RGBA { 12 | // default colormap: black-white 13 | if len(colormap) < 1 { 14 | colormap = []color.RGBA{{0, 0, 0, 255}, {255, 255, 255, 255}} 15 | } 16 | 17 | // map value to interval [O,1] 18 | val := float64((value - min) / (max - min)) 19 | if val > 1 { 20 | val = 1 21 | } 22 | if val < 0 { 23 | val = 0 24 | } 25 | 26 | // find index of color below our value 27 | maxIndex := float64(len(colormap) - 1) 28 | index := val * maxIndex 29 | // corner case val==max: 30 | if index == maxIndex { 31 | index-- 32 | } 33 | 34 | // get two neighboring colors 35 | i := int(index) 36 | if i < 0 { 37 | i = 0 38 | } 39 | if i >= len(colormap)-1 { 40 | i = len(colormap) - 2 41 | } 42 | c1 := colormap[i] 43 | c2 := colormap[i+1] 44 | 45 | // location between two neighboring colors [0..1] 46 | x := (val - float64(i)/maxIndex) * maxIndex 47 | if x < 0 || x > 1 { 48 | panic(fmt.Sprint("x=", x)) 49 | } 50 | 51 | // interpolate between colors 52 | r := (1-x)*float64(c1.R) + x*float64(c2.R) 53 | g := (1-x)*float64(c1.G) + x*float64(c2.G) 54 | b := (1-x)*float64(c1.B) + x*float64(c2.B) 55 | a := (1-x)*float64(c1.A) + x*float64(c2.A) 56 | 57 | return color.RGBA{bte(r), bte(g), bte(b), bte(a)} 58 | 59 | } 60 | 61 | func bte(x float64) uint8 { 62 | if x < 0 { 63 | return 0 64 | } 65 | if x > 255 { 66 | return 255 67 | } 68 | return uint8(x) 69 | } 70 | -------------------------------------------------------------------------------- /script/blockstmt.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "go/ast" 7 | "go/format" 8 | "go/token" 9 | "reflect" 10 | "strings" 11 | ) 12 | 13 | // block statement is a list of statements. 14 | type BlockStmt struct { 15 | Children []Expr 16 | Node []ast.Node 17 | } 18 | 19 | // does not enter scope because it does not necessarily needs to (e.g. for, if). 20 | func (w *World) compileBlockStmt_noScope(n *ast.BlockStmt) *BlockStmt { 21 | b := &BlockStmt{} 22 | for _, s := range n.List { 23 | b.append(w.compileStmt(s), s) 24 | } 25 | return b 26 | } 27 | 28 | func (b *BlockStmt) append(s Expr, n ast.Node) { 29 | b.Children = append(b.Children, s) 30 | b.Node = append(b.Node, n) 31 | } 32 | 33 | func (b *BlockStmt) Eval() interface{} { 34 | for _, s := range b.Children { 35 | s.Eval() 36 | } 37 | return nil 38 | } 39 | 40 | func (b *BlockStmt) Type() reflect.Type { 41 | return nil 42 | } 43 | 44 | func (b *BlockStmt) Child() []Expr { 45 | return b.Children 46 | } 47 | 48 | func Format(n ast.Node) string { 49 | var buf bytes.Buffer 50 | fset := token.NewFileSet() 51 | format.Node(&buf, fset, n) 52 | str := buf.String() 53 | if strings.HasSuffix(str, "\n") { 54 | str = str[:len(str)-1] 55 | } 56 | return str 57 | } 58 | 59 | func (b *BlockStmt) Format() string { 60 | var buf bytes.Buffer 61 | fset := token.NewFileSet() 62 | for i := range b.Children { 63 | format.Node(&buf, fset, b.Node[i]) 64 | fmt.Fprintln(&buf) 65 | } 66 | return buf.String() 67 | } 68 | 69 | func (b *BlockStmt) Fix() Expr { 70 | return &BlockStmt{Children: fixExprs(b.Children), Node: b.Node} 71 | } 72 | -------------------------------------------------------------------------------- /engine/backwardeuler.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "github.com/mumax/3/cuda" 5 | "github.com/mumax/3/data" 6 | "github.com/mumax/3/util" 7 | ) 8 | 9 | // Implicit midpoint solver. 10 | type BackwardEuler struct { 11 | dy1 *data.Slice 12 | } 13 | 14 | // Euler method, can be used as solver.Step. 15 | func (s *BackwardEuler) Step() { 16 | util.AssertMsg(MaxErr > 0, "Backward euler solver requires MaxErr > 0") 17 | 18 | t0 := Time 19 | 20 | y := M.Buffer() 21 | 22 | y0 := cuda.Buffer(VECTOR, y.Size()) 23 | defer cuda.Recycle(y0) 24 | data.Copy(y0, y) 25 | 26 | dy0 := cuda.Buffer(VECTOR, y.Size()) 27 | defer cuda.Recycle(dy0) 28 | if s.dy1 == nil { 29 | s.dy1 = cuda.Buffer(VECTOR, y.Size()) 30 | } 31 | dy1 := s.dy1 32 | 33 | Dt_si = FixDt 34 | dt := float32(Dt_si * GammaLL) 35 | util.AssertMsg(dt > 0, "Backward Euler solver requires fixed time step > 0") 36 | 37 | // Fist guess 38 | Time = t0 + 0.5*Dt_si // 0.5 dt makes it implicit midpoint method 39 | 40 | // with temperature, previous torque cannot be used as predictor 41 | if Temp.isZero() { 42 | cuda.Madd2(y, y0, dy1, 1, dt) // predictor euler step with previous torque 43 | M.normalize() 44 | } 45 | 46 | torqueFn(dy0) 47 | cuda.Madd2(y, y0, dy0, 1, dt) // y = y0 + dt * dy 48 | M.normalize() 49 | 50 | // One iteration 51 | torqueFn(dy1) 52 | cuda.Madd2(y, y0, dy1, 1, dt) // y = y0 + dt * dy1 53 | M.normalize() 54 | 55 | Time = t0 + Dt_si 56 | 57 | err := cuda.MaxVecDiff(dy0, dy1) * float64(dt) 58 | 59 | NSteps++ 60 | setLastErr(err) 61 | setMaxTorque(dy1) 62 | } 63 | 64 | func (s *BackwardEuler) Free() { 65 | s.dy1.Free() 66 | s.dy1 = nil 67 | } 68 | -------------------------------------------------------------------------------- /cuda/util.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "fmt" 5 | "github.com/mumax/3/cuda/cu" 6 | ) 7 | 8 | // CUDA Launch parameters. 9 | // there might be better choices for recent hardware, 10 | // but it barely makes a difference in the end. 11 | const ( 12 | BlockSize = 512 13 | TileX, TileY = 32, 32 14 | MaxGridSize = 65535 15 | ) 16 | 17 | // cuda launch configuration 18 | type config struct { 19 | Grid, Block cu.Dim3 20 | } 21 | 22 | // Make a 1D kernel launch configuration suited for N threads. 23 | func make1DConf(N int) *config { 24 | bl := cu.Dim3{X: BlockSize, Y: 1, Z: 1} 25 | 26 | n2 := divUp(N, BlockSize) // N2 blocks left 27 | nx := divUp(n2, MaxGridSize) 28 | ny := divUp(n2, nx) 29 | gr := cu.Dim3{X: nx, Y: ny, Z: 1} 30 | 31 | return &config{gr, bl} 32 | } 33 | 34 | // Make a 3D kernel launch configuration suited for N threads. 35 | func make3DConf(N [3]int) *config { 36 | bl := cu.Dim3{X: TileX, Y: TileY, Z: 1} 37 | 38 | nx := divUp(N[X], TileX) 39 | ny := divUp(N[Y], TileY) 40 | gr := cu.Dim3{X: nx, Y: ny, Z: N[Z]} 41 | 42 | return &config{gr, bl} 43 | } 44 | 45 | // integer minimum 46 | func iMin(a, b int) int { 47 | if a < b { 48 | return a 49 | } 50 | return b 51 | } 52 | 53 | // Integer division rounded up. 54 | func divUp(x, y int) int { 55 | return ((x - 1) / y) + 1 56 | } 57 | 58 | const ( 59 | X = 0 60 | Y = 1 61 | Z = 2 62 | ) 63 | 64 | func checkSize(a interface { 65 | Size() [3]int 66 | }, b ...interface { 67 | Size() [3]int 68 | }) { 69 | sa := a.Size() 70 | for _, b := range b { 71 | if b.Size() != sa { 72 | panic(fmt.Sprintf("size mismatch: %v != %v", sa, b.Size())) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /engine/ext_corepos.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | var CorePos = NewVectorValue("ext_corepos", "m", "Vortex core position (x,y) + polarization (z)", corePos) 4 | 5 | func corePos() []float64 { 6 | m := M.Buffer() 7 | m_z := m.Comp(Z).HostCopy().Scalars() 8 | s := m.Size() 9 | Nx, Ny, Nz := s[X], s[Y], s[Z] 10 | 11 | max := float32(-1.0) 12 | var maxX, maxY, maxZ int 13 | 14 | for z := 0; z < Nz; z++ { 15 | // Avoid the boundaries so the neighbor interpolation can't go out of bounds. 16 | for y := 1; y < Ny-1; y++ { 17 | for x := 1; x < Nx-1; x++ { 18 | m := abs(m_z[z][y][x]) 19 | if m > max { 20 | maxX, maxY, maxZ = x, y, z 21 | max = m 22 | } 23 | } 24 | } 25 | } 26 | 27 | pos := make([]float64, 3) 28 | mz := m_z[maxZ] 29 | 30 | // sub-cell interpolation in X and Y, but not Z 31 | pos[X] = float64(maxX) + interpolate_maxpos( 32 | max, -1, abs(mz[maxY][maxX-1]), 1, abs(mz[maxY][maxX+1])) - 33 | float64(Nx)/2 + 0.5 34 | pos[Y] = float64(maxY) + interpolate_maxpos( 35 | max, -1, abs(mz[maxY-1][maxX]), 1, abs(mz[maxY+1][maxX])) - 36 | float64(Ny)/2 + 0.5 37 | 38 | c := Mesh().CellSize() 39 | pos[X] *= c[X] 40 | pos[Y] *= c[Y] 41 | pos[Z] = float64(m_z[maxZ][maxY][maxX]) // 3rd coordinate is core polarization 42 | 43 | pos[X] += GetShiftPos() // add simulation window shift 44 | return pos 45 | } 46 | 47 | func interpolate_maxpos(f0, d1, f1, d2, f2 float32) float64 { 48 | b := (f2 - f1) / (d2 - d1) 49 | a := ((f2-f0)/d2 - (f0-f1)/(-d1)) / (d2 - d1) 50 | return float64(-b / (2 * a)) 51 | } 52 | 53 | func abs(x float32) float32 { 54 | if x > 0 { 55 | return x 56 | } else { 57 | return -x 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /cmd/mumax3-server/peers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Peer management: 4 | // portscan for peers 5 | // ping peers 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | ) 11 | 12 | var ( 13 | peers = make(map[string]*Peer) 14 | ) 15 | 16 | type Peer struct { 17 | } 18 | 19 | func AddPeer(pAddr string) { 20 | WLock() 21 | defer WUnlock() 22 | 23 | if _, ok := peers[pAddr]; !ok { 24 | log.Println("add new peer:", pAddr) 25 | peers[pAddr] = NewPeer() 26 | } 27 | } 28 | 29 | func NewPeer() *Peer { 30 | return &Peer{} 31 | } 32 | 33 | // RPC-called 34 | func Ping(peerAddr string) string { 35 | WLock() 36 | defer WUnlock() 37 | 38 | // Somebody just called my status, 39 | // and him as a peer (if not yet so). 40 | if _, ok := peers[peerAddr]; !ok { 41 | peers[peerAddr] = NewPeer() 42 | } 43 | return thisAddr 44 | } 45 | 46 | // Ping peer at address, add to peers list if he responds and is not yet added 47 | func ProbePeer(addr string) { 48 | ret, _ := RPCCall(addr, "Ping", thisAddr) 49 | if ret != "" { 50 | AddPeer(ret) 51 | } 52 | } 53 | 54 | // Scan IPs and port range for peers that respond to Ping, 55 | // add them to peers list. 56 | func FindPeers(IPs []string, minPort, maxPort int) { 57 | //log.Println("Portscan start") 58 | 59 | scanners := make(chan func()) 60 | 61 | for i := 0; i < N_SCANNERS; i++ { 62 | go func() { 63 | for f := range scanners { 64 | f() 65 | } 66 | }() 67 | } 68 | 69 | for _, ip := range IPs { 70 | for port := minPort; port <= maxPort; port++ { 71 | addr := fmt.Sprint(ip, ":", port) 72 | scanners <- func() { ProbePeer(addr) } 73 | } 74 | } 75 | close(scanners) 76 | log.Println("-- portscan done") 77 | } 78 | -------------------------------------------------------------------------------- /script/lvalue.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "go/ast" 5 | "reflect" 6 | ) 7 | 8 | // left-hand value in (single) assign statement 9 | type LValue interface { 10 | Expr 11 | SetValue(interface{}) // assigns a new value 12 | } 13 | 14 | func (w *World) compileLvalue(lhs ast.Node) LValue { 15 | switch lhs := lhs.(type) { 16 | default: 17 | panic(err(lhs.Pos(), "cannot assign to", typ(lhs))) 18 | case *ast.Ident: 19 | if l, ok := w.resolve(lhs.Pos(), lhs.Name).(LValue); ok { 20 | return l 21 | } else { 22 | panic(err(lhs.Pos(), "cannot assign to", lhs.Name)) 23 | } 24 | } 25 | } 26 | 27 | type reflectLvalue struct { 28 | elem reflect.Value 29 | } 30 | 31 | // general lvalue implementation using reflect. 32 | // lhs must be settable, e.g. address of something: 33 | // var x float64 34 | // newReflectLValue(&x) 35 | func newReflectLvalue(addr interface{}) LValue { 36 | elem := reflect.ValueOf(addr).Elem() 37 | if elem.Kind() == 0 { 38 | panic("variable/constant needs to be passed as pointer to addressable value") 39 | } 40 | return &reflectLvalue{elem} 41 | } 42 | 43 | func (l *reflectLvalue) Eval() interface{} { 44 | return l.elem.Interface() 45 | } 46 | 47 | func (l *reflectLvalue) Type() reflect.Type { 48 | return l.elem.Type() 49 | } 50 | 51 | func (l *reflectLvalue) SetValue(rvalue interface{}) { 52 | l.elem.Set(reflect.ValueOf(rvalue)) 53 | } 54 | 55 | func (l *reflectLvalue) Child() []Expr { 56 | return nil 57 | } 58 | 59 | func (l *reflectLvalue) Fix() Expr { 60 | return NewConst(l) 61 | } 62 | 63 | type TVar struct { 64 | LValue 65 | } 66 | 67 | func (t *TVar) Fix() Expr { 68 | return t // only variable that's not fixed 69 | } 70 | -------------------------------------------------------------------------------- /cuda/shift.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // shift dst by shx cells (positive or negative) along X-axis. 9 | // new edge value is clampL at left edge or clampR at right edge. 10 | func ShiftX(dst, src *data.Slice, shiftX int, clampL, clampR float32) { 11 | util.Argument(dst.NComp() == 1 && src.NComp() == 1) 12 | util.Assert(dst.Len() == src.Len()) 13 | N := dst.Size() 14 | cfg := make3DConf(N) 15 | k_shiftx_async(dst.DevPtr(0), src.DevPtr(0), N[X], N[Y], N[Z], shiftX, clampL, clampR, cfg) 16 | } 17 | 18 | func ShiftY(dst, src *data.Slice, shiftY int, clampL, clampR float32) { 19 | util.Argument(dst.NComp() == 1 && src.NComp() == 1) 20 | util.Assert(dst.Len() == src.Len()) 21 | N := dst.Size() 22 | cfg := make3DConf(N) 23 | k_shifty_async(dst.DevPtr(0), src.DevPtr(0), N[X], N[Y], N[Z], shiftY, clampL, clampR, cfg) 24 | } 25 | 26 | func ShiftZ(dst, src *data.Slice, shiftZ int, clampL, clampR float32) { 27 | util.Argument(dst.NComp() == 1 && src.NComp() == 1) 28 | util.Assert(dst.Len() == src.Len()) 29 | N := dst.Size() 30 | cfg := make3DConf(N) 31 | k_shiftz_async(dst.DevPtr(0), src.DevPtr(0), N[X], N[Y], N[Z], shiftZ, clampL, clampR, cfg) 32 | } 33 | 34 | // Like Shift, but for bytes 35 | func ShiftBytes(dst, src *Bytes, m *data.Mesh, shiftX int, clamp byte) { 36 | N := m.Size() 37 | cfg := make3DConf(N) 38 | k_shiftbytes_async(dst.Ptr, src.Ptr, N[X], N[Y], N[Z], shiftX, clamp, cfg) 39 | } 40 | 41 | func ShiftBytesY(dst, src *Bytes, m *data.Mesh, shiftY int, clamp byte) { 42 | N := m.Size() 43 | cfg := make3DConf(N) 44 | k_shiftbytesy_async(dst.Ptr, src.Ptr, N[X], N[Y], N[Z], shiftY, clamp, cfg) 45 | } 46 | -------------------------------------------------------------------------------- /cuda/exchangedecode.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include "stencil.h" 3 | #include "float3.h" 4 | #include "exchange.h" 5 | 6 | // see exchange.go 7 | extern "C" __global__ void 8 | exchangedecode(float* __restrict__ dst, float* __restrict__ aLUT2d, uint8_t* __restrict__ regions, 9 | float wx, float wy, float wz, int Nx, int Ny, int Nz, uint8_t PBC) { 10 | 11 | int ix = blockIdx.x * blockDim.x + threadIdx.x; 12 | int iy = blockIdx.y * blockDim.y + threadIdx.y; 13 | int iz = blockIdx.z * blockDim.z + threadIdx.z; 14 | 15 | if (ix >= Nx || iy >= Ny || iz >= Nz) { 16 | return; 17 | } 18 | 19 | // central cell 20 | int I = idx(ix, iy, iz); 21 | uint8_t r0 = regions[I]; 22 | 23 | int i_; // neighbor index 24 | float avg = 0.0f; 25 | 26 | // left neighbor 27 | i_ = idx(lclampx(ix-1), iy, iz); // clamps or wraps index according to PBC 28 | avg += aLUT2d[symidx(r0, regions[i_])]; 29 | 30 | // right neighbor 31 | i_ = idx(hclampx(ix+1), iy, iz); 32 | avg += aLUT2d[symidx(r0, regions[i_])]; 33 | 34 | // back neighbor 35 | i_ = idx(ix, lclampy(iy-1), iz); 36 | avg += aLUT2d[symidx(r0, regions[i_])]; 37 | 38 | // front neighbor 39 | i_ = idx(ix, hclampy(iy+1), iz); 40 | avg += aLUT2d[symidx(r0, regions[i_])]; 41 | 42 | // only take vertical derivative for 3D sim 43 | if (Nz != 1) { 44 | // bottom neighbor 45 | i_ = idx(ix, iy, lclampz(iz-1)); 46 | avg += aLUT2d[symidx(r0, regions[i_])]; 47 | 48 | // top neighbor 49 | i_ = idx(ix, iy, hclampz(iz+1)); 50 | avg += aLUT2d[symidx(r0, regions[i_])]; 51 | } 52 | 53 | dst[I] = avg; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /draw/hslscale.go: -------------------------------------------------------------------------------- 1 | package draw 2 | 3 | import ( 4 | "image/color" 5 | "math" 6 | ) 7 | 8 | // Colormap for 3D vector data. 9 | func HSLMap(x, y, z float32) color.RGBA { 10 | s := sqrtf(x*x + y*y + z*z) 11 | l := 0.5*z + 0.5 12 | h := float32(math.Atan2(float64(y), float64(x))) 13 | return HSLtoRGB(h, s, l) 14 | } 15 | 16 | // h = 0..2pi, s=0..1, l=0..1 17 | func HSLtoRGB(h, s, l float32) color.RGBA { 18 | if s > 1 { 19 | s = 1 20 | } 21 | if l > 1 { 22 | l = 1 23 | } 24 | 25 | h = h * (180.0 / math.Pi / 60.0) 26 | for h < 0 { 27 | h += 6 28 | } 29 | for h >= 6 { 30 | h -= 6 31 | } 32 | 33 | var c float32 // chroma 34 | if l <= 0.5 { 35 | c = 2 * l * s 36 | } else { 37 | c = (2 - 2*l) * s 38 | } 39 | x := c * (1 - abs(fmod(h, 2)-1)) 40 | 41 | var r, g, b float32 42 | 43 | switch { 44 | case 0 <= h && h < 1: 45 | r, g, b = c, x, 0. 46 | case 1 <= h && h < 2: 47 | r, g, b = x, c, 0. 48 | case 2 <= h && h < 3: 49 | r, g, b = 0., c, x 50 | case 3 <= h && h < 4: 51 | r, g, b = 0, x, c 52 | case 4 <= h && h < 5: 53 | r, g, b = x, 0., c 54 | case 5 <= h && h < 6: 55 | r, g, b = c, 0., x 56 | } 57 | 58 | m := l - 0.5*c 59 | r, g, b = r+m, g+m, b+m 60 | R, G, B := uint8(255*r), uint8(255*g), uint8(255*b) 61 | return color.RGBA{R, G, B, 255} 62 | } 63 | 64 | // modulo 65 | func fmod(number, mod float32) float32 { 66 | for number < mod { 67 | number += mod 68 | } 69 | for number >= mod { 70 | number -= mod 71 | } 72 | return number 73 | } 74 | 75 | func abs(number float32) float32 { 76 | if number < 0 { 77 | return -number 78 | } // else 79 | return number 80 | } 81 | 82 | func sqrtf(x float32) float32 { 83 | return float32(math.Sqrt(float64(x))) 84 | } 85 | -------------------------------------------------------------------------------- /engine/gofiles.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | // support for running Go files as if they were mx3 files. 4 | 5 | import ( 6 | "flag" 7 | "github.com/mumax/3/cuda" 8 | "github.com/mumax/3/util" 9 | "os" 10 | "path" 11 | ) 12 | 13 | var ( 14 | // These flags are shared between cmd/mumax3 and Go input files. 15 | Flag_cachedir = flag.String("cache", os.TempDir(), "Kernel cache directory (empty disables caching)") 16 | Flag_gpu = flag.Int("gpu", 0, "Specify GPU") 17 | Flag_interactive = flag.Bool("i", false, "Open interactive browser session") 18 | Flag_od = flag.String("o", "", "Override output directory") 19 | Flag_port = flag.String("http", ":35367", "Port to serve web gui") 20 | Flag_selftest = flag.Bool("paranoid", false, "Enable convolution self-test for cuFFT sanity.") 21 | Flag_silent = flag.Bool("s", false, "Silent") // provided for backwards compatibility 22 | Flag_sync = flag.Bool("sync", false, "Synchronize all CUDA calls (debug)") 23 | Flag_forceclean = flag.Bool("f", false, "Force start, clean existing output directory") 24 | ) 25 | 26 | // Usage: in every Go input file, write: 27 | // 28 | // func main(){ 29 | // defer InitAndClose()() 30 | // // ... 31 | // } 32 | // 33 | // This initialises the GPU, output directory, etc, 34 | // and makes sure pending output will get flushed. 35 | func InitAndClose() func() { 36 | 37 | flag.Parse() 38 | 39 | cuda.Init(*Flag_gpu) 40 | cuda.Synchronous = *Flag_sync 41 | 42 | od := *Flag_od 43 | if od == "" { 44 | od = path.Base(os.Args[0]) + ".out" 45 | } 46 | inFile := util.NoExt(od) 47 | InitIO(inFile, od, *Flag_forceclean) 48 | 49 | GoServe(*Flag_port) 50 | 51 | return func() { 52 | Close() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /cuda/magnetoelastic.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "github.com/mumax/3/data" 5 | "github.com/mumax/3/util" 6 | ) 7 | 8 | // Add magneto-elasticit coupling field to the effective field. 9 | // see magnetoelasticfield.cu 10 | func AddMagnetoelasticField(Beff, m *data.Slice, exx, eyy, ezz, exy, exz, eyz, B1, B2, Msat MSlice) { 11 | util.Argument(Beff.Size() == m.Size()) 12 | util.Argument(Beff.Size() == exx.Size()) 13 | util.Argument(Beff.Size() == eyy.Size()) 14 | util.Argument(Beff.Size() == ezz.Size()) 15 | util.Argument(Beff.Size() == exy.Size()) 16 | util.Argument(Beff.Size() == exz.Size()) 17 | util.Argument(Beff.Size() == eyz.Size()) 18 | 19 | N := Beff.Len() 20 | cfg := make1DConf(N) 21 | 22 | k_addmagnetoelasticfield_async(Beff.DevPtr(X), Beff.DevPtr(Y), Beff.DevPtr(Z), 23 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 24 | exx.DevPtr(0), exx.Mul(0), eyy.DevPtr(0), eyy.Mul(0), ezz.DevPtr(0), ezz.Mul(0), 25 | exy.DevPtr(0), exy.Mul(0), exz.DevPtr(0), exz.Mul(0), eyz.DevPtr(0), eyz.Mul(0), 26 | B1.DevPtr(0), B1.Mul(0), B2.DevPtr(0), B2.Mul(0), 27 | Msat.DevPtr(0), Msat.Mul(0), 28 | N, cfg) 29 | } 30 | 31 | // Calculate magneto-elasticit force density 32 | // see magnetoelasticforce.cu 33 | func GetMagnetoelasticForceDensity(out, m *data.Slice, B1, B2 MSlice, mesh *data.Mesh) { 34 | util.Argument(out.Size() == m.Size()) 35 | 36 | cellsize := mesh.CellSize() 37 | N := mesh.Size() 38 | cfg := make3DConf(N) 39 | 40 | rcsx := float32(1.0 / cellsize[X]) 41 | rcsy := float32(1.0 / cellsize[Y]) 42 | rcsz := float32(1.0 / cellsize[Z]) 43 | 44 | k_getmagnetoelasticforce_async(out.DevPtr(X), out.DevPtr(Y), out.DevPtr(Z), 45 | m.DevPtr(X), m.DevPtr(Y), m.DevPtr(Z), 46 | B1.DevPtr(0), B1.Mul(0), B2.DevPtr(0), B2.Mul(0), 47 | rcsx, rcsy, rcsz, 48 | N[X], N[Y], N[Z], 49 | mesh.PBC_code(), cfg) 50 | } 51 | -------------------------------------------------------------------------------- /doc/static/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin-left: 10%; 3 | margin-right: 10%; 4 | margin-top: 2em; 5 | font-family: sans-serif; 6 | } 7 | 8 | h1 { 9 | color: #000088 10 | } 11 | 12 | h2 { 13 | font-size: 18px; 14 | color: #000088 15 | } 16 | 17 | h3 { 18 | font-size: 15px; 19 | font-weight: normal; 20 | color: #000088 21 | } 22 | 23 | table { 24 | border: "10"; 25 | } 26 | 27 | hr { 28 | border-style: none; 29 | border-top: 1px solid #CCCCCC; 30 | margin-top: 10px; 31 | margin-bottom: 10px 32 | } 33 | 34 | a { 35 | color: #375EAB; 36 | text-decoration: none; 37 | } 38 | 39 | div { 40 | margin-left: 20px; 41 | margin-top: 10px; 42 | margin-bottom: 20px; 43 | } 44 | 45 | div#footer { 46 | color: #555555 47 | } 48 | 49 | pre { 50 | margin-left: 50px; 51 | margin-top: 10px; 52 | margin-bottom: 20px; 53 | color: #000044; 54 | font-size: 12px; 55 | background-color: #EEEEFF; 56 | padding: 10px; 57 | } 58 | 59 | figure { 60 | margin-left: 2px; 61 | margin-top: 2px; 62 | margin-bottom: 2px; 63 | padding: 2px; 64 | } 65 | 66 | figcaption { 67 | color: #555555 68 | } 69 | 70 | .api-section-link { 71 | padding-top: 0.2ex; 72 | padding-bottom: 0.2ex; 73 | padding-left: 10px 74 | } 75 | 76 | .api-container { 77 | display: flex; 78 | margin: 0px; 79 | padding: 0px; 80 | } 81 | 82 | .api-menu { 83 | float: left; 84 | display: block; 85 | width: 250px; 86 | background-color: #E0E0E0; 87 | padding: 20px; 88 | margin: 0px; 89 | } 90 | 91 | .api-content { 92 | float: left; 93 | flex: 1; 94 | min-width: 400px" 95 | 96 | } 97 | 98 | .api-entry { 99 | display:inline; 100 | margin: 0px; 101 | } -------------------------------------------------------------------------------- /draw/encode.go: -------------------------------------------------------------------------------- 1 | package draw 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "github.com/mumax/3/data" 7 | "image" 8 | "image/gif" 9 | "image/jpeg" 10 | "image/png" 11 | "io" 12 | "os" 13 | "path" 14 | "strings" 15 | ) 16 | 17 | func RenderFile(fname string, f *data.Slice, min, max string, arrowSize int, colormap ...ColorMapSpec) error { 18 | out, err := os.Create(fname) 19 | if err != nil { 20 | return err 21 | } 22 | defer out.Close() 23 | return RenderFormat(out, f, min, max, arrowSize, fname, colormap...) 24 | } 25 | 26 | func RenderFormat(out io.Writer, f *data.Slice, min, max string, arrowSize int, format string, colormap ...ColorMapSpec) error { 27 | var codecs = map[string]codec{".png": PNG, ".jpg": JPEG100, ".gif": GIF256} 28 | ext := strings.ToLower(path.Ext(format)) 29 | enc := codecs[ext] 30 | if enc == nil { 31 | return fmt.Errorf("render: unhandled image type: " + ext) 32 | } 33 | return Render(out, f, min, max, arrowSize, enc, colormap...) 34 | } 35 | 36 | // encodes an image 37 | type codec func(io.Writer, image.Image) error 38 | 39 | // Render data and encode with arbitrary codec. 40 | func Render(out io.Writer, f *data.Slice, min, max string, arrowSize int, encode codec, colormap ...ColorMapSpec) error { 41 | img := Image(f, min, max, arrowSize, colormap...) 42 | buf := bufio.NewWriter(out) 43 | defer buf.Flush() 44 | return encode(buf, img) 45 | } 46 | 47 | // full-quality jpeg codec, passable to Render() 48 | func JPEG100(w io.Writer, img image.Image) error { 49 | return jpeg.Encode(w, img, &jpeg.Options{100}) 50 | } 51 | 52 | // full quality gif coded, passable to Render() 53 | func GIF256(w io.Writer, img image.Image) error { 54 | return gif.Encode(w, img, &gif.Options{256, nil, nil}) 55 | } 56 | 57 | // png codec, passable to Render() 58 | func PNG(w io.Writer, img image.Image) error { 59 | return png.Encode(w, img) 60 | } 61 | -------------------------------------------------------------------------------- /cuda/curand/generator.go: -------------------------------------------------------------------------------- 1 | package curand 2 | 3 | //#include 4 | import "C" 5 | 6 | import ( 7 | "unsafe" 8 | ) 9 | 10 | type Generator uintptr 11 | 12 | type RngType int 13 | 14 | const ( 15 | PSEUDO_DEFAULT RngType = C.CURAND_RNG_PSEUDO_DEFAULT // Default pseudorandom generator 16 | PSEUDO_XORWOW RngType = C.CURAND_RNG_PSEUDO_XORWOW // XORWOW pseudorandom generator 17 | QUASI_DEFAULT RngType = C.CURAND_RNG_QUASI_DEFAULT // Default quasirandom generator 18 | QUASI_SOBOL32 RngType = C.CURAND_RNG_QUASI_SOBOL32 // Sobol32 quasirandom generator 19 | QUASI_SCRAMBLED_SOBOL32 RngType = C.CURAND_RNG_QUASI_SCRAMBLED_SOBOL32 // Scrambled Sobol32 quasirandom generator 20 | QUASI_SOBOL64 RngType = C.CURAND_RNG_QUASI_SOBOL64 // Sobol64 quasirandom generator 21 | QUASI_SCRAMBLED_SOBOL64 RngType = C.CURAND_RNG_QUASI_SCRAMBLED_SOBOL64 // Scrambled Sobol64 quasirandom generator 22 | ) 23 | 24 | func CreateGenerator(rngType RngType) Generator { 25 | var rng C.curandGenerator_t 26 | err := Status(C.curandCreateGenerator(&rng, C.curandRngType_t(rngType))) 27 | if err != SUCCESS { 28 | panic(err) 29 | } 30 | return Generator(uintptr(unsafe.Pointer(rng))) // cgo 31 | } 32 | 33 | func (g Generator) GenerateNormal(output uintptr, n int64, mean, stddev float32) { 34 | err := Status(C.curandGenerateNormal( 35 | C.curandGenerator_t(unsafe.Pointer(uintptr(g))), 36 | (*C.float)(unsafe.Pointer(output)), 37 | C.size_t(n), 38 | C.float(mean), 39 | C.float(stddev))) 40 | if err != SUCCESS { 41 | panic(err) 42 | } 43 | } 44 | 45 | func (g Generator) SetSeed(seed int64) { 46 | err := Status(C.curandSetPseudoRandomGeneratorSeed(C.curandGenerator_t(unsafe.Pointer(uintptr(g))), C.ulonglong(seed))) 47 | if err != SUCCESS { 48 | panic(err) 49 | } 50 | } 51 | 52 | // Documentation was taken from the curand headers. 53 | -------------------------------------------------------------------------------- /httpfs/reader.go: -------------------------------------------------------------------------------- 1 | package httpfs 2 | 3 | // Utility functions on top of standard httpfs protocol 4 | 5 | import ( 6 | "bufio" 7 | "bytes" 8 | "io" 9 | "io/ioutil" 10 | ) 11 | 12 | const BUFSIZE = 16 * 1024 * 1024 // bufio buffer size 13 | 14 | // create a file for writing, clobbers previous content if any. 15 | func Create(URL string) (WriteCloseFlusher, error) { 16 | _ = Remove(URL) 17 | err := Touch(URL) 18 | if err != nil { 19 | return nil, err 20 | } 21 | return &bufWriter{bufio.NewWriterSize(&appendWriter{URL, 0}, BUFSIZE)}, nil 22 | } 23 | 24 | func MustCreate(URL string) WriteCloseFlusher { 25 | f, err := Create(URL) 26 | if err != nil { 27 | panic(err) 28 | } 29 | return f 30 | } 31 | 32 | type WriteCloseFlusher interface { 33 | io.WriteCloser 34 | Flush() error 35 | } 36 | 37 | // open a file for reading 38 | func Open(URL string) (io.ReadCloser, error) { 39 | data, err := Read(URL) 40 | if err != nil { 41 | return nil, err 42 | } 43 | return ioutil.NopCloser(bytes.NewReader(data)), nil 44 | } 45 | 46 | func MustOpen(URL string) io.ReadCloser { 47 | f, err := Open(URL) 48 | if err != nil { 49 | panic(err) 50 | } 51 | return f 52 | } 53 | 54 | type bufWriter struct { 55 | buf *bufio.Writer 56 | } 57 | 58 | func (w *bufWriter) Write(p []byte) (int, error) { return w.buf.Write(p) } 59 | func (w *bufWriter) Close() error { 60 | err := w.buf.Flush() 61 | w.buf = nil // Dangling pointer somewhere? 62 | if err != nil { 63 | return err 64 | } 65 | return nil 66 | } 67 | func (w *bufWriter) Flush() error { return w.buf.Flush() } 68 | 69 | type appendWriter struct { 70 | URL string 71 | byteCount int64 72 | } 73 | 74 | func (w *appendWriter) Write(p []byte) (int, error) { 75 | err := AppendSize(w.URL, p, w.byteCount) 76 | if err != nil { 77 | return 0, err // don't know how many bytes written 78 | } 79 | w.byteCount += int64(len(p)) 80 | return len(p), nil 81 | } 82 | -------------------------------------------------------------------------------- /engine/rk4.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "github.com/mumax/3/cuda" 5 | "github.com/mumax/3/data" 6 | "github.com/mumax/3/util" 7 | "math" 8 | ) 9 | 10 | // Classical 4th order RK solver. 11 | type RK4 struct { 12 | } 13 | 14 | func (rk *RK4) Step() { 15 | m := M.Buffer() 16 | size := m.Size() 17 | 18 | if FixDt != 0 { 19 | Dt_si = FixDt 20 | } 21 | 22 | t0 := Time 23 | // backup magnetization 24 | m0 := cuda.Buffer(3, size) 25 | defer cuda.Recycle(m0) 26 | data.Copy(m0, m) 27 | 28 | k1, k2, k3, k4 := cuda.Buffer(3, size), cuda.Buffer(3, size), cuda.Buffer(3, size), cuda.Buffer(3, size) 29 | 30 | defer cuda.Recycle(k1) 31 | defer cuda.Recycle(k2) 32 | defer cuda.Recycle(k3) 33 | defer cuda.Recycle(k4) 34 | 35 | h := float32(Dt_si * GammaLL) // internal time step = Dt * gammaLL 36 | 37 | // stage 1 38 | torqueFn(k1) 39 | 40 | // stage 2 41 | Time = t0 + (1./2.)*Dt_si 42 | cuda.Madd2(m, m, k1, 1, (1./2.)*h) // m = m*1 + k1*h/2 43 | M.normalize() 44 | torqueFn(k2) 45 | 46 | // stage 3 47 | cuda.Madd2(m, m0, k2, 1, (1./2.)*h) // m = m0*1 + k2*1/2 48 | M.normalize() 49 | torqueFn(k3) 50 | 51 | // stage 4 52 | Time = t0 + Dt_si 53 | cuda.Madd2(m, m0, k3, 1, 1.*h) // m = m0*1 + k3*1 54 | M.normalize() 55 | torqueFn(k4) 56 | 57 | err := cuda.MaxVecDiff(k1, k4) * float64(h) 58 | 59 | // adjust next time step 60 | if err < MaxErr || Dt_si <= MinDt || FixDt != 0 { // mindt check to avoid infinite loop 61 | // step OK 62 | // 4th order solution 63 | cuda.Madd5(m, m0, k1, k2, k3, k4, 1, (1./6.)*h, (1./3.)*h, (1./3.)*h, (1./6.)*h) 64 | M.normalize() 65 | NSteps++ 66 | adaptDt(math.Pow(MaxErr/err, 1./4.)) 67 | setLastErr(err) 68 | setMaxTorque(k4) 69 | } else { 70 | // undo bad step 71 | util.Assert(FixDt == 0) 72 | Time = t0 73 | data.Copy(m, m0) 74 | NUndone++ 75 | adaptDt(math.Pow(MaxErr/err, 1./5.)) 76 | } 77 | } 78 | 79 | func (_ *RK4) Free() {} 80 | -------------------------------------------------------------------------------- /cuda/conv_common.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | // common code for all convolutions. 4 | 5 | import ( 6 | "log" 7 | "math" 8 | 9 | "github.com/mumax/3/data" 10 | "github.com/mumax/3/util" 11 | ) 12 | 13 | // Output size of R2C FFT with given logic size, expressed in floats. 14 | func fftR2COutputSizeFloats(logicSize [3]int) [3]int { 15 | return [3]int{2 * (logicSize[X]/2 + 1), logicSize[Y], logicSize[Z]} 16 | } 17 | 18 | // product of elements 19 | func prod(size [3]int) int { 20 | return size[X] * size[Y] * size[Z] 21 | } 22 | 23 | // Extract real parts, copy them from src to dst. 24 | // In the meanwhile, check if imaginary parts are nearly zero 25 | // and scale the kernel to compensate for unnormalized FFTs. 26 | // scale = 1/N, with N the FFT logical size. 27 | func scaleRealParts(dst, src *data.Slice, scale float32) { 28 | util.Argument(2*dst.Len() == src.Len()) 29 | util.Argument(dst.NComp() == 1 && src.NComp() == 1) 30 | 31 | srcList := src.Host()[0] 32 | dstList := dst.Host()[0] 33 | 34 | // Normally, the FFT'ed kernel is purely real because of symmetry, 35 | // so we only store the real parts... 36 | maximg := float32(0.) 37 | for i := 0; i < src.Len()/2; i++ { 38 | dstList[i] = srcList[2*i] * scale 39 | if fabs(srcList[2*i+1]) > maximg { 40 | maximg = fabs(srcList[2*i+1]) 41 | } 42 | } 43 | maximg *= float32(math.Sqrt(float64(scale))) // after 1 FFT, normalization is sqrt(N) 44 | 45 | // ...however, we check that the imaginary parts are nearly zero, 46 | // just to be sure we did not make a mistake during kernel creation. 47 | if maximg > FFT_IMAG_TOLERANCE { 48 | log.Fatalf("FFT kernel imaginary part: %v\n", maximg) 49 | } 50 | } 51 | 52 | // Maximum tolerable imaginary/real part for demag kernel in Fourier space. Assures kernel has correct symmetry. 53 | const FFT_IMAG_TOLERANCE = 1e-6 54 | 55 | // float32 absolute value 56 | func fabs(x float32) float32 { 57 | if x < 0 { 58 | return -x 59 | } 60 | return x 61 | } 62 | -------------------------------------------------------------------------------- /cuda/fft3dc2r.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/mumax/3/cuda/cu" 7 | "github.com/mumax/3/cuda/cufft" 8 | "github.com/mumax/3/data" 9 | "github.com/mumax/3/timer" 10 | ) 11 | 12 | // 3D single-precission real-to-complex FFT plan. 13 | type fft3DC2RPlan struct { 14 | fftplan 15 | size [3]int 16 | } 17 | 18 | // 3D single-precission real-to-complex FFT plan. 19 | func newFFT3DC2R(Nx, Ny, Nz int) fft3DC2RPlan { 20 | handle := cufft.Plan3d(Nz, Ny, Nx, cufft.C2R) // new xyz swap 21 | handle.SetStream(stream0) 22 | return fft3DC2RPlan{fftplan{handle}, [3]int{Nx, Ny, Nz}} 23 | } 24 | 25 | // Execute the FFT plan, asynchronous. 26 | // src and dst are 3D arrays stored 1D arrays. 27 | func (p *fft3DC2RPlan) ExecAsync(src, dst *data.Slice) { 28 | if Synchronous { 29 | Sync() 30 | timer.Start("fft") 31 | } 32 | oksrclen := p.InputLenFloats() 33 | if src.Len() != oksrclen { 34 | panic(fmt.Errorf("fft size mismatch: expecting src len %v, got %v", oksrclen, src.Len())) 35 | } 36 | okdstlen := p.OutputLenFloats() 37 | if dst.Len() != okdstlen { 38 | panic(fmt.Errorf("fft size mismatch: expecting dst len %v, got %v", okdstlen, dst.Len())) 39 | } 40 | p.handle.ExecC2R(cu.DevicePtr(uintptr(src.DevPtr(0))), cu.DevicePtr(uintptr(dst.DevPtr(0)))) 41 | if Synchronous { 42 | Sync() 43 | timer.Stop("fft") 44 | } 45 | } 46 | 47 | // 3D size of the input array. 48 | func (p *fft3DC2RPlan) InputSizeFloats() (Nx, Ny, Nz int) { 49 | return 2 * (p.size[X]/2 + 1), p.size[Y], p.size[Z] 50 | } 51 | 52 | // 3D size of the output array. 53 | func (p *fft3DC2RPlan) OutputSizeFloats() (Nx, Ny, Nz int) { 54 | return p.size[X], p.size[Y], p.size[Z] 55 | } 56 | 57 | // Required length of the (1D) input array. 58 | func (p *fft3DC2RPlan) InputLenFloats() int { 59 | return prod3(p.InputSizeFloats()) 60 | } 61 | 62 | // Required length of the (1D) output array. 63 | func (p *fft3DC2RPlan) OutputLenFloats() int { 64 | return prod3(p.OutputSizeFloats()) 65 | } 66 | -------------------------------------------------------------------------------- /cuda/magnetoelasticfield.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "amul.h" 4 | #include "float3.h" 5 | 6 | // Add magneto-elastic coupling field to B. 7 | // H = - δUmel / δM, 8 | // where Umel is magneto-elastic energy denstiy given by the eq. (12.18) of Gurevich&Melkov "Magnetization Oscillations and Waves", CRC Press, 1996 9 | extern "C" __global__ void 10 | addmagnetoelasticfield(float* __restrict__ Bx, float* __restrict__ By, float* __restrict__ Bz, 11 | float* __restrict__ mx, float* __restrict__ my, float* __restrict__ mz, 12 | float* __restrict__ exx_, float exx_mul, 13 | float* __restrict__ eyy_, float eyy_mul, 14 | float* __restrict__ ezz_, float ezz_mul, 15 | float* __restrict__ exy_, float exy_mul, 16 | float* __restrict__ exz_, float exz_mul, 17 | float* __restrict__ eyz_, float eyz_mul, 18 | float* __restrict__ B1_, float B1_mul, 19 | float* __restrict__ B2_, float B2_mul, 20 | float* __restrict__ Ms_, float Ms_mul, 21 | int N) { 22 | 23 | int I = ( blockIdx.y*gridDim.x + blockIdx.x ) * blockDim.x + threadIdx.x; 24 | 25 | if (I < N) { 26 | 27 | float Exx = amul(exx_, exx_mul, I); 28 | float Eyy = amul(eyy_, eyy_mul, I); 29 | float Ezz = amul(ezz_, ezz_mul, I); 30 | 31 | float Exy = amul(exy_, exy_mul, I); 32 | float Eyx = Exy; 33 | 34 | float Exz = amul(exz_, exz_mul, I); 35 | float Ezx = Exz; 36 | 37 | float Eyz = amul(eyz_, eyz_mul, I); 38 | float Ezy = Eyz; 39 | 40 | float invMs = inv_Msat(Ms_, Ms_mul, I); 41 | 42 | float B1 = amul(B1_, B1_mul, I) * invMs; 43 | float B2 = amul(B2_, B2_mul, I) * invMs; 44 | 45 | float3 m = {mx[I], my[I], mz[I]}; 46 | 47 | Bx[I] += -(2.0f*B1*m.x*Exx + B2*(m.y*Exy + m.z*Exz)); 48 | By[I] += -(2.0f*B1*m.y*Eyy + B2*(m.x*Eyx + m.z*Eyz)); 49 | Bz[I] += -(2.0f*B1*m.z*Ezz + B2*(m.x*Ezx + m.y*Ezy)); 50 | } 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /cuda/cu/function.go: -------------------------------------------------------------------------------- 1 | package cu 2 | 3 | // This file implements manipulations on CUDA functions 4 | 5 | //#include 6 | import "C" 7 | 8 | import ( 9 | "unsafe" 10 | ) 11 | 12 | // Represents a CUDA CUfunction, a reference to a function within a module. 13 | type Function uintptr 14 | 15 | func FuncGetAttribute(attrib FunctionAttribute, function Function) int { 16 | var attr C.int 17 | err := Result(C.cuFuncGetAttribute(&attr, C.CUfunction_attribute(attrib), C.CUfunction(unsafe.Pointer(uintptr(function))))) 18 | if err != SUCCESS { 19 | panic(err) 20 | } 21 | return int(attr) 22 | } 23 | 24 | func (f Function) GetAttribute(attrib FunctionAttribute) int { 25 | return FuncGetAttribute(attrib, f) 26 | } 27 | 28 | type FunctionAttribute int 29 | 30 | const ( 31 | FUNC_A_MAX_THREADS_PER_BLOCK FunctionAttribute = C.CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK // The maximum number of threads per block, beyond which a launch of the function would fail. 32 | FUNC_A_SHARED_SIZE_BYTES FunctionAttribute = C.CU_FUNC_ATTRIBUTE_SHARED_SIZE_BYTES // The size in bytes of statically-allocated shared memory required by this function. 33 | FUNC_A_CONST_SIZE_BYTES FunctionAttribute = C.CU_FUNC_ATTRIBUTE_CONST_SIZE_BYTES // The size in bytes of user-allocated constant memory required by this function. 34 | FUNC_A_LOCAL_SIZE_BYTES FunctionAttribute = C.CU_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES // The size in bytes of local memory used by each thread of this function. 35 | FUNC_A_NUM_REGS FunctionAttribute = C.CU_FUNC_ATTRIBUTE_NUM_REGS // The number of registers used by each thread of this function. 36 | FUNC_A_PTX_VERSION FunctionAttribute = C.CU_FUNC_ATTRIBUTE_PTX_VERSION // The PTX virtual architecture version for which the function was compiled. 37 | FUNC_A_BINARY_VERSION FunctionAttribute = C.CU_FUNC_ATTRIBUTE_BINARY_VERSION // The binary architecture version for which the function was compiled. 38 | ) 39 | -------------------------------------------------------------------------------- /engine/energy.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | // Total energy calculation 4 | 5 | import ( 6 | "github.com/mumax/3/cuda" 7 | "github.com/mumax/3/data" 8 | ) 9 | 10 | // TODO: Integrate(Edens) 11 | // TODO: consistent naming SetEdensTotal, ... 12 | 13 | var ( 14 | energyTerms []func() float64 // all contributions to total energy 15 | edensTerms []func(dst *data.Slice) // all contributions to total energy density (add to dst) 16 | Edens_total = NewScalarField("Edens_total", "J/m3", "Total energy density", SetTotalEdens) 17 | E_total = NewScalarValue("E_total", "J", "total energy", GetTotalEnergy) 18 | ) 19 | 20 | // add energy term to global energy 21 | func registerEnergy(term func() float64, dens func(*data.Slice)) { 22 | energyTerms = append(energyTerms, term) 23 | edensTerms = append(edensTerms, dens) 24 | } 25 | 26 | // Returns the total energy in J. 27 | func GetTotalEnergy() float64 { 28 | E := 0. 29 | for _, f := range energyTerms { 30 | E += f() 31 | } 32 | checkNaN1(E) 33 | return E 34 | } 35 | 36 | // Set dst to total energy density in J/m3 37 | func SetTotalEdens(dst *data.Slice) { 38 | cuda.Zero(dst) 39 | for _, addTerm := range edensTerms { 40 | addTerm(dst) 41 | } 42 | } 43 | 44 | // volume of one cell in m3 45 | func cellVolume() float64 { 46 | c := Mesh().CellSize() 47 | return c[0] * c[1] * c[2] 48 | } 49 | 50 | // returns a function that adds to dst the energy density: 51 | // prefactor * dot (M_full, field) 52 | func makeEdensAdder(field Quantity, prefactor float64) func(*data.Slice) { 53 | return func(dst *data.Slice) { 54 | B := ValueOf(field) 55 | defer cuda.Recycle(B) 56 | m := ValueOf(M_full) 57 | defer cuda.Recycle(m) 58 | factor := float32(prefactor) 59 | cuda.AddDotProduct(dst, factor, B, m) 60 | } 61 | } 62 | 63 | // vector dot product 64 | func dot(a, b Quantity) float64 { 65 | A := ValueOf(a) 66 | defer cuda.Recycle(A) 67 | B := ValueOf(b) 68 | defer cuda.Recycle(B) 69 | return float64(cuda.Dot(A, B)) 70 | } 71 | -------------------------------------------------------------------------------- /cuda/conv_kernmul.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | // Kernel multiplication for purely real kernel, symmetric around Y axis (apart from first row). 4 | // Launch configs range over all complex elements of fft input. This could be optimized: range only over kernel. 5 | 6 | import ( 7 | "github.com/mumax/3/data" 8 | "github.com/mumax/3/util" 9 | ) 10 | 11 | // kernel multiplication for 3D demag convolution, exploiting full kernel symmetry. 12 | func kernMulRSymm3D_async(fftM [3]*data.Slice, Kxx, Kyy, Kzz, Kyz, Kxz, Kxy *data.Slice, Nx, Ny, Nz int) { 13 | util.Argument(fftM[X].NComp() == 1 && Kxx.NComp() == 1) 14 | 15 | cfg := make3DConf([3]int{Nx, Ny, Nz}) 16 | k_kernmulRSymm3D_async(fftM[X].DevPtr(0), fftM[Y].DevPtr(0), fftM[Z].DevPtr(0), 17 | Kxx.DevPtr(0), Kyy.DevPtr(0), Kzz.DevPtr(0), Kyz.DevPtr(0), Kxz.DevPtr(0), Kxy.DevPtr(0), 18 | Nx, Ny, Nz, cfg) 19 | } 20 | 21 | // kernel multiplication for 2D demag convolution on X and Y, exploiting full kernel symmetry. 22 | func kernMulRSymm2Dxy_async(fftMx, fftMy, Kxx, Kyy, Kxy *data.Slice, Nx, Ny int) { 23 | util.Argument(fftMy.NComp() == 1 && Kxx.NComp() == 1) 24 | 25 | cfg := make3DConf([3]int{Nx, Ny, 1}) 26 | k_kernmulRSymm2Dxy_async(fftMx.DevPtr(0), fftMy.DevPtr(0), 27 | Kxx.DevPtr(0), Kyy.DevPtr(0), Kxy.DevPtr(0), 28 | Nx, Ny, cfg) 29 | } 30 | 31 | // kernel multiplication for 2D demag convolution on Z, exploiting full kernel symmetry. 32 | func kernMulRSymm2Dz_async(fftMz, Kzz *data.Slice, Nx, Ny int) { 33 | util.Argument(fftMz.NComp() == 1 && Kzz.NComp() == 1) 34 | 35 | cfg := make3DConf([3]int{Nx, Ny, 1}) 36 | k_kernmulRSymm2Dz_async(fftMz.DevPtr(0), Kzz.DevPtr(0), Nx, Ny, cfg) 37 | } 38 | 39 | // kernel multiplication for general 1D convolution. Does not assume any symmetry. 40 | // Used for MFM images. 41 | func kernMulC_async(fftM, K *data.Slice, Nx, Ny int) { 42 | util.Argument(fftM.NComp() == 1 && K.NComp() == 1) 43 | cfg := make3DConf([3]int{Nx, Ny, 1}) 44 | k_kernmulC_async(fftM.DevPtr(0), K.DevPtr(0), Nx, Ny, cfg) 45 | } 46 | -------------------------------------------------------------------------------- /cuda/fft3dr2c.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/mumax/3/cuda/cu" 7 | "github.com/mumax/3/cuda/cufft" 8 | "github.com/mumax/3/data" 9 | "github.com/mumax/3/timer" 10 | "github.com/mumax/3/util" 11 | ) 12 | 13 | // 3D single-precission real-to-complex FFT plan. 14 | type fft3DR2CPlan struct { 15 | fftplan 16 | size [3]int 17 | } 18 | 19 | // 3D single-precission real-to-complex FFT plan. 20 | func newFFT3DR2C(Nx, Ny, Nz int) fft3DR2CPlan { 21 | handle := cufft.Plan3d(Nz, Ny, Nx, cufft.R2C) // new xyz swap 22 | handle.SetStream(stream0) 23 | return fft3DR2CPlan{fftplan{handle}, [3]int{Nx, Ny, Nz}} 24 | } 25 | 26 | // Execute the FFT plan, asynchronous. 27 | // src and dst are 3D arrays stored 1D arrays. 28 | func (p *fft3DR2CPlan) ExecAsync(src, dst *data.Slice) { 29 | if Synchronous { 30 | Sync() 31 | timer.Start("fft") 32 | } 33 | util.Argument(src.NComp() == 1 && dst.NComp() == 1) 34 | oksrclen := p.InputLen() 35 | if src.Len() != oksrclen { 36 | log.Panicf("fft size mismatch: expecting src len %v, got %v", oksrclen, src.Len()) 37 | } 38 | okdstlen := p.OutputLen() 39 | if dst.Len() != okdstlen { 40 | log.Panicf("fft size mismatch: expecting dst len %v, got %v", okdstlen, dst.Len()) 41 | } 42 | p.handle.ExecR2C(cu.DevicePtr(uintptr(src.DevPtr(0))), cu.DevicePtr(uintptr(dst.DevPtr(0)))) 43 | if Synchronous { 44 | Sync() 45 | timer.Stop("fft") 46 | } 47 | } 48 | 49 | // 3D size of the input array. 50 | func (p *fft3DR2CPlan) InputSizeFloats() (Nx, Ny, Nz int) { 51 | return p.size[X], p.size[Y], p.size[Z] 52 | } 53 | 54 | // 3D size of the output array. 55 | func (p *fft3DR2CPlan) OutputSizeFloats() (Nx, Ny, Nz int) { 56 | return 2 * (p.size[X]/2 + 1), p.size[Y], p.size[Z] 57 | } 58 | 59 | // Required length of the (1D) input array. 60 | func (p *fft3DR2CPlan) InputLen() int { 61 | return prod3(p.InputSizeFloats()) 62 | } 63 | 64 | // Required length of the (1D) output array. 65 | func (p *fft3DR2CPlan) OutputLen() int { 66 | return prod3(p.OutputSizeFloats()) 67 | } 68 | -------------------------------------------------------------------------------- /engine/log.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "fmt" 5 | "github.com/mumax/3/httpfs" 6 | "github.com/mumax/3/util" 7 | "io" 8 | "os" 9 | ) 10 | 11 | var ( 12 | hist string // console history for GUI 13 | logfile io.WriteCloser // saves history of input commands + output 14 | ) 15 | 16 | // Special error that is not fatal when paniced on and called from GUI 17 | // E.g.: try to set bad grid size: panic on UserErr, recover, print error, carry on. 18 | type UserErr string 19 | 20 | func (e UserErr) Error() string { return string(e) } 21 | 22 | func CheckRecoverable(err error) { 23 | if err != nil { 24 | panic(UserErr(err.Error())) 25 | } 26 | } 27 | 28 | func LogIn(msg ...interface{}) { 29 | str := sprint(msg...) 30 | log2GUI(str) 31 | log2File(str) 32 | fmt.Println(str) 33 | } 34 | 35 | func LogOut(msg ...interface{}) { 36 | str := "//" + sprint(msg...) 37 | log2GUI(str) 38 | log2File(str) 39 | fmt.Println(str) 40 | } 41 | 42 | func LogErr(msg ...interface{}) { 43 | str := "//" + sprint(msg...) 44 | log2GUI(str) 45 | log2File(str) 46 | fprintln(os.Stderr, str) 47 | } 48 | 49 | func log2File(msg string) { 50 | if logfile != nil { 51 | fprintln(logfile, msg) 52 | } 53 | } 54 | 55 | func initLog() { 56 | if logfile != nil { 57 | panic("log already inited") 58 | } 59 | // open log file and flush what was logged before the file existed 60 | var err error 61 | logfile, err = httpfs.Create(OD() + "log.txt") 62 | if err != nil { 63 | panic(err) 64 | } 65 | util.FatalErr(err) 66 | logfile.Write(([]byte)(hist)) 67 | logfile.Write([]byte{'\n'}) 68 | } 69 | 70 | func log2GUI(msg string) { 71 | if len(msg) > 1000 { 72 | msg = msg[:1000-len("...")] + "..." 73 | } 74 | if hist != "" { // prepend newline 75 | hist += "\n" 76 | } 77 | hist += msg 78 | // TODO: push to web ? 79 | } 80 | 81 | // like fmt.Sprint but with spaces between args 82 | func sprint(msg ...interface{}) string { 83 | str := fmt.Sprintln(msg...) 84 | str = str[:len(str)-1] // strip newline 85 | return str 86 | } 87 | -------------------------------------------------------------------------------- /script/lit.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "reflect" 7 | "strconv" 8 | ) 9 | 10 | // compiles a basic literal, like numbers and strings 11 | func (w *World) compileBasicLit(n *ast.BasicLit) Expr { 12 | switch n.Kind { 13 | default: 14 | panic(err(n.Pos(), "not allowed:", n.Value, "(", typ(n), ")")) 15 | case token.FLOAT: 16 | return floatLit(parseFloat(n.Value)) 17 | case token.INT: 18 | return intLit(parseInt(n.Value)) 19 | case token.STRING: 20 | return stringLit(n.Value[1 : len(n.Value)-1]) // remove quotes 21 | } 22 | } 23 | 24 | type floatLit float64 25 | 26 | func (l floatLit) Eval() interface{} { return float64(l) } 27 | func (l floatLit) Type() reflect.Type { return float64_t } 28 | func (l floatLit) Child() []Expr { return nil } 29 | func (l floatLit) Fix() Expr { return l } 30 | 31 | type intLit int 32 | 33 | func (l intLit) Eval() interface{} { return int(l) } 34 | func (l intLit) Type() reflect.Type { return int_t } 35 | func (l intLit) Child() []Expr { return nil } 36 | func (l intLit) Fix() Expr { return l } 37 | 38 | type stringLit string 39 | 40 | func (l stringLit) Eval() interface{} { return string(l) } 41 | func (l stringLit) Type() reflect.Type { return string_t } 42 | func (l stringLit) Child() []Expr { return nil } 43 | func (l stringLit) Fix() Expr { return l } 44 | 45 | type boolLit bool 46 | 47 | func (l boolLit) Eval() interface{} { return bool(l) } 48 | func (l boolLit) Type() reflect.Type { return bool_t } 49 | func (l boolLit) Child() []Expr { return nil } 50 | func (l boolLit) Fix() Expr { return l } 51 | 52 | func parseFloat(str string) float64 { 53 | v, err := strconv.ParseFloat(str, 64) 54 | if err != nil { 55 | panic("internal error") // we were sure it was a number... 56 | } 57 | return v 58 | } 59 | 60 | func parseInt(str string) int { 61 | v, err := strconv.Atoi(str) 62 | if err != nil { 63 | panic("internal error") // we were sure it was a number... 64 | } 65 | return v 66 | } 67 | -------------------------------------------------------------------------------- /cuda/reduce_test.go: -------------------------------------------------------------------------------- 1 | package cuda 2 | 3 | import ( 4 | "testing" 5 | "unsafe" 6 | 7 | "github.com/mumax/3/data" 8 | "github.com/mumax/3/util" 9 | ) 10 | 11 | // test input data 12 | var in1, in2, in3 *data.Slice 13 | 14 | func initTest() { 15 | if in1 != nil { 16 | return 17 | } 18 | { 19 | inh1 := make([]float32, 1000) 20 | for i := range inh1 { 21 | inh1[i] = float32(i) 22 | } 23 | in1 = toGPU(inh1) 24 | } 25 | { 26 | inh2 := make([]float32, 100000) 27 | for i := range inh2 { 28 | inh2[i] = -float32(i) / 100 29 | } 30 | in2 = toGPU(inh2) 31 | } 32 | } 33 | 34 | func toGPU(list []float32) *data.Slice { 35 | mesh := [3]int{1, 1, len(list)} 36 | h := sliceFromList([][]float32{list}, mesh) 37 | d := NewSlice(1, mesh) 38 | data.Copy(d, h) 39 | return d 40 | } 41 | 42 | func TestReduceSum(t *testing.T) { 43 | initTest() 44 | result := Sum(in1) 45 | if result != 499500 { 46 | t.Error("got:", result) 47 | } 48 | } 49 | 50 | func TestReduceDot(t *testing.T) { 51 | initTest() 52 | 53 | // test for 1 comp 54 | a := toGPU([]float32{1, 2, 3, 4, 5}) 55 | b := toGPU([]float32{5, 4, 3, -1, 2}) 56 | result := Dot(a, b) 57 | if result != 5+8+9-4+10 { 58 | t.Error("got:", result) 59 | } 60 | 61 | // test for 3 comp 62 | const N = 32 63 | mesh := [3]int{1, 1, N} 64 | c := NewSlice(3, mesh) 65 | d := NewSlice(3, mesh) 66 | Memset(c, 1, 2, 3) 67 | Memset(d, 4, 5, 6) 68 | result = Dot(c, d) 69 | if result != N*(4+10+18) { 70 | t.Error("got:", result) 71 | } 72 | } 73 | 74 | func TestReduceMaxAbs(t *testing.T) { 75 | result := MaxAbs(in1) 76 | if result != 999 { 77 | t.Error("got:", result) 78 | } 79 | result = MaxAbs(in2) 80 | if result != 999.99 { 81 | t.Error("got:", result) 82 | } 83 | } 84 | 85 | func sliceFromList(arr [][]float32, size [3]int) *data.Slice { 86 | ptrs := make([]unsafe.Pointer, len(arr)) 87 | for i := range ptrs { 88 | util.Argument(len(arr[i]) == prod(size)) 89 | ptrs[i] = unsafe.Pointer(&arr[i][0]) 90 | } 91 | return data.SliceFromPtrs(size, data.CPUMemory, ptrs) 92 | } 93 | --------------------------------------------------------------------------------