Line data Source code
1 : /********************************************************************/ 2 : /* SOFTWARE COPYRIGHT NOTIFICATION */ 3 : /* Cardinal */ 4 : /* */ 5 : /* (c) 2021 UChicago Argonne, LLC */ 6 : /* ALL RIGHTS RESERVED */ 7 : /* */ 8 : /* Prepared by UChicago Argonne, LLC */ 9 : /* Under Contract No. DE-AC02-06CH11357 */ 10 : /* With the U. S. Department of Energy */ 11 : /* */ 12 : /* Prepared by Battelle Energy Alliance, LLC */ 13 : /* Under Contract No. DE-AC07-05ID14517 */ 14 : /* With the U. S. Department of Energy */ 15 : /* */ 16 : /* See LICENSE for full restrictions */ 17 : /********************************************************************/ 18 : 19 : #ifdef ENABLE_NEK_COUPLING 20 : 21 : #include "NekFieldVariable.h" 22 : 23 : registerMooseObject("CardinalApp", NekFieldVariable); 24 : 25 : InputParameters 26 1602 : NekFieldVariable::validParams() 27 : { 28 1602 : auto params = FieldTransferBase::validParams(); 29 3204 : params.addParam<MooseEnum>( 30 : "field", 31 3204 : getNekFieldEnum(), 32 : "NekRS field variable to read/write; defaults to the name of the object"); 33 1602 : params.addClassDescription("Reads/writes volumetric field data between NekRS and MOOSE."); 34 1602 : return params; 35 0 : } 36 : 37 801 : NekFieldVariable::NekFieldVariable(const InputParameters & parameters) 38 801 : : FieldTransferBase(parameters) 39 : { 40 801 : if (_direction == "from_nek") 41 1558 : addExternalVariable(_variable); 42 : else 43 : { 44 21 : if (_usrwrk_slot.size() > 1) 45 2 : paramError("usrwrk_slot", 46 : "'usrwrk_slot' must be of length 1 for field transfers to_nek; you have entered " 47 1 : "a vector of length " + 48 0 : Moose::stringify(_usrwrk_slot.size())); 49 : 50 40 : addExternalVariable(_usrwrk_slot[0], _variable); 51 : 52 : // we don't impose any requirements on boundary conditions on the NekRS side, because this data 53 : // being sent to NekRS doesn't necessarily get used in a boundary condition. It could get used 54 : // in a source term, for instance. 55 : } 56 : 57 1596 : if (isParamValid("field")) 58 1302 : _field = getParam<MooseEnum>("field").getEnum<field::NekFieldEnum>(); 59 : else 60 : { 61 : // try a reasonable default by seeing if the object name matches a valid enumeration 62 147 : auto enums = getNekFieldEnum().getNames(); 63 147 : auto obj_name = name(); 64 : std::transform(obj_name.begin(), obj_name.end(), obj_name.begin(), ::toupper); 65 147 : bool found_name = std::find(enums.begin(), enums.end(), obj_name) != enums.end(); 66 147 : if (found_name) 67 146 : _field = convertToFieldEnum(obj_name); 68 : else 69 1 : paramError("field", 70 1 : "We tried to choose a default 'field' as '" + name() + 71 : "', but this value is not an option in the 'field' enumeration. Please " 72 : "provide the 'field' parameter."); 73 146 : } 74 : 75 797 : if (_direction == "to_nek") 76 : { 77 20 : switch (_field) 78 : { 79 20 : case field::temperature: 80 20 : indices.temperature = _usrwrk_slot[0] * nekrs::fieldOffset(); 81 : break; 82 0 : default: 83 0 : paramError("field", 84 : "NekFieldVariable currently only supports transfers 'to_nek' for 'temperature'. " 85 : "Please contact the Cardinal developer team if you require writing of other " 86 : "NekRS field variables."); 87 : } 88 : } 89 : 90 797 : if (_field == field::velocity_component) 91 0 : paramError("field", 92 : "'velocity_component' is not yet supported; if you need velocity dotted with a " 93 : "specific direction, extract the three components of velocity and perform the " 94 : "postprocessing operation using a ParsedAux. If this is hindering your workflow, " 95 : "please contact the Cardinal developer team."); 96 797 : } 97 : 98 : field::NekFieldEnum 99 146 : NekFieldVariable::convertToFieldEnum(const std::string name) const 100 : { 101 146 : auto lowercase = name; 102 : std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), ::tolower); 103 146 : if (lowercase == "velocity_x") 104 : return field::velocity_x; 105 130 : if (lowercase == "velocity_y") 106 : return field::velocity_y; 107 114 : if (lowercase == "velocity_z") 108 : return field::velocity_z; 109 106 : if (lowercase == "velocity") 110 : return field::velocity; 111 102 : if (lowercase == "velocity_component") 112 : return field::velocity_component; 113 102 : if (lowercase == "velocity_x_squared") 114 : return field::velocity_x_squared; 115 102 : if (lowercase == "velocity_y_squared") 116 : return field::velocity_y_squared; 117 102 : if (lowercase == "velocity_z_squared") 118 : return field::velocity_z_squared; 119 98 : if (lowercase == "temperature") 120 : return field::temperature; 121 54 : if (lowercase == "pressure") 122 : return field::pressure; 123 46 : if (lowercase == "scalar01") 124 : return field::scalar01; 125 34 : if (lowercase == "scalar02") 126 : return field::scalar02; 127 8 : if (lowercase == "scalar03") 128 : return field::scalar03; 129 0 : if (lowercase == "unity") 130 : return field::unity; 131 0 : if (lowercase == "usrwrk00") 132 : return field::usrwrk00; 133 0 : if (lowercase == "usrwrk01") 134 : return field::usrwrk01; 135 0 : if (lowercase == "usrwrk02") 136 : return field::usrwrk02; 137 : 138 0 : mooseError("Unhandled NekFieldEnum in NekFieldVariable!"); 139 : } 140 : 141 : void 142 88448 : NekFieldVariable::readDataFromNek() 143 : { 144 88448 : if (!_nek_mesh->volume()) 145 20414 : _nek_problem.boundarySolution(_field, _external_data); 146 : else 147 68034 : _nek_problem.volumeSolution(_field, _external_data); 148 : 149 88448 : fillAuxVariable(_variable_number[_variable], _external_data); 150 88448 : } 151 : 152 : void 153 256 : NekFieldVariable::sendDataToNek() 154 : { 155 256 : _console << "Sending " << _variable << " to NekRS..." << std::endl; 156 256 : auto d = nekrs::nondimensionalDivisor(_field); 157 256 : auto a = nekrs::nondimensionalAdditive(_field); 158 : 159 256 : if (!_nek_mesh->volume()) 160 : { 161 6312 : for (unsigned int e = 0; e < _nek_mesh->numSurfaceElems(); e++) 162 : { 163 : // We can only write into the nekRS scratch space if that face is "owned" by the current 164 : // process 165 6068 : if (nekrs::commRank() != _nek_mesh->boundaryCoupling().processor_id(e)) 166 5034 : continue; 167 : 168 1034 : _nek_problem.mapFaceDataToNekFace(e, _variable_number[_variable], d, a, &_v_face); 169 1034 : _nek_problem.writeBoundarySolution(e, _field, _v_face); 170 : } 171 : } 172 : else 173 : { 174 3888 : for (unsigned int e = 0; e < _nek_mesh->numVolumeElems(); ++e) 175 : { 176 : // We can only write into the nekRS scratch space if that face is "owned" by the current 177 : // process 178 3876 : if (nekrs::commRank() != _nek_mesh->volumeCoupling().processor_id(e)) 179 1938 : continue; 180 : 181 1938 : _nek_problem.mapVolumeDataToNekVolume(e, _variable_number[_variable], d, a, &_v_elem); 182 1938 : _nek_problem.writeVolumeSolution(e, _field, _v_elem); 183 : } 184 : } 185 256 : } 186 : 187 : #endif