Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add darwin and clang 17 support #123

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
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
10 changes: 5 additions & 5 deletions a5py/ascotpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from a5py.routines.plotting import openfigureifnoaxes, plt
from a5py.exceptions import AscotInitException

from .libascot import LibAscot, _LIBASCOT
from .libascot import LibAscot, _LIBASCOT, _get_struct_class
from .libsimulate import LibSimulate
from .libproviders import LibProviders

Expand Down Expand Up @@ -87,13 +87,13 @@ def __init__(self):
self._offload_ready = False
self._nmrk = ctypes.c_int32()
self._diag_occupied = False
self._offload_data = ascot2py.struct_c__SA_offload_package()
self._offload_data = _get_struct_class("offload_package")()
self._offload_array = ctypes.POINTER(ctypes.c_double)()
self._int_offload_array = ctypes.POINTER(ctypes.c_int )()
self._inistate = ctypes.POINTER(ascot2py.struct_c__SA_particle_state)()
self._endstate = ctypes.POINTER(ascot2py.struct_c__SA_particle_state)()
self._inistate = ctypes.POINTER(_get_struct_class("particle_state"))()
self._endstate = ctypes.POINTER(_get_struct_class("particle_state"))()

self._sim = ascot2py.struct_c__SA_sim_offload_data()
self._sim = _get_struct_class("sim_offload_data")()
self._bfield_offload_array = ctypes.POINTER(ctypes.c_double)()
self._efield_offload_array = ctypes.POINTER(ctypes.c_double)()
self._plasma_offload_array = ctypes.POINTER(ctypes.c_double)()
Expand Down
31 changes: 26 additions & 5 deletions a5py/ascotpy/libascot.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,35 @@ def from_param(cls, obj):
return type(base.__name__, (base,),
{'from_param': classmethod(from_param)})

def _get_struct_class(struct_cname: str) -> type[ctypes.Structure]:
"""Get the ctypes class of a struct by its C name.

Required because ctypeslib returns different names depending on the
version of clang used to compile the C code.

Parameters
----------
struct_cname : str
Name of the struct in the C code.

Returns
-------
out : ctypes.Structure
The ctypes class of the struct.
"""
for name, obj in ascot2py.__dict__.items():
if name.startswith("struct_") and struct_cname in name:
return obj
return ctypes.Structure

PTR_REAL = _ndpointerwithnull(ctypes.c_double, flags="C_CONTIGUOUS")
PTR_INT = _ndpointerwithnull(ctypes.c_int, flags="C_CONTIGUOUS")
PTR_SIM = ctypes.POINTER(ascot2py.struct_c__SA_sim_offload_data)
PTR_SIM = ctypes.POINTER(_get_struct_class("sim_offload_data"))
PTR_ARR = ctypes.POINTER(ctypes.c_double)
STRUCT_DIST5DOFFLOAD = ascot2py.struct_c__SA_dist_5D_offload_data
STRUCT_DIST5D = ascot2py.struct_c__SA_dist_5D_data
STRUCT_AFSITHERMAL = ascot2py.struct_c__SA_afsi_thermal_data
STRUCT_AFSIDATA = ascot2py.struct_c__SA_afsi_data
STRUCT_DIST5DOFFLOAD = _get_struct_class("dist_5D_offload_data")
STRUCT_DIST5D = _get_struct_class("dist_5D_data")
STRUCT_AFSITHERMAL = _get_struct_class("afsi_thermal_data")
STRUCT_AFSIDATA = _get_struct_class("afsi_data")
AFSI_REACTIONS = ascot2py.Reaction__enumvalues
_LIBASCOT = ascot2py._libraries['libascot.so']

Expand Down
8 changes: 4 additions & 4 deletions a5py/ascotpy/libsimulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from a5py.routines.virtualrun import VirtualRun, VirtualBBNBIRun
from a5py.exceptions import *

from .libascot import _LIBASCOT
from .libascot import _LIBASCOT, _get_struct_class
if _LIBASCOT:
from . import ascot2py

Expand Down Expand Up @@ -341,7 +341,7 @@ def parse(r, phi, z, time, pitch, weight, ids):
p.id = ids[i]

