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

Smith, Barry F. bsmith at mcs.anl.gov
Tue Jan 2 06:22:16 CST 2018


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 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.

  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