The Open FUSION Toolkit 1.0.0-8905cc5
Modeling tools for plasma and fusion research and engineering
Loading...
Searching...
No Matches
API Example 1: Helmholtz solve

This example outlines the basic elements of a program which uses the Open FUSION Toolkit (OFT) to solve a PDE. In this case computing the lowest eigenvalue of the scalar Helmholtz equation \( ( \nabla^2 - \lambda ) u = 0 \).

Code Walk Through

The code consists of three basic sections, required imports and variable definitions, finite element setup, and system creation and solution.

Module Includes

The first thing that you must do is include the OFT modules which contain the required functions and variables. It is good practice to restrict the included elements to only those needed. This is done using the ONLY clause to specifically include only certain definitions. The exceptions to this practice are the local and oft_base modules, which contain a controlled set of commonly used elements that can be safely imported as a whole.

PROGRAM example1
!---Runtime
!---Grid
!---Linear algebra
!---Lagrange FE space
IMPLICIT NONE
Base FEM class and functions for construction of FE linkage.
Definition fem_base.F90:20
Classes and infrastructure for composite FE representations.
Definition fem_composite.F90:14
Multigrid initialization using nested meshes.
Definition multigrid_build.F90:14
subroutine multigrid_construct(mg_mesh, grnd_pt)
Construct multi-level mesh.
Definition multigrid_build.F90:440
Multi-Level grid implementation using nested meshes.
Definition multigrid.F90:14
Base environment functions and aliases for Open FUSION Toolkit.
Definition oft_base.F90:23
HDF5 file manipulation for output and restart data.
Definition oft_io.F90:19
Abstract vector and matrix interfaces.
Definition lin_alg_base.F90:20
Base Lagrange FE class and basis evaluation.
Definition lagrange_basis.F90:22
subroutine oft_lag_setup(mg_mesh, order, ml_lag_obj, ml_blag_obj, ml_vlag_obj, minlev)
Construct lagrange scalar FE on each mesh level.
Definition lagrange_basis.F90:317
Lagrange FE operator definitions.
Definition lagrange_operators.F90:25
subroutine oft_lag_getlop(fe_rep, mat, bc)
Construct laplacian matrix for Lagrange scalar representation.
Definition lagrange_operators.F90:884
subroutine oft_lag_getmop(fe_rep, mat, bc)
Construct mass matrix for Lagrange scalar representation.
Definition lagrange_operators.F90:770
Abstract solver interfaces and select native implementations.
Definition native_solvers.F90:32
Matrix and vector management routines.
Definition solver_utils.F90:14
subroutine create_diag_pre(pre)
Needs docs.
Definition solver_utils.F90:619
Needs docs.
Definition fem_base.F90:146
Multi-level composite FE type.
Definition fem_composite.F90:73
Multigrid meshes and ML context structure.
Definition multigrid.F90:44
Information for XDMF plotting groups in HDF5 plot file.
Definition oft_io.F90:77
Abstract matrix class.
Definition lin_alg_base.F90:566
Abstract vector class.
Definition lin_alg_base.F90:69
Zero Lagrange FE vector at all global boundary nodes.
Definition lagrange_operators.F90:111
CG eigensolver class.
Definition native_solvers.F90:109

The first two modules import runtime and helper functions. The tetmesh_local module contains the main global mesh object mesh and multigrid_build contains the grid construction driver. The three oft_lag_* modules contain the finite element basis and setup routines, vector definitions, and operator routines respectively for a Lagrange finite element representation. oft_cg contains the native Conjugate-Gradient solvers and oft_io contains output routines for producing plot files.

Variable Definition

This defines the vector object used to compute the eigenvalue/vector pair as well as the matrix objects for the Laplace and Mass operators. An eigensolver is also instantiated along with a preconditioner which utilizes diagonal scaling.

