mirror of
https://github.com/Cian-H/nanoconc.git
synced 2025-12-22 22:22:01 +00:00
Implemented property based testing via PyCall.jl and hypothesis.py
This commit is contained in:
161
.gitignore
vendored
161
.gitignore
vendored
@@ -72,6 +72,167 @@ Manifest.toml
|
|||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
# Project specific gitignores
|
# Project specific gitignores
|
||||||
# Original notes from when developing
|
# Original notes from when developing
|
||||||
notes/*
|
notes/*
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
name = "nanoconc"
|
name = "nanoconc"
|
||||||
uuid = "9a947172-b1ea-4b16-84a6-f3d50752424d"
|
uuid = "9a947172-b1ea-4b16-84a6-f3d50752424d"
|
||||||
authors = ["Cian Hughes <chughes000@gmail.com>"]
|
authors = ["Cian Hughes <chughes000@gmail.com>"]
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
||||||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||||
Debugger = "31a5f54b-26ea-5ae9-a837-f05ce5417438"
|
Debugger = "31a5f54b-26ea-5ae9-a837-f05ce5417438"
|
||||||
|
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
|
||||||
HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"
|
HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"
|
||||||
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
|
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
|
||||||
Memoize = "c03570c3-d221-55d1-a50c-7939bbd78826"
|
Memoize = "c03570c3-d221-55d1-a50c-7939bbd78826"
|
||||||
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||||
|
PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
|
||||||
QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
|
QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
|
||||||
XLSX = "fdbf4ff8-1666-58a4-91e7-1b58723a45e0"
|
XLSX = "fdbf4ff8-1666-58a4-91e7-1b58723a45e0"
|
||||||
|
|||||||
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
attrs==23.2.0
|
||||||
|
hypothesis==6.98.4
|
||||||
|
numpy==1.26.4
|
||||||
|
sortedcontainers==2.4.0
|
||||||
5
setup_venv.sh
Executable file
5
setup_venv.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
python -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
@@ -49,6 +49,7 @@ columns entitled "w","n" and "k" for wavelength in nm, n and k respectively)
|
|||||||
function addmaterial(z::Float64, am::Float64, rho::Float64, res::Float64,
|
function addmaterial(z::Float64, am::Float64, rho::Float64, res::Float64,
|
||||||
filepath::String, material::String, description::String;
|
filepath::String, material::String, description::String;
|
||||||
disp::Bool=true)
|
disp::Bool=true)
|
||||||
|
flag = false
|
||||||
try
|
try
|
||||||
flag = h5open(matfile, "r") do file
|
flag = h5open(matfile, "r") do file
|
||||||
has(file, material)
|
has(file, material)
|
||||||
@@ -96,6 +97,7 @@ An alternative version of the addmaterial function for materials with known mie
|
|||||||
function addmaterial(omp::Float64, om0::Float64, fv::Float64,
|
function addmaterial(omp::Float64, om0::Float64, fv::Float64,
|
||||||
filepath::String, material::String, description::String;
|
filepath::String, material::String, description::String;
|
||||||
disp::Bool=true)
|
disp::Bool=true)
|
||||||
|
flag = false
|
||||||
try
|
try
|
||||||
flag = h5open(matfile, "r") do file
|
flag = h5open(matfile, "r") do file
|
||||||
has(file, material)
|
has(file, material)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
[deps]
|
[deps]
|
||||||
AirspeedVelocity = "1c8270ee-6884-45cc-9545-60fa71ec23e4"
|
AirspeedVelocity = "1c8270ee-6884-45cc-9545-60fa71ec23e4"
|
||||||
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
|
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
|
||||||
PropCheck = "ca382230-33be-11e9-0059-d981d03070e4"
|
|
||||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ if abspath(PROGRAM_FILE) == @__FILE__
|
|||||||
current_package_version = Pkg.TOML.parsefile("$ROOT_DIR/Project.toml")["version"]
|
current_package_version = Pkg.TOML.parsefile("$ROOT_DIR/Project.toml")["version"]
|
||||||
|
|
||||||
function display_to_file(io, x)
|
function display_to_file(io, x)
|
||||||
show(IOContext(io, :limit => false), "text/plain", x)
|
show(IOContext(io, :limit => false, :color => true), "text/plain", x)
|
||||||
end
|
end
|
||||||
|
|
||||||
open("$ROOT_DIR/benchmarks/$current_package_version.txt", "w") do io
|
open("$ROOT_DIR/benchmarks/$current_package_version.ansi", "w") do io
|
||||||
println(io, "C Implementation")
|
println(io, "C Implementation")
|
||||||
display_to_file(io, result[1])
|
display_to_file(io, result[1])
|
||||||
println(io, "\n\nFortran Implementation")
|
println(io, "\n\nFortran Implementation")
|
||||||
|
|||||||
@@ -53,6 +53,6 @@ done
|
|||||||
|
|
||||||
# And, finally, we can compile the C, and Fortran implementations
|
# And, finally, we can compile the C, and Fortran implementations
|
||||||
cd $bhmie_dir
|
cd $bhmie_dir
|
||||||
gcc -shared -fPIC -o bhmie-c/bhmie.so bhmie-c/bhmie.c bhmie-c/complex.c bhmie-c/nrutil.c -lm -Wno-builtin-declaration-mismatch -Wno-implicit-function-declaration
|
gcc -g -shared -fPIC -o bhmie-c/bhmie.so bhmie-c/bhmie.c bhmie-c/complex.c bhmie-c/nrutil.c -lm -Wno-builtin-declaration-mismatch -Wno-implicit-function-declaration
|
||||||
gfortran -shared -fPIC -o bhmie-f/bhmie.so bhmie-f/bhmie.f
|
gfortran -g -shared -fPIC -o bhmie-f/bhmie.so bhmie-f/bhmie.f
|
||||||
gfortran -shared -fPIC -o bhmie-f/bhmie_f77.so bhmie-f/bhmie_f77.f
|
gfortran -g -shared -fPIC -o bhmie-f/bhmie_f77.so bhmie-f/bhmie_f77.f
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
using Test
|
using Test
|
||||||
|
using Random
|
||||||
using PropCheck
|
using PropCheck
|
||||||
|
using Debugger
|
||||||
|
using PyCall
|
||||||
|
|
||||||
|
|
||||||
include("../anchors.jl")
|
include("../anchors.jl")
|
||||||
|
|
||||||
import .Anchors: TEST_DIR, SRC_DIR
|
import .Anchors: TEST_DIR, SRC_DIR, ROOT_DIR
|
||||||
|
|
||||||
if !@isdefined TestUtils
|
if !@isdefined TestUtils
|
||||||
include(joinpath(TEST_DIR, "testutils.jl"))
|
include(joinpath(TEST_DIR, "testutils.jl"))
|
||||||
@@ -15,85 +19,129 @@ if !@isdefined FFIWraps
|
|||||||
include(joinpath(TEST_DIR, "ffi_wraps.jl"))
|
include(joinpath(TEST_DIR, "ffi_wraps.jl"))
|
||||||
end
|
end
|
||||||
|
|
||||||
# function julia_vs_c(args::Tuple{Float64, Float64, Float64, UInt32, Vector{Float64}, Vector{Float64}, Vector{Float64}, Vector{Float64}})
|
|
||||||
# x, cxref_re, cxref_im, nang, cxs1_re, cxs1_im, cxs2_re, cxs2_im = args
|
# Set up the Python environment
|
||||||
function julia_vs_c(x, cxref_re, cxref_im, nang, cxs1_re, cxs1_im, cxs2_re, cxs2_im)
|
run(`$ROOT_DIR/setup_venv.sh`)
|
||||||
cxref, cxs1, cxs2 = ComplexF64(cxref_re, cxref_im), ComplexF64.(cxs1_re, cxs1_im), ComplexF64.(cxs2_re, cxs2_im)
|
ENV["PYTHON"] = joinpath(ROOT_DIR, ".venv/bin/python")
|
||||||
x_c, cxref_c, nang_c, cxs1_c, cxs2_c = Float32(x), ComplexF32(cxref), UInt32(nang), ComplexF32.(cxs1), ComplexF32.(cxs2)
|
|
||||||
return isapprox(
|
@pyinclude(joinpath(TEST_DIR, "miemfp_tests.py"))
|
||||||
miemfp.bhmie(x, cxref, nang),
|
|
||||||
FFIWraps.bhmie_c(x_c, cxref_c, nang_c, cxs1_c, cxs2_c),
|
|
||||||
rtol=0.1,
|
miemfp.bhmie(
|
||||||
)
|
x::Float64,
|
||||||
|
cxref::ComplexF64,
|
||||||
|
nang::Int64,
|
||||||
|
s1::Vector{ComplexF64},
|
||||||
|
s2::Vector{ComplexF64},
|
||||||
|
) = miemfp.bhmie(x, cxref, UInt32(nang))
|
||||||
|
|
||||||
|
function miemfp.bhmie(
|
||||||
|
x::Float64,
|
||||||
|
cxref::ComplexF64,
|
||||||
|
nang::Int64,
|
||||||
|
s1::Vector{ComplexF64},
|
||||||
|
s2::Vector{ComplexF64},
|
||||||
|
event::PyObject,
|
||||||
|
)
|
||||||
|
event.clear()
|
||||||
|
result = miemfp.bhmie(x, cxref, nang, s1, s2)
|
||||||
|
event.set()
|
||||||
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
# function julia_vs_fortran(args::Tuple{Float64, Float64, Float64, UInt32, Vector{Float64}, Vector{Float64}, Vector{Float64}, Vector{Float64}})
|
FFIWraps.bhmie_fortran(
|
||||||
# x, cxref_re, cxref_im, nang, cxs1_re, cxs1_im, cxs2_re, cxs2_im = args
|
x::Float64,
|
||||||
function julia_vs_fortran(x, cxref_re, cxref_im, nang, cxs1_re, cxs1_im, cxs2_re, cxs2_im)
|
refrel::ComplexF64,
|
||||||
cxref, cxs1, cxs2 = ComplexF64(cxref_re, cxref_im), ComplexF64.(cxs1_re, cxs1_im), ComplexF64.(cxs2_re, cxs2_im)
|
nang::Int64,
|
||||||
x_f, cxref_f, nang_f, cxs1_f, cxs2_f = Float32(x), ComplexF32(cxref), Int32(nang), ComplexF32.(cxs1), ComplexF32.(cxs2)
|
s1::Vector{ComplexF64},
|
||||||
b = miemfp.bhmie(x, cxref, nang)
|
s2::Vector{ComplexF64},
|
||||||
f = FFIWraps.bhmie_fortran(x_f, cxref_f, nang_f, cxs1_f, cxs2_f)
|
) = FFIWraps.bhmie_fortran(
|
||||||
# open("bhmie_julia_vs_fortran.txt", "a") do io
|
Float32(x),
|
||||||
# println(io, "julia: ", b)
|
ComplexF32(refrel),
|
||||||
# println(io, "fortran: ", f)
|
Int32(nang),
|
||||||
# end
|
ComplexF32.(s1),
|
||||||
# return is_approx(b, f)
|
ComplexF32.(s2),
|
||||||
return isapprox(
|
|
||||||
miemfp.bhmie(x, cxref, nang),
|
|
||||||
FFIWraps.bhmie_fortran(x_f, cxref_f, nang_f, cxs1_f, cxs2_f),
|
|
||||||
rtol=0.1,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
# function julia_vs_fortran77(args::Tuple{Float64, Float64, Float64, UInt32, Vector{Float64}, Vector{Float64}, Vector{Float64}, Vector{Float64}})
|
|
||||||
# x, cxref_re, cxref_im, nang, cxs1_re, cxs1_im, cxs2_re, cxs2_im = args
|
|
||||||
function julia_vs_fortran77(x, cxref_re, cxref_im, nang, cxs1_re, cxs1_im, cxs2_re, cxs2_im)
|
|
||||||
cxref, cxs1, cxs2 = ComplexF64(cxref_re, cxref_im), ComplexF64.(cxs1_re, cxs1_im), ComplexF64.(cxs2_re, cxs2_im)
|
|
||||||
x_f, cxref_f, nang_f, cxs1_f, cxs2_f = Float32(x), ComplexF32(cxref), Int32(nang), ComplexF32.(cxs1), ComplexF32.(cxs2)
|
|
||||||
return isapprox(
|
|
||||||
miemfp.bhmie(x, cxref, nang),
|
|
||||||
FFIWraps.bhmie_fortran77(x_f, cxref_f, nang_f, cxs1_f, cxs2_f),
|
|
||||||
rtol=0.1,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
f64_gen = PropCheck.itype(Float64)
|
|
||||||
UInt32_gen = PropCheck.itype(UInt32)
|
|
||||||
f64_vec_gen = PropCheck.vector(isample(1:100), f64_gen)
|
|
||||||
bhmie_gen = PropCheck.interleave(
|
|
||||||
f64_gen,
|
|
||||||
f64_gen,
|
|
||||||
f64_gen,
|
|
||||||
UInt32_gen,
|
|
||||||
f64_vec_gen,
|
|
||||||
f64_vec_gen,
|
|
||||||
f64_vec_gen,
|
|
||||||
f64_vec_gen,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@testset "bhmie" begin
|
function FFIWraps.bhmie_fortran(
|
||||||
|
x::Float64,
|
||||||
|
refrel::ComplexF64,
|
||||||
|
nang::Int64,
|
||||||
|
s1::Vector{ComplexF64},
|
||||||
|
s2::Vector{ComplexF64},
|
||||||
|
event::PyObject,
|
||||||
|
)
|
||||||
|
event.clear()
|
||||||
|
result = FFIWraps.bhmie_fortran(x, refrel, nang, s1, s2)
|
||||||
|
event.set()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
FFIWraps.bhmie_fortran77(
|
||||||
|
x::Float64,
|
||||||
|
refrel::ComplexF64,
|
||||||
|
nang::Int64,
|
||||||
|
s1::Vector{ComplexF64},
|
||||||
|
s2::Vector{ComplexF64},
|
||||||
|
) = FFIWraps.bhmie_fortran77(
|
||||||
|
Float32(x),
|
||||||
|
ComplexF32(refrel),
|
||||||
|
Int32(nang),
|
||||||
|
ComplexF32.(s1),
|
||||||
|
ComplexF32.(s2),
|
||||||
|
)
|
||||||
|
|
||||||
|
function FFIWraps.bhmie_fortran77(
|
||||||
|
x::Float64,
|
||||||
|
refrel::ComplexF64,
|
||||||
|
nang::Int64,
|
||||||
|
s1::Vector{ComplexF64},
|
||||||
|
s2::Vector{ComplexF64},
|
||||||
|
event::PyObject,
|
||||||
|
)
|
||||||
|
event.clear()
|
||||||
|
result = FFIWraps.bhmie_fortran77(x, refrel, nang, s1, s2)
|
||||||
|
event.set()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
FFIWraps.bhmie_c(
|
||||||
|
x::Float64,
|
||||||
|
refrel::ComplexF64,
|
||||||
|
nang::Int64,
|
||||||
|
s1::Vector{ComplexF64},
|
||||||
|
s2::Vector{ComplexF64},
|
||||||
|
) = FFIWraps.bhmie_c(
|
||||||
|
Float32(x),
|
||||||
|
ComplexF32(refrel),
|
||||||
|
UInt32(nang),
|
||||||
|
ComplexF32.(s1),
|
||||||
|
ComplexF32.(s2),
|
||||||
|
)
|
||||||
|
|
||||||
|
function FFIWraps.bhmie_c(
|
||||||
|
x::Float64,
|
||||||
|
refrel::ComplexF64,
|
||||||
|
nang::Int64,
|
||||||
|
s1::Vector{ComplexF64},
|
||||||
|
s2::Vector{ComplexF64},
|
||||||
|
event::PyObject,
|
||||||
|
)
|
||||||
|
event.clear()
|
||||||
|
result = FFIWraps.bhmie_c(x, refrel, nang, s1, s2)
|
||||||
|
event.set()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
@testset "miemfp" begin
|
||||||
@testset "miemfp.bhmie" begin
|
@testset "miemfp.bhmie" begin
|
||||||
c_check = PropCheck.check(julia_vs_c, bhmie_gen)
|
event1, event2 = py"asyncio.Event"(), py"asyncio.Event"()
|
||||||
c_result = c_check == true
|
event1.set(), event2.set()
|
||||||
if !c_result
|
result, output = py"compare_bhmie_functions"(miemfp.bhmie, FFIWraps.bhmie_fortran, event1, event2)
|
||||||
println("Fail vs C, PropCheck:")
|
@test result
|
||||||
display(c_check)
|
result, output = py"compare_bhmie_functions"(miemfp.bhmie, FFIWraps.bhmie_fortran77, event1, event2)
|
||||||
end
|
@test result
|
||||||
@test c_result
|
result, output = py"compare_bhmie_functions"(miemfp.bhmie, FFIWraps.bhmie_c, event1, event2)
|
||||||
f_check = PropCheck.check(julia_vs_fortran, bhmie_gen)
|
@test result
|
||||||
f_result = f_check == true
|
|
||||||
if !f_result
|
|
||||||
println("Fail vs Fortran, PropCheck:")
|
|
||||||
display(f_check)
|
|
||||||
end
|
|
||||||
@test f_result
|
|
||||||
f77_check = PropCheck.check(julia_vs_fortran77, bhmie_gen)
|
|
||||||
f77_result = f77_check == true
|
|
||||||
if !f77_result
|
|
||||||
println("Fail vs Fortran77, PropCheck:")
|
|
||||||
display(f77_check)
|
|
||||||
end
|
|
||||||
@test f77_result
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
49
test/miemfp_tests.py
Normal file
49
test/miemfp_tests.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
from typing import List, Tuple
|
||||||
|
import asyncio
|
||||||
|
import numpy as np
|
||||||
|
from hypothesis import errors, given, settings, strategies as st # type: ignore
|
||||||
|
|
||||||
|
def compare_bhmie_functions(f1, f2, event1: asyncio.Event, event2: asyncio.Event) -> Tuple[bool, str]:
|
||||||
|
async def async_closure(
|
||||||
|
x: float,
|
||||||
|
cxref: Tuple[float, float],
|
||||||
|
cxs1: List[Tuple[float, float]],
|
||||||
|
cxs2: List[Tuple[float, float]],
|
||||||
|
) -> bool:
|
||||||
|
cxref = complex(*cxref)
|
||||||
|
cxs1 = [complex(*c) for c in cxs1]
|
||||||
|
cxs2 = [complex(*c) for c in cxs2]
|
||||||
|
|
||||||
|
# This is to ensure that only one instance of each function is running at a time
|
||||||
|
# to avoid memory issues in the FFI code
|
||||||
|
await event1.wait()
|
||||||
|
f1_result = f1(x, cxref, 2, cxs1, cxs2)[:2]
|
||||||
|
await event2.wait()
|
||||||
|
f2_result = f2(x, cxref, 2, cxs1, cxs2)[:2]
|
||||||
|
|
||||||
|
return np.all(np.isclose(f1_result, f2_result))
|
||||||
|
|
||||||
|
@settings(deadline=None)
|
||||||
|
@given(
|
||||||
|
# Must be bigger than an atom but still nanoscale
|
||||||
|
x=st.floats(min_value=0.1, max_value=100),
|
||||||
|
# Refractive indeces must be within a physically reasonable range
|
||||||
|
cxref=st.tuples(st.floats(min_value=0.1, max_value=4.0), st.floats(min_value=0.1, max_value=4.0)),
|
||||||
|
cxs1=st.lists(st.tuples(st.floats(min_value=0.1, allow_infinity=False), st.floats(min_value=0.1, allow_infinity=False)), min_size=10, max_size=100),
|
||||||
|
cxs2=st.lists(st.tuples(st.floats(min_value=0.1, allow_infinity=False), st.floats(min_value=0.1, allow_infinity=False)), min_size=10, max_size=100),
|
||||||
|
)
|
||||||
|
def sync_closure(
|
||||||
|
x: float,
|
||||||
|
cxref: Tuple[float, float],
|
||||||
|
cxs1: List[Tuple[float, float]],
|
||||||
|
cxs2: List[Tuple[float, float]],
|
||||||
|
) -> bool:
|
||||||
|
assert asyncio.run(async_closure(x, cxref, cxs1, cxs2))
|
||||||
|
|
||||||
|
try:
|
||||||
|
sync_closure()
|
||||||
|
return True, "Test passed"
|
||||||
|
except AssertionError as e:
|
||||||
|
return False, f"AssertionError: {str(e)}"
|
||||||
|
except errors.HypothesisException as e:
|
||||||
|
return False, f"HypothesisException: {str(e)}"
|
||||||
@@ -22,4 +22,9 @@ function test_from_serialized(fn::Function, filename::String)
|
|||||||
@test deep_compare([fn(a...; kw...) for (a, kw) in argskwargs], out)
|
@test deep_compare([fn(a...; kw...) for (a, kw) in argskwargs], out)
|
||||||
end
|
end
|
||||||
|
|
||||||
end # module TestUtils
|
function asymmetric_floatvec_to_complexvec(vec_a::Vector{Float32}, vec_b::Vector{Float32})
|
||||||
|
shortest = min(length(vec_a), length(vec_b))
|
||||||
|
ComplexF32.(vec_a[1:shortest], vec_b[1:shortest])
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user