# Presentation: 535730

## Language Interoperability and OO Design in C Using Babel: HypreAndrew J. Cleary(speaker)

**LACSI Workshop****October 18, 2001**

## Outline

**The *****hypre***** linear solver library**
**The BABEL language interoperability project**
**Implementing Babel/*****hypre***** wrappers**
**Calling***** hypre *****through the Babel-generated interface**
**Improving *****hypre***** using Babel’s OO features**
**Additional information**

## Hypre is a library of parallel linear solvers with a focus on complex preconditioners

## Must be callable from a handful of languages
Scalable parallel linear solvers and preconditioners 
Implemented in ANSI C using MPI
“Object Based” 

**Scalable parallel linear solvers and preconditioners **
**Implemented in ANSI C using MPI**
**“****Object Based”**** **

## Several Solvers and Preconditioners are available in hypre

**Current solver availability via conceptual interfaces**

## Multiple interfaces are necessary to provide “best” solvers and data layouts

## Why multiple interfaces?  The key points

**Provides natural “views” of the linear system**** **
**Eases some of the coding burden for users by eliminating the need to map to rows/columns **** **
**Provides for more efficient greybox linear solvers**** **
**Provides for more effective data storage schemes and more efficient computational kernels **

## The Babel language interoperability tool bridges gaps among different languages

**Tools automatically generate code to “glue” languages**
- library developer describes software interfaces in “SIDL” language
- interoperability tools automatically generate calling interfaces
- support C++, Fortran 77, and C (beginning Python and Java)

**package ****ESI**** {**
**   ****interface ****Vector**** {**
**      ****void ****axpy****(in ****Vector**** x, in double a);**
**      ****double ****dot****(in ****Vector**** x);**
**      ...**
**   ****};**
**   ****interface ****Matrix**** {**
**      ...**
**   ****};**
**};**

**SIDL****tools**

**library writer develops this**

**user runs this ...**

**... ****and gets these**

## Babel generates glue code

**SIDL interface****description**

**parser**

**analyzer**

**backend**

**f77**

**C**

**Python**

**C++**

**machine****configuration****database**

**XML repository****interface****description**

## Objects, Virtual Functions, RMI & Reference Counting: all from Babel

**Objects, Virtual Functions, RMI & Reference Counting: all from Babel**

**C**

**C++**

**f77**

**f90**

**Python**

**Java**

**Babel**

## C matrix example: IJMatrix

**HYPRE_IJMatrix      ij_A;**
**int *HYPRE_row_sizes;**
**HYPRE_ParCSRMatrix  parcsr_A;**
**ij_A = HYPRE_IJMatrixCreate( comm, first_local_row, **
**               ****last_local_row, first_local_col, last_local_col );**
**ierr += HYPRE_IJMatrixSetType( ij_A, HYPRE_PARCSR );**
**/* No reference to “parcsr” from this point on */**
**diag_sizes = hypre_CTAlloc(double, local_num_cols);**
**ierr += HYPRE_IJBuildMatrix_SetDiagOffdSizes( ij_A, **
**                 ****HYPRE_diag_sizes, HYPRE_offdiag_sizes );**
**ierr += HYPRE_BuildMatrix_Initialize( ij_A );**
**for (i=first_local_row; i<= last_local_row; i++)  {**
**   ****HYPRE_values = all_values[ i ];**
**   ****ierr += HYPRE_IJBuildMatrix_SetValues( ij_A, 1, **
**   ****HYPRE_row_sizes, HYPRE_ncols, HYPRE_col_inds, HYPRE_values );}**
**ierr += HYPRE_IJBuildMatrix_Assemble( ij_A );**
**ierr += HYPRE_IJBuildMatrix_GetObject( ij_A, &HYPRE_object );**

## Babel matrix example: IJMatrix

**Hypre_IJBuildMatrix Hypre_ij_A;**
**struct SIDL_int__array* Hypre_row_sizes;**
**Hypre_ParCSRMatrix  Hypre_parcsr_A = Hypre_ParCSRMatrix__create();**
**Hypre_ij_A = (Hypre_IJBuildMatrix) Hypre_ParCSRMatrix__cast( **
**   ****Hypre_parcsr_A, "Hypre.IJBuildMatrix");**
**/* No reference to “parcsr” from this point on */**
**ierr += Hypre_IJBuildMatrix_Create( Hypre_ij_A, comm, first_local_row, **
**               ****last_local_row, first_local_col, last_local_col );**
**Hypre_diag_sizes = SIDL_int__array_create( 1, lower, upper );**
**ierr += Hypre_IJBuildMatrix_SetDiagOffdSizes( Hypre_ij_A, **
**                 ****Hypre_diag_sizes, Hypre_offdiag_sizes );**
**ierr += Hypre_IJBuildMatrix_Initialize( Hypre_ij_A );**
**for (i=first_local_row; i<= last_local_row; i++)  {**
**  ****Hypre_values = SIDL_double__array_borrow( values, 1,**
**                          ****lower, upper, stride );**
**  ****ierr += Hypre_IJBuildMatrix_SetValues( Hypre_ij_A, 1, **
**   ****Hypre_row_sizes, Hypre_ncols, Hypre_col_inds, Hypre_values );}**
**ierr += Hypre_IJBuildMatrix_Assemble( Hypre_ij_A );**
**ierr += Hypre_IJBuildMatrix_GetObject( Hypre_ij_A, &Hypre_object );**

## Library implementation with Babel

**Write SIDL describing library in OO model**
**Run Babel tool to generate implementation skeletons in desired implementation language(s)**
**In C, for each class:**
**Fill in implementation.h file**
**Defines a single structure**
**Generally just a pointer or two to existing library structures if it was object-based **
**Fill in implementation.c file**
**One subroutine for each method**
**If desired, reimplement portions of library in terms of Babel-generated bindings**
**Allows OO polymorphism in implementation**

**Notes:**
All implementations do not have to be in the same language.

## Example of implementation task

- /* File:          Hypre_ParCSRMatrix_Impl.h */
- /* DO-NOT-DELETE splicer.begin(Hypre.ParCSRMatrix._includes)*/
- /* Put additional include files here... */
- #include "HYPRE_IJ_mv.h"
- #include "HYPRE.h"
- #include "utilities.h"
- /* DO-NOT-DELETE splicer.end(Hypre.ParCSRMatrix._includes)*/
- /*
-  * Private data for class Hypre.ParCSRMatrix
-  */
- struct Hypre_ParCSRMatrix__data {
-   /* DO-NOT-DELETE splicer.begin(Hypre.ParCSRMatrix._data)*/
-   /* Put private data members here... */
-   HYPRE_IJMatrix ij_A;
-   MPI_Comm *comm;
-   /* DO-NOT-DELETE splicer.end(Hypre.ParCSRMatrix._data) */
- };

