mumax / 3

GPU-accelerated micromagnetic simulator
Other
447 stars 150 forks source link

Feature/Time series signal from file support #271

Closed jakelove closed 3 years ago

jakelove commented 3 years ago

Added the capability to load time series data from external files so that material/region properties can be arbitrarily set to different values throughout the simulation. Currently to vary a property such as the external field you could write something like:

B_ext = A*sin(t)

Which is nice if you want B_ext to be an analytical expression, however this wasn't sufficient for my case where I need material properties to vary based on datasets from another source.

The functionality I have added allows you to load a multicolumned file into mumax3, then use each column as a ScalarFunction of (typically) t.

Example input file is given below showing all the exposed functions and an example usage.

// Units
ns := 1e-9

// A multidimensional signal can be loaded from a file containing an arbitary number of numerical columns. A timestep
// is then given that defines the sample rate of the signal (the time between adjacent rows).
S := LoadSignal("file.txt", 2*ns)

// Example 'file.txt':

//  0.0  1.2  2.8
//  1.1  2.7  3.8
//  1.9  1.3  3.5
//  1.5  1.3  4.9
//  4.7  3.4  2.3
//  5.3  2.3  1.0
//  1.0  2.2  0.8
//  1.3  3.7  0.8
//  4.1  4.3  1.5

// Various properties of the signal can be gathered with 
dt         := GetSignalDt(S)
len        := GetSignalLength(S)
duration   := GetSignalDuration(S)
dimensions := GetSignalDimensions(S)

// or dt can be set to a new value to repeat an experiment with a different sample rate
SetSignalDt(S, 1*ns)

// Signal values can be accessed by using SignalValue as a 'ScalarFunction' type, where the last argument represents
// the column index to read from
tableaddvar(SignalValue(S, t, 0), "external_field", "mT")
tableaddvar(SignalValue(S, t, 1), "vcc", "mV")
tableaddvar(SignalValue(S, t, 2), "vss", "mV")

// Intended usage is something like below:
//   B_ext = SignalValue(S, t, 0))
//   AppliedPotential.setRegion(vcc_region_id, SignalValue(S, t, 1))
//   AppliedPotential.setRegion(vss_region_id, SignalValue(S, t, 2))

tableautosave(0.01*ns)

// Arbitary system to get mumax3 running...
SetGridsize(256, 256, 1)
SetCellsize(3e-9, 3e-9, 3e-9)
Msat  = 800e3
Aex   = 13e-12

run(10*ns)

First time using GoLang so let me know if anything should be more 'Go-esque'.

JeroenMulkers commented 3 years ago

Hi @JakeLove . Having the option to define a (time) signal based on a data file could be very useful for many mumax3 users.

I think the code is nicely written but I do have some small suggestions on the coding style:

Some other remarks:

I implemented a similar feature some time ago myself (actually specifically for our joined project). You can find the code here. We can use either this implementation or we can use your implementation (after taking the above comments into account). Let me know which implementation you prefer and why.