Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.10']
python-version: ['3.14']

runs-on: ubuntu-latest

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Fidimag solves finite-difference micromagnetic problems and supports atomistic s
See: [https://fidimag.readthedocs.io/en/latest/install.html](https://fidimag.readthedocs.io/en/latest/install.html)

### Features
* Optimal LLG equation integration using modern [Sundial's v6](https://github.com/LLNL/sundials/) CVODE solver
* Optimal LLG equation integration using modern [Sundial's v7](https://github.com/LLNL/sundials/) CVODE solver
* Offers LLG and LLG with spin torque terms (Zhang-Li and Sloncewski)
* Calculations using the Geodesic-Nudged-Elastic-Band and String methods to compute energy barriers.
* Exchange, Zeeman, Demagnetising, Uniaxial Anisotropy energy classes.
Expand Down
2 changes: 1 addition & 1 deletion bin/install-fftw.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# This script installs FFTW locally. It may need to environment
# variables to work, like 'export CC=gcc' in ARCHER.

FFTW=fftw-3.3.8
FFTW=fftw-3.3.10

set -e

Expand Down
19 changes: 15 additions & 4 deletions bin/install-sundials.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ set -e
# when SUNDIALS moved to a CMake-based installation. Will install locally.
# It may need environment variables to work, like `export CC=gcc` in ARCHER.

# Parse command line arguments
SILENT=true
if [[ "$1" == "--not-silent" ]]; then
SILENT=false
fi

# Github release from Sundials repository
# https://github.com/LLNL/sundials
SUNDIALS_TAG=v6.6.1
SUNDIALS=sundials-6.6.1
SUNDIALS_TAG=v7.6.0
SUNDIALS=sundials-7.6.0

# Make sure CMake is installed, since SUNDIALS requires it.
type cmake >/dev/null 2>&1 || { printf "CMake required to build SUNDIALS. You can install it by typing: \nsudo apt install cmake\n"; exit 1;}
Expand Down Expand Up @@ -42,10 +48,15 @@ download_and_cmake_install() {
cmake ${4} ../${2}

echo "Compiling and installing "${2}"."
{
if [ "$SILENT" = true ]; then
{
make -j2
make install
} > /dev/null
else
make -j2
make install
} > /dev/null
fi

echo "Cleaning up."
cd ..
Expand Down
2 changes: 2 additions & 0 deletions doc/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ though many Linux distributions come with these. Using the scripts provided in F
bash install-fftw.sh
bash install-sundials.sh

The installation script will automatically download and build SUNDIALS v7.6.0.

Python library dependencies are specified in the `pyproject.toml` file. We can install the `fidimag` library in editable mode, using `pip`:

.. code-block:: bash
Expand Down
4 changes: 3 additions & 1 deletion fidimag/common/dipolar/demag.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,9 @@ void finalize_plan(fft_demag_plan *restrict plan) {
fftw_free(plan->hy);
fftw_free(plan->hz);

fftw_cleanup_threads();
// Note: fftw_cleanup_threads() is a global cleanup function and should
// NOT be called per-object. It should only be called once at program exit.
// Calling it here causes crashes when multiple FFTDemag objects are used.

free(plan);
}
99 changes: 50 additions & 49 deletions fidimag/common/sundials/cvode.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ cdef extern from "sundials/sundials_context.h":
struct _SUNContext:
pass
ctypedef _SUNContext *SUNContext
void* SUN_COMM_NULL
int SUNContext_Create(void *comm, SUNContext *ctx)
int SUNContext_Free(SUNContext *ctx)


cdef extern from "sundials/sundials_types.h":
ctypedef double realtype
ctypedef bint booleantype
ctypedef double sunsunrealtype
ctypedef bint sunsunbooleantype

# Types for the Sundials Linear System initialization
cdef extern from "sundials/sundials_matrix.h":
Expand All @@ -42,22 +43,22 @@ cdef extern from "sundials/sundials_nvector.h":


cdef extern from "nvector/nvector_serial.h":
cdef N_Vector N_VMake_Serial(long int vec_length, realtype *v_data, SUNContext sunctx)
cdef N_Vector N_VMake_Serial(long int vec_length, double *v_data, SUNContext sunctx)
struct _N_VectorContent_Serial:
long int length
realtype *data
booleantype own_data
double *data
int own_data

ctypedef _N_VectorContent_Serial *N_VectorContent_Serial


cdef extern from "nvector/nvector_openmp.h":
cdef N_Vector N_VMake_OpenMP(long int vec_length, realtype *v_data, int num_threads, SUNContext sunctx)
cdef N_Vector N_VMake_OpenMP(long int vec_length, double *v_data, int num_threads, SUNContext sunctx)

struct _N_VectorContent_OpenMP:
long int length
realtype *data
booleantype own_data
double *data
int own_data
int num_threads

ctypedef _N_VectorContent_OpenMP *N_VectorContent_OpenMP
Expand Down Expand Up @@ -100,34 +101,34 @@ cdef extern from "cvode/cvode.h":
int CV_BAD_DKY
int CV_TOO_CLOSE

ctypedef int (*CVRhsFn)(realtype t, N_Vector y, N_Vector ydot, void *user_data)
ctypedef int (*CVRootFn)(realtype t, N_Vector y, realtype *gout, void *user_data)
ctypedef int (*CVRhsFn)(double t, N_Vector y, N_Vector ydot, void *user_data)
ctypedef int (*CVRootFn)(double t, N_Vector y, double *gout, void *user_data)

void *CVodeCreate(int lmm, SUNContext sunctx)
# int CVode "CVode"(void *cvode_mem, realtype tout, N_Vector yout, realtype *tret, int itask) nogil
# int CVode "CVode"(void *cvode_mem, double tout, N_Vector yout, double *tret, int itask) nogil
int CVodeSetUserData(void *cvode_mem, void *user_data)
int CVodeSetMaxOrd(void *cvode_mem, int maxord)
int CVodeSetMaxNumSteps(void *cvode_mem, long int mxsteps)
int CVodeSetMaxHnilWarns(void *cvode_mem, int mxhnil)
int CVodeSetStabLimDet(void *cvode_mem, booleantype stldet)
int CVodeSetInitStep(void *cvode_mem, realtype hin)
int CVodeSetMinStep(void *cvode_mem, realtype hmin)
int CVodeSetMaxStep(void *cvode_mem, realtype hmax)
int CVodeSetStopTime(void *cvode_mem, realtype tstop)
int CVodeSetStabLimDet(void *cvode_mem, int stldet)
int CVodeSetInitStep(void *cvode_mem, double hin)
int CVodeSetMinStep(void *cvode_mem, double hmin)
int CVodeSetMaxStep(void *cvode_mem, double hmax)
int CVodeSetStopTime(void *cvode_mem, double tstop)
int CVodeSetMaxErrTestFails(void *cvode_mem, int maxnef)
int CVodeSetMaxNonlinIters(void *cvode_mem, int maxcor)
int CVodeSetMaxConvFails(void *cvode_mem, int maxncf)
int CVodeSetNonlinConvCoef(void *cvode_mem, realtype nlscoef)
int CVodeSetNonlinConvCoef(void *cvode_mem, double nlscoef)
int CVodeSetIterType(void *cvode_mem, int iter)
int CVodeSetRootDirection(void *cvode_mem, int *rootdir)
int CVodeSetNoInactiveRootWarn(void *cvode_mem)
int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0)
int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol)
int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol)
int CVodeInit(void *cvode_mem, CVRhsFn f, double t0, N_Vector y0)
int CVodeReInit(void *cvode_mem, double t0, N_Vector y0)
int CVodeSStolerances(void *cvode_mem, double reltol, double abstol)
int CVodeSVtolerances(void *cvode_mem, double reltol, N_Vector abstol)
int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
int CVode(void *cvode_mem, realtype tout, N_Vector yout, realtype *tret, int itask)
int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky)
int CVode(void *cvode_mem, double tout, N_Vector yout, double *tret, int itask)
int CVodeGetDky(void *cvode_mem, double t, int k, N_Vector dky)
int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw)
int CVodeGetNumSteps(void *cvode_mem, long int *nsteps)
int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals)
Expand All @@ -136,20 +137,20 @@ cdef extern from "cvode/cvode.h":
int CVodeGetLastOrder(void *cvode_mem, int *qlast)
int CVodeGetCurrentOrder(void *cvode_mem, int *qcur)
int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred)
int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused)
int CVodeGetLastStep(void *cvode_mem, realtype *hlast)
int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur)
int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur)
int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfac)
int CVodeGetActualInitStep(void *cvode_mem, double *hinused)
int CVodeGetLastStep(void *cvode_mem, double *hlast)
int CVodeGetCurrentStep(void *cvode_mem, double *hcur)
int CVodeGetCurrentTime(void *cvode_mem, double *tcur)
int CVodeGetTolScaleFactor(void *cvode_mem, double *tolsfac)
int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight)
int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele)
int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals)
int CVodeGetRootInfo(void *cvode_mem, int *rootsfound)
int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps,
long int *nfevals, long int *nlinsetups,
long int *netfails, int *qlast,
int *qcur, realtype *hinused, realtype *hlast,
realtype *hcur, realtype *tcur)
int *qcur, double *hinused, double *hlast,
double *hcur, double *tcur)
int CVodeGetNumNonlinSolvIters(void *cvode_mem, long int *nniters)
int CVodeGetNumNonlinSolvConvFails(void *cvode_mem, long int *nncfails)
int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters, long int *nncfails)
Expand Down Expand Up @@ -180,17 +181,17 @@ cdef extern from "cvode/cvode_ls.h":
# int CVSpilsSetPrecType(void *cvode_mem, int pretype)
# int CVSpilsSetGSType(void *cvode_mem, int gstype)
# int CVSpilsSetMaxl(void *cvode_mem, int maxl)
# int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac)

