# [petsc-users] Howto evaluate function on grid

Klaus Zimmermann klaus.zimmermann at physik.uni-freiburg.de
Tue Feb 8 10:52:01 CST 2011

```Hi Barry,

thanks for your response. I guess my code excerpt wasn't very good, nor
was my description. My apologies.

The evaluation in more details goes like this:
Depending on the coordinates x and y (and only on them) I calculate 4
vectors S1,...,S4.
I have a constant matrix C in the appctx. The three quantities I am
interested in are then:

1) u1 = (x+y)*VecTDot(S1, MatMult(C, S2))
2) u2 = u1/(x+y) + (x+y)*VecTDot(S3, MatMult(C, S2))
3) u3 = u1/(x+y) + (x+y)*VecTDot(S1, MatMult(C, S4))

With this (hopefully better) description let me answer to your points
below individually.
On 02/08/2011 05:29 PM, Barry Smith wrote:
> On Feb 8, 2011, at 10:16 AM, Klaus Zimmermann wrote:
>
>> Dear all,
>>
>> I want to evaluate a function on a grid. Right now I have some custom code (see the end of this message).
>> I am now thinking of rewriting this using more PETSC facilities because in the future we want to extend the
>> program to higher dimensions and also unstructured grids.
>     There is little similarity and little chance of code reuse between using a structured grid and an unstructured grid at the level of your function evaluations. So if you truly want to have a structured grid version and unstructured you should just have different FormFunctions for them.
This is why I hoped to reuse code for the unstructured version: As long
as I can call a method with coordinates and context I am fine.
I don't really need any solving. Do I still need different FormFunctions?

>> As I understand it now there are several
>> candidates in PETSC for doing this:
>>
>> 1) PF
>> 2) DALocalFunction
>     Using the "local" function approach with DMMGSetSNESLocal() is just a way of hiding the DAVecGetArray() calls from the function code and is good when you have simple FormFunctions that do no rely on other vectors beside the usual input and output vectors. In your example below I do not understand why you have the input and output vectors inside the appctx, usually they are the input and output arguments to the formfunction set with SNESSetFunction() or DMMGSetSNES()
I agree. This is mostly because I didn't understand the concepts so well
at the time I wrote this code and one of the reasons why I would like to
refactor.
In my case there should in principle be three output vectors. All the
facilities I have seen in petsc only deal with a single output vector.
Is this correct?
Of course there is an obvious mapping, but I would prefer to keep the
vectors apart because that way it is easier to deal with the parallel
layout.

>> 3) FIAT (?)
>>
>> Could you please advise on what should be used?
>> An additional problem is that several distinct functions should be evaluated at the same time due to the
>> due to the reuse of intermediate results.
>
>     Are these functions associated with different SNES solvers or is the composition of these "several distinct functions" that defines the equations you are solving with PETSc? If the later then you just need to write either a single function that computes everything or have some smart use of inline to get good performance even with different functions.
I am not really using any solving at the moment. Please let me know if
you need more detail.

Thanks again,
Klaus

>     Barry
>
>> Any help is appreciated!
>> Thanks in advance,
>> Klaus
>>
>> ------------------8<------------------8<------------------8<------------------8<------------------8<--------------
>>
>> PetscErrorCode EvaluatePsiAndGradPsi(AppCtx *user) {
>>   PetscErrorCode ierr;
>>   PetscInt i, j, cxs, cxm, cys, cym;
>>   PetscScalar **lpsi;
>>   Vec gc;
>>   DACoor2d **coors;
>>   DA cda;
>>   ierr = DAGetCoordinateDA(user->zGrid,&cda);CHKERRQ(ierr);
>>   ierr = DAGetCoordinates(user->zGrid,&gc);CHKERRQ(ierr);
>>   ierr = DAVecGetArray(cda, gc,&coors);CHKERRQ(ierr);
>>   ierr = DAGetCorners(cda,&cxs,&cys, PETSC_NULL,&cxm,&cym, PETSC_NULL);CHKERRQ(ierr);
>>
>>   ierr = DAVecGetArray(user->zGrid, user->psi,&lpsi);CHKERRQ(ierr);
>>   for(i=cys; i<cys+cym; i++) {
>>     for(j=cxs; j<cxs+cxm; j++) {
>>       PetscReal x = PetscRealPart(coors[i][j].x-coors[i][j].y),
>>     y = PetscRealPart(coors[i][j].y);
>>       if(x>=0) {
>>     ierr = EvaluatePsiAndGradPsi(user, x, y,
>> &(lpsi[i][j]),
>>       }
>>     }
>>   }