Note
Preconditioners are not generally interoperable between different backends, ie. native vs PETSc. As a result different preconditioner objects should be used for each backend and controlled using preprocessor gaurds. For more information on available preconditioners see Available Solvers
CLASS(oft_vector), POINTER :: u
CLASS(oft_matrix), POINTER :: lop,mop
TYPE(oft_native_cg_eigsolver) :: solver
INTEGER(i4), PARAMETER :: order = 3
REAL(r8) :: lambda
REAL(r8), POINTER, DIMENSION(:) :: vtmp => null()
TYPE(xdmf_plot_file) :: plot_file
TYPE(multigrid_mesh) :: mg_mesh
TYPE(oft_ml_fem_type), TARGET :: ML_oft_lagrange,ML_oft_blagrange
TYPE(oft_ml_fem_comp_type), TARGET :: ML_oft_vlagrange
TYPE(oft_lag_zerob) :: lag_zerob

Initialize Enviroment

This call setups of the basics OFT run environment, including initializing MPI and PETSc if applicable.

subroutine oft_init(nthreads)
Initializes Open FUSION Toolkit run environment.
Definition oft_base.F90:193

Setup Grid

This call constructs the grid levels through heirarchical refinement, multigrid_construct.

CALL multigrid_construct(mg_mesh)

Create Output Files

This call sets up metadata files for I/O and saves the mesh for use with solution fields output later in the program. The plotting grid handles high order fields by tesselating the mesh to produce additional tets using the new node points. The level of tesselation is set by the first argument to mesh%setup_io.

CALL plot_file%setup("Example1")
CALL mg_mesh%mesh%setup_io(plot_file,order)

Setup Lagrange FE

oft_lag_setup builds the Lagrange finte elements on each grid and polynomial level. This create element interaction lists as well as boundary and seam information. All FE index fields are encapsulated in the oft_fem_type structure, see fem_setup.

CALL oft_lag_setup(mg_mesh,order,ml_oft_lagrange,ml_oft_blagrange,ml_oft_vlagrange)
lag_zerob%ML_lag_rep=>ml_oft_lagrange

Setup linear system

Solving the Helmholtz eigensystem requires the operators coresponding the general eigenvalue problem \( Ax = \lambda Mx \). These operators are the distcretized Laplace operator \( A = \int \nabla u_i^T \cdot \nabla u_j dV \) and the finite element mass matrix \( M = \int u_i^T u_j dV \). Where u and \( u^T \) are the Lagrange basis and test functions respectively. A vector defining the solution space is also required, to store the solution and to create worker vectors. In this case a dirichlet boundary condition is used where u is 0 everywhere on the boundary, denoted by the BC flag ‘'zerob’` used in matrix construction.

CALL ml_oft_lagrange%vec_create(u)
!---Create Operators
NULLIFY(lop,mop)
CALL oft_lag_getlop(ml_oft_lagrange%current_level,lop,'zerob')
CALL oft_lag_getmop(ml_oft_lagrange%current_level,mop,'zerob')

Setup solver

This section assembles the solver object by fill the required references. The solver object used here is the native non-linear Conjugate-Gradient iterative method. It requires the right and left hand side matrices for the generalized EV problem, A and M. The convergence tolerance is also specified to be double precision convergence of the eigenvalue, see oft_cg_eigsolver. Preconditioning is supplied by diagonal scaling, which requires identifying the preconditioner matrix, in this case A.

The vector is then initialized with a guess solution and the boundary condition is applied to make sure the initial guess is consistent with the boundary condition. Finally, the assembled solver is used to compute the lowest eigenvalue/eigenvector pair.

solver%A=>lop
solver%M=>mop
solver%its=-2
CALL create_diag_pre(solver%pre) ! Setup Preconditioner
!---Compute EV
CALL u%set(1.d0)
CALL lag_zerob%apply(u)
CALL solver%apply(u,lambda)

Save Solution

The solution is output to the HDF5 dump files for plotting at a later time in VisIt. In order to save the field the local representation must be retrieved from the vector object using get_local. These values may then be saved using the hdf5_spdata subroutine. When the program has completed oft_finalize is called to cleanup the runtime environment and terminate the process. This subroutine calls any required MPI and PETSc finalize subroutines as well. After completing the run, the build_xdmf script may be used to construct VisIt files and view the solution field, saved as tag T.

