#include "FITKOFSnappyHexMeshDictWriter.h" #include "FITKDictObject.h" #include "FITKDictArray.h" #include "FITKDictGroup.h" #include "FITKDictVector.h" #include "FITKDictValue.h" #include "FITK_Kernel/FITKCore/FITKEnumTransformer.hpp" #include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h" #include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h" #include "FITK_Interface/FITKInterfaceFlowOF/FITKOFGeometryData.h" #include "FITK_Interface/FITKInterfaceMeshGen/FITKMeshGenInterface.h" #include "FITK_Interface/FITKInterfaceMeshGen/FITKGeometryMeshSize.h" #include "FITK_Interface/FITKInterfaceMeshGen/FITKRegionGeometryRefine.h" #include "FITK_Interface/FITKInterfaceGeometry/FITKGeoCommandList.h" #include "FITK_Interface/FITKInterfaceGeometry/FITKVirtualTopoManager.h" #include "FITK_Interface/FITKInterfaceGeometry/FITKAbsVirtualTopo.h" #include "FITK_Interface/FITKInterfaceMeshGen/FITKZonePoints.h" #include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoShapeAgent.h" #include "FITK_Interface/FITKInterfaceModel/FITKAbstractGeoModel.h" #include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelBox.h" #include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelCylinder.h" #include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelSphere.h" #include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoOperBool.h" #include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelImport.h" #include "FITK_Interface/FITKInterfaceMeshGen/FITKRegionMeshSize.h" #include "FITK_Interface/FITKInterfaceMeshGen/FITKRegionMeshSizeGeom.h" #include "FITK_Kernel/FITKCore/FITKDataRepo.h" #include #include //命名空间 namespace IO { FITKOFSnappyHexMeshDictWriter::FITKOFSnappyHexMeshDictWriter() { } FITKOFSnappyHexMeshDictWriter::~FITKOFSnappyHexMeshDictWriter() { } void FITKOFSnappyHexMeshDictWriter::setFilePath(const QString& filePath) { FITKOFAbstractDictWriter::setFilePath(filePath); QFileInfo fileInfo(filePath); //判断是否是路径 if (!fileInfo.isDir())return; m_fileName = QString("%1/system/snappyHexMeshDict").arg(filePath); } bool FITKOFSnappyHexMeshDictWriter::run() { //判断文件是否存在 if (m_fileName.isEmpty())return false; //获取网格生成单例 Interface::FITKMeshGenInterface* meshGen = Interface::FITKMeshGenInterface::getInstance(); if (!meshGen)return false; //获取几何网格区域大小管理器 m_geometryMeshSizeManager = meshGen->getGeometryMeshSizeManager(); if (!m_geometryMeshSizeManager)return false; //获取字典工程 this->openDictObject(); if (!m_objectDict)return false; //写出FoamFile this->dictObjectFoamFile(); //设置写出的网格区域数据 bool Ok = this->snappyHexMeshGeometryMeshW(); //写出字典文件 if (Ok) Ok = this->writeDictFile(); //关闭字典工程 this->closeDictObject(); return Ok; } QString FITKOFSnappyHexMeshDictWriter::getFileName() { return m_fileName; } void FITKOFSnappyHexMeshDictWriter::dictObjectFoamFile() { if (!m_objectDict)return; //FoamFile DICT::FITKDictGroup* group = new DICT::FITKDictGroup; group->append("version", 2.0); group->append("format", "ascii"); group->append("class", "dictionary"); group->append("location", "\"system\""); group->append("object", "snappyHexMeshDict"); m_objectDict->append("FoamFile", group); } bool FITKOFSnappyHexMeshDictWriter::snappyHexMeshGeometryMeshW() { if (!m_objectDict)return false; bool ok = true; m_objectDict->append("castellatedMesh", true); m_objectDict->append("snap", true); //是否有层数 bool addLayers = m_geometryMeshSizeManager->getDataCount() != 0 ? true : false; m_objectDict->append("addLayers", addLayers); ok &= this->geometrySnappyHexMesh(); ok &= this->castellatedMeshControls(); ok &= this->snapControls(); ok &= this->addLayersControls(addLayers); ok &= this->meshQualityControls(); m_objectDict->append("mergeTolerance", "1.0E-6"); m_objectDict->append("debug", 0); return ok; } bool FITKOFSnappyHexMeshDictWriter::geometrySnappyHexMesh() { if (!m_objectDict)return false; //获取全局数据管理器 AppFrame::FITKGlobalData* globalData = FITKAPP->getGlobalData(); if (!globalData)return false; //获取几何数据 Interface::FITKGeoCommandList* geometryData = globalData->getGeometryData(); int count = geometryData->getDataCount(); //创建字典组件 DICT::FITKDictGroup* group = new DICT::FITKDictGroup; m_objectDict->append("geometry", group); //获取几何数据 for (int i = 0; i < count; ++i) { //获取几何模型数据 Interface::FITKAbsGeoCommand* geoCommand = dynamic_cast(geometryData->getDataByIndex(i)); if (!geoCommand)continue; //获取名称 QString name = geoCommand->getDataObjectName(); //创建stl字典组件 DICT::FITKDictGroup* stlGroup = new DICT::FITKDictGroup; group->append(QString("%1.stl").arg(name), stlGroup); stlGroup->append("type", "triSurfaceMesh"); //获取类型 Interface::FITKGeoEnum::FITKGeometryComType type = geoCommand->getGeometryCommandType(); if (type == Interface::FITKGeoEnum::FITKGeometryComType::FGTBox) { Interface::FITKAbsGeoModelBox* box = dynamic_cast(geoCommand); if (!box)return false; stlGroup->append("simflowType", "primitive"); stlGroup->append("primitiveType", "box"); stlGroup->append("name", name); //第一个点 double minP[3]{ 0.0, 0.0, 0.0 }; box->getPoint1(minP); //长度 double length[3]{ 0.0, 0.0, 0.0 }; box->getLength(length); //最高点 double maxP[3]{ minP[0], minP[1], minP[2] }; length[0] < 0 ? minP[0] = minP[0] + length[0] : maxP[0] = minP[0] + length[0]; length[1] < 0 ? minP[1] = minP[1] + length[1] : maxP[1] = minP[1] + length[1]; length[2] < 0 ? minP[2] = minP[2] + length[2] : maxP[2] = minP[2] + length[2]; stlGroup->append("max", QString("(%1 %2 %3)").arg(maxP[0]).arg(maxP[1]).arg(maxP[2])); stlGroup->append("min", QString("(%1 %2 %3)").arg(minP[0]).arg(minP[1]).arg(minP[2])); } else if (type == Interface::FITKGeoEnum::FITKGeometryComType::FGTCylinder) { Interface::FITKAbsGeoModelCylinder* cylinder = dynamic_cast(geoCommand); if (!cylinder)return false; stlGroup->append("simflowType", "primitive"); stlGroup->append("primitiveType", "cylinder"); stlGroup->append("name", name); //底面圆心 double p[3]{ 0.0, 0.0, 0.0 }; cylinder->getLocation(p); stlGroup->append("point1", QString("(%1 %2 %3)").arg(p[0]).arg(p[1]).arg(p[2])); //轴向与长度 double axis[3]{ 0.0, 0.0, 0.0 }; double length = cylinder->getLength(); cylinder->getDirection(axis); double axisLenth = qSqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]); //获取上圆心 double p2[3]{ p[0] + length * axis[0] / axisLenth, p[1] + length * axis[1] / axisLenth, p[2] + length * axis[2] / axisLenth }; stlGroup->append("point2", QString("(%1 %2 %3)").arg(p2[0]).arg(p2[1]).arg(p2[2])); //半径 double r = cylinder->getRadius(); stlGroup->append("radius", r); } else if (type == Interface::FITKGeoEnum::FITKGeometryComType::FGTSphere) { Interface::FITKAbsGeoModelSphere* sphere = dynamic_cast(geoCommand); if (!sphere)return false; stlGroup->append("simflowType", "primitive"); stlGroup->append("primitiveType", "sphere"); stlGroup->append("name", name); //球心 double center[3]{ 0.0 }; sphere->getLocation(center); stlGroup->append("centre", QString("(%1 %2 %3)").arg(center[0]).arg(center[1]).arg(center[2])); //半径 double radius = sphere->getRadius(); stlGroup->append("radius", radius); } else if (type == Interface::FITKGeoEnum::FITKGeometryComType::FGTBool) { Interface::FITKAbsGeoOperBool* boolOper = dynamic_cast(geoCommand); if (!boolOper)return false; stlGroup->append("simflowType", "brep"); stlGroup->append("topoType", "compound"); stlGroup->append("name", name); } else if (type == Interface::FITKGeoEnum::FITKGeometryComType::FGTImport) { Interface::FITKAbsGeoModelImport* importModel = dynamic_cast(geoCommand); if (!importModel)return false; //stlGroup->append("simflowType", "stl"); stlGroup->append("simflowType", "stl"); stlGroup->append("topoType", "shell"); stlGroup->append("name", name); } if (!this->geoFaceGroupStl(geoCommand->getShapeAgent(), stlGroup, name)) return false; } return true; } bool FITKOFSnappyHexMeshDictWriter::castellatedMeshControls() { if (!m_objectDict)return false; //创建字典组件 DICT::FITKDictGroup* group = new DICT::FITKDictGroup; m_objectDict->append("castellatedMeshControls", group); //获取网格生成单例 Interface::FITKMeshGenInterface* meshGen = Interface::FITKMeshGenInterface::getInstance(); if (!meshGen)return false; //获取材料点管理器 Interface::FITKZonePointManager* pointManager = meshGen->getZonePointManager(); if (!pointManager)return false; //获取区域网格尺寸管理器 Interface::FITKRegionMeshSizeManager* meshRegionManager = meshGen->getRegionMeshSizeMgr(); if (!meshRegionManager)return false; //获取材料点的个数 int count = pointManager->getDataCount(); double point[3]{ 0,0,0 }; if (count == 0)return false; //材料点 if (count == 1) { Interface::FITKZonePoint* pointData = pointManager->getDataByIndex(0); if (!pointData)return false; pointData->getCoor(point); group->append("locationInMesh", QString("(%1 %2 %3)").arg(point[0]).arg(point[1]).arg(point[2])); } else { //多个材料点 DICT::FITKDictArray* materialPoint = new DICT::FITKDictArray; group->append("locationsInMesh", materialPoint); for (int i = 0; i < count; ++i) { Interface::FITKZonePoint* pointData = pointManager->getDataByIndex(i); if (!pointData)continue; pointData->getCoor(point); DICT::FITKDictVector* pointDict = new DICT::FITKDictVector; pointDict->append(QString("(%1 %2 %3)").arg(point[0]).arg(point[1]).arg(point[2])); pointDict->append(QString("zone%1").arg(i + 1)); materialPoint->append(pointDict); } } //面加密 创建字典组件 DICT::FITKDictGroup* refinement = new DICT::FITKDictGroup; group->append("refinementSurfaces", refinement); //获取集合大小 QList geomList = meshRegionManager->getRigonByType(Interface::FITKAbstractRegionMeshSize::RegionType::RigonGeom); for (Interface::FITKAbstractRegionMeshSize* geom : geomList) { Interface::FITKRegionMeshSizeGeom* geomData = dynamic_cast(geom); if (!geomData)continue; Interface::FITKAbsGeoCommand* geoCommand = FITKDATAREPO->getTDataByID(geomData->getGeomID()); if (!geoCommand)continue; //获取最值 int min = int(geomData->getMinSize()); int max = int(geomData->getMaxSize()); //获取名称 QString name = geoCommand->getDataObjectName(); //创建stl字典组件 DICT::FITKDictGroup* modelGroup = new DICT::FITKDictGroup; refinement->append(name, modelGroup); modelGroup->append("level", QString("( %1 %2 )").arg(min).arg(max)); DICT::FITKDictGroup* patchInfo = new DICT::FITKDictGroup; modelGroup->append("patchInfo", patchInfo); patchInfo->append("type", "wall"); } //获取几何优化管理器 Interface::FITKRegionGeometryRefineManager* geoRefineMgr = meshGen->getRegionGeometryRefineManager(); if (!geoRefineMgr) return false; //体加密-细化区域 DICT::FITKDictGroup* refinementRegions = new DICT::FITKDictGroup; group->append("refinementRegions", refinementRegions); count = geoRefineMgr->getDataCount(); for (int i = 0; i < count; ++i) { //获取区域优化数据 Interface::FITKRegionGeometryRefine* regRefine = geoRefineMgr->getDataByIndex(i); if (!regRefine)continue; //获取几何数据 Interface::FITKAbsGeoCommand* geoCommand = regRefine->getGeometryModel(); if (!geoCommand) continue; DICT::FITKDictGroup* refRegion = new DICT::FITKDictGroup; refinementRegions->append(geoCommand->getDataObjectName(), refRegion); //获取距离和限制 double distance = regRefine->getDistance(); int level = regRefine->getLevel(); //获取优化模式 Interface::FITKRegionGeometryRefine::RefineModelType refinetype = regRefine->getRefineModel(); if (refinetype == Interface::FITKRegionGeometryRefine::RefineModelType::RefineDistance) { refRegion->append("mode", "distance"); refRegion->append("levels", QString("((%1 %2))").arg(distance).arg(level)); } else if (refinetype == Interface::FITKRegionGeometryRefine::RefineModelType::RefineInside) { refRegion->append("mode", "inside"); refRegion->append("levels", QString("((1.0E30 %1))").arg(level)); } else if (refinetype == Interface::FITKRegionGeometryRefine::RefineModelType::RefineOutside) { refRegion->append("mode", "outside"); refRegion->append("levels", QString("((1.0E30 %1))").arg(level)); } //获取间隙参数 int cells = regRefine->getCellsInGapNum(); int maxGap = regRefine->getMaxGapLevel(); //获取间隙模式 Interface::FITKRegionGeometryRefine::GapModelType gaptype = regRefine->getGapRefineModel(); if (gaptype == Interface::FITKRegionGeometryRefine::GapModelType::GapMixed) { refRegion->append("gapMode", "mixed"); refRegion->append("gapLevel", QString("((%1 0 %2))").arg(cells).arg(maxGap)); } else if (gaptype == Interface::FITKRegionGeometryRefine::GapModelType::GapInside) { refRegion->append("gapMode", "inside"); refRegion->append("gapLevel", QString("((%1 0 %2))").arg(cells).arg(maxGap)); } else if (gaptype == Interface::FITKRegionGeometryRefine::GapModelType::GapOutside) { refRegion->append("gapMode", "outside"); refRegion->append("gapLevel", QString("((%1 0 %2))").arg(cells).arg(maxGap)); } } //限制区域 DICT::FITKDictGroup* limitRegions = new DICT::FITKDictGroup; group->append("limitRegions", limitRegions); for (int i = 0; i < count; ++i) { //获取区域优化数据 Interface::FITKRegionGeometryRefine* regRefine = geoRefineMgr->getDataByIndex(i); if (!regRefine)continue; //获取几何数据 Interface::FITKAbsGeoCommand* geoCommand = regRefine->getGeometryModel(); if (!geoCommand) continue; if (!regRefine->getLimitRefineMent())continue; DICT::FITKDictGroup* refRegion = new DICT::FITKDictGroup; limitRegions->append(geoCommand->getDataObjectName(), refRegion); //获取距离和限制 double distance = regRefine->getDistance(); int level = regRefine->getLevel(); //获取优化模式 Interface::FITKRegionGeometryRefine::RefineModelType refinetype = regRefine->getRefineModel(); if (refinetype == Interface::FITKRegionGeometryRefine::RefineModelType::RefineDistance) { refRegion->append("mode", "distance"); refRegion->append("levels", QString("(%1 %2)").arg(distance).arg(level)); } else if (refinetype == Interface::FITKRegionGeometryRefine::RefineModelType::RefineInside) { refRegion->append("mode", "outside"); refRegion->append("levels", QString("(1.0E30 %1)").arg(level)); } else if (refinetype == Interface::FITKRegionGeometryRefine::RefineModelType::RefineOutside) { refRegion->append("mode", "inside"); refRegion->append("levels", QString("(1.0E30 %1)").arg(level)); } } //默认数据 group->append("maxLocalCells", 1000000); group->append("maxGlobalCells", 10000000); group->append("nCellsBetweenLevels", 4); group->append("maxLoadUnbalance", 0.1); group->append("minRefinementCells", 10); group->append("resolveFeatureAngle", 30.0); group->append("allowFreeStandingZoneFaces", true); return true; } bool FITKOFSnappyHexMeshDictWriter::geoFaceGroupStl(Interface::FITKAbsGeoShapeAgent* geoModel, DICT::FITKDictGroup* stlGroup, QString name) { if (!geoModel || !stlGroup)return false; //获取几何组件管理器 Interface::FITKGeoComponentManager* geoComponentManager = geoModel->getGeoComponentManager(); if (!geoComponentManager)return false; //创建面数据字典组件 DICT::FITKDictGroup* faceGroups = new DICT::FITKDictGroup; stlGroup->append("faceGroups", faceGroups); if (!geoModel->getVirtualTopoManager())return false; Interface::FITKShapeVirtualTopoManager* faceMgr = geoModel->getVirtualTopoManager()->getShapeVirtualTopoManager(Interface::FITKGeoEnum::VTopoShapeType::VSFace); if (!faceMgr)return false; //获取模型全部表面数量 int allFaceNum = geoModel->getShapeCount(Interface::FITKModelEnum::FITKModelSetType::FMSSurface); for (int i = 0; i < allFaceNum; ++i) { DICT::FITKDictGroup* face = new DICT::FITKDictGroup; face->append("name", QString("%1").arg(name)); faceGroups->append(QString("face_%1").arg(i), face); } //获取面组链表 QList componentList = geoComponentManager->getGeoComponent(Interface::FITKModelEnum::FITKModelSetType::FMSSurface); for (Interface::FITKGeoComponent* componentData : componentList) { if (!componentData)continue; QString groupName = componentData->getDataObjectName(); //面id QList id_list = componentData->getMember(); for (int i = 0; i < id_list.size(); ++i) { Interface::FITKAbsVirtualTopo* topo = faceMgr->getDataByID(id_list.at(i)); if (!topo)continue; int index = topo->getIndexLabel(); faceGroups->removeKey(QString("face_%1").arg(index)); DICT::FITKDictGroup* face = new DICT::FITKDictGroup; face->append("name", QString("%1_%2").arg(name).arg(groupName)); faceGroups->append(QString("face_%1").arg(index), face); } } return true; } bool FITKOFSnappyHexMeshDictWriter::snapControls() { if (!m_objectDict)return false; //创建添加字典组件 DICT::FITKDictGroup* group = new DICT::FITKDictGroup; m_objectDict->append("snapControls", group); group->append("tolerance", 1.0); group->append("nSmoothPatch", 3); group->append("nSolveIter", 500); group->append("nRelaxIter", 5); group->append("nFeatureSnapIter", 10); group->append("implicitFeatureSnap", false); group->append("explicitFeatureSnap", true); group->append("multiRegionFeatureSnap", true); group->append("nFaceSplitInterval", 5); return true; } bool FITKOFSnappyHexMeshDictWriter::addLayersControls(bool isAddLayers) { if (!m_objectDict || !m_geometryMeshSizeManager)return false; //创建添加图层字典组件 DICT::FITKDictGroup* addLayer = new DICT::FITKDictGroup; m_objectDict->append("addLayersControls", addLayer); //创建添加层级字典组件 DICT::FITKDictGroup* layers = new DICT::FITKDictGroup; addLayer->append("layers", layers); //添加层数 int count = m_geometryMeshSizeManager->getDataCount(); for (int i = 0; i < count; ++i) { Interface::FITKGeometryMeshSize* geoMeshSize = m_geometryMeshSizeManager->getDataByIndex(i); if (!geoMeshSize)continue; //获取数据 int layerNum = geoMeshSize->getLayerNumber(); double ratio = geoMeshSize->getExpansionRatio(); double thickness = geoMeshSize->getLayerThickness(); //获取组件 Interface::FITKGeoComponent* componentData = geoMeshSize->getGeoComponent(); //获取模型 Interface::FITKAbsGeoCommand* geoCommand = geoMeshSize->getGeoModel(); if (!componentData || !geoCommand)continue; Interface::FITKAbsGeoShapeAgent* geoModel = geoCommand->getShapeAgent(); if (!geoModel || !geoModel->getVirtualTopoManager())return false; Interface::FITKShapeVirtualTopoManager* faceMgr = geoModel->getVirtualTopoManager()->getShapeVirtualTopoManager(Interface::FITKGeoEnum::VTopoShapeType::VSFace); if (!faceMgr)return false; QString name = geoCommand->getDataObjectName(); //编号 QList id_list = componentData->getMember(); for (int i = 0; i < id_list.size(); ++i) { Interface::FITKAbsVirtualTopo* topo = faceMgr->getDataByID(id_list.at(i)); if (!topo)continue; DICT::FITKDictGroup* face = new DICT::FITKDictGroup; face->append("nSurfaceLayers", layerNum); face->append("expansionRatio", ratio); face->append("firstLayerThickness", thickness); int index = topo->getIndexLabel(); layers->append(QString("%1_face_%2").arg(name).arg(index), face); } } //添加默认数据 addLayer->append("relativeSizes", true); addLayer->append("minThickness", 0.1); addLayer->append("firstLayerThickness", 0.2); addLayer->append("expansionRatio", 1.25); addLayer->append("nGrow", 0); addLayer->append("featureAngle", 180.0); addLayer->append("maxFaceThicknessRatio", 0.5); addLayer->append("nSmoothSurfaceNormals", 5); addLayer->append("nSmoothThickness", 10); addLayer->append("minMedialAxisAngle", 90.0); addLayer->append("maxThicknessToMedialRatio", 0.5); addLayer->append("nMedialAxisIter", 100); addLayer->append("nSmoothNormals", 3); addLayer->append("slipFeatureAngle", 30.0); addLayer->append("nRelaxIter", 5); addLayer->append("nBufferCellsNoExtrude", 0); addLayer->append("nLayerIter", 50); addLayer->append("nRelaxedIter", 20); addLayer->append("detectExtrusionIsland", true); //是否添加几何层级 if (!isAddLayers)return true; return true; } bool FITKOFSnappyHexMeshDictWriter::meshQualityControls() { if (!m_objectDict)return false; //创建添加字典组件 DICT::FITKDictGroup* group = new DICT::FITKDictGroup; m_objectDict->append("meshQualityControls", group); group->append("maxNonOrtho", 65.0); group->append("maxBoundarySkewness", 20.0); group->append("maxInternalSkewness", 4.0); group->append("maxConcave", 80.0); group->append("minVol", "1.0E-14"); group->append("minTetQuality", "1.0E-20"); group->append("minArea", -1.0); group->append("minTwist", 0.02); group->append("minTriangleTwist", -1.0); group->append("minDeterminant", 0.01); group->append("minFaceWeight", 0.05); group->append("minVolRatio", 0.01); group->append("minVolCollapseRatio", 0.1); group->append("nSmoothScale", 4); group->append("errorReduction", 0.75); DICT::FITKDictGroup* relaxed = new DICT::FITKDictGroup; group->append("relaxed", relaxed); relaxed->append("maxNonOrtho", 75.0); return true; } }