! This module contains the routine that upload the spectrum and
! the absorption lines expected to be in the wavelength interval
! given by the user and allocate some fundamental arrays.
!
! It is part of the program SP_Ace, which derives stellar parameters,
! such as gravity, temperature, and element abundances from optical
! stellar spectra, assuming Local Thermodynamic Equilibrium (LTE)
! and 1D stellar atmosphere models.
!
! Copyright (C) 2016 Corrado Boeche
!
! This program is free software: you can redistribute it and/or modify
! it under the terms of the GNU General Public License as published by
! the Free Software Foundation, either version 3 of the License, or
! (at your option) any later version.
!
! This program is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with this program. If not, see .
MODULE read_sp_ll
USE num_type
USE space_pars, ONLY: llist,llist_rej,&
&w_inf,w_sup,N_w_int,flag_rej,flag_alpha,norm_rad,sn_ratio
USE data_lib, ONLY: w_str_ll,dd_str_ll,w_rej_op,r_rej_op,&
&w_rej_nlte,r_rej_nlte,w_rej_unknown,r_rej_unknown,w_rej_bad,r_rej_bad
USE share
USE error
IMPLICIT NONE
LOGICAL, DIMENSION(:), ALLOCATABLE :: wave_mask,llist_mask,llist_mask_w,llist_mask_ll
INTEGER(I2B) :: add_pix_sp,add_pix_sp_l,add_pix_sp_u
CONTAINS
SUBROUTINE read_files(name1,name2,name4)
CHARACTER(len=120) :: name1,name2,name4
INTEGER(I1B) :: AllocateStatus
INTEGER(I4B) :: ierror
INTEGER(I2B) :: i,dims,sp_dim_trim,ll_dim_trim,w_center_line
INTEGER(I2B), PARAMETER :: MAX_SIZE_SP=32000
INTEGER(I2B) :: dim_trim1,dim_trim2,dim_trim3,dim_trim
REAL(DP), DIMENSION(MAX_SIZE_SP) :: wave,flux
REAL(DP), DIMENSION(MAX_SIZE_SP) :: w_ll,e_ll
REAL(DP), DIMENSION(MAX_SIZE_SP) :: col1,col2
REAL(DP) :: wave_lbound,wave_ubound
LOGICAL, DIMENSION(:), ALLOCATABLE :: mask
!initialize variables
wave=0;flux=1;w_ll=0;e_ll=0
!#############################
!######### read the spectrum
OPEN(unit=10,file=name1,status='OLD',action='READ',iostat=ierror)
IF(ierror/=0) CALL error_msg(9_I1B,'I cannot open the spectrum! (maybe wrong file?)')
sp_dim_trim=1_I2B
DO
IF(sp_dim_trim>MAX_SIZE_SP-1) THEN
write(*,*) 'Warning: the spectrum exceeds ',MAX_SIZE_SP,' pixels!'
EXIT
END IF
READ(unit=10,fmt=*,iostat=ierror) wave(sp_dim_trim),flux(sp_dim_trim)
IF(ierror/=0) EXIT
IF((wave(sp_dim_trim)>=6860.).AND.(wave(sp_dim_trim)<=8400.)) THEN
CYCLE
END IF
DO i=1,N_w_int
IF((wave(sp_dim_trim)>=w_inf(i)).AND.(wave(sp_dim_trim)<=w_sup(i))) THEN
sp_dim_trim=sp_dim_trim+1_I2B
ELSEIF (wave(sp_dim_trim)>w_sup(i).AND.wave(sp_dim_trim)<(MIN(w_sup(N_w_int),w_sup(i)+4.0_dp))) THEN
flux(sp_dim_trim)=1.0_dp
sp_dim_trim=sp_dim_trim+1_I2B
ELSEIF (wave(sp_dim_trim)>(MAX(w_inf(1),w_inf(i)-4.0_dp)).AND.wave(sp_dim_trim)wave_lbound.AND.wave(1:sp_dim_trim)1, the value rad_pix would be wrong because w_sp(2:dimsp)-w_sp(1:dimsp-1) would
!be too large (because it measures the excluded interval)
IF(N_w_int>1) THEN
DO i=2,N_w_int
w_center_line=INT(MINLOC(ABS(w_sp-(w_inf(i)-4.0)),1),I2B)
rad_pix(w_center_line)=rad_pix(w_center_line+1)
END DO
END IF
!######### select the upper and lower limits of the line list
!######### according to the limits given by the user and the spectrum
ALLOCATE(llist_mask(ll_dim_trim), STAT = AllocateStatus)
IF (AllocateStatus/=0) CALL stop_msg('Not enough memory to allocate llist_mask')
llist_mask=.FALSE.
ALLOCATE(llist_mask_w(ll_dim_trim), STAT = AllocateStatus)
IF (AllocateStatus/=0) CALL stop_msg('Not enough memory to allocate llist_mask')
llist_mask=.FALSE.
ALLOCATE(llist_mask_ll(ll_dim_trim), STAT = AllocateStatus)
IF (AllocateStatus/=0) CALL stop_msg('Not enough memory to allocate llist_mask')
llist_mask=.FALSE.
DO i=1,N_w_int
WHERE(w_ll(1:ll_dim_trim)>w_inf(i).AND.w_ll(1:ll_dim_trim)wave(1).AND.w_ll(1:ll_dim_trim)0.3.AND.ABS(ele_ll-7)>0.3.AND.ABS(ele_ll-8)>0.3.AND.&
&ABS(ele_ll-94)>0.3.AND.ABS(ele_ll-95)>0.3) ele_ll=26.0
END IF
!###########################################
!######### the linelist of strong lines are read from data_lib module
!######### here allocate the array damp_coeff for all the lines
ALLOCATE(damp_coeff(dim_ll), STAT = AllocateStatus)
IF (AllocateStatus/=0) CALL stop_msg('Not enough memory to allocate damp_coeff')
!initialize
damp_coeff=1.
DO i=1,size(w_str_ll)
WHERE(wave_ll==w_str_ll(i))
damp_coeff=dd_str_ll(i)
END WHERE
END DO
!######### prepare the rejected list taken from the llist in data_lib
!put the lines rejected because bad opacity correction
dim_trim=INT(SIZE(w_rej_op,1),I2B)
col1(1:dim_trim)=w_rej_op
col2(1:dim_trim)=r_rej_op
dims=dim_trim
!put the lines rejected because NLTE effect neglected
dim_trim1=INT(SIZE(w_rej_nlte,1),I2B)
col1(dims+1:dims+dim_trim1)=w_rej_nlte
col2(dims+1:dims+dim_trim1)=r_rej_nlte
dims=dims+dim_trim1
!put the lines rejected because unknown
dim_trim2=INT(SIZE(w_rej_unknown,1),I2B)
col1(dims+1:dims+dim_trim2)=w_rej_unknown
col2(dims+1:dims+dim_trim2)=r_rej_unknown
dims=dims+dim_trim2
!put the lines rejected because they fit bad for unknown reasons
dim_trim3=INT(SIZE(w_rej_bad,1),I2B)
col1(dims+1:dims+dim_trim3)=w_rej_bad
col2(dims+1:dims+dim_trim3)=r_rej_bad
dims=dims+dim_trim3
!######### read the user's list of lines to reject, if any
IF(flag_rej) THEN
OPEN(unit=10,file=name4,status='OLD',action='READ',iostat=ierror)
IF(ierror/=0) CALL stop_msg('I cannot open the reject line list')
dims=dims+1_I2B
DO
READ(unit=10,fmt=*,iostat=ierror) col1(dims),col2(dims)
IF(ierror/=0) THEN
dims=dims-1_I2B
EXIT
END IF
dims=dims+1_I2B
END DO
CLOSE(unit=10)
END IF
!sort the array
CALL sorting(col1(1:dims),col2(1:dims),dims)
!######### select the upper and lower limits of the rejected line list
!######### according to the limits given by the user and the spectrum
ALLOCATE(mask(dims), STAT = AllocateStatus)
IF (AllocateStatus/=0) CALL stop_msg('Not enough memory to allocate mask(dim_rej)')
mask=.FALSE.
IF(N_w_int==1) THEN
wave_lbound=MAXVAL((/w_inf(1),col1(1),wave(1)/))
wave_ubound=MINVAL((/w_sup(1),col1(dims),wave(sp_dim_trim)/))
WHERE((col1(1:dims)+col2(1:dims))>=wave_lbound.AND.(col1(1:dims)-col2(1:dims))<=wave_ubound) mask=.TRUE.
ELSE
DO i=1,N_w_int
IF(i==1) THEN
wave_lbound=MAXVAL((/w_inf(i),col1(1),wave(1)/))
wave_ubound=MINVAL((/w_sup(i),col1(dims),wave(sp_dim_trim)/))
WHERE((col1(1:dims)+col2(1:dims))>=wave_lbound.AND.(col1(1:dims)-col2(1:dims))<=wave_ubound) mask=.TRUE.
ELSEIF(i==N_w_int) THEN
wave_lbound=MAXVAL((/w_inf(i),col1(1)/))
wave_ubound=MINVAL((/w_sup(i),col1(dims),wave(sp_dim_trim)/))
WHERE((col1(1:dims)+col2(1:dims))>=wave_lbound.AND.(col1(1:dims)-col2(1:dims))<=wave_ubound) mask=.TRUE.
ELSE
wave_lbound=w_inf(i)
wave_ubound=w_sup(i)
WHERE((col1(1:dims)+col2(1:dims))>=wave_lbound.AND.(col1(1:dims)-col2(1:dims))<=wave_ubound) mask=.TRUE.
END IF
END DO
END IF
dim_rej=INT(COUNT(mask),I2B)
ALLOCATE(wave_rej(dim_rej), STAT = AllocateStatus)
IF (AllocateStatus/=0) CALL stop_msg('Not enough memory to allocate wave_rej')
ALLOCATE(rad_rej(dim_rej), STAT = AllocateStatus)
IF (AllocateStatus/=0) CALL stop_msg('Not enough memory to allocate rad_rej')
wave_rej=PACK(col1(1:dims),mask)
rad_rej=PACK(col2(1:dims),mask)
DEALLOCATE(mask)
END SUBROUTINE read_files
!##################
SUBROUTINE sorting(x,x1,dim)
IMPLICIT NONE
INTEGER (I2B), INTENT(IN) :: dim
REAL(DP), DIMENSION(dim), INTENT(INOUT) :: x,x1
REAL(DP), DIMENSION(dim) :: x_sort,x1_sort
INTEGER (I2B) :: a,i
LOGICAL, DIMENSION(dim) :: mask
mask=.TRUE.
DO i=1,INT(SIZE(x),I2B)
a=INT(MINLOC(x,1,mask),I2B)
mask(a)=.FALSE.
x_sort(i)=x(a)
x1_sort(i)=x1(a)
END DO
x=x_sort
x1=x1_sort
END SUBROUTINE sorting
!##################
END MODULE read_sp_ll