/*------------------------------- phasicFlow --------------------------------- O C enter of O O E ngineering and O O M ultiscale modeling of OOOOOOO F luid flow ------------------------------------------------------------------------------ Copyright (C): www.cemf.ir email: hamid.r.norouzi AT gmail.com ------------------------------------------------------------------------------ Licence: This file is part of phasicFlow code. It is a free software for simulating granular and multiphase flows. You can redistribute it and/or modify it under the terms of GNU General Public License v3 or any other later versions. phasicFlow is distributed to help others in their research in the field of granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -----------------------------------------------------------------------------*/ #include #include "vocabs.hpp" #include "systemControl.hpp" #include "fieldsDataBase.hpp" #include "fieldFunctions.hpp" #include "dictionary.hpp" namespace pFlow { bool pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace); } bool pFlow::fieldsDataBase::loadPointStructureToTime() { return false; } bool pFlow::fieldsDataBase::checkForUpdate(const word &compoundName, bool forceUpdate) { auto t = currentTime(); bool shouldUpdate = false; if(auto [iter, found]= captureTime_.findIf(compoundName); found) { shouldUpdate = iter->second < t || forceUpdate; iter->second = t; } else { shouldUpdate = true; captureTime_.insertIf(compoundName, t); } return shouldUpdate; } pFlow::span pFlow::fieldsDataBase::createOrGetRealField(const word &name) { bool shouldUpdate = checkForUpdate(name); if(shouldUpdate) { allFields_.emplaceBackOrReplace> ( name, FieldTypeHost ( name, "value", pointFieldSize() ) ); } auto& field = allFields_.getObject>(name); return span( field.data(), field.size()); } pFlow::span pFlow::fieldsDataBase::createOrGetVolume(bool forceUpdate) { const word fName = "volume"; bool shouldUpdate = checkForUpdate(fName, forceUpdate); if(shouldUpdate) { const auto index = updateFieldUint32("shapeIndex", true); auto vols = getShape().volume(); FieldTypeHost volField ( fName, "value", pointFieldSize() ); for(uint32 i=0; i< volField.size(); i++) { volField[i] = vols[index[i]]; } allFields_.emplaceBackOrReplace> ( fName, std::move(volField) ); } auto& field = allFields_.getObject>(fName); return span( field.data(), field.size()); } pFlow::span pFlow::fieldsDataBase::createOrGetDensity(bool forceUpdate) { const word fName = "density"; bool shouldUpdate = checkForUpdate(fName, forceUpdate); if(shouldUpdate) { const auto index = updateFieldUint32("shapeIndex", true); const auto dens = getShape().density(); FieldTypeHost denFeild ( fName, "value", pointFieldSize() ); for(uint32 i=0; i< denFeild.size(); i++) { denFeild[i] = dens[index[i]]; } allFields_.emplaceBackOrReplace> ( fName, std::move(denFeild) ); } auto& field = allFields_.getObject>(fName); return span( field.data(), field.size()); } pFlow::span pFlow::fieldsDataBase::createOrGetOne(bool forceUpdate) { const word fName = "one"; bool shouldUpdate = checkForUpdate(fName, forceUpdate); if(shouldUpdate) { allFields_.emplaceBackOrReplace> ( fName, FieldTypeHost ( fName, "value", pointFieldSize(), 1.0 ) ); } auto& field = allFields_.getObject>(fName); return span( field.data(), field.size()); } pFlow::span pFlow::fieldsDataBase::createOrGetMass(bool forceUpdate) { const word fName = "mass"; bool shouldUpdate = checkForUpdate(fName, forceUpdate); if(shouldUpdate) { const auto index = updateFieldUint32("shapeIndex", true); const auto ms = getShape().mass(); FieldTypeHost massField ( fName, "value", pointFieldSize() ); for(uint32 i=0; i< massField.size(); i++) { massField[i] = ms[index[i]]; } allFields_.emplaceBackOrReplace> ( fName, std::move(massField) ); } auto& field = allFields_.getObject>(fName); return span( field.data(), field.size()); } pFlow::span pFlow::fieldsDataBase::createOrGetI(bool forceUpdate) { const word fName = "I"; bool shouldUpdate = checkForUpdate(fName, forceUpdate); if(shouldUpdate) { const auto index = updateFieldUint32("shapeIndex", true); const auto Is = getShape().Inertia(); FieldTypeHost IField ( fName, "value", pointFieldSize() ); for(uint32 i=0; i< IField.size(); i++) { IField[i] = Is[index[i]]; } allFields_.emplaceBackOrReplace> ( fName, std::move(IField) ); } auto& field = allFields_.getObject>(fName); return span( field.data(), field.size()); } bool pFlow::fieldsDataBase::findFunction( const word &compoundFieldName, word &fieldName, fieldsDataBase::Functions &func) { std::regex pattern(R"((\w+)?\((\w+)(?:,([xyzw]))?\)|(\w+))"); std::smatch match; if (std::regex_match(compoundFieldName, match, pattern)) { if (match[1].matched) // Function is present { word functionName = match[1].str(); fieldName = match[2].str(); // Map the function name to the enum value if(functionName=="component") { if (!match[3].matched) // Component is not present { fatalErrorInFunction << "Component (x, y, z, or w) is not specified in the function component: " << compoundFieldName << " the format is component(u,x), where u is the vector field name and x is the compoenent." << endl; return false; } switch (match[3].str()[0]) { case 'x': func = fieldsDataBase::Functions::ComponentX; break; case 'y': func = fieldsDataBase::Functions::ComponentY; break; case 'z': func = fieldsDataBase::Functions::ComponentZ; break; case 'w': func = fieldsDataBase::Functions::ComponentW; break; default: fatalErrorInFunction << "Invalid component specified: " << match[3].str() << endl; return false; } return true; } else if (functionName == "abs") { func = fieldsDataBase::Functions::Abs; } else if (functionName == "square") { func = fieldsDataBase::Functions::Square; } else if (functionName == "cube") { func = fieldsDataBase::Functions::Cube; } else if (functionName == "sqrt") { func = fieldsDataBase::Functions::SqureRoot; } else if (functionName == "mag") { func = fieldsDataBase::Functions::Magnitude; } else if (functionName == "magSquare") { func = fieldsDataBase::Functions::MagnitudeSquare; } else if (functionName == "magCube") { func = fieldsDataBase::Functions::MagnitudeCube; } else if (functionName == "magSqrt") { func = fieldsDataBase::Functions::MagnitudeSquareRoot; } else { fatalErrorInFunction << "Unknown function specified: " << functionName<< " in: "<() || inputType == getTypeName() ) { outputType = getTypeName(); return true; } else { fatalErrorInFunction<<"Wrong function: component(u,comp), for input field type: "<() ) { outputType = getTypeName(); return true; } else { fatalErrorInFunction<<"Wrong function: component(u,w), for input field type: "<() || inputType == getTypeName() || inputType == getTypeName() || inputType == getTypeName() ) { outputType = getTypeName(); return true; } else { fatalErrorInFunction<<"Wrong input field type for functions abs, squqre, cube, and sqrt."<< " field type is "<< inputType<() || inputType == getTypeName() ) { outputType = getTypeName(); return true; } else { fatalErrorInFunction<<"Wroing input field type for functions mag, magSquare, magCube, magSqrt. "<< " Input field type is "<< inputType<() || inputType == getTypeName() || inputType == getTypeName()) { outputType = inputType; return true; } else if( inputType == getTypeName() || inputType == getTypeName() ) { outputType = getTypeName(); return true; } else { fatalErrorInFunction<< "Wroing input field type "<< inputType<("shapeType", ""); if(shapeType_.empty()) { WARNING << "shapeType is not set in dictionary: " << postDict.globalName() << " and you may need to set for some postprocess operations"<second; } else { // the name is in the Time object if(pointFieldNameExists(pointFieldName)) { originalType = getPointFieldType(pointFieldName); } else { fatalErrorInFunction << "The field name: "<< pointFieldName << " is not in the Time object.\n" <<" Avaiable ones are: \n"<< time().objectNames()< pFlow::fieldsDataBase::updatePoints(bool forceUpdate) { const word fName = "position"; bool shouldUpdate = checkForUpdate(fName, forceUpdate); if(shouldUpdate) { // load pointStructure if(!loadPointStructureToTime()) { fatalErrorInFunction<< "Error in loading pointStructure to Time object."< ( fName, pstruct.activePointsHost() ); } auto& points = allFields_.getObject(fName); return span( points.data(), points.size()); } pFlow::span pFlow::fieldsDataBase::updateFieldRealx3 ( const word &compoundName, bool forceUpdate ) { word originalType, typeAfterFunction, fieldName; Functions func; if( !getFieldTypeNameFunction( compoundName, fieldName, originalType, typeAfterFunction, func) ) { fatalErrorInFunction<< "Error in getting the type name of field: "<< compoundName<<", with type name: "<< originalType <(nullptr, 0); } if( originalType == getTypeName() && func == Functions::None ) { return updateField(fieldName, forceUpdate); } else { fatalErrorInFunction<< "Error in getting the type name of field: "<< compoundName<<", with type name: "<< originalType <(nullptr, 0); } } pFlow::span pFlow::fieldsDataBase::updateFieldRealx4 ( const word &compoundName, bool forceUpdate ) { word originalType, typeAfterFunction, fieldName; Functions func; if( !getFieldTypeNameFunction( compoundName, fieldName, originalType, typeAfterFunction, func)) { fatalErrorInFunction<< "Error in getting the type name of field: "<< compoundName<<", with type name: "<< originalType <(nullptr, 0); } if( originalType == getTypeName() && func == Functions::None ) { return updateField(fieldName, forceUpdate); } else { fatalErrorInFunction<< "Error in getting the type name of field: "<< compoundName<<", with type name: "<< originalType <(nullptr, 0); } } pFlow::span pFlow::fieldsDataBase::updateFieldReal ( const word &compoundName, bool forceUpdate ) { word originalType, typeAfterFunction, fieldName; Functions func; if( !getFieldTypeNameFunction( compoundName, fieldName, originalType, typeAfterFunction, func) ) { fatalErrorInFunction<< "Error in getting the type name of field: "<< compoundName<<", with type name: "<< originalType <(nullptr, 0); } // if the output type is not real, then it is not supported yet if(typeAfterFunction != getTypeName()) { fatalErrorInFunction<< "The output type of field "<< compoundName<< " is not real, it is: "<< typeAfterFunction<(nullptr, 0); } // if the orginal type is real and no function, then it is a normal field if( originalType == getTypeName() && func == Functions::None ) { return updateField(fieldName, forceUpdate); } // if the original type is uint32, and no funciton, cast to real if( originalType == getTypeName()) { if(func == Functions::None) { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(fieldName+".real"); funcCast(sp, spReal); return spReal; } else { fatalErrorInFunction<<"No function can be applied to field of type uint32. "<< " The field is: "<< compoundName<(nullptr, 0); fatalExit; } } if( originalType == getTypeName() ) { switch(func) { case Functions::Abs: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName); funcAbs(sp, spReal); return spReal; } case Functions::Square: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName); funcSquare(sp, spReal); return spReal; } case Functions::Cube: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName); funcCube(sp, spReal); return spReal; } case Functions::SqureRoot: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName+".sqrt"); funcSquareRoot(sp, spReal); return spReal; } default: { fatalErrorInFunction<< "Wrong function for field type real in :"<< compoundName<(nullptr, 0); } } } if( originalType == getTypeName()) { switch(func) { case Functions::Magnitude: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName); funcMagnitude(sp, spReal); return spReal; } case Functions::MagnitudeSquare: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName); funcMagnitudeSquare(sp, spReal); return spReal; } case Functions::MagnitudeCube: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName); funcMagnitudeCube(sp, spReal); return spReal; } case Functions::MagnitudeSquareRoot: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName); funcMagnitudeSquareRoot(sp, spReal); return spReal; } case Functions::ComponentX: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName); funcComponent(sp, spReal, 'x'); return spReal; } case Functions::ComponentY: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName); funcComponent(sp, spReal, 'y'); return spReal; } case Functions::ComponentZ: { auto sp = updateField(fieldName, forceUpdate); auto spReal = createOrGetRealField(compoundName); funcComponent(sp, spReal, 'z'); return spReal; } default: { fatalErrorInFunction<< "Wrong function for field type realx3 in :"<< compoundName<(nullptr, 0); } } } fatalErrorInFunction<<"NOT SUPPORTED "<(nullptr, 0); } pFlow::span pFlow::fieldsDataBase::updateFieldUint32 ( const word& name, bool forceUpdate ) { return updateField(name, forceUpdate); } pFlow::allPointFieldTypes pFlow::fieldsDataBase::updateFieldAll ( const word &compoundName, bool forceUpdate ) { word typeAfterFunction, originalType; if( !getFieldType(compoundName, originalType, typeAfterFunction)) { fatalErrorInFunction<< "Error in getting the type name of field: "<< compoundName<<", with type name: "<< originalType <(nullptr, 0); } if( typeAfterFunction == getTypeName() ) { return updateFieldRealx3(compoundName, forceUpdate); } else if( typeAfterFunction == getTypeName() ) { return updateFieldRealx4(compoundName, forceUpdate); } else if( typeAfterFunction == getTypeName() ) { return updateFieldReal(compoundName, forceUpdate); } else { fatalErrorInFunction<< "Invalid feild "<< compoundName<(nullptr, 0); } } pFlow::uniquePtr pFlow::fieldsDataBase::create ( systemControl& control, const dictionary& postDict, bool inSimulation, timeValue startTime ) { word dbType; if(inSimulation) { dbType = "fieldsDataBase"; } else { dbType = "fieldsDataBase"; } if( boolvCtorSelector_.search(dbType) ) { auto objPtr = boolvCtorSelector_[dbType](control, postDict, inSimulation, startTime); return objPtr; } else { printKeys ( fatalError << "Ctor Selector "<< dbType << " does not exist. \n" <<"Available ones are: \n\n" , boolvCtorSelector_ ); fatalExit; } return nullptr; } bool pFlow::pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace) { std::regex match("pointField\\<([A-Za-z1-9_]*)\\,([A-Za-z1-9_]*)\\>"); std::smatch search; if(!std::regex_match(TYPENAME, search, match)) return false; if(search.size()!= 3) return false; fieldType = search[1]; fieldSpace = search[2]; return true; }