void Foam::primitiveMesh::makeCellCentresAndVols ( const vectorField& fCtrs, const vectorField& fAreas, vectorField& cellCtrs, scalarField& cellVols ) const { // Clear the fields for accumulation cellCtrs = vector::zero; cellVols = 0.0; const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); // first estimate the approximate cell centre as the average of // face centres vectorField cEst(nCells(), vector::zero); labelField nCellFaces(nCells(), 0); forAll(own, facei) { cEst[own[facei]] += fCtrs[facei]; nCellFaces[own[facei]] += 1; }
const Foam::labelListList& Foam::primitiveMesh::cellPoints() const { if (!cpPtr_) { if (debug) { Pout<< "primitiveMesh::cellPoints() : " << "calculating cellPoints" << endl; if (debug == -1) { // For checking calls:abort so we can quickly hunt down // origin of call FatalErrorIn("primitiveMesh::cellPoints()") << abort(FatalError); } } // Invert pointCells cpPtr_ = new labelListList(nCells()); invertManyToMany(nCells(), pointCells(), *cpPtr_); } return *cpPtr_; }
void Foam::fvMesh::mapOldVolumes(const mapPolyMesh& meshMap) { const labelList& cellMap = meshMap.cellMap(); // Map the old volume. Just map to new cell labels. if (V0Ptr_) { if (debug) { InfoIn("void fvMesh::mapOldVolumes(const mapPolyMesh& meshMap)") << "Mapping old cell volumes." << endl; } scalarField& V0 = *V0Ptr_; scalarField savedV0(V0); V0.setSize(nCells()); forAll (V0, i) { if (cellMap[i] > -1) { V0[i] = savedV0[cellMap[i]]; } else { V0[i] = 0.0; } } } // Map the old-old volume. Just map to new cell labels. if (V00Ptr_) { if (debug) { InfoIn("void fvMesh::mapOldVolumes(const mapPolyMesh& meshMap)") << "Mapping old-old cell volumes." << endl; } scalarField& V00 = *V00Ptr_; scalarField savedV00(V00); V00.setSize(nCells()); forAll (V00, i) { if (cellMap[i] > -1) { V00[i] = savedV00[cellMap[i]]; } else { V00[i] = 0.0; } } } }
void Foam::primitiveMesh::calcCellShapes() const { if (debug) { Pout<< "primitiveMesh::calcCellShapes() : calculating cellShapes" << endl; } // It is an error to attempt to recalculate faceCells // if the pointer is already set if (cellShapesPtr_) { FatalErrorInFunction << "cellShapes already calculated" << abort(FatalError); } else { cellShapesPtr_ = new cellShapeList(nCells()); cellShapeList& cellShapes = *cellShapesPtr_; forAll(cellShapes, celli) { cellShapes[celli] = degenerateMatcher::match(*this, celli); } }
Foam::List<Foam::FixedList<Foam::label, 8>> Foam::block::cells() const { const label ni = density().x(); const label nj = density().y(); const label nk = density().z(); List<FixedList<label, 8>> cells(nCells()); label celli = 0; for (label k=0; k<nk; k++) { for (label j=0; j<nj; j++) { for (label i=0; i<ni; i++) { cells[celli][0] = pointLabel(i, j, k); cells[celli][1] = pointLabel(i+1, j, k); cells[celli][2] = pointLabel(i+1, j+1, k); cells[celli][3] = pointLabel(i, j+1, k); cells[celli][4] = pointLabel(i, j, k+1); cells[celli][5] = pointLabel(i+1, j, k+1); cells[celli][6] = pointLabel(i+1, j+1, k+1); cells[celli][7] = pointLabel(i, j+1, k+1); celli++; } } } return cells; }
void Foam::block::createCells() const { const label ni = meshDensity().x(); const label nj = meshDensity().y(); const label nk = meshDensity().z(); // // generate cells // cells_.clear(); cells_.setSize(nCells()); label cellNo = 0; for (label k = 0; k < nk; k++) { for (label j = 0; j < nj; j++) { for (label i = 0; i < ni; i++) { cells_[cellNo].setSize(8); cells_[cellNo][0] = vtxLabel(i, j, k); cells_[cellNo][1] = vtxLabel(i+1, j, k); cells_[cellNo][2] = vtxLabel(i+1, j+1, k); cells_[cellNo][3] = vtxLabel(i, j+1, k); cells_[cellNo][4] = vtxLabel(i, j, k+1); cells_[cellNo][5] = vtxLabel(i+1, j, k+1); cells_[cellNo][6] = vtxLabel(i+1, j+1, k+1); cells_[cellNo][7] = vtxLabel(i, j+1, k+1); cellNo++; } } } }
void primitiveMesh::makeCellCentresAndVols ( const vectorField& fCtrs, const vectorField& fAreas, vectorField& cellCtrs, scalarField& cellVols ) const { // Clear the fields for accumulation cellCtrs = vector::zero; cellVols = 0.0; const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); // next calculate exact cell volume and centre scalarField r1(nCells(), -1); scalarField r2(nCells(), -1); forAll (faces(), faceI) { if (!isRadialFace(fCtrs[faceI], fAreas[faceI])) { cellVols[own[faceI]] += fCtrs[faceI] & fAreas[faceI]; cellCtrs[own[faceI]] += fCtrs[faceI]; if (r1[own[faceI]] < 0) { r1 = mag(fCtrs[faceI]); } else { r2[own[faceI]] = mag(fCtrs[faceI]); } if (faceI < nInternalFaces()) { cellVols[nei[faceI]] += fCtrs[faceI] & fAreas[faceI]; cellCtrs[nei[faceI]] += fCtrs[faceI]; r2[nei[faceI]] = mag(fCtrs[faceI]); } } } cellVols *= 1./3.; cellCtrs *= 0.5*(r1+r2)/mag(cellCtrs); }
void Foam::primitiveMesh::calcCellCells() const { // Loop through faceCells and mark up neighbours if (debug) { Pout<< "primitiveMesh::calcCellCells() : calculating cellCells" << endl; if (debug == -1) { // For checking calls:abort so we can quickly hunt down // origin of call FatalErrorIn("primitiveMesh::calcCellCells()") << abort(FatalError); } } // It is an error to attempt to recalculate cellCells // if the pointer is already set if (ccPtr_) { FatalErrorIn("primitiveMesh::calcCellCells() const") << "cellCells already calculated" << abort(FatalError); } else { // 1. Count number of internal faces per cell labelList ncc(nCells(), 0); const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); forAll (nei, faceI) { ncc[own[faceI]]++; ncc[nei[faceI]]++; } // Create the storage ccPtr_ = new labelListList(ncc.size()); labelListList& cellCellAddr = *ccPtr_; // 2. Size and fill cellFaceAddr forAll (cellCellAddr, cellI) { cellCellAddr[cellI].setSize(ncc[cellI]); }
void Foam::primitiveMesh::calcCellCentresAndVols() const { if (debug) { Pout<< "primitiveMesh::calcCellCentresAndVols() : " << "Calculating cell centres and cell volumes" << endl; } // It is an error to attempt to recalculate cellCentres // if the pointer is already set if (cellCentresPtr_ || cellVolumesPtr_) { FatalErrorIn("primitiveMesh::calcCellCentresAndVols() const") << "Cell centres or cell volumes already calculated" << abort(FatalError); } // set the accumulated cell centre to zero vector cellCentresPtr_ = new vectorField(nCells()); vectorField& cellCtrs = *cellCentresPtr_; // Initialise cell volumes to 0 cellVolumesPtr_ = new scalarField(nCells()); scalarField& cellVols = *cellVolumesPtr_; // Make centres and volumes makeCellCentresAndVols(faceCentres(), faceAreas(), cellCtrs, cellVols); if (debug) { Pout<< "primitiveMesh::calcCellCentresAndVols() : " << "Finished calculating cell centres and cell volumes" << endl; } }
Foam::polyMesh::polyMesh(const IOobject& io) : objectRegistry(io), primitiveMesh(), points_ ( IOobject ( "points", time().findInstance(meshDir(), "points"), meshSubDir, *this, IOobject::MUST_READ, IOobject::NO_WRITE ) ), faces_ ( IOobject ( "faces", time().findInstance(meshDir(), "faces"), meshSubDir, *this, IOobject::MUST_READ, IOobject::NO_WRITE ) ), owner_ ( IOobject ( "owner", faces_.instance(), meshSubDir, *this, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE ) ), neighbour_ ( IOobject ( "neighbour", faces_.instance(), meshSubDir, *this, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE ) ), clearedPrimitives_(false), boundary_ ( IOobject ( "boundary", time().findInstance(meshDir(), "boundary"), meshSubDir, *this, IOobject::MUST_READ, IOobject::NO_WRITE ), *this ), bounds_(points_), comm_(UPstream::worldComm), geometricD_(Vector<label>::zero), solutionD_(Vector<label>::zero), tetBasePtIsPtr_(NULL), cellTreePtr_(NULL), pointZones_ ( IOobject ( "pointZones", time().findInstance ( meshDir(), "pointZones", IOobject::READ_IF_PRESENT ), meshSubDir, *this, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE ), *this ), faceZones_ ( IOobject ( "faceZones", time().findInstance ( meshDir(), "faceZones", IOobject::READ_IF_PRESENT ), meshSubDir, *this, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE ), *this ), cellZones_ ( IOobject ( "cellZones", time().findInstance ( meshDir(), "cellZones", IOobject::READ_IF_PRESENT ), meshSubDir, *this, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE ), *this ), globalMeshDataPtr_(NULL), moving_(false), topoChanging_(false), curMotionTimeIndex_(time().timeIndex()), oldPointsPtr_(NULL) { if (exists(owner_.objectPath())) { initMesh(); } else { cellCompactIOList cLst ( IOobject ( "cells", time().findInstance(meshDir(), "cells"), meshSubDir, *this, IOobject::MUST_READ, IOobject::NO_WRITE ) ); // Set the primitive mesh initMesh(cLst); owner_.write(); neighbour_.write(); } // Calculate topology for the patches (processor-processor comms etc.) boundary_.updateMesh(); // Calculate the geometry for the patches (transformation tensors etc.) boundary_.calcGeometry(); // Warn if global empty mesh if (returnReduce(nPoints(), sumOp<label>()) == 0) { WarningIn("polyMesh(const IOobject&)") << "no points in mesh" << endl; } if (returnReduce(nCells(), sumOp<label>()) == 0) { WarningIn("polyMesh(const IOobject&)") << "no cells in mesh" << endl; } // Initialise demand-driven data calcDirections(); }
void Foam::fvMesh::mapFields(const mapPolyMesh& meshMap) { if (debug) { Info<< "fvMesh::mapFields :" << " nOldCells:" << meshMap.nOldCells() << " nCells:" << nCells() << " nOldFaces:" << meshMap.nOldFaces() << " nFaces:" << nFaces() << endl; } // We require geometric properties valid for the old mesh if ( meshMap.cellMap().size() != nCells() || meshMap.faceMap().size() != nFaces() ) { FatalErrorIn("fvMesh::mapFields(const mapPolyMesh&)") << "mapPolyMesh does not correspond to the old mesh." << " nCells:" << nCells() << " cellMap:" << meshMap.cellMap().size() << " nOldCells:" << meshMap.nOldCells() << " nFaces:" << nFaces() << " faceMap:" << meshMap.faceMap().size() << " nOldFaces:" << meshMap.nOldFaces() << exit(FatalError); } // Create a mapper const fvMeshMapper mapper(*this, meshMap); // Map all the volFields in the objectRegistry MapGeometricFields<scalar, fvPatchField, fvMeshMapper, volMesh> (mapper); MapGeometricFields<vector, fvPatchField, fvMeshMapper, volMesh> (mapper); MapGeometricFields<sphericalTensor, fvPatchField, fvMeshMapper, volMesh> (mapper); MapGeometricFields<symmTensor, fvPatchField, fvMeshMapper, volMesh> (mapper); MapGeometricFields<tensor, fvPatchField, fvMeshMapper, volMesh> (mapper); // Map all the surfaceFields in the objectRegistry MapGeometricFields<scalar, fvsPatchField, fvMeshMapper, surfaceMesh> (mapper); MapGeometricFields<vector, fvsPatchField, fvMeshMapper, surfaceMesh> (mapper); MapGeometricFields<symmTensor, fvsPatchField, fvMeshMapper, surfaceMesh> (mapper); MapGeometricFields<symmTensor, fvsPatchField, fvMeshMapper, surfaceMesh> (mapper); MapGeometricFields<tensor, fvsPatchField, fvMeshMapper, surfaceMesh> (mapper); // Map all the dimensionedFields in the objectRegistry MapDimensionedFields<scalar, fvMeshMapper, volMesh>(mapper); MapDimensionedFields<vector, fvMeshMapper, volMesh>(mapper); MapDimensionedFields<sphericalTensor, fvMeshMapper, volMesh>(mapper); MapDimensionedFields<symmTensor, fvMeshMapper, volMesh>(mapper); MapDimensionedFields<tensor, fvMeshMapper, volMesh>(mapper); // Map all the clouds in the objectRegistry mapClouds(*this, meshMap); //TODO implement on gpu /* const labelList& cellMap = meshMap.cellMap(); // Map the old volume. Just map to new cell labels. if (V0Ptr_) { scalargpuField& V0 = (*V0Ptr_).getField(); scalargpuField savedV0(V0); V0.setSize(nCells()); forAll(V0, i) { if (cellMap[i] > -1) { V0[i] = savedV0[cellMap[i]]; } else { V0[i] = 0.0; } } // Inject volume of merged cells label nMerged = 0; forAll(meshMap.reverseCellMap(), oldCellI) { label index = meshMap.reverseCellMap()[oldCellI]; if (index < -1) { label cellI = -index-2; V0[cellI] += savedV0[oldCellI]; nMerged++; } } if (debug) { Info<< "Mapping old time volume V0. Merged " << nMerged << " out of " << nCells() << " cells" << endl; } } // Map the old-old volume. Just map to new cell labels. if (V00Ptr_) { scalargpuField& V00 = (*V00Ptr_).getField(); scalargpuField savedV00(V00); V00.setSize(nCells()); forAll(V00, i) { if (cellMap[i] > -1) { V00[i] = savedV00[cellMap[i]]; } else { V00[i] = 0.0; } } // Inject volume of merged cells label nMerged = 0; forAll(meshMap.reverseCellMap(), oldCellI) { label index = meshMap.reverseCellMap()[oldCellI]; if (index < -1) { label cellI = -index-2; V00[cellI] += savedV00[oldCellI]; nMerged++; } } if (debug) { Info<< "Mapping old time volume V00. Merged " << nMerged << " out of " << nCells() << " cells" << endl; } } */ }
void Foam::primitiveMesh::calcCellEdges() const { // Loop through all faces and mark up cells with edges of the face. // Check for duplicates if (debug) { Pout<< "primitiveMesh::calcCellEdges() : " << "calculating cellEdges" << endl; if (debug == -1) { // For checking calls:abort so we can quickly hunt down // origin of call FatalErrorIn("primitiveMesh::calcCellEdges()") << abort(FatalError); } } // It is an error to attempt to recalculate cellEdges // if the pointer is already set if (cePtr_) { FatalErrorIn("primitiveMesh::calcCellEdges() const") << "cellEdges already calculated" << abort(FatalError); } else { // Set up temporary storage List<DynamicList<label, edgesPerCell_> > ce(nCells()); // Get reference to faceCells and faceEdges const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); const labelListList& fe = faceEdges(); // loop through the list again and add edges; checking for duplicates forAll(own, faceI) { DynamicList<label, edgesPerCell_>& curCellEdges = ce[own[faceI]]; const labelList& curEdges = fe[faceI]; forAll(curEdges, edgeI) { if (findIndex(curCellEdges, curEdges[edgeI]) == -1) { // Add the edge curCellEdges.append(curEdges[edgeI]); } } } forAll(nei, faceI) { DynamicList<label, edgesPerCell_>& curCellEdges = ce[nei[faceI]]; const labelList& curEdges = fe[faceI]; forAll(curEdges, edgeI) { if (findIndex(curCellEdges, curEdges[edgeI]) == -1) { // add the edge curCellEdges.append(curEdges[edgeI]); } } }
void Mesh::buildInternalFaces() { if(faces_built) { return; } faces_built = true; //build naive list of faces int num_naive_faces{0}; for (auto i : IRange(0, nCells())) { num_naive_faces += numCellFaces(getCellType(i)); } internal_faces_.clear(); internal_faces_.reserve(num_naive_faces); std::vector<int> cell_nodes(8); for (auto i : IRange(0, nCells())) { getCellNodes(i, cell_nodes); auto ct = getCellType(i); for(auto f : IRange(0, numCellFaces(ct))) { auto F = CellFace::canonicalCellFace(ct,f); for(auto n : IRange(0,F.n_nodes)) { F.nodes[n] = cell_nodes[F.nodes[n]]; } F.left = i; F.left_flocal = f; F.orient(); internal_faces_.push_back(F); } } std::sort(internal_faces_.begin(), internal_faces_.end(), [](const CellFace &L, const CellFace &R) { return L.nodes < R.nodes; } ); for (auto i : IRange(1, static_cast<int>(internal_faces_.size()))) { auto &F = internal_faces_[i]; auto &Fprev = internal_faces_[i - 1]; if (F.nodes == Fprev.nodes) { Fprev.left = std::max(Fprev.left, F.left); Fprev.right = std::max(Fprev.right, F.right); Fprev.left_flocal = std::max(Fprev.left_flocal, F.left_flocal); Fprev.right_flocal = std::max(Fprev.right_flocal, F.right_flocal); Fprev.left_rot = std::max(Fprev.left_rot, F.left_rot); Fprev.right_rot = std::max(Fprev.right_rot, F.right_rot); } } auto new_end = std::unique(internal_faces_.begin(), internal_faces_.end(), [](const CellFace &L, const CellFace &R) { return L.nodes == R.nodes; }); auto new_size = std::distance(internal_faces_.begin(), new_end); internal_faces_.resize(new_size); internal_faces_.shrink_to_fit(); for (auto i : IRange(0, static_cast<int>(internal_faces_.size()))) { if (internal_faces_[i].left < 0 || internal_faces_[i].right < 0) { boundary_face_idxs_.push_back(i); } } }
Type Foam::functionObjects::fieldValues::volFieldValue::processValues ( const Field<Type>& values, const scalarField& V, const scalarField& weightField ) const { Type result = Zero; switch (operation_) { case opSum: { result = gSum(values); break; } case opSumMag: { result = gSum(cmptMag(values)); break; } case opAverage: { result = gSum(values)/nCells(); break; } case opWeightedAverage: { result = gSum(weightField*values)/gSum(weightField); break; } case opVolAverage: { result = gSum(V*values)/this->V(); break; } case opWeightedVolAverage: { result = gSum(weightField*V*values)/gSum(weightField*V); break; } case opVolIntegrate: { result = gSum(V*values); break; } case opMin: { result = gMin(values); break; } case opMax: { result = gMax(values); break; } case opCoV: { Type meanValue = gSum(values*V)/this->V(); const label nComp = pTraits<Type>::nComponents; for (direction d=0; d<nComp; ++d) { scalarField vals(values.component(d)); scalar mean = component(meanValue, d); scalar& res = setComponent(result, d); res = sqrt(gSum(V*sqr(vals - mean))/this->V())/mean; } break; } case opNone: {} } return result; }
void Foam::fvMesh::mapFields(const mapPolyMesh& meshMap) { // Create a mapper const fvMeshMapper mapper(*this, meshMap); // Map all the volFields in the objectRegistry MapGeometricFields<scalar, fvPatchField, fvMeshMapper, volMesh> (mapper); MapGeometricFields<vector, fvPatchField, fvMeshMapper, volMesh> (mapper); MapGeometricFields<sphericalTensor, fvPatchField, fvMeshMapper, volMesh> (mapper); MapGeometricFields<symmTensor, fvPatchField, fvMeshMapper, volMesh> (mapper); MapGeometricFields<tensor, fvPatchField, fvMeshMapper, volMesh> (mapper); // Map all the surfaceFields in the objectRegistry MapGeometricFields<scalar, fvsPatchField, fvMeshMapper, surfaceMesh> (mapper); MapGeometricFields<vector, fvsPatchField, fvMeshMapper, surfaceMesh> (mapper); MapGeometricFields<symmTensor, fvsPatchField, fvMeshMapper, surfaceMesh> (mapper); MapGeometricFields<symmTensor, fvsPatchField, fvMeshMapper, surfaceMesh> (mapper); MapGeometricFields<tensor, fvsPatchField, fvMeshMapper, surfaceMesh> (mapper); // Map all the clouds in the objectRegistry mapClouds(*this, meshMap); const labelList& cellMap = meshMap.cellMap(); // Map the old volume. Just map to new cell labels. if (V0Ptr_) { scalarField& V0 = *V0Ptr_; scalarField savedV0(V0); V0.setSize(nCells()); forAll(V0, i) { if (cellMap[i] > -1) { V0[i] = savedV0[cellMap[i]]; } else { V0[i] = 0.0; } } } // Map the old-old volume. Just map to new cell labels. if (V00Ptr_) { scalarField& V00 = *V00Ptr_; scalarField savedV00(V00); V00.setSize(nCells()); forAll(V00, i) { if (cellMap[i] > -1) { V00[i] = savedV00[cellMap[i]]; } else { V00[i] = 0.0; } } } }
void CPUUncontrolledApproximation::perform() { const auto &ctx = kernel->context(); auto &stateModel = kernel->getCPUKernelStateModel(); auto nl = stateModel.getNeighborList(); auto &data = nl->data(); const auto &box = ctx.boxSize().data(); const auto &pbc = ctx.periodicBoundaryConditions().data(); if (ctx.recordReactionsWithPositions()) { kernel->getCPUKernelStateModel().reactionRecords().clear(); } if (ctx.recordReactionCounts()) { stateModel.resetReactionCounts(); } // gather events std::vector<std::promise<std::size_t>> n_events_promises(kernel->getNThreads()); std::vector<event_promise_t> promises(kernel->getNThreads()); { auto &pool = kernel->pool(); std::vector<std::function<void(std::size_t)>> executables; executables.reserve(kernel->getNThreads()); std::size_t grainSize = data.size() / kernel->getNThreads(); std::size_t nlGrainSize = nl->nCells() / kernel->getNThreads(); auto it = data.cbegin(); std::size_t it_nl = 0; for (auto i = 0U; i < kernel->getNThreads()-1 ; ++i) { auto itNext = std::min(it+grainSize, data.cend()); auto nlNext = std::min(it_nl + nlGrainSize, nl->nCells()); auto bounds_nl = std::make_tuple(it_nl, nlNext); pool.push(findEvents, it, itNext, bounds_nl, kernel, timeStep(), false, std::cref(*nl), std::ref(promises.at(i)), std::ref(n_events_promises.at(i))); it = itNext; it_nl = nlNext; } pool.push(findEvents, it, data.cend(), std::make_tuple(it_nl, nl->nCells()), kernel, timeStep(), false, std::cref(*nl), std::ref(promises.back()), std::ref(n_events_promises.back())); } // collect events std::vector<event_t> events; { std::size_t n_events = 0; for (auto &&f : n_events_promises) { n_events += f.get_future().get(); } events.reserve(n_events); for (auto &&f : promises) { auto eventUpdate = std::move(f.get_future().get()); auto mBegin = std::make_move_iterator(eventUpdate.begin()); auto mEnd = std::make_move_iterator(eventUpdate.end()); events.insert(events.end(), mBegin, mEnd); } } // shuffle reactions std::shuffle(events.begin(), events.end(), std::mt19937(std::random_device()())); // execute reactions { data_t::EntriesUpdate newParticles{}; std::vector<data_t::size_type> decayedEntries{}; // todo better conflict detection? for (auto it = events.begin(); it != events.end(); ++it) { auto &event = *it; if (event.cumulativeRate == 0) { auto entry1 = event.idx1; if (event.nEducts == 1) { auto reaction = ctx.reactions().order1ByType(event.t1)[event.reactionIndex]; if (ctx.recordReactionsWithPositions()) { record_t record; record.id = reaction->id(); performReaction(&data, ctx, entry1, entry1, newParticles, decayedEntries, reaction, &record); bcs::fixPosition(record.where, box, pbc); kernel->getCPUKernelStateModel().reactionRecords().push_back(record); } else { performReaction(&data, ctx, entry1, entry1, newParticles, decayedEntries, reaction, nullptr); } if (ctx.recordReactionCounts()) { auto &counts = stateModel.reactionCounts(); counts.at(reaction->id())++; } for (auto _it2 = it + 1; _it2 != events.end(); ++_it2) { if (_it2->idx1 == entry1 || _it2->idx2 == entry1) { _it2->cumulativeRate = 1; } } } else { auto reaction = ctx.reactions().order2ByType(event.t1, event.t2)[event.reactionIndex]; if (ctx.recordReactionsWithPositions()) { record_t record; record.id = reaction->id(); performReaction(&data, ctx, entry1, event.idx2, newParticles, decayedEntries, reaction, &record); bcs::fixPosition(record.where, box, pbc); kernel->getCPUKernelStateModel().reactionRecords().push_back(record); } else { performReaction(&data, ctx, entry1, event.idx2, newParticles, decayedEntries, reaction, nullptr); } if (ctx.recordReactionCounts()) { auto &counts = stateModel.reactionCounts(); counts.at(reaction->id())++; } for (auto _it2 = it + 1; _it2 != events.end(); ++_it2) { if (_it2->idx1 == entry1 || _it2->idx2 == entry1 || _it2->idx1 == event.idx2 || _it2->idx2 == event.idx2) { _it2->cumulativeRate = 1; } } } } } data.update(std::make_pair(std::move(newParticles), std::move(decayedEntries))); } }