MOOSE Newsletter (October 2018)

MOOSEDocs

We are continuing to improve documentation for MOOSE, and our new website recently went live. All MOOSE Pull Requests which change or add tests now require additional language which details the tests' purpose, the GitHub issue(s) associated with the test, and any relevant design/documentation for the feature being tested. This additional documentation serves two purposes. First, it is useful when trying to understand what a test does, and second, it is also being used as software life-cycle documentation.

There is also ongoing work being done to convert "MOOSEDown" into LaTeX, and there will be more announcements on this task in the coming weeks and months.

ParsedFunction Improvement

The ParsedFunction can now take another function as a parameter - similarly to the way it can take a scalar value or a Postprocessor value. An example syntax follows:


[./a_fn]
  type = ParsedFunction
  value = sin(x)
[../]
[./parsed_fn]
  type = ParsedFunction
  value = '4*sqrt(a)'
  vars = 'a'
  vals = 'a_fn'
[../]

Obtaining the values from a nested function honors the time and space position of the evaluating function, i.e. in our example a_fn will be evaluated at the same time and space position as parsed_fn function.

App Object/Action Registration Changes

Previously, a MOOSE-based application's main App class contained several registration methods, e.g. registerObjects(), associateSyntax(), registerExecFlags(), etc., along with a special extern "C" function paired with each one. We are moving away from these functions in favor of a more consolidated, simple approach. Applications should now perform all registration (objects, syntax, actions, exec flags) and special setup inside a static registerAll() member function:


static void registerAll(Factory & f, ActionFactory & af, Syntax & s);

Applications will no longer be expected to register MOOSE framework objects directly - nor perform any registration for transitive dependencies. If your FooApp application depends on the heat_conduction module and BarApp, then your registerAll() function should look something like this:


void
FooApp::registerAll(Factory & f, ActionFactory & af, Syntax & s)
{
  Registry::registerObjectsTo(f, {"FooApp"});
  Registry::registerActionsTo(af, {"FooApp"});

  ModulesApp::registerAll(f, af, s);
  BarApp::registerAll(f, af, s);
}

extern "C" void
FooApp__registerAll(Factory & f, ActionFactory & af, Syntax & s)
{
  FooApp::registerAll(f, af, s);
}

All registration-related code in your App's constructor should be removed in favor of a single call: registerAll(_factory, _action_factory, _syntax);. Each application is only responsible to call registerAll() for its direct dependencies. If BarApp depends on the fluid_properties module or BazApp - then those registrations should occur automatically from calls within BarApp::registerAll() (no need for you to do that in FooApp).

Please add the registerAll() function to all of your applications/modules. If your application/module has no dependent applications, then you can just remove/delete the old functions (including the FooApp__register[Bla] functions) in favor of the new registerAll(). If your application/module does have downstream dependencies, then you will need to keep the old functions (please add deprecation warnings via the mooseDeprecated macro) until the downstream dependencies have been updated. Deprecation messages/warnings have been added to the old registerObjects(), etc. functions in MOOSE and its modules.

note

The registerApps() and FooApp__registerApps() functions are still required, and should remain unchanged.

If your application has a test app (e.g. FooTestApp) then this is the new convention:


...

FooTestApp::FooTestApp(const InputParameters & parameters) : MooseApp(parameters)
{
  FooTestApp::registerAll(
      _factory, _action_factory, _syntax, getParam<bool>("allow_test_objects"));
}

void
FooTestApp::registerAll(Factory & f, ActionFactory & af, Syntax & s, bool use_test_objs)
{
  FooApp::registerAll(f, af, s);
  if (use_test_objs)
  {
    Registry::registerObjectsTo(f, {"FooTestApp"});
    Registry::registerActionsTo(af, {"FooTestApp"});

    // ... register test action syntax, etc.
  }
}

...

Matrix assembly improvement

In MOOSE, a CouplingMatrix object is used to indicate which variables are coupled to one another. Checking all possible (i,j) variable pairs for coupling works well when the number of variables is small, but the setup time scales like O(N^2) in the number of variables, N. We have addressed this issue by using a different CouplingMatrix API which allows us to cache the coupled variable pairs in O(1) time, and then loop over only those variable pairs when assembling the global matrix.

SmoothMesh MeshModifier

The SmoothMesh MeshModifier can now be used to perform a user-defined number of "Laplace" mesh smoothing iterations on any mesh. Roughly speaking, the Laplace smoothing algorithm works by moving each node to the element-weighted centroid of the neighboring nodes. Multiple iterations tend to "converge" to a final configuration on convex domains, but may run into issues on non-convex domains. The smoothing operations can be subdomain-restricted, and in general boundary nodes are not moved. In the future, we plan to extend this capability to include other types of mesh smoothing algorithms.

ElementQualityAux AuxKernel

The ElementQualityAux AuxKernel was added. This AuxKernel calls the Elem::quality() function and builds an elemental AuxVariable field which can be used for visualization purposes. There are a number of different element quality metrics that can be employed; by default we use the so-called SHAPE quality metric. For more information about element quality metrics, see P. Knupp, "Algebraic mesh quality metrics for unstructured initial meshes," Finite Elements in Analysis and Design 39, 2003, p. 217-241, Sections 5.2 and 5.3. Low-quality elements such as nearly-degenerate quads/hexes and sliver tets/tris can negatively influence matrix conditioning and solution accuracy, and generally should be avoided if possible.

Add FEProblem-derived objects via Actions

Custom Problems are advanced MOOSE objects which are useful in several different scenarios, including coupling to external codes (ExternalProblem) and solving eigenvalue problems (EigenProblem). Prior to this new capability, using a custom Problem required users to declare a Problem block in their input file with a custom type = field, and this process has now been streamlined. Application developers can now also use an Action to add the derived FEProblem object programmatically. This makes input files more flexible and simpler, and allows the type of Problem chosen to depend on other information in the input file. This way, users can switch back and forth between different problem types with only minor modifications to their input file.

A test of this new capability has been added in action_custom_fe_problem_test.i. This test uses the dummy CreateSpecialProblemAction to add an FEProblem-derived class of type MooseTestProblem. The new capability is accessed in the test via the following input file syntax:


[TestProblem]
  name = 'MOOSE Action Test problem'
[]

Application developers can follow the pattern established by CreateSpecialProblemAction to make it easier to use custom problem types in their own codes.

Bug fixes

  • A bug in NodalNormalBC which prevented derived classes from correctly using the computed nodal normals was fixed in commit 4910bfa8.