diff --git a/.gitignore b/.gitignore index ce901c07..57e89b0a 100644 --- a/.gitignore +++ b/.gitignore @@ -25,13 +25,7 @@ vtks # ignore *.so created by cython -fidimag/extensions/baryakhtar_clib.so -fidimag/extensions/clib.so -fidimag/extensions/cvode.so -fidimag/extensions/dipolar.so -fidimag/extensions/micro_clib.so -fidimag/extensions/neb_clib.so - +fidimag/extensions/*.so # ignore output from coverage htmlcov @@ -39,3 +33,5 @@ htmlcov # ignore junit test output test-reports +# ignore notebook checkpoint directory +.ipynb_checkpoints/ diff --git a/install/docker/Dockerfile b/docker/minimal-py2/Dockerfile similarity index 94% rename from install/docker/Dockerfile rename to docker/minimal-py2/Dockerfile index 4042d8d2..54fe700b 100644 --- a/install/docker/Dockerfile +++ b/docker/minimal-py2/Dockerfile @@ -49,6 +49,10 @@ RUN useradd -m -s /bin/bash -G sudo fidimag && \ echo "fidimag ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers RUN chown -R fidimag $FIDIMAG_HOME +# For bind mounts from host +RUN mkdir /io +RUN chown -R fidimag /io + USER fidimag RUN touch $FIDIMAG_HOME/.sudo_as_admin_successful @@ -56,6 +60,5 @@ RUN touch $FIDIMAG_HOME/.sudo_as_admin_successful #COPY WELCOME $FIDIMAG_HOME/WELCOME - -WORKDIR $FIDIMAG_HOME +WORKDIR /io CMD ["/bin/bash","-i"] diff --git a/install/docker/Dockerfile.org b/docker/minimal-py2/Dockerfile.org similarity index 100% rename from install/docker/Dockerfile.org rename to docker/minimal-py2/Dockerfile.org diff --git a/install/docker/Makefile b/docker/minimal-py2/Makefile similarity index 50% rename from install/docker/Makefile rename to docker/minimal-py2/Makefile index 0751bb27..3a5d4083 100644 --- a/install/docker/Makefile +++ b/docker/minimal-py2/Makefile @@ -1,19 +1,16 @@ # to build a new docker image build: - time docker build -t fangohr/fidimag:latest . + time docker build -t fidimag/minimal-py2:latest . # to run new image -run: - docker run -ti fangohr/fidimag bash +run: build + docker run -v `pwd`:/io -ti fidimag/minimal-py2 # try 'ipython' and then 'import fidimag' -login: - docker login - # to push the new docker image to dockerhub (need to login first) -push: - docker push fangohr/fidimag:latest +push: build + docker push fidimag/minimal-py2:latest # to fetch image to local machine pull: - docker pull fangohr/fidimag:latest + docker pull fidimag/minimal-py2:latest diff --git a/docker/minimal-py2/Readme.md b/docker/minimal-py2/Readme.md new file mode 100644 index 00000000..a701838c --- /dev/null +++ b/docker/minimal-py2/Readme.md @@ -0,0 +1,31 @@ +# Docker + +Run fidimag with Python 2 under Docker. + +## Using the docker container + +There is a fidimag container available under `fidimag/minimal-py2`. + +To use it, you can try this: + +1. Install docker + +2. Pull the container onto your machine using + + docker pull fidimag/minimal-py2 + +3. Start the container using + + docker run -ti fidimag/minimal-py2 + + This command should show a bash prompt inside the docker container: + +
+    bin:docker fangohr$ docker run -v `pwd`:/io -ti fidimag/minimal-py2
+    fidimag@38fdd2a0feb4:/io$
+    
+ +## Creating the docker container + +The `Makefile` in this directory shows the relevant targets (build, login, push) +to create a new container and push it to the the cloud. diff --git a/docker/minimal-py3/Dockerfile b/docker/minimal-py3/Dockerfile new file mode 100644 index 00000000..037dd152 --- /dev/null +++ b/docker/minimal-py3/Dockerfile @@ -0,0 +1,64 @@ +FROM ubuntu:14.04 + +# packages we need to run fidimag +RUN apt-get -y update +RUN apt-get -y install python3-numpy python3-dev python3-scipy +RUN apt-get -y install python3-pytest ipython3 python3-matplotlib python3-pip +# standard tools for compilation +RUN apt-get -y install wget make git + +# where to install source +ENV FIDIMAG_HOME /home/fidimag + +RUN mkdir -p $FIDIMAG_HOME +WORKDIR $FIDIMAG_HOME +RUN git clone https://github.com/computationalmodelling/fidimag.git +WORKDIR $FIDIMAG_HOME/fidimag/bin + +# install third party libraries from source +RUN bash install-fftw.sh +RUN bash install-sundials-2.5.sh + +# for pip +RUN python3 -m pip install --user --upgrade setuptools pip +# install pyvtk +RUN python3 -m pip install pyvtk +# install cython +RUN python3 -m pip install cython --upgrade +WORKDIR $FIDIMAG_HOME/fidimag + +# compile fidimag +RUN python3 setup.py build_ext --inplace +env PYTHONPATH=$FIDIMAG_HOME/fidimag +env LD_LIBRARY_PATH=$FIDIMAG_HOME/fidimag/local/lib +WORKDIR $FIDIMAG_HOME/fidimag/tests + +# check that tests run okay +RUN py.test-3 -v + + +# install Jupyter, port exposing doesn't work yet +#RUN pip install jupyter + +# expose jupyter port - not working yet +#EXPOSE 8888 8888 + + +# Set up user so that we do not run as root +RUN useradd -m -s /bin/bash -G sudo fidimag && \ + echo "fidimag:docker" | chpasswd && \ + echo "fidimag ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers +RUN chown -R fidimag $FIDIMAG_HOME + +# For bind mounts from host +RUN mkdir /io +RUN chown -R fidimag /io + +USER fidimag +RUN touch $FIDIMAG_HOME/.sudo_as_admin_successful + +# Print something nice on entry. +#COPY WELCOME $FIDIMAG_HOME/WELCOME + +WORKDIR /io +CMD ["/bin/bash","-i"] diff --git a/docker/minimal-py3/Makefile b/docker/minimal-py3/Makefile new file mode 100644 index 00000000..659b56a4 --- /dev/null +++ b/docker/minimal-py3/Makefile @@ -0,0 +1,16 @@ +# to build a new docker image +build: + time docker build -t fidimag/minimal-py3:latest . + +# to run new image +run: build + docker run -v `pwd`:/io -ti fidimag/minimal-py3 + # try 'ipython3' and then 'import fidimag' + +# to push the new docker image to dockerhub (need to login first) +push: build + docker push fidimag/minimal-py3:latest + +# to fetch image to local machine +pull: + docker pull fidimag/minimal-py3:latest diff --git a/docker/minimal-py3/Readme.md b/docker/minimal-py3/Readme.md new file mode 100644 index 00000000..c83816b7 --- /dev/null +++ b/docker/minimal-py3/Readme.md @@ -0,0 +1,31 @@ +# Docker + +Run fidimag with Python 3 under Docker. + +## Using the docker container + +There is a fidimag container available under `fidimag/minimal-py3`. + +To use it, you can try this: + +1. Install docker + +2. Pull the container onto your machine using + + docker pull fidimag/minimal-py3 + +3. Start the container using + + docker run -ti fidimag/minimal-py3 + + This command should show a bash prompt inside the docker container: + +
+    bin:docker fangohr$ docker run -v `pwd`:/io -ti fidimag/minimal-py3
+    fidimag@38fdd2a0feb4:/io$
+    
+ +## Creating the docker container + +The `Makefile` in this directory shows the relevant targets (build, login, push) +to create a new container and push it to the the cloud. diff --git a/docker/notebook/Dockerfile b/docker/notebook/Dockerfile new file mode 100644 index 00000000..91bc2dda --- /dev/null +++ b/docker/notebook/Dockerfile @@ -0,0 +1,37 @@ +FROM jupyter/scipy-notebook + +# where to install source +ENV FIDIMAG_DIR $HOME/work/fidimag + +RUN git clone https://github.com/computationalmodelling/fidimag.git +WORKDIR $FIDIMAG_DIR + +# install third party libraries from source +RUN bash bin/install-fftw.sh +RUN bash bin/install-sundials-2.5.sh + +# install pyvtk +RUN pip install pyvtk +# install cython +RUN pip install cython --upgrade + +# compile fidimag +RUN python3 setup.py build_ext --inplace +ENV PYTHONPATH=$FIDIMAG_DIR +ENV LD_LIBRARY_PATH=$FIDIMAG_DIR/local/lib +WORKDIR $FIDIMAG_DIR/tests + +# https://github.com/conda-forge/matplotlib-feedstock/issues/36 +RUN conda install --quiet --yes icu + +# check that tests run okay +RUN conda install --quiet --yes pytest +RUN py.test -v + +# /io will be mounted from the host system +USER root +RUN mkdir /io +RUN chown -R $NB_USER /io +USER $NB_USER + +WORKDIR /io diff --git a/docker/notebook/Makefile b/docker/notebook/Makefile new file mode 100644 index 00000000..95caeb39 --- /dev/null +++ b/docker/notebook/Makefile @@ -0,0 +1,15 @@ +# to build a new docker image +build: + time docker build -t fidimag/notebook:latest . + +# to run new image +run: build + docker run -v `pwd`:/io -d -p 30008:8888 fidimag/notebook + +# to push the new docker image to dockerhub (need to login first) +push: build + docker push fidimag/notebook:latest + +# to fetch image to local machine +pull: + docker pull fidimag/notebook:latest diff --git a/docker/notebook/Readme.md b/docker/notebook/Readme.md new file mode 100644 index 00000000..441338e2 --- /dev/null +++ b/docker/notebook/Readme.md @@ -0,0 +1,42 @@ +# Docker + +First steps towards running fidimag through Docker. + +## Using the docker container + +There is a fidimag container available under `fangohr/fidimag`. + +To use it, you can try this: + +1. Install docker + +2. Pull the container onto your machine using + + docker pull fidimag/notebook + +3. Start the container using + + docker run -v `pwd`:/io -d -p 30008:8888 fidimag/notebook + + This will start a notebook server. You can see it in your browser at +http://localhost:30008/ on Linux, or http://192.168.99.100:30008/ on Mac (you may +need to change this IP address if your docker VM is at a different address). + +To run a shell instead of the notebook server, run: + + docker run -v `pwd`:/io -ti fidimag/notebook bash + +## Shortcomings + +- need to share directory between host and container (MOUNT or VOLUME) + + +## Creating the docker container + +The `Makefile` in this directory shows the relevant targets (build, login, push) +to create a new container and push it to the the cloud. + + + + + diff --git a/fidimag/atomistic/anisotropy.py b/fidimag/atomistic/anisotropy.py index e67a6cf1..a284f0dc 100644 --- a/fidimag/atomistic/anisotropy.py +++ b/fidimag/atomistic/anisotropy.py @@ -44,7 +44,7 @@ class Anisotropy(Energy): """ - def __init__(self, Ku, axis=(1, 0, 0), name='anis'): + def __init__(self, Ku, axis=(1, 0, 0), name='Anisotropy'): self.Ku = Ku self.name = name self.axis = axis diff --git a/fidimag/atomistic/demag.py b/fidimag/atomistic/demag.py index e265e4d3..a08d1293 100644 --- a/fidimag/atomistic/demag.py +++ b/fidimag/atomistic/demag.py @@ -33,7 +33,7 @@ class Demag(object): """ - def __init__(self, name='demag'): + def __init__(self, name='Demag'): self.name = name self.jac = True diff --git a/fidimag/atomistic/demag_full.py b/fidimag/atomistic/demag_full.py index 6e81f75d..fd6514d8 100644 --- a/fidimag/atomistic/demag_full.py +++ b/fidimag/atomistic/demag_full.py @@ -14,7 +14,7 @@ class DemagFull(Energy): the energy density. """ - def __init__(self, name='demag_full'): + def __init__(self, name='DemagFull'): self.name = name self.jac = True diff --git a/fidimag/atomistic/demag_hexagonal.py b/fidimag/atomistic/demag_hexagonal.py index e7a99ddb..b5cda137 100644 --- a/fidimag/atomistic/demag_hexagonal.py +++ b/fidimag/atomistic/demag_hexagonal.py @@ -47,7 +47,7 @@ class DemagHexagonal(object): """ - def __init__(self, name='demag_hex'): + def __init__(self, name='DemagHexagonal'): self.name = name self.jac = True diff --git a/fidimag/atomistic/exchange.py b/fidimag/atomistic/exchange.py index 82c0831b..8f93ce21 100644 --- a/fidimag/atomistic/exchange.py +++ b/fidimag/atomistic/exchange.py @@ -41,7 +41,7 @@ class UniformExchange(Energy): """ - def __init__(self, J=0, name='exch'): + def __init__(self, J=0, name='UniformExchange'): self.J = J self.name = name @@ -142,7 +142,7 @@ def my_exchange(pos): """ - def __init__(self, J_fun, name='exch'): + def __init__(self, J_fun, name='Exchange'): self.J_fun = J_fun self.name = name self.jac = False diff --git a/fidimag/atomistic/lib/llg.c b/fidimag/atomistic/lib/llg.c index 27b71f3e..bd0cd838 100644 --- a/fidimag/atomistic/lib/llg.c +++ b/fidimag/atomistic/lib/llg.c @@ -1,70 +1,167 @@ #include "clib.h" -void llg_rhs(double *dm_dt, double *m, double *h, double *alpha, int *pins, - double gamma, int n, int do_precession, double default_c) { +/* The right hand side of the LLG equation for the CVOde solver. This can be + * used both for the micromagnetic and atomistic codes since m or S are unitless + * and the prefactors keep the same structure. + * + * The LLG equation has the structure: + * ( * is for dot or scalar product) + * + * dm -gamma + * ---- = -------- ( m X H_eff + a * m X ( m x H_eff ) ) + * dt 2 + * ( 1 + a ) + * + * where a is the Gilbert damping constant, gamma is the gyromagnetic + * ratio ( gamma = 1.76e11 for a free electron; for the micromagnetic + * case, we use gamma_0 = mu_0 * gamma = 2.21e5, for a free electron), + * m is the magnetisation vector and H_eff is the effective field. + * + * In our calculation, we usually compute: + + * m x (m x H_eff) = ( m * H_eff) m - (m * m) H_eff + + * Then, if we define the perpendicular component of the effective + * field as: + + * H_perp = H_eff - ( m * H_eff) m + + * we can write + + * dm -gamma + * ---- = -------- ( m X H_perp - a * H_perp ) + * dt 2 + * ( 1 + a ) + + * since m X m = 0 and, theoretically, m * m = 1 (at zero temperature m has + * fixed length). However, for the second term to the right hand side, + * proportional to a, it is better to keep the m X ( m x H_eff ) term with (m * + * m) for stability purposes, thus we use + * + + * H_perp = (m * m) H_eff - ( m * H_eff) m + + * for both terms. + * + * Additionally, to preserve the magnetisation length, we need to correct the + * dm / dt term for every time step, adding the following term to the right + * hand size expression of the LLG: + + * dm dm 2 + * ---- ---> ---- + c * ( 1 - m ) m + * dt dt + + * with + _________ + * / 2 + * c = 6 * / ( dm ) + * / ( ---- ) + * \/ ( dt ) + + * The correction must be introduced since numerically, m can change length + * during a step of the integration (which would not occur if the integration + * step is infinitely small), deviating from the real answer. If we just + * rescaled m, we would have to recompute the effective field (m changes) and + * also the solution would present jumps due to the rescaling. With the term + * specified above, m stays close to 1, giving a more continuous solution, and + * also the term stays as zero if m is exactly 1 (notice that if m increases, + * the correction is negative and it decreases m length; similarly if m + * decreases). The prefactor c must be specified because the correction term + * must be sufficiently strong to affect the solution. Accordingly, we can + * think of dm/dt as a kind of velocity that is proportional to the change of + * rate of m, hence using its magnitude, the correction is stronger for large + * deviations and weak for small deviations. The factor 6 is added ad-hoc, +* which seems to work well when computing the solutions, but its specification +* stills requires a more strict proof. It is worth mentioning that the norm of +* dm/dt changes the time scaling by a factor proportional to 1/t, therefore in +* the future we could try to estimate its + * influence with more mathematical/numerical rigour and analyse an optimal + * value for the prefactor (6). + */ + +void llg_rhs(double * dm_dt, double * m, double * h, double * alpha, int * pins, + double gamma, int n, int do_precession, double default_c) { - int i, j, k; + int i, j, k; double coeff, mm, mh, c; - double hpi,hpj,hpk; - - #pragma omp parallel for private(i,j,k,coeff,mm, mh, c, hpi,hpj,hpk) - for (int id = 0; id < n; id++) { - i = 3*id; - j = i+1; - k = i+2; - - if (pins[id]>0){ - dm_dt[i] = 0; - dm_dt[j] = 0; - dm_dt[k] = 0; - continue; - } - - coeff = -gamma/(1.0+alpha[id]*alpha[id]); - - mm = m[i]*m[i] + m[j]*m[j] + m[k]*m[k]; - mh = m[i]*h[i] + m[j]*h[j] + m[k]*h[k]; - - //suppose m is normalised, i.e., mm=1; hp=mm.h-mh.m=-mx(mxh) - hpi = mm*h[i] - mh*m[i]; - hpj = mm*h[j] - mh*m[j]; - hpk = mm*h[k] - mh*m[k]; - //IMPORTANT: never ignore mm!!! - //what we found is that if we igonre mm, i.e. using - // hpi = h[i] - mh*m[i] - // hpj = h[j] - mh*m[j]; - // hpk = h[k] - mh*m[k]; - //then the standard problem 4 failed to converge ?!! - double mth0=0, mth1=0, mth2=0; + double hpi, hpj, hpk; + + #pragma omp parallel for private(i,j,k,coeff,mm, mh, c, hpi,hpj,hpk) + for (int id = 0; id < n; id++) { + // Indexes for the 3 components of the spin (magnetic moment) + // at the i-th lattice (mesh) site --> x, y, z + i = 3 * id; + j = i + 1; + k = i + 2; + + // Pinned spins do not follow the dynamical equation + if (pins[id] > 0) { + dm_dt[i] = 0; + dm_dt[j] = 0; + dm_dt[k] = 0; + continue; + } + coeff = -gamma / (1.0 + alpha[id] * alpha[id]); + + // Dot products + mm = m[i] * m[i] + m[j] * m[j] + m[k] * m[k]; + mh = m[i] * h[i] + m[j] * h[j] + m[k] * h[k]; + + // Usually, m is normalised, i.e., mm=1; + // so hp = mm.h - mh.m = -m x (m x h) + // We set here the perpendicular componenet of the field + // but using the (m * m) product + hpi = mm * h[i] - mh * m[i]; + hpj = mm * h[j] - mh * m[j]; + hpk = mm * h[k] - mh * m[k]; + + // IMPORTANT: do not ignore mm !! + // What we've found is that if we igonre mm, i.e. using + // hpi = h[i] - mh * m[i]; + // hpj = h[j] - mh * m[j]; + // hpk = h[k] - mh * m[k]; + // the micromagnetic standard problem 4 failed to converge (?) + // + // NOTE (Fri 08 Jul 2016 13:58): In fact, the problem converges but with 2 less + // decimals of accuracy, compared with the OOMMF calculation + double mth0 = 0, mth1 = 0, mth2 = 0; + + // The first term: m x H_eff = m x H_perp if (do_precession){ - mth0 = cross_x(m[i],m[j],m[k],hpi,hpj,hpk); - mth1 = cross_y(m[i],m[j],m[k],hpi,hpj,hpk); - mth2 = cross_z(m[i],m[j],m[k],hpi,hpj,hpk); + mth0 = cross_x(m[i], m[j], m[k], hpi, hpj, hpk); + mth1 = cross_y(m[i], m[j], m[k], hpi, hpj, hpk); + mth2 = cross_z(m[i], m[j], m[k], hpi, hpj, hpk); } - dm_dt[i] = coeff*(mth0 - hpi * alpha[id]); - dm_dt[j] = coeff*(mth1 - hpj * alpha[id]); - dm_dt[k] = coeff*(mth2 - hpk * alpha[id]); - - // in future, we will try the new method to integrate the LLG equation, - // A mixed mid-point Runge-Kutta like scheme for the integration of Landau-Lifshitz equation - // Journal of Applied Physics 115, 17D101 (2014) - // if possible, we can combine it with adaptive step size, don't know how to do but it's worth a try. - - if (default_c<0){ - c = 6*sqrt(dm_dt[i]*dm_dt[i]+dm_dt[j]*dm_dt[j]+dm_dt[k]*dm_dt[k]); - }else{ - c = default_c; + // The RHS term of the LLG equation + dm_dt[i] = coeff * (mth0 - hpi * alpha[id]); + dm_dt[j] = coeff * (mth1 - hpj * alpha[id]); + dm_dt[k] = coeff * (mth2 - hpk * alpha[id]); + + // In future, we will try the new method to integrate the LLG equation, + // A mixed mid-point Runge-Kutta like scheme for the integration of + // Landau-Lifshitz equation Journal of Applied Physics 115, 17D101 + // (2014) if possible, we can combine it with adaptive step size, don't + // know how to do but it's worth a try. + + if (default_c < 0){ + c = 6 * sqrt(dm_dt[i] * dm_dt[i] + + dm_dt[j] * dm_dt[j] + + dm_dt[k] * dm_dt[k] + ); + } else { + c = default_c; } //printf("%0.15g %0.15g\n", c, default_c); - dm_dt[i] += c*(1-mm)*m[i]; - dm_dt[j] += c*(1-mm)*m[j]; - dm_dt[k] += c*(1-mm)*m[k]; + // Correct the RHS term to keep m normalised + dm_dt[i] += c * (1 - mm) * m[i]; + dm_dt[j] += c * (1 - mm) * m[j]; + dm_dt[k] += c * (1 - mm) * m[k]; - } + } } @@ -106,9 +203,9 @@ void llg_rhs_jtimes(double *jtn, double *m, double *h, double *mp, double *hp, d /* if (default_c>0){ - jtn[i] += default_c *((1-mm)*mp[i]-2*mmp*m[i]); - jtn[j] += default_c *((1-mm)*mp[j]-2*mmp*m[j]); - jtn[k] += default_c *((1-mm)*mp[k]-2*mmp*m[k]); + jtn[i] += default_c *((1-mm)*mp[i]-2*mmp*m[i]); + jtn[j] += default_c *((1-mm)*mp[j]-2*mmp*m[j]); + jtn[k] += default_c *((1-mm)*mp[k]-2*mmp*m[k]); }*/ } @@ -118,16 +215,16 @@ void llg_rhs_jtimes(double *jtn, double *m, double *h, double *mp, double *hp, d void llg_s_rhs(double *dm_dt, double *m, double *h, double *alpha, double *chi, double gamma, int n) { - int i, j, k; + int i, j, k; - double mth0, mth1, mth2; - double coeff = - gamma; + double mth0, mth1, mth2; + double coeff = - gamma; double mm, c; double hpi,hpj,hpk,mh; - for (i = 0; i < n; i++) { - j = i + n; - k = j + n; + for (i = 0; i < n; i++) { + j = i + n; + k = j + n; if (chi[i] > 0.0){ mth0 = coeff * (m[j] * h[k] - m[k] * h[j]); @@ -147,7 +244,7 @@ void llg_s_rhs(double *dm_dt, double *m, double *h, double *alpha, double *chi, }else{ //do LL equation, similiar to the function of llg_rhs - mm = m[i] * m[i] + m[j] * m[j] + m[k] * m[k]; + mm = m[i] * m[i] + m[j] * m[j] + m[k] * m[k]; mh = m[i]*h[i] + m[j]*h[j] + m[k]*h[k]; hpi = mm*h[i] - mh*m[i]; @@ -163,6 +260,6 @@ void llg_s_rhs(double *dm_dt, double *m, double *h, double *alpha, double *chi, dm_dt[k] = coeff*(mth2 - hpk * alpha[i]); } - } + } } diff --git a/fidimag/common/cuboid_mesh.py b/fidimag/common/cuboid_mesh.py index cf69bb20..9ea0eeed 100644 --- a/fidimag/common/cuboid_mesh.py +++ b/fidimag/common/cuboid_mesh.py @@ -137,36 +137,44 @@ def init_neighbours(self): for i in range(self.nz): for j in range(self.ny): for k in range(self.nx): + # Unique index for the current lattice site cell = self._index(k, j, i) - ngbs = [other for other in [ + neighbours = [ self.index(k - 1, j, i), # left self.index(k + 1, j, i), # right self.index(k, j - 1, i), # behind self.index(k, j + 1, i), # in front self.index(k, j, i - 1), # under self.index(k, j, i + 1), # over - ]] + ] - nngbs = [other for other in [ + # If one of the neighbours is the cell itself, we + # set its index to -1 + # neighbours = [other if other != cell + # else -1 for other in neighbours] + + next_neighbours = [ self.index(k - 2, j, i), # left self.index(k + 2, j, i), # right self.index(k, j - 2, i), # behind self.index(k, j + 2, i), # in front self.index(k, j, i - 2), # under self.index(k, j, i + 2), # over - ]] - - # July 1st, 2016 Weiwei: I think it's okay for a cell with its neighbour is itself - # if periodic boundary conditions are used. For example, if we only have cell and enable - # periodic boundary condition in x-direction, then we got a rod. - # therefore, I commented two lines below. + ] + + # July 1st, 2016 Weiwei: I think it's okay for a cell with + # its neighbour is itself if periodic boundary conditions + # are used. For example, if we only have one cell and + # enable periodic boundary condition in x-direction, then + # we got a rod. therefore, I commented two lines below. # no cell should be its own neighbour - # neighbours = [other if other != cell - # else -1 for other in ngbs] - connectivity.append(ngbs) - connectivity_next.append(nngbs) - - return np.array(connectivity, dtype=np.int32), np.array(connectivity_next, dtype=np.int32) + + connectivity.append(neighbours) + connectivity_next.append(next_neighbours) + + return (np.array(connectivity, dtype=np.int32), + np.array(connectivity_next, dtype=np.int32) + ) def index(self, i, j, k): """ @@ -176,22 +184,22 @@ def index(self, i, j, k): i, j, k are the positions in the x, y and z directions, respectively """ - if self.periodicity[0]: # if mesh is periodic in x-direction - if i < 0: # then wrap the left side - i += self.nx # to the right - elif i >= self.nx: # and wrap the right side - i -= self.nx # to the left - - if self.periodicity[1]: - if j < 0: - j += self.ny - elif j >= self.ny: - j -= self.ny - - if self.periodicity[2]: - if k < 0: - k += self.nz - elif k >= self.nz: + if self.periodicity[0]: # if mesh is periodic in x-direction + if i < 0: # then wrap the left side + i += self.nx # to the right + elif i >= self.nx: # and wrap the right side + i -= self.nx # to the left + + if self.periodicity[1]: + if j < 0: + j += self.ny + elif j >= self.ny: + j -= self.ny + + if self.periodicity[2]: + if k < 0: + k += self.nz + elif k >= self.nz: k -= self.nz return self._index(i, j, k) @@ -199,7 +207,7 @@ def index(self, i, j, k): def _index(self, i, j, k): """ Returns the index for the cell with ordinals i, j, k - or False if that cell would be out of bounds. + or -1 if that cell would be out of bounds. """ if i < 0 or j < 0 or k < 0 or k >= self.nz or j >= self.ny or i >= self.nx: diff --git a/fidimag/micro/anisotropy.py b/fidimag/micro/anisotropy.py index c44a500b..eea40056 100644 --- a/fidimag/micro/anisotropy.py +++ b/fidimag/micro/anisotropy.py @@ -11,7 +11,7 @@ class UniaxialAnisotropy(Energy): compute the anisotropy field with the energy density E = K[1- (m.u)^2] """ - def __init__(self, Ku, axis=(1, 0, 0), name='anis'): + def __init__(self, Ku, axis=(1, 0, 0), name='Anisotropy'): self.Ku = Ku self.name = name self.jac = True diff --git a/fidimag/micro/demag.py b/fidimag/micro/demag.py index ee2a0e37..8ced3f44 100644 --- a/fidimag/micro/demag.py +++ b/fidimag/micro/demag.py @@ -6,15 +6,17 @@ default_options={ - 'pbc_2d_error':1e-10, - 'sample_repeat_nx':-1, - 'sample_repeat_ny':-1, - 'tensor_file_name':'2dpbc_tensors', + 'pbc_2d_error': 1e-10, + 'sample_repeat_nx': -1, + 'sample_repeat_ny': -1, + 'tensor_file_name': '2dpbc_tensors', } + class Demag(object): - def __init__(self, name='demag', pbc_2d=False, pbc_options=default_options): + def __init__(self, name='Demag', pbc_2d=False, + pbc_options=default_options): self.name = name self.oommf = True self.pbc_2d = pbc_2d @@ -36,7 +38,7 @@ def setup(self, mesh, spin, Ms): if self.pbc_2d is True: - self.demag = clib.FFTDemag(self.dx, self.dy, self.dz, + self.demag = clib.FFTDemag(self.dx, self.dy, self.dz, self.nx, self.ny, self.nz, tensor_type='2d_pbc') nxyz = self.nx*self.ny*self.nz @@ -65,7 +67,7 @@ def setup(self, mesh, spin, Ms): if len(tensor_file_name) > 0 : if not (os.path.exists(tensor_file_name+'.npz')): - + self.demag.compute_tensors_2dpbc(tensors, pbc_2d_error, sample_repeat_nx, sample_repeat_ny, dipolar_radius) else: npzfile = np.load(tensor_file_name+'.npz') @@ -82,14 +84,15 @@ def setup(self, mesh, spin, Ms): else: self.demag.compute_tensors_2dpbc(tensors, pbc_2d_error, sample_repeat_nx, sample_repeat_ny, dipolar_radius) - + #print tensors self.demag.fill_demag_tensors(tensors) - + else: self.demag = clib.FFTDemag(self.dx, self.dy, self.dz, - self.nx, self.ny, self.nz, tensor_type='demag') + self.nx, self.ny, self.nz, + tensor_type='demag') diff --git a/fidimag/micro/dmi.py b/fidimag/micro/dmi.py index d5b1bf2e..d282fc0d 100644 --- a/fidimag/micro/dmi.py +++ b/fidimag/micro/dmi.py @@ -12,7 +12,7 @@ class DMI(Energy): compute the DMI field in micromagnetics """ - def __init__(self, D, name='dmi', dmi_type='bulk'): + def __init__(self, D, name='DMI', dmi_type='bulk'): """ type could be 'interfacial' or 'bulk' """ diff --git a/fidimag/micro/exchange.py b/fidimag/micro/exchange.py index bcb958a2..3f187f89 100644 --- a/fidimag/micro/exchange.py +++ b/fidimag/micro/exchange.py @@ -9,7 +9,7 @@ class UniformExchange(Energy): Compute the exchange field in micromagnetics. """ - def __init__(self, A, name='exch'): + def __init__(self, A, name='UniformExchange'): self.A = A self.name = name self.jac = True diff --git a/install/docker/Readme.md b/install/docker/Readme.md deleted file mode 100644 index ca7662e8..00000000 --- a/install/docker/Readme.md +++ /dev/null @@ -1,61 +0,0 @@ -# Docker - -First steps towards running fidimag through Docker. - -## Using the docker container - -There is a fidimag container available under `fangohr/fidimag`. - -To use it, you can try this: - -1. Install docker - -2. Pull the container onto your machine using - -`docker pull fangohr/fidimag` - -3. Start the container using - -`docker run -ti fangohr/fidimag` - -This command should show a bash prompt inside the docker container: - -
-bin:docker fangohr$ docker run -ti fangohr/fidimag
-fidimag@38fdd2a0feb4:~$
-
- -One way to test the installation is to run the unit tests: - -
-fidimag@38fdd2a0feb4:~$ cd fidimag/tests/
-fidimag@38fdd2a0feb4:~/fidimag/tests$ py.test -v 
-========== test session starts =======================
-platform linux2 -- Python 2.7.6 -- pytest-2.5.1 -- /usr/bin/python
-collected 63 items 
-
-field_test.py:7: test_initialise_scalar PASSED
-field_test.py:13: test_initialise_vector PASSED
-test_2dpbc_cube.py:10: test_compute_field PASSED
-test_anis.py:7: test_anis PASSED
-.
-.
-.
-
- -## Shortcomings - -- need to share directory between host and container (MOUNT or VOLUME) - -- make use of jupyter notebook work (as we have seen in FEniCS course): connect port in container to port on host machine (EXPOSE) - - - -## Creating the docker container - -The `Makefile` in this directory shows the relevant targets (build, login, push) to create a new container and push it to the the cloud. - - - - - diff --git a/tests/test_demag_libraries.py b/tests/test_demag_libraries.py index 99e34ece..37cbc2d1 100644 --- a/tests/test_demag_libraries.py +++ b/tests/test_demag_libraries.py @@ -67,9 +67,9 @@ def test_hexagonal_demags_1Dchain(): # Brute force demag calculation sim.add(DemagFull()) - sim.get_interaction('demag_full').compute_field() - sim.get_interaction('demag_full').field - demag_full_energy = sim.compute_energy() / const.meV + sim.get_interaction('DemagFull').compute_field() + sim.get_interaction('DemagFull').field + DemagFull_energy = sim.compute_energy() / const.meV # Demag using the FFT approach and a larger mesh sim2 = Sim(mesh) @@ -78,13 +78,13 @@ def test_hexagonal_demags_1Dchain(): sim2.set_m(lambda pos: m_init_dw(pos, N, a)) sim2.add(DemagHexagonal()) - sim2.get_interaction('demag_hex').compute_field() + sim2.get_interaction('DemagHexagonal').compute_field() sim2.compute_energy() demag_2fft_energy = sim2.compute_energy() / const.meV # We compare both energies scaled in meV - assert (demag_full_energy - demag_2fft_energy) < 1e-10 + assert (DemagFull_energy - demag_2fft_energy) < 1e-10 def test_cuboid_demags_1Dchain(): @@ -108,9 +108,9 @@ def test_cuboid_demags_1Dchain(): # Brute force demag calculation sim.add(DemagFull()) - sim.get_interaction('demag_full').compute_field() - # print sim.get_interaction('demag_full').field - demag_full_energy = sim.compute_energy() / const.meV + sim.get_interaction('DemagFull').compute_field() + # print sim.get_interaction('DemagFull').field + DemagFull_energy = sim.compute_energy() / const.meV # Demag using the FFT approach sim2 = Sim(mesh) @@ -119,13 +119,13 @@ def test_cuboid_demags_1Dchain(): sim2.set_m(lambda pos: m_init_dw(pos, N, a)) sim2.add(Demag()) - sim2.get_interaction('demag').compute_field() + sim2.get_interaction('Demag').compute_field() sim2.compute_energy() demag_fft_energy = sim2.compute_energy() / const.meV # We compare both energies scaled in meV - assert (demag_full_energy - demag_fft_energy) < 1e-10 + assert (DemagFull_energy - demag_fft_energy) < 1e-10 def test_cuboid_demags_2D(): @@ -154,9 +154,9 @@ def test_cuboid_demags_2D(): # Brute force demag calculation sim.add(DemagFull()) - sim.get_interaction('demag_full').compute_field() - # print sim.get_interaction('demag_full').field - demag_full_energy = sim.compute_energy() / const.meV + sim.get_interaction('DemagFull').compute_field() + # print sim.get_interaction('DemagFull').field + DemagFull_energy = sim.compute_energy() / const.meV # Demag using the FFT approach sim2 = Sim(mesh) @@ -165,13 +165,13 @@ def test_cuboid_demags_2D(): sim2.set_m(lambda pos: m_init_2Dvortex(pos, (xc, yc))) sim2.add(Demag()) - sim2.get_interaction('demag').compute_field() + sim2.get_interaction('Demag').compute_field() sim2.compute_energy() demag_fft_energy = sim2.compute_energy() / const.meV # We compare both energies scaled in meV - assert (demag_full_energy - demag_fft_energy) < 1e-10 + assert (DemagFull_energy - demag_fft_energy) < 1e-10 def test_hexagonal_demags_2D(): @@ -202,9 +202,9 @@ def test_hexagonal_demags_2D(): # Brute force demag calculation sim.add(DemagFull()) - sim.get_interaction('demag_full').compute_field() - sim.get_interaction('demag_full').field - demag_full_energy = sim.compute_energy() / const.meV + sim.get_interaction('DemagFull').compute_field() + sim.get_interaction('DemagFull').field + DemagFull_energy = sim.compute_energy() / const.meV # Demag using the FFT approach and a larger mesh sim2 = Sim(mesh) @@ -213,13 +213,13 @@ def test_hexagonal_demags_2D(): sim2.set_m(lambda pos: m_init_2Dvortex(pos, (xc, yc))) sim2.add(DemagHexagonal()) - sim2.get_interaction('demag_hex').compute_field() + sim2.get_interaction('DemagHexagonal').compute_field() sim2.compute_energy() demag_2fft_energy = sim2.compute_energy() / const.meV # We compare both energies scaled in meV - assert (demag_full_energy - demag_2fft_energy) < 1e-10 + assert (DemagFull_energy - demag_2fft_energy) < 1e-10 if __name__ == '__main__':