Step 3: Introduction to MOOSE Objects

In this step, MOOSE Objects, and the purposes they serve, will be introduced. To demonstrate this concept, consider the same problem discussed in Step 2 and explore the basics of how the Laplace equation was developed in the form of a C++ class.

Anyone who feels that they need to review C++ and/or object-oriented programming are highly encouraged to do so before proceeding with the remainder of this tutorial. The C++ Programming References provides some helpful starting points for this.

MOOSE Objects

The core framework of MOOSE is built around systems, where each system uses object-oriented programming to provide a well-defined interface for using the system via C++ inheritance. In short, the framework provides a set of base class(es) for each system. These base classes are specialized using custom C++ objects within an application to achieve the desired behavior for the problem.

In practice, all objects in MOOSE and within an application being developed follow the same pattern. Thus, only a broad understanding is required to begin working with MOOSE. For example, consider the ADDiffusion object contained within the framework as shown in Listing 1 and Listing 2.

Listing 1: Header file that declares the ADDiffusion object.


#pragma once

#include "ADKernelGrad.h"

class ADDiffusion : public ADKernelGrad
{
public:
  static InputParameters validParams();

  ADDiffusion(const InputParameters & parameters);

protected:
  virtual ADRealVectorValue precomputeQpResidual() override;
};
(framework/include/kernels/ADDiffusion.h)

Listing 2: Source file that defines the ADDiffusion object.


#include "ADDiffusion.h"

registerMooseObject("MooseApp", ADDiffusion);

InputParameters
ADDiffusion::validParams()
{
  auto params = ADKernelGrad::validParams();
  params.addClassDescription("Same as `Diffusion` in terms of physics/residual, but the Jacobian "
                             "is computed using forward automatic differentiation");
  return params;
}

ADDiffusion::ADDiffusion(const InputParameters & parameters) : ADKernelGrad(parameters) {}

ADRealVectorValue
ADDiffusion::precomputeQpResidual()
{
  return _grad_u[_qp];
}
(framework/src/kernels/ADDiffusion.C)

This class can be used to demonstrate the form in which all objects created in a MOOSE-based application will follow. First, begin with the declarations in the header file. Foremost, all class headers should begin with:

#pragma once

This line ensures that the compiler does not include the contents of this file more then once.

Next, the base class that is being inherited from is included. For the ADDiffusion object, the base class is ADKernelGrad:

#include "ADKernelGrad.h"

Finally, the class being created is defined. This definition contains three main components common to all objects that will be created within an application:

  1. a static validParams function for creating input syntax,

      static InputParameters validParams();
    

  2. a constructor that is given the same name as the MooseObject that owns it and that consumes InputParameters objects, and

      ADDiffusion(const InputParameters & parameters);
    

  3. one or more methods that are overridden to provide the custom functionality desired for the application.

      virtual ADRealVectorValue precomputeQpResidual() override;
    
    commentnote:The method(s) overridden differ with each system.

    Each system within MOOSE has one or more base class objects. These objects are specialized by overriding one or more methods. The method required to be overridden varies with the base class. Please refer to the documentation of each system for more information.

The source (.C) file simply defines the functionality of these three components. As the tutorial progresses, the basic structure and syntax described here will be seen regularly and the purpose and use of methods, like validParams(), will become more clear.

Demonstration

Recall, from Step 2, that the foregoing BVP is governed by the following PDE:

(1)

It is necessary to acknowledge that PDEs must be expressed in a certain format to be able to solve them with MOOSE. That is, assuming that the natural boundary condition, , is satisfied, then the weak form of Eq. (1) is

(2)

In the next step, exactly what is meant by the terminology, "weak form," will be explained, so do not worry about this just yet.

Source Code

A MooseObject that was capable of solving the Laplace equation was required for Step 2 and it was demonstrated that ADDiffusion provides this capability. To understand how it works, consider Listing 2, and notice that the term of the integrand in Eq. (2) was coded:

ADRealVectorValue
ADDiffusion::precomputeQpResidual()
{
  return _grad_u[_qp];
}

Here, the term in Eq. (2), is automatically handled by the precomputeQpResidual() method of the ADKernelGrad base class, so there was no need to include this term manually.

schooltip:MOOSE does a lot already.

Before developing a new MooseObject in an application, confirm that something like it does not already exist. All MOOSE applications posses the full capability of the framework and physics modules (more on this later), in addition to their own capabilities.