Line data Source code
1 : #include "BooleanComboClusteringUserObject.h" 2 : #include "ClusteringUserObjectBase.h" 3 : 4 : registerMooseObject("CardinalApp", BooleanComboClusteringUserObject); 5 : 6 : std::unordered_map<std::string, int> BooleanComboClusteringUserObject::_precedence{ 7 : {"not", 3}, {"!", 3}, {"and", 2}, {"&&", 2}, {"or", 1}, {"||", 1}}; 8 : 9 : InputParameters 10 33 : BooleanComboClusteringUserObject::validParams() 11 : { 12 33 : InputParameters params = GeneralUserObject::validParams(); 13 66 : params.addRequiredParam<ExtraElementIDName>("id_name", "extra_element_integer_id name"); 14 66 : params.addRequiredParam<std::vector<std::string>>("expression", 15 : "boolean logic operation expression"); 16 33 : params.addClassDescription("Takes various heuristic user objects and applies a user defined " 17 : "boolean logic operation on them."); 18 33 : return params; 19 0 : } 20 : 21 15 : BooleanComboClusteringUserObject::BooleanComboClusteringUserObject( 22 15 : const InputParameters & parameters) 23 : : GeneralUserObject(parameters), 24 15 : _id_name(getParam<ExtraElementIDName>("id_name")), 25 30 : _mesh(_fe_problem.mesh().getMesh()) 26 : { 27 15 : if (!_mesh.has_elem_integer(_id_name)) 28 : { 29 3 : mooseWarning(_id_name, 30 : " extra element integer is missing in the mesh." 31 : " Adding extra element integer ", 32 : _id_name); 33 0 : _mesh.add_elem_integer(_id_name); 34 : } 35 : 36 12 : _extra_integer_index = _mesh.get_elem_integer_index(_id_name); 37 24 : reversePolishNotation(getParam<std::vector<std::string>>("expression")); 38 12 : initializeUserObjects(); 39 12 : } 40 : 41 : void 42 12 : BooleanComboClusteringUserObject::initializeUserObjects() 43 : { 44 : _clustering_user_objects.clear(); 45 36 : for (const auto & token : _output_stack) 46 : { 47 6 : if (_precedence.count(token)) 48 : // separate the user object names. If true that means token is an operator 49 6 : continue; 50 36 : const auto & uo = getUserObjectByName<ClusteringUserObjectBase>(token); 51 18 : _clustering_user_objects.insert(std::make_pair(token, &uo)); 52 : } 53 12 : } 54 : 55 : bool 56 8142 : BooleanComboClusteringUserObject::belongsToCluster(libMesh::Elem * base_element, 57 : libMesh::Elem * neighbor_elem) 58 : { 59 : // follow the reverse polish notation 60 8142 : std::stack<bool> result_stack; 61 : 62 24300 : for (const auto token : _output_stack) 63 : { 64 : // if token is an operator 65 16158 : if (token == "and" || token == "&&") 66 : { 67 2160 : bool rhs = result_stack.top(); 68 : result_stack.pop(); 69 2160 : bool lhs = result_stack.top(); 70 : result_stack.pop(); 71 4320 : result_stack.push(lhs && rhs); 72 : } 73 13998 : else if (token == "or" || token == "||") 74 : { 75 1848 : bool rhs = result_stack.top(); 76 : result_stack.pop(); 77 1848 : bool lhs = result_stack.top(); 78 : result_stack.pop(); 79 3696 : result_stack.push(lhs || rhs); 80 : } 81 12150 : else if (token == "not" || token == "!") 82 : { 83 0 : bool val = result_stack.top(); 84 : result_stack.pop(); 85 0 : result_stack.push(!val); 86 : } 87 : else 88 24300 : result_stack.push(_clustering_user_objects[token]->evaluate(base_element, neighbor_elem)); 89 : } 90 8142 : return result_stack.top(); 91 : } 92 : 93 : void 94 24 : BooleanComboClusteringUserObject::findCluster() 95 : { 96 24 : std::stack<libMesh::Elem *> neighbor_stack; 97 : 98 4848 : for (auto & elem : _mesh.active_element_ptr_range()) 99 : { 100 2400 : if (elem->get_extra_integer(_extra_integer_index) != NOT_VISITED) 101 192 : continue; 102 : 103 2208 : int cluster_id = elem->id(); 104 : neighbor_stack.push(elem); 105 : 106 4608 : while (!neighbor_stack.empty()) 107 : { 108 2400 : libMesh::Elem * current_elem = neighbor_stack.top(); 109 : neighbor_stack.pop(); 110 : 111 12000 : for (unsigned int s = 0; s < current_elem->n_sides(); s++) 112 : { 113 9600 : libMesh::Elem * neighbor_elem = current_elem->neighbor_ptr(s); 114 9600 : if (neighbor_elem && neighbor_elem->active() && 115 8640 : neighbor_elem->get_extra_integer(_extra_integer_index) == NOT_VISITED) 116 : { 117 8142 : if (belongsToCluster(current_elem, neighbor_elem)) 118 : { 119 192 : elem->set_extra_integer(_extra_integer_index, cluster_id); 120 192 : neighbor_elem->set_extra_integer(_extra_integer_index, cluster_id); 121 : neighbor_stack.push(neighbor_elem); 122 : } 123 : } 124 : } 125 : } 126 24 : } 127 24 : } 128 : 129 : void 130 24 : BooleanComboClusteringUserObject::resetExtraInteger() 131 : { 132 4848 : for (auto & elem : _mesh.active_element_ptr_range()) 133 2424 : elem->set_extra_integer(_extra_integer_index, NOT_VISITED); 134 24 : } 135 : 136 : void 137 24 : BooleanComboClusteringUserObject::execute() 138 : { 139 24 : resetExtraInteger(); 140 24 : findCluster(); 141 24 : } 142 : 143 : int 144 0 : BooleanComboClusteringUserObject::getExtraIntegerScore(libMesh::Elem * elem) const 145 : { 146 0 : return elem->get_extra_integer(_extra_integer_index); 147 : } 148 : 149 : void 150 12 : BooleanComboClusteringUserObject::reversePolishNotation(const std::vector<std::string> & expression) 151 : { 152 12 : std::stack<std::string> op_stack; 153 : 154 48 : for (const auto & token : expression) 155 : { 156 36 : if (token == _left_parenthesis) 157 : op_stack.push(token); 158 30 : else if (token == _right_parenthesis) 159 : { 160 12 : while (!op_stack.empty() && op_stack.top() != _left_parenthesis) 161 : { 162 6 : _output_stack.push_back(op_stack.top()); 163 : op_stack.pop(); 164 : } 165 6 : if (!op_stack.empty() && op_stack.top() == _left_parenthesis) 166 : op_stack.pop(); 167 : } 168 : // operator handling based on _precedence 169 24 : else if (_precedence.find(token) != _precedence.end()) 170 : { 171 : // if operation hasn't the least precedence 172 : // push back to the output stack 173 12 : while (!op_stack.empty() && _precedence.find(op_stack.top()) != _precedence.end() && 174 0 : _precedence[op_stack.top()] >= _precedence[token]) 175 : { 176 0 : _output_stack.push_back(op_stack.top()); 177 : op_stack.pop(); 178 : } 179 : op_stack.push(token); 180 : } 181 : else 182 18 : _output_stack.push_back(token); 183 : } 184 12 : while (!op_stack.empty()) 185 : { 186 0 : _output_stack.push_back(op_stack.top()); 187 : op_stack.pop(); 188 : } 189 12 : }