xx EllBase

EllBase

Gerd Lanfermann

Date

Abstract

Infrastructure for standard elliptic solvers

1 Introduction

Following a brief introduction to the elliptic solver interfaces provided by EllBase, we explain how to add a new class of elliptic equations and how to implement a particular solver for any class. We do not discuss the individual elliptic solvers here since these are documented in their own thorns.

1.1 Purpose of Thorn Thorn EllBase provides the basic functionality for

registering a class of elliptic equations

register a solver for any particular class

The solvers are called by the user through a unique interface, which calls the required elliptic solver for a class using the name under which the solver routine is registered.

EllBase itself defines the elliptic classes

flat: EllxLinFlat

solves a linear elliptic equation in flat space:

metric: EllxLinMetric

solves a linear elliptic equation for a given metric:

conformal metric: EllxLinConfMetric

solves a linear elliptic equation for a given metric and a conformal factor:

generic: solves a linear elliptic equation by passing the stencil functions. There is support for a maximum of 27 stencil functions (). This is not implemented, yet.

2 Technical Specification Implements: ellbase

Inherits from: grid

Tested with thorns:

CactusElliptic/EllTest,
CactusWave/IDScalarWaveElliptic

3 ToDo

Add more standard equation classes.

The method for passing boundary conditions into the elliptic solvers has not fully consolidated. We have some good ideas on what the interface should look like, but the implementation will take some time. If you are worried about BCs, please contact me.

4 Solving an elliptic equation

EllBase provides a calling interface for each of the elliptic classes implemented. As a user you must provide all information needed for a particular elliptic class. In general this will include

the gridfunction(s) to solve for the coefficient matrix or source terms

information on termination tolerances

the name of the solver to be used

Motivation: At a later stage you might want to compile with a different solver for this elliptic class: just change the name of the solver in your elliptic interface call. If somebody improves a solver you have been using, there is no need for you to change any code on your side: the interface will hide all of that. Another advantage is that your code will compile and run, even though certain solvers are not compiled in. In this case, you will have to do some return value checking to offer alternatives.

4.1 EllxLinFlat

xxcallxEll_LinFlatSolver(ierr,xcctkGH,xphi_gfi,xM_gfi,xN_gfi,
x.xxxxxxxxxxxxxxxxxxxxxxxAbsTol,xRelTol,x"solvername")

xxierrx=xEll_LinFlatSolver(GH,xphi_gfi,xM_gfi,xN_gfi,
xxxxxxxxxxxxxxxxxxxxxxxxxxxAbsTol,xRelTol,x"solvername");

Argument List: ierr: return value: “0” for success. cctkGH: the Fortran “pointer” to the grid function hierachy. GH: the C pointer to the grid hierarchy, type: pGH *GH. phixgif: the integer index of the grid function to solve for. Mxgfi: the integer index of the grid function which holds . Nxgif: the integer index of the grid function which holds . AbsTol: array of size : holding absolute tolerance values for the , , norm. Check if the solver side supports these norms. The interface side does not guarantee that these norms are actually implemenented by a solver. See the section on norms: 6. RelTol: array of size : holding relative tolerance factors for the , , . Check if the solver side supports these norms. The interface side does not guarantee that these norms are actually implemenented by a solver. See the section on Norms: 6.

"solvername": the name of a solver, which is registered for a particular equation class. How does one find out the names? Either check the documentation of the elliptic solvers or check for registration infomation outputted by a cactus at runtime.

Example use in Fortran, as used in the WaveToy arrangement: CactusWave/IDScalarWave:

