[petsc-dev] How to pass user data to a registered PC (PCRegister) ?

Smith, Barry F. bsmith at mcs.anl.gov
Tue Jan 2 07:50:02 CST 2018


  

> On Jan 2, 2018, at 7:47 AM, Franck Houssen <franck.houssen at inria.fr> wrote:
> 
> I'll try to fetch/pull the git clone: maybe there is a reg on the code level I am on.

  Unlikely.

   I'm afraid you need to use the debugger and slog through the call. It seems you are doing things ok so why this happens I cannot explain. We use this paradigm everywhere with options in PETSc and it always works so I am totally lost as to why it fails for you.

   Barry

> 
> ----- Mail original -----
>> De: "Barry F. Smith" <bsmith at mcs.anl.gov>
>> À: "Franck Houssen" <franck.houssen at inria.fr>
>> Cc: "For users of the development version of PETSc" <petsc-dev at mcs.anl.gov>
>> Envoyé: Mardi 2 Janvier 2018 13:22:16
>> Objet: Re: [petsc-dev] How to pass user data to a registered PC (PCRegister) ?
>> 
>> 
>> static PetscErrorCode PCSetFromOptions_Jacobi(PetscOptionItems
>> *PetscOptionsObject,PC pc)
>> {
>>  PC_Jacobi      *jac = (PC_Jacobi*)pc->data;
>>  PetscErrorCode ierr;
>>  PetscBool      flg;
>>  PCJacobiType   deflt,type;
>> 
>>  PetscFunctionBegin;
>>  ierr = PCJacobiGetType(pc,&deflt);CHKERRQ(ierr);
>>  ierr = PetscOptionsHead(PetscOptionsObject,"Jacobi options");CHKERRQ(ierr);
>>  ierr = PetscOptionsEnum("-pc_jacobi_type","How to construct diagonal
>>  matrix","PCJacobiSetType",PCJacobiTypes,(PetscEnum)deflt,(PetscEnum*)&type,&flg);CHKERRQ(ierr);
>>  if (flg) {
>>    ierr = PCJacobiSetType(pc,type);CHKERRQ(ierr);
>>  }
>>  ierr = PetscOptionsBool("-pc_jacobi_abs","Use absolute values of diagaonal
>>  entries","PCJacobiSetUseAbs",jac->useabs,&jac->useabs,NULL);CHKERRQ(ierr);
>>  ierr = PetscOptionsTail();CHKERRQ(ierr);
>>  PetscFunctionReturn(0);
>> }
>> 
>> Note how PetscOptionsHead() is called with the argument PetscOptionsObject
> 
> I do call PetscOptionsHead(PetscOptionsObject, ...);
> 
>> which is passed in from above. My guess is that you don't
>> call it with this argument? You would get behavior you describe if you don't.
>> Please send your REAL setupfromoptions_mypc() not just pseudo code.
>> 
> 
> #define SETERRABT(msg) SETERRABORT(PETSC_COMM_WORLD,PETSC_ERR_ARG_NULL,msg)
> 
> static PetscErrorCode setUpGenEOPCFromOptions(PetscOptionItems * PetscOptionsObject, PC pcPC) {
>  // Get the context.
> 
>  if (!pcPC) SETERRABT("GenEO preconditioner is invalid");
>  geneoContext * gCtx = (geneoContext *) pcPC->data;
>  if (!gCtx) SETERRABT("GenEO preconditioner without context");
> 
>  // Check arguments.
> 
>  PetscErrorCode pcRC = PetscOptionsHead(PetscOptionsObject, "GenEO options");
>  CHKERRQ(pcRC);
>  pcRC = PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "GenEO options", "GenEO options");
>  CHKERRQ(pcRC);
> 
>  PetscBool pcHasOpt = PETSC_FALSE;
>  PetscInt nbArgs = 2;
>  char *args[2];
>  pcRC = PetscOptionsStringArray("-geneo_lvl", "GenEO levels", "GenEO levels", args, &nbArgs, &pcHasOpt);
>  CHKERRQ(pcRC);
>  if (pcHasOpt) {
>    ...
> 
> 
>>  Barry
>> 
>> 
>> 
>> 
>>> On Jan 2, 2018, at 5:04 AM, Franck Houssen <franck.houssen at inria.fr> wrote:
>>> 
>>> ----- Mail original -----
>>>> De: "Barry F. Smith" <bsmith at mcs.anl.gov>
>>>> À: "Franck Houssen" <franck.houssen at inria.fr>
>>>> Cc: "For users of the development version of PETSc"
>>>> <petsc-dev at mcs.anl.gov>
>>>> Envoyé: Dimanche 31 Décembre 2017 23:41:42
>>>> Objet: Re: [petsc-dev] How to pass user data to a registered PC
>>>> (PCRegister) ?
>>>> 
>>>> 
>>>> 
>>>>> On Dec 31, 2017, at 8:40 AM, Franck Houssen <franck.houssen at inria.fr>
>>>>> wrote:
>>>>> 
>>>>> Seems finally, I got it to work.
>>>>> To get the options to work I had to call PetscOptionsBegin/End
>>>>> after/before
>>>>> PetscOptionsHead/Tail which is not what is done in the jacobi example: is
>>>>> this the right way to go ?
>>>> 
>>>> Something is wrong.
>>> 
>>> I felt there was something wrong !...
>>> 
>>>> PetscOptionsBegin/end are called in PCSetFromOptions()
>>>> that is suppose to wrap YOUR PCSetFromOptions_mypc().
>>> 
>>> OK, sounds logical, that's how I expected things to be done. That's why I
>>> was suspicious: what worked should not !...
>>> 
>>> I believed maybe the problem was connected to the fact that I do NOT use
>>> compose function, but, according to Matt's explanation, I would say no:
>>> the use of PetscComposeFunction seems independent from the
>>> PCSetFromOptions_mypc problem.
>>> 
>>> Note: in my case, I believe I do not really need PetscCompose, I just need
>>> one (regular) function to initialize specific stuffs needed in my_pc (at
>>> least for a start). I can go to PetscCompose later if it turns out to be
>>> relevant (that's how I understand this).
>>> 
>>>> Perhaps you are
>>>> calling PCSetFromOptions_mypc directly which you should never do.
>>> 
>>> No, I don't call PCSetFromOptions_mypc directly.
>>> 
>>>> Your PCCreate_mypc() should stick the function pointer for
>>>> PCSetFromOptions_mypc into the ops table like it does PCApply_mypc etc.
>>>> Then you just directly use PCSetFromOptions.
>>> 
>>> create_mpc(PC pc) { // CB for PCRegister
>>> ...
>>> pcPC->ops->setfromoptions = setupfromoptions_mypc;
>>> ...
>>> }
>>> 
>>> static PetscErrorCode setupfromoptions_mypc(PetscOptionItems *
>>> PetscOptionsObject, PC pcPC) {
>>> ...
>>> PetscOptionsHead()
>>> PetscOptionsBegin()
>>> PetscOptionsStringArray("-mypc_opt", ..., flag)
>>> cout << "debug " << flag << endl;
>>> PetscOptionsEnd()
>>> PetscOptionsTail()
>>> }
>>> 
>>> I got called on setupfromoptions_mypc when I call PCSetUpFromOptions().
>>> 
>>> If I let PetscOptionsBegin/End, it looks like I read in the "correct"
>>> option data base, I get (cout) : "debug 1" (-my_opt is read)
>>> 
>>> If I comment PetscOptionsBegin/End, seems I read an incorrect (empty ?)
>>> option data base, I get (cout) : "debug 0"
>>> 
>>> Looks weird even if it's not blocking for now (I know there is problem but
>>> I can by pass it)
>>> 
>>>> 
>>>>  Barry
>>>> 
>>>>> 
>>>>> Franck
>>>>> 
>>>>> PetscErrorCode PCSetFromOptions_mypc(PetscOptionItems *
>>>>> PetscOptionsObject,
>>>>> PC pcPC) {
>>>>> PetscOptionsHead
>>>>> PetscOptionsBegin
>>>>> ... // PetscOptionsStringArray
>>>>> PetscOptionsEnd
>>>>> PetscOptionsTail
>>>>> 
>>>>> 
>>>>> ----- Mail original -----
>>>>>> De: "Franck Houssen" <franck.houssen at inria.fr>
>>>>>> À: "Barry F. Smith" <bsmith at mcs.anl.gov>
>>>>>> Cc: "For users of the development version of PETSc"
>>>>>> <petsc-dev at mcs.anl.gov>
>>>>>> Envoyé: Dimanche 31 Décembre 2017 15:01:43
>>>>>> Objet: Re: [petsc-dev] How to pass user data to a registered PC
>>>>>> (PCRegister) ?
>>>>>> 
>>>>>> Using PCSHELL means calling:
>>>>>> - PCShellSetSetUp, PCShellSetApply, PCShellSetDestroy to set callbacks.
>>>>>> - PCShellSetContext/PCShellGetContext to get/set context in callbacks.
>>>>>> 
>>>>>> To go from PCSHELL to PCRegister, one need to:
>>>>>> - #include <petsc/private/pcimpl.h> // Access to PC data/struct.
>>>>>> - Set callbacks with pc->ops->...
>>>>>> - NO more use ANY shell methods (context, name), but, use pc->data
>>>>>> instead.
>>>>>> - call PCRegister.
>>>>>> 
>>>>>> Correct ? Did I miss something ?
>>>>>> 
>>>>>> Seems I get things to work (without compose function).
>>>>>> 
>>>>>> The last problem I have is in the options: options are passed to
>>>>>> PetscInitialize but not found in the database (I mimic'ed the jacobi
>>>>>> example). Is there specific related to this ?
>>>>>> 
>>>>>> 
>>>>>> ----- Mail original -----
>>>>>>> De: "Franck Houssen" <franck.houssen at inria.fr>
>>>>>>> À: "Barry F. Smith" <bsmith at mcs.anl.gov>
>>>>>>> Cc: "For users of the development version of PETSc"
>>>>>>> <petsc-dev at mcs.anl.gov>
>>>>>>> Envoyé: Samedi 30 Décembre 2017 17:12:09
>>>>>>> Objet: Re: [petsc-dev] How to pass user data to a registered PC
>>>>>>> (PCRegister) ?
>>>>>>> 
>>>>>>> Don't get the link. I'll try first with independent function (no
>>>>>>> compose)
>>>>>>> and
>>>>>>> see if this can work at least for a start.
>>>>>>> 
>>>>>>> Franck
>>>>>>> 
>>>>>>> ----- Mail original -----
>>>>>>>> De: "Barry F. Smith" <bsmith at mcs.anl.gov>
>>>>>>>> À: "Franck Houssen" <franck.houssen at inria.fr>
>>>>>>>> Cc: "For users of the development version of PETSc"
>>>>>>>> <petsc-dev at mcs.anl.gov>
>>>>>>>> Envoyé: Vendredi 29 Décembre 2017 17:55:30
>>>>>>>> Objet: Re: [petsc-dev] How to pass user data to a registered PC
>>>>>>>> (PCRegister) ?
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>>> On Dec 29, 2017, at 9:03 AM, Franck Houssen <franck.houssen at inria.fr>
>>>>>>>>> wrote:
>>>>>>>>> 
>>>>>>>>> OK, on the highway now (bad ssh !), I'll try to check this out.
>>>>>>>>> 
>>>>>>>>> ----- Mail original -----
>>>>>>>>>> De: "Barry F. Smith" <bsmith at mcs.anl.gov>
>>>>>>>>>> À: "Franck Houssen" <franck.houssen at inria.fr>
>>>>>>>>>> Cc: "For users of the development version of PETSc"
>>>>>>>>>> <petsc-dev at mcs.anl.gov>
>>>>>>>>>> Envoyé: Jeudi 28 Décembre 2017 18:21:48
>>>>>>>>>> Objet: Re: [petsc-dev] How to pass user data to a registered PC
>>>>>>>>>> (PCRegister) ?
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>>> On Dec 28, 2017, at 10:34 AM, Franck Houssen
>>>>>>>>>>> <franck.houssen at inria.fr>
>>>>>>>>>>> wrote:
>>>>>>>>>>> 
>>>>>>>>>>> ----- Mail original -----
>>>>>>>>>>>> De: "Barry F. Smith" <bsmith at mcs.anl.gov>
>>>>>>>>>>>> À: "Franck Houssen" <franck.houssen at inria.fr>
>>>>>>>>>>>> Cc: "For users of the development version of PETSc"
>>>>>>>>>>>> <petsc-dev at mcs.anl.gov>
>>>>>>>>>>>> Envoyé: Jeudi 28 Décembre 2017 16:43:16
>>>>>>>>>>>> Objet: Re: [petsc-dev] How to pass user data to a registered PC
>>>>>>>>>>>> (PCRegister) ?
>>>>>>>>>>>> 
>>>>>>>>>>>> 
>>>>>>>>>>>> The register is for a new type of PC of which can have many
>>>>>>>>>>>> instantiations
>>>>>>>>>>>> at the same time.
>>>>>>>>>>> 
>>>>>>>>>>> OK, I didn't get that that way ! I was looking for a way to plug
>>>>>>>>>>> "my"
>>>>>>>>>>> pc
>>>>>>>>>>> at
>>>>>>>>>>> the command line this way: -pc_type my_pc.
>>>>>>>>>>> I already call PCSetType(pc, PCSHELL) and PCShellSetName(pc,
>>>>>>>>>>> "my_pc"):
>>>>>>>>>>> maybe this already enables "-pc_type shell" or "-pc_type my_pc"...
>>>>>>>>>>> And
>>>>>>>>>>> I
>>>>>>>>>>> didn't know it ! :D I'll try that.
>>>>>>>>>>> 
>>>>>>>>>>> I was looking for a way to integrate "my" (external) pc as any
>>>>>>>>>>> other
>>>>>>>>>>> regular/existing petsc pc (bjacobi, ...) like a kind of plugin but
>>>>>>>>>>> still
>>>>>>>>>>> integrated to the cmd line: I believed PCRegister was meant for
>>>>>>>>>>> that.
>>>>>>>>>> 
>>>>>>>>>> Indeed it is exactly what it is meant for.  Please try to follow my
>>>>>>>>>> recipe
>>>>>>>>>> and let us know when you get stuck.
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>>> Not sure if this is actually possible/enabled by the API.
>>>>>>>>>>> 
>>>>>>>>>>>> For example
>>>>>>>>>>>> 
>>>>>>>>>>>> PCRegister("mypctype",mypc_create);
>>>>>>>>>>>> 
>>>>>>>>>>>> KSPCreate(&ksp1);
>>>>>>>>>>>> KSPCreate(&ksp2);
>>>>>>>>>>>> 
>>>>>>>>>>>> KSPGetPC(ksp1,&pc1);
>>>>>>>>>>>> KSPGetPC(ksp2,&pc2);
>>>>>>>>>>>> 
>>>>>>>>>>>> You don't want pc1 and pc2 to have the same dof multiplicities,
>>>>>>>>>>>> domain
>>>>>>>>>>>> intersections etc since they are associated with completely
>>>>>>>>>>>> different
>>>>>>>>>>>> linear systems and presumably meshes etc.
>>>>>>>>>>>> 
>>>>>>>>>>>> 
>>>>>>>>>>>> Presumably you want each of pc1, pc2, to have their own version
>>>>>>>>>>>> of
>>>>>>>>>>>> the
>>>>>>>>>>>> data so you need to stick it directly in the PC, for example
>>>>>>>>>>>> 
>>>>>>>>>>>> PCMypcSetDOFMultiplicities(pc1,stuff);
>>>>>>>>>>>> PCMypcSetDOFMultiplicities(pc2,otherstuff);
>>>>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> OK, I must provide/implement PCMypcSetDOFMultiplicities (add data to
>>>>>>>>> pc
>>>>>>>>> context) besides mypc_create: sounds logical.
>>>>>>>>> Is this OK if PCMypcSetDOFMultiplicities is independent from
>>>>>>>>> mypc_create
>>>>>>>>> ?
>>>>>>>>> I guess yes.
>>>>>>>>> 
>>>>>>>>> From what I remember/understand, I got lost here: from the jacobi
>>>>>>>>> example,
>>>>>>>>> mypc_create looks to be supposed (?) to call some kind of
>>>>>>>>> Petsc*ComposeFunction to associate PCMypcSetDOFMultiplicities to the
>>>>>>>>> pc
>>>>>>>>> (correct ?)... But, in the jacobi example, PCJacobiGetUseAbs_Jacobi
>>>>>>>>> is
>>>>>>>>> associated to PCJacobiGetUseAbs_C...
>>>>>>>> 
>>>>>>>> the _C name is a string name that is used by PETSc to "find" the
>>>>>>>> correct
>>>>>>>> function pointer which is PCJacobiGetUseAbs_Jacobi. There is no
>>>>>>>> _C function.
>>>>>>> 
>>>>>>> ?!
>>>>>>> 
>>>>>>>> 
>>>>>>>>> Which turns out not to be implemented according to git grep ?! Got
>>>>>>>>> lost
>>>>>>>>> here (and looked for a way to pass user data directly to PCRegister):
>>>>>>>>> is
>>>>>>>>> PCMypcSetDOFMultiplicities supposed to be "attached/composed" or
>>>>>>>>> independent from the pc ?
>>>>>>>> 
>>>>>>>> composed.
>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>>> git grep PCJacobiGetUseAbs_C
>>>>>>>>> src/ksp/pc/impls/jacobi/jacobi.c:  ierr =
>>>>>>>>> PetscObjectComposeFunction((PetscObject)pc,"PCJacobiGetUseAbs_C",PCJacobiGetUseAbs_Jacobi);CHKERRQ(ierr);
>>>>>>>>> src/ksp/pc/impls/jacobi/jacobi.c:  ierr =
>>>>>>>>> PetscUseMethod(pc,"PCJacobiGetUseAbs_C",(PC,PetscBool*),(pc,flg));CHKERRQ(ierr);
>>>>>>>>> 
>>>>>>>>> Sorry, for the short answer. Hope I succeeded to be clear enough.
>>>>>>>> 
>>>>>>>> Just copy jacobi.c and start converting it over to your names and
>>>>>>>> needs
>>>>>>>> and you'll see it is actually really straightforward and not as
>>>>>>>> complicated as you think it is.
>>>>>>>> 
>>>>>>>> Barry
>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>>>> You write as many of these Set() functions as you need for your
>>>>>>>>>>>> PCtype.
>>>>>>>>>>>> You
>>>>>>>>>>>> store the data inside the PC_Mypc data structure you create with
>>>>>>>>>>>> mypc_create(). Look at PCCreate_Jacobi() and PCJacobiSetType for
>>>>>>>>>>>> the
>>>>>>>>>>>> pattern.
>>>>>>>>>>>> 
>>>>>>>>>>>> Barry
>>>>>>>>>>>> 
>>>>>>>>>>>> 
>>>>>>>>>>>>> On Dec 28, 2017, at 9:34 AM, Franck Houssen
>>>>>>>>>>>>> <franck.houssen at inria.fr>
>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>> 
>>>>>>>>>>>>> How to pass user data to a registered PC (PCRegister) ?
>>>>>>>>>>>>> 
>>>>>>>>>>>>> At first, I expected the signature would be "PetscErrorCode
>>>>>>>>>>>>> PCRegister(const char sname[],PetscErrorCode (*function)(PC, void
>>>>>>>>>>>>> *))"
>>>>>>>>>>>>> but
>>>>>>>>>>>>> it turns out to be "PetscErrorCode PCRegister(const char
>>>>>>>>>>>>> sname[],PetscErrorCode (*function)(PC))"
>>>>>>>>>>>>> 
>>>>>>>>>>>>> I try to integrate a PC that needs A but also other informations
>>>>>>>>>>>>> (dof
>>>>>>>>>>>>> multiplicities, domain intersections that the user must provide).
>>>>>>>>>>>>> I
>>>>>>>>>>>>> guess
>>>>>>>>>>>>> I can get A with PCGetOperators in the setup callback of the PC.
>>>>>>>>>>>>> But
>>>>>>>>>>>>> still
>>>>>>>>>>>>> not sure how to pass the other informations if I get to use
>>>>>>>>>>>>> PCRegister.
>>>>>>>>>>>>> I
>>>>>>>>>>>>> looked a few examples in the bitbucket (jacobi:
>>>>>>>>>>>>> src/ksp/ksp/examples/tutorials/ex12.c and
>>>>>>>>>>>>> src/ksp/pc/impls/jacobi/jacobi.c
>>>>>>>>>>>>> + SOR: src/ksp/pc/impls/sor/sor.c)... But didn't get any real
>>>>>>>>>>>>> relevant
>>>>>>>>>>>>> answer and feel a bit lost among the numerous pc !...
>>>>>>>>>>>>> 
>>>>>>>>>>>>> The idea is: for now I use PCSetType(pc, PCSHELL) and
>>>>>>>>>>>>> PCShellSetContext
>>>>>>>>>>>>> with a context who knows the extra needed informations which is
>>>>>>>>>>>>> "not
>>>>>>>>>>>>> so
>>>>>>>>>>>>> handy" (that's OK as for now I am both the user and the PC
>>>>>>>>>>>>> provider).
>>>>>>>>>>>>> I'd
>>>>>>>>>>>>> like to package this in a more convenient way (a unique and
>>>>>>>>>>>>> "simple"
>>>>>>>>>>>>> call
>>>>>>>>>>>>> to PCRegister) to decouple the user from the PC machinery.
>>>>>>>>>>>>> 
>>>>>>>>>>>>> Franck



More information about the petsc-dev mailing list