Skip to content

Commit

Permalink
Unify element activation, element death and moving interface
Browse files Browse the repository at this point in the history
Generalize the existing ActivateElementUserObjects, add ElementSubdomainModifiers, and fix some parallel bugs.

close idaholab#17100
  • Loading branch information
hugary1995 committed Feb 23, 2021
1 parent afbb850 commit 3cdb20c
Show file tree
Hide file tree
Showing 42 changed files with 1,121 additions and 3 deletions.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# CoupledVarThresholdElementSubdomainModifier

!syntax description /UserObjects/CoupledVarThresholdElementSubdomainModifier

## Overview

The `CoupledVarThresholdElementSubdomainModifier` can model

- Element death (with applications in ablation, fracture, etc.);
- Element activation (with applications in additive manufacturing, sintering, solidification, etc.);
- Moving interface (with applications in metal oxidation, phase transformation, melt pool, etc.).

The `CoupledVarThresholdElementSubdomainModifier` changes the element subdomain based on the given criterion. It also handles the corresponding

- Moving boundary/interface nodeset/sideset modification,
- Solution initialization, and
- Stateful material property initialization,

all of which are demonstrated using the following example.

Consider a unit square domain, and an auxiliary variable defined by the function $\phi(x,y,t) = (x-t)^2+y^2-0.5^2$. The function represents a signed-distance function of a circle of radius $0.5$ whose center is moving along the x-axis towards right.

Initially, the domain is decomposed by a vertical line $x=0.25$. The elements on the left side of the vertical line have subdomain ID of 1, and the elements on the right side have subdomain ID of 2. The `CoupledVarThresholdElementSubdomainModifier` is used to change the subdomain ID from 2 to 1 for elements within the circle.

## Reversible vs. irreversible modification

If the `CoupledVarThresholdElementSubdomainModifier` is applied onto the entire domain, and the parameter `complement_subdomain_id` is set to 2, then the subdomain ID of all elements outside the circle will be set to 2:

!listing test/tests/userobjects/element_subdomain_modifier/reversible.i start=[moving_circle] end=[] include-end=true

!media media/userobjects/esm_reversible.jpg style=float:center;width:100%; caption=The result of a reversible element subdomain modifier at three different time steps

However, in many applications, e.g. element death and activation, the equivalent movement of element subdomains is not reversible. In this case, omitting the parameter `complement_subdomain_id` will make the subdomain modification irreversible:

!listing test/tests/userobjects/element_subdomain_modifier/block_restricted.i start=[moving_circle] end=[] include-end=true

!media media/userobjects/esm_irreversible.jpg style=float:center;width:100%; caption=The result of an irreversible element subdomain modifier at three different time steps

## Moving boundary/interface nodeset/sideset modification

The change of element subdomains will alter the definition of certain sidesets and nodesets. The `CoupledVarThresholdElementSubdomainModifier` optionally takes the parameter `moving_boundary_name` to help modify the corresponding sideset/nodeset. If the boundary provided through the `moving_boundary_name` parameter already exists, the modifier will attempt to modify the provided sideset/nodeset whenever an element changes subdomain. If the boundary does not exist, the modifier will create a sideset and a nodeset with the provided name.

!media media/userobjects/esm_sideset.jpg style=float:center;width:100%; caption=The evolving sideset (green) at three different time steps

!media media/userobjects/esm_nodeset.jpg style=float:center;width:100%; caption=The evolving nodeset (green) at three different time steps

Nodal and integrated BCs can be applied on the moving boundary.

## Solution initialization

Depending on the physics, one may or may not want to initialize the solution when an element and its related nodes change subdomain.
The parameter `apply_initial_conditions` defaults to true and determines whether the initial conditions should be re-evaluated.

Suppose initially there is an auxiliary variable $u=1$ everywhere inside the domain, and the variable value in subdomain 1 (blue) doubles at each time step:

!listing test/tests/userobjects/element_subdomain_modifier/initial_condition.i start=[AuxVariables] end=[Executioner]

!media media/userobjects/esm_ic.jpg style=float:center;width:100%; caption=The auxiliary variable $u$ at three different time steps

## Stateful material property initialization

Similarly, all stateful material properties will be re-initialized when an element changes subdomain. Suppose initially the diffusivity is $0.5$ everywhere, and the diffusivity doubles at each time step:

!listing test/tests/userobjects/element_subdomain_modifier/stateful_property.i start=[Materials] end=[Executioner]

!media media/userobjects/esm_material.jpg style=float:center;width:100%; caption=The diffusivity at three different time steps

!syntax parameters /UserObjects/CoupledVarThresholdElementSubdomainModifier

!syntax inputs /UserObjects/CoupledVarThresholdElementSubdomainModifier
2 changes: 1 addition & 1 deletion framework/include/mesh/MooseMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ class MooseMesh : public MooseObject, public Restartable, public PerfGraphInterf
const std::string & getSubdomainName(SubdomainID subdomain_id);

