Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #include <OpenFOAM/primitiveMesh.H>
00031 #include <OpenFOAM/pyramidPointFaceRef.H>
00032 #include <OpenFOAM/cell.H>
00033 #include <OpenFOAM/mathematicalConstants.H>
00034 
00035 
00036 
00037 
00038 
00039 
00040 bool Foam::primitiveMesh::checkMeshMotion
00041 (
00042     const pointField& newPoints,
00043     const bool report
00044 ) const
00045 {
00046     if (debug || report)
00047     {
00048         Pout<< "bool primitiveMesh::checkMeshMotion("
00049             << "const pointField& newPoints, const bool report) const: "
00050             << "checking mesh motion" << endl;
00051     }
00052 
00053     bool error = false;
00054 
00055     const faceList& f = faces();
00056 
00057     const labelList& own = faceOwner();
00058     const labelList& nei = faceNeighbour();
00059 
00060     vectorField fCtrs(nFaces());
00061     vectorField fAreas(nFaces());
00062 
00063     makeFaceCentresAndAreas(newPoints, fCtrs, fAreas);
00064 
00065     
00066     vectorField cellCtrs(nCells());
00067     scalarField cellVols(nCells());
00068 
00069     makeCellCentresAndVols(fCtrs, fAreas, cellCtrs, cellVols);
00070 
00071     scalar minVolume = GREAT;
00072     label nNegVols = 0;
00073 
00074     forAll (cellVols, cellI)
00075     {
00076         if (cellVols[cellI] < VSMALL)
00077         {
00078             if (debug || report)
00079             {
00080                 Pout<< "Zero or negative cell volume detected for cell "
00081                     << cellI << ".  Volume = " << cellVols[cellI] << endl;
00082             }
00083 
00084             nNegVols++;
00085         }
00086 
00087         minVolume = min(minVolume, cellVols[cellI]);
00088     }
00089 
00090     if (nNegVols > 0)
00091     {
00092         error = true;
00093 
00094         Pout<< "Zero or negative cell volume in mesh motion in " << nNegVols
00095             << " cells.  Min volume: " << minVolume << endl;
00096     }
00097     else
00098     {
00099         if (debug || report)
00100         {
00101             Pout<< "Min volume = " << minVolume
00102                 << ".  Total volume = " << sum(cellVols)
00103                 << ".  Cell volumes OK." << endl;
00104         }
00105     }
00106 
00107     
00108 
00109     scalar minArea = GREAT;
00110     label nNegAreas = 0;
00111     label nPyrErrors = 0;
00112     label nDotProductErrors = 0;
00113 
00114     forAll (f, faceI)
00115     {
00116         const scalar a = Foam::mag(fAreas[faceI]);
00117 
00118         if (a < VSMALL)
00119         {
00120             if (debug || report)
00121             {
00122                 if (isInternalFace(faceI))
00123                 {
00124                     Pout<< "Zero or negative face area detected for "
00125                         << "internal face "<< faceI << " between cells "
00126                         << own[faceI] << " and " << nei[faceI]
00127                         << ".  Face area magnitude = " << a << endl;
00128                 }
00129                 else
00130                 {
00131                     Pout<< "Zero or negative face area detected for "
00132                         << "boundary face " << faceI << " next to cell "
00133                         << own[faceI] << ".  Face area magnitude = "
00134                         << a << endl;
00135                 }
00136             }
00137 
00138             nNegAreas++;
00139         }
00140 
00141         minArea = min(minArea, a);
00142 
00143         
00144         scalar pyrVol =
00145             pyramidPointFaceRef(f[faceI], cellCtrs[own[faceI]]).mag(newPoints);
00146 
00147         if (pyrVol > SMALL)
00148         {
00149             if (debug || report)
00150             {
00151                 Pout<< "Negative pyramid volume: " << -pyrVol
00152                     << " for face " << faceI << " " << f[faceI]
00153                     << "  and owner cell: " << own[faceI] << endl
00154                     << "Owner cell vertex labels: "
00155                     << cells()[own[faceI]].labels(f)
00156                     << endl;
00157             }
00158 
00159             nPyrErrors++;
00160         }
00161 
00162         if (isInternalFace(faceI))
00163         {
00164             
00165             scalar pyrVol =
00166                 pyramidPointFaceRef
00167                 (
00168                     f[faceI],
00169                     cellCtrs[nei[faceI]]
00170                 ).mag(newPoints);
00171 
00172             if (pyrVol < -SMALL)
00173             {
00174                 if (debug || report)
00175                 {
00176                     Pout<< "Negative pyramid volume: " << pyrVol
00177                         << " for face " << faceI << " " << f[faceI]
00178                         << "  and neighbour cell: " << nei[faceI] << nl
00179                         << "Neighbour cell vertex labels: "
00180                         << cells()[nei[faceI]].labels(f)
00181                         << endl;
00182                 }
00183 
00184                 nPyrErrors++;
00185             }
00186 
00187             const vector d = cellCtrs[nei[faceI]] - cellCtrs[own[faceI]];
00188             const vector& s = fAreas[faceI];
00189             scalar dDotS = (d & s)/(mag(d)*mag(s) + VSMALL);
00190 
00191             
00192             if (dDotS < SMALL && nDotProductErrors == 0)
00193             {
00194                 
00195                 WarningIn
00196                 (
00197                     "primitiveMesh::checkMeshMotion"
00198                     "(const pointField& newPoints, const bool report) const"
00199                 )   << "Severe non-orthogonality in mesh motion for face "
00200                     << faceI
00201                     << " between cells " << own[faceI] << " and " << nei[faceI]
00202                     << ": Angle = " << ::acos(dDotS)/mathematicalConstant::pi*180.0
00203                     << " deg." << endl;
00204 
00205                 nDotProductErrors++;
00206             }
00207         }
00208     }
00209 
00210     if (nNegAreas > 0)
00211     {
00212         error = true;
00213 
00214         WarningIn
00215         (
00216             "primitiveMesh::checkMeshMotion"
00217             "(const pointField& newPoints, const bool report) const"
00218         )   << "Zero or negative face area in mesh motion in " << nNegAreas
00219             << " faces.  Min area: " << minArea << endl;
00220     }
00221     else
00222     {
00223         if (debug || report)
00224         {
00225             Pout<< "Min area = " << minArea
00226                 << ".  Face areas OK." << endl;
00227         }
00228     }
00229 
00230     if (nPyrErrors > 0)
00231     {
00232         Pout<< "Detected " << nPyrErrors
00233             << " negative pyramid volume in mesh motion" << endl;
00234 
00235         error = true;
00236     }
00237     else
00238     {
00239         if (debug || report)
00240         {
00241             Pout<< "Pyramid volumes OK." << endl;
00242         }
00243     }
00244 
00245     if (nDotProductErrors > 0)
00246     {
00247         Pout<< "Detected " << nDotProductErrors
00248             << " in non-orthogonality in mesh motion." << endl;
00249 
00250         error = true;
00251     }
00252     else
00253     {
00254         if (debug || report)
00255         {
00256             Pout<< "Non-orthogonality check OK." << endl;
00257         }
00258     }
00259 
00260     if (!error && (debug || report))
00261     {
00262         Pout << "Mesh motion check OK." << endl;
00263     }
00264 
00265     return error;
00266 }
00267 
00268 
00269