diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 891bbf3a..aa440f61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,6 @@ jobs: libopenblas-dev \ liblapack-dev \ doxygen \ - libgsl-dev \ libsuitesparse-dev \ libsuperlu-dev \ python3-dev \ diff --git a/AGENTS.md b/AGENTS.md index e743c3c3..e9f84b47 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,7 +58,7 @@ make clean - **LAPACK/BLAS** - Linear algebra - **SuiteSparse** - Sparse matrix operations - **HDF5** - Data storage -- **GSL** - GNU Scientific Library +- **fortnum** - Numerical core (special functions, quadrature, ODE, root finding) - **SUNDIALS** - Numerical solvers ### Python Dependencies diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d1daed0..9bc4961d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,12 +53,14 @@ project(KAMEL LANGUAGES C CXX Fortran) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) +# OpenMP is a project-wide dependency: -fopenmp is on the global compile flags +# below, and libneo objects in the KiLCA link closure use OMP critical sections +# (GOMP_critical_*). Resolve the imported target once at top scope so it is +# visible to every subdirectory and can ride on targets' PUBLIC link interfaces. +find_package(OpenMP REQUIRED COMPONENTS C Fortran) + # Set architecture flags based on platform if(APPLE) - # On macOS, use libomp from Homebrew for OpenMP support - # find_package(OpenMP REQUIRED) - find_package(OpenMP REQUIRED C Fortran) - # Locate libomp from Homebrew find_program(BREW_EXECUTABLE brew HINTS /opt/homebrew/bin /usr/local/bin) if(BREW_EXECUTABLE) diff --git a/KIM/README.md b/KIM/README.md index 160d1668..58abcc2f 100644 --- a/KIM/README.md +++ b/KIM/README.md @@ -5,7 +5,7 @@ This is the integral plasma response model based on the code and model Kinetic L ### Required Libraries - **LAPACK/BLAS** - Linear algebra -- **GSL** - GNU Scientific Library +- **fortnum** - Special functions (Bessel) and error function - **HDF5** - Data storage (with Fortran bindings) - **SuiteSparse** - Sparse matrix operations (UMFPACK) - **SuperLU** - Sparse direct solver diff --git a/KIM/src/CMakeLists.txt b/KIM/src/CMakeLists.txt index 04cdad21..6340c89e 100644 --- a/KIM/src/CMakeLists.txt +++ b/KIM/src/CMakeLists.txt @@ -31,11 +31,6 @@ target_include_directories(KIM_lib PUBLIC "${CMAKE_BINARY_DIR}/OBJS/sparse/") # fortnum provides the special functions (bessel_in) used by FLR2_asymptotics. target_link_libraries(KIM_lib PUBLIC fortnum) -# TODO: unify this: either use the system library everywhere, or use the cloned version -# KiLCA uses the cloned libraries for now, QL-Balance the system libraries -find_package(GSL REQUIRED) -target_include_directories(KIM_lib PUBLIC "${GSL_INCLUDE_DIRS}") - find_package(LAPACK REQUIRED) if("${LAPACK_FOUND}") message(" ====== LAPACK was found! ======") @@ -111,13 +106,11 @@ if("${SUPERLU_FOUND}") endif() set(KILCA_PATH ${CMAKE_SOURCE_DIR}/KiLCA) -set(KiLCA_lib_path ${CMAKE_SOURCE_DIR}/build/install/lib/libKiLCA_Lib_V_2.4.2_MDNO_FPGEN_POLYNOMIAL_Release_64bit.a) # KiLCA is NOT linked to KIM_lib: KIM does not use any KiLCA symbols. # Previously PUBLIC, this caused duplicate library linking when QL-Balance # linked both KIM_lib and kilca_lib, corrupting symbol resolution order # and breaking KiLCA's wave solver (besselj failures, vacuum stitching errors). # KIM_exe links KiLCA directly via slatec (which provides the math routines). -target_link_libraries(KIM_lib PUBLIC GSL::gsl GSL::gslcblas) target_include_directories(KIM_lib PUBLIC ${KILCA_PATH}/math/) find_package(HDF5 COMPONENTS C Fortran HL REQUIRED) @@ -141,7 +134,7 @@ set_target_properties(KIM_exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/install/bin/") target_link_libraries(KIM_exe KIM_lib - "${KiLCA_lib_path}" + kilca_lib lapack slatec ) diff --git a/KIM/src/math/ddeabm/CMakeLists.txt b/KIM/src/math/ddeabm/CMakeLists.txt index adc9cbaa..f3a4c231 100644 --- a/KIM/src/math/ddeabm/CMakeLists.txt +++ b/KIM/src/math/ddeabm/CMakeLists.txt @@ -13,7 +13,8 @@ set(ddeabm_files dsteps.f ) add_library(ddeabm "${ddeabm_files}") -# ddeabm.f/ddes.f reference xermsg (and i1mach/d1mach via that path); those -# live in libslatec. Declare the dependency so the linker orders libslatec -# after libddeabm and resolves xermsg_ instead of dropping it. + +# ddeabm calls the slatec error machinery (xermsg and friends); declare the +# dependency explicitly so the static-archive link order resolves xermsg_ +# regardless of how the consuming executable orders its libraries. target_link_libraries(ddeabm PUBLIC slatec) diff --git a/KIM/tests/CMakeLists.txt b/KIM/tests/CMakeLists.txt index 1f5c039e..c98cd1dd 100644 --- a/KIM/tests/CMakeLists.txt +++ b/KIM/tests/CMakeLists.txt @@ -1,12 +1,13 @@ -# KiLCA library path (needed for tests that use KIM_lib symbols depending on KiLCA math) -set(KiLCA_lib_path ${CMAKE_SOURCE_DIR}/build/install/lib/libKiLCA_Lib_V_2.4.2_MDNO_FPGEN_POLYNOMIAL_Release_64bit.a) +# OpenMP runtime (GOMP_critical_* from libneo's OMP critical sections) is +# carried transitively by kilca_lib's PUBLIC link interface, so no per-target +# OpenMP linkage is needed here. # Optional: build QUADPACK/RKF45 integration comparison test add_executable(test_integration_methods ${CMAKE_SOURCE_DIR}/KIM/tests/test_integration_methods.f90) set_target_properties(test_integration_methods PROPERTIES OUTPUT_NAME test_integration_methods.x RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests/") -target_link_libraries(test_integration_methods KIM_lib "${KiLCA_lib_path}" lapack cerf ddeabm slatec) +target_link_libraries(test_integration_methods KIM_lib kilca_lib lapack cerf ddeabm slatec) add_test(NAME test_integration_methods COMMAND ${CMAKE_BINARY_DIR}/tests/test_integration_methods.x) @@ -34,7 +35,7 @@ set_target_properties(test_profile_input PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests/") # Links the full math set: using profile_input_m pulls KIM objects whose # transitive deps (W2_arr) need the hypergeometric routines from KiLCA/slatec. -target_link_libraries(test_profile_input KIM_lib "${KiLCA_lib_path}" lapack cerf ddeabm slatec) +target_link_libraries(test_profile_input KIM_lib kilca_lib lapack cerf ddeabm slatec) add_test(NAME test_profile_input COMMAND ${CMAKE_BINARY_DIR}/tests/test_profile_input.x) @@ -42,7 +43,7 @@ add_executable(test_profile_input_integration ${CMAKE_SOURCE_DIR}/KIM/tests/test set_target_properties(test_profile_input_integration PROPERTIES OUTPUT_NAME test_profile_input_integration.x RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests/") -target_link_libraries(test_profile_input_integration KIM_lib "${KiLCA_lib_path}" lapack cerf ddeabm slatec) +target_link_libraries(test_profile_input_integration KIM_lib kilca_lib lapack cerf ddeabm slatec) add_test(NAME test_profile_input_integration COMMAND ${CMAKE_BINARY_DIR}/tests/test_profile_input_integration.x) @@ -50,7 +51,7 @@ add_executable(test_kim_diagnostics ${CMAKE_SOURCE_DIR}/KIM/tests/test_kim_diagn set_target_properties(test_kim_diagnostics PROPERTIES OUTPUT_NAME test_kim_diagnostics.x RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests/") -target_link_libraries(test_kim_diagnostics KIM_lib "${KiLCA_lib_path}" lapack cerf ddeabm slatec) +target_link_libraries(test_kim_diagnostics KIM_lib kilca_lib lapack cerf ddeabm slatec) add_test(NAME test_kim_diagnostics COMMAND ${CMAKE_BINARY_DIR}/tests/test_kim_diagnostics.x) @@ -58,7 +59,7 @@ add_executable(test_ampere_matrices ${CMAKE_SOURCE_DIR}/KIM/tests/test_ampere_ma set_target_properties(test_ampere_matrices PROPERTIES OUTPUT_NAME test_ampere_matrices.x RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests/") -target_link_libraries(test_ampere_matrices KIM_lib "${KiLCA_lib_path}" lapack cerf ddeabm slatec) +target_link_libraries(test_ampere_matrices KIM_lib kilca_lib lapack cerf ddeabm slatec) add_test(NAME test_ampere_matrices COMMAND ${CMAKE_BINARY_DIR}/tests/test_ampere_matrices.x) @@ -69,7 +70,7 @@ add_executable(test_plag_coeff ${CMAKE_SOURCE_DIR}/KIM/tests/test_plag_coeff.f90 set_target_properties(test_plag_coeff PROPERTIES OUTPUT_NAME test_plag_coeff.x RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests/") -target_link_libraries(test_plag_coeff KIM_lib "${KiLCA_lib_path}" lapack cerf ddeabm slatec) +target_link_libraries(test_plag_coeff KIM_lib kilca_lib lapack cerf ddeabm slatec) add_test(NAME test_plag_coeff COMMAND ${CMAKE_BINARY_DIR}/tests/test_plag_coeff.x) @@ -77,7 +78,7 @@ add_executable(test_findIndex ${CMAKE_SOURCE_DIR}/KIM/tests/test_findIndex.f90) set_target_properties(test_findIndex PROPERTIES OUTPUT_NAME test_findIndex.x RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests/") -target_link_libraries(test_findIndex KIM_lib "${KiLCA_lib_path}" lapack cerf ddeabm slatec) +target_link_libraries(test_findIndex KIM_lib kilca_lib lapack cerf ddeabm slatec) add_test(NAME test_findIndex COMMAND ${CMAKE_BINARY_DIR}/tests/test_findIndex.x) @@ -85,7 +86,7 @@ add_executable(test_grid_equidistant ${CMAKE_SOURCE_DIR}/KIM/tests/test_grid_equ set_target_properties(test_grid_equidistant PROPERTIES OUTPUT_NAME test_grid_equidistant.x RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests/") -target_link_libraries(test_grid_equidistant KIM_lib "${KiLCA_lib_path}" lapack cerf ddeabm slatec) +target_link_libraries(test_grid_equidistant KIM_lib kilca_lib lapack cerf ddeabm slatec) add_test(NAME test_grid_equidistant COMMAND ${CMAKE_BINARY_DIR}/tests/test_grid_equidistant.x) @@ -94,7 +95,7 @@ add_executable(test_kim_solver ${CMAKE_SOURCE_DIR}/KIM/tests/test_kim_solver.f90 set_target_properties(test_kim_solver PROPERTIES OUTPUT_NAME test_kim_solver.x RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests/") -target_link_libraries(test_kim_solver KIM_lib "${KiLCA_lib_path}" lapack cerf ddeabm slatec) +target_link_libraries(test_kim_solver KIM_lib kilca_lib lapack cerf ddeabm slatec) add_test(NAME test_kim_solver COMMAND ${CMAKE_BINARY_DIR}/tests/test_kim_solver.x) @@ -103,7 +104,7 @@ add_executable(test_kim_solver_em ${CMAKE_SOURCE_DIR}/KIM/tests/test_kim_solver_ set_target_properties(test_kim_solver_em PROPERTIES OUTPUT_NAME test_kim_solver_em.x RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests/") -target_link_libraries(test_kim_solver_em KIM_lib "${KiLCA_lib_path}" lapack cerf ddeabm slatec) +target_link_libraries(test_kim_solver_em KIM_lib kilca_lib lapack cerf ddeabm slatec) configure_file(${CMAKE_SOURCE_DIR}/KIM/tests/test_data/KIM_config_em_small.nml ${CMAKE_BINARY_DIR}/tests/KIM_config_em_small.nml COPYONLY) add_test(NAME test_kim_solver_em diff --git a/KiLCA/CMakeLists.txt b/KiLCA/CMakeLists.txt index d8e63fa8..51a34442 100644 --- a/KiLCA/CMakeLists.txt +++ b/KiLCA/CMakeLists.txt @@ -109,9 +109,8 @@ set (kilca_eigparam_main progs/main_eig_param.cpp) # include paths: set (libs_root_path ${CMAKE_BINARY_DIR}/external-install) -set (gsl_include_path ${libs_root_path}/gsl/include) -set(EXTERNAL_LIBS slatec lapack blas SUNDIALS::cvode SUNDIALS::nvecserial fortnum gsl gslcblas) +set(EXTERNAL_LIBS slatec lapack blas SUNDIALS::cvode SUNDIALS::nvecserial fortnum) # configure a header file to pass some of the CMake settings to the source code configure_file( @@ -121,7 +120,6 @@ configure_file( # Make generated header available include_directories("${CMAKE_CURRENT_BINARY_DIR}") -include_directories ("${gsl_include_path}") # fortnum C ABI header (fortnum.h); the Fortran fortnum target is linked above. include_directories ("${fortnum_SOURCE_DIR}/include") include_directories ("${PROJECT_BINARY_DIR}") @@ -251,7 +249,11 @@ set_target_properties(kilca_lib PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/install/lib/ Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/OBJS/kilca/) add_dependencies(kilca_lib ${EXTERNAL_LIBS}) -target_link_libraries(kilca_lib PUBLIC ${EXTERNAL_LIBS}) +# libneo objects pulled into the KiLCA link closure use OMP critical sections +# (GOMP_critical_*). Carry the OpenMP runtime on kilca_lib's PUBLIC interface so +# every consumer (KIM_exe, ql-balance_lib, and all KIM tests) inherits it and no +# downstream target has to re-declare OpenMP to link. +target_link_libraries(kilca_lib PUBLIC ${EXTERNAL_LIBS} OpenMP::OpenMP_Fortran) # Add include directories on `kilca_lib` target for all source and module paths target_include_directories(kilca_lib PUBLIC @@ -284,7 +286,6 @@ target_include_directories(kilca_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/spline # External dependencies ${sundials_include_path} - ${gsl_include_path} ${fortnum_SOURCE_DIR}/include ) diff --git a/KiLCA/interface/make_it b/KiLCA/interface/make_it index 889f947f..a12f39c8 100755 --- a/KiLCA/interface/make_it +++ b/KiLCA/interface/make_it @@ -18,4 +18,4 @@ kilca_64bit="KiLCA_Lib_V_2.4_MDNO_FPGEN_USUAL_Debug_64bit" #kilca_64bit="KiLCA_Lib_V_2.4_MDYES_FPGEN_POLYNOMIAL_Debug_64bit" #kilca_64bit="libkilca_64bit" -gfortran ql-balance_mod.f90 wave_code_data_64bit.f90 bessel.f90 amn_of_r.f90 test_interface.f90 -L$kilca_lib_path -l$kilca_64bit -L$cvode_lib_path -lsundials_cvode -lsundials_nvecserial -L$slatec_lib_path -lslatec -lgsl -lgslcblas -lblas -llapack -lm -lc -lgfortran -lstdc++ +gfortran ql-balance_mod.f90 wave_code_data_64bit.f90 bessel.f90 amn_of_r.f90 test_interface.f90 -L$kilca_lib_path -l$kilca_64bit -L$cvode_lib_path -lsundials_cvode -lsundials_nvecserial -L$slatec_lib_path -lslatec -lfortnum -lblas -llapack -lm -lc -lgfortran -lstdc++ diff --git a/KiLCA/math/fourier/mk_fourier b/KiLCA/math/fourier/mk_fourier index 9a5c51cb..db421871 100644 --- a/KiLCA/math/fourier/mk_fourier +++ b/KiLCA/math/fourier/mk_fourier @@ -64,7 +64,7 @@ cvode_lib_path = /usr/local/lib libs = -L$(LINKER_PATH) \ -L$(math_lib_path) -lslatec_gf_430 -llapack_gf_430 -lblas_gf_430 \ -L$(cvode_lib_path) -lsundials_cvode -lsundials_nvecserial \ --lgsl -lgslcblas \ +-lfortnum \ -lgfortran \ -lstdc++ diff --git a/KiLCA/math/hyper/Makefile b/KiLCA/math/hyper/Makefile index 4f0cb870..c46515c8 100644 --- a/KiLCA/math/hyper/Makefile +++ b/KiLCA/math/hyper/Makefile @@ -47,13 +47,13 @@ LINKER_PATH = /usr/local/gcc$(COMPILER_PREFIX)/lib math_lib_path = /usr/local/lib/math_lib cvode_lib_path = /usr/local/lib -libs = -lgsl -lstdc++ +libs = -lfortnum -lstdc++ # libs = -L$(LINKER_PATH) \ # -L$(math_lib_path) -lslatec_gf_430 -llapack_gf_430 -lblas_gf_430 \ # -L$(cvode_lib_path) -lsundials_cvode -lsundials_nvecserial \ -# -lgsl -lgslcblas \ +# -lfortnum \ # -lgfortran \ # -lstdc++ diff --git a/QL-Balance/CMakeLists.txt b/QL-Balance/CMakeLists.txt index 70a5d3d1..5f88161a 100644 --- a/QL-Balance/CMakeLists.txt +++ b/QL-Balance/CMakeLists.txt @@ -154,8 +154,6 @@ target_link_libraries(ql-balance_lib PUBLIC SUNDIALS::nvecserial blas fortnum - gsl - gslcblas hdf5::hdf5 hdf5::hdf5_fortran hdf5::hdf5_hl diff --git a/README.md b/README.md index b9ad348a..10f1b3a8 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ The framework consists of three main codes: ### Auto-Fetched Libraries The following are automatically downloaded and built if not found on the system: -- **GSL** - GNU Scientific Library +- **fortnum** - Numerical core (special functions, quadrature, ODE, root finding) - **SuiteSparse** - Sparse matrix operations (UMFPACK) - **SUNDIALS** - Numerical differential equation solvers - **NetCDF** - Network Common Data Form (with Fortran bindings) @@ -60,7 +60,7 @@ make QL-Balance make clean ``` -**Note:** External dependencies (LAPACK, SuiteSparse, GSL, SUNDIALS) are automatically downloaded and built during the first compilation if not found on the system. +**Note:** External dependencies (LAPACK, SuiteSparse, fortnum, SUNDIALS) are automatically downloaded and built during the first compilation if not found on the system. To pin libneo to a specific branch, tag, or commit, pass `-DLIBNEO_REF=` to cmake or `LIBNEO_REF=` to make. To use a local checkout instead of fetching, pass `-DLIBNEO_PATH=` / `LIBNEO_PATH=`. diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index c886cede..b7c410a4 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -5,7 +5,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") # Core dependencies -include(FetchGSL) include(FetchLapack) include(FetchNetcdf) include(FetchSuiteSparse) diff --git a/cmake/FetchGSL.cmake b/cmake/FetchGSL.cmake deleted file mode 100644 index 51838ea8..00000000 --- a/cmake/FetchGSL.cmake +++ /dev/null @@ -1,42 +0,0 @@ -include(ExternalProject) - -if(NOT DEFINED GSL_INSTALL_DIR) - set(GSL_INSTALL_DIR - ${CMAKE_BINARY_DIR}/external-install/gsl - CACHE PATH "Where to install GSL headers & libs") -endif() - -ExternalProject_Add(EXTERNAL_gsl - PREFIX ${CMAKE_BINARY_DIR}/download - URL https://mirror.easyname.at/gnu/gsl/gsl-2.4.tar.gz - DOWNLOAD_NAME gsl-2.4.tar.gz - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - BUILD_IN_SOURCE TRUE - - CONFIGURE_COMMAND - /configure --prefix=${GSL_INSTALL_DIR} - - BUILD_COMMAND - make -C -j - - INSTALL_COMMAND - make -C install - - BUILD_BYPRODUCTS - ${GSL_INSTALL_DIR}/lib/libgsl.a - ${GSL_INSTALL_DIR}/lib/libgslcblas.a -) - -add_library(gsl STATIC IMPORTED GLOBAL) -set_target_properties(gsl PROPERTIES - IMPORTED_LOCATION - "${GSL_INSTALL_DIR}/lib/libgsl.a" -) -add_dependencies(gsl EXTERNAL_gsl) - -add_library(gslcblas STATIC IMPORTED GLOBAL) -set_target_properties(gslcblas PROPERTIES - IMPORTED_LOCATION - "${GSL_INSTALL_DIR}/lib/libgslcblas.a" -) -add_dependencies(gslcblas EXTERNAL_gsl) diff --git a/python/susc_functions/f2py_Ifuncs.sh b/python/susc_functions/f2py_Ifuncs.sh index 1e88f8f9..9cf42a97 100755 --- a/python/susc_functions/f2py_Ifuncs.sh +++ b/python/susc_functions/f2py_Ifuncs.sh @@ -9,8 +9,7 @@ f2py -c src/getIfunc.f90 src/W2_arr.f90 $curr_loc/../../KiLCA/flre/conductivity/ -L$libs_path/sundials/build/src/nvector/serial/ -lsundials_nvecserial \ -L$libs_path/slatec/ -lslatec \ -L$libs_path/bessel/lib/ -lbessel \ - -lgsl \ - -lgslcblas \ + -L$libs_path -lfortnum \ -lm \ -lc \ --verbose diff --git a/utility_scripts/setup_arch.sh b/utility_scripts/setup_arch.sh index 5a4615b8..819b545c 100755 --- a/utility_scripts/setup_arch.sh +++ b/utility_scripts/setup_arch.sh @@ -8,7 +8,6 @@ sudo pacman -Sy \ gcc \ gcc-fortran \ git \ - gsl \ make \ netcdf \ netcdf-cxx \ diff --git a/utility_scripts/setup_debian.sh b/utility_scripts/setup_debian.sh index 966f9f88..e9d530b2 100755 --- a/utility_scripts/setup_debian.sh +++ b/utility_scripts/setup_debian.sh @@ -2,5 +2,5 @@ sudo apt update && apt install -y wget git cmake make gcc g++ gfortran \ libnetcdf-dev libnetcdff-dev openmpi-bin libopenmpi-dev libfftw3-dev \ - python3 python3-pip python3-numpy python3-scipy ninja-build libgsl-dev \ + python3 python3-pip python3-numpy python3-scipy ninja-build \ libopenblas-dev