Check that a global set map can be split into sub-meshes.
The partition is valid when 1. 1 <= s(e) <= nSets for every global element e; 2. every set k = 1..nSets holds at least one element; 3. every 2:1 mortar (big element and its four small elements) and every anisotropic mortar (big element and its two small elements) lies in a single set, because the interface exchange between sets handles conforming faces only. The mortar tables hold global element ids and are replicated, and setOfElem is global, so every rank returns the same answer without communication. The first violation found is printed on rank 0.
Input - globalMesh : the decomposed global mesh - setOfElem(1:nGlobalElem) : set id of each global element (GatherSetOfElem) - nSets : number of sets, >= 1 Output - ok : .true. when all three conditions hold
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(Mesh3D), | intent(in) | :: | globalMesh | |||
| integer, | intent(in) | :: | setOfElem(1:) | |||
| integer, | intent(in) | :: | nSets |
function ValidateSetPartition(globalMesh,setOfElem,nSets) result(ok)
!! Check that a global set map can be split into sub-meshes.
!!
!! The partition is valid when
!! 1. 1 <= s(e) <= nSets for every global element e;
!! 2. every set k = 1..nSets holds at least one element;
!! 3. every 2:1 mortar (big element and its four small elements) and every
!! anisotropic mortar (big element and its two small elements) lies in a single
!! set, because the interface exchange between sets handles conforming faces
!! only.
!! The mortar tables hold global element ids and are replicated, and setOfElem is
!! global, so every rank returns the same answer without communication. The first
!! violation found is printed on rank 0.
!!
!! Input
!! - globalMesh : the decomposed global mesh
!! - setOfElem(1:nGlobalElem) : set id of each global element (GatherSetOfElem)
!! - nSets : number of sets, >= 1
!! Output
!! - ok : .true. when all three conditions hold
implicit none
type(Mesh3D),intent(in) :: globalMesh
integer,intent(in) :: setOfElem(1:)
integer,intent(in) :: nSets
logical :: ok
! Local
integer :: e,k,m,q,s0
integer,allocatable :: nInSet(:)
logical :: report
ok = .true.
report = (globalMesh%decomp%rankId == 0)
if(nSets < 1) then
ok = .false.
if(report) print*,__FILE__," : Error : nSets must be at least 1, got ",nSets
return
endif
allocate(nInSet(1:nSets))
nInSet = 0
do e = 1,size(setOfElem)
if(setOfElem(e) < 1 .or. setOfElem(e) > nSets) then
ok = .false.
if(report) print*,__FILE__," : Error : element ",e," has set id ",setOfElem(e), &
" outside 1..",nSets
deallocate(nInSet)
return
endif
nInSet(setOfElem(e)) = nInSet(setOfElem(e))+1
enddo
do k = 1,nSets
if(nInSet(k) == 0) then
ok = .false.
if(report) print*,__FILE__," : Error : element set ",k," is empty"
deallocate(nInSet)
return
endif
enddo
deallocate(nInSet)
! Mortar element rows: 1 (big) and 3,5,7,9 (small) in mortarInfo; 1 (big) and 3,5
! (small) in anisoMortarInfo.
do m = 1,globalMesh%nMortars
s0 = setOfElem(globalMesh%mortarInfo(1,m))
do q = 1,4
if(setOfElem(globalMesh%mortarInfo(1+2*q,m)) /= s0) then
ok = .false.
if(report) print*,__FILE__," : Error : mortar ",m," crosses element sets"
return
endif
enddo
enddo
do m = 1,globalMesh%nAnisoMortars
s0 = setOfElem(globalMesh%anisoMortarInfo(1,m))
do q = 1,2
if(setOfElem(globalMesh%anisoMortarInfo(1+2*q,m)) /= s0) then
ok = .false.
if(report) print*,__FILE__," : Error : anisotropic mortar ",m, &
" crosses element sets"
return
endif
enddo
enddo
endfunction ValidateSetPartition