• The UserObject system provides data and calculation results to other MOOSE objects.
• All Postprocessors are UserObjects that compute a single scalar value.
• Therefore, a UserObject can be thought of as a more generic Postprocessor with more functionality.
• UserObjects define their own interface, which other MOOSE objects can call to retrieve data.
• Just like Postprocessors, there are 4 types of UserObjects:
• ElementUserObject - perform evaluations on each element.
• NodalUserObject - perform evaluations on each node.
• SideUserObject - perform evaluations on each side.
• GeneralUserObject - a generic object that can do "anything" while providing a common interface for use by other MOOSE objects.
• For example, a GeneralUserObject might read in a large data set, hold it in memory, and provide an interface for Material classes to access the data.

# UserObject Anatomy

All UserObjects must override the following functions:

virtual void initialize();

• Called just one time before beginning the UserObject calculation.
• Useful for resetting data structures.
virtual void execute();

• Called once on each geometric object (element, node or side) or just one time per calculation for a GeneralUserObject.
• This is where you actually do your calculation, read data, etc.

virtual void threadJoin(const UserObject & y);

• During threaded execution this function is used to "join" together calculations generated on different threads.
• In general you need to cast y to a const reference of your type of UserObject, then extract data from - y} and add it to the data in "this" object.
• Note, this is not required for a GeneralUserObject because it is not threaded.
virtual void finalize();

• The very last function called after all calculations have been completed.
• In this function, the user must take all of the small calculations performed in execute() and do some last operation to get the final values.
• Be careful to do parallel communication where necessary to ensure all processors compute the same values.

• A UserObject defines its own interface by defining const accessor functions.
• When another MOOSE object uses a UserObject, they do so by calling these accessor functions.
• For example, if a UserObject is computing the average value of a variable on every block in the mesh, it might provide a function like:
Real averageValue(SubdomainID block) const;

• Another MOOSE object using this UserObject would then call averageValue() to get the result of the calculation.
• Take special note of the const at the end of the function declaration!
• This means the function cannot modify any member variables of the object, and is required for UserObject accessors functions.

# Using a UserObject

• Any MOOSE object can retrieve a UserObject in a manner similar to retrieving a Function.
• Generally, it is a good idea to take the name of the UserObject to use from the input file:
template<>
InputParameters validParams<BlockAverageDiffusionMaterial>()
{
InputParameters params = validParams<Material>();
return params;
}


A UserObject comes through as a const reference of the UserObject type. So, in your object:

const BlockAverageValue & _block_average_value;


The reference is set in the initialization list of your object by calling the templated getUserObject() method:

BlockAverageDiffusionMaterial::BlockAverageDiffusionMaterial(const InputParameters & parameters) :
Material(parameters),
_block_average_value(getUserObject<BlockAverageValue>("block_average_userobject"))
{}


Use the reference by calling some of the interface functions defined by the UserObject:

_diffusivity[_qp] = 0.5 * _block_average_value.averageValue(_current_elem->subdomain_id());


Example 20