cxxxxxWexderivexthexgridxfunctionxindiciesxfromxthexnamesxofxthe
cxxxxxgridxfunctions:
xxxxxxcallxCCTK_VarIndexx(Mcoeff_gfi,x"idscalarwaveelliptic::Mcoeff")
xxxxxxcallxCCTK_VarIndexx(Ncoeff_gfi,x"idscalarwaveelliptic::Ncoeff")
xxxxxxcallxCCTK_VarIndexx(phi_gfi,xxxx"wavetoy::phi")
cxxxxxLoadxthexAbsolutexTolerancexArrays
xxxxxxAbsTol(1)=1.0d-5
xxxxxxAbsTol(2)=1.0d-5
xxxxxxAbsTol(3)=1.0d-5
cxxxxxLoadxthexRelativexTolerancexArrays,xtheyxarexnot
cxxxxxusedxhere:x-1
xxxxxxRelTol(1)=-1
xxxxxxRelTol(2)=-1
xxxxxxRelTol(3)=-1
cxxxxxCallxtoxellipticxsolver,xnamedx``sor''
xxxxxxcallxEll_LinFlatSolver(ierr,xcctkGH,
xxxxx.xxxxxphi_gfi,xMcoeff_gfi,xNcoeff_gfi,xAbsTol,xRelTol,
xxxxx.xxxxx"sor")
cxxxxxDoxsomexerrorxchecking,xaxcallxtoxanotherxsolver
cxxxxxcouldxbexcodedxhere
xxxxxxifx(ierr.ne.0)xthen
xxxxxxxxxcallxCCTK_WARN(0,"Requestedxsolverxnotxfoundx/xsolvexfailed");
xxxxxxendif

4.2 EllxLinMetric

xxcallxEll_LinMetricSolver(ierr,xcctkGH,xMetric_gfi,
x.xxxxxxxxxxxxxphi_gfi,xM_gfi,xN_gfi,
x.xxxxxxxxxxxxxxxxxxxxxxxxxAbsTol,xRelTol,x"solvername")

xxierrx=xEll_LinMetricSolver(GH,xMetric_gfi,
xxxxxxxxxxxxxxxxphi_gfi,xM_gfi,xN_gfi,
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxAbsTol,xRelTol,x"solvername");

Argument List: ierr: return value: “0” success cctkGH: the Fortran “pointer” to the grid function hierachy. GH: the C pointer to the grid hierarchy, type: pGH *GH Metricxgfi: array of size , containing the index components of the metric : , , , , , . The order is important. phixgif: the integer index of the grid function so solver for. Mxgfi: the integer index of the grid function which holds . Nxgif: the integer index of the grid function which holds AbsTol: array of size : holding absolute tolerance values for the , , Norm. Check, if the solver side supports these norms.The interface side does not guarantee that these norms are actually implemenented by a solver. See the section on Norms: 6. RelTol: array of size : holding relative tolerance factors for the , , . Check, if the solver side supports these norms. The interface side does not guarantee that these norms are actually implemenented by a solver. See the section on Norms: 6.

"solvername": the name of a solver, which is registered for a particular equation class. How to find out the names ? Either check the documentation of the elliptic solvers or check for registration infomation outputted by a cactus at runtime.

4.3 EllxLinConfMetric

xxcallxEll_LinMetricSolver(ierr,xcctkGH,xMetricPsi_gfi,
x.xxxxxxxxxxxxxphi_gfi,xM_gfi,xN_gfi,
x.xxxxxxxxxxxxxxxxxxxxxxxxxAbsTol,xRelTol,x"solvername")

xxierrx=xEll_LinMetricSolver(GH,xMetricPsi_gfi,
xxxxxxxxxxxxxxxxphi_gfi,xM_gfi,xN_gfi,
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxAbsTol,xRelTol,x"solvername");

Argument List: ierr: return value: “0” success cctkGH: the Fortran “pointer” to the grid function hierachy. GH: the C pointer to the grid hierarchy, type: pGH *GH MetricPsixgfi: array of size , containing the grid function index of the metric components and the grid function index of the conformal factor : , , , , , , . The order is important. phixgif: the integer index of the grid function so solver for. Mxgfi: the integer index of the grid function which holds . Nxgif: the integer index of the grid function which holds AbsTol: array of size : holding absolute tolerance values for the , , Norm. Check, if the solver side supports these norms.The interface side does not guarantee that these norms are actually implemenented by a solver. See the section on Norms: 6. RelTol: array of size : holding relative tolerance factors for the , , . Check, if the solver side supports these norms. The interface side does not guarantee that these norms are actually implemenented by a solver. See the section on Norms: 6.

