@@ -5,6 +5,7 @@ module PrtPrtExchangeModule
55 use ConstantsModule, only: LENPACKAGENAME, LINELENGTH, LENMEMPATH, &
66 LENMODELNAME, LENBOUNDNAME, LENAUXNAME, &
77 DZERO, DONE
8+ use ErrorUtilModule, only: pstop
89 use ListsModule, only: basemodellist, baseexchangelist
910 use SimModule, only: store_error, store_error_filename, count_errors
1011 use SimVariablesModule, only: errmsg
@@ -31,7 +32,7 @@ module PrtPrtExchangeModule
3132 private
3233
3334 public :: PrtPrtExchangeType
34- public :: prtprt_cr, try_particle_transfer
35+ public :: prtprt_cr, try_transfer_particle
3536 public :: GetPrtPrtExchangeFromList
3637
3738 ! > @brief Exchange that transfers particles between two PRT models.
@@ -78,6 +79,7 @@ module PrtPrtExchangeModule
7879 procedure , private :: noder
7980 procedure , private :: get_exchange_faces
8081 procedure , private :: transform_particle
82+ procedure , private :: transfer_particle
8183 end type PrtPrtExchangeType
8284
8385contains
@@ -162,8 +164,8 @@ subroutine exg_df(this)
162164 end if
163165 !
164166 p = > this% self ! self-pointer. can't point directly to `this`
165- call this% prtmodel1% handlers% subscribe(try_particle_transfer , p)
166- call this% prtmodel2% handlers% subscribe(try_particle_transfer , p)
167+ call this% prtmodel1% handlers% subscribe(try_transfer_particle , p)
168+ call this% prtmodel2% handlers% subscribe(try_transfer_particle , p)
167169 end subroutine exg_df
168170
169171 ! > @brief Allocate and read: load the connected-cell list from IDM.
@@ -470,7 +472,10 @@ function noder(this, model, cellid, iout)
470472 noder = model% dis% get_nodenumber(node, 0 )
471473 end function noder
472474
473- function try_particle_transfer (context , particle , event ) result(transferred)
475+ ! > @brief Event handler for particle transfers. Checks whether the particle
476+ ! ! should be transferred in either direction through any exchange connection
477+ ! ! and, if so, conducts the transfer and return signals that it has occurred.
478+ function try_transfer_particle (context , particle , event ) result(transferred)
474479 use ModelExitEventModule, only: ModelExitEventType
475480 use PrtPrpModule, only: PrtPrpType, ExgPrtPrpType
476481 ! dummy
@@ -480,10 +485,8 @@ function try_particle_transfer(context, particle, event) result(transferred)
480485 logical (LGP) :: transferred
481486 ! local
482487 type (PrtPrtExchangeType), pointer :: exg
483- class(BndType), pointer :: exgprp_obj
484- type (ExgPrtPrpType), pointer :: exgprp
485- integer (I4B) :: i, dest_cell
486- logical (LGP) :: found
488+ logical (LGP) :: should
489+ integer (I4B) :: iexg
487490
488491 transferred = .false.
489492
@@ -496,110 +499,105 @@ function try_particle_transfer(context, particle, event) result(transferred)
496499
497500 select type (event)
498501 type is (ModelExitEventType)
499- ! model1 -> model2
500- found = .false.
501- do i = 1 , exg% nexg
502+ ! model1-> model2
503+ should = .false.
504+ do iexg = 1 , exg% nexg
502505 if ((particle% itrdomain(LEVEL_MODEL) == exg% prtmodel1% id) .and. &
503- (particle% icu == exg% nodem1(i))) then
504- dest_cell = exg% nodem2(i)
505- found = .true.
506+ (particle% icu == exg% nodem1(iexg))) then
507+ should = .true.
506508 exit
507509 end if
508510 end do
509- if (found) then
510- exgprp_obj = > GetBndFromList( &
511- exg% prtmodel2% bndlist, &
512- exg% prtmodel2% bndlist% Count ())
513- select type (exgprp_obj)
514- type is (ExgPrtPrpType)
515- exgprp = > exgprp_obj
516- call exg% transform_particle(particle, particle% icu, &
517- nint (exg% auxvar(exg% iflowface1, i)), &
518- from_m1= .true. )
519- exgprp% has_pending = .true.
520- exgprp% nparticles = exgprp% nparticles + 1
521- call exgprp% particles% resize(exgprp% nparticles, exgprp% memoryPath)
522- call exgprp% particles% put(particle, exgprp% nparticles)
523- particle% itrdomain(1 ) = exg% prtmodel1% id
524- particle% advancing = .false.
525- transferred = .true.
526- return
527- end select
511+ if (should) then
512+ call exg% transfer_particle(particle, iexg= iexg, from_m1= .true. )
513+ return
528514 end if
529515
530- ! model2 -> model1
531- found = .false.
532- do i = 1 , exg% nexg
516+ ! model2-> model1
517+ should = .false.
518+ do iexg = 1 , exg% nexg
533519 if ((particle% itrdomain(LEVEL_MODEL) == exg% prtmodel2% id) .and. &
534- (particle% icu == exg% nodem2(i))) then
535- dest_cell = exg% nodem1(i)
536- found = .true.
520+ (particle% icu == exg% nodem2(iexg))) then
521+ should = .true.
537522 exit
538523 end if
539524 end do
540- if (found) then
541- exgprp_obj = > GetBndFromList( &
542- exg% prtmodel1% bndlist, &
543- exg% prtmodel1% bndlist% Count ())
544- select type (exgprp_obj)
545- type is (ExgPrtPrpType)
546- exgprp = > exgprp_obj
547- call exg% transform_particle(particle, particle% icu, &
548- nint (exg% auxvar(exg% iflowface2, i)), &
549- from_m1= .false. )
550- exgprp% has_pending = .true.
551- exgprp% nparticles = exgprp% nparticles + 1
552- call exgprp% particles% resize(exgprp% nparticles, exgprp% memoryPath)
553- call exgprp% particles% put(particle, exgprp% nparticles)
554- particle% itrdomain(1 ) = exg% prtmodel2% id
555- particle% advancing = .false.
556- transferred = .true.
557- return
558- end select
525+ if (should) then
526+ call exg% transfer_particle(particle, iexg= iexg, from_m1= .false. )
527+ return
559528 end if
560529 end select
561- end function try_particle_transfer
530+ end function try_transfer_particle
562531
563- ! > @brief Get PRT-PRT exchange from list
564- function GetPrtPrtExchangeFromList (list , idx ) result(res)
565- use ListModule, only: ListType
566- implicit none
567- type (ListType), intent (inout ) :: list
568- integer (I4B), intent (in ) :: idx
569- class(PrtPrtExchangeType), pointer :: res
570- class(* ), pointer :: obj
571-
572- obj = > list% GetItem(idx)
573- res = > CastAsPrtPrtExchange(obj)
574- end function GetPrtPrtExchangeFromList
575-
576- ! > @brief Cast object as PRT-PRT exchange
577- function CastAsPrtPrtExchange (obj ) result(res)
578- implicit none
579- class(* ), pointer , intent (inout ) :: obj
580- class(PrtPrtExchangeType), pointer :: res
532+ ! > @brief Transfer the particle from one model to the other through
533+ ! ! the given exchange connection.
534+ subroutine transfer_particle (this , particle , iexg , from_m1 )
535+ use PrtPrpModule, only: PrtPrpType, ExgPrtPrpType
536+ class(PrtPrtExchangeType), intent (inout ) :: this
537+ type (ParticleType), intent (inout ), pointer :: particle
538+ integer (I4B), intent (in ) :: iexg
539+ logical (LGP), intent (in ) :: from_m1
540+ ! local
541+ type (PrtModelType), pointer :: prt_dst
542+ type (ExgPrtPrpType), pointer :: exgprp
543+ class(BndType), pointer :: exgprp_obj
544+ integer (I4B) :: icu_dst
581545
582- res = > null ()
583- if (.not. associated (obj)) return
546+ if (from_m1) then
547+ prt_dst = > this% prtmodel2
548+ else
549+ prt_dst = > this% prtmodel1
550+ end if
584551
585- select type (obj)
586- class is (PrtPrtExchangeType)
587- res = > obj
552+ exgprp_obj = > GetBndFromList( &
553+ prt_dst% bndlist, &
554+ prt_dst% bndlist% Count ())
555+
556+ select type (exgprp_obj)
557+ type is (ExgPrtPrpType)
558+ call this% transform_particle(particle, particle% icu, icu_dst, &
559+ nint (this% auxvar(this% iflowface1, iexg)), &
560+ from_m1= from_m1)
561+
562+ particle% icu = icu_dst
563+ particle% advancing = .true.
564+ particle% itrdomain(LEVEL_MODEL) = prt_dst% id
565+ particle% itrdomain(LEVEL_FEATURE) = &
566+ prt_dst% dis% get_nodenumber(particle% icu, 1 )
567+
568+ exgprp = > exgprp_obj
569+ exgprp% has_pending = .true.
570+ exgprp% nparticles = exgprp% nparticles + 1
571+ call exgprp% particles% resize(exgprp% nparticles, exgprp% memoryPath)
572+ call exgprp% particles% put(particle, exgprp% nparticles)
588573 end select
589- end function CastAsPrtPrtExchange
590-
591- ! > @brief Transform particle coordinates from source to destination model
592- subroutine transform_particle (this , particle , n_src , f_src , from_m1 )
574+ end subroutine transfer_particle
575+
576+ ! > @brief Transform particle coordinates from source to destination cell,
577+ ! ! by way of intermediate transformations via cell-normalized coordinates.
578+ ! !
579+ ! ! Transforms particle from the source model's coordinate system to coords
580+ ! ! local to the source cell, then to coords local to the destination cell,
581+ ! ! and finally to the destination model's coordinate system.
582+ ! !
583+ ! ! If the source cell connects to multiple cells in the destination model,
584+ ! ! the destination cells' connecting faces are together assumed to coincide
585+ ! ! with the source cell's connecting face. Coordinates are then computed by
586+ ! ! reference to the extent of the cell in the 2 dimensions parallel to the
587+ ! ! connected faces, and used to determine which among potential destination
588+ ! ! cells the particle should enter.
589+ ! <
590+ subroutine transform_particle (this , particle , n_src , n_dst , f_src , from_m1 )
593591 class(PrtPrtExchangeType) :: this
594592 type (ParticleType), pointer :: particle
595593 integer (I4B), intent (in ) :: n_src ! source cell
594+ integer (I4B), intent (out ) :: n_dst ! destination cell
596595 integer (I4B), intent (in ) :: f_src ! source face (IFLOWFACE numbering)
597596 logical (LGP), intent (in ) :: from_m1 ! true = m1->m2, false = m2->m1
598-
599- ! Local variables
597+ ! local
600598 integer (I4B), allocatable :: iexg_candidates(:)
601599 integer (I4B) :: n_candidates
602- integer (I4B) :: n_dst, f_dst, iexg, i
600+ integer (I4B) :: f_dst, iexg, i
603601 integer (I4B) :: iflowface_src, iflowface_dst
604602 real (DP) :: x1min, x1max, y1min, y1max, z1min, z1max
605603 real (DP) :: x2min, x2max, y2min, y2max, z2min, z2max
@@ -609,7 +607,7 @@ subroutine transform_particle(this, particle, n_src, f_src, from_m1)
609607 logical :: found
610608 class(PrtModelType), pointer :: prt_src, prt_dst
611609
612- ! Set up source/destination based on direction
610+ ! set source/destination model
613611 if (from_m1) then
614612 prt_src = > this% prtmodel1
615613 prt_dst = > this% prtmodel2
@@ -622,66 +620,60 @@ subroutine transform_particle(this, particle, n_src, f_src, from_m1)
622620 iflowface_dst = this% iflowface1
623621 end if
624622
625- ! 1. Find all candidate destination connections
623+ ! find candidate connections
626624 call get_connections(this, n_src, f_src, iexg_candidates, &
627625 n_candidates, from_m1)
628626
629- ! 2. Get source face bounds
627+ ! compute source face bounds
630628 call get_face_bounds(prt_src% dis, n_src, f_src, &
631629 x1min, x1max, y1min, y1max, z1min, z1max)
632630
633- ! 3. Get consolidated destination face bounds
631+ ! compute destination face bounds
634632 call get_consolidated_bounds(this, iexg_candidates, n_candidates, &
635633 x2min, x2max, y2min, y2max, z2min, z2max, &
636634 prt_dst% dis, iflowface_dst)
637635
638- ! 4. Normalize particle position in source face [0,1]
636+ ! map to cell-local coords
639637 dx1 = x1max - x1min
640638 dy1 = y1max - y1min
641639 dz1 = z1max - z1min
642-
643640 if (dx1 > DZERO) then
644641 tx = (particle% x - x1min) / dx1
645642 else
646- tx = DZERO ! dimension constant on this face
643+ tx = DZERO ! constant dimension
647644 end if
648-
649645 if (dy1 > DZERO) then
650646 ty = (particle% y - y1min) / dy1
651647 else
652648 ty = DZERO
653649 end if
654-
655650 if (dz1 > DZERO) then
656651 tz = (particle% z - z1min) / dz1
657652 else
658653 tz = DZERO
659654 end if
660655
661- ! 5. Map to destination face space
656+ ! map to destination model coords
662657 dx2 = x2max - x2min
663658 dy2 = y2max - y2min
664659 dz2 = z2max - z2min
665-
666660 if (dx2 > DZERO) then
667661 xt = x2min + tx * dx2
668662 else
669663 xt = x2min
670664 end if
671-
672665 if (dy2 > DZERO) then
673666 yt = y2min + ty * dy2
674667 else
675668 yt = y2min
676669 end if
677-
678670 if (dz2 > DZERO) then
679671 zt = z2min + tz * dz2
680672 else
681673 zt = z2min
682674 end if
683675
684- ! 6. Find which destination cell contains this position
676+ ! which cell is the particle in?
685677 found = .false.
686678 do i = 1 , n_candidates
687679 iexg = iexg_candidates(i)
@@ -692,28 +684,20 @@ subroutine transform_particle(this, particle, n_src, f_src, from_m1)
692684 n_dst = this% nodem1(iexg)
693685 f_dst = nint (this% auxvar(iflowface_dst, iexg))
694686 end if
695-
696687 if (point_in_face_bounds(prt_dst% dis, n_dst, f_dst, xt, yt, zt)) then
697- ! Found the destination!
698688 particle% x = xt
699689 particle% y = yt
700690 particle% z = zt
701- particle% icu = n_dst
702- particle% advancing = .true.
703- particle% itrdomain(LEVEL_MODEL) = prt_dst% id
704- particle% itrdomain(LEVEL_FEATURE) = &
705- prt_dst% dis% get_nodenumber(particle% icu, 1 )
706691 found = .true.
707692 exit
708693 end if
709694 end do
710-
711695 if (.not. found) then
712696 write (errmsg, ' (a,i0,a,i0,a,3g15.6,a)' ) &
713697 ' Particle transferring from cell ' , n_src, ' face ' , f_src, &
714698 ' at position (' , xt, yt, zt, &
715- ' ) not found in any destination face '
716- call store_error(errmsg, terminate = .TRUE. )
699+ ' ) not found in any destination cell '
700+ call pstop( 1 , errmsg )
717701 end if
718702
719703 deallocate (iexg_candidates)
@@ -1055,4 +1039,32 @@ function point_on_line_segment(x, y, x1, y1, x2, y2, tol) result(on_seg)
10551039 end if
10561040 end function point_on_line_segment
10571041
1042+ ! > @brief Get PRT-PRT exchange from list
1043+ function GetPrtPrtExchangeFromList (list , idx ) result(res)
1044+ use ListModule, only: ListType
1045+ implicit none
1046+ type (ListType), intent (inout ) :: list
1047+ integer (I4B), intent (in ) :: idx
1048+ class(PrtPrtExchangeType), pointer :: res
1049+ class(* ), pointer :: obj
1050+
1051+ obj = > list% GetItem(idx)
1052+ res = > CastAsPrtPrtExchange(obj)
1053+ end function GetPrtPrtExchangeFromList
1054+
1055+ ! > @brief Cast object as PRT-PRT exchange
1056+ function CastAsPrtPrtExchange (obj ) result(res)
1057+ implicit none
1058+ class(* ), pointer , intent (inout ) :: obj
1059+ class(PrtPrtExchangeType), pointer :: res
1060+
1061+ res = > null ()
1062+ if (.not. associated (obj)) return
1063+
1064+ select type (obj)
1065+ class is (PrtPrtExchangeType)
1066+ res = > obj
1067+ end select
1068+ end function CastAsPrtPrtExchange
1069+
10581070end module PrtPrtExchangeModule
0 commit comments