/*---------------------------------------------------------------------------*\ ========= | \\ / 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) 2020-2024 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 "LUscalarMatrix.H" #include "lduMatrix.H" #include "procLduMatrix.H" #include "procLduInterface.H" #include "cyclicLduInterface.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(LUscalarMatrix, 0); } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::LUscalarMatrix::LUscalarMatrix() noexcept : comm_(UPstream::worldComm) {} Foam::LUscalarMatrix::LUscalarMatrix(const scalarSquareMatrix& mat) : scalarSquareMatrix(mat), comm_(UPstream::worldComm) { LUDecompose(*this, pivotIndices_); } Foam::LUscalarMatrix::LUscalarMatrix ( const lduMatrix& ldum, const FieldField& interfaceCoeffs, const lduInterfaceFieldPtrsList& interfaces ) : comm_(ldum.mesh().comm()) { if (UPstream::parRun()) { PtrList lduMatrices ( UPstream::master(comm_) ? UPstream::nProcs(comm_) : 1 ); lduMatrices.set ( 0, // rank-local matrix (and/or master) new procLduMatrix ( ldum, interfaceCoeffs, interfaces ) ); if (UPstream::master(comm_)) { for (const int proci : UPstream::subProcs(comm_)) { auto& mat = lduMatrices.emplace_set(proci); IPstream::recv(mat, proci, UPstream::msgType(), comm_); } convert(lduMatrices); } else { OPstream::send ( lduMatrices[0], // rank-local matrix UPstream::masterNo(), UPstream::msgType(), comm_ ); } } else { convert(ldum, interfaceCoeffs, interfaces); } if (debug && UPstream::master(comm_)) { const label numRows = nRows(); const label numCols = nCols(); Pout<< "LUscalarMatrix : size:" << numRows << endl; for (label rowi = 0; rowi < numRows; ++rowi) { const scalar* row = operator[](rowi); Pout<< "cell:" << rowi << " diagCoeff:" << row[rowi] << nl; Pout<< " connects to upper cells :"; for (label coli = rowi+1; coli < numCols; ++coli) { if (mag(row[coli]) > SMALL) { Pout<< ' ' << coli << " (coeff:" << row[coli] << ')'; } } Pout<< nl; Pout<< " connects to lower cells :"; for (label coli = 0; coli < rowi; ++coli) { if (mag(row[coli]) > SMALL) { Pout<< ' ' << coli << " (coeff:" << row[coli] << ')'; } } Pout<< nl; } Pout<< endl; } if (UPstream::master(comm_)) { LUDecompose(*this, pivotIndices_); } } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::LUscalarMatrix::convert ( const lduMatrix& ldum, const FieldField& interfaceCoeffs, const lduInterfaceFieldPtrsList& interfaces ) { // Resize and fill with zero scalarSquareMatrix::resize_nocopy(ldum.lduAddr().size()); scalarSquareMatrix::operator=(Foam::zero{}); const label* __restrict__ uPtr = ldum.lduAddr().upperAddr().begin(); const label* __restrict__ lPtr = ldum.lduAddr().lowerAddr().begin(); const scalar* __restrict__ diagPtr = ldum.diag().begin(); const scalar* __restrict__ upperPtr = ldum.upper().begin(); const scalar* __restrict__ lowerPtr = ldum.lower().begin(); const label nCells = ldum.diag().size(); const label nFaces = ldum.upper().size(); for (label cell=0; cell(interface); label nbrInt = cycInterface.neighbPatchID(); const label* __restrict__ uPtr = interfaces[nbrInt].interface().faceCells().begin(); const scalar* __restrict__ nbrUpperLowerPtr = interfaceCoeffs[nbrInt].begin(); label inFaces = interface.faceCells().size(); for (label face=0; face& lduMatrices ) { procOffsets_.resize_nocopy(lduMatrices.size() + 1); { auto iter = procOffsets_.begin(); label nCellsTotal = 0; *iter++ = nCellsTotal; for (const auto& mat : lduMatrices) { nCellsTotal += mat.size(); *iter++ = nCellsTotal; } // Resize and fill with zero scalarSquareMatrix::resize_nocopy(nCellsTotal); scalarSquareMatrix::operator=(Foam::zero{}); } forAll(lduMatrices, ldumi) { const procLduMatrix& lduMatrixi = lduMatrices[ldumi]; label offset = procOffsets_[ldumi]; const label* __restrict__ uPtr = lduMatrixi.upperAddr_.begin(); const label* __restrict__ lPtr = lduMatrixi.lowerAddr_.begin(); const scalar* __restrict__ diagPtr = lduMatrixi.diag_.begin(); const scalar* __restrict__ upperPtr = lduMatrixi.upper_.begin(); const scalar* __restrict__ lowerPtr = lduMatrixi.lower_.begin(); const label nCells = lduMatrixi.size(); const label nFaces = lduMatrixi.upper_.size(); for (label cell=0; cell& interfaces = lduMatrixi.interfaces_; forAll(interfaces, inti) { const procLduInterface& interface = interfaces[inti]; if (interface.myProcNo_ == interface.neighbProcNo_) { const label* __restrict__ ulPtr = interface.faceCells_.begin(); const scalar* __restrict__ upperLowerPtr = interface.coeffs_.begin(); label inFaces = interface.faceCells_.size()/2; for (label face=0; face& neiInterfaces = lduMatrices[interface.neighbProcNo_].interfaces_; label neiInterfacei = -1; forAll(neiInterfaces, ninti) { if ( ( neiInterfaces[ninti].neighbProcNo_ == interface.myProcNo_ ) && (neiInterfaces[ninti].tag_ == interface.tag_) ) { neiInterfacei = ninti; break; } } if (neiInterfacei == -1) { FatalErrorInFunction << exit(FatalError); } const procLduInterface& neiInterface = neiInterfaces[neiInterfacei]; const label* __restrict__ uPtr = interface.faceCells_.begin(); const label* __restrict__ lPtr = neiInterface.faceCells_.begin(); const scalar* __restrict__ upperPtr = interface.coeffs_.begin(); const scalar* __restrict__ lowerPtr = neiInterface.coeffs_.begin(); label inFaces = interface.faceCells_.size(); label neiOffset = procOffsets_[interface.neighbProcNo_]; for (label face=0; face