def initmarkers():
ps = ctypes.pointer(ascot2py.struct_c__SA_particle_state())
ps = ctypes.pointer(_get_struct_class("particle_state")())
self._nmrk.value = nmrk
n_proc = ctypes.c_int32(0)
ascot2py.prepare_markers(
Expand Down Expand Up @@ -421,7 +421,7 @@ def simulation_run(self, printsummary=True):
setattr(inistate[j], name, val)

# Initialize diagnostics array and endstate
self._endstate = ctypes.pointer(ascot2py.struct_c__SA_particle_state())
self._endstate = ctypes.pointer(_get_struct_class("particle_state")())
ascot2py.diag_init_offload(ctypes.byref(self._sim.diag_offload_data),
ctypes.byref(self._diag_offload_array),
self._nmrk)
Expand Down Expand Up @@ -523,7 +523,7 @@ def simulation_bbnbi(self, nprt, t1=0, t2=0, printsummary=True):
raise AscotInitException(
"Free previous results before running the simulation")
# Initialize diagnostics array and endstate
self._endstate = ctypes.pointer(ascot2py.struct_c__SA_particle_state())
self._endstate = ctypes.pointer(_get_struct_class("particle_state")())
ascot2py.diag_init_offload(ctypes.byref(self._sim.diag_offload_data),
ctypes.byref(self._diag_offload_array),
nprt)
Expand Down
37 changes: 29 additions & 8 deletions src/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
CC=h5cc
LFLAGS=


ifdef TRAP_FPE
DEFINES+=-DTRAP_FPE=$(TRAP_FPE)
CFLAGS+= -fsignaling-nans -ftrapping-math
Expand Down Expand Up @@ -53,9 +54,25 @@ ifeq ($(DEBUG),1)
else
CFLAGS+=-O2
endif
CFLAGS+=-lm -Wall -fopenmp -fPIC -std=c11 -D_XOPEN_SOURCE=700 \
CFLAGS+=-Wall -fopenmp -fPIC -std=c11 -D_XOPEN_SOURCE=700 \
$(DEFINES) $(FLAGS)

UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
CFLAGS+=-D_DARWIN_C_SOURCE # for MONOTONIC_CLOCK_RAW
H5_INCLUDES=$(shell dirname $(shell which h5cc))/../include
CLANG2PY_ARGS=$(CFLAGS) -I$(H5_INCLUDES)
# For MacOS, we need to add the clang library path to the environment
# since built-in clang doesn't have openmp support enabled by default
ascot2py.py: export CLANG_LIBRARY_PATH=$(shell $(CC) --print-resource-dir)/../..
endif
ifeq ($(UNAME_S),Linux)
ifdef CONDA_PREFIX
CLANG2PY_ARGS=-I$(CONDA_PREFIX)/include/ \
-I$(CONDA_PREFIX)/x86_64-conda-linux-gnu/sysroot/usr/include/
endif
endif

# Write CFLAGS and CC to a file to be included into output
$(shell echo "#define CFLAGS " $(CFLAGS) > compiler_flags.h)
$(shell echo "#define CC " $(CC) >> compiler_flags.h)
Expand Down Expand Up @@ -155,15 +172,20 @@ all: $(BINS)
libascot: libascot.so
true

libascot.so: CFLAGS+=-fPIC -shared

ifeq ($(CC),h5cc)
libascot.so: CFLAGS+=-shlib
ifeq ($(UNAME_S),Darwin)
ifeq ($(CC), $(filter $(CC), h5cc h5pcc))
# don't share the hdf5 library since it isn't the same as h5py anyway
# also.. non't need -shared -lm or -fPIC on MacOS.. they are default/redundant
libascot.so: CFLAGS+=-noshlib
endif
else

ifeq ($(CC),h5pcc)
libascot.so: CFLAGS+=-fPIC -shared -lm

ifeq ($(CC), $(filter $(CC), h5cc h5pcc))
libascot.so: CFLAGS+=-shlib
endif
endif

libascot.so: libascot.o ascot5_main.o libascot_mem.o afsi.o bbnbi5.o $(OBJS)
$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS)
Expand Down Expand Up @@ -241,8 +263,7 @@ ASCOT2PY_HEADERFILES=ascot5.h particle.h mpi_interface.h endcond.h simulate.h \
ascot2py.py : libascot.so
$(eval CLANGOMP=$(shell clang --print-resource-dir)) \
clang2py -l libascot.so -o $@ $(ASCOT2PY_HEADERFILES) \
--clang-args="-I$(CLANGOMP)/include/ -I$(CONDA_PREFIX)/include/\
-I$(CONDA_PREFIX)/x86_64-conda-linux-gnu/sysroot/usr/include/"
--clang-args="$(CLANG2PY_ARGS) -I$(CLANGOMP)/include/"

clean:
@rm -f *.o *.so *.test *.optrpt $(BINS) $(SIMDIR)*.o $(STEPDIR)*.o \
Expand Down