/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2018-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "MapLagrangianFields.H" #include "passiveParticleCloud.H" #include "meshSearch.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { static const scalar perturbFactor = 1e-6; // Special version of findCell that generates a cell guaranteed to be // compatible with tracking. static label findCell(const Cloud& cloud, const point& pt) { label celli = -1; label tetFacei = -1; label tetPtI = -1; const polyMesh& mesh = cloud.pMesh(); mesh.findCellFacePt(pt, celli, tetFacei, tetPtI); if (celli >= 0) { return celli; } else { // See if particle on face by finding nearest face and shifting // particle. meshSearch meshSearcher ( mesh, polyMesh::FACE_PLANES // no decomposition needed ); label facei = meshSearcher.findNearestBoundaryFace(pt); if (facei >= 0) { const point& cc = mesh.cellCentres()[mesh.faceOwner()[facei]]; const point perturbPt = (1-perturbFactor)*pt+perturbFactor*cc; mesh.findCellFacePt(perturbPt, celli, tetFacei, tetPtI); return celli; } } return -1; } void mapLagrangian(const meshToMesh& interp) { // Determine which particles are in meshTarget // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const polyMesh& meshSource = interp.srcRegion(); const polyMesh& meshTarget = interp.tgtRegion(); const labelListList& sourceToTarget = interp.srcToTgtCellAddr(); const fileNameList cloudDirs ( readDir ( meshSource.time().timePath()/cloud::prefix, fileName::DIRECTORY ) ); for (const fileName& cloudDir : cloudDirs) { // Search for list of lagrangian objects for this time IOobjectList objects ( meshSource, meshSource.time().timeName(), cloud::prefix/cloudDir ); if ( returnReduceOr ( objects.found("coordinates") || objects.found("positions") ) ) { // Has coordinates/positions - so must be a valid cloud Info<< nl << " processing cloud " << cloudDir << endl; // Read positions & cell passiveParticleCloud sourceParcels ( meshSource, cloudDir, false ); Info<< " read " << sourceParcels.size() << " parcels from source mesh." << endl; // Construct empty target cloud passiveParticleCloud targetParcels ( meshTarget, Foam::zero{}, cloudDir ); passiveParticle::trackingData td(targetParcels); label sourceParticleI = 0; // Indices of source particles that get added to targetParcels DynamicList