"solvername": the name of a solver, which is registered for a particular equation class. How to find out the names ? Either check the documentation of the elliptic solvers or check for registration infomation outputted by a cactus at runtime.

5 Extending the elliptic solver class

EllBase by itself does not provide any elliptic solving capabilities. It merely provides the registration structure and calling interface.

The idea of a unified calling interface can be motivated as follows: assume you a have elliptic problem which conforms to one of the elliptic classes defined in EllBase.

5.1 Registration Mechanism

Before a user can successfully apply a elliptic solver to one of his problems, two things need to be done by the author who programs the solver.

Register a class of elliptic equations Depending on the elliptic problem This provides the unique calling, the solving routines needs to have specific input data. The interface, which is called by the user, has to reflect these arguments. EllBase already offers several of these interfaces, but if you need to have a new one, you can provide your own.

Register a solver for a particular elliptic equation class Once a class of elliptic equations has been made available as described above, the author can now register solvers for that particular class. Later a user will access the solver calling the interface with the arguments needed for the elliptic class and a name, under which a solver for this elliptic problem has been registered.

The registration process is part of the authors thorn, not part of EllBase. There is no need to change code in EllBase. Usually, a author of solver routines will register the routines that register an elliptic equation class and/or an elliptic solver in the STARTUP timebin. If a author registers both, class and solver, you must make sure, that the elliptic class is registered before the solver registration takes place.

5.2 EllBase Programming Guide

Here we give a step by step guide on how to implement an new elliptic solver class, its interface and provide a solver for this class. Since some of the functionality needed in the registration code can only be achieved in C, a basic knowledge of C is helpful.

Assumption:

The elliptic equation class will be called “SimpleEllClass”: it will be flat space solver, that only takes the coefficient matrix : Note that this solver class is already provided by EllBase.

The name of the demonstration thorn will be “ThornFastSOR”. Since I will only demonstrate the registration principle and calling structure, I leave it to the interested reader to write a really fast SOR solver.

The solver for this elliptic equation will be called “FastSORxsolver” and will be written in Fortran. Since Fortran cannot be called directly by the registration mechanism, we need to have C wrapper function “FastSORxwrapper”.

Elliptic class declaration: SimpleEllThorn/src/SimpleEllxClass.c

Elliptic solver interface: src/SimpleEllxInterface.c

#includex``cctk.h''
#includex``cctk_Parameters.h''
#includex``cctk_FortranString.h''
#includex``StoreNamedData.h''
staticxpNamedDatax*SimpleEllSolverDB;
voidxEll_SimpleEllSolverRegistry(voidx(*solver_func),xconstxcharx*solver_name)
{
xxStoreNamedData(&SimpleEllSolverDB,solver_name,(void*)solver_func);
}

The routine above registers the solver (or better the function pointer of the solver routine “*solvexfunc”) for the equation class SimpleEllClass by the name solverxname in the database SimpleEllSolverDB. This database is declared in statement static pNamedData....

Next, we write our interface in the same file ./SimpleEllxInterface.c:

voidxEll_SimpleEllSolver(cGHx*GH,xintx*FieldIndex,xintx*MIndex,
xxxxxxxxxxxCCTK_REALx*AbsTol,xCCTK_REALx*RelTol,
xxxxxxxxxxxxxxxxxxxxxxxxxconstxcharx*solver_name)x{
/*xprototypexforxthexequationxclassxwrapper:
xxxgridxhierarchy(*GH),xID-numberxofxfieldxtoxsolvexforx(*FieldIndex),
xxxtwoxarraysxofxsizexthreexholdingxconvergencexinformationx(*AbsTol,x*RelTol)
*/
xxvoidx(*fn)(cGHx*GH,xintx*FieldIndex,xintx*AbsTol,xintx*RelTol);
xx/*xderivexthexfunctionxnamexfromxthexrequestedxnamexandxhopexitxisxtherex*/
xxfnx=x(void(*))xGetNamedData(LinConfMetricSolverDB,solver_name);
xxifx(!fn)xCCTK_WARN(0,''Ell_SimpleEllSolver:xCannotxfindxsolver!x``);
xx/*xNowxthatxwexhavexthexfunctionxpointerxtoxourxsolver,xcallxthe
xxxxxsolverxandxpassxthroughxallxthexnecessaryxargumentsx*/
xxfn(xGH,xFieldIndex,xMIndex,xAbsTol,xRelTol);
}

