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.
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 (test/tests/problems/action_custom_fe_problem/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.