- void impl_Hypre_ParCSRMatrix__ctor(
-   Hypre_ParCSRMatrix self){
-   /* DO-NOT-DELETE splicer.begin(Hypre.ParCSRMatrix._ctor)
-   /* Insert the implementation here... */
-    struct Hypre_ParCSRMatrix__data * data;
-    data = hypre_CTAlloc(struct Hypre_ParCSRMatrix__data);
-    data -> comm = NULL;
-    data -> ij_A = NULL;
-    Hypre_ParCSRMatrix__set_data( self, data );
-   /* DO-NOT-DELETE splicer.end(Hypre.ParCSRMatrix._ctor)*/
- }
- int32_t impl_Hypre_ParCSRMatrix_SetDiagOffdSizes(
-   Hypre_ParCSRMatrix self,
-   struct SIDL_int__array* diag_sizes,
-   struct SIDL_int__array* offdiag_sizes){
-   /* DO-NOT-DELETE splicer.begin(Hypre.ParCSRMatrix.SetDiagOffdSizes) */
-   /* Insert the implementation here... */
-    int ierr=0;
-    struct Hypre_ParCSRMatrix__data * data;
-    HYPRE_IJMatrix ij_A;
-    data = Hypre_ParCSRMatrix__get_data( self );
-     ij_A = data -> ij_A;
-     ierr = HYPRE_IJMatrixSetDiagOffdSizes( ij_A,
-        SIDLArrayAddr1(diag_sizes, 0 ), SIDLArrayAddr1(offdiag_sizes, 0) );
-     return( ierr );
-   /* DO-NOT-DELETE splicer.end(Hypre.ParCSRMatrix.SetDiagOffdSizes) */}

## Hypre’s OO architecture is two-tiered: generic interfaces and specific classes