The interface EllxSimpleEllSolver is called from the user side. It receives a pointer to the grid hierarchy, the ID-number of the field to solver for, two arrays which the used upload with convergence test info, and finally, the name of the solver the user want to employ *solverxname. Note: all these quantities are referenced by pointers, hence the “*”.

Within the interface, the solverxname is used to get the pointer to function which was registered under this name. Once the function is known, it called with all the arguments passed to the interface.

To allow calls from Fortran, the interface in C needs to be “wrapped”. (This wrapping is different from the one necessary to make to actual solver accessible by the elliptic registry).

/*xFortranxwrapperxforxthexroutinexEll_SimpleEllSolverx*/
voidxCCTK_FCALLxCCTK_FNAME(Ell_SimpelEllSolver)
xxxxx(cGHx*GH,xintx*FieldIndex,xintx*MIndex,
xxxxxintx*AbsTol,xintx*RelTol,xONE_FORTSTRING_ARG)x{
xxONE_FORTSTRING_CREATE(solver_name);
xx/*xCallxthexinterfacex*/
xxEll_SimpleEllSolver(GH,xFieldIndex,xMIndex,xAbsTol,xRelTol,xsolver_name);
xxfree(solver_name);
}

Elliptic solver:./src/FastSORxsolver.F

Here we show the first lines of the Fortran code for the solver:

