This lightly commented program performs a unit test on the Ortho_Diffusion Class.
program Unit_Test
use Caesar_Linear_Algebra_Module
use Caesar_Multi_Mesh_Class
use Caesar_Ortho_Diffusion_Class
use Caesar_Monomial_Class
use Caesar_Numbers_Module, only: zero, half, one, two, three, four, &
six, eight, twelve, sixteen
implicit none
type(Communication_type) :: Comm
type(Status_type) :: status
type(integer) :: c, NRows
! Mesh variables.
type(real,2) :: Coordinates_Cells ! Coordinates of the cell centers.
type(real,1) :: Lengths ! Physical extent of the
! domain in each direction.
type(Multi_Mesh_type) :: Mesh ! Mesh object.
type(integer) :: NDimensions ! Number of dimensions.
type(integer) :: NCells_X ! Number of cells in X.
type(integer) :: NCells_Y ! Number of cells in Y.
type(integer) :: NCells_Z ! Number of cells in Z.
type(integer) :: Faces_per_Cell ! Number of local faces per cell.
type(integer,2) :: Flag_Faces_of_Cells ! Mesh boundary flags.
type(real,3) :: Coordinates_Faces_of_Cells ! Coordinates of face centers.
type(real) :: X ! Local X coordinate.
! Physics variables.
type(real,1) :: Diffusion_Coefficient ! Diffusion Coefficient.
type(Mathematic_Vector_type) :: Phi_MV ! Diffused Quantity (MV).
type(real,1) :: Phi ! Diffused Quantity (BNV).
type(real,2) :: Gradient_Cells ! Gradient vectors at the cells.
type(real) :: Phi_0, Phi_1 ! Dirichlet BC constants.
type(real,1) :: Sigma_a ! Absorption cross-section.
type(real,1) :: Source ! Source term.
type(integer,2) :: BC_Faces_of_Cells ! Boundary condition flags.
type(real,2) :: Phi_BC_Faces_of_Cells ! Boundary condition constants.
type(real) :: Extrapolation ! Boundary condition factor.
type(real) :: D0, D1, D2, Q0
! Equation variables.
type(Ortho_Diffusion_type) :: Ortho_Diff_Term ! Diffusion term.
type(Monomial_type) :: Linear_Term ! Absorption term.
type(Monomial_type) :: Constant_Term ! Source term.
type(logical) :: Derivative ! Time derivative toggle.
type(real) :: Delta_t ! Time step size.
type(real) :: Exponent ! Exponent used in setting Monomial terms.
! Matrix variables.
type(ELL_Matrix_type) :: Matrix_ELLM ! Diffusion equation matrix.
type(integer) :: MaxNonzeros ! Maximum number of nonzero entries per row.
type(real,1) :: X_BNV ! Solution (BNV).
type(Mathematic_Vector_type) :: X_MV ! Solution (MV).
type(Mathematic_Vector_type) :: RHS_MV ! Right-hand side of diffusion eqn.
type(Mathematic_Vector_type) :: Error_MV ! Error Vector (MV).
type(Mathematic_Vector_type) :: Exact_MV ! Exact Vector (MV).
type(real,1) :: Exact ! Exact Vector (BNV).
type(real) :: Relative_L2_Error_Norm ! Relative L2 Error Norm.
! Base structures for the matrix.
type(Base_Structure_type) :: Row_Structure, Column_Structure
type(Solver_type) :: Solver
type(integer) :: Variable ! Variable number.
type(integer) :: Equation, eq ! Equation number.
type(integer) :: NEquations ! Number of equations.
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Initializations.
call Initialize (Comm)
call Output (Comm)
call Initialize (status)
! Create a mesh.
NCells_X = 10
NCells_Y = 2
NCells_Z = 12
!NCells_X = 2
!NCells_Y = 1
!NCells_Z = 1
NDimensions = 3
call Initialize (Lengths, NDimensions)
Lengths = (/ 1.d0, 1.d0, 1.d0 /)
call Initialize (Mesh, NDimensions, Lengths, NCells_X, NCells_Y, NCells_Z, &
'Uniform Mesh', status)
call Initialize (Coordinates_Cells, NDimensions, NCells_PE(Mesh), &
status)
call Get_Coordinates_Cells (Coordinates_Cells, Mesh)
Delta_t = zero
Derivative = .false.
Variable = 3
Equation = 2
NEquations = 3
! Set Diffusion Coefficient for every face of each cell.
! Faces_of_Cells way -- for later:
!
!Faces_per_Cell = two*NDimensions
!call Initialize (Diffusion_Coefficient, NCells_PE(Mesh), Faces_per_Cell, &
! status(4))
!do lf = 1, Faces_per_Cell
! where (Coordinates_Cells(1,:) < 0.5)
! Diffusion_Coefficient(:,lf) = Diff_Coeff(1)
! elsewhere
! Diffusion_Coefficient(:,lf) = Diff_Coeff(2)
! end where
!end do
! Set Boundary Conditions.
! (Should do by face, but doing by faces_of_cells is easier for now.)
! call Initialize (Boundary_Conditions, NFaces_PE(Mesh), status)
Faces_per_Cell = Get_Faces_per_Cell (Mesh)
call Initialize (BC_Faces_of_Cells, NCells_PE(Mesh), Faces_per_Cell, &
status)
call Initialize (Flag_Faces_of_Cells, NCells_PE(Mesh), Faces_per_Cell, &
status)
call Initialize (Phi_BC_Faces_of_Cells, NCells_PE(Mesh), Faces_per_Cell, &
status)
call Get_Flag_Faces_of_Cells (Flag_Faces_of_Cells, Mesh)
! Extrapolation Factor is set to the default value -- cannot leave it out of
! the initialize call because it appears before the status variable.
Extrapolation = half
! Get Cell Face Coordinates.
call Initialize (Coordinates_Faces_of_Cells, NDimensions, &
NCells_PE(Mesh), Faces_per_Cell)
call Get_Coordinates_Faces_of_Cells (Coordinates_Faces_of_Cells, Mesh)
! Physics initializations.
call Initialize (Sigma_a, NCells_PE(Mesh), status)
call Initialize (Source, NCells_PE(Mesh), status)
call Initialize (Diffusion_Coefficient, NCells_PE(Mesh), status)
call Initialize (Phi, NCells_PE(Mesh), status)
call Initialize (Gradient_Cells, NDimensions, NCells_PE(Mesh), status)
call Initialize (Exact, NCells_PE(Mesh), status)
call Initialize (Phi_MV, Cell_Structure(Mesh), 'Phi_Cells', status)
call Initialize (Error_MV, Cell_Structure(Mesh), 'Error = Solution - Exact', &
status)
call Initialize (Exact_MV, Cell_Structure(Mesh), 'Exact', status)
! Set up Matrix Equation.
MaxNonzeros = 2*NDimensions + 1
call Generate_Multiple (Row_Structure, NEquations, Cell_Structure(Mesh), &
'Rows')
call Generate_Multiple (Column_Structure, NEquations, Cell_Structure(Mesh), &
'Columns')
call Initialize (Matrix_ELLM, MaxNonzeros, Row_Structure, Column_Structure, &
'Coefficients', status)
call Initialize (X_BNV, Length_PE(Column_Structure), status)
call Initialize (X_MV, Column_Structure, 'Solution', status)
call Initialize (RHS_MV, Row_Structure, 'Right-Hand Side', &
status)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Problem X.1: 1-D Linear Solution with Dirichlet BCs
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (this_is_IO_PE) then
write (6,100) 'Problem X.1: 1-D Linear Solution with Dirichlet BCs'
end if
! Problem parameters.
Phi_0 = 47.d0
D0 = one/3.d0
Q0 = zero
! Set Absorption (Removal) cross-section for each cell.
Sigma_a = zero
! Set Source term for each cell.
Source = -Q0
! Set Diffusion Coefficient for each cell.
Diffusion_Coefficient = D0
! Set Boundary Conditions.
where (Flag_Faces_of_Cells == 1) ! Left (-x) Face.
BC_Faces_of_Cells = Dirichlet_BC
Phi_BC_Faces_of_Cells = Phi_0
elsewhere (Flag_Faces_of_Cells == 2) ! Right (+x) Face.
BC_Faces_of_Cells = Homogeneous_BC
elsewhere (Flag_Faces_of_Cells == 3) ! Front (-y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 4) ! Back (+y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 5) ! Bottom (-z) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 6) ! Top (+z) Face.
BC_Faces_of_Cells = Reflective_BC
end where
! Set Phi and X to an initial guess to avoid division by zero error in
! LAMG in the stopping test.
Phi = one
Phi_MV = Phi
X_BNV = one
X_MV = X_BNV
! Define Steady State Diffusion Equation.
call Initialize (Ortho_Diff_Term, Diffusion_Coefficient, BC_Faces_of_Cells, &
Phi_BC_Faces_of_Cells, Phi_MV, 'Cells', Mesh, &
'Diffusion Term', Extrapolation, Equation, NEquations, &
status)
Exponent = one
call Initialize (Linear_Term, Sigma_a, Exponent, Phi_MV, 'Cells', Mesh, &
'Absorption Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
Exponent = zero
call Initialize (Constant_Term, Source, Exponent, Phi_MV, 'Cells', Mesh, &
'Source Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
! Output Terms.
NRows = NCells_PE(Mesh)
!call Output ( Constant_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output ( Linear_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output (Ortho_Diff_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check state of Equation Terms.
VERIFY(Valid_State( Constant_Term),0)
VERIFY(Valid_State( Linear_Term),0)
VERIFY(Valid_State(Ortho_Diff_Term),0)
! Populate Matrix Equation.
call Add_to_Matrix_Equation (Ortho_Diff_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Linear_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Constant_Term, Matrix_ELLM, RHS_MV)
call Set_0_Diagonal_to_1 (Matrix_ELLM)
! Solve Matrix Equation.
VERIFY(Valid_State(Matrix_ELLM),0)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
call Initialize (Solver, 'LAMG')
call Set (Solver, 'Epsilon', 1.d-10)
call Solve (Solver, Matrix_ELLM, X_MV, RHS_MV)
call Finalize (Solver)
! Output.
VERIFY(Valid_State(X_MV),0)
!call Output (X_MV)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
VERIFY(Valid_State(RHS_MV),0)
!call Output (RHS_MV, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check answers.
X_BNV = X_MV
Phi = X_BNV(Equation::NEquations)
Phi_MV = Phi
do c = 1, NCells_PE(Mesh)
Exact(c) = Phi_0*(one-Coordinates_Cells(1,c))
! write (6,*) c, Coordinates_Cells(1,c), Phi(c), Exact(c), Exact(c) - Phi(c)
end do
Error_MV = Phi - Exact
call Output (Error_MV, 0, 0)
Exact_MV = Exact
Relative_L2_Error_Norm = Norm(Error_MV) / Norm(Exact_MV)
if (this_is_IO_PE) &
write (6,102) ' Relative L2 error norm = ', Relative_L2_Error_Norm
! Plotting output (turn on if desired).
if (.false.) then
call Dump_GMV ('GMVout.gmv', Mesh, Phi_MV, Exact_MV, Error_MV)
end if
! Check gradient.
call Evaluate_Gradient_Cells (Ortho_Diff_Term, Phi_MV, Gradient_Cells)
do c = 1, NCells_PE(Mesh)
if (ABS(Gradient_Cells(1,c) - (-Phi_0)) > 9.d-8 .or. &
ABS(Gradient_Cells(2,c) - (zero) ) > 2.d-8 .or. &
ABS(Gradient_Cells(3,c) - (zero) ) > 5.d-8) then
write (6,*) 'Error (Problem X.1): Grad = ', Gradient_Cells(:,c)
end if
end do
! Finalize terms.
call Finalize (Ortho_Diff_Term)
call Finalize (Linear_Term)
call Finalize (Constant_Term)
! Reset entire Matrix Equation.
!
! Note that we must finalize X_MV before Matrix_ELLM because the call to
! Solver may use a MatVec to calculate a residual, which would create an
! OV in X_MV based on the Data_Index in Matrix_ELLM. Tricky.
call Finalize (X_MV)
call Finalize (RHS_MV)
call Finalize (Matrix_ELLM)
call Initialize (Matrix_ELLM, MaxNonzeros, Row_Structure, Column_Structure, &
'Coefficients', status)
call Initialize (RHS_MV, Row_Structure, 'Right-Hand Side', &
status)
call Initialize (X_MV, Column_Structure, 'Solution', status)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Problem X.2: 1-D Linear Solution with Source/Vacuum BCs
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (this_is_IO_PE) then
write (6,100) 'Problem X.2: 1-D Linear Solution with Source/Vacuum BCs'
end if
! Problem parameters.
Phi_0 = 47.d0
D0 = one/3.d0
Q0 = zero
! Set Absorption (Removal) cross-section for each cell.
Sigma_a = zero
! Set Source term for each cell.
Source = -Q0
! Set Diffusion Coefficient for each cell.
Diffusion_Coefficient = D0
! Set Boundary Conditions.
where (Flag_Faces_of_Cells == 1) ! Left (-x) Face.
BC_Faces_of_Cells = Source_BC
Phi_BC_Faces_of_Cells = Phi_0
elsewhere (Flag_Faces_of_Cells == 2) ! Right (+x) Face.
BC_Faces_of_Cells = Vacuum_BC
elsewhere (Flag_Faces_of_Cells == 3) ! Front (-y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 4) ! Back (+y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 5) ! Bottom (-z) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 6) ! Top (+z) Face.
BC_Faces_of_Cells = Reflective_BC
end where
! Set Phi and X to an initial guess to avoid division by zero error in
! LAMG in the stopping test.
Phi = one
Phi_MV = Phi
X_BNV = one
X_MV = X_BNV
! Define Steady State Diffusion Equation.
call Initialize (Ortho_Diff_Term, Diffusion_Coefficient, BC_Faces_of_Cells, &
Phi_BC_Faces_of_Cells, Phi_MV, 'Cells', Mesh, &
'Diffusion Term', Extrapolation, Equation, NEquations, &
status)
Exponent = one
call Initialize (Linear_Term, Sigma_a, Exponent, Phi_MV, 'Cells', Mesh, &
'Absorption Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
Exponent = zero
call Initialize (Constant_Term, Source, Exponent, Phi_MV, 'Cells', Mesh, &
'Source Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
! Output Terms.
NRows = NCells_PE(Mesh)
!call Output ( Constant_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output ( Linear_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output (Ortho_Diff_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check state of Equation Terms.
VERIFY(Valid_State( Constant_Term),0)
VERIFY(Valid_State( Linear_Term),0)
VERIFY(Valid_State(Ortho_Diff_Term),0)
! Populate Matrix Equation.
call Add_to_Matrix_Equation (Ortho_Diff_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Linear_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Constant_Term, Matrix_ELLM, RHS_MV)
call Set_0_Diagonal_to_1 (Matrix_ELLM)
! Solve Matrix Equation.
VERIFY(Valid_State(Matrix_ELLM),0)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
call Initialize (Solver, 'LAMG')
call Set (Solver, 'Epsilon', 1.d-10)
call Solve (Solver, Matrix_ELLM, X_MV, RHS_MV)
call Finalize (Solver)
! Output.
VERIFY(Valid_State(X_MV),0)
!call Output (X_MV)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
VERIFY(Valid_State(RHS_MV),0)
!call Output (RHS_MV, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check answers.
X_BNV = X_MV
Phi = X_BNV(Equation::NEquations)
Phi_MV = Phi
do c = 1, NCells_PE(Mesh)
Exact(c) = Phi_0 * (one + two*D0 - Coordinates_Cells(1,c)) / &
(one + four*D0)
! write (6,*) c, Coordinates_Cells(1,c), Phi(c), Exact(c), Exact(c) - Phi(c)
end do
Error_MV = Phi - Exact
call Output (Error_MV, 0, 0)
Exact_MV = Exact
Relative_L2_Error_Norm = Norm(Error_MV) / Norm(Exact_MV)
if (this_is_IO_PE) &
write (6,102) ' Relative L2 error norm = ', Relative_L2_Error_Norm
! Plotting output (turn on if desired).
if (.false.) then
call Dump_GMV ('GMVout.gmv', Mesh, Phi_MV, Exact_MV, Error_MV)
end if
! Check gradient.
call Evaluate_Gradient_Cells (Ortho_Diff_Term, Phi_MV, Gradient_Cells)
do c = 1, NCells_PE(Mesh)
if (ABS(Gradient_Cells(1,c) - (-Phi_0/(one + four*D0))) > 5.d-9 .or. &
ABS(Gradient_Cells(2,c) - (zero) ) > 4.d-9 .or. &
ABS(Gradient_Cells(3,c) - (zero) ) > 4.d-9) then
write (6,*) 'Error (Problem X.2): Grad = ', Gradient_Cells(:,c)
end if
end do
! Finalize terms.
call Finalize (Ortho_Diff_Term)
call Finalize (Linear_Term)
call Finalize (Constant_Term)
! Reset entire Matrix Equation.
!
! Note that we must finalize X_MV before Matrix_ELLM because the call to
! Solver may use a MatVec to calculate a residual, which would create an
! OV in X_MV based on the Data_Index in Matrix_ELLM. Tricky.
call Finalize (X_MV)
call Finalize (RHS_MV)
call Finalize (Matrix_ELLM)
call Initialize (Matrix_ELLM, MaxNonzeros, Row_Structure, Column_Structure, &
'Coefficients', status)
call Initialize (RHS_MV, Row_Structure, 'Right-Hand Side', &
status)
call Initialize (X_MV, Column_Structure, 'Solution', status)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Problem X.3: Multi-D Linear Solution with Dirichlet BCs
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (this_is_IO_PE) then
write (6,100) 'Problem X.3: Multi-D Linear Solution with Dirichlet BCs'
end if
! Problem parameters.
Phi_0 = 47.d0
D0 = one/3.d0
Q0 = zero
! Set Absorption (Removal) cross-section for each cell.
Sigma_a = zero
! Set Source term for each cell.
Source = -Q0
! Set Diffusion Coefficient for each cell.
Diffusion_Coefficient = D0
! Set Boundary Conditions.
where (Flag_Faces_of_Cells == 1) ! Left (-x) Face.
BC_Faces_of_Cells = Dirichlet_BC
elsewhere (Flag_Faces_of_Cells == 2) ! Right (+x) Face.
BC_Faces_of_Cells = Dirichlet_BC
elsewhere (Flag_Faces_of_Cells == 3) ! Front (-y) Face.
BC_Faces_of_Cells = Dirichlet_BC
elsewhere (Flag_Faces_of_Cells == 4) ! Back (+y) Face.
BC_Faces_of_Cells = Dirichlet_BC
elsewhere (Flag_Faces_of_Cells == 5) ! Bottom (-z) Face.
BC_Faces_of_Cells = Dirichlet_BC
elsewhere (Flag_Faces_of_Cells == 6) ! Top (+z) Face.
BC_Faces_of_Cells = Dirichlet_BC
end where
Phi_BC_Faces_of_Cells(:,:) = Phi_0 * SUM(Coordinates_Faces_of_Cells(:,:,:),1)
! Set Phi and X to an initial guess to avoid division by zero error in
! LAMG in the stopping test.
Phi = one
Phi_MV = Phi
X_BNV = one
X_MV = X_BNV
! Define Steady State Diffusion Equation.
call Initialize (Ortho_Diff_Term, Diffusion_Coefficient, BC_Faces_of_Cells, &
Phi_BC_Faces_of_Cells, Phi_MV, 'Cells', Mesh, &
'Diffusion Term', Extrapolation, Equation, NEquations, &
status)
Exponent = one
call Initialize (Linear_Term, Sigma_a, Exponent, Phi_MV, 'Cells', Mesh, &
'Absorption Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
Exponent = zero
call Initialize (Constant_Term, Source, Exponent, Phi_MV, 'Cells', Mesh, &
'Source Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
! Output Terms.
NRows = NCells_PE(Mesh)
!call Output ( Constant_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output ( Linear_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output (Ortho_Diff_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check state of Equation Terms.
VERIFY(Valid_State( Constant_Term),0)
VERIFY(Valid_State( Linear_Term),0)
VERIFY(Valid_State(Ortho_Diff_Term),0)
! Populate Matrix Equation.
call Add_to_Matrix_Equation (Ortho_Diff_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Linear_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Constant_Term, Matrix_ELLM, RHS_MV)
call Set_0_Diagonal_to_1 (Matrix_ELLM)
! Solve Matrix Equation.
VERIFY(Valid_State(Matrix_ELLM),0)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
call Initialize (Solver, 'LAMG')
call Set (Solver, 'Epsilon', 1.d-10)
call Solve (Solver, Matrix_ELLM, X_MV, RHS_MV)
call Finalize (Solver)
! Output.
VERIFY(Valid_State(X_MV),0)
!call Output (X_MV)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
VERIFY(Valid_State(RHS_MV),0)
!call Output (RHS_MV, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check answers.
X_BNV = X_MV
Phi = X_BNV(Equation::NEquations)
Phi_MV = Phi
do c = 1, NCells_PE(Mesh)
Exact(c) = Phi_0 * SUM(Coordinates_Cells(:,c),1)
! write (6,*) c, Coordinates_Cells(1,c), Phi(c), Exact(c), Exact(c) - Phi(c)
end do
Error_MV = Phi - Exact
call Output (Error_MV, 0, 0)
Exact_MV = Exact
Relative_L2_Error_Norm = Norm(Error_MV) / Norm(Exact_MV)
if (this_is_IO_PE) &
write (6,102) ' Relative L2 error norm = ', Relative_L2_Error_Norm
! Plotting output (turn on if desired).
if (.false.) then
call Dump_GMV ('GMVout.gmv', Mesh, Phi_MV, Exact_MV, Error_MV)
end if
! Check gradient.
call Evaluate_Gradient_Cells (Ortho_Diff_Term, Phi_MV, Gradient_Cells)
do c = 1, NCells_PE(Mesh)
if (ABS(Gradient_Cells(1,c) - (Phi_0) ) > 7.d-7 .or. &
ABS(Gradient_Cells(2,c) - (Phi_0) ) > 7.d-7 .or. &
ABS(Gradient_Cells(3,c) - (Phi_0) ) > 7.d-7) then
write (6,*) 'Error (Problem X.3): Grad = ', Gradient_Cells(:,c)
end if
end do
! Finalize terms.
call Finalize (Ortho_Diff_Term)
call Finalize (Linear_Term)
call Finalize (Constant_Term)
! Reset entire Matrix Equation.
!
! Note that we must finalize X_MV before Matrix_ELLM because the call to
! Solver may use a MatVec to calculate a residual, which would create an
! OV in X_MV based on the Data_Index in Matrix_ELLM. Tricky.
call Finalize (X_MV)
call Finalize (RHS_MV)
call Finalize (Matrix_ELLM)
call Initialize (Matrix_ELLM, MaxNonzeros, Row_Structure, Column_Structure, &
'Coefficients', status)
call Initialize (RHS_MV, Row_Structure, 'Right-Hand Side', &
status)
call Initialize (X_MV, Column_Structure, 'Solution', status)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Problem X.4: 1-D Quadratic Solution with Dirichlet BCs
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (this_is_IO_PE) then
write (6,100) 'Problem X.4: 1-D Quadratic Solution with Dirichlet BCs'
end if
! Problem parameters.
D0 = one/3.d0
Q0 = 23.d0
Phi_0 = 6.d0
Phi_1 = 19.d0
! Set Absorption (Removal) cross-section for each cell.
Sigma_a = zero
! Set Source term for each cell.
Source = -Q0
! Set Diffusion Coefficient for each cell.
Diffusion_Coefficient = D0
! Set Boundary Conditions.
Phi_BC_Faces_of_Cells = zero
where (Flag_Faces_of_Cells == 1) ! Left (-x) Face.
BC_Faces_of_Cells = Dirichlet_BC
Phi_BC_Faces_of_Cells = Phi_0
elsewhere (Flag_Faces_of_Cells == 2) ! Right (+x) Face.
BC_Faces_of_Cells = Dirichlet_BC
Phi_BC_Faces_of_Cells = Phi_1
elsewhere (Flag_Faces_of_Cells == 3) ! Front (-y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 4) ! Back (+y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 5) ! Bottom (-z) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 6) ! Top (+z) Face.
BC_Faces_of_Cells = Reflective_BC
end where
! Set Phi and X to an initial guess to avoid division by zero error in
! LAMG in the stopping test.
Phi = one
Phi_MV = Phi
X_BNV = one
X_MV = X_BNV
! Define Steady State Diffusion Equation.
call Initialize (Ortho_Diff_Term, Diffusion_Coefficient, BC_Faces_of_Cells, &
Phi_BC_Faces_of_Cells, Phi_MV, 'Cells', Mesh, &
'Diffusion Term', Extrapolation, Equation, NEquations, &
status)
Exponent = one
call Initialize (Linear_Term, Sigma_a, Exponent, Phi_MV, 'Cells', Mesh, &
'Absorption Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
Exponent = zero
call Initialize (Constant_Term, Source, Exponent, Phi_MV, 'Cells', Mesh, &
'Source Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
! Output Terms.
NRows = NCells_PE(Mesh)
!call Output ( Constant_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output ( Linear_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output (Ortho_Diff_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check state of Equation Terms.
VERIFY(Valid_State( Constant_Term),0)
VERIFY(Valid_State( Linear_Term),0)
VERIFY(Valid_State(Ortho_Diff_Term),0)
! Populate Matrix Equation.
call Add_to_Matrix_Equation (Ortho_Diff_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Linear_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Constant_Term, Matrix_ELLM, RHS_MV)
call Set_0_Diagonal_to_1 (Matrix_ELLM)
! Solve Matrix Equation.
VERIFY(Valid_State(Matrix_ELLM),0)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
call Initialize (Solver, 'LAMG')
call Set (Solver, 'Epsilon', 1.d-10)
call Solve (Solver, Matrix_ELLM, X_MV, RHS_MV)
call Finalize (Solver)
! Output.
VERIFY(Valid_State(X_MV),0)
!call Output (X_MV)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
VERIFY(Valid_State(RHS_MV),0)
!call Output (RHS_MV, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check answers.
! Note: I tested problem X.4 and it converged by 2nd Order when
! refined in the X-direction.
X_BNV = X_MV
Phi = X_BNV(Equation::NEquations)
Phi_MV = Phi
do c = 1, NCells_PE(Mesh)
X = Coordinates_Cells(1,c)
Exact(c) = Q0 / (two*D0) * (X - X**2) + (Phi_1 - Phi_0) * X + Phi_0
!write (6,*) c, Coordinates_Cells(1,c), Phi(c), Exact(c), Exact(c) - Phi(c)
end do
Error_MV = Phi - Exact
call Output (Error_MV, 0, 0)
Exact_MV = Exact
Relative_L2_Error_Norm = Norm(Error_MV) / Norm(Exact_MV)
if (this_is_IO_PE) &
write (6,102) ' Relative L2 error norm = ', Relative_L2_Error_Norm
! Plotting output (turn on if desired).
if (.false.) then
call Dump_GMV ('GMVout.gmv', Mesh, Phi_MV, Exact_MV, Error_MV)
end if
! Check gradient.
call Evaluate_Gradient_Cells (Ortho_Diff_Term, Phi_MV, Gradient_Cells)
do c = 1, NCells_PE(Mesh)
X = Coordinates_Cells(1,c)
if (ABS(Gradient_Cells(1,c) - &
(Q0 / (two*D0) * (1 - 2*X) + (Phi_1 - Phi_0)) ) > 1.d-8 .or. &
ABS(Gradient_Cells(2,c) - (zero) ) > 1.d-8 .or. &
ABS(Gradient_Cells(3,c) - (zero) ) > 1.d-8) then
write (6,*) 'Error (Problem X.4): Grad = ', Gradient_Cells(:,c)
end if
end do
! Finalize terms.
call Finalize (Ortho_Diff_Term)
call Finalize (Linear_Term)
call Finalize (Constant_Term)
! Reset entire Matrix Equation.
!
! Note that we must finalize X_MV before Matrix_ELLM because the call to
! Solver may use a MatVec to calculate a residual, which would create an
! OV in X_MV based on the Data_Index in Matrix_ELLM. Tricky.
call Finalize (X_MV)
call Finalize (RHS_MV)
call Finalize (Matrix_ELLM)
call Initialize (Matrix_ELLM, MaxNonzeros, Row_Structure, Column_Structure, &
'Coefficients', status)
call Initialize (RHS_MV, Row_Structure, 'Right-Hand Side', &
status)
call Initialize (X_MV, Column_Structure, 'Solution', status)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Problem X.5: 1-D Quadratic Solution with Vacuum BCs
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (this_is_IO_PE) then
write (6,100) 'Problem X.5: 1-D Quadratic Solution with Vacuum BCs'
end if
! Problem parameters.
D0 = one/3.d0
Q0 = 23.d0
! Set Absorption (Removal) cross-section for each cell.
Sigma_a = zero
! Set Source term for each cell.
Source = -Q0
! Set Diffusion Coefficient for each cell.
Diffusion_Coefficient = D0
! Set Boundary Conditions.
where (Flag_Faces_of_Cells == 1) ! Left (-x) Face.
BC_Faces_of_Cells = Vacuum_BC
elsewhere (Flag_Faces_of_Cells == 2) ! Right (+x) Face.
BC_Faces_of_Cells = Vacuum_BC
elsewhere (Flag_Faces_of_Cells == 3) ! Front (-y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 4) ! Back (+y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 5) ! Bottom (-z) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 6) ! Top (+z) Face.
BC_Faces_of_Cells = Reflective_BC
end where
Phi_BC_Faces_of_Cells = zero
! Set Phi and X to an initial guess to avoid division by zero error in
! LAMG in the stopping test.
Phi = one
Phi_MV = Phi
X_BNV = one
X_MV = X_BNV
! Define Steady State Diffusion Equation.
call Initialize (Ortho_Diff_Term, Diffusion_Coefficient, BC_Faces_of_Cells, &
Phi_BC_Faces_of_Cells, Phi_MV, 'Cells', Mesh, &
'Diffusion Term', Extrapolation, Equation, NEquations, &
status)
Exponent = one
call Initialize (Linear_Term, Sigma_a, Exponent, Phi_MV, 'Cells', Mesh, &
'Absorption Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
Exponent = zero
call Initialize (Constant_Term, Source, Exponent, Phi_MV, 'Cells', Mesh, &
'Source Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
! Output Terms.
NRows = NCells_PE(Mesh)
!call Output ( Constant_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output ( Linear_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output (Ortho_Diff_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check state of Equation Terms.
VERIFY(Valid_State( Constant_Term),0)
VERIFY(Valid_State( Linear_Term),0)
VERIFY(Valid_State(Ortho_Diff_Term),0)
! Populate Matrix Equation.
call Add_to_Matrix_Equation (Ortho_Diff_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Linear_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Constant_Term, Matrix_ELLM, RHS_MV)
call Set_0_Diagonal_to_1 (Matrix_ELLM)
! Solve Matrix Equation.
VERIFY(Valid_State(Matrix_ELLM),0)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
call Initialize (Solver, 'LAMG')
call Set (Solver, 'Epsilon', 1.d-10)
call Solve (Solver, Matrix_ELLM, X_MV, RHS_MV)
call Finalize (Solver)
! Output.
VERIFY(Valid_State(X_MV),0)
!call Output (X_MV)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
VERIFY(Valid_State(RHS_MV),0)
!call Output (RHS_MV, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check answers.
! Note: I tested problem X.5 and it converged by 2nd Order when
! refined in the X-direction.
X_BNV = X_MV
Phi = X_BNV(Equation::NEquations)
Phi_MV = Phi
do c = 1, NCells_PE(Mesh)
X = Coordinates_Cells(1,c)
Exact(c) = Q0 / (two*D0) * ( two*D0 + X - X**2)
! write (6,*) c, Coordinates_Cells(1,c), Phi(c), Exact(c), Exact(c) - Phi(c)
end do
Error_MV = Phi - Exact
call Output (Error_MV, 0, 0)
Exact_MV = Exact
Relative_L2_Error_Norm = Norm(Error_MV) / Norm(Exact_MV)
if (this_is_IO_PE) &
write (6,102) ' Relative L2 error norm = ', Relative_L2_Error_Norm
! Plotting output (turn on if desired).
if (.false.) then
call Dump_GMV ('GMVout.gmv', Mesh, Phi_MV, Exact_MV, Error_MV)
end if
! Check gradient.
call Evaluate_Gradient_Cells (Ortho_Diff_Term, Phi_MV, Gradient_Cells)
do c = 1, NCells_PE(Mesh)
X = Coordinates_Cells(1,c)
if (ABS(Gradient_Cells(1,c) - (Q0 / (two*D0) * (1 - 2*X)) ) > 1.d-8 .or. &
ABS(Gradient_Cells(2,c) - (zero) ) > 1.d-8 .or. &
ABS(Gradient_Cells(3,c) - (zero) ) > 1.d-8) then
write (6,*) 'Error (Problem X.5): Grad = ', Gradient_Cells(:,c)
end if
end do
! Finalize terms.
call Finalize (Ortho_Diff_Term)
call Finalize (Linear_Term)
call Finalize (Constant_Term)
! Reset entire Matrix Equation.
!
! Note that we must finalize X_MV before Matrix_ELLM because the call to
! Solver may use a MatVec to calculate a residual, which would create an
! OV in X_MV based on the Data_Index in Matrix_ELLM. Tricky.
call Finalize (X_MV)
call Finalize (RHS_MV)
call Finalize (Matrix_ELLM)
call Initialize (Matrix_ELLM, MaxNonzeros, Row_Structure, Column_Structure, &
'Coefficients', status)
call Initialize (RHS_MV, Row_Structure, 'Right-Hand Side', &
status)
call Initialize (X_MV, Column_Structure, 'Solution', status)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Problem X.6: 1-D Quartic Solution with Vacuum BCs
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (this_is_IO_PE) then
write (6,100) 'Problem X.6: 1-D Quartic Solution with Vacuum BCs'
end if
! Problem parameters.
D0 = one/3.d0
Q0 = 23.d0
! Set Absorption (Removal) cross-section for each cell.
Sigma_a = zero
! Set Source term for each cell.
do c = 1, NCells_PE(Mesh)
Source(c) = -Q0 * Coordinates_Cells(1,c)**2
end do
! Set Diffusion Coefficient for each cell.
Diffusion_Coefficient = D0
! Set Boundary Conditions.
where (Flag_Faces_of_Cells == 1) ! Left (-x) Face.
BC_Faces_of_Cells = Vacuum_BC
elsewhere (Flag_Faces_of_Cells == 2) ! Right (+x) Face.
BC_Faces_of_Cells = Vacuum_BC
elsewhere (Flag_Faces_of_Cells == 3) ! Front (-y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 4) ! Back (+y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 5) ! Bottom (-z) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 6) ! Top (+z) Face.
BC_Faces_of_Cells = Reflective_BC
end where
Phi_BC_Faces_of_Cells = zero
! Set Phi and X to an initial guess to avoid division by zero error in
! LAMG in the stopping test.
Phi = one
Phi_MV = Phi
X_BNV = one
X_MV = X_BNV
! Define Steady State Diffusion Equation.
call Initialize (Ortho_Diff_Term, Diffusion_Coefficient, BC_Faces_of_Cells, &
Phi_BC_Faces_of_Cells, Phi_MV, 'Cells', Mesh, &
'Diffusion Term', Extrapolation, Equation, NEquations, &
status)
Exponent = one
call Initialize (Linear_Term, Sigma_a, Exponent, Phi_MV, 'Cells', Mesh, &
'Absorption Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
Exponent = zero
call Initialize (Constant_Term, Source, Exponent, Phi_MV, 'Cells', Mesh, &
'Source Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
! Output Terms.
NRows = NCells_PE(Mesh)
!call Output ( Constant_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output ( Linear_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output (Ortho_Diff_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check state of Equation Terms.
VERIFY(Valid_State( Constant_Term),0)
VERIFY(Valid_State( Linear_Term),0)
VERIFY(Valid_State(Ortho_Diff_Term),0)
! Populate Matrix Equation.
call Add_to_Matrix_Equation (Ortho_Diff_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Linear_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Constant_Term, Matrix_ELLM, RHS_MV)
call Set_0_Diagonal_to_1 (Matrix_ELLM)
! Solve Matrix Equation.
VERIFY(Valid_State(Matrix_ELLM),0)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
call Initialize (Solver, 'LAMG')
call Set (Solver, 'Epsilon', 1.d-10)
call Solve (Solver, Matrix_ELLM, X_MV, RHS_MV)
call Finalize (Solver)
! Output.
VERIFY(Valid_State(X_MV),0)
!call Output (X_MV)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
VERIFY(Valid_State(RHS_MV),0)
!call Output (RHS_MV, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check answers.
! Note: I tested problem X.6 and it converged by 2nd Order when
! refined in the X-direction.
X_BNV = X_MV
Phi = X_BNV(Equation::NEquations)
Phi_MV = Phi
do c = 1, NCells_PE(Mesh)
X = Coordinates_Cells(1,c)
Exact(c) = (Q0 / six) * ((one + eight * D0)/(one + four*D0) * &
(one + X / (two*D0)) - X**4 / (two*D0))
! write (6,*) c, Coordinates_Cells(1,c), Phi(c), Exact(c), Exact(c) - Phi(c)
end do
Error_MV = Phi - Exact
call Output (Error_MV, 0, 0)
Exact_MV = Exact
Relative_L2_Error_Norm = Norm(Error_MV) / Norm(Exact_MV)
if (this_is_IO_PE) &
write (6,102) ' Relative L2 error norm = ', Relative_L2_Error_Norm
! Plotting output (turn on if desired).
if (.false.) then
call Dump_GMV ('GMVout.gmv', Mesh, Phi_MV, Exact_MV, Error_MV)
end if
! Check gradient.
call Evaluate_Gradient_Cells (Ortho_Diff_Term, Phi_MV, Gradient_Cells)
do c = 1, NCells_PE(Mesh)
X = Coordinates_Cells(1,c)
if (ABS(Gradient_Cells(1,c) - &
((Q0 / six) * ((one + eight * D0)/(one + four*D0) * &
(one / (two*D0)) - four*X**3 / (two*D0))) ) > 0.12d0 .or. &
ABS(Gradient_Cells(2,c) - (zero) ) > 1.d-8 .or. &
ABS(Gradient_Cells(3,c) - (zero) ) > 1.d-8) then
write (6,*) 'Error (Problem X.6): Grad = ', Gradient_Cells(:,c)
write (6,*) 'Error (Problem X.6): Diff = ', ABS(Gradient_Cells(1,c) - &
((Q0 / six) * ((one + eight * D0)/(one + four*D0) * &
(one / (two*D0)) - four*X**3 / (two*D0))))
end if
end do
! Finalize terms.
call Finalize (Ortho_Diff_Term)
call Finalize (Linear_Term)
call Finalize (Constant_Term)
! Reset entire Matrix Equation.
!
! Note that we must finalize X_MV before Matrix_ELLM because the call to
! Solver may use a MatVec to calculate a residual, which would create an
! OV in X_MV based on the Data_Index in Matrix_ELLM. Tricky.
call Finalize (X_MV)
call Finalize (RHS_MV)
call Finalize (Matrix_ELLM)
call Initialize (Matrix_ELLM, MaxNonzeros, Row_Structure, Column_Structure, &
'Coefficients', status)
call Initialize (RHS_MV, Row_Structure, 'Right-Hand Side', &
status)
call Initialize (X_MV, Column_Structure, 'Solution', status)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Problem X.7: 1-D Quartic Solution with Two Materials
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (this_is_IO_PE) then
write (6,100) 'Problem X.7: 1-D Quartic Solution with Two Materials'
end if
! Problem parameters.
D1 = one/3.d0
D2 = one/3.d6
Q0 = 0.00023d0
! Set Absorption (Removal) cross-section for each cell.
Sigma_a = zero
! Set Source term for each cell.
do c = 1, NCells_PE(Mesh)
Source(c) = -Q0 * Coordinates_Cells(1,c)**2
end do
! Set Diffusion Coefficient for each cell.
where (Coordinates_Cells(1,:) < 0.5)
Diffusion_Coefficient(:) = D1
elsewhere
Diffusion_Coefficient(:) = D2
end where
! Set Boundary Conditions.
where (Flag_Faces_of_Cells == 1) ! Left (-x) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 2) ! Right (+x) Face.
BC_Faces_of_Cells = Vacuum_BC
elsewhere (Flag_Faces_of_Cells == 3) ! Front (-y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 4) ! Back (+y) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 5) ! Bottom (-z) Face.
BC_Faces_of_Cells = Reflective_BC
elsewhere (Flag_Faces_of_Cells == 6) ! Top (+z) Face.
BC_Faces_of_Cells = Reflective_BC
end where
Phi_BC_Faces_of_Cells = zero
! Set Phi and X to an initial guess to avoid division by zero error in
! LAMG in the stopping test.
Phi = one
Phi_MV = Phi
X_BNV = one
X_MV = X_BNV
! Define Steady State Diffusion Equation.
call Initialize (Ortho_Diff_Term, Diffusion_Coefficient, BC_Faces_of_Cells, &
Phi_BC_Faces_of_Cells, Phi_MV, 'Cells', Mesh, &
'Diffusion Term', Extrapolation, Equation, NEquations, &
status)
Exponent = one
call Initialize (Linear_Term, Sigma_a, Exponent, Phi_MV, 'Cells', Mesh, &
'Absorption Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
Exponent = zero
call Initialize (Constant_Term, Source, Exponent, Phi_MV, 'Cells', Mesh, &
'Source Term', Derivative, Delta_t, Phi_MV, Variable, &
Equation, NEquations, status)
! Output Terms.
NRows = NCells_PE(Mesh)
!call Output ( Constant_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output ( Linear_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
!call Output (Ortho_Diff_Term, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check state of Equation Terms.
VERIFY(Valid_State( Constant_Term),0)
VERIFY(Valid_State( Linear_Term),0)
VERIFY(Valid_State(Ortho_Diff_Term),0)
! Populate Matrix Equation.
call Add_to_Matrix_Equation (Ortho_Diff_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Linear_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Constant_Term, Matrix_ELLM, RHS_MV)
! ---------------------------------------------------------------------------
! This is a difficult problem, and it turned out that setting the diagonals
! to unity on zero rows, as is done for the other problems, resulted in a
! fairly good answer, but the gradients didn't pass the current tests. So,
! instead of taking that approach, we enter the same equation multiple times.
! So we repeat the steps above for the other equations. This works well.
do eq = 1, NEquations
if (eq /= Equation) then
! Finalize terms.
call Finalize (Ortho_Diff_Term)
call Finalize (Linear_Term)
call Finalize (Constant_Term)
! Define Steady State Diffusion Equation for Equation = eq.
call Initialize (Ortho_Diff_Term, Diffusion_Coefficient, &
BC_Faces_of_Cells, Phi_BC_Faces_of_Cells, Phi_MV, &
'Cells', Mesh, 'Diffusion Term', Extrapolation, eq, &
NEquations, status)
Exponent = one
call Initialize (Linear_Term, Sigma_a, Exponent, Phi_MV, 'Cells', Mesh, &
'Absorption Term', Derivative, Delta_t, Phi_MV, &
Variable, eq, NEquations, status)
Exponent = zero
call Initialize (Constant_Term, Source, Exponent, Phi_MV, 'Cells', Mesh, &
'Source Term', Derivative, Delta_t, Phi_MV, &
Variable, eq, NEquations, status)
! Populate Matrix Equation for Equation = eq.
call Add_to_Matrix_Equation (Ortho_Diff_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Linear_Term, Matrix_ELLM, RHS_MV)
call Add_to_Matrix_Equation (Constant_Term, Matrix_ELLM, RHS_MV)
end if
end do
! End of repeated equation.
! -------------------------
! Solve Matrix Equation.
VERIFY(Valid_State(Matrix_ELLM),0)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
call Initialize (Solver, 'LAMG')
call Set (Solver, 'Epsilon', 1.d-10)
call Solve (Solver, Matrix_ELLM, X_MV, RHS_MV)
call Finalize (Solver)
! Output.
VERIFY(Valid_State(X_MV),0)
!call Output (X_MV)
!call Output (Matrix_ELLM, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
VERIFY(Valid_State(RHS_MV),0)
!call Output (RHS_MV, MAX(1, NRows/10), MIN(NRows, NRows/10+50))
! Check answers.
! Note: I tested problem X.7 and it converged by 2nd Order when
! refined in the X-direction.
X_BNV = X_MV
Phi = X_BNV(Equation::NEquations)
Phi_MV = Phi
do c = 1, NCells_PE(Mesh)
X = Coordinates_Cells(1,c)
if (X < 0.5) then
Exact(c) = Q0 / (twelve*D2) * (one + eight * D2 + &
(D2 - D1) / (sixteen*D1) - (D2/D1) * X**4)
else
Exact(c) = Q0 / (twelve*D2) * (one + eight * D2 - X**4)
end if
! write (6,*) c, Coordinates_Cells(1,c), Phi(c), Exact(c), Exact(c) - Phi(c)
end do
Error_MV = Phi - Exact
call Output (Error_MV, 0, 0)
Exact_MV = Exact
Relative_L2_Error_Norm = Norm(Error_MV) / Norm(Exact_MV)
if (this_is_IO_PE) &
write (6,102) ' Relative L2 error norm = ', Relative_L2_Error_Norm
! Plotting output (turn on if desired).
if (.false.) then
call Dump_GMV ('GMVout.gmv', Mesh, Phi_MV, Exact_MV, Error_MV)
end if
! Check gradient.
call Evaluate_Gradient_Cells (Ortho_Diff_Term, Phi_MV, Gradient_Cells)
do c = 1, NCells_PE(Mesh)
X = Coordinates_Cells(1,c)
if (X < 0.5) then
if (ABS(Gradient_Cells(1,c) - &
(-Q0 / (three*D1) * X**3) ) > 1.1d0 .or. &
ABS(Gradient_Cells(2,c) - (zero) ) > 1.d-8 .or. &
ABS(Gradient_Cells(3,c) - (zero) ) > 1.d-8) then
write (6,*) 'Error (Problem X.7): Grad = ', Gradient_Cells(:,c)
write (6,*) 'Error (Problem X.7): Real = ', &
(-Q0 / (three*D1) * X**3), X
write (6,*) 'Error (Problem X.7): Diff = ', &
ABS(Gradient_Cells(1,c) - (-Q0 / (three*D1) * X**3) )
end if
else
if (ABS(Gradient_Cells(1,c) - &
(-Q0 / (three*D2) * X**3) ) > 1.1d0 .or. &
ABS(Gradient_Cells(2,c) - (zero) ) > 1.d-8 .or. &
ABS(Gradient_Cells(3,c) - (zero) ) > 1.d-8) then
write (6,*) 'Error (Problem X.7): Grad = ', Gradient_Cells(:,c)
write (6,*) 'Error (Problem X.7): Real = ', &
(-Q0 / (three*D2) * X**3), X
write (6,*) 'Error (Problem X.7): Diff = ', &
ABS(Gradient_Cells(1,c) - (-Q0 / (three*D2) * X**3) )
end if
end if
end do
! Finalize terms.
call Finalize (Ortho_Diff_Term)
call Finalize (Linear_Term)
call Finalize (Constant_Term)
! Reset entire Matrix Equation.
!
! Note that we must finalize X_MV before Matrix_ELLM because the call to
! Solver may use a MatVec to calculate a residual, which would create an
! OV in X_MV based on the Data_Index in Matrix_ELLM. Tricky.
call Finalize (X_MV)
call Finalize (RHS_MV)
call Finalize (Matrix_ELLM)
call Initialize (Matrix_ELLM, MaxNonzeros, Row_Structure, Column_Structure, &
'Coefficients', status)
call Initialize (RHS_MV, Row_Structure, 'Right-Hand Side', &
status)
call Initialize (X_MV, Column_Structure, 'Solution', status)
!~~~~~~~~~~~End of test problems.~~~~~~~~~~~
! Finalize variables.
call Finalize (BC_Faces_of_Cells)
call Finalize (Flag_Faces_of_Cells)
call Finalize (Phi_BC_Faces_of_Cells)
call Finalize (Coordinates_Faces_of_Cells)
call Finalize (MaxNonzeros)
call Finalize (Phi_MV)
call Finalize (Error_MV)
call Finalize (RHS_MV)
call Finalize (Matrix_ELLM)
call Finalize (Phi)
call Finalize (Source)
call Finalize (Sigma_a)
call Finalize (Diffusion_Coefficient)
call Finalize (Mesh)
call Finalize (NDimensions)
call Finalize (Lengths)
call Finalize (NCells_X)
call Finalize (NCells_Y)
call Finalize (NCells_Z)
call Finalize (Comm)
! Format statements.
100 format (/,a,:,a,:,a,:,a)
102 format (a,1pe22.15)
end