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 1406 : NekFieldVariable::validParams() 27 : { 28 1406 : auto params = FieldTransferBase::validParams(); 29 2812 : params.addParam<MooseEnum>( 30 : "field", 31 2812 : getNekFieldEnum(), 32 : "NekRS field variable to read/write; defaults to the name of the object"); 33 1406 : params.addClassDescription("Reads/writes volumetric field data between NekRS and MOOSE."); 34 1406 : return params; 35 0 : } 36 : 37 703 : NekFieldVariable::NekFieldVariable(const InputParameters & parameters) 38 703 : : FieldTransferBase(parameters) 39 : { 40 1406 : if (isParamValid("field")) 41 1254 : _field = getParam<MooseEnum>("field").getEnum<field::NekFieldEnum>(); 42 : else 43 : { 44 : // try a reasonable default by seeing if the object name matches a valid enumeration 45 76 : auto enums = getNekFieldEnum().getNames(); 46 76 : auto obj_name = name(); 47 : std::transform(obj_name.begin(), obj_name.end(), obj_name.begin(), ::toupper); 48 76 : bool found_name = std::find(enums.begin(), enums.end(), obj_name) != enums.end(); 49 76 : if (found_name) 50 75 : _field = convertToFieldEnum(obj_name); 51 : else 52 2 : paramError("field", 53 1 : "We tried to choose a default 'field' as '" + name() + 54 : "', but this value is not an option in the 'field' enumeration. Please " 55 : "provide the 'field' parameter."); 56 75 : } 57 : 58 702 : if (_direction == "from_nek") 59 1344 : addExternalVariable(_variable); 60 : else 61 : { 62 29 : if (_usrwrk_slot.size() > 1) 63 2 : paramError("usrwrk_slot", 64 : "'usrwrk_slot' must be of length 1 for field transfers to_nek; you have entered " 65 1 : "a vector of length " + 66 0 : Moose::stringify(_usrwrk_slot.size())); 67 : 68 28 : auto d = nekrs::nondimensionalDivisor(_field); 69 28 : auto a = nekrs::nondimensionalAdditive(_field); 70 56 : addExternalVariable(_usrwrk_slot[0], _variable, a, d); 71 : 72 : // we don't impose any requirements on boundary conditions on the NekRS side, because this data 73 : // being sent to NekRS doesn't necessarily get used in a boundary condition. It could get used 74 : // in a source term, for instance. 75 : } 76 : 77 : // TODO: add test to relax this 78 699 : if (_direction == "to_nek" && _field != field::temperature) 79 0 : paramError("field", 80 : "NekFieldVariable currently only supports transfers 'to_nek' for 'temperature'. " 81 : "Please contact the Cardinal developer team if you require writing of other " 82 : "NekRS field variables."); 83 : 84 699 : if (_field == field::velocity_component) 85 0 : paramError("field", 86 : "'velocity_component' is not yet supported; if you need velocity dotted with a " 87 : "specific direction, extract the three components of velocity and perform the " 88 : "postprocessing operation using a ParsedAux. If this is hindering your workflow, " 89 : "please contact the Cardinal developer team."); 90 699 : } 91 : 92 : field::NekFieldEnum 93 75 : NekFieldVariable::convertToFieldEnum(const std::string name) const 94 : { 95 75 : auto lowercase = name; 96 : std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), ::tolower); 97 75 : if (lowercase == "velocity_x") 98 : return field::velocity_x; 99 75 : if (lowercase == "velocity_y") 100 : return field::velocity_y; 101 75 : if (lowercase == "velocity_z") 102 : return field::velocity_z; 103 75 : if (lowercase == "velocity") 104 : return field::velocity; 105 71 : if (lowercase == "velocity_component") 106 : return field::velocity_component; 107 71 : if (lowercase == "velocity_x_squared") 108 : return field::velocity_x_squared; 109 71 : if (lowercase == "velocity_y_squared") 110 : return field::velocity_y_squared; 111 71 : if (lowercase == "velocity_z_squared") 112 : return field::velocity_z_squared; 113 67 : if (lowercase == "temperature") 114 : return field::temperature; 115 46 : if (lowercase == "pressure") 116 : return field::pressure; 117 46 : if (lowercase == "scalar01") 118 : return field::scalar01; 119 34 : if (lowercase == "scalar02") 120 : return field::scalar02; 121 8 : if (lowercase == "scalar03") 122 : return field::scalar03; 123 0 : if (lowercase == "unity") 124 : return field::unity; 125 0 : if (lowercase == "usrwrk00") 126 : return field::usrwrk00; 127 0 : if (lowercase == "usrwrk01") 128 : return field::usrwrk01; 129 0 : if (lowercase == "usrwrk02") 130 : return field::usrwrk02; 131 : 132 0 : mooseError("Unhandled NekFieldEnum in NekFieldVariable!"); 133 : } 134 : 135 : void 136 86506 : NekFieldVariable::readDataFromNek() 137 : { 138 86506 : if (!_nek_mesh->volume()) 139 19794 : _nek_problem.boundarySolution(_field, _external_data); 140 : else 141 66712 : _nek_problem.volumeSolution(_field, _external_data); 142 : 143 86506 : fillAuxVariable(_variable_number[_variable], _external_data); 144 86506 : } 145 : 146 : void 147 264 : NekFieldVariable::sendDataToNek() 148 : { 149 264 : _console << "Sending " << _variable << " to NekRS..." << std::endl; 150 264 : auto d = nekrs::nondimensionalDivisor(_field); 151 264 : auto a = nekrs::nondimensionalAdditive(_field); 152 : 153 264 : if (!_nek_mesh->volume()) 154 : { 155 6456 : for (unsigned int e = 0; e < _nek_mesh->numSurfaceElems(); e++) 156 : { 157 : // We can only write into the nekRS scratch space if that face is "owned" by the current 158 : // process 159 6204 : if (nekrs::commRank() != _nek_mesh->boundaryCoupling().processor_id(e)) 160 5102 : continue; 161 : 162 1102 : _nek_problem.mapFaceDataToNekFace(e, _variable_number[_variable], d, a, &_v_face); 163 1102 : _nek_problem.writeBoundarySolution(_usrwrk_slot[0] * nekrs::fieldOffset(), e, _v_face); 164 : } 165 : } 166 : else 167 : { 168 3888 : for (unsigned int e = 0; e < _nek_mesh->numVolumeElems(); ++e) 169 : { 170 : // We can only write into the nekRS scratch space if that face is "owned" by the current 171 : // process 172 3876 : if (nekrs::commRank() != _nek_mesh->volumeCoupling().processor_id(e)) 173 1938 : continue; 174 : 175 1938 : _nek_problem.mapVolumeDataToNekVolume(e, _variable_number[_variable], d, a, &_v_elem); 176 1938 : _nek_problem.writeVolumeSolution(_usrwrk_slot[0] * nekrs::fieldOffset(), e, _v_elem); 177 : } 178 : } 179 264 : } 180 : 181 : #endif