xxxxxxsubroutinexFastSOR_solver(_CCTK_ARGUMENTS,
xxxxx.xxxMlinear_lsh,Mlinear,
xxxxx.xxxvar,
xxxxx.xxxabstol,reltol)
xxxxxximplicitxnone
xxxxxx_DECLARE_CCTK_ARGUMENTS
xxxxxxDECLARE_CCTK_PARAMETERS
xxxxxxINTEGERxCCTK_Equals
xxxxxxINTEGERxMlinear_lsh(3)
xxxxxxCCTK_REALxMlinear(Mlinear_lsh(1),Mlinear_lsh(2),Mlinear_lsh(3))
xxxxxxCCTK_REALxvar(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
x
xxxxxxINTEGERxMlinear_storage
cxxxxxWexhavexnoxstoragexforxMxifxtheyxarexofxsizexonexinxeachxdirection
xxxxxxifx((Mlinear_lsh(1).eq.1)x.and.
xxxxx.xxx(Mlinear_lsh(2).eq.1)xx.and.
xxxxx.xxx(Mlinear_lsh(3).eq.1))xthen
xxxxxxxxxMlinear_storage=0
xxxxxxelse
xxxxxxxxxMlinear_storage=1
xxxxxxendif

This Fortran solver receives the following arguments: the “typical” CCTKxARGUMENTS: xCCTKxARGUMENTS, the size of the coefficient matrix: Mlinearxlsh, the coefficient matrix Mlinear, the variable to solve for: var, and the two arrays with convergence information.

In the declaration section, we declare: the cctk arguments, the Mlinear size array, the coefficient matrix, by the 3-dim. size array, the variable to solve for. Why do we pass the size of Mlinear explicitly and do not use the cctkxlsh (processor local shape of a grid function) as we did for var ? The reason is the following: while we can expect the storage of var to be on for the solve, there is no reason (in a more general elliptic case) to assume, that the coefficient matrix has storage allocated, perhaps it is not needed at all! In this case, we have to protect ourself against referencing empty arrays. For this reason, we also employ the flag

Mlinearxstorage.

Elliptic solver wrapper:./src/FastSORxwrapper.c

The Fortran solver can not be used within the elliptic registry directly. Instead the Fortran code is called through a wrapper:

voidxFastSOR_wrapper(cGHx*GH,xintx*FieldIndex,xintx*MIndex,
xxxxxxxintx*AbsTol,intx*RelTol)x{
xxCCTK_REALx*Mlinear=NULL,x*var=NULL;
xxintxMlinear_lsh[3];
xxintxi;
xxvarx=x(CCTK_REAL*)xCCTK_VarDataPtrI(GH,0,*FieldIndex);
xxifx(*MIndex>0)xMlinearxxx=x(CCTK_REAL*)xCCTK_VarDataPtrI(GH,0,*MIndex);

xxifx(GH->cctk_dim>3)
xxxxCCTK_WARN(0,''Thisxellipticxsolverximplementationxdoesxnotxdoxdimension>3!'');
xxforx(i=0;i<GH->cctk_dim;i++)x{
xxxxif((*MIndex<0))xxMlinear_lsh[i]=1;
xxxxelsexxxxxxxxxxxxxMlinear_lsh[i]=GH->cctk_lsh[i];
xx}
xx/*xcallxthexfortranxroutinex*/
xxCCTK_FNAME(SimpleEll_Solver)(_PASS_CCTK_C2F(GH),
xxxxxxxxxMlinear_lsh,xMlinear,xvar,xx
xxAbsTol,xRelTol);
}

The wrapper FastSORxwrapper takes these arguments: the indices of the field to solve for (FieldIndex) and the coefficient matrix (MIndex), the two arrays containing convergence information (AbsTol, RelTol). In the body of the program we provide two CCTKxREAL pointers to the data section of the field to solver (var, Mlinear) by means of GetxVarDataPtrI. For Mlinear, we only do this, if the index is non-negative. A negative index is a signal by the user that the coefficient matrix has no storage allocated.(For more general elliptic equation cases, e.g. no source terms.) To make this information of a possibly empty matrix available to Fortran, we load a 3-dim. and pass this array through to Fortran. See discussion above.

Elliptic solver startup: ./src/Startup.c The routine below in Startup.c performs the registration of our solver wrapper FastSORxwrapper under the name “fastsor” for the elliptic class “EllxSimpleEll”. We do not register with the solver interface EllxSimpleEllSolver directly, but with the class. In Startup,c we have:

voidxFastSOR_register(cGHx*GH)x{
xx/*xprotoypexofxthexsolverxwrapper:x*/
xxvoidxFastSOR_wrapper(cGHx*GH,xintx*FieldIndex,xintx*MIndex,
xxxxxxxxxxxxxxxxxxxxxxxintx*AbsTol,xint*RelTol);
xxEll_RegisterSolver(FastSOR_wrapper,''fastsor'',''Ell_SimpleEll'');
}

Note that more solver registration code could be put here (registration for other classes, etc.)

Elliptic solver scheduling: schedule.ccl We schedule the registration of the fast SOR solver at CCTKxBASE, by this time, the elliptic class EllxSimpleEll has already been registered.

     schedulexFastSOR_registerxatxCCTK_INITIAL
     {
     xxLANG:C
     }x``Registerxthexfastxsorxsolver''

6 Norms

7 Parameters

11 ellipticxverbose10 Scope: restricted01  KEYWORD

11 Description: elliptic verbosity

11 Range 10 01 Default: no
11 yes  10 be verbose in elliptic
11 no  10 silence in elliptic
11 debug  10 even more verbose in elliptic

11

8 Interfaces

General Implements:

ellbase

Adds header: EllBase.h EllxDBstructure.h

9 Schedule This section lists all the variables which are assigned storage by thorn CactusElliptic/EllBase. Storage can either last for the duration of the run (Always means that if this thorn is activated storage will be assigned, Conditional means that if this thorn is activated storage will be assigned for the duration of the run if some condition is met), or can be turned on for the duration of a schedule function.

Storage NONE

Scheduled Functions

CCTKxSTARTUP x ellxregisterbaseeqtypes x register the standard elliptic classes x

11 x 11 Language: 11 c
11 x 11 Type:  11 function