The main documentation of the Add_to_Matrix_Equation_Ortho_Diffusion Procedure contains additional explanation of this code listing.
subroutine Add_to_Matrix_Equation_Ortho_D (Diff_Term, ELLM, RHS_MV)
! Input variables.
! Diff_Term to be added.
type(Ortho_Diffusion_type), intent(inout) :: Diff_Term
! Input/Output variables.
! ELL_Matrix to be incremented.
type(ELL_Matrix_type), intent(inout) :: ELLM
! RHS mathematic vector.
type(Mathematic_Vector_type), intent(inout) :: RHS_MV
! Internal variables.
! Arrays to manipulate values of the matrix.
type(real,2) :: Matrix_Values
type(real,1) :: RHS_Values
type(integer,1) :: Matrix_Rows
type(integer,2) :: Matrix_Columns
type(integer) :: face, i, other_cell ! Loop parameters.
type(integer) :: shift ! Index shift.
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.
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Verify requirements.
VERIFY(Valid_State(Diff_Term),5) ! Diff_Term is valid.
VERIFY(Valid_State(ELLM),5) ! ELLM is valid.
VERIFY(Valid_State(RHS_MV),5) ! RHS_MV is valid.
! 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.
! 2. Other pseudo-ortho methods.
! Create some working vectors.
call Initialize (Matrix_Values, NCells_PE(Diff_Term%Mesh), &
1+Faces_per_Cell)
call Initialize (RHS_Values, NCells_PE(Diff_Term%Mesh))
call Initialize (Matrix_Rows, NCells_PE(Diff_Term%Mesh))
call Initialize (Matrix_Columns, NCells_PE(Diff_Term%Mesh), &
1+Faces_per_Cell)
! 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)
!call Get_VecDeltaR21_Cells_of_Cells (DeltaR21_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)
! Must be dimensioned as follows:
! call Initialize (Diff_Term%Boundary_Condition, &
! NCells_PE(Diff_Term%Mesh), &
! Faces_per_Cell)
! 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
! 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
! Set Matrix_Rows, Matrix_Columns.
!
! To spread out the rows and columns from this equation into a multiple
! equation matrix, translate local numbers via:
! i --> NEquations*(i - 1) + Equation
! and global numbers via:
! i + shift --> NEquations*(i + shift - 1) + Equation
Matrix_Columns(:,2:) = Diff_Term%Mesh%Cells_of_Cells_Index
Matrix_Columns(:,2:) = Diff_Term%NEquations * (Matrix_Columns(:,2:) - 1) &
+ Diff_Term%Equation
shift = First_PE(Diff_Term%Structure) - 1
do i = 1, Length_PE(Diff_Term%Structure)
Matrix_Rows(i) = Diff_Term%NEquations*(i - 1) + Diff_Term%Equation
Matrix_Columns(i,1) = Diff_Term%NEquations*(i + shift - 1) + &
Diff_Term%Equation
end do
! Calculate matrix coefficients for F . A .
! f f
! Matrix structure:
! Matrix_Values(:,1) = Diagonal, the cell center value.
! Matrix_Values(:,2:Faces_per_Cell+1) = The values for the cells on
! the other side of each face, shifted by one from the face number
! to allow for the diagonal entry.
Matrix_Values = zero
do face = 1, Faces_per_Cell
other_cell = face ! Another name for clearer semantics.
where (Diff_Term%Boundary_Condition(:,face) == Internal_or_Periodic_BC)
! For the internal faces and periodic boundary conditions:
!
! ( Phi - Phi )
! h ( 1 2 )
! F . A = A D ---------------
! f f f 12 | delta r |
! | 12 |
!
! The other_cell (Phi_2) coefficient is calculated and stored
! here. The cell (diagonal entry, Phi_1) coefficient is calculated
! below by summing and subtracting all the other_cell coefficients.
Matrix_Values(:,other_cell+1) = &
- Pseudo_Ortho_Area_F_of_C(:,face) &
* Harmonic_Diffusion_Coef_F_of_C(:,face) &
/ DeltaR21_Cells_of_Cells(:,face)
elsewhere
! For the generalized Robin Boundary Conditions:
!
! A ( Beta Phi - Beta Phi )
! f ( 1 1 3 BC )
! F . A = -------------------------------------
! f f ( Beta + Beta | delta r | / D )
! ( 2 1 | 1f | 1 )
!
! The cell (diagonal entry, Phi_1) coefficient and the constant, RHS,
! value are both calculated here. Note the sign flip on the RHS value
! to move it to the right-hand side.
!
! Since a Fick's law extrapolation is used to determine this
! term, if D_1 is set to zero the flow (F.A) is set to zero,
! regardless of the Beta values.
where (Diff_Term%Coefficient(:) /= zero)
Matrix_Values(:,1) = Matrix_Values(:,1) + &
Pseudo_Ortho_Area_F_of_C(:,face) &
* Beta(1,:,face) &
/ (Beta(2,:,face) &
+ Beta(1,:,face) * DeltaR1f_Cells_of_Cells(:,face) &
/ Diff_Term%Coefficient(:) )
RHS_Values(:) = RHS_Values(:) + &
Pseudo_Ortho_Area_F_of_C(:,face) &
* 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 where
end do
! Finish the cell (diagonal entry, Phi_1) coefficient calculation by
! by summing and subtracting all the other_cell coefficients.
Matrix_Values(:,1) = Matrix_Values(:,1) - SUM(Matrix_Values(:,2:),2)
! Add the values to the ELLM matrix and RHS vector.
call Add_Values (ELLM, Matrix_Values, Matrix_Rows, Matrix_Columns, &
Global=.false.)
call Add_Values (RHS_MV, RHS_Values, Matrix_Rows, Global=.false.)
! Finalize working structures.
call Finalize (DeltaR21_Cells_of_Cells)
call Finalize (DeltaR1f_Cells_of_Cells)
call Finalize (Harmonic_Diffusion_Coef_F_of_C)
call Finalize (Pseudo_Ortho_Area_F_of_C)
call Finalize (Beta)
call Finalize (Area_Faces_of_Cells)
call Finalize (Matrix_Values)
call Finalize (RHS_Values)
call Finalize (Matrix_Rows)
call Finalize (Matrix_Columns)
! Verify guarantees.
VERIFY(Valid_State(ELLM),5) ! ELLM is valid.
VERIFY(Valid_State(RHS_MV),5) ! RHS_MV is valid.
return
end subroutine Add_to_Matrix_Equation_Ortho_D