CALL u%get_local(vtmp)
CALL mg_mesh%mesh%save_vertex_scalar(vtmp,plot_file,'T')
DEALLOCATE(vtmp)
!---Program Stop
END PROGRAM example1
subroutine oft_finalize()
Finalize Open FUSION Toolkit environment.
Definition oft_base.F90:356

Input file

Below is an input file which can be used with this example in a serial environment. For this example we have disabled additional debug output, debug=0, and are using the built in cube mesh type, cad_type=92, with 4 grid refinements, nbase=nlevels=4.

&runtime_options
 ppn=1
 debug=0
/

&mesh_options
 meshname='cube'
 cad_type=92
 nlevels=4
 nbase=4
/

Parallel input file

In order to run the code in a distributed memory environment, with MPI, the mesh must be decomposed. This requires that nlevels>nbase as explained in Mesh settings. To perform a parallel run that is analogous to the serial run shown above the input file must be modified as below. The choice of nbase is somewhat arbitrary here, but generally is a function of the number of MPI tasks and the size of the base mesh. nlevels however, must be incremented by 1 in order to account for the additional transfer level create during decomposition.

&runtime_options
 ppn=1
 debug=0
/

&mesh_options
 meshname='cube'
 cad_type=92
 nlevels=5
 nbase=3
/

Complete Source

PROGRAM example1
!---Runtime
!---Grid
!---Linear algebra
!---Lagrange FE space
IMPLICIT NONE
!------------------------------------------------------------------------------
! Variable Definition
!------------------------------------------------------------------------------
CLASS(oft_vector), POINTER :: u
CLASS(oft_matrix), POINTER :: lop,mop
TYPE(oft_native_cg_eigsolver) :: solver
INTEGER(i4), PARAMETER :: order = 3
REAL(r8) :: lambda
REAL(r8), POINTER, DIMENSION(:) :: vtmp => null()
TYPE(xdmf_plot_file) :: plot_file
TYPE(multigrid_mesh) :: mg_mesh
TYPE(oft_ml_fem_type), TARGET :: ML_oft_lagrange,ML_oft_blagrange
TYPE(oft_ml_fem_comp_type), TARGET :: ML_oft_vlagrange
TYPE(oft_lag_zerob) :: lag_zerob
!------------------------------------------------------------------------------
! Initialize Enviroment
!------------------------------------------------------------------------------
!------------------------------------------------------------------------------
! Setup Grid
!------------------------------------------------------------------------------
CALL multigrid_construct(mg_mesh)
!------------------------------------------------------------------------------
! Create Output Files
!------------------------------------------------------------------------------
CALL plot_file%setup("Example1")
CALL mg_mesh%mesh%setup_io(plot_file,order)
!------------------------------------------------------------------------------
! Setup Lagrange FE
!------------------------------------------------------------------------------
CALL oft_lag_setup(mg_mesh,order,ml_oft_lagrange,ml_oft_blagrange,ml_oft_vlagrange)
lag_zerob%ML_lag_rep=>ml_oft_lagrange
!------------------------------------------------------------------------------
! Setup linear system
!------------------------------------------------------------------------------
CALL ml_oft_lagrange%vec_create(u)
!---Create Operators
NULLIFY(lop,mop)
CALL oft_lag_getlop(ml_oft_lagrange%current_level,lop,'zerob')
CALL oft_lag_getmop(ml_oft_lagrange%current_level,mop,'zerob')
!------------------------------------------------------------------------------
! Setup solver
!------------------------------------------------------------------------------
solver%A=>lop
solver%M=>mop
solver%its=-2
CALL create_diag_pre(solver%pre) ! Setup Preconditioner
!---Compute EV
CALL u%set(1.d0)
CALL lag_zerob%apply(u)
CALL solver%apply(u,lambda)
!------------------------------------------------------------------------------
! Save Solution
!------------------------------------------------------------------------------
CALL u%get_local(vtmp)
CALL mg_mesh%mesh%save_vertex_scalar(vtmp,plot_file,'T')
DEALLOCATE(vtmp)
!---Program Stop
END PROGRAM example1