conservativeMeshToMesh::conservativeMeshToMesh ( const fvMesh& srcMesh, const fvMesh& tgtMesh, const label nThreads, const bool forceRecalculation, const bool writeAddressing ) : meshSrc_(srcMesh), meshTgt_(tgtMesh), addressing_ ( IOobject ( "addressing", tgtMesh.time().timeName(), tgtMesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE ), tgtMesh.nCells() ), weights_ ( IOobject ( "weights", tgtMesh.time().timeName(), tgtMesh, IOobject::NO_READ, IOobject::NO_WRITE ), tgtMesh.nCells() ), centres_ ( IOobject ( "centres", tgtMesh.time().timeName(), tgtMesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE ), tgtMesh.nCells() ), cellAddressing_(tgtMesh.nCells()), counter_(0), boundaryAddressing_(tgtMesh.boundaryMesh().size()) { if (addressing_.headerOk() && weights_.headerOk() && centres_.headerOk()) { // Check if sizes match. Otherwise, re-calculate. if ( addressing_.size() == tgtMesh.nCells() && weights_.size() == tgtMesh.nCells() && centres_.size() == tgtMesh.nCells() && !forceRecalculation ) { Info<< " Reading addressing from file." << endl; return; } Info<< " Recalculating addressing." << endl; } else { Info<< " Calculating addressing." << endl; } // Check if the source mesh has a calculated addressing // If yes, try and invert that. IOobject srcHeader ( "addressing", srcMesh.time().timeName(), srcMesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE ); if (srcHeader.headerOk() && !addressing_.headerOk()) { Info<< " Found addressing in source directory." << " Checking for compatibility." << endl; if (invertAddressing()) { Info<< " Inversion successful. " << endl; return; } } // Track calculation time clockTime calcTimer; // Compute nearest cell addressing calcCellAddressing(); if (nThreads == 1) { calcAddressingAndWeights(0, tgtMesh.nCells(), true); } else { // Prior to multi-threaded operation, // force calculation of demand-driven data tgtMesh.cells(); srcMesh.cells(); srcMesh.cellCentres(); srcMesh.cellCells(); multiThreader threader(nThreads); // Set one handler per thread PtrList<handler> hdl(threader.getNumThreads()); forAll(hdl, i) { hdl.set(i, new handler(*this, threader)); } // Simple, but inefficient load-balancing scheme labelList tStarts(threader.getNumThreads(), 0); labelList tSizes(threader.getNumThreads(), 0); label index = tgtMesh.nCells(), j = 0; while (index--) { tSizes[(j = tSizes.fcIndex(j))]++; } label total = 0; for (label i = 1; i < tStarts.size(); i++) { tStarts[i] = tSizes[i-1] + total; total += tSizes[i-1]; } if (debug) { Info<< " Load starts: " << tStarts << endl; Info<< " Load sizes: " << tSizes << endl; } // Set the argument list for each thread forAll(hdl, i) { // Size up the argument list hdl[i].setSize(2); // Set the start/end cell indices hdl[i].set(0, &tStarts[i]); hdl[i].set(1, &tSizes[i]); // Lock the slave thread first hdl[i].lock(handler::START); hdl[i].unsetPredicate(handler::START); hdl[i].lock(handler::STOP); hdl[i].unsetPredicate(handler::STOP); }
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh>> Foam::levelSetAverage ( const fvMesh& mesh, const scalarField& levelC, const scalarField& levelP, const DimensionedField<Type, volMesh>& positiveC, const DimensionedField<Type, pointMesh>& positiveP, const DimensionedField<Type, volMesh>& negativeC, const DimensionedField<Type, pointMesh>& negativeP ) { tmp<DimensionedField<Type, volMesh>> tResult ( new DimensionedField<Type, volMesh> ( IOobject ( positiveC.name() + ":levelSetAverage", mesh.time().timeName(), mesh ), mesh, dimensioned<Type>("0", positiveC.dimensions(), Zero) ) ); DimensionedField<Type, volMesh>& result = tResult.ref(); forAll(result, cI) { const List<tetIndices> cellTetIs = polyMeshTetDecomposition::cellTetIndices(mesh, cI); scalar v = 0; Type r = Zero; forAll(cellTetIs, cellTetI) { const triFace triIs = cellTetIs[cellTetI].faceTriIs(mesh); const FixedList<point, 4> tet = { mesh.cellCentres()[cI], mesh.points()[triIs[0]], mesh.points()[triIs[1]], mesh.points()[triIs[2]] }; const FixedList<scalar, 4> level = { levelC[cI], levelP[triIs[0]], levelP[triIs[1]], levelP[triIs[2]] }; const cut::volumeIntegrateOp<Type> positive = FixedList<Type, 4> ({ positiveC[cI], positiveP[triIs[0]], positiveP[triIs[1]], positiveP[triIs[2]] }); const cut::volumeIntegrateOp<Type> negative = FixedList<Type, 4> ({ negativeC[cI], negativeP[triIs[0]], negativeP[triIs[1]], negativeP[triIs[2]] }); v += cut::volumeOp()(tet); r += tetCut(tet, level, positive, negative); } result[cI] = r/v; } return tResult; }