diff --git a/.gitignore b/.gitignore index 765362f15..b426cd4ee 100644 --- a/.gitignore +++ b/.gitignore @@ -173,4 +173,12 @@ src/lduSolvers/amg/amgPolicy/samgPolicy.H src/lduSolvers/amg/amgPolicy/aamgPolicy.C src/lduSolvers/amg/amgPolicy/aamgPolicy.H +# The following files are blacklisted because of a DMCA complaint by ANSYS. +src/lduSolvers/tools/PriorityArray.C +src/lduSolvers/tools/PriorityArray.H +src/lduSolvers/amg/amgPolicy/samgPolicy.C +src/lduSolvers/amg/amgPolicy/samgPolicy.H +src/lduSolvers/amg/amgPolicy/aamgPolicy.C +src/lduSolvers/amg/amgPolicy/aamgPolicy.H + # end-of-file diff --git a/src/dynamicMesh/meshMotion/mesquiteMotionSolver/mesquiteMotionSolver.C b/src/dynamicMesh/meshMotion/mesquiteMotionSolver/mesquiteMotionSolver.C index 20926f113..d6bebd5c1 100644 --- a/src/dynamicMesh/meshMotion/mesquiteMotionSolver/mesquiteMotionSolver.C +++ b/src/dynamicMesh/meshMotion/mesquiteMotionSolver/mesquiteMotionSolver.C @@ -27,7 +27,9 @@ License #include "mesquiteMotionSolver.H" #include "Random.H" #include "IOmanip.H" +#include "SortableList.H" #include "globalMeshData.H" +#include "cyclicPolyPatch.H" #include "processorPolyPatch.H" #include "addToRunTimeSelectionTable.H" #include "polyMesh.H" @@ -37,6 +39,11 @@ License #include "pointPatchField.H" #include "pointMesh.H" +#include "hexMatcher.H" +#include "tetMatcher.H" +#include "pyrMatcher.H" +#include "prismMatcher.H" + // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam @@ -71,9 +78,6 @@ mesquiteMotionSolver::mesquiteMotionSolver nSweeps_(1), surfInterval_(1), relax_(1.0), - vtxCoords_(NULL), - cellToNode_(NULL), - fixFlags_(NULL), refPoints_ ( IOobject @@ -114,9 +118,6 @@ mesquiteMotionSolver::mesquiteMotionSolver nSweeps_(1), surfInterval_(1), relax_(1.0), - vtxCoords_(NULL), - cellToNode_(NULL), - fixFlags_(NULL), refPoints_ ( IOobject @@ -138,33 +139,9 @@ mesquiteMotionSolver::mesquiteMotionSolver // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // mesquiteMotionSolver::~mesquiteMotionSolver() -{ - clearOut(); -} +{} -// Clear out addressing -void mesquiteMotionSolver::clearOut() -{ - if (debug) - { - Info<< "Clearing out mesquite arrays" << endl; - } - - // Delete memory pointers - delete [] vtxCoords_; - delete [] cellToNode_; - delete [] fixFlags_; - - // Reset to NULL - vtxCoords_ = NULL; - cellToNode_ = NULL; - fixFlags_ = NULL; - - // Reset array flag - arraysInitialized_ = false; -} - // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // Parallel blocking send @@ -443,19 +420,99 @@ void mesquiteMotionSolver::readOptions() ) ); - // Read the optimization metric - qMetric_ = word(optionsDict.lookup("optMetric")); + qMetricTable_.insert + ( + "EdgeLengthQuality", + autoPtr + ( + new Mesquite::EdgeLengthQualityMetric + ) + ); - if (!qMetricTable_.found(qMetric_)) + qMetricTable_.insert + ( + "EdgeLength", + autoPtr + ( + new Mesquite::EdgeLengthMetric + ) + ); + + qMetricTable_.insert + ( + "UntangleBeta", + autoPtr + ( + new Mesquite::UntangleBetaQualityMetric + ) + ); + + qMetricTable_.insert + ( + "LocalSize", + autoPtr + ( + new Mesquite::LocalSizeQualityMetric + ) + ); + + // Size up metric list to contain at least one entry + qMetrics_.setSize(1); + + // Read the optimization metric + if (optionsDict.isDict("optMetric")) { - FatalErrorIn("void mesquiteMotionSolver::readOptions()") - << "Unrecognized quality metric: " << qMetric_ << nl - << "Available metrics are: " << nl << qMetricTable_.toc() - << abort(FatalError); + // Metrics are in dictionary form + const dictionary& metricDict = optionsDict.subDict("optMetric"); + + // Read first metric + qMetrics_[0] = word(metricDict.lookup("firstMetric")); + + // Optionally read the second metric + if (metricDict.found("secondMetric")) + { + qMetrics_.setSize(2); + qMetrics_[1] = word(metricDict.lookup("secondMetric")); + } + + forAll(qMetrics_, wordI) + { + if (!qMetricTable_.found(qMetrics_[wordI])) + { + FatalErrorIn("void mesquiteMotionSolver::readOptions()") + << "Unrecognized quality metric: " + << qMetrics_[wordI] << nl + << "Available metrics are: " + << nl << qMetricTable_.toc() + << abort(FatalError); + } + else + { + Info<< "Selecting quality metric: " + << qMetrics_[wordI] << endl; + } + } } else { - Info<< "Selecting quality metric: " << qMetric_ << endl; + // Conventional keyword entry + + // Alias for convenience... + word& qMetric = qMetrics_[0]; + + qMetric = word(optionsDict.lookup("optMetric")); + + if (!qMetricTable_.found(qMetric)) + { + FatalErrorIn("void mesquiteMotionSolver::readOptions()") + << "Unrecognized quality metric: " << qMetric << nl + << "Available metrics are: " << nl << qMetricTable_.toc() + << abort(FatalError); + } + else + { + Info<< "Selecting quality metric: " << qMetric << endl; + } } // Define the objective function table, @@ -510,6 +567,14 @@ void mesquiteMotionSolver::readOptions() << "Cannot make a composite of composite functions." << abort(FatalError); } + + // Make sure we have two quality metrics + if (qMetrics_.size() < 2) + { + FatalErrorIn("void mesquiteMotionSolver::readOptions()") + << "Two quality metrics are needed for composite functions." + << abort(FatalError); + } } else // Check if a scaled function is requested @@ -552,7 +617,7 @@ void mesquiteMotionSolver::readOptions() ( new Mesquite::LInfTemplate ( - &qMetricTable_[qMetric_]() + &qMetricTable_[qMetrics_[i]]() ) ); @@ -568,7 +633,7 @@ void mesquiteMotionSolver::readOptions() ( new Mesquite::LPtoPTemplate ( - &qMetricTable_[qMetric_](), + &qMetricTable_[qMetrics_[i]](), pValue, err ) @@ -584,7 +649,7 @@ void mesquiteMotionSolver::readOptions() ( new Mesquite::MaxTemplate ( - &qMetricTable_[qMetric_]() + &qMetricTable_[qMetrics_[i]]() ) ); @@ -603,7 +668,7 @@ void mesquiteMotionSolver::readOptions() new Mesquite::PMeanPTemplate ( power, - &qMetricTable_[qMetric_]() + &qMetricTable_[qMetrics_[i]]() ) ); @@ -616,7 +681,7 @@ void mesquiteMotionSolver::readOptions() ( new Mesquite::StdDevTemplate ( - &qMetricTable_[qMetric_]() + &qMetricTable_[qMetrics_[i]]() ) ); @@ -629,7 +694,7 @@ void mesquiteMotionSolver::readOptions() ( new Mesquite::VarianceTemplate ( - &qMetricTable_[qMetric_]() + &qMetricTable_[qMetrics_[i]]() ) ); @@ -647,7 +712,7 @@ void mesquiteMotionSolver::readOptions() new Mesquite::PatchPowerMeanP ( power, - &qMetricTable_[qMetric_]() + &qMetricTable_[qMetrics_[i]]() ) ); @@ -794,7 +859,7 @@ void mesquiteMotionSolver::readOptions() ( dynamic_cast ( - &qMetricTable_[qMetric_]() + &qMetricTable_[qMetrics_[0]]() ) ) ); @@ -1142,50 +1207,103 @@ void mesquiteMotionSolver::initArrays() return; } - // Prepare arrays for mesquite - vtxCoords_ = new double[3 * nPoints_]; - cellToNode_ = new unsigned long[4 * nCells_]; - fixFlags_ = new int[nPoints_]; + // Construct shape recognizers + label nUnknown = 0; + FixedList nTypes(0); + FixedList, 4> matcher; + FixedList cellType; - // Set connectivity information - label cIndex = 0; + // Set types + matcher[0].set(new hexMatcher()); + cellType[0] = Mesquite::HEXAHEDRON; + + matcher[1].set(new tetMatcher()); + cellType[1] = Mesquite::TETRAHEDRON; + + matcher[2].set(new pyrMatcher()); + cellType[2] = Mesquite::PYRAMID; + + matcher[3].set(new prismMatcher()); + cellType[3] = Mesquite::PRISM; const faceList& meshFaces = mesh().faces(); const cellList& meshCells = mesh().cells(); - const labelList& owner = mesh().faceOwner(); + const labelList& faceOwner = mesh().faceOwner(); forAll(meshCells, cellI) { - const cell& curCell = meshCells[cellI]; - const face& currFace = meshFaces[curCell[0]]; - const face& nextFace = meshFaces[curCell[1]]; + bool foundMatch = false; - // Get the fourth point - forAll(nextFace, pointI) + forAll(matcher, indexI) { - if - ( - nextFace[pointI] != currFace[0] - && nextFace[pointI] != currFace[1] - && nextFace[pointI] != currFace[2] - ) + if (matcher[indexI]->isA(mesh(), cellI)) { - // Fill in cellPoints in order - if (owner[curCell[0]] == cellI) + nTypes[indexI]++; + + foundMatch = true; + break; + } + } + + if (!foundMatch) + { + nUnknown++; + } + } + + if (debug) + { + Pout<< "nHex = " << nTypes[0] << nl + << "nTet = " << nTypes[1] << nl + << "nPyr = " << nTypes[2] << nl + << "nPrism = " << nTypes[3] << nl + << "nUnknown = " << nUnknown << endl; + } + + label nCellToNode = + ( + (8 * nTypes[0]) + + (4 * nTypes[1]) + + (5 * nTypes[2]) + + (6 * nTypes[3]) + ); + + // Prepare arrays for mesquite + vtxCoords_.setSize(3 * nPoints_); + cellToNode_.setSize(nCellToNode); + fixFlags_.setSize(nPoints_); + mixedTypes_.setSize(nCells_); + + // Set connectivity information + label cIndex = 0, cellIndex = 0; + + forAll(meshCells, cellI) + { + forAll(matcher, indexI) + { + if (matcher[indexI]->isA(mesh(), cellI)) + { + // Match shape + matcher[indexI]->matchShape + ( + false, + meshFaces, + faceOwner, + cellI, + meshCells[cellI] + ); + + // Set cellToNode + const labelList& cellToNode = matcher[indexI]->vertLabels(); + + forAll(cellToNode, nodeI) { - cellToNode_[cIndex++] = currFace[2]; - cellToNode_[cIndex++] = currFace[1]; - cellToNode_[cIndex++] = currFace[0]; - cellToNode_[cIndex++] = nextFace[pointI]; - } - else - { - cellToNode_[cIndex++] = currFace[0]; - cellToNode_[cIndex++] = currFace[1]; - cellToNode_[cIndex++] = currFace[2]; - cellToNode_[cIndex++] = nextFace[pointI]; + cellToNode_[cIndex++] = cellToNode[nodeI]; } + // Set element type + mixedTypes_[cellIndex++] = cellType[indexI]; + break; } } @@ -1213,6 +1331,29 @@ void mesquiteMotionSolver::initArrays() } } + // Optionally fix additional zone points + const dictionary& optionsDict = subDict("mesquiteOptions"); + + if (optionsDict.found("fixPointsZone")) + { + wordList fixZones = optionsDict.subDict("fixPointsZone").toc(); + + forAll(fixZones, zoneI) + { + label zoneID = mesh().pointZones().findZoneID(fixZones[zoneI]); + + if (zoneID > -1) + { + const pointZone& pLabels = mesh().pointZones()[zoneID]; + + forAll(pLabels, pointI) + { + fixFlags_[pLabels[pointI]] = 1; + } + } + } + } + // Initialise parallel connectivity, if necessary initParallelConnectivity(); @@ -1242,16 +1383,17 @@ void mesquiteMotionSolver::identifyCoupledPatches() // Fetch the list of global points from polyMesh. const globalMeshData& gData = mesh().globalData(); - const labelList& spAddr = gData.sharedPointAddr(); - const labelList& spLabels = gData.sharedPointLabels(); + const labelList& spA = gData.sharedPointAddr(); + const labelList& spL = gData.sharedPointLabels(); - labelListList spBuffer(Pstream::nProcs(), labelList(0)); + labelListList spB(Pstream::nProcs(), labelList(0)); if (gData.nGlobalPoints()) { if (debug) { - Info<< " Found " << gData.nGlobalPoints() + Info<< " mesquiteMotionSolver::identifyCoupledPatches :" + << " Found " << gData.nGlobalPoints() << " global points." << endl; } @@ -1261,12 +1403,12 @@ void mesquiteMotionSolver::identifyCoupledPatches() if (proc != Pstream::myProcNo()) { // Send number of entities first. - parWrite(proc, spAddr.size()); + parWrite(proc, spA.size()); // Send the buffer. - if (spAddr.size()) + if (spA.size()) { - parWrite(proc, spAddr); + parWrite(proc, spA); } } } @@ -1284,10 +1426,10 @@ void mesquiteMotionSolver::identifyCoupledPatches() if (procInfoSize) { // Size the receive buffer. - spBuffer[proc].setSize(procInfoSize, -1); + spB[proc].setSize(procInfoSize, -1); // Schedule for receipt. - parRead(proc, spBuffer[proc]); + parRead(proc, spB[proc]); } } } @@ -1295,11 +1437,19 @@ void mesquiteMotionSolver::identifyCoupledPatches() else if (debug) { - Info<< "Did not find any global points." << endl; + Info<< " mesquiteMotionSolver::identifyCoupledPatches :" + << " Did not find any global points." << endl; } labelHashSet immNeighbours; - labelListList procPatchPoints(Pstream::nProcs()); + labelListList procPoints(Pstream::nProcs()); + + // Track globally shared points + List > globalProcPoints + ( + Pstream::nProcs(), + DynamicList(5) + ); // Insert my immediate neighbours into the list. forAll(boundary, pI) @@ -1314,7 +1464,7 @@ void mesquiteMotionSolver::identifyCoupledPatches() label neiProcNo = pp.neighbProcNo(); // Insert all boundary points. - procPatchPoints[neiProcNo] = pp.meshPoints(); + procPoints[neiProcNo] = pp.meshPoints(); // Keep track of immediate neighbours. immNeighbours.insert(neiProcNo); @@ -1333,39 +1483,69 @@ void mesquiteMotionSolver::identifyCoupledPatches() // as well (if not already). for (label proc = 0; proc < Pstream::nProcs(); proc++) { - if - ( - (proc != Pstream::myProcNo()) && - (!immNeighbours.found(proc)) - ) + if (proc == Pstream::myProcNo()) { - bool foundGlobalMatch = false; + continue; + } - labelHashSet neiSet; + bool foundGlobalMatch = false; - forAll(spBuffer[proc], pointI) + // Fetch reference to buffer + const labelList& procBuffer = spB[proc]; + DynamicList& gPP = globalProcPoints[proc]; + + forAll(procBuffer, pointI) + { + forAll(spA, pointJ) { - forAll(spAddr, pointJ) + if (spA[pointJ] == procBuffer[pointI]) { - if (spAddr[pointJ] == spBuffer[proc][pointI]) + // Make an entry, if one wasn't made already + if (findIndex(procPoints[proc], spL[pointJ]) == -1) { - // Make an entry - neiSet.insert(spLabels[pointJ]); - - foundGlobalMatch = true; - - break; + gPP.append(labelPair(spL[pointJ], spA[pointJ])); } + + foundGlobalMatch = true; + + break; } } + } - if (foundGlobalMatch && debug) + // Sort in ascending order of global point labels + if (gPP.size()) + { + SortableList