I never liked, and never understood, the business of
PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGAMGSetProcEqLim_C",NULL));
a large list of functions that match was composed in earlier when an object's
type is destroyed.
And now I see this horrific -checkfunctionlist that got into the CI.
Side note: I think it is a mistake to add much of anything to the
.gitlab-ci.yml file about options for tests. The net effect of them is that no
one can (reasonably) run, at home, the same tests as the CI trivially. They
have to hunt around and look for options in the .gitlab-ci.yml that they may
want to add somewhere when they run the test harness. This type of thing I
believe belongs in the test harness infrastructure so people running make test
get the same tests as the CI does, not in the .gitlab-ci.yml file. I have
removed some in the past and will continue to remove them when possible. Satish
likes it because it is easy to do and he lets it happen, I'm too lazy to notice
that someone is adding something there so it grows again.
Back to the main topic. Why don't we just destroy the obj->qlist always when
the object's type is destroyed? Then one needs not worry about getting the
exact list into each type destroy function.
Is it for fear that the user may have put other functions on the PetscObject,
that are not related to the object's specific type and we don't want them
destroyed? Or some other reason?
I think we should get rid of this horrible need to manually remove the function
pointers. If needed, one way to do it would be to have two qlists for each
object or to somehow mark the implementation functions in some way and only
remove those? For example, note the naming convention ClassTypeXXX
PCGAMGSetProc... when destroying a type we could remove all composed functions
that start with ClassType. For example the block of code (that appears in many
places)
/* Destroy the previous private PC context */
if (pc->ops->destroy) {
PetscCall((*pc->ops->destroy)(pc));
pc->ops->destroy = NULL;
pc->data = NULL;
}
could be a function that cleans up the qlist and resets the destroy and data.
Say
PetscObjectDestroyType(PetscObject obj)
if obj->hdr.destroytype {
PetscFunctionListPurge(obj->list,objectname+typename)
obj->hdr.destroytype = NULL
obj->hdr.data = NULL
}
This would be a good thing to do anyways since almost all PETSc objects have a
type destroy and type data already, best to get them in the unified base class,
less code duplication for each new PETSc object.