The main documentation of the Evaluate_Ortho_Diffusion Procedure contains additional explanation of this code listing.
subroutine Evaluate_Ortho_Diffusion (Diff_Term, Phi_MV, Div_D_Grad_Phi_Cells)
! Input variables.
type(Ortho_Diffusion_type), intent(inout) :: Diff_Term ! Diffusion term.
type(Mathematic_Vector_type), intent(inout) :: Phi_MV ! Phi math vector.
! Output variable.
type(real,1) :: Div_D_Grad_Phi_Cells ! Div D Grad at each cell center.
! Internal variables.
type(integer) :: face, other_cell ! Loop parameters.
type(real,3) :: Area_Faces_of_Cells, Beta
type(real,2) :: Pseudo_Ortho_Area_F_of_C
type(real,2) :: Harmonic_Diffusion_Coef_F_of_C ! Harmonic D at faces.
type(real,2) :: DeltaR21_Cells_of_Cells, DeltaR1f_Cells_of_Cells
type(integer) :: Faces_per_Cell ! Number of faces per cell.
type(integer) :: NDimensions ! Number of dimensions.
type(real,1) :: Volume_Cells ! Volume of the cells.
! Phi manipulation variables.
type(real,1) :: Phi_Cells
type(Distributed_Vector_type) :: Phi_Cells_DV
type(Collected_Array_type) :: Phi_Cells_of_Cells_CA
type(real,2) :: Phi_Cells_of_Cells
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Verify requirements.
VERIFY(Valid_State(Diff_Term),5) ! Diff_Term is valid.
VERIFY(Valid_State(Phi_MV),5) ! Phi_MV is valid.
VERIFY(Valid_State(Div_D_Grad_Phi_Cells),5) ! Div_D_Grad_Phi_Cells is valid.
! Div_D_Grad_Phi_Cells is dimensioned correctly.
VERIFY(SIZE(Div_D_Grad_Phi_Cells,1) == NCells_PE(Diff_Term%Mesh),5)
! Query the mesh.
Faces_per_Cell = Get_Faces_per_Cell (Diff_Term%Mesh)
NDimensions = Get_NDimensions (Diff_Term%Mesh)
! Future mods:
! 1. Access routine for Mesh%Cells_of_Cells_Index.
! Define Delta R's.
call Initialize (DeltaR21_Cells_of_Cells, NCells_PE(Diff_Term%Mesh), &
Faces_per_Cell)
call Initialize (DeltaR1f_Cells_of_Cells, NCells_PE(Diff_Term%Mesh), &
Faces_per_Cell)
call Get_DeltaR21_Cells_of_Cells (DeltaR21_Cells_of_Cells, Diff_Term%Mesh)
call Get_DeltaR1f_Cells_of_Cells (DeltaR1f_Cells_of_Cells, Diff_Term%Mesh)
! Define Harmonic Average Diffusion Coefficient.
call Initialize (Harmonic_Diffusion_Coef_F_of_C, &
NCells_PE(Diff_Term%Mesh), Faces_per_Cell)
call Get_Harmonic_Diffusion_Coef (Harmonic_Diffusion_Coef_F_of_C, &
Diff_Term)
! Define Pseudo-Ortho Area. Options are:
! 1. Scalar area.
! 2. Vector area dotted with unit vector joining the cell centers.
! 3. Middle area of face-center box.
call Initialize (Area_Faces_of_Cells, NDimensions, &
NCells_PE(Diff_Term%Mesh), &
Faces_per_Cell)
call Initialize (Pseudo_Ortho_Area_F_of_C, NCells_PE(Diff_Term%Mesh), &
Faces_per_Cell)
call Get_Area_Faces_of_Cells (Area_Faces_of_Cells, Diff_Term%Mesh)
if (.true.) then
! Option 1, Scalar Area.
Pseudo_Ortho_Area_F_of_C = ABS(SUM(Area_Faces_of_Cells(:,:,:),1))
end if
! Get cell volumes.
call Initialize (Volume_Cells, NCells_PE(Diff_Term%Mesh))
call Get_Volume_Cells (Volume_Cells, Diff_Term%Mesh)
! Get Phi for Cells and Cells of Cells.
call Initialize (Phi_Cells, NCells_PE(Diff_Term%Mesh))
call Initialize (Phi_Cells_DV, Diff_Term%Structure, 1)
call Initialize (Phi_Cells_of_Cells_CA, &
Diff_Term%Mesh%Cells_of_Cells_Index, 1)
call Initialize (Phi_Cells_of_Cells, NCells_PE(Diff_Term%Mesh), &
Faces_per_Cell)
Phi_Cells = Phi_MV
Phi_Cells_DV = Phi_Cells
Phi_Cells_of_Cells_CA = Phi_Cells_DV
Phi_Cells_of_Cells = Phi_Cells_of_Cells_CA
call Finalize (Phi_Cells_DV)
call Finalize (Phi_Cells_of_Cells_CA)
! Define Beta values for Boundary Conditions.
call Initialize (Beta, 3, NCells_PE(Diff_Term%Mesh), &
Faces_per_Cell)
where (Diff_Term%Boundary_Condition(:,:) == Dirichlet_BC)
Beta(1,:,:) = one
Beta(2,:,:) = zero
Beta(3,:,:) = one
elsewhere (Diff_Term%Boundary_Condition(:,:) == Homogeneous_BC)
Beta(1,:,:) = one
Beta(2,:,:) = zero
Beta(3,:,:) = zero
elsewhere (Diff_Term%Boundary_Condition(:,:) == Neumann_BC)
Beta(1,:,:) = zero
Beta(2,:,:) = -one
Beta(3,:,:) = one
elsewhere (Diff_Term%Boundary_Condition(:,:) == Reflective_BC)
Beta(1,:,:) = zero
Beta(2,:,:) = -one
Beta(3,:,:) = zero
elsewhere (Diff_Term%Boundary_Condition(:,:) == Source_BC)
Beta(1,:,:) = Diff_Term%Extrapolation
Beta(2,:,:) = one
Beta(3,:,:) = Diff_Term%Extrapolation
elsewhere (Diff_Term%Boundary_Condition(:,:) == Vacuum_BC)
Beta(1,:,:) = Diff_Term%Extrapolation
Beta(2,:,:) = one
Beta(3,:,:) = zero
end where
! Calculate -Div D Grad Phi, by integrating over the cell and
! dividing by the volume:
!
! ---
! 1 \
! - Div D Grad Phi = --- / F . A
! c V --- f f
! c faces
!
Div_D_Grad_Phi_Cells = zero
do face = 1, Faces_per_Cell
other_cell = face ! Another name for clearer semantics.
where (Diff_Term%Coefficient(:) == zero)
! No op. Flux is zero.
elsewhere (Diff_Term%Boundary_Condition(:,face) == &
Internal_or_Periodic_BC)
! For the internal faces and periodic boundary conditions:
!
! h
! F . A A D ( Phi - Phi )
! f f f 12 ( 1 2 )
! ------ = ------ ---------------
! V V | delta r |
! c c | 12 |
Div_D_Grad_Phi_Cells(:) = Div_D_Grad_Phi_Cells(:) + &
Pseudo_Ortho_Area_F_of_C(:,face) / Volume_Cells(:) &
* Harmonic_Diffusion_Coef_F_of_C(:,face) &
* (Phi_Cells(:) - Phi_Cells_of_Cells(:,other_cell)) &
/ DeltaR21_Cells_of_Cells(:,face)
elsewhere
! For the generalized Robin Boundary Conditions:
!
! F . A A ( Beta Phi - Beta Phi )
! f f f ( 1 1 3 BC )
! ------ = ----------------------------------------
! V V ( Beta + Beta | delta r | / D )
! c c ( 2 1 | 1f | 1 )
Div_D_Grad_Phi_Cells(:) = Div_D_Grad_Phi_Cells(:) + &
Pseudo_Ortho_Area_F_of_C(:,face) / Volume_Cells(:) &
* (Beta(1,:,face) * Phi_Cells(:) &
- Beta(3,:,face) * Diff_Term%Phi_BC(:,face) ) &
/ (Beta(2,:,face) &
+ Beta(1,:,face) * DeltaR1f_Cells_of_Cells(:,face) &
/ Diff_Term%Coefficient(:) )
end where
end do
! Finalize working structures.
call Finalize (Area_Faces_of_Cells)
call Finalize (Pseudo_Ortho_Area_F_of_C)
call Finalize (Volume_Cells)
call Finalize (DeltaR21_Cells_of_Cells)
call Finalize (DeltaR1f_Cells_of_Cells)
call Finalize (Harmonic_Diffusion_Coef_F_of_C)
call Finalize (Beta)
call Finalize (Phi_Cells)
call Finalize (Phi_Cells_of_Cells)
! Verify guarantees.
VERIFY(Valid_State(Div_D_Grad_Phi_Cells),5) ! Div_D_Grad_Phi_Cells is valid.
VERIFY(Valid_State(Phi_MV),5) ! Phi_MV is valid.
VERIFY(Valid_State(Diff_Term),5) ! Diff_Term is valid.
return
end subroutine Evaluate_Ortho_Diffusion