Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #include "NodeValueAtXFEMInterface.h" 11 : #include "MooseVariableFE.h" 12 : #include "XFEM.h" 13 : #include "InterfaceMeshCutUserObjectBase.h" 14 : #include "libmesh/parallel_algebra.h" 15 : #include "libmesh/parallel.h" 16 : 17 : registerMooseObject("XFEMApp", NodeValueAtXFEMInterface); 18 : 19 : InputParameters 20 24 : NodeValueAtXFEMInterface::validParams() 21 : { 22 24 : InputParameters params = GeneralUserObject::validParams(); 23 48 : params.addRequiredParam<VariableName>( 24 : "variable", "The name of the variable that this UserObject operates on"); 25 48 : params.addParam<UserObjectName>( 26 : "interface_mesh_cut_userobject", 27 : "Name of InterfaceMeshCutUserObject that provides cut locations to this UserObject."); 28 48 : params.addRequiredParam<VariableName>( 29 : "level_set_var", "The name of level set variable used to represent the interface"); 30 24 : params.addClassDescription("Obtain field values and gradients on the interface."); 31 24 : return params; 32 0 : } 33 : 34 12 : NodeValueAtXFEMInterface::NodeValueAtXFEMInterface(const InputParameters & parameters) 35 : : GeneralUserObject(parameters), 36 12 : _mesh(_subproblem.mesh()), 37 12 : _var(&_subproblem.getVariable(_tid, parameters.get<VariableName>("variable"))), 38 12 : _level_set_var_number( 39 12 : _subproblem.getVariable(_tid, parameters.get<VariableName>("level_set_var")).number()), 40 24 : _system(_subproblem.getSystem(getParam<VariableName>("level_set_var"))), 41 24 : _solution(*_system.current_local_solution.get()) 42 : { 43 12 : } 44 : 45 : void 46 60 : NodeValueAtXFEMInterface::initialize() 47 : { 48 120 : _pl = _mesh.getPointLocator(); 49 180 : _xfem = MooseSharedNamespace::dynamic_pointer_cast<XFEM>(_fe_problem.getXFEM()); 50 60 : if (_xfem == nullptr) 51 0 : mooseError("Problem casting to XFEM in NodeValueAtXFEMInterface"); 52 : 53 : const UserObject * uo = 54 120 : &(_fe_problem.getUserObjectBase(getParam<UserObjectName>("interface_mesh_cut_userobject"))); 55 : 56 60 : if (dynamic_cast<const InterfaceMeshCutUserObjectBase *>(uo) == nullptr) 57 0 : mooseError("UserObject casting to InterfaceMeshCutUserObjectBase in NodeValueAtXFEMInterface"); 58 : 59 60 : _mesh_cut = dynamic_cast<const InterfaceMeshCutUserObjectBase *>(uo); 60 60 : _elem_pairs = _xfem->getXFEMCutElemPairs(_xfem->getGeometricCutID(_mesh_cut)); 61 60 : } 62 : 63 : void 64 60 : NodeValueAtXFEMInterface::execute() 65 : { 66 : _values_positive_level_set_side.clear(); 67 : _values_negative_level_set_side.clear(); 68 : _grad_values_positive_level_set_side.clear(); 69 : _grad_values_negative_level_set_side.clear(); 70 60 : _nodes.clear(); 71 : 72 60 : std::shared_ptr<MeshBase> cutter_mesh = _mesh_cut->getCutterMesh(); 73 : 74 7560 : for (const auto & node : cutter_mesh->node_ptr_range()) 75 3780 : _nodes.push_back(*node); 76 : 77 60 : _pl->enable_out_of_mesh_mode(); 78 : 79 7560 : for (const auto & node : cutter_mesh->node_ptr_range()) 80 : { 81 3720 : unsigned int i = node->id(); 82 : 83 3720 : if ((*_pl)(*node) != nullptr) 84 : { 85 2760 : const Elem * elem = getElemContainingPoint(*node, /*positive_level_set = */ true); 86 : 87 2760 : if (elem != nullptr) 88 : { 89 2070 : _subproblem.setCurrentSubdomainID(elem, /*_tid */ 0); 90 2070 : _subproblem.reinitElemPhys(elem, {*node}, 0); 91 : 92 2070 : _values_positive_level_set_side[i] = (dynamic_cast<MooseVariable *>(_var))->sln()[0]; 93 2070 : _grad_values_positive_level_set_side[i] = 94 2070 : ((dynamic_cast<MooseVariable *>(_var))->gradSln())[0]; 95 : } 96 : 97 2760 : const Elem * elem2 = getElemContainingPoint(*node, false); 98 2760 : if (elem2 != nullptr) 99 : { 100 2070 : _subproblem.setCurrentSubdomainID(elem2, /*_tid */ 0); 101 2070 : _subproblem.reinitElemPhys(elem2, {*node}, 0); 102 : 103 2070 : _values_negative_level_set_side[i] = (dynamic_cast<MooseVariable *>(_var))->sln()[0]; 104 2070 : _grad_values_negative_level_set_side[i] = 105 2070 : ((dynamic_cast<MooseVariable *>(_var))->gradSln())[0]; 106 : } 107 : } 108 : else // When node is outside of computation domain 109 : { 110 960 : _values_positive_level_set_side[i] = 0; 111 960 : _values_negative_level_set_side[i] = 0; 112 960 : _grad_values_positive_level_set_side[i] = RealVectorValue(0); 113 960 : _grad_values_negative_level_set_side[i] = RealVectorValue(0); 114 : } 115 60 : } 116 60 : } 117 : 118 : void 119 60 : NodeValueAtXFEMInterface::finalize() 120 : { 121 60 : _communicator.set_union(_values_positive_level_set_side); 122 60 : _communicator.set_union(_grad_values_positive_level_set_side); 123 60 : _communicator.set_union(_values_negative_level_set_side); 124 60 : _communicator.set_union(_grad_values_negative_level_set_side); 125 60 : } 126 : 127 : const Elem * 128 5520 : NodeValueAtXFEMInterface::getElemContainingPoint(const Node & p, bool positive_level_set) 129 : { 130 5520 : const Elem * elem1 = (*_pl)(p); 131 : 132 5520 : if (elem1->processor_id() != processor_id()) 133 : return nullptr; 134 : 135 : const Node * node = elem1->node_ptr(0); 136 : 137 4140 : dof_id_type ls_dof_id = node->dof_number(_system.number(), _level_set_var_number, 0); 138 : 139 4140 : Number ls_node_value = _solution(ls_dof_id); 140 : 141 : bool positive = false; 142 : 143 4140 : if (_xfem->isPointInsidePhysicalDomain(elem1, *node)) 144 : { 145 4140 : if (ls_node_value > 0.0) 146 : positive = true; 147 : } 148 : else 149 : { 150 : if (ls_node_value < 0.0) 151 : positive = false; 152 : } 153 : 154 : const Elem * elem2 = nullptr; 155 : bool found = false; 156 8280 : for (auto & pair : *_elem_pairs) 157 : { 158 4140 : if (pair.first == elem1) 159 : { 160 4140 : elem2 = pair.second; 161 : found = true; 162 : } 163 0 : else if (pair.second == elem1) 164 : { 165 : elem2 = pair.first; 166 : found = true; 167 : } 168 : } 169 : 170 4140 : if (!found) 171 0 : mooseError("NodeValueAtXFEMInterface: The interface node ", 172 : p, 173 : " are not found by element pair locator."); 174 : 175 4140 : if ((positive && positive_level_set) || (!positive && !positive_level_set)) 176 : return elem1; 177 : else if ((!positive && positive_level_set) || (positive && !positive_level_set)) 178 2070 : return elem2; 179 : else 180 : return nullptr; 181 : }