- package Hypre {
- // -------------------------- Interfaces ---------------------------
- interface Vector {
-    int Clear ();
-    int Copy (in Vector x);
-    int Clone (out Vector x);
-    int Scale (in double a);
-    int Dot (in Vector x, out double d);
-    int Axpy (in double a, in Vector x);
- }
- interface ProblemDefinition{
-    int SetCommunicator (in opaque mpi_comm);
-    int Initialize ();
-    int Assemble ();
-    int GetObject ( out SIDL.BaseInterface A );
- }
- interface StructGridBuildMatrix extends ProblemDefinition
-    int SetGrid (in StructGrid grid );
-    int SetStencil (in StructStencil stencil );
-    int SetValues (in array<int> index, int in num_index,
-       in array<int> stencil_indices, in array<double>
-       values);
- }
- interface IJBuildMatrix extends ProblemDefinition {
-    int Create( in int ilower, in int iupper,
-       in int jlower, in int jupper );
-    int SetRowSizes( in array<int> sizes );
-    int SetValues( in int nrows, in array<int> ncols,
-    in array<int> rows, in array<int> cols, in
-       array<double>,values );
- interface Operator{
-    int Setup ();
-    int Apply (in Vector x, out Vector y);
-    int Compose( in Operator B, out Operator product );
- }
- interface Solver extends Operator{
-    int SetOperator (in Operator A);
-    int GetResidual (out Vector r);
- }
- interface CoefficientAccess{
-    int GetRow (in int row, out int size, out array<int>
-        col_ind, out array<double> values);
- }

- // -------------------------- Classes -------
- class StructMatrix implements-all
- StructuredGridBuildMatrix, Operator { };
- class ParCSRMatrix implements-all IJBuildMatrix,
-    Operator, CoefficientAccess;
- class StructSMG implements-all Solver { };
- class ParAMG implements-all Solver { };
- class Pilut implements-all Solver { };
- class ParaSAILS implements-all Solver { };
- class AMGe implements-all Solver { };
- class Jacobi implements-all Solver { };
- class PCG implements-all PreconditionedSolver { };
- class CGNR implements-all PreconditionedSolver { };
- class GMRES implements-all PreconditionedSolver { };
-  ** **

## Setup and use of solvers is largely the same (see Reference Manual for details)

**Create the solver**
**HYPRE_SolverCreate(MPI_COMM_WORLD, &solver);**
**Set parameters**
**HYPRE_SolverSetTol(solver, 1.0e-06);**
**Prepare to solve the system**
**HYPRE_SolverSetup(solver, A, b, x);**
**Solve the system**
**HYPRE_SolverSolve(solver, A, b, x);**
**Get solution info out via conceptual interface**
**HYPRE_StructVectorGetValues(struct_x, index, values);**
**Destroy the solver**
**HYPRE_SolverDestroy(solver);**

## Benefits of Babel for hypre

**No Hand F77 bindings, other languagues**
**Very hard to maintain by hand**
**Better for design **
**easy for discussion**
**impossible to mix implementation & interface**
**Eases interoperability**
**Forward compatibility with CCA, ESI, etc**

**Petsc/Hypre interop as part of TOPS program**
**Promote common interfaces to TOPS package**
**Automatic reference counting, QI, etc**
**Compromise between:**
**Wanting polymorphism and OO techniques**
**Preserves ANSI C developer familiarity**
**Allows other development languages**

## Getting the code

**The User’s Manual and Reference Manual can be downloaded directly**
**A form must be filled out prior to download.  ****This is just for our own records.**

**http://www.llnl.gov/CASC/hypre/**

## Our Websitehttp://www.llnl.gov/CASC/components
Alexandria (Component Repository)
Quorum (Online Voting)
Generic Parallel Redistribution

**Our Website****http://www.llnl.gov/CASC/components**
**Alexandria (Component Repository)**
**Quorum (Online Voting)**
**Generic Parallel Redistribution**

## This work was performed under the auspices of the U.S. Department of Energy by Lawrence Livermore National Laboratory under contract no. W-7405-Eng-48.

- UCRL-VG-140609

## Collaboration Objectives

**Babel side:**
**demonstrate Babel technology **
**feedback from library developers**
**Hypre side:**
**Automatically create Fortran bindings**
**Explore new designs **
**Object-Oriented **
**Component-Based**
**Integrate other software **
**C++ or F77**