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

Full test suite #82

Merged
merged 14 commits into from
Nov 29, 2023
4 changes: 2 additions & 2 deletions .github/actions/test/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ runs:
shell: bash
working-directory: test_suite
run: |
wget https://ipag.osug.fr/~pintec/mcfost/test_data_ee572a652377a58197232071980657f7f7fbc3f9.tar.gz
wget -nv https://ipag.osug.fr/~pintec/mcfost/test_data_0c484a1a905c13bea4c3bc0494ba288daddbe779.tgz
rm -rf test_data
tar xzf test_data_ee572a652377a58197232071980657f7f7fbc3f9.tar.gz
tar xzf test_data_0c484a1a905c13bea4c3bc0494ba288daddbe779.tgz

# Only do this if not in manylinux docker container
- uses: actions/setup-python@v4
Expand Down
6 changes: 5 additions & 1 deletion src/Voronoi.f90
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ subroutine Voronoi_tesselation(n_points, particle_id, x,y,z,h, vx,vy,vz, is_ghos
real(kind=dp), parameter :: threshold = 3 ! defines at how many h cells will be cut
character(len=2) :: unit

logical, parameter :: lrandom = .true.
logical :: lrandom
integer, dimension(:), allocatable :: order,SPH_id2,SPH_original_id2
real(kind=dp), dimension(:), allocatable :: x_tmp2,y_tmp2,z_tmp2,h_tmp2

Expand Down Expand Up @@ -299,6 +299,10 @@ subroutine Voronoi_tesselation(n_points, particle_id, x,y,z,h, vx,vy,vz, is_ghos
n_cells = icell
n_cells_per_cpu = (1.0*n_cells) / nb_proc_voro + 1


lrandom = .true.
if (lnot_random_Voronoi) lrandom = .false.

! Randomizing particles
if (lrandom) then
allocate(x_tmp2(n_cells), y_tmp2(n_cells), z_tmp2(n_cells), h_tmp2(n_cells), &
Expand Down
5 changes: 5 additions & 0 deletions src/init_mcfost.f90
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ subroutine set_default_variables()
llinear_rgrid = .false.
image_offset_centre(:) = (/0.0,0.0,0.0/)
loverwrite_s12 = .false.
lnot_random_Voronoi = .false.

tmp_dir = "./"

Expand Down Expand Up @@ -1459,6 +1460,9 @@ subroutine initialisation_mcfost()
call get_command_argument(i_arg,s)
read(s,*) v_syst
i_arg = i_arg + 1
case("-not_random_Voronoi")
i_arg = i_arg + 1
lnot_random_Voronoi = .true.
case default
write(*,*) "Error: unknown option: "//trim(s)
write(*,*) "Use 'mcfost -h' to get list of available options"
Expand Down Expand Up @@ -2068,6 +2072,7 @@ subroutine display_help()
write(*,*) " : -SPH_amax <size> [mum] : force the grain size that follow the dust"
write(*,*) " (only works with 1 grain size dump)"
write(*,*) " : -force_Mgas : force the gas mass to be the value given the mcfost parameter file"
write(*,*) " : -not_random_Voronoi : force the particle order to remain the same"
write(*,*) ""
write(*,*) "You can find the full documentation at:"
write(*,*) trim(doc_webpage)
Expand Down
4 changes: 2 additions & 2 deletions src/parameters.f90
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ module parametres
!if limit_mem == 1: the continua are stored on a small frequency grid and interpolated locally on the full grid.
! This approach is faster than computing the continua for each wavelength point, and is relatively cheap in ram.
! -> good trade-off between 0 and 2.
!if limit_mem == 2: everything is computed locally on the full grid. Slow but cheap in memory.
!if limit_mem == 2: everything is computed locally on the full grid. Slow but cheap in memory.

! Decomposition image
logical :: lsepar_contrib, lsepar_pola, lonly_capt_interet, lsepar_ori
Expand Down Expand Up @@ -162,7 +162,7 @@ module parametres
logical :: ldelete_inside_rsph, ldelete_outside_rsph, ldelete_above_theta
real(kind=dp) :: ufac_implicit,scale_length_units_factor,scale_mass_units_factor,correct_density_factor_elongated_cells
real(kind=dp) :: SPH_amin, SPH_amax, fluffyness, gap_factor, rsph_min, rsph_max
logical :: lupdate_velocities, lno_vr, lno_vz, lvphi_Kep, lfluffy
logical :: lupdate_velocities, lno_vr, lno_vz, lvphi_Kep, lfluffy, lnot_random_Voronoi
integer :: isink_centre

! Disk parameters
Expand Down
7 changes: 5 additions & 2 deletions test_suite/compute_test_suite.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#!/bin/bash

# results to be uploaded to ipag-nfs.u-ga.fr:webpage/mcfost/
#export mcfost=$MCFOST_INSTALL/../src/mcfost
export OMP_NUM_THREADS=1
export mcfost=$(pwd)/../src/mcfost
export MCFOST_UTILS=$(pwd)/../utils

for dir in test_data/*; do
param=`basename "$dir".para`
Expand All @@ -11,9 +14,9 @@ for dir in test_data/*; do
pwd
echo "---------------------------------------------"

rm -rf data_*
rm -rf data_* *.tmp
if [ "$param" == "discF_00500.para" ]; then
opt="-phantom discF_00500"
opt="-phantom discF_00500 -not_random_Voronoi"
else
opt=""
fi
Expand Down
3 changes: 3 additions & 0 deletions test_suite/get_test_data.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
wget -nv https://ipag.osug.fr/~pintec/mcfost/test_data_b17a7fd4bce16a7c2befe713f6dd91773c057740.tar.gz
rm -rf test_data
tar xzf test_data_b17a7fd4bce16a7c2befe713f6dd91773c057740.tar.gz
2 changes: 1 addition & 1 deletion test_suite/test_data/debris/debris.para
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
1 1=Mie, 2=hg (2 implies the loss of polarizarion)

#Symetries
T image symmetry
F image symmetry
T central symmetry
T axial symmetry (important only if N_phi > 1)

Expand Down
21 changes: 5 additions & 16 deletions test_suite/test_data/discF_00500/discF_00500.para
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
2.20 mcfost version
3.00 mcfost version

#Number of photon packages
1e7 nbr_photons_eq_th : T computation
Expand All @@ -17,7 +17,6 @@

#Maps
301 301 900. grid (nx,ny), size [AU]
10 10 MC : N_bin_incl, N_bin_az
0 90. 2 F RT: imin, imax, n_incl, centered ?
0 180. 2 RT: az_min, az_max, n_az angles
140.0 distance (pc)
Expand Down Expand Up @@ -50,11 +49,6 @@
1.125 flaring exponent, unused for envelope
-0.5 0.0 surface density exponent (or -gamma for tappered-edge disk or volume density for envelope), usually < 0, -gamma_exp (or alpha_in & alpha_out for debris disk)

#Cavity : everything is empty above the surface
F cavity ?
15. 50. height, reference radius (AU)
1.5 flaring exponent

#Grain properties
1 Number of species
Mie 1 2 0.0 1.0 0.9 Grain type (Mie or DHS), N_components, mixing rule (1 = EMT or 2 = coating), porosity, mass fraction, Vmax (for DHS)
Expand All @@ -68,13 +62,13 @@
2 nmol

[email protected] 6 molecular data filename, level_max
15.0 100 vmax (km.s^-1), n_speed
15.0 25 vmax (km.s^-1), n_speed
T 1.e-4 abundance.fits.gz cst molecule abundance ?, abundance, abundance file
T 2 ray tracing ?, number of lines in ray-tracing
1 3 transition numbers
T 1 ray tracing ?, number of lines in ray-tracing
3 transition numbers

[email protected] 6
15.0 150 vmax (km.s^-1), n_speed
15.0 25 vmax (km.s^-1), n_speed
T 1e-9 abundance.fits.gz cst molecule abundance ?, abundance, abundance file
T 1 ray tracing ?, number of lines in ray-tracing
4 transition numbers
Expand All @@ -87,8 +81,3 @@
3360.0 2.31 0.3 1.875252612114377E+01 -1.635726683116375E+01 -1.433567792771137E+00 T Temp, radius (solar radius),M (solar mass),x,y,z (AU), is a blackbody?
lte4000-3.5.NextGen.fits.gz
0.0 2.2 fUV, slope_fUV

Executed command line : ./mcfost disc_00130.para -phantom /Users/cpinte/disc_00130 -max_mem 0
Fri Jun 17 15:27:32 AEST 2016
Darwin MacBook-Pro-de-Christophe.local 15.5.0 Darwin Kernel Version 15.5.0: Tue Apr 19 18:36:36 PDT 2016; root:xnu-3248.50.21~8/RELEASE_X86_64 x86_64
sha = 6b533cb7ad9d31eeec10691e4f065e7c1c285b47
2 changes: 1 addition & 1 deletion test_suite/test_data/ref3.0_multi/ref3.0_multi.para
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
100 70 1 20 n_rad (log distribution), nz (or n_theta), n_az, n_rad_in

#Maps
101 101 3000. grid (nx,ny), size [AU]
101 101 700. grid (nx,ny), size [AU]
0. 90. 5 F RT: imin, imax, n_incl, centered ?
0 0. 1 RT: az_min, az_max, n_az angles
140.0 distance (pc)
Expand Down
93 changes: 54 additions & 39 deletions test_suite/test_mcfost.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,42 @@
import glob
import os

# Reference tests are computed with db94244c41cad9c1517363b1607f8596af1c55c0
_mcfost_bin = "../src/mcfost"

# Get list of models using directory names
model_list = glob.glob1("test_data/","*")

# If running on CI, only test ref3.0
if os.environ.get('CI', None) == 'true':
model_list = ["ref3.0"]
model_list = ["ref3.0"]#["ref3.0","ref3.0_multi","debris"]

wl_list = ["1.0","10","100","1000"]
wl_list_pola = ["1.0","1000"]
wl_list_contrib = ["1.0","100","1000"]


# flag to skip the calculations and set-up the thresholds in a easy way
compute_models = True

# change this to test results downloaded from other machines
test_dir = "."

if test_dir != ".":
compute_models = False

def mcfost(filename,opt=""):
cmd = _mcfost_bin+" "+filename+" "+opt
result = subprocess.call(cmd.split())

def clean_results(model_name):
#cmd = ["rm","-rf"]+glob.glob("data_*")
cmd = ["rm","-rf",model_name]
cmd = ["rm","-rf",model_name," *.tmp"]
result = subprocess.call(cmd)

def all_almost_equal(x,y,threshold=0.01):
# test if all the values of two arrays are almost equal
return (abs((x-y)) < threshold * x).all()

def MC_similar(x,y,threshold=0.01,mask_threshold=1e-25):
def MC_similar(x,y,threshold=0.01,mask_threshold=1e-24):
# test if two arrays have the same at the 75% percentile
# ignoring values that are very small as they are very noisy

Expand All @@ -44,7 +51,7 @@ def MC_similar(x,y,threshold=0.01,mask_threshold=1e-25):
y_ma = np.ma.masked_where(mask, y)

#return (abs((x_ma-y_ma)/x_ma).mean() < threshold)
return ( np.percentile(abs((x_ma-y_ma)/x_ma), 75) < threshold )
return ( np.percentile(abs((x_ma-y_ma)/x_ma).compressed(), 75) < threshold )

def test_mcfost_bin():
# We first test if the mcfost binary actually exists and runs
Expand All @@ -56,19 +63,20 @@ def test_mcfost_bin():

@pytest.mark.parametrize("model_name", model_list)
def test_Temperature(model_name):
clean_results(model_name) # removing all previous calculations
if compute_models:
clean_results(model_name) # removing all previous calculations

# Run the mcfost model
filename = "test_data/"+model_name+"/"+model_name+".para"
if (model_name == "discF_00500"):
opt=" -phantom test_data/"+model_name+"/"+model_name
else:
opt=""
mcfost(filename,opt="-mol -root_dir "+model_name+opt)
# Run the mcfost model
filename = "test_data/"+model_name+"/"+model_name+".para"
if (model_name == "discF_00500"):
opt=" -phantom test_data/"+model_name+"/"+model_name+" -not_random_Voronoi"
else:
opt=""
mcfost(filename,opt="-mol -root_dir "+model_name+opt)

# Read the results
T_name = model_name+"/data_th/Temperature.fits.gz"
T = fits.getdata(T_name)
T = fits.getdata(test_dir+"/"+T_name)
T_ref = fits.getdata("test_data/"+T_name)

print("Maximum T difference", (abs(T-T_ref)/(T_ref+1e-30)).max())
Expand All @@ -84,7 +92,7 @@ def test_SED(model_name):
SED_name = model_name+"/data_th/sed_rt.fits.gz"
if (not os.path.isfile(SED_name)):
pytest.skip("No SED")
SED = fits.getdata(SED_name)
SED = fits.getdata(test_dir+"/"+SED_name)
SED_ref = fits.getdata("test_data/"+SED_name)

print("Maximum SED difference", (abs(SED-SED_ref)/(SED_ref+1e-30)).max())
Expand All @@ -99,29 +107,31 @@ def test_mol_map(model_name):

# Read the results
image_name = model_name+"/data_CO/lines.fits.gz"
image = fits.getdata(image_name)
image = fits.getdata(test_dir+"/"+image_name)
image_ref = fits.getdata("test_data/"+image_name)

print("Maximum mol map difference", (abs(image-image_ref)/(image_ref+1e-30)).max())
print("Mean mol map difference ", (abs(image-image_ref)/(image_ref+1e-30)).mean())

assert MC_similar(image_ref,image,threshold=0.05)
assert MC_similar(image_ref,image,threshold=0.1)


@pytest.mark.parametrize("model_name", model_list)
@pytest.mark.parametrize("wl", wl_list)
def test_image(model_name, wl):
# Run the mcfost model
filename = "test_data/"+model_name+"/"+model_name+".para"
if (model_name == "discF_00500"):
opt=" -phantom test_data/"+model_name+"/"+model_name
else:
opt=""
mcfost(filename,opt="-img "+wl+" -root_dir "+model_name+opt)

if compute_models:
# Run the mcfost model
filename = "test_data/"+model_name+"/"+model_name+".para"
if (model_name == "discF_00500"):
opt=" -phantom test_data/"+model_name+"/"+model_name
else:
opt=""
mcfost(filename,opt="-img "+wl+" -root_dir "+model_name+opt)

# Read the results
image_name = model_name+"/data_"+wl+"/RT.fits.gz"
image = fits.getdata(image_name)
image = fits.getdata(test_dir+"/"+image_name)
image_ref = fits.getdata("test_data/"+image_name)

# We just keep intensity
Expand All @@ -141,7 +151,7 @@ def test_pola(model_name, wl):

# Read the results
image_name = model_name+"/data_"+wl+"/RT.fits.gz"
image = fits.getdata(image_name)
image = fits.getdata(test_dir+"/"+image_name)
if ((image.shape[0] != 4) & (image.shape[0] != 8)):
pytest.skip("No pola")
image_ref = fits.getdata("test_data/"+image_name)
Expand All @@ -150,24 +160,24 @@ def test_pola(model_name, wl):
image = image[[1,2],:,:,:,:]
image_ref = image_ref[[1,2],:,:,:,:]

print("Maximum image difference", (abs(image-image_ref)/(image_ref+1e-30)).max())
print("Mean image difference ", (abs(image-image_ref)/(image_ref+1e-30)).mean())
print("Maximum pola difference", (abs(image-image_ref)/(image_ref+1e-36)).max())
print("Mean pola difference ", (abs(image-image_ref)/(image_ref+1e-36)).mean())

if model_name == "debris":
mask_threshold = 1e-32
else:
mask_threshold = 1e-21

assert MC_similar(image_ref,image,threshold=0.05)
assert MC_similar(image_ref,image,threshold=0.1,mask_threshold=mask_threshold)

@pytest.mark.parametrize("model_name", model_list)
@pytest.mark.parametrize("wl", wl_list_contrib)
def test_contrib(model_name, wl):
# Re-use previous calculation

# Skip test on CI because it currently fails
# TODO: fix this test failure
if os.environ.get('CI', None) == 'true':
pytest.skip("CI")

# Read the results
image_name = model_name+"/data_"+wl+"/RT.fits.gz"
image = fits.getdata(image_name)
image = fits.getdata(test_dir+"/"+image_name)
if ((image.shape[0] != 5) & (image.shape[0] != 8)):
pytest.skip("No contrib")
image_ref = fits.getdata("test_data/"+image_name)
Expand All @@ -176,7 +186,12 @@ def test_contrib(model_name, wl):
image = image[[4,5,6,7],:,:,:,:]
image_ref = image_ref[[4,5,6,7],:,:,:,:]

print("Maximum image difference", (abs(image-image_ref)/(image_ref+1e-30)).max())
print("Mean image difference ", (abs(image-image_ref)/(image_ref+1e-30)).mean())
print("Maximum contrib difference", (abs(image-image_ref)/(image_ref+1e-30)).max())
print("Mean contrib difference ", (abs(image-image_ref)/(image_ref+1e-30)).mean())

if model_name == "ref3.0_multi":
mask_threshold=1e-20
else:
mask_threshold=1e-23

assert MC_similar(image_ref,image,threshold=0.05)
assert MC_similar(image_ref,image,threshold=0.1,mask_threshold=mask_threshold)
Loading