Files
sicspsi/tecs/conv.f90

666 lines
16 KiB
Fortran

program conv
use strings
integer, parameter :: ncolumn=3
logical init
integer lun/0/,pos/0/,nlist/0/,ctx/0/
integer i,l,lin
character*128 file, input, list(1000), line
logical wild
integer errstat
call sys_get_cmdpar(input, l)
if (input .ne. ' ') then
i=index(input, '.')
if (i .ne. 0) input(i:)=' '
endif
if (input == ' ') then
print '(a,$)',' Device(s) (lowercase, separated by space, return for all): '
read(*,'(a)',end=99) input
endif
if (input == 'all') input=' '
open(3, file='src/cfg/tecs.cfg', status='old',readonly,iostat=i)
if (i .ne. 0) then
print *,'can not open tecs.cfg'
end if
do
read(3, '(a)', iostat=i) line
if (i .ne. 0) EXIT
i=index(line, "'")
if (i==0) CYCLE
file=line(i+1:)
i=index(file, "'")
if (i<2) CYCLE
file(i:i)=' '
if (input .ne. ' ' .and. index(' '//input, ' '//file(1:i)) .eq. 0) CYCLE
file(i:)='.inp'
l=i+3
print *
open(1,name='src/cfg/'//file(1:l),status='old',readonly,iostat=i)
if (i .ne. 0) then
print *,'can not open ',file(1:l)
print "(x,60('-'))"
nlist=nlist+1
list(nlist)='can not open '//file(1:l)
else
lin=0
do
print "(x,60('-'))"
call lsc_errinit(1) ! 1=lun
call lsc_convert_table(lin, file(1:l))
if (lin<0) EXIT
enddo
close(1)
endif
enddo
print "(x,60('-'))"
do i=1,nlist
call str_trim(list(i), list(i), l)
print *,list(i)(1:l)
enddo
99 continue
contains
subroutine pack(line, l, x, y, offset, m)
character line*(*)
integer l, offset, m
real x(m), y(m)
integer j,p
p=0
do j=1,m
call str_append(line, p, '#0,')
call str_fmt_real(line(p+1:), l, 1.0*(offset+j), 1, 0, 6, 3)
p=p+l
call str_append(line, p, ':')
call str_fmt_real(line(p+1:), l, x(j), 1, 0, 6, 3)
p=p+l
call str_append(line, p, ',')
call str_fmt_real(line(p+1:), l, y(j), 1, 0, 6, 3)
p=p+l
call str_append(line, p, ';')
enddo
line(p:p)=' '
l=p-1
end subroutine
subroutine lsc_convert_table(lin, file)
implicit none
integer lin
character(len=*) file
integer, parameter :: ntypes=12, nvolts=12, namps=12
integer n
real x(200), y(200), ex, ey
integer i,j,l,p,li,crc,form
character name*15, sensor*10, header*64, line*128, old*128, intype*16
character crcmp*3, filnam*24
character months*12/'123456789ond'/
character c40*40/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$+-&'/
integer unit, type, excit, irange, coef, iunit, stdcurv
! codes
character types(0:ntypes)*12/'Special','Si Diode','GaAlAs Diode' &
,'Pt250 Ohm','Pt500 Ohm','Pt2500 Ohm','RhFe','C-Glass' &
,'Cernox','RuOx','Ge','??','TC'/
integer, parameter :: nunits=3
character units(nunits)*5/'mV','V','Ohm'/
integer, parameter :: nexcits=12
character excits(0:nexcits)*8/'Off','30nA','100nA','300nA','1uA','3uA' &
,'10uA','30uA','100uA','300uA','1mA','10mV','1mV'/
integer, parameter :: nforms=5
character forms(nforms)*6/'ill','ill','lin','log','loglog'/
! default values
integer defu(ntypes)/ 1, 1, 2, 2,2, 2, 2, 2, 2, 2, 3, 1/ ! unit
integer defe(ntypes)/ 6, 6,10,10,8,10,11,11,11,12, 0, 0/ ! excit
integer defr(ntypes)/11,12, 8, 9,8, 8, 4, 4, 4, 1, 1, 6/ ! range
integer defc(ntypes)/ 1, 1, 2, 2,2, 2, 1, 1, 1, 1, 2, 2/ ! coef
real volts(nvolts)/1E-3,2.5E-3,5E-3,1E-2,2.5E-2,5E-2 &
,1E-1,2.5E-1,5E-1,1E-0,2.5E-0,5E-0/
real amps(namps)/3E-8,1E-7,3E-7,1E-6,3E-6,1E-5,3E-5,1E-4,3E-4,1E-3 &
,3E-8,3E-8/ ! minimal values are for voltage excitation
integer, parameter :: stdmax=10
character (len=40) stdhdr(stdmax)/ &
'DT-470 ,Standard ,2,+475.000E+0,1', &
'DT-500-D ,Standard ,2,+365.000E+0,1', &
'DT-500-E1 ,Standard ,2,+330.000E+0,1', &
'PT-100 ,Standard ,3,+800.000E+0,2', &
'PT-1000 ,Standard ,3,+800.000E+0,2', &
'TYPE K ,Standard ,1,+1645.00E+0,2', &
'TYPE E ,Standard ,1,+1188.50E+0,2', &
'TYPE T ,Standard ,1,+673.000E+0,2', &
'CrAuFe.03%,Standard ,1,+500.000E+0,2', &
'CrAuFe.07%,Standard ,1,+610.000E+0,2'/
integer stdtype(stdmax)/1,1,1,4,5,12,12,12,12,12/
real tlim, range, xmax, ymax, curr, rl
real x1,x2,xi,y1,y2,yi,sum,sum1,sum2,mum,mum1,mum2,d,at,at1,at2
logical eof, first
first=.true.
eof=.false.
n=0
name=' '
sensor=' '
unit=0
tlim=0
type=0
excit=0
form=0
range=-1.0
stdcurv=0
1 read(1,'(q,a)',err=97,end=97) l,line
lin=lin+1
l=max(1,min(l,len(line)))
call str_first_nonblank(line, i)
if (i .eq. 0) goto 1
if (line(i:i) .eq. '!') goto 1
first=.false.
call str_upcase(line(1:l),line(i:l))
i=index(line(1:l),'!')
if (i .ne. 0) line=line(1:i-1)
call str_trim(line(1:l),line(1:l),l)
if (line(1:4) .ne. 'CURV') then
i=index(line,'=')
if (i .eq. 0) then
call lsc_error(lin, 'missing "="')
goto 1
endif
if (i .eq. l) then
call lsc_error(lin, 'missing value')
goto 1
endif
call str_first_nonblank(line(i+1:l), j)
i=i+j
if (line(1:4) .eq. 'NAME') then
call str_lowcase(name,line(i:l))
elseif (line(1:4) .eq. 'SENS') then
sensor=line(i:l)
elseif (line(1:4) .eq. 'UNIT') then
unit=lsc_getno(units, nunits, line(i:l))
if (unit .le. 0) call lsc_error(lin, 'illegal unit')
elseif (line(1:4) .eq. 'TLIM') then
read(line(i:l),*,err=92,end=92) tlim
elseif (line(1:4) .eq. 'TYPE') then
type=lsc_getno(types, ntypes, line(i:l))-1
if (type .lt. 0) call lsc_error(lin, 'illegal type')
elseif (line(1:4) .eq. 'EXCI') then
call str_substitute(line(1:8),line(i:l),' ',char(0))
excit=lsc_getno(excits, nexcits, line(1:8))-1
if (excit .lt. 0) call lsc_error(lin, 'illegal excitation')
elseif (line(1:4) .eq. 'RANG') then
read(line(i:l),*,err=93,end=93) range
if (range .lt. 0) goto 93
elseif (line(1:4) .eq. 'FORM') then
form=lsc_getno(forms, nforms, line(i:l))
if (form .lt. 3) call lsc_error(lin, 'illegal format')
else
call lsc_error(lin, 'unknown parameter name')
endif
goto 1
endif
if (name .eq. ' ') call lsc_error(lin, 'missing name')
i=index(line,'=')
if (i .ne. 0) then
read(line(i+1:l), *, err=2,end=2) stdcurv
2 continue
if (stdcurv<0 .or. stdcurv>stdmax) then
call lsc_error(lin, 'illegal standard curve no.')
goto 101
endif
if (unit/=0 .or. type/=0 .or. &
excit/=0 .or. tlim/=0 .or. sensor/=' ') then
print *,'Warning: all parameters except "name", "range" and "curv" are ignored',char(7)
errstat=max(errstat,1)
endif
line=stdhdr(stdcurv)
i=index(line, ',')
if (i .eq. 0) goto 96 ! illegal stdhdr
j=index(line(i+1:), ',')
if (j .eq. 0) goto 96 ! illegal stdhdr
read(line(i+j+1:), *, err=96, end=96) unit, ymax, coef
type=stdtype(stdcurv)
! if (range < 0) then
! range=stdrange(stdcurv)
! end if
xmax=0
excit=0
tlim=0
goto 100
endif
if (line(5:) /= ' ') then
call lsc_error(lin, 'missing "="')
goto 101
end if
! user curve
if (unit .eq. 0) call lsc_error(lin, 'missing unit')
if (type .eq. 0) then
if (excit .le. 0) call lsc_error(lin, 'missing excitation')
if (range .lt. 0) call lsc_error(lin, 'missing range')
else
if (excit .eq. 0) excit=defe(type)
endif
3 n=n+1
read(1,'(a)',err=98,end=98) line
lin=lin+1
if (line .eq. ' ') goto 9
read(line, *, err=94, end=94) x(n), y(n)
goto 3
92 call lsc_error(lin,'illegal tlim')
goto 1
93 call lsc_error(lin,'illegal range')
goto 1
94 call lsc_error(lin,'illegal datapoint')
goto 101
95 call lsc_error(lin,'illegal table no')
goto 1
96 stop 'internal error: illegal stdhdr'
97 if (.not. first) then
call lsc_error(lin,'unexpected end of file')
endif
lin=-1
RETURN
98 eof=.true.
9 x(n)=0
y(n)=0
if (n .lt. 3) call lsc_error(lin+n-1, 'not enough data points')
if (x(n-1) .lt. x(1)) then ! inverse order
j=n
do i=1,n/2
j=j-1
ex=x(i)
ey=y(i)
x(i)=x(j)
y(i)=y(j)
x(j)=ex
y(j)=ey
enddo
endif
do i=2,n-1
if (x(i) .le. x(i-1)) then
call lsc_error(lin+n, 'table not ordered')
goto 101
endif
enddo
xmax=x(n-1)
if (y(n-1) .lt. y(1)) then
coef=1
do i=2,n-1
if (y(i) .ge. y(i-1)) then
call lsc_error(lin+n, 'table not ordered')
goto 101
endif
enddo
ymax=y(1)
else
coef=2
do i=2,n-1
if (y(i) .le. y(i-1)) then
call lsc_error(lin+n, 'table not ordered')
goto 101
endif
enddo
ymax=y(n-1)
endif
101 continue
do i=1,n-1
if (x(i) .le. 0.0) call lsc_error(lin+n, 'illegal sensor value')
if (y(i) .le. 0.0) call lsc_error(lin+n, 'illegal temperature')
enddo
if (errstat .gt. 1) goto 999
sum=0
sum1=0
sum2=0
mum=0
mum1=0
mum2=0
do i=2,n-2
xi=x(i)
x1=x(i-1)
x2=x(i+1)
yi=log(y(i))
y1=y(i-1)
y2=y(i+1)
d=abs(yi-log(y1+(xi-x1)/(x2-x1)*(y2-y1)))
sum=sum+d*d
if (d .gt. mum) then
mum=d
at=y(i)
endif
xi=log(xi)
x1=log(x1)
x2=log(x2)
d=abs(yi-log(y1+(xi-x1)/(x2-x1)*(y2-y1)))
sum1=sum1+d*d
if (d .gt. mum1) then
mum1=d
at1=y(i)
endif
y1=log(y1)
y2=log(y2)
d=abs(yi-(y1+(xi-x1)/(x2-x1)*(y2-y1)))
sum2=sum2+d*d
if (d .gt. mum2) then
mum2=d
at2=y(i)
endif
enddo
if (n .gt. 3) then
sum=sqrt(sum/(n-2))*25
sum1=sqrt(sum1/(n-2))*25
sum2=sqrt(sum2/(n-2))*25
print '(x,a)','Interpolation accuracy mean worst at'
print '(13x,a,3(f8.2,a))','linear ',sum, '%',mum *25,'%',at,' K'
print '(13x,a,3(f8.2,a))','log/lin ',sum1,'%',mum1*25,'%',at1,' K'
print '(13x,a,3(f8.2,a))','log/log ',sum2,'%',mum2*25,'%',at2,' K'
if (unit .eq. 3) then
sum1=(sum1/sum)**2+(mum1/mum)**2
sum2=(sum2/sum)**2+(mum2/mum)**2
if (form .eq. 0 .and. (sum1 .lt. 1.0 .or. sum2 .lt. 1.0) &
.or. form .gt. 3) then
if (form .eq. 0 .and. sum2 .lt. sum1 .or. form .eq. 5) then
unit=5
do i=1,n-1
y(i)=log10(y(i))
enddo
else
unit=4
endif
do i=1,n-1
x(i)=log10(x(i))
enddo
endif
else
if (form .gt. 3) print *,'FORM ignored (not unit Ohm)'
endif
endif
100 continue
if (unit .eq. 1) then ! check for mV / V consistency
if (xmax .gt. 990) then
unit=2
do i=1,n-1
x(n)=x(n)/1000.0
enddo
endif
xmax=xmax/1000.0
range=range/1000.0
elseif (unit .eq. 2) then
if (xmax .lt. 0.5) then
unit=1
do i=1,n-1
x(n)=x(n)*1000.0
enddo
endif
endif
if (range .eq. 0) range=xmax
if (tlim .eq. 0 .or. tlim .gt. ymax) tlim=ymax
irange=0
if (range .gt. 0) then
if (unit .ge. 3) then ! Ohm
curr=amps(excit)
rl=range*curr ! convert Ohm to V
if (rl .gt. 5.0) then
! print *,'Warning: maximum range exceeded: ', range,'>',5/curr,' Ohm',char(7)
! errstat=max(errstat,1)
irange=12
endif
else
rl=range ! V
endif
if (irange .eq. 0) then
if (type==12) then
j=6
else
j=nvolts
end if
do i=1,j
if (rl .le. volts(i)) then
irange=i
goto 150
endif
enddo
! print *,'Warning: maximum range exceeded: ', range,' > ',volts(j),' V',char(7)
! errstat=max(errstat,1)
irange=j
150 continue
if (excit .eq. 11) then ! 10 mV excit -> min. 10 mV range
if (irange .lt. 4) irange=4
endif
endif
else
irange=defr(type)
range=xmax
endif
if (stdcurv==0) then
if (unit .ge. 3) then
if (range*amps(excit) .gt. volts(irange)) then
print *,'Warning: max. range exceeded: ',range,' > ',volts(irange)/amps(excit),' Ohm',char(7)
errstat=max(errstat,1)
endif
else if (range .gt. volts(irange)) then
print *,'Warning: max. range exceeded: ',range,' > ',volts(irange), ' V',char(7)
errstat=max(errstat,1)
endif
endif
if (type .gt. 0) then
if (excit .le. 0) excit=defe(type)
if (irange .eq. 0) irange=defr(type)
endif
print *,'Sensor type: ',types(type)
print *,'Excitation: ',excits(excit)
if (unit .eq. 1) then
print *,'Sensor Range: ',volts(irange)*1000,' mV'
elseif (unit .eq. 2) then
print *,'Sensor Range: ',volts(irange),' V'
else
print *,'Sensor Range: ',volts(irange)/amps(excit),' Ohm'
if (unit .eq. 5) then
print *,'table double logarithmic'
elseif (unit .eq. 4) then
print *,'table logarithmic'
else
print *,'table linear'
endif
endif
if (coef .eq. 1) then
print *,'negative characteristic'
else
print *,'positive characteristic'
endif
print *
if (type .eq. 0) then
if (unit .ge. 3) then
iunit=2
else
iunit=1
endif
else
if (unit .le. 2) then ! mV / V
iunit=1
else ! Ohm
iunit=2
endif
if (iunit .ne. defu(type) .or. &
coef .ne. defc(type) .or. &
excit .ne. defe(type) .or. &
irange.ne. defr(type)) then
if (type .ne. 12) type=0
endif
endif
if (type .eq. 12) then
l=5
write (line(1:l), '(a,i1)') ',,,,',max(0,irange-5)
elseif (type .eq. 0) then
l=14
write (line(1:l), '(i2,4(a,i2.0))') type,',',iunit,',',coef,',',excit,',',irange
else
l=2
write(line(1:l), '(i2)') type
endif
call str_substitute(intype, line(1:l), ' ', char(0))
call str_trim(intype, intype, li)
if (tlim .gt. 1500) tlim=1500
if (tlim .lt. 0) tlim=0
if (stdcurv==0) then
! calculate crc of table
crc=0
do i=1,n,ncolumn
call pack(line, l, x(i), y(i), i-1, 1)
call str_crc(crc, line(1:l))
enddo
call str_crc_comp(crc, crcmp)
write (header, "(a,x,a,',',a,',',i1,',',f8.3,',',i1)") name(1:11), crcmp,sensor,unit,tlim,coef
else
header=stdhdr(stdcurv)
endif
! compare with old file
call str_trim(filnam, name, l)
filnam(l+1:)='.crv'
filnam='tecs/'//filnam
open(unit=2, file=filnam, status='old', action='read',err=198)
read(2, '(a)',end=199) old
if (old/=header) goto 199
read(2, '(a)', end=199) old
if (old/=intype) goto 199
do i=1,n,ncolumn
read(2, '(a)') old
call pack(line, l, x(i), y(i), i-1, min(ncolumn,n-i+1))
if (line/=old) goto 199
enddo
close(2)
print *,'curve file has not changed: ',filnam
goto 999
198 print *,'create new curve file: ',filnam
nlist=nlist+1
list(nlist)='created '//filnam
goto 200
199 close(2)
print *,'modify curve file: ',filnam
nlist=nlist+1
list(nlist)='modified '//filnam
200 continue
open(unit=2, file=filnam, status='unknown', action='write', carriagecontrol='list')
call str_trim(header, header, l)
if (stdcurv/=0) then
write(2, '(a)') header(1:l)
write(2, '(a)') intype(1:li)
write(2, '(a,i2)') '$',stdcurv
else
write(2, '(a)') header(1:l)
write(2, '(a)') intype(1:li)
do i=1,n,ncolumn
call pack(line, l, x(i), y(i), i-1, min(ncolumn,n-i+1))
write(2,'(a)') line(1:l)
enddo
endif
close(2)
999 continue
if (errstat .gt. 0) then
if (name==' ') name='<unknown>'
nlist=nlist+1
if (errstat .gt. 1) then
list(nlist)='error in '//file//', curve '//name
print *,'no curve file written'
lin=-1
else
list(nlist)='warning in '//file//', curve '//name
endif
endif
if (eof) lin=-1
return
end subroutine
integer function lsc_getno(list, n, name)
integer n
character list(n)*(*), name*(*)
character str*32
integer i,l
call str_trim(name, name, l)
l=min(l,len(str))
do i=1,n
call str_upcase(str(1:l), list(i))
if (name(1:l) .eq. str(1:l)) then
lsc_getno=i
RETURN
endif
enddo
lsc_getno=0
end function
subroutine lsc_errinit(lunit)
integer lunit
lun=lunit
pos=0
errstat=0
end subroutine
subroutine lsc_error(lin, text)
integer lin
character text*(*)
integer i,l
character line*132
if (pos .eq. 0) then
print *
endif
if (lin .gt. pos) then
rewind lun
do i=1,lin-1
read(lun, '(q,a)', end=8) l,line
if (i .gt. max(pos,lin-3)) then
print '(5x,a)',line(1:max(1,min(l,len(line))))
endif
enddo
read(lun, '(q,a)', end=8) l,line
print '(x,2a)','>>> ',line(1:max(1,min(l,len(line))))
8 pos=lin
errstat=2
endif
9 print '(x,a)', text
end subroutine
end program