-
Notifications
You must be signed in to change notification settings - Fork 0
/
mille.f90
185 lines (172 loc) · 6.78 KB
/
mille.f90
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
! Code converted using TO_F90 by Alan Miller
! Date: 2012-03-03 Time: 17:00:12
!> \file
!! Write Millepede-II F-binary record.
!!
!! \author Volker Blobel, University Hamburg, 2005-2009 (initial Fortran77 version)
!! \author Claus Kleinwort, DESY (maintenance and developement)
!!
!! \copyright
!! Copyright (c) 2009 - 2015 Deutsches Elektronen-Synchroton,
!! Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY \n\n
!! This library is free software; you can redistribute it and/or modify
!! it under the terms of the GNU Library General Public License as
!! published by the Free Software Foundation; either version 2 of the
!! License, or (at your option) any later version. \n\n
!! This library 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 Library General Public License for more details. \n\n
!! You should have received a copy of the GNU Library General Public
!! License along with this program (see the file COPYING.LIB for more
!! details); if not, write to the Free Software Foundation, Inc.,
!! 675 Mass Ave, Cambridge, MA 02139, USA.
!> Add data block to record. Called from user code.
!!
!! CALL MILLE(...) ! measured value, derivatives (one set)
!! CALL ENDLE ! complete, write record (many sets)
!! (or CALL KILLE ! stop record)
!!
!! The data transmitted by MILLE calls are collected in two arrays,
!! a real array and an integer array, of same length. The collected
!! data are written at the ENDLE call. The content of the arrays:
!!
!! real array integer array
!! 1 0.0 error count (this record)
!! 2 RMEAS, measured value 0 JA
!! 3 local derivative index of local derivative
!! 4 local derivative index of local derivative
!! 5 ...
!! 6 SIGMA, error (>0) 0 JB
!! global derivative label of global derivative
!! global derivative label of global derivative IST
!! RMEAS, measured value 0
!! local derivative index of local derivative
!! local derivative index of local derivative
!! ...
!! SIGMA, error 0
!! global derivative label of global derivative
!! global derivative label of global derivative
!! ...
!! NR global derivative label of global derivative
!!
!! The 0's in the integer array allow to recognize the start
!! of a new set, the measured value and the error. The local and
!! the global derivatives are inbetween, with a positive value in
!! the integer array, the index of the local derivative or the
!! label of the global derivative.
!!
!! If more than one output unit is needed: duplicate this subroutine
!! change the entry names to e.g. AMILLE, AENDLE, AKILLE and change
!! the value of LUN and evtl. the dimension parameter in the
!! parameter statements.
!!
!! \param [in] NLC number of local derivatives
!! \param [in] DERLC local derivatives
!! \param [in] NGL number of global derivatives
!! \param [in] DERGL global derivatives
!! \param [in] LABEL labels for global derivatives
!! \param [in] RMEAS measurement
!! \param [in] SIGMA error of measurement
SUBROUTINE MILLE(nlc,derlc,ngl,dergl,label,rmeas,sigma) ! add data
USE mpdef
IMPLICIT NONE
INTEGER(mpi) :: i
INTEGER(mpi) :: icount
INTEGER(mpi) :: isp
INTEGER(mpi) :: nr
INTEGER(mpi) :: nsp
! -----------------------------------------------------------------
INTEGER(mpi), INTENT(IN) :: nlc
REAL(mps), INTENT(IN) :: derlc(nlc)
INTEGER(mpi), INTENT(IN) :: ngl
REAL(mps), INTENT(IN) :: dergl(ngl)
INTEGER(mpi), INTENT(IN) :: label(ngl)
REAL(mps), INTENT(IN) :: rmeas
REAL(mps), INTENT(IN) :: sigma
INTEGER(mpi), PARAMETER :: lun=51
INTEGER(mpi), PARAMETER :: ndim=10000
REAL(mps) :: glder(ndim) ! real data record array
INTEGER(mpi) :: inder(ndim) ! integer data record array
! -----------------------------------------------------------------
SAVE
DATA nr/0/ ! initial record length
DATA icount/0/
! ...
IF(sigma <= 0.0) RETURN ! error zero - no measurement
IF(nr == 0) THEN
nr=1
glder(1)=0.0
inder(1)=0 ! error counter
isp=0
END IF
IF(nr+nlc+ngl+2 > ndim) THEN
icount=icount+1
IF(icount <= 10) THEN
WRITE(*,*) 'Mille warning: data can not be stored'
IF(icount == 10) THEN
WRITE(*,*) 'Mille warning: no further printout'
END IF
END IF
inder(1)=inder(1)+1 ! count errors
RETURN ! record dimension too small
END IF
nr=nr+1
glder(nr)=rmeas ! measured value
inder(nr)=0
DO i=1,nlc ! local derivatives
IF(derlc(i) /= 0.0) THEN
nr=nr+1
glder(nr)=derlc(i) ! derivative of local parameter
inder(nr)=i ! index of local parameter
END IF
END DO
nr=nr+1
glder(nr)=sigma ! error of measured value
inder(nr)=0
DO i=1,ngl ! global derivatives
IF(dergl(i) /= 0.0.AND.label(i) > 0) THEN
nr=nr+1
glder(nr)=dergl(i) ! derivative of global parameter
inder(nr)=label(i) ! index of global parameter
END IF
END DO
RETURN
ENTRY MILLSP(nsp,dergl,label)
! add NSP special words (floating-point and integer)
! 0.0 0
! -float(NSP) 0 ! indicates special data
! following NSP floating and NSP integer data
IF(nsp <= 0.OR.isp /= 0) RETURN
isp=nr
IF(nr == 0) THEN
nr=1
glder(1)=0.0
inder(1)=0 ! error counter
END IF
IF(nr+nsp+2 > ndim) THEN
inder(1)=inder(1)+1 ! count errors
RETURN ! record dimension too small
END IF
nr=nr+1 ! zero pair
glder(nr)=0.0
inder(nr)=0
nr=nr+1 ! nsp and zero
glder(nr)=-REAL(nsp,mps)
inder(nr)=0
DO i=1,nsp
nr=nr+1
glder(nr)=dergl(i) ! floating-point
inder(nr)=label(i) ! integer
END DO
RETURN
ENTRY KILLE ! stop record
nr=0 ! reset
RETURN
ENTRY ENDLE ! end-of-record
IF(nr > 1) THEN
WRITE(lun) nr+nr,(glder(i),i=1,nr),(inder(i),i=1,nr)
END IF
nr=0 ! reset
RETURN
END SUBROUTINE MILLE