UserObject System
The UserObject system is developing and running custom algorithms that may not fit well within any other system in MOOSE. Examples include complex calculations that may result values that don't associate in a one to one manner with elements, nodes, or sides. Perhaps your user object produces values based on height in your domain or based on groups of related elements (not necessarily associated with subdomains or other static mesh features). Often these calculations may result in custom data structures that can be managed by the developer.
The UserObject system is the basis for the Postprocessor system. The only difference being that Postprocessors have an additional interface for returning values and corresponding managed storage within the framework for retrieving those values through well-defined interfaces \(PostprocessorInterface\).
User-defined APIs
One benefit of the UserObject system is that it is designed with user-defined APIs in mind. UserObjects can and should define additional public methods that may be used to retrieve data computed by the UserObject. The UserObjectInterface is templated so that an object that depends on a specific type of UserObject may retrieve that specific type of UserObject and use the interface without the use of dynamic casts.
Types of UserObjects
GeneralUserObject: "execute" is called once on each execution flag.
NodalUserObject: "execute" is called for each node within the mesh on each execution flag.
ElementalUserObject: "execute" is called for each element within the mesh on each execution flag.
InternalSideUserObject: "execute" is called for each side, that is not on a boundary, within the mesh on each execution flag.
SideUserObject: "execute" is called for each side, that is on a boundary, within the mesh on each execution flag. If the boundary is internal within the mesh, only variables, material properties, etc. at the primal side of the boundary are available.
InterfaceUserObject: "execute" is called for each side, that is on an internal boundary, within the mesh on each execution flag. Variables, material properties, etc. at both the primary and the secondary side of the internal boundary are available.
DomainUserObject: this object is capable of executing all the operations of a ElementUserObject, InternalSideUserObject, SideUserObject and InterfaceUserObject.
MortarUserObject: "execute" is called for each mortar segment element corresponding to the secondary-primary mortar interface pairing on each execution flag
Execution order
Within an execution stage set by the execute_on parameter, user objects are executed in the following order:
residualSetup/jacobianSetupIf the current
execute_onflag is eitherEXEC_LINEARorEXEC_NONLINEARtheresidualSetupandjacobianSetupare called respectively in the following orderfor objects derived from
ElementUserObject,SideUserObject,InternalSideUserObjectInterfaceUserObject, andDomainUserObject.for objects derived from
NodalUserObject.for objects derived from
ThreadedGeneralUserObject.for objects derived from
GeneralUserObject.
initializeis called for objects derived fromElementUserObject,SideUserObject,InternalSideUserObjectInterfaceUserObject, andDomainUserObjectin that order.All active local elements are iterated over and objects derived from
ElementUserObject,SideUserObject,InternalSideUserObjectInterfaceUserObject, andDomainUserObjectare executed on elements, boundaries attached to the element, internal sides between elements, and on subdomain changes, in that order. The order within each type group is determined through dependency resolution.threadJoinandfinalizeare called in the following orderfor objects derived from
SideUserObjectfor objects derived from
InternalSideUserObjectfor objects derived from
InterfaceUserObjectfor objects derived from
ElementUserObjectfor objects derived from
DomainUserObject
initializeis called for objects derived fromNodalUserObject.NodalUserObjectare looped over all local nodes and executed on each node. On each node, the order is determined through dependency resolution.threadJoinandfinalizeare called forNodalUserObjects.initializeis called for objects derived fromThreadedGeneralUserObject.executeis called for objects derived fromThreadedGeneralUserObjectin a threaded way.threadJoinandfinalizeare called forThreadedGeneralUserObjects.initialize,execute, andfinalizeare called in that order for eachGeneralUserObject(which in turn are ordered through dependency resolution within the set of applicableGeneralUserObjects).
For additional control over the user object execution order every user object has a execution_order_group parameter of type integer. This parameter can be used to force multiple execution rounds of the above order, so it effectively supersedes all the ordering described above. All objects with the same execution_order_group parameter value are executed in the same round, and groups with a lower number are executed first. The default execution_order_group is 0 (zero). Negative values can be specified to force user object execution before the default group, and positive values can be uses to create execution groups that run after the default group. Execution order groups apply to all execute_on flags specified for a given object.
Restartable Data
Since UserObjects often create and store large data structures, the developer of a UserObject should consider whether or not those data structures needs to be declared as "restartable". Knowing whether or not a data structure should be declared restartable is straight-forward: If the information in a data structure is expected to persist across time steps, it must be declared as restartable. Conversely, if the data in a data structure is recomputed at each invocation of the UserObject, no action is necessary. See restart_recover.md for more information.