ctypedef int (*CVLsPrecSetupFn)(realtype t, N_Vector y, N_Vector fy,
booleantype jok, booleantype *jcurPtr,
realtype gamma, void *user_data);
ctypedef int (*CVLsPrecSolveFn)(realtype t, N_Vector y, N_Vector fy,
N_Vector r, N_Vector z, realtype gamma,
realtype delta, int lr, void *user_data);
ctypedef int (*CVLsJacTimesSetupFn)(realtype t, N_Vector y,
# int CVSpilsSetEpsLin(void *cvode_mem, sunrealtype eplifac)

ctypedef int (*CVLsPrecSetupFn)(double t, N_Vector y, N_Vector fy,
int jok, int *jcurPtr,
double gamma, void *user_data);
ctypedef int (*CVLsPrecSolveFn)(double t, N_Vector y, N_Vector fy,
N_Vector r, N_Vector z, double gamma,
double delta, int lr, void *user_data);
ctypedef int (*CVLsJacTimesSetupFn)(double t, N_Vector y,
N_Vector fy, void *user_data);
ctypedef int (*CVLsJacTimesVecFn)(N_Vector v, N_Vector Jv, realtype t,
ctypedef int (*CVLsJacTimesVecFn)(N_Vector v, N_Vector Jv, double t,
N_Vector y, N_Vector fy,
void *user_data, N_Vector tmp);

Expand Down Expand Up @@ -312,8 +313,8 @@ cdef int cv_jtimes_openmp(N_Vector v, N_Vector Jv, double t, N_Vector y, N_Vecto
return 0


# static int PSolve(realtype tn, N_Vector u, N_Vector fu, N_Vector r, N_Vector z,
# realtype gamma, realtype delta, int lr, void *user_data);
# static int PSolve(sunrealtype tn, N_Vector u, N_Vector fu, N_Vector r, N_Vector z,
# sunrealtype gamma, sunrealtype delta, int lr, void *user_data);
cdef int psolve(double t, N_Vector y, N_Vector fy, N_Vector r, N_Vector z,
double gamma, double delta, int lr, void * user_data):
copy_nv2nv(z, r)
Expand Down Expand Up @@ -375,7 +376,7 @@ cdef class CvodeSolver(object):
# All of the SUNDIALS objects (vectors, linear and nonlinear solvers, matrices, etc.)
# that collectively form a SUNDIALS simulation, hold a reference to a common simulation context object
# defined by the SUNContext class.
SUNContext_Create(NULL, & self.sunctx);
SUNContext_Create(SUN_COMM_NULL, & self.sunctx);

# The recommended choices for lmm are CV ADAMS for nonstiff problems and CV BDF for
# stiff problems. The default Newton iteration is recommended for stiff problems, and
Expand Down Expand Up @@ -504,10 +505,10 @@ cdef class CvodeSolver(object):
return 0

# From exmaples: cvDiurnal_kry.c in Sundials repo:
# static int Precond(realtype tn, N_Vector u, N_Vector fu, booleantype jok,
# booleantype *jcurPtr, realtype gamma, void *user_data)
cdef int Precond(self, double t, N_Vector y, N_Vector fy, booleantype jok,
booleantype * jcurPtr, double gamma, void * user_data):
# static int Precond(sunrealtype tn, N_Vector u, N_Vector fu, sunbooleantype jok,
# sunbooleantype *jcurPtr, sunrealtype gamma, void *user_data)
cdef int Precond(self, double t, N_Vector y, N_Vector fy, int jok,
int * jcurPtr, double gamma, void * user_data):
if not jok:
copy_nv2arr(y, self.y)
return 0
Expand Down Expand Up @@ -600,7 +601,7 @@ cdef class CvodeSolver_OpenMP(object):
if jtimes_fun is not None:
self.has_jtimes = 1

SUNContext_Create(NULL, & self.sunctx);
SUNContext_Create(SUN_COMM_NULL, & self.sunctx);
# Newton iterator is set by default now (Sundials 4.0)
self.cvode_mem = CVodeCreate(CV_BDF, self.sunctx)

Expand Down Expand Up @@ -702,7 +703,7 @@ cdef class CvodeSolver_OpenMP(object):
return 0

cdef int Precond(self, double t, N_Vector y, N_Vector fy,
booleantype jok, booleantype * jcurPtr, double gamma,
int jok, int * jcurPtr, double gamma,
void * user_data):
if not jok:
copy_nv2arr_openmp(y, self.y)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ readme = "README.md"
# Not fully supported:
# license-files = ["LICENSE.txt"]
# license = "BSD-2-Clause"
requires-python = ">= 3.10"
requires-python = ">= 3.14"
dependencies = [
'numpy',
'scipy',
Expand Down
16 changes: 8 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,10 @@
# rpath: run-time search path for the sundials (cvode) and fftw library objects
com_link = ['-Wl,-rpath,{},-rpath,{}'.format(str(LIB_DIR), str(LIB_DIR64)), '-fopenmp']
lib_paths = [str(LIB_DIR), str(LIB_DIR64)]
com_libs = ['m', 'fftw3_omp', 'fftw3', 'sundials_cvodes', 'sundials_nvecserial', 'sundials_nvecopenmp', 'blas', 'lapack']
com_libs = ['m', 'fftw3_omp', 'fftw3', 'sundials_core', 'sundials_cvodes', 'sundials_nvecserial', 'sundials_nvecopenmp', 'blas', 'lapack']
com_args = ['-O3', '-Wno-cpp', '-Wno-unused-function', '-Wall', '-std=c99', '-fopenmp']
com_args_cpp = ['-O3', '-Wno-unused-function', '-Wall', '-std=c++14', '-fopenmp']

if 'SUNDIALS_INC' in os.environ:
com_inc.append(os.environ['SUNDIALS_INC'])

if 'FFTW_INC' in os.environ:
com_inc.append(os.environ['FFTW_INC'])

# Find all .pyx files with extensions (source files) -> relative paths
ROOT_DIR = MODULE_DIR / 'fidimag'
source_files = [s for s in ROOT_DIR.rglob('*.pyx')] # Paths
Expand All @@ -49,6 +43,12 @@

com_inc = [numpy.get_include(), str(INCLUDE_DIR)]

if 'SUNDIALS_INC' in os.environ:
com_inc.append(os.environ['SUNDIALS_INC'])

if 'FFTW_INC' in os.environ:
com_inc.append(os.environ['FFTW_INC'])

ext_modules = []
for i, (module, src) in enumerate(zip(ext_names, source_files)):
print(sYellow + f"Compiling module {module}" + sReset)
Expand Down Expand Up @@ -109,7 +109,7 @@ def get_version():
raise Exception("Couldn't find __version__ in %s" % pkg_init_path)


nthreads = multiprocessing.cpu_count()
nthreads = 0 # Disabled parallel compilation due to Python 3.14 multiprocessing issues (0 = no multiprocessing)
print(sYellow + f'Building with {nthreads} threads' + sReset)
setup(
name='fidimag',
Expand Down