Line data Source code
1 0 : subroutine do_CSHEP2_sg (N,X,Y,F,NC,NW,NR,LCELL,LNEXT,XMIN,
2 0 : & YMIN,DX,DY,RMAX,RW,A,IER)
3 : integer :: N, NC, NW, NR, LCELL(NR,NR), LNEXT(N), IER
4 : real :: X(N), Y(N), F(N), XMIN, YMIN, DX, DY, RMAX, RW(N), A(9,N)
5 :
6 : ! **********************************************************
7 :
8 : ! From CSHEP2D
9 : ! Robert J. Renka
10 : ! Dept. of Computer Science
11 : ! Univ. of North Texas
12 : ! renka@cs.unt.edu
13 : ! 02/13/97
14 :
15 : ! This subroutine computes a set of parameters defining a
16 : ! C2 (twice continuously differentiable) bivariate function
17 : ! C(X,Y) which interpolates data values F at a set of N
18 : ! arbitrarily distributed points (X,Y) in the plane (nodes).
19 : ! The interpolant C may be evaluated at an arbitrary point
20 : ! by function CS2VAL, and its first partial derivatives are
21 : ! computed by Subroutine CS2GRD.
22 :
23 : ! The interpolation scheme is a modified Cubic Shepard
24 : ! method:
25 :
26 : ! C = [W(1)*C(1)+W(2)*C(2)+..+W(N)*C(N)]/[W(1)+W(2)+..+W(N)]
27 :
28 : ! for bivariate functions W(k) and C(k). The nodal func-
29 : ! tions are given by
30 :
31 : ! C(k)(x,y) = A(1,k)*(x-X(k))**3 +
32 : ! A(2,k)*(x-X(k))**2*(y-Y(k)) +
33 : ! A(3,k)*(x-X(k))*(y-Y(k))**2 +
34 : ! A(4,k)*(y-Y(k))**3 + A(5,k)*(x-X(k))**2 +
35 : ! A(6,k)*(x-X(k))*(y-Y(k)) + A(7,k)*(y-Y(k))**2
36 : ! + A(8,k)*(x-X(k)) + A(9,k)*(y-Y(k)) + F(k) .
37 :
38 : ! Thus, C(k) is a cubic function which interpolates the data
39 : ! value at node k. Its coefficients A(,k) are obtained by a
40 : ! weighted least squares fit to the closest NC data points
41 : ! with weights similar to W(k). Note that the radius of
42 : ! influence for the least squares fit is fixed for each k,
43 : ! but varies with k.
44 :
45 : ! The weights are taken to be
46 :
47 : ! W(k)(x,y) = ( (R(k)-D(k))+ / R(k)*D(k) )**3 ,
48 :
49 : ! where (R(k)-D(k))+ = 0 if R(k) < D(k), and D(k)(x,y) is
50 : ! the Euclidean distance between (x,y) and (X(k),Y(k)). The
51 : ! radius of influence R(k) varies with k and is chosen so
52 : ! that NW nodes are within the radius. Note that W(k) is
53 : ! not defined at node (X(k),Y(k)), but C(x,y) has limit F(k)
54 : ! as (x,y) approaches (X(k),Y(k)).
55 :
56 : ! On input:
57 :
58 : ! N = Number of nodes and data values. N >= 10.
59 :
60 : ! X,Y = Arrays of length N containing the Cartesian
61 : ! coordinates of the nodes.
62 :
63 : ! F = Array of length N containing the data values
64 : ! in one-to-one correspondence with the nodes.
65 :
66 : ! NC = Number of data points to be used in the least
67 : ! squares fit for coefficients defining the nodal
68 : ! functions C(k). Values found to be optimal for
69 : ! test data sets ranged from 11 to 25. A recom-
70 : ! mended value for general data sets is NC = 17.
71 : ! For nodes lying on (or close to) a rectangular
72 : ! grid, the recommended value is NC = 11. In any
73 : ! case, NC must be in the range 9 to Min(40,N-1).
74 :
75 : ! NW = Number of nodes within (and defining) the radii
76 : ! of influence R(k) which enter into the weights
77 : ! W(k). For N sufficiently large, a recommended
78 : ! value is NW = 30. In general, NW should be
79 : ! about 1.5*NC. 1 <= NW <= Min(40,N-1).
80 :
81 : ! NR = Number of rows and columns in the cell grid de-
82 : ! fined in Subroutine STORE2_sg. A rectangle con-
83 : ! taining the nodes is partitioned into cells in
84 : ! order to increase search efficiency. NR =
85 : ! Sqrt(N/3) is recommended. NR >= 1.
86 :
87 : ! The above parameters are not altered by this routine.
88 :
89 : ! LCELL = Array of length >= NR**2.
90 :
91 : ! LNEXT = Array of length >= N.
92 :
93 : ! RW = Array of length >= N.
94 :
95 : ! A = Array of length >= 9N.
96 :
97 : ! On output:
98 :
99 : ! LCELL = NR by NR array of nodal indexes associated
100 : ! with cells. Refer to Subroutine STORE2_sg.
101 :
102 : ! LNEXT = Array of length N containing next-node
103 : ! indexes. Refer to Subroutine STORE2_sg.
104 :
105 : ! XMIN,YMIN,DX,DY = Minimum nodal coordinates and cell
106 : ! dimensions. Refer to Subroutine
107 : ! STORE2_sg.
108 :
109 : ! RMAX = Largest element in RW -- maximum radius R(k).
110 :
111 : ! RW = Array containing the the radii R(k) which enter
112 : ! into the weights W(k).
113 :
114 : ! A = 9 by N array containing the coefficients for
115 : ! cubic nodal function C(k) in column k.
116 :
117 : ! Note that the output parameters described above are not
118 : ! defined unless IER = 0.
119 :
120 : ! IER = Error indicator:
121 : ! IER = 0 if no errors were encountered.
122 : ! IER = 1 if N, NC, NW, or NR is outside its
123 : ! valid range.
124 : ! IER = 2 if duplicate nodes were encountered.
125 : ! IER = 3 if all nodes are collinear.
126 :
127 : ! Modules required by CSHEP2: GETNP2_sg, GIVENS_sg, ROTATE_sg,
128 : ! SETUP2_sg, STORE2_sg
129 :
130 : ! Intrinsic functions called by CSHEP2: ABS, DBLE, MAX,
131 : ! MIN, SQRT
132 :
133 : ! **********************************************************
134 :
135 : integer :: LMX
136 : parameter (LMX=40)
137 : integer :: I, IERR, IP1, IRM1, IROW, J, JP1, K, LMAX,
138 : & LNP, NEQ, NN, NNC, NNR, NNW, NP, NPTS(LMX),
139 : & NCWMAX
140 0 : real :: B(10,10), C, DDX, DDY, DMIN, DTOL,
141 0 : & FK, RC, RS, RSMX, RSOLD, RTOL, RWS,
142 0 : & S, SF, SFC, SFS, STF, SUM, T, XK,
143 0 : & XMN, YK, YMN
144 :
145 : DATA RTOL/1.D-5/, DTOL/.01/
146 :
147 : ! Local parameters:
148 :
149 : ! B = Transpose of the augmented regression matrix
150 : ! C = First component of the plane rotation used to
151 : ! zero the lower triangle of B**T -- computed
152 : ! by Subroutine GIVENS_sg
153 : ! DDX,DDY = Local variables for DX and DY
154 : ! DMIN = Minimum of the magnitudes of the diagonal
155 : ! elements of the regression matrix after
156 : ! zeros are introduced below the diagonal
157 : ! DTOL = Tolerance for detecting an ill-conditioned
158 : ! system. The system is accepted when
159 : ! DMIN*RC >= DTOL.
160 : ! FK = Data value at mode K -- F(K)
161 : ! I = Index for A, B, and NPTS
162 : ! IERR = Error flag for the call to Subroutine STORE2_sg
163 : ! IP1 = I+1
164 : ! IRM1 = IROW-1
165 : ! IROW = Row index for B
166 : ! J = Index for A and B
167 : ! JP1 = J+1
168 : ! K = Nodal function index and column index for A
169 : ! LMAX = Maximum number of NPTS elements
170 : ! LMX = Maximum value of LMAX
171 : ! LNP = Current length of NPTS
172 : ! NEQ = Number of equations in the least squares fit
173 : ! NN,NNC,NNR = Local copies of N, NC, and NR
174 : ! NNW = Local copy of NW
175 : ! NP = NPTS element
176 : ! NPTS = Array containing the indexes of a sequence of
177 : ! nodes to be used in the least squares fit
178 : ! or to compute RW. The nodes are ordered
179 : ! by distance from K, and the last element
180 : ! (usually indexed by LNP) is used only to
181 : ! determine RC, or RW(K) if NW > NC.
182 : ! NCWMAX = Max(NC,NW)
183 : ! RC = Radius of influence which enters into the
184 : ! weights for C(K) (see Subroutine SETUP2_sg)
185 : ! RS = Squared distance between K and NPTS(LNP) --
186 : ! used to compute RC and RW(K)
187 : ! RSMX = Maximum squared RW element encountered
188 : ! RSOLD = Squared distance between K and NPTS(LNP-1) --
189 : ! used to compute a relative change in RS
190 : ! between succeeding NPTS elements
191 : ! RTOL = Tolerance for detecting a sufficiently large
192 : ! relative change in RS. If the change is
193 : ! not greater than RTOL, the nodes are
194 : ! treated as being the same distance from K
195 : ! RWS = Current squared value of RW(K)
196 : ! S = Second component of the plane rotation deter-
197 : ! mined by subroutine GIVENS_sg
198 : ! SF = Scale factor for the linear terms (columns 8
199 : ! and 9) in the least squares fit -- inverse
200 : ! of the root-mean-square distance between K
201 : ! and the nodes (other than K) in the least
202 : ! squares fit
203 : ! SFS = Scale factor for the quadratic terms (columns
204 : ! 5, 6, and 7) in the least squares fit --
205 : ! SF*SF
206 : ! SFC = Scale factor for the cubic terms (first 4
207 : ! columns) in the least squares fit -- SF**3
208 : ! STF = Marquardt stabilization factor used to damp
209 : ! out the first 4 solution components (third
210 : ! partials of the cubic) when the system is
211 : ! ill-conditioned. As STF increases, the
212 : ! fitting function approaches a quadratic
213 : ! polynomial.
214 : ! SUM = Sum of squared Euclidean distances between
215 : ! node K and the nodes used in the least
216 : ! squares fit (unless additional nodes are
217 : ! added for stability)
218 : ! T = Temporary variable for accumulating a scalar
219 : ! product in the back solve
220 : ! XK,YK = Coordinates of node K -- X(K), Y(K)
221 : ! XMN,YMN = Local variables for XMIN and YMIN
222 :
223 0 : NN = N
224 0 : NNC = NC
225 0 : NNW = NW
226 0 : NNR = NR
227 0 : NCWMAX = MAX(NNC,NNW)
228 0 : LMAX = MIN(LMX,NN-1)
229 : if (NNC < 9 .or. NNW < 1 .or. NCWMAX >
230 0 : & LMAX .or. NNR < 1) GOTO 21
231 :
232 : ! Create the cell data structure, and initialize RSMX.
233 :
234 0 : call STORE2_sg (NN,X,Y,NNR, LCELL,LNEXT,XMN,YMN,DDX,DDY,IERR)
235 0 : if (IERR /= 0) GOTO 23
236 : RSMX = 0.
237 :
238 : ! Outer loop on node K:
239 :
240 0 : do K = 1,NN
241 0 : XK = X(K)
242 0 : YK = Y(K)
243 0 : FK = F(K)
244 :
245 : ! Mark node K to exclude it from the search for nearest
246 : ! neighbors.
247 :
248 0 : LNEXT(K) = -LNEXT(K)
249 :
250 : ! Initialize for loop on NPTS.
251 :
252 0 : RS = 0.
253 0 : SUM = 0.
254 0 : RWS = 0.
255 0 : RC = 0.
256 0 : LNP = 0
257 :
258 : ! Compute NPTS, LNP, RWS, NEQ, RC, and SFS.
259 :
260 0 : 1 SUM = SUM + RS
261 0 : if (LNP == LMAX) GOTO 2
262 0 : LNP = LNP + 1
263 0 : RSOLD = RS
264 : call GETNP2_sg (XK,YK,X,Y,NNR,LCELL,LNEXT,XMN,YMN,
265 0 : & DDX,DDY, NP,RS)
266 0 : if (RS == 0.) GOTO 22
267 0 : NPTS(LNP) = NP
268 0 : if ( (RS-RSOLD)/RS < RTOL ) GOTO 1
269 0 : if (RWS == 0. .and. LNP > NNW) RWS = RS
270 0 : if (RC == 0. .and. LNP > NNC) then
271 :
272 : ! RC = 0 (not yet computed) and LNP > NC. RC = Sqrt(RS)
273 : ! is sufficiently large to (strictly) include NC nodes.
274 : ! The least squares fit will include NEQ = LNP - 1
275 : ! equations for 9 <= NC <= NEQ < LMAX <= N-1.
276 :
277 0 : NEQ = LNP - 1
278 0 : RC = SQRT(RS)
279 0 : SFS = DBLE(NEQ)/SUM
280 : end if
281 :
282 : ! Bottom of loop -- test for termination.
283 :
284 0 : if (LNP > NCWMAX) GOTO 3
285 0 : GOTO 1
286 :
287 : ! All LMAX nodes are included in NPTS. RWS and/or RC**2 is
288 : ! (arbitrarily) taken to be 10 percent larger than the
289 : ! distance RS to the last node included.
290 :
291 0 : 2 if (RWS == 0.) RWS = 1.1*RS
292 0 : if (RC == 0.) then
293 0 : NEQ = LMAX
294 0 : RC = SQRT(1.1*RS)
295 0 : SFS = DBLE(NEQ)/SUM
296 : end if
297 :
298 : ! Store RW(K), update RSMX if necessary, and compute SF
299 : ! and SFC.
300 :
301 0 : 3 RW(K) = SQRT(RWS)
302 0 : if (RWS > RSMX) RSMX = RWS
303 0 : SF = SQRT(SFS)
304 0 : SFC = SF*SFS
305 :
306 : ! A Q-R decomposition is used to solve the least squares
307 : ! system. The transpose of the augmented regression
308 : ! matrix is stored in B with columns (rows of B) defined
309 : ! as follows: 1-4 are the cubic terms, 5-7 are the quad-
310 : ! ratic terms, 8 and 9 are the linear terms, and the last
311 : ! column is the right hand side.
312 :
313 : ! Set up the equations and zero out the lower triangle with
314 : ! Givens rotations.
315 :
316 0 : I = 0
317 0 : 4 I = I + 1
318 0 : NP = NPTS(I)
319 0 : IROW = MIN(I,10)
320 : call SETUP2_sg (XK,YK,FK,X(NP),Y(NP),F(NP),SF,SFS,
321 0 : & SFC,RC, B(1,IROW))
322 0 : if (I == 1) GOTO 4
323 : IRM1 = IROW-1
324 0 : do 5 J = 1,IRM1
325 0 : JP1 = J + 1
326 0 : call GIVENS_sg (B(J,J),B(J,IROW),C,S)
327 0 : call ROTATE_sg (10-J,C,S,B(JP1,J),B(JP1,IROW))
328 0 : 5 continue
329 0 : if (I < NEQ) GOTO 4
330 :
331 : ! Test the system for ill-conditioning.
332 :
333 : DMIN = MIN( ABS(B(1,1)),ABS(B(2,2)),ABS(B(3,3)),
334 : & ABS(B(4,4)),ABS(B(5,5)),ABS(B(6,6)),
335 0 : & ABS(B(7,7)),ABS(B(8,8)),ABS(B(9,9)) )
336 0 : if (DMIN*RC >= DTOL) GOTO 11
337 0 : if (NEQ == LMAX) GOTO 7
338 :
339 : ! Increase RC and add another equation to the system to
340 : ! improve the conditioning. The number of NPTS elements
341 : ! is also increased if necessary.
342 :
343 0 : 6 RSOLD = RS
344 0 : NEQ = NEQ + 1
345 0 : if (NEQ == LMAX) then
346 0 : RC = SQRT(1.1*RS)
347 0 : GOTO 4
348 : end if
349 0 : if (NEQ < LNP) then
350 :
351 : ! NEQ < LNP.
352 :
353 0 : NP = NPTS(NEQ+1)
354 0 : RS = (X(NP)-XK)**2 + (Y(NP)-YK)**2
355 0 : if ( (RS-RSOLD)/RS < RTOL ) GOTO 6
356 0 : RC = SQRT(RS)
357 0 : GOTO 4
358 : end if
359 :
360 : ! NEQ = LNP. Add an element to NPTS.
361 :
362 0 : LNP = LNP + 1
363 : call GETNP2_sg (XK,YK,X,Y,NNR,LCELL,LNEXT,XMN,YMN,
364 0 : & DDX,DDY, NP,RS)
365 0 : if (NP == 0) GOTO 22
366 0 : NPTS(LNP) = NP
367 0 : if ( (RS-RSOLD)/RS < RTOL ) GOTO 6
368 0 : RC = SQRT(RS)
369 0 : GOTO 4
370 :
371 : ! Stabilize the system by damping third partials -- add
372 : ! multiples of the first four unit vectors to the first
373 : ! four equations.
374 :
375 0 : 7 STF = 1.0/RC
376 0 : do I = 1,4
377 0 : B(I,10) = STF
378 0 : IP1 = I + 1
379 0 : do J = IP1,10
380 0 : B(J,10) = 0.
381 : end do
382 0 : do J = I,9
383 0 : JP1 = J + 1
384 0 : call GIVENS_sg (B(J,J),B(J,10),C,S)
385 0 : call ROTATE_sg (10-J,C,S,B(JP1,J),B(JP1,10))
386 : end do
387 : end do
388 :
389 : ! Test the damped system for ill-conditioning.
390 :
391 : DMIN = MIN( ABS(B(5,5)),ABS(B(6,6)),ABS(B(7,7)),
392 0 : & ABS(B(8,8)),ABS(B(9,9)) )
393 0 : if (DMIN*RC < DTOL) GOTO 23
394 :
395 : ! Solve the 9 by 9 triangular system for the coefficients.
396 :
397 0 : 11 do I = 9,1,-1
398 0 : T = 0.
399 0 : if (I /= 9) then
400 0 : IP1 = I + 1
401 0 : do J = IP1,9
402 0 : T = T + B(J,I)*A(J,K)
403 : end do
404 : end if
405 0 : A(I,K) = (B(10,I)-T)/B(I,I)
406 : end do
407 :
408 : ! Scale the coefficients to adjust for the column scaling.
409 :
410 0 : do I = 1,4
411 0 : A(I,K) = A(I,K)*SFC
412 : end do
413 0 : A(5,K) = A(5,K)*SFS
414 0 : A(6,K) = A(6,K)*SFS
415 0 : A(7,K) = A(7,K)*SFS
416 0 : A(8,K) = A(8,K)*SF
417 0 : A(9,K) = A(9,K)*SF
418 :
419 : ! Unmark K and the elements of NPTS.
420 :
421 0 : LNEXT(K) = -LNEXT(K)
422 0 : do I = 1,LNP
423 0 : NP = NPTS(I)
424 0 : LNEXT(NP) = -LNEXT(NP)
425 : end do
426 : end do
427 :
428 : ! No errors encountered.
429 :
430 0 : XMIN = XMN
431 0 : YMIN = YMN
432 0 : DX = DDX
433 0 : DY = DDY
434 0 : RMAX = SQRT(RSMX)
435 0 : IER = 0
436 0 : return
437 :
438 : ! N, NC, NW, or NR is outside its valid range.
439 :
440 0 : 21 IER = 1
441 0 : return
442 :
443 : ! Duplicate nodes were encountered by GETNP2_sg.
444 :
445 0 : 22 IER = 2
446 0 : return
447 :
448 : ! No unique solution due to collinear nodes.
449 :
450 0 : 23 XMIN = XMN
451 0 : YMIN = YMN
452 0 : DX = DDX
453 0 : DY = DDY
454 0 : IER = 3
455 0 : return
456 : end subroutine do_CSHEP2_sg
457 :
458 0 : real FUNCTION do_CS2VAL_sg (PX,PY,N,X,Y,F,NR,
459 0 : & LCELL,LNEXT,XMIN,YMIN,DX,DY,RMAX,RW,A,IER)
460 : integer :: N, NR, LCELL(NR,NR), LNEXT(N), IER
461 : real :: PX, PY, X(N), Y(N), F(N), XMIN, YMIN,
462 : & DX, DY, RMAX, RW(N), A(9,N)
463 :
464 : ! **********************************************************
465 :
466 : ! From CSHEP2D
467 : ! Robert J. Renka
468 : ! Dept. of Computer Science
469 : ! Univ. of North Texas
470 : ! renka@cs.unt.edu
471 : ! 02/03/97
472 :
473 : ! This function returns the value C(PX,PY), where C is the
474 : ! weighted sum of cubic nodal functions defined in Subrou-
475 : ! tine CSHEP2. CS2GRD may be called to compute a gradient
476 : ! of C along with the value, and/or to test for errors.
477 : ! CS2HES_sg may be called to compute a value, first partial
478 : ! derivatives, and second partial derivatives at a point.
479 :
480 : ! On input:
481 :
482 : ! PX,PY = Cartesian coordinates of the point P at
483 : ! which C is to be evaluated.
484 :
485 : ! N = Number of nodes and data values defining C.
486 : ! N >= 10.
487 :
488 : ! X,Y,F = Arrays of length N containing the nodes and
489 : ! data values interpolated by C.
490 :
491 : ! NR = Number of rows and columns in the cell grid.
492 : ! Refer to Subroutine STORE2_sg. NR >= 1.
493 :
494 : ! LCELL = NR by NR array of nodal indexes associated
495 : ! with cells. Refer to Subroutine STORE2_sg.
496 :
497 : ! LNEXT = Array of length N containing next-node
498 : ! indexes. Refer to Subroutine STORE2_sg.
499 :
500 : ! XMIN,YMIN,DX,DY = Minimum nodal coordinates and cell
501 : ! dimensions. DX and DY must be
502 : ! positive. Refer to Subroutine
503 : ! STORE2_sg.
504 :
505 : ! RMAX = Largest element in RW -- maximum radius R(k).
506 :
507 : ! RW = Array containing the the radii R(k) which enter
508 : ! into the weights W(k) defining C.
509 :
510 : ! A = 9 by N array containing the coefficients for
511 : ! cubic nodal function C(k) in column k.
512 :
513 : ! Input parameters are not altered by this function. The
514 : ! parameters other than PX and PY should be input unaltered
515 : ! from their values on output from CSHEP2. This function
516 : ! should not be called if a nonzero error flag was returned
517 : ! by CSHEP2.
518 :
519 : ! On output:
520 :
521 : ! CS2VAL = Function value C(PX,PY) unless N, NR, DX,
522 : ! DY, or RMAX is invalid, in which case no
523 : ! value is returned.
524 :
525 : ! Modules required by CS2VAL: NONE
526 :
527 : ! Intrinsic functions called by CS2VAL: INT, SQRT
528 :
529 : ! **********************************************************
530 :
531 : integer :: I, IMAX, IMIN, J, JMAX, JMIN, K, KP
532 0 : real :: D, DELX, DELY, R, SW, SWC, W, XP, YP
533 :
534 : ! Local parameters:
535 :
536 : ! D = Distance between P and node K
537 : ! DELX = XP - X(K)
538 : ! DELY = YP - Y(K)
539 : ! I = Cell row index in the range IMIN to IMAX
540 : ! IMIN,IMAX = Range of cell row indexes of the cells
541 : ! intersected by a disk of radius RMAX
542 : ! centered at P
543 : ! J = Cell column index in the range JMIN to JMAX
544 : ! JMIN,JMAX = Range of cell column indexes of the cells
545 : ! intersected by a disk of radius RMAX
546 : ! centered at P
547 : ! K = Index of a node in cell (I,J)
548 : ! KP = Previous value of K in the sequence of nodes
549 : ! in cell (I,J)
550 : ! R = Radius of influence for node K
551 : ! SW = Sum of weights W(K)
552 : ! SWC = Sum of weighted nodal function values at P
553 : ! W = Weight W(K) value at P: ((R-D)+/(R*D))**3,
554 : ! where (R-D)+ = 0 if R < D
555 : ! XP,YP = Local copies of PX and PY -- coordinates of P
556 :
557 0 : XP = PX
558 0 : YP = PY
559 0 : IER = -1
560 : if (N < 10 .or. NR < 1 .or. DX <= 0. .or.
561 0 : & DY <= 0. .or. RMAX < 0.) return
562 0 : IER = 0
563 :
564 : ! Set IMIN, IMAX, JMIN, and JMAX to cell indexes defining
565 : ! the range of the search for nodes whose radii include
566 : ! P. The cells which must be searched are those inter-
567 : ! sected by (or contained in) a circle of radius RMAX
568 : ! centered at P.
569 :
570 0 : IMIN = INT((XP-XMIN-RMAX)/DX) + 1
571 0 : IMAX = INT((XP-XMIN+RMAX)/DX) + 1
572 0 : if (IMIN < 1) IMIN = 1
573 0 : if (IMAX > NR) IMAX = NR
574 0 : JMIN = INT((YP-YMIN-RMAX)/DY) + 1
575 0 : JMAX = INT((YP-YMIN+RMAX)/DY) + 1
576 0 : if (JMIN < 1) JMIN = 1
577 0 : if (JMAX > NR) JMAX = NR
578 :
579 : ! The following is a test for no cells within the circle
580 : ! of radius RMAX.
581 :
582 0 : if (IMIN > IMAX .or. JMIN > JMAX) GOTO 6
583 :
584 : ! Accumulate weight values in SW and weighted nodal function
585 : ! values in SWC. The weights are W(K) = ((R-D)+/(R*D))**3
586 : ! for R = RW(K) and D = distance between P and node K.
587 :
588 : SW = 0.
589 : SWC = 0.
590 :
591 : ! Outer loop on cells (I,J).
592 :
593 0 : do 4 J = JMIN,JMAX
594 0 : do 3 I = IMIN,IMAX
595 0 : K = LCELL(I,J)
596 0 : if (K == 0) GOTO 3
597 :
598 : ! Inner loop on nodes K.
599 :
600 0 : 1 DELX = XP - X(K)
601 0 : DELY = YP - Y(K)
602 0 : D = SQRT(DELX*DELX + DELY*DELY)
603 0 : R = RW(K)
604 0 : if (D >= R) GOTO 2
605 0 : if (D == 0.) GOTO 5
606 0 : W = (1.0/D - 1.0/R)*(1.0/D - 1.0/R)*(1.0/D - 1.0/R)
607 0 : SW = SW + W
608 : SWC = SWC + W*( ( (A(1,K)*DELX+A(2,K)*DELY+
609 : & A(5,K))*DELX + (A(3,K)*DELY+
610 : & A(6,K))*DELY + A(8,K) )*DELX +
611 : & ( (A(4,K)*DELY+A(7,K))*DELY +
612 0 : & A(9,K) )*DELY + F(K) )
613 :
614 : ! Bottom of loop on nodes in cell (I,J).
615 :
616 0 : 2 KP = K
617 0 : K = LNEXT(KP)
618 0 : if (K /= KP) GOTO 1
619 0 : 3 continue
620 0 : 4 continue
621 :
622 : ! SW = 0 iff P is not within the radius R(K) for any node K.
623 :
624 0 : if (SW == 0.) GOTO 6
625 0 : do_CS2VAL_sg = SWC/SW
626 0 : return
627 :
628 : ! (PX,PY) = (X(K),Y(K)).
629 :
630 0 : 5 do_CS2VAL_sg = F(K)
631 0 : return
632 :
633 : ! All weights are 0 at P.
634 :
635 0 : 6 do_CS2VAL_sg = 0.
636 : return
637 : end function do_CS2VAL_sg
638 :
639 0 : subroutine do_CS2GRD_sg (PX,PY,N,X,Y,F,NR,LCELL,LNEXT,XMIN,
640 0 : & YMIN,DX,DY,RMAX,RW,A, C,CX,CY,IER)
641 : integer :: N, NR, LCELL(NR,NR), LNEXT(N), IER
642 : real :: PX, PY, X(N), Y(N), F(N), XMIN, YMIN,
643 : & DX, DY, RMAX, RW(N), A(9,N), C, CX, CY
644 :
645 : ! **********************************************************
646 :
647 : ! From CSHEP2D
648 : ! Robert J. Renka
649 : ! Dept. of Computer Science
650 : ! Univ. of North Texas
651 : ! renka@cs.unt.edu
652 : ! 02/03/97
653 :
654 : ! This subroutine computes the value and gradient at P =
655 : ! (PX,PY) of the interpolatory function C defined in Sub-
656 : ! routine CSHEP2. C is a weighted sum of cubic nodal
657 : ! functions.
658 :
659 : ! On input:
660 :
661 : ! PX,PY = Cartesian coordinates of the point P at
662 : ! which C and its partial derivatives are
663 : ! to be evaluated.
664 :
665 : ! N = Number of nodes and data values defining C.
666 : ! N >= 10.
667 :
668 : ! X,Y,F = Arrays of length N containing the nodes and
669 : ! data values interpolated by C.
670 :
671 : ! NR = Number of rows and columns in the cell grid.
672 : ! Refer to Subroutine STORE2_sg. NR >= 1.
673 :
674 : ! LCELL = NR by NR array of nodal indexes associated
675 : ! with cells. Refer to Subroutine STORE2_sg.
676 :
677 : ! LNEXT = Array of length N containing next-node
678 : ! indexes. Refer to Subroutine STORE2_sg.
679 :
680 : ! XMIN,YMIN,DX,DY = Minimum nodal coordinates and cell
681 : ! dimensions. DX and DY must be
682 : ! positive. Refer to Subroutine
683 : ! STORE2_sg.
684 :
685 : ! RMAX = Largest element in RW -- maximum radius R(k).
686 :
687 : ! RW = Array of length N containing the the radii R(k)
688 : ! which enter into the weights W(k) defining C.
689 :
690 : ! A = 9 by N array containing the coefficients for
691 : ! cubic nodal function C(k) in column k.
692 :
693 : ! Input parameters are not altered by this subroutine.
694 : ! The parameters other than PX and PY should be input
695 : ! unaltered from their values on output from CSHEP2. This
696 : ! subroutine should not be called if a nonzero error flag
697 : ! was returned by CSHEP2.
698 :
699 : ! On output:
700 :
701 : ! C = Value of C at (PX,PY) unless IER == 1, in
702 : ! which case no values are returned.
703 :
704 : ! CX,CY = First partial derivatives of C at (PX,PY)
705 : ! unless IER == 1.
706 :
707 : ! IER = Error indicator:
708 : ! IER = 0 if no errors were encountered.
709 : ! IER = 1 if N, NR, DX, DY or RMAX is invalid.
710 : ! IER = 2 if no errors were encountered but
711 : ! (PX,PY) is not within the radius R(k)
712 : ! for any node k (and thus C=CX=CY=0).
713 :
714 : ! Modules required by CS2GRD: None
715 :
716 : ! Intrinsic functions called by CS2GRD: INT, SQRT
717 :
718 : ! **********************************************************
719 :
720 : integer :: I, IMAX, IMIN, J, JMAX, JMIN, K, KP
721 0 : real :: CK, CKX, CKY, D, DELX, DELY, R, SW,
722 0 : & SWC, SWCX, SWCY, SWS, SWX, SWY, T, W,
723 0 : & WX, WY, XP, YP
724 :
725 : ! Local parameters:
726 :
727 : ! CK = Value of cubic nodal function C(K) at P
728 : ! CKX,CKY = Partial derivatives of C(K) with respect to X
729 : ! and Y, respectively
730 : ! D = Distance between P and node K
731 : ! DELX = XP - X(K)
732 : ! DELY = YP - Y(K)
733 : ! I = Cell row index in the range IMIN to IMAX
734 : ! IMIN,IMAX = Range of cell row indexes of the cells
735 : ! intersected by a disk of radius RMAX
736 : ! centered at P
737 : ! J = Cell column index in the range JMIN to JMAX
738 : ! JMIN,JMAX = Range of cell column indexes of the cells
739 : ! intersected by a disk of radius RMAX
740 : ! centered at P
741 : ! K = Index of a node in cell (I,J)
742 : ! KP = Previous value of K in the sequence of nodes
743 : ! in cell (I,J)
744 : ! R = Radius of influence for node K
745 : ! SW = Sum of weights W(K)
746 : ! SWC = Sum of weighted nodal function values at P
747 : ! SWCX,SWCY = Partial derivatives of SWC with respect to X
748 : ! and Y, respectively
749 : ! SWS = SW**2
750 : ! SWX,SWY = Partial derivatives of SW with respect to X
751 : ! and Y, respectively
752 : ! T = Temporary variable
753 : ! W = Weight W(K) value at P: ((R-D)+/(R*D))**3,
754 : ! where (R-D)+ = 0 if R < D
755 : ! WX,WY = Partial derivatives of W with respect to X
756 : ! and Y, respectively
757 : ! XP,YP = Local copies of PX and PY -- coordinates of P
758 :
759 0 : XP = PX
760 0 : YP = PY
761 : if (N < 10 .or. NR < 1 .or. DX <= 0. .or.
762 0 : & DY <= 0. .or. RMAX < 0.) GOTO 6
763 :
764 : ! Set IMIN, IMAX, JMIN, and JMAX to cell indexes defining
765 : ! the range of the search for nodes whose radii include
766 : ! P. The cells which must be searched are those inter-
767 : ! sected by (or contained in) a circle of radius RMAX
768 : ! centered at P.
769 :
770 0 : IMIN = INT((XP-XMIN-RMAX)/DX) + 1
771 0 : IMAX = INT((XP-XMIN+RMAX)/DX) + 1
772 0 : if (IMIN < 1) IMIN = 1
773 0 : if (IMAX > NR) IMAX = NR
774 0 : JMIN = INT((YP-YMIN-RMAX)/DY) + 1
775 0 : JMAX = INT((YP-YMIN+RMAX)/DY) + 1
776 0 : if (JMIN < 1) JMIN = 1
777 0 : if (JMAX > NR) JMAX = NR
778 :
779 : ! The following is a test for no cells within the circle
780 : ! of radius RMAX.
781 :
782 0 : if (IMIN > IMAX .or. JMIN > JMAX) GOTO 7
783 :
784 : ! C = SWC/SW = Sum(W(K)*C(K))/Sum(W(K)), where the sum is
785 : ! from K = 1 to N, C(K) is the cubic nodal function value,
786 : ! and W(K) = ((R-D)+/(R*D))**3 for radius R(K) and dist-
787 : ! ance D(K). Thus
788 :
789 : ! CX = (SWCX*SW - SWC*SWX)/SW**2 and
790 : ! CY = (SWCY*SW - SWC*SWY)/SW**2
791 :
792 : ! where SWCX and SWX are partial derivatives with respect
793 : ! to X of SWC and SW, respectively. SWCY and SWY are de-
794 : ! fined similarly.
795 :
796 : SW = 0.
797 : SWX = 0.
798 : SWY = 0.
799 : SWC = 0.
800 : SWCX = 0.
801 : SWCY = 0.
802 :
803 : ! Outer loop on cells (I,J).
804 :
805 0 : do 4 J = JMIN,JMAX
806 0 : do 3 I = IMIN,IMAX
807 0 : K = LCELL(I,J)
808 0 : if (K == 0) GOTO 3
809 :
810 : ! Inner loop on nodes K.
811 :
812 0 : 1 DELX = XP - X(K)
813 0 : DELY = YP - Y(K)
814 0 : D = SQRT(DELX*DELX + DELY*DELY)
815 0 : R = RW(K)
816 0 : if (D >= R) GOTO 2
817 0 : if (D == 0.) GOTO 5
818 0 : T = (1.0/D - 1.0/R)
819 0 : W = T*T*T
820 0 : T = -3.0*T*T/(D*D*D)
821 0 : WX = DELX*T
822 0 : WY = DELY*T
823 0 : T = A(2,K)*DELX + A(3,K)*DELY + A(6,K)
824 : CKY = ( 3.0*A(4,K)*DELY + A(3,K)*DELX +
825 0 : & 2.0*A(7,K) )*DELY + T*DELX + A(9,K)
826 0 : T = T*DELY + A(8,K)
827 : CKX = ( 3.0*A(1,K)*DELX + A(2,K)*DELY +
828 0 : & 2.0*A(5,K) )*DELX + T
829 : CK = ( (A(1,K)*DELX+A(5,K))*DELX + T )*DELX +
830 : & ( (A(4,K)*DELY+A(7,K))*DELY + A(9,K) )*DELY +
831 0 : & F(K)
832 0 : SW = SW + W
833 0 : SWX = SWX + WX
834 0 : SWY = SWY + WY
835 0 : SWC = SWC + W*CK
836 0 : SWCX = SWCX + WX*CK + W*CKX
837 0 : SWCY = SWCY + WY*CK + W*CKY
838 :
839 : ! Bottom of loop on nodes in cell (I,J).
840 :
841 0 : 2 KP = K
842 0 : K = LNEXT(KP)
843 0 : if (K /= KP) GOTO 1
844 0 : 3 continue
845 0 : 4 continue
846 :
847 : ! SW = 0 iff P is not within the radius R(K) for any node K.
848 :
849 0 : if (SW == 0.) GOTO 7
850 0 : C = SWC/SW
851 0 : SWS = SW*SW
852 0 : CX = (SWCX*SW - SWC*SWX)/SWS
853 0 : CY = (SWCY*SW - SWC*SWY)/SWS
854 0 : IER = 0
855 0 : return
856 :
857 : ! (PX,PY) = (X(K),Y(K)).
858 :
859 0 : 5 C = F(K)
860 0 : CX = A(8,K)
861 0 : CY = A(9,K)
862 0 : IER = 0
863 0 : return
864 :
865 : ! Invalid input parameter.
866 :
867 0 : 6 IER = 1
868 0 : return
869 :
870 : ! No cells contain a point within RMAX of P, or
871 : ! SW = 0 and thus D >= RW(K) for all K.
872 :
873 0 : 7 C = 0.
874 0 : CX = 0.
875 0 : CY = 0.
876 0 : IER = 2
877 0 : return
878 : end subroutine do_CS2GRD_sg
879 0 : subroutine CS2HES_sg (PX,PY,N,X,Y,F,NR,LCELL,LNEXT,XMIN,
880 0 : & YMIN,DX,DY,RMAX,RW,A, C,CX,CY,CXX,
881 : & CXY,CYY,IER)
882 : integer :: N, NR, LCELL(NR,NR), LNEXT(N), IER
883 : real :: PX, PY, X(N), Y(N), F(N), XMIN, YMIN,
884 : & DX, DY, RMAX, RW(N), A(9,N), C, CX,
885 : & CY, CXX, CXY, CYY
886 :
887 : ! **********************************************************
888 :
889 : ! From CSHEP2D
890 : ! Robert J. Renka
891 : ! Dept. of Computer Science
892 : ! Univ. of North Texas
893 : ! renka@cs.unt.edu
894 : ! 02/03/97
895 :
896 : ! This subroutine computes the value, gradient, and
897 : ! Hessian at P = (PX,PY) of the interpolatory function C
898 : ! defined in Subroutine CSHEP2. C is a weighted sum of
899 : ! cubic nodal functions.
900 :
901 : ! On input:
902 :
903 : ! PX,PY = Cartesian coordinates of the point P at
904 : ! which C and its partial derivatives are
905 : ! to be evaluated.
906 :
907 : ! N = Number of nodes and data values defining C.
908 : ! N >= 10.
909 :
910 : ! X,Y,F = Arrays of length N containing the nodes and
911 : ! data values interpolated by C.
912 :
913 : ! NR = Number of rows and columns in the cell grid.
914 : ! Refer to Subroutine STORE2_sg. NR >= 1.
915 :
916 : ! LCELL = NR by NR array of nodal indexes associated
917 : ! with cells. Refer to Subroutine STORE2_sg.
918 :
919 : ! LNEXT = Array of length N containing next-node
920 : ! indexes. Refer to Subroutine STORE2_sg.
921 :
922 : ! XMIN,YMIN,DX,DY = Minimum nodal coordinates and cell
923 : ! dimensions. DX and DY must be
924 : ! positive. Refer to Subroutine
925 : ! STORE2_sg.
926 :
927 : ! RMAX = Largest element in RW -- maximum radius R(k).
928 :
929 : ! RW = Array of length N containing the the radii R(k)
930 : ! which enter into the weights W(k) defining C.
931 :
932 : ! A = 9 by N array containing the coefficients for
933 : ! cubic nodal function C(k) in column k.
934 :
935 : ! Input parameters are not altered by this subroutine.
936 : ! The parameters other than PX and PY should be input
937 : ! unaltered from their values on output from CSHEP2. This
938 : ! subroutine should not be called if a nonzero error flag
939 : ! was returned by CSHEP2.
940 :
941 : ! On output:
942 :
943 : ! C = Value of C at (PX,PY) unless IER == 1, in
944 : ! which case no values are returned.
945 :
946 : ! CX,CY = First partial derivatives of C at (PX,PY)
947 : ! unless IER == 1.
948 :
949 : ! CXX,CXY,CYY = Second partial derivatives of C at
950 : ! (PX,PY) unless IER == 1.
951 :
952 : ! IER = Error indicator:
953 : ! IER = 0 if no errors were encountered.
954 : ! IER = 1 if N, NR, DX, DY or RMAX is invalid.
955 : ! IER = 2 if no errors were encountered but
956 : ! (PX,PY) is not within the radius R(k)
957 : ! for any node k (and thus C = 0).
958 :
959 : ! Modules required by CS2HES_sg: None
960 :
961 : ! Intrinsic functions called by CS2HES_sg: INT, SQRT
962 :
963 : ! **********************************************************
964 :
965 : integer :: I, IMAX, IMIN, J, JMAX, JMIN, K, KP
966 0 : real :: CK, CKX, CKXX, CKXY, CKY, CKYY, D,
967 0 : & DELX, DELY, DXSQ, DYSQ, R, SW, SWC,
968 0 : & SWCX, SWCXX, SWCXY, SWCY, SWCYY, SWS,
969 0 : & SWX, SWXX, SWXY, SWY, SWYY, T1, T2,
970 0 : & T3, T4, W, WX, WXX, WXY, WY, WYY, XP,
971 0 : & YP, D6
972 :
973 : ! Local parameters:
974 :
975 : ! CK = Value of cubic nodal function C(K) at P
976 : ! CKX,CKY = Partial derivatives of C(K) with respect to X
977 : ! and Y, respectively
978 : ! CKXX,CKXY,CKYY = Second partial derivatives of CK
979 : ! D = Distance between P and node K
980 : ! DELX = XP - X(K)
981 : ! DELY = YP - Y(K)
982 : ! DXSQ,DYSQ = DELX**2, DELY**2
983 : ! I = Cell row index in the range IMIN to IMAX
984 : ! IMIN,IMAX = Range of cell row indexes of the cells
985 : ! intersected by a disk of radius RMAX
986 : ! centered at P
987 : ! J = Cell column index in the range JMIN to JMAX
988 : ! JMIN,JMAX = Range of cell column indexes of the cells
989 : ! intersected by a disk of radius RMAX
990 : ! centered at P
991 : ! K = Index of a node in cell (I,J)
992 : ! KP = Previous value of K in the sequence of nodes
993 : ! in cell (I,J)
994 : ! R = Radius of influence for node K
995 : ! SW = Sum of weights W(K)
996 : ! SWC = Sum of weighted nodal function values at P
997 : ! SWCX,SWCY = Partial derivatives of SWC with respect to X
998 : ! and Y, respectively
999 : ! SWCXX,SWCXY,SWCYY = Second partial derivatives of SWC
1000 : ! SWS = SW**2
1001 : ! SWX,SWY = Partial derivatives of SW with respect to X
1002 : ! and Y, respectively
1003 : ! SWXX,SWXY,SWYY = Second partial derivatives of SW
1004 : ! T1,T2,T3,T4 = Temporary variables
1005 : ! W = Weight W(K) value at P: ((R-D)+/(R*D))**3,
1006 : ! where (R-D)+ = 0 if R < D
1007 : ! WX,WY = Partial derivatives of W with respect to X
1008 : ! and Y, respectively
1009 : ! WXX,WXY,WYY = Second partial derivatives of W
1010 : ! XP,YP = Local copies of PX and PY -- coordinates of P
1011 :
1012 0 : XP = PX
1013 0 : YP = PY
1014 : if (N < 10 .or. NR < 1 .or. DX <= 0. .or.
1015 0 : & DY <= 0. .or. RMAX < 0.) GOTO 6
1016 :
1017 : ! Set IMIN, IMAX, JMIN, and JMAX to cell indexes defining
1018 : ! the range of the search for nodes whose radii include
1019 : ! P. The cells which must be searched are those inter-
1020 : ! sected by (or contained in) a circle of radius RMAX
1021 : ! centered at P.
1022 :
1023 0 : IMIN = INT((XP-XMIN-RMAX)/DX) + 1
1024 0 : IMAX = INT((XP-XMIN+RMAX)/DX) + 1
1025 0 : if (IMIN < 1) IMIN = 1
1026 0 : if (IMAX > NR) IMAX = NR
1027 0 : JMIN = INT((YP-YMIN-RMAX)/DY) + 1
1028 0 : JMAX = INT((YP-YMIN+RMAX)/DY) + 1
1029 0 : if (JMIN < 1) JMIN = 1
1030 0 : if (JMAX > NR) JMAX = NR
1031 :
1032 : ! The following is a test for no cells within the circle
1033 : ! of radius RMAX.
1034 :
1035 0 : if (IMIN > IMAX .or. JMIN > JMAX) GOTO 7
1036 :
1037 : ! C = SWC/SW = Sum(W(K)*C(K))/Sum(W(K)), where the sum is
1038 : ! from K = 1 to N, C(K) is the cubic nodal function value,
1039 : ! and W(K) = ((R-D)+/(R*D))**3 for radius R(K) and dist-
1040 : ! ance D(K). Thus
1041 :
1042 : ! CX = (SWCX*SW - SWC*SWX)/SW**2 and
1043 : ! CY = (SWCY*SW - SWC*SWY)/SW**2
1044 :
1045 : ! where SWCX and SWX are partial derivatives with respect
1046 : ! to x of SWC and SW, respectively. SWCY and SWY are de-
1047 : ! fined similarly. The second partials are
1048 :
1049 : ! CXX = ( SW*(SWCXX - 2*SWX*CX) - SWC*SWXX )/SW**2
1050 : ! CXY = ( SW*(SWCXY-SWX*CY-SWY*CX) - SWC*SWXY )/SW**2
1051 : ! CYY = ( SW*(SWCYY - 2*SWY*CY) - SWC*SWYY )/SW**2
1052 :
1053 : ! where SWCXX and SWXX are second partials with respect
1054 : ! to x, SWCXY and SWXY are mixed partials, and SWCYY and
1055 : ! SWYY are second partials with respect to y.
1056 :
1057 : SW = 0.
1058 : SWX = 0.
1059 : SWY = 0.
1060 : SWXX = 0.
1061 : SWXY = 0.
1062 : SWYY = 0.
1063 : SWC = 0.
1064 : SWCX = 0.
1065 : SWCY = 0.
1066 : SWCXX = 0.
1067 : SWCXY = 0.
1068 : SWCYY = 0.
1069 :
1070 : ! Outer loop on cells (I,J).
1071 :
1072 0 : do 4 J = JMIN,JMAX
1073 0 : do 3 I = IMIN,IMAX
1074 0 : K = LCELL(I,J)
1075 0 : if (K == 0) GOTO 3
1076 :
1077 : ! Inner loop on nodes K.
1078 :
1079 0 : 1 DELX = XP - X(K)
1080 0 : DELY = YP - Y(K)
1081 0 : DXSQ = DELX*DELX
1082 0 : DYSQ = DELY*DELY
1083 0 : D = SQRT(DXSQ + DYSQ)
1084 0 : R = RW(K)
1085 0 : if (D >= R) GOTO 2
1086 0 : if (D == 0.) GOTO 5
1087 0 : T1 = (1.0/D - 1.0/R)
1088 0 : W = T1*T1*T1
1089 0 : T2 = -3.0*T1*T1/(D*D*D)
1090 0 : WX = DELX*T2
1091 0 : WY = DELY*T2
1092 0 : D6 = D*D*D*D*D*D
1093 0 : T1 = 3.0*T1*(2.0+3.0*D*T1)/D6
1094 0 : WXX = T1*DXSQ + T2
1095 0 : WXY = T1*DELX*DELY
1096 0 : WYY = T1*DYSQ + T2
1097 0 : T1 = A(1,K)*DELX + A(2,K)*DELY + A(5,K)
1098 0 : T2 = T1 + T1 + A(1,K)*DELX
1099 0 : T3 = A(4,K)*DELY + A(3,K)*DELX + A(7,K)
1100 0 : T4 = T3 + T3 + A(4,K)*DELY
1101 : CK = (T1*DELX + A(6,K)*DELY + A(8,K))*DELX +
1102 0 : & (T3*DELY + A(9,K))*DELY + F(K)
1103 0 : CKX = T2*DELX + (A(3,K)*DELY+A(6,K))*DELY + A(8,K)
1104 0 : CKY = T4*DELY + (A(2,K)*DELX+A(6,K))*DELX + A(9,K)
1105 0 : CKXX = T2 + 3.0*A(1,K)*DELX
1106 0 : CKXY = 2.0*(A(2,K)*DELX + A(3,K)*DELY) + A(6,K)
1107 0 : CKYY = T4 + 3.0*A(4,K)*DELY
1108 0 : SW = SW + W
1109 0 : SWX = SWX + WX
1110 0 : SWY = SWY + WY
1111 0 : SWXX = SWXX + WXX
1112 0 : SWXY = SWXY + WXY
1113 0 : SWYY = SWYY + WYY
1114 0 : SWC = SWC + W*CK
1115 0 : SWCX = SWCX + WX*CK + W*CKX
1116 0 : SWCY = SWCY + WY*CK + W*CKY
1117 0 : SWCXX = SWCXX + W*CKXX + 2.0*WX*CKX + CK*WXX
1118 0 : SWCXY = SWCXY + W*CKXY + WX*CKY + WY*CKX + CK*WXY
1119 0 : SWCYY = SWCYY + W*CKYY + 2.0*WY*CKY + CK*WYY
1120 :
1121 : ! Bottom of loop on nodes in cell (I,J).
1122 :
1123 0 : 2 KP = K
1124 0 : K = LNEXT(KP)
1125 0 : if (K /= KP) GOTO 1
1126 0 : 3 continue
1127 0 : 4 continue
1128 :
1129 : ! SW = 0 iff P is not within the radius R(K) for any node K.
1130 :
1131 0 : if (SW == 0.) GOTO 7
1132 0 : C = SWC/SW
1133 0 : SWS = SW*SW
1134 0 : CX = (SWCX*SW - SWC*SWX)/SWS
1135 0 : CY = (SWCY*SW - SWC*SWY)/SWS
1136 0 : CXX = (SW*(SWCXX-2.0*SWX*CX) - SWC*SWXX)/SWS
1137 0 : CXY = (SW*(SWCXY-SWY*CX-SWX*CY) - SWC*SWXY)/SWS
1138 0 : CYY = (SW*(SWCYY-2.0*SWY*CY) - SWC*SWYY)/SWS
1139 0 : IER = 0
1140 0 : return
1141 :
1142 : ! (PX,PY) = (X(K),Y(K)).
1143 :
1144 0 : 5 C = F(K)
1145 0 : CX = A(8,K)
1146 0 : CY = A(9,K)
1147 0 : CXX = 2.0*A(5,K)
1148 0 : CXY = A(6,K)
1149 0 : CYY = 2.0*A(7,K)
1150 0 : IER = 0
1151 0 : return
1152 :
1153 : ! Invalid input parameter.
1154 :
1155 0 : 6 IER = 1
1156 0 : return
1157 :
1158 : ! No cells contain a point within RMAX of P, or
1159 : ! SW = 0 and thus D >= RW(K) for all K.
1160 :
1161 0 : 7 C = 0.
1162 0 : CX = 0.
1163 0 : CY = 0.
1164 0 : CXX = 0.
1165 0 : CXY = 0.
1166 0 : CYY = 0.
1167 0 : IER = 2
1168 0 : return
1169 : end subroutine CS2HES_sg
1170 0 : subroutine GETNP2_sg (PX,PY,X,Y,NR,LCELL,LNEXT,XMIN,YMIN,
1171 : & DX,DY, NP,DSQ)
1172 : integer :: NR, LCELL(NR,NR), LNEXT(*), NP
1173 : real :: PX, PY, X(*), Y(*), XMIN, YMIN, DX, DY, DSQ
1174 :
1175 : ! **********************************************************
1176 :
1177 : ! From CSHEP2D
1178 : ! Robert J. Renka
1179 : ! Dept. of Computer Science
1180 : ! Univ. of North Texas
1181 : ! renka@cs.unt.edu
1182 : ! 02/03/97
1183 :
1184 : ! Given a set of N nodes and the data structure defined in
1185 : ! Subroutine STORE2_sg, this subroutine uses the cell method to
1186 : ! find the closest unmarked node NP to a specified point P.
1187 : ! NP is then marked by setting LNEXT(NP) to -LNEXT(NP). (A
1188 : ! node is marked if and only if the corresponding LNEXT element
1189 : ! is negative. The absolute values of LNEXT elements,
1190 : ! however, must be preserved.) Thus, the closest M nodes to
1191 : ! P may be determined by a sequence of M calls to this rou-
1192 : ! tine. Note that if the nearest neighbor to node K is to
1193 : ! be determined (PX = X(K) and PY = Y(K)), then K should be
1194 : ! marked before the call to this routine.
1195 :
1196 : ! The search is begun in the cell containing (or closest
1197 : ! to) P and proceeds outward in rectangular layers until all
1198 : ! cells which contain points within distance R of P have
1199 : ! been searched, where R is the distance from P to the first
1200 : ! unmarked node encountered (infinite if no unmarked nodes
1201 : ! are present).
1202 :
1203 : ! This code is essentially unaltered from the subroutine
1204 : ! of the same name in QSHEP2D.
1205 :
1206 : ! On input:
1207 :
1208 : ! PX,PY = Cartesian coordinates of the point P whose
1209 : ! nearest unmarked neighbor is to be found.
1210 :
1211 : ! X,Y = Arrays of length N, for N >= 2, containing
1212 : ! the Cartesian coordinates of the nodes.
1213 :
1214 : ! NR = Number of rows and columns in the cell grid.
1215 : ! Refer to Subroutine STORE2_sg. NR >= 1.
1216 :
1217 : ! LCELL = NR by NR array of nodal indexes associated
1218 : ! with cells. Refer to Subroutine STORE2_sg.
1219 :
1220 : ! LNEXT = Array of length N containing next-node
1221 : ! indexes (or their negatives). Refer to
1222 : ! Subroutine STORE2_sg.
1223 :
1224 : ! XMIN,YMIN,DX,DY = Minimum nodal coordinates and cell
1225 : ! dimensions. DX and DY must be
1226 : ! positive. Refer to Subroutine
1227 : ! STORE2_sg.
1228 :
1229 : ! Input parameters other than LNEXT are not altered by
1230 : ! this routine. With the exception of (PX,PY) and the signs
1231 : ! of LNEXT elements, these parameters should be unaltered
1232 : ! from their values on output from Subroutine STORE2_sg.
1233 :
1234 : ! On output:
1235 :
1236 : ! NP = Index (for X and Y) of the nearest unmarked
1237 : ! node to P, or 0 if all nodes are marked or NR
1238 : ! < 1 or DX <= 0 or DY <= 0. LNEXT(NP)
1239 : ! < 0 if NP /= 0.
1240 :
1241 : ! DSQ = Squared Euclidean distance between P and node
1242 : ! NP, or 0 if NP = 0.
1243 :
1244 : ! Modules required by GETNP2_sg: None
1245 :
1246 : ! Intrinsic functions called by GETNP2_sg: ABS, INT, SQRT
1247 :
1248 : ! **********************************************************
1249 :
1250 : integer :: I, I0, I1, I2, IMAX, IMIN, J, J0, J1, J2,
1251 : & JMAX, JMIN, L, LMIN, LN
1252 : LOGICAL :: FIRST
1253 0 : real :: DELX, DELY, R, RSMIN, RSQ, XP, YP
1254 :
1255 : ! Local parameters:
1256 :
1257 : ! DELX,DELY = PX-XMIN, PY-YMIN
1258 : ! FIRST = Logical variable with value TRUE iff the
1259 : ! first unmarked node has yet to be
1260 : ! encountered
1261 : ! I,J = Cell indexes in the range [I1,I2] X [J1,J2]
1262 : ! I0,J0 = Indexes of the cell containing or closest
1263 : ! to P
1264 : ! I1,I2,J1,J2 = Range of cell indexes defining the layer
1265 : ! whose intersection with the range
1266 : ! [IMIN,IMAX] X [JMIN,JMAX] is currently
1267 : ! being searched
1268 : ! IMIN,IMAX = Cell row indexes defining the range of the
1269 : ! search
1270 : ! JMIN,JMAX = Cell column indexes defining the range of
1271 : ! the search
1272 : ! L,LN = Indexes of nodes in cell (I,J)
1273 : ! LMIN = Current candidate for NP
1274 : ! R = Distance from P to node LMIN
1275 : ! RSMIN = Squared distance from P to node LMIN
1276 : ! RSQ = Squared distance from P to node L
1277 : ! XP,YP = Local copy of PX,PY -- coordinates of P
1278 :
1279 0 : XP = PX
1280 0 : YP = PY
1281 :
1282 : ! Test for invalid input parameters.
1283 :
1284 0 : if (NR < 1 .or. DX <= 0. .or. DY <= 0.) GOTO 9
1285 :
1286 : ! Initialize parameters.
1287 :
1288 0 : FIRST = .true.
1289 0 : IMIN = 1
1290 0 : IMAX = NR
1291 0 : JMIN = 1
1292 0 : JMAX = NR
1293 0 : DELX = XP - XMIN
1294 0 : DELY = YP - YMIN
1295 0 : I0 = INT(DELX/DX) + 1
1296 0 : if (I0 < 1) I0 = 1
1297 0 : if (I0 > NR) I0 = NR
1298 0 : J0 = INT(DELY/DY) + 1
1299 0 : if (J0 < 1) J0 = 1
1300 0 : if (J0 > NR) J0 = NR
1301 0 : I1 = I0
1302 0 : I2 = I0
1303 0 : J1 = J0
1304 0 : J2 = J0
1305 :
1306 : ! Outer loop on layers, inner loop on layer cells, excluding
1307 : ! those outside the range [IMIN,IMAX] X [JMIN,JMAX].
1308 :
1309 0 : 1 do 6 J = J1,J2
1310 0 : if (J > JMAX) GOTO 7
1311 0 : if (J < JMIN) GOTO 6
1312 0 : do 5 I = I1,I2
1313 0 : if (I > IMAX) GOTO 6
1314 0 : if (I < IMIN) GOTO 5
1315 : if (J /= J1 .and. J /= J2 .and. I /= I1
1316 0 : & .and. I /= I2) GOTO 5
1317 :
1318 : ! Search cell (I,J) for unmarked nodes L.
1319 :
1320 0 : L = LCELL(I,J)
1321 0 : if (L == 0) GOTO 5
1322 :
1323 : ! Loop on nodes in cell (I,J).
1324 :
1325 0 : 2 LN = LNEXT(L)
1326 0 : if (LN < 0) GOTO 4
1327 :
1328 : ! Node L is not marked.
1329 :
1330 0 : RSQ = (X(L)-XP)**2 + (Y(L)-YP)**2
1331 0 : if (.not. FIRST) GOTO 3
1332 :
1333 : ! Node L is the first unmarked neighbor of P encountered.
1334 : ! Initialize LMIN to the current candidate for NP, and
1335 : ! RSMIN to the squared distance from P to LMIN. IMIN,
1336 : ! IMAX, JMIN, and JMAX are updated to define the smal-
1337 : ! lest rectangle containing a circle of radius R =
1338 : ! Sqrt(RSMIN) centered at P, and contained in [1,NR] X
1339 : ! [1,NR] (except that, if P is outside the rectangle
1340 : ! defined by the nodes, it is possible that IMIN > NR,
1341 : ! IMAX < 1, JMIN > NR, or JMAX < 1). FIRST is reset to
1342 : ! FALSE.
1343 :
1344 0 : LMIN = L
1345 0 : RSMIN = RSQ
1346 0 : R = SQRT(RSMIN)
1347 0 : IMIN = INT((DELX-R)/DX) + 1
1348 0 : if (IMIN < 1) IMIN = 1
1349 0 : IMAX = INT((DELX+R)/DX) + 1
1350 0 : if (IMAX > NR) IMAX = NR
1351 0 : JMIN = INT((DELY-R)/DY) + 1
1352 0 : if (JMIN < 1) JMIN = 1
1353 0 : JMAX = INT((DELY+R)/DY) + 1
1354 0 : if (JMAX > NR) JMAX = NR
1355 : FIRST = .false.
1356 0 : GOTO 4
1357 :
1358 : ! Test for node L closer than LMIN to P.
1359 :
1360 0 : 3 if (RSQ >= RSMIN) GOTO 4
1361 :
1362 : ! Update LMIN and RSMIN.
1363 :
1364 0 : LMIN = L
1365 0 : RSMIN = RSQ
1366 :
1367 : ! Test for termination of loop on nodes in cell (I,J).
1368 :
1369 0 : 4 if (ABS(LN) == L) GOTO 5
1370 : L = ABS(LN)
1371 0 : GOTO 2
1372 0 : 5 continue
1373 0 : 6 continue
1374 :
1375 : ! Test for termination of loop on cell layers.
1376 :
1377 : 7 if (I1 <= IMIN .and. I2 >= IMAX .and.
1378 0 : & J1 <= JMIN .and. J2 >= JMAX) GOTO 8
1379 0 : I1 = I1 - 1
1380 0 : I2 = I2 + 1
1381 0 : J1 = J1 - 1
1382 0 : J2 = J2 + 1
1383 0 : GOTO 1
1384 :
1385 : ! Unless no unmarked nodes were encountered, LMIN is the
1386 : ! closest unmarked node to P.
1387 :
1388 0 : 8 if (FIRST) GOTO 9
1389 0 : NP = LMIN
1390 0 : DSQ = RSMIN
1391 0 : LNEXT(LMIN) = -LNEXT(LMIN)
1392 0 : return
1393 :
1394 : ! Error: NR, DX, or DY is invalid or all nodes are marked.
1395 :
1396 0 : 9 NP = 0
1397 0 : DSQ = 0.
1398 0 : return
1399 : end subroutine GETNP2_sg
1400 :
1401 0 : subroutine GIVENS_sg (A,B, C,S)
1402 : real :: A, B, C, S
1403 :
1404 : ! **********************************************************
1405 :
1406 : ! From SRFPACK
1407 : ! Robert J. Renka
1408 : ! Dept. of Computer Science
1409 : ! Univ. of North Texas
1410 : ! renka@cs.unt.edu
1411 : ! 09/01/88
1412 :
1413 : ! This subroutine constructs the Givens plane rotation,
1414 :
1415 : ! ( C S)
1416 : ! G = ( ) , where C*C + S*S = 1,
1417 : ! (-S C)
1418 :
1419 : ! which zeros the second component of the vector (A,B)**T
1420 : ! (transposed). Subroutine ROTATE_sg may be called to apply
1421 : ! the transformation to a 2 by N matrix.
1422 :
1423 : ! This routine is identical to subroutine SROTG from the
1424 : ! LINPACK BLAS (Basic Linear Algebra Subroutines).
1425 :
1426 : ! On input:
1427 :
1428 : ! A,B = Components of the vector defining the rota-
1429 : ! tion. These are overwritten by values R
1430 : ! and Z (described below) which define C and S.
1431 :
1432 : ! On output:
1433 :
1434 : ! A = Signed Euclidean norm R of the input vector:
1435 : ! R = +/-SQRT(A*A + B*B)
1436 :
1437 : ! B = Value Z such that:
1438 : ! C = SQRT(1-Z*Z) and S=Z if ABS(Z) <= 1, and
1439 : ! C = 1/Z and S = SQRT(1-C*C) if ABS(Z) > 1.
1440 :
1441 : ! C = +/-(A/R) or 1 if R = 0.
1442 :
1443 : ! S = +/-(B/R) or 0 if R = 0.
1444 :
1445 : ! Modules required by GIVENS_sg: None
1446 :
1447 : ! Intrinsic functions called by GIVENS_sg: ABS, SQRT
1448 :
1449 : ! **********************************************************
1450 :
1451 0 : real :: AA, BB, R, U, V
1452 :
1453 : ! Local parameters:
1454 :
1455 : ! AA,BB = Local copies of A and B
1456 : ! R = C*A + S*B = +/-SQRT(A*A+B*B)
1457 : ! U,V = Variables used to scale A and B for computing R
1458 :
1459 0 : AA = A
1460 0 : BB = B
1461 0 : if (ABS(AA) <= ABS(BB)) GOTO 1
1462 :
1463 : ! ABS(A) > ABS(B).
1464 :
1465 0 : U = AA + AA
1466 0 : V = BB/U
1467 0 : R = SQRT(.25 + V*V) * U
1468 0 : C = AA/R
1469 0 : S = V * (C + C)
1470 :
1471 : ! Note that R has the sign of A, C > 0, and S has
1472 : ! SIGN(A)*SIGN(B).
1473 :
1474 0 : B = S
1475 0 : A = R
1476 0 : return
1477 :
1478 : ! ABS(A) <= ABS(B).
1479 :
1480 0 : 1 if (BB == 0.) GOTO 2
1481 0 : U = BB + BB
1482 0 : V = AA/U
1483 :
1484 : ! Store R in A.
1485 :
1486 0 : A = SQRT(.25 + V*V) * U
1487 0 : S = BB/A
1488 0 : C = V * (S + S)
1489 :
1490 : ! Note that R has the sign of B, S > 0, and C has
1491 : ! SIGN(A)*SIGN(B).
1492 :
1493 0 : B = 1.
1494 0 : if (C /= 0.) B = 1./C
1495 0 : return
1496 :
1497 : ! A = B = 0.
1498 :
1499 0 : 2 C = 1.
1500 0 : S = 0.
1501 0 : return
1502 : end subroutine GIVENS_sg
1503 :
1504 0 : subroutine ROTATE_sg (N,C,S, X,Y )
1505 : integer :: N
1506 : real :: C, S, X(N), Y(N)
1507 :
1508 : ! **********************************************************
1509 :
1510 : ! From SRFPACK
1511 : ! Robert J. Renka
1512 : ! Dept. of Computer Science
1513 : ! Univ. of North Texas
1514 : ! renka@cs.unt.edu
1515 : ! 09/01/88
1516 :
1517 : ! ( C S)
1518 : ! This subroutine applies the Givens rotation ( ) to
1519 : ! (-S C)
1520 : ! (X(1) ... X(N))
1521 : ! the 2 by N matrix ( ) .
1522 : ! (Y(1) ... Y(N))
1523 :
1524 : ! This routine is identical to subroutine SROT from the
1525 : ! LINPACK BLAS (Basic Linear Algebra Subroutines).
1526 :
1527 : ! On input:
1528 :
1529 : ! N = Number of columns to be rotated.
1530 :
1531 : ! C,S = Elements of the Givens rotation. Refer to
1532 : ! subroutine GIVENS_sg.
1533 :
1534 : ! The above parameters are not altered by this routine.
1535 :
1536 : ! X,Y = Arrays of length >= N containing the compo-
1537 : ! nents of the vectors to be rotated.
1538 :
1539 : ! On output:
1540 :
1541 : ! X,Y = Arrays containing the rotated vectors (not
1542 : ! altered if N < 1).
1543 :
1544 : ! Modules required by ROTATE_sg: None
1545 :
1546 : ! **********************************************************
1547 :
1548 : integer :: I
1549 0 : real :: XI, YI
1550 :
1551 0 : do I = 1,N
1552 0 : XI = X(I)
1553 0 : YI = Y(I)
1554 0 : X(I) = C*XI + S*YI
1555 0 : Y(I) = -S*XI + C*YI
1556 : end do
1557 0 : return
1558 : end subroutine ROTATE_sg
1559 0 : subroutine SETUP2_sg (XK,YK,ZK,XI,YI,ZI,S1,S2,S3,R, ROW)
1560 : real :: XK, YK, ZK, XI, YI, ZI, S1, S2, S3,
1561 : & R, ROW(10)
1562 :
1563 : ! **********************************************************
1564 :
1565 : ! From CSHEP2D
1566 : ! Robert J. Renka
1567 : ! Dept. of Computer Science
1568 : ! Univ. of North Texas
1569 : ! renka@cs.unt.edu
1570 : ! 02/03/97
1571 :
1572 : ! This subroutine sets up the I-th row of an augmented re-
1573 : ! gression matrix for a weighted least squares fit of a
1574 : ! cubic function f(x,y) to a set of data values z, where
1575 : ! f(XK,YK) = ZK. The first four columns (cubic terms) are
1576 : ! scaled by S3, the next three columns (quadratic terms)
1577 : ! are scaled by S2, and the eighth and ninth columns (lin-
1578 : ! ear terms) are scaled by S1.
1579 :
1580 : ! On input:
1581 :
1582 : ! XK,YK = Coordinates of node K.
1583 :
1584 : ! ZK = Data value at node K to be interpolated by f.
1585 :
1586 : ! XI,YI,ZI = Coordinates and data value at node I.
1587 :
1588 : ! S1,S2,S3 = Scale factors.
1589 :
1590 : ! R = Radius of influence about node K defining the
1591 : ! weight.
1592 :
1593 : ! The above parameters are not altered by this routine.
1594 :
1595 : ! ROW = Array of length 10.
1596 :
1597 : ! On output:
1598 :
1599 : ! ROW = Array containing a row of the augmented re-
1600 : ! gression matrix.
1601 :
1602 : ! Modules required by SETUP2_sg: None
1603 :
1604 : ! Intrinsic function called by SETUP2_sg: SQRT
1605 :
1606 : ! **********************************************************
1607 :
1608 : integer :: I
1609 0 : real :: D, DX, DXSQ, DY, DYSQ, W, W1, W2, W3
1610 :
1611 : ! Local parameters:
1612 :
1613 : ! D = Distance between nodes K and I
1614 : ! DX = XI - XK
1615 : ! DXSQ = DX*DX
1616 : ! DY = YI - YK
1617 : ! DYSQ = DY*DY
1618 : ! I = DO-loop index
1619 : ! W = Weight associated with the row: (R-D)/(R*D)
1620 : ! (0 if D = 0 or D > R)
1621 : ! W1 = S1*W
1622 : ! W2 = S2*W
1623 : ! W3 = W3*W
1624 :
1625 0 : DX = XI - XK
1626 0 : DY = YI - YK
1627 0 : DXSQ = DX*DX
1628 0 : DYSQ = DY*DY
1629 0 : D = SQRT(DXSQ + DYSQ)
1630 0 : if (D <= 0. .or. D >= R) GOTO 1
1631 0 : W = (R-D)/R/D
1632 0 : W1 = S1*W
1633 0 : W2 = S2*W
1634 0 : W3 = S3*W
1635 0 : ROW(1) = DXSQ*DX*W3
1636 0 : ROW(2) = DXSQ*DY*W3
1637 0 : ROW(3) = DX*DYSQ*W3
1638 0 : ROW(4) = DYSQ*DY*W3
1639 0 : ROW(5) = DXSQ*W2
1640 0 : ROW(6) = DX*DY*W2
1641 0 : ROW(7) = DYSQ*W2
1642 0 : ROW(8) = DX*W1
1643 0 : ROW(9) = DY*W1
1644 0 : ROW(10) = (ZI - ZK)*W
1645 0 : return
1646 :
1647 : ! Nodes K and I coincide or node I is outside of the radius
1648 : ! of influence. Set ROW to the zero vector.
1649 :
1650 0 : 1 do I = 1,10
1651 0 : ROW(I) = 0.
1652 : end do
1653 : return
1654 : end subroutine SETUP2_sg
1655 :
1656 0 : subroutine STORE2_sg (N,X,Y,NR, LCELL,LNEXT,XMIN,YMIN,DX,
1657 : & DY,IER)
1658 : integer :: N, NR, LCELL(NR,NR), LNEXT(N), IER
1659 : real :: X(N), Y(N), XMIN, YMIN, DX, DY
1660 :
1661 : ! **********************************************************
1662 :
1663 : ! From CSHEP2D
1664 : ! Robert J. Renka
1665 : ! Dept. of Computer Science
1666 : ! Univ. of North Texas
1667 : ! renka@cs.unt.edu
1668 : ! 03/28/97
1669 :
1670 : ! Given a set of N arbitrarily distributed nodes in the
1671 : ! plane, this subroutine creates a data structure for a
1672 : ! cell-based method of solving closest-point problems. The
1673 : ! smallest rectangle containing the nodes is partitioned
1674 : ! into an NR by NR uniform grid of cells, and nodes are as-
1675 : ! sociated with cells. In particular, the data structure
1676 : ! stores the indexes of the nodes contained in each cell.
1677 : ! For a uniform random distribution of nodes, the nearest
1678 : ! node to an arbitrary point can be determined in constant
1679 : ! expected time.
1680 :
1681 : ! This code is essentially unaltered from the subroutine
1682 : ! of the same name in QSHEP2D.
1683 :
1684 : ! On input:
1685 :
1686 : ! N = Number of nodes. N >= 2.
1687 :
1688 : ! X,Y = Arrays of length N containing the Cartesian
1689 : ! coordinates of the nodes.
1690 :
1691 : ! NR = Number of rows and columns in the grid. The
1692 : ! cell density (average number of nodes per cell)
1693 : ! is D = N/(NR**2). A recommended value, based
1694 : ! on empirical evidence, is D = 3 -- NR =
1695 : ! Sqrt(N/3). NR >= 1.
1696 :
1697 : ! The above parameters are not altered by this routine.
1698 :
1699 : ! LCELL = Array of length >= NR**2.
1700 :
1701 : ! LNEXT = Array of length >= N.
1702 :
1703 : ! On output:
1704 :
1705 : ! LCELL = NR by NR cell array such that LCELL(I,J)
1706 : ! contains the index (for X and Y) of the
1707 : ! first node (node with smallest index) in
1708 : ! cell (I,J), or LCELL(I,J) = 0 if no nodes
1709 : ! are contained in the cell. The upper right
1710 : ! corner of cell (I,J) has coordinates (XMIN+
1711 : ! I*DX,YMIN+J*DY). LCELL is not defined if
1712 : ! IER /= 0.
1713 :
1714 : ! LNEXT = Array of next-node indexes such that
1715 : ! LNEXT(K) contains the index of the next node
1716 : ! in the cell which contains node K, or
1717 : ! LNEXT(K) = K if K is the last node in the
1718 : ! cell for K = 1,...,N. (The nodes contained
1719 : ! in a cell are ordered by their indexes.)
1720 : ! If, for example, cell (I,J) contains nodes
1721 : ! 2, 3, and 5 (and no others), then LCELL(I,J)
1722 : ! = 2, LNEXT(2) = 3, LNEXT(3) = 5, and
1723 : ! LNEXT(5) = 5. LNEXT is not defined if
1724 : ! IER /= 0.
1725 :
1726 : ! XMIN,YMIN = Cartesian coordinates of the lower left
1727 : ! corner of the rectangle defined by the
1728 : ! nodes (smallest nodal coordinates) un-
1729 : ! less IER = 1. The upper right corner is
1730 : ! (XMAX,YMAX) for XMAX = XMIN + NR*DX and
1731 : ! YMAX = YMIN + NR*DY.
1732 :
1733 : ! DX,DY = Dimensions of the cells unless IER = 1. DX
1734 : ! = (XMAX-XMIN)/NR and DY = (YMAX-YMIN)/NR,
1735 : ! where XMIN, XMAX, YMIN, and YMAX are the
1736 : ! extrema of X and Y.
1737 :
1738 : ! IER = Error indicator:
1739 : ! IER = 0 if no errors were encountered.
1740 : ! IER = 1 if N < 2 or NR < 1.
1741 : ! IER = 2 if DX = 0 or DY = 0.
1742 :
1743 : ! Modules required by STORE2_sg: None
1744 :
1745 : ! Intrinsic functions called by STORE2_sg: DBLE, INT
1746 :
1747 : ! **********************************************************
1748 :
1749 : integer :: I, J, K, L, NN, NNR
1750 0 : real :: DELX, DELY, XMN, XMX, YMN, YMX
1751 :
1752 : ! Local parameters:
1753 :
1754 : ! DELX,DELY = Components of the cell dimensions -- local
1755 : ! copies of DX,DY
1756 : ! I,J = Cell indexes
1757 : ! K = Nodal index
1758 : ! L = Index of a node in cell (I,J)
1759 : ! NN = Local copy of N
1760 : ! NNR = Local copy of NR
1761 : ! XMN,XMX = Range of nodal X coordinates
1762 : ! YMN,YMX = Range of nodal Y coordinates
1763 :
1764 0 : NN = N
1765 0 : NNR = NR
1766 0 : if (NN < 2 .or. NNR < 1) GOTO 5
1767 :
1768 : ! Compute the dimensions of the rectangle containing the
1769 : ! nodes.
1770 :
1771 0 : XMN = X(1)
1772 0 : XMX = XMN
1773 0 : YMN = Y(1)
1774 0 : YMX = YMN
1775 0 : do K = 2,NN
1776 0 : if (X(K) < XMN) XMN = X(K)
1777 0 : if (X(K) > XMX) XMX = X(K)
1778 0 : if (Y(K) < YMN) YMN = Y(K)
1779 0 : if (Y(K) > YMX) YMX = Y(K)
1780 : end do
1781 0 : XMIN = XMN
1782 0 : YMIN = YMN
1783 :
1784 : ! Compute cell dimensions and test for zero area.
1785 :
1786 0 : DELX = (XMX-XMN)/DBLE(NNR)
1787 0 : DELY = (YMX-YMN)/DBLE(NNR)
1788 0 : DX = DELX
1789 0 : DY = DELY
1790 0 : if (DELX == 0. .or. DELY == 0.) GOTO 6
1791 :
1792 : ! Initialize LCELL.
1793 :
1794 0 : do J = 1,NNR
1795 0 : do I = 1,NNR
1796 0 : LCELL(I,J) = 0
1797 : end do
1798 : end do
1799 :
1800 : ! Loop on nodes, storing indexes in LCELL and LNEXT.
1801 :
1802 0 : do K = NN,1,-1
1803 0 : I = INT((X(K)-XMN)/DELX) + 1
1804 0 : if (I > NNR) I = NNR
1805 0 : J = INT((Y(K)-YMN)/DELY) + 1
1806 0 : if (J > NNR) J = NNR
1807 0 : L = LCELL(I,J)
1808 0 : LNEXT(K) = L
1809 0 : if (L == 0) LNEXT(K) = K
1810 0 : LCELL(I,J) = K
1811 : end do
1812 :
1813 : ! No errors encountered.
1814 :
1815 0 : IER = 0
1816 0 : return
1817 :
1818 : ! Invalid input parameter.
1819 :
1820 0 : 5 IER = 1
1821 0 : return
1822 :
1823 : ! DX = 0 or DY = 0.
1824 :
1825 0 : 6 IER = 2
1826 0 : return
1827 : end subroutine STORE2_sg
|