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

Franck Houssen franck.houssen at inria.fr
Tue Jan 2 08:15:25 CST 2018


----- 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 14:50:02
> Objet: Re: [petsc-dev] How to pass user data to a registered PC (PCRegister) ?
> 
> 
>   
> 
> > 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.

OK, I'll do that ! For now, calling Begin/End is this only by-pass I have.

> 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