00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 subroutine psmile_neigh_cells_3d_reg_real ( &
00011 grid_valid_shape, interpolation_mode, &
00012 cyclic, grid_id, search, corners, &
00013 npoints, srclocs, ncpl, nbr_cells, &
00014 ierror )
00015
00016
00017
00018 use PRISM_constants
00019
00020 use PSMILe, dummy_interface => PSMILe_Neigh_cells_3d_reg_real
00021
00022 implicit none
00023
00024
00025
00026 Integer, Intent (In) :: grid_valid_shape (2, ndim_3d)
00027
00028
00029
00030 Integer, Intent (In) :: interpolation_mode
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 Logical, Intent (In) :: cyclic (ndim_3d)
00041
00042
00043
00044 Integer, Intent (In) :: grid_id
00045
00046
00047
00048 Type (Enddef_search), Intent (In) :: search
00049
00050
00051
00052 Type (real_vector), Intent (In) :: corners (ndim_3d, search%npart)
00053
00054
00055
00056 Integer, Intent (In) :: npoints (ndim_3d, search%npart)
00057
00058
00059
00060 Type (integer_vector), Intent (In) :: srclocs (ndim_3d, search%npart)
00061
00062
00063
00064 Integer, Intent (In) :: ncpl
00065
00066
00067
00068
00069
00070 Integer, Intent (Out) :: nbr_cells(ncpl)
00071
00072
00073
00074 Integer, Intent (Out) :: ierror
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 Integer, Parameter :: n_corners_3d = 2 * 2 * 2
00088 Integer, Parameter :: n_corners_2d = 2 * 2
00089 Integer, Parameter :: n_corners_1d = 2
00090
00091
00092
00093
00094
00095 Real :: ctr_corner, global(ndim_3d)
00096 Integer :: is
00097
00098 Type (Corner_Block), Pointer :: cp
00099
00100 Type (Dble_vector) :: chmin(ndim_3d), chmax(ndim_3d)
00101
00102 Type (Integer_vector) :: ic (ndim_3d, search%npart)
00103
00104 Integer :: nbr_cells_tot
00105 Integer :: ipart, jpart, jstart
00106 Integer :: i, j, k, n, nbeg, nend, nprev
00107 Integer :: lenij, lenk, lenijk, n_corners
00108 Integer :: ii, jj, kk, offset, icell
00109
00110
00111
00112 Integer :: length (ndim_3d)
00113 Integer :: lenc (ndim_3d)
00114
00115 Integer :: nlocs (ndim_3d)
00116 Integer :: nca (ndim_3d)
00117 Integer :: ndim
00118 Logical :: overlap
00119
00120
00121
00122 Integer, Parameter :: nerrp = 1
00123 Integer :: ierrp (nerrp)
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 Character(len=len_cvs_string), save :: mycvs =
00156 '$Id: psmile_neigh_cells_3d_reg_real.F90 2082 2009-10-21 13:31:19Z hanke $'
00157
00158
00159
00160 data nca /n_corners_1d, n_corners_2d, n_corners_3d/
00161 data global /360.0d0, 360.0d0, 1.0d35/
00162
00163
00164
00165 #ifdef VERBOSE
00166 print 9990, trim(ch_id)
00167
00168 call psmile_flushstd
00169 #endif /* VERBOSE */
00170
00171
00172
00173 ierror = 0
00174
00175 cp => Grids(grid_id)%corner_pointer
00176
00177 nprev = 0
00178
00179 n_corners = nca (interpolation_mode)
00180
00181 length (1:ndim_3d) = grid_valid_shape(2,1:ndim_3d) - &
00182 grid_valid_shape(1,1:ndim_3d) + 1
00183
00184 lenc (1:ndim_3d) = cp%corner_shape(2,1:ndim_3d) - &
00185 cp%corner_shape(1,1:ndim_3d) + 1
00186
00187
00188
00189 if (interpolation_mode < ndim_2d .or. interpolation_mode > ndim_3d) then
00190 ierrp (1) = interpolation_mode
00191 ierror = PRISM_Error_Internal
00192
00193 call psmile_error ( ierror, 'unsupported interpolation mode', &
00194 ierrp, 1, __FILE__, __LINE__ )
00195 return
00196 endif
00197
00198
00199
00200
00201 ndim = interpolation_mode
00202
00203
00204
00205
00206 do i = 1, ndim
00207 Allocate( chmin(i)%vector(length(i)), chmax(i)%vector(length(i)), STAT=ierror )
00208 if (ierror /= 0) then
00209 ierrp (1) = 2 * length(i)
00210 ierror = PRISM_Error_Alloc
00211 call psmile_error ( ierror, 'chmin, chmax', &
00212 ierrp, 1, __FILE__, __LINE__ )
00213 return
00214 endif
00215 enddo
00216
00217 do i = 1, ndim
00218 jstart = Grids(grid_id)%grid_shape(1,i) - cp%corner_shape(1,i)
00219 do jpart = 1, length(i), 256
00220
00221 do j = jpart, min(length(i),jpart+256-1)
00222 chmin(i)%vector(j) = min(cp%corners_real(i)%vector(jstart+j), &
00223 cp%corners_real(i)%vector(jstart+lenc(i)+j))
00224 chmax(i)%vector(j) = max(cp%corners_real(i)%vector(jstart+j), &
00225 cp%corners_real(i)%vector(jstart+lenc(i)+j))
00226 enddo
00227 enddo
00228 enddo
00229
00230 do ipart = 1, search%npart
00231 do i = 1, ndim
00232 Allocate( ic(i,ipart)%vector(npoints(i,ipart)-1), STAT=ierror )
00233 if (ierror /= 0) then
00234 ierrp (1) = npoints(i,ipart)
00235 ierror = PRISM_Error_Alloc
00236 call psmile_error ( ierror, 'ic vector', &
00237 ierrp, 1, __FILE__, __LINE__ )
00238 return
00239 endif
00240 enddo
00241 enddo
00242
00243 do ipart = 1, search%npart
00244
00245 nlocs(1) = npoints(1,ipart) - 1
00246 nlocs(2) = npoints(2,ipart) - 1
00247 if ( ndim == ndim_3d ) then
00248 nlocs(3) = npoints(3,ipart) - 1
00249 else
00250 nlocs(3) = npoints(3,ipart)
00251 endif
00252
00253
00254
00255
00256 lenij = nlocs (1) * nlocs (2)
00257 lenijk = lenij * nlocs (3)
00258
00259 nbeg = nprev + 1
00260 nend = nprev + lenijk
00261
00262 #ifdef PRISM_ASSERTION
00263
00264
00265
00266 if (ncpl < nprev + lenijk ) then
00267 print *, trim(ch_id), " ncpl, nprev, nlocs ", ncpl, nprev, nlocs
00268 call psmile_assert (__FILE__, __LINE__, &
00269 'ncpl < nprev + lenijk ')
00270 endif
00271
00272
00273
00274
00275 do j = 1, ndim_3d
00276
00277 do i = 1, nlocs (j)
00278 if (srclocs(j,ipart)%vector(i) < grid_valid_shape(1,j) .or. &
00279 srclocs(j,ipart)%vector(i) > grid_valid_shape(2,j)) exit
00280 end do
00281
00282 if (i <= nlocs(j)) then
00283 print *, trim(ch_id),':','Incorrect index in j, i', &
00284 j, i, srclocs(j,ipart)%vector(i)
00285 call psmile_assert (__FILE__, __LINE__, &
00286 'wrong index')
00287 endif
00288
00289 enddo
00290 #endif
00291
00292
00293
00294 do i = 1, ndim
00295 do jpart = 1, nlocs(i), 256
00296
00297 do j = jpart, min(nlocs(i),jpart+256-1)
00298
00299 do n = srclocs(i,ipart)%vector(j) - grid_valid_shape(1,i) + 1, length(i)
00300
00301 if ( ( corners(i,ipart)%vector(j+1) - chmin(i)%vector(n) ) * &
00302 ( chmax(i)%vector(n) - corners(i,ipart)%vector(j) ) < 0 ) &
00303 exit
00304
00305 enddo
00306
00307
00308 ic(i,ipart)%vector(j) = n - srclocs(i,ipart)%vector(j) + grid_valid_shape(1,i) - 1
00309
00310
00311
00312 is = srclocs(i,ipart)%vector(j) - grid_valid_shape(1,i) + 1
00313
00314 if ( corners(i,ipart)%vector(j) < chmin(i)%vector(is) .and. cyclic(i) ) then
00315 #ifdef DEBUG
00316 print *, trim(ch_id),':',' search cell minimum ', corners(i,ipart)%vector(j)
00317 print *, trim(ch_id),':',' is outside of local cell ', chmin(i)%vector(is)
00318 #endif
00319 n = minval(srclocs(i,ipart)%vector)
00320
00321 do ii = length(i), n-grid_valid_shape(1,i)+1, -1
00322 if ( corners(i,ipart)%vector(j) < chmax(i)%vector(ii)-global(i) ) exit
00323 enddo
00324
00325 ii = length(i) - ii + 1
00326
00327 ic(i,ipart)%vector(j) = ic(i,ipart)%vector(j) + ii
00328 #ifdef DEBUG
00329 print *, trim(ch_id),':',' ic vector increased from ', &
00330 ic(i,ipart)%vector(j) -ii, &
00331 ' to ', ic(i,ipart)%vector(j)
00332 #endif
00333 endif
00334
00335 #ifdef DEBUG
00336 if ( ic(i,ipart)%vector(j) == 0 ) then
00337 n = srclocs(i,ipart)%vector(j) - grid_valid_shape(1,i) + 1
00338 print *, trim(ch_id),':',' Problem at ', chmin(i)%vector(n), &
00339 chmax(i)%vector(n)
00340 print *, trim(ch_id),':',' for element ', corners(i,ipart)%vector(j), &
00341 corners(i,ipart)%vector(j+1)
00342 print *, trim(ch_id),':',' for with index ', i, ipart, j
00343 endif
00344 #endif
00345
00346 enddo
00347 enddo
00348 enddo
00349
00350 if ( ndim == ndim_2d ) then
00351
00352 do j = 1, nlocs (2)
00353 do i = 1, nlocs (1)
00354 nbr_cells(nprev+(j-1)*nlocs(1)+i) = ic(1,ipart)%vector(i) &
00355 * ic(2,ipart)%vector(j)
00356 enddo
00357 enddo
00358
00359 do k = 2, nlocs (3)
00360 nbr_cells (nprev+(k-1)*lenij+1:nprev+k*lenij) = nbr_cells(nprev+1:nprev+lenij)
00361 end do
00362
00363 else
00364
00365 do k = 1, nlocs (3)
00366 do j = 1, nlocs (2)
00367 do i = 1, nlocs (1)
00368 nbr_cells(nprev+(k-1)*lenij+(j-1)*nlocs(1)+i) = &
00369 ic(1,ipart)%vector(i) &
00370 * ic(2,ipart)%vector(j) &
00371 * ic(3,ipart)%vector(k)
00372 enddo
00373 enddo
00374 enddo
00375
00376 endif
00377
00378
00379
00380 nprev = nend
00381
00382 enddo
00383
00384
00385
00386
00387
00388 if ( ndim == ndim_2d ) then
00389 lenij = 0
00390 do ipart = 1, search%npart
00391 do j = 1, npoints(2,ipart)-1
00392 do i = 1, npoints(1,ipart)-1
00393 lenij = lenij + ic(1,ipart)%vector(i)*ic(2,ipart)%vector(j)
00394 enddo
00395 enddo
00396 enddo
00397 lenk = npoints(3,1)
00398 #ifdef PRISM_ASSERTION
00399 if ( sum(npoints(3,:))/search%npart /= lenk ) then
00400 print *, trim(ch_id), lenk, npoints(3,:)
00401 call psmile_assert (__FILE__, __LINE__, &
00402 'npoints(3) should be the same for all parts')
00403 endif
00404 #endif
00405 nbr_cells_tot = lenij * lenk
00406 else
00407
00408 nbr_cells_tot = sum(nbr_cells)
00409
00410 endif
00411
00412 Allocate ( neighcells_3d(ndim_3d,nbr_cells_tot,n_corners), STAT=ierror)
00413
00414 if (ierror /= 0) then
00415 ierrp (1) = 3 * nbr_cells_tot * n_corners
00416 ierror = PRISM_Error_Alloc
00417 call psmile_error ( ierror, 'neighcells_3d', &
00418 ierrp, 1, __FILE__, __LINE__ )
00419 return
00420 endif
00421
00422 neighcells_3d = PSMILe_undef
00423
00424 if ( ndim == ndim_2d ) then
00425
00426
00427
00428 offset = 0
00429 do ipart = 1, search%npart
00430
00431 do j = 1, npoints(2,ipart)-1
00432 do i = 1, npoints(1,ipart)-1
00433
00434 do jj = 1, ic(2,ipart)%vector(j)
00435 do ii = 1, ic(1,ipart)%vector(i)
00436
00437 icell = srclocs(1,ipart)%vector(i) - grid_valid_shape(1,1) + ii
00438
00439 if ( icell <= length(1) ) then
00440
00441
00442
00443 overlap = ( corners(1,ipart)%vector(i+1) - chmin(1)%vector(icell) ) * &
00444 ( chmax(1)%vector(icell) - corners(1,ipart)%vector(i) ) >= 0
00445
00446 if ( .not. overlap .and. cyclic(1) ) then
00447
00448 icell = srclocs(1,ipart)%vector(i) - grid_valid_shape(1,1) + 1
00449 if ( corners(1,ipart)%vector(i) < chmin(1)%vector(icell) ) then
00450 #ifdef DEBUGX
00451 print *, trim(ch_id),':',' search cell minimum ', &
00452 corners(1,ipart)%vector(i)
00453 print *, trim(ch_id),':',' is outside of local cell ', &
00454 chmin(1)%vector(icell)
00455 print *, trim(ch_id),':',' We look to the left.'
00456 #endif
00457 ctr_corner = corners(1,ipart)%vector(i) + global(1)
00458 do icell = length(1), 1, -1
00459 if ( ctr_corner > chmin(1)%vector(icell) ) exit
00460 enddo
00461 else
00462 #ifdef DEBUGX
00463 print *, trim(ch_id),':', ' nothing on the left ', i, j, ii, jj
00464 #endif
00465 icell = PSMILe_undef
00466 endif
00467 endif
00468 else
00469 #ifdef DEBUGX
00470 print *, trim(ch_id),':',' nothing there ', j, i, jj, ii
00471 #endif
00472 icell = PSMILe_undef
00473 endif
00474
00475 neighcells_3d(1,offset + ii + (jj-1)*ic(1,ipart)%vector(i), 1 ) &
00476 = icell
00477 neighcells_3d(2,offset + ii + (jj-1)*ic(1,ipart)%vector(i), 1 ) &
00478 = srclocs(2,ipart)%vector(j) + jj - 1
00479
00480 enddo
00481 enddo
00482
00483 offset = offset + ic(1,ipart)%vector(i)*ic(2,ipart)%vector(j)
00484
00485 enddo
00486 enddo
00487
00488
00489
00490
00491 do k = 1, npoints(3,ipart)
00492 neighcells_3d(3,(k-1)*lenij+1:k*lenij,1) = srclocs(3,ipart)%vector(k)
00493 enddo
00494
00495 enddo
00496
00497
00498
00499 do k = 2, npoints(3,1)
00500 neighcells_3d(1,(k-1)*lenij+1:k*lenij,1) = neighcells_3d(1,1:lenij,1)
00501 neighcells_3d(2,(k-1)*lenij+1:k*lenij,1) = neighcells_3d(2,1:lenij,1)
00502 enddo
00503
00504 else if ( ndim == ndim_3d ) then
00505
00506
00507
00508 offset = 0
00509
00510 do ipart = 1, search%npart
00511 do k = 1, npoints(3,ipart)-1
00512 do j = 1, npoints(2,ipart)-1
00513 do i = 1, npoints(1,ipart)-1
00514
00515 do kk = 1, ic(3,ipart)%vector(k)
00516 do jj = 1, ic(2,ipart)%vector(j)
00517 do ii = 1, ic(1,ipart)%vector(i)
00518
00519 icell = srclocs(1,ipart)%vector(i) + ii - 1
00520
00521 if ( icell <= length(1) ) then
00522 if ( corners(1,ipart)%vector(i ) >= chmin(1)%vector(icell) .and. &
00523 corners(1,ipart)%vector(i+1) <= chmax(1)%vector(icell) ) then
00524 n = icell
00525 endif
00526 else
00527 n = 99
00528 endif
00529
00530 neighcells_3d(1,offset + ii + (jj-1)*ic(1,ipart)%vector(i), 1 ) &
00531 = n
00532 neighcells_3d(2,offset + ii + (jj-1)*ic(1,ipart)%vector(i), 1 ) &
00533 = srclocs(2,ipart)%vector(j) + jj - 1
00534 enddo
00535 enddo
00536 enddo
00537
00538 offset = offset + ic(1,ipart)%vector(i) &
00539 * ic(2,ipart)%vector(j) &
00540 * ic(3,ipart)%vector(k)
00541 enddo
00542 enddo
00543 enddo
00544 enddo
00545
00546
00547
00548
00549 do k = 1, lenk
00550 neighcells_3d(3,(k-1)*lenij+1:k*lenij,1) = neighcells_3d(3,1:lenij,1)
00551 enddo
00552
00553 endif
00554
00555
00556
00557 neighcells_3d(1,1:nbr_cells_tot,2) = neighcells_3d(1,1:nbr_cells_tot,1) + 1
00558 neighcells_3d(1,1:nbr_cells_tot,3) = neighcells_3d(1,1:nbr_cells_tot,1) + 1
00559 neighcells_3d(1,1:nbr_cells_tot,4) = neighcells_3d(1,1:nbr_cells_tot,1)
00560
00561 neighcells_3d(2,1:nbr_cells_tot,2) = neighcells_3d(2,1:nbr_cells_tot,1)
00562 neighcells_3d(2,1:nbr_cells_tot,3) = neighcells_3d(2,1:nbr_cells_tot,1) + 1
00563 neighcells_3d(2,1:nbr_cells_tot,4) = neighcells_3d(2,1:nbr_cells_tot,1) + 1
00564
00565 neighcells_3d(3,1:nbr_cells_tot,2) = neighcells_3d(3,1:nbr_cells_tot,1)
00566 neighcells_3d(3,1:nbr_cells_tot,3) = neighcells_3d(3,1:nbr_cells_tot,1)
00567 neighcells_3d(3,1:nbr_cells_tot,4) = neighcells_3d(3,1:nbr_cells_tot,1)
00568
00569
00570
00571
00572 if ( n_corners == 8 ) then
00573 do n = 5, n_corners
00574 neighcells_3d(1,1:nbr_cells_tot,n) = neighcells_3d(1,1:nbr_cells_tot,n-4)
00575 neighcells_3d(2,1:nbr_cells_tot,n) = neighcells_3d(2,1:nbr_cells_tot,n-4)
00576 neighcells_3d(3,1:nbr_cells_tot,n) = neighcells_3d(3,1:nbr_cells_tot,1)+1
00577 enddo
00578 endif
00579
00580
00581
00582 do i = 1, ndim_3d
00583
00584 if (cyclic(i) .and. length(i) > 1) then
00585
00586 do n = 1, n_corners
00587
00588 do j = 1, nbr_cells_tot
00589
00590 if ( neighcells_3d(i,j,n) < grid_valid_shape(1,i)) then
00591 neighcells_3d(i,j,n) = neighcells_3d(i,j,n) + length (i)
00592 else if ( neighcells_3d(i,j,n) > grid_valid_shape(2,i)) then
00593 neighcells_3d(i,j,n) = neighcells_3d(i,j,n) - length (i)
00594 endif
00595
00596 enddo
00597
00598 end do
00599
00600 endif
00601
00602 end do
00603
00604
00605
00606 do i = 1, ndim_3d
00607 if (length(i) == 1) then
00608 neighcells_3d(i,1:nbr_cells_tot,:) = grid_valid_shape(1,i)
00609 endif
00610 end do
00611
00612
00613
00614 do i = 1, ndim
00615 Deallocate( chmin(i)%vector, chmax(i)%vector, STAT=ierror )
00616 if (ierror /= 0) then
00617 ierrp (1) = 2 * length(i)
00618 ierror = PRISM_Error_Dealloc
00619 call psmile_error ( ierror, 'chmin, chmax', &
00620 ierrp, 1, __FILE__, __LINE__ )
00621 return
00622 endif
00623 enddo
00624
00625 do ipart = 1, search%npart
00626 do i = 1, ndim
00627 Deallocate(ic(i,ipart)%vector, STAT=ierror )
00628 if (ierror /= 0) then
00629 ierrp (1) = npoints(i,ipart)-1
00630 ierror = PRISM_Error_Dealloc
00631 call psmile_error ( ierror, 'ic vector', &
00632 ierrp, 1, __FILE__, __LINE__ )
00633 return
00634 endif
00635 enddo
00636 enddo
00637
00638
00639
00640 #ifdef VERBOSE
00641 print 9980, trim(ch_id)
00642
00643 call psmile_flushstd
00644 #endif /* VERBOSE */
00645
00646
00647
00648 9990 format (1x, a, ': psmile_neigh_cells_3d_reg_real')
00649 9980 format (1x, a, ': psmile_neigh_cells_3d_reg_real: eof')
00650
00651 #ifdef PRISM_ASSERTION
00652 9970 format (1x, a, ': number of neighbors', i2, '; expected at least', i2)
00653 #endif
00654
00655 end subroutine psmile_neigh_cells_3d_reg_real