| 551 | } |
| 552 | |
| 553 | void seissol::initializer::MemoryManager::fixateBoundaryLtsTree() { |
| 554 | seissol::initializer::LayerMask ghostMask(Ghost); |
| 555 | |
| 556 | // Boundary face tree |
| 557 | m_boundary.addTo(m_boundaryTree); |
| 558 | m_boundaryTree.setNumberOfTimeClusters(m_ltsTree.numChildren()); |
| 559 | m_boundaryTree.fixate(); |
| 560 | |
| 561 | // First count the number of faces with relevant boundary condition. |
| 562 | for (unsigned tc = 0; tc < m_boundaryTree.numChildren(); ++tc) { |
| 563 | auto& cluster = m_boundaryTree.child(tc); |
| 564 | cluster.child<Ghost>().setNumberOfCells(0); |
| 565 | cluster.child<Copy>().setNumberOfCells(0); |
| 566 | cluster.child<Interior>().setNumberOfCells(0); |
| 567 | } |
| 568 | |
| 569 | // Iterate over layers of standard lts tree and face lts tree together. |
| 570 | for (auto [layer, boundaryLayer] : seissol::common::zip(m_ltsTree.leaves(ghostMask), m_boundaryTree.leaves(ghostMask))) { |
| 571 | CellLocalInformation* cellInformation = layer.var(m_lts.cellInformation); |
| 572 | |
| 573 | unsigned numberOfBoundaryFaces = 0; |
| 574 | const auto layerSize = layer.getNumberOfCells(); |
| 575 | #ifdef _OPENMP |
| 576 | #pragma omp parallel for schedule(static) reduction(+ : numberOfBoundaryFaces) |
| 577 | #endif // _OPENMP |
| 578 | for (unsigned cell = 0; cell < layerSize; ++cell) { |
| 579 | for (unsigned face = 0; face < 4; ++face) { |
| 580 | if (requiresNodalFlux(cellInformation[cell].faceTypes[face])) { |
| 581 | ++numberOfBoundaryFaces; |
| 582 | } |
| 583 | } |
| 584 | } |
| 585 | boundaryLayer.setNumberOfCells(numberOfBoundaryFaces); |
| 586 | } |
| 587 | m_boundaryTree.allocateVariables(); |
| 588 | m_boundaryTree.touchVariables(); |
| 589 | |
| 590 | // The boundary tree is now allocated, now we only need to map from cell lts |
| 591 | // to face lts. |
| 592 | // We do this by, once again, iterating over both trees at the same time. |
| 593 | for (auto [layer, boundaryLayer] : seissol::common::zip(m_ltsTree.leaves(ghostMask), m_boundaryTree.leaves(ghostMask))) { |
| 594 | auto* cellInformation = layer.var(m_lts.cellInformation); |
| 595 | auto* boundaryMapping = layer.var(m_lts.boundaryMapping); |
| 596 | auto* boundaryMappingDevice = layer.var(m_lts.boundaryMappingDevice); |
| 597 | auto* faceInformation = boundaryLayer.var(m_boundary.faceInformation, AllocationPlace::Host); |
| 598 | auto* faceInformationDevice = boundaryLayer.var(m_boundary.faceInformation, AllocationPlace::Device); |
| 599 | |
| 600 | auto boundaryFace = 0; |
| 601 | for (unsigned cell = 0; cell < layer.getNumberOfCells(); ++cell) { |
| 602 | for (unsigned face = 0; face < 4; ++face) { |
| 603 | if (requiresNodalFlux(cellInformation[cell].faceTypes[face])) { |
| 604 | boundaryMapping[cell][face].nodes = faceInformation[boundaryFace].nodes; |
| 605 | boundaryMapping[cell][face].TData = faceInformation[boundaryFace].TData; |
| 606 | boundaryMapping[cell][face].TinvData = faceInformation[boundaryFace].TinvData; |
| 607 | boundaryMapping[cell][face].easiBoundaryMap = faceInformation[boundaryFace].easiBoundaryMap; |
| 608 | boundaryMapping[cell][face].easiBoundaryConstant = faceInformation[boundaryFace].easiBoundaryConstant; |
| 609 | boundaryMappingDevice[cell][face].nodes = faceInformationDevice[boundaryFace].nodes; |
| 610 | boundaryMappingDevice[cell][face].TData = faceInformationDevice[boundaryFace].TData; |
no test coverage detected