/**
* This method returns a writable reference to a boundary name based on the id parameter
* This method sets the boundary name of the boundary based on the id parameter
*/
void setBoundaryName(BoundaryID boundary_id, BoundaryName name);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#pragma once

#include "ThresholdElementSubdomainModifier.h"

class CoupledVarThresholdElementSubdomainModifier : public ThresholdElementSubdomainModifier
{
public:
static InputParameters validParams();

CoupledVarThresholdElementSubdomainModifier(const InputParameters & parameters);

protected:
virtual Real computeValue() override;

private:
/// The coupled variable used in the criterion
const VariableValue & _v;
};
94 changes: 94 additions & 0 deletions framework/include/userobject/ElementSubdomainModifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#pragma once

#include "ElementUserObject.h"
#include "NonlinearSystemBase.h"
#include "AuxiliarySystem.h"

class ElementSubdomainModifier : public ElementUserObject
{
public:
static InputParameters validParams();

ElementSubdomainModifier(const InputParameters & parameters);

virtual void initialize() override;
virtual void execute() override;
virtual void threadJoin(const UserObject & /*uo*/) override{};
virtual void finalize() override;

protected:
virtual SubdomainID computeSubdomainID() = 0;

BoundaryID movingBoundaryID() const
{
if (!_moving_boundary_specified)
mooseError("no moving boundary specified");
return _moving_boundary_id;
}

const BoundaryName movingBoundaryName() const
{
if (!_moving_boundary_specified)
mooseError("no moving boundary specified");
return _moving_boundary_name;
}

ConstElemRange & movedElemsRange() const { return *_moved_elems_range.get(); }

ConstBndNodeRange & movedBndNodesRange() const { return *_moved_bnd_nodes_range.get(); }

std::shared_ptr<DisplacedProblem> _displaced_problem;

private:
void setMovingBoundaryName(MooseMesh & mesh);

void updateBoundaryInfo(MooseMesh & mesh, const std::vector<const Elem *> & moved_elems);

void recordNodeIdsOnElemSide(const Elem * elem,
const unsigned short int side,
std::set<dof_id_type> & node_ids);

void pushBoundarySideInfo(
MooseMesh & mesh,
std::unordered_map<processor_id_type, std::vector<std::pair<dof_id_type, unsigned int>>> &
elems_to_push);

void pushBoundaryNodeInfo(
MooseMesh & mesh,
std::unordered_map<processor_id_type, std::vector<dof_id_type>> & nodes_to_push);

void buildMovedElemsRange();
void buildMovedBndNodesRange();

/**
* Initialize solutions for the nodes
*/
void setSolutionForMovedNodes(SystemBase & sys);

std::vector<const Elem *> _moved_elems;
std::vector<const Elem *> _moved_displaced_elems;
std::set<dof_id_type> _moved_nodes;

std::unique_ptr<ConstElemRange> _moved_elems_range;
std::unique_ptr<ConstBndNodeRange> _moved_bnd_nodes_range;

const bool _apply_ic;

/// Whether a moving boundary name is provided
const bool _moving_boundary_specified;

/// The name of the moving boundary
BoundaryName _moving_boundary_name;

/// The Id of the moving boundary
BoundaryID _moving_boundary_id;
};
38 changes: 38 additions & 0 deletions framework/include/userobject/ThresholdElementSubdomainModifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#pragma once

#include "ElementSubdomainModifier.h"
#include "MooseEnum.h"

class ThresholdElementSubdomainModifier : public ElementSubdomainModifier
{
public:
static InputParameters validParams();

ThresholdElementSubdomainModifier(const InputParameters & parameters);

protected:
virtual SubdomainID computeSubdomainID() override;

/// Compute the value used in the criterion
virtual Real computeValue() = 0;

private:
/// Threshold to modify the element subdomain ID
const Real _threshold;

/// Criterion type
const enum class CriterionType { Below, Equal, Above } _criterion_type;

/// Target subdomain ID
const SubdomainID _subdomain_id;
const SubdomainID _complement_subdomain_id;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "CoupledVarThresholdElementSubdomainModifier.h"

#include "libmesh/quadrature.h"

registerMooseObject("MooseApp", CoupledVarThresholdElementSubdomainModifier);

InputParameters
CoupledVarThresholdElementSubdomainModifier::validParams()
{
InputParameters params = ThresholdElementSubdomainModifier::validParams();
params.addRequiredCoupledVar("coupled_var",
"Coupled variable whose value is used in the criterion");
return params;
}

CoupledVarThresholdElementSubdomainModifier::CoupledVarThresholdElementSubdomainModifier(
const InputParameters & parameters)
: ThresholdElementSubdomainModifier(parameters), _v(coupledValue("coupled_var"))
{
}

Real
CoupledVarThresholdElementSubdomainModifier::computeValue()
{
Real avg_val = 0;

for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp)
avg_val += _v[qp];
avg_val /= _qrule->n_points();

return avg_val;
}

0 comments on commit 3cdb20c

Please sign in to comment.