Blame view

SRC/rational_function_fit.F90 8.21 KB
886c558b   Steve Greedy   SACAMOS Public Re...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
!
! This file is part of SACAMOS, State of the Art CAble MOdels in Spice. 
! It was developed by the University of Nottingham and the Netherlands Aerospace 
! Centre (NLR) for ESA under contract number 4000112765/14/NL/HK.
! 
! Copyright (C) 2016-2017 University of Nottingham
! 
! SACAMOS 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.
! 
! SACAMOS 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.
! 
! A copy of the GNU General Public License version 3 can be found in the 
! file GNU_GPL_v3 in the root or at <http://www.gnu.org/licenses/>.
! 
! SACAMOS uses the EISPACK library (in /SRC/EISPACK). EISPACK is subject to 
! the GNU Lesser General Public License. A copy of the GNU Lesser General Public 
! License version can be found in the file GNU_LGPL in the root of EISPACK 
! (/SRC/EISPACK ) or at <http://www.gnu.org/licenses/>.
! 
! The University of Nottingham can be contacted at: ggiemr@nottingham.ac.uk
!
! File Contents:
! PROGRAM rational_function_fit
!
! NAME
!     rational_function_fit
!
! AUTHORS
!     Chris Smartt
!
! DESCRIPTION
!     Read in complex frequency domain data from a file and calculate a 'best fit' rational function
!     to represent the data. The numerator and denominator orders of the rational function should be specified explicitly.
!    
!     The rational function is returned in a file.
!
!     This process can be used to generate models for frequency dependent dielectric relative permittivity functions
!     or for frequency dependent transfer impedance functions which can subsequently be used to develop cable bundle
!     models for Spice.
!
!
! COMMENTS
!     The rational function fitting process is done with no constraints applied at the moment.
!
! HISTORY
!
!     started 22/08/2016 CJS 
!
!
PROGRAM rational_function_fit

USE type_specifications
USE general_module
USE constants
USE frequency_spec
USE filter_module
USE Sfilter_fit_module

IMPLICIT NONE

! local variables

character(len=filename_length)    :: ipfilename     ! name of the input datafile
character(len=filename_length)    :: opfilename     ! filename for the output rational function
    
logical        :: file_exists

integer                  :: n_frequency_samples ! number of frequencies for which data is available
real(dp),allocatable     :: f(:)                ! Frequency data
complex(dp),allocatable  :: function(:)         ! Frequency dependent complex function data

integer        :: aorder                        ! numerator order of rational function model
integer        :: border                        ! denominator order of rational function model
integer        :: relative_border               ! denominator order relative to numerator order

type(Sfilter)  :: function_model                ! Frequency dependent rational function model of the input data

logical        :: stable                        ! flag to indicate whether this model has stable poles (LHS of s-plane) or not

character(len=line_length) :: line              ! line read from the input file

real(dp)       :: f_in                          ! frequency read from file
real(dp)       :: re                            ! real part of function
real(dp)       :: im                            ! imaginary part of function

complex(dp)    :: function_fit                  ! function value from the rational function model

integer        :: loop                          ! data reading loop variable
integer        :: frequency_sample              ! frequency loop variable
 
integer        :: ierr  ! integer to return error codes from file reads

! START

! Open the input file containing the complex frequency domain data

  verbose=.TRUE.

  program_name="rational_function_fit"
  run_status='Started'
  CALL write_program_status()
  
  CALL read_version()
    
  CALL write_license()

  write(*,*)'Enter the name of the complex frequency domain data'

  read(*,'(A)')ipfilename
 
  inquire(file=trim(ipfilename),exist=file_exists)
  if (.NOT.file_exists) then
    run_status='ERROR in rational_function_fit, Cannot find the file:'//trim(ipfilename)
    CALL write_program_status()
    STOP 1
  end if 
  
! open and read the file
  
  OPEN(unit=local_file_unit,file=ipfilename)

  write(*,*)'Opened file:',trim(ipfilename)
  
  do loop=1,2     ! read the data file twice, the first time to work out the amount of data, the second to read the data into arrays

    frequency_sample=0       ! reset the counter for the frequency samples

100 CONTINUE  
      read(local_file_unit,'(A)',END=200)line   ! read the next line of the file into the string, line; exit at the end of the file
    
! try to read data in the expected format from the line just read, if the line does not have data in the correct format then skip it
      read(line,*,END=110,ERR=110)f_in,re,im
    
      frequency_sample=frequency_sample+1
    
      if (loop.EQ.2) then                            ! put the values in the frequency and function value arrays
        f(frequency_sample)=f_in
        function(frequency_sample)=cmplx(re,im)
      end if
  
110   CONTINUE    ! jump here if the line read doesn't have data in the correct format
      
      GOTO 100

200 CONTINUE    ! jump here when we reach the end of the file

    if (loop.EQ.1) then                             ! allocate space for all of the data points
    
      n_frequency_samples=frequency_sample
      ALLOCATE( f(1:n_frequency_samples) )
      ALLOCATE( function(1:n_frequency_samples) )
      rewind(local_file_unit)                       ! go back to the beginning of the file to read it again
      
    end if
  
  end do ! next read loop

! close the file with the input data
  CLOSE(unit=local_file_unit)
  
  write(*,*)'Number of frequency samples read:',n_frequency_samples
  write(*,*)
  
! Create a rational function model of the function data 
  
  write(*,*)'Enter the numerator order for the model, this should be no more than the denominator order+1'
  read(*,*)aorder
  
  write(*,*)'Enter the denominator order for the model'
  read(*,*)border
  
  if (aorder.GT.border+1) then
    run_status='ERROR: The  numerator order should be no more than the denominator order+1'
    CALL write_program_status()
    STOP 1
  end if
  
  relative_border=border-aorder
  
! call calculate_Sfilter for the specified model order

  write(*,*)'Calculating the rational function model...'
  CALL Calculate_Sfilter(function,f,n_frequency_samples,function_model,aorder,relative_border,0) ! call with fit_type=0 i.e. no constraints

! check the stability of the model i.e. the poles are on the LHS of the s-plane  
  CALL test_filter_pole_stability(function_model,stable)
  
  if (stable) then
    write(*,*)'This model is stable'
  else
    write(*,*)'********** WARNING ************'
    write(*,*)'*** This model is unstable ****'  
    write(*,*)'*******************************'
  end if
  
! Write vector fit models to file
  open(unit=local_file_unit,file='function_fit.fout')
  do frequency_sample=1,n_frequency_samples
  
    function_fit=evaluate_Sfilter_frequency_response(function_model,f(frequency_sample))
    
    write(local_file_unit,8000)f(frequency_sample),real(function(frequency_sample)),aimag(function(frequency_sample)),   &
                                                   real(function_fit),aimag(function_fit)
8000 format(5ES16.6)

  end do
  
  close(unit=local_file_unit)

! Open a file for the best fit model

!  write(*,*)'Enter the name of the best fit model'
!  read(*,'(A)')opfilename

  opfilename=trim(ipfilename)//'.function_fit'
  
  open(unit=local_file_unit,file=opfilename)

! Write the rational function model to the file

  write(local_file_unit,*)'# Rational function model fit to data from file:',trim(ipfilename)
  CALL Write_Sfilter(function_model,local_file_unit)

  close(unit=local_file_unit)

! deallocate memory and finish up
  CALL deallocate_Sfilter(function_model)
  
  DEALLOCATE(f)
  DEALLOCATE(function)

  run_status='Finished_Correctly'
  CALL write_program_status()
  
END PROGRAM rational_function_fit